diff --git a/gantt.php b/gantt.php new file mode 100644 index 0000000..d0d301b --- /dev/null +++ b/gantt.php @@ -0,0 +1,173 @@ + + + + + + + Highcharts Gantt Example + + + + + + + +
+ + + + + + diff --git a/index.php b/index.php index 1a5711b..ca5c0fa 100644 --- a/index.php +++ b/index.php @@ -155,11 +155,16 @@ if($plantilla_inicio[0] =="grid"){}else{ $logo = remplacetas('empresa','id',"$v[1]",'imagen','') ; $modo="minimalista"; $plantilla_inicio[0]='grid'; + $librerias = " + + + "; //$no_mostrar="display:none; "; $asistento="hide "; /// datos proyecto $formulario_proyectos ="1070"; + $campo_proyectos ="3705"; /// datos equipo $formulario_equipo ="998"; $campo_equipo ="316"; @@ -169,8 +174,10 @@ if($plantilla_inicio[0] =="grid"){}else{ $campo_rol ="325"; /// datos tareas $formulario_tareas ="1069"; + $campo_tareas ="3715"; /// datos microtareas $formulario_microtarea ="1071"; + $campo_microtarea ="3710"; $formulario_microtarea_asignacion ="1075"; $campo_microtareas_asignacion = "3722"; @@ -188,13 +195,19 @@ if($plantilla_inicio[0] =="grid"){}else{ /// microtareas /// + $formularios_microtareas['formulario_proyectos']=$formulario_proyectos; + $formularios_microtareas['campo_proyectos']=$campo_proyectos; + $formularios_microtareas['formulario_tareas']=$formulario_tareas; + $formularios_microtareas['campo_tareas']=$campo_tareas; $formularios_microtareas['formulario_microtarea']=$formulario_microtarea; $formularios_microtareas['formulario_microtarea_asignacion']=$formulario_microtarea_asignacion; - $formularios_microtareas['campo_microtarea_asignacion']=$campo_microtarea_asignacion; + $formularios_microtareas['campo_microtarea']=$campo_microtarea; + $formularios_microtareas['campo_microtareas_asignacion']=$campo_microtareas_asignacion; $formularios_microtareas['formulario_microtarea_asignacion']="$formulario_microtarea_asignacion"; $formularios_microtareas['formulario_equipo']="$formulario_equipo"; $formularios_microtareas['campo_equipo']="$campo_equipo"; - $microtareas_planilla = planilla("$formulario_microtarea","10",'exportable'); + //$microtareas_planilla = planilla("$formulario_microtarea","10",'exportable'); + $gantt_array = gantt($formularios_microtareas,"array",""); $microtarea_titulo = remplacetas('form_id','id',"$formulario_microtarea",'nombre',"") ; $microtarea_descripcion = remplacetas('form_id','id',"$formulario_microtarea",'descripcion',"") ; @@ -246,7 +259,7 @@ foreach($proyectos as $control_proyecto => $valor_proyecto) $microtarea_listado = microtareas($formularios_microtareas,"",""); $pagina_inicio=" - + $librerias ' + + '' + + '' + + '' + + this.getTable(true) + + '', base64 = function (s) { + return win.btoa(unescape(encodeURIComponent(s))); // #50 + }; + downloadURL(getBlobFromContent(template, 'application/vnd.ms-excel') || + uri + base64(template), this.getFilename() + '.xls'); +}; +/** + * Export-data module required. View the data in a table below the chart. + * + * @function Highcharts.Chart#viewData + * + * @fires Highcharts.Chart#event:afterViewData + */ +Highcharts.Chart.prototype.viewData = function () { + if (!this.dataTableDiv) { + this.dataTableDiv = doc.createElement('div'); + this.dataTableDiv.className = 'highcharts-data-table'; + // Insert after the chart container + this.renderTo.parentNode.insertBefore(this.dataTableDiv, this.renderTo.nextSibling); + } + this.dataTableDiv.innerHTML = this.getTable(); + fireEvent(this, 'afterViewData', this.dataTableDiv); +}; +// Add "Download CSV" to the exporting menu. +var exportingOptions = Highcharts.getOptions().exporting; +if (exportingOptions) { + extend(exportingOptions.menuItemDefinitions, { + downloadCSV: { + textKey: 'downloadCSV', + onclick: function () { + this.downloadCSV(); + } + }, + downloadXLS: { + textKey: 'downloadXLS', + onclick: function () { + this.downloadXLS(); + } + }, + viewData: { + textKey: 'viewData', + onclick: function () { + this.viewData(); + } + } + }); + if (exportingOptions.buttons) { + exportingOptions.buttons.contextButton.menuItems.push('separator', 'downloadCSV', 'downloadXLS', 'viewData'); + } +} +// Series specific +if (seriesTypes.map) { + seriesTypes.map.prototype.exportKey = 'name'; +} +if (seriesTypes.mapbubble) { + seriesTypes.mapbubble.prototype.exportKey = 'name'; +} +if (seriesTypes.treemap) { + seriesTypes.treemap.prototype.exportKey = 'name'; +} diff --git a/librerias/gantt/code/es-modules/modules/exporting.src.js b/librerias/gantt/code/es-modules/modules/exporting.src.js new file mode 100644 index 0000000..ec658f0 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/exporting.src.js @@ -0,0 +1,1990 @@ +/* * + * + * Exporting module + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +/** + * Gets fired after a chart is printed through the context menu item or the + * Chart.print method. + * + * @callback Highcharts.ExportingAfterPrintCallbackFunction + * + * @param {Highcharts.Chart} chart + * The chart on which the event occured. + * + * @param {global.Event} event + * The event that occured. + */ +/** + * Gets fired before a chart is printed through the context menu item or the + * Chart.print method. + * + * @callback Highcharts.ExportingBeforePrintCallbackFunction + * + * @param {Highcharts.Chart} chart + * The chart on which the event occured. + * + * @param {global.Event} event + * The event that occured. + */ +/** + * Function to call if the offline-exporting module fails to export a chart on + * the client side. + * + * @callback Highcharts.ExportingErrorCallbackFunction + * + * @param {Highcharts.ExportingOptions} options + * The exporting options. + * + * @param {global.Error} err + * The error from the module. + */ +/** + * Definition for a menu item in the context menu. + * + * @interface Highcharts.ExportingMenuObject + */ /** +* The text for the menu item. +* +* @name Highcharts.ExportingMenuObject#text +* @type {string|undefined} +*/ /** +* If internationalization is required, the key to a language string. +* +* @name Highcharts.ExportingMenuObject#textKey +* @type {string|undefined} +*/ /** +* The click handler for the menu item. +* +* @name Highcharts.ExportingMenuObject#onclick +* @type {Highcharts.EventCallbackFunction|undefined} +*/ /** +* Indicates a separator line instead of an item. +* +* @name Highcharts.ExportingMenuObject#separator +* @type {boolean|undefined} +*/ +/** + * Possible MIME types for exporting. + * + * @typedef {"image/png"|"image/jpeg"|"application/pdf"|"image/svg+xml"} Highcharts.ExportingMimeTypeValue + */ +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, css = U.css, createElement = U.createElement, discardElement = U.discardElement, extend = U.extend, find = U.find, fireEvent = U.fireEvent, isObject = U.isObject, merge = U.merge, objectEach = U.objectEach, pick = U.pick, removeEvent = U.removeEvent, uniqueKey = U.uniqueKey; +import '../parts/Options.js'; +import '../parts/Chart.js'; +import chartNavigationMixin from '../mixins/navigation.js'; +// create shortcuts +var defaultOptions = H.defaultOptions, doc = H.doc, Chart = H.Chart, isTouchDevice = H.isTouchDevice, win = H.win, userAgent = win.navigator.userAgent, SVGRenderer = H.SVGRenderer, symbols = H.Renderer.prototype.symbols, isMSBrowser = /Edge\/|Trident\/|MSIE /.test(userAgent), isFirefoxBrowser = /firefox/i.test(userAgent); +// Add language +extend(defaultOptions.lang +/** + * @optionparent lang + */ +, { + /** + * Exporting module only. The text for the menu item to view the chart + * in full screen. + * + * @since 8.0.1 + * + * @private + */ + viewFullscreen: 'View in full screen', + /** + * Exporting module only. The text for the menu item to exit the chart + * from full screen. + * + * @since 8.0.1 + * + * @private + */ + exitFullscreen: 'Exit from full screen', + /** + * Exporting module only. The text for the menu item to print the chart. + * + * @since 3.0.1 + * @requires modules/exporting + * + * @private + */ + printChart: 'Print chart', + /** + * Exporting module only. The text for the PNG download menu item. + * + * @since 2.0 + * @requires modules/exporting + * + * @private + */ + downloadPNG: 'Download PNG image', + /** + * Exporting module only. The text for the JPEG download menu item. + * + * @since 2.0 + * @requires modules/exporting + * + * @private + */ + downloadJPEG: 'Download JPEG image', + /** + * Exporting module only. The text for the PDF download menu item. + * + * @since 2.0 + * @requires modules/exporting + * + * @private + */ + downloadPDF: 'Download PDF document', + /** + * Exporting module only. The text for the SVG download menu item. + * + * @since 2.0 + * @requires modules/exporting + * + * @private + */ + downloadSVG: 'Download SVG vector image', + /** + * Exporting module menu. The tooltip title for the context menu holding + * print and export menu items. + * + * @since 3.0 + * @requires modules/exporting + * + * @private + */ + contextButtonTitle: 'Chart context menu' +}); +if (!defaultOptions.navigation) { + // Buttons and menus are collected in a separate config option set called + // 'navigation'. This can be extended later to add control buttons like + // zoom and pan right click menus. + /** + * A collection of options for buttons and menus appearing in the exporting + * module. + * + * @requires modules/exporting + * @optionparent navigation + */ + defaultOptions.navigation = {}; +} +merge(true, defaultOptions.navigation, { + /** + * @optionparent navigation.buttonOptions + * + * @private + */ + buttonOptions: { + theme: {}, + /** + * Whether to enable buttons. + * + * @sample highcharts/navigation/buttonoptions-enabled/ + * Exporting module loaded but buttons disabled + * + * @type {boolean} + * @default true + * @since 2.0 + * @apioption navigation.buttonOptions.enabled + */ + /** + * The pixel size of the symbol on the button. + * + * @sample highcharts/navigation/buttonoptions-height/ + * Bigger buttons + * + * @since 2.0 + */ + symbolSize: 14, + /** + * The x position of the center of the symbol inside the button. + * + * @sample highcharts/navigation/buttonoptions-height/ + * Bigger buttons + * + * @since 2.0 + */ + symbolX: 12.5, + /** + * The y position of the center of the symbol inside the button. + * + * @sample highcharts/navigation/buttonoptions-height/ + * Bigger buttons + * + * @since 2.0 + */ + symbolY: 10.5, + /** + * Alignment for the buttons. + * + * @sample highcharts/navigation/buttonoptions-align/ + * Center aligned + * + * @type {Highcharts.AlignValue} + * @since 2.0 + */ + align: 'right', + /** + * The pixel spacing between buttons. + * + * @since 2.0 + */ + buttonSpacing: 3, + /** + * Pixel height of the buttons. + * + * @sample highcharts/navigation/buttonoptions-height/ + * Bigger buttons + * + * @since 2.0 + */ + height: 22, + /** + * A text string to add to the individual button. + * + * @sample highcharts/exporting/buttons-text/ + * Full text button + * @sample highcharts/exporting/buttons-text-symbol/ + * Combined symbol and text + * + * @type {string} + * @default null + * @since 3.0 + * @apioption navigation.buttonOptions.text + */ + /** + * The vertical offset of the button's position relative to its + * `verticalAlign`. + * + * @sample highcharts/navigation/buttonoptions-verticalalign/ + * Buttons at lower right + * + * @type {number} + * @default 0 + * @since 2.0 + * @apioption navigation.buttonOptions.y + */ + /** + * The vertical alignment of the buttons. Can be one of `"top"`, + * `"middle"` or `"bottom"`. + * + * @sample highcharts/navigation/buttonoptions-verticalalign/ + * Buttons at lower right + * + * @type {Highcharts.VerticalAlignValue} + * @since 2.0 + */ + verticalAlign: 'top', + /** + * The pixel width of the button. + * + * @sample highcharts/navigation/buttonoptions-height/ + * Bigger buttons + * + * @since 2.0 + */ + width: 24 + } +}); +// Presentational attributes +merge(true, defaultOptions.navigation +/** + * A collection of options for buttons and menus appearing in the exporting + * module. + * + * @optionparent navigation + */ +, { + /** + * CSS styles for the popup menu appearing by default when the export + * icon is clicked. This menu is rendered in HTML. + * + * @see In styled mode, the menu is styled with the `.highcharts-menu` + * class. + * + * @sample highcharts/navigation/menustyle/ + * Light gray menu background + * + * @type {Highcharts.CSSObject} + * @default {"border": "1px solid #999999", "background": "#ffffff", "padding": "5px 0"} + * @since 2.0 + * + * @private + */ + menuStyle: { + /** @ignore-option */ + border: '1px solid #999999', + /** @ignore-option */ + background: '#ffffff', + /** @ignore-option */ + padding: '5px 0' + }, + /** + * CSS styles for the individual items within the popup menu appearing + * by default when the export icon is clicked. The menu items are + * rendered in HTML. Font size defaults to `11px` on desktop and `14px` + * on touch devices. + * + * @see In styled mode, the menu items are styled with the + * `.highcharts-menu-item` class. + * + * @sample {highcharts} highcharts/navigation/menuitemstyle/ + * Add a grey stripe to the left + * + * @type {Highcharts.CSSObject} + * @default {"padding": "0.5em 1em", "color": "#333333", "background": "none", "fontSize": "11px/14px", "transition": "background 250ms, color 250ms"} + * @since 2.0 + * + * @private + */ + menuItemStyle: { + /** @ignore-option */ + padding: '0.5em 1em', + /** @ignore-option */ + color: '#333333', + /** @ignore-option */ + background: 'none', + /** @ignore-option */ + fontSize: isTouchDevice ? '14px' : '11px', + /** @ignore-option */ + transition: 'background 250ms, color 250ms' + }, + /** + * CSS styles for the hover state of the individual items within the + * popup menu appearing by default when the export icon is clicked. The + * menu items are rendered in HTML. + * + * @see In styled mode, the menu items are styled with the + * `.highcharts-menu-item` class. + * + * @sample highcharts/navigation/menuitemhoverstyle/ + * Bold text on hover + * + * @type {Highcharts.CSSObject} + * @default {"background": "#335cad", "color": "#ffffff"} + * @since 2.0 + * + * @private + */ + menuItemHoverStyle: { + /** @ignore-option */ + background: '#335cad', + /** @ignore-option */ + color: '#ffffff' + }, + /** + * A collection of options for buttons appearing in the exporting + * module. + * + * In styled mode, the buttons are styled with the + * `.highcharts-contextbutton` and `.highcharts-button-symbol` classes. + * + * @requires modules/exporting + * + * @private + */ + buttonOptions: { + /** + * Fill color for the symbol within the button. + * + * @sample highcharts/navigation/buttonoptions-symbolfill/ + * Blue symbol stroke for one of the buttons + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.0 + */ + symbolFill: '#666666', + /** + * The color of the symbol's stroke or line. + * + * @sample highcharts/navigation/buttonoptions-symbolstroke/ + * Blue symbol stroke + * + * @type {Highcharts.ColorString} + * @since 2.0 + */ + symbolStroke: '#666666', + /** + * The pixel stroke width of the symbol on the button. + * + * @sample highcharts/navigation/buttonoptions-height/ + * Bigger buttons + * + * @since 2.0 + */ + symbolStrokeWidth: 3, + /** + * A configuration object for the button theme. The object accepts + * SVG properties like `stroke-width`, `stroke` and `fill`. + * Tri-state button styles are supported by the `states.hover` and + * `states.select` objects. + * + * @sample highcharts/navigation/buttonoptions-theme/ + * Theming the buttons + * + * @requires modules/exporting + * + * @since 3.0 + */ + theme: { + /** + * The default fill exists only to capture hover events. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #ffffff + * @apioption navigation.buttonOptions.theme.fill + */ + /** + * Default stroke for the buttons. + * @type {Highcharts.ColorString} + * @default none + * @apioption navigation.buttonOptions.theme.stroke + */ + /** + * Padding for the button. + */ + padding: 5 + } + } +}); +// Add the export related options +/** + * Options for the exporting module. For an overview on the matter, see + * [the docs](https://www.highcharts.com/docs/export-module/export-module-overview). + * + * @requires modules/exporting + * @optionparent exporting + */ +defaultOptions.exporting = { + /** + * Experimental setting to allow HTML inside the chart (added through + * the `useHTML` options), directly in the exported image. This allows + * you to preserve complicated HTML structures like tables or bi-directional + * text in exported charts. + * + * Disclaimer: The HTML is rendered in a `foreignObject` tag in the + * generated SVG. The official export server is based on PhantomJS, + * which supports this, but other SVG clients, like Batik, does not + * support it. This also applies to downloaded SVG that you want to + * open in a desktop client. + * + * @type {boolean} + * @default false + * @since 4.1.8 + * @apioption exporting.allowHTML + */ + /** + * Additional chart options to be merged into the chart before exporting to + * an image format. This does not apply to printing the chart via the export + * menu. + * + * For example, a common use case is to add data labels to improve + * readability of the exported chart, or to add a printer-friendly color + * scheme to exported PDFs. + * + * @sample {highcharts} highcharts/exporting/chartoptions-data-labels/ + * Added data labels + * @sample {highstock} highcharts/exporting/chartoptions-data-labels/ + * Added data labels + * + * @type {Highcharts.Options} + * @apioption exporting.chartOptions + */ + /** + * Whether to enable the exporting module. Disabling the module will + * hide the context button, but API methods will still be available. + * + * @sample {highcharts} highcharts/exporting/enabled-false/ + * Exporting module is loaded but disabled + * @sample {highstock} highcharts/exporting/enabled-false/ + * Exporting module is loaded but disabled + * + * @type {boolean} + * @default true + * @since 2.0 + * @apioption exporting.enabled + */ + /** + * Function to call if the offline-exporting module fails to export + * a chart on the client side, and [fallbackToExportServer]( + * #exporting.fallbackToExportServer) is disabled. If left undefined, an + * exception is thrown instead. Receives two parameters, the exporting + * options, and the error from the module. + * + * @see [fallbackToExportServer](#exporting.fallbackToExportServer) + * + * @type {Highcharts.ExportingErrorCallbackFunction} + * @since 5.0.0 + * @requires modules/exporting + * @requires modules/offline-exporting + * @apioption exporting.error + */ + /** + * Whether or not to fall back to the export server if the offline-exporting + * module is unable to export the chart on the client side. This happens for + * certain browsers, and certain features (e.g. + * [allowHTML](#exporting.allowHTML)), depending on the image type exporting + * to. For very complex charts, it is possible that export can fail in + * browsers that don't support Blob objects, due to data URL length limits. + * It is recommended to define the [exporting.error](#exporting.error) + * handler if disabling fallback, in order to notify users in case export + * fails. + * + * @type {boolean} + * @default true + * @since 4.1.8 + * @requires modules/exporting + * @requires modules/offline-exporting + * @apioption exporting.fallbackToExportServer + */ + /** + * The filename, without extension, to use for the exported chart. + * + * @sample {highcharts} highcharts/exporting/filename/ + * Custom file name + * @sample {highstock} highcharts/exporting/filename/ + * Custom file name + * + * @type {string} + * @default chart + * @since 2.0 + * @apioption exporting.filename + */ + /** + * An object containing additional key value data for the POST form that + * sends the SVG to the export server. For example, a `target` can be set to + * make sure the generated image is received in another frame, or a custom + * `enctype` or `encoding` can be set. + * + * @type {Highcharts.HTMLAttributes} + * @since 3.0.8 + * @apioption exporting.formAttributes + */ + /** + * Path where Highcharts will look for export module dependencies to + * load on demand if they don't already exist on `window`. Should currently + * point to location of [CanVG](https://github.com/canvg/canvg) library, + * [RGBColor.js](https://github.com/canvg/canvg), + * [jsPDF](https://github.com/yWorks/jsPDF) and + * [svg2pdf.js](https://github.com/yWorks/svg2pdf.js), required for client + * side export in certain browsers. + * + * @type {string} + * @default https://code.highcharts.com/{version}/lib + * @since 5.0.0 + * @apioption exporting.libURL + */ + /** + * Analogous to [sourceWidth](#exporting.sourceWidth). + * + * @type {number} + * @since 3.0 + * @apioption exporting.sourceHeight + */ + /** + * The width of the original chart when exported, unless an explicit + * [chart.width](#chart.width) is set, or a pixel width is set on the + * container. The width exported raster image is then multiplied by + * [scale](#exporting.scale). + * + * @sample {highcharts} highcharts/exporting/sourcewidth/ + * Source size demo + * @sample {highstock} highcharts/exporting/sourcewidth/ + * Source size demo + * @sample {highmaps} maps/exporting/sourcewidth/ + * Source size demo + * + * @type {number} + * @since 3.0 + * @apioption exporting.sourceWidth + */ + /** + * The pixel width of charts exported to PNG or JPG. As of Highcharts + * 3.0, the default pixel width is a function of the [chart.width]( + * #chart.width) or [exporting.sourceWidth](#exporting.sourceWidth) and the + * [exporting.scale](#exporting.scale). + * + * @sample {highcharts} highcharts/exporting/width/ + * Export to 200px wide images + * @sample {highstock} highcharts/exporting/width/ + * Export to 200px wide images + * + * @type {number} + * @since 2.0 + * @apioption exporting.width + */ + /** + * Default MIME type for exporting if `chart.exportChart()` is called + * without specifying a `type` option. Possible values are `image/png`, + * `image/jpeg`, `application/pdf` and `image/svg+xml`. + * + * @type {Highcharts.ExportingMimeTypeValue} + * @since 2.0 + */ + type: 'image/png', + /** + * The URL for the server module converting the SVG string to an image + * format. By default this points to Highchart's free web service. + * + * @since 2.0 + */ + url: 'https://export.highcharts.com/', + /** + * When printing the chart from the menu item in the burger menu, if + * the on-screen chart exceeds this width, it is resized. After printing + * or cancelled, it is restored. The default width makes the chart + * fit into typical paper format. Note that this does not affect the + * chart when printing the web page as a whole. + * + * @since 4.2.5 + */ + printMaxWidth: 780, + /** + * Defines the scale or zoom factor for the exported image compared + * to the on-screen display. While for instance a 600px wide chart + * may look good on a website, it will look bad in print. The default + * scale of 2 makes this chart export to a 1200px PNG or JPG. + * + * @see [chart.width](#chart.width) + * @see [exporting.sourceWidth](#exporting.sourceWidth) + * + * @sample {highcharts} highcharts/exporting/scale/ + * Scale demonstrated + * @sample {highstock} highcharts/exporting/scale/ + * Scale demonstrated + * @sample {highmaps} maps/exporting/scale/ + * Scale demonstrated + * + * @since 3.0 + */ + scale: 2, + /** + * Options for the export related buttons, print and export. In addition + * to the default buttons listed here, custom buttons can be added. + * See [navigation.buttonOptions](#navigation.buttonOptions) for general + * options. + * + * @type {Highcharts.Dictionary<*>} + * @requires modules/exporting + */ + buttons: { + /** + * Options for the export button. + * + * In styled mode, export button styles can be applied with the + * `.highcharts-contextbutton` class. + * + * @declare Highcharts.ExportingButtonsOptionsObject + * @extends navigation.buttonOptions + * @requires modules/exporting + */ + contextButton: { + /** + * A click handler callback to use on the button directly instead of + * the popup menu. + * + * @sample highcharts/exporting/buttons-contextbutton-onclick/ + * Skip the menu and export the chart directly + * + * @type {Function} + * @since 2.0 + * @apioption exporting.buttons.contextButton.onclick + */ + /** + * See [navigation.buttonOptions.symbolFill]( + * #navigation.buttonOptions.symbolFill). + * + * @type {Highcharts.ColorString} + * @default #666666 + * @since 2.0 + * @apioption exporting.buttons.contextButton.symbolFill + */ + /** + * The horizontal position of the button relative to the `align` + * option. + * + * @type {number} + * @default -10 + * @since 2.0 + * @apioption exporting.buttons.contextButton.x + */ + /** + * The class name of the context button. + */ + className: 'highcharts-contextbutton', + /** + * The class name of the menu appearing from the button. + */ + menuClassName: 'highcharts-contextmenu', + /** + * The symbol for the button. Points to a definition function in + * the `Highcharts.Renderer.symbols` collection. The default + * `exportIcon` function is part of the exporting module. Possible + * values are "circle", "square", "diamond", "triangle", + * "triangle-down", "menu", "menuball" or custom shape. + * + * @sample highcharts/exporting/buttons-contextbutton-symbol/ + * Use a circle for symbol + * @sample highcharts/exporting/buttons-contextbutton-symbol-custom/ + * Custom shape as symbol + * + * @type {Highcharts.SymbolKeyValue|"exportIcon"|"menu"|"menuball"|string} + * @since 2.0 + */ + symbol: 'menu', + /** + * The key to a [lang](#lang) option setting that is used for the + * button's title tooltip. When the key is `contextButtonTitle`, it + * refers to [lang.contextButtonTitle](#lang.contextButtonTitle) + * that defaults to "Chart context menu". + * + * @since 6.1.4 + */ + titleKey: 'contextButtonTitle', + /** + * This option is deprecated, use + * [titleKey](#exporting.buttons.contextButton.titleKey) instead. + * + * @deprecated + * @type {string} + * @apioption exporting.buttons.contextButton._titleKey + */ + /** + * A collection of strings pointing to config options for the menu + * items. The config options are defined in the + * `menuItemDefinitions` option. + * + * By default, there is the "View in full screen" and "Print" menu + * items, plus one menu item for each of the available export types. + * + * @sample {highcharts} highcharts/exporting/menuitemdefinitions/ + * Menu item definitions + * @sample {highstock} highcharts/exporting/menuitemdefinitions/ + * Menu item definitions + * @sample {highmaps} highcharts/exporting/menuitemdefinitions/ + * Menu item definitions + * + * @type {Array} + * @default ["viewFullscreen", "printChart", "separator", "downloadPNG", "downloadJPEG", "downloadPDF", "downloadSVG"] + * @since 2.0 + */ + menuItems: [ + 'viewFullscreen', + 'printChart', + 'separator', + 'downloadPNG', + 'downloadJPEG', + 'downloadPDF', + 'downloadSVG' + ] + } + }, + /** + * An object consisting of definitions for the menu items in the context + * menu. Each key value pair has a `key` that is referenced in the + * [menuItems](#exporting.buttons.contextButton.menuItems) setting, + * and a `value`, which is an object with the following properties: + * + * - **onclick:** The click handler for the menu item + * + * - **text:** The text for the menu item + * + * - **textKey:** If internationalization is required, the key to a language + * string + * + * Custom text for the "exitFullScreen" can be set only in lang options + * (it is not a separate button). + * + * @sample {highcharts} highcharts/exporting/menuitemdefinitions/ + * Menu item definitions + * @sample {highstock} highcharts/exporting/menuitemdefinitions/ + * Menu item definitions + * @sample {highmaps} highcharts/exporting/menuitemdefinitions/ + * Menu item definitions + * + * + * @type {Highcharts.Dictionary} + * @default {"viewFullscreen": {}, "printChart": {}, "separator": {}, "downloadPNG": {}, "downloadJPEG": {}, "downloadPDF": {}, "downloadSVG": {}} + * @since 5.0.13 + */ + menuItemDefinitions: { + /** + * @ignore + */ + viewFullscreen: { + textKey: 'viewFullscreen', + onclick: function () { + this.fullscreen.toggle(); + } + }, + /** + * @ignore + */ + printChart: { + textKey: 'printChart', + onclick: function () { + this.print(); + } + }, + /** + * @ignore + */ + separator: { + separator: true + }, + /** + * @ignore + */ + downloadPNG: { + textKey: 'downloadPNG', + onclick: function () { + this.exportChart(); + } + }, + /** + * @ignore + */ + downloadJPEG: { + textKey: 'downloadJPEG', + onclick: function () { + this.exportChart({ + type: 'image/jpeg' + }); + } + }, + /** + * @ignore + */ + downloadPDF: { + textKey: 'downloadPDF', + onclick: function () { + this.exportChart({ + type: 'application/pdf' + }); + } + }, + /** + * @ignore + */ + downloadSVG: { + textKey: 'downloadSVG', + onclick: function () { + this.exportChart({ + type: 'image/svg+xml' + }); + } + } + } +}; +/** + * Fires after a chart is printed through the context menu item or the + * `Chart.print` method. + * + * @sample highcharts/chart/events-beforeprint-afterprint/ + * Rescale the chart to print + * + * @type {Highcharts.ExportingAfterPrintCallbackFunction} + * @since 4.1.0 + * @context Highcharts.Chart + * @requires modules/exporting + * @apioption chart.events.afterPrint + */ +/** + * Fires before a chart is printed through the context menu item or + * the `Chart.print` method. + * + * @sample highcharts/chart/events-beforeprint-afterprint/ + * Rescale the chart to print + * + * @type {Highcharts.ExportingBeforePrintCallbackFunction} + * @since 4.1.0 + * @context Highcharts.Chart + * @requires modules/exporting + * @apioption chart.events.beforePrint + */ +/** + * The post utility + * + * @private + * @function Highcharts.post + * @param {string} url + * Post URL + * @param {object} data + * Post data + * @param {Highcharts.Dictionary} [formAttributes] + * Additional attributes for the post request + * @return {void} + */ +H.post = function (url, data, formAttributes) { + // create the form + var form = createElement('form', merge({ + method: 'post', + action: url, + enctype: 'multipart/form-data' + }, formAttributes), { + display: 'none' + }, doc.body); + // add the data + objectEach(data, function (val, name) { + createElement('input', { + type: 'hidden', + name: name, + value: val + }, null, form); + }); + // submit + form.submit(); + // clean up + discardElement(form); +}; +if (H.isSafari) { + H.win.matchMedia('print').addListener(function (mqlEvent) { + if (!H.printingChart) { + return void 0; + } + if (mqlEvent.matches) { + H.printingChart.beforePrint(); + } + else { + H.printingChart.afterPrint(); + } + }); +} +extend(Chart.prototype, /** @lends Highcharts.Chart.prototype */ { + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Exporting module only. A collection of fixes on the produced SVG to + * account for expando properties, browser bugs, VML problems and other. + * Returns a cleaned SVG. + * + * @private + * @function Highcharts.Chart#sanitizeSVG + * @param {string} svg + * SVG code to sanitize + * @param {Highcharts.Options} options + * Chart options to apply + * @return {string} + * Sanitized SVG code + * @requires modules/exporting + */ + sanitizeSVG: function (svg, options) { + var split = svg.indexOf('') + 6, html = svg.substr(split); + // Remove any HTML added to the container after the SVG (#894, #9087) + svg = svg.substr(0, split); + // Move HTML into a foreignObject + if (options && options.exporting && options.exporting.allowHTML) { + if (html) { + html = '' + + '' + + html + + '' + + ''; + svg = svg.replace('', html + ''); + } + } + svg = svg + .replace(/zIndex="[^"]+"/g, '') + .replace(/symbolName="[^"]+"/g, '') + .replace(/jQuery[0-9]+="[^"]+"/g, '') + .replace(/url\(("|")(.*?)("|")\;?\)/g, 'url($2)') + .replace(/url\([^#]+#/g, 'url(#') + .replace(/]+(>|$)/g, '') // strip HTML tags + .replace(/[\s_]+/g, '-') + .replace(/[^a-z0-9\-]/g, '') // preserve only latin + .replace(/^[\-]+/g, '') // dashes in the start + .replace(/[\-]+/g, '-') // dashes in a row + .substr(0, 24) + .replace(/[\-]+$/g, ''); // dashes in the end; + } + if (!filename || filename.length < 5) { + filename = 'chart'; + } + return filename; + }, + /** + * Exporting module required. Submit an SVG version of the chart to a server + * along with some parameters for conversion. + * + * @sample highcharts/members/chart-exportchart/ + * Export with no options + * @sample highcharts/members/chart-exportchart-filename/ + * PDF type and custom filename + * @sample highcharts/members/chart-exportchart-custom-background/ + * Different chart background in export + * @sample stock/members/chart-exportchart/ + * Export with Highstock + * + * @function Highcharts.Chart#exportChart + * + * @param {Highcharts.ExportingOptions} exportingOptions + * Exporting options in addition to those defined in + * [exporting](https://api.highcharts.com/highcharts/exporting). + * + * @param {Highcharts.Options} chartOptions + * Additional chart options for the exported chart. For example a + * different background color can be added here, or `dataLabels` for + * export only. + * + * @return {void} + * + * @requires modules/exporting + */ + exportChart: function (exportingOptions, chartOptions) { + var svg = this.getSVGForExport(exportingOptions, chartOptions); + // merge the options + exportingOptions = merge(this.options.exporting, exportingOptions); + // do the post + H.post(exportingOptions.url, { + filename: exportingOptions.filename ? exportingOptions.filename.replace(/\//g, '-') : this.getFilename(), + type: exportingOptions.type, + // IE8 fails to post undefined correctly, so use 0 + width: exportingOptions.width || 0, + scale: exportingOptions.scale, + svg: svg + }, exportingOptions.formAttributes); + }, + /** + * Move the chart container(s) to another div. + * + * @function Highcharts#moveContainers + * + * @private + * + * @param {Highcharts.HTMLDOMElement} moveTo + * Move target + * @return {void} + */ + moveContainers: function (moveTo) { + var chart = this; + (chart.fixedDiv ? // When scrollablePlotArea is active (#9533) + [chart.fixedDiv, chart.scrollingContainer] : + [chart.container]).forEach(function (div) { + moveTo.appendChild(div); + }); + }, + /** + * Prepare chart and document before printing a chart. + * + * @function Highcharts#beforePrint + * + * @private + * + * @return {void} + * + * @fires Highcharts.Chart#event:beforePrint + */ + beforePrint: function () { + var chart = this, body = doc.body, printMaxWidth = chart.options.exporting.printMaxWidth, printReverseInfo = { + childNodes: body.childNodes, + origDisplay: [], + resetParams: void 0 + }; + var handleMaxWidth; + chart.isPrinting = true; + chart.pointer.reset(null, 0); + fireEvent(chart, 'beforePrint'); + // Handle printMaxWidth + handleMaxWidth = printMaxWidth && chart.chartWidth > printMaxWidth; + if (handleMaxWidth) { + printReverseInfo.resetParams = [ + chart.options.chart.width, + void 0, + false + ]; + chart.setSize(printMaxWidth, void 0, false); + } + // hide all body content + [].forEach.call(printReverseInfo.childNodes, function (node, i) { + if (node.nodeType === 1) { + printReverseInfo.origDisplay[i] = node.style.display; + node.style.display = 'none'; + } + }); + // pull out the chart + chart.moveContainers(body); + // Storage details for undo action after printing + chart.printReverseInfo = printReverseInfo; + }, + /** + * Clena up after printing a chart. + * + * @function Highcharts#afterPrint + * + * @private + * + * @param {Highcharts.Chart} chart + * Chart that was (or suppose to be) printed + * @return {void} + * + * @fires Highcharts.Chart#event:afterPrint + */ + afterPrint: function () { + var chart = this; + if (!chart.printReverseInfo) { + return void 0; + } + var childNodes = chart.printReverseInfo.childNodes, origDisplay = chart.printReverseInfo.origDisplay, resetParams = chart.printReverseInfo.resetParams; + // put the chart back in + chart.moveContainers(chart.renderTo); + // restore all body content + [].forEach.call(childNodes, function (node, i) { + if (node.nodeType === 1) { + node.style.display = (origDisplay[i] || ''); + } + }); + chart.isPrinting = false; + // Reset printMaxWidth + if (resetParams) { + chart.setSize.apply(chart, resetParams); + } + delete chart.printReverseInfo; + delete H.printingChart; + fireEvent(chart, 'afterPrint'); + }, + /** + * Exporting module required. Clears away other elements in the page and + * prints the chart as it is displayed. By default, when the exporting + * module is enabled, a context button with a drop down menu in the upper + * right corner accesses this function. + * + * @sample highcharts/members/chart-print/ + * Print from a HTML button + * + * @function Highcharts.Chart#print + * + * @return {void} + * + * @fires Highcharts.Chart#event:beforePrint + * @fires Highcharts.Chart#event:afterPrint + * + * @requires modules/exporting + */ + print: function () { + var chart = this; + if (chart.isPrinting) { // block the button while in printing mode + return; + } + H.printingChart = chart; + if (!H.isSafari) { + chart.beforePrint(); + } + // Give the browser time to draw WebGL content, an issue that randomly + // appears (at least) in Chrome ~67 on the Mac (#8708). + setTimeout(function () { + win.focus(); // #1510 + win.print(); + // allow the browser to prepare before reverting + if (!H.isSafari) { + setTimeout(function () { + chart.afterPrint(); + }, 1000); + } + }, 1); + }, + /** + * Display a popup menu for choosing the export type. + * + * @private + * @function Highcharts.Chart#contextMenu + * @param {string} className + * An identifier for the menu. + * @param {Array} items + * A collection with text and onclicks for the items. + * @param {number} x + * The x position of the opener button + * @param {number} y + * The y position of the opener button + * @param {number} width + * The width of the opener button + * @param {number} height + * The height of the opener button + * @return {void} + * @requires modules/exporting + */ + contextMenu: function (className, items, x, y, width, height, button) { + var chart = this, navOptions = chart.options.navigation, chartWidth = chart.chartWidth, chartHeight = chart.chartHeight, cacheName = 'cache-' + className, menu = chart[cacheName], menuPadding = Math.max(width, height), // for mouse leave detection + innerMenu, menuStyle; + // create the menu only the first time + if (!menu) { + // create a HTML element above the SVG + chart.exportContextMenu = chart[cacheName] = menu = + createElement('div', { + className: className + }, { + position: 'absolute', + zIndex: 1000, + padding: menuPadding + 'px', + pointerEvents: 'auto' + }, chart.fixedDiv || chart.container); + innerMenu = createElement('ul', { className: 'highcharts-menu' }, { + listStyle: 'none', + margin: 0, + padding: 0 + }, menu); + // Presentational CSS + if (!chart.styledMode) { + css(innerMenu, extend({ + MozBoxShadow: '3px 3px 10px #888', + WebkitBoxShadow: '3px 3px 10px #888', + boxShadow: '3px 3px 10px #888' + }, navOptions.menuStyle)); + } + // hide on mouse out + menu.hideMenu = function () { + css(menu, { display: 'none' }); + if (button) { + button.setState(0); + } + chart.openMenu = false; + css(chart.renderTo, { overflow: 'hidden' }); // #10361 + U.clearTimeout(menu.hideTimer); + fireEvent(chart, 'exportMenuHidden'); + }; + // Hide the menu some time after mouse leave (#1357) + chart.exportEvents.push(addEvent(menu, 'mouseleave', function () { + menu.hideTimer = win.setTimeout(menu.hideMenu, 500); + }), addEvent(menu, 'mouseenter', function () { + U.clearTimeout(menu.hideTimer); + }), + // Hide it on clicking or touching outside the menu (#2258, + // #2335, #2407) + addEvent(doc, 'mouseup', function (e) { + if (!chart.pointer.inClass(e.target, className)) { + menu.hideMenu(); + } + }), addEvent(menu, 'click', function () { + if (chart.openMenu) { + menu.hideMenu(); + } + })); + // create the items + items.forEach(function (item) { + if (typeof item === 'string') { + item = chart.options.exporting + .menuItemDefinitions[item]; + } + if (isObject(item, true)) { + var element; + if (item.separator) { + element = createElement('hr', null, null, innerMenu); + } + else { + element = createElement('li', { + className: 'highcharts-menu-item', + onclick: function (e) { + if (e) { // IE7 + e.stopPropagation(); + } + menu.hideMenu(); + if (item.onclick) { + item.onclick + .apply(chart, arguments); + } + }, + innerHTML: (item.text || + chart.options.lang[item.textKey]) + }, null, innerMenu); + if (!chart.styledMode) { + element.onmouseover = function () { + css(this, navOptions.menuItemHoverStyle); + }; + element.onmouseout = function () { + css(this, navOptions.menuItemStyle); + }; + css(element, extend({ + cursor: 'pointer' + }, navOptions.menuItemStyle)); + } + } + // Keep references to menu divs to be able to destroy them + chart.exportDivElements.push(element); + } + }); + // Keep references to menu and innerMenu div to be able to destroy + // them + chart.exportDivElements.push(innerMenu, menu); + chart.exportMenuWidth = menu.offsetWidth; + chart.exportMenuHeight = menu.offsetHeight; + } + menuStyle = { display: 'block' }; + // if outside right, right align it + if (x + chart.exportMenuWidth > chartWidth) { + menuStyle.right = (chartWidth - x - width - menuPadding) + 'px'; + } + else { + menuStyle.left = (x - menuPadding) + 'px'; + } + // if outside bottom, bottom align it + if (y + height + chart.exportMenuHeight > chartHeight && + button.alignOptions.verticalAlign !== 'top') { + menuStyle.bottom = (chartHeight - y - menuPadding) + 'px'; + } + else { + menuStyle.top = (y + height - menuPadding) + 'px'; + } + css(menu, menuStyle); + css(chart.renderTo, { overflow: '' }); // #10361 + chart.openMenu = true; + fireEvent(chart, 'exportMenuShown'); + }, + /** + * Add the export button to the chart, with options. + * + * @private + * @function Highcharts.Chart#addButton + * @param {Highcharts.NavigationButtonOptions} options + * @return {void} + * @requires modules/exporting + */ + addButton: function (options) { + var chart = this, renderer = chart.renderer, btnOptions = merge(chart.options.navigation.buttonOptions, options), onclick = btnOptions.onclick, menuItems = btnOptions.menuItems, symbol, button, symbolSize = btnOptions.symbolSize || 12; + if (!chart.btnCount) { + chart.btnCount = 0; + } + // Keeps references to the button elements + if (!chart.exportDivElements) { + chart.exportDivElements = []; + chart.exportSVGElements = []; + } + if (btnOptions.enabled === false) { + return; + } + var attr = btnOptions.theme, states = attr.states, hover = states && states.hover, select = states && states.select, callback; + if (!chart.styledMode) { + attr.fill = pick(attr.fill, '#ffffff'); + attr.stroke = pick(attr.stroke, 'none'); + } + delete attr.states; + if (onclick) { + callback = function (e) { + if (e) { + e.stopPropagation(); + } + onclick.call(chart, e); + }; + } + else if (menuItems) { + callback = function (e) { + // consistent with onclick call (#3495) + if (e) { + e.stopPropagation(); + } + chart.contextMenu(button.menuClassName, menuItems, button.translateX, button.translateY, button.width, button.height, button); + button.setState(2); + }; + } + if (btnOptions.text && btnOptions.symbol) { + attr.paddingLeft = pick(attr.paddingLeft, 25); + } + else if (!btnOptions.text) { + extend(attr, { + width: btnOptions.width, + height: btnOptions.height, + padding: 0 + }); + } + if (!chart.styledMode) { + attr['stroke-linecap'] = 'round'; + attr.fill = pick(attr.fill, '#ffffff'); + attr.stroke = pick(attr.stroke, 'none'); + } + button = renderer + .button(btnOptions.text, 0, 0, callback, attr, hover, select) + .addClass(options.className) + .attr({ + title: pick(chart.options.lang[btnOptions._titleKey || btnOptions.titleKey], '') + }); + button.menuClassName = (options.menuClassName || + 'highcharts-menu-' + chart.btnCount++); + if (btnOptions.symbol) { + symbol = renderer + .symbol(btnOptions.symbol, btnOptions.symbolX - (symbolSize / 2), btnOptions.symbolY - (symbolSize / 2), symbolSize, symbolSize + // If symbol is an image, scale it (#7957) + , { + width: symbolSize, + height: symbolSize + }) + .addClass('highcharts-button-symbol') + .attr({ + zIndex: 1 + }) + .add(button); + if (!chart.styledMode) { + symbol.attr({ + stroke: btnOptions.symbolStroke, + fill: btnOptions.symbolFill, + 'stroke-width': btnOptions.symbolStrokeWidth || 1 + }); + } + } + button + .add(chart.exportingGroup) + .align(extend(btnOptions, { + width: button.width, + x: pick(btnOptions.x, chart.buttonOffset) // #1654 + }), true, 'spacingBox'); + chart.buttonOffset += ((button.width + btnOptions.buttonSpacing) * + (btnOptions.align === 'right' ? -1 : 1)); + chart.exportSVGElements.push(button, symbol); + }, + /** + * Destroy the export buttons. + * @private + * @function Highcharts.Chart#destroyExport + * @param {global.Event} [e] + * @return {void} + * @requires modules/exporting + */ + destroyExport: function (e) { + var chart = e ? e.target : this, exportSVGElements = chart.exportSVGElements, exportDivElements = chart.exportDivElements, exportEvents = chart.exportEvents, cacheName; + // Destroy the extra buttons added + if (exportSVGElements) { + exportSVGElements.forEach(function (elem, i) { + // Destroy and null the svg elements + if (elem) { // #1822 + elem.onclick = elem.ontouchstart = null; + cacheName = 'cache-' + elem.menuClassName; + if (chart[cacheName]) { + delete chart[cacheName]; + } + chart.exportSVGElements[i] = elem.destroy(); + } + }); + exportSVGElements.length = 0; + } + // Destroy the exporting group + if (chart.exportingGroup) { + chart.exportingGroup.destroy(); + delete chart.exportingGroup; + } + // Destroy the divs for the menu + if (exportDivElements) { + exportDivElements.forEach(function (elem, i) { + // Remove the event handler + U.clearTimeout(elem.hideTimer); // #5427 + removeEvent(elem, 'mouseleave'); + // Remove inline events + chart.exportDivElements[i] = + elem.onmouseout = + elem.onmouseover = + elem.ontouchstart = + elem.onclick = null; + // Destroy the div by moving to garbage bin + discardElement(elem); + }); + exportDivElements.length = 0; + } + if (exportEvents) { + exportEvents.forEach(function (unbind) { + unbind(); + }); + exportEvents.length = 0; + } + } + /* eslint-enable no-invalid-this, valid-jsdoc */ +}); +// These ones are translated to attributes rather than styles +SVGRenderer.prototype.inlineToAttributes = [ + 'fill', + 'stroke', + 'strokeLinecap', + 'strokeLinejoin', + 'strokeWidth', + 'textAnchor', + 'x', + 'y' +]; +// These CSS properties are not inlined. Remember camelCase. +SVGRenderer.prototype.inlineBlacklist = [ + /-/, + /^(clipPath|cssText|d|height|width)$/, + /^font$/, + /[lL]ogical(Width|Height)$/, + /perspective/, + /TapHighlightColor/, + /^transition/, + /^length$/ // #7700 + // /^text (border|color|cursor|height|webkitBorder)/ +]; +SVGRenderer.prototype.unstyledElements = [ + 'clipPath', + 'defs', + 'desc' +]; +/** + * Analyze inherited styles from stylesheets and add them inline + * + * @private + * @function Highcharts.Chart#inlineStyles + * @return {void} + * + * @todo: What are the border styles for text about? In general, text has a lot + * of properties. + * @todo: Make it work with IE9 and IE10. + * + * @requires modules/exporting + */ +Chart.prototype.inlineStyles = function () { + var renderer = this.renderer, inlineToAttributes = renderer.inlineToAttributes, blacklist = renderer.inlineBlacklist, whitelist = renderer.inlineWhitelist, // For IE + unstyledElements = renderer.unstyledElements, defaultStyles = {}, dummySVG, iframe, iframeDoc; + // Create an iframe where we read default styles without pollution from this + // body + iframe = doc.createElement('iframe'); + css(iframe, { + width: '1px', + height: '1px', + visibility: 'hidden' + }); + doc.body.appendChild(iframe); + iframeDoc = iframe.contentWindow.document; + iframeDoc.open(); + iframeDoc.write(''); + iframeDoc.close(); + /** + * Make hyphenated property names out of camelCase + * @private + * @param {string} prop + * Property name in camelCase + * @return {string} + * Hyphenated property name + */ + function hyphenate(prop) { + return prop.replace(/([A-Z])/g, function (a, b) { + return '-' + b.toLowerCase(); + }); + } + /** + * Call this on all elements and recurse to children + * @private + * @param {Highcharts.HTMLDOMElement} node + * Element child + * @return {void} + */ + function recurse(node) { + var styles, parentStyles, cssText = '', dummy, styleAttr, blacklisted, whitelisted, i; + /** + * Check computed styles and whether they are in the white/blacklist for + * styles or atttributes. + * @private + * @param {string} val + * Style value + * @param {string} prop + * Style property name + * @return {void} + */ + function filterStyles(val, prop) { + // Check against whitelist & blacklist + blacklisted = whitelisted = false; + if (whitelist) { + // Styled mode in IE has a whitelist instead. + // Exclude all props not in this list. + i = whitelist.length; + while (i-- && !whitelisted) { + whitelisted = whitelist[i].test(prop); + } + blacklisted = !whitelisted; + } + // Explicitly remove empty transforms + if (prop === 'transform' && val === 'none') { + blacklisted = true; + } + i = blacklist.length; + while (i-- && !blacklisted) { + blacklisted = (blacklist[i].test(prop) || + typeof val === 'function'); + } + if (!blacklisted) { + // If parent node has the same style, it gets inherited, no need + // to inline it. Top-level props should be diffed against parent + // (#7687). + if ((parentStyles[prop] !== val || node.nodeName === 'svg') && + defaultStyles[node.nodeName][prop] !== val) { + // Attributes + if (inlineToAttributes.indexOf(prop) !== -1) { + node.setAttribute(hyphenate(prop), val); + // Styles + } + else { + cssText += hyphenate(prop) + ':' + val + ';'; + } + } + } + } + if (node.nodeType === 1 && + unstyledElements.indexOf(node.nodeName) === -1) { + styles = win.getComputedStyle(node, null); + parentStyles = node.nodeName === 'svg' ? + {} : + win.getComputedStyle(node.parentNode, null); + // Get default styles from the browser so that we don't have to add + // these + if (!defaultStyles[node.nodeName]) { + /* + if (!dummySVG) { + dummySVG = doc.createElementNS(H.SVG_NS, 'svg'); + dummySVG.setAttribute('version', '1.1'); + doc.body.appendChild(dummySVG); + } + */ + dummySVG = iframeDoc.getElementsByTagName('svg')[0]; + dummy = iframeDoc.createElementNS(node.namespaceURI, node.nodeName); + dummySVG.appendChild(dummy); + // Copy, so we can remove the node + defaultStyles[node.nodeName] = merge(win.getComputedStyle(dummy, null)); + // Remove default fill, otherwise text disappears when exported + if (node.nodeName === 'text') { + delete defaultStyles.text.fill; + } + dummySVG.removeChild(dummy); + } + // Loop through all styles and add them inline if they are ok + if (isFirefoxBrowser || isMSBrowser) { + // Some browsers put lots of styles on the prototype + for (var p in styles) { // eslint-disable-line guard-for-in + filterStyles(styles[p], p); + } + } + else { + objectEach(styles, filterStyles); + } + // Apply styles + if (cssText) { + styleAttr = node.getAttribute('style'); + node.setAttribute('style', (styleAttr ? styleAttr + ';' : '') + cssText); + } + // Set default stroke width (needed at least for IE) + if (node.nodeName === 'svg') { + node.setAttribute('stroke-width', '1px'); + } + if (node.nodeName === 'text') { + return; + } + // Recurse + [].forEach.call(node.children || node.childNodes, recurse); + } + } + /** + * Remove the dummy objects used to get defaults + * @private + * @return {void} + */ + function tearDown() { + dummySVG.parentNode.removeChild(dummySVG); + } + recurse(this.container.querySelector('svg')); + tearDown(); +}; +symbols.menu = function (x, y, width, height) { + var arr = [ + ['M', x, y + 2.5], + ['L', x + width, y + 2.5], + ['M', x, y + height / 2 + 0.5], + ['L', x + width, y + height / 2 + 0.5], + ['M', x, y + height - 1.5], + ['L', x + width, y + height - 1.5] + ]; + return arr; +}; +symbols.menuball = function (x, y, width, height) { + var path = [], h = (height / 3) - 2; + path = path.concat(this.circle(width - h, y, h, h), this.circle(width - h, y + h + 4, h, h), this.circle(width - h, y + 2 * (h + 4), h, h)); + return path; +}; +/** + * Add the buttons on chart load + * @private + * @function Highcharts.Chart#renderExporting + * @return {void} + * @requires modules/exporting + */ +Chart.prototype.renderExporting = function () { + var chart = this, exportingOptions = chart.options.exporting, buttons = exportingOptions.buttons, isDirty = chart.isDirtyExporting || !chart.exportSVGElements; + chart.buttonOffset = 0; + if (chart.isDirtyExporting) { + chart.destroyExport(); + } + if (isDirty && exportingOptions.enabled !== false) { + chart.exportEvents = []; + chart.exportingGroup = chart.exportingGroup || + chart.renderer.g('exporting-group').attr({ + zIndex: 3 // #4955, // #8392 + }).add(); + objectEach(buttons, function (button) { + chart.addButton(button); + }); + chart.isDirtyExporting = false; + } + // Destroy the export elements at chart destroy + addEvent(chart, 'destroy', chart.destroyExport); +}; +/* eslint-disable no-invalid-this */ +// Add update methods to handle chart.update and chart.exporting.update and +// chart.navigation.update. These must be added to the chart instance rather +// than the Chart prototype in order to use the chart instance inside the update +// function. +addEvent(Chart, 'init', function () { + var chart = this; + /** + * @private + * @param {"exporting"|"navigation"} prop + * Property name in option root + * @param {Highcharts.ExportingOptions|Highcharts.NavigationOptions} options + * Options to update + * @param {boolean} [redraw=true] + * Whether to redraw + * @return {void} + */ + function update(prop, options, redraw) { + chart.isDirtyExporting = true; + merge(true, chart.options[prop], options); + if (pick(redraw, true)) { + chart.redraw(); + } + } + chart.exporting = { + update: function (options, redraw) { + update('exporting', options, redraw); + } + }; + // Register update() method for navigation. Can not be set the same way as + // for exporting, because navigation options are shared with bindings which + // has separate update() logic. + chartNavigationMixin.addUpdate(function (options, redraw) { + update('navigation', options, redraw); + }, chart); +}); +/* eslint-enable no-invalid-this */ +Chart.prototype.callbacks.push(function (chart) { + chart.renderExporting(); + addEvent(chart, 'redraw', chart.renderExporting); + // Uncomment this to see a button directly below the chart, for quick + // testing of export + /* + var button, viewImage, viewSource; + if (!chart.renderer.forExport) { + viewImage = function () { + var div = doc.createElement('div'); + div.innerHTML = chart.getSVGForExport(); + chart.renderTo.parentNode.appendChild(div); + }; + + viewSource = function () { + var pre = doc.createElement('pre'); + pre.innerHTML = chart.getSVGForExport() + .replace(//g, '>'); + chart.renderTo.parentNode.appendChild(pre); + }; + + viewImage(); + + // View SVG Image + button = doc.createElement('button'); + button.innerHTML = 'View SVG Image'; + chart.renderTo.parentNode.appendChild(button); + button.onclick = viewImage; + + // View SVG Source + button = doc.createElement('button'); + button.innerHTML = 'View SVG Source'; + chart.renderTo.parentNode.appendChild(button); + button.onclick = viewSource; + } + //*/ +}); diff --git a/librerias/gantt/code/es-modules/modules/full-screen.src.js b/librerias/gantt/code/es-modules/modules/full-screen.src.js new file mode 100644 index 0000000..dbcbab3 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/full-screen.src.js @@ -0,0 +1,212 @@ +/* * + * (c) 2009-2020 Rafal Sebestjanski + * + * Full screen for Highcharts + * + * License: www.highcharts.com/license + */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent; +var Chart = H.Chart; +/** + * The module allows user to enable display chart in full screen mode. + * Used in StockTools too. + * Based on default solutions in browsers. + * + */ +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * Handles displaying chart's container in the fullscreen mode. + * + * @class + * @name Highcharts.Fullscreen + * @hideconstructor + * @requires modules/full-screen + */ +var Fullscreen = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Fullscreen(chart) { + /** + * Chart managed by the fullscreen controller. + * @name Highcharts.Fullscreen#chart + * @type {Highcharts.Chart} + */ + this.chart = chart; + /** + * The flag is set to `true` when the chart is displayed in + * the fullscreen mode. + * + * @name Highcharts.Fullscreen#isOpen + * @type {boolean|undefined} + * @since 8.0.1 + */ + this.isOpen = false; + var container = chart.renderTo; + // Hold event and methods available only for a current browser. + if (!this.browserProps) { + if (typeof container.requestFullscreen === 'function') { + this.browserProps = { + fullscreenChange: 'fullscreenchange', + requestFullscreen: 'requestFullscreen', + exitFullscreen: 'exitFullscreen' + }; + } + else if (container.mozRequestFullScreen) { + this.browserProps = { + fullscreenChange: 'mozfullscreenchange', + requestFullscreen: 'mozRequestFullScreen', + exitFullscreen: 'mozCancelFullScreen' + }; + } + else if (container.webkitRequestFullScreen) { + this.browserProps = { + fullscreenChange: 'webkitfullscreenchange', + requestFullscreen: 'webkitRequestFullScreen', + exitFullscreen: 'webkitExitFullscreen' + }; + } + else if (container.msRequestFullscreen) { + this.browserProps = { + fullscreenChange: 'MSFullscreenChange', + requestFullscreen: 'msRequestFullscreen', + exitFullscreen: 'msExitFullscreen' + }; + } + } + } + /* * + * + * Functions + * + * */ + /** + * Stops displaying the chart in fullscreen mode. + * Exporting module required. + * + * @since 8.0.1 + * + * @function Highcharts.Fullscreen#close + * @return {void} + * @requires modules/full-screen + */ + Fullscreen.prototype.close = function () { + var fullscreen = this, chart = fullscreen.chart; + // Don't fire exitFullscreen() when user exited using 'Escape' button. + if (fullscreen.isOpen && + fullscreen.browserProps && + chart.container.ownerDocument instanceof Document) { + chart.container.ownerDocument[fullscreen.browserProps.exitFullscreen](); + } + // Unbind event as it's necessary only before exiting from fullscreen. + if (fullscreen.unbindFullscreenEvent) { + fullscreen.unbindFullscreenEvent(); + } + fullscreen.isOpen = false; + fullscreen.setButtonText(); + }; + /** + * Displays the chart in fullscreen mode. + * When fired customly by user before exporting context button is created, + * button's text will not be replaced - it's on the user side. + * Exporting module required. + * + * @since 8.0.1 + * + * @function Highcharts.Fullscreen#open + * @return {void} + * @requires modules/full-screen + */ + Fullscreen.prototype.open = function () { + var fullscreen = this, chart = fullscreen.chart; + // Handle exitFullscreen() method when user clicks 'Escape' button. + if (fullscreen.browserProps) { + fullscreen.unbindFullscreenEvent = addEvent(chart.container.ownerDocument, // chart's document + fullscreen.browserProps.fullscreenChange, function () { + // Handle lack of async of browser's fullScreenChange event. + if (fullscreen.isOpen) { + fullscreen.isOpen = false; + fullscreen.close(); + } + else { + fullscreen.isOpen = true; + fullscreen.setButtonText(); + } + }); + var promise = chart.renderTo[fullscreen.browserProps.requestFullscreen](); + if (promise) { + // No dot notation because of IE8 compatibility + promise['catch'](function () { + alert(// eslint-disable-line no-alert + 'Full screen is not supported inside a frame.'); + }); + } + addEvent(chart, 'destroy', fullscreen.unbindFullscreenEvent); + } + }; + /** + * Replaces the exporting context button's text when toogling the + * fullscreen mode. + * + * @private + * + * @since 8.0.1 + * + * @requires modules/full-screen + * @return {void} + */ + Fullscreen.prototype.setButtonText = function () { + var _a; + var chart = this.chart, exportDivElements = chart.exportDivElements, exportingOptions = chart.options.exporting, menuItems = (_a = exportingOptions === null || exportingOptions === void 0 ? void 0 : exportingOptions.buttons) === null || _a === void 0 ? void 0 : _a.contextButton.menuItems, lang = chart.options.lang; + if ((exportingOptions === null || exportingOptions === void 0 ? void 0 : exportingOptions.menuItemDefinitions) && (lang === null || lang === void 0 ? void 0 : lang.exitFullscreen) && + lang.viewFullscreen && + menuItems && + exportDivElements && + exportDivElements.length) { + exportDivElements[menuItems.indexOf('viewFullscreen')] + .innerHTML = !this.isOpen ? + (exportingOptions.menuItemDefinitions.viewFullscreen.text || + lang.viewFullscreen) : lang.exitFullscreen; + } + }; + /** + * Toggles displaying the chart in fullscreen mode. + * By default, when the exporting module is enabled, a context button with + * a drop down menu in the upper right corner accesses this function. + * Exporting module required. + * + * @since 8.0.1 + * + * @sample highcharts/members/chart-togglefullscreen/ + * Toggle fullscreen mode from a HTML button + * + * @function Highcharts.Fullscreen#toggle + * @requires modules/full-screen + */ + Fullscreen.prototype.toggle = function () { + var fullscreen = this; + if (!fullscreen.isOpen) { + fullscreen.open(); + } + else { + fullscreen.close(); + } + }; + return Fullscreen; +}()); +H.Fullscreen = Fullscreen; +export default H.Fullscreen; +// Initialize fullscreen +addEvent(Chart, 'beforeRender', function () { + /** + * @name Highcharts.Chart#fullscreen + * @type {Highcharts.Fullscreen} + * @requires modules/full-screen + */ + this.fullscreen = new H.Fullscreen(this); +}); diff --git a/librerias/gantt/code/es-modules/modules/funnel.src.js b/librerias/gantt/code/es-modules/modules/funnel.src.js new file mode 100644 index 0000000..f35bc5f --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/funnel.src.js @@ -0,0 +1,545 @@ +/* * + * + * Highcharts funnel module + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +/* eslint indent: 0 */ +'use strict'; +import Highcharts from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var isArray = U.isArray, pick = U.pick; +import '../parts/Options.js'; +import '../parts/Series.js'; +// create shortcuts +var seriesType = Highcharts.seriesType, seriesTypes = Highcharts.seriesTypes, fireEvent = Highcharts.fireEvent, addEvent = Highcharts.addEvent, noop = Highcharts.noop; +/** + * @private + * @class + * @name Highcharts.seriesTypes.funnel + * + * @augments Highcharts.Series + */ +seriesType('funnel', 'pie', +/** + * Funnel charts are a type of chart often used to visualize stages in a + * sales project, where the top are the initial stages with the most + * clients. It requires that the modules/funnel.js file is loaded. + * + * @sample highcharts/demo/funnel/ + * Funnel demo + * + * @extends plotOptions.pie + * @excluding innerSize,size,dataSorting + * @product highcharts + * @requires modules/funnel + * @optionparent plotOptions.funnel + */ +{ + /** + * Initial animation is by default disabled for the funnel chart. + */ + animation: false, + /** + * The center of the series. By default, it is centered in the middle + * of the plot area, so it fills the plot area height. + * + * @type {Array} + * @default ["50%", "50%"] + * @since 3.0 + */ + center: ['50%', '50%'], + /** + * The width of the funnel compared to the width of the plot area, + * or the pixel width if it is a number. + * + * @type {number|string} + * @since 3.0 + */ + width: '90%', + /** + * The width of the neck, the lower part of the funnel. A number defines + * pixel width, a percentage string defines a percentage of the plot + * area width. + * + * @sample {highcharts} highcharts/demo/funnel/ + * Funnel demo + * + * @type {number|string} + * @since 3.0 + */ + neckWidth: '30%', + /** + * The height of the funnel or pyramid. If it is a number it defines + * the pixel height, if it is a percentage string it is the percentage + * of the plot area height. + * + * @sample {highcharts} highcharts/demo/funnel/ + * Funnel demo + * + * @type {number|string} + * @since 3.0 + */ + height: '100%', + /** + * The height of the neck, the lower part of the funnel. A number + * defines pixel width, a percentage string defines a percentage of the + * plot area height. + * + * @type {number|string} + */ + neckHeight: '25%', + /** + * A reversed funnel has the widest area down. A reversed funnel with + * no neck width and neck height is a pyramid. + * + * @since 3.0.10 + */ + reversed: false, + /** + * To avoid adapting the data label size in Pie.drawDataLabels. + * @ignore-option + */ + size: true, + dataLabels: { + connectorWidth: 1, + verticalAlign: 'middle' + }, + /** + * Options for the series states. + */ + states: { + /** + * @excluding halo, marker, lineWidth, lineWidthPlus + * @apioption plotOptions.funnel.states.hover + */ + /** + * Options for a selected funnel item. + * + * @excluding halo, marker, lineWidth, lineWidthPlus + */ + select: { + /** + * A specific color for the selected point. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + color: '#cccccc', + /** + * A specific border color for the selected point. + * + * @type {Highcharts.ColorString} + */ + borderColor: '#000000' + } + } +}, +// Properties +{ + animate: noop, + // Overrides the pie translate method + translate: function () { + var sum = 0, series = this, chart = series.chart, options = series.options, reversed = options.reversed, ignoreHiddenPoint = options.ignoreHiddenPoint, plotWidth = chart.plotWidth, plotHeight = chart.plotHeight, cumulative = 0, // start at top + center = options.center, centerX = getLength(center[0], plotWidth), centerY = getLength(center[1], plotHeight), width = getLength(options.width, plotWidth), tempWidth, height = getLength(options.height, plotHeight), neckWidth = getLength(options.neckWidth, plotWidth), neckHeight = getLength(options.neckHeight, plotHeight), neckY = (centerY - height / 2) + height - neckHeight, data = series.data, path, fraction, half = (options.dataLabels.position === 'left' ? + 1 : + 0), x1, y1, x2, x3, y3, x4, y5; + /** + * Get positions - either an integer or a percentage string must be + * given. + * @private + * @param {number|string|undefined} length + * Length + * @param {number} relativeTo + * Relative factor + * @return {number} + * Relative position + */ + function getLength(length, relativeTo) { + return (/%$/).test(length) ? + relativeTo * parseInt(length, 10) / 100 : + parseInt(length, 10); + } + series.getWidthAt = function (y) { + var top = (centerY - height / 2); + return (y > neckY || height === neckHeight) ? + neckWidth : + neckWidth + (width - neckWidth) * + (1 - (y - top) / (height - neckHeight)); + }; + series.getX = function (y, half, point) { + return centerX + (half ? -1 : 1) * + ((series.getWidthAt(reversed ? 2 * centerY - y : y) / 2) + + point.labelDistance); + }; + // Expose + series.center = [centerX, centerY, height]; + series.centerX = centerX; + /* + Individual point coordinate naming: + + x1,y1 _________________ x2,y1 + \ / + \ / + \ / + \ / + \ / + x3,y3 _________ x4,y3 + + Additional for the base of the neck: + + | | + | | + | | + x3,y5 _________ x4,y5 + + */ + // get the total sum + data.forEach(function (point) { + if (!ignoreHiddenPoint || point.visible !== false) { + sum += point.y; + } + }); + data.forEach(function (point) { + // set start and end positions + y5 = null; + fraction = sum ? point.y / sum : 0; + y1 = centerY - height / 2 + cumulative * height; + y3 = y1 + fraction * height; + tempWidth = series.getWidthAt(y1); + x1 = centerX - tempWidth / 2; + x2 = x1 + tempWidth; + tempWidth = series.getWidthAt(y3); + x3 = centerX - tempWidth / 2; + x4 = x3 + tempWidth; + // the entire point is within the neck + if (y1 > neckY) { + x1 = x3 = centerX - neckWidth / 2; + x2 = x4 = centerX + neckWidth / 2; + // the base of the neck + } + else if (y3 > neckY) { + y5 = y3; + tempWidth = series.getWidthAt(neckY); + x3 = centerX - tempWidth / 2; + x4 = x3 + tempWidth; + y3 = neckY; + } + if (reversed) { + y1 = 2 * centerY - y1; + y3 = 2 * centerY - y3; + if (y5 !== null) { + y5 = 2 * centerY - y5; + } + } + // save the path + path = [ + ['M', x1, y1], + ['L', x2, y1], + ['L', x4, y3] + ]; + if (y5 !== null) { + path.push(['L', x4, y5], ['L', x3, y5]); + } + path.push(['L', x3, y3], ['Z']); + // prepare for using shared dr + point.shapeType = 'path'; + point.shapeArgs = { d: path }; + // for tooltips and data labels + point.percentage = fraction * 100; + point.plotX = centerX; + point.plotY = (y1 + (y5 || y3)) / 2; + // Placement of tooltips and data labels + point.tooltipPos = [ + centerX, + point.plotY + ]; + point.dlBox = { + x: x3, + y: y1, + topWidth: x2 - x1, + bottomWidth: x4 - x3, + height: Math.abs(pick(y5, y3) - y1), + width: NaN + }; + // Slice is a noop on funnel points + point.slice = noop; + // Mimicking pie data label placement logic + point.half = half; + if (!ignoreHiddenPoint || point.visible !== false) { + cumulative += fraction; + } + }); + fireEvent(series, 'afterTranslate'); + }, + // Funnel items don't have angles (#2289) + sortByAngle: function (points) { + points.sort(function (a, b) { + return a.plotY - b.plotY; + }); + }, + // Extend the pie data label method + drawDataLabels: function () { + var series = this, data = series.data, labelDistance = series.options.dataLabels.distance, leftSide, sign, point, i = data.length, x, y; + // In the original pie label anticollision logic, the slots are + // distributed from one labelDistance above to one labelDistance + // below the pie. In funnels we don't want this. + series.center[2] -= 2 * labelDistance; + // Set the label position array for each point. + while (i--) { + point = data[i]; + leftSide = point.half; + sign = leftSide ? 1 : -1; + y = point.plotY; + point.labelDistance = pick(point.options.dataLabels && + point.options.dataLabels.distance, labelDistance); + series.maxLabelDistance = Math.max(point.labelDistance, series.maxLabelDistance || 0); + x = series.getX(y, leftSide, point); + // set the anchor point for data labels + point.labelPosition = { + // initial position of the data label - it's utilized for + // finding the final position for the label + natural: { + x: 0, + y: y + }, + 'final': { + // used for generating connector path - + // initialized later in drawDataLabels function + // x: undefined, + // y: undefined + }, + // left - funnel on the left side of the data label + // right - funnel on the right side of the data label + alignment: leftSide ? 'right' : 'left', + connectorPosition: { + breakAt: { + x: x + (point.labelDistance - 5) * sign, + y: y + }, + touchingSliceAt: { + x: x + point.labelDistance * sign, + y: y + } + } + }; + } + seriesTypes[series.options.dataLabels.inside ? 'column' : 'pie'].prototype.drawDataLabels.call(this); + }, + alignDataLabel: function (point, dataLabel, options, alignTo, isNew) { + var series = point.series, reversed = series.options.reversed, dlBox = point.dlBox || point.shapeArgs, align = options.align, verticalAlign = options.verticalAlign, inside = ((series.options || {}).dataLabels || {}).inside, centerY = series.center[1], pointPlotY = (reversed ? + 2 * centerY - point.plotY : + point.plotY), widthAtLabel = series.getWidthAt(pointPlotY - dlBox.height / 2 + + dataLabel.height), offset = verticalAlign === 'middle' ? + (dlBox.topWidth - dlBox.bottomWidth) / 4 : + (widthAtLabel - dlBox.bottomWidth) / 2, y = dlBox.y, x = dlBox.x; + if (verticalAlign === 'middle') { + y = dlBox.y - dlBox.height / 2 + dataLabel.height / 2; + } + else if (verticalAlign === 'top') { + y = dlBox.y - dlBox.height + dataLabel.height + + options.padding; + } + if (verticalAlign === 'top' && !reversed || + verticalAlign === 'bottom' && reversed || + verticalAlign === 'middle') { + if (align === 'right') { + x = dlBox.x - options.padding + offset; + } + else if (align === 'left') { + x = dlBox.x + options.padding - offset; + } + } + alignTo = { + x: x, + y: reversed ? y - dlBox.height : y, + width: dlBox.bottomWidth, + height: dlBox.height + }; + options.verticalAlign = 'bottom'; + // Call the parent method + if (!inside || point.visible) { + Highcharts.Series.prototype.alignDataLabel.call(this, point, dataLabel, options, alignTo, isNew); + } + if (inside) { + if (!point.visible && point.dataLabel) { + // Avoid animation from top + point.dataLabel.placed = false; + } + // If label is inside and we have contrast, set it: + if (point.contrastColor) { + dataLabel.css({ + color: point.contrastColor + }); + } + } + } +}); +/* eslint-disable no-invalid-this */ +addEvent(Highcharts.Chart, 'afterHideAllOverlappingLabels', function () { + this.series.forEach(function (series) { + var dataLabelsOptions = series.options && series.options.dataLabels; + if (isArray(dataLabelsOptions)) { + dataLabelsOptions = dataLabelsOptions[0]; + } + if (series.is('pie') && + series.placeDataLabels && + dataLabelsOptions && + !dataLabelsOptions.inside) { + series.placeDataLabels(); + } + }); +}); +/** + * A `funnel` series. If the [type](#series.funnel.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.funnel + * @excluding dataParser, dataURL, stack, xAxis, yAxis, dataSorting + * @product highcharts + * @requires modules/funnel + * @apioption series.funnel + */ +/** + * An array of data points for the series. For the `funnel` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values + * will be interpreted as `y` options. Example: + * + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of data + * points exceeds the series' [turboThreshold](#series.funnel.turboThreshold), + * this option is not available. + * + * ```js + * data: [{ + * y: 3, + * name: "Point2", + * color: "#00FF00" + * }, { + * y: 1, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array} + * @extends series.pie.data + * @excluding sliced + * @product highcharts + * @apioption series.funnel.data + */ +/** + * Pyramid series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.pyramid + * + * @augments Highcharts.Series + */ +seriesType('pyramid', 'funnel', +/** + * A pyramid series is a special type of funnel, without neck and reversed + * by default. + * + * @sample highcharts/demo/pyramid/ + * Pyramid chart + * + * @extends plotOptions.funnel + * @product highcharts + * @requires modules/funnel + * @optionparent plotOptions.pyramid + */ +{ + /** + * The pyramid neck width is zero by default, as opposed to the funnel, + * which shares the same layout logic. + * + * @since 3.0.10 + */ + neckWidth: '0%', + /** + * The pyramid neck width is zero by default, as opposed to the funnel, + * which shares the same layout logic. + * + * @since 3.0.10 + */ + neckHeight: '0%', + /** + * The pyramid is reversed by default, as opposed to the funnel, which + * shares the layout engine, and is not reversed. + * + * @since 3.0.10 + */ + reversed: true +}); +/** + * A `pyramid` series. If the [type](#series.pyramid.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.pyramid + * @excluding dataParser, dataURL, stack, xAxis, yAxis, dataSorting + * @product highcharts + * @requires modules/funnel + * @apioption series.pyramid + */ +/** + * An array of data points for the series. For the `pyramid` series + * type, points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.pyramid.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * y: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * y: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array} + * @extends series.pie.data + * @excluding sliced + * @product highcharts + * @apioption series.pyramid.data + */ +''; // adds doclets above into transpiled file diff --git a/librerias/gantt/code/es-modules/modules/funnel3d.src.js b/librerias/gantt/code/es-modules/modules/funnel3d.src.js new file mode 100644 index 0000000..c5f827b --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/funnel3d.src.js @@ -0,0 +1,701 @@ +/* * + * + * Highcharts funnel3d series module + * + * (c) 2010-2020 Highsoft AS + * + * Author: Kacper Madej + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import Color from '../parts/Color.js'; +var color = Color.parse; +import U from '../parts/Utilities.js'; +var error = U.error, extend = U.extend, merge = U.merge, pick = U.pick, relativeLength = U.relativeLength, seriesType = U.seriesType; +import '../parts/ColumnSeries.js'; +import '../parts/SvgRenderer.js'; +var charts = H.charts, seriesTypes = H.seriesTypes, +// Use H.Renderer instead of H.SVGRenderer for VML support. +RendererProto = H.Renderer.prototype, +// +cuboidPath = RendererProto.cuboidPath, funnel3dMethods; +/** + * The funnel3d series type. + * + * @constructor seriesTypes.funnel3d + * @augments seriesTypes.column + * @requires highcharts-3d + * @requires modules/cylinder + * @requires modules/funnel3d + */ +seriesType('funnel3d', 'column', +/** + * A funnel3d is a 3d version of funnel series type. Funnel charts are + * a type of chart often used to visualize stages in a sales project, + * where the top are the initial stages with the most clients. + * + * It requires that the `highcharts-3d.js`, `cylinder.js` and + * `funnel3d.js` module are loaded. + * + * @sample highcharts/demo/funnel3d/ + * Funnel3d + * + * @extends plotOptions.column + * @excluding allAreas, boostThreshold, colorAxis, compare, compareBase, + * dataSorting + * @product highcharts + * @since 7.1.0 + * @requires highcharts-3d + * @requires modules/cylinder + * @requires modules/funnel3d + * @optionparent plotOptions.funnel3d + */ +{ + /** @ignore-option */ + center: ['50%', '50%'], + /** + * The max width of the series compared to the width of the plot area, + * or the pixel width if it is a number. + * + * @type {number|string} + * @sample {highcharts} highcharts/demo/funnel3d/ Funnel3d demo + * @product highcharts + */ + width: '90%', + /** + * The width of the neck, the lower part of the funnel. A number defines + * pixel width, a percentage string defines a percentage of the plot + * area width. + * + * @type {number|string} + * @sample {highcharts} highcharts/demo/funnel3d/ Funnel3d demo + * @product highcharts + */ + neckWidth: '30%', + /** + * The height of the series. If it is a number it defines + * the pixel height, if it is a percentage string it is the percentage + * of the plot area height. + * + * @type {number|string} + * @sample {highcharts} highcharts/demo/funnel3d/ Funnel3d demo + * @product highcharts + */ + height: '100%', + /** + * The height of the neck, the lower part of the funnel. A number + * defines pixel width, a percentage string defines a percentage + * of the plot area height. + * + * @type {number|string} + * @sample {highcharts} highcharts/demo/funnel3d/ Funnel3d demo + * @product highcharts + */ + neckHeight: '25%', + /** + * A reversed funnel has the widest area down. A reversed funnel with + * no neck width and neck height is a pyramid. + * + * @product highcharts + */ + reversed: false, + /** + * By deafult sides fill is set to a gradient through this option being + * set to `true`. Set to `false` to get solid color for the sides. + * + * @product highcharts + */ + gradientForSides: true, + animation: false, + edgeWidth: 0, + colorByPoint: true, + showInLegend: false, + dataLabels: { + align: 'right', + crop: false, + inside: false, + overflow: 'allow' + } +}, { + // Override default axis options with series required options for axes + bindAxes: function () { + H.Series.prototype.bindAxes.apply(this, arguments); + extend(this.xAxis.options, { + gridLineWidth: 0, + lineWidth: 0, + title: null, + tickPositions: [] + }); + extend(this.yAxis.options, { + gridLineWidth: 0, + title: null, + labels: { + enabled: false + } + }); + }, + translate3dShapes: H.noop, + translate: function () { + H.Series.prototype.translate.apply(this, arguments); + var sum = 0, series = this, chart = series.chart, options = series.options, reversed = options.reversed, ignoreHiddenPoint = options.ignoreHiddenPoint, plotWidth = chart.plotWidth, plotHeight = chart.plotHeight, cumulative = 0, // start at top + center = options.center, centerX = relativeLength(center[0], plotWidth), centerY = relativeLength(center[1], plotHeight), width = relativeLength(options.width, plotWidth), tempWidth, getWidthAt, height = relativeLength(options.height, plotHeight), neckWidth = relativeLength(options.neckWidth, plotWidth), neckHeight = relativeLength(options.neckHeight, plotHeight), neckY = (centerY - height / 2) + height - neckHeight, data = series.data, fraction, tooltipPos, + // + y1, y3, y5, + // + h, shapeArgs; + // Return the width at a specific y coordinate + series.getWidthAt = getWidthAt = function (y) { + var top = (centerY - height / 2); + return (y > neckY || height === neckHeight) ? + neckWidth : + neckWidth + (width - neckWidth) * + (1 - (y - top) / (height - neckHeight)); + }; + // Expose + series.center = [centerX, centerY, height]; + series.centerX = centerX; + /* + * Individual point coordinate naming: + * + * _________centerX,y1________ + * \ / + * \ / + * \ / + * \ / + * \ / + * ___centerX,y3___ + * + * Additional for the base of the neck: + * + * | | + * | | + * | | + * ___centerX,y5___ + */ + // get the total sum + data.forEach(function (point) { + if (!ignoreHiddenPoint || point.visible !== false) { + sum += point.y; + } + }); + data.forEach(function (point) { + // set start and end positions + y5 = null; + fraction = sum ? point.y / sum : 0; + y1 = centerY - height / 2 + cumulative * height; + y3 = y1 + fraction * height; + tempWidth = getWidthAt(y1); + h = y3 - y1; + shapeArgs = { + // for fill setter + gradientForSides: pick(point.options.gradientForSides, options.gradientForSides), + x: centerX, + y: y1, + height: h, + width: tempWidth, + z: 1, + top: { + width: tempWidth + } + }; + tempWidth = getWidthAt(y3); + shapeArgs.bottom = { + fraction: fraction, + width: tempWidth + }; + // the entire point is within the neck + if (y1 >= neckY) { + shapeArgs.isCylinder = true; + } + else if (y3 > neckY) { + // the base of the neck + y5 = y3; + tempWidth = getWidthAt(neckY); + y3 = neckY; + shapeArgs.bottom.width = tempWidth; + shapeArgs.middle = { + fraction: h ? (neckY - y1) / h : 0, + width: tempWidth + }; + } + if (reversed) { + shapeArgs.y = y1 = centerY + height / 2 - + (cumulative + fraction) * height; + if (shapeArgs.middle) { + shapeArgs.middle.fraction = 1 - + (h ? shapeArgs.middle.fraction : 0); + } + tempWidth = shapeArgs.width; + shapeArgs.width = shapeArgs.bottom.width; + shapeArgs.bottom.width = tempWidth; + } + point.shapeArgs = extend(point.shapeArgs, shapeArgs); + // for tooltips and data labels context + point.percentage = fraction * 100; + point.plotX = centerX; + if (reversed) { + point.plotY = centerY + height / 2 - + (cumulative + fraction / 2) * height; + } + else { + point.plotY = (y1 + (y5 || y3)) / 2; + } + // Placement of tooltips and data labels in 3D + tooltipPos = H.perspective([{ + x: centerX, + y: point.plotY, + z: reversed ? + -(width - getWidthAt(point.plotY)) / 2 : + -(getWidthAt(point.plotY)) / 2 + }], chart, true)[0]; + point.tooltipPos = [tooltipPos.x, tooltipPos.y]; + // base to be used when alignment options are known + point.dlBoxRaw = { + x: centerX, + width: getWidthAt(point.plotY), + y: y1, + bottom: shapeArgs.height, + fullWidth: width + }; + if (!ignoreHiddenPoint || point.visible !== false) { + cumulative += fraction; + } + }); + }, + alignDataLabel: function (point, dataLabel, options) { + var series = this, dlBoxRaw = point.dlBoxRaw, inverted = series.chart.inverted, below = point.plotY > pick(series.translatedThreshold, series.yAxis.len), inside = pick(options.inside, !!series.options.stacking), dlBox = { + x: dlBoxRaw.x, + y: dlBoxRaw.y, + height: 0 + }; + options.align = pick(options.align, !inverted || inside ? 'center' : below ? 'right' : 'left'); + options.verticalAlign = pick(options.verticalAlign, inverted || inside ? 'middle' : below ? 'top' : 'bottom'); + if (options.verticalAlign !== 'top') { + dlBox.y += dlBoxRaw.bottom / + (options.verticalAlign === 'bottom' ? 1 : 2); + } + dlBox.width = series.getWidthAt(dlBox.y); + if (series.options.reversed) { + dlBox.width = dlBoxRaw.fullWidth - dlBox.width; + } + if (inside) { + dlBox.x -= dlBox.width / 2; + } + else { + // swap for inside + if (options.align === 'left') { + options.align = 'right'; + dlBox.x -= dlBox.width * 1.5; + } + else if (options.align === 'right') { + options.align = 'left'; + dlBox.x += dlBox.width / 2; + } + else { + dlBox.x -= dlBox.width / 2; + } + } + point.dlBox = dlBox; + seriesTypes.column.prototype.alignDataLabel.apply(series, arguments); + } +}, /** @lends seriesTypes.funnel3d.prototype.pointClass.prototype */ { + shapeType: 'funnel3d', + hasNewShapeType: H + .seriesTypes.column.prototype + .pointClass.prototype + .hasNewShapeType +}); +/** + * A `funnel3d` series. If the [type](#series.funnel3d.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @sample {highcharts} highcharts/demo/funnel3d/ + * Funnel3d demo + * + * @since 7.1.0 + * @extends series,plotOptions.funnel3d + * @excluding allAreas,boostThreshold,colorAxis,compare,compareBase + * @product highcharts + * @requires highcharts-3d + * @requires modules/cylinder + * @requires modules/funnel3d + * @apioption series.funnel3d + */ +/** + * An array of data points for the series. For the `funnel3d` series + * type, points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values + * will be interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from `pointStart` + * and `pointInterval` given in the series options. If the axis has + * categories, these will be used. Example: + * + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of data + * points exceeds the series' [turboThreshold](#series.funnel3d.turboThreshold), + * this option is not available. + * + * ```js + * data: [{ + * y: 2, + * name: "Point2", + * color: "#00FF00" + * }, { + * y: 4, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|*>} + * @extends series.column.data + * @product highcharts + * @apioption series.funnel3d.data + */ +/** + * By deafult sides fill is set to a gradient through this option being + * set to `true`. Set to `false` to get solid color for the sides. + * + * @type {boolean} + * @product highcharts + * @apioption series.funnel3d.data.gradientForSides + */ +funnel3dMethods = merge(RendererProto.elements3d.cuboid, { + parts: [ + 'top', 'bottom', + 'frontUpper', 'backUpper', + 'frontLower', 'backLower', + 'rightUpper', 'rightLower' + ], + mainParts: ['top', 'bottom'], + sideGroups: [ + 'upperGroup', 'lowerGroup' + ], + sideParts: { + upperGroup: ['frontUpper', 'backUpper', 'rightUpper'], + lowerGroup: ['frontLower', 'backLower', 'rightLower'] + }, + pathType: 'funnel3d', + // override opacity and color setters to control opacity + opacitySetter: function (opacity) { + var funnel3d = this, parts = funnel3d.parts, chart = H.charts[funnel3d.renderer.chartIndex], filterId = 'group-opacity-' + opacity + '-' + chart.index; + // use default for top and bottom + funnel3d.parts = funnel3d.mainParts; + funnel3d.singleSetterForParts('opacity', opacity); + // restore + funnel3d.parts = parts; + if (!chart.renderer.filterId) { + chart.renderer.definition({ + tagName: 'filter', + id: filterId, + children: [{ + tagName: 'feComponentTransfer', + children: [{ + tagName: 'feFuncA', + type: 'table', + tableValues: '0 ' + opacity + }] + }] + }); + funnel3d.sideGroups.forEach(function (groupName) { + funnel3d[groupName].attr({ + filter: 'url(#' + filterId + ')' + }); + }); + // styled mode + if (funnel3d.renderer.styledMode) { + chart.renderer.definition({ + tagName: 'style', + textContent: '.highcharts-' + filterId + + ' {filter:url(#' + filterId + ')}' + }); + funnel3d.sideGroups.forEach(function (group) { + group.addClass('highcharts-' + filterId); + }); + } + } + return funnel3d; + }, + fillSetter: function (fill) { + // extract alpha channel to use the opacitySetter + var funnel3d = this, fillColor = color(fill), alpha = fillColor.rgba[3], partsWithColor = { + // standard color for top and bottom + top: color(fill).brighten(0.1).get(), + bottom: color(fill).brighten(-0.2).get() + }; + if (alpha < 1) { + fillColor.rgba[3] = 1; + fillColor = fillColor.get('rgb'); + // set opacity through the opacitySetter + funnel3d.attr({ + opacity: alpha + }); + } + else { + // use default for full opacity + fillColor = fill; + } + // add gradient for sides + if (!fillColor.linearGradient && + !fillColor.radialGradient && + funnel3d.gradientForSides) { + fillColor = { + linearGradient: { x1: 0, x2: 1, y1: 1, y2: 1 }, + stops: [ + [0, color(fill).brighten(-0.2).get()], + [0.5, fill], + [1, color(fill).brighten(-0.2).get()] + ] + }; + } + // gradient support + if (fillColor.linearGradient) { + // color in steps, as each gradient will generate a key + funnel3d.sideGroups.forEach(function (sideGroupName) { + var box = funnel3d[sideGroupName].gradientBox, gradient = fillColor.linearGradient, alteredGradient = merge(fillColor, { + linearGradient: { + x1: box.x + gradient.x1 * box.width, + y1: box.y + gradient.y1 * box.height, + x2: box.x + gradient.x2 * box.width, + y2: box.y + gradient.y2 * box.height + } + }); + funnel3d.sideParts[sideGroupName].forEach(function (partName) { + partsWithColor[partName] = alteredGradient; + }); + }); + } + else { + merge(true, partsWithColor, { + frontUpper: fillColor, + backUpper: fillColor, + rightUpper: fillColor, + frontLower: fillColor, + backLower: fillColor, + rightLower: fillColor + }); + if (fillColor.radialGradient) { + funnel3d.sideGroups.forEach(function (sideGroupName) { + var gradBox = funnel3d[sideGroupName].gradientBox, centerX = gradBox.x + gradBox.width / 2, centerY = gradBox.y + gradBox.height / 2, diameter = Math.min(gradBox.width, gradBox.height); + funnel3d.sideParts[sideGroupName].forEach(function (partName) { + funnel3d[partName].setRadialReference([ + centerX, centerY, diameter + ]); + }); + }); + } + } + funnel3d.singleSetterForParts('fill', null, partsWithColor); + // fill for animation getter (#6776) + funnel3d.color = funnel3d.fill = fill; + // change gradientUnits to userSpaceOnUse for linearGradient + if (fillColor.linearGradient) { + [funnel3d.frontLower, funnel3d.frontUpper].forEach(function (part) { + var elem = part.element, grad = elem && funnel3d.renderer.gradients[elem.gradient]; + if (grad && grad.attr('gradientUnits') !== 'userSpaceOnUse') { + grad.attr({ + gradientUnits: 'userSpaceOnUse' + }); + } + }); + } + return funnel3d; + }, + adjustForGradient: function () { + var funnel3d = this, bbox; + funnel3d.sideGroups.forEach(function (sideGroupName) { + // use common extremes for groups for matching gradients + var topLeftEdge = { + x: Number.MAX_VALUE, + y: Number.MAX_VALUE + }, bottomRightEdge = { + x: -Number.MAX_VALUE, + y: -Number.MAX_VALUE + }; + // get extremes + funnel3d.sideParts[sideGroupName].forEach(function (partName) { + var part = funnel3d[partName]; + bbox = part.getBBox(true); + topLeftEdge = { + x: Math.min(topLeftEdge.x, bbox.x), + y: Math.min(topLeftEdge.y, bbox.y) + }; + bottomRightEdge = { + x: Math.max(bottomRightEdge.x, bbox.x + bbox.width), + y: Math.max(bottomRightEdge.y, bbox.y + bbox.height) + }; + }); + // store for color fillSetter + funnel3d[sideGroupName].gradientBox = { + x: topLeftEdge.x, + width: bottomRightEdge.x - topLeftEdge.x, + y: topLeftEdge.y, + height: bottomRightEdge.y - topLeftEdge.y + }; + }); + }, + zIndexSetter: function () { + // this.added won't work, because zIndex is set after the prop is set, + // but before the graphic is really added + if (this.finishedOnAdd) { + this.adjustForGradient(); + } + // run default + return this.renderer.Element.prototype.zIndexSetter.apply(this, arguments); + }, + onAdd: function () { + this.adjustForGradient(); + this.finishedOnAdd = true; + } +}); +RendererProto.elements3d.funnel3d = funnel3dMethods; +RendererProto.funnel3d = function (shapeArgs) { + var renderer = this, funnel3d = renderer.element3d('funnel3d', shapeArgs), styledMode = renderer.styledMode, + // hide stroke for Firefox + strokeAttrs = { + 'stroke-width': 1, + stroke: 'none' + }; + // create groups for sides for oppacity setter + funnel3d.upperGroup = renderer.g('funnel3d-upper-group').attr({ + zIndex: funnel3d.frontUpper.zIndex + }).add(funnel3d); + [ + funnel3d.frontUpper, + funnel3d.backUpper, + funnel3d.rightUpper + ].forEach(function (upperElem) { + if (!styledMode) { + upperElem.attr(strokeAttrs); + } + upperElem.add(funnel3d.upperGroup); + }); + funnel3d.lowerGroup = renderer.g('funnel3d-lower-group').attr({ + zIndex: funnel3d.frontLower.zIndex + }).add(funnel3d); + [ + funnel3d.frontLower, + funnel3d.backLower, + funnel3d.rightLower + ].forEach(function (lowerElem) { + if (!styledMode) { + lowerElem.attr(strokeAttrs); + } + lowerElem.add(funnel3d.lowerGroup); + }); + funnel3d.gradientForSides = shapeArgs.gradientForSides; + return funnel3d; +}; +// eslint-disable-next-line valid-jsdoc +/** + * Generates paths and zIndexes. + * @private + */ +RendererProto.funnel3dPath = function (shapeArgs) { + // Check getCylinderEnd for better error message if + // the cylinder module is missing + if (!this.getCylinderEnd) { + error('A required Highcharts module is missing: cylinder.js', true, charts[this.chartIndex]); + } + var renderer = this, chart = charts[renderer.chartIndex], + // adjust angles for visible edges + // based on alpha, selected through visual tests + alphaCorrection = shapeArgs.alphaCorrection = 90 - + Math.abs((chart.options.chart.options3d.alpha % 180) - 90), + // set zIndexes of parts based on cubiod logic, for consistency + cuboidData = cuboidPath.call(renderer, merge(shapeArgs, { + depth: shapeArgs.width, + width: (shapeArgs.width + shapeArgs.bottom.width) / 2 + })), isTopFirst = cuboidData.isTop, isFrontFirst = !cuboidData.isFront, hasMiddle = !!shapeArgs.middle, + // + top = renderer.getCylinderEnd(chart, merge(shapeArgs, { + x: shapeArgs.x - shapeArgs.width / 2, + z: shapeArgs.z - shapeArgs.width / 2, + alphaCorrection: alphaCorrection + })), bottomWidth = shapeArgs.bottom.width, bottomArgs = merge(shapeArgs, { + width: bottomWidth, + x: shapeArgs.x - bottomWidth / 2, + z: shapeArgs.z - bottomWidth / 2, + alphaCorrection: alphaCorrection + }), bottom = renderer.getCylinderEnd(chart, bottomArgs, true), + // + middleWidth = bottomWidth, middleTopArgs = bottomArgs, middleTop = bottom, middleBottom = bottom, ret, + // masking for cylinders or a missing part of a side shape + useAlphaCorrection; + if (hasMiddle) { + middleWidth = shapeArgs.middle.width; + middleTopArgs = merge(shapeArgs, { + y: shapeArgs.y + shapeArgs.middle.fraction * shapeArgs.height, + width: middleWidth, + x: shapeArgs.x - middleWidth / 2, + z: shapeArgs.z - middleWidth / 2 + }); + middleTop = renderer.getCylinderEnd(chart, middleTopArgs, false); + middleBottom = renderer.getCylinderEnd(chart, middleTopArgs, false); + } + ret = { + top: top, + bottom: bottom, + frontUpper: renderer.getCylinderFront(top, middleTop), + zIndexes: { + group: cuboidData.zIndexes.group, + top: isTopFirst !== 0 ? 0 : 3, + bottom: isTopFirst !== 1 ? 0 : 3, + frontUpper: isFrontFirst ? 2 : 1, + backUpper: isFrontFirst ? 1 : 2, + rightUpper: isFrontFirst ? 2 : 1 + } + }; + ret.backUpper = renderer.getCylinderBack(top, middleTop); + useAlphaCorrection = (Math.min(middleWidth, shapeArgs.width) / + Math.max(middleWidth, shapeArgs.width)) !== 1; + ret.rightUpper = renderer.getCylinderFront(renderer.getCylinderEnd(chart, merge(shapeArgs, { + x: shapeArgs.x - shapeArgs.width / 2, + z: shapeArgs.z - shapeArgs.width / 2, + alphaCorrection: useAlphaCorrection ? -alphaCorrection : 0 + }), false), renderer.getCylinderEnd(chart, merge(middleTopArgs, { + alphaCorrection: useAlphaCorrection ? -alphaCorrection : 0 + }), !hasMiddle)); + if (hasMiddle) { + useAlphaCorrection = (Math.min(middleWidth, bottomWidth) / + Math.max(middleWidth, bottomWidth)) !== 1; + merge(true, ret, { + frontLower: renderer.getCylinderFront(middleBottom, bottom), + backLower: renderer.getCylinderBack(middleBottom, bottom), + rightLower: renderer.getCylinderFront(renderer.getCylinderEnd(chart, merge(bottomArgs, { + alphaCorrection: useAlphaCorrection ? + -alphaCorrection : 0 + }), true), renderer.getCylinderEnd(chart, merge(middleTopArgs, { + alphaCorrection: useAlphaCorrection ? + -alphaCorrection : 0 + }), false)), + zIndexes: { + frontLower: isFrontFirst ? 2 : 1, + backLower: isFrontFirst ? 1 : 2, + rightLower: isFrontFirst ? 1 : 2 + } + }); + } + return ret; +}; diff --git a/librerias/gantt/code/es-modules/modules/histogram.src.js b/librerias/gantt/code/es-modules/modules/histogram.src.js new file mode 100644 index 0000000..3e3b742 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/histogram.src.js @@ -0,0 +1,190 @@ +/* * + * + * Copyright (c) 2010-2017 Highsoft AS + * Author: Sebastian Domas + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import U from '../parts/Utilities.js'; +var arrayMax = U.arrayMax, arrayMin = U.arrayMin, correctFloat = U.correctFloat, isNumber = U.isNumber, merge = U.merge, objectEach = U.objectEach, seriesType = U.seriesType; +import derivedSeriesMixin from '../mixins/derived-series.js'; +/* ************************************************************************** * + * HISTOGRAM + * ************************************************************************** */ +/** + * A dictionary with formulas for calculating number of bins based on the + * base series + **/ +var binsNumberFormulas = { + 'square-root': function (baseSeries) { + return Math.ceil(Math.sqrt(baseSeries.options.data.length)); + }, + 'sturges': function (baseSeries) { + return Math.ceil(Math.log(baseSeries.options.data.length) * Math.LOG2E); + }, + 'rice': function (baseSeries) { + return Math.ceil(2 * Math.pow(baseSeries.options.data.length, 1 / 3)); + } +}; +/** + * Returns a function for mapping number to the closed (right opened) bins + * @private + * @param {Array} bins - Width of the bins + * @return {Function} + **/ +function fitToBinLeftClosed(bins) { + return function (y) { + var i = 1; + while (bins[i] <= y) { + i++; + } + return bins[--i]; + }; +} +/** + * Histogram class + * @private + * @class + * @name Highcharts.seriesTypes.histogram + * @augments Highcharts.Series + */ +seriesType('histogram', 'column', +/** + * A histogram is a column series which represents the distribution of the + * data set in the base series. Histogram splits data into bins and shows + * their frequencies. + * + * @sample {highcharts} highcharts/demo/histogram/ + * Histogram + * + * @extends plotOptions.column + * @excluding boostThreshold, dragDrop, pointInterval, pointIntervalUnit, + * stacking + * @product highcharts + * @since 6.0.0 + * @requires modules/histogram + * @optionparent plotOptions.histogram + */ +{ + /** + * A preferable number of bins. It is a suggestion, so a histogram may + * have a different number of bins. By default it is set to the square + * root of the base series' data length. Available options are: + * `square-root`, `sturges`, `rice`. You can also define a function + * which takes a `baseSeries` as a parameter and should return a + * positive integer. + * + * @type {"square-root"|"sturges"|"rice"|number|function} + */ + binsNumber: 'square-root', + /** + * Width of each bin. By default the bin's width is calculated as + * `(max - min) / number of bins`. This option takes precedence over + * [binsNumber](#plotOptions.histogram.binsNumber). + * + * @type {number} + */ + binWidth: void 0, + pointPadding: 0, + groupPadding: 0, + grouping: false, + pointPlacement: 'between', + tooltip: { + headerFormat: '', + pointFormat: ('{point.x} - {point.x2}' + + '
' + + '\u25CF' + + ' {series.name} {point.y}
') + } +}, merge(derivedSeriesMixin, { + setDerivedData: function () { + var yData = this.baseSeries.yData; + if (!yData.length) { + return; + } + var data = this.derivedData(yData, this.binsNumber(), this.options.binWidth); + this.setData(data, false); + }, + derivedData: function (baseData, binsNumber, binWidth) { + var series = this, max = arrayMax(baseData), + // Float correction needed, because first frequency value is not + // corrected when generating frequencies (within for loop). + min = correctFloat(arrayMin(baseData)), frequencies = [], bins = {}, data = [], x, fitToBin; + binWidth = series.binWidth = series.options.pointRange = (correctFloat(isNumber(binWidth) ? + (binWidth || 1) : + (max - min) / binsNumber)); + // If binWidth is 0 then max and min are equaled, + // increment the x with some positive value to quit the loop + for (x = min; + // This condition is needed because of the margin of error while + // operating on decimal numbers. Without that, additional bin + // was sometimes noticeable on the graph, because of too small + // precision of float correction. + x < max && + (series.userOptions.binWidth || + correctFloat(max - x) >= binWidth || + // #13069 - Every add and subtract operation should + // be corrected, due to general problems with + // operations on float numbers in JS. + correctFloat(correctFloat(min + (frequencies.length * binWidth)) - + x) <= 0); x = correctFloat(x + binWidth)) { + frequencies.push(x); + bins[x] = 0; + } + if (bins[min] !== 0) { + frequencies.push(correctFloat(min)); + bins[correctFloat(min)] = 0; + } + fitToBin = fitToBinLeftClosed(frequencies.map(function (elem) { + return parseFloat(elem); + })); + baseData.forEach(function (y) { + var x = correctFloat(fitToBin(y)); + bins[x]++; + }); + objectEach(bins, function (frequency, x) { + data.push({ + x: Number(x), + y: frequency, + x2: correctFloat(Number(x) + binWidth) + }); + }); + data.sort(function (a, b) { + return a.x - b.x; + }); + return data; + }, + binsNumber: function () { + var binsNumberOption = this.options.binsNumber; + var binsNumber = binsNumberFormulas[binsNumberOption] || + // #7457 + (typeof binsNumberOption === 'function' && binsNumberOption); + return Math.ceil((binsNumber && binsNumber(this.baseSeries)) || + (isNumber(binsNumberOption) ? + binsNumberOption : + binsNumberFormulas['square-root'](this.baseSeries))); + } +})); +/** + * A `histogram` series. If the [type](#series.histogram.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.histogram + * @excluding data, dataParser, dataURL + * @product highcharts + * @since 6.0.0 + * @requires modules/histogram + * @apioption series.histogram + */ +/** + * An integer identifying the index to use for the base series, or a string + * representing the id of the series. + * + * @type {number|string} + * @apioption series.histogram.baseSeries + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/modules/item-series.src.js b/librerias/gantt/code/es-modules/modules/item-series.src.js new file mode 100644 index 0000000..cd16b08 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/item-series.src.js @@ -0,0 +1,448 @@ +/* * + * + * (c) 2020 Torstein Honsi + * + * Item series type for Highcharts + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var defined = U.defined, extend = U.extend, fireEvent = U.fireEvent, isNumber = U.isNumber, merge = U.merge, objectEach = U.objectEach, pick = U.pick, seriesType = U.seriesType; +import '../parts/Series.js'; +var piePoint = H.seriesTypes.pie.prototype.pointClass.prototype; +/** + * The item series type. + * + * @requires module:modules/item-series + * + * @private + * @class + * @name Highcharts.seriesTypes.item + * + * @augments Highcharts.seriesTypes.pie + */ +seriesType('item', +// Inherits pie as the most tested non-cartesian series with individual +// point legend, tooltips etc. Only downside is we need to re-enable +// marker options. +'pie', +/** + * An item chart is an infographic chart where a number of items are laid + * out in either a rectangular or circular pattern. It can be used to + * visualize counts within a group, or for the circular pattern, typically + * a parliament. + * + * The circular layout has much in common with a pie chart. Many of the item + * series options, like `center`, `size` and data label positioning, are + * inherited from the pie series and don't apply for rectangular layouts. + * + * @sample highcharts/demo/parliament-chart + * Parliament chart (circular item chart) + * @sample highcharts/series-item/rectangular + * Rectangular item chart + * @sample highcharts/series-item/symbols + * Infographic with symbols + * + * @extends plotOptions.pie + * @since 7.1.0 + * @product highcharts + * @excluding borderColor, borderWidth, depth, linecap, shadow, + * slicedOffset + * @requires modules/item-series + * @optionparent plotOptions.item + */ +{ + /** + * In circular view, the end angle of the item layout, in degrees where + * 0 is up. + * + * @sample highcharts/demo/parliament-chart + * Parliament chart + * @type {undefined|number} + */ + endAngle: void 0, + /** + * In circular view, the size of the inner diameter of the circle. Can + * be a percentage or pixel value. Percentages are relative to the outer + * perimeter. Pixel values are given as integers. + * + * If the `rows` option is set, it overrides the `innerSize` setting. + * + * @sample highcharts/demo/parliament-chart + * Parliament chart + * @type {string|number} + */ + innerSize: '40%', + /** + * The padding between the items, given in relative size where the size + * of the item is 1. + * @type {number} + */ + itemPadding: 0.1, + /** + * The layout of the items in rectangular view. Can be either + * `horizontal` or `vertical`. + * @sample highcharts/series-item/symbols + * Horizontal layout + * @type {string} + */ + layout: 'vertical', + /** + * @extends plotOptions.series.marker + */ + marker: merge(H.defaultOptions.plotOptions.line.marker, { + radius: null + }), + /** + * The number of rows to display in the rectangular or circular view. If + * the `innerSize` is set, it will be overridden by the `rows` setting. + * + * @sample highcharts/series-item/rows-columns + * Fixed row count + * @type {number} + */ + rows: void 0, + crisp: false, + showInLegend: true, + /** + * In circular view, the start angle of the item layout, in degrees + * where 0 is up. + * + * @sample highcharts/demo/parliament-chart + * Parliament chart + * @type {undefined|number} + */ + startAngle: void 0 +}, +// Prototype members +{ + markerAttribs: void 0, + translate: function () { + if (!this.slots) { + this.slots = []; + } + if (isNumber(this.options.startAngle) && + isNumber(this.options.endAngle)) { + H.seriesTypes.pie.prototype.translate.call(this); + this.slots = this.getSlots(); + } + else { + this.generatePoints(); + fireEvent(this, 'afterTranslate'); + } + }, + // Get the semi-circular slots + getSlots: function () { + var center = this.center, diameter = center[2], innerSize = center[3], row, slots = this.slots, x, y, rowRadius, rowLength, colCount, increment, angle, col, itemSize = 0, rowCount, fullAngle = (this.endAngleRad - this.startAngleRad), itemCount = Number.MAX_VALUE, finalItemCount, rows, testRows, rowsOption = this.options.rows, + // How many rows (arcs) should be used + rowFraction = (diameter - innerSize) / diameter; + // Increase the itemSize until we find the best fit + while (itemCount > this.total) { + finalItemCount = itemCount; + // Reset + slots.length = 0; + itemCount = 0; + // Now rows is the last successful run + rows = testRows; + testRows = []; + itemSize++; + // Total number of rows (arcs) from the center to the + // perimeter + rowCount = diameter / itemSize / 2; + if (rowsOption) { + innerSize = ((rowCount - rowsOption) / rowCount) * diameter; + if (innerSize >= 0) { + rowCount = rowsOption; + // If innerSize is negative, we are trying to set too + // many rows in the rows option, so fall back to + // treating it as innerSize 0 + } + else { + innerSize = 0; + rowFraction = 1; + } + } + else { + rowCount = Math.floor(rowCount * rowFraction); + } + for (row = rowCount; row > 0; row--) { + rowRadius = (innerSize + (row / rowCount) * + (diameter - innerSize - itemSize)) / 2; + rowLength = fullAngle * rowRadius; + colCount = Math.ceil(rowLength / itemSize); + testRows.push({ + rowRadius: rowRadius, + rowLength: rowLength, + colCount: colCount + }); + itemCount += colCount + 1; + } + } + if (!rows) { + return; + } + // We now have more slots than we have total items. Loop over + // the rows and remove the last slot until the count is correct. + // For each iteration we sort the last slot by the angle, and + // remove those with the highest angles. + var overshoot = finalItemCount - this.total; + /** + * @private + * @param {Highcharts.ItemRowContainerObject} item + * Wrapped object with angle and row + * @return {void} + */ + function cutOffRow(item) { + if (overshoot > 0) { + item.row.colCount--; + overshoot--; + } + } + while (overshoot > 0) { + rows + // Return a simplified representation of the angle of + // the last slot within each row. + .map(function (row) { + return { + angle: row.colCount / row.rowLength, + row: row + }; + }) + // Sort by the angles... + .sort(function (a, b) { + return b.angle - a.angle; + }) + // ...so that we can ignore the items with the lowest + // angles... + .slice(0, Math.min(overshoot, Math.ceil(rows.length / 2))) + // ...and remove the ones with the highest angles + .forEach(cutOffRow); + } + rows.forEach(function (row) { + var rowRadius = row.rowRadius, colCount = row.colCount; + increment = colCount ? fullAngle / colCount : 0; + for (col = 0; col <= colCount; col += 1) { + angle = this.startAngleRad + col * increment; + x = center[0] + Math.cos(angle) * rowRadius; + y = center[1] + Math.sin(angle) * rowRadius; + slots.push({ x: x, y: y, angle: angle }); + } + }, this); + // Sort by angle + slots.sort(function (a, b) { + return a.angle - b.angle; + }); + this.itemSize = itemSize; + return slots; + }, + getRows: function () { + var rows = this.options.rows, cols, ratio; + // Get the row count that gives the most square cells + if (!rows) { + ratio = this.chart.plotWidth / this.chart.plotHeight; + rows = Math.sqrt(this.total); + if (ratio > 1) { + rows = Math.ceil(rows); + while (rows > 0) { + cols = this.total / rows; + if (cols / rows > ratio) { + break; + } + rows--; + } + } + else { + rows = Math.floor(rows); + while (rows < this.total) { + cols = this.total / rows; + if (cols / rows < ratio) { + break; + } + rows++; + } + } + } + return rows; + }, + drawPoints: function () { + var series = this, options = this.options, renderer = series.chart.renderer, seriesMarkerOptions = options.marker, borderWidth = this.borderWidth, crisp = borderWidth % 2 ? 0.5 : 1, i = 0, rows = this.getRows(), cols = Math.ceil(this.total / rows), cellWidth = this.chart.plotWidth / cols, cellHeight = this.chart.plotHeight / rows, itemSize = this.itemSize || Math.min(cellWidth, cellHeight); + /* + this.slots.forEach(slot => { + this.chart.renderer.circle(slot.x, slot.y, 6) + .attr({ + fill: 'silver' + }) + .add(this.group); + }); + //*/ + this.points.forEach(function (point) { + var attr, graphics, pointAttr, pointMarkerOptions = point.marker || {}, symbol = (pointMarkerOptions.symbol || + seriesMarkerOptions.symbol), r = pick(pointMarkerOptions.radius, seriesMarkerOptions.radius), size = defined(r) ? 2 * r : itemSize, padding = size * options.itemPadding, x, y, width, height; + point.graphics = graphics = point.graphics || {}; + if (!series.chart.styledMode) { + pointAttr = series.pointAttribs(point, point.selected && 'select'); + } + if (!point.isNull && point.visible) { + if (!point.graphic) { + point.graphic = renderer.g('point') + .add(series.group); + } + for (var val = 0; val < point.y; val++) { + // Semi-circle + if (series.center && series.slots) { + // Fill up the slots from left to right + var slot = series.slots.shift(); + x = slot.x - itemSize / 2; + y = slot.y - itemSize / 2; + } + else if (options.layout === 'horizontal') { + x = cellWidth * (i % cols); + y = cellHeight * Math.floor(i / cols); + } + else { + x = cellWidth * Math.floor(i / rows); + y = cellHeight * (i % rows); + } + x += padding; + y += padding; + width = Math.round(size - 2 * padding); + height = width; + if (series.options.crisp) { + x = Math.round(x) - crisp; + y = Math.round(y) + crisp; + } + attr = { + x: x, + y: y, + width: width, + height: height + }; + if (typeof r !== 'undefined') { + attr.r = r; + } + if (graphics[val]) { + graphics[val].animate(attr); + } + else { + graphics[val] = renderer + .symbol(symbol, null, null, null, null, { + backgroundSize: 'within' + }) + .attr(extend(attr, pointAttr)) + .add(point.graphic); + } + graphics[val].isActive = true; + i++; + } + } + objectEach(graphics, function (graphic, key) { + if (!graphic.isActive) { + graphic.destroy(); + delete graphics[key]; + } + else { + graphic.isActive = false; + } + }); + }); + }, + drawDataLabels: function () { + if (this.center && this.slots) { + H.seriesTypes.pie.prototype.drawDataLabels.call(this); + // else, it's just a dot chart with no natural place to put the + // data labels + } + else { + this.points.forEach(function (point) { + point.destroyElements({ dataLabel: 1 }); + }); + } + }, + // Fade in the whole chart + animate: function (init) { + if (init) { + this.group.attr({ + opacity: 0 + }); + } + else { + this.group.animate({ + opacity: 1 + }, this.options.animation); + } + } +}, +// Point class +{ + connectorShapes: piePoint.connectorShapes, + getConnectorPath: piePoint.getConnectorPath, + setVisible: piePoint.setVisible, + getTranslate: piePoint.getTranslate +}); +/** + * An `item` series. If the [type](#series.item.type) option is not specified, + * it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.item + * @excluding dataParser, dataURL, stack, xAxis, yAxis, dataSorting + * @product highcharts + * @requires modules/item-series + * @apioption series.item + */ +/** + * An array of data points for the series. For the `item` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.item.turboThreshold), + * this option is not available. + * ```js + * data: [{ + * y: 1, + * name: "Point2", + * color: "#00FF00" + * }, { + * y: 7, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.pie.data + * @excludes sliced + * @product highcharts + * @apioption series.item.data + */ +/** + * The sequential index of the data point in the legend. + * + * @type {number} + * @product highcharts + * @apioption series.pie.data.legendIndex + */ +''; // adds the doclets above to the transpiled file diff --git a/librerias/gantt/code/es-modules/modules/lollipop.src.js b/librerias/gantt/code/es-modules/modules/lollipop.src.js new file mode 100644 index 0000000..60107df --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/lollipop.src.js @@ -0,0 +1,140 @@ +/* * + * + * (c) 2010-2020 Sebastian Bochan, Rafal Sebestjanski + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var seriesType = U.seriesType; +var areaProto = H.seriesTypes.area.prototype, colProto = H.seriesTypes.column.prototype; +/** + * The lollipop series is a carteseian series with a line anchored from + * the x axis and a dot at the end to mark the value. + * Requires `highcharts-more.js`, `modules/dumbbell.js` and + * `modules/lollipop.js`. + * + * @sample {highcharts} highcharts/demo/lollipop/ + * Lollipop chart + * @sample {highcharts} highcharts/series-dumbbell/styled-mode-dumbbell/ + * Styled mode + * + * @extends plotOptions.dumbbell + * @product highcharts highstock + * @excluding fillColor, fillOpacity, lineWidth, stack, stacking, lowColor, + * stickyTracking, trackByArea + * @since 8.0.0 + * @optionparent plotOptions.lollipop + */ +seriesType('lollipop', 'dumbbell', { + /** @ignore-option */ + lowColor: void 0, + /** @ignore-option */ + threshold: 0, + /** @ignore-option */ + connectorWidth: 1, + /** @ignore-option */ + groupPadding: 0.2, + /** @ignore-option */ + pointPadding: 0.1, + /** @ignore-option */ + states: { + hover: { + /** @ignore-option */ + lineWidthPlus: 0, + /** @ignore-option */ + connectorWidthPlus: 1, + /** @ignore-option */ + halo: false + } + }, + tooltip: { + pointFormat: ' {series.name}: {point.low}
' + } +}, { + translatePoint: areaProto.translate, + drawPoint: areaProto.drawPoints, + drawDataLabels: colProto.drawDataLabels, + setShapeArgs: colProto.translate +}, { + pointSetState: areaProto.pointClass.prototype.setState, + setState: H.seriesTypes.dumbbell.prototype.pointClass.prototype.setState +}); +/** + * The `lollipop` series. If the [type](#series.lollipop.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.lollipop + * @product highcharts highstock + * @requires highcharts-more + * @requires modules/dumbbell + * @requires modules/lollipop + * @apioption series.lollipop + */ +/** + * An array of data points for the series. For the `lollipop` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 6], + * [1, 2], + * [2, 6] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.lollipop.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 9, + * name: "Point2", + * color: "#00FF00", + * connectorWidth: 3, + * connectorColor: "#FF00FF" + * }, { + * x: 1, + * y: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.dumbbell.data + * @excluding lowColor + * @product highcharts highstock + * @apioption series.lollipop.data + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/modules/marker-clusters.src.js b/librerias/gantt/code/es-modules/modules/marker-clusters.src.js new file mode 100644 index 0000000..ab29b15 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/marker-clusters.src.js @@ -0,0 +1,1522 @@ +/* * + * + * Marker clusters module. + * + * (c) 2010-2020 Torstein Honsi + * + * Author: Wojciech Chmiel + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +var __read = (this && this.__read) || function (o, n) { + var m = typeof Symbol === "function" && o[Symbol.iterator]; + if (!m) return o; + var i = m.call(o), r, ar = [], e; + try { + while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); + } + catch (error) { e = { error: error }; } + finally { + try { + if (r && !r.done && (m = i["return"])) m.call(i); + } + finally { if (e) throw e.error; } + } + return ar; +}; +import H from '../parts/Globals.js'; +/** + * Function callback when a cluster is clicked. + * + * @callback Highcharts.MarkerClusterDrillCallbackFunction + * + * @param {Highcharts.Point} this + * The point where the event occured. + * + * @param {Highcharts.PointClickEventObject} event + * Event arguments. + */ +''; // detach doclets from following code +import Point from '../parts/Point.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, animObject = U.animObject, defined = U.defined, error = U.error, isArray = U.isArray, isFunction = U.isFunction, isObject = U.isObject, isNumber = U.isNumber, merge = U.merge, objectEach = U.objectEach, relativeLength = U.relativeLength, syncTimeout = U.syncTimeout; +/* eslint-disable no-invalid-this */ +import '../parts/Axis.js'; +import '../parts/Series.js'; +import '../parts/SvgRenderer.js'; +var Series = H.Series, Scatter = H.seriesTypes.scatter, SvgRenderer = H.SVGRenderer, baseGeneratePoints = Series.prototype.generatePoints, stateIdCounter = 0, +// Points that ids are included in the oldPointsStateId array +// are hidden before animation. Other ones are destroyed. +oldPointsStateId = []; +/** + * Options for marker clusters, the concept of sampling the data + * values into larger blocks in order to ease readability and + * increase performance of the JavaScript charts. + * + * Note: marker clusters module is not working with `boost` + * and `draggable-points` modules. + * + * The marker clusters feature requires the marker-clusters.js + * file to be loaded, found in the modules directory of the download + * package, or online at [code.highcharts.com/modules/marker-clusters.js + * ](code.highcharts.com/modules/marker-clusters.js). + * + * @sample maps/marker-clusters/europe + * Maps marker clusters + * @sample highcharts/marker-clusters/basic + * Scatter marker clusters + * @sample maps/marker-clusters/optimized-kmeans + * Marker clusters with colorAxis + * + * @product highcharts highmaps + * @since 8.0.0 + * @optionparent plotOptions.scatter.cluster + * + * @private + */ +var clusterDefaultOptions = { + /** + * Whether to enable the marker-clusters module. + * + * @sample maps/marker-clusters/basic + * Maps marker clusters + * @sample highcharts/marker-clusters/basic + * Scatter marker clusters + */ + enabled: false, + /** + * When set to `false` prevent cluster overlapping - this option + * works only when `layoutAlgorithm.type = "grid"`. + * + * @sample highcharts/marker-clusters/grid + * Prevent overlapping + */ + allowOverlap: true, + /** + * Options for the cluster marker animation. + * @type {boolean|Highcharts.AnimationOptionsObject} + * @default { "duration": 500 } + */ + animation: { + /** @ignore-option */ + duration: 500 + }, + /** + * Zoom the plot area to the cluster points range when a cluster is clicked. + */ + drillToCluster: true, + /** + * The minimum amount of points to be combined into a cluster. + * This value has to be greater or equal to 2. + * + * @sample highcharts/marker-clusters/basic + * At least three points in the cluster + */ + minimumClusterSize: 2, + /** + * Options for layout algorithm. Inside there + * are options to change the type of the algorithm, gridSize, + * distance or iterations. + */ + layoutAlgorithm: { + /** + * Type of the algorithm used to combine points into a cluster. + * There are three available algorithms: + * + * 1) `grid` - grid-based clustering technique. Points are assigned + * to squares of set size depending on their position on the plot + * area. Points inside the grid square are combined into a cluster. + * The grid size can be controlled by `gridSize` property + * (grid size changes at certain zoom levels). + * + * 2) `kmeans` - based on K-Means clustering technique. In the + * first step, points are divided using the grid method (distance + * property is a grid size) to find the initial amount of clusters. + * Next, each point is classified by computing the distance between + * each cluster center and that point. When the closest cluster + * distance is lower than distance property set by a user the point + * is added to this cluster otherwise is classified as `noise`. The + * algorithm is repeated until each cluster center not change its + * previous position more than one pixel. This technique is more + * accurate but also more time consuming than the `grid` algorithm, + * especially for big datasets. + * + * 3) `optimizedKmeans` - based on K-Means clustering technique. This + * algorithm uses k-means algorithm only on the chart initialization + * or when chart extremes have greater range than on initialization. + * When a chart is redrawn the algorithm checks only clustered points + * distance from the cluster center and rebuild it when the point is + * spaced enough to be outside the cluster. It provides performance + * improvement and more stable clusters position yet can be used rather + * on small and sparse datasets. + * + * By default, the algorithm depends on visible quantity of points + * and `kmeansThreshold`. When there are more visible points than the + * `kmeansThreshold` the `grid` algorithm is used, otherwise `kmeans`. + * + * The custom clustering algorithm can be added by assigning a callback + * function as the type property. This function takes an array of + * `processedXData`, `processedYData`, `processedXData` indexes and + * `layoutAlgorithm` options as arguments and should return an object + * with grouped data. + * + * The algorithm should return an object like that: + *
{
+         *  clusterId1: [{
+         *      x: 573,
+         *      y: 285,
+         *      index: 1 // point index in the data array
+         *  }, {
+         *      x: 521,
+         *      y: 197,
+         *      index: 2
+         *  }],
+         *  clusterId2: [{
+         *      ...
+         *  }]
+         *  ...
+         * }
+ * + * `clusterId` (example above - unique id of a cluster or noise) + * is an array of points belonging to a cluster. If the + * array has only one point or fewer points than set in + * `cluster.minimumClusterSize` it won't be combined into a cluster. + * + * @sample maps/marker-clusters/optimized-kmeans + * Optimized K-Means algorithm + * @sample highcharts/marker-clusters/kmeans + * K-Means algorithm + * @sample highcharts/marker-clusters/grid + * Grid algorithm + * @sample maps/marker-clusters/custom-alg + * Custom algorithm + * + * @type {string|Function} + * @see [cluster.minimumClusterSize](#plotOptions.scatter.marker.cluster.minimumClusterSize) + * @apioption plotOptions.scatter.cluster.layoutAlgorithm.type + */ + /** + * When `type` is set to the `grid`, + * `gridSize` is a size of a grid square element either as a number + * defining pixels, or a percentage defining a percentage + * of the plot area width. + * + * @type {number|string} + */ + gridSize: 50, + /** + * When `type` is set to `kmeans`, + * `iterations` are the number of iterations that this algorithm will be + * repeated to find clusters positions. + * + * @type {number} + * @apioption plotOptions.scatter.cluster.layoutAlgorithm.iterations + */ + /** + * When `type` is set to `kmeans`, + * `distance` is a maximum distance between point and cluster center + * so that this point will be inside the cluster. The distance + * is either a number defining pixels or a percentage + * defining a percentage of the plot area width. + * + * @type {number|string} + */ + distance: 40, + /** + * When `type` is set to `undefined` and there are more visible points + * than the kmeansThreshold the `grid` algorithm is used to find + * clusters, otherwise `kmeans`. It ensures good performance on + * large datasets and better clusters arrangement after the zoom. + */ + kmeansThreshold: 100 + }, + /** + * Options for the cluster marker. + * @extends plotOptions.series.marker + * @excluding enabledThreshold, states + * @type {Highcharts.PointMarkerOptionsObject} + */ + marker: { + /** @internal */ + symbol: 'cluster', + /** @internal */ + radius: 15, + /** @internal */ + lineWidth: 0, + /** @internal */ + lineColor: '#ffffff' + }, + /** + * Fires when the cluster point is clicked and `drillToCluster` is enabled. + * One parameter, `event`, is passed to the function. The default action + * is to zoom to the cluster points range. This can be prevented + * by calling `event.preventDefault()`. + * + * @type {Highcharts.MarkerClusterDrillCallbackFunction} + * @product highcharts highmaps + * @see [cluster.drillToCluster](#plotOptions.scatter.marker.cluster.drillToCluster) + * @apioption plotOptions.scatter.cluster.events.drillToCluster + */ + /** + * An array defining zones within marker clusters. + * + * In styled mode, the color zones are styled with the + * `.highcharts-cluster-zone-{n}` class, or custom + * classed from the `className` + * option. + * + * @sample highcharts/marker-clusters/basic + * Marker clusters zones + * @sample maps/marker-clusters/custom-alg + * Zones on maps + * + * @type {Array<*>} + * @product highcharts highmaps + * @apioption plotOptions.scatter.cluster.zones + */ + /** + * Styled mode only. A custom class name for the zone. + * + * @sample highcharts/css/color-zones/ + * Zones styled by class name + * + * @type {string} + * @apioption plotOptions.scatter.cluster.zones.className + */ + /** + * Settings for the cluster marker belonging to the zone. + * + * @see [cluster.marker](#plotOptions.scatter.cluster.marker) + * @extends plotOptions.scatter.cluster.marker + * @product highcharts highmaps + * @apioption plotOptions.scatter.cluster.zones.marker + */ + /** + * The value where the zone starts. + * + * @type {number} + * @product highcharts highmaps + * @apioption plotOptions.scatter.cluster.zones.from + */ + /** + * The value where the zone ends. + * + * @type {number} + * @product highcharts highmaps + * @apioption plotOptions.scatter.cluster.zones.to + */ + /** + * The fill color of the cluster marker in hover state. When + * `undefined`, the series' or point's fillColor for normal + * state is used. + * + * @type {Highcharts.ColorType} + * @apioption plotOptions.scatter.cluster.states.hover.fillColor + */ + /** + * Options for the cluster data labels. + * @type {Highcharts.DataLabelsOptions} + */ + dataLabels: { + /** @internal */ + enabled: true, + /** @internal */ + format: '{point.clusterPointsAmount}', + /** @internal */ + verticalAlign: 'middle', + /** @internal */ + align: 'center', + /** @internal */ + style: { + color: 'contrast' + }, + /** @internal */ + inside: true + } +}; +(H.defaultOptions.plotOptions || {}).series = merge((H.defaultOptions.plotOptions || {}).series, { + cluster: clusterDefaultOptions, + tooltip: { + /** + * The HTML of the cluster point's in the tooltip. Works only with + * marker-clusters module and analogously to + * [pointFormat](#tooltip.pointFormat). + * + * The cluster tooltip can be also formatted using + * `tooltip.formatter` callback function and `point.isCluster` flag. + * + * @sample highcharts/marker-clusters/grid + * Format tooltip for cluster points. + * + * @sample maps/marker-clusters/europe/ + * Format tooltip for clusters using tooltip.formatter + * + * @apioption tooltip.clusterFormat + */ + clusterFormat: 'Clustered points: ' + + '{point.clusterPointsAmount}
' + } +}); +// Utils. +/* eslint-disable require-jsdoc */ +function getClusterPosition(points) { + var pointsLen = points.length, sumX = 0, sumY = 0, i; + for (i = 0; i < pointsLen; i++) { + sumX += points[i].x; + sumY += points[i].y; + } + return { + x: sumX / pointsLen, + y: sumY / pointsLen + }; +} +// Prepare array with sorted data objects to be +// compared in getPointsState method. +function getDataState(clusteredData, stateDataLen) { + var state = []; + state.length = stateDataLen; + clusteredData.clusters.forEach(function (cluster) { + cluster.data.forEach(function (elem) { + state[elem.dataIndex] = elem; + }); + }); + clusteredData.noise.forEach(function (noise) { + state[noise.data[0].dataIndex] = noise.data[0]; + }); + return state; +} +function fadeInElement(elem, opacity, animation) { + elem + .attr({ + opacity: opacity + }) + .animate({ + opacity: 1 + }, animation); +} +function fadeInStatePoint(stateObj, opacity, animation, fadeinGraphic, fadeinDataLabel) { + if (stateObj.point) { + if (fadeinGraphic && stateObj.point.graphic) { + stateObj.point.graphic.show(); + fadeInElement(stateObj.point.graphic, opacity, animation); + } + if (fadeinDataLabel && stateObj.point.dataLabel) { + stateObj.point.dataLabel.show(); + fadeInElement(stateObj.point.dataLabel, opacity, animation); + } + } +} +function hideStatePoint(stateObj, hideGraphic, hideDataLabel) { + if (stateObj.point) { + if (hideGraphic && stateObj.point.graphic) { + stateObj.point.graphic.hide(); + } + if (hideDataLabel && stateObj.point.dataLabel) { + stateObj.point.dataLabel.hide(); + } + } +} +function destroyOldPoints(oldState) { + if (oldState) { + objectEach(oldState, function (state) { + if (state.point && state.point.destroy) { + state.point.destroy(); + } + }); + } +} +function fadeInNewPointAndDestoryOld(newPointObj, oldPoints, animation, opacity) { + // Fade in new point. + fadeInStatePoint(newPointObj, opacity, animation, true, true); + // Destroy old animated points. + oldPoints.forEach(function (p) { + if (p.point && p.point.destroy) { + p.point.destroy(); + } + }); +} +// Generate unique stateId for a state element. +function getStateId() { + return Math.random().toString(36).substring(2, 7) + '-' + stateIdCounter++; +} +// Useful for debugging. +// function drawGridLines( +// series: Highcharts.Series, +// options: Highcharts.MarkerClusterLayoutAlgorithmOptions +// ): void { +// var chart = series.chart, +// xAxis = series.xAxis, +// yAxis = series.yAxis, +// xAxisLen = series.xAxis.len, +// yAxisLen = series.yAxis.len, +// i, j, elem, text, +// currentX = 0, +// currentY = 0, +// scaledGridSize = 50, +// gridX = 0, +// gridY = 0, +// gridOffset = series.getGridOffset(), +// mapXSize, mapYSize; +// if (series.debugGridLines && series.debugGridLines.length) { +// series.debugGridLines.forEach(function (gridItem): void { +// if (gridItem && gridItem.destroy) { +// gridItem.destroy(); +// } +// }); +// } +// series.debugGridLines = []; +// scaledGridSize = series.getScaledGridSize(options); +// mapXSize = Math.abs( +// xAxis.toPixels(xAxis.dataMax || 0) - +// xAxis.toPixels(xAxis.dataMin || 0) +// ); +// mapYSize = Math.abs( +// yAxis.toPixels(yAxis.dataMax || 0) - +// yAxis.toPixels(yAxis.dataMin || 0) +// ); +// gridX = Math.ceil(mapXSize / scaledGridSize); +// gridY = Math.ceil(mapYSize / scaledGridSize); +// for (i = 0; i < gridX; i++) { +// currentX = i * scaledGridSize; +// if ( +// gridOffset.plotLeft + currentX >= 0 && +// gridOffset.plotLeft + currentX < xAxisLen +// ) { +// for (j = 0; j < gridY; j++) { +// currentY = j * scaledGridSize; +// if ( +// gridOffset.plotTop + currentY >= 0 && +// gridOffset.plotTop + currentY < yAxisLen +// ) { +// if (j % 2 === 0 && i % 2 === 0) { +// var rect = chart.renderer +// .rect( +// gridOffset.plotLeft + currentX, +// gridOffset.plotTop + currentY, +// scaledGridSize * 2, +// scaledGridSize * 2 +// ) +// .attr({ +// stroke: series.color, +// 'stroke-width': '2px' +// }) +// .add() +// .toFront(); +// series.debugGridLines.push(rect); +// } +// elem = chart.renderer +// .rect( +// gridOffset.plotLeft + currentX, +// gridOffset.plotTop + currentY, +// scaledGridSize, +// scaledGridSize +// ) +// .attr({ +// stroke: series.color, +// opacity: 0.3, +// 'stroke-width': '1px' +// }) +// .add() +// .toFront(); +// text = chart.renderer +// .text( +// j + '-' + i, +// gridOffset.plotLeft + currentX + 2, +// gridOffset.plotTop + currentY + 7 +// ) +// .css({ +// fill: 'rgba(0, 0, 0, 0.7)', +// fontSize: '7px' +// }) +// .add() +// .toFront(); +// series.debugGridLines.push(elem); +// series.debugGridLines.push(text); +// } +// } +// } +// } +// } +/* eslint-enable require-jsdoc */ +// Cluster symbol. +SvgRenderer.prototype.symbols.cluster = function (x, y, width, height) { + var w = width / 2, h = height / 2, outerWidth = 1, space = 1, inner, outer1, outer2; + inner = this.arc(x + w, y + h, w - space * 4, h - space * 4, { + start: Math.PI * 0.5, + end: Math.PI * 2.5, + open: false + }); + outer1 = this.arc(x + w, y + h, w - space * 3, h - space * 3, { + start: Math.PI * 0.5, + end: Math.PI * 2.5, + innerR: w - outerWidth * 2, + open: false + }); + outer2 = this.arc(x + w, y + h, w - space, h - space, { + start: Math.PI * 0.5, + end: Math.PI * 2.5, + innerR: w, + open: false + }); + return outer2.concat(outer1, inner); +}; +Scatter.prototype.animateClusterPoint = function (clusterObj) { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, chart = series.chart, clusterOptions = series.options.cluster, animation = animObject((clusterOptions || {}).animation), animDuration = animation.duration || 500, pointsState = (series.markerClusterInfo || {}).pointsState, newState = (pointsState || {}).newState, oldState = (pointsState || {}).oldState, parentId, oldPointObj, newPointObj, oldPoints = [], newPointBBox, offset = 0, newX = 0, newY = 0, isOldPointGrahic = false, isCbHandled = false; + if (oldState && newState) { + newPointObj = newState[clusterObj.stateId]; + newX = xAxis.toPixels(newPointObj.x) - chart.plotLeft; + newY = yAxis.toPixels(newPointObj.y) - chart.plotTop; + // Point has one ancestor. + if (newPointObj.parentsId.length === 1) { + parentId = (newState || {})[clusterObj.stateId].parentsId[0]; + oldPointObj = oldState[parentId]; + // If old and new poistions are the same do not animate. + if (newPointObj.point && + newPointObj.point.graphic && + oldPointObj && + oldPointObj.point && + oldPointObj.point.plotX && + oldPointObj.point.plotY && + oldPointObj.point.plotX !== newPointObj.point.plotX && + oldPointObj.point.plotY !== newPointObj.point.plotY) { + newPointBBox = newPointObj.point.graphic.getBBox(); + offset = newPointBBox.width / 2; + newPointObj.point.graphic.attr({ + x: oldPointObj.point.plotX - offset, + y: oldPointObj.point.plotY - offset + }); + newPointObj.point.graphic.animate({ + x: newX - newPointObj.point.graphic.radius, + y: newY - newPointObj.point.graphic.radius + }, animation, function () { + isCbHandled = true; + // Destroy old point. + if (oldPointObj.point && oldPointObj.point.destroy) { + oldPointObj.point.destroy(); + } + }); + // Data label animation. + if (newPointObj.point.dataLabel && + newPointObj.point.dataLabel.alignAttr && + oldPointObj.point.dataLabel && + oldPointObj.point.dataLabel.alignAttr) { + newPointObj.point.dataLabel.attr({ + x: oldPointObj.point.dataLabel.alignAttr.x, + y: oldPointObj.point.dataLabel.alignAttr.y + }); + newPointObj.point.dataLabel.animate({ + x: newPointObj.point.dataLabel.alignAttr.x, + y: newPointObj.point.dataLabel.alignAttr.y + }, animation); + } + } + } + else if (newPointObj.parentsId.length === 0) { + // Point has no ancestors - new point. + // Hide new point. + hideStatePoint(newPointObj, true, true); + syncTimeout(function () { + // Fade in new point. + fadeInStatePoint(newPointObj, 0.1, animation, true, true); + }, animDuration / 2); + } + else { + // Point has many ancestors. + // Hide new point before animation. + hideStatePoint(newPointObj, true, true); + newPointObj.parentsId.forEach(function (elem) { + if (oldState && oldState[elem]) { + oldPointObj = oldState[elem]; + oldPoints.push(oldPointObj); + if (oldPointObj.point && + oldPointObj.point.graphic) { + isOldPointGrahic = true; + oldPointObj.point.graphic.show(); + oldPointObj.point.graphic.animate({ + x: newX - oldPointObj.point.graphic.radius, + y: newY - oldPointObj.point.graphic.radius, + opacity: 0.4 + }, animation, function () { + isCbHandled = true; + fadeInNewPointAndDestoryOld(newPointObj, oldPoints, animation, 0.7); + }); + if (oldPointObj.point.dataLabel && + oldPointObj.point.dataLabel.y !== -9999 && + newPointObj.point && + newPointObj.point.dataLabel && + newPointObj.point.dataLabel.alignAttr) { + oldPointObj.point.dataLabel.show(); + oldPointObj.point.dataLabel.animate({ + x: newPointObj.point.dataLabel.alignAttr.x, + y: newPointObj.point.dataLabel.alignAttr.y, + opacity: 0.4 + }, animation); + } + } + } + }); + // Make sure point is faded in. + syncTimeout(function () { + if (!isCbHandled) { + fadeInNewPointAndDestoryOld(newPointObj, oldPoints, animation, 0.85); + } + }, animDuration); + if (!isOldPointGrahic) { + syncTimeout(function () { + fadeInNewPointAndDestoryOld(newPointObj, oldPoints, animation, 0.1); + }, animDuration / 2); + } + } + } +}; +Scatter.prototype.getGridOffset = function () { + var series = this, chart = series.chart, xAxis = series.xAxis, yAxis = series.yAxis, plotLeft = 0, plotTop = 0; + if (series.dataMinX && series.dataMaxX) { + plotLeft = xAxis.reversed ? + xAxis.toPixels(series.dataMaxX) : xAxis.toPixels(series.dataMinX); + } + else { + plotLeft = chart.plotLeft; + } + if (series.dataMinY && series.dataMaxY) { + plotTop = yAxis.reversed ? + yAxis.toPixels(series.dataMinY) : yAxis.toPixels(series.dataMaxY); + } + else { + plotTop = chart.plotTop; + } + return { plotLeft: plotLeft, plotTop: plotTop }; +}; +Scatter.prototype.getScaledGridSize = function (options) { + var series = this, xAxis = series.xAxis, search = true, k = 1, divider = 1, processedGridSize = options.processedGridSize || + clusterDefaultOptions.layoutAlgorithm.gridSize, gridSize, scale, level; + if (!series.gridValueSize) { + series.gridValueSize = Math.abs(xAxis.toValue(processedGridSize) - xAxis.toValue(0)); + } + gridSize = xAxis.toPixels(series.gridValueSize) - xAxis.toPixels(0); + scale = +(processedGridSize / gridSize).toFixed(14); + // Find the level and its divider. + while (search && scale !== 1) { + level = Math.pow(2, k); + if (scale > 0.75 && scale < 1.25) { + search = false; + } + else if (scale >= (1 / level) && scale < 2 * (1 / level)) { + search = false; + divider = level; + } + else if (scale <= level && scale > level / 2) { + search = false; + divider = 1 / level; + } + k++; + } + return (processedGridSize / divider) / scale; +}; +Scatter.prototype.getRealExtremes = function () { + var _a, _b; + var series = this, chart = series.chart, xAxis = series.xAxis, yAxis = series.yAxis, realMinX = xAxis ? xAxis.toValue(chart.plotLeft) : 0, realMaxX = xAxis ? + xAxis.toValue(chart.plotLeft + chart.plotWidth) : 0, realMinY = yAxis ? yAxis.toValue(chart.plotTop) : 0, realMaxY = yAxis ? + yAxis.toValue(chart.plotTop + chart.plotHeight) : 0; + if (realMinX > realMaxX) { + _a = __read([realMinX, realMaxX], 2), realMaxX = _a[0], realMinX = _a[1]; + } + if (realMinY > realMaxY) { + _b = __read([realMinY, realMaxY], 2), realMaxY = _b[0], realMinY = _b[1]; + } + return { + minX: realMinX, + maxX: realMaxX, + minY: realMinY, + maxY: realMaxY + }; +}; +Scatter.prototype.onDrillToCluster = function (event) { + var point = event.point || event.target; + point.firePointEvent('drillToCluster', event, function (e) { + var _a, _b; + var point = e.point || e.target, series = point.series, xAxis = point.series.xAxis, yAxis = point.series.yAxis, chart = point.series.chart, clusterOptions = series.options.cluster, drillToCluster = (clusterOptions || {}).drillToCluster, offsetX, offsetY, sortedDataX, sortedDataY, minX, minY, maxX, maxY; + if (drillToCluster && point.clusteredData) { + sortedDataX = point.clusteredData.map(function (data) { + return data.x; + }).sort(function (a, b) { return a - b; }); + sortedDataY = point.clusteredData.map(function (data) { + return data.y; + }).sort(function (a, b) { return a - b; }); + minX = sortedDataX[0]; + maxX = sortedDataX[sortedDataX.length - 1]; + minY = sortedDataY[0]; + maxY = sortedDataY[sortedDataY.length - 1]; + offsetX = Math.abs((maxX - minX) * 0.1); + offsetY = Math.abs((maxY - minY) * 0.1); + chart.pointer.zoomX = true; + chart.pointer.zoomY = true; + // Swap when minus values. + if (minX > maxX) { + _a = __read([maxX, minX], 2), minX = _a[0], maxX = _a[1]; + } + if (minY > maxY) { + _b = __read([maxY, minY], 2), minY = _b[0], maxY = _b[1]; + } + chart.zoom({ + originalEvent: e, + xAxis: [{ + axis: xAxis, + min: minX - offsetX, + max: maxX + offsetX + }], + yAxis: [{ + axis: yAxis, + min: minY - offsetY, + max: maxY + offsetY + }] + }); + } + }); +}; +Scatter.prototype.getClusterDistancesFromPoint = function (clusters, pointX, pointY) { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, pointClusterDistance = [], j, distance; + for (j = 0; j < clusters.length; j++) { + distance = Math.sqrt(Math.pow(xAxis.toPixels(pointX) - + xAxis.toPixels(clusters[j].posX), 2) + + Math.pow(yAxis.toPixels(pointY) - + yAxis.toPixels(clusters[j].posY), 2)); + pointClusterDistance.push({ + clusterIndex: j, + distance: distance + }); + } + return pointClusterDistance.sort(function (a, b) { return a.distance - b.distance; }); +}; +// Point state used when animation is enabled to compare +// and bind old points with new ones. +Scatter.prototype.getPointsState = function (clusteredData, oldMarkerClusterInfo, dataLength) { + var oldDataStateArr = oldMarkerClusterInfo ? + getDataState(oldMarkerClusterInfo, dataLength) : [], newDataStateArr = getDataState(clusteredData, dataLength), state = {}, newState, oldState, i; + // Clear global array before populate with new ids. + oldPointsStateId = []; + // Build points state structure. + clusteredData.clusters.forEach(function (cluster) { + state[cluster.stateId] = { + x: cluster.x, + y: cluster.y, + id: cluster.stateId, + point: cluster.point, + parentsId: [] + }; + }); + clusteredData.noise.forEach(function (noise) { + state[noise.stateId] = { + x: noise.x, + y: noise.y, + id: noise.stateId, + point: noise.point, + parentsId: [] + }; + }); + // Bind new and old state. + for (i = 0; i < newDataStateArr.length; i++) { + newState = newDataStateArr[i]; + oldState = oldDataStateArr[i]; + if (newState && + oldState && + newState.parentStateId && + oldState.parentStateId && + state[newState.parentStateId] && + state[newState.parentStateId].parentsId.indexOf(oldState.parentStateId) === -1) { + state[newState.parentStateId].parentsId.push(oldState.parentStateId); + if (oldPointsStateId.indexOf(oldState.parentStateId) === -1) { + oldPointsStateId.push(oldState.parentStateId); + } + } + } + return state; +}; +Scatter.prototype.markerClusterAlgorithms = { + grid: function (dataX, dataY, dataIndexes, options) { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, grid = {}, gridOffset = series.getGridOffset(), scaledGridSize, x, y, gridX, gridY, key, i; + // drawGridLines(series, options); + scaledGridSize = series.getScaledGridSize(options); + for (i = 0; i < dataX.length; i++) { + x = xAxis.toPixels(dataX[i]) - gridOffset.plotLeft; + y = yAxis.toPixels(dataY[i]) - gridOffset.plotTop; + gridX = Math.floor(x / scaledGridSize); + gridY = Math.floor(y / scaledGridSize); + key = gridY + '-' + gridX; + if (!grid[key]) { + grid[key] = []; + } + grid[key].push({ + dataIndex: dataIndexes[i], + x: dataX[i], + y: dataY[i] + }); + } + return grid; + }, + kmeans: function (dataX, dataY, dataIndexes, options) { + var series = this, clusters = [], noise = [], group = {}, pointMaxDistance = options.processedDistance || + clusterDefaultOptions.layoutAlgorithm.distance, iterations = options.iterations, + // Max pixel difference beetwen new and old cluster position. + maxClusterShift = 1, currentIteration = 0, repeat = true, pointX = 0, pointY = 0, tempPos, pointClusterDistance = [], groupedData, key, i, j; + options.processedGridSize = options.processedDistance; + // Use grid method to get groupedData object. + groupedData = series.markerClusterAlgorithms ? + series.markerClusterAlgorithms.grid.call(series, dataX, dataY, dataIndexes, options) : {}; + // Find clusters amount and its start positions + // based on grid grouped data. + for (key in groupedData) { + if (groupedData[key].length > 1) { + tempPos = getClusterPosition(groupedData[key]); + clusters.push({ + posX: tempPos.x, + posY: tempPos.y, + oldX: 0, + oldY: 0, + startPointsLen: groupedData[key].length, + points: [] + }); + } + } + // Start kmeans iteration process. + while (repeat) { + clusters.map(function (c) { + c.points.length = 0; + return c; + }); + noise.length = 0; + for (i = 0; i < dataX.length; i++) { + pointX = dataX[i]; + pointY = dataY[i]; + pointClusterDistance = series.getClusterDistancesFromPoint(clusters, pointX, pointY); + if (pointClusterDistance.length && + pointClusterDistance[0].distance < pointMaxDistance) { + clusters[pointClusterDistance[0].clusterIndex].points.push({ + x: pointX, + y: pointY, + dataIndex: dataIndexes[i] + }); + } + else { + noise.push({ + x: pointX, + y: pointY, + dataIndex: dataIndexes[i] + }); + } + } + // When cluster points array has only one point the + // point should be classified again. + for (j = 0; j < clusters.length; j++) { + if (clusters[j].points.length === 1) { + pointClusterDistance = series.getClusterDistancesFromPoint(clusters, clusters[j].points[0].x, clusters[j].points[0].y); + if (pointClusterDistance[1].distance < pointMaxDistance) { + // Add point to the next closest cluster. + clusters[pointClusterDistance[1].clusterIndex].points + .push(clusters[j].points[0]); + // Clear points array. + clusters[pointClusterDistance[0].clusterIndex] + .points.length = 0; + } + } + } + // Compute a new clusters position and check if it + // is different than the old one. + repeat = false; + for (j = 0; j < clusters.length; j++) { + tempPos = getClusterPosition(clusters[j].points); + clusters[j].oldX = clusters[j].posX; + clusters[j].oldY = clusters[j].posY; + clusters[j].posX = tempPos.x; + clusters[j].posY = tempPos.y; + // Repeat the algorithm if at least one cluster + // is shifted more than maxClusterShift property. + if (clusters[j].posX > clusters[j].oldX + maxClusterShift || + clusters[j].posX < clusters[j].oldX - maxClusterShift || + clusters[j].posY > clusters[j].oldY + maxClusterShift || + clusters[j].posY < clusters[j].oldY - maxClusterShift) { + repeat = true; + } + } + // If iterations property is set repeat the algorithm + // specified amount of times. + if (iterations) { + repeat = currentIteration < iterations - 1; + } + currentIteration++; + } + clusters.forEach(function (cluster, i) { + group['cluster' + i] = cluster.points; + }); + noise.forEach(function (noise, i) { + group['noise' + i] = [noise]; + }); + return group; + }, + optimizedKmeans: function (processedXData, processedYData, dataIndexes, options) { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, pointMaxDistance = options.processedDistance || + clusterDefaultOptions.layoutAlgorithm.gridSize, group = {}, extremes = series.getRealExtremes(), clusterMarkerOptions = (series.options.cluster || {}).marker, offset, distance, radius; + if (!series.markerClusterInfo || (series.initMaxX && series.initMaxX < extremes.maxX || + series.initMinX && series.initMinX > extremes.minX || + series.initMaxY && series.initMaxY < extremes.maxY || + series.initMinY && series.initMinY > extremes.minY)) { + series.initMaxX = extremes.maxX; + series.initMinX = extremes.minX; + series.initMaxY = extremes.maxY; + series.initMinY = extremes.minY; + group = series.markerClusterAlgorithms ? + series.markerClusterAlgorithms.kmeans.call(series, processedXData, processedYData, dataIndexes, options) : {}; + series.baseClusters = null; + } + else { + if (!series.baseClusters) { + series.baseClusters = { + clusters: series.markerClusterInfo.clusters, + noise: series.markerClusterInfo.noise + }; + } + series.baseClusters.clusters.forEach(function (cluster) { + cluster.pointsOutside = []; + cluster.pointsInside = []; + cluster.data.forEach(function (dataPoint) { + distance = Math.sqrt(Math.pow(xAxis.toPixels(dataPoint.x) - + xAxis.toPixels(cluster.x), 2) + + Math.pow(yAxis.toPixels(dataPoint.y) - + yAxis.toPixels(cluster.y), 2)); + if (cluster.clusterZone && + cluster.clusterZone.marker && + cluster.clusterZone.marker.radius) { + radius = cluster.clusterZone.marker.radius; + } + else if (clusterMarkerOptions && + clusterMarkerOptions.radius) { + radius = clusterMarkerOptions.radius; + } + else { + radius = clusterDefaultOptions.marker.radius; + } + offset = pointMaxDistance - radius >= 0 ? + pointMaxDistance - radius : radius; + if (distance > radius + offset && + defined(cluster.pointsOutside)) { + cluster.pointsOutside.push(dataPoint); + } + else if (defined(cluster.pointsInside)) { + cluster.pointsInside.push(dataPoint); + } + }); + if (cluster.pointsInside.length) { + group[cluster.id] = cluster.pointsInside; + } + cluster.pointsOutside.forEach(function (p, i) { + group[cluster.id + '_noise' + i] = [p]; + }); + }); + series.baseClusters.noise.forEach(function (noise) { + group[noise.id] = noise.data; + }); + } + return group; + } +}; +Scatter.prototype.preventClusterCollisions = function (props) { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, _a = __read(props.key.split('-').map(parseFloat), 2), gridY = _a[0], gridX = _a[1], gridSize = props.gridSize, groupedData = props.groupedData, defaultRadius = props.defaultRadius, clusterRadius = props.clusterRadius, gridXPx = gridX * gridSize, gridYPx = gridY * gridSize, xPixel = xAxis.toPixels(props.x), yPixel = yAxis.toPixels(props.y), gridsToCheckCollision = [], pointsLen = 0, radius = 0, clusterMarkerOptions = (series.options.cluster || {}).marker, zoneOptions = (series.options.cluster || {}).zones, gridOffset = series.getGridOffset(), nextXPixel, nextYPixel, signX, signY, cornerGridX, cornerGridY, i, j, itemX, itemY, nextClusterPos, maxDist, keys, x, y; + // Distance to the grid start. + xPixel -= gridOffset.plotLeft; + yPixel -= gridOffset.plotTop; + for (i = 1; i < 5; i++) { + signX = i % 2 ? -1 : 1; + signY = i < 3 ? -1 : 1; + cornerGridX = Math.floor((xPixel + signX * clusterRadius) / gridSize); + cornerGridY = Math.floor((yPixel + signY * clusterRadius) / gridSize); + keys = [ + cornerGridY + '-' + cornerGridX, + cornerGridY + '-' + gridX, + gridY + '-' + cornerGridX + ]; + for (j = 0; j < keys.length; j++) { + if (gridsToCheckCollision.indexOf(keys[j]) === -1 && + keys[j] !== props.key) { + gridsToCheckCollision.push(keys[j]); + } + } + } + gridsToCheckCollision.forEach(function (item) { + var _a; + if (groupedData[item]) { + // Cluster or noise position is already computed. + if (!groupedData[item].posX) { + nextClusterPos = getClusterPosition(groupedData[item]); + groupedData[item].posX = nextClusterPos.x; + groupedData[item].posY = nextClusterPos.y; + } + nextXPixel = xAxis.toPixels(groupedData[item].posX || 0) - + gridOffset.plotLeft; + nextYPixel = yAxis.toPixels(groupedData[item].posY || 0) - + gridOffset.plotTop; + _a = __read(item.split('-').map(parseFloat), 2), itemY = _a[0], itemX = _a[1]; + if (zoneOptions) { + pointsLen = groupedData[item].length; + for (i = 0; i < zoneOptions.length; i++) { + if (pointsLen >= zoneOptions[i].from && + pointsLen <= zoneOptions[i].to) { + if (defined((zoneOptions[i].marker || {}).radius)) { + radius = zoneOptions[i].marker.radius || 0; + } + else if (clusterMarkerOptions && + clusterMarkerOptions.radius) { + radius = clusterMarkerOptions.radius; + } + else { + radius = clusterDefaultOptions.marker.radius; + } + } + } + } + if (groupedData[item].length > 1 && + radius === 0 && + clusterMarkerOptions && + clusterMarkerOptions.radius) { + radius = clusterMarkerOptions.radius; + } + else if (groupedData[item].length === 1) { + radius = defaultRadius; + } + maxDist = clusterRadius + radius; + radius = 0; + if (itemX !== gridX && + Math.abs(xPixel - nextXPixel) < maxDist) { + xPixel = itemX - gridX < 0 ? gridXPx + clusterRadius : + gridXPx + gridSize - clusterRadius; + } + if (itemY !== gridY && + Math.abs(yPixel - nextYPixel) < maxDist) { + yPixel = itemY - gridY < 0 ? gridYPx + clusterRadius : + gridYPx + gridSize - clusterRadius; + } + } + }); + x = xAxis.toValue(xPixel + gridOffset.plotLeft); + y = yAxis.toValue(yPixel + gridOffset.plotTop); + groupedData[props.key].posX = x; + groupedData[props.key].posY = y; + return { x: x, y: y }; +}; +// Check if user algorithm result is valid groupedDataObject. +Scatter.prototype.isValidGroupedDataObject = function (groupedData) { + var result = false, i; + if (!isObject(groupedData)) { + return false; + } + objectEach(groupedData, function (elem) { + result = true; + if (!isArray(elem) || !elem.length) { + result = false; + return; + } + for (i = 0; i < elem.length; i++) { + if (!isObject(elem[i]) || (!elem[i].x || !elem[i].y)) { + result = false; + return; + } + } + }); + return result; +}; +Scatter.prototype.getClusteredData = function (groupedData, options) { + var series = this, groupedXData = [], groupedYData = [], clusters = [], // Container for clusters. + noise = [], // Container for points not belonging to any cluster. + groupMap = [], index = 0, + // Prevent minimumClusterSize lower than 2. + minimumClusterSize = Math.max(2, options.minimumClusterSize || 2), stateId, point, points, pointUserOptions, pointsLen, marker, clusterPos, pointOptions, clusterTempPos, zoneOptions, clusterZone, clusterZoneClassName, i, k; + // Check if groupedData is valid when user uses a custom algorithm. + if (isFunction(options.layoutAlgorithm.type) && + !series.isValidGroupedDataObject(groupedData)) { + error('Highcharts marker-clusters module: ' + + 'The custom algorithm result is not valid!', false, series.chart); + return false; + } + for (k in groupedData) { + if (groupedData[k].length >= minimumClusterSize) { + points = groupedData[k]; + stateId = getStateId(); + pointsLen = points.length; + // Get zone options for cluster. + if (options.zones) { + for (i = 0; i < options.zones.length; i++) { + if (pointsLen >= options.zones[i].from && + pointsLen <= options.zones[i].to) { + clusterZone = options.zones[i]; + clusterZone.zoneIndex = i; + zoneOptions = options.zones[i].marker; + clusterZoneClassName = options.zones[i].className; + } + } + } + clusterTempPos = getClusterPosition(points); + if (options.layoutAlgorithm.type === 'grid' && + !options.allowOverlap) { + marker = series.options.marker || {}; + clusterPos = series.preventClusterCollisions({ + x: clusterTempPos.x, + y: clusterTempPos.y, + key: k, + groupedData: groupedData, + gridSize: series.getScaledGridSize(options.layoutAlgorithm), + defaultRadius: marker.radius || 3 + (marker.lineWidth || 0), + clusterRadius: (zoneOptions && zoneOptions.radius) ? + zoneOptions.radius : + (options.marker || {}).radius || + clusterDefaultOptions.marker.radius + }); + } + else { + clusterPos = { + x: clusterTempPos.x, + y: clusterTempPos.y + }; + } + for (i = 0; i < pointsLen; i++) { + points[i].parentStateId = stateId; + } + clusters.push({ + x: clusterPos.x, + y: clusterPos.y, + id: k, + stateId: stateId, + index: index, + data: points, + clusterZone: clusterZone, + clusterZoneClassName: clusterZoneClassName + }); + groupedXData.push(clusterPos.x); + groupedYData.push(clusterPos.y); + groupMap.push({ + options: { + formatPrefix: 'cluster', + dataLabels: options.dataLabels, + marker: merge(options.marker, { + states: options.states + }, zoneOptions || {}) + } + }); + // Save cluster data points options. + if (series.options.data && series.options.data.length) { + for (i = 0; i < pointsLen; i++) { + if (isObject(series.options.data[points[i].dataIndex])) { + points[i].options = + series.options.data[points[i].dataIndex]; + } + } + } + index++; + zoneOptions = null; + } + else { + for (i = 0; i < groupedData[k].length; i++) { + // Points not belonging to any cluster. + point = groupedData[k][i]; + stateId = getStateId(); + pointOptions = null; + pointUserOptions = + ((series.options || {}).data || [])[point.dataIndex]; + groupedXData.push(point.x); + groupedYData.push(point.y); + point.parentStateId = stateId; + noise.push({ + x: point.x, + y: point.y, + id: k, + stateId: stateId, + index: index, + data: groupedData[k] + }); + if (pointUserOptions && + typeof pointUserOptions === 'object' && + !isArray(pointUserOptions)) { + pointOptions = merge(pointUserOptions, { x: point.x, y: point.y }); + } + else { + pointOptions = { + userOptions: pointUserOptions, + x: point.x, + y: point.y + }; + } + groupMap.push({ options: pointOptions }); + index++; + } + } + } + return { + clusters: clusters, + noise: noise, + groupedXData: groupedXData, + groupedYData: groupedYData, + groupMap: groupMap + }; +}; +// Destroy clustered data points. +Scatter.prototype.destroyClusteredData = function () { + var clusteredSeriesData = this.markerClusterSeriesData; + // Clear previous groups. + (clusteredSeriesData || []).forEach(function (point) { + if (point && point.destroy) { + point.destroy(); + } + }); + this.markerClusterSeriesData = null; +}; +// Hide clustered data points. +Scatter.prototype.hideClusteredData = function () { + var series = this, clusteredSeriesData = this.markerClusterSeriesData, oldState = ((series.markerClusterInfo || {}).pointsState || {}).oldState || {}, oldPointsId = oldPointsStateId.map(function (elem) { + return (oldState[elem].point || {}).id || ''; + }); + (clusteredSeriesData || []).forEach(function (point) { + // If an old point is used in animation hide it, otherwise destroy. + if (point && + oldPointsId.indexOf(point.id) !== -1) { + if (point.graphic) { + point.graphic.hide(); + } + if (point.dataLabel) { + point.dataLabel.hide(); + } + } + else { + if (point && point.destroy) { + point.destroy(); + } + } + }); +}; +// Override the generatePoints method by adding a reference to grouped data. +Scatter.prototype.generatePoints = function () { + var series = this, chart = series.chart, xAxis = series.xAxis, yAxis = series.yAxis, clusterOptions = series.options.cluster, realExtremes = series.getRealExtremes(), visibleXData = [], visibleYData = [], visibleDataIndexes = [], oldPointsState, oldDataLen, oldMarkerClusterInfo, kmeansThreshold, cropDataOffsetX, cropDataOffsetY, seriesMinX, seriesMaxX, seriesMinY, seriesMaxY, type, algorithm, clusteredData, groupedData, layoutAlgOptions, point, i; + if (clusterOptions && + clusterOptions.enabled && + series.xData && + series.yData && + !chart.polar) { + type = clusterOptions.layoutAlgorithm.type; + layoutAlgOptions = clusterOptions.layoutAlgorithm; + // Get processed algorithm properties. + layoutAlgOptions.processedGridSize = relativeLength(layoutAlgOptions.gridSize || + clusterDefaultOptions.layoutAlgorithm.gridSize, chart.plotWidth); + layoutAlgOptions.processedDistance = relativeLength(layoutAlgOptions.distance || + clusterDefaultOptions.layoutAlgorithm.distance, chart.plotWidth); + kmeansThreshold = layoutAlgOptions.kmeansThreshold || + clusterDefaultOptions.layoutAlgorithm.kmeansThreshold; + // Offset to prevent cluster size changes. + cropDataOffsetX = Math.abs(xAxis.toValue(layoutAlgOptions.processedGridSize / 2) - + xAxis.toValue(0)); + cropDataOffsetY = Math.abs(yAxis.toValue(layoutAlgOptions.processedGridSize / 2) - + yAxis.toValue(0)); + // Get only visible data. + for (i = 0; i < series.xData.length; i++) { + if (!series.dataMaxX) { + if (!defined(seriesMaxX) || + !defined(seriesMinX) || + !defined(seriesMaxY) || + !defined(seriesMinY)) { + seriesMaxX = seriesMinX = series.xData[i]; + seriesMaxY = seriesMinY = series.yData[i]; + } + else if (isNumber(series.yData[i]) && + isNumber(seriesMaxY) && + isNumber(seriesMinY)) { + seriesMaxX = Math.max(series.xData[i], seriesMaxX); + seriesMinX = Math.min(series.xData[i], seriesMinX); + seriesMaxY = Math.max(series.yData[i] || seriesMaxY, seriesMaxY); + seriesMinY = Math.min(series.yData[i] || seriesMinY, seriesMinY); + } + } + // Crop data to visible ones with appropriate offset to prevent + // cluster size changes on the edge of the plot area. + if (series.xData[i] >= (realExtremes.minX - cropDataOffsetX) && + series.xData[i] <= (realExtremes.maxX + cropDataOffsetX) && + (series.yData[i] || realExtremes.minY) >= + (realExtremes.minY - cropDataOffsetY) && + (series.yData[i] || realExtremes.maxY) <= + (realExtremes.maxY + cropDataOffsetY)) { + visibleXData.push(series.xData[i]); + visibleYData.push(series.yData[i]); + visibleDataIndexes.push(i); + } + } + // Save data max values. + if (defined(seriesMaxX) && defined(seriesMinX) && + isNumber(seriesMaxY) && isNumber(seriesMinY)) { + series.dataMaxX = seriesMaxX; + series.dataMinX = seriesMinX; + series.dataMaxY = seriesMaxY; + series.dataMinY = seriesMinY; + } + if (isFunction(type)) { + algorithm = type; + } + else if (series.markerClusterAlgorithms) { + if (type && series.markerClusterAlgorithms[type]) { + algorithm = series.markerClusterAlgorithms[type]; + } + else { + algorithm = visibleXData.length < kmeansThreshold ? + series.markerClusterAlgorithms.kmeans : + series.markerClusterAlgorithms.grid; + } + } + else { + algorithm = function () { + return false; + }; + } + groupedData = algorithm.call(this, visibleXData, visibleYData, visibleDataIndexes, layoutAlgOptions); + clusteredData = groupedData ? series.getClusteredData(groupedData, clusterOptions) : groupedData; + // When animation is enabled get old points state. + if (clusterOptions.animation && + series.markerClusterInfo && + series.markerClusterInfo.pointsState && + series.markerClusterInfo.pointsState.oldState) { + // Destroy old points. + destroyOldPoints(series.markerClusterInfo.pointsState.oldState); + oldPointsState = series.markerClusterInfo.pointsState.newState; + } + else { + oldPointsState = {}; + } + // Save points old state info. + oldDataLen = series.xData.length; + oldMarkerClusterInfo = series.markerClusterInfo; + if (clusteredData) { + series.processedXData = clusteredData.groupedXData; + series.processedYData = clusteredData.groupedYData; + series.hasGroupedData = true; + series.markerClusterInfo = clusteredData; + series.groupMap = clusteredData.groupMap; + } + baseGeneratePoints.apply(this); + if (clusteredData && series.markerClusterInfo) { + // Mark cluster points. Safe point reference in the cluster object. + (series.markerClusterInfo.clusters || []).forEach(function (cluster) { + point = series.points[cluster.index]; + point.isCluster = true; + point.clusteredData = cluster.data; + point.clusterPointsAmount = cluster.data.length; + cluster.point = point; + // Add zoom to cluster range. + addEvent(point, 'click', series.onDrillToCluster); + }); + // Safe point reference in the noise object. + (series.markerClusterInfo.noise || []).forEach(function (noise) { + noise.point = series.points[noise.index]; + }); + // When animation is enabled save points state. + if (clusterOptions.animation && + series.markerClusterInfo) { + series.markerClusterInfo.pointsState = { + oldState: oldPointsState, + newState: series.getPointsState(clusteredData, oldMarkerClusterInfo, oldDataLen) + }; + } + // Record grouped data in order to let it be destroyed the next time + // processData runs. + if (!clusterOptions.animation) { + this.destroyClusteredData(); + } + else { + this.hideClusteredData(); + } + this.markerClusterSeriesData = + this.hasGroupedData ? this.points : null; + } + } + else { + baseGeneratePoints.apply(this); + } +}; +// Handle animation. +addEvent(H.Chart, 'render', function () { + var chart = this; + (chart.series || []).forEach(function (series) { + if (series.markerClusterInfo) { + var options = series.options.cluster, pointsState = (series.markerClusterInfo || {}).pointsState, oldState = (pointsState || {}).oldState; + if ((options || {}).animation && + series.markerClusterInfo && + series.chart.pointer.pinchDown.length === 0 && + (series.xAxis.eventArgs || {}).trigger !== 'pan' && + oldState && + Object.keys(oldState).length) { + series.markerClusterInfo.clusters.forEach(function (cluster) { + series.animateClusterPoint(cluster); + }); + series.markerClusterInfo.noise.forEach(function (noise) { + series.animateClusterPoint(noise); + }); + } + } + }); +}); +// Override point prototype to throw a warning when trying to update +// clustered point. +addEvent(Point, 'update', function () { + if (this.dataGroup) { + error('Highcharts marker-clusters module: ' + + 'Running `Point.update` when point belongs to clustered series' + + ' is not supported.', false, this.series.chart); + return false; + } +}); +// Destroy grouped data on series destroy. +addEvent(Series, 'destroy', Scatter.prototype.destroyClusteredData); +// Add classes, change mouse cursor. +addEvent(Series, 'afterRender', function () { + var series = this, clusterZoomEnabled = (series.options.cluster || {}).drillToCluster; + if (series.markerClusterInfo && series.markerClusterInfo.clusters) { + series.markerClusterInfo.clusters.forEach(function (cluster) { + if (cluster.point && cluster.point.graphic) { + cluster.point.graphic.addClass('highcharts-cluster-point'); + // Change cursor to pointer when drillToCluster is enabled. + if (clusterZoomEnabled && cluster.point) { + cluster.point.graphic.css({ + cursor: 'pointer' + }); + if (cluster.point.dataLabel) { + cluster.point.dataLabel.css({ + cursor: 'pointer' + }); + } + } + if (defined(cluster.clusterZone)) { + cluster.point.graphic.addClass(cluster.clusterZoneClassName || + 'highcharts-cluster-zone-' + + cluster.clusterZone.zoneIndex); + } + } + }); + } +}); +addEvent(Point, 'drillToCluster', function (event) { + var point = event.point || event.target, series = point.series, clusterOptions = series.options.cluster, onDrillToCluster = ((clusterOptions || {}).events || {}).drillToCluster; + if (isFunction(onDrillToCluster)) { + onDrillToCluster.call(this, event); + } +}); +// Destroy the old tooltip after zoom. +addEvent(H.Axis, 'setExtremes', function () { + var chart = this.chart, animationDuration = 0, animation; + chart.series.forEach(function (series) { + if (series.markerClusterInfo) { + animation = animObject((series.options.cluster || {}).animation); + animationDuration = animation.duration || 0; + } + }); + syncTimeout(function () { + if (chart.tooltip) { + chart.tooltip.destroy(); + } + }, animationDuration); +}); diff --git a/librerias/gantt/code/es-modules/modules/networkgraph/QuadTree.js b/librerias/gantt/code/es-modules/modules/networkgraph/QuadTree.js new file mode 100644 index 0000000..33afb4c --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/networkgraph/QuadTree.js @@ -0,0 +1,354 @@ +/* * + * + * Networkgraph series + * + * (c) 2010-2020 Paweł Fus + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../../parts/Globals.js'; +import U from '../../parts/Utilities.js'; +var extend = U.extend; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * The QuadTree node class. Used in Networkgraph chart as a base for Barnes-Hut + * approximation. + * + * @private + * @class + * @name Highcharts.QuadTreeNode + * + * @param {Highcharts.Dictionary} box Available space for the node + */ +var QuadTreeNode = H.QuadTreeNode = function (box) { + /** + * Read only. The available space for node. + * + * @name Highcharts.QuadTreeNode#box + * @type {Highcharts.Dictionary} + */ + this.box = box; + /** + * Read only. The minium of width and height values. + * + * @name Highcharts.QuadTreeNode#boxSize + * @type {number} + */ + this.boxSize = Math.min(box.width, box.height); + /** + * Read only. Array of subnodes. Empty if QuadTreeNode has just one Point. + * When added another Point to this QuadTreeNode, array is filled with four + * subnodes. + * + * @name Highcharts.QuadTreeNode#nodes + * @type {Array} + */ + this.nodes = []; + /** + * Read only. Flag to determine if QuadTreeNode is internal (and has + * subnodes with mass and central position) or external (bound to Point). + * + * @name Highcharts.QuadTreeNode#isInternal + * @type {boolean} + */ + this.isInternal = false; + /** + * Read only. If QuadTreeNode is an external node, Point is stored in + * `this.body`. + * + * @name Highcharts.QuadTreeNode#body + * @type {boolean|Highcharts.Point} + */ + this.body = false; + /** + * Read only. Internal nodes when created are empty to reserve the space. If + * Point is added to this QuadTreeNode, QuadTreeNode is no longer empty. + * + * @name Highcharts.QuadTreeNode#isEmpty + * @type {boolean} + */ + this.isEmpty = true; +}; +extend(QuadTreeNode.prototype, +/** @lends Highcharts.QuadTreeNode.prototype */ +{ + /** + * Insert recursively point(node) into the QuadTree. If the given + * quadrant is already occupied, divide it into smaller quadrants. + * + * @param {Highcharts.Point} point + * Point/node to be inserted + * @param {number} depth + * Max depth of the QuadTree + */ + insert: function (point, depth) { + var newQuadTreeNode; + if (this.isInternal) { + // Internal node: + this.nodes[this.getBoxPosition(point)].insert(point, depth - 1); + } + else { + this.isEmpty = false; + if (!this.body) { + // First body in a quadrant: + this.isInternal = false; + this.body = point; + } + else { + if (depth) { + // Every other body in a quadrant: + this.isInternal = true; + this.divideBox(); + // Reinsert main body only once: + if (this.body !== true) { + this.nodes[this.getBoxPosition(this.body)] + .insert(this.body, depth - 1); + this.body = true; + } + // Add second body: + this.nodes[this.getBoxPosition(point)] + .insert(point, depth - 1); + } + else { + // We are below max allowed depth. That means either: + // - really huge number of points + // - falling two points into exactly the same position + // In this case, create another node in the QuadTree. + // + // Alternatively we could add some noise to the + // position, but that could result in different + // rendered chart in exporting. + newQuadTreeNode = new QuadTreeNode({ + top: point.plotX, + left: point.plotY, + // Width/height below 1px + width: 0.1, + height: 0.1 + }); + newQuadTreeNode.body = point; + newQuadTreeNode.isInternal = false; + this.nodes.push(newQuadTreeNode); + } + } + } + }, + /** + * Each quad node requires it's mass and center position. That mass and + * position is used to imitate real node in the layout by approximation. + */ + updateMassAndCenter: function () { + var mass = 0, plotX = 0, plotY = 0; + if (this.isInternal) { + // Calcualte weightened mass of the quad node: + this.nodes.forEach(function (pointMass) { + if (!pointMass.isEmpty) { + mass += pointMass.mass; + plotX += + pointMass.plotX * pointMass.mass; + plotY += + pointMass.plotY * pointMass.mass; + } + }); + plotX /= mass; + plotY /= mass; + } + else if (this.body) { + // Just one node, use coordinates directly: + mass = this.body.mass; + plotX = this.body.plotX; + plotY = this.body.plotY; + } + // Store details: + this.mass = mass; + this.plotX = plotX; + this.plotY = plotY; + }, + /** + * When inserting another node into the box, that already hove one node, + * divide the available space into another four quadrants. + * + * Indexes of quadrants are: + * ``` + * ------------- ------------- + * | | | | | + * | | | 0 | 1 | + * | | divide() | | | + * | 1 | -----------> ------------- + * | | | | | + * | | | 3 | 2 | + * | | | | | + * ------------- ------------- + * ``` + */ + divideBox: function () { + var halfWidth = this.box.width / 2, halfHeight = this.box.height / 2; + // Top left + this.nodes[0] = new QuadTreeNode({ + left: this.box.left, + top: this.box.top, + width: halfWidth, + height: halfHeight + }); + // Top right + this.nodes[1] = new QuadTreeNode({ + left: this.box.left + halfWidth, + top: this.box.top, + width: halfWidth, + height: halfHeight + }); + // Bottom right + this.nodes[2] = new QuadTreeNode({ + left: this.box.left + halfWidth, + top: this.box.top + halfHeight, + width: halfWidth, + height: halfHeight + }); + // Bottom left + this.nodes[3] = new QuadTreeNode({ + left: this.box.left, + top: this.box.top + halfHeight, + width: halfWidth, + height: halfHeight + }); + }, + /** + * Determine which of the quadrants should be used when placing node in + * the QuadTree. Returned index is always in range `< 0 , 3 >`. + * + * @param {Highcharts.Point} point + * @return {number} + */ + getBoxPosition: function (point) { + var left = point.plotX < this.box.left + this.box.width / 2, top = point.plotY < this.box.top + this.box.height / 2, index; + if (left) { + if (top) { + // Top left + index = 0; + } + else { + // Bottom left + index = 3; + } + } + else { + if (top) { + // Top right + index = 1; + } + else { + // Bottom right + index = 2; + } + } + return index; + } +}); +/** + * The QuadTree class. Used in Networkgraph chart as a base for Barnes-Hut + * approximation. + * + * @private + * @class + * @name Highcharts.QuadTree + * + * @param {number} x left position of the plotting area + * @param {number} y top position of the plotting area + * @param {number} width width of the plotting area + * @param {number} height height of the plotting area + */ +var QuadTree = H.QuadTree = function (x, y, width, height) { + // Boundary rectangle: + this.box = { + left: x, + top: y, + width: width, + height: height + }; + this.maxDepth = 25; + this.root = new QuadTreeNode(this.box, '0'); + this.root.isInternal = true; + this.root.isRoot = true; + this.root.divideBox(); +}; +extend(QuadTree.prototype, +/** @lends Highcharts.QuadTree.prototype */ +{ + /** + * Insert nodes into the QuadTree + * + * @param {Array} points + */ + insertNodes: function (points) { + points.forEach(function (point) { + this.root.insert(point, this.maxDepth); + }, this); + }, + /** + * Depfth first treversal (DFS). Using `before` and `after` callbacks, + * we can get two results: preorder and postorder traversals, reminder: + * + * ``` + * (a) + * / \ + * (b) (c) + * / \ + * (d) (e) + * ``` + * + * DFS (preorder): `a -> b -> d -> e -> c` + * + * DFS (postorder): `d -> e -> b -> c -> a` + * + * @param {Highcharts.QuadTreeNode|null} node + * @param {Function} [beforeCallback] function to be called before + * visiting children nodes + * @param {Function} [afterCallback] function to be called after + * visiting children nodes + */ + visitNodeRecursive: function (node, beforeCallback, afterCallback) { + var goFurther; + if (!node) { + node = this.root; + } + if (node === this.root && beforeCallback) { + goFurther = beforeCallback(node); + } + if (goFurther === false) { + return; + } + node.nodes.forEach(function (qtNode) { + if (qtNode.isInternal) { + if (beforeCallback) { + goFurther = beforeCallback(qtNode); + } + if (goFurther === false) { + return; + } + this.visitNodeRecursive(qtNode, beforeCallback, afterCallback); + } + else if (qtNode.body) { + if (beforeCallback) { + beforeCallback(qtNode.body); + } + } + if (afterCallback) { + afterCallback(qtNode); + } + }, this); + if (node === this.root && afterCallback) { + afterCallback(node); + } + }, + /** + * Calculate mass of the each QuadNode in the tree. + */ + calculateMassAndCenter: function () { + this.visitNodeRecursive(null, null, function (node) { + node.updateMassAndCenter(); + }); + } +}); diff --git a/librerias/gantt/code/es-modules/modules/networkgraph/draggable-nodes.js b/librerias/gantt/code/es-modules/modules/networkgraph/draggable-nodes.js new file mode 100644 index 0000000..a24ee18 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/networkgraph/draggable-nodes.js @@ -0,0 +1,150 @@ +/* * + * + * Networkgraph series + * + * (c) 2010-2020 Paweł Fus + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +import H from '../../parts/Globals.js'; +import U from '../../parts/Utilities.js'; +var addEvent = U.addEvent; +var Chart = H.Chart; +/* eslint-disable no-invalid-this, valid-jsdoc */ +H.dragNodesMixin = { + /** + * Mouse down action, initializing drag&drop mode. + * + * @private + * @param {Highcharts.Point} point The point that event occured. + * @param {Highcharts.PointerEventObject} event Browser event, before normalization. + * @return {void} + */ + onMouseDown: function (point, event) { + var normalizedEvent = this.chart.pointer.normalize(event); + point.fixedPosition = { + chartX: normalizedEvent.chartX, + chartY: normalizedEvent.chartY, + plotX: point.plotX, + plotY: point.plotY + }; + point.inDragMode = true; + }, + /** + * Mouse move action during drag&drop. + * + * @private + * + * @param {global.Event} event Browser event, before normalization. + * @param {Highcharts.Point} point The point that event occured. + * + * @return {void} + */ + onMouseMove: function (point, event) { + if (point.fixedPosition && point.inDragMode) { + var series = this, chart = series.chart, normalizedEvent = chart.pointer.normalize(event), diffX = point.fixedPosition.chartX - normalizedEvent.chartX, diffY = point.fixedPosition.chartY - normalizedEvent.chartY, newPlotX, newPlotY; + // At least 5px to apply change (avoids simple click): + if (Math.abs(diffX) > 5 || Math.abs(diffY) > 5) { + newPlotX = point.fixedPosition.plotX - diffX; + newPlotY = point.fixedPosition.plotY - diffY; + if (chart.isInsidePlot(newPlotX, newPlotY)) { + point.plotX = newPlotX; + point.plotY = newPlotY; + point.hasDragged = true; + this.redrawHalo(point); + if (!series.layout.simulation) { + // When dragging nodes, we don't need to calculate + // initial positions and rendering nodes: + series.layout.setInitialRendering(false); + // Start new simulation: + if (!series.layout.enableSimulation) { + // Run only one iteration to speed things up: + series.layout.setMaxIterations(1); + } + else { + series.layout.start(); + } + series.chart.redraw(); + // Restore defaults: + series.layout.setInitialRendering(true); + } + else { + // Extend current simulation: + series.layout.resetSimulation(); + } + } + } + } + }, + /** + * Mouse up action, finalizing drag&drop. + * + * @private + * @param {Highcharts.Point} point The point that event occured. + * @return {void} + */ + onMouseUp: function (point, event) { + if (point.fixedPosition && point.hasDragged) { + if (this.layout.enableSimulation) { + this.layout.start(); + } + else { + this.chart.redraw(); + } + point.inDragMode = point.hasDragged = false; + if (!this.options.fixedDraggable) { + delete point.fixedPosition; + } + } + }, + // Draggable mode: + /** + * Redraw halo on mousemove during the drag&drop action. + * + * @private + * @param {Highcharts.Point} point The point that should show halo. + * @return {void} + */ + redrawHalo: function (point) { + if (point && this.halo) { + this.halo.attr({ + d: point.haloPath(this.options.states.hover.halo.size) + }); + } + } +}; +/* + * Draggable mode: + */ +addEvent(Chart, 'load', function () { + var chart = this, mousedownUnbinder, mousemoveUnbinder, mouseupUnbinder; + if (chart.container) { + mousedownUnbinder = addEvent(chart.container, 'mousedown', function (event) { + var point = chart.hoverPoint; + if (point && + point.series && + point.series.hasDraggableNodes && + point.series.options.draggable) { + point.series.onMouseDown(point, event); + mousemoveUnbinder = addEvent(chart.container, 'mousemove', function (e) { + return point && + point.series && + point.series.onMouseMove(point, e); + }); + mouseupUnbinder = addEvent(chart.container.ownerDocument, 'mouseup', function (e) { + mousemoveUnbinder(); + mouseupUnbinder(); + return point && + point.series && + point.series.onMouseUp(point, e); + }); + } + }); + } + addEvent(chart, 'destroy', function () { + mousedownUnbinder(); + }); +}); diff --git a/librerias/gantt/code/es-modules/modules/networkgraph/integrations.js b/librerias/gantt/code/es-modules/modules/networkgraph/integrations.js new file mode 100644 index 0000000..afafee2 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/networkgraph/integrations.js @@ -0,0 +1,362 @@ +/* * + * + * Networkgraph series + * + * (c) 2010-2020 Paweł Fus + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../../parts/Globals.js'; +/* eslint-disable no-invalid-this, valid-jsdoc */ +H.networkgraphIntegrations = { + verlet: { + /** + * Attractive force funtion. Can be replaced by API's + * `layoutAlgorithm.attractiveForce` + * + * @private + * @param {number} d current distance between two nodes + * @param {number} k expected distance between two nodes + * @return {number} force + */ + attractiveForceFunction: function (d, k) { + // Used in API: + return (k - d) / d; + }, + /** + * Repulsive force funtion. Can be replaced by API's + * `layoutAlgorithm.repulsiveForce` + * + * @private + * @param {number} d current distance between two nodes + * @param {number} k expected distance between two nodes + * @return {number} force + */ + repulsiveForceFunction: function (d, k) { + // Used in API: + return (k - d) / d * (k > d ? 1 : 0); // Force only for close nodes + }, + /** + * Barycenter force. Calculate and applys barycenter forces on the + * nodes. Making them closer to the center of their barycenter point. + * + * In Verlet integration, force is applied on a node immidatelly to it's + * `plotX` and `plotY` position. + * + * @private + * @return {void} + */ + barycenter: function () { + var gravitationalConstant = this.options.gravitationalConstant, xFactor = this.barycenter.xFactor, yFactor = this.barycenter.yFactor; + // To consider: + xFactor = (xFactor - (this.box.left + this.box.width) / 2) * + gravitationalConstant; + yFactor = (yFactor - (this.box.top + this.box.height) / 2) * + gravitationalConstant; + this.nodes.forEach(function (node) { + if (!node.fixedPosition) { + node.plotX -= + xFactor / node.mass / node.degree; + node.plotY -= + yFactor / node.mass / node.degree; + } + }); + }, + /** + * Repulsive force. + * + * In Verlet integration, force is applied on a node immidatelly to it's + * `plotX` and `plotY` position. + * + * @private + * @param {Highcharts.Point} node + * Node that should be translated by force. + * @param {number} force + * Force calcualated in `repulsiveForceFunction` + * @param {Highcharts.PositionObject} distance + * Distance between two nodes e.g. `{x, y}` + * @return {void} + */ + repulsive: function (node, force, distanceXY) { + var factor = force * this.diffTemperature / node.mass / node.degree; + if (!node.fixedPosition) { + node.plotX += distanceXY.x * factor; + node.plotY += distanceXY.y * factor; + } + }, + /** + * Attractive force. + * + * In Verlet integration, force is applied on a node immidatelly to it's + * `plotX` and `plotY` position. + * + * @private + * @param {Highcharts.Point} link + * Link that connects two nodes + * @param {number} force + * Force calcualated in `repulsiveForceFunction` + * @param {Highcharts.PositionObject} distance + * Distance between two nodes e.g. `{x, y}` + * @return {void} + */ + attractive: function (link, force, distanceXY) { + var massFactor = link.getMass(), translatedX = -distanceXY.x * force * this.diffTemperature, translatedY = -distanceXY.y * force * this.diffTemperature; + if (!link.fromNode.fixedPosition) { + link.fromNode.plotX -= + translatedX * massFactor.fromNode / link.fromNode.degree; + link.fromNode.plotY -= + translatedY * massFactor.fromNode / link.fromNode.degree; + } + if (!link.toNode.fixedPosition) { + link.toNode.plotX += + translatedX * massFactor.toNode / link.toNode.degree; + link.toNode.plotY += + translatedY * massFactor.toNode / link.toNode.degree; + } + }, + /** + * Integration method. + * + * In Verlet integration, forces are applied on node immidatelly to it's + * `plotX` and `plotY` position. + * + * Verlet without velocity: + * + * x(n+1) = 2 * x(n) - x(n-1) + A(T) * deltaT ^ 2 + * + * where: + * - x(n+1) - new position + * - x(n) - current position + * - x(n-1) - previous position + * + * Assuming A(t) = 0 (no acceleration) and (deltaT = 1) we get: + * + * x(n+1) = x(n) + (x(n) - x(n-1)) + * + * where: + * - (x(n) - x(n-1)) - position change + * + * TO DO: + * Consider Verlet with velocity to support additional + * forces. Or even Time-Corrected Verlet by Jonathan + * "lonesock" Dummer + * + * @private + * @param {Highcharts.NetworkgraphLayout} layout layout object + * @param {Highcharts.Point} node node that should be translated + * @return {void} + */ + integrate: function (layout, node) { + var friction = -layout.options.friction, maxSpeed = layout.options.maxSpeed, prevX = node.prevX, prevY = node.prevY, + // Apply friciton: + diffX = ((node.plotX + node.dispX - + prevX) * friction), diffY = ((node.plotY + node.dispY - + prevY) * friction), abs = Math.abs, signX = abs(diffX) / (diffX || 1), // need to deal with 0 + signY = abs(diffY) / (diffY || 1); + // Apply max speed: + diffX = signX * Math.min(maxSpeed, Math.abs(diffX)); + diffY = signY * Math.min(maxSpeed, Math.abs(diffY)); + // Store for the next iteration: + node.prevX = node.plotX + node.dispX; + node.prevY = node.plotY + node.dispY; + // Update positions: + node.plotX += diffX; + node.plotY += diffY; + node.temperature = layout.vectorLength({ + x: diffX, + y: diffY + }); + }, + /** + * Estiamte the best possible distance between two nodes, making graph + * readable. + * + * @private + * @param {Highcharts.NetworkgraphLayout} layout layout object + * @return {number} + */ + getK: function (layout) { + return Math.pow(layout.box.width * layout.box.height / layout.nodes.length, 0.5); + } + }, + euler: { + /** + * Attractive force funtion. Can be replaced by API's + * `layoutAlgorithm.attractiveForce` + * + * Other forces that can be used: + * + * basic, not recommended: + * `function (d, k) { return d / k }` + * + * @private + * @param {number} d current distance between two nodes + * @param {number} k expected distance between two nodes + * @return {number} force + */ + attractiveForceFunction: function (d, k) { + return d * d / k; + }, + /** + * Repulsive force funtion. Can be replaced by API's + * `layoutAlgorithm.repulsiveForce`. + * + * Other forces that can be used: + * + * basic, not recommended: + * `function (d, k) { return k / d }` + * + * standard: + * `function (d, k) { return k * k / d }` + * + * grid-variant: + * `function (d, k) { return k * k / d * (2 * k - d > 0 ? 1 : 0) }` + * + * @private + * @param {number} d current distance between two nodes + * @param {number} k expected distance between two nodes + * @return {number} force + */ + repulsiveForceFunction: function (d, k) { + return k * k / d; + }, + /** + * Barycenter force. Calculate and applys barycenter forces on the + * nodes. Making them closer to the center of their barycenter point. + * + * In Euler integration, force is stored in a node, not changing it's + * position. Later, in `integrate()` forces are applied on nodes. + * + * @private + * @return {void} + */ + barycenter: function () { + var gravitationalConstant = this.options.gravitationalConstant, xFactor = this.barycenter.xFactor, yFactor = this.barycenter.yFactor; + this.nodes.forEach(function (node) { + if (!node.fixedPosition) { + var degree = node.getDegree(), phi = degree * (1 + degree / 2); + node.dispX += ((xFactor - node.plotX) * + gravitationalConstant * + phi / node.degree); + node.dispY += ((yFactor - node.plotY) * + gravitationalConstant * + phi / node.degree); + } + }); + }, + /** + * Repulsive force. + * + * @private + * @param {Highcharts.Point} node + * Node that should be translated by force. + * @param {number} force + * Force calcualated in `repulsiveForceFunction` + * @param {Highcharts.PositionObject} distanceXY + * Distance between two nodes e.g. `{x, y}` + * @return {void} + */ + repulsive: function (node, force, distanceXY, distanceR) { + node.dispX += + (distanceXY.x / distanceR) * force / node.degree; + node.dispY += + (distanceXY.y / distanceR) * force / node.degree; + }, + /** + * Attractive force. + * + * In Euler integration, force is stored in a node, not changing it's + * position. Later, in `integrate()` forces are applied on nodes. + * + * @private + * @param {Highcharts.Point} link + * Link that connects two nodes + * @param {number} force + * Force calcualated in `repulsiveForceFunction` + * @param {Highcharts.PositionObject} distanceXY + * Distance between two nodes e.g. `{x, y}` + * @param {number} distanceR + * @return {void} + */ + attractive: function (link, force, distanceXY, distanceR) { + var massFactor = link.getMass(), translatedX = (distanceXY.x / distanceR) * force, translatedY = (distanceXY.y / distanceR) * force; + if (!link.fromNode.fixedPosition) { + link.fromNode.dispX -= + translatedX * massFactor.fromNode / link.fromNode.degree; + link.fromNode.dispY -= + translatedY * massFactor.fromNode / link.fromNode.degree; + } + if (!link.toNode.fixedPosition) { + link.toNode.dispX += + translatedX * massFactor.toNode / link.toNode.degree; + link.toNode.dispY += + translatedY * massFactor.toNode / link.toNode.degree; + } + }, + /** + * Integration method. + * + * In Euler integration, force were stored in a node, not changing it's + * position. Now, in the integrator method, we apply changes. + * + * Euler: + * + * Basic form: `x(n+1) = x(n) + v(n)` + * + * With Rengoild-Fruchterman we get: + * `x(n+1) = x(n) + v(n) / length(v(n)) * min(v(n), temperature(n))` + * where: + * - `x(n+1)`: next position + * - `x(n)`: current position + * - `v(n)`: velocity (comes from net force) + * - `temperature(n)`: current temperature + * + * Known issues: + * Oscillations when force vector has the same magnitude but opposite + * direction in the next step. Potentially solved by decreasing force by + * `v * (1 / node.degree)` + * + * Note: + * Actually `min(v(n), temperature(n))` replaces simulated annealing. + * + * @private + * @param {Highcharts.NetworkgraphLayout} layout + * Layout object + * @param {Highcharts.Point} node + * Node that should be translated + * @return {void} + */ + integrate: function (layout, node) { + var distanceR; + node.dispX += + node.dispX * layout.options.friction; + node.dispY += + node.dispY * layout.options.friction; + distanceR = node.temperature = layout.vectorLength({ + x: node.dispX, + y: node.dispY + }); + if (distanceR !== 0) { + node.plotX += (node.dispX / distanceR * + Math.min(Math.abs(node.dispX), layout.temperature)); + node.plotY += (node.dispY / distanceR * + Math.min(Math.abs(node.dispY), layout.temperature)); + } + }, + /** + * Estiamte the best possible distance between two nodes, making graph + * readable. + * + * @private + * @param {object} layout layout object + * @return {number} + */ + getK: function (layout) { + return Math.pow(layout.box.width * layout.box.height / layout.nodes.length, 0.3); + } + } +}; diff --git a/librerias/gantt/code/es-modules/modules/networkgraph/layouts.js b/librerias/gantt/code/es-modules/modules/networkgraph/layouts.js new file mode 100644 index 0000000..0d6c770 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/networkgraph/layouts.js @@ -0,0 +1,525 @@ +/* * + * + * Networkgraph series + * + * (c) 2010-2020 Paweł Fus + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../../parts/Globals.js'; +import U from '../../parts/Utilities.js'; +var addEvent = U.addEvent, merge = U.merge, clamp = U.clamp, defined = U.defined, extend = U.extend, isFunction = U.isFunction, pick = U.pick, setAnimation = U.setAnimation; +import './integrations.js'; +import './QuadTree.js'; +var Chart = H.Chart; +/* eslint-disable no-invalid-this, valid-jsdoc */ +H.layouts = { + 'reingold-fruchterman': function () { + } +}; +extend( +/** + * Reingold-Fruchterman algorithm from + * "Graph Drawing by Force-directed Placement" paper. + * @private + */ +H.layouts['reingold-fruchterman'].prototype, { + init: function (options) { + this.options = options; + this.nodes = []; + this.links = []; + this.series = []; + this.box = { + x: 0, + y: 0, + width: 0, + height: 0 + }; + this.setInitialRendering(true); + this.integration = + H.networkgraphIntegrations[options.integration]; + this.enableSimulation = options.enableSimulation; + this.attractiveForce = pick(options.attractiveForce, this.integration.attractiveForceFunction); + this.repulsiveForce = pick(options.repulsiveForce, this.integration.repulsiveForceFunction); + this.approximation = options.approximation; + }, + updateSimulation: function (enable) { + this.enableSimulation = pick(enable, this.options.enableSimulation); + }, + start: function () { + var layout = this, series = this.series, options = this.options; + layout.currentStep = 0; + layout.forces = series[0] && series[0].forces || []; + layout.chart = series[0] && series[0].chart; + if (layout.initialRendering) { + layout.initPositions(); + // Render elements in initial positions: + series.forEach(function (s) { + s.finishedAnimating = true; // #13169 + s.render(); + }); + } + layout.setK(); + layout.resetSimulation(options); + if (layout.enableSimulation) { + layout.step(); + } + }, + step: function () { + var layout = this, series = this.series, options = this.options; + // Algorithm: + layout.currentStep++; + if (layout.approximation === 'barnes-hut') { + layout.createQuadTree(); + layout.quadTree.calculateMassAndCenter(); + } + layout.forces.forEach(function (forceName) { + layout[forceName + 'Forces'](layout.temperature); + }); + // Limit to the plotting area and cool down: + layout.applyLimits(layout.temperature); + // Cool down the system: + layout.temperature = layout.coolDown(layout.startTemperature, layout.diffTemperature, layout.currentStep); + layout.prevSystemTemperature = layout.systemTemperature; + layout.systemTemperature = layout.getSystemTemperature(); + if (layout.enableSimulation) { + series.forEach(function (s) { + // Chart could be destroyed during the simulation + if (s.chart) { + s.render(); + } + }); + if (layout.maxIterations-- && + isFinite(layout.temperature) && + !layout.isStable()) { + if (layout.simulation) { + H.win.cancelAnimationFrame(layout.simulation); + } + layout.simulation = H.win.requestAnimationFrame(function () { + layout.step(); + }); + } + else { + layout.simulation = false; + } + } + }, + stop: function () { + if (this.simulation) { + H.win.cancelAnimationFrame(this.simulation); + } + }, + setArea: function (x, y, w, h) { + this.box = { + left: x, + top: y, + width: w, + height: h + }; + }, + setK: function () { + // Optimal distance between nodes, + // available space around the node: + this.k = this.options.linkLength || this.integration.getK(this); + }, + addElementsToCollection: function (elements, collection) { + elements.forEach(function (elem) { + if (collection.indexOf(elem) === -1) { + collection.push(elem); + } + }); + }, + removeElementFromCollection: function (element, collection) { + var index = collection.indexOf(element); + if (index !== -1) { + collection.splice(index, 1); + } + }, + clear: function () { + this.nodes.length = 0; + this.links.length = 0; + this.series.length = 0; + this.resetSimulation(); + }, + resetSimulation: function () { + this.forcedStop = false; + this.systemTemperature = 0; + this.setMaxIterations(); + this.setTemperature(); + this.setDiffTemperature(); + }, + setMaxIterations: function (maxIterations) { + this.maxIterations = pick(maxIterations, this.options.maxIterations); + }, + setTemperature: function () { + this.temperature = this.startTemperature = + Math.sqrt(this.nodes.length); + }, + setDiffTemperature: function () { + this.diffTemperature = this.startTemperature / + (this.options.maxIterations + 1); + }, + setInitialRendering: function (enable) { + this.initialRendering = enable; + }, + createQuadTree: function () { + this.quadTree = new H.QuadTree(this.box.left, this.box.top, this.box.width, this.box.height); + this.quadTree.insertNodes(this.nodes); + }, + initPositions: function () { + var initialPositions = this.options.initialPositions; + if (isFunction(initialPositions)) { + initialPositions.call(this); + this.nodes.forEach(function (node) { + if (!defined(node.prevX)) { + node.prevX = node.plotX; + } + if (!defined(node.prevY)) { + node.prevY = node.plotY; + } + node.dispX = 0; + node.dispY = 0; + }); + } + else if (initialPositions === 'circle') { + this.setCircularPositions(); + } + else { + this.setRandomPositions(); + } + }, + setCircularPositions: function () { + var box = this.box, nodes = this.nodes, nodesLength = nodes.length + 1, angle = 2 * Math.PI / nodesLength, rootNodes = nodes.filter(function (node) { + return node.linksTo.length === 0; + }), sortedNodes = [], visitedNodes = {}, radius = this.options.initialPositionRadius; + /** + * @private + */ + function addToNodes(node) { + node.linksFrom.forEach(function (link) { + if (!visitedNodes[link.toNode.id]) { + visitedNodes[link.toNode.id] = true; + sortedNodes.push(link.toNode); + addToNodes(link.toNode); + } + }); + } + // Start with identified root nodes an sort the nodes by their + // hierarchy. In trees, this ensures that branches don't cross + // eachother. + rootNodes.forEach(function (rootNode) { + sortedNodes.push(rootNode); + addToNodes(rootNode); + }); + // Cyclic tree, no root node found + if (!sortedNodes.length) { + sortedNodes = nodes; + // Dangling, cyclic trees + } + else { + nodes.forEach(function (node) { + if (sortedNodes.indexOf(node) === -1) { + sortedNodes.push(node); + } + }); + } + // Initial positions are laid out along a small circle, appearing + // as a cluster in the middle + sortedNodes.forEach(function (node, index) { + node.plotX = node.prevX = pick(node.plotX, box.width / 2 + radius * Math.cos(index * angle)); + node.plotY = node.prevY = pick(node.plotY, box.height / 2 + radius * Math.sin(index * angle)); + node.dispX = 0; + node.dispY = 0; + }); + }, + setRandomPositions: function () { + var box = this.box, nodes = this.nodes, nodesLength = nodes.length + 1; + /** + * Return a repeatable, quasi-random number based on an integer + * input. For the initial positions + * @private + */ + function unrandom(n) { + var rand = n * n / Math.PI; + rand = rand - Math.floor(rand); + return rand; + } + // Initial positions: + nodes.forEach(function (node, index) { + node.plotX = node.prevX = pick(node.plotX, box.width * unrandom(index)); + node.plotY = node.prevY = pick(node.plotY, box.height * unrandom(nodesLength + index)); + node.dispX = 0; + node.dispY = 0; + }); + }, + force: function (name) { + this.integration[name].apply(this, Array.prototype.slice.call(arguments, 1)); + }, + barycenterForces: function () { + this.getBarycenter(); + this.force('barycenter'); + }, + getBarycenter: function () { + var systemMass = 0, cx = 0, cy = 0; + this.nodes.forEach(function (node) { + cx += node.plotX * node.mass; + cy += node.plotY * node.mass; + systemMass += node.mass; + }); + this.barycenter = { + x: cx, + y: cy, + xFactor: cx / systemMass, + yFactor: cy / systemMass + }; + return this.barycenter; + }, + barnesHutApproximation: function (node, quadNode) { + var layout = this, distanceXY = layout.getDistXY(node, quadNode), distanceR = layout.vectorLength(distanceXY), goDeeper, force; + if (node !== quadNode && distanceR !== 0) { + if (quadNode.isInternal) { + // Internal node: + if (quadNode.boxSize / distanceR < + layout.options.theta && + distanceR !== 0) { + // Treat as an external node: + force = layout.repulsiveForce(distanceR, layout.k); + layout.force('repulsive', node, force * quadNode.mass, distanceXY, distanceR); + goDeeper = false; + } + else { + // Go deeper: + goDeeper = true; + } + } + else { + // External node, direct force: + force = layout.repulsiveForce(distanceR, layout.k); + layout.force('repulsive', node, force * quadNode.mass, distanceXY, distanceR); + } + } + return goDeeper; + }, + repulsiveForces: function () { + var layout = this; + if (layout.approximation === 'barnes-hut') { + layout.nodes.forEach(function (node) { + layout.quadTree.visitNodeRecursive(null, function (quadNode) { + return layout.barnesHutApproximation(node, quadNode); + }); + }); + } + else { + layout.nodes.forEach(function (node) { + layout.nodes.forEach(function (repNode) { + var force, distanceR, distanceXY; + if ( + // Node can not repulse itself: + node !== repNode && + // Only close nodes affect each other: + // layout.getDistR(node, repNode) < 2 * k && + // Not dragged: + !node.fixedPosition) { + distanceXY = layout.getDistXY(node, repNode); + distanceR = layout.vectorLength(distanceXY); + if (distanceR !== 0) { + force = layout.repulsiveForce(distanceR, layout.k); + layout.force('repulsive', node, force * repNode.mass, distanceXY, distanceR); + } + } + }); + }); + } + }, + attractiveForces: function () { + var layout = this, distanceXY, distanceR, force; + layout.links.forEach(function (link) { + if (link.fromNode && link.toNode) { + distanceXY = layout.getDistXY(link.fromNode, link.toNode); + distanceR = layout.vectorLength(distanceXY); + if (distanceR !== 0) { + force = layout.attractiveForce(distanceR, layout.k); + layout.force('attractive', link, force, distanceXY, distanceR); + } + } + }); + }, + applyLimits: function () { + var layout = this, nodes = layout.nodes; + nodes.forEach(function (node) { + if (node.fixedPosition) { + return; + } + layout.integration.integrate(layout, node); + layout.applyLimitBox(node, layout.box); + // Reset displacement: + node.dispX = 0; + node.dispY = 0; + }); + }, + /** + * External box that nodes should fall. When hitting an edge, node + * should stop or bounce. + * @private + */ + applyLimitBox: function (node, box) { + var radius = node.radius; + /* + TO DO: Consider elastic collision instead of stopping. + o' means end position when hitting plotting area edge: + + - "inelastic": + o + \ + ______ + | o' + | \ + | \ + + - "elastic"/"bounced": + o + \ + ______ + | ^ + | / \ + |o' \ + + Euler sample: + if (plotX < 0) { + plotX = 0; + dispX *= -1; + } + + if (plotX > box.width) { + plotX = box.width; + dispX *= -1; + } + + */ + // Limit X-coordinates: + node.plotX = clamp(node.plotX, box.left + radius, box.width - radius); + // Limit Y-coordinates: + node.plotY = clamp(node.plotY, box.top + radius, box.height - radius); + }, + /** + * From "A comparison of simulated annealing cooling strategies" by + * Nourani and Andresen work. + * @private + */ + coolDown: function (temperature, temperatureStep, currentStep) { + // Logarithmic: + /* + return Math.sqrt(this.nodes.length) - + Math.log( + currentStep * layout.diffTemperature + ); + */ + // Exponential: + /* + var alpha = 0.1; + layout.temperature = Math.sqrt(layout.nodes.length) * + Math.pow(alpha, layout.diffTemperature); + */ + // Linear: + return temperature - temperatureStep * currentStep; + }, + isStable: function () { + return Math.abs(this.systemTemperature - + this.prevSystemTemperature) < 0.00001 || this.temperature <= 0; + }, + getSystemTemperature: function () { + return this.nodes.reduce(function (value, node) { + return value + node.temperature; + }, 0); + }, + vectorLength: function (vector) { + return Math.sqrt(vector.x * vector.x + vector.y * vector.y); + }, + getDistR: function (nodeA, nodeB) { + var distance = this.getDistXY(nodeA, nodeB); + return this.vectorLength(distance); + }, + getDistXY: function (nodeA, nodeB) { + var xDist = nodeA.plotX - nodeB.plotX, yDist = nodeA.plotY - nodeB.plotY; + return { + x: xDist, + y: yDist, + absX: Math.abs(xDist), + absY: Math.abs(yDist) + }; + } +}); +/* ************************************************************************** * + * Multiple series support: + * ************************************************************************** */ +// Clear previous layouts +addEvent(Chart, 'predraw', function () { + if (this.graphLayoutsLookup) { + this.graphLayoutsLookup.forEach(function (layout) { + layout.stop(); + }); + } +}); +addEvent(Chart, 'render', function () { + var systemsStable, afterRender = false; + /** + * @private + */ + function layoutStep(layout) { + if (layout.maxIterations-- && + isFinite(layout.temperature) && + !layout.isStable() && + !layout.enableSimulation) { + // Hook similar to build-in addEvent, but instead of + // creating whole events logic, use just a function. + // It's faster which is important for rAF code. + // Used e.g. in packed-bubble series for bubble radius + // calculations + if (layout.beforeStep) { + layout.beforeStep(); + } + layout.step(); + systemsStable = false; + afterRender = true; + } + } + if (this.graphLayoutsLookup) { + setAnimation(false, this); + // Start simulation + this.graphLayoutsLookup.forEach(function (layout) { + layout.start(); + }); + // Just one sync step, to run different layouts similar to + // async mode. + while (!systemsStable) { + systemsStable = true; + this.graphLayoutsLookup.forEach(layoutStep); + } + if (afterRender) { + this.series.forEach(function (s) { + if (s && s.layout) { + s.render(); + } + }); + } + } +}); +// disable simulation before print if enabled +addEvent(Chart, 'beforePrint', function () { + this.graphLayoutsLookup.forEach(function (layout) { + layout.updateSimulation(false); + }); + this.redraw(); +}); +// re-enable simulation after print +addEvent(Chart, 'afterPrint', function () { + this.graphLayoutsLookup.forEach(function (layout) { + // return to default simulation + layout.updateSimulation(); + }); + this.redraw(); +}); diff --git a/librerias/gantt/code/es-modules/modules/networkgraph/networkgraph.src.js b/librerias/gantt/code/es-modules/modules/networkgraph/networkgraph.src.js new file mode 100644 index 0000000..06ddafa --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/networkgraph/networkgraph.src.js @@ -0,0 +1,1087 @@ +/* * + * + * Networkgraph series + * + * (c) 2010-2020 Paweł Fus + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../../parts/Globals.js'; +/** + * Formatter callback function. + * + * @callback Highcharts.SeriesNetworkgraphDataLabelsFormatterCallbackFunction + * + * @param {Highcharts.SeriesNetworkgraphDataLabelsFormatterContextObject|Highcharts.PointLabelObject} this + * Data label context to format + * + * @return {string} + * Formatted data label text + */ +/** + * Context for the formatter function. + * + * @interface Highcharts.SeriesNetworkgraphDataLabelsFormatterContextObject + * @extends Highcharts.PointLabelObject + * @since 7.0.0 + */ /** +* The color of the node. +* @name Highcharts.SeriesNetworkgraphDataLabelsFormatterContextObject#color +* @type {Highcharts.ColorString} +* @since 7.0.0 +*/ /** +* The point (node) object. The node name, if defined, is available through +* `this.point.name`. Arrays: `this.point.linksFrom` and `this.point.linksTo` +* contains all nodes connected to this point. +* @name Highcharts.SeriesNetworkgraphDataLabelsFormatterContextObject#point +* @type {Highcharts.Point} +* @since 7.0.0 +*/ /** +* The ID of the node. +* @name Highcharts.SeriesNetworkgraphDataLabelsFormatterContextObject#key +* @type {string} +* @since 7.0.0 +*/ +''; // detach doclets above +import Point from '../../parts/Point.js'; +import U from '../../parts/Utilities.js'; +var addEvent = U.addEvent, css = U.css, defined = U.defined, pick = U.pick, seriesType = U.seriesType; +import '../../parts/Options.js'; +import '../../mixins/nodes.js'; +import './layouts.js'; +import './draggable-nodes.js'; +var seriesTypes = H.seriesTypes, Series = H.Series, dragNodesMixin = H.dragNodesMixin; +/** + * @private + * @class + * @name Highcharts.seriesTypes.networkgraph + * + * @extends Highcharts.Series + */ +seriesType('networkgraph', 'line', +/** + * A networkgraph is a type of relationship chart, where connnections + * (links) attracts nodes (points) and other nodes repulse each other. + * + * @extends plotOptions.line + * @product highcharts + * @sample highcharts/demo/network-graph/ + * Networkgraph + * @since 7.0.0 + * @excluding boostThreshold, animation, animationLimit, connectEnds, + * colorAxis, colorKey, connectNulls, dragDrop, + * getExtremesFromAll, label, linecap, negativeColor, + * pointInterval, pointIntervalUnit, pointPlacement, + * pointStart, softThreshold, stack, stacking, step, + * threshold, xAxis, yAxis, zoneAxis, dataSorting + * @requires modules/networkgraph + * @optionparent plotOptions.networkgraph + */ +{ + stickyTracking: false, + /** + * @ignore-option + * @private + */ + inactiveOtherPoints: true, + marker: { + enabled: true, + states: { + /** + * The opposite state of a hover for a single point node. + * Applied to all not connected nodes to the hovered one. + * + * @declare Highcharts.PointStatesInactiveOptionsObject + */ + inactive: { + /** + * Opacity of inactive markers. + */ + opacity: 0.3, + /** + * Animation when not hovering over the node. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + */ + animation: { + /** @internal */ + duration: 50 + } + } + } + }, + states: { + /** + * The opposite state of a hover for a single point link. Applied + * to all links that are not comming from the hovered node. + * + * @declare Highcharts.SeriesStatesInactiveOptionsObject + */ + inactive: { + /** + * Opacity of inactive links. + */ + linkOpacity: 0.3, + /** + * Animation when not hovering over the node. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + */ + animation: { + /** @internal */ + duration: 50 + } + } + }, + /** + * @sample highcharts/series-networkgraph/link-datalabels + * Networkgraph with labels on links + * @sample highcharts/series-networkgraph/textpath-datalabels + * Networkgraph with labels around nodes + * @sample highcharts/series-networkgraph/link-datalabels + * Data labels moved into the nodes + * @sample highcharts/series-networkgraph/link-datalabels + * Data labels moved under the links + * + * @declare Highcharts.SeriesNetworkgraphDataLabelsOptionsObject + * + * @private + */ + dataLabels: { + /** + * The + * [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) + * specifying what to show for _node_ in the networkgraph. In v7.0 + * defaults to `{key}`, since v7.1 defaults to `undefined` and + * `formatter` is used instead. + * + * @type {string} + * @since 7.0.0 + * @apioption plotOptions.networkgraph.dataLabels.format + */ + // eslint-disable-next-line valid-jsdoc + /** + * Callback JavaScript function to format the data label for a node. + * Note that if a `format` is defined, the format takes precedence + * and the formatter is ignored. + * + * @type {Highcharts.SeriesNetworkgraphDataLabelsFormatterCallbackFunction} + * @since 7.0.0 + */ + formatter: function () { + return this.key; + }, + /** + * The + * [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) + * specifying what to show for _links_ in the networkgraph. + * (Default: `undefined`) + * + * @type {string} + * @since 7.1.0 + * @apioption plotOptions.networkgraph.dataLabels.linkFormat + */ + // eslint-disable-next-line valid-jsdoc + /** + * Callback to format data labels for _links_ in the sankey diagram. + * The `linkFormat` option takes precedence over the + * `linkFormatter`. + * + * @type {Highcharts.SeriesNetworkgraphDataLabelsFormatterCallbackFunction} + * @since 7.1.0 + */ + linkFormatter: function () { + return (this.point.fromNode.name + + '
' + + this.point.toNode.name); + }, + /** + * Options for a _link_ label text which should follow link + * connection. Border and background are disabled for a label that + * follows a path. + * + * **Note:** Only SVG-based renderer supports this option. Setting + * `useHTML` to true will disable this option. + * + * @extends plotOptions.networkgraph.dataLabels.textPath + * @since 7.1.0 + */ + linkTextPath: { + enabled: true + }, + textPath: { + enabled: false + }, + style: { + transition: 'opacity 2000ms' + } + }, + /** + * Link style options + * @private + */ + link: { + /** + * A name for the dash style to use for links. + * + * @type {string} + * @apioption plotOptions.networkgraph.link.dashStyle + */ + /** + * Color of the link between two nodes. + */ + color: 'rgba(100, 100, 100, 0.5)', + /** + * Width (px) of the link between two nodes. + */ + width: 1 + }, + /** + * Flag to determine if nodes are draggable or not. + * @private + */ + draggable: true, + layoutAlgorithm: { + /** + * Repulsive force applied on a node. Passed are two arguments: + * - `d` - which is current distance between two nodes + * - `k` - which is desired distance between two nodes + * + * In `verlet` integration, defaults to: + * `function (d, k) { return (k - d) / d * (k > d ? 1 : 0) }` + * + * @see [layoutAlgorithm.integration](#series.networkgraph.layoutAlgorithm.integration) + * + * @sample highcharts/series-networkgraph/forces/ + * Custom forces with Euler integration + * @sample highcharts/series-networkgraph/cuboids/ + * Custom forces with Verlet integration + * + * @type {Function} + * @default function (d, k) { return k * k / d; } + * @apioption plotOptions.networkgraph.layoutAlgorithm.repulsiveForce + */ + /** + * Attraction force applied on a node which is conected to another + * node by a link. Passed are two arguments: + * - `d` - which is current distance between two nodes + * - `k` - which is desired distance between two nodes + * + * In `verlet` integration, defaults to: + * `function (d, k) { return (k - d) / d; }` + * + * @see [layoutAlgorithm.integration](#series.networkgraph.layoutAlgorithm.integration) + * + * @sample highcharts/series-networkgraph/forces/ + * Custom forces with Euler integration + * @sample highcharts/series-networkgraph/cuboids/ + * Custom forces with Verlet integration + * + * @type {Function} + * @default function (d, k) { return k * k / d; } + * @apioption plotOptions.networkgraph.layoutAlgorithm.attractiveForce + */ + /** + * Ideal length (px) of the link between two nodes. When not + * defined, length is calculated as: + * `Math.pow(availableWidth * availableHeight / nodesLength, 0.4);` + * + * Note: Because of the algorithm specification, length of each link + * might be not exactly as specified. + * + * @sample highcharts/series-networkgraph/styled-links/ + * Numerical values + * + * @type {number} + * @apioption plotOptions.networkgraph.layoutAlgorithm.linkLength + */ + /** + * Initial layout algorithm for positioning nodes. Can be one of + * built-in options ("circle", "random") or a function where + * positions should be set on each node (`this.nodes`) as + * `node.plotX` and `node.plotY` + * + * @sample highcharts/series-networkgraph/initial-positions/ + * Initial positions with callback + * + * @type {"circle"|"random"|Function} + */ + initialPositions: 'circle', + /** + * When `initialPositions` are set to 'circle', + * `initialPositionRadius` is a distance from the center of circle, + * in which nodes are created. + * + * @type {number} + * @default 1 + * @since 7.1.0 + */ + initialPositionRadius: 1, + /** + * Experimental. Enables live simulation of the algorithm + * implementation. All nodes are animated as the forces applies on + * them. + * + * @sample highcharts/demo/network-graph/ + * Live simulation enabled + */ + enableSimulation: false, + /** + * Barnes-Hut approximation only. + * Deteremines when distance between cell and node is small enough + * to caculate forces. Value of `theta` is compared directly with + * quotient `s / d`, where `s` is the size of the cell, and `d` is + * distance between center of cell's mass and currently compared + * node. + * + * @see [layoutAlgorithm.approximation](#series.networkgraph.layoutAlgorithm.approximation) + * + * @since 7.1.0 + */ + theta: 0.5, + /** + * Verlet integration only. + * Max speed that node can get in one iteration. In terms of + * simulation, it's a maximum translation (in pixels) that node can + * move (in both, x and y, dimensions). While `friction` is applied + * on all nodes, max speed is applied only for nodes that move very + * fast, for example small or disconnected ones. + * + * @see [layoutAlgorithm.integration](#series.networkgraph.layoutAlgorithm.integration) + * @see [layoutAlgorithm.friction](#series.networkgraph.layoutAlgorithm.friction) + * + * @since 7.1.0 + */ + maxSpeed: 10, + /** + * Approximation used to calculate repulsive forces affecting nodes. + * By default, when calculateing net force, nodes are compared + * against each other, which gives O(N^2) complexity. Using + * Barnes-Hut approximation, we decrease this to O(N log N), but the + * resulting graph will have different layout. Barnes-Hut + * approximation divides space into rectangles via quad tree, where + * forces exerted on nodes are calculated directly for nearby cells, + * and for all others, cells are treated as a separate node with + * center of mass. + * + * @see [layoutAlgorithm.theta](#series.networkgraph.layoutAlgorithm.theta) + * + * @sample highcharts/series-networkgraph/barnes-hut-approximation/ + * A graph with Barnes-Hut approximation + * + * @type {string} + * @validvalue ["barnes-hut", "none"] + * @since 7.1.0 + */ + approximation: 'none', + /** + * Type of the algorithm used when positioning nodes. + * + * @type {string} + * @validvalue ["reingold-fruchterman"] + */ + type: 'reingold-fruchterman', + /** + * Integration type. Available options are `'euler'` and `'verlet'`. + * Integration determines how forces are applied on particles. In + * Euler integration, force is applied direct as + * `newPosition += velocity;`. + * In Verlet integration, new position is based on a previous + * posittion without velocity: + * `newPosition += previousPosition - newPosition`. + * + * Note that different integrations give different results as forces + * are different. + * + * In Highcharts v7.0.x only `'euler'` integration was supported. + * + * @sample highcharts/series-networkgraph/integration-comparison/ + * Comparison of Verlet and Euler integrations + * + * @type {string} + * @validvalue ["euler", "verlet"] + * @since 7.1.0 + */ + integration: 'euler', + /** + * Max number of iterations before algorithm will stop. In general, + * algorithm should find positions sooner, but when rendering huge + * number of nodes, it is recommended to increase this value as + * finding perfect graph positions can require more time. + */ + maxIterations: 1000, + /** + * Gravitational const used in the barycenter force of the + * algorithm. + * + * @sample highcharts/series-networkgraph/forces/ + * Custom forces with Euler integration + */ + gravitationalConstant: 0.0625, + /** + * Friction applied on forces to prevent nodes rushing to fast to + * the desired positions. + */ + friction: -0.981 + }, + showInLegend: false +}, { + /** + * Array of internal forces. Each force should be later defined in + * integrations.js. + * @private + */ + forces: ['barycenter', 'repulsive', 'attractive'], + hasDraggableNodes: true, + drawGraph: null, + isCartesian: false, + requireSorting: false, + directTouch: true, + noSharedTooltip: true, + pointArrayMap: ['from', 'to'], + trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'], + drawTracker: H.TrackerMixin.drawTrackerPoint, + // Animation is run in `series.simulation`. + animate: null, + buildKDTree: H.noop, + /** + * Create a single node that holds information on incoming and outgoing + * links. + * @private + */ + createNode: H.NodesMixin.createNode, + destroy: function () { + this.layout.removeElementFromCollection(this, this.layout.series); + H.NodesMixin.destroy.call(this); + }, + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Extend init with base event, which should stop simulation during + * update. After data is updated, `chart.render` resumes the simulation. + * @private + */ + init: function () { + Series.prototype.init.apply(this, arguments); + addEvent(this, 'updatedData', function () { + if (this.layout) { + this.layout.stop(); + } + }); + return this; + }, + /** + * Extend generatePoints by adding the nodes, which are Point objects + * but pushed to the this.nodes array. + * @private + */ + generatePoints: function () { + var node, i; + H.NodesMixin.generatePoints.apply(this, arguments); + // In networkgraph, it's fine to define stanalone nodes, create + // them: + if (this.options.nodes) { + this.options.nodes.forEach(function (nodeOptions) { + if (!this.nodeLookup[nodeOptions.id]) { + this.nodeLookup[nodeOptions.id] = + this.createNode(nodeOptions.id); + } + }, this); + } + for (i = this.nodes.length - 1; i >= 0; i--) { + node = this.nodes[i]; + node.degree = node.getDegree(); + node.radius = pick(node.marker && node.marker.radius, this.options.marker && this.options.marker.radius, 0); + // If node exists, but it's not available in nodeLookup, + // then it's leftover from previous runs (e.g. setData) + if (!this.nodeLookup[node.id]) { + node.remove(); + } + } + this.data.forEach(function (link) { + link.formatPrefix = 'link'; + }); + this.indexateNodes(); + }, + /** + * In networkgraph, series.points refers to links, + * but series.nodes refers to actual points. + * @private + */ + getPointsCollection: function () { + return this.nodes || []; + }, + /** + * Set index for each node. Required for proper `node.update()`. + * Note that links are indexated out of the box in `generatePoints()`. + * + * @private + */ + indexateNodes: function () { + this.nodes.forEach(function (node, index) { + node.index = index; + }); + }, + /** + * Extend the default marker attribs by using a non-rounded X position, + * otherwise the nodes will jump from pixel to pixel which looks a bit + * jaggy when approaching equilibrium. + * @private + */ + markerAttribs: function (point, state) { + var attribs = Series.prototype.markerAttribs.call(this, point, state); + // series.render() is called before initial positions are set: + if (!defined(point.plotY)) { + attribs.y = 0; + } + attribs.x = (point.plotX || 0) - (attribs.width / 2 || 0); + return attribs; + }, + /** + * Run pre-translation and register nodes&links to the deffered layout. + * @private + */ + translate: function () { + if (!this.processedXData) { + this.processData(); + } + this.generatePoints(); + this.deferLayout(); + this.nodes.forEach(function (node) { + // Draw the links from this node + node.isInside = true; + node.linksFrom.forEach(function (point) { + point.shapeType = 'path'; + // Pass test in drawPoints + point.y = 1; + }); + }); + }, + /** + * Defer the layout. + * Each series first registers all nodes and links, then layout + * calculates all nodes positions and calls `series.render()` in every + * simulation step. + * + * Note: + * Animation is done through `requestAnimationFrame` directly, without + * `Highcharts.animate()` use. + * @private + */ + deferLayout: function () { + var layoutOptions = this.options.layoutAlgorithm, graphLayoutsStorage = this.chart.graphLayoutsStorage, graphLayoutsLookup = this.chart.graphLayoutsLookup, chartOptions = this.chart.options.chart, layout; + if (!this.visible) { + return; + } + if (!graphLayoutsStorage) { + this.chart.graphLayoutsStorage = graphLayoutsStorage = {}; + this.chart.graphLayoutsLookup = graphLayoutsLookup = []; + } + layout = graphLayoutsStorage[layoutOptions.type]; + if (!layout) { + layoutOptions.enableSimulation = + !defined(chartOptions.forExport) ? + layoutOptions.enableSimulation : + !chartOptions.forExport; + graphLayoutsStorage[layoutOptions.type] = layout = + new H.layouts[layoutOptions.type](); + layout.init(layoutOptions); + graphLayoutsLookup.splice(layout.index, 0, layout); + } + this.layout = layout; + layout.setArea(0, 0, this.chart.plotWidth, this.chart.plotHeight); + layout.addElementsToCollection([this], layout.series); + layout.addElementsToCollection(this.nodes, layout.nodes); + layout.addElementsToCollection(this.points, layout.links); + }, + /** + * Extend the render function to also render this.nodes together with + * the points. + * @private + */ + render: function () { + var series = this, points = series.points, hoverPoint = series.chart.hoverPoint, dataLabels = []; + // Render markers: + series.points = series.nodes; + seriesTypes.line.prototype.render.call(this); + series.points = points; + points.forEach(function (point) { + if (point.fromNode && point.toNode) { + point.renderLink(); + point.redrawLink(); + } + }); + if (hoverPoint && hoverPoint.series === series) { + series.redrawHalo(hoverPoint); + } + if (series.chart.hasRendered && + !series.options.dataLabels.allowOverlap) { + series.nodes.concat(series.points).forEach(function (node) { + if (node.dataLabel) { + dataLabels.push(node.dataLabel); + } + }); + series.chart.hideOverlappingLabels(dataLabels); + } + }, + // Networkgraph has two separate collecions of nodes and lines, render + // dataLabels for both sets: + drawDataLabels: function () { + var textPath = this.options.dataLabels.textPath; + // Render node labels: + Series.prototype.drawDataLabels.apply(this, arguments); + // Render link labels: + this.points = this.data; + this.options.dataLabels.textPath = + this.options.dataLabels.linkTextPath; + Series.prototype.drawDataLabels.apply(this, arguments); + // Restore nodes + this.points = this.nodes; + this.options.dataLabels.textPath = textPath; + }, + // Return the presentational attributes. + pointAttribs: function (point, state) { + // By default, only `selected` state is passed on + var pointState = state || point && point.state || 'normal', attribs = Series.prototype.pointAttribs.call(this, point, pointState), stateOptions = this.options.states[pointState]; + if (point && !point.isNode) { + attribs = point.getLinkAttributes(); + // For link, get prefixed names: + if (stateOptions) { + attribs = { + // TO DO: API? + stroke: stateOptions.linkColor || attribs.stroke, + dashstyle: (stateOptions.linkDashStyle || attribs.dashstyle), + opacity: pick(stateOptions.linkOpacity, attribs.opacity), + 'stroke-width': stateOptions.linkColor || + attribs['stroke-width'] + }; + } + } + return attribs; + }, + // Draggable mode: + /** + * Redraw halo on mousemove during the drag&drop action. + * @private + * @param {Highcharts.Point} point The point that should show halo. + */ + redrawHalo: dragNodesMixin.redrawHalo, + /** + * Mouse down action, initializing drag&drop mode. + * @private + * @param {global.Event} event Browser event, before normalization. + * @param {Highcharts.Point} point The point that event occured. + */ + onMouseDown: dragNodesMixin.onMouseDown, + /** + * Mouse move action during drag&drop. + * @private + * @param {global.Event} event Browser event, before normalization. + * @param {Highcharts.Point} point The point that event occured. + */ + onMouseMove: dragNodesMixin.onMouseMove, + /** + * Mouse up action, finalizing drag&drop. + * @private + * @param {Highcharts.Point} point The point that event occured. + */ + onMouseUp: dragNodesMixin.onMouseUp, + /** + * When state should be passed down to all points, concat nodes and + * links and apply this state to all of them. + * @private + */ + setState: function (state, inherit) { + if (inherit) { + this.points = this.nodes.concat(this.data); + Series.prototype.setState.apply(this, arguments); + this.points = this.data; + } + else { + Series.prototype.setState.apply(this, arguments); + } + // If simulation is done, re-render points with new states: + if (!this.layout.simulation && !state) { + this.render(); + } + } +}, { + setState: H.NodesMixin.setNodeState, + /** + * Basic `point.init()` and additional styles applied when + * `series.draggable` is enabled. + * @private + */ + init: function () { + Point.prototype.init.apply(this, arguments); + if (this.series.options.draggable && + !this.series.chart.styledMode) { + addEvent(this, 'mouseOver', function () { + css(this.series.chart.container, { cursor: 'move' }); + }); + addEvent(this, 'mouseOut', function () { + css(this.series.chart.container, { cursor: 'default' }); + }); + } + return this; + }, + /** + * Return degree of a node. If node has no connections, it still has + * deg=1. + * @private + * @return {number} + */ + getDegree: function () { + var deg = this.isNode ? + this.linksFrom.length + this.linksTo.length : + 0; + return deg === 0 ? 1 : deg; + }, + // Links: + /** + * Get presentational attributes of link connecting two nodes. + * @private + * @return {Highcharts.SVGAttributes} + */ + getLinkAttributes: function () { + var linkOptions = this.series.options.link, pointOptions = this.options; + return { + 'stroke-width': pick(pointOptions.width, linkOptions.width), + stroke: (pointOptions.color || linkOptions.color), + dashstyle: (pointOptions.dashStyle || linkOptions.dashStyle), + opacity: pick(pointOptions.opacity, linkOptions.opacity, 1) + }; + }, + /** + * Render link and add it to the DOM. + * @private + */ + renderLink: function () { + var attribs; + if (!this.graphic) { + this.graphic = this.series.chart.renderer + .path(this.getLinkPath()) + .add(this.series.group); + if (!this.series.chart.styledMode) { + attribs = this.series.pointAttribs(this); + this.graphic.attr(attribs); + (this.dataLabels || []).forEach(function (label) { + if (label) { + label.attr({ + opacity: attribs.opacity + }); + } + }); + } + } + }, + /** + * Redraw link's path. + * @private + */ + redrawLink: function () { + var path = this.getLinkPath(), attribs; + if (this.graphic) { + this.shapeArgs = { + d: path + }; + if (!this.series.chart.styledMode) { + attribs = this.series.pointAttribs(this); + this.graphic.attr(attribs); + (this.dataLabels || []).forEach(function (label) { + if (label) { + label.attr({ + opacity: attribs.opacity + }); + } + }); + } + this.graphic.animate(this.shapeArgs); + // Required for dataLabels + var start = path[0]; + var end = path[1]; + if (start[0] === 'M' && end[0] === 'L') { + this.plotX = (start[1] + end[1]) / 2; + this.plotY = (start[2] + end[2]) / 2; + } + } + }, + /** + * Get mass fraction applied on two nodes connected to each other. By + * default, when mass is equal to `1`, mass fraction for both nodes + * equal to 0.5. + * @private + * @return {Highcharts.Dictionary} + * For example `{ fromNode: 0.5, toNode: 0.5 }` + */ + getMass: function () { + var m1 = this.fromNode.mass, m2 = this.toNode.mass, sum = m1 + m2; + return { + fromNode: 1 - m1 / sum, + toNode: 1 - m2 / sum + }; + }, + /** + * Get link path connecting two nodes. + * @private + * @return {Array} + * Path: `['M', x, y, 'L', x, y]` + */ + getLinkPath: function () { + var left = this.fromNode, right = this.toNode; + // Start always from left to the right node, to prevent rendering + // labels upside down + if (left.plotX > right.plotX) { + left = this.toNode; + right = this.fromNode; + } + return [ + ['M', left.plotX || 0, left.plotY || 0], + ['L', right.plotX || 0, right.plotY || 0] + ]; + /* + IDEA: different link shapes? + return [ + 'M', + from.plotX, + from.plotY, + 'Q', + (to.plotX + from.plotX) / 2, + (to.plotY + from.plotY) / 2 + 15, + to.plotX, + to.plotY + ];*/ + }, + isValid: function () { + return !this.isNode || defined(this.id); + }, + /** + * Common method for removing points and nodes in networkgraph. To + * remove `link`, use `series.data[index].remove()`. To remove `node` + * with all connections, use `series.nodes[index].remove()`. + * @private + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call. When + * doing more operations on the chart, for example running + * `point.remove()` in a loop, it is best practice to set + * `redraw` to false and call `chart.redraw()` after. + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=false] + * Whether to apply animation, and optionally animation + * configuration. + * @return {void} + */ + remove: function (redraw, animation) { + var point = this, series = point.series, nodesOptions = series.options.nodes || [], index, i = nodesOptions.length; + // For nodes, remove all connected links: + if (point.isNode) { + // Temporary disable series.points array, because + // Series.removePoint() modifies it + series.points = []; + // Remove link from all nodes collections: + [] + .concat(point.linksFrom) + .concat(point.linksTo) + .forEach(function (linkFromTo) { + // Incoming links + index = linkFromTo.fromNode.linksFrom.indexOf(linkFromTo); + if (index > -1) { + linkFromTo.fromNode.linksFrom.splice(index, 1); + } + // Outcoming links + index = linkFromTo.toNode.linksTo.indexOf(linkFromTo); + if (index > -1) { + linkFromTo.toNode.linksTo.splice(index, 1); + } + // Remove link from data/points collections + Series.prototype.removePoint.call(series, series.data.indexOf(linkFromTo), false, false); + }); + // Restore points array, after links are removed + series.points = series.data.slice(); + // Proceed with removing node. It's similar to + // Series.removePoint() method, but doesn't modify other arrays + series.nodes.splice(series.nodes.indexOf(point), 1); + // Remove node options from config + while (i--) { + if (nodesOptions[i].id === point.options.id) { + series.options.nodes.splice(i, 1); + break; + } + } + if (point) { + point.destroy(); + } + // Run redraw if requested + series.isDirty = true; + series.isDirtyData = true; + if (redraw) { + series.chart.redraw(redraw); + } + } + else { + series.removePoint(series.data.indexOf(point), redraw, animation); + } + }, + /** + * Destroy point. If it's a node, remove all links coming out of this + * node. Then remove point from the layout. + * @private + * @return {void} + */ + destroy: function () { + if (this.isNode) { + this.linksFrom.concat(this.linksTo).forEach(function (link) { + // Removing multiple nodes at the same time + // will try to remove link between nodes twice + if (link.destroyElements) { + link.destroyElements(); + } + }); + } + this.series.layout.removeElementFromCollection(this, this.series.layout[this.isNode ? 'nodes' : 'links']); + return Point.prototype.destroy.apply(this, arguments); + } +}); +/** + * A `networkgraph` series. If the [type](#series.networkgraph.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.networkgraph + * @excluding boostThreshold, animation, animationLimit, connectEnds, + * connectNulls, dragDrop, getExtremesFromAll, label, linecap, + * negativeColor, pointInterval, pointIntervalUnit, + * pointPlacement, pointStart, softThreshold, stack, stacking, + * step, threshold, xAxis, yAxis, zoneAxis, dataSorting + * @product highcharts + * @requires modules/networkgraph + * @apioption series.networkgraph + */ +/** + * An array of data points for the series. For the `networkgraph` series type, + * points can be given in the following way: + * + * An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.area.turboThreshold), this option is not available. + * + * ```js + * data: [{ + * from: 'Category1', + * to: 'Category2' + * }, { + * from: 'Category1', + * to: 'Category3' + * }] + * ``` + * + * @type {Array} + * @extends series.line.data + * @excluding drilldown,marker,x,y,draDrop + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * @product highcharts + * @apioption series.networkgraph.data + */ +/** + * @type {Highcharts.SeriesNetworkgraphDataLabelsOptionsObject|Array} + * @product highcharts + * @apioption series.networkgraph.data.dataLabels + */ +/** + * The node that the link runs from. + * + * @type {string} + * @product highcharts + * @apioption series.networkgraph.data.from + */ +/** + * The node that the link runs to. + * + * @type {string} + * @product highcharts + * @apioption series.networkgraph.data.to + */ +/** + * A collection of options for the individual nodes. The nodes in a + * networkgraph diagram are auto-generated instances of `Highcharts.Point`, + * but options can be applied here and linked by the `id`. + * + * @sample highcharts/series-networkgraph/data-options/ + * Networkgraph diagram with node options + * + * @type {Array<*>} + * @product highcharts + * @apioption series.networkgraph.nodes + */ +/** + * The id of the auto-generated node, refering to the `from` or `to` setting of + * the link. + * + * @type {string} + * @product highcharts + * @apioption series.networkgraph.nodes.id + */ +/** + * The color of the auto generated node. + * + * @type {Highcharts.ColorString} + * @product highcharts + * @apioption series.networkgraph.nodes.color + */ +/** + * The color index of the auto generated node, especially for use in styled + * mode. + * + * @type {number} + * @product highcharts + * @apioption series.networkgraph.nodes.colorIndex + */ +/** + * The name to display for the node in data labels and tooltips. Use this when + * the name is different from the `id`. Where the id must be unique for each + * node, this is not necessary for the name. + * + * @sample highcharts/series-networkgraph/data-options/ + * Networkgraph diagram with node options + * + * @type {string} + * @product highcharts + * @apioption series.networkgraph.nodes.name + */ +/** + * Mass of the node. By default, each node has mass equal to it's marker radius + * . Mass is used to determine how two connected nodes should affect + * each other: + * + * Attractive force is multiplied by the ratio of two connected + * nodes; if a big node has weights twice as the small one, then the small one + * will move towards the big one twice faster than the big one to the small one + * . + * + * @sample highcharts/series-networkgraph/ragdoll/ + * Mass determined by marker.radius + * + * @type {number} + * @product highcharts + * @apioption series.networkgraph.nodes.mass + */ +/** + * Individual data label for each node. The options are the same as + * the ones for [series.networkgraph.dataLabels](#series.networkgraph.dataLabels). + * + * @type {Highcharts.SeriesNetworkgraphDataLabelsOptionsObject|Array} + * + * @apioption series.networkgraph.nodes.dataLabels + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/modules/no-data-to-display.src.js b/librerias/gantt/code/es-modules/modules/no-data-to-display.src.js new file mode 100644 index 0000000..4450e2f --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/no-data-to-display.src.js @@ -0,0 +1,187 @@ +/* * + * + * Plugin for displaying a message when there is no data visible in chart. + * + * (c) 2010-2020 Highsoft AS + * + * Author: Oystein Moseng + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, extend = U.extend; +import '../parts/Series.js'; +import '../parts/Options.js'; +var chartPrototype = H.Chart.prototype, defaultOptions = H.getOptions(); +// Add language option +extend(defaultOptions.lang, +/** + * @optionparent lang + */ +{ + /** + * The text to display when the chart contains no data. + * + * @see [noData](#noData) + * + * @sample highcharts/no-data-to-display/no-data-line + * No-data text + * + * @since 3.0.8 + * @product highcharts highstock + * @requires modules/no-data-to-display + */ + noData: 'No data to display' +}); +// Add default display options for message +/** + * Options for displaying a message like "No data to display". + * This feature requires the file no-data-to-display.js to be loaded in the + * page. The actual text to display is set in the lang.noData option. + * + * @sample highcharts/no-data-to-display/no-data-line + * Line chart with no-data module + * @sample highcharts/no-data-to-display/no-data-pie + * Pie chart with no-data module + * + * @product highcharts highstock gantt + * @requires modules/no-data-to-display + * @optionparent noData + */ +defaultOptions.noData = { + /** + * An object of additional SVG attributes for the no-data label. + * + * @type {Highcharts.SVGAttributes} + * @since 3.0.8 + * @product highcharts highstock gantt + * @apioption noData.attr + */ + attr: { + zIndex: 1 + }, + /** + * Whether to insert the label as HTML, or as pseudo-HTML rendered with + * SVG. + * + * @type {boolean} + * @default false + * @since 4.1.10 + * @product highcharts highstock gantt + * @apioption noData.useHTML + */ + /** + * The position of the no-data label, relative to the plot area. + * + * @type {Highcharts.AlignObject} + * @since 3.0.8 + */ + position: { + /** + * Horizontal offset of the label, in pixels. + */ + x: 0, + /** + * Vertical offset of the label, in pixels. + */ + y: 0, + /** + * Horizontal alignment of the label. + * + * @type {Highcharts.AlignValue} + */ + align: 'center', + /** + * Vertical alignment of the label. + * + * @type {Highcharts.VerticalAlignValue} + */ + verticalAlign: 'middle' + }, + /** + * CSS styles for the no-data label. + * + * @sample highcharts/no-data-to-display/no-data-line + * Styled no-data text + * + * @type {Highcharts.CSSObject} + */ + style: { + /** @ignore */ + fontWeight: 'bold', + /** @ignore */ + fontSize: '12px', + /** @ignore */ + color: '#666666' + } +}; +/** + * Display a no-data message. + * @private + * @function Highcharts.Chart#showNoData + * @param {string} [str] + * An optional message to show in place of the default one + * @return {void} + * @requires modules/no-data-to-display + */ +chartPrototype.showNoData = function (str) { + var chart = this, options = chart.options, text = str || (options && options.lang.noData), noDataOptions = options && options.noData; + if (!chart.noDataLabel && chart.renderer) { + chart.noDataLabel = chart.renderer + .label(text, 0, 0, null, null, null, noDataOptions.useHTML, null, 'no-data'); + if (!chart.styledMode) { + chart.noDataLabel + .attr(noDataOptions.attr) + .css(noDataOptions.style); + } + chart.noDataLabel.add(); + chart.noDataLabel.align(extend(chart.noDataLabel.getBBox(), noDataOptions.position), false, 'plotBox'); + } +}; +/** + * Hide no-data message. + * + * @private + * @function Highcharts.Chart#hideNoData + * @return {void} + * @requires modules/no-data-to-display + */ +chartPrototype.hideNoData = function () { + var chart = this; + if (chart.noDataLabel) { + chart.noDataLabel = chart.noDataLabel.destroy(); + } +}; +/** + * Returns true if there are data points within the plot area now. + * + * @private + * @function Highcharts.Chart#hasData + * @return {boolean|undefined} + * True, if there are data points. + * @requires modules/no-data-to-display + */ +chartPrototype.hasData = function () { + var chart = this, series = chart.series || [], i = series.length; + while (i--) { + if (series[i].hasData() && !series[i].options.isInternal) { + return true; + } + } + return chart.loadingShown; // #4588 +}; +/* eslint-disable no-invalid-this */ +// Add event listener to handle automatic show or hide no-data message. +addEvent(H.Chart, 'render', function handleNoData() { + if (this.hasData()) { + this.hideNoData(); + } + else { + this.showNoData(); + } +}); diff --git a/librerias/gantt/code/es-modules/modules/offline-exporting.src.js b/librerias/gantt/code/es-modules/modules/offline-exporting.src.js new file mode 100644 index 0000000..7129360 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/offline-exporting.src.js @@ -0,0 +1,591 @@ +/* * + * + * Client side exporting module + * + * (c) 2015 Torstein Honsi / Oystein Moseng + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +/* global MSBlobBuilder */ +import Highcharts from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var extend = U.extend; +import '../parts/Chart.js'; +import '../parts/Options.js'; +import '../mixins/download-url.js'; +var addEvent = Highcharts.addEvent, merge = Highcharts.merge, win = Highcharts.win, nav = win.navigator, doc = win.document, domurl = win.URL || win.webkitURL || win, isMSBrowser = /Edge\/|Trident\/|MSIE /.test(nav.userAgent), +// Milliseconds to defer image load event handlers to offset IE bug +loadEventDeferDelay = isMSBrowser ? 150 : 0; +// Dummy object so we can reuse our canvas-tools.js without errors +Highcharts.CanVGRenderer = {}; +/* eslint-disable valid-jsdoc */ +/** + * Downloads a script and executes a callback when done. + * + * @private + * @function getScript + * @param {string} scriptLocation + * @param {Function} callback + * @return {void} + */ +function getScript(scriptLocation, callback) { + var head = doc.getElementsByTagName('head')[0], script = doc.createElement('script'); + script.type = 'text/javascript'; + script.src = scriptLocation; + script.onload = callback; + script.onerror = function () { + Highcharts.error('Error loading script ' + scriptLocation); + }; + head.appendChild(script); +} +/** + * Get blob URL from SVG code. Falls back to normal data URI. + * + * @private + * @function Highcharts.svgToDataURL + * @param {string} svg + * @return {string} + */ +Highcharts.svgToDataUrl = function (svg) { + // Webkit and not chrome + var webKit = (nav.userAgent.indexOf('WebKit') > -1 && + nav.userAgent.indexOf('Chrome') < 0); + try { + // Safari requires data URI since it doesn't allow navigation to blob + // URLs. Firefox has an issue with Blobs and internal references, + // leading to gradients not working using Blobs (#4550) + if (!webKit && nav.userAgent.toLowerCase().indexOf('firefox') < 0) { + return domurl.createObjectURL(new win.Blob([svg], { + type: 'image/svg+xml;charset-utf-16' + })); + } + } + catch (e) { + // Ignore + } + return 'data:image/svg+xml;charset=UTF-8,' + encodeURIComponent(svg); +}; +/** + * Get data:URL from image URL. Pass in callbacks to handle results. + * + * @private + * @function Highcharts.imageToDataUrl + * + * @param {string} imageURL + * + * @param {string} imageType + * + * @param {*} callbackArgs + * callbackArgs is used only by callbacks. + * + * @param {number} scale + * + * @param {Function} successCallback + * Receives four arguments: imageURL, imageType, callbackArgs, and scale. + * + * @param {Function} taintedCallback + * Receives four arguments: imageURL, imageType, callbackArgs, and scale. + * + * @param {Function} noCanvasSupportCallback + * Receives four arguments: imageURL, imageType, callbackArgs, and scale. + * + * @param {Function} failedLoadCallback + * Receives four arguments: imageURL, imageType, callbackArgs, and scale. + * + * @param {Function} [finallyCallback] + * finallyCallback is always called at the end of the process. All + * callbacks receive four arguments: imageURL, imageType, callbackArgs, + * and scale. + * + * @return {void} + */ +Highcharts.imageToDataUrl = function (imageURL, imageType, callbackArgs, scale, successCallback, taintedCallback, noCanvasSupportCallback, failedLoadCallback, finallyCallback) { + var img = new win.Image(), taintedHandler, loadHandler = function () { + setTimeout(function () { + var canvas = doc.createElement('canvas'), ctx = canvas.getContext && canvas.getContext('2d'), dataURL; + try { + if (!ctx) { + noCanvasSupportCallback(imageURL, imageType, callbackArgs, scale); + } + else { + canvas.height = img.height * scale; + canvas.width = img.width * scale; + ctx.drawImage(img, 0, 0, canvas.width, canvas.height); + // Now we try to get the contents of the canvas. + try { + dataURL = canvas.toDataURL(imageType); + successCallback(dataURL, imageType, callbackArgs, scale); + } + catch (e) { + taintedHandler(imageURL, imageType, callbackArgs, scale); + } + } + } + finally { + if (finallyCallback) { + finallyCallback(imageURL, imageType, callbackArgs, scale); + } + } + // IE bug where image is not always ready despite calling load + // event. + }, loadEventDeferDelay); + }, + // Image load failed (e.g. invalid URL) + errorHandler = function () { + failedLoadCallback(imageURL, imageType, callbackArgs, scale); + if (finallyCallback) { + finallyCallback(imageURL, imageType, callbackArgs, scale); + } + }; + // This is called on load if the image drawing to canvas failed with a + // security error. We retry the drawing with crossOrigin set to Anonymous. + taintedHandler = function () { + img = new win.Image(); + taintedHandler = taintedCallback; + // Must be set prior to loading image source + img.crossOrigin = 'Anonymous'; + img.onload = loadHandler; + img.onerror = errorHandler; + img.src = imageURL; + }; + img.onload = loadHandler; + img.onerror = errorHandler; + img.src = imageURL; +}; +/* eslint-enable valid-jsdoc */ +/** + * Get data URL to an image of an SVG and call download on it options object: + * + * - **filename:** Name of resulting downloaded file without extension. Default + * is `chart`. + * + * - **type:** File type of resulting download. Default is `image/png`. + * + * - **scale:** Scaling factor of downloaded image compared to source. Default + * is `1`. + * + * - **libURL:** URL pointing to location of dependency scripts to download on + * demand. Default is the exporting.libURL option of the global Highcharts + * options pointing to our server. + * + * @function Highcharts.downloadSVGLocal + * + * @param {string} svg + * The generated SVG + * + * @param {Highcharts.ExportingOptions} options + * The exporting options + * + * @param {Function} failCallback + * The callback function in case of errors + * + * @param {Function} [successCallback] + * The callback function in case of success + * + * @return {void} + */ +Highcharts.downloadSVGLocal = function (svg, options, failCallback, successCallback) { + var svgurl, blob, objectURLRevoke = true, finallyHandler, libURL = (options.libURL || Highcharts.getOptions().exporting.libURL), dummySVGContainer = doc.createElement('div'), imageType = options.type || 'image/png', filename = ((options.filename || 'chart') + + '.' + + (imageType === 'image/svg+xml' ? 'svg' : imageType.split('/')[1])), scale = options.scale || 1; + // Allow libURL to end with or without fordward slash + libURL = libURL.slice(-1) !== '/' ? libURL + '/' : libURL; + /* eslint-disable valid-jsdoc */ + /** + * @private + */ + function svgToPdf(svgElement, margin) { + var width = svgElement.width.baseVal.value + 2 * margin, height = svgElement.height.baseVal.value + 2 * margin, pdf = new win.jsPDF(// eslint-disable-line new-cap + 'l', 'pt', [width, height]); + // Workaround for #7090, hidden elements were drawn anyway. It comes + // down to https://github.com/yWorks/svg2pdf.js/issues/28. Check this + // later. + [].forEach.call(svgElement.querySelectorAll('*[visibility="hidden"]'), function (node) { + node.parentNode.removeChild(node); + }); + win.svg2pdf(svgElement, pdf, { removeInvalid: true }); + return pdf.output('datauristring'); + } + /** + * @private + * @return {void} + */ + function downloadPDF() { + dummySVGContainer.innerHTML = svg; + var textElements = dummySVGContainer.getElementsByTagName('text'), titleElements, svgData, + // Copy style property to element from parents if it's not there. + // Searches up hierarchy until it finds prop, or hits the chart + // container. + setStylePropertyFromParents = function (el, propName) { + var curParent = el; + while (curParent && curParent !== dummySVGContainer) { + if (curParent.style[propName]) { + el.style[propName] = + curParent.style[propName]; + break; + } + curParent = curParent.parentNode; + } + }; + // Workaround for the text styling. Making sure it does pick up settings + // for parent elements. + [].forEach.call(textElements, function (el) { + // Workaround for the text styling. making sure it does pick up the + // root element + ['font-family', 'font-size'].forEach(function (property) { + setStylePropertyFromParents(el, property); + }); + el.style['font-family'] = (el.style['font-family'] && + el.style['font-family'].split(' ').splice(-1)); + // Workaround for plotband with width, removing title from text + // nodes + titleElements = el.getElementsByTagName('title'); + [].forEach.call(titleElements, function (titleElement) { + el.removeChild(titleElement); + }); + }); + svgData = svgToPdf(dummySVGContainer.firstChild, 0); + try { + Highcharts.downloadURL(svgData, filename); + if (successCallback) { + successCallback(); + } + } + catch (e) { + failCallback(e); + } + } + /* eslint-enable valid-jsdoc */ + // Initiate download depending on file type + if (imageType === 'image/svg+xml') { + // SVG download. In this case, we want to use Microsoft specific Blob if + // available + try { + if (typeof nav.msSaveOrOpenBlob !== 'undefined') { + blob = new MSBlobBuilder(); + blob.append(svg); + svgurl = blob.getBlob('image/svg+xml'); + } + else { + svgurl = Highcharts.svgToDataUrl(svg); + } + Highcharts.downloadURL(svgurl, filename); + if (successCallback) { + successCallback(); + } + } + catch (e) { + failCallback(e); + } + } + else if (imageType === 'application/pdf') { + if (win.jsPDF && win.svg2pdf) { + downloadPDF(); + } + else { + // Must load pdf libraries first. // Don't destroy the object URL + // yet since we are doing things asynchronously. A cleaner solution + // would be nice, but this will do for now. + objectURLRevoke = true; + getScript(libURL + 'jspdf.js', function () { + getScript(libURL + 'svg2pdf.js', function () { + downloadPDF(); + }); + }); + } + } + else { + // PNG/JPEG download - create bitmap from SVG + svgurl = Highcharts.svgToDataUrl(svg); + finallyHandler = function () { + try { + domurl.revokeObjectURL(svgurl); + } + catch (e) { + // Ignore + } + }; + // First, try to get PNG by rendering on canvas + Highcharts.imageToDataUrl(svgurl, imageType, {}, scale, function (imageURL) { + // Success + try { + Highcharts.downloadURL(imageURL, filename); + if (successCallback) { + successCallback(); + } + } + catch (e) { + failCallback(e); + } + }, function () { + // Failed due to tainted canvas + // Create new and untainted canvas + var canvas = doc.createElement('canvas'), ctx = canvas.getContext('2d'), imageWidth = svg.match(/^]*width\s*=\s*\"?(\d+)\"?[^>]*>/)[1] * scale, imageHeight = svg.match(/^]*height\s*=\s*\"?(\d+)\"?[^>]*>/)[1] * scale, downloadWithCanVG = function () { + ctx.drawSvg(svg, 0, 0, imageWidth, imageHeight); + try { + Highcharts.downloadURL(nav.msSaveOrOpenBlob ? + canvas.msToBlob() : + canvas.toDataURL(imageType), filename); + if (successCallback) { + successCallback(); + } + } + catch (e) { + failCallback(e); + } + finally { + finallyHandler(); + } + }; + canvas.width = imageWidth; + canvas.height = imageHeight; + if (win.canvg) { + // Use preloaded canvg + downloadWithCanVG(); + } + else { + // Must load canVG first. // Don't destroy the object URL + // yet since we are doing things asynchronously. A cleaner + // solution would be nice, but this will do for now. + objectURLRevoke = true; + // Get RGBColor.js first, then canvg + getScript(libURL + 'rgbcolor.js', function () { + getScript(libURL + 'canvg.js', function () { + downloadWithCanVG(); + }); + }); + } + }, + // No canvas support + failCallback, + // Failed to load image + failCallback, + // Finally + function () { + if (objectURLRevoke) { + finallyHandler(); + } + }); + } +}; +/* eslint-disable valid-jsdoc */ +/** + * Get SVG of chart prepared for client side export. This converts embedded + * images in the SVG to data URIs. It requires the regular exporting module. The + * options and chartOptions arguments are passed to the getSVGForExport + * function. + * + * @private + * @function Highcharts.Chart#getSVGForLocalExport + * @param {Highcharts.ExportingOptions} options + * @param {Highcharts.Options} chartOptions + * @param {Function} failCallback + * @param {Function} successCallback + * @return {void} + */ +Highcharts.Chart.prototype.getSVGForLocalExport = function (options, chartOptions, failCallback, successCallback) { + var chart = this, images, imagesEmbedded = 0, chartCopyContainer, chartCopyOptions, el, i, l, href, + // After grabbing the SVG of the chart's copy container we need to do + // sanitation on the SVG + sanitize = function (svg) { + return chart.sanitizeSVG(svg, chartCopyOptions); + }, + // When done with last image we have our SVG + checkDone = function () { + if (imagesEmbedded === images.length) { + successCallback(sanitize(chartCopyContainer.innerHTML)); + } + }, + // Success handler, we converted image to base64! + embeddedSuccess = function (imageURL, imageType, callbackArgs) { + ++imagesEmbedded; + // Change image href in chart copy + callbackArgs.imageElement.setAttributeNS('http://www.w3.org/1999/xlink', 'href', imageURL); + checkDone(); + }; + // Hook into getSVG to get a copy of the chart copy's container (#8273) + chart.unbindGetSVG = addEvent(chart, 'getSVG', function (e) { + chartCopyOptions = e.chartCopy.options; + chartCopyContainer = e.chartCopy.container.cloneNode(true); + }); + // Trigger hook to get chart copy + chart.getSVGForExport(options, chartOptions); + images = chartCopyContainer.getElementsByTagName('image'); + try { + // If there are no images to embed, the SVG is okay now. + if (!images.length) { + // Use SVG of chart copy + successCallback(sanitize(chartCopyContainer.innerHTML)); + return; + } + // Go through the images we want to embed + for (i = 0, l = images.length; i < l; ++i) { + el = images[i]; + href = el.getAttributeNS('http://www.w3.org/1999/xlink', 'href'); + if (href) { + Highcharts.imageToDataUrl(href, 'image/png', { imageElement: el }, options.scale, embeddedSuccess, + // Tainted canvas + failCallback, + // No canvas support + failCallback, + // Failed to load source + failCallback); + // Hidden, boosted series have blank href (#10243) + } + else { + ++imagesEmbedded; + el.parentNode.removeChild(el); + checkDone(); + } + } + } + catch (e) { + failCallback(e); + } + // Clean up + chart.unbindGetSVG(); +}; +/* eslint-enable valid-jsdoc */ +/** + * Exporting and offline-exporting modules required. Export a chart to an image + * locally in the user's browser. + * + * @function Highcharts.Chart#exportChartLocal + * + * @param {Highcharts.ExportingOptions} [exportingOptions] + * Exporting options, the same as in + * {@link Highcharts.Chart#exportChart}. + * + * @param {Highcharts.Options} [chartOptions] + * Additional chart options for the exported chart. For example a + * different background color can be added here, or `dataLabels` + * for export only. + * + * @return {void} + * + * @requires modules/exporting + */ +Highcharts.Chart.prototype.exportChartLocal = function (exportingOptions, chartOptions) { + var chart = this, options = Highcharts.merge(chart.options.exporting, exportingOptions), fallbackToExportServer = function (err) { + if (options.fallbackToExportServer === false) { + if (options.error) { + options.error(options, err); + } + else { + Highcharts.error(28, true); // Fallback disabled + } + } + else { + chart.exportChart(options); + } + }, svgSuccess = function (svg) { + // If SVG contains foreignObjects all exports except SVG will fail, + // as both CanVG and svg2pdf choke on this. Gracefully fall back. + if (svg.indexOf(' -1 && + options.type !== 'image/svg+xml') { + fallbackToExportServer('Image type not supported' + + 'for charts with embedded HTML'); + } + else { + Highcharts.downloadSVGLocal(svg, extend({ filename: chart.getFilename() }, options), fallbackToExportServer); + } + }, + // Return true if the SVG contains images with external data. With the + // boost module there are `image` elements with encoded PNGs, these are + // supported by svg2pdf and should pass (#10243). + hasExternalImages = function () { + return [].some.call(chart.container.getElementsByTagName('image'), function (image) { + var href = image.getAttribute('href'); + return href !== '' && href.indexOf('data:') !== 0; + }); + }; + // If we are on IE and in styled mode, add a whitelist to the renderer for + // inline styles that we want to pass through. There are so many styles by + // default in IE that we don't want to blacklist them all. + if (isMSBrowser && chart.styledMode) { + Highcharts.SVGRenderer.prototype.inlineWhitelist = [ + /^blockSize/, + /^border/, + /^caretColor/, + /^color/, + /^columnRule/, + /^columnRuleColor/, + /^cssFloat/, + /^cursor/, + /^fill$/, + /^fillOpacity/, + /^font/, + /^inlineSize/, + /^length/, + /^lineHeight/, + /^opacity/, + /^outline/, + /^parentRule/, + /^rx$/, + /^ry$/, + /^stroke/, + /^textAlign/, + /^textAnchor/, + /^textDecoration/, + /^transform/, + /^vectorEffect/, + /^visibility/, + /^x$/, + /^y$/ + ]; + } + // Always fall back on: + // - MS browsers: Embedded images JPEG/PNG, or any PDF + // - Embedded images and PDF + if ((isMSBrowser && + (options.type === 'application/pdf' || + chart.container.getElementsByTagName('image').length && + options.type !== 'image/svg+xml')) || (options.type === 'application/pdf' && + hasExternalImages())) { + fallbackToExportServer('Image type not supported for this chart/browser.'); + return; + } + chart.getSVGForLocalExport(options, chartOptions, fallbackToExportServer, svgSuccess); +}; +// Extend the default options to use the local exporter logic +merge(true, Highcharts.getOptions().exporting, { + libURL: 'https://code.highcharts.com/8.1.0/lib/', + // When offline-exporting is loaded, redefine the menu item definitions + // related to download. + menuItemDefinitions: { + downloadPNG: { + textKey: 'downloadPNG', + onclick: function () { + this.exportChartLocal(); + } + }, + downloadJPEG: { + textKey: 'downloadJPEG', + onclick: function () { + this.exportChartLocal({ + type: 'image/jpeg' + }); + } + }, + downloadSVG: { + textKey: 'downloadSVG', + onclick: function () { + this.exportChartLocal({ + type: 'image/svg+xml' + }); + } + }, + downloadPDF: { + textKey: 'downloadPDF', + onclick: function () { + this.exportChartLocal({ + type: 'application/pdf' + }); + } + } + } +}); diff --git a/librerias/gantt/code/es-modules/modules/oldie-polyfills.src.js b/librerias/gantt/code/es-modules/modules/oldie-polyfills.src.js new file mode 100644 index 0000000..2fc1b58 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/oldie-polyfills.src.js @@ -0,0 +1,144 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * Simple polyfills for array functions in old IE browsers (6, 7 and 8) in + * Highcharts v7+. These polyfills are sufficient for Highcharts to work, but + * for fully compatible polyfills, see MDN. + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +/* global document */ +'use strict'; +/* eslint-disable no-extend-native */ +if (!Array.prototype.forEach) { + Array.prototype.forEach = function (fn, thisArg) { + var i = 0, len = this.length; + for (; i < len; i++) { + if (typeof this[i] !== 'undefined' && // added check + fn.call(thisArg, this[i], i, this) === false) { + return i; + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function (fn + // @todo support optional ctx + ) { + var results = [], i = 0, len = this.length; + for (; i < len; i++) { + results[i] = fn.call(this[i], this[i], i, this); + } + return results; + }; +} +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (member, fromIndex) { + var arr = this, // #8874 + len, i = fromIndex || 0; // #8346 + if (arr) { + len = arr.length; + for (; i < len; i++) { + if (arr[i] === member) { + return i; + } + } + } + return -1; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function (fn + // @todo support optional ctx + ) { + var ret = [], i = 0, length = this.length; + for (; i < length; i++) { + if (fn(this[i], i)) { + ret.push(this[i]); + } + } + return ret; + }; +} +if (!Array.prototype.some) { + Array.prototype.some = function (fn, thisArg) { + var i = 0, len = this.length; + for (; i < len; i++) { + if (fn.call(thisArg, this[i], i, this) === true) { + return true; + } + } + return false; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function (func, initialValue) { + var context = this, i = arguments.length > 1 ? 0 : 1, accumulator = arguments.length > 1 ? initialValue : this[0], len = this.length; + for (; i < len; ++i) { + accumulator = func.call(context, accumulator, this[i], i, this); + } + return accumulator; + }; +} +if (!Function.prototype.bind) { + Function.prototype.bind = function () { + var thatFunc = this; + var thatArg = arguments[0]; + var args = Array.prototype.slice.call(arguments, 1); + if (typeof thatFunc !== 'function') { + // closest thing possible to the ECMAScript 5 + // internal IsCallable function + throw new TypeError('Function.prototype.bind - ' + + 'what is trying to be bound is not callable'); + } + return function () { + var funcArgs = args.concat(Array.prototype.slice.call(arguments)); + return thatFunc.apply(thatArg, funcArgs); + }; + }; +} +if (!Object.keys) { + Object.keys = function (obj) { + var result = [], prop; + for (prop in obj) { + if (Object.hasOwnProperty.call(obj, prop)) { + result.push(prop); + } + } + return result; + }; +} +// Add a getElementsByClassName function if the browser doesn't have one +// Limitation: only works with one class name +// Copyright: Eike Send https://eike.se/nd +// License: MIT License +if (!document.getElementsByClassName) { + document.getElementsByClassName = function (search) { + var d = document, elements, pattern, i, results = []; + if (d.querySelectorAll) { // IE8 + return d.querySelectorAll('.' + search); + } + if (d.evaluate) { // IE6, IE7 + pattern = './/*[contains(concat(\' \', @class, \' \'), \' ' + + search + ' \')]'; + elements = d.evaluate(pattern, d, null, 0, null); + while ((i = elements.iterateNext())) { + results.push(i); + } + } + else { + elements = d.getElementsByTagName('*'); + pattern = new RegExp('(^|\\s)' + search + '(\\s|$)'); + for (i = 0; i < elements.length; i++) { + if (pattern.test(elements[i].className)) { + results.push(elements[i]); + } + } + } + return results; + }; +} diff --git a/librerias/gantt/code/es-modules/modules/oldie.src.js b/librerias/gantt/code/es-modules/modules/oldie.src.js new file mode 100644 index 0000000..321709c --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/oldie.src.js @@ -0,0 +1,1235 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * Support for old IE browsers (6, 7 and 8) in Highcharts v6+. + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import Color from '../parts/Color.js'; +var color = Color.parse; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, createElement = U.createElement, css = U.css, defined = U.defined, discardElement = U.discardElement, erase = U.erase, extend = U.extend, extendClass = U.extendClass, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, merge = U.merge, offset = U.offset, pick = U.pick, pInt = U.pInt, uniqueKey = U.uniqueKey; +import '../parts/SvgRenderer.js'; +var VMLRenderer, VMLRendererExtension, VMLElement, Chart = H.Chart, deg2rad = H.deg2rad, doc = H.doc, noop = H.noop, svg = H.svg, SVGElement = H.SVGElement, SVGRenderer = H.SVGRenderer, win = H.win; +/** + * Path to the pattern image required by VML browsers in order to + * draw radial gradients. + * + * @type {string} + * @default http://code.highcharts.com/{version}/gfx/vml-radial-gradient.png + * @since 2.3.0 + * @requires modules/oldie + * @apioption global.VMLRadialGradientURL + */ +H.getOptions().global.VMLRadialGradientURL = + 'http://code.highcharts.com/8.1.0/gfx/vml-radial-gradient.png'; +// Utilites +if (doc && !doc.defaultView) { + H.getStyle = U.getStyle = function (el, prop) { + var val, alias = { + width: 'clientWidth', + height: 'clientHeight' + }[prop]; + if (el.style[prop]) { + return pInt(el.style[prop]); + } + if (prop === 'opacity') { + prop = 'filter'; + } + // Getting the rendered width and height + if (alias) { + el.style.zoom = 1; + return Math.max(el[alias] - 2 * U.getStyle(el, 'padding'), 0); + } + val = el.currentStyle[prop.replace(/\-(\w)/g, function (a, b) { + return b.toUpperCase(); + })]; + if (prop === 'filter') { + val = val.replace(/alpha\(opacity=([0-9]+)\)/, function (a, b) { + return (b / 100); + }); + } + return val === '' ? 1 : pInt(val); + }; +} +/* eslint-disable no-invalid-this, valid-jsdoc */ +if (!svg) { + // Prevent wrapping from creating false offsetWidths in export in legacy IE. + // This applies only to charts for export, where IE runs the SVGRenderer + // instead of the VMLRenderer + // (#1079, #1063) + addEvent(SVGElement, 'afterInit', function () { + if (this.element.nodeName === 'text') { + this.css({ + position: 'absolute' + }); + } + }); + /** + * Old IE override for pointer normalize, adds chartX and chartY to event + * arguments. + * + * @ignore + * @function Highcharts.Pointer#normalize + * @param {global.PointerEvent} e + * @param {boolean} [chartPosition=false] + * @return {Highcharts.PointerEventObject} + */ + H.Pointer.prototype.normalize = function (e, chartPosition) { + e = e || win.event; + if (!e.target) { + e.target = e.srcElement; + } + // Get mouse position + if (!chartPosition) { + this.chartPosition = chartPosition = offset(this.chart.container); + } + return extend(e, { + // #2005, #2129: the second case is for IE10 quirks mode within + // framesets + chartX: Math.round(Math.max(e.x, e.clientX - chartPosition.left)), + chartY: Math.round(e.y) + }); + }; + /** + * Further sanitize the mock-SVG that is generated when exporting charts in + * oldIE. + * + * @private + * @function Highcharts.Chart#ieSanitizeSVG + */ + Chart.prototype.ieSanitizeSVG = function (svg) { + svg = svg + .replace(//g, '<$1title>') + .replace(/height=([^" ]+)/g, 'height="$1"') + .replace(/width=([^" ]+)/g, 'width="$1"') + .replace(/hc-svg-href="([^"]+)">/g, 'xlink:href="$1"/>') + .replace(/ id=([^" >]+)/g, ' id="$1"') // #4003 + .replace(/class=([^" >]+)/g, 'class="$1"') + .replace(/ transform /g, ' ') + .replace(/:(path|rect)/g, '$1') + .replace(/style="([^"]+)"/g, function (s) { + return s.toLowerCase(); + }); + return svg; + }; + /** + * VML namespaces can't be added until after complete. Listening + * for Perini's doScroll hack is not enough. + * + * @private + * @function Highcharts.Chart#isReadyToRender + */ + Chart.prototype.isReadyToRender = function () { + var chart = this; + // Note: win == win.top is required + if (!svg && + (win == win.top && // eslint-disable-line eqeqeq + doc.readyState !== 'complete')) { + doc.attachEvent('onreadystatechange', function () { + doc.detachEvent('onreadystatechange', chart.firstRender); + if (doc.readyState === 'complete') { + chart.firstRender(); + } + }); + return false; + } + return true; + }; + // IE compatibility hack for generating SVG content that it doesn't really + // understand. Used by the exporting module. + if (!doc.createElementNS) { + doc.createElementNS = function (ns, tagName) { + return doc.createElement(tagName); + }; + } + /** + * Old IE polyfill for addEventListener, called from inside the addEvent + * function. + * + * @private + * @function Highcharts.addEventListenerPolyfill + * @param {string} type + * @param {Highcharts.EventCallbackFunction} fn + * @return {void} + */ + H.addEventListenerPolyfill = function (type, fn) { + var el = this; + /** + * @private + */ + function wrappedFn(e) { + e.target = e.srcElement || win; // #2820 + fn.call(el, e); + } + if (el.attachEvent) { + if (!el.hcEventsIE) { + el.hcEventsIE = {}; + } + // unique function string (#6746) + if (!fn.hcKey) { + fn.hcKey = uniqueKey(); + } + // Link wrapped fn with original fn, so we can get this in + // removeEvent + el.hcEventsIE[fn.hcKey] = wrappedFn; + el.attachEvent('on' + type, wrappedFn); + } + }; + /** + * @private + * @function Highcharts.removeEventListenerPolyfill + * @param {string} type + * @param {Highcharts.EventCallbackFunction} fn + * @return {void} + */ + H.removeEventListenerPolyfill = function (type, fn) { + if (this.detachEvent) { + fn = this.hcEventsIE[fn.hcKey]; + this.detachEvent('on' + type, fn); + } + }; + /** + * The VML element wrapper. + * + * @private + * @class + * @name Highcharts.VMLElement + * + * @augments Highcharts.SVGElement + */ + VMLElement = { + docMode8: doc && doc.documentMode === 8, + /** + * Initialize a new VML element wrapper. It builds the markup as a + * string to minimize DOM traffic. + * + * @function Highcharts.VMLElement#init + * @param {Highcharts.VMLRenderer} renderer + * @param {string} nodeName + */ + init: function (renderer, nodeName) { + var wrapper = this, markup = ['<', nodeName, ' filled="f" stroked="f"'], style = ['position: ', 'absolute', ';'], isDiv = nodeName === 'div'; + // divs and shapes need size + if (nodeName === 'shape' || isDiv) { + style.push('left:0;top:0;width:1px;height:1px;'); + } + style.push('visibility: ', isDiv ? 'hidden' : 'visible'); + markup.push(' style="', style.join(''), '"/>'); + // create element with default attributes and style + if (nodeName) { + markup = isDiv || nodeName === 'span' || nodeName === 'img' ? + markup.join('') : + renderer.prepVML(markup); + wrapper.element = createElement(markup); + } + wrapper.renderer = renderer; + }, + /** + * Add the node to the given parent + * + * @function Highcharts.VMLElement + * @param {Highcharts.VMLElement} parent + * @return {Highcharts.VMLElement} + */ + add: function (parent) { + var wrapper = this, renderer = wrapper.renderer, element = wrapper.element, box = renderer.box, inverted = parent && parent.inverted, + // get the parent node + parentNode = parent ? + parent.element || parent : + box; + if (parent) { + this.parentGroup = parent; + } + // if the parent group is inverted, apply inversion on all children + if (inverted) { // only on groups + renderer.invertChild(element, parentNode); + } + // append it + parentNode.appendChild(element); + // align text after adding to be able to read offset + wrapper.added = true; + if (wrapper.alignOnAdd && !wrapper.deferUpdateTransform) { + wrapper.updateTransform(); + } + // fire an event for internal hooks + if (wrapper.onAdd) { + wrapper.onAdd(); + } + // IE8 Standards can't set the class name before the element is + // appended + if (this.className) { + this.attr('class', this.className); + } + return wrapper; + }, + /** + * VML always uses htmlUpdateTransform + * + * @function Highcharts.VMLElement#updateTransform + */ + updateTransform: SVGElement.prototype.htmlUpdateTransform, + /** + * Set the rotation of a span with oldIE's filter + * + * @function Highcharts.VMLElement#setSpanRotation + * @return {void} + */ + setSpanRotation: function () { + // Adjust for alignment and rotation. Rotation of useHTML content is + // not yet implemented but it can probably be implemented for + // Firefox 3.5+ on user request. FF3.5+ has support for CSS3 + // transform. The getBBox method also needs to be updated to + // compensate for the rotation, like it currently does for SVG. + // Test case: https://jsfiddle.net/highcharts/Ybt44/ + var rotation = this.rotation, costheta = Math.cos(rotation * deg2rad), sintheta = Math.sin(rotation * deg2rad); + css(this.element, { + filter: rotation ? [ + 'progid:DXImageTransform.Microsoft.Matrix(M11=', costheta, + ', M12=', -sintheta, ', M21=', sintheta, ', M22=', costheta, + ', sizingMethod=\'auto expand\')' + ].join('') : 'none' + }); + }, + /** + * Get the positioning correction for the span after rotating. + * + * @function Highcharts.VMLElement#getSpanCorrection + */ + getSpanCorrection: function (width, baseline, alignCorrection, rotation, align) { + var costheta = rotation ? Math.cos(rotation * deg2rad) : 1, sintheta = rotation ? Math.sin(rotation * deg2rad) : 0, height = pick(this.elemHeight, this.element.offsetHeight), quad, nonLeft = align && align !== 'left'; + // correct x and y + this.xCorr = (costheta < 0 && -width); + this.yCorr = (sintheta < 0 && -height); + // correct for baseline and corners spilling out after rotation + quad = costheta * sintheta < 0; + this.xCorr += (sintheta * + baseline * + (quad ? 1 - alignCorrection : alignCorrection)); + this.yCorr -= (costheta * + baseline * + (rotation ? (quad ? alignCorrection : 1 - alignCorrection) : 1)); + // correct for the length/height of the text + if (nonLeft) { + this.xCorr -= + width * alignCorrection * (costheta < 0 ? -1 : 1); + if (rotation) { + this.yCorr -= (height * + alignCorrection * + (sintheta < 0 ? -1 : 1)); + } + css(this.element, { + textAlign: align + }); + } + }, + /** + * Converts a subset of an SVG path definition to its VML counterpart. + * Takes an array as the parameter and returns a string. + * + * @function Highcharts.VMLElement#pathToVML + */ + pathToVML: function (value) { + // convert paths + var i = value.length, path = []; + while (i--) { + // Multiply by 10 to allow subpixel precision. + // Substracting half a pixel seems to make the coordinates + // align with SVG, but this hasn't been tested thoroughly + if (isNumber(value[i])) { + path[i] = Math.round(value[i] * 10) - 5; + } + else if (value[i] === 'Z') { // close the path + path[i] = 'x'; + } + else { + path[i] = value[i]; + // When the start X and end X coordinates of an arc are too + // close, they are rounded to the same value above. In this + // case, substract or add 1 from the end X and Y positions. + // #186, #760, #1371, #1410. + if (value.isArc && + (value[i] === 'wa' || value[i] === 'at')) { + // Start and end X + if (path[i + 5] === path[i + 7]) { + path[i + 7] += + value[i + 7] > value[i + 5] ? 1 : -1; + } + // Start and end Y + if (path[i + 6] === path[i + 8]) { + path[i + 8] += + value[i + 8] > value[i + 6] ? 1 : -1; + } + } + } + } + return path.join(' ') || 'x'; + }, + /** + * Set the element's clipping to a predefined rectangle + * + * @function Highcharts.VMLElement#clip + * @param {Highcharts.VMLClipRectObject} clipRect + * @return {Highcharts.VMLElement} + */ + clip: function (clipRect) { + var wrapper = this, clipMembers, cssRet; + if (clipRect) { + clipMembers = clipRect.members; + // Ensure unique list of elements (#1258) + erase(clipMembers, wrapper); + clipMembers.push(wrapper); + wrapper.destroyClip = function () { + erase(clipMembers, wrapper); + }; + cssRet = clipRect.getCSS(wrapper); + } + else { + if (wrapper.destroyClip) { + wrapper.destroyClip(); + } + cssRet = { + clip: wrapper.docMode8 ? 'inherit' : 'rect(auto)' + }; // #1214 + } + return wrapper.css(cssRet); + }, + /** + * Set styles for the element + * + * @function Highcharts.VMLElement#css + * @param {Highcharts.CSSObject} styles + * @return {Highcharts.VMLElement} + */ + css: SVGElement.prototype.htmlCss, + /** + * Removes a child either by removeChild or move to garbageBin. + * Issue 490; in VML removeChild results in Orphaned nodes according to + * sIEve, discardElement does not. + * + * @function Highcharts.VMLElement#safeRemoveChild + * @param {Highcharts.HTMLDOMElement} element + * @return {void} + */ + safeRemoveChild: function (element) { + // discardElement will detach the node from its parent before + // attaching it to the garbage bin. Therefore it is important that + // the node is attached and have parent. + if (element.parentNode) { + discardElement(element); + } + }, + /** + * Extend element.destroy by removing it from the clip members array + * + * @function Highcharts.VMLElement#destroy + */ + destroy: function () { + if (this.destroyClip) { + this.destroyClip(); + } + return SVGElement.prototype.destroy.apply(this); + }, + /** + * Add an event listener. VML override for normalizing event parameters. + * + * @function Highcharts.VMLElement#on + * @param {string} eventType + * @param {Function} handler + * @return {Highcharts.VMLElement} + */ + on: function (eventType, handler) { + // simplest possible event model for internal use + this.element['on' + eventType] = function () { + var e = win.event; + e.target = e.srcElement; + handler(e); + }; + return this; + }, + /** + * In stacked columns, cut off the shadows so that they don't overlap + * + * @function Highcharts.VMLElement#cutOffPath + * @param {string} path + * @param {number} length + * @return {string} + */ + cutOffPath: function (path, length) { + var len; + // The extra comma tricks the trailing comma remover in + // "gulp scripts" task + path = path.split(/[ ,]/); + len = path.length; + if (len === 9 || len === 11) { + path[len - 4] = path[len - 2] = + pInt(path[len - 2]) - 10 * length; + } + return path.join(' '); + }, + /** + * Apply a drop shadow by copying elements and giving them different + * strokes. + * + * @function Highcharts.VMLElement#shadow + * @param {Highcharts.ShadowOptionsObject} shadowOptions + * @param {Highcharts.VMLElement} group + * @param {boolean} cutOff + * @return {Highcharts.VMLElement} + */ + shadow: function (shadowOptions, group, cutOff) { + var shadows = [], i, element = this.element, renderer = this.renderer, shadow, elemStyle = element.style, markup, path = element.path, strokeWidth, modifiedPath, shadowWidth, shadowElementOpacity; + // some times empty paths are not strings + if (path && typeof path.value !== 'string') { + path = 'x'; + } + modifiedPath = path; + if (shadowOptions) { + shadowWidth = pick(shadowOptions.width, 3); + shadowElementOpacity = + (shadowOptions.opacity || 0.15) / shadowWidth; + for (i = 1; i <= 3; i++) { + strokeWidth = (shadowWidth * 2) + 1 - (2 * i); + // Cut off shadows for stacked column items + if (cutOff) { + modifiedPath = this.cutOffPath(path.value, strokeWidth + 0.5); + } + markup = [ + '' + ]; + shadow = createElement(renderer.prepVML(markup), null, { + left: pInt(elemStyle.left) + + pick(shadowOptions.offsetX, 1), + top: pInt(elemStyle.top) + + pick(shadowOptions.offsetY, 1) + }); + if (cutOff) { + shadow.cutOff = strokeWidth + 1; + } + // apply the opacity + markup = [ + '' + ]; + createElement(renderer.prepVML(markup), null, null, shadow); + // insert it + if (group) { + group.element.appendChild(shadow); + } + else { + element.parentNode + .insertBefore(shadow, element); + } + // record it + shadows.push(shadow); + } + this.shadows = shadows; + } + return this; + }, + updateShadows: noop, + setAttr: function (key, value) { + if (this.docMode8) { // IE8 setAttribute bug + this.element[key] = value; + } + else { + this.element.setAttribute(key, value); + } + }, + getAttr: function (key) { + if (this.docMode8) { // IE8 setAttribute bug + return this.element[key]; + } + return this.element.getAttribute(key); + }, + classSetter: function (value) { + // IE8 Standards mode has problems retrieving the className unless + // set like this. IE8 Standards can't set the class name before the + // element is appended. + (this.added ? this.element : this).className = value; + }, + dashstyleSetter: function (value, key, element) { + var strokeElem = element.getElementsByTagName('stroke')[0] || + createElement(this.renderer.prepVML(['']), null, null, element); + strokeElem[key] = value || 'solid'; + // Because changing stroke-width will change the dash length and + // cause an epileptic effect + this[key] = value; + }, + dSetter: function (value, key, element) { + var i, shadows = this.shadows; + value = value || []; + // Used in getter for animation + this.d = value.join && value.join(' '); + element.path = value = this.pathToVML(value); + // update shadows + if (shadows) { + i = shadows.length; + while (i--) { + shadows[i].path = shadows[i].cutOff ? + this.cutOffPath(value, shadows[i].cutOff) : + value; + } + } + this.setAttr(key, value); + }, + fillSetter: function (value, key, element) { + var nodeName = element.nodeName; + if (nodeName === 'SPAN') { // text color + element.style.color = value; + } + else if (nodeName !== 'IMG') { // #1336 + element.filled = value !== 'none'; + this.setAttr('fillcolor', this.renderer.color(value, element, key, this)); + } + }, + 'fill-opacitySetter': function (value, key, element) { + createElement(this.renderer.prepVML(['<', key.split('-')[0], ' opacity="', value, '"/>']), null, null, element); + }, + // Don't bother - animation is too slow and filters introduce artifacts + opacitySetter: noop, + rotationSetter: function (value, key, element) { + var style = element.style; + // style is for #1873: + this[key] = style[key] = value; + // Correction for the 1x1 size of the shape container. Used in gauge + // needles. + style.left = + -Math.round(Math.sin(value * deg2rad) + 1) + 'px'; + style.top = + Math.round(Math.cos(value * deg2rad)) + 'px'; + }, + strokeSetter: function (value, key, element) { + this.setAttr('strokecolor', this.renderer.color(value, element, key, this)); + }, + 'stroke-widthSetter': function (value, key, element) { + element.stroked = !!value; // VML "stroked" attribute + this[key] = value; // used in getter, issue #113 + if (isNumber(value)) { + value += 'px'; + } + this.setAttr('strokeweight', value); + }, + titleSetter: function (value, key) { + this.setAttr(key, value); + }, + visibilitySetter: function (value, key, element) { + // Handle inherited visibility + if (value === 'inherit') { + value = 'visible'; + } + // Let the shadow follow the main element + if (this.shadows) { + this.shadows.forEach(function (shadow) { + shadow.style[key] = value; + }); + } + // Instead of toggling the visibility CSS property, move the div out + // of the viewport. This works around #61 and #586 + if (element.nodeName === 'DIV') { + value = value === 'hidden' ? '-999em' : 0; + // In order to redraw, IE7 needs the div to be visible when + // tucked away outside the viewport. So the visibility is + // actually opposite of the expected value. This applies to the + // tooltip only. + if (!this.docMode8) { + element.style[key] = value ? 'visible' : 'hidden'; + } + key = 'top'; + } + element.style[key] = value; + }, + xSetter: function (value, key, element) { + this[key] = value; // used in getter + if (key === 'x') { + key = 'left'; + } + else if (key === 'y') { + key = 'top'; + } + // clipping rectangle special + if (this.updateClipping) { + // the key is now 'left' or 'top' for 'x' and 'y' + this[key] = value; + this.updateClipping(); + } + else { + // normal + element.style[key] = value; + } + }, + zIndexSetter: function (value, key, element) { + element.style[key] = value; + }, + fillGetter: function () { + return this.getAttr('fillcolor') || ''; + }, + strokeGetter: function () { + return this.getAttr('strokecolor') || ''; + }, + // #7850 + classGetter: function () { + return this.getAttr('className') || ''; + } + }; + VMLElement['stroke-opacitySetter'] = + VMLElement['fill-opacitySetter']; + H.VMLElement = VMLElement = extendClass(SVGElement, VMLElement); + // Some shared setters + VMLElement.prototype.ySetter = + VMLElement.prototype.widthSetter = + VMLElement.prototype.heightSetter = + VMLElement.prototype.xSetter; + /** + * The VML renderer + * + * @private + * @class + * @name Highcharts.VMLRenderer + * + * @augments Highcharts.SVGRenderer + */ + VMLRendererExtension = { + Element: VMLElement, + isIE8: win.navigator.userAgent.indexOf('MSIE 8.0') > -1, + /** + * Initialize the VMLRenderer. + * + * @function Highcharts.VMLRenderer#init + * @param {Highcharts.HTMLDOMElement} container + * @param {number} width + * @param {number} height + * @return {void} + */ + init: function (container, width, height) { + var renderer = this, boxWrapper, box, css; + // Extended SVGRenderer member + this.crispPolyLine = SVGRenderer.prototype.crispPolyLine; + renderer.alignedObjects = []; + boxWrapper = renderer.createElement('div') + .css({ position: 'relative' }); + box = boxWrapper.element; + container.appendChild(boxWrapper.element); + // generate the containing box + renderer.isVML = true; + renderer.box = box; + renderer.boxWrapper = boxWrapper; + renderer.gradients = {}; + renderer.cache = {}; // Cache for numerical bounding boxes + renderer.cacheKeys = []; + renderer.imgCount = 0; + renderer.setSize(width, height, false); + // The only way to make IE6 and IE7 print is to use a global + // namespace. However, with IE8 the only way to make the dynamic + // shapes visible in screen and print mode seems to be to add the + // xmlns attribute and the behaviour style inline. + if (!doc.namespaces.hcv) { + doc.namespaces.add('hcv', 'urn:schemas-microsoft-com:vml'); + // Setup default CSS (#2153, #2368, #2384) + css = 'hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke' + + '{ behavior:url(#default#VML); display: inline-block; } '; + try { + doc.createStyleSheet().cssText = css; + } + catch (e) { + doc.styleSheets[0].cssText += css; + } + } + }, + /** + * Detect whether the renderer is hidden. This happens when one of the + * parent elements has display: none + * + * @function Highcharts.VMLRenderer#isHidden + */ + isHidden: function () { + return !this.box.offsetWidth; + }, + /** + * Define a clipping rectangle. In VML it is accomplished by storing the + * values for setting the CSS style to all associated members. + * + * @function Highcharts.VMLRenderer#clipRect + * @param {number|Highcharts.SizeObject} x + * @param {number} y + * @param {number} width + * @param {number} height + * @return {Highcharts.VMLElement} + */ + clipRect: function (x, y, width, height) { + // create a dummy element + var clipRect = this.createElement(), isObj = isObject(x); + // mimic a rectangle with its style object for automatic updating in + // attr + return extend(clipRect, { + members: [], + count: 0, + left: (isObj ? x.x : x) + 1, + top: (isObj ? x.y : y) + 1, + width: (isObj ? x.width : width) - 1, + height: (isObj ? x.height : height) - 1, + getCSS: function (wrapper) { + var element = wrapper.element, nodeName = element.nodeName, isShape = nodeName === 'shape', inverted = wrapper.inverted, rect = this, top = rect.top - (isShape ? element.offsetTop : 0), left = rect.left, right = left + rect.width, bottom = top + rect.height, ret = { + clip: 'rect(' + + Math.round(inverted ? left : top) + 'px,' + + Math.round(inverted ? bottom : right) + 'px,' + + Math.round(inverted ? right : bottom) + 'px,' + + Math.round(inverted ? top : left) + 'px)' + }; + // issue 74 workaround + if (!inverted && wrapper.docMode8 && nodeName === 'DIV') { + extend(ret, { + width: right + 'px', + height: bottom + 'px' + }); + } + return ret; + }, + // used in attr and animation to update the clipping of all + // members + updateClipping: function () { + clipRect.members.forEach(function (member) { + // Member.element is falsy on deleted series, like in + // stock/members/series-remove demo. Should be removed + // from members, but this will do. + if (member.element) { + member.css(clipRect.getCSS(member)); + } + }); + } + }); + }, + /** + * Take a color and return it if it's a string, make it a gradient if + * it's a gradient configuration object, and apply opacity. + * + * @function Highcharts.VMLRenderer#color + * + * @param {T} color + * The color or config object + * + * @return {T} + */ + color: function (colorOption, elem, prop, wrapper) { + var renderer = this, colorObject, regexRgba = /^rgba/, markup, fillType, ret = 'none'; + // Check for linear or radial gradient + if (colorOption && + colorOption.linearGradient) { + fillType = 'gradient'; + } + else if (colorOption && + colorOption.radialGradient) { + fillType = 'pattern'; + } + if (fillType) { + var stopColor, stopOpacity, gradient = (colorOption.linearGradient || + colorOption.radialGradient), x1, y1, x2, y2, opacity1, opacity2, color1, color2, fillAttr = '', stops = colorOption.stops, firstStop, lastStop, colors = [], addFillNode = function () { + // Add the fill subnode. When colors attribute is used, + // the meanings of opacity and o:opacity2 are reversed. + markup = ['']; + createElement(renderer.prepVML(markup), null, null, elem); + }; + // Extend from 0 to 1 + firstStop = stops[0]; + lastStop = stops[stops.length - 1]; + if (firstStop[0] > 0) { + stops.unshift([ + 0, + firstStop[1] + ]); + } + if (lastStop[0] < 1) { + stops.push([ + 1, + lastStop[1] + ]); + } + // Compute the stops + stops.forEach(function (stop, i) { + if (regexRgba.test(stop[1])) { + colorObject = color(stop[1]); + stopColor = colorObject.get('rgb'); + stopOpacity = colorObject.get('a'); + } + else { + stopColor = stop[1]; + stopOpacity = 1; + } + // Build the color attribute + colors.push((stop[0] * 100) + '% ' + stopColor); + // Only start and end opacities are allowed, so we use the + // first and the last + if (!i) { + opacity1 = stopOpacity; + color2 = stopColor; + } + else { + opacity2 = stopOpacity; + color1 = stopColor; + } + }); + // Apply the gradient to fills only. + if (prop === 'fill') { + // Handle linear gradient angle + if (fillType === 'gradient') { + x1 = gradient.x1 || gradient[0] || 0; + y1 = gradient.y1 || gradient[1] || 0; + x2 = gradient.x2 || gradient[2] || 0; + y2 = gradient.y2 || gradient[3] || 0; + fillAttr = 'angle="' + (90 - Math.atan((y2 - y1) / // y vector + (x2 - x1) // x vector + ) * 180 / Math.PI) + '"'; + addFillNode(); + // Radial (circular) gradient + } + else { + var r = gradient.r, sizex = r * 2, sizey = r * 2, cx = gradient.cx, cy = gradient.cy, radialReference = elem.radialReference, bBox, applyRadialGradient = function () { + if (radialReference) { + bBox = wrapper.getBBox(); + cx += (radialReference[0] - bBox.x) / + bBox.width - 0.5; + cy += (radialReference[1] - bBox.y) / + bBox.height - 0.5; + sizex *= radialReference[2] / bBox.width; + sizey *= radialReference[2] / bBox.height; + } + fillAttr = + 'src="' + H.getOptions().global.VMLRadialGradientURL + + '" ' + + 'size="' + sizex + ',' + sizey + '" ' + + 'origin="0.5,0.5" ' + + 'position="' + cx + ',' + cy + '" ' + + 'color2="' + color2 + '" '; + addFillNode(); + }; + // Apply radial gradient + if (wrapper.added) { + applyRadialGradient(); + } + else { + // We need to know the bounding box to get the size + // and position right + wrapper.onAdd = applyRadialGradient; + } + // The fill element's color attribute is broken in IE8 + // standards mode, so we need to set the parent shape's + // fillcolor attribute instead. + ret = color1; + } + // Gradients are not supported for VML stroke, return the first + // color. #722. + } + else { + ret = stopColor; + } + // If the color is an rgba color, split it and add a fill node + // to hold the opacity component + } + else if (regexRgba.test(colorOption) && elem.tagName !== 'IMG') { + colorObject = color(colorOption); + wrapper[prop + '-opacitySetter'](colorObject.get('a'), prop, elem); + ret = colorObject.get('rgb'); + } + else { + // 'stroke' or 'fill' node + var propNodes = elem.getElementsByTagName(prop); + if (propNodes.length) { + propNodes[0].opacity = 1; + propNodes[0].type = 'solid'; + } + ret = colorOption; + } + return ret; + }, + /** + * Take a VML string and prepare it for either IE8 or IE6/IE7. + * + * @function Highcharts.VMLRenderer#prepVML + * + * @param {Array<(number|string)>} markup + * A string array of the VML markup to prepare + * + * @return {string} + */ + prepVML: function (markup) { + var vmlStyle = 'display:inline-block;behavior:url(#default#VML);', isIE8 = this.isIE8; + markup = markup.join(''); + if (isIE8) { // add xmlns and style inline + markup = markup.replace('/>', ' xmlns="urn:schemas-microsoft-com:vml" />'); + if (markup.indexOf('style="') === -1) { + markup = markup.replace('/>', ' style="' + vmlStyle + '" />'); + } + else { + markup = markup.replace('style="', 'style="' + vmlStyle); + } + } + else { // add namespace + markup = markup.replace('<', '} x + * @param {number} [y] + * @param {number} [r] + * @return {Highcharts.VMLElement} + */ + circle: function (x, y, r) { + var circle = this.symbol('circle'); + if (isObject(x)) { + r = x.r; + y = x.y; + x = x.x; + } + circle.isCircle = true; // Causes x and y to mean center (#1682) + circle.r = r; + return circle.attr({ x: x, y: y }); + }, + /** + * Create a group using an outer div and an inner v:group to allow + * rotating and flipping. A simple v:group would have problems with + * positioning child HTML elements and CSS clip. + * + * @function Highcharts.VMLRenderer#g + * + * @param {string} name + * The name of the group + * + * @return {Highcharts.VMLElement} + */ + g: function (name) { + var wrapper, attribs; + // set the class name + if (name) { + attribs = { + 'className': 'highcharts-' + name, + 'class': 'highcharts-' + name + }; + } + // the div to hold HTML and clipping + wrapper = this.createElement('div').attr(attribs); + return wrapper; + }, + /** + * VML override to create a regular HTML image. + * + * @function Highcharts.VMLRenderer#image + * + * @param {string} src + * + * @param {number} x + * + * @param {number} y + * + * @param {number} width + * + * @param {number} height + * @return {Highcharts.VMLElement} + */ + image: function (src, x, y, width, height) { + var obj = this.createElement('img').attr({ src: src }); + if (arguments.length > 1) { + obj.attr({ + x: x, + y: y, + width: width, + height: height + }); + } + return obj; + }, + /** + * For rectangles, VML uses a shape for rect to overcome bugs and + * rotation problems + * + * @function Highcharts.VMLRenderer#createElement + * @param {string} nodeName + * @return {Highcharts.VMLElement} + */ + createElement: function (nodeName) { + return nodeName === 'rect' ? + this.symbol(nodeName) : + SVGRenderer.prototype.createElement.call(this, nodeName); + }, + /** + * In the VML renderer, each child of an inverted div (group) is + * inverted + * + * @function Highcharts.VMLRenderer#invertChild + * + * @param {Highcharts.HTMLDOMElement} element + * + * @param {Highcharts.HTMLDOMElement} parentNode + */ + invertChild: function (element, parentNode) { + var ren = this, parentStyle = parentNode.style, imgStyle = element.tagName === 'IMG' && element.style; // #1111 + css(element, { + flip: 'x', + left: pInt(parentStyle.width) - + (imgStyle ? pInt(imgStyle.top) : 1), + top: pInt(parentStyle.height) - + (imgStyle ? pInt(imgStyle.left) : 1), + rotation: -90 + }); + // Recursively invert child elements, needed for nested composite + // shapes like box plots and error bars. #1680, #1806. + [].forEach.call(element.childNodes, function (child) { + ren.invertChild(child, element); + }); + }, + /** + * Symbol definitions that override the parent SVG renderer's symbols + * + * @name Highcharts.VMLRenderer#symbols + * @type {Highcharts.Dictionary} + */ + symbols: { + // VML specific arc function + arc: function (x, y, w, h, options) { + var start = options.start, end = options.end, radius = options.r || w || h, innerRadius = options.innerR, cosStart = Math.cos(start), sinStart = Math.sin(start), cosEnd = Math.cos(end), sinEnd = Math.sin(end), ret; + if (end - start === 0) { // no angle, don't show it. + return ['x']; + } + ret = [ + 'wa', + x - radius, + y - radius, + x + radius, + y + radius, + x + radius * cosStart, + y + radius * sinStart, + x + radius * cosEnd, + y + radius * sinEnd // end y + ]; + if (options.open && !innerRadius) { + ret.push('e', 'M', x, // - innerRadius, + y // - innerRadius + ); + } + ret.push('at', // anti clockwise arc to + x - innerRadius, // left + y - innerRadius, // top + x + innerRadius, // right + y + innerRadius, // bottom + x + innerRadius * cosEnd, // start x + y + innerRadius * sinEnd, // start y + x + innerRadius * cosStart, // end x + y + innerRadius * sinStart, // end y + 'x', // finish path + 'e' // close + ); + ret.isArc = true; + return ret; + }, + // Add circle symbol path. This performs significantly faster than + // v:oval. + circle: function (x, y, w, h, wrapper) { + if (wrapper && defined(wrapper.r)) { + w = h = 2 * wrapper.r; + } + // Center correction, #1682 + if (wrapper && wrapper.isCircle) { + x -= w / 2; + y -= h / 2; + } + // Return the path + return [ + 'wa', + x, + y, + x + w, + y + h, + x + w, + y + h / 2, + x + w, + y + h / 2, + 'e' // close + ]; + }, + /** + * Add rectangle symbol path which eases rotation and omits arcsize + * problems compared to the built-in VML roundrect shape. When + * borders are not rounded, use the simpler square path, else use + * the callout path without the arrow. + */ + rect: function (x, y, w, h, options) { + return SVGRenderer.prototype.symbols[!defined(options) || !options.r ? 'square' : 'callout'].call(0, x, y, w, h, options); + } + } + }; + H.VMLRenderer = VMLRenderer = function () { + this.init.apply(this, arguments); + }; + VMLRenderer.prototype = merge(SVGRenderer.prototype, VMLRendererExtension); + // general renderer + H.Renderer = VMLRenderer; +} +SVGRenderer.prototype.getSpanWidth = function (wrapper, tspan) { + var renderer = this, bBox = wrapper.getBBox(true), actualWidth = bBox.width; + // Old IE cannot measure the actualWidth for SVG elements (#2314) + if (!svg && renderer.forExport) { + actualWidth = renderer.measureSpanWidth(tspan.firstChild.data, wrapper.styles); + } + return actualWidth; +}; +// This method is used with exporting in old IE, when emulating SVG (see #2314) +SVGRenderer.prototype.measureSpanWidth = function (text, styles) { + var measuringSpan = doc.createElement('span'), offsetWidth, textNode = doc.createTextNode(text); + measuringSpan.appendChild(textNode); + css(measuringSpan, styles); + this.box.appendChild(measuringSpan); + offsetWidth = measuringSpan.offsetWidth; + discardElement(measuringSpan); // #2463 + return offsetWidth; +}; diff --git a/librerias/gantt/code/es-modules/modules/organization.src.js b/librerias/gantt/code/es-modules/modules/organization.src.js new file mode 100644 index 0000000..489fc01 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/organization.src.js @@ -0,0 +1,516 @@ +/* * + * + * Organization chart module + * + * (c) 2018-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var css = U.css, pick = U.pick, seriesType = U.seriesType, wrap = U.wrap; +/** + * Layout value for the child nodes in an organization chart. If `hanging`, this + * node's children will hang below their parent, allowing a tighter packing of + * nodes in the diagram. + * + * @typedef {"normal"|"hanging"} Highcharts.SeriesOrganizationNodesLayoutValue + */ +var base = H.seriesTypes.sankey.prototype; +/** + * @private + * @class + * @name Highcharts.seriesTypes.organization + * + * @augments Highcharts.seriesTypes.sankey + */ +seriesType('organization', 'sankey', +/** + * An organization chart is a diagram that shows the structure of an + * organization and the relationships and relative ranks of its parts and + * positions. + * + * @sample highcharts/demo/organization-chart/ + * Organization chart + * @sample highcharts/series-organization/horizontal/ + * Horizontal organization chart + * @sample highcharts/series-organization/borderless + * Borderless design + * @sample highcharts/series-organization/center-layout + * Centered layout + * + * @extends plotOptions.sankey + * @excluding allowPointSelect, curveFactor, dataSorting + * @since 7.1.0 + * @product highcharts + * @requires modules/organization + * @optionparent plotOptions.organization + */ +{ + /** + * The border color of the node cards. + * + * @type {Highcharts.ColorString} + * @private + */ + borderColor: '#666666', + /** + * The border radius of the node cards. + * + * @private + */ + borderRadius: 3, + /** + * Radius for the rounded corners of the links between nodes. + * + * @sample highcharts/series-organization/link-options + * Square links + * + * @private + */ + linkRadius: 10, + borderWidth: 1, + /** + * @declare Highcharts.SeriesOrganizationDataLabelsOptionsObject + * + * @private + */ + dataLabels: { + /* eslint-disable valid-jsdoc */ + /** + * A callback for defining the format for _nodes_ in the + * organization chart. The `nodeFormat` option takes precedence + * over `nodeFormatter`. + * + * In an organization chart, the `nodeFormatter` is a quite complex + * function of the available options, striving for a good default + * layout of cards with or without images. In organization chart, + * the data labels come with `useHTML` set to true, meaning they + * will be rendered as true HTML above the SVG. + * + * @sample highcharts/series-organization/datalabels-nodeformatter + * Modify the default label format output + * + * @type {Highcharts.SeriesSankeyDataLabelsFormatterCallbackFunction} + * @since 6.0.2 + */ + nodeFormatter: function () { + var outerStyle = { + width: '100%', + height: '100%', + display: 'flex', + 'flex-direction': 'row', + 'align-items': 'center', + 'justify-content': 'center' + }, imageStyle = { + 'max-height': '100%', + 'border-radius': '50%' + }, innerStyle = { + width: '100%', + padding: 0, + 'text-align': 'center', + 'white-space': 'normal' + }, nameStyle = { + margin: 0 + }, titleStyle = { + margin: 0 + }, descriptionStyle = { + opacity: 0.75, + margin: '5px' + }; + // eslint-disable-next-line valid-jsdoc + /** + * @private + */ + function styleAttr(style) { + return Object.keys(style).reduce(function (str, key) { + return str + key + ':' + style[key] + ';'; + }, 'style="') + '"'; + } + if (this.point.image) { + imageStyle['max-width'] = '30%'; + innerStyle.width = '70%'; + } + // PhantomJS doesn't support flex, roll back to absolute + // positioning + if (this.series.chart.renderer.forExport) { + outerStyle.display = 'block'; + innerStyle.position = 'absolute'; + innerStyle.left = this.point.image ? '30%' : 0; + innerStyle.top = 0; + } + var html = '
'; + if (this.point.image) { + html += ''; + } + html += '
'; + if (this.point.name) { + html += '

' + + this.point.name + '

'; + } + if (this.point.title) { + html += '

' + + (this.point.title || '') + '

'; + } + if (this.point.description) { + html += '

' + + this.point.description + '

'; + } + html += '
' + + '
'; + return html; + }, + /* eslint-enable valid-jsdoc */ + style: { + /** @internal */ + fontWeight: 'normal', + /** @internal */ + fontSize: '13px' + }, + useHTML: true + }, + /** + * The indentation in pixels of hanging nodes, nodes which parent has + * [layout](#series.organization.nodes.layout) set to `hanging`. + * + * @private + */ + hangingIndent: 20, + /** + * The color of the links between nodes. + * + * @type {Highcharts.ColorString} + * @private + */ + linkColor: '#666666', + /** + * The line width of the links connecting nodes, in pixels. + * + * @sample highcharts/series-organization/link-options + * Square links + * + * @private + */ + linkLineWidth: 1, + /** + * In a horizontal chart, the width of the nodes in pixels. Node that + * most organization charts are vertical, so the name of this option + * is counterintuitive. + * + * @private + */ + nodeWidth: 50, + tooltip: { + nodeFormat: '{point.name}
{point.title}
{point.description}' + } +}, { + pointAttribs: function (point, state) { + var series = this, attribs = base.pointAttribs.call(series, point, state), level = point.isNode ? point.level : point.fromNode.level, levelOptions = series.mapOptionsToLevel[level || 0] || {}, options = point.options, stateOptions = (levelOptions.states && levelOptions.states[state]) || {}, values = ['borderRadius', 'linkColor', 'linkLineWidth'] + .reduce(function (obj, key) { + obj[key] = pick(stateOptions[key], options[key], levelOptions[key], series.options[key]); + return obj; + }, {}); + if (!point.isNode) { + attribs.stroke = values.linkColor; + attribs['stroke-width'] = values.linkLineWidth; + delete attribs.fill; + } + else { + if (values.borderRadius) { + attribs.r = values.borderRadius; + } + } + return attribs; + }, + createNode: function (id) { + var node = base.createNode + .call(this, id); + // All nodes in an org chart are equal width + node.getSum = function () { + return 1; + }; + return node; + }, + createNodeColumn: function () { + var column = base.createNodeColumn.call(this); + // Wrap the offset function so that the hanging node's children are + // aligned to their parent + wrap(column, 'offset', function (proceed, node, factor) { + var offset = proceed.call(this, node, factor); // eslint-disable-line no-invalid-this + // Modify the default output if the parent's layout is 'hanging' + if (node.hangsFrom) { + return { + absoluteTop: node.hangsFrom.nodeY + }; + } + return offset; + }); + return column; + }, + translateNode: function (node, column) { + base.translateNode.call(this, node, column); + if (node.hangsFrom) { + node.shapeArgs.height -= + this.options.hangingIndent; + if (!this.chart.inverted) { + node.shapeArgs.y += this.options.hangingIndent; + } + } + node.nodeHeight = this.chart.inverted ? + node.shapeArgs.width : + node.shapeArgs.height; + }, + // General function to apply corner radius to a path - can be lifted to + // renderer or utilities if we need it elsewhere. + curvedPath: function (path, r) { + var d = []; + for (var i = 0; i < path.length; i++) { + var x = path[i][1]; + var y = path[i][2]; + if (typeof x === 'number' && typeof y === 'number') { + // moveTo + if (i === 0) { + d.push(['M', x, y]); + } + else if (i === path.length - 1) { + d.push(['L', x, y]); + // curveTo + } + else if (r) { + var prevSeg = path[i - 1]; + var nextSeg = path[i + 1]; + if (prevSeg && nextSeg) { + var x1 = prevSeg[1], y1 = prevSeg[2], x2 = nextSeg[1], y2 = nextSeg[2]; + // Only apply to breaks + if (typeof x1 === 'number' && + typeof x2 === 'number' && + typeof y1 === 'number' && + typeof y2 === 'number' && + x1 !== x2 && + y1 !== y2) { + var directionX = x1 < x2 ? 1 : -1, directionY = y1 < y2 ? 1 : -1; + d.push([ + 'L', + x - directionX * Math.min(Math.abs(x - x1), r), + y - directionY * Math.min(Math.abs(y - y1), r) + ], [ + 'C', + x, + y, + x, + y, + x + directionX * Math.min(Math.abs(x - x2), r), + y + directionY * Math.min(Math.abs(y - y2), r) + ]); + } + } + // lineTo + } + else { + d.push(['L', x, y]); + } + } + } + return d; + }, + translateLink: function (point) { + var fromNode = point.fromNode, toNode = point.toNode, crisp = Math.round(this.options.linkLineWidth) % 2 / 2, x1 = Math.floor(fromNode.shapeArgs.x + + fromNode.shapeArgs.width) + crisp, y1 = Math.floor(fromNode.shapeArgs.y + + fromNode.shapeArgs.height / 2) + crisp, x2 = Math.floor(toNode.shapeArgs.x) + crisp, y2 = Math.floor(toNode.shapeArgs.y + + toNode.shapeArgs.height / 2) + crisp, xMiddle, hangingIndent = this.options.hangingIndent, toOffset = toNode.options.offset, percentOffset = /%$/.test(toOffset) && parseInt(toOffset, 10), inverted = this.chart.inverted; + if (inverted) { + x1 -= fromNode.shapeArgs.width; + x2 += toNode.shapeArgs.width; + } + xMiddle = Math.floor(x2 + + (inverted ? 1 : -1) * + (this.colDistance - this.nodeWidth) / 2) + crisp; + // Put the link on the side of the node when an offset is given. HR + // node in the main demo. + if (percentOffset && + (percentOffset >= 50 || percentOffset <= -50)) { + xMiddle = x2 = Math.floor(x2 + (inverted ? -0.5 : 0.5) * + toNode.shapeArgs.width) + crisp; + y2 = toNode.shapeArgs.y; + if (percentOffset > 0) { + y2 += toNode.shapeArgs.height; + } + } + if (toNode.hangsFrom === fromNode) { + if (this.chart.inverted) { + y1 = Math.floor(fromNode.shapeArgs.y + + fromNode.shapeArgs.height - + hangingIndent / 2) + crisp; + y2 = (toNode.shapeArgs.y + + toNode.shapeArgs.height); + } + else { + y1 = Math.floor(fromNode.shapeArgs.y + + hangingIndent / 2) + crisp; + } + xMiddle = x2 = Math.floor(toNode.shapeArgs.x + + toNode.shapeArgs.width / 2) + crisp; + } + point.plotY = 1; + point.shapeType = 'path'; + point.shapeArgs = { + d: this.curvedPath([ + ['M', x1, y1], + ['L', xMiddle, y1], + ['L', xMiddle, y2], + ['L', x2, y2] + ], this.options.linkRadius) + }; + }, + alignDataLabel: function (point, dataLabel, options) { + // Align the data label to the point graphic + if (options.useHTML) { + var width = point.shapeArgs.width, height = point.shapeArgs.height, padjust = (this.options.borderWidth + + 2 * this.options.dataLabels.padding); + if (this.chart.inverted) { + width = height; + height = point.shapeArgs.width; + } + height -= padjust; + width -= padjust; + // Set the size of the surrounding div emulating `g` + var text = dataLabel.text; + if (text) { + css(text.element.parentNode, { + width: width + 'px', + height: height + 'px' + }); + // Set properties for the span emulating `text` + css(text.element, { + left: 0, + top: 0, + width: '100%', + height: '100%', + overflow: 'hidden' + }); + } + // The getBBox function is used in `alignDataLabel` to align + // inside the box + dataLabel.getBBox = function () { + return { + width: width, + height: height + }; + }; + // Overwrite dataLabel dimensions (#13100). + dataLabel.width = width; + dataLabel.height = height; + } + H.seriesTypes.column.prototype.alignDataLabel.apply(this, arguments); + } +}); +/** + * An `organization` series. If the [type](#series.organization.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.organization + * @exclude dataSorting + * @product highcharts + * @requires modules/organization + * @apioption series.organization + */ +/** + * @type {Highcharts.SeriesOrganizationDataLabelsOptionsObject|Array} + * @product highcharts + * @apioption series.organization.data.dataLabels + */ +/** + * A collection of options for the individual nodes. The nodes in an org chart + * are auto-generated instances of `Highcharts.Point`, but options can be + * applied here and linked by the `id`. + * + * @extends series.sankey.nodes + * @type {Array<*>} + * @product highcharts + * @apioption series.organization.nodes + */ +/** + * Individual data label for each node. The options are the same as + * the ones for [series.organization.dataLabels](#series.organization.dataLabels). + * + * @type {Highcharts.SeriesOrganizationDataLabelsOptionsObject|Array} + * + * @apioption series.organization.nodes.dataLabels + */ +/** + * The job description for the node card, will be inserted by the default + * `dataLabel.nodeFormatter`. + * + * @sample highcharts/demo/organization-chart + * Org chart with job descriptions + * + * @type {string} + * @product highcharts + * @apioption series.organization.nodes.description + */ +/** + * An image for the node card, will be inserted by the default + * `dataLabel.nodeFormatter`. + * + * @sample highcharts/demo/organization-chart + * Org chart with images + * + * @type {string} + * @product highcharts + * @apioption series.organization.nodes.image + */ +/** + * Layout for the node's children. If `hanging`, this node's children will hang + * below their parent, allowing a tighter packing of nodes in the diagram. + * + * @sample highcharts/demo/organization-chart + * Hanging layout + * + * @type {Highcharts.SeriesOrganizationNodesLayoutValue} + * @default normal + * @product highcharts + * @apioption series.organization.nodes.layout + */ +/** + * The job title for the node card, will be inserted by the default + * `dataLabel.nodeFormatter`. + * + * @sample highcharts/demo/organization-chart + * Org chart with job titles + * + * @type {string} + * @product highcharts + * @apioption series.organization.nodes.title + */ +/** + * An array of data points for the series. For the `organization` series + * type, points can be given in the following way: + * + * An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of data + * points exceeds the series' [turboThreshold](#series.area.turboThreshold), + * this option is not available. + * + * ```js + * data: [{ + * from: 'Category1', + * to: 'Category2', + * weight: 2 + * }, { + * from: 'Category1', + * to: 'Category3', + * weight: 5 + * }] + * ``` + * + * @type {Array<*>} + * @extends series.sankey.data + * @product highcharts + * @apioption series.organization.data + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/modules/overlapping-datalabels.src.js b/librerias/gantt/code/es-modules/modules/overlapping-datalabels.src.js new file mode 100644 index 0000000..3838e58 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/overlapping-datalabels.src.js @@ -0,0 +1,192 @@ +/* * + * + * Highcharts module to hide overlapping data labels. + * This module is included in Highcharts. + * + * (c) 2009-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, fireEvent = U.fireEvent, isArray = U.isArray, objectEach = U.objectEach, pick = U.pick; +import '../parts/Chart.js'; +var Chart = H.Chart; +/* eslint-disable no-invalid-this */ +// Collect potensial overlapping data labels. Stack labels probably don't need +// to be considered because they are usually accompanied by data labels that lie +// inside the columns. +addEvent(Chart, 'render', function collectAndHide() { + var labels = []; + // Consider external label collectors + (this.labelCollectors || []).forEach(function (collector) { + labels = labels.concat(collector()); + }); + (this.yAxis || []).forEach(function (yAxis) { + if (yAxis.stacking && + yAxis.options.stackLabels && + !yAxis.options.stackLabels.allowOverlap) { + objectEach(yAxis.stacking.stacks, function (stack) { + objectEach(stack, function (stackItem) { + labels.push(stackItem.label); + }); + }); + } + }); + (this.series || []).forEach(function (series) { + var dlOptions = series.options.dataLabels; + if (series.visible && + !(dlOptions.enabled === false && !series._hasPointLabels)) { // #3866 + (series.nodes || series.points).forEach(function (point) { + if (point.visible) { + var dataLabels = (isArray(point.dataLabels) ? + point.dataLabels : + (point.dataLabel ? [point.dataLabel] : [])); + dataLabels.forEach(function (label) { + var options = label.options; + label.labelrank = pick(options.labelrank, point.labelrank, point.shapeArgs && point.shapeArgs.height); // #4118 + if (!options.allowOverlap) { + labels.push(label); + } + }); + } + }); + } + }); + this.hideOverlappingLabels(labels); +}); +/** + * Hide overlapping labels. Labels are moved and faded in and out on zoom to + * provide a smooth visual imression. + * + * @private + * @function Highcharts.Chart#hideOverlappingLabels + * @param {Array} labels + * Rendered data labels + * @return {void} + * @requires modules/overlapping-datalabels + */ +Chart.prototype.hideOverlappingLabels = function (labels) { + var chart = this, len = labels.length, ren = chart.renderer, label, i, j, label1, label2, box1, box2, isLabelAffected = false, isIntersectRect = function (box1, box2) { + return !(box2.x > box1.x + box1.width || + box2.x + box2.width < box1.x || + box2.y > box1.y + box1.height || + box2.y + box2.height < box1.y); + }, + // Get the box with its position inside the chart, as opposed to getBBox + // that only reports the position relative to the parent. + getAbsoluteBox = function (label) { + var pos, parent, bBox, + // Substract the padding if no background or border (#4333) + padding = label.box ? 0 : (label.padding || 0), lineHeightCorrection = 0, xOffset = 0, boxWidth, alignValue; + if (label && + (!label.alignAttr || label.placed)) { + pos = label.alignAttr || { + x: label.attr('x'), + y: label.attr('y') + }; + parent = label.parentGroup; + // Get width and height if pure text nodes (stack labels) + if (!label.width) { + bBox = label.getBBox(); + label.width = bBox.width; + label.height = bBox.height; + // Labels positions are computed from top left corner, so + // we need to substract the text height from text nodes too. + lineHeightCorrection = ren + .fontMetrics(null, label.element).h; + } + boxWidth = label.width - 2 * padding; + alignValue = { + left: '0', + center: '0.5', + right: '1' + }[label.alignValue]; + if (alignValue) { + xOffset = +alignValue * boxWidth; + } + else if (Math.round(label.x) !== label.translateX) { + xOffset = label.x - label.translateX; + } + return { + x: pos.x + (parent.translateX || 0) + padding - xOffset, + y: pos.y + (parent.translateY || 0) + padding - + lineHeightCorrection, + width: label.width - 2 * padding, + height: label.height - 2 * padding + }; + } + }; + for (i = 0; i < len; i++) { + label = labels[i]; + if (label) { + // Mark with initial opacity + label.oldOpacity = label.opacity; + label.newOpacity = 1; + label.absoluteBox = getAbsoluteBox(label); + } + } + // Prevent a situation in a gradually rising slope, that each label will + // hide the previous one because the previous one always has lower rank. + labels.sort(function (a, b) { + return (b.labelrank || 0) - (a.labelrank || 0); + }); + // Detect overlapping labels + for (i = 0; i < len; i++) { + label1 = labels[i]; + box1 = label1 && label1.absoluteBox; + for (j = i + 1; j < len; ++j) { + label2 = labels[j]; + box2 = label2 && label2.absoluteBox; + if (box1 && + box2 && + label1 !== label2 && // #6465, polar chart with connectEnds + label1.newOpacity !== 0 && + label2.newOpacity !== 0) { + if (isIntersectRect(box1, box2)) { + (label1.labelrank < label2.labelrank ? label1 : label2) + .newOpacity = 0; + } + } + } + } + // Hide or show + labels.forEach(function (label) { + var complete, newOpacity; + if (label) { + newOpacity = label.newOpacity; + if (label.oldOpacity !== newOpacity) { + // Make sure the label is completely hidden to avoid catching + // clicks (#4362) + if (label.alignAttr && label.placed) { // data labels + label[newOpacity ? 'removeClass' : 'addClass']('highcharts-data-label-hidden'); + complete = function () { + if (!chart.styledMode) { + label.css({ pointerEvents: newOpacity ? 'auto' : 'none' }); + } + label.visibility = newOpacity ? 'inherit' : 'hidden'; + label.placed = !!newOpacity; + }; + isLabelAffected = true; + // Animate or set the opacity + label.alignAttr.opacity = newOpacity; + label[label.isOld ? 'animate' : 'attr'](label.alignAttr, null, complete); + fireEvent(chart, 'afterHideOverlappingLabel'); + } + else { // other labels, tick labels + label.attr({ + opacity: newOpacity + }); + } + } + label.isOld = true; + } + }); + if (isLabelAffected) { + fireEvent(chart, 'afterHideAllOverlappingLabels'); + } +}; diff --git a/librerias/gantt/code/es-modules/modules/parallel-coordinates.src.js b/librerias/gantt/code/es-modules/modules/parallel-coordinates.src.js new file mode 100644 index 0000000..b7d1706 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/parallel-coordinates.src.js @@ -0,0 +1,451 @@ +/* * + * + * Parallel coordinates module + * + * (c) 2010-2020 Pawel Fus + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Axis from '../parts/Axis.js'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, arrayMax = U.arrayMax, arrayMin = U.arrayMin, defined = U.defined, erase = U.erase, extend = U.extend, format = U.format, merge = U.merge, pick = U.pick, splat = U.splat, wrap = U.wrap; +import '../parts/Chart.js'; +import '../parts/Series.js'; +// Extensions for parallel coordinates plot. +var Chart = H.Chart, ChartProto = Chart.prototype; +var defaultXAxisOptions = { + lineWidth: 0, + tickLength: 0, + opposite: true, + type: 'category' +}; +/* eslint-disable valid-jsdoc */ +/** + * @optionparent chart + */ +var defaultParallelOptions = { + /** + * Flag to render charts as a parallel coordinates plot. In a parallel + * coordinates plot (||-coords) by default all required yAxes are generated + * and the legend is disabled. This feature requires + * `modules/parallel-coordinates.js`. + * + * @sample {highcharts} /highcharts/demo/parallel-coordinates/ + * Parallel coordinates demo + * @sample {highcharts} highcharts/parallel-coordinates/polar/ + * Star plot, multivariate data in a polar chart + * + * @since 6.0.0 + * @product highcharts + * @requires modules/parallel-coordinates + */ + parallelCoordinates: false, + /** + * Common options for all yAxes rendered in a parallel coordinates plot. + * This feature requires `modules/parallel-coordinates.js`. + * + * The default options are: + * ```js + * parallelAxes: { + * lineWidth: 1, // classic mode only + * gridlinesWidth: 0, // classic mode only + * title: { + * text: '', + * reserveSpace: false + * }, + * labels: { + * x: 0, + * y: 0, + * align: 'center', + * reserveSpace: false + * }, + * offset: 0 + * } + * ``` + * + * @sample {highcharts} highcharts/parallel-coordinates/parallelaxes/ + * Set the same tickAmount for all yAxes + * + * @extends yAxis + * @since 6.0.0 + * @product highcharts + * @excluding alternateGridColor, breaks, id, gridLineColor, + * gridLineDashStyle, gridLineWidth, minorGridLineColor, + * minorGridLineDashStyle, minorGridLineWidth, plotBands, + * plotLines, angle, gridLineInterpolation, maxColor, maxZoom, + * minColor, scrollbar, stackLabels, stops + * @requires modules/parallel-coordinates + */ + parallelAxes: { + lineWidth: 1, + /** + * Titles for yAxes are taken from + * [xAxis.categories](#xAxis.categories). All options for `xAxis.labels` + * applies to parallel coordinates titles. For example, to style + * categories, use [xAxis.labels.style](#xAxis.labels.style). + * + * @excluding align, enabled, margin, offset, position3d, reserveSpace, + * rotation, skew3d, style, text, useHTML, x, y + */ + title: { + text: '', + reserveSpace: false + }, + labels: { + x: 0, + y: 4, + align: 'center', + reserveSpace: false + }, + offset: 0 + } +}; +H.setOptions({ + chart: defaultParallelOptions +}); +/** + * Support for parallel axes. + * @private + * @class + */ +var ParallelAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function ParallelAxisAdditions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Set predefined left+width and top+height (inverted) for yAxes. + * This method modifies options param. + * + * @private + * + * @param {Array} axisPosition + * ['left', 'width', 'height', 'top'] or ['top', 'height', 'width', 'left'] + * for an inverted chart. + * + * @param {Highcharts.AxisOptions} options + * Axis options. + */ + ParallelAxisAdditions.prototype.setPosition = function (axisPosition, options) { + var parallel = this; + var axis = parallel.axis; + var chart = axis.chart; + var fraction = ((parallel.position || 0) + 0.5) / + (chart.parallelInfo.counter + 1); + if (chart.polar) { + options.angle = 360 * fraction; + } + else { + options[axisPosition[0]] = 100 * fraction + '%'; + axis[axisPosition[1]] = + options[axisPosition[1]] = 0; + // In case of chart.update(inverted), remove old options: + axis[axisPosition[2]] = + options[axisPosition[2]] = null; + axis[axisPosition[3]] = + options[axisPosition[3]] = null; + } + }; + return ParallelAxisAdditions; +}()); +/** + * Axis with parallel support. + * @private + * @class + */ +var ParallelAxis = /** @class */ (function () { + function ParallelAxis() { + } + /** + * Adds support for parallel axes. + * @private + */ + ParallelAxis.compose = function (AxisClass) { + /* eslint-disable no-invalid-this */ + // On update, keep parallel additions. + AxisClass.keepProps.push('parallel'); + // Add parallel addition + addEvent(AxisClass, 'init', function () { + var axis = this; + if (!axis.parallelCoordinates) { + axis.parallelCoordinates = new ParallelAxisAdditions(axis); + } + }); + // Update default options with predefined for a parallel coords. + addEvent(AxisClass, 'afterSetOptions', function (e) { + var axis = this; + var chart = axis.chart; + var parallelCoordinates = axis.parallelCoordinates; + var axisPosition = ['left', 'width', 'height', 'top']; + if (chart.hasParallelCoordinates) { + if (chart.inverted) { + axisPosition = axisPosition.reverse(); + } + if (axis.isXAxis) { + axis.options = merge(axis.options, defaultXAxisOptions, e.userOptions); + } + else { + axis.options = merge(axis.options, axis.chart.options.chart.parallelAxes, e.userOptions); + parallelCoordinates.position = pick(parallelCoordinates.position, chart.yAxis.length); + parallelCoordinates.setPosition(axisPosition, axis.options); + } + } + }); + // Each axis should gather extremes from points on a particular position + // in series.data. Not like the default one, which gathers extremes from + // all series bind to this axis. Consider using series.points instead of + // series.yData. + addEvent(AxisClass, 'getSeriesExtremes', function (e) { + var axis = this; + var chart = axis.chart; + var parallelCoordinates = axis.parallelCoordinates; + if (!parallelCoordinates) { + return; + } + if (chart && chart.hasParallelCoordinates && !axis.isXAxis) { + var index = parallelCoordinates.position, currentPoints = []; + axis.series.forEach(function (series) { + if (series.visible && + defined(series.yData[index])) { + // We need to use push() beacause of null points + currentPoints.push(series.yData[index]); + } + }); + axis.dataMin = arrayMin(currentPoints); + axis.dataMax = arrayMax(currentPoints); + e.preventDefault(); + } + }); + /* eslint-enable no-invalid-this */ + }; + return ParallelAxis; +}()); +ParallelAxis.compose(Axis); +export default ParallelAxis; +/* eslint-disable no-invalid-this */ +// Initialize parallelCoordinates +addEvent(Chart, 'init', function (e) { + var options = e.args[0], defaultyAxis = splat(options.yAxis || {}), yAxisLength = defaultyAxis.length, newYAxes = []; + /** + * Flag used in parallel coordinates plot to check if chart has ||-coords + * (parallel coords). + * + * @requires module:modules/parallel-coordinates + * + * @name Highcharts.Chart#hasParallelCoordinates + * @type {boolean} + */ + this.hasParallelCoordinates = options.chart && + options.chart.parallelCoordinates; + if (this.hasParallelCoordinates) { + this.setParallelInfo(options); + // Push empty yAxes in case user did not define them: + for (; yAxisLength <= this.parallelInfo.counter; yAxisLength++) { + newYAxes.push({}); + } + if (!options.legend) { + options.legend = {}; + } + if (typeof options.legend.enabled === 'undefined') { + options.legend.enabled = false; + } + merge(true, options, + // Disable boost + { + boost: { + seriesThreshold: Number.MAX_VALUE + }, + plotOptions: { + series: { + boostThreshold: Number.MAX_VALUE + } + } + }); + options.yAxis = defaultyAxis.concat(newYAxes); + options.xAxis = merge(defaultXAxisOptions, // docs + splat(options.xAxis || {})[0]); + } +}); +// Initialize parallelCoordinates +addEvent(Chart, 'update', function (e) { + var options = e.options; + if (options.chart) { + if (defined(options.chart.parallelCoordinates)) { + this.hasParallelCoordinates = options.chart.parallelCoordinates; + } + this.options.chart.parallelAxes = merge(this.options.chart.parallelAxes, options.chart.parallelAxes); + } + if (this.hasParallelCoordinates) { + // (#10081) + if (options.series) { + this.setParallelInfo(options); + } + this.yAxis.forEach(function (axis) { + axis.update({}, false); + }); + } +}); +/* eslint-disable valid-jsdoc */ +extend(ChartProto, /** @lends Highcharts.Chart.prototype */ { + /** + * Define how many parellel axes we have according to the longest dataset. + * This is quite heavy - loop over all series and check series.data.length + * Consider: + * + * - make this an option, so user needs to set this to get better + * performance + * + * - check only first series for number of points and assume the rest is the + * same + * + * @private + * @function Highcharts.Chart#setParallelInfo + * @param {Highcharts.Options} options + * User options + * @return {void} + * @requires modules/parallel-coordinates + */ + setParallelInfo: function (options) { + var chart = this, seriesOptions = options.series; + chart.parallelInfo = { + counter: 0 + }; + seriesOptions.forEach(function (series) { + if (series.data) { + chart.parallelInfo.counter = Math.max(chart.parallelInfo.counter, series.data.length - 1); + } + }); + } +}); +// Bind each series to each yAxis. yAxis needs a reference to all series to +// calculate extremes. +addEvent(H.Series, 'bindAxes', function (e) { + if (this.chart.hasParallelCoordinates) { + var series = this; + this.chart.axes.forEach(function (axis) { + series.insert(axis.series); + axis.isDirty = true; + }); + series.xAxis = this.chart.xAxis[0]; + series.yAxis = this.chart.yAxis[0]; + e.preventDefault(); + } +}); +// Translate each point using corresponding yAxis. +addEvent(H.Series, 'afterTranslate', function () { + var series = this, chart = this.chart, points = series.points, dataLength = points && points.length, closestPointRangePx = Number.MAX_VALUE, lastPlotX, point, i; + if (this.chart.hasParallelCoordinates) { + for (i = 0; i < dataLength; i++) { + point = points[i]; + if (defined(point.y)) { + if (chart.polar) { + point.plotX = chart.yAxis[i].angleRad || 0; + } + else if (chart.inverted) { + point.plotX = (chart.plotHeight - + chart.yAxis[i].top + + chart.plotTop); + } + else { + point.plotX = chart.yAxis[i].left - chart.plotLeft; + } + point.clientX = point.plotX; + point.plotY = chart.yAxis[i] + .translate(point.y, false, true, null, true); + if (typeof lastPlotX !== 'undefined') { + closestPointRangePx = Math.min(closestPointRangePx, Math.abs(point.plotX - lastPlotX)); + } + lastPlotX = point.plotX; + point.isInside = chart.isInsidePlot(point.plotX, point.plotY, chart.inverted); + } + else { + point.isNull = true; + } + } + this.closestPointRangePx = closestPointRangePx; + } +}, { order: 1 }); +// On destroy, we need to remove series from each axis.series +addEvent(H.Series, 'destroy', function () { + if (this.chart.hasParallelCoordinates) { + (this.chart.axes || []).forEach(function (axis) { + if (axis && axis.series) { + erase(axis.series, this); + axis.isDirty = axis.forceRedraw = true; + } + }, this); + } +}); +/** + * @private + */ +function addFormattedValue(proceed) { + var chart = this.series && this.series.chart, config = proceed.apply(this, Array.prototype.slice.call(arguments, 1)), formattedValue, yAxisOptions, labelFormat, yAxis; + if (chart && + chart.hasParallelCoordinates && + !defined(config.formattedValue)) { + yAxis = chart.yAxis[this.x]; + yAxisOptions = yAxis.options; + labelFormat = pick( + /** + * Parallel coordinates only. Format that will be used for point.y + * and available in [tooltip.pointFormat](#tooltip.pointFormat) as + * `{point.formattedValue}`. If not set, `{point.formattedValue}` + * will use other options, in this order: + * + * 1. [yAxis.labels.format](#yAxis.labels.format) will be used if + * set + * + * 2. If yAxis is a category, then category name will be displayed + * + * 3. If yAxis is a datetime, then value will use the same format as + * yAxis labels + * + * 4. If yAxis is linear/logarithmic type, then simple value will be + * used + * + * @sample {highcharts} + * /highcharts/parallel-coordinates/tooltipvalueformat/ + * Different tooltipValueFormats's + * + * @type {string} + * @default undefined + * @since 6.0.0 + * @product highcharts + * @requires modules/parallel-coordinates + * @apioption yAxis.tooltipValueFormat + */ + yAxisOptions.tooltipValueFormat, yAxisOptions.labels.format); + if (labelFormat) { + formattedValue = format(labelFormat, extend(this, { value: this.y }), chart); + } + else if (yAxis.dateTime) { + formattedValue = chart.time.dateFormat(chart.time.resolveDTLFormat(yAxisOptions.dateTimeLabelFormats[yAxis.tickPositions.info.unitName]).main, this.y); + } + else if (yAxisOptions.categories) { + formattedValue = yAxisOptions.categories[this.y]; + } + else { + formattedValue = this.y; + } + config.formattedValue = config.point.formattedValue = formattedValue; + } + return config; +} +['line', 'spline'].forEach(function (seriesName) { + wrap(H.seriesTypes[seriesName].prototype.pointClass.prototype, 'getLabelConfig', addFormattedValue); +}); diff --git a/librerias/gantt/code/es-modules/modules/pareto.src.js b/librerias/gantt/code/es-modules/modules/pareto.src.js new file mode 100644 index 0000000..82f0a05 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/pareto.src.js @@ -0,0 +1,140 @@ +/* * + * + * (c) 2010-2017 Sebastian Bochan + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import U from '../parts/Utilities.js'; +var correctFloat = U.correctFloat, merge = U.merge, seriesType = U.seriesType; +import '../parts/Options.js'; +import derivedSeriesMixin from '../mixins/derived-series.js'; +/** + * The pareto series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.pareto + * + * @augments Highcharts.Series + */ +seriesType('pareto', 'line' +/** + * A pareto diagram is a type of chart that contains both bars and a line + * graph, where individual values are represented in descending order by + * bars, and the cumulative total is represented by the line. + * + * @sample {highcharts} highcharts/demo/pareto/ + * Pareto diagram + * + * @extends plotOptions.line + * @since 6.0.0 + * @product highcharts + * @excluding allAreas, boostThreshold, borderColor, borderRadius, + * borderWidth, crisp, colorAxis, depth, data, dragDrop, + * edgeColor, edgeWidth, findNearestPointBy, gapSize, gapUnit, + * grouping, groupPadding, groupZPadding, maxPointWidth, keys, + * negativeColor, pointInterval, pointIntervalUnit, + * pointPadding, pointPlacement, pointRange, pointStart, + * pointWidth, shadow, step, softThreshold, stacking, + * threshold, zoneAxis, zones + * @requires modules/pareto + * @optionparent plotOptions.pareto + */ +, { + /** + * Higher zIndex than column series to draw line above shapes. + */ + zIndex: 3 +}, +/* eslint-disable no-invalid-this, valid-jsdoc */ +merge(derivedSeriesMixin, { + /** + * Calculate sum and return percent points. + * + * @private + * @function Highcharts.Series#setDerivedData + * @requires modules/pareto + */ + setDerivedData: function () { + var xValues = this.baseSeries.xData, yValues = this.baseSeries.yData, sum = this.sumPointsPercents(yValues, xValues, null, true); + this.setData(this.sumPointsPercents(yValues, xValues, sum, false), false); + }, + /** + * Calculate y sum and each percent point. + * + * @private + * @function Highcharts.Series#sumPointsPercents + * + * @param {Array} yValues + * Y values + * + * @param {Array} xValues + * X values + * + * @param {number} sum + * Sum of all y values + * + * @param {boolean} [isSum] + * Declares if calculate sum of all points + * + * @return {number|Array} + * Returns sum of points or array of points [x,sum] + * + * @requires modules/pareto + */ + sumPointsPercents: function (yValues, xValues, sum, isSum) { + var sumY = 0, sumPercent = 0, percentPoints = [], percentPoint; + yValues.forEach(function (point, i) { + if (point !== null) { + if (isSum) { + sumY += point; + } + else { + percentPoint = (point / sum) * 100; + percentPoints.push([ + xValues[i], + correctFloat(sumPercent + percentPoint) + ]); + sumPercent += percentPoint; + } + } + }); + return (isSum ? sumY : percentPoints); + } +}) +/* eslint-enable no-invalid-this, valid-jsdoc */ +); +/** + * A `pareto` series. If the [type](#series.pareto.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.pareto + * @since 6.0.0 + * @product highcharts + * @excluding data, dataParser, dataURL + * @requires modules/pareto + * @apioption series.pareto + */ +/** + * An integer identifying the index to use for the base series, or a string + * representing the id of the series. + * + * @type {number|string} + * @default undefined + * @apioption series.pareto.baseSeries + */ +/** + * An array of data points for the series. For the `pareto` series type, + * points are calculated dynamically. + * + * @type {Array|*>} + * @extends series.column.data + * @since 6.0.0 + * @product highcharts + * @apioption series.pareto.data + */ +''; // adds the doclets above to the transpiled file diff --git a/librerias/gantt/code/es-modules/modules/pattern-fill.src.js b/librerias/gantt/code/es-modules/modules/pattern-fill.src.js new file mode 100644 index 0000000..3bb9126 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/pattern-fill.src.js @@ -0,0 +1,544 @@ +/* * + * + * Module for using patterns or images as point fills. + * + * (c) 2010-2020 Highsoft AS + * Author: Torstein Hønsi, Øystein Moseng + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +/** + * Pattern options + * + * @interface Highcharts.PatternOptionsObject + */ /** +* Background color for the pattern if a `path` is set (not images). +* @name Highcharts.PatternOptionsObject#backgroundColor +* @type {Highcharts.ColorString} +*/ /** +* URL to an image to use as the pattern. +* @name Highcharts.PatternOptionsObject#image +* @type {string} +*/ /** +* Width of the pattern. For images this is automatically set to the width of +* the element bounding box if not supplied. For non-image patterns the default +* is 32px. Note that automatic resizing of image patterns to fill a bounding +* box dynamically is only supported for patterns with an automatically +* calculated ID. +* @name Highcharts.PatternOptionsObject#width +* @type {number} +*/ /** +* Analogous to pattern.width. +* @name Highcharts.PatternOptionsObject#height +* @type {number} +*/ /** +* For automatically calculated width and height on images, it is possible to +* set an aspect ratio. The image will be zoomed to fill the bounding box, +* maintaining the aspect ratio defined. +* @name Highcharts.PatternOptionsObject#aspectRatio +* @type {number} +*/ /** +* Horizontal offset of the pattern. Defaults to 0. +* @name Highcharts.PatternOptionsObject#x +* @type {number|undefined} +*/ /** +* Vertical offset of the pattern. Defaults to 0. +* @name Highcharts.PatternOptionsObject#y +* @type {number|undefined} +*/ /** +* Either an SVG path as string, or an object. As an object, supply the path +* string in the `path.d` property. Other supported properties are standard SVG +* attributes like `path.stroke` and `path.fill`. If a path is supplied for the +* pattern, the `image` property is ignored. +* @name Highcharts.PatternOptionsObject#path +* @type {string|Highcharts.SVGAttributes} +*/ /** +* SVG `patternTransform` to apply to the entire pattern. +* @name Highcharts.PatternOptionsObject#patternTransform +* @type {string} +* @see [patternTransform demo](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/series/pattern-fill-transform) +*/ /** +* Pattern color, used as default path stroke. +* @name Highcharts.PatternOptionsObject#color +* @type {Highcharts.ColorString} +*/ /** +* Opacity of the pattern as a float value from 0 to 1. +* @name Highcharts.PatternOptionsObject#opacity +* @type {number} +*/ /** +* ID to assign to the pattern. This is automatically computed if not added, and +* identical patterns are reused. To refer to an existing pattern for a +* Highcharts color, use `color: "url(#pattern-id)"`. +* @name Highcharts.PatternOptionsObject#id +* @type {string|undefined} +*/ +/** + * Holds a pattern definition. + * + * @sample highcharts/series/pattern-fill-area/ + * Define a custom path pattern + * @sample highcharts/series/pattern-fill-pie/ + * Default patterns and a custom image pattern + * @sample maps/demo/pattern-fill-map/ + * Custom images on map + * + * @example + * // Pattern used as a color option + * color: { + * pattern: { + * path: { + * d: 'M 3 3 L 8 3 L 8 8 Z', + * fill: '#102045' + * }, + * width: 12, + * height: 12, + * color: '#907000', + * opacity: 0.5 + * } + * } + * + * @interface Highcharts.PatternObject + */ /** +* Pattern options +* @name Highcharts.PatternObject#pattern +* @type {Highcharts.PatternOptionsObject} +*/ /** +* Animation options for the image pattern loading. +* @name Highcharts.PatternObject#animation +* @type {boolean|Highcharts.AnimationOptionsObject|undefined} +*/ /** +* Optionally an index referencing which pattern to use. Highcharts adds +* 10 default patterns to the `Highcharts.patterns` array. Additional +* pattern definitions can be pushed to this array if desired. This option +* is an index into this array. +* @name Highcharts.PatternObject#patternIndex +* @type {number|undefined} +*/ +''; // detach doclets above +import Point from '../parts/Point.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, animObject = U.animObject, erase = U.erase, merge = U.merge, pick = U.pick, removeEvent = U.removeEvent, wrap = U.wrap; +// Add the predefined patterns +H.patterns = (function () { + var patterns = [], colors = H.getOptions().colors; + [ + 'M 0 0 L 10 10 M 9 -1 L 11 1 M -1 9 L 1 11', + 'M 0 10 L 10 0 M -1 1 L 1 -1 M 9 11 L 11 9', + 'M 3 0 L 3 10 M 8 0 L 8 10', + 'M 0 3 L 10 3 M 0 8 L 10 8', + 'M 0 3 L 5 3 L 5 0 M 5 10 L 5 7 L 10 7', + 'M 3 3 L 8 3 L 8 8 L 3 8 Z', + 'M 5 5 m -4 0 a 4 4 0 1 1 8 0 a 4 4 0 1 1 -8 0', + 'M 10 3 L 5 3 L 5 0 M 5 10 L 5 7 L 0 7', + 'M 2 5 L 5 2 L 8 5 L 5 8 Z', + 'M 0 0 L 5 10 L 10 0' + ].forEach(function (pattern, i) { + patterns.push({ + path: pattern, + color: colors[i], + width: 10, + height: 10 + }); + }); + return patterns; +})(); +/** + * Utility function to compute a hash value from an object. Modified Java + * String.hashCode implementation in JS. Use the preSeed parameter to add an + * additional seeding step. + * + * @private + * @function hashFromObject + * + * @param {object} obj + * The javascript object to compute the hash from. + * + * @param {boolean} [preSeed=false] + * Add an optional preSeed stage. + * + * @return {string} + * The computed hash. + */ +function hashFromObject(obj, preSeed) { + var str = JSON.stringify(obj), strLen = str.length || 0, hash = 0, i = 0, char, seedStep; + if (preSeed) { + seedStep = Math.max(Math.floor(strLen / 500), 1); + for (var a = 0; a < strLen; a += seedStep) { + hash += str.charCodeAt(a); + } + hash = hash & hash; + } + for (; i < strLen; ++i) { + char = str.charCodeAt(i); + hash = ((hash << 5) - hash) + char; + hash = hash & hash; + } + return hash.toString(16).replace('-', '1'); +} +/** + * Set dimensions on pattern from point. This function will set internal + * pattern._width/_height properties if width and height are not both already + * set. We only do this on image patterns. The _width/_height properties are set + * to the size of the bounding box of the point, optionally taking aspect ratio + * into account. If only one of width or height are supplied as options, the + * undefined option is calculated as above. + * + * @private + * @function Highcharts.Point#calculatePatternDimensions + * + * @param {Highcharts.PatternOptionsObject} pattern + * The pattern to set dimensions on. + * + * @return {void} + * + * @requires modules/pattern-fill + */ +Point.prototype.calculatePatternDimensions = function (pattern) { + if (pattern.width && pattern.height) { + return; + } + var bBox = this.graphic && (this.graphic.getBBox && + this.graphic.getBBox(true) || + this.graphic.element && + this.graphic.element.getBBox()) || {}, shapeArgs = this.shapeArgs; + // Prefer using shapeArgs, as it is animation agnostic + if (shapeArgs) { + bBox.width = shapeArgs.width || bBox.width; + bBox.height = shapeArgs.height || bBox.height; + bBox.x = shapeArgs.x || bBox.x; + bBox.y = shapeArgs.y || bBox.y; + } + // For images we stretch to bounding box + if (pattern.image) { + // If we do not have a bounding box at this point, simply add a defer + // key and pick this up in the fillSetter handler, where the bounding + // box should exist. + if (!bBox.width || !bBox.height) { + pattern._width = 'defer'; + pattern._height = 'defer'; + return; + } + // Handle aspect ratio filling + if (pattern.aspectRatio) { + bBox.aspectRatio = bBox.width / bBox.height; + if (pattern.aspectRatio > bBox.aspectRatio) { + // Height of bBox will determine width + bBox.aspectWidth = bBox.height * pattern.aspectRatio; + } + else { + // Width of bBox will determine height + bBox.aspectHeight = bBox.width / pattern.aspectRatio; + } + } + // We set the width/height on internal properties to differentiate + // between the options set by a user and by this function. + pattern._width = pattern.width || + Math.ceil(bBox.aspectWidth || bBox.width); + pattern._height = pattern.height || + Math.ceil(bBox.aspectHeight || bBox.height); + } + // Set x/y accordingly, centering if using aspect ratio, otherwise adjusting + // so bounding box corner is 0,0 of pattern. + if (!pattern.width) { + pattern._x = pattern.x || 0; + pattern._x += bBox.x - Math.round(bBox.aspectWidth ? + Math.abs(bBox.aspectWidth - bBox.width) / 2 : + 0); + } + if (!pattern.height) { + pattern._y = pattern.y || 0; + pattern._y += bBox.y - Math.round(bBox.aspectHeight ? + Math.abs(bBox.aspectHeight - bBox.height) / 2 : + 0); + } +}; +/* eslint-disable no-invalid-this */ +/** + * Add a pattern to the renderer. + * + * @private + * @function Highcharts.SVGRenderer#addPattern + * + * @param {Highcharts.PatternObject} options + * The pattern options. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * The animation options. + * + * @return {Highcharts.SVGElement|undefined} + * The added pattern. Undefined if the pattern already exists. + * + * @requires modules/pattern-fill + */ +H.SVGRenderer.prototype.addPattern = function (options, animation) { + var pattern, animate = pick(animation, true), animationOptions = animObject(animate), path, defaultSize = 32, width = options.width || options._width || defaultSize, height = (options.height || options._height || defaultSize), color = options.color || '#343434', id = options.id, ren = this, rect = function (fill) { + ren.rect(0, 0, width, height) + .attr({ fill: fill }) + .add(pattern); + }, attribs; + if (!id) { + this.idCounter = this.idCounter || 0; + id = 'highcharts-pattern-' + this.idCounter + '-' + (this.chartIndex || 0); + ++this.idCounter; + } + // Do nothing if ID already exists + this.defIds = this.defIds || []; + if (this.defIds.indexOf(id) > -1) { + return; + } + // Store ID in list to avoid duplicates + this.defIds.push(id); + // Calculate pattern element attributes + var attrs = { + id: id, + patternUnits: 'userSpaceOnUse', + patternContentUnits: options.patternContentUnits || 'userSpaceOnUse', + width: width, + height: height, + x: options._x || options.x || 0, + y: options._y || options.y || 0 + }; + if (options.patternTransform) { + attrs.patternTransform = options.patternTransform; + } + pattern = this.createElement('pattern').attr(attrs).add(this.defs); + // Set id on the SVGRenderer object + pattern.id = id; + // Use an SVG path for the pattern + if (options.path) { + path = options.path; + // The background + if (options.backgroundColor) { + rect(options.backgroundColor); + } + // The pattern + attribs = { + 'd': path.d || path + }; + if (!this.styledMode) { + attribs.stroke = path.stroke || color; + attribs['stroke-width'] = pick(path.strokeWidth, 2); + attribs.fill = path.fill || 'none'; + } + if (path.transform) { + attribs.transform = path.transform; + } + this.createElement('path').attr(attribs).add(pattern); + pattern.color = color; + // Image pattern + } + else if (options.image) { + if (animate) { + this.image(options.image, 0, 0, width, height, function () { + // Onload + this.animate({ + opacity: pick(options.opacity, 1) + }, animationOptions); + removeEvent(this.element, 'load'); + }).attr({ opacity: 0 }).add(pattern); + } + else { + this.image(options.image, 0, 0, width, height).add(pattern); + } + } + // For non-animated patterns, set opacity now + if (!(options.image && animate) && typeof options.opacity !== 'undefined') { + [].forEach.call(pattern.element.childNodes, function (child) { + child.setAttribute('opacity', options.opacity); + }); + } + // Store for future reference + this.patternElements = this.patternElements || {}; + this.patternElements[id] = pattern; + return pattern; +}; +// Make sure we have a series color +wrap(H.Series.prototype, 'getColor', function (proceed) { + var oldColor = this.options.color; + // Temporarely remove color options to get defaults + if (oldColor && + oldColor.pattern && + !oldColor.pattern.color) { + delete this.options.color; + // Get default + proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + // Replace with old, but add default color + oldColor.pattern.color = + this.color; + this.color = this.options.color = oldColor; + } + else { + // We have a color, no need to do anything special + proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + } +}); +// Calculate pattern dimensions on points that have their own pattern. +addEvent(H.Series, 'render', function () { + var isResizing = this.chart.isResizing; + if (this.isDirtyData || isResizing || !this.chart.hasRendered) { + (this.points || []).forEach(function (point) { + var colorOptions = point.options && point.options.color; + if (colorOptions && + colorOptions.pattern) { + // For most points we want to recalculate the dimensions on + // render, where we have the shape args and bbox. But if we + // are resizing and don't have the shape args, defer it, since + // the bounding box is still not resized. + if (isResizing && + !(point.shapeArgs && + point.shapeArgs.width && + point.shapeArgs.height)) { + colorOptions.pattern._width = + 'defer'; + colorOptions.pattern._height = + 'defer'; + } + else { + point.calculatePatternDimensions(colorOptions.pattern); + } + } + }); + } +}); +// Merge series color options to points +addEvent(Point, 'afterInit', function () { + var point = this, colorOptions = point.options.color; + // Only do this if we have defined a specific color on this point. Otherwise + // we will end up trying to re-add the series color for each point. + if (colorOptions && colorOptions.pattern) { + // Move path definition to object, allows for merge with series path + // definition + if (typeof colorOptions.pattern.path === 'string') { + colorOptions.pattern.path = { + d: colorOptions.pattern.path + }; + } + // Merge with series options + point.color = point.options.color = merge(point.series.options.color, colorOptions); + } +}); +// Add functionality to SVG renderer to handle patterns as complex colors +addEvent(H.SVGRenderer, 'complexColor', function (args) { + var color = args.args[0], prop = args.args[1], element = args.args[2], chartIndex = (this.chartIndex || 0); + var pattern = color.pattern, value = '#343434'; + // Handle patternIndex + if (typeof color.patternIndex !== 'undefined' && H.patterns) { + pattern = H.patterns[color.patternIndex]; + } + // Skip and call default if there is no pattern + if (!pattern) { + return true; + } + // We have a pattern. + if (pattern.image || + typeof pattern.path === 'string' || + pattern.path && pattern.path.d) { + // Real pattern. Add it and set the color value to be a reference. + // Force Hash-based IDs for legend items, as they are drawn before + // point render, meaning they are drawn before autocalculated image + // width/heights. We don't want them to highjack the width/height for + // this ID if it is defined by users. + var forceHashId = element.parentNode && + element.parentNode.getAttribute('class'); + forceHashId = forceHashId && + forceHashId.indexOf('highcharts-legend') > -1; + // If we don't have a width/height yet, handle it. Try faking a point + // and running the algorithm again. + if (pattern._width === 'defer' || pattern._height === 'defer') { + Point.prototype.calculatePatternDimensions.call({ graphic: { element: element } }, pattern); + } + // If we don't have an explicit ID, compute a hash from the + // definition and use that as the ID. This ensures that points with + // the same pattern definition reuse existing pattern elements by + // default. We combine two hashes, the second with an additional + // preSeed algorithm, to minimize collision probability. + if (forceHashId || !pattern.id) { + // Make a copy so we don't accidentally edit options when setting ID + pattern = merge({}, pattern); + pattern.id = 'highcharts-pattern-' + chartIndex + '-' + + hashFromObject(pattern) + hashFromObject(pattern, true); + } + // Add it. This function does nothing if an element with this ID + // already exists. + this.addPattern(pattern, !this.forExport && pick(pattern.animation, this.globalAnimation, { duration: 100 })); + value = "url(" + this.url + "#" + pattern.id + ")"; + } + else { + // Not a full pattern definition, just add color + value = pattern.color || value; + } + // Set the fill/stroke prop on the element + element.setAttribute(prop, value); + // Allow the color to be concatenated into tooltips formatters etc. + color.toString = function () { + return value; + }; + // Skip default handler + return false; +}); +// When animation is used, we have to recalculate pattern dimensions after +// resize, as the bounding boxes are not available until then. +addEvent(H.Chart, 'endResize', function () { + if ((this.renderer && this.renderer.defIds || []).filter(function (id) { + return (id && + id.indexOf && + id.indexOf('highcharts-pattern-') === 0); + }).length) { + // We have non-default patterns to fix. Find them by looping through + // all points. + this.series.forEach(function (series) { + series.points.forEach(function (point) { + var colorOptions = point.options && point.options.color; + if (colorOptions && + colorOptions.pattern) { + colorOptions.pattern._width = + 'defer'; + colorOptions.pattern._height = + 'defer'; + } + }); + }); + // Redraw without animation + this.redraw(false); + } +}); +// Add a garbage collector to delete old patterns with autogenerated hashes that +// are no longer being referenced. +addEvent(H.Chart, 'redraw', function () { + var usedIds = {}, renderer = this.renderer, + // Get the autocomputed patterns - these are the ones we might delete + patterns = (renderer.defIds || []).filter(function (pattern) { + return (pattern.indexOf && + pattern.indexOf('highcharts-pattern-') === 0); + }); + if (patterns.length) { + // Look through the DOM for usage of the patterns. This can be points, + // series, tooltips etc. + [].forEach.call(this.renderTo.querySelectorAll('[color^="url("], [fill^="url("], [stroke^="url("]'), function (node) { + var id = node.getAttribute('fill') || + node.getAttribute('color') || + node.getAttribute('stroke'); + if (id) { + var sanitizedId = id.replace(renderer.url, '').replace('url(#', '').replace(')', ''); + usedIds[sanitizedId] = true; + } + }); + // Loop through the patterns that exist and see if they are used + patterns.forEach(function (id) { + if (!usedIds[id]) { + // Remove id from used id list + erase(renderer.defIds, id); + // Remove pattern element + if (renderer.patternElements[id]) { + renderer.patternElements[id].destroy(); + delete renderer.patternElements[id]; + } + } + }); + } +}); diff --git a/librerias/gantt/code/es-modules/modules/price-indicator.src.js b/librerias/gantt/code/es-modules/modules/price-indicator.src.js new file mode 100644 index 0000000..598b7cb --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/price-indicator.src.js @@ -0,0 +1,124 @@ +/** + * (c) 2009-2020 Sebastian Bochann + * + * Price indicator for Highcharts + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, isArray = U.isArray, merge = U.merge; +/** + * The line marks the last price from visible range of points. + * + * @sample {highstock} stock/indicators/last-visible-price + * Last visible price + * + * @declare Highcharts.SeriesLastVisiblePriceOptionsObject + * @product highstock + * @requires modules/price-indicator + * @apioption plotOptions.series.lastVisiblePrice + */ +/** + * Enable or disable the indicator. + * + * @type {boolean} + * @product highstock + * @default true + * @apioption plotOptions.series.lastVisiblePrice.enabled + */ +/** + * @declare Highcharts.SeriesLastVisiblePriceLabelOptionsObject + * @apioption plotOptions.series.lastVisiblePrice.label + */ +/** + * Enable or disable the label. + * + * @type {boolean} + * @product highstock + * @default true + * @apioption plotOptions.series.lastVisiblePrice.label.enabled + * + */ +/** + * The line marks the last price from all points. + * + * @sample {highstock} stock/indicators/last-price + * Last price + * + * @declare Highcharts.SeriesLastPriceOptionsObject + * @product highstock + * @requires modules/price-indicator + * @apioption plotOptions.series.lastPrice + */ +/** + * Enable or disable the indicator. + * + * @type {boolean} + * @product highstock + * @default true + * @apioption plotOptions.series.lastPrice.enabled + */ +/** + * The color of the line of last price. + * + * @type {string} + * @product highstock + * @default red + * @apioption plotOptions.series.lastPrice.color + * + */ +/* eslint-disable no-invalid-this */ +addEvent(H.Series, 'afterRender', function () { + var serie = this, seriesOptions = serie.options, pointRange = seriesOptions.pointRange, lastVisiblePrice = seriesOptions.lastVisiblePrice, lastPrice = seriesOptions.lastPrice; + if ((lastVisiblePrice || lastPrice) && + seriesOptions.id !== 'highcharts-navigator-series') { + var xAxis = serie.xAxis, yAxis = serie.yAxis, origOptions = yAxis.crosshair, origGraphic = yAxis.cross, origLabel = yAxis.crossLabel, points = serie.points, yLength = serie.yData.length, pLength = points.length, x = serie.xData[serie.xData.length - 1], y = serie.yData[yLength - 1], lastPoint, yValue, crop; + if (lastPrice && lastPrice.enabled) { + yAxis.crosshair = yAxis.options.crosshair = seriesOptions.lastPrice; + yAxis.cross = serie.lastPrice; + yValue = isArray(y) ? y[3] : y; + yAxis.drawCrosshair(null, ({ + x: x, + y: yValue, + plotX: xAxis.toPixels(x, true), + plotY: yAxis.toPixels(yValue, true) + })); + // Save price + if (serie.yAxis.cross) { + serie.lastPrice = serie.yAxis.cross; + serie.lastPrice.y = yValue; + } + } + if (lastVisiblePrice && + lastVisiblePrice.enabled && + pLength > 0) { + crop = (points[pLength - 1].x === x) || pointRange === null ? 1 : 2; + yAxis.crosshair = yAxis.options.crosshair = merge({ + color: 'transparent' + }, seriesOptions.lastVisiblePrice); + yAxis.cross = serie.lastVisiblePrice; + lastPoint = points[pLength - crop]; + if (serie.crossLabel) { + serie.crossLabel.destroy(); + // Set to undefined to avoid collision with + // the yAxis crosshair #11480 + delete yAxis.crossLabel; + } + // Save price + yAxis.drawCrosshair(null, lastPoint); + if (yAxis.cross) { + serie.lastVisiblePrice = yAxis.cross; + serie.lastVisiblePrice.y = lastPoint.y; + } + serie.crossLabel = yAxis.crossLabel; + } + // Restore crosshair: + yAxis.crosshair = origOptions; + yAxis.cross = origGraphic; + yAxis.crossLabel = origLabel; + } +}); diff --git a/librerias/gantt/code/es-modules/modules/pyramid3d.src.js b/librerias/gantt/code/es-modules/modules/pyramid3d.src.js new file mode 100644 index 0000000..ca96932 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/pyramid3d.src.js @@ -0,0 +1,121 @@ +/* * + * + * Highcharts pyramid3d series module + * + * (c) 2010-2020 Highsoft AS + * Author: Kacper Madej + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import U from '../parts/Utilities.js'; +var seriesType = U.seriesType; +import '../parts/ColumnSeries.js'; +import '../parts/SvgRenderer.js'; +/** + * The pyramid3d series type. + * + * @constructor seriesTypes.pyramid3d + * @augments seriesTypes.funnel3d + * @requires highcharts-3d + * @requires modules/cylinder + * @requires modules/funnel3d + * @requires modules/pyramid3d + */ +seriesType('pyramid3d', 'funnel3d', +/** + * A pyramid3d is a 3d version of pyramid series type. Pyramid charts are + * a type of chart often used to visualize stages in a sales project, + * where the top are the initial stages with the most clients. + * + * @sample highcharts/demo/pyramid3d/ + * Pyramid3d + * + * @extends plotOptions.funnel3d + * @excluding neckHeight, neckWidth, dataSorting + * @product highcharts + * @since 7.1.0 + * @requires highcharts-3d + * @requires modules/cylinder + * @requires modules/funnel3d + * @requires modules/pyramid3d + * @optionparent plotOptions.pyramid3d + */ +{ + /** + * A reversed pyramid3d is funnel3d, but the latter supports neck + * related options: neckHeight and neckWidth + * + * @product highcharts + */ + reversed: true, + neckHeight: 0, + neckWidth: 0, + dataLabels: { + verticalAlign: 'top' + } +}); +/** + * A `pyramid3d` series. If the [type](#series.pyramid3d.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @since 7.1.0 + * @extends series,plotOptions.pyramid3d + * @excluding allAreas,boostThreshold,colorAxis,compare,compareBase,dataSorting + * @product highcharts + * @sample {highcharts} highcharts/demo/pyramid3d/ Pyramid3d + * @requires modules/pyramid3d + * @apioption series.pyramid3d + */ +/** + * An array of data points for the series. For the `pyramid3d` series + * type, points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values + * will be interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from `pointStart` + * and `pointInterval` given in the series options. If the axis has + * categories, these will be used. Example: + * + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of data + * points exceeds the series' + * [turboThreshold](#series.pyramid3d.turboThreshold), + * this option is not available. + * + * ```js + * data: [{ + * y: 2, + * name: "Point2", + * color: "#00FF00" + * }, { + * y: 4, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|*>} + * @extends series.funnel3d.data + * @product highcharts + * @apioption series.pyramid3d.data + */ +''; // adds doclets above to the transpiled file diff --git a/librerias/gantt/code/es-modules/modules/sankey.src.js b/librerias/gantt/code/es-modules/modules/sankey.src.js new file mode 100644 index 0000000..f29f2b4 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/sankey.src.js @@ -0,0 +1,1064 @@ +/* * + * + * Sankey diagram module + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +/** + * A node in a sankey diagram. + * + * @interface Highcharts.SankeyNodeObject + * @extends Highcharts.Point + * @product highcharts + */ /** +* The color of the auto generated node. +* +* @name Highcharts.SankeyNodeObject#color +* @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} +*/ /** +* The color index of the auto generated node, especially for use in styled +* mode. +* +* @name Highcharts.SankeyNodeObject#colorIndex +* @type {number} +*/ /** +* An optional column index of where to place the node. The default behaviour is +* to place it next to the preceding node. +* +* @see {@link https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/sankey-node-column/|Highcharts-Demo:} +* Specified node column +* +* @name Highcharts.SankeyNodeObject#column +* @type {number} +* @since 6.0.5 +*/ /** +* The id of the auto-generated node, refering to the `from` or `to` setting of +* the link. +* +* @name Highcharts.SankeyNodeObject#id +* @type {string} +*/ /** +* The name to display for the node in data labels and tooltips. Use this when +* the name is different from the `id`. Where the id must be unique for each +* node, this is not necessary for the name. +* +* @see {@link https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/css/sankey/|Highcharts-Demo:} +* Sankey diagram with node options +* +* @name Highcharts.SankeyNodeObject#name +* @type {string} +* @product highcharts +*/ /** +* The vertical offset of a node in terms of weight. Positive values shift the +* node downwards, negative shift it upwards. +* +* @see {@link https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/sankey-node-column/|Highcharts-Demo:} +* Specified node offset +* +* @name Highcharts.SankeyNodeObject#offset +* @type {number} +* @default 0 +* @since 6.0.5 +*/ +/** + * Formatter callback function. + * + * @callback Highcharts.SeriesSankeyDataLabelsFormatterCallbackFunction + * + * @param {Highcharts.SeriesSankeyDataLabelsFormatterContextObject|Highcharts.PointLabelObject} this + * Data label context to format + * + * @return {string|undefined} + * Formatted data label text + */ +/** + * Context for the node formatter function. + * + * @interface Highcharts.SeriesSankeyDataLabelsFormatterContextObject + * @extends Highcharts.PointLabelObject + */ /** +* The node object. The node name, if defined, is available through +* `this.point.name`. +* @name Highcharts.SeriesSankeyDataLabelsFormatterContextObject#point +* @type {Highcharts.SankeyNodeObject} +*/ +import Color from '../parts/Color.js'; +import Point from '../parts/Point.js'; +import U from '../parts/Utilities.js'; +var defined = U.defined, find = U.find, isObject = U.isObject, merge = U.merge, pick = U.pick, relativeLength = U.relativeLength, seriesType = U.seriesType, stableSort = U.stableSort; +import '../parts/Options.js'; +import '../mixins/nodes.js'; +import mixinTreeSeries from '../mixins/tree-series.js'; +var getLevelOptions = mixinTreeSeries.getLevelOptions; +// eslint-disable-next-line valid-jsdoc +/** + * @private + */ +var getDLOptions = function getDLOptions(params) { + var optionsPoint = (isObject(params.optionsPoint) ? + params.optionsPoint.dataLabels : + {}), optionsLevel = (isObject(params.level) ? + params.level.dataLabels : + {}), options = merge({ + style: {} + }, optionsLevel, optionsPoint); + return options; +}; +/** + * @private + * @class + * @name Highcharts.seriesTypes.sankey + * + * @augments Highcharts.Series + */ +seriesType('sankey', 'column', +/** + * A sankey diagram is a type of flow diagram, in which the width of the + * link between two nodes is shown proportionally to the flow quantity. + * + * @sample highcharts/demo/sankey-diagram/ + * Sankey diagram + * @sample highcharts/plotoptions/sankey-inverted/ + * Inverted sankey diagram + * @sample highcharts/plotoptions/sankey-outgoing + * Sankey diagram with outgoing links + * + * @extends plotOptions.column + * @since 6.0.0 + * @product highcharts + * @excluding animationLimit, boostThreshold, borderRadius, + * crisp, cropThreshold, colorAxis, colorKey, depth, dragDrop, + * edgeColor, edgeWidth, findNearestPointBy, grouping, + * groupPadding, groupZPadding, maxPointWidth, negativeColor, + * pointInterval, pointIntervalUnit, pointPadding, + * pointPlacement, pointRange, pointStart, pointWidth, + * shadow, softThreshold, stacking, threshold, zoneAxis, + * zones, minPointLength, dataSorting + * @requires modules/sankey + * @optionparent plotOptions.sankey + */ +{ + borderWidth: 0, + colorByPoint: true, + /** + * Higher numbers makes the links in a sankey diagram or dependency + * wheelrender more curved. A `curveFactor` of 0 makes the lines + * straight. + * + * @private + */ + curveFactor: 0.33, + /** + * Options for the data labels appearing on top of the nodes and links. + * For sankey charts, data labels are visible for the nodes by default, + * but hidden for links. This is controlled by modifying the + * `nodeFormat`, and the `format` that applies to links and is an empty + * string by default. + * + * @declare Highcharts.SeriesSankeyDataLabelsOptionsObject + * + * @private + */ + dataLabels: { + enabled: true, + backgroundColor: 'none', + crop: false, + /** + * The + * [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) + * specifying what to show for _nodes_ in the sankey diagram. By + * default the `nodeFormatter` returns `{point.name}`. + * + * @sample highcharts/plotoptions/sankey-link-datalabels/ + * Node and link data labels + * + * @type {string} + */ + nodeFormat: void 0, + // eslint-disable-next-line valid-jsdoc + /** + * Callback to format data labels for _nodes_ in the sankey diagram. + * The `nodeFormat` option takes precedence over the + * `nodeFormatter`. + * + * @type {Highcharts.SeriesSankeyDataLabelsFormatterCallbackFunction} + * @since 6.0.2 + */ + nodeFormatter: function () { + return this.point.name; + }, + format: void 0, + // eslint-disable-next-line valid-jsdoc + /** + * @type {Highcharts.SeriesSankeyDataLabelsFormatterCallbackFunction} + */ + formatter: function () { + return; + }, + inside: true + }, + /** + * @ignore-option + * + * @private + */ + inactiveOtherPoints: true, + /** + * Set options on specific levels. Takes precedence over series options, + * but not node and link options. + * + * @sample highcharts/demo/sunburst + * Sunburst chart + * + * @type {Array<*>} + * @since 7.1.0 + * @apioption plotOptions.sankey.levels + */ + /** + * Can set `borderColor` on all nodes which lay on the same level. + * + * @type {Highcharts.ColorString} + * @apioption plotOptions.sankey.levels.borderColor + */ + /** + * Can set `borderWidth` on all nodes which lay on the same level. + * + * @type {number} + * @apioption plotOptions.sankey.levels.borderWidth + */ + /** + * Can set `color` on all nodes which lay on the same level. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.sankey.levels.color + */ + /** + * Can set `colorByPoint` on all nodes which lay on the same level. + * + * @type {boolean} + * @default true + * @apioption plotOptions.sankey.levels.colorByPoint + */ + /** + * Can set `dataLabels` on all points which lay on the same level. + * + * @extends plotOptions.sankey.dataLabels + * @apioption plotOptions.sankey.levels.dataLabels + */ + /** + * Decides which level takes effect from the options set in the levels + * object. + * + * @type {number} + * @apioption plotOptions.sankey.levels.level + */ + /** + * Can set `linkOpacity` on all points which lay on the same level. + * + * @type {number} + * @default 0.5 + * @apioption plotOptions.sankey.levels.linkOpacity + */ + /** + * Can set `states` on all nodes and points which lay on the same level. + * + * @extends plotOptions.sankey.states + * @apioption plotOptions.sankey.levels.states + */ + /** + * Opacity for the links between nodes in the sankey diagram. + * + * @private + */ + linkOpacity: 0.5, + /** + * The minimal width for a line of a sankey. By default, + * 0 values are not shown. + * + * @sample highcharts/plotoptions/sankey-minlinkwidth + * Sankey diagram with minimal link height + * + * @type {number} + * @since 7.1.3 + * @default 0 + * @apioption plotOptions.sankey.minLinkWidth + * + * @private + */ + minLinkWidth: 0, + /** + * The pixel width of each node in a sankey diagram or dependency wheel, + * or the height in case the chart is inverted. + * + * @private + */ + nodeWidth: 20, + /** + * The padding between nodes in a sankey diagram or dependency wheel, in + * pixels. + * + * If the number of nodes is so great that it is possible to lay them + * out within the plot area with the given `nodePadding`, they will be + * rendered with a smaller padding as a strategy to avoid overflow. + * + * @private + */ + nodePadding: 10, + showInLegend: false, + states: { + hover: { + /** + * Opacity for the links between nodes in the sankey diagram in + * hover mode. + */ + linkOpacity: 1 + }, + /** + * The opposite state of a hover for a single point node/link. + * + * @declare Highcharts.SeriesStatesInactiveOptionsObject + */ + inactive: { + /** + * Opacity for the links between nodes in the sankey diagram in + * inactive mode. + */ + linkOpacity: 0.1, + /** + * Opacity of inactive markers. + * + * @type {number} + * @apioption plotOptions.series.states.inactive.opacity + */ + opacity: 0.1, + /** + * Animation when not hovering over the marker. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + * @apioption plotOptions.series.states.inactive.animation + */ + animation: { + /** @internal */ + duration: 50 + } + } + }, + tooltip: { + /** + * A callback for defining the format for _nodes_ in the chart's + * tooltip, as opposed to links. + * + * @type {Highcharts.FormatterCallbackFunction} + * @since 6.0.2 + * @apioption plotOptions.sankey.tooltip.nodeFormatter + */ + /** + * Whether the tooltip should follow the pointer or stay fixed on + * the item. + */ + followPointer: true, + headerFormat: '{series.name}
', + pointFormat: '{point.fromNode.name} \u2192 {point.toNode.name}: {point.weight}
', + /** + * The + * [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) + * specifying what to show for _nodes_ in tooltip of a diagram + * series, as opposed to links. + */ + nodeFormat: '{point.name}: {point.sum}
' + } +}, { + isCartesian: false, + invertable: true, + forceDL: true, + orderNodes: true, + pointArrayMap: ['from', 'to'], + // Create a single node that holds information on incoming and outgoing + // links. + createNode: H.NodesMixin.createNode, + searchPoint: H.noop, + setData: H.NodesMixin.setData, + destroy: H.NodesMixin.destroy, + /* eslint-disable valid-jsdoc */ + /** + * Overridable function to get node padding, overridden in dependency + * wheel series type. + * @private + */ + getNodePadding: function () { + var nodePadding = this.options.nodePadding || 0; + // If the number of columns is so great that they will overflow with + // the given nodePadding, we sacrifice the padding in order to + // render all nodes within the plot area (#11917). + if (this.nodeColumns) { + var maxLength = this.nodeColumns.reduce(function (acc, col) { return Math.max(acc, col.length); }, 0); + if (maxLength * nodePadding > this.chart.plotSizeY) { + nodePadding = this.chart.plotSizeY / maxLength; + } + } + return nodePadding; + }, + /** + * Create a node column. + * @private + */ + createNodeColumn: function () { + var series = this, chart = this.chart, column = []; + column.sum = function () { + return this.reduce(function (sum, node) { + return sum + node.getSum(); + }, 0); + }; + // Get the offset in pixels of a node inside the column. + column.offset = function (node, factor) { + var offset = 0, totalNodeOffset, nodePadding = series.nodePadding; + for (var i = 0; i < column.length; i++) { + var sum = column[i].getSum(); + var height = Math.max(sum * factor, series.options.minLinkWidth); + if (sum) { + totalNodeOffset = height + nodePadding; + } + else { + // If node sum equals 0 nodePadding is missed #12453 + totalNodeOffset = 0; + } + if (column[i] === node) { + return { + relativeTop: offset + relativeLength(node.options.offset || 0, totalNodeOffset) + }; + } + offset += totalNodeOffset; + } + }; + // Get the top position of the column in pixels. + column.top = function (factor) { + var nodePadding = series.nodePadding; + var height = this.reduce(function (height, node) { + if (height > 0) { + height += nodePadding; + } + var nodeHeight = Math.max(node.getSum() * factor, series.options.minLinkWidth); + height += nodeHeight; + return height; + }, 0); + return (chart.plotSizeY - height) / 2; + }; + return column; + }, + /** + * Create node columns by analyzing the nodes and the relations between + * incoming and outgoing links. + * @private + */ + createNodeColumns: function () { + var columns = []; + this.nodes.forEach(function (node) { + var fromColumn = -1, fromNode, i, point; + if (!defined(node.options.column)) { + // No links to this node, place it left + if (node.linksTo.length === 0) { + node.column = 0; + // There are incoming links, place it to the right of the + // highest order column that links to this one. + } + else { + for (i = 0; i < node.linksTo.length; i++) { + point = node.linksTo[0]; + if (point.fromNode.column > fromColumn) { + fromNode = point.fromNode; + fromColumn = fromNode.column; + } + } + node.column = fromColumn + 1; + // Hanging layout for organization chart + if (fromNode && + fromNode.options.layout === 'hanging') { + node.hangsFrom = fromNode; + i = -1; // Reuse existing variable i + find(fromNode.linksFrom, function (link, index) { + var found = link.toNode === node; + if (found) { + i = index; + } + return found; + }); + node.column += i; + } + } + } + if (!columns[node.column]) { + columns[node.column] = this.createNodeColumn(); + } + columns[node.column].push(node); + }, this); + // Fill in empty columns (#8865) + for (var i = 0; i < columns.length; i++) { + if (typeof columns[i] === 'undefined') { + columns[i] = this.createNodeColumn(); + } + } + return columns; + }, + /** + * Define hasData function for non-cartesian series. + * @private + * @return {boolean} + * Returns true if the series has points at all. + */ + hasData: function () { + return !!this.processedXData.length; // != 0 + }, + /** + * Return the presentational attributes. + * @private + */ + pointAttribs: function (point, state) { + var series = this, level = point.isNode ? point.level : point.fromNode.level, levelOptions = series.mapOptionsToLevel[level || 0] || {}, options = point.options, stateOptions = (levelOptions.states && levelOptions.states[state]) || {}, values = [ + 'colorByPoint', 'borderColor', 'borderWidth', 'linkOpacity' + ].reduce(function (obj, key) { + obj[key] = pick(stateOptions[key], options[key], levelOptions[key], series.options[key]); + return obj; + }, {}), color = pick(stateOptions.color, options.color, values.colorByPoint ? point.color : levelOptions.color); + // Node attributes + if (point.isNode) { + return { + fill: color, + stroke: values.borderColor, + 'stroke-width': values.borderWidth + }; + } + // Link attributes + return { + fill: Color.parse(color).setOpacity(values.linkOpacity).get() + }; + }, + /** + * Extend generatePoints by adding the nodes, which are Point objects + * but pushed to the this.nodes array. + * @private + */ + generatePoints: function () { + H.NodesMixin.generatePoints.apply(this, arguments); + /** + * Order the nodes, starting with the root node(s). (#9818) + * @private + */ + function order(node, level) { + // Prevents circular recursion: + if (typeof node.level === 'undefined') { + node.level = level; + node.linksFrom.forEach(function (link) { + if (link.toNode) { + order(link.toNode, level + 1); + } + }); + } + } + if (this.orderNodes) { + this.nodes + // Identify the root node(s) + .filter(function (node) { + return node.linksTo.length === 0; + }) + // Start by the root node(s) and recursively set the level + // on all following nodes. + .forEach(function (node) { + order(node, 0); + }); + stableSort(this.nodes, function (a, b) { + return a.level - b.level; + }); + } + }, + /** + * Run translation operations for one node. + * @private + */ + translateNode: function (node, column) { + var translationFactor = this.translationFactor, chart = this.chart, options = this.options, sum = node.getSum(), height = Math.max(Math.round(sum * translationFactor), this.options.minLinkWidth), crisp = Math.round(options.borderWidth) % 2 / 2, nodeOffset = column.offset(node, translationFactor), fromNodeTop = Math.floor(pick(nodeOffset.absoluteTop, (column.top(translationFactor) + + nodeOffset.relativeTop))) + crisp, left = Math.floor(this.colDistance * node.column + + options.borderWidth / 2) + crisp, nodeLeft = chart.inverted ? + chart.plotSizeX - left : + left, nodeWidth = Math.round(this.nodeWidth); + node.sum = sum; + // If node sum is 0, don't render the rect #12453 + if (sum) { + // Draw the node + node.shapeType = 'rect'; + node.nodeX = nodeLeft; + node.nodeY = fromNodeTop; + if (!chart.inverted) { + node.shapeArgs = { + x: nodeLeft, + y: fromNodeTop, + width: node.options.width || options.width || nodeWidth, + height: node.options.height || options.height || height + }; + } + else { + node.shapeArgs = { + x: nodeLeft - nodeWidth, + y: chart.plotSizeY - fromNodeTop - height, + width: node.options.height || options.height || nodeWidth, + height: node.options.width || options.width || height + }; + } + node.shapeArgs.display = node.hasShape() ? '' : 'none'; + // Calculate data label options for the point + node.dlOptions = getDLOptions({ + level: this.mapOptionsToLevel[node.level], + optionsPoint: node.options + }); + // Pass test in drawPoints + node.plotY = 1; + // Set the anchor position for tooltips + node.tooltipPos = chart.inverted ? [ + chart.plotSizeY - node.shapeArgs.y - node.shapeArgs.height / 2, + chart.plotSizeX - node.shapeArgs.x - node.shapeArgs.width / 2 + ] : [ + node.shapeArgs.x + node.shapeArgs.width / 2, + node.shapeArgs.y + node.shapeArgs.height / 2 + ]; + } + else { + node.dlOptions = { + enabled: false + }; + } + }, + /** + * Run translation operations for one link. + * @private + */ + translateLink: function (point) { + var getY = function (node, fromOrTo) { + var _a; + var linkTop = (node.offset(point, fromOrTo) * + translationFactor); + var y = Math.min(node.nodeY + linkTop, + // Prevent links from spilling below the node (#12014) + node.nodeY + ((_a = node.shapeArgs) === null || _a === void 0 ? void 0 : _a.height) - linkHeight); + return y; + }; + var fromNode = point.fromNode, toNode = point.toNode, chart = this.chart, translationFactor = this.translationFactor, linkHeight = Math.max(point.weight * translationFactor, this.options.minLinkWidth), options = this.options, curvy = ((chart.inverted ? -this.colDistance : this.colDistance) * + options.curveFactor), fromY = getY(fromNode, 'linksFrom'), toY = getY(toNode, 'linksTo'), nodeLeft = fromNode.nodeX, nodeW = this.nodeWidth, right = toNode.column * this.colDistance, outgoing = point.outgoing, straight = right > nodeLeft + nodeW; + if (chart.inverted) { + fromY = chart.plotSizeY - fromY; + toY = (chart.plotSizeY || 0) - toY; + right = chart.plotSizeX - right; + nodeW = -nodeW; + linkHeight = -linkHeight; + straight = nodeLeft > right; + } + point.shapeType = 'path'; + point.linkBase = [ + fromY, + fromY + linkHeight, + toY, + toY + linkHeight + ]; + // Links going from left to right + if (straight && typeof toY === 'number') { + point.shapeArgs = { + d: [ + ['M', nodeLeft + nodeW, fromY], + [ + 'C', + nodeLeft + nodeW + curvy, + fromY, + right - curvy, + toY, + right, + toY + ], + ['L', right + (outgoing ? nodeW : 0), toY + linkHeight / 2], + ['L', right, toY + linkHeight], + [ + 'C', + right - curvy, + toY + linkHeight, + nodeLeft + nodeW + curvy, + fromY + linkHeight, + nodeLeft + nodeW, fromY + linkHeight + ], + ['Z'] + ] + }; + // Experimental: Circular links pointing backwards. In + // v6.1.0 this breaks the rendering completely, so even + // this experimental rendering is an improvement. #8218. + // @todo + // - Make room for the link in the layout + // - Automatically determine if the link should go up or + // down. + } + else if (typeof toY === 'number') { + var bend = 20, vDist = chart.plotHeight - fromY - linkHeight, x1 = right - bend - linkHeight, x2 = right - bend, x3 = right, x4 = nodeLeft + nodeW, x5 = x4 + bend, x6 = x5 + linkHeight, fy1 = fromY, fy2 = fromY + linkHeight, fy3 = fy2 + bend, y4 = fy3 + vDist, y5 = y4 + bend, y6 = y5 + linkHeight, ty1 = toY, ty2 = ty1 + linkHeight, ty3 = ty2 + bend, cfy1 = fy2 - linkHeight * 0.7, cy2 = y5 + linkHeight * 0.7, cty1 = ty2 - linkHeight * 0.7, cx1 = x3 - linkHeight * 0.7, cx2 = x4 + linkHeight * 0.7; + point.shapeArgs = { + d: [ + ['M', x4, fy1], + ['C', cx2, fy1, x6, cfy1, x6, fy3], + ['L', x6, y4], + ['C', x6, cy2, cx2, y6, x4, y6], + ['L', x3, y6], + ['C', cx1, y6, x1, cy2, x1, y4], + ['L', x1, ty3], + ['C', x1, cty1, cx1, ty1, x3, ty1], + ['L', x3, ty2], + ['C', x2, ty2, x2, ty2, x2, ty3], + ['L', x2, y4], + ['C', x2, y5, x2, y5, x3, y5], + ['L', x4, y5], + ['C', x5, y5, x5, y5, x5, y4], + ['L', x5, fy3], + ['C', x5, fy2, x5, fy2, x4, fy2], + ['Z'] + ] + }; + } + // Place data labels in the middle + point.dlBox = { + x: nodeLeft + (right - nodeLeft + nodeW) / 2, + y: fromY + (toY - fromY) / 2, + height: linkHeight, + width: 0 + }; + // And set the tooltip anchor in the middle + point.tooltipPos = chart.inverted ? [ + chart.plotSizeY - point.dlBox.y - linkHeight / 2, + chart.plotSizeX - point.dlBox.x + ] : [ + point.dlBox.x, + point.dlBox.y + linkHeight / 2 + ]; + // Pass test in drawPoints + point.y = point.plotY = 1; + if (!point.color) { + point.color = fromNode.color; + } + }, + /** + * Run pre-translation by generating the nodeColumns. + * @private + */ + translate: function () { + var _this = this; + // Get the translation factor needed for each column to fill up the + // plot height + var getColumnTranslationFactor = function (column) { + var nodes = column.slice(); + var minLinkWidth = _this.options.minLinkWidth || 0; + var exceedsMinLinkWidth; + var factor = 0; + var i; + var remainingHeight = chart.plotSizeY - + options.borderWidth - (column.length - 1) * series.nodePadding; + // Because the minLinkWidth option doesn't obey the direct + // translation, we need to run translation iteratively, check + // node heights, remove those nodes affected by minLinkWidth, + // check again, etc. + while (column.length) { + factor = remainingHeight / column.sum(); + exceedsMinLinkWidth = false; + i = column.length; + while (i--) { + if (column[i].getSum() * factor < minLinkWidth) { + column.splice(i, 1); + remainingHeight -= minLinkWidth + series.nodePadding; + exceedsMinLinkWidth = true; + } + } + if (!exceedsMinLinkWidth) { + break; + } + } + // Re-insert original nodes + column.length = 0; + nodes.forEach(function (node) { return column.push(node); }); + return factor; + }; + if (!this.processedXData) { + this.processData(); + } + this.generatePoints(); + this.nodeColumns = this.createNodeColumns(); + this.nodeWidth = relativeLength(this.options.nodeWidth, this.chart.plotSizeX); + var series = this, chart = this.chart, options = this.options, nodeWidth = this.nodeWidth, nodeColumns = this.nodeColumns; + this.nodePadding = this.getNodePadding(); + // Find out how much space is needed. Base it on the translation + // factor of the most spaceous column. + this.translationFactor = nodeColumns.reduce(function (translationFactor, column) { return Math.min(translationFactor, getColumnTranslationFactor(column)); }, Infinity); + this.colDistance = + (chart.plotSizeX - nodeWidth - + options.borderWidth) / Math.max(1, nodeColumns.length - 1); + // Calculate level options used in sankey and organization + series.mapOptionsToLevel = getLevelOptions({ + // NOTE: if support for allowTraversingTree is added, then from + // should be the level of the root node. + from: 1, + levels: options.levels, + to: nodeColumns.length - 1, + defaults: { + borderColor: options.borderColor, + borderRadius: options.borderRadius, + borderWidth: options.borderWidth, + color: series.color, + colorByPoint: options.colorByPoint, + // NOTE: if support for allowTraversingTree is added, then + // levelIsConstant should be optional. + levelIsConstant: true, + linkColor: options.linkColor, + linkLineWidth: options.linkLineWidth, + linkOpacity: options.linkOpacity, + states: options.states + } + }); + // First translate all nodes so we can use them when drawing links + nodeColumns.forEach(function (column) { + column.forEach(function (node) { + series.translateNode(node, column); + }); + }, this); + // Then translate links + this.nodes.forEach(function (node) { + // Translate the links from this node + node.linksFrom.forEach(function (linkPoint) { + // If weight is 0 - don't render the link path #12453, + // render null points (for organization chart) + if ((linkPoint.weight || linkPoint.isNull) && linkPoint.to) { + series.translateLink(linkPoint); + linkPoint.allowShadow = false; + } + }); + }); + }, + /** + * Extend the render function to also render this.nodes together with + * the points. + * @private + */ + render: function () { + var points = this.points; + this.points = this.points.concat(this.nodes || []); + H.seriesTypes.column.prototype.render.call(this); + this.points = points; + }, + /* eslint-enable valid-jsdoc */ + animate: H.Series.prototype.animate +}, { + applyOptions: function (options, x) { + Point.prototype.applyOptions.call(this, options, x); + // Treat point.level as a synonym of point.column + if (defined(this.options.level)) { + this.options.column = this.column = this.options.level; + } + return this; + }, + setState: H.NodesMixin.setNodeState, + getClassName: function () { + return (this.isNode ? 'highcharts-node ' : 'highcharts-link ') + + Point.prototype.getClassName.call(this); + }, + isValid: function () { + return this.isNode || typeof this.weight === 'number'; + } +}); +/** + * A `sankey` series. If the [type](#series.sankey.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.sankey + * @excluding animationLimit, boostBlending, boostThreshold, borderColor, + * borderRadius, borderWidth, crisp, cropThreshold, dataParser, + * dataURL, depth, dragDrop, edgeColor, edgeWidth, + * findNearestPointBy, getExtremesFromAll, grouping, groupPadding, + * groupZPadding, label, maxPointWidth, negativeColor, pointInterval, + * pointIntervalUnit, pointPadding, pointPlacement, pointRange, + * pointStart, pointWidth, shadow, softThreshold, stacking, + * threshold, zoneAxis, zones, dataSorting + * @product highcharts + * @requires modules/sankey + * @apioption series.sankey + */ +/** + * A collection of options for the individual nodes. The nodes in a sankey + * diagram are auto-generated instances of `Highcharts.Point`, but options can + * be applied here and linked by the `id`. + * + * @sample highcharts/css/sankey/ + * Sankey diagram with node options + * + * @declare Highcharts.SeriesSankeyNodesOptionsObject + * @type {Array<*>} + * @product highcharts + * @apioption series.sankey.nodes + */ +/** + * The id of the auto-generated node, refering to the `from` or `to` setting of + * the link. + * + * @type {string} + * @product highcharts + * @apioption series.sankey.nodes.id + */ +/** + * The color of the auto generated node. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts + * @apioption series.sankey.nodes.color + */ +/** + * The color index of the auto generated node, especially for use in styled + * mode. + * + * @type {number} + * @product highcharts + * @apioption series.sankey.nodes.colorIndex + */ +/** + * An optional column index of where to place the node. The default behaviour is + * to place it next to the preceding node. Note that this option name is + * counter intuitive in inverted charts, like for example an organization chart + * rendered top down. In this case the "columns" are horizontal. + * + * @sample highcharts/plotoptions/sankey-node-column/ + * Specified node column + * + * @type {number} + * @since 6.0.5 + * @product highcharts + * @apioption series.sankey.nodes.column + */ +/** + * Individual data label for each node. The options are the same as + * the ones for [series.sankey.dataLabels](#series.sankey.dataLabels). + * + * @extends plotOptions.sankey.dataLabels + * @apioption series.sankey.nodes.dataLabels + */ +/** + * An optional level index of where to place the node. The default behaviour is + * to place it next to the preceding node. Alias of `nodes.column`, but in + * inverted sankeys and org charts, the levels are laid out as rows. + * + * @type {number} + * @since 7.1.0 + * @product highcharts + * @apioption series.sankey.nodes.level + */ +/** + * The name to display for the node in data labels and tooltips. Use this when + * the name is different from the `id`. Where the id must be unique for each + * node, this is not necessary for the name. + * + * @sample highcharts/css/sankey/ + * Sankey diagram with node options + * + * @type {string} + * @product highcharts + * @apioption series.sankey.nodes.name + */ +/** + * In a horizontal layout, the vertical offset of a node in terms of weight. + * Positive values shift the node downwards, negative shift it upwards. In a + * vertical layout, like organization chart, the offset is horizontal. + * + * If a percantage string is given, the node is offset by the percentage of the + * node size plus `nodePadding`. + * + * @sample highcharts/plotoptions/sankey-node-column/ + * Specified node offset + * + * @type {number|string} + * @default 0 + * @since 6.0.5 + * @product highcharts + * @apioption series.sankey.nodes.offset + */ +/** + * An array of data points for the series. For the `sankey` series type, + * points can be given in the following way: + * + * An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of data + * points exceeds the series' [turboThreshold](#series.area.turboThreshold), + * this option is not available. + * + * ```js + * data: [{ + * from: 'Category1', + * to: 'Category2', + * weight: 2 + * }, { + * from: 'Category1', + * to: 'Category3', + * weight: 5 + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @declare Highcharts.SeriesSankeyPointOptionsObject + * @type {Array<*>} + * @extends series.line.data + * @excluding dragDrop, drilldown, marker, x, y + * @product highcharts + * @apioption series.sankey.data + */ +/** + * The color for the individual _link_. By default, the link color is the same + * as the node it extends from. The `series.fillOpacity` option also applies to + * the points, so when setting a specific link color, consider setting the + * `fillOpacity` to 1. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts + * @apioption series.sankey.data.color + */ +/** + * @type {Highcharts.SeriesSankeyDataLabelsOptionsObject|Array} + * @product highcharts + * @apioption series.sankey.data.dataLabels + */ +/** + * The node that the link runs from. + * + * @type {string} + * @product highcharts + * @apioption series.sankey.data.from + */ +/** + * The node that the link runs to. + * + * @type {string} + * @product highcharts + * @apioption series.sankey.data.to + */ +/** + * Whether the link goes out of the system. + * + * @sample highcharts/plotoptions/sankey-outgoing + * Sankey chart with outgoing links + * + * @type {boolean} + * @default false + * @product highcharts + * @apioption series.sankey.data.outgoing + */ +/** + * The weight of the link. + * + * @type {number|null} + * @product highcharts + * @apioption series.sankey.data.weight + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/modules/sonification/Earcon.js b/librerias/gantt/code/es-modules/modules/sonification/Earcon.js new file mode 100644 index 0000000..25d1450 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/sonification/Earcon.js @@ -0,0 +1,167 @@ +/* * + * + * (c) 2009-2020 Øystein Moseng + * + * Earcons for the sonification module in Highcharts. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../../parts/Globals.js'; +import U from '../../parts/Utilities.js'; +var error = U.error, merge = U.merge, pick = U.pick, uniqueKey = U.uniqueKey; +/** + * Define an Instrument and the options for playing it. + * + * @requires module:modules/sonification + * + * @interface Highcharts.EarconInstrument + */ /** +* An instrument instance or the name of the instrument in the +* Highcharts.sonification.instruments map. +* @name Highcharts.EarconInstrument#instrument +* @type {string|Highcharts.Instrument} +*/ /** +* The options to pass to Instrument.play. +* @name Highcharts.EarconInstrument#playOptions +* @type {Highcharts.InstrumentPlayOptionsObject} +*/ +/** + * Options for an Earcon. + * + * @requires module:modules/sonification + * + * @interface Highcharts.EarconOptionsObject + */ /** +* The instruments and their options defining this earcon. +* @name Highcharts.EarconOptionsObject#instruments +* @type {Array} +*/ /** +* The unique ID of the Earcon. Generated if not supplied. +* @name Highcharts.EarconOptionsObject#id +* @type {string|undefined} +*/ /** +* Global panning of all instruments. Overrides all panning on individual +* instruments. Can be a number between -1 and 1. +* @name Highcharts.EarconOptionsObject#pan +* @type {number|undefined} +*/ /** +* Master volume for all instruments. Volume settings on individual instruments +* can still be used for relative volume between the instruments. This setting +* does not affect volumes set by functions in individual instruments. Can be a +* number between 0 and 1. Defaults to 1. +* @name Highcharts.EarconOptionsObject#volume +* @type {number|undefined} +*/ /** +* Callback function to call when earcon has finished playing. +* @name Highcharts.EarconOptionsObject#onEnd +* @type {Function|undefined} +*/ +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * The Earcon class. Earcon objects represent a certain sound consisting of + * one or more instruments playing a predefined sound. + * + * @sample highcharts/sonification/earcon/ + * Using earcons directly + * + * @requires module:modules/sonification + * + * @class + * @name Highcharts.Earcon + * + * @param {Highcharts.EarconOptionsObject} options + * Options for the Earcon instance. + */ +function Earcon(options) { + this.init(options || {}); +} +Earcon.prototype.init = function (options) { + this.options = options; + if (!this.options.id) { + this.options.id = this.id = uniqueKey(); + } + this.instrumentsPlaying = {}; +}; +/** + * Play the earcon, optionally overriding init options. + * + * @sample highcharts/sonification/earcon/ + * Using earcons directly + * + * @function Highcharts.Earcon#sonify + * + * @param {Highcharts.EarconOptionsObject} options + * Override existing options. + * + * @return {void} + */ +Earcon.prototype.sonify = function (options) { + var playOptions = merge(this.options, options); + // Find master volume/pan settings + var masterVolume = pick(playOptions.volume, 1), masterPan = playOptions.pan, earcon = this, playOnEnd = options && options.onEnd, masterOnEnd = earcon.options.onEnd; + // Go through the instruments and play them + playOptions.instruments.forEach(function (opts) { + var instrument = typeof opts.instrument === 'string' ? + H.sonification.instruments[opts.instrument] : opts.instrument, instrumentOpts = merge(opts.playOptions), instrOnEnd, instrumentCopy, copyId = ''; + if (instrument && instrument.play) { + if (opts.playOptions) { + // Handle master pan/volume + if (typeof opts.playOptions.volume !== 'function') { + instrumentOpts.volume = pick(masterVolume, 1) * + pick(opts.playOptions.volume, 1); + } + instrumentOpts.pan = pick(masterPan, instrumentOpts.pan); + // Handle onEnd + instrOnEnd = instrumentOpts.onEnd; + instrumentOpts.onEnd = function () { + delete earcon.instrumentsPlaying[copyId]; + if (instrOnEnd) { + instrOnEnd.apply(this, arguments); + } + if (!Object.keys(earcon.instrumentsPlaying).length) { + if (playOnEnd) { + playOnEnd.apply(this, arguments); + } + if (masterOnEnd) { + masterOnEnd.apply(this, arguments); + } + } + }; + // Play the instrument. Use a copy so we can play multiple at + // the same time. + instrumentCopy = instrument.copy(); + copyId = instrumentCopy.id; + earcon.instrumentsPlaying[copyId] = instrumentCopy; + instrumentCopy.play(instrumentOpts); + } + } + else { + error(30); + } + }); +}; +/** + * Cancel any current sonification of the Earcon. Calls onEnd functions. + * + * @function Highcharts.Earcon#cancelSonify + * + * @param {boolean} [fadeOut=false] + * Whether or not to fade out as we stop. If false, the earcon is + * cancelled synchronously. + * + * @return {void} + */ +Earcon.prototype.cancelSonify = function (fadeOut) { + var playing = this.instrumentsPlaying, instrIds = playing && Object.keys(playing); + if (instrIds && instrIds.length) { + instrIds.forEach(function (instr) { + playing[instr].stop(!fadeOut, null, 'cancelled'); + }); + this.instrumentsPlaying = {}; + } +}; +export default Earcon; diff --git a/librerias/gantt/code/es-modules/modules/sonification/Instrument.js b/librerias/gantt/code/es-modules/modules/sonification/Instrument.js new file mode 100644 index 0000000..8f9e27b --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/sonification/Instrument.js @@ -0,0 +1,515 @@ +/* * + * + * (c) 2009-2020 Øystein Moseng + * + * Instrument class for sonification module. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../../parts/Globals.js'; +import U from '../../parts/Utilities.js'; +var error = U.error, merge = U.merge, pick = U.pick, uniqueKey = U.uniqueKey; +/** + * A set of options for the Instrument class. + * + * @requires module:modules/sonification + * + * @interface Highcharts.InstrumentOptionsObject + */ /** +* The type of instrument. Currently only `oscillator` is supported. Defaults +* to `oscillator`. +* @name Highcharts.InstrumentOptionsObject#type +* @type {string|undefined} +*/ /** +* The unique ID of the instrument. Generated if not supplied. +* @name Highcharts.InstrumentOptionsObject#id +* @type {string|undefined} +*/ /** +* When using functions to determine frequency or other parameters during +* playback, this options specifies how often to call the callback functions. +* Number given in milliseconds. Defaults to 20. +* @name Highcharts.InstrumentOptionsObject#playCallbackInterval +* @type {number|undefined} +*/ /** +* A list of allowed frequencies for this instrument. If trying to play a +* frequency not on this list, the closest frequency will be used. Set to `null` +* to allow all frequencies to be used. Defaults to `null`. +* @name Highcharts.InstrumentOptionsObject#allowedFrequencies +* @type {Array|undefined} +*/ /** +* Options specific to oscillator instruments. +* @name Highcharts.InstrumentOptionsObject#oscillator +* @type {Highcharts.OscillatorOptionsObject|undefined} +*/ +/** + * Options for playing an instrument. + * + * @requires module:modules/sonification + * + * @interface Highcharts.InstrumentPlayOptionsObject + */ /** +* The frequency of the note to play. Can be a fixed number, or a function. The +* function receives one argument: the relative time of the note playing (0 +* being the start, and 1 being the end of the note). It should return the +* frequency number for each point in time. The poll interval of this function +* is specified by the Instrument.playCallbackInterval option. +* @name Highcharts.InstrumentPlayOptionsObject#frequency +* @type {number|Function} +*/ /** +* The duration of the note in milliseconds. +* @name Highcharts.InstrumentPlayOptionsObject#duration +* @type {number} +*/ /** +* The minimum frequency to allow. If the instrument has a set of allowed +* frequencies, the closest frequency is used by default. Use this option to +* stop too low frequencies from being used. +* @name Highcharts.InstrumentPlayOptionsObject#minFrequency +* @type {number|undefined} +*/ /** +* The maximum frequency to allow. If the instrument has a set of allowed +* frequencies, the closest frequency is used by default. Use this option to +* stop too high frequencies from being used. +* @name Highcharts.InstrumentPlayOptionsObject#maxFrequency +* @type {number|undefined} +*/ /** +* The volume of the instrument. Can be a fixed number between 0 and 1, or a +* function. The function receives one argument: the relative time of the note +* playing (0 being the start, and 1 being the end of the note). It should +* return the volume for each point in time. The poll interval of this function +* is specified by the Instrument.playCallbackInterval option. Defaults to 1. +* @name Highcharts.InstrumentPlayOptionsObject#volume +* @type {number|Function|undefined} +*/ /** +* The panning of the instrument. Can be a fixed number between -1 and 1, or a +* function. The function receives one argument: the relative time of the note +* playing (0 being the start, and 1 being the end of the note). It should +* return the panning value for each point in time. The poll interval of this +* function is specified by the Instrument.playCallbackInterval option. +* Defaults to 0. +* @name Highcharts.InstrumentPlayOptionsObject#pan +* @type {number|Function|undefined} +*/ /** +* Callback function to be called when the play is completed. +* @name Highcharts.InstrumentPlayOptionsObject#onEnd +* @type {Function|undefined} +*/ +/** + * @requires module:modules/sonification + * + * @interface Highcharts.OscillatorOptionsObject + */ /** +* The waveform shape to use for oscillator instruments. Defaults to `sine`. +* @name Highcharts.OscillatorOptionsObject#waveformShape +* @type {string|undefined} +*/ +// Default options for Instrument constructor +var defaultOptions = { + type: 'oscillator', + playCallbackInterval: 20, + oscillator: { + waveformShape: 'sine' + } +}; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * The Instrument class. Instrument objects represent an instrument capable of + * playing a certain pitch for a specified duration. + * + * @sample highcharts/sonification/instrument/ + * Using Instruments directly + * @sample highcharts/sonification/instrument-advanced/ + * Using callbacks for instrument parameters + * + * @requires module:modules/sonification + * + * @class + * @name Highcharts.Instrument + * + * @param {Highcharts.InstrumentOptionsObject} options + * Options for the instrument instance. + */ +function Instrument(options) { + this.init(options); +} +Instrument.prototype.init = function (options) { + if (!this.initAudioContext()) { + error(29); + return; + } + this.options = merge(defaultOptions, options); + this.id = this.options.id = options && options.id || uniqueKey(); + // Init the audio nodes + var ctx = H.audioContext; + this.gainNode = ctx.createGain(); + this.setGain(0); + this.panNode = ctx.createStereoPanner && ctx.createStereoPanner(); + if (this.panNode) { + this.setPan(0); + this.gainNode.connect(this.panNode); + this.panNode.connect(ctx.destination); + } + else { + this.gainNode.connect(ctx.destination); + } + // Oscillator initialization + if (this.options.type === 'oscillator') { + this.initOscillator(this.options.oscillator); + } + // Init timer list + this.playCallbackTimers = []; +}; +/** + * Return a copy of an instrument. Only one instrument instance can play at a + * time, so use this to get a new copy of the instrument that can play alongside + * it. The new instrument copy will receive a new ID unless one is supplied in + * options. + * + * @function Highcharts.Instrument#copy + * + * @param {Highcharts.InstrumentOptionsObject} [options] + * Options to merge in for the copy. + * + * @return {Highcharts.Instrument} + * A new Instrument instance with the same options. + */ +Instrument.prototype.copy = function (options) { + return new Instrument(merge(this.options, { id: null }, options)); +}; +/** + * Init the audio context, if we do not have one. + * @private + * @return {boolean} True if successful, false if not. + */ +Instrument.prototype.initAudioContext = function () { + var Context = H.win.AudioContext || H.win.webkitAudioContext, hasOldContext = !!H.audioContext; + if (Context) { + H.audioContext = H.audioContext || new Context(); + if (!hasOldContext && + H.audioContext && + H.audioContext.state === 'running') { + H.audioContext.suspend(); // Pause until we need it + } + return !!(H.audioContext && + H.audioContext.createOscillator && + H.audioContext.createGain); + } + return false; +}; +/** + * Init an oscillator instrument. + * @private + * @param {Highcharts.OscillatorOptionsObject} oscillatorOptions + * The oscillator options passed to Highcharts.Instrument#init. + * @return {void} + */ +Instrument.prototype.initOscillator = function (options) { + var ctx = H.audioContext; + this.oscillator = ctx.createOscillator(); + this.oscillator.type = options.waveformShape; + this.oscillator.connect(this.gainNode); + this.oscillatorStarted = false; +}; +/** + * Set pan position. + * @private + * @param {number} panValue + * The pan position to set for the instrument. + * @return {void} + */ +Instrument.prototype.setPan = function (panValue) { + if (this.panNode) { + this.panNode.pan.setValueAtTime(panValue, H.audioContext.currentTime); + } +}; +/** + * Set gain level. A maximum of 1.2 is allowed before we emit a warning. The + * actual volume is not set above this level regardless of input. + * @private + * @param {number} gainValue + * The gain level to set for the instrument. + * @param {number} [rampTime=0] + * Gradually change the gain level, time given in milliseconds. + * @return {void} + */ +Instrument.prototype.setGain = function (gainValue, rampTime) { + if (this.gainNode) { + if (gainValue > 1.2) { + console.warn(// eslint-disable-line + 'Highcharts sonification warning: ' + + 'Volume of instrument set too high.'); + gainValue = 1.2; + } + if (rampTime) { + this.gainNode.gain.setValueAtTime(this.gainNode.gain.value, H.audioContext.currentTime); + this.gainNode.gain.linearRampToValueAtTime(gainValue, H.audioContext.currentTime + rampTime / 1000); + } + else { + this.gainNode.gain.setValueAtTime(gainValue, H.audioContext.currentTime); + } + } +}; +/** + * Cancel ongoing gain ramps. + * @private + * @return {void} + */ +Instrument.prototype.cancelGainRamp = function () { + if (this.gainNode) { + this.gainNode.gain.cancelScheduledValues(0); + } +}; +/** + * Get the closest valid frequency for this instrument. + * @private + * @param {number} frequency - The target frequency. + * @param {number} [min] - Minimum frequency to return. + * @param {number} [max] - Maximum frequency to return. + * @return {number} The closest valid frequency to the input frequency. + */ +Instrument.prototype.getValidFrequency = function (frequency, min, max) { + var validFrequencies = this.options.allowedFrequencies, maximum = pick(max, Infinity), minimum = pick(min, -Infinity); + return !validFrequencies || !validFrequencies.length ? + // No valid frequencies for this instrument, return the target + frequency : + // Use the valid frequencies and return the closest match + validFrequencies.reduce(function (acc, cur) { + // Find the closest allowed value + return Math.abs(cur - frequency) < Math.abs(acc - frequency) && + cur < maximum && cur > minimum ? + cur : acc; + }, Infinity); +}; +/** + * Clear existing play callback timers. + * @private + * @return {void} + */ +Instrument.prototype.clearPlayCallbackTimers = function () { + this.playCallbackTimers.forEach(function (timer) { + clearInterval(timer); + }); + this.playCallbackTimers = []; +}; +/** + * Set the current frequency being played by the instrument. The closest valid + * frequency between the frequency limits is used. + * @param {number} frequency + * The frequency to set. + * @param {Highcharts.Dictionary} [frequencyLimits] + * Object with maxFrequency and minFrequency + * @return {void} + */ +Instrument.prototype.setFrequency = function (frequency, frequencyLimits) { + var limits = frequencyLimits || {}, validFrequency = this.getValidFrequency(frequency, limits.min, limits.max); + if (this.options.type === 'oscillator') { + this.oscillatorPlay(validFrequency); + } +}; +/** + * Play oscillator instrument. + * @private + * @param {number} frequency - The frequency to play. + */ +Instrument.prototype.oscillatorPlay = function (frequency) { + if (!this.oscillatorStarted) { + this.oscillator.start(); + this.oscillatorStarted = true; + } + this.oscillator.frequency.setValueAtTime(frequency, H.audioContext.currentTime); +}; +/** + * Prepare instrument before playing. Resumes the audio context and starts the + * oscillator. + * @private + */ +Instrument.prototype.preparePlay = function () { + this.setGain(0.001); + if (H.audioContext.state === 'suspended') { + H.audioContext.resume(); + } + if (this.oscillator && !this.oscillatorStarted) { + this.oscillator.start(); + this.oscillatorStarted = true; + } +}; +/** + * Play the instrument according to options. + * + * @sample highcharts/sonification/instrument/ + * Using Instruments directly + * @sample highcharts/sonification/instrument-advanced/ + * Using callbacks for instrument parameters + * + * @function Highcharts.Instrument#play + * + * @param {Highcharts.InstrumentPlayOptionsObject} options + * Options for the playback of the instrument. + * + * @return {void} + */ +Instrument.prototype.play = function (options) { + var instrument = this, duration = options.duration || 0, + // Set a value, or if it is a function, set it continously as a timer. + // Pass in the value/function to set, the setter function, and any + // additional data to pass through to the setter function. + setOrStartTimer = function (value, setter, setterData) { + var target = options.duration, currentDurationIx = 0, callbackInterval = instrument.options.playCallbackInterval; + if (typeof value === 'function') { + var timer = setInterval(function () { + currentDurationIx++; + var curTime = (currentDurationIx * callbackInterval / target); + if (curTime >= 1) { + instrument[setter](value(1), setterData); + clearInterval(timer); + } + else { + instrument[setter](value(curTime), setterData); + } + }, callbackInterval); + instrument.playCallbackTimers.push(timer); + } + else { + instrument[setter](value, setterData); + } + }; + if (!instrument.id) { + // No audio support - do nothing + return; + } + // If the AudioContext is suspended we have to resume it before playing + if (H.audioContext.state === 'suspended' || + this.oscillator && !this.oscillatorStarted) { + instrument.preparePlay(); + // Try again in 10ms + setTimeout(function () { + instrument.play(options); + }, 10); + return; + } + // Clear any existing play timers + if (instrument.playCallbackTimers.length) { + instrument.clearPlayCallbackTimers(); + } + // Clear any gain ramps + instrument.cancelGainRamp(); + // Clear stop oscillator timer + if (instrument.stopOscillatorTimeout) { + clearTimeout(instrument.stopOscillatorTimeout); + delete instrument.stopOscillatorTimeout; + } + // If a note is playing right now, clear the stop timeout, and call the + // callback. + if (instrument.stopTimeout) { + clearTimeout(instrument.stopTimeout); + delete instrument.stopTimeout; + if (instrument.stopCallback) { + // We have a callback for the play we are interrupting. We do not + // allow this callback to start a new play, because that leads to + // chaos. We pass in 'cancelled' to indicate that this note did not + // finish, but still stopped. + instrument._play = instrument.play; + instrument.play = function () { }; + instrument.stopCallback('cancelled'); + instrument.play = instrument._play; + } + } + // Stop the note without fadeOut if the duration is too short to hear the + // note otherwise. + var immediate = duration < H.sonification.fadeOutDuration + 20; + // Stop the instrument after the duration of the note + instrument.stopCallback = options.onEnd; + var onStop = function () { + delete instrument.stopTimeout; + instrument.stop(immediate); + }; + if (duration) { + instrument.stopTimeout = setTimeout(onStop, immediate ? duration : + duration - H.sonification.fadeOutDuration); + // Play the note + setOrStartTimer(options.frequency, 'setFrequency', { + minFrequency: options.minFrequency, + maxFrequency: options.maxFrequency + }); + // Set the volume and panning + setOrStartTimer(pick(options.volume, 1), 'setGain', 4); // Slight ramp + setOrStartTimer(pick(options.pan, 0), 'setPan'); + } + else { + // No note duration, so just stop immediately + onStop(); + } +}; +/** + * Mute an instrument that is playing. If the instrument is not currently + * playing, this function does nothing. + * + * @function Highcharts.Instrument#mute + */ +Instrument.prototype.mute = function () { + this.setGain(0.0001, H.sonification.fadeOutDuration * 0.8); +}; +/** + * Stop the instrument playing. + * + * @function Highcharts.Instrument#stop + * + * @param {boolean} immediately + * Whether to do the stop immediately or fade out. + * + * @param {Function} [onStopped] + * Callback function to be called when the stop is completed. + * + * @param {*} [callbackData] + * Data to send to the onEnd callback functions. + * + * @return {void} + */ +Instrument.prototype.stop = function (immediately, onStopped, callbackData) { + var instr = this, reset = function () { + // Remove timeout reference + if (instr.stopOscillatorTimeout) { + delete instr.stopOscillatorTimeout; + } + // The oscillator may have stopped in the meantime here, so allow + // this function to fail if so. + try { + instr.oscillator.stop(); + } + catch (e) { + // silent error + } + instr.oscillator.disconnect(instr.gainNode); + // We need a new oscillator in order to restart it + instr.initOscillator(instr.options.oscillator); + // Done stopping, call the callback from the stop + if (onStopped) { + onStopped(callbackData); + } + // Call the callback for the play we finished + if (instr.stopCallback) { + instr.stopCallback(callbackData); + } + }; + // Clear any existing timers + if (instr.playCallbackTimers.length) { + instr.clearPlayCallbackTimers(); + } + if (instr.stopTimeout) { + clearTimeout(instr.stopTimeout); + } + if (immediately) { + instr.setGain(0); + reset(); + } + else { + instr.mute(); + // Stop the oscillator after the mute fade-out has finished + instr.stopOscillatorTimeout = + setTimeout(reset, H.sonification.fadeOutDuration + 100); + } +}; +export default Instrument; diff --git a/librerias/gantt/code/es-modules/modules/sonification/Timeline.js b/librerias/gantt/code/es-modules/modules/sonification/Timeline.js new file mode 100644 index 0000000..054d06a --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/sonification/Timeline.js @@ -0,0 +1,606 @@ +/* * + * + * (c) 2009-2020 Øystein Moseng + * + * TimelineEvent class definition. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../../parts/Globals.js'; +import U from '../../parts/Utilities.js'; +var merge = U.merge, splat = U.splat, uniqueKey = U.uniqueKey; +/** + * A set of options for the TimelineEvent class. + * + * @requires module:modules/sonification + * + * @private + * @interface Highcharts.TimelineEventOptionsObject + */ /** +* The object we want to sonify when playing the TimelineEvent. Can be any +* object that implements the `sonify` and `cancelSonify` functions. If this is +* not supplied, the TimelineEvent is considered a silent event, and the onEnd +* event is immediately called. +* @name Highcharts.TimelineEventOptionsObject#eventObject +* @type {*} +*/ /** +* Options to pass on to the eventObject when playing it. +* @name Highcharts.TimelineEventOptionsObject#playOptions +* @type {object|undefined} +*/ /** +* The time at which we want this event to play (in milliseconds offset). This +* is not used for the TimelineEvent.play function, but rather intended as a +* property to decide when to call TimelineEvent.play. Defaults to 0. +* @name Highcharts.TimelineEventOptionsObject#time +* @type {number|undefined} +*/ /** +* Unique ID for the event. Generated automatically if not supplied. +* @name Highcharts.TimelineEventOptionsObject#id +* @type {string|undefined} +*/ /** +* Callback called when the play has finished. +* @name Highcharts.TimelineEventOptionsObject#onEnd +* @type {Function|undefined} +*/ +import utilities from './utilities.js'; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * The TimelineEvent class. Represents a sound event on a timeline. + * + * @requires module:modules/sonification + * + * @private + * @class + * @name Highcharts.TimelineEvent + * + * @param {Highcharts.TimelineEventOptionsObject} options + * Options for the TimelineEvent. + */ +function TimelineEvent(options) { + this.init(options || {}); +} +TimelineEvent.prototype.init = function (options) { + this.options = options; + this.time = options.time || 0; + this.id = this.options.id = options.id || uniqueKey(); +}; +/** + * Play the event. Does not take the TimelineEvent.time option into account, + * and plays the event immediately. + * + * @function Highcharts.TimelineEvent#play + * + * @param {Highcharts.TimelineEventOptionsObject} [options] + * Options to pass in to the eventObject when playing it. + * + * @return {void} + */ +TimelineEvent.prototype.play = function (options) { + var eventObject = this.options.eventObject, masterOnEnd = this.options.onEnd, playOnEnd = options && options.onEnd, playOptionsOnEnd = this.options.playOptions && + this.options.playOptions.onEnd, playOptions = merge(this.options.playOptions, options); + if (eventObject && eventObject.sonify) { + // If we have multiple onEnds defined, use all + playOptions.onEnd = masterOnEnd || playOnEnd || playOptionsOnEnd ? + function () { + var args = arguments; + [masterOnEnd, playOnEnd, playOptionsOnEnd].forEach(function (onEnd) { + if (onEnd) { + onEnd.apply(this, args); + } + }); + } : void 0; + eventObject.sonify(playOptions); + } + else { + if (playOnEnd) { + playOnEnd(); + } + if (masterOnEnd) { + masterOnEnd(); + } + } +}; +/** + * Cancel the sonification of this event. Does nothing if the event is not + * currently sonifying. + * + * @function Highcharts.TimelineEvent#cancel + * + * @param {boolean} [fadeOut=false] + * Whether or not to fade out as we stop. If false, the event is + * cancelled synchronously. + */ +TimelineEvent.prototype.cancel = function (fadeOut) { + this.options.eventObject.cancelSonify(fadeOut); +}; +/** + * A set of options for the TimelinePath class. + * + * @requires module:modules/ + * + * @private + * @interface Highcharts.TimelinePathOptionsObject + */ /** +* List of TimelineEvents to play on this track. +* @name Highcharts.TimelinePathOptionsObject#events +* @type {Array} +*/ /** +* If this option is supplied, this path ignores all events and just waits for +* the specified number of milliseconds before calling onEnd. +* @name Highcharts.TimelinePathOptionsObject#silentWait +* @type {number|undefined} +*/ /** +* Unique ID for this timeline path. Automatically generated if not supplied. +* @name Highcharts.TimelinePathOptionsObject#id +* @type {string|undefined} +*/ /** +* Callback called before the path starts playing. +* @name Highcharts.TimelinePathOptionsObject#onStart +* @type {Function|undefined} +*/ /** +* Callback function to call before an event plays. +* @name Highcharts.TimelinePathOptionsObject#onEventStart +* @type {Function|undefined} +*/ /** +* Callback function to call after an event has stopped playing. +* @name Highcharts.TimelinePathOptionsObject#onEventEnd +* @type {Function|undefined} +*/ /** +* Callback called when the whole path is finished. +* @name Highcharts.TimelinePathOptionsObject#onEnd +* @type {Function|undefined} +*/ +/** + * The TimelinePath class. Represents a track on a timeline with a list of + * sound events to play at certain times relative to each other. + * + * @requires module:modules/sonification + * + * @private + * @class + * @name Highcharts.TimelinePath + * + * @param {Highcharts.TimelinePathOptionsObject} options + * Options for the TimelinePath. + */ +function TimelinePath(options) { + this.init(options); +} +TimelinePath.prototype.init = function (options) { + this.options = options; + this.id = this.options.id = options.id || uniqueKey(); + this.cursor = 0; + this.eventsPlaying = {}; + // Handle silent wait, otherwise use events from options + this.events = options.silentWait ? + [ + new TimelineEvent({ time: 0 }), + new TimelineEvent({ time: options.silentWait }) + ] : + this.options.events; + // We need to sort our events by time + this.sortEvents(); + // Get map from event ID to index + this.updateEventIdMap(); + // Signal events to fire + this.signalHandler = new utilities.SignalHandler(['playOnEnd', 'masterOnEnd', 'onStart', 'onEventStart', 'onEventEnd']); + this.signalHandler.registerSignalCallbacks(merge(options, { masterOnEnd: options.onEnd })); +}; +/** + * Sort the internal event list by time. + * @private + */ +TimelinePath.prototype.sortEvents = function () { + this.events = this.events.sort(function (a, b) { + return a.time - b.time; + }); +}; +/** + * Update the internal eventId to index map. + * @private + */ +TimelinePath.prototype.updateEventIdMap = function () { + this.eventIdMap = this.events.reduce(function (acc, cur, i) { + acc[cur.id] = i; + return acc; + }, {}); +}; +/** + * Add events to the path. Should not be done while the path is playing. + * The new events are inserted according to their time property. + * @private + * @param {Array} newEvents - The new timeline events + * to add. + */ +TimelinePath.prototype.addTimelineEvents = function (newEvents) { + this.events = this.events.concat(newEvents); + this.sortEvents(); // Sort events by time + this.updateEventIdMap(); // Update the event ID to index map +}; +/** + * Get the current TimelineEvent under the cursor. + * @private + * @return {Highcharts.TimelineEvent} The current timeline event. + */ +TimelinePath.prototype.getCursor = function () { + return this.events[this.cursor]; +}; +/** + * Set the current TimelineEvent under the cursor. + * @private + * @param {string} eventId + * The ID of the timeline event to set as current. + * @return {boolean} + * True if there is an event with this ID in the path. False otherwise. + */ +TimelinePath.prototype.setCursor = function (eventId) { + var ix = this.eventIdMap[eventId]; + if (typeof ix !== 'undefined') { + this.cursor = ix; + return true; + } + return false; +}; +/** + * Play the timeline from the current cursor. + * @private + * @param {Function} onEnd + * Callback to call when play finished. Does not override other onEnd callbacks. + * @return {void} + */ +TimelinePath.prototype.play = function (onEnd) { + this.pause(); + this.signalHandler.emitSignal('onStart'); + this.signalHandler.clearSignalCallbacks(['playOnEnd']); + this.signalHandler.registerSignalCallbacks({ playOnEnd: onEnd }); + this.playEvents(1); +}; +/** + * Play the timeline backwards from the current cursor. + * @private + * @param {Function} onEnd + * Callback to call when play finished. Does not override other onEnd callbacks. + * @return {void} + */ +TimelinePath.prototype.rewind = function (onEnd) { + this.pause(); + this.signalHandler.emitSignal('onStart'); + this.signalHandler.clearSignalCallbacks(['playOnEnd']); + this.signalHandler.registerSignalCallbacks({ playOnEnd: onEnd }); + this.playEvents(-1); +}; +/** + * Reset the cursor to the beginning. + * @private + */ +TimelinePath.prototype.resetCursor = function () { + this.cursor = 0; +}; +/** + * Reset the cursor to the end. + * @private + */ +TimelinePath.prototype.resetCursorEnd = function () { + this.cursor = this.events.length - 1; +}; +/** + * Cancel current playing. Leaves the cursor intact. + * @private + * @param {boolean} [fadeOut=false] - Whether or not to fade out as we stop. If + * false, the path is cancelled synchronously. + */ +TimelinePath.prototype.pause = function (fadeOut) { + var timelinePath = this; + // Cancel next scheduled play + clearTimeout(timelinePath.nextScheduledPlay); + // Cancel currently playing events + Object.keys(timelinePath.eventsPlaying).forEach(function (id) { + if (timelinePath.eventsPlaying[id]) { + timelinePath.eventsPlaying[id].cancel(fadeOut); + } + }); + timelinePath.eventsPlaying = {}; +}; +/** + * Play the events, starting from current cursor, and going in specified + * direction. + * @private + * @param {number} direction + * The direction to play, 1 for forwards and -1 for backwards. + * @return {void} + */ +TimelinePath.prototype.playEvents = function (direction) { + var timelinePath = this, curEvent = timelinePath.events[this.cursor], nextEvent = timelinePath.events[this.cursor + direction], timeDiff, onEnd = function (signalData) { + timelinePath.signalHandler.emitSignal('masterOnEnd', signalData); + timelinePath.signalHandler.emitSignal('playOnEnd', signalData); + }; + // Store reference to path on event + curEvent.timelinePath = timelinePath; + // Emit event, cancel if returns false + if (timelinePath.signalHandler.emitSignal('onEventStart', curEvent) === false) { + onEnd({ + event: curEvent, + cancelled: true + }); + return; + } + // Play the current event + timelinePath.eventsPlaying[curEvent.id] = curEvent; + curEvent.play({ + onEnd: function (cancelled) { + var signalData = { + event: curEvent, + cancelled: !!cancelled + }; + // Keep track of currently playing events for cancelling + delete timelinePath.eventsPlaying[curEvent.id]; + // Handle onEventEnd + timelinePath.signalHandler.emitSignal('onEventEnd', signalData); + // Reached end of path? + if (!nextEvent) { + onEnd(signalData); + } + } + }); + // Schedule next + if (nextEvent) { + timeDiff = Math.abs(nextEvent.time - curEvent.time); + if (timeDiff < 1) { + // Play immediately + timelinePath.cursor += direction; + timelinePath.playEvents(direction); + } + else { + // Schedule after the difference in ms + this.nextScheduledPlay = setTimeout(function () { + timelinePath.cursor += direction; + timelinePath.playEvents(direction); + }, timeDiff); + } + } +}; +/* ************************************************************************** * + * TIMELINE * + * ************************************************************************** */ +/** + * A set of options for the Timeline class. + * + * @requires module:modules/sonification + * + * @private + * @interface Highcharts.TimelineOptionsObject + */ /** +* List of TimelinePaths to play. Multiple paths can be grouped together and +* played simultaneously by supplying an array of paths in place of a single +* path. +* @name Highcharts.TimelineOptionsObject#paths +* @type {Array<(Highcharts.TimelinePath|Array)>} +*/ /** +* Callback function to call before a path plays. +* @name Highcharts.TimelineOptionsObject#onPathStart +* @type {Function|undefined} +*/ /** +* Callback function to call after a path has stopped playing. +* @name Highcharts.TimelineOptionsObject#onPathEnd +* @type {Function|undefined} +*/ /** +* Callback called when the whole path is finished. +* @name Highcharts.TimelineOptionsObject#onEnd +* @type {Function|undefined} +*/ +/** + * The Timeline class. Represents a sonification timeline with a list of + * timeline paths with events to play at certain times relative to each other. + * + * @requires module:modules/sonification + * + * @private + * @class + * @name Highcharts.Timeline + * + * @param {Highcharts.TimelineOptionsObject} options + * Options for the Timeline. + */ +function Timeline(options) { + this.init(options || {}); +} +Timeline.prototype.init = function (options) { + this.options = options; + this.cursor = 0; + this.paths = options.paths; + this.pathsPlaying = {}; + this.signalHandler = new utilities.SignalHandler(['playOnEnd', 'masterOnEnd', 'onPathStart', 'onPathEnd']); + this.signalHandler.registerSignalCallbacks(merge(options, { masterOnEnd: options.onEnd })); +}; +/** + * Play the timeline forwards from cursor. + * @private + * @param {Function} [onEnd] + * Callback to call when play finished. Does not override other onEnd callbacks. + * @return {void} + */ +Timeline.prototype.play = function (onEnd) { + this.pause(); + this.signalHandler.clearSignalCallbacks(['playOnEnd']); + this.signalHandler.registerSignalCallbacks({ playOnEnd: onEnd }); + this.playPaths(1); +}; +/** + * Play the timeline backwards from cursor. + * @private + * @param {Function} onEnd + * Callback to call when play finished. Does not override other onEnd callbacks. + * @return {void} + */ +Timeline.prototype.rewind = function (onEnd) { + this.pause(); + this.signalHandler.clearSignalCallbacks(['playOnEnd']); + this.signalHandler.registerSignalCallbacks({ playOnEnd: onEnd }); + this.playPaths(-1); +}; +/** + * Play the timeline in the specified direction. + * @private + * @param {number} direction + * Direction to play in. 1 for forwards, -1 for backwards. + * @return {void} + */ +Timeline.prototype.playPaths = function (direction) { + var curPaths = splat(this.paths[this.cursor]), nextPaths = this.paths[this.cursor + direction], timeline = this, signalHandler = this.signalHandler, pathsEnded = 0, + // Play a path + playPath = function (path) { + // Emit signal and set playing state + signalHandler.emitSignal('onPathStart', path); + timeline.pathsPlaying[path.id] = path; + // Do the play + path[direction > 0 ? 'play' : 'rewind'](function (callbackData) { + // Play ended callback + // Data to pass to signal callbacks + var cancelled = callbackData && callbackData.cancelled, signalData = { + path: path, + cancelled: cancelled + }; + // Clear state and send signal + delete timeline.pathsPlaying[path.id]; + signalHandler.emitSignal('onPathEnd', signalData); + // Handle next paths + pathsEnded++; + if (pathsEnded >= curPaths.length) { + // We finished all of the current paths for cursor. + if (nextPaths && !cancelled) { + // We have more paths, move cursor along + timeline.cursor += direction; + // Reset upcoming path cursors before playing + splat(nextPaths).forEach(function (nextPath) { + nextPath[direction > 0 ? 'resetCursor' : 'resetCursorEnd'](); + }); + // Play next + timeline.playPaths(direction); + } + else { + // If it is the last path in this direction, call onEnd + signalHandler.emitSignal('playOnEnd', signalData); + signalHandler.emitSignal('masterOnEnd', signalData); + } + } + }); + }; + // Go through the paths under cursor and play them + curPaths.forEach(function (path) { + if (path) { + // Store reference to timeline + path.timeline = timeline; + // Leave a timeout to let notes fade out before next play + setTimeout(function () { + playPath(path); + }, H.sonification.fadeOutDuration); + } + }); +}; +/** + * Stop the playing of the timeline. Cancels all current sounds, but does not + * affect the cursor. + * @private + * @param {boolean} [fadeOut=false] + * Whether or not to fade out as we stop. If false, the timeline is cancelled + * synchronously. + * @return {void} + */ +Timeline.prototype.pause = function (fadeOut) { + var timeline = this; + // Cancel currently playing events + Object.keys(timeline.pathsPlaying).forEach(function (id) { + if (timeline.pathsPlaying[id]) { + timeline.pathsPlaying[id].pause(fadeOut); + } + }); + timeline.pathsPlaying = {}; +}; +/** + * Reset the cursor to the beginning of the timeline. + * @private + * @return {void} + */ +Timeline.prototype.resetCursor = function () { + this.paths.forEach(function (paths) { + splat(paths).forEach(function (path) { + path.resetCursor(); + }); + }); + this.cursor = 0; +}; +/** + * Reset the cursor to the end of the timeline. + * @private + * @return {void} + */ +Timeline.prototype.resetCursorEnd = function () { + this.paths.forEach(function (paths) { + splat(paths).forEach(function (path) { + path.resetCursorEnd(); + }); + }); + this.cursor = this.paths.length - 1; +}; +/** + * Set the current TimelineEvent under the cursor. If multiple paths are being + * played at the same time, this function only affects a single path (the one + * that contains the eventId that is passed in). + * @private + * @param {string} eventId + * The ID of the timeline event to set as current. + * @return {boolean} + * True if the cursor was set, false if no TimelineEvent was found for this ID. + */ +Timeline.prototype.setCursor = function (eventId) { + return this.paths.some(function (paths) { + return splat(paths).some(function (path) { + return path.setCursor(eventId); + }); + }); +}; +/** + * Get the current TimelineEvents under the cursors. This function will return + * the event under the cursor for each currently playing path, as an object + * where the path ID is mapped to the TimelineEvent under that path's cursor. + * @private + * @return {Highcharts.Dictionary} + * The TimelineEvents under each path's cursors. + */ +Timeline.prototype.getCursor = function () { + return this.getCurrentPlayingPaths().reduce(function (acc, cur) { + acc[cur.id] = cur.getCursor(); + return acc; + }, {}); +}; +/** + * Check if timeline is reset or at start. + * @private + * @return {boolean} + * True if timeline is at the beginning. + */ +Timeline.prototype.atStart = function () { + return !this.getCurrentPlayingPaths().some(function (path) { + return path.cursor; + }); +}; +/** + * Get the current TimelinePaths being played. + * @private + * @return {Array} + * The TimelinePaths currently being played. + */ +Timeline.prototype.getCurrentPlayingPaths = function () { + return splat(this.paths[this.cursor]); +}; +// Export the classes +var timelineClasses = { + TimelineEvent: TimelineEvent, + TimelinePath: TimelinePath, + Timeline: Timeline +}; +export default timelineClasses; diff --git a/librerias/gantt/code/es-modules/modules/sonification/chartSonify.js b/librerias/gantt/code/es-modules/modules/sonification/chartSonify.js new file mode 100644 index 0000000..634ca2a --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/sonification/chartSonify.js @@ -0,0 +1,927 @@ +/* * + * + * (c) 2009-2020 Øystein Moseng + * + * Sonification functions for chart/series. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../../parts/Globals.js'; +/** + * An Earcon configuration, specifying an Earcon and when to play it. + * + * @requires module:modules/sonification + * + * @interface Highcharts.EarconConfiguration + */ /** +* An Earcon instance. +* @name Highcharts.EarconConfiguration#earcon +* @type {Highcharts.Earcon} +*/ /** +* The ID of the point to play the Earcon on. +* @name Highcharts.EarconConfiguration#onPoint +* @type {string|undefined} +*/ /** +* A function to determine whether or not to play this earcon on a point. The +* function is called for every point, receiving that point as parameter. It +* should return either a boolean indicating whether or not to play the earcon, +* or a new Earcon instance - in which case the new Earcon will be played. +* @name Highcharts.EarconConfiguration#condition +* @type {Function|undefined} +*/ +/** + * Options for sonifying a series. + * + * @requires module:modules/sonification + * + * @interface Highcharts.SonifySeriesOptionsObject + */ /** +* The duration for playing the points. Note that points might continue to play +* after the duration has passed, but no new points will start playing. +* @name Highcharts.SonifySeriesOptionsObject#duration +* @type {number} +*/ /** +* The axis to use for when to play the points. Can be a string with a data +* property (e.g. `x`), or a function. If it is a function, this function +* receives the point as argument, and should return a numeric value. The points +* with the lowest numeric values are then played first, and the time between +* points will be proportional to the distance between the numeric values. +* @name Highcharts.SonifySeriesOptionsObject#pointPlayTime +* @type {string|Function} +*/ /** +* The instrument definitions for the points in this series. +* @name Highcharts.SonifySeriesOptionsObject#instruments +* @type {Array} +*/ /** +* Earcons to add to the series. +* @name Highcharts.SonifySeriesOptionsObject#earcons +* @type {Array|undefined} +*/ /** +* Optionally provide the minimum/maximum data values for the points. If this is +* not supplied, it is calculated from all points in the chart on demand. This +* option is supplied in the following format, as a map of point data properties +* to objects with min/max values: +* ```js +* dataExtremes: { +* y: { +* min: 0, +* max: 100 +* }, +* z: { +* min: -10, +* max: 10 +* } +* // Properties used and not provided are calculated on demand +* } +* ``` +* @name Highcharts.SonifySeriesOptionsObject#dataExtremes +* @type {Highcharts.Dictionary|undefined} +*/ /** +* Callback before a point is played. +* @name Highcharts.SonifySeriesOptionsObject#onPointStart +* @type {Function|undefined} +*/ /** +* Callback after a point has finished playing. +* @name Highcharts.SonifySeriesOptionsObject#onPointEnd +* @type {Function|undefined} +*/ /** +* Callback after the series has played. +* @name Highcharts.SonifySeriesOptionsObject#onEnd +* @type {Function|undefined} +*/ +''; // detach doclets above +import Point from '../../parts/Point.js'; +import U from '../../parts/Utilities.js'; +var find = U.find, isArray = U.isArray, merge = U.merge, pick = U.pick, splat = U.splat; +import utilities from './utilities.js'; +/** + * Get the relative time value of a point. + * @private + * @param {Highcharts.Point} point + * The point. + * @param {Function|string} timeProp + * The time axis data prop or the time function. + * @return {number} + * The time value. + */ +function getPointTimeValue(point, timeProp) { + return typeof timeProp === 'function' ? + timeProp(point) : + pick(point[timeProp], point.options[timeProp]); +} +/** + * Get the time extremes of this series. This is handled outside of the + * dataExtremes, as we always want to just sonify the visible points, and we + * always want the extremes to be the extremes of the visible points. + * @private + * @param {Highcharts.Series} series + * The series to compute on. + * @param {Function|string} timeProp + * The time axis data prop or the time function. + * @return {Highcharts.RangeObject} + * Object with min/max extremes for the time values. + */ +function getTimeExtremes(series, timeProp) { + // Compute the extremes from the visible points. + return series.points.reduce(function (acc, point) { + var value = getPointTimeValue(point, timeProp); + acc.min = Math.min(acc.min, value); + acc.max = Math.max(acc.max, value); + return acc; + }, { + min: Infinity, + max: -Infinity + }); +} +/** + * Calculate value extremes for used instrument data properties. + * @private + * @param {Highcharts.Chart} chart + * The chart to calculate extremes from. + * @param {Array} instruments + * The instrument definitions used. + * @param {Highcharts.Dictionary} [dataExtremes] + * Predefined extremes for each data prop. + * @return {Highcharts.Dictionary} + * New extremes with data properties mapped to min/max objects. + */ +function getExtremesForInstrumentProps(chart, instruments, dataExtremes) { + return (instruments || []).reduce(function (newExtremes, instrumentDefinition) { + Object.keys(instrumentDefinition.instrumentMapping || {}).forEach(function (instrumentParameter) { + var value = instrumentDefinition.instrumentMapping[instrumentParameter]; + if (typeof value === 'string' && !newExtremes[value]) { + // This instrument parameter is mapped to a data prop. + // If we don't have predefined data extremes, find them. + newExtremes[value] = utilities.calculateDataExtremes(chart, value); + } + }); + return newExtremes; + }, merge(dataExtremes)); +} +/** + * Get earcons for the point if there are any. + * @private + * @param {Highcharts.Point} point + * The point to find earcons for. + * @param {Array} earconDefinitions + * Earcons to check. + * @return {Array} + * Array of earcons to be played with this point. + */ +function getPointEarcons(point, earconDefinitions) { + return earconDefinitions.reduce(function (earcons, earconDefinition) { + var cond, earcon = earconDefinition.earcon; + if (earconDefinition.condition) { + // We have a condition. This overrides onPoint + cond = earconDefinition.condition(point); + if (cond instanceof H.sonification.Earcon) { + // Condition returned an earcon + earcons.push(cond); + } + else if (cond) { + // Condition returned true + earcons.push(earcon); + } + } + else if (earconDefinition.onPoint && + point.id === earconDefinition.onPoint) { + // We have earcon onPoint + earcons.push(earcon); + } + return earcons; + }, []); +} +/** + * Utility function to get a new list of instrument options where all the + * instrument references are copies. + * @private + * @param {Array} instruments + * The instrument options. + * @return {Array} + * Array of copied instrument options. + */ +function makeInstrumentCopies(instruments) { + return instruments.map(function (instrumentDef) { + var instrument = instrumentDef.instrument, copy = (typeof instrument === 'string' ? + H.sonification.instruments[instrument] : + instrument).copy(); + return merge(instrumentDef, { instrument: copy }); + }); +} +/** + * Create a TimelinePath from a series. Takes the same options as seriesSonify. + * To intuitively allow multiple series to play simultaneously we make copies of + * the instruments for each series. + * @private + * @param {Highcharts.Series} series + * The series to build from. + * @param {Highcharts.SonifySeriesOptionsObject} options + * The options for building the TimelinePath. + * @return {Highcharts.TimelinePath} + * A timeline path with events. + */ +function buildTimelinePathFromSeries(series, options) { + // options.timeExtremes is internal and used so that the calculations from + // chart.sonify can be reused. + var timeExtremes = options.timeExtremes || getTimeExtremes(series, options.pointPlayTime), + // Get time offset for a point, relative to duration + pointToTime = function (point) { + return utilities.virtualAxisTranslate(getPointTimeValue(point, options.pointPlayTime), timeExtremes, { min: 0, max: options.duration }); + }, + // Compute any data extremes that aren't defined yet + dataExtremes = getExtremesForInstrumentProps(series.chart, options.instruments, options.dataExtremes), + // Make copies of the instruments used for this series, to allow + // multiple series with the same instrument to play together + instruments = makeInstrumentCopies(options.instruments), + // Go through the points, convert to events, optionally add Earcons + timelineEvents = series.points.reduce(function (events, point) { + var earcons = getPointEarcons(point, options.earcons || []), time = pointToTime(point); + return events.concat( + // Event object for point + new H.sonification.TimelineEvent({ + eventObject: point, + time: time, + id: point.id, + playOptions: { + instruments: instruments, + dataExtremes: dataExtremes + } + }), + // Earcons + earcons.map(function (earcon) { + return new H.sonification.TimelineEvent({ + eventObject: earcon, + time: time + }); + })); + }, []); + // Build the timeline path + return new H.sonification.TimelinePath({ + events: timelineEvents, + onStart: function () { + if (options.onStart) { + options.onStart(series); + } + }, + onEventStart: function (event) { + var eventObject = event.options && event.options.eventObject; + if (eventObject instanceof Point) { + // Check for hidden series + if (!eventObject.series.visible && + !eventObject.series.chart.series.some(function (series) { + return series.visible; + })) { + // We have no visible series, stop the path. + event.timelinePath.timeline.pause(); + event.timelinePath.timeline.resetCursor(); + return false; + } + // Emit onPointStart + if (options.onPointStart) { + options.onPointStart(event, eventObject); + } + } + }, + onEventEnd: function (eventData) { + var eventObject = eventData.event && eventData.event.options && + eventData.event.options.eventObject; + if (eventObject instanceof Point && options.onPointEnd) { + options.onPointEnd(eventData.event, eventObject); + } + }, + onEnd: function () { + if (options.onEnd) { + options.onEnd(series); + } + } + }); +} +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * Sonify a series. + * + * @sample highcharts/sonification/series-basic/ + * Click on series to sonify + * @sample highcharts/sonification/series-earcon/ + * Series with earcon + * @sample highcharts/sonification/point-play-time/ + * Play y-axis by time + * @sample highcharts/sonification/earcon-on-point/ + * Earcon set on point + * + * @requires module:modules/sonification + * + * @function Highcharts.Series#sonify + * + * @param {Highcharts.SonifySeriesOptionsObject} options + * The options for sonifying this series. + * + * @return {void} + */ +function seriesSonify(options) { + var timelinePath = buildTimelinePathFromSeries(this, options), chartSonification = this.chart.sonification; + // Only one timeline can play at a time. If we want multiple series playing + // at the same time, use chart.sonify. + if (chartSonification.timeline) { + chartSonification.timeline.pause(); + } + // Store reference to duration + chartSonification.duration = options.duration; + // Create new timeline for this series, and play it. + chartSonification.timeline = new H.sonification.Timeline({ + paths: [timelinePath] + }); + chartSonification.timeline.play(); +} +/** + * Utility function to assemble options for creating a TimelinePath from a + * series when sonifying an entire chart. + * @private + * @param {Highcharts.Series} series + * The series to return options for. + * @param {Highcharts.RangeObject} dataExtremes + * Pre-calculated data extremes for the chart. + * @param {Highcharts.SonificationOptions} chartSonifyOptions + * Options passed in to chart.sonify. + * @return {Partial} + * Options for buildTimelinePathFromSeries. + */ +function buildSeriesOptions(series, dataExtremes, chartSonifyOptions) { + var seriesOptions = chartSonifyOptions.seriesOptions || {}; + return merge({ + // Calculated dataExtremes for chart + dataExtremes: dataExtremes, + // We need to get timeExtremes for each series. We pass this + // in when building the TimelinePath objects to avoid + // calculating twice. + timeExtremes: getTimeExtremes(series, chartSonifyOptions.pointPlayTime), + // Some options we just pass on + instruments: chartSonifyOptions.instruments, + onStart: chartSonifyOptions.onSeriesStart, + onEnd: chartSonifyOptions.onSeriesEnd, + earcons: chartSonifyOptions.earcons + }, + // Merge in the specific series options by ID + isArray(seriesOptions) ? (find(seriesOptions, function (optEntry) { + return optEntry.id === pick(series.id, series.options.id); + }) || {}) : seriesOptions, { + // Forced options + pointPlayTime: chartSonifyOptions.pointPlayTime + }); +} +/** + * Utility function to normalize the ordering of timeline paths when sonifying + * a chart. + * @private + * @param {string|Array>} orderOptions - + * Order options for the sonification. + * @param {Highcharts.Chart} chart - The chart we are sonifying. + * @param {Function} seriesOptionsCallback + * A function that takes a series as argument, and returns the series options + * for that series to be used with buildTimelinePathFromSeries. + * @return {Array>} If order is + * sequential, we return an array of objects to create series paths from. If + * order is simultaneous we return an array of an array with the same. If there + * is a custom order, we return an array of arrays of either objects (for + * series) or TimelinePaths (for earcons and delays). + */ +function buildPathOrder(orderOptions, chart, seriesOptionsCallback) { + var order; + if (orderOptions === 'sequential' || orderOptions === 'simultaneous') { + // Just add the series from the chart + order = chart.series.reduce(function (seriesList, series) { + if (series.visible) { + seriesList.push({ + series: series, + seriesOptions: seriesOptionsCallback(series) + }); + } + return seriesList; + }, []); + // If order is simultaneous, group all series together + if (orderOptions === 'simultaneous') { + order = [order]; + } + } + else { + // We have a specific order, and potentially custom items - like + // earcons or silent waits. + order = orderOptions.reduce(function (orderList, orderDef) { + // Return set of items to play simultaneously. Could be only one. + var simulItems = splat(orderDef).reduce(function (items, item) { + var itemObject; + // Is this item a series ID? + if (typeof item === 'string') { + var series = chart.get(item); + if (series.visible) { + itemObject = { + series: series, + seriesOptions: seriesOptionsCallback(series) + }; + } + // Is it an earcon? If so, just create the path. + } + else if (item instanceof H.sonification.Earcon) { + // Path with a single event + itemObject = new H.sonification.TimelinePath({ + events: [new H.sonification.TimelineEvent({ + eventObject: item + })] + }); + } + // Is this item a silent wait? If so, just create the path. + if (item.silentWait) { + itemObject = new H.sonification.TimelinePath({ + silentWait: item.silentWait + }); + } + // Add to items to play simultaneously + if (itemObject) { + items.push(itemObject); + } + return items; + }, []); + // Add to order list + if (simulItems.length) { + orderList.push(simulItems); + } + return orderList; + }, []); + } + return order; +} +/** + * Utility function to add a silent wait after all series. + * @private + * @param {Array>} order + * The order of items. + * @param {number} wait + * The wait in milliseconds to add. + * @return {Array>} + * The order with waits inserted. + */ +function addAfterSeriesWaits(order, wait) { + if (!wait) { + return order; + } + return order.reduce(function (newOrder, orderDef, i) { + var simultaneousPaths = splat(orderDef); + newOrder.push(simultaneousPaths); + // Go through the simultaneous paths and see if there is a series there + if (i < order.length - 1 && // Do not add wait after last series + simultaneousPaths.some(function (item) { + return item.series; + })) { + // We have a series, meaning we should add a wait after these + // paths have finished. + newOrder.push(new H.sonification.TimelinePath({ + silentWait: wait + })); + } + return newOrder; + }, []); +} +/** + * Utility function to find the total amout of wait time in the TimelinePaths. + * @private + * @param {Array>} order - The order of + * TimelinePaths/items. + * @return {number} The total time in ms spent on wait paths between playing. + */ +function getWaitTime(order) { + return order.reduce(function (waitTime, orderDef) { + var def = splat(orderDef); + return waitTime + (def.length === 1 && + def[0].options && + def[0].options.silentWait || 0); + }, 0); +} +/** + * Utility function to ensure simultaneous paths have start/end events at the + * same time, to sync them. + * @private + * @param {Array} paths - The paths to sync. + */ +function syncSimultaneousPaths(paths) { + // Find the extremes for these paths + var extremes = paths.reduce(function (extremes, path) { + var events = path.events; + if (events && events.length) { + extremes.min = Math.min(events[0].time, extremes.min); + extremes.max = Math.max(events[events.length - 1].time, extremes.max); + } + return extremes; + }, { + min: Infinity, + max: -Infinity + }); + // Go through the paths and add events to make them fit the same timespan + paths.forEach(function (path) { + var events = path.events, hasEvents = events && events.length, eventsToAdd = []; + if (!(hasEvents && events[0].time <= extremes.min)) { + eventsToAdd.push(new H.sonification.TimelineEvent({ + time: extremes.min + })); + } + if (!(hasEvents && events[events.length - 1].time >= extremes.max)) { + eventsToAdd.push(new H.sonification.TimelineEvent({ + time: extremes.max + })); + } + if (eventsToAdd.length) { + path.addTimelineEvents(eventsToAdd); + } + }); +} +/** + * Utility function to find the total duration span for all simul path sets + * that include series. + * @private + * @param {Array>} order - The + * order of TimelinePaths/items. + * @return {number} The total time value span difference for all series. + */ +function getSimulPathDurationTotal(order) { + return order.reduce(function (durationTotal, orderDef) { + return durationTotal + splat(orderDef).reduce(function (maxPathDuration, item) { + var timeExtremes = (item.series && + item.seriesOptions && + item.seriesOptions.timeExtremes); + return timeExtremes ? + Math.max(maxPathDuration, timeExtremes.max - timeExtremes.min) : maxPathDuration; + }, 0); + }, 0); +} +/** + * Function to calculate the duration in ms for a series. + * @private + * @param {number} seriesValueDuration - The duration of the series in value + * difference. + * @param {number} totalValueDuration - The total duration of all (non + * simultaneous) series in value difference. + * @param {number} totalDurationMs - The desired total duration for all series + * in milliseconds. + * @return {number} The duration for the series in milliseconds. + */ +function getSeriesDurationMs(seriesValueDuration, totalValueDuration, totalDurationMs) { + // A series spanning the whole chart would get the full duration. + return utilities.virtualAxisTranslate(seriesValueDuration, { min: 0, max: totalValueDuration }, { min: 0, max: totalDurationMs }); +} +/** + * Convert series building objects into paths and return a new list of + * TimelinePaths. + * @private + * @param {Array>} order - The + * order list. + * @param {number} duration - Total duration to aim for in milliseconds. + * @return {Array>} Array of TimelinePath objects + * to play. + */ +function buildPathsFromOrder(order, duration) { + // Find time used for waits (custom or after series), and subtract it from + // available duration. + var totalAvailableDurationMs = Math.max(duration - getWaitTime(order), 0), + // Add up simultaneous path durations to find total value span duration + // of everything + totalUsedDuration = getSimulPathDurationTotal(order); + // Go through the order list and convert the items + return order.reduce(function (allPaths, orderDef) { + var simultaneousPaths = splat(orderDef).reduce(function (simulPaths, item) { + if (item instanceof H.sonification.TimelinePath) { + // This item is already a path object + simulPaths.push(item); + } + else if (item.series) { + // We have a series. + // We need to set the duration of the series + item.seriesOptions.duration = + item.seriesOptions.duration || getSeriesDurationMs(item.seriesOptions.timeExtremes.max - + item.seriesOptions.timeExtremes.min, totalUsedDuration, totalAvailableDurationMs); + // Add the path + simulPaths.push(buildTimelinePathFromSeries(item.series, item.seriesOptions)); + } + return simulPaths; + }, []); + // Add in the simultaneous paths + allPaths.push(simultaneousPaths); + return allPaths; + }, []); +} +/** + * @private + * @param {Highcharts.Chart} chart The chart to get options for. + * @param {Highcharts.SonificationOptions} userOptions + * Options to merge with options on chart and default options. + * @returns {Highcharts.SonificationOptions} The merged options. + */ +function getChartSonifyOptions(chart, userOptions) { + return merge(chart.options.sonification, userOptions); +} +/** + * Options for sonifying a chart. + * + * @requires module:modules/sonification + * + * @interface Highcharts.SonificationOptions + */ /** +* Duration for sonifying the entire chart. The duration is distributed across +* the different series intelligently, but does not take earcons into account. +* It is also possible to set the duration explicitly per series, using +* `seriesOptions`. Note that points may continue to play after the duration has +* passed, but no new points will start playing. +* @name Highcharts.SonificationOptions#duration +* @type {number} +*/ /** +* Define the order to play the series in. This can be given as a string, or an +* array specifying a custom ordering. If given as a string, valid values are +* `sequential` - where each series is played in order - or `simultaneous`, +* where all series are played at once. For custom ordering, supply an array as +* the order. Each element in the array can be either a string with a series ID, +* an Earcon object, or an object with a numeric `silentWait` property +* designating a number of milliseconds to wait before continuing. Each element +* of the array will be played in order. To play elements simultaneously, group +* the elements in an array. +* @name Highcharts.SonificationOptions#order +* @type {string|Array>} +*/ /** +* The axis to use for when to play the points. Can be a string with a data +* property (e.g. `x`), or a function. If it is a function, this function +* receives the point as argument, and should return a numeric value. The points +* with the lowest numeric values are then played first, and the time between +* points will be proportional to the distance between the numeric values. This +* option can not be overridden per series. +* @name Highcharts.SonificationOptions#pointPlayTime +* @type {string|Function} +*/ /** +* Milliseconds of silent waiting to add between series. Note that waiting time +* is considered part of the sonify duration. +* @name Highcharts.SonificationOptions#afterSeriesWait +* @type {number|undefined} +*/ /** +* Options as given to `series.sonify` to override options per series. If the +* option is supplied as an array of options objects, the `id` property of the +* object should correspond to the series' id. If the option is supplied as a +* single object, the options apply to all series. +* @name Highcharts.SonificationOptions#seriesOptions +* @type {Object|Array|undefined} +*/ /** +* The instrument definitions for the points in this chart. +* @name Highcharts.SonificationOptions#instruments +* @type {Array|undefined} +*/ /** +* Earcons to add to the chart. Note that earcons can also be added per series +* using `seriesOptions`. +* @name Highcharts.SonificationOptions#earcons +* @type {Array|undefined} +*/ /** +* Optionally provide the minimum/maximum data values for the points. If this is +* not supplied, it is calculated from all points in the chart on demand. This +* option is supplied in the following format, as a map of point data properties +* to objects with min/max values: +* ```js +* dataExtremes: { +* y: { +* min: 0, +* max: 100 +* }, +* z: { +* min: -10, +* max: 10 +* } +* // Properties used and not provided are calculated on demand +* } +* ``` +* @name Highcharts.SonificationOptions#dataExtremes +* @type {Highcharts.Dictionary|undefined} +*/ /** +* Callback before a series is played. +* @name Highcharts.SonificationOptions#onSeriesStart +* @type {Function|undefined} +*/ /** +* Callback after a series has finished playing. +* @name Highcharts.SonificationOptions#onSeriesEnd +* @type {Function|undefined} +*/ /** +* Callback after the chart has played. +* @name Highcharts.SonificationOptions#onEnd +* @type {Function|undefined} +*/ +/** + * Sonify a chart. + * + * @sample highcharts/sonification/chart-sequential/ + * Sonify a basic chart + * @sample highcharts/sonification/chart-simultaneous/ + * Sonify series simultaneously + * @sample highcharts/sonification/chart-custom-order/ + * Custom defined order of series + * @sample highcharts/sonification/chart-earcon/ + * Earcons on chart + * @sample highcharts/sonification/chart-events/ + * Sonification events on chart + * + * @requires module:modules/sonification + * + * @function Highcharts.Chart#sonify + * + * @param {Highcharts.SonificationOptions} options + * The options for sonifying this chart. + * + * @return {void} + */ +function chartSonify(options) { + var opts = getChartSonifyOptions(this, options); + // Only one timeline can play at a time. + if (this.sonification.timeline) { + this.sonification.timeline.pause(); + } + // Store reference to duration + this.sonification.duration = opts.duration; + // Calculate data extremes for the props used + var dataExtremes = getExtremesForInstrumentProps(this, opts.instruments, opts.dataExtremes); + // Figure out ordering of series and custom paths + var order = buildPathOrder(opts.order, this, function (series) { + return buildSeriesOptions(series, dataExtremes, opts); + }); + // Add waits after simultaneous paths with series in them. + order = addAfterSeriesWaits(order, opts.afterSeriesWait || 0); + // We now have a list of either TimelinePath objects or series that need to + // be converted to TimelinePath objects. Convert everything to paths. + var paths = buildPathsFromOrder(order, opts.duration); + // Sync simultaneous paths + paths.forEach(function (simultaneousPaths) { + syncSimultaneousPaths(simultaneousPaths); + }); + // We have a set of paths. Create the timeline, and play it. + this.sonification.timeline = new H.sonification.Timeline({ + paths: paths, + onEnd: opts.onEnd + }); + this.sonification.timeline.play(); +} +/** + * Get a list of the points currently under cursor. + * + * @requires module:modules/sonification + * + * @function Highcharts.Chart#getCurrentSonifyPoints + * + * @return {Array} + * The points currently under the cursor. + */ +function getCurrentPoints() { + var cursorObj; + if (this.sonification.timeline) { + cursorObj = this.sonification.timeline.getCursor(); // Cursor per pathID + return Object.keys(cursorObj).map(function (path) { + // Get the event objects under cursor for each path + return cursorObj[path].eventObject; + }).filter(function (eventObj) { + // Return the events that are points + return eventObj instanceof Point; + }); + } + return []; +} +/** + * Set the cursor to a point or set of points in different series. + * + * @requires module:modules/sonification + * + * @function Highcharts.Chart#setSonifyCursor + * + * @param {Highcharts.Point|Array} points + * The point or points to set the cursor to. If setting multiple points + * under the cursor, the points have to be in different series that are + * being played simultaneously. + */ +function setCursor(points) { + var timeline = this.sonification.timeline; + if (timeline) { + splat(points).forEach(function (point) { + // We created the events with the ID of the points, which makes + // this easy. Just call setCursor for each ID. + timeline.setCursor(point.id); + }); + } +} +/** + * Pause the running sonification. + * + * @requires module:modules/sonification + * + * @function Highcharts.Chart#pauseSonify + * + * @param {boolean} [fadeOut=true] + * Fade out as we pause to avoid clicks. + * + * @return {void} + */ +function pause(fadeOut) { + if (this.sonification.timeline) { + this.sonification.timeline.pause(pick(fadeOut, true)); + } + else if (this.sonification.currentlyPlayingPoint) { + this.sonification.currentlyPlayingPoint.cancelSonify(fadeOut); + } +} +/** + * Resume the currently running sonification. Requires series.sonify or + * chart.sonify to have been played at some point earlier. + * + * @requires module:modules/sonification + * + * @function Highcharts.Chart#resumeSonify + * + * @param {Function} onEnd + * Callback to call when play finished. + * + * @return {void} + */ +function resume(onEnd) { + if (this.sonification.timeline) { + this.sonification.timeline.play(onEnd); + } +} +/** + * Play backwards from cursor. Requires series.sonify or chart.sonify to have + * been played at some point earlier. + * + * @requires module:modules/sonification + * + * @function Highcharts.Chart#rewindSonify + * + * @param {Function} onEnd + * Callback to call when play finished. + * + * @return {void} + */ +function rewind(onEnd) { + if (this.sonification.timeline) { + this.sonification.timeline.rewind(onEnd); + } +} +/** + * Cancel current sonification and reset cursor. + * + * @requires module:modules/sonification + * + * @function Highcharts.Chart#cancelSonify + * + * @param {boolean} [fadeOut=true] + * Fade out as we pause to avoid clicks. + * + * @return {void} + */ +function cancel(fadeOut) { + this.pauseSonify(fadeOut); + this.resetSonifyCursor(); +} +/** + * Reset cursor to start. Requires series.sonify or chart.sonify to have been + * played at some point earlier. + * + * @requires module:modules/sonification + * + * @function Highcharts.Chart#resetSonifyCursor + * + * @return {void} + */ +function resetCursor() { + if (this.sonification.timeline) { + this.sonification.timeline.resetCursor(); + } +} +/** + * Reset cursor to end. Requires series.sonify or chart.sonify to have been + * played at some point earlier. + * + * @requires module:modules/sonification + * + * @function Highcharts.Chart#resetSonifyCursorEnd + * + * @return {void} + */ +function resetCursorEnd() { + if (this.sonification.timeline) { + this.sonification.timeline.resetCursorEnd(); + } +} +// Export functions +var chartSonifyFunctions = { + chartSonify: chartSonify, + seriesSonify: seriesSonify, + pause: pause, + resume: resume, + rewind: rewind, + cancel: cancel, + getCurrentPoints: getCurrentPoints, + setCursor: setCursor, + resetCursor: resetCursor, + resetCursorEnd: resetCursorEnd +}; +export default chartSonifyFunctions; diff --git a/librerias/gantt/code/es-modules/modules/sonification/instrumentDefinitions.js b/librerias/gantt/code/es-modules/modules/sonification/instrumentDefinitions.js new file mode 100644 index 0000000..16f6566 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/sonification/instrumentDefinitions.js @@ -0,0 +1,32 @@ +/* * + * + * (c) 2009-2020 Øystein Moseng + * + * Instrument definitions for sonification module. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Instrument from './Instrument.js'; +import utilities from './utilities.js'; +var instruments = {}; +['sine', 'square', 'triangle', 'sawtooth'].forEach(function (waveform) { + // Add basic instruments + instruments[waveform] = new Instrument({ + oscillator: { waveformShape: waveform } + }); + // Add musical instruments + instruments[waveform + 'Musical'] = new Instrument({ + allowedFrequencies: utilities.musicalFrequencies, + oscillator: { waveformShape: waveform } + }); + // Add scaled instruments + instruments[waveform + 'Major'] = new Instrument({ + allowedFrequencies: utilities.getMusicalScale([1, 3, 5, 6, 8, 10, 12]), + oscillator: { waveformShape: waveform } + }); +}); +export default instruments; diff --git a/librerias/gantt/code/es-modules/modules/sonification/musicalFrequencies.js b/librerias/gantt/code/es-modules/modules/sonification/musicalFrequencies.js new file mode 100644 index 0000000..844a03c --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/sonification/musicalFrequencies.js @@ -0,0 +1,112 @@ +/* * + * + * (c) 2009-2020 Øystein Moseng + * + * List of musical frequencies from C0 to C8. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +var frequencies = [ + 16.351597831287414, + 17.323914436054505, + 18.354047994837977, + 19.445436482630058, + 20.601722307054366, + 21.826764464562746, + 23.12465141947715, + 24.499714748859326, + 25.956543598746574, + 27.5, + 29.13523509488062, + 30.86770632850775, + 32.70319566257483, + 34.64782887210901, + 36.70809598967594, + 38.890872965260115, + 41.20344461410875, + 43.653528929125486, + 46.2493028389543, + 48.999429497718666, + 51.91308719749314, + 55, + 58.27047018976124, + 61.7354126570155, + 65.40639132514966, + 69.29565774421802, + 73.41619197935188, + 77.78174593052023, + 82.4068892282175, + 87.30705785825097, + 92.4986056779086, + 97.99885899543733, + 103.82617439498628, + 110, + 116.54094037952248, + 123.47082531403103, + 130.8127826502993, + 138.59131548843604, + 146.8323839587038, + 155.56349186104046, + 164.81377845643496, + 174.61411571650194, + 184.9972113558172, + 195.99771799087463, + 207.65234878997256, + 220, + 233.08188075904496, + 246.94165062806206, + 261.6255653005986, + 277.1826309768721, + 293.6647679174076, + 311.1269837220809, + 329.6275569128699, + 349.2282314330039, + 369.9944227116344, + 391.99543598174927, + 415.3046975799451, + 440, + 466.1637615180899, + 493.8833012561241, + 523.2511306011972, + 554.3652619537442, + 587.3295358348151, + 622.2539674441618, + 659.2551138257398, + 698.4564628660078, + 739.9888454232688, + 783.9908719634985, + 830.6093951598903, + 880, + 932.3275230361799, + 987.7666025122483, + 1046.5022612023945, + 1108.7305239074883, + 1174.6590716696303, + 1244.5079348883237, + 1318.5102276514797, + 1396.9129257320155, + 1479.9776908465376, + 1567.981743926997, + 1661.2187903197805, + 1760, + 1864.6550460723597, + 1975.533205024496, + 2093.004522404789, + 2217.4610478149766, + 2349.31814333926, + 2489.0158697766474, + 2637.02045530296, + 2793.825851464031, + 2959.955381693075, + 3135.9634878539946, + 3322.437580639561, + 3520, + 3729.3100921447194, + 3951.066410048992, + 4186.009044809578 // C8 +]; +export default frequencies; diff --git a/librerias/gantt/code/es-modules/modules/sonification/options.js b/librerias/gantt/code/es-modules/modules/sonification/options.js new file mode 100644 index 0000000..b2eafe2 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/sonification/options.js @@ -0,0 +1,36 @@ +/* * + * + * (c) 2009-2020 Øystein Moseng + * + * Default options for sonification. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +// Experimental, disabled by default, not exposed in API +var options = { + sonification: { + enabled: false, + duration: 2000, + afterSeriesWait: 1000, + order: 'sequential', + pointPlayTime: 'x', + instruments: [{ + instrument: 'sineMusical', + instrumentMapping: { + duration: 400, + frequency: 'y', + volume: 0.7 + }, + // Start at G4 note, end at C6 + instrumentOptions: { + minFrequency: 392, + maxFrequency: 1046 + } + }] + } +}; +export default options; diff --git a/librerias/gantt/code/es-modules/modules/sonification/pointSonify.js b/librerias/gantt/code/es-modules/modules/sonification/pointSonify.js new file mode 100644 index 0000000..cf4811b --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/sonification/pointSonify.js @@ -0,0 +1,321 @@ +/* * + * + * (c) 2009-2020 Øystein Moseng + * + * Code for sonifying single points. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../../parts/Globals.js'; +import U from '../../parts/Utilities.js'; +var error = U.error, merge = U.merge, pick = U.pick; +/** + * Define the parameter mapping for an instrument. + * + * @requires module:modules/sonification + * + * @interface Highcharts.PointInstrumentMappingObject + */ /** +* Define the volume of the instrument. This can be a string with a data +* property name, e.g. `'y'`, in which case this data property is used to define +* the volume relative to the `y`-values of the other points. A higher `y` value +* would then result in a higher volume. This option can also be a fixed number +* or a function. If it is a function, this function is called in regular +* intervals while the note is playing. It receives three arguments: The point, +* the dataExtremes, and the current relative time - where 0 is the beginning of +* the note and 1 is the end. The function should return the volume of the note +* as a number between 0 and 1. +* @name Highcharts.PointInstrumentMappingObject#volume +* @type {string|number|Function} +*/ /** +* Define the duration of the notes for this instrument. This can be a string +* with a data property name, e.g. `'y'`, in which case this data property is +* used to define the duration relative to the `y`-values of the other points. A +* higher `y` value would then result in a longer duration. This option can also +* be a fixed number or a function. If it is a function, this function is called +* once before the note starts playing, and should return the duration in +* milliseconds. It receives two arguments: The point, and the dataExtremes. +* @name Highcharts.PointInstrumentMappingObject#duration +* @type {string|number|Function} +*/ /** +* Define the panning of the instrument. This can be a string with a data +* property name, e.g. `'x'`, in which case this data property is used to define +* the panning relative to the `x`-values of the other points. A higher `x` +* value would then result in a higher panning value (panned further to the +* right). This option can also be a fixed number or a function. If it is a +* function, this function is called in regular intervals while the note is +* playing. It receives three arguments: The point, the dataExtremes, and the +* current relative time - where 0 is the beginning of the note and 1 is the +* end. The function should return the panning of the note as a number between +* -1 and 1. +* @name Highcharts.PointInstrumentMappingObject#pan +* @type {string|number|Function|undefined} +*/ /** +* Define the frequency of the instrument. This can be a string with a data +* property name, e.g. `'y'`, in which case this data property is used to define +* the frequency relative to the `y`-values of the other points. A higher `y` +* value would then result in a higher frequency. This option can also be a +* fixed number or a function. If it is a function, this function is called in +* regular intervals while the note is playing. It receives three arguments: +* The point, the dataExtremes, and the current relative time - where 0 is the +* beginning of the note and 1 is the end. The function should return the +* frequency of the note as a number (in Hz). +* @name Highcharts.PointInstrumentMappingObject#frequency +* @type {string|number|Function} +*/ +/** + * @requires module:modules/sonification + * + * @interface Highcharts.PointInstrumentOptionsObject + */ /** +* The minimum duration for a note when using a data property for duration. Can +* be overridden by using either a fixed number or a function for +* instrumentMapping.duration. Defaults to 20. +* @name Highcharts.PointInstrumentOptionsObject#minDuration +* @type {number|undefined} +*/ /** +* The maximum duration for a note when using a data property for duration. Can +* be overridden by using either a fixed number or a function for +* instrumentMapping.duration. Defaults to 2000. +* @name Highcharts.PointInstrumentOptionsObject#maxDuration +* @type {number|undefined} +*/ /** +* The minimum pan value for a note when using a data property for panning. Can +* be overridden by using either a fixed number or a function for +* instrumentMapping.pan. Defaults to -1 (fully left). +* @name Highcharts.PointInstrumentOptionsObject#minPan +* @type {number|undefined} +*/ /** +* The maximum pan value for a note when using a data property for panning. Can +* be overridden by using either a fixed number or a function for +* instrumentMapping.pan. Defaults to 1 (fully right). +* @name Highcharts.PointInstrumentOptionsObject#maxPan +* @type {number|undefined} +*/ /** +* The minimum volume for a note when using a data property for volume. Can be +* overridden by using either a fixed number or a function for +* instrumentMapping.volume. Defaults to 0.1. +* @name Highcharts.PointInstrumentOptionsObject#minVolume +* @type {number|undefined} +*/ /** +* The maximum volume for a note when using a data property for volume. Can be +* overridden by using either a fixed number or a function for +* instrumentMapping.volume. Defaults to 1. +* @name Highcharts.PointInstrumentOptionsObject#maxVolume +* @type {number|undefined} +*/ /** +* The minimum frequency for a note when using a data property for frequency. +* Can be overridden by using either a fixed number or a function for +* instrumentMapping.frequency. Defaults to 220. +* @name Highcharts.PointInstrumentOptionsObject#minFrequency +* @type {number|undefined} +*/ /** +* The maximum frequency for a note when using a data property for frequency. +* Can be overridden by using either a fixed number or a function for +* instrumentMapping.frequency. Defaults to 2200. +* @name Highcharts.PointInstrumentOptionsObject#maxFrequency +* @type {number|undefined} +*/ +/** + * An instrument definition for a point, specifying the instrument to play and + * how to play it. + * + * @interface Highcharts.PointInstrumentObject + */ /** +* An Instrument instance or the name of the instrument in the +* Highcharts.sonification.instruments map. +* @name Highcharts.PointInstrumentObject#instrument +* @type {Highcharts.Instrument|string} +*/ /** +* Mapping of instrument parameters for this instrument. +* @name Highcharts.PointInstrumentObject#instrumentMapping +* @type {Highcharts.PointInstrumentMappingObject} +*/ /** +* Options for this instrument. +* @name Highcharts.PointInstrumentObject#instrumentOptions +* @type {Highcharts.PointInstrumentOptionsObject|undefined} +*/ /** +* Callback to call when the instrument has stopped playing. +* @name Highcharts.PointInstrumentObject#onEnd +* @type {Function|undefined} +*/ +/** + * Options for sonifying a point. + * @interface Highcharts.PointSonifyOptionsObject + */ /** +* The instrument definitions for this point. +* @name Highcharts.PointSonifyOptionsObject#instruments +* @type {Array} +*/ /** +* Optionally provide the minimum/maximum values for the points. If this is not +* supplied, it is calculated from the points in the chart on demand. This +* option is supplied in the following format, as a map of point data properties +* to objects with min/max values: +* ```js +* dataExtremes: { +* y: { +* min: 0, +* max: 100 +* }, +* z: { +* min: -10, +* max: 10 +* } +* // Properties used and not provided are calculated on demand +* } +* ``` +* @name Highcharts.PointSonifyOptionsObject#dataExtremes +* @type {object|undefined} +*/ /** +* Callback called when the sonification has finished. +* @name Highcharts.PointSonifyOptionsObject#onEnd +* @type {Function|undefined} +*/ +import utilities from './utilities.js'; +// Defaults for the instrument options +// NOTE: Also change defaults in Highcharts.PointInstrumentOptionsObject if +// making changes here. +var defaultInstrumentOptions = { + minDuration: 20, + maxDuration: 2000, + minVolume: 0.1, + maxVolume: 1, + minPan: -1, + maxPan: 1, + minFrequency: 220, + maxFrequency: 2200 +}; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * Sonify a single point. + * + * @sample highcharts/sonification/point-basic/ + * Click on points to sonify + * @sample highcharts/sonification/point-advanced/ + * Sonify bubbles + * + * @requires module:modules/sonification + * + * @function Highcharts.Point#sonify + * + * @param {Highcharts.PointSonifyOptionsObject} options + * Options for the sonification of the point. + * + * @return {void} + */ +function pointSonify(options) { + var point = this, chart = point.series.chart, dataExtremes = options.dataExtremes || {}, + // Get the value to pass to instrument.play from the mapping value + // passed in. + getMappingValue = function (value, makeFunction, allowedExtremes) { + // Function. Return new function if we try to use callback, + // otherwise call it now and return result. + if (typeof value === 'function') { + return makeFunction ? + function (time) { + return value(point, dataExtremes, time); + } : + value(point, dataExtremes); + } + // String, this is a data prop. + if (typeof value === 'string') { + // Find data extremes if we don't have them + dataExtremes[value] = dataExtremes[value] || + utilities.calculateDataExtremes(point.series.chart, value); + // Find the value + return utilities.virtualAxisTranslate(pick(point[value], point.options[value]), dataExtremes[value], allowedExtremes); + } + // Fixed number or something else weird, just use that + return value; + }; + // Register playing point on chart + chart.sonification.currentlyPlayingPoint = point; + // Keep track of instruments playing + point.sonification = point.sonification || {}; + point.sonification.instrumentsPlaying = + point.sonification.instrumentsPlaying || {}; + // Register signal handler for the point + var signalHandler = point.sonification.signalHandler = + point.sonification.signalHandler || + new utilities.SignalHandler(['onEnd']); + signalHandler.clearSignalCallbacks(); + signalHandler.registerSignalCallbacks({ onEnd: options.onEnd }); + // If we have a null point or invisible point, just return + if (point.isNull || !point.visible || !point.series.visible) { + signalHandler.emitSignal('onEnd'); + return; + } + // Go through instruments and play them + options.instruments.forEach(function (instrumentDefinition) { + var instrument = typeof instrumentDefinition.instrument === 'string' ? + H.sonification.instruments[instrumentDefinition.instrument] : + instrumentDefinition.instrument, mapping = instrumentDefinition.instrumentMapping || {}, extremes = merge(defaultInstrumentOptions, instrumentDefinition.instrumentOptions), id = instrument.id, onEnd = function (cancelled) { + // Instrument on end + if (instrumentDefinition.onEnd) { + instrumentDefinition.onEnd.apply(this, arguments); + } + // Remove currently playing point reference on chart + if (chart.sonification && + chart.sonification.currentlyPlayingPoint) { + delete chart.sonification.currentlyPlayingPoint; + } + // Remove reference from instruments playing + if (point.sonification && point.sonification.instrumentsPlaying) { + delete point.sonification.instrumentsPlaying[id]; + // This was the last instrument? + if (!Object.keys(point.sonification.instrumentsPlaying).length) { + signalHandler.emitSignal('onEnd', cancelled); + } + } + }; + // Play the note on the instrument + if (instrument && instrument.play) { + point.sonification.instrumentsPlaying[instrument.id] = + instrument; + instrument.play({ + frequency: getMappingValue(mapping.frequency, true, { min: extremes.minFrequency, max: extremes.maxFrequency }), + duration: getMappingValue(mapping.duration, false, { min: extremes.minDuration, max: extremes.maxDuration }), + pan: getMappingValue(mapping.pan, true, { min: extremes.minPan, max: extremes.maxPan }), + volume: getMappingValue(mapping.volume, true, { min: extremes.minVolume, max: extremes.maxVolume }), + onEnd: onEnd, + minFrequency: extremes.minFrequency, + maxFrequency: extremes.maxFrequency + }); + } + else { + error(30); + } + }); +} +/** + * Cancel sonification of a point. Calls onEnd functions. + * + * @requires module:modules/sonification + * + * @function Highcharts.Point#cancelSonify + * + * @param {boolean} [fadeOut=false] + * Whether or not to fade out as we stop. If false, the points are + * cancelled synchronously. + * + * @return {void} + */ +function pointCancelSonify(fadeOut) { + var playing = this.sonification && this.sonification.instrumentsPlaying, instrIds = playing && Object.keys(playing); + if (instrIds && instrIds.length) { + instrIds.forEach(function (instr) { + playing[instr].stop(!fadeOut, null, 'cancelled'); + }); + this.sonification.instrumentsPlaying = {}; + this.sonification.signalHandler.emitSignal('onEnd', 'cancelled'); + } +} +var pointSonifyFunctions = { + pointSonify: pointSonify, + pointCancelSonify: pointCancelSonify +}; +export default pointSonifyFunctions; diff --git a/librerias/gantt/code/es-modules/modules/sonification/sonification.js b/librerias/gantt/code/es-modules/modules/sonification/sonification.js new file mode 100644 index 0000000..ec64bde --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/sonification/sonification.js @@ -0,0 +1,119 @@ +/* * + * + * (c) 2009-2020 Øystein Moseng + * + * Sonification module for Highcharts + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../../parts/Globals.js'; +import Point from '../../parts/Point.js'; +import U from '../../parts/Utilities.js'; +var addEvent = U.addEvent, extend = U.extend, merge = U.merge; +import Instrument from './Instrument.js'; +import instruments from './instrumentDefinitions.js'; +import Earcon from './Earcon.js'; +import pointSonifyFunctions from './pointSonify.js'; +import chartSonifyFunctions from './chartSonify.js'; +import utilities from './utilities.js'; +import TimelineClasses from './Timeline.js'; +import sonificationOptions from './options.js'; +// Expose on the Highcharts object +/** + * Global classes and objects related to sonification. + * + * @requires module:modules/sonification + * + * @name Highcharts.sonification + * @type {Highcharts.SonificationObject} + */ +/** + * Global classes and objects related to sonification. + * + * @requires module:modules/sonification + * + * @interface Highcharts.SonificationObject + */ /** +* Note fade-out-time in milliseconds. Most notes are faded out quickly by +* default if there is time. This is to avoid abrupt stops which will cause +* perceived clicks. +* @name Highcharts.SonificationObject#fadeOutDuration +* @type {number} +*/ /** +* Utility functions. +* @name Highcharts.SonificationObject#utilities +* @private +* @type {object} +*/ /** +* The Instrument class. +* @name Highcharts.SonificationObject#Instrument +* @type {Function} +*/ /** +* Predefined instruments, given as an object with a map between the instrument +* name and the Highcharts.Instrument object. +* @name Highcharts.SonificationObject#instruments +* @type {Object} +*/ /** +* The Earcon class. +* @name Highcharts.SonificationObject#Earcon +* @type {Function} +*/ /** +* The TimelineEvent class. +* @private +* @name Highcharts.SonificationObject#TimelineEvent +* @type {Function} +*/ /** +* The TimelinePath class. +* @private +* @name Highcharts.SonificationObject#TimelinePath +* @type {Function} +*/ /** +* The Timeline class. +* @private +* @name Highcharts.SonificationObject#Timeline +* @type {Function} +*/ +H.sonification = { + fadeOutDuration: 20, + // Classes and functions + utilities: utilities, + Instrument: Instrument, + instruments: instruments, + Earcon: Earcon, + TimelineEvent: TimelineClasses.TimelineEvent, + TimelinePath: TimelineClasses.TimelinePath, + Timeline: TimelineClasses.Timeline +}; +// Add default options +merge(true, H.defaultOptions, sonificationOptions); +// Chart specific +Point.prototype.sonify = pointSonifyFunctions.pointSonify; +Point.prototype.cancelSonify = pointSonifyFunctions.pointCancelSonify; +H.Series.prototype.sonify = chartSonifyFunctions.seriesSonify; +extend(H.Chart.prototype, { + sonify: chartSonifyFunctions.chartSonify, + pauseSonify: chartSonifyFunctions.pause, + resumeSonify: chartSonifyFunctions.resume, + rewindSonify: chartSonifyFunctions.rewind, + cancelSonify: chartSonifyFunctions.cancel, + getCurrentSonifyPoints: chartSonifyFunctions.getCurrentPoints, + setSonifyCursor: chartSonifyFunctions.setCursor, + resetSonifyCursor: chartSonifyFunctions.resetCursor, + resetSonifyCursorEnd: chartSonifyFunctions.resetCursorEnd +}); +/* eslint-disable no-invalid-this */ +// Prepare charts for sonification on init +addEvent(H.Chart, 'init', function () { + this.sonification = {}; +}); +// Update with chart/series/point updates +addEvent(H.Chart, 'update', function (e) { + var newOptions = e.options.sonification; + if (newOptions) { + merge(true, this.options.sonification, newOptions); + } +}); diff --git a/librerias/gantt/code/es-modules/modules/sonification/utilities.js b/librerias/gantt/code/es-modules/modules/sonification/utilities.js new file mode 100644 index 0000000..f463def --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/sonification/utilities.js @@ -0,0 +1,165 @@ +/* * + * + * (c) 2009-2020 Øystein Moseng + * + * Utility functions for sonification. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import musicalFrequencies from './musicalFrequencies.js'; +import U from '../../parts/Utilities.js'; +var clamp = U.clamp; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * The SignalHandler class. Stores signal callbacks (event handlers), and + * provides an interface to register them, and emit signals. The word "event" is + * not used to avoid confusion with TimelineEvents. + * + * @requires module:modules/sonification + * + * @private + * @class + * @name Highcharts.SignalHandler + * + * @param {Array} supportedSignals + * List of supported signal names. + */ +function SignalHandler(supportedSignals) { + this.init(supportedSignals || []); +} +SignalHandler.prototype.init = function (supportedSignals) { + this.supportedSignals = supportedSignals; + this.signals = {}; +}; +/** + * Register a set of signal callbacks with this SignalHandler. + * Multiple signal callbacks can be registered for the same signal. + * @private + * @param {Highcharts.Dictionary<(Function|undefined)>} signals + * An object that contains a mapping from the signal name to the callbacks. Only + * supported events are considered. + * @return {void} + */ +SignalHandler.prototype.registerSignalCallbacks = function (signals) { + var signalHandler = this; + signalHandler.supportedSignals.forEach(function (supportedSignal) { + var signal = signals[supportedSignal]; + if (signal) { + (signalHandler.signals[supportedSignal] = + signalHandler.signals[supportedSignal] || []).push(signal); + } + }); +}; +/** + * Clear signal callbacks, optionally by name. + * @private + * @param {Array} [signalNames] - A list of signal names to clear. If + * not supplied, all signal callbacks are removed. + * @return {void} + */ +SignalHandler.prototype.clearSignalCallbacks = function (signalNames) { + var signalHandler = this; + if (signalNames) { + signalNames.forEach(function (signalName) { + if (signalHandler.signals[signalName]) { + delete signalHandler.signals[signalName]; + } + }); + } + else { + signalHandler.signals = {}; + } +}; +/** + * Emit a signal. Does nothing if the signal does not exist, or has no + * registered callbacks. + * @private + * @param {string} signalNames + * Name of signal to emit. + * @param {*} [data] + * Data to pass to the callback. + * @return {*} + */ +SignalHandler.prototype.emitSignal = function (signalName, data) { + var retval; + if (this.signals[signalName]) { + this.signals[signalName].forEach(function (handler) { + var result = handler(data); + retval = typeof result !== 'undefined' ? result : retval; + }); + } + return retval; +}; +var utilities = { + // List of musical frequencies from C0 to C8 + musicalFrequencies: musicalFrequencies, + // SignalHandler class + SignalHandler: SignalHandler, + /** + * Get a musical scale by specifying the semitones from 1-12 to include. + * 1: C, 2: C#, 3: D, 4: D#, 5: E, 6: F, + * 7: F#, 8: G, 9: G#, 10: A, 11: Bb, 12: B + * @private + * @param {Array} semitones + * Array of semitones from 1-12 to include in the scale. Duplicate entries + * are ignored. + * @return {Array} + * Array of frequencies from C0 to C8 that are included in this scale. + */ + getMusicalScale: function (semitones) { + return musicalFrequencies.filter(function (freq, i) { + var interval = i % 12 + 1; + return semitones.some(function (allowedInterval) { + return allowedInterval === interval; + }); + }); + }, + /** + * Calculate the extreme values in a chart for a data prop. + * @private + * @param {Highcharts.Chart} chart - The chart + * @param {string} prop - The data prop to find extremes for + * @return {Highcharts.RangeObject} Object with min and max properties + */ + calculateDataExtremes: function (chart, prop) { + return chart.series.reduce(function (extremes, series) { + // We use cropped points rather than series.data here, to allow + // users to zoom in for better fidelity. + series.points.forEach(function (point) { + var val = typeof point[prop] !== 'undefined' ? + point[prop] : point.options[prop]; + extremes.min = Math.min(extremes.min, val); + extremes.max = Math.max(extremes.max, val); + }); + return extremes; + }, { + min: Infinity, + max: -Infinity + }); + }, + /** + * Translate a value on a virtual axis. Creates a new, virtual, axis with a + * min and max, and maps the relative value onto this axis. + * @private + * @param {number} value + * The relative data value to translate. + * @param {Highcharts.RangeObject} DataExtremesObject + * The possible extremes for this value. + * @param {object} limits + * Limits for the virtual axis. + * @return {number} + * The value mapped to the virtual axis. + */ + virtualAxisTranslate: function (value, dataExtremes, limits) { + var lenValueAxis = dataExtremes.max - dataExtremes.min, lenVirtualAxis = limits.max - limits.min, virtualAxisValue = limits.min + + lenVirtualAxis * (value - dataExtremes.min) / lenValueAxis; + return lenValueAxis > 0 ? + clamp(virtualAxisValue, limits.min, limits.max) : + limits.min; + } +}; +export default utilities; diff --git a/librerias/gantt/code/es-modules/modules/static-scale.src.js b/librerias/gantt/code/es-modules/modules/static-scale.src.js new file mode 100644 index 0000000..e17a480 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/static-scale.src.js @@ -0,0 +1,74 @@ +/* * + * + * (c) 2016-2020 Torstein Honsi, Lars Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, defined = U.defined, isNumber = U.isNumber, pick = U.pick; +var Chart = H.Chart; +/* eslint-disable no-invalid-this */ +/** + * For vertical axes only. Setting the static scale ensures that each tick unit + * is translated into a fixed pixel height. For example, setting the static + * scale to 24 results in each Y axis category taking up 24 pixels, and the + * height of the chart adjusts. Adding or removing items will make the chart + * resize. + * + * @sample gantt/xrange-series/demo/ + * X-range series with static scale + * + * @type {number} + * @default 50 + * @since 6.2.0 + * @product gantt + * @apioption yAxis.staticScale + */ +addEvent(H.Axis, 'afterSetOptions', function () { + var chartOptions = this.chart.options && this.chart.options.chart; + if (!this.horiz && + isNumber(this.options.staticScale) && + (!chartOptions.height || + (chartOptions.scrollablePlotArea && + chartOptions.scrollablePlotArea.minHeight))) { + this.staticScale = this.options.staticScale; + } +}); +Chart.prototype.adjustHeight = function () { + if (this.redrawTrigger !== 'adjustHeight') { + (this.axes || []).forEach(function (axis) { + var chart = axis.chart, animate = !!chart.initiatedScale && + chart.options.animation, staticScale = axis.options.staticScale, height, diff; + if (axis.staticScale && defined(axis.min)) { + height = pick(axis.brokenAxis && axis.brokenAxis.unitLength, axis.max + axis.tickInterval - axis.min) * staticScale; + // Minimum height is 1 x staticScale. + height = Math.max(height, staticScale); + diff = height - chart.plotHeight; + if (Math.abs(diff) >= 1) { + chart.plotHeight = height; + chart.redrawTrigger = 'adjustHeight'; + chart.setSize(void 0, chart.chartHeight + diff, animate); + } + // Make sure clip rects have the right height before initial + // animation. + axis.series.forEach(function (series) { + var clipRect = series.sharedClipKey && + chart[series.sharedClipKey]; + if (clipRect) { + clipRect.attr({ + height: chart.plotHeight + }); + } + }); + } + }); + this.initiatedScale = true; + } + this.redrawTrigger = null; +}; +addEvent(Chart, 'render', Chart.prototype.adjustHeight); diff --git a/librerias/gantt/code/es-modules/modules/stock-tools-bindings.js b/librerias/gantt/code/es-modules/modules/stock-tools-bindings.js new file mode 100644 index 0000000..11ef3a9 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/stock-tools-bindings.js @@ -0,0 +1,1720 @@ +/** + * + * Events generator for Stock tools + * + * (c) 2009-2020 Paweł Fus + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import NavigationBindings from '../annotations/navigationBindings.js'; +import U from '../parts/Utilities.js'; +var correctFloat = U.correctFloat, defined = U.defined, extend = U.extend, fireEvent = U.fireEvent, isNumber = U.isNumber, merge = U.merge, pick = U.pick, uniqueKey = U.uniqueKey; +var bindingsUtils = NavigationBindings.prototype.utils, PREFIX = 'highcharts-'; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * Generates function which will add a flag series using modal in GUI. + * Method fires an event "showPopup" with config: + * `{type, options, callback}`. + * + * Example: NavigationBindings.utils.addFlagFromForm('url(...)') - will + * generate function that shows modal in GUI. + * + * @private + * @function bindingsUtils.addFlagFromForm + * + * @param {Highcharts.FlagsShapeValue} type + * Type of flag series, e.g. "squarepin" + * + * @return {Function} + * Callback to be used in `start` callback + */ +bindingsUtils.addFlagFromForm = function (type) { + return function (e) { + var navigation = this, chart = navigation.chart, toolbar = chart.stockTools, getFieldType = bindingsUtils.getFieldType, point = bindingsUtils.attractToPoint(e, chart), pointConfig = { + x: point.x, + y: point.y + }, seriesOptions = { + type: 'flags', + onSeries: point.series.id, + shape: type, + data: [pointConfig], + point: { + events: { + click: function () { + var point = this, options = point.options; + fireEvent(navigation, 'showPopup', { + point: point, + formType: 'annotation-toolbar', + options: { + langKey: 'flags', + type: 'flags', + title: [ + options.title, + getFieldType(options.title) + ], + name: [ + options.name, + getFieldType(options.name) + ] + }, + onSubmit: function (updated) { + if (updated.actionType === 'remove') { + point.remove(); + } + else { + point.update(navigation.fieldsToOptions(updated.fields, {})); + } + } + }); + } + } + } + }; + if (!toolbar || !toolbar.guiEnabled) { + chart.addSeries(seriesOptions); + } + fireEvent(navigation, 'showPopup', { + formType: 'flag', + // Enabled options: + options: { + langKey: 'flags', + type: 'flags', + title: ['A', getFieldType('A')], + name: ['Flag A', getFieldType('Flag A')] + }, + // Callback on submit: + onSubmit: function (data) { + navigation.fieldsToOptions(data.fields, seriesOptions.data[0]); + chart.addSeries(seriesOptions); + } + }); + }; +}; +bindingsUtils.manageIndicators = function (data) { + var navigation = this, chart = navigation.chart, seriesConfig = { + linkedTo: data.linkedTo, + type: data.type + }, indicatorsWithVolume = [ + 'ad', + 'cmf', + 'mfi', + 'vbp', + 'vwap' + ], indicatorsWithAxes = [ + 'ad', + 'atr', + 'cci', + 'cmf', + 'macd', + 'mfi', + 'roc', + 'rsi', + 'ao', + 'aroon', + 'aroonoscillator', + 'trix', + 'apo', + 'dpo', + 'ppo', + 'natr', + 'williamsr', + 'stochastic', + 'slowstochastic', + 'linearRegression', + 'linearRegressionSlope', + 'linearRegressionIntercept', + 'linearRegressionAngle' + ], yAxis, series; + if (data.actionType === 'edit') { + navigation.fieldsToOptions(data.fields, seriesConfig); + series = chart.get(data.seriesId); + if (series) { + series.update(seriesConfig, false); + } + } + else if (data.actionType === 'remove') { + series = chart.get(data.seriesId); + if (series) { + yAxis = series.yAxis; + if (series.linkedSeries) { + series.linkedSeries.forEach(function (linkedSeries) { + linkedSeries.remove(false); + }); + } + series.remove(false); + if (indicatorsWithAxes.indexOf(series.type) >= 0) { + yAxis.remove(false); + navigation.resizeYAxes(); + } + } + } + else { + seriesConfig.id = uniqueKey(); + navigation.fieldsToOptions(data.fields, seriesConfig); + if (indicatorsWithAxes.indexOf(data.type) >= 0) { + yAxis = chart.addAxis({ + id: uniqueKey(), + offset: 0, + opposite: true, + title: { + text: '' + }, + tickPixelInterval: 40, + showLastLabel: false, + labels: { + align: 'left', + y: -2 + } + }, false, false); + seriesConfig.yAxis = yAxis.options.id; + navigation.resizeYAxes(); + } + else { + seriesConfig.yAxis = chart.get(data.linkedTo).options.yAxis; + } + if (indicatorsWithVolume.indexOf(data.type) >= 0) { + seriesConfig.params.volumeSeriesID = chart.series.filter(function (series) { + return series.options.type === 'column'; + })[0].options.id; + } + chart.addSeries(seriesConfig, false); + } + fireEvent(navigation, 'deselectButton', { + button: navigation.selectedButtonElement + }); + chart.redraw(); +}; +/** + * Update height for an annotation. Height is calculated as a difference + * between last point in `typeOptions` and current position. It's a value, + * not pixels height. + * + * @private + * @function bindingsUtils.updateHeight + * + * @param {Highcharts.PointerEventObject} e + * normalized browser event + * + * @param {Highcharts.Annotation} annotation + * Annotation to be updated + * + * @return {void} + */ +bindingsUtils.updateHeight = function (e, annotation) { + annotation.update({ + typeOptions: { + height: this.chart.pointer.getCoordinates(e).yAxis[0].value - + annotation.options.typeOptions.points[1].y + } + }); +}; +// @todo +// Consider using getHoverData(), but always kdTree (columns?) +bindingsUtils.attractToPoint = function (e, chart) { + var coords = chart.pointer.getCoordinates(e), x = coords.xAxis[0].value, y = coords.yAxis[0].value, distX = Number.MAX_VALUE, closestPoint; + chart.series.forEach(function (series) { + series.points.forEach(function (point) { + if (point && distX > Math.abs(point.x - x)) { + distX = Math.abs(point.x - x); + closestPoint = point; + } + }); + }); + return { + x: closestPoint.x, + y: closestPoint.y, + below: y < closestPoint.y, + series: closestPoint.series, + xAxis: closestPoint.series.xAxis.index || 0, + yAxis: closestPoint.series.yAxis.index || 0 + }; +}; +/** + * Shorthand to check if given yAxis comes from navigator. + * + * @private + * @function bindingsUtils.isNotNavigatorYAxis + * + * @param {Highcharts.Axis} axis + * Axis to check. + * + * @return {boolean} + * True, if axis comes from navigator. + */ +bindingsUtils.isNotNavigatorYAxis = function (axis) { + return axis.userOptions.className !== PREFIX + 'navigator-yaxis'; +}; +/** + * Update each point after specified index, most of the annotations use + * this. For example crooked line: logic behind updating each point is the + * same, only index changes when adding an annotation. + * + * Example: NavigationBindings.utils.updateNthPoint(1) - will generate + * function that updates all consecutive points except point with index=0. + * + * @private + * @function bindingsUtils.updateNthPoint + * + * @param {number} startIndex + * Index from each point should udpated + * + * @return {Function} + * Callback to be used in steps array + */ +bindingsUtils.updateNthPoint = function (startIndex) { + return function (e, annotation) { + var options = annotation.options.typeOptions, coords = this.chart.pointer.getCoordinates(e), x = coords.xAxis[0].value, y = coords.yAxis[0].value; + options.points.forEach(function (point, index) { + if (index >= startIndex) { + point.x = x; + point.y = y; + } + }); + annotation.update({ + typeOptions: { + points: options.points + } + }); + }; +}; +// Extends NavigationBindigs to support indicators and resizers: +extend(NavigationBindings.prototype, { + /* eslint-disable valid-jsdoc */ + /** + * Get current positions for all yAxes. If new axis does not have position, + * returned is default height and last available top place. + * + * @private + * @function Highcharts.NavigationBindings#getYAxisPositions + * + * @param {Array} yAxes + * Array of yAxes available in the chart. + * + * @param {number} plotHeight + * Available height in the chart. + * + * @param {number} defaultHeight + * Default height in percents. + * + * @return {Array} + * An array of calculated positions in percentages. + * Format: `{top: Number, height: Number}` + */ + getYAxisPositions: function (yAxes, plotHeight, defaultHeight) { + var positions, allAxesHeight = 0; + /** @private */ + function isPercentage(prop) { + return defined(prop) && !isNumber(prop) && prop.match('%'); + } + positions = yAxes.map(function (yAxis) { + var height = isPercentage(yAxis.options.height) ? + parseFloat(yAxis.options.height) / 100 : + yAxis.height / plotHeight, top = isPercentage(yAxis.options.top) ? + parseFloat(yAxis.options.top) / 100 : + correctFloat(yAxis.top - yAxis.chart.plotTop) / plotHeight; + // New yAxis does not contain "height" info yet + if (!isNumber(height)) { + height = defaultHeight / 100; + } + allAxesHeight = correctFloat(allAxesHeight + height); + return { + height: height * 100, + top: top * 100 + }; + }); + positions.allAxesHeight = allAxesHeight; + return positions; + }, + /** + * Get current resize options for each yAxis. Note that each resize is + * linked to the next axis, except the last one which shouldn't affect + * axes in the navigator. Because indicator can be removed with it's yAxis + * in the middle of yAxis array, we need to bind closest yAxes back. + * + * @private + * @function Highcharts.NavigationBindings#getYAxisResizers + * + * @param {Array} yAxes + * Array of yAxes available in the chart + * + * @return {Array} + * An array of resizer options. + * Format: `{enabled: Boolean, controlledAxis: { next: [String]}}` + */ + getYAxisResizers: function (yAxes) { + var resizers = []; + yAxes.forEach(function (_yAxis, index) { + var nextYAxis = yAxes[index + 1]; + // We have next axis, bind them: + if (nextYAxis) { + resizers[index] = { + enabled: true, + controlledAxis: { + next: [ + pick(nextYAxis.options.id, nextYAxis.options.index) + ] + } + }; + } + else { + // Remove binding: + resizers[index] = { + enabled: false + }; + } + }); + return resizers; + }, + /** + * Resize all yAxes (except navigator) to fit the plotting height. Method + * checks if new axis is added, then shrinks other main axis up to 5 panes. + * If added is more thatn 5 panes, it rescales all other axes to fit new + * yAxis. + * + * If axis is removed, and we have more than 5 panes, rescales all other + * axes. If chart has less than 5 panes, first pane receives all extra + * space. + * + * @private + * @function Highcharts.NavigationBindings#resizeYAxes + * @param {number} [defaultHeight] + * Default height for yAxis + * @return {void} + */ + resizeYAxes: function (defaultHeight) { + defaultHeight = defaultHeight || 20; // in %, but as a number + var chart = this.chart, + // Only non-navigator axes + yAxes = chart.yAxis.filter(bindingsUtils.isNotNavigatorYAxis), plotHeight = chart.plotHeight, allAxesLength = yAxes.length, + // Gather current heights (in %) + positions = this.getYAxisPositions(yAxes, plotHeight, defaultHeight), resizers = this.getYAxisResizers(yAxes), allAxesHeight = positions.allAxesHeight, changedSpace = defaultHeight; + // More than 100% + if (allAxesHeight > 1) { + // Simple case, add new panes up to 5 + if (allAxesLength < 6) { + // Added axis, decrease first pane's height: + positions[0].height = correctFloat(positions[0].height - changedSpace); + // And update all other "top" positions: + positions = this.recalculateYAxisPositions(positions, changedSpace); + } + else { + // We have more panes, rescale all others to gain some space, + // This is new height for upcoming yAxis: + defaultHeight = 100 / allAxesLength; + // This is how much we need to take from each other yAxis: + changedSpace = defaultHeight / (allAxesLength - 1); + // Now update all positions: + positions = this.recalculateYAxisPositions(positions, changedSpace, true, -1); + } + // Set last position manually: + positions[allAxesLength - 1] = { + top: correctFloat(100 - defaultHeight), + height: defaultHeight + }; + } + else { + // Less than 100% + changedSpace = correctFloat(1 - allAxesHeight) * 100; + // Simple case, return first pane it's space: + if (allAxesLength < 5) { + positions[0].height = correctFloat(positions[0].height + changedSpace); + positions = this.recalculateYAxisPositions(positions, changedSpace); + } + else { + // There were more panes, return to each pane a bit of space: + changedSpace /= allAxesLength; + // Removed axis, add extra space to the first pane: + // And update all other positions: + positions = this.recalculateYAxisPositions(positions, changedSpace, true, 1); + } + } + positions.forEach(function (position, index) { + // if (index === 0) debugger; + yAxes[index].update({ + height: position.height + '%', + top: position.top + '%', + resize: resizers[index] + }, false); + }); + }, + /** + * Utility to modify calculated positions according to the remaining/needed + * space. Later, these positions are used in `yAxis.update({ top, height })` + * + * @private + * @function Highcharts.NavigationBindings#recalculateYAxisPositions + * @param {Array>} positions + * Default positions of all yAxes. + * @param {number} changedSpace + * How much space should be added or removed. + * @param {boolean} modifyHeight + * Update only `top` or both `top` and `height`. + * @param {number} adder + * `-1` or `1`, to determine whether we should add or remove space. + * + * @return {Array} + * Modified positions, + */ + recalculateYAxisPositions: function (positions, changedSpace, modifyHeight, adder) { + positions.forEach(function (position, index) { + var prevPosition = positions[index - 1]; + position.top = !prevPosition ? 0 : + correctFloat(prevPosition.height + prevPosition.top); + if (modifyHeight) { + position.height = correctFloat(position.height + adder * changedSpace); + } + }); + return positions; + } + /* eslint-enable valid-jsdoc */ +}); +/** + * @type {Highcharts.Dictionary} + * @since 7.0.0 + * @optionparent navigation.bindings + */ +var stockToolsBindings = { + // Line type annotations: + /** + * A segment annotation bindings. Includes `start` and one event in `steps` + * array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-segment", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + segment: { + /** @ignore-option */ + className: 'highcharts-segment', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'segment', + type: 'crookedLine', + typeOptions: { + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.segment.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1) + ] + }, + /** + * A segment with an arrow annotation bindings. Includes `start` and one + * event in `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-arrow-segment", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + arrowSegment: { + /** @ignore-option */ + className: 'highcharts-arrow-segment', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'arrowSegment', + type: 'crookedLine', + typeOptions: { + line: { + markerEnd: 'arrow' + }, + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.arrowSegment.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1) + ] + }, + /** + * A ray annotation bindings. Includes `start` and one event in `steps` + * array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-ray", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + ray: { + /** @ignore-option */ + className: 'highcharts-ray', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'ray', + type: 'crookedLine', + typeOptions: { + type: 'ray', + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.ray.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1) + ] + }, + /** + * A ray with an arrow annotation bindings. Includes `start` and one event + * in `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-arrow-ray", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + arrowRay: { + /** @ignore-option */ + className: 'highcharts-arrow-ray', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'arrowRay', + type: 'infinityLine', + typeOptions: { + type: 'ray', + line: { + markerEnd: 'arrow' + }, + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.arrowRay.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1) + ] + }, + /** + * A line annotation. Includes `start` and one event in `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-infinity-line", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + infinityLine: { + /** @ignore-option */ + className: 'highcharts-infinity-line', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'infinityLine', + type: 'infinityLine', + typeOptions: { + type: 'line', + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.infinityLine.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1) + ] + }, + /** + * A line with arrow annotation. Includes `start` and one event in `steps` + * array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-arrow-infinity-line", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + arrowInfinityLine: { + /** @ignore-option */ + className: 'highcharts-arrow-infinity-line', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'arrowInfinityLine', + type: 'infinityLine', + typeOptions: { + type: 'line', + line: { + markerEnd: 'arrow' + }, + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.arrowInfinityLine.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1) + ] + }, + /** + * A horizontal line annotation. Includes `start` event. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-horizontal-line", "start": function() {}, "annotationsOptions": {}} + */ + horizontalLine: { + /** @ignore-option */ + className: 'highcharts-horizontal-line', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'horizontalLine', + type: 'infinityLine', + draggable: 'y', + typeOptions: { + type: 'horizontalLine', + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.horizontalLine.annotationsOptions); + this.chart.addAnnotation(options); + } + }, + /** + * A vertical line annotation. Includes `start` event. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-vertical-line", "start": function() {}, "annotationsOptions": {}} + */ + verticalLine: { + /** @ignore-option */ + className: 'highcharts-vertical-line', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'verticalLine', + type: 'infinityLine', + draggable: 'x', + typeOptions: { + type: 'verticalLine', + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.verticalLine.annotationsOptions); + this.chart.addAnnotation(options); + } + }, + /** + * Crooked line (three points) annotation bindings. Includes `start` and two + * events in `steps` (for second and third points in crooked line) array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-crooked3", "start": function() {}, "steps": [function() {}, function() {}], "annotationsOptions": {}} + */ + // Crooked Line type annotations: + crooked3: { + /** @ignore-option */ + className: 'highcharts-crooked3', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'crooked3', + type: 'crookedLine', + typeOptions: { + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.crooked3.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1), + bindingsUtils.updateNthPoint(2) + ] + }, + /** + * Crooked line (five points) annotation bindings. Includes `start` and four + * events in `steps` (for all consequent points in crooked line) array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-crooked3", "start": function() {}, "steps": [function() {}, function() {}, function() {}, function() {}], "annotationsOptions": {}} + */ + crooked5: { + /** @ignore-option */ + className: 'highcharts-crooked5', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'crookedLine', + type: 'crookedLine', + typeOptions: { + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.crooked5.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1), + bindingsUtils.updateNthPoint(2), + bindingsUtils.updateNthPoint(3), + bindingsUtils.updateNthPoint(4) + ] + }, + /** + * Elliott wave (three points) annotation bindings. Includes `start` and two + * events in `steps` (for second and third points) array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-elliott3", "start": function() {}, "steps": [function() {}, function() {}], "annotationsOptions": {}} + */ + elliott3: { + /** @ignore-option */ + className: 'highcharts-elliott3', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'elliott3', + type: 'elliottWave', + typeOptions: { + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + }, + labelOptions: { + style: { + color: '#666666' + } + } + }, navigation.annotationsOptions, navigation.bindings.elliott3.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1), + bindingsUtils.updateNthPoint(2), + bindingsUtils.updateNthPoint(3) + ] + }, + /** + * Elliott wave (five points) annotation bindings. Includes `start` and four + * event in `steps` (for all consequent points in Elliott wave) array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-elliott3", "start": function() {}, "steps": [function() {}, function() {}, function() {}, function() {}], "annotationsOptions": {}} + */ + elliott5: { + /** @ignore-option */ + className: 'highcharts-elliott5', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'elliott5', + type: 'elliottWave', + typeOptions: { + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + }, + labelOptions: { + style: { + color: '#666666' + } + } + }, navigation.annotationsOptions, navigation.bindings.elliott5.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1), + bindingsUtils.updateNthPoint(2), + bindingsUtils.updateNthPoint(3), + bindingsUtils.updateNthPoint(4), + bindingsUtils.updateNthPoint(5) + ] + }, + /** + * A measure (x-dimension) annotation bindings. Includes `start` and one + * event in `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-measure-x", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + measureX: { + /** @ignore-option */ + className: 'highcharts-measure-x', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'measure', + type: 'measure', + typeOptions: { + selectType: 'x', + point: { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value, + xAxis: 0, + yAxis: 0 + }, + crosshairX: { + strokeWidth: 1, + stroke: '#000000' + }, + crosshairY: { + enabled: false, + strokeWidth: 0, + stroke: '#000000' + }, + background: { + width: 0, + height: 0, + strokeWidth: 0, + stroke: '#ffffff' + } + }, + labelOptions: { + style: { + color: '#666666' + } + } + }, navigation.annotationsOptions, navigation.bindings.measureX.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateRectSize + ] + }, + /** + * A measure (y-dimension) annotation bindings. Includes `start` and one + * event in `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-measure-y", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + measureY: { + /** @ignore-option */ + className: 'highcharts-measure-y', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'measure', + type: 'measure', + typeOptions: { + selectType: 'y', + point: { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value, + xAxis: 0, + yAxis: 0 + }, + crosshairX: { + enabled: false, + strokeWidth: 0, + stroke: '#000000' + }, + crosshairY: { + strokeWidth: 1, + stroke: '#000000' + }, + background: { + width: 0, + height: 0, + strokeWidth: 0, + stroke: '#ffffff' + } + }, + labelOptions: { + style: { + color: '#666666' + } + } + }, navigation.annotationsOptions, navigation.bindings.measureY.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateRectSize + ] + }, + /** + * A measure (xy-dimension) annotation bindings. Includes `start` and one + * event in `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-measure-xy", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + measureXY: { + /** @ignore-option */ + className: 'highcharts-measure-xy', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'measure', + type: 'measure', + typeOptions: { + selectType: 'xy', + point: { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value, + xAxis: 0, + yAxis: 0 + }, + background: { + width: 0, + height: 0, + strokeWidth: 10 + }, + crosshairX: { + strokeWidth: 1, + stroke: '#000000' + }, + crosshairY: { + strokeWidth: 1, + stroke: '#000000' + } + }, + labelOptions: { + style: { + color: '#666666' + } + } + }, navigation.annotationsOptions, navigation.bindings.measureXY.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateRectSize + ] + }, + // Advanced type annotations: + /** + * A fibonacci annotation bindings. Includes `start` and two events in + * `steps` array (updates second point, then height). + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-fibonacci", "start": function() {}, "steps": [function() {}, function() {}], "annotationsOptions": {}} + */ + fibonacci: { + /** @ignore-option */ + className: 'highcharts-fibonacci', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'fibonacci', + type: 'fibonacci', + typeOptions: { + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + }, + labelOptions: { + style: { + color: '#666666' + } + } + }, navigation.annotationsOptions, navigation.bindings.fibonacci.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1), + bindingsUtils.updateHeight + ] + }, + /** + * A parallel channel (tunnel) annotation bindings. Includes `start` and + * two events in `steps` array (updates second point, then height). + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-parallel-channel", "start": function() {}, "steps": [function() {}, function() {}], "annotationsOptions": {}} + */ + parallelChannel: { + /** @ignore-option */ + className: 'highcharts-parallel-channel', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'parallelChannel', + type: 'tunnel', + typeOptions: { + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.parallelChannel.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1), + bindingsUtils.updateHeight + ] + }, + /** + * An Andrew's pitchfork annotation bindings. Includes `start` and two + * events in `steps` array (sets second and third control points). + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-pitchfork", "start": function() {}, "steps": [function() {}, function() {}], "annotationsOptions": {}} + */ + pitchfork: { + /** @ignore-option */ + className: 'highcharts-pitchfork', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'pitchfork', + type: 'pitchfork', + typeOptions: { + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value, + controlPoint: { + style: { + fill: 'red' + } + } + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }], + innerBackground: { + fill: 'rgba(100, 170, 255, 0.8)' + } + }, + shapeOptions: { + strokeWidth: 2 + } + }, navigation.annotationsOptions, navigation.bindings.pitchfork.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1), + bindingsUtils.updateNthPoint(2) + ] + }, + // Labels with arrow and auto increments + /** + * A vertical counter annotation bindings. Includes `start` event. On click, + * finds the closest point and marks it with a numeric annotation - + * incrementing counter on each add. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-vertical-counter", "start": function() {}, "annotationsOptions": {}} + */ + verticalCounter: { + /** @ignore-option */ + className: 'highcharts-vertical-counter', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var closestPoint = bindingsUtils.attractToPoint(e, this.chart), navigation = this.chart.options.navigation, verticalCounter = !defined(this.verticalCounter) ? 0 : + this.verticalCounter, options = merge({ + langKey: 'verticalCounter', + type: 'verticalLine', + typeOptions: { + point: { + x: closestPoint.x, + y: closestPoint.y, + xAxis: closestPoint.xAxis, + yAxis: closestPoint.yAxis + }, + label: { + offset: closestPoint.below ? 40 : -40, + text: verticalCounter.toString() + } + }, + labelOptions: { + style: { + color: '#666666', + fontSize: '11px' + } + }, + shapeOptions: { + stroke: 'rgba(0, 0, 0, 0.75)', + strokeWidth: 1 + } + }, navigation.annotationsOptions, navigation.bindings.verticalCounter.annotationsOptions), annotation; + annotation = this.chart.addAnnotation(options); + verticalCounter++; + annotation.options.events.click.call(annotation, {}); + } + }, + /** + * A vertical arrow annotation bindings. Includes `start` event. On click, + * finds the closest point and marks it with an arrow and a label with + * value. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-vertical-label", "start": function() {}, "annotationsOptions": {}} + */ + verticalLabel: { + /** @ignore-option */ + className: 'highcharts-vertical-label', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var closestPoint = bindingsUtils.attractToPoint(e, this.chart), navigation = this.chart.options.navigation, options = merge({ + langKey: 'verticalLabel', + type: 'verticalLine', + typeOptions: { + point: { + x: closestPoint.x, + y: closestPoint.y, + xAxis: closestPoint.xAxis, + yAxis: closestPoint.yAxis + }, + label: { + offset: closestPoint.below ? 40 : -40 + } + }, + labelOptions: { + style: { + color: '#666666', + fontSize: '11px' + } + }, + shapeOptions: { + stroke: 'rgba(0, 0, 0, 0.75)', + strokeWidth: 1 + } + }, navigation.annotationsOptions, navigation.bindings.verticalLabel.annotationsOptions), annotation; + annotation = this.chart.addAnnotation(options); + annotation.options.events.click.call(annotation, {}); + } + }, + /** + * A vertical arrow annotation bindings. Includes `start` event. On click, + * finds the closest point and marks it with an arrow. Green arrow when + * pointing from above, red when pointing from below the point. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-vertical-arrow", "start": function() {}, "annotationsOptions": {}} + */ + verticalArrow: { + /** @ignore-option */ + className: 'highcharts-vertical-arrow', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var closestPoint = bindingsUtils.attractToPoint(e, this.chart), navigation = this.chart.options.navigation, options = merge({ + langKey: 'verticalArrow', + type: 'verticalLine', + typeOptions: { + point: { + x: closestPoint.x, + y: closestPoint.y, + xAxis: closestPoint.xAxis, + yAxis: closestPoint.yAxis + }, + label: { + offset: closestPoint.below ? 40 : -40, + format: ' ' + }, + connector: { + fill: 'none', + stroke: closestPoint.below ? 'red' : 'green' + } + }, + shapeOptions: { + stroke: 'rgba(0, 0, 0, 0.75)', + strokeWidth: 1 + } + }, navigation.annotationsOptions, navigation.bindings.verticalArrow.annotationsOptions), annotation; + annotation = this.chart.addAnnotation(options); + annotation.options.events.click.call(annotation, {}); + } + }, + // Flag types: + /** + * A flag series bindings. Includes `start` event. On click, finds the + * closest point and marks it with a flag with `'circlepin'` shape. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-flag-circlepin", "start": function() {}} + */ + flagCirclepin: { + /** @ignore-option */ + className: 'highcharts-flag-circlepin', + /** @ignore-option */ + start: bindingsUtils.addFlagFromForm('circlepin') + }, + /** + * A flag series bindings. Includes `start` event. On click, finds the + * closest point and marks it with a flag with `'diamondpin'` shape. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-flag-diamondpin", "start": function() {}} + */ + flagDiamondpin: { + /** @ignore-option */ + className: 'highcharts-flag-diamondpin', + /** @ignore-option */ + start: bindingsUtils.addFlagFromForm('flag') + }, + /** + * A flag series bindings. Includes `start` event. + * On click, finds the closest point and marks it with a flag with + * `'squarepin'` shape. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-flag-squarepin", "start": function() {}} + */ + flagSquarepin: { + /** @ignore-option */ + className: 'highcharts-flag-squarepin', + /** @ignore-option */ + start: bindingsUtils.addFlagFromForm('squarepin') + }, + /** + * A flag series bindings. Includes `start` event. + * On click, finds the closest point and marks it with a flag without pin + * shape. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-flag-simplepin", "start": function() {}} + */ + flagSimplepin: { + /** @ignore-option */ + className: 'highcharts-flag-simplepin', + /** @ignore-option */ + start: bindingsUtils.addFlagFromForm('nopin') + }, + // Other tools: + /** + * Enables zooming in xAxis on a chart. Includes `start` event which + * changes [chart.zoomType](#chart.zoomType). + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-zoom-x", "init": function() {}} + */ + zoomX: { + /** @ignore-option */ + className: 'highcharts-zoom-x', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function (button) { + this.chart.update({ + chart: { + zoomType: 'x' + } + }); + fireEvent(this, 'deselectButton', { button: button }); + } + }, + /** + * Enables zooming in yAxis on a chart. Includes `start` event which + * changes [chart.zoomType](#chart.zoomType). + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-zoom-y", "init": function() {}} + */ + zoomY: { + /** @ignore-option */ + className: 'highcharts-zoom-y', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function (button) { + this.chart.update({ + chart: { + zoomType: 'y' + } + }); + fireEvent(this, 'deselectButton', { button: button }); + } + }, + /** + * Enables zooming in xAxis and yAxis on a chart. Includes `start` event + * which changes [chart.zoomType](#chart.zoomType). + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-zoom-xy", "init": function() {}} + */ + zoomXY: { + /** @ignore-option */ + className: 'highcharts-zoom-xy', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function (button) { + this.chart.update({ + chart: { + zoomType: 'xy' + } + }); + fireEvent(this, 'deselectButton', { button: button }); + } + }, + /** + * Changes main series to `'line'` type. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-series-type-line", "init": function() {}} + */ + seriesTypeLine: { + /** @ignore-option */ + className: 'highcharts-series-type-line', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function (button) { + this.chart.series[0].update({ + type: 'line', + useOhlcData: true + }); + fireEvent(this, 'deselectButton', { button: button }); + } + }, + /** + * Changes main series to `'ohlc'` type. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-series-type-ohlc", "init": function() {}} + */ + seriesTypeOhlc: { + /** @ignore-option */ + className: 'highcharts-series-type-ohlc', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function (button) { + this.chart.series[0].update({ + type: 'ohlc' + }); + fireEvent(this, 'deselectButton', { button: button }); + } + }, + /** + * Changes main series to `'candlestick'` type. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-series-type-candlestick", "init": function() {}} + */ + seriesTypeCandlestick: { + /** @ignore-option */ + className: 'highcharts-series-type-candlestick', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function (button) { + this.chart.series[0].update({ + type: 'candlestick' + }); + fireEvent(this, 'deselectButton', { button: button }); + } + }, + /** + * Displays chart in fullscreen. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-full-screen", "init": function() {}} + */ + fullScreen: { + /** @ignore-option */ + className: 'highcharts-full-screen', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function (button) { + this.chart.fullscreen.toggle(); + fireEvent(this, 'deselectButton', { button: button }); + } + }, + /** + * Hides/shows two price indicators: + * - last price in the dataset + * - last price in the selected range + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-current-price-indicator", "init": function() {}} + */ + currentPriceIndicator: { + /** @ignore-option */ + className: 'highcharts-current-price-indicator', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function (button) { + var chart = this.chart, series = chart.series[0], options = series.options, lastVisiblePrice = (options.lastVisiblePrice && + options.lastVisiblePrice.enabled), lastPrice = options.lastPrice && options.lastPrice.enabled, gui = chart.stockTools, iconsURL = gui.getIconsURL(); + if (gui && gui.guiEnabled) { + if (lastPrice) { + button.firstChild.style['background-image'] = + 'url("' + iconsURL + + 'current-price-show.svg")'; + } + else { + button.firstChild.style['background-image'] = + 'url("' + iconsURL + + 'current-price-hide.svg")'; + } + } + series.update({ + // line + lastPrice: { + enabled: !lastPrice, + color: 'red' + }, + // label + lastVisiblePrice: { + enabled: !lastVisiblePrice, + label: { + enabled: true + } + } + }); + fireEvent(this, 'deselectButton', { button: button }); + } + }, + /** + * Indicators bindings. Includes `init` event to show a popup. + * + * Note: In order to show base series from the chart in the popup's + * dropdown each series requires + * [series.id](https://api.highcharts.com/highstock/series.line.id) to be + * defined. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-indicators", "init": function() {}} + */ + indicators: { + /** @ignore-option */ + className: 'highcharts-indicators', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function () { + var navigation = this; + fireEvent(navigation, 'showPopup', { + formType: 'indicators', + options: {}, + // Callback on submit: + onSubmit: function (data) { + navigation.utils.manageIndicators.call(navigation, data); + } + }); + } + }, + /** + * Hides/shows all annotations on a chart. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-toggle-annotations", "init": function() {}} + */ + toggleAnnotations: { + /** @ignore-option */ + className: 'highcharts-toggle-annotations', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function (button) { + var chart = this.chart, gui = chart.stockTools, iconsURL = gui.getIconsURL(); + this.toggledAnnotations = !this.toggledAnnotations; + (chart.annotations || []).forEach(function (annotation) { + annotation.setVisibility(!this.toggledAnnotations); + }, this); + if (gui && gui.guiEnabled) { + if (this.toggledAnnotations) { + button.firstChild.style['background-image'] = + 'url("' + iconsURL + + 'annotations-hidden.svg")'; + } + else { + button.firstChild.style['background-image'] = + 'url("' + iconsURL + + 'annotations-visible.svg")'; + } + } + fireEvent(this, 'deselectButton', { button: button }); + } + }, + /** + * Save a chart in localStorage under `highcharts-chart` key. + * Stored items: + * - annotations + * - indicators (with yAxes) + * - flags + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-save-chart", "init": function() {}} + */ + saveChart: { + /** @ignore-option */ + className: 'highcharts-save-chart', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function (button) { + var navigation = this, chart = navigation.chart, annotations = [], indicators = [], flags = [], yAxes = []; + chart.annotations.forEach(function (annotation, index) { + annotations[index] = annotation.userOptions; + }); + chart.series.forEach(function (series) { + if (series.is('sma')) { + indicators.push(series.userOptions); + } + else if (series.type === 'flags') { + flags.push(series.userOptions); + } + }); + chart.yAxis.forEach(function (yAxis) { + if (bindingsUtils.isNotNavigatorYAxis(yAxis)) { + yAxes.push(yAxis.options); + } + }); + H.win.localStorage.setItem(PREFIX + 'chart', JSON.stringify({ + annotations: annotations, + indicators: indicators, + flags: flags, + yAxes: yAxes + })); + fireEvent(this, 'deselectButton', { button: button }); + } + } +}; +H.setOptions({ + navigation: { + bindings: stockToolsBindings + } +}); +NavigationBindings.prototype.utils = merge(bindingsUtils, NavigationBindings.prototype.utils); diff --git a/librerias/gantt/code/es-modules/modules/stock-tools-gui.js b/librerias/gantt/code/es-modules/modules/stock-tools-gui.js new file mode 100644 index 0000000..3083f5a --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/stock-tools-gui.js @@ -0,0 +1,1291 @@ +/* * + * + * GUI generator for Stock tools + * + * (c) 2009-2017 Sebastian Bochan + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +import NavigationBindings from '../annotations/navigationBindings.js'; +var addEvent = U.addEvent, createElement = U.createElement, css = U.css, extend = U.extend, fireEvent = U.fireEvent, getStyle = U.getStyle, isArray = U.isArray, merge = U.merge, pick = U.pick; +var win = H.win, DIV = 'div', SPAN = 'span', UL = 'ul', LI = 'li', PREFIX = 'highcharts-', activeClass = PREFIX + 'active'; +H.setOptions({ + /** + * @optionparent lang + */ + lang: { + /** + * Configure the stockTools GUI titles(hints) in the chart. Requires + * the `stock-tools.js` module to be loaded. + * + * @product highstock + * @since 7.0.0 + */ + stockTools: { + gui: { + // Main buttons: + simpleShapes: 'Simple shapes', + lines: 'Lines', + crookedLines: 'Crooked lines', + measure: 'Measure', + advanced: 'Advanced', + toggleAnnotations: 'Toggle annotations', + verticalLabels: 'Vertical labels', + flags: 'Flags', + zoomChange: 'Zoom change', + typeChange: 'Type change', + saveChart: 'Save chart', + indicators: 'Indicators', + currentPriceIndicator: 'Current Price Indicators', + // Other features: + zoomX: 'Zoom X', + zoomY: 'Zoom Y', + zoomXY: 'Zooom XY', + fullScreen: 'Fullscreen', + typeOHLC: 'OHLC', + typeLine: 'Line', + typeCandlestick: 'Candlestick', + // Basic shapes: + circle: 'Circle', + label: 'Label', + rectangle: 'Rectangle', + // Flags: + flagCirclepin: 'Flag circle', + flagDiamondpin: 'Flag diamond', + flagSquarepin: 'Flag square', + flagSimplepin: 'Flag simple', + // Measures: + measureXY: 'Measure XY', + measureX: 'Measure X', + measureY: 'Measure Y', + // Segment, ray and line: + segment: 'Segment', + arrowSegment: 'Arrow segment', + ray: 'Ray', + arrowRay: 'Arrow ray', + line: 'Line', + arrowLine: 'Arrow line', + horizontalLine: 'Horizontal line', + verticalLine: 'Vertical line', + infinityLine: 'Infinity line', + // Crooked lines: + crooked3: 'Crooked 3 line', + crooked5: 'Crooked 5 line', + elliott3: 'Elliott 3 line', + elliott5: 'Elliott 5 line', + // Counters: + verticalCounter: 'Vertical counter', + verticalLabel: 'Vertical label', + verticalArrow: 'Vertical arrow', + // Advanced: + fibonacci: 'Fibonacci', + pitchfork: 'Pitchfork', + parallelChannel: 'Parallel channel' + } + }, + navigation: { + popup: { + // Annotations: + circle: 'Circle', + rectangle: 'Rectangle', + label: 'Label', + segment: 'Segment', + arrowSegment: 'Arrow segment', + ray: 'Ray', + arrowRay: 'Arrow ray', + line: 'Line', + arrowLine: 'Arrow line', + horizontalLine: 'Horizontal line', + verticalLine: 'Vertical line', + crooked3: 'Crooked 3 line', + crooked5: 'Crooked 5 line', + elliott3: 'Elliott 3 line', + elliott5: 'Elliott 5 line', + verticalCounter: 'Vertical counter', + verticalLabel: 'Vertical label', + verticalArrow: 'Vertical arrow', + fibonacci: 'Fibonacci', + pitchfork: 'Pitchfork', + parallelChannel: 'Parallel channel', + infinityLine: 'Infinity line', + measure: 'Measure', + measureXY: 'Measure XY', + measureX: 'Measure X', + measureY: 'Measure Y', + // Flags: + flags: 'Flags', + // GUI elements: + addButton: 'add', + saveButton: 'save', + editButton: 'edit', + removeButton: 'remove', + series: 'Series', + volume: 'Volume', + connector: 'Connector', + // Field names: + innerBackground: 'Inner background', + outerBackground: 'Outer background', + crosshairX: 'Crosshair X', + crosshairY: 'Crosshair Y', + tunnel: 'Tunnel', + background: 'Background' + } + } + }, + /** + * Configure the stockTools gui strings in the chart. Requires the + * [stockTools module]() to be loaded. For a description of the module + * and information on its features, see [Highcharts StockTools](). + * + * @product highstock + * + * @sample stock/demo/stock-tools-gui Stock Tools GUI + * + * @sample stock/demo/stock-tools-custom-gui Stock Tools customized GUI + * + * @since 7.0.0 + * @optionparent stockTools + */ + stockTools: { + /** + * Definitions of buttons in Stock Tools GUI. + */ + gui: { + /** + * Path where Highcharts will look for icons. Change this to use + * icons from a different server. + * + * Since 7.1.3 use [iconsURL](#navigation.iconsURL) for popup and + * stock tools. + * + * @deprecated + * @apioption stockTools.gui.iconsURL + * + */ + /** + * Enable or disable the stockTools gui. + */ + enabled: true, + /** + * A CSS class name to apply to the stocktools' div, + * allowing unique CSS styling for each chart. + */ + className: 'highcharts-bindings-wrapper', + /** + * A CSS class name to apply to the container of buttons, + * allowing unique CSS styling for each chart. + */ + toolbarClassName: 'stocktools-toolbar', + /** + * A collection of strings pointing to config options for the + * toolbar items. Each name refers to unique key from definitions + * object. + * + * @default [ + * 'indicators', + * 'separator', + * 'simpleShapes', + * 'lines', + * 'crookedLines', + * 'measure', + * 'advanced', + * 'toggleAnnotations', + * 'separator', + * 'verticalLabels', + * 'flags', + * 'separator', + * 'zoomChange', + * 'fullScreen', + * 'typeChange', + * 'separator', + * 'currentPriceIndicator', + * 'saveChart' + * ] + */ + buttons: [ + 'indicators', + 'separator', + 'simpleShapes', + 'lines', + 'crookedLines', + 'measure', + 'advanced', + 'toggleAnnotations', + 'separator', + 'verticalLabels', + 'flags', + 'separator', + 'zoomChange', + 'fullScreen', + 'typeChange', + 'separator', + 'currentPriceIndicator', + 'saveChart' + ], + /** + * An options object of the buttons definitions. Each name refers to + * unique key from buttons array. + */ + definitions: { + separator: { + /** + * A predefined background symbol for the button. + */ + symbol: 'separator.svg' + }, + simpleShapes: { + /** + * A collection of strings pointing to config options for + * the items. + * + * @type {array} + * @default [ + * 'label', + * 'circle', + * 'rectangle' + * ] + * + */ + items: [ + 'label', + 'circle', + 'rectangle' + ], + circle: { + /** + * A predefined background symbol for the button. + * + * @type {string} + * + */ + symbol: 'circle.svg' + }, + rectangle: { + /** + * A predefined background symbol for the button. + * + * @type {string} + * + */ + symbol: 'rectangle.svg' + }, + label: { + /** + * A predefined background symbol for the button. + * + * @type {string} + * + */ + symbol: 'label.svg' + } + }, + flags: { + /** + * A collection of strings pointing to config options for + * the items. + * + * @type {array} + * @default [ + * 'flagCirclepin', + * 'flagDiamondpin', + * 'flagSquarepin', + * 'flagSimplepin' + * ] + * + */ + items: [ + 'flagCirclepin', + 'flagDiamondpin', + 'flagSquarepin', + 'flagSimplepin' + ], + flagSimplepin: { + /** + * A predefined background symbol for the button. + * + * @type {string} + * + */ + symbol: 'flag-basic.svg' + }, + flagDiamondpin: { + /** + * A predefined background symbol for the button. + * + * @type {string} + * + */ + symbol: 'flag-diamond.svg' + }, + flagSquarepin: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'flag-trapeze.svg' + }, + flagCirclepin: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'flag-elipse.svg' + } + }, + lines: { + /** + * A collection of strings pointing to config options for + * the items. + * + * @type {array} + * @default [ + * 'segment', + * 'arrowSegment', + * 'ray', + * 'arrowRay', + * 'line', + * 'arrowLine', + * 'horizontalLine', + * 'verticalLine' + * ] + */ + items: [ + 'segment', + 'arrowSegment', + 'ray', + 'arrowRay', + 'line', + 'arrowLine', + 'horizontalLine', + 'verticalLine' + ], + segment: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'segment.svg' + }, + arrowSegment: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'arrow-segment.svg' + }, + ray: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'ray.svg' + }, + arrowRay: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'arrow-ray.svg' + }, + line: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'line.svg' + }, + arrowLine: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'arrow-line.svg' + }, + verticalLine: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'vertical-line.svg' + }, + horizontalLine: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'horizontal-line.svg' + } + }, + crookedLines: { + /** + * A collection of strings pointing to config options for + * the items. + * + * @type {array} + * @default [ + * 'elliott3', + * 'elliott5', + * 'crooked3', + * 'crooked5' + * ] + * + */ + items: [ + 'elliott3', + 'elliott5', + 'crooked3', + 'crooked5' + ], + crooked3: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'crooked-3.svg' + }, + crooked5: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'crooked-5.svg' + }, + elliott3: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'elliott-3.svg' + }, + elliott5: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'elliott-5.svg' + } + }, + verticalLabels: { + /** + * A collection of strings pointing to config options for + * the items. + * + * @type {array} + * @default [ + * 'verticalCounter', + * 'verticalLabel', + * 'verticalArrow' + * ] + */ + items: [ + 'verticalCounter', + 'verticalLabel', + 'verticalArrow' + ], + verticalCounter: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'vertical-counter.svg' + }, + verticalLabel: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'vertical-label.svg' + }, + verticalArrow: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'vertical-arrow.svg' + } + }, + advanced: { + /** + * A collection of strings pointing to config options for + * the items. + * + * @type {array} + * @default [ + * 'fibonacci', + * 'pitchfork', + * 'parallelChannel' + * ] + */ + items: [ + 'fibonacci', + 'pitchfork', + 'parallelChannel' + ], + pitchfork: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'pitchfork.svg' + }, + fibonacci: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'fibonacci.svg' + }, + parallelChannel: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'parallel-channel.svg' + } + }, + measure: { + /** + * A collection of strings pointing to config options for + * the items. + * + * @type {array} + * @default [ + * 'measureXY', + * 'measureX', + * 'measureY' + * ] + */ + items: [ + 'measureXY', + 'measureX', + 'measureY' + ], + measureX: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'measure-x.svg' + }, + measureY: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'measure-y.svg' + }, + measureXY: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'measure-xy.svg' + } + }, + toggleAnnotations: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'annotations-visible.svg' + }, + currentPriceIndicator: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'current-price-show.svg' + }, + indicators: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'indicators.svg' + }, + zoomChange: { + /** + * A collection of strings pointing to config options for + * the items. + * + * @type {array} + * @default [ + * 'zoomX', + * 'zoomY', + * 'zoomXY' + * ] + */ + items: [ + 'zoomX', + 'zoomY', + 'zoomXY' + ], + zoomX: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'zoom-x.svg' + }, + zoomY: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'zoom-y.svg' + }, + zoomXY: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'zoom-xy.svg' + } + }, + typeChange: { + /** + * A collection of strings pointing to config options for + * the items. + * + * @type {array} + * @default [ + * 'typeOHLC', + * 'typeLine', + * 'typeCandlestick' + * ] + */ + items: [ + 'typeOHLC', + 'typeLine', + 'typeCandlestick' + ], + typeOHLC: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'series-ohlc.svg' + }, + typeLine: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'series-line.svg' + }, + typeCandlestick: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'series-candlestick.svg' + } + }, + fullScreen: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'fullscreen.svg' + }, + saveChart: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'save-chart.svg' + } + } + } + } +}); +/* eslint-disable no-invalid-this, valid-jsdoc */ +// Run HTML generator +addEvent(H.Chart, 'afterGetContainer', function () { + this.setStockTools(); +}); +addEvent(H.Chart, 'getMargins', function () { + var listWrapper = this.stockTools && this.stockTools.listWrapper, offsetWidth = listWrapper && ((listWrapper.startWidth + + getStyle(listWrapper, 'padding-left') + + getStyle(listWrapper, 'padding-right')) || listWrapper.offsetWidth); + if (offsetWidth && offsetWidth < this.plotWidth) { + this.plotLeft += offsetWidth; + } +}); +addEvent(H.Chart, 'destroy', function () { + if (this.stockTools) { + this.stockTools.destroy(); + } +}); +addEvent(H.Chart, 'redraw', function () { + if (this.stockTools && this.stockTools.guiEnabled) { + this.stockTools.redraw(); + } +}); +/** + * Toolbar Class + * @private + * @constructor + * @param {Object} - options of toolbar + * @param {Chart} - Reference to chart + */ +var Toolbar = /** @class */ (function () { + function Toolbar(options, langOptions, chart) { + this.arrowDown = void 0; + this.arrowUp = void 0; + this.arrowWrapper = void 0; + this.listWrapper = void 0; + this.showhideBtn = void 0; + this.submenu = void 0; + this.toolbar = void 0; + this.wrapper = void 0; + this.chart = chart; + this.options = options; + this.lang = langOptions; + // set url for icons. + this.iconsURL = this.getIconsURL(); + this.guiEnabled = options.enabled; + this.visible = pick(options.visible, true); + this.placed = pick(options.placed, false); + // General events collection which should be removed upon + // destroy/update: + this.eventsToUnbind = []; + if (this.guiEnabled) { + this.createHTML(); + this.init(); + this.showHideNavigatorion(); + } + fireEvent(this, 'afterInit'); + } + /** + * Initialize the toolbar. Create buttons and submenu for each option + * defined in `stockTools.gui`. + * @private + */ + Toolbar.prototype.init = function () { + var _self = this, lang = this.lang, guiOptions = this.options, toolbar = this.toolbar, addSubmenu = _self.addSubmenu, buttons = guiOptions.buttons, defs = guiOptions.definitions, allButtons = toolbar.childNodes, button; + // create buttons + buttons.forEach(function (btnName) { + button = _self.addButton(toolbar, defs, btnName, lang); + _self.eventsToUnbind.push(addEvent(button.buttonWrapper, 'click', function () { + _self.eraseActiveButtons(allButtons, button.buttonWrapper); + })); + if (isArray(defs[btnName].items)) { + // create submenu buttons + addSubmenu.call(_self, button, defs[btnName]); + } + }); + }; + /** + * Create submenu (list of buttons) for the option. In example main button + * is Line, in submenu will be buttons with types of lines. + * @private + * @param {Highcharts.Dictionary} + * button which has submenu + * @param {Highcharts.StockToolsGuiDefinitionsButtonsOptions} + * list of all buttons + */ + Toolbar.prototype.addSubmenu = function (parentBtn, button) { + var _self = this, submenuArrow = parentBtn.submenuArrow, buttonWrapper = parentBtn.buttonWrapper, buttonWidth = getStyle(buttonWrapper, 'width'), wrapper = this.wrapper, menuWrapper = this.listWrapper, allButtons = this.toolbar.childNodes, topMargin = 0, submenuWrapper; + // create submenu container + this.submenu = submenuWrapper = createElement(UL, { + className: PREFIX + 'submenu-wrapper' + }, null, buttonWrapper); + // create submenu buttons and select the first one + this.addSubmenuItems(buttonWrapper, button); + // show / hide submenu + _self.eventsToUnbind.push(addEvent(submenuArrow, 'click', function (e) { + e.stopPropagation(); + // Erase active class on all other buttons + _self.eraseActiveButtons(allButtons, buttonWrapper); + // hide menu + if (buttonWrapper.className.indexOf(PREFIX + 'current') >= 0) { + menuWrapper.style.width = + menuWrapper.startWidth + 'px'; + buttonWrapper.classList.remove(PREFIX + 'current'); + submenuWrapper.style.display = 'none'; + } + else { + // show menu + // to calculate height of element + submenuWrapper.style.display = 'block'; + topMargin = submenuWrapper.offsetHeight - + buttonWrapper.offsetHeight - 3; + // calculate position of submenu in the box + // if submenu is inside, reset top margin + if ( + // cut on the bottom + !(submenuWrapper.offsetHeight + + buttonWrapper.offsetTop > + wrapper.offsetHeight && + // cut on the top + buttonWrapper.offsetTop > topMargin)) { + topMargin = 0; + } + // apply calculated styles + css(submenuWrapper, { + top: -topMargin + 'px', + left: buttonWidth + 3 + 'px' + }); + buttonWrapper.className += ' ' + PREFIX + 'current'; + menuWrapper.startWidth = wrapper.offsetWidth; + menuWrapper.style.width = menuWrapper.startWidth + + getStyle(menuWrapper, 'padding-left') + + submenuWrapper.offsetWidth + 3 + 'px'; + } + })); + }; + /** + * Create buttons in submenu + * @private + * @param {Highcharts.HTMLDOMElement} + * button where submenu is placed + * @param {Highcharts.StockToolsGuiDefinitionsButtonsOptions} + * list of all buttons options + * + */ + Toolbar.prototype.addSubmenuItems = function (buttonWrapper, button) { + var _self = this, submenuWrapper = this.submenu, lang = this.lang, menuWrapper = this.listWrapper, items = button.items, firstSubmenuItem, submenuBtn; + // add items to submenu + items.forEach(function (btnName) { + // add buttons to submenu + submenuBtn = _self.addButton(submenuWrapper, button, btnName, lang); + _self.eventsToUnbind.push(addEvent(submenuBtn.mainButton, 'click', function () { + _self.switchSymbol(this, buttonWrapper, true); + menuWrapper.style.width = + menuWrapper.startWidth + 'px'; + submenuWrapper.style.display = 'none'; + })); + }); + // select first submenu item + firstSubmenuItem = submenuWrapper + .querySelectorAll('li > .' + PREFIX + 'menu-item-btn')[0]; + // replace current symbol, in main button, with submenu's button style + _self.switchSymbol(firstSubmenuItem, false); + }; + /* + * Erase active class on all other buttons. + * + * @param {Array} - Array of HTML buttons + * @param {HTMLDOMElement} - Current HTML button + * + */ + Toolbar.prototype.eraseActiveButtons = function (buttons, currentButton, submenuItems) { + [].forEach.call(buttons, function (btn) { + if (btn !== currentButton) { + btn.classList.remove(PREFIX + 'current'); + btn.classList.remove(PREFIX + 'active'); + submenuItems = + btn.querySelectorAll('.' + PREFIX + 'submenu-wrapper'); + // hide submenu + if (submenuItems.length > 0) { + submenuItems[0].style.display = 'none'; + } + } + }); + }; + /** + * Create single button. Consist of HTML elements `li`, `span`, and (if + * exists) submenu container. + * @private + * @param {Highcharts.HTMLDOMElement} target + * HTML reference, where button should be added + * @param {Highcharts.StockToolsGuiDefinitionsButtonsOptions|Highcharts.StockToolsGuiDefinitionsOptions} options + * All options, by btnName refer to particular button + * @param {string} btnName + * of functionality mapped for specific class + * @param {Highcharts.Dictionary} lang + * All titles, by btnName refer to particular button + * @return {Object} - references to all created HTML elements + */ + Toolbar.prototype.addButton = function (target, options, btnName, lang) { + if (lang === void 0) { lang = {}; } + var btnOptions = options[btnName], items = btnOptions.items, classMapping = Toolbar.prototype.classMapping, userClassName = btnOptions.className || '', mainButton, submenuArrow, buttonWrapper; + // main button wrapper + buttonWrapper = createElement(LI, { + className: pick(classMapping[btnName], '') + ' ' + userClassName, + title: lang[btnName] || btnName + }, null, target); + // single button + mainButton = createElement(SPAN, { + className: PREFIX + 'menu-item-btn' + }, null, buttonWrapper); + // submenu + if (items && items.length) { + // arrow is a hook to show / hide submenu + submenuArrow = createElement(SPAN, { + className: PREFIX + 'submenu-item-arrow ' + + PREFIX + 'arrow-right' + }, null, buttonWrapper); + submenuArrow.style['background-image'] = 'url(' + + this.iconsURL + 'arrow-bottom.svg)'; + } + else { + mainButton.style['background-image'] = 'url(' + + this.iconsURL + btnOptions.symbol + ')'; + } + return { + buttonWrapper: buttonWrapper, + mainButton: mainButton, + submenuArrow: submenuArrow + }; + }; + /* + * Create navigation's HTML elements: container and arrows. + * + */ + Toolbar.prototype.addNavigation = function () { + var stockToolbar = this, wrapper = stockToolbar.wrapper; + // arrow wrapper + stockToolbar.arrowWrapper = createElement(DIV, { + className: PREFIX + 'arrow-wrapper' + }); + stockToolbar.arrowUp = createElement(DIV, { + className: PREFIX + 'arrow-up' + }, null, stockToolbar.arrowWrapper); + stockToolbar.arrowUp.style['background-image'] = + 'url(' + this.iconsURL + 'arrow-right.svg)'; + stockToolbar.arrowDown = createElement(DIV, { + className: PREFIX + 'arrow-down' + }, null, stockToolbar.arrowWrapper); + stockToolbar.arrowDown.style['background-image'] = + 'url(' + this.iconsURL + 'arrow-right.svg)'; + wrapper.insertBefore(stockToolbar.arrowWrapper, wrapper.childNodes[0]); + // attach scroll events + stockToolbar.scrollButtons(); + }; + /* + * Add events to navigation (two arrows) which allows user to scroll + * top/down GUI buttons, if container's height is not enough. + * + */ + Toolbar.prototype.scrollButtons = function () { + var targetY = 0, _self = this, wrapper = _self.wrapper, toolbar = _self.toolbar, step = 0.1 * wrapper.offsetHeight; // 0.1 = 10% + _self.eventsToUnbind.push(addEvent(_self.arrowUp, 'click', function () { + if (targetY > 0) { + targetY -= step; + toolbar.style['margin-top'] = -targetY + 'px'; + } + })); + _self.eventsToUnbind.push(addEvent(_self.arrowDown, 'click', function () { + if (wrapper.offsetHeight + targetY <= + toolbar.offsetHeight + step) { + targetY += step; + toolbar.style['margin-top'] = -targetY + 'px'; + } + })); + }; + /* + * Create stockTools HTML main elements. + * + */ + Toolbar.prototype.createHTML = function () { + var stockToolbar = this, chart = stockToolbar.chart, guiOptions = stockToolbar.options, container = chart.container, navigation = chart.options.navigation, bindingsClassName = navigation && navigation.bindingsClassName, listWrapper, toolbar, wrapper; + // create main container + stockToolbar.wrapper = wrapper = createElement(DIV, { + className: PREFIX + 'stocktools-wrapper ' + + guiOptions.className + ' ' + bindingsClassName + }); + container.parentNode.insertBefore(wrapper, container); + // toolbar + stockToolbar.toolbar = toolbar = createElement(UL, { + className: PREFIX + 'stocktools-toolbar ' + + guiOptions.toolbarClassName + }); + // add container for list of buttons + stockToolbar.listWrapper = listWrapper = createElement(DIV, { + className: PREFIX + 'menu-wrapper' + }); + wrapper.insertBefore(listWrapper, wrapper.childNodes[0]); + listWrapper.insertBefore(toolbar, listWrapper.childNodes[0]); + stockToolbar.showHideToolbar(); + // add navigation which allows user to scroll down / top GUI buttons + stockToolbar.addNavigation(); + }; + /** + * Function called in redraw verifies if the navigation should be visible. + * @private + */ + Toolbar.prototype.showHideNavigatorion = function () { + // arrows + // 50px space for arrows + if (this.visible && + this.toolbar.offsetHeight > (this.wrapper.offsetHeight - 50)) { + this.arrowWrapper.style.display = 'block'; + } + else { + // reset margin if whole toolbar is visible + this.toolbar.style.marginTop = '0px'; + // hide arrows + this.arrowWrapper.style.display = 'none'; + } + }; + /** + * Create button which shows or hides GUI toolbar. + * @private + */ + Toolbar.prototype.showHideToolbar = function () { + var stockToolbar = this, chart = this.chart, wrapper = stockToolbar.wrapper, toolbar = this.listWrapper, submenu = this.submenu, visible = this.visible, showhideBtn; + // Show hide toolbar + this.showhideBtn = showhideBtn = createElement(DIV, { + className: PREFIX + 'toggle-toolbar ' + PREFIX + 'arrow-left' + }, null, wrapper); + showhideBtn.style['background-image'] = + 'url(' + this.iconsURL + 'arrow-right.svg)'; + if (!visible) { + // hide + if (submenu) { + submenu.style.display = 'none'; + } + showhideBtn.style.left = '0px'; + stockToolbar.visible = visible = false; + toolbar.classList.add(PREFIX + 'hide'); + showhideBtn.classList.toggle(PREFIX + 'arrow-right'); + wrapper.style.height = showhideBtn.offsetHeight + 'px'; + } + else { + wrapper.style.height = '100%'; + showhideBtn.style.top = getStyle(toolbar, 'padding-top') + 'px'; + showhideBtn.style.left = (wrapper.offsetWidth + + getStyle(toolbar, 'padding-left')) + 'px'; + } + // Toggle menu + stockToolbar.eventsToUnbind.push(addEvent(showhideBtn, 'click', function () { + chart.update({ + stockTools: { + gui: { + visible: !visible, + placed: true + } + } + }); + })); + }; + /* + * In main GUI button, replace icon and class with submenu button's + * class / symbol. + * + * @param {HTMLDOMElement} - submenu button + * @param {Boolean} - true or false + * + */ + Toolbar.prototype.switchSymbol = function (button, redraw) { + var buttonWrapper = button.parentNode, buttonWrapperClass = buttonWrapper.classList.value, + // main button in first level og GUI + mainNavButton = buttonWrapper.parentNode.parentNode; + // set class + mainNavButton.className = ''; + if (buttonWrapperClass) { + mainNavButton.classList.add(buttonWrapperClass.trim()); + } + // set icon + mainNavButton + .querySelectorAll('.' + PREFIX + 'menu-item-btn')[0] + .style['background-image'] = + button.style['background-image']; + // set active class + if (redraw) { + this.selectButton(mainNavButton); + } + }; + /* + * Set select state (active class) on button. + * + * @param {HTMLDOMElement} - button + * + */ + Toolbar.prototype.selectButton = function (button) { + if (button.className.indexOf(activeClass) >= 0) { + button.classList.remove(activeClass); + } + else { + button.classList.add(activeClass); + } + }; + /* + * Remove active class from all buttons except defined. + * + * @param {HTMLDOMElement} - button which should not be deactivated + * + */ + Toolbar.prototype.unselectAllButtons = function (button) { + var activeButtons = button.parentNode + .querySelectorAll('.' + activeClass); + [].forEach.call(activeButtons, function (activeBtn) { + if (activeBtn !== button) { + activeBtn.classList.remove(activeClass); + } + }); + }; + /* + * Update GUI with given options. + * + * @param {Object} - general options for Stock Tools + */ + Toolbar.prototype.update = function (options) { + merge(true, this.chart.options.stockTools, options); + this.destroy(); + this.chart.setStockTools(options); + // If Stock Tools are updated, then bindings should be updated too: + if (this.chart.navigationBindings) { + this.chart.navigationBindings.update(); + } + }; + /** + * Destroy all HTML GUI elements. + * @private + */ + Toolbar.prototype.destroy = function () { + var stockToolsDiv = this.wrapper, parent = stockToolsDiv && stockToolsDiv.parentNode; + this.eventsToUnbind.forEach(function (unbinder) { + unbinder(); + }); + // Remove the empty element + if (parent) { + parent.removeChild(stockToolsDiv); + } + // redraw + this.chart.isDirtyBox = true; + this.chart.redraw(); + }; + /** + * Redraw, GUI requires to verify if the navigation should be visible. + * @private + */ + Toolbar.prototype.redraw = function () { + this.showHideNavigatorion(); + }; + Toolbar.prototype.getIconsURL = function () { + return this.chart.options.navigation.iconsURL || + this.options.iconsURL || + 'https://code.highcharts.com/8.1.0/gfx/stock-icons/'; + }; + return Toolbar; +}()); +/** + * Mapping JSON fields to CSS classes. + * @private + */ +Toolbar.prototype.classMapping = { + circle: PREFIX + 'circle-annotation', + rectangle: PREFIX + 'rectangle-annotation', + label: PREFIX + 'label-annotation', + segment: PREFIX + 'segment', + arrowSegment: PREFIX + 'arrow-segment', + ray: PREFIX + 'ray', + arrowRay: PREFIX + 'arrow-ray', + line: PREFIX + 'infinity-line', + arrowLine: PREFIX + 'arrow-infinity-line', + verticalLine: PREFIX + 'vertical-line', + horizontalLine: PREFIX + 'horizontal-line', + crooked3: PREFIX + 'crooked3', + crooked5: PREFIX + 'crooked5', + elliott3: PREFIX + 'elliott3', + elliott5: PREFIX + 'elliott5', + pitchfork: PREFIX + 'pitchfork', + fibonacci: PREFIX + 'fibonacci', + parallelChannel: PREFIX + 'parallel-channel', + measureX: PREFIX + 'measure-x', + measureY: PREFIX + 'measure-y', + measureXY: PREFIX + 'measure-xy', + verticalCounter: PREFIX + 'vertical-counter', + verticalLabel: PREFIX + 'vertical-label', + verticalArrow: PREFIX + 'vertical-arrow', + currentPriceIndicator: PREFIX + 'current-price-indicator', + indicators: PREFIX + 'indicators', + flagCirclepin: PREFIX + 'flag-circlepin', + flagDiamondpin: PREFIX + 'flag-diamondpin', + flagSquarepin: PREFIX + 'flag-squarepin', + flagSimplepin: PREFIX + 'flag-simplepin', + zoomX: PREFIX + 'zoom-x', + zoomY: PREFIX + 'zoom-y', + zoomXY: PREFIX + 'zoom-xy', + typeLine: PREFIX + 'series-type-line', + typeOHLC: PREFIX + 'series-type-ohlc', + typeCandlestick: PREFIX + 'series-type-candlestick', + fullScreen: PREFIX + 'full-screen', + toggleAnnotations: PREFIX + 'toggle-annotations', + saveChart: PREFIX + 'save-chart', + separator: PREFIX + 'separator' +}; +extend(H.Chart.prototype, { + /** + * Verify if Toolbar should be added. + * @private + * @param {Highcharts.StockToolsOptions} - chart options + * @return {void} + */ + setStockTools: function (options) { + var chartOptions = this.options, lang = chartOptions.lang, guiOptions = merge(chartOptions.stockTools && chartOptions.stockTools.gui, options && options.gui), langOptions = lang.stockTools && lang.stockTools.gui; + this.stockTools = new H.Toolbar(guiOptions, langOptions, this); + if (this.stockTools.guiEnabled) { + this.isDirtyBox = true; + } + } +}); +// Comunication with bindings: +addEvent(NavigationBindings, 'selectButton', function (event) { + var button = event.button, className = PREFIX + 'submenu-wrapper', gui = this.chart.stockTools; + if (gui && gui.guiEnabled) { + // Unslect other active buttons + gui.unselectAllButtons(event.button); + // If clicked on a submenu, select state for it's parent + if (button.parentNode.className.indexOf(className) >= 0) { + button = button.parentNode.parentNode; + } + // Set active class on the current button + gui.selectButton(button); + } +}); +addEvent(NavigationBindings, 'deselectButton', function (event) { + var button = event.button, className = PREFIX + 'submenu-wrapper', gui = this.chart.stockTools; + if (gui && gui.guiEnabled) { + // If deselecting a button from a submenu, select state for it's parent + if (button.parentNode.className.indexOf(className) >= 0) { + button = button.parentNode.parentNode; + } + gui.selectButton(button); + } +}); +H.Toolbar = Toolbar; +export default H.Toolbar; diff --git a/librerias/gantt/code/es-modules/modules/streamgraph.src.js b/librerias/gantt/code/es-modules/modules/streamgraph.src.js new file mode 100644 index 0000000..5b2d5b2 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/streamgraph.src.js @@ -0,0 +1,127 @@ +/* * + * + * Streamgraph module + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import '../parts/AreaSeries.js'; +import U from '../parts/Utilities.js'; +var seriesType = U.seriesType; +/** + * @private + * @class + * @name Highcharts.seriesTypes.streamgraph + * + * @augments Highcharts.Series + */ +seriesType('streamgraph', 'areaspline' +/** + * A streamgraph is a type of stacked area graph which is displaced around a + * central axis, resulting in a flowing, organic shape. + * + * @sample {highcharts|highstock} highcharts/demo/streamgraph/ + * Streamgraph + * + * @extends plotOptions.areaspline + * @since 6.0.0 + * @product highcharts highstock + * @requires modules/streamgraph + * @optionparent plotOptions.streamgraph + */ +, { + fillOpacity: 1, + lineWidth: 0, + marker: { + enabled: false + }, + stacking: 'stream' + // Prototype functions +}, { + negStacks: false, + // Modifier function for stream stacks. It simply moves the point up or + // down in order to center the full stack vertically. + streamStacker: function (pointExtremes, stack, i) { + // Y bottom value + pointExtremes[0] -= stack.total / 2; + // Y value + pointExtremes[1] -= stack.total / 2; + // Record the Y data for use when getting axis extremes + this.stackedYData[i] = pointExtremes; + } +}); +/** + * A `streamgraph` series. If the [type](#series.streamgraph.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.streamgraph + * @excluding dataParser, dataURL, step + * @product highcharts highstock + * @requires modules/streamgraph + * @apioption series.streamgraph + */ +/** + * An array of data points for the series. For the `streamgraph` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 9], + * [1, 7], + * [2, 6] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.area.turboThreshold), + * this option is not available. + * ```js + * data: [{ + * x: 1, + * y: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @product highcharts highstock + * @apioption series.streamgraph.data + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/modules/sunburst.src.js b/librerias/gantt/code/es-modules/modules/sunburst.src.js new file mode 100644 index 0000000..0d805e9 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/sunburst.src.js @@ -0,0 +1,955 @@ +/* * + * + * This module implements sunburst charts in Highcharts. + * + * (c) 2016-2020 Highsoft AS + * + * Authors: Jon Arild Nygard + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var correctFloat = U.correctFloat, error = U.error, extend = U.extend, isNumber = U.isNumber, isObject = U.isObject, isString = U.isString, merge = U.merge, seriesType = U.seriesType, splat = U.splat; +import '../mixins/centered-series.js'; +import drawPoint from '../mixins/draw-point.js'; +import mixinTreeSeries from '../mixins/tree-series.js'; +import '../parts/Series.js'; +import './treemap.src.js'; +var CenteredSeriesMixin = H.CenteredSeriesMixin, Series = H.Series, getCenter = CenteredSeriesMixin.getCenter, getColor = mixinTreeSeries.getColor, getLevelOptions = mixinTreeSeries.getLevelOptions, getStartAndEndRadians = CenteredSeriesMixin.getStartAndEndRadians, isBoolean = function (x) { + return typeof x === 'boolean'; +}, noop = H.noop, rad2deg = 180 / Math.PI, seriesTypes = H.seriesTypes, setTreeValues = mixinTreeSeries.setTreeValues, updateRootId = mixinTreeSeries.updateRootId; +// TODO introduce step, which should default to 1. +var range = function range(from, to) { + var result = [], i; + if (isNumber(from) && isNumber(to) && from <= to) { + for (i = from; i <= to; i++) { + result.push(i); + } + } + return result; +}; +/** + * @private + * @function calculateLevelSizes + * + * @param {object} levelOptions + * Map of level to its options. + * + * @param {Highcharts.Dictionary} params + * Object containing number parameters `innerRadius` and `outerRadius`. + * + * @return {Highcharts.SunburstSeriesLevelsOptions|undefined} + * Returns the modified options, or undefined. + */ +var calculateLevelSizes = function calculateLevelSizes(levelOptions, params) { + var result, p = isObject(params) ? params : {}, totalWeight = 0, diffRadius, levels, levelsNotIncluded, remainingSize, from, to; + if (isObject(levelOptions)) { + result = merge({}, levelOptions); + from = isNumber(p.from) ? p.from : 0; + to = isNumber(p.to) ? p.to : 0; + levels = range(from, to); + levelsNotIncluded = Object.keys(result).filter(function (k) { + return levels.indexOf(+k) === -1; + }); + diffRadius = remainingSize = isNumber(p.diffRadius) ? p.diffRadius : 0; + // Convert percentage to pixels. + // Calculate the remaining size to divide between "weight" levels. + // Calculate total weight to use in convertion from weight to pixels. + levels.forEach(function (level) { + var options = result[level], unit = options.levelSize.unit, value = options.levelSize.value; + if (unit === 'weight') { + totalWeight += value; + } + else if (unit === 'percentage') { + options.levelSize = { + unit: 'pixels', + value: (value / 100) * diffRadius + }; + remainingSize -= options.levelSize.value; + } + else if (unit === 'pixels') { + remainingSize -= value; + } + }); + // Convert weight to pixels. + levels.forEach(function (level) { + var options = result[level], weight; + if (options.levelSize.unit === 'weight') { + weight = options.levelSize.value; + result[level].levelSize = { + unit: 'pixels', + value: (weight / totalWeight) * remainingSize + }; + } + }); + // Set all levels not included in interval [from,to] to have 0 pixels. + levelsNotIncluded.forEach(function (level) { + result[level].levelSize = { + value: 0, + unit: 'pixels' + }; + }); + } + return result; +}; +/** + * Find a set of coordinates given a start coordinates, an angle, and a + * distance. + * + * @private + * @function getEndPoint + * + * @param {number} x + * Start coordinate x + * + * @param {number} y + * Start coordinate y + * + * @param {number} angle + * Angle in radians + * + * @param {number} distance + * Distance from start to end coordinates + * + * @return {Highcharts.SVGAttributes} + * Returns the end coordinates, x and y. + */ +var getEndPoint = function getEndPoint(x, y, angle, distance) { + return { + x: x + (Math.cos(angle) * distance), + y: y + (Math.sin(angle) * distance) + }; +}; +var layoutAlgorithm = function layoutAlgorithm(parent, children, options) { + var startAngle = parent.start, range = parent.end - startAngle, total = parent.val, x = parent.x, y = parent.y, radius = ((options && + isObject(options.levelSize) && + isNumber(options.levelSize.value)) ? + options.levelSize.value : + 0), innerRadius = parent.r, outerRadius = innerRadius + radius, slicedOffset = options && isNumber(options.slicedOffset) ? + options.slicedOffset : + 0; + return (children || []).reduce(function (arr, child) { + var percentage = (1 / total) * child.val, radians = percentage * range, radiansCenter = startAngle + (radians / 2), offsetPosition = getEndPoint(x, y, radiansCenter, slicedOffset), values = { + x: child.sliced ? offsetPosition.x : x, + y: child.sliced ? offsetPosition.y : y, + innerR: innerRadius, + r: outerRadius, + radius: radius, + start: startAngle, + end: startAngle + radians + }; + arr.push(values); + startAngle = values.end; + return arr; + }, []); +}; +var getDlOptions = function getDlOptions(params) { + // Set options to new object to avoid problems with scope + var point = params.point, shape = isObject(params.shapeArgs) ? params.shapeArgs : {}, optionsPoint = (isObject(params.optionsPoint) ? + params.optionsPoint.dataLabels : + {}), + // The splat was used because levels dataLabels + // options doesn't work as an array + optionsLevel = splat(isObject(params.level) ? + params.level.dataLabels : + {})[0], options = merge({ + style: {} + }, optionsLevel, optionsPoint), rotationRad, rotation, rotationMode = options.rotationMode; + if (!isNumber(options.rotation)) { + if (rotationMode === 'auto' || rotationMode === 'circular') { + if (point.innerArcLength < 1 && + point.outerArcLength > shape.radius) { + rotationRad = 0; + // Triger setTextPath function to get textOutline etc. + if (point.dataLabelPath && rotationMode === 'circular') { + options.textPath = { + enabled: true + }; + } + } + else if (point.innerArcLength > 1 && + point.outerArcLength > 1.5 * shape.radius) { + if (rotationMode === 'circular') { + options.textPath = { + enabled: true, + attributes: { + dy: 5 + } + }; + } + else { + rotationMode = 'parallel'; + } + } + else { + // Trigger the destroyTextPath function + if (point.dataLabel && + point.dataLabel.textPathWrapper && + rotationMode === 'circular') { + options.textPath = { + enabled: false + }; + } + rotationMode = 'perpendicular'; + } + } + if (rotationMode !== 'auto' && rotationMode !== 'circular') { + rotationRad = (shape.end - + (shape.end - shape.start) / 2); + } + if (rotationMode === 'parallel') { + options.style.width = Math.min(shape.radius * 2.5, (point.outerArcLength + point.innerArcLength) / 2); + } + else { + options.style.width = shape.radius; + } + if (rotationMode === 'perpendicular' && + point.series.chart.renderer.fontMetrics(options.style.fontSize).h > point.outerArcLength) { + options.style.width = 1; + } + // Apply padding (#8515) + options.style.width = Math.max(options.style.width - 2 * (options.padding || 0), 1); + rotation = (rotationRad * rad2deg) % 180; + if (rotationMode === 'parallel') { + rotation -= 90; + } + // Prevent text from rotating upside down + if (rotation > 90) { + rotation -= 180; + } + else if (rotation < -90) { + rotation += 180; + } + options.rotation = rotation; + } + if (options.textPath) { + if (point.shapeExisting.innerR === 0 && + options.textPath.enabled) { + // Enable rotation to render text + options.rotation = 0; + // Center dataLabel - disable textPath + options.textPath.enabled = false; + // Setting width and padding + options.style.width = Math.max((point.shapeExisting.r * 2) - + 2 * (options.padding || 0), 1); + } + else if (point.dlOptions && + point.dlOptions.textPath && + !point.dlOptions.textPath.enabled && + (rotationMode === 'circular')) { + // Bring dataLabel back if was a center dataLabel + options.textPath.enabled = true; + } + if (options.textPath.enabled) { + // Enable rotation to render text + options.rotation = 0; + // Setting width and padding + options.style.width = Math.max((point.outerArcLength + + point.innerArcLength) / 2 - + 2 * (options.padding || 0), 1); + } + } + // NOTE: alignDataLabel positions the data label differntly when rotation is + // 0. Avoiding this by setting rotation to a small number. + if (options.rotation === 0) { + options.rotation = 0.001; + } + return options; +}; +var getAnimation = function getAnimation(shape, params) { + var point = params.point, radians = params.radians, innerR = params.innerR, idRoot = params.idRoot, idPreviousRoot = params.idPreviousRoot, shapeExisting = params.shapeExisting, shapeRoot = params.shapeRoot, shapePreviousRoot = params.shapePreviousRoot, visible = params.visible, from = {}, to = { + end: shape.end, + start: shape.start, + innerR: shape.innerR, + r: shape.r, + x: shape.x, + y: shape.y + }; + if (visible) { + // Animate points in + if (!point.graphic && shapePreviousRoot) { + if (idRoot === point.id) { + from = { + start: radians.start, + end: radians.end + }; + } + else { + from = (shapePreviousRoot.end <= shape.start) ? { + start: radians.end, + end: radians.end + } : { + start: radians.start, + end: radians.start + }; + } + // Animate from center and outwards. + from.innerR = from.r = innerR; + } + } + else { + // Animate points out + if (point.graphic) { + if (idPreviousRoot === point.id) { + to = { + innerR: innerR, + r: innerR + }; + } + else if (shapeRoot) { + to = (shapeRoot.end <= shapeExisting.start) ? + { + innerR: innerR, + r: innerR, + start: radians.end, + end: radians.end + } : { + innerR: innerR, + r: innerR, + start: radians.start, + end: radians.start + }; + } + } + } + return { + from: from, + to: to + }; +}; +var getDrillId = function getDrillId(point, idRoot, mapIdToNode) { + var drillId, node = point.node, nodeRoot; + if (!node.isLeaf) { + // When it is the root node, the drillId should be set to parent. + if (idRoot === point.id) { + nodeRoot = mapIdToNode[idRoot]; + drillId = nodeRoot.parent; + } + else { + drillId = point.id; + } + } + return drillId; +}; +var getLevelFromAndTo = function getLevelFromAndTo(_a) { + var level = _a.level, height = _a.height; + // Never displays level below 1 + var from = level > 0 ? level : 1; + var to = level + height; + return { from: from, to: to }; +}; +var cbSetTreeValuesBefore = function before(node, options) { + var mapIdToNode = options.mapIdToNode, nodeParent = mapIdToNode[node.parent], series = options.series, chart = series.chart, points = series.points, point = points[node.i], colors = (series.options.colors || chart && chart.options.colors), colorInfo = getColor(node, { + colors: colors, + colorIndex: series.colorIndex, + index: options.index, + mapOptionsToLevel: options.mapOptionsToLevel, + parentColor: nodeParent && nodeParent.color, + parentColorIndex: nodeParent && nodeParent.colorIndex, + series: options.series, + siblings: options.siblings + }); + node.color = colorInfo.color; + node.colorIndex = colorInfo.colorIndex; + if (point) { + point.color = node.color; + point.colorIndex = node.colorIndex; + // Set slicing on node, but avoid slicing the top node. + node.sliced = (node.id !== options.idRoot) ? point.sliced : false; + } + return node; +}; +/** + * A Sunburst displays hierarchical data, where a level in the hierarchy is + * represented by a circle. The center represents the root node of the tree. + * The visualization bears a resemblance to both treemap and pie charts. + * + * @sample highcharts/demo/sunburst + * Sunburst chart + * + * @extends plotOptions.pie + * @excluding allAreas, clip, colorAxis, colorKey, compare, compareBase, + * dataGrouping, depth, dragDrop, endAngle, gapSize, gapUnit, + * ignoreHiddenPoint, innerSize, joinBy, legendType, linecap, + * minSize, navigatorOptions, pointRange + * @product highcharts + * @requires modules/sunburst.js + * @optionparent plotOptions.sunburst + * @private + */ +var sunburstOptions = { + /** + * Set options on specific levels. Takes precedence over series options, + * but not point options. + * + * @sample highcharts/demo/sunburst + * Sunburst chart + * + * @type {Array<*>} + * @apioption plotOptions.sunburst.levels + */ + /** + * Can set a `borderColor` on all points which lies on the same level. + * + * @type {Highcharts.ColorString} + * @apioption plotOptions.sunburst.levels.borderColor + */ + /** + * Can set a `borderWidth` on all points which lies on the same level. + * + * @type {number} + * @apioption plotOptions.sunburst.levels.borderWidth + */ + /** + * Can set a `borderDashStyle` on all points which lies on the same level. + * + * @type {Highcharts.DashStyleValue} + * @apioption plotOptions.sunburst.levels.borderDashStyle + */ + /** + * Can set a `color` on all points which lies on the same level. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.sunburst.levels.color + */ + /** + * Can set a `colorVariation` on all points which lies on the same level. + * + * @apioption plotOptions.sunburst.levels.colorVariation + */ + /** + * The key of a color variation. Currently supports `brightness` only. + * + * @type {string} + * @apioption plotOptions.sunburst.levels.colorVariation.key + */ + /** + * The ending value of a color variation. The last sibling will receive this + * value. + * + * @type {number} + * @apioption plotOptions.sunburst.levels.colorVariation.to + */ + /** + * Can set `dataLabels` on all points which lies on the same level. + * + * @extends plotOptions.sunburst.dataLabels + * @apioption plotOptions.sunburst.levels.dataLabels + */ + /** + * Can set a `levelSize` on all points which lies on the same level. + * + * @type {object} + * @apioption plotOptions.sunburst.levels.levelSize + */ + /** + * Can set a `rotation` on all points which lies on the same level. + * + * @type {number} + * @apioption plotOptions.sunburst.levels.rotation + */ + /** + * Can set a `rotationMode` on all points which lies on the same level. + * + * @type {string} + * @apioption plotOptions.sunburst.levels.rotationMode + */ + /** + * When enabled the user can click on a point which is a parent and + * zoom in on its children. Deprecated and replaced by + * [allowTraversingTree](#plotOptions.sunburst.allowTraversingTree). + * + * @deprecated + * @type {boolean} + * @default false + * @since 6.0.0 + * @product highcharts + * @apioption plotOptions.sunburst.allowDrillToNode + */ + /** + * When enabled the user can click on a point which is a parent and + * zoom in on its children. + * + * @type {boolean} + * @default false + * @since 7.0.3 + * @product highcharts + * @apioption plotOptions.sunburst.allowTraversingTree + */ + /** + * The center of the sunburst chart relative to the plot area. Can be + * percentages or pixel values. + * + * @sample {highcharts} highcharts/plotoptions/pie-center/ + * Centered at 100, 100 + * + * @type {Array} + * @default ["50%", "50%"] + * @product highcharts + */ + center: ['50%', '50%'], + colorByPoint: false, + /** + * Disable inherited opacity from Treemap series. + * + * @ignore-option + */ + opacity: 1, + /** + * @declare Highcharts.SeriesSunburstDataLabelsOptionsObject + */ + dataLabels: { + allowOverlap: true, + defer: true, + /** + * Decides how the data label will be rotated relative to the perimeter + * of the sunburst. Valid values are `auto`, `circular`, `parallel` and + * `perpendicular`. When `auto`, the best fit will be + * computed for the point. The `circular` option works similiar + * to `auto`, but uses the `textPath` feature - labels are curved, + * resulting in a better layout, however multiple lines and + * `textOutline` are not supported. + * + * The `series.rotation` option takes precedence over `rotationMode`. + * + * @type {string} + * @sample {highcharts} highcharts/plotoptions/sunburst-datalabels-rotationmode-circular/ + * Circular rotation mode + * @validvalue ["auto", "perpendicular", "parallel", "circular"] + * @since 6.0.0 + */ + rotationMode: 'auto', + style: { + /** @internal */ + textOverflow: 'ellipsis' + } + }, + /** + * Which point to use as a root in the visualization. + * + * @type {string} + */ + rootId: void 0, + /** + * Used together with the levels and `allowDrillToNode` options. When + * set to false the first level visible when drilling is considered + * to be level one. Otherwise the level will be the same as the tree + * structure. + */ + levelIsConstant: true, + /** + * Determines the width of the ring per level. + * + * @sample {highcharts} highcharts/plotoptions/sunburst-levelsize/ + * Sunburst with various sizes per level + * + * @since 6.0.5 + */ + levelSize: { + /** + * The value used for calculating the width of the ring. Its' affect is + * determined by `levelSize.unit`. + * + * @sample {highcharts} highcharts/plotoptions/sunburst-levelsize/ + * Sunburst with various sizes per level + */ + value: 1, + /** + * How to interpret `levelSize.value`. + * + * - `percentage` gives a width relative to result of outer radius minus + * inner radius. + * + * - `pixels` gives the ring a fixed width in pixels. + * + * - `weight` takes the remaining width after percentage and pixels, and + * distributes it accross all "weighted" levels. The value relative to + * the sum of all weights determines the width. + * + * @sample {highcharts} highcharts/plotoptions/sunburst-levelsize/ + * Sunburst with various sizes per level + * + * @validvalue ["percentage", "pixels", "weight"] + */ + unit: 'weight' + }, + /** + * Options for the button appearing when traversing down in a treemap. + * + * @extends plotOptions.treemap.traverseUpButton + * @since 6.0.0 + * @apioption plotOptions.sunburst.traverseUpButton + */ + /** + * If a point is sliced, moved out from the center, how many pixels + * should it be moved?. + * + * @sample highcharts/plotoptions/sunburst-sliced + * Sliced sunburst + * + * @since 6.0.4 + */ + slicedOffset: 10 +}; +// Properties of the Sunburst series. +var sunburstSeries = { + drawDataLabels: noop, + drawPoints: function drawPoints() { + var series = this, mapOptionsToLevel = series.mapOptionsToLevel, shapeRoot = series.shapeRoot, group = series.group, hasRendered = series.hasRendered, idRoot = series.rootNode, idPreviousRoot = series.idPreviousRoot, nodeMap = series.nodeMap, nodePreviousRoot = nodeMap[idPreviousRoot], shapePreviousRoot = nodePreviousRoot && nodePreviousRoot.shapeArgs, points = series.points, radians = series.startAndEndRadians, chart = series.chart, optionsChart = chart && chart.options && chart.options.chart || {}, animation = (isBoolean(optionsChart.animation) ? + optionsChart.animation : + true), positions = series.center, center = { + x: positions[0], + y: positions[1] + }, innerR = positions[3] / 2, renderer = series.chart.renderer, animateLabels, animateLabelsCalled = false, addedHack = false, hackDataLabelAnimation = !!(animation && + hasRendered && + idRoot !== idPreviousRoot && + series.dataLabelsGroup); + if (hackDataLabelAnimation) { + series.dataLabelsGroup.attr({ opacity: 0 }); + animateLabels = function () { + var s = series; + animateLabelsCalled = true; + if (s.dataLabelsGroup) { + s.dataLabelsGroup.animate({ + opacity: 1, + visibility: 'visible' + }); + } + }; + } + points.forEach(function (point) { + var node = point.node, level = mapOptionsToLevel[node.level], shapeExisting = point.shapeExisting || {}, shape = node.shapeArgs || {}, animationInfo, onComplete, visible = !!(node.visible && node.shapeArgs); + if (hasRendered && animation) { + animationInfo = getAnimation(shape, { + center: center, + point: point, + radians: radians, + innerR: innerR, + idRoot: idRoot, + idPreviousRoot: idPreviousRoot, + shapeExisting: shapeExisting, + shapeRoot: shapeRoot, + shapePreviousRoot: shapePreviousRoot, + visible: visible + }); + } + else { + // When animation is disabled, attr is called from animation. + animationInfo = { + to: shape, + from: {} + }; + } + extend(point, { + shapeExisting: shape, + tooltipPos: [shape.plotX, shape.plotY], + drillId: getDrillId(point, idRoot, nodeMap), + name: '' + (point.name || point.id || point.index), + plotX: shape.plotX, + plotY: shape.plotY, + value: node.val, + isNull: !visible // used for dataLabels & point.draw + }); + point.dlOptions = getDlOptions({ + point: point, + level: level, + optionsPoint: point.options, + shapeArgs: shape + }); + if (!addedHack && visible) { + addedHack = true; + onComplete = animateLabels; + } + point.draw({ + animatableAttribs: animationInfo.to, + attribs: extend(animationInfo.from, (!chart.styledMode && series.pointAttribs(point, (point.selected && 'select')))), + onComplete: onComplete, + group: group, + renderer: renderer, + shapeType: 'arc', + shapeArgs: shape + }); + }); + // Draw data labels after points + // TODO draw labels one by one to avoid addtional looping + if (hackDataLabelAnimation && addedHack) { + series.hasRendered = false; + series.options.dataLabels.defer = true; + Series.prototype.drawDataLabels.call(series); + series.hasRendered = true; + // If animateLabels is called before labels were hidden, then call + // it again. + if (animateLabelsCalled) { + animateLabels(); + } + } + else { + Series.prototype.drawDataLabels.call(series); + } + }, + pointAttribs: seriesTypes.column.prototype.pointAttribs, + // The layout algorithm for the levels + layoutAlgorithm: layoutAlgorithm, + // Set the shape arguments on the nodes. Recursive from root down. + setShapeArgs: function (parent, parentValues, mapOptionsToLevel) { + var childrenValues = [], level = parent.level + 1, options = mapOptionsToLevel[level], + // Collect all children which should be included + children = parent.children.filter(function (n) { + return n.visible; + }), twoPi = 6.28; // Two times Pi. + childrenValues = this.layoutAlgorithm(parentValues, children, options); + children.forEach(function (child, index) { + var values = childrenValues[index], angle = values.start + ((values.end - values.start) / 2), radius = values.innerR + ((values.r - values.innerR) / 2), radians = (values.end - values.start), isCircle = (values.innerR === 0 && radians > twoPi), center = (isCircle ? + { x: values.x, y: values.y } : + getEndPoint(values.x, values.y, angle, radius)), val = (child.val ? + (child.childrenTotal > child.val ? + child.childrenTotal : + child.val) : + child.childrenTotal); + // The inner arc length is a convenience for data label filters. + if (this.points[child.i]) { + this.points[child.i].innerArcLength = radians * values.innerR; + this.points[child.i].outerArcLength = radians * values.r; + } + child.shapeArgs = merge(values, { + plotX: center.x, + plotY: center.y + 4 * Math.abs(Math.cos(angle)) + }); + child.values = merge(values, { + val: val + }); + // If node has children, then call method recursively + if (child.children.length) { + this.setShapeArgs(child, child.values, mapOptionsToLevel); + } + }, this); + }, + translate: function translate() { + var series = this, options = series.options, positions = series.center = getCenter.call(series), radians = series.startAndEndRadians = getStartAndEndRadians(options.startAngle, options.endAngle), innerRadius = positions[3] / 2, outerRadius = positions[2] / 2, diffRadius = outerRadius - innerRadius, + // NOTE: updateRootId modifies series. + rootId = updateRootId(series), mapIdToNode = series.nodeMap, mapOptionsToLevel, idTop, nodeRoot = mapIdToNode && mapIdToNode[rootId], nodeTop, tree, values, nodeIds = {}; + series.shapeRoot = nodeRoot && nodeRoot.shapeArgs; + // Call prototype function + Series.prototype.translate.call(series); + // @todo Only if series.isDirtyData is true + tree = series.tree = series.getTree(); + // Render traverseUpButton, after series.nodeMap i calculated. + series.renderTraverseUpButton(rootId); + mapIdToNode = series.nodeMap; + nodeRoot = mapIdToNode[rootId]; + idTop = isString(nodeRoot.parent) ? nodeRoot.parent : ''; + nodeTop = mapIdToNode[idTop]; + var _a = getLevelFromAndTo(nodeRoot), from = _a.from, to = _a.to; + mapOptionsToLevel = getLevelOptions({ + from: from, + levels: series.options.levels, + to: to, + defaults: { + colorByPoint: options.colorByPoint, + dataLabels: options.dataLabels, + levelIsConstant: options.levelIsConstant, + levelSize: options.levelSize, + slicedOffset: options.slicedOffset + } + }); + // NOTE consider doing calculateLevelSizes in a callback to + // getLevelOptions + mapOptionsToLevel = calculateLevelSizes(mapOptionsToLevel, { + diffRadius: diffRadius, + from: from, + to: to + }); + // TODO Try to combine setTreeValues & setColorRecursive to avoid + // unnecessary looping. + setTreeValues(tree, { + before: cbSetTreeValuesBefore, + idRoot: rootId, + levelIsConstant: options.levelIsConstant, + mapOptionsToLevel: mapOptionsToLevel, + mapIdToNode: mapIdToNode, + points: series.points, + series: series + }); + values = mapIdToNode[''].shapeArgs = { + end: radians.end, + r: innerRadius, + start: radians.start, + val: nodeRoot.val, + x: positions[0], + y: positions[1] + }; + this.setShapeArgs(nodeTop, values, mapOptionsToLevel); + // Set mapOptionsToLevel on series for use in drawPoints. + series.mapOptionsToLevel = mapOptionsToLevel; + // #10669 - verify if all nodes have unique ids + series.data.forEach(function (child) { + if (nodeIds[child.id]) { + error(31, false, series.chart); + } + // map + nodeIds[child.id] = true; + }); + // reset object + nodeIds = {}; + }, + alignDataLabel: function (point, dataLabel, labelOptions) { + if (labelOptions.textPath && labelOptions.textPath.enabled) { + return; + } + return seriesTypes.treemap.prototype.alignDataLabel + .apply(this, arguments); + }, + // Animate the slices in. Similar to the animation of polar charts. + animate: function (init) { + var chart = this.chart, center = [ + chart.plotWidth / 2, + chart.plotHeight / 2 + ], plotLeft = chart.plotLeft, plotTop = chart.plotTop, attribs, group = this.group; + // Initialize the animation + if (init) { + // Scale down the group and place it in the center + attribs = { + translateX: center[0] + plotLeft, + translateY: center[1] + plotTop, + scaleX: 0.001, + scaleY: 0.001, + rotation: 10, + opacity: 0.01 + }; + group.attr(attribs); + // Run the animation + } + else { + attribs = { + translateX: plotLeft, + translateY: plotTop, + scaleX: 1, + scaleY: 1, + rotation: 0, + opacity: 1 + }; + group.animate(attribs, this.options.animation); + } + }, + utils: { + calculateLevelSizes: calculateLevelSizes, + getLevelFromAndTo: getLevelFromAndTo, + range: range + } +}; +// Properties of the Sunburst series. +var sunburstPoint = { + draw: drawPoint, + shouldDraw: function shouldDraw() { + return !this.isNull; + }, + isValid: function isValid() { + return true; + }, + getDataLabelPath: function (label) { + var renderer = this.series.chart.renderer, shapeArgs = this.shapeExisting, start = shapeArgs.start, end = shapeArgs.end, angle = start + (end - start) / 2, // arc middle value + upperHalf = angle < 0 && + angle > -Math.PI || + angle > Math.PI, r = (shapeArgs.r + (label.options.distance || 0)), moreThanHalf; + // Check if point is a full circle + if (start === -Math.PI / 2 && + correctFloat(end) === correctFloat(Math.PI * 1.5)) { + start = -Math.PI + Math.PI / 360; + end = -Math.PI / 360; + upperHalf = true; + } + // Check if dataLabels should be render in the + // upper half of the circle + if (end - start > Math.PI) { + upperHalf = false; + moreThanHalf = true; + } + if (this.dataLabelPath) { + this.dataLabelPath = this.dataLabelPath.destroy(); + } + this.dataLabelPath = renderer + .arc({ + open: true, + longArc: moreThanHalf ? 1 : 0 + }) + // Add it inside the data label group so it gets destroyed + // with the label + .add(label); + this.dataLabelPath.attr({ + start: (upperHalf ? start : end), + end: (upperHalf ? end : start), + clockwise: +upperHalf, + x: shapeArgs.x, + y: shapeArgs.y, + r: (r + shapeArgs.innerR) / 2 + }); + return this.dataLabelPath; + } +}; +/** + * A `sunburst` series. If the [type](#series.sunburst.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.sunburst + * @excluding dataParser, dataURL, stack, dataSorting + * @product highcharts + * @requires modules/sunburst.js + * @apioption series.sunburst + */ +/** + * @type {Array} + * @extends series.treemap.data + * @excluding x, y + * @product highcharts + * @apioption series.sunburst.data + */ +/** + * @type {Highcharts.SeriesSunburstDataLabelsOptionsObject|Array} + * @product highcharts + * @apioption series.sunburst.data.dataLabels + */ +/** + * The value of the point, resulting in a relative area of the point + * in the sunburst. + * + * @type {number|null} + * @since 6.0.0 + * @product highcharts + * @apioption series.sunburst.data.value + */ +/** + * Use this option to build a tree structure. The value should be the id of the + * point which is the parent. If no points has a matching id, or this option is + * undefined, then the parent will be set to the root. + * + * @type {string} + * @since 6.0.0 + * @product highcharts + * @apioption series.sunburst.data.parent + */ +/** + * Whether to display a slice offset from the center. When a sunburst point is + * sliced, its children are also offset. + * + * @sample highcharts/plotoptions/sunburst-sliced + * Sliced sunburst + * + * @type {boolean} + * @default false + * @since 6.0.4 + * @product highcharts + * @apioption series.sunburst.data.sliced + */ +/** + * @private + * @class + * @name Highcharts.seriesTypes.sunburst + * + * @augments Highcharts.Series + */ +seriesType('sunburst', 'treemap', sunburstOptions, sunburstSeries, sunburstPoint); diff --git a/librerias/gantt/code/es-modules/modules/tilemap.src.js b/librerias/gantt/code/es-modules/modules/tilemap.src.js new file mode 100644 index 0000000..c68a260 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/tilemap.src.js @@ -0,0 +1,581 @@ +/* * + * + * Tilemaps module + * + * (c) 2010-2017 Highsoft AS + * Author: Øystein Moseng + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +/** + * @typedef {"circle"|"diamond"|"hexagon"|"square"} Highcharts.TilemapShapeValue + */ +''; // detach doclets above +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, clamp = U.clamp, extend = U.extend, pick = U.pick, seriesType = U.seriesType; +import '../parts-map/HeatmapSeries.js'; +/** + * Utility func to get padding definition from tile size division + * @private + * @param {Highcharts.TilemapSeries} series + * series + * @param {Highcharts.number} xDiv + * xDiv + * @param {Highcharts.number} yDiv + * yDiv + * @return {Highcharts.TilemapPaddingObject} + */ +function tilePaddingFromTileSize(series, xDiv, yDiv) { + var options = series.options; + return { + xPad: (options.colsize || 1) / -xDiv, + yPad: (options.rowsize || 1) / -yDiv + }; +} +// Map of shape types. +H.tileShapeTypes = { + // Hexagon shape type. + hexagon: { + alignDataLabel: H.seriesTypes.scatter.prototype.alignDataLabel, + getSeriesPadding: function (series) { + return tilePaddingFromTileSize(series, 3, 2); + }, + haloPath: function (size) { + if (!size) { + return []; + } + var hexagon = this.tileEdges; + return [ + ['M', hexagon.x2 - size, hexagon.y1 + size], + ['L', hexagon.x3 + size, hexagon.y1 + size], + ['L', hexagon.x4 + size * 1.5, hexagon.y2], + ['L', hexagon.x3 + size, hexagon.y3 - size], + ['L', hexagon.x2 - size, hexagon.y3 - size], + ['L', hexagon.x1 - size * 1.5, hexagon.y2], + ['Z'] + ]; + }, + translate: function () { + var series = this, options = series.options, xAxis = series.xAxis, yAxis = series.yAxis, seriesPointPadding = options.pointPadding || 0, xPad = (options.colsize || 1) / 3, yPad = (options.rowsize || 1) / 2, yShift; + series.generatePoints(); + series.points.forEach(function (point) { + var x1 = clamp(Math.floor(xAxis.len - + xAxis.translate(point.x - xPad * 2, 0, 1, 0, 1)), -xAxis.len, 2 * xAxis.len), x2 = clamp(Math.floor(xAxis.len - + xAxis.translate(point.x - xPad, 0, 1, 0, 1)), -xAxis.len, 2 * xAxis.len), x3 = clamp(Math.floor(xAxis.len - + xAxis.translate(point.x + xPad, 0, 1, 0, 1)), -xAxis.len, 2 * xAxis.len), x4 = clamp(Math.floor(xAxis.len - + xAxis.translate(point.x + xPad * 2, 0, 1, 0, 1)), -xAxis.len, 2 * xAxis.len), y1 = clamp(Math.floor(yAxis.translate(point.y - yPad, 0, 1, 0, 1)), -yAxis.len, 2 * yAxis.len), y2 = clamp(Math.floor(yAxis.translate(point.y, 0, 1, 0, 1)), -yAxis.len, 2 * yAxis.len), y3 = clamp(Math.floor(yAxis.translate(point.y + yPad, 0, 1, 0, 1)), -yAxis.len, 2 * yAxis.len), pointPadding = pick(point.pointPadding, seriesPointPadding), + // We calculate the point padding of the midpoints to + // preserve the angles of the shape. + midPointPadding = pointPadding * + Math.abs(x2 - x1) / Math.abs(y3 - y2), xMidPadding = xAxis.reversed ? + -midPointPadding : midPointPadding, xPointPadding = xAxis.reversed ? + -pointPadding : pointPadding, yPointPadding = yAxis.reversed ? + -pointPadding : pointPadding; + // Shift y-values for every second grid column + if (point.x % 2) { + yShift = yShift || Math.round(Math.abs(y3 - y1) / 2) * + // We have to reverse the shift for reversed y-axes + (yAxis.reversed ? -1 : 1); + y1 += yShift; + y2 += yShift; + y3 += yShift; + } + // Set plotX and plotY for use in K-D-Tree and more + point.plotX = point.clientX = (x2 + x3) / 2; + point.plotY = y2; + // Apply point padding to translated coordinates + x1 += xMidPadding + xPointPadding; + x2 += xPointPadding; + x3 -= xPointPadding; + x4 -= xMidPadding + xPointPadding; + y1 -= yPointPadding; + y3 += yPointPadding; + // Store points for halo creation + point.tileEdges = { + x1: x1, x2: x2, x3: x3, x4: x4, y1: y1, y2: y2, y3: y3 + }; + // Finally set the shape for this point + point.shapeType = 'path'; + point.shapeArgs = { + d: [ + ['M', x2, y1], + ['L', x3, y1], + ['L', x4, y2], + ['L', x3, y3], + ['L', x2, y3], + ['L', x1, y2], + ['Z'] + ] + }; + }); + series.translateColors(); + } + }, + // Diamond shape type. + diamond: { + alignDataLabel: H.seriesTypes.scatter.prototype.alignDataLabel, + getSeriesPadding: function (series) { + return tilePaddingFromTileSize(series, 2, 2); + }, + haloPath: function (size) { + if (!size) { + return []; + } + var diamond = this.tileEdges; + return [ + ['M', diamond.x2, diamond.y1 + size], + ['L', diamond.x3 + size, diamond.y2], + ['L', diamond.x2, diamond.y3 - size], + ['L', diamond.x1 - size, diamond.y2], + ['Z'] + ]; + }, + translate: function () { + var series = this, options = series.options, xAxis = series.xAxis, yAxis = series.yAxis, seriesPointPadding = options.pointPadding || 0, xPad = (options.colsize || 1), yPad = (options.rowsize || 1) / 2, yShift; + series.generatePoints(); + series.points.forEach(function (point) { + var x1 = clamp(Math.round(xAxis.len - + xAxis.translate(point.x - xPad, 0, 1, 0, 0)), -xAxis.len, 2 * xAxis.len), x2 = clamp(Math.round(xAxis.len - + xAxis.translate(point.x, 0, 1, 0, 0)), -xAxis.len, 2 * xAxis.len), x3 = clamp(Math.round(xAxis.len - + xAxis.translate(point.x + xPad, 0, 1, 0, 0)), -xAxis.len, 2 * xAxis.len), y1 = clamp(Math.round(yAxis.translate(point.y - yPad, 0, 1, 0, 0)), -yAxis.len, 2 * yAxis.len), y2 = clamp(Math.round(yAxis.translate(point.y, 0, 1, 0, 0)), -yAxis.len, 2 * yAxis.len), y3 = clamp(Math.round(yAxis.translate(point.y + yPad, 0, 1, 0, 0)), -yAxis.len, 2 * yAxis.len), pointPadding = pick(point.pointPadding, seriesPointPadding), + // We calculate the point padding of the midpoints to + // preserve the angles of the shape. + midPointPadding = pointPadding * + Math.abs(x2 - x1) / Math.abs(y3 - y2), xPointPadding = xAxis.reversed ? + -midPointPadding : midPointPadding, yPointPadding = yAxis.reversed ? + -pointPadding : pointPadding; + // Shift y-values for every second grid column + // We have to reverse the shift for reversed y-axes + if (point.x % 2) { + yShift = Math.abs(y3 - y1) / 2 * (yAxis.reversed ? -1 : 1); + y1 += yShift; + y2 += yShift; + y3 += yShift; + } + // Set plotX and plotY for use in K-D-Tree and more + point.plotX = point.clientX = x2; + point.plotY = y2; + // Apply point padding to translated coordinates + x1 += xPointPadding; + x3 -= xPointPadding; + y1 -= yPointPadding; + y3 += yPointPadding; + // Store points for halo creation + point.tileEdges = { + x1: x1, x2: x2, x3: x3, y1: y1, y2: y2, y3: y3 + }; + // Set this point's shape parameters + point.shapeType = 'path'; + point.shapeArgs = { + d: [ + ['M', x2, y1], + ['L', x3, y2], + ['L', x2, y3], + ['L', x1, y2], + ['Z'] + ] + }; + }); + series.translateColors(); + } + }, + // Circle shape type. + circle: { + alignDataLabel: H.seriesTypes.scatter.prototype.alignDataLabel, + getSeriesPadding: function (series) { + return tilePaddingFromTileSize(series, 2, 2); + }, + haloPath: function (size) { + return H.seriesTypes.scatter.prototype.pointClass.prototype.haloPath + .call(this, size + (size && this.radius)); + }, + translate: function () { + var series = this, options = series.options, xAxis = series.xAxis, yAxis = series.yAxis, seriesPointPadding = options.pointPadding || 0, yRadius = (options.rowsize || 1) / 2, colsize = (options.colsize || 1), colsizePx, yRadiusPx, xRadiusPx, radius, forceNextRadiusCompute = false; + series.generatePoints(); + series.points.forEach(function (point) { + var x = clamp(Math.round(xAxis.len - + xAxis.translate(point.x, 0, 1, 0, 0)), -xAxis.len, 2 * xAxis.len), y = clamp(Math.round(yAxis.translate(point.y, 0, 1, 0, 0)), -yAxis.len, 2 * yAxis.len), pointPadding = seriesPointPadding, hasPerPointPadding = false; + // If there is point padding defined on a single point, add it + if (typeof point.pointPadding !== 'undefined') { + pointPadding = point.pointPadding; + hasPerPointPadding = true; + forceNextRadiusCompute = true; + } + // Find radius if not found already. + // Use the smallest one (x vs y) to avoid overlap. + // Note that the radius will be recomputed for each series. + // Ideal (max) x radius is dependent on y radius: + /* + * (circle 2) + + * (circle 3) + | yRadiusPx + (circle 1) *-------| + colsizePx + + The distance between circle 1 and 3 (and circle 2 and 3) is + 2r, which is the hypotenuse of the triangle created by + colsizePx and yRadiusPx. If the distance between circle 2 + and circle 1 is less than 2r, we use half of that distance + instead (yRadiusPx). + */ + if (!radius || forceNextRadiusCompute) { + colsizePx = Math.abs(clamp(Math.floor(xAxis.len - + xAxis.translate(point.x + colsize, 0, 1, 0, 0)), -xAxis.len, 2 * xAxis.len) - x); + yRadiusPx = Math.abs(clamp(Math.floor(yAxis.translate(point.y + yRadius, 0, 1, 0, 0)), -yAxis.len, 2 * yAxis.len) - y); + xRadiusPx = Math.floor(Math.sqrt((colsizePx * colsizePx + yRadiusPx * yRadiusPx)) / 2); + radius = Math.min(colsizePx, xRadiusPx, yRadiusPx) - pointPadding; + // If we have per point padding we need to always compute + // the radius for this point and the next. If we used to + // have per point padding but don't anymore, don't force + // compute next radius. + if (forceNextRadiusCompute && !hasPerPointPadding) { + forceNextRadiusCompute = false; + } + } + // Shift y-values for every second grid column. + // Note that we always use the optimal y axis radius for this. + // Also note: We have to reverse the shift for reversed y-axes. + if (point.x % 2) { + y += yRadiusPx * (yAxis.reversed ? -1 : 1); + } + // Set plotX and plotY for use in K-D-Tree and more + point.plotX = point.clientX = x; + point.plotY = y; + // Save radius for halo + point.radius = radius; + // Set this point's shape parameters + point.shapeType = 'circle'; + point.shapeArgs = { + x: x, + y: y, + r: radius + }; + }); + series.translateColors(); + } + }, + // Square shape type. + square: { + alignDataLabel: H.seriesTypes.heatmap.prototype.alignDataLabel, + translate: H.seriesTypes.heatmap.prototype.translate, + getSeriesPadding: function () { + }, + haloPath: H.seriesTypes.heatmap.prototype.pointClass.prototype.haloPath + } +}; +/* eslint-disable no-invalid-this */ +// Extension to add pixel padding for series. Uses getSeriesPixelPadding on each +// series and adds the largest padding required. If no series has this function +// defined, we add nothing. +addEvent(H.Axis, 'afterSetAxisTranslation', function () { + if (this.recomputingForTilemap || this.coll === 'colorAxis') { + return; + } + var axis = this, + // Find which series' padding to use + seriesPadding = axis.series + .map(function (series) { + return series.getSeriesPixelPadding && + series.getSeriesPixelPadding(axis); + }) + .reduce(function (a, b) { + return (a && a.padding) > (b && b.padding) ? + a : + b; + }, void 0) || + { + padding: 0, + axisLengthFactor: 1 + }, lengthPadding = Math.round(seriesPadding.padding * seriesPadding.axisLengthFactor); + // Don't waste time on this if we're not adding extra padding + if (seriesPadding.padding) { + // Recompute translation with new axis length now (minus padding) + axis.len -= lengthPadding; + axis.recomputingForTilemap = true; + axis.setAxisTranslation(); + delete axis.recomputingForTilemap; + axis.minPixelPadding += seriesPadding.padding; + axis.len += lengthPadding; + } +}); +/** + * @private + * @class + * @name Highcharts.seriesTypes.tilemap + * + * @augments Highcharts.Series + */ +seriesType('tilemap', 'heatmap' +/** + * A tilemap series is a type of heatmap where the tile shapes are + * configurable. + * + * @sample highcharts/demo/honeycomb-usa/ + * Honeycomb tilemap, USA + * @sample maps/plotoptions/honeycomb-brazil/ + * Honeycomb tilemap, Brazil + * @sample maps/plotoptions/honeycomb-china/ + * Honeycomb tilemap, China + * @sample maps/plotoptions/honeycomb-europe/ + * Honeycomb tilemap, Europe + * @sample maps/demo/circlemap-africa/ + * Circlemap tilemap, Africa + * @sample maps/demo/diamondmap + * Diamondmap tilemap + * + * @extends plotOptions.heatmap + * @since 6.0.0 + * @excluding jitter, joinBy, shadow, allAreas, mapData, marker, data, + * dataSorting + * @product highcharts highmaps + * @requires modules/tilemap.js + * @optionparent plotOptions.tilemap + */ +, { + // Remove marker from tilemap default options, as it was before + // heatmap refactoring. + marker: null, + states: { + hover: { + halo: { + enabled: true, + size: 2, + opacity: 0.5, + attributes: { + zIndex: 3 + } + } + } + }, + /** + * The padding between points in the tilemap. + * + * @sample maps/plotoptions/tilemap-pointpadding + * Point padding on tiles + */ + pointPadding: 2, + /** + * The column size - how many X axis units each column in the tilemap + * should span. Works as in [Heatmaps](#plotOptions.heatmap.colsize). + * + * @sample {highcharts} maps/demo/heatmap/ + * One day + * @sample {highmaps} maps/demo/heatmap/ + * One day + * + * @type {number} + * @default 1 + * @product highcharts highmaps + * @apioption plotOptions.tilemap.colsize + */ + /** + * The row size - how many Y axis units each tilemap row should span. + * Analogous to [colsize](#plotOptions.tilemap.colsize). + * + * @sample {highcharts} maps/demo/heatmap/ + * 1 by default + * @sample {highmaps} maps/demo/heatmap/ + * 1 by default + * + * @type {number} + * @default 1 + * @product highcharts highmaps + * @apioption plotOptions.tilemap.rowsize + */ + /** + * The shape of the tiles in the tilemap. Possible values are `hexagon`, + * `circle`, `diamond`, and `square`. + * + * @sample maps/demo/circlemap-africa + * Circular tile shapes + * @sample maps/demo/diamondmap + * Diamond tile shapes + * + * @type {Highcharts.TilemapShapeValue} + */ + tileShape: 'hexagon' +}, { + // Use drawPoints, markerAttribs, pointAttribs methods from the old + // heatmap implementation. + // TODO: Consider standarizing heatmap and tilemap into more + // consistent form. + markerAttribs: H.seriesTypes.scatter.prototype.markerAttribs, + pointAttribs: H.seriesTypes.column.prototype.pointAttribs, + // Revert the noop on getSymbol. + getSymbol: H.noop, + drawPoints: function () { + var _this = this; + // In styled mode, use CSS, otherwise the fill used in the style + // sheet will take precedence over the fill attribute. + H.seriesTypes.column.prototype.drawPoints.call(this); + this.points.forEach(function (point) { + point.graphic && + point.graphic[_this.chart.styledMode ? 'css' : 'animate'](_this.colorAttribs(point)); + }); + }, + // Set tile shape object on series + setOptions: function () { + // Call original function + var ret = H.seriesTypes.heatmap.prototype.setOptions.apply(this, Array.prototype.slice.call(arguments)); + this.tileShape = H.tileShapeTypes[ret.tileShape]; + return ret; + }, + // Use the shape's defined data label alignment function + alignDataLabel: function () { + return this.tileShape.alignDataLabel.apply(this, Array.prototype.slice.call(arguments)); + }, + // Get metrics for padding of axis for this series + getSeriesPixelPadding: function (axis) { + var isX = axis.isXAxis, padding = this.tileShape.getSeriesPadding(this), coord1, coord2; + // If the shape type does not require padding, return no-op padding + if (!padding) { + return { + padding: 0, + axisLengthFactor: 1 + }; + } + // Use translate to compute how far outside the points we + // draw, and use this difference as padding. + coord1 = Math.round(axis.translate(isX ? + padding.xPad * 2 : + padding.yPad, 0, 1, 0, 1)); + coord2 = Math.round(axis.translate(isX ? padding.xPad : 0, 0, 1, 0, 1)); + return { + padding: Math.abs(coord1 - coord2) || 0, + // Offset the yAxis length to compensate for shift. Setting the + // length factor to 2 would add the same margin to max as min. + // Now we only add a slight bit of the min margin to max, as we + // don't actually draw outside the max bounds. For the xAxis we + // draw outside on both sides so we add the same margin to min + // and max. + axisLengthFactor: isX ? 2 : 1.1 + }; + }, + // Use translate from tileShape + translate: function () { + return this.tileShape.translate.apply(this, Array.prototype.slice.call(arguments)); + } +}, extend({ + // eslint-disable-next-line valid-jsdoc + /** + * @private + * @function Highcharts.Point#haloPath + * + * @return {Highcharts.SVGElement|Highcharts.SVGPathArray|Array} + */ + haloPath: function () { + return this.series.tileShape.haloPath.apply(this, Array.prototype.slice.call(arguments)); + } +}, H.colorPointMixin)); +/** + * A `tilemap` series. If the [type](#series.tilemap.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.tilemap + * @excluding allAreas, dataParser, dataURL, joinBy, mapData, marker, + * pointRange, shadow, stack, dataSorting + * @product highcharts highmaps + * @requires modules/tilemap.js + * @apioption series.tilemap + */ +/** + * An array of data points for the series. For the `tilemap` series + * type, points can be given in the following ways: + * + * 1. An array of arrays with 3 or 2 values. In this case, the values correspond + * to `x,y,value`. If the first value is a string, it is applied as the name + * of the point, and the `x` value is inferred. The `x` value can also be + * omitted, in which case the inner arrays should be of length 2\. Then the + * `x` value is automatically calculated, either starting at 0 and + * incremented by 1, or from `pointStart` and `pointInterval` given in the + * series options. + * ```js + * data: [ + * [0, 9, 7], + * [1, 10, 4], + * [2, 6, 3] + * ] + * ``` + * + * 2. An array of objects with named values. The objects are point configuration + * objects as seen below. If the total number of data points exceeds the + * series' [turboThreshold](#series.tilemap.turboThreshold), this option is + * not available. + * ```js + * data: [{ + * x: 1, + * y: 3, + * value: 10, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 7, + * value: 10, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * Note that for some [tileShapes](#plotOptions.tilemap.tileShape) the grid + * coordinates are offset. + * + * @sample maps/series/tilemap-gridoffset + * Offset grid coordinates + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|Array<(number|string),number,number>|*>} + * @extends series.heatmap.data + * @excluding marker + * @product highcharts highmaps + * @apioption series.tilemap.data + */ +/** + * The color of the point. In tilemaps the point color is rarely set + * explicitly, as we use the color to denote the `value`. Options for + * this are set in the [colorAxis](#colorAxis) configuration. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highmaps + * @apioption series.tilemap.data.color + */ +/** + * The x coordinate of the point. + * + * Note that for some [tileShapes](#plotOptions.tilemap.tileShape) the grid + * coordinates are offset. + * + * @sample maps/series/tilemap-gridoffset + * Offset grid coordinates + * + * @type {number} + * @product highcharts highmaps + * @apioption series.tilemap.data.x + */ +/** + * The y coordinate of the point. + * + * Note that for some [tileShapes](#plotOptions.tilemap.tileShape) the grid + * coordinates are offset. + * + * @sample maps/series/tilemap-gridoffset + * Offset grid coordinates + * + * @type {number} + * @product highcharts highmaps + * @apioption series.tilemap.data.y + */ +''; // adds doclets above to the transpiled file diff --git a/librerias/gantt/code/es-modules/modules/timeline.src.js b/librerias/gantt/code/es-modules/modules/timeline.src.js new file mode 100644 index 0000000..4bf6ed4 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/timeline.src.js @@ -0,0 +1,591 @@ +/* * + * + * Timeline Series. + * + * (c) 2010-2020 Highsoft AS + * + * Author: Daniel Studencki + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +/** + * Callback JavaScript function to format the data label as a string. Note that + * if a `format` is defined, the format takes precedence and the formatter is + * ignored. + * + * @callback Highcharts.TimelineDataLabelsFormatterCallbackFunction + * + * @param {Highcharts.PointLabelObject|Highcharts.TimelineDataLabelsFormatterContextObject} this + * Data label context to format + * + * @return {number|string|null|undefined} + * Formatted data label text + */ +/** + * @interface Highcharts.TimelineDataLabelsFormatterContextObject + * @extends Highcharts.PointLabelObject + */ /** +* @name Highcharts.TimelineDataLabelsFormatterContextObject#key +* @type {string|undefined} +*/ /** +* @name Highcharts.TimelineDataLabelsFormatterContextObject#point +* @type {Highcharts.Point} +*/ /** +* @name Highcharts.TimelineDataLabelsFormatterContextObject#series +* @type {Highcharts.Series} +*/ +import Point from '../parts/Point.js'; +import LegendSymbolMixin from '../mixins/legend-symbol.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, arrayMax = U.arrayMax, arrayMin = U.arrayMin, defined = U.defined, isNumber = U.isNumber, merge = U.merge, objectEach = U.objectEach, pick = U.pick, seriesType = U.seriesType; +var TrackerMixin = H.TrackerMixin, Series = H.Series, seriesTypes = H.seriesTypes; +/** + * The timeline series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.timeline + * + * @augments Highcharts.Series + */ +seriesType('timeline', 'line', +/** + * The timeline series presents given events along a drawn line. + * + * @sample highcharts/series-timeline/alternate-labels + * Timeline series + * @sample highcharts/series-timeline/inverted + * Inverted timeline + * @sample highcharts/series-timeline/datetime-axis + * With true datetime axis + * + * @extends plotOptions.line + * @since 7.0.0 + * @product highcharts + * @excluding animationLimit, boostThreshold, connectEnds, connectNulls, + * cropThreshold, dashStyle, findNearestPointBy, + * getExtremesFromAll, lineWidth, negativeColor, + * pointInterval, pointIntervalUnit, pointPlacement, + * pointStart, softThreshold, stacking, step, threshold, + * turboThreshold, zoneAxis, zones, dataSorting + * @requires modules/timeline + * @optionparent plotOptions.timeline + */ +{ + colorByPoint: true, + stickyTracking: false, + ignoreHiddenPoint: true, + legendType: 'point', + lineWidth: 4, + tooltip: { + headerFormat: '\u25CF ' + + ' {point.key}
', + pointFormat: '{point.description}' + }, + states: { + hover: { + lineWidthPlus: 0 + } + }, + /** + * @declare Highcharts.TimelineDataLabelsOptionsObject + * + * @private + */ + dataLabels: { + enabled: true, + allowOverlap: true, + /** + * Whether to position data labels alternately. For example, if + * [distance](#plotOptions.timeline.dataLabels.distance) + * is set equal to `100`, then data labels will be positioned + * alternately (on both sides of the point) at a distance of 100px. + * + * @sample {highcharts} highcharts/series-timeline/alternate-disabled + * Alternate disabled + */ + alternate: true, + backgroundColor: '#ffffff', + borderWidth: 1, + borderColor: '#999999', + borderRadius: 3, + color: '#333333', + /** + * The color of the line connecting the data label to the point. + * The default color is the same as the point's color. + * + * In styled mode, the connector stroke is given in the + * `.highcharts-data-label-connector` class. + * + * @sample {highcharts} highcharts/series-timeline/connector-styles + * Custom connector width and color + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.timeline.dataLabels.connectorColor + */ + /** + * The width of the line connecting the data label to the point. + * + * In styled mode, the connector stroke width is given in the + * `.highcharts-data-label-connector` class. + * + * @sample {highcharts} highcharts/series-timeline/connector-styles + * Custom connector width and color + */ + connectorWidth: 1, + /** + * A pixel value defining the distance between the data label and + * the point. Negative numbers puts the label on top of the point. + */ + distance: 100, + // eslint-disable-next-line valid-jsdoc + /** + * @type {Highcharts.TimelineDataLabelsFormatterCallbackFunction} + * @default function () { + * var format; + * + * if (!this.series.chart.styledMode) { + * format = ''; + * } else { + * format = ''; + * } + * format += '' + (this.key || '') + '
' + + * (this.point.label || ''); + * return format; + * } + */ + formatter: function () { + var format; + if (!this.series.chart.styledMode) { + format = ''; + } + else { + format = ''; + } + format += '' + + (this.key || '') + '
' + + (this.point.label || ''); + return format; + }, + style: { + /** @internal */ + textOutline: 'none', + /** @internal */ + fontWeight: 'normal', + /** @internal */ + fontSize: '12px' + }, + /** + * Shadow options for the data label. + * + * @type {boolean|Highcharts.CSSObject} + */ + shadow: false, + /** + * @type {number} + * @apioption plotOptions.timeline.dataLabels.width + */ + verticalAlign: 'middle' + }, + marker: { + enabledThreshold: 0, + symbol: 'square', + radius: 6, + lineWidth: 2, + height: 15 + }, + showInLegend: false, + colorKey: 'x' +}, +/** + * @lends Highcharts.Series# + */ +{ + trackerGroups: ['markerGroup', 'dataLabelsGroup'], + // Use a simple symbol from LegendSymbolMixin + drawLegendSymbol: LegendSymbolMixin.drawRectangle, + // Use a group of trackers from TrackerMixin + drawTracker: TrackerMixin.drawTrackerPoint, + init: function () { + var series = this; + Series.prototype.init.apply(series, arguments); + addEvent(series, 'afterTranslate', function () { + var lastPlotX, closestPointRangePx = Number.MAX_VALUE; + series.points.forEach(function (point) { + // Set the isInside parameter basing also on the real point + // visibility, in order to avoid showing hidden points + // in drawPoints method. + point.isInside = point.isInside && point.visible; + // New way of calculating closestPointRangePx value, which + // respects the real point visibility is needed. + if (point.visible && !point.isNull) { + if (defined(lastPlotX)) { + closestPointRangePx = Math.min(closestPointRangePx, Math.abs(point.plotX - lastPlotX)); + } + lastPlotX = point.plotX; + } + }); + series.closestPointRangePx = closestPointRangePx; + }); + // Distribute data labels before rendering them. Distribution is + // based on the 'dataLabels.distance' and 'dataLabels.alternate' + // property. + addEvent(series, 'drawDataLabels', function () { + // Distribute data labels basing on defined algorithm. + series.distributeDL(); // @todo use this scope for series + }); + addEvent(series, 'afterDrawDataLabels', function () { + var dataLabel; // @todo use this scope for series + // Draw or align connector for each point. + series.points.forEach(function (point) { + dataLabel = point.dataLabel; + if (dataLabel) { + // Within this wrap method is necessary to save the + // current animation params, because the data label + // target position (after animation) is needed to align + // connectors. + dataLabel.animate = function (params) { + if (this.targetPosition) { + this.targetPosition = params; + } + return H.SVGElement.prototype.animate.apply(this, arguments); + }; + // Initialize the targetPosition field within data label + // object. It's necessary because there is need to know + // expected position of specific data label, when + // aligning connectors. This field is overrided inside + // of SVGElement.animate() wrapped method. + if (!dataLabel.targetPosition) { + dataLabel.targetPosition = {}; + } + return point.drawConnector(); + } + }); + }); + addEvent(series.chart, 'afterHideOverlappingLabel', function () { + series.points.forEach(function (p) { + if (p.connector && + p.dataLabel && + p.dataLabel.oldOpacity !== p.dataLabel.newOpacity) { + p.alignConnector(); + } + }); + }); + }, + alignDataLabel: function (point, dataLabel, options, alignTo) { + var series = this, isInverted = series.chart.inverted, visiblePoints = series.visibilityMap.filter(function (point) { + return point; + }), visiblePointsCount = series.visiblePointsCount, pointIndex = visiblePoints.indexOf(point), isFirstOrLast = (!pointIndex || pointIndex === visiblePointsCount - 1), dataLabelsOptions = series.options.dataLabels, userDLOptions = point.userDLOptions || {}, + // Define multiplier which is used to calculate data label + // width. If data labels are alternate, they have two times more + // space to adapt (excepting first and last ones, which has only + // one and half), than in case of placing all data labels side + // by side. + multiplier = dataLabelsOptions.alternate ? + (isFirstOrLast ? 1.5 : 2) : + 1, distance, availableSpace = Math.floor(series.xAxis.len / visiblePointsCount), pad = dataLabel.padding, targetDLWidth, styles; + // Adjust data label width to the currently available space. + if (point.visible) { + distance = Math.abs(userDLOptions.x || point.options.dataLabels.x); + if (isInverted) { + targetDLWidth = ((distance - pad) * 2 - (point.itemHeight / 2)); + styles = { + width: targetDLWidth + 'px', + // Apply ellipsis when data label height is exceeded. + textOverflow: dataLabel.width / targetDLWidth * + dataLabel.height / 2 > availableSpace * multiplier ? + 'ellipsis' : 'none' + }; + } + else { + styles = { + width: (userDLOptions.width || + dataLabelsOptions.width || + availableSpace * multiplier - (pad * 2)) + 'px' + }; + } + dataLabel.css(styles); + if (!series.chart.styledMode) { + dataLabel.shadow(dataLabelsOptions.shadow); + } + } + Series.prototype.alignDataLabel.apply(series, arguments); + }, + processData: function () { + var series = this, visiblePoints = 0, i; + series.visibilityMap = series.getVisibilityMap(); + // Calculate currently visible points. + series.visibilityMap.forEach(function (point) { + if (point) { + visiblePoints++; + } + }); + series.visiblePointsCount = visiblePoints; + for (i = 0; i < series.xData.length; i++) { + series.yData[i] = 1; + } + Series.prototype.processData.call(this, arguments); + return; + }, + getXExtremes: function (xData) { + var series = this, filteredData = xData.filter(function (x, i) { + return series.points[i].isValid() && + series.points[i].visible; + }); + return { + min: arrayMin(filteredData), + max: arrayMax(filteredData) + }; + }, + generatePoints: function () { + var series = this; + Series.prototype.generatePoints.apply(series); + series.points.forEach(function (point, i) { + point.applyOptions({ + x: series.xData[i] + }, series.xData[i]); + }); + }, + getVisibilityMap: function () { + var series = this, map = (series.data.length ? + series.data : series.userOptions.data).map(function (point) { + return (point && + point.visible !== false && + !point.isNull) ? point : false; + }); + return map; + }, + distributeDL: function () { + var series = this, dataLabelsOptions = series.options.dataLabels, options, pointDLOptions, newOptions = {}, visibilityIndex = 1, distance = dataLabelsOptions.distance; + series.points.forEach(function (point) { + if (point.visible && !point.isNull) { + options = point.options; + pointDLOptions = point.options.dataLabels; + if (!series.hasRendered) { + point.userDLOptions = + merge({}, pointDLOptions); + } + newOptions[series.chart.inverted ? 'x' : 'y'] = + dataLabelsOptions.alternate && visibilityIndex % 2 ? + -distance : distance; + options.dataLabels = merge(newOptions, point.userDLOptions); + visibilityIndex++; + } + }); + }, + markerAttribs: function (point, state) { + var series = this, seriesMarkerOptions = series.options.marker, seriesStateOptions, pointMarkerOptions = point.marker || {}, symbol = (pointMarkerOptions.symbol || seriesMarkerOptions.symbol), pointStateOptions, width = pick(pointMarkerOptions.width, seriesMarkerOptions.width, series.closestPointRangePx), height = pick(pointMarkerOptions.height, seriesMarkerOptions.height), radius = 0, attribs; + // Call default markerAttribs method, when the xAxis type + // is set to datetime. + if (series.xAxis.dateTime) { + return seriesTypes.line.prototype.markerAttribs + .call(this, point, state); + } + // Handle hover and select states + if (state) { + seriesStateOptions = + seriesMarkerOptions.states[state] || {}; + pointStateOptions = pointMarkerOptions.states && + pointMarkerOptions.states[state] || {}; + radius = pick(pointStateOptions.radius, seriesStateOptions.radius, radius + (seriesStateOptions.radiusPlus || 0)); + } + point.hasImage = (symbol && symbol.indexOf('url') === 0); + attribs = { + x: Math.floor(point.plotX) - (width / 2) - (radius / 2), + y: point.plotY - (height / 2) - (radius / 2), + width: width + radius, + height: height + radius + }; + return attribs; + }, + bindAxes: function () { + var series = this; + Series.prototype.bindAxes.call(series); + ['xAxis', 'yAxis'].forEach(function (axis) { + // Initially set the linked xAxis type to category. + if (axis === 'xAxis' && !series[axis].userOptions.type) { + series[axis].categories = series[axis].hasNames = true; + } + }); + } +}, +/** + * @lends Highcharts.Point# + */ +{ + init: function () { + var point = Point.prototype.init.apply(this, arguments); + point.name = pick(point.name, 'Event'); + point.y = 1; + return point; + }, + isValid: function () { + return this.options.y !== null; + }, + setVisible: function (vis, redraw) { + var point = this, series = point.series; + redraw = pick(redraw, series.options.ignoreHiddenPoint); + seriesTypes.pie.prototype.pointClass.prototype + .setVisible.call(point, vis, false); + // Process new data + series.processData(); + if (redraw) { + series.chart.redraw(); + } + }, + setState: function () { + var proceed = Series.prototype.pointClass.prototype.setState; + // Prevent triggering the setState method on null points. + if (!this.isNull) { + proceed.apply(this, arguments); + } + }, + getConnectorPath: function () { + var point = this, chart = point.series.chart, xAxisLen = point.series.xAxis.len, inverted = chart.inverted, direction = inverted ? 'x2' : 'y2', dl = point.dataLabel, targetDLPos = dl.targetPosition, coords = { + x1: point.plotX, + y1: point.plotY, + x2: point.plotX, + y2: isNumber(targetDLPos.y) ? targetDLPos.y : dl.y + }, negativeDistance = ((dl.alignAttr || dl)[direction[0]] < + point.series.yAxis.len / 2), path; + // Recalculate coords when the chart is inverted. + if (inverted) { + coords = { + x1: point.plotY, + y1: xAxisLen - point.plotX, + x2: targetDLPos.x || dl.x, + y2: xAxisLen - point.plotX + }; + } + // Subtract data label width or height from expected coordinate so + // that the connector would start from the appropriate edge. + if (negativeDistance) { + coords[direction] += dl[inverted ? 'width' : 'height']; + } + // Change coordinates so that they will be relative to data label. + objectEach(coords, function (_coord, i) { + coords[i] -= (dl.alignAttr || dl)[i[0]]; + }); + path = chart.renderer.crispLine([ + ['M', coords.x1, coords.y1], + ['L', coords.x2, coords.y2] + ], dl.options.connectorWidth); + return path; + }, + drawConnector: function () { + var point = this, series = point.series; + if (!point.connector) { + point.connector = series.chart.renderer + .path(point.getConnectorPath()) + .attr({ + zIndex: -1 + }) + .add(point.dataLabel); + } + if (point.series.chart.isInsidePlot(// #10507 + point.dataLabel.x, point.dataLabel.y)) { + point.alignConnector(); + } + }, + alignConnector: function () { + var point = this, series = point.series, connector = point.connector, dl = point.dataLabel, dlOptions = point.dataLabel.options = merge(series.options.dataLabels, point.options.dataLabels), chart = point.series.chart, bBox = connector.getBBox(), plotPos = { + x: bBox.x + dl.translateX, + y: bBox.y + dl.translateY + }, isVisible; + // Include a half of connector width in order to run animation, + // when connectors are aligned to the plot area edge. + if (chart.inverted) { + plotPos.y -= dl.options.connectorWidth / 2; + } + else { + plotPos.x += dl.options.connectorWidth / 2; + } + isVisible = chart.isInsidePlot(plotPos.x, plotPos.y); + connector[isVisible ? 'animate' : 'attr']({ + d: point.getConnectorPath() + }); + if (!series.chart.styledMode) { + connector.attr({ + stroke: dlOptions.connectorColor || point.color, + 'stroke-width': dlOptions.connectorWidth, + opacity: dl[defined(dl.newOpacity) ? 'newOpacity' : 'opacity'] + }); + } + } +}); +/** + * The `timeline` series. If the [type](#series.timeline.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.timeline + * @excluding animationLimit, boostThreshold, connectEnds, connectNulls, + * cropThreshold, dashStyle, dataParser, dataURL, findNearestPointBy, + * getExtremesFromAll, lineWidth, negativeColor, + * pointInterval, pointIntervalUnit, pointPlacement, pointStart, + * softThreshold, stacking, stack, step, threshold, turboThreshold, + * zoneAxis, zones, dataSorting + * @product highcharts + * @requires modules/timeline + * @apioption series.timeline + */ +/** + * An array of data points for the series. For the `timeline` series type, + * points can be given with three general parameters, `name`, `label`, + * and `description`: + * + * Example: + * + * ```js + * series: [{ + * type: 'timeline', + * data: [{ + * name: 'Jan 2018', + * label: 'Some event label', + * description: 'Description to show in tooltip' + * }] + * }] + * ``` + * If all points additionally have the `x` values, and xAxis type is set to + * `datetime`, then events are laid out on a true time axis, where their + * placement reflects the actual time between them. + * + * @sample {highcharts} highcharts/series-timeline/alternate-labels + * Alternate labels + * @sample {highcharts} highcharts/series-timeline/datetime-axis + * Real time intervals + * + * @type {Array<*>} + * @extends series.line.data + * @excluding marker, y + * @product highcharts + * @apioption series.timeline.data + */ +/** + * The name of event. + * + * @type {string} + * @product highcharts + * @apioption series.timeline.data.name + */ +/** + * The label of event. + * + * @type {string} + * @product highcharts + * @apioption series.timeline.data.label + */ +/** + * The description of event. This description will be shown in tooltip. + * + * @type {string} + * @product highcharts + * @apioption series.timeline.data.description + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/modules/treemap.src.js b/librerias/gantt/code/es-modules/modules/treemap.src.js new file mode 100644 index 0000000..acfcf3b --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/treemap.src.js @@ -0,0 +1,1539 @@ +/* * + * + * (c) 2014-2020 Highsoft AS + * + * Authors: Jon Arild Nygard / Oystein Moseng + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import mixinTreeSeries from '../mixins/tree-series.js'; +import drawPoint from '../mixins/draw-point.js'; +import Color from '../parts/Color.js'; +var color = Color.parse; +import LegendSymbolMixin from '../mixins/legend-symbol.js'; +import Point from '../parts/Point.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, correctFloat = U.correctFloat, defined = U.defined, error = U.error, extend = U.extend, fireEvent = U.fireEvent, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, isString = U.isString, merge = U.merge, objectEach = U.objectEach, pick = U.pick, seriesType = U.seriesType, stableSort = U.stableSort; +import '../parts/Options.js'; +import '../parts/Series.js'; +/* eslint-disable no-invalid-this */ +var AXIS_MAX = 100; +var seriesTypes = H.seriesTypes, noop = H.noop, getColor = mixinTreeSeries.getColor, getLevelOptions = mixinTreeSeries.getLevelOptions, +// @todo Similar to eachObject, this function is likely redundant +isBoolean = function (x) { + return typeof x === 'boolean'; +}, Series = H.Series, +// @todo Similar to recursive, this function is likely redundant +eachObject = function (list, func, context) { + context = context || this; + objectEach(list, function (val, key) { + func.call(context, val, key, list); + }); +}, +// @todo find correct name for this function. +// @todo Similar to reduce, this function is likely redundant +recursive = function (item, func, context) { + var next; + context = context || this; + next = func.call(context, item); + if (next !== false) { + recursive(next, func, context); + } +}, updateRootId = mixinTreeSeries.updateRootId, treemapAxisDefaultValues = false; +/* eslint-enable no-invalid-this */ +/** + * @private + * @class + * @name Highcharts.seriesTypes.treemap + * + * @augments Highcharts.Series + */ +seriesType('treemap', 'scatter' +/** + * A treemap displays hierarchical data using nested rectangles. The data + * can be laid out in varying ways depending on options. + * + * @sample highcharts/demo/treemap-large-dataset/ + * Treemap + * + * @extends plotOptions.scatter + * @excluding dragDrop, marker, jitter, dataSorting + * @product highcharts + * @requires modules/treemap + * @optionparent plotOptions.treemap + */ +, { + /** + * When enabled the user can click on a point which is a parent and + * zoom in on its children. Deprecated and replaced by + * [allowTraversingTree](#plotOptions.treemap.allowTraversingTree). + * + * @sample {highcharts} highcharts/plotoptions/treemap-allowdrilltonode/ + * Enabled + * + * @deprecated + * @type {boolean} + * @default false + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.allowDrillToNode + */ + /** + * When enabled the user can click on a point which is a parent and + * zoom in on its children. + * + * @sample {highcharts} highcharts/plotoptions/treemap-allowtraversingtree/ + * Enabled + * + * @since 7.0.3 + * @product highcharts + */ + allowTraversingTree: false, + animationLimit: 250, + /** + * When the series contains less points than the crop threshold, all + * points are drawn, event if the points fall outside the visible plot + * area at the current zoom. The advantage of drawing all points + * (including markers and columns), is that animation is performed on + * updates. On the other hand, when the series contains more points than + * the crop threshold, the series data is cropped to only contain points + * that fall within the plot area. The advantage of cropping away + * invisible points is to increase performance on large series. + * + * @type {number} + * @default 300 + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.cropThreshold + */ + /** + * Fires on a request for change of root node for the tree, before the + * update is made. An event object is passed to the function, containing + * additional properties `newRootId`, `previousRootId`, `redraw` and + * `trigger`. + * + * @type {function} + * @default undefined + * @sample {highcharts} highcharts/plotoptions/treemap-events-setrootnode/ + * Alert update information on setRootNode event. + * @since 7.0.3 + * @product highcharts + * @apioption plotOptions.treemap.events.setRootNode + */ + /** + * This option decides if the user can interact with the parent nodes + * or just the leaf nodes. When this option is undefined, it will be + * true by default. However when allowTraversingTree is true, then it + * will be false by default. + * + * @sample {highcharts} highcharts/plotoptions/treemap-interactbyleaf-false/ + * False + * @sample {highcharts} highcharts/plotoptions/treemap-interactbyleaf-true-and-allowtraversingtree/ + * InteractByLeaf and allowTraversingTree is true + * + * @type {boolean} + * @since 4.1.2 + * @product highcharts + * @apioption plotOptions.treemap.interactByLeaf + */ + /** + * The sort index of the point inside the treemap level. + * + * @sample {highcharts} highcharts/plotoptions/treemap-sortindex/ + * Sort by years + * + * @type {number} + * @since 4.1.10 + * @product highcharts + * @apioption plotOptions.treemap.sortIndex + */ + /** + * A series specific or series type specific color set to apply instead + * of the global [colors](#colors) when + * [colorByPoint](#plotOptions.treemap.colorByPoint) is true. + * + * @type {Array} + * @since 3.0 + * @product highcharts + * @apioption plotOptions.treemap.colors + */ + /** + * Whether to display this series type or specific series item in the + * legend. + */ + showInLegend: false, + /** + * @ignore-option + */ + marker: false, + /** + * When using automatic point colors pulled from the `options.colors` + * collection, this option determines whether the chart should receive + * one color per series or one color per point. + * + * @see [series colors](#plotOptions.treemap.colors) + * + * @since 2.0 + * @product highcharts + * @apioption plotOptions.treemap.colorByPoint + */ + colorByPoint: false, + /** + * @since 4.1.0 + */ + dataLabels: { + defer: false, + enabled: true, + formatter: function () { + var point = this && this.point ? + this.point : + {}, name = isString(point.name) ? point.name : ''; + return name; + }, + inside: true, + verticalAlign: 'middle' + }, + tooltip: { + headerFormat: '', + pointFormat: '{point.name}: {point.value}
' + }, + /** + * Whether to ignore hidden points when the layout algorithm runs. + * If `false`, hidden points will leave open spaces. + * + * @since 5.0.8 + */ + ignoreHiddenPoint: true, + /** + * This option decides which algorithm is used for setting position + * and dimensions of the points. + * + * @see [How to write your own algorithm](https://www.highcharts.com/docs/chart-and-series-types/treemap) + * + * @sample {highcharts} highcharts/plotoptions/treemap-layoutalgorithm-sliceanddice/ + * SliceAndDice by default + * @sample {highcharts} highcharts/plotoptions/treemap-layoutalgorithm-stripes/ + * Stripes + * @sample {highcharts} highcharts/plotoptions/treemap-layoutalgorithm-squarified/ + * Squarified + * @sample {highcharts} highcharts/plotoptions/treemap-layoutalgorithm-strip/ + * Strip + * + * @since 4.1.0 + * @validvalue ["sliceAndDice", "stripes", "squarified", "strip"] + */ + layoutAlgorithm: 'sliceAndDice', + /** + * Defines which direction the layout algorithm will start drawing. + * + * @since 4.1.0 + * @validvalue ["vertical", "horizontal"] + */ + layoutStartingDirection: 'vertical', + /** + * Enabling this option will make the treemap alternate the drawing + * direction between vertical and horizontal. The next levels starting + * direction will always be the opposite of the previous. + * + * @sample {highcharts} highcharts/plotoptions/treemap-alternatestartingdirection-true/ + * Enabled + * + * @since 4.1.0 + */ + alternateStartingDirection: false, + /** + * Used together with the levels and allowTraversingTree options. When + * set to false the first level visible to be level one, which is + * dynamic when traversing the tree. Otherwise the level will be the + * same as the tree structure. + * + * @since 4.1.0 + */ + levelIsConstant: true, + /** + * Options for the button appearing when drilling down in a treemap. + * Deprecated and replaced by + * [traverseUpButton](#plotOptions.treemap.traverseUpButton). + * + * @deprecated + */ + drillUpButton: { + /** + * The position of the button. + * + * @deprecated + */ + position: { + /** + * Vertical alignment of the button. + * + * @deprecated + * @type {Highcharts.VerticalAlignValue} + * @default top + * @product highcharts + * @apioption plotOptions.treemap.drillUpButton.position.verticalAlign + */ + /** + * Horizontal alignment of the button. + * + * @deprecated + * @type {Highcharts.AlignValue} + */ + align: 'right', + /** + * Horizontal offset of the button. + * + * @deprecated + */ + x: -10, + /** + * Vertical offset of the button. + * + * @deprecated + */ + y: 10 + } + }, + /** + * Options for the button appearing when traversing down in a treemap. + */ + traverseUpButton: { + /** + * The position of the button. + */ + position: { + /** + * Vertical alignment of the button. + * + * @type {Highcharts.VerticalAlignValue} + * @default top + * @product highcharts + * @apioption plotOptions.treemap.traverseUpButton.position.verticalAlign + */ + /** + * Horizontal alignment of the button. + * + * @type {Highcharts.AlignValue} + */ + align: 'right', + /** + * Horizontal offset of the button. + */ + x: -10, + /** + * Vertical offset of the button. + */ + y: 10 + } + }, + /** + * Set options on specific levels. Takes precedence over series options, + * but not point options. + * + * @sample {highcharts} highcharts/plotoptions/treemap-levels/ + * Styling dataLabels and borders + * @sample {highcharts} highcharts/demo/treemap-with-levels/ + * Different layoutAlgorithm + * + * @type {Array<*>} + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.levels + */ + /** + * Can set a `borderColor` on all points which lies on the same level. + * + * @type {Highcharts.ColorString} + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.borderColor + */ + /** + * Set the dash style of the border of all the point which lies on the + * level. See + * [plotOptions.scatter.dashStyle](#plotoptions.scatter.dashstyle) + * for possible options. + * + * @type {Highcharts.DashStyleValue} + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.borderDashStyle + */ + /** + * Can set the borderWidth on all points which lies on the same level. + * + * @type {number} + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.borderWidth + */ + /** + * Can set a color on all points which lies on the same level. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.color + */ + /** + * A configuration object to define how the color of a child varies from + * the parent's color. The variation is distributed among the children + * of node. For example when setting brightness, the brightness change + * will range from the parent's original brightness on the first child, + * to the amount set in the `to` setting on the last node. This allows a + * gradient-like color scheme that sets children out from each other + * while highlighting the grouping on treemaps and sectors on sunburst + * charts. + * + * @sample highcharts/demo/sunburst/ + * Sunburst with color variation + * + * @since 6.0.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.colorVariation + */ + /** + * The key of a color variation. Currently supports `brightness` only. + * + * @type {string} + * @since 6.0.0 + * @product highcharts + * @validvalue ["brightness"] + * @apioption plotOptions.treemap.levels.colorVariation.key + */ + /** + * The ending value of a color variation. The last sibling will receive + * this value. + * + * @type {number} + * @since 6.0.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.colorVariation.to + */ + /** + * Can set the options of dataLabels on each point which lies on the + * level. + * [plotOptions.treemap.dataLabels](#plotOptions.treemap.dataLabels) for + * possible values. + * + * @extends plotOptions.treemap.dataLabels + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.dataLabels + */ + /** + * Can set the layoutAlgorithm option on a specific level. + * + * @type {string} + * @since 4.1.0 + * @product highcharts + * @validvalue ["sliceAndDice", "stripes", "squarified", "strip"] + * @apioption plotOptions.treemap.levels.layoutAlgorithm + */ + /** + * Can set the layoutStartingDirection option on a specific level. + * + * @type {string} + * @since 4.1.0 + * @product highcharts + * @validvalue ["vertical", "horizontal"] + * @apioption plotOptions.treemap.levels.layoutStartingDirection + */ + /** + * Decides which level takes effect from the options set in the levels + * object. + * + * @sample {highcharts} highcharts/plotoptions/treemap-levels/ + * Styling of both levels + * + * @type {number} + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.level + */ + // Presentational options + /** + * The color of the border surrounding each tree map item. + * + * @type {Highcharts.ColorString} + */ + borderColor: '#e6e6e6', + /** + * The width of the border surrounding each tree map item. + */ + borderWidth: 1, + colorKey: 'colorValue', + /** + * The opacity of a point in treemap. When a point has children, the + * visibility of the children is determined by the opacity. + * + * @since 4.2.4 + */ + opacity: 0.15, + /** + * A wrapper object for all the series options in specific states. + * + * @extends plotOptions.heatmap.states + */ + states: { + /** + * Options for the hovered series + * + * @extends plotOptions.heatmap.states.hover + * @excluding halo + */ + hover: { + /** + * The border color for the hovered state. + */ + borderColor: '#999999', + /** + * Brightness for the hovered point. Defaults to 0 if the + * heatmap series is loaded first, otherwise 0.1. + * + * @type {number} + * @default undefined + */ + brightness: seriesTypes.heatmap ? 0 : 0.1, + /** + * @extends plotOptions.heatmap.states.hover.halo + */ + halo: false, + /** + * The opacity of a point in treemap. When a point has children, + * the visibility of the children is determined by the opacity. + * + * @since 4.2.4 + */ + opacity: 0.75, + /** + * The shadow option for hovered state. + */ + shadow: false + } + } + // Prototype members +}, { + pointArrayMap: ['value'], + directTouch: true, + optionalAxis: 'colorAxis', + getSymbol: noop, + parallelArrays: ['x', 'y', 'value', 'colorValue'], + colorKey: 'colorValue', + trackerGroups: ['group', 'dataLabelsGroup'], + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Creates an object map from parent id to childrens index. + * + * @private + * @function Highcharts.Series#getListOfParents + * + * @param {Highcharts.SeriesTreemapDataOptions} [data] + * List of points set in options. + * + * @param {Array} [existingIds] + * List of all point ids. + * + * @return {object} + * Map from parent id to children index in data. + */ + getListOfParents: function (data, existingIds) { + var arr = isArray(data) ? data : [], ids = isArray(existingIds) ? existingIds : [], listOfParents = arr.reduce(function (prev, curr, i) { + var parent = pick(curr.parent, ''); + if (typeof prev[parent] === 'undefined') { + prev[parent] = []; + } + prev[parent].push(i); + return prev; + }, { + '': [] // Root of tree + }); + // If parent does not exist, hoist parent to root of tree. + eachObject(listOfParents, function (children, parent, list) { + if ((parent !== '') && (ids.indexOf(parent) === -1)) { + children.forEach(function (child) { + list[''].push(child); + }); + delete list[parent]; + } + }); + return listOfParents; + }, + // Creates a tree structured object from the series points + getTree: function () { + var series = this, allIds = this.data.map(function (d) { + return d.id; + }), parentList = series.getListOfParents(this.data, allIds); + series.nodeMap = []; + return series.buildNode('', -1, 0, parentList, null); + }, + // Define hasData function for non-cartesian series. + // Returns true if the series has points at all. + hasData: function () { + return !!this.processedXData.length; // != 0 + }, + init: function (chart, options) { + var series = this, colorMapSeriesMixin = H.colorMapSeriesMixin; + // If color series logic is loaded, add some properties + if (colorMapSeriesMixin) { + this.colorAttribs = colorMapSeriesMixin.colorAttribs; + } + // Handle deprecated options. + series.eventsToUnbind.push(addEvent(series, 'setOptions', function (event) { + var options = event.userOptions; + if (defined(options.allowDrillToNode) && + !defined(options.allowTraversingTree)) { + options.allowTraversingTree = options.allowDrillToNode; + delete options.allowDrillToNode; + } + if (defined(options.drillUpButton) && + !defined(options.traverseUpButton)) { + options.traverseUpButton = options.drillUpButton; + delete options.drillUpButton; + } + })); + Series.prototype.init.call(series, chart, options); + if (series.options.allowTraversingTree) { + series.eventsToUnbind.push(addEvent(series, 'click', series.onClickDrillToNode)); + } + }, + buildNode: function (id, i, level, list, parent) { + var series = this, children = [], point = series.points[i], height = 0, node, child; + // Actions + ((list[id] || [])).forEach(function (i) { + child = series.buildNode(series.points[i].id, i, (level + 1), list, id); + height = Math.max(child.height + 1, height); + children.push(child); + }); + node = { + id: id, + i: i, + children: children, + height: height, + level: level, + parent: parent, + visible: false // @todo move this to better location + }; + series.nodeMap[node.id] = node; + if (point) { + point.node = node; + } + return node; + }, + setTreeValues: function (tree) { + var series = this, options = series.options, idRoot = series.rootNode, mapIdToNode = series.nodeMap, nodeRoot = mapIdToNode[idRoot], levelIsConstant = (isBoolean(options.levelIsConstant) ? + options.levelIsConstant : + true), childrenTotal = 0, children = [], val, point = series.points[tree.i]; + // First give the children some values + tree.children.forEach(function (child) { + child = series.setTreeValues(child); + children.push(child); + if (!child.ignore) { + childrenTotal += child.val; + } + }); + // Sort the children + stableSort(children, function (a, b) { + return a.sortIndex - b.sortIndex; + }); + // Set the values + val = pick(point && point.options.value, childrenTotal); + if (point) { + point.value = val; + } + extend(tree, { + children: children, + childrenTotal: childrenTotal, + // Ignore this node if point is not visible + ignore: !(pick(point && point.visible, true) && (val > 0)), + isLeaf: tree.visible && !childrenTotal, + levelDynamic: (tree.level - (levelIsConstant ? 0 : nodeRoot.level)), + name: pick(point && point.name, ''), + sortIndex: pick(point && point.sortIndex, -val), + val: val + }); + return tree; + }, + /** + * Recursive function which calculates the area for all children of a + * node. + * + * @private + * @function Highcharts.Series#calculateChildrenAreas + * + * @param {object} node + * The node which is parent to the children. + * + * @param {object} area + * The rectangular area of the parent. + */ + calculateChildrenAreas: function (parent, area) { + var series = this, options = series.options, mapOptionsToLevel = series.mapOptionsToLevel, level = mapOptionsToLevel[parent.level + 1], algorithm = pick((series[(level && level.layoutAlgorithm)] && + level.layoutAlgorithm), options.layoutAlgorithm), alternate = options.alternateStartingDirection, childrenValues = [], children; + // Collect all children which should be included + children = parent.children.filter(function (n) { + return !n.ignore; + }); + if (level && level.layoutStartingDirection) { + area.direction = level.layoutStartingDirection === 'vertical' ? + 0 : + 1; + } + childrenValues = series[algorithm](area, children); + children.forEach(function (child, index) { + var values = childrenValues[index]; + child.values = merge(values, { + val: child.childrenTotal, + direction: (alternate ? 1 - area.direction : area.direction) + }); + child.pointValues = merge(values, { + x: (values.x / series.axisRatio), + // Flip y-values to avoid visual regression with csvCoord in + // Axis.translate at setPointValues. #12488 + y: AXIS_MAX - values.y - values.height, + width: (values.width / series.axisRatio) + }); + // If node has children, then call method recursively + if (child.children.length) { + series.calculateChildrenAreas(child, child.values); + } + }); + }, + setPointValues: function () { + var series = this; + var points = series.points, xAxis = series.xAxis, yAxis = series.yAxis; + var styledMode = series.chart.styledMode; + // Get the crisp correction in classic mode. For this to work in + // styled mode, we would need to first add the shape (without x, + // y, width and height), then read the rendered stroke width + // using point.graphic.strokeWidth(), then modify and apply the + // shapeArgs. This applies also to column series, but the + // downside is performance and code complexity. + var getCrispCorrection = function (point) { return (styledMode ? + 0 : + ((series.pointAttribs(point)['stroke-width'] || 0) % 2) / 2); }; + points.forEach(function (point) { + var _a = point.node, values = _a.pointValues, visible = _a.visible; + // Points which is ignored, have no values. + if (values && visible) { + var height = values.height, width = values.width, x = values.x, y = values.y; + var crispCorr = getCrispCorrection(point); + var x1 = Math.round(xAxis.toPixels(x, true)) - crispCorr; + var x2 = Math.round(xAxis.toPixels(x + width, true)) - crispCorr; + var y1 = Math.round(yAxis.toPixels(y, true)) - crispCorr; + var y2 = Math.round(yAxis.toPixels(y + height, true)) - crispCorr; + // Set point values + point.shapeArgs = { + x: Math.min(x1, x2), + y: Math.min(y1, y2), + width: Math.abs(x2 - x1), + height: Math.abs(y2 - y1) + }; + point.plotX = + point.shapeArgs.x + (point.shapeArgs.width / 2); + point.plotY = + point.shapeArgs.y + (point.shapeArgs.height / 2); + } + else { + // Reset visibility + delete point.plotX; + delete point.plotY; + } + }); + }, + // Set the node's color recursively, from the parent down. + setColorRecursive: function (node, parentColor, colorIndex, index, siblings) { + var series = this, chart = series && series.chart, colors = chart && chart.options && chart.options.colors, colorInfo, point; + if (node) { + colorInfo = getColor(node, { + colors: colors, + index: index, + mapOptionsToLevel: series.mapOptionsToLevel, + parentColor: parentColor, + parentColorIndex: colorIndex, + series: series, + siblings: siblings + }); + point = series.points[node.i]; + if (point) { + point.color = colorInfo.color; + point.colorIndex = colorInfo.colorIndex; + } + // Do it all again with the children + (node.children || []).forEach(function (child, i) { + series.setColorRecursive(child, colorInfo.color, colorInfo.colorIndex, i, node.children.length); + }); + } + }, + algorithmGroup: function (h, w, d, p) { + this.height = h; + this.width = w; + this.plot = p; + this.direction = d; + this.startDirection = d; + this.total = 0; + this.nW = 0; + this.lW = 0; + this.nH = 0; + this.lH = 0; + this.elArr = []; + this.lP = { + total: 0, + lH: 0, + nH: 0, + lW: 0, + nW: 0, + nR: 0, + lR: 0, + aspectRatio: function (w, h) { + return Math.max((w / h), (h / w)); + } + }; + this.addElement = function (el) { + this.lP.total = this.elArr[this.elArr.length - 1]; + this.total = this.total + el; + if (this.direction === 0) { + // Calculate last point old aspect ratio + this.lW = this.nW; + this.lP.lH = this.lP.total / this.lW; + this.lP.lR = this.lP.aspectRatio(this.lW, this.lP.lH); + // Calculate last point new aspect ratio + this.nW = this.total / this.height; + this.lP.nH = this.lP.total / this.nW; + this.lP.nR = this.lP.aspectRatio(this.nW, this.lP.nH); + } + else { + // Calculate last point old aspect ratio + this.lH = this.nH; + this.lP.lW = this.lP.total / this.lH; + this.lP.lR = this.lP.aspectRatio(this.lP.lW, this.lH); + // Calculate last point new aspect ratio + this.nH = this.total / this.width; + this.lP.nW = this.lP.total / this.nH; + this.lP.nR = this.lP.aspectRatio(this.lP.nW, this.nH); + } + this.elArr.push(el); + }; + this.reset = function () { + this.nW = 0; + this.lW = 0; + this.elArr = []; + this.total = 0; + }; + }, + algorithmCalcPoints: function (directionChange, last, group, childrenArea) { + var pX, pY, pW, pH, gW = group.lW, gH = group.lH, plot = group.plot, keep, i = 0, end = group.elArr.length - 1; + if (last) { + gW = group.nW; + gH = group.nH; + } + else { + keep = group.elArr[group.elArr.length - 1]; + } + group.elArr.forEach(function (p) { + if (last || (i < end)) { + if (group.direction === 0) { + pX = plot.x; + pY = plot.y; + pW = gW; + pH = p / pW; + } + else { + pX = plot.x; + pY = plot.y; + pH = gH; + pW = p / pH; + } + childrenArea.push({ + x: pX, + y: pY, + width: pW, + height: correctFloat(pH) + }); + if (group.direction === 0) { + plot.y = plot.y + pH; + } + else { + plot.x = plot.x + pW; + } + } + i = i + 1; + }); + // Reset variables + group.reset(); + if (group.direction === 0) { + group.width = group.width - gW; + } + else { + group.height = group.height - gH; + } + plot.y = plot.parent.y + (plot.parent.height - group.height); + plot.x = plot.parent.x + (plot.parent.width - group.width); + if (directionChange) { + group.direction = 1 - group.direction; + } + // If not last, then add uncalculated element + if (!last) { + group.addElement(keep); + } + }, + algorithmLowAspectRatio: function (directionChange, parent, children) { + var childrenArea = [], series = this, pTot, plot = { + x: parent.x, + y: parent.y, + parent: parent + }, direction = parent.direction, i = 0, end = children.length - 1, group = new this.algorithmGroup(// eslint-disable-line new-cap + parent.height, parent.width, direction, plot); + // Loop through and calculate all areas + children.forEach(function (child) { + pTot = + (parent.width * parent.height) * (child.val / parent.val); + group.addElement(pTot); + if (group.lP.nR > group.lP.lR) { + series.algorithmCalcPoints(directionChange, false, group, childrenArea, plot // @todo no supported + ); + } + // If last child, then calculate all remaining areas + if (i === end) { + series.algorithmCalcPoints(directionChange, true, group, childrenArea, plot // @todo not supported + ); + } + i = i + 1; + }); + return childrenArea; + }, + algorithmFill: function (directionChange, parent, children) { + var childrenArea = [], pTot, direction = parent.direction, x = parent.x, y = parent.y, width = parent.width, height = parent.height, pX, pY, pW, pH; + children.forEach(function (child) { + pTot = + (parent.width * parent.height) * (child.val / parent.val); + pX = x; + pY = y; + if (direction === 0) { + pH = height; + pW = pTot / pH; + width = width - pW; + x = x + pW; + } + else { + pW = width; + pH = pTot / pW; + height = height - pH; + y = y + pH; + } + childrenArea.push({ + x: pX, + y: pY, + width: pW, + height: pH + }); + if (directionChange) { + direction = 1 - direction; + } + }); + return childrenArea; + }, + strip: function (parent, children) { + return this.algorithmLowAspectRatio(false, parent, children); + }, + squarified: function (parent, children) { + return this.algorithmLowAspectRatio(true, parent, children); + }, + sliceAndDice: function (parent, children) { + return this.algorithmFill(true, parent, children); + }, + stripes: function (parent, children) { + return this.algorithmFill(false, parent, children); + }, + translate: function () { + var series = this, options = series.options, + // NOTE: updateRootId modifies series. + rootId = updateRootId(series), rootNode, pointValues, seriesArea, tree, val; + // Call prototype function + Series.prototype.translate.call(series); + // @todo Only if series.isDirtyData is true + tree = series.tree = series.getTree(); + rootNode = series.nodeMap[rootId]; + series.renderTraverseUpButton(rootId); + series.mapOptionsToLevel = getLevelOptions({ + from: rootNode.level + 1, + levels: options.levels, + to: tree.height, + defaults: { + levelIsConstant: series.options.levelIsConstant, + colorByPoint: options.colorByPoint + } + }); + if (rootId !== '' && + (!rootNode || !rootNode.children.length)) { + series.setRootNode('', false); + rootId = series.rootNode; + rootNode = series.nodeMap[rootId]; + } + // Parents of the root node is by default visible + recursive(series.nodeMap[series.rootNode], function (node) { + var next = false, p = node.parent; + node.visible = true; + if (p || p === '') { + next = series.nodeMap[p]; + } + return next; + }); + // Children of the root node is by default visible + recursive(series.nodeMap[series.rootNode].children, function (children) { + var next = false; + children.forEach(function (child) { + child.visible = true; + if (child.children.length) { + next = (next || []).concat(child.children); + } + }); + return next; + }); + series.setTreeValues(tree); + // Calculate plotting values. + series.axisRatio = (series.xAxis.len / series.yAxis.len); + series.nodeMap[''].pointValues = pointValues = { + x: 0, + y: 0, + width: AXIS_MAX, + height: AXIS_MAX + }; + series.nodeMap[''].values = seriesArea = merge(pointValues, { + width: (pointValues.width * series.axisRatio), + direction: (options.layoutStartingDirection === 'vertical' ? 0 : 1), + val: tree.val + }); + series.calculateChildrenAreas(tree, seriesArea); + // Logic for point colors + if (!series.colorAxis && + !options.colorByPoint) { + series.setColorRecursive(series.tree); + } + // Update axis extremes according to the root node. + if (options.allowTraversingTree) { + val = rootNode.pointValues; + series.xAxis.setExtremes(val.x, val.x + val.width, false); + series.yAxis.setExtremes(val.y, val.y + val.height, false); + series.xAxis.setScale(); + series.yAxis.setScale(); + } + // Assign values to points. + series.setPointValues(); + }, + /** + * Extend drawDataLabels with logic to handle custom options related to + * the treemap series: + * + * - Points which is not a leaf node, has dataLabels disabled by + * default. + * + * - Options set on series.levels is merged in. + * + * - Width of the dataLabel is set to match the width of the point + * shape. + * + * @private + * @function Highcharts.Series#drawDataLabels + */ + drawDataLabels: function () { + var series = this, mapOptionsToLevel = series.mapOptionsToLevel, points = series.points.filter(function (n) { + return n.node.visible; + }), options, level; + points.forEach(function (point) { + level = mapOptionsToLevel[point.node.level]; + // Set options to new object to avoid problems with scope + options = { style: {} }; + // If not a leaf, then label should be disabled as default + if (!point.node.isLeaf) { + options.enabled = false; + } + // If options for level exists, include them as well + if (level && level.dataLabels) { + options = merge(options, level.dataLabels); + series._hasPointLabels = true; + } + // Set dataLabel width to the width of the point shape. + if (point.shapeArgs) { + options.style.width = point.shapeArgs.width; + if (point.dataLabel) { + point.dataLabel.css({ + width: point.shapeArgs.width + 'px' + }); + } + } + // Merge custom options with point options + point.dlOptions = merge(options, point.options.dataLabels); + }); + Series.prototype.drawDataLabels.call(this); + }, + // Over the alignment method by setting z index + alignDataLabel: function (point, dataLabel, labelOptions) { + var style = labelOptions.style; + // #8160: Prevent the label from exceeding the point's + // boundaries in treemaps by applying ellipsis overflow. + // The issue was happening when datalabel's text contained a + // long sequence of characters without a whitespace. + if (!defined(style.textOverflow) && + dataLabel.text && + dataLabel.getBBox().width > dataLabel.text.textWidth) { + dataLabel.css({ + textOverflow: 'ellipsis', + // unit (px) is required when useHTML is true + width: style.width += 'px' + }); + } + seriesTypes.column.prototype.alignDataLabel.apply(this, arguments); + if (point.dataLabel) { + // point.node.zIndex could be undefined (#6956) + point.dataLabel.attr({ zIndex: (point.node.zIndex || 0) + 1 }); + } + }, + // Get presentational attributes + pointAttribs: function (point, state) { + var series = this, mapOptionsToLevel = (isObject(series.mapOptionsToLevel) ? + series.mapOptionsToLevel : + {}), level = point && mapOptionsToLevel[point.node.level] || {}, options = this.options, attr, stateOptions = (state && options.states[state]) || {}, className = (point && point.getClassName()) || '', opacity; + // Set attributes by precedence. Point trumps level trumps series. + // Stroke width uses pick because it can be 0. + attr = { + 'stroke': (point && point.borderColor) || + level.borderColor || + stateOptions.borderColor || + options.borderColor, + 'stroke-width': pick(point && point.borderWidth, level.borderWidth, stateOptions.borderWidth, options.borderWidth), + 'dashstyle': (point && point.borderDashStyle) || + level.borderDashStyle || + stateOptions.borderDashStyle || + options.borderDashStyle, + 'fill': (point && point.color) || this.color + }; + // Hide levels above the current view + if (className.indexOf('highcharts-above-level') !== -1) { + attr.fill = 'none'; + attr['stroke-width'] = 0; + // Nodes with children that accept interaction + } + else if (className.indexOf('highcharts-internal-node-interactive') !== -1) { + opacity = pick(stateOptions.opacity, options.opacity); + attr.fill = color(attr.fill).setOpacity(opacity).get(); + attr.cursor = 'pointer'; + // Hide nodes that have children + } + else if (className.indexOf('highcharts-internal-node') !== -1) { + attr.fill = 'none'; + } + else if (state) { + // Brighten and hoist the hover nodes + attr.fill = color(attr.fill) + .brighten(stateOptions.brightness) + .get(); + } + return attr; + }, + // Override drawPoints + drawPoints: function () { + var series = this, chart = series.chart, renderer = chart.renderer, points = series.points, styledMode = chart.styledMode, options = series.options, shadow = styledMode ? {} : options.shadow, borderRadius = options.borderRadius, withinAnimationLimit = chart.pointCount < options.animationLimit, allowTraversingTree = options.allowTraversingTree; + points.forEach(function (point) { + var levelDynamic = point.node.levelDynamic, animate = {}, attr = {}, css = {}, groupKey = 'level-group-' + levelDynamic, hasGraphic = !!point.graphic, shouldAnimate = withinAnimationLimit && hasGraphic, shapeArgs = point.shapeArgs; + // Don't bother with calculate styling if the point is not drawn + if (point.shouldDraw()) { + if (borderRadius) { + attr.r = borderRadius; + } + merge(true, // Extend object + // Which object to extend + shouldAnimate ? animate : attr, + // Add shapeArgs to animate/attr if graphic exists + hasGraphic ? shapeArgs : {}, + // Add style attribs if !styleMode + styledMode ? + {} : + series.pointAttribs(point, (point.selected && 'select'))); + // In styled mode apply point.color. Use CSS, otherwise the + // fill used in the style sheet will take precedence over + // the fill attribute. + if (series.colorAttribs && styledMode) { + // Heatmap is loaded + extend(css, series.colorAttribs(point)); + } + if (!series[groupKey]) { + series[groupKey] = renderer.g(groupKey) + .attr({ + // @todo Set the zIndex based upon the number of + // levels, instead of using 1000 + zIndex: 1000 - levelDynamic + }) + .add(series.group); + series[groupKey].survive = true; + } + } + // Draw the point + point.draw({ + animatableAttribs: animate, + attribs: attr, + css: css, + group: series[groupKey], + renderer: renderer, + shadow: shadow, + shapeArgs: shapeArgs, + shapeType: 'rect' + }); + // If setRootNode is allowed, set a point cursor on clickables & + // add drillId to point + if (allowTraversingTree && point.graphic) { + point.drillId = options.interactByLeaf ? + series.drillToByLeaf(point) : + series.drillToByGroup(point); + } + }); + }, + // Add drilling on the suitable points + onClickDrillToNode: function (event) { + var series = this, point = event.point, drillId = point && point.drillId; + // If a drill id is returned, add click event and cursor. + if (isString(drillId)) { + point.setState(''); // Remove hover + series.setRootNode(drillId, true, { trigger: 'click' }); + } + }, + /** + * Finds the drill id for a parent node. Returns false if point should + * not have a click event. + * + * @private + * @function Highcharts.Series#drillToByGroup + * + * @param {Highcharts.Point} point + * + * @return {boolean|string} + * Drill to id or false when point should not have a click + * event. + */ + drillToByGroup: function (point) { + var series = this, drillId = false; + if ((point.node.level - series.nodeMap[series.rootNode].level) === + 1 && + !point.node.isLeaf) { + drillId = point.id; + } + return drillId; + }, + /** + * Finds the drill id for a leaf node. Returns false if point should not + * have a click event + * + * @private + * @function Highcharts.Series#drillToByLeaf + * + * @param {Highcharts.Point} point + * + * @return {boolean|string} + * Drill to id or false when point should not have a click + * event. + */ + drillToByLeaf: function (point) { + var series = this, drillId = false, nodeParent; + if ((point.node.parent !== series.rootNode) && + point.node.isLeaf) { + nodeParent = point.node; + while (!drillId) { + nodeParent = series.nodeMap[nodeParent.parent]; + if (nodeParent.parent === series.rootNode) { + drillId = nodeParent.id; + } + } + } + return drillId; + }, + drillUp: function () { + var series = this, node = series.nodeMap[series.rootNode]; + if (node && isString(node.parent)) { + series.setRootNode(node.parent, true, { trigger: 'traverseUpButton' }); + } + }, + // TODO remove this function at a suitable version. + drillToNode: function (id, redraw) { + error('WARNING: treemap.drillToNode has been renamed to treemap.' + + 'setRootNode, and will be removed in the next major version.'); + this.setRootNode(id, redraw); + }, + /** + * Sets a new root node for the series. + * + * @private + * @function Highcharts.Series#setRootNode + * + * @param {string} id The id of the new root node. + * @param {boolean} [redraw=true] Wether to redraw the chart or not. + * @param {object} [eventArguments] Arguments to be accessed in + * event handler. + * @param {string} [eventArguments.newRootId] Id of the new root. + * @param {string} [eventArguments.previousRootId] Id of the previous + * root. + * @param {boolean} [eventArguments.redraw] Wether to redraw the + * chart after. + * @param {object} [eventArguments.series] The series to update the root + * of. + * @param {string} [eventArguments.trigger] The action which + * triggered the event. Undefined if the setRootNode is called + * directly. + * @return {void} + * + * @fires Highcharts.Series#event:setRootNode + */ + setRootNode: function (id, redraw, eventArguments) { + var series = this, eventArgs = extend({ + newRootId: id, + previousRootId: series.rootNode, + redraw: pick(redraw, true), + series: series + }, eventArguments); + /** + * The default functionality of the setRootNode event. + * + * @private + * @param {object} args The event arguments. + * @param {string} args.newRootId Id of the new root. + * @param {string} args.previousRootId Id of the previous root. + * @param {boolean} args.redraw Wether to redraw the chart after. + * @param {object} args.series The series to update the root of. + * @param {string} [args.trigger=undefined] The action which + * triggered the event. Undefined if the setRootNode is called + * directly. + * @return {void} + */ + var defaultFn = function (args) { + var series = args.series; + // Store previous and new root ids on the series. + series.idPreviousRoot = args.previousRootId; + series.rootNode = args.newRootId; + // Redraw the chart + series.isDirty = true; // Force redraw + if (args.redraw) { + series.chart.redraw(); + } + }; + // Fire setRootNode event. + fireEvent(series, 'setRootNode', eventArgs, defaultFn); + }, + renderTraverseUpButton: function (rootId) { + var series = this, nodeMap = series.nodeMap, node = nodeMap[rootId], name = node.name, buttonOptions = series.options.traverseUpButton, backText = pick(buttonOptions.text, name, '< Back'), attr, states; + if (rootId === '') { + if (series.drillUpButton) { + series.drillUpButton = + series.drillUpButton.destroy(); + } + } + else if (!this.drillUpButton) { + attr = buttonOptions.theme; + states = attr && attr.states; + this.drillUpButton = this.chart.renderer + .button(backText, null, null, function () { + series.drillUp(); + }, attr, states && states.hover, states && states.select) + .addClass('highcharts-drillup-button') + .attr({ + align: buttonOptions.position.align, + zIndex: 7 + }) + .add() + .align(buttonOptions.position, false, buttonOptions.relativeTo || 'plotBox'); + } + else { + this.drillUpButton.placed = false; + this.drillUpButton.attr({ + text: backText + }) + .align(); + } + }, + buildKDTree: noop, + drawLegendSymbol: LegendSymbolMixin.drawRectangle, + getExtremes: function () { + // Get the extremes from the value data + var _a = Series.prototype.getExtremes + .call(this, this.colorValueData), dataMin = _a.dataMin, dataMax = _a.dataMax; + this.valueMin = dataMin; + this.valueMax = dataMax; + // Get the extremes from the y data + return Series.prototype.getExtremes.call(this); + }, + getExtremesFromAll: true, + /** + * Workaround for `inactive` state. Since `series.opacity` option is + * already reserved, don't use that state at all by disabling + * `inactiveOtherPoints` and not inheriting states by points. + * + * @private + */ + setState: function (state) { + this.options.inactiveOtherPoints = true; + Series.prototype.setState.call(this, state, false); + this.options.inactiveOtherPoints = false; + }, + utils: { + recursive: recursive + } + /* eslint-enable no-invalid-this, valid-jsdoc */ +}, { + draw: drawPoint, + setVisible: seriesTypes.pie.prototype.pointClass.prototype.setVisible, + /* eslint-disable no-invalid-this, valid-jsdoc */ + getClassName: function () { + var className = Point.prototype.getClassName.call(this), series = this.series, options = series.options; + // Above the current level + if (this.node.level <= series.nodeMap[series.rootNode].level) { + className += ' highcharts-above-level'; + } + else if (!this.node.isLeaf && + !pick(options.interactByLeaf, !options.allowTraversingTree)) { + className += ' highcharts-internal-node-interactive'; + } + else if (!this.node.isLeaf) { + className += ' highcharts-internal-node'; + } + return className; + }, + /** + * A tree point is valid if it has han id too, assume it may be a parent + * item. + * + * @private + * @function Highcharts.Point#isValid + */ + isValid: function () { + return this.id || isNumber(this.value); + }, + setState: function (state) { + Point.prototype.setState.call(this, state); + // Graphic does not exist when point is not visible. + if (this.graphic) { + this.graphic.attr({ + zIndex: state === 'hover' ? 1 : 0 + }); + } + }, + shouldDraw: function () { + var point = this; + return isNumber(point.plotY) && point.y !== null; + } +}); +addEvent(H.Series, 'afterBindAxes', function () { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, treeAxis; + if (xAxis && yAxis) { + if (series.is('treemap')) { + treeAxis = { + endOnTick: false, + gridLineWidth: 0, + lineWidth: 0, + min: 0, + dataMin: 0, + minPadding: 0, + max: AXIS_MAX, + dataMax: AXIS_MAX, + maxPadding: 0, + startOnTick: false, + title: null, + tickPositions: [] + }; + extend(yAxis.options, treeAxis); + extend(xAxis.options, treeAxis); + treemapAxisDefaultValues = true; + } + else if (treemapAxisDefaultValues) { + yAxis.setOptions(yAxis.userOptions); + xAxis.setOptions(xAxis.userOptions); + treemapAxisDefaultValues = false; + } + } +}); +/* eslint-enable no-invalid-this, valid-jsdoc */ +/** + * A `treemap` series. If the [type](#series.treemap.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.treemap + * @excluding dataParser, dataURL, stack, dataSorting + * @product highcharts + * @requires modules/treemap + * @apioption series.treemap + */ +/** + * An array of data points for the series. For the `treemap` series + * type, points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `value` options. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.treemap.turboThreshold), + * this option is not available. + * ```js + * data: [{ + * value: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * value: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array} + * @extends series.heatmap.data + * @excluding x, y + * @product highcharts + * @apioption series.treemap.data + */ +/** + * The value of the point, resulting in a relative area of the point + * in the treemap. + * + * @type {number|null} + * @product highcharts + * @apioption series.treemap.data.value + */ +/** + * Serves a purpose only if a `colorAxis` object is defined in the chart + * options. This value will decide which color the point gets from the + * scale of the colorAxis. + * + * @type {number} + * @since 4.1.0 + * @product highcharts + * @apioption series.treemap.data.colorValue + */ +/** + * Only for treemap. Use this option to build a tree structure. The + * value should be the id of the point which is the parent. If no points + * has a matching id, or this option is undefined, then the parent will + * be set to the root. + * + * @sample {highcharts} highcharts/point/parent/ + * Point parent + * @sample {highcharts} highcharts/demo/treemap-with-levels/ + * Example where parent id is not matching + * + * @type {string} + * @since 4.1.0 + * @product highcharts + * @apioption series.treemap.data.parent + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/modules/variable-pie.src.js b/librerias/gantt/code/es-modules/modules/variable-pie.src.js new file mode 100644 index 0000000..37336d6 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/variable-pie.src.js @@ -0,0 +1,373 @@ +/* * + * + * Variable Pie module for Highcharts + * + * (c) 2010-2017 Grzegorz Blachliński + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +/** + * @typedef {"area"|"radius"} Highcharts.VariablePieSizeByValue + */ +import U from '../parts/Utilities.js'; +var arrayMax = U.arrayMax, arrayMin = U.arrayMin, clamp = U.clamp, fireEvent = U.fireEvent, pick = U.pick, seriesType = U.seriesType; +import '../parts/Options.js'; +var pieProto = H.seriesTypes.pie.prototype; +/** + * The variablepie series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.variablepie + * + * @augments Highcharts.Series + */ +seriesType('variablepie', 'pie', +/** + * A variable pie series is a two dimensional series type, where each point + * renders an Y and Z value. Each point is drawn as a pie slice where the + * size (arc) of the slice relates to the Y value and the radius of pie + * slice relates to the Z value. + * + * @sample {highcharts} highcharts/demo/variable-radius-pie/ + * Variable-radius pie chart + * + * @extends plotOptions.pie + * @excluding dragDrop + * @since 6.0.0 + * @product highcharts + * @requires modules/variable-pie.js + * @optionparent plotOptions.variablepie + */ +{ + /** + * The minimum size of the points' radius related to chart's `plotArea`. + * If a number is set, it applies in pixels. + * + * @sample {highcharts} highcharts/variable-radius-pie/min-max-point-size/ + * Example of minPointSize and maxPointSize + * @sample {highcharts} highcharts/variable-radius-pie/min-point-size-100/ + * minPointSize set to 100 + * + * @type {number|string} + * @since 6.0.0 + */ + minPointSize: '10%', + /** + * The maximum size of the points' radius related to chart's `plotArea`. + * If a number is set, it applies in pixels. + * + * @sample {highcharts} highcharts/variable-radius-pie/min-max-point-size/ + * Example of minPointSize and maxPointSize + * + * @type {number|string} + * @since 6.0.0 + */ + maxPointSize: '100%', + /** + * The minimum possible z value for the point's radius calculation. If + * the point's Z value is smaller than zMin, the slice will be drawn + * according to the zMin value. + * + * @sample {highcharts} highcharts/variable-radius-pie/zmin-5/ + * zMin set to 5, smaller z values are treated as 5 + * @sample {highcharts} highcharts/variable-radius-pie/zmin-zmax/ + * Series limited by both zMin and zMax + * + * @type {number} + * @since 6.0.0 + */ + zMin: void 0, + /** + * The maximum possible z value for the point's radius calculation. If + * the point's Z value is bigger than zMax, the slice will be drawn + * according to the zMax value + * + * @sample {highcharts} highcharts/variable-radius-pie/zmin-zmax/ + * Series limited by both zMin and zMax + * + * @type {number} + * @since 6.0.0 + */ + zMax: void 0, + /** + * Whether the pie slice's value should be represented by the area or + * the radius of the slice. Can be either `area` or `radius`. The + * default, `area`, corresponds best to the human perception of the size + * of each pie slice. + * + * @sample {highcharts} highcharts/variable-radius-pie/sizeby/ + * Difference between area and radius sizeBy + * + * @type {Highcharts.VariablePieSizeByValue} + * @since 6.0.0 + */ + sizeBy: 'area', + tooltip: { + pointFormat: '\u25CF {series.name}
Value: {point.y}
Size: {point.z}
' + } +}, { + pointArrayMap: ['y', 'z'], + parallelArrays: ['x', 'y', 'z'], + // It is needed to null series.center on chart redraw. Probably good + // idea will be to add this option in directly in pie series. + redraw: function () { + this.center = null; + pieProto.redraw.call(this, arguments); + }, + // For arrayMin and arrayMax calculations array shouldn't have + // null/undefined/string values. In this case it is needed to check if + // points Z value is a Number. + zValEval: function (zVal) { + if (typeof zVal === 'number' && !isNaN(zVal)) { + return true; + } + return null; + }, + // Before standard translate method for pie chart it is needed to + // calculate min/max radius of each pie slice based on its Z value. + calculateExtremes: function () { + var series = this, chart = series.chart, plotWidth = chart.plotWidth, plotHeight = chart.plotHeight, seriesOptions = series.options, slicingRoom = 2 * (seriesOptions.slicedOffset || 0), zMin, zMax, zData = series.zData, smallestSize = Math.min(plotWidth, plotHeight) - slicingRoom, + // Min and max size of pie slice: + extremes = {}, + // In pie charts size of a pie is changed to make space for + // dataLabels, then series.center is changing. + positions = series.center || series.getCenter(); + ['minPointSize', 'maxPointSize'].forEach(function (prop) { + var length = seriesOptions[prop], isPercent = /%$/.test(length); + length = parseInt(length, 10); + extremes[prop] = isPercent ? + smallestSize * length / 100 : + length * 2; // Because it should be radius, not diameter. + }); + series.minPxSize = positions[3] + extremes.minPointSize; + series.maxPxSize = clamp(positions[2], positions[3] + extremes.minPointSize, extremes.maxPointSize); + if (zData.length) { + zMin = pick(seriesOptions.zMin, arrayMin(zData.filter(series.zValEval))); + zMax = pick(seriesOptions.zMax, arrayMax(zData.filter(series.zValEval))); + this.getRadii(zMin, zMax, series.minPxSize, series.maxPxSize); + } + }, + /* eslint-disable valid-jsdoc */ + /** + * Finding radius of series points based on their Z value and min/max Z + * value for all series. + * + * @private + * @function Highcharts.Series#getRadii + * + * @param {number} zMin + * Min threshold for Z value. If point's Z value is smaller that + * zMin, point will have the smallest possible radius. + * + * @param {number} zMax + * Max threshold for Z value. If point's Z value is bigger that + * zMax, point will have the biggest possible radius. + * + * @param {number} minSize + * Minimal pixel size possible for radius. + * + * @param {numbner} maxSize + * Minimal pixel size possible for radius. + * + * @return {void} + */ + getRadii: function (zMin, zMax, minSize, maxSize) { + var i = 0, pos, zData = this.zData, len = zData.length, radii = [], options = this.options, sizeByArea = options.sizeBy !== 'radius', zRange = zMax - zMin, value, radius; + // Calculate radius for all pie slice's based on their Z values + for (i; i < len; i++) { + // if zData[i] is null/undefined/string we need to take zMin for + // smallest radius. + value = this.zValEval(zData[i]) ? zData[i] : zMin; + if (value <= zMin) { + radius = minSize / 2; + } + else if (value >= zMax) { + radius = maxSize / 2; + } + else { + // Relative size, a number between 0 and 1 + pos = zRange > 0 ? (value - zMin) / zRange : 0.5; + if (sizeByArea) { + pos = Math.sqrt(pos); + } + radius = Math.ceil(minSize + pos * (maxSize - minSize)) / 2; + } + radii.push(radius); + } + this.radii = radii; + }, + /* eslint-enable valid-jsdoc */ + // Extend translate by updating radius for each pie slice instead of + // using one global radius. + translate: function (positions) { + this.generatePoints(); + var series = this, cumulative = 0, precision = 1000, // issue #172 + options = series.options, slicedOffset = options.slicedOffset, connectorOffset = slicedOffset + (options.borderWidth || 0), finalConnectorOffset, start, end, angle, startAngle = options.startAngle || 0, startAngleRad = Math.PI / 180 * (startAngle - 90), endAngleRad = Math.PI / 180 * (pick(options.endAngle, startAngle + 360) - 90), circ = endAngleRad - startAngleRad, // 2 * Math.PI, + points = series.points, + // the x component of the radius vector for a given point + radiusX, radiusY, labelDistance = options.dataLabels.distance, ignoreHiddenPoint = options.ignoreHiddenPoint, i, len = points.length, point, pointRadii, pointRadiusX, pointRadiusY; + series.startAngleRad = startAngleRad; + series.endAngleRad = endAngleRad; + // Use calculateExtremes to get series.radii array. + series.calculateExtremes(); + // Get positions - either an integer or a percentage string must be + // given. If positions are passed as a parameter, we're in a + // recursive loop for adjusting space for data labels. + if (!positions) { + series.center = positions = series.getCenter(); + } + // Calculate the geometry for each point + for (i = 0; i < len; i++) { + point = points[i]; + pointRadii = series.radii[i]; + // Used for distance calculation for specific point. + point.labelDistance = pick(point.options.dataLabels && + point.options.dataLabels.distance, labelDistance); + // Saved for later dataLabels distance calculation. + series.maxLabelDistance = Math.max(series.maxLabelDistance || 0, point.labelDistance); + // set start and end angle + start = startAngleRad + (cumulative * circ); + if (!ignoreHiddenPoint || point.visible) { + cumulative += point.percentage / 100; + } + end = startAngleRad + (cumulative * circ); + // set the shape + point.shapeType = 'arc'; + point.shapeArgs = { + x: positions[0], + y: positions[1], + r: pointRadii, + innerR: positions[3] / 2, + start: Math.round(start * precision) / precision, + end: Math.round(end * precision) / precision + }; + // The angle must stay within -90 and 270 (#2645) + angle = (end + start) / 2; + if (angle > 1.5 * Math.PI) { + angle -= 2 * Math.PI; + } + else if (angle < -Math.PI / 2) { + angle += 2 * Math.PI; + } + // Center for the sliced out slice + point.slicedTranslation = { + translateX: Math.round(Math.cos(angle) * slicedOffset), + translateY: Math.round(Math.sin(angle) * slicedOffset) + }; + // set the anchor point for tooltips + radiusX = Math.cos(angle) * positions[2] / 2; + radiusY = Math.sin(angle) * positions[2] / 2; + pointRadiusX = Math.cos(angle) * pointRadii; + pointRadiusY = Math.sin(angle) * pointRadii; + point.tooltipPos = [ + positions[0] + radiusX * 0.7, + positions[1] + radiusY * 0.7 + ]; + point.half = angle < -Math.PI / 2 || angle > Math.PI / 2 ? + 1 : + 0; + point.angle = angle; + // Set the anchor point for data labels. Use point.labelDistance + // instead of labelDistance // #1174 + // finalConnectorOffset - not override connectorOffset value. + finalConnectorOffset = Math.min(connectorOffset, point.labelDistance / 5); // #1678 + point.labelPosition = { + natural: { + // initial position of the data label - it's utilized + // for finding the final position for the label + x: positions[0] + pointRadiusX + + Math.cos(angle) * point.labelDistance, + y: positions[1] + pointRadiusY + + Math.sin(angle) * point.labelDistance + }, + 'final': { + // used for generating connector path - + // initialized later in drawDataLabels function + // x: undefined, + // y: undefined + }, + // left - pie on the left side of the data label + // right - pie on the right side of the data label + alignment: point.half ? 'right' : 'left', + connectorPosition: { + breakAt: { + x: positions[0] + pointRadiusX + + Math.cos(angle) * finalConnectorOffset, + y: positions[1] + pointRadiusY + + Math.sin(angle) * finalConnectorOffset + }, + touchingSliceAt: { + x: positions[0] + pointRadiusX, + y: positions[1] + pointRadiusY + } + } + }; + } + fireEvent(series, 'afterTranslate'); + } +}); +/** + * A `variablepie` series. If the [type](#series.variablepie.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.variablepie + * @excluding dataParser, dataURL, stack, xAxis, yAxis, dataSorting + * @product highcharts + * @requires modules/variable-pie.js + * @apioption series.variablepie + */ +/** + * An array of data points for the series. For the `variablepie` series type, + * points can be given in the following ways: + * + * 1. An array of arrays with 2 values. In this case, the numerical values will + * be interpreted as `y, z` options. Example: + * ```js + * data: [ + * [40, 75], + * [50, 50], + * [60, 40] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.variablepie.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * y: 1, + * z: 4, + * name: "Point2", + * color: "#00FF00" + * }, { + * y: 7, + * z: 10, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|*>} + * @extends series.pie.data + * @excluding marker, x + * @product highcharts + * @apioption series.variablepie.data + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/modules/variwide.src.js b/librerias/gantt/code/es-modules/modules/variwide.src.js new file mode 100644 index 0000000..de609b9 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/variwide.src.js @@ -0,0 +1,311 @@ +/* * + * + * Highcharts variwide module + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, isNumber = U.isNumber, pick = U.pick, seriesType = U.seriesType, wrap = U.wrap; +import '../parts/AreaSeries.js'; +var seriesTypes = H.seriesTypes; +/** + * @private + * @class + * @name Highcharts.seriesTypes.variwide + * + * @augments Highcharts.Series + */ +seriesType('variwide', 'column' +/** + * A variwide chart (related to marimekko chart) is a column chart with a + * variable width expressing a third dimension. + * + * @sample {highcharts} highcharts/demo/variwide/ + * Variwide chart + * @sample {highcharts} highcharts/series-variwide/inverted/ + * Inverted variwide chart + * @sample {highcharts} highcharts/series-variwide/datetime/ + * Variwide columns on a datetime axis + * + * @extends plotOptions.column + * @since 6.0.0 + * @product highcharts + * @excluding boostThreshold, crisp, depth, edgeColor, edgeWidth, + * groupZPadding + * @requires modules/variwide + * @optionparent plotOptions.variwide + */ +, { + /** + * In a variwide chart, the point padding is 0 in order to express the + * horizontal stacking of items. + */ + pointPadding: 0, + /** + * In a variwide chart, the group padding is 0 in order to express the + * horizontal stacking of items. + */ + groupPadding: 0 +}, { + irregularWidths: true, + pointArrayMap: ['y', 'z'], + parallelArrays: ['x', 'y', 'z'], + processData: function (force) { + this.totalZ = 0; + this.relZ = []; + seriesTypes.column.prototype.processData.call(this, force); + (this.xAxis.reversed ? + this.zData.slice().reverse() : + this.zData).forEach(function (z, i) { + this.relZ[i] = this.totalZ; + this.totalZ += z; + }, this); + if (this.xAxis.categories) { + this.xAxis.variwide = true; + this.xAxis.zData = this.zData; // Used for label rank + } + return; + }, + /* eslint-disable valid-jsdoc */ + /** + * Translate an x value inside a given category index into the distorted + * axis translation. + * + * @private + * @function Highcharts.Series#postTranslate + * + * @param {number} index + * The category index + * + * @param {number} x + * The X pixel position in undistorted axis pixels + * + * @param {Highcharts.Point} point + * For crosshairWidth for every point + * + * @return {number} + * Distorted X position + */ + postTranslate: function (index, x, point) { + var axis = this.xAxis, relZ = this.relZ, i = axis.reversed ? relZ.length - index : index, goRight = axis.reversed ? -1 : 1, len = axis.len, totalZ = this.totalZ, linearSlotLeft = i / relZ.length * len, linearSlotRight = (i + goRight) / relZ.length * len, slotLeft = (pick(relZ[i], totalZ) / totalZ) * len, slotRight = (pick(relZ[i + goRight], totalZ) / totalZ) * len, xInsideLinearSlot = x - linearSlotLeft, ret; + // Set crosshairWidth for every point (#8173) + if (point) { + point.crosshairWidth = slotRight - slotLeft; + } + ret = slotLeft + + xInsideLinearSlot * (slotRight - slotLeft) / + (linearSlotRight - linearSlotLeft); + return ret; + }, + /* eslint-enable valid-jsdoc */ + // Extend translation by distoring X position based on Z. + translate: function () { + // Temporarily disable crisping when computing original shapeArgs + var crispOption = this.options.crisp, xAxis = this.xAxis; + this.options.crisp = false; + seriesTypes.column.prototype.translate.call(this); + // Reset option + this.options.crisp = crispOption; + var inverted = this.chart.inverted, crisp = this.borderWidth % 2 / 2; + // Distort the points to reflect z dimension + this.points.forEach(function (point, i) { + var left, right; + if (xAxis.variwide) { + left = this.postTranslate(i, point.shapeArgs.x, point); + right = this.postTranslate(i, point.shapeArgs.x + + point.shapeArgs.width); + // For linear or datetime axes, the variwide column should + // start with X and extend Z units, without modifying the + // axis. + } + else { + left = point.plotX; + right = xAxis.translate(point.x + point.z, 0, 0, 0, 1); + } + if (this.options.crisp) { + left = Math.round(left) - crisp; + right = Math.round(right) - crisp; + } + point.shapeArgs.x = left; + point.shapeArgs.width = Math.max(right - left, 1); + // Crosshair position (#8083) + point.plotX = (left + right) / 2; + // Adjust the tooltip position + if (!inverted) { + point.tooltipPos[0] = + point.shapeArgs.x + + point.shapeArgs.width / 2; + } + else { + point.tooltipPos[1] = + xAxis.len - point.shapeArgs.x - + point.shapeArgs.width / 2; + } + }, this); + if (this.options.stacking) { + this.correctStackLabels(); + } + }, + // Function that corrects stack labels positions + correctStackLabels: function () { + var series = this, options = series.options, yAxis = series.yAxis, pointStack, pointWidth, stack, xValue; + series.points.forEach(function (point) { + xValue = point.x; + pointWidth = point.shapeArgs.width; + stack = yAxis.stacking.stacks[(series.negStacks && + point.y < (options.startFromThreshold ? + 0 : + options.threshold) ? + '-' : + '') + series.stackKey]; + if (stack) { + pointStack = stack[xValue]; + if (pointStack && !point.isNull) { + pointStack.setOffset(-(pointWidth / 2) || 0, pointWidth || 0, void 0, void 0, point.plotX); + } + } + }); + } + // Point functions +}, { + isValid: function () { + return isNumber(this.y) && isNumber(this.z); + } +}); +H.Tick.prototype.postTranslate = function (xy, xOrY, index) { + var axis = this.axis, pos = xy[xOrY] - axis.pos; + if (!axis.horiz) { + pos = axis.len - pos; + } + pos = axis.series[0].postTranslate(index, pos); + if (!axis.horiz) { + pos = axis.len - pos; + } + xy[xOrY] = axis.pos + pos; +}; +/* eslint-disable no-invalid-this */ +// Same width as the category (#8083) +addEvent(H.Axis, 'afterDrawCrosshair', function (e) { + if (this.variwide && this.cross) { + this.cross.attr('stroke-width', (e.point && e.point.crosshairWidth)); + } +}); +// On a vertical axis, apply anti-collision logic to the labels. +addEvent(H.Axis, 'afterRender', function () { + var axis = this; + if (!this.horiz && this.variwide) { + this.chart.labelCollectors.push(function () { + return axis.tickPositions + .filter(function (pos) { + return axis.ticks[pos].label; + }) + .map(function (pos, i) { + var label = axis.ticks[pos].label; + label.labelrank = axis.zData[i]; + return label; + }); + }); + } +}); +addEvent(H.Tick, 'afterGetPosition', function (e) { + var axis = this.axis, xOrY = axis.horiz ? 'x' : 'y'; + if (axis.variwide) { + this[xOrY + 'Orig'] = e.pos[xOrY]; + this.postTranslate(e.pos, xOrY, this.pos); + } +}); +wrap(H.Tick.prototype, 'getLabelPosition', function (proceed, x, y, label, horiz, labelOptions, tickmarkOffset, index) { + var args = Array.prototype.slice.call(arguments, 1), xy, xOrY = horiz ? 'x' : 'y'; + // Replace the x with the original x + if (this.axis.variwide && + typeof this[xOrY + 'Orig'] === 'number') { + args[horiz ? 0 : 1] = this[xOrY + 'Orig']; + } + xy = proceed.apply(this, args); + // Post-translate + if (this.axis.variwide && this.axis.categories) { + this.postTranslate(xy, xOrY, index); + } + return xy; +}); +/** + * A `variwide` series. If the [type](#series.variwide.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.variwide + * @product highcharts + * @requires modules/variwide + * @apioption series.variwide + */ +/** + * An array of data points for the series. For the `variwide` series type, + * points can be given in the following ways: + * + * 1. An array of arrays with 3 or 2 values. In this case, the values correspond + * to `x,y,z`. If the first value is a string, it is applied as the name of + * the point, and the `x` value is inferred. The `x` value can also be + * omitted, in which case the inner arrays should be of length 2. Then the + * `x` value is automatically calculated, either starting at 0 and + * incremented by 1, or from `pointStart` and `pointInterval` given in the + * series options. + * ```js + * data: [ + * [0, 1, 2], + * [1, 5, 5], + * [2, 0, 2] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.variwide.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 1, + * z: 1, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 5, + * z: 4, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|Array<(number|string),number,number>|*>} + * @extends series.line.data + * @excluding marker + * @product highcharts + * @apioption series.variwide.data + */ +/** + * The relative width for each column. On a category axis, the widths are + * distributed so they sum up to the X axis length. On linear and datetime axes, + * the columns will be laid out from the X value and Z units along the axis. + * + * @type {number} + * @product highcharts + * @apioption series.variwide.data.z + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/modules/vector.src.js b/librerias/gantt/code/es-modules/modules/vector.src.js new file mode 100644 index 0000000..6858193 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/vector.src.js @@ -0,0 +1,325 @@ +/* * + * + * Vector plot series module + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var animObject = U.animObject, arrayMax = U.arrayMax, pick = U.pick, seriesType = U.seriesType; +/** + * The vector series class. + * + * @private + * @class + * @name Highcharts.seriesTypes.vector + * + * @augments Highcharts.seriesTypes.scatter + */ +seriesType('vector', 'scatter' +/** + * A vector plot is a type of cartesian chart where each point has an X and + * Y position, a length and a direction. Vectors are drawn as arrows. + * + * @sample {highcharts|highstock} highcharts/demo/vector-plot/ + * Vector pot + * + * @since 6.0.0 + * @extends plotOptions.scatter + * @excluding boostThreshold, marker, connectEnds, connectNulls, + * cropThreshold, dashStyle, dragDrop, gapSize, gapUnit, + * dataGrouping, linecap, shadow, stacking, step, jitter + * @product highcharts highstock + * @requires modules/vector + * @optionparent plotOptions.vector + */ +, { + /** + * The line width for each vector arrow. + */ + lineWidth: 2, + /** + * @ignore + */ + marker: null, + /** + * What part of the vector it should be rotated around. Can be one of + * `start`, `center` and `end`. When `start`, the vectors will start + * from the given [x, y] position, and when `end` the vectors will end + * in the [x, y] position. + * + * @sample highcharts/plotoptions/vector-rotationorigin-start/ + * Rotate from start + * + * @validvalue ["start", "center", "end"] + */ + rotationOrigin: 'center', + states: { + hover: { + /** + * Additonal line width for the vector errors when they are + * hovered. + */ + lineWidthPlus: 1 + } + }, + tooltip: { + /** + * @default [{point.x}, {point.y}] Length: {point.length} Direction: {point.direction}° + */ + pointFormat: '[{point.x}, {point.y}]
Length: {point.length}
Direction: {point.direction}\u00B0
' + }, + /** + * Maximum length of the arrows in the vector plot. The individual arrow + * length is computed between 0 and this value. + */ + vectorLength: 20 +}, { + pointArrayMap: ['y', 'length', 'direction'], + parallelArrays: ['x', 'y', 'length', 'direction'], + /* eslint-disable valid-jsdoc */ + /** + * Get presentational attributes. + * + * @private + * @function Highcharts.seriesTypes.vector#pointAttribs + * + * @param {Highcharts.Point} point + * + * @param {string} [state] + * + * @return {Highcharts.SVGAttributes} + */ + pointAttribs: function (point, state) { + var options = this.options, stroke = point.color || this.color, strokeWidth = this.options.lineWidth; + if (state) { + stroke = options.states[state].color || stroke; + strokeWidth = + (options.states[state].lineWidth || strokeWidth) + + (options.states[state].lineWidthPlus || 0); + } + return { + 'stroke': stroke, + 'stroke-width': strokeWidth + }; + }, + /** + * @ignore + * @deprecated + * @function Highcharts.seriesTypes.vector#markerAttribs + */ + markerAttribs: H.noop, + /** + * @ignore + * @deprecated + * @function Highcharts.seriesTypes.vector#getSymbol + */ + getSymbol: H.noop, + /** + * Create a single arrow. It is later rotated around the zero + * centerpoint. + * + * @private + * @function Highcharts.seriesTypes.vector#arrow + * + * @param {Highcharts.Point} point + * + * @return {Highcharts.SVGPathArray} + */ + arrow: function (point) { + var path, fraction = point.length / this.lengthMax, u = fraction * this.options.vectorLength / 20, o = { + start: 10 * u, + center: 0, + end: -10 * u + }[this.options.rotationOrigin] || 0; + // The stem and the arrow head. Draw the arrow first with rotation + // 0, which is the arrow pointing down (vector from north to south). + path = [ + ['M', 0, 7 * u + o], + ['L', -1.5 * u, 7 * u + o], + ['L', 0, 10 * u + o], + ['L', 1.5 * u, 7 * u + o], + ['L', 0, 7 * u + o], + ['L', 0, -10 * u + o] // top + ]; + return path; + }, + /** + * @private + * @function Highcharts.seriesTypes.vector#translate + */ + translate: function () { + H.Series.prototype.translate.call(this); + this.lengthMax = arrayMax(this.lengthData); + }, + /** + * @private + * @function Highcharts.seriesTypes.vector#drawPoints + */ + drawPoints: function () { + var chart = this.chart; + this.points.forEach(function (point) { + var plotX = point.plotX, plotY = point.plotY; + if (this.options.clip === false || + chart.isInsidePlot(plotX, plotY, chart.inverted)) { + if (!point.graphic) { + point.graphic = this.chart.renderer + .path() + .add(this.markerGroup) + .addClass('highcharts-point ' + + 'highcharts-color-' + + pick(point.colorIndex, point.series.colorIndex)); + } + point.graphic + .attr({ + d: this.arrow(point), + translateX: plotX, + translateY: plotY, + rotation: point.direction + }); + if (!this.chart.styledMode) { + point.graphic + .attr(this.pointAttribs(point)); + } + } + else if (point.graphic) { + point.graphic = point.graphic.destroy(); + } + }, this); + }, + /** + * @ignore + * @deprecated + * @function Highcharts.seriesTypes.vector#drawGraph + */ + drawGraph: H.noop, + /* + drawLegendSymbol: function (legend, item) { + var options = legend.options, + symbolHeight = legend.symbolHeight, + square = options.squareSymbol, + symbolWidth = square ? symbolHeight : legend.symbolWidth, + path = this.arrow.call({ + lengthMax: 1, + options: { + vectorLength: symbolWidth + } + }, { + length: 1 + }); + + item.legendLine = this.chart.renderer.path(path) + .addClass('highcharts-point') + .attr({ + zIndex: 3, + translateY: symbolWidth / 2, + rotation: 270, + 'stroke-width': 1, + 'stroke': 'black' + }).add(item.legendGroup); + + }, + */ + /** + * Fade in the arrows on initializing series. + * + * @private + * @function Highcharts.seriesTypes.vector#animate + * + * @param {boolean} [init] + */ + animate: function (init) { + if (init) { + this.markerGroup.attr({ + opacity: 0.01 + }); + } + else { + this.markerGroup.animate({ + opacity: 1 + }, animObject(this.options.animation)); + } + } + /* eslint-enable valid-jsdoc */ +}); +/** + * A `vector` series. If the [type](#series.vector.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.vector + * @excluding dataParser, dataURL + * @product highcharts highstock + * @requires modules/vector + * @apioption series.vector + */ +/** + * An array of data points for the series. For the `vector` series type, + * points can be given in the following ways: + * + * 1. An array of arrays with 4 values. In this case, the values correspond to + * to `x,y,length,direction`. If the first value is a string, it is applied + * as the name of the point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 0, 10, 90], + * [0, 1, 5, 180], + * [1, 1, 2, 270] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.area.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 0, + * y: 0, + * name: "Point2", + * length: 10, + * direction: 90 + * }, { + * x: 1, + * y: 1, + * name: "Point1", + * direction: 270 + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|*>} + * @extends series.line.data + * @product highcharts highstock + * @apioption series.vector.data + */ +/** + * The length of the vector. The rendered length will relate to the + * `vectorLength` setting. + * + * @type {number} + * @product highcharts highstock + * @apioption series.vector.data.length + */ +/** + * The vector direction in degrees, where 0 is north (pointing towards south). + * + * @type {number} + * @product highcharts highstock + * @apioption series.vector.data.direction + */ +''; // adds doclets above to the transpiled file diff --git a/librerias/gantt/code/es-modules/modules/venn.src.js b/librerias/gantt/code/es-modules/modules/venn.src.js new file mode 100644 index 0000000..7544699 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/venn.src.js @@ -0,0 +1,1023 @@ +/* * + * + * Experimental Highcharts module which enables visualization of a Venn + * diagram. + * + * (c) 2016-2020 Highsoft AS + * Authors: Jon Arild Nygard + * + * Layout algorithm by Ben Frederickson: + * https://www.benfrederickson.com/better-venn-diagrams/ + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import draw from '../mixins/draw-point.js'; +import geometry from '../mixins/geometry.js'; +import geometryCirclesModule from '../mixins/geometry-circles.js'; +var getAreaOfCircle = geometryCirclesModule.getAreaOfCircle, getAreaOfIntersectionBetweenCircles = geometryCirclesModule.getAreaOfIntersectionBetweenCircles, getCircleCircleIntersection = geometryCirclesModule.getCircleCircleIntersection, getCirclesIntersectionPolygon = geometryCirclesModule.getCirclesIntersectionPolygon, getOverlapBetweenCirclesByDistance = geometryCirclesModule.getOverlapBetweenCircles, isCircle1CompletelyOverlappingCircle2 = geometryCirclesModule.isCircle1CompletelyOverlappingCircle2, isPointInsideAllCircles = geometryCirclesModule.isPointInsideAllCircles, isPointInsideCircle = geometryCirclesModule.isPointInsideCircle, isPointOutsideAllCircles = geometryCirclesModule.isPointOutsideAllCircles; +import nelderMeadModule from '../mixins/nelder-mead.js'; +// TODO: replace with individual imports +var nelderMead = nelderMeadModule.nelderMead; +import Color from '../parts/Color.js'; +var color = Color.parse; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, animObject = U.animObject, extend = U.extend, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, isString = U.isString, merge = U.merge, seriesType = U.seriesType; +import '../parts/Series.js'; +var getCenterOfPoints = geometry.getCenterOfPoints, getDistanceBetweenPoints = geometry.getDistanceBetweenPoints, seriesTypes = H.seriesTypes; +var objectValues = function objectValues(obj) { + return Object.keys(obj).map(function (x) { + return obj[x]; + }); +}; +/** + * Calculates the area of overlap between a list of circles. + * @private + * @todo add support for calculating overlap between more than 2 circles. + * @param {Array} circles + * List of circles with their given positions. + * @return {number} + * Returns the area of overlap between all the circles. + */ +var getOverlapBetweenCircles = function getOverlapBetweenCircles(circles) { + var overlap = 0; + // When there is only two circles we can find the overlap by using their + // radiuses and the distance between them. + if (circles.length === 2) { + var circle1 = circles[0]; + var circle2 = circles[1]; + overlap = getOverlapBetweenCirclesByDistance(circle1.r, circle2.r, getDistanceBetweenPoints(circle1, circle2)); + } + return overlap; +}; +/** + * Calculates the difference between the desired overlap and the actual overlap + * between two circles. + * @private + * @param {Dictionary} mapOfIdToCircle + * Map from id to circle. + * @param {Array} relations + * List of relations to calculate the loss of. + * @return {number} + * Returns the loss between positions of the circles for the given relations. + */ +var loss = function loss(mapOfIdToCircle, relations) { + var precision = 10e10; + // Iterate all the relations and calculate their individual loss. + return relations.reduce(function (totalLoss, relation) { + var loss = 0; + if (relation.sets.length > 1) { + var wantedOverlap = relation.value; + // Calculate the actual overlap between the sets. + var actualOverlap = getOverlapBetweenCircles( + // Get the circles for the given sets. + relation.sets.map(function (set) { + return mapOfIdToCircle[set]; + })); + var diff = wantedOverlap - actualOverlap; + loss = Math.round((diff * diff) * precision) / precision; + } + // Add calculated loss to the sum. + return totalLoss + loss; + }, 0); +}; +/** + * Finds the root of a given function. The root is the input value needed for + * a function to return 0. + * + * See https://en.wikipedia.org/wiki/Bisection_method#Algorithm + * + * TODO: Add unit tests. + * + * @param {Function} f + * The function to find the root of. + * @param {number} a + * The lowest number in the search range. + * @param {number} b + * The highest number in the search range. + * @param {number} [tolerance=1e-10] + * The allowed difference between the returned value and root. + * @param {number} [maxIterations=100] + * The maximum iterations allowed. + * @return {number} + * Root number. + */ +var bisect = function bisect(f, a, b, tolerance, maxIterations) { + var fA = f(a), fB = f(b), nMax = maxIterations || 100, tol = tolerance || 1e-10, delta = b - a, n = 1, x, fX; + if (a >= b) { + throw new Error('a must be smaller than b.'); + } + else if (fA * fB > 0) { + throw new Error('f(a) and f(b) must have opposite signs.'); + } + if (fA === 0) { + x = a; + } + else if (fB === 0) { + x = b; + } + else { + while (n++ <= nMax && fX !== 0 && delta > tol) { + delta = (b - a) / 2; + x = a + delta; + fX = f(x); + // Update low and high for next search interval. + if (fA * fX > 0) { + a = x; + } + else { + b = x; + } + } + } + return x; +}; +/** + * Uses the bisection method to make a best guess of the ideal distance between + * two circles too get the desired overlap. + * Currently there is no known formula to calculate the distance from the area + * of overlap, which makes the bisection method preferred. + * @private + * @param {number} r1 + * Radius of the first circle. + * @param {number} r2 + * Radiues of the second circle. + * @param {number} overlap + * The wanted overlap between the two circles. + * @return {number} + * Returns the distance needed to get the wanted overlap between the two + * circles. + */ +var getDistanceBetweenCirclesByOverlap = function getDistanceBetweenCirclesByOverlap(r1, r2, overlap) { + var maxDistance = r1 + r2, distance; + if (overlap <= 0) { + // If overlap is below or equal to zero, then there is no overlap. + distance = maxDistance; + } + else if (getAreaOfCircle(r1 < r2 ? r1 : r2) <= overlap) { + // When area of overlap is larger than the area of the smallest circle, + // then it is completely overlapping. + distance = 0; + } + else { + distance = bisect(function (x) { + var actualOverlap = getOverlapBetweenCirclesByDistance(r1, r2, x); + // Return the differance between wanted and actual overlap. + return overlap - actualOverlap; + }, 0, maxDistance); + } + return distance; +}; +var isSet = function (x) { + return isArray(x.sets) && x.sets.length === 1; +}; +/** + * Calculates a margin for a point based on the iternal and external circles. + * The margin describes if the point is well placed within the internal circles, + * and away from the external + * @private + * @todo add unit tests. + * @param {Highcharts.PositionObject} point + * The point to evaluate. + * @param {Array} internal + * The internal circles. + * @param {Array} external + * The external circles. + * @return {number} + * Returns the margin. + */ +var getMarginFromCircles = function getMarginFromCircles(point, internal, external) { + var margin = internal.reduce(function (margin, circle) { + var m = circle.r - getDistanceBetweenPoints(point, circle); + return (m <= margin) ? m : margin; + }, Number.MAX_VALUE); + margin = external.reduce(function (margin, circle) { + var m = getDistanceBetweenPoints(point, circle) - circle.r; + return (m <= margin) ? m : margin; + }, margin); + return margin; +}; +/** + * Finds the optimal label position by looking for a position that has a low + * distance from the internal circles, and as large possible distane to the + * external circles. + * @private + * @todo Optimize the intial position. + * @todo Add unit tests. + * @param {Array} internal + * Internal circles. + * @param {Array} external + * External circles. + * @return {Highcharts.PositionObject} + * Returns the found position. + */ +var getLabelPosition = function getLabelPosition(internal, external) { + // Get the best label position within the internal circles. + var best = internal.reduce(function (best, circle) { + var d = circle.r / 2; + // Give a set of points with the circle to evaluate as the best label + // position. + return [ + { x: circle.x, y: circle.y }, + { x: circle.x + d, y: circle.y }, + { x: circle.x - d, y: circle.y }, + { x: circle.x, y: circle.y + d }, + { x: circle.x, y: circle.y - d } + ] + // Iterate the given points and return the one with the largest + // margin. + .reduce(function (best, point) { + var margin = getMarginFromCircles(point, internal, external); + // If the margin better than the current best, then update best. + if (best.margin < margin) { + best.point = point; + best.margin = margin; + } + return best; + }, best); + }, { + point: void 0, + margin: -Number.MAX_VALUE + }).point; + // Use nelder mead to optimize the initial label position. + var optimal = nelderMead(function (p) { + return -(getMarginFromCircles({ x: p[0], y: p[1] }, internal, external)); + }, [best.x, best.y]); + // Update best to be the point which was found to have the best margin. + best = { + x: optimal[0], + y: optimal[1] + }; + if (!(isPointInsideAllCircles(best, internal) && + isPointOutsideAllCircles(best, external))) { + // If point was either outside one of the internal, or inside one of the + // external, then it was invalid and should use a fallback. + if (internal.length > 1) { + best = getCenterOfPoints(getCirclesIntersectionPolygon(internal)); + } + else { + best = { + x: internal[0].x, + y: internal[0].y + }; + } + } + // Return the best point. + return best; +}; +/** + * Finds the available width for a label, by taking the label position and + * finding the largest distance, which is inside all internal circles, and + * outside all external circles. + * + * @private + * @param {Highcharts.PositionObject} pos + * The x and y coordinate of the label. + * @param {Array} internal + * Internal circles. + * @param {Array} external + * External circles. + * @return {number} + * Returns available width for the label. + */ +var getLabelWidth = function getLabelWidth(pos, internal, external) { + var radius = internal.reduce(function (min, circle) { + return Math.min(circle.r, min); + }, Infinity), + // Filter out external circles that are completely overlapping. + filteredExternals = external.filter(function (circle) { + return !isPointInsideCircle(pos, circle); + }); + var findDistance = function (maxDistance, direction) { + return bisect(function (x) { + var testPos = { + x: pos.x + (direction * x), + y: pos.y + }, isValid = (isPointInsideAllCircles(testPos, internal) && + isPointOutsideAllCircles(testPos, filteredExternals)); + // If the position is valid, then we want to move towards the max + // distance. If not, then we want to away from the max distance. + return -(maxDistance - x) + (isValid ? 0 : Number.MAX_VALUE); + }, 0, maxDistance); + }; + // Find the smallest distance of left and right. + return Math.min(findDistance(radius, -1), findDistance(radius, 1)) * 2; +}; +/** + * Calulates data label values for a given relations object. + * + * @private + * @todo add unit tests + * @param {Highcharts.VennRelationObject} relation A relations object. + * @param {Array} setRelations The list of + * relations that is a set. + * @return {Highcharts.VennLabelValuesObject} + * Returns an object containing position and width of the label. + */ +function getLabelValues(relation, setRelations) { + var sets = relation.sets; + // Create a list of internal and external circles. + var data = setRelations.reduce(function (data, set) { + // If the set exists in this relation, then it is internal, + // otherwise it will be external. + var isInternal = sets.indexOf(set.sets[0]) > -1; + var property = isInternal ? 'internal' : 'external'; + // Add the circle to the list. + data[property].push(set.circle); + return data; + }, { + internal: [], + external: [] + }); + // Filter out external circles that are completely overlapping all internal + data.external = data.external.filter(function (externalCircle) { + return data.internal.some(function (internalCircle) { + return !isCircle1CompletelyOverlappingCircle2(externalCircle, internalCircle); + }); + }); + // Calulate the label position. + var position = getLabelPosition(data.internal, data.external); + // Calculate the label width + var width = getLabelWidth(position, data.internal, data.external); + return { + position: position, + width: width + }; +} +/** + * Takes an array of relations and adds the properties `totalOverlap` and + * `overlapping` to each set. The property `totalOverlap` is the sum of value + * for each relation where this set is included. The property `overlapping` is + * a map of how much this set is overlapping another set. + * NOTE: This algorithm ignores relations consisting of more than 2 sets. + * @private + * @param {Array} relations + * The list of relations that should be sorted. + * @return {Array} + * Returns the modified input relations with added properties `totalOverlap` and + * `overlapping`. + */ +var addOverlapToSets = function addOverlapToSets(relations) { + // Calculate the amount of overlap per set. + var mapOfIdToProps = relations + // Filter out relations consisting of 2 sets. + .filter(function (relation) { + return relation.sets.length === 2; + }) + // Sum up the amount of overlap for each set. + .reduce(function (map, relation) { + var sets = relation.sets; + sets.forEach(function (set, i, arr) { + if (!isObject(map[set])) { + map[set] = { + overlapping: {}, + totalOverlap: 0 + }; + } + map[set].totalOverlap += relation.value; + map[set].overlapping[arr[1 - i]] = relation.value; + }); + return map; + }, {}); + relations + // Filter out single sets + .filter(isSet) + // Extend the set with the calculated properties. + .forEach(function (set) { + var properties = mapOfIdToProps[set.sets[0]]; + extend(set, properties); + }); + // Returns the modified relations. + return relations; +}; +/** + * Takes two sets and finds the one with the largest total overlap. + * @private + * @param {object} a The first set to compare. + * @param {object} b The second set to compare. + * @return {number} Returns 0 if a and b are equal, <0 if a is greater, >0 if b + * is greater. + */ +var sortByTotalOverlap = function sortByTotalOverlap(a, b) { + return b.totalOverlap - a.totalOverlap; +}; +/** + * Uses a greedy approach to position all the sets. Works well with a small + * number of sets, and are in these cases a good choice aesthetically. + * @private + * @param {Array} relations List of the overlap between two or more + * sets, or the size of a single set. + * @return {Array} List of circles and their calculated positions. + */ +var layoutGreedyVenn = function layoutGreedyVenn(relations) { + var positionedSets = [], mapOfIdToCircles = {}; + // Define a circle for each set. + relations + .filter(function (relation) { + return relation.sets.length === 1; + }).forEach(function (relation) { + mapOfIdToCircles[relation.sets[0]] = relation.circle = { + x: Number.MAX_VALUE, + y: Number.MAX_VALUE, + r: Math.sqrt(relation.value / Math.PI) + }; + }); + /** + * Takes a set and updates the position, and add the set to the list of + * positioned sets. + * @private + * @param {object} set + * The set to add to its final position. + * @param {object} coordinates + * The coordinates to position the set at. + * @return {void} + */ + var positionSet = function positionSet(set, coordinates) { + var circle = set.circle; + circle.x = coordinates.x; + circle.y = coordinates.y; + positionedSets.push(set); + }; + // Find overlap between sets. Ignore relations with more then 2 sets. + addOverlapToSets(relations); + // Sort sets by the sum of their size from large to small. + var sortedByOverlap = relations + .filter(isSet) + .sort(sortByTotalOverlap); + // Position the most overlapped set at 0,0. + positionSet(sortedByOverlap.shift(), { x: 0, y: 0 }); + var relationsWithTwoSets = relations.filter(function (x) { + return x.sets.length === 2; + }); + // Iterate and position the remaining sets. + sortedByOverlap.forEach(function (set) { + var circle = set.circle, radius = circle.r, overlapping = set.overlapping; + var bestPosition = positionedSets + .reduce(function (best, positionedSet, i) { + var positionedCircle = positionedSet.circle, overlap = overlapping[positionedSet.sets[0]]; + // Calculate the distance between the sets to get the correct + // overlap + var distance = getDistanceBetweenCirclesByOverlap(radius, positionedCircle.r, overlap); + // Create a list of possible coordinates calculated from + // distance. + var possibleCoordinates = [ + { x: positionedCircle.x + distance, y: positionedCircle.y }, + { x: positionedCircle.x - distance, y: positionedCircle.y }, + { x: positionedCircle.x, y: positionedCircle.y + distance }, + { x: positionedCircle.x, y: positionedCircle.y - distance } + ]; + // If there are more circles overlapping, then add the + // intersection points as possible positions. + positionedSets.slice(i + 1).forEach(function (positionedSet2) { + var positionedCircle2 = positionedSet2.circle, overlap2 = overlapping[positionedSet2.sets[0]], distance2 = getDistanceBetweenCirclesByOverlap(radius, positionedCircle2.r, overlap2); + // Add intersections to list of coordinates. + possibleCoordinates = possibleCoordinates.concat(getCircleCircleIntersection({ + x: positionedCircle.x, + y: positionedCircle.y, + r: distance + }, { + x: positionedCircle2.x, + y: positionedCircle2.y, + r: distance2 + })); + }); + // Iterate all suggested coordinates and find the best one. + possibleCoordinates.forEach(function (coordinates) { + circle.x = coordinates.x; + circle.y = coordinates.y; + // Calculate loss for the suggested coordinates. + var currentLoss = loss(mapOfIdToCircles, relationsWithTwoSets); + // If the loss is better, then use these new coordinates. + if (currentLoss < best.loss) { + best.loss = currentLoss; + best.coordinates = coordinates; + } + }); + // Return resulting coordinates. + return best; + }, { + loss: Number.MAX_VALUE, + coordinates: void 0 + }); + // Add the set to its final position. + positionSet(set, bestPosition.coordinates); + }); + // Return the positions of each set. + return mapOfIdToCircles; +}; +/** + * Calculates the positions, and the label values of all the sets in the venn + * diagram. + * + * @private + * @todo Add support for constrained MDS. + * @param {Array} relations + * List of the overlap between two or more sets, or the size of a single set. + * @return {Highcharts.Dictionary<*>} + * List of circles and their calculated positions. + */ +function layout(relations) { + var mapOfIdToShape = {}; + var mapOfIdToLabelValues = {}; + // Calculate best initial positions by using greedy layout. + if (relations.length > 0) { + var mapOfIdToCircles_1 = layoutGreedyVenn(relations); + var setRelations_1 = relations.filter(isSet); + relations + .forEach(function (relation) { + var sets = relation.sets; + var id = sets.join(); + // Get shape from map of circles, or calculate intersection. + var shape = isSet(relation) ? + mapOfIdToCircles_1[id] : + getAreaOfIntersectionBetweenCircles(sets.map(function (set) { + return mapOfIdToCircles_1[set]; + })); + // Calculate label values if the set has a shape + if (shape) { + mapOfIdToShape[id] = shape; + mapOfIdToLabelValues[id] = getLabelValues(relation, setRelations_1); + } + }); + } + return { mapOfIdToShape: mapOfIdToShape, mapOfIdToLabelValues: mapOfIdToLabelValues }; +} +var isValidRelation = function (x) { + var map = {}; + return (isObject(x) && + (isNumber(x.value) && x.value > -1) && + (isArray(x.sets) && x.sets.length > 0) && + !x.sets.some(function (set) { + var invalid = false; + if (!map[set] && isString(set)) { + map[set] = true; + } + else { + invalid = true; + } + return invalid; + })); +}; +var isValidSet = function (x) { + return (isValidRelation(x) && isSet(x) && x.value > 0); +}; +/** + * Prepares the venn data so that it is usable for the layout function. Filter + * out sets, or intersections that includes sets, that are missing in the data + * or has (value < 1). Adds missing relations between sets in the data as + * value = 0. + * @private + * @param {Array} data The raw input data. + * @return {Array} Returns an array of valid venn data. + */ +var processVennData = function processVennData(data) { + var d = isArray(data) ? data : []; + var validSets = d + .reduce(function (arr, x) { + // Check if x is a valid set, and that it is not an duplicate. + if (isValidSet(x) && arr.indexOf(x.sets[0]) === -1) { + arr.push(x.sets[0]); + } + return arr; + }, []) + .sort(); + var mapOfIdToRelation = d.reduce(function (mapOfIdToRelation, relation) { + if (isValidRelation(relation) && + !relation.sets.some(function (set) { + return validSets.indexOf(set) === -1; + })) { + mapOfIdToRelation[relation.sets.sort().join()] = + relation; + } + return mapOfIdToRelation; + }, {}); + validSets.reduce(function (combinations, set, i, arr) { + var remaining = arr.slice(i + 1); + remaining.forEach(function (set2) { + combinations.push(set + ',' + set2); + }); + return combinations; + }, []).forEach(function (combination) { + if (!mapOfIdToRelation[combination]) { + var obj = { + sets: combination.split(','), + value: 0 + }; + mapOfIdToRelation[combination] = obj; + } + }); + // Transform map into array. + return objectValues(mapOfIdToRelation); +}; +/** + * Calculates the proper scale to fit the cloud inside the plotting area. + * @private + * @todo add unit test + * @param {number} targetWidth + * Width of target area. + * @param {number} targetHeight + * Height of target area. + * @param {Highcharts.PolygonBoxObject} field + * The playing field. + * @return {Highcharts.Dictionary} + * Returns the value to scale the playing field up to the size of the target + * area, and center of x and y. + */ +var getScale = function getScale(targetWidth, targetHeight, field) { + var height = field.bottom - field.top, // top is smaller than bottom + width = field.right - field.left, scaleX = width > 0 ? 1 / width * targetWidth : 1, scaleY = height > 0 ? 1 / height * targetHeight : 1, adjustX = (field.right + field.left) / 2, adjustY = (field.top + field.bottom) / 2, scale = Math.min(scaleX, scaleY); + return { + scale: scale, + centerX: targetWidth / 2 - adjustX * scale, + centerY: targetHeight / 2 - adjustY * scale + }; +}; +/** + * If a circle is outside a give field, then the boundaries of the field is + * adjusted accordingly. Modifies the field object which is passed as the first + * parameter. + * @private + * @todo NOTE: Copied from wordcloud, can probably be unified. + * @param {Highcharts.PolygonBoxObject} field + * The bounding box of a playing field. + * @param {Highcharts.CircleObject} circle + * The bounding box for a placed point. + * @return {Highcharts.PolygonBoxObject} + * Returns a modified field object. + */ +var updateFieldBoundaries = function updateFieldBoundaries(field, circle) { + var left = circle.x - circle.r, right = circle.x + circle.r, bottom = circle.y + circle.r, top = circle.y - circle.r; + // TODO improve type checking. + if (!isNumber(field.left) || field.left > left) { + field.left = left; + } + if (!isNumber(field.right) || field.right < right) { + field.right = right; + } + if (!isNumber(field.top) || field.top > top) { + field.top = top; + } + if (!isNumber(field.bottom) || field.bottom < bottom) { + field.bottom = bottom; + } + return field; +}; +/** + * A Venn diagram displays all possible logical relations between a collection + * of different sets. The sets are represented by circles, and the relation + * between the sets are displayed by the overlap or lack of overlap between + * them. The venn diagram is a special case of Euler diagrams, which can also + * be displayed by this series type. + * + * @sample {highcharts} highcharts/demo/venn-diagram/ + * Venn diagram + * @sample {highcharts} highcharts/demo/euler-diagram/ + * Euler diagram + * + * @extends plotOptions.scatter + * @excluding connectEnds, connectNulls, cropThreshold, dragDrop, + * findNearestPointBy, getExtremesFromAll, jitter, label, linecap, + * lineWidth, linkedTo, marker, negativeColor, pointInterval, + * pointIntervalUnit, pointPlacement, pointStart, softThreshold, + * stacking, steps, threshold, xAxis, yAxis, zoneAxis, zones, + * dataSorting + * @product highcharts + * @requires modules/venn + * @optionparent plotOptions.venn + */ +var vennOptions = { + borderColor: '#cccccc', + borderDashStyle: 'solid', + borderWidth: 1, + brighten: 0, + clip: false, + colorByPoint: true, + dataLabels: { + enabled: true, + verticalAlign: 'middle', + formatter: function () { + return this.point.name; + } + }, + /** + * @ignore-option + * @private + */ + inactiveOtherPoints: true, + marker: false, + opacity: 0.75, + showInLegend: false, + states: { + /** + * @excluding halo + */ + hover: { + opacity: 1, + borderColor: '#333333' + }, + /** + * @excluding halo + */ + select: { + color: '#cccccc', + borderColor: '#000000', + animation: false + }, + inactive: { + opacity: 0.075 + } + }, + tooltip: { + pointFormat: '{point.name}: {point.value}' + } +}; +var vennSeries = { + isCartesian: false, + axisTypes: [], + directTouch: true, + pointArrayMap: ['value'], + translate: function () { + var chart = this.chart; + this.processedXData = this.xData; + this.generatePoints(); + // Process the data before passing it into the layout function. + var relations = processVennData(this.options.data); + // Calculate the positions of each circle. + var _a = layout(relations), mapOfIdToShape = _a.mapOfIdToShape, mapOfIdToLabelValues = _a.mapOfIdToLabelValues; + // Calculate the scale, and center of the plot area. + var field = Object.keys(mapOfIdToShape) + .filter(function (key) { + var shape = mapOfIdToShape[key]; + return shape && isNumber(shape.r); + }) + .reduce(function (field, key) { + return updateFieldBoundaries(field, mapOfIdToShape[key]); + }, { top: 0, bottom: 0, left: 0, right: 0 }), scaling = getScale(chart.plotWidth, chart.plotHeight, field), scale = scaling.scale, centerX = scaling.centerX, centerY = scaling.centerY; + // Iterate all points and calculate and draw their graphics. + this.points.forEach(function (point) { + var sets = isArray(point.sets) ? point.sets : [], id = sets.join(), shape = mapOfIdToShape[id], shapeArgs, dataLabelValues = mapOfIdToLabelValues[id] || {}, dataLabelWidth = dataLabelValues.width, dataLabelPosition = dataLabelValues.position, dlOptions = point.options && point.options.dataLabels; + if (shape) { + if (shape.r) { + shapeArgs = { + x: centerX + shape.x * scale, + y: centerY + shape.y * scale, + r: shape.r * scale + }; + } + else if (shape.d) { + var d = shape.d; + d.forEach(function (seg) { + if (seg[0] === 'M') { + seg[1] = centerX + seg[1] * scale; + seg[2] = centerY + seg[2] * scale; + } + else if (seg[0] === 'A') { + seg[1] = seg[1] * scale; + seg[2] = seg[2] * scale; + seg[6] = centerX + seg[6] * scale; + seg[7] = centerY + seg[7] * scale; + } + }); + shapeArgs = { d: d }; + } + // Scale the position for the data label. + if (dataLabelPosition) { + dataLabelPosition.x = centerX + dataLabelPosition.x * scale; + dataLabelPosition.y = centerY + dataLabelPosition.y * scale; + } + else { + dataLabelPosition = {}; + } + if (isNumber(dataLabelWidth)) { + dataLabelWidth = Math.round(dataLabelWidth * scale); + } + } + point.shapeArgs = shapeArgs; + // Placement for the data labels + if (dataLabelPosition && shapeArgs) { + point.plotX = dataLabelPosition.x; + point.plotY = dataLabelPosition.y; + } + // Add width for the data label + if (dataLabelWidth && shapeArgs) { + point.dlOptions = merge(true, { + style: { + width: dataLabelWidth + } + }, isObject(dlOptions) && dlOptions); + } + // Set name for usage in tooltip and in data label. + point.name = point.options.name || sets.join('∩'); + }); + }, + /* eslint-disable valid-jsdoc */ + /** + * Draw the graphics for each point. + * @private + */ + drawPoints: function () { + var series = this, + // Series properties + chart = series.chart, group = series.group, points = series.points || [], + // Chart properties + renderer = chart.renderer; + // Iterate all points and calculate and draw their graphics. + points.forEach(function (point) { + var attribs = { + zIndex: isArray(point.sets) ? point.sets.length : 0 + }, shapeArgs = point.shapeArgs; + // Add point attribs + if (!chart.styledMode) { + extend(attribs, series.pointAttribs(point, point.state)); + } + // Draw the point graphic. + point.draw({ + isNew: !point.graphic, + animatableAttribs: shapeArgs, + attribs: attribs, + group: group, + renderer: renderer, + shapeType: shapeArgs && shapeArgs.d ? 'path' : 'circle' + }); + }); + }, + /** + * Calculates the style attributes for a point. The attributes can vary + * depending on the state of the point. + * @private + * @param {Highcharts.Point} point + * The point which will get the resulting attributes. + * @param {string} [state] + * The state of the point. + * @return {Highcharts.SVGAttributes} + * Returns the calculated attributes. + */ + pointAttribs: function (point, state) { + var series = this, seriesOptions = series.options || {}, pointOptions = point && point.options || {}, stateOptions = (state && seriesOptions.states[state]) || {}, options = merge(seriesOptions, { color: point && point.color }, pointOptions, stateOptions); + // Return resulting values for the attributes. + return { + 'fill': color(options.color) + .setOpacity(options.opacity) + .brighten(options.brightness) + .get(), + 'stroke': options.borderColor, + 'stroke-width': options.borderWidth, + 'dashstyle': options.borderDashStyle + }; + }, + /* eslint-enable valid-jsdoc */ + animate: function (init) { + if (!init) { + var series = this, animOptions = animObject(series.options.animation); + series.points.forEach(function (point) { + var args = point.shapeArgs; + if (point.graphic && args) { + var attr = {}, animate = {}; + if (args.d) { + // If shape is a path, then animate opacity. + attr.opacity = 0.001; + } + else { + // If shape is a circle, then animate radius. + attr.r = 0; + animate.r = args.r; + } + point.graphic + .attr(attr) + .animate(animate, animOptions); + // If shape is path, then fade it in after the circles + // animation + if (args.d) { + setTimeout(function () { + if (point && point.graphic) { + point.graphic.animate({ + opacity: 1 + }); + } + }, animOptions.duration); + } + } + }, series); + } + }, + utils: { + addOverlapToSets: addOverlapToSets, + geometry: geometry, + geometryCircles: geometryCirclesModule, + getLabelWidth: getLabelWidth, + getMarginFromCircles: getMarginFromCircles, + getDistanceBetweenCirclesByOverlap: getDistanceBetweenCirclesByOverlap, + layoutGreedyVenn: layoutGreedyVenn, + loss: loss, + nelderMead: nelderMeadModule, + processVennData: processVennData, + sortByTotalOverlap: sortByTotalOverlap + } +}; +var vennPoint = { + draw: draw, + shouldDraw: function () { + var point = this; + // Only draw points with single sets. + return !!point.shapeArgs; + }, + isValid: function () { + return isNumber(this.value); + } +}; +/** + * A `venn` series. If the [type](#series.venn.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.venn + * @excluding connectEnds, connectNulls, cropThreshold, dataParser, dataURL, + * findNearestPointBy, getExtremesFromAll, label, linecap, lineWidth, + * linkedTo, marker, negativeColor, pointInterval, pointIntervalUnit, + * pointPlacement, pointStart, softThreshold, stack, stacking, steps, + * threshold, xAxis, yAxis, zoneAxis, zones, dataSorting + * @product highcharts + * @requires modules/venn + * @apioption series.venn + */ +/** + * @type {Array<*>} + * @extends series.scatter.data + * @excluding marker, x, y + * @product highcharts + * @apioption series.venn.data + */ +/** + * The name of the point. Used in data labels and tooltip. If name is not + * defined then it will default to the joined values in + * [sets](#series.venn.sets). + * + * @sample {highcharts} highcharts/demo/venn-diagram/ + * Venn diagram + * @sample {highcharts} highcharts/demo/euler-diagram/ + * Euler diagram + * + * @type {number} + * @since 7.0.0 + * @product highcharts + * @apioption series.venn.data.name + */ +/** + * The value of the point, resulting in a relative area of the circle, or area + * of overlap between two sets in the venn or euler diagram. + * + * @sample {highcharts} highcharts/demo/venn-diagram/ + * Venn diagram + * @sample {highcharts} highcharts/demo/euler-diagram/ + * Euler diagram + * + * @type {number} + * @since 7.0.0 + * @product highcharts + * @apioption series.venn.data.value + */ +/** + * The set or sets the options will be applied to. If a single entry is defined, + * then it will create a new set. If more than one entry is defined, then it + * will define the overlap between the sets in the array. + * + * @sample {highcharts} highcharts/demo/venn-diagram/ + * Venn diagram + * @sample {highcharts} highcharts/demo/euler-diagram/ + * Euler diagram + * + * @type {Array} + * @since 7.0.0 + * @product highcharts + * @apioption series.venn.data.sets + */ +/** + * @excluding halo + * @apioption series.venn.states.hover + */ +/** + * @excluding halo + * @apioption series.venn.states.select + */ +/** + * @private + * @class + * @name Highcharts.seriesTypes.venn + * + * @augments Highcharts.Series + */ +seriesType('venn', 'scatter', vennOptions, vennSeries, vennPoint); +/* eslint-disable no-invalid-this */ +// Modify final series options. +addEvent(seriesTypes.venn, 'afterSetOptions', function (e) { + var options = e.options, states = options.states; + if (this.is('venn')) { + // Explicitly disable all halo options. + Object.keys(states).forEach(function (state) { + states[state].halo = false; + }); + } +}); diff --git a/librerias/gantt/code/es-modules/modules/windbarb.src.js b/librerias/gantt/code/es-modules/modules/windbarb.src.js new file mode 100644 index 0000000..045d687 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/windbarb.src.js @@ -0,0 +1,393 @@ +/* * + * + * Wind barb series module + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var animObject = U.animObject, isNumber = U.isNumber, pick = U.pick, seriesType = U.seriesType; +import onSeriesMixin from '../mixins/on-series.js'; +var noop = H.noop; +// eslint-disable-next-line valid-jsdoc +/** + * Once off, register the windbarb approximation for data grouping. This can be + * called anywhere (not necessarily in the translate function), but must happen + * after the data grouping module is loaded and before the wind barb series uses + * it. + * @private + */ +function registerApproximation() { + if (H.approximations && !H.approximations.windbarb) { + H.approximations.windbarb = function (values, directions) { + var vectorX = 0, vectorY = 0, i, len = values.length; + for (i = 0; i < len; i++) { + vectorX += values[i] * Math.cos(directions[i] * H.deg2rad); + vectorY += values[i] * Math.sin(directions[i] * H.deg2rad); + } + return [ + // Wind speed + values.reduce(function (sum, value) { + return sum + value; + }, 0) / values.length, + // Wind direction + Math.atan2(vectorY, vectorX) / H.deg2rad + ]; + }; + } +} +registerApproximation(); +/** + * @private + * @class + * @name Highcharts.seriesTypes.windbarb + * + * @augments Highcharts.Series + */ +seriesType('windbarb', 'column' +/** + * Wind barbs are a convenient way to represent wind speed and direction in + * one graphical form. Wind direction is given by the stem direction, and + * wind speed by the number and shape of barbs. + * + * @sample {highcharts|highstock} highcharts/demo/windbarb-series/ + * Wind barb series + * + * @extends plotOptions.column + * @excluding boostThreshold, marker, connectEnds, connectNulls, + * cropThreshold, dashStyle, dragDrop, gapSize, gapUnit, + * linecap, shadow, stacking, step + * @since 6.0.0 + * @product highcharts highstock + * @requires modules/windbarb + * @optionparent plotOptions.windbarb + */ +, { + /** + * Data grouping options for the wind barbs. In Highcharts, this + * requires the `modules/datagrouping.js` module to be loaded. In + * Highstock, data grouping is included. + * + * @sample highcharts/plotoptions/windbarb-datagrouping + * Wind barb with data grouping + * + * @since 7.1.0 + * @product highcharts highstock + */ + dataGrouping: { + /** + * Whether to enable data grouping. + * + * @product highcharts highstock + */ + enabled: true, + /** + * Approximation function for the data grouping. The default + * returns an average of wind speed and a vector average direction + * weighted by wind speed. + * + * @product highcharts highstock + * + * @type {string|Function} + */ + approximation: 'windbarb', + /** + * The approximate data group width. + * + * @product highcharts highstock + */ + groupPixelWidth: 30 + }, + /** + * The line width of the wind barb symbols. + */ + lineWidth: 2, + /** + * The id of another series in the chart that the wind barbs are + * projected on. When `null`, the wind symbols are drawn on the X axis, + * but offset up or down by the `yOffset` setting. + * + * @sample {highcharts|highstock} highcharts/plotoptions/windbarb-onseries + * Projected on area series + * + * @type {string|null} + */ + onSeries: null, + states: { + hover: { + lineWidthPlus: 0 + } + }, + tooltip: { + /** + * The default point format for the wind barb tooltip. Note the + * `point.beaufort` property that refers to the Beaufort wind scale. + * The names can be internationalized by modifying + * `Highcharts.seriesTypes.windbarb.prototype.beaufortNames`. + */ + pointFormat: '\u25CF {series.name}: {point.value} ({point.beaufort})
' + }, + /** + * Pixel length of the stems. + */ + vectorLength: 20, + /** + * @default value + */ + colorKey: 'value', + /** + * Vertical offset from the cartesian position, in pixels. The default + * value makes sure the symbols don't overlap the X axis when `onSeries` + * is `null`, and that they don't overlap the linked series when + * `onSeries` is given. + */ + yOffset: -20, + /** + * Horizontal offset from the cartesian position, in pixels. When the + * chart is inverted, this option allows translation like + * [yOffset](#plotOptions.windbarb.yOffset) in non inverted charts. + * + * @since 6.1.0 + */ + xOffset: 0 +}, { + pointArrayMap: ['value', 'direction'], + parallelArrays: ['x', 'value', 'direction'], + beaufortName: ['Calm', 'Light air', 'Light breeze', + 'Gentle breeze', 'Moderate breeze', 'Fresh breeze', + 'Strong breeze', 'Near gale', 'Gale', 'Strong gale', 'Storm', + 'Violent storm', 'Hurricane'], + beaufortFloor: [0, 0.3, 1.6, 3.4, 5.5, 8.0, 10.8, 13.9, 17.2, 20.8, + 24.5, 28.5, 32.7], + trackerGroups: ['markerGroup'], + init: function (chart, options) { + registerApproximation(); + H.Series.prototype.init.call(this, chart, options); + }, + // Get presentational attributes. + pointAttribs: function (point, state) { + var options = this.options, stroke = point.color || this.color, strokeWidth = this.options.lineWidth; + if (state) { + stroke = options.states[state].color || stroke; + strokeWidth = + (options.states[state].lineWidth || strokeWidth) + + (options.states[state].lineWidthPlus || 0); + } + return { + 'stroke': stroke, + 'stroke-width': strokeWidth + }; + }, + markerAttribs: function () { + return; + }, + getPlotBox: onSeriesMixin.getPlotBox, + // Create a single wind arrow. It is later rotated around the zero + // centerpoint. + windArrow: function (point) { + var knots = point.value * 1.943844, level = point.beaufortLevel, path, barbs, u = this.options.vectorLength / 20, pos = -10; + if (point.isNull) { + return []; + } + if (level === 0) { + return this.chart.renderer.symbols.circle(-10 * u, -10 * u, 20 * u, 20 * u); + } + // The stem and the arrow head + path = [ + ['M', 0, 7 * u], + ['L', -1.5 * u, 7 * u], + ['L', 0, 10 * u], + ['L', 1.5 * u, 7 * u], + ['L', 0, 7 * u], + ['L', 0, -10 * u] // top + ]; + // For each full 50 knots, add a pennant + barbs = (knots - knots % 50) / 50; // pennants + if (barbs > 0) { + while (barbs--) { + path.push(pos === -10 ? ['L', 0, pos * u] : ['M', 0, pos * u], ['L', 5 * u, pos * u + 2], ['L', 0, pos * u + 4]); + // Substract from the rest and move position for next + knots -= 50; + pos += 7; + } + } + // For each full 10 knots, add a full barb + barbs = (knots - knots % 10) / 10; + if (barbs > 0) { + while (barbs--) { + path.push(pos === -10 ? ['L', 0, pos * u] : ['M', 0, pos * u], ['L', 7 * u, pos * u]); + knots -= 10; + pos += 3; + } + } + // For each full 5 knots, add a half barb + barbs = (knots - knots % 5) / 5; // half barbs + if (barbs > 0) { + while (barbs--) { + path.push(pos === -10 ? ['L', 0, pos * u] : ['M', 0, pos * u], ['L', 4 * u, pos * u]); + knots -= 5; + pos += 3; + } + } + return path; + }, + translate: function () { + var beaufortFloor = this.beaufortFloor, beaufortName = this.beaufortName; + onSeriesMixin.translate.call(this); + this.points.forEach(function (point) { + var level = 0; + // Find the beaufort level (zero based) + for (; level < beaufortFloor.length; level++) { + if (beaufortFloor[level] > point.value) { + break; + } + } + point.beaufortLevel = level - 1; + point.beaufort = beaufortName[level - 1]; + }); + }, + drawPoints: function () { + var chart = this.chart, yAxis = this.yAxis, inverted = chart.inverted, shapeOffset = this.options.vectorLength / 2; + this.points.forEach(function (point) { + var plotX = point.plotX, plotY = point.plotY; + // Check if it's inside the plot area, but only for the X + // dimension. + if (this.options.clip === false || + chart.isInsidePlot(plotX, 0, false)) { + // Create the graphic the first time + if (!point.graphic) { + point.graphic = this.chart.renderer + .path() + .add(this.markerGroup) + .addClass('highcharts-point ' + + 'highcharts-color-' + + pick(point.colorIndex, point.series.colorIndex)); + } + // Position the graphic + point.graphic + .attr({ + d: this.windArrow(point), + translateX: plotX + this.options.xOffset, + translateY: plotY + this.options.yOffset, + rotation: point.direction + }); + if (!this.chart.styledMode) { + point.graphic + .attr(this.pointAttribs(point)); + } + } + else if (point.graphic) { + point.graphic = point.graphic.destroy(); + } + // Set the tooltip anchor position + point.tooltipPos = [ + plotX + this.options.xOffset + + (inverted && !this.onSeries ? shapeOffset : 0), + plotY + this.options.yOffset - + (inverted ? + 0 : + shapeOffset + yAxis.pos - chart.plotTop) + ]; // #6327 + }, this); + }, + // Fade in the arrows on initializing series. + animate: function (init) { + if (init) { + this.markerGroup.attr({ + opacity: 0.01 + }); + } + else { + this.markerGroup.animate({ + opacity: 1 + }, animObject(this.options.animation)); + } + }, + // Don't invert the marker group (#4960) + invertGroups: noop, + // No data extremes for the Y axis + getExtremes: function () { return ({}); } +}, { + isValid: function () { + return isNumber(this.value) && this.value >= 0; + } +}); +/** + * A `windbarb` series. If the [type](#series.windbarb.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.windbarb + * @excluding dataParser, dataURL + * @product highcharts highstock + * @requires modules/windbarb + * @apioption series.windbarb + */ +/** + * An array of data points for the series. For the `windbarb` series type, + * points can be given in the following ways: + * + * 1. An array of arrays with 3 values. In this case, the values correspond to + * `x,value,direction`. If the first value is a string, it is applied as the + * name of the point, and the `x` value is inferred. + * ```js + * data: [ + * [Date.UTC(2017, 0, 1, 0), 3.3, 90], + * [Date.UTC(2017, 0, 1, 1), 12.1, 180], + * [Date.UTC(2017, 0, 1, 2), 11.1, 270] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.area.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: Date.UTC(2017, 0, 1, 0), + * value: 12.1, + * direction: 90 + * }, { + * x: Date.UTC(2017, 0, 1, 1), + * value: 11.1, + * direction: 270 + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|*>} + * @extends series.line.data + * @product highcharts highstock + * @apioption series.windbarb.data + */ +/** + * The wind speed in meters per second. + * + * @type {number|null} + * @product highcharts highstock + * @apioption series.windbarb.data.value + */ +/** + * The wind direction in degrees, where 0 is north (pointing towards south). + * + * @type {number} + * @product highcharts highstock + * @apioption series.windbarb.data.direction + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/modules/wordcloud.src.js b/librerias/gantt/code/es-modules/modules/wordcloud.src.js new file mode 100644 index 0000000..ee8947b --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/wordcloud.src.js @@ -0,0 +1,932 @@ +/* * + * + * Experimental Highcharts module which enables visualization of a word cloud. + * + * (c) 2016-2020 Highsoft AS + * Authors: Jon Arild Nygard + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var extend = U.extend, find = U.find, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, merge = U.merge, seriesType = U.seriesType; +import drawPoint from '../mixins/draw-point.js'; +import polygon from '../mixins/polygon.js'; +import '../parts/Series.js'; +var noop = H.noop, getBoundingBoxFromPolygon = polygon.getBoundingBoxFromPolygon, getPolygon = polygon.getPolygon, isPolygonsColliding = polygon.isPolygonsColliding, movePolygon = polygon.movePolygon, Series = H.Series; +/** + * Detects if there is a collision between two rectangles. + * + * @private + * @function isRectanglesIntersecting + * + * @param {Highcharts.PolygonBoxObject} r1 + * First rectangle. + * + * @param {Highcharts.PolygonBoxObject} r2 + * Second rectangle. + * + * @return {boolean} + * Returns true if the rectangles overlap. + */ +function isRectanglesIntersecting(r1, r2) { + return !(r2.left > r1.right || + r2.right < r1.left || + r2.top > r1.bottom || + r2.bottom < r1.top); +} +/** + * Detects if a word collides with any previously placed words. + * + * @private + * @function intersectsAnyWord + * + * @param {Highcharts.Point} point + * Point which the word is connected to. + * + * @param {Array} points + * Previously placed points to check against. + * + * @return {boolean} + * Returns true if there is collision. + */ +function intersectsAnyWord(point, points) { + var intersects = false, rect = point.rect, polygon = point.polygon, lastCollidedWith = point.lastCollidedWith, isIntersecting = function (p) { + var result = isRectanglesIntersecting(rect, p.rect); + if (result && + (point.rotation % 90 || p.rotation % 90)) { + result = isPolygonsColliding(polygon, p.polygon); + } + return result; + }; + // If the point has already intersected a different point, chances are they + // are still intersecting. So as an enhancement we check this first. + if (lastCollidedWith) { + intersects = isIntersecting(lastCollidedWith); + // If they no longer intersects, remove the cache from the point. + if (!intersects) { + delete point.lastCollidedWith; + } + } + // If not already found, then check if we can find a point that is + // intersecting. + if (!intersects) { + intersects = !!find(points, function (p) { + var result = isIntersecting(p); + if (result) { + point.lastCollidedWith = p; + } + return result; + }); + } + return intersects; +} +/** + * Gives a set of cordinates for an Archimedian Spiral. + * + * @private + * @function archimedeanSpiral + * + * @param {number} attempt + * How far along the spiral we have traversed. + * + * @param {Highcharts.WordcloudSpiralParamsObject} [params] + * Additional parameters. + * + * @return {boolean|Highcharts.PositionObject} + * Resulting coordinates, x and y. False if the word should be dropped from the + * visualization. + */ +function archimedeanSpiral(attempt, params) { + var field = params.field, result = false, maxDelta = (field.width * field.width) + (field.height * field.height), t = attempt * 0.8; // 0.2 * 4 = 0.8. Enlarging the spiral. + // Emergency brake. TODO make spiralling logic more foolproof. + if (attempt <= 10000) { + result = { + x: t * Math.cos(t), + y: t * Math.sin(t) + }; + if (!(Math.min(Math.abs(result.x), Math.abs(result.y)) < maxDelta)) { + result = false; + } + } + return result; +} +/** + * Gives a set of cordinates for an rectangular spiral. + * + * @private + * @function squareSpiral + * + * @param {number} attempt + * How far along the spiral we have traversed. + * + * @param {Highcharts.WordcloudSpiralParamsObject} [params] + * Additional parameters. + * + * @return {boolean|Highcharts.PositionObject} + * Resulting coordinates, x and y. False if the word should be dropped from the + * visualization. + */ +function squareSpiral(attempt, params) { + var a = attempt * 4, k = Math.ceil((Math.sqrt(a) - 1) / 2), t = 2 * k + 1, m = Math.pow(t, 2), isBoolean = function (x) { + return typeof x === 'boolean'; + }, result = false; + t -= 1; + if (attempt <= 10000) { + if (isBoolean(result) && a >= m - t) { + result = { + x: k - (m - a), + y: -k + }; + } + m -= t; + if (isBoolean(result) && a >= m - t) { + result = { + x: -k, + y: -k + (m - a) + }; + } + m -= t; + if (isBoolean(result)) { + if (a >= m - t) { + result = { + x: -k + (m - a), + y: k + }; + } + else { + result = { + x: k, + y: k - (m - a - t) + }; + } + } + result.x *= 5; + result.y *= 5; + } + return result; +} +/** + * Gives a set of cordinates for an rectangular spiral. + * + * @private + * @function rectangularSpiral + * + * @param {number} attempt + * How far along the spiral we have traversed. + * + * @param {Highcharts.WordcloudSpiralParamsObject} [params] + * Additional parameters. + * + * @return {boolean|Higcharts.PositionObject} + * Resulting coordinates, x and y. False if the word should be dropped from the + * visualization. + */ +function rectangularSpiral(attempt, params) { + var result = squareSpiral(attempt, params), field = params.field; + if (result) { + result.x *= field.ratioX; + result.y *= field.ratioY; + } + return result; +} +/** + * @private + * @function getRandomPosition + * + * @param {number} size + * Random factor. + * + * @return {number} + * Random position. + */ +function getRandomPosition(size) { + return Math.round((size * (Math.random() + 0.5)) / 2); +} +/** + * Calculates the proper scale to fit the cloud inside the plotting area. + * + * @private + * @function getScale + * + * @param {number} targetWidth + * Width of target area. + * + * @param {number} targetHeight + * Height of target area. + * + * @param {object} field + * The playing field. + * + * @param {Highcharts.Series} series + * Series object. + * + * @return {number} + * Returns the value to scale the playing field up to the size of the target + * area. + */ +function getScale(targetWidth, targetHeight, field) { + var height = Math.max(Math.abs(field.top), Math.abs(field.bottom)) * 2, width = Math.max(Math.abs(field.left), Math.abs(field.right)) * 2, scaleX = width > 0 ? 1 / width * targetWidth : 1, scaleY = height > 0 ? 1 / height * targetHeight : 1; + return Math.min(scaleX, scaleY); +} +/** + * Calculates what is called the playing field. The field is the area which all + * the words are allowed to be positioned within. The area is proportioned to + * match the target aspect ratio. + * + * @private + * @function getPlayingField + * + * @param {number} targetWidth + * Width of the target area. + * + * @param {number} targetHeight + * Height of the target area. + * + * @param {Array} data + * Array of points. + * + * @param {object} data.dimensions + * The height and width of the word. + * + * @return {object} + * The width and height of the playing field. + */ +function getPlayingField(targetWidth, targetHeight, data) { + var info = data.reduce(function (obj, point) { + var dimensions = point.dimensions, x = Math.max(dimensions.width, dimensions.height); + // Find largest height. + obj.maxHeight = Math.max(obj.maxHeight, dimensions.height); + // Find largest width. + obj.maxWidth = Math.max(obj.maxWidth, dimensions.width); + // Sum up the total maximum area of all the words. + obj.area += x * x; + return obj; + }, { + maxHeight: 0, + maxWidth: 0, + area: 0 + }), + /** + * Use largest width, largest height, or root of total area to give size + * to the playing field. + */ + x = Math.max(info.maxHeight, // Have enough space for the tallest word + info.maxWidth, // Have enough space for the broadest word + // Adjust 15% to account for close packing of words + Math.sqrt(info.area) * 0.85), ratioX = targetWidth > targetHeight ? targetWidth / targetHeight : 1, ratioY = targetHeight > targetWidth ? targetHeight / targetWidth : 1; + return { + width: x * ratioX, + height: x * ratioY, + ratioX: ratioX, + ratioY: ratioY + }; +} +/** + * Calculates a number of degrees to rotate, based upon a number of orientations + * within a range from-to. + * + * @private + * @function getRotation + * + * @param {number} [orientations] + * Number of orientations. + * + * @param {number} [index] + * Index of point, used to decide orientation. + * + * @param {number} [from] + * The smallest degree of rotation. + * + * @param {number} [to] + * The largest degree of rotation. + * + * @return {boolean|number} + * Returns the resulting rotation for the word. Returns false if invalid input + * parameters. + */ +function getRotation(orientations, index, from, to) { + var result = false, // Default to false + range, intervals, orientation; + // Check if we have valid input parameters. + if (isNumber(orientations) && + isNumber(index) && + isNumber(from) && + isNumber(to) && + orientations > 0 && + index > -1 && + to > from) { + range = to - from; + intervals = range / (orientations - 1 || 1); + orientation = index % orientations; + result = from + (orientation * intervals); + } + return result; +} +/** + * Calculates the spiral positions and store them in scope for quick access. + * + * @private + * @function getSpiral + * + * @param {Function} fn + * The spiral function. + * + * @param {object} params + * Additional parameters for the spiral. + * + * @return {Function} + * Function with access to spiral positions. + */ +function getSpiral(fn, params) { + var length = 10000, i, arr = []; + for (i = 1; i < length; i++) { + arr.push(fn(i, params)); // @todo unnecessary amount of precaclulation + } + return function (attempt) { + return attempt <= length ? arr[attempt - 1] : false; + }; +} +/** + * Detects if a word is placed outside the playing field. + * + * @private + * @function outsidePlayingField + * + * @param {Highcharts.PolygonBoxObject} rect + * The word box. + * + * @param {Highcharts.WordcloudFieldObject} field + * The width and height of the playing field. + * + * @return {boolean} + * Returns true if the word is placed outside the field. + */ +function outsidePlayingField(rect, field) { + var playingField = { + left: -(field.width / 2), + right: field.width / 2, + top: -(field.height / 2), + bottom: field.height / 2 + }; + return !(playingField.left < rect.left && + playingField.right > rect.right && + playingField.top < rect.top && + playingField.bottom > rect.bottom); +} +/** + * Check if a point intersects with previously placed words, or if it goes + * outside the field boundaries. If a collision, then try to adjusts the + * position. + * + * @private + * @function intersectionTesting + * + * @param {Highcharts.Point} point + * Point to test for intersections. + * + * @param {Highcharts.WordcloudTestOptionsObject} options + * Options object. + * + * @return {boolean|Highcharts.PositionObject} + * Returns an object with how much to correct the positions. Returns false if + * the word should not be placed at all. + */ +function intersectionTesting(point, options) { + var placed = options.placed, field = options.field, rectangle = options.rectangle, polygon = options.polygon, spiral = options.spiral, attempt = 1, delta = { + x: 0, + y: 0 + }, + // Make a copy to update values during intersection testing. + rect = point.rect = extend({}, rectangle); + point.polygon = polygon; + point.rotation = options.rotation; + /* while w intersects any previously placed words: + do { + move w a little bit along a spiral path + } while any part of w is outside the playing field and + the spiral radius is still smallish */ + while (delta !== false && + (intersectsAnyWord(point, placed) || + outsidePlayingField(rect, field))) { + delta = spiral(attempt); + if (isObject(delta)) { + // Update the DOMRect with new positions. + rect.left = rectangle.left + delta.x; + rect.right = rectangle.right + delta.x; + rect.top = rectangle.top + delta.y; + rect.bottom = rectangle.bottom + delta.y; + point.polygon = movePolygon(delta.x, delta.y, polygon); + } + attempt++; + } + return delta; +} +/** + * Extends the playing field to have enough space to fit a given word. + * + * @private + * @function extendPlayingField + * + * @param {Highcharts.WordcloudFieldObject} field + * The width, height and ratios of a playing field. + * + * @param {Highcharts.PolygonBoxObject} rectangle + * The bounding box of the word to add space for. + * + * @return {Highcharts.WordcloudFieldObject} + * Returns the extended playing field with updated height and width. + */ +function extendPlayingField(field, rectangle) { + var height, width, ratioX, ratioY, x, extendWidth, extendHeight, result; + if (isObject(field) && isObject(rectangle)) { + height = (rectangle.bottom - rectangle.top); + width = (rectangle.right - rectangle.left); + ratioX = field.ratioX; + ratioY = field.ratioY; + // Use the same variable to extend both the height and width. + x = ((width * ratioX) > (height * ratioY)) ? width : height; + // Multiply variable with ratios to preserve aspect ratio. + extendWidth = x * ratioX; + extendHeight = x * ratioY; + // Calculate the size of the new field after adding space for the word. + result = merge(field, { + // Add space on the left and right. + width: field.width + (extendWidth * 2), + // Add space on the top and bottom. + height: field.height + (extendHeight * 2) + }); + } + else { + result = field; + } + // Return the new extended field. + return result; +} +/** + * If a rectangle is outside a give field, then the boundaries of the field is + * adjusted accordingly. Modifies the field object which is passed as the first + * parameter. + * + * @private + * @function updateFieldBoundaries + * + * @param {Highcharts.WordcloudFieldObject} field + * The bounding box of a playing field. + * + * @param {Highcharts.PolygonBoxObject} rectangle + * The bounding box for a placed point. + * + * @return {Highcharts.WordcloudFieldObject} + * Returns a modified field object. + */ +function updateFieldBoundaries(field, rectangle) { + // @todo improve type checking. + if (!isNumber(field.left) || field.left > rectangle.left) { + field.left = rectangle.left; + } + if (!isNumber(field.right) || field.right < rectangle.right) { + field.right = rectangle.right; + } + if (!isNumber(field.top) || field.top > rectangle.top) { + field.top = rectangle.top; + } + if (!isNumber(field.bottom) || field.bottom < rectangle.bottom) { + field.bottom = rectangle.bottom; + } + return field; +} +/** + * A word cloud is a visualization of a set of words, where the size and + * placement of a word is determined by how it is weighted. + * + * @sample highcharts/demo/wordcloud + * Word Cloud chart + * + * @extends plotOptions.column + * @excluding allAreas, boostThreshold, clip, colorAxis, compare, + * compareBase, crisp, cropTreshold, dataGrouping, dataLabels, + * depth, dragDrop, edgeColor, findNearestPointBy, + * getExtremesFromAll, grouping, groupPadding, groupZPadding, + * joinBy, maxPointWidth, minPointLength, navigatorOptions, + * negativeColor, pointInterval, pointIntervalUnit, pointPadding, + * pointPlacement, pointRange, pointStart, pointWidth, pointStart, + * pointWidth, shadow, showCheckbox, showInNavigator, + * softThreshold, stacking, threshold, zoneAxis, zones, + * dataSorting + * @product highcharts + * @since 6.0.0 + * @requires modules/wordcloud + * @optionparent plotOptions.wordcloud + */ +var wordCloudOptions = { + /** + * If there is no space for a word on the playing field, then this option + * will allow the playing field to be extended to fit the word. If false + * then the word will be dropped from the visualization. + * + * NB! This option is currently not decided to be published in the API, and + * is therefore marked as private. + * + * @private + */ + allowExtendPlayingField: true, + animation: { + /** @internal */ + duration: 500 + }, + borderWidth: 0, + clip: false, + colorByPoint: true, + /** + * A threshold determining the minimum font size that can be applied to a + * word. + */ + minFontSize: 1, + /** + * The word with the largest weight will have a font size equal to this + * value. The font size of a word is the ratio between its weight and the + * largest occuring weight, multiplied with the value of maxFontSize. + */ + maxFontSize: 25, + /** + * This option decides which algorithm is used for placement, and rotation + * of a word. The choice of algorith is therefore a crucial part of the + * resulting layout of the wordcloud. It is possible for users to add their + * own custom placement strategies for use in word cloud. Read more about it + * in our + * [documentation](https://www.highcharts.com/docs/chart-and-series-types/word-cloud-series#custom-placement-strategies) + * + * @validvalue: ["center", "random"] + */ + placementStrategy: 'center', + /** + * Rotation options for the words in the wordcloud. + * + * @sample highcharts/plotoptions/wordcloud-rotation + * Word cloud with rotation + */ + rotation: { + /** + * The smallest degree of rotation for a word. + */ + from: 0, + /** + * The number of possible orientations for a word, within the range of + * `rotation.from` and `rotation.to`. Must be a number larger than 0. + */ + orientations: 2, + /** + * The largest degree of rotation for a word. + */ + to: 90 + }, + showInLegend: false, + /** + * Spiral used for placing a word after the initial position experienced a + * collision with either another word or the borders. + * It is possible for users to add their own custom spiralling algorithms + * for use in word cloud. Read more about it in our + * [documentation](https://www.highcharts.com/docs/chart-and-series-types/word-cloud-series#custom-spiralling-algorithm) + * + * @validvalue: ["archimedean", "rectangular", "square"] + */ + spiral: 'rectangular', + /** + * CSS styles for the words. + * + * @type {Highcharts.CSSObject} + * @default {"fontFamily":"sans-serif", "fontWeight": "900"} + */ + style: { + /** @ignore-option */ + fontFamily: 'sans-serif', + /** @ignore-option */ + fontWeight: '900', + /** @ignore-option */ + whiteSpace: 'nowrap' + }, + tooltip: { + followPointer: true, + pointFormat: '\u25CF {series.name}: {point.weight}
' + } +}; +// Properties of the WordCloud series. +var wordCloudSeries = { + animate: Series.prototype.animate, + animateDrilldown: noop, + animateDrillupFrom: noop, + setClip: noop, + bindAxes: function () { + var wordcloudAxis = { + endOnTick: false, + gridLineWidth: 0, + lineWidth: 0, + maxPadding: 0, + startOnTick: false, + title: null, + tickPositions: [] + }; + Series.prototype.bindAxes.call(this); + extend(this.yAxis.options, wordcloudAxis); + extend(this.xAxis.options, wordcloudAxis); + }, + pointAttribs: function (point, state) { + var attribs = H.seriesTypes.column.prototype + .pointAttribs.call(this, point, state); + delete attribs.stroke; + delete attribs['stroke-width']; + return attribs; + }, + /** + * Calculates the fontSize of a word based on its weight. + * + * @private + * @function Highcharts.Series#deriveFontSize + * + * @param {number} [relativeWeight=0] + * The weight of the word, on a scale 0-1. + * + * @param {number} [maxFontSize=1] + * The maximum font size of a word. + * + * @param {number} [minFontSize=1] + * The minimum font size of a word. + * + * @return {number} + * Returns the resulting fontSize of a word. If minFontSize is larger then + * maxFontSize the result will equal minFontSize. + */ + deriveFontSize: function deriveFontSize(relativeWeight, maxFontSize, minFontSize) { + var weight = isNumber(relativeWeight) ? relativeWeight : 0, max = isNumber(maxFontSize) ? maxFontSize : 1, min = isNumber(minFontSize) ? minFontSize : 1; + return Math.floor(Math.max(min, weight * max)); + }, + drawPoints: function () { + var series = this, hasRendered = series.hasRendered, xAxis = series.xAxis, yAxis = series.yAxis, chart = series.chart, group = series.group, options = series.options, animation = options.animation, allowExtendPlayingField = options.allowExtendPlayingField, renderer = chart.renderer, testElement = renderer.text().add(group), placed = [], placementStrategy = series.placementStrategy[options.placementStrategy], spiral, rotation = options.rotation, scale, weights = series.points.map(function (p) { + return p.weight; + }), maxWeight = Math.max.apply(null, weights), + // concat() prevents from sorting the original array. + data = series.points.concat().sort(function (a, b) { + return b.weight - a.weight; // Sort descending + }), field; + // Reset the scale before finding the dimensions (#11993). + // SVGGRaphicsElement.getBBox() (used in SVGElement.getBBox(boolean)) + // returns slightly different values for the same element depending on + // whether it is rendered in a group which has already defined scale + // (e.g. 6) or in the group without a scale (scale = 1). + series.group.attr({ + scaleX: 1, + scaleY: 1 + }); + // Get the dimensions for each word. + // Used in calculating the playing field. + data.forEach(function (point) { + var relativeWeight = 1 / maxWeight * point.weight, fontSize = series.deriveFontSize(relativeWeight, options.maxFontSize, options.minFontSize), css = extend({ + fontSize: fontSize + 'px' + }, options.style), bBox; + testElement.css(css).attr({ + x: 0, + y: 0, + text: point.name + }); + bBox = testElement.getBBox(true); + point.dimensions = { + height: bBox.height, + width: bBox.width + }; + }); + // Calculate the playing field. + field = getPlayingField(xAxis.len, yAxis.len, data); + spiral = getSpiral(series.spirals[options.spiral], { + field: field + }); + // Draw all the points. + data.forEach(function (point) { + var relativeWeight = 1 / maxWeight * point.weight, fontSize = series.deriveFontSize(relativeWeight, options.maxFontSize, options.minFontSize), css = extend({ + fontSize: fontSize + 'px' + }, options.style), placement = placementStrategy(point, { + data: data, + field: field, + placed: placed, + rotation: rotation + }), attr = extend(series.pointAttribs(point, (point.selected && 'select')), { + align: 'center', + 'alignment-baseline': 'middle', + x: placement.x, + y: placement.y, + text: point.name, + rotation: placement.rotation + }), polygon = getPolygon(placement.x, placement.y, point.dimensions.width, point.dimensions.height, placement.rotation), rectangle = getBoundingBoxFromPolygon(polygon), delta = intersectionTesting(point, { + rectangle: rectangle, + polygon: polygon, + field: field, + placed: placed, + spiral: spiral, + rotation: placement.rotation + }), animate; + // If there is no space for the word, extend the playing field. + if (!delta && allowExtendPlayingField) { + // Extend the playing field to fit the word. + field = extendPlayingField(field, rectangle); + // Run intersection testing one more time to place the word. + delta = intersectionTesting(point, { + rectangle: rectangle, + polygon: polygon, + field: field, + placed: placed, + spiral: spiral, + rotation: placement.rotation + }); + } + // Check if point was placed, if so delete it, otherwise place it on + // the correct positions. + if (isObject(delta)) { + attr.x += delta.x; + attr.y += delta.y; + rectangle.left += delta.x; + rectangle.right += delta.x; + rectangle.top += delta.y; + rectangle.bottom += delta.y; + field = updateFieldBoundaries(field, rectangle); + placed.push(point); + point.isNull = false; + } + else { + point.isNull = true; + } + if (animation) { + // Animate to new positions + animate = { + x: attr.x, + y: attr.y + }; + // Animate from center of chart + if (!hasRendered) { + attr.x = 0; + attr.y = 0; + // or animate from previous position + } + else { + delete attr.x; + delete attr.y; + } + } + point.draw({ + animatableAttribs: animate, + attribs: attr, + css: css, + group: group, + renderer: renderer, + shapeArgs: void 0, + shapeType: 'text' + }); + }); + // Destroy the element after use. + testElement = testElement.destroy(); + // Scale the series group to fit within the plotArea. + scale = getScale(xAxis.len, yAxis.len, field); + series.group.attr({ + scaleX: scale, + scaleY: scale + }); + }, + hasData: function () { + var series = this; + return (isObject(series) && + series.visible === true && + isArray(series.points) && + series.points.length > 0); + }, + // Strategies used for deciding rotation and initial position of a word. To + // implement a custom strategy, have a look at the function random for + // example. + placementStrategy: { + random: function (point, options) { + var field = options.field, r = options.rotation; + return { + x: getRandomPosition(field.width) - (field.width / 2), + y: getRandomPosition(field.height) - (field.height / 2), + rotation: getRotation(r.orientations, point.index, r.from, r.to) + }; + }, + center: function (point, options) { + var r = options.rotation; + return { + x: 0, + y: 0, + rotation: getRotation(r.orientations, point.index, r.from, r.to) + }; + } + }, + pointArrayMap: ['weight'], + // Spirals used for placing a word after the initial position experienced a + // collision with either another word or the borders. To implement a custom + // spiral, look at the function archimedeanSpiral for example. + spirals: { + 'archimedean': archimedeanSpiral, + 'rectangular': rectangularSpiral, + 'square': squareSpiral + }, + utils: { + extendPlayingField: extendPlayingField, + getRotation: getRotation, + isPolygonsColliding: isPolygonsColliding, + rotate2DToOrigin: polygon.rotate2DToOrigin, + rotate2DToPoint: polygon.rotate2DToPoint + }, + getPlotBox: function () { + var series = this, chart = series.chart, inverted = chart.inverted, + // Swap axes for inverted (#2339) + xAxis = series[(inverted ? 'yAxis' : 'xAxis')], yAxis = series[(inverted ? 'xAxis' : 'yAxis')], width = xAxis ? xAxis.len : chart.plotWidth, height = yAxis ? yAxis.len : chart.plotHeight, x = xAxis ? xAxis.left : chart.plotLeft, y = yAxis ? yAxis.top : chart.plotTop; + return { + translateX: x + (width / 2), + translateY: y + (height / 2), + scaleX: 1, + scaleY: 1 + }; + } +}; +// Properties of the Sunburst series. +var wordCloudPoint = { + draw: drawPoint, + shouldDraw: function shouldDraw() { + var point = this; + return !point.isNull; + }, + isValid: function isValid() { + return true; + }, + weight: 1 +}; +/** + * A `wordcloud` series. If the [type](#series.wordcloud.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.wordcloud + * @exclude dataSorting + * @product highcharts + * @requires modules/wordcloud + * @apioption series.wordcloud + */ +/** + * An array of data points for the series. For the `wordcloud` series type, + * points can be given in the following ways: + * + * 1. An array of arrays with 2 values. In this case, the values correspond to + * `name,weight`. + * ```js + * data: [ + * ['Lorem', 4], + * ['Ipsum', 1] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.arearange.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * name: "Lorem", + * weight: 4 + * }, { + * name: "Ipsum", + * weight: 1 + * }] + * ``` + * + * @type {Array|*>} + * @extends series.line.data + * @excluding drilldown, marker, x, y + * @product highcharts + * @apioption series.wordcloud.data + */ +/** + * The name decides the text for a word. + * + * @type {string} + * @since 6.0.0 + * @product highcharts + * @apioption series.sunburst.data.name + */ +/** + * The weighting of a word. The weight decides the relative size of a word + * compared to the rest of the collection. + * + * @type {number} + * @since 6.0.0 + * @product highcharts + * @apioption series.sunburst.data.weight + */ +/** + * @private + * @class + * @name Highcharts.seriesTypes.wordcloud + * + * @augments Highcharts.Series + */ +seriesType('wordcloud', 'column', wordCloudOptions, wordCloudSeries, wordCloudPoint); diff --git a/librerias/gantt/code/es-modules/modules/xrange.src.js b/librerias/gantt/code/es-modules/modules/xrange.src.js new file mode 100644 index 0000000..9bf7809 --- /dev/null +++ b/librerias/gantt/code/es-modules/modules/xrange.src.js @@ -0,0 +1,670 @@ +/* * + * + * X-range series module + * + * (c) 2010-2020 Torstein Honsi, Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +/* * + * @interface Highcharts.PointOptionsObject in parts/Point.ts + */ /** +* The ending X value of the range point. +* @name Highcharts.PointOptionsObject#x2 +* @type {number|undefined} +* @requires modules/xrange +*/ +import Color from '../parts/Color.js'; +var color = Color.parse; +import Point from '../parts/Point.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, clamp = U.clamp, correctFloat = U.correctFloat, defined = U.defined, find = U.find, isNumber = U.isNumber, isObject = U.isObject, merge = U.merge, pick = U.pick, seriesType = U.seriesType; +var columnType = H.seriesTypes.column, seriesTypes = H.seriesTypes, Axis = H.Axis, Series = H.Series; +/** + * Return color of a point based on its category. + * + * @private + * @function getColorByCategory + * + * @param {object} series + * The series which the point belongs to. + * + * @param {object} point + * The point to calculate its color for. + * + * @return {object} + * Returns an object containing the properties color and colorIndex. + */ +function getColorByCategory(series, point) { + var colors = series.options.colors || series.chart.options.colors, colorCount = colors ? + colors.length : + series.chart.options.chart.colorCount, colorIndex = point.y % colorCount, color = colors && colors[colorIndex]; + return { + colorIndex: colorIndex, + color: color + }; +} +/** + * @private + * @class + * @name Highcharts.seriesTypes.xrange + * + * @augments Highcharts.Series + */ +seriesType('xrange', 'column' +/** + * The X-range series displays ranges on the X axis, typically time + * intervals with a start and end date. + * + * @sample {highcharts} highcharts/demo/x-range/ + * X-range + * @sample {highcharts} highcharts/css/x-range/ + * Styled mode X-range + * @sample {highcharts} highcharts/chart/inverted-xrange/ + * Inverted X-range + * + * @extends plotOptions.column + * @since 6.0.0 + * @product highcharts highstock gantt + * @excluding boostThreshold, crisp, cropThreshold, depth, edgeColor, + * edgeWidth, findNearestPointBy, getExtremesFromAll, + * negativeColor, pointInterval, pointIntervalUnit, + * pointPlacement, pointRange, pointStart, softThreshold, + * stacking, threshold, data, dataSorting + * @requires modules/xrange + * @optionparent plotOptions.xrange + */ +, { + /** + * A partial fill for each point, typically used to visualize how much + * of a task is performed. The partial fill object can be set either on + * series or point level. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range with partial fill + * + * @product highcharts highstock gantt + * @apioption plotOptions.xrange.partialFill + */ + /** + * The fill color to be used for partial fills. Defaults to a darker + * shade of the point color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock gantt + * @apioption plotOptions.xrange.partialFill.fill + */ + /** + * A partial fill for each point, typically used to visualize how much + * of a task is performed. See [completed](series.gantt.data.completed). + * + * @sample gantt/demo/progress-indicator + * Gantt with progress indicator + * + * @product gantt + * @apioption plotOptions.gantt.partialFill + */ + /** + * In an X-range series, this option makes all points of the same Y-axis + * category the same color. + */ + colorByPoint: true, + dataLabels: { + formatter: function () { + var point = this.point, amount = point.partialFill; + if (isObject(amount)) { + amount = amount.amount; + } + if (isNumber(amount) && amount > 0) { + return correctFloat(amount * 100) + '%'; + } + }, + inside: true, + verticalAlign: 'middle' + }, + tooltip: { + headerFormat: '{point.x} - {point.x2}
', + pointFormat: '\u25CF {series.name}: {point.yCategory}
' + }, + borderRadius: 3, + pointRange: 0 +}, { + type: 'xrange', + parallelArrays: ['x', 'x2', 'y'], + requireSorting: false, + animate: seriesTypes.line.prototype.animate, + cropShoulder: 1, + getExtremesFromAll: true, + autoIncrement: H.noop, + buildKDTree: H.noop, + /* eslint-disable valid-jsdoc */ + /** + * @private + * @function Highcarts.seriesTypes.xrange#init + * @return {void} + */ + init: function () { + seriesTypes.column.prototype.init.apply(this, arguments); + this.options.stacking = void 0; // #13161 + }, + /** + * Borrow the column series metrics, but with swapped axes. This gives + * free access to features like groupPadding, grouping, pointWidth etc. + * + * @private + * @function Highcharts.Series#getColumnMetrics + * + * @return {Highcharts.ColumnMetricsObject} + */ + getColumnMetrics: function () { + var metrics, chart = this.chart; + /** + * @private + */ + function swapAxes() { + chart.series.forEach(function (s) { + var xAxis = s.xAxis; + s.xAxis = s.yAxis; + s.yAxis = xAxis; + }); + } + swapAxes(); + metrics = columnType.prototype.getColumnMetrics.call(this); + swapAxes(); + return metrics; + }, + /** + * Override cropData to show a point where x or x2 is outside visible + * range, but one of them is inside. + * + * @private + * @function Highcharts.Series#cropData + * + * @param {Array} xData + * + * @param {Array} yData + * + * @param {number} min + * + * @param {number} max + * + * @param {number} [cropShoulder] + * + * @return {*} + */ + cropData: function (xData, yData, min, max) { + // Replace xData with x2Data to find the appropriate cropStart + var cropData = Series.prototype.cropData, crop = cropData.call(this, this.x2Data, yData, min, max); + // Re-insert the cropped xData + crop.xData = xData.slice(crop.start, crop.end); + return crop; + }, + /** + * Finds the index of an existing point that matches the given point + * options. + * + * @private + * @function Highcharts.Series#findPointIndex + * @param {object} options The options of the point. + * @returns {number|undefined} Returns index of a matching point, + * returns undefined if no match is found. + */ + findPointIndex: function (options) { + var _a = this, cropped = _a.cropped, cropStart = _a.cropStart, points = _a.points; + var id = options.id; + var pointIndex; + if (id) { + var point = find(points, function (point) { + return point.id === id; + }); + pointIndex = point ? point.index : void 0; + } + if (typeof pointIndex === 'undefined') { + var point = find(points, function (point) { + return (point.x === options.x && + point.x2 === options.x2 && + !point.touched); + }); + pointIndex = point ? point.index : void 0; + } + // Reduce pointIndex if data is cropped + if (cropped && + isNumber(pointIndex) && + isNumber(cropStart) && + pointIndex >= cropStart) { + pointIndex -= cropStart; + } + return pointIndex; + }, + /** + * @private + * @function Highcharts.Series#translatePoint + * + * @param {Highcharts.Point} point + */ + translatePoint: function (point) { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, metrics = series.columnMetrics, options = series.options, minPointLength = options.minPointLength || 0, plotX = point.plotX, posX = pick(point.x2, point.x + (point.len || 0)), plotX2 = xAxis.translate(posX, 0, 0, 0, 1), length = Math.abs(plotX2 - plotX), widthDifference, shapeArgs, partialFill, inverted = this.chart.inverted, borderWidth = pick(options.borderWidth, 1), crisper = borderWidth % 2 / 2, yOffset = metrics.offset, pointHeight = Math.round(metrics.width), dlLeft, dlRight, dlWidth, clipRectWidth, tooltipYOffset; + if (minPointLength) { + widthDifference = minPointLength - length; + if (widthDifference < 0) { + widthDifference = 0; + } + plotX -= widthDifference / 2; + plotX2 += widthDifference / 2; + } + plotX = Math.max(plotX, -10); + plotX2 = clamp(plotX2, -10, xAxis.len + 10); + // Handle individual pointWidth + if (defined(point.options.pointWidth)) { + yOffset -= ((Math.ceil(point.options.pointWidth) - pointHeight) / 2); + pointHeight = Math.ceil(point.options.pointWidth); + } + // Apply pointPlacement to the Y axis + if (options.pointPlacement && + isNumber(point.plotY) && + yAxis.categories) { + point.plotY = yAxis.translate(point.y, 0, 1, 0, 1, options.pointPlacement); + } + point.shapeArgs = { + x: Math.floor(Math.min(plotX, plotX2)) + crisper, + y: Math.floor(point.plotY + yOffset) + crisper, + width: Math.round(Math.abs(plotX2 - plotX)), + height: pointHeight, + r: series.options.borderRadius + }; + // Align data labels inside the shape and inside the plot area + dlLeft = point.shapeArgs.x; + dlRight = dlLeft + point.shapeArgs.width; + if (dlLeft < 0 || dlRight > xAxis.len) { + dlLeft = clamp(dlLeft, 0, xAxis.len); + dlRight = clamp(dlRight, 0, xAxis.len); + dlWidth = dlRight - dlLeft; + point.dlBox = merge(point.shapeArgs, { + x: dlLeft, + width: dlRight - dlLeft, + centerX: dlWidth ? dlWidth / 2 : null + }); + } + else { + point.dlBox = null; + } + // Tooltip position + var tooltipPos = point.tooltipPos; + var xIndex = !inverted ? 0 : 1; + var yIndex = !inverted ? 1 : 0; + tooltipYOffset = series.columnMetrics ? + series.columnMetrics.offset : -metrics.width / 2; + // Limit position by the correct axis size (#9727) + tooltipPos[xIndex] = clamp(tooltipPos[xIndex] + ((!inverted ? 1 : -1) * (xAxis.reversed ? -1 : 1) * + (length / 2)), 0, xAxis.len - 1); + tooltipPos[yIndex] = clamp(tooltipPos[yIndex] + ((inverted ? -1 : 1) * tooltipYOffset), 0, yAxis.len - 1); + // Add a partShapeArgs to the point, based on the shapeArgs property + partialFill = point.partialFill; + if (partialFill) { + // Get the partial fill amount + if (isObject(partialFill)) { + partialFill = partialFill.amount; + } + // If it was not a number, assume 0 + if (!isNumber(partialFill)) { + partialFill = 0; + } + shapeArgs = point.shapeArgs; + point.partShapeArgs = { + x: shapeArgs.x, + y: shapeArgs.y, + width: shapeArgs.width, + height: shapeArgs.height, + r: series.options.borderRadius + }; + clipRectWidth = Math.max(Math.round(length * partialFill + point.plotX - + plotX), 0); + point.clipRectArgs = { + x: xAxis.reversed ? // #10717 + shapeArgs.x + length - clipRectWidth : + shapeArgs.x, + y: shapeArgs.y, + width: clipRectWidth, + height: shapeArgs.height + }; + } + }, + /** + * @private + * @function Highcharts.Series#translate + */ + translate: function () { + columnType.prototype.translate.apply(this, arguments); + this.points.forEach(function (point) { + this.translatePoint(point); + }, this); + }, + /** + * Draws a single point in the series. Needed for partial fill. + * + * This override turns point.graphic into a group containing the + * original graphic and an overlay displaying the partial fill. + * + * @private + * @function Highcharts.Series#drawPoint + * + * @param {Highcharts.Point} point + * An instance of Point in the series. + * + * @param {"animate"|"attr"} verb + * 'animate' (animates changes) or 'attr' (sets options) + */ + drawPoint: function (point, verb) { + var series = this, seriesOpts = series.options, renderer = series.chart.renderer, graphic = point.graphic, type = point.shapeType, shapeArgs = point.shapeArgs, partShapeArgs = point.partShapeArgs, clipRectArgs = point.clipRectArgs, pfOptions = point.partialFill, cutOff = seriesOpts.stacking && !seriesOpts.borderRadius, pointState = point.state, stateOpts = (seriesOpts.states[pointState || 'normal'] || + {}), pointStateVerb = typeof pointState === 'undefined' ? + 'attr' : verb, pointAttr = series.pointAttribs(point, pointState), animation = pick(series.chart.options.chart.animation, stateOpts.animation), fill; + if (!point.isNull && point.visible !== false) { + // Original graphic + if (graphic) { // update + graphic.rect[verb](shapeArgs); + } + else { + point.graphic = graphic = renderer.g('point') + .addClass(point.getClassName()) + .add(point.group || series.group); + graphic.rect = renderer[type](merge(shapeArgs)) + .addClass(point.getClassName()) + .addClass('highcharts-partfill-original') + .add(graphic); + } + // Partial fill graphic + if (partShapeArgs) { + if (graphic.partRect) { + graphic.partRect[verb](merge(partShapeArgs)); + graphic.partialClipRect[verb](merge(clipRectArgs)); + } + else { + graphic.partialClipRect = renderer.clipRect(clipRectArgs.x, clipRectArgs.y, clipRectArgs.width, clipRectArgs.height); + graphic.partRect = + renderer[type](partShapeArgs) + .addClass('highcharts-partfill-overlay') + .add(graphic) + .clip(graphic.partialClipRect); + } + } + // Presentational + if (!series.chart.styledMode) { + graphic + .rect[verb](pointAttr, animation) + .shadow(seriesOpts.shadow, null, cutOff); + if (partShapeArgs) { + // Ensure pfOptions is an object + if (!isObject(pfOptions)) { + pfOptions = {}; + } + if (isObject(seriesOpts.partialFill)) { + pfOptions = merge(pfOptions, seriesOpts.partialFill); + } + fill = (pfOptions.fill || + color(pointAttr.fill).brighten(-0.3).get() || + color(point.color || series.color) + .brighten(-0.3).get()); + pointAttr.fill = fill; + graphic + .partRect[pointStateVerb](pointAttr, animation) + .shadow(seriesOpts.shadow, null, cutOff); + } + } + } + else if (graphic) { + point.graphic = graphic.destroy(); // #1269 + } + }, + /** + * @private + * @function Highcharts.Series#drawPoints + */ + drawPoints: function () { + var series = this, verb = series.getAnimationVerb(); + // Draw the columns + series.points.forEach(function (point) { + series.drawPoint(point, verb); + }); + }, + /** + * Returns "animate", or "attr" if the number of points is above the + * animation limit. + * + * @private + * @function Highcharts.Series#getAnimationVerb + * + * @return {string} + */ + getAnimationVerb: function () { + return (this.chart.pointCount < (this.options.animationLimit || 250) ? + 'animate' : + 'attr'); + } + /* + // Override to remove stroke from points. For partial fill. + pointAttribs: function () { + var series = this, + retVal = columnType.prototype.pointAttribs + .apply(series, arguments); + + //retVal['stroke-width'] = 0; + return retVal; + } + //*/ + /* eslint-enable valid-jsdoc */ +}, { + /** + * The ending X value of the range point. + * @name Highcharts.Point#x2 + * @type {number|undefined} + * @requires modules/xrange + */ + /** + * Extend applyOptions so that `colorByPoint` for x-range means that one + * color is applied per Y axis category. + * + * @private + * @function Highcharts.Point#applyOptions + * + * @return {Highcharts.Series} + */ + /* eslint-disable valid-jsdoc */ + /** + * @private + */ + resolveColor: function () { + var series = this.series, colorByPoint; + if (series.options.colorByPoint && !this.options.color) { + colorByPoint = getColorByCategory(series, this); + if (!series.chart.styledMode) { + this.color = colorByPoint.color; + } + if (!this.options.colorIndex) { + this.colorIndex = colorByPoint.colorIndex; + } + } + else if (!this.color) { + this.color = series.color; + } + }, + /** + * Extend init to have y default to 0. + * + * @private + * @function Highcharts.Point#init + * + * @return {Highcharts.Point} + */ + init: function () { + Point.prototype.init.apply(this, arguments); + if (!this.y) { + this.y = 0; + } + return this; + }, + /** + * @private + * @function Highcharts.Point#setState + */ + setState: function () { + Point.prototype.setState.apply(this, arguments); + this.series.drawPoint(this, this.series.getAnimationVerb()); + }, + /** + * @private + * @function Highcharts.Point#getLabelConfig + * + * @return {Highcharts.PointLabelObject} + */ + // Add x2 and yCategory to the available properties for tooltip formats + getLabelConfig: function () { + var point = this, cfg = Point.prototype.getLabelConfig.call(point), yCats = point.series.yAxis.categories; + cfg.x2 = point.x2; + cfg.yCategory = point.yCategory = yCats && yCats[point.y]; + return cfg; + }, + tooltipDateKeys: ['x', 'x2'], + /** + * @private + * @function Highcharts.Point#isValid + * + * @return {boolean} + */ + isValid: function () { + return typeof this.x === 'number' && + typeof this.x2 === 'number'; + } + /* eslint-enable valid-jsdoc */ +}); +/** + * Max x2 should be considered in xAxis extremes + */ +addEvent(Axis, 'afterGetSeriesExtremes', function () { + var axis = this, // eslint-disable-line no-invalid-this + axisSeries = axis.series, dataMax, modMax; + if (axis.isXAxis) { + dataMax = pick(axis.dataMax, -Number.MAX_VALUE); + axisSeries.forEach(function (series) { + if (series.x2Data) { + series.x2Data + .forEach(function (val) { + if (val > dataMax) { + dataMax = val; + modMax = true; + } + }); + } + }); + if (modMax) { + axis.dataMax = dataMax; + } + } +}); +/** + * An `xrange` series. If the [type](#series.xrange.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.xrange + * @excluding boostThreshold, crisp, cropThreshold, depth, edgeColor, edgeWidth, + * findNearestPointBy, getExtremesFromAll, negativeColor, + * pointInterval, pointIntervalUnit, pointPlacement, pointRange, + * pointStart, softThreshold, stacking, threshold, dataSorting + * @product highcharts highstock gantt + * @requires modules/xrange + * @apioption series.xrange + */ +/** + * An array of data points for the series. For the `xrange` series type, + * points can be given in the following ways: + * + * 1. An array of objects with named values. The objects are point configuration + * objects as seen below. + * ```js + * data: [{ + * x: Date.UTC(2017, 0, 1), + * x2: Date.UTC(2017, 0, 3), + * name: "Test", + * y: 0, + * color: "#00FF00" + * }, { + * x: Date.UTC(2017, 0, 4), + * x2: Date.UTC(2017, 0, 5), + * name: "Deploy", + * y: 1, + * color: "#FF0000" + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @declare Highcharts.XrangePointOptionsObject + * @type {Array<*>} + * @extends series.line.data + * @product highcharts highstock gantt + * @apioption series.xrange.data + */ +/** + * The starting X value of the range point. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range + * + * @type {number} + * @product highcharts highstock gantt + * @apioption series.xrange.data.x + */ +/** + * The ending X value of the range point. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range + * + * @type {number} + * @product highcharts highstock gantt + * @apioption series.xrange.data.x2 + */ +/** + * The Y value of the range point. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range + * + * @type {number} + * @product highcharts highstock gantt + * @apioption series.xrange.data.y + */ +/** + * A partial fill for each point, typically used to visualize how much of + * a task is performed. The partial fill object can be set either on series + * or point level. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range with partial fill + * + * @declare Highcharts.XrangePointPartialFillOptionsObject + * @product highcharts highstock gantt + * @apioption series.xrange.data.partialFill + */ +/** + * The amount of the X-range point to be filled. Values can be 0-1 and are + * converted to percentages in the default data label formatter. + * + * @type {number} + * @product highcharts highstock gantt + * @apioption series.xrange.data.partialFill.amount + */ +/** + * The fill color to be used for partial fills. Defaults to a darker shade + * of the point color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock gantt + * @apioption series.xrange.data.partialFill.fill + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/parts-3d/Axis3D.js b/librerias/gantt/code/es-modules/parts-3d/Axis3D.js new file mode 100644 index 0000000..5b5986f --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-3d/Axis3D.js @@ -0,0 +1,606 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * Extenstion for 3d axes + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import Tick from '../parts/Tick.js'; +import Tick3D from './Tick3D.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, merge = U.merge, pick = U.pick, wrap = U.wrap; +var deg2rad = H.deg2rad, perspective = H.perspective, perspective3D = H.perspective3D, shapeArea = H.shapeArea; +/* eslint-disable valid-jsdoc */ +/** + * Adds 3D support to axes. + * @private + * @class + */ +var Axis3DAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + /** + * @private + */ + function Axis3DAdditions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * @private + * @param {Highcharts.Axis} axis + * Related axis. + * @param {Highcharts.Position3dObject} pos + * Position to fix. + * @param {boolean} [isTitle] + * Whether this is a title position. + * @return {Highcharts.Position3dObject} + * Fixed position. + */ + Axis3DAdditions.prototype.fix3dPosition = function (pos, isTitle) { + var axis3D = this; + var axis = axis3D.axis; + var chart = axis.chart; + // Do not do this if the chart is not 3D + if (axis.coll === 'colorAxis' || + !chart.is3d()) { + return pos; + } + var alpha = deg2rad * chart.options.chart.options3d.alpha, beta = deg2rad * chart.options.chart.options3d.beta, positionMode = pick(isTitle && axis.options.title.position3d, axis.options.labels.position3d), skew = pick(isTitle && axis.options.title.skew3d, axis.options.labels.skew3d), frame = chart.frame3d, plotLeft = chart.plotLeft, plotRight = chart.plotWidth + plotLeft, plotTop = chart.plotTop, plotBottom = chart.plotHeight + plotTop, + // Indicates that we are labelling an X or Z axis on the "back" of + // the chart + reverseFlap = false, offsetX = 0, offsetY = 0, vecX, vecY = { x: 0, y: 1, z: 0 }; + pos = axis.axis3D.swapZ({ x: pos.x, y: pos.y, z: 0 }); + if (axis.isZAxis) { // Z Axis + if (axis.opposite) { + if (frame.axes.z.top === null) { + return {}; + } + offsetY = pos.y - plotTop; + pos.x = frame.axes.z.top.x; + pos.y = frame.axes.z.top.y; + vecX = frame.axes.z.top.xDir; + reverseFlap = !frame.top.frontFacing; + } + else { + if (frame.axes.z.bottom === null) { + return {}; + } + offsetY = pos.y - plotBottom; + pos.x = frame.axes.z.bottom.x; + pos.y = frame.axes.z.bottom.y; + vecX = frame.axes.z.bottom.xDir; + reverseFlap = !frame.bottom.frontFacing; + } + } + else if (axis.horiz) { // X Axis + if (axis.opposite) { + if (frame.axes.x.top === null) { + return {}; + } + offsetY = pos.y - plotTop; + pos.y = frame.axes.x.top.y; + pos.z = frame.axes.x.top.z; + vecX = frame.axes.x.top.xDir; + reverseFlap = !frame.top.frontFacing; + } + else { + if (frame.axes.x.bottom === null) { + return {}; + } + offsetY = pos.y - plotBottom; + pos.y = frame.axes.x.bottom.y; + pos.z = frame.axes.x.bottom.z; + vecX = frame.axes.x.bottom.xDir; + reverseFlap = !frame.bottom.frontFacing; + } + } + else { // Y Axis + if (axis.opposite) { + if (frame.axes.y.right === null) { + return {}; + } + offsetX = pos.x - plotRight; + pos.x = frame.axes.y.right.x; + pos.z = frame.axes.y.right.z; + vecX = frame.axes.y.right.xDir; + // Rotate 90º on opposite edge + vecX = { x: vecX.z, y: vecX.y, z: -vecX.x }; + } + else { + if (frame.axes.y.left === null) { + return {}; + } + offsetX = pos.x - plotLeft; + pos.x = frame.axes.y.left.x; + pos.z = frame.axes.y.left.z; + vecX = frame.axes.y.left.xDir; + } + } + if (positionMode === 'chart') { + // Labels preserve their direction relative to the chart + // nothing to do + } + else if (positionMode === 'flap') { + // Labels are rotated around the axis direction to face the screen + if (!axis.horiz) { // Y Axis + vecX = { x: Math.cos(beta), y: 0, z: Math.sin(beta) }; + } + else { // X and Z Axis + var sin = Math.sin(alpha); + var cos = Math.cos(alpha); + if (axis.opposite) { + sin = -sin; + } + if (reverseFlap) { + sin = -sin; + } + vecY = { x: vecX.z * sin, y: cos, z: -vecX.x * sin }; + } + } + else if (positionMode === 'ortho') { + // Labels will be rotated to be ortogonal to the axis + if (!axis.horiz) { // Y Axis + vecX = { x: Math.cos(beta), y: 0, z: Math.sin(beta) }; + } + else { // X and Z Axis + var sina = Math.sin(alpha); + var cosa = Math.cos(alpha); + var sinb = Math.sin(beta); + var cosb = Math.cos(beta); + var vecZ = { x: sinb * cosa, y: -sina, z: -cosa * cosb }; + vecY = { + x: vecX.y * vecZ.z - vecX.z * vecZ.y, + y: vecX.z * vecZ.x - vecX.x * vecZ.z, + z: vecX.x * vecZ.y - vecX.y * vecZ.x + }; + var scale = 1 / Math.sqrt(vecY.x * vecY.x + vecY.y * vecY.y + vecY.z * vecY.z); + if (reverseFlap) { + scale = -scale; + } + vecY = { x: scale * vecY.x, y: scale * vecY.y, z: scale * vecY.z }; + } + } + else { // positionMode == 'offset' + // Labels will be skewd to maintain vertical / horizontal offsets + // from axis + if (!axis.horiz) { // Y Axis + vecX = { x: Math.cos(beta), y: 0, z: Math.sin(beta) }; + } + else { // X and Z Axis + vecY = { + x: Math.sin(beta) * Math.sin(alpha), + y: Math.cos(alpha), + z: -Math.cos(beta) * Math.sin(alpha) + }; + } + } + pos.x += offsetX * vecX.x + offsetY * vecY.x; + pos.y += offsetX * vecX.y + offsetY * vecY.y; + pos.z += offsetX * vecX.z + offsetY * vecY.z; + var projected = perspective([pos], axis.chart)[0]; + if (skew) { + // Check if the label text would be mirrored + var isMirrored = shapeArea(perspective([ + pos, + { x: pos.x + vecX.x, y: pos.y + vecX.y, z: pos.z + vecX.z }, + { x: pos.x + vecY.x, y: pos.y + vecY.y, z: pos.z + vecY.z } + ], axis.chart)) < 0; + if (isMirrored) { + vecX = { x: -vecX.x, y: -vecX.y, z: -vecX.z }; + } + var pointsProjected = perspective([ + { x: pos.x, y: pos.y, z: pos.z }, + { x: pos.x + vecX.x, y: pos.y + vecX.y, z: pos.z + vecX.z }, + { x: pos.x + vecY.x, y: pos.y + vecY.y, z: pos.z + vecY.z } + ], axis.chart); + projected.matrix = [ + pointsProjected[1].x - pointsProjected[0].x, + pointsProjected[1].y - pointsProjected[0].y, + pointsProjected[2].x - pointsProjected[0].x, + pointsProjected[2].y - pointsProjected[0].y, + projected.x, + projected.y + ]; + projected.matrix[4] -= projected.x * projected.matrix[0] + + projected.y * projected.matrix[2]; + projected.matrix[5] -= projected.x * projected.matrix[1] + + projected.y * projected.matrix[3]; + } + return projected; + }; + /** + * @private + */ + Axis3DAdditions.prototype.swapZ = function (p, insidePlotArea) { + var axis = this.axis; + if (axis.isZAxis) { + var plotLeft = insidePlotArea ? 0 : axis.chart.plotLeft; + return { + x: plotLeft + p.z, + y: p.y, + z: p.x - plotLeft + }; + } + return p; + }; + return Axis3DAdditions; +}()); +/** + * Axis with 3D support. + * @private + * @class + */ +var Axis3D = /** @class */ (function () { + function Axis3D() { + } + /* * + * + * Static Functions + * + * */ + /** + * Extends axis class with 3D support. + * @private + */ + Axis3D.compose = function (AxisClass) { + merge(true, AxisClass.defaultOptions, Axis3D.defaultOptions); + AxisClass.keepProps.push('axis3D'); + addEvent(AxisClass, 'init', Axis3D.onInit); + addEvent(AxisClass, 'afterSetOptions', Axis3D.onAfterSetOptions); + addEvent(AxisClass, 'drawCrosshair', Axis3D.onDrawCrosshair); + addEvent(AxisClass, 'destroy', Axis3D.onDestroy); + var axisProto = AxisClass.prototype; + wrap(axisProto, 'getLinePath', Axis3D.wrapGetLinePath); + wrap(axisProto, 'getPlotBandPath', Axis3D.wrapGetPlotBandPath); + wrap(axisProto, 'getPlotLinePath', Axis3D.wrapGetPlotLinePath); + wrap(axisProto, 'getSlotWidth', Axis3D.wrapGetSlotWidth); + wrap(axisProto, 'getTitlePosition', Axis3D.wrapGetTitlePosition); + Tick3D.compose(Tick); + }; + /** + * @private + */ + Axis3D.onAfterSetOptions = function () { + var axis = this; + var chart = axis.chart; + var options = axis.options; + if (chart.is3d && chart.is3d() && axis.coll !== 'colorAxis') { + options.tickWidth = pick(options.tickWidth, 0); + options.gridLineWidth = pick(options.gridLineWidth, 1); + } + }; + /** + * @private + */ + Axis3D.onDestroy = function () { + ['backFrame', 'bottomFrame', 'sideFrame'].forEach(function (prop) { + if (this[prop]) { + this[prop] = this[prop].destroy(); + } + }, this); + }; + /** + * @private + */ + Axis3D.onDrawCrosshair = function (e) { + var axis = this; + if (axis.chart.is3d() && + axis.coll !== 'colorAxis') { + if (e.point) { + e.point.crosshairPos = axis.isXAxis ? + e.point.axisXpos : + axis.len - e.point.axisYpos; + } + } + }; + /** + * @private + */ + Axis3D.onInit = function () { + var axis = this; + if (!axis.axis3D) { + axis.axis3D = new Axis3DAdditions(axis); + } + }; + /** + * Do not draw axislines in 3D. + * @private + */ + Axis3D.wrapGetLinePath = function (proceed) { + var axis = this; + // Do not do this if the chart is not 3D + if (!axis.chart.is3d() || axis.coll === 'colorAxis') { + return proceed.apply(axis, [].slice.call(arguments, 1)); + } + return []; + }; + /** + * @private + */ + Axis3D.wrapGetPlotBandPath = function (proceed) { + // Do not do this if the chart is not 3D + if (!this.chart.is3d() || this.coll === 'colorAxis') { + return proceed.apply(this, [].slice.call(arguments, 1)); + } + var args = arguments, from = args[1], to = args[2], path = [], fromPath = this.getPlotLinePath({ value: from }), toPath = this.getPlotLinePath({ value: to }); + if (fromPath && toPath) { + for (var i = 0; i < fromPath.length; i += 2) { + var fromStartSeg = fromPath[i], fromEndSeg = fromPath[i + 1], toStartSeg = toPath[i], toEndSeg = toPath[i + 1]; + if (fromStartSeg[0] === 'M' && + fromEndSeg[0] === 'L' && + toStartSeg[0] === 'M' && + toEndSeg[0] === 'L') { + path.push(fromStartSeg, fromEndSeg, toEndSeg, + // lineTo instead of moveTo + ['L', toStartSeg[1], toStartSeg[2]], ['Z']); + } + } + } + return path; + }; + /** + * @private + */ + Axis3D.wrapGetPlotLinePath = function (proceed) { + var axis = this; + var axis3D = axis.axis3D; + var chart = axis.chart; + var path = proceed.apply(axis, [].slice.call(arguments, 1)); + // Do not do this if the chart is not 3D + if (!chart.is3d() || axis.coll === 'colorAxis') { + return path; + } + if (path === null) { + return path; + } + var options3d = chart.options.chart.options3d, d = axis.isZAxis ? chart.plotWidth : options3d.depth, frame = chart.frame3d, startSegment = path[0], endSegment = path[1], pArr, pathSegments = []; + if (startSegment[0] === 'M' && endSegment[0] === 'L') { + pArr = [ + axis3D.swapZ({ x: startSegment[1], y: startSegment[2], z: 0 }), + axis3D.swapZ({ x: startSegment[1], y: startSegment[2], z: d }), + axis3D.swapZ({ x: endSegment[1], y: endSegment[2], z: 0 }), + axis3D.swapZ({ x: endSegment[1], y: endSegment[2], z: d }) + ]; + if (!this.horiz) { // Y-Axis + if (frame.front.visible) { + pathSegments.push(pArr[0], pArr[2]); + } + if (frame.back.visible) { + pathSegments.push(pArr[1], pArr[3]); + } + if (frame.left.visible) { + pathSegments.push(pArr[0], pArr[1]); + } + if (frame.right.visible) { + pathSegments.push(pArr[2], pArr[3]); + } + } + else if (this.isZAxis) { // Z-Axis + if (frame.left.visible) { + pathSegments.push(pArr[0], pArr[2]); + } + if (frame.right.visible) { + pathSegments.push(pArr[1], pArr[3]); + } + if (frame.top.visible) { + pathSegments.push(pArr[0], pArr[1]); + } + if (frame.bottom.visible) { + pathSegments.push(pArr[2], pArr[3]); + } + } + else { // X-Axis + if (frame.front.visible) { + pathSegments.push(pArr[0], pArr[2]); + } + if (frame.back.visible) { + pathSegments.push(pArr[1], pArr[3]); + } + if (frame.top.visible) { + pathSegments.push(pArr[0], pArr[1]); + } + if (frame.bottom.visible) { + pathSegments.push(pArr[2], pArr[3]); + } + } + pathSegments = perspective(pathSegments, this.chart, false); + } + return chart.renderer.toLineSegments(pathSegments); + }; + /** + * Wrap getSlotWidth function to calculate individual width value for each + * slot (#8042). + * @private + */ + Axis3D.wrapGetSlotWidth = function (proceed, tick) { + var axis = this; + var chart = axis.chart; + var ticks = axis.ticks; + var gridGroup = axis.gridGroup; + if (axis.categories && + chart.frameShapes && + chart.is3d() && + gridGroup && + tick && + tick.label) { + var firstGridLine = gridGroup.element.childNodes[0].getBBox(), frame3DLeft = chart.frameShapes.left.getBBox(), options3d = chart.options.chart.options3d, origin = { + x: chart.plotWidth / 2, + y: chart.plotHeight / 2, + z: options3d.depth / 2, + vd: pick(options3d.depth, 1) * pick(options3d.viewDistance, 0) + }, labelPos, prevLabelPos, nextLabelPos, slotWidth, tickId = tick.pos, prevTick = ticks[tickId - 1], nextTick = ticks[tickId + 1]; + // Check whether the tick is not the first one and previous tick + // exists, then calculate position of previous label. + if (tickId !== 0 && prevTick && prevTick.label.xy) { + prevLabelPos = perspective3D({ + x: prevTick.label.xy.x, + y: prevTick.label.xy.y, + z: null + }, origin, origin.vd); + } + // If next label position is defined, then recalculate its position + // basing on the perspective. + if (nextTick && nextTick.label.xy) { + nextLabelPos = perspective3D({ + x: nextTick.label.xy.x, + y: nextTick.label.xy.y, + z: null + }, origin, origin.vd); + } + labelPos = { + x: tick.label.xy.x, + y: tick.label.xy.y, + z: null + }; + labelPos = perspective3D(labelPos, origin, origin.vd); + // If tick is first one, check whether next label position is + // already calculated, then return difference between the first and + // the second label. If there is no next label position calculated, + // return the difference between the first grid line and left 3d + // frame. + slotWidth = Math.abs(prevLabelPos ? + labelPos.x - prevLabelPos.x : nextLabelPos ? + nextLabelPos.x - labelPos.x : + firstGridLine.x - frame3DLeft.x); + return slotWidth; + } + return proceed.apply(axis, [].slice.call(arguments, 1)); + }; + /** + * @private + */ + Axis3D.wrapGetTitlePosition = function (proceed) { + var pos = proceed.apply(this, [].slice.call(arguments, 1)); + return this.axis3D ? + this.axis3D.fix3dPosition(pos, true) : + pos; + }; + /* * + * + * Static Properties + * + * */ + /** + * @optionparent xAxis + */ + Axis3D.defaultOptions = { + labels: { + /** + * Defines how the labels are be repositioned according to the 3D + * chart orientation. + * + * - `'offset'`: Maintain a fixed horizontal/vertical distance from + * the tick marks, despite the chart orientation. This is the + * backwards compatible behavior, and causes skewing of X and Z + * axes. + * + * - `'chart'`: Preserve 3D position relative to the chart. This + * looks nice, but hard to read if the text isn't forward-facing. + * + * - `'flap'`: Rotated text along the axis to compensate for the + * chart orientation. This tries to maintain text as legible as + * possible on all orientations. + * + * - `'ortho'`: Rotated text along the axis direction so that the + * labels are orthogonal to the axis. This is very similar to + * `'flap'`, but prevents skewing the labels (X and Y scaling are + * still present). + * + * @sample highcharts/3d/skewed-labels/ + * Skewed labels + * + * @since 5.0.15 + * @validvalue ['offset', 'chart', 'flap', 'ortho'] + * @product highcharts + * @requires highcharts-3d + */ + position3d: 'offset', + /** + * If enabled, the axis labels will skewed to follow the + * perspective. + * + * This will fix overlapping labels and titles, but texts become + * less legible due to the distortion. + * + * The final appearance depends heavily on `labels.position3d`. + * + * @sample highcharts/3d/skewed-labels/ + * Skewed labels + * + * @since 5.0.15 + * @product highcharts + * @requires highcharts-3d + */ + skew3d: false + }, + title: { + /** + * Defines how the title is repositioned according to the 3D chart + * orientation. + * + * - `'offset'`: Maintain a fixed horizontal/vertical distance from + * the tick marks, despite the chart orientation. This is the + * backwards compatible behavior, and causes skewing of X and Z + * axes. + * + * - `'chart'`: Preserve 3D position relative to the chart. This + * looks nice, but hard to read if the text isn't forward-facing. + * + * - `'flap'`: Rotated text along the axis to compensate for the + * chart orientation. This tries to maintain text as legible as + * possible on all orientations. + * + * - `'ortho'`: Rotated text along the axis direction so that the + * labels are orthogonal to the axis. This is very similar to + * `'flap'`, but prevents skewing the labels (X and Y scaling are + * still present). + * + * - `undefined`: Will use the config from `labels.position3d` + * + * @sample highcharts/3d/skewed-labels/ + * Skewed labels + * + * @type {"offset"|"chart"|"flap"|"ortho"|null} + * @since 5.0.15 + * @product highcharts + * @requires highcharts-3d + */ + position3d: null, + /** + * If enabled, the axis title will skewed to follow the perspective. + * + * This will fix overlapping labels and titles, but texts become + * less legible due to the distortion. + * + * The final appearance depends heavily on `title.position3d`. + * + * A `null` value will use the config from `labels.skew3d`. + * + * @sample highcharts/3d/skewed-labels/ + * Skewed labels + * + * @type {boolean|null} + * @since 5.0.15 + * @product highcharts + * @requires highcharts-3d + */ + skew3d: null + } + }; + return Axis3D; +}()); +export default Axis3D; diff --git a/librerias/gantt/code/es-modules/parts-3d/Chart.js b/librerias/gantt/code/es-modules/parts-3d/Chart.js new file mode 100644 index 0000000..b598d77 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-3d/Chart.js @@ -0,0 +1,1577 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * Extension for 3D charts + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Axis from '../parts/Axis.js'; +import Axis3D from './Axis3D.js'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, Fx = U.Fx, isArray = U.isArray, merge = U.merge, pick = U.pick, wrap = U.wrap; +import ZAxis from './ZAxis.js'; +import '../parts/Chart.js'; +var Chart = H.Chart, perspective = H.perspective; +/** + * Shorthand to check the is3d flag. + * @private + * @return {boolean} + * Whether it is a 3D chart. + */ +Chart.prototype.is3d = function () { + return (this.options.chart.options3d && + this.options.chart.options3d.enabled); // #4280 +}; +Chart.prototype.propsRequireDirtyBox.push('chart.options3d'); +Chart.prototype.propsRequireUpdateSeries.push('chart.options3d'); +/* eslint-disable no-invalid-this */ +// Legacy support for HC < 6 to make 'scatter' series in a 3D chart route to the +// real 'scatter3d' series type. +addEvent(Chart, 'afterInit', function () { + var options = this.options; + if (this.is3d()) { + (options.series || []).forEach(function (s) { + var type = s.type || + options.chart.type || + options.chart.defaultSeriesType; + if (type === 'scatter') { + s.type = 'scatter3d'; + } + }); + } +}); +// And do it on dynamic add (#8407) +addEvent(Chart, 'addSeries', function (e) { + if (this.is3d()) { + if (e.options.type === 'scatter') { + e.options.type = 'scatter3d'; + } + } +}); +/** + * Calculate scale of the 3D view. That is required to + * fit chart's 3D projection into the actual plotting area. Reported as #4933. + * @notice This function should ideally take the plot values instead of a chart + * object, but since the chart object is needed for perspective it is + * not practical. Possible to make both getScale and perspective more + * logical and also immutable. + * + * @private + * @function getScale + * + * @param {Highcharts.Chart} chart + * Chart object + * + * @param {number} depth + * The depth of the chart + * + * @return {number} + * The scale to fit the 3D chart into the plotting area. + * + * @requires highcharts-3d + */ +function getScale(chart, depth) { + var plotLeft = chart.plotLeft, plotRight = chart.plotWidth + plotLeft, plotTop = chart.plotTop, plotBottom = chart.plotHeight + plotTop, originX = plotLeft + chart.plotWidth / 2, originY = plotTop + chart.plotHeight / 2, bbox3d = { + minX: Number.MAX_VALUE, + maxX: -Number.MAX_VALUE, + minY: Number.MAX_VALUE, + maxY: -Number.MAX_VALUE + }, corners, scale = 1; + // Top left corners: + corners = [{ + x: plotLeft, + y: plotTop, + z: 0 + }, { + x: plotLeft, + y: plotTop, + z: depth + }]; + // Top right corners: + [0, 1].forEach(function (i) { + corners.push({ + x: plotRight, + y: corners[i].y, + z: corners[i].z + }); + }); + // All bottom corners: + [0, 1, 2, 3].forEach(function (i) { + corners.push({ + x: corners[i].x, + y: plotBottom, + z: corners[i].z + }); + }); + // Calculate 3D corners: + corners = perspective(corners, chart, false); + // Get bounding box of 3D element: + corners.forEach(function (corner) { + bbox3d.minX = Math.min(bbox3d.minX, corner.x); + bbox3d.maxX = Math.max(bbox3d.maxX, corner.x); + bbox3d.minY = Math.min(bbox3d.minY, corner.y); + bbox3d.maxY = Math.max(bbox3d.maxY, corner.y); + }); + // Left edge: + if (plotLeft > bbox3d.minX) { + scale = Math.min(scale, 1 - Math.abs((plotLeft + originX) / (bbox3d.minX + originX)) % 1); + } + // Right edge: + if (plotRight < bbox3d.maxX) { + scale = Math.min(scale, (plotRight - originX) / (bbox3d.maxX - originX)); + } + // Top edge: + if (plotTop > bbox3d.minY) { + if (bbox3d.minY < 0) { + scale = Math.min(scale, (plotTop + originY) / (-bbox3d.minY + plotTop + originY)); + } + else { + scale = Math.min(scale, 1 - (plotTop + originY) / (bbox3d.minY + originY) % 1); + } + } + // Bottom edge: + if (plotBottom < bbox3d.maxY) { + scale = Math.min(scale, Math.abs((plotBottom - originY) / (bbox3d.maxY - originY))); + } + return scale; +} +wrap(H.Chart.prototype, 'isInsidePlot', function (proceed) { + return this.is3d() || proceed.apply(this, [].slice.call(arguments, 1)); +}); +var defaultOptions = H.getOptions(); +/** + * @optionparent + */ +var extendedOptions = { + chart: { + /** + * Options to render charts in 3 dimensions. This feature requires + * `highcharts-3d.js`, found in the download package or online at + * [code.highcharts.com/highcharts-3d.js](https://code.highcharts.com/highcharts-3d.js). + * + * @since 4.0 + * @product highcharts + * @requires highcharts-3d + */ + options3d: { + /** + * Wether to render the chart using the 3D functionality. + * + * @since 4.0 + * @product highcharts + */ + enabled: false, + /** + * One of the two rotation angles for the chart. + * + * @since 4.0 + * @product highcharts + */ + alpha: 0, + /** + * One of the two rotation angles for the chart. + * + * @since 4.0 + * @product highcharts + */ + beta: 0, + /** + * The total depth of the chart. + * + * @since 4.0 + * @product highcharts + */ + depth: 100, + /** + * Whether the 3d box should automatically adjust to the chart plot + * area. + * + * @since 4.2.4 + * @product highcharts + */ + fitToPlot: true, + /** + * Defines the distance the viewer is standing in front of the + * chart, this setting is important to calculate the perspective + * effect in column and scatter charts. It is not used for 3D pie + * charts. + * + * @since 4.0 + * @product highcharts + */ + viewDistance: 25, + /** + * Set it to `"auto"` to automatically move the labels to the best + * edge. + * + * @type {"auto"|null} + * @since 5.0.12 + * @product highcharts + */ + axisLabelPosition: null, + /** + * Provides the option to draw a frame around the charts by defining + * a bottom, front and back panel. + * + * @since 4.0 + * @product highcharts + * @requires highcharts-3d + */ + frame: { + /** + * Whether the frames are visible. + */ + visible: 'default', + /** + * General pixel thickness for the frame faces. + */ + size: 1, + /** + * The bottom of the frame around a 3D chart. + * + * @since 4.0 + * @product highcharts + * @requires highcharts-3d + */ + /** + * The color of the panel. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default transparent + * @since 4.0 + * @product highcharts + * @apioption chart.options3d.frame.bottom.color + */ + /** + * The thickness of the panel. + * + * @type {number} + * @default 1 + * @since 4.0 + * @product highcharts + * @apioption chart.options3d.frame.bottom.size + */ + /** + * Whether to display the frame. Possible values are `true`, + * `false`, `"auto"` to display only the frames behind the data, + * and `"default"` to display faces behind the data based on the + * axis layout, ignoring the point of view. + * + * @sample {highcharts} highcharts/3d/scatter-frame/ + * Auto frames + * + * @type {boolean|"default"|"auto"} + * @default default + * @since 5.0.12 + * @product highcharts + * @apioption chart.options3d.frame.bottom.visible + */ + /** + * The bottom of the frame around a 3D chart. + */ + bottom: {}, + /** + * The top of the frame around a 3D chart. + * + * @extends chart.options3d.frame.bottom + */ + top: {}, + /** + * The left side of the frame around a 3D chart. + * + * @extends chart.options3d.frame.bottom + */ + left: {}, + /** + * The right of the frame around a 3D chart. + * + * @extends chart.options3d.frame.bottom + */ + right: {}, + /** + * The back side of the frame around a 3D chart. + * + * @extends chart.options3d.frame.bottom + */ + back: {}, + /** + * The front of the frame around a 3D chart. + * + * @extends chart.options3d.frame.bottom + */ + front: {} + } + } + } +}; +merge(true, defaultOptions, extendedOptions); +// Add the required CSS classes for column sides (#6018) +addEvent(Chart, 'afterGetContainer', function () { + if (this.styledMode) { + this.renderer.definition({ + tagName: 'style', + textContent: '.highcharts-3d-top{' + + 'filter: url(#highcharts-brighter)' + + '}\n' + + '.highcharts-3d-side{' + + 'filter: url(#highcharts-darker)' + + '}\n' + }); + // Add add definitions used by brighter and darker faces of the cuboids. + [{ + name: 'darker', + slope: 0.6 + }, { + name: 'brighter', + slope: 1.4 + }].forEach(function (cfg) { + this.renderer.definition({ + tagName: 'filter', + id: 'highcharts-' + cfg.name, + children: [{ + tagName: 'feComponentTransfer', + children: [{ + tagName: 'feFuncR', + type: 'linear', + slope: cfg.slope + }, { + tagName: 'feFuncG', + type: 'linear', + slope: cfg.slope + }, { + tagName: 'feFuncB', + type: 'linear', + slope: cfg.slope + }] + }] + }); + }, this); + } +}); +wrap(Chart.prototype, 'setClassName', function (proceed) { + proceed.apply(this, [].slice.call(arguments, 1)); + if (this.is3d()) { + this.container.className += ' highcharts-3d-chart'; + } +}); +addEvent(H.Chart, 'afterSetChartSize', function () { + var chart = this, options3d = chart.options.chart.options3d; + if (chart.is3d()) { + // Add a 0-360 normalisation for alfa and beta angles in 3d graph + if (options3d) { + options3d.alpha = options3d.alpha % 360 + (options3d.alpha >= 0 ? 0 : 360); + options3d.beta = options3d.beta % 360 + (options3d.beta >= 0 ? 0 : 360); + } + var inverted = chart.inverted, clipBox = chart.clipBox, margin = chart.margin, x = inverted ? 'y' : 'x', y = inverted ? 'x' : 'y', w = inverted ? 'height' : 'width', h = inverted ? 'width' : 'height'; + clipBox[x] = -(margin[3] || 0); + clipBox[y] = -(margin[0] || 0); + clipBox[w] = + chart.chartWidth + (margin[3] || 0) + (margin[1] || 0); + clipBox[h] = + chart.chartHeight + (margin[0] || 0) + (margin[2] || 0); + // Set scale, used later in perspective method(): + // getScale uses perspective, so scale3d has to be reset. + chart.scale3d = 1; + if (options3d.fitToPlot === true) { + chart.scale3d = getScale(chart, options3d.depth); + } + // Recalculate the 3d frame with every call of setChartSize, + // instead of doing it after every redraw(). It avoids ticks + // and axis title outside of chart. + chart.frame3d = this.get3dFrame(); // #7942 + } +}); +addEvent(Chart, 'beforeRedraw', function () { + if (this.is3d()) { + // Set to force a redraw of all elements + this.isDirtyBox = true; + } +}); +addEvent(Chart, 'beforeRender', function () { + if (this.is3d()) { + this.frame3d = this.get3dFrame(); + } +}); +// Draw the series in the reverse order (#3803, #3917) +wrap(Chart.prototype, 'renderSeries', function (proceed) { + var series, i = this.series.length; + if (this.is3d()) { + while (i--) { + series = this.series[i]; + series.translate(); + series.render(); + } + } + else { + proceed.call(this); + } +}); +addEvent(Chart, 'afterDrawChartBox', function () { + if (this.is3d()) { + var chart = this, renderer = chart.renderer, options3d = this.options.chart.options3d, frame = chart.get3dFrame(), xm = this.plotLeft, xp = this.plotLeft + this.plotWidth, ym = this.plotTop, yp = this.plotTop + this.plotHeight, zm = 0, zp = options3d.depth, xmm = xm - (frame.left.visible ? frame.left.size : 0), xpp = xp + (frame.right.visible ? frame.right.size : 0), ymm = ym - (frame.top.visible ? frame.top.size : 0), ypp = yp + (frame.bottom.visible ? frame.bottom.size : 0), zmm = zm - (frame.front.visible ? frame.front.size : 0), zpp = zp + (frame.back.visible ? frame.back.size : 0), verb = chart.hasRendered ? 'animate' : 'attr'; + this.frame3d = frame; + if (!this.frameShapes) { + this.frameShapes = { + bottom: renderer.polyhedron().add(), + top: renderer.polyhedron().add(), + left: renderer.polyhedron().add(), + right: renderer.polyhedron().add(), + back: renderer.polyhedron().add(), + front: renderer.polyhedron().add() + }; + } + this.frameShapes.bottom[verb]({ + 'class': 'highcharts-3d-frame highcharts-3d-frame-bottom', + zIndex: frame.bottom.frontFacing ? -1000 : 1000, + faces: [{ + fill: H.color(frame.bottom.color).brighten(0.1).get(), + vertexes: [{ + x: xmm, + y: ypp, + z: zmm + }, { + x: xpp, + y: ypp, + z: zmm + }, { + x: xpp, + y: ypp, + z: zpp + }, { + x: xmm, + y: ypp, + z: zpp + }], + enabled: frame.bottom.visible + }, + { + fill: H.color(frame.bottom.color).brighten(0.1).get(), + vertexes: [{ + x: xm, + y: yp, + z: zp + }, { + x: xp, + y: yp, + z: zp + }, { + x: xp, + y: yp, + z: zm + }, { + x: xm, + y: yp, + z: zm + }], + enabled: frame.bottom.visible + }, + { + fill: H.color(frame.bottom.color).brighten(-0.1).get(), + vertexes: [{ + x: xmm, + y: ypp, + z: zmm + }, { + x: xmm, + y: ypp, + z: zpp + }, { + x: xm, + y: yp, + z: zp + }, { + x: xm, + y: yp, + z: zm + }], + enabled: frame.bottom.visible && !frame.left.visible + }, + { + fill: H.color(frame.bottom.color).brighten(-0.1).get(), + vertexes: [{ + x: xpp, + y: ypp, + z: zpp + }, { + x: xpp, + y: ypp, + z: zmm + }, { + x: xp, + y: yp, + z: zm + }, { + x: xp, + y: yp, + z: zp + }], + enabled: frame.bottom.visible && !frame.right.visible + }, + { + fill: H.color(frame.bottom.color).get(), + vertexes: [{ + x: xpp, + y: ypp, + z: zmm + }, { + x: xmm, + y: ypp, + z: zmm + }, { + x: xm, + y: yp, + z: zm + }, { + x: xp, + y: yp, + z: zm + }], + enabled: frame.bottom.visible && !frame.front.visible + }, + { + fill: H.color(frame.bottom.color).get(), + vertexes: [{ + x: xmm, + y: ypp, + z: zpp + }, { + x: xpp, + y: ypp, + z: zpp + }, { + x: xp, + y: yp, + z: zp + }, { + x: xm, + y: yp, + z: zp + }], + enabled: frame.bottom.visible && !frame.back.visible + }] + }); + this.frameShapes.top[verb]({ + 'class': 'highcharts-3d-frame highcharts-3d-frame-top', + zIndex: frame.top.frontFacing ? -1000 : 1000, + faces: [{ + fill: H.color(frame.top.color).brighten(0.1).get(), + vertexes: [{ + x: xmm, + y: ymm, + z: zpp + }, { + x: xpp, + y: ymm, + z: zpp + }, { + x: xpp, + y: ymm, + z: zmm + }, { + x: xmm, + y: ymm, + z: zmm + }], + enabled: frame.top.visible + }, + { + fill: H.color(frame.top.color).brighten(0.1).get(), + vertexes: [{ + x: xm, + y: ym, + z: zm + }, { + x: xp, + y: ym, + z: zm + }, { + x: xp, + y: ym, + z: zp + }, { + x: xm, + y: ym, + z: zp + }], + enabled: frame.top.visible + }, + { + fill: H.color(frame.top.color).brighten(-0.1).get(), + vertexes: [{ + x: xmm, + y: ymm, + z: zpp + }, { + x: xmm, + y: ymm, + z: zmm + }, { + x: xm, + y: ym, + z: zm + }, { + x: xm, + y: ym, + z: zp + }], + enabled: frame.top.visible && !frame.left.visible + }, + { + fill: H.color(frame.top.color).brighten(-0.1).get(), + vertexes: [{ + x: xpp, + y: ymm, + z: zmm + }, { + x: xpp, + y: ymm, + z: zpp + }, { + x: xp, + y: ym, + z: zp + }, { + x: xp, + y: ym, + z: zm + }], + enabled: frame.top.visible && !frame.right.visible + }, + { + fill: H.color(frame.top.color).get(), + vertexes: [{ + x: xmm, + y: ymm, + z: zmm + }, { + x: xpp, + y: ymm, + z: zmm + }, { + x: xp, + y: ym, + z: zm + }, { + x: xm, + y: ym, + z: zm + }], + enabled: frame.top.visible && !frame.front.visible + }, + { + fill: H.color(frame.top.color).get(), + vertexes: [{ + x: xpp, + y: ymm, + z: zpp + }, { + x: xmm, + y: ymm, + z: zpp + }, { + x: xm, + y: ym, + z: zp + }, { + x: xp, + y: ym, + z: zp + }], + enabled: frame.top.visible && !frame.back.visible + }] + }); + this.frameShapes.left[verb]({ + 'class': 'highcharts-3d-frame highcharts-3d-frame-left', + zIndex: frame.left.frontFacing ? -1000 : 1000, + faces: [{ + fill: H.color(frame.left.color).brighten(0.1).get(), + vertexes: [{ + x: xmm, + y: ypp, + z: zmm + }, { + x: xm, + y: yp, + z: zm + }, { + x: xm, + y: yp, + z: zp + }, { + x: xmm, + y: ypp, + z: zpp + }], + enabled: frame.left.visible && !frame.bottom.visible + }, + { + fill: H.color(frame.left.color).brighten(0.1).get(), + vertexes: [{ + x: xmm, + y: ymm, + z: zpp + }, { + x: xm, + y: ym, + z: zp + }, { + x: xm, + y: ym, + z: zm + }, { + x: xmm, + y: ymm, + z: zmm + }], + enabled: frame.left.visible && !frame.top.visible + }, + { + fill: H.color(frame.left.color).brighten(-0.1).get(), + vertexes: [{ + x: xmm, + y: ypp, + z: zpp + }, { + x: xmm, + y: ymm, + z: zpp + }, { + x: xmm, + y: ymm, + z: zmm + }, { + x: xmm, + y: ypp, + z: zmm + }], + enabled: frame.left.visible + }, + { + fill: H.color(frame.left.color).brighten(-0.1).get(), + vertexes: [{ + x: xm, + y: ym, + z: zp + }, { + x: xm, + y: yp, + z: zp + }, { + x: xm, + y: yp, + z: zm + }, { + x: xm, + y: ym, + z: zm + }], + enabled: frame.left.visible + }, + { + fill: H.color(frame.left.color).get(), + vertexes: [{ + x: xmm, + y: ypp, + z: zmm + }, { + x: xmm, + y: ymm, + z: zmm + }, { + x: xm, + y: ym, + z: zm + }, { + x: xm, + y: yp, + z: zm + }], + enabled: frame.left.visible && !frame.front.visible + }, + { + fill: H.color(frame.left.color).get(), + vertexes: [{ + x: xmm, + y: ymm, + z: zpp + }, { + x: xmm, + y: ypp, + z: zpp + }, { + x: xm, + y: yp, + z: zp + }, { + x: xm, + y: ym, + z: zp + }], + enabled: frame.left.visible && !frame.back.visible + }] + }); + this.frameShapes.right[verb]({ + 'class': 'highcharts-3d-frame highcharts-3d-frame-right', + zIndex: frame.right.frontFacing ? -1000 : 1000, + faces: [{ + fill: H.color(frame.right.color).brighten(0.1).get(), + vertexes: [{ + x: xpp, + y: ypp, + z: zpp + }, { + x: xp, + y: yp, + z: zp + }, { + x: xp, + y: yp, + z: zm + }, { + x: xpp, + y: ypp, + z: zmm + }], + enabled: frame.right.visible && !frame.bottom.visible + }, + { + fill: H.color(frame.right.color).brighten(0.1).get(), + vertexes: [{ + x: xpp, + y: ymm, + z: zmm + }, { + x: xp, + y: ym, + z: zm + }, { + x: xp, + y: ym, + z: zp + }, { + x: xpp, + y: ymm, + z: zpp + }], + enabled: frame.right.visible && !frame.top.visible + }, + { + fill: H.color(frame.right.color).brighten(-0.1).get(), + vertexes: [{ + x: xp, + y: ym, + z: zm + }, { + x: xp, + y: yp, + z: zm + }, { + x: xp, + y: yp, + z: zp + }, { + x: xp, + y: ym, + z: zp + }], + enabled: frame.right.visible + }, + { + fill: H.color(frame.right.color).brighten(-0.1).get(), + vertexes: [{ + x: xpp, + y: ypp, + z: zmm + }, { + x: xpp, + y: ymm, + z: zmm + }, { + x: xpp, + y: ymm, + z: zpp + }, { + x: xpp, + y: ypp, + z: zpp + }], + enabled: frame.right.visible + }, + { + fill: H.color(frame.right.color).get(), + vertexes: [{ + x: xpp, + y: ymm, + z: zmm + }, { + x: xpp, + y: ypp, + z: zmm + }, { + x: xp, + y: yp, + z: zm + }, { + x: xp, + y: ym, + z: zm + }], + enabled: frame.right.visible && !frame.front.visible + }, + { + fill: H.color(frame.right.color).get(), + vertexes: [{ + x: xpp, + y: ypp, + z: zpp + }, { + x: xpp, + y: ymm, + z: zpp + }, { + x: xp, + y: ym, + z: zp + }, { + x: xp, + y: yp, + z: zp + }], + enabled: frame.right.visible && !frame.back.visible + }] + }); + this.frameShapes.back[verb]({ + 'class': 'highcharts-3d-frame highcharts-3d-frame-back', + zIndex: frame.back.frontFacing ? -1000 : 1000, + faces: [{ + fill: H.color(frame.back.color).brighten(0.1).get(), + vertexes: [{ + x: xpp, + y: ypp, + z: zpp + }, { + x: xmm, + y: ypp, + z: zpp + }, { + x: xm, + y: yp, + z: zp + }, { + x: xp, + y: yp, + z: zp + }], + enabled: frame.back.visible && !frame.bottom.visible + }, + { + fill: H.color(frame.back.color).brighten(0.1).get(), + vertexes: [{ + x: xmm, + y: ymm, + z: zpp + }, { + x: xpp, + y: ymm, + z: zpp + }, { + x: xp, + y: ym, + z: zp + }, { + x: xm, + y: ym, + z: zp + }], + enabled: frame.back.visible && !frame.top.visible + }, + { + fill: H.color(frame.back.color).brighten(-0.1).get(), + vertexes: [{ + x: xmm, + y: ypp, + z: zpp + }, { + x: xmm, + y: ymm, + z: zpp + }, { + x: xm, + y: ym, + z: zp + }, { + x: xm, + y: yp, + z: zp + }], + enabled: frame.back.visible && !frame.left.visible + }, + { + fill: H.color(frame.back.color).brighten(-0.1).get(), + vertexes: [{ + x: xpp, + y: ymm, + z: zpp + }, { + x: xpp, + y: ypp, + z: zpp + }, { + x: xp, + y: yp, + z: zp + }, { + x: xp, + y: ym, + z: zp + }], + enabled: frame.back.visible && !frame.right.visible + }, + { + fill: H.color(frame.back.color).get(), + vertexes: [{ + x: xm, + y: ym, + z: zp + }, { + x: xp, + y: ym, + z: zp + }, { + x: xp, + y: yp, + z: zp + }, { + x: xm, + y: yp, + z: zp + }], + enabled: frame.back.visible + }, + { + fill: H.color(frame.back.color).get(), + vertexes: [{ + x: xmm, + y: ypp, + z: zpp + }, { + x: xpp, + y: ypp, + z: zpp + }, { + x: xpp, + y: ymm, + z: zpp + }, { + x: xmm, + y: ymm, + z: zpp + }], + enabled: frame.back.visible + }] + }); + this.frameShapes.front[verb]({ + 'class': 'highcharts-3d-frame highcharts-3d-frame-front', + zIndex: frame.front.frontFacing ? -1000 : 1000, + faces: [{ + fill: H.color(frame.front.color).brighten(0.1).get(), + vertexes: [{ + x: xmm, + y: ypp, + z: zmm + }, { + x: xpp, + y: ypp, + z: zmm + }, { + x: xp, + y: yp, + z: zm + }, { + x: xm, + y: yp, + z: zm + }], + enabled: frame.front.visible && !frame.bottom.visible + }, + { + fill: H.color(frame.front.color).brighten(0.1).get(), + vertexes: [{ + x: xpp, + y: ymm, + z: zmm + }, { + x: xmm, + y: ymm, + z: zmm + }, { + x: xm, + y: ym, + z: zm + }, { + x: xp, + y: ym, + z: zm + }], + enabled: frame.front.visible && !frame.top.visible + }, + { + fill: H.color(frame.front.color).brighten(-0.1).get(), + vertexes: [{ + x: xmm, + y: ymm, + z: zmm + }, { + x: xmm, + y: ypp, + z: zmm + }, { + x: xm, + y: yp, + z: zm + }, { + x: xm, + y: ym, + z: zm + }], + enabled: frame.front.visible && !frame.left.visible + }, + { + fill: H.color(frame.front.color).brighten(-0.1).get(), + vertexes: [{ + x: xpp, + y: ypp, + z: zmm + }, { + x: xpp, + y: ymm, + z: zmm + }, { + x: xp, + y: ym, + z: zm + }, { + x: xp, + y: yp, + z: zm + }], + enabled: frame.front.visible && !frame.right.visible + }, + { + fill: H.color(frame.front.color).get(), + vertexes: [{ + x: xp, + y: ym, + z: zm + }, { + x: xm, + y: ym, + z: zm + }, { + x: xm, + y: yp, + z: zm + }, { + x: xp, + y: yp, + z: zm + }], + enabled: frame.front.visible + }, + { + fill: H.color(frame.front.color).get(), + vertexes: [{ + x: xpp, + y: ypp, + z: zmm + }, { + x: xmm, + y: ypp, + z: zmm + }, { + x: xmm, + y: ymm, + z: zmm + }, { + x: xpp, + y: ymm, + z: zmm + }], + enabled: frame.front.visible + }] + }); + } +}); +Chart.prototype.retrieveStacks = function (stacking) { + var series = this.series, stacks = {}, stackNumber, i = 1; + this.series.forEach(function (s) { + stackNumber = pick(s.options.stack, (stacking ? 0 : series.length - 1 - s.index)); // #3841, #4532 + if (!stacks[stackNumber]) { + stacks[stackNumber] = { series: [s], position: i }; + i++; + } + else { + stacks[stackNumber].series.push(s); + } + }); + stacks.totalStacks = i + 1; + return stacks; +}; +Chart.prototype.get3dFrame = function () { + var chart = this, options3d = chart.options.chart.options3d, frameOptions = options3d.frame, xm = chart.plotLeft, xp = chart.plotLeft + chart.plotWidth, ym = chart.plotTop, yp = chart.plotTop + chart.plotHeight, zm = 0, zp = options3d.depth, faceOrientation = function (vertexes) { + var area = H.shapeArea3d(vertexes, chart); + // Give it 0.5 squared-pixel as a margin for rounding errors. + if (area > 0.5) { + return 1; + } + if (area < -0.5) { + return -1; + } + return 0; + }, bottomOrientation = faceOrientation([ + { x: xm, y: yp, z: zp }, + { x: xp, y: yp, z: zp }, + { x: xp, y: yp, z: zm }, + { x: xm, y: yp, z: zm } + ]), topOrientation = faceOrientation([ + { x: xm, y: ym, z: zm }, + { x: xp, y: ym, z: zm }, + { x: xp, y: ym, z: zp }, + { x: xm, y: ym, z: zp } + ]), leftOrientation = faceOrientation([ + { x: xm, y: ym, z: zm }, + { x: xm, y: ym, z: zp }, + { x: xm, y: yp, z: zp }, + { x: xm, y: yp, z: zm } + ]), rightOrientation = faceOrientation([ + { x: xp, y: ym, z: zp }, + { x: xp, y: ym, z: zm }, + { x: xp, y: yp, z: zm }, + { x: xp, y: yp, z: zp } + ]), frontOrientation = faceOrientation([ + { x: xm, y: yp, z: zm }, + { x: xp, y: yp, z: zm }, + { x: xp, y: ym, z: zm }, + { x: xm, y: ym, z: zm } + ]), backOrientation = faceOrientation([ + { x: xm, y: ym, z: zp }, + { x: xp, y: ym, z: zp }, + { x: xp, y: yp, z: zp }, + { x: xm, y: yp, z: zp } + ]), defaultShowBottom = false, defaultShowTop = false, defaultShowLeft = false, defaultShowRight = false, defaultShowFront = false, defaultShowBack = true; + // The 'default' criteria to visible faces of the frame is looking up every + // axis to decide whenever the left/right//top/bottom sides of the frame + // will be shown + [] + .concat(chart.xAxis, chart.yAxis, chart.zAxis) + .forEach(function (axis) { + if (axis) { + if (axis.horiz) { + if (axis.opposite) { + defaultShowTop = true; + } + else { + defaultShowBottom = true; + } + } + else { + if (axis.opposite) { + defaultShowRight = true; + } + else { + defaultShowLeft = true; + } + } + } + }); + var getFaceOptions = function (sources, faceOrientation, defaultVisible) { + var faceAttrs = ['size', 'color', 'visible']; + var options = {}; + for (var i = 0; i < faceAttrs.length; i++) { + var attr = faceAttrs[i]; + for (var j = 0; j < sources.length; j++) { + if (typeof sources[j] === 'object') { + var val = sources[j][attr]; + if (typeof val !== 'undefined' && val !== null) { + options[attr] = val; + break; + } + } + } + } + var isVisible = defaultVisible; + if (options.visible === true || options.visible === false) { + isVisible = options.visible; + } + else if (options.visible === 'auto') { + isVisible = faceOrientation > 0; + } + return { + size: pick(options.size, 1), + color: pick(options.color, 'none'), + frontFacing: faceOrientation > 0, + visible: isVisible + }; + }; + // docs @TODO: Add all frame options (left, right, top, bottom, front, back) + // to apioptions JSDoc once the new system is up. + var ret = { + axes: {}, + // FIXME: Previously, left/right, top/bottom and front/back pairs shared + // size and color. + // For compatibility and consistency sake, when one face have + // size/color/visibility set, the opposite face will default to the same + // values. Also, left/right used to be called 'side', so that's also + // added as a fallback + bottom: getFaceOptions([frameOptions.bottom, frameOptions.top, frameOptions], bottomOrientation, defaultShowBottom), + top: getFaceOptions([frameOptions.top, frameOptions.bottom, frameOptions], topOrientation, defaultShowTop), + left: getFaceOptions([ + frameOptions.left, + frameOptions.right, + frameOptions.side, + frameOptions + ], leftOrientation, defaultShowLeft), + right: getFaceOptions([ + frameOptions.right, + frameOptions.left, + frameOptions.side, + frameOptions + ], rightOrientation, defaultShowRight), + back: getFaceOptions([frameOptions.back, frameOptions.front, frameOptions], backOrientation, defaultShowBack), + front: getFaceOptions([frameOptions.front, frameOptions.back, frameOptions], frontOrientation, defaultShowFront) + }; + // Decide the bast place to put axis title/labels based on the visible + // faces. Ideally, The labels can only be on the edge between a visible face + // and an invisble one. Also, the Y label should be one the left-most edge + // (right-most if opposite), + if (options3d.axisLabelPosition === 'auto') { + var isValidEdge = function (face1, face2) { + return ((face1.visible !== face2.visible) || + (face1.visible && + face2.visible && + (face1.frontFacing !== face2.frontFacing))); + }; + var yEdges = []; + if (isValidEdge(ret.left, ret.front)) { + yEdges.push({ + y: (ym + yp) / 2, + x: xm, + z: zm, + xDir: { x: 1, y: 0, z: 0 } + }); + } + if (isValidEdge(ret.left, ret.back)) { + yEdges.push({ + y: (ym + yp) / 2, + x: xm, + z: zp, + xDir: { x: 0, y: 0, z: -1 } + }); + } + if (isValidEdge(ret.right, ret.front)) { + yEdges.push({ + y: (ym + yp) / 2, + x: xp, + z: zm, + xDir: { x: 0, y: 0, z: 1 } + }); + } + if (isValidEdge(ret.right, ret.back)) { + yEdges.push({ + y: (ym + yp) / 2, + x: xp, + z: zp, + xDir: { x: -1, y: 0, z: 0 } + }); + } + var xBottomEdges = []; + if (isValidEdge(ret.bottom, ret.front)) { + xBottomEdges.push({ + x: (xm + xp) / 2, + y: yp, + z: zm, + xDir: { x: 1, y: 0, z: 0 } + }); + } + if (isValidEdge(ret.bottom, ret.back)) { + xBottomEdges.push({ + x: (xm + xp) / 2, + y: yp, + z: zp, + xDir: { x: -1, y: 0, z: 0 } + }); + } + var xTopEdges = []; + if (isValidEdge(ret.top, ret.front)) { + xTopEdges.push({ + x: (xm + xp) / 2, + y: ym, + z: zm, + xDir: { x: 1, y: 0, z: 0 } + }); + } + if (isValidEdge(ret.top, ret.back)) { + xTopEdges.push({ + x: (xm + xp) / 2, + y: ym, + z: zp, + xDir: { x: -1, y: 0, z: 0 } + }); + } + var zBottomEdges = []; + if (isValidEdge(ret.bottom, ret.left)) { + zBottomEdges.push({ + z: (zm + zp) / 2, + y: yp, + x: xm, + xDir: { x: 0, y: 0, z: -1 } + }); + } + if (isValidEdge(ret.bottom, ret.right)) { + zBottomEdges.push({ + z: (zm + zp) / 2, + y: yp, + x: xp, + xDir: { x: 0, y: 0, z: 1 } + }); + } + var zTopEdges = []; + if (isValidEdge(ret.top, ret.left)) { + zTopEdges.push({ + z: (zm + zp) / 2, + y: ym, + x: xm, + xDir: { x: 0, y: 0, z: -1 } + }); + } + if (isValidEdge(ret.top, ret.right)) { + zTopEdges.push({ + z: (zm + zp) / 2, + y: ym, + x: xp, + xDir: { x: 0, y: 0, z: 1 } + }); + } + var pickEdge = function (edges, axis, mult) { + if (edges.length === 0) { + return null; + } + if (edges.length === 1) { + return edges[0]; + } + var best = 0, projections = perspective(edges, chart, false); + for (var i = 1; i < projections.length; i++) { + if (mult * projections[i][axis] > + mult * projections[best][axis]) { + best = i; + } + else if ((mult * projections[i][axis] === + mult * projections[best][axis]) && + (projections[i].z < projections[best].z)) { + best = i; + } + } + return edges[best]; + }; + ret.axes = { + y: { + 'left': pickEdge(yEdges, 'x', -1), + 'right': pickEdge(yEdges, 'x', +1) + }, + x: { + 'top': pickEdge(xTopEdges, 'y', -1), + 'bottom': pickEdge(xBottomEdges, 'y', +1) + }, + z: { + 'top': pickEdge(zTopEdges, 'y', -1), + 'bottom': pickEdge(zBottomEdges, 'y', +1) + } + }; + } + else { + ret.axes = { + y: { + 'left': { x: xm, z: zm, xDir: { x: 1, y: 0, z: 0 } }, + 'right': { x: xp, z: zm, xDir: { x: 0, y: 0, z: 1 } } + }, + x: { + 'top': { y: ym, z: zm, xDir: { x: 1, y: 0, z: 0 } }, + 'bottom': { y: yp, z: zm, xDir: { x: 1, y: 0, z: 0 } } + }, + z: { + 'top': { + x: defaultShowLeft ? xp : xm, + y: ym, + xDir: defaultShowLeft ? + { x: 0, y: 0, z: 1 } : + { x: 0, y: 0, z: -1 } + }, + 'bottom': { + x: defaultShowLeft ? xp : xm, + y: yp, + xDir: defaultShowLeft ? + { x: 0, y: 0, z: 1 } : + { x: 0, y: 0, z: -1 } + } + } + }; + } + return ret; +}; +// Animation setter for matrix property. +Fx.prototype.matrixSetter = function () { + var interpolated; + if (this.pos < 1 && + (isArray(this.start) || isArray(this.end))) { + var start = this.start || [1, 0, 0, 1, 0, 0]; + var end = this.end || [1, 0, 0, 1, 0, 0]; + interpolated = []; + for (var i = 0; i < 6; i++) { + interpolated.push(this.pos * end[i] + (1 - this.pos) * start[i]); + } + } + else { + interpolated = this.end; + } + this.elem.attr(this.prop, interpolated, null, true); +}; +ZAxis.ZChartComposition.compose(Chart); +Axis3D.compose(Axis); +/** + * Note: As of v5.0.12, `frame.left` or `frame.right` should be used instead. + * + * The side for the frame around a 3D chart. + * + * @deprecated + * @since 4.0 + * @product highcharts + * @requires highcharts-3d + * @apioption chart.options3d.frame.side + */ +/** + * The color of the panel. + * + * @deprecated + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default transparent + * @since 4.0 + * @product highcharts + * @apioption chart.options3d.frame.side.color + */ +/** + * The thickness of the panel. + * + * @deprecated + * @type {number} + * @default 1 + * @since 4.0 + * @product highcharts + * @apioption chart.options3d.frame.side.size + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/parts-3d/Column.js b/librerias/gantt/code/es-modules/parts-3d/Column.js new file mode 100644 index 0000000..2cad9d9 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-3d/Column.js @@ -0,0 +1,409 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, pick = U.pick, wrap = U.wrap; +import '../parts/Series.js'; +import StackItem from '../parts/Stacking.js'; +var perspective = H.perspective, Series = H.Series, seriesTypes = H.seriesTypes, svg = H.svg; +/** + * Depth of the columns in a 3D column chart. + * + * @type {number} + * @default 25 + * @since 4.0 + * @product highcharts + * @requires highcharts-3d + * @apioption plotOptions.column.depth + */ +/** + * 3D columns only. The color of the edges. Similar to `borderColor`, except it + * defaults to the same color as the column. + * + * @type {Highcharts.ColorString} + * @product highcharts + * @requires highcharts-3d + * @apioption plotOptions.column.edgeColor + */ +/** + * 3D columns only. The width of the colored edges. + * + * @type {number} + * @default 1 + * @product highcharts + * @requires highcharts-3d + * @apioption plotOptions.column.edgeWidth + */ +/** + * The spacing between columns on the Z Axis in a 3D chart. + * + * @type {number} + * @default 1 + * @since 4.0 + * @product highcharts + * @requires highcharts-3d + * @apioption plotOptions.column.groupZPadding + */ +/* eslint-disable no-invalid-this */ +wrap(seriesTypes.column.prototype, 'translate', function (proceed) { + proceed.apply(this, [].slice.call(arguments, 1)); + // Do not do this if the chart is not 3D + if (this.chart.is3d()) { + this.translate3dShapes(); + } +}); +// Don't use justifyDataLabel when point is outsidePlot +wrap(H.Series.prototype, 'justifyDataLabel', function (proceed) { + return !(arguments[2].outside3dPlot) ? + proceed.apply(this, [].slice.call(arguments, 1)) : + false; +}); +seriesTypes.column.prototype.translate3dPoints = function () { }; +seriesTypes.column.prototype.translate3dShapes = function () { + var series = this, chart = series.chart, seriesOptions = series.options, depth = seriesOptions.depth, stack = seriesOptions.stacking ? + (seriesOptions.stack || 0) : + series.index, // #4743 + z = stack * (depth + (seriesOptions.groupZPadding || 1)), borderCrisp = series.borderWidth % 2 ? 0.5 : 0, point2dPos; // Position of point in 2D, used for 3D position calculation. + if (chart.inverted && !series.yAxis.reversed) { + borderCrisp *= -1; + } + if (seriesOptions.grouping !== false) { + z = 0; + } + z += (seriesOptions.groupZPadding || 1); + series.data.forEach(function (point) { + // #7103 Reset outside3dPlot flag + point.outside3dPlot = null; + if (point.y !== null) { + var shapeArgs = point.shapeArgs, tooltipPos = point.tooltipPos, + // Array for final shapeArgs calculation. + // We are checking two dimensions (x and y). + dimensions = [['x', 'width'], ['y', 'height']], borderlessBase; // Crisped rects can have +/- 0.5 pixels offset. + // #3131 We need to check if column is inside plotArea. + dimensions.forEach(function (d) { + borderlessBase = shapeArgs[d[0]] - borderCrisp; + if (borderlessBase < 0) { + // If borderLessBase is smaller than 0, it is needed to set + // its value to 0 or 0.5 depending on borderWidth + // borderWidth may be even or odd. + shapeArgs[d[1]] += + shapeArgs[d[0]] + borderCrisp; + shapeArgs[d[0]] = -borderCrisp; + borderlessBase = 0; + } + if ((borderlessBase + shapeArgs[d[1]] > + series[d[0] + 'Axis'].len) && + // Do not change height/width of column if 0 (#6708) + shapeArgs[d[1]] !== 0) { + shapeArgs[d[1]] = + series[d[0] + 'Axis'].len - + shapeArgs[d[0]]; + } + if ( + // Do not remove columns with zero height/width. + (shapeArgs[d[1]] !== 0) && + (shapeArgs[d[0]] >= + series[d[0] + 'Axis'].len || + shapeArgs[d[0]] + shapeArgs[d[1]] <= + borderCrisp)) { + // Set args to 0 if column is outside the chart. + for (var key in shapeArgs) { // eslint-disable-line guard-for-in + shapeArgs[key] = 0; + } + // #7103 outside3dPlot flag is set on Points which are + // currently outside of plot. + point.outside3dPlot = true; + } + }); + // Change from 2d to 3d + if (point.shapeType === 'rect') { + point.shapeType = 'cuboid'; + } + shapeArgs.z = z; + shapeArgs.depth = depth; + shapeArgs.insidePlotArea = true; + // Point's position in 2D + point2dPos = { + x: shapeArgs.x + shapeArgs.width / 2, + y: shapeArgs.y, + z: z + depth / 2 // The center of column in Z dimension + }; + // Recalculate point positions for inverted graphs + if (chart.inverted) { + point2dPos.x = shapeArgs.height; + point2dPos.y = point.clientX; + } + // Calculate and store point's position in 3D, + // using perspective method. + point.plot3d = perspective([point2dPos], chart, true, false)[0]; + // Translate the tooltip position in 3d space + tooltipPos = perspective([{ + x: tooltipPos[0], + y: tooltipPos[1], + z: z + depth / 2 // The center of column in Z dimension + }], chart, true, false)[0]; + point.tooltipPos = [tooltipPos.x, tooltipPos.y]; + } + }); + // store for later use #4067 + series.z = z; +}; +wrap(seriesTypes.column.prototype, 'animate', function (proceed) { + if (!this.chart.is3d()) { + proceed.apply(this, [].slice.call(arguments, 1)); + } + else { + var args = arguments, init = args[1], yAxis = this.yAxis, series = this, reversed = this.yAxis.reversed; + if (svg) { // VML is too slow anyway + if (init) { + series.data.forEach(function (point) { + if (point.y !== null) { + point.height = point.shapeArgs.height; + point.shapey = point.shapeArgs.y; // #2968 + point.shapeArgs.height = 1; + if (!reversed) { + if (point.stackY) { + point.shapeArgs.y = + point.plotY + + yAxis.translate(point.stackY); + } + else { + point.shapeArgs.y = + point.plotY + + (point.negative ? + -point.height : + point.height); + } + } + } + }); + } + else { // run the animation + series.data.forEach(function (point) { + if (point.y !== null) { + point.shapeArgs.height = point.height; + point.shapeArgs.y = point.shapey; // #2968 + // null value do not have a graphic + if (point.graphic) { + point.graphic.animate(point.shapeArgs, series.options.animation); + } + } + }); + // redraw datalabels to the correct position + this.drawDataLabels(); + } + } + } +}); +// In case of 3d columns there is no sense to add this columns to a specific +// series group - if series is added to a group all columns will have the same +// zIndex in comparison with different series. +wrap(seriesTypes.column.prototype, 'plotGroup', function (proceed, prop, name, visibility, zIndex, parent) { + if (prop !== 'dataLabelsGroup') { + if (this.chart.is3d()) { + if (this[prop]) { + delete this[prop]; + } + if (parent) { + if (!this.chart.columnGroup) { + this.chart.columnGroup = + this.chart.renderer.g('columnGroup').add(parent); + } + this[prop] = this.chart.columnGroup; + this.chart.columnGroup.attr(this.getPlotBox()); + this[prop].survive = true; + if (prop === 'group' || prop === 'markerGroup') { + arguments[3] = 'visible'; + // For 3D column group and markerGroup should be visible + } + } + } + } + return proceed.apply(this, Array.prototype.slice.call(arguments, 1)); +}); +// When series is not added to group it is needed to change setVisible method to +// allow correct Legend funcionality. This wrap is basing on pie chart series. +wrap(seriesTypes.column.prototype, 'setVisible', function (proceed, vis) { + var series = this, pointVis; + if (series.chart.is3d()) { + series.data.forEach(function (point) { + point.visible = point.options.visible = vis = + typeof vis === 'undefined' ? + !pick(series.visible, point.visible) : vis; + pointVis = vis ? 'visible' : 'hidden'; + series.options.data[series.data.indexOf(point)] = + point.options; + if (point.graphic) { + point.graphic.attr({ + visibility: pointVis + }); + } + }); + } + proceed.apply(this, Array.prototype.slice.call(arguments, 1)); +}); +seriesTypes.column.prototype + .handle3dGrouping = true; +addEvent(Series, 'afterInit', function () { + if (this.chart.is3d() && + this.handle3dGrouping) { + var series = this, seriesOptions = this.options, grouping = seriesOptions.grouping, stacking = seriesOptions.stacking, reversedStacks = pick(this.yAxis.options.reversedStacks, true), z = 0; + // @todo grouping === true ? + if (!(typeof grouping !== 'undefined' && !grouping)) { + var stacks = this.chart.retrieveStacks(stacking), stack = seriesOptions.stack || 0, i; // position within the stack + for (i = 0; i < stacks[stack].series.length; i++) { + if (stacks[stack].series[i] === this) { + break; + } + } + z = (10 * (stacks.totalStacks - stacks[stack].position)) + + (reversedStacks ? i : -i); // #4369 + // In case when axis is reversed, columns are also reversed inside + // the group (#3737) + if (!this.xAxis.reversed) { + z = (stacks.totalStacks * 10) - z; + } + } + seriesOptions.depth = seriesOptions.depth || 25; + series.z = series.z || 0; + seriesOptions.zIndex = z; + } +}); +// eslint-disable-next-line valid-jsdoc +/** + * @private + */ +function pointAttribs(proceed) { + var attr = proceed.apply(this, [].slice.call(arguments, 1)); + if (this.chart.is3d && this.chart.is3d()) { + // Set the fill color to the fill color to provide a smooth edge + attr.stroke = this.options.edgeColor || attr.fill; + attr['stroke-width'] = pick(this.options.edgeWidth, 1); // #4055 + } + return attr; +} +// eslint-disable-next-line valid-jsdoc +/** + * In 3D mode, all column-series are rendered in one main group. Because of that + * we need to apply inactive state on all points. + * @private + */ +function setState(proceed, state, inherit) { + var is3d = this.chart.is3d && this.chart.is3d(); + if (is3d) { + this.options.inactiveOtherPoints = true; + } + proceed.call(this, state, inherit); + if (is3d) { + this.options.inactiveOtherPoints = false; + } +} +// eslint-disable-next-line valid-jsdoc +/** + * In 3D mode, simple checking for a new shape to animate is not enough. + * Additionally check if graphic is a group of elements + * @private + */ +function hasNewShapeType(proceed) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + return this.series.chart.is3d() ? + this.graphic && this.graphic.element.nodeName !== 'g' : + proceed.apply(this, args); +} +wrap(seriesTypes.column.prototype, 'pointAttribs', pointAttribs); +wrap(seriesTypes.column.prototype, 'setState', setState); +wrap(seriesTypes.column.prototype.pointClass.prototype, 'hasNewShapeType', hasNewShapeType); +if (seriesTypes.columnrange) { + wrap(seriesTypes.columnrange.prototype, 'pointAttribs', pointAttribs); + wrap(seriesTypes.columnrange.prototype, 'setState', setState); + wrap(seriesTypes.columnrange.prototype.pointClass.prototype, 'hasNewShapeType', hasNewShapeType); + seriesTypes.columnrange.prototype.plotGroup = + seriesTypes.column.prototype.plotGroup; + seriesTypes.columnrange.prototype.setVisible = + seriesTypes.column.prototype.setVisible; +} +wrap(Series.prototype, 'alignDataLabel', function (proceed, point, dataLabel, options, alignTo) { + var chart = this.chart; + // In 3D we need to pass point.outsidePlot option to the justifyDataLabel + // method for disabling justifying dataLabels in columns outside plot + options.outside3dPlot = point.outside3dPlot; + // Only do this for 3D columns and it's derived series + if (chart.is3d() && + this.is('column')) { + var series = this, seriesOptions = series.options, inside = pick(options.inside, !!series.options.stacking), options3d = chart.options.chart.options3d, xOffset = point.pointWidth / 2 || 0; + var dLPosition = { + x: alignTo.x + xOffset, + y: alignTo.y, + z: series.z + seriesOptions.depth / 2 + }; + if (chart.inverted) { + // Inside dataLabels are positioned according to above + // logic and there is no need to position them using + // non-3D algorighm (that use alignTo.width) + if (inside) { + alignTo.width = 0; + dLPosition.x += point.shapeArgs.height / 2; + } + // When chart is upside down + // (alpha angle between 180 and 360 degrees) + // it is needed to add column width to calculated value. + if (options3d.alpha >= 90 && options3d.alpha <= 270) { + dLPosition.y += point.shapeArgs.width; + } + } + // dLPosition is recalculated for 3D graphs + dLPosition = perspective([dLPosition], chart, true, false)[0]; + alignTo.x = dLPosition.x - xOffset; + // #7103 If point is outside of plotArea, hide data label. + alignTo.y = point.outside3dPlot ? -9e9 : dLPosition.y; + } + proceed.apply(this, [].slice.call(arguments, 1)); +}); +// Added stackLabels position calculation for 3D charts. +wrap(StackItem.prototype, 'getStackBox', function (proceed, chart, stackItem, x, y, xWidth, h, axis) { + var stackBox = proceed.apply(this, [].slice.call(arguments, 1)); + // Only do this for 3D graph + if (chart.is3d() && stackItem.base) { + // First element of stackItem.base is an index of base series. + var baseSeriesInd = +(stackItem.base).split(',')[0]; + var columnSeries = chart.series[baseSeriesInd]; + var options3d = chart.options.chart.options3d; + // Only do this if base series is a column or inherited type, + // use its barW, z and depth parameters + // for correct stackLabels position calculation + if (columnSeries && + columnSeries instanceof seriesTypes.column) { + var dLPosition = { + x: stackBox.x + (chart.inverted ? h : xWidth / 2), + y: stackBox.y, + z: columnSeries.options.depth / 2 + }; + if (chart.inverted) { + // Do not use default offset calculation logic + // for 3D inverted stackLabels. + stackBox.width = 0; + // When chart is upside down + // (alpha angle between 180 and 360 degrees) + // it is needed to add column width to calculated value. + if (options3d.alpha >= 90 && options3d.alpha <= 270) { + dLPosition.y += xWidth; + } + } + dLPosition = perspective([dLPosition], chart, true, false)[0]; + stackBox.x = dLPosition.x - xWidth / 2; + stackBox.y = dLPosition.y; + } + } + return stackBox; +}); diff --git a/librerias/gantt/code/es-modules/parts-3d/Math.js b/librerias/gantt/code/es-modules/parts-3d/Math.js new file mode 100644 index 0000000..9181acf --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-3d/Math.js @@ -0,0 +1,232 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var pick = U.pick; +// Mathematical Functionility +var deg2rad = H.deg2rad; +/* eslint-disable max-len */ +/** + * Apply 3-D rotation + * Euler Angles (XYZ): + * cosA = cos(Alfa|Roll) + * cosB = cos(Beta|Pitch) + * cosG = cos(Gamma|Yaw) + * + * Composite rotation: + * | cosB * cosG | cosB * sinG | -sinB | + * | sinA * sinB * cosG - cosA * sinG | sinA * sinB * sinG + cosA * cosG | sinA * cosB | + * | cosA * sinB * cosG + sinA * sinG | cosA * sinB * sinG - sinA * cosG | cosA * cosB | + * + * Now, Gamma/Yaw is not used (angle=0), so we assume cosG = 1 and sinG = 0, so + * we get: + * | cosB | 0 | - sinB | + * | sinA * sinB | cosA | sinA * cosB | + * | cosA * sinB | - sinA | cosA * cosB | + * + * But in browsers, y is reversed, so we get sinA => -sinA. The general result + * is: + * | cosB | 0 | - sinB | | x | | px | + * | - sinA * sinB | cosA | - sinA * cosB | x | y | = | py | + * | cosA * sinB | sinA | cosA * cosB | | z | | pz | + * + * @private + * @function rotate3D + */ +/* eslint-enable max-len */ +/** + * @private + * @param {number} x + * X coordinate + * @param {number} y + * Y coordinate + * @param {number} z + * Z coordinate + * @param {Highcharts.Rotation3dObject} angles + * Rotation angles + * @return {Highcharts.Rotation3dObject} + * Rotated position + */ +function rotate3D(x, y, z, angles) { + return { + x: angles.cosB * x - angles.sinB * z, + y: -angles.sinA * angles.sinB * x + angles.cosA * y - + angles.cosB * angles.sinA * z, + z: angles.cosA * angles.sinB * x + angles.sinA * y + + angles.cosA * angles.cosB * z + }; +} +/** + * Perspective3D function is available in global Highcharts scope because is + * needed also outside of perspective() function (#8042). + * @private + * @function Highcharts.perspective3D + * + * @param {Highcharts.Position3dObject} coordinate + * 3D position + * + * @param {Highcharts.Position3dObject} origin + * 3D root position + * + * @param {number} distance + * Perspective distance + * + * @return {Highcharts.PositionObject} + * Perspective 3D Position + * + * @requires highcharts-3d + */ +H.perspective3D = function (coordinate, origin, distance) { + var projection = ((distance > 0) && (distance < Number.POSITIVE_INFINITY)) ? + distance / (coordinate.z + origin.z + distance) : + 1; + return { + x: coordinate.x * projection, + y: coordinate.y * projection + }; +}; +/** + * Transforms a given array of points according to the angles in chart.options. + * + * @private + * @function Highcharts.perspective + * + * @param {Array} points + * The array of points + * + * @param {Highcharts.Chart} chart + * The chart + * + * @param {boolean} [insidePlotArea] + * Whether to verifiy that the points are inside the plotArea + * + * @param {boolean} [useInvertedPersp] + * Whether to use inverted perspective in calculations + * + * @return {Array} + * An array of transformed points + * + * @requires highcharts-3d + */ +H.perspective = function (points, chart, insidePlotArea, useInvertedPersp) { + var options3d = chart.options.chart.options3d, + /* The useInvertedPersp argument is used for + * inverted charts with already inverted elements, + * such as dataLabels or tooltip positions. + */ + inverted = pick(useInvertedPersp, insidePlotArea ? chart.inverted : false), origin = { + x: chart.plotWidth / 2, + y: chart.plotHeight / 2, + z: options3d.depth / 2, + vd: pick(options3d.depth, 1) * pick(options3d.viewDistance, 0) + }, scale = chart.scale3d || 1, beta = deg2rad * options3d.beta * (inverted ? -1 : 1), alpha = deg2rad * options3d.alpha * (inverted ? -1 : 1), angles = { + cosA: Math.cos(alpha), + cosB: Math.cos(-beta), + sinA: Math.sin(alpha), + sinB: Math.sin(-beta) + }; + if (!insidePlotArea) { + origin.x += chart.plotLeft; + origin.y += chart.plotTop; + } + // Transform each point + return points.map(function (point) { + var rotated = rotate3D((inverted ? point.y : point.x) - origin.x, (inverted ? point.x : point.y) - origin.y, (point.z || 0) - origin.z, angles), + // Apply perspective + coordinate = H.perspective3D(rotated, origin, origin.vd); + // Apply translation + coordinate.x = coordinate.x * scale + origin.x; + coordinate.y = coordinate.y * scale + origin.y; + coordinate.z = rotated.z * scale + origin.z; + return { + x: (inverted ? coordinate.y : coordinate.x), + y: (inverted ? coordinate.x : coordinate.y), + z: coordinate.z + }; + }); +}; +/** + * Calculate a distance from camera to points - made for calculating zIndex of + * scatter points. + * + * @private + * @function Highcharts.pointCameraDistance + * + * @param {Highcharts.Dictionary} coordinates + * Coordinates of the specific point + * + * @param {Highcharts.Chart} chart + * Related chart + * + * @return {number} + * Distance from camera to point + * + * @requires highcharts-3d + */ +H.pointCameraDistance = function (coordinates, chart) { + var options3d = chart.options.chart.options3d, cameraPosition = { + x: chart.plotWidth / 2, + y: chart.plotHeight / 2, + z: pick(options3d.depth, 1) * pick(options3d.viewDistance, 0) + + options3d.depth + }, + // Added support for objects with plotX or x coordinates. + distance = Math.sqrt(Math.pow(cameraPosition.x - pick(coordinates.plotX, coordinates.x), 2) + + Math.pow(cameraPosition.y - pick(coordinates.plotY, coordinates.y), 2) + + Math.pow(cameraPosition.z - pick(coordinates.plotZ, coordinates.z), 2)); + return distance; +}; +/** + * Calculate area of a 2D polygon using Shoelace algorithm + * https://en.wikipedia.org/wiki/Shoelace_formula + * + * @private + * @function Highcharts.shapeArea + * + * @param {Array} vertexes + * 2D Polygon + * + * @return {number} + * Calculated area + * + * @requires highcharts-3d + */ +H.shapeArea = function (vertexes) { + var area = 0, i, j; + for (i = 0; i < vertexes.length; i++) { + j = (i + 1) % vertexes.length; + area += vertexes[i].x * vertexes[j].y - vertexes[j].x * vertexes[i].y; + } + return area / 2; +}; +/** + * Calculate area of a 3D polygon after perspective projection + * + * @private + * @function Highcharts.shapeArea3d + * + * @param {Array} vertexes + * 3D Polygon + * + * @param {Highcharts.Chart} chart + * Related chart + * + * @param {boolean} [insidePlotArea] + * Whether to verifiy that the points are inside the plotArea + * + * @return {number} + * Calculated area + * + * @requires highcharts-3d + */ +H.shapeArea3d = function (vertexes, chart, insidePlotArea) { + return H.shapeArea(H.perspective(vertexes, chart, insidePlotArea)); +}; diff --git a/librerias/gantt/code/es-modules/parts-3d/Pie.js b/librerias/gantt/code/es-modules/parts-3d/Pie.js new file mode 100644 index 0000000..c8e3cfb --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-3d/Pie.js @@ -0,0 +1,141 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * 3D pie series + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var pick = U.pick, wrap = U.wrap; +var deg2rad = H.deg2rad, seriesTypes = H.seriesTypes, svg = H.svg; +/** + * The thickness of a 3D pie. + * + * @type {number} + * @default 0 + * @since 4.0 + * @product highcharts + * @requires highcharts-3d + * @apioption plotOptions.pie.depth + */ +/* eslint-disable no-invalid-this */ +wrap(seriesTypes.pie.prototype, 'translate', function (proceed) { + proceed.apply(this, [].slice.call(arguments, 1)); + // Do not do this if the chart is not 3D + if (!this.chart.is3d()) { + return; + } + var series = this, seriesOptions = series.options, depth = seriesOptions.depth || 0, options3d = series.chart.options.chart.options3d, alpha = options3d.alpha, beta = options3d.beta, z = seriesOptions.stacking ? + (seriesOptions.stack || 0) * depth : + series._i * depth; + z += depth / 2; + if (seriesOptions.grouping !== false) { + z = 0; + } + series.data.forEach(function (point) { + var shapeArgs = point.shapeArgs, angle; + point.shapeType = 'arc3d'; + shapeArgs.z = z; + shapeArgs.depth = depth * 0.75; + shapeArgs.alpha = alpha; + shapeArgs.beta = beta; + shapeArgs.center = series.center; + angle = (shapeArgs.end + shapeArgs.start) / 2; + point.slicedTranslation = { + translateX: Math.round(Math.cos(angle) * + seriesOptions.slicedOffset * + Math.cos(alpha * deg2rad)), + translateY: Math.round(Math.sin(angle) * + seriesOptions.slicedOffset * + Math.cos(alpha * deg2rad)) + }; + }); +}); +wrap(seriesTypes.pie.prototype.pointClass.prototype, 'haloPath', function (proceed) { + var args = arguments; + return this.series.chart.is3d() ? [] : proceed.call(this, args[1]); +}); +wrap(seriesTypes.pie.prototype, 'pointAttribs', function (proceed, point, state) { + var attr = proceed.call(this, point, state), options = this.options; + if (this.chart.is3d() && !this.chart.styledMode) { + attr.stroke = options.edgeColor || point.color || this.color; + attr['stroke-width'] = pick(options.edgeWidth, 1); + } + return attr; +}); +wrap(seriesTypes.pie.prototype, 'drawDataLabels', function (proceed) { + if (this.chart.is3d()) { + var series = this, chart = series.chart, options3d = chart.options.chart.options3d; + series.data.forEach(function (point) { + var shapeArgs = point.shapeArgs, r = shapeArgs.r, + // #3240 issue with datalabels for 0 and null values + a1 = (shapeArgs.alpha || options3d.alpha) * deg2rad, b1 = (shapeArgs.beta || options3d.beta) * deg2rad, a2 = (shapeArgs.start + shapeArgs.end) / 2, labelPosition = point.labelPosition, connectorPosition = labelPosition.connectorPosition, yOffset = (-r * (1 - Math.cos(a1)) * Math.sin(a2)), xOffset = r * (Math.cos(b1) - 1) * Math.cos(a2); + // Apply perspective on label positions + [ + labelPosition.natural, + connectorPosition.breakAt, + connectorPosition.touchingSliceAt + ].forEach(function (coordinates) { + coordinates.x += xOffset; + coordinates.y += yOffset; + }); + }); + } + proceed.apply(this, [].slice.call(arguments, 1)); +}); +wrap(seriesTypes.pie.prototype, 'addPoint', function (proceed) { + proceed.apply(this, [].slice.call(arguments, 1)); + if (this.chart.is3d()) { + // destroy (and rebuild) everything!!! + this.update(this.userOptions, true); // #3845 pass the old options + } +}); +wrap(seriesTypes.pie.prototype, 'animate', function (proceed) { + if (!this.chart.is3d()) { + proceed.apply(this, [].slice.call(arguments, 1)); + } + else { + var args = arguments, init = args[1], animation = this.options.animation, attribs, center = this.center, group = this.group, markerGroup = this.markerGroup; + if (svg) { // VML is too slow anyway + if (animation === true) { + animation = {}; + } + // Initialize the animation + if (init) { + // Scale down the group and place it in the center + group.oldtranslateX = pick(group.oldtranslateX, group.translateX); + group.oldtranslateY = pick(group.oldtranslateY, group.translateY); + attribs = { + translateX: center[0], + translateY: center[1], + scaleX: 0.001, + scaleY: 0.001 + }; + group.attr(attribs); + if (markerGroup) { + markerGroup.attrSetters = group.attrSetters; + markerGroup.attr(attribs); + } + // Run the animation + } + else { + attribs = { + translateX: group.oldtranslateX, + translateY: group.oldtranslateY, + scaleX: 1, + scaleY: 1 + }; + group.animate(attribs, animation); + if (markerGroup) { + markerGroup.animate(attribs, animation); + } + } + } + } +}); diff --git a/librerias/gantt/code/es-modules/parts-3d/SVGRenderer.js b/librerias/gantt/code/es-modules/parts-3d/SVGRenderer.js new file mode 100644 index 0000000..ac1d409 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-3d/SVGRenderer.js @@ -0,0 +1,876 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * Extensions to the SVGRenderer class to enable 3D shapes + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var animObject = U.animObject, defined = U.defined, extend = U.extend, merge = U.merge, objectEach = U.objectEach, pick = U.pick; +import '../parts/Color.js'; +import '../parts/SvgRenderer.js'; +var cos = Math.cos, PI = Math.PI, sin = Math.sin; +var charts = H.charts, color = H.color, deg2rad = H.deg2rad, perspective = H.perspective, SVGElement = H.SVGElement, SVGRenderer = H.SVGRenderer, +// internal: +dFactor, element3dMethods, cuboidMethods; +/* + EXTENSION TO THE SVG-RENDERER TO ENABLE 3D SHAPES +*/ +// HELPER METHODS +dFactor = (4 * (Math.sqrt(2) - 1) / 3) / (PI / 2); +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * Method to construct a curved path. Can 'wrap' around more then 180 degrees. + * @private + */ +function curveTo(cx, cy, rx, ry, start, end, dx, dy) { + var result = [], arcAngle = end - start; + if ((end > start) && (end - start > Math.PI / 2 + 0.0001)) { + result = result.concat(curveTo(cx, cy, rx, ry, start, start + (Math.PI / 2), dx, dy)); + result = result.concat(curveTo(cx, cy, rx, ry, start + (Math.PI / 2), end, dx, dy)); + return result; + } + if ((end < start) && (start - end > Math.PI / 2 + 0.0001)) { + result = result.concat(curveTo(cx, cy, rx, ry, start, start - (Math.PI / 2), dx, dy)); + result = result.concat(curveTo(cx, cy, rx, ry, start - (Math.PI / 2), end, dx, dy)); + return result; + } + return [[ + 'C', + cx + (rx * Math.cos(start)) - + ((rx * dFactor * arcAngle) * Math.sin(start)) + dx, + cy + (ry * Math.sin(start)) + + ((ry * dFactor * arcAngle) * Math.cos(start)) + dy, + cx + (rx * Math.cos(end)) + + ((rx * dFactor * arcAngle) * Math.sin(end)) + dx, + cy + (ry * Math.sin(end)) - + ((ry * dFactor * arcAngle) * Math.cos(end)) + dy, + cx + (rx * Math.cos(end)) + dx, + cy + (ry * Math.sin(end)) + dy + ]]; +} +SVGRenderer.prototype.toLinePath = function (points, closed) { + var result = []; + // Put "L x y" for each point + points.forEach(function (point) { + result.push(['L', point.x, point.y]); + }); + if (points.length) { + // Set the first element to M + result[0][0] = 'M'; + // If it is a closed line, add Z + if (closed) { + result.push(['Z']); + } + } + return result; +}; +SVGRenderer.prototype.toLineSegments = function (points) { + var result = [], m = true; + points.forEach(function (point) { + result.push(m ? ['M', point.x, point.y] : ['L', point.x, point.y]); + m = !m; + }); + return result; +}; +// A 3-D Face is defined by it's 3D vertexes, and is only visible if it's +// vertexes are counter-clockwise (Back-face culling). It is used as a +// polyhedron Element +SVGRenderer.prototype.face3d = function (args) { + var renderer = this, ret = this.createElement('path'); + ret.vertexes = []; + ret.insidePlotArea = false; + ret.enabled = true; + ret.attr = function (hash) { + if (typeof hash === 'object' && + (defined(hash.enabled) || + defined(hash.vertexes) || + defined(hash.insidePlotArea))) { + this.enabled = pick(hash.enabled, this.enabled); + this.vertexes = pick(hash.vertexes, this.vertexes); + this.insidePlotArea = pick(hash.insidePlotArea, this.insidePlotArea); + delete hash.enabled; + delete hash.vertexes; + delete hash.insidePlotArea; + var chart = charts[renderer.chartIndex], vertexes2d = perspective(this.vertexes, chart, this.insidePlotArea), path = renderer.toLinePath(vertexes2d, true), area = H.shapeArea(vertexes2d), visibility = (this.enabled && area > 0) ? 'visible' : 'hidden'; + hash.d = path; + hash.visibility = visibility; + } + return SVGElement.prototype.attr.apply(this, arguments); + }; + ret.animate = function (params) { + if (typeof params === 'object' && + (defined(params.enabled) || + defined(params.vertexes) || + defined(params.insidePlotArea))) { + this.enabled = pick(params.enabled, this.enabled); + this.vertexes = pick(params.vertexes, this.vertexes); + this.insidePlotArea = pick(params.insidePlotArea, this.insidePlotArea); + delete params.enabled; + delete params.vertexes; + delete params.insidePlotArea; + var chart = charts[renderer.chartIndex], vertexes2d = perspective(this.vertexes, chart, this.insidePlotArea), path = renderer.toLinePath(vertexes2d, true), area = H.shapeArea(vertexes2d), visibility = (this.enabled && area > 0) ? 'visible' : 'hidden'; + params.d = path; + this.attr('visibility', visibility); + } + return SVGElement.prototype.animate.apply(this, arguments); + }; + return ret.attr(args); +}; +// A Polyhedron is a handy way of defining a group of 3-D faces. It's only +// attribute is `faces`, an array of attributes of each one of it's Face3D +// instances. +SVGRenderer.prototype.polyhedron = function (args) { + var renderer = this, result = this.g(), destroy = result.destroy; + if (!this.styledMode) { + result.attr({ + 'stroke-linejoin': 'round' + }); + } + result.faces = []; + // destroy all children + result.destroy = function () { + for (var i = 0; i < result.faces.length; i++) { + result.faces[i].destroy(); + } + return destroy.call(this); + }; + result.attr = function (hash, val, complete, continueAnimation) { + if (typeof hash === 'object' && defined(hash.faces)) { + while (result.faces.length > hash.faces.length) { + result.faces.pop().destroy(); + } + while (result.faces.length < hash.faces.length) { + result.faces.push(renderer.face3d().add(result)); + } + for (var i = 0; i < hash.faces.length; i++) { + if (renderer.styledMode) { + delete hash.faces[i].fill; + } + result.faces[i].attr(hash.faces[i], null, complete, continueAnimation); + } + delete hash.faces; + } + return SVGElement.prototype.attr.apply(this, arguments); + }; + result.animate = function (params, duration, complete) { + if (params && params.faces) { + while (result.faces.length > params.faces.length) { + result.faces.pop().destroy(); + } + while (result.faces.length < params.faces.length) { + result.faces.push(renderer.face3d().add(result)); + } + for (var i = 0; i < params.faces.length; i++) { + result.faces[i].animate(params.faces[i], duration, complete); + } + delete params.faces; + } + return SVGElement.prototype.animate.apply(this, arguments); + }; + return result.attr(args); +}; +// Base, abstract prototype member for 3D elements +element3dMethods = { + /** + * The init is used by base - renderer.Element + * @private + */ + initArgs: function (args) { + var elem3d = this, renderer = elem3d.renderer, paths = renderer[elem3d.pathType + 'Path'](args), zIndexes = paths.zIndexes; + // build parts + elem3d.parts.forEach(function (part) { + elem3d[part] = renderer.path(paths[part]).attr({ + 'class': 'highcharts-3d-' + part, + zIndex: zIndexes[part] || 0 + }).add(elem3d); + }); + elem3d.attr({ + 'stroke-linejoin': 'round', + zIndex: zIndexes.group + }); + // store original destroy + elem3d.originalDestroy = elem3d.destroy; + elem3d.destroy = elem3d.destroyParts; + // Store information if any side of element was rendered by force. + elem3d.forcedSides = paths.forcedSides; + }, + /** + * Single property setter that applies options to each part + * @private + */ + singleSetterForParts: function (prop, val, values, verb, duration, complete) { + var elem3d = this, newAttr = {}, optionsToApply = [null, null, (verb || 'attr'), duration, complete], hasZIndexes = values && values.zIndexes; + if (!values) { + newAttr[prop] = val; + optionsToApply[0] = newAttr; + } + else { + // It is needed to deal with the whole group zIndexing + // in case of graph rotation + if (hasZIndexes && hasZIndexes.group) { + this.attr({ + zIndex: hasZIndexes.group + }); + } + objectEach(values, function (partVal, part) { + newAttr[part] = {}; + newAttr[part][prop] = partVal; + // include zIndexes if provided + if (hasZIndexes) { + newAttr[part].zIndex = values.zIndexes[part] || 0; + } + }); + optionsToApply[1] = newAttr; + } + return elem3d.processParts.apply(elem3d, optionsToApply); + }, + /** + * Calls function for each part. Used for attr, animate and destroy. + * @private + */ + processParts: function (props, partsProps, verb, duration, complete) { + var elem3d = this; + elem3d.parts.forEach(function (part) { + // if different props for different parts + if (partsProps) { + props = pick(partsProps[part], false); + } + // only if something to set, but allow undefined + if (props !== false) { + elem3d[part][verb](props, duration, complete); + } + }); + return elem3d; + }, + /** + * Destroy all parts + * @private + */ + destroyParts: function () { + this.processParts(null, null, 'destroy'); + return this.originalDestroy(); + } +}; +// CUBOID +cuboidMethods = merge(element3dMethods, { + parts: ['front', 'top', 'side'], + pathType: 'cuboid', + attr: function (args, val, complete, continueAnimation) { + // Resolve setting attributes by string name + if (typeof args === 'string' && typeof val !== 'undefined') { + var key = args; + args = {}; + args[key] = val; + } + if (args.shapeArgs || defined(args.x)) { + return this.singleSetterForParts('d', null, this.renderer[this.pathType + 'Path'](args.shapeArgs || args)); + } + return SVGElement.prototype.attr.call(this, args, void 0, complete, continueAnimation); + }, + animate: function (args, duration, complete) { + if (defined(args.x) && defined(args.y)) { + var paths = this.renderer[this.pathType + 'Path'](args), forcedSides = paths.forcedSides; + this.singleSetterForParts('d', null, paths, 'animate', duration, complete); + this.attr({ + zIndex: paths.zIndexes.group + }); + // If sides that are forced to render changed, recalculate colors. + if (forcedSides !== this.forcedSides) { + this.forcedSides = forcedSides; + cuboidMethods.fillSetter.call(this, this.fill); + } + } + else { + SVGElement.prototype.animate.call(this, args, duration, complete); + } + return this; + }, + fillSetter: function (fill) { + var elem3d = this; + elem3d.forcedSides = elem3d.forcedSides || []; + elem3d.singleSetterForParts('fill', null, { + front: fill, + // Do not change color if side was forced to render. + top: color(fill).brighten(elem3d.forcedSides.indexOf('top') >= 0 ? 0 : 0.1).get(), + side: color(fill).brighten(elem3d.forcedSides.indexOf('side') >= 0 ? 0 : -0.1).get() + }); + // fill for animation getter (#6776) + elem3d.color = elem3d.fill = fill; + return elem3d; + } +}); +// set them up +SVGRenderer.prototype.elements3d = { + base: element3dMethods, + cuboid: cuboidMethods +}; +/** + * return result, generalization + * @private + * @requires highcharts-3d + */ +SVGRenderer.prototype.element3d = function (type, shapeArgs) { + // base + var ret = this.g(); + // extend + extend(ret, this.elements3d[type]); + // init + ret.initArgs(shapeArgs); + // return + return ret; +}; +// generelized, so now use simply +SVGRenderer.prototype.cuboid = function (shapeArgs) { + return this.element3d('cuboid', shapeArgs); +}; +// Generates a cuboid path and zIndexes +H.SVGRenderer.prototype.cuboidPath = function (shapeArgs) { + var x = shapeArgs.x, y = shapeArgs.y, z = shapeArgs.z || 0, + // For side calculation (right/left) + // there is a need for height (and other shapeArgs arguments) + // to be at least 1px + h = shapeArgs.height, w = shapeArgs.width, d = shapeArgs.depth, chart = charts[this.chartIndex], front, back, top, bottom, left, right, shape, path1, path2, path3, isFront, isTop, isRight, options3d = chart.options.chart.options3d, alpha = options3d.alpha, + // Priority for x axis is the biggest, + // because of x direction has biggest influence on zIndex + incrementX = 1000000, + // y axis has the smallest priority in case of our charts + // (needs to be set because of stacking) + incrementY = 10, incrementZ = 100, zIndex = 0, + // The 8 corners of the cube + pArr = [{ + x: x, + y: y, + z: z + }, { + x: x + w, + y: y, + z: z + }, { + x: x + w, + y: y + h, + z: z + }, { + x: x, + y: y + h, + z: z + }, { + x: x, + y: y + h, + z: z + d + }, { + x: x + w, + y: y + h, + z: z + d + }, { + x: x + w, + y: y, + z: z + d + }, { + x: x, + y: y, + z: z + d + }], forcedSides = [], pickShape; + // apply perspective + pArr = perspective(pArr, chart, shapeArgs.insidePlotArea); + /** + * helper method to decide which side is visible + * @private + */ + function mapSidePath(i) { + // Added support for 0 value in columns, where height is 0 + // but the shape is rendered. + // Height is used from 1st to 6th element of pArr + if (h === 0 && i > 1 && i < 6) { // [2, 3, 4, 5] + return { + x: pArr[i].x, + // when height is 0 instead of cuboid we render plane + // so it is needed to add fake 10 height to imitate cuboid + // for side calculation + y: pArr[i].y + 10, + z: pArr[i].z + }; + } + // It is needed to calculate dummy sides (front/back) for breaking + // points in case of x and depth values. If column has side, + // it means that x values of front and back side are different. + if (pArr[0].x === pArr[7].x && i >= 4) { // [4, 5, 6, 7] + return { + x: pArr[i].x + 10, + // when height is 0 instead of cuboid we render plane + // so it is needed to add fake 10 height to imitate cuboid + // for side calculation + y: pArr[i].y, + z: pArr[i].z + }; + } + // Added dummy depth + if (d === 0 && i < 2 || i > 5) { // [0, 1, 6, 7] + return { + x: pArr[i].x, + // when height is 0 instead of cuboid we render plane + // so it is needed to add fake 10 height to imitate cuboid + // for side calculation + y: pArr[i].y, + z: pArr[i].z + 10 + }; + } + return pArr[i]; + } + /** + * method creating the final side + * @private + */ + function mapPath(i) { + return pArr[i]; + } + /** + * First value - path with specific face + * Second value - added information about side for later calculations. + * Possible second values are 0 for path1, 1 for path2 and -1 for no path + * chosen. + * Third value - string containing information about current side + * of cuboid for forcing side rendering. + * @private + */ + pickShape = function (verticesIndex1, verticesIndex2, side) { + var ret = [[], -1], + // An array of vertices for cuboid face + face1 = verticesIndex1.map(mapPath), face2 = verticesIndex2.map(mapPath), + // dummy face is calculated the same way as standard face, + // but if cuboid height is 0 additional height is added so it is + // possible to use this vertices array for visible face calculation + dummyFace1 = verticesIndex1.map(mapSidePath), dummyFace2 = verticesIndex2.map(mapSidePath); + if (H.shapeArea(face1) < 0) { + ret = [face1, 0]; + } + else if (H.shapeArea(face2) < 0) { + ret = [face2, 1]; + } + else if (side) { + forcedSides.push(side); + if (H.shapeArea(dummyFace1) < 0) { + ret = [face1, 0]; + } + else if (H.shapeArea(dummyFace2) < 0) { + ret = [face2, 1]; + } + else { + ret = [face1, 0]; // force side calculation. + } + } + return ret; + }; + // front or back + front = [3, 2, 1, 0]; + back = [7, 6, 5, 4]; + shape = pickShape(front, back, 'front'); + path1 = shape[0]; + isFront = shape[1]; + // top or bottom + top = [1, 6, 7, 0]; + bottom = [4, 5, 2, 3]; + shape = pickShape(top, bottom, 'top'); + path2 = shape[0]; + isTop = shape[1]; + // side + right = [1, 2, 5, 6]; + left = [0, 7, 4, 3]; + shape = pickShape(right, left, 'side'); + path3 = shape[0]; + isRight = shape[1]; + /* New block used for calculating zIndex. It is basing on X, Y and Z + position of specific columns. All zIndexes (for X, Y and Z values) are + added to the final zIndex, where every value has different priority. The + biggest priority is in X and Z directions, the lowest index is for + stacked columns (Y direction and the same X and Z positions). Big + differences between priorities is made because we need to ensure that + even for big changes in Y and Z parameters all columns will be drawn + correctly. */ + if (isRight === 1) { + // It is needed to connect value with current chart width + // for big chart size. + zIndex += incrementX * (chart.plotWidth - x); + } + else if (!isRight) { + zIndex += incrementX * x; + } + zIndex += incrementY * (!isTop || + // Numbers checked empirically + (alpha >= 0 && alpha <= 180 || alpha < 360 && alpha > 357.5) ? + chart.plotHeight - y : 10 + y); + if (isFront === 1) { + zIndex += incrementZ * (z); + } + else if (!isFront) { + zIndex += incrementZ * (1000 - z); + } + return { + front: this.toLinePath(path1, true), + top: this.toLinePath(path2, true), + side: this.toLinePath(path3, true), + zIndexes: { + group: Math.round(zIndex) + }, + forcedSides: forcedSides, + // additional info about zIndexes + isFront: isFront, + isTop: isTop + }; // #4774 +}; +// SECTORS // +H.SVGRenderer.prototype.arc3d = function (attribs) { + var wrapper = this.g(), renderer = wrapper.renderer, customAttribs = ['x', 'y', 'r', 'innerR', 'start', 'end', 'depth']; + /** + * Get custom attributes. Don't mutate the original object and return an + * object with only custom attr. + * @private + */ + function suckOutCustom(params) { + var hasCA = false, ca = {}, key; + params = merge(params); // Don't mutate the original object + for (key in params) { + if (customAttribs.indexOf(key) !== -1) { + ca[key] = params[key]; + delete params[key]; + hasCA = true; + } + } + return hasCA ? ca : false; + } + attribs = merge(attribs); + attribs.alpha = (attribs.alpha || 0) * deg2rad; + attribs.beta = (attribs.beta || 0) * deg2rad; + // Create the different sub sections of the shape + wrapper.top = renderer.path(); + wrapper.side1 = renderer.path(); + wrapper.side2 = renderer.path(); + wrapper.inn = renderer.path(); + wrapper.out = renderer.path(); + // Add all faces + wrapper.onAdd = function () { + var parent = wrapper.parentGroup, className = wrapper.attr('class'); + wrapper.top.add(wrapper); + // These faces are added outside the wrapper group because the z index + // relates to neighbour elements as well + ['out', 'inn', 'side1', 'side2'].forEach(function (face) { + wrapper[face] + .attr({ + 'class': className + ' highcharts-3d-side' + }) + .add(parent); + }); + }; + // Cascade to faces + ['addClass', 'removeClass'].forEach(function (fn) { + wrapper[fn] = function () { + var args = arguments; + ['top', 'out', 'inn', 'side1', 'side2'].forEach(function (face) { + wrapper[face][fn].apply(wrapper[face], args); + }); + }; + }); + /** + * Compute the transformed paths and set them to the composite shapes + * @private + */ + wrapper.setPaths = function (attribs) { + var paths = wrapper.renderer.arc3dPath(attribs), zIndex = paths.zTop * 100; + wrapper.attribs = attribs; + wrapper.top.attr({ d: paths.top, zIndex: paths.zTop }); + wrapper.inn.attr({ d: paths.inn, zIndex: paths.zInn }); + wrapper.out.attr({ d: paths.out, zIndex: paths.zOut }); + wrapper.side1.attr({ d: paths.side1, zIndex: paths.zSide1 }); + wrapper.side2.attr({ d: paths.side2, zIndex: paths.zSide2 }); + // show all children + wrapper.zIndex = zIndex; + wrapper.attr({ zIndex: zIndex }); + // Set the radial gradient center the first time + if (attribs.center) { + wrapper.top.setRadialReference(attribs.center); + delete attribs.center; + } + }; + wrapper.setPaths(attribs); + /** + * Apply the fill to the top and a darker shade to the sides + * @private + */ + wrapper.fillSetter = function (value) { + var darker = color(value).brighten(-0.1).get(); + this.fill = value; + this.side1.attr({ fill: darker }); + this.side2.attr({ fill: darker }); + this.inn.attr({ fill: darker }); + this.out.attr({ fill: darker }); + this.top.attr({ fill: value }); + return this; + }; + // Apply the same value to all. These properties cascade down to the + // children when set to the composite arc3d. + ['opacity', 'translateX', 'translateY', 'visibility'].forEach(function (setter) { + wrapper[setter + 'Setter'] = function (value, key) { + wrapper[key] = value; + ['out', 'inn', 'side1', 'side2', 'top'].forEach(function (el) { + wrapper[el].attr(key, value); + }); + }; + }); + // Override attr to remove shape attributes and use those to set child paths + wrapper.attr = function (params) { + var ca; + if (typeof params === 'object') { + ca = suckOutCustom(params); + if (ca) { + extend(wrapper.attribs, ca); + wrapper.setPaths(wrapper.attribs); + } + } + return SVGElement.prototype.attr.apply(wrapper, arguments); + }; + // Override the animate function by sucking out custom parameters related to + // the shapes directly, and update the shapes from the animation step. + wrapper.animate = function (params, animation, complete) { + var ca, from = this.attribs, to, anim, randomProp = 'data-' + Math.random().toString(26).substring(2, 9); + // Attribute-line properties connected to 3D. These shouldn't have been + // in the attribs collection in the first place. + delete params.center; + delete params.z; + delete params.alpha; + delete params.beta; + anim = animObject(pick(animation, this.renderer.globalAnimation)); + if (anim.duration) { + ca = suckOutCustom(params); + // Params need to have a property in order for the step to run + // (#5765, #7097, #7437) + wrapper[randomProp] = 0; + params[randomProp] = 1; + wrapper[randomProp + 'Setter'] = H.noop; + if (ca) { + to = ca; + anim.step = function (a, fx) { + /** + * @private + */ + function interpolate(key) { + return from[key] + (pick(to[key], from[key]) - + from[key]) * fx.pos; + } + if (fx.prop === randomProp) { + fx.elem.setPaths(merge(from, { + x: interpolate('x'), + y: interpolate('y'), + r: interpolate('r'), + innerR: interpolate('innerR'), + start: interpolate('start'), + end: interpolate('end'), + depth: interpolate('depth') + })); + } + }; + } + animation = anim; // Only when duration (#5572) + } + return SVGElement.prototype.animate.call(this, params, animation, complete); + }; + // destroy all children + wrapper.destroy = function () { + this.top.destroy(); + this.out.destroy(); + this.inn.destroy(); + this.side1.destroy(); + this.side2.destroy(); + return SVGElement.prototype.destroy.call(this); + }; + // hide all children + wrapper.hide = function () { + this.top.hide(); + this.out.hide(); + this.inn.hide(); + this.side1.hide(); + this.side2.hide(); + }; + wrapper.show = function (inherit) { + this.top.show(inherit); + this.out.show(inherit); + this.inn.show(inherit); + this.side1.show(inherit); + this.side2.show(inherit); + }; + return wrapper; +}; +// Generate the paths required to draw a 3D arc +SVGRenderer.prototype.arc3dPath = function (shapeArgs) { + var cx = shapeArgs.x, // x coordinate of the center + cy = shapeArgs.y, // y coordinate of the center + start = shapeArgs.start, // start angle + end = shapeArgs.end - 0.00001, // end angle + r = shapeArgs.r, // radius + ir = shapeArgs.innerR || 0, // inner radius + d = shapeArgs.depth || 0, // depth + alpha = shapeArgs.alpha, // alpha rotation of the chart + beta = shapeArgs.beta; // beta rotation of the chart + // Derived Variables + var cs = Math.cos(start), // cosinus of the start angle + ss = Math.sin(start), // sinus of the start angle + ce = Math.cos(end), // cosinus of the end angle + se = Math.sin(end), // sinus of the end angle + rx = r * Math.cos(beta), // x-radius + ry = r * Math.cos(alpha), // y-radius + irx = ir * Math.cos(beta), // x-radius (inner) + iry = ir * Math.cos(alpha), // y-radius (inner) + dx = d * Math.sin(beta), // distance between top and bottom in x + dy = d * Math.sin(alpha); // distance between top and bottom in y + // TOP + var top = [ + ['M', cx + (rx * cs), cy + (ry * ss)] + ]; + top = top.concat(curveTo(cx, cy, rx, ry, start, end, 0, 0)); + top.push([ + 'L', cx + (irx * ce), cy + (iry * se) + ]); + top = top.concat(curveTo(cx, cy, irx, iry, end, start, 0, 0)); + top.push(['Z']); + // OUTSIDE + var b = (beta > 0 ? Math.PI / 2 : 0), a = (alpha > 0 ? 0 : Math.PI / 2); + var start2 = start > -b ? start : (end > -b ? -b : start), end2 = end < PI - a ? end : (start < PI - a ? PI - a : end), midEnd = 2 * PI - a; + // When slice goes over bottom middle, need to add both, left and right + // outer side. Additionally, when we cross right hand edge, create sharp + // edge. Outer shape/wall: + // + // ------- + // / ^ \ + // 4) / / \ \ 1) + // / / \ \ + // / / \ \ + // (c)=> ==== ==== <=(d) + // \ \ / / + // \ \<=(a)/ / + // \ \ / / <=(b) + // 3) \ v / 2) + // ------- + // + // (a) - inner side + // (b) - outer side + // (c) - left edge (sharp) + // (d) - right edge (sharp) + // 1..n - rendering order for startAngle = 0, when set to e.g 90, order + // changes clockwise (1->2, 2->3, n->1) and counterclockwise for negative + // startAngle + var out = [ + ['M', cx + (rx * cos(start2)), cy + (ry * sin(start2))] + ]; + out = out.concat(curveTo(cx, cy, rx, ry, start2, end2, 0, 0)); + // When shape is wide, it can cross both, (c) and (d) edges, when using + // startAngle + if (end > midEnd && start < midEnd) { + // Go to outer side + out.push([ + 'L', cx + (rx * cos(end2)) + dx, cy + (ry * sin(end2)) + dy + ]); + // Curve to the right edge of the slice (d) + out = out.concat(curveTo(cx, cy, rx, ry, end2, midEnd, dx, dy)); + // Go to the inner side + out.push([ + 'L', cx + (rx * cos(midEnd)), cy + (ry * sin(midEnd)) + ]); + // Curve to the true end of the slice + out = out.concat(curveTo(cx, cy, rx, ry, midEnd, end, 0, 0)); + // Go to the outer side + out.push([ + 'L', cx + (rx * cos(end)) + dx, cy + (ry * sin(end)) + dy + ]); + // Go back to middle (d) + out = out.concat(curveTo(cx, cy, rx, ry, end, midEnd, dx, dy)); + out.push([ + 'L', cx + (rx * cos(midEnd)), cy + (ry * sin(midEnd)) + ]); + // Go back to the left edge + out = out.concat(curveTo(cx, cy, rx, ry, midEnd, end2, 0, 0)); + // But shape can cross also only (c) edge: + } + else if (end > PI - a && start < PI - a) { + // Go to outer side + out.push([ + 'L', + cx + (rx * Math.cos(end2)) + dx, + cy + (ry * Math.sin(end2)) + dy + ]); + // Curve to the true end of the slice + out = out.concat(curveTo(cx, cy, rx, ry, end2, end, dx, dy)); + // Go to the inner side + out.push([ + 'L', cx + (rx * Math.cos(end)), cy + (ry * Math.sin(end)) + ]); + // Go back to the artifical end2 + out = out.concat(curveTo(cx, cy, rx, ry, end, end2, 0, 0)); + } + out.push([ + 'L', cx + (rx * Math.cos(end2)) + dx, cy + (ry * Math.sin(end2)) + dy + ]); + out = out.concat(curveTo(cx, cy, rx, ry, end2, start2, dx, dy)); + out.push(['Z']); + // INSIDE + var inn = [ + ['M', cx + (irx * cs), cy + (iry * ss)] + ]; + inn = inn.concat(curveTo(cx, cy, irx, iry, start, end, 0, 0)); + inn.push([ + 'L', cx + (irx * Math.cos(end)) + dx, cy + (iry * Math.sin(end)) + dy + ]); + inn = inn.concat(curveTo(cx, cy, irx, iry, end, start, dx, dy)); + inn.push(['Z']); + // SIDES + var side1 = [ + ['M', cx + (rx * cs), cy + (ry * ss)], + ['L', cx + (rx * cs) + dx, cy + (ry * ss) + dy], + ['L', cx + (irx * cs) + dx, cy + (iry * ss) + dy], + ['L', cx + (irx * cs), cy + (iry * ss)], + ['Z'] + ]; + var side2 = [ + ['M', cx + (rx * ce), cy + (ry * se)], + ['L', cx + (rx * ce) + dx, cy + (ry * se) + dy], + ['L', cx + (irx * ce) + dx, cy + (iry * se) + dy], + ['L', cx + (irx * ce), cy + (iry * se)], + ['Z'] + ]; + // correction for changed position of vanishing point caused by alpha and + // beta rotations + var angleCorr = Math.atan2(dy, -dx), angleEnd = Math.abs(end + angleCorr), angleStart = Math.abs(start + angleCorr), angleMid = Math.abs((start + end) / 2 + angleCorr); + /** + * set to 0-PI range + * @private + */ + function toZeroPIRange(angle) { + angle = angle % (2 * Math.PI); + if (angle > Math.PI) { + angle = 2 * Math.PI - angle; + } + return angle; + } + angleEnd = toZeroPIRange(angleEnd); + angleStart = toZeroPIRange(angleStart); + angleMid = toZeroPIRange(angleMid); + // *1e5 is to compensate pInt in zIndexSetter + var incPrecision = 1e5, a1 = angleMid * incPrecision, a2 = angleStart * incPrecision, a3 = angleEnd * incPrecision; + return { + top: top, + // max angle is PI, so this is always higher + zTop: Math.PI * incPrecision + 1, + out: out, + zOut: Math.max(a1, a2, a3), + inn: inn, + zInn: Math.max(a1, a2, a3), + side1: side1, + zSide1: a3 * 0.99, + side2: side2, + zSide2: a2 * 0.99 + }; +}; diff --git a/librerias/gantt/code/es-modules/parts-3d/Scatter.js b/librerias/gantt/code/es-modules/parts-3d/Scatter.js new file mode 100644 index 0000000..063b98f --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-3d/Scatter.js @@ -0,0 +1,145 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * Scatter 3D series. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import Point from '../parts/Point.js'; +import U from '../parts/Utilities.js'; +var seriesType = U.seriesType; +var seriesTypes = H.seriesTypes; +/** + * @private + * @class + * @name Highcharts.seriesTypes.scatter3d + * + * @augments Highcharts.Series + */ +seriesType('scatter3d', 'scatter', +/** + * A 3D scatter plot uses x, y and z coordinates to display values for three + * variables for a set of data. + * + * @sample {highcharts} highcharts/3d/scatter/ + * Simple 3D scatter + * @sample {highcharts} highcharts/demo/3d-scatter-draggable + * Draggable 3d scatter + * + * @extends plotOptions.scatter + * @excluding dragDrop, cluster + * @product highcharts + * @requires highcharts-3d + * @optionparent plotOptions.scatter3d + */ +{ + tooltip: { + pointFormat: 'x: {point.x}
y: {point.y}
z: {point.z}
' + } + // Series class +}, { + pointAttribs: function (point) { + var attribs = seriesTypes.scatter.prototype.pointAttribs + .apply(this, arguments); + if (this.chart.is3d() && point) { + attribs.zIndex = + H.pointCameraDistance(point, this.chart); + } + return attribs; + }, + axisTypes: ['xAxis', 'yAxis', 'zAxis'], + pointArrayMap: ['x', 'y', 'z'], + parallelArrays: ['x', 'y', 'z'], + // Require direct touch rather than using the k-d-tree, because the + // k-d-tree currently doesn't take the xyz coordinate system into + // account (#4552) + directTouch: true + // Point class +}, { + applyOptions: function () { + Point.prototype.applyOptions.apply(this, arguments); + if (typeof this.z === 'undefined') { + this.z = 0; + } + return this; + } +}); +/** + * A `scatter3d` series. If the [type](#series.scatter3d.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * scatter3d](#plotOptions.scatter3d). + * + * @extends series,plotOptions.scatter3d + * @product highcharts + * @requires highcharts-3d + * @apioption series.scatter3d + */ +/** + * An array of data points for the series. For the `scatter3d` series + * type, points can be given in the following ways: + * + * 1. An array of arrays with 3 values. In this case, the values correspond + * to `x,y,z`. If the first value is a string, it is applied as the name + * of the point, and the `x` value is inferred. + * + * ```js + * data: [ + * [0, 0, 1], + * [1, 8, 7], + * [2, 9, 2] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of data + * points exceeds the series' + * [turboThreshold](#series.scatter3d.turboThreshold), this option is not + * available. + * + * ```js + * data: [{ + * x: 1, + * y: 2, + * z: 24, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 4, + * z: 12, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|*>} + * @extends series.scatter.data + * @product highcharts + * @apioption series.scatter3d.data + */ +/** + * The z value for each data point. + * + * @type {number} + * @product highcharts + * @apioption series.scatter3d.data.z + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/parts-3d/Series.js b/librerias/gantt/code/es-modules/parts-3d/Series.js new file mode 100644 index 0000000..43c001e --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-3d/Series.js @@ -0,0 +1,59 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * Extension to the Series object in 3D charts. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, pick = U.pick; +var perspective = H.perspective; +/* eslint-disable no-invalid-this */ +// Wrap the translate method to post-translate points into 3D perspective +addEvent(H.Series, 'afterTranslate', function () { + if (this.chart.is3d()) { + this.translate3dPoints(); + } +}); +// Translate the plotX, plotY properties and add plotZ. +H.Series.prototype.translate3dPoints = function () { + var series = this, chart = series.chart, zAxis = pick(series.zAxis, chart.options.zAxis[0]), rawPoints = [], rawPoint, projectedPoints, projectedPoint, zValue, i; + for (i = 0; i < series.data.length; i++) { + rawPoint = series.data[i]; + if (zAxis && zAxis.translate) { + zValue = zAxis.logarithmic && zAxis.val2lin ? + zAxis.val2lin(rawPoint.z) : + rawPoint.z; // #4562 + rawPoint.plotZ = zAxis.translate(zValue); + rawPoint.isInside = rawPoint.isInside ? + (zValue >= zAxis.min && + zValue <= zAxis.max) : + false; + } + else { + rawPoint.plotZ = 0; + } + rawPoint.axisXpos = rawPoint.plotX; + rawPoint.axisYpos = rawPoint.plotY; + rawPoint.axisZpos = rawPoint.plotZ; + rawPoints.push({ + x: rawPoint.plotX, + y: rawPoint.plotY, + z: rawPoint.plotZ + }); + } + projectedPoints = perspective(rawPoints, chart, true); + for (i = 0; i < series.data.length; i++) { + rawPoint = series.data[i]; + projectedPoint = projectedPoints[i]; + rawPoint.plotX = projectedPoint.x; + rawPoint.plotY = projectedPoint.y; + rawPoint.plotZ = projectedPoint.z; + } +}; diff --git a/librerias/gantt/code/es-modules/parts-3d/Tick3D.js b/librerias/gantt/code/es-modules/parts-3d/Tick3D.js new file mode 100644 index 0000000..ccee179 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-3d/Tick3D.js @@ -0,0 +1,68 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * Extenstion for 3d axes + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, extend = U.extend, wrap = U.wrap; +/* eslint-disable valid-jsdoc */ +/** + * Tick with 3D support + * @private + * @class + */ +var Tick3D = /** @class */ (function () { + function Tick3D() { + } + /* * + * + * Static Functions + * + * */ + /** + * @private + */ + Tick3D.compose = function (TickClass) { + addEvent(TickClass, 'afterGetLabelPosition', Tick3D.onAfterGetLabelPosition); + var tickProto = TickClass.prototype; + wrap(tickProto, 'getMarkPath', Tick3D.wrapGetMarkPath); + }; + /** + * @private + */ + Tick3D.onAfterGetLabelPosition = function (e) { + var axis3D = this.axis.axis3D; + if (axis3D) { + extend(e.pos, axis3D.fix3dPosition(e.pos)); + } + }; + /** + * @private + */ + Tick3D.wrapGetMarkPath = function (proceed) { + var chart = this.axis.chart; + var axis3D = this.axis.axis3D; + var path = proceed.apply(this, [].slice.call(arguments, 1)); + if (axis3D) { + var start = path[0]; + var end = path[1]; + if (start[0] === 'M' && end[0] === 'L') { + var pArr = [ + axis3D.fix3dPosition({ x: start[1], y: start[2], z: 0 }), + axis3D.fix3dPosition({ x: end[1], y: end[2], z: 0 }) + ]; + return this.axis.chart.renderer.toLineSegments(pArr); + } + } + return path; + }; + return Tick3D; +}()); +export default Tick3D; diff --git a/librerias/gantt/code/es-modules/parts-3d/VMLAxis3D.js b/librerias/gantt/code/es-modules/parts-3d/VMLAxis3D.js new file mode 100644 index 0000000..eff1249 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-3d/VMLAxis3D.js @@ -0,0 +1,76 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * Extension to the VML Renderer + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent; +/* eslint-disable valid-jsdoc */ +var VMLAxis3DAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function VMLAxis3DAdditions(axis) { + this.axis = axis; + } + return VMLAxis3DAdditions; +}()); +var VMLAxis3D = /** @class */ (function () { + function VMLAxis3D() { + } + /* * + * + * Static Properties + * + * */ + VMLAxis3D.compose = function (AxisClass) { + AxisClass.keepProps.push('vml'); + addEvent(AxisClass, 'init', VMLAxis3D.onInit); + addEvent(AxisClass, 'render', VMLAxis3D.onRender); + }; + /** + * @private + */ + VMLAxis3D.onInit = function () { + var axis = this; + if (!axis.vml) { + axis.vml = new VMLAxis3DAdditions(axis); + } + }; + /** + * @private + */ + VMLAxis3D.onRender = function () { + var axis = this; + var vml = axis.vml; + // VML doesn't support a negative z-index + if (vml.sideFrame) { + vml.sideFrame.css({ zIndex: 0 }); + vml.sideFrame.front.attr({ + fill: vml.sideFrame.color + }); + } + if (vml.bottomFrame) { + vml.bottomFrame.css({ zIndex: 1 }); + vml.bottomFrame.front.attr({ + fill: vml.bottomFrame.color + }); + } + if (vml.backFrame) { + vml.backFrame.css({ zIndex: 0 }); + vml.backFrame.front.attr({ + fill: vml.backFrame.color + }); + } + }; + return VMLAxis3D; +}()); +export default VMLAxis3D; diff --git a/librerias/gantt/code/es-modules/parts-3d/VMLRenderer.js b/librerias/gantt/code/es-modules/parts-3d/VMLRenderer.js new file mode 100644 index 0000000..09fbe7e --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-3d/VMLRenderer.js @@ -0,0 +1,35 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * Extension to the VML Renderer + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Axis from '../parts/Axis.js'; +import H from '../parts/Globals.js'; +import VMLAxis3D from './VMLAxis3D.js'; +import '../parts/SvgRenderer.js'; +var SVGRenderer = H.SVGRenderer, VMLRenderer = H.VMLRenderer; +if (VMLRenderer) { + H.setOptions({ animate: false }); + VMLRenderer.prototype.face3d = SVGRenderer.prototype.face3d; + VMLRenderer.prototype.polyhedron = SVGRenderer.prototype.polyhedron; + VMLRenderer.prototype.elements3d = SVGRenderer.prototype.elements3d; + VMLRenderer.prototype.element3d = SVGRenderer.prototype.element3d; + VMLRenderer.prototype.cuboid = SVGRenderer.prototype.cuboid; + VMLRenderer.prototype.cuboidPath = SVGRenderer.prototype.cuboidPath; + VMLRenderer.prototype.toLinePath = SVGRenderer.prototype.toLinePath; + VMLRenderer.prototype.toLineSegments = SVGRenderer.prototype.toLineSegments; + VMLRenderer.prototype.arc3d = function (shapeArgs) { + var result = SVGRenderer.prototype.arc3d.call(this, shapeArgs); + result.css({ zIndex: result.zIndex }); + return result; + }; + H.VMLRenderer.prototype.arc3dPath = H.SVGRenderer.prototype.arc3dPath; + VMLAxis3D.compose(Axis); +} diff --git a/librerias/gantt/code/es-modules/parts-3d/ZAxis.js b/librerias/gantt/code/es-modules/parts-3d/ZAxis.js new file mode 100644 index 0000000..9086e5b --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-3d/ZAxis.js @@ -0,0 +1,155 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +import Axis from '../parts/Axis.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, merge = U.merge, pick = U.pick, splat = U.splat; +/* eslint-disable valid-jsdoc */ +/** + * 3D chart with support of z coordinates. + * @private + * @class + */ +var ZChart = /** @class */ (function () { + function ZChart() { + } + /* * + * + * Static Functions + * + * */ + ZChart.compose = function (ChartClass) { + addEvent(ChartClass, 'afterGetAxes', ZChart.onAfterGetAxes); + var chartProto = ChartClass.prototype; + chartProto.addZAxis = ZChart.wrapAddZAxis; + chartProto.collectionsWithInit.zAxis = [chartProto.addZAxis]; + chartProto.collectionsWithUpdate.push('zAxis'); + }; + /** + * Get the Z axis in addition to the default X and Y. + * @private + */ + ZChart.onAfterGetAxes = function () { + var chart = this; + var options = this.options; + var zAxisOptions = options.zAxis = splat(options.zAxis || {}); + if (!chart.is3d()) { + return; + } + chart.zAxis = []; + zAxisOptions.forEach(function (axisOptions, i) { + axisOptions.index = i; + // Z-Axis is shown horizontally, so it's kind of a X-Axis + axisOptions.isX = true; + chart + .addZAxis(axisOptions) + .setScale(); + }); + }; + /** + * @private + */ + ZChart.wrapAddZAxis = function (options) { + return new ZAxis(this, options); + }; + return ZChart; +}()); +/** + * 3D axis for z coordinates. + */ +var ZAxis = /** @class */ (function (_super) { + __extends(ZAxis, _super); + /* * + * + * Constructors + * + * */ + function ZAxis(chart, userOptions) { + var _this = _super.call(this, chart, userOptions) || this; + _this.isZAxis = true; + return _this; + } + /* * + * + * Functions + * + * */ + ZAxis.prototype.getSeriesExtremes = function () { + var axis = this; + var chart = axis.chart; + axis.hasVisibleSeries = false; + // Reset properties in case we're redrawing (#3353) + axis.dataMin = axis.dataMax = axis.ignoreMinPadding = axis.ignoreMaxPadding = void 0; + if (axis.stacking) { + axis.stacking.buildStacks(); + } + // loop through this axis' series + axis.series.forEach(function (series) { + if (series.visible || + !(chart.options.chart && + chart.options.chart.ignoreHiddenSeries)) { + var seriesOptions = series.options, zData, threshold = seriesOptions.threshold; + axis.hasVisibleSeries = true; + // Validate threshold in logarithmic axes + if (axis.positiveValuesOnly && threshold <= 0) { + threshold = void 0; + } + zData = series.zData; + if (zData.length) { + axis.dataMin = Math.min(pick(axis.dataMin, zData[0]), Math.min.apply(null, zData)); + axis.dataMax = Math.max(pick(axis.dataMax, zData[0]), Math.max.apply(null, zData)); + } + } + }); + }; + /** + * @private + */ + ZAxis.prototype.setAxisSize = function () { + var axis = this; + var chart = axis.chart; + _super.prototype.setAxisSize.call(this); + axis.width = axis.len = (chart.options.chart && + chart.options.chart.options3d && + chart.options.chart.options3d.depth) || 0; + axis.right = chart.chartWidth - axis.width - axis.left; + }; + /** + * @private + */ + ZAxis.prototype.setOptions = function (userOptions) { + userOptions = merge({ + offset: 0, + lineWidth: 0 + }, userOptions); + _super.prototype.setOptions.call(this, userOptions); + this.coll = 'zAxis'; + }; + /* * + * + * Static Properties + * + * */ + ZAxis.ZChartComposition = ZChart; + return ZAxis; +}(Axis)); +export default ZAxis; diff --git a/librerias/gantt/code/es-modules/parts-gantt/ArrowSymbols.js b/librerias/gantt/code/es-modules/parts-gantt/ArrowSymbols.js new file mode 100644 index 0000000..acc02b2 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-gantt/ArrowSymbols.js @@ -0,0 +1,194 @@ +/* * + * + * (c) 2017 Highsoft AS + * Authors: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +/** + * Creates an arrow symbol. Like a triangle, except not filled. + * ``` + * o + * o + * o + * o + * o + * o + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ +H.SVGRenderer.prototype.symbols.arrow = function (x, y, w, h) { + return [ + ['M', x, y + h / 2], + ['L', x + w, y], + ['L', x, y + h / 2], + ['L', x + w, y + h] + ]; +}; +/** + * Creates a half-width arrow symbol. Like a triangle, except not filled. + * ``` + * o + * o + * o + * o + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ +H.SVGRenderer.prototype.symbols['arrow-half'] = function (x, y, w, h) { + return H.SVGRenderer.prototype.symbols.arrow(x, y, w / 2, h); +}; +/** + * Creates a left-oriented triangle. + * ``` + * o + * ooooooo + * ooooooooooooo + * ooooooo + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the triangle + * + * @param {number} y + * y position of the triangle + * + * @param {number} w + * width of the triangle + * + * @param {number} h + * height of the triangle + * + * @return {Highcharts.SVGPathArray} + * Path array + */ +H.SVGRenderer.prototype.symbols['triangle-left'] = function (x, y, w, h) { + return [ + ['M', x + w, y], + ['L', x, y + h / 2], + ['L', x + w, y + h], + ['Z'] + ]; +}; +/** + * Alias function for triangle-left. + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ +H.SVGRenderer.prototype.symbols['arrow-filled'] = + H.SVGRenderer.prototype.symbols['triangle-left']; +/** + * Creates a half-width, left-oriented triangle. + * ``` + * o + * oooo + * ooooooo + * oooo + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the triangle + * + * @param {number} y + * y position of the triangle + * + * @param {number} w + * width of the triangle + * + * @param {number} h + * height of the triangle + * + * @return {Highcharts.SVGPathArray} + * Path array + */ +H.SVGRenderer.prototype.symbols['triangle-left-half'] = function (x, y, w, h) { + return H.SVGRenderer.prototype.symbols['triangle-left'](x, y, w / 2, h); +}; +/** + * Alias function for triangle-left-half. + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ +H.SVGRenderer.prototype.symbols['arrow-filled-half'] = + H.SVGRenderer.prototype.symbols['triangle-left-half']; diff --git a/librerias/gantt/code/es-modules/parts-gantt/CurrentDateIndicator.js b/librerias/gantt/code/es-modules/parts-gantt/CurrentDateIndicator.js new file mode 100644 index 0000000..46d2bf2 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-gantt/CurrentDateIndicator.js @@ -0,0 +1,97 @@ +/* * + * + * (c) 2016-2020 Highsoft AS + * + * Author: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, merge = U.merge, wrap = U.wrap; +import PlotLineOrBand from '../parts/PlotLineOrBand.js'; +var Axis = H.Axis; +var defaultConfig = { + /** + * Show an indicator on the axis for the current date and time. Can be a + * boolean or a configuration object similar to + * [xAxis.plotLines](#xAxis.plotLines). + * + * @sample gantt/current-date-indicator/demo + * Current date indicator enabled + * @sample gantt/current-date-indicator/object-config + * Current date indicator with custom options + * + * @declare Highcharts.AxisCurrentDateIndicatorOptions + * @type {boolean|*} + * @default true + * @extends xAxis.plotLines + * @excluding value + * @product gantt + * @apioption xAxis.currentDateIndicator + */ + currentDateIndicator: true, + color: '#ccd6eb', + width: 2, + /** + * @declare Highcharts.AxisCurrentDateIndicatorLabelOptions + */ + label: { + /** + * Format of the label. This options is passed as the fist argument to + * [dateFormat](/class-reference/Highcharts#dateFormat) function. + * + * @type {string} + * @default '%a, %b %d %Y, %H:%M' + * @product gantt + * @apioption xAxis.currentDateIndicator.label.format + */ + format: '%a, %b %d %Y, %H:%M', + formatter: function (value, format) { + return H.dateFormat(format, value); + }, + rotation: 0, + /** + * @type {Highcharts.CSSObject} + */ + style: { + /** @internal */ + fontSize: '10px' + } + } +}; +/* eslint-disable no-invalid-this */ +addEvent(Axis, 'afterSetOptions', function () { + var options = this.options, cdiOptions = options.currentDateIndicator; + if (cdiOptions) { + cdiOptions = typeof cdiOptions === 'object' ? + merge(defaultConfig, cdiOptions) : merge(defaultConfig); + cdiOptions.value = new Date(); + if (!options.plotLines) { + options.plotLines = []; + } + options.plotLines.push(cdiOptions); + } +}); +addEvent(PlotLineOrBand, 'render', function () { + // If the label already exists, update its text + if (this.label) { + this.label.attr({ + text: this.getLabelText(this.options.label) + }); + } +}); +wrap(PlotLineOrBand.prototype, 'getLabelText', function (defaultMethod, defaultLabelOptions) { + var options = this.options; + if (options.currentDateIndicator && options.label && + typeof options.label.formatter === 'function') { + options.value = new Date(); + return options.label.formatter + .call(this, options.value, options.label.format); + } + return defaultMethod.call(this, defaultLabelOptions); +}); diff --git a/librerias/gantt/code/es-modules/parts-gantt/GanttChart.js b/librerias/gantt/code/es-modules/parts-gantt/GanttChart.js new file mode 100644 index 0000000..d8be5e0 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-gantt/GanttChart.js @@ -0,0 +1,113 @@ +/* * + * + * (c) 2016-2020 Highsoft AS + * + * Author: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var isArray = U.isArray, merge = U.merge, splat = U.splat; +import './GanttSeries.js'; +var Chart = H.Chart; +/** + * Factory function for Gantt charts. + * + * @example + * // Render a chart in to div#container + * var chart = Highcharts.ganttChart('container', { + * title: { + * text: 'My chart' + * }, + * series: [{ + * data: ... + * }] + * }); + * + * @function Highcharts.ganttChart + * + * @param {string|Highcharts.HTMLDOMElement} renderTo + * The DOM element to render to, or its id. + * + * @param {Highcharts.Options} options + * The chart options structure. + * + * @param {Highcharts.ChartCallbackFunction} [callback] + * Function to run when the chart has loaded and and all external images + * are loaded. Defining a + * [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load) + * handler is equivalent. + * + * @return {Highcharts.Chart} + * Returns the Chart object. + */ +H.ganttChart = function (renderTo, options, callback) { + var hasRenderToArg = typeof renderTo === 'string' || renderTo.nodeName, seriesOptions = options.series, defaultOptions = H.getOptions(), defaultLinkedTo, userOptions = options; + options = arguments[hasRenderToArg ? 1 : 0]; + // If user hasn't defined axes as array, make it into an array and add a + // second axis by default. + if (!isArray(options.xAxis)) { + options.xAxis = [options.xAxis || {}, {}]; + } + // apply X axis options to both single and multi x axes + options.xAxis = options.xAxis.map(function (xAxisOptions, i) { + if (i === 1) { // Second xAxis + defaultLinkedTo = 0; + } + return merge(defaultOptions.xAxis, { + grid: { + enabled: true + }, + opposite: true, + linkedTo: defaultLinkedTo + }, xAxisOptions, // user options + { + type: 'datetime' + }); + }); + // apply Y axis options to both single and multi y axes + options.yAxis = (splat(options.yAxis || {})).map(function (yAxisOptions) { + return merge(defaultOptions.yAxis, // #3802 + { + grid: { + enabled: true + }, + staticScale: 50, + reversed: true, + // Set default type treegrid, but only if 'categories' is + // undefined + type: yAxisOptions.categories ? yAxisOptions.type : 'treegrid' + }, yAxisOptions // user options + ); + }); + options.series = null; + options = merge(true, { + chart: { + type: 'gantt' + }, + title: { + text: null + }, + legend: { + enabled: false + } + }, options, // user's options + // forced options + { + isGantt: true + }); + options.series = userOptions.series = seriesOptions; + options.series.forEach(function (series) { + series.data.forEach(function (point) { + H.seriesTypes.gantt.prototype.setGanttPointAliases(point); + }); + }); + return hasRenderToArg ? + new Chart(renderTo, options, callback) : + new Chart(options, options); // @todo does not look correct +}; diff --git a/librerias/gantt/code/es-modules/parts-gantt/GanttSeries.js b/librerias/gantt/code/es-modules/parts-gantt/GanttSeries.js new file mode 100644 index 0000000..ae616b4 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-gantt/GanttSeries.js @@ -0,0 +1,350 @@ +/* * + * + * (c) 2016-2020 Highsoft AS + * + * Author: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var isNumber = U.isNumber, merge = U.merge, pick = U.pick, seriesType = U.seriesType, splat = U.splat; +import './CurrentDateIndicator.js'; +import '../modules/static-scale.src.js'; +import './TreeGridAxis.js'; +import './Pathfinder.js'; +import '../modules/xrange.src.js'; +var dateFormat = H.dateFormat, seriesTypes = H.seriesTypes, Series = H.Series, parent = seriesTypes.xrange; +/** + * @private + * @class + * @name Highcharts.seriesTypes.gantt + * + * @augments Highcharts.Series + */ +seriesType('gantt', 'xrange' +/** + * A `gantt` series. If the [type](#series.gantt.type) option is not specified, + * it is inherited from [chart.type](#chart.type). + * + * @extends plotOptions.xrange + * @product gantt + * @requires highcharts-gantt + * @optionparent plotOptions.gantt + */ +, { + // options - default options merged with parent + grouping: false, + dataLabels: { + enabled: true + }, + tooltip: { + headerFormat: '{series.name}
', + pointFormat: null, + pointFormatter: function () { + var point = this, series = point.series, tooltip = series.chart.tooltip, xAxis = series.xAxis, formats = series.tooltipOptions.dateTimeLabelFormats, startOfWeek = xAxis.options.startOfWeek, ttOptions = series.tooltipOptions, format = ttOptions.xDateFormat, start, end, milestone = point.options.milestone, retVal = '' + (point.name || point.yCategory) + ''; + if (ttOptions.pointFormat) { + return point.tooltipFormatter(ttOptions.pointFormat); + } + if (!format) { + format = splat(tooltip.getDateFormat(xAxis.closestPointRange, point.start, startOfWeek, formats))[0]; + } + start = dateFormat(format, point.start); + end = dateFormat(format, point.end); + retVal += '
'; + if (!milestone) { + retVal += 'Start: ' + start + '
'; + retVal += 'End: ' + end + '
'; + } + else { + retVal += start + '
'; + } + return retVal; + } + }, + connectors: { + type: 'simpleConnect', + /** + * @declare Highcharts.ConnectorsAnimationOptionsObject + */ + animation: { + reversed: true // Dependencies go from child to parent + }, + startMarker: { + enabled: true, + symbol: 'arrow-filled', + radius: 4, + fill: '#fa0', + align: 'left' + }, + endMarker: { + enabled: false, + align: 'right' + } + } +}, { + pointArrayMap: ['start', 'end', 'y'], + // Keyboard navigation, don't use nearest vertical mode + keyboardMoveVertical: false, + /* eslint-disable valid-jsdoc */ + /** + * Handle milestones, as they have no x2. + * @private + */ + translatePoint: function (point) { + var series = this, shapeArgs, size; + parent.prototype.translatePoint.call(series, point); + if (point.options.milestone) { + shapeArgs = point.shapeArgs; + size = shapeArgs.height; + point.shapeArgs = { + x: shapeArgs.x - (size / 2), + y: shapeArgs.y, + width: size, + height: size + }; + } + }, + /** + * Draws a single point in the series. + * + * This override draws the point as a diamond if point.options.milestone + * is true, and uses the original drawPoint() if it is false or not set. + * + * @requires highcharts-gantt + * + * @private + * @function Highcharts.seriesTypes.gantt#drawPoint + * + * @param {Highcharts.Point} point + * An instance of Point in the series + * + * @param {"animate"|"attr"} verb + * 'animate' (animates changes) or 'attr' (sets options) + * + * @return {void} + */ + drawPoint: function (point, verb) { + var series = this, seriesOpts = series.options, renderer = series.chart.renderer, shapeArgs = point.shapeArgs, plotY = point.plotY, graphic = point.graphic, state = point.selected && 'select', cutOff = seriesOpts.stacking && !seriesOpts.borderRadius, diamondShape; + if (point.options.milestone) { + if (isNumber(plotY) && point.y !== null && point.visible !== false) { + diamondShape = renderer.symbols.diamond(shapeArgs.x, shapeArgs.y, shapeArgs.width, shapeArgs.height); + if (graphic) { + graphic[verb]({ + d: diamondShape + }); + } + else { + point.graphic = graphic = renderer.path(diamondShape) + .addClass(point.getClassName(), true) + .add(point.group || series.group); + } + // Presentational + if (!series.chart.styledMode) { + point.graphic + .attr(series.pointAttribs(point, state)) + .shadow(seriesOpts.shadow, null, cutOff); + } + } + else if (graphic) { + point.graphic = graphic.destroy(); // #1269 + } + } + else { + parent.prototype.drawPoint.call(series, point, verb); + } + }, + setData: Series.prototype.setData, + /** + * @private + */ + setGanttPointAliases: function (options) { + /** + * Add a value to options if the value exists. + * @private + */ + function addIfExists(prop, val) { + if (typeof val !== 'undefined') { + options[prop] = val; + } + } + addIfExists('x', pick(options.start, options.x)); + addIfExists('x2', pick(options.end, options.x2)); + addIfExists('partialFill', pick(options.completed, options.partialFill)); + addIfExists('connect', pick(options.dependency, options.connect)); + } + /* eslint-enable valid-jsdoc */ +}, merge(parent.prototype.pointClass.prototype, { + // pointProps - point member overrides. We inherit from parent as well. + /* eslint-disable valid-jsdoc */ + /** + * Applies the options containing the x and y data and possible some + * extra properties. This is called on point init or from point.update. + * + * @private + * @function Highcharts.Point#applyOptions + * + * @param {object} options + * The point options + * + * @param {number} x + * The x value + * + * @return {Highcharts.Point} + * The Point instance + */ + applyOptions: function (options, x) { + var point = this, retVal = merge(options); + H.seriesTypes.gantt.prototype.setGanttPointAliases(retVal); + retVal = parent.prototype.pointClass.prototype.applyOptions + .call(point, retVal, x); + return retVal; + }, + isValid: function () { + return ((typeof this.start === 'number' || + typeof this.x === 'number') && + (typeof this.end === 'number' || + typeof this.x2 === 'number' || + this.milestone)); + } + /* eslint-enable valid-jsdoc */ +})); +/** + * A `gantt` series. + * + * @extends series,plotOptions.gantt + * @excluding boostThreshold, connectors, dashStyle, findNearestPointBy, + * getExtremesFromAll, marker, negativeColor, pointInterval, + * pointIntervalUnit, pointPlacement, pointStart + * @product gantt + * @requires highcharts-gantt + * @apioption series.gantt + */ +/** + * Data for a Gantt series. + * + * @declare Highcharts.GanttPointOptionsObject + * @type {Array<*>} + * @extends series.xrange.data + * @excluding className, color, colorIndex, connect, dataLabels, events, id, + * partialFill, selected, x, x2 + * @product gantt + * @apioption series.gantt.data + */ +/** + * Whether the grid node belonging to this point should start as collapsed. Used + * in axes of type treegrid. + * + * @sample {gantt} gantt/treegrid-axis/collapsed/ + * Start as collapsed + * + * @type {boolean} + * @default false + * @product gantt + * @apioption series.gantt.data.collapsed + */ +/** + * The start time of a task. + * + * @type {number} + * @product gantt + * @apioption series.gantt.data.start + */ +/** + * The end time of a task. + * + * @type {number} + * @product gantt + * @apioption series.gantt.data.end + */ +/** + * The Y value of a task. + * + * @type {number} + * @product gantt + * @apioption series.gantt.data.y + */ +/** + * The name of a task. If a `treegrid` y-axis is used (default in Gantt charts), + * this will be picked up automatically, and used to calculate the y-value. + * + * @type {string} + * @product gantt + * @apioption series.gantt.data.name + */ +/** + * Progress indicator, how much of the task completed. If it is a number, the + * `fill` will be applied automatically. + * + * @sample {gantt} gantt/demo/progress-indicator + * Progress indicator + * + * @type {number|*} + * @extends series.xrange.data.partialFill + * @product gantt + * @apioption series.gantt.data.completed + */ +/** + * The amount of the progress indicator, ranging from 0 (not started) to 1 + * (finished). + * + * @type {number} + * @default 0 + * @apioption series.gantt.data.completed.amount + */ +/** + * The fill of the progress indicator. Defaults to a darkened variety of the + * main color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption series.gantt.data.completed.fill + */ +/** + * The ID of the point (task) that this point depends on in Gantt charts. + * Aliases [connect](series.xrange.data.connect). Can also be an object, + * specifying further connecting [options](series.gantt.connectors) between the + * points. Multiple connections can be specified by providing an array. + * + * @sample gantt/demo/project-management + * Dependencies + * @sample gantt/pathfinder/demo + * Different connection types + * + * @type {string|Array|*} + * @extends series.xrange.data.connect + * @since 6.2.0 + * @product gantt + * @apioption series.gantt.data.dependency + */ +/** + * Whether this point is a milestone. If so, only the `start` option is handled, + * while `end` is ignored. + * + * @sample gantt/gantt/milestones + * Milestones + * + * @type {boolean} + * @since 6.2.0 + * @product gantt + * @apioption series.gantt.data.milestone + */ +/** + * The ID of the parent point (task) of this point in Gantt charts. + * + * @sample gantt/demo/subtasks + * Gantt chart with subtasks + * + * @type {string} + * @since 6.2.0 + * @product gantt + * @apioption series.gantt.data.parent + */ +/** + * @excluding afterAnimate + * @apioption series.gantt.events + */ +''; // adds doclets above to the transpiled file diff --git a/librerias/gantt/code/es-modules/parts-gantt/GridAxis.js b/librerias/gantt/code/es-modules/parts-gantt/GridAxis.js new file mode 100644 index 0000000..acc537a --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-gantt/GridAxis.js @@ -0,0 +1,843 @@ +/* * + * + * (c) 2016 Highsoft AS + * Authors: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Axis from '../parts/Axis.js'; +import H from '../parts/Globals.js'; +import Tick from '../parts/Tick.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, defined = U.defined, erase = U.erase, find = U.find, isArray = U.isArray, isNumber = U.isNumber, merge = U.merge, pick = U.pick, timeUnits = U.timeUnits, wrap = U.wrap; +var argsToArray = function (args) { + return Array.prototype.slice.call(args, 1); +}, dateFormat = H.dateFormat, isObject = function (x) { + // Always use strict mode + return U.isObject(x, true); +}, Chart = H.Chart; +var applyGridOptions = function applyGridOptions(axis) { + var options = axis.options; + // Center-align by default + if (!options.labels) { + options.labels = {}; + } + options.labels.align = pick(options.labels.align, 'center'); + // @todo: Check against tickLabelPlacement between/on etc + /* Prevents adding the last tick label if the axis is not a category + axis. + Since numeric labels are normally placed at starts and ends of a + range of value, and this module makes the label point at the value, + an "extra" label would appear. */ + if (!axis.categories) { + options.showLastLabel = false; + } + // Prevents rotation of labels when squished, as rotating them would not + // help. + axis.labelRotation = 0; + options.labels.rotation = 0; +}; +/** + * Set grid options for the axis labels. Requires Highcharts Gantt. + * + * @since 6.2.0 + * @product gantt + * @apioption xAxis.grid + */ +/** + * Enable grid on the axis labels. Defaults to true for Gantt charts. + * + * @type {boolean} + * @default true + * @since 6.2.0 + * @product gantt + * @apioption xAxis.grid.enabled + */ +/** + * Set specific options for each column (or row for horizontal axes) in the + * grid. Each extra column/row is its own axis, and the axis options can be set + * here. + * + * @sample gantt/demo/left-axis-table + * Left axis as a table + * + * @type {Array} + * @apioption xAxis.grid.columns + */ +/** + * Set border color for the label grid lines. + * + * @type {Highcharts.ColorString} + * @apioption xAxis.grid.borderColor + */ +/** + * Set border width of the label grid lines. + * + * @type {number} + * @default 1 + * @apioption xAxis.grid.borderWidth + */ +/** + * Set cell height for grid axis labels. By default this is calculated from font + * size. This option only applies to horizontal axes. + * + * @sample gantt/grid-axis/cellheight + * Gant chart with custom cell height + * @type {number} + * @apioption xAxis.grid.cellHeight + */ +''; // detach doclets above +/** + * Get the largest label width and height. + * + * @private + * @function Highcharts.Axis#getMaxLabelDimensions + * + * @param {Highcharts.Dictionary} ticks + * All the ticks on one axis. + * + * @param {Array} tickPositions + * All the tick positions on one axis. + * + * @return {Highcharts.SizeObject} + * Object containing the properties height and width. + * + * @todo Move this to the generic axis implementation, as it is used there. + */ +Axis.prototype.getMaxLabelDimensions = function (ticks, tickPositions) { + var dimensions = { + width: 0, + height: 0 + }; + tickPositions.forEach(function (pos) { + var tick = ticks[pos], tickHeight = 0, tickWidth = 0, label; + if (isObject(tick)) { + label = isObject(tick.label) ? tick.label : {}; + // Find width and height of tick + tickHeight = label.getBBox ? label.getBBox().height : 0; + if (label.textStr && !isNumber(label.textPxLength)) { + label.textPxLength = label.getBBox().width; + } + tickWidth = isNumber(label.textPxLength) ? + // Math.round ensures crisp lines + Math.round(label.textPxLength) : + 0; + // Update the result if width and/or height are larger + dimensions.height = Math.max(tickHeight, dimensions.height); + dimensions.width = Math.max(tickWidth, dimensions.width); + } + }); + return dimensions; +}; +// Adds week date format +H.dateFormats.W = function (timestamp) { + var d = new this.Date(timestamp); + var firstDay = (this.get('Day', d) + 6) % 7; + var thursday = new this.Date(d.valueOf()); + this.set('Date', thursday, this.get('Date', d) - firstDay + 3); + var firstThursday = new this.Date(this.get('FullYear', thursday), 0, 1); + if (this.get('Day', firstThursday) !== 4) { + this.set('Month', d, 0); + this.set('Date', d, 1 + (11 - this.get('Day', firstThursday)) % 7); + } + return (1 + + Math.floor((thursday.valueOf() - firstThursday.valueOf()) / 604800000)).toString(); +}; +// First letter of the day of the week, e.g. 'M' for 'Monday'. +H.dateFormats.E = function (timestamp) { + return dateFormat('%a', timestamp, true).charAt(0); +}; +/* eslint-disable no-invalid-this */ +addEvent(Chart, 'afterSetChartSize', function () { + this.axes.forEach(function (axis) { + (axis.grid && axis.grid.columns || []).forEach(function (column) { + column.setAxisSize(); + column.setAxisTranslation(); + }); + }); +}); +// Center tick labels in cells. +addEvent(Tick, 'afterGetLabelPosition', function (e) { + var tick = this, label = tick.label, axis = tick.axis, reversed = axis.reversed, chart = axis.chart, options = axis.options, gridOptions = options.grid || {}, labelOpts = axis.options.labels, align = labelOpts.align, + // verticalAlign is currently not supported for axis.labels. + verticalAlign = 'middle', // labelOpts.verticalAlign, + side = GridAxis.Side[axis.side], tickmarkOffset = e.tickmarkOffset, tickPositions = axis.tickPositions, tickPos = tick.pos - tickmarkOffset, nextTickPos = (isNumber(tickPositions[e.index + 1]) ? + tickPositions[e.index + 1] - tickmarkOffset : + axis.max + tickmarkOffset), tickSize = axis.tickSize('tick'), tickWidth = tickSize ? tickSize[0] : 0, crispCorr = tickSize ? tickSize[1] / 2 : 0, labelHeight, lblMetrics, lines, bottom, top, left, right; + // Only center tick labels in grid axes + if (gridOptions.enabled === true) { + // Calculate top and bottom positions of the cell. + if (side === 'top') { + bottom = axis.top + axis.offset; + top = bottom - tickWidth; + } + else if (side === 'bottom') { + top = chart.chartHeight - axis.bottom + axis.offset; + bottom = top + tickWidth; + } + else { + bottom = axis.top + axis.len - axis.translate(reversed ? nextTickPos : tickPos); + top = axis.top + axis.len - axis.translate(reversed ? tickPos : nextTickPos); + } + // Calculate left and right positions of the cell. + if (side === 'right') { + left = chart.chartWidth - axis.right + axis.offset; + right = left + tickWidth; + } + else if (side === 'left') { + right = axis.left + axis.offset; + left = right - tickWidth; + } + else { + left = Math.round(axis.left + axis.translate(reversed ? nextTickPos : tickPos)) - crispCorr; + right = Math.round(axis.left + axis.translate(reversed ? tickPos : nextTickPos)) - crispCorr; + } + tick.slotWidth = right - left; + // Calculate the positioning of the label based on + // alignment. + e.pos.x = (align === 'left' ? + left : + align === 'right' ? + right : + left + ((right - left) / 2) // default to center + ); + e.pos.y = (verticalAlign === 'top' ? + top : + verticalAlign === 'bottom' ? + bottom : + top + ((bottom - top) / 2) // default to middle + ); + lblMetrics = chart.renderer.fontMetrics(labelOpts.style.fontSize, label.element); + labelHeight = label.getBBox().height; + // Adjustment to y position to align the label correctly. + // Would be better to have a setter or similar for this. + if (!labelOpts.useHTML) { + lines = Math.round(labelHeight / lblMetrics.h); + e.pos.y += ( + // Center the label + // TODO: why does this actually center the label? + ((lblMetrics.b - (lblMetrics.h - lblMetrics.f)) / 2) + + // Adjust for height of additional lines. + -(((lines - 1) * lblMetrics.h) / 2)); + } + else { + e.pos.y += ( + // Readjust yCorr in htmlUpdateTransform + lblMetrics.b + + // Adjust for height of html label + -(labelHeight / 2)); + } + e.pos.x += (axis.horiz && labelOpts.x || 0); + } +}); +/* eslint-enable no-invalid-this */ +/** + * Additions for grid axes. + * @private + * @class + */ +var GridAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function GridAxisAdditions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Checks if an axis is the outer axis in its dimension. Since + * axes are placed outwards in order, the axis with the highest + * index is the outermost axis. + * + * Example: If there are multiple x-axes at the top of the chart, + * this function returns true if the axis supplied is the last + * of the x-axes. + * + * @private + * + * @return {boolean} + * True if the axis is the outermost axis in its dimension; false if + * not. + */ + GridAxisAdditions.prototype.isOuterAxis = function () { + var axis = this.axis; + var chart = axis.chart; + var columnIndex = axis.grid.columnIndex; + var columns = (axis.linkedParent && axis.linkedParent.grid.columns || + axis.grid.columns); + var parentAxis = columnIndex ? axis.linkedParent : axis; + var thisIndex = -1, lastIndex = 0; + chart[axis.coll].forEach(function (otherAxis, index) { + if (otherAxis.side === axis.side && !otherAxis.options.isInternal) { + lastIndex = index; + if (otherAxis === parentAxis) { + // Get the index of the axis in question + thisIndex = index; + } + } + }); + return (lastIndex === thisIndex && + (isNumber(columnIndex) ? columns.length === columnIndex : true)); + }; + return GridAxisAdditions; +}()); +/** + * Axis with grid support. + * @private + * @class + */ +var GridAxis = /** @class */ (function () { + function GridAxis() { + } + /* * + * + * Static Functions + * + * */ + /* eslint-disable valid-jsdoc */ + /** + * Extends axis class with grid support. + * @private + */ + GridAxis.compose = function (AxisClass) { + Axis.keepProps.push('grid'); + wrap(AxisClass.prototype, 'unsquish', GridAxis.wrapUnsquish); + // Add event handlers + addEvent(AxisClass, 'init', GridAxis.onInit); + addEvent(AxisClass, 'afterGetOffset', GridAxis.onAfterGetOffset); + addEvent(AxisClass, 'afterGetTitlePosition', GridAxis.onAfterGetTitlePosition); + addEvent(AxisClass, 'afterInit', GridAxis.onAfterInit); + addEvent(AxisClass, 'afterRender', GridAxis.onAfterRender); + addEvent(AxisClass, 'afterSetAxisTranslation', GridAxis.onAfterSetAxisTranslation); + addEvent(AxisClass, 'afterSetOptions', GridAxis.onAfterSetOptions); + addEvent(AxisClass, 'afterSetOptions', GridAxis.onAfterSetOptions2); + addEvent(AxisClass, 'afterSetScale', GridAxis.onAfterSetScale); + addEvent(AxisClass, 'afterTickSize', GridAxis.onAfterTickSize); + addEvent(AxisClass, 'trimTicks', GridAxis.onTrimTicks); + addEvent(AxisClass, 'destroy', GridAxis.onDestroy); + }; + /** + * Handle columns and getOffset. + * @private + */ + GridAxis.onAfterGetOffset = function () { + var grid = this.grid; + (grid && grid.columns || []).forEach(function (column) { + column.getOffset(); + }); + }; + /** + * @private + */ + GridAxis.onAfterGetTitlePosition = function (e) { + var axis = this; + var options = axis.options; + var gridOptions = options.grid || {}; + if (gridOptions.enabled === true) { + // compute anchor points for each of the title align options + var title = axis.axisTitle, axisHeight = axis.height, horiz = axis.horiz, axisLeft = axis.left, offset = axis.offset, opposite = axis.opposite, _a = axis.options.title, axisTitleOptions = _a === void 0 ? {} : _a, axisTop = axis.top, axisWidth = axis.width; + var tickSize = axis.tickSize(); + var titleWidth = title && title.getBBox().width; + var xOption = axisTitleOptions.x || 0; + var yOption = axisTitleOptions.y || 0; + var titleMargin = pick(axisTitleOptions.margin, horiz ? 5 : 10); + var titleFontSize = axis.chart.renderer.fontMetrics(axisTitleOptions.style && + axisTitleOptions.style.fontSize, title).f; + var crispCorr = tickSize ? tickSize[0] / 2 : 0; + // TODO account for alignment + // the position in the perpendicular direction of the axis + var offAxis = ((horiz ? axisTop + axisHeight : axisLeft) + + (horiz ? 1 : -1) * // horizontal axis reverses the margin + (opposite ? -1 : 1) * // so does opposite axes + crispCorr + + (axis.side === GridAxis.Side.bottom ? titleFontSize : 0)); + e.titlePosition.x = horiz ? + axisLeft - titleWidth / 2 - titleMargin + xOption : + offAxis + (opposite ? axisWidth : 0) + offset + xOption; + e.titlePosition.y = horiz ? + (offAxis - + (opposite ? axisHeight : 0) + + (opposite ? titleFontSize : -titleFontSize) / 2 + + offset + + yOption) : + axisTop - titleMargin + yOption; + } + }; + /** + * @private + */ + GridAxis.onAfterInit = function () { + var axis = this; + var chart = axis.chart, _a = axis.options.grid, gridOptions = _a === void 0 ? {} : _a, userOptions = axis.userOptions; + if (gridOptions.enabled) { + applyGridOptions(axis); + /* eslint-disable no-invalid-this */ + // TODO: wrap the axis instead + wrap(axis, 'labelFormatter', function (proceed) { + var _a = this, axis = _a.axis, value = _a.value; + var tickPos = axis.tickPositions; + var series = (axis.isLinked ? + axis.linkedParent : + axis).series[0]; + var isFirst = value === tickPos[0]; + var isLast = value === tickPos[tickPos.length - 1]; + var point = series && find(series.options.data, function (p) { + return p[axis.isXAxis ? 'x' : 'y'] === value; + }); + // Make additional properties available for the + // formatter + this.isFirst = isFirst; + this.isLast = isLast; + this.point = point; + // Call original labelFormatter + return proceed.call(this); + }); + /* eslint-enable no-invalid-this */ + } + if (gridOptions.columns) { + var columns = axis.grid.columns = [], columnIndex = axis.grid.columnIndex = 0; + // Handle columns, each column is a grid axis + while (++columnIndex < gridOptions.columns.length) { + var columnOptions = merge(userOptions, gridOptions.columns[gridOptions.columns.length - columnIndex - 1], { + linkedTo: 0, + // Force to behave like category axis + type: 'category' + }); + delete columnOptions.grid.columns; // Prevent recursion + var column = new Axis(axis.chart, columnOptions); + column.grid.isColumn = true; + column.grid.columnIndex = columnIndex; + // Remove column axis from chart axes array, and place it + // in the columns array. + erase(chart.axes, column); + erase(chart[axis.coll], column); + columns.push(column); + } + } + }; + /** + * Draw an extra line on the far side of the outermost axis, + * creating floor/roof/wall of a grid. And some padding. + * ``` + * Make this: + * (axis.min) __________________________ (axis.max) + * | | | | | + * Into this: + * (axis.min) __________________________ (axis.max) + * ___|____|____|____|____|__ + * ``` + * @private + */ + GridAxis.onAfterRender = function () { + var axis = this; + var grid = axis.grid; + var options = axis.options; + var renderer = axis.chart.renderer; + var gridOptions = options.grid || {}; + var yStartIndex, yEndIndex, xStartIndex, xEndIndex; + if (gridOptions.enabled === true) { + // @todo acutual label padding (top, bottom, left, right) + axis.maxLabelDimensions = axis.getMaxLabelDimensions(axis.ticks, axis.tickPositions); + // Remove right wall before rendering if updating + if (axis.rightWall) { + axis.rightWall.destroy(); + } + /* + Draw an extra axis line on outer axes + > + Make this: |______|______|______|___ + + > _________________________ + Into this: |______|______|______|__| + */ + if (axis.grid && axis.grid.isOuterAxis() && axis.axisLine) { + var lineWidth = options.lineWidth; + if (lineWidth) { + var linePath = axis.getLinePath(lineWidth); + var startPoint = linePath[0]; + var endPoint = linePath[1]; + // Negate distance if top or left axis + // Subtract 1px to draw the line at the end of the tick + var tickLength = (axis.tickSize('tick') || [1])[0]; + var distance = (tickLength - 1) * ((axis.side === GridAxis.Side.top || + axis.side === GridAxis.Side.left) ? -1 : 1); + // If axis is horizontal, reposition line path vertically + if (startPoint[0] === 'M' && endPoint[0] === 'L') { + if (axis.horiz) { + startPoint[2] += distance; + endPoint[2] += distance; + } + else { + // If axis is vertical, reposition line path + // horizontally + startPoint[1] += distance; + endPoint[1] += distance; + } + } + if (!axis.grid.axisLineExtra) { + axis.grid.axisLineExtra = renderer + .path(linePath) + .attr({ + zIndex: 7 + }) + .addClass('highcharts-axis-line') + .add(axis.axisGroup); + if (!renderer.styledMode) { + axis.grid.axisLineExtra.attr({ + stroke: options.lineColor, + 'stroke-width': lineWidth + }); + } + } + else { + axis.grid.axisLineExtra.animate({ + d: linePath + }); + } + // show or hide the line depending on + // options.showEmpty + axis.axisLine[axis.showAxis ? 'show' : 'hide'](true); + } + } + (grid && grid.columns || []).forEach(function (column) { + column.render(); + }); + } + }; + /** + * @private + */ + GridAxis.onAfterSetAxisTranslation = function () { + var axis = this; + var tickInfo = axis.tickPositions && axis.tickPositions.info; + var options = axis.options; + var gridOptions = options.grid || {}; + var userLabels = axis.userOptions.labels || {}; + if (axis.horiz) { + if (gridOptions.enabled === true) { + axis.series.forEach(function (series) { + series.options.pointRange = 0; + }); + } + // Lower level time ticks, like hours or minutes, represent + // points in time and not ranges. These should be aligned + // left in the grid cell by default. The same applies to + // years of higher order. + if (tickInfo && + options.dateTimeLabelFormats && + options.labels && + !defined(userLabels.align) && + (options.dateTimeLabelFormats[tickInfo.unitName].range === false || + tickInfo.count > 1 // years + )) { + options.labels.align = 'left'; + if (!defined(userLabels.x)) { + options.labels.x = 3; + } + } + } + }; + /** + * Creates a left and right wall on horizontal axes: + * - Places leftmost tick at the start of the axis, to create a left + * wall + * - Ensures that the rightmost tick is at the end of the axis, to + * create a right wall. + * @private + */ + GridAxis.onAfterSetOptions = function (e) { + var options = this.options, userOptions = e.userOptions, gridAxisOptions, gridOptions = ((options && isObject(options.grid)) ? options.grid : {}); + if (gridOptions.enabled === true) { + // Merge the user options into default grid axis options so + // that when a user option is set, it takes presedence. + gridAxisOptions = merge(true, { + className: ('highcharts-grid-axis ' + (userOptions.className || '')), + dateTimeLabelFormats: { + hour: { + list: ['%H:%M', '%H'] + }, + day: { + list: ['%A, %e. %B', '%a, %e. %b', '%E'] + }, + week: { + list: ['Week %W', 'W%W'] + }, + month: { + list: ['%B', '%b', '%o'] + } + }, + grid: { + borderWidth: 1 + }, + labels: { + padding: 2, + style: { + fontSize: '13px' + } + }, + margin: 0, + title: { + text: null, + reserveSpace: false, + rotation: 0 + }, + // In a grid axis, only allow one unit of certain types, + // for example we shouln't have one grid cell spanning + // two days. + units: [[ + 'millisecond', + [1, 10, 100] + ], [ + 'second', + [1, 10] + ], [ + 'minute', + [1, 5, 15] + ], [ + 'hour', + [1, 6] + ], [ + 'day', + [1] + ], [ + 'week', + [1] + ], [ + 'month', + [1] + ], [ + 'year', + null + ]] + }, userOptions); + // X-axis specific options + if (this.coll === 'xAxis') { + // For linked axes, tickPixelInterval is used only if + // the tickPositioner below doesn't run or returns + // undefined (like multiple years) + if (defined(userOptions.linkedTo) && + !defined(userOptions.tickPixelInterval)) { + gridAxisOptions.tickPixelInterval = 350; + } + // For the secondary grid axis, use the primary axis' + // tick intervals and return ticks one level higher. + if ( + // Check for tick pixel interval in options + !defined(userOptions.tickPixelInterval) && + // Only for linked axes + defined(userOptions.linkedTo) && + !defined(userOptions.tickPositioner) && + !defined(userOptions.tickInterval)) { + gridAxisOptions.tickPositioner = function (min, max) { + var parentInfo = (this.linkedParent && + this.linkedParent.tickPositions && + this.linkedParent.tickPositions.info); + if (parentInfo) { + var unitIdx, count, unitName, i, units = gridAxisOptions.units, unitRange; + for (i = 0; i < units.length; i++) { + if (units[i][0] === + parentInfo.unitName) { + unitIdx = i; + break; + } + } + // Get the first allowed count on the next + // unit. + if (units[unitIdx + 1]) { + unitName = units[unitIdx + 1][0]; + count = + (units[unitIdx + 1][1] || [1])[0]; + // In case the base X axis shows years, make + // the secondary axis show ten times the + // years (#11427) + } + else if (parentInfo.unitName === 'year') { + unitName = 'year'; + count = parentInfo.count * 10; + } + unitRange = timeUnits[unitName]; + this.tickInterval = unitRange * count; + return this.getTimeTicks({ + unitRange: unitRange, + count: count, + unitName: unitName + }, min, max, this.options.startOfWeek); + } + }; + } + } + // Now merge the combined options into the axis options + merge(true, this.options, gridAxisOptions); + if (this.horiz) { + /* _________________________ + Make this: ___|_____|_____|_____|__| + ^ ^ + _________________________ + Into this: |_____|_____|_____|_____| + ^ ^ */ + options.minPadding = pick(userOptions.minPadding, 0); + options.maxPadding = pick(userOptions.maxPadding, 0); + } + // If borderWidth is set, then use its value for tick and + // line width. + if (isNumber(options.grid.borderWidth)) { + options.tickWidth = options.lineWidth = gridOptions.borderWidth; + } + } + }; + /** + * @private + */ + GridAxis.onAfterSetOptions2 = function (e) { + var axis = this; + var userOptions = e.userOptions; + var gridOptions = userOptions && userOptions.grid || {}; + var columns = gridOptions.columns; + // Add column options to the parent axis. Children has their column + // options set on init in onGridAxisAfterInit. + if (gridOptions.enabled && columns) { + merge(true, axis.options, columns[columns.length - 1]); + } + }; + /** + * Handle columns and setScale. + * @private + */ + GridAxis.onAfterSetScale = function () { + var axis = this; + (axis.grid.columns || []).forEach(function (column) { + column.setScale(); + }); + }; + /** + * Draw vertical axis ticks extra long to create cell floors and roofs. + * Overrides the tickLength for vertical axes. + * @private + */ + GridAxis.onAfterTickSize = function (e) { + var defaultLeftAxisOptions = Axis.defaultLeftAxisOptions; + var _a = this, horiz = _a.horiz, maxLabelDimensions = _a.maxLabelDimensions, _b = _a.options.grid, gridOptions = _b === void 0 ? {} : _b; + if (gridOptions.enabled && maxLabelDimensions) { + var labelPadding = (Math.abs(defaultLeftAxisOptions.labels.x) * 2); + var distance = horiz ? + gridOptions.cellHeight || labelPadding + maxLabelDimensions.height : + labelPadding + maxLabelDimensions.width; + if (isArray(e.tickSize)) { + e.tickSize[0] = distance; + } + else { + e.tickSize = [distance, 0]; + } + } + }; + /** + * @private + */ + GridAxis.onDestroy = function (e) { + var grid = this.grid; + (grid.columns || []).forEach(function (column) { + column.destroy(e.keepEvents); + }); + grid.columns = void 0; + }; + /** + * Wraps axis init to draw cell walls on vertical axes. + * @private + */ + GridAxis.onInit = function (e) { + var axis = this; + var userOptions = e.userOptions || {}; + var gridOptions = userOptions.grid || {}; + if (gridOptions.enabled && defined(gridOptions.borderColor)) { + userOptions.tickColor = userOptions.lineColor = gridOptions.borderColor; + } + if (!axis.grid) { + axis.grid = new GridAxisAdditions(axis); + } + }; + /** + * Makes tick labels which are usually ignored in a linked axis + * displayed if they are within range of linkedParent.min. + * ``` + * _____________________________ + * | | | | | + * Make this: | | 2 | 3 | 4 | + * |___|_______|_______|_______| + * ^ + * _____________________________ + * | | | | | + * Into this: | 1 | 2 | 3 | 4 | + * |___|_______|_______|_______| + * ^ + * ``` + * @private + * @todo Does this function do what the drawing says? Seems to affect + * ticks and not the labels directly? + */ + GridAxis.onTrimTicks = function () { + var axis = this; + var options = axis.options; + var gridOptions = options.grid || {}; + var categoryAxis = axis.categories; + var tickPositions = axis.tickPositions; + var firstPos = tickPositions[0]; + var lastPos = tickPositions[tickPositions.length - 1]; + var linkedMin = axis.linkedParent && axis.linkedParent.min; + var linkedMax = axis.linkedParent && axis.linkedParent.max; + var min = linkedMin || axis.min; + var max = linkedMax || axis.max; + var tickInterval = axis.tickInterval; + var endMoreThanMin = (firstPos < min && + firstPos + tickInterval > min); + var startLessThanMax = (lastPos > max && + lastPos - tickInterval < max); + if (gridOptions.enabled === true && + !categoryAxis && + (axis.horiz || axis.isLinked)) { + if (endMoreThanMin && !options.startOnTick) { + tickPositions[0] = min; + } + if (startLessThanMax && !options.endOnTick) { + tickPositions[tickPositions.length - 1] = max; + } + } + }; + /** + * Avoid altering tickInterval when reserving space. + * @private + */ + GridAxis.wrapUnsquish = function (proceed) { + var axis = this; + var _a = axis.options.grid, gridOptions = _a === void 0 ? {} : _a; + if (gridOptions.enabled === true && axis.categories) { + return axis.tickInterval; + } + return proceed.apply(axis, argsToArray(arguments)); + }; + return GridAxis; +}()); +(function (GridAxis) { + /** + * Enum for which side the axis is on. Maps to axis.side. + * @private + */ + var Side; + (function (Side) { + Side[Side["top"] = 0] = "top"; + Side[Side["right"] = 1] = "right"; + Side[Side["bottom"] = 2] = "bottom"; + Side[Side["left"] = 3] = "left"; + })(Side = GridAxis.Side || (GridAxis.Side = {})); +})(GridAxis || (GridAxis = {})); +GridAxis.compose(Axis); +export default GridAxis; diff --git a/librerias/gantt/code/es-modules/parts-gantt/Pathfinder.js b/librerias/gantt/code/es-modules/parts-gantt/Pathfinder.js new file mode 100644 index 0000000..2c77a88 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-gantt/Pathfinder.js @@ -0,0 +1,1080 @@ +/* * + * + * (c) 2016 Highsoft AS + * Authors: Øystein Moseng, Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +/** + * The default pathfinder algorithm to use for a chart. It is possible to define + * your own algorithms by adding them to the + * `Highcharts.Pathfinder.prototype.algorithms` + * object before the chart has been created. + * + * The default algorithms are as follows: + * + * `straight`: Draws a straight line between the connecting + * points. Does not avoid other points when drawing. + * + * `simpleConnect`: Finds a path between the points using right angles + * only. Takes only starting/ending points into + * account, and will not avoid other points. + * + * `fastAvoid`: Finds a path between the points using right angles + * only. Will attempt to avoid other points, but its + * focus is performance over accuracy. Works well with + * less dense datasets. + * + * @typedef {"fastAvoid"|"simpleConnect"|"straight"|string} Highcharts.PathfinderTypeValue + */ +''; // detach doclets above +import Point from '../parts/Point.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, defined = U.defined, error = U.error, extend = U.extend, merge = U.merge, objectEach = U.objectEach, pick = U.pick, splat = U.splat; +import pathfinderAlgorithms from './PathfinderAlgorithms.js'; +import './ArrowSymbols.js'; +var deg2rad = H.deg2rad, max = Math.max, min = Math.min; +/* + @todo: + - Document how to write your own algorithms + - Consider adding a Point.pathTo method that wraps creating a connection + and rendering it +*/ +// Set default Pathfinder options +extend(H.defaultOptions, { + /** + * The Pathfinder module allows you to define connections between any two + * points, represented as lines - optionally with markers for the start + * and/or end points. Multiple algorithms are available for calculating how + * the connecting lines are drawn. + * + * Connector functionality requires Highcharts Gantt to be loaded. In Gantt + * charts, the connectors are used to draw dependencies between tasks. + * + * @see [dependency](series.gantt.data.dependency) + * + * @sample gantt/pathfinder/demo + * Pathfinder connections + * + * @declare Highcharts.ConnectorsOptions + * @product gantt + * @optionparent connectors + */ + connectors: { + /** + * Enable connectors for this chart. Requires Highcharts Gantt. + * + * @type {boolean} + * @default true + * @since 6.2.0 + * @apioption connectors.enabled + */ + /** + * Set the default dash style for this chart's connecting lines. + * + * @type {string} + * @default solid + * @since 6.2.0 + * @apioption connectors.dashStyle + */ + /** + * Set the default color for this chart's Pathfinder connecting lines. + * Defaults to the color of the point being connected. + * + * @type {Highcharts.ColorString} + * @since 6.2.0 + * @apioption connectors.lineColor + */ + /** + * Set the default pathfinder margin to use, in pixels. Some Pathfinder + * algorithms attempt to avoid obstacles, such as other points in the + * chart. These algorithms use this margin to determine how close lines + * can be to an obstacle. The default is to compute this automatically + * from the size of the obstacles in the chart. + * + * To draw connecting lines close to existing points, set this to a low + * number. For more space around existing points, set this number + * higher. + * + * @sample gantt/pathfinder/algorithm-margin + * Small algorithmMargin + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.algorithmMargin + */ + /** + * Set the default pathfinder algorithm to use for this chart. It is + * possible to define your own algorithms by adding them to the + * Highcharts.Pathfinder.prototype.algorithms object before the chart + * has been created. + * + * The default algorithms are as follows: + * + * `straight`: Draws a straight line between the connecting + * points. Does not avoid other points when drawing. + * + * `simpleConnect`: Finds a path between the points using right angles + * only. Takes only starting/ending points into + * account, and will not avoid other points. + * + * `fastAvoid`: Finds a path between the points using right angles + * only. Will attempt to avoid other points, but its + * focus is performance over accuracy. Works well with + * less dense datasets. + * + * Default value: `straight` is used as default for most series types, + * while `simpleConnect` is used as default for Gantt series, to show + * dependencies between points. + * + * @sample gantt/pathfinder/demo + * Different types used + * + * @type {Highcharts.PathfinderTypeValue} + * @default undefined + * @since 6.2.0 + */ + type: 'straight', + /** + * Set the default pixel width for this chart's Pathfinder connecting + * lines. + * + * @since 6.2.0 + */ + lineWidth: 1, + /** + * Marker options for this chart's Pathfinder connectors. Note that + * this option is overridden by the `startMarker` and `endMarker` + * options. + * + * @declare Highcharts.ConnectorsMarkerOptions + * @since 6.2.0 + */ + marker: { + /** + * Set the radius of the connector markers. The default is + * automatically computed based on the algorithmMargin setting. + * + * Setting marker.width and marker.height will override this + * setting. + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.marker.radius + */ + /** + * Set the width of the connector markers. If not supplied, this + * is inferred from the marker radius. + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.marker.width + */ + /** + * Set the height of the connector markers. If not supplied, this + * is inferred from the marker radius. + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.marker.height + */ + /** + * Set the color of the connector markers. By default this is the + * same as the connector color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 6.2.0 + * @apioption connectors.marker.color + */ + /** + * Set the line/border color of the connector markers. By default + * this is the same as the marker color. + * + * @type {Highcharts.ColorString} + * @since 6.2.0 + * @apioption connectors.marker.lineColor + */ + /** + * Enable markers for the connectors. + */ + enabled: false, + /** + * Horizontal alignment of the markers relative to the points. + * + * @type {Highcharts.AlignValue} + */ + align: 'center', + /** + * Vertical alignment of the markers relative to the points. + * + * @type {Highcharts.VerticalAlignValue} + */ + verticalAlign: 'middle', + /** + * Whether or not to draw the markers inside the points. + */ + inside: false, + /** + * Set the line/border width of the pathfinder markers. + */ + lineWidth: 1 + }, + /** + * Marker options specific to the start markers for this chart's + * Pathfinder connectors. Overrides the generic marker options. + * + * @declare Highcharts.ConnectorsStartMarkerOptions + * @extends connectors.marker + * @since 6.2.0 + */ + startMarker: { + /** + * Set the symbol of the connector start markers. + */ + symbol: 'diamond' + }, + /** + * Marker options specific to the end markers for this chart's + * Pathfinder connectors. Overrides the generic marker options. + * + * @declare Highcharts.ConnectorsEndMarkerOptions + * @extends connectors.marker + * @since 6.2.0 + */ + endMarker: { + /** + * Set the symbol of the connector end markers. + */ + symbol: 'arrow-filled' + } + } +}); +/** + * Override Pathfinder connector options for a series. Requires Highcharts Gantt + * to be loaded. + * + * @declare Highcharts.SeriesConnectorsOptionsObject + * @extends connectors + * @since 6.2.0 + * @excluding enabled, algorithmMargin + * @product gantt + * @apioption plotOptions.series.connectors + */ +/** + * Connect to a point. This option can be either a string, referring to the ID + * of another point, or an object, or an array of either. If the option is an + * array, each element defines a connection. + * + * @sample gantt/pathfinder/demo + * Different connection types + * + * @declare Highcharts.XrangePointConnectorsOptionsObject + * @type {string|Array|*} + * @extends plotOptions.series.connectors + * @since 6.2.0 + * @excluding enabled + * @product gantt + * @requires highcharts-gantt + * @apioption series.xrange.data.connect + */ +/** + * The ID of the point to connect to. + * + * @type {string} + * @since 6.2.0 + * @product gantt + * @apioption series.xrange.data.connect.to + */ +/** + * Get point bounding box using plotX/plotY and shapeArgs. If using + * graphic.getBBox() directly, the bbox will be affected by animation. + * + * @private + * @function + * + * @param {Highcharts.Point} point + * The point to get BB of. + * + * @return {Highcharts.Dictionary|null} + * Result xMax, xMin, yMax, yMin. + */ +function getPointBB(point) { + var shapeArgs = point.shapeArgs, bb; + // Prefer using shapeArgs (columns) + if (shapeArgs) { + return { + xMin: shapeArgs.x, + xMax: shapeArgs.x + shapeArgs.width, + yMin: shapeArgs.y, + yMax: shapeArgs.y + shapeArgs.height + }; + } + // Otherwise use plotX/plotY and bb + bb = point.graphic && point.graphic.getBBox(); + return bb ? { + xMin: point.plotX - bb.width / 2, + xMax: point.plotX + bb.width / 2, + yMin: point.plotY - bb.height / 2, + yMax: point.plotY + bb.height / 2 + } : null; +} +/** + * Calculate margin to place around obstacles for the pathfinder in pixels. + * Returns a minimum of 1 pixel margin. + * + * @private + * @function + * + * @param {Array} obstacles + * Obstacles to calculate margin from. + * + * @return {number} + * The calculated margin in pixels. At least 1. + */ +function calculateObstacleMargin(obstacles) { + var len = obstacles.length, i = 0, j, obstacleDistance, distances = [], + // Compute smallest distance between two rectangles + distance = function (a, b, bbMargin) { + // Count the distance even if we are slightly off + var margin = pick(bbMargin, 10), yOverlap = a.yMax + margin > b.yMin - margin && + a.yMin - margin < b.yMax + margin, xOverlap = a.xMax + margin > b.xMin - margin && + a.xMin - margin < b.xMax + margin, xDistance = yOverlap ? (a.xMin > b.xMax ? a.xMin - b.xMax : b.xMin - a.xMax) : Infinity, yDistance = xOverlap ? (a.yMin > b.yMax ? a.yMin - b.yMax : b.yMin - a.yMax) : Infinity; + // If the rectangles collide, try recomputing with smaller margin. + // If they collide anyway, discard the obstacle. + if (xOverlap && yOverlap) { + return (margin ? + distance(a, b, Math.floor(margin / 2)) : + Infinity); + } + return min(xDistance, yDistance); + }; + // Go over all obstacles and compare them to the others. + for (; i < len; ++i) { + // Compare to all obstacles ahead. We will already have compared this + // obstacle to the ones before. + for (j = i + 1; j < len; ++j) { + obstacleDistance = distance(obstacles[i], obstacles[j]); + // TODO: Magic number 80 + if (obstacleDistance < 80) { // Ignore large distances + distances.push(obstacleDistance); + } + } + } + // Ensure we always have at least one value, even in very spaceous charts + distances.push(80); + return max(Math.floor(distances.sort(function (a, b) { + return (a - b); + })[ + // Discard first 10% of the relevant distances, and then grab + // the smallest one. + Math.floor(distances.length / 10)] / 2 - 1 // Divide the distance by 2 and subtract 1. + ), 1 // 1 is the minimum margin + ); +} +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * The Connection class. Used internally to represent a connection between two + * points. + * + * @private + * @class + * @name Highcharts.Connection + * + * @param {Highcharts.Point} from + * Connection runs from this Point. + * + * @param {Highcharts.Point} to + * Connection runs to this Point. + * + * @param {Highcharts.ConnectorsOptions} [options] + * Connection options. + */ +function Connection(from, to, options) { + this.init(from, to, options); +} +Connection.prototype = { + /** + * Initialize the Connection object. Used as constructor only. + * + * @function Highcharts.Connection#init + * + * @param {Highcharts.Point} from + * Connection runs from this Point. + * + * @param {Highcharts.Point} to + * Connection runs to this Point. + * + * @param {Highcharts.ConnectorsOptions} [options] + * Connection options. + */ + init: function (from, to, options) { + this.fromPoint = from; + this.toPoint = to; + this.options = options; + this.chart = from.series.chart; + this.pathfinder = this.chart.pathfinder; + }, + /** + * Add (or update) this connection's path on chart. Stores reference to the + * created element on this.graphics.path. + * + * @function Highcharts.Connection#renderPath + * + * @param {Highcharts.SVGPathArray} path + * Path to render, in array format. E.g. ['M', 0, 0, 'L', 10, 10] + * + * @param {Highcharts.SVGAttributes} [attribs] + * SVG attributes for the path. + * + * @param {Highcharts.AnimationOptionsObject} [animation] + * Animation options for the rendering. + */ + renderPath: function (path, attribs, animation) { + var connection = this, chart = this.chart, styledMode = chart.styledMode, pathfinder = chart.pathfinder, animate = !chart.options.chart.forExport && animation !== false, pathGraphic = connection.graphics && connection.graphics.path, anim; + // Add the SVG element of the pathfinder group if it doesn't exist + if (!pathfinder.group) { + pathfinder.group = chart.renderer.g() + .addClass('highcharts-pathfinder-group') + .attr({ zIndex: -1 }) + .add(chart.seriesGroup); + } + // Shift the group to compensate for plot area. + // Note: Do this always (even when redrawing a path) to avoid issues + // when updating chart in a way that changes plot metrics. + pathfinder.group.translate(chart.plotLeft, chart.plotTop); + // Create path if does not exist + if (!(pathGraphic && pathGraphic.renderer)) { + pathGraphic = chart.renderer.path() + .add(pathfinder.group); + if (!styledMode) { + pathGraphic.attr({ + opacity: 0 + }); + } + } + // Set path attribs and animate to the new path + pathGraphic.attr(attribs); + anim = { d: path }; + if (!styledMode) { + anim.opacity = 1; + } + pathGraphic[animate ? 'animate' : 'attr'](anim, animation); + // Store reference on connection + this.graphics = this.graphics || {}; + this.graphics.path = pathGraphic; + }, + /** + * Calculate and add marker graphics for connection to the chart. The + * created/updated elements are stored on this.graphics.start and + * this.graphics.end. + * + * @function Highcharts.Connection#addMarker + * + * @param {string} type + * Marker type, either 'start' or 'end'. + * + * @param {Highcharts.ConnectorsMarkerOptions} options + * All options for this marker. Not calculated or merged with other + * options. + * + * @param {Highcharts.SVGPathArray} path + * Connection path in array format. This is used to calculate the + * rotation angle of the markers. + */ + addMarker: function (type, options, path) { + var connection = this, chart = connection.fromPoint.series.chart, pathfinder = chart.pathfinder, renderer = chart.renderer, point = (type === 'start' ? + connection.fromPoint : + connection.toPoint), anchor = point.getPathfinderAnchorPoint(options), markerVector, radians, rotation, box, width, height, pathVector, segment; + if (!options.enabled) { + return; + } + // Last vector before start/end of path, used to get angle + if (type === 'start') { + segment = path[1]; + } + else { // 'end' + segment = path[path.length - 2]; + } + if (segment && segment[0] === 'M' || segment[0] === 'L') { + pathVector = { + x: segment[1], + y: segment[2] + }; + // Get angle between pathVector and anchor point and use it to + // create marker position. + radians = point.getRadiansToVector(pathVector, anchor); + markerVector = point.getMarkerVector(radians, options.radius, anchor); + // Rotation of marker is calculated from angle between pathVector + // and markerVector. + // (Note: + // Used to recalculate radians between markerVector and pathVector, + // but this should be the same as between pathVector and anchor.) + rotation = -radians / deg2rad; + if (options.width && options.height) { + width = options.width; + height = options.height; + } + else { + width = height = options.radius * 2; + } + // Add graphics object if it does not exist + connection.graphics = connection.graphics || {}; + box = { + x: markerVector.x - (width / 2), + y: markerVector.y - (height / 2), + width: width, + height: height, + rotation: rotation, + rotationOriginX: markerVector.x, + rotationOriginY: markerVector.y + }; + if (!connection.graphics[type]) { + // Create new marker element + connection.graphics[type] = renderer + .symbol(options.symbol) + .addClass('highcharts-point-connecting-path-' + type + '-marker') + .attr(box) + .add(pathfinder.group); + if (!renderer.styledMode) { + connection.graphics[type].attr({ + fill: options.color || connection.fromPoint.color, + stroke: options.lineColor, + 'stroke-width': options.lineWidth, + opacity: 0 + }) + .animate({ + opacity: 1 + }, point.series.options.animation); + } + } + else { + connection.graphics[type].animate(box); + } + } + }, + /** + * Calculate and return connection path. + * Note: Recalculates chart obstacles on demand if they aren't calculated. + * + * @function Highcharts.Connection#getPath + * + * @param {Highcharts.ConnectorsOptions} options + * Connector options. Not calculated or merged with other options. + * + * @return {object|undefined} + * Calculated SVG path data in array format. + */ + getPath: function (options) { + var pathfinder = this.pathfinder, chart = this.chart, algorithm = pathfinder.algorithms[options.type], chartObstacles = pathfinder.chartObstacles; + if (typeof algorithm !== 'function') { + error('"' + options.type + '" is not a Pathfinder algorithm.'); + return; + } + // This function calculates obstacles on demand if they don't exist + if (algorithm.requiresObstacles && !chartObstacles) { + chartObstacles = + pathfinder.chartObstacles = + pathfinder.getChartObstacles(options); + // If the algorithmMargin was computed, store the result in default + // options. + chart.options.connectors.algorithmMargin = + options.algorithmMargin; + // Cache some metrics too + pathfinder.chartObstacleMetrics = + pathfinder.getObstacleMetrics(chartObstacles); + } + // Get the SVG path + return algorithm( + // From + this.fromPoint.getPathfinderAnchorPoint(options.startMarker), + // To + this.toPoint.getPathfinderAnchorPoint(options.endMarker), merge({ + chartObstacles: chartObstacles, + lineObstacles: pathfinder.lineObstacles || [], + obstacleMetrics: pathfinder.chartObstacleMetrics, + hardBounds: { + xMin: 0, + xMax: chart.plotWidth, + yMin: 0, + yMax: chart.plotHeight + }, + obstacleOptions: { + margin: options.algorithmMargin + }, + startDirectionX: pathfinder.getAlgorithmStartDirection(options.startMarker) + }, options)); + }, + /** + * (re)Calculate and (re)draw the connection. + * + * @function Highcharts.Connection#render + */ + render: function () { + var connection = this, fromPoint = connection.fromPoint, series = fromPoint.series, chart = series.chart, pathfinder = chart.pathfinder, pathResult, path, options = merge(chart.options.connectors, series.options.connectors, fromPoint.options.connectors, connection.options), attribs = {}; + // Set path attribs + if (!chart.styledMode) { + attribs.stroke = options.lineColor || fromPoint.color; + attribs['stroke-width'] = options.lineWidth; + if (options.dashStyle) { + attribs.dashstyle = options.dashStyle; + } + } + attribs['class'] = // eslint-disable-line dot-notation + 'highcharts-point-connecting-path ' + + 'highcharts-color-' + fromPoint.colorIndex; + options = merge(attribs, options); + // Set common marker options + if (!defined(options.marker.radius)) { + options.marker.radius = min(max(Math.ceil((options.algorithmMargin || 8) / 2) - 1, 1), 5); + } + // Get the path + pathResult = connection.getPath(options); + path = pathResult.path; + // Always update obstacle storage with obstacles from this path. + // We don't know if future calls will need this for their algorithm. + if (pathResult.obstacles) { + pathfinder.lineObstacles = + pathfinder.lineObstacles || []; + pathfinder.lineObstacles = + pathfinder.lineObstacles.concat(pathResult.obstacles); + } + // Add the calculated path to the pathfinder group + connection.renderPath(path, attribs, series.options.animation); + // Render the markers + connection.addMarker('start', merge(options.marker, options.startMarker), path); + connection.addMarker('end', merge(options.marker, options.endMarker), path); + }, + /** + * Destroy connection by destroying the added graphics elements. + * + * @function Highcharts.Connection#destroy + */ + destroy: function () { + if (this.graphics) { + objectEach(this.graphics, function (val) { + val.destroy(); + }); + delete this.graphics; + } + } +}; +/** + * The Pathfinder class. + * + * @private + * @class + * @name Highcharts.Pathfinder + * + * @param {Highcharts.Chart} chart + * The chart to operate on. + */ +function Pathfinder(chart) { + this.init(chart); +} +Pathfinder.prototype = { + /** + * @name Highcharts.Pathfinder#algorithms + * @type {Highcharts.Dictionary} + */ + algorithms: pathfinderAlgorithms, + /** + * Initialize the Pathfinder object. + * + * @function Highcharts.Pathfinder#init + * + * @param {Highcharts.Chart} chart + * The chart context. + */ + init: function (chart) { + // Initialize pathfinder with chart context + this.chart = chart; + // Init connection reference list + this.connections = []; + // Recalculate paths/obstacles on chart redraw + addEvent(chart, 'redraw', function () { + this.pathfinder.update(); + }); + }, + /** + * Update Pathfinder connections from scratch. + * + * @function Highcharts.Pathfinder#update + * + * @param {boolean} [deferRender] + * Whether or not to defer rendering of connections until + * series.afterAnimate event has fired. Used on first render. + */ + update: function (deferRender) { + var chart = this.chart, pathfinder = this, oldConnections = pathfinder.connections; + // Rebuild pathfinder connections from options + pathfinder.connections = []; + chart.series.forEach(function (series) { + if (series.visible && !series.options.isInternal) { + series.points.forEach(function (point) { + var to, connects = (point.options && + point.options.connect && + splat(point.options.connect)); + if (point.visible && point.isInside !== false && connects) { + connects.forEach(function (connect) { + to = chart.get(typeof connect === 'string' ? + connect : connect.to); + if (to instanceof Point && + to.series.visible && + to.visible && + to.isInside !== false) { + // Add new connection + pathfinder.connections.push(new Connection(point, // from + to, typeof connect === 'string' ? + {} : + connect)); + } + }); + } + }); + } + }); + // Clear connections that should not be updated, and move old info over + // to new connections. + for (var j = 0, k, found, lenOld = oldConnections.length, lenNew = pathfinder.connections.length; j < lenOld; ++j) { + found = false; + for (k = 0; k < lenNew; ++k) { + if (oldConnections[j].fromPoint === + pathfinder.connections[k].fromPoint && + oldConnections[j].toPoint === + pathfinder.connections[k].toPoint) { + pathfinder.connections[k].graphics = + oldConnections[j].graphics; + found = true; + break; + } + } + if (!found) { + oldConnections[j].destroy(); + } + } + // Clear obstacles to force recalculation. This must be done on every + // redraw in case positions have changed. Recalculation is handled in + // Connection.getPath on demand. + delete this.chartObstacles; + delete this.lineObstacles; + // Draw the pending connections + pathfinder.renderConnections(deferRender); + }, + /** + * Draw the chart's connecting paths. + * + * @function Highcharts.Pathfinder#renderConnections + * + * @param {boolean} [deferRender] + * Whether or not to defer render until series animation is finished. + * Used on first render. + */ + renderConnections: function (deferRender) { + if (deferRender) { + // Render after series are done animating + this.chart.series.forEach(function (series) { + var render = function () { + // Find pathfinder connections belonging to this series + // that haven't rendered, and render them now. + var pathfinder = series.chart.pathfinder, conns = pathfinder && pathfinder.connections || []; + conns.forEach(function (connection) { + if (connection.fromPoint && + connection.fromPoint.series === series) { + connection.render(); + } + }); + if (series.pathfinderRemoveRenderEvent) { + series.pathfinderRemoveRenderEvent(); + delete series.pathfinderRemoveRenderEvent; + } + }; + if (series.options.animation === false) { + render(); + } + else { + series.pathfinderRemoveRenderEvent = addEvent(series, 'afterAnimate', render); + } + }); + } + else { + // Go through connections and render them + this.connections.forEach(function (connection) { + connection.render(); + }); + } + }, + /** + * Get obstacles for the points in the chart. Does not include connecting + * lines from Pathfinder. Applies algorithmMargin to the obstacles. + * + * @function Highcharts.Pathfinder#getChartObstacles + * + * @param {object} options + * Options for the calculation. Currenlty only + * options.algorithmMargin. + * + * @return {Array} + * An array of calculated obstacles. Each obstacle is defined as an + * object with xMin, xMax, yMin and yMax properties. + */ + getChartObstacles: function (options) { + var obstacles = [], series = this.chart.series, margin = pick(options.algorithmMargin, 0), calculatedMargin; + for (var i = 0, sLen = series.length; i < sLen; ++i) { + if (series[i].visible && !series[i].options.isInternal) { + for (var j = 0, pLen = series[i].points.length, bb, point; j < pLen; ++j) { + point = series[i].points[j]; + if (point.visible) { + bb = getPointBB(point); + if (bb) { + obstacles.push({ + xMin: bb.xMin - margin, + xMax: bb.xMax + margin, + yMin: bb.yMin - margin, + yMax: bb.yMax + margin + }); + } + } + } + } + } + // Sort obstacles by xMin for optimization + obstacles = obstacles.sort(function (a, b) { + return a.xMin - b.xMin; + }); + // Add auto-calculated margin if the option is not defined + if (!defined(options.algorithmMargin)) { + calculatedMargin = + options.algorithmMargin = + calculateObstacleMargin(obstacles); + obstacles.forEach(function (obstacle) { + obstacle.xMin -= calculatedMargin; + obstacle.xMax += calculatedMargin; + obstacle.yMin -= calculatedMargin; + obstacle.yMax += calculatedMargin; + }); + } + return obstacles; + }, + /** + * Utility function to get metrics for obstacles: + * - Widest obstacle width + * - Tallest obstacle height + * + * @function Highcharts.Pathfinder#getObstacleMetrics + * + * @param {Array} obstacles + * An array of obstacles to inspect. + * + * @return {object} + * The calculated metrics, as an object with maxHeight and maxWidth + * properties. + */ + getObstacleMetrics: function (obstacles) { + var maxWidth = 0, maxHeight = 0, width, height, i = obstacles.length; + while (i--) { + width = obstacles[i].xMax - obstacles[i].xMin; + height = obstacles[i].yMax - obstacles[i].yMin; + if (maxWidth < width) { + maxWidth = width; + } + if (maxHeight < height) { + maxHeight = height; + } + } + return { + maxHeight: maxHeight, + maxWidth: maxWidth + }; + }, + /** + * Utility to get which direction to start the pathfinding algorithm + * (X vs Y), calculated from a set of marker options. + * + * @function Highcharts.Pathfinder#getAlgorithmStartDirection + * + * @param {Highcharts.ConnectorsMarkerOptions} markerOptions + * Marker options to calculate from. + * + * @return {boolean} + * Returns true for X, false for Y, and undefined for autocalculate. + */ + getAlgorithmStartDirection: function (markerOptions) { + var xCenter = markerOptions.align !== 'left' && + markerOptions.align !== 'right', yCenter = markerOptions.verticalAlign !== 'top' && + markerOptions.verticalAlign !== 'bottom', undef; + return xCenter ? + (yCenter ? undef : false) : // x is centered + (yCenter ? true : undef); // x is off-center + } +}; +// Add to Highcharts namespace +H.Connection = Connection; +H.Pathfinder = Pathfinder; +// Add pathfinding capabilities to Points +extend(Point.prototype, /** @lends Point.prototype */ { + /** + * Get coordinates of anchor point for pathfinder connection. + * + * @private + * @function Highcharts.Point#getPathfinderAnchorPoint + * + * @param {Highcharts.ConnectorsMarkerOptions} markerOptions + * Connection options for position on point. + * + * @return {Highcharts.PositionObject} + * An object with x/y properties for the position. Coordinates are + * in plot values, not relative to point. + */ + getPathfinderAnchorPoint: function (markerOptions) { + var bb = getPointBB(this), x, y; + switch (markerOptions.align) { // eslint-disable-line default-case + case 'right': + x = 'xMax'; + break; + case 'left': + x = 'xMin'; + } + switch (markerOptions.verticalAlign) { // eslint-disable-line default-case + case 'top': + y = 'yMin'; + break; + case 'bottom': + y = 'yMax'; + } + return { + x: x ? bb[x] : (bb.xMin + bb.xMax) / 2, + y: y ? bb[y] : (bb.yMin + bb.yMax) / 2 + }; + }, + /** + * Utility to get the angle from one point to another. + * + * @private + * @function Highcharts.Point#getRadiansToVector + * + * @param {Highcharts.PositionObject} v1 + * The first vector, as an object with x/y properties. + * + * @param {Highcharts.PositionObject} v2 + * The second vector, as an object with x/y properties. + * + * @return {number} + * The angle in degrees + */ + getRadiansToVector: function (v1, v2) { + var box; + if (!defined(v2)) { + box = getPointBB(this); + if (box) { + v2 = { + x: (box.xMin + box.xMax) / 2, + y: (box.yMin + box.yMax) / 2 + }; + } + } + return Math.atan2(v2.y - v1.y, v1.x - v2.x); + }, + /** + * Utility to get the position of the marker, based on the path angle and + * the marker's radius. + * + * @private + * @function Highcharts.Point#getMarkerVector + * + * @param {number} radians + * The angle in radians from the point center to another vector. + * + * @param {number} markerRadius + * The radius of the marker, to calculate the additional distance to + * the center of the marker. + * + * @param {object} anchor + * The anchor point of the path and marker as an object with x/y + * properties. + * + * @return {object} + * The marker vector as an object with x/y properties. + */ + getMarkerVector: function (radians, markerRadius, anchor) { + var twoPI = Math.PI * 2.0, theta = radians, bb = getPointBB(this), rectWidth = bb.xMax - bb.xMin, rectHeight = bb.yMax - bb.yMin, rAtan = Math.atan2(rectHeight, rectWidth), tanTheta = 1, leftOrRightRegion = false, rectHalfWidth = rectWidth / 2.0, rectHalfHeight = rectHeight / 2.0, rectHorizontalCenter = bb.xMin + rectHalfWidth, rectVerticalCenter = bb.yMin + rectHalfHeight, edgePoint = { + x: rectHorizontalCenter, + y: rectVerticalCenter + }, markerPoint = {}, xFactor = 1, yFactor = 1; + while (theta < -Math.PI) { + theta += twoPI; + } + while (theta > Math.PI) { + theta -= twoPI; + } + tanTheta = Math.tan(theta); + if ((theta > -rAtan) && (theta <= rAtan)) { + // Right side + yFactor = -1; + leftOrRightRegion = true; + } + else if (theta > rAtan && theta <= (Math.PI - rAtan)) { + // Top side + yFactor = -1; + } + else if (theta > (Math.PI - rAtan) || theta <= -(Math.PI - rAtan)) { + // Left side + xFactor = -1; + leftOrRightRegion = true; + } + else { + // Bottom side + xFactor = -1; + } + // Correct the edgePoint according to the placement of the marker + if (leftOrRightRegion) { + edgePoint.x += xFactor * (rectHalfWidth); + edgePoint.y += yFactor * (rectHalfWidth) * tanTheta; + } + else { + edgePoint.x += xFactor * (rectHeight / (2.0 * tanTheta)); + edgePoint.y += yFactor * (rectHalfHeight); + } + if (anchor.x !== rectHorizontalCenter) { + edgePoint.x = anchor.x; + } + if (anchor.y !== rectVerticalCenter) { + edgePoint.y = anchor.y; + } + markerPoint.x = edgePoint.x + (markerRadius * Math.cos(theta)); + markerPoint.y = edgePoint.y - (markerRadius * Math.sin(theta)); + return markerPoint; + } +}); +/** + * Warn if using legacy options. Copy the options over. Note that this will + * still break if using the legacy options in chart.update, addSeries etc. + * @private + */ +function warnLegacy(chart) { + if (chart.options.pathfinder || + chart.series.reduce(function (acc, series) { + if (series.options) { + merge(true, (series.options.connectors = series.options.connectors || + {}), series.options.pathfinder); + } + return acc || series.options && series.options.pathfinder; + }, false)) { + merge(true, (chart.options.connectors = chart.options.connectors || {}), chart.options.pathfinder); + error('WARNING: Pathfinder options have been renamed. ' + + 'Use "chart.connectors" or "series.connectors" instead.'); + } +} +// Initialize Pathfinder for charts +H.Chart.prototype.callbacks.push(function (chart) { + var options = chart.options; + if (options.connectors.enabled !== false) { + warnLegacy(chart); + this.pathfinder = new Pathfinder(this); + this.pathfinder.update(true); // First draw, defer render + } +}); diff --git a/librerias/gantt/code/es-modules/parts-gantt/PathfinderAlgorithms.js b/librerias/gantt/code/es-modules/parts-gantt/PathfinderAlgorithms.js new file mode 100644 index 0000000..26bead9 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-gantt/PathfinderAlgorithms.js @@ -0,0 +1,656 @@ +/* * + * + * (c) 2016 Highsoft AS + * Author: Øystein Moseng + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import U from '../parts/Utilities.js'; +var extend = U.extend, pick = U.pick; +var min = Math.min, max = Math.max, abs = Math.abs; +/** + * Get index of last obstacle before xMin. Employs a type of binary search, and + * thus requires that obstacles are sorted by xMin value. + * + * @private + * @function findLastObstacleBefore + * + * @param {Array} obstacles + * Array of obstacles to search in. + * + * @param {number} xMin + * The xMin threshold. + * + * @param {number} [startIx] + * Starting index to search from. Must be within array range. + * + * @return {number} + * The index of the last obstacle element before xMin. + */ +function findLastObstacleBefore(obstacles, xMin, startIx) { + var left = startIx || 0, // left limit + right = obstacles.length - 1, // right limit + min = xMin - 0.0000001, // Make sure we include all obstacles at xMin + cursor, cmp; + while (left <= right) { + cursor = (right + left) >> 1; + cmp = min - obstacles[cursor].xMin; + if (cmp > 0) { + left = cursor + 1; + } + else if (cmp < 0) { + right = cursor - 1; + } + else { + return cursor; + } + } + return left > 0 ? left - 1 : 0; +} +/** + * Test if a point lays within an obstacle. + * + * @private + * @function pointWithinObstacle + * + * @param {object} obstacle + * Obstacle to test. + * + * @param {Highcharts.Point} point + * Point with x/y props. + * + * @return {boolean} + * Whether point is within the obstacle or not. + */ +function pointWithinObstacle(obstacle, point) { + return (point.x <= obstacle.xMax && + point.x >= obstacle.xMin && + point.y <= obstacle.yMax && + point.y >= obstacle.yMin); +} +/** + * Find the index of an obstacle that wraps around a point. + * Returns -1 if not found. + * + * @private + * @function findObstacleFromPoint + * + * @param {Array} obstacles + * Obstacles to test. + * + * @param {Highcharts.Point} point + * Point with x/y props. + * + * @return {number} + * Ix of the obstacle in the array, or -1 if not found. + */ +function findObstacleFromPoint(obstacles, point) { + var i = findLastObstacleBefore(obstacles, point.x + 1) + 1; + while (i--) { + if (obstacles[i].xMax >= point.x && + // optimization using lazy evaluation + pointWithinObstacle(obstacles[i], point)) { + return i; + } + } + return -1; +} +/** + * Get SVG path array from array of line segments. + * + * @private + * @function pathFromSegments + * + * @param {Array} segments + * The segments to build the path from. + * + * @return {Highcharts.SVGPathArray} + * SVG path array as accepted by the SVG Renderer. + */ +function pathFromSegments(segments) { + var path = []; + if (segments.length) { + path.push(['M', segments[0].start.x, segments[0].start.y]); + for (var i = 0; i < segments.length; ++i) { + path.push(['L', segments[i].end.x, segments[i].end.y]); + } + } + return path; +} +/** + * Limits obstacle max/mins in all directions to bounds. Modifies input + * obstacle. + * + * @private + * @function limitObstacleToBounds + * + * @param {object} obstacle + * Obstacle to limit. + * + * @param {object} bounds + * Bounds to use as limit. + * + * @return {void} + */ +function limitObstacleToBounds(obstacle, bounds) { + obstacle.yMin = max(obstacle.yMin, bounds.yMin); + obstacle.yMax = min(obstacle.yMax, bounds.yMax); + obstacle.xMin = max(obstacle.xMin, bounds.xMin); + obstacle.xMax = min(obstacle.xMax, bounds.xMax); +} +// Define the available pathfinding algorithms. +// Algorithms take up to 3 arguments: starting point, ending point, and an +// options object. +var algorithms = { + /** + * Get an SVG path from a starting coordinate to an ending coordinate. + * Draws a straight line. + * + * @function Highcharts.Pathfinder.algorithms.straight + * + * @param {Highcharts.PositionObject} start + * Starting coordinate, object with x/y props. + * + * @param {Highcharts.PositionObject} end + * Ending coordinate, object with x/y props. + * + * @return {object} + * An object with the SVG path in Array form as accepted by the SVG + * renderer, as well as an array of new obstacles making up this + * path. + */ + straight: function (start, end) { + return { + path: [ + ['M', start.x, start.y], + ['L', end.x, end.y] + ], + obstacles: [{ start: start, end: end }] + }; + }, + /** + * Find a path from a starting coordinate to an ending coordinate, using + * right angles only, and taking only starting/ending obstacle into + * consideration. + * + * @function Highcharts.Pathfinder.algorithms.simpleConnect + * + * @param {Highcharts.PositionObject} start + * Starting coordinate, object with x/y props. + * + * @param {Highcharts.PositionObject} end + * Ending coordinate, object with x/y props. + * + * @param {object} options + * Options for the algorithm: + * - chartObstacles: Array of chart obstacles to avoid + * - startDirectionX: Optional. True if starting in the X direction. + * If not provided, the algorithm starts in the direction that is + * the furthest between start/end. + * + * @return {object} + * An object with the SVG path in Array form as accepted by the SVG + * renderer, as well as an array of new obstacles making up this + * path. + */ + simpleConnect: extend(function (start, end, options) { + var segments = [], endSegment, dir = pick(options.startDirectionX, abs(end.x - start.x) > abs(end.y - start.y)) ? 'x' : 'y', chartObstacles = options.chartObstacles, startObstacleIx = findObstacleFromPoint(chartObstacles, start), endObstacleIx = findObstacleFromPoint(chartObstacles, end), startObstacle, endObstacle, prevWaypoint, waypoint, waypoint2, useMax, endPoint; + // eslint-disable-next-line valid-jsdoc + /** + * Return a clone of a point with a property set from a target object, + * optionally with an offset + * @private + */ + function copyFromPoint(from, fromKey, to, toKey, offset) { + var point = { + x: from.x, + y: from.y + }; + point[fromKey] = to[toKey || fromKey] + (offset || 0); + return point; + } + // eslint-disable-next-line valid-jsdoc + /** + * Return waypoint outside obstacle. + * @private + */ + function getMeOut(obstacle, point, direction) { + var useMax = abs(point[direction] - obstacle[direction + 'Min']) > + abs(point[direction] - obstacle[direction + 'Max']); + return copyFromPoint(point, direction, obstacle, direction + (useMax ? 'Max' : 'Min'), useMax ? 1 : -1); + } + // Pull out end point + if (endObstacleIx > -1) { + endObstacle = chartObstacles[endObstacleIx]; + waypoint = getMeOut(endObstacle, end, dir); + endSegment = { + start: waypoint, + end: end + }; + endPoint = waypoint; + } + else { + endPoint = end; + } + // If an obstacle envelops the start point, add a segment to get out, + // and around it. + if (startObstacleIx > -1) { + startObstacle = chartObstacles[startObstacleIx]; + waypoint = getMeOut(startObstacle, start, dir); + segments.push({ + start: start, + end: waypoint + }); + // If we are going back again, switch direction to get around start + // obstacle. + if ( + // Going towards max from start: + waypoint[dir] >= start[dir] === + // Going towards min to end: + waypoint[dir] >= endPoint[dir]) { + dir = dir === 'y' ? 'x' : 'y'; + useMax = start[dir] < end[dir]; + segments.push({ + start: waypoint, + end: copyFromPoint(waypoint, dir, startObstacle, dir + (useMax ? 'Max' : 'Min'), useMax ? 1 : -1) + }); + // Switch direction again + dir = dir === 'y' ? 'x' : 'y'; + } + } + // We are around the start obstacle. Go towards the end in one + // direction. + prevWaypoint = segments.length ? + segments[segments.length - 1].end : + start; + waypoint = copyFromPoint(prevWaypoint, dir, endPoint); + segments.push({ + start: prevWaypoint, + end: waypoint + }); + // Final run to end point in the other direction + dir = dir === 'y' ? 'x' : 'y'; + waypoint2 = copyFromPoint(waypoint, dir, endPoint); + segments.push({ + start: waypoint, + end: waypoint2 + }); + // Finally add the endSegment + segments.push(endSegment); + return { + path: pathFromSegments(segments), + obstacles: segments + }; + }, { + requiresObstacles: true + }), + /** + * Find a path from a starting coordinate to an ending coordinate, taking + * obstacles into consideration. Might not always find the optimal path, + * but is fast, and usually good enough. + * + * @function Highcharts.Pathfinder.algorithms.fastAvoid + * + * @param {Highcharts.PositionObject} start + * Starting coordinate, object with x/y props. + * + * @param {Highcharts.PositionObject} end + * Ending coordinate, object with x/y props. + * + * @param {object} options + * Options for the algorithm. + * - chartObstacles: Array of chart obstacles to avoid + * - lineObstacles: Array of line obstacles to jump over + * - obstacleMetrics: Object with metrics of chartObstacles cached + * - hardBounds: Hard boundaries to not cross + * - obstacleOptions: Options for the obstacles, including margin + * - startDirectionX: Optional. True if starting in the X direction. + * If not provided, the algorithm starts in the + * direction that is the furthest between + * start/end. + * + * @return {object} + * An object with the SVG path in Array form as accepted by the SVG + * renderer, as well as an array of new obstacles making up this + * path. + */ + fastAvoid: extend(function (start, end, options) { + /* + Algorithm rules/description + - Find initial direction + - Determine soft/hard max for each direction. + - Move along initial direction until obstacle. + - Change direction. + - If hitting obstacle, first try to change length of previous line + before changing direction again. + + Soft min/max x = start/destination x +/- widest obstacle + margin + Soft min/max y = start/destination y +/- tallest obstacle + margin + + @todo: + - Make retrospective, try changing prev segment to reduce + corners + - Fix logic for breaking out of end-points - not always picking + the best direction currently + - When going around the end obstacle we should not always go the + shortest route, rather pick the one closer to the end point + */ + var dirIsX = pick(options.startDirectionX, abs(end.x - start.x) > abs(end.y - start.y)), dir = dirIsX ? 'x' : 'y', segments, useMax, extractedEndPoint, endSegments = [], forceObstacleBreak = false, // Used in clearPathTo to keep track of + // when to force break through an obstacle. + // Boundaries to stay within. If beyond soft boundary, prefer to + // change direction ASAP. If at hard max, always change immediately. + metrics = options.obstacleMetrics, softMinX = min(start.x, end.x) - metrics.maxWidth - 10, softMaxX = max(start.x, end.x) + metrics.maxWidth + 10, softMinY = min(start.y, end.y) - metrics.maxHeight - 10, softMaxY = max(start.y, end.y) + metrics.maxHeight + 10, + // Obstacles + chartObstacles = options.chartObstacles, startObstacleIx = findLastObstacleBefore(chartObstacles, softMinX), endObstacleIx = findLastObstacleBefore(chartObstacles, softMaxX); + // eslint-disable-next-line valid-jsdoc + /** + * How far can you go between two points before hitting an obstacle? + * Does not work for diagonal lines (because it doesn't have to). + * @private + */ + function pivotPoint(fromPoint, toPoint, directionIsX) { + var firstPoint, lastPoint, highestPoint, lowestPoint, i, searchDirection = fromPoint.x < toPoint.x ? 1 : -1; + if (fromPoint.x < toPoint.x) { + firstPoint = fromPoint; + lastPoint = toPoint; + } + else { + firstPoint = toPoint; + lastPoint = fromPoint; + } + if (fromPoint.y < toPoint.y) { + lowestPoint = fromPoint; + highestPoint = toPoint; + } + else { + lowestPoint = toPoint; + highestPoint = fromPoint; + } + // Go through obstacle range in reverse if toPoint is before + // fromPoint in the X-dimension. + i = searchDirection < 0 ? + // Searching backwards, start at last obstacle before last point + min(findLastObstacleBefore(chartObstacles, lastPoint.x), chartObstacles.length - 1) : + // Forwards. Since we're not sorted by xMax, we have to look + // at all obstacles. + 0; + // Go through obstacles in this X range + while (chartObstacles[i] && (searchDirection > 0 && chartObstacles[i].xMin <= lastPoint.x || + searchDirection < 0 && chartObstacles[i].xMax >= firstPoint.x)) { + // If this obstacle is between from and to points in a straight + // line, pivot at the intersection. + if (chartObstacles[i].xMin <= lastPoint.x && + chartObstacles[i].xMax >= firstPoint.x && + chartObstacles[i].yMin <= highestPoint.y && + chartObstacles[i].yMax >= lowestPoint.y) { + if (directionIsX) { + return { + y: fromPoint.y, + x: fromPoint.x < toPoint.x ? + chartObstacles[i].xMin - 1 : + chartObstacles[i].xMax + 1, + obstacle: chartObstacles[i] + }; + } + // else ... + return { + x: fromPoint.x, + y: fromPoint.y < toPoint.y ? + chartObstacles[i].yMin - 1 : + chartObstacles[i].yMax + 1, + obstacle: chartObstacles[i] + }; + } + i += searchDirection; + } + return toPoint; + } + /** + * Decide in which direction to dodge or get out of an obstacle. + * Considers desired direction, which way is shortest, soft and hard + * bounds. + * + * (? Returns a string, either xMin, xMax, yMin or yMax.) + * + * @private + * @function + * + * @param {object} obstacle + * Obstacle to dodge/escape. + * + * @param {object} fromPoint + * Point with x/y props that's dodging/escaping. + * + * @param {object} toPoint + * Goal point. + * + * @param {boolean} dirIsX + * Dodge in X dimension. + * + * @param {object} bounds + * Hard and soft boundaries. + * + * @return {boolean} + * Use max or not. + */ + function getDodgeDirection(obstacle, fromPoint, toPoint, dirIsX, bounds) { + var softBounds = bounds.soft, hardBounds = bounds.hard, dir = dirIsX ? 'x' : 'y', toPointMax = { x: fromPoint.x, y: fromPoint.y }, toPointMin = { x: fromPoint.x, y: fromPoint.y }, minPivot, maxPivot, maxOutOfSoftBounds = obstacle[dir + 'Max'] >= + softBounds[dir + 'Max'], minOutOfSoftBounds = obstacle[dir + 'Min'] <= + softBounds[dir + 'Min'], maxOutOfHardBounds = obstacle[dir + 'Max'] >= + hardBounds[dir + 'Max'], minOutOfHardBounds = obstacle[dir + 'Min'] <= + hardBounds[dir + 'Min'], + // Find out if we should prefer one direction over the other if + // we can choose freely + minDistance = abs(obstacle[dir + 'Min'] - fromPoint[dir]), maxDistance = abs(obstacle[dir + 'Max'] - fromPoint[dir]), + // If it's a small difference, pick the one leading towards dest + // point. Otherwise pick the shortest distance + useMax = abs(minDistance - maxDistance) < 10 ? + fromPoint[dir] < toPoint[dir] : + maxDistance < minDistance; + // Check if we hit any obstacles trying to go around in either + // direction. + toPointMin[dir] = obstacle[dir + 'Min']; + toPointMax[dir] = obstacle[dir + 'Max']; + minPivot = pivotPoint(fromPoint, toPointMin, dirIsX)[dir] !== + toPointMin[dir]; + maxPivot = pivotPoint(fromPoint, toPointMax, dirIsX)[dir] !== + toPointMax[dir]; + useMax = minPivot ? + (maxPivot ? useMax : true) : + (maxPivot ? false : useMax); + // useMax now contains our preferred choice, bounds not taken into + // account. If both or neither direction is out of bounds we want to + // use this. + // Deal with soft bounds + useMax = minOutOfSoftBounds ? + (maxOutOfSoftBounds ? useMax : true) : // Out on min + (maxOutOfSoftBounds ? false : useMax); // Not out on min + // Deal with hard bounds + useMax = minOutOfHardBounds ? + (maxOutOfHardBounds ? useMax : true) : // Out on min + (maxOutOfHardBounds ? false : useMax); // Not out on min + return useMax; + } + // eslint-disable-next-line valid-jsdoc + /** + * Find a clear path between point. + * @private + */ + function clearPathTo(fromPoint, toPoint, dirIsX) { + // Don't waste time if we've hit goal + if (fromPoint.x === toPoint.x && fromPoint.y === toPoint.y) { + return []; + } + var dir = dirIsX ? 'x' : 'y', pivot, segments, waypoint, waypointUseMax, envelopingObstacle, secondEnvelopingObstacle, envelopWaypoint, obstacleMargin = options.obstacleOptions.margin, bounds = { + soft: { + xMin: softMinX, + xMax: softMaxX, + yMin: softMinY, + yMax: softMaxY + }, + hard: options.hardBounds + }; + // If fromPoint is inside an obstacle we have a problem. Break out + // by just going to the outside of this obstacle. We prefer to go to + // the nearest edge in the chosen direction. + envelopingObstacle = + findObstacleFromPoint(chartObstacles, fromPoint); + if (envelopingObstacle > -1) { + envelopingObstacle = chartObstacles[envelopingObstacle]; + waypointUseMax = getDodgeDirection(envelopingObstacle, fromPoint, toPoint, dirIsX, bounds); + // Cut obstacle to hard bounds to make sure we stay within + limitObstacleToBounds(envelopingObstacle, options.hardBounds); + envelopWaypoint = dirIsX ? { + y: fromPoint.y, + x: envelopingObstacle[waypointUseMax ? 'xMax' : 'xMin'] + + (waypointUseMax ? 1 : -1) + } : { + x: fromPoint.x, + y: envelopingObstacle[waypointUseMax ? 'yMax' : 'yMin'] + + (waypointUseMax ? 1 : -1) + }; + // If we crashed into another obstacle doing this, we put the + // waypoint between them instead + secondEnvelopingObstacle = findObstacleFromPoint(chartObstacles, envelopWaypoint); + if (secondEnvelopingObstacle > -1) { + secondEnvelopingObstacle = chartObstacles[secondEnvelopingObstacle]; + // Cut obstacle to hard bounds + limitObstacleToBounds(secondEnvelopingObstacle, options.hardBounds); + // Modify waypoint to lay between obstacles + envelopWaypoint[dir] = waypointUseMax ? max(envelopingObstacle[dir + 'Max'] - obstacleMargin + 1, (secondEnvelopingObstacle[dir + 'Min'] + + envelopingObstacle[dir + 'Max']) / 2) : + min((envelopingObstacle[dir + 'Min'] + obstacleMargin - 1), ((secondEnvelopingObstacle[dir + 'Max'] + + envelopingObstacle[dir + 'Min']) / 2)); + // We are not going anywhere. If this happens for the first + // time, do nothing. Otherwise, try to go to the extreme of + // the obstacle pair in the current direction. + if (fromPoint.x === envelopWaypoint.x && + fromPoint.y === envelopWaypoint.y) { + if (forceObstacleBreak) { + envelopWaypoint[dir] = waypointUseMax ? + max(envelopingObstacle[dir + 'Max'], secondEnvelopingObstacle[dir + 'Max']) + 1 : + min(envelopingObstacle[dir + 'Min'], secondEnvelopingObstacle[dir + 'Min']) - 1; + } + // Toggle on if off, and the opposite + forceObstacleBreak = !forceObstacleBreak; + } + else { + // This point is not identical to previous. + // Clear break trigger. + forceObstacleBreak = false; + } + } + segments = [{ + start: fromPoint, + end: envelopWaypoint + }]; + } + else { // If not enveloping, use standard pivot calculation + pivot = pivotPoint(fromPoint, { + x: dirIsX ? toPoint.x : fromPoint.x, + y: dirIsX ? fromPoint.y : toPoint.y + }, dirIsX); + segments = [{ + start: fromPoint, + end: { + x: pivot.x, + y: pivot.y + } + }]; + // Pivot before goal, use a waypoint to dodge obstacle + if (pivot[dirIsX ? 'x' : 'y'] !== toPoint[dirIsX ? 'x' : 'y']) { + // Find direction of waypoint + waypointUseMax = getDodgeDirection(pivot.obstacle, pivot, toPoint, !dirIsX, bounds); + // Cut waypoint to hard bounds + limitObstacleToBounds(pivot.obstacle, options.hardBounds); + waypoint = { + x: dirIsX ? + pivot.x : + pivot.obstacle[waypointUseMax ? 'xMax' : 'xMin'] + + (waypointUseMax ? 1 : -1), + y: dirIsX ? + pivot.obstacle[waypointUseMax ? 'yMax' : 'yMin'] + + (waypointUseMax ? 1 : -1) : + pivot.y + }; + // We're changing direction here, store that to make sure we + // also change direction when adding the last segment array + // after handling waypoint. + dirIsX = !dirIsX; + segments = segments.concat(clearPathTo({ + x: pivot.x, + y: pivot.y + }, waypoint, dirIsX)); + } + } + // Get segments for the other direction too + // Recursion is our friend + segments = segments.concat(clearPathTo(segments[segments.length - 1].end, toPoint, !dirIsX)); + return segments; + } + // eslint-disable-next-line valid-jsdoc + /** + * Extract point to outside of obstacle in whichever direction is + * closest. Returns new point outside obstacle. + * @private + */ + function extractFromObstacle(obstacle, point, goalPoint) { + var dirIsX = min(obstacle.xMax - point.x, point.x - obstacle.xMin) < + min(obstacle.yMax - point.y, point.y - obstacle.yMin), bounds = { + soft: options.hardBounds, + hard: options.hardBounds + }, useMax = getDodgeDirection(obstacle, point, goalPoint, dirIsX, bounds); + return dirIsX ? { + y: point.y, + x: obstacle[useMax ? 'xMax' : 'xMin'] + (useMax ? 1 : -1) + } : { + x: point.x, + y: obstacle[useMax ? 'yMax' : 'yMin'] + (useMax ? 1 : -1) + }; + } + // Cut the obstacle array to soft bounds for optimization in large + // datasets. + chartObstacles = + chartObstacles.slice(startObstacleIx, endObstacleIx + 1); + // If an obstacle envelops the end point, move it out of there and add + // a little segment to where it was. + if ((endObstacleIx = findObstacleFromPoint(chartObstacles, end)) > -1) { + extractedEndPoint = extractFromObstacle(chartObstacles[endObstacleIx], end, start); + endSegments.push({ + end: end, + start: extractedEndPoint + }); + end = extractedEndPoint; + } + // If it's still inside one or more obstacles, get out of there by + // force-moving towards the start point. + while ((endObstacleIx = findObstacleFromPoint(chartObstacles, end)) > -1) { + useMax = end[dir] - start[dir] < 0; + extractedEndPoint = { + x: end.x, + y: end.y + }; + extractedEndPoint[dir] = chartObstacles[endObstacleIx][useMax ? dir + 'Max' : dir + 'Min'] + (useMax ? 1 : -1); + endSegments.push({ + end: end, + start: extractedEndPoint + }); + end = extractedEndPoint; + } + // Find the path + segments = clearPathTo(start, end, dirIsX); + // Add the end-point segments + segments = segments.concat(endSegments.reverse()); + return { + path: pathFromSegments(segments), + obstacles: segments + }; + }, { + requiresObstacles: true + }) +}; +export default algorithms; diff --git a/librerias/gantt/code/es-modules/parts-gantt/Tree.js b/librerias/gantt/code/es-modules/parts-gantt/Tree.js new file mode 100644 index 0000000..625f102 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-gantt/Tree.js @@ -0,0 +1,110 @@ +/* * + * + * (c) 2016-2020 Highsoft AS + * + * Authors: Jon Arild Nygard + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +/* eslint no-console: 0 */ +'use strict'; +import U from '../parts/Utilities.js'; +var extend = U.extend, isNumber = U.isNumber, pick = U.pick; +/** + * Creates an object map from parent id to childrens index. + * + * @private + * @function Highcharts.Tree#getListOfParents + * + * @param {Array<*>} data + * List of points set in options. `Array.parent` is parent id of point. + * + * @param {Array} ids + * List of all point ids. + * + * @return {Highcharts.Dictionary>} + * Map from parent id to children index in data + */ +var getListOfParents = function (data, ids) { + var listOfParents = data.reduce(function (prev, curr) { + var parent = pick(curr.parent, ''); + if (typeof prev[parent] === 'undefined') { + prev[parent] = []; + } + prev[parent].push(curr); + return prev; + }, {}), parents = Object.keys(listOfParents); + // If parent does not exist, hoist parent to root of tree. + parents.forEach(function (parent, list) { + var children = listOfParents[parent]; + if ((parent !== '') && (ids.indexOf(parent) === -1)) { + children.forEach(function (child) { + list[''].push(child); + }); + delete list[parent]; + } + }); + return listOfParents; +}; +var getNode = function (id, parent, level, data, mapOfIdToChildren, options) { + var descendants = 0, height = 0, after = options && options.after, before = options && options.before, node = { + data: data, + depth: level - 1, + id: id, + level: level, + parent: parent + }, start, end, children; + // Allow custom logic before the children has been created. + if (typeof before === 'function') { + before(node, options); + } + // Call getNode recursively on the children. Calulate the height of the + // node, and the number of descendants. + children = ((mapOfIdToChildren[id] || [])).map(function (child) { + var node = getNode(child.id, id, (level + 1), child, mapOfIdToChildren, options), childStart = child.start, childEnd = (child.milestone === true ? + childStart : + child.end); + // Start should be the lowest child.start. + start = ((!isNumber(start) || childStart < start) ? + childStart : + start); + // End should be the largest child.end. + // If child is milestone, then use start as end. + end = ((!isNumber(end) || childEnd > end) ? + childEnd : + end); + descendants = descendants + 1 + node.descendants; + height = Math.max(node.height + 1, height); + return node; + }); + // Calculate start and end for point if it is not already explicitly set. + if (data) { + data.start = pick(data.start, start); + data.end = pick(data.end, end); + } + extend(node, { + children: children, + descendants: descendants, + height: height + }); + // Allow custom logic after the children has been created. + if (typeof after === 'function') { + after(node, options); + } + return node; +}; +var getTree = function (data, options) { + var ids = data.map(function (d) { + return d.id; + }), mapOfIdToChildren = getListOfParents(data, ids); + return getNode('', null, 1, null, mapOfIdToChildren, options); +}; +var Tree = { + getListOfParents: getListOfParents, + getNode: getNode, + getTree: getTree +}; +export default Tree; diff --git a/librerias/gantt/code/es-modules/parts-gantt/TreeGridAxis.js b/librerias/gantt/code/es-modules/parts-gantt/TreeGridAxis.js new file mode 100644 index 0000000..03adc91 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-gantt/TreeGridAxis.js @@ -0,0 +1,656 @@ +/* * + * + * (c) 2016 Highsoft AS + * Authors: Jon Arild Nygard + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Axis from '../parts/Axis.js'; +import Tick from '../parts/Tick.js'; +import Tree from './Tree.js'; +import TreeGridTick from './TreeGridTick.js'; +import TreeSeriesMixin from '../mixins/tree-series.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, find = U.find, fireEvent = U.fireEvent, isNumber = U.isNumber, isObject = U.isObject, isString = U.isString, merge = U.merge, pick = U.pick, wrap = U.wrap; +import './GridAxis.js'; +import '../modules/broken-axis.src.js'; +/** + * @private + */ +var TreeGridAxis; +(function (TreeGridAxis) { + /* * + * + * Interfaces + * + * */ + /* * + * + * Variables + * + * */ + var applied = false; + /* * + * + * Functions + * + * */ + /** + * @private + */ + function compose(AxisClass) { + if (!applied) { + wrap(AxisClass.prototype, 'generateTick', wrapGenerateTick); + wrap(AxisClass.prototype, 'getMaxLabelDimensions', wrapGetMaxLabelDimensions); + wrap(AxisClass.prototype, 'init', wrapInit); + wrap(AxisClass.prototype, 'setTickInterval', wrapSetTickInterval); + TreeGridTick.compose(Tick); + applied = true; + } + } + TreeGridAxis.compose = compose; + /** + * @private + */ + function getBreakFromNode(node, max) { + var from = node.collapseStart || 0, to = node.collapseEnd || 0; + // In broken-axis, the axis.max is minimized until it is not within a + // break. Therefore, if break.to is larger than axis.max, the axis.to + // should not add the 0.5 axis.tickMarkOffset, to avoid adding a break + // larger than axis.max. + // TODO consider simplifying broken-axis and this might solve itself + if (to >= max) { + from -= 0.5; + } + return { + from: from, + to: to, + showPoints: false + }; + } + /** + * Creates a tree structure of the data, and the treegrid. Calculates + * categories, and y-values of points based on the tree. + * + * @private + * @function getTreeGridFromData + * + * @param {Array} data + * All the data points to display in the axis. + * + * @param {boolean} uniqueNames + * Wether or not the data node with the same name should share grid cell. If + * true they do share cell. False by default. + * + * @param {number} numberOfSeries + * + * @return {object} + * Returns an object containing categories, mapOfIdToNode, + * mapOfPosToGridNode, and tree. + * + * @todo There should be only one point per line. + * @todo It should be optional to have one category per point, or merge + * cells + * @todo Add unit-tests. + */ + function getTreeGridFromData(data, uniqueNames, numberOfSeries) { + var categories = [], collapsedNodes = [], mapOfIdToNode = {}, mapOfPosToGridNode = {}, posIterator = -1, uniqueNamesEnabled = typeof uniqueNames === 'boolean' ? uniqueNames : false, tree; + // Build the tree from the series data. + var treeParams = { + // After the children has been created. + after: function (node) { + var gridNode = mapOfPosToGridNode[node.pos], height = 0, descendants = 0; + gridNode.children.forEach(function (child) { + descendants += (child.descendants || 0) + 1; + height = Math.max((child.height || 0) + 1, height); + }); + gridNode.descendants = descendants; + gridNode.height = height; + if (gridNode.collapsed) { + collapsedNodes.push(gridNode); + } + }, + // Before the children has been created. + before: function (node) { + var data = isObject(node.data, true) ? node.data : {}, name = isString(data.name) ? data.name : '', parentNode = mapOfIdToNode[node.parent], parentGridNode = (isObject(parentNode, true) ? + mapOfPosToGridNode[parentNode.pos] : + null), hasSameName = function (x) { + return x.name === name; + }, gridNode, pos; + // If not unique names, look for sibling node with the same name + if (uniqueNamesEnabled && + isObject(parentGridNode, true) && + !!(gridNode = find(parentGridNode.children, hasSameName))) { + // If there is a gridNode with the same name, reuse position + pos = gridNode.pos; + // Add data node to list of nodes in the grid node. + gridNode.nodes.push(node); + } + else { + // If it is a new grid node, increment position. + pos = posIterator++; + } + // Add new grid node to map. + if (!mapOfPosToGridNode[pos]) { + mapOfPosToGridNode[pos] = gridNode = { + depth: parentGridNode ? parentGridNode.depth + 1 : 0, + name: name, + nodes: [node], + children: [], + pos: pos + }; + // If not root, then add name to categories. + if (pos !== -1) { + categories.push(name); + } + // Add name to list of children. + if (isObject(parentGridNode, true)) { + parentGridNode.children.push(gridNode); + } + } + // Add data node to map + if (isString(node.id)) { + mapOfIdToNode[node.id] = node; + } + // If one of the points are collapsed, then start the grid node + // in collapsed state. + if (gridNode && + data.collapsed === true) { + gridNode.collapsed = true; + } + // Assign pos to data node + node.pos = pos; + } + }; + var updateYValuesAndTickPos = function (map, numberOfSeries) { + var setValues = function (gridNode, start, result) { + var nodes = gridNode.nodes, end = start + (start === -1 ? 0 : numberOfSeries - 1), diff = (end - start) / 2, padding = 0.5, pos = start + diff; + nodes.forEach(function (node) { + var data = node.data; + if (isObject(data, true)) { + // Update point + data.y = start + (data.seriesIndex || 0); + // Remove the property once used + delete data.seriesIndex; + } + node.pos = pos; + }); + result[pos] = gridNode; + gridNode.pos = pos; + gridNode.tickmarkOffset = diff + padding; + gridNode.collapseStart = end + padding; + gridNode.children.forEach(function (child) { + setValues(child, end + 1, result); + end = (child.collapseEnd || 0) - padding; + }); + // Set collapseEnd to the end of the last child node. + gridNode.collapseEnd = end + padding; + return result; + }; + return setValues(map['-1'], -1, {}); + }; + // Create tree from data + tree = Tree.getTree(data, treeParams); + // Update y values of data, and set calculate tick positions. + mapOfPosToGridNode = updateYValuesAndTickPos(mapOfPosToGridNode, numberOfSeries); + // Return the resulting data. + return { + categories: categories, + mapOfIdToNode: mapOfIdToNode, + mapOfPosToGridNode: mapOfPosToGridNode, + collapsedNodes: collapsedNodes, + tree: tree + }; + } + /** + * Builds the tree of categories and calculates its positions. + * @private + * @param {object} e Event object + * @param {object} e.target The chart instance which the event was fired on. + * @param {object[]} e.target.axes The axes of the chart. + */ + function onBeforeRender(e) { + var chart = e.target, axes = chart.axes; + axes.filter(function (axis) { + return axis.options.type === 'treegrid'; + }).forEach(function (axis) { + var options = axis.options || {}, labelOptions = options.labels, uniqueNames = options.uniqueNames, numberOfSeries = 0, isDirty, data, treeGrid; + // Check whether any of series is rendering for the first time, + // visibility has changed, or its data is dirty, + // and only then update. #10570, #10580 + // Also check if mapOfPosToGridNode exists. #10887 + isDirty = (!axis.treeGrid.mapOfPosToGridNode || + axis.series.some(function (series) { + return !series.hasRendered || + series.isDirtyData || + series.isDirty; + })); + if (isDirty) { + // Concatenate data from all series assigned to this axis. + data = axis.series.reduce(function (arr, s) { + if (s.visible) { + // Push all data to array + (s.options.data || []).forEach(function (data) { + if (isObject(data, true)) { + // Set series index on data. Removed again + // after use. + data.seriesIndex = numberOfSeries; + arr.push(data); + } + }); + // Increment series index + if (uniqueNames === true) { + numberOfSeries++; + } + } + return arr; + }, []); + // setScale is fired after all the series is initialized, + // which is an ideal time to update the axis.categories. + treeGrid = getTreeGridFromData(data, uniqueNames || false, (uniqueNames === true) ? numberOfSeries : 1); + // Assign values to the axis. + axis.categories = treeGrid.categories; + axis.treeGrid.mapOfPosToGridNode = treeGrid.mapOfPosToGridNode; + axis.hasNames = true; + axis.treeGrid.tree = treeGrid.tree; + // Update yData now that we have calculated the y values + axis.series.forEach(function (series) { + var data = (series.options.data || []).map(function (d) { + return isObject(d, true) ? merge(d) : d; + }); + // Avoid destroying points when series is not visible + if (series.visible) { + series.setData(data, false); + } + }); + // Calculate the label options for each level in the tree. + axis.treeGrid.mapOptionsToLevel = + TreeSeriesMixin.getLevelOptions({ + defaults: labelOptions, + from: 1, + levels: labelOptions && labelOptions.levels, + to: axis.treeGrid.tree && axis.treeGrid.tree.height + }); + // Setting initial collapsed nodes + if (e.type === 'beforeRender') { + axis.treeGrid.collapsedNodes = treeGrid.collapsedNodes; + } + } + }); + } + /** + * Generates a tick for initial positioning. + * + * @private + * @function Highcharts.GridAxis#generateTick + * + * @param {Function} proceed + * The original generateTick function. + * + * @param {number} pos + * The tick position in axis values. + */ + function wrapGenerateTick(proceed, pos) { + var axis = this, mapOptionsToLevel = axis.treeGrid.mapOptionsToLevel || {}, isTreeGrid = axis.options.type === 'treegrid', ticks = axis.ticks; + var tick = ticks[pos], levelOptions, options, gridNode; + if (isTreeGrid && + axis.treeGrid.mapOfPosToGridNode) { + gridNode = axis.treeGrid.mapOfPosToGridNode[pos]; + levelOptions = mapOptionsToLevel[gridNode.depth]; + if (levelOptions) { + options = { + labels: levelOptions + }; + } + if (!tick) { + ticks[pos] = tick = + new Tick(axis, pos, void 0, void 0, { + category: gridNode.name, + tickmarkOffset: gridNode.tickmarkOffset, + options: options + }); + } + else { + // update labels depending on tick interval + tick.parameters.category = gridNode.name; + tick.options = options; + tick.addLabel(); + } + } + else { + proceed.apply(axis, Array.prototype.slice.call(arguments, 1)); + } + } + /** + * Override to add indentation to axis.maxLabelDimensions. + * + * @private + * @function Highcharts.GridAxis#getMaxLabelDimensions + * + * @param {Function} proceed + * The original function + */ + function wrapGetMaxLabelDimensions(proceed) { + var axis = this, options = axis.options, labelOptions = options && options.labels, indentation = (labelOptions && isNumber(labelOptions.indentation) ? + labelOptions.indentation : + 0), retVal = proceed.apply(axis, Array.prototype.slice.call(arguments, 1)), isTreeGrid = axis.options.type === 'treegrid'; + var treeDepth; + if (isTreeGrid && axis.treeGrid.mapOfPosToGridNode) { + treeDepth = axis.treeGrid.mapOfPosToGridNode[-1].height || 0; + retVal.width += indentation * (treeDepth - 1); + } + return retVal; + } + /** + * @private + */ + function wrapInit(proceed, chart, userOptions) { + var axis = this, isTreeGrid = userOptions.type === 'treegrid'; + if (!axis.treeGrid) { + axis.treeGrid = new Additions(axis); + } + // Set default and forced options for TreeGrid + if (isTreeGrid) { + // Add event for updating the categories of a treegrid. + // NOTE Preferably these events should be set on the axis. + addEvent(chart, 'beforeRender', onBeforeRender); + addEvent(chart, 'beforeRedraw', onBeforeRender); + // Add new collapsed nodes on addseries + addEvent(chart, 'addSeries', function (e) { + if (e.options.data) { + var treeGrid = getTreeGridFromData(e.options.data, userOptions.uniqueNames || false, 1); + axis.treeGrid.collapsedNodes = (axis.treeGrid.collapsedNodes || []).concat(treeGrid.collapsedNodes); + } + }); + // Collapse all nodes in axis.treegrid.collapsednodes + // where collapsed equals true. + addEvent(axis, 'foundExtremes', function () { + if (axis.treeGrid.collapsedNodes) { + axis.treeGrid.collapsedNodes.forEach(function (node) { + var breaks = axis.treeGrid.collapse(node); + if (axis.brokenAxis) { + axis.brokenAxis.setBreaks(breaks, false); + // remove the node from the axis collapsedNodes + if (axis.treeGrid.collapsedNodes) { + axis.treeGrid.collapsedNodes = axis.treeGrid.collapsedNodes.filter(function (n) { + return node.collapseStart !== n.collapseStart || + node.collapseEnd !== n.collapseEnd; + }); + } + } + }); + } + }); + userOptions = merge({ + // Default options + grid: { + enabled: true + }, + // TODO: add support for align in treegrid. + labels: { + align: 'left', + /** + * Set options on specific levels in a tree grid axis. Takes + * precedence over labels options. + * + * @sample {gantt} gantt/treegrid-axis/labels-levels + * Levels on TreeGrid Labels + * + * @type {Array<*>} + * @product gantt + * @apioption yAxis.labels.levels + * + * @private + */ + levels: [{ + /** + * Specify the level which the options within this object + * applies to. + * + * @type {number} + * @product gantt + * @apioption yAxis.labels.levels.level + * + * @private + */ + level: void 0 + }, { + level: 1, + /** + * @type {Highcharts.CSSObject} + * @product gantt + * @apioption yAxis.labels.levels.style + * + * @private + */ + style: { + /** @ignore-option */ + fontWeight: 'bold' + } + }], + /** + * The symbol for the collapse and expand icon in a + * treegrid. + * + * @product gantt + * @optionparent yAxis.labels.symbol + * + * @private + */ + symbol: { + /** + * The symbol type. Points to a definition function in + * the `Highcharts.Renderer.symbols` collection. + * + * @type {Highcharts.SymbolKeyValue} + * + * @private + */ + type: 'triangle', + x: -5, + y: -5, + height: 10, + width: 10, + padding: 5 + } + }, + uniqueNames: false + }, userOptions, { + // Forced options + reversed: true, + // grid.columns is not supported in treegrid + grid: { + columns: void 0 + } + }); + } + // Now apply the original function with the original arguments, + // which are sliced off this function's arguments + proceed.apply(axis, [chart, userOptions]); + if (isTreeGrid) { + axis.hasNames = true; + axis.options.showLastLabel = true; + } + } + /** + * Set the tick positions, tickInterval, axis min and max. + * + * @private + * @function Highcharts.GridAxis#setTickInterval + * + * @param {Function} proceed + * The original setTickInterval function. + */ + function wrapSetTickInterval(proceed) { + var axis = this, options = axis.options, isTreeGrid = options.type === 'treegrid'; + if (isTreeGrid) { + axis.min = pick(axis.userMin, options.min, axis.dataMin); + axis.max = pick(axis.userMax, options.max, axis.dataMax); + fireEvent(axis, 'foundExtremes'); + // setAxisTranslation modifies the min and max according to + // axis breaks. + axis.setAxisTranslation(true); + axis.tickmarkOffset = 0.5; + axis.tickInterval = 1; + axis.tickPositions = axis.treeGrid.mapOfPosToGridNode ? + axis.treeGrid.getTickPositions() : + []; + } + else { + proceed.apply(axis, Array.prototype.slice.call(arguments, 1)); + } + } + /* * + * + * Classes + * + * */ + /** + * @private + * @class + */ + var Additions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + /** + * @private + */ + function Additions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Calculates the new axis breaks to collapse a node. + * + * @private + * + * @param {Highcharts.Axis} axis + * The axis to check against. + * + * @param {Highcharts.GridNode} node + * The node to collapse. + * + * @param {number} pos + * The tick position to collapse. + * + * @return {Array} + * Returns an array of the new breaks for the axis. + */ + Additions.prototype.collapse = function (node) { + var axis = this.axis, breaks = (axis.options.breaks || []), obj = getBreakFromNode(node, axis.max); + breaks.push(obj); + return breaks; + }; + /** + * Calculates the new axis breaks to expand a node. + * + * @private + * + * @param {Highcharts.Axis} axis + * The axis to check against. + * + * @param {Highcharts.GridNode} node + * The node to expand. + * + * @param {number} pos + * The tick position to expand. + * + * @return {Array} + * Returns an array of the new breaks for the axis. + */ + Additions.prototype.expand = function (node) { + var axis = this.axis, breaks = (axis.options.breaks || []), obj = getBreakFromNode(node, axis.max); + // Remove the break from the axis breaks array. + return breaks.reduce(function (arr, b) { + if (b.to !== obj.to || b.from !== obj.from) { + arr.push(b); + } + return arr; + }, []); + }; + /** + * Creates a list of positions for the ticks on the axis. Filters out + * positions that are outside min and max, or is inside an axis break. + * + * @private + * + * @return {Array} + * List of positions. + */ + Additions.prototype.getTickPositions = function () { + var axis = this.axis; + return Object.keys(axis.treeGrid.mapOfPosToGridNode || {}).reduce(function (arr, key) { + var pos = +key; + if (axis.min <= pos && + axis.max >= pos && + !(axis.brokenAxis && axis.brokenAxis.isInAnyBreak(pos))) { + arr.push(pos); + } + return arr; + }, []); + }; + /** + * Check if a node is collapsed. + * + * @private + * + * @param {Highcharts.Axis} axis + * The axis to check against. + * + * @param {object} node + * The node to check if is collapsed. + * + * @param {number} pos + * The tick position to collapse. + * + * @return {boolean} + * Returns true if collapsed, false if expanded. + */ + Additions.prototype.isCollapsed = function (node) { + var axis = this.axis, breaks = (axis.options.breaks || []), obj = getBreakFromNode(node, axis.max); + return breaks.some(function (b) { + return b.from === obj.from && b.to === obj.to; + }); + }; + /** + * Calculates the new axis breaks after toggling the collapse/expand + * state of a node. If it is collapsed it will be expanded, and if it is + * exapended it will be collapsed. + * + * @private + * + * @param {Highcharts.Axis} axis + * The axis to check against. + * + * @param {Highcharts.GridNode} node + * The node to toggle. + * + * @return {Array} + * Returns an array of the new breaks for the axis. + */ + Additions.prototype.toggleCollapse = function (node) { + return (this.isCollapsed(node) ? + this.expand(node) : + this.collapse(node)); + }; + return Additions; + }()); + TreeGridAxis.Additions = Additions; +})(TreeGridAxis || (TreeGridAxis = {})); +// Make utility functions available for testing. +Axis.prototype.utils = { + getNode: Tree.getNode +}; +TreeGridAxis.compose(Axis); +export default TreeGridAxis; diff --git a/librerias/gantt/code/es-modules/parts-gantt/TreeGridTick.js b/librerias/gantt/code/es-modules/parts-gantt/TreeGridTick.js new file mode 100644 index 0000000..9799ca9 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-gantt/TreeGridTick.js @@ -0,0 +1,305 @@ +/* * + * + * (c) 2016 Highsoft AS + * Authors: Jon Arild Nygard + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, defined = U.defined, isObject = U.isObject, isNumber = U.isNumber, pick = U.pick, wrap = U.wrap; +/** + * @private + */ +var TreeGridTick; +(function (TreeGridTick) { + /* * + * + * Interfaces + * + * */ + /* * + * + * Variables + * + * */ + var applied = false; + /* * + * + * Functions + * + * */ + /** + * @private + */ + function compose(TickClass) { + if (!applied) { + addEvent(TickClass, 'init', onInit); + wrap(TickClass.prototype, 'getLabelPosition', wrapGetLabelPosition); + wrap(TickClass.prototype, 'renderLabel', wrapRenderLabel); + // backwards compatibility + TickClass.prototype.collapse = function (redraw) { + this.treeGrid.collapse(redraw); + }; + TickClass.prototype.expand = function (redraw) { + this.treeGrid.expand(redraw); + }; + TickClass.prototype.toggleCollapse = function (redraw) { + this.treeGrid.toggleCollapse(redraw); + }; + applied = true; + } + } + TreeGridTick.compose = compose; + /** + * @private + */ + function onInit() { + var tick = this; + if (!tick.treeGrid) { + tick.treeGrid = new Additions(tick); + } + } + /** + * @private + */ + function onTickHover(label) { + label.addClass('highcharts-treegrid-node-active'); + if (!label.renderer.styledMode) { + label.css({ + textDecoration: 'underline' + }); + } + } + /** + * @private + */ + function onTickHoverExit(label, options) { + var css = defined(options.style) ? options.style : {}; + label.removeClass('highcharts-treegrid-node-active'); + if (!label.renderer.styledMode) { + label.css({ textDecoration: css.textDecoration }); + } + } + /** + * @private + */ + function renderLabelIcon(tick, params) { + var treeGrid = tick.treeGrid, isNew = !treeGrid.labelIcon, renderer = params.renderer, labelBox = params.xy, options = params.options, width = options.width, height = options.height, iconCenter = { + x: labelBox.x - (width / 2) - options.padding, + y: labelBox.y - (height / 2) + }, rotation = params.collapsed ? 90 : 180, shouldRender = params.show && isNumber(iconCenter.y); + var icon = treeGrid.labelIcon; + if (!icon) { + treeGrid.labelIcon = icon = renderer + .path(renderer.symbols[options.type](options.x, options.y, width, height)) + .addClass('highcharts-label-icon') + .add(params.group); + } + // Set the new position, and show or hide + if (!shouldRender) { + icon.attr({ y: -9999 }); // #1338 + } + // Presentational attributes + if (!renderer.styledMode) { + icon + .attr({ + 'stroke-width': 1, + 'fill': pick(params.color, '#666666') + }) + .css({ + cursor: 'pointer', + stroke: options.lineColor, + strokeWidth: options.lineWidth + }); + } + // Update the icon positions + icon[isNew ? 'attr' : 'animate']({ + translateX: iconCenter.x, + translateY: iconCenter.y, + rotation: rotation + }); + } + /** + * @private + */ + function wrapGetLabelPosition(proceed, x, y, label, horiz, labelOptions, tickmarkOffset, index, step) { + var tick = this, lbOptions = pick(tick.options && tick.options.labels, labelOptions), pos = tick.pos, axis = tick.axis, options = axis.options, isTreeGrid = options.type === 'treegrid', result = proceed.apply(tick, [x, y, label, horiz, lbOptions, tickmarkOffset, index, step]); + var symbolOptions, indentation, mapOfPosToGridNode, node, level; + if (isTreeGrid) { + symbolOptions = (lbOptions && isObject(lbOptions.symbol, true) ? + lbOptions.symbol : + {}); + indentation = (lbOptions && isNumber(lbOptions.indentation) ? + lbOptions.indentation : + 0); + mapOfPosToGridNode = axis.treeGrid.mapOfPosToGridNode; + node = mapOfPosToGridNode && mapOfPosToGridNode[pos]; + level = (node && node.depth) || 1; + result.x += ( + // Add space for symbols + ((symbolOptions.width) + (symbolOptions.padding * 2)) + + // Apply indentation + ((level - 1) * indentation)); + } + return result; + } + /** + * @private + */ + function wrapRenderLabel(proceed) { + var tick = this, pos = tick.pos, axis = tick.axis, label = tick.label, mapOfPosToGridNode = axis.treeGrid.mapOfPosToGridNode, options = axis.options, labelOptions = pick(tick.options && tick.options.labels, options && options.labels), symbolOptions = (labelOptions && isObject(labelOptions.symbol, true) ? + labelOptions.symbol : + {}), node = mapOfPosToGridNode && mapOfPosToGridNode[pos], level = node && node.depth, isTreeGrid = options.type === 'treegrid', shouldRender = axis.tickPositions.indexOf(pos) > -1, prefixClassName = 'highcharts-treegrid-node-', styledMode = axis.chart.styledMode; + var collapsed, addClassName, removeClassName; + if (isTreeGrid && node) { + // Add class name for hierarchical styling. + if (label && + label.element) { + label.addClass(prefixClassName + 'level-' + level); + } + } + proceed.apply(tick, Array.prototype.slice.call(arguments, 1)); + if (isTreeGrid && + label && + label.element && + node && + node.descendants && + node.descendants > 0) { + collapsed = axis.treeGrid.isCollapsed(node); + renderLabelIcon(tick, { + color: !styledMode && label.styles && label.styles.color || '', + collapsed: collapsed, + group: label.parentGroup, + options: symbolOptions, + renderer: label.renderer, + show: shouldRender, + xy: label.xy + }); + // Add class name for the node. + addClassName = prefixClassName + + (collapsed ? 'collapsed' : 'expanded'); + removeClassName = prefixClassName + + (collapsed ? 'expanded' : 'collapsed'); + label + .addClass(addClassName) + .removeClass(removeClassName); + if (!styledMode) { + label.css({ + cursor: 'pointer' + }); + } + // Add events to both label text and icon + [label, tick.treeGrid.labelIcon].forEach(function (object) { + if (object && !object.attachedTreeGridEvents) { + // On hover + addEvent(object.element, 'mouseover', function () { + onTickHover(label); + }); + // On hover out + addEvent(object.element, 'mouseout', function () { + onTickHoverExit(label, labelOptions); + }); + addEvent(object.element, 'click', function () { + tick.treeGrid.toggleCollapse(); + }); + object.attachedTreeGridEvents = true; + } + }); + } + } + /* * + * + * Classes + * + * */ + /** + * @private + * @class + */ + var Additions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + /** + * @private + */ + function Additions(tick) { + this.tick = tick; + } + /* * + * + * Functions + * + * */ + /** + * Collapse the grid cell. Used when axis is of type treegrid. + * + * @see gantt/treegrid-axis/collapsed-dynamically/demo.js + * + * @private + * @function Highcharts.Tick#collapse + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call to + * {@link Highcharts.Chart#redraw} + */ + Additions.prototype.collapse = function (redraw) { + var tick = this.tick, axis = tick.axis, brokenAxis = axis.brokenAxis; + if (brokenAxis && + axis.treeGrid.mapOfPosToGridNode) { + var pos = tick.pos, node = axis.treeGrid.mapOfPosToGridNode[pos], breaks = axis.treeGrid.collapse(node); + brokenAxis.setBreaks(breaks, pick(redraw, true)); + } + }; + /** + * Expand the grid cell. Used when axis is of type treegrid. + * + * @see gantt/treegrid-axis/collapsed-dynamically/demo.js + * + * @private + * @function Highcharts.Tick#expand + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call to + * {@link Highcharts.Chart#redraw} + */ + Additions.prototype.expand = function (redraw) { + var tick = this.tick, axis = tick.axis, brokenAxis = axis.brokenAxis; + if (brokenAxis && + axis.treeGrid.mapOfPosToGridNode) { + var pos = tick.pos, node = axis.treeGrid.mapOfPosToGridNode[pos], breaks = axis.treeGrid.expand(node); + brokenAxis.setBreaks(breaks, pick(redraw, true)); + } + }; + /** + * Toggle the collapse/expand state of the grid cell. Used when axis is + * of type treegrid. + * + * @see gantt/treegrid-axis/collapsed-dynamically/demo.js + * + * @private + * @function Highcharts.Tick#toggleCollapse + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call to + * {@link Highcharts.Chart#redraw} + */ + Additions.prototype.toggleCollapse = function (redraw) { + var tick = this.tick, axis = tick.axis, brokenAxis = axis.brokenAxis; + if (brokenAxis && + axis.treeGrid.mapOfPosToGridNode) { + var pos = tick.pos, node = axis.treeGrid.mapOfPosToGridNode[pos], breaks = axis.treeGrid.toggleCollapse(node); + brokenAxis.setBreaks(breaks, pick(redraw, true)); + } + }; + return Additions; + }()); + TreeGridTick.Additions = Additions; +})(TreeGridTick || (TreeGridTick = {})); +export default TreeGridTick; diff --git a/librerias/gantt/code/es-modules/parts-map/ColorAxis.js b/librerias/gantt/code/es-modules/parts-map/ColorAxis.js new file mode 100644 index 0000000..2223792 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-map/ColorAxis.js @@ -0,0 +1,1169 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +import Axis from '../parts/Axis.js'; +import Color from '../parts/Color.js'; +var color = Color.parse; +import H from '../parts/Globals.js'; +import Legend from '../parts/Legend.js'; +import LegendSymbolMixin from '../mixins/legend-symbol.js'; +import Point from '../parts/Point.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, erase = U.erase, extend = U.extend, Fx = U.Fx, isNumber = U.isNumber, merge = U.merge, pick = U.pick, splat = U.splat; +/** + * Color axis types + * + * @typedef {"linear"|"logarithmic"} Highcharts.ColorAxisTypeValue + */ +''; // detach doclet above +import '../parts/Chart.js'; +import './ColorSeriesMixin.js'; +var Chart = H.Chart, Series = H.Series, colorPointMixin = H.colorPointMixin, colorSeriesMixin = H.colorSeriesMixin, noop = H.noop; +extend(Series.prototype, colorSeriesMixin); +extend(Point.prototype, colorPointMixin); +Chart.prototype.collectionsWithUpdate.push('colorAxis'); +Chart.prototype.collectionsWithInit.colorAxis = [Chart.prototype.addColorAxis]; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * The ColorAxis object for inclusion in gradient legends. + * + * @class + * @name Highcharts.ColorAxis + * @augments Highcharts.Axis + * + * @param {Highcharts.Chart} chart + * The related chart of the color axis. + * + * @param {Highcharts.ColorAxisOptions} userOptions + * The color axis options for initialization. + */ +var ColorAxis = /** @class */ (function (_super) { + __extends(ColorAxis, _super); + /* * + * + * Constructors + * + * */ + /** + * @private + */ + function ColorAxis(chart, userOptions) { + var _this = _super.call(this, chart, userOptions) || this; + _this.beforePadding = false; // Prevents unnecessary padding with `hc-more` + _this.chart = void 0; + _this.coll = 'colorAxis'; + _this.dataClasses = void 0; + _this.legendItem = void 0; + _this.legendItems = void 0; + _this.name = ''; // Prevents 'undefined' in legend in IE8 + _this.options = void 0; + _this.stops = void 0; + _this.visible = true; + _this.init(chart, userOptions); + return _this; + } + /* * + * + * Static Functions + * + * */ + /** + * Build options to keep layout params on init and update. + * @private + */ + ColorAxis.buildOptions = function (chart, options, userOptions) { + var legend = chart.options.legend || {}, horiz = userOptions.layout ? + userOptions.layout !== 'vertical' : + legend.layout !== 'vertical'; + return merge(options, { + side: horiz ? 2 : 1, + reversed: !horiz + }, userOptions, { + opposite: !horiz, + showEmpty: false, + title: null, + visible: legend.enabled && + (userOptions ? userOptions.visible !== false : true) + }); + }; + /* * + * + * Functions + * + * */ + /** + * Initializes the color axis. + * + * @function Highcharts.ColorAxis#init + * + * @param {Highcharts.Chart} chart + * The related chart of the color axis. + * + * @param {Highcharts.ColorAxisOptions} userOptions + * The color axis options for initialization. + */ + ColorAxis.prototype.init = function (chart, userOptions) { + var axis = this; + var options = ColorAxis.buildOptions(// Build the options + chart, ColorAxis.defaultOptions, userOptions); + axis.coll = 'colorAxis'; + _super.prototype.init.call(this, chart, options); + // Base init() pushes it to the xAxis array, now pop it again + // chart[this.isXAxis ? 'xAxis' : 'yAxis'].pop(); + // Prepare data classes + if (userOptions.dataClasses) { + axis.initDataClasses(userOptions); + } + axis.initStops(); + // Override original axis properties + axis.horiz = !options.opposite; + axis.zoomEnabled = false; + }; + /** + * @private + */ + ColorAxis.prototype.initDataClasses = function (userOptions) { + var axis = this; + var chart = axis.chart, dataClasses, colorCounter = 0, colorCount = chart.options.chart.colorCount, options = axis.options, len = userOptions.dataClasses.length; + axis.dataClasses = dataClasses = []; + axis.legendItems = []; + userOptions.dataClasses.forEach(function (dataClass, i) { + var colors; + dataClass = merge(dataClass); + dataClasses.push(dataClass); + if (!chart.styledMode && dataClass.color) { + return; + } + if (options.dataClassColor === 'category') { + if (!chart.styledMode) { + colors = chart.options.colors; + colorCount = colors.length; + dataClass.color = colors[colorCounter]; + } + dataClass.colorIndex = colorCounter; + // increase and loop back to zero + colorCounter++; + if (colorCounter === colorCount) { + colorCounter = 0; + } + } + else { + dataClass.color = color(options.minColor).tweenTo(color(options.maxColor), len < 2 ? 0.5 : i / (len - 1) // #3219 + ); + } + }); + }; + /** + * Returns true if the series has points at all. + * + * @function Highcharts.ColorAxis#hasData + * + * @return {boolean} + * True, if the series has points, otherwise false. + */ + ColorAxis.prototype.hasData = function () { + return !!(this.tickPositions || []).length; + }; + /** + * Override so that ticks are not added in data class axes (#6914) + * @private + */ + ColorAxis.prototype.setTickPositions = function () { + if (!this.dataClasses) { + return _super.prototype.setTickPositions.call(this); + } + }; + /** + * @private + */ + ColorAxis.prototype.initStops = function () { + var axis = this; + axis.stops = axis.options.stops || [ + [0, axis.options.minColor], + [1, axis.options.maxColor] + ]; + axis.stops.forEach(function (stop) { + stop.color = color(stop[1]); + }); + }; + /** + * Extend the setOptions method to process extreme colors and color stops. + * @private + */ + ColorAxis.prototype.setOptions = function (userOptions) { + var axis = this; + _super.prototype.setOptions.call(this, userOptions); + axis.options.crosshair = axis.options.marker; + }; + /** + * @private + */ + ColorAxis.prototype.setAxisSize = function () { + var axis = this; + var symbol = axis.legendSymbol; + var chart = axis.chart; + var legendOptions = chart.options.legend || {}; + var x, y, width, height; + if (symbol) { + this.left = x = symbol.attr('x'); + this.top = y = symbol.attr('y'); + this.width = width = symbol.attr('width'); + this.height = height = symbol.attr('height'); + this.right = chart.chartWidth - x - width; + this.bottom = chart.chartHeight - y - height; + this.len = this.horiz ? width : height; + this.pos = this.horiz ? x : y; + } + else { + // Fake length for disabled legend to avoid tick issues + // and such (#5205) + this.len = (this.horiz ? + legendOptions.symbolWidth : + legendOptions.symbolHeight) || ColorAxis.defaultLegendLength; + } + }; + /** + * @private + */ + ColorAxis.prototype.normalizedValue = function (value) { + var axis = this; + if (axis.logarithmic) { + value = axis.logarithmic.log2lin(value); + } + return 1 - ((axis.max - value) / + ((axis.max - axis.min) || 1)); + }; + /** + * Translate from a value to a color. + * @private + */ + ColorAxis.prototype.toColor = function (value, point) { + var axis = this; + var dataClasses = axis.dataClasses; + var stops = axis.stops; + var pos, from, to, color, dataClass, i; + if (dataClasses) { + i = dataClasses.length; + while (i--) { + dataClass = dataClasses[i]; + from = dataClass.from; + to = dataClass.to; + if ((typeof from === 'undefined' || value >= from) && + (typeof to === 'undefined' || value <= to)) { + color = dataClass.color; + if (point) { + point.dataClass = i; + point.colorIndex = dataClass.colorIndex; + } + break; + } + } + } + else { + pos = axis.normalizedValue(value); + i = stops.length; + while (i--) { + if (pos > stops[i][0]) { + break; + } + } + from = stops[i] || stops[i + 1]; + to = stops[i + 1] || from; + // The position within the gradient + pos = 1 - (to[0] - pos) / ((to[0] - from[0]) || 1); + color = from.color.tweenTo(to.color, pos); + } + return color; + }; + /** + * Override the getOffset method to add the whole axis groups inside the + * legend. + * @private + */ + ColorAxis.prototype.getOffset = function () { + var axis = this; + var group = axis.legendGroup; + var sideOffset = axis.chart.axisOffset[axis.side]; + if (group) { + // Hook for the getOffset method to add groups to this parent + // group + axis.axisParent = group; + // Call the base + _super.prototype.getOffset.call(this); + // First time only + if (!axis.added) { + axis.added = true; + axis.labelLeft = 0; + axis.labelRight = axis.width; + } + // Reset it to avoid color axis reserving space + axis.chart.axisOffset[axis.side] = sideOffset; + } + }; + /** + * Create the color gradient. + * @private + */ + ColorAxis.prototype.setLegendColor = function () { + var axis = this; + var horiz = axis.horiz; + var reversed = axis.reversed; + var one = reversed ? 1 : 0; + var zero = reversed ? 0 : 1; + var grad = horiz ? [one, 0, zero, 0] : [0, zero, 0, one]; // #3190 + axis.legendColor = { + linearGradient: { + x1: grad[0], + y1: grad[1], + x2: grad[2], + y2: grad[3] + }, + stops: axis.stops + }; + }; + /** + * The color axis appears inside the legend and has its own legend symbol. + * @private + */ + ColorAxis.prototype.drawLegendSymbol = function (legend, item) { + var axis = this; + var padding = legend.padding; + var legendOptions = legend.options; + var horiz = axis.horiz; + var width = pick(legendOptions.symbolWidth, horiz ? ColorAxis.defaultLegendLength : 12); + var height = pick(legendOptions.symbolHeight, horiz ? 12 : ColorAxis.defaultLegendLength); + var labelPadding = pick(legendOptions.labelPadding, horiz ? 16 : 30); + var itemDistance = pick(legendOptions.itemDistance, 10); + this.setLegendColor(); + // Create the gradient + item.legendSymbol = this.chart.renderer.rect(0, legend.baseline - 11, width, height).attr({ + zIndex: 1 + }).add(item.legendGroup); + // Set how much space this legend item takes up + axis.legendItemWidth = width + padding + (horiz ? itemDistance : labelPadding); + axis.legendItemHeight = height + padding + (horiz ? labelPadding : 0); + }; + /** + * Fool the legend. + * @private + */ + ColorAxis.prototype.setState = function (state) { + this.series.forEach(function (series) { + series.setState(state); + }); + }; + /** + * @private + */ + ColorAxis.prototype.setVisible = function () { + }; + /** + * @private + */ + ColorAxis.prototype.getSeriesExtremes = function () { + var axis = this; + var series = axis.series; + var colorValArray, colorKey, colorValIndex, pointArrayMap, calculatedExtremes, cSeries, i = series.length, yData, j; + this.dataMin = Infinity; + this.dataMax = -Infinity; + while (i--) { // x, y, value, other + cSeries = series[i]; + colorKey = cSeries.colorKey = pick(cSeries.options.colorKey, cSeries.colorKey, cSeries.pointValKey, cSeries.zoneAxis, 'y'); + pointArrayMap = cSeries.pointArrayMap; + calculatedExtremes = cSeries[colorKey + 'Min'] && + cSeries[colorKey + 'Max']; + if (cSeries[colorKey + 'Data']) { + colorValArray = cSeries[colorKey + 'Data']; + } + else { + if (!pointArrayMap) { + colorValArray = cSeries.yData; + } + else { + colorValArray = []; + colorValIndex = pointArrayMap.indexOf(colorKey); + yData = cSeries.yData; + if (colorValIndex >= 0 && yData) { + for (j = 0; j < yData.length; j++) { + colorValArray.push(pick(yData[j][colorValIndex], yData[j])); + } + } + } + } + // If color key extremes are already calculated, use them. + if (calculatedExtremes) { + cSeries.minColorValue = cSeries[colorKey + 'Min']; + cSeries.maxColorValue = cSeries[colorKey + 'Max']; + } + else { + var cExtremes = Series.prototype.getExtremes.call(cSeries, colorValArray); + cSeries.minColorValue = cExtremes.dataMin; + cSeries.maxColorValue = cExtremes.dataMax; + } + if (typeof cSeries.minColorValue !== 'undefined') { + this.dataMin = + Math.min(this.dataMin, cSeries.minColorValue); + this.dataMax = + Math.max(this.dataMax, cSeries.maxColorValue); + } + if (!calculatedExtremes) { + Series.prototype.applyExtremes.call(cSeries); + } + } + }; + /** + * Internal function to draw a crosshair. + * + * @function Highcharts.ColorAxis#drawCrosshair + * + * @param {Highcharts.PointerEventObject} [e] + * The event arguments from the modified pointer event, extended with + * `chartX` and `chartY` + * + * @param {Highcharts.Point} [point] + * The Point object if the crosshair snaps to points. + * + * @fires Highcharts.ColorAxis#event:afterDrawCrosshair + * @fires Highcharts.ColorAxis#event:drawCrosshair + */ + ColorAxis.prototype.drawCrosshair = function (e, point) { + var axis = this; + var plotX = point && point.plotX; + var plotY = point && point.plotY; + var axisPos = axis.pos; + var axisLen = axis.len; + var crossPos; + if (point) { + crossPos = axis.toPixels(point.getNestedProperty(point.series.colorKey)); + if (crossPos < axisPos) { + crossPos = axisPos - 2; + } + else if (crossPos > axisPos + axisLen) { + crossPos = axisPos + axisLen + 2; + } + point.plotX = crossPos; + point.plotY = axis.len - crossPos; + _super.prototype.drawCrosshair.call(this, e, point); + point.plotX = plotX; + point.plotY = plotY; + if (axis.cross && + !axis.cross.addedToColorAxis && + axis.legendGroup) { + axis.cross + .addClass('highcharts-coloraxis-marker') + .add(axis.legendGroup); + axis.cross.addedToColorAxis = true; + if (!axis.chart.styledMode && + axis.crosshair) { + axis.cross.attr({ + fill: axis.crosshair.color + }); + } + } + } + }; + /** + * @private + */ + ColorAxis.prototype.getPlotLinePath = function (options) { + var axis = this; + var left = axis.left; + var pos = options.translatedValue; + var top = axis.top; + // crosshairs only + return isNumber(pos) ? // pos can be 0 (#3969) + (axis.horiz ? [ + ['M', pos - 4, this.top - 6], + ['L', pos + 4, this.top - 6], + ['L', pos, this.top], + ['Z'] + ] : [ + ['M', this.left, pos], + ['L', this.left - 6, pos + 6], + ['L', this.left - 6, pos - 6], + ['Z'] + ]) : + _super.prototype.getPlotLinePath.call(this, options); + }; + /** + * Updates a color axis instance with a new set of options. The options are + * merged with the existing options, so only new or altered options need to + * be specified. + * + * @function Highcharts.ColorAxis#update + * + * @param {Highcharts.ColorAxisOptions} newOptions + * The new options that will be merged in with existing options on the color + * axis. + * + * @param {boolean} [redraw] + * Whether to redraw the chart after the color axis is altered. If doing + * more operations on the chart, it is a good idea to set redraw to `false` + * and call {@link Highcharts.Chart#redraw} after. + */ + ColorAxis.prototype.update = function (newOptions, redraw) { + var axis = this; + var chart = axis.chart; + var legend = chart.legend; + var updatedOptions = ColorAxis.buildOptions(chart, {}, newOptions); + this.series.forEach(function (series) { + // Needed for Axis.update when choropleth colors change + series.isDirtyData = true; + }); + // When updating data classes, destroy old items and make sure new + // ones are created (#3207) + if (newOptions.dataClasses && legend.allItems || axis.dataClasses) { + axis.destroyItems(); + } + // Keep the options structure updated for export. Unlike xAxis and + // yAxis, the colorAxis is not an array. (#3207) + chart.options[axis.coll] = + merge(axis.userOptions, updatedOptions); + _super.prototype.update.call(this, updatedOptions, redraw); + if (axis.legendItem) { + axis.setLegendColor(); + legend.colorizeItem(this, true); + } + }; + /** + * Destroy color axis legend items. + * @private + */ + ColorAxis.prototype.destroyItems = function () { + var axis = this; + var chart = axis.chart; + if (axis.legendItem) { + chart.legend.destroyItem(axis); + } + else if (axis.legendItems) { + axis.legendItems.forEach(function (item) { + chart.legend.destroyItem(item); + }); + } + chart.isDirtyLegend = true; + }; + /** + * Removes the color axis and the related legend item. + * + * @function Highcharts.ColorAxis#remove + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart following the remove. + */ + ColorAxis.prototype.remove = function (redraw) { + this.destroyItems(); + _super.prototype.remove.call(this, redraw); + }; + /** + * Get the legend item symbols for data classes. + * @private + */ + ColorAxis.prototype.getDataClassLegendSymbols = function () { + var axis = this; + var chart = axis.chart; + var legendItems = axis.legendItems; + var legendOptions = chart.options.legend; + var valueDecimals = legendOptions.valueDecimals; + var valueSuffix = legendOptions.valueSuffix || ''; + var name; + if (!legendItems.length) { + axis.dataClasses.forEach(function (dataClass, i) { + var vis = true, from = dataClass.from, to = dataClass.to; + var numberFormatter = chart.numberFormatter; + // Assemble the default name. This can be overridden + // by legend.options.labelFormatter + name = ''; + if (typeof from === 'undefined') { + name = '< '; + } + else if (typeof to === 'undefined') { + name = '> '; + } + if (typeof from !== 'undefined') { + name += numberFormatter(from, valueDecimals) + valueSuffix; + } + if (typeof from !== 'undefined' && typeof to !== 'undefined') { + name += ' - '; + } + if (typeof to !== 'undefined') { + name += numberFormatter(to, valueDecimals) + valueSuffix; + } + // Add a mock object to the legend items + legendItems.push(extend({ + chart: chart, + name: name, + options: {}, + drawLegendSymbol: LegendSymbolMixin.drawRectangle, + visible: true, + setState: noop, + isDataClass: true, + setVisible: function () { + vis = axis.visible = !vis; + axis.series.forEach(function (series) { + series.points.forEach(function (point) { + if (point.dataClass === i) { + point.setVisible(vis); + } + }); + }); + chart.legend.colorizeItem(this, vis); + } + }, dataClass)); + }); + } + return legendItems; + }; + /* * + * + * Static Functions + * + * */ + ColorAxis.defaultLegendLength = 200; + /** + * A color axis for series. Visually, the color + * axis will appear as a gradient or as separate items inside the + * legend, depending on whether the axis is scalar or based on data + * classes. + * + * For supported color formats, see the + * [docs article about colors](https://www.highcharts.com/docs/chart-design-and-style/colors). + * + * A scalar color axis is represented by a gradient. The colors either + * range between the [minColor](#colorAxis.minColor) and the + * [maxColor](#colorAxis.maxColor), or for more fine grained control the + * colors can be defined in [stops](#colorAxis.stops). Often times, the + * color axis needs to be adjusted to get the right color spread for the + * data. In addition to stops, consider using a logarithmic + * [axis type](#colorAxis.type), or setting [min](#colorAxis.min) and + * [max](#colorAxis.max) to avoid the colors being determined by + * outliers. + * + * When [dataClasses](#colorAxis.dataClasses) are used, the ranges are + * subdivided into separate classes like categories based on their + * values. This can be used for ranges between two values, but also for + * a true category. However, when your data is categorized, it may be as + * convenient to add each category to a separate series. + * + * Color axis does not work with: `sankey`, `sunburst`, `dependencywheel`, + * `networkgraph`, `wordcloud`, `venn`, `gauge` and `solidgauge` series + * types. + * + * Since v7.2.0 `colorAxis` can also be an array of options objects. + * + * See [the Axis object](/class-reference/Highcharts.Axis) for + * programmatic access to the axis. + * + * @sample {highcharts} highcharts/coloraxis/custom-color-key + * Column chart with color axis + * @sample {highcharts} highcharts/coloraxis/horizontal-layout + * Horizontal layout + * @sample {highmaps} maps/coloraxis/dataclasscolor + * With data classes + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor + * Min color and max color + * + * @extends xAxis + * @excluding alignTicks, allowDecimals, alternateGridColor, breaks, + * categories, crosshair, dateTimeLabelFormats, height, left, + * lineWidth, linkedTo, maxZoom, minRange, minTickInterval, + * offset, opposite, pane, plotBands, plotLines, + * reversedStacks, showEmpty, title, top, width, zoomEnabled + * @product highcharts highstock highmaps + * @type {*|Array<*>} + * @optionparent colorAxis + * @ignore + */ + ColorAxis.defaultOptions = { + /** + * Whether to allow decimals on the color axis. + * @type {boolean} + * @default true + * @product highcharts highstock highmaps + * @apioption colorAxis.allowDecimals + */ + /** + * Determines how to set each data class' color if no individual + * color is set. The default value, `tween`, computes intermediate + * colors between `minColor` and `maxColor`. The other possible + * value, `category`, pulls colors from the global or chart specific + * [colors](#colors) array. + * + * @sample {highmaps} maps/coloraxis/dataclasscolor/ + * Category colors + * + * @type {string} + * @default tween + * @product highcharts highstock highmaps + * @validvalue ["tween", "category"] + * @apioption colorAxis.dataClassColor + */ + /** + * An array of data classes or ranges for the choropleth map. If + * none given, the color axis is scalar and values are distributed + * as a gradient between the minimum and maximum colors. + * + * @sample {highmaps} maps/demo/data-class-ranges/ + * Multiple ranges + * + * @sample {highmaps} maps/demo/data-class-two-ranges/ + * Two ranges + * + * @type {Array<*>} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses + */ + /** + * The layout of the color axis. Can be `'horizontal'` or `'vertical'`. + * If none given, the color axis has the same layout as the legend. + * + * @sample highcharts/coloraxis/horizontal-layout/ + * Horizontal color axis layout with vertical legend + * + * @type {string|undefined} + * @since 7.2.0 + * @product highcharts highstock highmaps + * @apioption colorAxis.layout + */ + /** + * The color of each data class. If not set, the color is pulled + * from the global or chart-specific [colors](#colors) array. In + * styled mode, this option is ignored. Instead, use colors defined + * in CSS. + * + * @sample {highmaps} maps/demo/data-class-two-ranges/ + * Explicit colors + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses.color + */ + /** + * The start of the value range that the data class represents, + * relating to the point value. + * + * The range of each `dataClass` is closed in both ends, but can be + * overridden by the next `dataClass`. + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses.from + */ + /** + * The name of the data class as it appears in the legend. + * If no name is given, it is automatically created based on the + * `from` and `to` values. For full programmatic control, + * [legend.labelFormatter](#legend.labelFormatter) can be used. + * In the formatter, `this.from` and `this.to` can be accessed. + * + * @sample {highmaps} maps/coloraxis/dataclasses-name/ + * Named data classes + * + * @sample {highmaps} maps/coloraxis/dataclasses-labelformatter/ + * Formatted data classes + * + * @type {string} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses.name + */ + /** + * The end of the value range that the data class represents, + * relating to the point value. + * + * The range of each `dataClass` is closed in both ends, but can be + * overridden by the next `dataClass`. + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses.to + */ + /** @ignore-option */ + lineWidth: 0, + /** + * Padding of the min value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. + * + * @product highcharts highstock highmaps + */ + minPadding: 0, + /** + * The maximum value of the axis in terms of map point values. If + * `null`, the max value is automatically calculated. If the + * `endOnTick` option is true, the max value might be rounded up. + * + * @sample {highmaps} maps/coloraxis/gridlines/ + * Explicit min and max to reduce the effect of outliers + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.max + */ + /** + * The minimum value of the axis in terms of map point values. If + * `null`, the min value is automatically calculated. If the + * `startOnTick` option is true, the min value might be rounded + * down. + * + * @sample {highmaps} maps/coloraxis/gridlines/ + * Explicit min and max to reduce the effect of outliers + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.min + */ + /** + * Padding of the max value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. + * + * @product highcharts highstock highmaps + */ + maxPadding: 0, + /** + * Color of the grid lines extending from the axis across the + * gradient. + * + * @sample {highmaps} maps/coloraxis/gridlines/ + * Grid lines demonstrated + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #e6e6e6 + * @product highcharts highstock highmaps + * @apioption colorAxis.gridLineColor + */ + /** + * The width of the grid lines extending from the axis across the + * gradient of a scalar color axis. + * + * @sample {highmaps} maps/coloraxis/gridlines/ + * Grid lines demonstrated + * + * @product highcharts highstock highmaps + */ + gridLineWidth: 1, + /** + * The interval of the tick marks in axis units. When `null`, the + * tick interval is computed to approximately follow the + * `tickPixelInterval`. + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.tickInterval + */ + /** + * If [tickInterval](#colorAxis.tickInterval) is `null` this option + * sets the approximate pixel interval of the tick marks. + * + * @product highcharts highstock highmaps + */ + tickPixelInterval: 72, + /** + * Whether to force the axis to start on a tick. Use this option + * with the `maxPadding` option to control the axis start. + * + * @product highcharts highstock highmaps + */ + startOnTick: true, + /** + * Whether to force the axis to end on a tick. Use this option with + * the [maxPadding](#colorAxis.maxPadding) option to control the + * axis end. + * + * @product highcharts highstock highmaps + */ + endOnTick: true, + /** @ignore */ + offset: 0, + /** + * The triangular marker on a scalar color axis that points to the + * value of the hovered area. To disable the marker, set + * `marker: null`. + * + * @sample {highmaps} maps/coloraxis/marker/ + * Black marker + * + * @declare Highcharts.PointMarkerOptionsObject + * @product highcharts highstock highmaps + */ + marker: { + /** + * Animation for the marker as it moves between values. Set to + * `false` to disable animation. Defaults to `{ duration: 50 }`. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + * @product highcharts highstock highmaps + */ + animation: { + /** @internal */ + duration: 50 + }, + /** @internal */ + width: 0.01, + /** + * The color of the marker. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock highmaps + */ + color: '#999999' + }, + /** + * The axis labels show the number for each tick. + * + * For more live examples on label options, see [xAxis.labels in the + * Highcharts API.](/highcharts#xAxis.labels) + * + * @extends xAxis.labels + * @product highcharts highstock highmaps + */ + labels: { + /** + * How to handle overflowing labels on horizontal color axis. If set + * to `"allow"`, it will not be aligned at all. By default it + * `"justify"` labels inside the chart area. If there is room to + * move it, it will be aligned to the edge, else it will be removed. + * + * @validvalue ["allow", "justify"] + * @product highcharts highstock highmaps + */ + overflow: 'justify', + rotation: 0 + }, + /** + * The color to represent the minimum of the color axis. Unless + * [dataClasses](#colorAxis.dataClasses) or + * [stops](#colorAxis.stops) are set, the gradient starts at this + * value. + * + * If dataClasses are set, the color is based on minColor and + * maxColor unless a color is set for each data class, or the + * [dataClassColor](#colorAxis.dataClassColor) is set. + * + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor/ + * Min and max colors on scalar (gradient) axis + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor-dataclasses/ + * On data classes + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock highmaps + */ + minColor: '#e6ebf5', + /** + * The color to represent the maximum of the color axis. Unless + * [dataClasses](#colorAxis.dataClasses) or + * [stops](#colorAxis.stops) are set, the gradient ends at this + * value. + * + * If dataClasses are set, the color is based on minColor and + * maxColor unless a color is set for each data class, or the + * [dataClassColor](#colorAxis.dataClassColor) is set. + * + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor/ + * Min and max colors on scalar (gradient) axis + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor-dataclasses/ + * On data classes + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock highmaps + */ + maxColor: '#003399', + /** + * Color stops for the gradient of a scalar color axis. Use this in + * cases where a linear gradient between a `minColor` and `maxColor` + * is not sufficient. The stops is an array of tuples, where the + * first item is a float between 0 and 1 assigning the relative + * position in the gradient, and the second item is the color. + * + * @sample {highmaps} maps/demo/heatmap/ + * Heatmap with three color stops + * + * @type {Array>} + * @product highcharts highstock highmaps + * @apioption colorAxis.stops + */ + /** + * The pixel length of the main tick marks on the color axis. + */ + tickLength: 5, + /** + * The type of interpolation to use for the color axis. Can be + * `linear` or `logarithmic`. + * + * @sample highcharts/coloraxis/logarithmic-with-emulate-negative-values/ + * Logarithmic color axis with extension to emulate negative + * values + * + * @type {Highcharts.ColorAxisTypeValue} + * @default linear + * @product highcharts highstock highmaps + * @apioption colorAxis.type + */ + /** + * Whether to reverse the axis so that the highest number is closest + * to the origin. Defaults to `false` in a horizontal legend and + * `true` in a vertical legend, where the smallest value starts on + * top. + * + * @type {boolean} + * @product highcharts highstock highmaps + * @apioption colorAxis.reversed + */ + /** + * @product highcharts highstock highmaps + * @excluding afterBreaks, pointBreak, pointInBreak + * @apioption colorAxis.events + */ + /** + * Fires when the legend item belonging to the colorAxis is clicked. + * One parameter, `event`, is passed to the function. + * + * @type {Function} + * @product highcharts highstock highmaps + * @apioption colorAxis.events.legendItemClick + */ + /** + * Whether to display the colorAxis in the legend. + * + * @sample highcharts/coloraxis/hidden-coloraxis-with-3d-chart/ + * Hidden color axis with 3d chart + * + * @see [heatmap.showInLegend](#series.heatmap.showInLegend) + * + * @since 4.2.7 + * @product highcharts highstock highmaps + */ + showInLegend: true + }; + /** + * @private + */ + ColorAxis.keepProps = [ + 'legendGroup', + 'legendItemHeight', + 'legendItemWidth', + 'legendItem', + 'legendSymbol' + ]; + return ColorAxis; +}(Axis)); +// Properties to preserve after destroy, for Axis.update (#5881, #6025). +Array.prototype.push.apply(Axis.keepProps, ColorAxis.keepProps); +H.ColorAxis = ColorAxis; +/** + * Handle animation of the color attributes directly + * + * @private + * @function Highcharts.Fx#fillSetter + */ /** +* Handle animation of the color attributes directly +* +* @private +* @function Highcharts.Fx#strokeSetter +*/ +['fill', 'stroke'].forEach(function (prop) { + Fx.prototype[prop + 'Setter'] = function () { + this.elem.attr(prop, color(this.start).tweenTo(color(this.end), this.pos), null, true); + }; +}); +// Extend the chart getAxes method to also get the color axis +addEvent(Chart, 'afterGetAxes', function () { + var chart = this, options = chart.options; + this.colorAxis = []; + if (options.colorAxis) { + options.colorAxis = splat(options.colorAxis); + options.colorAxis.forEach(function (axisOptions, i) { + axisOptions.index = i; + new ColorAxis(chart, axisOptions); // eslint-disable-line no-new + }); + } +}); +// Add colorAxis to series axisTypes +addEvent(Series, 'bindAxes', function () { + var axisTypes = this.axisTypes; + if (!axisTypes) { + this.axisTypes = ['colorAxis']; + } + else if (axisTypes.indexOf('colorAxis') === -1) { + axisTypes.push('colorAxis'); + } +}); +// Add the color axis. This also removes the axis' own series to prevent +// them from showing up individually. +addEvent(Legend, 'afterGetAllItems', function (e) { + var colorAxisItems = [], colorAxes = this.chart.colorAxis || [], options, i; + colorAxes.forEach(function (colorAxis) { + options = colorAxis.options; + if (options && options.showInLegend) { + // Data classes + if (options.dataClasses && options.visible) { + colorAxisItems = colorAxisItems.concat(colorAxis.getDataClassLegendSymbols()); + // Gradient legend + } + else if (options.visible) { + // Add this axis on top + colorAxisItems.push(colorAxis); + } + // If dataClasses are defined or showInLegend option is not set to + // true, do not add color axis' series to legend. + colorAxis.series.forEach(function (series) { + if (!series.options.showInLegend || options.dataClasses) { + if (series.options.legendType === 'point') { + series.points.forEach(function (point) { + erase(e.allItems, point); + }); + } + else { + erase(e.allItems, series); + } + } + }); + } + }); + i = colorAxisItems.length; + while (i--) { + e.allItems.unshift(colorAxisItems[i]); + } +}); +addEvent(Legend, 'afterColorizeItem', function (e) { + if (e.visible && e.item.legendColor) { + e.item.legendSymbol.attr({ + fill: e.item.legendColor + }); + } +}); +// Updates in the legend need to be reflected in the color axis (6888) +addEvent(Legend, 'afterUpdate', function () { + var colorAxes = this.chart.colorAxis; + if (colorAxes) { + colorAxes.forEach(function (colorAxis) { + colorAxis.update({}, arguments[2]); + }); + } +}); +// Calculate and set colors for points +addEvent(Series, 'afterTranslate', function () { + if (this.chart.colorAxis && + this.chart.colorAxis.length || + this.colorAttribs) { + this.translateColors(); + } +}); +export default ColorAxis; diff --git a/librerias/gantt/code/es-modules/parts-map/ColorMapSeriesMixin.js b/librerias/gantt/code/es-modules/parts-map/ColorMapSeriesMixin.js new file mode 100644 index 0000000..76fe411 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-map/ColorMapSeriesMixin.js @@ -0,0 +1,81 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import Point from '../parts/Point.js'; +import U from '../parts/Utilities.js'; +var defined = U.defined; +var noop = H.noop, seriesTypes = H.seriesTypes; +/** + * Mixin for maps and heatmaps + * + * @private + * @mixin Highcharts.colorMapPointMixin + */ +H.colorMapPointMixin = { + dataLabelOnNull: true, + /* eslint-disable valid-jsdoc */ + /** + * Color points have a value option that determines whether or not it is + * a null point + * @private + * @function Highcharts.colorMapPointMixin.isValid + * @return {boolean} + */ + isValid: function () { + // undefined is allowed + return (this.value !== null && + this.value !== Infinity && + this.value !== -Infinity); + }, + /** + * @private + * @function Highcharts.colorMapPointMixin.setState + * @param {string} state + * @return {void} + */ + setState: function (state) { + Point.prototype.setState.call(this, state); + if (this.graphic) { + this.graphic.attr({ + zIndex: state === 'hover' ? 1 : 0 + }); + } + } + /* eslint-enable valid-jsdoc */ +}; +/** + * @private + * @mixin Highcharts.colorMapSeriesMixin + */ +H.colorMapSeriesMixin = { + pointArrayMap: ['value'], + axisTypes: ['xAxis', 'yAxis', 'colorAxis'], + trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'], + getSymbol: noop, + parallelArrays: ['x', 'y', 'value'], + colorKey: 'value', + pointAttribs: seriesTypes.column.prototype.pointAttribs, + /* eslint-disable valid-jsdoc */ + /** + * Get the color attibutes to apply on the graphic + * @private + * @function Highcharts.colorMapSeriesMixin.colorAttribs + * @param {Highcharts.Point} point + * @return {Highcharts.SVGAttributes} + */ + colorAttribs: function (point) { + var ret = {}; + if (defined(point.color)) { + ret[this.colorProp || 'fill'] = point.color; + } + return ret; + } +}; diff --git a/librerias/gantt/code/es-modules/parts-map/ColorSeriesMixin.js b/librerias/gantt/code/es-modules/parts-map/ColorSeriesMixin.js new file mode 100644 index 0000000..defd5ad --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-map/ColorSeriesMixin.js @@ -0,0 +1,70 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +/** + * Mixin for maps and heatmaps + * + * @private + * @mixin Highcharts.colorPointMixin + */ +H.colorPointMixin = { + /* eslint-disable valid-jsdoc */ + /** + * Set the visibility of a single point + * @private + * @function Highcharts.colorPointMixin.setVisible + * @param {boolean} visible + * @return {void} + */ + setVisible: function (vis) { + var point = this, method = vis ? 'show' : 'hide'; + point.visible = point.options.visible = Boolean(vis); + // Show and hide associated elements + ['graphic', 'dataLabel'].forEach(function (key) { + if (point[key]) { + point[key][method](); + } + }); + } + /* eslint-enable valid-jsdoc */ +}; +/** + * @private + * @mixin Highcharts.colorSeriesMixin + */ +H.colorSeriesMixin = { + optionalAxis: 'colorAxis', + colorAxis: 0, + /* eslint-disable valid-jsdoc */ + /** + * In choropleth maps, the color is a result of the value, so this needs + * translation too + * @private + * @function Highcharts.colorSeriesMixin.translateColors + * @return {void} + */ + translateColors: function () { + var series = this, points = this.data.length ? this.data : this.points, nullColor = this.options.nullColor, colorAxis = this.colorAxis, colorKey = this.colorKey; + points.forEach(function (point) { + var value = point.getNestedProperty(colorKey), color; + color = point.options.color || + (point.isNull || point.value === null ? + nullColor : + (colorAxis && typeof value !== 'undefined') ? + colorAxis.toColor(value, point) : + point.color || series.color); + if (color) { + point.color = color; + } + }); + } + /* eslint-enable valid-jsdoc */ +}; diff --git a/librerias/gantt/code/es-modules/parts-map/GeoJSON.js b/librerias/gantt/code/es-modules/parts-map/GeoJSON.js new file mode 100644 index 0000000..67b03be --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-map/GeoJSON.js @@ -0,0 +1,353 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +/** + * Result object of a map transformation. + * + * @interface Highcharts.MapCoordinateObject + */ /** +* X coordinate on the map. +* @name Highcharts.MapCoordinateObject#x +* @type {number} +*/ /** +* Y coordinate on the map. +* @name Highcharts.MapCoordinateObject#y +* @type {number|null} +*/ +/** + * A latitude/longitude object. + * + * @interface Highcharts.MapLatLonObject + */ /** +* The latitude. +* @name Highcharts.MapLatLonObject#lat +* @type {number} +*/ /** +* The longitude. +* @name Highcharts.MapLatLonObject#lon +* @type {number} +*/ +import U from '../parts/Utilities.js'; +var error = U.error, extend = U.extend, format = U.format, merge = U.merge, wrap = U.wrap; +import '../parts/Options.js'; +import '../parts/Chart.js'; +var Chart = H.Chart, win = H.win; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * Test for point in polygon. Polygon defined as array of [x,y] points. + * @private + */ +function pointInPolygon(point, polygon) { + var i, j, rel1, rel2, c = false, x = point.x, y = point.y; + for (i = 0, j = polygon.length - 1; i < polygon.length; j = i++) { + rel1 = polygon[i][1] > y; + rel2 = polygon[j][1] > y; + if (rel1 !== rel2 && + (x < (polygon[j][0] - + polygon[i][0]) * (y - polygon[i][1]) / + (polygon[j][1] - polygon[i][1]) + + polygon[i][0])) { + c = !c; + } + } + return c; +} +/** + * Highmaps only. Get point from latitude and longitude using specified + * transform definition. + * + * @requires modules/map + * + * @sample maps/series/latlon-transform/ + * Use specific transformation for lat/lon + * + * @function Highcharts.Chart#transformFromLatLon + * + * @param {Highcharts.MapLatLonObject} latLon + * A latitude/longitude object. + * + * @param {*} transform + * The transform definition to use as explained in the + * {@link https://www.highcharts.com/docs/maps/latlon|documentation}. + * + * @return {Highcharts.MapCoordinateObject} + * An object with `x` and `y` properties. + */ +Chart.prototype.transformFromLatLon = function (latLon, transform) { + /** + * Allows to manually load the proj4 library from Highcharts options + * instead of the `window`. + * In case of loading the library from a `script` tag, + * this option is not needed, it will be loaded from there by default. + * + * @type {function} + * @product highmaps + * @apioption chart.proj4 + */ + var _a; + var proj4 = (((_a = this.userOptions.chart) === null || _a === void 0 ? void 0 : _a.proj4) || win.proj4); + if (!proj4) { + error(21, false, this); + return { + x: 0, + y: null + }; + } + var projected = proj4(transform.crs, [latLon.lon, latLon.lat]), cosAngle = transform.cosAngle || + (transform.rotation && Math.cos(transform.rotation)), sinAngle = transform.sinAngle || + (transform.rotation && Math.sin(transform.rotation)), rotated = transform.rotation ? [ + projected[0] * cosAngle + projected[1] * sinAngle, + -projected[0] * sinAngle + projected[1] * cosAngle + ] : projected; + return { + x: ((rotated[0] - (transform.xoffset || 0)) * (transform.scale || 1) + + (transform.xpan || 0)) * (transform.jsonres || 1) + + (transform.jsonmarginX || 0), + y: (((transform.yoffset || 0) - rotated[1]) * (transform.scale || 1) + + (transform.ypan || 0)) * (transform.jsonres || 1) - + (transform.jsonmarginY || 0) + }; +}; +/** + * Highmaps only. Get latLon from point using specified transform definition. + * The method returns an object with the numeric properties `lat` and `lon`. + * + * @requires modules/map + * + * @sample maps/series/latlon-transform/ + * Use specific transformation for lat/lon + * + * @function Highcharts.Chart#transformToLatLon + * + * @param {Highcharts.Point|Highcharts.MapCoordinateObject} point + * A `Point` instance, or any object containing the properties `x` and + * `y` with numeric values. + * + * @param {*} transform + * The transform definition to use as explained in the + * {@link https://www.highcharts.com/docs/maps/latlon|documentation}. + * + * @return {Highcharts.MapLatLonObject|undefined} + * An object with `lat` and `lon` properties. + */ +Chart.prototype.transformToLatLon = function (point, transform) { + if (typeof win.proj4 === 'undefined') { + error(21, false, this); + return; + } + var normalized = { + x: ((point.x - + (transform.jsonmarginX || 0)) / (transform.jsonres || 1) - + (transform.xpan || 0)) / (transform.scale || 1) + + (transform.xoffset || 0), + y: ((-point.y - (transform.jsonmarginY || 0)) / (transform.jsonres || 1) + + (transform.ypan || 0)) / (transform.scale || 1) + + (transform.yoffset || 0) + }, cosAngle = transform.cosAngle || + (transform.rotation && Math.cos(transform.rotation)), sinAngle = transform.sinAngle || + (transform.rotation && Math.sin(transform.rotation)), + // Note: Inverted sinAngle to reverse rotation direction + projected = win.proj4(transform.crs, 'WGS84', transform.rotation ? { + x: normalized.x * cosAngle + normalized.y * -sinAngle, + y: normalized.x * sinAngle + normalized.y * cosAngle + } : normalized); + return { lat: projected.y, lon: projected.x }; +}; +/** + * Highmaps only. Calculate latitude/longitude values for a point. Returns an + * object with the numeric properties `lat` and `lon`. + * + * @requires modules/map + * + * @sample maps/demo/latlon-advanced/ + * Advanced lat/lon demo + * + * @function Highcharts.Chart#fromPointToLatLon + * + * @param {Highcharts.Point|Highcharts.MapCoordinateObject} point + * A `Point` instance or anything containing `x` and `y` properties with + * numeric values. + * + * @return {Highcharts.MapLatLonObject|undefined} + * An object with `lat` and `lon` properties. + */ +Chart.prototype.fromPointToLatLon = function (point) { + var transforms = this.mapTransforms, transform; + if (!transforms) { + error(22, false, this); + return; + } + for (transform in transforms) { + if (Object.hasOwnProperty.call(transforms, transform) && + transforms[transform].hitZone && + pointInPolygon({ x: point.x, y: -point.y }, transforms[transform].hitZone.coordinates[0])) { + return this.transformToLatLon(point, transforms[transform]); + } + } + return this.transformToLatLon(point, transforms['default'] // eslint-disable-line dot-notation + ); +}; +/** + * Highmaps only. Get chart coordinates from latitude/longitude. Returns an + * object with x and y values corresponding to the `xAxis` and `yAxis`. + * + * @requires modules/map + * + * @sample maps/series/latlon-to-point/ + * Find a point from lat/lon + * + * @function Highcharts.Chart#fromLatLonToPoint + * + * @param {Highcharts.MapLatLonObject} latLon + * Coordinates. + * + * @return {Highcharts.MapCoordinateObject} + * X and Y coordinates in terms of chart axis values. + */ +Chart.prototype.fromLatLonToPoint = function (latLon) { + var transforms = this.mapTransforms, transform, coords; + if (!transforms) { + error(22, false, this); + return { + x: 0, + y: null + }; + } + for (transform in transforms) { + if (Object.hasOwnProperty.call(transforms, transform) && + transforms[transform].hitZone) { + coords = this.transformFromLatLon(latLon, transforms[transform]); + if (pointInPolygon({ x: coords.x, y: -coords.y }, transforms[transform].hitZone.coordinates[0])) { + return coords; + } + } + } + return this.transformFromLatLon(latLon, transforms['default'] // eslint-disable-line dot-notation + ); +}; +/** + * Highmaps only. Restructure a GeoJSON object in preparation to be read + * directly by the + * {@link https://api.highcharts.com/highmaps/plotOptions.series.mapData|series.mapData} + * option. The GeoJSON will be broken down to fit a specific Highcharts type, + * either `map`, `mapline` or `mappoint`. Meta data in GeoJSON's properties + * object will be copied directly over to {@link Point.properties} in Highmaps. + * + * @requires modules/map + * + * @sample maps/demo/geojson/ + * Simple areas + * @sample maps/demo/geojson-multiple-types/ + * Multiple types + * + * @function Highcharts.geojson + * + * @param {*} geojson + * The GeoJSON structure to parse, represented as a JavaScript object + * rather than a JSON string. + * + * @param {string} [hType=map] + * The Highmaps series type to prepare for. Setting "map" will return + * GeoJSON polygons and multipolygons. Setting "mapline" will return + * GeoJSON linestrings and multilinestrings. Setting "mappoint" will + * return GeoJSON points and multipoints. + * + * @return {Array<*>} + * An object ready for the `mapData` option. + */ +H.geojson = function (geojson, hType, series) { + var mapData = [], path = [], polygonToPath = function (polygon) { + polygon.forEach(function (point, i) { + if (i === 0) { + path.push(['M', point[0], -point[1]]); + } + else { + path.push(['L', point[0], -point[1]]); + } + }); + }; + hType = hType || 'map'; + geojson.features.forEach(function (feature) { + var geometry = feature.geometry, type = geometry.type, coordinates = geometry.coordinates, properties = feature.properties, point; + path = []; + if (hType === 'map' || hType === 'mapbubble') { + if (type === 'Polygon') { + coordinates.forEach(polygonToPath); + path.push(['Z']); + } + else if (type === 'MultiPolygon') { + coordinates.forEach(function (items) { + items.forEach(polygonToPath); + }); + path.push(['Z']); + } + if (path.length) { + point = { path: path }; + } + } + else if (hType === 'mapline') { + if (type === 'LineString') { + polygonToPath(coordinates); + } + else if (type === 'MultiLineString') { + coordinates.forEach(polygonToPath); + } + if (path.length) { + point = { path: path }; + } + } + else if (hType === 'mappoint') { + if (type === 'Point') { + point = { + x: coordinates[0], + y: -coordinates[1] + }; + } + } + if (point) { + mapData.push(extend(point, { + name: properties.name || properties.NAME, + /** + * In Highmaps, when data is loaded from GeoJSON, the GeoJSON + * item's properies are copied over here. + * + * @requires modules/map + * @name Highcharts.Point#properties + * @type {*} + */ + properties: properties + })); + } + }); + // Create a credits text that includes map source, to be picked up in + // Chart.addCredits + if (series && geojson.copyrightShort) { + series.chart.mapCredits = format(series.chart.options.credits.mapText, { geojson: geojson }); + series.chart.mapCreditsFull = format(series.chart.options.credits.mapTextFull, { geojson: geojson }); + } + return mapData; +}; +// Override addCredits to include map source by default +wrap(Chart.prototype, 'addCredits', function (proceed, credits) { + credits = merge(true, this.options.credits, credits); + // Disable credits link if map credits enabled. This to allow for in-text + // anchors. + if (this.mapCredits) { + credits.href = null; + } + proceed.call(this, credits); + // Add full map credits to hover + if (this.credits && this.mapCreditsFull) { + this.credits.attr({ + title: this.mapCreditsFull + }); + } +}); diff --git a/librerias/gantt/code/es-modules/parts-map/HeatmapSeries.js b/librerias/gantt/code/es-modules/parts-map/HeatmapSeries.js new file mode 100644 index 0000000..00d4153 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-map/HeatmapSeries.js @@ -0,0 +1,953 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +/* * + * @interface Highcharts.PointOptionsObject in parts/Point.ts + */ /** +* Heatmap series only. Point padding for a single point. +* @name Highcharts.PointOptionsObject#pointPadding +* @type {number|undefined} +*/ /** +* Heatmap series only. The value of the point, resulting in a color controled +* by options as set in the colorAxis configuration. +* @name Highcharts.PointOptionsObject#value +* @type {number|null|undefined} +*/ +import LegendSymbolMixin from '../mixins/legend-symbol.js'; +import U from '../parts/Utilities.js'; +var clamp = U.clamp, extend = U.extend, fireEvent = U.fireEvent, isNumber = U.isNumber, merge = U.merge, pick = U.pick, seriesType = U.seriesType; +import '../parts/Options.js'; +import '../parts/Series.js'; +import './ColorMapSeriesMixin.js'; +var colorMapPointMixin = H.colorMapPointMixin, colorMapSeriesMixin = H.colorMapSeriesMixin, noop = H.noop, Series = H.Series, seriesTypes = H.seriesTypes, symbols = H.SVGRenderer.prototype.symbols; +/** + * @private + * @class + * @name Highcharts.seriesTypes.heatmap + * + * @augments Highcharts.Series + */ +seriesType('heatmap', 'scatter', +/** + * A heatmap is a graphical representation of data where the individual + * values contained in a matrix are represented as colors. + * + * @productdesc {highcharts} + * Requires `modules/heatmap`. + * + * @sample highcharts/demo/heatmap/ + * Simple heatmap + * @sample highcharts/demo/heatmap-canvas/ + * Heavy heatmap + * + * @extends plotOptions.scatter + * @excluding animationLimit, connectEnds, connectNulls, dashStyle, + * findNearestPointBy, getExtremesFromAll, jitter, linecap, + * lineWidth, pointInterval, pointIntervalUnit, pointRange, + * pointStart, shadow, softThreshold, stacking, step, + * threshold, cluster + * @product highcharts highmaps + * @optionparent plotOptions.heatmap + */ +{ + /** + * Animation is disabled by default on the heatmap series. + */ + animation: false, + /** + * The border width for each heat map item. + */ + borderWidth: 0, + /** + * Padding between the points in the heatmap. + * + * @type {number} + * @default 0 + * @since 6.0 + * @apioption plotOptions.heatmap.pointPadding + */ + /** + * @default value + * @apioption plotOptions.heatmap.colorKey + */ + /** + * The main color of the series. In heat maps this color is rarely used, + * as we mostly use the color to denote the value of each point. Unless + * options are set in the [colorAxis](#colorAxis), the default value + * is pulled from the [options.colors](#colors) array. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 4.0 + * @product highcharts + * @apioption plotOptions.heatmap.color + */ + /** + * The column size - how many X axis units each column in the heatmap + * should span. + * + * @sample {highcharts} maps/demo/heatmap/ + * One day + * @sample {highmaps} maps/demo/heatmap/ + * One day + * + * @type {number} + * @default 1 + * @since 4.0 + * @product highcharts highmaps + * @apioption plotOptions.heatmap.colsize + */ + /** + * The row size - how many Y axis units each heatmap row should span. + * + * @sample {highcharts} maps/demo/heatmap/ + * 1 by default + * @sample {highmaps} maps/demo/heatmap/ + * 1 by default + * + * @type {number} + * @default 1 + * @since 4.0 + * @product highcharts highmaps + * @apioption plotOptions.heatmap.rowsize + */ + /** + * The color applied to null points. In styled mode, a general CSS class + * is applied instead. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + nullColor: '#f7f7f7', + dataLabels: { + formatter: function () { + return this.point.value; + }, + inside: true, + verticalAlign: 'middle', + crop: false, + overflow: false, + padding: 0 // #3837 + }, + /** + * @excluding radius, enabledThreshold + */ + marker: { + /** + * A predefined shape or symbol for the marker. When undefined, the + * symbol is pulled from options.symbols. Other possible values are + * `'circle'`, `'square'`,`'diamond'`, `'triangle'`, + * `'triangle-down'`, `'rect'`, and `'ellipse'`. + * + * Additionally, the URL to a graphic can be given on this form: + * `'url(graphic.png)'`. Note that for the image to be applied to + * exported charts, its URL needs to be accessible by the export + * server. + * + * Custom callbacks for symbol path generation can also be added to + * `Highcharts.SVGRenderer.prototype.symbols`. The callback is then + * used by its method name, as shown in the demo. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-symbol/ + * Predefined, graphic and custom markers + * @sample {highstock} highcharts/plotoptions/series-marker-symbol/ + * Predefined, graphic and custom markers + */ + symbol: 'rect', + /** @ignore-option */ + radius: 0, + lineColor: void 0, + states: { + /** + * @excluding radius, radiusPlus + */ + hover: { + /** + * Set the marker's fixed width on hover state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.hover.width + */ + /** + * Set the marker's fixed height on hover state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.hover.height + */ + /** + * The number of pixels to increase the width of the + * selected point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * 20px greater width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.hover.widthPlus + */ + /** + * The number of pixels to increase the height of the + * selected point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * 20px greater width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.hover.heightPlus + */ + /** + * The additional line width for a hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-linewidthplus + * 5 pixels wider lineWidth on hover + * @sample {highmaps} maps/plotoptions/heatmap-marker-states-hover-linewidthplus + * 5 pixels wider lineWidth on hover + */ + lineWidthPlus: 0 + }, + /** + * @excluding radius + */ + select: { + /** + * Set the marker's fixed width on select state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.select.width + */ + /** + * Set the marker's fixed height on select state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.select.height + */ + /** + * The number of pixels to increase the width of the + * selected point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * 20px greater width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.select.widthPlus + */ + /** + * The number of pixels to increase the height of the + * selected point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * 20px greater width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.select.heightPlus + */ + } + } + }, + clip: true, + /** @ignore-option */ + pointRange: null, + tooltip: { + pointFormat: '{point.x}, {point.y}: {point.value}
' + }, + states: { + hover: { + /** @ignore-option */ + halo: false, + /** + * How much to brighten the point on interaction. Requires the + * main color to be defined in hex or rgb(a) format. + * + * In styled mode, the hover brightening is by default replaced + * with a fill-opacity set in the `.highcharts-point:hover` + * rule. + */ + brightness: 0.2 + } + } +}, merge(colorMapSeriesMixin, { + pointArrayMap: ['y', 'value'], + hasPointSpecificOptions: true, + getExtremesFromAll: true, + directTouch: true, + /* eslint-disable valid-jsdoc */ + /** + * Override the init method to add point ranges on both axes. + * + * @private + * @function Highcharts.seriesTypes.heatmap#init + * @return {void} + */ + init: function () { + var options; + Series.prototype.init.apply(this, arguments); + options = this.options; + // #3758, prevent resetting in setData + options.pointRange = pick(options.pointRange, options.colsize || 1); + // general point range + this.yAxis.axisPointRange = options.rowsize || 1; + // Bind new symbol names + extend(symbols, { + ellipse: symbols.circle, + rect: symbols.square + }); + }, + getSymbol: Series.prototype.getSymbol, + /** + * @private + * @function Highcharts.seriesTypes.heatmap#setClip + * @return {void} + */ + setClip: function (animation) { + var series = this, chart = series.chart; + Series.prototype.setClip.apply(series, arguments); + if (series.options.clip !== false || animation) { + series.markerGroup + .clip((animation || series.clipBox) && series.sharedClipKey ? + chart[series.sharedClipKey] : + chart.clipRect); + } + }, + /** + * @private + * @function Highcharts.seriesTypes.heatmap#translate + * @return {void} + */ + translate: function () { + var series = this, options = series.options, symbol = options.marker && options.marker.symbol || '', shape = symbols[symbol] ? symbol : 'rect', options = series.options, hasRegularShape = ['circle', 'square'].indexOf(shape) !== -1; + series.generatePoints(); + series.points.forEach(function (point) { + var pointAttr, sizeDiff, hasImage, cellAttr = point.getCellAttributes(), shapeArgs = { + x: Math.min(cellAttr.x1, cellAttr.x2), + y: Math.min(cellAttr.y1, cellAttr.y2), + width: Math.max(Math.abs(cellAttr.x2 - cellAttr.x1), 0), + height: Math.max(Math.abs(cellAttr.y2 - cellAttr.y1), 0) + }; + hasImage = point.hasImage = + (point.marker && point.marker.symbol || symbol || '') + .indexOf('url') === 0; + // If marker shape is regular (symetric), find shorter + // cell's side. + if (hasRegularShape) { + sizeDiff = Math.abs(shapeArgs.width - shapeArgs.height); + shapeArgs.x = Math.min(cellAttr.x1, cellAttr.x2) + + (shapeArgs.width < shapeArgs.height ? 0 : sizeDiff / 2); + shapeArgs.y = Math.min(cellAttr.y1, cellAttr.y2) + + (shapeArgs.width < shapeArgs.height ? sizeDiff / 2 : 0); + shapeArgs.width = shapeArgs.height = + Math.min(shapeArgs.width, shapeArgs.height); + } + pointAttr = { + plotX: (cellAttr.x1 + cellAttr.x2) / 2, + plotY: (cellAttr.y1 + cellAttr.y2) / 2, + clientX: (cellAttr.x1 + cellAttr.x2) / 2, + shapeType: 'path', + shapeArgs: merge(true, shapeArgs, { + d: symbols[shape](shapeArgs.x, shapeArgs.y, shapeArgs.width, shapeArgs.height) + }) + }; + if (hasImage) { + point.marker = { + width: shapeArgs.width, + height: shapeArgs.height + }; + } + extend(point, pointAttr); + }); + fireEvent(series, 'afterTranslate'); + }, + /** + * @private + * @function Highcharts.seriesTypes.heatmap#pointAttribs + * @param {Highcharts.HeatmapPoint} point + * @param {string} state + * @return {Highcharts.SVGAttributes} + */ + pointAttribs: function (point, state) { + var series = this, attr = Series.prototype.pointAttribs + .call(series, point, state), seriesOptions = series.options || {}, plotOptions = series.chart.options.plotOptions || {}, seriesPlotOptions = plotOptions.series || {}, heatmapPlotOptions = plotOptions.heatmap || {}, stateOptions, brightness, + // Get old properties in order to keep backward compatibility + borderColor = seriesOptions.borderColor || + heatmapPlotOptions.borderColor || + seriesPlotOptions.borderColor, borderWidth = seriesOptions.borderWidth || + heatmapPlotOptions.borderWidth || + seriesPlotOptions.borderWidth || + attr['stroke-width']; + // Apply lineColor, or set it to default series color. + attr.stroke = ((point && point.marker && point.marker.lineColor) || + (seriesOptions.marker && seriesOptions.marker.lineColor) || + borderColor || + this.color); + // Apply old borderWidth property if exists. + attr['stroke-width'] = borderWidth; + if (state) { + stateOptions = + merge(seriesOptions.states[state], seriesOptions.marker && + seriesOptions.marker.states[state], point.options.states && + point.options.states[state] || {}); + brightness = stateOptions.brightness; + attr.fill = + stateOptions.color || + H.color(attr.fill).brighten(brightness || 0).get(); + attr.stroke = stateOptions.lineColor; + } + return attr; + }, + /** + * @private + * @function Highcharts.seriesTypes.heatmap#markerAttribs + * @param {Highcharts.HeatmapPoint} point + * @return {Highcharts.SVGAttributes} + */ + markerAttribs: function (point, state) { + var pointMarkerOptions = point.marker || {}, seriesMarkerOptions = this.options.marker || {}, seriesStateOptions, pointStateOptions, shapeArgs = point.shapeArgs || {}, hasImage = point.hasImage, attribs = {}; + if (hasImage) { + return { + x: point.plotX, + y: point.plotY + }; + } + // Setting width and height attributes on image does not affect + // on its dimensions. + if (state) { + seriesStateOptions = seriesMarkerOptions.states[state] || {}; + pointStateOptions = pointMarkerOptions.states && + pointMarkerOptions.states[state] || {}; + [['width', 'x'], ['height', 'y']].forEach(function (dimension) { + // Set new width and height basing on state options. + attribs[dimension[0]] = (pointStateOptions[dimension[0]] || + seriesStateOptions[dimension[0]] || + shapeArgs[dimension[0]]) + (pointStateOptions[dimension[0] + 'Plus'] || + seriesStateOptions[dimension[0] + 'Plus'] || 0); + // Align marker by a new size. + attribs[dimension[1]] = shapeArgs[dimension[1]] + + (shapeArgs[dimension[0]] - attribs[dimension[0]]) / 2; + }); + } + return state ? attribs : shapeArgs; + }, + /** + * @private + * @function Highcharts.seriesTypes.heatmap#drawPoints + * @return {void} + */ + drawPoints: function () { + var _this = this; + // In styled mode, use CSS, otherwise the fill used in the style + // sheet will take precedence over the fill attribute. + var seriesMarkerOptions = this.options.marker || {}; + if (seriesMarkerOptions.enabled || this._hasPointMarkers) { + Series.prototype.drawPoints.call(this); + this.points.forEach(function (point) { + point.graphic && + point.graphic[_this.chart.styledMode ? 'css' : 'animate'](_this.colorAttribs(point)); + }); + } + }, + // Define hasData function for non-cartesian series. + // Returns true if the series has points at all. + hasData: function () { + return !!this.processedXData.length; // != 0 + }, + // Override to also allow null points, used when building the k-d-tree + // for tooltips in boost mode. + getValidPoints: function (points, insideOnly) { + return Series.prototype.getValidPoints.call(this, points, insideOnly, true); + }, + /** + * @ignore + * @deprecated + * @function Highcharts.seriesTypes.heatmap#getBox + */ + getBox: noop, + /** + * @private + * @borrows Highcharts.LegendSymbolMixin.drawRectangle as Highcharts.seriesTypes.heatmap#drawLegendSymbol + */ + drawLegendSymbol: LegendSymbolMixin.drawRectangle, + /** + * @private + * @borrows Highcharts.seriesTypes.column#alignDataLabel as Highcharts.seriesTypes.heatmap#alignDataLabel + */ + alignDataLabel: seriesTypes.column.prototype.alignDataLabel, + /** + * @private + * @function Highcharts.seriesTypes.heatmap#getExtremes + * @return {void} + */ + getExtremes: function () { + // Get the extremes from the value data + var _a = Series.prototype.getExtremes + .call(this, this.valueData), dataMin = _a.dataMin, dataMax = _a.dataMax; + if (isNumber(dataMin)) { + this.valueMin = dataMin; + } + if (isNumber(dataMax)) { + this.valueMax = dataMax; + } + // Get the extremes from the y data + return Series.prototype.getExtremes.call(this); + } + /* eslint-enable valid-jsdoc */ +}), merge(colorMapPointMixin, { + /** + * Heatmap series only. Padding between the points in the heatmap. + * @name Highcharts.Point#pointPadding + * @type {number|undefined} + */ + /** + * Heatmap series only. The value of the point, resulting in a color + * controled by options as set in the colorAxis configuration. + * @name Highcharts.Point#value + * @type {number|null|undefined} + */ + /* eslint-disable valid-jsdoc */ + /** + * @private + * @function Highcharts.Point#applyOptions + * @param {Highcharts.HeatmapPointOptions} options + * @param {number} x + * @return {Highcharts.SVGPathArray} + */ + applyOptions: function (options, x) { + var point = H.Point.prototype + .applyOptions.call(this, options, x); + point.formatPrefix = + point.isNull || point.value === null ? + 'null' : 'point'; + return point; + }, + /** + * Color points have a value option that determines whether or not it is + * a null point + * @private + * @function Highcharts.HeatmapPoint.isValid + * @return {boolean} + */ + isValid: function () { + // undefined is allowed + return (this.value !== Infinity && + this.value !== -Infinity); + }, + /** + * @private + * @function Highcharts.Point#haloPath + * @param {number} size + * @return {Highcharts.SVGPathArray} + */ + haloPath: function (size) { + if (!size) { + return []; + } + var rect = this.shapeArgs; + return [ + 'M', + rect.x - size, + rect.y - size, + 'L', + rect.x - size, + rect.y + rect.height + size, + rect.x + rect.width + size, + rect.y + rect.height + size, + rect.x + rect.width + size, + rect.y - size, + 'Z' + ]; + }, + getCellAttributes: function () { + var point = this, series = point.series, seriesOptions = series.options, xPad = (seriesOptions.colsize || 1) / 2, yPad = (seriesOptions.rowsize || 1) / 2, xAxis = series.xAxis, yAxis = series.yAxis, markerOptions = point.options.marker || series.options.marker, pointPlacement = series.pointPlacementToXValue(), // #7860 + pointPadding = pick(point.pointPadding, seriesOptions.pointPadding, 0), cellAttr = { + x1: clamp(Math.round(xAxis.len - + (xAxis.translate(point.x - xPad, false, true, false, true, -pointPlacement) || 0)), -xAxis.len, 2 * xAxis.len), + x2: clamp(Math.round(xAxis.len - + (xAxis.translate(point.x + xPad, false, true, false, true, -pointPlacement) || 0)), -xAxis.len, 2 * xAxis.len), + y1: clamp(Math.round((yAxis.translate(point.y - yPad, false, true, false, true) || 0)), -yAxis.len, 2 * yAxis.len), + y2: clamp(Math.round((yAxis.translate(point.y + yPad, false, true, false, true) || 0)), -yAxis.len, 2 * yAxis.len) + }; + // Handle marker's fixed width, and height values including border + // and pointPadding while calculating cell attributes. + [['width', 'x'], ['height', 'y']].forEach(function (dimension) { + var prop = dimension[0], direction = dimension[1]; + var start = direction + '1', end = direction + '2'; + var side = Math.abs(cellAttr[start] - cellAttr[end]), borderWidth = markerOptions && + markerOptions.lineWidth || 0, plotPos = Math.abs(cellAttr[start] + cellAttr[end]) / 2; + if (markerOptions[prop] && + markerOptions[prop] < side) { + cellAttr[start] = plotPos - (markerOptions[prop] / 2) - + (borderWidth / 2); + cellAttr[end] = plotPos + (markerOptions[prop] / 2) + + (borderWidth / 2); + } + // Handle pointPadding + if (pointPadding) { + if (direction === 'y') { + start = end; + end = direction + '1'; + } + cellAttr[start] += pointPadding; + cellAttr[end] -= pointPadding; + } + }); + return cellAttr; + } + /* eslint-enable valid-jsdoc */ +})); +/** + * A `heatmap` series. If the [type](#series.heatmap.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @productdesc {highcharts} + * Requires `modules/heatmap`. + * + * @extends series,plotOptions.heatmap + * @excluding dataParser, dataURL, pointRange, stack, + * @product highcharts highmaps + * @apioption series.heatmap + */ +/** + * An array of data points for the series. For the `heatmap` series + * type, points can be given in the following ways: + * + * 1. An array of arrays with 3 or 2 values. In this case, the values + * correspond to `x,y,value`. If the first value is a string, it is + * applied as the name of the point, and the `x` value is inferred. + * The `x` value can also be omitted, in which case the inner arrays + * should be of length 2\. Then the `x` value is automatically calculated, + * either starting at 0 and incremented by 1, or from `pointStart` + * and `pointInterval` given in the series options. + * + * ```js + * data: [ + * [0, 9, 7], + * [1, 10, 4], + * [2, 6, 3] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of data + * points exceeds the series' [turboThreshold](#series.heatmap.turboThreshold), + * this option is not available. + * + * ```js + * data: [{ + * x: 1, + * y: 3, + * value: 10, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 7, + * value: 10, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|*>} + * @extends series.line.data + * @product highcharts highmaps + * @apioption series.heatmap.data + */ +/** + * The color of the point. In heat maps the point color is rarely set + * explicitly, as we use the color to denote the `value`. Options for + * this are set in the [colorAxis](#colorAxis) configuration. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highmaps + * @apioption series.heatmap.data.color + */ +/** + * The value of the point, resulting in a color controled by options + * as set in the [colorAxis](#colorAxis) configuration. + * + * @type {number} + * @product highcharts highmaps + * @apioption series.heatmap.data.value + */ +/** + * The x value of the point. For datetime axes, + * the X value is the timestamp in milliseconds since 1970. + * + * @type {number} + * @product highcharts highmaps + * @apioption series.heatmap.data.x + */ +/** + * The y value of the point. + * + * @type {number} + * @product highcharts highmaps + * @apioption series.heatmap.data.y + */ +/** + * Point padding for a single point. + * + * @sample maps/plotoptions/tilemap-pointpadding + * Point padding on tiles + * + * @type {number} + * @product highcharts highmaps + * @apioption series.heatmap.data.pointPadding + */ +/** + * @excluding radius, enabledThreshold + * @product highcharts highmaps + * @apioption series.heatmap.data.marker + */ +/** + * @excluding radius, enabledThreshold + * @product highcharts highmaps + * @apioption series.heatmap.marker + */ +/** + * @excluding radius, radiusPlus + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.hover + */ +/** + * @excluding radius + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.select + */ +/** + * @excluding radius, radiusPlus + * @product highcharts highmaps + * @apioption series.heatmap.data.marker.states.hover + */ +/** + * @excluding radius + * @product highcharts highmaps + * @apioption series.heatmap.data.marker.states.select + */ +/** +* Set the marker's fixed width on hover state. +* +* @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-linewidthplus +* 5 pixels wider lineWidth on hover +* +* @type {number|undefined} +* @default 0 +* @product highcharts highmaps +* @apioption series.heatmap.marker.states.hover.lineWidthPlus +*/ +/** +* Set the marker's fixed width on hover state. +* +* @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width +* 70px fixed marker's width and height on hover +* +* @type {number|undefined} +* @default undefined +* @product highcharts highmaps +* @apioption series.heatmap.marker.states.hover.width +*/ +/** + * Set the marker's fixed height on hover state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.hover.height + */ +/** +* The number of pixels to increase the width of the +* hovered point. +* +* @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus +* One day +* +* @type {number|undefined} +* @default undefined +* @product highcharts highmaps +* @apioption series.heatmap.marker.states.hover.widthPlus +*/ +/** + * The number of pixels to increase the height of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.hover.heightPlus + */ +/** + * The number of pixels to increase the width of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.select.widthPlus + */ +/** + * The number of pixels to increase the height of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.select.heightPlus + */ +/** +* Set the marker's fixed width on hover state. +* +* @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-linewidthplus +* 5 pixels wider lineWidth on hover +* +* @type {number|undefined} +* @default 0 +* @product highcharts highmaps +* @apioption series.heatmap.data.marker.states.hover.lineWidthPlus +*/ +/** + * Set the marker's fixed width on hover state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.data.marker.states.hover.width + */ +/** + * Set the marker's fixed height on hover state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.data.marker.states.hover.height + */ +/** + * The number of pixels to increase the width of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highstock + * @apioption series.heatmap.data.marker.states.hover.widthPlus + */ +/** + * The number of pixels to increase the height of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highstock + * @apioption series.heatmap.data.marker.states.hover.heightPlus + */ +/** +* Set the marker's fixed width on select state. +* +* @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width +* 70px fixed marker's width and height on hover +* +* @type {number|undefined} +* @default undefined +* @product highcharts highmaps +* @apioption series.heatmap.data.marker.states.select.width +*/ +/** + * Set the marker's fixed height on select state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.data.marker.states.select.height + */ +/** + * The number of pixels to increase the width of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highstock + * @apioption series.heatmap.data.marker.states.select.widthPlus + */ +/** + * The number of pixels to increase the height of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highstock + * @apioption series.heatmap.data.marker.states.select.heightPlus + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/parts-map/Map.js b/librerias/gantt/code/es-modules/parts-map/Map.js new file mode 100644 index 0000000..a8fb9ac --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-map/Map.js @@ -0,0 +1,410 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var extend = U.extend, merge = U.merge, pick = U.pick; +import '../parts/Options.js'; +import '../parts/Chart.js'; +import '../parts/SvgRenderer.js'; +var Chart = H.Chart, defaultOptions = H.defaultOptions, Renderer = H.Renderer, SVGRenderer = H.SVGRenderer, VMLRenderer = H.VMLRenderer; +// Add language +extend(defaultOptions.lang, { + zoomIn: 'Zoom in', + zoomOut: 'Zoom out' +}); +// Set the default map navigation options +/** + * @product highmaps + * @optionparent mapNavigation + */ +defaultOptions.mapNavigation = { + /** + * General options for the map navigation buttons. Individual options + * can be given from the [mapNavigation.buttons](#mapNavigation.buttons) + * option set. + * + * @sample {highmaps} maps/mapnavigation/button-theme/ + * Theming the navigation buttons + */ + buttonOptions: { + /** + * What box to align the buttons to. Possible values are `plotBox` + * and `spacingBox`. + * + * @type {Highcharts.ButtonRelativeToValue} + */ + alignTo: 'plotBox', + /** + * The alignment of the navigation buttons. + * + * @type {Highcharts.AlignValue} + */ + align: 'left', + /** + * The vertical alignment of the buttons. Individual alignment can + * be adjusted by each button's `y` offset. + * + * @type {Highcharts.VerticalAlignValue} + */ + verticalAlign: 'top', + /** + * The X offset of the buttons relative to its `align` setting. + */ + x: 0, + /** + * The width of the map navigation buttons. + */ + width: 18, + /** + * The pixel height of the map navigation buttons. + */ + height: 18, + /** + * Padding for the navigation buttons. + * + * @since 5.0.0 + */ + padding: 5, + /** + * Text styles for the map navigation buttons. + * + * @type {Highcharts.CSSObject} + * @default {"fontSize": "15px", "fontWeight": "bold"} + */ + style: { + /** @ignore */ + fontSize: '15px', + /** @ignore */ + fontWeight: 'bold' + }, + /** + * A configuration object for the button theme. The object accepts + * SVG properties like `stroke-width`, `stroke` and `fill`. Tri-state + * button styles are supported by the `states.hover` and `states.select` + * objects. + * + * @sample {highmaps} maps/mapnavigation/button-theme/ + * Themed navigation buttons + * + * @type {Highcharts.SVGAttributes} + * @default {"stroke-width": 1, "text-align": "center"} + */ + theme: { + /** @ignore */ + 'stroke-width': 1, + /** @ignore */ + 'text-align': 'center' + } + }, + /** + * The individual buttons for the map navigation. This usually includes + * the zoom in and zoom out buttons. Properties for each button is + * inherited from + * [mapNavigation.buttonOptions](#mapNavigation.buttonOptions), while + * individual options can be overridden. But default, the `onclick`, `text` + * and `y` options are individual. + */ + buttons: { + /** + * Options for the zoom in button. Properties for the zoom in and zoom + * out buttons are inherited from + * [mapNavigation.buttonOptions](#mapNavigation.buttonOptions), while + * individual options can be overridden. By default, the `onclick`, + * `text` and `y` options are individual. + * + * @extends mapNavigation.buttonOptions + */ + zoomIn: { + // eslint-disable-next-line valid-jsdoc + /** + * Click handler for the button. + * + * @type {Function} + * @default function () { this.mapZoom(0.5); } + */ + onclick: function () { + this.mapZoom(0.5); + }, + /** + * The text for the button. The tooltip (title) is a language option + * given by [lang.zoomIn](#lang.zoomIn). + */ + text: '+', + /** + * The position of the zoomIn button relative to the vertical + * alignment. + */ + y: 0 + }, + /** + * Options for the zoom out button. Properties for the zoom in and + * zoom out buttons are inherited from + * [mapNavigation.buttonOptions](#mapNavigation.buttonOptions), while + * individual options can be overridden. By default, the `onclick`, + * `text` and `y` options are individual. + * + * @extends mapNavigation.buttonOptions + */ + zoomOut: { + // eslint-disable-next-line valid-jsdoc + /** + * Click handler for the button. + * + * @type {Function} + * @default function () { this.mapZoom(2); } + */ + onclick: function () { + this.mapZoom(2); + }, + /** + * The text for the button. The tooltip (title) is a language option + * given by [lang.zoomOut](#lang.zoomIn). + */ + text: '-', + /** + * The position of the zoomOut button relative to the vertical + * alignment. + */ + y: 28 + } + }, + /** + * Whether to enable navigation buttons. By default it inherits the + * [enabled](#mapNavigation.enabled) setting. + * + * @type {boolean} + * @apioption mapNavigation.enableButtons + */ + /** + * Whether to enable map navigation. The default is not to enable + * navigation, as many choropleth maps are simple and don't need it. + * Additionally, when touch zoom and mousewheel zoom is enabled, it breaks + * the default behaviour of these interactions in the website, and the + * implementer should be aware of this. + * + * Individual interactions can be enabled separately, namely buttons, + * multitouch zoom, double click zoom, double click zoom to element and + * mousewheel zoom. + * + * @type {boolean} + * @default false + * @apioption mapNavigation.enabled + */ + /** + * Enables zooming in on an area on double clicking in the map. By default + * it inherits the [enabled](#mapNavigation.enabled) setting. + * + * @type {boolean} + * @apioption mapNavigation.enableDoubleClickZoom + */ + /** + * Whether to zoom in on an area when that area is double clicked. + * + * @sample {highmaps} maps/mapnavigation/doubleclickzoomto/ + * Enable double click zoom to + * + * @type {boolean} + * @default false + * @apioption mapNavigation.enableDoubleClickZoomTo + */ + /** + * Enables zooming by mouse wheel. By default it inherits the [enabled]( + * #mapNavigation.enabled) setting. + * + * @type {boolean} + * @apioption mapNavigation.enableMouseWheelZoom + */ + /** + * Whether to enable multitouch zooming. Note that if the chart covers the + * viewport, this prevents the user from using multitouch and touchdrag on + * the web page, so you should make sure the user is not trapped inside the + * chart. By default it inherits the [enabled](#mapNavigation.enabled) + * setting. + * + * @type {boolean} + * @apioption mapNavigation.enableTouchZoom + */ + /** + * Sensitivity of mouse wheel or trackpad scrolling. 1 is no sensitivity, + * while with 2, one mousewheel delta will zoom in 50%. + * + * @since 4.2.4 + */ + mouseWheelSensitivity: 1.1 + // enabled: false, + // enableButtons: null, // inherit from enabled + // enableTouchZoom: null, // inherit from enabled + // enableDoubleClickZoom: null, // inherit from enabled + // enableDoubleClickZoomTo: false + // enableMouseWheelZoom: null, // inherit from enabled +}; +/* eslint-disable valid-jsdoc */ +/** + * Utility for reading SVG paths directly. + * + * @requires modules/map + * + * @function Highcharts.splitPath + * + * @param {string|Array} path + * + * @return {Highcharts.SVGPathArray} + */ +H.splitPath = function (path) { + var arr; + if (typeof path === 'string') { + path = path + // Move letters apart + .replace(/([A-Za-z])/g, ' $1 ') + // Trim + .replace(/^\s*/, '').replace(/\s*$/, ''); + // Split on spaces and commas. The semicolon is bogus, designed to + // circumvent string replacement in the pre-v7 assembler that built + // specific styled mode files. + var split = path.split(/[ ,;]+/); + arr = split.map(function (item) { + if (!/[A-za-z]/.test(item)) { + return parseFloat(item); + } + return item; + }); + } + else { + arr = path; + } + return SVGRenderer.prototype.pathToSegments(arr); +}; +/** + * Contains all loaded map data for Highmaps. + * + * @requires modules/map + * + * @name Highcharts.maps + * @type {Highcharts.Dictionary<*>} + */ +H.maps = {}; +/** + * Create symbols for the zoom buttons + * @private + */ +function selectiveRoundedRect(x, y, w, h, rTopLeft, rTopRight, rBottomRight, rBottomLeft) { + return [ + ['M', x + rTopLeft, y], + // top side + ['L', x + w - rTopRight, y], + // top right corner + ['C', x + w - rTopRight / 2, y, x + w, y + rTopRight / 2, x + w, y + rTopRight], + // right side + ['L', x + w, y + h - rBottomRight], + // bottom right corner + ['C', x + w, y + h - rBottomRight / 2, x + w - rBottomRight / 2, y + h, x + w - rBottomRight, y + h], + // bottom side + ['L', x + rBottomLeft, y + h], + // bottom left corner + ['C', x + rBottomLeft / 2, y + h, x, y + h - rBottomLeft / 2, x, y + h - rBottomLeft], + // left side + ['L', x, y + rTopLeft], + // top left corner + ['C', x, y + rTopLeft / 2, x + rTopLeft / 2, y, x + rTopLeft, y], + ['Z'] + ]; +} +SVGRenderer.prototype.symbols.topbutton = function (x, y, w, h, attr) { + return selectiveRoundedRect(x - 1, y - 1, w, h, attr.r, attr.r, 0, 0); +}; +SVGRenderer.prototype.symbols.bottombutton = function (x, y, w, h, attr) { + return selectiveRoundedRect(x - 1, y - 1, w, h, 0, 0, attr.r, attr.r); +}; +// The symbol callbacks are generated on the SVGRenderer object in all browsers. +// Even VML browsers need this in order to generate shapes in export. Now share +// them with the VMLRenderer. +if (Renderer === VMLRenderer) { + ['topbutton', 'bottombutton'].forEach(function (shape) { + VMLRenderer.prototype.symbols[shape] = + SVGRenderer.prototype.symbols[shape]; + }); +} +/** + * The factory function for creating new map charts. Creates a new {@link + * Highcharts.Chart|Chart} object with different default options than the basic + * Chart. + * + * @requires modules/map + * + * @function Highcharts.mapChart + * + * @param {string|Highcharts.HTMLDOMElement} [renderTo] + * The DOM element to render to, or its id. + * + * @param {Highcharts.Options} options + * The chart options structure as described in the + * [options reference](https://api.highcharts.com/highstock). + * + * @param {Highcharts.ChartCallbackFunction} [callback] + * A function to execute when the chart object is finished loading and + * rendering. In most cases the chart is built in one thread, but in + * Internet Explorer version 8 or less the chart is sometimes + * initialized before the document is ready, and in these cases the + * chart object will not be finished synchronously. As a consequence, + * code that relies on the newly built Chart object should always run in + * the callback. Defining a + * [chart.events.load](https://api.highcharts.com/highstock/chart.events.load) + * handler is equivalent. + * + * @return {Highcharts.Chart} + * The chart object. + */ +H.Map = H.mapChart = function (a, b, c) { + var hasRenderToArg = typeof a === 'string' || a.nodeName, options = arguments[hasRenderToArg ? 1 : 0], userOptions = options, hiddenAxis = { + endOnTick: false, + visible: false, + minPadding: 0, + maxPadding: 0, + startOnTick: false + }, seriesOptions, defaultCreditsOptions = H.getOptions().credits; + /* For visual testing + hiddenAxis.gridLineWidth = 1; + hiddenAxis.gridZIndex = 10; + hiddenAxis.tickPositions = undefined; + // */ + // Don't merge the data + seriesOptions = options.series; + options.series = null; + options = merge({ + chart: { + panning: { + enabled: true, + type: 'xy' + }, + type: 'map' + }, + credits: { + mapText: pick(defaultCreditsOptions.mapText, ' \u00a9 ' + + '{geojson.copyrightShort}'), + mapTextFull: pick(defaultCreditsOptions.mapTextFull, '{geojson.copyright}') + }, + tooltip: { + followTouchMove: false + }, + xAxis: hiddenAxis, + yAxis: merge(hiddenAxis, { reversed: true }) + }, options, // user's options + { + chart: { + inverted: false, + alignTicks: false + } + }); + options.series = userOptions.series = seriesOptions; + return hasRenderToArg ? + new Chart(a, options, c) : + new Chart(options, b); +}; diff --git a/librerias/gantt/code/es-modules/parts-map/MapAxis.js b/librerias/gantt/code/es-modules/parts-map/MapAxis.js new file mode 100644 index 0000000..692e8c0 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-map/MapAxis.js @@ -0,0 +1,157 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Axis from '../parts/Axis.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, pick = U.pick; +/** + * Map support for axes. + * @private + * @class + */ +var MapAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function MapAxisAdditions(axis) { + this.axis = axis; + } + return MapAxisAdditions; +}()); +/** + * Axis with map support. + * @private + * @class + */ +var MapAxis = /** @class */ (function () { + function MapAxis() { + } + /** + * Extends axes with map support. + * @private + * + * @param {Highcharts.Axis} AxisClass + * Axis class to extend. + */ + MapAxis.compose = function (AxisClass) { + AxisClass.keepProps.push('mapAxis'); + /* eslint-disable no-invalid-this */ + addEvent(AxisClass, 'init', function () { + var axis = this; + if (!axis.mapAxis) { + axis.mapAxis = new MapAxisAdditions(axis); + } + }); + // Override to use the extreme coordinates from the SVG shape, not the + // data values + addEvent(AxisClass, 'getSeriesExtremes', function () { + if (!this.mapAxis) { + return; + } + var axis = this; + var xData = []; + // Remove the xData array and cache it locally so that the proceed + // method doesn't use it + if (axis.isXAxis) { + axis.series.forEach(function (series, i) { + if (series.useMapGeometry) { + xData[i] = series.xData; + series.xData = []; + } + }); + axis.mapAxis.seriesXData = xData; + } + }); + addEvent(AxisClass, 'afterGetSeriesExtremes', function () { + if (!this.mapAxis) { + return; + } + var axis = this; + var xData = axis.mapAxis.seriesXData || []; + var dataMin, dataMax, useMapGeometry; + // Run extremes logic for map and mapline + if (axis.isXAxis) { + dataMin = pick(axis.dataMin, Number.MAX_VALUE); + dataMax = pick(axis.dataMax, -Number.MAX_VALUE); + axis.series.forEach(function (series, i) { + if (series.useMapGeometry) { + dataMin = Math.min(dataMin, pick(series.minX, dataMin)); + dataMax = Math.max(dataMax, pick(series.maxX, dataMax)); + series.xData = xData[i]; // Reset xData array + useMapGeometry = true; + } + }); + if (useMapGeometry) { + axis.dataMin = dataMin; + axis.dataMax = dataMax; + } + axis.mapAxis.seriesXData = void 0; + } + }); + // Override axis translation to make sure the aspect ratio is always + // kept + addEvent(AxisClass, 'afterSetAxisTranslation', function () { + if (!this.mapAxis) { + return; + } + var axis = this; + var chart = axis.chart; + var plotRatio = chart.plotWidth / chart.plotHeight; + var xAxis = chart.xAxis[0]; + var mapRatio, adjustedAxisLength, padAxis, fixTo, fixDiff, preserveAspectRatio; + // Check for map-like series + if (axis.coll === 'yAxis' && typeof xAxis.transA !== 'undefined') { + axis.series.forEach(function (series) { + if (series.preserveAspectRatio) { + preserveAspectRatio = true; + } + }); + } + // On Y axis, handle both + if (preserveAspectRatio) { + // Use the same translation for both axes + axis.transA = xAxis.transA = Math.min(axis.transA, xAxis.transA); + mapRatio = plotRatio / ((xAxis.max - xAxis.min) / + (axis.max - axis.min)); + // What axis to pad to put the map in the middle + padAxis = mapRatio < 1 ? axis : xAxis; + // Pad it + adjustedAxisLength = + (padAxis.max - padAxis.min) * padAxis.transA; + padAxis.mapAxis.pixelPadding = padAxis.len - adjustedAxisLength; + padAxis.minPixelPadding = padAxis.mapAxis.pixelPadding / 2; + fixTo = padAxis.mapAxis.fixTo; + if (fixTo) { + fixDiff = fixTo[1] - padAxis.toValue(fixTo[0], true); + fixDiff *= padAxis.transA; + if (Math.abs(fixDiff) > padAxis.minPixelPadding || + (padAxis.min === padAxis.dataMin && + padAxis.max === padAxis.dataMax)) { // zooming out again, keep within restricted area + fixDiff = 0; + } + padAxis.minPixelPadding -= fixDiff; + } + } + }); + // Override Axis.render in order to delete the fixTo prop + addEvent(AxisClass, 'render', function () { + var axis = this; + if (axis.mapAxis) { + axis.mapAxis.fixTo = void 0; + } + }); + /* eslint-enable no-invalid-this */ + }; + return MapAxis; +}()); +MapAxis.compose(Axis); // @todo move to factory functions +export default MapAxis; diff --git a/librerias/gantt/code/es-modules/parts-map/MapBubbleSeries.js b/librerias/gantt/code/es-modules/parts-map/MapBubbleSeries.js new file mode 100644 index 0000000..5e3e87d --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-map/MapBubbleSeries.js @@ -0,0 +1,244 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import Point from '../parts/Point.js'; +import U from '../parts/Utilities.js'; +var merge = U.merge, seriesType = U.seriesType; +import '../parts/Options.js'; +import '../parts-more/BubbleSeries.js'; +var seriesTypes = H.seriesTypes; +// The mapbubble series type +if (seriesTypes.bubble) { + /** + * @private + * @class + * @name Highcharts.seriesTypes.mapbubble + * + * @augments Highcharts.Series + */ + seriesType('mapbubble', 'bubble' + /** + * A map bubble series is a bubble series laid out on top of a map + * series, where each bubble is tied to a specific map area. + * + * @sample maps/demo/map-bubble/ + * Map bubble chart + * + * @extends plotOptions.bubble + * @product highmaps + * @optionparent plotOptions.mapbubble + */ + , { + /** + * The main color of the series. This color affects both the fill + * and the stroke of the bubble. For enhanced control, use `marker` + * options. + * + * @sample {highmaps} maps/plotoptions/mapbubble-color/ + * Pink bubbles + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.mapbubble.color + */ + /** + * Whether to display negative sized bubbles. The threshold is + * given by the [zThreshold](#plotOptions.mapbubble.zThreshold) + * option, and negative bubbles can be visualized by setting + * [negativeColor](#plotOptions.bubble.negativeColor). + * + * @type {boolean} + * @default true + * @apioption plotOptions.mapbubble.displayNegative + */ + /** + * @sample {highmaps} maps/demo/map-bubble/ + * Bubble size + * + * @apioption plotOptions.mapbubble.maxSize + */ + /** + * @sample {highmaps} maps/demo/map-bubble/ + * Bubble size + * + * @apioption plotOptions.mapbubble.minSize + */ + /** + * When a point's Z value is below the + * [zThreshold](#plotOptions.mapbubble.zThreshold) setting, this + * color is used. + * + * @sample {highmaps} maps/plotoptions/mapbubble-negativecolor/ + * Negative color below a threshold + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.mapbubble.negativeColor + */ + /** + * Whether the bubble's value should be represented by the area or + * the width of the bubble. The default, `area`, corresponds best to + * the human perception of the size of each bubble. + * + * @type {Highcharts.BubbleSizeByValue} + * @default area + * @apioption plotOptions.mapbubble.sizeBy + */ + /** + * When this is true, the absolute value of z determines the size + * of the bubble. This means that with the default `zThreshold` of + * 0, a bubble of value -1 will have the same size as a bubble of + * value 1, while a bubble of value 0 will have a smaller size + * according to `minSize`. + * + * @sample {highmaps} highcharts/plotoptions/bubble-sizebyabsolutevalue/ + * Size by absolute value, various thresholds + * + * @type {boolean} + * @default false + * @since 1.1.9 + * @apioption plotOptions.mapbubble.sizeByAbsoluteValue + */ + /** + * The minimum for the Z value range. Defaults to the highest Z + * value in the data. + * + * @see [zMax](#plotOptions.mapbubble.zMin) + * + * @sample {highmaps} highcharts/plotoptions/bubble-zmin-zmax/ + * Z has a possible range of 0-100 + * + * @type {number} + * @since 1.0.3 + * @apioption plotOptions.mapbubble.zMax + */ + /** + * The minimum for the Z value range. Defaults to the lowest Z value + * in the data. + * + * @see [zMax](#plotOptions.mapbubble.zMax) + * + * @sample {highmaps} highcharts/plotoptions/bubble-zmin-zmax/ + * Z has a possible range of 0-100 + * + * @type {number} + * @since 1.0.3 + * @apioption plotOptions.mapbubble.zMin + */ + /** + * When [displayNegative](#plotOptions.mapbubble.displayNegative) + * is `false`, bubbles with lower Z values are skipped. When + * `displayNegative` is `true` and a + * [negativeColor](#plotOptions.mapbubble.negativeColor) is given, + * points with lower Z is colored. + * + * @sample {highmaps} maps/plotoptions/mapbubble-negativecolor/ + * Negative color below a threshold + * + * @type {number} + * @default 0 + * @apioption plotOptions.mapbubble.zThreshold + */ + animationLimit: 500, + tooltip: { + pointFormat: '{point.name}: {point.z}' + } + // Prototype members + }, { + xyFromShape: true, + type: 'mapbubble', + // If one single value is passed, it is interpreted as z + pointArrayMap: ['z'], + // Return the map area identified by the dataJoinBy option + getMapData: seriesTypes.map.prototype.getMapData, + getBox: seriesTypes.map.prototype.getBox, + setData: seriesTypes.map.prototype.setData, + setOptions: seriesTypes.map.prototype.setOptions + // Point class + }, { + applyOptions: function (options, x) { + var point; + if (options && + typeof options.lat !== 'undefined' && + typeof options.lon !== 'undefined') { + point = Point.prototype.applyOptions.call(this, merge(options, this.series.chart.fromLatLonToPoint(options)), x); + } + else { + point = seriesTypes.map.prototype.pointClass.prototype + .applyOptions.call(this, options, x); + } + return point; + }, + isValid: function () { + return typeof this.z === 'number'; + }, + ttBelow: false + }); +} +/** + * A `mapbubble` series. If the [type](#series.mapbubble.type) option + * is not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.mapbubble + * @excluding dataParser, dataURL + * @product highmaps + * @apioption series.mapbubble + */ +/** + * An array of data points for the series. For the `mapbubble` series + * type, points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values + * will be interpreted as `z` options. Example: + * + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.mapbubble.turboThreshold), + * this option is not available. + * + * ```js + * data: [{ + * z: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * z: 10, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @type {Array} + * @extends series.mappoint.data + * @excluding labelrank, middleX, middleY, path, value, x, y, lat, lon + * @product highmaps + * @apioption series.mapbubble.data + */ +/** + * While the `x` and `y` values of the bubble are determined by the + * underlying map, the `z` indicates the actual value that gives the + * size of the bubble. + * + * @sample {highmaps} maps/demo/map-bubble/ + * Bubble + * + * @type {number|null} + * @product highmaps + * @apioption series.mapbubble.data.z + */ +/** + * @excluding enabled, enabledThreshold, height, radius, width + * @apioption series.mapbubble.marker + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/parts-map/MapLineSeries.js b/librerias/gantt/code/es-modules/parts-map/MapLineSeries.js new file mode 100644 index 0000000..0e83c67 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-map/MapLineSeries.js @@ -0,0 +1,127 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var seriesType = U.seriesType; +import '../parts/Options.js'; +var seriesTypes = H.seriesTypes; +/** + * @private + * @class + * @name Highcharts.seriesTypes.mapline + * + * @augments Highcharts.Series + */ +seriesType('mapline', 'map', +/** + * A mapline series is a special case of the map series where the value + * colors are applied to the strokes rather than the fills. It can also be + * used for freeform drawing, like dividers, in the map. + * + * @sample maps/demo/mapline-mappoint/ + * Mapline and map-point chart + * + * @extends plotOptions.map + * @product highmaps + * @optionparent plotOptions.mapline + */ +{ + /** + * The width of the map line. + */ + lineWidth: 1, + /** + * Fill color for the map line shapes + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + fillColor: 'none' +}, { + type: 'mapline', + colorProp: 'stroke', + pointAttrToOptions: { + 'stroke': 'color', + 'stroke-width': 'lineWidth' + }, + /* eslint-disable valid-jsdoc */ + /** + * Get presentational attributes + * + * @private + * @function Highcharts.seriesTypes.mapline#pointAttribs + * @param {Highcharts.Point} point + * @param {string} state + * @return {Highcharts.SVGAttributes} + */ + pointAttribs: function (point, state) { + var attr = seriesTypes.map.prototype.pointAttribs.call(this, point, state); + // The difference from a map series is that the stroke takes the + // point color + attr.fill = this.options.fillColor; + return attr; + }, + drawLegendSymbol: seriesTypes.line.prototype.drawLegendSymbol + /* eslint-enable valid-jsdoc */ +}); +/** + * A `mapline` series. If the [type](#series.mapline.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.mapline + * @excluding dataParser, dataURL, marker + * @product highmaps + * @apioption series.mapline + */ +/** + * An array of data points for the series. For the `mapline` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values + * will be interpreted as `value` options. Example: + * + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond + * to `[hc-key, value]`. Example: + * + * ```js + * data: [ + * ['us-ny', 0], + * ['us-mi', 5], + * ['us-tx', 3], + * ['us-ak', 5] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of data + * points exceeds the series' [turboThreshold](#series.map.turboThreshold), + * this option is not available. + * + * ```js + * data: [{ + * value: 6, + * name: "Point2", + * color: "#00FF00" + * }, { + * value: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @type {Array|null|*>} + * @product highmaps + * @apioption series.mapline.data + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/parts-map/MapNavigation.js b/librerias/gantt/code/es-modules/parts-map/MapNavigation.js new file mode 100644 index 0000000..cb0c95d --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-map/MapNavigation.js @@ -0,0 +1,301 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, extend = U.extend, merge = U.merge, objectEach = U.objectEach, pick = U.pick; +import '../parts/Chart.js'; +var Chart = H.Chart, doc = H.doc; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * @private + */ +function stopEvent(e) { + if (e) { + if (e.preventDefault) { + e.preventDefault(); + } + if (e.stopPropagation) { + e.stopPropagation(); + } + e.cancelBubble = true; + } +} +/** + * The MapNavigation handles buttons for navigation in addition to mousewheel + * and doubleclick handlers for chart zooming. + * + * @private + * @class + * @name MapNavigation + * + * @param {Highcharts.Chart} chart + * The Chart instance. + */ +function MapNavigation(chart) { + this.init(chart); +} +/** + * Initialize function. + * + * @function MapNavigation#init + * + * @param {Highcharts.Chart} chart + * The Chart instance. + * + * @return {void} + */ +MapNavigation.prototype.init = function (chart) { + this.chart = chart; + chart.mapNavButtons = []; +}; +/** + * Update the map navigation with new options. Calling this is the same as + * calling `chart.update({ mapNavigation: {} })`. + * + * @function MapNavigation#update + * + * @param {Highcharts.MapNavigationOptions} [options] + * New options for the map navigation. + * + * @return {void} + */ +MapNavigation.prototype.update = function (options) { + var chart = this.chart, o = chart.options.mapNavigation, buttonOptions, attr, states, hoverStates, selectStates, outerHandler = function (e) { + this.handler.call(chart, e); + stopEvent(e); // Stop default click event (#4444) + }, mapNavButtons = chart.mapNavButtons; + // Merge in new options in case of update, and register back to chart + // options. + if (options) { + o = chart.options.mapNavigation = + merge(chart.options.mapNavigation, options); + } + // Destroy buttons in case of dynamic update + while (mapNavButtons.length) { + mapNavButtons.pop().destroy(); + } + if (pick(o.enableButtons, o.enabled) && !chart.renderer.forExport) { + objectEach(o.buttons, function (button, n) { + buttonOptions = merge(o.buttonOptions, button); + // Presentational + if (!chart.styledMode) { + attr = buttonOptions.theme; + attr.style = merge(buttonOptions.theme.style, buttonOptions.style // #3203 + ); + states = attr.states; + hoverStates = states && states.hover; + selectStates = states && states.select; + } + button = chart.renderer + .button(buttonOptions.text, 0, 0, outerHandler, attr, hoverStates, selectStates, 0, n === 'zoomIn' ? 'topbutton' : 'bottombutton') + .addClass('highcharts-map-navigation highcharts-' + { + zoomIn: 'zoom-in', + zoomOut: 'zoom-out' + }[n]) + .attr({ + width: buttonOptions.width, + height: buttonOptions.height, + title: chart.options.lang[n], + padding: buttonOptions.padding, + zIndex: 5 + }) + .add(); + button.handler = buttonOptions.onclick; + // Stop double click event (#4444) + addEvent(button.element, 'dblclick', stopEvent); + mapNavButtons.push(button); + // Align it after the plotBox is known (#12776) + var bo = buttonOptions; + var un = addEvent(chart, 'load', function () { + button.align(extend(bo, { + width: button.width, + height: 2 * button.height + }), null, bo.alignTo); + un(); + }); + }); + } + this.updateEvents(o); +}; +/** + * Update events, called internally from the update function. Add new event + * handlers, or unbinds events if disabled. + * + * @function MapNavigation#updateEvents + * + * @param {Highcharts.MapNavigationOptions} options + * Options for map navigation. + * + * @return {void} + */ +MapNavigation.prototype.updateEvents = function (options) { + var chart = this.chart; + // Add the double click event + if (pick(options.enableDoubleClickZoom, options.enabled) || + options.enableDoubleClickZoomTo) { + this.unbindDblClick = this.unbindDblClick || addEvent(chart.container, 'dblclick', function (e) { + chart.pointer.onContainerDblClick(e); + }); + } + else if (this.unbindDblClick) { + // Unbind and set unbinder to undefined + this.unbindDblClick = this.unbindDblClick(); + } + // Add the mousewheel event + if (pick(options.enableMouseWheelZoom, options.enabled)) { + this.unbindMouseWheel = this.unbindMouseWheel || addEvent(chart.container, typeof doc.onmousewheel === 'undefined' ? + 'DOMMouseScroll' : 'mousewheel', function (e) { + chart.pointer.onContainerMouseWheel(e); + // Issue #5011, returning false from non-jQuery event does + // not prevent default + stopEvent(e); + return false; + }); + } + else if (this.unbindMouseWheel) { + // Unbind and set unbinder to undefined + this.unbindMouseWheel = this.unbindMouseWheel(); + } +}; +// Add events to the Chart object itself +extend(Chart.prototype, /** @lends Chart.prototype */ { + /** + * Fit an inner box to an outer. If the inner box overflows left or right, + * align it to the sides of the outer. If it overflows both sides, fit it + * within the outer. This is a pattern that occurs more places in + * Highcharts, perhaps it should be elevated to a common utility function. + * + * @ignore + * @function Highcharts.Chart#fitToBox + * + * @param {Highcharts.BBoxObject} inner + * + * @param {Highcharts.BBoxObject} outer + * + * @return {Highcharts.BBoxObject} + * The inner box + */ + fitToBox: function (inner, outer) { + [['x', 'width'], ['y', 'height']].forEach(function (dim) { + var pos = dim[0], size = dim[1]; + if (inner[pos] + inner[size] > + outer[pos] + outer[size]) { // right + // the general size is greater, fit fully to outer + if (inner[size] > outer[size]) { + inner[size] = outer[size]; + inner[pos] = outer[pos]; + } + else { // align right + inner[pos] = outer[pos] + + outer[size] - inner[size]; + } + } + if (inner[size] > outer[size]) { + inner[size] = outer[size]; + } + if (inner[pos] < outer[pos]) { + inner[pos] = outer[pos]; + } + }); + return inner; + }, + /** + * Highmaps only. Zoom in or out of the map. See also {@link Point#zoomTo}. + * See {@link Chart#fromLatLonToPoint} for how to get the `centerX` and + * `centerY` parameters for a geographic location. + * + * @function Highcharts.Chart#mapZoom + * + * @param {number} [howMuch] + * How much to zoom the map. Values less than 1 zooms in. 0.5 zooms + * in to half the current view. 2 zooms to twice the current view. If + * omitted, the zoom is reset. + * + * @param {number} [centerX] + * The X axis position to center around if available space. + * + * @param {number} [centerY] + * The Y axis position to center around if available space. + * + * @param {number} [mouseX] + * Fix the zoom to this position if possible. This is used for + * example in mousewheel events, where the area under the mouse + * should be fixed as we zoom in. + * + * @param {number} [mouseY] + * Fix the zoom to this position if possible. + * + * @return {void} + */ + mapZoom: function (howMuch, centerXArg, centerYArg, mouseX, mouseY) { + var chart = this, xAxis = chart.xAxis[0], xRange = xAxis.max - xAxis.min, centerX = pick(centerXArg, xAxis.min + xRange / 2), newXRange = xRange * howMuch, yAxis = chart.yAxis[0], yRange = yAxis.max - yAxis.min, centerY = pick(centerYArg, yAxis.min + yRange / 2), newYRange = yRange * howMuch, fixToX = mouseX ? ((mouseX - xAxis.pos) / xAxis.len) : 0.5, fixToY = mouseY ? ((mouseY - yAxis.pos) / yAxis.len) : 0.5, newXMin = centerX - newXRange * fixToX, newYMin = centerY - newYRange * fixToY, newExt = chart.fitToBox({ + x: newXMin, + y: newYMin, + width: newXRange, + height: newYRange + }, { + x: xAxis.dataMin, + y: yAxis.dataMin, + width: xAxis.dataMax - xAxis.dataMin, + height: yAxis.dataMax - yAxis.dataMin + }), zoomOut = (newExt.x <= xAxis.dataMin && + newExt.width >= + xAxis.dataMax - xAxis.dataMin && + newExt.y <= yAxis.dataMin && + newExt.height >= yAxis.dataMax - yAxis.dataMin); + // When mousewheel zooming, fix the point under the mouse + if (mouseX && xAxis.mapAxis) { + xAxis.mapAxis.fixTo = [mouseX - xAxis.pos, centerXArg]; + } + if (mouseY && yAxis.mapAxis) { + yAxis.mapAxis.fixTo = [mouseY - yAxis.pos, centerYArg]; + } + // Zoom + if (typeof howMuch !== 'undefined' && !zoomOut) { + xAxis.setExtremes(newExt.x, newExt.x + newExt.width, false); + yAxis.setExtremes(newExt.y, newExt.y + newExt.height, false); + // Reset zoom + } + else { + xAxis.setExtremes(void 0, void 0, false); + yAxis.setExtremes(void 0, void 0, false); + } + // Prevent zooming until this one is finished animating + /* + chart.holdMapZoom = true; + setTimeout(function () { + chart.holdMapZoom = false; + }, 200); + */ + /* + delay = animation ? animation.duration || 500 : 0; + if (delay) { + chart.isMapZooming = true; + setTimeout(function () { + chart.isMapZooming = false; + if (chart.mapZoomQueue) { + chart.mapZoom.apply(chart, chart.mapZoomQueue); + } + chart.mapZoomQueue = null; + }, delay); + } + */ + chart.redraw(); + } +}); +// Extend the Chart.render method to add zooming and panning +addEvent(Chart, 'beforeRender', function () { + // Render the plus and minus buttons. Doing this before the shapes makes + // getBBox much quicker, at least in Chrome. + this.mapNavigation = new MapNavigation(this); + this.mapNavigation.update(); +}); +H.MapNavigation = MapNavigation; diff --git a/librerias/gantt/code/es-modules/parts-map/MapPointSeries.js b/librerias/gantt/code/es-modules/parts-map/MapPointSeries.js new file mode 100644 index 0000000..ed71e59 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-map/MapPointSeries.js @@ -0,0 +1,174 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import '../parts/Utilities.js'; +import '../parts/Options.js'; +import '../parts/Point.js'; +import '../parts/ScatterSeries.js'; +var merge = H.merge, Point = H.Point, Series = H.Series, seriesType = H.seriesType; +/** + * @private + * @class + * @name Highcharts.seriesTypes.mappoint + * + * @augments Highcharts.Series + */ +seriesType('mappoint', 'scatter', +/** + * A mappoint series is a special form of scatter series where the points + * can be laid out in map coordinates on top of a map. + * + * @sample maps/demo/mapline-mappoint/ + * Map-line and map-point series. + * + * @extends plotOptions.scatter + * @product highmaps + * @optionparent plotOptions.mappoint + */ +{ + dataLabels: { + crop: false, + defer: false, + enabled: true, + formatter: function () { + return this.point.name; + }, + overflow: false, + style: { + /** @internal */ + color: '#000000' + } + } + // Prototype members +}, { + type: 'mappoint', + forceDL: true, + drawDataLabels: function () { + Series.prototype.drawDataLabels.call(this); + if (this.dataLabelsGroup) { + this.dataLabelsGroup.clip(this.chart.clipRect); + } + } + // Point class +}, { + applyOptions: function (options, x) { + var mergedOptions = (typeof options.lat !== 'undefined' && + typeof options.lon !== 'undefined' ? + merge(options, this.series.chart.fromLatLonToPoint(options)) : + options); + return Point.prototype + .applyOptions.call(this, mergedOptions, x); + } +}); +/** + * A `mappoint` series. If the [type](#series.mappoint.type) option + * is not specified, it is inherited from [chart.type](#chart.type). + * + * + * @extends series,plotOptions.mappoint + * @excluding dataParser, dataURL + * @product highmaps + * @apioption series.mappoint + */ +/** + * An array of data points for the series. For the `mappoint` series + * type, points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 1], + * [1, 8], + * [2, 7] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.mappoint.turboThreshold), + * this option is not available. + * ```js + * data: [{ + * x: 1, + * y: 7, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 4, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @type {Array|null|*>} + * @extends series.map.data + * @excluding labelrank, middleX, middleY, path, value + * @product highmaps + * @apioption series.mappoint.data + */ +/** + * The latitude of the point. Must be combined with the `lon` option + * to work. Overrides `x` and `y` values. + * + * @sample {highmaps} maps/demo/mappoint-latlon/ + * Point position by lat/lon + * + * @type {number} + * @since 1.1.0 + * @product highmaps + * @apioption series.mappoint.data.lat + */ +/** + * The longitude of the point. Must be combined with the `lon` option + * to work. Overrides `x` and `y` values. + * + * @sample {highmaps} maps/demo/mappoint-latlon/ + * Point position by lat/lon + * + * @type {number} + * @since 1.1.0 + * @product highmaps + * @apioption series.mappoint.data.lon + */ +/** + * The x coordinate of the point in terms of the map path coordinates. + * + * @sample {highmaps} maps/demo/mapline-mappoint/ + * Map point demo + * + * @type {number} + * @product highmaps + * @apioption series.mappoint.data.x + */ +/** + * The x coordinate of the point in terms of the map path coordinates. + * + * @sample {highmaps} maps/demo/mapline-mappoint/ + * Map point demo + * + * @type {number|null} + * @product highmaps + * @apioption series.mappoint.data.y + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/parts-map/MapPointer.js b/librerias/gantt/code/es-modules/parts-map/MapPointer.js new file mode 100644 index 0000000..d8075c5 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-map/MapPointer.js @@ -0,0 +1,62 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var extend = U.extend, pick = U.pick, wrap = U.wrap; +import '../parts/Pointer.js'; +var Pointer = H.Pointer; +/* eslint-disable no-invalid-this */ +// Extend the Pointer +extend(Pointer.prototype, { + // The event handler for the doubleclick event + onContainerDblClick: function (e) { + var chart = this.chart; + e = this.normalize(e); + if (chart.options.mapNavigation.enableDoubleClickZoomTo) { + if (chart.pointer.inClass(e.target, 'highcharts-tracker') && + chart.hoverPoint) { + chart.hoverPoint.zoomTo(); + } + } + else if (chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop)) { + chart.mapZoom(0.5, chart.xAxis[0].toValue(e.chartX), chart.yAxis[0].toValue(e.chartY), e.chartX, e.chartY); + } + }, + // The event handler for the mouse scroll event + onContainerMouseWheel: function (e) { + var chart = this.chart, delta; + e = this.normalize(e); + // Firefox uses e.detail, WebKit and IE uses wheelDelta + delta = e.detail || -(e.wheelDelta / 120); + if (chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop)) { + chart.mapZoom(Math.pow(chart.options.mapNavigation.mouseWheelSensitivity, delta), chart.xAxis[0].toValue(e.chartX), chart.yAxis[0].toValue(e.chartY), e.chartX, e.chartY); + } + } +}); +// The pinchType is inferred from mapNavigation options. +wrap(Pointer.prototype, 'zoomOption', function (proceed) { + var mapNavigation = this.chart.options.mapNavigation; + // Pinch status + if (pick(mapNavigation.enableTouchZoom, mapNavigation.enabled)) { + this.chart.options.chart.pinchType = 'xy'; + } + proceed.apply(this, [].slice.call(arguments, 1)); +}); +// Extend the pinchTranslate method to preserve fixed ratio when zooming +wrap(Pointer.prototype, 'pinchTranslate', function (proceed, pinchDown, touches, transform, selectionMarker, clip, lastValidTouch) { + var xBigger; + proceed.call(this, pinchDown, touches, transform, selectionMarker, clip, lastValidTouch); + // Keep ratio + if (this.chart.options.chart.type === 'map' && this.hasZoom) { + xBigger = transform.scaleX > transform.scaleY; + this.pinchTranslateDirection(!xBigger, pinchDown, touches, transform, selectionMarker, clip, lastValidTouch, xBigger ? transform.scaleX : transform.scaleY); + } +}); diff --git a/librerias/gantt/code/es-modules/parts-map/MapSeries.js b/librerias/gantt/code/es-modules/parts-map/MapSeries.js new file mode 100644 index 0000000..c93f1a1 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-map/MapSeries.js @@ -0,0 +1,1070 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import '../parts/Options.js'; +import '../parts/ScatterSeries.js'; +import '../parts/Series.js'; +import './ColorMapSeriesMixin.js'; +import LegendSymbolMixin from '../mixins/legend-symbol.js'; +import Point from '../parts/Point.js'; +import U from '../parts/Utilities.js'; +var extend = U.extend, fireEvent = U.fireEvent, getNestedProperty = U.getNestedProperty, isArray = U.isArray, isNumber = U.isNumber, merge = U.merge, objectEach = U.objectEach, pick = U.pick, seriesType = U.seriesType, splat = U.splat; +var colorMapPointMixin = H.colorMapPointMixin, colorMapSeriesMixin = H.colorMapSeriesMixin, noop = H.noop, Series = H.Series, seriesTypes = H.seriesTypes; +/** + * @private + * @class + * @name Highcharts.seriesTypes.map + * + * @augments Highcharts.Series + */ +seriesType('map', 'scatter', +/** + * The map series is used for basic choropleth maps, where each map area has + * a color based on its value. + * + * @sample maps/demo/all-maps/ + * Choropleth map + * + * @extends plotOptions.scatter + * @excluding marker, cluster + * @product highmaps + * @optionparent plotOptions.map + */ +{ + animation: false, + dataLabels: { + crop: false, + formatter: function () { + return this.point.value; + }, + inside: true, + overflow: false, + padding: 0, + verticalAlign: 'middle' + }, + /** + * @ignore-option + * + * @private + */ + marker: null, + /** + * The color to apply to null points. + * + * In styled mode, the null point fill is set in the + * `.highcharts-null-point` class. + * + * @sample maps/demo/all-areas-as-null/ + * Null color + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * + * @private + */ + nullColor: '#f7f7f7', + /** + * Whether to allow pointer interaction like tooltips and mouse events + * on null points. + * + * @type {boolean} + * @since 4.2.7 + * @apioption plotOptions.map.nullInteraction + * + * @private + */ + stickyTracking: false, + tooltip: { + followPointer: true, + pointFormat: '{point.name}: {point.value}
' + }, + /** + * @ignore-option + * + * @private + */ + turboThreshold: 0, + /** + * Whether all areas of the map defined in `mapData` should be rendered. + * If `true`, areas which don't correspond to a data point, are rendered + * as `null` points. If `false`, those areas are skipped. + * + * @sample maps/plotoptions/series-allareas-false/ + * All areas set to false + * + * @type {boolean} + * @default true + * @product highmaps + * @apioption plotOptions.series.allAreas + * + * @private + */ + allAreas: true, + /** + * The border color of the map areas. + * + * In styled mode, the border stroke is given in the `.highcharts-point` + * class. + * + * @sample {highmaps} maps/plotoptions/series-border/ + * Borders demo + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default '#cccccc' + * @product highmaps + * @apioption plotOptions.series.borderColor + * + * @private + */ + borderColor: '#cccccc', + /** + * The border width of each map area. + * + * In styled mode, the border stroke width is given in the + * `.highcharts-point` class. + * + * @sample maps/plotoptions/series-border/ + * Borders demo + * + * @type {number} + * @default 1 + * @product highmaps + * @apioption plotOptions.series.borderWidth + * + * @private + */ + borderWidth: 1, + /** + * @default value + * @apioption plotOptions.map.colorKey + */ + /** + * What property to join the `mapData` to the value data. For example, + * if joinBy is "code", the mapData items with a specific code is merged + * into the data with the same code. For maps loaded from GeoJSON, the + * keys may be held in each point's `properties` object. + * + * The joinBy option can also be an array of two values, where the first + * points to a key in the `mapData`, and the second points to another + * key in the `data`. + * + * When joinBy is `null`, the map items are joined by their position in + * the array, which performs much better in maps with many data points. + * This is the recommended option if you are printing more than a + * thousand data points and have a backend that can preprocess the data + * into a parallel array of the mapData. + * + * @sample maps/plotoptions/series-border/ + * Joined by "code" + * @sample maps/demo/geojson/ + * GeoJSON joined by an array + * @sample maps/series/joinby-null/ + * Simple data joined by null + * + * @type {string|Array} + * @default hc-key + * @product highmaps + * @apioption plotOptions.series.joinBy + * + * @private + */ + joinBy: 'hc-key', + /** + * Define the z index of the series. + * + * @type {number} + * @product highmaps + * @apioption plotOptions.series.zIndex + */ + /** + * @apioption plotOptions.series.states + * + * @private + */ + states: { + /** + * @apioption plotOptions.series.states.hover + */ + hover: { + /** @ignore-option */ + halo: null, + /** + * The color of the shape in this state. + * + * @sample maps/plotoptions/series-states-hover/ + * Hover options + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highmaps + * @apioption plotOptions.series.states.hover.color + */ + /** + * The border color of the point in this state. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highmaps + * @apioption plotOptions.series.states.hover.borderColor + */ + /** + * The border width of the point in this state + * + * @type {number} + * @product highmaps + * @apioption plotOptions.series.states.hover.borderWidth + */ + /** + * The relative brightness of the point when hovered, relative + * to the normal point color. + * + * @type {number} + * @product highmaps + * @default 0.2 + * @apioption plotOptions.series.states.hover.brightness + */ + brightness: 0.2 + }, + /** + * @apioption plotOptions.series.states.normal + */ + normal: { + /** + * @productdesc {highmaps} + * The animation adds some latency in order to reduce the effect + * of flickering when hovering in and out of for example an + * uneven coastline. + * + * @sample {highmaps} maps/plotoptions/series-states-animation-false/ + * No animation of fill color + * + * @apioption plotOptions.series.states.normal.animation + */ + animation: true + }, + /** + * @apioption plotOptions.series.states.select + */ + select: { + /** + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #cccccc + * @product highmaps + * @apioption plotOptions.series.states.select.color + */ + color: '#cccccc' + }, + inactive: { + opacity: 1 + } + } + // Prototype members +}, merge(colorMapSeriesMixin, { + type: 'map', + getExtremesFromAll: true, + useMapGeometry: true, + forceDL: true, + searchPoint: noop, + // When tooltip is not shared, this series (and derivatives) requires + // direct touch/hover. KD-tree does not apply. + directTouch: true, + // X axis and Y axis must have same translation slope + preserveAspectRatio: true, + pointArrayMap: ['value'], + // Extend setOptions by picking up the joinBy option and applying it + // to a series property + setOptions: function (itemOptions) { + var options = Series.prototype.setOptions.call(this, itemOptions), joinBy = options.joinBy, joinByNull = joinBy === null; + if (joinByNull) { + joinBy = '_i'; + } + joinBy = this.joinBy = splat(joinBy); + if (!joinBy[1]) { + joinBy[1] = joinBy[0]; + } + return options; + }, + // Get the bounding box of all paths in the map combined. + getBox: function (paths) { + var MAX_VALUE = Number.MAX_VALUE, maxX = -MAX_VALUE, minX = MAX_VALUE, maxY = -MAX_VALUE, minY = MAX_VALUE, minRange = MAX_VALUE, xAxis = this.xAxis, yAxis = this.yAxis, hasBox; + // Find the bounding box + (paths || []).forEach(function (point) { + if (point.path) { + if (typeof point.path === 'string') { + point.path = H.splitPath(point.path); + // Legacy one-dimensional array + } + else if (point.path[0] === 'M') { + point.path = H.SVGRenderer.prototype.pathToSegments(point.path); + } + var path = point.path || [], pointMaxX = -MAX_VALUE, pointMinX = MAX_VALUE, pointMaxY = -MAX_VALUE, pointMinY = MAX_VALUE, properties = point.properties; + // The first time a map point is used, analyze its box + if (!point._foundBox) { + path.forEach(function (seg) { + var x = seg[seg.length - 2]; + var y = seg[seg.length - 1]; + if (typeof x === 'number' && typeof y === 'number') { + pointMinX = Math.min(pointMinX, x); + pointMaxX = Math.max(pointMaxX, x); + pointMinY = Math.min(pointMinY, y); + pointMaxY = Math.max(pointMaxY, y); + } + }); + // Cache point bounding box for use to position data + // labels, bubbles etc + point._midX = (pointMinX + (pointMaxX - pointMinX) * pick(point.middleX, properties && + properties['hc-middle-x'], 0.5)); + point._midY = (pointMinY + (pointMaxY - pointMinY) * pick(point.middleY, properties && + properties['hc-middle-y'], 0.5)); + point._maxX = pointMaxX; + point._minX = pointMinX; + point._maxY = pointMaxY; + point._minY = pointMinY; + point.labelrank = pick(point.labelrank, (pointMaxX - pointMinX) * (pointMaxY - pointMinY)); + point._foundBox = true; + } + maxX = Math.max(maxX, point._maxX); + minX = Math.min(minX, point._minX); + maxY = Math.max(maxY, point._maxY); + minY = Math.min(minY, point._minY); + minRange = Math.min(point._maxX - point._minX, point._maxY - point._minY, minRange); + hasBox = true; + } + }); + // Set the box for the whole series + if (hasBox) { + this.minY = Math.min(minY, pick(this.minY, MAX_VALUE)); + this.maxY = Math.max(maxY, pick(this.maxY, -MAX_VALUE)); + this.minX = Math.min(minX, pick(this.minX, MAX_VALUE)); + this.maxX = Math.max(maxX, pick(this.maxX, -MAX_VALUE)); + // If no minRange option is set, set the default minimum zooming + // range to 5 times the size of the smallest element + if (xAxis && typeof xAxis.options.minRange === 'undefined') { + xAxis.minRange = Math.min(5 * minRange, (this.maxX - this.minX) / 5, xAxis.minRange || MAX_VALUE); + } + if (yAxis && typeof yAxis.options.minRange === 'undefined') { + yAxis.minRange = Math.min(5 * minRange, (this.maxY - this.minY) / 5, yAxis.minRange || MAX_VALUE); + } + } + }, + // Define hasData function for non-cartesian series. + // Returns true if the series has points at all. + hasData: function () { + return !!this.processedXData.length; // != 0 + }, + getExtremes: function () { + // Get the actual value extremes for colors + var _a = Series.prototype.getExtremes + .call(this, this.valueData), dataMin = _a.dataMin, dataMax = _a.dataMax; + // Recalculate box on updated data + if (this.chart.hasRendered && this.isDirtyData) { + this.getBox(this.options.data); + } + if (isNumber(dataMin)) { + this.valueMin = dataMin; + } + if (isNumber(dataMax)) { + this.valueMax = dataMax; + } + // Extremes for the mock Y axis + return { dataMin: this.minY, dataMax: this.maxY }; + }, + // Translate the path, so it automatically fits into the plot area box + translatePath: function (path) { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, xMin = xAxis.min, xTransA = xAxis.transA, xMinPixelPadding = xAxis.minPixelPadding, yMin = yAxis.min, yTransA = yAxis.transA, yMinPixelPadding = yAxis.minPixelPadding, ret = []; // Preserve the original + // Do the translation + if (path) { + path.forEach(function (seg) { + if (seg[0] === 'M') { + ret.push([ + 'M', + (seg[1] - (xMin || 0)) * xTransA + xMinPixelPadding, + (seg[2] - (yMin || 0)) * yTransA + yMinPixelPadding + ]); + } + else if (seg[0] === 'L') { + ret.push([ + 'L', + (seg[1] - (xMin || 0)) * xTransA + xMinPixelPadding, + (seg[2] - (yMin || 0)) * yTransA + yMinPixelPadding + ]); + } + else if (seg[0] === 'C') { + ret.push([ + 'C', + (seg[1] - (xMin || 0)) * xTransA + xMinPixelPadding, + (seg[2] - (yMin || 0)) * yTransA + yMinPixelPadding, + (seg[3] - (xMin || 0)) * xTransA + xMinPixelPadding, + (seg[4] - (yMin || 0)) * yTransA + yMinPixelPadding, + (seg[5] - (xMin || 0)) * xTransA + xMinPixelPadding, + (seg[6] - (yMin || 0)) * yTransA + yMinPixelPadding + ]); + } + else if (seg[0] === 'Q') { + ret.push([ + 'Q', + (seg[1] - (xMin || 0)) * xTransA + xMinPixelPadding, + (seg[2] - (yMin || 0)) * yTransA + yMinPixelPadding, + (seg[3] - (xMin || 0)) * xTransA + xMinPixelPadding, + (seg[4] - (yMin || 0)) * yTransA + yMinPixelPadding + ]); + } + else if (seg[0] === 'Z') { + ret.push(['Z']); + } + }); + } + return ret; + }, + // Extend setData to join in mapData. If the allAreas option is true, + // all areas from the mapData are used, and those that don't correspond + // to a data value are given null values. + setData: function (data, redraw, animation, updatePoints) { + var options = this.options, chartOptions = this.chart.options.chart, globalMapData = chartOptions && chartOptions.map, mapData = options.mapData, joinBy = this.joinBy, pointArrayMap = options.keys || this.pointArrayMap, dataUsed = [], mapMap = {}, mapPoint, mapTransforms = this.chart.mapTransforms, props, i; + // Collect mapData from chart options if not defined on series + if (!mapData && globalMapData) { + mapData = typeof globalMapData === 'string' ? + H.maps[globalMapData] : + globalMapData; + } + // Pick up numeric values, add index + // Convert Array point definitions to objects using pointArrayMap + if (data) { + data.forEach(function (val, i) { + var ix = 0; + if (isNumber(val)) { + data[i] = { + value: val + }; + } + else if (isArray(val)) { + data[i] = {}; + // Automatically copy first item to hc-key if there is + // an extra leading string + if (!options.keys && + val.length > pointArrayMap.length && + typeof val[0] === 'string') { + data[i]['hc-key'] = val[0]; + ++ix; + } + // Run through pointArrayMap and what's left of the + // point data array in parallel, copying over the values + for (var j = 0; j < pointArrayMap.length; ++j, ++ix) { + if (pointArrayMap[j] && + typeof val[ix] !== 'undefined') { + if (pointArrayMap[j].indexOf('.') > 0) { + Point.prototype.setNestedProperty(data[i], val[ix], pointArrayMap[j]); + } + else { + data[i][pointArrayMap[j]] = + val[ix]; + } + } + } + } + if (joinBy && joinBy[0] === '_i') { + data[i]._i = i; + } + }); + } + this.getBox(data); + // Pick up transform definitions for chart + this.chart.mapTransforms = mapTransforms = + chartOptions && chartOptions.mapTransforms || + mapData && mapData['hc-transform'] || + mapTransforms; + // Cache cos/sin of transform rotation angle + if (mapTransforms) { + objectEach(mapTransforms, function (transform) { + if (transform.rotation) { + transform.cosAngle = Math.cos(transform.rotation); + transform.sinAngle = Math.sin(transform.rotation); + } + }); + } + if (mapData) { + if (mapData.type === 'FeatureCollection') { + this.mapTitle = mapData.title; + mapData = H.geojson(mapData, this.type, this); + } + this.mapData = mapData; + this.mapMap = {}; + for (i = 0; i < mapData.length; i++) { + mapPoint = mapData[i]; + props = mapPoint.properties; + mapPoint._i = i; + // Copy the property over to root for faster access + if (joinBy[0] && props && props[joinBy[0]]) { + mapPoint[joinBy[0]] = props[joinBy[0]]; + } + mapMap[mapPoint[joinBy[0]]] = mapPoint; + } + this.mapMap = mapMap; + // Registered the point codes that actually hold data + if (data && joinBy[1]) { + var joinKey_1 = joinBy[1]; + data.forEach(function (pointOptions) { + var mapKey = getNestedProperty(joinKey_1, pointOptions); + if (mapMap[mapKey]) { + dataUsed.push(mapMap[mapKey]); + } + }); + } + if (options.allAreas) { + this.getBox(mapData); + data = data || []; + // Registered the point codes that actually hold data + if (joinBy[1]) { + var joinKey_2 = joinBy[1]; + data.forEach(function (pointOptions) { + dataUsed.push(getNestedProperty(joinKey_2, pointOptions)); + }); + } + // Add those map points that don't correspond to data, which + // will be drawn as null points + dataUsed = ('|' + dataUsed.map(function (point) { + return point && point[joinBy[0]]; + }).join('|') + '|'); // Faster than array.indexOf + mapData.forEach(function (mapPoint) { + if (!joinBy[0] || + dataUsed.indexOf('|' + mapPoint[joinBy[0]] + '|') === -1) { + data.push(merge(mapPoint, { value: null })); + // #5050 - adding all areas causes the update + // optimization of setData to kick in, even though + // the point order has changed + updatePoints = false; + } + }); + } + else { + this.getBox(dataUsed); // Issue #4784 + } + } + Series.prototype.setData.call(this, data, redraw, animation, updatePoints); + }, + // No graph for the map series + drawGraph: noop, + // We need the points' bounding boxes in order to draw the data labels, + // so we skip it now and call it from drawPoints instead. + drawDataLabels: noop, + // Allow a quick redraw by just translating the area group. Used for + // zooming and panning in capable browsers. + doFullTranslate: function () { + return (this.isDirtyData || + this.chart.isResizing || + this.chart.renderer.isVML || + !this.baseTrans); + }, + // Add the path option for data points. Find the max value for color + // calculation. + translate: function () { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, doFullTranslate = series.doFullTranslate(); + series.generatePoints(); + series.data.forEach(function (point) { + // Record the middle point (loosely based on centroid), + // determined by the middleX and middleY options. + if (isNumber(point._midX) && isNumber(point._midY)) { + point.plotX = xAxis.toPixels(point._midX, true); + point.plotY = yAxis.toPixels(point._midY, true); + } + if (doFullTranslate) { + point.shapeType = 'path'; + point.shapeArgs = { + d: series.translatePath(point.path) + }; + } + }); + fireEvent(series, 'afterTranslate'); + }, + // Get presentational attributes. In the maps series this runs in both + // styled and non-styled mode, because colors hold data when a colorAxis + // is used. + pointAttribs: function (point, state) { + var attr = point.series.chart.styledMode ? + this.colorAttribs(point) : + seriesTypes.column.prototype.pointAttribs.call(this, point, state); + // Set the stroke-width on the group element and let all point + // graphics inherit. That way we don't have to iterate over all + // points to update the stroke-width on zooming. + attr['stroke-width'] = pick(point.options[(this.pointAttrToOptions && + this.pointAttrToOptions['stroke-width']) || 'borderWidth'], 'inherit'); + return attr; + }, + // Use the drawPoints method of column, that is able to handle simple + // shapeArgs. Extend it by assigning the tooltip position. + drawPoints: function () { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, group = series.group, chart = series.chart, renderer = chart.renderer, scaleX, scaleY, translateX, translateY, baseTrans = this.baseTrans, transformGroup, startTranslateX, startTranslateY, startScaleX, startScaleY; + // Set a group that handles transform during zooming and panning in + // order to preserve clipping on series.group + if (!series.transformGroup) { + series.transformGroup = renderer.g() + .attr({ + scaleX: 1, + scaleY: 1 + }) + .add(group); + series.transformGroup.survive = true; + } + // Draw the shapes again + if (series.doFullTranslate()) { + // Individual point actions. + if (chart.hasRendered && !chart.styledMode) { + series.points.forEach(function (point) { + // Restore state color on update/redraw (#3529) + if (point.shapeArgs) { + point.shapeArgs.fill = series.pointAttribs(point, point.state).fill; + } + }); + } + // Draw them in transformGroup + series.group = series.transformGroup; + seriesTypes.column.prototype.drawPoints.apply(series); + series.group = group; // Reset + // Add class names + series.points.forEach(function (point) { + if (point.graphic) { + var className = ''; + if (point.name) { + className += + 'highcharts-name-' + + point.name.replace(/ /g, '-').toLowerCase(); + } + if (point.properties && + point.properties['hc-key']) { + className += + ' highcharts-key-' + + point.properties['hc-key'].toLowerCase(); + } + if (className) { + point.graphic.addClass(className); + } + // In styled mode, apply point colors by CSS + if (chart.styledMode) { + point.graphic.css(series.pointAttribs(point, point.selected && 'select' || void 0)); + } + } + }); + // Set the base for later scale-zooming. The originX and originY + // properties are the axis values in the plot area's upper left + // corner. + this.baseTrans = { + originX: (xAxis.min - + xAxis.minPixelPadding / xAxis.transA), + originY: (yAxis.min - + yAxis.minPixelPadding / yAxis.transA + + (yAxis.reversed ? 0 : yAxis.len / yAxis.transA)), + transAX: xAxis.transA, + transAY: yAxis.transA + }; + // Reset transformation in case we're doing a full translate + // (#3789) + this.transformGroup.animate({ + translateX: 0, + translateY: 0, + scaleX: 1, + scaleY: 1 + }); + // Just update the scale and transform for better performance + } + else { + scaleX = xAxis.transA / baseTrans.transAX; + scaleY = yAxis.transA / baseTrans.transAY; + translateX = xAxis.toPixels(baseTrans.originX, true); + translateY = yAxis.toPixels(baseTrans.originY, true); + // Handle rounding errors in normal view (#3789) + if (scaleX > 0.99 && + scaleX < 1.01 && + scaleY > 0.99 && + scaleY < 1.01) { + scaleX = 1; + scaleY = 1; + translateX = Math.round(translateX); + translateY = Math.round(translateY); + } + /* Animate or move to the new zoom level. In order to prevent + flickering as the different transform components are set out + of sync (#5991), we run a fake animator attribute and set + scale and translation synchronously in the same step. + + A possible improvement to the API would be to handle this in + the renderer or animation engine itself, to ensure that when + we are animating multiple properties, we make sure that each + step for each property is performed in the same step. Also, + for symbols and for transform properties, it should induce a + single updateTransform and symbolAttr call. */ + transformGroup = this.transformGroup; + if (chart.renderer.globalAnimation) { + startTranslateX = transformGroup.attr('translateX'); + startTranslateY = transformGroup.attr('translateY'); + startScaleX = transformGroup.attr('scaleX'); + startScaleY = transformGroup.attr('scaleY'); + transformGroup + .attr({ animator: 0 }) + .animate({ + animator: 1 + }, { + step: function (now, fx) { + transformGroup.attr({ + translateX: (startTranslateX + + (translateX - startTranslateX) * fx.pos), + translateY: (startTranslateY + + (translateY - startTranslateY) * fx.pos), + scaleX: (startScaleX + + (scaleX - startScaleX) * + fx.pos), + scaleY: (startScaleY + + (scaleY - startScaleY) * fx.pos) + }); + } + }); + // When dragging, animation is off. + } + else { + transformGroup.attr({ + translateX: translateX, + translateY: translateY, + scaleX: scaleX, + scaleY: scaleY + }); + } + } + /* Set the stroke-width directly on the group element so the + children inherit it. We need to use setAttribute directly, + because the stroke-widthSetter method expects a stroke color also + to be set. */ + if (!chart.styledMode) { + group.element.setAttribute('stroke-width', (pick(series.options[(series.pointAttrToOptions && + series.pointAttrToOptions['stroke-width']) || 'borderWidth'], 1 // Styled mode + ) / (scaleX || 1))); + } + this.drawMapDataLabels(); + }, + // Draw the data labels. Special for maps is the time that the data + // labels are drawn (after points), and the clipping of the + // dataLabelsGroup. + drawMapDataLabels: function () { + Series.prototype.drawDataLabels.call(this); + if (this.dataLabelsGroup) { + this.dataLabelsGroup.clip(this.chart.clipRect); + } + }, + // Override render to throw in an async call in IE8. Otherwise it chokes + // on the US counties demo. + render: function () { + var series = this, render = Series.prototype.render; + // Give IE8 some time to breathe. + if (series.chart.renderer.isVML && series.data.length > 3000) { + setTimeout(function () { + render.call(series); + }); + } + else { + render.call(series); + } + }, + // The initial animation for the map series. By default, animation is + // disabled. Animation of map shapes is not at all supported in VML + // browsers. + animate: function (init) { + var chart = this.chart, animation = this.options.animation, group = this.group, xAxis = this.xAxis, yAxis = this.yAxis, left = xAxis.pos, top = yAxis.pos; + if (chart.renderer.isSVG) { + if (animation === true) { + animation = { + duration: 1000 + }; + } + // Initialize the animation + if (init) { + // Scale down the group and place it in the center + group.attr({ + translateX: left + xAxis.len / 2, + translateY: top + yAxis.len / 2, + scaleX: 0.001, + scaleY: 0.001 + }); + // Run the animation + } + else { + group.animate({ + translateX: left, + translateY: top, + scaleX: 1, + scaleY: 1 + }, animation); + } + } + }, + // Animate in the new series from the clicked point in the old series. + // Depends on the drilldown.js module + animateDrilldown: function (init) { + var toBox = this.chart.plotBox, level = this.chart.drilldownLevels[this.chart.drilldownLevels.length - 1], fromBox = level.bBox, animationOptions = this.chart.options.drilldown.animation, scale; + if (!init) { + scale = Math.min(fromBox.width / toBox.width, fromBox.height / toBox.height); + level.shapeArgs = { + scaleX: scale, + scaleY: scale, + translateX: fromBox.x, + translateY: fromBox.y + }; + this.points.forEach(function (point) { + if (point.graphic) { + point.graphic + .attr(level.shapeArgs) + .animate({ + scaleX: 1, + scaleY: 1, + translateX: 0, + translateY: 0 + }, animationOptions); + } + }); + } + }, + drawLegendSymbol: LegendSymbolMixin.drawRectangle, + // When drilling up, pull out the individual point graphics from the + // lower series and animate them into the origin point in the upper + // series. + animateDrillupFrom: function (level) { + seriesTypes.column.prototype + .animateDrillupFrom.call(this, level); + }, + // When drilling up, keep the upper series invisible until the lower + // series has moved into place + animateDrillupTo: function (init) { + seriesTypes.column.prototype + .animateDrillupTo.call(this, init); + } + // Point class +}), extend({ + // Extend the Point object to split paths + applyOptions: function (options, x) { + var series = this.series, point = Point.prototype.applyOptions.call(this, options, x), joinBy = series.joinBy, mapPoint; + if (series.mapData && series.mapMap) { + var joinKey = joinBy[1]; + var mapKey = Point.prototype.getNestedProperty.call(point, joinKey); + mapPoint = typeof mapKey !== 'undefined' && + series.mapMap[mapKey]; + if (mapPoint) { + // This applies only to bubbles + if (series.xyFromShape) { + point.x = mapPoint._midX; + point.y = mapPoint._midY; + } + extend(point, mapPoint); // copy over properties + } + else { + point.value = point.value || null; + } + } + return point; + }, + // Stop the fade-out + onMouseOver: function (e) { + U.clearTimeout(this.colorInterval); + if (this.value !== null || this.series.options.nullInteraction) { + Point.prototype.onMouseOver.call(this, e); + } + else { + // #3401 Tooltip doesn't hide when hovering over null points + this.series.onMouseOut(e); + } + }, + // eslint-disable-next-line valid-jsdoc + /** + * Highmaps only. Zoom in on the point using the global animation. + * + * @sample maps/members/point-zoomto/ + * Zoom to points from butons + * + * @requires modules/map + * + * @function Highcharts.Point#zoomTo + */ + zoomTo: function () { + var point = this, series = point.series; + series.xAxis.setExtremes(point._minX, point._maxX, false); + series.yAxis.setExtremes(point._minY, point._maxY, false); + series.chart.redraw(); + } +}, colorMapPointMixin)); +/** + * A map data object containing a `path` definition and optionally additional + * properties to join in the data as per the `joinBy` option. + * + * @sample maps/demo/category-map/ + * Map data and joinBy + * + * @type {Array|*} + * @product highmaps + * @apioption series.mapData + */ +/** + * A `map` series. If the [type](#series.map.type) option is not specified, it + * is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.map + * @excluding dataParser, dataURL, marker + * @product highmaps + * @apioption series.map + */ +/** + * An array of data points for the series. For the `map` series type, points can + * be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `value` options. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `[hc-key, value]`. Example: + * ```js + * data: [ + * ['us-ny', 0], + * ['us-mi', 5], + * ['us-tx', 3], + * ['us-ak', 5] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.map.turboThreshold), + * this option is not available. + * ```js + * data: [{ + * value: 6, + * name: "Point2", + * color: "#00FF00" + * }, { + * value: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @type {Array|null|*>} + * @product highmaps + * @apioption series.map.data + */ +/** + * Individual color for the point. By default the color is either used + * to denote the value, or pulled from the global `colors` array. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highmaps + * @apioption series.map.data.color + */ +/** + * Individual data label for each point. The options are the same as + * the ones for [plotOptions.series.dataLabels]( + * #plotOptions.series.dataLabels). + * + * @sample maps/series/data-datalabels/ + * Disable data labels for individual areas + * + * @type {Highcharts.DataLabelsOptions} + * @product highmaps + * @apioption series.map.data.dataLabels + */ +/** + * The `id` of a series in the [drilldown.series](#drilldown.series) + * array to use for a drilldown for this point. + * + * @sample maps/demo/map-drilldown/ + * Basic drilldown + * + * @type {string} + * @product highmaps + * @apioption series.map.data.drilldown + */ +/** + * An id for the point. This can be used after render time to get a + * pointer to the point object through `chart.get()`. + * + * @sample maps/series/data-id/ + * Highlight a point by id + * + * @type {string} + * @product highmaps + * @apioption series.map.data.id + */ +/** + * When data labels are laid out on a map, Highmaps runs a simplified + * algorithm to detect collision. When two labels collide, the one with + * the lowest rank is hidden. By default the rank is computed from the + * area. + * + * @type {number} + * @product highmaps + * @apioption series.map.data.labelrank + */ +/** + * The relative mid point of an area, used to place the data label. + * Ranges from 0 to 1\. When `mapData` is used, middleX can be defined + * there. + * + * @type {number} + * @default 0.5 + * @product highmaps + * @apioption series.map.data.middleX + */ +/** + * The relative mid point of an area, used to place the data label. + * Ranges from 0 to 1\. When `mapData` is used, middleY can be defined + * there. + * + * @type {number} + * @default 0.5 + * @product highmaps + * @apioption series.map.data.middleY + */ +/** + * The name of the point as shown in the legend, tooltip, dataLabel + * etc. + * + * @sample maps/series/data-datalabels/ + * Point names + * + * @type {string} + * @product highmaps + * @apioption series.map.data.name + */ +/** + * For map and mapline series types, the SVG path for the shape. For + * compatibily with old IE, not all SVG path definitions are supported, + * but M, L and C operators are safe. + * + * To achieve a better separation between the structure and the data, + * it is recommended to use `mapData` to define that paths instead + * of defining them on the data points themselves. + * + * @sample maps/series/data-path/ + * Paths defined in data + * + * @type {string} + * @product highmaps + * @apioption series.map.data.path + */ +/** + * The numeric value of the data point. + * + * @type {number|null} + * @product highmaps + * @apioption series.map.data.value + */ +/** + * Individual point events + * + * @extends plotOptions.series.point.events + * @product highmaps + * @apioption series.map.data.events + */ +''; // adds doclets above to the transpiled file diff --git a/librerias/gantt/code/es-modules/parts-more/AreaRangeSeries.js b/librerias/gantt/code/es-modules/parts-more/AreaRangeSeries.js new file mode 100644 index 0000000..8f86a0e --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-more/AreaRangeSeries.js @@ -0,0 +1,623 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import Point from '../parts/Point.js'; +import U from '../parts/Utilities.js'; +var defined = U.defined, extend = U.extend, isArray = U.isArray, isNumber = U.isNumber, pick = U.pick, seriesType = U.seriesType; +import '../parts/Options.js'; +import '../parts/Series.js'; +var noop = H.noop, Series = H.Series, seriesTypes = H.seriesTypes, seriesProto = Series.prototype, pointProto = Point.prototype; +/** + * The area range series is a carteseian series with higher and lower values for + * each point along an X axis, where the area between the values is shaded. + * + * @sample {highcharts} highcharts/demo/arearange/ + * Area range chart + * @sample {highstock} stock/demo/arearange/ + * Area range chart + * + * @extends plotOptions.area + * @product highcharts highstock + * @excluding stack, stacking + * @requires highcharts-more + * @optionparent plotOptions.arearange + */ +seriesType('arearange', 'area', { + /** + * Whether to apply a drop shadow to the graph line. Since 2.3 the shadow + * can be an object configuration containing `color`, `offsetX`, `offsetY`, + * `opacity` and `width`. + * + * @type {boolean|Highcharts.ShadowOptionsObject} + * @product highcharts + * @apioption plotOptions.arearange.shadow + */ + /** + * @default low + * @apioption plotOptions.arearange.colorKey + */ + /** + * Pixel width of the arearange graph line. + * + * @since 2.3.0 + * + * @private + */ + lineWidth: 1, + threshold: null, + tooltip: { + pointFormat: '\u25CF ' + + '{series.name}: {point.low} - {point.high}
' + }, + /** + * Whether the whole area or just the line should respond to mouseover + * tooltips and other mouse or touch events. + * + * @since 2.3.0 + * + * @private + */ + trackByArea: true, + /** + * Extended data labels for range series types. Range series data labels use + * no `x` and `y` options. Instead, they have `xLow`, `xHigh`, `yLow` and + * `yHigh` options to allow the higher and lower data label sets + * individually. + * + * @declare Highcharts.SeriesAreaRangeDataLabelsOptionsObject + * @exclude x, y + * @since 2.3.0 + * @product highcharts highstock + * + * @private + */ + dataLabels: { + align: null, + verticalAlign: null, + /** + * X offset of the lower data labels relative to the point value. + * + * @sample highcharts/plotoptions/arearange-datalabels/ + * Data labels on range series + * @sample highcharts/plotoptions/arearange-datalabels/ + * Data labels on range series + */ + xLow: 0, + /** + * X offset of the higher data labels relative to the point value. + * + * @sample highcharts/plotoptions/arearange-datalabels/ + * Data labels on range series + */ + xHigh: 0, + /** + * Y offset of the lower data labels relative to the point value. + * + * @sample highcharts/plotoptions/arearange-datalabels/ + * Data labels on range series + */ + yLow: 0, + /** + * Y offset of the higher data labels relative to the point value. + * + * @sample highcharts/plotoptions/arearange-datalabels/ + * Data labels on range series + */ + yHigh: 0 + } + // Prototype members +}, { + pointArrayMap: ['low', 'high'], + pointValKey: 'low', + deferTranslatePolar: true, + /* eslint-disable valid-jsdoc */ + /** + * @private + */ + toYData: function (point) { + return [point.low, point.high]; + }, + /** + * Translate a point's plotHigh from the internal angle and radius measures + * to true plotHigh coordinates. This is an addition of the toXY method + * found in Polar.js, because it runs too early for arearanges to be + * considered (#3419). + * @private + */ + highToXY: function (point) { + // Find the polar plotX and plotY + var chart = this.chart, xy = this.xAxis.postTranslate(point.rectPlotX, this.yAxis.len - point.plotHigh); + point.plotHighX = xy.x - chart.plotLeft; + point.plotHigh = xy.y - chart.plotTop; + point.plotLowX = point.plotX; + }, + /** + * Translate data points from raw values x and y to plotX and plotY. + * @private + */ + translate: function () { + var series = this, yAxis = series.yAxis, hasModifyValue = !!series.modifyValue; + seriesTypes.area.prototype.translate.apply(series); + // Set plotLow and plotHigh + series.points.forEach(function (point) { + var high = point.high, plotY = point.plotY; + if (point.isNull) { + point.plotY = null; + } + else { + point.plotLow = plotY; + point.plotHigh = yAxis.translate(hasModifyValue ? + series.modifyValue(high, point) : + high, 0, 1, 0, 1); + if (hasModifyValue) { + point.yBottom = point.plotHigh; + } + } + }); + // Postprocess plotHigh + if (this.chart.polar) { + this.points.forEach(function (point) { + series.highToXY(point); + point.tooltipPos = [ + (point.plotHighX + point.plotLowX) / 2, + (point.plotHigh + point.plotLow) / 2 + ]; + }); + } + }, + /** + * Extend the line series' getSegmentPath method by applying the segment + * path to both lower and higher values of the range. + * @private + */ + getGraphPath: function (points) { + var highPoints = [], highAreaPoints = [], i, getGraphPath = seriesTypes.area.prototype.getGraphPath, point, pointShim, linePath, lowerPath, options = this.options, connectEnds = this.chart.polar && options.connectEnds !== false, connectNulls = options.connectNulls, step = options.step, higherPath, higherAreaPath; + points = points || this.points; + i = points.length; + // Create the top line and the top part of the area fill. The area fill + // compensates for null points by drawing down to the lower graph, + // moving across the null gap and starting again at the lower graph. + i = points.length; + while (i--) { + point = points[i]; + if (!point.isNull && + !connectEnds && + !connectNulls && + (!points[i + 1] || points[i + 1].isNull)) { + highAreaPoints.push({ + plotX: point.plotX, + plotY: point.plotY, + doCurve: false // #5186, gaps in areasplinerange fill + }); + } + pointShim = { + polarPlotY: point.polarPlotY, + rectPlotX: point.rectPlotX, + yBottom: point.yBottom, + // plotHighX is for polar charts + plotX: pick(point.plotHighX, point.plotX), + plotY: point.plotHigh, + isNull: point.isNull + }; + highAreaPoints.push(pointShim); + highPoints.push(pointShim); + if (!point.isNull && + !connectEnds && + !connectNulls && + (!points[i - 1] || points[i - 1].isNull)) { + highAreaPoints.push({ + plotX: point.plotX, + plotY: point.plotY, + doCurve: false // #5186, gaps in areasplinerange fill + }); + } + } + // Get the paths + lowerPath = getGraphPath.call(this, points); + if (step) { + if (step === true) { + step = 'left'; + } + options.step = { + left: 'right', + center: 'center', + right: 'left' + }[step]; // swap for reading in getGraphPath + } + higherPath = getGraphPath.call(this, highPoints); + higherAreaPath = getGraphPath.call(this, highAreaPoints); + options.step = step; + // Create a line on both top and bottom of the range + linePath = [] + .concat(lowerPath, higherPath); + // For the area path, we need to change the 'move' statement + // into 'lineTo' + if (!this.chart.polar && higherAreaPath[0] && higherAreaPath[0][0] === 'M') { + // This probably doesn't work for spline + higherAreaPath[0] = ['L', higherAreaPath[0][1], higherAreaPath[0][2]]; + } + this.graphPath = linePath; + this.areaPath = lowerPath.concat(higherAreaPath); + // Prepare for sideways animation + linePath.isArea = true; + linePath.xMap = lowerPath.xMap; + this.areaPath.xMap = lowerPath.xMap; + return linePath; + }, + /** + * Extend the basic drawDataLabels method by running it for both lower and + * higher values. + * @private + */ + drawDataLabels: function () { + var data = this.points, length = data.length, i, originalDataLabels = [], dataLabelOptions = this.options.dataLabels, point, up, inverted = this.chart.inverted, upperDataLabelOptions, lowerDataLabelOptions; + // Split into upper and lower options. If data labels is an array, the + // first element is the upper label, the second is the lower. + // + // TODO: We want to change this and allow multiple labels for both upper + // and lower values in the future - introducing some options for which + // point value to use as Y for the dataLabel, so that this could be + // handled in Series.drawDataLabels. This would also improve performance + // since we now have to loop over all the points multiple times to work + // around the data label logic. + if (isArray(dataLabelOptions)) { + if (dataLabelOptions.length > 1) { + upperDataLabelOptions = dataLabelOptions[0]; + lowerDataLabelOptions = dataLabelOptions[1]; + } + else { + upperDataLabelOptions = dataLabelOptions[0]; + lowerDataLabelOptions = { enabled: false }; + } + } + else { + // Make copies + upperDataLabelOptions = extend({}, dataLabelOptions); + upperDataLabelOptions.x = dataLabelOptions.xHigh; + upperDataLabelOptions.y = dataLabelOptions.yHigh; + lowerDataLabelOptions = extend({}, dataLabelOptions); + lowerDataLabelOptions.x = dataLabelOptions.xLow; + lowerDataLabelOptions.y = dataLabelOptions.yLow; + } + // Draw upper labels + if (upperDataLabelOptions.enabled || this._hasPointLabels) { + // Set preliminary values for plotY and dataLabel + // and draw the upper labels + i = length; + while (i--) { + point = data[i]; + if (point) { + up = upperDataLabelOptions.inside ? + point.plotHigh < point.plotLow : + point.plotHigh > point.plotLow; + point.y = point.high; + point._plotY = point.plotY; + point.plotY = point.plotHigh; + // Store original data labels and set preliminary label + // objects to be picked up in the uber method + originalDataLabels[i] = point.dataLabel; + point.dataLabel = point.dataLabelUpper; + // Set the default offset + point.below = up; + if (inverted) { + if (!upperDataLabelOptions.align) { + upperDataLabelOptions.align = up ? 'right' : 'left'; + } + } + else { + if (!upperDataLabelOptions.verticalAlign) { + upperDataLabelOptions.verticalAlign = up ? + 'top' : + 'bottom'; + } + } + } + } + this.options.dataLabels = upperDataLabelOptions; + if (seriesProto.drawDataLabels) { + // #1209: + seriesProto.drawDataLabels.apply(this, arguments); + } + // Reset state after the upper labels were created. Move + // it to point.dataLabelUpper and reassign the originals. + // We do this here to support not drawing a lower label. + i = length; + while (i--) { + point = data[i]; + if (point) { + point.dataLabelUpper = point.dataLabel; + point.dataLabel = originalDataLabels[i]; + delete point.dataLabels; + point.y = point.low; + point.plotY = point._plotY; + } + } + } + // Draw lower labels + if (lowerDataLabelOptions.enabled || this._hasPointLabels) { + i = length; + while (i--) { + point = data[i]; + if (point) { + up = lowerDataLabelOptions.inside ? + point.plotHigh < point.plotLow : + point.plotHigh > point.plotLow; + // Set the default offset + point.below = !up; + if (inverted) { + if (!lowerDataLabelOptions.align) { + lowerDataLabelOptions.align = up ? 'left' : 'right'; + } + } + else { + if (!lowerDataLabelOptions.verticalAlign) { + lowerDataLabelOptions.verticalAlign = up ? + 'bottom' : + 'top'; + } + } + } + } + this.options.dataLabels = lowerDataLabelOptions; + if (seriesProto.drawDataLabels) { + seriesProto.drawDataLabels.apply(this, arguments); + } + } + // Merge upper and lower into point.dataLabels for later destroying + if (upperDataLabelOptions.enabled) { + i = length; + while (i--) { + point = data[i]; + if (point) { + point.dataLabels = [ + point.dataLabelUpper, + point.dataLabel + ].filter(function (label) { + return !!label; + }); + } + } + } + // Reset options + this.options.dataLabels = dataLabelOptions; + }, + alignDataLabel: function () { + seriesTypes.column.prototype.alignDataLabel + .apply(this, arguments); + }, + drawPoints: function () { + var series = this, pointLength = series.points.length, point, i; + // Draw bottom points + seriesProto.drawPoints + .apply(series, arguments); + // Prepare drawing top points + i = 0; + while (i < pointLength) { + point = series.points[i]; + // Save original props to be overridden by temporary props for top + // points + point.origProps = { + plotY: point.plotY, + plotX: point.plotX, + isInside: point.isInside, + negative: point.negative, + zone: point.zone, + y: point.y + }; + point.lowerGraphic = point.graphic; + point.graphic = point.upperGraphic; + point.plotY = point.plotHigh; + if (defined(point.plotHighX)) { + point.plotX = point.plotHighX; + } + point.y = point.high; + point.negative = point.high < (series.options.threshold || 0); + point.zone = (series.zones.length && point.getZone()); + if (!series.chart.polar) { + point.isInside = point.isTopInside = (typeof point.plotY !== 'undefined' && + point.plotY >= 0 && + point.plotY <= series.yAxis.len && // #3519 + point.plotX >= 0 && + point.plotX <= series.xAxis.len); + } + i++; + } + // Draw top points + seriesProto.drawPoints.apply(series, arguments); + // Reset top points preliminary modifications + i = 0; + while (i < pointLength) { + point = series.points[i]; + point.upperGraphic = point.graphic; + point.graphic = point.lowerGraphic; + extend(point, point.origProps); + delete point.origProps; + i++; + } + }, + /* eslint-enable valid-jsdoc */ + setStackedPoints: noop +}, { + /** + * Range series only. The high or maximum value for each data point. + * @name Highcharts.Point#high + * @type {number|undefined} + */ + /** + * Range series only. The low or minimum value for each data point. + * @name Highcharts.Point#low + * @type {number|undefined} + */ + /* eslint-disable valid-jsdoc */ + /** + * @private + */ + setState: function () { + var prevState = this.state, series = this.series, isPolar = series.chart.polar; + if (!defined(this.plotHigh)) { + // Boost doesn't calculate plotHigh + this.plotHigh = series.yAxis.toPixels(this.high, true); + } + if (!defined(this.plotLow)) { + // Boost doesn't calculate plotLow + this.plotLow = this.plotY = series.yAxis.toPixels(this.low, true); + } + if (series.stateMarkerGraphic) { + series.lowerStateMarkerGraphic = series.stateMarkerGraphic; + series.stateMarkerGraphic = series.upperStateMarkerGraphic; + } + // Change state also for the top marker + this.graphic = this.upperGraphic; + this.plotY = this.plotHigh; + if (isPolar) { + this.plotX = this.plotHighX; + } + // Top state: + pointProto.setState.apply(this, arguments); + this.state = prevState; + // Now restore defaults + this.plotY = this.plotLow; + this.graphic = this.lowerGraphic; + if (isPolar) { + this.plotX = this.plotLowX; + } + if (series.stateMarkerGraphic) { + series.upperStateMarkerGraphic = series.stateMarkerGraphic; + series.stateMarkerGraphic = series.lowerStateMarkerGraphic; + // Lower marker is stored at stateMarkerGraphic + // to avoid reference duplication (#7021) + series.lowerStateMarkerGraphic = void 0; + } + pointProto.setState.apply(this, arguments); + }, + haloPath: function () { + var isPolar = this.series.chart.polar, path = []; + // Bottom halo + this.plotY = this.plotLow; + if (isPolar) { + this.plotX = this.plotLowX; + } + if (this.isInside) { + path = pointProto.haloPath.apply(this, arguments); + } + // Top halo + this.plotY = this.plotHigh; + if (isPolar) { + this.plotX = this.plotHighX; + } + if (this.isTopInside) { + path = path.concat(pointProto.haloPath.apply(this, arguments)); + } + return path; + }, + destroyElements: function () { + var graphics = ['lowerGraphic', 'upperGraphic']; + graphics.forEach(function (graphicName) { + if (this[graphicName]) { + this[graphicName] = + this[graphicName].destroy(); + } + }, this); + // Clear graphic for states, removed in the above each: + this.graphic = null; + return pointProto.destroyElements.apply(this, arguments); + }, + isValid: function () { + return isNumber(this.low) && isNumber(this.high); + } + /* eslint-enable valid-jsdoc */ +}); +/** + * A `arearange` series. If the [type](#series.arearange.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * + * @extends series,plotOptions.arearange + * @excluding dataParser, dataURL, stack, stacking + * @product highcharts highstock + * @requires highcharts-more + * @apioption series.arearange + */ +/** + * An array of data points for the series. For the `arearange` series type, + * points can be given in the following ways: + * + * 1. An array of arrays with 3 or 2 values. In this case, the values + * correspond to `x,low,high`. If the first value is a string, it is + * applied as the name of the point, and the `x` value is inferred. + * The `x` value can also be omitted, in which case the inner arrays + * should be of length 2\. Then the `x` value is automatically calculated, + * either starting at 0 and incremented by 1, or from `pointStart` + * and `pointInterval` given in the series options. + * ```js + * data: [ + * [0, 8, 3], + * [1, 1, 1], + * [2, 6, 8] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.arearange.turboThreshold), + * this option is not available. + * ```js + * data: [{ + * x: 1, + * low: 9, + * high: 0, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * low: 3, + * high: 4, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|Array<(number|string),number,number>|*>} + * @extends series.line.data + * @excluding marker, y + * @product highcharts highstock + * @apioption series.arearange.data + */ +/** + * @extends series.arearange.dataLabels + * @product highcharts highstock + * @apioption series.arearange.data.dataLabels + */ +/** + * The high or maximum value for each data point. + * + * @type {number} + * @product highcharts highstock + * @apioption series.arearange.data.high + */ +/** + * The low or minimum value for each data point. + * + * @type {number} + * @product highcharts highstock + * @apioption series.arearange.data.low + */ +''; // adds doclets above to tranpiled file diff --git a/librerias/gantt/code/es-modules/parts-more/AreaSplineRangeSeries.js b/librerias/gantt/code/es-modules/parts-more/AreaSplineRangeSeries.js new file mode 100644 index 0000000..13f2058 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-more/AreaSplineRangeSeries.js @@ -0,0 +1,98 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var seriesType = U.seriesType; +import '../parts/Options.js'; +var seriesTypes = H.seriesTypes; +/** + * The area spline range is a cartesian series type with higher and + * lower Y values along an X axis. The area inside the range is colored, and + * the graph outlining the area is a smoothed spline. + * + * @sample {highstock|highstock} stock/demo/areasplinerange/ + * Area spline range + * + * @extends plotOptions.arearange + * @since 2.3.0 + * @excluding step + * @product highcharts highstock + * @requires highcharts-more + * @apioption plotOptions.areasplinerange + */ +seriesType('areasplinerange', 'arearange', null, { + getPointSpline: seriesTypes.spline.prototype.getPointSpline +}); +/** + * A `areasplinerange` series. If the [type](#series.areasplinerange.type) + * option is not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.areasplinerange + * @excluding dataParser, dataURL, stack, step + * @product highcharts highstock + * @requires highcharts-more + * @apioption series.areasplinerange + */ +/** + * An array of data points for the series. For the `areasplinerange` + * series type, points can be given in the following ways: + * + * 1. An array of arrays with 3 or 2 values. In this case, the values correspond + * to `x,low,high`. If the first value is a string, it is applied as the name + * of the point, and the `x` value is inferred. The `x` value can also be + * omitted, in which case the inner arrays should be of length 2\. Then the + * `x` value is automatically calculated, either starting at 0 and + * incremented by 1, or from `pointStart` and `pointInterval` given in the + * series options. + * ```js + * data: [ + * [0, 0, 5], + * [1, 9, 1], + * [2, 5, 2] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.areasplinerange.turboThreshold), this option is + * not available. + * ```js + * data: [{ + * x: 1, + * low: 5, + * high: 0, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * low: 4, + * high: 1, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|Array<(number|string),number,number>|*>} + * @extends series.arearange.data + * @product highcharts highstock + * @apioption series.areasplinerange.data + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/parts-more/BoxPlotSeries.js b/librerias/gantt/code/es-modules/parts-more/BoxPlotSeries.js new file mode 100644 index 0000000..e8add7d --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-more/BoxPlotSeries.js @@ -0,0 +1,616 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var pick = U.pick, seriesType = U.seriesType; +import '../parts/Options.js'; +var noop = H.noop, seriesTypes = H.seriesTypes; +/** + * The boxplot series type. + * + * @private + * @class + * @name Highcharts.seriesTypes#boxplot + * + * @augments Highcharts.Series + */ +/** + * A box plot is a convenient way of depicting groups of data through their + * five-number summaries: the smallest observation (sample minimum), lower + * quartile (Q1), median (Q2), upper quartile (Q3), and largest observation + * (sample maximum). + * + * @sample highcharts/demo/box-plot/ + * Box plot + * + * @extends plotOptions.column + * @excluding borderColor, borderRadius, borderWidth, groupZPadding, states + * @product highcharts + * @requires highcharts-more + * @optionparent plotOptions.boxplot + */ +seriesType('boxplot', 'column', { + threshold: null, + tooltip: { + pointFormat: '\u25CF ' + + '{series.name}
' + + 'Maximum: {point.high}
' + + 'Upper quartile: {point.q3}
' + + 'Median: {point.median}
' + + 'Lower quartile: {point.q1}
' + + 'Minimum: {point.low}
' + }, + /** + * The length of the whiskers, the horizontal lines marking low and + * high values. It can be a numerical pixel value, or a percentage + * value of the box width. Set `0` to disable whiskers. + * + * @sample {highcharts} highcharts/plotoptions/box-plot-styling/ + * True by default + * + * @type {number|string} + * @since 3.0 + * @product highcharts + */ + whiskerLength: '50%', + /** + * The fill color of the box. + * + * In styled mode, the fill color can be set with the + * `.highcharts-boxplot-box` class. + * + * @sample {highcharts} highcharts/plotoptions/box-plot-styling/ + * Box plot styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #ffffff + * @since 3.0 + * @product highcharts + */ + fillColor: '#ffffff', + /** + * The width of the line surrounding the box. If any of + * [stemWidth](#plotOptions.boxplot.stemWidth), + * [medianWidth](#plotOptions.boxplot.medianWidth) + * or [whiskerWidth](#plotOptions.boxplot.whiskerWidth) are `null`, + * the lineWidth also applies to these lines. + * + * @sample {highcharts} highcharts/plotoptions/box-plot-styling/ + * Box plot styling + * @sample {highcharts} highcharts/plotoptions/error-bar-styling/ + * Error bar styling + * + * @since 3.0 + * @product highcharts + */ + lineWidth: 1, + /** + * The color of the median line. If `undefined`, the general series color + * applies. + * + * In styled mode, the median stroke width can be set with the + * `.highcharts-boxplot-median` class. + * + * @sample {highcharts} highcharts/plotoptions/box-plot-styling/ + * Box plot styling + * @sample {highcharts} highcharts/css/boxplot/ + * Box plot in styled mode + * @sample {highcharts} highcharts/plotoptions/error-bar-styling/ + * Error bar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject} + * @since 3.0 + * @product highcharts + * @apioption plotOptions.boxplot.medianColor + */ + /** + * The pixel width of the median line. If `null`, the + * [lineWidth](#plotOptions.boxplot.lineWidth) is used. + * + * In styled mode, the median stroke width can be set with the + * `.highcharts-boxplot-median` class. + * + * @sample {highcharts} highcharts/plotoptions/box-plot-styling/ + * Box plot styling + * @sample {highcharts} highcharts/css/boxplot/ + * Box plot in styled mode + * + * @type {number|null} + * @since 3.0 + * @product highcharts + */ + medianWidth: 2, + /* + // States are not working and are removed from docs. + // Refer to: #2340 + states: { + hover: { + brightness: -0.3 + } + }, + + /** + * The color of the stem, the vertical line extending from the box to + * the whiskers. If `undefined`, the series color is used. + * + * In styled mode, the stem stroke can be set with the + * `.highcharts-boxplot-stem` class. + * + * @sample {highcharts} highcharts/plotoptions/box-plot-styling/ + * Box plot styling + * @sample {highcharts} highcharts/css/boxplot/ + * Box plot in styled mode + * @sample {highcharts} highcharts/plotoptions/error-bar-styling/ + * Error bar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 3.0 + * @product highcharts + * @apioption plotOptions.boxplot.stemColor + */ + /** + * The dash style of the box. + * + * @sample {highcharts} highcharts/plotoptions/box-plot-styling/ + * Box plot styling + * @sample {highcharts} highcharts/css/boxplot/ + * Box plot in styled mode + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 8.1.0 + * @product highcharts + * @apioption plotOptions.boxplot.boxDashStyle + */ + /** + * The dash style of the median. + * + * @sample {highcharts} highcharts/plotoptions/box-plot-styling/ + * Box plot styling + * @sample {highcharts} highcharts/css/boxplot/ + * Box plot in styled mode + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 8.1.0 + * @product highcharts + * @apioption plotOptions.boxplot.medianDashStyle + */ + /** + * The dash style of the stem, the vertical line extending from the + * box to the whiskers. + * + * @sample {highcharts} highcharts/plotoptions/box-plot-styling/ + * Box plot styling + * @sample {highcharts} highcharts/css/boxplot/ + * Box plot in styled mode + * @sample {highcharts} highcharts/plotoptions/error-bar-styling/ + * Error bar styling + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 3.0 + * @product highcharts + * @apioption plotOptions.boxplot.stemDashStyle + */ + /** + * The dash style of the whiskers. + * + * @sample {highcharts} highcharts/plotoptions/box-plot-styling/ + * Box plot styling + * @sample {highcharts} highcharts/css/boxplot/ + * Box plot in styled mode + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 8.1.0 + * @product highcharts + * @apioption plotOptions.boxplot.whiskerDashStyle + */ + /** + * The width of the stem, the vertical line extending from the box to + * the whiskers. If `undefined`, the width is inherited from the + * [lineWidth](#plotOptions.boxplot.lineWidth) option. + * + * In styled mode, the stem stroke width can be set with the + * `.highcharts-boxplot-stem` class. + * + * @sample {highcharts} highcharts/plotoptions/box-plot-styling/ + * Box plot styling + * @sample {highcharts} highcharts/css/boxplot/ + * Box plot in styled mode + * @sample {highcharts} highcharts/plotoptions/error-bar-styling/ + * Error bar styling + * + * @type {number} + * @since 3.0 + * @product highcharts + * @apioption plotOptions.boxplot.stemWidth + */ + /** + * @default high + * @apioption plotOptions.boxplot.colorKey + */ + /** + * The color of the whiskers, the horizontal lines marking low and high + * values. When `undefined`, the general series color is used. + * + * In styled mode, the whisker stroke can be set with the + * `.highcharts-boxplot-whisker` class . + * + * @sample {highcharts} highcharts/plotoptions/box-plot-styling/ + * Box plot styling + * @sample {highcharts} highcharts/css/boxplot/ + * Box plot in styled mode + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 3.0 + * @product highcharts + * @apioption plotOptions.boxplot.whiskerColor + */ + /** + * The line width of the whiskers, the horizontal lines marking low and + * high values. When `undefined`, the general + * [lineWidth](#plotOptions.boxplot.lineWidth) applies. + * + * In styled mode, the whisker stroke width can be set with the + * `.highcharts-boxplot-whisker` class. + * + * @sample {highcharts} highcharts/plotoptions/box-plot-styling/ + * Box plot styling + * @sample {highcharts} highcharts/css/boxplot/ + * Box plot in styled mode + * + * @since 3.0 + * @product highcharts + */ + whiskerWidth: 2 +}, /** @lends Highcharts.seriesTypes.boxplot */ { + // array point configs are mapped to this + pointArrayMap: ['low', 'q1', 'median', 'q3', 'high'], + // return a plain array for speedy calculation + toYData: function (point) { + return [point.low, point.q1, point.median, point.q3, point.high]; + }, + // defines the top of the tracker + pointValKey: 'high', + // Get presentational attributes + pointAttribs: function () { + // No attributes should be set on point.graphic which is the group + return {}; + }, + // Disable data labels for box plot + drawDataLabels: noop, + // Translate data points from raw values x and y to plotX and plotY + translate: function () { + var series = this, yAxis = series.yAxis, pointArrayMap = series.pointArrayMap; + seriesTypes.column.prototype.translate.apply(series); + // do the translation on each point dimension + series.points.forEach(function (point) { + pointArrayMap.forEach(function (key) { + if (point[key] !== null) { + point[key + 'Plot'] = yAxis.translate(point[key], 0, 1, 0, 1); + } + }); + point.plotHigh = point.highPlot; // For data label validation + }); + }, + // eslint-disable-next-line valid-jsdoc + /** + * Draw the data points + * @private + */ + drawPoints: function () { + var series = this, points = series.points, options = series.options, chart = series.chart, renderer = chart.renderer, q1Plot, q3Plot, highPlot, lowPlot, medianPlot, medianPath, crispCorr, crispX = 0, boxPath, width, left, right, halfWidth, + // error bar inherits this series type but doesn't do quartiles + doQuartiles = series.doQuartiles !== false, pointWiskerLength, whiskerLength = series.options.whiskerLength; + points.forEach(function (point) { + var graphic = point.graphic, verb = graphic ? 'animate' : 'attr', shapeArgs = point.shapeArgs, boxAttr = {}, stemAttr = {}, whiskersAttr = {}, medianAttr = {}, color = point.color || series.color; + if (typeof point.plotY !== 'undefined') { + // crisp vector coordinates + width = Math.round(shapeArgs.width); + left = Math.floor(shapeArgs.x); + right = left + width; + halfWidth = Math.round(width / 2); + q1Plot = Math.floor(doQuartiles ? point.q1Plot : point.lowPlot); + q3Plot = Math.floor(doQuartiles ? point.q3Plot : point.lowPlot); + highPlot = Math.floor(point.highPlot); + lowPlot = Math.floor(point.lowPlot); + if (!graphic) { + point.graphic = graphic = renderer.g('point') + .add(series.group); + point.stem = renderer.path() + .addClass('highcharts-boxplot-stem') + .add(graphic); + if (whiskerLength) { + point.whiskers = renderer.path() + .addClass('highcharts-boxplot-whisker') + .add(graphic); + } + if (doQuartiles) { + point.box = renderer.path(boxPath) + .addClass('highcharts-boxplot-box') + .add(graphic); + } + point.medianShape = renderer.path(medianPath) + .addClass('highcharts-boxplot-median') + .add(graphic); + } + if (!chart.styledMode) { + // Stem attributes + stemAttr.stroke = + point.stemColor || options.stemColor || color; + stemAttr['stroke-width'] = pick(point.stemWidth, options.stemWidth, options.lineWidth); + stemAttr.dashstyle = (point.stemDashStyle || + options.stemDashStyle || + options.dashStyle); + point.stem.attr(stemAttr); + // Whiskers attributes + if (whiskerLength) { + whiskersAttr.stroke = (point.whiskerColor || + options.whiskerColor || + color); + whiskersAttr['stroke-width'] = pick(point.whiskerWidth, options.whiskerWidth, options.lineWidth); + whiskersAttr.dashstyle = (point.whiskerDashStyle || + options.whiskerDashStyle || + options.dashStyle); + point.whiskers.attr(whiskersAttr); + } + if (doQuartiles) { + boxAttr.fill = (point.fillColor || + options.fillColor || + color); + boxAttr.stroke = options.lineColor || color; + boxAttr['stroke-width'] = options.lineWidth || 0; + boxAttr.dashstyle = (point.boxDashStyle || + options.boxDashStyle || + options.dashStyle); + point.box.attr(boxAttr); + } + // Median attributes + medianAttr.stroke = (point.medianColor || + options.medianColor || + color); + medianAttr['stroke-width'] = pick(point.medianWidth, options.medianWidth, options.lineWidth); + medianAttr.dashstyle = (point.medianDashStyle || + options.medianDashStyle || + options.dashStyle); + point.medianShape.attr(medianAttr); + } + var d = void 0; + // The stem + crispCorr = (point.stem.strokeWidth() % 2) / 2; + crispX = left + halfWidth + crispCorr; + d = [ + // stem up + ['M', crispX, q3Plot], + ['L', crispX, highPlot], + // stem down + ['M', crispX, q1Plot], + ['L', crispX, lowPlot] + ]; + point.stem[verb]({ d: d }); + // The box + if (doQuartiles) { + crispCorr = (point.box.strokeWidth() % 2) / 2; + q1Plot = Math.floor(q1Plot) + crispCorr; + q3Plot = Math.floor(q3Plot) + crispCorr; + left += crispCorr; + right += crispCorr; + d = [ + ['M', left, q3Plot], + ['L', left, q1Plot], + ['L', right, q1Plot], + ['L', right, q3Plot], + ['L', left, q3Plot], + ['Z'] + ]; + point.box[verb]({ d: d }); + } + // The whiskers + if (whiskerLength) { + crispCorr = (point.whiskers.strokeWidth() % 2) / 2; + highPlot = highPlot + crispCorr; + lowPlot = lowPlot + crispCorr; + pointWiskerLength = (/%$/).test(whiskerLength) ? + halfWidth * parseFloat(whiskerLength) / 100 : + whiskerLength / 2; + d = [ + // High whisker + ['M', crispX - pointWiskerLength, highPlot], + ['L', crispX + pointWiskerLength, highPlot], + // Low whisker + ['M', crispX - pointWiskerLength, lowPlot], + ['L', crispX + pointWiskerLength, lowPlot] + ]; + point.whiskers[verb]({ d: d }); + } + // The median + medianPlot = Math.round(point.medianPlot); + crispCorr = (point.medianShape.strokeWidth() % 2) / 2; + medianPlot = medianPlot + crispCorr; + d = [ + ['M', left, medianPlot], + ['L', right, medianPlot] + ]; + point.medianShape[verb]({ d: d }); + } + }); + }, + setStackedPoints: noop // #3890 +}); +/** + * A `boxplot` series. If the [type](#series.boxplot.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.boxplot + * @excluding dataParser, dataURL, marker, stack, stacking, states + * @product highcharts + * @requires highcharts-more + * @apioption series.boxplot + */ +/** + * An array of data points for the series. For the `boxplot` series + * type, points can be given in the following ways: + * + * 1. An array of arrays with 6 or 5 values. In this case, the values correspond + * to `x,low,q1,median,q3,high`. If the first value is a string, it is + * applied as the name of the point, and the `x` value is inferred. The `x` + * value can also be omitted, in which case the inner arrays should be of + * length 5. Then the `x` value is automatically calculated, either starting + * at 0 and incremented by 1, or from `pointStart` and `pointInterval` given + * in the series options. + * ```js + * data: [ + * [0, 3, 0, 10, 3, 5], + * [1, 7, 8, 7, 2, 9], + * [2, 6, 9, 5, 1, 3] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.boxplot.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * low: 4, + * q1: 9, + * median: 9, + * q3: 1, + * high: 10, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * low: 5, + * q1: 7, + * median: 3, + * q3: 6, + * high: 2, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|Array<(number|string),number,number,number,number,number>|*>} + * @extends series.line.data + * @excluding marker + * @product highcharts + * @apioption series.boxplot.data + */ +/** + * The `high` value for each data point, signifying the highest value + * in the sample set. The top whisker is drawn here. + * + * @type {number} + * @product highcharts + * @apioption series.boxplot.data.high + */ +/** + * The `low` value for each data point, signifying the lowest value + * in the sample set. The bottom whisker is drawn here. + * + * @type {number} + * @product highcharts + * @apioption series.boxplot.data.low + */ +/** + * The median for each data point. This is drawn as a line through the + * middle area of the box. + * + * @type {number} + * @product highcharts + * @apioption series.boxplot.data.median + */ +/** + * The lower quartile for each data point. This is the bottom of the + * box. + * + * @type {number} + * @product highcharts + * @apioption series.boxplot.data.q1 + */ +/** + * The higher quartile for each data point. This is the top of the box. + * + * @type {number} + * @product highcharts + * @apioption series.boxplot.data.q3 + */ +/** + * The dash style of the box. + * + * @sample {highcharts} highcharts/plotoptions/box-plot-styling/ + * Box plot styling + * @sample {highcharts} highcharts/css/boxplot/ + * Box plot in styled mode + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 8.1.0 + * @product highcharts + * @apioption series.boxplot.data.boxDashStyle + */ +/** + * The dash style of the median. + * + * @sample {highcharts} highcharts/plotoptions/box-plot-styling/ + * Box plot styling + * @sample {highcharts} highcharts/css/boxplot/ + * Box plot in styled mode + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 8.1.0 + * @product highcharts + * @apioption series.boxplot.data.medianDashStyle + */ +/** + * The dash style of the stem. + * + * @sample {highcharts} highcharts/plotoptions/box-plot-styling/ + * Box plot styling + * @sample {highcharts} highcharts/css/boxplot/ + * Box plot in styled mode + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 8.1.0 + * @product highcharts + * @apioption series.boxplot.data.stemDashStyle + */ +/** + * The dash style of the whiskers. + * + * @sample {highcharts} highcharts/plotoptions/box-plot-styling/ + * Box plot styling + * @sample {highcharts} highcharts/css/boxplot/ + * Box plot in styled mode + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 8.1.0 + * @product highcharts + * @apioption series.boxplot.data.whiskerDashStyle + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/parts-more/BubbleLegend.js b/librerias/gantt/code/es-modules/parts-more/BubbleLegend.js new file mode 100644 index 0000000..451b3b1 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-more/BubbleLegend.js @@ -0,0 +1,904 @@ +/* * + * + * (c) 2010-2020 Highsoft AS + * + * Author: Paweł Potaczek + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +/** + * @interface Highcharts.BubbleLegendFormatterContextObject + */ /** +* The center y position of the range. +* @name Highcharts.BubbleLegendFormatterContextObject#center +* @type {number} +*/ /** +* The radius of the bubble range. +* @name Highcharts.BubbleLegendFormatterContextObject#radius +* @type {number} +*/ /** +* The bubble value. +* @name Highcharts.BubbleLegendFormatterContextObject#value +* @type {number} +*/ +''; // detach doclets above +import Color from '../parts/Color.js'; +var color = Color.parse; +import Legend from '../parts/Legend.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, arrayMax = U.arrayMax, arrayMin = U.arrayMin, isNumber = U.isNumber, merge = U.merge, objectEach = U.objectEach, pick = U.pick, stableSort = U.stableSort, wrap = U.wrap; +var Series = H.Series, Chart = H.Chart, noop = H.noop, setOptions = H.setOptions; +setOptions({ + legend: { + /** + * The bubble legend is an additional element in legend which + * presents the scale of the bubble series. Individual bubble ranges + * can be defined by user or calculated from series. In the case of + * automatically calculated ranges, a 1px margin of error is + * permitted. + * + * @since 7.0.0 + * @product highcharts highstock highmaps + * @requires highcharts-more + * @optionparent legend.bubbleLegend + */ + bubbleLegend: { + /** + * The color of the ranges borders, can be also defined for an + * individual range. + * + * @sample highcharts/bubble-legend/similartoseries/ + * Similat look to the bubble series + * @sample highcharts/bubble-legend/bordercolor/ + * Individual bubble border color + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + borderColor: void 0, + /** + * The width of the ranges borders in pixels, can be also + * defined for an individual range. + */ + borderWidth: 2, + /** + * An additional class name to apply to the bubble legend' + * circle graphical elements. This option does not replace + * default class names of the graphical element. + * + * @sample {highcharts} highcharts/css/bubble-legend/ + * Styling by CSS + * + * @type {string} + */ + className: void 0, + /** + * The main color of the bubble legend. Applies to ranges, if + * individual color is not defined. + * + * @sample highcharts/bubble-legend/similartoseries/ + * Similat look to the bubble series + * @sample highcharts/bubble-legend/color/ + * Individual bubble color + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + color: void 0, + /** + * An additional class name to apply to the bubble legend's + * connector graphical elements. This option does not replace + * default class names of the graphical element. + * + * @sample {highcharts} highcharts/css/bubble-legend/ + * Styling by CSS + * + * @type {string} + */ + connectorClassName: void 0, + /** + * The color of the connector, can be also defined + * for an individual range. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + connectorColor: void 0, + /** + * The length of the connectors in pixels. If labels are + * centered, the distance is reduced to 0. + * + * @sample highcharts/bubble-legend/connectorandlabels/ + * Increased connector length + */ + connectorDistance: 60, + /** + * The width of the connectors in pixels. + * + * @sample highcharts/bubble-legend/connectorandlabels/ + * Increased connector width + */ + connectorWidth: 1, + /** + * Enable or disable the bubble legend. + */ + enabled: false, + /** + * Options for the bubble legend labels. + */ + labels: { + /** + * An additional class name to apply to the bubble legend + * label graphical elements. This option does not replace + * default class names of the graphical element. + * + * @sample {highcharts} highcharts/css/bubble-legend/ + * Styling by CSS + * + * @type {string} + */ + className: void 0, + /** + * Whether to allow data labels to overlap. + */ + allowOverlap: false, + /** + * A format string for the bubble legend labels. Available + * variables are the same as for `formatter`. + * + * @sample highcharts/bubble-legend/format/ + * Add a unit + * + * @type {string} + */ + format: '', + /** + * Available `this` properties are: + * + * - `this.value`: The bubble value. + * + * - `this.radius`: The radius of the bubble range. + * + * - `this.center`: The center y position of the range. + * + * @type {Highcharts.FormatterCallbackFunction} + */ + formatter: void 0, + /** + * The alignment of the labels compared to the bubble + * legend. Can be one of `left`, `center` or `right`. + * + * @sample highcharts/bubble-legend/connectorandlabels/ + * Labels on left + * + * @type {Highcharts.AlignValue} + */ + align: 'right', + /** + * CSS styles for the labels. + * + * @type {Highcharts.CSSObject} + */ + style: { + /** @ignore-option */ + fontSize: 10, + /** @ignore-option */ + color: void 0 + }, + /** + * The x position offset of the label relative to the + * connector. + */ + x: 0, + /** + * The y position offset of the label relative to the + * connector. + */ + y: 0 + }, + /** + * Miximum bubble legend range size. If values for ranges are + * not specified, the `minSize` and the `maxSize` are calculated + * from bubble series. + */ + maxSize: 60, + /** + * Minimum bubble legend range size. If values for ranges are + * not specified, the `minSize` and the `maxSize` are calculated + * from bubble series. + */ + minSize: 10, + /** + * The position of the bubble legend in the legend. + * @sample highcharts/bubble-legend/connectorandlabels/ + * Bubble legend as last item in legend + */ + legendIndex: 0, + /** + * Options for specific range. One range consists of bubble, + * label and connector. + * + * @sample highcharts/bubble-legend/ranges/ + * Manually defined ranges + * @sample highcharts/bubble-legend/autoranges/ + * Auto calculated ranges + * + * @type {Array<*>} + */ + ranges: { + /** + * Range size value, similar to bubble Z data. + * @type {number} + */ + value: void 0, + /** + * The color of the border for individual range. + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + borderColor: void 0, + /** + * The color of the bubble for individual range. + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + color: void 0, + /** + * The color of the connector for individual range. + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + connectorColor: void 0 + }, + /** + * Whether the bubble legend range value should be represented + * by the area or the width of the bubble. The default, area, + * corresponds best to the human perception of the size of each + * bubble. + * + * @sample highcharts/bubble-legend/ranges/ + * Size by width + * + * @type {Highcharts.BubbleSizeByValue} + */ + sizeBy: 'area', + /** + * When this is true, the absolute value of z determines the + * size of the bubble. This means that with the default + * zThreshold of 0, a bubble of value -1 will have the same size + * as a bubble of value 1, while a bubble of value 0 will have a + * smaller size according to minSize. + */ + sizeByAbsoluteValue: false, + /** + * Define the visual z index of the bubble legend. + */ + zIndex: 1, + /** + * Ranges with with lower value than zThreshold, are skipped. + */ + zThreshold: 0 + } + } +}); +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * BubbleLegend class. + * + * @private + * @class + * @name Highcharts.BubbleLegend + * @param {Highcharts.LegendBubbleLegendOptions} options + * Bubble legend options + * @param {Highcharts.Legend} legend + * Legend + */ +var BubbleLegend = /** @class */ (function () { + function BubbleLegend(options, legend) { + this.chart = void 0; + this.fontMetrics = void 0; + this.legend = void 0; + this.legendGroup = void 0; + this.legendItem = void 0; + this.legendItemHeight = void 0; + this.legendItemWidth = void 0; + this.legendSymbol = void 0; + this.maxLabel = void 0; + this.movementX = void 0; + this.ranges = void 0; + this.visible = void 0; + this.symbols = void 0; + this.options = void 0; + this.setState = noop; + this.init(options, legend); + } + /** + * Create basic bubbleLegend properties similar to item in legend. + * + * @private + * @function Highcharts.BubbleLegend#init + * @param {Highcharts.LegendBubbleLegendOptions} options + * Bubble legend options + * @param {Highcharts.Legend} legend + * Legend + * @return {void} + */ + BubbleLegend.prototype.init = function (options, legend) { + this.options = options; + this.visible = true; + this.chart = legend.chart; + this.legend = legend; + }; + /** + * Depending on the position option, add bubbleLegend to legend items. + * + * @private + * @function Highcharts.BubbleLegend#addToLegend + * @param {Array<(Highcharts.Point|Highcharts.Series)>} + * All legend items + * @return {void} + */ + BubbleLegend.prototype.addToLegend = function (items) { + // Insert bubbleLegend into legend items + items.splice(this.options.legendIndex, 0, this); + }; + /** + * Calculate ranges, sizes and call the next steps of bubbleLegend + * creation. + * + * @private + * @function Highcharts.BubbleLegend#drawLegendSymbol + * @param {Highcharts.Legend} legend + * Legend instance + * @return {void} + */ + BubbleLegend.prototype.drawLegendSymbol = function (legend) { + var chart = this.chart, options = this.options, size, itemDistance = pick(legend.options.itemDistance, 20), connectorSpace, ranges = options.ranges, radius, maxLabel, connectorDistance = options.connectorDistance; + // Predict label dimensions + this.fontMetrics = chart.renderer.fontMetrics(options.labels.style.fontSize.toString() + 'px'); + // Do not create bubbleLegend now if ranges or ranges valeus are not + // specified or if are empty array. + if (!ranges || !ranges.length || !isNumber(ranges[0].value)) { + legend.options.bubbleLegend.autoRanges = true; + return; + } + // Sort ranges to right render order + stableSort(ranges, function (a, b) { + return b.value - a.value; + }); + this.ranges = ranges; + this.setOptions(); + this.render(); + // Get max label size + maxLabel = this.getMaxLabelSize(); + radius = this.ranges[0].radius; + size = radius * 2; + // Space for connectors and labels. + connectorSpace = + connectorDistance - radius + maxLabel.width; + connectorSpace = connectorSpace > 0 ? connectorSpace : 0; + this.maxLabel = maxLabel; + this.movementX = options.labels.align === 'left' ? + connectorSpace : 0; + this.legendItemWidth = size + connectorSpace + itemDistance; + this.legendItemHeight = size + this.fontMetrics.h / 2; + }; + /** + * Set style options for each bubbleLegend range. + * + * @private + * @function Highcharts.BubbleLegend#setOptions + * @return {void} + */ + BubbleLegend.prototype.setOptions = function () { + var ranges = this.ranges, options = this.options, series = this.chart.series[options.seriesIndex], baseline = this.legend.baseline, bubbleStyle = { + 'z-index': options.zIndex, + 'stroke-width': options.borderWidth + }, connectorStyle = { + 'z-index': options.zIndex, + 'stroke-width': options.connectorWidth + }, labelStyle = this.getLabelStyles(), fillOpacity = series.options.marker.fillOpacity, styledMode = this.chart.styledMode; + // Allow to parts of styles be used individually for range + ranges.forEach(function (range, i) { + if (!styledMode) { + bubbleStyle.stroke = pick(range.borderColor, options.borderColor, series.color); + bubbleStyle.fill = pick(range.color, options.color, fillOpacity !== 1 ? + color(series.color).setOpacity(fillOpacity) + .get('rgba') : + series.color); + connectorStyle.stroke = pick(range.connectorColor, options.connectorColor, series.color); + } + // Set options needed for rendering each range + ranges[i].radius = this.getRangeRadius(range.value); + ranges[i] = merge(ranges[i], { + center: (ranges[0].radius - ranges[i].radius + + baseline) + }); + if (!styledMode) { + merge(true, ranges[i], { + bubbleStyle: merge(false, bubbleStyle), + connectorStyle: merge(false, connectorStyle), + labelStyle: labelStyle + }); + } + }, this); + }; + /** + * Merge options for bubbleLegend labels. + * + * @private + * @function Highcharts.BubbleLegend#getLabelStyles + * @return {Highcharts.CSSObject} + */ + BubbleLegend.prototype.getLabelStyles = function () { + var options = this.options, additionalLabelsStyle = {}, labelsOnLeft = options.labels.align === 'left', rtl = this.legend.options.rtl; + // To separate additional style options + objectEach(options.labels.style, function (value, key) { + if (key !== 'color' && + key !== 'fontSize' && + key !== 'z-index') { + additionalLabelsStyle[key] = value; + } + }); + return merge(false, additionalLabelsStyle, { + 'font-size': options.labels.style.fontSize, + fill: pick(options.labels.style.color, '#000000'), + 'z-index': options.zIndex, + align: rtl || labelsOnLeft ? 'right' : 'left' + }); + }; + /** + * Calculate radius for each bubble range, + * used code from BubbleSeries.js 'getRadius' method. + * + * @private + * @function Highcharts.BubbleLegend#getRangeRadius + * @param {number} value + * Range value + * @return {number|null} + * Radius for one range + */ + BubbleLegend.prototype.getRangeRadius = function (value) { + var options = this.options, seriesIndex = this.options.seriesIndex, bubbleSeries = this.chart.series[seriesIndex], zMax = options.ranges[0].value, zMin = options.ranges[options.ranges.length - 1].value, minSize = options.minSize, maxSize = options.maxSize; + return bubbleSeries.getRadius.call(this, zMin, zMax, minSize, maxSize, value); + }; + /** + * Render the legendSymbol group. + * + * @private + * @function Highcharts.BubbleLegend#render + * @return {void} + */ + BubbleLegend.prototype.render = function () { + var renderer = this.chart.renderer, zThreshold = this.options.zThreshold; + if (!this.symbols) { + this.symbols = { + connectors: [], + bubbleItems: [], + labels: [] + }; + } + // Nesting SVG groups to enable handleOverflow + this.legendSymbol = renderer.g('bubble-legend'); + this.legendItem = renderer.g('bubble-legend-item'); + // To enable default 'hideOverlappingLabels' method + this.legendSymbol.translateX = 0; + this.legendSymbol.translateY = 0; + this.ranges.forEach(function (range) { + if (range.value >= zThreshold) { + this.renderRange(range); + } + }, this); + // To use handleOverflow method + this.legendSymbol.add(this.legendItem); + this.legendItem.add(this.legendGroup); + this.hideOverlappingLabels(); + }; + /** + * Render one range, consisting of bubble symbol, connector and label. + * + * @private + * @function Highcharts.BubbleLegend#renderRange + * @param {Highcharts.LegendBubbleLegendRangesOptions} range + * Range options + * @return {void} + */ + BubbleLegend.prototype.renderRange = function (range) { + var mainRange = this.ranges[0], legend = this.legend, options = this.options, labelsOptions = options.labels, chart = this.chart, renderer = chart.renderer, symbols = this.symbols, labels = symbols.labels, label, elementCenter = range.center, absoluteRadius = Math.abs(range.radius), connectorDistance = options.connectorDistance || 0, labelsAlign = labelsOptions.align, rtl = legend.options.rtl, fontSize = labelsOptions.style.fontSize, connectorLength = rtl || labelsAlign === 'left' ? + -connectorDistance : connectorDistance, borderWidth = options.borderWidth, connectorWidth = options.connectorWidth, posX = mainRange.radius || 0, posY = elementCenter - absoluteRadius - + borderWidth / 2 + connectorWidth / 2, labelY, labelX, fontMetrics = this.fontMetrics, labelMovement = fontSize / 2 - (fontMetrics.h - fontSize) / 2, crispMovement = (posY % 1 ? 1 : 0.5) - + (connectorWidth % 2 ? 0 : 0.5), styledMode = renderer.styledMode; + // Set options for centered labels + if (labelsAlign === 'center') { + connectorLength = 0; // do not use connector + options.connectorDistance = 0; + range.labelStyle.align = 'center'; + } + labelY = posY + options.labels.y; + labelX = posX + connectorLength + options.labels.x; + // Render bubble symbol + symbols.bubbleItems.push(renderer + .circle(posX, elementCenter + crispMovement, absoluteRadius) + .attr(styledMode ? {} : range.bubbleStyle) + .addClass((styledMode ? + 'highcharts-color-' + + this.options.seriesIndex + ' ' : + '') + + 'highcharts-bubble-legend-symbol ' + + (options.className || '')).add(this.legendSymbol)); + // Render connector + symbols.connectors.push(renderer + .path(renderer.crispLine([ + ['M', posX, posY], + ['L', posX + connectorLength, posY] + ], options.connectorWidth)) + .attr(styledMode ? {} : range.connectorStyle) + .addClass((styledMode ? + 'highcharts-color-' + + this.options.seriesIndex + ' ' : '') + + 'highcharts-bubble-legend-connectors ' + + (options.connectorClassName || '')).add(this.legendSymbol)); + // Render label + label = renderer + .text(this.formatLabel(range), labelX, labelY + labelMovement) + .attr(styledMode ? {} : range.labelStyle) + .addClass('highcharts-bubble-legend-labels ' + + (options.labels.className || '')).add(this.legendSymbol); + labels.push(label); + // To enable default 'hideOverlappingLabels' method + label.placed = true; + label.alignAttr = { + x: labelX, + y: labelY + labelMovement + }; + }; + /** + * Get the label which takes up the most space. + * + * @private + * @function Highcharts.BubbleLegend#getMaxLabelSize + * @return {Highcharts.BBoxObject} + */ + BubbleLegend.prototype.getMaxLabelSize = function () { + var labels = this.symbols.labels, maxLabel, labelSize; + labels.forEach(function (label) { + labelSize = label.getBBox(true); + if (maxLabel) { + maxLabel = labelSize.width > maxLabel.width ? + labelSize : maxLabel; + } + else { + maxLabel = labelSize; + } + }); + return maxLabel || {}; + }; + /** + * Get formatted label for range. + * + * @private + * @function Highcharts.BubbleLegend#formatLabel + * @param {Highcharts.LegendBubbleLegendRangesOptions} range + * Range options + * @return {string} + * Range label text + */ + BubbleLegend.prototype.formatLabel = function (range) { + var options = this.options, formatter = options.labels.formatter, format = options.labels.format; + var numberFormatter = this.chart.numberFormatter; + return format ? U.format(format, range) : + formatter ? formatter.call(range) : + numberFormatter(range.value, 1); + }; + /** + * By using default chart 'hideOverlappingLabels' method, hide or show + * labels and connectors. + * + * @private + * @function Highcharts.BubbleLegend#hideOverlappingLabels + * @return {void} + */ + BubbleLegend.prototype.hideOverlappingLabels = function () { + var chart = this.chart, allowOverlap = this.options.labels.allowOverlap, symbols = this.symbols; + if (!allowOverlap && symbols) { + chart.hideOverlappingLabels(symbols.labels); + // Hide or show connectors + symbols.labels.forEach(function (label, index) { + if (!label.newOpacity) { + symbols.connectors[index].hide(); + } + else if (label.newOpacity !== label.oldOpacity) { + symbols.connectors[index].show(); + } + }); + } + }; + /** + * Calculate ranges from created series. + * + * @private + * @function Highcharts.BubbleLegend#getRanges + * @return {Array} + * Array of range objects + */ + BubbleLegend.prototype.getRanges = function () { + var bubbleLegend = this.legend.bubbleLegend, series = bubbleLegend.chart.series, ranges, rangesOptions = bubbleLegend.options.ranges, zData, minZ = Number.MAX_VALUE, maxZ = -Number.MAX_VALUE; + series.forEach(function (s) { + // Find the min and max Z, like in bubble series + if (s.isBubble && !s.ignoreSeries) { + zData = s.zData.filter(isNumber); + if (zData.length) { + minZ = pick(s.options.zMin, Math.min(minZ, Math.max(arrayMin(zData), s.options.displayNegative === false ? + s.options.zThreshold : + -Number.MAX_VALUE))); + maxZ = pick(s.options.zMax, Math.max(maxZ, arrayMax(zData))); + } + } + }); + // Set values for ranges + if (minZ === maxZ) { + // Only one range if min and max values are the same. + ranges = [{ value: maxZ }]; + } + else { + ranges = [ + { value: minZ }, + { value: (minZ + maxZ) / 2 }, + { value: maxZ, autoRanges: true } + ]; + } + // Prevent reverse order of ranges after redraw + if (rangesOptions.length && rangesOptions[0].radius) { + ranges.reverse(); + } + // Merge ranges values with user options + ranges.forEach(function (range, i) { + if (rangesOptions && rangesOptions[i]) { + ranges[i] = merge(false, rangesOptions[i], range); + } + }); + return ranges; + }; + /** + * Calculate bubble legend sizes from rendered series. + * + * @private + * @function Highcharts.BubbleLegend#predictBubbleSizes + * @return {Array} + * Calculated min and max bubble sizes + */ + BubbleLegend.prototype.predictBubbleSizes = function () { + var chart = this.chart, fontMetrics = this.fontMetrics, legendOptions = chart.legend.options, floating = legendOptions.floating, horizontal = legendOptions.layout === 'horizontal', lastLineHeight = horizontal ? chart.legend.lastLineHeight : 0, plotSizeX = chart.plotSizeX, plotSizeY = chart.plotSizeY, bubbleSeries = chart.series[this.options.seriesIndex], minSize = Math.ceil(bubbleSeries.minPxSize), maxPxSize = Math.ceil(bubbleSeries.maxPxSize), maxSize = bubbleSeries.options.maxSize, plotSize = Math.min(plotSizeY, plotSizeX), calculatedSize; + // Calculate prediceted max size of bubble + if (floating || !(/%$/.test(maxSize))) { + calculatedSize = maxPxSize; + } + else { + maxSize = parseFloat(maxSize); + calculatedSize = ((plotSize + lastLineHeight - + fontMetrics.h / 2) * maxSize / 100) / (maxSize / 100 + 1); + // Get maxPxSize from bubble series if calculated bubble legend + // size will not affect to bubbles series. + if ((horizontal && plotSizeY - calculatedSize >= + plotSizeX) || (!horizontal && plotSizeX - + calculatedSize >= plotSizeY)) { + calculatedSize = maxPxSize; + } + } + return [minSize, Math.ceil(calculatedSize)]; + }; + /** + * Correct ranges with calculated sizes. + * + * @private + * @function Highcharts.BubbleLegend#updateRanges + * @param {number} min + * @param {number} max + * @return {void} + */ + BubbleLegend.prototype.updateRanges = function (min, max) { + var bubbleLegendOptions = this.legend.options.bubbleLegend; + bubbleLegendOptions.minSize = min; + bubbleLegendOptions.maxSize = max; + bubbleLegendOptions.ranges = this.getRanges(); + }; + /** + * Because of the possibility of creating another legend line, predicted + * bubble legend sizes may differ by a few pixels, so it is necessary to + * correct them. + * + * @private + * @function Highcharts.BubbleLegend#correctSizes + * @return {void} + */ + BubbleLegend.prototype.correctSizes = function () { + var legend = this.legend, chart = this.chart, bubbleSeries = chart.series[this.options.seriesIndex], bubbleSeriesSize = bubbleSeries.maxPxSize, bubbleLegendSize = this.options.maxSize; + if (Math.abs(Math.ceil(bubbleSeriesSize) - bubbleLegendSize) > + 1) { + this.updateRanges(this.options.minSize, bubbleSeries.maxPxSize); + legend.render(); + } + }; + return BubbleLegend; +}()); +// Start the bubble legend creation process. +addEvent(Legend, 'afterGetAllItems', function (e) { + var legend = this, bubbleLegend = legend.bubbleLegend, legendOptions = legend.options, options = legendOptions.bubbleLegend, bubbleSeriesIndex = legend.chart.getVisibleBubbleSeriesIndex(); + // Remove unnecessary element + if (bubbleLegend && bubbleLegend.ranges && bubbleLegend.ranges.length) { + // Allow change the way of calculating ranges in update + if (options.ranges.length) { + options.autoRanges = + !!options.ranges[0].autoRanges; + } + // Update bubbleLegend dimensions in each redraw + legend.destroyItem(bubbleLegend); + } + // Create bubble legend + if (bubbleSeriesIndex >= 0 && + legendOptions.enabled && + options.enabled) { + options.seriesIndex = bubbleSeriesIndex; + legend.bubbleLegend = new H.BubbleLegend(options, legend); + legend.bubbleLegend.addToLegend(e.allItems); + } +}); +/** + * Check if there is at least one visible bubble series. + * + * @private + * @function Highcharts.Chart#getVisibleBubbleSeriesIndex + * @return {number} + * First visible bubble series index + */ +Chart.prototype.getVisibleBubbleSeriesIndex = function () { + var series = this.series, i = 0; + while (i < series.length) { + if (series[i] && + series[i].isBubble && + series[i].visible && + series[i].zData.length) { + return i; + } + i++; + } + return -1; +}; +/** + * Calculate height for each row in legend. + * + * @private + * @function Highcharts.Legend#getLinesHeights + * @return {Array>} + * Informations about line height and items amount + */ +Legend.prototype.getLinesHeights = function () { + var items = this.allItems, lines = [], lastLine, length = items.length, i = 0, j = 0; + for (i = 0; i < length; i++) { + if (items[i].legendItemHeight) { + // for bubbleLegend + items[i].itemHeight = items[i].legendItemHeight; + } + if ( // Line break + items[i] === items[length - 1] || + items[i + 1] && + items[i]._legendItemPos[1] !== + items[i + 1]._legendItemPos[1]) { + lines.push({ height: 0 }); + lastLine = lines[lines.length - 1]; + // Find the highest item in line + for (j; j <= i; j++) { + if (items[j].itemHeight > lastLine.height) { + lastLine.height = items[j].itemHeight; + } + } + lastLine.step = i; + } + } + return lines; +}; +/** + * Correct legend items translation in case of different elements heights. + * + * @private + * @function Highcharts.Legend#retranslateItems + * @param {Array>} lines + * Informations about line height and items amount + * @return {void} + */ +Legend.prototype.retranslateItems = function (lines) { + var items = this.allItems, orgTranslateX, orgTranslateY, movementX, rtl = this.options.rtl, actualLine = 0; + items.forEach(function (item, index) { + orgTranslateX = item.legendGroup.translateX; + orgTranslateY = item._legendItemPos[1]; + movementX = item.movementX; + if (movementX || (rtl && item.ranges)) { + movementX = rtl ? + orgTranslateX - item.options.maxSize / 2 : + orgTranslateX + movementX; + item.legendGroup.attr({ translateX: movementX }); + } + if (index > lines[actualLine].step) { + actualLine++; + } + item.legendGroup.attr({ + translateY: Math.round(orgTranslateY + lines[actualLine].height / 2) + }); + item._legendItemPos[1] = orgTranslateY + + lines[actualLine].height / 2; + }); +}; +// Toggle bubble legend depending on the visible status of bubble series. +addEvent(Series, 'legendItemClick', function () { + var series = this, chart = series.chart, visible = series.visible, legend = series.chart.legend, status; + if (legend && legend.bubbleLegend) { + // Temporary correct 'visible' property + series.visible = !visible; + // Save future status for getRanges method + series.ignoreSeries = visible; + // Check if at lest one bubble series is visible + status = chart.getVisibleBubbleSeriesIndex() >= 0; + // Hide bubble legend if all bubble series are disabled + if (legend.bubbleLegend.visible !== status) { + // Show or hide bubble legend + legend.update({ + bubbleLegend: { enabled: status } + }); + legend.bubbleLegend.visible = status; // Restore default status + } + series.visible = visible; + } +}); +// If ranges are not specified, determine ranges from rendered bubble series +// and render legend again. +wrap(Chart.prototype, 'drawChartBox', function (proceed, options, callback) { + var chart = this, legend = chart.legend, bubbleSeries = chart.getVisibleBubbleSeriesIndex() >= 0, bubbleLegendOptions, bubbleSizes; + if (legend && legend.options.enabled && legend.bubbleLegend && + legend.options.bubbleLegend.autoRanges && bubbleSeries) { + bubbleLegendOptions = legend.bubbleLegend.options; + bubbleSizes = legend.bubbleLegend.predictBubbleSizes(); + legend.bubbleLegend.updateRanges(bubbleSizes[0], bubbleSizes[1]); + // Disable animation on init + if (!bubbleLegendOptions.placed) { + legend.group.placed = false; + legend.allItems.forEach(function (item) { + item.legendGroup.translateY = null; + }); + } + // Create legend with bubbleLegend + legend.render(); + chart.getMargins(); + chart.axes.forEach(function (axis) { + if (axis.visible) { // #11448 + axis.render(); + } + if (!bubbleLegendOptions.placed) { + axis.setScale(); + axis.updateNames(); + // Disable axis animation on init + objectEach(axis.ticks, function (tick) { + tick.isNew = true; + tick.isNewLabel = true; + }); + } + }); + bubbleLegendOptions.placed = true; + // After recalculate axes, calculate margins again. + chart.getMargins(); + // Call default 'drawChartBox' method. + proceed.call(chart, options, callback); + // Check bubble legend sizes and correct them if necessary. + legend.bubbleLegend.correctSizes(); + // Correct items positions with different dimensions in legend. + legend.retranslateItems(legend.getLinesHeights()); + } + else { + proceed.call(chart, options, callback); + // Allow color change on static bubble legend after click on legend + if (legend && legend.options.enabled && legend.bubbleLegend) { + legend.render(); + legend.retranslateItems(legend.getLinesHeights()); + } + } +}); +H.BubbleLegend = BubbleLegend; +export default H.BubbleLegend; diff --git a/librerias/gantt/code/es-modules/parts-more/BubbleSeries.js b/librerias/gantt/code/es-modules/parts-more/BubbleSeries.js new file mode 100644 index 0000000..0938152 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-more/BubbleSeries.js @@ -0,0 +1,567 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +/** + * @typedef {"area"|"width"} Highcharts.BubbleSizeByValue + */ +import Color from '../parts/Color.js'; +var color = Color.parse; +import Point from '../parts/Point.js'; +import U from '../parts/Utilities.js'; +var arrayMax = U.arrayMax, arrayMin = U.arrayMin, clamp = U.clamp, extend = U.extend, isNumber = U.isNumber, pick = U.pick, pInt = U.pInt, seriesType = U.seriesType; +import '../parts/Axis.js'; +import '../parts/Series.js'; +import '../parts/ScatterSeries.js'; +import './BubbleLegend.js'; +var Axis = H.Axis, noop = H.noop, Series = H.Series, seriesTypes = H.seriesTypes; +/** + * A bubble series is a three dimensional series type where each point renders + * an X, Y and Z value. Each points is drawn as a bubble where the position + * along the X and Y axes mark the X and Y values, and the size of the bubble + * relates to the Z value. + * + * @sample {highcharts} highcharts/demo/bubble/ + * Bubble chart + * + * @extends plotOptions.scatter + * @excluding cluster + * @product highcharts highstock + * @requires highcharts-more + * @optionparent plotOptions.bubble + */ +seriesType('bubble', 'scatter', { + dataLabels: { + formatter: function () { + return this.point.z; + }, + inside: true, + verticalAlign: 'middle' + }, + /** + * If there are more points in the series than the `animationLimit`, the + * animation won't run. Animation affects overall performance and doesn't + * work well with heavy data series. + * + * @since 6.1.0 + */ + animationLimit: 250, + /** + * Whether to display negative sized bubbles. The threshold is given + * by the [zThreshold](#plotOptions.bubble.zThreshold) option, and negative + * bubbles can be visualized by setting + * [negativeColor](#plotOptions.bubble.negativeColor). + * + * @sample {highcharts} highcharts/plotoptions/bubble-negative/ + * Negative bubbles + * + * @type {boolean} + * @default true + * @since 3.0 + * @apioption plotOptions.bubble.displayNegative + */ + /** + * @extends plotOptions.series.marker + * @excluding enabled, enabledThreshold, height, radius, width + */ + marker: { + lineColor: null, + lineWidth: 1, + /** + * The fill opacity of the bubble markers. + */ + fillOpacity: 0.5, + /** + * In bubble charts, the radius is overridden and determined based on + * the point's data value. + * + * @ignore-option + */ + radius: null, + states: { + hover: { + radiusPlus: 0 + } + }, + /** + * A predefined shape or symbol for the marker. Possible values are + * "circle", "square", "diamond", "triangle" and "triangle-down". + * + * Additionally, the URL to a graphic can be given on the form + * `url(graphic.png)`. Note that for the image to be applied to exported + * charts, its URL needs to be accessible by the export server. + * + * Custom callbacks for symbol path generation can also be added to + * `Highcharts.SVGRenderer.prototype.symbols`. The callback is then + * used by its method name, as shown in the demo. + * + * @sample {highcharts} highcharts/plotoptions/bubble-symbol/ + * Bubble chart with various symbols + * @sample {highcharts} highcharts/plotoptions/series-marker-symbol/ + * General chart with predefined, graphic and custom markers + * + * @type {Highcharts.SymbolKeyValue|string} + * @since 5.0.11 + */ + symbol: 'circle' + }, + /** + * Minimum bubble size. Bubbles will automatically size between the + * `minSize` and `maxSize` to reflect the `z` value of each bubble. + * Can be either pixels (when no unit is given), or a percentage of + * the smallest one of the plot width and height. + * + * @sample {highcharts} highcharts/plotoptions/bubble-size/ + * Bubble size + * + * @type {number|string} + * @since 3.0 + * @product highcharts highstock + */ + minSize: 8, + /** + * Maximum bubble size. Bubbles will automatically size between the + * `minSize` and `maxSize` to reflect the `z` value of each bubble. + * Can be either pixels (when no unit is given), or a percentage of + * the smallest one of the plot width and height. + * + * @sample {highcharts} highcharts/plotoptions/bubble-size/ + * Bubble size + * + * @type {number|string} + * @since 3.0 + * @product highcharts highstock + */ + maxSize: '20%', + /** + * When a point's Z value is below the + * [zThreshold](#plotOptions.bubble.zThreshold) setting, this color is used. + * + * @sample {highcharts} highcharts/plotoptions/bubble-negative/ + * Negative bubbles + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 3.0 + * @product highcharts + * @apioption plotOptions.bubble.negativeColor + */ + /** + * Whether the bubble's value should be represented by the area or the + * width of the bubble. The default, `area`, corresponds best to the + * human perception of the size of each bubble. + * + * @sample {highcharts} highcharts/plotoptions/bubble-sizeby/ + * Comparison of area and size + * + * @type {Highcharts.BubbleSizeByValue} + * @default area + * @since 3.0.7 + * @apioption plotOptions.bubble.sizeBy + */ + /** + * When this is true, the absolute value of z determines the size of + * the bubble. This means that with the default `zThreshold` of 0, a + * bubble of value -1 will have the same size as a bubble of value 1, + * while a bubble of value 0 will have a smaller size according to + * `minSize`. + * + * @sample {highcharts} highcharts/plotoptions/bubble-sizebyabsolutevalue/ + * Size by absolute value, various thresholds + * + * @type {boolean} + * @default false + * @since 4.1.9 + * @product highcharts + * @apioption plotOptions.bubble.sizeByAbsoluteValue + */ + /** + * When this is true, the series will not cause the Y axis to cross + * the zero plane (or [threshold](#plotOptions.series.threshold) option) + * unless the data actually crosses the plane. + * + * For example, if `softThreshold` is `false`, a series of 0, 1, 2, + * 3 will make the Y axis show negative values according to the `minPadding` + * option. If `softThreshold` is `true`, the Y axis starts at 0. + * + * @since 4.1.9 + * @product highcharts + */ + softThreshold: false, + states: { + hover: { + halo: { + size: 5 + } + } + }, + tooltip: { + pointFormat: '({point.x}, {point.y}), Size: {point.z}' + }, + turboThreshold: 0, + /** + * The minimum for the Z value range. Defaults to the highest Z value + * in the data. + * + * @see [zMin](#plotOptions.bubble.zMin) + * + * @sample {highcharts} highcharts/plotoptions/bubble-zmin-zmax/ + * Z has a possible range of 0-100 + * + * @type {number} + * @since 4.0.3 + * @product highcharts + * @apioption plotOptions.bubble.zMax + */ + /** + * @default z + * @apioption plotOptions.bubble.colorKey + */ + /** + * The minimum for the Z value range. Defaults to the lowest Z value + * in the data. + * + * @see [zMax](#plotOptions.bubble.zMax) + * + * @sample {highcharts} highcharts/plotoptions/bubble-zmin-zmax/ + * Z has a possible range of 0-100 + * + * @type {number} + * @since 4.0.3 + * @product highcharts + * @apioption plotOptions.bubble.zMin + */ + /** + * When [displayNegative](#plotOptions.bubble.displayNegative) is `false`, + * bubbles with lower Z values are skipped. When `displayNegative` + * is `true` and a [negativeColor](#plotOptions.bubble.negativeColor) + * is given, points with lower Z is colored. + * + * @sample {highcharts} highcharts/plotoptions/bubble-negative/ + * Negative bubbles + * + * @since 3.0 + * @product highcharts + */ + zThreshold: 0, + zoneAxis: 'z' + // Prototype members +}, { + pointArrayMap: ['y', 'z'], + parallelArrays: ['x', 'y', 'z'], + trackerGroups: ['group', 'dataLabelsGroup'], + specialGroup: 'group', + bubblePadding: true, + zoneAxis: 'z', + directTouch: true, + isBubble: true, + /* eslint-disable valid-jsdoc */ + /** + * @private + */ + pointAttribs: function (point, state) { + var markerOptions = this.options.marker, fillOpacity = markerOptions.fillOpacity, attr = Series.prototype.pointAttribs.call(this, point, state); + if (fillOpacity !== 1) { + attr.fill = color(attr.fill) + .setOpacity(fillOpacity) + .get('rgba'); + } + return attr; + }, + /** + * Get the radius for each point based on the minSize, maxSize and each + * point's Z value. This must be done prior to Series.translate because + * the axis needs to add padding in accordance with the point sizes. + * @private + */ + getRadii: function (zMin, zMax, series) { + var len, i, zData = this.zData, yData = this.yData, minSize = series.minPxSize, maxSize = series.maxPxSize, radii = [], value; + // Set the shape type and arguments to be picked up in drawPoints + for (i = 0, len = zData.length; i < len; i++) { + value = zData[i]; + // Separate method to get individual radius for bubbleLegend + radii.push(this.getRadius(zMin, zMax, minSize, maxSize, value, yData[i])); + } + this.radii = radii; + }, + /** + * Get the individual radius for one point. + * @private + */ + getRadius: function (zMin, zMax, minSize, maxSize, value, yValue) { + var options = this.options, sizeByArea = options.sizeBy !== 'width', zThreshold = options.zThreshold, zRange = zMax - zMin, pos = 0.5; + // #8608 - bubble should be visible when z is undefined + if (yValue === null || value === null) { + return null; + } + if (isNumber(value)) { + // When sizing by threshold, the absolute value of z determines + // the size of the bubble. + if (options.sizeByAbsoluteValue) { + value = Math.abs(value - zThreshold); + zMax = zRange = Math.max(zMax - zThreshold, Math.abs(zMin - zThreshold)); + zMin = 0; + } + // Issue #4419 - if value is less than zMin, push a radius that's + // always smaller than the minimum size + if (value < zMin) { + return minSize / 2 - 1; + } + // Relative size, a number between 0 and 1 + if (zRange > 0) { + pos = (value - zMin) / zRange; + } + } + if (sizeByArea && pos >= 0) { + pos = Math.sqrt(pos); + } + return Math.ceil(minSize + pos * (maxSize - minSize)) / 2; + }, + /** + * Perform animation on the bubbles + * @private + */ + animate: function (init) { + if (!init && + this.points.length < this.options.animationLimit // #8099 + ) { + this.points.forEach(function (point) { + var graphic = point.graphic, animationTarget; + if (graphic && graphic.width) { // URL symbols don't have width + animationTarget = { + x: graphic.x, + y: graphic.y, + width: graphic.width, + height: graphic.height + }; + // Start values + graphic.attr({ + x: point.plotX, + y: point.plotY, + width: 1, + height: 1 + }); + // Run animation + graphic.animate(animationTarget, this.options.animation); + } + }, this); + } + }, + /** + * Define hasData function for non-cartesian series. + * Returns true if the series has points at all. + * @private + */ + hasData: function () { + return !!this.processedXData.length; // != 0 + }, + /** + * Extend the base translate method to handle bubble size + * @private + */ + translate: function () { + var i, data = this.data, point, radius, radii = this.radii; + // Run the parent method + seriesTypes.scatter.prototype.translate.call(this); + // Set the shape type and arguments to be picked up in drawPoints + i = data.length; + while (i--) { + point = data[i]; + radius = radii ? radii[i] : 0; // #1737 + if (isNumber(radius) && radius >= this.minPxSize / 2) { + // Shape arguments + point.marker = extend(point.marker, { + radius: radius, + width: 2 * radius, + height: 2 * radius + }); + // Alignment box for the data label + point.dlBox = { + x: point.plotX - radius, + y: point.plotY - radius, + width: 2 * radius, + height: 2 * radius + }; + } + else { // below zThreshold + // #1691 + point.shapeArgs = point.plotY = point.dlBox = void 0; + } + } + }, + alignDataLabel: seriesTypes.column.prototype.alignDataLabel, + buildKDTree: noop, + applyZones: noop + // Point class +}, { + /** + * @private + */ + haloPath: function (size) { + return Point.prototype.haloPath.call(this, + // #6067 + size === 0 ? 0 : (this.marker ? this.marker.radius || 0 : 0) + size); + }, + ttBelow: false +}); +// Add logic to pad each axis with the amount of pixels necessary to avoid the +// bubbles to overflow. +Axis.prototype.beforePadding = function () { + var axis = this, axisLength = this.len, chart = this.chart, pxMin = 0, pxMax = axisLength, isXAxis = this.isXAxis, dataKey = isXAxis ? 'xData' : 'yData', min = this.min, extremes = {}, smallestSize = Math.min(chart.plotWidth, chart.plotHeight), zMin = Number.MAX_VALUE, zMax = -Number.MAX_VALUE, range = this.max - min, transA = axisLength / range, activeSeries = []; + // Handle padding on the second pass, or on redraw + this.series.forEach(function (series) { + var seriesOptions = series.options, zData; + if (series.bubblePadding && + (series.visible || !chart.options.chart.ignoreHiddenSeries)) { + // Correction for #1673 + axis.allowZoomOutside = true; + // Cache it + activeSeries.push(series); + if (isXAxis) { // because X axis is evaluated first + // For each series, translate the size extremes to pixel values + ['minSize', 'maxSize'].forEach(function (prop) { + var length = seriesOptions[prop], isPercent = /%$/.test(length); + length = pInt(length); + extremes[prop] = isPercent ? + smallestSize * length / 100 : + length; + }); + series.minPxSize = extremes.minSize; + // Prioritize min size if conflict to make sure bubbles are + // always visible. #5873 + series.maxPxSize = Math.max(extremes.maxSize, extremes.minSize); + // Find the min and max Z + zData = series.zData.filter(isNumber); + if (zData.length) { // #1735 + zMin = pick(seriesOptions.zMin, clamp(arrayMin(zData), seriesOptions.displayNegative === false ? + seriesOptions.zThreshold : + -Number.MAX_VALUE, zMin)); + zMax = pick(seriesOptions.zMax, Math.max(zMax, arrayMax(zData))); + } + } + } + }); + activeSeries.forEach(function (series) { + var data = series[dataKey], i = data.length, radius; + if (isXAxis) { + series.getRadii(zMin, zMax, series); + } + if (range > 0) { + while (i--) { + if (isNumber(data[i]) && + axis.dataMin <= data[i] && + data[i] <= axis.max) { + radius = series.radii ? series.radii[i] : 0; + pxMin = Math.min(((data[i] - min) * transA) - radius, pxMin); + pxMax = Math.max(((data[i] - min) * transA) + radius, pxMax); + } + } + } + }); + // Apply the padding to the min and max properties + if (activeSeries.length && range > 0 && !this.logarithmic) { + pxMax -= axisLength; + transA *= (axisLength + + Math.max(0, pxMin) - // #8901 + Math.min(pxMax, axisLength)) / axisLength; + [ + ['min', 'userMin', pxMin], + ['max', 'userMax', pxMax] + ].forEach(function (keys) { + if (typeof pick(axis.options[keys[0]], axis[keys[1]]) === 'undefined') { + axis[keys[0]] += keys[2] / transA; + } + }); + } + /* eslint-enable valid-jsdoc */ +}; +/** + * A `bubble` series. If the [type](#series.bubble.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.bubble + * @excluding dataParser, dataURL, stack + * @product highcharts highstock + * @requires highcharts-more + * @apioption series.bubble + */ +/** + * An array of data points for the series. For the `bubble` series type, + * points can be given in the following ways: + * + * 1. An array of arrays with 3 or 2 values. In this case, the values correspond + * to `x,y,z`. If the first value is a string, it is applied as the name of + * the point, and the `x` value is inferred. The `x` value can also be + * omitted, in which case the inner arrays should be of length 2\. Then the + * `x` value is automatically calculated, either starting at 0 and + * incremented by 1, or from `pointStart` and `pointInterval` given in the + * series options. + * ```js + * data: [ + * [0, 1, 2], + * [1, 5, 5], + * [2, 0, 2] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.bubble.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 1, + * z: 1, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 5, + * z: 4, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|Array<(number|string),number,number>|*>} + * @extends series.line.data + * @product highcharts + * @apioption series.bubble.data + */ +/** + * @extends series.line.data.marker + * @excluding enabledThreshold, height, radius, width + * @product highcharts + * @apioption series.bubble.data.marker + */ +/** + * The size value for each bubble. The bubbles' diameters are computed + * based on the `z`, and controlled by series options like `minSize`, + * `maxSize`, `sizeBy`, `zMin` and `zMax`. + * + * @type {number|null} + * @product highcharts + * @apioption series.bubble.data.z + */ +/** + * @excluding enabled, enabledThreshold, height, radius, width + * @apioption series.bubble.marker + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/parts-more/ColumnPyramidSeries.js b/librerias/gantt/code/es-modules/parts-more/ColumnPyramidSeries.js new file mode 100644 index 0000000..088611b --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-more/ColumnPyramidSeries.js @@ -0,0 +1,255 @@ +/* * + * + * (c) 2010-2020 Sebastian Bochan + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var clamp = U.clamp, pick = U.pick, seriesType = U.seriesType; +var seriesTypes = H.seriesTypes; +var colProto = seriesTypes.column.prototype; +/** + * The ColumnPyramidSeries class + * + * @private + * @class + * @name Highcharts.seriesTypes.columnpyramid + * + * @augments Highcharts.Series + */ +seriesType('columnpyramid', 'column', +/** + * Column pyramid series display one pyramid per value along an X axis. + * To display horizontal pyramids, set [chart.inverted](#chart.inverted) to + * `true`. + * + * @sample {highcharts|highstock} highcharts/demo/column-pyramid/ + * Column pyramid + * @sample {highcharts|highstock} highcharts/plotoptions/columnpyramid-stacked/ + * Column pyramid stacked + * @sample {highcharts|highstock} highcharts/plotoptions/columnpyramid-inverted/ + * Column pyramid inverted + * + * @extends plotOptions.column + * @since 7.0.0 + * @product highcharts highstock + * @excluding boostThreshold, borderRadius, crisp, depth, edgeColor, + * edgeWidth, groupZPadding, negativeColor, softThreshold, + * threshold, zoneAxis, zones + * @requires highcharts-more + * @optionparent plotOptions.columnpyramid + */ +{ +// no additions +}, { + /* eslint-disable-next-line valid-jsdoc */ + /** + * Overrides the column translate method + * @private + */ + translate: function () { + var series = this, chart = series.chart, options = series.options, dense = series.dense = + series.closestPointRange * series.xAxis.transA < 2, borderWidth = series.borderWidth = pick(options.borderWidth, dense ? 0 : 1 // #3635 + ), yAxis = series.yAxis, threshold = options.threshold, translatedThreshold = series.translatedThreshold = + yAxis.getThreshold(threshold), minPointLength = pick(options.minPointLength, 5), metrics = series.getColumnMetrics(), pointWidth = metrics.width, + // postprocessed for border width + seriesBarW = series.barW = + Math.max(pointWidth, 1 + 2 * borderWidth), pointXOffset = series.pointXOffset = metrics.offset; + if (chart.inverted) { + translatedThreshold -= 0.5; // #3355 + } + // When the pointPadding is 0, + // we want the pyramids to be packed tightly, + // so we allow individual pyramids to have individual sizes. + // When pointPadding is greater, + // we strive for equal-width columns (#2694). + if (options.pointPadding) { + seriesBarW = Math.ceil(seriesBarW); + } + colProto.translate.apply(series); + // Record the new values + series.points.forEach(function (point) { + var yBottom = pick(point.yBottom, translatedThreshold), safeDistance = 999 + Math.abs(yBottom), plotY = clamp(point.plotY, -safeDistance, yAxis.len + safeDistance), + // Don't draw too far outside plot area + // (#1303, #2241, #4264) + barX = point.plotX + pointXOffset, barW = seriesBarW / 2, barY = Math.min(plotY, yBottom), barH = Math.max(plotY, yBottom) - barY, stackTotal, stackHeight, topPointY, topXwidth, bottomXwidth, invBarPos, x1, x2, x3, x4, y1, y2; + point.barX = barX; + point.pointWidth = pointWidth; + // Fix the tooltip on center of grouped pyramids + // (#1216, #424, #3648) + point.tooltipPos = chart.inverted ? + [ + yAxis.len + yAxis.pos - chart.plotLeft - plotY, + series.xAxis.len - barX - barW, + barH + ] : + [ + barX + barW, + plotY + yAxis.pos - chart.plotTop, + barH + ]; + stackTotal = + threshold + (point.total || point.y); + // overwrite stacktotal (always 100 / -100) + if (options.stacking === 'percent') { + stackTotal = + threshold + (point.y < 0) ? + -100 : + 100; + } + // get the highest point (if stack, extract from total) + topPointY = yAxis.toPixels((stackTotal), true); + // calculate height of stack (in pixels) + stackHeight = + chart.plotHeight - topPointY - + (chart.plotHeight - translatedThreshold); + // topXwidth and bottomXwidth = width of lines from the center + // calculated from tanges proportion. + // Can not be a NaN #12514 + topXwidth = stackHeight ? (barW * (barY - topPointY)) / stackHeight : 0; + // like topXwidth, but with height of point + bottomXwidth = stackHeight ? (barW * (barY + barH - topPointY)) / stackHeight : 0; + /* + /\ + / \ + x1,y1,------ x2,y1 + / \ + ---------- + x4,y2 x3,y2 + */ + x1 = barX - topXwidth + barW; + x2 = barX + topXwidth + barW; + x3 = barX + bottomXwidth + barW; + x4 = barX - bottomXwidth + barW; + y1 = barY - minPointLength; + y2 = barY + barH; + if (point.y < 0) { + y1 = barY; + y2 = barY + barH + minPointLength; + } + // inverted chart + if (chart.inverted) { + invBarPos = chart.plotWidth - barY; + stackHeight = (topPointY - + (chart.plotWidth - translatedThreshold)); + // proportion tanges + topXwidth = (barW * + (topPointY - invBarPos)) / stackHeight; + bottomXwidth = (barW * + (topPointY - (invBarPos - barH))) / stackHeight; + x1 = barX + barW + topXwidth; // top bottom + x2 = x1 - 2 * topXwidth; // top top + x3 = barX - bottomXwidth + barW; // bottom top + x4 = barX + bottomXwidth + barW; // bottom bottom + y1 = barY; + y2 = barY + barH - minPointLength; + if (point.y < 0) { + y2 = barY + barH + minPointLength; + } + } + // Register shape type and arguments to be used in drawPoints + point.shapeType = 'path'; + point.shapeArgs = { + // args for datalabels positioning + x: x1, + y: y1, + width: x2 - x1, + height: barH, + // path of pyramid + d: [ + ['M', x1, y1], + ['L', x2, y1], + ['L', x3, y2], + ['L', x4, y2], + ['Z'] + ] + }; + }); + } +}); +/** + * A `columnpyramid` series. If the [type](#series.columnpyramid.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.columnpyramid + * @excluding connectEnds, connectNulls, dashStyle, dataParser, dataURL, + * gapSize, gapUnit, linecap, lineWidth, marker, step + * @product highcharts highstock + * @requires highcharts-more + * @apioption series.columnpyramid + */ +/** + * @excluding halo, lineWidth, lineWidthPlus, marker + * @product highcharts highstock + * @apioption series.columnpyramid.states.hover + */ +/** + * @excluding halo, lineWidth, lineWidthPlus, marker + * @product highcharts highstock + * @apioption series.columnpyramid.states.select + */ +/** + * An array of data points for the series. For the `columnpyramid` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 6], + * [1, 2], + * [2, 6] + * ] + * ``` + * + * 3. An array of objects with named values. The objects are point configuration + * objects as seen below. If the total number of data points exceeds the + * series' [turboThreshold](#series.columnpyramid.turboThreshold), this + * option is not available. + * ```js + * data: [{ + * x: 1, + * y: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @excluding marker + * @product highcharts highstock + * @apioption series.columnpyramid.data + */ +''; // adds doclets above to transpiled file; diff --git a/librerias/gantt/code/es-modules/parts-more/ColumnRangeSeries.js b/librerias/gantt/code/es-modules/parts-more/ColumnRangeSeries.js new file mode 100644 index 0000000..cb50b6a --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-more/ColumnRangeSeries.js @@ -0,0 +1,239 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var clamp = U.clamp, merge = U.merge, pick = U.pick, seriesType = U.seriesType; +var defaultPlotOptions = H.defaultPlotOptions, noop = H.noop, seriesTypes = H.seriesTypes; +var colProto = seriesTypes.column.prototype; +/** + * The column range is a cartesian series type with higher and lower + * Y values along an X axis. To display horizontal bars, set + * [chart.inverted](#chart.inverted) to `true`. + * + * @sample {highcharts|highstock} highcharts/demo/columnrange/ + * Inverted column range + * + * @extends plotOptions.column + * @since 2.3.0 + * @excluding negativeColor, stacking, softThreshold, threshold + * @product highcharts highstock + * @requires highcharts-more + * @optionparent plotOptions.columnrange + */ +var columnRangeOptions = { + /** + * Extended data labels for range series types. Range series data labels + * have no `x` and `y` options. Instead, they have `xLow`, `xHigh`, + * `yLow` and `yHigh` options to allow the higher and lower data label + * sets individually. + * + * @declare Highcharts.SeriesAreaRangeDataLabelsOptionsObject + * @extends plotOptions.arearange.dataLabels + * @since 2.3.0 + * @product highcharts highstock + * @apioption plotOptions.columnrange.dataLabels + */ + pointRange: null, + /** @ignore-option */ + marker: null, + states: { + hover: { + /** @ignore-option */ + halo: false + } + } +}; +/** + * The ColumnRangeSeries class + * + * @private + * @class + * @name Highcharts.seriesTypes.columnrange + * + * @augments Highcharts.Series + */ +seriesType('columnrange', 'arearange', merge(defaultPlotOptions.column, defaultPlotOptions.arearange, columnRangeOptions), { + // eslint-disable-next-line valid-jsdoc + /** + * Translate data points from raw values x and y to plotX and plotY + * @private + */ + translate: function () { + var series = this, yAxis = series.yAxis, xAxis = series.xAxis, startAngleRad = xAxis.startAngleRad, start, chart = series.chart, isRadial = series.xAxis.isRadial, safeDistance = Math.max(chart.chartWidth, chart.chartHeight) + 999, plotHigh; + // eslint-disable-next-line valid-jsdoc + /** + * Don't draw too far outside plot area (#6835) + * @private + */ + function safeBounds(pixelPos) { + return clamp(pixelPos, -safeDistance, safeDistance); + } + colProto.translate.apply(series); + // Set plotLow and plotHigh + series.points.forEach(function (point) { + var shapeArgs = point.shapeArgs, minPointLength = series.options.minPointLength, heightDifference, height, y; + point.plotHigh = plotHigh = safeBounds(yAxis.translate(point.high, 0, 1, 0, 1)); + point.plotLow = safeBounds(point.plotY); + // adjust shape + y = plotHigh; + height = pick(point.rectPlotY, point.plotY) - plotHigh; + // Adjust for minPointLength + if (Math.abs(height) < minPointLength) { + heightDifference = (minPointLength - height); + height += heightDifference; + y -= heightDifference / 2; + // Adjust for negative ranges or reversed Y axis (#1457) + } + else if (height < 0) { + height *= -1; + y -= height; + } + if (isRadial) { + start = point.barX + startAngleRad; + point.shapeType = 'arc'; + point.shapeArgs = series.polarArc(y + height, y, start, start + point.pointWidth); + } + else { + shapeArgs.height = height; + shapeArgs.y = y; + point.tooltipPos = chart.inverted ? + [ + yAxis.len + yAxis.pos - chart.plotLeft - y - + height / 2, + xAxis.len + xAxis.pos - chart.plotTop - + shapeArgs.x - shapeArgs.width / 2, + height + ] : [ + xAxis.left - chart.plotLeft + shapeArgs.x + + shapeArgs.width / 2, + yAxis.pos - chart.plotTop + y + height / 2, + height + ]; // don't inherit from column tooltip position - #3372 + } + }); + }, + directTouch: true, + trackerGroups: ['group', 'dataLabelsGroup'], + drawGraph: noop, + getSymbol: noop, + // Overrides from modules that may be loaded after this module + crispCol: function () { + return colProto.crispCol.apply(this, arguments); + }, + drawPoints: function () { + return colProto.drawPoints.apply(this, arguments); + }, + drawTracker: function () { + return colProto.drawTracker.apply(this, arguments); + }, + getColumnMetrics: function () { + return colProto.getColumnMetrics.apply(this, arguments); + }, + pointAttribs: function () { + return colProto.pointAttribs.apply(this, arguments); + }, + animate: function () { + return colProto.animate.apply(this, arguments); + }, + polarArc: function () { + return colProto.polarArc.apply(this, arguments); + }, + translate3dPoints: function () { + return colProto.translate3dPoints.apply(this, arguments); + }, + translate3dShapes: function () { + return colProto.translate3dShapes.apply(this, arguments); + } +}, { + setState: colProto.pointClass.prototype.setState +}); +/** + * A `columnrange` series. If the [type](#series.columnrange.type) + * option is not specified, it is inherited from + * [chart.type](#chart.type). + * + * @extends series,plotOptions.columnrange + * @excluding dataParser, dataURL, stack, stacking + * @product highcharts highstock + * @requires highcharts-more + * @apioption series.columnrange + */ +/** + * An array of data points for the series. For the `columnrange` series + * type, points can be given in the following ways: + * + * 1. An array of arrays with 3 or 2 values. In this case, the values correspond + * to `x,low,high`. If the first value is a string, it is applied as the name + * of the point, and the `x` value is inferred. The `x` value can also be + * omitted, in which case the inner arrays should be of length 2\. Then the + * `x` value is automatically calculated, either starting at 0 and + * incremented by 1, or from `pointStart` and `pointInterval` given in the + * series options. + * ```js + * data: [ + * [0, 4, 2], + * [1, 2, 1], + * [2, 9, 10] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.columnrange.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * low: 0, + * high: 4, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * low: 5, + * high: 3, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|Array<(number|string),number,number>|*>} + * @extends series.arearange.data + * @excluding marker + * @product highcharts highstock + * @apioption series.columnrange.data + */ +/** + * @extends series.columnrange.dataLabels + * @product highcharts highstock + * @apioption series.columnrange.data.dataLabels + */ +/** + * @excluding halo, lineWidth, lineWidthPlus, marker + * @product highcharts highstock + * @apioption series.columnrange.states.hover + */ +/** + * @excluding halo, lineWidth, lineWidthPlus, marker + * @product highcharts highstock + * @apioption series.columnrange.states.select + */ +''; // adds doclets above into transpiled diff --git a/librerias/gantt/code/es-modules/parts-more/ErrorBarSeries.js b/librerias/gantt/code/es-modules/parts-more/ErrorBarSeries.js new file mode 100644 index 0000000..0359a19 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-more/ErrorBarSeries.js @@ -0,0 +1,166 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var seriesType = U.seriesType; +import '../parts/Options.js'; +import './BoxPlotSeries.js'; +var noop = H.noop, seriesTypes = H.seriesTypes; +/** + * Error bars are a graphical representation of the variability of data and are + * used on graphs to indicate the error, or uncertainty in a reported + * measurement. + * + * @sample highcharts/demo/error-bar/ + * Error bars on a column series + * @sample highcharts/series-errorbar/on-scatter/ + * Error bars on a scatter series + * + * @extends plotOptions.boxplot + * @product highcharts highstock + * @requires highcharts-more + * @optionparent plotOptions.errorbar + */ +seriesType('errorbar', 'boxplot', { + /** + * The main color of the bars. This can be overridden by + * [stemColor](#plotOptions.errorbar.stemColor) and + * [whiskerColor](#plotOptions.errorbar.whiskerColor) individually. + * + * @sample {highcharts} highcharts/plotoptions/error-bar-styling/ + * Error bar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #000000 + * @since 3.0 + * @product highcharts + */ + color: '#000000', + grouping: false, + /** + * The parent series of the error bar. The default value links it to + * the previous series. Otherwise, use the id of the parent series. + * + * @since 3.0 + * @product highcharts + */ + linkedTo: ':previous', + tooltip: { + pointFormat: '\u25CF {series.name}: {point.low} - {point.high}
' + }, + /** + * The line width of the whiskers, the horizontal lines marking low + * and high values. When `null`, the general + * [lineWidth](#plotOptions.errorbar.lineWidth) applies. + * + * @sample {highcharts} highcharts/plotoptions/error-bar-styling/ + * Error bar styling + * + * @type {number} + * @since 3.0 + * @product highcharts + */ + whiskerWidth: null + // Prototype members +}, { + type: 'errorbar', + // array point configs are mapped to this + pointArrayMap: ['low', 'high'], + // return a plain array for speedy calculation + toYData: function (point) { + return [point.low, point.high]; + }, + pointValKey: 'high', + doQuartiles: false, + drawDataLabels: seriesTypes.arearange ? + function () { + var valKey = this.pointValKey; + seriesTypes.arearange.prototype.drawDataLabels.call(this); + // Arearange drawDataLabels does not reset point.y to high, + // but to low after drawing (#4133) + this.data.forEach(function (point) { + point.y = point[valKey]; + }); + } : + noop, + // Get the width and X offset, either on top of the linked series column or + // standalone + getColumnMetrics: function () { + return ((this.linkedParent && this.linkedParent.columnMetrics) || + seriesTypes.column.prototype.getColumnMetrics.call(this)); + } +}); +/** + * A `errorbar` series. If the [type](#series.errorbar.type) option + * is not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.errorbar + * @excluding dataParser, dataURL, stack, stacking + * @product highcharts + * @requires highcharts-more + * @apioption series.errorbar + */ +/** + * An array of data points for the series. For the `errorbar` series + * type, points can be given in the following ways: + * + * 1. An array of arrays with 3 or 2 values. In this case, the values correspond + * to `x,low,high`. If the first value is a string, it is applied as the name + * of the point, and the `x` value is inferred. The `x` value can also be + * omitted, in which case the inner arrays should be of length 2\. Then the + * `x` value is automatically calculated, either starting at 0 and + * incremented by 1, or from `pointStart` and `pointInterval` given in the + * series options. + * ```js + * data: [ + * [0, 10, 2], + * [1, 1, 8], + * [2, 4, 5] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.errorbar.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * low: 0, + * high: 0, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * low: 5, + * high: 5, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|Array<(number|string),number,number>|*>} + * @extends series.arearange.data + * @excluding dataLabels, drilldown, marker, states + * @product highcharts + * @apioption series.errorbar.data + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/parts-more/GaugeSeries.js b/librerias/gantt/code/es-modules/parts-more/GaugeSeries.js new file mode 100644 index 0000000..bdfd095 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-more/GaugeSeries.js @@ -0,0 +1,509 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var clamp = U.clamp, isNumber = U.isNumber, merge = U.merge, pick = U.pick, pInt = U.pInt, seriesType = U.seriesType; +import '../parts/Options.js'; +import '../parts/Point.js'; +import '../parts/Series.js'; +import '../parts/Interaction.js'; +var noop = H.noop, Series = H.Series, TrackerMixin = H.TrackerMixin; +/** + * Gauges are circular plots displaying one or more values with a dial pointing + * to values along the perimeter. + * + * @sample highcharts/demo/gauge-speedometer/ + * Gauge chart + * + * @extends plotOptions.line + * @excluding animationLimit, boostThreshold, colorAxis, colorKey, + * connectEnds, connectNulls, cropThreshold, dashStyle, dragDrop, + * findNearestPointBy, getExtremesFromAll, marker, negativeColor, + * pointPlacement, shadow, softThreshold, stacking, states, step, + * threshold, turboThreshold, xAxis, zoneAxis, zones, dataSorting + * @product highcharts + * @requires highcharts-more + * @optionparent plotOptions.gauge + */ +seriesType('gauge', 'line', { + /** + * When this option is `true`, the dial will wrap around the axes. For + * instance, in a full-range gauge going from 0 to 360, a value of 400 + * will point to 40\. When `wrap` is `false`, the dial stops at 360. + * + * @see [overshoot](#plotOptions.gauge.overshoot) + * + * @type {boolean} + * @default true + * @since 3.0 + * @product highcharts + * @apioption plotOptions.gauge.wrap + */ + /** + * Data labels for the gauge. For gauges, the data labels are enabled + * by default and shown in a bordered box below the point. + * + * @since 2.3.0 + * @product highcharts + */ + dataLabels: { + borderColor: '#cccccc', + borderRadius: 3, + borderWidth: 1, + crop: false, + defer: false, + enabled: true, + verticalAlign: 'top', + y: 15, + zIndex: 2 + }, + /** + * Options for the dial or arrow pointer of the gauge. + * + * In styled mode, the dial is styled with the + * `.highcharts-gauge-series .highcharts-dial` rule. + * + * @sample {highcharts} highcharts/css/gauge/ + * Styled mode + * + * @type {*} + * @since 2.3.0 + * @product highcharts + */ + dial: {}, + /** + * The length of the dial's base part, relative to the total radius + * or length of the dial. + * + * @sample {highcharts} highcharts/plotoptions/gauge-dial/ + * Dial options demonstrated + * + * @type {string} + * @default 70% + * @since 2.3.0 + * @product highcharts + * @apioption plotOptions.gauge.dial.baseLength + */ + /** + * The pixel width of the base of the gauge dial. The base is the part + * closest to the pivot, defined by baseLength. + * + * @sample {highcharts} highcharts/plotoptions/gauge-dial/ + * Dial options demonstrated + * + * @type {number} + * @default 3 + * @since 2.3.0 + * @product highcharts + * @apioption plotOptions.gauge.dial.baseWidth + */ + /** + * The radius or length of the dial, in percentages relative to the + * radius of the gauge itself. + * + * @sample {highcharts} highcharts/plotoptions/gauge-dial/ + * Dial options demonstrated + * + * @type {string} + * @default 80% + * @since 2.3.0 + * @product highcharts + * @apioption plotOptions.gauge.dial.radius + */ + /** + * The length of the dial's rear end, the part that extends out on the + * other side of the pivot. Relative to the dial's length. + * + * @sample {highcharts} highcharts/plotoptions/gauge-dial/ + * Dial options demonstrated + * + * @type {string} + * @default 10% + * @since 2.3.0 + * @product highcharts + * @apioption plotOptions.gauge.dial.rearLength + */ + /** + * The width of the top of the dial, closest to the perimeter. The pivot + * narrows in from the base to the top. + * + * @sample {highcharts} highcharts/plotoptions/gauge-dial/ + * Dial options demonstrated + * + * @type {number} + * @default 1 + * @since 2.3.0 + * @product highcharts + * @apioption plotOptions.gauge.dial.topWidth + */ + /** + * The background or fill color of the gauge's dial. + * + * @sample {highcharts} highcharts/plotoptions/gauge-dial/ + * Dial options demonstrated + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #000000 + * @since 2.3.0 + * @product highcharts + * @apioption plotOptions.gauge.dial.backgroundColor + */ + /** + * The border color or stroke of the gauge's dial. By default, the + * borderWidth is 0, so this must be set in addition to a custom border + * color. + * + * @sample {highcharts} highcharts/plotoptions/gauge-dial/ + * Dial options demonstrated + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #cccccc + * @since 2.3.0 + * @product highcharts + * @apioption plotOptions.gauge.dial.borderColor + */ + /** + * The width of the gauge dial border in pixels. + * + * @sample {highcharts} highcharts/plotoptions/gauge-dial/ + * Dial options demonstrated + * + * @type {number} + * @default 0 + * @since 2.3.0 + * @product highcharts + * @apioption plotOptions.gauge.dial.borderWidth + */ + /** + * Allow the dial to overshoot the end of the perimeter axis by this + * many degrees. Say if the gauge axis goes from 0 to 60, a value of + * 100, or 1000, will show 5 degrees beyond the end of the axis when this + * option is set to 5. + * + * @see [wrap](#plotOptions.gauge.wrap) + * + * @sample {highcharts} highcharts/plotoptions/gauge-overshoot/ + * Allow 5 degrees overshoot + * + * @type {number} + * @since 3.0.10 + * @product highcharts + * @apioption plotOptions.gauge.overshoot + */ + /** + * Options for the pivot or the center point of the gauge. + * + * In styled mode, the pivot is styled with the + * `.highcharts-gauge-series .highcharts-pivot` rule. + * + * @sample {highcharts} highcharts/css/gauge/ + * Styled mode + * + * @type {*} + * @since 2.3.0 + * @product highcharts + */ + pivot: {}, + /** + * The pixel radius of the pivot. + * + * @sample {highcharts} highcharts/plotoptions/gauge-pivot/ + * Pivot options demonstrated + * + * @type {number} + * @default 5 + * @since 2.3.0 + * @product highcharts + * @apioption plotOptions.gauge.pivot.radius + */ + /** + * The border or stroke width of the pivot. + * + * @sample {highcharts} highcharts/plotoptions/gauge-pivot/ + * Pivot options demonstrated + * + * @type {number} + * @default 0 + * @since 2.3.0 + * @product highcharts + * @apioption plotOptions.gauge.pivot.borderWidth + */ + /** + * The border or stroke color of the pivot. In able to change this, + * the borderWidth must also be set to something other than the default + * 0. + * + * @sample {highcharts} highcharts/plotoptions/gauge-pivot/ + * Pivot options demonstrated + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #cccccc + * @since 2.3.0 + * @product highcharts + * @apioption plotOptions.gauge.pivot.borderColor + */ + /** + * The background color or fill of the pivot. + * + * @sample {highcharts} highcharts/plotoptions/gauge-pivot/ + * Pivot options demonstrated + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #000000 + * @since 2.3.0 + * @product highcharts + * @apioption plotOptions.gauge.pivot.backgroundColor + */ + tooltip: { + headerFormat: '' + }, + /** + * Whether to display this particular series or series type in the + * legend. Defaults to false for gauge series. + * + * @since 2.3.0 + * @product highcharts + */ + showInLegend: false + // Prototype members +}, { + // chart.angular will be set to true when a gauge series is present, + // and this will be used on the axes + angular: true, + directTouch: true, + drawGraph: noop, + fixedBox: true, + forceDL: true, + noSharedTooltip: true, + trackerGroups: ['group', 'dataLabelsGroup'], + /* eslint-disable valid-jsdoc */ + /** + * Calculate paths etc + * @private + */ + translate: function () { + var series = this, yAxis = series.yAxis, options = series.options, center = yAxis.center; + series.generatePoints(); + series.points.forEach(function (point) { + var dialOptions = merge(options.dial, point.dial), radius = ((pInt(pick(dialOptions.radius, '80%')) * center[2]) / + 200), baseLength = ((pInt(pick(dialOptions.baseLength, '70%')) * radius) / + 100), rearLength = ((pInt(pick(dialOptions.rearLength, '10%')) * radius) / + 100), baseWidth = dialOptions.baseWidth || 3, topWidth = dialOptions.topWidth || 1, overshoot = options.overshoot, rotation = yAxis.startAngleRad + yAxis.translate(point.y, null, null, null, true); + // Handle the wrap and overshoot options + if (isNumber(overshoot) || options.wrap === false) { + overshoot = isNumber(overshoot) ? + (overshoot / 180 * Math.PI) : 0; + rotation = clamp(rotation, yAxis.startAngleRad - overshoot, yAxis.endAngleRad + overshoot); + } + rotation = rotation * 180 / Math.PI; + point.shapeType = 'path'; + var d = dialOptions.path || [ + ['M', -rearLength, -baseWidth / 2], + ['L', baseLength, -baseWidth / 2], + ['L', radius, -topWidth / 2], + ['L', radius, topWidth / 2], + ['L', baseLength, baseWidth / 2], + ['L', -rearLength, baseWidth / 2], + ['Z'] + ]; + point.shapeArgs = { + d: d, + translateX: center[0], + translateY: center[1], + rotation: rotation + }; + // Positions for data label + point.plotX = center[0]; + point.plotY = center[1]; + }); + }, + /** + * Draw the points where each point is one needle + * @private + */ + drawPoints: function () { + var series = this, chart = series.chart, center = series.yAxis.center, pivot = series.pivot, options = series.options, pivotOptions = options.pivot, renderer = chart.renderer; + series.points.forEach(function (point) { + var graphic = point.graphic, shapeArgs = point.shapeArgs, d = shapeArgs.d, dialOptions = merge(options.dial, point.dial); // #1233 + if (graphic) { + graphic.animate(shapeArgs); + shapeArgs.d = d; // animate alters it + } + else { + point.graphic = + renderer[point.shapeType](shapeArgs) + .attr({ + // required by VML when animation is false + rotation: shapeArgs.rotation, + zIndex: 1 + }) + .addClass('highcharts-dial') + .add(series.group); + } + // Presentational attributes + if (!chart.styledMode) { + point.graphic[graphic ? 'animate' : 'attr']({ + stroke: dialOptions.borderColor || 'none', + 'stroke-width': dialOptions.borderWidth || 0, + fill: dialOptions.backgroundColor || + '#000000' + }); + } + }); + // Add or move the pivot + if (pivot) { + pivot.animate({ + translateX: center[0], + translateY: center[1] + }); + } + else { + series.pivot = + renderer.circle(0, 0, pick(pivotOptions.radius, 5)) + .attr({ + zIndex: 2 + }) + .addClass('highcharts-pivot') + .translate(center[0], center[1]) + .add(series.group); + // Presentational attributes + if (!chart.styledMode) { + series.pivot.attr({ + 'stroke-width': pivotOptions.borderWidth || 0, + stroke: pivotOptions.borderColor || + '#cccccc', + fill: pivotOptions.backgroundColor || + '#000000' + }); + } + } + }, + /** + * Animate the arrow up from startAngle + * @private + */ + animate: function (init) { + var series = this; + if (!init) { + series.points.forEach(function (point) { + var graphic = point.graphic; + if (graphic) { + // start value + graphic.attr({ + rotation: series.yAxis.startAngleRad * 180 / Math.PI + }); + // animate + graphic.animate({ + rotation: point.shapeArgs.rotation + }, series.options.animation); + } + }); + } + }, + /** + * @private + */ + render: function () { + this.group = this.plotGroup('group', 'series', this.visible ? 'visible' : 'hidden', this.options.zIndex, this.chart.seriesGroup); + Series.prototype.render.call(this); + this.group.clip(this.chart.clipRect); + }, + /** + * Extend the basic setData method by running processData and generatePoints + * immediately, in order to access the points from the legend. + * @private + */ + setData: function (data, redraw) { + Series.prototype.setData.call(this, data, false); + this.processData(); + this.generatePoints(); + if (pick(redraw, true)) { + this.chart.redraw(); + } + }, + /** + * Define hasData function for non-cartesian series. + * Returns true if the series has points at all. + * @private + */ + hasData: function () { + return !!this.points.length; // != 0 + }, + // If the tracking module is loaded, add the point tracker + drawTracker: TrackerMixin && TrackerMixin.drawTrackerPoint + /* eslint-enable valid-jsdoc */ +}, { + // Point members + /* eslint-disable valid-jsdoc */ + /** + * Don't do any hover colors or anything + * @private + */ + setState: function (state) { + this.state = state; + } + /* eslint-enable valid-jsdoc */ +}); +/** + * A `gauge` series. If the [type](#series.gauge.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.gauge + * @excluding animationLimit, boostThreshold, connectEnds, connectNulls, + * cropThreshold, dashStyle, dataParser, dataURL, findNearestPointBy, + * getExtremesFromAll, marker, negativeColor, pointPlacement, shadow, + * softThreshold, stack, stacking, states, step, threshold, + * turboThreshold, zoneAxis, zones, dataSorting + * @product highcharts + * @requires highcharts-more + * @apioption series.gauge + */ +/** + * An array of data points for the series. For the `gauge` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.gauge.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * y: 6, + * name: "Point2", + * color: "#00FF00" + * }, { + * y: 8, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * The typical gauge only contains a single data value. + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array} + * @extends series.line.data + * @excluding drilldown, marker, x + * @product highcharts + * @apioption series.gauge.data + */ +''; // adds the doclets above in the transpiled file diff --git a/librerias/gantt/code/es-modules/parts-more/HiddenAxis.js b/librerias/gantt/code/es-modules/parts-more/HiddenAxis.js new file mode 100644 index 0000000..4bc7d14 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-more/HiddenAxis.js @@ -0,0 +1,46 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +/** + * @private + * @class + */ +var HiddenAxis = /** @class */ (function () { + function HiddenAxis() { + } + /** + * Augments methods for the x axis in order to hide it completely. Used for + * the X axis in gauges + * + * @private + * + * @param {Highcharts.Axis} axis + * Radial axis to augment. + */ + HiddenAxis.init = function (axis) { + axis.getOffset = function () { }; + axis.redraw = function () { + this.isDirty = false; // prevent setting Y axis dirty + }; + axis.render = function () { + this.isDirty = false; // prevent setting Y axis dirty + }; + axis.createLabelCollector = function () { + return function () { + return; + }; + }; + axis.setScale = function () { }; + axis.setCategories = function () { }; + axis.setTitle = function () { }; + axis.isHidden = true; + }; + return HiddenAxis; +}()); +export default HiddenAxis; diff --git a/librerias/gantt/code/es-modules/parts-more/PackedBubbleSeries.js b/librerias/gantt/code/es-modules/parts-more/PackedBubbleSeries.js new file mode 100644 index 0000000..cb2cd4b --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-more/PackedBubbleSeries.js @@ -0,0 +1,1263 @@ +/* * + * + * (c) 2010-2018 Grzegorz Blachlinski, Sebastian Bochan + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +/** + * Formatter callback function. + * + * @callback Highcharts.SeriesPackedBubbleDataLabelsFormatterCallbackFunction + * + * @param {Highcharts.SeriesPackedBubbleDataLabelsFormatterContextObject} this + * Data label context to format + * + * @return {string} + * Formatted data label text + */ +/** + * Context for the formatter function. + * + * @interface Highcharts.SeriesPackedBubbleDataLabelsFormatterContextObject + * @extends Highcharts.PointLabelObject + * @since 7.0.0 + */ /** +* The color of the node. +* @name Highcharts.SeriesPackedBubbleDataLabelsFormatterContextObject#color +* @type {Highcharts.ColorString} +* @since 7.0.0 +*/ /** +* The point (node) object. The node name, if defined, is available through +* `this.point.name`. Arrays: `this.point.linksFrom` and `this.point.linksTo` +* contains all nodes connected to this point. +* @name Highcharts.SeriesPackedBubbleDataLabelsFormatterContextObject#point +* @type {Highcharts.Point} +* @since 7.0.0 +*/ /** +* The ID of the node. +* @name Highcharts.SeriesPackedBubbleDataLabelsFormatterContextObject#key +* @type {string} +* @since 7.0.0 +*/ +import Color from '../parts/Color.js'; +var color = Color.parse; +import Point from '../parts/Point.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, clamp = U.clamp, defined = U.defined, extend = U.extend, extendClass = U.extendClass, fireEvent = U.fireEvent, isArray = U.isArray, isNumber = U.isNumber, merge = U.merge, pick = U.pick, seriesType = U.seriesType; +import '../parts/Axis.js'; +import '../parts/Series.js'; +import '../modules/networkgraph/layouts.js'; +import '../modules/networkgraph/draggable-nodes.js'; +var Series = H.Series, Chart = H.Chart, Reingold = H.layouts['reingold-fruchterman'], NetworkPoint = H.seriesTypes.bubble.prototype.pointClass, dragNodesMixin = H.dragNodesMixin; +H.networkgraphIntegrations.packedbubble = { + repulsiveForceFunction: function (d, k, node, repNode) { + return Math.min(d, (node.marker.radius + repNode.marker.radius) / 2); + }, + barycenter: function () { + var layout = this, gravitationalConstant = layout.options.gravitationalConstant, box = layout.box, nodes = layout.nodes, centerX, centerY; + nodes.forEach(function (node) { + if (layout.options.splitSeries && !node.isParentNode) { + centerX = node.series.parentNode.plotX; + centerY = node.series.parentNode.plotY; + } + else { + centerX = box.width / 2; + centerY = box.height / 2; + } + if (!node.fixedPosition) { + node.plotX -= + (node.plotX - centerX) * + gravitationalConstant / + (node.mass * Math.sqrt(nodes.length)); + node.plotY -= + (node.plotY - centerY) * + gravitationalConstant / + (node.mass * Math.sqrt(nodes.length)); + } + }); + }, + repulsive: function (node, force, distanceXY, repNode) { + var factor = (force * this.diffTemperature / node.mass / + node.degree), x = distanceXY.x * factor, y = distanceXY.y * factor; + if (!node.fixedPosition) { + node.plotX += x; + node.plotY += y; + } + if (!repNode.fixedPosition) { + repNode.plotX -= x; + repNode.plotY -= y; + } + }, + integrate: H.networkgraphIntegrations.verlet.integrate, + getK: H.noop +}; +H.layouts.packedbubble = extendClass(Reingold, { + beforeStep: function () { + if (this.options.marker) { + this.series.forEach(function (series) { + if (series) { + series.calculateParentRadius(); + } + }); + } + }, + setCircularPositions: function () { + var layout = this, box = layout.box, nodes = layout.nodes, nodesLength = nodes.length + 1, angle = 2 * Math.PI / nodesLength, centerX, centerY, radius = layout.options.initialPositionRadius; + nodes.forEach(function (node, index) { + if (layout.options.splitSeries && + !node.isParentNode) { + centerX = node.series.parentNode.plotX; + centerY = node.series.parentNode.plotY; + } + else { + centerX = box.width / 2; + centerY = box.height / 2; + } + node.plotX = node.prevX = pick(node.plotX, centerX + + radius * Math.cos(node.index || index * angle)); + node.plotY = node.prevY = pick(node.plotY, centerY + + radius * Math.sin(node.index || index * angle)); + node.dispX = 0; + node.dispY = 0; + }); + }, + repulsiveForces: function () { + var layout = this, force, distanceR, distanceXY, bubblePadding = layout.options.bubblePadding; + layout.nodes.forEach(function (node) { + node.degree = node.mass; + node.neighbours = 0; + layout.nodes.forEach(function (repNode) { + force = 0; + if ( + // Node can not repulse itself: + node !== repNode && + // Only close nodes affect each other: + // Not dragged: + !node.fixedPosition && + (layout.options.seriesInteraction || + node.series === repNode.series)) { + distanceXY = layout.getDistXY(node, repNode); + distanceR = (layout.vectorLength(distanceXY) - + (node.marker.radius + + repNode.marker.radius + + bubblePadding)); + // TODO padding configurable + if (distanceR < 0) { + node.degree += 0.01; + node.neighbours++; + force = layout.repulsiveForce(-distanceR / Math.sqrt(node.neighbours), layout.k, node, repNode); + } + layout.force('repulsive', node, force * repNode.mass, distanceXY, repNode, distanceR); + } + }); + }); + }, + applyLimitBox: function (node) { + var layout = this, distanceXY, distanceR, factor = 0.01; + // parentNodeLimit should be used together + // with seriesInteraction: false + if (layout.options.splitSeries && + !node.isParentNode && + layout.options.parentNodeLimit) { + distanceXY = layout.getDistXY(node, node.series.parentNode); + distanceR = (node.series.parentNodeRadius - + node.marker.radius - + layout.vectorLength(distanceXY)); + if (distanceR < 0 && + distanceR > -2 * node.marker.radius) { + node.plotX -= distanceXY.x * factor; + node.plotY -= distanceXY.y * factor; + } + } + Reingold.prototype.applyLimitBox.apply(this, arguments); + } +}); +/** + * @private + * @class + * @name Highcharts.seriesTypes.packedbubble + * + * @extends Highcharts.Series + */ +seriesType('packedbubble', 'bubble', +/** + * A packed bubble series is a two dimensional series type, where each point + * renders a value in X, Y position. Each point is drawn as a bubble + * where the bubbles don't overlap with each other and the radius + * of the bubble relates to the value. + * + * @sample highcharts/demo/packed-bubble/ + * Packed bubble chart + * @sample highcharts/demo/packed-bubble-split/ + * Split packed bubble chart + + * @extends plotOptions.bubble + * @excluding connectEnds, connectNulls, dragDrop, jitter, keys, + * pointPlacement, sizeByAbsoluteValue, step, xAxis, yAxis, + * zMax, zMin, dataSorting + * @product highcharts + * @since 7.0.0 + * @requires highcharts-more + * @optionparent plotOptions.packedbubble + */ +{ + /** + * Minimum bubble size. Bubbles will automatically size between the + * `minSize` and `maxSize` to reflect the value of each bubble. + * Can be either pixels (when no unit is given), or a percentage of + * the smallest one of the plot width and height, divided by the square + * root of total number of points. + * + * @sample highcharts/plotoptions/bubble-size/ + * Bubble size + * + * @type {number|string} + * + * @private + */ + minSize: '10%', + /** + * Maximum bubble size. Bubbles will automatically size between the + * `minSize` and `maxSize` to reflect the value of each bubble. + * Can be either pixels (when no unit is given), or a percentage of + * the smallest one of the plot width and height, divided by the square + * root of total number of points. + * + * @sample highcharts/plotoptions/bubble-size/ + * Bubble size + * + * @type {number|string} + * + * @private + */ + maxSize: '50%', + sizeBy: 'area', + zoneAxis: 'y', + crisp: false, + tooltip: { + pointFormat: 'Value: {point.value}' + }, + /** + * Flag to determine if nodes are draggable or not. Available for + * graph with useSimulation set to true only. + * + * @since 7.1.0 + * + * @private + */ + draggable: true, + /** + * An option is giving a possibility to choose between using simulation + * for calculating bubble positions. These reflects in both animation + * and final position of bubbles. Simulation is also adding options to + * the series graph based on used layout. In case of big data sets, with + * any performance issues, it is possible to disable animation and pack + * bubble in a simple circular way. + * + * @sample highcharts/series-packedbubble/spiral/ + * useSimulation set to false + * + * @since 7.1.0 + * + * @private + */ + useSimulation: true, + /** + * @declare Highcharts.SeriesPackedBubbleDataLabelsOptionsObject + * + * @private + */ + dataLabels: { + /** + * The + * [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) + * specifying what to show for _node_ in the networkgraph. In v7.0 + * defaults to `{key}`, since v7.1 defaults to `undefined` and + * `formatter` is used instead. + * + * @type {string} + * @since 7.0.0 + * @apioption plotOptions.packedbubble.dataLabels.format + */ + // eslint-disable-next-line valid-jsdoc + /** + * Callback JavaScript function to format the data label for a node. + * Note that if a `format` is defined, the format takes precedence + * and the formatter is ignored. + * + * @type {Highcharts.SeriesPackedBubbleDataLabelsFormatterCallbackFunction} + * @since 7.0.0 + */ + formatter: function () { + return this.point.value; + }, + /** + * @type {string} + * @since 7.1.0 + * @apioption plotOptions.packedbubble.dataLabels.parentNodeFormat + */ + // eslint-disable-next-line valid-jsdoc + /** + * Callback to format data labels for _parentNodes_. The + * `parentNodeFormat` option takes precedence over the + * `parentNodeFormatter`. + * + * @type {Highcharts.SeriesPackedBubbleDataLabelsFormatterCallbackFunction} + * @since 7.1.0 + */ + parentNodeFormatter: function () { + return this.name; + }, + /** + * Options for a _parentNode_ label text. + * + * **Note:** Only SVG-based renderer supports this option. + * + * @sample {highcharts} highcharts/series-packedbubble/packed-dashboard + * Dashboard with dataLabels on parentNodes + * + * @declare Highcharts.SeriesPackedBubbleDataLabelsTextPathOptionsObject + * @since 7.1.0 + */ + parentNodeTextPath: { + /** + * Presentation attributes for the text path. + * + * @type {Highcharts.SVGAttributes} + * @since 7.1.0 + * @apioption plotOptions.packedbubble.dataLabels.attributes + */ + /** + * Enable or disable `textPath` option for link's or marker's + * data labels. + * + * @since 7.1.0 + */ + enabled: true + }, + /** + * Options for a _node_ label text which should follow marker's + * shape. + * + * **Note:** Only SVG-based renderer supports this option. + * + * @extends plotOptions.series.dataLabels.textPath + * @apioption plotOptions.packedbubble.dataLabels.textPath + */ + padding: 0, + style: { + transition: 'opacity 2000ms' + } + }, + /** + * Options for layout algorithm when simulation is enabled. Inside there + * are options to change the speed, padding, initial bubbles positions + * and more. + * + * @extends plotOptions.networkgraph.layoutAlgorithm + * @excluding approximation, attractiveForce, repulsiveForce, theta + * @since 7.1.0 + * + * @private + */ + layoutAlgorithm: { + /** + * Initial layout algorithm for positioning nodes. Can be one of + * the built-in options ("circle", "random") or a function where + * positions should be set on each node (`this.nodes`) as + * `node.plotX` and `node.plotY`. + * + * @sample highcharts/series-networkgraph/initial-positions/ + * Initial positions with callback + * + * @type {"circle"|"random"|Function} + */ + initialPositions: 'circle', + /** + * @sample highcharts/series-packedbubble/initial-radius/ + * Initial radius set to 200 + * + * @extends plotOptions.networkgraph.layoutAlgorithm.initialPositionRadius + * @excluding states + */ + initialPositionRadius: 20, + /** + * The distance between two bubbles, when the algorithm starts to + * treat two bubbles as overlapping. The `bubblePadding` is also the + * expected distance between all the bubbles on simulation end. + */ + bubblePadding: 5, + /** + * Whether bubbles should interact with their parentNode to keep + * them inside. + */ + parentNodeLimit: false, + /** + * Whether series should interact with each other or not. When + * `parentNodeLimit` is set to true, thi option should be set to + * false to avoid sticking points in wrong series parentNode. + */ + seriesInteraction: true, + /** + * In case of split series, this option allows user to drag and + * drop points between series, for changing point related series. + * + * @sample highcharts/series-packedbubble/packed-dashboard/ + * Example of drag'n drop bubbles for bubble kanban + */ + dragBetweenSeries: false, + /** + * Layout algorithm options for parent nodes. + * + * @extends plotOptions.networkgraph.layoutAlgorithm + * @excluding approximation, attractiveForce, enableSimulation, + * repulsiveForce, theta + */ + parentNodeOptions: { + maxIterations: 400, + gravitationalConstant: 0.03, + maxSpeed: 50, + initialPositionRadius: 100, + seriesInteraction: true, + /** + * Styling options for parentNodes markers. Similar to + * line.marker options. + * + * @sample highcharts/series-packedbubble/parentnode-style/ + * Bubble size + * + * @extends plotOptions.series.marker + * @excluding states + */ + marker: { + fillColor: null, + fillOpacity: 1, + lineWidth: 1, + lineColor: null, + symbol: 'circle' + } + }, + enableSimulation: true, + /** + * Type of the algorithm used when positioning bubbles. + * @ignore-option + */ + type: 'packedbubble', + /** + * Integration type. Integration determines how forces are applied + * on particles. The `packedbubble` integration is based on + * the networkgraph `verlet` integration, where the new position + * is based on a previous position without velocity: + * `newPosition += previousPosition - newPosition`. + * + * @sample highcharts/series-networkgraph/forces/ + * + * @ignore-option + */ + integration: 'packedbubble', + maxIterations: 1000, + /** + * Whether to split series into individual groups or to mix all + * series together. + * + * @since 7.1.0 + * @default false + */ + splitSeries: false, + /** + * Max speed that node can get in one iteration. In terms of + * simulation, it's a maximum translation (in pixels) that a node + * can move (in both, x and y, dimensions). While `friction` is + * applied on all nodes, max speed is applied only for nodes that + * move very fast, for example small or disconnected ones. + * + * @see [layoutAlgorithm.integration](#series.networkgraph.layoutAlgorithm.integration) + * + * @see [layoutAlgorithm.friction](#series.networkgraph.layoutAlgorithm.friction) + */ + maxSpeed: 5, + gravitationalConstant: 0.01, + friction: -0.981 + } +}, { + /** + * An internal option used for allowing nodes dragging. + * @private + */ + hasDraggableNodes: true, + /** + * Array of internal forces. Each force should be later defined in + * integrations.js. + * @private + */ + forces: ['barycenter', 'repulsive'], + pointArrayMap: ['value'], + pointValKey: 'value', + isCartesian: false, + requireSorting: false, + directTouch: true, + axisTypes: [], + noSharedTooltip: true, + // solving #12287 + searchPoint: H.noop, + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Create a single array of all points from all series + * @private + * @param {Highcharts.Series} series Array of all series objects + * @return {Array} Returns the array of all points. + */ + accumulateAllPoints: function (series) { + var chart = series.chart, allDataPoints = [], i, j; + for (i = 0; i < chart.series.length; i++) { + series = chart.series[i]; + if (series.visible || + !chart.options.chart.ignoreHiddenSeries) { + // add data to array only if series is visible + for (j = 0; j < series.yData.length; j++) { + allDataPoints.push([ + null, null, + series.yData[j], + series.index, + j, + { + id: j, + marker: { + radius: 0 + } + } + ]); + } + } + } + return allDataPoints; + }, + init: function () { + Series.prototype.init.apply(this, arguments); + // When one series is modified, the others need to be recomputed + addEvent(this, 'updatedData', function () { + this.chart.series.forEach(function (s) { + if (s.type === this.type) { + s.isDirty = true; + } + }, this); + }); + return this; + }, + render: function () { + var series = this, dataLabels = []; + Series.prototype.render.apply(this, arguments); + // #10823 - dataLabels should stay visible + // when enabled allowOverlap. + if (!series.options.dataLabels.allowOverlap) { + series.data.forEach(function (point) { + if (isArray(point.dataLabels)) { + point.dataLabels.forEach(function (dataLabel) { + dataLabels.push(dataLabel); + }); + } + }); + // Only hide overlapping dataLabels for layouts that + // use simulation. Spiral packedbubble don't need + // additional dataLabel hiding on every simulation step + if (series.options.useSimulation) { + series.chart.hideOverlappingLabels(dataLabels); + } + } + }, + // Needed because of z-indexing issue if point is added in series.group + setVisible: function () { + var series = this; + Series.prototype.setVisible.apply(series, arguments); + if (series.parentNodeLayout && series.graph) { + if (series.visible) { + series.graph.show(); + if (series.parentNode.dataLabel) { + series.parentNode.dataLabel.show(); + } + } + else { + series.graph.hide(); + series.parentNodeLayout + .removeElementFromCollection(series.parentNode, series.parentNodeLayout.nodes); + if (series.parentNode.dataLabel) { + series.parentNode.dataLabel.hide(); + } + } + } + else if (series.layout) { + if (series.visible) { + series.layout.addElementsToCollection(series.points, series.layout.nodes); + } + else { + series.points.forEach(function (node) { + series.layout.removeElementFromCollection(node, series.layout.nodes); + }); + } + } + }, + // Packedbubble has two separate collecions of nodes if split, render + // dataLabels for both sets: + drawDataLabels: function () { + var textPath = this.options.dataLabels.textPath, points = this.points; + // Render node labels: + Series.prototype.drawDataLabels.apply(this, arguments); + // Render parentNode labels: + if (this.parentNode) { + this.parentNode.formatPrefix = 'parentNode'; + this.points = [this.parentNode]; + this.options.dataLabels.textPath = + this.options.dataLabels.parentNodeTextPath; + Series.prototype.drawDataLabels.apply(this, arguments); + // Restore nodes + this.points = points; + this.options.dataLabels.textPath = textPath; + } + }, + /** + * The function responsible for calculating series bubble' s bBox. + * Needed because of exporting failure when useSimulation + * is set to false + * @private + */ + seriesBox: function () { + var series = this, chart = series.chart, data = series.data, max = Math.max, min = Math.min, radius, + // bBox = [xMin, xMax, yMin, yMax] + bBox = [ + chart.plotLeft, + chart.plotLeft + chart.plotWidth, + chart.plotTop, + chart.plotTop + chart.plotHeight + ]; + data.forEach(function (p) { + if (defined(p.plotX) && + defined(p.plotY) && + p.marker.radius) { + radius = p.marker.radius; + bBox[0] = min(bBox[0], p.plotX - radius); + bBox[1] = max(bBox[1], p.plotX + radius); + bBox[2] = min(bBox[2], p.plotY - radius); + bBox[3] = max(bBox[3], p.plotY + radius); + } + }); + return isNumber(bBox.width / bBox.height) ? + bBox : + null; + }, + /** + * The function responsible for calculating the parent node radius + * based on the total surface of iniside-bubbles and the group BBox + * @private + */ + calculateParentRadius: function () { + var series = this, bBox, parentPadding = 20, minParentRadius = 20; + bBox = series.seriesBox(); + series.parentNodeRadius = clamp(Math.sqrt(2 * series.parentNodeMass / Math.PI) + parentPadding, minParentRadius, bBox ? + Math.max(Math.sqrt(Math.pow(bBox.width, 2) + + Math.pow(bBox.height, 2)) / 2 + parentPadding, minParentRadius) : + Math.sqrt(2 * series.parentNodeMass / Math.PI) + parentPadding); + if (series.parentNode) { + series.parentNode.marker.radius = + series.parentNode.radius = series.parentNodeRadius; + } + }, + // Create Background/Parent Nodes for split series. + drawGraph: function () { + // if the series is not using layout, don't add parent nodes + if (!this.layout || !this.layout.options.splitSeries) { + return; + } + var series = this, chart = series.chart, parentAttribs = {}, nodeMarker = this.layout.options.parentNodeOptions.marker, parentOptions = { + fill: nodeMarker.fillColor || color(series.color).brighten(0.4).get(), + opacity: nodeMarker.fillOpacity, + stroke: nodeMarker.lineColor || series.color, + 'stroke-width': nodeMarker.lineWidth + }, visibility = series.visible ? 'inherit' : 'hidden'; + // create the group for parent Nodes if doesn't exist + if (!this.parentNodesGroup) { + series.parentNodesGroup = series.plotGroup('parentNodesGroup', 'parentNode', visibility, 0.1, chart.seriesGroup); + series.group.attr({ + zIndex: 2 + }); + } + this.calculateParentRadius(); + parentAttribs = merge({ + x: series.parentNode.plotX - + series.parentNodeRadius, + y: series.parentNode.plotY - + series.parentNodeRadius, + width: series.parentNodeRadius * 2, + height: series.parentNodeRadius * 2 + }, parentOptions); + if (!series.parentNode.graphic) { + series.graph = series.parentNode.graphic = + chart.renderer.symbol(parentOptions.symbol) + .add(series.parentNodesGroup); + } + series.parentNode.graphic.attr(parentAttribs); + }, + /** + * Creating parent nodes for split series, in which all the bubbles + * are rendered. + * @private + */ + createParentNodes: function () { + var series = this, chart = series.chart, parentNodeLayout = series.parentNodeLayout, nodeAdded, parentNode = series.parentNode; + series.parentNodeMass = 0; + series.points.forEach(function (p) { + series.parentNodeMass += + Math.PI * Math.pow(p.marker.radius, 2); + }); + series.calculateParentRadius(); + parentNodeLayout.nodes.forEach(function (node) { + if (node.seriesIndex === series.index) { + nodeAdded = true; + } + }); + parentNodeLayout.setArea(0, 0, chart.plotWidth, chart.plotHeight); + if (!nodeAdded) { + if (!parentNode) { + parentNode = (new NetworkPoint()).init(this, { + mass: series.parentNodeRadius / 2, + marker: { + radius: series.parentNodeRadius + }, + dataLabels: { + inside: false + }, + dataLabelOnNull: true, + degree: series.parentNodeRadius, + isParentNode: true, + seriesIndex: series.index + }); + } + if (series.parentNode) { + parentNode.plotX = series.parentNode.plotX; + parentNode.plotY = series.parentNode.plotY; + } + series.parentNode = parentNode; + parentNodeLayout.addElementsToCollection([series], parentNodeLayout.series); + parentNodeLayout.addElementsToCollection([parentNode], parentNodeLayout.nodes); + } + }, + /** + * Function responsible for adding series layout, used for parent nodes. + * @private + */ + addSeriesLayout: function () { + var series = this, layoutOptions = series.options.layoutAlgorithm, graphLayoutsStorage = series.chart.graphLayoutsStorage, graphLayoutsLookup = series.chart.graphLayoutsLookup, parentNodeOptions = merge(layoutOptions, layoutOptions.parentNodeOptions, { + enableSimulation: series.layout.options.enableSimulation + }), parentNodeLayout; + parentNodeLayout = graphLayoutsStorage[layoutOptions.type + '-series']; + if (!parentNodeLayout) { + graphLayoutsStorage[layoutOptions.type + '-series'] = + parentNodeLayout = + new H.layouts[layoutOptions.type](); + parentNodeLayout.init(parentNodeOptions); + graphLayoutsLookup.splice(parentNodeLayout.index, 0, parentNodeLayout); + } + series.parentNodeLayout = parentNodeLayout; + this.createParentNodes(); + }, + /** + * Adding the basic layout to series points. + * @private + */ + addLayout: function () { + var series = this, layoutOptions = series.options.layoutAlgorithm, graphLayoutsStorage = series.chart.graphLayoutsStorage, graphLayoutsLookup = series.chart.graphLayoutsLookup, chartOptions = series.chart.options.chart, layout; + if (!graphLayoutsStorage) { + series.chart.graphLayoutsStorage = graphLayoutsStorage = {}; + series.chart.graphLayoutsLookup = graphLayoutsLookup = []; + } + layout = graphLayoutsStorage[layoutOptions.type]; + if (!layout) { + layoutOptions.enableSimulation = + !defined(chartOptions.forExport) ? + layoutOptions.enableSimulation : + !chartOptions.forExport; + graphLayoutsStorage[layoutOptions.type] = layout = + new H.layouts[layoutOptions.type](); + layout.init(layoutOptions); + graphLayoutsLookup.splice(layout.index, 0, layout); + } + series.layout = layout; + series.points.forEach(function (node) { + node.mass = 2; + node.degree = 1; + node.collisionNmb = 1; + }); + layout.setArea(0, 0, series.chart.plotWidth, series.chart.plotHeight); + layout.addElementsToCollection([series], layout.series); + layout.addElementsToCollection(series.points, layout.nodes); + }, + /** + * Function responsible for adding all the layouts to the chart. + * @private + */ + deferLayout: function () { + // TODO split layouts to independent methods + var series = this, layoutOptions = series.options.layoutAlgorithm; + if (!series.visible) { + return; + } + // layout is using nodes for position calculation + series.addLayout(); + if (layoutOptions.splitSeries) { + series.addSeriesLayout(); + } + }, + /** + * Extend the base translate method to handle bubble size, + * and correct positioning them. + * @private + */ + translate: function () { + var series = this, chart = series.chart, data = series.data, index = series.index, point, radius, positions, i, useSimulation = series.options.useSimulation; + series.processedXData = series.xData; + series.generatePoints(); + // merged data is an array with all of the data from all series + if (!defined(chart.allDataPoints)) { + chart.allDataPoints = series.accumulateAllPoints(series); + // calculate radius for all added data + series.getPointRadius(); + } + // after getting initial radius, calculate bubble positions + if (useSimulation) { + positions = chart.allDataPoints; + } + else { + positions = series.placeBubbles(chart.allDataPoints); + series.options.draggable = false; + } + // Set the shape and arguments to be picked up in drawPoints + for (i = 0; i < positions.length; i++) { + if (positions[i][3] === index) { + // update the series points with the val from positions + // array + point = data[positions[i][4]]; + radius = positions[i][2]; + if (!useSimulation) { + point.plotX = (positions[i][0] - chart.plotLeft + + chart.diffX); + point.plotY = (positions[i][1] - chart.plotTop + + chart.diffY); + } + point.marker = extend(point.marker, { + radius: radius, + width: 2 * radius, + height: 2 * radius + }); + point.radius = radius; + } + } + if (useSimulation) { + series.deferLayout(); + } + fireEvent(series, 'afterTranslate'); + }, + /** + * Check if two bubbles overlaps. + * @private + * @param {Array} first bubble + * @param {Array} second bubble + * @return {Boolean} overlap or not + */ + checkOverlap: function (bubble1, bubble2) { + var diffX = bubble1[0] - bubble2[0], // diff of X center values + diffY = bubble1[1] - bubble2[1], // diff of Y center values + sumRad = bubble1[2] + bubble2[2]; // sum of bubble radius + return (Math.sqrt(diffX * diffX + diffY * diffY) - + Math.abs(sumRad)) < -0.001; + }, + /** + * Function that is adding one bubble based on positions and sizes of + * two other bubbles, lastBubble is the last added bubble, newOrigin is + * the bubble for positioning new bubbles. nextBubble is the curently + * added bubble for which we are calculating positions + * @private + * @param {Array} lastBubble The closest last bubble + * @param {Array} newOrigin New bubble + * @param {Array} nextBubble The closest next bubble + * @return {Array} Bubble with correct positions + */ + positionBubble: function (lastBubble, newOrigin, nextBubble) { + var sqrt = Math.sqrt, asin = Math.asin, acos = Math.acos, pow = Math.pow, abs = Math.abs, distance = sqrt(// dist between lastBubble and newOrigin + pow((lastBubble[0] - newOrigin[0]), 2) + + pow((lastBubble[1] - newOrigin[1]), 2)), alfa = acos( + // from cosinus theorem: alfa is an angle used for + // calculating correct position + (pow(distance, 2) + + pow(nextBubble[2] + newOrigin[2], 2) - + pow(nextBubble[2] + lastBubble[2], 2)) / (2 * (nextBubble[2] + newOrigin[2]) * distance)), beta = asin(// from sinus theorem. + abs(lastBubble[0] - newOrigin[0]) / + distance), + // providing helping variables, related to angle between + // lastBubble and newOrigin + gamma = (lastBubble[1] - newOrigin[1]) < 0 ? 0 : Math.PI, + // if new origin y is smaller than last bubble y value + // (2 and 3 quarter), + // add Math.PI to final angle + delta = (lastBubble[0] - newOrigin[0]) * + (lastBubble[1] - newOrigin[1]) < 0 ? + 1 : -1, // (1st and 3rd quarter) + finalAngle = gamma + alfa + beta * delta, cosA = Math.cos(finalAngle), sinA = Math.sin(finalAngle), posX = newOrigin[0] + (newOrigin[2] + nextBubble[2]) * sinA, + // center of new origin + (radius1 + radius2) * sinus A + posY = newOrigin[1] - (newOrigin[2] + nextBubble[2]) * cosA; + return [ + posX, + posY, + nextBubble[2], + nextBubble[3], + nextBubble[4] + ]; // the same as described before + }, + /** + * This is the main function responsible + * for positioning all of the bubbles + * allDataPoints - bubble array, in format [pixel x value, + * pixel y value, radius, + * related series index, related point index] + * @private + * @param {Array} allDataPoints All points from all series + * @return {Array} Positions of all bubbles + */ + placeBubbles: function (allDataPoints) { + var series = this, checkOverlap = series.checkOverlap, positionBubble = series.positionBubble, bubblePos = [], stage = 1, j = 0, k = 0, calculatedBubble, sortedArr, arr = [], i; + // sort all points + sortedArr = allDataPoints.sort(function (a, b) { + return b[2] - a[2]; + }); + if (sortedArr.length) { + // create first bubble in the middle of the chart + bubblePos.push([ + [ + 0, + 0, + sortedArr[0][2], + sortedArr[0][3], + sortedArr[0][4] + ] // point index + ]); // 0 level bubble + if (sortedArr.length > 1) { + bubblePos.push([ + [ + 0, + (0 - sortedArr[1][2] - + sortedArr[0][2]), + // move bubble above first one + sortedArr[1][2], + sortedArr[1][3], + sortedArr[1][4] + ] + ]); // 1 level 1st bubble + // first two already positioned so starting from 2 + for (i = 2; i < sortedArr.length; i++) { + sortedArr[i][2] = sortedArr[i][2] || 1; + // in case if radius is calculated as 0. + calculatedBubble = positionBubble(bubblePos[stage][j], bubblePos[stage - 1][k], sortedArr[i]); // calculate initial bubble position + if (checkOverlap(calculatedBubble, bubblePos[stage][0])) { + /* if new bubble is overlapping with first bubble + * in current level (stage) + */ + bubblePos.push([]); + k = 0; + /* reset index of bubble, used for + * positioning the bubbles around it, + * we are starting from first bubble in next + * stage because we are changing level to higher + */ + bubblePos[stage + 1].push(positionBubble(bubblePos[stage][j], bubblePos[stage][0], sortedArr[i])); + // (last bubble, 1. from curr stage, new bubble) + stage++; // the new level is created, above current + j = 0; // set the index of bubble in curr level to 0 + } + else if (stage > 1 && + bubblePos[stage - 1][k + 1] && + checkOverlap(calculatedBubble, bubblePos[stage - 1][k + 1])) { + /* if new bubble is overlapping with one of the prev + * stage bubbles, it means that - bubble, used for + * positioning the bubbles around it has changed + * so we need to recalculate it + */ + k++; + bubblePos[stage].push(positionBubble(bubblePos[stage][j], bubblePos[stage - 1][k], sortedArr[i])); + // (last bubble, prev stage bubble, new bubble) + j++; + } + else { // simply add calculated bubble + j++; + bubblePos[stage].push(calculatedBubble); + } + } + } + series.chart.stages = bubblePos; + // it may not be necessary but adding it just in case - + // it is containing all of the bubble levels + series.chart.rawPositions = + [] + .concat.apply([], bubblePos); + // bubble positions merged into one array + series.resizeRadius(); + arr = series.chart.rawPositions; + } + return arr; + }, + /** + * The function responsible for resizing the bubble radius. + * In shortcut: it is taking the initially + * calculated positions of bubbles. Then it is calculating the min max + * of both dimensions, creating something in shape of bBox. + * The comparison of bBox and the size of plotArea + * (later it may be also the size set by customer) is giving the + * value how to recalculate the radius so it will match the size + * @private + */ + resizeRadius: function () { + var chart = this.chart, positions = chart.rawPositions, min = Math.min, max = Math.max, plotLeft = chart.plotLeft, plotTop = chart.plotTop, chartHeight = chart.plotHeight, chartWidth = chart.plotWidth, minX, maxX, minY, maxY, radius, bBox, spaceRatio, smallerDimension, i; + minX = minY = Number.POSITIVE_INFINITY; // set initial values + maxX = maxY = Number.NEGATIVE_INFINITY; + for (i = 0; i < positions.length; i++) { + radius = positions[i][2]; + minX = min(minX, positions[i][0] - radius); + // (x center-radius) is the min x value used by specific bubble + maxX = max(maxX, positions[i][0] + radius); + minY = min(minY, positions[i][1] - radius); + maxY = max(maxY, positions[i][1] + radius); + } + bBox = [maxX - minX, maxY - minY]; + spaceRatio = [ + (chartWidth - plotLeft) / bBox[0], + (chartHeight - plotTop) / bBox[1] + ]; + smallerDimension = min.apply([], spaceRatio); + if (Math.abs(smallerDimension - 1) > 1e-10) { + // if bBox is considered not the same width as possible size + for (i = 0; i < positions.length; i++) { + positions[i][2] *= smallerDimension; + } + this.placeBubbles(positions); + } + else { + /** if no radius recalculation is needed, we need to position + * the whole bubbles in center of chart plotarea + * for this, we are adding two parameters, + * diffY and diffX, that are related to differences + * between the initial center and the bounding box + */ + chart.diffY = chartHeight / 2 + + plotTop - minY - (maxY - minY) / 2; + chart.diffX = chartWidth / 2 + + plotLeft - minX - (maxX - minX) / 2; + } + }, + /** + * Calculate min and max bubble value for radius calculation. + * @private + */ + calculateZExtremes: function () { + var chart = this.chart, zMin = this.options.zMin, zMax = this.options.zMax, valMin = Infinity, valMax = -Infinity; + if (zMin && zMax) { + return [zMin, zMax]; + } + // it is needed to deal with null + // and undefined values + chart.series.forEach(function (s) { + s.yData.forEach(function (p) { + if (defined(p)) { + if (p > valMax) { + valMax = p; + } + if (p < valMin) { + valMin = p; + } + } + }); + }); + zMin = pick(zMin, valMin); + zMax = pick(zMax, valMax); + return [zMin, zMax]; + }, + /** + * Calculate radius of bubbles in series. + * @private + */ + getPointRadius: function () { + var series = this, chart = series.chart, plotWidth = chart.plotWidth, plotHeight = chart.plotHeight, seriesOptions = series.options, useSimulation = seriesOptions.useSimulation, smallestSize = Math.min(plotWidth, plotHeight), extremes = {}, radii = [], allDataPoints = chart.allDataPoints, minSize, maxSize, value, radius, zExtremes; + ['minSize', 'maxSize'].forEach(function (prop) { + var length = parseInt(seriesOptions[prop], 10), isPercent = /%$/.test(seriesOptions[prop]); + extremes[prop] = isPercent ? + smallestSize * length / 100 : + length * Math.sqrt(allDataPoints.length); + }); + chart.minRadius = minSize = extremes.minSize / + Math.sqrt(allDataPoints.length); + chart.maxRadius = maxSize = extremes.maxSize / + Math.sqrt(allDataPoints.length); + zExtremes = useSimulation ? + series.calculateZExtremes() : + [minSize, maxSize]; + (allDataPoints || []).forEach(function (point, i) { + value = useSimulation ? + clamp(point[2], zExtremes[0], zExtremes[1]) : + point[2]; + radius = series.getRadius(zExtremes[0], zExtremes[1], minSize, maxSize, value); + if (radius === 0) { + radius = null; + } + allDataPoints[i][2] = radius; + radii.push(radius); + }); + series.radii = radii; + }, + // Draggable mode: + /** + * Redraw halo on mousemove during the drag&drop action. + * @private + * @param {Highcharts.Point} point The point that should show halo. + */ + redrawHalo: dragNodesMixin.redrawHalo, + /** + * Mouse down action, initializing drag&drop mode. + * @private + * @param {global.Event} event Browser event, before normalization. + * @param {Highcharts.Point} point The point that event occured. + */ + onMouseDown: dragNodesMixin.onMouseDown, + /** + * Mouse move action during drag&drop. + * @private + * @param {global.Event} event Browser event, before normalization. + * @param {Highcharts.Point} point The point that event occured. + */ + onMouseMove: dragNodesMixin.onMouseMove, + /** + * Mouse up action, finalizing drag&drop. + * @private + * @param {Highcharts.Point} point The point that event occured. + */ + onMouseUp: function (point) { + if (point.fixedPosition && !point.removed) { + var distanceXY, distanceR, layout = this.layout, parentNodeLayout = this.parentNodeLayout; + if (parentNodeLayout && layout.options.dragBetweenSeries) { + parentNodeLayout.nodes.forEach(function (node) { + if (point && point.marker && + node !== point.series.parentNode) { + distanceXY = layout.getDistXY(point, node); + distanceR = (layout.vectorLength(distanceXY) - + node.marker.radius - + point.marker.radius); + if (distanceR < 0) { + node.series.addPoint(merge(point.options, { + plotX: point.plotX, + plotY: point.plotY + }), false); + layout.removeElementFromCollection(point, layout.nodes); + point.remove(); + } + } + }); + } + dragNodesMixin.onMouseUp.apply(this, arguments); + } + }, + destroy: function () { + // Remove the series from all layouts series collections #11469 + if (this.chart.graphLayoutsLookup) { + this.chart.graphLayoutsLookup.forEach(function (layout) { + layout.removeElementFromCollection(this, layout.series); + }, this); + } + if (this.parentNode) { + this.parentNodeLayout.removeElementFromCollection(this.parentNode, this.parentNodeLayout.nodes); + if (this.parentNode.dataLabel) { + this.parentNode.dataLabel = + this.parentNode.dataLabel.destroy(); + } + } + H.Series.prototype.destroy.apply(this, arguments); + }, + alignDataLabel: H.Series.prototype.alignDataLabel +}, { + /** + * Destroy point. + * Then remove point from the layout. + * @private + * @return {undefined} + */ + destroy: function () { + if (this.series.layout) { + this.series.layout.removeElementFromCollection(this, this.series.layout.nodes); + } + return Point.prototype.destroy.apply(this, arguments); + } +}); +// Remove accumulated data points to redistribute all of them again +// (i.e after hiding series by legend) +addEvent(Chart, 'beforeRedraw', function () { + if (this.allDataPoints) { + delete this.allDataPoints; + } +}); +/* eslint-enable no-invalid-this, valid-jsdoc */ +/** + * A `packedbubble` series. If the [type](#series.packedbubble.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @type {Object} + * @extends series,plotOptions.packedbubble + * @excluding dataParser, dataSorting, dataURL, dragDrop, stack + * @product highcharts + * @requires highcharts-more + * @apioption series.packedbubble + */ +/** + * An array of data points for the series. For the `packedbubble` series type, + * points can be given in the following ways: + * + * 1. An array of `values`. + * + * ```js + * data: [5, 1, 20] + * ``` + * + * 2. An array of objects with named values. The objects are point + * configuration objects as seen below. If the total number of data points + * exceeds the series' [turboThreshold](#series.packedbubble.turboThreshold), + * this option is not available. + * + * ```js + * data: [{ + * value: 1, + * name: "Point2", + * color: "#00FF00" + * }, { + * value: 5, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @type {Array} + * @extends series.line.data + * @excluding marker, x, y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * @product highcharts + * @apioption series.packedbubble.data + */ +/** + * @type {Highcharts.SeriesPackedBubbleDataLabelsOptionsObject|Array} + * @product highcharts + * @apioption series.packedbubble.data.dataLabels + */ +/** + * @excluding enabled,enabledThreshold,height,radius,width + * @product highcharts + * @apioption series.packedbubble.marker + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/parts-more/Pane.js b/librerias/gantt/code/es-modules/parts-more/Pane.js new file mode 100644 index 0000000..eca4f9b --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-more/Pane.js @@ -0,0 +1,401 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +/** + * @typedef {"arc"|"circle"|"solid"} Highcharts.PaneBackgroundShapeValue + */ +import '../mixins/centered-series.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, extend = U.extend, merge = U.merge, pick = U.pick, splat = U.splat; +var CenteredSeriesMixin = H.CenteredSeriesMixin; +/* eslint-disable no-invalid-this, valid-jsdoc */ +H.Chart.prototype.collectionsWithUpdate.push('pane'); +/** + * The Pane object allows options that are common to a set of X and Y axes. + * + * In the future, this can be extended to basic Highcharts and Highstock. + * + * @private + * @class + * @name Highcharts.Pane + * @param {Highcharts.PaneOptions} options + * @param {Highcharts.Chart} chart + */ +var Pane = /** @class */ (function () { + function Pane(options, chart) { + this.background = void 0; + this.center = void 0; + this.chart = void 0; + this.options = void 0; + this.coll = 'pane'; // Member of chart.pane + /** + * The pane serves as a container for axes and backgrounds for circular + * gauges and polar charts. + * + * @since 2.3.0 + * @product highcharts + * @requires highcharts-more + * @optionparent pane + */ + this.defaultOptions = { + /** + * The end angle of the polar X axis or gauge value axis, given in + * degrees where 0 is north. Defaults to [startAngle](#pane.startAngle) + * + 360. + * + * @sample {highcharts} highcharts/demo/gauge-vu-meter/ + * VU-meter with custom start and end angle + * + * @type {number} + * @since 2.3.0 + * @product highcharts + * @apioption pane.endAngle + */ + /** + * The center of a polar chart or angular gauge, given as an array + * of [x, y] positions. Positions can be given as integers that + * transform to pixels, or as percentages of the plot area size. + * + * @sample {highcharts} highcharts/demo/gauge-vu-meter/ + * Two gauges with different center + * + * @type {Array} + * @default ["50%", "50%"] + * @since 2.3.0 + * @product highcharts + */ + center: ['50%', '50%'], + /** + * The size of the pane, either as a number defining pixels, or a + * percentage defining a percentage of the available plot area (the + * smallest of the plot height or plot width). + * + * @sample {highcharts} highcharts/demo/gauge-vu-meter/ + * Smaller size + * + * @type {number|string} + * @product highcharts + */ + size: '85%', + /** + * The inner size of the pane, either as a number defining pixels, or a + * percentage defining a percentage of the pane's size. + * + * @sample {highcharts} highcharts/series-polar/column-inverted-inner + * The inner size set to 20% + * + * @type {number|string} + * @product highcharts + */ + innerSize: '0%', + /** + * The start angle of the polar X axis or gauge axis, given in degrees + * where 0 is north. Defaults to 0. + * + * @sample {highcharts} highcharts/demo/gauge-vu-meter/ + * VU-meter with custom start and end angle + * + * @since 2.3.0 + * @product highcharts + */ + startAngle: 0 + }; + /** + * An array of background items for the pane. + * + * @sample {highcharts} highcharts/demo/gauge-speedometer/ + * Speedometer gauge with multiple backgrounds + * + * @type {Array<*>} + * @optionparent pane.background + */ + this.defaultBackgroundOptions = { + /** + * The class name for this background. + * + * @sample {highcharts} highcharts/css/pane/ + * Panes styled by CSS + * @sample {highstock} highcharts/css/pane/ + * Panes styled by CSS + * @sample {highmaps} highcharts/css/pane/ + * Panes styled by CSS + * + * @type {string} + * @default highcharts-pane + * @since 5.0.0 + * @apioption pane.background.className + */ + /** + * The shape of the pane background. When `solid`, the background + * is circular. When `arc`, the background extends only from the min + * to the max of the value axis. + * + * @type {Highcharts.PaneBackgroundShapeValue} + * @since 2.3.0 + * @product highcharts + */ + shape: 'circle', + /** + * The pixel border width of the pane background. + * + * @since 2.3.0 + * @product highcharts + */ + borderWidth: 1, + /** + * The pane background border color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.3.0 + * @product highcharts + */ + borderColor: '#cccccc', + /** + * The background color or gradient for the pane. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default { linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, stops: [[0, #ffffff], [1, #e6e6e6]] } + * @since 2.3.0 + * @product highcharts + */ + backgroundColor: { + /** @ignore-option */ + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + /** @ignore-option */ + stops: [ + [0, '#ffffff'], + [1, '#e6e6e6'] + ] + }, + /** @ignore-option */ + from: -Number.MAX_VALUE, + /** + * The inner radius of the pane background. Can be either numeric + * (pixels) or a percentage string. + * + * @type {number|string} + * @since 2.3.0 + * @product highcharts + */ + innerRadius: 0, + /** @ignore-option */ + to: Number.MAX_VALUE, + /** + * The outer radius of the circular pane background. Can be either + * numeric (pixels) or a percentage string. + * + * @type {number|string} + * @since 2.3.0 + * @product highcharts + */ + outerRadius: '105%' + }; + this.init(options, chart); + } + /** + * Initialize the Pane object + * + * @private + * @function Highcharts.Pane#init + * + * @param {Highcharts.PaneOptions} options + * + * @param {Highcharts.Chart} chart + */ + Pane.prototype.init = function (options, chart) { + this.chart = chart; + this.background = []; + chart.pane.push(this); + this.setOptions(options); + }; + /** + * @private + * @function Highcharts.Pane#setOptions + * + * @param {Highcharts.PaneOptions} options + */ + Pane.prototype.setOptions = function (options) { + // Set options. Angular charts have a default background (#3318) + this.options = options = merge(this.defaultOptions, this.chart.angular ? { background: {} } : void 0, options); + }; + /** + * Render the pane with its backgrounds. + * + * @private + * @function Highcharts.Pane#render + */ + Pane.prototype.render = function () { + var options = this.options, backgroundOption = this.options.background, renderer = this.chart.renderer, len, i; + if (!this.group) { + this.group = renderer.g('pane-group') + .attr({ zIndex: options.zIndex || 0 }) + .add(); + } + this.updateCenter(); + // Render the backgrounds + if (backgroundOption) { + backgroundOption = splat(backgroundOption); + len = Math.max(backgroundOption.length, this.background.length || 0); + for (i = 0; i < len; i++) { + // #6641 - if axis exists, chart is circular and apply + // background + if (backgroundOption[i] && this.axis) { + this.renderBackground(merge(this.defaultBackgroundOptions, backgroundOption[i]), i); + } + else if (this.background[i]) { + this.background[i] = this.background[i].destroy(); + this.background.splice(i, 1); + } + } + } + }; + /** + * Render an individual pane background. + * + * @private + * @function Highcharts.Pane#renderBackground + * + * @param {Highcharts.PaneBackgroundOptions} backgroundOptions + * Background options + * + * @param {number} i + * The index of the background in this.backgrounds + */ + Pane.prototype.renderBackground = function (backgroundOptions, i) { + var method = 'animate', attribs = { + 'class': 'highcharts-pane ' + (backgroundOptions.className || '') + }; + if (!this.chart.styledMode) { + extend(attribs, { + 'fill': backgroundOptions.backgroundColor, + 'stroke': backgroundOptions.borderColor, + 'stroke-width': backgroundOptions.borderWidth + }); + } + if (!this.background[i]) { + this.background[i] = this.chart.renderer + .path() + .add(this.group); + method = 'attr'; + } + this.background[i][method]({ + 'd': this.axis.getPlotBandPath(backgroundOptions.from, backgroundOptions.to, backgroundOptions) + }).attr(attribs); + }; + /** + * Gets the center for the pane and its axis. + * + * @private + * @function Highcharts.Pane#updateCenter + * @param {Highcharts.Axis} [axis] + * @return {void} + */ + Pane.prototype.updateCenter = function (axis) { + this.center = (axis || + this.axis || + {}).center = CenteredSeriesMixin.getCenter.call(this); + }; + /** + * Destroy the pane item + * + * @ignore + * @private + * @function Highcharts.Pane#destroy + * / + destroy: function () { + erase(this.chart.pane, this); + this.background.forEach(function (background) { + background.destroy(); + }); + this.background.length = 0; + this.group = this.group.destroy(); + }, + */ + /** + * Update the pane item with new options + * + * @private + * @function Highcharts.Pane#update + * @param {Highcharts.PaneOptions} options + * New pane options + * @param {boolean} [redraw] + * @return {void} + */ + Pane.prototype.update = function (options, redraw) { + merge(true, this.options, options); + merge(true, this.chart.options.pane, options); // #9917 + this.setOptions(this.options); + this.render(); + this.chart.axes.forEach(function (axis) { + if (axis.pane === this) { + axis.pane = null; + axis.update({}, redraw); + } + }, this); + }; + return Pane; +}()); +/** + * Check whether element is inside or outside pane. + * @private + * @param {number} x Element's x coordinate + * @param {number} y Element's y coordinate + * @param {Array} center Pane's center (x, y) and diameter + * @return {boolean} + */ +function isInsidePane(x, y, center) { + return Math.sqrt(Math.pow(x - center[0], 2) + Math.pow(y - center[1], 2)) < center[2] / 2; +} +H.Chart.prototype.getHoverPane = function (eventArgs) { + var chart = this; + var hoverPane; + if (eventArgs) { + chart.pane.forEach(function (pane) { + var plotX = eventArgs.chartX - chart.plotLeft, plotY = eventArgs.chartY - chart.plotTop, x = chart.inverted ? plotY : plotX, y = chart.inverted ? plotX : plotY; + if (isInsidePane(x, y, pane.center)) { + hoverPane = pane; + } + }); + } + return hoverPane; +}; +addEvent(H.Chart, 'afterIsInsidePlot', function (e) { + var chart = this; + if (chart.polar) { + e.isInsidePlot = chart.pane.some(function (pane) { return isInsidePane(e.x, e.y, pane.center); }); + } +}); +addEvent(H.Pointer, 'beforeGetHoverData', function (eventArgs) { + var chart = this.chart; + if (chart.polar) { + // Find pane we are currently hovering over. + chart.hoverPane = chart.getHoverPane(eventArgs); + // Edit filter method to handle polar + eventArgs.filter = function (s) { + return (s.visible && + !(!eventArgs.shared && s.directTouch) && // #3821 + pick(s.options.enableMouseTracking, true) && + (!chart.hoverPane || s.xAxis.pane === chart.hoverPane)); + }; + } +}); +addEvent(H.Pointer, 'afterGetHoverData', function (eventArgs) { + var chart = this.chart; + if (eventArgs.hoverPoint && + eventArgs.hoverPoint.plotX && + eventArgs.hoverPoint.plotY && + chart.hoverPane && + !isInsidePane(eventArgs.hoverPoint.plotX, eventArgs.hoverPoint.plotY, chart.hoverPane.center)) { + eventArgs.hoverPoint = void 0; + } +}); +H.Pane = Pane; +export default H.Pane; diff --git a/librerias/gantt/code/es-modules/parts-more/Polar.js b/librerias/gantt/code/es-modules/parts-more/Polar.js new file mode 100644 index 0000000..34e5e4f --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-more/Polar.js @@ -0,0 +1,723 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, animObject = U.animObject, defined = U.defined, find = U.find, isNumber = U.isNumber, pick = U.pick, splat = U.splat, uniqueKey = U.uniqueKey, wrap = U.wrap; +import Pane from '../parts-more/Pane.js'; +import '../parts/Pointer.js'; +import '../parts/Series.js'; +import '../parts/Pointer.js'; +// Extensions for polar charts. Additionally, much of the geometry required for +// polar charts is gathered in RadialAxes.js. +var Pointer = H.Pointer, Series = H.Series, seriesTypes = H.seriesTypes, seriesProto = Series.prototype, pointerProto = Pointer.prototype, colProto, arearangeProto; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * Search a k-d tree by the point angle, used for shared tooltips in polar + * charts + * @private + */ +seriesProto.searchPointByAngle = function (e) { + var series = this, chart = series.chart, xAxis = series.xAxis, center = xAxis.pane.center, plotX = e.chartX - center[0] - chart.plotLeft, plotY = e.chartY - center[1] - chart.plotTop; + return this.searchKDTree({ + clientX: 180 + (Math.atan2(plotX, plotY) * (-180 / Math.PI)) + }); +}; +/** + * #6212 Calculate connectors for spline series in polar chart. + * @private + * @param {boolean} calculateNeighbours + * Check if connectors should be calculated for neighbour points as + * well allows short recurence + */ +seriesProto.getConnectors = function (segment, index, calculateNeighbours, connectEnds) { + var i, prevPointInd, nextPointInd, previousPoint, nextPoint, previousX, previousY, nextX, nextY, plotX, plotY, ret, + // 1 means control points midway between points, 2 means 1/3 from + // the point, 3 is 1/4 etc; + smoothing = 1.5, denom = smoothing + 1, leftContX, leftContY, rightContX, rightContY, dLControlPoint, // distance left control point + dRControlPoint, leftContAngle, rightContAngle, jointAngle, addedNumber = connectEnds ? 1 : 0; + // Calculate final index of points depending on the initial index value. + // Because of calculating neighbours, index may be outisde segment + // array. + if (index >= 0 && index <= segment.length - 1) { + i = index; + } + else if (index < 0) { + i = segment.length - 1 + index; + } + else { + i = 0; + } + prevPointInd = (i - 1 < 0) ? segment.length - (1 + addedNumber) : i - 1; + nextPointInd = (i + 1 > segment.length - 1) ? addedNumber : i + 1; + previousPoint = segment[prevPointInd]; + nextPoint = segment[nextPointInd]; + previousX = previousPoint.plotX; + previousY = previousPoint.plotY; + nextX = nextPoint.plotX; + nextY = nextPoint.plotY; + plotX = segment[i].plotX; // actual point + plotY = segment[i].plotY; + leftContX = (smoothing * plotX + previousX) / denom; + leftContY = (smoothing * plotY + previousY) / denom; + rightContX = (smoothing * plotX + nextX) / denom; + rightContY = (smoothing * plotY + nextY) / denom; + dLControlPoint = Math.sqrt(Math.pow(leftContX - plotX, 2) + Math.pow(leftContY - plotY, 2)); + dRControlPoint = Math.sqrt(Math.pow(rightContX - plotX, 2) + Math.pow(rightContY - plotY, 2)); + leftContAngle = Math.atan2(leftContY - plotY, leftContX - plotX); + rightContAngle = Math.atan2(rightContY - plotY, rightContX - plotX); + jointAngle = (Math.PI / 2) + ((leftContAngle + rightContAngle) / 2); + // Ensure the right direction, jointAngle should be in the same quadrant + // as leftContAngle + if (Math.abs(leftContAngle - jointAngle) > Math.PI / 2) { + jointAngle -= Math.PI; + } + // Find the corrected control points for a spline straight through the + // point + leftContX = plotX + Math.cos(jointAngle) * dLControlPoint; + leftContY = plotY + Math.sin(jointAngle) * dLControlPoint; + rightContX = plotX + Math.cos(Math.PI + jointAngle) * dRControlPoint; + rightContY = plotY + Math.sin(Math.PI + jointAngle) * dRControlPoint; + // push current point's connectors into returned object + ret = { + rightContX: rightContX, + rightContY: rightContY, + leftContX: leftContX, + leftContY: leftContY, + plotX: plotX, + plotY: plotY + }; + // calculate connectors for previous and next point and push them inside + // returned object + if (calculateNeighbours) { + ret.prevPointCont = this.getConnectors(segment, prevPointInd, false, connectEnds); + } + return ret; +}; +/** + * Translate a point's plotX and plotY from the internal angle and radius + * measures to true plotX, plotY coordinates + * @private + */ +seriesProto.toXY = function (point) { + var xy, chart = this.chart, xAxis = this.xAxis, yAxis = this.yAxis, plotX = point.plotX, plotY = point.plotY, series = point.series, inverted = chart.inverted, pointY = point.y, radius = inverted ? plotX : yAxis.len - plotY, clientX; + // Corrected y position of inverted series other than column + if (inverted && series && !series.isRadialBar) { + point.plotY = plotY = + typeof pointY === 'number' ? (yAxis.translate(pointY) || 0) : 0; + } + // Save rectangular plotX, plotY for later computation + point.rectPlotX = plotX; + point.rectPlotY = plotY; + if (yAxis.center) { + radius += yAxis.center[3] / 2; + } + // Find the polar plotX and plotY + xy = inverted ? yAxis.postTranslate(plotY, radius) : + xAxis.postTranslate(plotX, radius); + point.plotX = point.polarPlotX = xy.x - chart.plotLeft; + point.plotY = point.polarPlotY = xy.y - chart.plotTop; + // If shared tooltip, record the angle in degrees in order to align X + // points. Otherwise, use a standard k-d tree to get the nearest point + // in two dimensions. + if (this.kdByAngle) { + clientX = ((plotX / Math.PI * 180) + + xAxis.pane.options.startAngle) % 360; + if (clientX < 0) { // #2665 + clientX += 360; + } + point.clientX = clientX; + } + else { + point.clientX = point.plotX; + } +}; +if (seriesTypes.spline) { + /** + * Overridden method for calculating a spline from one point to the next + * @private + */ + wrap(seriesTypes.spline.prototype, 'getPointSpline', function (proceed, segment, point, i) { + var ret, connectors; + if (this.chart.polar) { + // moveTo or lineTo + if (!i) { + ret = ['M', point.plotX, point.plotY]; + } + else { // curve from last point to this + connectors = this.getConnectors(segment, i, true, this.connectEnds); + ret = [ + 'C', + connectors.prevPointCont.rightContX, + connectors.prevPointCont.rightContY, + connectors.leftContX, + connectors.leftContY, + connectors.plotX, + connectors.plotY + ]; + } + } + else { + ret = proceed.call(this, segment, point, i); + } + return ret; + }); + // #6430 Areasplinerange series use unwrapped getPointSpline method, so + // we need to set this method again. + if (seriesTypes.areasplinerange) { + seriesTypes.areasplinerange.prototype.getPointSpline = + seriesTypes.spline.prototype.getPointSpline; + } +} +/** + * Extend translate. The plotX and plotY values are computed as if the polar + * chart were a cartesian plane, where plotX denotes the angle in radians + * and (yAxis.len - plotY) is the pixel distance from center. + * @private + */ +addEvent(Series, 'afterTranslate', function () { + var series = this; + var chart = series.chart; + if (chart.polar && series.xAxis) { + // Prepare k-d-tree handling. It searches by angle (clientX) in + // case of shared tooltip, and by two dimensional distance in case + // of non-shared. + series.kdByAngle = chart.tooltip && chart.tooltip.shared; + if (series.kdByAngle) { + series.searchPoint = series.searchPointByAngle; + } + else { + series.options.findNearestPointBy = 'xy'; + } + // Postprocess plot coordinates + if (!series.preventPostTranslate) { + var points = series.points; + var i = points.length; + while (i--) { + // Translate plotX, plotY from angle and radius to true plot + // coordinates + series.toXY(points[i]); + // Treat points below Y axis min as null (#10082) + if (!chart.hasParallelCoordinates && + !series.yAxis.reversed && + points[i].y < series.yAxis.min) { + points[i].isNull = true; + } + } + } + // Perform clip after render + if (!this.hasClipCircleSetter) { + this.hasClipCircleSetter = !!series.eventsToUnbind.push(addEvent(series, 'afterRender', function () { + var circ; + if (chart.polar) { + // For clipping purposes there is a need for + // coordinates from the absolute center + circ = this.yAxis.pane.center; + if (!this.clipCircle) { + this.clipCircle = chart.renderer.clipCircle(circ[0], circ[1], circ[2] / 2, circ[3] / 2); + } + else { + this.clipCircle.animate({ + x: circ[0], + y: circ[1], + r: circ[2] / 2, + innerR: circ[3] / 2 + }); + } + this.group.clip(this.clipCircle); + this.setClip = H.noop; + } + })); + } + } +}, { order: 2 }); // Run after translation of ||-coords +/** + * Extend getSegmentPath to allow connecting ends across 0 to provide a + * closed circle in line-like series. + * @private + */ +wrap(seriesProto, 'getGraphPath', function (proceed, points) { + var series = this, i, firstValid, popLastPoint; + // Connect the path + if (this.chart.polar) { + points = points || this.points; + // Append first valid point in order to connect the ends + for (i = 0; i < points.length; i++) { + if (!points[i].isNull) { + firstValid = i; + break; + } + } + /** + * Polar charts only. Whether to connect the ends of a line series + * plot across the extremes. + * + * @sample {highcharts} highcharts/plotoptions/line-connectends-false/ + * Do not connect + * + * @type {boolean} + * @since 2.3.0 + * @product highcharts + * @apioption plotOptions.series.connectEnds + */ + if (this.options.connectEnds !== false && + typeof firstValid !== 'undefined') { + this.connectEnds = true; // re-used in splines + points.splice(points.length, 0, points[firstValid]); + popLastPoint = true; + } + // For area charts, pseudo points are added to the graph, now we + // need to translate these + points.forEach(function (point) { + if (typeof point.polarPlotY === 'undefined') { + series.toXY(point); + } + }); + } + // Run uber method + var ret = proceed.apply(this, [].slice.call(arguments, 1)); + // #6212 points.splice method is adding points to an array. In case of + // areaspline getGraphPath method is used two times and in both times + // points are added to an array. That is why points.pop is used, to get + // unmodified points. + if (popLastPoint) { + points.pop(); + } + return ret; +}); +var polarAnimate = function (proceed, init) { + var series = this, chart = this.chart, animation = this.options.animation, group = this.group, markerGroup = this.markerGroup, center = this.xAxis.center, plotLeft = chart.plotLeft, plotTop = chart.plotTop, attribs, paneInnerR, graphic, shapeArgs, r, innerR; + // Specific animation for polar charts + if (chart.polar) { + if (series.isRadialBar) { + if (!init) { + // Run the pie animation for radial bars + series.startAngleRad = pick(series.translatedThreshold, series.xAxis.startAngleRad); + H.seriesTypes.pie.prototype.animate.call(series, init); + } + } + else { + // Enable animation on polar charts only in SVG. In VML, the scaling + // is different, plus animation would be so slow it would't matter. + if (chart.renderer.isSVG) { + animation = animObject(animation); + // A different animation needed for column like series + if (series.is('column')) { + if (!init) { + paneInnerR = center[3] / 2; + series.points.forEach(function (point) { + graphic = point.graphic; + shapeArgs = point.shapeArgs; + r = shapeArgs && shapeArgs.r; + innerR = shapeArgs && shapeArgs.innerR; + if (graphic && shapeArgs) { + // start values + graphic.attr({ + r: paneInnerR, + innerR: paneInnerR + }); + // animate + graphic.animate({ + r: r, + innerR: innerR + }, series.options.animation); + } + }); + } + } + else { + // Initialize the animation + if (init) { + // Scale down the group and place it in the center + attribs = { + translateX: center[0] + plotLeft, + translateY: center[1] + plotTop, + scaleX: 0.001, + scaleY: 0.001 + }; + group.attr(attribs); + if (markerGroup) { + markerGroup.attr(attribs); + } + // Run the animation + } + else { + attribs = { + translateX: plotLeft, + translateY: plotTop, + scaleX: 1, + scaleY: 1 + }; + group.animate(attribs, animation); + if (markerGroup) { + markerGroup.animate(attribs, animation); + } + } + } + } + } + // For non-polar charts, revert to the basic animation + } + else { + proceed.call(this, init); + } +}; +// Define the animate method for regular series +wrap(seriesProto, 'animate', polarAnimate); +if (seriesTypes.column) { + arearangeProto = seriesTypes.arearange.prototype; + colProto = seriesTypes.column.prototype; + colProto.polarArc = function (low, high, start, end) { + var center = this.xAxis.center, len = this.yAxis.len, paneInnerR = center[3] / 2, r = len - high + paneInnerR, innerR = len - pick(low, len) + paneInnerR; + // Prevent columns from shooting through the pane's center + if (this.yAxis.reversed) { + if (r < 0) { + r = paneInnerR; + } + if (innerR < 0) { + innerR = paneInnerR; + } + } + // Return a new shapeArgs + return { + x: center[0], + y: center[1], + r: r, + innerR: innerR, + start: start, + end: end + }; + }; + /** + * Define the animate method for columnseries + * @private + */ + wrap(colProto, 'animate', polarAnimate); + /** + * Extend the column prototype's translate method + * @private + */ + wrap(colProto, 'translate', function (proceed) { + var series = this, options = series.options, threshold = options.threshold, stacking = options.stacking, chart = series.chart, xAxis = series.xAxis, yAxis = series.yAxis, reversed = yAxis.reversed, center = yAxis.center, startAngleRad = xAxis.startAngleRad, endAngleRad = xAxis.endAngleRad, visibleRange = endAngleRad - startAngleRad, thresholdAngleRad, points, point, i, yMin, yMax, start, end, tooltipPos, pointX, pointY, stackValues, stack, barX, innerR, r; + series.preventPostTranslate = true; + // Run uber method + proceed.call(series); + // Postprocess plot coordinates + if (xAxis.isRadial) { + points = series.points; + i = points.length; + yMin = yAxis.translate(yAxis.min); + yMax = yAxis.translate(yAxis.max); + threshold = options.threshold || 0; + if (chart.inverted) { + // Finding a correct threshold + if (isNumber(threshold)) { + thresholdAngleRad = yAxis.translate(threshold); + // Checks if threshold is outside the visible range + if (defined(thresholdAngleRad)) { + if (thresholdAngleRad < 0) { + thresholdAngleRad = 0; + } + else if (thresholdAngleRad > visibleRange) { + thresholdAngleRad = visibleRange; + } + // Adding start angle offset + series.translatedThreshold = + thresholdAngleRad + startAngleRad; + } + } + } + while (i--) { + point = points[i]; + barX = point.barX; + pointX = point.x; + pointY = point.y; + point.shapeType = 'arc'; + if (chart.inverted) { + point.plotY = yAxis.translate(pointY); + if (stacking && yAxis.stacking) { + stack = yAxis.stacking.stacks[(pointY < 0 ? '-' : '') + + series.stackKey]; + if (series.visible && stack && stack[pointX]) { + if (!point.isNull) { + stackValues = stack[pointX].points[series.getStackIndicator(void 0, pointX, series.index).key]; + // Translating to radial values + start = yAxis.translate(stackValues[0]); + end = yAxis.translate(stackValues[1]); + // If starting point is beyond the + // range, set it to 0 + if (defined(start)) { + start = U.clamp(start, 0, visibleRange); + } + } + } + } + else { + // Initial start and end angles for radial bar + start = thresholdAngleRad; + end = point.plotY; + } + if (start > end) { + // Swapping start and end + end = [start, start = end][0]; + } + // Prevent from rendering point outside the + // acceptable circular range + if (!reversed) { + if (start < yMin) { + start = yMin; + } + else if (end > yMax) { + end = yMax; + } + else if (end < yMin || start > yMax) { + start = end = 0; + } + } + else { + if (end > yMin) { + end = yMin; + } + else if (start < yMax) { + start = yMax; + } + else if (start > yMin || end < yMax) { + start = end = visibleRange; + } + } + if (yAxis.min > yAxis.max) { + start = end = reversed ? visibleRange : 0; + } + start += startAngleRad; + end += startAngleRad; + if (center) { + point.barX = barX += center[3] / 2; + } + // In case when radius, inner radius or both are + // negative, a point is rendered but partially or as + // a center point + innerR = Math.max(barX, 0); + r = Math.max(barX + point.pointWidth, 0); + point.shapeArgs = { + x: center && center[0], + y: center && center[1], + r: r, + innerR: innerR, + start: start, + end: end + }; + // Fade out the points if not inside the polar "plot area" + point.opacity = start === end ? 0 : void 0; + // A correct value for stacked or not fully visible + // point + point.plotY = (defined(series.translatedThreshold) && + (start < series.translatedThreshold ? start : end)) - + startAngleRad; + } + else { + start = barX + startAngleRad; + // Changed the way polar columns are drawn in order to make + // it more consistent with the drawing of inverted columns + // (they are using the same function now). Also, it was + // essential to make the animation work correctly (the + // scaling of the group) is replaced by animating each + // element separately. + point.shapeArgs = series.polarArc(point.yBottom, point.plotY, start, start + point.pointWidth); + } + // Provided a correct coordinates for the tooltip + series.toXY(point); + if (chart.inverted) { + tooltipPos = yAxis.postTranslate(point.rectPlotY, barX + point.pointWidth / 2); + point.tooltipPos = [ + tooltipPos.x - chart.plotLeft, + tooltipPos.y - chart.plotTop + ]; + } + else { + point.tooltipPos = [point.plotX, point.plotY]; + } + if (center) { + point.ttBelow = point.plotY > center[1]; + } + } + } + }); + /** + * Find correct align and vertical align based on an angle in polar chart + * @private + */ + colProto.findAlignments = function (angle, options) { + var align, verticalAlign; + if (options.align === null) { + if (angle > 20 && angle < 160) { + align = 'left'; // right hemisphere + } + else if (angle > 200 && angle < 340) { + align = 'right'; // left hemisphere + } + else { + align = 'center'; // top or bottom + } + options.align = align; + } + if (options.verticalAlign === null) { + if (angle < 45 || angle > 315) { + verticalAlign = 'bottom'; // top part + } + else if (angle > 135 && angle < 225) { + verticalAlign = 'top'; // bottom part + } + else { + verticalAlign = 'middle'; // left or right + } + options.verticalAlign = verticalAlign; + } + return options; + }; + if (arearangeProto) { + arearangeProto.findAlignments = colProto.findAlignments; + } + /** + * Align column data labels outside the columns. #1199. + * @private + */ + wrap(colProto, 'alignDataLabel', function (proceed, point, dataLabel, options, alignTo, isNew) { + var chart = this.chart, inside = pick(options.inside, !!this.options.stacking), angle, shapeArgs, labelPos; + if (chart.polar) { + angle = point.rectPlotX / Math.PI * 180; + if (!chart.inverted) { + // Align nicely outside the perimeter of the columns + if (this.findAlignments) { + options = this.findAlignments(angle, options); + } + } + else { // Required corrections for data labels of inverted bars + // The plotX and plotY are correctly set therefore they + // don't need to be swapped (inverted argument is false) + this.forceDL = chart.isInsidePlot(point.plotX, Math.round(point.plotY), false); + // Checks if labels should be positioned inside + if (inside && point.shapeArgs) { + shapeArgs = point.shapeArgs; + // Calculates pixel positions for a data label to be + // inside + labelPos = + this.yAxis.postTranslate( + // angle + (shapeArgs.start + shapeArgs.end) / 2 - + this + .xAxis.startAngleRad, + // radius + point.barX + + point.pointWidth / 2); + alignTo = { + x: labelPos.x - chart.plotLeft, + y: labelPos.y - chart.plotTop + }; + } + else if (point.tooltipPos) { + alignTo = { + x: point.tooltipPos[0], + y: point.tooltipPos[1] + }; + } + options.align = pick(options.align, 'center'); + options.verticalAlign = + pick(options.verticalAlign, 'middle'); + } + seriesProto.alignDataLabel.call(this, point, dataLabel, options, alignTo, isNew); + // Hide label of a point (only inverted) that is outside the + // visible y range + if (this.isRadialBar && point.shapeArgs && + point.shapeArgs.start === point.shapeArgs.end) { + dataLabel.hide(true); + } + } + else { + proceed.call(this, point, dataLabel, options, alignTo, isNew); + } + }); +} +/** + * Extend getCoordinates to prepare for polar axis values + * @private + */ +wrap(pointerProto, 'getCoordinates', function (proceed, e) { + var chart = this.chart, ret = { + xAxis: [], + yAxis: [] + }; + if (chart.polar) { + chart.axes.forEach(function (axis) { + var isXAxis = axis.isXAxis, center = axis.center, x, y; + // Skip colorAxis + if (axis.coll === 'colorAxis') { + return; + } + x = e.chartX - center[0] - chart.plotLeft; + y = e.chartY - center[1] - chart.plotTop; + ret[isXAxis ? 'xAxis' : 'yAxis'].push({ + axis: axis, + value: axis.translate(isXAxis ? + Math.PI - Math.atan2(x, y) : // angle + // distance from center + Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)), true) + }); + }); + } + else { + ret = proceed.call(this, e); + } + return ret; +}); +H.SVGRenderer.prototype.clipCircle = function (x, y, r, innerR) { + var wrapper, id = uniqueKey(), clipPath = this.createElement('clipPath').attr({ + id: id + }).add(this.defs); + wrapper = innerR ? + this.arc(x, y, r, innerR, 0, 2 * Math.PI).add(clipPath) : + this.circle(x, y, r).add(clipPath); + wrapper.id = id; + wrapper.clipPath = clipPath; + return wrapper; +}; +addEvent(H.Chart, 'getAxes', function () { + if (!this.pane) { + this.pane = []; + } + splat(this.options.pane).forEach(function (paneOptions) { + new Pane(// eslint-disable-line no-new + paneOptions, this); + }, this); +}); +addEvent(H.Chart, 'afterDrawChartBox', function () { + this.pane.forEach(function (pane) { + pane.render(); + }); +}); +addEvent(H.Series, 'afterInit', function () { + var chart = this.chart; + // Add flags that identifies radial inverted series + if (chart.inverted && chart.polar) { + this.isRadialSeries = true; + if (this.is('column')) { + this.isRadialBar = true; + } + } +}); +/** + * Extend chart.get to also search in panes. Used internally in + * responsiveness and chart.update. + * @private + */ +wrap(H.Chart.prototype, 'get', function (proceed, id) { + return find(this.pane, function (pane) { + return pane.options.id === id; + }) || proceed.call(this, id); +}); diff --git a/librerias/gantt/code/es-modules/parts-more/PolygonSeries.js b/librerias/gantt/code/es-modules/parts-more/PolygonSeries.js new file mode 100644 index 0000000..0199ff2 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-more/PolygonSeries.js @@ -0,0 +1,144 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import LegendSymbolMixin from '../mixins/legend-symbol.js'; +import U from '../parts/Utilities.js'; +var seriesType = U.seriesType; +import '../parts/Options.js'; +import '../parts/Series.js'; +import '../parts/Legend.js'; +import '../parts/ScatterSeries.js'; +var noop = H.noop, Series = H.Series, seriesTypes = H.seriesTypes; +/** + * A polygon series can be used to draw any freeform shape in the cartesian + * coordinate system. A fill is applied with the `color` option, and + * stroke is applied through `lineWidth` and `lineColor` options. + * + * @sample {highcharts} highcharts/demo/polygon/ + * Polygon + * @sample {highstock} highcharts/demo/polygon/ + * Polygon + * + * @extends plotOptions.scatter + * @since 4.1.0 + * @excluding jitter, softThreshold, threshold, cluster + * @product highcharts highstock + * @requires highcharts-more + * @optionparent plotOptions.polygon + */ +seriesType('polygon', 'scatter', { + marker: { + enabled: false, + states: { + hover: { + enabled: false + } + } + }, + stickyTracking: false, + tooltip: { + followPointer: true, + pointFormat: '' + }, + trackByArea: true + // Prototype members +}, { + type: 'polygon', + getGraphPath: function () { + var graphPath = Series.prototype.getGraphPath.call(this), i = graphPath.length + 1; + // Close all segments + while (i--) { + if ((i === graphPath.length || graphPath[i][0] === 'M') && i > 0) { + graphPath.splice(i, 0, ['Z']); + } + } + this.areaPath = graphPath; + return graphPath; + }, + drawGraph: function () { + // Hack into the fill logic in area.drawGraph + this.options.fillColor = this.color; + seriesTypes.area.prototype.drawGraph.call(this); + }, + drawLegendSymbol: LegendSymbolMixin.drawRectangle, + drawTracker: Series.prototype.drawTracker, + setStackedPoints: noop // No stacking points on polygons (#5310) +}); +/** + * A `polygon` series. If the [type](#series.polygon.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.polygon + * @excluding dataParser, dataURL, stack + * @product highcharts highstock + * @requires highcharts-more + * @apioption series.polygon + */ +/** + * An array of data points for the series. For the `polygon` series + * type, points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 10], + * [1, 3], + * [2, 1] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.polygon.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 1, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 8, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @product highcharts highstock + * @apioption series.polygon.data + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/parts-more/RadialAxis.js b/librerias/gantt/code/es-modules/parts-more/RadialAxis.js new file mode 100644 index 0000000..18735d8 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-more/RadialAxis.js @@ -0,0 +1,856 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Axis from '../parts/Axis.js'; +import Tick from '../parts/Tick.js'; +import HiddenAxis from './HiddenAxis.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, correctFloat = U.correctFloat, defined = U.defined, extend = U.extend, fireEvent = U.fireEvent, merge = U.merge, pick = U.pick, pInt = U.pInt, relativeLength = U.relativeLength, wrap = U.wrap; +/** + * @private + * @class + */ +var RadialAxis = /** @class */ (function () { + function RadialAxis() { + } + /* * + * + * Static Functions + * + * */ + RadialAxis.init = function (axis) { + var axisProto = Axis.prototype; + // Merge and set options. + axis.setOptions = function (userOptions) { + var options = this.options = merge(axis.constructor.defaultOptions, this.defaultPolarOptions, userOptions); + // Make sure the plotBands array is instanciated for each Axis + // (#2649) + if (!options.plotBands) { + options.plotBands = []; + } + fireEvent(this, 'afterSetOptions'); + }; + // Wrap the getOffset method to return zero offset for title or labels + // in a radial axis. + axis.getOffset = function () { + // Call the Axis prototype method (the method we're in now is on the + // instance) + axisProto.getOffset.call(this); + // Title or label offsets are not counted + this.chart.axisOffset[this.side] = 0; + }; + /** + * Get the path for the axis line. This method is also referenced in the + * getPlotLinePath method. + * + * @private + * + * @param {number} _lineWidth + * Line width is not used. + * + * @param {number} [radius] + * Radius of radial path. + * + * @param {number} [innerRadius] + * Inner radius of radial path. + * + * @return {RadialAxisPath} + */ + axis.getLinePath = function (_lineWidth, radius, innerRadius) { + var center = this.pane.center, end, chart = this.chart, r = pick(radius, center[2] / 2 - this.offset), path; + if (typeof innerRadius === 'undefined') { + innerRadius = this.horiz ? 0 : this.center && -this.center[3] / 2; + } + // In case when innerSize of pane is set, it must be included + if (innerRadius) { + r += innerRadius; + } + if (this.isCircular || typeof radius !== 'undefined') { + path = this.chart.renderer.symbols.arc(this.left + center[0], this.top + center[1], r, r, { + start: this.startAngleRad, + end: this.endAngleRad, + open: true, + innerR: 0 + }); + // Bounds used to position the plotLine label next to the line + // (#7117) + path.xBounds = [this.left + center[0]]; + path.yBounds = [this.top + center[1] - r]; + } + else { + end = this.postTranslate(this.angleRad, r); + path = [ + ['M', this.center[0] + chart.plotLeft, this.center[1] + chart.plotTop], + ['L', end.x, end.y] + ]; + } + return path; + }; + /** + * Override setAxisTranslation by setting the translation to the + * difference in rotation. This allows the translate method to return + * angle for any given value. + * + * @private + */ + axis.setAxisTranslation = function () { + // Call uber method + axisProto.setAxisTranslation.call(this); + // Set transA and minPixelPadding + if (this.center) { // it's not defined the first time + if (this.isCircular) { + this.transA = (this.endAngleRad - this.startAngleRad) / + ((this.max - this.min) || 1); + } + else { + // The transA here is the length of the axis, so in case + // of inner radius, the length must be decreased by it + this.transA = ((this.center[2] - this.center[3]) / 2) / + ((this.max - this.min) || 1); + } + if (this.isXAxis) { + this.minPixelPadding = this.transA * this.minPointOffset; + } + else { + // This is a workaround for regression #2593, but categories + // still don't position correctly. + this.minPixelPadding = 0; + } + } + }; + /** + * In case of auto connect, add one closestPointRange to the max value + * right before tickPositions are computed, so that ticks will extend + * passed the real max. + * @private + */ + axis.beforeSetTickPositions = function () { + // If autoConnect is true, polygonal grid lines are connected, and + // one closestPointRange is added to the X axis to prevent the last + // point from overlapping the first. + this.autoConnect = (this.isCircular && + typeof pick(this.userMax, this.options.max) === 'undefined' && + correctFloat(this.endAngleRad - this.startAngleRad) === + correctFloat(2 * Math.PI)); + // This will lead to add an extra tick to xAxis in order to display + // a correct range on inverted polar + if (!this.isCircular && this.chart.inverted) { + this.max++; + } + if (this.autoConnect) { + this.max += ((this.categories && 1) || + this.pointRange || + this.closestPointRange || + 0); // #1197, #2260 + } + }; + /** + * Override the setAxisSize method to use the arc's circumference as + * length. This allows tickPixelInterval to apply to pixel lengths along + * the perimeter. + * @private + */ + axis.setAxisSize = function () { + var center, start; + axisProto.setAxisSize.call(this); + if (this.isRadial) { + // Set the center array + this.pane.updateCenter(this); + // In case when the innerSize is set in a polar chart, the axis' + // center cannot be a reference to pane's center + center = this.center = extend([], this.pane.center); + // The sector is used in Axis.translate to compute the + // translation of reversed axis points (#2570) + if (this.isCircular) { + this.sector = this.endAngleRad - this.startAngleRad; + } + else { + // When the pane's startAngle or the axis' angle is set then + // new x and y values for vertical axis' center must be + // calulated + start = this.postTranslate(this.angleRad, center[3] / 2); + center[0] = start.x - this.chart.plotLeft; + center[1] = start.y - this.chart.plotTop; + } + // Axis len is used to lay out the ticks + this.len = this.width = this.height = + (center[2] - center[3]) * pick(this.sector, 1) / 2; + } + }; + /** + * Returns the x, y coordinate of a point given by a value and a pixel + * distance from center. + * + * @private + * + * @param {number} value + * Point value. + * + * @param {number} [length] + * Distance from center. + * + * @return {Highcharts.PositionObject} + */ + axis.getPosition = function (value, length) { + var translatedVal = this.translate(value); + return this.postTranslate(this.isCircular ? translatedVal : this.angleRad, // #2848 + // In case when translatedVal is negative, the 0 value must be + // used instead, in order to deal with lines and labels that + // fall out of the visible range near the center of a pane + pick(this.isCircular ? + length : + (translatedVal < 0 ? 0 : translatedVal), this.center[2] / 2) - this.offset); + }; + /** + * Translate from intermediate plotX (angle), plotY (axis.len - radius) + * to final chart coordinates. + * + * @private + * + * @param {number} angle + * Translation angle. + * + * @param {number} radius + * Translation radius. + * + * @return {Highcharts.PositionObject} + */ + axis.postTranslate = function (angle, radius) { + var chart = this.chart, center = this.center; + angle = this.startAngleRad + angle; + return { + x: chart.plotLeft + center[0] + Math.cos(angle) * radius, + y: chart.plotTop + center[1] + Math.sin(angle) * radius + }; + }; + /** + * Find the path for plot bands along the radial axis. + * + * @private + * + * @param {number} from + * From value. + * + * @param {number} to + * To value. + * + * @param {Highcharts.AxisPlotBandsOptions} options + * Band options. + * + * @return {RadialAxisPath} + */ + axis.getPlotBandPath = function (from, to, options) { + var center = this.center, startAngleRad = this.startAngleRad, fullRadius = center[2] / 2, radii = [ + pick(options.outerRadius, '100%'), + options.innerRadius, + pick(options.thickness, 10) + ], offset = Math.min(this.offset, 0), percentRegex = /%$/, start, end, angle, xOnPerimeter, open, isCircular = this.isCircular, // X axis in a polar chart + path; + // Polygonal plot bands + if (this.options.gridLineInterpolation === 'polygon') { + path = this.getPlotLinePath({ value: from }).concat(this.getPlotLinePath({ value: to, reverse: true })); + // Circular grid bands + } + else { + // Keep within bounds + from = Math.max(from, this.min); + to = Math.min(to, this.max); + // Plot bands on Y axis (radial axis) - inner and outer radius + // depend on to and from + if (!isCircular) { + radii[0] = this.translate(from); + radii[1] = this.translate(to); + } + // Convert percentages to pixel values + radii = radii.map(function (radius) { + if (percentRegex.test(radius)) { + radius = (pInt(radius, 10) * fullRadius) / 100; + } + return radius; + }); + // Handle full circle + if (options.shape === 'circle' || !isCircular) { + start = -Math.PI / 2; + end = Math.PI * 1.5; + open = true; + } + else { + start = startAngleRad + this.translate(from); + end = startAngleRad + this.translate(to); + } + radii[0] -= offset; // #5283 + radii[2] -= offset; // #5283 + path = this.chart.renderer.symbols.arc(this.left + center[0], this.top + center[1], radii[0], radii[0], { + // Math is for reversed yAxis (#3606) + start: Math.min(start, end), + end: Math.max(start, end), + innerR: pick(radii[1], radii[0] - radii[2]), + open: open + }); + // Provide positioning boxes for the label (#6406) + if (isCircular) { + angle = (end + start) / 2; + xOnPerimeter = (this.left + + center[0] + + (center[2] / 2) * Math.cos(angle)); + path.xBounds = angle > -Math.PI / 2 && angle < Math.PI / 2 ? + // Right hemisphere + [xOnPerimeter, this.chart.plotWidth] : + // Left hemisphere + [0, xOnPerimeter]; + path.yBounds = [ + this.top + center[1] + (center[2] / 2) * Math.sin(angle) + ]; + // Shift up or down to get the label clear of the perimeter + path.yBounds[0] += ((angle > -Math.PI && angle < 0) || + (angle > Math.PI)) ? -10 : 10; + } + } + return path; + }; + // Find the correct end values of crosshair in polar. + axis.getCrosshairPosition = function (options, x1, y1) { + var axis = this, value = options.value, center = axis.pane.center, shapeArgs, end, x2, y2; + if (axis.isCircular) { + if (!defined(value)) { + // When the snap is set to false + x2 = options.chartX || 0; + y2 = options.chartY || 0; + value = axis.translate(Math.atan2(y2 - y1, x2 - x1) - axis.startAngleRad, true); + } + else if (options.point) { + // When the snap is set to true + shapeArgs = options.point.shapeArgs || {}; + if (shapeArgs.start) { + // Find a true value of the point based on the + // angle + value = axis.chart.inverted ? + axis.translate(options.point.rectPlotY, true) : + options.point.x; + } + } + end = axis.getPosition(value); + x2 = end.x; + y2 = end.y; + } + else { + if (!defined(value)) { + x2 = options.chartX; + y2 = options.chartY; + } + if (defined(x2) && defined(y2)) { + // Calculate radius of non-circular axis' crosshair + y1 = center[1] + axis.chart.plotTop; + value = axis.translate(Math.min(Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)), center[2] / 2) - center[3] / 2, true); + } + } + return [value, x2 || 0, y2 || 0]; + }; + // Find the path for plot lines perpendicular to the radial axis. + axis.getPlotLinePath = function (options) { + var axis = this, center = axis.pane.center, chart = axis.chart, inverted = chart.inverted, value = options.value, reverse = options.reverse, end = axis.getPosition(value), background = axis.pane.options.background ? + (axis.pane.options.background[0] || + axis.pane.options.background) : + {}, innerRadius = background.innerRadius || '0%', outerRadius = background.outerRadius || '100%', x1 = center[0] + chart.plotLeft, y1 = center[1] + chart.plotTop, x2 = end.x, y2 = end.y, height = axis.height, isCrosshair = options.isCrosshair, paneInnerR = center[3] / 2, innerRatio, distance, a, b, otherAxis, xy, tickPositions, crossPos, path; + // Crosshair logic + if (isCrosshair) { + // Find crosshair's position and perform destructuring + // assignment + crossPos = this.getCrosshairPosition(options, x1, y1); + value = crossPos[0]; + x2 = crossPos[1]; + y2 = crossPos[2]; + } + // Spokes + if (axis.isCircular) { + distance = + Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); + a = (typeof innerRadius === 'string') ? + relativeLength(innerRadius, 1) : (innerRadius / distance); + b = (typeof outerRadius === 'string') ? + relativeLength(outerRadius, 1) : (outerRadius / distance); + // To ensure that gridlines won't be displayed in area + // defined by innerSize in case of custom radiuses of pane's + // background + if (center && paneInnerR) { + innerRatio = paneInnerR / distance; + if (a < innerRatio) { + a = innerRatio; + } + if (b < innerRatio) { + b = innerRatio; + } + } + path = [ + ['M', x1 + a * (x2 - x1), y1 - a * (y1 - y2)], + ['L', x2 - (1 - b) * (x2 - x1), y2 + (1 - b) * (y1 - y2)] + ]; + // Concentric circles + } + else { + // Pick the right values depending if it is grid line or + // crosshair + value = axis.translate(value); + // This is required in case when xAxis is non-circular to + // prevent grid lines (or crosshairs, if enabled) from + // rendering above the center after they supposed to be + // displayed below the center point + if (value) { + if (value < 0 || value > height) { + value = 0; + } + } + if (axis.options.gridLineInterpolation === 'circle') { + // A value of 0 is in the center, so it won't be + // visible, but draw it anyway for update and animation + // (#2366) + path = axis.getLinePath(0, value, paneInnerR); + // Concentric polygons + } + else { + path = []; + // Find the other axis (a circular one) in the same pane + chart[inverted ? 'yAxis' : 'xAxis'].forEach(function (a) { + if (a.pane === axis.pane) { + otherAxis = a; + } + }); + if (otherAxis) { + tickPositions = otherAxis.tickPositions; + if (otherAxis.autoConnect) { + tickPositions = + tickPositions.concat([tickPositions[0]]); + } + // Reverse the positions for concatenation of polygonal + // plot bands + if (reverse) { + tickPositions = tickPositions.slice().reverse(); + } + if (value) { + value += paneInnerR; + } + for (var i = 0; i < tickPositions.length; i++) { + xy = otherAxis.getPosition(tickPositions[i], value); + path.push(i ? ['L', xy.x, xy.y] : ['M', xy.x, xy.y]); + } + } + } + } + return path; + }; + // Find the position for the axis title, by default inside the gauge. + axis.getTitlePosition = function () { + var center = this.center, chart = this.chart, titleOptions = this.options.title; + return { + x: chart.plotLeft + center[0] + (titleOptions.x || 0), + y: (chart.plotTop + + center[1] - + ({ + high: 0.5, + middle: 0.25, + low: 0 + }[titleOptions.align] * + center[2]) + + (titleOptions.y || 0)) + }; + }; + /** + * Attach and return collecting function for labels in radial axis for + * anti-collision. + * + * @private + * + * @return {Highcharts.ChartLabelCollectorFunction} + */ + axis.createLabelCollector = function () { + var axis = this; + return function () { + if (axis.isRadial && + axis.tickPositions && + // undocumented option for now, but working + axis.options.labels.allowOverlap !== true) { + return axis.tickPositions + .map(function (pos) { + return axis.ticks[pos] && axis.ticks[pos].label; + }) + .filter(function (label) { + return Boolean(label); + }); + } + }; + }; + }; + /** + * Augments methods for the value axis. + * + * @private + * + * @param {Highcharts.Axis} AxisClass + * Axis class to extend. + * + * @param {Highcharts.Tick} TickClass + * Tick class to use. + */ + RadialAxis.compose = function (AxisClass, TickClass) { + /* eslint-disable no-invalid-this */ + // Actions before axis init. + addEvent(AxisClass, 'init', function (e) { + var axis = this; + var chart = axis.chart; + var inverted = chart.inverted, angular = chart.angular, polar = chart.polar, isX = axis.isXAxis, coll = axis.coll, isHidden = angular && isX, isCircular, chartOptions = chart.options, paneIndex = e.userOptions.pane || 0, pane = this.pane = + chart.pane && chart.pane[paneIndex]; + // Prevent changes for colorAxis + if (coll === 'colorAxis') { + this.isRadial = false; + return; + } + // Before prototype.init + if (angular) { + if (isHidden) { + HiddenAxis.init(axis); + } + else { + RadialAxis.init(axis); + } + isCircular = !isX; + if (isCircular) { + axis.defaultPolarOptions = RadialAxis.defaultRadialGaugeOptions; + } + } + else if (polar) { + RadialAxis.init(axis); + // Check which axis is circular + isCircular = axis.horiz; + axis.defaultPolarOptions = isCircular ? + RadialAxis.defaultCircularOptions : + merge(coll === 'xAxis' ? + AxisClass.defaultOptions : + AxisClass.defaultYAxisOptions, RadialAxis.defaultRadialOptions); + // Apply the stack labels for yAxis in case of inverted chart + if (inverted && coll === 'yAxis') { + axis.defaultPolarOptions.stackLabels = AxisClass.defaultYAxisOptions.stackLabels; + } + } + // Disable certain features on angular and polar axes + if (angular || polar) { + axis.isRadial = true; + chartOptions.chart.zoomType = null; + if (!axis.labelCollector) { + axis.labelCollector = axis.createLabelCollector(); + } + if (axis.labelCollector) { + // Prevent overlapping axis labels (#9761) + chart.labelCollectors.push(axis.labelCollector); + } + } + else { + this.isRadial = false; + } + // A pointer back to this axis to borrow geometry + if (pane && isCircular) { + pane.axis = axis; + } + axis.isCircular = isCircular; + }); + addEvent(AxisClass, 'afterInit', function () { + var axis = this; + var chart = axis.chart, options = axis.options, isHidden = chart.angular && axis.isXAxis, pane = axis.pane, paneOptions = pane && pane.options; + if (!isHidden && pane && (chart.angular || chart.polar)) { + // Start and end angle options are given in degrees relative to + // top, while internal computations are in radians relative to + // right (like SVG). + // Y axis in polar charts + axis.angleRad = (options.angle || 0) * Math.PI / 180; + // Gauges + axis.startAngleRad = + (paneOptions.startAngle - 90) * Math.PI / 180; + axis.endAngleRad = (pick(paneOptions.endAngle, paneOptions.startAngle + 360) - 90) * Math.PI / 180; // Gauges + axis.offset = options.offset || 0; + } + }); + // Wrap auto label align to avoid setting axis-wide rotation on radial + // axes. (#4920) + addEvent(AxisClass, 'autoLabelAlign', function (e) { + if (this.isRadial) { + e.align = void 0; + e.preventDefault(); + } + }); + // Remove label collector function on axis remove/update + addEvent(AxisClass, 'destroy', function () { + var axis = this; + if (axis.chart && + axis.chart.labelCollectors) { + var index = (axis.labelCollector ? + axis.chart.labelCollectors.indexOf(axis.labelCollector) : + -1); + if (index >= 0) { + axis.chart.labelCollectors.splice(index, 1); + } + } + }); + // Add special cases within the Tick class' methods for radial axes. + addEvent(TickClass, 'afterGetPosition', function (e) { + var tick = this; + if (tick.axis.getPosition) { + extend(e.pos, tick.axis.getPosition(this.pos)); + } + }); + // Find the center position of the label based on the distance option. + addEvent(TickClass, 'afterGetLabelPosition', function (e) { + var tick = this; + var axis = tick.axis; + var label = tick.label; + if (!label) { + return; + } + var labelBBox = label.getBBox(), labelOptions = axis.options.labels, optionsY = labelOptions.y, ret, centerSlot = 20, // 20 degrees to each side at the top and bottom + align = labelOptions.align, angle = ((axis.translate(this.pos) + axis.startAngleRad + + Math.PI / 2) / Math.PI * 180) % 360, correctAngle = Math.round(angle), labelDir = 'end', // Direction of the label 'start' or 'end' + reducedAngle1 = correctAngle < 0 ? + correctAngle + 360 : correctAngle, reducedAngle2 = reducedAngle1, translateY = 0, translateX = 0, labelYPosCorrection = labelOptions.y === null ? -labelBBox.height * 0.3 : 0; + if (axis.isRadial) { // Both X and Y axes in a polar chart + ret = axis.getPosition(this.pos, (axis.center[2] / 2) + + relativeLength(pick(labelOptions.distance, -25), axis.center[2] / 2, -axis.center[2] / 2)); + // Automatically rotated + if (labelOptions.rotation === 'auto') { + label.attr({ + rotation: angle + }); + // Vertically centered + } + else if (optionsY === null) { + optionsY = (axis.chart.renderer + .fontMetrics(label.styles && label.styles.fontSize).b - + labelBBox.height / 2); + } + // Automatic alignment + if (align === null) { + if (axis.isCircular) { // Y axis + if (labelBBox.width > + axis.len * axis.tickInterval / (axis.max - axis.min)) { // #3506 + centerSlot = 0; + } + if (angle > centerSlot && angle < 180 - centerSlot) { + align = 'left'; // right hemisphere + } + else if (angle > 180 + centerSlot && + angle < 360 - centerSlot) { + align = 'right'; // left hemisphere + } + else { + align = 'center'; // top or bottom + } + } + else { + align = 'center'; + } + label.attr({ + align: align + }); + } + // Auto alignment for solid-gauges with two labels (#10635) + if (align === 'auto' && + axis.tickPositions.length === 2 && + axis.isCircular) { + // Angles reduced to 0 - 90 or 180 - 270 + if (reducedAngle1 > 90 && reducedAngle1 < 180) { + reducedAngle1 = 180 - reducedAngle1; + } + else if (reducedAngle1 > 270 && reducedAngle1 <= 360) { + reducedAngle1 = 540 - reducedAngle1; + } + // Angles reduced to 0 - 180 + if (reducedAngle2 > 180 && reducedAngle2 <= 360) { + reducedAngle2 = 360 - reducedAngle2; + } + if ((axis.pane.options.startAngle === correctAngle) || + (axis.pane.options.startAngle === correctAngle + 360) || + (axis.pane.options.startAngle === correctAngle - 360)) { + labelDir = 'start'; + } + if ((correctAngle >= -90 && correctAngle <= 90) || + (correctAngle >= -360 && correctAngle <= -270) || + (correctAngle >= 270 && correctAngle <= 360)) { + align = (labelDir === 'start') ? 'right' : 'left'; + } + else { + align = (labelDir === 'start') ? 'left' : 'right'; + } + // For angles beetwen (90 + n * 180) +- 20 + if (reducedAngle2 > 70 && reducedAngle2 < 110) { + align = 'center'; + } + // auto Y translation + if (reducedAngle1 < 15 || + (reducedAngle1 >= 180 && reducedAngle1 < 195)) { + translateY = labelBBox.height * 0.3; + } + else if (reducedAngle1 >= 15 && reducedAngle1 <= 35) { + translateY = labelDir === 'start' ? + 0 : labelBBox.height * 0.75; + } + else if (reducedAngle1 >= 195 && reducedAngle1 <= 215) { + translateY = labelDir === 'start' ? + labelBBox.height * 0.75 : 0; + } + else if (reducedAngle1 > 35 && reducedAngle1 <= 90) { + translateY = labelDir === 'start' ? + -labelBBox.height * 0.25 : labelBBox.height; + } + else if (reducedAngle1 > 215 && reducedAngle1 <= 270) { + translateY = labelDir === 'start' ? + labelBBox.height : -labelBBox.height * 0.25; + } + // auto X translation + if (reducedAngle2 < 15) { + translateX = labelDir === 'start' ? + -labelBBox.height * 0.15 : labelBBox.height * 0.15; + } + else if (reducedAngle2 > 165 && reducedAngle2 <= 180) { + translateX = labelDir === 'start' ? + labelBBox.height * 0.15 : -labelBBox.height * 0.15; + } + label.attr({ align: align }); + label.translate(translateX, translateY + labelYPosCorrection); + } + e.pos.x = ret.x + labelOptions.x; + e.pos.y = ret.y + optionsY; + } + }); + // Wrap the getMarkPath function to return the path of the radial marker + wrap(TickClass.prototype, 'getMarkPath', function (proceed, x, y, tickLength, tickWidth, horiz, renderer) { + var tick = this; + var axis = tick.axis; + var endPoint, ret; + if (axis.isRadial) { + endPoint = axis.getPosition(this.pos, axis.center[2] / 2 + tickLength); + ret = [ + 'M', + x, + y, + 'L', + endPoint.x, + endPoint.y + ]; + } + else { + ret = proceed.call(this, x, y, tickLength, tickWidth, horiz, renderer); + } + return ret; + }); + }; + /* * + * + * Static Properties + * + * */ + /** + * Circular axis around the perimeter of a polar chart. + * @private + */ + RadialAxis.defaultCircularOptions = { + gridLineWidth: 1, + labels: { + align: null, + distance: 15, + x: 0, + y: null, + style: { + textOverflow: 'none' // wrap lines by default (#7248) + } + }, + maxPadding: 0, + minPadding: 0, + showLastLabel: false, + tickLength: 0 + }; + /** + * The default options extend defaultYAxisOptions. + * @private + */ + RadialAxis.defaultRadialGaugeOptions = { + labels: { + align: 'center', + x: 0, + y: null // auto + }, + minorGridLineWidth: 0, + minorTickInterval: 'auto', + minorTickLength: 10, + minorTickPosition: 'inside', + minorTickWidth: 1, + tickLength: 10, + tickPosition: 'inside', + tickWidth: 2, + title: { + rotation: 0 + }, + zIndex: 2 // behind dials, points in the series group + }; + /** + * Radial axis, like a spoke in a polar chart. + * @private + */ + RadialAxis.defaultRadialOptions = { + /** + * In a polar chart, this is the angle of the Y axis in degrees, where + * 0 is up and 90 is right. The angle determines the position of the + * axis line and the labels, though the coordinate system is unaffected. + * Since v8.0.0 this option is also applicable for X axis (inverted + * polar). + * + * @sample {highcharts} highcharts/xaxis/angle/ + * Custom X axis' angle on inverted polar chart + * @sample {highcharts} highcharts/yaxis/angle/ + * Dual axis polar chart + * + * @type {number} + * @default 0 + * @since 4.2.7 + * @product highcharts + * @apioption xAxis.angle + */ + /** + * Polar charts only. Whether the grid lines should draw as a polygon + * with straight lines between categories, or as circles. Can be either + * `circle` or `polygon`. Since v8.0.0 this option is also applicable + * for X axis (inverted polar). + * + * @sample {highcharts} highcharts/demo/polar-spider/ + * Polygon grid lines + * @sample {highcharts} highcharts/xaxis/gridlineinterpolation/ + * Circle and polygon on inverted polar + * @sample {highcharts} highcharts/yaxis/gridlineinterpolation/ + * Circle and polygon + * + * @type {string} + * @product highcharts + * @validvalue ["circle", "polygon"] + * @apioption xAxis.gridLineInterpolation + */ + gridLineInterpolation: 'circle', + gridLineWidth: 1, + labels: { + align: 'right', + x: -3, + y: -2 + }, + showLastLabel: false, + title: { + x: 4, + text: null, + rotation: 90 + } + }; + return RadialAxis; +}()); +RadialAxis.compose(Axis, Tick); // @todo move outside +export default RadialAxis; diff --git a/librerias/gantt/code/es-modules/parts-more/WaterfallSeries.js b/librerias/gantt/code/es-modules/parts-more/WaterfallSeries.js new file mode 100644 index 0000000..580ed61 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts-more/WaterfallSeries.js @@ -0,0 +1,734 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from '../parts/Globals.js'; +import Point from '../parts/Point.js'; +import U from '../parts/Utilities.js'; +var addEvent = U.addEvent, arrayMax = U.arrayMax, arrayMin = U.arrayMin, correctFloat = U.correctFloat, isNumber = U.isNumber, objectEach = U.objectEach, pick = U.pick, seriesType = U.seriesType; +import '../parts/Options.js'; +import '../parts/Series.js'; +import StackItem from '../parts/Stacking.js'; +var Axis = H.Axis, Chart = H.Chart, Series = H.Series, seriesTypes = H.seriesTypes; +/** + * Returns true if the key is a direct property of the object. + * @private + * @param {*} obj - Object with property to test + * @param {string} key - Property key to test + * @return {boolean} - Whether it is a direct property + */ +function ownProp(obj, key) { + return Object.hasOwnProperty.call(obj, key); +} +/* eslint-disable no-invalid-this */ +addEvent(Axis, 'afterInit', function () { + if (!this.isXAxis) { + this.waterfallStacks = { + changed: false + }; + } +}); +addEvent(Axis, 'afterBuildStacks', function () { + this.waterfallStacks.changed = false; + delete this.waterfallStacks.alreadyChanged; +}); +addEvent(Chart, 'beforeRedraw', function () { + var axes = this.axes, series = this.series, i = series.length; + while (i--) { + if (series[i].options.stacking) { + axes.forEach(function (axis) { + if (!axis.isXAxis) { + axis.waterfallStacks.changed = true; + } + }); + i = 0; + } + } +}); +addEvent(Axis, 'afterRender', function () { + var stackLabelOptions = this.options.stackLabels; + if (stackLabelOptions && stackLabelOptions.enabled && + this.waterfallStacks) { + this.renderWaterfallStackTotals(); + } +}); +// eslint-disable-next-line valid-jsdoc +/** + * Calls StackItem.prototype.render function that creates and renders stack + * total label for each waterfall stack item. + * + * @private + * @function Highcharts.Axis#renderWaterfallStackTotals + */ +Axis.prototype.renderWaterfallStackTotals = function () { + var yAxis = this, waterfallStacks = yAxis.waterfallStacks, stackTotalGroup = yAxis.stacking && yAxis.stacking.stackTotalGroup, dummyStackItem = new StackItem(yAxis, yAxis.options.stackLabels, false, 0, void 0); + yAxis.dummyStackItem = dummyStackItem; + // Render each waterfall stack total + objectEach(waterfallStacks, function (type) { + objectEach(type, function (stackItem) { + dummyStackItem.total = stackItem.stackTotal; + if (stackItem.label) { + dummyStackItem.label = stackItem.label; + } + StackItem.prototype.render.call(dummyStackItem, stackTotalGroup); + stackItem.label = dummyStackItem.label; + delete dummyStackItem.label; + }); + }); + dummyStackItem.total = null; +}; +/** + * A waterfall chart displays sequentially introduced positive or negative + * values in cumulative columns. + * + * @sample highcharts/demo/waterfall/ + * Waterfall chart + * @sample highcharts/plotoptions/waterfall-inverted/ + * Horizontal (inverted) waterfall + * @sample highcharts/plotoptions/waterfall-stacked/ + * Stacked waterfall chart + * + * @extends plotOptions.column + * @product highcharts + * @requires highcharts-more + * @optionparent plotOptions.waterfall + */ +seriesType('waterfall', 'column', { + /** + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.waterfall.color + */ + /** + * The color used specifically for positive point columns. When not + * specified, the general series color is used. + * + * In styled mode, the waterfall colors can be set with the + * `.highcharts-point-negative`, `.highcharts-sum` and + * `.highcharts-intermediate-sum` classes. + * + * @sample {highcharts} highcharts/demo/waterfall/ + * Waterfall + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts + * @apioption plotOptions.waterfall.upColor + */ + dataLabels: { + inside: true + }, + /** + * The width of the line connecting waterfall columns. + * + * @product highcharts + */ + lineWidth: 1, + /** + * The color of the line that connects columns in a waterfall series. + * + * In styled mode, the stroke can be set with the `.highcharts-graph` class. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 3.0 + * @product highcharts + */ + lineColor: '#333333', + /** + * A name for the dash style to use for the line connecting the columns + * of the waterfall series. Possible values: Dash, DashDot, Dot, LongDash, + * LongDashDot, LongDashDotDot, ShortDash, ShortDashDot, ShortDashDotDot, + * ShortDot, Solid + * + * In styled mode, the stroke dash-array can be set with the + * `.highcharts-graph` class. + * + * @type {Highcharts.DashStyleValue} + * @since 3.0 + * @product highcharts + */ + dashStyle: 'Dot', + /** + * The color of the border of each waterfall column. + * + * In styled mode, the border stroke can be set with the + * `.highcharts-point` class. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 3.0 + * @product highcharts + */ + borderColor: '#333333', + states: { + hover: { + lineWidthPlus: 0 // #3126 + } + } + // Prototype members +}, { + pointValKey: 'y', + // Property needed to prevent lines between the columns from disappearing + // when negativeColor is used. + showLine: true, + // After generating points, set y-values for all sums. + generatePoints: function () { + var point, len, i, y; + // Parent call: + seriesTypes.column.prototype.generatePoints.apply(this); + for (i = 0, len = this.points.length; i < len; i++) { + point = this.points[i]; + y = this.processedYData[i]; + // override point value for sums + // #3710 Update point does not propagate to sum + if (point.isIntermediateSum || point.isSum) { + point.y = correctFloat(y); + } + } + }, + // Translate data points from raw values + translate: function () { + var series = this, options = series.options, yAxis = series.yAxis, len, i, points, point, shapeArgs, y, yValue, previousY, previousIntermediate, range, minPointLength = pick(options.minPointLength, 5), halfMinPointLength = minPointLength / 2, threshold = options.threshold, stacking = options.stacking, tooltipY, actualStack = yAxis.waterfallStacks[series.stackKey], actualStackX, dummyStackItem, total, pointY, yPos, hPos; + // run column series translate + seriesTypes.column.prototype.translate.apply(series); + previousY = previousIntermediate = threshold; + points = series.points; + for (i = 0, len = points.length; i < len; i++) { + // cache current point object + point = points[i]; + yValue = series.processedYData[i]; + shapeArgs = point.shapeArgs; + range = [0, yValue]; + pointY = point.y; + // code responsible for correct positions of stacked points + // starts here + if (stacking) { + if (actualStack) { + actualStackX = actualStack[i]; + if (stacking === 'overlap') { + total = + actualStackX.stackState[actualStackX.stateIndex--]; + y = pointY >= 0 ? total : total - pointY; + if (ownProp(actualStackX, 'absolutePos')) { + delete actualStackX.absolutePos; + } + if (ownProp(actualStackX, 'absoluteNeg')) { + delete actualStackX.absoluteNeg; + } + } + else { + if (pointY >= 0) { + total = actualStackX.threshold + + actualStackX.posTotal; + actualStackX.posTotal -= pointY; + y = total; + } + else { + total = actualStackX.threshold + + actualStackX.negTotal; + actualStackX.negTotal -= pointY; + y = total - pointY; + } + if (!actualStackX.posTotal) { + if (ownProp(actualStackX, 'absolutePos')) { + actualStackX.posTotal = + actualStackX.absolutePos; + delete actualStackX.absolutePos; + } + } + if (!actualStackX.negTotal) { + if (ownProp(actualStackX, 'absoluteNeg')) { + actualStackX.negTotal = + actualStackX.absoluteNeg; + delete actualStackX.absoluteNeg; + } + } + } + if (!point.isSum) { + // the connectorThreshold property is later used in + // getCrispPath function to draw a connector line in a + // correct place + actualStackX.connectorThreshold = + actualStackX.threshold + actualStackX.stackTotal; + } + if (yAxis.reversed) { + yPos = (pointY >= 0) ? (y - pointY) : (y + pointY); + hPos = y; + } + else { + yPos = y; + hPos = y - pointY; + } + point.below = yPos <= pick(threshold, 0); + shapeArgs.y = yAxis.translate(yPos, 0, 1, 0, 1); + shapeArgs.height = Math.abs(shapeArgs.y - + yAxis.translate(hPos, 0, 1, 0, 1)); + } + dummyStackItem = yAxis.dummyStackItem; + if (dummyStackItem) { + dummyStackItem.x = i; + dummyStackItem.label = actualStack[i].label; + dummyStackItem.setOffset(series.pointXOffset || 0, series.barW || 0, series.stackedYNeg[i], series.stackedYPos[i]); + } + } + else { + // up points + y = + Math.max(previousY, previousY + pointY) + range[0]; + shapeArgs.y = + yAxis.translate(y, 0, 1, 0, 1); + // sum points + if (point.isSum) { + shapeArgs.y = yAxis.translate(range[1], 0, 1, 0, 1); + shapeArgs.height = Math.min(yAxis.translate(range[0], 0, 1, 0, 1), yAxis.len) - shapeArgs.y; // #4256 + } + else if (point.isIntermediateSum) { + if (pointY >= 0) { + yPos = range[1] + previousIntermediate; + hPos = previousIntermediate; + } + else { + yPos = previousIntermediate; + hPos = range[1] + previousIntermediate; + } + if (yAxis.reversed) { + // swapping values + yPos ^= hPos; + hPos ^= yPos; + yPos ^= hPos; + } + shapeArgs.y = yAxis.translate(yPos, 0, 1, 0, 1); + shapeArgs.height = Math.abs(shapeArgs.y - + Math.min(yAxis.translate(hPos, 0, 1, 0, 1), yAxis.len)); + previousIntermediate += range[1]; + // If it's not the sum point, update previous stack end position + // and get shape height (#3886) + } + else { + shapeArgs.height = yValue > 0 ? + yAxis.translate(previousY, 0, 1, 0, 1) - shapeArgs.y : + yAxis.translate(previousY, 0, 1, 0, 1) - yAxis.translate(previousY - yValue, 0, 1, 0, 1); + previousY += yValue; + point.below = previousY < pick(threshold, 0); + } + // #3952 Negative sum or intermediate sum not rendered correctly + if (shapeArgs.height < 0) { + shapeArgs.y += shapeArgs.height; + shapeArgs.height *= -1; + } + } + point.plotY = shapeArgs.y = + Math.round(shapeArgs.y) - (series.borderWidth % 2) / 2; + // #3151 + shapeArgs.height = + Math.max(Math.round(shapeArgs.height), 0.001); + point.yBottom = shapeArgs.y + shapeArgs.height; + if (shapeArgs.height <= minPointLength && !point.isNull) { + shapeArgs.height = minPointLength; + shapeArgs.y -= halfMinPointLength; + point.plotY = shapeArgs.y; + if (point.y < 0) { + point.minPointLengthOffset = -halfMinPointLength; + } + else { + point.minPointLengthOffset = halfMinPointLength; + } + } + else { + if (point.isNull) { + shapeArgs.width = 0; + } + point.minPointLengthOffset = 0; + } + // Correct tooltip placement (#3014) + tooltipY = + point.plotY + (point.negative ? shapeArgs.height : 0); + if (series.chart.inverted) { + point.tooltipPos[0] = yAxis.len - tooltipY; + } + else { + point.tooltipPos[1] = tooltipY; + } + } + }, + // Call default processData then override yData to reflect waterfall's + // extremes on yAxis + processData: function (force) { + var series = this, options = series.options, yData = series.yData, + // #3710 Update point does not propagate to sum + points = options.data, point, dataLength = yData.length, threshold = options.threshold || 0, subSum, sum, dataMin, dataMax, y, i; + sum = subSum = dataMin = dataMax = 0; + for (i = 0; i < dataLength; i++) { + y = yData[i]; + point = points && points[i] ? points[i] : {}; + if (y === 'sum' || point.isSum) { + yData[i] = correctFloat(sum); + } + else if (y === 'intermediateSum' || + point.isIntermediateSum) { + yData[i] = correctFloat(subSum); + subSum = 0; + } + else { + sum += y; + subSum += y; + } + dataMin = Math.min(sum, dataMin); + dataMax = Math.max(sum, dataMax); + } + Series.prototype.processData.call(this, force); + // Record extremes only if stacking was not set: + if (!options.stacking) { + series.dataMin = dataMin + threshold; + series.dataMax = dataMax; + } + return; + }, + // Return y value or string if point is sum + toYData: function (pt) { + if (pt.isSum) { + return 'sum'; + } + if (pt.isIntermediateSum) { + return 'intermediateSum'; + } + return pt.y; + }, + updateParallelArrays: function (point, i) { + Series.prototype.updateParallelArrays.call(this, point, i); + // Prevent initial sums from triggering an error (#3245, #7559) + if (this.yData[0] === 'sum' || this.yData[0] === 'intermediateSum') { + this.yData[0] = null; + } + }, + // Postprocess mapping between options and SVG attributes + pointAttribs: function (point, state) { + var upColor = this.options.upColor, attr; + // Set or reset up color (#3710, update to negative) + if (upColor && !point.options.color) { + point.color = point.y > 0 ? upColor : null; + } + attr = seriesTypes.column.prototype.pointAttribs.call(this, point, state); + // The dashStyle option in waterfall applies to the graph, not + // the points + delete attr.dashstyle; + return attr; + }, + // Return an empty path initially, because we need to know the stroke-width + // in order to set the final path. + getGraphPath: function () { + return [['M', 0, 0]]; + }, + // Draw columns' connector lines + getCrispPath: function () { + var data = this.data, yAxis = this.yAxis, length = data.length, graphNormalizer = Math.round(this.graph.strokeWidth()) % 2 / 2, borderNormalizer = Math.round(this.borderWidth) % 2 / 2, reversedXAxis = this.xAxis.reversed, reversedYAxis = this.yAxis.reversed, stacking = this.options.stacking, path = [], connectorThreshold, prevStack, prevStackX, prevPoint, yPos, isPos, prevArgs, pointArgs, i; + for (i = 1; i < length; i++) { + pointArgs = data[i].shapeArgs; + prevPoint = data[i - 1]; + prevArgs = data[i - 1].shapeArgs; + prevStack = yAxis.waterfallStacks[this.stackKey]; + isPos = prevPoint.y > 0 ? -prevArgs.height : 0; + if (prevStack && prevArgs && pointArgs) { + prevStackX = prevStack[i - 1]; + // y position of the connector is different when series are + // stacked, yAxis is reversed and it also depends on point's + // value + if (stacking) { + connectorThreshold = prevStackX.connectorThreshold; + yPos = Math.round((yAxis.translate(connectorThreshold, 0, 1, 0, 1) + + (reversedYAxis ? isPos : 0))) - graphNormalizer; + } + else { + yPos = + prevArgs.y + prevPoint.minPointLengthOffset + + borderNormalizer - graphNormalizer; + } + path.push([ + 'M', + (prevArgs.x || 0) + (reversedXAxis ? + 0 : + (prevArgs.width || 0)), + yPos + ], [ + 'L', + (pointArgs.x || 0) + (reversedXAxis ? + (pointArgs.width || 0) : + 0), + yPos + ]); + } + if (!stacking && + path.length && + prevArgs && + ((prevPoint.y < 0 && !reversedYAxis) || + (prevPoint.y > 0 && reversedYAxis))) { + path[path.length - 2][2] += prevArgs.height; + path[path.length - 1][2] += prevArgs.height; + } + } + return path; + }, + // The graph is initially drawn with an empty definition, then updated with + // crisp rendering. + drawGraph: function () { + Series.prototype.drawGraph.call(this); + this.graph.attr({ + d: this.getCrispPath() + }); + }, + // Waterfall has stacking along the x-values too. + setStackedPoints: function () { + var series = this, options = series.options, waterfallStacks = series.yAxis.waterfallStacks, seriesThreshold = options.threshold, stackThreshold = seriesThreshold || 0, interSum = stackThreshold, stackKey = series.stackKey, xData = series.xData, xLength = xData.length, actualStack, actualStackX, totalYVal, actualSum, prevSum, statesLen, posTotal, negTotal, xPoint, yVal, x, alreadyChanged, changed; + // function responsible for calculating correct values for stackState + // array of each stack item. The arguments are: firstS - the value for + // the first state, nextS - the difference between the previous and the + // newest state, sInx - counter used in the for that updates each state + // when necessary, sOff - offset that must be added to each state when + // they need to be updated (if point isn't a total sum) + // eslint-disable-next-line require-jsdoc + function calculateStackState(firstS, nextS, sInx, sOff) { + if (!statesLen) { + actualStackX.stackState[0] = firstS; + statesLen = actualStackX.stackState.length; + } + else { + for (sInx; sInx < statesLen; sInx++) { + actualStackX.stackState[sInx] += sOff; + } + } + actualStackX.stackState.push(actualStackX.stackState[statesLen - 1] + nextS); + } + series.yAxis.stacking.usePercentage = false; + totalYVal = actualSum = prevSum = stackThreshold; + // code responsible for creating stacks for waterfall series + if (series.visible || + !series.chart.options.chart.ignoreHiddenSeries) { + changed = waterfallStacks.changed; + alreadyChanged = waterfallStacks.alreadyChanged; + // in case of a redraw, stack for each x value must be + // emptied (only for the first series in a specific stack) + // and recalculated once more + if (alreadyChanged && + alreadyChanged.indexOf(stackKey) < 0) { + changed = true; + } + if (!waterfallStacks[stackKey]) { + waterfallStacks[stackKey] = {}; + } + actualStack = waterfallStacks[stackKey]; + for (var i = 0; i < xLength; i++) { + x = xData[i]; + if (!actualStack[x] || changed) { + actualStack[x] = { + negTotal: 0, + posTotal: 0, + stackTotal: 0, + threshold: 0, + stateIndex: 0, + stackState: [], + label: ((changed && + actualStack[x]) ? + actualStack[x].label : + void 0) + }; + } + actualStackX = actualStack[x]; + yVal = series.yData[i]; + if (yVal >= 0) { + actualStackX.posTotal += yVal; + } + else { + actualStackX.negTotal += yVal; + } + // points do not exist yet, so raw data is used + xPoint = options.data[i]; + posTotal = actualStackX.absolutePos = + actualStackX.posTotal; + negTotal = actualStackX.absoluteNeg = + actualStackX.negTotal; + actualStackX.stackTotal = posTotal + negTotal; + statesLen = actualStackX.stackState.length; + if (xPoint && xPoint.isIntermediateSum) { + calculateStackState(prevSum, actualSum, 0, prevSum); + prevSum = actualSum; + actualSum = seriesThreshold; + // swapping values + stackThreshold ^= interSum; + interSum ^= stackThreshold; + stackThreshold ^= interSum; + } + else if (xPoint && xPoint.isSum) { + calculateStackState(seriesThreshold, totalYVal, statesLen); + stackThreshold = seriesThreshold; + } + else { + calculateStackState(stackThreshold, yVal, 0, totalYVal); + if (xPoint) { + totalYVal += yVal; + actualSum += yVal; + } + } + actualStackX.stateIndex++; + actualStackX.threshold = stackThreshold; + stackThreshold += actualStackX.stackTotal; + } + waterfallStacks.changed = false; + if (!waterfallStacks.alreadyChanged) { + waterfallStacks.alreadyChanged = []; + } + waterfallStacks.alreadyChanged.push(stackKey); + } + }, + // Extremes for a non-stacked series are recorded in processData. + // In case of stacking, use Series.stackedYData to calculate extremes. + getExtremes: function () { + var stacking = this.options.stacking, yAxis, waterfallStacks, stackedYNeg, stackedYPos; + if (stacking) { + yAxis = this.yAxis; + waterfallStacks = yAxis.waterfallStacks; + stackedYNeg = this.stackedYNeg = []; + stackedYPos = this.stackedYPos = []; + // the visible y range can be different when stacking is set to + // overlap and different when it's set to normal + if (stacking === 'overlap') { + objectEach(waterfallStacks[this.stackKey], function (stackX) { + stackedYNeg.push(arrayMin(stackX.stackState)); + stackedYPos.push(arrayMax(stackX.stackState)); + }); + } + else { + objectEach(waterfallStacks[this.stackKey], function (stackX) { + stackedYNeg.push(stackX.negTotal + stackX.threshold); + stackedYPos.push(stackX.posTotal + stackX.threshold); + }); + } + return { + dataMin: arrayMin(stackedYNeg), + dataMax: arrayMax(stackedYPos) + }; + } + // When not stacking, data extremes have already been computed in the + // processData function. + return { + dataMin: this.dataMin, + dataMax: this.dataMax + }; + } + // Point members +}, { + getClassName: function () { + var className = Point.prototype.getClassName.call(this); + if (this.isSum) { + className += ' highcharts-sum'; + } + else if (this.isIntermediateSum) { + className += ' highcharts-intermediate-sum'; + } + return className; + }, + // Pass the null test in ColumnSeries.translate. + isValid: function () { + return (isNumber(this.y) || + this.isSum || + Boolean(this.isIntermediateSum)); + } +}); +/** + * A `waterfall` series. If the [type](#series.waterfall.type) option + * is not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.waterfall + * @excluding dataParser, dataURL + * @product highcharts + * @requires highcharts-more + * @apioption series.waterfall + */ +/** + * An array of data points for the series. For the `waterfall` series + * type, points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 7], + * [1, 8], + * [2, 3] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.waterfall.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 8, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 8, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @excluding marker + * @product highcharts + * @apioption series.waterfall.data + */ +/** + * When this property is true, the points acts as a summary column for + * the values added or substracted since the last intermediate sum, + * or since the start of the series. The `y` value is ignored. + * + * @sample {highcharts} highcharts/demo/waterfall/ + * Waterfall + * + * @type {boolean} + * @default false + * @product highcharts + * @apioption series.waterfall.data.isIntermediateSum + */ +/** + * When this property is true, the point display the total sum across + * the entire series. The `y` value is ignored. + * + * @sample {highcharts} highcharts/demo/waterfall/ + * Waterfall + * + * @type {boolean} + * @default false + * @product highcharts + * @apioption series.waterfall.data.isSum + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/parts.js b/librerias/gantt/code/es-modules/parts.js new file mode 100644 index 0000000..0d8330a --- /dev/null +++ b/librerias/gantt/code/es-modules/parts.js @@ -0,0 +1,684 @@ +'use strict'; +/* eslint-disable max-len, no-unused-vars */ +var HighchartsConfig = { + 'version': [{ + 'highcharts': '4.0.1-modified' + }, { + 'Highstock': '2.0.1-modified' + }], + 'parts': [{ + 'name': 'Intro', + 'component': 'Core', + 'group': 'Core', + 'baseUrl': 'parts' + }, { + 'name': 'Globals', + 'component': 'Core', + 'group': 'Core', + 'baseUrl': 'parts' + }, { + 'name': 'Utilities', + 'component': 'Core', + 'group': 'Core', + 'baseUrl': 'parts' + }, { + 'name': 'Options', + 'component': 'Core', + 'group': 'Core', + 'baseUrl': 'parts' + }, { + 'name': 'Color', + 'component': 'Core', + 'group': 'Core', + 'baseUrl': 'parts' + }, { + 'name': 'SvgRenderer', + 'component': 'Core', + 'group': 'Core', + 'baseUrl': 'parts' + }, { + 'name': 'Html', + 'component': 'Html', + 'group': 'Features', + 'baseUrl': 'parts', + 'depends': { + 'component': ['Core'] + } + }, { + 'name': 'VmlRenderer', + 'component': 'VML renderer', + 'group': 'Renderers', + 'depends': { + 'component': ['Html'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'Tick', + 'component': 'Core', + 'group': 'Core', + 'baseUrl': 'parts' + }, { + 'name': 'PlotLineOrBand', + 'component': 'Plotlines or bands', + 'group': 'Features', + 'depends': { + 'component': ['Core'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'Axis', + 'component': 'Core', + 'group': 'Core', + 'baseUrl': 'parts' + }, { + 'name': 'DateTimeAxis', + 'component': 'Datetime axis', + 'group': 'Features', + 'depends': { + 'component': ['Core'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'LogarithmicAxis', + 'component': 'Logarithmic axis', + 'group': 'Features', + 'depends': { + 'component': ['Core'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'Tooltip', + 'component': 'Tooltip', + 'group': 'Dynamics and Interaction', + 'depends': { + 'component': ['Interaction'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'Pointer', + 'component': 'Interaction', + 'group': 'Dynamics and Interaction', + 'depends': { + 'component': ['Core'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'TouchPointer', + 'component': 'Touch', + 'group': 'Dynamics and Interaction', + 'depends': { + 'component': ['Interaction', 'Core'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'MSPointer', + 'component': 'MS Touch', + 'group': 'Dynamics and Interaction', + 'depends': { + 'component': ['Touch'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'Legend', + 'component': 'Core', + 'group': 'Core', + 'baseUrl': 'parts' + }, { + 'name': 'Chart', + 'component': 'Core', + 'group': 'Core', + 'baseUrl': 'parts' + }, { + 'name': 'CenteredSeriesMixin', + 'component': 'CenteredSeriesMixin', + 'baseUrl': 'parts' + }, { + 'name': 'Point', + 'component': 'Core', + 'group': 'Core', + 'baseUrl': 'parts' + }, { + 'name': 'Series', + 'component': 'Core', + 'group': 'Core', + 'baseUrl': 'parts' + }, { + 'name': 'Stacking', + 'component': 'Stacking', + 'group': 'Features', + 'baseUrl': 'parts' + }, { + 'name': 'Dynamics', + 'component': 'Dynamics', + 'group': 'Dynamics and Interaction', + 'depends': { + 'component': ['Core'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'LineSeries', + 'component': 'Line', + 'group': 'Chart and Serie types', + 'depends': { + 'component': ['Core'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'AreaSeries', + 'component': 'Area', + 'group': 'Chart and Serie types', + 'depends': { + 'component': ['Core'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'SplineSeries', + 'component': 'Spline', + 'group': 'Chart and Serie types', + 'depends': { + 'component': ['Core'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'AreaSplineSeries', + 'component': 'AreaSpline', + 'group': 'Chart and Serie types', + 'depends': { + 'component': ['Core', 'Area', 'Spline'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'ColumnSeries', + 'component': 'Column', + 'group': 'Chart and Serie types', + 'depends': { + 'component': ['Core'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'BarSeries', + 'component': 'Bar', + 'group': 'Chart and Serie types', + 'depends': { + 'component': ['Core', 'Column'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'ScatterSeries', + 'component': 'Scatter', + 'group': 'Chart and Serie types', + 'depends': { + 'component': ['Core', 'Column'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'PieSeries', + 'component': 'Pie', + 'group': 'Chart and Serie types', + 'depends': { + 'component': ['Core'], + 'name': ['CenteredSeriesMixin'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'DataLabels', + 'component': 'Datalabels', + 'group': 'Features', + 'depends': { + 'component': ['Core'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'Interaction', + 'component': 'Interaction', + 'group': 'Dynamics and Interaction', + 'depends': { + 'component': ['Core'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'OrdinalAxis', + 'component': 'Stock', + 'group': 'Stock', + 'depends': { + 'component': ['Core'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'DataGrouping', + 'component': 'Stock', + 'group': 'Stock', + 'depends': { + 'component': ['Core'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'OHLCSeries', + 'component': 'OHLC', + 'group': 'Stock', + 'depends': { + 'component': ['Stock', 'Column'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'CandlestickSeries', + 'component': 'Candlestick', + 'group': 'Stock', + 'depends': { + 'component': ['Stock', 'OHLC', 'Column'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'FlagsSeries', + 'component': 'Flags', + 'group': 'Stock', + 'depends': { + 'component': ['Stock', 'Column'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'Scroller', + 'component': 'Stock', + 'group': 'Stock', + 'depends': { + 'component': ['Core', 'Line'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'RangeSelector', + 'component': 'Stock', + 'group': 'Stock', + 'depends': { + 'component': ['Core'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'StockNavigation', + 'component': 'Stock', + 'group': 'Stock', + 'depends': { + 'component': ['Core'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'StockChart', + 'component': 'Stock', + 'group': 'Stock', + 'depends': { + 'component': ['Core', 'Interaction', 'Tooltip'] + }, + 'baseUrl': 'parts' + }, { + 'name': 'Pane', + 'baseUrl': 'parts-more' + }, { + 'name': 'RadialAxis', + 'depends': { + 'name': ['CenteredSeriesMixin'] + }, + 'baseUrl': 'parts-more' + }, { + 'name': 'AreaRangeSeries', + 'component': 'Arearange', + 'group': 'Chart and Serie types', + 'depends': { + 'component': ['Column', 'Area'] + }, + 'baseUrl': 'parts-more' + }, { + 'name': 'AreaSplineRangeSeries', + 'component': 'Areasplinerange', + 'group': 'Chart and Serie types', + 'depends': { + 'component': ['Arearange', 'Spline'] + }, + 'baseUrl': 'parts-more' + }, { + 'name': 'ColumnRangeSeries', + 'component': 'Columnrange', + 'group': 'Chart and Serie types', + 'depends': { + 'component': ['Core', 'Column', 'Arearange'] + }, + 'baseUrl': 'parts-more' + }, { + 'name': 'ColumnPyramidSeries', + 'component': 'Columnpyramid', + 'group': 'Chart and Serie types', + 'depends': { + 'component': ['Core', 'Column'] + }, + 'baseUrl': 'parts-more' + }, { + 'name': 'GaugeSeries', + 'component': 'Gauge', + 'group': 'Chart and Serie types', + 'depends': { + 'component': ['Core', 'Line'], + 'name': ['RadialAxis', 'Pane', 'PlotLineOrBand'] + }, + 'baseUrl': 'parts-more' + }, { + 'name': 'BoxPlotSeries', + 'component': 'Boxplot', + 'group': 'Chart and Serie types', + 'depends': { + 'component': ['Column'] + }, + 'baseUrl': 'parts-more' + }, { + 'name': 'ErrorBarSeries', + 'component': 'Errorbar', + 'group': 'Chart and Serie types', + 'depends': { + 'component': ['Boxplot'] + }, + 'baseUrl': 'parts-more' + }, { + 'name': 'WaterfallSeries', + 'component': 'Waterfall', + 'group': 'Chart and Serie types', + 'depends': { + 'component': ['Column', 'Stacking'] + }, + 'baseUrl': 'parts-more' + }, { + 'name': 'BubbleSeries', + 'component': 'Bubble', + 'group': 'Chart and Serie types', + 'depends': { + 'component': ['Core', 'Scatter'] + }, + 'baseUrl': 'parts-more' + }, { + 'name': 'PackedBubbleSeries', + 'component': 'Packedbubble', + 'group': 'Chart and Serie types', + 'depends': { + 'component': ['Core', 'Scatter'] + }, + 'baseUrl': 'parts-more' + }, { + 'name': 'Polar', + 'component': 'Polar', + 'group': 'Features', + 'depends': { + 'component': ['Core'], + 'name': ['RadialAxis', 'Pane', 'Column', 'Area'] + }, + 'baseUrl': 'parts-more' + }, { + 'name': 'Facade', + 'component': 'Core', + 'group': 'Core', + 'baseUrl': 'parts' + }, { + 'name': 'Outro', + 'component': 'Core', + 'group': 'Core', + 'baseUrl': 'parts' + }, { + 'name': 'funnel.src', + 'component': 'Funnel', + 'group': 'Chart and Serie types', + 'depends': { + 'component': ['Core', 'Datalabels', 'Pie'] + }, + 'baseUrl': 'modules' + }, { + 'name': 'exporting.src', + 'component': 'Exporting', + 'group': 'Modules', + 'depends': { + 'component': ['Core'] + }, + 'baseUrl': 'modules' + }, { + 'name': 'offline-exporting.src', + 'component': 'Offline exporting', + 'group': 'Modules', + 'depends': { + 'component': ['Core', 'Exporting'] + }, + 'baseUrl': 'modules' + }, { + 'name': 'data.src', + 'component': 'Data', + 'group': 'Modules', + 'depends': { + 'component': ['Core'] + }, + 'baseUrl': 'modules' + }, { + 'name': 'no-data-to-display.src', + 'component': 'No data to display', + 'group': 'Modules', + 'depends': { + 'component': ['Core'] + }, + 'baseUrl': 'modules' + }, { + 'name': 'drilldown.src', + 'component': 'Drilldown', + 'group': 'Modules', + 'depends': { + 'component': ['Core'] + }, + 'baseUrl': 'modules' + }, { + 'name': 'solid-gauge.src', + 'component': 'Solid gauge', + 'group': 'Modules', + 'depends': { + 'component': ['Gauge'] + }, + 'baseUrl': 'modules' + }, { + 'name': 'HeatmapIntro', + 'component': 'Heatmap', + 'group': 'Modules', + 'depends': { + 'component': ['Core', 'Column', 'Scatter'] + }, + 'baseUrl': 'parts-map' + }, { + 'name': 'HeatmapGlobals', + 'component': 'Heatmap', + 'group': 'Modules', + 'depends': { + 'component': [] + }, + 'baseUrl': 'parts-map' + }, { + 'name': 'ColorAxis', + 'component': 'Heatmap', + 'group': 'Modules', + 'depends': { + 'component': [] + }, + 'baseUrl': 'parts-map' + }, { + 'name': 'ColorSeriesMixin', + 'component': 'Heatmap', + 'group': 'Modules', + 'depends': { + 'component': [] + }, + 'baseUrl': 'parts-map' + }, { + 'name': 'HeatmapSeries', + 'component': 'Heatmap', + 'group': 'Modules', + 'depends': { + 'component': [] + }, + 'baseUrl': 'parts-map' + }, { + 'name': 'Outro', + 'component': 'Heatmap', + 'group': 'Modules', + 'depends': { + 'component': [] + }, + 'baseUrl': 'parts-map' + }], + 'groups': { + 'Core': { + 'description': 'The Core of Highcharts', + 'depends': { + 'component': ['Line'] + } + }, + 'Stock': { + 'description': 'Highstock lets you create stock or general timeline charts' + }, + 'Chart and Serie types': { + 'description': 'All the serie types available with Highcharts. Note: Line series is the base serie, required by the Core module' + }, + 'Features': { + 'description': 'Enable behaviours to the chart' + }, + 'Renderers': { + 'description': 'Alternatives to standard SVG rendering' + }, + 'Modules': { + 'description': '' + }, + + 'Dynamics and Interaction': { + 'description': 'Leaving these out makes your chart completely static' + } + }, + 'components': { + 'Core': { + 'description': 'This module is required for all other modules.' + }, + 'Stock': { + 'description': 'For general stock and timeline chart, including navigator, scrollbar and range selector' + }, + 'VML renderer': { + 'description': 'This concerns old IE, which doesn\'t support SVG.' + }, + 'Tooltip': { + 'description': 'The tooltip appears when hovering over a point in a series' + }, + 'Interaction': { + 'description': 'Enabling mouse interaction with the chart' + }, + 'Touch': { + 'description': 'Zooming the preferred way, by two-finger gestures. In response to the zoomType settings, the charts can be zoomed in and out as well as panned by one finger.' + }, + 'Html': { + 'description': 'Use HTML to render the contents of the tooltip instead of SVG. Using HTML allows advanced formatting like tables and images in the tooltip. It is also recommended for rtl languages' + }, + 'Datetime axis': { + 'description': 'Enable support for an Axis based on time units' + }, + 'Plotlines or bands': { + 'description': 'Enable drawing plotlines and -bands on your chart.' + }, + 'Logarithmic axis': { + 'description': 'Enable logarithmic axis. On a logarithmic axis the numbers along the axis increase logarithmically and the axis adjusts itself to the data series present in the chart.' + }, + 'Stacking': { + 'description': 'Stack the data in your series on top of each other instead of overlapping.' + }, + 'Datalabels': { + 'description': 'Data labels display each point\'s value or other information related to the point' + }, + 'Polar': { + 'description': 'For turning the regular chart into a polar chart.' + }, + 'MS Touch': { + 'description': 'Optimised touch support for Microsoft touch devices' + }, + 'Dynamics': { + 'description': 'Adds support for creating more dynamic charts, by adding API methods for adding series, points, etc.' + }, + 'Line': { + 'description': '' + }, + 'Area': { + 'description': '' + }, + 'Spline': { + 'description': '' + }, + 'Column': { + 'description': '' + }, + 'Bar': { + 'description': '' + }, + 'Scatter': { + 'description': '' + }, + 'Pie': { + 'description': '' + }, + 'Arearange': { + 'description': '' + }, + 'Areaspline': { + 'description': '' + }, + 'Areasplinerange': { + 'description': '' + }, + 'Columnrange': { + 'description': '' + }, + 'Columnpyramid': { + 'description': '' + }, + 'Packedbubble': { + 'description': '' + }, + 'Gauge': { + 'description': '' + }, + 'BoxPlot': { + 'description': 'A box plot, or box-and-whiskers chart, displays groups of data by their five point summaries: minimum, lower quartile, median, upper quartile and maximum. ' + }, + 'Bubble': { + 'description': 'Bubble charts allow three dimensional data to be plotted in an X/Y diagram with sized bubbles.' + }, + 'Waterfall': { + 'description': 'Waterfall charts display the cumulative effects of income and expences, or other similar data. In Highcharts, a point can either be positive or negative, an intermediate sum or the total sum.' + }, + 'Funnel': { + 'description': 'A funnel is a chart type mainly used by sales personnel to monitor the stages of the sales cycle, from first interest to the closed sale.' + }, + 'ErrorBar': { + 'description': 'An error bar series is a secondary series that lies on top of a parent series and displays the possible error range of each parent point.' + }, + 'OHLC': { + 'description': 'The Open-High-Low-Close chart is typically used to illustrate movements in the price over time' + }, + 'Candlestick': { + 'description': 'Like the OHLC chart, using columns to represent the range of price movement.' + }, + 'Flags': { + 'description': 'Series consists of flags marking events or points of interests' + }, + 'Exporting': { + 'description': 'For saving the chart to an image' + }, + 'Data': { + 'description': 'Intended to ease the common process of loading data from CSV, HTML tables and even Google Spreadsheets' + }, + 'No data to display': { + 'description': 'When there\'s no data to display, the chart is showing a message' + }, + 'Drilldown': { + 'description': 'Add drill down features, allowing point click to show detailed data series related to each point.' + }, + 'Solid gauge': { + 'description': 'Display your data in a solid gauge' + }, + 'Heatmap': { + 'description': 'Make heatmap out of your data' + } + } +}; +/* eslint-enable no-unused-vars */ diff --git a/librerias/gantt/code/es-modules/parts/AreaSeries.js b/librerias/gantt/code/es-modules/parts/AreaSeries.js new file mode 100644 index 0000000..66b313e --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/AreaSeries.js @@ -0,0 +1,499 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +import Color from './Color.js'; +var color = Color.parse; +import LegendSymbolMixin from '../mixins/legend-symbol.js'; +import U from './Utilities.js'; +var objectEach = U.objectEach, pick = U.pick, seriesType = U.seriesType; +import './Series.js'; +import './Options.js'; +var Series = H.Series; +/** + * Area series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.area + * + * @augments Highcharts.Series + */ +seriesType('area', 'line', +/** + * The area series type. + * + * @sample {highcharts} highcharts/demo/area-basic/ + * Area chart + * @sample {highstock} stock/demo/area/ + * Area chart + * + * @extends plotOptions.line + * @excluding useOhlcData + * @product highcharts highstock + * @optionparent plotOptions.area + */ +{ + /** + * Fill color or gradient for the area. When `null`, the series' `color` + * is used with the series' `fillOpacity`. + * + * In styled mode, the fill color can be set with the `.highcharts-area` + * class name. + * + * @sample {highcharts} highcharts/plotoptions/area-fillcolor-default/ + * Null by default + * @sample {highcharts} highcharts/plotoptions/area-fillcolor-gradient/ + * Gradient + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock + * @apioption plotOptions.area.fillColor + */ + /** + * Fill opacity for the area. When you set an explicit `fillColor`, + * the `fillOpacity` is not applied. Instead, you should define the + * opacity in the `fillColor` with an rgba color definition. The + * `fillOpacity` setting, also the default setting, overrides the alpha + * component of the `color` setting. + * + * In styled mode, the fill opacity can be set with the + * `.highcharts-area` class name. + * + * @sample {highcharts} highcharts/plotoptions/area-fillopacity/ + * Automatic fill color and fill opacity of 0.1 + * + * @type {number} + * @default {highcharts} 0.75 + * @default {highstock} 0.75 + * @product highcharts highstock + * @apioption plotOptions.area.fillOpacity + */ + /** + * A separate color for the graph line. By default the line takes the + * `color` of the series, but the lineColor setting allows setting a + * separate color for the line without altering the `fillColor`. + * + * In styled mode, the line stroke can be set with the + * `.highcharts-graph` class name. + * + * @sample {highcharts} highcharts/plotoptions/area-linecolor/ + * Dark gray line + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock + * @apioption plotOptions.area.lineColor + */ + /** + * A separate color for the negative part of the area. + * + * In styled mode, a negative color is set with the + * `.highcharts-negative` class name. + * + * @see [negativeColor](#plotOptions.area.negativeColor) + * + * @sample {highcharts} highcharts/css/series-negative-color/ + * Negative color in styled mode + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 3.0 + * @product highcharts + * @apioption plotOptions.area.negativeFillColor + */ + /** + * Whether the whole area or just the line should respond to mouseover + * tooltips and other mouse or touch events. + * + * @sample {highcharts|highstock} highcharts/plotoptions/area-trackbyarea/ + * Display the tooltip when the area is hovered + * + * @type {boolean} + * @default false + * @since 1.1.6 + * @product highcharts highstock + * @apioption plotOptions.area.trackByArea + */ + /** + * When this is true, the series will not cause the Y axis to cross + * the zero plane (or [threshold](#plotOptions.series.threshold) option) + * unless the data actually crosses the plane. + * + * For example, if `softThreshold` is `false`, a series of 0, 1, 2, + * 3 will make the Y axis show negative values according to the + * `minPadding` option. If `softThreshold` is `true`, the Y axis starts + * at 0. + * + * @since 4.1.9 + * @product highcharts highstock + */ + softThreshold: false, + /** + * The Y axis value to serve as the base for the area, for + * distinguishing between values above and below a threshold. The area + * between the graph and the threshold is filled. + * + * * If a number is given, the Y axis will scale to the threshold. + * * If `null`, the scaling behaves like a line series with fill between + * the graph and the Y axis minimum. + * * If `Infinity` or `-Infinity`, the area between the graph and the + * corresponing Y axis extreme is filled (since v6.1.0). + * + * @sample {highcharts} highcharts/plotoptions/area-threshold/ + * A threshold of 100 + * @sample {highcharts} highcharts/plotoptions/area-threshold-infinity/ + * A threshold of Infinity + * + * @type {number|null} + * @since 2.0 + * @product highcharts highstock + */ + threshold: 0 +}, +/* eslint-disable valid-jsdoc */ +/** + * @lends seriesTypes.area.prototype + */ +{ + singleStacks: false, + /** + * Return an array of stacked points, where null and missing points are + * replaced by dummy points in order for gaps to be drawn correctly in + * stacks. + * @private + */ + getStackPoints: function (points) { + var series = this, segment = [], keys = [], xAxis = this.xAxis, yAxis = this.yAxis, stack = yAxis.stacking.stacks[this.stackKey], pointMap = {}, seriesIndex = series.index, yAxisSeries = yAxis.series, seriesLength = yAxisSeries.length, visibleSeries, upOrDown = pick(yAxis.options.reversedStacks, true) ? 1 : -1, i; + points = points || this.points; + if (this.options.stacking) { + for (i = 0; i < points.length; i++) { + // Reset after point update (#7326) + points[i].leftNull = points[i].rightNull = void 0; + // Create a map where we can quickly look up the points by + // their X values. + pointMap[points[i].x] = points[i]; + } + // Sort the keys (#1651) + objectEach(stack, function (stackX, x) { + // nulled after switching between + // grouping and not (#1651, #2336) + if (stackX.total !== null) { + keys.push(x); + } + }); + keys.sort(function (a, b) { + return a - b; + }); + visibleSeries = yAxisSeries.map(function (s) { + return s.visible; + }); + keys.forEach(function (x, idx) { + var y = 0, stackPoint, stackedValues; + if (pointMap[x] && !pointMap[x].isNull) { + segment.push(pointMap[x]); + // Find left and right cliff. -1 goes left, 1 goes + // right. + [-1, 1].forEach(function (direction) { + var nullName = direction === 1 ? + 'rightNull' : + 'leftNull', cliffName = direction === 1 ? + 'rightCliff' : + 'leftCliff', cliff = 0, otherStack = stack[keys[idx + direction]]; + // If there is a stack next to this one, + // to the left or to the right... + if (otherStack) { + i = seriesIndex; + // Can go either up or down, + // depending on reversedStacks + while (i >= 0 && i < seriesLength) { + stackPoint = otherStack.points[i]; + if (!stackPoint) { + // If the next point in this series + // is missing, mark the point + // with point.leftNull or + // point.rightNull = true. + if (i === seriesIndex) { + pointMap[x][nullName] = + true; + // If there are missing points in + // the next stack in any of the + // series below this one, we need + // to substract the missing values + // and add a hiatus to the left or + // right. + } + else if (visibleSeries[i]) { + stackedValues = + stack[x].points[i]; + if (stackedValues) { + cliff -= + stackedValues[1] - + stackedValues[0]; + } + } + } + // When reversedStacks is true, loop up, + // else loop down + i += upOrDown; + } + } + pointMap[x][cliffName] = cliff; + }); + // There is no point for this X value in this series, so we + // insert a dummy point in order for the areas to be drawn + // correctly. + } + else { + // Loop down the stack to find the series below this + // one that has a value (#1991) + i = seriesIndex; + while (i >= 0 && i < seriesLength) { + stackPoint = stack[x].points[i]; + if (stackPoint) { + y = stackPoint[1]; + break; + } + // When reversedStacks is true, loop up, else loop + // down + i += upOrDown; + } + y = yAxis.translate(// #6272 + y, 0, 1, 0, 1); + segment.push({ + isNull: true, + plotX: xAxis.translate(// #6272 + x, 0, 0, 0, 1), + x: x, + plotY: y, + yBottom: y + }); + } + }); + } + return segment; + }, + /** + * @private + */ + getGraphPath: function (points) { + var getGraphPath = Series.prototype.getGraphPath, graphPath, options = this.options, stacking = options.stacking, yAxis = this.yAxis, topPath, bottomPath, bottomPoints = [], graphPoints = [], seriesIndex = this.index, i, areaPath, plotX, stacks = yAxis.stacking.stacks[this.stackKey], threshold = options.threshold, translatedThreshold = Math.round(// #10909 + yAxis.getThreshold(options.threshold)), isNull, yBottom, connectNulls = pick(// #10574 + options.connectNulls, stacking === 'percent'), + // To display null points in underlying stacked series, this + // series graph must be broken, and the area also fall down to + // fill the gap left by the null point. #2069 + addDummyPoints = function (i, otherI, side) { + var point = points[i], stackedValues = stacking && + stacks[point.x].points[seriesIndex], nullVal = point[side + 'Null'] || 0, cliffVal = point[side + 'Cliff'] || 0, top, bottom, isNull = true; + if (cliffVal || nullVal) { + top = (nullVal ? + stackedValues[0] : + stackedValues[1]) + cliffVal; + bottom = stackedValues[0] + cliffVal; + isNull = !!nullVal; + } + else if (!stacking && + points[otherI] && + points[otherI].isNull) { + top = bottom = threshold; + } + // Add to the top and bottom line of the area + if (typeof top !== 'undefined') { + graphPoints.push({ + plotX: plotX, + plotY: top === null ? + translatedThreshold : + yAxis.getThreshold(top), + isNull: isNull, + isCliff: true + }); + bottomPoints.push({ + plotX: plotX, + plotY: bottom === null ? + translatedThreshold : + yAxis.getThreshold(bottom), + doCurve: false // #1041, gaps in areaspline areas + }); + } + }; + // Find what points to use + points = points || this.points; + // Fill in missing points + if (stacking) { + points = this.getStackPoints(points); + } + for (i = 0; i < points.length; i++) { + // Reset after series.update of stacking property (#12033) + if (!stacking) { + points[i].leftCliff = points[i].rightCliff = + points[i].leftNull = points[i].rightNull = void 0; + } + isNull = points[i].isNull; + plotX = pick(points[i].rectPlotX, points[i].plotX); + yBottom = pick(points[i].yBottom, translatedThreshold); + if (!isNull || connectNulls) { + if (!connectNulls) { + addDummyPoints(i, i - 1, 'left'); + } + // Skip null point when stacking is false and connectNulls + // true + if (!(isNull && !stacking && connectNulls)) { + graphPoints.push(points[i]); + bottomPoints.push({ + x: i, + plotX: plotX, + plotY: yBottom + }); + } + if (!connectNulls) { + addDummyPoints(i, i + 1, 'right'); + } + } + } + topPath = getGraphPath.call(this, graphPoints, true, true); + bottomPoints.reversed = true; + bottomPath = getGraphPath.call(this, bottomPoints, true, true); + var firstBottomPoint = bottomPath[0]; + if (firstBottomPoint && firstBottomPoint[0] === 'M') { + bottomPath[0] = ['L', firstBottomPoint[1], firstBottomPoint[2]]; + } + areaPath = topPath.concat(bottomPath); + // TODO: don't set leftCliff and rightCliff when connectNulls? + graphPath = getGraphPath + .call(this, graphPoints, false, connectNulls); + areaPath.xMap = topPath.xMap; + this.areaPath = areaPath; + return graphPath; + }, + /** + * Draw the graph and the underlying area. This method calls the Series + * base function and adds the area. The areaPath is calculated in the + * getSegmentPath method called from Series.prototype.drawGraph. + * @private + */ + drawGraph: function () { + // Define or reset areaPath + this.areaPath = []; + // Call the base method + Series.prototype.drawGraph.apply(this); + // Define local variables + var series = this, areaPath = this.areaPath, options = this.options, zones = this.zones, props = [[ + 'area', + 'highcharts-area', + this.color, + options.fillColor + ]]; // area name, main color, fill color + zones.forEach(function (zone, i) { + props.push([ + 'zone-area-' + i, + 'highcharts-area highcharts-zone-area-' + i + ' ' + + zone.className, + zone.color || series.color, + zone.fillColor || options.fillColor + ]); + }); + props.forEach(function (prop) { + var areaKey = prop[0], area = series[areaKey], verb = area ? 'animate' : 'attr', attribs = {}; + // Create or update the area + if (area) { // update + area.endX = series.preventGraphAnimation ? + null : + areaPath.xMap; + area.animate({ d: areaPath }); + } + else { // create + attribs.zIndex = 0; // #1069 + area = series[areaKey] = series.chart.renderer + .path(areaPath) + .addClass(prop[1]) + .add(series.group); + area.isArea = true; + } + if (!series.chart.styledMode) { + attribs.fill = pick(prop[3], color(prop[2]) + .setOpacity(pick(options.fillOpacity, 0.75)) + .get()); + } + area[verb](attribs); + area.startX = areaPath.xMap; + area.shiftUnit = options.step ? 2 : 1; + }); + }, + drawLegendSymbol: LegendSymbolMixin.drawRectangle +}); +/* eslint-enable valid-jsdoc */ +/** + * A `area` series. If the [type](#series.area.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.area + * @excluding dataParser, dataURL, useOhlcData + * @product highcharts highstock + * @apioption series.area + */ +/** + * An array of data points for the series. For the `area` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` * and `pointInterval` given in the series options. If the + * axis has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 9], + * [1, 7], + * [2, 6] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.area.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @product highcharts highstock + * @apioption series.area.data + */ +''; // adds doclets above to transpilat diff --git a/librerias/gantt/code/es-modules/parts/AreaSplineSeries.js b/librerias/gantt/code/es-modules/parts/AreaSplineSeries.js new file mode 100644 index 0000000..ebbcfd0 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/AreaSplineSeries.js @@ -0,0 +1,117 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +import LegendSymbolMixin from '../mixins/legend-symbol.js'; +import U from './Utilities.js'; +var seriesType = U.seriesType; +import './AreaSeries.js'; +import './SplineSeries.js'; +var areaProto = H.seriesTypes.area.prototype, defaultPlotOptions = H.defaultPlotOptions; +/** + * AreaSpline series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.areaspline + * + * @augments Highcharts.Series + */ +seriesType('areaspline', 'spline', +/** + * The area spline series is an area series where the graph between the + * points is smoothed into a spline. + * + * @sample {highcharts} highcharts/demo/areaspline/ + * Area spline chart + * @sample {highstock} stock/demo/areaspline/ + * Area spline chart + * + * @extends plotOptions.area + * @excluding step + * @product highcharts highstock + * @apioption plotOptions.areaspline + */ +defaultPlotOptions.area, { + getStackPoints: areaProto.getStackPoints, + getGraphPath: areaProto.getGraphPath, + drawGraph: areaProto.drawGraph, + drawLegendSymbol: LegendSymbolMixin.drawRectangle +}); +/** + * A `areaspline` series. If the [type](#series.areaspline.type) option + * is not specified, it is inherited from [chart.type](#chart.type). + * + * + * @extends series,plotOptions.areaspline + * @excluding dataParser, dataURL, step + * @product highcharts highstock + * @apioption series.areaspline + */ +/** + * An array of data points for the series. For the `areaspline` series + * type, points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 10], + * [1, 9], + * [2, 3] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.areaspline.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 4, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 4, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @product highcharts highstock + * @apioption series.areaspline.data + */ +''; // adds doclets above into transpilat diff --git a/librerias/gantt/code/es-modules/parts/Axis.js b/librerias/gantt/code/es-modules/parts/Axis.js new file mode 100644 index 0000000..6941afb --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/Axis.js @@ -0,0 +1,5904 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Color from './Color.js'; +import H from './Globals.js'; +import Tick from './Tick.js'; +import U from './Utilities.js'; +var addEvent = U.addEvent, animObject = U.animObject, arrayMax = U.arrayMax, arrayMin = U.arrayMin, clamp = U.clamp, correctFloat = U.correctFloat, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, error = U.error, extend = U.extend, fireEvent = U.fireEvent, format = U.format, getMagnitude = U.getMagnitude, isArray = U.isArray, isFunction = U.isFunction, isNumber = U.isNumber, isString = U.isString, merge = U.merge, normalizeTickInterval = U.normalizeTickInterval, objectEach = U.objectEach, pick = U.pick, relativeLength = U.relativeLength, removeEvent = U.removeEvent, splat = U.splat, syncTimeout = U.syncTimeout; +/** + * Options for the path on the Axis to be calculated. + * @interface Highcharts.AxisPlotLinePathOptionsObject + */ /** +* Axis value. +* @name Highcharts.AxisPlotLinePathOptionsObject#value +* @type {number|undefined} +*/ /** +* Line width used for calculation crisp line coordinates. Defaults to 1. +* @name Highcharts.AxisPlotLinePathOptionsObject#lineWidth +* @type {number|undefined} +*/ /** +* If `false`, the function will return null when it falls outside the axis +* bounds. If `true`, the function will return a path aligned to the plot area +* sides if it falls outside. If `pass`, it will return a path outside. +* @name Highcharts.AxisPlotLinePathOptionsObject#force +* @type {string|boolean|undefined} +*/ /** +* Used in Highstock. When `true`, plot paths (crosshair, plotLines, gridLines) +* will be rendered on all axes when defined on the first axis. +* @name Highcharts.AxisPlotLinePathOptionsObject#acrossPanes +* @type {boolean|undefined} +*/ /** +* Use old coordinates (for resizing and rescaling). +* If not set, defaults to `false`. +* @name Highcharts.AxisPlotLinePathOptionsObject#old +* @type {boolean|undefined} +*/ /** +* If given, return the plot line path of a pixel position on the axis. +* @name Highcharts.AxisPlotLinePathOptionsObject#translatedValue +* @type {number|undefined} +*/ /** +* Used in Polar axes. Reverse the positions for concatenation of polygonal +* plot bands +* @name Highcharts.AxisPlotLinePathOptionsObject#reverse +* @type {boolean|undefined} +*/ +/** + * Options for crosshairs on axes. + * + * @product highstock + * + * @typedef {Highcharts.XAxisCrosshairOptions|Highcharts.YAxisCrosshairOptions} Highcharts.AxisCrosshairOptions + */ +/** + * @typedef {"navigator"|"pan"|"rangeSelectorButton"|"rangeSelectorInput"|"scrollbar"|"traverseUpButton"|"zoom"} Highcharts.AxisExtremesTriggerValue + */ +/** + * @callback Highcharts.AxisEventCallbackFunction + * + * @param {Highcharts.Axis} this + */ +/** + * @interface Highcharts.AxisLabelsFormatterContextObject + */ /** +* @name Highcharts.AxisLabelsFormatterContextObject#axis +* @type {Highcharts.Axis} +*/ /** +* @name Highcharts.AxisLabelsFormatterContextObject#chart +* @type {Highcharts.Chart} +*/ /** +* @name Highcharts.AxisLabelsFormatterContextObject#isFirst +* @type {boolean} +*/ /** +* @name Highcharts.AxisLabelsFormatterContextObject#isLast +* @type {boolean} +*/ /** +* @name Highcharts.AxisLabelsFormatterContextObject#pos +* @type {number} +*/ /** +* @name Highcharts.AxisLabelsFormatterContextObject#value +* @type {number} +*/ +/** + * Options for axes. + * + * @typedef {Highcharts.XAxisOptions|Highcharts.YAxisOptions|Highcharts.ZAxisOptions} Highcharts.AxisOptions + */ +/** + * @callback Highcharts.AxisPointBreakEventCallbackFunction + * + * @param {Highcharts.Axis} this + * + * @param {Highcharts.AxisPointBreakEventObject} evt + */ +/** + * @interface Highcharts.AxisPointBreakEventObject + */ /** +* @name Highcharts.AxisPointBreakEventObject#brk +* @type {Highcharts.Dictionary} +*/ /** +* @name Highcharts.AxisPointBreakEventObject#point +* @type {Highcharts.Point} +*/ /** +* @name Highcharts.AxisPointBreakEventObject#preventDefault +* @type {Function} +*/ /** +* @name Highcharts.AxisPointBreakEventObject#target +* @type {Highcharts.SVGElement} +*/ /** +* @name Highcharts.AxisPointBreakEventObject#type +* @type {"pointBreak"|"pointInBreak"} +*/ +/** + * @callback Highcharts.AxisSetExtremesEventCallbackFunction + * + * @param {Highcharts.Axis} this + * + * @param {Highcharts.AxisSetExtremesEventObject} evt + */ +/** + * @interface Highcharts.AxisSetExtremesEventObject + * @extends Highcharts.ExtremesObject + */ /** +* @name Highcharts.AxisSetExtremesEventObject#preventDefault +* @type {Function} +*/ /** +* @name Highcharts.AxisSetExtremesEventObject#target +* @type {Highcharts.SVGElement} +*/ /** +* @name Highcharts.AxisSetExtremesEventObject#trigger +* @type {Highcharts.AxisExtremesTriggerValue|string} +*/ /** +* @name Highcharts.AxisSetExtremesEventObject#type +* @type {"setExtremes"} +*/ +/** + * @callback Highcharts.AxisTickPositionerCallbackFunction + * + * @param {Highcharts.Axis} this + * + * @return {Array} + */ +/** + * @interface Highcharts.AxisTickPositionsArray + * @augments Array + */ +/** + * @typedef {"high"|"low"|"middle"} Highcharts.AxisTitleAlignValue + */ +/** + * @typedef {Highcharts.XAxisTitleOptions|Highcharts.YAxisTitleOptions|Highcharts.ZAxisTitleOptions} Highcharts.AxisTitleOptions + */ +/** + * @typedef {"linear"|"logarithmic"|"datetime"|"category"|"treegrid"} Highcharts.AxisTypeValue + */ +/** + * The returned object literal from the {@link Highcharts.Axis#getExtremes} + * function. + * + * @interface Highcharts.ExtremesObject + */ /** +* The maximum value of the axis' associated series. +* @name Highcharts.ExtremesObject#dataMax +* @type {number} +*/ /** +* The minimum value of the axis' associated series. +* @name Highcharts.ExtremesObject#dataMin +* @type {number} +*/ /** +* The maximum axis value, either automatic or set manually. If the `max` option +* is not set, `maxPadding` is 0 and `endOnTick` is false, this value will be +* the same as `dataMax`. +* @name Highcharts.ExtremesObject#max +* @type {number} +*/ /** +* The minimum axis value, either automatic or set manually. If the `min` option +* is not set, `minPadding` is 0 and `startOnTick` is false, this value will be +* the same as `dataMin`. +* @name Highcharts.ExtremesObject#min +* @type {number} +*/ /** +* The user defined maximum, either from the `max` option or from a zoom or +* `setExtremes` action. +* @name Highcharts.ExtremesObject#userMax +* @type {number} +*/ /** +* The user defined minimum, either from the `min` option or from a zoom or +* `setExtremes` action. +* @name Highcharts.ExtremesObject#userMin +* @type {number} +*/ +/** + * Formatter function for the text of a crosshair label. + * + * @callback Highcharts.XAxisCrosshairLabelFormatterCallbackFunction + * + * @param {Highcharts.Axis} this + * Axis context + * + * @param {number} value + * Y value of the data point + * + * @return {string} + */ +import './Options.js'; +var defaultOptions = H.defaultOptions, deg2rad = H.deg2rad; +/** + * Create a new axis object. Called internally when instanciating a new chart or + * adding axes by {@link Highcharts.Chart#addAxis}. + * + * A chart can have from 0 axes (pie chart) to multiples. In a normal, single + * series cartesian chart, there is one X axis and one Y axis. + * + * The X axis or axes are referenced by {@link Highcharts.Chart.xAxis}, which is + * an array of Axis objects. If there is only one axis, it can be referenced + * through `chart.xAxis[0]`, and multiple axes have increasing indices. The same + * pattern goes for Y axes. + * + * If you need to get the axes from a series object, use the `series.xAxis` and + * `series.yAxis` properties. These are not arrays, as one series can only be + * associated to one X and one Y axis. + * + * A third way to reference the axis programmatically is by `id`. Add an `id` in + * the axis configuration options, and get the axis by + * {@link Highcharts.Chart#get}. + * + * Configuration options for the axes are given in options.xAxis and + * options.yAxis. + * + * @class + * @name Highcharts.Axis + * + * @param {Highcharts.Chart} chart + * The Chart instance to apply the axis on. + * + * @param {Highcharts.AxisOptions} userOptions + * Axis options. + */ +var Axis = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Axis(chart, userOptions) { + this.alternateBands = void 0; + this.bottom = void 0; + this.categories = void 0; + this.chart = void 0; + this.closestPointRange = void 0; + this.coll = void 0; + this.hasNames = void 0; + this.hasVisibleSeries = void 0; + this.height = void 0; + this.isLinked = void 0; + this.labelEdge = void 0; // @todo + this.labelFormatter = void 0; + this.left = void 0; + this.len = void 0; + this.max = void 0; + this.maxLabelLength = void 0; + this.min = void 0; + this.minorTickInterval = void 0; + this.minorTicks = void 0; + this.minPixelPadding = void 0; + this.names = void 0; + this.offset = void 0; + this.oldMax = void 0; + this.oldMin = void 0; + this.options = void 0; + this.overlap = void 0; + this.paddedTicks = void 0; + this.plotLinesAndBands = void 0; + this.plotLinesAndBandsGroups = void 0; + this.pointRange = void 0; + this.pointRangePadding = void 0; + this.pos = void 0; + this.positiveValuesOnly = void 0; + this.right = void 0; + this.series = void 0; + this.side = void 0; + this.tickAmount = void 0; + this.tickInterval = void 0; + this.tickmarkOffset = void 0; + this.tickPositions = void 0; + this.tickRotCorr = void 0; + this.ticks = void 0; + this.top = void 0; + this.transA = void 0; + this.transB = void 0; + this.translationSlope = void 0; + this.userOptions = void 0; + this.visible = void 0; + this.width = void 0; + this.zoomEnabled = void 0; + this.init(chart, userOptions); + } + /* * + * + * Functions + * + * */ + /** + * Overrideable function to initialize the axis. + * + * @see {@link Axis} + * + * @function Highcharts.Axis#init + * + * @param {Highcharts.Chart} chart + * The Chart instance to apply the axis on. + * + * @param {Highcharts.AxisOptions} userOptions + * Axis options. + * + * @fires Highcharts.Axis#event:afterInit + * @fires Highcharts.Axis#event:init + */ + Axis.prototype.init = function (chart, userOptions) { + var isXAxis = userOptions.isX, axis = this; + /** + * The Chart that the axis belongs to. + * + * @name Highcharts.Axis#chart + * @type {Highcharts.Chart} + */ + axis.chart = chart; + /** + * Whether the axis is horizontal. + * + * @name Highcharts.Axis#horiz + * @type {boolean|undefined} + */ + axis.horiz = chart.inverted && !axis.isZAxis ? !isXAxis : isXAxis; + /** + * Whether the axis is the x-axis. + * + * @name Highcharts.Axis#isXAxis + * @type {boolean|undefined} + */ + axis.isXAxis = isXAxis; + /** + * The collection where the axis belongs, for example `xAxis`, `yAxis` + * or `colorAxis`. Corresponds to properties on Chart, for example + * {@link Chart.xAxis}. + * + * @name Highcharts.Axis#coll + * @type {string} + */ + axis.coll = axis.coll || (isXAxis ? 'xAxis' : 'yAxis'); + fireEvent(this, 'init', { userOptions: userOptions }); + axis.opposite = userOptions.opposite; // needed in setOptions + /** + * The side on which the axis is rendered. 0 is top, 1 is right, 2 + * is bottom and 3 is left. + * + * @name Highcharts.Axis#side + * @type {number} + */ + axis.side = userOptions.side || (axis.horiz ? + (axis.opposite ? 0 : 2) : // top : bottom + (axis.opposite ? 1 : 3)); // right : left + /** + * Current options for the axis after merge of defaults and user's + * options. + * + * @name Highcharts.Axis#options + * @type {Highcharts.AxisOptions} + */ + axis.setOptions(userOptions); + var options = this.options, type = options.type; + axis.labelFormatter = (options.labels.formatter || + // can be overwritten by dynamic format + axis.defaultLabelFormatter); + /** + * User's options for this axis without defaults. + * + * @name Highcharts.Axis#userOptions + * @type {Highcharts.AxisOptions} + */ + axis.userOptions = userOptions; + axis.minPixelPadding = 0; + /** + * Whether the axis is reversed. Based on the `axis.reversed`, + * option, but inverted charts have reversed xAxis by default. + * + * @name Highcharts.Axis#reversed + * @type {boolean} + */ + axis.reversed = options.reversed; + axis.visible = options.visible !== false; + axis.zoomEnabled = options.zoomEnabled !== false; + // Initial categories + axis.hasNames = + type === 'category' || options.categories === true; + /** + * If categories are present for the axis, names are used instead of + * numbers for that axis. + * + * Since Highcharts 3.0, categories can also be extracted by giving each + * point a name and setting axis type to `category`. However, if you + * have multiple series, best practice remains defining the `categories` + * array. + * + * @see [xAxis.categories](/highcharts/xAxis.categories) + * + * @name Highcharts.Axis#categories + * @type {Array} + * @readonly + */ + axis.categories = options.categories || axis.hasNames; + if (!axis.names) { // Preserve on update (#3830) + axis.names = []; + axis.names.keys = {}; + } + // Placeholder for plotlines and plotbands groups + axis.plotLinesAndBandsGroups = {}; + // Shorthand types + axis.positiveValuesOnly = !!(axis.logarithmic && !options.allowNegativeLog); + // Flag, if axis is linked to another axis + axis.isLinked = defined(options.linkedTo); + /** + * List of major ticks mapped by postition on axis. + * + * @see {@link Highcharts.Tick} + * + * @name Highcharts.Axis#ticks + * @type {Highcharts.Dictionary} + */ + axis.ticks = {}; + axis.labelEdge = []; + /** + * List of minor ticks mapped by position on the axis. + * + * @see {@link Highcharts.Tick} + * + * @name Highcharts.Axis#minorTicks + * @type {Highcharts.Dictionary} + */ + axis.minorTicks = {}; + // List of plotLines/Bands + axis.plotLinesAndBands = []; + // Alternate bands + axis.alternateBands = {}; + // Axis metrics + axis.len = 0; + axis.minRange = axis.userMinRange = options.minRange || options.maxZoom; + axis.range = options.range; + axis.offset = options.offset || 0; + /** + * The maximum value of the axis. In a logarithmic axis, this is the + * logarithm of the real value, and the real value can be obtained from + * {@link Axis#getExtremes}. + * + * @name Highcharts.Axis#max + * @type {number|null} + */ + axis.max = null; + /** + * The minimum value of the axis. In a logarithmic axis, this is the + * logarithm of the real value, and the real value can be obtained from + * {@link Axis#getExtremes}. + * + * @name Highcharts.Axis#min + * @type {number|null} + */ + axis.min = null; + /** + * The processed crosshair options. + * + * @name Highcharts.Axis#crosshair + * @type {boolean|Highcharts.AxisCrosshairOptions} + */ + axis.crosshair = pick(options.crosshair, splat(chart.options.tooltip.crosshairs)[isXAxis ? 0 : 1], false); + var events = axis.options.events; + // Register. Don't add it again on Axis.update(). + if (chart.axes.indexOf(axis) === -1) { // + if (isXAxis) { // #2713 + chart.axes.splice(chart.xAxis.length, 0, axis); + } + else { + chart.axes.push(axis); + } + chart[axis.coll].push(axis); + } + /** + * All series associated to the axis. + * + * @name Highcharts.Axis#series + * @type {Array} + */ + axis.series = axis.series || []; // populated by Series + // Reversed axis + if (chart.inverted && + !axis.isZAxis && + isXAxis && + typeof axis.reversed === 'undefined') { + axis.reversed = true; + } + axis.labelRotation = axis.options.labels.rotation; + // register event listeners + objectEach(events, function (event, eventType) { + if (isFunction(event)) { + addEvent(axis, eventType, event); + } + }); + fireEvent(this, 'afterInit'); + }; + /** + * Merge and set options. + * + * @private + * @function Highcharts.Axis#setOptions + * + * @param {Highcharts.AxisOptions} userOptions + * Axis options. + * + * @fires Highcharts.Axis#event:afterSetOptions + */ + Axis.prototype.setOptions = function (userOptions) { + this.options = merge(Axis.defaultOptions, (this.coll === 'yAxis') && Axis.defaultYAxisOptions, [ + Axis.defaultTopAxisOptions, + Axis.defaultRightAxisOptions, + Axis.defaultBottomAxisOptions, + Axis.defaultLeftAxisOptions + ][this.side], merge( + // if set in setOptions (#1053): + defaultOptions[this.coll], userOptions)); + fireEvent(this, 'afterSetOptions', { userOptions: userOptions }); + }; + /** + * The default label formatter. The context is a special config object for + * the label. In apps, use the + * [labels.formatter](https://api.highcharts.com/highcharts/xAxis.labels.formatter) + * instead, except when a modification is needed. + * + * @function Highcharts.Axis#defaultLabelFormatter + * + * @param {Highcharts.AxisLabelsFormatterContextObject} this + * Formatter context of axis label. + * + * @return {string} + * The formatted label content. + */ + Axis.prototype.defaultLabelFormatter = function () { + var axis = this.axis, value = this.value, time = axis.chart.time, categories = axis.categories, dateTimeLabelFormat = this.dateTimeLabelFormat, lang = defaultOptions.lang, numericSymbols = lang.numericSymbols, numSymMagnitude = lang.numericSymbolMagnitude || 1000, i = numericSymbols && numericSymbols.length, multi, ret, formatOption = axis.options.labels.format, + // make sure the same symbol is added for all labels on a linear + // axis + numericSymbolDetector = axis.logarithmic ? + Math.abs(value) : + axis.tickInterval; + var chart = this.chart; + var numberFormatter = chart.numberFormatter; + if (formatOption) { + ret = format(formatOption, this, chart); + } + else if (categories) { + ret = value; + } + else if (dateTimeLabelFormat) { // datetime axis + ret = time.dateFormat(dateTimeLabelFormat, value); + } + else if (i && numericSymbolDetector >= 1000) { + // Decide whether we should add a numeric symbol like k (thousands) + // or M (millions). If we are to enable this in tooltip or other + // places as well, we can move this logic to the numberFormatter and + // enable it by a parameter. + while (i-- && typeof ret === 'undefined') { + multi = Math.pow(numSymMagnitude, i + 1); + if ( + // Only accept a numeric symbol when the distance is more + // than a full unit. So for example if the symbol is k, we + // don't accept numbers like 0.5k. + numericSymbolDetector >= multi && + // Accept one decimal before the symbol. Accepts 0.5k but + // not 0.25k. How does this work with the previous? + (value * 10) % multi === 0 && + numericSymbols[i] !== null && + value !== 0) { // #5480 + ret = numberFormatter(value / multi, -1) + + numericSymbols[i]; + } + } + } + if (typeof ret === 'undefined') { + if (Math.abs(value) >= 10000) { // add thousands separators + ret = numberFormatter(value, -1); + } + else { // small numbers + ret = numberFormatter(value, -1, void 0, ''); // #2466 + } + } + return ret; + }; + /** + * Get the minimum and maximum for the series of each axis. The function + * analyzes the axis series and updates `this.dataMin` and `this.dataMax`. + * + * @private + * @function Highcharts.Axis#getSeriesExtremes + * + * @fires Highcharts.Axis#event:afterGetSeriesExtremes + * @fires Highcharts.Axis#event:getSeriesExtremes + */ + Axis.prototype.getSeriesExtremes = function () { + var axis = this, chart = axis.chart, xExtremes; + fireEvent(this, 'getSeriesExtremes', null, function () { + axis.hasVisibleSeries = false; + // Reset properties in case we're redrawing (#3353) + axis.dataMin = axis.dataMax = axis.threshold = null; + axis.softThreshold = !axis.isXAxis; + if (axis.stacking) { + axis.stacking.buildStacks(); + } + // loop through this axis' series + axis.series.forEach(function (series) { + if (series.visible || + !chart.options.chart.ignoreHiddenSeries) { + var seriesOptions = series.options, xData, threshold = seriesOptions.threshold, seriesDataMin, seriesDataMax; + axis.hasVisibleSeries = true; + // Validate threshold in logarithmic axes + if (axis.positiveValuesOnly && threshold <= 0) { + threshold = null; + } + // Get dataMin and dataMax for X axes + if (axis.isXAxis) { + xData = series.xData; + if (xData.length) { + xExtremes = series.getXExtremes(xData); + // If xData contains values which is not numbers, + // then filter them out. To prevent performance hit, + // we only do this after we have already found + // seriesDataMin because in most cases all data is + // valid. #5234. + seriesDataMin = xExtremes.min; + seriesDataMax = xExtremes.max; + if (!isNumber(seriesDataMin) && + // #5010: + !(seriesDataMin instanceof Date)) { + xData = xData.filter(isNumber); + xExtremes = series.getXExtremes(xData); + // Do it again with valid data + seriesDataMin = xExtremes.min; + seriesDataMax = xExtremes.max; + } + if (xData.length) { + axis.dataMin = Math.min(pick(axis.dataMin, seriesDataMin), seriesDataMin); + axis.dataMax = Math.max(pick(axis.dataMax, seriesDataMax), seriesDataMax); + } + } + // Get dataMin and dataMax for Y axes, as well as handle + // stacking and processed data + } + else { + // Get this particular series extremes + var dataExtremes = series.applyExtremes(); + // Get the dataMin and dataMax so far. If percentage is + // used, the min and max are always 0 and 100. If + // seriesDataMin and seriesDataMax is null, then series + // doesn't have active y data, we continue with nulls + if (isNumber(dataExtremes.dataMin)) { + seriesDataMin = dataExtremes.dataMin; + axis.dataMin = Math.min(pick(axis.dataMin, seriesDataMin), seriesDataMin); + } + if (isNumber(dataExtremes.dataMax)) { + seriesDataMax = dataExtremes.dataMax; + axis.dataMax = Math.max(pick(axis.dataMax, seriesDataMax), seriesDataMax); + } + // Adjust to threshold + if (defined(threshold)) { + axis.threshold = threshold; + } + // If any series has a hard threshold, it takes + // precedence + if (!seriesOptions.softThreshold || + axis.positiveValuesOnly) { + axis.softThreshold = false; + } + } + } + }); + }); + fireEvent(this, 'afterGetSeriesExtremes'); + }; + /** + * Translate from axis value to pixel position on the chart, or back. Use + * the `toPixels` and `toValue` functions in applications. + * + * @private + * @function Highcharts.Axis#translate + * + * @param {number} val + * TO-DO: parameter description + * + * @param {boolean|null} [backwards] + * TO-DO: parameter description + * + * @param {boolean|null} [cvsCoord] + * TO-DO: parameter description + * + * @param {boolean|null} [old] + * TO-DO: parameter description + * + * @param {boolean} [handleLog] + * TO-DO: parameter description + * + * @param {number} [pointPlacement] + * TO-DO: parameter description + * + * @return {number|undefined} + */ + Axis.prototype.translate = function (val, backwards, cvsCoord, old, handleLog, pointPlacement) { + var axis = this.linkedParent || this, // #1417 + sign = 1, cvsOffset = 0, localA = old ? axis.oldTransA : axis.transA, localMin = old ? axis.oldMin : axis.min, returnValue = 0, minPixelPadding = axis.minPixelPadding, doPostTranslate = (axis.isOrdinal || + axis.brokenAxis && axis.brokenAxis.hasBreaks || + (axis.logarithmic && handleLog)) && axis.lin2val; + if (!localA) { + localA = axis.transA; + } + // In vertical axes, the canvas coordinates start from 0 at the top like + // in SVG. + if (cvsCoord) { + sign *= -1; // canvas coordinates inverts the value + cvsOffset = axis.len; + } + // Handle reversed axis + if (axis.reversed) { + sign *= -1; + cvsOffset -= sign * (axis.sector || axis.len); + } + // From pixels to value + if (backwards) { // reverse translation + val = val * sign + cvsOffset; + val -= minPixelPadding; + // from chart pixel to value: + returnValue = val / localA + localMin; + if (doPostTranslate) { // log and ordinal axes + returnValue = axis.lin2val(returnValue); + } + // From value to pixels + } + else { + if (doPostTranslate) { // log and ordinal axes + val = axis.val2lin(val); + } + returnValue = isNumber(localMin) ? + (sign * (val - localMin) * localA + + cvsOffset + + (sign * minPixelPadding) + + (isNumber(pointPlacement) ? + localA * pointPlacement : + 0)) : + void 0; + } + return returnValue; + }; + /** + * Translate a value in terms of axis units into pixels within the chart. + * + * @function Highcharts.Axis#toPixels + * + * @param {number} value + * A value in terms of axis units. + * + * @param {boolean} paneCoordinates + * Whether to return the pixel coordinate relative to the chart or just the + * axis/pane itself. + * + * @return {number} + * Pixel position of the value on the chart or axis. + */ + Axis.prototype.toPixels = function (value, paneCoordinates) { + return this.translate(value, false, !this.horiz, null, true) + + (paneCoordinates ? 0 : this.pos); + }; + /** + * Translate a pixel position along the axis to a value in terms of axis + * units. + * + * @function Highcharts.Axis#toValue + * + * @param {number} pixel + * The pixel value coordinate. + * + * @param {boolean} [paneCoordinates=false] + * Whether the input pixel is relative to the chart or just the axis/pane + * itself. + * + * @return {number} + * The axis value. + */ + Axis.prototype.toValue = function (pixel, paneCoordinates) { + return this.translate(pixel - (paneCoordinates ? 0 : this.pos), true, !this.horiz, null, true); + }; + /** + * Create the path for a plot line that goes from the given value on + * this axis, across the plot to the opposite side. Also used internally for + * grid lines and crosshairs. + * + * @function Highcharts.Axis#getPlotLinePath + * + * @param {Highcharts.AxisPlotLinePathOptionsObject} options + * Options for the path. + * + * @return {Highcharts.SVGPathArray|null} + * The SVG path definition for the plot line. + */ + Axis.prototype.getPlotLinePath = function (options) { + var axis = this, chart = axis.chart, axisLeft = axis.left, axisTop = axis.top, old = options.old, value = options.value, translatedValue = options.translatedValue, lineWidth = options.lineWidth, force = options.force, x1, y1, x2, y2, cHeight = (old && chart.oldChartHeight) || chart.chartHeight, cWidth = (old && chart.oldChartWidth) || chart.chartWidth, skip, transB = axis.transB, evt; + // eslint-disable-next-line valid-jsdoc + /** + * Check if x is between a and b. If not, either move to a/b + * or skip, depending on the force parameter. + * @private + */ + function between(x, a, b) { + if (force !== 'pass' && x < a || x > b) { + if (force) { + x = clamp(x, a, b); + } + else { + skip = true; + } + } + return x; + } + evt = { + value: value, + lineWidth: lineWidth, + old: old, + force: force, + acrossPanes: options.acrossPanes, + translatedValue: translatedValue + }; + fireEvent(this, 'getPlotLinePath', evt, function (e) { + translatedValue = pick(translatedValue, axis.translate(value, null, null, old)); + // Keep the translated value within sane bounds, and avoid Infinity + // to fail the isNumber test (#7709). + translatedValue = clamp(translatedValue, -1e5, 1e5); + x1 = x2 = Math.round(translatedValue + transB); + y1 = y2 = Math.round(cHeight - translatedValue - transB); + if (!isNumber(translatedValue)) { // no min or max + skip = true; + force = false; // #7175, don't force it when path is invalid + } + else if (axis.horiz) { + y1 = axisTop; + y2 = cHeight - axis.bottom; + x1 = x2 = between(x1, axisLeft, axisLeft + axis.width); + } + else { + x1 = axisLeft; + x2 = cWidth - axis.right; + y1 = y2 = between(y1, axisTop, axisTop + axis.height); + } + e.path = skip && !force ? + null : + chart.renderer.crispLine([['M', x1, y1], ['L', x2, y2]], lineWidth || 1); + }); + return evt.path; + }; + /** + * Internal function to et the tick positions of a linear axis to round + * values like whole tens or every five. + * + * @function Highcharts.Axis#getLinearTickPositions + * + * @param {number} tickInterval + * The normalized tick interval. + * + * @param {number} min + * Axis minimum. + * + * @param {number} max + * Axis maximum. + * + * @return {Array} + * An array of axis values where ticks should be placed. + */ + Axis.prototype.getLinearTickPositions = function (tickInterval, min, max) { + var pos, lastPos, roundedMin = correctFloat(Math.floor(min / tickInterval) * tickInterval), roundedMax = correctFloat(Math.ceil(max / tickInterval) * tickInterval), tickPositions = [], precision; + // When the precision is higher than what we filter out in + // correctFloat, skip it (#6183). + if (correctFloat(roundedMin + tickInterval) === roundedMin) { + precision = 20; + } + // For single points, add a tick regardless of the relative position + // (#2662, #6274) + if (this.single) { + return [min]; + } + // Populate the intermediate values + pos = roundedMin; + while (pos <= roundedMax) { + // Place the tick on the rounded value + tickPositions.push(pos); + // Always add the raw tickInterval, not the corrected one. + pos = correctFloat(pos + tickInterval, precision); + // If the interval is not big enough in the current min - max range + // to actually increase the loop variable, we need to break out to + // prevent endless loop. Issue #619 + if (pos === lastPos) { + break; + } + // Record the last value + lastPos = pos; + } + return tickPositions; + }; + /** + * Resolve the new minorTicks/minorTickInterval options into the legacy + * loosely typed minorTickInterval option. + * + * @function Highcharts.Axis#getMinorTickInterval + * + * @return {number|"auto"|null} + */ + Axis.prototype.getMinorTickInterval = function () { + var options = this.options; + if (options.minorTicks === true) { + return pick(options.minorTickInterval, 'auto'); + } + if (options.minorTicks === false) { + return null; + } + return options.minorTickInterval; + }; + /** + * Internal function to return the minor tick positions. For logarithmic + * axes, the same logic as for major ticks is reused. + * + * @function Highcharts.Axis#getMinorTickPositions + * + * @return {Array} + * An array of axis values where ticks should be placed. + */ + Axis.prototype.getMinorTickPositions = function () { + var axis = this, options = axis.options, tickPositions = axis.tickPositions, minorTickInterval = axis.minorTickInterval, minorTickPositions = [], pos, pointRangePadding = axis.pointRangePadding || 0, min = axis.min - pointRangePadding, // #1498 + max = axis.max + pointRangePadding, // #1498 + range = max - min; + // If minor ticks get too dense, they are hard to read, and may cause + // long running script. So we don't draw them. + if (range && range / minorTickInterval < axis.len / 3) { // #3875 + var logarithmic_1 = axis.logarithmic; + if (logarithmic_1) { + // For each interval in the major ticks, compute the minor ticks + // separately. + this.paddedTicks.forEach(function (_pos, i, paddedTicks) { + if (i) { + minorTickPositions.push.apply(minorTickPositions, logarithmic_1.getLogTickPositions(minorTickInterval, paddedTicks[i - 1], paddedTicks[i], true)); + } + }); + } + else if (axis.dateTime && + this.getMinorTickInterval() === 'auto') { // #1314 + minorTickPositions = minorTickPositions.concat(axis.getTimeTicks(axis.dateTime.normalizeTimeTickInterval(minorTickInterval), min, max, options.startOfWeek)); + } + else { + for (pos = min + (tickPositions[0] - min) % minorTickInterval; pos <= max; pos += minorTickInterval) { + // Very, very, tight grid lines (#5771) + if (pos === minorTickPositions[0]) { + break; + } + minorTickPositions.push(pos); + } + } + } + if (minorTickPositions.length !== 0) { + axis.trimTicks(minorTickPositions); // #3652 #3743 #1498 #6330 + } + return minorTickPositions; + }; + /** + * Adjust the min and max for the minimum range. Keep in mind that the + * series data is not yet processed, so we don't have information on data + * cropping and grouping, or updated `axis.pointRange` or + * `series.pointRange`. The data can't be processed until we have finally + * established min and max. + * + * @private + * @function Highcharts.Axis#adjustForMinRange + */ + Axis.prototype.adjustForMinRange = function () { + var axis = this, options = axis.options, min = axis.min, max = axis.max, log = axis.logarithmic, zoomOffset, spaceAvailable, closestDataRange, i, distance, xData, loopLength, minArgs, maxArgs, minRange; + // Set the automatic minimum range based on the closest point distance + if (axis.isXAxis && + typeof axis.minRange === 'undefined' && + !log) { + if (defined(options.min) || defined(options.max)) { + axis.minRange = null; // don't do this again + } + else { + // Find the closest distance between raw data points, as opposed + // to closestPointRange that applies to processed points + // (cropped and grouped) + axis.series.forEach(function (series) { + xData = series.xData; + loopLength = series.xIncrement ? 1 : xData.length - 1; + for (i = loopLength; i > 0; i--) { + distance = xData[i] - xData[i - 1]; + if (typeof closestDataRange === 'undefined' || + distance < closestDataRange) { + closestDataRange = distance; + } + } + }); + axis.minRange = Math.min(closestDataRange * 5, axis.dataMax - axis.dataMin); + } + } + // if minRange is exceeded, adjust + if (max - min < axis.minRange) { + spaceAvailable = + axis.dataMax - axis.dataMin >= + axis.minRange; + minRange = axis.minRange; + zoomOffset = (minRange - max + min) / 2; + // if min and max options have been set, don't go beyond it + minArgs = [ + min - zoomOffset, + pick(options.min, min - zoomOffset) + ]; + // If space is available, stay within the data range + if (spaceAvailable) { + minArgs[2] = axis.logarithmic ? + axis.logarithmic.log2lin(axis.dataMin) : + axis.dataMin; + } + min = arrayMax(minArgs); + maxArgs = [ + min + minRange, + pick(options.max, min + minRange) + ]; + // If space is availabe, stay within the data range + if (spaceAvailable) { + maxArgs[2] = log ? + log.log2lin(axis.dataMax) : + axis.dataMax; + } + max = arrayMin(maxArgs); + // now if the max is adjusted, adjust the min back + if (max - min < minRange) { + minArgs[0] = max - minRange; + minArgs[1] = pick(options.min, max - minRange); + min = arrayMax(minArgs); + } + } + // Record modified extremes + axis.min = min; + axis.max = max; + }; + // eslint-disable-next-line valid-jsdoc + /** + * Find the closestPointRange across all series. + * + * @private + * @function Highcharts.Axis#getClosest + */ + Axis.prototype.getClosest = function () { + var ret; + if (this.categories) { + ret = 1; + } + else { + this.series.forEach(function (series) { + var seriesClosest = series.closestPointRange, visible = series.visible || + !series.chart.options.chart.ignoreHiddenSeries; + if (!series.noSharedTooltip && + defined(seriesClosest) && + visible) { + ret = defined(ret) ? + Math.min(ret, seriesClosest) : + seriesClosest; + } + }); + } + return ret; + }; + /** + * When a point name is given and no x, search for the name in the existing + * categories, or if categories aren't provided, search names or create a + * new category (#2522). + * @private + * @function Highcharts.Axis#nameToX + * + * @param {Highcharts.Point} point + * The point to inspect. + * + * @return {number} + * The X value that the point is given. + */ + Axis.prototype.nameToX = function (point) { + var explicitCategories = isArray(this.categories), names = explicitCategories ? this.categories : this.names, nameX = point.options.x, x; + point.series.requireSorting = false; + if (!defined(nameX)) { + nameX = this.options.uniqueNames === false ? + point.series.autoIncrement() : + (explicitCategories ? + names.indexOf(point.name) : + pick(names.keys[point.name], -1)); + } + if (nameX === -1) { // Not found in currenct categories + if (!explicitCategories) { + x = names.length; + } + } + else { + x = nameX; + } + // Write the last point's name to the names array + if (typeof x !== 'undefined') { + this.names[x] = point.name; + // Backwards mapping is much faster than array searching (#7725) + this.names.keys[point.name] = x; + } + return x; + }; + /** + * When changes have been done to series data, update the axis.names. + * + * @private + * @function Highcharts.Axis#updateNames + */ + Axis.prototype.updateNames = function () { + var axis = this, names = this.names, i = names.length; + if (i > 0) { + Object.keys(names.keys).forEach(function (key) { + delete (names.keys)[key]; + }); + names.length = 0; + this.minRange = this.userMinRange; // Reset + (this.series || []).forEach(function (series) { + // Reset incrementer (#5928) + series.xIncrement = null; + // When adding a series, points are not yet generated + if (!series.points || series.isDirtyData) { + // When we're updating the series with data that is longer + // than it was, and cropThreshold is passed, we need to make + // sure that the axis.max is increased _before_ running the + // premature processData. Otherwise this early iteration of + // processData will crop the points to axis.max, and the + // names array will be too short (#5857). + axis.max = Math.max(axis.max, series.xData.length - 1); + series.processData(); + series.generatePoints(); + } + series.data.forEach(function (point, i) { + var x; + if (point && + point.options && + typeof point.name !== 'undefined' // #9562 + ) { + x = axis.nameToX(point); + if (typeof x !== 'undefined' && x !== point.x) { + point.x = x; + series.xData[i] = x; + } + } + }); + }); + } + }; + /** + * Update translation information. + * + * @private + * @function Highcharts.Axis#setAxisTranslation + * + * @param {boolean} [saveOld] + * TO-DO: parameter description + * + * @fires Highcharts.Axis#event:afterSetAxisTranslation + */ + Axis.prototype.setAxisTranslation = function (saveOld) { + var axis = this, range = axis.max - axis.min, pointRange = axis.axisPointRange || 0, closestPointRange, minPointOffset = 0, pointRangePadding = 0, linkedParent = axis.linkedParent, ordinalCorrection, hasCategories = !!axis.categories, transA = axis.transA, isXAxis = axis.isXAxis; + // Adjust translation for padding. Y axis with categories need to go + // through the same (#1784). + if (isXAxis || hasCategories || pointRange) { + // Get the closest points + closestPointRange = axis.getClosest(); + if (linkedParent) { + minPointOffset = linkedParent.minPointOffset; + pointRangePadding = linkedParent.pointRangePadding; + } + else { + axis.series.forEach(function (series) { + var seriesPointRange = hasCategories ? + 1 : + (isXAxis ? + pick(series.options.pointRange, closestPointRange, 0) : + (axis.axisPointRange || 0)), // #2806 + pointPlacement = series.options.pointPlacement; + pointRange = Math.max(pointRange, seriesPointRange); + if (!axis.single || hasCategories) { + // TODO: series should internally set x- and y- + // pointPlacement to simplify this logic. + var isPointPlacementAxis = series.is('xrange') ? !isXAxis : isXAxis; + // minPointOffset is the value padding to the left of + // the axis in order to make room for points with a + // pointRange, typically columns. When the + // pointPlacement option is 'between' or 'on', this + // padding does not apply. + minPointOffset = Math.max(minPointOffset, isPointPlacementAxis && isString(pointPlacement) ? + 0 : + seriesPointRange / 2); + // Determine the total padding needed to the length of + // the axis to make room for the pointRange. If the + // series' pointPlacement is 'on', no padding is added. + pointRangePadding = Math.max(pointRangePadding, isPointPlacementAxis && pointPlacement === 'on' ? + 0 : + seriesPointRange); + } + }); + } + // Record minPointOffset and pointRangePadding + ordinalCorrection = axis.ordinal && axis.ordinal.slope && closestPointRange ? + axis.ordinal.slope / closestPointRange : + 1; // #988, #1853 + axis.minPointOffset = minPointOffset = + minPointOffset * ordinalCorrection; + axis.pointRangePadding = + pointRangePadding = pointRangePadding * ordinalCorrection; + // pointRange means the width reserved for each point, like in a + // column chart + axis.pointRange = Math.min(pointRange, axis.single && hasCategories ? 1 : range); + // closestPointRange means the closest distance between points. In + // columns it is mostly equal to pointRange, but in lines pointRange + // is 0 while closestPointRange is some other value + if (isXAxis) { + axis.closestPointRange = closestPointRange; + } + } + // Secondary values + if (saveOld) { + axis.oldTransA = transA; + } + axis.translationSlope = axis.transA = transA = + axis.staticScale || + axis.len / ((range + pointRangePadding) || 1); + // Translation addend + axis.transB = axis.horiz ? axis.left : axis.bottom; + axis.minPixelPadding = transA * minPointOffset; + fireEvent(this, 'afterSetAxisTranslation'); + }; + /** + * @private + * @function Highcharts.Axis#minFromRange + * + * @return {number} + */ + Axis.prototype.minFromRange = function () { + var axis = this; + return axis.max - axis.range; + }; + /** + * Set the tick positions to round values and optionally extend the extremes + * to the nearest tick. + * + * @private + * @function Highcharts.Axis#setTickInterval + * + * @param {boolean} secondPass + * TO-DO: parameter description + * + * @fires Highcharts.Axis#event:foundExtremes + */ + Axis.prototype.setTickInterval = function (secondPass) { + var axis = this, chart = axis.chart, log = axis.logarithmic, options = axis.options, isXAxis = axis.isXAxis, isLinked = axis.isLinked, maxPadding = options.maxPadding, minPadding = options.minPadding, length, linkedParentExtremes, tickIntervalOption = options.tickInterval, minTickInterval, tickPixelIntervalOption = options.tickPixelInterval, categories = axis.categories, threshold = isNumber(axis.threshold) ? axis.threshold : null, softThreshold = axis.softThreshold, thresholdMin, thresholdMax, hardMin, hardMax; + if (!axis.dateTime && !categories && !isLinked) { + this.getTickAmount(); + } + // Min or max set either by zooming/setExtremes or initial options + hardMin = pick(axis.userMin, options.min); + hardMax = pick(axis.userMax, options.max); + // Linked axis gets the extremes from the parent axis + if (isLinked) { + axis.linkedParent = chart[axis.coll][options.linkedTo]; + linkedParentExtremes = axis.linkedParent.getExtremes(); + axis.min = pick(linkedParentExtremes.min, linkedParentExtremes.dataMin); + axis.max = pick(linkedParentExtremes.max, linkedParentExtremes.dataMax); + if (options.type !== axis.linkedParent.options.type) { + // Can't link axes of different type + error(11, 1, chart); + } + // Initial min and max from the extreme data values + } + else { + // Adjust to hard threshold + if (!softThreshold && defined(threshold)) { + if (axis.dataMin >= threshold) { + thresholdMin = threshold; + minPadding = 0; + } + else if (axis.dataMax <= threshold) { + thresholdMax = threshold; + maxPadding = 0; + } + } + axis.min = pick(hardMin, thresholdMin, axis.dataMin); + axis.max = pick(hardMax, thresholdMax, axis.dataMax); + } + if (log) { + if (axis.positiveValuesOnly && + !secondPass && + Math.min(axis.min, pick(axis.dataMin, axis.min)) <= 0) { // #978 + // Can't plot negative values on log axis + error(10, 1, chart); + } + // The correctFloat cures #934, float errors on full tens. But it + // was too aggressive for #4360 because of conversion back to lin, + // therefore use precision 15. + axis.min = correctFloat(log.log2lin(axis.min), 16); + axis.max = correctFloat(log.log2lin(axis.max), 16); + } + // handle zoomed range + if (axis.range && defined(axis.max)) { + // #618, #6773: + axis.userMin = axis.min = hardMin = + Math.max(axis.dataMin, axis.minFromRange()); + axis.userMax = hardMax = axis.max; + axis.range = null; // don't use it when running setExtremes + } + // Hook for Highstock Scroller. Consider combining with beforePadding. + fireEvent(axis, 'foundExtremes'); + // Hook for adjusting this.min and this.max. Used by bubble series. + if (axis.beforePadding) { + axis.beforePadding(); + } + // adjust min and max for the minimum range + axis.adjustForMinRange(); + // Pad the values to get clear of the chart's edges. To avoid + // tickInterval taking the padding into account, we do this after + // computing tick interval (#1337). + if (!categories && + !axis.axisPointRange && + !(axis.stacking && axis.stacking.usePercentage) && + !isLinked && + defined(axis.min) && + defined(axis.max)) { + length = axis.max - axis.min; + if (length) { + if (!defined(hardMin) && minPadding) { + axis.min -= length * minPadding; + } + if (!defined(hardMax) && maxPadding) { + axis.max += length * maxPadding; + } + } + } + // Handle options for floor, ceiling, softMin and softMax (#6359) + if (!isNumber(axis.userMin)) { + if (isNumber(options.softMin) && options.softMin < axis.min) { + axis.min = hardMin = options.softMin; // #6894 + } + if (isNumber(options.floor)) { + axis.min = Math.max(axis.min, options.floor); + } + } + if (!isNumber(axis.userMax)) { + if (isNumber(options.softMax) && options.softMax > axis.max) { + axis.max = hardMax = options.softMax; // #6894 + } + if (isNumber(options.ceiling)) { + axis.max = Math.min(axis.max, options.ceiling); + } + } + // When the threshold is soft, adjust the extreme value only if the data + // extreme and the padded extreme land on either side of the threshold. + // For example, a series of [0, 1, 2, 3] would make the yAxis add a tick + // for -1 because of the default minPadding and startOnTick options. + // This is prevented by the softThreshold option. + if (softThreshold && defined(axis.dataMin)) { + threshold = threshold || 0; + if (!defined(hardMin) && + axis.min < threshold && + axis.dataMin >= threshold) { + axis.min = axis.options.minRange ? + Math.min(threshold, axis.max - + axis.minRange) : + threshold; + } + else if (!defined(hardMax) && + axis.max > threshold && + axis.dataMax <= threshold) { + axis.max = axis.options.minRange ? + Math.max(threshold, axis.min + + axis.minRange) : + threshold; + } + } + // get tickInterval + if (axis.min === axis.max || + typeof axis.min === 'undefined' || + typeof axis.max === 'undefined') { + axis.tickInterval = 1; + } + else if (isLinked && + !tickIntervalOption && + tickPixelIntervalOption === + axis.linkedParent.options.tickPixelInterval) { + axis.tickInterval = tickIntervalOption = + axis.linkedParent.tickInterval; + } + else { + axis.tickInterval = pick(tickIntervalOption, this.tickAmount ? + ((axis.max - axis.min) / + Math.max(this.tickAmount - 1, 1)) : + void 0, + // For categoried axis, 1 is default, for linear axis use + // tickPix + categories ? + 1 : + // don't let it be more than the data range + (axis.max - axis.min) * + tickPixelIntervalOption / + Math.max(axis.len, tickPixelIntervalOption)); + } + // Now we're finished detecting min and max, crop and group series data. + // This is in turn needed in order to find tick positions in ordinal + // axes. + if (isXAxis && !secondPass) { + axis.series.forEach(function (series) { + series.processData(axis.min !== axis.oldMin || axis.max !== axis.oldMax); + }); + } + // set the translation factor used in translate function + axis.setAxisTranslation(true); + // hook for ordinal axes and radial axes + if (axis.beforeSetTickPositions) { + axis.beforeSetTickPositions(); + } + // hook for extensions, used in Highstock ordinal axes + if (axis.ordinal) { + axis.tickInterval = axis.ordinal.postProcessTickInterval(axis.tickInterval); + } + // In column-like charts, don't cramp in more ticks than there are + // points (#1943, #4184) + if (axis.pointRange && !tickIntervalOption) { + axis.tickInterval = Math.max(axis.pointRange, axis.tickInterval); + } + // Before normalizing the tick interval, handle minimum tick interval. + // This applies only if tickInterval is not defined. + minTickInterval = pick(options.minTickInterval, (axis.dateTime && axis.closestPointRange)); + if (!tickIntervalOption && axis.tickInterval < minTickInterval) { + axis.tickInterval = minTickInterval; + } + // for linear axes, get magnitude and normalize the interval + if (!axis.dateTime && !axis.logarithmic && !tickIntervalOption) { + axis.tickInterval = normalizeTickInterval(axis.tickInterval, void 0, getMagnitude(axis.tickInterval), pick(options.allowDecimals, + // If the tick interval is greather than 0.5, avoid + // decimals, as linear axes are often used to render + // discrete values. #3363. If a tick amount is set, allow + // decimals by default, as it increases the chances for a + // good fit. + axis.tickInterval < 0.5 || this.tickAmount !== void 0), !!this.tickAmount); + } + // Prevent ticks from getting so close that we can't draw the labels + if (!this.tickAmount) { + axis.tickInterval = axis.unsquish(); + } + this.setTickPositions(); + }; + /** + * Now we have computed the normalized tickInterval, get the tick positions + * + * @function Highcharts.Axis#setTickPositions + * + * @fires Highcharts.Axis#event:afterSetTickPositions + */ + Axis.prototype.setTickPositions = function () { + var axis = this, options = this.options, tickPositions, tickPositionsOption = options.tickPositions, minorTickIntervalOption = this.getMinorTickInterval(), tickPositioner = options.tickPositioner, hasVerticalPanning = this.hasVerticalPanning(), isColorAxis = this.coll === 'colorAxis', startOnTick = (isColorAxis || !hasVerticalPanning) && options.startOnTick, endOnTick = (isColorAxis || !hasVerticalPanning) && options.endOnTick; + // Set the tickmarkOffset + this.tickmarkOffset = (this.categories && + options.tickmarkPlacement === 'between' && + this.tickInterval === 1) ? 0.5 : 0; // #3202 + // get minorTickInterval + this.minorTickInterval = + minorTickIntervalOption === 'auto' && + this.tickInterval ? + this.tickInterval / 5 : + minorTickIntervalOption; + // When there is only one point, or all points have the same value on + // this axis, then min and max are equal and tickPositions.length is 0 + // or 1. In this case, add some padding in order to center the point, + // but leave it with one tick. #1337. + this.single = + this.min === this.max && + defined(this.min) && + !this.tickAmount && + ( + // Data is on integer (#6563) + parseInt(this.min, 10) === this.min || + // Between integers and decimals are not allowed (#6274) + options.allowDecimals !== false); + /** + * Contains the current positions that are laid out on the axis. The + * positions are numbers in terms of axis values. In a category axis + * they are integers, in a datetime axis they are also integers, but + * designating milliseconds. + * + * This property is read only - for modifying the tick positions, use + * the `tickPositioner` callback or [axis.tickPositions( + * https://api.highcharts.com/highcharts/xAxis.tickPositions) option + * instead. + * + * @name Highcharts.Axis#tickPositions + * @type {Highcharts.AxisTickPositionsArray|undefined} + */ + this.tickPositions = + // Find the tick positions. Work on a copy (#1565) + tickPositions = + (tickPositionsOption && tickPositionsOption.slice()); + if (!tickPositions) { + // Too many ticks (#6405). Create a friendly warning and provide two + // ticks so at least we can show the data series. + if ((!axis.ordinal || !axis.ordinal.positions) && + ((this.max - this.min) / + this.tickInterval > + Math.max(2 * this.len, 200))) { + tickPositions = [this.min, this.max]; + error(19, false, this.chart); + } + else if (axis.dateTime) { + tickPositions = axis.getTimeTicks(axis.dateTime.normalizeTimeTickInterval(this.tickInterval, options.units), this.min, this.max, options.startOfWeek, axis.ordinal && axis.ordinal.positions, this.closestPointRange, true); + } + else if (axis.logarithmic) { + tickPositions = axis.logarithmic.getLogTickPositions(this.tickInterval, this.min, this.max); + } + else { + tickPositions = this.getLinearTickPositions(this.tickInterval, this.min, this.max); + } + // Too dense ticks, keep only the first and last (#4477) + if (tickPositions.length > this.len) { + tickPositions = [tickPositions[0], tickPositions.pop()]; + // Reduce doubled value (#7339) + if (tickPositions[0] === tickPositions[1]) { + tickPositions.length = 1; + } + } + this.tickPositions = tickPositions; + // Run the tick positioner callback, that allows modifying auto tick + // positions. + if (tickPositioner) { + tickPositioner = tickPositioner.apply(axis, [this.min, this.max]); + if (tickPositioner) { + this.tickPositions = tickPositions = tickPositioner; + } + } + } + // Reset min/max or remove extremes based on start/end on tick + this.paddedTicks = tickPositions.slice(0); // Used for logarithmic minor + this.trimTicks(tickPositions, startOnTick, endOnTick); + if (!this.isLinked) { + // Substract half a unit (#2619, #2846, #2515, #3390), + // but not in case of multiple ticks (#6897) + if (this.single && + tickPositions.length < 2 && + !this.categories && + !this.series.some(function (s) { + return (s.is('heatmap') && s.options.pointPlacement === 'between'); + })) { + this.min -= 0.5; + this.max += 0.5; + } + if (!tickPositionsOption && !tickPositioner) { + this.adjustTickAmount(); + } + } + fireEvent(this, 'afterSetTickPositions'); + }; + /** + * Handle startOnTick and endOnTick by either adapting to padding min/max or + * rounded min/max. Also handle single data points. + * + * @private + * @function Highcharts.Axis#trimTicks + * + * @param {Array} tickPositions + * TO-DO: parameter description + * + * @param {boolean} [startOnTick] + * TO-DO: parameter description + * + * @param {boolean} [endOnTick] + * TO-DO: parameter description + */ + Axis.prototype.trimTicks = function (tickPositions, startOnTick, endOnTick) { + var roundedMin = tickPositions[0], roundedMax = tickPositions[tickPositions.length - 1], minPointOffset = (!this.isOrdinal && this.minPointOffset) || 0; // (#12716) + fireEvent(this, 'trimTicks'); + if (!this.isLinked) { + if (startOnTick && roundedMin !== -Infinity) { // #6502 + this.min = roundedMin; + } + else { + while (this.min - minPointOffset > tickPositions[0]) { + tickPositions.shift(); + } + } + if (endOnTick) { + this.max = roundedMax; + } + else { + while (this.max + minPointOffset < + tickPositions[tickPositions.length - 1]) { + tickPositions.pop(); + } + } + // If no tick are left, set one tick in the middle (#3195) + if (tickPositions.length === 0 && + defined(roundedMin) && + !this.options.tickPositions) { + tickPositions.push((roundedMax + roundedMin) / 2); + } + } + }; + /** + * Check if there are multiple axes in the same pane. + * + * @private + * @function Highcharts.Axis#alignToOthers + * + * @return {boolean|undefined} + * True if there are other axes. + */ + Axis.prototype.alignToOthers = function () { + var axis = this, others = // Whether there is another axis to pair with this one + {}, hasOther, options = axis.options; + if ( + // Only if alignTicks is true + this.chart.options.chart.alignTicks !== false && + options.alignTicks !== false && + // Disabled when startOnTick or endOnTick are false (#7604) + options.startOnTick !== false && + options.endOnTick !== false && + // Don't try to align ticks on a log axis, they are not evenly + // spaced (#6021) + !axis.logarithmic) { + this.chart[this.coll].forEach(function (axis) { + var otherOptions = axis.options, horiz = axis.horiz, key = [ + horiz ? otherOptions.left : otherOptions.top, + otherOptions.width, + otherOptions.height, + otherOptions.pane + ].join(','); + if (axis.series.length) { // #4442 + if (others[key]) { + hasOther = true; // #4201 + } + else { + others[key] = 1; + } + } + }); + } + return hasOther; + }; + /** + * Find the max ticks of either the x and y axis collection, and record it + * in `this.tickAmount`. + * + * @private + * @function Highcharts.Axis#getTickAmount + */ + Axis.prototype.getTickAmount = function () { + var axis = this, options = this.options, tickAmount = options.tickAmount, tickPixelInterval = options.tickPixelInterval; + if (!defined(options.tickInterval) && + !tickAmount && this.len < tickPixelInterval && + !this.isRadial && + !axis.logarithmic && + options.startOnTick && + options.endOnTick) { + tickAmount = 2; + } + if (!tickAmount && this.alignToOthers()) { + // Add 1 because 4 tick intervals require 5 ticks (including first + // and last) + tickAmount = Math.ceil(this.len / tickPixelInterval) + 1; + } + // For tick amounts of 2 and 3, compute five ticks and remove the + // intermediate ones. This prevents the axis from adding ticks that are + // too far away from the data extremes. + if (tickAmount < 4) { + this.finalTickAmt = tickAmount; + tickAmount = 5; + } + this.tickAmount = tickAmount; + }; + /** + * When using multiple axes, adjust the number of ticks to match the highest + * number of ticks in that group. + * + * @private + * @function Highcharts.Axis#adjustTickAmount + */ + Axis.prototype.adjustTickAmount = function () { + var axis = this, axisOptions = axis.options, tickInterval = axis.tickInterval, tickPositions = axis.tickPositions, tickAmount = axis.tickAmount, finalTickAmt = axis.finalTickAmt, currentTickAmount = tickPositions && tickPositions.length, threshold = pick(axis.threshold, axis.softThreshold ? 0 : null), min, len, i; + if (axis.hasData()) { + if (currentTickAmount < tickAmount) { + min = axis.min; + while (tickPositions.length < tickAmount) { + // Extend evenly for both sides unless we're on the + // threshold (#3965) + if (tickPositions.length % 2 || + min === threshold) { + // to the end + tickPositions.push(correctFloat(tickPositions[tickPositions.length - 1] + + tickInterval)); + } + else { + // to the start + tickPositions.unshift(correctFloat(tickPositions[0] - tickInterval)); + } + } + axis.transA *= (currentTickAmount - 1) / (tickAmount - 1); + // Do not crop when ticks are not extremes (#9841) + axis.min = axisOptions.startOnTick ? + tickPositions[0] : + Math.min(axis.min, tickPositions[0]); + axis.max = axisOptions.endOnTick ? + tickPositions[tickPositions.length - 1] : + Math.max(axis.max, tickPositions[tickPositions.length - 1]); + // We have too many ticks, run second pass to try to reduce ticks + } + else if (currentTickAmount > tickAmount) { + axis.tickInterval *= 2; + axis.setTickPositions(); + } + // The finalTickAmt property is set in getTickAmount + if (defined(finalTickAmt)) { + i = len = tickPositions.length; + while (i--) { + if ( + // Remove every other tick + (finalTickAmt === 3 && i % 2 === 1) || + // Remove all but first and last + (finalTickAmt <= 2 && i > 0 && i < len - 1)) { + tickPositions.splice(i, 1); + } + } + axis.finalTickAmt = void 0; + } + } + }; + /** + * Set the scale based on data min and max, user set min and max or options. + * + * @private + * @function Highcharts.Axis#setScale + * + * @fires Highcharts.Axis#event:afterSetScale + */ + Axis.prototype.setScale = function () { + var axis = this, isDirtyAxisLength, isDirtyData = false, isXAxisDirty = false; + axis.series.forEach(function (series) { + var _a; + isDirtyData = isDirtyData || series.isDirtyData || series.isDirty; + // When x axis is dirty, we need new data extremes for y as + // well: + isXAxisDirty = isXAxisDirty || ((_a = series.xAxis) === null || _a === void 0 ? void 0 : _a.isDirty) || false; + }); + axis.oldMin = axis.min; + axis.oldMax = axis.max; + axis.oldAxisLength = axis.len; + // set the new axisLength + axis.setAxisSize(); + isDirtyAxisLength = axis.len !== axis.oldAxisLength; + // do we really need to go through all this? + if (isDirtyAxisLength || + isDirtyData || + isXAxisDirty || + axis.isLinked || + axis.forceRedraw || + axis.userMin !== axis.oldUserMin || + axis.userMax !== axis.oldUserMax || + axis.alignToOthers()) { + if (axis.stacking) { + axis.stacking.resetStacks(); + } + axis.forceRedraw = false; + // get data extremes if needed + axis.getSeriesExtremes(); + // get fixed positions based on tickInterval + axis.setTickInterval(); + // record old values to decide whether a rescale is necessary later + // on (#540) + axis.oldUserMin = axis.userMin; + axis.oldUserMax = axis.userMax; + // Mark as dirty if it is not already set to dirty and extremes have + // changed. #595. + if (!axis.isDirty) { + axis.isDirty = + isDirtyAxisLength || + axis.min !== axis.oldMin || + axis.max !== axis.oldMax; + } + } + else if (axis.stacking) { + axis.stacking.cleanStacks(); + } + // Recalculate panning state object, when the data + // has changed. It is required when vertical panning is enabled. + if (isDirtyData && axis.panningState) { + axis.panningState.isDirty = true; + } + fireEvent(this, 'afterSetScale'); + }; + /** + * Set the minimum and maximum of the axes after render time. If the + * `startOnTick` and `endOnTick` options are true, the minimum and maximum + * values are rounded off to the nearest tick. To prevent this, these + * options can be set to false before calling setExtremes. Also, setExtremes + * will not allow a range lower than the `minRange` option, which by default + * is the range of five points. + * + * @sample highcharts/members/axis-setextremes/ + * Set extremes from a button + * @sample highcharts/members/axis-setextremes-datetime/ + * Set extremes on a datetime axis + * @sample highcharts/members/axis-setextremes-off-ticks/ + * Set extremes off ticks + * @sample stock/members/axis-setextremes/ + * Set extremes in Highstock + * @sample maps/members/axis-setextremes/ + * Set extremes in Highmaps + * + * @function Highcharts.Axis#setExtremes + * + * @param {number} [newMin] + * The new minimum value. + * + * @param {number} [newMax] + * The new maximum value. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call to + * {@link Highcharts.Chart#redraw} + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=true] + * Enable or modify animations. + * + * @param {*} [eventArguments] + * Arguments to be accessed in event handler. + * + * @fires Highcharts.Axis#event:setExtremes + */ + Axis.prototype.setExtremes = function (newMin, newMax, redraw, animation, eventArguments) { + var axis = this, chart = axis.chart; + redraw = pick(redraw, true); // defaults to true + axis.series.forEach(function (serie) { + delete serie.kdTree; + }); + // Extend the arguments with min and max + eventArguments = extend(eventArguments, { + min: newMin, + max: newMax + }); + // Fire the event + fireEvent(axis, 'setExtremes', eventArguments, function () { + axis.userMin = newMin; + axis.userMax = newMax; + axis.eventArgs = eventArguments; + if (redraw) { + chart.redraw(animation); + } + }); + }; + /** + * Overridable method for zooming chart. Pulled out in a separate method to + * allow overriding in stock charts. + * @private + * @function Highcharts.Axis#zoom + * + * @param {number} newMin + * TO-DO: parameter description + * + * @param {number} newMax + * TO-DO: parameter description + * + * @return {boolean} + */ + Axis.prototype.zoom = function (newMin, newMax) { + var axis = this, dataMin = this.dataMin, dataMax = this.dataMax, options = this.options, min = Math.min(dataMin, pick(options.min, dataMin)), max = Math.max(dataMax, pick(options.max, dataMax)), evt = { + newMin: newMin, + newMax: newMax + }; + fireEvent(this, 'zoom', evt, function (e) { + // Use e.newMin and e.newMax - event handlers may have altered them + var newMin = e.newMin, newMax = e.newMax; + if (newMin !== axis.min || newMax !== axis.max) { // #5790 + // Prevent pinch zooming out of range. Check for defined is for + // #1946. #1734. + if (!axis.allowZoomOutside) { + // #6014, sometimes newMax will be smaller than min (or + // newMin will be larger than max). + if (defined(dataMin)) { + if (newMin < min) { + newMin = min; + } + if (newMin > max) { + newMin = max; + } + } + if (defined(dataMax)) { + if (newMax < min) { + newMax = min; + } + if (newMax > max) { + newMax = max; + } + } + } + // In full view, displaying the reset zoom button is not + // required + axis.displayBtn = (typeof newMin !== 'undefined' || + typeof newMax !== 'undefined'); + // Do it + axis.setExtremes(newMin, newMax, false, void 0, { trigger: 'zoom' }); + } + e.zoomed = true; + }); + return evt.zoomed; + }; + /** + * Update the axis metrics. + * + * @private + * @function Highcharts.Axis#setAxisSize + */ + Axis.prototype.setAxisSize = function () { + var chart = this.chart, options = this.options, + // [top, right, bottom, left] + offsets = options.offsets || [0, 0, 0, 0], horiz = this.horiz, + // Check for percentage based input values. Rounding fixes problems + // with column overflow and plot line filtering (#4898, #4899) + width = this.width = Math.round(relativeLength(pick(options.width, chart.plotWidth - offsets[3] + offsets[1]), chart.plotWidth)), height = this.height = Math.round(relativeLength(pick(options.height, chart.plotHeight - offsets[0] + offsets[2]), chart.plotHeight)), top = this.top = Math.round(relativeLength(pick(options.top, chart.plotTop + offsets[0]), chart.plotHeight, chart.plotTop)), left = this.left = Math.round(relativeLength(pick(options.left, chart.plotLeft + offsets[3]), chart.plotWidth, chart.plotLeft)); + // Expose basic values to use in Series object and navigator + this.bottom = chart.chartHeight - height - top; + this.right = chart.chartWidth - width - left; + // Direction agnostic properties + this.len = Math.max(horiz ? width : height, 0); // Math.max fixes #905 + this.pos = horiz ? left : top; // distance from SVG origin + }; + /** + * Get the current extremes for the axis. + * + * @sample highcharts/members/axis-getextremes/ + * Report extremes by click on a button + * @sample maps/members/axis-getextremes/ + * Get extremes in Highmaps + * + * @function Highcharts.Axis#getExtremes + * + * @return {Highcharts.ExtremesObject} + * An object containing extremes information. + */ + Axis.prototype.getExtremes = function () { + var axis = this; + var log = axis.logarithmic; + return { + min: log ? + correctFloat(log.lin2log(axis.min)) : + axis.min, + max: log ? + correctFloat(log.lin2log(axis.max)) : + axis.max, + dataMin: axis.dataMin, + dataMax: axis.dataMax, + userMin: axis.userMin, + userMax: axis.userMax + }; + }; + /** + * Get the zero plane either based on zero or on the min or max value. + * Used in bar and area plots. + * + * @function Highcharts.Axis#getThreshold + * + * @param {number} threshold + * The threshold in axis values. + * + * @return {number|undefined} + * The translated threshold position in terms of pixels, and corrected to + * stay within the axis bounds. + */ + Axis.prototype.getThreshold = function (threshold) { + var axis = this, log = axis.logarithmic, realMin = log ? log.lin2log(axis.min) : axis.min, realMax = log ? log.lin2log(axis.max) : axis.max; + if (threshold === null || threshold === -Infinity) { + threshold = realMin; + } + else if (threshold === Infinity) { + threshold = realMax; + } + else if (realMin > threshold) { + threshold = realMin; + } + else if (realMax < threshold) { + threshold = realMax; + } + return axis.translate(threshold, 0, 1, 0, 1); + }; + /** + * Compute auto alignment for the axis label based on which side the axis is + * on and the given rotation for the label. + * + * @private + * @function Highcharts.Axis#autoLabelAlign + * + * @param {number} rotation + * The rotation in degrees as set by either the `rotation` or `autoRotation` + * options. + * + * @return {Highcharts.AlignValue} + * Can be `"center"`, `"left"` or `"right"`. + */ + Axis.prototype.autoLabelAlign = function (rotation) { + var angle = (pick(rotation, 0) - (this.side * 90) + 720) % 360, evt = { align: 'center' }; + fireEvent(this, 'autoLabelAlign', evt, function (e) { + if (angle > 15 && angle < 165) { + e.align = 'right'; + } + else if (angle > 195 && angle < 345) { + e.align = 'left'; + } + }); + return evt.align; + }; + /** + * Get the tick length and width for the axis based on axis options. + * @private + * @function Highcharts.Axis#tickSize + * + * @param {string} [prefix] + * 'tick' or 'minorTick' + * + * @return {Array|undefined} + * An array of tickLength and tickWidth + */ + Axis.prototype.tickSize = function (prefix) { + var options = this.options, tickLength = options[prefix === 'tick' ? 'tickLength' : 'minorTickLength'], tickWidth = pick(options[prefix === 'tick' ? 'tickWidth' : 'minorTickWidth'], + // Default to 1 on linear and datetime X axes + prefix === 'tick' && this.isXAxis && !this.categories ? 1 : 0), e, tickSize; + if (tickWidth && tickLength) { + // Negate the length + if (options[prefix + 'Position'] === 'inside') { + tickLength = -tickLength; + } + tickSize = [tickLength, tickWidth]; + } + e = { tickSize: tickSize }; + fireEvent(this, 'afterTickSize', e); + return e.tickSize; + }; + /** + * Return the size of the labels. + * + * @private + * @function Highcharts.Axis#labelMetrics + * + * @return {Highcharts.FontMetricsObject} + */ + Axis.prototype.labelMetrics = function () { + var index = this.tickPositions && this.tickPositions[0] || 0; + return this.chart.renderer.fontMetrics(this.options.labels.style && + this.options.labels.style.fontSize, this.ticks[index] && this.ticks[index].label); + }; + /** + * Prevent the ticks from getting so close we can't draw the labels. On a + * horizontal axis, this is handled by rotating the labels, removing ticks + * and adding ellipsis. On a vertical axis remove ticks and add ellipsis. + * + * @private + * @function Highcharts.Axis#unsquish + * + * @return {number} + */ + Axis.prototype.unsquish = function () { + var labelOptions = this.options.labels, horiz = this.horiz, tickInterval = this.tickInterval, newTickInterval = tickInterval, slotSize = this.len / (((this.categories ? 1 : 0) + + this.max - + this.min) / + tickInterval), rotation, rotationOption = labelOptions.rotation, labelMetrics = this.labelMetrics(), step, bestScore = Number.MAX_VALUE, autoRotation, range = this.max - this.min, + // Return the multiple of tickInterval that is needed to avoid + // collision + getStep = function (spaceNeeded) { + var step = spaceNeeded / (slotSize || 1); + step = step > 1 ? Math.ceil(step) : 1; + // Guard for very small or negative angles (#9835) + if (step * tickInterval > range && + spaceNeeded !== Infinity && + slotSize !== Infinity && + range) { + step = Math.ceil(range / tickInterval); + } + return correctFloat(step * tickInterval); + }; + if (horiz) { + autoRotation = !labelOptions.staggerLines && + !labelOptions.step && + ( // #3971 + defined(rotationOption) ? + [rotationOption] : + slotSize < pick(labelOptions.autoRotationLimit, 80) && labelOptions.autoRotation); + if (autoRotation) { + // Loop over the given autoRotation options, and determine + // which gives the best score. The best score is that with + // the lowest number of steps and a rotation closest + // to horizontal. + autoRotation.forEach(function (rot) { + var score; + if (rot === rotationOption || + (rot && rot >= -90 && rot <= 90)) { // #3891 + step = getStep(Math.abs(labelMetrics.h / Math.sin(deg2rad * rot))); + score = step + Math.abs(rot / 360); + if (score < bestScore) { + bestScore = score; + rotation = rot; + newTickInterval = step; + } + } + }); + } + } + else if (!labelOptions.step) { // #4411 + newTickInterval = getStep(labelMetrics.h); + } + this.autoRotation = autoRotation; + this.labelRotation = pick(rotation, rotationOption); + return newTickInterval; + }; + /** + * Get the general slot width for labels/categories on this axis. This may + * change between the pre-render (from Axis.getOffset) and the final tick + * rendering and placement. + * + * @private + * @function Highcharts.Axis#getSlotWidth + * + * @param {Highcharts.Tick} [tick] Optionally, calculate the slot width + * basing on tick label. It is used in highcharts-3d module, where the slots + * has different widths depending on perspective angles. + * + * @return {number} + * The pixel width allocated to each axis label. + */ + Axis.prototype.getSlotWidth = function (tick) { + var _a; + // #5086, #1580, #1931 + var chart = this.chart, horiz = this.horiz, labelOptions = this.options.labels, slotCount = Math.max(this.tickPositions.length - (this.categories ? 0 : 1), 1), marginLeft = chart.margin[3]; + // Used by grid axis + if (tick && isNumber(tick.slotWidth)) { // #13221, can be 0 + return tick.slotWidth; + } + if (horiz && + labelOptions && + (labelOptions.step || 0) < 2) { + if (labelOptions.rotation) { // #4415 + return 0; + } + return ((this.staggerLines || 1) * this.len) / slotCount; + } + if (!horiz) { + // #7028 + var cssWidth = (_a = labelOptions === null || labelOptions === void 0 ? void 0 : labelOptions.style) === null || _a === void 0 ? void 0 : _a.width; + if (cssWidth !== void 0) { + return parseInt(cssWidth, 10); + } + if (marginLeft) { + return marginLeft - chart.spacing[3]; + } + } + // Last resort, a fraction of the available size + return chart.chartWidth * 0.33; + }; + /** + * Render the axis labels and determine whether ellipsis or rotation need to + * be applied. + * + * @private + * @function Highcharts.Axis#renderUnsquish + */ + Axis.prototype.renderUnsquish = function () { + var chart = this.chart, renderer = chart.renderer, tickPositions = this.tickPositions, ticks = this.ticks, labelOptions = this.options.labels, labelStyleOptions = (labelOptions && labelOptions.style || {}), horiz = this.horiz, slotWidth = this.getSlotWidth(), innerWidth = Math.max(1, Math.round(slotWidth - 2 * (labelOptions.padding || 5))), attr = {}, labelMetrics = this.labelMetrics(), textOverflowOption = (labelOptions.style && + labelOptions.style.textOverflow), commonWidth, commonTextOverflow, maxLabelLength = 0, label, i, pos; + // Set rotation option unless it is "auto", like in gauges + if (!isString(labelOptions.rotation)) { + // #4443: + attr.rotation = labelOptions.rotation || 0; + } + // Get the longest label length + tickPositions.forEach(function (tick) { + tick = ticks[tick]; + // Replace label - sorting animation + if (tick.movedLabel) { + tick.replaceMovedLabel(); + } + if (tick && + tick.label && + tick.label.textPxLength > maxLabelLength) { + maxLabelLength = tick.label.textPxLength; + } + }); + this.maxLabelLength = maxLabelLength; + // Handle auto rotation on horizontal axis + if (this.autoRotation) { + // Apply rotation only if the label is too wide for the slot, and + // the label is wider than its height. + if (maxLabelLength > innerWidth && + maxLabelLength > labelMetrics.h) { + attr.rotation = this.labelRotation; + } + else { + this.labelRotation = 0; + } + // Handle word-wrap or ellipsis on vertical axis + } + else if (slotWidth) { + // For word-wrap or ellipsis + commonWidth = innerWidth; + if (!textOverflowOption) { + commonTextOverflow = 'clip'; + // On vertical axis, only allow word wrap if there is room + // for more lines. + i = tickPositions.length; + while (!horiz && i--) { + pos = tickPositions[i]; + label = ticks[pos].label; + if (label) { + // Reset ellipsis in order to get the correct + // bounding box (#4070) + if (label.styles && + label.styles.textOverflow === 'ellipsis') { + label.css({ textOverflow: 'clip' }); + // Set the correct width in order to read + // the bounding box height (#4678, #5034) + } + else if (label.textPxLength > slotWidth) { + label.css({ width: slotWidth + 'px' }); + } + if (label.getBBox().height > (this.len / tickPositions.length - + (labelMetrics.h - labelMetrics.f))) { + label.specificTextOverflow = 'ellipsis'; + } + } + } + } + } + // Add ellipsis if the label length is significantly longer than ideal + if (attr.rotation) { + commonWidth = (maxLabelLength > chart.chartHeight * 0.5 ? + chart.chartHeight * 0.33 : + maxLabelLength); + if (!textOverflowOption) { + commonTextOverflow = 'ellipsis'; + } + } + // Set the explicit or automatic label alignment + this.labelAlign = labelOptions.align || + this.autoLabelAlign(this.labelRotation); + if (this.labelAlign) { + attr.align = this.labelAlign; + } + // Apply general and specific CSS + tickPositions.forEach(function (pos) { + var tick = ticks[pos], label = tick && tick.label, widthOption = labelStyleOptions.width, css = {}; + if (label) { + // This needs to go before the CSS in old IE (#4502) + label.attr(attr); + if (tick.shortenLabel) { + tick.shortenLabel(); + } + else if (commonWidth && + !widthOption && + // Setting width in this case messes with the bounding box + // (#7975) + labelStyleOptions.whiteSpace !== 'nowrap' && + ( + // Speed optimizing, #7656 + commonWidth < label.textPxLength || + // Resetting CSS, #4928 + label.element.tagName === 'SPAN')) { + css.width = commonWidth + 'px'; + if (!textOverflowOption) { + css.textOverflow = (label.specificTextOverflow || + commonTextOverflow); + } + label.css(css); + // Reset previously shortened label (#8210) + } + else if (label.styles && + label.styles.width && + !css.width && + !widthOption) { + label.css({ width: null }); + } + delete label.specificTextOverflow; + tick.rotation = attr.rotation; + } + }, this); + // Note: Why is this not part of getLabelPosition? + this.tickRotCorr = renderer.rotCorr(labelMetrics.b, this.labelRotation || 0, this.side !== 0); + }; + /** + * Return true if the axis has associated data. + * + * @function Highcharts.Axis#hasData + * + * @return {boolean} + * True if the axis has associated visible series and those series have + * either valid data points or explicit `min` and `max` settings. + */ + Axis.prototype.hasData = function () { + return this.series.some(function (s) { + return s.hasData(); + }) || + (this.options.showEmpty && + defined(this.min) && + defined(this.max)); + }; + /** + * Adds the title defined in axis.options.title. + * + * @function Highcharts.Axis#addTitle + * + * @param {boolean} [display] + * Whether or not to display the title. + */ + Axis.prototype.addTitle = function (display) { + var axis = this, renderer = axis.chart.renderer, horiz = axis.horiz, opposite = axis.opposite, options = axis.options, axisTitleOptions = options.title, textAlign, styledMode = axis.chart.styledMode; + if (!axis.axisTitle) { + textAlign = axisTitleOptions.textAlign; + if (!textAlign) { + textAlign = (horiz ? { + low: 'left', + middle: 'center', + high: 'right' + } : { + low: opposite ? 'right' : 'left', + middle: 'center', + high: opposite ? 'left' : 'right' + })[axisTitleOptions.align]; + } + axis.axisTitle = renderer + .text(axisTitleOptions.text, 0, 0, axisTitleOptions.useHTML) + .attr({ + zIndex: 7, + rotation: axisTitleOptions.rotation || 0, + align: textAlign + }) + .addClass('highcharts-axis-title'); + // #7814, don't mutate style option + if (!styledMode) { + axis.axisTitle.css(merge(axisTitleOptions.style)); + } + axis.axisTitle.add(axis.axisGroup); + axis.axisTitle.isNew = true; + } + // Max width defaults to the length of the axis + if (!styledMode && + !axisTitleOptions.style.width && + !axis.isRadial) { + axis.axisTitle.css({ + width: axis.len + 'px' + }); + } + // hide or show the title depending on whether showEmpty is set + axis.axisTitle[display ? 'show' : 'hide'](display); + }; + /** + * Generates a tick for initial positioning. + * + * @private + * @function Highcharts.Axis#generateTick + * + * @param {number} pos + * The tick position in axis values. + * + * @param {number} [i] + * The index of the tick in {@link Axis.tickPositions}. + */ + Axis.prototype.generateTick = function (pos) { + var axis = this; + var ticks = axis.ticks; + if (!ticks[pos]) { + ticks[pos] = new Tick(axis, pos); + } + else { + ticks[pos].addLabel(); // update labels depending on tick interval + } + }; + /** + * Render the tick labels to a preliminary position to get their sizes + * + * @private + * @function Highcharts.Axis#getOffset + * + * @fires Highcharts.Axis#event:afterGetOffset + */ + Axis.prototype.getOffset = function () { + var axis = this, chart = axis.chart, renderer = chart.renderer, options = axis.options, tickPositions = axis.tickPositions, ticks = axis.ticks, horiz = axis.horiz, side = axis.side, invertedSide = chart.inverted && + !axis.isZAxis ? [1, 0, 3, 2][side] : side, hasData, showAxis, titleOffset = 0, titleOffsetOption, titleMargin = 0, axisTitleOptions = options.title, labelOptions = options.labels, labelOffset = 0, // reset + labelOffsetPadded, axisOffset = chart.axisOffset, clipOffset = chart.clipOffset, clip, directionFactor = [-1, 1, 1, -1][side], className = options.className, axisParent = axis.axisParent, // Used in color axis + lineHeightCorrection; + // For reuse in Axis.render + hasData = axis.hasData(); + axis.showAxis = showAxis = hasData || pick(options.showEmpty, true); + // Set/reset staggerLines + axis.staggerLines = axis.horiz && labelOptions.staggerLines; + // Create the axisGroup and gridGroup elements on first iteration + if (!axis.axisGroup) { + axis.gridGroup = renderer.g('grid') + .attr({ zIndex: options.gridZIndex || 1 }) + .addClass('highcharts-' + this.coll.toLowerCase() + '-grid ' + + (className || '')) + .add(axisParent); + axis.axisGroup = renderer.g('axis') + .attr({ zIndex: options.zIndex || 2 }) + .addClass('highcharts-' + this.coll.toLowerCase() + ' ' + + (className || '')) + .add(axisParent); + axis.labelGroup = renderer.g('axis-labels') + .attr({ zIndex: labelOptions.zIndex || 7 }) + .addClass('highcharts-' + axis.coll.toLowerCase() + '-labels ' + + (className || '')) + .add(axisParent); + } + if (hasData || axis.isLinked) { + // Generate ticks + tickPositions.forEach(function (pos, i) { + // i is not used here, but may be used in overrides + axis.generateTick(pos, i); + }); + axis.renderUnsquish(); + // Left side must be align: right and right side must + // have align: left for labels + axis.reserveSpaceDefault = (side === 0 || + side === 2 || + { 1: 'left', 3: 'right' }[side] === axis.labelAlign); + if (pick(labelOptions.reserveSpace, axis.labelAlign === 'center' ? true : null, axis.reserveSpaceDefault)) { + tickPositions.forEach(function (pos) { + // get the highest offset + labelOffset = Math.max(ticks[pos].getLabelSize(), labelOffset); + }); + } + if (axis.staggerLines) { + labelOffset *= axis.staggerLines; + } + axis.labelOffset = labelOffset * (axis.opposite ? -1 : 1); + } + else { // doesn't have data + objectEach(ticks, function (tick, n) { + tick.destroy(); + delete ticks[n]; + }); + } + if (axisTitleOptions && + axisTitleOptions.text && + axisTitleOptions.enabled !== false) { + axis.addTitle(showAxis); + if (showAxis && axisTitleOptions.reserveSpace !== false) { + axis.titleOffset = titleOffset = + axis.axisTitle.getBBox()[horiz ? 'height' : 'width']; + titleOffsetOption = axisTitleOptions.offset; + titleMargin = defined(titleOffsetOption) ? + 0 : + pick(axisTitleOptions.margin, horiz ? 5 : 10); + } + } + // Render the axis line + axis.renderLine(); + // handle automatic or user set offset + axis.offset = directionFactor * pick(options.offset, axisOffset[side] ? axisOffset[side] + (options.margin || 0) : 0); + axis.tickRotCorr = axis.tickRotCorr || { x: 0, y: 0 }; // polar + if (side === 0) { + lineHeightCorrection = -axis.labelMetrics().h; + } + else if (side === 2) { + lineHeightCorrection = axis.tickRotCorr.y; + } + else { + lineHeightCorrection = 0; + } + // Find the padded label offset + labelOffsetPadded = Math.abs(labelOffset) + titleMargin; + if (labelOffset) { + labelOffsetPadded -= lineHeightCorrection; + labelOffsetPadded += directionFactor * (horiz ? + pick(labelOptions.y, axis.tickRotCorr.y + directionFactor * 8) : + labelOptions.x); + } + axis.axisTitleMargin = pick(titleOffsetOption, labelOffsetPadded); + if (axis.getMaxLabelDimensions) { + axis.maxLabelDimensions = axis.getMaxLabelDimensions(ticks, tickPositions); + } + // Due to GridAxis.tickSize, tickSize should be calculated after ticks + // has rendered. + var tickSize = this.tickSize('tick'); + axisOffset[side] = Math.max(axisOffset[side], axis.axisTitleMargin + titleOffset + + directionFactor * axis.offset, labelOffsetPadded, // #3027 + tickPositions && tickPositions.length && tickSize ? + tickSize[0] + directionFactor * axis.offset : + 0 // #4866 + ); + // Decide the clipping needed to keep the graph inside + // the plot area and axis lines + clip = options.offset ? + 0 : + // #4308, #4371: + Math.floor(axis.axisLine.strokeWidth() / 2) * 2; + clipOffset[invertedSide] = + Math.max(clipOffset[invertedSide], clip); + fireEvent(this, 'afterGetOffset'); + }; + /** + * Internal function to get the path for the axis line. Extended for polar + * charts. + * + * @function Highcharts.Axis#getLinePath + * + * @param {number} lineWidth + * The line width in pixels. + * + * @return {Highcharts.SVGPathArray} + * The SVG path definition in array form. + */ + Axis.prototype.getLinePath = function (lineWidth) { + var chart = this.chart, opposite = this.opposite, offset = this.offset, horiz = this.horiz, lineLeft = this.left + (opposite ? this.width : 0) + offset, lineTop = chart.chartHeight - this.bottom - + (opposite ? this.height : 0) + offset; + if (opposite) { + lineWidth *= -1; // crispify the other way - #1480, #1687 + } + return chart.renderer + .crispLine([ + [ + 'M', + horiz ? + this.left : + lineLeft, + horiz ? + lineTop : + this.top + ], + [ + 'L', + horiz ? + chart.chartWidth - this.right : + lineLeft, + horiz ? + lineTop : + chart.chartHeight - this.bottom + ] + ], lineWidth); + }; + /** + * Render the axis line. Called internally when rendering and redrawing the + * axis. + * + * @function Highcharts.Axis#renderLine + */ + Axis.prototype.renderLine = function () { + if (!this.axisLine) { + this.axisLine = this.chart.renderer.path() + .addClass('highcharts-axis-line') + .add(this.axisGroup); + if (!this.chart.styledMode) { + this.axisLine.attr({ + stroke: this.options.lineColor, + 'stroke-width': this.options.lineWidth, + zIndex: 7 + }); + } + } + }; + /** + * Position the axis title. + * + * @private + * @function Highcharts.Axis#getTitlePosition + * + * @return {Highcharts.PositionObject} + * X and Y positions for the title. + */ + Axis.prototype.getTitlePosition = function () { + // compute anchor points for each of the title align options + var horiz = this.horiz, axisLeft = this.left, axisTop = this.top, axisLength = this.len, axisTitleOptions = this.options.title, margin = horiz ? axisLeft : axisTop, opposite = this.opposite, offset = this.offset, xOption = axisTitleOptions.x || 0, yOption = axisTitleOptions.y || 0, axisTitle = this.axisTitle, fontMetrics = this.chart.renderer.fontMetrics(axisTitleOptions.style && + axisTitleOptions.style.fontSize, axisTitle), + // The part of a multiline text that is below the baseline of the + // first line. Subtract 1 to preserve pixel-perfectness from the + // old behaviour (v5.0.12), where only one line was allowed. + textHeightOvershoot = Math.max(axisTitle.getBBox(null, 0).height - fontMetrics.h - 1, 0), + // the position in the length direction of the axis + alongAxis = { + low: margin + (horiz ? 0 : axisLength), + middle: margin + axisLength / 2, + high: margin + (horiz ? axisLength : 0) + }[axisTitleOptions.align], + // the position in the perpendicular direction of the axis + offAxis = (horiz ? axisTop + this.height : axisLeft) + + (horiz ? 1 : -1) * // horizontal axis reverses the margin + (opposite ? -1 : 1) * // so does opposite axes + this.axisTitleMargin + + [ + -textHeightOvershoot, + textHeightOvershoot, + fontMetrics.f, + -textHeightOvershoot // left + ][this.side], titlePosition = { + x: horiz ? + alongAxis + xOption : + offAxis + (opposite ? this.width : 0) + offset + xOption, + y: horiz ? + offAxis + yOption - (opposite ? this.height : 0) + offset : + alongAxis + yOption + }; + fireEvent(this, 'afterGetTitlePosition', { titlePosition: titlePosition }); + return titlePosition; + }; + /** + * Render a minor tick into the given position. If a minor tick already + * exists in this position, move it. + * + * @function Highcharts.Axis#renderMinorTick + * + * @param {number} pos + * The position in axis values. + */ + Axis.prototype.renderMinorTick = function (pos) { + var axis = this; + var slideInTicks = axis.chart.hasRendered && isNumber(axis.oldMin); + var minorTicks = axis.minorTicks; + if (!minorTicks[pos]) { + minorTicks[pos] = new Tick(axis, pos, 'minor'); + } + // Render new ticks in old position + if (slideInTicks && minorTicks[pos].isNew) { + minorTicks[pos].render(null, true); + } + minorTicks[pos].render(null, false, 1); + }; + /** + * Render a major tick into the given position. If a tick already exists + * in this position, move it. + * + * @function Highcharts.Axis#renderTick + * + * @param {number} pos + * The position in axis values. + * + * @param {number} i + * The tick index. + */ + Axis.prototype.renderTick = function (pos, i) { + var axis = this; + var isLinked = axis.isLinked; + var ticks = axis.ticks; + var slideInTicks = axis.chart.hasRendered && isNumber(axis.oldMin); + // Linked axes need an extra check to find out if + if (!isLinked || + (pos >= axis.min && pos <= axis.max)) { + if (!ticks[pos]) { + ticks[pos] = new Tick(axis, pos); + } + // NOTE this seems like overkill. Could be handled in tick.render by + // setting old position in attr, then set new position in animate. + // render new ticks in old position + if (slideInTicks && ticks[pos].isNew) { + // Start with negative opacity so that it is visible from + // halfway into the animation + ticks[pos].render(i, true, -1); + } + ticks[pos].render(i); + } + }; + /** + * Render the axis. + * + * @private + * @function Highcharts.Axis#render + * + * @fires Highcharts.Axis#event:afterRender + */ + Axis.prototype.render = function () { + var axis = this, chart = axis.chart, log = axis.logarithmic, renderer = chart.renderer, options = axis.options, isLinked = axis.isLinked, tickPositions = axis.tickPositions, axisTitle = axis.axisTitle, ticks = axis.ticks, minorTicks = axis.minorTicks, alternateBands = axis.alternateBands, stackLabelOptions = options.stackLabels, alternateGridColor = options.alternateGridColor, tickmarkOffset = axis.tickmarkOffset, axisLine = axis.axisLine, showAxis = axis.showAxis, animation = animObject(renderer.globalAnimation), from, to; + // Reset + axis.labelEdge.length = 0; + axis.overlap = false; + // Mark all elements inActive before we go over and mark the active ones + [ticks, minorTicks, alternateBands].forEach(function (coll) { + objectEach(coll, function (tick) { + tick.isActive = false; + }); + }); + // If the series has data draw the ticks. Else only the line and title + if (axis.hasData() || isLinked) { + // minor ticks + if (axis.minorTickInterval && !axis.categories) { + axis.getMinorTickPositions().forEach(function (pos) { + axis.renderMinorTick(pos); + }); + } + // Major ticks. Pull out the first item and render it last so that + // we can get the position of the neighbour label. #808. + if (tickPositions.length) { // #1300 + tickPositions.forEach(function (pos, i) { + axis.renderTick(pos, i); + }); + // In a categorized axis, the tick marks are displayed + // between labels. So we need to add a tick mark and + // grid line at the left edge of the X axis. + if (tickmarkOffset && (axis.min === 0 || axis.single)) { + if (!ticks[-1]) { + ticks[-1] = new Tick(axis, -1, null, true); + } + ticks[-1].render(-1); + } + } + // alternate grid color + if (alternateGridColor) { + tickPositions.forEach(function (pos, i) { + to = typeof tickPositions[i + 1] !== 'undefined' ? + tickPositions[i + 1] + tickmarkOffset : + axis.max - tickmarkOffset; + if (i % 2 === 0 && + pos < axis.max && + to <= axis.max + (chart.polar ? + -tickmarkOffset : + tickmarkOffset)) { // #2248, #4660 + if (!alternateBands[pos]) { + // Should be imported from PlotLineOrBand.js, but + // the dependency cycle with axis is a problem + alternateBands[pos] = new H.PlotLineOrBand(axis); + } + from = pos + tickmarkOffset; // #949 + alternateBands[pos].options = { + from: log ? log.lin2log(from) : from, + to: log ? log.lin2log(to) : to, + color: alternateGridColor + }; + alternateBands[pos].render(); + alternateBands[pos].isActive = true; + } + }); + } + // custom plot lines and bands + if (!axis._addedPlotLB) { // only first time + (options.plotLines || []) + .concat(options.plotBands || []) + .forEach(function (plotLineOptions) { + axis.addPlotBandOrLine(plotLineOptions); + }); + axis._addedPlotLB = true; + } + } // end if hasData + // Remove inactive ticks + [ticks, minorTicks, alternateBands].forEach(function (coll) { + var i, forDestruction = [], delay = animation.duration, destroyInactiveItems = function () { + i = forDestruction.length; + while (i--) { + // When resizing rapidly, the same items + // may be destroyed in different timeouts, + // or the may be reactivated + if (coll[forDestruction[i]] && + !coll[forDestruction[i]].isActive) { + coll[forDestruction[i]].destroy(); + delete coll[forDestruction[i]]; + } + } + }; + objectEach(coll, function (tick, pos) { + if (!tick.isActive) { + // Render to zero opacity + tick.render(pos, false, 0); + tick.isActive = false; + forDestruction.push(pos); + } + }); + // When the objects are finished fading out, destroy them + syncTimeout(destroyInactiveItems, coll === alternateBands || + !chart.hasRendered || + !delay ? + 0 : + delay); + }); + // Set the axis line path + if (axisLine) { + axisLine[axisLine.isPlaced ? 'animate' : 'attr']({ + d: this.getLinePath(axisLine.strokeWidth()) + }); + axisLine.isPlaced = true; + // Show or hide the line depending on options.showEmpty + axisLine[showAxis ? 'show' : 'hide'](showAxis); + } + if (axisTitle && showAxis) { + var titleXy = axis.getTitlePosition(); + if (isNumber(titleXy.y)) { + axisTitle[axisTitle.isNew ? 'attr' : 'animate'](titleXy); + axisTitle.isNew = false; + } + else { + axisTitle.attr('y', -9999); + axisTitle.isNew = true; + } + } + // Stacked totals: + if (stackLabelOptions && stackLabelOptions.enabled && axis.stacking) { + axis.stacking.renderStackTotals(); + } + // End stacked totals + axis.isDirty = false; + fireEvent(this, 'afterRender'); + }; + /** + * Redraw the axis to reflect changes in the data or axis extremes. Called + * internally from Highcharts.Chart#redraw. + * + * @private + * @function Highcharts.Axis#redraw + */ + Axis.prototype.redraw = function () { + if (this.visible) { + // render the axis + this.render(); + // move plot lines and bands + this.plotLinesAndBands.forEach(function (plotLine) { + plotLine.render(); + }); + } + // mark associated series as dirty and ready for redraw + this.series.forEach(function (series) { + series.isDirty = true; + }); + }; + /** + * Returns an array of axis properties, that should be untouched during + * reinitialization. + * + * @private + * @function Highcharts.Axis#getKeepProps + * + * @return {Array} + */ + Axis.prototype.getKeepProps = function () { + return (this.keepProps || Axis.keepProps); + }; + /** + * Destroys an Axis instance. See {@link Axis#remove} for the API endpoint + * to fully remove the axis. + * + * @private + * @function Highcharts.Axis#destroy + * + * @param {boolean} [keepEvents] + * Whether to preserve events, used internally in Axis.update. + */ + Axis.prototype.destroy = function (keepEvents) { + var axis = this, plotLinesAndBands = axis.plotLinesAndBands, plotGroup, i; + fireEvent(this, 'destroy', { keepEvents: keepEvents }); + // Remove the events + if (!keepEvents) { + removeEvent(axis); + } + // Destroy collections + [axis.ticks, axis.minorTicks, axis.alternateBands].forEach(function (coll) { + destroyObjectProperties(coll); + }); + if (plotLinesAndBands) { + i = plotLinesAndBands.length; + while (i--) { // #1975 + plotLinesAndBands[i].destroy(); + } + } + // Destroy elements + ['axisLine', 'axisTitle', 'axisGroup', + 'gridGroup', 'labelGroup', 'cross', 'scrollbar'].forEach(function (prop) { + if (axis[prop]) { + axis[prop] = axis[prop].destroy(); + } + }); + // Destroy each generated group for plotlines and plotbands + for (plotGroup in axis.plotLinesAndBandsGroups) { // eslint-disable-line guard-for-in + axis.plotLinesAndBandsGroups[plotGroup] = + axis.plotLinesAndBandsGroups[plotGroup].destroy(); + } + // Delete all properties and fall back to the prototype. + objectEach(axis, function (val, key) { + if (axis.getKeepProps().indexOf(key) === -1) { + delete axis[key]; + } + }); + }; + /** + * Internal function to draw a crosshair. + * + * @function Highcharts.Axis#drawCrosshair + * + * @param {Highcharts.PointerEventObject} [e] + * The event arguments from the modified pointer event, extended with + * `chartX` and `chartY` + * + * @param {Highcharts.Point} [point] + * The Point object if the crosshair snaps to points. + * + * @fires Highcharts.Axis#event:afterDrawCrosshair + * @fires Highcharts.Axis#event:drawCrosshair + */ + Axis.prototype.drawCrosshair = function (e, point) { + var path, options = this.crosshair, snap = pick(options.snap, true), pos, categorized, graphic = this.cross, crossOptions, chart = this.chart; + fireEvent(this, 'drawCrosshair', { e: e, point: point }); + // Use last available event when updating non-snapped crosshairs without + // mouse interaction (#5287) + if (!e) { + e = this.cross && this.cross.e; + } + if ( + // Disabled in options + !this.crosshair || + // Snap + ((defined(point) || !snap) === false)) { + this.hideCrosshair(); + } + else { + // Get the path + if (!snap) { + pos = e && + (this.horiz ? + e.chartX - this.pos : + this.len - e.chartY + this.pos); + } + else if (defined(point)) { + // #3834 + pos = pick(this.coll !== 'colorAxis' ? + point.crosshairPos : // 3D axis extension + null, this.isXAxis ? + point.plotX : + this.len - point.plotY); + } + if (defined(pos)) { + crossOptions = { + // value, only used on radial + value: point && (this.isXAxis ? + point.x : + pick(point.stackY, point.y)), + translatedValue: pos + }; + if (chart.polar) { + // Additional information required for crosshairs in + // polar chart + extend(crossOptions, { + isCrosshair: true, + chartX: e && e.chartX, + chartY: e && e.chartY, + point: point + }); + } + path = this.getPlotLinePath(crossOptions) || + null; // #3189 + } + if (!defined(path)) { + this.hideCrosshair(); + return; + } + categorized = this.categories && !this.isRadial; + // Draw the cross + if (!graphic) { + this.cross = graphic = chart.renderer + .path() + .addClass('highcharts-crosshair highcharts-crosshair-' + + (categorized ? 'category ' : 'thin ') + + options.className) + .attr({ + zIndex: pick(options.zIndex, 2) + }) + .add(); + // Presentational attributes + if (!chart.styledMode) { + graphic.attr({ + stroke: options.color || + (categorized ? + Color + .parse('#ccd6eb') + .setOpacity(0.25) + .get() : + '#cccccc'), + 'stroke-width': pick(options.width, 1) + }).css({ + 'pointer-events': 'none' + }); + if (options.dashStyle) { + graphic.attr({ + dashstyle: options.dashStyle + }); + } + } + } + graphic.show().attr({ + d: path + }); + if (categorized && !options.width) { + graphic.attr({ + 'stroke-width': this.transA + }); + } + this.cross.e = e; + } + fireEvent(this, 'afterDrawCrosshair', { e: e, point: point }); + }; + /** + * Hide the crosshair if visible. + * + * @function Highcharts.Axis#hideCrosshair + */ + Axis.prototype.hideCrosshair = function () { + if (this.cross) { + this.cross.hide(); + } + fireEvent(this, 'afterHideCrosshair'); + }; + /** + * Check whether the chart has vertical panning ('y' or 'xy' type). + * + * @private + * @function Highcharts.Axis#hasVerticalPanning + * @return {boolean} + * + */ + Axis.prototype.hasVerticalPanning = function () { + var _a, _b; + return /y/.test(((_b = (_a = this.chart.options.chart) === null || _a === void 0 ? void 0 : _a.panning) === null || _b === void 0 ? void 0 : _b.type) || ''); + }; + /* * + * + * Static Properties + * + * */ + /** + * The X axis or category axis. Normally this is the horizontal axis, + * though if the chart is inverted this is the vertical axis. In case of + * multiple axes, the xAxis node is an array of configuration objects. + * + * See the [Axis class](/class-reference/Highcharts.Axis) for programmatic + * access to the axis. + * + * @productdesc {highmaps} + * In Highmaps, the axis is hidden, but it is used behind the scenes to + * control features like zooming and panning. Zooming is in effect the same + * as setting the extremes of one of the exes. + * + * @type {*|Array<*>} + * @optionparent xAxis + * + * @private + */ + Axis.defaultOptions = { + /** + * When using multiple axis, the ticks of two or more opposite axes + * will automatically be aligned by adding ticks to the axis or axes + * with the least ticks, as if `tickAmount` were specified. + * + * This can be prevented by setting `alignTicks` to false. If the grid + * lines look messy, it's a good idea to hide them for the secondary + * axis by setting `gridLineWidth` to 0. + * + * If `startOnTick` or `endOnTick` in an Axis options are set to false, + * then the `alignTicks ` will be disabled for the Axis. + * + * Disabled for logarithmic axes. + * + * @type {boolean} + * @default true + * @product highcharts highstock gantt + * @apioption xAxis.alignTicks + */ + /** + * Whether to allow decimals in this axis' ticks. When counting + * integers, like persons or hits on a web page, decimals should + * be avoided in the labels. + * + * @see [minTickInterval](#xAxis.minTickInterval) + * + * @sample {highcharts|highstock} highcharts/yaxis/allowdecimals-true/ + * True by default + * @sample {highcharts|highstock} highcharts/yaxis/allowdecimals-false/ + * False + * + * @type {boolean} + * @default true + * @since 2.0 + * @apioption xAxis.allowDecimals + */ + /** + * When using an alternate grid color, a band is painted across the + * plot area between every other grid line. + * + * @sample {highcharts} highcharts/yaxis/alternategridcolor/ + * Alternate grid color on the Y axis + * @sample {highstock} stock/xaxis/alternategridcolor/ + * Alternate grid color on the Y axis + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption xAxis.alternateGridColor + */ + /** + * An array defining breaks in the axis, the sections defined will be + * left out and all the points shifted closer to each other. + * + * @productdesc {highcharts} + * Requires that the broken-axis.js module is loaded. + * + * @sample {highcharts} highcharts/axisbreak/break-simple/ + * Simple break + * @sample {highcharts|highstock} highcharts/axisbreak/break-visualized/ + * Advanced with callback + * @sample {highstock} stock/demo/intraday-breaks/ + * Break on nights and weekends + * + * @type {Array<*>} + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption xAxis.breaks + */ + /** + * A number indicating how much space should be left between the start + * and the end of the break. The break size is given in axis units, + * so for instance on a `datetime` axis, a break size of 3600000 would + * indicate the equivalent of an hour. + * + * @type {number} + * @default 0 + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption xAxis.breaks.breakSize + */ + /** + * The point where the break starts. + * + * @type {number} + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption xAxis.breaks.from + */ + /** + * Defines an interval after which the break appears again. By default + * the breaks do not repeat. + * + * @type {number} + * @default 0 + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption xAxis.breaks.repeat + */ + /** + * The point where the break ends. + * + * @type {number} + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption xAxis.breaks.to + */ + /** + * If categories are present for the xAxis, names are used instead of + * numbers for that axis. + * + * Since Highcharts 3.0, categories can also + * be extracted by giving each point a [name](#series.data) and setting + * axis [type](#xAxis.type) to `category`. However, if you have multiple + * series, best practice remains defining the `categories` array. + * + * Example: `categories: ['Apples', 'Bananas', 'Oranges']` + * + * @sample {highcharts} highcharts/demo/line-labels/ + * With + * @sample {highcharts} highcharts/xaxis/categories/ + * Without + * + * @type {Array} + * @product highcharts gantt + * @apioption xAxis.categories + */ + /** + * The highest allowed value for automatically computed axis extremes. + * + * @see [floor](#xAxis.floor) + * + * @sample {highcharts|highstock} highcharts/yaxis/floor-ceiling/ + * Floor and ceiling + * + * @type {number} + * @since 4.0 + * @product highcharts highstock gantt + * @apioption xAxis.ceiling + */ + /** + * A class name that opens for styling the axis by CSS, especially in + * Highcharts styled mode. The class name is applied to group elements + * for the grid, axis elements and labels. + * + * @sample {highcharts|highstock|highmaps} highcharts/css/axis/ + * Multiple axes with separate styling + * + * @type {string} + * @since 5.0.0 + * @apioption xAxis.className + */ + /** + * Configure a crosshair that follows either the mouse pointer or the + * hovered point. + * + * In styled mode, the crosshairs are styled in the + * `.highcharts-crosshair`, `.highcharts-crosshair-thin` or + * `.highcharts-xaxis-category` classes. + * + * @productdesc {highstock} + * In Highstock, by default, the crosshair is enabled on the X axis and + * disabled on the Y axis. + * + * @sample {highcharts} highcharts/xaxis/crosshair-both/ + * Crosshair on both axes + * @sample {highstock} stock/xaxis/crosshairs-xy/ + * Crosshair on both axes + * @sample {highmaps} highcharts/xaxis/crosshair-both/ + * Crosshair on both axes + * + * @declare Highcharts.AxisCrosshairOptions + * @type {boolean|*} + * @default false + * @since 4.1 + * @apioption xAxis.crosshair + */ + /** + * A class name for the crosshair, especially as a hook for styling. + * + * @type {string} + * @since 5.0.0 + * @apioption xAxis.crosshair.className + */ + /** + * The color of the crosshair. Defaults to `#cccccc` for numeric and + * datetime axes, and `rgba(204,214,235,0.25)` for category axes, where + * the crosshair by default highlights the whole category. + * + * @sample {highcharts|highstock|highmaps} highcharts/xaxis/crosshair-customized/ + * Customized crosshairs + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #cccccc + * @since 4.1 + * @apioption xAxis.crosshair.color + */ + /** + * The dash style for the crosshair. See + * [plotOptions.series.dashStyle](#plotOptions.series.dashStyle) + * for possible values. + * + * @sample {highcharts|highmaps} highcharts/xaxis/crosshair-dotted/ + * Dotted crosshair + * @sample {highstock} stock/xaxis/crosshair-dashed/ + * Dashed X axis crosshair + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 4.1 + * @apioption xAxis.crosshair.dashStyle + */ + /** + * A label on the axis next to the crosshair. + * + * In styled mode, the label is styled with the + * `.highcharts-crosshair-label` class. + * + * @sample {highstock} stock/xaxis/crosshair-label/ + * Crosshair labels + * @sample {highstock} highcharts/css/crosshair-label/ + * Style mode + * + * @declare Highcharts.AxisCrosshairLabelOptions + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label + */ + /** + * Alignment of the label compared to the axis. Defaults to `"left"` for + * right-side axes, `"right"` for left-side axes and `"center"` for + * horizontal axes. + * + * @type {Highcharts.AlignValue} + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.align + */ + /** + * The background color for the label. Defaults to the related series + * color, or `#666666` if that is not available. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.backgroundColor + */ + /** + * The border color for the crosshair label + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.borderColor + */ + /** + * The border corner radius of the crosshair label. + * + * @type {number} + * @default 3 + * @since 2.1.10 + * @product highstock + * @apioption xAxis.crosshair.label.borderRadius + */ + /** + * The border width for the crosshair label. + * + * @type {number} + * @default 0 + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.borderWidth + */ + /** + * Flag to enable crosshair's label. + * + * @sample {highstock} stock/xaxis/crosshairs-xy/ + * Enabled label for yAxis' crosshair + * + * @type {boolean} + * @default false + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.enabled + */ + /** + * A format string for the crosshair label. Defaults to `{value}` for + * numeric axes and `{value:%b %d, %Y}` for datetime axes. + * + * @type {string} + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.format + */ + /** + * Formatter function for the label text. + * + * @type {Highcharts.XAxisCrosshairLabelFormatterCallbackFunction} + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.formatter + */ + /** + * Padding inside the crosshair label. + * + * @type {number} + * @default 8 + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.padding + */ + /** + * The shape to use for the label box. + * + * @type {string} + * @default callout + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.shape + */ + /** + * Text styles for the crosshair label. + * + * @type {Highcharts.CSSObject} + * @default {"color": "white", "fontWeight": "normal", "fontSize": "11px", "textAlign": "center"} + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.style + */ + /** + * Whether the crosshair should snap to the point or follow the pointer + * independent of points. + * + * @sample {highcharts|highstock} highcharts/xaxis/crosshair-snap-false/ + * True by default + * @sample {highmaps} maps/demo/latlon-advanced/ + * Snap is false + * + * @type {boolean} + * @default true + * @since 4.1 + * @apioption xAxis.crosshair.snap + */ + /** + * The pixel width of the crosshair. Defaults to 1 for numeric or + * datetime axes, and for one category width for category axes. + * + * @sample {highcharts} highcharts/xaxis/crosshair-customized/ + * Customized crosshairs + * @sample {highstock} highcharts/xaxis/crosshair-customized/ + * Customized crosshairs + * @sample {highmaps} highcharts/xaxis/crosshair-customized/ + * Customized crosshairs + * + * @type {number} + * @default 1 + * @since 4.1 + * @apioption xAxis.crosshair.width + */ + /** + * The Z index of the crosshair. Higher Z indices allow drawing the + * crosshair on top of the series or behind the grid lines. + * + * @type {number} + * @default 2 + * @since 4.1 + * @apioption xAxis.crosshair.zIndex + */ + /** + * Whether to zoom axis. If `chart.zoomType` is set, the option allows + * to disable zooming on an individual axis. + * + * @sample {highcharts} highcharts/xaxis/zoomenabled/ + * Zoom enabled is false + * + * + * @type {boolean} + * @default enabled + * @apioption xAxis.zoomEnabled + */ + /** + * For a datetime axis, the scale will automatically adjust to the + * appropriate unit. This member gives the default string + * representations used for each unit. For intermediate values, + * different units may be used, for example the `day` unit can be used + * on midnight and `hour` unit be used for intermediate values on the + * same axis. For an overview of the replacement codes, see + * [dateFormat](/class-reference/Highcharts#dateFormat). + * + * Defaults to: + * ```js + * { + * millisecond: '%H:%M:%S.%L', + * second: '%H:%M:%S', + * minute: '%H:%M', + * hour: '%H:%M', + * day: '%e. %b', + * week: '%e. %b', + * month: '%b \'%y', + * year: '%Y' + * } + * ``` + * + * @sample {highcharts} highcharts/xaxis/datetimelabelformats/ + * Different day format on X axis + * @sample {highstock} stock/xaxis/datetimelabelformats/ + * More information in x axis labels + * + * @declare Highcharts.AxisDateTimeLabelFormatsOptions + * @product highcharts highstock gantt + */ + dateTimeLabelFormats: { + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + millisecond: { + main: '%H:%M:%S.%L', + range: false + }, + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + second: { + main: '%H:%M:%S', + range: false + }, + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + minute: { + main: '%H:%M', + range: false + }, + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + hour: { + main: '%H:%M', + range: false + }, + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + day: { + main: '%e. %b' + }, + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + week: { + main: '%e. %b' + }, + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + month: { + main: '%b \'%y' + }, + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + year: { + main: '%Y' + } + }, + /** + * Whether to force the axis to end on a tick. Use this option with + * the `maxPadding` option to control the axis end. + * + * @productdesc {highstock} + * In Highstock, `endOnTick` is always `false` when the navigator + * is enabled, to prevent jumpy scrolling. + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * True by default + * @sample {highcharts} highcharts/yaxis/endontick/ + * False + * @sample {highstock} stock/demo/basic-line/ + * True by default + * @sample {highstock} stock/xaxis/endontick/ + * False + * + * @since 1.2.0 + */ + endOnTick: false, + /** + * Event handlers for the axis. + * + * @type {*} + * @apioption xAxis.events + */ + /** + * An event fired after the breaks have rendered. + * + * @see [breaks](#xAxis.breaks) + * + * @sample {highcharts} highcharts/axisbreak/break-event/ + * AfterBreak Event + * + * @type {Highcharts.AxisEventCallbackFunction} + * @since 4.1.0 + * @product highcharts gantt + * @apioption xAxis.events.afterBreaks + */ + /** + * As opposed to the `setExtremes` event, this event fires after the + * final min and max values are computed and corrected for `minRange`. + * + * Fires when the minimum and maximum is set for the axis, either by + * calling the `.setExtremes()` method or by selecting an area in the + * chart. One parameter, `event`, is passed to the function, containing + * common event information. + * + * The new user set minimum and maximum values can be found by + * `event.min` and `event.max`. These reflect the axis minimum and + * maximum in axis values. The actual data extremes are found in + * `event.dataMin` and `event.dataMax`. + * + * @type {Highcharts.AxisSetExtremesEventCallbackFunction} + * @since 2.3 + * @context Highcharts.Axis + * @apioption xAxis.events.afterSetExtremes + */ + /** + * An event fired when a break from this axis occurs on a point. + * + * @see [breaks](#xAxis.breaks) + * + * @sample {highcharts} highcharts/axisbreak/break-visualized/ + * Visualization of a Break + * + * @type {Highcharts.AxisPointBreakEventCallbackFunction} + * @since 4.1.0 + * @product highcharts gantt + * @context Highcharts.Axis + * @apioption xAxis.events.pointBreak + */ + /** + * An event fired when a point falls inside a break from this axis. + * + * @type {Highcharts.AxisPointBreakEventCallbackFunction} + * @product highcharts highstock gantt + * @context Highcharts.Axis + * @apioption xAxis.events.pointInBreak + */ + /** + * Fires when the minimum and maximum is set for the axis, either by + * calling the `.setExtremes()` method or by selecting an area in the + * chart. One parameter, `event`, is passed to the function, + * containing common event information. + * + * The new user set minimum and maximum values can be found by + * `event.min` and `event.max`. These reflect the axis minimum and + * maximum in data values. When an axis is zoomed all the way out from + * the "Reset zoom" button, `event.min` and `event.max` are null, and + * the new extremes are set based on `this.dataMin` and `this.dataMax`. + * + * @sample {highstock} stock/xaxis/events-setextremes/ + * Log new extremes on x axis + * + * @type {Highcharts.AxisSetExtremesEventCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Axis + * @apioption xAxis.events.setExtremes + */ + /** + * The lowest allowed value for automatically computed axis extremes. + * + * @see [ceiling](#yAxis.ceiling) + * + * @sample {highcharts} highcharts/yaxis/floor-ceiling/ + * Floor and ceiling + * @sample {highstock} stock/demo/lazy-loading/ + * Prevent negative stock price on Y axis + * + * @type {number} + * @since 4.0 + * @product highcharts highstock gantt + * @apioption xAxis.floor + */ + /** + * The dash or dot style of the grid lines. For possible values, see + * [this demonstration](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/). + * + * @sample {highcharts} highcharts/yaxis/gridlinedashstyle/ + * Long dashes + * @sample {highstock} stock/xaxis/gridlinedashstyle/ + * Long dashes + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 1.2 + * @apioption xAxis.gridLineDashStyle + */ + /** + * The Z index of the grid lines. + * + * @sample {highcharts|highstock} highcharts/xaxis/gridzindex/ + * A Z index of 4 renders the grid above the graph + * + * @type {number} + * @default 1 + * @product highcharts highstock gantt + * @apioption xAxis.gridZIndex + */ + /** + * An id for the axis. This can be used after render time to get + * a pointer to the axis object through `chart.get()`. + * + * @sample {highcharts} highcharts/xaxis/id/ + * Get the object + * @sample {highstock} stock/xaxis/id/ + * Get the object + * + * @type {string} + * @since 1.2.0 + * @apioption xAxis.id + */ + /** + * The axis labels show the number or category for each tick. + * + * Since v8.0.0: Labels are animated in categorized x-axis with + * updating data if `tickInterval` and `step` is set to 1. + * + * @productdesc {highmaps} + * X and Y axis labels are by default disabled in Highmaps, but the + * functionality is inherited from Highcharts and used on `colorAxis`, + * and can be enabled on X and Y axes too. + */ + labels: { + /** + * What part of the string the given position is anchored to. + * If `left`, the left side of the string is at the axis position. + * Can be one of `"left"`, `"center"` or `"right"`. Defaults to + * an intelligent guess based on which side of the chart the axis + * is on and the rotation of the label. + * + * @see [reserveSpace](#xAxis.labels.reserveSpace) + * + * @sample {highcharts} highcharts/xaxis/labels-align-left/ + * Left + * @sample {highcharts} highcharts/xaxis/labels-align-right/ + * Right + * @sample {highcharts} highcharts/xaxis/labels-reservespace-true/ + * Left-aligned labels on a vertical category axis + * + * @type {Highcharts.AlignValue} + * @apioption xAxis.labels.align + */ + /** + * For horizontal axes, the allowed degrees of label rotation + * to prevent overlapping labels. If there is enough space, + * labels are not rotated. As the chart gets narrower, it + * will start rotating the labels -45 degrees, then remove + * every second label and try again with rotations 0 and -45 etc. + * Set it to `false` to disable rotation, which will + * cause the labels to word-wrap if possible. + * + * @sample {highcharts|highstock} highcharts/xaxis/labels-autorotation-default/ + * Default auto rotation of 0 or -45 + * @sample {highcharts|highstock} highcharts/xaxis/labels-autorotation-0-90/ + * Custom graded auto rotation + * + * @type {Array|false} + * @default [-45] + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption xAxis.labels.autoRotation + */ + /** + * When each category width is more than this many pixels, we don't + * apply auto rotation. Instead, we lay out the axis label with word + * wrap. A lower limit makes sense when the label contains multiple + * short words that don't extend the available horizontal space for + * each label. + * + * @sample {highcharts} highcharts/xaxis/labels-autorotationlimit/ + * Lower limit + * + * @type {number} + * @default 80 + * @since 4.1.5 + * @product highcharts gantt + * @apioption xAxis.labels.autoRotationLimit + */ + /** + * Polar charts only. The label's pixel distance from the perimeter + * of the plot area. + * + * @type {number} + * @default 15 + * @product highcharts gantt + * @apioption xAxis.labels.distance + */ + /** + * Enable or disable the axis labels. + * + * @sample {highcharts} highcharts/xaxis/labels-enabled/ + * X axis labels disabled + * @sample {highstock} stock/xaxis/labels-enabled/ + * X axis labels disabled + * + * @default {highcharts|highstock|gantt} true + * @default {highmaps} false + */ + enabled: true, + /** + * A [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) + * for the axis label. + * + * @sample {highcharts|highstock} highcharts/yaxis/labels-format/ + * Add units to Y axis label + * + * @type {string} + * @default {value} + * @since 3.0 + * @apioption xAxis.labels.format + */ + /** + * Callback JavaScript function to format the label. The value + * is given by `this.value`. Additional properties for `this` are + * `axis`, `chart`, `isFirst` and `isLast`. The value of the default + * label formatter can be retrieved by calling + * `this.axis.defaultLabelFormatter.call(this)` within the function. + * + * Defaults to: + * ```js + * function() { + * return this.value; + * } + * ``` + * + * @sample {highcharts} highcharts/xaxis/labels-formatter-linked/ + * Linked category names + * @sample {highcharts} highcharts/xaxis/labels-formatter-extended/ + * Modified numeric labels + * @sample {highstock} stock/xaxis/labels-formatter/ + * Added units on Y axis + * + * @type {Highcharts.FormatterCallbackFunction} + * @apioption xAxis.labels.formatter + */ + /** + * The number of pixels to indent the labels per level in a treegrid + * axis. + * + * @sample gantt/treegrid-axis/demo + * Indentation 10px by default. + * @sample gantt/treegrid-axis/indentation-0px + * Indentation set to 0px. + * + * @product gantt + */ + indentation: 10, + /** + * Horizontal axis only. When `staggerLines` is not set, + * `maxStaggerLines` defines how many lines the axis is allowed to + * add to automatically avoid overlapping X labels. Set to `1` to + * disable overlap detection. + * + * @deprecated + * @type {number} + * @default 5 + * @since 1.3.3 + * @apioption xAxis.labels.maxStaggerLines + */ + /** + * How to handle overflowing labels on horizontal axis. If set to + * `"allow"`, it will not be aligned at all. By default it + * `"justify"` labels inside the chart area. If there is room to + * move it, it will be aligned to the edge, else it will be removed. + * + * @type {string} + * @default justify + * @since 2.2.5 + * @validvalue ["allow", "justify"] + * @apioption xAxis.labels.overflow + */ + /** + * The pixel padding for axis labels, to ensure white space between + * them. + * + * @type {number} + * @default 5 + * @product highcharts gantt + * @apioption xAxis.labels.padding + */ + /** + * Whether to reserve space for the labels. By default, space is + * reserved for the labels in these cases: + * + * * On all horizontal axes. + * * On vertical axes if `label.align` is `right` on a left-side + * axis or `left` on a right-side axis. + * * On vertical axes if `label.align` is `center`. + * + * This can be turned off when for example the labels are rendered + * inside the plot area instead of outside. + * + * @see [labels.align](#xAxis.labels.align) + * + * @sample {highcharts} highcharts/xaxis/labels-reservespace/ + * No reserved space, labels inside plot + * @sample {highcharts} highcharts/xaxis/labels-reservespace-true/ + * Left-aligned labels on a vertical category axis + * + * @type {boolean} + * @since 4.1.10 + * @product highcharts gantt + * @apioption xAxis.labels.reserveSpace + */ + /** + * Rotation of the labels in degrees. + * + * @sample {highcharts} highcharts/xaxis/labels-rotation/ + * X axis labels rotated 90° + * + * @type {number} + * @default 0 + * @apioption xAxis.labels.rotation + */ + /** + * Horizontal axes only. The number of lines to spread the labels + * over to make room or tighter labels. + * + * @sample {highcharts} highcharts/xaxis/labels-staggerlines/ + * Show labels over two lines + * @sample {highstock} stock/xaxis/labels-staggerlines/ + * Show labels over two lines + * + * @type {number} + * @since 2.1 + * @apioption xAxis.labels.staggerLines + */ + /** + * To show only every _n_'th label on the axis, set the step to _n_. + * Setting the step to 2 shows every other label. + * + * By default, the step is calculated automatically to avoid + * overlap. To prevent this, set it to 1\. This usually only + * happens on a category axis, and is often a sign that you have + * chosen the wrong axis type. + * + * Read more at + * [Axis docs](https://www.highcharts.com/docs/chart-concepts/axes) + * => What axis should I use? + * + * @sample {highcharts} highcharts/xaxis/labels-step/ + * Showing only every other axis label on a categorized + * x-axis + * @sample {highcharts} highcharts/xaxis/labels-step-auto/ + * Auto steps on a category axis + * + * @type {number} + * @since 2.1 + * @apioption xAxis.labels.step + */ + /** + * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the labels. + * + * @type {boolean} + * @default false + * @apioption xAxis.labels.useHTML + */ + /** + * The x position offset of the label relative to the tick position + * on the axis. + * + * @sample {highcharts} highcharts/xaxis/labels-x/ + * Y axis labels placed on grid lines + */ + x: 0, + /** + * The y position offset of the label relative to the tick position + * on the axis. The default makes it adapt to the font size on + * bottom axis. + * + * @sample {highcharts} highcharts/xaxis/labels-x/ + * Y axis labels placed on grid lines + * + * @type {number} + * @apioption xAxis.labels.y + */ + /** + * The Z index for the axis labels. + * + * @type {number} + * @default 7 + * @apioption xAxis.labels.zIndex + */ + /** + * CSS styles for the label. Use `whiteSpace: 'nowrap'` to prevent + * wrapping of category labels. Use `textOverflow: 'none'` to + * prevent ellipsis (dots). + * + * In styled mode, the labels are styled with the + * `.highcharts-axis-labels` class. + * + * @sample {highcharts} highcharts/xaxis/labels-style/ + * Red X axis labels + * + * @type {Highcharts.CSSObject} + */ + style: { + /** @internal */ + color: '#666666', + /** @internal */ + cursor: 'default', + /** @internal */ + fontSize: '11px' + } + }, + /** + * The left position as the horizontal axis. If it's a number, it is + * interpreted as pixel position relative to the chart. + * + * Since Highcharts v5.0.13: If it's a percentage string, it is + * interpreted as percentages of the plot width, offset from plot area + * left. + * + * @type {number|string} + * @product highcharts highstock + * @apioption xAxis.left + */ + /** + * The top position as the vertical axis. If it's a number, it is + * interpreted as pixel position relative to the chart. + * + * Since Highcharts 2: If it's a percentage string, it is interpreted + * as percentages of the plot height, offset from plot area top. + * + * @type {number|string} + * @product highcharts highstock + * @apioption xAxis.top + */ + /** + * Index of another axis that this axis is linked to. When an axis is + * linked to a master axis, it will take the same extremes as + * the master, but as assigned by min or max or by setExtremes. + * It can be used to show additional info, or to ease reading the + * chart by duplicating the scales. + * + * @sample {highcharts} highcharts/xaxis/linkedto/ + * Different string formats of the same date + * @sample {highcharts} highcharts/yaxis/linkedto/ + * Y values on both sides + * + * @type {number} + * @since 2.0.2 + * @product highcharts highstock gantt + * @apioption xAxis.linkedTo + */ + /** + * The maximum value of the axis. If `null`, the max value is + * automatically calculated. + * + * If the [endOnTick](#yAxis.endOnTick) option is true, the `max` value + * might be rounded up. + * + * If a [tickAmount](#yAxis.tickAmount) is set, the axis may be extended + * beyond the set max in order to reach the given number of ticks. The + * same may happen in a chart with multiple axes, determined by [chart. + * alignTicks](#chart), where a `tickAmount` is applied internally. + * + * @sample {highcharts} highcharts/yaxis/max-200/ + * Y axis max of 200 + * @sample {highcharts} highcharts/yaxis/max-logarithmic/ + * Y axis max on logarithmic axis + * @sample {highstock} stock/xaxis/min-max/ + * Fixed min and max on X axis + * @sample {highmaps} maps/axis/min-max/ + * Pre-zoomed to a specific area + * + * @type {number|null} + * @apioption xAxis.max + */ + /** + * Padding of the max value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. This is useful + * when you don't want the highest data value to appear on the edge + * of the plot area. When the axis' `max` option is set or a max extreme + * is set using `axis.setExtremes()`, the maxPadding will be ignored. + * + * @sample {highcharts} highcharts/yaxis/maxpadding/ + * Max padding of 0.25 on y axis + * @sample {highstock} stock/xaxis/minpadding-maxpadding/ + * Greater min- and maxPadding + * @sample {highmaps} maps/chart/plotbackgroundcolor-gradient/ + * Add some padding + * + * @default {highcharts} 0.01 + * @default {highstock|highmaps} 0 + * @since 1.2.0 + */ + maxPadding: 0.01, + /** + * Deprecated. Use `minRange` instead. + * + * @deprecated + * @type {number} + * @product highcharts highstock + * @apioption xAxis.maxZoom + */ + /** + * The minimum value of the axis. If `null` the min value is + * automatically calculated. + * + * If the [startOnTick](#yAxis.startOnTick) option is true (default), + * the `min` value might be rounded down. + * + * The automatically calculated minimum value is also affected by + * [floor](#yAxis.floor), [softMin](#yAxis.softMin), + * [minPadding](#yAxis.minPadding), [minRange](#yAxis.minRange) + * as well as [series.threshold](#plotOptions.series.threshold) + * and [series.softThreshold](#plotOptions.series.softThreshold). + * + * @sample {highcharts} highcharts/yaxis/min-startontick-false/ + * -50 with startOnTick to false + * @sample {highcharts} highcharts/yaxis/min-startontick-true/ + * -50 with startOnTick true by default + * @sample {highstock} stock/xaxis/min-max/ + * Set min and max on X axis + * @sample {highmaps} maps/axis/min-max/ + * Pre-zoomed to a specific area + * + * @type {number|null} + * @apioption xAxis.min + */ + /** + * The dash or dot style of the minor grid lines. For possible values, + * see [this demonstration](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/). + * + * @sample {highcharts} highcharts/yaxis/minorgridlinedashstyle/ + * Long dashes on minor grid lines + * @sample {highstock} stock/xaxis/minorgridlinedashstyle/ + * Long dashes on minor grid lines + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 1.2 + * @apioption xAxis.minorGridLineDashStyle + */ + /** + * Specific tick interval in axis units for the minor ticks. On a linear + * axis, if `"auto"`, the minor tick interval is calculated as a fifth + * of the tickInterval. If `null` or `undefined`, minor ticks are not + * shown. + * + * On logarithmic axes, the unit is the power of the value. For example, + * setting the minorTickInterval to 1 puts one tick on each of 0.1, 1, + * 10, 100 etc. Setting the minorTickInterval to 0.1 produces 9 ticks + * between 1 and 10, 10 and 100 etc. + * + * If user settings dictate minor ticks to become too dense, they don't + * make sense, and will be ignored to prevent performance problems. + * + * @sample {highcharts} highcharts/yaxis/minortickinterval-null/ + * Null by default + * @sample {highcharts} highcharts/yaxis/minortickinterval-5/ + * 5 units + * @sample {highcharts} highcharts/yaxis/minortickinterval-log-auto/ + * "auto" + * @sample {highcharts} highcharts/yaxis/minortickinterval-log/ + * 0.1 + * @sample {highstock} stock/demo/basic-line/ + * Null by default + * @sample {highstock} stock/xaxis/minortickinterval-auto/ + * "auto" + * + * @type {number|string|null} + * @apioption xAxis.minorTickInterval + */ + /** + * The pixel length of the minor tick marks. + * + * @sample {highcharts} highcharts/yaxis/minorticklength/ + * 10px on Y axis + * @sample {highstock} stock/xaxis/minorticks/ + * 10px on Y axis + */ + minorTickLength: 2, + /** + * The position of the minor tick marks relative to the axis line. + * Can be one of `inside` and `outside`. + * + * @sample {highcharts} highcharts/yaxis/minortickposition-outside/ + * Outside by default + * @sample {highcharts} highcharts/yaxis/minortickposition-inside/ + * Inside + * @sample {highstock} stock/xaxis/minorticks/ + * Inside + * + * @validvalue ["inside", "outside"] + */ + minorTickPosition: 'outside', + /** + * Enable or disable minor ticks. Unless + * [minorTickInterval](#xAxis.minorTickInterval) is set, the tick + * interval is calculated as a fifth of the `tickInterval`. + * + * On a logarithmic axis, minor ticks are laid out based on a best + * guess, attempting to enter approximately 5 minor ticks between + * each major tick. + * + * Prior to v6.0.0, ticks were unabled in auto layout by setting + * `minorTickInterval` to `"auto"`. + * + * @productdesc {highcharts} + * On axes using [categories](#xAxis.categories), minor ticks are not + * supported. + * + * @sample {highcharts} highcharts/yaxis/minorticks-true/ + * Enabled on linear Y axis + * + * @type {boolean} + * @default false + * @since 6.0.0 + * @apioption xAxis.minorTicks + */ + /** + * The pixel width of the minor tick mark. + * + * @sample {highcharts} highcharts/yaxis/minortickwidth/ + * 3px width + * @sample {highstock} stock/xaxis/minorticks/ + * 1px width + * + * @type {number} + * @default 0 + * @apioption xAxis.minorTickWidth + */ + /** + * Padding of the min value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. This is useful + * when you don't want the lowest data value to appear on the edge + * of the plot area. When the axis' `min` option is set or a min extreme + * is set using `axis.setExtremes()`, the minPadding will be ignored. + * + * @sample {highcharts} highcharts/yaxis/minpadding/ + * Min padding of 0.2 + * @sample {highstock} stock/xaxis/minpadding-maxpadding/ + * Greater min- and maxPadding + * @sample {highmaps} maps/chart/plotbackgroundcolor-gradient/ + * Add some padding + * + * @default {highcharts} 0.01 + * @default {highstock|highmaps} 0 + * @since 1.2.0 + * @product highcharts highstock gantt + */ + minPadding: 0.01, + /** + * The minimum range to display on this axis. The entire axis will not + * be allowed to span over a smaller interval than this. For example, + * for a datetime axis the main unit is milliseconds. If minRange is + * set to 3600000, you can't zoom in more than to one hour. + * + * The default minRange for the x axis is five times the smallest + * interval between any of the data points. + * + * On a logarithmic axis, the unit for the minimum range is the power. + * So a minRange of 1 means that the axis can be zoomed to 10-100, + * 100-1000, 1000-10000 etc. + * + * Note that the `minPadding`, `maxPadding`, `startOnTick` and + * `endOnTick` settings also affect how the extremes of the axis + * are computed. + * + * @sample {highcharts} highcharts/xaxis/minrange/ + * Minimum range of 5 + * @sample {highstock} stock/xaxis/minrange/ + * Max zoom of 6 months overrides user selections + * @sample {highmaps} maps/axis/minrange/ + * Minimum range of 1000 + * + * @type {number} + * @apioption xAxis.minRange + */ + /** + * The minimum tick interval allowed in axis values. For example on + * zooming in on an axis with daily data, this can be used to prevent + * the axis from showing hours. Defaults to the closest distance between + * two points on the axis. + * + * @type {number} + * @since 2.3.0 + * @apioption xAxis.minTickInterval + */ + /** + * The distance in pixels from the plot area to the axis line. + * A positive offset moves the axis with it's line, labels and ticks + * away from the plot area. This is typically used when two or more + * axes are displayed on the same side of the plot. With multiple + * axes the offset is dynamically adjusted to avoid collision, this + * can be overridden by setting offset explicitly. + * + * @sample {highcharts} highcharts/yaxis/offset/ + * Y axis offset of 70 + * @sample {highcharts} highcharts/yaxis/offset-centered/ + * Axes positioned in the center of the plot + * @sample {highstock} stock/xaxis/offset/ + * Y axis offset by 70 px + * + * @type {number} + * @default 0 + * @apioption xAxis.offset + */ + /** + * Whether to display the axis on the opposite side of the normal. The + * normal is on the left side for vertical axes and bottom for + * horizontal, so the opposite sides will be right and top respectively. + * This is typically used with dual or multiple axes. + * + * @sample {highcharts} highcharts/yaxis/opposite/ + * Secondary Y axis opposite + * @sample {highstock} stock/xaxis/opposite/ + * Y axis on left side + * + * @type {boolean} + * @default false + * @apioption xAxis.opposite + */ + /** + * In an ordinal axis, the points are equally spaced in the chart + * regardless of the actual time or x distance between them. This means + * that missing data periods (e.g. nights or weekends for a stock chart) + * will not take up space in the chart. + * Having `ordinal: false` will show any gaps created by the `gapSize` + * setting proportionate to their duration. + * + * In stock charts the X axis is ordinal by default, unless + * the boost module is used and at least one of the series' data length + * exceeds the [boostThreshold](#series.line.boostThreshold). + * + * @sample {highstock} stock/xaxis/ordinal-true/ + * True by default + * @sample {highstock} stock/xaxis/ordinal-false/ + * False + * + * @type {boolean} + * @default true + * @since 1.1 + * @product highstock + * @apioption xAxis.ordinal + */ + /** + * Additional range on the right side of the xAxis. Works similar to + * `xAxis.maxPadding`, but value is set in milliseconds. Can be set for + * both main `xAxis` and the navigator's `xAxis`. + * + * @sample {highstock} stock/xaxis/overscroll/ + * One minute overscroll with live data + * + * @type {number} + * @default 0 + * @since 6.0.0 + * @product highstock + * @apioption xAxis.overscroll + */ + /** + * Refers to the index in the [panes](#panes) array. Used for circular + * gauges and polar charts. When the option is not set then first pane + * will be used. + * + * @sample highcharts/demo/gauge-vu-meter + * Two gauges with different center + * + * @type {number} + * @product highcharts + * @apioption xAxis.pane + */ + /** + * The zoomed range to display when only defining one or none of `min` + * or `max`. For example, to show the latest month, a range of one month + * can be set. + * + * @sample {highstock} stock/xaxis/range/ + * Setting a zoomed range when the rangeSelector is disabled + * + * @type {number} + * @product highstock + * @apioption xAxis.range + */ + /** + * Whether to reverse the axis so that the highest number is closest + * to the origin. If the chart is inverted, the x axis is reversed by + * default. + * + * @sample {highcharts} highcharts/yaxis/reversed/ + * Reversed Y axis + * @sample {highstock} stock/xaxis/reversed/ + * Reversed Y axis + * + * @type {boolean} + * @default false + * @apioption xAxis.reversed + */ + // reversed: false, + /** + * This option determines how stacks should be ordered within a group. + * For example reversed xAxis also reverses stacks, so first series + * comes last in a group. To keep order like for non-reversed xAxis + * enable this option. + * + * @sample {highcharts} highcharts/xaxis/reversedstacks/ + * Reversed stacks comparison + * @sample {highstock} highcharts/xaxis/reversedstacks/ + * Reversed stacks comparison + * + * @type {boolean} + * @default false + * @since 6.1.1 + * @product highcharts highstock + * @apioption xAxis.reversedStacks + */ + /** + * An optional scrollbar to display on the X axis in response to + * limiting the minimum and maximum of the axis values. + * + * In styled mode, all the presentational options for the scrollbar are + * replaced by the classes `.highcharts-scrollbar-thumb`, + * `.highcharts-scrollbar-arrow`, `.highcharts-scrollbar-button`, + * `.highcharts-scrollbar-rifles` and `.highcharts-scrollbar-track`. + * + * @sample {highstock} stock/yaxis/heatmap-scrollbars/ + * Heatmap with both scrollbars + * + * @extends scrollbar + * @since 4.2.6 + * @product highstock + * @apioption xAxis.scrollbar + */ + /** + * Whether to show the axis line and title when the axis has no data. + * + * @sample {highcharts} highcharts/yaxis/showempty/ + * When clicking the legend to hide series, one axis preserves + * line and title, the other doesn't + * @sample {highstock} highcharts/yaxis/showempty/ + * When clicking the legend to hide series, one axis preserves + * line and title, the other doesn't + * + * @since 1.1 + */ + showEmpty: true, + /** + * Whether to show the first tick label. + * + * @sample {highcharts} highcharts/xaxis/showfirstlabel-false/ + * Set to false on X axis + * @sample {highstock} stock/xaxis/showfirstlabel/ + * Labels below plot lines on Y axis + * + * @type {boolean} + * @default true + * @apioption xAxis.showFirstLabel + */ + /** + * Whether to show the last tick label. Defaults to `true` on cartesian + * charts, and `false` on polar charts. + * + * @sample {highcharts} highcharts/xaxis/showlastlabel-true/ + * Set to true on X axis + * @sample {highstock} stock/xaxis/showfirstlabel/ + * Labels below plot lines on Y axis + * + * @type {boolean} + * @default true + * @product highcharts highstock gantt + * @apioption xAxis.showLastLabel + */ + /** + * A soft maximum for the axis. If the series data maximum is less than + * this, the axis will stay at this maximum, but if the series data + * maximum is higher, the axis will flex to show all data. + * + * @sample highcharts/yaxis/softmin-softmax/ + * Soft min and max + * + * @type {number} + * @since 5.0.1 + * @product highcharts highstock gantt + * @apioption xAxis.softMax + */ + /** + * A soft minimum for the axis. If the series data minimum is greater + * than this, the axis will stay at this minimum, but if the series + * data minimum is lower, the axis will flex to show all data. + * + * @sample highcharts/yaxis/softmin-softmax/ + * Soft min and max + * + * @type {number} + * @since 5.0.1 + * @product highcharts highstock gantt + * @apioption xAxis.softMin + */ + /** + * For datetime axes, this decides where to put the tick between weeks. + * 0 = Sunday, 1 = Monday. + * + * @sample {highcharts} highcharts/xaxis/startofweek-monday/ + * Monday by default + * @sample {highcharts} highcharts/xaxis/startofweek-sunday/ + * Sunday + * @sample {highstock} stock/xaxis/startofweek-1 + * Monday by default + * @sample {highstock} stock/xaxis/startofweek-0 + * Sunday + * + * @product highcharts highstock gantt + */ + startOfWeek: 1, + /** + * Whether to force the axis to start on a tick. Use this option with + * the `minPadding` option to control the axis start. + * + * @productdesc {highstock} + * In Highstock, `startOnTick` is always `false` when the navigator + * is enabled, to prevent jumpy scrolling. + * + * @sample {highcharts} highcharts/xaxis/startontick-false/ + * False by default + * @sample {highcharts} highcharts/xaxis/startontick-true/ + * True + * + * @since 1.2.0 + */ + startOnTick: false, + /** + * The amount of ticks to draw on the axis. This opens up for aligning + * the ticks of multiple charts or panes within a chart. This option + * overrides the `tickPixelInterval` option. + * + * This option only has an effect on linear axes. Datetime, logarithmic + * or category axes are not affected. + * + * @sample {highcharts} highcharts/yaxis/tickamount/ + * 8 ticks on Y axis + * @sample {highstock} highcharts/yaxis/tickamount/ + * 8 ticks on Y axis + * + * @type {number} + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption xAxis.tickAmount + */ + /** + * The interval of the tick marks in axis units. When `undefined`, the + * tick interval is computed to approximately follow the + * [tickPixelInterval](#xAxis.tickPixelInterval) on linear and datetime + * axes. On categorized axes, a `undefined` tickInterval will default to + * 1, one category. Note that datetime axes are based on milliseconds, + * so for example an interval of one day is expressed as + * `24 * 3600 * 1000`. + * + * On logarithmic axes, the tickInterval is based on powers, so a + * tickInterval of 1 means one tick on each of 0.1, 1, 10, 100 etc. A + * tickInterval of 2 means a tick of 0.1, 10, 1000 etc. A tickInterval + * of 0.2 puts a tick on 0.1, 0.2, 0.4, 0.6, 0.8, 1, 2, 4, 6, 8, 10, 20, + * 40 etc. + * + * + * If the tickInterval is too dense for labels to be drawn, Highcharts + * may remove ticks. + * + * If the chart has multiple axes, the [alignTicks](#chart.alignTicks) + * option may interfere with the `tickInterval` setting. + * + * @see [tickPixelInterval](#xAxis.tickPixelInterval) + * @see [tickPositions](#xAxis.tickPositions) + * @see [tickPositioner](#xAxis.tickPositioner) + * + * @sample {highcharts} highcharts/xaxis/tickinterval-5/ + * Tick interval of 5 on a linear axis + * @sample {highstock} stock/xaxis/tickinterval/ + * Tick interval of 0.01 on Y axis + * + * @type {number} + * @apioption xAxis.tickInterval + */ + /** + * The pixel length of the main tick marks. + * + * @sample {highcharts} highcharts/xaxis/ticklength/ + * 20 px tick length on the X axis + * @sample {highstock} stock/xaxis/ticks/ + * Formatted ticks on X axis + */ + tickLength: 10, + /** + * If tickInterval is `null` this option sets the approximate pixel + * interval of the tick marks. Not applicable to categorized axis. + * + * The tick interval is also influenced by the [minTickInterval]( + * #xAxis.minTickInterval) option, that, by default prevents ticks from + * being denser than the data points. + * + * @see [tickInterval](#xAxis.tickInterval) + * @see [tickPositioner](#xAxis.tickPositioner) + * @see [tickPositions](#xAxis.tickPositions) + * + * @sample {highcharts} highcharts/xaxis/tickpixelinterval-50/ + * 50 px on X axis + * @sample {highstock} stock/xaxis/tickpixelinterval/ + * 200 px on X axis + */ + tickPixelInterval: 100, + /** + * For categorized axes only. If `on` the tick mark is placed in the + * center of the category, if `between` the tick mark is placed between + * categories. The default is `between` if the `tickInterval` is 1, else + * `on`. + * + * @sample {highcharts} highcharts/xaxis/tickmarkplacement-between/ + * "between" by default + * @sample {highcharts} highcharts/xaxis/tickmarkplacement-on/ + * "on" + * + * @product highcharts gantt + * @validvalue ["on", "between"] + */ + tickmarkPlacement: 'between', + /** + * The position of the major tick marks relative to the axis line. + * Can be one of `inside` and `outside`. + * + * @sample {highcharts} highcharts/xaxis/tickposition-outside/ + * "outside" by default + * @sample {highcharts} highcharts/xaxis/tickposition-inside/ + * "inside" + * @sample {highstock} stock/xaxis/ticks/ + * Formatted ticks on X axis + * + * @validvalue ["inside", "outside"] + */ + tickPosition: 'outside', + /** + * A callback function returning array defining where the ticks are + * laid out on the axis. This overrides the default behaviour of + * [tickPixelInterval](#xAxis.tickPixelInterval) and [tickInterval]( + * #xAxis.tickInterval). The automatic tick positions are accessible + * through `this.tickPositions` and can be modified by the callback. + * + * @see [tickPositions](#xAxis.tickPositions) + * + * @sample {highcharts} highcharts/xaxis/tickpositions-tickpositioner/ + * Demo of tickPositions and tickPositioner + * @sample {highstock} highcharts/xaxis/tickpositions-tickpositioner/ + * Demo of tickPositions and tickPositioner + * + * @type {Highcharts.AxisTickPositionerCallbackFunction} + * @apioption xAxis.tickPositioner + */ + /** + * An array defining where the ticks are laid out on the axis. This + * overrides the default behaviour of [tickPixelInterval]( + * #xAxis.tickPixelInterval) and [tickInterval](#xAxis.tickInterval). + * + * @see [tickPositioner](#xAxis.tickPositioner) + * + * @sample {highcharts} highcharts/xaxis/tickpositions-tickpositioner/ + * Demo of tickPositions and tickPositioner + * @sample {highstock} highcharts/xaxis/tickpositions-tickpositioner/ + * Demo of tickPositions and tickPositioner + * + * @type {Array} + * @apioption xAxis.tickPositions + */ + /** + * The pixel width of the major tick marks. Defaults to 0 on category + * axes, otherwise 1. + * + * In styled mode, the stroke width is given in the `.highcharts-tick` + * class, but in order for the element to be generated on category axes, + * the option must be explicitly set to 1. + * + * @sample {highcharts} highcharts/xaxis/tickwidth/ + * 10 px width + * @sample {highcharts} highcharts/css/axis-grid/ + * Styled mode + * @sample {highstock} stock/xaxis/ticks/ + * Formatted ticks on X axis + * @sample {highstock} highcharts/css/axis-grid/ + * Styled mode + * + * @type {undefined|number} + * @default {highstock} 1 + * @default {highmaps} 0 + * @apioption xAxis.tickWidth + */ + /** + * The axis title, showing next to the axis line. + * + * @productdesc {highmaps} + * In Highmaps, the axis is hidden by default, but adding an axis title + * is still possible. X axis and Y axis titles will appear at the bottom + * and left by default. + */ + title: { + /** + * Deprecated. Set the `text` to `null` to disable the title. + * + * @deprecated + * @type {boolean} + * @product highcharts + * @apioption xAxis.title.enabled + */ + /** + * The pixel distance between the axis labels or line and the title. + * Defaults to 0 for horizontal axes, 10 for vertical + * + * @sample {highcharts} highcharts/xaxis/title-margin/ + * Y axis title margin of 60 + * + * @type {number} + * @apioption xAxis.title.margin + */ + /** + * The distance of the axis title from the axis line. By default, + * this distance is computed from the offset width of the labels, + * the labels' distance from the axis and the title's margin. + * However when the offset option is set, it overrides all this. + * + * @sample {highcharts} highcharts/yaxis/title-offset/ + * Place the axis title on top of the axis + * @sample {highstock} highcharts/yaxis/title-offset/ + * Place the axis title on top of the Y axis + * + * @type {number} + * @since 2.2.0 + * @apioption xAxis.title.offset + */ + /** + * Whether to reserve space for the title when laying out the axis. + * + * @type {boolean} + * @default true + * @since 5.0.11 + * @product highcharts highstock gantt + * @apioption xAxis.title.reserveSpace + */ + /** + * The rotation of the text in degrees. 0 is horizontal, 270 is + * vertical reading from bottom to top. + * + * @sample {highcharts} highcharts/yaxis/title-offset/ + * Horizontal + * + * @type {number} + * @default 0 + * @apioption xAxis.title.rotation + */ + /** + * The actual text of the axis title. It can contain basic HTML tags + * like `b`, `i` and `span` with style. + * + * @sample {highcharts} highcharts/xaxis/title-text/ + * Custom HTML + * @sample {highstock} stock/xaxis/title-text/ + * Titles for both axes + * + * @type {string|null} + * @apioption xAxis.title.text + */ + /** + * Alignment of the text, can be `"left"`, `"right"` or `"center"`. + * Default alignment depends on the + * [title.align](xAxis.title.align): + * + * Horizontal axes: + * - for `align` = `"low"`, `textAlign` is set to `left` + * - for `align` = `"middle"`, `textAlign` is set to `center` + * - for `align` = `"high"`, `textAlign` is set to `right` + * + * Vertical axes: + * - for `align` = `"low"` and `opposite` = `true`, `textAlign` is + * set to `right` + * - for `align` = `"low"` and `opposite` = `false`, `textAlign` is + * set to `left` + * - for `align` = `"middle"`, `textAlign` is set to `center` + * - for `align` = `"high"` and `opposite` = `true` `textAlign` is + * set to `left` + * - for `align` = `"high"` and `opposite` = `false` `textAlign` is + * set to `right` + * + * @type {Highcharts.AlignValue} + * @apioption xAxis.title.textAlign + */ + /** + * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the axis title. + * + * @type {boolean} + * @default false + * @product highcharts highstock gantt + * @apioption xAxis.title.useHTML + */ + /** + * Horizontal pixel offset of the title position. + * + * @type {number} + * @default 0 + * @since 4.1.6 + * @product highcharts highstock gantt + * @apioption xAxis.title.x + */ + /** + * Vertical pixel offset of the title position. + * + * @type {number} + * @product highcharts highstock gantt + * @apioption xAxis.title.y + */ + /** + * Alignment of the title relative to the axis values. Possible + * values are "low", "middle" or "high". + * + * @sample {highcharts} highcharts/xaxis/title-align-low/ + * "low" + * @sample {highcharts} highcharts/xaxis/title-align-center/ + * "middle" by default + * @sample {highcharts} highcharts/xaxis/title-align-high/ + * "high" + * @sample {highcharts} highcharts/yaxis/title-offset/ + * Place the Y axis title on top of the axis + * @sample {highstock} stock/xaxis/title-align/ + * Aligned to "high" value + * + * @type {Highcharts.AxisTitleAlignValue} + */ + align: 'middle', + /** + * CSS styles for the title. If the title text is longer than the + * axis length, it will wrap to multiple lines by default. This can + * be customized by setting `textOverflow: 'ellipsis'`, by + * setting a specific `width` or by setting `whiteSpace: 'nowrap'`. + * + * In styled mode, the stroke width is given in the + * `.highcharts-axis-title` class. + * + * @sample {highcharts} highcharts/xaxis/title-style/ + * Red + * @sample {highcharts} highcharts/css/axis/ + * Styled mode + * + * @type {Highcharts.CSSObject} + */ + style: { + /** @internal */ + color: '#666666' + } + }, + /** + * The type of axis. Can be one of `linear`, `logarithmic`, `datetime` + * or `category`. In a datetime axis, the numbers are given in + * milliseconds, and tick marks are placed on appropriate values like + * full hours or days. In a category axis, the + * [point names](#series.line.data.name) of the chart's series are used + * for categories, if not a [categories](#xAxis.categories) array is + * defined. + * + * @sample {highcharts} highcharts/xaxis/type-linear/ + * Linear + * @sample {highcharts} highcharts/yaxis/type-log/ + * Logarithmic + * @sample {highcharts} highcharts/yaxis/type-log-minorgrid/ + * Logarithmic with minor grid lines + * @sample {highcharts} highcharts/xaxis/type-log-both/ + * Logarithmic on two axes + * @sample {highcharts} highcharts/yaxis/type-log-negative/ + * Logarithmic with extension to emulate negative values + * + * @type {Highcharts.AxisTypeValue} + * @product highcharts gantt + */ + type: 'linear', + /** + * If there are multiple axes on the same side of the chart, the pixel + * margin between the axes. Defaults to 0 on vertical axes, 15 on + * horizontal axes. + * + * @type {number} + * @since 7.0.3 + * @apioption xAxis.margin + */ + /** + * Applies only when the axis `type` is `category`. When `uniqueNames` + * is true, points are placed on the X axis according to their names. + * If the same point name is repeated in the same or another series, + * the point is placed on the same X position as other points of the + * same name. When `uniqueNames` is false, the points are laid out in + * increasing X positions regardless of their names, and the X axis + * category will take the name of the last point in each position. + * + * @sample {highcharts} highcharts/xaxis/uniquenames-true/ + * True by default + * @sample {highcharts} highcharts/xaxis/uniquenames-false/ + * False + * + * @type {boolean} + * @default true + * @since 4.2.7 + * @product highcharts gantt + * @apioption xAxis.uniqueNames + */ + /** + * Datetime axis only. An array determining what time intervals the + * ticks are allowed to fall on. Each array item is an array where the + * first value is the time unit and the second value another array of + * allowed multiples. + * + * Defaults to: + * ```js + * units: [[ + * 'millisecond', // unit name + * [1, 2, 5, 10, 20, 25, 50, 100, 200, 500] // allowed multiples + * ], [ + * 'second', + * [1, 2, 5, 10, 15, 30] + * ], [ + * 'minute', + * [1, 2, 5, 10, 15, 30] + * ], [ + * 'hour', + * [1, 2, 3, 4, 6, 8, 12] + * ], [ + * 'day', + * [1] + * ], [ + * 'week', + * [1] + * ], [ + * 'month', + * [1, 3, 6] + * ], [ + * 'year', + * null + * ]] + * ``` + * + * @type {Array|null)>>} + * @product highcharts highstock gantt + * @apioption xAxis.units + */ + /** + * Whether axis, including axis title, line, ticks and labels, should + * be visible. + * + * @type {boolean} + * @default true + * @since 4.1.9 + * @product highcharts highstock gantt + * @apioption xAxis.visible + */ + /** + * Color of the minor, secondary grid lines. + * + * In styled mode, the stroke width is given in the + * `.highcharts-minor-grid-line` class. + * + * @sample {highcharts} highcharts/yaxis/minorgridlinecolor/ + * Bright grey lines from Y axis + * @sample {highcharts|highstock} highcharts/css/axis-grid/ + * Styled mode + * @sample {highstock} stock/xaxis/minorgridlinecolor/ + * Bright grey lines from Y axis + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #f2f2f2 + */ + minorGridLineColor: '#f2f2f2', + /** + * Width of the minor, secondary grid lines. + * + * In styled mode, the stroke width is given in the + * `.highcharts-grid-line` class. + * + * @sample {highcharts} highcharts/yaxis/minorgridlinewidth/ + * 2px lines from Y axis + * @sample {highcharts|highstock} highcharts/css/axis-grid/ + * Styled mode + * @sample {highstock} stock/xaxis/minorgridlinewidth/ + * 2px lines from Y axis + */ + minorGridLineWidth: 1, + /** + * Color for the minor tick marks. + * + * @sample {highcharts} highcharts/yaxis/minortickcolor/ + * Black tick marks on Y axis + * @sample {highstock} stock/xaxis/minorticks/ + * Black tick marks on Y axis + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #999999 + */ + minorTickColor: '#999999', + /** + * The color of the line marking the axis itself. + * + * In styled mode, the line stroke is given in the + * `.highcharts-axis-line` or `.highcharts-xaxis-line` class. + * + * @productdesc {highmaps} + * In Highmaps, the axis line is hidden by default, because the axis is + * not visible by default. + * + * @sample {highcharts} highcharts/yaxis/linecolor/ + * A red line on Y axis + * @sample {highcharts|highstock} highcharts/css/axis/ + * Axes in styled mode + * @sample {highstock} stock/xaxis/linecolor/ + * A red line on X axis + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #ccd6eb + */ + lineColor: '#ccd6eb', + /** + * The width of the line marking the axis itself. + * + * In styled mode, the stroke width is given in the + * `.highcharts-axis-line` or `.highcharts-xaxis-line` class. + * + * @sample {highcharts} highcharts/yaxis/linecolor/ + * A 1px line on Y axis + * @sample {highcharts|highstock} highcharts/css/axis/ + * Axes in styled mode + * @sample {highstock} stock/xaxis/linewidth/ + * A 2px line on X axis + * + * @default {highcharts|highstock} 1 + * @default {highmaps} 0 + */ + lineWidth: 1, + /** + * Color of the grid lines extending the ticks across the plot area. + * + * In styled mode, the stroke is given in the `.highcharts-grid-line` + * class. + * + * @productdesc {highmaps} + * In Highmaps, the grid lines are hidden by default. + * + * @sample {highcharts} highcharts/yaxis/gridlinecolor/ + * Green lines + * @sample {highcharts|highstock} highcharts/css/axis-grid/ + * Styled mode + * @sample {highstock} stock/xaxis/gridlinecolor/ + * Green lines + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #e6e6e6 + */ + gridLineColor: '#e6e6e6', + // gridLineDashStyle: 'solid', + /** + * The width of the grid lines extending the ticks across the plot area. + * + * In styled mode, the stroke width is given in the + * `.highcharts-grid-line` class. + * + * @sample {highcharts} highcharts/yaxis/gridlinewidth/ + * 2px lines + * @sample {highcharts|highstock} highcharts/css/axis-grid/ + * Styled mode + * @sample {highstock} stock/xaxis/gridlinewidth/ + * 2px lines + * + * @type {number} + * @default 0 + * @apioption xAxis.gridLineWidth + */ + // gridLineWidth: 0, + /** + * The height as the vertical axis. If it's a number, it is + * interpreted as pixels. + * + * Since Highcharts 2: If it's a percentage string, it is interpreted + * as percentages of the total plot height. + * + * @type {number|string} + * @product highcharts highstock + * @apioption xAxis.height + */ + /** + * The width as the horizontal axis. If it's a number, it is interpreted + * as pixels. + * + * Since Highcharts v5.0.13: If it's a percentage string, it is + * interpreted as percentages of the total plot width. + * + * @type {number|string} + * @product highcharts highstock + * @apioption xAxis.width + */ + /** + * Color for the main tick marks. + * + * In styled mode, the stroke is given in the `.highcharts-tick` + * class. + * + * @sample {highcharts} highcharts/xaxis/tickcolor/ + * Red ticks on X axis + * @sample {highcharts|highstock} highcharts/css/axis-grid/ + * Styled mode + * @sample {highstock} stock/xaxis/ticks/ + * Formatted ticks on X axis + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #ccd6eb + */ + tickColor: '#ccd6eb' + // tickWidth: 1 + }; + /** + * The Y axis or value axis. Normally this is the vertical axis, + * though if the chart is inverted this is the horizontal axis. + * In case of multiple axes, the yAxis node is an array of + * configuration objects. + * + * See [the Axis object](/class-reference/Highcharts.Axis) for programmatic + * access to the axis. + * + * @type {*|Array<*>} + * @extends xAxis + * @excluding currentDateIndicator,ordinal,overscroll + * @optionparent yAxis + * + * @private + */ + Axis.defaultYAxisOptions = { + /** + * The type of axis. Can be one of `linear`, `logarithmic`, `datetime`, + * `category` or `treegrid`. Defaults to `treegrid` for Gantt charts, + * `linear` for other chart types. + * + * In a datetime axis, the numbers are given in milliseconds, and tick + * marks are placed on appropriate values, like full hours or days. In a + * category or treegrid axis, the [point names](#series.line.data.name) + * of the chart's series are used for categories, if a + * [categories](#xAxis.categories) array is not defined. + * + * @sample {highcharts} highcharts/yaxis/type-log-minorgrid/ + * Logarithmic with minor grid lines + * @sample {highcharts} highcharts/yaxis/type-log-negative/ + * Logarithmic with extension to emulate negative values + * @sample {gantt} gantt/treegrid-axis/demo + * Treegrid axis + * + * @type {Highcharts.AxisTypeValue} + * @default {highcharts} linear + * @default {gantt} treegrid + * @product highcharts gantt + * @apioption yAxis.type + */ + /** + * The height of the Y axis. If it's a number, it is interpreted as + * pixels. + * + * Since Highcharts 2: If it's a percentage string, it is interpreted as + * percentages of the total plot height. + * + * @see [yAxis.top](#yAxis.top) + * + * @sample {highstock} stock/demo/candlestick-and-volume/ + * Percentage height panes + * + * @type {number|string} + * @product highcharts highstock + * @apioption yAxis.height + */ + /** + * Solid gauge only. Unless [stops](#yAxis.stops) are set, the color + * to represent the maximum value of the Y axis. + * + * @sample {highcharts} highcharts/yaxis/mincolor-maxcolor/ + * Min and max colors + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #003399 + * @since 4.0 + * @product highcharts + * @apioption yAxis.maxColor + */ + /** + * Solid gauge only. Unless [stops](#yAxis.stops) are set, the color + * to represent the minimum value of the Y axis. + * + * @sample {highcharts} highcharts/yaxis/mincolor-maxcolor/ + * Min and max color + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #e6ebf5 + * @since 4.0 + * @product highcharts + * @apioption yAxis.minColor + */ + /** + * Whether to reverse the axis so that the highest number is closest + * to the origin. + * + * @sample {highcharts} highcharts/yaxis/reversed/ + * Reversed Y axis + * @sample {highstock} stock/xaxis/reversed/ + * Reversed Y axis + * + * @type {boolean} + * @default {highcharts} false + * @default {highstock} false + * @default {highmaps} true + * @default {gantt} true + * @apioption yAxis.reversed + */ + /** + * If `true`, the first series in a stack will be drawn on top in a + * positive, non-reversed Y axis. If `false`, the first series is in + * the base of the stack. + * + * @sample {highcharts} highcharts/yaxis/reversedstacks-false/ + * Non-reversed stacks + * @sample {highstock} highcharts/yaxis/reversedstacks-false/ + * Non-reversed stacks + * + * @type {boolean} + * @default true + * @since 3.0.10 + * @product highcharts highstock + * @apioption yAxis.reversedStacks + */ + /** + * Solid gauge series only. Color stops for the solid gauge. Use this + * in cases where a linear gradient between a `minColor` and `maxColor` + * is not sufficient. The stops is an array of tuples, where the first + * item is a float between 0 and 1 assigning the relative position in + * the gradient, and the second item is the color. + * + * For solid gauges, the Y axis also inherits the concept of + * [data classes](https://api.highcharts.com/highmaps#colorAxis.dataClasses) + * from the Highmaps color axis. + * + * @see [minColor](#yAxis.minColor) + * @see [maxColor](#yAxis.maxColor) + * + * @sample {highcharts} highcharts/demo/gauge-solid/ + * True by default + * + * @type {Array} + * @since 4.0 + * @product highcharts + * @apioption yAxis.stops + */ + /** + * The pixel width of the major tick marks. + * + * @sample {highcharts} highcharts/xaxis/tickwidth/ 10 px width + * @sample {highstock} stock/xaxis/ticks/ Formatted ticks on X axis + * + * @type {number} + * @default 0 + * @product highcharts highstock gantt + * @apioption yAxis.tickWidth + */ + /** + * Angular gauges and solid gauges only. + * The label's pixel distance from the perimeter of the plot area. + * + * Since v7.1.2: If it's a percentage string, it is interpreted the + * same as [series.radius](#plotOptions.gauge.radius), so label can be + * aligned under the gauge's shape. + * + * @sample {highcharts} highcharts/yaxis/labels-distance/ + * Labels centered under the arc + * + * @type {number|string} + * @default -25 + * @product highcharts + * @apioption yAxis.labels.distance + */ + /** + * The y position offset of the label relative to the tick position + * on the axis. + * + * @sample {highcharts} highcharts/xaxis/labels-x/ + * Y axis labels placed on grid lines + * + * @type {number} + * @default {highcharts} 3 + * @default {highstock} -2 + * @default {highmaps} 3 + * @apioption yAxis.labels.y + */ + /** + * Whether to force the axis to end on a tick. Use this option with + * the `maxPadding` option to control the axis end. + * + * This option is always disabled, when panning type is + * either `y` or `xy`. + * + * @see [type](#chart.panning.type) + * + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * True by default + * @sample {highcharts} highcharts/yaxis/endontick/ + * False + * @sample {highstock} stock/demo/basic-line/ + * True by default + * @sample {highstock} stock/xaxis/endontick/ + * False for Y axis + * + * @since 1.2.0 + */ + endOnTick: true, + /** + * Padding of the max value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. This is useful + * when you don't want the highest data value to appear on the edge + * of the plot area. When the axis' `max` option is set or a max extreme + * is set using `axis.setExtremes()`, the maxPadding will be ignored. + * + * Also the `softThreshold` option takes precedence over `maxPadding`, + * so if the data is tangent to the threshold, `maxPadding` may not + * apply unless `softThreshold` is set to false. + * + * @sample {highcharts} highcharts/yaxis/maxpadding-02/ + * Max padding of 0.2 + * @sample {highstock} stock/xaxis/minpadding-maxpadding/ + * Greater min- and maxPadding + * + * @since 1.2.0 + * @product highcharts highstock gantt + */ + maxPadding: 0.05, + /** + * Padding of the min value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. This is useful + * when you don't want the lowest data value to appear on the edge + * of the plot area. When the axis' `min` option is set or a max extreme + * is set using `axis.setExtremes()`, the maxPadding will be ignored. + * + * Also the `softThreshold` option takes precedence over `minPadding`, + * so if the data is tangent to the threshold, `minPadding` may not + * apply unless `softThreshold` is set to false. + * + * @sample {highcharts} highcharts/yaxis/minpadding/ + * Min padding of 0.2 + * @sample {highstock} stock/xaxis/minpadding-maxpadding/ + * Greater min- and maxPadding + * + * @since 1.2.0 + * @product highcharts highstock gantt + */ + minPadding: 0.05, + /** + * @productdesc {highstock} + * In Highstock 1.x, the Y axis was placed on the left side by default. + * + * @sample {highcharts} highcharts/yaxis/opposite/ + * Secondary Y axis opposite + * @sample {highstock} stock/xaxis/opposite/ + * Y axis on left side + * + * @type {boolean} + * @default {highstock} true + * @default {highcharts} false + * @product highstock highcharts gantt + * @apioption yAxis.opposite + */ + /** + * @see [tickInterval](#xAxis.tickInterval) + * @see [tickPositioner](#xAxis.tickPositioner) + * @see [tickPositions](#xAxis.tickPositions) + */ + tickPixelInterval: 72, + showLastLabel: true, + /** + * @extends xAxis.labels + */ + labels: { + /** + * What part of the string the given position is anchored to. Can + * be one of `"left"`, `"center"` or `"right"`. The exact position + * also depends on the `labels.x` setting. + * + * Angular gauges and solid gauges defaults to `"center"`. + * Solid gauges with two labels have additional option `"auto"` + * for automatic horizontal and vertical alignment. + * + * @see [yAxis.labels.distance](#yAxis.labels.distance) + * + * @sample {highcharts} highcharts/yaxis/labels-align-left/ + * Left + * @sample {highcharts} highcharts/series-solidgauge/labels-auto-aligned/ + * Solid gauge labels auto aligned + * + * @type {Highcharts.AlignValue} + * @default {highcharts|highmaps} right + * @default {highstock} left + * @apioption yAxis.labels.align + */ + /** + * The x position offset of the label relative to the tick position + * on the axis. Defaults to -15 for left axis, 15 for right axis. + * + * @sample {highcharts} highcharts/xaxis/labels-x/ + * Y axis labels placed on grid lines + */ + x: -8 + }, + /** + * @productdesc {highmaps} + * In Highmaps, the axis line is hidden by default, because the axis is + * not visible by default. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption yAxis.lineColor + */ + /** + * @sample {highcharts} highcharts/yaxis/max-200/ + * Y axis max of 200 + * @sample {highcharts} highcharts/yaxis/max-logarithmic/ + * Y axis max on logarithmic axis + * @sample {highstock} stock/yaxis/min-max/ + * Fixed min and max on Y axis + * @sample {highmaps} maps/axis/min-max/ + * Pre-zoomed to a specific area + * + * @apioption yAxis.max + */ + /** + * @sample {highcharts} highcharts/yaxis/min-startontick-false/ + * -50 with startOnTick to false + * @sample {highcharts} highcharts/yaxis/min-startontick-true/ + * -50 with startOnTick true by default + * @sample {highstock} stock/yaxis/min-max/ + * Fixed min and max on Y axis + * @sample {highmaps} maps/axis/min-max/ + * Pre-zoomed to a specific area + * + * @apioption yAxis.min + */ + /** + * An optional scrollbar to display on the Y axis in response to + * limiting the minimum an maximum of the axis values. + * + * In styled mode, all the presentational options for the scrollbar + * are replaced by the classes `.highcharts-scrollbar-thumb`, + * `.highcharts-scrollbar-arrow`, `.highcharts-scrollbar-button`, + * `.highcharts-scrollbar-rifles` and `.highcharts-scrollbar-track`. + * + * @sample {highstock} stock/yaxis/scrollbar/ + * Scrollbar on the Y axis + * + * @extends scrollbar + * @since 4.2.6 + * @product highstock + * @excluding height + * @apioption yAxis.scrollbar + */ + /** + * Enable the scrollbar on the Y axis. + * + * @sample {highstock} stock/yaxis/scrollbar/ + * Enabled on Y axis + * + * @type {boolean} + * @default false + * @since 4.2.6 + * @product highstock + * @apioption yAxis.scrollbar.enabled + */ + /** + * Pixel margin between the scrollbar and the axis elements. + * + * @type {number} + * @default 10 + * @since 4.2.6 + * @product highstock + * @apioption yAxis.scrollbar.margin + */ + /** + * Whether to show the scrollbar when it is fully zoomed out at max + * range. Setting it to `false` on the Y axis makes the scrollbar stay + * hidden until the user zooms in, like common in browsers. + * + * @type {boolean} + * @default true + * @since 4.2.6 + * @product highstock + * @apioption yAxis.scrollbar.showFull + */ + /** + * The width of a vertical scrollbar or height of a horizontal + * scrollbar. Defaults to 20 on touch devices. + * + * @type {number} + * @default 14 + * @since 4.2.6 + * @product highstock + * @apioption yAxis.scrollbar.size + */ + /** + * Z index of the scrollbar elements. + * + * @type {number} + * @default 3 + * @since 4.2.6 + * @product highstock + * @apioption yAxis.scrollbar.zIndex + */ + /** + * A soft maximum for the axis. If the series data maximum is less + * than this, the axis will stay at this maximum, but if the series + * data maximum is higher, the axis will flex to show all data. + * + * **Note**: The [series.softThreshold]( + * #plotOptions.series.softThreshold) option takes precedence over this + * option. + * + * @sample highcharts/yaxis/softmin-softmax/ + * Soft min and max + * + * @type {number} + * @since 5.0.1 + * @product highcharts highstock gantt + * @apioption yAxis.softMax + */ + /** + * A soft minimum for the axis. If the series data minimum is greater + * than this, the axis will stay at this minimum, but if the series + * data minimum is lower, the axis will flex to show all data. + * + * **Note**: The [series.softThreshold]( + * #plotOptions.series.softThreshold) option takes precedence over this + * option. + * + * @sample highcharts/yaxis/softmin-softmax/ + * Soft min and max + * + * @type {number} + * @since 5.0.1 + * @product highcharts highstock gantt + * @apioption yAxis.softMin + */ + /** + * Defines the horizontal alignment of the stack total label. Can be one + * of `"left"`, `"center"` or `"right"`. The default value is calculated + * at runtime and depends on orientation and whether the stack is + * positive or negative. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-align-left/ + * Aligned to the left + * @sample {highcharts} highcharts/yaxis/stacklabels-align-center/ + * Aligned in center + * @sample {highcharts} highcharts/yaxis/stacklabels-align-right/ + * Aligned to the right + * + * @type {Highcharts.AlignValue} + * @since 2.1.5 + * @product highcharts + * @apioption yAxis.stackLabels.align + */ + /** + * A format string for the data label. Available variables are the same + * as for `formatter`. + * + * @type {string} + * @default {total} + * @since 3.0.2 + * @product highcharts highstock + * @apioption yAxis.stackLabels.format + */ + /** + * Rotation of the labels in degrees. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-rotation/ + * Labels rotated 45° + * + * @type {number} + * @default 0 + * @since 2.1.5 + * @product highcharts + * @apioption yAxis.stackLabels.rotation + */ + /** + * The text alignment for the label. While `align` determines where the + * texts anchor point is placed with regards to the stack, `textAlign` + * determines how the text is aligned against its anchor point. Possible + * values are `"left"`, `"center"` and `"right"`. The default value is + * calculated at runtime and depends on orientation and whether the + * stack is positive or negative. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-textalign-left/ + * Label in center position but text-aligned left + * + * @type {Highcharts.AlignValue} + * @since 2.1.5 + * @product highcharts + * @apioption yAxis.stackLabels.textAlign + */ + /** + * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the labels. + * + * @type {boolean} + * @default false + * @since 3.0 + * @product highcharts highstock + * @apioption yAxis.stackLabels.useHTML + */ + /** + * Defines the vertical alignment of the stack total label. Can be one + * of `"top"`, `"middle"` or `"bottom"`. The default value is calculated + * at runtime and depends on orientation and whether the stack is + * positive or negative. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-verticalalign-top/ + * Vertically aligned top + * @sample {highcharts} highcharts/yaxis/stacklabels-verticalalign-middle/ + * Vertically aligned middle + * @sample {highcharts} highcharts/yaxis/stacklabels-verticalalign-bottom/ + * Vertically aligned bottom + * + * @type {Highcharts.VerticalAlignValue} + * @since 2.1.5 + * @product highcharts + * @apioption yAxis.stackLabels.verticalAlign + */ + /** + * The x position offset of the label relative to the left of the + * stacked bar. The default value is calculated at runtime and depends + * on orientation and whether the stack is positive or negative. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-x/ + * Stack total labels with x offset + * + * @type {number} + * @since 2.1.5 + * @product highcharts + * @apioption yAxis.stackLabels.x + */ + /** + * The y position offset of the label relative to the tick position + * on the axis. The default value is calculated at runtime and depends + * on orientation and whether the stack is positive or negative. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-y/ + * Stack total labels with y offset + * + * @type {number} + * @since 2.1.5 + * @product highcharts + * @apioption yAxis.stackLabels.y + */ + /** + * Whether to force the axis to start on a tick. Use this option with + * the `maxPadding` option to control the axis start. + * + * This option is always disabled, when panning type is + * either `y` or `xy`. + * + * @see [type](#chart.panning.type) + * + * @sample {highcharts} highcharts/xaxis/startontick-false/ + * False by default + * @sample {highcharts} highcharts/xaxis/startontick-true/ + * True + * @sample {highstock} stock/xaxis/endontick/ + * False for Y axis + * + * @since 1.2.0 + * @product highcharts highstock gantt + */ + startOnTick: true, + title: { + /** + * The pixel distance between the axis labels and the title. + * Positive values are outside the axis line, negative are inside. + * + * @sample {highcharts} highcharts/xaxis/title-margin/ + * Y axis title margin of 60 + * + * @type {number} + * @default 40 + * @apioption yAxis.title.margin + */ + /** + * The rotation of the text in degrees. 0 is horizontal, 270 is + * vertical reading from bottom to top. + * + * @sample {highcharts} highcharts/yaxis/title-offset/ + * Horizontal + */ + rotation: 270, + /** + * The actual text of the axis title. Horizontal texts can contain + * HTML, but rotated texts are painted using vector techniques and + * must be clean text. The Y axis title is disabled by setting the + * `text` option to `undefined`. + * + * @sample {highcharts} highcharts/xaxis/title-text/ + * Custom HTML + * + * @type {string|null} + * @default {highcharts} Values + * @default {highstock} undefined + * @product highcharts highstock gantt + */ + text: 'Values' + }, + /** + * The top position of the Y axis. If it's a number, it is interpreted + * as pixel position relative to the chart. + * + * Since Highcharts 2: If it's a percentage string, it is interpreted as + * percentages of the plot height, offset from plot area top. + * + * @see [yAxis.height](#yAxis.height) + * + * @sample {highstock} stock/demo/candlestick-and-volume/ + * Percentage height panes + * + * @type {number|string} + * @product highcharts highstock + * @apioption yAxis.top + */ + /** + * The stack labels show the total value for each bar in a stacked + * column or bar chart. The label will be placed on top of positive + * columns and below negative columns. In case of an inverted column + * chart or a bar chart the label is placed to the right of positive + * bars and to the left of negative bars. + * + * @product highcharts + */ + stackLabels: { + /** + * Allow the stack labels to overlap. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-allowoverlap-false/ + * Default false + * + * @since 5.0.13 + * @product highcharts + */ + allowOverlap: false, + /** + * The background color or gradient for the stack label. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-box/ + * Stack labels box options + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 8.1.0 + * @apioption yAxis.stackLabels.backgroundColor + */ + /** + * The border color for the stack label. Defaults to `undefined`. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-box/ + * Stack labels box options + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 8.1.0 + * @apioption yAxis.stackLabels.borderColor + */ + /** + * The border radius in pixels for the stack label. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-box/ + * Stack labels box options + * @type {number} + * @default 0 + * @since 8.1.0 + * @apioption yAxis.stackLabels.borderRadius + */ + /** + * The border width in pixels for the stack label. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-box/ + * Stack labels box options + * @type {number} + * @default 0 + * @since 8.1.0 + * @apioption yAxis.stackLabels.borderWidth + */ + /** + * Enable or disable the stack total labels. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-enabled/ + * Enabled stack total labels + * @sample {highcharts} highcharts/yaxis/stacklabels-enabled-waterfall/ + * Enabled stack labels in waterfall chart + * + * @since 2.1.5 + * @product highcharts + */ + enabled: false, + /** + * Whether to hide stack labels that are outside the plot area. + * By default, the stack label is moved + * inside the plot area according to the + * [overflow](/highcharts/#yAxis/stackLabels/overflow) + * option. + * + * @type {boolean} + * @since 7.1.3 + */ + crop: true, + /** + * How to handle stack total labels that flow outside the plot area. + * The default is set to `"justify"`, + * which aligns them inside the plot area. + * For columns and bars, this means it will be moved inside the bar. + * To display stack labels outside the plot area, + * set `crop` to `false` and `overflow` to `"allow"`. + * + * @sample highcharts/yaxis/stacklabels-overflow/ + * Stack labels flows outside the plot area. + * + * @type {Highcharts.DataLabelsOverflowValue} + * @since 7.1.3 + */ + overflow: 'justify', + /* eslint-disable valid-jsdoc */ + /** + * Callback JavaScript function to format the label. The value is + * given by `this.total`. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-formatter/ + * Added units to stack total value + * + * @type {Highcharts.FormatterCallbackFunction} + * @since 2.1.5 + * @product highcharts + */ + formatter: function () { + var numberFormatter = this.axis.chart.numberFormatter; + /* eslint-enable valid-jsdoc */ + return numberFormatter(this.total, -1); + }, + /** + * CSS styles for the label. + * + * In styled mode, the styles are set in the + * `.highcharts-stack-label` class. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-style/ + * Red stack total labels + * + * @type {Highcharts.CSSObject} + * @since 2.1.5 + * @product highcharts + */ + style: { + /** @internal */ + color: '#000000', + /** @internal */ + fontSize: '11px', + /** @internal */ + fontWeight: 'bold', + /** @internal */ + textOutline: '1px contrast' + } + }, + gridLineWidth: 1, + lineWidth: 0 + // tickWidth: 0 + }; + /** + * The Z axis or depth axis for 3D plots. + * + * See the [Axis class](/class-reference/Highcharts.Axis) for programmatic + * access to the axis. + * + * @sample {highcharts} highcharts/3d/scatter-zaxis-categories/ + * Z-Axis with Categories + * @sample {highcharts} highcharts/3d/scatter-zaxis-grid/ + * Z-Axis with styling + * + * @type {*|Array<*>} + * @extends xAxis + * @since 5.0.0 + * @product highcharts + * @excluding breaks, crosshair, height, left, lineColor, lineWidth, + * nameToX, showEmpty, top, width + * @apioption zAxis + * + * @private + */ + // This variable extends the defaultOptions for left axes. + Axis.defaultLeftAxisOptions = { + labels: { + x: -15 + }, + title: { + rotation: 270 + } + }; + // This variable extends the defaultOptions for right axes. + Axis.defaultRightAxisOptions = { + labels: { + x: 15 + }, + title: { + rotation: 90 + } + }; + // This variable extends the defaultOptions for bottom axes. + Axis.defaultBottomAxisOptions = { + labels: { + autoRotation: [-45], + x: 0 + // overflow: undefined, + // staggerLines: null + }, + margin: 15, + title: { + rotation: 0 + } + }; + // This variable extends the defaultOptions for top axes. + Axis.defaultTopAxisOptions = { + labels: { + autoRotation: [-45], + x: 0 + // overflow: undefined + // staggerLines: null + }, + margin: 15, + title: { + rotation: 0 + } + }; + // Properties to survive after destroy, needed for Axis.update (#4317, + // #5773, #5881). + Axis.keepProps = ['extKey', 'hcEvents', 'names', 'series', 'userMax', 'userMin']; + return Axis; +}()); +H.Axis = Axis; +export default H.Axis; diff --git a/librerias/gantt/code/es-modules/parts/BarSeries.js b/librerias/gantt/code/es-modules/parts/BarSeries.js new file mode 100644 index 0000000..4274a3c --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/BarSeries.js @@ -0,0 +1,120 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import U from './Utilities.js'; +var seriesType = U.seriesType; +import './ColumnSeries.js'; +/** + * Bar series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.bar + * + * @augments Highcharts.Series + */ +seriesType('bar', 'column', +/** + * A bar series is a special type of column series where the columns are + * horizontal. + * + * @sample highcharts/demo/bar-basic/ + * Bar chart + * + * @extends plotOptions.column + * @product highcharts + * @apioption plotOptions.bar + */ +/** + * @ignore + */ +null, { + inverted: true +}); +/** + * A `bar` series. If the [type](#series.bar.type) option is not specified, + * it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.bar + * @excluding connectNulls, dashStyle, dataParser, dataURL, gapSize, gapUnit, + * linecap, lineWidth, marker, connectEnds, step + * @product highcharts + * @apioption series.bar + */ +/** + * An array of data points for the series. For the `bar` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 5], + * [1, 10], + * [2, 3] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.bar.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 1, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 10, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.column.data + * @product highcharts + * @apioption series.bar.data + */ +/** + * @excluding halo,lineWidth,lineWidthPlus,marker + * @product highcharts highstock + * @apioption series.bar.states.hover + */ +/** + * @excluding halo,lineWidth,lineWidthPlus,marker + * @product highcharts highstock + * @apioption series.bar.states.select + */ +''; // gets doclets above into transpilat diff --git a/librerias/gantt/code/es-modules/parts/CandlestickSeries.js b/librerias/gantt/code/es-modules/parts/CandlestickSeries.js new file mode 100644 index 0000000..1f265fc --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/CandlestickSeries.js @@ -0,0 +1,291 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +import U from './Utilities.js'; +var merge = U.merge, seriesType = U.seriesType; +var defaultPlotOptions = H.defaultPlotOptions, seriesTypes = H.seriesTypes; +/** + * A candlestick chart is a style of financial chart used to describe price + * movements over time. + * + * @sample stock/demo/candlestick/ + * Candlestick chart + * + * @extends plotOptions.ohlc + * @excluding borderColor,borderRadius,borderWidth + * @product highstock + * @optionparent plotOptions.candlestick + */ +var candlestickOptions = { + /** + * The specific line color for up candle sticks. The default is to inherit + * the general `lineColor` setting. + * + * @sample {highstock} stock/plotoptions/candlestick-linecolor/ + * Candlestick line colors + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 1.3.6 + * @product highstock + * @apioption plotOptions.candlestick.upLineColor + */ + /** + * @type {Highcharts.DataGroupingApproximationValue|Function} + * @default ohlc + * @product highstock + * @apioption plotOptions.candlestick.dataGrouping.approximation + */ + states: { + /** + * @extends plotOptions.column.states.hover + * @product highstock + */ + hover: { + /** + * The pixel width of the line/border around the candlestick. + * + * @product highstock + */ + lineWidth: 2 + } + }, + /** + * @extends plotOptions.ohlc.tooltip + */ + tooltip: defaultPlotOptions.ohlc.tooltip, + /** + * @type {number|null} + * @product highstock + */ + threshold: null, + /** + * The color of the line/border of the candlestick. + * + * In styled mode, the line stroke can be set with the + * `.highcharts-candlestick-series .highcahrts-point` rule. + * + * @see [upLineColor](#plotOptions.candlestick.upLineColor) + * + * @sample {highstock} stock/plotoptions/candlestick-linecolor/ + * Candlestick line colors + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #000000 + * @product highstock + */ + lineColor: '#000000', + /** + * The pixel width of the candlestick line/border. Defaults to `1`. + * + * + * In styled mode, the line stroke width can be set with the + * `.highcharts-candlestick-series .highcahrts-point` rule. + * + * @product highstock + */ + lineWidth: 1, + /** + * The fill color of the candlestick when values are rising. + * + * In styled mode, the up color can be set with the + * `.highcharts-candlestick-series .highcharts-point-up` rule. + * + * @sample {highstock} stock/plotoptions/candlestick-color/ + * Custom colors + * @sample {highstock} highcharts/css/candlestick/ + * Colors in styled mode + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #ffffff + * @product highstock + */ + upColor: '#ffffff', + /** + * @product highstock + */ + stickyTracking: true +}; +/** + * The candlestick series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.candlestick + * + * @augments Highcharts.seriesTypes.ohlc + */ +seriesType('candlestick', 'ohlc', merge(defaultPlotOptions.column, candlestickOptions), +/** + * @lends seriesTypes.candlestick + */ +{ + /* eslint-disable valid-jsdoc */ + /** + * Postprocess mapping between options and SVG attributes + * + * @private + * @function Highcharts.seriesTypes.candlestick#pointAttribs + * @param {Highcharts.Point} point + * @param {string} [state] + * @return {Highcharts.SVGAttributes} + */ + pointAttribs: function (point, state) { + var attribs = seriesTypes.column.prototype.pointAttribs.call(this, point, state), options = this.options, isUp = point.open < point.close, stroke = options.lineColor || this.color, stateOptions; + attribs['stroke-width'] = options.lineWidth; + attribs.fill = point.options.color || + (isUp ? (options.upColor || this.color) : this.color); + attribs.stroke = point.options.lineColor || + (isUp ? (options.upLineColor || stroke) : stroke); + // Select or hover states + if (state) { + stateOptions = options.states[state]; + attribs.fill = stateOptions.color || attribs.fill; + attribs.stroke = stateOptions.lineColor || attribs.stroke; + attribs['stroke-width'] = + stateOptions.lineWidth || attribs['stroke-width']; + } + return attribs; + }, + /** + * Draw the data points. + * + * @private + * @function Highcharts.seriesTypes.candlestick#drawPoints + * @return {void} + */ + drawPoints: function () { + var series = this, points = series.points, chart = series.chart, reversedYAxis = series.yAxis.reversed; + points.forEach(function (point) { + var graphic = point.graphic, plotOpen, plotClose, topBox, bottomBox, hasTopWhisker, hasBottomWhisker, crispCorr, crispX, path, halfWidth, isNew = !graphic; + if (typeof point.plotY !== 'undefined') { + if (!graphic) { + point.graphic = graphic = chart.renderer.path() + .add(series.group); + } + if (!series.chart.styledMode) { + graphic + .attr(series.pointAttribs(point, (point.selected && 'select'))) // #3897 + .shadow(series.options.shadow); + } + // Crisp vector coordinates + crispCorr = (graphic.strokeWidth() % 2) / 2; + // #2596: + crispX = Math.round(point.plotX) - crispCorr; + plotOpen = point.plotOpen; + plotClose = point.plotClose; + topBox = Math.min(plotOpen, plotClose); + bottomBox = Math.max(plotOpen, plotClose); + halfWidth = Math.round(point.shapeArgs.width / 2); + hasTopWhisker = reversedYAxis ? + bottomBox !== point.yBottom : + Math.round(topBox) !== + Math.round(point.plotHigh); + hasBottomWhisker = reversedYAxis ? + Math.round(topBox) !== + Math.round(point.plotHigh) : + bottomBox !== point.yBottom; + topBox = Math.round(topBox) + crispCorr; + bottomBox = Math.round(bottomBox) + crispCorr; + // Create the path. Due to a bug in Chrome 49, the path is + // first instanciated with no values, then the values + // pushed. For unknown reasons, instanciating the path array + // with all the values would lead to a crash when updating + // frequently (#5193). + path = []; + path.push(['M', crispX - halfWidth, bottomBox], ['L', crispX - halfWidth, topBox], ['L', crispX + halfWidth, topBox], ['L', crispX + halfWidth, bottomBox], ['Z'], // Ensure a nice rectangle #2602 + ['M', crispX, topBox], [ + 'L', + // #460, #2094 + crispX, + hasTopWhisker ? + Math.round(reversedYAxis ? + point.yBottom : + point.plotHigh) : + topBox + ], ['M', crispX, bottomBox], [ + 'L', + // #460, #2094 + crispX, + hasBottomWhisker ? + Math.round(reversedYAxis ? + point.plotHigh : + point.yBottom) : + bottomBox + ]); + graphic[isNew ? 'attr' : 'animate']({ d: path }) + .addClass(point.getClassName(), true); + } + }); + /* eslint-enable valid-jsdoc */ + } +}); +/** + * A `candlestick` series. If the [type](#series.candlestick.type) + * option is not specified, it is inherited from [chart.type]( + * #chart.type). + * + * @type {*} + * @extends series,plotOptions.candlestick + * @excluding dataParser, dataURL + * @product highstock + * @apioption series.candlestick + */ +/** + * An array of data points for the series. For the `candlestick` series + * type, points can be given in the following ways: + * + * 1. An array of arrays with 5 or 4 values. In this case, the values correspond + * to `x,open,high,low,close`. If the first value is a string, it is applied + * as the name of the point, and the `x` value is inferred. The `x` value can + * also be omitted, in which case the inner arrays should be of length 4. + * Then the `x` value is automatically calculated, either starting at 0 and + * incremented by 1, or from `pointStart` and `pointInterval` given in the + * series options. + * ```js + * data: [ + * [0, 7, 2, 0, 4], + * [1, 1, 4, 2, 8], + * [2, 3, 3, 9, 3] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.candlestick.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * open: 9, + * high: 2, + * low: 4, + * close: 6, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * open: 1, + * high: 4, + * low: 7, + * close: 7, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @type {Array|Array<(number|string),number,number,number,number>|*>} + * @extends series.ohlc.data + * @excluding y + * @product highstock + * @apioption series.candlestick.data + */ +''; // adds doclets above to transpilat diff --git a/librerias/gantt/code/es-modules/parts/Chart.js b/librerias/gantt/code/es-modules/parts/Chart.js new file mode 100644 index 0000000..f4ef506 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/Chart.js @@ -0,0 +1,2043 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +/** + * Callback for chart constructors. + * + * @callback Highcharts.ChartCallbackFunction + * + * @param {Highcharts.Chart} chart + * Created chart. + */ +/** + * Format a number and return a string based on input settings. + * + * @callback Highcharts.NumberFormatterCallbackFunction + * + * @param {number} number + * The input number to format. + * + * @param {number} decimals + * The amount of decimals. A value of -1 preserves the amount in the + * input number. + * + * @param {string} [decimalPoint] + * The decimal point, defaults to the one given in the lang options, or + * a dot. + * + * @param {string} [thousandsSep] + * The thousands separator, defaults to the one given in the lang + * options, or a space character. + * + * @return {string} The formatted number. + */ +/** + * The chart title. The title has an `update` method that allows modifying the + * options directly or indirectly via `chart.update`. + * + * @interface Highcharts.TitleObject + * @extends Highcharts.SVGElement + */ /** +* Modify options for the title. +* +* @function Highcharts.TitleObject#update +* +* @param {Highcharts.TitleOptions} titleOptions +* Options to modify. +* +* @param {boolean} [redraw=true] +* Whether to redraw the chart after the title is altered. If doing more +* operations on the chart, it is a good idea to set redraw to false and +* call {@link Chart#redraw} after. +*/ +/** + * The chart subtitle. The subtitle has an `update` method that + * allows modifying the options directly or indirectly via + * `chart.update`. + * + * @interface Highcharts.SubtitleObject + * @extends Highcharts.SVGElement + */ /** +* Modify options for the subtitle. +* +* @function Highcharts.SubtitleObject#update +* +* @param {Highcharts.SubtitleOptions} subtitleOptions +* Options to modify. +* +* @param {boolean} [redraw=true] +* Whether to redraw the chart after the subtitle is altered. If doing +* more operations on the chart, it is a good idea to set redraw to false +* and call {@link Chart#redraw} after. +*/ +/** + * The chart caption. The caption has an `update` method that + * allows modifying the options directly or indirectly via + * `chart.update`. + * + * @interface Highcharts.CaptionObject + * @extends Highcharts.SVGElement + */ /** +* Modify options for the caption. +* +* @function Highcharts.CaptionObject#update +* +* @param {Highcharts.CaptionOptions} captionOptions +* Options to modify. +* +* @param {boolean} [redraw=true] +* Whether to redraw the chart after the caption is altered. If doing +* more operations on the chart, it is a good idea to set redraw to false +* and call {@link Chart#redraw} after. +*/ +import Legend from './Legend.js'; +import MSPointer from './MSPointer.js'; +import Pointer from './Pointer.js'; +import Time from './Time.js'; +import U from './Utilities.js'; +var addEvent = U.addEvent, animate = U.animate, animObject = U.animObject, attr = U.attr, createElement = U.createElement, css = U.css, defined = U.defined, discardElement = U.discardElement, erase = U.erase, error = U.error, extend = U.extend, find = U.find, fireEvent = U.fireEvent, getStyle = U.getStyle, isArray = U.isArray, isFunction = U.isFunction, isNumber = U.isNumber, isObject = U.isObject, isString = U.isString, merge = U.merge, numberFormat = U.numberFormat, objectEach = U.objectEach, pick = U.pick, pInt = U.pInt, relativeLength = U.relativeLength, removeEvent = U.removeEvent, setAnimation = U.setAnimation, splat = U.splat, syncTimeout = U.syncTimeout, uniqueKey = U.uniqueKey; +import './Axis.js'; +import './Options.js'; +import './Pointer.js'; +var doc = H.doc, Axis = H.Axis, // @todo add as requirement +defaultOptions = H.defaultOptions, charts = H.charts, marginNames = H.marginNames, seriesTypes = H.seriesTypes, win = H.win; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * The Chart class. The recommended constructor is {@link Highcharts#chart}. + * + * @example + * var chart = Highcharts.chart('container', { + * title: { + * text: 'My chart' + * }, + * series: [{ + * data: [1, 3, 2, 4] + * }] + * }) + * + * @class + * @name Highcharts.Chart + * + * @param {string|Highcharts.HTMLDOMElement} [renderTo] + * The DOM element to render to, or its id. + * + * @param {Highcharts.Options} options + * The chart options structure. + * + * @param {Highcharts.ChartCallbackFunction} [callback] + * Function to run when the chart has loaded and and all external images + * are loaded. Defining a + * [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load) + * handler is equivalent. + */ +var Chart = H.Chart = function () { + this.getArgs.apply(this, arguments); +}; +/** + * Factory function for basic charts. + * + * @example + * // Render a chart in to div#container + * var chart = Highcharts.chart('container', { + * title: { + * text: 'My chart' + * }, + * series: [{ + * data: [1, 3, 2, 4] + * }] + * }); + * + * @function Highcharts.chart + * + * @param {string|Highcharts.HTMLDOMElement} [renderTo] + * The DOM element to render to, or its id. + * + * @param {Highcharts.Options} options + * The chart options structure. + * + * @param {Highcharts.ChartCallbackFunction} [callback] + * Function to run when the chart has loaded and and all external images + * are loaded. Defining a + * [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load) + * handler is equivalent. + * + * @return {Highcharts.Chart} + * Returns the Chart object. + */ +H.chart = function (a, b, c) { + return new Chart(a, b, c); +}; +extend(Chart.prototype, /** @lends Highcharts.Chart.prototype */ { + // Hook for adding callbacks in modules + callbacks: [], + /** + * Handle the arguments passed to the constructor. + * + * @private + * @function Highcharts.Chart#getArgs + * + * @param {...Array<*>} arguments + * All arguments for the constructor. + * + * @return {Array<*>} + * Passed arguments without renderTo. + * + * @fires Highcharts.Chart#event:init + * @fires Highcharts.Chart#event:afterInit + */ + getArgs: function () { + var args = [].slice.call(arguments); + // Remove the optional first argument, renderTo, and + // set it on this. + if (isString(args[0]) || args[0].nodeName) { + this.renderTo = args.shift(); + } + this.init(args[0], args[1]); + }, + /** + * Overridable function that initializes the chart. The constructor's + * arguments are passed on directly. + * + * @function Highcharts.Chart#init + * + * @param {Highcharts.Options} userOptions + * Custom options. + * + * @param {Function} [callback] + * Function to run when the chart has loaded and and all external + * images are loaded. + * + * @return {void} + * + * @fires Highcharts.Chart#event:init + * @fires Highcharts.Chart#event:afterInit + */ + init: function (userOptions, callback) { + // Handle regular options + var options, + // skip merging data points to increase performance + seriesOptions = userOptions.series, userPlotOptions = userOptions.plotOptions || {}; + // Fire the event with a default function + fireEvent(this, 'init', { args: arguments }, function () { + userOptions.series = null; + options = merge(defaultOptions, userOptions); // do the merge + var optionsChart = options.chart || {}; + // Override (by copy of user options) or clear tooltip options + // in chart.options.plotOptions (#6218) + objectEach(options.plotOptions, function (typeOptions, type) { + if (isObject(typeOptions)) { // #8766 + typeOptions.tooltip = (userPlotOptions[type] && // override by copy: + merge(userPlotOptions[type].tooltip)) || void 0; // or clear + } + }); + // User options have higher priority than default options + // (#6218). In case of exporting: path is changed + options.tooltip.userOptions = (userOptions.chart && + userOptions.chart.forExport && + userOptions.tooltip.userOptions) || userOptions.tooltip; + // set back the series data + options.series = userOptions.series = seriesOptions; + /** + * The original options given to the constructor or a chart factory + * like {@link Highcharts.chart} and {@link Highcharts.stockChart}. + * + * @name Highcharts.Chart#userOptions + * @type {Highcharts.Options} + */ + this.userOptions = userOptions; + var chartEvents = optionsChart.events; + this.margin = []; + this.spacing = []; + // Pixel data bounds for touch zoom + this.bounds = { h: {}, v: {} }; + // An array of functions that returns labels that should be + // considered for anti-collision + this.labelCollectors = []; + this.callback = callback; + this.isResizing = 0; + /** + * The options structure for the chart after merging + * {@link #defaultOptions} and {@link #userOptions}. It contains + * members for the sub elements like series, legend, tooltip etc. + * + * @name Highcharts.Chart#options + * @type {Highcharts.Options} + */ + this.options = options; + /** + * All the axes in the chart. + * + * @see Highcharts.Chart.xAxis + * @see Highcharts.Chart.yAxis + * + * @name Highcharts.Chart#axes + * @type {Array} + */ + this.axes = []; + /** + * All the current series in the chart. + * + * @name Highcharts.Chart#series + * @type {Array} + */ + this.series = []; + /** + * The `Time` object associated with the chart. Since v6.0.5, + * time settings can be applied individually for each chart. If + * no individual settings apply, the `Time` object is shared by + * all instances. + * + * @name Highcharts.Chart#time + * @type {Highcharts.Time} + */ + this.time = + userOptions.time && Object.keys(userOptions.time).length ? + new Time(userOptions.time) : + H.time; + /** + * Callback function to override the default function that formats + * all the numbers in the chart. Returns a string with the formatted + * number. + * + * @name Highcharts.Chart#numberFormatter + * @type {Highcharts.NumberFormatterCallbackFunction} + */ + this.numberFormatter = optionsChart.numberFormatter || numberFormat; + /** + * Whether the chart is in styled mode, meaning all presentatinoal + * attributes are avoided. + * + * @name Highcharts.Chart#styledMode + * @type {boolean} + */ + this.styledMode = optionsChart.styledMode; + this.hasCartesianSeries = optionsChart.showAxes; + var chart = this; + /** + * Index position of the chart in the {@link Highcharts#charts} + * property. + * + * @name Highcharts.Chart#index + * @type {number} + * @readonly + */ + chart.index = charts.length; // Add the chart to the global lookup + charts.push(chart); + H.chartCount++; + // Chart event handlers + if (chartEvents) { + objectEach(chartEvents, function (event, eventType) { + if (isFunction(event)) { + addEvent(chart, eventType, event); + } + }); + } + /** + * A collection of the X axes in the chart. + * + * @name Highcharts.Chart#xAxis + * @type {Array} + */ + chart.xAxis = []; + /** + * A collection of the Y axes in the chart. + * + * @name Highcharts.Chart#yAxis + * @type {Array} + * + * @todo + * Make events official: Fire the event `afterInit`. + */ + chart.yAxis = []; + chart.pointCount = chart.colorCounter = chart.symbolCounter = 0; + // Fire after init but before first render, before axes and series + // have been initialized. + fireEvent(chart, 'afterInit'); + chart.firstRender(); + }); + }, + /** + * Internal function to unitialize an individual series. + * + * @private + * @function Highcharts.Chart#initSeries + * + * @param {Highcharts.SeriesOptions} options + * + * @return {Highcharts.Series} + */ + initSeries: function (options) { + var chart = this, optionsChart = chart.options.chart, type = (options.type || + optionsChart.type || + optionsChart.defaultSeriesType), series, Constr = seriesTypes[type]; + // No such series type + if (!Constr) { + error(17, true, chart, { missingModuleFor: type }); + } + series = new Constr(); + series.init(this, options); + return series; + }, + /** + * Internal function to set data for all series with enabled sorting. + * + * @private + * @function Highcharts.Chart#setSeriesData + * + * @param {Highcharts.SeriesOptions} options + * + * @return {void} + */ + setSeriesData: function () { + this.getSeriesOrderByLinks().forEach(function (series) { + // We need to set data for series with sorting after series init + if (!series.points && !series.data && series.enabledDataSorting) { + series.setData(series.options.data, false); + } + }); + }, + /** + * Sort and return chart series in order depending on the number of linked + * series. + * + * @private + * @function Highcharts.Series#getSeriesOrderByLinks + * + * @return {Array} + */ + getSeriesOrderByLinks: function () { + return this.series.concat().sort(function (a, b) { + if (a.linkedSeries.length || b.linkedSeries.length) { + return b.linkedSeries.length - a.linkedSeries.length; + } + return 0; + }); + }, + /** + * Order all series above a given index. When series are added and ordered + * by configuration, only the last series is handled (#248, #1123, #2456, + * #6112). This function is called on series initialization and destroy. + * + * @private + * @function Highcharts.Series#orderSeries + * @param {number} [fromIndex] + * If this is given, only the series above this index are handled. + * @return {void} + */ + orderSeries: function (fromIndex) { + var series = this.series, i = fromIndex || 0; + for (; i < series.length; i++) { + if (series[i]) { + /** + * Contains the series' index in the `Chart.series` array. + * + * @name Highcharts.Series#index + * @type {number} + * @readonly + */ + series[i].index = i; + series[i].name = series[i].getName(); + } + } + }, + /** + * Check whether a given point is within the plot area. + * + * @function Highcharts.Chart#isInsidePlot + * + * @param {number} plotX + * Pixel x relative to the plot area. + * + * @param {number} plotY + * Pixel y relative to the plot area. + * + * @param {boolean} [inverted] + * Whether the chart is inverted. + * + * @return {boolean} + * Returns true if the given point is inside the plot area. + */ + isInsidePlot: function (plotX, plotY, inverted) { + var x = inverted ? plotY : plotX, y = inverted ? plotX : plotY, e = { + x: x, + y: y, + isInsidePlot: x >= 0 && + x <= this.plotWidth && + y >= 0 && + y <= this.plotHeight + }; + fireEvent(this, 'afterIsInsidePlot', e); + return e.isInsidePlot; + }, + /** + * Redraw the chart after changes have been done to the data, axis extremes + * chart size or chart elements. All methods for updating axes, series or + * points have a parameter for redrawing the chart. This is `true` by + * default. But in many cases you want to do more than one operation on the + * chart before redrawing, for example add a number of points. In those + * cases it is a waste of resources to redraw the chart for each new point + * added. So you add the points and call `chart.redraw()` after. + * + * @function Highcharts.Chart#redraw + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * If or how to apply animation to the redraw. + * + * @return {void} + * + * @fires Highcharts.Chart#event:afterSetExtremes + * @fires Highcharts.Chart#event:beforeRedraw + * @fires Highcharts.Chart#event:predraw + * @fires Highcharts.Chart#event:redraw + * @fires Highcharts.Chart#event:render + * @fires Highcharts.Chart#event:updatedData + */ + redraw: function (animation) { + fireEvent(this, 'beforeRedraw'); + var chart = this, axes = chart.axes, series = chart.series, pointer = chart.pointer, legend = chart.legend, legendUserOptions = chart.userOptions.legend, redrawLegend = chart.isDirtyLegend, hasStackedSeries, hasDirtyStacks, hasCartesianSeries = chart.hasCartesianSeries, isDirtyBox = chart.isDirtyBox, i, serie, renderer = chart.renderer, isHiddenChart = renderer.isHidden(), afterRedraw = []; + // Handle responsive rules, not only on resize (#6130) + if (chart.setResponsive) { + chart.setResponsive(false); + } + // Set the global animation. When chart.hasRendered is not true, the + // redraw call comes from a responsive rule and animation should not + // occur. + setAnimation(chart.hasRendered ? animation : false, chart); + if (isHiddenChart) { + chart.temporaryDisplay(); + } + // Adjust title layout (reflow multiline text) + chart.layOutTitles(); + // link stacked series + i = series.length; + while (i--) { + serie = series[i]; + if (serie.options.stacking) { + hasStackedSeries = true; + if (serie.isDirty) { + hasDirtyStacks = true; + break; + } + } + } + if (hasDirtyStacks) { // mark others as dirty + i = series.length; + while (i--) { + serie = series[i]; + if (serie.options.stacking) { + serie.isDirty = true; + } + } + } + // Handle updated data in the series + series.forEach(function (serie) { + if (serie.isDirty) { + if (serie.options.legendType === 'point') { + if (serie.updateTotals) { + serie.updateTotals(); + } + redrawLegend = true; + } + else if (legendUserOptions && + (legendUserOptions.labelFormatter || + legendUserOptions.labelFormat)) { + redrawLegend = true; // #2165 + } + } + if (serie.isDirtyData) { + fireEvent(serie, 'updatedData'); + } + }); + // handle added or removed series + if (redrawLegend && legend && legend.options.enabled) { + // draw legend graphics + legend.render(); + chart.isDirtyLegend = false; + } + // reset stacks + if (hasStackedSeries) { + chart.getStacks(); + } + if (hasCartesianSeries) { + // set axes scales + axes.forEach(function (axis) { + axis.updateNames(); + axis.setScale(); + }); + } + chart.getMargins(); // #3098 + if (hasCartesianSeries) { + // If one axis is dirty, all axes must be redrawn (#792, #2169) + axes.forEach(function (axis) { + if (axis.isDirty) { + isDirtyBox = true; + } + }); + // redraw axes + axes.forEach(function (axis) { + // Fire 'afterSetExtremes' only if extremes are set + var key = axis.min + ',' + axis.max; + if (axis.extKey !== key) { // #821, #4452 + axis.extKey = key; + // prevent a recursive call to chart.redraw() (#1119) + afterRedraw.push(function () { + fireEvent(axis, 'afterSetExtremes', extend(axis.eventArgs, axis.getExtremes())); // #747, #751 + delete axis.eventArgs; + }); + } + if (isDirtyBox || hasStackedSeries) { + axis.redraw(); + } + }); + } + // the plot areas size has changed + if (isDirtyBox) { + chart.drawChartBox(); + } + // Fire an event before redrawing series, used by the boost module to + // clear previous series renderings. + fireEvent(chart, 'predraw'); + // redraw affected series + series.forEach(function (serie) { + if ((isDirtyBox || serie.isDirty) && serie.visible) { + serie.redraw(); + } + // Set it here, otherwise we will have unlimited 'updatedData' calls + // for a hidden series after setData(). Fixes #6012 + serie.isDirtyData = false; + }); + // move tooltip or reset + if (pointer) { + pointer.reset(true); + } + // redraw if canvas + renderer.draw(); + // Fire the events + fireEvent(chart, 'redraw'); + fireEvent(chart, 'render'); + if (isHiddenChart) { + chart.temporaryDisplay(true); + } + // Fire callbacks that are put on hold until after the redraw + afterRedraw.forEach(function (callback) { + callback.call(); + }); + }, + /** + * Get an axis, series or point object by `id` as given in the configuration + * options. Returns `undefined` if no item is found. + * + * @sample highcharts/plotoptions/series-id/ + * Get series by id + * + * @function Highcharts.Chart#get + * + * @param {string} id + * The id as given in the configuration options. + * + * @return {Highcharts.Axis|Highcharts.Series|Highcharts.Point|undefined} + * The retrieved item. + */ + get: function (id) { + var ret, series = this.series, i; + /** + * @private + * @param {Highcharts.Axis|Highcharts.Series} item + * @return {boolean} + */ + function itemById(item) { + return (item.id === id || + (item.options && item.options.id === id)); + } + ret = + // Search axes + find(this.axes, itemById) || + // Search series + find(this.series, itemById); + // Search points + for (i = 0; !ret && i < series.length; i++) { + ret = find(series[i].points || [], itemById); + } + return ret; + }, + /** + * Create the Axis instances based on the config options. + * + * @private + * @function Highcharts.Chart#getAxes + * + * @return {void} + * + * @fires Highcharts.Chart#event:afterGetAxes + * @fires Highcharts.Chart#event:getAxes + */ + getAxes: function () { + var chart = this, options = this.options, xAxisOptions = options.xAxis = splat(options.xAxis || {}), yAxisOptions = options.yAxis = splat(options.yAxis || {}), optionsArray; + fireEvent(this, 'getAxes'); + // make sure the options are arrays and add some members + xAxisOptions.forEach(function (axis, i) { + axis.index = i; + axis.isX = true; + }); + yAxisOptions.forEach(function (axis, i) { + axis.index = i; + }); + // concatenate all axis options into one array + optionsArray = xAxisOptions.concat(yAxisOptions); + optionsArray.forEach(function (axisOptions) { + new Axis(chart, axisOptions); // eslint-disable-line no-new + }); + fireEvent(this, 'afterGetAxes'); + }, + /** + * Returns an array of all currently selected points in the chart. Points + * can be selected by clicking or programmatically by the + * {@link Highcharts.Point#select} + * function. + * + * @sample highcharts/plotoptions/series-allowpointselect-line/ + * Get selected points + * + * @function Highcharts.Chart#getSelectedPoints + * + * @return {Array} + * The currently selected points. + */ + getSelectedPoints: function () { + var points = []; + this.series.forEach(function (serie) { + // For one-to-one points inspect series.data in order to retrieve + // points outside the visible range (#6445). For grouped data, + // inspect the generated series.points. + points = points.concat(serie.getPointsCollection().filter(function (point) { + return pick(point.selectedStaging, point.selected); + })); + }); + return points; + }, + /** + * Returns an array of all currently selected series in the chart. Series + * can be selected either programmatically by the + * {@link Highcharts.Series#select} + * function or by checking the checkbox next to the legend item if + * [series.showCheckBox](https://api.highcharts.com/highcharts/plotOptions.series.showCheckbox) + * is true. + * + * @sample highcharts/members/chart-getselectedseries/ + * Get selected series + * + * @function Highcharts.Chart#getSelectedSeries + * + * @return {Array} + * The currently selected series. + */ + getSelectedSeries: function () { + return this.series.filter(function (serie) { + return serie.selected; + }); + }, + /** + * Set a new title or subtitle for the chart. + * + * @sample highcharts/members/chart-settitle/ + * Set title text and styles + * + * @function Highcharts.Chart#setTitle + * + * @param {Highcharts.TitleOptions} [titleOptions] + * New title options. The title text itself is set by the + * `titleOptions.text` property. + * + * @param {Highcharts.SubtitleOptions} [subtitleOptions] + * New subtitle options. The subtitle text itself is set by the + * `subtitleOptions.text` property. + * + * @param {boolean} [redraw] + * Whether to redraw the chart or wait for a later call to + * `chart.redraw()`. + * + * @return {void} + */ + setTitle: function (titleOptions, subtitleOptions, redraw) { + this.applyDescription('title', titleOptions); + this.applyDescription('subtitle', subtitleOptions); + // The initial call also adds the caption. On update, chart.update will + // relay to Chart.setCaption. + this.applyDescription('caption', void 0); + this.layOutTitles(redraw); + }, + /** + * Apply a title, subtitle or caption for the chart + * + * @private + * @function Highcharts.Chart#applyDescription + * + * @param name {string} + * Either title, subtitle or caption + * @param {Highcharts.TitleOptions|Highcharts.SubtitleOptions|Highcharts.CaptionOptions|undefined} explicitOptions + * The options to set, will be merged with default options. + * + * @return {void} + */ + applyDescription: function (name, explicitOptions) { + var chart = this; + // Default style + var style = name === 'title' ? { + color: '#333333', + fontSize: this.options.isStock ? '16px' : '18px' // #2944 + } : { + color: '#666666' + }; + // Merge default options with explicit options + var options = this.options[name] = merge( + // Default styles + (!this.styledMode && { style: style }), this.options[name], explicitOptions); + var elem = this[name]; + if (elem && explicitOptions) { + this[name] = elem = elem.destroy(); // remove old + } + if (options && !elem) { + elem = this.renderer.text(options.text, 0, 0, options.useHTML) + .attr({ + align: options.align, + 'class': 'highcharts-' + name, + zIndex: options.zIndex || 4 + }) + .add(); + // Update methods, shortcut to Chart.setTitle, Chart.setSubtitle and + // Chart.setCaption + elem.update = function (updateOptions) { + var fn = { + title: 'setTitle', + subtitle: 'setSubtitle', + caption: 'setCaption' + }[name]; + chart[fn](updateOptions); + }; + // Presentational + if (!this.styledMode) { + elem.css(options.style); + } + /** + * The chart title. The title has an `update` method that allows + * modifying the options directly or indirectly via + * `chart.update`. + * + * @sample highcharts/members/title-update/ + * Updating titles + * + * @name Highcharts.Chart#title + * @type {Highcharts.TitleObject} + */ + /** + * The chart subtitle. The subtitle has an `update` method that + * allows modifying the options directly or indirectly via + * `chart.update`. + * + * @name Highcharts.Chart#subtitle + * @type {Highcharts.SubtitleObject} + */ + this[name] = elem; + } + }, + /** + * Internal function to lay out the chart title, subtitle and caption, and + * cache the full offset height for use in `getMargins`. The result is + * stored in `this.titleOffset`. + * + * @private + * @function Highcharts.Chart#layOutTitles + * + * @param {boolean} [redraw=true] + * + * @return {void} + * + * @fires Highcharts.Chart#event:afterLayOutTitles + */ + layOutTitles: function (redraw) { + var titleOffset = [0, 0, 0], requiresDirtyBox, renderer = this.renderer, spacingBox = this.spacingBox; + // Lay out the title and the subtitle respectively + ['title', 'subtitle', 'caption'].forEach(function (key) { + var title = this[key], titleOptions = this.options[key], verticalAlign = titleOptions.verticalAlign || 'top', offset = key === 'title' ? -3 : + // Floating subtitle (#6574) + verticalAlign === 'top' ? titleOffset[0] + 2 : 0, titleSize, height; + if (title) { + if (!this.styledMode) { + titleSize = titleOptions.style.fontSize; + } + titleSize = renderer.fontMetrics(titleSize, title).b; + title + .css({ + width: (titleOptions.width || + spacingBox.width + (titleOptions.widthAdjust || 0)) + 'px' + }); + // Skip the cache for HTML (#3481, #11666) + height = Math.round(title.getBBox(titleOptions.useHTML).height); + title.align(extend({ + y: verticalAlign === 'bottom' ? + titleSize : + offset + titleSize, + height: height + }, titleOptions), false, 'spacingBox'); + if (!titleOptions.floating) { + if (verticalAlign === 'top') { + titleOffset[0] = Math.ceil(titleOffset[0] + + height); + } + else if (verticalAlign === 'bottom') { + titleOffset[2] = Math.ceil(titleOffset[2] + + height); + } + } + } + }, this); + // Handle title.margin and caption.margin + if (titleOffset[0] && + (this.options.title.verticalAlign || 'top') === 'top') { + titleOffset[0] += this.options.title.margin; + } + if (titleOffset[2] && + this.options.caption.verticalAlign === 'bottom') { + titleOffset[2] += this.options.caption.margin; + } + requiresDirtyBox = (!this.titleOffset || + this.titleOffset.join(',') !== titleOffset.join(',')); + // Used in getMargins + this.titleOffset = titleOffset; + fireEvent(this, 'afterLayOutTitles'); + if (!this.isDirtyBox && requiresDirtyBox) { + this.isDirtyBox = this.isDirtyLegend = requiresDirtyBox; + // Redraw if necessary (#2719, #2744) + if (this.hasRendered && pick(redraw, true) && this.isDirtyBox) { + this.redraw(); + } + } + }, + /** + * Internal function to get the chart width and height according to options + * and container size. Sets {@link Chart.chartWidth} and + * {@link Chart.chartHeight}. + * + * @private + * @function Highcharts.Chart#getChartSize + * + * @return {void} + */ + getChartSize: function () { + var chart = this, optionsChart = chart.options.chart, widthOption = optionsChart.width, heightOption = optionsChart.height, renderTo = chart.renderTo; + // Get inner width and height + if (!defined(widthOption)) { + chart.containerWidth = getStyle(renderTo, 'width'); + } + if (!defined(heightOption)) { + chart.containerHeight = getStyle(renderTo, 'height'); + } + /** + * The current pixel width of the chart. + * + * @name Highcharts.Chart#chartWidth + * @type {number} + */ + chart.chartWidth = Math.max(// #1393 + 0, widthOption || chart.containerWidth || 600 // #1460 + ); + /** + * The current pixel height of the chart. + * + * @name Highcharts.Chart#chartHeight + * @type {number} + */ + chart.chartHeight = Math.max(0, relativeLength(heightOption, chart.chartWidth) || + (chart.containerHeight > 1 ? + chart.containerHeight : + 400)); + }, + /** + * If the renderTo element has no offsetWidth, most likely one or more of + * its parents are hidden. Loop up the DOM tree to temporarily display the + * parents, then save the original display properties, and when the true + * size is retrieved, reset them. Used on first render and on redraws. + * + * @private + * @function Highcharts.Chart#temporaryDisplay + * + * @param {boolean} [revert] + * Revert to the saved original styles. + * + * @return {void} + */ + temporaryDisplay: function (revert) { + var node = this.renderTo, tempStyle; + if (!revert) { + while (node && node.style) { + // When rendering to a detached node, it needs to be temporarily + // attached in order to read styling and bounding boxes (#5783, + // #7024). + if (!doc.body.contains(node) && !node.parentNode) { + node.hcOrigDetached = true; + doc.body.appendChild(node); + } + if (getStyle(node, 'display', false) === 'none' || + node.hcOricDetached) { + node.hcOrigStyle = { + display: node.style.display, + height: node.style.height, + overflow: node.style.overflow + }; + tempStyle = { + display: 'block', + overflow: 'hidden' + }; + if (node !== this.renderTo) { + tempStyle.height = 0; + } + css(node, tempStyle); + // If it still doesn't have an offset width after setting + // display to block, it probably has an !important priority + // #2631, 6803 + if (!node.offsetWidth) { + node.style.setProperty('display', 'block', 'important'); + } + } + node = node.parentNode; + if (node === doc.body) { + break; + } + } + } + else { + while (node && node.style) { + if (node.hcOrigStyle) { + css(node, node.hcOrigStyle); + delete node.hcOrigStyle; + } + if (node.hcOrigDetached) { + doc.body.removeChild(node); + node.hcOrigDetached = false; + } + node = node.parentNode; + } + } + }, + /** + * Set the {@link Chart.container|chart container's} class name, in + * addition to `highcharts-container`. + * + * @function Highcharts.Chart#setClassName + * + * @param {string} [className] + * + * @return {void} + */ + setClassName: function (className) { + this.container.className = 'highcharts-container ' + (className || ''); + }, + /** + * Get the containing element, determine the size and create the inner + * container div to hold the chart. + * + * @private + * @function Highcharts.Chart#afterGetContainer + * + * @return {void} + * + * @fires Highcharts.Chart#event:afterGetContainer + */ + getContainer: function () { + var chart = this, container, options = chart.options, optionsChart = options.chart, chartWidth, chartHeight, renderTo = chart.renderTo, indexAttrName = 'data-highcharts-chart', oldChartIndex, Ren, containerId = uniqueKey(), containerStyle, key; + if (!renderTo) { + chart.renderTo = renderTo = + optionsChart.renderTo; + } + if (isString(renderTo)) { + chart.renderTo = renderTo = + doc.getElementById(renderTo); + } + // Display an error if the renderTo is wrong + if (!renderTo) { + error(13, true, chart); + } + // If the container already holds a chart, destroy it. The check for + // hasRendered is there because web pages that are saved to disk from + // the browser, will preserve the data-highcharts-chart attribute and + // the SVG contents, but not an interactive chart. So in this case, + // charts[oldChartIndex] will point to the wrong chart if any (#2609). + oldChartIndex = pInt(attr(renderTo, indexAttrName)); + if (isNumber(oldChartIndex) && + charts[oldChartIndex] && + charts[oldChartIndex].hasRendered) { + charts[oldChartIndex].destroy(); + } + // Make a reference to the chart from the div + attr(renderTo, indexAttrName, chart.index); + // remove previous chart + renderTo.innerHTML = ''; + // If the container doesn't have an offsetWidth, it has or is a child of + // a node that has display:none. We need to temporarily move it out to a + // visible state to determine the size, else the legend and tooltips + // won't render properly. The skipClone option is used in sparklines as + // a micro optimization, saving about 1-2 ms each chart. + if (!optionsChart.skipClone && !renderTo.offsetWidth) { + chart.temporaryDisplay(); + } + // get the width and height + chart.getChartSize(); + chartWidth = chart.chartWidth; + chartHeight = chart.chartHeight; + // Allow table cells and flex-boxes to shrink without the chart blocking + // them out (#6427) + css(renderTo, { overflow: 'hidden' }); + // Create the inner container + if (!chart.styledMode) { + containerStyle = extend({ + position: 'relative', + // needed for context menu (avoidscrollbars) and content + // overflow in IE + overflow: 'hidden', + width: chartWidth + 'px', + height: chartHeight + 'px', + textAlign: 'left', + lineHeight: 'normal', + zIndex: 0, + '-webkit-tap-highlight-color': 'rgba(0,0,0,0)' + }, optionsChart.style); + } + /** + * The containing HTML element of the chart. The container is + * dynamically inserted into the element given as the `renderTo` + * parameter in the {@link Highcharts#chart} constructor. + * + * @name Highcharts.Chart#container + * @type {Highcharts.HTMLDOMElement} + */ + container = createElement('div', { + id: containerId + }, containerStyle, renderTo); + chart.container = container; + // cache the cursor (#1650) + chart._cursor = container.style.cursor; + // Initialize the renderer + Ren = H[optionsChart.renderer] || H.Renderer; + /** + * The renderer instance of the chart. Each chart instance has only one + * associated renderer. + * + * @name Highcharts.Chart#renderer + * @type {Highcharts.SVGRenderer} + */ + chart.renderer = new Ren(container, chartWidth, chartHeight, null, optionsChart.forExport, options.exporting && options.exporting.allowHTML, chart.styledMode); + // Set the initial animation from the options + setAnimation(void 0, chart); + chart.setClassName(optionsChart.className); + if (!chart.styledMode) { + chart.renderer.setStyle(optionsChart.style); + } + else { + // Initialize definitions + for (key in options.defs) { // eslint-disable-line guard-for-in + this.renderer.definition(options.defs[key]); + } + } + // Add a reference to the charts index + chart.renderer.chartIndex = chart.index; + fireEvent(this, 'afterGetContainer'); + }, + /** + * Calculate margins by rendering axis labels in a preliminary position. + * Title, subtitle and legend have already been rendered at this stage, but + * will be moved into their final positions. + * + * @private + * @function Highcharts.Chart#getMargins + * @param {boolean} skipAxes + * @return {void} + * @fires Highcharts.Chart#event:getMargins + */ + getMargins: function (skipAxes) { + var _a = this, spacing = _a.spacing, margin = _a.margin, titleOffset = _a.titleOffset; + this.resetMargins(); + // Adjust for title and subtitle + if (titleOffset[0] && !defined(margin[0])) { + this.plotTop = Math.max(this.plotTop, titleOffset[0] + spacing[0]); + } + if (titleOffset[2] && !defined(margin[2])) { + this.marginBottom = Math.max(this.marginBottom, titleOffset[2] + spacing[2]); + } + // Adjust for legend + if (this.legend && this.legend.display) { + this.legend.adjustMargins(margin, spacing); + } + fireEvent(this, 'getMargins'); + if (!skipAxes) { + this.getAxisMargins(); + } + }, + /** + * @private + * @function Highcharts.Chart#getAxisMargins + * @return {void} + */ + getAxisMargins: function () { + var chart = this, + // [top, right, bottom, left] + axisOffset = chart.axisOffset = [0, 0, 0, 0], colorAxis = chart.colorAxis, margin = chart.margin, getOffset = function (axes) { + axes.forEach(function (axis) { + if (axis.visible) { + axis.getOffset(); + } + }); + }; + // pre-render axes to get labels offset width + if (chart.hasCartesianSeries) { + getOffset(chart.axes); + } + else if (colorAxis && colorAxis.length) { + getOffset(colorAxis); + } + // Add the axis offsets + marginNames.forEach(function (m, side) { + if (!defined(margin[side])) { + chart[m] += axisOffset[side]; + } + }); + chart.setChartSize(); + }, + /** + * Reflows the chart to its container. By default, the chart reflows + * automatically to its container following a `window.resize` event, as per + * the [chart.reflow](https://api.highcharts.com/highcharts/chart.reflow) + * option. However, there are no reliable events for div resize, so if the + * container is resized without a window resize event, this must be called + * explicitly. + * + * @sample highcharts/members/chart-reflow/ + * Resize div and reflow + * @sample highcharts/chart/events-container/ + * Pop up and reflow + * + * @function Highcharts.Chart#reflow + * + * @param {global.Event} [e] + * Event arguments. Used primarily when the function is called + * internally as a response to window resize. + */ + reflow: function (e) { + var chart = this, optionsChart = chart.options.chart, renderTo = chart.renderTo, hasUserSize = (defined(optionsChart.width) && + defined(optionsChart.height)), width = optionsChart.width || getStyle(renderTo, 'width'), height = optionsChart.height || getStyle(renderTo, 'height'), target = e ? e.target : win; + // Width and height checks for display:none. Target is doc in IE8 and + // Opera, win in Firefox, Chrome and IE9. + if (!hasUserSize && + !chart.isPrinting && + width && + height && + (target === win || target === doc)) { + if (width !== chart.containerWidth || + height !== chart.containerHeight) { + U.clearTimeout(chart.reflowTimeout); + // When called from window.resize, e is set, else it's called + // directly (#2224) + chart.reflowTimeout = syncTimeout(function () { + // Set size, it may have been destroyed in the meantime + // (#1257) + if (chart.container) { + chart.setSize(void 0, void 0, false); + } + }, e ? 100 : 0); + } + chart.containerWidth = width; + chart.containerHeight = height; + } + }, + /** + * Toggle the event handlers necessary for auto resizing, depending on the + * `chart.reflow` option. + * + * @private + * @function Highcharts.Chart#setReflow + * @param {boolean} [reflow] + * @return {void} + */ + setReflow: function (reflow) { + var chart = this; + if (reflow !== false && !this.unbindReflow) { + this.unbindReflow = addEvent(win, 'resize', function (e) { + // a removed event listener still runs in Edge and IE if the + // listener was removed while the event runs, so check if the + // chart is not destroyed (#11609) + if (chart.options) { + chart.reflow(e); + } + }); + addEvent(this, 'destroy', this.unbindReflow); + } + else if (reflow === false && this.unbindReflow) { + // Unbind and unset + this.unbindReflow = this.unbindReflow(); + } + // The following will add listeners to re-fit the chart before and after + // printing (#2284). However it only works in WebKit. Should have worked + // in Firefox, but not supported in IE. + /* + if (win.matchMedia) { + win.matchMedia('print').addListener(function reflow() { + chart.reflow(); + }); + } + //*/ + }, + /** + * Resize the chart to a given width and height. In order to set the width + * only, the height argument may be skipped. To set the height only, pass + * `undefined` for the width. + * + * @sample highcharts/members/chart-setsize-button/ + * Test resizing from buttons + * @sample highcharts/members/chart-setsize-jquery-resizable/ + * Add a jQuery UI resizable + * @sample stock/members/chart-setsize/ + * Highstock with UI resizable + * + * @function Highcharts.Chart#setSize + * + * @param {number|null} [width] + * The new pixel width of the chart. Since v4.2.6, the argument can + * be `undefined` in order to preserve the current value (when + * setting height only), or `null` to adapt to the width of the + * containing element. + * + * @param {number|null} [height] + * The new pixel height of the chart. Since v4.2.6, the argument can + * be `undefined` in order to preserve the current value, or `null` + * in order to adapt to the height of the containing element. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=true] + * Whether and how to apply animation. + * + * @return {void} + * + * @fires Highcharts.Chart#event:endResize + * @fires Highcharts.Chart#event:resize + */ + setSize: function (width, height, animation) { + var chart = this, renderer = chart.renderer, globalAnimation; + // Handle the isResizing counter + chart.isResizing += 1; + // set the animation for the current process + setAnimation(animation, chart); + globalAnimation = renderer.globalAnimation; + chart.oldChartHeight = chart.chartHeight; + chart.oldChartWidth = chart.chartWidth; + if (typeof width !== 'undefined') { + chart.options.chart.width = width; + } + if (typeof height !== 'undefined') { + chart.options.chart.height = height; + } + chart.getChartSize(); + // Resize the container with the global animation applied if enabled + // (#2503) + if (!chart.styledMode) { + (globalAnimation ? animate : css)(chart.container, { + width: chart.chartWidth + 'px', + height: chart.chartHeight + 'px' + }, globalAnimation); + } + chart.setChartSize(true); + renderer.setSize(chart.chartWidth, chart.chartHeight, globalAnimation); + // handle axes + chart.axes.forEach(function (axis) { + axis.isDirty = true; + axis.setScale(); + }); + chart.isDirtyLegend = true; // force legend redraw + chart.isDirtyBox = true; // force redraw of plot and chart border + chart.layOutTitles(); // #2857 + chart.getMargins(); + chart.redraw(globalAnimation); + chart.oldChartHeight = null; + fireEvent(chart, 'resize'); + // Fire endResize and set isResizing back. If animation is disabled, + // fire without delay + syncTimeout(function () { + if (chart) { + fireEvent(chart, 'endResize', null, function () { + chart.isResizing -= 1; + }); + } + }, animObject(globalAnimation).duration || 0); + }, + /** + * Set the public chart properties. This is done before and after the + * pre-render to determine margin sizes. + * + * @private + * @function Highcharts.Chart#setChartSize + * + * @param {boolean} skipAxes + * + * @return {void} + * + * @fires Highcharts.Chart#event:afterSetChartSize + */ + setChartSize: function (skipAxes) { + var chart = this, inverted = chart.inverted, renderer = chart.renderer, chartWidth = chart.chartWidth, chartHeight = chart.chartHeight, optionsChart = chart.options.chart, spacing = chart.spacing, clipOffset = chart.clipOffset, clipX, clipY, plotLeft, plotTop, plotWidth, plotHeight, plotBorderWidth; + /** + * The current left position of the plot area in pixels. + * + * @name Highcharts.Chart#plotLeft + * @type {number} + */ + chart.plotLeft = plotLeft = Math.round(chart.plotLeft); + /** + * The current top position of the plot area in pixels. + * + * @name Highcharts.Chart#plotTop + * @type {number} + */ + chart.plotTop = plotTop = Math.round(chart.plotTop); + /** + * The current width of the plot area in pixels. + * + * @name Highcharts.Chart#plotWidth + * @type {number} + */ + chart.plotWidth = plotWidth = Math.max(0, Math.round(chartWidth - plotLeft - chart.marginRight)); + /** + * The current height of the plot area in pixels. + * + * @name Highcharts.Chart#plotHeight + * @type {number} + */ + chart.plotHeight = plotHeight = Math.max(0, Math.round(chartHeight - plotTop - chart.marginBottom)); + chart.plotSizeX = inverted ? plotHeight : plotWidth; + chart.plotSizeY = inverted ? plotWidth : plotHeight; + chart.plotBorderWidth = optionsChart.plotBorderWidth || 0; + // Set boxes used for alignment + chart.spacingBox = renderer.spacingBox = { + x: spacing[3], + y: spacing[0], + width: chartWidth - spacing[3] - spacing[1], + height: chartHeight - spacing[0] - spacing[2] + }; + chart.plotBox = renderer.plotBox = { + x: plotLeft, + y: plotTop, + width: plotWidth, + height: plotHeight + }; + plotBorderWidth = 2 * Math.floor(chart.plotBorderWidth / 2); + clipX = Math.ceil(Math.max(plotBorderWidth, clipOffset[3]) / 2); + clipY = Math.ceil(Math.max(plotBorderWidth, clipOffset[0]) / 2); + chart.clipBox = { + x: clipX, + y: clipY, + width: Math.floor(chart.plotSizeX - + Math.max(plotBorderWidth, clipOffset[1]) / 2 - + clipX), + height: Math.max(0, Math.floor(chart.plotSizeY - + Math.max(plotBorderWidth, clipOffset[2]) / 2 - + clipY)) + }; + if (!skipAxes) { + chart.axes.forEach(function (axis) { + axis.setAxisSize(); + axis.setAxisTranslation(); + }); + } + fireEvent(chart, 'afterSetChartSize', { skipAxes: skipAxes }); + }, + /** + * Initial margins before auto size margins are applied. + * + * @private + * @function Highcharts.Chart#resetMargins + * @return {void} + */ + resetMargins: function () { + fireEvent(this, 'resetMargins'); + var chart = this, chartOptions = chart.options.chart; + // Create margin and spacing array + ['margin', 'spacing'].forEach(function splashArrays(target) { + var value = chartOptions[target], values = isObject(value) ? value : [value, value, value, value]; + [ + 'Top', + 'Right', + 'Bottom', + 'Left' + ].forEach(function (sideName, side) { + chart[target][side] = pick(chartOptions[target + sideName], values[side]); + }); + }); + // Set margin names like chart.plotTop, chart.plotLeft, + // chart.marginRight, chart.marginBottom. + marginNames.forEach(function (m, side) { + chart[m] = pick(chart.margin[side], chart.spacing[side]); + }); + chart.axisOffset = [0, 0, 0, 0]; // top, right, bottom, left + chart.clipOffset = [0, 0, 0, 0]; + }, + /** + * Internal function to draw or redraw the borders and backgrounds for chart + * and plot area. + * + * @private + * @function Highcharts.Chart#drawChartBox + * @return {void} + * @fires Highcharts.Chart#event:afterDrawChartBox + */ + drawChartBox: function () { + var chart = this, optionsChart = chart.options.chart, renderer = chart.renderer, chartWidth = chart.chartWidth, chartHeight = chart.chartHeight, chartBackground = chart.chartBackground, plotBackground = chart.plotBackground, plotBorder = chart.plotBorder, chartBorderWidth, styledMode = chart.styledMode, plotBGImage = chart.plotBGImage, chartBackgroundColor = optionsChart.backgroundColor, plotBackgroundColor = optionsChart.plotBackgroundColor, plotBackgroundImage = optionsChart.plotBackgroundImage, mgn, bgAttr, plotLeft = chart.plotLeft, plotTop = chart.plotTop, plotWidth = chart.plotWidth, plotHeight = chart.plotHeight, plotBox = chart.plotBox, clipRect = chart.clipRect, clipBox = chart.clipBox, verb = 'animate'; + // Chart area + if (!chartBackground) { + chart.chartBackground = chartBackground = renderer.rect() + .addClass('highcharts-background') + .add(); + verb = 'attr'; + } + if (!styledMode) { + // Presentational + chartBorderWidth = optionsChart.borderWidth || 0; + mgn = chartBorderWidth + (optionsChart.shadow ? 8 : 0); + bgAttr = { + fill: chartBackgroundColor || 'none' + }; + if (chartBorderWidth || chartBackground['stroke-width']) { // #980 + bgAttr.stroke = optionsChart.borderColor; + bgAttr['stroke-width'] = chartBorderWidth; + } + chartBackground + .attr(bgAttr) + .shadow(optionsChart.shadow); + } + else { + chartBorderWidth = mgn = chartBackground.strokeWidth(); + } + chartBackground[verb]({ + x: mgn / 2, + y: mgn / 2, + width: chartWidth - mgn - chartBorderWidth % 2, + height: chartHeight - mgn - chartBorderWidth % 2, + r: optionsChart.borderRadius + }); + // Plot background + verb = 'animate'; + if (!plotBackground) { + verb = 'attr'; + chart.plotBackground = plotBackground = renderer.rect() + .addClass('highcharts-plot-background') + .add(); + } + plotBackground[verb](plotBox); + if (!styledMode) { + // Presentational attributes for the background + plotBackground + .attr({ + fill: plotBackgroundColor || 'none' + }) + .shadow(optionsChart.plotShadow); + // Create the background image + if (plotBackgroundImage) { + if (!plotBGImage) { + chart.plotBGImage = renderer.image(plotBackgroundImage, plotLeft, plotTop, plotWidth, plotHeight).add(); + } + else { + if (plotBackgroundImage !== plotBGImage.attr('href')) { + plotBGImage.attr('href', plotBackgroundImage); + } + plotBGImage.animate(plotBox); + } + } + } + // Plot clip + if (!clipRect) { + chart.clipRect = renderer.clipRect(clipBox); + } + else { + clipRect.animate({ + width: clipBox.width, + height: clipBox.height + }); + } + // Plot area border + verb = 'animate'; + if (!plotBorder) { + verb = 'attr'; + chart.plotBorder = plotBorder = renderer.rect() + .addClass('highcharts-plot-border') + .attr({ + zIndex: 1 // Above the grid + }) + .add(); + } + if (!styledMode) { + // Presentational + plotBorder.attr({ + stroke: optionsChart.plotBorderColor, + 'stroke-width': optionsChart.plotBorderWidth || 0, + fill: 'none' + }); + } + plotBorder[verb](plotBorder.crisp({ + x: plotLeft, + y: plotTop, + width: plotWidth, + height: plotHeight + }, -plotBorder.strokeWidth())); // #3282 plotBorder should be negative; + // reset + chart.isDirtyBox = false; + fireEvent(this, 'afterDrawChartBox'); + }, + /** + * Detect whether a certain chart property is needed based on inspecting its + * options and series. This mainly applies to the chart.inverted property, + * and in extensions to the chart.angular and chart.polar properties. + * + * @private + * @function Highcharts.Chart#propFromSeries + * @return {void} + */ + propFromSeries: function () { + var chart = this, optionsChart = chart.options.chart, klass, seriesOptions = chart.options.series, i, value; + /** + * The flag is set to `true` if a series of the chart is inverted. + * + * @name Highcharts.Chart#inverted + * @type {boolean|undefined} + */ + ['inverted', 'angular', 'polar'].forEach(function (key) { + // The default series type's class + klass = seriesTypes[(optionsChart.type || + optionsChart.defaultSeriesType)]; + // Get the value from available chart-wide properties + value = + // It is set in the options: + optionsChart[key] || + // The default series class: + (klass && klass.prototype[key]); + // requires it + // 4. Check if any the chart's series require it + i = seriesOptions && seriesOptions.length; + while (!value && i--) { + klass = seriesTypes[seriesOptions[i].type]; + if (klass && klass.prototype[key]) { + value = true; + } + } + // Set the chart property + chart[key] = value; + }); + }, + /** + * Internal function to link two or more series together, based on the + * `linkedTo` option. This is done from `Chart.render`, and after + * `Chart.addSeries` and `Series.remove`. + * + * @private + * @function Highcharts.Chart#linkSeries + * @return {void} + * @fires Highcharts.Chart#event:afterLinkSeries + */ + linkSeries: function () { + var chart = this, chartSeries = chart.series; + // Reset links + chartSeries.forEach(function (series) { + series.linkedSeries.length = 0; + }); + // Apply new links + chartSeries.forEach(function (series) { + var linkedTo = series.options.linkedTo; + if (isString(linkedTo)) { + if (linkedTo === ':previous') { + linkedTo = chart.series[series.index - 1]; + } + else { + linkedTo = chart.get(linkedTo); + } + // #3341 avoid mutual linking + if (linkedTo && linkedTo.linkedParent !== series) { + linkedTo.linkedSeries.push(series); + series.linkedParent = linkedTo; + if (linkedTo.enabledDataSorting) { + series.setDataSortingOptions(); + } + series.visible = pick(series.options.visible, linkedTo.options.visible, series.visible); // #3879 + } + } + }); + fireEvent(this, 'afterLinkSeries'); + }, + /** + * Render series for the chart. + * + * @private + * @function Highcharts.Chart#renderSeries + * @return {void} + */ + renderSeries: function () { + this.series.forEach(function (serie) { + serie.translate(); + serie.render(); + }); + }, + /** + * Render labels for the chart. + * + * @private + * @function Highcharts.Chart#renderLabels + * @return {void} + */ + renderLabels: function () { + var chart = this, labels = chart.options.labels; + if (labels.items) { + labels.items.forEach(function (label) { + var style = extend(labels.style, label.style), x = pInt(style.left) + chart.plotLeft, y = pInt(style.top) + chart.plotTop + 12; + // delete to prevent rewriting in IE + delete style.left; + delete style.top; + chart.renderer.text(label.html, x, y) + .attr({ zIndex: 2 }) + .css(style) + .add(); + }); + } + }, + /** + * Render all graphics for the chart. Runs internally on initialization. + * + * @private + * @function Highcharts.Chart#render + * @return {void} + */ + render: function () { + var chart = this, axes = chart.axes, colorAxis = chart.colorAxis, renderer = chart.renderer, options = chart.options, correction = 0, // correction for X axis labels + tempWidth, tempHeight, redoHorizontal, redoVertical, renderAxes = function (axes) { + axes.forEach(function (axis) { + if (axis.visible) { + axis.render(); + } + }); + }; + // Title + chart.setTitle(); + /** + * The overview of the chart's series. + * + * @name Highcharts.Chart#legend + * @type {Highcharts.Legend} + */ + chart.legend = new Legend(chart, options.legend); + // Get stacks + if (chart.getStacks) { + chart.getStacks(); + } + // Get chart margins + chart.getMargins(true); + chart.setChartSize(); + // Record preliminary dimensions for later comparison + tempWidth = chart.plotWidth; + axes.some(function (axis) { + if (axis.horiz && + axis.visible && + axis.options.labels.enabled && + axis.series.length) { + // 21 is the most common correction for X axis labels + correction = 21; + return true; + } + }); + // use Math.max to prevent negative plotHeight + chart.plotHeight = Math.max(chart.plotHeight - correction, 0); + tempHeight = chart.plotHeight; + // Get margins by pre-rendering axes + axes.forEach(function (axis) { + axis.setScale(); + }); + chart.getAxisMargins(); + // If the plot area size has changed significantly, calculate tick + // positions again + redoHorizontal = tempWidth / chart.plotWidth > 1.1; + // Height is more sensitive, use lower threshold + redoVertical = tempHeight / chart.plotHeight > 1.05; + if (redoHorizontal || redoVertical) { + axes.forEach(function (axis) { + if ((axis.horiz && redoHorizontal) || + (!axis.horiz && redoVertical)) { + // update to reflect the new margins + axis.setTickInterval(true); + } + }); + chart.getMargins(); // second pass to check for new labels + } + // Draw the borders and backgrounds + chart.drawChartBox(); + // Axes + if (chart.hasCartesianSeries) { + renderAxes(axes); + } + else if (colorAxis && colorAxis.length) { + renderAxes(colorAxis); + } + // The series + if (!chart.seriesGroup) { + chart.seriesGroup = renderer.g('series-group') + .attr({ zIndex: 3 }) + .add(); + } + chart.renderSeries(); + // Labels + chart.renderLabels(); + // Credits + chart.addCredits(); + // Handle responsiveness + if (chart.setResponsive) { + chart.setResponsive(); + } + // Handle scaling + chart.updateContainerScaling(); + // Set flag + chart.hasRendered = true; + }, + /** + * Set a new credits label for the chart. + * + * @sample highcharts/credits/credits-update/ + * Add and update credits + * + * @function Highcharts.Chart#addCredits + * + * @param {Highcharts.CreditsOptions} credits + * A configuration object for the new credits. + * + * @return {void} + */ + addCredits: function (credits) { + var chart = this; + credits = merge(true, this.options.credits, credits); + if (credits.enabled && !this.credits) { + /** + * The chart's credits label. The label has an `update` method that + * allows setting new options as per the + * [credits options set](https://api.highcharts.com/highcharts/credits). + * + * @name Highcharts.Chart#credits + * @type {Highcharts.SVGElement} + */ + this.credits = this.renderer.text(credits.text + (this.mapCredits || ''), 0, 0) + .addClass('highcharts-credits') + .on('click', function () { + if (credits.href) { + win.location.href = credits.href; + } + }) + .attr({ + align: credits.position.align, + zIndex: 8 + }); + if (!chart.styledMode) { + this.credits.css(credits.style); + } + this.credits + .add() + .align(credits.position); + // Dynamically update + this.credits.update = function (options) { + chart.credits = chart.credits.destroy(); + chart.addCredits(options); + }; + } + }, + /** + * Handle scaling, #11329 - when there is scaling/transform on the container + * or on a parent element, we need to take this into account. We calculate + * the scaling once here and it is picked up where we need to use it + * (Pointer, Tooltip). + * + * @private + * @function Highcharts.Chart#updateContainerScaling + * @return {void} + */ + updateContainerScaling: function () { + var container = this.container; + if (container.offsetWidth && + container.offsetHeight && + container.getBoundingClientRect) { + var bb = container.getBoundingClientRect(), scaleX = bb.width / container.offsetWidth, scaleY = bb.height / container.offsetHeight; + if (scaleX !== 1 || scaleY !== 1) { + this.containerScaling = { scaleX: scaleX, scaleY: scaleY }; + } + else { + delete this.containerScaling; + } + } + }, + /** + * Remove the chart and purge memory. This method is called internally + * before adding a second chart into the same container, as well as on + * window unload to prevent leaks. + * + * @sample highcharts/members/chart-destroy/ + * Destroy the chart from a button + * @sample stock/members/chart-destroy/ + * Destroy with Highstock + * + * @function Highcharts.Chart#destroy + * + * @return {void} + * + * @fires Highcharts.Chart#event:destroy + */ + destroy: function () { + var chart = this, axes = chart.axes, series = chart.series, container = chart.container, i, parentNode = container && container.parentNode; + // fire the chart.destoy event + fireEvent(chart, 'destroy'); + // Delete the chart from charts lookup array + if (chart.renderer.forExport) { + erase(charts, chart); // #6569 + } + else { + charts[chart.index] = void 0; + } + H.chartCount--; + chart.renderTo.removeAttribute('data-highcharts-chart'); + // remove events + removeEvent(chart); + // ==== Destroy collections: + // Destroy axes + i = axes.length; + while (i--) { + axes[i] = axes[i].destroy(); + } + // Destroy scroller & scroller series before destroying base series + if (this.scroller && this.scroller.destroy) { + this.scroller.destroy(); + } + // Destroy each series + i = series.length; + while (i--) { + series[i] = series[i].destroy(); + } + // ==== Destroy chart properties: + [ + 'title', 'subtitle', 'chartBackground', 'plotBackground', + 'plotBGImage', 'plotBorder', 'seriesGroup', 'clipRect', 'credits', + 'pointer', 'rangeSelector', 'legend', 'resetZoomButton', 'tooltip', + 'renderer' + ].forEach(function (name) { + var prop = chart[name]; + if (prop && prop.destroy) { + chart[name] = prop.destroy(); + } + }); + // Remove container and all SVG, check container as it can break in IE + // when destroyed before finished loading + if (container) { + container.innerHTML = ''; + removeEvent(container); + if (parentNode) { + discardElement(container); + } + } + // clean it all up + objectEach(chart, function (val, key) { + delete chart[key]; + }); + }, + /** + * Prepare for first rendering after all data are loaded. + * + * @private + * @function Highcharts.Chart#firstRender + * @return {void} + * + * @fires Highcharts.Chart#event:beforeRender + */ + firstRender: function () { + var chart = this, options = chart.options; + // Hook for oldIE to check whether the chart is ready to render + if (chart.isReadyToRender && !chart.isReadyToRender()) { + return; + } + // Create the container + chart.getContainer(); + chart.resetMargins(); + chart.setChartSize(); + // Set the common chart properties (mainly invert) from the given series + chart.propFromSeries(); + // get axes + chart.getAxes(); + // Initialize the series + (isArray(options.series) ? options.series : []).forEach( + // #9680 + function (serieOptions) { + chart.initSeries(serieOptions); + }); + chart.linkSeries(); + chart.setSeriesData(); + // Run an event after axes and series are initialized, but before + // render. At this stage, the series data is indexed and cached in the + // xData and yData arrays, so we can access those before rendering. Used + // in Highstock. + fireEvent(chart, 'beforeRender'); + // depends on inverted and on margins being set + if (Pointer) { + if (!H.hasTouch && (win.PointerEvent || win.MSPointerEvent)) { + chart.pointer = new MSPointer(chart, options); + } + else { + /** + * The Pointer that keeps track of mouse and touch interaction. + * + * @memberof Highcharts.Chart + * @name pointer + * @type {Highcharts.Pointer} + * @instance + */ + chart.pointer = new Pointer(chart, options); + } + } + chart.render(); + // Fire the load event if there are no external images + if (!chart.renderer.imgCount && !chart.hasLoaded) { + chart.onload(); + } + // If the chart was rendered outside the top container, put it back in + // (#3679) + chart.temporaryDisplay(true); + }, + /** + * Internal function that runs on chart load, async if any images are loaded + * in the chart. Runs the callbacks and triggers the `load` and `render` + * events. + * + * @private + * @function Highcharts.Chart#onload + * @return {void} + * @fires Highcharts.Chart#event:load + * @fires Highcharts.Chart#event:render + */ + onload: function () { + // Run callbacks, first the ones registered by modules, then user's one + this.callbacks.concat([this.callback]).forEach(function (fn) { + // Chart destroyed in its own callback (#3600) + if (fn && typeof this.index !== 'undefined') { + fn.apply(this, [this]); + } + }, this); + fireEvent(this, 'load'); + fireEvent(this, 'render'); + // Set up auto resize, check for not destroyed (#6068) + if (defined(this.index)) { + this.setReflow(this.options.chart.reflow); + } + // Don't run again + this.hasLoaded = true; + } +}); // end Chart diff --git a/librerias/gantt/code/es-modules/parts/Color.js b/librerias/gantt/code/es-modules/parts/Color.js new file mode 100644 index 0000000..29114d8 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/Color.js @@ -0,0 +1,405 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +/** + * A valid color to be parsed and handled by Highcharts. Highcharts internally + * supports hex colors like `#ffffff`, rgb colors like `rgb(255,255,255)` and + * rgba colors like `rgba(255,255,255,1)`. Other colors may be supported by the + * browsers and displayed correctly, but Highcharts is not able to process them + * and apply concepts like opacity and brightening. + * + * @typedef {string} Highcharts.ColorString + */ +/** + * A valid color type than can be parsed and handled by Highcharts. It can be a + * color string, a gradient object, or a pattern object. + * + * @typedef {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} Highcharts.ColorType + */ +/** + * Gradient options instead of a solid color. + * + * @example + * // Linear gradient used as a color option + * color: { + * linearGradient: { x1: 0, x2: 0, y1: 0, y2: 1 }, + * stops: [ + * [0, '#003399'], // start + * [0.5, '#ffffff'], // middle + * [1, '#3366AA'] // end + * ] + * } + * + * @interface Highcharts.GradientColorObject + */ /** +* Holds an object that defines the start position and the end position relative +* to the shape. +* @name Highcharts.GradientColorObject#linearGradient +* @type {Highcharts.LinearGradientColorObject|undefined} +*/ /** +* Holds an object that defines the center position and the radius. +* @name Highcharts.GradientColorObject#radialGradient +* @type {Highcharts.RadialGradientColorObject|undefined} +*/ /** +* The first item in each tuple is the position in the gradient, where 0 is the +* start of the gradient and 1 is the end of the gradient. Multiple stops can be +* applied. The second item is the color for each stop. This color can also be +* given in the rgba format. +* @name Highcharts.GradientColorObject#stops +* @type {Array} +*/ +/** + * Color stop tuple. + * + * @see Highcharts.GradientColorObject + * + * @interface Highcharts.GradientColorStopObject + */ /** +* @name Highcharts.GradientColorStopObject#0 +* @type {number} +*/ /** +* @name Highcharts.GradientColorStopObject#1 +* @type {Highcharts.ColorString} +*/ /** +* @name Highcharts.GradoentColorStopObject#color +* @type {Highcharts.Color|undefined} +*/ +/** + * Defines the start position and the end position for a gradient relative + * to the shape. Start position (x1, y1) and end position (x2, y2) are relative + * to the shape, where 0 means top/left and 1 is bottom/right. + * + * @interface Highcharts.LinearGradientColorObject + */ /** +* Start horizontal position of the gradient. Float ranges 0-1. +* @name Highcharts.LinearGradientColorObject#x1 +* @type {number} +*/ /** +* End horizontal position of the gradient. Float ranges 0-1. +* @name Highcharts.LinearGradientColorObject#x2 +* @type {number} +*/ /** +* Start vertical position of the gradient. Float ranges 0-1. +* @name Highcharts.LinearGradientColorObject#y1 +* @type {number} +*/ /** +* End vertical position of the gradient. Float ranges 0-1. +* @name Highcharts.LinearGradientColorObject#y2 +* @type {number} +*/ +/** + * Defines the center position and the radius for a gradient. + * + * @interface Highcharts.RadialGradientColorObject + */ /** +* Center horizontal position relative to the shape. Float ranges 0-1. +* @name Highcharts.RadialGradientColorObject#cx +* @type {number} +*/ /** +* Center vertical position relative to the shape. Float ranges 0-1. +* @name Highcharts.RadialGradientColorObject#cy +* @type {number} +*/ /** +* Radius relative to the shape. Float ranges 0-1. +* @name Highcharts.RadialGradientColorObject#r +* @type {number} +*/ +import U from './Utilities.js'; +var isNumber = U.isNumber, merge = U.merge, pInt = U.pInt; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * Handle color operations. Some object methods are chainable. + * + * @class + * @name Highcharts.Color + * + * @param {Highcharts.ColorType} input + * The input color in either rbga or hex format + */ +var Color = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Color(input) { + // Collection of parsers. This can be extended from the outside by pushing + // parsers to Highcharts.Color.prototype.parsers. + this.parsers = [{ + // RGBA color + // eslint-disable-next-line max-len + regex: /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/, + parse: function (result) { + return [ + pInt(result[1]), + pInt(result[2]), + pInt(result[3]), + parseFloat(result[4], 10) + ]; + } + }, { + // RGB color + regex: /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/, + parse: function (result) { + return [pInt(result[1]), pInt(result[2]), pInt(result[3]), 1]; + } + }]; + this.rgba = []; + // Backwards compatibility, allow instanciation without new (#13053) + if (!(this instanceof Color)) { + return new Color(input); + } + this.init(input); + } + /* * + * + * Static Functions + * + * */ + /** + * Creates a color instance out of a color string or object. + * + * @function Highcharts.Color.parse + * + * @param {Highcharts.ColorType} input + * The input color in either rbga or hex format. + * + * @return {Highcharts.Color} + * Color instance. + */ + Color.parse = function (input) { + return new Color(input); + }; + /* * + * + * Functions + * + * */ + /** + * Parse the input color to rgba array + * + * @private + * @function Highcharts.Color#init + * + * @param {Highcharts.ColorType} input + * The input color in either rbga or hex format + * + * @return {void} + */ + Color.prototype.init = function (input) { + var result, rgba, i, parser, len; + this.input = input = Color.names[input && input.toLowerCase ? + input.toLowerCase() : + ''] || input; + // Gradients + if (input && input.stops) { + this.stops = input.stops.map(function (stop) { + return new Color(stop[1]); + }); + // Solid colors + } + else { + // Bitmasking as input[0] is not working for legacy IE. + if (input && + input.charAt && + input.charAt() === '#') { + len = input.length; + input = parseInt(input.substr(1), 16); + // Handle long-form, e.g. #AABBCC + if (len === 7) { + rgba = [ + (input & 0xFF0000) >> 16, + (input & 0xFF00) >> 8, + (input & 0xFF), + 1 + ]; + // Handle short-form, e.g. #ABC + // In short form, the value is assumed to be the same + // for both nibbles for each component. e.g. #ABC = #AABBCC + } + else if (len === 4) { + rgba = [ + (((input & 0xF00) >> 4) | + (input & 0xF00) >> 8), + (((input & 0xF0) >> 4) | + (input & 0xF0)), + ((input & 0xF) << 4) | (input & 0xF), + 1 + ]; + } + } + // Otherwise, check regex parsers + if (!rgba) { + i = this.parsers.length; + while (i-- && !rgba) { + parser = this.parsers[i]; + result = parser.regex.exec(input); + if (result) { + rgba = parser.parse(result); + } + } + } + } + this.rgba = rgba || []; + }; + /** + * Return the color or gradient stops in the specified format + * + * @function Highcharts.Color#get + * + * @param {string} [format] + * Possible values are 'a', 'rgb', 'rgba' (default). + * + * @return {Highcharts.ColorType} + * This color as a string or gradient stops. + */ + Color.prototype.get = function (format) { + var input = this.input, rgba = this.rgba, ret; + if (typeof this.stops !== 'undefined') { + ret = merge(input); + ret.stops = [].concat(ret.stops); + this.stops.forEach(function (stop, i) { + ret.stops[i] = [ + ret.stops[i][0], + stop.get(format) + ]; + }); + // it's NaN if gradient colors on a column chart + } + else if (rgba && isNumber(rgba[0])) { + if (format === 'rgb' || (!format && rgba[3] === 1)) { + ret = 'rgb(' + rgba[0] + ',' + rgba[1] + ',' + rgba[2] + ')'; + } + else if (format === 'a') { + ret = rgba[3]; + } + else { + ret = 'rgba(' + rgba.join(',') + ')'; + } + } + else { + ret = input; + } + return ret; + }; + /** + * Brighten the color instance. + * + * @function Highcharts.Color#brighten + * + * @param {number} alpha + * The alpha value. + * + * @return {Highcharts.Color} + * This color with modifications. + */ + Color.prototype.brighten = function (alpha) { + var i, rgba = this.rgba; + if (this.stops) { + this.stops.forEach(function (stop) { + stop.brighten(alpha); + }); + } + else if (isNumber(alpha) && alpha !== 0) { + for (i = 0; i < 3; i++) { + rgba[i] += pInt(alpha * 255); + if (rgba[i] < 0) { + rgba[i] = 0; + } + if (rgba[i] > 255) { + rgba[i] = 255; + } + } + } + return this; + }; + /** + * Set the color's opacity to a given alpha value. + * + * @function Highcharts.Color#setOpacity + * + * @param {number} alpha + * Opacity between 0 and 1. + * + * @return {Highcharts.Color} + * Color with modifications. + */ + Color.prototype.setOpacity = function (alpha) { + this.rgba[3] = alpha; + return this; + }; + /** + * Return an intermediate color between two colors. + * + * @function Highcharts.Color#tweenTo + * + * @param {Highcharts.Color} to + * The color object to tween to. + * + * @param {number} pos + * The intermediate position, where 0 is the from color (current + * color item), and 1 is the `to` color. + * + * @return {Highcharts.ColorString} + * The intermediate color in rgba notation. + */ + Color.prototype.tweenTo = function (to, pos) { + // Check for has alpha, because rgba colors perform worse due to lack of + // support in WebKit. + var fromRgba = this.rgba, toRgba = to.rgba, hasAlpha, ret; + // Unsupported color, return to-color (#3920, #7034) + if (!toRgba.length || !fromRgba || !fromRgba.length) { + ret = to.input || 'none'; + // Interpolate + } + else { + hasAlpha = (toRgba[3] !== 1 || fromRgba[3] !== 1); + ret = (hasAlpha ? 'rgba(' : 'rgb(') + + Math.round(toRgba[0] + (fromRgba[0] - toRgba[0]) * (1 - pos)) + + ',' + + Math.round(toRgba[1] + (fromRgba[1] - toRgba[1]) * (1 - pos)) + + ',' + + Math.round(toRgba[2] + (fromRgba[2] - toRgba[2]) * (1 - pos)) + + (hasAlpha ? + (',' + + (toRgba[3] + (fromRgba[3] - toRgba[3]) * (1 - pos))) : + '') + + ')'; + } + return ret; + }; + /* * + * + * Static Properties + * + * */ + // Collection of named colors. Can be extended from the outside by adding + // colors to Highcharts.Color.names. + Color.names = { + white: '#ffffff', + black: '#000000' + }; + return Color; +}()); +H.Color = Color; +/** + * Creates a color instance out of a color string. + * + * @function Highcharts.color + * + * @param {Highcharts.ColorType} input + * The input color in either rbga or hex format + * + * @return {Highcharts.Color} + * Color instance + */ +H.color = Color.parse; +export default H.Color; diff --git a/librerias/gantt/code/es-modules/parts/ColumnSeries.js b/librerias/gantt/code/es-modules/parts/ColumnSeries.js new file mode 100644 index 0000000..a36d0f4 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/ColumnSeries.js @@ -0,0 +1,969 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +/** + * Adjusted width and x offset of the columns for grouping. + * + * @private + * @interface Highcharts.ColumnMetricsObject + */ /** +* Width of the columns. +* @name Highcharts.ColumnMetricsObject#width +* @type {number} +*/ /** +* Offset of the columns. +* @name Highcharts.ColumnMetricsObject#offset +* @type {number} +*/ +''; // detach doclets above +import Color from './Color.js'; +var color = Color.parse; +import LegendSymbolMixin from '../mixins/legend-symbol.js'; +import U from './Utilities.js'; +var animObject = U.animObject, clamp = U.clamp, defined = U.defined, extend = U.extend, isNumber = U.isNumber, merge = U.merge, pick = U.pick, seriesType = U.seriesType; +import './Series.js'; +import './Options.js'; +var noop = H.noop, Series = H.Series, svg = H.svg; +/** + * The column series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.column + * + * @augments Highcharts.Series + */ +seriesType('column', 'line', +/** + * Column series display one column per value along an X axis. + * + * @sample {highcharts} highcharts/demo/column-basic/ + * Column chart + * @sample {highstock} stock/demo/column/ + * Column chart + * + * @extends plotOptions.line + * @excluding connectEnds, connectNulls, gapSize, gapUnit, linecap, + * lineWidth, marker, step, useOhlcData + * @product highcharts highstock + * @optionparent plotOptions.column + */ +{ + /** + * The corner radius of the border surrounding each column or bar. + * + * @sample {highcharts} highcharts/plotoptions/column-borderradius/ + * Rounded columns + * + * @product highcharts highstock gantt + * + * @private + */ + borderRadius: 0, + /** + * When using automatic point colors pulled from the global + * [colors](colors) or series-specific + * [plotOptions.column.colors](series.colors) collections, this option + * determines whether the chart should receive one color per series or + * one color per point. + * + * In styled mode, the `colors` or `series.colors` arrays are not + * supported, and instead this option gives the points individual color + * class names on the form `highcharts-color-{n}`. + * + * @see [series colors](#plotOptions.column.colors) + * + * @sample {highcharts} highcharts/plotoptions/column-colorbypoint-false/ + * False by default + * @sample {highcharts} highcharts/plotoptions/column-colorbypoint-true/ + * True + * + * @type {boolean} + * @default false + * @since 2.0 + * @product highcharts highstock gantt + * @apioption plotOptions.column.colorByPoint + */ + /** + * A series specific or series type specific color set to apply instead + * of the global [colors](#colors) when [colorByPoint]( + * #plotOptions.column.colorByPoint) is true. + * + * @type {Array} + * @since 3.0 + * @product highcharts highstock gantt + * @apioption plotOptions.column.colors + */ + /** + * Padding between each value groups, in x axis units. + * + * @sample {highcharts} highcharts/plotoptions/column-grouppadding-default/ + * 0.2 by default + * @sample {highcharts} highcharts/plotoptions/column-grouppadding-none/ + * No group padding - all columns are evenly spaced + * + * @product highcharts highstock gantt + * + * @private + */ + groupPadding: 0.2, + /** + * Whether to group non-stacked columns or to let them render + * independent of each other. Non-grouped columns will be laid out + * individually and overlap each other. + * + * @sample {highcharts} highcharts/plotoptions/column-grouping-false/ + * Grouping disabled + * @sample {highstock} highcharts/plotoptions/column-grouping-false/ + * Grouping disabled + * + * @type {boolean} + * @default true + * @since 2.3.0 + * @product highcharts highstock gantt + * @apioption plotOptions.column.grouping + */ + /** + * @ignore-option + * @private + */ + marker: null, + /** + * The maximum allowed pixel width for a column, translated to the + * height of a bar in a bar chart. This prevents the columns from + * becoming too wide when there is a small number of points in the + * chart. + * + * @see [pointWidth](#plotOptions.column.pointWidth) + * + * @sample {highcharts} highcharts/plotoptions/column-maxpointwidth-20/ + * Limited to 50 + * @sample {highstock} highcharts/plotoptions/column-maxpointwidth-20/ + * Limited to 50 + * + * @type {number} + * @since 4.1.8 + * @product highcharts highstock gantt + * @apioption plotOptions.column.maxPointWidth + */ + /** + * Padding between each column or bar, in x axis units. + * + * @sample {highcharts} highcharts/plotoptions/column-pointpadding-default/ + * 0.1 by default + * @sample {highcharts} highcharts/plotoptions/column-pointpadding-025/ + * 0.25 + * @sample {highcharts} highcharts/plotoptions/column-pointpadding-none/ + * 0 for tightly packed columns + * + * @product highcharts highstock gantt + * + * @private + */ + pointPadding: 0.1, + /** + * A pixel value specifying a fixed width for each column or bar. When + * `null`, the width is calculated from the `pointPadding` and + * `groupPadding`. + * + * @see [maxPointWidth](#plotOptions.column.maxPointWidth) + * + * @sample {highcharts} highcharts/plotoptions/column-pointwidth-20/ + * 20px wide columns regardless of chart width or the amount of + * data points + * + * @type {number} + * @since 1.2.5 + * @product highcharts highstock gantt + * @apioption plotOptions.column.pointWidth + */ + /** + * A pixel value specifying a fixed width for the column or bar. + * Overrides pointWidth on the series. + * + * @see [series.pointWidth](#plotOptions.column.pointWidth) + * + * @type {number} + * @default undefined + * @since 7.0.0 + * @product highcharts highstock gantt + * @apioption series.column.data.pointWidth + */ + /** + * The minimal height for a column or width for a bar. By default, + * 0 values are not shown. To visualize a 0 (or close to zero) point, + * set the minimal point length to a pixel value like 3\. In stacked + * column charts, minPointLength might not be respected for tightly + * packed values. + * + * @sample {highcharts} highcharts/plotoptions/column-minpointlength/ + * Zero base value + * @sample {highcharts} highcharts/plotoptions/column-minpointlength-pos-and-neg/ + * Positive and negative close to zero values + * + * @product highcharts highstock gantt + * + * @private + */ + minPointLength: 0, + /** + * When the series contains less points than the crop threshold, all + * points are drawn, event if the points fall outside the visible plot + * area at the current zoom. The advantage of drawing all points + * (including markers and columns), is that animation is performed on + * updates. On the other hand, when the series contains more points than + * the crop threshold, the series data is cropped to only contain points + * that fall within the plot area. The advantage of cropping away + * invisible points is to increase performance on large series. + * + * @product highcharts highstock gantt + * + * @private + */ + cropThreshold: 50, + /** + * The X axis range that each point is valid for. This determines the + * width of the column. On a categorized axis, the range will be 1 + * by default (one category unit). On linear and datetime axes, the + * range will be computed as the distance between the two closest data + * points. + * + * The default `null` means it is computed automatically, but this + * option can be used to override the automatic value. + * + * This option is set by default to 1 if data sorting is enabled. + * + * @sample {highcharts} highcharts/plotoptions/column-pointrange/ + * Set the point range to one day on a data set with one week + * between the points + * + * @type {number|null} + * @since 2.3 + * @product highcharts highstock gantt + * + * @private + */ + pointRange: null, + states: { + /** + * Options for the hovered point. These settings override the normal + * state options when a point is moused over or touched. + * + * @extends plotOptions.series.states.hover + * @excluding halo, lineWidth, lineWidthPlus, marker + * @product highcharts highstock gantt + */ + hover: { + /** @ignore-option */ + halo: false, + /** + * A specific border color for the hovered point. Defaults to + * inherit the normal state border color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts gantt + * @apioption plotOptions.column.states.hover.borderColor + */ + /** + * A specific color for the hovered point. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts gantt + * @apioption plotOptions.column.states.hover.color + */ + /** + * How much to brighten the point on interaction. Requires the + * main color to be defined in hex or rgb(a) format. + * + * In styled mode, the hover brightening is by default replaced + * with a fill-opacity set in the `.highcharts-point:hover` + * rule. + * + * @sample {highcharts} highcharts/plotoptions/column-states-hover-brightness/ + * Brighten by 0.5 + * + * @product highcharts highstock gantt + */ + brightness: 0.1 + }, + /** + * Options for the selected point. These settings override the + * normal state options when a point is selected. + * + * @extends plotOptions.series.states.select + * @excluding halo, lineWidth, lineWidthPlus, marker + * @product highcharts highstock gantt + */ + select: { + /** + * A specific color for the selected point. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #cccccc + * @product highcharts highstock gantt + */ + color: '#cccccc', + /** + * A specific border color for the selected point. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #000000 + * @product highcharts highstock gantt + */ + borderColor: '#000000' + } + }, + dataLabels: { + align: null, + verticalAlign: null, + y: null + }, + /** + * When this is true, the series will not cause the Y axis to cross + * the zero plane (or [threshold](#plotOptions.series.threshold) option) + * unless the data actually crosses the plane. + * + * For example, if `softThreshold` is `false`, a series of 0, 1, 2, + * 3 will make the Y axis show negative values according to the + * `minPadding` option. If `softThreshold` is `true`, the Y axis starts + * at 0. + * + * @since 4.1.9 + * @product highcharts highstock + * + * @private + */ + softThreshold: false, + // false doesn't work well: https://jsfiddle.net/highcharts/hz8fopan/14/ + /** + * @ignore-option + * @private + */ + startFromThreshold: true, + stickyTracking: false, + tooltip: { + distance: 6 + }, + /** + * The Y axis value to serve as the base for the columns, for + * distinguishing between values above and below a threshold. If `null`, + * the columns extend from the padding Y axis minimum. + * + * @type {number|null} + * @since 2.0 + * @product highcharts + * + * @private + */ + threshold: 0, + /** + * The width of the border surrounding each column or bar. Defaults to + * `1` when there is room for a border, but to `0` when the columns are + * so dense that a border would cover the next column. + * + * In styled mode, the stroke width can be set with the + * `.highcharts-point` rule. + * + * @sample {highcharts} highcharts/plotoptions/column-borderwidth/ + * 2px black border + * + * @type {number} + * @default undefined + * @product highcharts highstock gantt + * @apioption plotOptions.column.borderWidth + */ + /** + * The color of the border surrounding each column or bar. + * + * In styled mode, the border stroke can be set with the + * `.highcharts-point` rule. + * + * @sample {highcharts} highcharts/plotoptions/column-bordercolor/ + * Dark gray border + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #ffffff + * @product highcharts highstock gantt + * + * @private + */ + borderColor: '#ffffff' +}, +/** + * @lends seriesTypes.column.prototype + */ +{ + cropShoulder: 0, + // When tooltip is not shared, this series (and derivatives) requires + // direct touch/hover. KD-tree does not apply. + directTouch: true, + trackerGroups: ['group', 'dataLabelsGroup'], + // use separate negative stacks, unlike area stacks where a negative + // point is substracted from previous (#1910) + negStacks: true, + /* eslint-disable valid-jsdoc */ + /** + * Initialize the series. Extends the basic Series.init method by + * marking other series of the same type as dirty. + * + * @private + * @function Highcharts.seriesTypes.column#init + * @return {void} + */ + init: function () { + Series.prototype.init.apply(this, arguments); + var series = this, chart = series.chart; + // if the series is added dynamically, force redraw of other + // series affected by a new column + if (chart.hasRendered) { + chart.series.forEach(function (otherSeries) { + if (otherSeries.type === series.type) { + otherSeries.isDirty = true; + } + }); + } + }, + /** + * Return the width and x offset of the columns adjusted for grouping, + * groupPadding, pointPadding, pointWidth etc. + * + * @private + * @function Highcharts.seriesTypes.column#getColumnMetrics + * @return {Highcharts.ColumnMetricsObject} + */ + getColumnMetrics: function () { + var series = this, options = series.options, xAxis = series.xAxis, yAxis = series.yAxis, reversedStacks = xAxis.options.reversedStacks, + // Keep backward compatibility: reversed xAxis had reversed + // stacks + reverseStacks = (xAxis.reversed && !reversedStacks) || + (!xAxis.reversed && reversedStacks), stackKey, stackGroups = {}, columnCount = 0; + // Get the total number of column type series. This is called on + // every series. Consider moving this logic to a chart.orderStacks() + // function and call it on init, addSeries and removeSeries + if (options.grouping === false) { + columnCount = 1; + } + else { + series.chart.series.forEach(function (otherSeries) { + var otherYAxis = otherSeries.yAxis, otherOptions = otherSeries.options, columnIndex; + if (otherSeries.type === series.type && + (otherSeries.visible || + !series.chart.options.chart + .ignoreHiddenSeries) && + yAxis.len === otherYAxis.len && + yAxis.pos === otherYAxis.pos) { // #642, #2086 + if (otherOptions.stacking) { + stackKey = otherSeries.stackKey; + if (typeof stackGroups[stackKey] === + 'undefined') { + stackGroups[stackKey] = columnCount++; + } + columnIndex = stackGroups[stackKey]; + } + else if (otherOptions.grouping !== false) { // #1162 + columnIndex = columnCount++; + } + otherSeries.columnIndex = columnIndex; + } + }); + } + var categoryWidth = Math.min(Math.abs(xAxis.transA) * ((xAxis.ordinal && xAxis.ordinal.slope) || + options.pointRange || + xAxis.closestPointRange || + xAxis.tickInterval || + 1), // #2610 + xAxis.len // #1535 + ), groupPadding = categoryWidth * options.groupPadding, groupWidth = categoryWidth - 2 * groupPadding, pointOffsetWidth = groupWidth / (columnCount || 1), pointWidth = Math.min(options.maxPointWidth || xAxis.len, pick(options.pointWidth, pointOffsetWidth * (1 - 2 * options.pointPadding))), pointPadding = (pointOffsetWidth - pointWidth) / 2, + // #1251, #3737 + colIndex = (series.columnIndex || 0) + (reverseStacks ? 1 : 0), pointXOffset = pointPadding + + (groupPadding + + colIndex * pointOffsetWidth - + (categoryWidth / 2)) * (reverseStacks ? -1 : 1); + // Save it for reading in linked series (Error bars particularly) + series.columnMetrics = { + width: pointWidth, + offset: pointXOffset + }; + return series.columnMetrics; + }, + /** + * Make the columns crisp. The edges are rounded to the nearest full + * pixel. + * + * @private + * @function Highcharts.seriesTypes.column#crispCol + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @return {Highcharts.BBoxObject} + */ + crispCol: function (x, y, w, h) { + var chart = this.chart, borderWidth = this.borderWidth, xCrisp = -(borderWidth % 2 ? 0.5 : 0), yCrisp = borderWidth % 2 ? 0.5 : 1, right, bottom, fromTop; + if (chart.inverted && chart.renderer.isVML) { + yCrisp += 1; + } + // Horizontal. We need to first compute the exact right edge, then + // round it and compute the width from there. + if (this.options.crisp) { + right = Math.round(x + w) + xCrisp; + x = Math.round(x) + xCrisp; + w = right - x; + } + // Vertical + bottom = Math.round(y + h) + yCrisp; + fromTop = Math.abs(y) <= 0.5 && bottom > 0.5; // #4504, #4656 + y = Math.round(y) + yCrisp; + h = bottom - y; + // Top edges are exceptions + if (fromTop && h) { // #5146 + y -= 1; + h += 1; + } + return { + x: x, + y: y, + width: w, + height: h + }; + }, + /** + * Translate each point to the plot area coordinate system and find + * shape positions + * + * @private + * @function Highcharts.seriesTypes.column#translate + */ + translate: function () { + var series = this, chart = series.chart, options = series.options, dense = series.dense = + series.closestPointRange * series.xAxis.transA < 2, borderWidth = series.borderWidth = pick(options.borderWidth, dense ? 0 : 1 // #3635 + ), xAxis = series.xAxis, yAxis = series.yAxis, threshold = options.threshold, translatedThreshold = series.translatedThreshold = + yAxis.getThreshold(threshold), minPointLength = pick(options.minPointLength, 5), metrics = series.getColumnMetrics(), seriesPointWidth = metrics.width, + // postprocessed for border width + seriesBarW = series.barW = + Math.max(seriesPointWidth, 1 + 2 * borderWidth), seriesXOffset = series.pointXOffset = metrics.offset, dataMin = series.dataMin, dataMax = series.dataMax; + if (chart.inverted) { + translatedThreshold -= 0.5; // #3355 + } + // When the pointPadding is 0, we want the columns to be packed + // tightly, so we allow individual columns to have individual sizes. + // When pointPadding is greater, we strive for equal-width columns + // (#2694). + if (options.pointPadding) { + seriesBarW = Math.ceil(seriesBarW); + } + Series.prototype.translate.apply(series); + // Record the new values + series.points.forEach(function (point) { + var yBottom = pick(point.yBottom, translatedThreshold), safeDistance = 999 + Math.abs(yBottom), pointWidth = seriesPointWidth, plotX = point.plotX, + // Don't draw too far outside plot area (#1303, #2241, + // #4264) + plotY = clamp(point.plotY, -safeDistance, yAxis.len + safeDistance), barX = point.plotX + seriesXOffset, barW = seriesBarW, barY = Math.min(plotY, yBottom), up, barH = Math.max(plotY, yBottom) - barY; + // Handle options.minPointLength + if (minPointLength && Math.abs(barH) < minPointLength) { + barH = minPointLength; + up = (!yAxis.reversed && !point.negative) || + (yAxis.reversed && point.negative); + // Reverse zeros if there's no positive value in the series + // in visible range (#7046) + if (isNumber(threshold) && + isNumber(dataMax) && + point.y === threshold && + dataMax <= threshold && + // and if there's room for it (#7311) + (yAxis.min || 0) < threshold && + // if all points are the same value (i.e zero) not draw + // as negative points (#10646) + dataMin !== dataMax) { + up = !up; + } + // If stacked... + barY = (Math.abs(barY - translatedThreshold) > minPointLength ? + // ...keep position + yBottom - minPointLength : + // #1485, #4051 + translatedThreshold - + (up ? minPointLength : 0)); + } + // Handle point.options.pointWidth + // @todo Handle grouping/stacking too. Calculate offset properly + if (defined(point.options.pointWidth)) { + pointWidth = barW = + Math.ceil(point.options.pointWidth); + barX -= Math.round((pointWidth - seriesPointWidth) / 2); + } + // Cache for access in polar + point.barX = barX; + point.pointWidth = pointWidth; + // Fix the tooltip on center of grouped columns (#1216, #424, + // #3648) + point.tooltipPos = chart.inverted ? + [ + yAxis.len + yAxis.pos - chart.plotLeft - plotY, + xAxis.len + xAxis.pos - chart.plotTop - (plotX || 0) - seriesXOffset - barW / 2, + barH + ] : + [barX + barW / 2, plotY + yAxis.pos - + chart.plotTop, barH]; + // Register shape type and arguments to be used in drawPoints + // Allow shapeType defined on pointClass level + point.shapeType = + series.pointClass.prototype.shapeType || 'rect'; + point.shapeArgs = series.crispCol.apply(series, point.isNull ? + // #3169, drilldown from null must have a position to work + // from #6585, dataLabel should be placed on xAxis, not + // floating in the middle of the chart + [barX, translatedThreshold, barW, 0] : + [barX, barY, barW, barH]); + }); + }, + getSymbol: noop, + /** + * Use a solid rectangle like the area series types + * + * @private + * @function Highcharts.seriesTypes.column#drawLegendSymbol + * + * @param {Highcharts.Legend} legend + * The legend object + * + * @param {Highcharts.Series|Highcharts.Point} item + * The series (this) or point + */ + drawLegendSymbol: LegendSymbolMixin.drawRectangle, + /** + * Columns have no graph + * + * @private + * @function Highcharts.seriesTypes.column#drawGraph + */ + drawGraph: function () { + this.group[this.dense ? 'addClass' : 'removeClass']('highcharts-dense-data'); + }, + /** + * Get presentational attributes + * + * @private + * @function Highcharts.seriesTypes.column#pointAttribs + * + * @param {Highcharts.ColumnPoint} point + * + * @param {string} state + * + * @return {Highcharts.SVGAttributes} + */ + pointAttribs: function (point, state) { + var options = this.options, stateOptions, ret, p2o = this.pointAttrToOptions || {}, strokeOption = p2o.stroke || 'borderColor', strokeWidthOption = p2o['stroke-width'] || 'borderWidth', fill = (point && point.color) || this.color, + // set to fill when borderColor null: + stroke = ((point && point[strokeOption]) || + options[strokeOption] || + this.color || + fill), strokeWidth = (point && point[strokeWidthOption]) || + options[strokeWidthOption] || + this[strokeWidthOption] || 0, dashstyle = (point && point.options.dashStyle) || options.dashStyle, opacity = pick(point && point.opacity, options.opacity, 1), zone, brightness; + // Handle zone colors + if (point && this.zones.length) { + zone = point.getZone(); + // When zones are present, don't use point.color (#4267). + // Changed order (#6527), added support for colorAxis (#10670) + fill = (point.options.color || + (zone && (zone.color || point.nonZonedColor)) || + this.color); + if (zone) { + stroke = zone.borderColor || stroke; + dashstyle = zone.dashStyle || dashstyle; + strokeWidth = zone.borderWidth || strokeWidth; + } + } + // Select or hover states + if (state && point) { + stateOptions = merge(options.states[state], + // #6401 + point.options.states && + point.options.states[state] || + {}); + brightness = stateOptions.brightness; + fill = + stateOptions.color || (typeof brightness !== 'undefined' && + color(fill) + .brighten(stateOptions.brightness) + .get()) || fill; + stroke = stateOptions[strokeOption] || stroke; + strokeWidth = + stateOptions[strokeWidthOption] || strokeWidth; + dashstyle = stateOptions.dashStyle || dashstyle; + opacity = pick(stateOptions.opacity, opacity); + } + ret = { + fill: fill, + stroke: stroke, + 'stroke-width': strokeWidth, + opacity: opacity + }; + if (dashstyle) { + ret.dashstyle = dashstyle; + } + return ret; + }, + /** + * Draw the columns. For bars, the series.group is rotated, so the same + * coordinates apply for columns and bars. This method is inherited by + * scatter series. + * + * @private + * @function Highcharts.seriesTypes.column#drawPoints + */ + drawPoints: function () { + var series = this, chart = this.chart, options = series.options, renderer = chart.renderer, animationLimit = options.animationLimit || 250, shapeArgs; + // draw the columns + series.points.forEach(function (point) { + var plotY = point.plotY, graphic = point.graphic, hasGraphic = !!graphic, verb = graphic && chart.pointCount < animationLimit ? + 'animate' : 'attr'; + if (isNumber(plotY) && point.y !== null) { + shapeArgs = point.shapeArgs; + // When updating a series between 2d and 3d or cartesian and + // polar, the shape type changes. + if (graphic && point.hasNewShapeType()) { + graphic = graphic.destroy(); + } + // Set starting position for point sliding animation. + if (series.enabledDataSorting) { + point.startXPos = series.xAxis.reversed ? + -(shapeArgs ? shapeArgs.width : 0) : + series.xAxis.width; + } + if (!graphic) { + point.graphic = graphic = + renderer[point.shapeType](shapeArgs) + .add(point.group || series.group); + if (graphic && + series.enabledDataSorting && + chart.hasRendered && + chart.pointCount < animationLimit) { + graphic.attr({ + x: point.startXPos + }); + hasGraphic = true; + verb = 'animate'; + } + } + if (graphic && hasGraphic) { // update + graphic[verb](merge(shapeArgs)); + } + // Border radius is not stylable (#6900) + if (options.borderRadius) { + graphic[verb]({ + r: options.borderRadius + }); + } + // Presentational + if (!chart.styledMode) { + graphic[verb](series.pointAttribs(point, (point.selected && 'select'))) + .shadow(point.allowShadow !== false && options.shadow, null, options.stacking && !options.borderRadius); + } + graphic.addClass(point.getClassName(), true); + } + else if (graphic) { + point.graphic = graphic.destroy(); // #1269 + } + }); + }, + /** + * Animate the column heights one by one from zero. + * + * @private + * @function Highcharts.seriesTypes.column#animate + * + * @param {boolean} init + * Whether to initialize the animation or run it + */ + animate: function (init) { + var series = this, yAxis = this.yAxis, options = series.options, inverted = this.chart.inverted, attr = {}, translateProp = inverted ? 'translateX' : 'translateY', translateStart, translatedThreshold; + if (init) { + attr.scaleY = 0.001; + translatedThreshold = clamp(yAxis.toPixels(options.threshold), yAxis.pos, yAxis.pos + yAxis.len); + if (inverted) { + attr.translateX = translatedThreshold - yAxis.len; + } + else { + attr.translateY = translatedThreshold; + } + // apply finnal clipping (used in Highstock) (#7083) + // animation is done by scaleY, so cliping is for panes + if (series.clipBox) { + series.setClip(); + } + series.group.attr(attr); + } + else { // run the animation + translateStart = series.group.attr(translateProp); + series.group.animate({ scaleY: 1 }, extend(animObject(series.options.animation), { + // Do the scale synchronously to ensure smooth + // updating (#5030, #7228) + step: function (val, fx) { + if (series.group) { + attr[translateProp] = translateStart + + fx.pos * (yAxis.pos - translateStart); + series.group.attr(attr); + } + } + })); + } + }, + /** + * Remove this series from the chart + * + * @private + * @function Highcharts.seriesTypes.column#remove + */ + remove: function () { + var series = this, chart = series.chart; + // column and bar series affects other series of the same type + // as they are either stacked or grouped + if (chart.hasRendered) { + chart.series.forEach(function (otherSeries) { + if (otherSeries.type === series.type) { + otherSeries.isDirty = true; + } + }); + } + Series.prototype.remove.apply(series, arguments); + } +}); +/* eslint-enable valid-jsdoc */ +/** + * A `column` series. If the [type](#series.column.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.column + * @excluding connectNulls, dataParser, dataURL, gapSize, gapUnit, linecap, + * lineWidth, marker, connectEnds, step + * @product highcharts highstock + * @apioption series.column + */ +/** + * An array of data points for the series. For the `column` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 6], + * [1, 2], + * [2, 6] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.column.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @excluding marker + * @product highcharts highstock + * @apioption series.column.data + */ +/** + * The color of the border surrounding the column or bar. + * + * In styled mode, the border stroke can be set with the `.highcharts-point` + * rule. + * + * @sample {highcharts} highcharts/plotoptions/column-bordercolor/ + * Dark gray border + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock + * @apioption series.column.data.borderColor + */ +/** + * The width of the border surrounding the column or bar. + * + * In styled mode, the stroke width can be set with the `.highcharts-point` + * rule. + * + * @sample {highcharts} highcharts/plotoptions/column-borderwidth/ + * 2px black border + * + * @type {number} + * @product highcharts highstock + * @apioption series.column.data.borderWidth + */ +/** + * A name for the dash style to use for the column or bar. Overrides + * dashStyle on the series. + * + * In styled mode, the stroke dash-array can be set with the same classes as + * listed under [data.color](#series.column.data.color). + * + * @see [series.pointWidth](#plotOptions.column.dashStyle) + * + * @type {Highcharts.DashStyleValue} + * @apioption series.column.data.dashStyle + */ +/** + * A pixel value specifying a fixed width for the column or bar. Overrides + * pointWidth on the series. + * + * @see [series.pointWidth](#plotOptions.column.pointWidth) + * + * @type {number} + * @apioption series.column.data.pointWidth + */ +/** + * @excluding halo, lineWidth, lineWidthPlus, marker + * @product highcharts highstock + * @apioption series.column.states.hover + */ +/** + * @excluding halo, lineWidth, lineWidthPlus, marker + * @product highcharts highstock + * @apioption series.column.states.select + */ +''; // includes above doclets in transpilat diff --git a/librerias/gantt/code/es-modules/parts/DataGrouping.js b/librerias/gantt/code/es-modules/parts/DataGrouping.js new file mode 100644 index 0000000..34afb7e --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/DataGrouping.js @@ -0,0 +1,894 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import DateTimeAxis from './DateTimeAxis.js'; +import H from './Globals.js'; +/** + * @typedef {"average"|"averages"|"open"|"high"|"low"|"close"|"sum"} Highcharts.DataGroupingApproximationValue + */ +/** + * @interface Highcharts.DataGroupingInfoObject + */ /** +* @name Highcharts.DataGroupingInfoObject#length +* @type {number} +*/ /** +* @name Highcharts.DataGroupingInfoObject#options +* @type {Highcharts.SeriesOptionsType|undefined} +*/ /** +* @name Highcharts.DataGroupingInfoObject#start +* @type {number} +*/ +''; // detach doclets above +import Point from './Point.js'; +import Tooltip from './Tooltip.js'; +import U from './Utilities.js'; +var addEvent = U.addEvent, arrayMax = U.arrayMax, arrayMin = U.arrayMin, correctFloat = U.correctFloat, defined = U.defined, error = U.error, extend = U.extend, format = U.format, isNumber = U.isNumber, merge = U.merge, pick = U.pick; +import './Axis.js'; +import './Series.js'; +var Axis = H.Axis, defaultPlotOptions = H.defaultPlotOptions, Series = H.Series; +/* ************************************************************************** * + * Start data grouping module * + * ************************************************************************** */ +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * Define the available approximation types. The data grouping + * approximations takes an array or numbers as the first parameter. In case + * of ohlc, four arrays are sent in as four parameters. Each array consists + * only of numbers. In case null values belong to the group, the property + * .hasNulls will be set to true on the array. + * + * @product highstock + * + * @private + * @name Highcharts.approximations + * @type {Highcharts.Dictionary} + */ +var approximations = H.approximations = { + sum: function (arr) { + var len = arr.length, ret; + // 1. it consists of nulls exclusive + if (!len && arr.hasNulls) { + ret = null; + // 2. it has a length and real values + } + else if (len) { + ret = 0; + while (len--) { + ret += arr[len]; + } + } + // 3. it has zero length, so just return undefined + // => doNothing() + return ret; + }, + average: function (arr) { + var len = arr.length, ret = approximations.sum(arr); + // If we have a number, return it divided by the length. If not, + // return null or undefined based on what the sum method finds. + if (isNumber(ret) && len) { + ret = correctFloat(ret / len); + } + return ret; + }, + // The same as average, but for series with multiple values, like area + // ranges. + averages: function () { + var ret = []; + [].forEach.call(arguments, function (arr) { + ret.push(approximations.average(arr)); + }); + // Return undefined when first elem. is undefined and let + // sum method handle null (#7377) + return typeof ret[0] === 'undefined' ? void 0 : ret; + }, + open: function (arr) { + return arr.length ? arr[0] : (arr.hasNulls ? null : void 0); + }, + high: function (arr) { + return arr.length ? + arrayMax(arr) : + (arr.hasNulls ? null : void 0); + }, + low: function (arr) { + return arr.length ? + arrayMin(arr) : + (arr.hasNulls ? null : void 0); + }, + close: function (arr) { + return arr.length ? + arr[arr.length - 1] : + (arr.hasNulls ? null : void 0); + }, + // ohlc and range are special cases where a multidimensional array is + // input and an array is output + ohlc: function (open, high, low, close) { + open = approximations.open(open); + high = approximations.high(high); + low = approximations.low(low); + close = approximations.close(close); + if (isNumber(open) || + isNumber(high) || + isNumber(low) || + isNumber(close)) { + return [open, high, low, close]; + } + // else, return is undefined + }, + range: function (low, high) { + low = approximations.low(low); + high = approximations.high(high); + if (isNumber(low) || isNumber(high)) { + return [low, high]; + } + if (low === null && high === null) { + return null; + } + // else, return is undefined + } +}; +var groupData = function (xData, yData, groupPositions, approximation) { + var series = this, data = series.data, dataOptions = series.options && series.options.data, groupedXData = [], groupedYData = [], groupMap = [], dataLength = xData.length, pointX, pointY, groupedY, + // when grouping the fake extended axis for panning, + // we don't need to consider y + handleYData = !!yData, values = [], approximationFn, pointArrayMap = series.pointArrayMap, pointArrayMapLength = pointArrayMap && pointArrayMap.length, extendedPointArrayMap = ['x'].concat(pointArrayMap || ['y']), pos = 0, start = 0, valuesLen, i, j; + /** + * @private + */ + function getApproximation(approx) { + if (typeof approx === 'function') { + return approx; + } + if (approximations[approx]) { + return approximations[approx]; + } + return approximations[(series.getDGApproximation && series.getDGApproximation()) || + 'average']; + } + approximationFn = getApproximation(approximation); + // Calculate values array size from pointArrayMap length + if (pointArrayMapLength) { + pointArrayMap.forEach(function () { + values.push([]); + }); + } + else { + values.push([]); + } + valuesLen = pointArrayMapLength || 1; + // Start with the first point within the X axis range (#2696) + for (i = 0; i <= dataLength; i++) { + if (xData[i] >= groupPositions[0]) { + break; + } + } + for (i; i <= dataLength; i++) { + // when a new group is entered, summarize and initialize + // the previous group + while ((typeof groupPositions[pos + 1] !== 'undefined' && + xData[i] >= groupPositions[pos + 1]) || + i === dataLength) { // get the last group + // get group x and y + pointX = groupPositions[pos]; + series.dataGroupInfo = { + start: series.cropStart + start, + length: values[0].length + }; + groupedY = approximationFn.apply(series, values); + // By default, let options of the first grouped point be passed over + // to the grouped point. This allows preserving properties like + // `name` and `color` or custom properties. Implementers can + // override this from the approximation function, where they can + // write custom options to `this.dataGroupInfo.options`. + if (series.pointClass && !defined(series.dataGroupInfo.options)) { + // Convert numbers and arrays into objects + series.dataGroupInfo.options = merge(series.pointClass.prototype + .optionsToObject.call({ series: series }, series.options.data[series.cropStart + start])); + // Make sure the raw data (x, y, open, high etc) is not copied + // over and overwriting approximated data. + extendedPointArrayMap.forEach(function (key) { + delete series.dataGroupInfo.options[key]; + }); + } + // push the grouped data + if (typeof groupedY !== 'undefined') { + groupedXData.push(pointX); + groupedYData.push(groupedY); + groupMap.push(series.dataGroupInfo); + } + // reset the aggregate arrays + start = i; + for (j = 0; j < valuesLen; j++) { + values[j].length = 0; // faster than values[j] = [] + values[j].hasNulls = false; + } + // Advance on the group positions + pos += 1; + // don't loop beyond the last group + if (i === dataLength) { + break; + } + } + // break out + if (i === dataLength) { + break; + } + // for each raw data point, push it to an array that contains all values + // for this specific group + if (pointArrayMap) { + var index = series.cropStart + i, point = (data && data[index]) || + series.pointClass.prototype.applyOptions.apply({ + series: series + }, [dataOptions[index]]), val; + for (j = 0; j < pointArrayMapLength; j++) { + val = point[pointArrayMap[j]]; + if (isNumber(val)) { + values[j].push(val); + } + else if (val === null) { + values[j].hasNulls = true; + } + } + } + else { + pointY = handleYData ? yData[i] : null; + if (isNumber(pointY)) { + values[0].push(pointY); + } + else if (pointY === null) { + values[0].hasNulls = true; + } + } + } + return { + groupedXData: groupedXData, + groupedYData: groupedYData, + groupMap: groupMap + }; +}; +var dataGrouping = { + approximations: approximations, + groupData: groupData +}; +// ----------------------------------------------------------------------------- +// The following code applies to implementation of data grouping on a Series +var seriesProto = Series.prototype, baseProcessData = seriesProto.processData, baseGeneratePoints = seriesProto.generatePoints, +/** @ignore */ +commonOptions = { + // enabled: null, // (true for stock charts, false for basic), + // forced: undefined, + groupPixelWidth: 2, + // the first one is the point or start value, the second is the start + // value if we're dealing with range, the third one is the end value if + // dealing with a range + dateTimeLabelFormats: { + millisecond: [ + '%A, %b %e, %H:%M:%S.%L', + '%A, %b %e, %H:%M:%S.%L', + '-%H:%M:%S.%L' + ], + second: [ + '%A, %b %e, %H:%M:%S', + '%A, %b %e, %H:%M:%S', + '-%H:%M:%S' + ], + minute: [ + '%A, %b %e, %H:%M', + '%A, %b %e, %H:%M', + '-%H:%M' + ], + hour: [ + '%A, %b %e, %H:%M', + '%A, %b %e, %H:%M', + '-%H:%M' + ], + day: [ + '%A, %b %e, %Y', + '%A, %b %e', + '-%A, %b %e, %Y' + ], + week: [ + 'Week from %A, %b %e, %Y', + '%A, %b %e', + '-%A, %b %e, %Y' + ], + month: [ + '%B %Y', + '%B', + '-%B %Y' + ], + year: [ + '%Y', + '%Y', + '-%Y' + ] + } + // smoothed = false, // enable this for navigator series only +}, specificOptions = { + line: {}, + spline: {}, + area: {}, + areaspline: {}, + arearange: {}, + column: { + groupPixelWidth: 10 + }, + columnrange: { + groupPixelWidth: 10 + }, + candlestick: { + groupPixelWidth: 10 + }, + ohlc: { + groupPixelWidth: 5 + } +}, +// units are defined in a separate array to allow complete overriding in +// case of a user option +defaultDataGroupingUnits = H.defaultDataGroupingUnits = [ + [ + 'millisecond', + [1, 2, 5, 10, 20, 25, 50, 100, 200, 500] // allowed multiples + ], [ + 'second', + [1, 2, 5, 10, 15, 30] + ], [ + 'minute', + [1, 2, 5, 10, 15, 30] + ], [ + 'hour', + [1, 2, 3, 4, 6, 8, 12] + ], [ + 'day', + [1] + ], [ + 'week', + [1] + ], [ + 'month', + [1, 3, 6] + ], [ + 'year', + null + ] +]; +// Set default approximations to the prototypes if present. Properties are +// inherited down. Can be overridden for individual series types. +seriesProto.getDGApproximation = function () { + if (this.is('arearange')) { + return 'range'; + } + if (this.is('ohlc')) { + return 'ohlc'; + } + if (this.is('column')) { + return 'sum'; + } + return 'average'; +}; +/** + * Takes parallel arrays of x and y data and groups the data into intervals + * defined by groupPositions, a collection of starting x values for each group. + * + * @private + * @function Highcharts.Series#groupData + * + * @param {Array} xData + * + * @param {Array|Array>} yData + * + * @param {boolean} groupPositions + * + * @param {string|Function} approximation + * + * @return {void} + */ +seriesProto.groupData = groupData; +// Extend the basic processData method, that crops the data to the current zoom +// range, with data grouping logic. +seriesProto.processData = function () { + var series = this, chart = series.chart, options = series.options, dataGroupingOptions = options.dataGrouping, groupingEnabled = series.allowDG !== false && dataGroupingOptions && + pick(dataGroupingOptions.enabled, chart.options.isStock), visible = (series.visible || !chart.options.chart.ignoreHiddenSeries), hasGroupedData, skip, lastDataGrouping = this.currentDataGrouping, currentDataGrouping, croppedData, revertRequireSorting = false; + // Run base method + series.forceCrop = groupingEnabled; // #334 + series.groupPixelWidth = null; // #2110 + series.hasProcessed = true; // #2692 + // Data needs to be sorted for dataGrouping + if (groupingEnabled && !series.requireSorting) { + series.requireSorting = revertRequireSorting = true; + } + // Skip if processData returns false or if grouping is disabled (in that + // order) + skip = (baseProcessData.apply(series, arguments) === false || + !groupingEnabled); + // Revert original requireSorting value if changed + if (revertRequireSorting) { + series.requireSorting = false; + } + if (!skip) { + series.destroyGroupedData(); + var i, processedXData = dataGroupingOptions.groupAll ? + series.xData : + series.processedXData, processedYData = dataGroupingOptions.groupAll ? + series.yData : + series.processedYData, plotSizeX = chart.plotSizeX, xAxis = series.xAxis, ordinal = xAxis.options.ordinal, groupPixelWidth = series.groupPixelWidth = + xAxis.getGroupPixelWidth && xAxis.getGroupPixelWidth(); + // Execute grouping if the amount of points is greater than the limit + // defined in groupPixelWidth + if (groupPixelWidth) { + hasGroupedData = true; + // Force recreation of point instances in series.translate, #5699 + series.isDirty = true; + series.points = null; // #6709 + var extremes = xAxis.getExtremes(), xMin = extremes.min, xMax = extremes.max, groupIntervalFactor = (ordinal && + xAxis.ordinal && + xAxis.ordinal.getGroupIntervalFactor(xMin, xMax, series)) || 1, interval = (groupPixelWidth * (xMax - xMin) / plotSizeX) * + groupIntervalFactor, groupPositions = xAxis.getTimeTicks(DateTimeAxis.AdditionsClass.prototype.normalizeTimeTickInterval(interval, dataGroupingOptions.units || + defaultDataGroupingUnits), + // Processed data may extend beyond axis (#4907) + Math.min(xMin, processedXData[0]), Math.max(xMax, processedXData[processedXData.length - 1]), xAxis.options.startOfWeek, processedXData, series.closestPointRange), groupedData = seriesProto.groupData.apply(series, [ + processedXData, + processedYData, + groupPositions, + dataGroupingOptions.approximation + ]), groupedXData = groupedData.groupedXData, groupedYData = groupedData.groupedYData, gapSize = 0; + // Prevent the smoothed data to spill out left and right, and make + // sure data is not shifted to the left + if (dataGroupingOptions.smoothed && groupedXData.length) { + i = groupedXData.length - 1; + groupedXData[i] = Math.min(groupedXData[i], xMax); + while (i-- && i > 0) { + groupedXData[i] += interval / 2; + } + groupedXData[0] = Math.max(groupedXData[0], xMin); + } + // Record what data grouping values were used + for (i = 1; i < groupPositions.length; i++) { + // The grouped gapSize needs to be the largest distance between + // the group to capture varying group sizes like months or DST + // crossing (#10000). Also check that the gap is not at the + // start of a segment. + if (!groupPositions.info.segmentStarts || + groupPositions.info.segmentStarts.indexOf(i) === -1) { + gapSize = Math.max(groupPositions[i] - groupPositions[i - 1], gapSize); + } + } + currentDataGrouping = groupPositions.info; + currentDataGrouping.gapSize = gapSize; + series.closestPointRange = groupPositions.info.totalRange; + series.groupMap = groupedData.groupMap; + // Make sure the X axis extends to show the first group (#2533) + // But only for visible series (#5493, #6393) + if (defined(groupedXData[0]) && + groupedXData[0] < xAxis.min && + visible) { + if ((!defined(xAxis.options.min) && + xAxis.min <= xAxis.dataMin) || + xAxis.min === xAxis.dataMin) { + xAxis.min = Math.min(groupedXData[0], xAxis.min); + } + xAxis.dataMin = Math.min(groupedXData[0], xAxis.dataMin); + } + // We calculated all group positions but we should render + // only the ones within the visible range + if (dataGroupingOptions.groupAll) { + croppedData = series.cropData(groupedXData, groupedYData, xAxis.min, xAxis.max, 1 // Ordinal xAxis will remove left-most points otherwise + ); + groupedXData = croppedData.xData; + groupedYData = croppedData.yData; + } + // Set series props + series.processedXData = groupedXData; + series.processedYData = groupedYData; + } + else { + series.groupMap = null; + } + series.hasGroupedData = hasGroupedData; + series.currentDataGrouping = currentDataGrouping; + series.preventGraphAnimation = + (lastDataGrouping && lastDataGrouping.totalRange) !== + (currentDataGrouping && currentDataGrouping.totalRange); + } +}; +// Destroy the grouped data points. #622, #740 +seriesProto.destroyGroupedData = function () { + // Clear previous groups + if (this.groupedData) { + this.groupedData.forEach(function (point, i) { + if (point) { + this.groupedData[i] = point.destroy ? + point.destroy() : null; + } + }, this); + // Clears all: + // - `this.groupedData` + // - `this.points` + // - `preserve` object in series.update() + this.groupedData.length = 0; + } +}; +// Override the generatePoints method by adding a reference to grouped data +seriesProto.generatePoints = function () { + baseGeneratePoints.apply(this); + // Record grouped data in order to let it be destroyed the next time + // processData runs + this.destroyGroupedData(); // #622 + this.groupedData = this.hasGroupedData ? this.points : null; +}; +// Override point prototype to throw a warning when trying to update grouped +// points. +addEvent(Point, 'update', function () { + if (this.dataGroup) { + error(24, false, this.series.chart); + return false; + } +}); +// Extend the original method, make the tooltip's header reflect the grouped +// range. +addEvent(Tooltip, 'headerFormatter', function (e) { + var tooltip = this, chart = this.chart, time = chart.time, labelConfig = e.labelConfig, series = labelConfig.series, options = series.options, tooltipOptions = series.tooltipOptions, dataGroupingOptions = options.dataGrouping, xDateFormat = tooltipOptions.xDateFormat, xDateFormatEnd, xAxis = series.xAxis, currentDataGrouping, dateTimeLabelFormats, labelFormats, formattedKey, formatString = tooltipOptions[(e.isFooter ? 'footer' : 'header') + 'Format']; + // apply only to grouped series + if (xAxis && + xAxis.options.type === 'datetime' && + dataGroupingOptions && + isNumber(labelConfig.key)) { + // set variables + currentDataGrouping = series.currentDataGrouping; + dateTimeLabelFormats = dataGroupingOptions.dateTimeLabelFormats || + // Fallback to commonOptions (#9693) + commonOptions.dateTimeLabelFormats; + // if we have grouped data, use the grouping information to get the + // right format + if (currentDataGrouping) { + labelFormats = + dateTimeLabelFormats[currentDataGrouping.unitName]; + if (currentDataGrouping.count === 1) { + xDateFormat = labelFormats[0]; + } + else { + xDateFormat = labelFormats[1]; + xDateFormatEnd = labelFormats[2]; + } + // if not grouped, and we don't have set the xDateFormat option, get the + // best fit, so if the least distance between points is one minute, show + // it, but if the least distance is one day, skip hours and minutes etc. + } + else if (!xDateFormat && dateTimeLabelFormats) { + xDateFormat = tooltip.getXDateFormat(labelConfig, tooltipOptions, xAxis); + } + // now format the key + formattedKey = time.dateFormat(xDateFormat, labelConfig.key); + if (xDateFormatEnd) { + formattedKey += time.dateFormat(xDateFormatEnd, labelConfig.key + currentDataGrouping.totalRange - 1); + } + // Replace default header style with class name + if (series.chart.styledMode) { + formatString = this.styledModeFormat(formatString); + } + // return the replaced format + e.text = format(formatString, { + point: extend(labelConfig.point, { key: formattedKey }), + series: series + }, chart); + e.preventDefault(); + } +}); +// Destroy grouped data on series destroy +addEvent(Series, 'destroy', seriesProto.destroyGroupedData); +// Handle default options for data grouping. This must be set at runtime because +// some series types are defined after this. +addEvent(Series, 'afterSetOptions', function (e) { + var options = e.options, type = this.type, plotOptions = this.chart.options.plotOptions, defaultOptions = defaultPlotOptions[type].dataGrouping, + // External series, for example technical indicators should also + // inherit commonOptions which are not available outside this module + baseOptions = this.useCommonDataGrouping && commonOptions; + if (specificOptions[type] || baseOptions) { // #1284 + if (!defaultOptions) { + defaultOptions = merge(commonOptions, specificOptions[type]); + } + options.dataGrouping = merge(baseOptions, defaultOptions, plotOptions.series && plotOptions.series.dataGrouping, // #1228 + // Set by the StockChart constructor: + plotOptions[type].dataGrouping, this.userOptions.dataGrouping); + } +}); +// When resetting the scale reset the hasProccessed flag to avoid taking +// previous data grouping of neighbour series into accound when determining +// group pixel width (#2692). +addEvent(Axis, 'afterSetScale', function () { + this.series.forEach(function (series) { + series.hasProcessed = false; + }); +}); +// Get the data grouping pixel width based on the greatest defined individual +// width of the axis' series, and if whether one of the axes need grouping. +Axis.prototype.getGroupPixelWidth = function () { + var series = this.series, len = series.length, i, groupPixelWidth = 0, doGrouping = false, dataLength, dgOptions; + // If multiple series are compared on the same x axis, give them the same + // group pixel width (#334) + i = len; + while (i--) { + dgOptions = series[i].options.dataGrouping; + if (dgOptions) { + groupPixelWidth = Math.max(groupPixelWidth, + // Fallback to commonOptions (#9693) + pick(dgOptions.groupPixelWidth, commonOptions.groupPixelWidth)); + } + } + // If one of the series needs grouping, apply it to all (#1634) + i = len; + while (i--) { + dgOptions = series[i].options.dataGrouping; + if (dgOptions && series[i].hasProcessed) { // #2692 + dataLength = (series[i].processedXData || series[i].data).length; + // Execute grouping if the amount of points is greater than the + // limit defined in groupPixelWidth + if (series[i].groupPixelWidth || + dataLength > + (this.chart.plotSizeX / groupPixelWidth) || + (dataLength && dgOptions.forced)) { + doGrouping = true; + } + } + } + return doGrouping ? groupPixelWidth : 0; +}; +/** + * Highstock only. Force data grouping on all the axis' series. + * + * @product highstock + * + * @function Highcharts.Axis#setDataGrouping + * + * @param {boolean|Highcharts.DataGroupingOptionsObject} [dataGrouping] + * A `dataGrouping` configuration. Use `false` to disable data grouping + * dynamically. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for a later call to + * {@link Chart#redraw}. + * + * @return {void} + */ +Axis.prototype.setDataGrouping = function (dataGrouping, redraw) { + var axis = this; + var i; + redraw = pick(redraw, true); + if (!dataGrouping) { + dataGrouping = { + forced: false, + units: null + }; + } + // Axis is instantiated, update all series + if (this instanceof Axis) { + i = this.series.length; + while (i--) { + this.series[i].update({ + dataGrouping: dataGrouping + }, false); + } + // Axis not yet instanciated, alter series options + } + else { + this.chart.options.series.forEach(function (seriesOptions) { + seriesOptions.dataGrouping = dataGrouping; + }, false); + } + // Clear ordinal slope, so we won't accidentaly use the old one (#7827) + if (axis.ordinal) { + axis.ordinal.slope = void 0; + } + if (redraw) { + this.chart.redraw(); + } +}; +H.dataGrouping = dataGrouping; +export default dataGrouping; +/* eslint-enable no-invalid-this, valid-jsdoc */ +/** + * Data grouping is the concept of sampling the data values into larger + * blocks in order to ease readability and increase performance of the + * JavaScript charts. Highstock by default applies data grouping when + * the points become closer than a certain pixel value, determined by + * the `groupPixelWidth` option. + * + * If data grouping is applied, the grouping information of grouped + * points can be read from the [Point.dataGroup]( + * /class-reference/Highcharts.Point#dataGroup). If point options other than + * the data itself are set, for example `name` or `color` or custom properties, + * the grouping logic doesn't know how to group it. In this case the options of + * the first point instance are copied over to the group point. This can be + * altered through a custom `approximation` callback function. + * + * @declare Highcharts.DataGroupingOptionsObject + * @product highstock + * @requires product:highstock + * @requires module:modules/datagrouping + * @apioption plotOptions.series.dataGrouping + */ +/** + * The method of approximation inside a group. When for example 30 days + * are grouped into one month, this determines what value should represent + * the group. Possible values are "average", "averages", "open", "high", + * "low", "close" and "sum". For OHLC and candlestick series the approximation + * is "ohlc" by default, which finds the open, high, low and close values + * within all the grouped data. For ranges, the approximation is "range", + * which finds the low and high values. For multi-dimensional data, + * like ranges and OHLC, "averages" will compute the average for each + * dimension. + * + * Custom aggregate methods can be added by assigning a callback function + * as the approximation. This function takes a numeric array as the + * argument and should return a single numeric value or `null`. Note + * that the numeric array will never contain null values, only true + * numbers. Instead, if null values are present in the raw data, the + * numeric array will have an `.hasNulls` property set to `true`. For + * single-value data sets the data is available in the first argument + * of the callback function. For OHLC data sets, all the open values + * are in the first argument, all high values in the second etc. + * + * Since v4.2.7, grouping meta data is available in the approximation + * callback from `this.dataGroupInfo`. It can be used to extract information + * from the raw data. + * + * Defaults to `average` for line-type series, `sum` for columns, `range` + * for range series and `ohlc` for OHLC and candlestick. + * + * @sample {highstock} stock/plotoptions/series-datagrouping-approximation + * Approximation callback with custom data + * + * @type {Highcharts.DataGroupingApproximationValue|Function} + * @apioption plotOptions.series.dataGrouping.approximation + */ +/** + * Datetime formats for the header of the tooltip in a stock chart. + * The format can vary within a chart depending on the currently selected + * time range and the current data grouping. + * + * The default formats are: + * ```js + * { + * millisecond: [ + * '%A, %b %e, %H:%M:%S.%L', '%A, %b %e, %H:%M:%S.%L', '-%H:%M:%S.%L' + * ], + * second: ['%A, %b %e, %H:%M:%S', '%A, %b %e, %H:%M:%S', '-%H:%M:%S'], + * minute: ['%A, %b %e, %H:%M', '%A, %b %e, %H:%M', '-%H:%M'], + * hour: ['%A, %b %e, %H:%M', '%A, %b %e, %H:%M', '-%H:%M'], + * day: ['%A, %b %e, %Y', '%A, %b %e', '-%A, %b %e, %Y'], + * week: ['Week from %A, %b %e, %Y', '%A, %b %e', '-%A, %b %e, %Y'], + * month: ['%B %Y', '%B', '-%B %Y'], + * year: ['%Y', '%Y', '-%Y'] + * } + * ``` + * + * For each of these array definitions, the first item is the format + * used when the active time span is one unit. For instance, if the + * current data applies to one week, the first item of the week array + * is used. The second and third items are used when the active time + * span is more than two units. For instance, if the current data applies + * to two weeks, the second and third item of the week array are used, + * and applied to the start and end date of the time span. + * + * @type {object} + * @apioption plotOptions.series.dataGrouping.dateTimeLabelFormats + */ +/** + * Enable or disable data grouping. + * + * @type {boolean} + * @default true + * @apioption plotOptions.series.dataGrouping.enabled + */ +/** + * When data grouping is forced, it runs no matter how small the intervals + * are. This can be handy for example when the sum should be calculated + * for values appearing at random times within each hour. + * + * @type {boolean} + * @default false + * @apioption plotOptions.series.dataGrouping.forced + */ +/** + * The approximate pixel width of each group. If for example a series + * with 30 points is displayed over a 600 pixel wide plot area, no grouping + * is performed. If however the series contains so many points that + * the spacing is less than the groupPixelWidth, Highcharts will try + * to group it into appropriate groups so that each is more or less + * two pixels wide. If multiple series with different group pixel widths + * are drawn on the same x axis, all series will take the greatest width. + * For example, line series have 2px default group width, while column + * series have 10px. If combined, both the line and the column will + * have 10px by default. + * + * @type {number} + * @default 2 + * @apioption plotOptions.series.dataGrouping.groupPixelWidth + */ +/** + * By default only points within the visible range are grouped. Enabling this + * option will force data grouping to calculate all grouped points for a given + * dataset. That option prevents for example a column series from calculating + * a grouped point partially. The effect is similar to + * [Series.getExtremesFromAll](#plotOptions.series.getExtremesFromAll) but does + * not affect yAxis extremes. + * + * @sample {highstock} stock/plotoptions/series-datagrouping-groupall/ + * Two series with the same data but different groupAll setting + * + * @type {boolean} + * @default false + * @since 6.1.0 + * @apioption plotOptions.series.dataGrouping.groupAll + */ +/** + * Normally, a group is indexed by the start of that group, so for example + * when 30 daily values are grouped into one month, that month's x value + * will be the 1st of the month. This apparently shifts the data to + * the left. When the smoothed option is true, this is compensated for. + * The data is shifted to the middle of the group, and min and max + * values are preserved. Internally, this is used in the Navigator series. + * + * @type {boolean} + * @default false + * @apioption plotOptions.series.dataGrouping.smoothed + */ +/** + * An array determining what time intervals the data is allowed to be + * grouped to. Each array item is an array where the first value is + * the time unit and the second value another array of allowed multiples. + * + * Defaults to: + * ```js + * units: [[ + * 'millisecond', // unit name + * [1, 2, 5, 10, 20, 25, 50, 100, 200, 500] // allowed multiples + * ], [ + * 'second', + * [1, 2, 5, 10, 15, 30] + * ], [ + * 'minute', + * [1, 2, 5, 10, 15, 30] + * ], [ + * 'hour', + * [1, 2, 3, 4, 6, 8, 12] + * ], [ + * 'day', + * [1] + * ], [ + * 'week', + * [1] + * ], [ + * 'month', + * [1, 3, 6] + * ], [ + * 'year', + * null + * ]] + * ``` + * + * @type {Array|null)>>} + * @apioption plotOptions.series.dataGrouping.units + */ +/** + * The approximate pixel width of each group. If for example a series + * with 30 points is displayed over a 600 pixel wide plot area, no grouping + * is performed. If however the series contains so many points that + * the spacing is less than the groupPixelWidth, Highcharts will try + * to group it into appropriate groups so that each is more or less + * two pixels wide. Defaults to `10`. + * + * @sample {highstock} stock/plotoptions/series-datagrouping-grouppixelwidth/ + * Two series with the same data density but different groupPixelWidth + * + * @type {number} + * @default 10 + * @apioption plotOptions.column.dataGrouping.groupPixelWidth + */ +''; // required by JSDoc parsing diff --git a/librerias/gantt/code/es-modules/parts/DataLabels.js b/librerias/gantt/code/es-modules/parts/DataLabels.js new file mode 100644 index 0000000..304c37c --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/DataLabels.js @@ -0,0 +1,1147 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +/** + * Callback JavaScript function to format the data label as a string. Note that + * if a `format` is defined, the format takes precedence and the formatter is + * ignored. + * + * @callback Highcharts.DataLabelsFormatterCallbackFunction + * + * @param {Highcharts.PointLabelObject} this + * Data label context to format + * + * @param {Highcharts.DataLabelsOptions} options + * [API options](/highcharts/plotOptions.series.dataLabels) of the data label + * + * @return {number|string|null|undefined} + * Formatted data label text + */ +/** + * Values for handling data labels that flow outside the plot area. + * + * @typedef {"allow"|"justify"} Highcharts.DataLabelsOverflowValue + */ +import U from './Utilities.js'; +var animObject = U.animObject, arrayMax = U.arrayMax, clamp = U.clamp, defined = U.defined, extend = U.extend, fireEvent = U.fireEvent, format = U.format, isArray = U.isArray, merge = U.merge, objectEach = U.objectEach, pick = U.pick, relativeLength = U.relativeLength, splat = U.splat, stableSort = U.stableSort; +import './Series.js'; +var noop = H.noop, Series = H.Series, seriesTypes = H.seriesTypes; +/* eslint-disable valid-jsdoc */ +/** + * General distribution algorithm for distributing labels of differing size + * along a confined length in two dimensions. The algorithm takes an array of + * objects containing a size, a target and a rank. It will place the labels as + * close as possible to their targets, skipping the lowest ranked labels if + * necessary. + * + * @private + * @function Highcharts.distribute + * @param {Highcharts.DataLabelsBoxArray} boxes + * @param {number} len + * @param {number} [maxDistance] + * @return {void} + */ +H.distribute = function (boxes, len, maxDistance) { + var i, overlapping = true, origBoxes = boxes, // Original array will be altered with added .pos + restBoxes = [], // The outranked overshoot + box, target, total = 0, reducedLen = origBoxes.reducedLen || len; + /** + * @private + */ + function sortByTarget(a, b) { + return a.target - b.target; + } + // If the total size exceeds the len, remove those boxes with the lowest + // rank + i = boxes.length; + while (i--) { + total += boxes[i].size; + } + // Sort by rank, then slice away overshoot + if (total > reducedLen) { + stableSort(boxes, function (a, b) { + return (b.rank || 0) - (a.rank || 0); + }); + i = 0; + total = 0; + while (total <= reducedLen) { + total += boxes[i].size; + i++; + } + restBoxes = boxes.splice(i - 1, boxes.length); + } + // Order by target + stableSort(boxes, sortByTarget); + // So far we have been mutating the original array. Now + // create a copy with target arrays + boxes = boxes.map(function (box) { + return { + size: box.size, + targets: [box.target], + align: pick(box.align, 0.5) + }; + }); + while (overlapping) { + // Initial positions: target centered in box + i = boxes.length; + while (i--) { + box = boxes[i]; + // Composite box, average of targets + target = (Math.min.apply(0, box.targets) + + Math.max.apply(0, box.targets)) / 2; + box.pos = clamp(target - box.size * box.align, 0, len - box.size); + } + // Detect overlap and join boxes + i = boxes.length; + overlapping = false; + while (i--) { + // Overlap + if (i > 0 && + boxes[i - 1].pos + boxes[i - 1].size > + boxes[i].pos) { + // Add this size to the previous box + boxes[i - 1].size += boxes[i].size; + boxes[i - 1].targets = boxes[i - 1] + .targets + .concat(boxes[i].targets); + boxes[i - 1].align = 0.5; + // Overlapping right, push left + if (boxes[i - 1].pos + boxes[i - 1].size > len) { + boxes[i - 1].pos = len - boxes[i - 1].size; + } + boxes.splice(i, 1); // Remove this item + overlapping = true; + } + } + } + // Add the rest (hidden boxes) + origBoxes.push.apply(origBoxes, restBoxes); + // Now the composite boxes are placed, we need to put the original boxes + // within them + i = 0; + boxes.some(function (box) { + var posInCompositeBox = 0; + if (box.targets.some(function () { + origBoxes[i].pos = box.pos + posInCompositeBox; + // If the distance between the position and the target exceeds + // maxDistance, abort the loop and decrease the length in increments + // of 10% to recursively reduce the number of visible boxes by + // rank. Once all boxes are within the maxDistance, we're good. + if (typeof maxDistance !== 'undefined' && + Math.abs(origBoxes[i].pos - origBoxes[i].target) > maxDistance) { + // Reset the positions that are already set + origBoxes.slice(0, i + 1).forEach(function (box) { + delete box.pos; + }); + // Try with a smaller length + origBoxes.reducedLen = + (origBoxes.reducedLen || len) - (len * 0.1); + // Recurse + if (origBoxes.reducedLen > len * 0.1) { + H.distribute(origBoxes, len, maxDistance); + } + // Exceeded maxDistance => abort + return true; + } + posInCompositeBox += origBoxes[i].size; + i++; + })) { + // Exceeded maxDistance => abort + return true; + } + }); + // Add the rest (hidden) boxes and sort by target + stableSort(origBoxes, sortByTarget); +}; +/** + * Draw the data labels + * + * @private + * @function Highcharts.Series#drawDataLabels + * @return {void} + * @fires Highcharts.Series#event:afterDrawDataLabels + */ +Series.prototype.drawDataLabels = function () { + var series = this, chart = series.chart, seriesOptions = series.options, seriesDlOptions = seriesOptions.dataLabels, points = series.points, pointOptions, hasRendered = series.hasRendered || 0, dataLabelsGroup, seriesAnimDuration = animObject(seriesOptions.animation).duration, fadeInDuration = Math.min(seriesAnimDuration, 200), defer = !chart.renderer.forExport && pick(seriesDlOptions.defer, fadeInDuration > 0), renderer = chart.renderer; + /** + * Handle the dataLabels.filter option. + * @private + */ + function applyFilter(point, options) { + var filter = options.filter, op, prop, val; + if (filter) { + op = filter.operator; + prop = point[filter.property]; + val = filter.value; + if ((op === '>' && prop > val) || + (op === '<' && prop < val) || + (op === '>=' && prop >= val) || + (op === '<=' && prop <= val) || + (op === '==' && prop == val) || // eslint-disable-line eqeqeq + (op === '===' && prop === val)) { + return true; + } + return false; + } + return true; + } + /** + * Merge two objects that can be arrays. If one of them is an array, the + * other is merged into each element. If both are arrays, each element is + * merged by index. If neither are arrays, we use normal merge. + * @private + */ + function mergeArrays(one, two) { + var res = [], i; + if (isArray(one) && !isArray(two)) { + res = one.map(function (el) { + return merge(el, two); + }); + } + else if (isArray(two) && !isArray(one)) { + res = two.map(function (el) { + return merge(one, el); + }); + } + else if (!isArray(one) && !isArray(two)) { + res = merge(one, two); + } + else { + i = Math.max(one.length, two.length); + while (i--) { + res[i] = merge(one[i], two[i]); + } + } + return res; + } + // Merge in plotOptions.dataLabels for series + seriesDlOptions = mergeArrays(mergeArrays(chart.options.plotOptions && + chart.options.plotOptions.series && + chart.options.plotOptions.series.dataLabels, chart.options.plotOptions && + chart.options.plotOptions[series.type] && + chart.options.plotOptions[series.type].dataLabels), seriesDlOptions); + fireEvent(this, 'drawDataLabels'); + if (isArray(seriesDlOptions) || + seriesDlOptions.enabled || + series._hasPointLabels) { + // Create a separate group for the data labels to avoid rotation + dataLabelsGroup = series.plotGroup('dataLabelsGroup', 'data-labels', defer && !hasRendered ? 'hidden' : 'inherit', // #5133, #10220 + seriesDlOptions.zIndex || 6); + if (defer) { + dataLabelsGroup.attr({ opacity: +hasRendered }); // #3300 + if (!hasRendered) { + setTimeout(function () { + var group = series.dataLabelsGroup; + if (group) { + if (series.visible) { // #2597, #3023, #3024 + dataLabelsGroup.show(true); + } + group[seriesOptions.animation ? 'animate' : 'attr']({ opacity: 1 }, { duration: fadeInDuration }); + } + }, seriesAnimDuration - fadeInDuration); + } + } + // Make the labels for each point + points.forEach(function (point) { + // Merge in series options for the point. + // @note dataLabelAttribs (like pointAttribs) would eradicate + // the need for dlOptions, and simplify the section below. + pointOptions = splat(mergeArrays(seriesDlOptions, point.dlOptions || // dlOptions is used in treemaps + (point.options && point.options.dataLabels))); + // Handle each individual data label for this point + pointOptions.forEach(function (labelOptions, i) { + // Options for one datalabel + var labelEnabled = (labelOptions.enabled && + // #2282, #4641, #7112, #10049 + (!point.isNull || point.dataLabelOnNull) && + applyFilter(point, labelOptions)), labelConfig, formatString, labelText, style, rotation, attr, dataLabel = point.dataLabels ? point.dataLabels[i] : + point.dataLabel, connector = point.connectors ? point.connectors[i] : + point.connector, labelDistance = pick(labelOptions.distance, point.labelDistance), isNew = !dataLabel; + if (labelEnabled) { + // Create individual options structure that can be extended + // without affecting others + labelConfig = point.getLabelConfig(); + formatString = pick(labelOptions[point.formatPrefix + 'Format'], labelOptions.format); + labelText = defined(formatString) ? + format(formatString, labelConfig, chart) : + (labelOptions[point.formatPrefix + 'Formatter'] || + labelOptions.formatter).call(labelConfig, labelOptions); + style = labelOptions.style; + rotation = labelOptions.rotation; + if (!chart.styledMode) { + // Determine the color + style.color = pick(labelOptions.color, style.color, series.color, '#000000'); + // Get automated contrast color + if (style.color === 'contrast') { + point.contrastColor = renderer.getContrast((point.color || series.color)); + style.color = (!defined(labelDistance) && + labelOptions.inside) || + labelDistance < 0 || + !!seriesOptions.stacking ? + point.contrastColor : + '#000000'; + } + else { + delete point.contrastColor; + } + if (seriesOptions.cursor) { + style.cursor = seriesOptions.cursor; + } + } + attr = { + r: labelOptions.borderRadius || 0, + rotation: rotation, + padding: labelOptions.padding, + zIndex: 1 + }; + if (!chart.styledMode) { + attr.fill = labelOptions.backgroundColor; + attr.stroke = labelOptions.borderColor; + attr['stroke-width'] = labelOptions.borderWidth; + } + // Remove unused attributes (#947) + objectEach(attr, function (val, name) { + if (typeof val === 'undefined') { + delete attr[name]; + } + }); + } + // If the point is outside the plot area, destroy it. #678, #820 + if (dataLabel && (!labelEnabled || !defined(labelText))) { + point.dataLabel = + point.dataLabel && point.dataLabel.destroy(); + if (point.dataLabels) { + // Remove point.dataLabels if this was the last one + if (point.dataLabels.length === 1) { + delete point.dataLabels; + } + else { + delete point.dataLabels[i]; + } + } + if (!i) { + delete point.dataLabel; + } + if (connector) { + point.connector = point.connector.destroy(); + if (point.connectors) { + // Remove point.connectors if this was the last one + if (point.connectors.length === 1) { + delete point.connectors; + } + else { + delete point.connectors[i]; + } + } + } + // Individual labels are disabled if the are explicitly disabled + // in the point options, or if they fall outside the plot area. + } + else if (labelEnabled && defined(labelText)) { + if (!dataLabel) { + // Create new label element + point.dataLabels = point.dataLabels || []; + dataLabel = point.dataLabels[i] = rotation ? + // Labels don't rotate, use text element + renderer.text(labelText, 0, -9999, labelOptions.useHTML) + .addClass('highcharts-data-label') : + // We can use label + renderer.label(labelText, 0, -9999, labelOptions.shape, null, null, labelOptions.useHTML, null, 'data-label'); + // Store for backwards compatibility + if (!i) { + point.dataLabel = dataLabel; + } + dataLabel.addClass(' highcharts-data-label-color-' + point.colorIndex + + ' ' + (labelOptions.className || '') + + ( // #3398 + labelOptions.useHTML ? + ' highcharts-tracker' : + '')); + } + else { + // Use old element and just update text + attr.text = labelText; + } + // Store data label options for later access + dataLabel.options = labelOptions; + dataLabel.attr(attr); + if (!chart.styledMode) { + // Styles must be applied before add in order to read + // text bounding box + dataLabel.css(style).shadow(labelOptions.shadow); + } + if (!dataLabel.added) { + dataLabel.add(dataLabelsGroup); + } + if (labelOptions.textPath && !labelOptions.useHTML) { + dataLabel.setTextPath((point.getDataLabelPath && + point.getDataLabelPath(dataLabel)) || point.graphic, labelOptions.textPath); + if (point.dataLabelPath && + !labelOptions.textPath.enabled) { + // clean the DOM + point.dataLabelPath = point.dataLabelPath.destroy(); + } + } + // Now the data label is created and placed at 0,0, so we + // need to align it + series.alignDataLabel(point, dataLabel, labelOptions, null, isNew); + } + }); + }); + } + fireEvent(this, 'afterDrawDataLabels'); +}; +/** + * Align each individual data label. + * + * @private + * @function Highcharts.Series#alignDataLabel + * @param {Highcharts.Point} point + * @param {Highcharts.SVGElement} dataLabel + * @param {Highcharts.DataLabelsOptions} options + * @param {Highcharts.BBoxObject} alignTo + * @param {boolean} [isNew] + * @return {void} + */ +Series.prototype.alignDataLabel = function (point, dataLabel, options, alignTo, isNew) { + var series = this, chart = this.chart, inverted = this.isCartesian && chart.inverted, enabledDataSorting = this.enabledDataSorting, plotX = pick(point.dlBox && point.dlBox.centerX, point.plotX, -9999), plotY = pick(point.plotY, -9999), bBox = dataLabel.getBBox(), baseline, rotation = options.rotation, normRotation, negRotation, align = options.align, rotCorr, // rotation correction + isInsidePlot = chart.isInsidePlot(plotX, Math.round(plotY), inverted), + // Math.round for rounding errors (#2683), alignTo to allow column + // labels (#2700) + alignAttr, // the final position; + justify = pick(options.overflow, (enabledDataSorting ? 'none' : 'justify')) === 'justify', visible = this.visible && + point.visible !== false && + (point.series.forceDL || + (enabledDataSorting && !justify) || + isInsidePlot || + ( + // If the data label is inside the align box, it is enough + // that parts of the align box is inside the plot area + // (#12370) + options.inside && alignTo && chart.isInsidePlot(plotX, inverted ? + alignTo.x + 1 : + alignTo.y + alignTo.height - 1, inverted))), setStartPos = function (alignOptions) { + if (enabledDataSorting && series.xAxis && !justify) { + series.setDataLabelStartPos(point, dataLabel, isNew, isInsidePlot, alignOptions); + } + }; + if (visible) { + baseline = chart.renderer.fontMetrics(chart.styledMode ? void 0 : options.style.fontSize, dataLabel).b; + // The alignment box is a singular point + alignTo = extend({ + x: inverted ? this.yAxis.len - plotY : plotX, + y: Math.round(inverted ? this.xAxis.len - plotX : plotY), + width: 0, + height: 0 + }, alignTo); + // Add the text size for alignment calculation + extend(options, { + width: bBox.width, + height: bBox.height + }); + // Allow a hook for changing alignment in the last moment, then do the + // alignment + if (rotation) { + justify = false; // Not supported for rotated text + rotCorr = chart.renderer.rotCorr(baseline, rotation); // #3723 + alignAttr = { + x: (alignTo.x + + options.x + + alignTo.width / 2 + + rotCorr.x), + y: (alignTo.y + + options.y + + { top: 0, middle: 0.5, bottom: 1 }[options.verticalAlign] * + alignTo.height) + }; + setStartPos(alignAttr); // data sorting + dataLabel[isNew ? 'attr' : 'animate'](alignAttr) + .attr({ + align: align + }); + // Compensate for the rotated label sticking out on the sides + normRotation = (rotation + 720) % 360; + negRotation = normRotation > 180 && normRotation < 360; + if (align === 'left') { + alignAttr.y -= negRotation ? bBox.height : 0; + } + else if (align === 'center') { + alignAttr.x -= bBox.width / 2; + alignAttr.y -= bBox.height / 2; + } + else if (align === 'right') { + alignAttr.x -= bBox.width; + alignAttr.y -= negRotation ? 0 : bBox.height; + } + dataLabel.placed = true; + dataLabel.alignAttr = alignAttr; + } + else { + setStartPos(alignTo); // data sorting + dataLabel.align(options, null, alignTo); + alignAttr = dataLabel.alignAttr; + } + // Handle justify or crop + if (justify && alignTo.height >= 0) { // #8830 + this.justifyDataLabel(dataLabel, options, alignAttr, bBox, alignTo, isNew); + // Now check that the data label is within the plot area + } + else if (pick(options.crop, true)) { + visible = + chart.isInsidePlot(alignAttr.x, alignAttr.y) && + chart.isInsidePlot(alignAttr.x + bBox.width, alignAttr.y + bBox.height); + } + // When we're using a shape, make it possible with a connector or an + // arrow pointing to thie point + if (options.shape && !rotation) { + dataLabel[isNew ? 'attr' : 'animate']({ + anchorX: inverted ? + chart.plotWidth - point.plotY : + point.plotX, + anchorY: inverted ? + chart.plotHeight - point.plotX : + point.plotY + }); + } + } + // To use alignAttr property in hideOverlappingLabels + if (isNew && enabledDataSorting) { + dataLabel.placed = false; + } + // Show or hide based on the final aligned position + if (!visible && (!enabledDataSorting || justify)) { + dataLabel.hide(true); + dataLabel.placed = false; // don't animate back in + } +}; +/** + * Set starting position for data label sorting animation. + * + * @private + * @function Highcharts.Series#setDataLabelStartPos + * @param {Highcharts.SVGElement} dataLabel + * @param {Highcharts.ColumnPoint} point + * @param {boolean | undefined} [isNew] + * @param {boolean} [isInside] + * @param {Highcharts.AlignObject} [alignOptions] + * + * @return {void} + */ +Series.prototype.setDataLabelStartPos = function (point, dataLabel, isNew, isInside, alignOptions) { + var chart = this.chart, inverted = chart.inverted, xAxis = this.xAxis, reversed = xAxis.reversed, labelCenter = inverted ? dataLabel.height / 2 : dataLabel.width / 2, pointWidth = point.pointWidth, halfWidth = pointWidth ? pointWidth / 2 : 0, startXPos, startYPos; + startXPos = inverted ? + alignOptions.x : + (reversed ? + -labelCenter - halfWidth : + xAxis.width - labelCenter + halfWidth); + startYPos = inverted ? + (reversed ? + this.yAxis.height - labelCenter + halfWidth : + -labelCenter - halfWidth) : alignOptions.y; + dataLabel.startXPos = startXPos; + dataLabel.startYPos = startYPos; + // We need to handle visibility in case of sorting point outside plot area + if (!isInside) { + dataLabel + .attr({ opacity: 1 }) + .animate({ opacity: 0 }, void 0, dataLabel.hide); + } + else if (dataLabel.visibility === 'hidden') { + dataLabel.show(); + dataLabel + .attr({ opacity: 0 }) + .animate({ opacity: 1 }); + } + // Save start position on first render, but do not change position + if (!chart.hasRendered) { + return; + } + // Set start position + if (isNew) { + dataLabel.attr({ x: dataLabel.startXPos, y: dataLabel.startYPos }); + } + dataLabel.placed = true; +}; +/** + * If data labels fall partly outside the plot area, align them back in, in a + * way that doesn't hide the point. + * + * @private + * @function Highcharts.Series#justifyDataLabel + * @param {Highcharts.SVGElement} dataLabel + * @param {Highcharts.DataLabelsOptions} options + * @param {Highcharts.SVGAttributes} alignAttr + * @param {Highcharts.BBoxObject} bBox + * @param {Highcharts.BBoxObject} [alignTo] + * @param {boolean} [isNew] + * @return {boolean|undefined} + */ +Series.prototype.justifyDataLabel = function (dataLabel, options, alignAttr, bBox, alignTo, isNew) { + var chart = this.chart, align = options.align, verticalAlign = options.verticalAlign, off, justified, padding = dataLabel.box ? 0 : (dataLabel.padding || 0); + // Off left + off = alignAttr.x + padding; + if (off < 0) { + if (align === 'right') { + options.align = 'left'; + options.inside = true; + } + else { + options.x = -off; + } + justified = true; + } + // Off right + off = alignAttr.x + bBox.width - padding; + if (off > chart.plotWidth) { + if (align === 'left') { + options.align = 'right'; + options.inside = true; + } + else { + options.x = chart.plotWidth - off; + } + justified = true; + } + // Off top + off = alignAttr.y + padding; + if (off < 0) { + if (verticalAlign === 'bottom') { + options.verticalAlign = 'top'; + options.inside = true; + } + else { + options.y = -off; + } + justified = true; + } + // Off bottom + off = alignAttr.y + bBox.height - padding; + if (off > chart.plotHeight) { + if (verticalAlign === 'top') { + options.verticalAlign = 'bottom'; + options.inside = true; + } + else { + options.y = chart.plotHeight - off; + } + justified = true; + } + if (justified) { + dataLabel.placed = !isNew; + dataLabel.align(options, null, alignTo); + } + return justified; +}; +if (seriesTypes.pie) { + seriesTypes.pie.prototype.dataLabelPositioners = { + // Based on the value computed in Highcharts' distribute algorithm. + radialDistributionY: function (point) { + return point.top + point.distributeBox.pos; + }, + // get the x - use the natural x position for labels near the + // top and bottom, to prevent the top and botton slice + // connectors from touching each other on either side + // Based on the value computed in Highcharts' distribute algorithm. + radialDistributionX: function (series, point, y, naturalY) { + return series.getX(y < point.top + 2 || y > point.bottom - 2 ? + naturalY : + y, point.half, point); + }, + // dataLabels.distance determines the x position of the label + justify: function (point, radius, seriesCenter) { + return seriesCenter[0] + (point.half ? -1 : 1) * + (radius + point.labelDistance); + }, + // Left edges of the left-half labels touch the left edge of the plot + // area. Right edges of the right-half labels touch the right edge of + // the plot area. + alignToPlotEdges: function (dataLabel, half, plotWidth, plotLeft) { + var dataLabelWidth = dataLabel.getBBox().width; + return half ? dataLabelWidth + plotLeft : + plotWidth - dataLabelWidth - plotLeft; + }, + // Connectors of each side end in the same x position. Labels are + // aligned to them. Left edge of the widest left-half label touches the + // left edge of the plot area. Right edge of the widest right-half label + // touches the right edge of the plot area. + alignToConnectors: function (points, half, plotWidth, plotLeft) { + var maxDataLabelWidth = 0, dataLabelWidth; + // find widest data label + points.forEach(function (point) { + dataLabelWidth = point.dataLabel.getBBox().width; + if (dataLabelWidth > maxDataLabelWidth) { + maxDataLabelWidth = dataLabelWidth; + } + }); + return half ? maxDataLabelWidth + plotLeft : + plotWidth - maxDataLabelWidth - plotLeft; + } + }; + /** + * Override the base drawDataLabels method by pie specific functionality + * + * @private + * @function Highcharts.seriesTypes.pie#drawDataLabels + * @return {void} + */ + seriesTypes.pie.prototype.drawDataLabels = function () { + var series = this, data = series.data, point, chart = series.chart, options = series.options.dataLabels || {}, connectorPadding = options.connectorPadding, connectorWidth, plotWidth = chart.plotWidth, plotHeight = chart.plotHeight, plotLeft = chart.plotLeft, maxWidth = Math.round(chart.chartWidth / 3), connector, seriesCenter = series.center, radius = seriesCenter[2] / 2, centerY = seriesCenter[1], dataLabel, dataLabelWidth, + // labelPos, + labelPosition, labelHeight, + // divide the points into right and left halves for anti collision + halves = [ + [], + [] // left + ], x, y, visibility, j, overflow = [0, 0, 0, 0], // top, right, bottom, left + dataLabelPositioners = series.dataLabelPositioners, pointDataLabelsOptions; + // get out if not enabled + if (!series.visible || + (!options.enabled && + !series._hasPointLabels)) { + return; + } + // Reset all labels that have been shortened + data.forEach(function (point) { + if (point.dataLabel && point.visible && point.dataLabel.shortened) { + point.dataLabel + .attr({ + width: 'auto' + }).css({ + width: 'auto', + textOverflow: 'clip' + }); + point.dataLabel.shortened = false; + } + }); + // run parent method + Series.prototype.drawDataLabels.apply(series); + data.forEach(function (point) { + if (point.dataLabel) { + if (point.visible) { // #407, #2510 + // Arrange points for detection collision + halves[point.half].push(point); + // Reset positions (#4905) + point.dataLabel._pos = null; + // Avoid long labels squeezing the pie size too far down + if (!defined(options.style.width) && + !defined(point.options.dataLabels && + point.options.dataLabels.style && + point.options.dataLabels.style.width)) { + if (point.dataLabel.getBBox().width > maxWidth) { + point.dataLabel.css({ + // Use a fraction of the maxWidth to avoid + // wrapping close to the end of the string. + width: Math.round(maxWidth * 0.7) + 'px' + }); + point.dataLabel.shortened = true; + } + } + } + else { + point.dataLabel = point.dataLabel.destroy(); + // Workaround to make pies destroy multiple datalabels + // correctly. This logic needs rewriting to support multiple + // datalabels fully. + if (point.dataLabels && point.dataLabels.length === 1) { + delete point.dataLabels; + } + } + } + }); + /* Loop over the points in each half, starting from the top and bottom + * of the pie to detect overlapping labels. + */ + halves.forEach(function (points, i) { + var top, bottom, length = points.length, positions = [], naturalY, sideOverflow, size, distributionLength; + if (!length) { + return; + } + // Sort by angle + series.sortByAngle(points, i - 0.5); + // Only do anti-collision when we have dataLabels outside the pie + // and have connectors. (#856) + if (series.maxLabelDistance > 0) { + top = Math.max(0, centerY - radius - series.maxLabelDistance); + bottom = Math.min(centerY + radius + series.maxLabelDistance, chart.plotHeight); + points.forEach(function (point) { + // check if specific points' label is outside the pie + if (point.labelDistance > 0 && point.dataLabel) { + // point.top depends on point.labelDistance value + // Used for calculation of y value in getX method + point.top = Math.max(0, centerY - radius - point.labelDistance); + point.bottom = Math.min(centerY + radius + point.labelDistance, chart.plotHeight); + size = point.dataLabel.getBBox().height || 21; + // point.positionsIndex is needed for getting index of + // parameter related to specific point inside positions + // array - not every point is in positions array. + point.distributeBox = { + target: point.labelPosition.natural.y - + point.top + size / 2, + size: size, + rank: point.y + }; + positions.push(point.distributeBox); + } + }); + distributionLength = bottom + size - top; + H.distribute(positions, distributionLength, distributionLength / 5); + } + // Now the used slots are sorted, fill them up sequentially + for (j = 0; j < length; j++) { + point = points[j]; + // labelPos = point.labelPos; + labelPosition = point.labelPosition; + dataLabel = point.dataLabel; + visibility = point.visible === false ? 'hidden' : 'inherit'; + naturalY = labelPosition.natural.y; + y = naturalY; + if (positions && defined(point.distributeBox)) { + if (typeof point.distributeBox.pos === 'undefined') { + visibility = 'hidden'; + } + else { + labelHeight = point.distributeBox.size; + // Find label's y position + y = dataLabelPositioners + .radialDistributionY(point); + } + } + // It is needed to delete point.positionIndex for + // dynamically added points etc. + delete point.positionIndex; // @todo unused + // Find label's x position + // justify is undocumented in the API - preserve support for it + if (options.justify) { + x = dataLabelPositioners.justify(point, radius, seriesCenter); + } + else { + switch (options.alignTo) { + case 'connectors': + x = dataLabelPositioners.alignToConnectors(points, i, plotWidth, plotLeft); + break; + case 'plotEdges': + x = dataLabelPositioners.alignToPlotEdges(dataLabel, i, plotWidth, plotLeft); + break; + default: + x = dataLabelPositioners.radialDistributionX(series, point, y, naturalY); + } + } + // Record the placement and visibility + dataLabel._attr = { + visibility: visibility, + align: labelPosition.alignment + }; + pointDataLabelsOptions = point.options.dataLabels || {}; + dataLabel._pos = { + x: (x + + pick(pointDataLabelsOptions.x, options.x) + // (#12985) + ({ + left: connectorPadding, + right: -connectorPadding + }[labelPosition.alignment] || 0)), + // 10 is for the baseline (label vs text) + y: (y + + pick(pointDataLabelsOptions.y, options.y) - // (#12985) + 10) + }; + // labelPos.x = x; + // labelPos.y = y; + labelPosition.final.x = x; + labelPosition.final.y = y; + // Detect overflowing data labels + if (pick(options.crop, true)) { + dataLabelWidth = dataLabel.getBBox().width; + sideOverflow = null; + // Overflow left + if (x - dataLabelWidth < connectorPadding && + i === 1 // left half + ) { + sideOverflow = Math.round(dataLabelWidth - x + connectorPadding); + overflow[3] = Math.max(sideOverflow, overflow[3]); + // Overflow right + } + else if (x + dataLabelWidth > plotWidth - connectorPadding && + i === 0 // right half + ) { + sideOverflow = Math.round(x + dataLabelWidth - plotWidth + connectorPadding); + overflow[1] = Math.max(sideOverflow, overflow[1]); + } + // Overflow top + if (y - labelHeight / 2 < 0) { + overflow[0] = Math.max(Math.round(-y + labelHeight / 2), overflow[0]); + // Overflow left + } + else if (y + labelHeight / 2 > plotHeight) { + overflow[2] = Math.max(Math.round(y + labelHeight / 2 - plotHeight), overflow[2]); + } + dataLabel.sideOverflow = sideOverflow; + } + } // for each point + }); // for each half + // Do not apply the final placement and draw the connectors until we + // have verified that labels are not spilling over. + if (arrayMax(overflow) === 0 || + this.verifyDataLabelOverflow(overflow)) { + // Place the labels in the final position + this.placeDataLabels(); + this.points.forEach(function (point) { + // #8864: every connector can have individual options + pointDataLabelsOptions = + merge(options, point.options.dataLabels); + connectorWidth = + pick(pointDataLabelsOptions.connectorWidth, 1); + // Draw the connector + if (connectorWidth) { + var isNew; + connector = point.connector; + dataLabel = point.dataLabel; + if (dataLabel && + dataLabel._pos && + point.visible && + point.labelDistance > 0) { + visibility = dataLabel._attr.visibility; + isNew = !connector; + if (isNew) { + point.connector = connector = chart.renderer + .path() + .addClass('highcharts-data-label-connector ' + + ' highcharts-color-' + point.colorIndex + + (point.className ? + ' ' + point.className : + '')) + .add(series.dataLabelsGroup); + if (!chart.styledMode) { + connector.attr({ + 'stroke-width': connectorWidth, + 'stroke': (pointDataLabelsOptions.connectorColor || + point.color || + '#666666') + }); + } + } + connector[isNew ? 'attr' : 'animate']({ + d: point.getConnectorPath() + }); + connector.attr('visibility', visibility); + } + else if (connector) { + point.connector = connector.destroy(); + } + } + }); + } + }; + /** + * Extendable method for getting the path of the connector between the data + * label and the pie slice. + * + * @private + * @function Highcharts.seriesTypes.pie#connectorPath + * + * @param {*} labelPos + * + * @return {Highcharts.SVGPathArray} + */ + // TODO: depracated - remove it + /* + seriesTypes.pie.prototype.connectorPath = function (labelPos) { + var x = labelPos.x, + y = labelPos.y; + return pick(this.options.dataLabels.softConnector, true) ? [ + 'M', + // end of the string at the label + x + (labelPos[6] === 'left' ? 5 : -5), y, + 'C', + x, y, // first break, next to the label + 2 * labelPos[2] - labelPos[4], 2 * labelPos[3] - labelPos[5], + labelPos[2], labelPos[3], // second break + 'L', + labelPos[4], labelPos[5] // base + ] : [ + 'M', + // end of the string at the label + x + (labelPos[6] === 'left' ? 5 : -5), y, + 'L', + labelPos[2], labelPos[3], // second break + 'L', + labelPos[4], labelPos[5] // base + ]; + }; + */ + /** + * Perform the final placement of the data labels after we have verified + * that they fall within the plot area. + * + * @private + * @function Highcharts.seriesTypes.pie#placeDataLabels + * @return {void} + */ + seriesTypes.pie.prototype.placeDataLabels = function () { + this.points.forEach(function (point) { + var dataLabel = point.dataLabel, _pos; + if (dataLabel && point.visible) { + _pos = dataLabel._pos; + if (_pos) { + // Shorten data labels with ellipsis if they still overflow + // after the pie has reached minSize (#223). + if (dataLabel.sideOverflow) { + dataLabel._attr.width = + Math.max(dataLabel.getBBox().width - + dataLabel.sideOverflow, 0); + dataLabel.css({ + width: dataLabel._attr.width + 'px', + textOverflow: ((this.options.dataLabels.style || {}) + .textOverflow || + 'ellipsis') + }); + dataLabel.shortened = true; + } + dataLabel.attr(dataLabel._attr); + dataLabel[dataLabel.moved ? 'animate' : 'attr'](_pos); + dataLabel.moved = true; + } + else if (dataLabel) { + dataLabel.attr({ y: -9999 }); + } + } + // Clear for update + delete point.distributeBox; + }, this); + }; + seriesTypes.pie.prototype.alignDataLabel = noop; + /** + * Verify whether the data labels are allowed to draw, or we should run more + * translation and data label positioning to keep them inside the plot area. + * Returns true when data labels are ready to draw. + * + * @private + * @function Highcharts.seriesTypes.pie#verifyDataLabelOverflow + * @param {Array} overflow + * @return {boolean} + */ + seriesTypes.pie.prototype.verifyDataLabelOverflow = function (overflow) { + var center = this.center, options = this.options, centerOption = options.center, minSize = options.minSize || 80, newSize = minSize, + // If a size is set, return true and don't try to shrink the pie + // to fit the labels. + ret = options.size !== null; + if (!ret) { + // Handle horizontal size and center + if (centerOption[0] !== null) { // Fixed center + newSize = Math.max(center[2] - + Math.max(overflow[1], overflow[3]), minSize); + } + else { // Auto center + newSize = Math.max( + // horizontal overflow + center[2] - overflow[1] - overflow[3], minSize); + // horizontal center + center[0] += (overflow[3] - overflow[1]) / 2; + } + // Handle vertical size and center + if (centerOption[1] !== null) { // Fixed center + newSize = clamp(newSize, minSize, center[2] - Math.max(overflow[0], overflow[2])); + } + else { // Auto center + newSize = clamp(newSize, minSize, + // vertical overflow + center[2] - overflow[0] - overflow[2]); + // vertical center + center[1] += (overflow[0] - overflow[2]) / 2; + } + // If the size must be decreased, we need to run translate and + // drawDataLabels again + if (newSize < center[2]) { + center[2] = newSize; + center[3] = Math.min(// #3632 + relativeLength(options.innerSize || 0, newSize), newSize); + this.translate(center); + if (this.drawDataLabels) { + this.drawDataLabels(); + } + // Else, return true to indicate that the pie and its labels is + // within the plot area + } + else { + ret = true; + } + } + return ret; + }; +} +if (seriesTypes.column) { + /** + * Override the basic data label alignment by adjusting for the position of + * the column. + * + * @private + * @function Highcharts.seriesTypes.column#alignDataLabel + * @param {Highcharts.Point} point + * @param {Highcharts.SVGElement} dataLabel + * @param {Highcharts.DataLabelsOptions} options + * @param {Highcharts.BBoxObject} alignTo + * @param {boolean} [isNew] + * @return {void} + */ + seriesTypes.column.prototype.alignDataLabel = function (point, dataLabel, options, alignTo, isNew) { + var inverted = this.chart.inverted, series = point.series, + // data label box for alignment + dlBox = point.dlBox || point.shapeArgs, below = pick(point.below, // range series + point.plotY > + pick(this.translatedThreshold, series.yAxis.len)), + // draw it inside the box? + inside = pick(options.inside, !!this.options.stacking), overshoot; + // Align to the column itself, or the top of it + if (dlBox) { // Area range uses this method but not alignTo + alignTo = merge(dlBox); + if (alignTo.y < 0) { + alignTo.height += alignTo.y; + alignTo.y = 0; + } + // If parts of the box overshoots outside the plot area, modify the + // box to center the label inside + overshoot = alignTo.y + alignTo.height - series.yAxis.len; + if (overshoot > 0 && overshoot < alignTo.height) { + alignTo.height -= overshoot; + } + if (inverted) { + alignTo = { + x: series.yAxis.len - alignTo.y - alignTo.height, + y: series.xAxis.len - alignTo.x - alignTo.width, + width: alignTo.height, + height: alignTo.width + }; + } + // Compute the alignment box + if (!inside) { + if (inverted) { + alignTo.x += below ? 0 : alignTo.width; + alignTo.width = 0; + } + else { + alignTo.y += below ? alignTo.height : 0; + alignTo.height = 0; + } + } + } + // When alignment is undefined (typically columns and bars), display the + // individual point below or above the point depending on the threshold + options.align = pick(options.align, !inverted || inside ? 'center' : below ? 'right' : 'left'); + options.verticalAlign = pick(options.verticalAlign, inverted || inside ? 'middle' : below ? 'top' : 'bottom'); + // Call the parent method + Series.prototype.alignDataLabel.call(this, point, dataLabel, options, alignTo, isNew); + // If label was justified and we have contrast, set it: + if (options.inside && point.contrastColor) { + dataLabel.css({ + color: point.contrastColor + }); + } + }; +} diff --git a/librerias/gantt/code/es-modules/parts/DateTimeAxis.js b/librerias/gantt/code/es-modules/parts/DateTimeAxis.js new file mode 100644 index 0000000..a3eaa73 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/DateTimeAxis.js @@ -0,0 +1,177 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Axis from './Axis.js'; +import U from './Utilities.js'; +var addEvent = U.addEvent, getMagnitude = U.getMagnitude, normalizeTickInterval = U.normalizeTickInterval, timeUnits = U.timeUnits; +/* eslint-disable valid-jsdoc */ +var DateTimeAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function DateTimeAxisAdditions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Get a normalized tick interval for dates. Returns a configuration object + * with unit range (interval), count and name. Used to prepare data for + * `getTimeTicks`. Previously this logic was part of getTimeTicks, but as + * `getTimeTicks` now runs of segments in stock charts, the normalizing + * logic was extracted in order to prevent it for running over again for + * each segment having the same interval. #662, #697. + * @private + */ + /** + * Get a normalized tick interval for dates. Returns a configuration object + * with unit range (interval), count and name. Used to prepare data for + * `getTimeTicks`. Previously this logic was part of getTimeTicks, but as + * `getTimeTicks` now runs of segments in stock charts, the normalizing + * logic was extracted in order to prevent it for running over again for + * each segment having the same interval. #662, #697. + * @private + */ + DateTimeAxisAdditions.prototype.normalizeTimeTickInterval = function (tickInterval, unitsOption) { + var units = unitsOption || [[ + 'millisecond', + [1, 2, 5, 10, 20, 25, 50, 100, 200, 500] // allowed multiples + ], [ + 'second', + [1, 2, 5, 10, 15, 30] + ], [ + 'minute', + [1, 2, 5, 10, 15, 30] + ], [ + 'hour', + [1, 2, 3, 4, 6, 8, 12] + ], [ + 'day', + [1, 2] + ], [ + 'week', + [1, 2] + ], [ + 'month', + [1, 2, 3, 4, 6] + ], [ + 'year', + null + ]], unit = units[units.length - 1], // default unit is years + interval = timeUnits[unit[0]], multiples = unit[1], count, i; + // loop through the units to find the one that best fits the + // tickInterval + for (i = 0; i < units.length; i++) { + unit = units[i]; + interval = timeUnits[unit[0]]; + multiples = unit[1]; + if (units[i + 1]) { + // lessThan is in the middle between the highest multiple and + // the next unit. + var lessThan = (interval * + multiples[multiples.length - 1] + + timeUnits[units[i + 1][0]]) / 2; + // break and keep the current unit + if (tickInterval <= lessThan) { + break; + } + } + } + // prevent 2.5 years intervals, though 25, 250 etc. are allowed + if (interval === timeUnits.year && tickInterval < 5 * interval) { + multiples = [1, 2, 5]; + } + // get the count + count = normalizeTickInterval(tickInterval / interval, multiples, unit[0] === 'year' ? // #1913, #2360 + Math.max(getMagnitude(tickInterval / interval), 1) : + 1); + return { + unitRange: interval, + count: count, + unitName: unit[0] + }; + }; + return DateTimeAxisAdditions; +}()); +/** + * Date and time support for axes. + * + * @private + * @class + */ +var DateTimeAxis = /** @class */ (function () { + function DateTimeAxis() { + } + /* * + * + * Static Functions + * + * */ + /** + * Extends axis class with date and time support. + * @private + */ + DateTimeAxis.compose = function (AxisClass) { + AxisClass.keepProps.push('dateTime'); + var axisProto = AxisClass.prototype; + /** + * Set the tick positions to a time unit that makes sense, for example + * on the first of each month or on every Monday. Return an array with + * the time positions. Used in datetime axes as well as for grouping + * data on a datetime axis. + * + * @private + * @function Highcharts.Axis#getTimeTicks + * + * @param {Highcharts.TimeNormalizeObject} normalizedInterval + * The interval in axis values (ms) and thecount. + * + * @param {number} min + * The minimum in axis values. + * + * @param {number} max + * The maximum in axis values. + * + * @param {number} startOfWeek + * + * @return {Highcharts.AxisTickPositionsArray} + */ + axisProto.getTimeTicks = function () { + return this.chart.time.getTimeTicks.apply(this.chart.time, arguments); + }; + /* eslint-disable no-invalid-this */ + addEvent(AxisClass, 'init', function (e) { + var axis = this; + var options = e.userOptions; + if (options.type !== 'datetime') { + axis.dateTime = void 0; + return; + } + if (!axis.dateTime) { + axis.dateTime = new DateTimeAxisAdditions(axis); + } + }); + /* eslint-enable no-invalid-this */ + }; + /* * + * + * Static Properties + * + * */ + DateTimeAxis.AdditionsClass = DateTimeAxisAdditions; + return DateTimeAxis; +}()); +DateTimeAxis.compose(Axis); +export default DateTimeAxis; diff --git a/librerias/gantt/code/es-modules/parts/Dynamics.js b/librerias/gantt/code/es-modules/parts/Dynamics.js new file mode 100644 index 0000000..d007a89 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/Dynamics.js @@ -0,0 +1,1318 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +import Point from './Point.js'; +import Time from './Time.js'; +import U from './Utilities.js'; +var addEvent = U.addEvent, animate = U.animate, createElement = U.createElement, css = U.css, defined = U.defined, erase = U.erase, error = U.error, extend = U.extend, fireEvent = U.fireEvent, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, isString = U.isString, merge = U.merge, objectEach = U.objectEach, pick = U.pick, relativeLength = U.relativeLength, setAnimation = U.setAnimation, splat = U.splat; +import './Axis.js'; +import './Chart.js'; +import './Series.js'; +var Axis = H.Axis, Chart = H.Chart, Series = H.Series, seriesTypes = H.seriesTypes; +/* eslint-disable valid-jsdoc */ +/** + * Remove settings that have not changed, to avoid unnecessary rendering or + * computing (#9197). + * @private + */ +H.cleanRecursively = function (newer, older) { + var result = {}; + objectEach(newer, function (val, key) { + var ob; + // Dive into objects (except DOM nodes) + if (isObject(newer[key], true) && + !newer.nodeType && // #10044 + older[key]) { + ob = H.cleanRecursively(newer[key], older[key]); + if (Object.keys(ob).length) { + result[key] = ob; + } + // Arrays, primitives and DOM nodes are copied directly + } + else if (isObject(newer[key]) || + newer[key] !== older[key]) { + result[key] = newer[key]; + } + }); + return result; +}; +// Extend the Chart prototype for dynamic methods +extend(Chart.prototype, /** @lends Highcharts.Chart.prototype */ { + /** + * Add a series to the chart after render time. Note that this method should + * never be used when adding data synchronously at chart render time, as it + * adds expense to the calculations and rendering. When adding data at the + * same time as the chart is initialized, add the series as a configuration + * option instead. With multiple axes, the `offset` is dynamically adjusted. + * + * @sample highcharts/members/chart-addseries/ + * Add a series from a button + * @sample stock/members/chart-addseries/ + * Add a series in Highstock + * + * @function Highcharts.Chart#addSeries + * + * @param {Highcharts.SeriesOptionsType} options + * The config options for the series. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after adding. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * Whether to apply animation, and optionally animation + * configuration. + * + * @return {Highcharts.Series} + * The newly created series object. + * + * @fires Highcharts.Chart#event:addSeries + * @fires Highcharts.Chart#event:afterAddSeries + */ + addSeries: function (options, redraw, animation) { + var series, chart = this; + if (options) { // <- not necessary + redraw = pick(redraw, true); // defaults to true + fireEvent(chart, 'addSeries', { options: options }, function () { + series = chart.initSeries(options); + chart.isDirtyLegend = true; + chart.linkSeries(); + if (series.enabledDataSorting) { + // We need to call `setData` after `linkSeries` + series.setData(options.data, false); + } + fireEvent(chart, 'afterAddSeries', { series: series }); + if (redraw) { + chart.redraw(animation); + } + }); + } + return series; + }, + /** + * Add an axis to the chart after render time. Note that this method should + * never be used when adding data synchronously at chart render time, as it + * adds expense to the calculations and rendering. When adding data at the + * same time as the chart is initialized, add the axis as a configuration + * option instead. + * + * @sample highcharts/members/chart-addaxis/ + * Add and remove axes + * + * @function Highcharts.Chart#addAxis + * + * @param {Highcharts.AxisOptions} options + * The axis options. + * + * @param {boolean} [isX=false] + * Whether it is an X axis or a value axis. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after adding. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=true] + * Whether and how to apply animation in the redraw. + * + * @return {Highcharts.Axis} + * The newly generated Axis object. + */ + addAxis: function (options, isX, redraw, animation) { + return this.createAxis(isX ? 'xAxis' : 'yAxis', { axis: options, redraw: redraw, animation: animation }); + }, + /** + * Add a color axis to the chart after render time. Note that this method + * should never be used when adding data synchronously at chart render time, + * as it adds expense to the calculations and rendering. When adding data at + * the same time as the chart is initialized, add the axis as a + * configuration option instead. + * + * @sample highcharts/members/chart-addaxis/ + * Add and remove axes + * + * @function Highcharts.Chart#addColorAxis + * + * @param {Highcharts.ColorAxisOptions} options + * The axis options. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after adding. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=true] + * Whether and how to apply animation in the redraw. + * + * @return {Highcharts.ColorAxis} + * The newly generated Axis object. + */ + addColorAxis: function (options, redraw, animation) { + return this.createAxis('colorAxis', { axis: options, redraw: redraw, animation: animation }); + }, + /** + * Factory for creating different axis types. + * + * @private + * @function Highcharts.Chart#createAxis + * + * @param {string} type + * An axis type. + * + * @param {...Array<*>} arguments + * All arguments for the constructor. + * + * @return {Highcharts.Axis | Highcharts.ColorAxis} + * The newly generated Axis object. + */ + createAxis: function (type, options) { + var chartOptions = this.options, isColorAxis = type === 'colorAxis', axisOptions = options.axis, redraw = options.redraw, animation = options.animation, userOptions = merge(axisOptions, { + index: this[type].length, + isX: type === 'xAxis' + }), axis; + if (isColorAxis) { + axis = new H.ColorAxis(this, userOptions); + } + else { + axis = new Axis(this, userOptions); + } + // Push the new axis options to the chart options + chartOptions[type] = splat(chartOptions[type] || {}); + chartOptions[type].push(userOptions); + if (isColorAxis) { + this.isDirtyLegend = true; + // Clear before 'bindAxes' (#11924) + this.axes.forEach(function (axis) { + axis.series = []; + }); + this.series.forEach(function (series) { + series.bindAxes(); + series.isDirtyData = true; + }); + } + if (pick(redraw, true)) { + this.redraw(animation); + } + return axis; + }, + /** + * Dim the chart and show a loading text or symbol. Options for the loading + * screen are defined in {@link + * https://api.highcharts.com/highcharts/loading|the loading options}. + * + * @sample highcharts/members/chart-hideloading/ + * Show and hide loading from a button + * @sample highcharts/members/chart-showloading/ + * Apply different text labels + * @sample stock/members/chart-show-hide-loading/ + * Toggle loading in Highstock + * + * @function Highcharts.Chart#showLoading + * + * @param {string} [str] + * An optional text to show in the loading label instead of the + * default one. The default text is set in + * [lang.loading](https://api.highcharts.com/highcharts/lang.loading). + * + * @return {void} + */ + showLoading: function (str) { + var chart = this, options = chart.options, loadingDiv = chart.loadingDiv, loadingOptions = options.loading, setLoadingSize = function () { + if (loadingDiv) { + css(loadingDiv, { + left: chart.plotLeft + 'px', + top: chart.plotTop + 'px', + width: chart.plotWidth + 'px', + height: chart.plotHeight + 'px' + }); + } + }; + // create the layer at the first call + if (!loadingDiv) { + chart.loadingDiv = loadingDiv = createElement('div', { + className: 'highcharts-loading highcharts-loading-hidden' + }, null, chart.container); + chart.loadingSpan = createElement('span', { className: 'highcharts-loading-inner' }, null, loadingDiv); + addEvent(chart, 'redraw', setLoadingSize); // #1080 + } + loadingDiv.className = 'highcharts-loading'; + // Update text + chart.loadingSpan.innerHTML = + pick(str, options.lang.loading, ''); + if (!chart.styledMode) { + // Update visuals + css(loadingDiv, extend(loadingOptions.style, { + zIndex: 10 + })); + css(chart.loadingSpan, loadingOptions.labelStyle); + // Show it + if (!chart.loadingShown) { + css(loadingDiv, { + opacity: 0, + display: '' + }); + animate(loadingDiv, { + opacity: loadingOptions.style.opacity || 0.5 + }, { + duration: loadingOptions.showDuration || 0 + }); + } + } + chart.loadingShown = true; + setLoadingSize(); + }, + /** + * Hide the loading layer. + * + * @see Highcharts.Chart#showLoading + * + * @sample highcharts/members/chart-hideloading/ + * Show and hide loading from a button + * @sample stock/members/chart-show-hide-loading/ + * Toggle loading in Highstock + * + * @function Highcharts.Chart#hideLoading + * + * @return {void} + */ + hideLoading: function () { + var options = this.options, loadingDiv = this.loadingDiv; + if (loadingDiv) { + loadingDiv.className = + 'highcharts-loading highcharts-loading-hidden'; + if (!this.styledMode) { + animate(loadingDiv, { + opacity: 0 + }, { + duration: options.loading.hideDuration || 100, + complete: function () { + css(loadingDiv, { display: 'none' }); + } + }); + } + } + this.loadingShown = false; + }, + /** + * These properties cause isDirtyBox to be set to true when updating. Can be + * extended from plugins. + */ + propsRequireDirtyBox: [ + 'backgroundColor', + 'borderColor', + 'borderWidth', + 'borderRadius', + 'plotBackgroundColor', + 'plotBackgroundImage', + 'plotBorderColor', + 'plotBorderWidth', + 'plotShadow', + 'shadow' + ], + /** + * These properties require a full reflow of chart elements, best + * implemented through running `Chart.setSize` internally (#8190). + * @type {Array} + */ + propsRequireReflow: [ + 'margin', + 'marginTop', + 'marginRight', + 'marginBottom', + 'marginLeft', + 'spacing', + 'spacingTop', + 'spacingRight', + 'spacingBottom', + 'spacingLeft' + ], + /** + * These properties cause all series to be updated when updating. Can be + * extended from plugins. + */ + propsRequireUpdateSeries: [ + 'chart.inverted', + 'chart.polar', + 'chart.ignoreHiddenSeries', + 'chart.type', + 'colors', + 'plotOptions', + 'time', + 'tooltip' + ], + /** + * These collections (arrays) implement update() methods with support for + * one-to-one option. + */ + collectionsWithUpdate: [ + 'xAxis', + 'yAxis', + 'zAxis', + 'series' + ], + /** + * A generic function to update any element of the chart. Elements can be + * enabled and disabled, moved, re-styled, re-formatted etc. + * + * A special case is configuration objects that take arrays, for example + * [xAxis](https://api.highcharts.com/highcharts/xAxis), + * [yAxis](https://api.highcharts.com/highcharts/yAxis) or + * [series](https://api.highcharts.com/highcharts/series). For these + * collections, an `id` option is used to map the new option set to an + * existing object. If an existing object of the same id is not found, the + * corresponding item is updated. So for example, running `chart.update` + * with a series item without an id, will cause the existing chart's series + * with the same index in the series array to be updated. When the + * `oneToOne` parameter is true, `chart.update` will also take care of + * adding and removing items from the collection. Read more under the + * parameter description below. + * + * Note that when changing series data, `chart.update` may mutate the passed + * data options. + * + * See also the + * [responsive option set](https://api.highcharts.com/highcharts/responsive). + * Switching between `responsive.rules` basically runs `chart.update` under + * the hood. + * + * @sample highcharts/members/chart-update/ + * Update chart geometry + * + * @function Highcharts.Chart#update + * + * @param {Highcharts.Options} options + * A configuration object for the new chart options. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart. + * + * @param {boolean} [oneToOne=false] + * When `true`, the `series`, `xAxis`, `yAxis` and `annotations` + * collections will be updated one to one, and items will be either + * added or removed to match the new updated options. For example, + * if the chart has two series and we call `chart.update` with a + * configuration containing three series, one will be added. If we + * call `chart.update` with one series, one will be removed. Setting + * an empty `series` array will remove all series, but leaving out + * the`series` property will leave all series untouched. If the + * series have id's, the new series options will be matched by id, + * and the remaining ones removed. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=true] + * Whether to apply animation, and optionally animation + * configuration. + * + * @return {void} + * + * @fires Highcharts.Chart#event:update + * @fires Highcharts.Chart#event:afterUpdate + */ + update: function (options, redraw, oneToOne, animation) { + var chart = this, adders = { + credits: 'addCredits', + title: 'setTitle', + subtitle: 'setSubtitle', + caption: 'setCaption' + }, optionsChart, updateAllAxes, updateAllSeries, newWidth, newHeight, runSetSize, isResponsiveOptions = options.isResponsiveOptions, itemsForRemoval = []; + fireEvent(chart, 'update', { options: options }); + // If there are responsive rules in action, undo the responsive rules + // before we apply the updated options and replay the responsive rules + // on top from the chart.redraw function (#9617). + if (!isResponsiveOptions) { + chart.setResponsive(false, true); + } + options = H.cleanRecursively(options, chart.options); + merge(true, chart.userOptions, options); + // If the top-level chart option is present, some special updates are + // required + optionsChart = options.chart; + if (optionsChart) { + merge(true, chart.options.chart, optionsChart); + // Setter function + if ('className' in optionsChart) { + chart.setClassName(optionsChart.className); + } + if ('reflow' in optionsChart) { + chart.setReflow(optionsChart.reflow); + } + if ('inverted' in optionsChart || + 'polar' in optionsChart || + 'type' in optionsChart) { + // Parse options.chart.inverted and options.chart.polar together + // with the available series. + chart.propFromSeries(); + updateAllAxes = true; + } + if ('alignTicks' in optionsChart) { // #6452 + updateAllAxes = true; + } + objectEach(optionsChart, function (val, key) { + if (chart.propsRequireUpdateSeries.indexOf('chart.' + key) !== + -1) { + updateAllSeries = true; + } + // Only dirty box + if (chart.propsRequireDirtyBox.indexOf(key) !== -1) { + chart.isDirtyBox = true; + } + // Chart setSize + if (!isResponsiveOptions && + chart.propsRequireReflow.indexOf(key) !== -1) { + runSetSize = true; + } + }); + if (!chart.styledMode && 'style' in optionsChart) { + chart.renderer.setStyle(optionsChart.style); + } + } + // Moved up, because tooltip needs updated plotOptions (#6218) + if (!chart.styledMode && options.colors) { + this.options.colors = options.colors; + } + if (options.plotOptions) { + merge(true, this.options.plotOptions, options.plotOptions); + } + // Maintaining legacy global time. If the chart is instanciated first + // with global time, then updated with time options, we need to create a + // new Time instance to avoid mutating the global time (#10536). + if (options.time && this.time === H.time) { + this.time = new Time(options.time); + } + // Some option stuctures correspond one-to-one to chart objects that + // have update methods, for example + // options.credits => chart.credits + // options.legend => chart.legend + // options.title => chart.title + // options.tooltip => chart.tooltip + // options.subtitle => chart.subtitle + // options.mapNavigation => chart.mapNavigation + // options.navigator => chart.navigator + // options.scrollbar => chart.scrollbar + objectEach(options, function (val, key) { + if (chart[key] && + typeof chart[key].update === 'function') { + chart[key].update(val, false); + // If a one-to-one object does not exist, look for an adder function + } + else if (typeof chart[adders[key]] === 'function') { + chart[adders[key]](val); + } + if (key !== 'chart' && + chart.propsRequireUpdateSeries.indexOf(key) !== -1) { + updateAllSeries = true; + } + }); + // Setters for collections. For axes and series, each item is referred + // by an id. If the id is not found, it defaults to the corresponding + // item in the collection, so setting one series without an id, will + // update the first series in the chart. Setting two series without + // an id will update the first and the second respectively (#6019) + // chart.update and responsive. + this.collectionsWithUpdate.forEach(function (coll) { + var indexMap; + if (options[coll]) { + // In stock charts, the navigator series are also part of the + // chart.series array, but those series should not be handled + // here (#8196). + if (coll === 'series') { + indexMap = []; + chart[coll].forEach(function (s, i) { + if (!s.options.isInternal) { + indexMap.push(pick(s.options.index, i)); + } + }); + } + splat(options[coll]).forEach(function (newOptions, i) { + var item = (defined(newOptions.id) && + chart.get(newOptions.id)) || chart[coll][indexMap ? indexMap[i] : i]; + if (item && item.coll === coll) { + item.update(newOptions, false); + if (oneToOne) { + item.touched = true; + } + } + // If oneToOne and no matching item is found, add one + if (!item && oneToOne && chart.collectionsWithInit[coll]) { + chart.collectionsWithInit[coll][0].apply(chart, + // [newOptions, ...extraArguments, redraw=false] + [ + newOptions + ].concat( + // Not all initializers require extra args + chart.collectionsWithInit[coll][1] || []).concat([ + false + ])).touched = true; + } + }); + // Add items for removal + if (oneToOne) { + chart[coll].forEach(function (item) { + if (!item.touched && !item.options.isInternal) { + itemsForRemoval.push(item); + } + else { + delete item.touched; + } + }); + } + } + }); + itemsForRemoval.forEach(function (item) { + if (item.remove) { + item.remove(false); + } + }); + if (updateAllAxes) { + chart.axes.forEach(function (axis) { + axis.update({}, false); + }); + } + // Certain options require the whole series structure to be thrown away + // and rebuilt + if (updateAllSeries) { + chart.getSeriesOrderByLinks().forEach(function (series) { + // Avoid removed navigator series + if (series.chart) { + series.update({}, false); + } + }, this); + } + // For loading, just update the options, do not redraw + if (options.loading) { + merge(true, chart.options.loading, options.loading); + } + // Update size. Redraw is forced. + newWidth = optionsChart && optionsChart.width; + newHeight = optionsChart && optionsChart.height; + if (isString(newHeight)) { + newHeight = relativeLength(newHeight, newWidth || chart.chartWidth); + } + if ( + // In this case, run chart.setSize with newWidth and newHeight which + // are undefined, only for reflowing chart elements because margin + // or spacing has been set (#8190) + runSetSize || + // In this case, the size is actually set + (isNumber(newWidth) && newWidth !== chart.chartWidth) || + (isNumber(newHeight) && newHeight !== chart.chartHeight)) { + chart.setSize(newWidth, newHeight, animation); + } + else if (pick(redraw, true)) { + chart.redraw(animation); + } + fireEvent(chart, 'afterUpdate', { + options: options, + redraw: redraw, + animation: animation + }); + }, + /** + * Shortcut to set the subtitle options. This can also be done from {@link + * Chart#update} or {@link Chart#setTitle}. + * + * @function Highcharts.Chart#setSubtitle + * + * @param {Highcharts.SubtitleOptions} options + * New subtitle options. The subtitle text itself is set by the + * `options.text` property. + * + * @return {void} + */ + setSubtitle: function (options, redraw) { + this.applyDescription('subtitle', options); + this.layOutTitles(redraw); + }, + /** + * Set the caption options. This can also be done from {@link + * Chart#update}. + * + * @function Highcharts.Chart#setCaption + * + * @param {Highcharts.CaptionOptions} options + * New caption options. The caption text itself is set by the + * `options.text` property. + * + * @return {void} + */ + setCaption: function (options, redraw) { + this.applyDescription('caption', options); + this.layOutTitles(redraw); + } +}); +/** + * These collections (arrays) implement `Chart.addSomethig` method used in + * chart.update() to create new object in the collection. Equivalent for + * deleting is resolved by simple `Somethig.remove()`. + * + * Note: We need to define these references after initializers are bound to + * chart's prototype. + */ +Chart.prototype.collectionsWithInit = { + // collectionName: [ initializingMethod, [extraArguments] ] + xAxis: [Chart.prototype.addAxis, [true]], + yAxis: [Chart.prototype.addAxis, [false]], + series: [Chart.prototype.addSeries] +}; +// extend the Point prototype for dynamic methods +extend(Point.prototype, /** @lends Highcharts.Point.prototype */ { + /** + * Update point with new options (typically x/y data) and optionally redraw + * the series. + * + * @sample highcharts/members/point-update-column/ + * Update column value + * @sample highcharts/members/point-update-pie/ + * Update pie slice + * @sample maps/members/point-update/ + * Update map area value in Highmaps + * + * @function Highcharts.Point#update + * + * @param {Highcharts.PointOptionsType} options + * The point options. Point options are handled as described under + * the `series.type.data` item for each series type. For example + * for a line series, if options is a single number, the point will + * be given that number as the marin y value. If it is an array, it + * will be interpreted as x and y values respectively. If it is an + * object, advanced options are applied. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the point is updated. If doing + * more operations on the chart, it is best practice to set + * `redraw` to false and call `chart.redraw()` after. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=true] + * Whether to apply animation, and optionally animation + * configuration. + * + * @return {void} + * + * @fires Highcharts.Point#event:update + */ + update: function (options, redraw, animation, runEvent) { + var point = this, series = point.series, graphic = point.graphic, i, chart = series.chart, seriesOptions = series.options; + redraw = pick(redraw, true); + /** + * @private + */ + function update() { + point.applyOptions(options); + // Update visuals, #4146 + // Handle dummy graphic elements for a11y, #12718 + var hasDummyGraphic = graphic && point.hasDummyGraphic; + var shouldDestroyGraphic = point.y === null ? !hasDummyGraphic : hasDummyGraphic; + if (graphic && shouldDestroyGraphic) { + point.graphic = graphic.destroy(); + delete point.hasDummyGraphic; + } + if (isObject(options, true)) { + // Destroy so we can get new elements + if (graphic && graphic.element) { + // "null" is also a valid symbol + if (options && + options.marker && + typeof options.marker.symbol !== 'undefined') { + point.graphic = graphic.destroy(); + } + } + if (options && options.dataLabels && point.dataLabel) { + point.dataLabel = point.dataLabel.destroy(); // #2468 + } + if (point.connector) { + point.connector = point.connector.destroy(); // #7243 + } + } + // record changes in the parallel arrays + i = point.index; + series.updateParallelArrays(point, i); + // Record the options to options.data. If the old or the new config + // is an object, use point options, otherwise use raw options + // (#4701, #4916). + seriesOptions.data[i] = (isObject(seriesOptions.data[i], true) || + isObject(options, true)) ? + point.options : + pick(options, seriesOptions.data[i]); + // redraw + series.isDirty = series.isDirtyData = true; + if (!series.fixedBox && series.hasCartesianSeries) { // #1906, #2320 + chart.isDirtyBox = true; + } + if (seriesOptions.legendType === 'point') { // #1831, #1885 + chart.isDirtyLegend = true; + } + if (redraw) { + chart.redraw(animation); + } + } + // Fire the event with a default handler of doing the update + if (runEvent === false) { // When called from setData + update(); + } + else { + point.firePointEvent('update', { options: options }, update); + } + }, + /** + * Remove a point and optionally redraw the series and if necessary the axes + * + * @sample highcharts/plotoptions/series-point-events-remove/ + * Remove point and confirm + * @sample highcharts/members/point-remove/ + * Remove pie slice + * @sample maps/members/point-remove/ + * Remove selected points in Highmaps + * + * @function Highcharts.Point#remove + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call. When + * doing more operations on the chart, for example running + * `point.remove()` in a loop, it is best practice to set `redraw` + * to false and call `chart.redraw()` after. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=false] + * Whether to apply animation, and optionally animation + * configuration. + * + * @return {void} + */ + remove: function (redraw, animation) { + this.series.removePoint(this.series.data.indexOf(this), redraw, animation); + } +}); +// Extend the series prototype for dynamic methods +extend(Series.prototype, /** @lends Series.prototype */ { + /** + * Add a point to the series after render time. The point can be added at + * the end, or by giving it an X value, to the start or in the middle of the + * series. + * + * @sample highcharts/members/series-addpoint-append/ + * Append point + * @sample highcharts/members/series-addpoint-append-and-shift/ + * Append and shift + * @sample highcharts/members/series-addpoint-x-and-y/ + * Both X and Y values given + * @sample highcharts/members/series-addpoint-pie/ + * Append pie slice + * @sample stock/members/series-addpoint/ + * Append 100 points in Highstock + * @sample stock/members/series-addpoint-shift/ + * Append and shift in Highstock + * @sample maps/members/series-addpoint/ + * Add a point in Highmaps + * + * @function Highcharts.Series#addPoint + * + * @param {Highcharts.PointOptionsType} options + * The point options. If options is a single number, a point with + * that y value is appended to the series. If it is an array, it will + * be interpreted as x and y values respectively. If it is an + * object, advanced options as outlined under `series.data` are + * applied. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the point is added. When adding + * more than one point, it is highly recommended that the redraw + * option be set to false, and instead {@link Chart#redraw} is + * explicitly called after the adding of points is finished. + * Otherwise, the chart will redraw after adding each point. + * + * @param {boolean} [shift=false] + * If true, a point is shifted off the start of the series as one is + * appended to the end. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * Whether to apply animation, and optionally animation + * configuration. + * + * @param {boolean} [withEvent=true] + * Used internally, whether to fire the series `addPoint` event. + * + * @return {void} + * + * @fires Highcharts.Series#event:addPoint + */ + addPoint: function (options, redraw, shift, animation, withEvent) { + var series = this, seriesOptions = series.options, data = series.data, chart = series.chart, xAxis = series.xAxis, names = xAxis && xAxis.hasNames && xAxis.names, dataOptions = seriesOptions.data, point, xData = series.xData, isInTheMiddle, i, x; + // Optional redraw, defaults to true + redraw = pick(redraw, true); + // Get options and push the point to xData, yData and series.options. In + // series.generatePoints the Point instance will be created on demand + // and pushed to the series.data array. + point = { series: series }; + series.pointClass.prototype.applyOptions.apply(point, [options]); + x = point.x; + // Get the insertion point + i = xData.length; + if (series.requireSorting && x < xData[i - 1]) { + isInTheMiddle = true; + while (i && xData[i - 1] > x) { + i--; + } + } + // Insert undefined item + series.updateParallelArrays(point, 'splice', i, 0, 0); + // Update it + series.updateParallelArrays(point, i); + if (names && point.name) { + names[x] = point.name; + } + dataOptions.splice(i, 0, options); + if (isInTheMiddle) { + series.data.splice(i, 0, null); + series.processData(); + } + // Generate points to be added to the legend (#1329) + if (seriesOptions.legendType === 'point') { + series.generatePoints(); + } + // Shift the first point off the parallel arrays + if (shift) { + if (data[0] && data[0].remove) { + data[0].remove(false); + } + else { + data.shift(); + series.updateParallelArrays(point, 'shift'); + dataOptions.shift(); + } + } + // Fire event + if (withEvent !== false) { + fireEvent(series, 'addPoint', { point: point }); + } + // redraw + series.isDirty = true; + series.isDirtyData = true; + if (redraw) { + chart.redraw(animation); // Animation is set anyway on redraw, #5665 + } + }, + /** + * Remove a point from the series. Unlike the + * {@link Highcharts.Point#remove} method, this can also be done on a point + * that is not instanciated because it is outside the view or subject to + * Highstock data grouping. + * + * @sample highcharts/members/series-removepoint/ + * Remove cropped point + * + * @function Highcharts.Series#removePoint + * + * @param {number} i + * The index of the point in the {@link Highcharts.Series.data|data} + * array. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the point is added. When + * removing more than one point, it is highly recommended that the + * `redraw` option be set to `false`, and instead {@link + * Highcharts.Chart#redraw} is explicitly called after the adding of + * points is finished. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * Whether and optionally how the series should be animated. + * + * @return {void} + * + * @fires Highcharts.Point#event:remove + */ + removePoint: function (i, redraw, animation) { + var series = this, data = series.data, point = data[i], points = series.points, chart = series.chart, remove = function () { + if (points && points.length === data.length) { // #4935 + points.splice(i, 1); + } + data.splice(i, 1); + series.options.data.splice(i, 1); + series.updateParallelArrays(point || { series: series }, 'splice', i, 1); + if (point) { + point.destroy(); + } + // redraw + series.isDirty = true; + series.isDirtyData = true; + if (redraw) { + chart.redraw(); + } + }; + setAnimation(animation, chart); + redraw = pick(redraw, true); + // Fire the event with a default handler of removing the point + if (point) { + point.firePointEvent('remove', null, remove); + } + else { + remove(); + } + }, + /** + * Remove a series and optionally redraw the chart. + * + * @sample highcharts/members/series-remove/ + * Remove first series from a button + * + * @function Highcharts.Series#remove + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call to + * {@link Highcharts.Chart#redraw}. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * Whether to apply animation, and optionally animation + * configuration. + * + * @param {boolean} [withEvent=true] + * Used internally, whether to fire the series `remove` event. + * + * @return {void} + * + * @fires Highcharts.Series#event:remove + */ + remove: function (redraw, animation, withEvent, keepEvents) { + var series = this, chart = series.chart; + /** + * @private + */ + function remove() { + // Destroy elements + series.destroy(keepEvents); + series.remove = null; // Prevent from doing again (#9097) + // Redraw + chart.isDirtyLegend = chart.isDirtyBox = true; + chart.linkSeries(); + if (pick(redraw, true)) { + chart.redraw(animation); + } + } + // Fire the event with a default handler of removing the point + if (withEvent !== false) { + fireEvent(series, 'remove', null, remove); + } + else { + remove(); + } + }, + /** + * Update the series with a new set of options. For a clean and precise + * handling of new options, all methods and elements from the series are + * removed, and it is initialized from scratch. Therefore, this method is + * more performance expensive than some other utility methods like {@link + * Series#setData} or {@link Series#setVisible}. + * + * Note that `Series.update` may mutate the passed `data` options. + * + * @sample highcharts/members/series-update/ + * Updating series options + * @sample maps/members/series-update/ + * Update series options in Highmaps + * + * @function Highcharts.Series#update + * + * @param {Highcharts.SeriesOptionsType} options + * New options that will be merged with the series' existing options. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the series is altered. If doing + * more operations on the chart, it is a good idea to set redraw to + * false and call {@link Chart#redraw} after. + * + * @return {void} + * + * @fires Highcharts.Series#event:update + * @fires Highcharts.Series#event:afterUpdate + */ + update: function (options, redraw) { + options = H.cleanRecursively(options, this.userOptions); + fireEvent(this, 'update', { options: options }); + var series = this, chart = series.chart, + // must use user options when changing type because series.options + // is merged in with type specific plotOptions + oldOptions = series.userOptions, seriesOptions, initialType = series.initialType || series.type, newType = (options.type || + oldOptions.type || + chart.options.chart.type), keepPoints = !( + // Indicators, histograms etc recalculate the data. It should be + // possible to omit this. + this.hasDerivedData || + // Changes to data grouping requires new points in new groups + options.dataGrouping || + // New type requires new point classes + (newType && newType !== this.type) || + // New options affecting how the data points are built + typeof options.pointStart !== 'undefined' || + options.pointInterval || + options.pointIntervalUnit || + options.keys), initialSeriesProto = seriesTypes[initialType].prototype, n, groups = [ + 'group', + 'markerGroup', + 'dataLabelsGroup', + 'transformGroup' + ], preserve = [ + 'eventOptions', + 'navigatorSeries', + 'baseSeries' + ], + // Animation must be enabled when calling update before the initial + // animation has first run. This happens when calling update + // directly after chart initialization, or when applying responsive + // rules (#6912). + animation = series.finishedAnimating && { animation: false }, kinds = {}; + if (keepPoints) { + preserve.push('data', 'isDirtyData', 'points', 'processedXData', 'processedYData', 'xIncrement', '_hasPointMarkers', '_hasPointLabels', + // Map specific, consider moving it to series-specific preserve- + // properties (#10617) + 'mapMap', 'mapData', 'minY', 'maxY', 'minX', 'maxX'); + if (options.visible !== false) { + preserve.push('area', 'graph'); + } + series.parallelArrays.forEach(function (key) { + preserve.push(key + 'Data'); + }); + if (options.data) { + // setData uses dataSorting options so we need to update them + // earlier + if (options.dataSorting) { + extend(series.options.dataSorting, options.dataSorting); + } + this.setData(options.data, false); + } + } + // Do the merge, with some forced options + options = merge(oldOptions, animation, { + // When oldOptions.index is null it should't be cleared. + // Otherwise navigator series will have wrong indexes (#10193). + index: typeof oldOptions.index === 'undefined' ? + series.index : oldOptions.index, + pointStart: pick( + // when updating from blank (#7933) + oldOptions.pointStart, + // when updating after addPoint + series.xData[0]) + }, (!keepPoints && { data: series.options.data }), options); + // Merge does not merge arrays, but replaces them. Since points were + // updated, `series.options.data` has correct merged options, use it: + if (keepPoints && options.data) { + options.data = series.options.data; + } + // Make sure preserved properties are not destroyed (#3094) + preserve = groups.concat(preserve); + preserve.forEach(function (prop) { + preserve[prop] = series[prop]; + delete series[prop]; + }); + // Destroy the series and delete all properties. Reinsert all + // methods and properties from the new type prototype (#2270, + // #3719). + series.remove(false, null, false, true); + for (n in initialSeriesProto) { // eslint-disable-line guard-for-in + series[n] = void 0; + } + if (seriesTypes[newType || initialType]) { + extend(series, seriesTypes[newType || initialType].prototype); + } + else { + error(17, true, chart, { missingModuleFor: (newType || initialType) }); + } + // Re-register groups (#3094) and other preserved properties + preserve.forEach(function (prop) { + series[prop] = preserve[prop]; + }); + series.init(chart, options); + // Remove particular elements of the points. Check `series.options` + // because we need to consider the options being set on plotOptions as + // well. + if (keepPoints && this.points) { + seriesOptions = series.options; + // What kind of elements to destroy + if (seriesOptions.visible === false) { + kinds.graphic = 1; + kinds.dataLabel = 1; + } + else if (!series._hasPointLabels) { + var marker = seriesOptions.marker, dataLabels = seriesOptions.dataLabels; + if (marker && (marker.enabled === false || + 'symbol' in marker // #10870 + )) { + kinds.graphic = 1; + } + if (dataLabels && + dataLabels.enabled === false) { + kinds.dataLabel = 1; + } + } + this.points.forEach(function (point) { + if (point && point.series) { + point.resolveColor(); + // Destroy elements in order to recreate based on updated + // series options. + if (Object.keys(kinds).length) { + point.destroyElements(kinds); + } + if (seriesOptions.showInLegend === false && + point.legendItem) { + chart.legend.destroyItem(point); + } + } + }, this); + } + // Update the Z index of groups (#3380, #7397) + if (options.zIndex !== oldOptions.zIndex) { + groups.forEach(function (groupName) { + if (series[groupName]) { + series[groupName].attr({ + zIndex: options.zIndex + }); + } + }); + } + series.initialType = initialType; + chart.linkSeries(); // Links are lost in series.remove (#3028) + fireEvent(this, 'afterUpdate'); + if (pick(redraw, true)) { + chart.redraw(keepPoints ? void 0 : false); + } + }, + /** + * Used from within series.update + * + * @private + * @function Highcharts.Series#setName + * + * @param {string} name + * + * @return {void} + */ + setName: function (name) { + this.name = this.options.name = this.userOptions.name = name; + this.chart.isDirtyLegend = true; + } +}); +// Extend the Axis.prototype for dynamic methods +extend(Axis.prototype, /** @lends Highcharts.Axis.prototype */ { + /** + * Update an axis object with a new set of options. The options are merged + * with the existing options, so only new or altered options need to be + * specified. + * + * @sample highcharts/members/axis-update/ + * Axis update demo + * + * @function Highcharts.Axis#update + * + * @param {Highcharts.AxisOptions} options + * The new options that will be merged in with existing options on + * the axis. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the axis is altered. If doing + * more operations on the chart, it is a good idea to set redraw to + * false and call {@link Chart#redraw} after. + * + * @return {void} + */ + update: function (options, redraw) { + var chart = this.chart, newEvents = ((options && options.events) || {}); + options = merge(this.userOptions, options); + // Color Axis is not an array, + // This change is applied in the ColorAxis wrapper + if (chart.options[this.coll].indexOf) { + // Don't use this.options.index, + // StockChart has Axes in navigator too + chart.options[this.coll][chart.options[this.coll].indexOf(this.userOptions)] = options; + } + // Remove old events, if no new exist (#8161) + objectEach(chart.options[this.coll].events, function (fn, ev) { + if (typeof newEvents[ev] === 'undefined') { + newEvents[ev] = void 0; + } + }); + this.destroy(true); + this.init(chart, extend(options, { events: newEvents })); + chart.isDirtyBox = true; + if (pick(redraw, true)) { + chart.redraw(); + } + }, + /** + * Remove the axis from the chart. + * + * @sample highcharts/members/chart-addaxis/ + * Add and remove axes + * + * @function Highcharts.Axis#remove + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart following the remove. + * + * @return {void} + */ + remove: function (redraw) { + var chart = this.chart, key = this.coll, // xAxis or yAxis + axisSeries = this.series, i = axisSeries.length; + // Remove associated series (#2687) + while (i--) { + if (axisSeries[i]) { + axisSeries[i].remove(false); + } + } + // Remove the axis + erase(chart.axes, this); + erase(chart[key], this); + if (isArray(chart.options[key])) { + chart.options[key].splice(this.options.index, 1); + } + else { // color axis, #6488 + delete chart.options[key]; + } + chart[key].forEach(function (axis, i) { + // Re-index, #1706, #8075 + axis.options.index = axis.userOptions.index = i; + }); + this.destroy(); + chart.isDirtyBox = true; + if (pick(redraw, true)) { + chart.redraw(); + } + }, + /** + * Update the axis title by options after render time. + * + * @sample highcharts/members/axis-settitle/ + * Set a new Y axis title + * + * @function Highcharts.Axis#setTitle + * + * @param {Highcharts.AxisTitleOptions} titleOptions + * The additional title options. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after setting the title. + * + * @return {void} + */ + setTitle: function (titleOptions, redraw) { + this.update({ title: titleOptions }, redraw); + }, + /** + * Set new axis categories and optionally redraw. + * + * @sample highcharts/members/axis-setcategories/ + * Set categories by click on a button + * + * @function Highcharts.Axis#setCategories + * + * @param {Array} categories + * The new categories. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart. + * + * @return {void} + */ + setCategories: function (categories, redraw) { + this.update({ categories: categories }, redraw); + } +}); diff --git a/librerias/gantt/code/es-modules/parts/FlagsSeries.js b/librerias/gantt/code/es-modules/parts/FlagsSeries.js new file mode 100644 index 0000000..263b6f8 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/FlagsSeries.js @@ -0,0 +1,646 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +/** + * @typedef {"circlepin"|"flag"|"squarepin"} Highcharts.FlagsShapeValue + */ +import U from './Utilities.js'; +var addEvent = U.addEvent, defined = U.defined, isNumber = U.isNumber, merge = U.merge, objectEach = U.objectEach, seriesType = U.seriesType, wrap = U.wrap; +import './Series.js'; +import './SvgRenderer.js'; +import onSeriesMixin from '../mixins/on-series.js'; +var noop = H.noop, Renderer = H.Renderer, Series = H.Series, SVGRenderer = H.SVGRenderer, TrackerMixin = H.TrackerMixin, VMLRenderer = H.VMLRenderer, symbols = SVGRenderer.prototype.symbols; +/** + * The Flags series. + * + * @private + * @class + * @name Highcharts.seriesTypes.flags + * + * @augments Highcharts.Series + */ +seriesType('flags', 'column' +/** + * Flags are used to mark events in stock charts. They can be added on the + * timeline, or attached to a specific series. + * + * @sample stock/demo/flags-general/ + * Flags on a line series + * + * @extends plotOptions.column + * @excluding animation, borderColor, borderRadius, borderWidth, + * colorByPoint, dataGrouping, pointPadding, pointWidth, + * turboThreshold + * @product highstock + * @optionparent plotOptions.flags + */ +, { + /** + * In case the flag is placed on a series, on what point key to place + * it. Line and columns have one key, `y`. In range or OHLC-type series, + * however, the flag can optionally be placed on the `open`, `high`, + * `low` or `close` key. + * + * @sample {highstock} stock/plotoptions/flags-onkey/ + * Range series, flag on high + * + * @type {string} + * @default y + * @since 4.2.2 + * @product highstock + * @validvalue ["y", "open", "high", "low", "close"] + * @apioption plotOptions.flags.onKey + */ + /** + * The id of the series that the flags should be drawn on. If no id + * is given, the flags are drawn on the x axis. + * + * @sample {highstock} stock/plotoptions/flags/ + * Flags on series and on x axis + * + * @type {string} + * @product highstock + * @apioption plotOptions.flags.onSeries + */ + pointRange: 0, + /** + * Whether the flags are allowed to overlap sideways. If `false`, the + * flags are moved sideways using an algorithm that seeks to place every + * flag as close as possible to its original position. + * + * @sample {highstock} stock/plotoptions/flags-allowoverlapx + * Allow sideways overlap + * + * @since 6.0.4 + */ + allowOverlapX: false, + /** + * The shape of the marker. Can be one of "flag", "circlepin", + * "squarepin", or an image of the format `url(/path-to-image.jpg)`. + * Individual shapes can also be set for each point. + * + * @sample {highstock} stock/plotoptions/flags/ + * Different shapes + * + * @type {Highcharts.FlagsShapeValue} + * @product highstock + */ + shape: 'flag', + /** + * When multiple flags in the same series fall on the same value, this + * number determines the vertical offset between them. + * + * @sample {highstock} stock/plotoptions/flags-stackdistance/ + * A greater stack distance + * + * @product highstock + */ + stackDistance: 12, + /** + * Text alignment for the text inside the flag. + * + * @since 5.0.0 + * @product highstock + * @validvalue ["left", "center", "right"] + */ + textAlign: 'center', + /** + * Specific tooltip options for flag series. Flag series tooltips are + * different from most other types in that a flag doesn't have a data + * value, so the tooltip rather displays the `text` option for each + * point. + * + * @extends plotOptions.series.tooltip + * @excluding changeDecimals, valueDecimals, valuePrefix, valueSuffix + * @product highstock + */ + tooltip: { + pointFormat: '{point.text}
' + }, + threshold: null, + /** + * The text to display on each flag. This can be defined on series + * level, or individually for each point. Defaults to `"A"`. + * + * @type {string} + * @default A + * @product highstock + * @apioption plotOptions.flags.title + */ + /** + * The y position of the top left corner of the flag relative to either + * the series (if onSeries is defined), or the x axis. Defaults to + * `-30`. + * + * @product highstock + */ + y: -30, + /** + * Whether to use HTML to render the flag texts. Using HTML allows for + * advanced formatting, images and reliable bi-directional text + * rendering. Note that exported images won't respect the HTML, and that + * HTML won't respect Z-index settings. + * + * @type {boolean} + * @default false + * @since 1.3 + * @product highstock + * @apioption plotOptions.flags.useHTML + */ + /** + * Fixed width of the flag's shape. By default, width is autocalculated + * according to the flag's title. + * + * @sample {highstock} stock/demo/flags-shapes/ + * Flags with fixed width + * + * @type {number} + * @product highstock + * @apioption plotOptions.flags.width + */ + /** + * Fixed height of the flag's shape. By default, height is + * autocalculated according to the flag's title. + * + * @type {number} + * @product highstock + * @apioption plotOptions.flags.height + */ + /** + * The fill color for the flags. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highstock + */ + fillColor: '#ffffff', + /** + * The color of the line/border of the flag. + * + * In styled mode, the stroke is set in the + * `.highcharts-flag-series.highcharts-point` rule. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #000000 + * @product highstock + * @apioption plotOptions.flags.lineColor + */ + /** + * The pixel width of the flag's line/border. + * + * @product highstock + */ + lineWidth: 1, + states: { + /** + * @extends plotOptions.column.states.hover + * @product highstock + */ + hover: { + /** + * The color of the line/border of the flag. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highstock + */ + lineColor: '#000000', + /** + * The fill or background color of the flag. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highstock + */ + fillColor: '#ccd6eb' + } + }, + /** + * The text styles of the flag. + * + * In styled mode, the styles are set in the + * `.highcharts-flag-series .highcharts-point` rule. + * + * @type {Highcharts.CSSObject} + * @default {"fontSize": "11px", "fontWeight": "bold"} + * @product highstock + */ + style: { + /** @ignore-option */ + fontSize: '11px', + /** @ignore-option */ + fontWeight: 'bold' + } +}, +/** + * @lends seriesTypes.flags.prototype + */ +{ + sorted: false, + noSharedTooltip: true, + allowDG: false, + takeOrdinalPosition: false, + trackerGroups: ['markerGroup'], + forceCrop: true, + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Inherit the initialization from base Series. + * + * @private + * @borrows Highcharts.Series#init as Highcharts.seriesTypes.flags#init + */ + init: Series.prototype.init, + /** + * Get presentational attributes + * + * @private + * @function Highcharts.seriesTypes.flags#pointAttribs + * + * @param {Highcharts.Point} point + * + * @param {string} [state] + * + * @return {Highcharts.SVGAttributes} + */ + pointAttribs: function (point, state) { + var options = this.options, color = (point && point.color) || this.color, lineColor = options.lineColor, lineWidth = (point && point.lineWidth), fill = (point && point.fillColor) || options.fillColor; + if (state) { + fill = options.states[state].fillColor; + lineColor = options.states[state].lineColor; + lineWidth = options.states[state].lineWidth; + } + return { + fill: fill || color, + stroke: lineColor || color, + 'stroke-width': lineWidth || options.lineWidth || 0 + }; + }, + translate: onSeriesMixin.translate, + getPlotBox: onSeriesMixin.getPlotBox, + /** + * Draw the markers. + * + * @private + * @function Highcharts.seriesTypes.flags#drawPoints + * @return {void} + */ + drawPoints: function () { + var series = this, points = series.points, chart = series.chart, renderer = chart.renderer, plotX, plotY, inverted = chart.inverted, options = series.options, optionsY = options.y, shape, i, point, graphic, stackIndex, anchorY, attribs, outsideRight, yAxis = series.yAxis, boxesMap = {}, boxes = [], centered; + i = points.length; + while (i--) { + point = points[i]; + outsideRight = + (inverted ? point.plotY : point.plotX) > + series.xAxis.len; + plotX = point.plotX; + stackIndex = point.stackIndex; + shape = point.options.shape || options.shape; + plotY = point.plotY; + if (typeof plotY !== 'undefined') { + plotY = point.plotY + optionsY - + (typeof stackIndex !== 'undefined' && + (stackIndex * options.stackDistance)); + } + // skip connectors for higher level stacked points + point.anchorX = stackIndex ? void 0 : point.plotX; + anchorY = stackIndex ? void 0 : point.plotY; + centered = shape !== 'flag'; + graphic = point.graphic; + // Only draw the point if y is defined and the flag is within + // the visible area + if (typeof plotY !== 'undefined' && + plotX >= 0 && + !outsideRight) { + // Create the flag + if (!graphic) { + graphic = point.graphic = renderer.label('', null, null, shape, null, null, options.useHTML); + if (!chart.styledMode) { + graphic + .attr(series.pointAttribs(point)) + .css(merge(options.style, point.style)); + } + graphic.attr({ + align: centered ? 'center' : 'left', + width: options.width, + height: options.height, + 'text-align': options.textAlign + }) + .addClass('highcharts-point') + .add(series.markerGroup); + // Add reference to the point for tracker (#6303) + if (point.graphic.div) { + point.graphic.div.point = point; + } + if (!chart.styledMode) { + graphic.shadow(options.shadow); + } + graphic.isNew = true; + } + if (plotX > 0) { // #3119 + plotX -= graphic.strokeWidth() % 2; // #4285 + } + // Plant the flag + attribs = { + y: plotY, + anchorY: anchorY + }; + if (options.allowOverlapX) { + attribs.x = plotX; + attribs.anchorX = point.anchorX; + } + graphic.attr({ + text: point.options.title || options.title || 'A' + })[graphic.isNew ? 'attr' : 'animate'](attribs); + // Rig for the distribute function + if (!options.allowOverlapX) { + if (!boxesMap[point.plotX]) { + boxesMap[point.plotX] = { + align: centered ? 0.5 : 0, + size: graphic.width, + target: plotX, + anchorX: plotX + }; + } + else { + boxesMap[point.plotX].size = Math.max(boxesMap[point.plotX].size, graphic.width); + } + } + // Set the tooltip anchor position + point.tooltipPos = [ + plotX, + plotY + yAxis.pos - chart.plotTop + ]; // #6327 + } + else if (graphic) { + point.graphic = graphic.destroy(); + } + } + // Handle X-dimension overlapping + if (!options.allowOverlapX) { + objectEach(boxesMap, function (box) { + box.plotX = box.anchorX; + boxes.push(box); + }); + H.distribute(boxes, inverted ? yAxis.len : this.xAxis.len, 100); + points.forEach(function (point) { + var box = point.graphic && boxesMap[point.plotX]; + if (box) { + point.graphic[point.graphic.isNew ? 'attr' : 'animate']({ + x: box.pos + box.align * box.size, + anchorX: point.anchorX + }); + // Hide flag when its box position is not specified + // (#8573, #9299) + if (!defined(box.pos)) { + point.graphic.attr({ + x: -9999, + anchorX: -9999 + }); + point.graphic.isNew = true; + } + else { + point.graphic.isNew = false; + } + } + }); + } + // Can be a mix of SVG and HTML and we need events for both (#6303) + if (options.useHTML) { + wrap(series.markerGroup, 'on', function (proceed) { + return H.SVGElement.prototype.on.apply( + // for HTML + proceed.apply(this, [].slice.call(arguments, 1)), + // and for SVG + [].slice.call(arguments, 1)); + }); + } + }, + /** + * Extend the column trackers with listeners to expand and contract + * stacks. + * + * @private + * @function Highcharts.seriesTypes.flags#drawTracker + * @return {void} + */ + drawTracker: function () { + var series = this, points = series.points; + TrackerMixin.drawTrackerPoint.apply(this); + /* * + * Bring each stacked flag up on mouse over, this allows readability + * of vertically stacked elements as well as tight points on the x + * axis. #1924. + */ + points.forEach(function (point) { + var graphic = point.graphic; + if (graphic) { + addEvent(graphic.element, 'mouseover', function () { + // Raise this point + if (point.stackIndex > 0 && + !point.raised) { + point._y = graphic.y; + graphic.attr({ + y: point._y - 8 + }); + point.raised = true; + } + // Revert other raised points + points.forEach(function (otherPoint) { + if (otherPoint !== point && + otherPoint.raised && + otherPoint.graphic) { + otherPoint.graphic.attr({ + y: otherPoint._y + }); + otherPoint.raised = false; + } + }); + }); + } + }); + }, + /** + * Disable animation, but keep clipping (#8546). + * + * @private + * @function Highcharts.seriesTypes.flags#animate + * @param {boolean} [init] + * @return {void} + */ + animate: function (init) { + if (init) { + this.setClip(); + } + }, + /** + * @private + * @function Highcharts.seriesTypes.flags#setClip + * @return {void} + */ + setClip: function () { + Series.prototype.setClip.apply(this, arguments); + if (this.options.clip !== false && this.sharedClipKey) { + this.markerGroup + .clip(this.chart[this.sharedClipKey]); + } + }, + /** + * @private + * @function Highcharts.seriesTypes.flags#buildKDTree + */ + buildKDTree: noop, + /** + * Don't invert the flag marker group (#4960). + * + * @private + * @function Highcharts.seriesTypes.flags#invertGroups + */ + invertGroups: noop + /* eslint-enable no-invalid-this, valid-jsdoc */ +}, +/** + * @lends Highcharts.seriesTypes.flag.prototype.pointClass.prototype + */ +{ + isValid: function () { + // #9233 - Prevent from treating flags as null points (even if + // they have no y values defined). + return isNumber(this.y) || typeof this.y === 'undefined'; + } +}); +// create the flag icon with anchor +symbols.flag = function (x, y, w, h, options) { + var anchorX = (options && options.anchorX) || x, anchorY = (options && options.anchorY) || y; + // To do: unwanted any cast because symbols.circle has wrong type, it + // actually returns an SVGPathArray + var path = symbols.circle(anchorX - 1, anchorY - 1, 2, 2); + path.push(['M', anchorX, anchorY], ['L', x, y + h], ['L', x, y], ['L', x + w, y], ['L', x + w, y + h], ['L', x, y + h], ['Z']); + return path; +}; +/** + * Create the circlepin and squarepin icons with anchor. + * @private + * @param {string} shape - circle or square + * @return {void} + */ +function createPinSymbol(shape) { + symbols[shape + 'pin'] = function (x, y, w, h, options) { + var anchorX = options && options.anchorX, anchorY = options && options.anchorY, path; + // For single-letter flags, make sure circular flags are not taller + // than their width + if (shape === 'circle' && h > w) { + x -= Math.round((h - w) / 2); + w = h; + } + path = (symbols[shape])(x, y, w, h); + if (anchorX && anchorY) { + /** + * If the label is below the anchor, draw the connecting line from + * the top edge of the label, otherwise start drawing from the + * bottom edge + */ + var labelX = anchorX; + if (shape === 'circle') { + labelX = x + w / 2; + } + else { + var startSeg = path[0]; + var endSeg = path[1]; + if (startSeg[0] === 'M' && endSeg[0] === 'L') { + labelX = (startSeg[1] + endSeg[1]) / 2; + } + } + var labelY = (y > anchorY) ? y : y + h; + path.push([ + 'M', + labelX, + labelY + ], [ + 'L', + anchorX, + anchorY + ]); + path = path.concat(symbols.circle(anchorX - 1, anchorY - 1, 2, 2)); + } + return path; + }; +} +createPinSymbol('circle'); +createPinSymbol('square'); +/** + * The symbol callbacks are generated on the SVGRenderer object in all browsers. + * Even VML browsers need this in order to generate shapes in export. Now share + * them with the VMLRenderer. + */ +if (Renderer === VMLRenderer) { + ['circlepin', 'flag', 'squarepin'].forEach(function (shape) { + VMLRenderer.prototype.symbols[shape] = symbols[shape]; + }); +} +/** + * A `flags` series. If the [type](#series.flags.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.flags + * @excluding animation, borderColor, borderRadius, borderWidth, colorByPoint, + * connectNulls, dashStyle, dataGrouping, dataParser, dataURL, + * gapSize, gapUnit, linecap, lineWidth, marker, pointPadding, + * pointWidth, step, turboThreshold, useOhlcData + * @product highstock + * @apioption series.flags + */ +/** + * An array of data points for the series. For the `flags` series type, + * points can be given in the following ways: + * + * 1. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.flags.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * title: "A", + * text: "First event" + * }, { + * x: 1, + * title: "B", + * text: "Second event" + * }] + * ``` + * + * @type {Array<*>} + * @extends series.line.data + * @excluding dataLabels, marker, name, y + * @product highstock + * @apioption series.flags.data + */ +/** + * The fill color of an individual flag. By default it inherits from + * the series color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highstock + * @apioption series.flags.data.fillColor + */ +/** + * The longer text to be shown in the flag's tooltip. + * + * @type {string} + * @product highstock + * @apioption series.flags.data.text + */ +/** + * The short text to be shown on the flag. + * + * @type {string} + * @product highstock + * @apioption series.flags.data.title + */ +''; // adds doclets above to transpiled file diff --git a/librerias/gantt/code/es-modules/parts/Globals.js b/librerias/gantt/code/es-modules/parts/Globals.js new file mode 100644 index 0000000..6101292 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/Globals.js @@ -0,0 +1,77 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +/* globals Image, window */ +/** + * Reference to the global SVGElement class as a workaround for a name conflict + * in the Highcharts namespace. + * + * @global + * @typedef {global.SVGElement} GlobalSVGElement + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/SVGElement + */ +// glob is a temporary fix to allow our es-modules to work. +var glob = ( // @todo UMD variable named `window`, and glob named `win` +typeof win !== 'undefined' ? + win : + typeof window !== 'undefined' ? + window : + {}), doc = glob.document, SVG_NS = 'http://www.w3.org/2000/svg', userAgent = (glob.navigator && glob.navigator.userAgent) || '', svg = (doc && + doc.createElementNS && + !!doc.createElementNS(SVG_NS, 'svg').createSVGRect), isMS = /(edge|msie|trident)/i.test(userAgent) && !glob.opera, isFirefox = userAgent.indexOf('Firefox') !== -1, isChrome = userAgent.indexOf('Chrome') !== -1, hasBidiBug = (isFirefox && + parseInt(userAgent.split('Firefox/')[1], 10) < 4 // issue #38 +); +var H = { + product: 'Highcharts', + version: '8.1.0', + deg2rad: Math.PI * 2 / 360, + doc: doc, + hasBidiBug: hasBidiBug, + hasTouch: !!glob.TouchEvent, + isMS: isMS, + isWebKit: userAgent.indexOf('AppleWebKit') !== -1, + isFirefox: isFirefox, + isChrome: isChrome, + isSafari: !isChrome && userAgent.indexOf('Safari') !== -1, + isTouchDevice: /(Mobile|Android|Windows Phone)/.test(userAgent), + SVG_NS: SVG_NS, + chartCount: 0, + seriesTypes: {}, + symbolSizes: {}, + svg: svg, + win: glob, + marginNames: ['plotTop', 'marginRight', 'marginBottom', 'plotLeft'], + noop: function () { }, + /** + * An array containing the current chart objects in the page. A chart's + * position in the array is preserved throughout the page's lifetime. When + * a chart is destroyed, the array item becomes `undefined`. + * + * @name Highcharts.charts + * @type {Array} + */ + charts: [], + /** + * A hook for defining additional date format specifiers. New + * specifiers are defined as key-value pairs by using the + * specifier as key, and a function which takes the timestamp as + * value. This function returns the formatted portion of the + * date. + * + * @sample highcharts/global/dateformats/ + * Adding support for week number + * + * @name Highcharts.dateFormats + * @type {Highcharts.Dictionary} + */ + dateFormats: {} +}; +export default H; diff --git a/librerias/gantt/code/es-modules/parts/Html.js b/librerias/gantt/code/es-modules/parts/Html.js new file mode 100644 index 0000000..cc6f82a --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/Html.js @@ -0,0 +1,424 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +import U from './Utilities.js'; +var attr = U.attr, createElement = U.createElement, css = U.css, defined = U.defined, extend = U.extend, pick = U.pick, pInt = U.pInt; +import './SvgRenderer.js'; +var isFirefox = H.isFirefox, isMS = H.isMS, isWebKit = H.isWebKit, SVGElement = H.SVGElement, SVGRenderer = H.SVGRenderer, win = H.win; +/* eslint-disable valid-jsdoc */ +// Extend SvgElement for useHTML option. +extend(SVGElement.prototype, /** @lends SVGElement.prototype */ { + /** + * Apply CSS to HTML elements. This is used in text within SVG rendering and + * by the VML renderer + * + * @private + * @function Highcharts.SVGElement#htmlCss + * + * @param {Highcharts.CSSObject} styles + * + * @return {Highcharts.SVGElement} + */ + htmlCss: function (styles) { + var wrapper = this, element = wrapper.element, + // When setting or unsetting the width style, we need to update + // transform (#8809) + isSettingWidth = (element.tagName === 'SPAN' && + styles && + 'width' in styles), textWidth = pick(isSettingWidth && styles.width, void 0), doTransform; + if (isSettingWidth) { + delete styles.width; + wrapper.textWidth = textWidth; + doTransform = true; + } + if (styles && styles.textOverflow === 'ellipsis') { + styles.whiteSpace = 'nowrap'; + styles.overflow = 'hidden'; + } + wrapper.styles = extend(wrapper.styles, styles); + css(wrapper.element, styles); + // Now that all styles are applied, to the transform + if (doTransform) { + wrapper.htmlUpdateTransform(); + } + return wrapper; + }, + /** + * VML and useHTML method for calculating the bounding box based on offsets. + * + * @private + * @function Highcharts.SVGElement#htmlGetBBox + * + * @param {boolean} refresh + * Whether to force a fresh value from the DOM or to use the cached + * value. + * + * @return {Highcharts.BBoxObject} + * A hash containing values for x, y, width and height. + */ + htmlGetBBox: function () { + var wrapper = this, element = wrapper.element; + return { + x: element.offsetLeft, + y: element.offsetTop, + width: element.offsetWidth, + height: element.offsetHeight + }; + }, + /** + * VML override private method to update elements based on internal + * properties based on SVG transform. + * + * @private + * @function Highcharts.SVGElement#htmlUpdateTransform + * @return {void} + */ + htmlUpdateTransform: function () { + // aligning non added elements is expensive + if (!this.added) { + this.alignOnAdd = true; + return; + } + var wrapper = this, renderer = wrapper.renderer, elem = wrapper.element, translateX = wrapper.translateX || 0, translateY = wrapper.translateY || 0, x = wrapper.x || 0, y = wrapper.y || 0, align = wrapper.textAlign || 'left', alignCorrection = { + left: 0, center: 0.5, right: 1 + }[align], styles = wrapper.styles, whiteSpace = styles && styles.whiteSpace; + /** + * @private + * @return {number} + */ + function getTextPxLength() { + // Reset multiline/ellipsis in order to read width (#4928, + // #5417) + css(elem, { + width: '', + whiteSpace: whiteSpace || 'nowrap' + }); + return elem.offsetWidth; + } + // apply translate + css(elem, { + marginLeft: translateX, + marginTop: translateY + }); + if (!renderer.styledMode && wrapper.shadows) { // used in labels/tooltip + wrapper.shadows.forEach(function (shadow) { + css(shadow, { + marginLeft: translateX + 1, + marginTop: translateY + 1 + }); + }); + } + // apply inversion + if (wrapper.inverted) { // wrapper is a group + [].forEach.call(elem.childNodes, function (child) { + renderer.invertChild(child, elem); + }); + } + if (elem.tagName === 'SPAN') { + var rotation = wrapper.rotation, baseline, textWidth = wrapper.textWidth && pInt(wrapper.textWidth), currentTextTransform = [ + rotation, + align, + elem.innerHTML, + wrapper.textWidth, + wrapper.textAlign + ].join(','); + // Update textWidth. Use the memoized textPxLength if possible, to + // avoid the getTextPxLength function using elem.offsetWidth. + // Calling offsetWidth affects rendering time as it forces layout + // (#7656). + if (textWidth !== wrapper.oldTextWidth && + ((textWidth > wrapper.oldTextWidth) || + (wrapper.textPxLength || getTextPxLength()) > textWidth) && ( + // Only set the width if the text is able to word-wrap, or + // text-overflow is ellipsis (#9537) + /[ \-]/.test(elem.textContent || elem.innerText) || + elem.style.textOverflow === 'ellipsis')) { // #983, #1254 + css(elem, { + width: textWidth + 'px', + display: 'block', + whiteSpace: whiteSpace || 'normal' // #3331 + }); + wrapper.oldTextWidth = textWidth; + wrapper.hasBoxWidthChanged = true; // #8159 + } + else { + wrapper.hasBoxWidthChanged = false; // #8159 + } + // Do the calculations and DOM access only if properties changed + if (currentTextTransform !== wrapper.cTT) { + baseline = renderer.fontMetrics(elem.style.fontSize, elem).b; + // Renderer specific handling of span rotation, but only if we + // have something to update. + if (defined(rotation) && + ((rotation !== (wrapper.oldRotation || 0)) || + (align !== wrapper.oldAlign))) { + wrapper.setSpanRotation(rotation, alignCorrection, baseline); + } + wrapper.getSpanCorrection( + // Avoid elem.offsetWidth if we can, it affects rendering + // time heavily (#7656) + ((!defined(rotation) && wrapper.textPxLength) || // #7920 + elem.offsetWidth), baseline, alignCorrection, rotation, align); + } + // apply position with correction + css(elem, { + left: (x + (wrapper.xCorr || 0)) + 'px', + top: (y + (wrapper.yCorr || 0)) + 'px' + }); + // record current text transform + wrapper.cTT = currentTextTransform; + wrapper.oldRotation = rotation; + wrapper.oldAlign = align; + } + }, + /** + * Set the rotation of an individual HTML span. + * + * @private + * @function Highcharts.SVGElement#setSpanRotation + * @param {number} rotation + * @param {number} alignCorrection + * @param {number} baseline + * @return {void} + */ + setSpanRotation: function (rotation, alignCorrection, baseline) { + var rotationStyle = {}, cssTransformKey = this.renderer.getTransformKey(); + rotationStyle[cssTransformKey] = rotationStyle.transform = + 'rotate(' + rotation + 'deg)'; + rotationStyle[cssTransformKey + (isFirefox ? 'Origin' : '-origin')] = + rotationStyle.transformOrigin = + (alignCorrection * 100) + '% ' + baseline + 'px'; + css(this.element, rotationStyle); + }, + /** + * Get the correction in X and Y positioning as the element is rotated. + * + * @private + * @function Highcharts.SVGElement#getSpanCorrection + * @param {number} width + * @param {number} baseline + * @param {number} alignCorrection + * @return {void} + */ + getSpanCorrection: function (width, baseline, alignCorrection) { + this.xCorr = -width * alignCorrection; + this.yCorr = -baseline; + } +}); +// Extend SvgRenderer for useHTML option. +extend(SVGRenderer.prototype, /** @lends SVGRenderer.prototype */ { + /** + * @private + * @function Highcharts.SVGRenderer#getTransformKey + * + * @return {string} + */ + getTransformKey: function () { + return isMS && !/Edge/.test(win.navigator.userAgent) ? + '-ms-transform' : + isWebKit ? + '-webkit-transform' : + isFirefox ? + 'MozTransform' : + win.opera ? + '-o-transform' : + ''; + }, + /** + * Create HTML text node. This is used by the VML renderer as well as the + * SVG renderer through the useHTML option. + * + * @private + * @function Highcharts.SVGRenderer#html + * + * @param {string} str + * The text of (subset) HTML to draw. + * + * @param {number} x + * The x position of the text's lower left corner. + * + * @param {number} y + * The y position of the text's lower left corner. + * + * @return {Highcharts.HTMLDOMElement} + */ + html: function (str, x, y) { + var wrapper = this.createElement('span'), element = wrapper.element, renderer = wrapper.renderer, isSVG = renderer.isSVG, addSetters = function (gWrapper, style) { + // These properties are set as attributes on the SVG group, and + // as identical CSS properties on the div. (#3542) + ['opacity', 'visibility'].forEach(function (prop) { + gWrapper[prop + 'Setter'] = function (value, key, elem) { + var styleObject = gWrapper.div ? + gWrapper.div.style : + style; + SVGElement.prototype[prop + 'Setter'] + .call(this, value, key, elem); + if (styleObject) { + styleObject[key] = value; + } + }; + }); + gWrapper.addedSetters = true; + }; + // Text setter + wrapper.textSetter = function (value) { + if (value !== element.innerHTML) { + delete this.bBox; + delete this.oldTextWidth; + } + this.textStr = value; + element.innerHTML = pick(value, ''); + wrapper.doTransform = true; + }; + // Add setters for the element itself (#4938) + if (isSVG) { // #4938, only for HTML within SVG + addSetters(wrapper, wrapper.element.style); + } + // Various setters which rely on update transform + wrapper.xSetter = + wrapper.ySetter = + wrapper.alignSetter = + wrapper.rotationSetter = + function (value, key) { + if (key === 'align') { + // Do not overwrite the SVGElement.align method. Same as VML. + key = 'textAlign'; + } + wrapper[key] = value; + wrapper.doTransform = true; + }; + // Runs at the end of .attr() + wrapper.afterSetters = function () { + // Update transform. Do this outside the loop to prevent redundant + // updating for batch setting of attributes. + if (this.doTransform) { + this.htmlUpdateTransform(); + this.doTransform = false; + } + }; + // Set the default attributes + wrapper + .attr({ + text: str, + x: Math.round(x), + y: Math.round(y) + }) + .css({ + position: 'absolute' + }); + if (!renderer.styledMode) { + wrapper.css({ + fontFamily: this.style.fontFamily, + fontSize: this.style.fontSize + }); + } + // Keep the whiteSpace style outside the wrapper.styles collection + element.style.whiteSpace = 'nowrap'; + // Use the HTML specific .css method + wrapper.css = wrapper.htmlCss; + // This is specific for HTML within SVG + if (isSVG) { + wrapper.add = function (svgGroupWrapper) { + var htmlGroup, container = renderer.box.parentNode, parentGroup, parents = []; + this.parentGroup = svgGroupWrapper; + // Create a mock group to hold the HTML elements + if (svgGroupWrapper) { + htmlGroup = svgGroupWrapper.div; + if (!htmlGroup) { + // Read the parent chain into an array and read from top + // down + parentGroup = svgGroupWrapper; + while (parentGroup) { + parents.push(parentGroup); + // Move up to the next parent group + parentGroup = parentGroup.parentGroup; + } + // Ensure dynamically updating position when any parent + // is translated + parents.reverse().forEach(function (parentGroup) { + var htmlGroupStyle, cls = attr(parentGroup.element, 'class'); + /** + * Common translate setter for X and Y on the HTML + * group. Reverted the fix for #6957 du to + * positioning problems and offline export (#7254, + * #7280, #7529) + * @private + * @param {*} value + * @param {string} key + * @return {void} + */ + function translateSetter(value, key) { + parentGroup[key] = value; + if (key === 'translateX') { + htmlGroupStyle.left = value + 'px'; + } + else { + htmlGroupStyle.top = value + 'px'; + } + parentGroup.doTransform = true; + } + // Create a HTML div and append it to the parent div + // to emulate the SVG group structure + htmlGroup = + parentGroup.div = + parentGroup.div || createElement('div', cls ? { className: cls } : void 0, { + position: 'absolute', + left: (parentGroup.translateX || 0) + 'px', + top: (parentGroup.translateY || 0) + 'px', + display: parentGroup.display, + opacity: parentGroup.opacity, + pointerEvents: (parentGroup.styles && + parentGroup.styles.pointerEvents) // #5595 + // the top group is appended to container + }, htmlGroup || container); + // Shortcut + htmlGroupStyle = htmlGroup.style; + // Set listeners to update the HTML div's position + // whenever the SVG group position is changed. + extend(parentGroup, { + // (#7287) Pass htmlGroup to use + // the related group + classSetter: (function (htmlGroup) { + return function (value) { + this.element.setAttribute('class', value); + htmlGroup.className = value; + }; + }(htmlGroup)), + on: function () { + if (parents[0].div) { // #6418 + wrapper.on.apply({ element: parents[0].div }, arguments); + } + return parentGroup; + }, + translateXSetter: translateSetter, + translateYSetter: translateSetter + }); + if (!parentGroup.addedSetters) { + addSetters(parentGroup); + } + }); + } + } + else { + htmlGroup = container; + } + htmlGroup.appendChild(element); + // Shared with VML: + wrapper.added = true; + if (wrapper.alignOnAdd) { + wrapper.htmlUpdateTransform(); + } + return wrapper; + }; + } + return wrapper; + } +}); diff --git a/librerias/gantt/code/es-modules/parts/Interaction.js b/librerias/gantt/code/es-modules/parts/Interaction.js new file mode 100644 index 0000000..eeec1d2 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/Interaction.js @@ -0,0 +1,1166 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +/** + * @interface Highcharts.PointEventsOptionsObject + */ /** +* Fires when the point is selected either programmatically or following a click +* on the point. One parameter, `event`, is passed to the function. Returning +* `false` cancels the operation. +* @name Highcharts.PointEventsOptionsObject#select +* @type {Highcharts.PointSelectCallbackFunction|undefined} +*/ /** +* Fires when the point is unselected either programmatically or following a +* click on the point. One parameter, `event`, is passed to the function. +* Returning `false` cancels the operation. +* @name Highcharts.PointEventsOptionsObject#unselect +* @type {Highcharts.PointUnselectCallbackFunction|undefined} +*/ +/** + * Information about the select/unselect event. + * + * @interface Highcharts.PointInteractionEventObject + * @extends global.Event + */ /** +* @name Highcharts.PointInteractionEventObject#accumulate +* @type {boolean} +*/ +/** + * Gets fired when the point is selected either programmatically or following a + * click on the point. + * + * @callback Highcharts.PointSelectCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {Highcharts.PointInteractionEventObject} event + * Event that occured. + */ +/** + * Fires when the point is unselected either programmatically or following a + * click on the point. + * + * @callback Highcharts.PointUnselectCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {Highcharts.PointInteractionEventObject} event + * Event that occured. + */ +import Legend from './Legend.js'; +import Point from './Point.js'; +import U from './Utilities.js'; +var addEvent = U.addEvent, createElement = U.createElement, css = U.css, defined = U.defined, extend = U.extend, fireEvent = U.fireEvent, isArray = U.isArray, isFunction = U.isFunction, isNumber = U.isNumber, isObject = U.isObject, merge = U.merge, objectEach = U.objectEach, pick = U.pick; +import './Chart.js'; +import './Options.js'; +import './Series.js'; +var Chart = H.Chart, defaultOptions = H.defaultOptions, defaultPlotOptions = H.defaultPlotOptions, hasTouch = H.hasTouch, Series = H.Series, seriesTypes = H.seriesTypes, svg = H.svg, TrackerMixin; +/* eslint-disable valid-jsdoc */ +/** + * TrackerMixin for points and graphs. + * + * @private + * @mixin Highcharts.TrackerMixin + */ +TrackerMixin = H.TrackerMixin = { + /** + * Draw the tracker for a point. + * + * @private + * @function Highcharts.TrackerMixin.drawTrackerPoint + * @param {Highcharts.Series} this + * @fires Highcharts.Series#event:afterDrawTracker + */ + drawTrackerPoint: function () { + var series = this, chart = series.chart, pointer = chart.pointer, onMouseOver = function (e) { + var point = pointer.getPointFromEvent(e); + // undefined on graph in scatterchart + if (typeof point !== 'undefined') { + pointer.isDirectTouch = true; + point.onMouseOver(e); + } + }, dataLabels; + // Add reference to the point + series.points.forEach(function (point) { + dataLabels = (isArray(point.dataLabels) ? + point.dataLabels : + (point.dataLabel ? [point.dataLabel] : [])); + if (point.graphic) { + point.graphic.element.point = point; + } + dataLabels.forEach(function (dataLabel) { + if (dataLabel.div) { + dataLabel.div.point = point; + } + else { + dataLabel.element.point = point; + } + }); + }); + // Add the event listeners, we need to do this only once + if (!series._hasTracking) { + series.trackerGroups.forEach(function (key) { + if (series[key]) { + // we don't always have dataLabelsGroup + series[key] + .addClass('highcharts-tracker') + .on('mouseover', onMouseOver) + .on('mouseout', function (e) { + pointer.onTrackerMouseOut(e); + }); + if (hasTouch) { + series[key].on('touchstart', onMouseOver); + } + if (!chart.styledMode && series.options.cursor) { + series[key] + .css(css) + .css({ cursor: series.options.cursor }); + } + } + }); + series._hasTracking = true; + } + fireEvent(this, 'afterDrawTracker'); + }, + /** + * Draw the tracker object that sits above all data labels and markers to + * track mouse events on the graph or points. For the line type charts + * the tracker uses the same graphPath, but with a greater stroke width + * for better control. + * + * @private + * @function Highcharts.TrackerMixin.drawTrackerGraph + * @param {Highcharts.Series} this + * @fires Highcharts.Series#event:afterDrawTracker + */ + drawTrackerGraph: function () { + var series = this, options = series.options, trackByArea = options.trackByArea, trackerPath = [].concat(trackByArea ? + series.areaPath : + series.graphPath), + // trackerPathLength = trackerPath.length, + chart = series.chart, pointer = chart.pointer, renderer = chart.renderer, snap = chart.options.tooltip.snap, tracker = series.tracker, i, onMouseOver = function (e) { + if (chart.hoverSeries !== series) { + series.onMouseOver(); + } + }, + /* + * Empirical lowest possible opacities for TRACKER_FILL for an + * element to stay invisible but clickable + * IE6: 0.002 + * IE7: 0.002 + * IE8: 0.002 + * IE9: 0.00000000001 (unlimited) + * IE10: 0.0001 (exporting only) + * FF: 0.00000000001 (unlimited) + * Chrome: 0.000001 + * Safari: 0.000001 + * Opera: 0.00000000001 (unlimited) + */ + TRACKER_FILL = 'rgba(192,192,192,' + (svg ? 0.0001 : 0.002) + ')'; + // Draw the tracker + if (tracker) { + tracker.attr({ d: trackerPath }); + } + else if (series.graph) { // create + series.tracker = renderer.path(trackerPath) + .attr({ + visibility: series.visible ? 'visible' : 'hidden', + zIndex: 2 + }) + .addClass(trackByArea ? + 'highcharts-tracker-area' : + 'highcharts-tracker-line') + .add(series.group); + if (!chart.styledMode) { + series.tracker.attr({ + 'stroke-linecap': 'round', + 'stroke-linejoin': 'round', + stroke: TRACKER_FILL, + fill: trackByArea ? TRACKER_FILL : 'none', + 'stroke-width': series.graph.strokeWidth() + + (trackByArea ? 0 : 2 * snap) + }); + } + // The tracker is added to the series group, which is clipped, but + // is covered by the marker group. So the marker group also needs to + // capture events. + [series.tracker, series.markerGroup].forEach(function (tracker) { + tracker.addClass('highcharts-tracker') + .on('mouseover', onMouseOver) + .on('mouseout', function (e) { + pointer.onTrackerMouseOut(e); + }); + if (options.cursor && !chart.styledMode) { + tracker.css({ cursor: options.cursor }); + } + if (hasTouch) { + tracker.on('touchstart', onMouseOver); + } + }); + } + fireEvent(this, 'afterDrawTracker'); + } +}; +/* End TrackerMixin */ +// Add tracking event listener to the series group, so the point graphics +// themselves act as trackers +if (seriesTypes.column) { + /** + * @private + * @borrows Highcharts.TrackerMixin.drawTrackerPoint as Highcharts.seriesTypes.column#drawTracker + */ + seriesTypes.column.prototype.drawTracker = TrackerMixin.drawTrackerPoint; +} +if (seriesTypes.pie) { + /** + * @private + * @borrows Highcharts.TrackerMixin.drawTrackerPoint as Highcharts.seriesTypes.pie#drawTracker + */ + seriesTypes.pie.prototype.drawTracker = TrackerMixin.drawTrackerPoint; +} +if (seriesTypes.scatter) { + /** + * @private + * @borrows Highcharts.TrackerMixin.drawTrackerPoint as Highcharts.seriesTypes.scatter#drawTracker + */ + seriesTypes.scatter.prototype.drawTracker = TrackerMixin.drawTrackerPoint; +} +// Extend Legend for item events. +extend(Legend.prototype, { + /** + * @private + * @function Highcharts.Legend#setItemEvents + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + * @param {Highcharts.SVGElement} legendItem + * @param {boolean} [useHTML=false] + * @fires Highcharts.Point#event:legendItemClick + * @fires Highcharts.Series#event:legendItemClick + */ + setItemEvents: function (item, legendItem, useHTML) { + var legend = this, boxWrapper = legend.chart.renderer.boxWrapper, isPoint = item instanceof Point, activeClass = 'highcharts-legend-' + + (isPoint ? 'point' : 'series') + '-active', styledMode = legend.chart.styledMode, + // When `useHTML`, the symbol is rendered in other group, so + // we need to apply events listeners to both places + legendItems = useHTML ? + [legendItem, item.legendSymbol] : + [item.legendGroup]; + // Set the events on the item group, or in case of useHTML, the item + // itself (#1249) + legendItems.forEach(function (element) { + if (element) { + element + .on('mouseover', function () { + if (item.visible) { + legend.allItems.forEach(function (inactiveItem) { + if (item !== inactiveItem) { + inactiveItem.setState('inactive', !isPoint); + } + }); + } + item.setState('hover'); + // A CSS class to dim or hide other than the hovered + // series. + // Works only if hovered series is visible (#10071). + if (item.visible) { + boxWrapper.addClass(activeClass); + } + if (!styledMode) { + legendItem.css(legend.options.itemHoverStyle); + } + }) + .on('mouseout', function () { + if (!legend.chart.styledMode) { + legendItem.css(merge(item.visible ? + legend.itemStyle : + legend.itemHiddenStyle)); + } + legend.allItems.forEach(function (inactiveItem) { + if (item !== inactiveItem) { + inactiveItem.setState('', !isPoint); + } + }); + // A CSS class to dim or hide other than the hovered + // series. + boxWrapper.removeClass(activeClass); + item.setState(); + }) + .on('click', function (event) { + var strLegendItemClick = 'legendItemClick', fnLegendItemClick = function () { + if (item.setVisible) { + item.setVisible(); + } + // Reset inactive state + legend.allItems.forEach(function (inactiveItem) { + if (item !== inactiveItem) { + inactiveItem.setState(item.visible ? 'inactive' : '', !isPoint); + } + }); + }; + // A CSS class to dim or hide other than the hovered + // series. Event handling in iOS causes the activeClass + // to be added prior to click in some cases (#7418). + boxWrapper.removeClass(activeClass); + // Pass over the click/touch event. #4. + event = { + browserEvent: event + }; + // click the name or symbol + if (item.firePointEvent) { // point + item.firePointEvent(strLegendItemClick, event, fnLegendItemClick); + } + else { + fireEvent(item, strLegendItemClick, event, fnLegendItemClick); + } + }); + } + }); + }, + /** + * @private + * @function Highcharts.Legend#createCheckboxForItem + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + * @fires Highcharts.Series#event:checkboxClick + */ + createCheckboxForItem: function (item) { + var legend = this; + item.checkbox = createElement('input', { + type: 'checkbox', + className: 'highcharts-legend-checkbox', + checked: item.selected, + defaultChecked: item.selected // required by IE7 + }, legend.options.itemCheckboxStyle, legend.chart.container); + addEvent(item.checkbox, 'click', function (event) { + var target = event.target; + fireEvent(item.series || item, 'checkboxClick', { + checked: target.checked, + item: item + }, function () { + item.select(); + }); + }); + } +}); +// Extend the Chart object with interaction +extend(Chart.prototype, /** @lends Chart.prototype */ { + /** + * Display the zoom button, so users can reset zoom to the default view + * settings. + * + * @function Highcharts.Chart#showResetZoom + * + * @fires Highcharts.Chart#event:afterShowResetZoom + * @fires Highcharts.Chart#event:beforeShowResetZoom + */ + showResetZoom: function () { + var chart = this, lang = defaultOptions.lang, btnOptions = chart.options.chart.resetZoomButton, theme = btnOptions.theme, states = theme.states, alignTo = (btnOptions.relativeTo === 'chart' || + btnOptions.relativeTo === 'spaceBox' ? + null : + 'plotBox'); + /** + * @private + */ + function zoomOut() { + chart.zoomOut(); + } + fireEvent(this, 'beforeShowResetZoom', null, function () { + chart.resetZoomButton = chart.renderer + .button(lang.resetZoom, null, null, zoomOut, theme, states && states.hover) + .attr({ + align: btnOptions.position.align, + title: lang.resetZoomTitle + }) + .addClass('highcharts-reset-zoom') + .add() + .align(btnOptions.position, false, alignTo); + }); + fireEvent(this, 'afterShowResetZoom'); + }, + /** + * Zoom the chart out after a user has zoomed in. See also + * [Axis.setExtremes](/class-reference/Highcharts.Axis#setExtremes). + * + * @function Highcharts.Chart#zoomOut + * + * @fires Highcharts.Chart#event:selection + */ + zoomOut: function () { + fireEvent(this, 'selection', { resetSelection: true }, this.zoom); + }, + /** + * Zoom into a given portion of the chart given by axis coordinates. + * + * @private + * @function Highcharts.Chart#zoom + * @param {Highcharts.SelectEventObject} event + */ + zoom: function (event) { + var chart = this, hasZoomed, pointer = chart.pointer, displayButton = false, mouseDownPos = chart.inverted ? pointer.mouseDownX : pointer.mouseDownY, resetZoomButton; + // If zoom is called with no arguments, reset the axes + if (!event || event.resetSelection) { + chart.axes.forEach(function (axis) { + hasZoomed = axis.zoom(); + }); + pointer.initiated = false; // #6804 + } + else { // else, zoom in on all axes + event.xAxis.concat(event.yAxis).forEach(function (axisData) { + var axis = axisData.axis, axisStartPos = chart.inverted ? axis.left : axis.top, axisEndPos = chart.inverted ? + axisStartPos + axis.width : axisStartPos + axis.height, isXAxis = axis.isXAxis, isWithinPane = false; + // Check if zoomed area is within the pane (#1289). + // In case of multiple panes only one pane should be zoomed. + if ((!isXAxis && + mouseDownPos >= axisStartPos && + mouseDownPos <= axisEndPos) || + isXAxis || + !defined(mouseDownPos)) { + isWithinPane = true; + } + // don't zoom more than minRange + if (pointer[isXAxis ? 'zoomX' : 'zoomY'] && isWithinPane) { + hasZoomed = axis.zoom(axisData.min, axisData.max); + if (axis.displayBtn) { + displayButton = true; + } + } + }); + } + // Show or hide the Reset zoom button + resetZoomButton = chart.resetZoomButton; + if (displayButton && !resetZoomButton) { + chart.showResetZoom(); + } + else if (!displayButton && isObject(resetZoomButton)) { + chart.resetZoomButton = resetZoomButton.destroy(); + } + // Redraw + if (hasZoomed) { + chart.redraw(pick(chart.options.chart.animation, event && event.animation, chart.pointCount < 100)); + } + }, + /** + * Pan the chart by dragging the mouse across the pane. This function is + * called on mouse move, and the distance to pan is computed from chartX + * compared to the first chartX position in the dragging operation. + * + * @private + * @function Highcharts.Chart#pan + * @param {Highcharts.PointerEventObject} e + * @param {string} panning + */ + pan: function (e, panning) { + var chart = this, hoverPoints = chart.hoverPoints, panningOptions, chartOptions = chart.options.chart, hasMapNavigation = chart.options.mapNavigation && + chart.options.mapNavigation.enabled, doRedraw, type; + if (typeof panning === 'object') { + panningOptions = panning; + } + else { + panningOptions = { + enabled: panning, + type: 'x' + }; + } + if (chartOptions && chartOptions.panning) { + chartOptions.panning = panningOptions; + } + type = panningOptions.type; + fireEvent(this, 'pan', { originalEvent: e }, function () { + // remove active points for shared tooltip + if (hoverPoints) { + hoverPoints.forEach(function (point) { + point.setState(); + }); + } + // panning axis mapping + var xy = [1]; // x + if (type === 'xy') { + xy = [1, 0]; + } + else if (type === 'y') { + xy = [0]; + } + xy.forEach(function (isX) { + var axis = chart[isX ? 'xAxis' : 'yAxis'][0], axisOpt = axis.options, horiz = axis.horiz, mousePos = e[horiz ? 'chartX' : 'chartY'], mouseDown = horiz ? 'mouseDownX' : 'mouseDownY', startPos = chart[mouseDown], halfPointRange = (axis.pointRange || 0) / 2, pointRangeDirection = (axis.reversed && !chart.inverted) || + (!axis.reversed && chart.inverted) ? + -1 : + 1, extremes = axis.getExtremes(), panMin = axis.toValue(startPos - mousePos, true) + + halfPointRange * pointRangeDirection, panMax = axis.toValue(startPos + axis.len - mousePos, true) - + halfPointRange * pointRangeDirection, flipped = panMax < panMin, newMin = flipped ? panMax : panMin, newMax = flipped ? panMin : panMax, hasVerticalPanning = axis.hasVerticalPanning(), paddedMin, paddedMax, spill, panningState = axis.panningState; + // General calculations of panning state. + // This is related to using vertical panning. (#11315). + axis.series.forEach(function (series) { + if (hasVerticalPanning && + !isX && (!panningState || panningState.isDirty)) { + var processedData = series.getProcessedData(true), dataExtremes = series.getExtremes(processedData.yData, true); + if (!panningState) { + panningState = { + startMin: Number.MAX_VALUE, + startMax: -Number.MAX_VALUE + }; + } + if (isNumber(dataExtremes.dataMin) && + isNumber(dataExtremes.dataMax)) { + panningState.startMin = Math.min(dataExtremes.dataMin, panningState.startMin); + panningState.startMax = Math.max(dataExtremes.dataMax, panningState.startMax); + } + } + }); + paddedMin = Math.min(H.pick(panningState === null || panningState === void 0 ? void 0 : panningState.startMin, extremes.dataMin), halfPointRange ? + extremes.min : + axis.toValue(axis.toPixels(extremes.min) - + axis.minPixelPadding)); + paddedMax = Math.max(H.pick(panningState === null || panningState === void 0 ? void 0 : panningState.startMax, extremes.dataMax), halfPointRange ? + extremes.max : + axis.toValue(axis.toPixels(extremes.max) + + axis.minPixelPadding)); + axis.panningState = panningState; + // It is not necessary to calculate extremes on ordinal axis, + // because the are already calculated, so we don't want to + // override them. + if (!axisOpt.ordinal) { + // If the new range spills over, either to the min or max, + // adjust the new range. + spill = paddedMin - newMin; + if (spill > 0) { + newMax += spill; + newMin = paddedMin; + } + spill = newMax - paddedMax; + if (spill > 0) { + newMax = paddedMax; + newMin -= spill; + } + // Set new extremes if they are actually new + if (axis.series.length && + newMin !== extremes.min && + newMax !== extremes.max && + isX ? true : (panningState && + newMin >= paddedMin && + newMax <= paddedMax)) { + axis.setExtremes(newMin, newMax, false, false, { trigger: 'pan' }); + if (!chart.resetZoomButton && + !hasMapNavigation && + type.match('y')) { + chart.showResetZoom(); + axis.displayBtn = false; + } + doRedraw = true; + } + // set new reference for next run: + chart[mouseDown] = mousePos; + } + }); + if (doRedraw) { + chart.redraw(false); + } + css(chart.container, { cursor: 'move' }); + }); + } +}); +// Extend the Point object with interaction +extend(Point.prototype, /** @lends Highcharts.Point.prototype */ { + /** + * Toggle the selection status of a point. + * + * @see Highcharts.Chart#getSelectedPoints + * + * @sample highcharts/members/point-select/ + * Select a point from a button + * @sample highcharts/chart/events-selection-points/ + * Select a range of points through a drag selection + * @sample maps/series/data-id/ + * Select a point in Highmaps + * + * @function Highcharts.Point#select + * + * @param {boolean} [selected] + * When `true`, the point is selected. When `false`, the point is + * unselected. When `null` or `undefined`, the selection state is toggled. + * + * @param {boolean} [accumulate=false] + * When `true`, the selection is added to other selected points. + * When `false`, other selected points are deselected. Internally in + * Highcharts, when + * [allowPointSelect](https://api.highcharts.com/highcharts/plotOptions.series.allowPointSelect) + * is `true`, selected points are accumulated on Control, Shift or Cmd + * clicking the point. + * + * @fires Highcharts.Point#event:select + * @fires Highcharts.Point#event:unselect + */ + select: function (selected, accumulate) { + var point = this, series = point.series, chart = series.chart; + selected = pick(selected, !point.selected); + this.selectedStaging = selected; + // fire the event with the default handler + point.firePointEvent(selected ? 'select' : 'unselect', { accumulate: accumulate }, function () { + /** + * Whether the point is selected or not. + * + * @see Point#select + * @see Chart#getSelectedPoints + * + * @name Highcharts.Point#selected + * @type {boolean} + */ + point.selected = point.options.selected = selected; + series.options.data[series.data.indexOf(point)] = + point.options; + point.setState(selected && 'select'); + // unselect all other points unless Ctrl or Cmd + click + if (!accumulate) { + chart.getSelectedPoints().forEach(function (loopPoint) { + var loopSeries = loopPoint.series; + if (loopPoint.selected && loopPoint !== point) { + loopPoint.selected = loopPoint.options.selected = + false; + loopSeries.options.data[loopSeries.data.indexOf(loopPoint)] = loopPoint.options; + // Programatically selecting a point should restore + // normal state, but when click happened on other + // point, set inactive state to match other points + loopPoint.setState(chart.hoverPoints && + loopSeries.options.inactiveOtherPoints ? + 'inactive' : ''); + loopPoint.firePointEvent('unselect'); + } + }); + } + }); + delete this.selectedStaging; + }, + /** + * Runs on mouse over the point. Called internally from mouse and touch + * events. + * + * @function Highcharts.Point#onMouseOver + * + * @param {Highcharts.PointerEventObject} [e] + * The event arguments. + */ + onMouseOver: function (e) { + var point = this, series = point.series, chart = series.chart, pointer = chart.pointer; + e = e ? + pointer.normalize(e) : + // In cases where onMouseOver is called directly without an event + pointer.getChartCoordinatesFromPoint(point, chart.inverted); + pointer.runPointActions(e, point); + }, + /** + * Runs on mouse out from the point. Called internally from mouse and touch + * events. + * + * @function Highcharts.Point#onMouseOut + * @fires Highcharts.Point#event:mouseOut + */ + onMouseOut: function () { + var point = this, chart = point.series.chart; + point.firePointEvent('mouseOut'); + if (!point.series.options.inactiveOtherPoints) { + (chart.hoverPoints || []).forEach(function (p) { + p.setState(); + }); + } + chart.hoverPoints = chart.hoverPoint = null; + }, + /** + * Import events from the series' and point's options. Only do it on + * demand, to save processing time on hovering. + * + * @private + * @function Highcharts.Point#importEvents + */ + importEvents: function () { + if (!this.hasImportedEvents) { + var point = this, options = merge(point.series.options.point, point.options), events = options.events; + point.events = events; + objectEach(events, function (event, eventType) { + if (isFunction(event)) { + addEvent(point, eventType, event); + } + }); + this.hasImportedEvents = true; + } + }, + /** + * Set the point's state. + * + * @function Highcharts.Point#setState + * + * @param {Highcharts.PointStateValue|""} [state] + * The new state, can be one of `'hover'`, `'select'`, `'inactive'`, + * or `''` (an empty string), `'normal'` or `undefined` to set to + * normal state. + * @param {boolean} [move] + * State for animation. + * + * @fires Highcharts.Point#event:afterSetState + */ + setState: function (state, move) { + var point = this, series = point.series, previousState = point.state, stateOptions = (series.options.states[state || 'normal'] || + {}), markerOptions = (defaultPlotOptions[series.type].marker && + series.options.marker), normalDisabled = (markerOptions && markerOptions.enabled === false), markerStateOptions = ((markerOptions && + markerOptions.states && + markerOptions.states[state || 'normal']) || {}), stateDisabled = markerStateOptions.enabled === false, stateMarkerGraphic = series.stateMarkerGraphic, pointMarker = point.marker || {}, chart = series.chart, halo = series.halo, haloOptions, markerAttribs, pointAttribs, pointAttribsAnimation, hasMarkers = (markerOptions && series.markerAttribs), newSymbol; + state = state || ''; // empty string + if ( + // already has this state + (state === point.state && !move) || + // selected points don't respond to hover + (point.selected && state !== 'select') || + // series' state options is disabled + (stateOptions.enabled === false) || + // general point marker's state options is disabled + (state && (stateDisabled || + (normalDisabled && + markerStateOptions.enabled === false))) || + // individual point marker's state options is disabled + (state && + pointMarker.states && + pointMarker.states[state] && + pointMarker.states[state].enabled === false) // #1610 + ) { + return; + } + point.state = state; + if (hasMarkers) { + markerAttribs = series.markerAttribs(point, state); + } + // Apply hover styles to the existing point + if (point.graphic) { + if (previousState) { + point.graphic.removeClass('highcharts-point-' + previousState); + } + if (state) { + point.graphic.addClass('highcharts-point-' + state); + } + if (!chart.styledMode) { + pointAttribs = series.pointAttribs(point, state); + pointAttribsAnimation = pick(chart.options.chart.animation, stateOptions.animation); + // Some inactive points (e.g. slices in pie) should apply + // oppacity also for it's labels + if (series.options.inactiveOtherPoints && pointAttribs.opacity) { + (point.dataLabels || []).forEach(function (label) { + if (label) { + label.animate({ + opacity: pointAttribs.opacity + }, pointAttribsAnimation); + } + }); + if (point.connector) { + point.connector.animate({ + opacity: pointAttribs.opacity + }, pointAttribsAnimation); + } + } + point.graphic.animate(pointAttribs, pointAttribsAnimation); + } + if (markerAttribs) { + point.graphic.animate(markerAttribs, pick( + // Turn off globally: + chart.options.chart.animation, markerStateOptions.animation, markerOptions.animation)); + } + // Zooming in from a range with no markers to a range with markers + if (stateMarkerGraphic) { + stateMarkerGraphic.hide(); + } + } + else { + // if a graphic is not applied to each point in the normal state, + // create a shared graphic for the hover state + if (state && markerStateOptions) { + newSymbol = pointMarker.symbol || series.symbol; + // If the point has another symbol than the previous one, throw + // away the state marker graphic and force a new one (#1459) + if (stateMarkerGraphic && + stateMarkerGraphic.currentSymbol !== newSymbol) { + stateMarkerGraphic = stateMarkerGraphic.destroy(); + } + // Add a new state marker graphic + if (markerAttribs) { + if (!stateMarkerGraphic) { + if (newSymbol) { + series.stateMarkerGraphic = stateMarkerGraphic = + chart.renderer + .symbol(newSymbol, markerAttribs.x, markerAttribs.y, markerAttribs.width, markerAttribs.height) + .add(series.markerGroup); + stateMarkerGraphic.currentSymbol = newSymbol; + } + // Move the existing graphic + } + else { + stateMarkerGraphic[move ? 'animate' : 'attr']({ + x: markerAttribs.x, + y: markerAttribs.y + }); + } + } + if (!chart.styledMode && stateMarkerGraphic) { + stateMarkerGraphic.attr(series.pointAttribs(point, state)); + } + } + if (stateMarkerGraphic) { + stateMarkerGraphic[state && point.isInside ? 'show' : 'hide'](); // #2450 + stateMarkerGraphic.element.point = point; // #4310 + } + } + // Show me your halo + haloOptions = stateOptions.halo; + var markerGraphic = (point.graphic || stateMarkerGraphic); + var markerVisibility = (markerGraphic && markerGraphic.visibility || 'inherit'); + if (haloOptions && + haloOptions.size && + markerGraphic && + markerVisibility !== 'hidden' && + !point.isCluster) { + if (!halo) { + series.halo = halo = chart.renderer.path() + // #5818, #5903, #6705 + .add(markerGraphic.parentGroup); + } + halo.show()[move ? 'animate' : 'attr']({ + d: point.haloPath(haloOptions.size) + }); + halo.attr({ + 'class': 'highcharts-halo highcharts-color-' + + pick(point.colorIndex, series.colorIndex) + + (point.className ? ' ' + point.className : ''), + 'visibility': markerVisibility, + 'zIndex': -1 // #4929, #8276 + }); + halo.point = point; // #6055 + if (!chart.styledMode) { + halo.attr(extend({ + 'fill': point.color || series.color, + 'fill-opacity': haloOptions.opacity + }, haloOptions.attributes)); + } + } + else if (halo && halo.point && halo.point.haloPath) { + // Animate back to 0 on the current halo point (#6055) + halo.animate({ d: halo.point.haloPath(0) }, null, + // Hide after unhovering. The `complete` callback runs in the + // halo's context (#7681). + halo.hide); + } + fireEvent(point, 'afterSetState'); + }, + /** + * Get the path definition for the halo, which is usually a shadow-like + * circle around the currently hovered point. + * + * @function Highcharts.Point#haloPath + * + * @param {number} size + * The radius of the circular halo. + * + * @return {Highcharts.SVGPathArray} + * The path definition. + */ + haloPath: function (size) { + var series = this.series, chart = series.chart; + return chart.renderer.symbols.circle(Math.floor(this.plotX) - size, this.plotY - size, size * 2, size * 2); + } +}); +// Extend the Series object with interaction +extend(Series.prototype, /** @lends Highcharts.Series.prototype */ { + /** + * Runs on mouse over the series graphical items. + * + * @function Highcharts.Series#onMouseOver + * @fires Highcharts.Series#event:mouseOver + */ + onMouseOver: function () { + var series = this, chart = series.chart, hoverSeries = chart.hoverSeries, pointer = chart.pointer; + pointer.setHoverChartIndex(); + // set normal state to previous series + if (hoverSeries && hoverSeries !== series) { + hoverSeries.onMouseOut(); + } + // trigger the event, but to save processing time, + // only if defined + if (series.options.events.mouseOver) { + fireEvent(series, 'mouseOver'); + } + // hover this + series.setState('hover'); + /** + * Contains the original hovered series. + * + * @name Highcharts.Chart#hoverSeries + * @type {Highcharts.Series|null} + */ + chart.hoverSeries = series; + }, + /** + * Runs on mouse out of the series graphical items. + * + * @function Highcharts.Series#onMouseOut + * + * @fires Highcharts.Series#event:mouseOut + */ + onMouseOut: function () { + // trigger the event only if listeners exist + var series = this, options = series.options, chart = series.chart, tooltip = chart.tooltip, hoverPoint = chart.hoverPoint; + // #182, set to null before the mouseOut event fires + chart.hoverSeries = null; + // trigger mouse out on the point, which must be in this series + if (hoverPoint) { + hoverPoint.onMouseOut(); + } + // fire the mouse out event + if (series && options.events.mouseOut) { + fireEvent(series, 'mouseOut'); + } + // hide the tooltip + if (tooltip && + !series.stickyTracking && + (!tooltip.shared || series.noSharedTooltip)) { + tooltip.hide(); + } + // Reset all inactive states + chart.series.forEach(function (s) { + s.setState('', true); + }); + }, + /** + * Set the state of the series. Called internally on mouse interaction + * operations, but it can also be called directly to visually + * highlight a series. + * + * @function Highcharts.Series#setState + * + * @param {Highcharts.SeriesStateValue|""} [state] + * The new state, can be either `'hover'`, `'inactive'`, `'select'`, + * or `''` (an empty string), `'normal'` or `undefined` to set to + * normal state. + * @param {boolean} [inherit] + * Determines if state should be inherited by points too. + */ + setState: function (state, inherit) { + var series = this, options = series.options, graph = series.graph, inactiveOtherPoints = options.inactiveOtherPoints, stateOptions = options.states, lineWidth = options.lineWidth, opacity = options.opacity, + // By default a quick animation to hover/inactive, + // slower to un-hover + stateAnimation = pick((stateOptions[state || 'normal'] && + stateOptions[state || 'normal'].animation), series.chart.options.chart.animation), attribs, i = 0; + state = state || ''; + if (series.state !== state) { + // Toggle class names + [ + series.group, + series.markerGroup, + series.dataLabelsGroup + ].forEach(function (group) { + if (group) { + // Old state + if (series.state) { + group.removeClass('highcharts-series-' + series.state); + } + // New state + if (state) { + group.addClass('highcharts-series-' + state); + } + } + }); + series.state = state; + if (!series.chart.styledMode) { + if (stateOptions[state] && + stateOptions[state].enabled === false) { + return; + } + if (state) { + lineWidth = (stateOptions[state].lineWidth || + lineWidth + (stateOptions[state].lineWidthPlus || 0)); // #4035 + opacity = pick(stateOptions[state].opacity, opacity); + } + if (graph && !graph.dashstyle) { + attribs = { + 'stroke-width': lineWidth + }; + // Animate the graph stroke-width. + graph.animate(attribs, stateAnimation); + while (series['zone-graph-' + i]) { + series['zone-graph-' + i].attr(attribs); + i = i + 1; + } + } + // For some types (pie, networkgraph, sankey) opacity is + // resolved on a point level + if (!inactiveOtherPoints) { + [ + series.group, + series.markerGroup, + series.dataLabelsGroup, + series.labelBySeries + ].forEach(function (group) { + if (group) { + group.animate({ + opacity: opacity + }, stateAnimation); + } + }); + } + } + } + // Don't loop over points on a series that doesn't apply inactive state + // to siblings markers (e.g. line, column) + if (inherit && inactiveOtherPoints && series.points) { + series.setAllPointsToState(state); + } + }, + /** + * Set the state for all points in the series. + * + * @function Highcharts.Series#setAllPointsToState + * + * @private + * + * @param {string} [state] + * Can be either `hover` or undefined to set to normal state. + */ + setAllPointsToState: function (state) { + this.points.forEach(function (point) { + if (point.setState) { + point.setState(state); + } + }); + }, + /** + * Show or hide the series. + * + * @function Highcharts.Series#setVisible + * + * @param {boolean} [visible] + * True to show the series, false to hide. If undefined, the visibility is + * toggled. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the series is altered. If doing more + * operations on the chart, it is a good idea to set redraw to false and + * call {@link Chart#redraw|chart.redraw()} after. + * + * @fires Highcharts.Series#event:hide + * @fires Highcharts.Series#event:show + */ + setVisible: function (vis, redraw) { + var series = this, chart = series.chart, legendItem = series.legendItem, showOrHide, ignoreHiddenSeries = chart.options.chart.ignoreHiddenSeries, oldVisibility = series.visible; + // if called without an argument, toggle visibility + series.visible = + vis = + series.options.visible = + series.userOptions.visible = + typeof vis === 'undefined' ? !oldVisibility : vis; // #5618 + showOrHide = vis ? 'show' : 'hide'; + // show or hide elements + [ + 'group', + 'dataLabelsGroup', + 'markerGroup', + 'tracker', + 'tt' + ].forEach(function (key) { + if (series[key]) { + series[key][showOrHide](); + } + }); + // hide tooltip (#1361) + if (chart.hoverSeries === series || + (chart.hoverPoint && chart.hoverPoint.series) === series) { + series.onMouseOut(); + } + if (legendItem) { + chart.legend.colorizeItem(series, vis); + } + // rescale or adapt to resized chart + series.isDirty = true; + // in a stack, all other series are affected + if (series.options.stacking) { + chart.series.forEach(function (otherSeries) { + if (otherSeries.options.stacking && otherSeries.visible) { + otherSeries.isDirty = true; + } + }); + } + // show or hide linked series + series.linkedSeries.forEach(function (otherSeries) { + otherSeries.setVisible(vis, false); + }); + if (ignoreHiddenSeries) { + chart.isDirtyBox = true; + } + fireEvent(series, showOrHide); + if (redraw !== false) { + chart.redraw(); + } + }, + /** + * Show the series if hidden. + * + * @sample highcharts/members/series-hide/ + * Toggle visibility from a button + * + * @function Highcharts.Series#show + * @fires Highcharts.Series#event:show + */ + show: function () { + this.setVisible(true); + }, + /** + * Hide the series if visible. If the + * [chart.ignoreHiddenSeries](https://api.highcharts.com/highcharts/chart.ignoreHiddenSeries) + * option is true, the chart is redrawn without this series. + * + * @sample highcharts/members/series-hide/ + * Toggle visibility from a button + * + * @function Highcharts.Series#hide + * @fires Highcharts.Series#event:hide + */ + hide: function () { + this.setVisible(false); + }, + /** + * Select or unselect the series. This means its + * {@link Highcharts.Series.selected|selected} + * property is set, the checkbox in the legend is toggled and when selected, + * the series is returned by the {@link Highcharts.Chart#getSelectedSeries} + * function. + * + * @sample highcharts/members/series-select/ + * Select a series from a button + * + * @function Highcharts.Series#select + * + * @param {boolean} [selected] + * True to select the series, false to unselect. If undefined, the selection + * state is toggled. + * + * @fires Highcharts.Series#event:select + * @fires Highcharts.Series#event:unselect + */ + select: function (selected) { + var series = this; + series.selected = + selected = + this.options.selected = (typeof selected === 'undefined' ? + !series.selected : + selected); + if (series.checkbox) { + series.checkbox.checked = selected; + } + fireEvent(series, selected ? 'select' : 'unselect'); + }, + /** + * @private + * @borrows Highcharts.TrackerMixin.drawTrackerGraph as Highcharts.Series#drawTracker + */ + drawTracker: TrackerMixin.drawTrackerGraph +}); diff --git a/librerias/gantt/code/es-modules/parts/Legend.js b/librerias/gantt/code/es-modules/parts/Legend.js new file mode 100644 index 0000000..a36ee76 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/Legend.js @@ -0,0 +1,1114 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +/** + * Gets fired when the legend item belonging to a point is clicked. The default + * action is to toggle the visibility of the point. This can be prevented by + * returning `false` or calling `event.preventDefault()`. + * + * @callback Highcharts.PointLegendItemClickCallbackFunction + * + * @param {Highcharts.Point} this + * The point on which the event occured. + * + * @param {Highcharts.PointLegendItemClickEventObject} event + * The event that occured. + */ +/** + * Information about the legend click event. + * + * @interface Highcharts.PointLegendItemClickEventObject + */ /** +* Related browser event. +* @name Highcharts.PointLegendItemClickEventObject#browserEvent +* @type {Highcharts.PointerEvent} +*/ /** +* Prevent the default action of toggle the visibility of the point. +* @name Highcharts.PointLegendItemClickEventObject#preventDefault +* @type {Function} +*/ /** +* Related point. +* @name Highcharts.PointLegendItemClickEventObject#target +* @type {Highcharts.Point} +*/ /** +* Event type. +* @name Highcharts.PointLegendItemClickEventObject#type +* @type {"legendItemClick"} +*/ +/** + * Gets fired when the legend item belonging to a series is clicked. The default + * action is to toggle the visibility of the series. This can be prevented by + * returning `false` or calling `event.preventDefault()`. + * + * @callback Highcharts.SeriesLegendItemClickCallbackFunction + * + * @param {Highcharts.Series} this + * The series where the event occured. + * + * @param {Highcharts.SeriesLegendItemClickEventObject} event + * The event that occured. + */ +/** + * Information about the legend click event. + * + * @interface Highcharts.SeriesLegendItemClickEventObject + */ /** +* Related browser event. +* @name Highcharts.SeriesLegendItemClickEventObject#browserEvent +* @type {Highcharts.PointerEvent} +*/ /** +* Prevent the default action of toggle the visibility of the series. +* @name Highcharts.SeriesLegendItemClickEventObject#preventDefault +* @type {Function} +*/ /** +* Related series. +* @name Highcharts.SeriesLegendItemClickEventObject#target +* @type {Highcharts.Series} +*/ /** +* Event type. +* @name Highcharts.SeriesLegendItemClickEventObject#type +* @type {"legendItemClick"} +*/ +import U from './Utilities.js'; +var addEvent = U.addEvent, animObject = U.animObject, css = U.css, defined = U.defined, discardElement = U.discardElement, find = U.find, fireEvent = U.fireEvent, format = U.format, isNumber = U.isNumber, merge = U.merge, pick = U.pick, relativeLength = U.relativeLength, setAnimation = U.setAnimation, stableSort = U.stableSort, syncTimeout = U.syncTimeout, wrap = U.wrap; +var isFirefox = H.isFirefox, marginNames = H.marginNames, win = H.win; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * The overview of the chart's series. The legend object is instanciated + * internally in the chart constructor, and is available from the `chart.legend` + * property. Each chart has only one legend. + * + * @class + * @name Highcharts.Legend + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @param {Highcharts.LegendOptions} options + * Legend options. + */ +var Legend = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Legend(chart, options) { + /* * + * + * Properties + * + * */ + this.allItems = []; + this.box = void 0; + this.contentGroup = void 0; + this.display = false; + this.group = void 0; + this.initialItemY = 0; + this.itemHeight = 0; + this.itemMarginBottom = 0; + this.itemMarginTop = 0; + this.itemX = 0; + this.itemY = 0; + this.lastItemY = 0; + this.lastLineHeight = 0; + this.legendHeight = 0; + this.legendWidth = 0; + this.maxItemWidth = 0; + this.maxLegendWidth = 0; + this.offsetWidth = 0; + this.options = {}; + this.padding = 0; + this.pages = []; + this.proximate = false; + this.scrollGroup = void 0; + this.symbolHeight = 0; + this.symbolWidth = 0; + this.titleHeight = 0; + this.totalItemWidth = 0; + this.widthOption = 0; + this.chart = chart; + this.init(chart, options); + } + /* * + * + * Functions + * + * */ + /** + * Initialize the legend. + * + * @private + * @function Highcharts.Legend#init + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @param {Highcharts.LegendOptions} options + * Legend options. + */ + Legend.prototype.init = function (chart, options) { + /** + * Chart of this legend. + * + * @readonly + * @name Highcharts.Legend#chart + * @type {Highcharts.Chart} + */ + this.chart = chart; + this.setOptions(options); + if (options.enabled) { + // Render it + this.render(); + // move checkboxes + addEvent(this.chart, 'endResize', function () { + this.legend.positionCheckboxes(); + }); + if (this.proximate) { + this.unchartrender = addEvent(this.chart, 'render', function () { + this.legend.proximatePositions(); + this.legend.positionItems(); + }); + } + else if (this.unchartrender) { + this.unchartrender(); + } + } + }; + /** + * @private + * @function Highcharts.Legend#setOptions + * @param {Highcharts.LegendOptions} options + */ + Legend.prototype.setOptions = function (options) { + var padding = pick(options.padding, 8); + /** + * Legend options. + * + * @readonly + * @name Highcharts.Legend#options + * @type {Highcharts.LegendOptions} + */ + this.options = options; + if (!this.chart.styledMode) { + this.itemStyle = options.itemStyle; + this.itemHiddenStyle = merge(this.itemStyle, options.itemHiddenStyle); + } + this.itemMarginTop = options.itemMarginTop || 0; + this.itemMarginBottom = options.itemMarginBottom || 0; + this.padding = padding; + this.initialItemY = padding - 5; // 5 is pixels above the text + this.symbolWidth = pick(options.symbolWidth, 16); + this.pages = []; + this.proximate = options.layout === 'proximate' && !this.chart.inverted; + this.baseline = void 0; // #12705: baseline has to be reset on every update + }; + /** + * Update the legend with new options. Equivalent to running `chart.update` + * with a legend configuration option. + * + * @sample highcharts/legend/legend-update/ + * Legend update + * + * @function Highcharts.Legend#update + * + * @param {Highcharts.LegendOptions} options + * Legend options. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the axis is altered. If doing more + * operations on the chart, it is a good idea to set redraw to false and + * call {@link Chart#redraw} after. Whether to redraw the chart. + * + * @fires Highcharts.Legends#event:afterUpdate + */ + Legend.prototype.update = function (options, redraw) { + var chart = this.chart; + this.setOptions(merge(true, this.options, options)); + this.destroy(); + chart.isDirtyLegend = chart.isDirtyBox = true; + if (pick(redraw, true)) { + chart.redraw(); + } + fireEvent(this, 'afterUpdate'); + }; + /** + * Set the colors for the legend item. + * + * @private + * @function Highcharts.Legend#colorizeItem + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + * A Series or Point instance + * @param {boolean} [visible=false] + * Dimmed or colored + * + * @todo + * Make events official: Fires the event `afterColorizeItem`. + */ + Legend.prototype.colorizeItem = function (item, visible) { + item.legendGroup[visible ? 'removeClass' : 'addClass']('highcharts-legend-item-hidden'); + if (!this.chart.styledMode) { + var legend = this, options = legend.options, legendItem = item.legendItem, legendLine = item.legendLine, legendSymbol = item.legendSymbol, hiddenColor = legend.itemHiddenStyle.color, textColor = visible ? + options.itemStyle.color : + hiddenColor, symbolColor = visible ? + (item.color || hiddenColor) : + hiddenColor, markerOptions = item.options && item.options.marker, symbolAttr = { fill: symbolColor }; + if (legendItem) { + legendItem.css({ + fill: textColor, + color: textColor // #1553, oldIE + }); + } + if (legendLine) { + legendLine.attr({ stroke: symbolColor }); + } + if (legendSymbol) { + // Apply marker options + if (markerOptions && legendSymbol.isMarker) { // #585 + symbolAttr = item.pointAttribs(); + if (!visible) { + // #6769 + symbolAttr.stroke = symbolAttr.fill = hiddenColor; + } + } + legendSymbol.attr(symbolAttr); + } + } + fireEvent(this, 'afterColorizeItem', { item: item, visible: visible }); + }; + /** + * @private + * @function Highcharts.Legend#positionItems + */ + Legend.prototype.positionItems = function () { + // Now that the legend width and height are established, put the items + // in the final position + this.allItems.forEach(this.positionItem, this); + if (!this.chart.isResizing) { + this.positionCheckboxes(); + } + }; + /** + * Position the legend item. + * + * @private + * @function Highcharts.Legend#positionItem + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + * The item to position + */ + Legend.prototype.positionItem = function (item) { + var legend = this, options = legend.options, symbolPadding = options.symbolPadding, ltr = !options.rtl, legendItemPos = item._legendItemPos, itemX = legendItemPos[0], itemY = legendItemPos[1], checkbox = item.checkbox, legendGroup = item.legendGroup; + if (legendGroup && legendGroup.element) { + legendGroup[defined(legendGroup.translateY) ? 'animate' : 'attr']({ + translateX: ltr ? + itemX : + legend.legendWidth - itemX - 2 * symbolPadding - 4, + translateY: itemY + }); + } + if (checkbox) { + checkbox.x = itemX; + checkbox.y = itemY; + } + }; + /** + * Destroy a single legend item, used internally on removing series items. + * + * @private + * @function Highcharts.Legend#destroyItem + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + * The item to remove + */ + Legend.prototype.destroyItem = function (item) { + var checkbox = item.checkbox; + // destroy SVG elements + ['legendItem', 'legendLine', 'legendSymbol', 'legendGroup'].forEach(function (key) { + if (item[key]) { + item[key] = item[key].destroy(); + } + }); + if (checkbox) { + discardElement(item.checkbox); + } + }; + /** + * Destroy the legend. Used internally. To reflow objects, `chart.redraw` + * must be called after destruction. + * + * @private + * @function Highcharts.Legend#destroy + */ + Legend.prototype.destroy = function () { + /** + * @private + * @param {string} key + * @return {void} + */ + function destroyItems(key) { + if (this[key]) { + this[key] = this[key].destroy(); + } + } + // Destroy items + this.getAllItems().forEach(function (item) { + ['legendItem', 'legendGroup'].forEach(destroyItems, item); + }); + // Destroy legend elements + [ + 'clipRect', + 'up', + 'down', + 'pager', + 'nav', + 'box', + 'title', + 'group' + ].forEach(destroyItems, this); + this.display = null; // Reset in .render on update. + }; + /** + * Position the checkboxes after the width is determined. + * + * @private + * @function Highcharts.Legend#positionCheckboxes + */ + Legend.prototype.positionCheckboxes = function () { + var alignAttr = this.group && this.group.alignAttr, translateY, clipHeight = this.clipHeight || this.legendHeight, titleHeight = this.titleHeight; + if (alignAttr) { + translateY = alignAttr.translateY; + this.allItems.forEach(function (item) { + var checkbox = item.checkbox, top; + if (checkbox) { + top = translateY + titleHeight + checkbox.y + + (this.scrollOffset || 0) + 3; + css(checkbox, { + left: (alignAttr.translateX + item.checkboxOffset + + checkbox.x - 20) + 'px', + top: top + 'px', + display: this.proximate || (top > translateY - 6 && + top < translateY + clipHeight - 6) ? + '' : + 'none' + }); + } + }, this); + } + }; + /** + * Render the legend title on top of the legend. + * + * @private + * @function Highcharts.Legend#renderTitle + */ + Legend.prototype.renderTitle = function () { + var options = this.options, padding = this.padding, titleOptions = options.title, titleHeight = 0, bBox; + if (titleOptions.text) { + if (!this.title) { + /** + * SVG element of the legend title. + * + * @readonly + * @name Highcharts.Legend#title + * @type {Highcharts.SVGElement} + */ + this.title = this.chart.renderer.label(titleOptions.text, padding - 3, padding - 4, null, null, null, options.useHTML, null, 'legend-title') + .attr({ zIndex: 1 }); + if (!this.chart.styledMode) { + this.title.css(titleOptions.style); + } + this.title.add(this.group); + } + // Set the max title width (#7253) + if (!titleOptions.width) { + this.title.css({ + width: this.maxLegendWidth + 'px' + }); + } + bBox = this.title.getBBox(); + titleHeight = bBox.height; + this.offsetWidth = bBox.width; // #1717 + this.contentGroup.attr({ translateY: titleHeight }); + } + this.titleHeight = titleHeight; + }; + /** + * Set the legend item text. + * + * @function Highcharts.Legend#setText + * @param {Highcharts.Point|Highcharts.Series} item + * The item for which to update the text in the legend. + */ + Legend.prototype.setText = function (item) { + var options = this.options; + item.legendItem.attr({ + text: options.labelFormat ? + format(options.labelFormat, item, this.chart) : + options.labelFormatter.call(item) + }); + }; + /** + * Render a single specific legend item. Called internally from the `render` + * function. + * + * @private + * @function Highcharts.Legend#renderItem + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + * The item to render. + */ + Legend.prototype.renderItem = function (item) { + var legend = this, chart = legend.chart, renderer = chart.renderer, options = legend.options, horizontal = options.layout === 'horizontal', symbolWidth = legend.symbolWidth, symbolPadding = options.symbolPadding, itemStyle = legend.itemStyle, itemHiddenStyle = legend.itemHiddenStyle, itemDistance = horizontal ? pick(options.itemDistance, 20) : 0, ltr = !options.rtl, bBox, li = item.legendItem, isSeries = !item.series, series = !isSeries && item.series.drawLegendSymbol ? + item.series : + item, seriesOptions = series.options, showCheckbox = legend.createCheckboxForItem && + seriesOptions && + seriesOptions.showCheckbox, + // full width minus text width + itemExtraWidth = symbolWidth + symbolPadding + + itemDistance + (showCheckbox ? 20 : 0), useHTML = options.useHTML, itemClassName = item.options.className; + if (!li) { // generate it once, later move it + // Generate the group box, a group to hold the symbol and text. Text + // is to be appended in Legend class. + item.legendGroup = renderer + .g('legend-item') + .addClass('highcharts-' + series.type + '-series ' + + 'highcharts-color-' + item.colorIndex + + (itemClassName ? ' ' + itemClassName : '') + + (isSeries ? + ' highcharts-series-' + item.index : + '')) + .attr({ zIndex: 1 }) + .add(legend.scrollGroup); + // Generate the list item text and add it to the group + item.legendItem = li = renderer.text('', ltr ? + symbolWidth + symbolPadding : + -symbolPadding, legend.baseline || 0, useHTML); + if (!chart.styledMode) { + // merge to prevent modifying original (#1021) + li.css(merge(item.visible ? + itemStyle : + itemHiddenStyle)); + } + li + .attr({ + align: ltr ? 'left' : 'right', + zIndex: 2 + }) + .add(item.legendGroup); + // Get the baseline for the first item - the font size is equal for + // all + if (!legend.baseline) { + legend.fontMetrics = renderer.fontMetrics(chart.styledMode ? 12 : itemStyle.fontSize, li); + legend.baseline = + legend.fontMetrics.f + 3 + legend.itemMarginTop; + li.attr('y', legend.baseline); + } + // Draw the legend symbol inside the group box + legend.symbolHeight = + options.symbolHeight || legend.fontMetrics.f; + series.drawLegendSymbol(legend, item); + if (legend.setItemEvents) { + legend.setItemEvents(item, li, useHTML); + } + } + // Add the HTML checkbox on top + if (showCheckbox && !item.checkbox && legend.createCheckboxForItem) { + legend.createCheckboxForItem(item); + } + // Colorize the items + legend.colorizeItem(item, item.visible); + // Take care of max width and text overflow (#6659) + if (chart.styledMode || !itemStyle.width) { + li.css({ + width: ((options.itemWidth || + legend.widthOption || + chart.spacingBox.width) - itemExtraWidth) + 'px' + }); + } + // Always update the text + legend.setText(item); + // calculate the positions for the next line + bBox = li.getBBox(); + item.itemWidth = item.checkboxOffset = + options.itemWidth || + item.legendItemWidth || + bBox.width + itemExtraWidth; + legend.maxItemWidth = Math.max(legend.maxItemWidth, item.itemWidth); + legend.totalItemWidth += item.itemWidth; + legend.itemHeight = item.itemHeight = Math.round(item.legendItemHeight || bBox.height || legend.symbolHeight); + }; + /** + * Get the position of the item in the layout. We now know the + * maxItemWidth from the previous loop. + * + * @private + * @function Highcharts.Legend#layoutItem + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + */ + Legend.prototype.layoutItem = function (item) { + var options = this.options, padding = this.padding, horizontal = options.layout === 'horizontal', itemHeight = item.itemHeight, itemMarginBottom = this.itemMarginBottom, itemMarginTop = this.itemMarginTop, itemDistance = horizontal ? pick(options.itemDistance, 20) : 0, maxLegendWidth = this.maxLegendWidth, itemWidth = (options.alignColumns && + this.totalItemWidth > maxLegendWidth) ? + this.maxItemWidth : + item.itemWidth; + // If the item exceeds the width, start a new line + if (horizontal && + this.itemX - padding + itemWidth > maxLegendWidth) { + this.itemX = padding; + if (this.lastLineHeight) { // Not for the first line (#10167) + this.itemY += (itemMarginTop + + this.lastLineHeight + + itemMarginBottom); + } + this.lastLineHeight = 0; // reset for next line (#915, #3976) + } + // Set the edge positions + this.lastItemY = itemMarginTop + this.itemY + itemMarginBottom; + this.lastLineHeight = Math.max(// #915 + itemHeight, this.lastLineHeight); + // cache the position of the newly generated or reordered items + item._legendItemPos = [this.itemX, this.itemY]; + // advance + if (horizontal) { + this.itemX += itemWidth; + } + else { + this.itemY += + itemMarginTop + itemHeight + itemMarginBottom; + this.lastLineHeight = itemHeight; + } + // the width of the widest item + this.offsetWidth = this.widthOption || Math.max((horizontal ? this.itemX - padding - (item.checkbox ? + // decrease by itemDistance only when no checkbox #4853 + 0 : + itemDistance) : itemWidth) + padding, this.offsetWidth); + }; + /** + * Get all items, which is one item per series for most series and one + * item per point for pie series and its derivatives. Fires the event + * `afterGetAllItems`. + * + * @private + * @function Highcharts.Legend#getAllItems + * @return {Array<(Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series)>} + * The current items in the legend. + * @fires Highcharts.Legend#event:afterGetAllItems + */ + Legend.prototype.getAllItems = function () { + var allItems = []; + this.chart.series.forEach(function (series) { + var seriesOptions = series && series.options; + // Handle showInLegend. If the series is linked to another series, + // defaults to false. + if (series && pick(seriesOptions.showInLegend, !defined(seriesOptions.linkedTo) ? void 0 : false, true)) { + // Use points or series for the legend item depending on + // legendType + allItems = allItems.concat(series.legendItems || + (seriesOptions.legendType === 'point' ? + series.data : + series)); + } + }); + fireEvent(this, 'afterGetAllItems', { allItems: allItems }); + return allItems; + }; + /** + * Get a short, three letter string reflecting the alignment and layout. + * + * @private + * @function Highcharts.Legend#getAlignment + * @return {string} + * The alignment, empty string if floating + */ + Legend.prototype.getAlignment = function () { + var options = this.options; + // Use the first letter of each alignment option in order to detect + // the side. (#4189 - use charAt(x) notation instead of [x] for IE7) + if (this.proximate) { + return options.align.charAt(0) + 'tv'; + } + return options.floating ? '' : (options.align.charAt(0) + + options.verticalAlign.charAt(0) + + options.layout.charAt(0)); + }; + /** + * Adjust the chart margins by reserving space for the legend on only one + * side of the chart. If the position is set to a corner, top or bottom is + * reserved for horizontal legends and left or right for vertical ones. + * + * @private + * @function Highcharts.Legend#adjustMargins + * @param {Array} margin + * @param {Array} spacing + */ + Legend.prototype.adjustMargins = function (margin, spacing) { + var chart = this.chart, options = this.options, alignment = this.getAlignment(); + if (alignment) { + ([ + /(lth|ct|rth)/, + /(rtv|rm|rbv)/, + /(rbh|cb|lbh)/, + /(lbv|lm|ltv)/ + ]).forEach(function (alignments, side) { + if (alignments.test(alignment) && !defined(margin[side])) { + // Now we have detected on which side of the chart we should + // reserve space for the legend + chart[marginNames[side]] = Math.max(chart[marginNames[side]], (chart.legend[(side + 1) % 2 ? 'legendHeight' : 'legendWidth'] + + [1, -1, -1, 1][side] * options[(side % 2) ? 'x' : 'y'] + + pick(options.margin, 12) + + spacing[side] + + (chart.titleOffset[side] || 0))); + } + }); + } + }; + /** + * @private + * @function Highcharts.Legend#proximatePositions + */ + Legend.prototype.proximatePositions = function () { + var chart = this.chart, boxes = [], alignLeft = this.options.align === 'left'; + this.allItems.forEach(function (item) { + var lastPoint, height, useFirstPoint = alignLeft, target, top; + if (item.yAxis && item.points) { + if (item.xAxis.options.reversed) { + useFirstPoint = !useFirstPoint; + } + lastPoint = find(useFirstPoint ? + item.points : + item.points.slice(0).reverse(), function (item) { + return isNumber(item.plotY); + }); + height = this.itemMarginTop + + item.legendItem.getBBox().height + + this.itemMarginBottom; + top = item.yAxis.top - chart.plotTop; + if (item.visible) { + target = lastPoint ? + lastPoint.plotY : + item.yAxis.height; + target += top - 0.3 * height; + } + else { + target = top + item.yAxis.height; + } + boxes.push({ + target: target, + size: height, + item: item + }); + } + }, this); + H.distribute(boxes, chart.plotHeight); + boxes.forEach(function (box) { + box.item._legendItemPos[1] = + chart.plotTop - chart.spacing[0] + box.pos; + }); + }; + /** + * Render the legend. This method can be called both before and after + * `chart.render`. If called after, it will only rearrange items instead + * of creating new ones. Called internally on initial render and after + * redraws. + * + * @private + * @function Highcharts.Legend#render + */ + Legend.prototype.render = function () { + var legend = this, chart = legend.chart, renderer = chart.renderer, legendGroup = legend.group, allItems, display, legendWidth, legendHeight, box = legend.box, options = legend.options, padding = legend.padding, allowedWidth; + legend.itemX = padding; + legend.itemY = legend.initialItemY; + legend.offsetWidth = 0; + legend.lastItemY = 0; + legend.widthOption = relativeLength(options.width, chart.spacingBox.width - padding); + // Compute how wide the legend is allowed to be + allowedWidth = + chart.spacingBox.width - 2 * padding - options.x; + if (['rm', 'lm'].indexOf(legend.getAlignment().substring(0, 2)) > -1) { + allowedWidth /= 2; + } + legend.maxLegendWidth = legend.widthOption || allowedWidth; + if (!legendGroup) { + /** + * SVG group of the legend. + * + * @readonly + * @name Highcharts.Legend#group + * @type {Highcharts.SVGElement} + */ + legend.group = legendGroup = renderer.g('legend') + .attr({ zIndex: 7 }) + .add(); + legend.contentGroup = renderer.g() + .attr({ zIndex: 1 }) // above background + .add(legendGroup); + legend.scrollGroup = renderer.g() + .add(legend.contentGroup); + } + legend.renderTitle(); + // add each series or point + allItems = legend.getAllItems(); + // sort by legendIndex + stableSort(allItems, function (a, b) { + return ((a.options && a.options.legendIndex) || 0) - + ((b.options && b.options.legendIndex) || 0); + }); + // reversed legend + if (options.reversed) { + allItems.reverse(); + } + /** + * All items for the legend, which is an array of series for most series + * and an array of points for pie series and its derivatives. + * + * @readonly + * @name Highcharts.Legend#allItems + * @type {Array<(Highcharts.Point|Highcharts.Series)>} + */ + legend.allItems = allItems; + legend.display = display = !!allItems.length; + // Render the items. First we run a loop to set the text and properties + // and read all the bounding boxes. The next loop computes the item + // positions based on the bounding boxes. + legend.lastLineHeight = 0; + legend.maxItemWidth = 0; + legend.totalItemWidth = 0; + legend.itemHeight = 0; + allItems.forEach(legend.renderItem, legend); + allItems.forEach(legend.layoutItem, legend); + // Get the box + legendWidth = (legend.widthOption || legend.offsetWidth) + padding; + legendHeight = legend.lastItemY + legend.lastLineHeight + + legend.titleHeight; + legendHeight = legend.handleOverflow(legendHeight); + legendHeight += padding; + // Draw the border and/or background + if (!box) { + /** + * SVG element of the legend box. + * + * @readonly + * @name Highcharts.Legend#box + * @type {Highcharts.SVGElement} + */ + legend.box = box = renderer.rect() + .addClass('highcharts-legend-box') + .attr({ + r: options.borderRadius + }) + .add(legendGroup); + box.isNew = true; + } + // Presentational + if (!chart.styledMode) { + box + .attr({ + stroke: options.borderColor, + 'stroke-width': options.borderWidth || 0, + fill: options.backgroundColor || 'none' + }) + .shadow(options.shadow); + } + if (legendWidth > 0 && legendHeight > 0) { + box[box.isNew ? 'attr' : 'animate'](box.crisp.call({}, { + x: 0, + y: 0, + width: legendWidth, + height: legendHeight + }, box.strokeWidth())); + box.isNew = false; + } + // hide the border if no items + box[display ? 'show' : 'hide'](); + // Open for responsiveness + if (chart.styledMode && legendGroup.getStyle('display') === 'none') { + legendWidth = legendHeight = 0; + } + legend.legendWidth = legendWidth; + legend.legendHeight = legendHeight; + if (display) { + legend.align(); + } + if (!this.proximate) { + this.positionItems(); + } + fireEvent(this, 'afterRender'); + }; + /** + * Align the legend to chart's box. + * + * @private + * @function Highcharts.align + * @param {Highcharts.BBoxObject} alignTo + * @return {void} + */ + Legend.prototype.align = function (alignTo) { + if (alignTo === void 0) { alignTo = this.chart.spacingBox; } + var chart = this.chart, options = this.options; + // If aligning to the top and the layout is horizontal, adjust for + // the title (#7428) + var y = alignTo.y; + if (/(lth|ct|rth)/.test(this.getAlignment()) && + chart.titleOffset[0] > 0) { + y += chart.titleOffset[0]; + } + else if (/(lbh|cb|rbh)/.test(this.getAlignment()) && + chart.titleOffset[2] > 0) { + y -= chart.titleOffset[2]; + } + if (y !== alignTo.y) { + alignTo = merge(alignTo, { y: y }); + } + this.group.align(merge(options, { + width: this.legendWidth, + height: this.legendHeight, + verticalAlign: this.proximate ? 'top' : options.verticalAlign + }), true, alignTo); + }; + /** + * Set up the overflow handling by adding navigation with up and down arrows + * below the legend. + * + * @private + * @function Highcharts.Legend#handleOverflow + * @param {number} legendHeight + * @return {number} + */ + Legend.prototype.handleOverflow = function (legendHeight) { + var legend = this, chart = this.chart, renderer = chart.renderer, options = this.options, optionsY = options.y, alignTop = options.verticalAlign === 'top', padding = this.padding, spaceHeight = (chart.spacingBox.height + + (alignTop ? -optionsY : optionsY) - padding), maxHeight = options.maxHeight, clipHeight, clipRect = this.clipRect, navOptions = options.navigation, animation = pick(navOptions.animation, true), arrowSize = navOptions.arrowSize || 12, nav = this.nav, pages = this.pages, lastY, allItems = this.allItems, clipToHeight = function (height) { + if (typeof height === 'number') { + clipRect.attr({ + height: height + }); + } + else if (clipRect) { // Reset (#5912) + legend.clipRect = clipRect.destroy(); + legend.contentGroup.clip(); + } + // useHTML + if (legend.contentGroup.div) { + legend.contentGroup.div.style.clip = height ? + 'rect(' + padding + 'px,9999px,' + + (padding + height) + 'px,0)' : + 'auto'; + } + }, addTracker = function (key) { + legend[key] = renderer + .circle(0, 0, arrowSize * 1.3) + .translate(arrowSize / 2, arrowSize / 2) + .add(nav); + if (!chart.styledMode) { + legend[key].attr('fill', 'rgba(0,0,0,0.0001)'); + } + return legend[key]; + }; + // Adjust the height + if (options.layout === 'horizontal' && + options.verticalAlign !== 'middle' && + !options.floating) { + spaceHeight /= 2; + } + if (maxHeight) { + spaceHeight = Math.min(spaceHeight, maxHeight); + } + // Reset the legend height and adjust the clipping rectangle + pages.length = 0; + if (legendHeight > spaceHeight && + navOptions.enabled !== false) { + this.clipHeight = clipHeight = + Math.max(spaceHeight - 20 - this.titleHeight - padding, 0); + this.currentPage = pick(this.currentPage, 1); + this.fullHeight = legendHeight; + // Fill pages with Y positions so that the top of each a legend item + // defines the scroll top for each page (#2098) + allItems.forEach(function (item, i) { + var y = item._legendItemPos[1], h = Math.round(item.legendItem.getBBox().height), len = pages.length; + if (!len || (y - pages[len - 1] > clipHeight && + (lastY || y) !== pages[len - 1])) { + pages.push(lastY || y); + len++; + } + // Keep track of which page each item is on + item.pageIx = len - 1; + if (lastY) { + allItems[i - 1].pageIx = len - 1; + } + if (i === allItems.length - 1 && + y + h - pages[len - 1] > clipHeight && + y !== lastY // #2617 + ) { + pages.push(y); + item.pageIx = len; + } + if (y !== lastY) { + lastY = y; + } + }); + // Only apply clipping if needed. Clipping causes blurred legend in + // PDF export (#1787) + if (!clipRect) { + clipRect = legend.clipRect = + renderer.clipRect(0, padding, 9999, 0); + legend.contentGroup.clip(clipRect); + } + clipToHeight(clipHeight); + // Add navigation elements + if (!nav) { + this.nav = nav = renderer.g() + .attr({ zIndex: 1 }) + .add(this.group); + this.up = renderer + .symbol('triangle', 0, 0, arrowSize, arrowSize) + .add(nav); + addTracker('upTracker') + .on('click', function () { + legend.scroll(-1, animation); + }); + this.pager = renderer.text('', 15, 10) + .addClass('highcharts-legend-navigation'); + if (!chart.styledMode) { + this.pager.css(navOptions.style); + } + this.pager.add(nav); + this.down = renderer + .symbol('triangle-down', 0, 0, arrowSize, arrowSize) + .add(nav); + addTracker('downTracker') + .on('click', function () { + legend.scroll(1, animation); + }); + } + // Set initial position + legend.scroll(0); + legendHeight = spaceHeight; + // Reset + } + else if (nav) { + clipToHeight(); + this.nav = nav.destroy(); // #6322 + this.scrollGroup.attr({ + translateY: 1 + }); + this.clipHeight = 0; // #1379 + } + return legendHeight; + }; + /** + * Scroll the legend by a number of pages. + * + * @private + * @function Highcharts.Legend#scroll + * + * @param {number} scrollBy + * The number of pages to scroll. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * Whether and how to apply animation. + * + * @return {void} + */ + Legend.prototype.scroll = function (scrollBy, animation) { + var _this = this; + var chart = this.chart, pages = this.pages, pageCount = pages.length, currentPage = this.currentPage + scrollBy, clipHeight = this.clipHeight, navOptions = this.options.navigation, pager = this.pager, padding = this.padding; + // When resizing while looking at the last page + if (currentPage > pageCount) { + currentPage = pageCount; + } + if (currentPage > 0) { + if (typeof animation !== 'undefined') { + setAnimation(animation, chart); + } + this.nav.attr({ + translateX: padding, + translateY: clipHeight + this.padding + 7 + this.titleHeight, + visibility: 'visible' + }); + [this.up, this.upTracker].forEach(function (elem) { + elem.attr({ + 'class': currentPage === 1 ? + 'highcharts-legend-nav-inactive' : + 'highcharts-legend-nav-active' + }); + }); + pager.attr({ + text: currentPage + '/' + pageCount + }); + [this.down, this.downTracker].forEach(function (elem) { + elem.attr({ + // adjust to text width + x: 18 + this.pager.getBBox().width, + 'class': currentPage === pageCount ? + 'highcharts-legend-nav-inactive' : + 'highcharts-legend-nav-active' + }); + }, this); + if (!chart.styledMode) { + this.up + .attr({ + fill: currentPage === 1 ? + navOptions.inactiveColor : + navOptions.activeColor + }); + this.upTracker + .css({ + cursor: currentPage === 1 ? 'default' : 'pointer' + }); + this.down + .attr({ + fill: currentPage === pageCount ? + navOptions.inactiveColor : + navOptions.activeColor + }); + this.downTracker + .css({ + cursor: currentPage === pageCount ? + 'default' : + 'pointer' + }); + } + this.scrollOffset = -pages[currentPage - 1] + this.initialItemY; + this.scrollGroup.animate({ + translateY: this.scrollOffset + }); + this.currentPage = currentPage; + this.positionCheckboxes(); + // Fire event after scroll animation is complete + var animOptions = animObject(pick(animation, chart.renderer.globalAnimation, true)); + syncTimeout(function () { + fireEvent(_this, 'afterScroll', { currentPage: currentPage }); + }, animOptions.duration || 0); + } + }; + return Legend; +}()); +// Workaround for #2030, horizontal legend items not displaying in IE11 Preview, +// and for #2580, a similar drawing flaw in Firefox 26. +// Explore if there's a general cause for this. The problem may be related +// to nested group elements, as the legend item texts are within 4 group +// elements. +if (/Trident\/7\.0/.test(win.navigator && win.navigator.userAgent) || + isFirefox) { + wrap(Legend.prototype, 'positionItem', function (proceed, item) { + var legend = this, + // If chart destroyed in sync, this is undefined (#2030) + runPositionItem = function () { + if (item._legendItemPos) { + proceed.call(legend, item); + } + }; + // Do it now, for export and to get checkbox placement + runPositionItem(); + // Do it after to work around the core issue + if (!legend.bubbleLegend) { + setTimeout(runPositionItem); + } + }); +} +H.Legend = Legend; +export default H.Legend; diff --git a/librerias/gantt/code/es-modules/parts/LogarithmicAxis.js b/librerias/gantt/code/es-modules/parts/LogarithmicAxis.js new file mode 100644 index 0000000..1fab933 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/LogarithmicAxis.js @@ -0,0 +1,176 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Axis from './Axis.js'; +import U from './Utilities.js'; +var addEvent = U.addEvent, getMagnitude = U.getMagnitude, normalizeTickInterval = U.normalizeTickInterval, pick = U.pick; +/* eslint-disable valid-jsdoc */ +/** + * Provides logarithmic support for axes. + * + * @private + * @class + */ +var LogarithmicAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function LogarithmicAxisAdditions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Set the tick positions of a logarithmic axis. + */ + LogarithmicAxisAdditions.prototype.getLogTickPositions = function (interval, min, max, minor) { + var log = this; + var axis = log.axis; + var axisLength = axis.len; + var options = axis.options; + // Since we use this method for both major and minor ticks, + // use a local variable and return the result + var positions = []; + // Reset + if (!minor) { + log.minorAutoInterval = void 0; + } + // First case: All ticks fall on whole logarithms: 1, 10, 100 etc. + if (interval >= 0.5) { + interval = Math.round(interval); + positions = axis.getLinearTickPositions(interval, min, max); + // Second case: We need intermediary ticks. For example + // 1, 2, 4, 6, 8, 10, 20, 40 etc. + } + else if (interval >= 0.08) { + var roundedMin = Math.floor(min), intermediate, i, j, len, pos, lastPos, break2; + if (interval > 0.3) { + intermediate = [1, 2, 4]; + // 0.2 equals five minor ticks per 1, 10, 100 etc + } + else if (interval > 0.15) { + intermediate = [1, 2, 4, 6, 8]; + } + else { // 0.1 equals ten minor ticks per 1, 10, 100 etc + intermediate = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + } + for (i = roundedMin; i < max + 1 && !break2; i++) { + len = intermediate.length; + for (j = 0; j < len && !break2; j++) { + pos = log.log2lin(log.lin2log(i) * intermediate[j]); + // #1670, lastPos is #3113 + if (pos > min && + (!minor || lastPos <= max) && + typeof lastPos !== 'undefined') { + positions.push(lastPos); + } + if (lastPos > max) { + break2 = true; + } + lastPos = pos; + } + } + // Third case: We are so deep in between whole logarithmic values that + // we might as well handle the tick positions like a linear axis. For + // example 1.01, 1.02, 1.03, 1.04. + } + else { + var realMin = log.lin2log(min), realMax = log.lin2log(max), tickIntervalOption = minor ? + axis.getMinorTickInterval() : + options.tickInterval, filteredTickIntervalOption = tickIntervalOption === 'auto' ? + null : + tickIntervalOption, tickPixelIntervalOption = options.tickPixelInterval / (minor ? 5 : 1), totalPixelLength = minor ? + axisLength / axis.tickPositions.length : + axisLength; + interval = pick(filteredTickIntervalOption, log.minorAutoInterval, (realMax - realMin) * + tickPixelIntervalOption / (totalPixelLength || 1)); + interval = normalizeTickInterval(interval, void 0, getMagnitude(interval)); + positions = axis.getLinearTickPositions(interval, realMin, realMax).map(log.log2lin); + if (!minor) { + log.minorAutoInterval = interval / 5; + } + } + // Set the axis-level tickInterval variable + if (!minor) { + axis.tickInterval = interval; + } + return positions; + }; + LogarithmicAxisAdditions.prototype.lin2log = function (num) { + return Math.pow(10, num); + }; + LogarithmicAxisAdditions.prototype.log2lin = function (num) { + return Math.log(num) / Math.LN10; + }; + return LogarithmicAxisAdditions; +}()); +var LogarithmicAxis = /** @class */ (function () { + function LogarithmicAxis() { + } + /** + * Provides logarithmic support for axes. + * + * @private + */ + LogarithmicAxis.compose = function (AxisClass) { + AxisClass.keepProps.push('logarithmic'); + // HC <= 8 backwards compatibility, allow wrapping + // Axis.prototype.lin2log and log2lin + // @todo Remove this in next major + var axisProto = AxisClass.prototype; + var logAxisProto = LogarithmicAxisAdditions.prototype; + axisProto.log2lin = logAxisProto.log2lin; + axisProto.lin2log = logAxisProto.lin2log; + /* eslint-disable no-invalid-this */ + addEvent(AxisClass, 'init', function (e) { + var axis = this; + var options = e.userOptions; + var logarithmic = axis.logarithmic; + if (options.type !== 'logarithmic') { + axis.logarithmic = void 0; + } + else { + if (!logarithmic) { + logarithmic = axis.logarithmic = new LogarithmicAxisAdditions(axis); + } + // HC <= 8 backwards compatibility, allow wrapping + // Axis.prototype.lin2log and log2lin + // @todo Remove this in next major + if (axis.log2lin !== logarithmic.log2lin) { + logarithmic.log2lin = axis.log2lin.bind(axis); + } + if (axis.lin2log !== logarithmic.lin2log) { + logarithmic.lin2log = axis.lin2log.bind(axis); + } + } + }); + addEvent(AxisClass, 'afterInit', function () { + var axis = this; + var log = axis.logarithmic; + // extend logarithmic axis + if (log) { + axis.lin2val = function (num) { + return log.lin2log(num); + }; + axis.val2lin = function (num) { + return log.log2lin(num); + }; + } + }); + }; + return LogarithmicAxis; +}()); +LogarithmicAxis.compose(Axis); // @todo move to factory functions +export default LogarithmicAxis; diff --git a/librerias/gantt/code/es-modules/parts/MSPointer.js b/librerias/gantt/code/es-modules/parts/MSPointer.js new file mode 100644 index 0000000..f682731 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/MSPointer.js @@ -0,0 +1,160 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +import H from './Globals.js'; +/* globals MSPointerEvent, PointerEvent */ +import Pointer from './Pointer.js'; +import U from './Utilities.js'; +var addEvent = U.addEvent, css = U.css, objectEach = U.objectEach, removeEvent = U.removeEvent; +var charts = H.charts, doc = H.doc, noop = H.noop, win = H.win; +// The touches object keeps track of the points being touched at all times +var touches = {}; +var hasPointerEvent = !!win.PointerEvent; +/* eslint-disable valid-jsdoc */ +/** @private */ +function getWebkitTouches() { + var fake = []; + fake.item = function (i) { + return this[i]; + }; + objectEach(touches, function (touch) { + fake.push({ + pageX: touch.pageX, + pageY: touch.pageY, + target: touch.target + }); + }); + return fake; +} +/** @private */ +function translateMSPointer(e, method, wktype, func) { + var p; + if ((e.pointerType === 'touch' || + e.pointerType === e.MSPOINTER_TYPE_TOUCH) && charts[H.hoverChartIndex]) { + func(e); + p = charts[H.hoverChartIndex].pointer; + p[method]({ + type: wktype, + target: e.currentTarget, + preventDefault: noop, + touches: getWebkitTouches() + }); + } +} +/** @private */ +var MSPointer = /** @class */ (function (_super) { + __extends(MSPointer, _super); + function MSPointer() { + return _super !== null && _super.apply(this, arguments) || this; + } + /* * + * + * Functions + * + * */ + /** + * Add or remove the MS Pointer specific events + * + * @private + * @function Highcharts.Pointer#batchMSEvents + * + * @param {Function} fn + * + * @return {void} + */ + MSPointer.prototype.batchMSEvents = function (fn) { + fn(this.chart.container, hasPointerEvent ? 'pointerdown' : 'MSPointerDown', this.onContainerPointerDown); + fn(this.chart.container, hasPointerEvent ? 'pointermove' : 'MSPointerMove', this.onContainerPointerMove); + fn(doc, hasPointerEvent ? 'pointerup' : 'MSPointerUp', this.onDocumentPointerUp); + }; + // Destroy MS events also + MSPointer.prototype.destroy = function () { + this.batchMSEvents(removeEvent); + _super.prototype.destroy.call(this); + }; + // Disable default IE actions for pinch and such on chart element + MSPointer.prototype.init = function (chart, options) { + _super.prototype.init.call(this, chart, options); + if (this.hasZoom) { // #4014 + css(chart.container, { + '-ms-touch-action': 'none', + 'touch-action': 'none' + }); + } + }; + /** + * @private + * @function Highcharts.Pointer#onContainerPointerDown + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + MSPointer.prototype.onContainerPointerDown = function (e) { + translateMSPointer(e, 'onContainerTouchStart', 'touchstart', function (e) { + touches[e.pointerId] = { + pageX: e.pageX, + pageY: e.pageY, + target: e.currentTarget + }; + }); + }; + /** + * @private + * @function Highcharts.Pointer#onContainerPointerMove + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + MSPointer.prototype.onContainerPointerMove = function (e) { + translateMSPointer(e, 'onContainerTouchMove', 'touchmove', function (e) { + touches[e.pointerId] = ({ pageX: e.pageX, pageY: e.pageY }); + if (!touches[e.pointerId].target) { + touches[e.pointerId].target = e.currentTarget; + } + }); + }; + /** + * @private + * @function Highcharts.Pointer#onDocumentPointerUp + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + MSPointer.prototype.onDocumentPointerUp = function (e) { + translateMSPointer(e, 'onDocumentTouchEnd', 'touchend', function (e) { + delete touches[e.pointerId]; + }); + }; + // Add IE specific touch events to chart + MSPointer.prototype.setDOMEvents = function () { + _super.prototype.setDOMEvents.call(this); + if (this.hasZoom || this.followTouchMove) { + this.batchMSEvents(addEvent); + } + }; + return MSPointer; +}(Pointer)); +export default MSPointer; diff --git a/librerias/gantt/code/es-modules/parts/Navigator.js b/librerias/gantt/code/es-modules/parts/Navigator.js new file mode 100644 index 0000000..4202765 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/Navigator.js @@ -0,0 +1,1910 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Axis from './Axis.js'; +import Color from './Color.js'; +var color = Color.parse; +import H from './Globals.js'; +import NavigatorAxis from './NavigatorAxis.js'; +import Scrollbar from './Scrollbar.js'; +import U from './Utilities.js'; +var addEvent = U.addEvent, clamp = U.clamp, correctFloat = U.correctFloat, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, erase = U.erase, extend = U.extend, find = U.find, isArray = U.isArray, isNumber = U.isNumber, merge = U.merge, pick = U.pick, removeEvent = U.removeEvent, splat = U.splat; +import './Chart.js'; +import './Series.js'; +import './Options.js'; +var Chart = H.Chart, defaultOptions = H.defaultOptions, hasTouch = H.hasTouch, isTouchDevice = H.isTouchDevice, Series = H.Series, seriesTypes = H.seriesTypes, defaultSeriesType, +// Finding the min or max of a set of variables where we don't know if they +// are defined, is a pattern that is repeated several places in Highcharts. +// Consider making this a global utility method. +numExt = function (extreme) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + var numbers = [].filter.call(args, isNumber); + if (numbers.length) { + return Math[extreme].apply(0, numbers); + } +}; +defaultSeriesType = typeof seriesTypes.areaspline === 'undefined' ? + 'line' : + 'areaspline'; +extend(defaultOptions, { + /** + * Maximum range which can be set using the navigator's handles. + * Opposite of [xAxis.minRange](#xAxis.minRange). + * + * @sample {highstock} stock/navigator/maxrange/ + * Defined max and min range + * + * @type {number} + * @since 6.0.0 + * @product highstock gantt + * @apioption xAxis.maxRange + */ + /** + * The navigator is a small series below the main series, displaying + * a view of the entire data set. It provides tools to zoom in and + * out on parts of the data as well as panning across the dataset. + * + * @product highstock gantt + * @optionparent navigator + */ + navigator: { + /** + * Whether the navigator and scrollbar should adapt to updated data + * in the base X axis. When loading data async, as in the demo below, + * this should be `false`. Otherwise new data will trigger navigator + * redraw, which will cause unwanted looping. In the demo below, the + * data in the navigator is set only once. On navigating, only the main + * chart content is updated. + * + * @sample {highstock} stock/demo/lazy-loading/ + * Set to false with async data loading + * + * @type {boolean} + * @default true + * @apioption navigator.adaptToUpdatedData + */ + /** + * An integer identifying the index to use for the base series, or a + * string representing the id of the series. + * + * **Note**: As of Highcharts 5.0, this is now a deprecated option. + * Prefer [series.showInNavigator](#plotOptions.series.showInNavigator). + * + * @see [series.showInNavigator](#plotOptions.series.showInNavigator) + * + * @deprecated + * @type {number|string} + * @default 0 + * @apioption navigator.baseSeries + */ + /** + * Enable or disable the navigator. + * + * @sample {highstock} stock/navigator/enabled/ + * Disable the navigator + * + * @type {boolean} + * @default true + * @apioption navigator.enabled + */ + /** + * When the chart is inverted, whether to draw the navigator on the + * opposite side. + * + * @type {boolean} + * @default false + * @since 5.0.8 + * @apioption navigator.opposite + */ + /** + * The height of the navigator. + * + * @sample {highstock} stock/navigator/height/ + * A higher navigator + */ + height: 40, + /** + * The distance from the nearest element, the X axis or X axis labels. + * + * @sample {highstock} stock/navigator/margin/ + * A margin of 2 draws the navigator closer to the X axis labels + */ + margin: 25, + /** + * Whether the mask should be inside the range marking the zoomed + * range, or outside. In Highstock 1.x it was always `false`. + * + * @sample {highstock} stock/navigator/maskinside-false/ + * False, mask outside + * + * @since 2.0 + */ + maskInside: true, + /** + * Options for the handles for dragging the zoomed area. + * + * @sample {highstock} stock/navigator/handles/ + * Colored handles + */ + handles: { + /** + * Width for handles. + * + * @sample {highstock} stock/navigator/styled-handles/ + * Styled handles + * + * @since 6.0.0 + */ + width: 7, + /** + * Height for handles. + * + * @sample {highstock} stock/navigator/styled-handles/ + * Styled handles + * + * @since 6.0.0 + */ + height: 15, + /** + * Array to define shapes of handles. 0-index for left, 1-index for + * right. + * + * Additionally, the URL to a graphic can be given on this form: + * `url(graphic.png)`. Note that for the image to be applied to + * exported charts, its URL needs to be accessible by the export + * server. + * + * Custom callbacks for symbol path generation can also be added to + * `Highcharts.SVGRenderer.prototype.symbols`. The callback is then + * used by its method name, as shown in the demo. + * + * @sample {highstock} stock/navigator/styled-handles/ + * Styled handles + * + * @type {Array} + * @default ["navigator-handle", "navigator-handle"] + * @since 6.0.0 + */ + symbols: ['navigator-handle', 'navigator-handle'], + /** + * Allows to enable/disable handles. + * + * @since 6.0.0 + */ + enabled: true, + /** + * The width for the handle border and the stripes inside. + * + * @sample {highstock} stock/navigator/styled-handles/ + * Styled handles + * + * @since 6.0.0 + * @apioption navigator.handles.lineWidth + */ + lineWidth: 1, + /** + * The fill for the handle. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + backgroundColor: '#f2f2f2', + /** + * The stroke for the handle border and the stripes inside. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + borderColor: '#999999' + }, + /** + * The color of the mask covering the areas of the navigator series + * that are currently not visible in the main series. The default + * color is bluish with an opacity of 0.3 to see the series below. + * + * @see In styled mode, the mask is styled with the + * `.highcharts-navigator-mask` and + * `.highcharts-navigator-mask-inside` classes. + * + * @sample {highstock} stock/navigator/maskfill/ + * Blue, semi transparent mask + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default rgba(102,133,194,0.3) + */ + maskFill: color('#6685c2').setOpacity(0.3).get(), + /** + * The color of the line marking the currently zoomed area in the + * navigator. + * + * @sample {highstock} stock/navigator/outline/ + * 2px blue outline + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #cccccc + */ + outlineColor: '#cccccc', + /** + * The width of the line marking the currently zoomed area in the + * navigator. + * + * @see In styled mode, the outline stroke width is set with the + * `.highcharts-navigator-outline` class. + * + * @sample {highstock} stock/navigator/outline/ + * 2px blue outline + * + * @type {number} + */ + outlineWidth: 1, + /** + * Options for the navigator series. Available options are the same + * as any series, documented at [plotOptions](#plotOptions.series) + * and [series](#series). + * + * Unless data is explicitly defined on navigator.series, the data + * is borrowed from the first series in the chart. + * + * Default series options for the navigator series are: + * ```js + * series: { + * type: 'areaspline', + * fillOpacity: 0.05, + * dataGrouping: { + * smoothed: true + * }, + * lineWidth: 1, + * marker: { + * enabled: false + * } + * } + * ``` + * + * @see In styled mode, the navigator series is styled with the + * `.highcharts-navigator-series` class. + * + * @sample {highstock} stock/navigator/series-data/ + * Using a separate data set for the navigator + * @sample {highstock} stock/navigator/series/ + * A green navigator series + * + * @type {*|Array<*>|Highcharts.SeriesOptionsType|Array} + */ + series: { + /** + * The type of the navigator series. Defaults to `areaspline` if + * defined, otherwise `line`. + * + * Heads up: + * In column-type navigator, zooming is limited to at least one + * point with its `pointRange`. + * + * @sample {highstock} stock/navigator/column/ + * Column type navigator + * + * @type {string} + * @default areaspline + */ + type: defaultSeriesType, + /** + * The fill opacity of the navigator series. + */ + fillOpacity: 0.05, + /** + * The pixel line width of the navigator series. + */ + lineWidth: 1, + /** + * @ignore-option + */ + compare: null, + /** + * Unless data is explicitly defined, the data is borrowed from the + * first series in the chart. + * + * @type {Array|object|null>} + * @product highstock + * @apioption navigator.series.data + */ + /** + * Data grouping options for the navigator series. + * + * @extends plotOptions.series.dataGrouping + */ + dataGrouping: { + approximation: 'average', + enabled: true, + groupPixelWidth: 2, + smoothed: true, + // Day and week differs from plotOptions.series.dataGrouping + units: [ + ['millisecond', [1, 2, 5, 10, 20, 25, 50, 100, 200, 500]], + ['second', [1, 2, 5, 10, 15, 30]], + ['minute', [1, 2, 5, 10, 15, 30]], + ['hour', [1, 2, 3, 4, 6, 8, 12]], + ['day', [1, 2, 3, 4]], + ['week', [1, 2, 3]], + ['month', [1, 3, 6]], + ['year', null] + ] + }, + /** + * Data label options for the navigator series. Data labels are + * disabled by default on the navigator series. + * + * @extends plotOptions.series.dataLabels + */ + dataLabels: { + enabled: false, + zIndex: 2 // #1839 + }, + id: 'highcharts-navigator-series', + className: 'highcharts-navigator-series', + /** + * Sets the fill color of the navigator series. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption navigator.series.color + */ + /** + * Line color for the navigator series. Allows setting the color + * while disallowing the default candlestick setting. + * + * @type {Highcharts.ColorString|null} + */ + lineColor: null, + marker: { + enabled: false + }, + /** + * Since Highstock v8, default value is the same as default + * `pointRange` defined for a specific type (e.g. `null` for + * column type). + * + * In Highstock version < 8, defaults to 0. + * + * @extends plotOptions.series.pointRange + * @type {number|null} + * @apioption navigator.series.pointRange + */ + /** + * The threshold option. Setting it to 0 will make the default + * navigator area series draw its area from the 0 value and up. + * + * @type {number|null} + */ + threshold: null + }, + /** + * Options for the navigator X axis. Default series options for the + * navigator xAxis are: + * ```js + * xAxis: { + * tickWidth: 0, + * lineWidth: 0, + * gridLineWidth: 1, + * tickPixelInterval: 200, + * labels: { + * align: 'left', + * style: { + * color: '#888' + * }, + * x: 3, + * y: -4 + * } + * } + * ``` + * + * @extends xAxis + * @excluding linkedTo, maxZoom, minRange, opposite, range, scrollbar, + * showEmpty, maxRange + */ + xAxis: { + /** + * Additional range on the right side of the xAxis. Works similar to + * xAxis.maxPadding, but value is set in milliseconds. + * Can be set for both, main xAxis and navigator's xAxis. + * + * @since 6.0.0 + */ + overscroll: 0, + className: 'highcharts-navigator-xaxis', + tickLength: 0, + lineWidth: 0, + gridLineColor: '#e6e6e6', + gridLineWidth: 1, + tickPixelInterval: 200, + labels: { + align: 'left', + /** + * @type {Highcharts.CSSObject} + */ + style: { + /** @ignore */ + color: '#999999' + }, + x: 3, + y: -4 + }, + crosshair: false + }, + /** + * Options for the navigator Y axis. Default series options for the + * navigator yAxis are: + * ```js + * yAxis: { + * gridLineWidth: 0, + * startOnTick: false, + * endOnTick: false, + * minPadding: 0.1, + * maxPadding: 0.1, + * labels: { + * enabled: false + * }, + * title: { + * text: null + * }, + * tickWidth: 0 + * } + * ``` + * + * @extends yAxis + * @excluding height, linkedTo, maxZoom, minRange, ordinal, range, + * showEmpty, scrollbar, top, units, maxRange, minLength, + * maxLength, resize + */ + yAxis: { + className: 'highcharts-navigator-yaxis', + gridLineWidth: 0, + startOnTick: false, + endOnTick: false, + minPadding: 0.1, + maxPadding: 0.1, + labels: { + enabled: false + }, + crosshair: false, + title: { + text: null + }, + tickLength: 0, + tickWidth: 0 + } + } +}); +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * Draw one of the handles on the side of the zoomed range in the navigator + * + * @private + * @function Highcharts.Renderer#symbols.navigator-handle + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @param {Highcharts.NavigatorHandlesOptions} options + * @return {Highcharts.SVGPathArray} + * Path to be used in a handle + */ +H.Renderer.prototype.symbols['navigator-handle'] = function (x, y, w, h, options) { + var halfWidth = options.width / 2, markerPosition = Math.round(halfWidth / 3) + 0.5, height = options.height || 0; + return [ + ['M', -halfWidth - 1, 0.5], + ['L', halfWidth, 0.5], + ['L', halfWidth, height + 0.5], + ['L', -halfWidth - 1, height + 0.5], + ['L', -halfWidth - 1, 0.5], + ['M', -markerPosition, 4], + ['L', -markerPosition, height - 3], + ['M', markerPosition - 1, 4], + ['L', markerPosition - 1, height - 3] + ]; +}; +/** + * The Navigator class + * + * @private + * @class + * @name Highcharts.Navigator + * + * @param {Highcharts.Chart} chart + * Chart object + */ +var Navigator = /** @class */ (function () { + function Navigator(chart) { + this.baseSeries = void 0; + this.chart = void 0; + this.handles = void 0; + this.height = void 0; + this.left = void 0; + this.navigatorEnabled = void 0; + this.navigatorGroup = void 0; + this.navigatorOptions = void 0; + this.navigatorSeries = void 0; + this.navigatorSize = void 0; + this.opposite = void 0; + this.outline = void 0; + this.outlineHeight = void 0; + this.range = void 0; + this.rendered = void 0; + this.shades = void 0; + this.size = void 0; + this.top = void 0; + this.xAxis = void 0; + this.yAxis = void 0; + this.zoomedMax = void 0; + this.zoomedMin = void 0; + this.init(chart); + } + /** + * Draw one of the handles on the side of the zoomed range in the navigator + * + * @private + * @function Highcharts.Navigator#drawHandle + * + * @param {number} x + * The x center for the handle + * + * @param {number} index + * 0 for left and 1 for right + * + * @param {boolean|undefined} inverted + * flag for chart.inverted + * + * @param {string} verb + * use 'animate' or 'attr' + */ + Navigator.prototype.drawHandle = function (x, index, inverted, verb) { + var navigator = this, height = navigator.navigatorOptions.handles.height; + // Place it + navigator.handles[index][verb](inverted ? { + translateX: Math.round(navigator.left + navigator.height / 2), + translateY: Math.round(navigator.top + parseInt(x, 10) + 0.5 - height) + } : { + translateX: Math.round(navigator.left + parseInt(x, 10)), + translateY: Math.round(navigator.top + navigator.height / 2 - height / 2 - 1) + }); + }; + /** + * Render outline around the zoomed range + * + * @private + * @function Highcharts.Navigator#drawOutline + * + * @param {number} zoomedMin + * in pixels position where zoomed range starts + * + * @param {number} zoomedMax + * in pixels position where zoomed range ends + * + * @param {boolean|undefined} inverted + * flag if chart is inverted + * + * @param {string} verb + * use 'animate' or 'attr' + */ + Navigator.prototype.drawOutline = function (zoomedMin, zoomedMax, inverted, verb) { + var navigator = this, maskInside = navigator.navigatorOptions.maskInside, outlineWidth = navigator.outline.strokeWidth(), halfOutline = outlineWidth / 2, outlineCorrection = (outlineWidth % 2) / 2, // #5800 + outlineHeight = navigator.outlineHeight, scrollbarHeight = navigator.scrollbarHeight || 0, navigatorSize = navigator.size, left = navigator.left - scrollbarHeight, navigatorTop = navigator.top, verticalMin, path; + if (inverted) { + left -= halfOutline; + verticalMin = navigatorTop + zoomedMax + outlineCorrection; + zoomedMax = navigatorTop + zoomedMin + outlineCorrection; + path = [ + ['M', left + outlineHeight, navigatorTop - scrollbarHeight - outlineCorrection], + ['L', left + outlineHeight, verticalMin], + ['L', left, verticalMin], + ['L', left, zoomedMax], + ['L', left + outlineHeight, zoomedMax], + ['L', left + outlineHeight, navigatorTop + navigatorSize + scrollbarHeight] + ]; + if (maskInside) { + path.push(['M', left + outlineHeight, verticalMin - halfOutline], // upper left of zoomed range + ['L', left + outlineHeight, zoomedMax + halfOutline] // upper right of z.r. + ); + } + } + else { + zoomedMin += left + scrollbarHeight - outlineCorrection; + zoomedMax += left + scrollbarHeight - outlineCorrection; + navigatorTop += halfOutline; + path = [ + ['M', left, navigatorTop], + ['L', zoomedMin, navigatorTop], + ['L', zoomedMin, navigatorTop + outlineHeight], + ['L', zoomedMax, navigatorTop + outlineHeight], + ['L', zoomedMax, navigatorTop], + ['L', left + navigatorSize + scrollbarHeight * 2, navigatorTop] // right + ]; + if (maskInside) { + path.push(['M', zoomedMin - halfOutline, navigatorTop], // upper left of zoomed range + ['L', zoomedMax + halfOutline, navigatorTop] // upper right of z.r. + ); + } + } + navigator.outline[verb]({ + d: path + }); + }; + /** + * Render outline around the zoomed range + * + * @private + * @function Highcharts.Navigator#drawMasks + * + * @param {number} zoomedMin + * in pixels position where zoomed range starts + * + * @param {number} zoomedMax + * in pixels position where zoomed range ends + * + * @param {boolean|undefined} inverted + * flag if chart is inverted + * + * @param {string} verb + * use 'animate' or 'attr' + */ + Navigator.prototype.drawMasks = function (zoomedMin, zoomedMax, inverted, verb) { + var navigator = this, left = navigator.left, top = navigator.top, navigatorHeight = navigator.height, height, width, x, y; + // Determine rectangle position & size + // According to (non)inverted position: + if (inverted) { + x = [left, left, left]; + y = [top, top + zoomedMin, top + zoomedMax]; + width = [navigatorHeight, navigatorHeight, navigatorHeight]; + height = [ + zoomedMin, + zoomedMax - zoomedMin, + navigator.size - zoomedMax + ]; + } + else { + x = [left, left + zoomedMin, left + zoomedMax]; + y = [top, top, top]; + width = [ + zoomedMin, + zoomedMax - zoomedMin, + navigator.size - zoomedMax + ]; + height = [navigatorHeight, navigatorHeight, navigatorHeight]; + } + navigator.shades.forEach(function (shade, i) { + shade[verb]({ + x: x[i], + y: y[i], + width: width[i], + height: height[i] + }); + }); + }; + /** + * Generate DOM elements for a navigator: + * + * - main navigator group + * + * - all shades + * + * - outline + * + * - handles + * + * @private + * @function Highcharts.Navigator#renderElements + */ + Navigator.prototype.renderElements = function () { + var navigator = this, navigatorOptions = navigator.navigatorOptions, maskInside = navigatorOptions.maskInside, chart = navigator.chart, inverted = chart.inverted, renderer = chart.renderer, navigatorGroup, mouseCursor = { + cursor: inverted ? 'ns-resize' : 'ew-resize' + }; + // Create the main navigator group + navigator.navigatorGroup = navigatorGroup = renderer.g('navigator') + .attr({ + zIndex: 8, + visibility: 'hidden' + }) + .add(); + // Create masks, each mask will get events and fill: + [ + !maskInside, + maskInside, + !maskInside + ].forEach(function (hasMask, index) { + navigator.shades[index] = renderer.rect() + .addClass('highcharts-navigator-mask' + + (index === 1 ? '-inside' : '-outside')) + .add(navigatorGroup); + if (!chart.styledMode) { + navigator.shades[index] + .attr({ + fill: hasMask ? + navigatorOptions.maskFill : + 'rgba(0,0,0,0)' + }) + .css((index === 1) && mouseCursor); + } + }); + // Create the outline: + navigator.outline = renderer.path() + .addClass('highcharts-navigator-outline') + .add(navigatorGroup); + if (!chart.styledMode) { + navigator.outline.attr({ + 'stroke-width': navigatorOptions.outlineWidth, + stroke: navigatorOptions.outlineColor + }); + } + // Create the handlers: + if (navigatorOptions.handles.enabled) { + [0, 1].forEach(function (index) { + navigatorOptions.handles.inverted = chart.inverted; + navigator.handles[index] = renderer.symbol(navigatorOptions.handles.symbols[index], -navigatorOptions.handles.width / 2 - 1, 0, navigatorOptions.handles.width, navigatorOptions.handles.height, navigatorOptions.handles); + // zIndex = 6 for right handle, 7 for left. + // Can't be 10, because of the tooltip in inverted chart #2908 + navigator.handles[index].attr({ zIndex: 7 - index }) + .addClass('highcharts-navigator-handle ' + + 'highcharts-navigator-handle-' + + ['left', 'right'][index]).add(navigatorGroup); + if (!chart.styledMode) { + var handlesOptions = navigatorOptions.handles; + navigator.handles[index] + .attr({ + fill: handlesOptions.backgroundColor, + stroke: handlesOptions.borderColor, + 'stroke-width': handlesOptions.lineWidth + }) + .css(mouseCursor); + } + }); + } + }; + /** + * Update navigator + * + * @private + * @function Highcharts.Navigator#update + * + * @param {Highcharts.NavigatorOptions} options + * Options to merge in when updating navigator + */ + Navigator.prototype.update = function (options) { + // Remove references to old navigator series in base series + (this.series || []).forEach(function (series) { + if (series.baseSeries) { + delete series.baseSeries.navigatorSeries; + } + }); + // Destroy and rebuild navigator + this.destroy(); + var chartOptions = this.chart.options; + merge(true, chartOptions.navigator, this.options, options); + this.init(this.chart); + }; + /** + * Render the navigator + * + * @private + * @function Highcharts.Navigator#render + * @param {number} min + * X axis value minimum + * @param {number} max + * X axis value maximum + * @param {number} [pxMin] + * Pixel value minimum + * @param {number} [pxMax] + * Pixel value maximum + * @return {void} + */ + Navigator.prototype.render = function (min, max, pxMin, pxMax) { + var navigator = this, chart = navigator.chart, navigatorWidth, scrollbarLeft, scrollbarTop, scrollbarHeight = navigator.scrollbarHeight, navigatorSize, xAxis = navigator.xAxis, pointRange = xAxis.pointRange || 0, scrollbarXAxis = xAxis.navigatorAxis.fake ? chart.xAxis[0] : xAxis, navigatorEnabled = navigator.navigatorEnabled, zoomedMin, zoomedMax, rendered = navigator.rendered, inverted = chart.inverted, verb, newMin, newMax, currentRange, minRange = chart.xAxis[0].minRange, maxRange = chart.xAxis[0].options.maxRange; + // Don't redraw while moving the handles (#4703). + if (this.hasDragged && !defined(pxMin)) { + return; + } + min = correctFloat(min - pointRange / 2); + max = correctFloat(max + pointRange / 2); + // Don't render the navigator until we have data (#486, #4202, #5172). + if (!isNumber(min) || !isNumber(max)) { + // However, if navigator was already rendered, we may need to resize + // it. For example hidden series, but visible navigator (#6022). + if (rendered) { + pxMin = 0; + pxMax = pick(xAxis.width, scrollbarXAxis.width); + } + else { + return; + } + } + navigator.left = pick(xAxis.left, + // in case of scrollbar only, without navigator + chart.plotLeft + scrollbarHeight + + (inverted ? chart.plotWidth : 0)); + navigator.size = zoomedMax = navigatorSize = pick(xAxis.len, (inverted ? chart.plotHeight : chart.plotWidth) - + 2 * scrollbarHeight); + if (inverted) { + navigatorWidth = scrollbarHeight; + } + else { + navigatorWidth = navigatorSize + 2 * scrollbarHeight; + } + // Get the pixel position of the handles + pxMin = pick(pxMin, xAxis.toPixels(min, true)); + pxMax = pick(pxMax, xAxis.toPixels(max, true)); + // Verify (#1851, #2238) + if (!isNumber(pxMin) || Math.abs(pxMin) === Infinity) { + pxMin = 0; + pxMax = navigatorWidth; + } + // Are we below the minRange? (#2618, #6191) + newMin = xAxis.toValue(pxMin, true); + newMax = xAxis.toValue(pxMax, true); + currentRange = Math.abs(correctFloat(newMax - newMin)); + if (currentRange < minRange) { + if (this.grabbedLeft) { + pxMin = xAxis.toPixels(newMax - minRange - pointRange, true); + } + else if (this.grabbedRight) { + pxMax = xAxis.toPixels(newMin + minRange + pointRange, true); + } + } + else if (defined(maxRange) && + correctFloat(currentRange - pointRange) > maxRange) { + if (this.grabbedLeft) { + pxMin = xAxis.toPixels(newMax - maxRange - pointRange, true); + } + else if (this.grabbedRight) { + pxMax = xAxis.toPixels(newMin + maxRange + pointRange, true); + } + } + // Handles are allowed to cross, but never exceed the plot area + navigator.zoomedMax = clamp(Math.max(pxMin, pxMax), 0, zoomedMax); + navigator.zoomedMin = clamp(navigator.fixedWidth ? + navigator.zoomedMax - navigator.fixedWidth : + Math.min(pxMin, pxMax), 0, zoomedMax); + navigator.range = navigator.zoomedMax - navigator.zoomedMin; + zoomedMax = Math.round(navigator.zoomedMax); + zoomedMin = Math.round(navigator.zoomedMin); + if (navigatorEnabled) { + navigator.navigatorGroup.attr({ + visibility: 'visible' + }); + // Place elements + verb = rendered && !navigator.hasDragged ? 'animate' : 'attr'; + navigator.drawMasks(zoomedMin, zoomedMax, inverted, verb); + navigator.drawOutline(zoomedMin, zoomedMax, inverted, verb); + if (navigator.navigatorOptions.handles.enabled) { + navigator.drawHandle(zoomedMin, 0, inverted, verb); + navigator.drawHandle(zoomedMax, 1, inverted, verb); + } + } + if (navigator.scrollbar) { + if (inverted) { + scrollbarTop = navigator.top - scrollbarHeight; + scrollbarLeft = navigator.left - scrollbarHeight + + (navigatorEnabled || !scrollbarXAxis.opposite ? 0 : + // Multiple axes has offsets: + (scrollbarXAxis.titleOffset || 0) + + // Self margin from the axis.title + scrollbarXAxis.axisTitleMargin); + scrollbarHeight = navigatorSize + 2 * scrollbarHeight; + } + else { + scrollbarTop = navigator.top + (navigatorEnabled ? + navigator.height : + -scrollbarHeight); + scrollbarLeft = navigator.left - scrollbarHeight; + } + // Reposition scrollbar + navigator.scrollbar.position(scrollbarLeft, scrollbarTop, navigatorWidth, scrollbarHeight); + // Keep scale 0-1 + navigator.scrollbar.setRange( + // Use real value, not rounded because range can be very small + // (#1716) + navigator.zoomedMin / (navigatorSize || 1), navigator.zoomedMax / (navigatorSize || 1)); + } + navigator.rendered = true; + }; + /** + * Set up the mouse and touch events for the navigator + * + * @private + * @function Highcharts.Navigator#addMouseEvents + */ + Navigator.prototype.addMouseEvents = function () { + var navigator = this, chart = navigator.chart, container = chart.container, eventsToUnbind = [], mouseMoveHandler, mouseUpHandler; + /** + * Create mouse events' handlers. + * Make them as separate functions to enable wrapping them: + */ + navigator.mouseMoveHandler = mouseMoveHandler = function (e) { + navigator.onMouseMove(e); + }; + navigator.mouseUpHandler = mouseUpHandler = function (e) { + navigator.onMouseUp(e); + }; + // Add shades and handles mousedown events + eventsToUnbind = navigator.getPartsEvents('mousedown'); + // Add mouse move and mouseup events. These are bind to doc/container, + // because Navigator.grabbedSomething flags are stored in mousedown + // events + eventsToUnbind.push(addEvent(chart.renderTo, 'mousemove', mouseMoveHandler), addEvent(container.ownerDocument, 'mouseup', mouseUpHandler)); + // Touch events + if (hasTouch) { + eventsToUnbind.push(addEvent(chart.renderTo, 'touchmove', mouseMoveHandler), addEvent(container.ownerDocument, 'touchend', mouseUpHandler)); + eventsToUnbind.concat(navigator.getPartsEvents('touchstart')); + } + navigator.eventsToUnbind = eventsToUnbind; + // Data events + if (navigator.series && navigator.series[0]) { + eventsToUnbind.push(addEvent(navigator.series[0].xAxis, 'foundExtremes', function () { + chart.navigator.modifyNavigatorAxisExtremes(); + })); + } + }; + /** + * Generate events for handles and masks + * + * @private + * @function Highcharts.Navigator#getPartsEvents + * + * @param {string} eventName + * Event name handler, 'mousedown' or 'touchstart' + * + * @return {Array} + * An array of functions to remove navigator functions from the + * events again. + */ + Navigator.prototype.getPartsEvents = function (eventName) { + var navigator = this, events = []; + ['shades', 'handles'].forEach(function (name) { + navigator[name].forEach(function (navigatorItem, index) { + events.push(addEvent(navigatorItem.element, eventName, function (e) { + navigator[name + 'Mousedown'](e, index); + })); + }); + }); + return events; + }; + /** + * Mousedown on a shaded mask, either: + * + * - will be stored for future drag&drop + * + * - will directly shift to a new range + * + * @private + * @function Highcharts.Navigator#shadesMousedown + * + * @param {Highcharts.PointerEventObject} e + * Mouse event + * + * @param {number} index + * Index of a mask in Navigator.shades array + */ + Navigator.prototype.shadesMousedown = function (e, index) { + e = this.chart.pointer.normalize(e); + var navigator = this, chart = navigator.chart, xAxis = navigator.xAxis, zoomedMin = navigator.zoomedMin, navigatorPosition = navigator.left, navigatorSize = navigator.size, range = navigator.range, chartX = e.chartX, fixedMax, fixedMin, ext, left; + // For inverted chart, swap some options: + if (chart.inverted) { + chartX = e.chartY; + navigatorPosition = navigator.top; + } + if (index === 1) { + // Store information for drag&drop + navigator.grabbedCenter = chartX; + navigator.fixedWidth = range; + navigator.dragOffset = chartX - zoomedMin; + } + else { + // Shift the range by clicking on shaded areas + left = chartX - navigatorPosition - range / 2; + if (index === 0) { + left = Math.max(0, left); + } + else if (index === 2 && left + range >= navigatorSize) { + left = navigatorSize - range; + if (navigator.reversedExtremes) { + // #7713 + left -= range; + fixedMin = navigator.getUnionExtremes().dataMin; + } + else { + // #2293, #3543 + fixedMax = navigator.getUnionExtremes().dataMax; + } + } + if (left !== zoomedMin) { // it has actually moved + navigator.fixedWidth = range; // #1370 + ext = xAxis.navigatorAxis.toFixedRange(left, left + range, fixedMin, fixedMax); + if (defined(ext.min)) { // #7411 + chart.xAxis[0].setExtremes(Math.min(ext.min, ext.max), Math.max(ext.min, ext.max), true, null, // auto animation + { trigger: 'navigator' }); + } + } + } + }; + /** + * Mousedown on a handle mask. + * Will store necessary information for drag&drop. + * + * @private + * @function Highcharts.Navigator#handlesMousedown + * @param {Highcharts.PointerEventObject} e + * Mouse event + * @param {number} index + * Index of a handle in Navigator.handles array + * @return {void} + */ + Navigator.prototype.handlesMousedown = function (e, index) { + e = this.chart.pointer.normalize(e); + var navigator = this, chart = navigator.chart, baseXAxis = chart.xAxis[0], + // For reversed axes, min and max are changed, + // so the other extreme should be stored + reverse = navigator.reversedExtremes; + if (index === 0) { + // Grab the left handle + navigator.grabbedLeft = true; + navigator.otherHandlePos = navigator.zoomedMax; + navigator.fixedExtreme = reverse ? baseXAxis.min : baseXAxis.max; + } + else { + // Grab the right handle + navigator.grabbedRight = true; + navigator.otherHandlePos = navigator.zoomedMin; + navigator.fixedExtreme = reverse ? baseXAxis.max : baseXAxis.min; + } + chart.fixedRange = null; + }; + /** + * Mouse move event based on x/y mouse position. + * + * @private + * @function Highcharts.Navigator#onMouseMove + * + * @param {Highcharts.PointerEventObject} e + * Mouse event + */ + Navigator.prototype.onMouseMove = function (e) { + var navigator = this, chart = navigator.chart, left = navigator.left, navigatorSize = navigator.navigatorSize, range = navigator.range, dragOffset = navigator.dragOffset, inverted = chart.inverted, chartX; + // In iOS, a mousemove event with e.pageX === 0 is fired when holding + // the finger down in the center of the scrollbar. This should be + // ignored. + if (!e.touches || e.touches[0].pageX !== 0) { // #4696 + e = chart.pointer.normalize(e); + chartX = e.chartX; + // Swap some options for inverted chart + if (inverted) { + left = navigator.top; + chartX = e.chartY; + } + // Drag left handle or top handle + if (navigator.grabbedLeft) { + navigator.hasDragged = true; + navigator.render(0, 0, chartX - left, navigator.otherHandlePos); + // Drag right handle or bottom handle + } + else if (navigator.grabbedRight) { + navigator.hasDragged = true; + navigator.render(0, 0, navigator.otherHandlePos, chartX - left); + // Drag scrollbar or open area in navigator + } + else if (navigator.grabbedCenter) { + navigator.hasDragged = true; + if (chartX < dragOffset) { // outside left + chartX = dragOffset; + // outside right + } + else if (chartX > + navigatorSize + dragOffset - range) { + chartX = navigatorSize + dragOffset - range; + } + navigator.render(0, 0, chartX - dragOffset, chartX - dragOffset + range); + } + if (navigator.hasDragged && + navigator.scrollbar && + pick(navigator.scrollbar.options.liveRedraw, + // By default, don't run live redraw on VML, on touch + // devices or if the chart is in boost. + H.svg && !isTouchDevice && !this.chart.isBoosting)) { + e.DOMType = e.type; // DOMType is for IE8 + setTimeout(function () { + navigator.onMouseUp(e); + }, 0); + } + } + }; + /** + * Mouse up event based on x/y mouse position. + * + * @private + * @function Highcharts.Navigator#onMouseUp + * @param {Highcharts.PointerEventObject} e + * Mouse event + * @return {void} + */ + Navigator.prototype.onMouseUp = function (e) { + var navigator = this, chart = navigator.chart, xAxis = navigator.xAxis, scrollbar = navigator.scrollbar, DOMEvent = e.DOMEvent || e, inverted = chart.inverted, verb = navigator.rendered && !navigator.hasDragged ? + 'animate' : 'attr', zoomedMax = Math.round(navigator.zoomedMax), zoomedMin = Math.round(navigator.zoomedMin), unionExtremes, fixedMin, fixedMax, ext; + if ( + // MouseUp is called for both, navigator and scrollbar (that order), + // which causes calling afterSetExtremes twice. Prevent first call + // by checking if scrollbar is going to set new extremes (#6334) + (navigator.hasDragged && (!scrollbar || !scrollbar.hasDragged)) || + e.trigger === 'scrollbar') { + unionExtremes = navigator.getUnionExtremes(); + // When dragging one handle, make sure the other one doesn't change + if (navigator.zoomedMin === navigator.otherHandlePos) { + fixedMin = navigator.fixedExtreme; + } + else if (navigator.zoomedMax === navigator.otherHandlePos) { + fixedMax = navigator.fixedExtreme; + } + // Snap to right edge (#4076) + if (navigator.zoomedMax === navigator.size) { + fixedMax = navigator.reversedExtremes ? + unionExtremes.dataMin : + unionExtremes.dataMax; + } + // Snap to left edge (#7576) + if (navigator.zoomedMin === 0) { + fixedMin = navigator.reversedExtremes ? + unionExtremes.dataMax : + unionExtremes.dataMin; + } + ext = xAxis.navigatorAxis.toFixedRange(navigator.zoomedMin, navigator.zoomedMax, fixedMin, fixedMax); + if (defined(ext.min)) { + chart.xAxis[0].setExtremes(Math.min(ext.min, ext.max), Math.max(ext.min, ext.max), true, + // Run animation when clicking buttons, scrollbar track etc, + // but not when dragging handles or scrollbar + navigator.hasDragged ? false : null, { + trigger: 'navigator', + triggerOp: 'navigator-drag', + DOMEvent: DOMEvent // #1838 + }); + } + } + if (e.DOMType !== 'mousemove' && + e.DOMType !== 'touchmove') { + navigator.grabbedLeft = navigator.grabbedRight = + navigator.grabbedCenter = navigator.fixedWidth = + navigator.fixedExtreme = navigator.otherHandlePos = + navigator.hasDragged = navigator.dragOffset = null; + } + // Update position of navigator shades, outline and handles (#12573) + if (navigator.navigatorEnabled) { + if (navigator.shades) { + navigator.drawMasks(zoomedMin, zoomedMax, inverted, verb); + } + if (navigator.outline) { + navigator.drawOutline(zoomedMin, zoomedMax, inverted, verb); + } + if (navigator.navigatorOptions.handles.enabled && + Object.keys(navigator.handles).length === + navigator.handles.length) { + navigator.drawHandle(zoomedMin, 0, inverted, verb); + navigator.drawHandle(zoomedMax, 1, inverted, verb); + } + } + }; + /** + * Removes the event handlers attached previously with addEvents. + * + * @private + * @function Highcharts.Navigator#removeEvents + * @return {void} + */ + Navigator.prototype.removeEvents = function () { + if (this.eventsToUnbind) { + this.eventsToUnbind.forEach(function (unbind) { + unbind(); + }); + this.eventsToUnbind = void 0; + } + this.removeBaseSeriesEvents(); + }; + /** + * Remove data events. + * + * @private + * @function Highcharts.Navigator#removeBaseSeriesEvents + * @return {void} + */ + Navigator.prototype.removeBaseSeriesEvents = function () { + var baseSeries = this.baseSeries || []; + if (this.navigatorEnabled && baseSeries[0]) { + if (this.navigatorOptions.adaptToUpdatedData !== false) { + baseSeries.forEach(function (series) { + removeEvent(series, 'updatedData', this.updatedDataHandler); + }, this); + } + // We only listen for extremes-events on the first baseSeries + if (baseSeries[0].xAxis) { + removeEvent(baseSeries[0].xAxis, 'foundExtremes', this.modifyBaseAxisExtremes); + } + } + }; + /** + * Initialize the Navigator object + * + * @private + * @function Highcharts.Navigator#init + * + * @param {Highcharts.Chart} chart + */ + Navigator.prototype.init = function (chart) { + var chartOptions = chart.options, navigatorOptions = chartOptions.navigator, navigatorEnabled = navigatorOptions.enabled, scrollbarOptions = chartOptions.scrollbar, scrollbarEnabled = scrollbarOptions.enabled, height = navigatorEnabled ? navigatorOptions.height : 0, scrollbarHeight = scrollbarEnabled ? + scrollbarOptions.height : + 0; + this.handles = []; + this.shades = []; + this.chart = chart; + this.setBaseSeries(); + this.height = height; + this.scrollbarHeight = scrollbarHeight; + this.scrollbarEnabled = scrollbarEnabled; + this.navigatorEnabled = navigatorEnabled; + this.navigatorOptions = navigatorOptions; + this.scrollbarOptions = scrollbarOptions; + this.outlineHeight = height + scrollbarHeight; + this.opposite = pick(navigatorOptions.opposite, Boolean(!navigatorEnabled && chart.inverted)); // #6262 + var navigator = this, baseSeries = navigator.baseSeries, xAxisIndex = chart.xAxis.length, yAxisIndex = chart.yAxis.length, baseXaxis = baseSeries && baseSeries[0] && baseSeries[0].xAxis || + chart.xAxis[0] || { options: {} }; + chart.isDirtyBox = true; + if (navigator.navigatorEnabled) { + // an x axis is required for scrollbar also + navigator.xAxis = new Axis(chart, merge({ + // inherit base xAxis' break and ordinal options + breaks: baseXaxis.options.breaks, + ordinal: baseXaxis.options.ordinal + }, navigatorOptions.xAxis, { + id: 'navigator-x-axis', + yAxis: 'navigator-y-axis', + isX: true, + type: 'datetime', + index: xAxisIndex, + isInternal: true, + offset: 0, + keepOrdinalPadding: true, + startOnTick: false, + endOnTick: false, + minPadding: 0, + maxPadding: 0, + zoomEnabled: false + }, chart.inverted ? { + offsets: [scrollbarHeight, 0, -scrollbarHeight, 0], + width: height + } : { + offsets: [0, -scrollbarHeight, 0, scrollbarHeight], + height: height + })); + navigator.yAxis = new Axis(chart, merge(navigatorOptions.yAxis, { + id: 'navigator-y-axis', + alignTicks: false, + offset: 0, + index: yAxisIndex, + isInternal: true, + zoomEnabled: false + }, chart.inverted ? { + width: height + } : { + height: height + })); + // If we have a base series, initialize the navigator series + if (baseSeries || navigatorOptions.series.data) { + navigator.updateNavigatorSeries(false); + // If not, set up an event to listen for added series + } + else if (chart.series.length === 0) { + navigator.unbindRedraw = addEvent(chart, 'beforeRedraw', function () { + // We've got one, now add it as base + if (chart.series.length > 0 && !navigator.series) { + navigator.setBaseSeries(); + navigator.unbindRedraw(); // reset + } + }); + } + navigator.reversedExtremes = (chart.inverted && !navigator.xAxis.reversed) || (!chart.inverted && navigator.xAxis.reversed); + // Render items, so we can bind events to them: + navigator.renderElements(); + // Add mouse events + navigator.addMouseEvents(); + // in case of scrollbar only, fake an x axis to get translation + } + else { + navigator.xAxis = { + chart: chart, + navigatorAxis: { + fake: true + }, + translate: function (value, reverse) { + var axis = chart.xAxis[0], ext = axis.getExtremes(), scrollTrackWidth = axis.len - 2 * scrollbarHeight, min = numExt('min', axis.options.min, ext.dataMin), valueRange = numExt('max', axis.options.max, ext.dataMax) - min; + return reverse ? + // from pixel to value + (value * valueRange / scrollTrackWidth) + min : + // from value to pixel + scrollTrackWidth * (value - min) / valueRange; + }, + toPixels: function (value) { + return this.translate(value); + }, + toValue: function (value) { + return this.translate(value, true); + } + }; + navigator.xAxis.navigatorAxis.axis = navigator.xAxis; + navigator.xAxis.navigatorAxis.toFixedRange = (NavigatorAxis.AdditionsClass.prototype.toFixedRange.bind(navigator.xAxis.navigatorAxis)); + } + // Initialize the scrollbar + if (chart.options.scrollbar.enabled) { + chart.scrollbar = navigator.scrollbar = new Scrollbar(chart.renderer, merge(chart.options.scrollbar, { + margin: navigator.navigatorEnabled ? 0 : 10, + vertical: chart.inverted + }), chart); + addEvent(navigator.scrollbar, 'changed', function (e) { + var range = navigator.size, to = range * this.to, from = range * this.from; + navigator.hasDragged = navigator.scrollbar.hasDragged; + navigator.render(0, 0, from, to); + if (chart.options.scrollbar.liveRedraw || + (e.DOMType !== 'mousemove' && + e.DOMType !== 'touchmove')) { + setTimeout(function () { + navigator.onMouseUp(e); + }); + } + }); + } + // Add data events + navigator.addBaseSeriesEvents(); + // Add redraw events + navigator.addChartEvents(); + }; + /** + * Get the union data extremes of the chart - the outer data extremes of the + * base X axis and the navigator axis. + * + * @private + * @function Highcharts.Navigator#getUnionExtremes + * @param {boolean} [returnFalseOnNoBaseSeries] + * as the param says. + * @return {Highcharts.Dictionary<(number|undefined)>|undefined} + */ + Navigator.prototype.getUnionExtremes = function (returnFalseOnNoBaseSeries) { + var baseAxis = this.chart.xAxis[0], navAxis = this.xAxis, navAxisOptions = navAxis.options, baseAxisOptions = baseAxis.options, ret; + if (!returnFalseOnNoBaseSeries || baseAxis.dataMin !== null) { + ret = { + dataMin: pick(// #4053 + navAxisOptions && navAxisOptions.min, numExt('min', baseAxisOptions.min, baseAxis.dataMin, navAxis.dataMin, navAxis.min)), + dataMax: pick(navAxisOptions && navAxisOptions.max, numExt('max', baseAxisOptions.max, baseAxis.dataMax, navAxis.dataMax, navAxis.max)) + }; + } + return ret; + }; + /** + * Set the base series and update the navigator series from this. With a bit + * of modification we should be able to make this an API method to be called + * from the outside + * + * @private + * @function Highcharts.Navigator#setBaseSeries + * @param {Highcharts.SeriesOptionsType} [baseSeriesOptions] + * Additional series options for a navigator + * @param {boolean} [redraw] + * Whether to redraw after update. + * @return {void} + */ + Navigator.prototype.setBaseSeries = function (baseSeriesOptions, redraw) { + var chart = this.chart, baseSeries = this.baseSeries = []; + baseSeriesOptions = (baseSeriesOptions || + chart.options && chart.options.navigator.baseSeries || + (chart.series.length ? + // Find the first non-navigator series (#8430) + find(chart.series, function (s) { + return !s.options.isInternal; + }).index : + 0)); + // Iterate through series and add the ones that should be shown in + // navigator. + (chart.series || []).forEach(function (series, i) { + if ( + // Don't include existing nav series + !series.options.isInternal && + (series.options.showInNavigator || + (i === baseSeriesOptions || + series.options.id === baseSeriesOptions) && + series.options.showInNavigator !== false)) { + baseSeries.push(series); + } + }); + // When run after render, this.xAxis already exists + if (this.xAxis && !this.xAxis.navigatorAxis.fake) { + this.updateNavigatorSeries(true, redraw); + } + }; + /** + * Update series in the navigator from baseSeries, adding new if does not + * exist. + * + * @private + * @function Highcharts.Navigator.updateNavigatorSeries + * @param {boolean} addEvents + * @param {boolean} [redraw] + * @return {void} + */ + Navigator.prototype.updateNavigatorSeries = function (addEvents, redraw) { + var navigator = this, chart = navigator.chart, baseSeries = navigator.baseSeries, baseOptions, mergedNavSeriesOptions, chartNavigatorSeriesOptions = navigator.navigatorOptions.series, baseNavigatorOptions, navSeriesMixin = { + enableMouseTracking: false, + index: null, + linkedTo: null, + group: 'nav', + padXAxis: false, + xAxis: 'navigator-x-axis', + yAxis: 'navigator-y-axis', + showInLegend: false, + stacking: void 0, + isInternal: true, + states: { + inactive: { + opacity: 1 + } + } + }, + // Remove navigator series that are no longer in the baseSeries + navigatorSeries = navigator.series = + (navigator.series || []).filter(function (navSeries) { + var base = navSeries.baseSeries; + if (baseSeries.indexOf(base) < 0) { // Not in array + // If there is still a base series connected to this + // series, remove event handler and reference. + if (base) { + removeEvent(base, 'updatedData', navigator.updatedDataHandler); + delete base.navigatorSeries; + } + // Kill the nav series. It may already have been + // destroyed (#8715). + if (navSeries.chart) { + navSeries.destroy(); + } + return false; + } + return true; + }); + // Go through each base series and merge the options to create new + // series + if (baseSeries && baseSeries.length) { + baseSeries.forEach(function eachBaseSeries(base) { + var linkedNavSeries = base.navigatorSeries, userNavOptions = extend( + // Grab color and visibility from base as default + { + color: base.color, + visible: base.visible + }, !isArray(chartNavigatorSeriesOptions) ? + chartNavigatorSeriesOptions : + defaultOptions.navigator.series); + // Don't update if the series exists in nav and we have disabled + // adaptToUpdatedData. + if (linkedNavSeries && + navigator.navigatorOptions.adaptToUpdatedData === false) { + return; + } + navSeriesMixin.name = 'Navigator ' + baseSeries.length; + baseOptions = base.options || {}; + baseNavigatorOptions = baseOptions.navigatorOptions || {}; + mergedNavSeriesOptions = merge(baseOptions, navSeriesMixin, userNavOptions, baseNavigatorOptions); + // Once nav series type is resolved, pick correct pointRange + mergedNavSeriesOptions.pointRange = pick( + // Stricte set pointRange in options + userNavOptions.pointRange, baseNavigatorOptions.pointRange, + // Fallback to default values, e.g. `null` for column + defaultOptions.plotOptions[mergedNavSeriesOptions.type || 'line'].pointRange); + // Merge data separately. Do a slice to avoid mutating the + // navigator options from base series (#4923). + var navigatorSeriesData = baseNavigatorOptions.data || userNavOptions.data; + navigator.hasNavigatorData = + navigator.hasNavigatorData || !!navigatorSeriesData; + mergedNavSeriesOptions.data = + navigatorSeriesData || + baseOptions.data && baseOptions.data.slice(0); + // Update or add the series + if (linkedNavSeries && linkedNavSeries.options) { + linkedNavSeries.update(mergedNavSeriesOptions, redraw); + } + else { + base.navigatorSeries = chart.initSeries(mergedNavSeriesOptions); + base.navigatorSeries.baseSeries = base; // Store ref + navigatorSeries.push(base.navigatorSeries); + } + }); + } + // If user has defined data (and no base series) or explicitly defined + // navigator.series as an array, we create these series on top of any + // base series. + if (chartNavigatorSeriesOptions.data && + !(baseSeries && baseSeries.length) || + isArray(chartNavigatorSeriesOptions)) { + navigator.hasNavigatorData = false; + // Allow navigator.series to be an array + chartNavigatorSeriesOptions = + splat(chartNavigatorSeriesOptions); + chartNavigatorSeriesOptions.forEach(function (userSeriesOptions, i) { + navSeriesMixin.name = + 'Navigator ' + (navigatorSeries.length + 1); + mergedNavSeriesOptions = merge(defaultOptions.navigator.series, { + // Since we don't have a base series to pull color from, + // try to fake it by using color from series with same + // index. Otherwise pull from the colors array. We need + // an explicit color as otherwise updates will increment + // color counter and we'll get a new color for each + // update of the nav series. + color: chart.series[i] && + !chart.series[i].options.isInternal && + chart.series[i].color || + chart.options.colors[i] || + chart.options.colors[0] + }, navSeriesMixin, userSeriesOptions); + mergedNavSeriesOptions.data = userSeriesOptions.data; + if (mergedNavSeriesOptions.data) { + navigator.hasNavigatorData = true; + navigatorSeries.push(chart.initSeries(mergedNavSeriesOptions)); + } + }); + } + if (addEvents) { + this.addBaseSeriesEvents(); + } + }; + /** + * Add data events. + * For example when main series is updated we need to recalculate extremes + * + * @private + * @function Highcharts.Navigator#addBaseSeriesEvent + * @return {void} + */ + Navigator.prototype.addBaseSeriesEvents = function () { + var navigator = this, baseSeries = navigator.baseSeries || []; + // Bind modified extremes event to first base's xAxis only. + // In event of > 1 base-xAxes, the navigator will ignore those. + // Adding this multiple times to the same axis is no problem, as + // duplicates should be discarded by the browser. + if (baseSeries[0] && baseSeries[0].xAxis) { + addEvent(baseSeries[0].xAxis, 'foundExtremes', this.modifyBaseAxisExtremes); + } + baseSeries.forEach(function (base) { + // Link base series show/hide to navigator series visibility + addEvent(base, 'show', function () { + if (this.navigatorSeries) { + this.navigatorSeries.setVisible(true, false); + } + }); + addEvent(base, 'hide', function () { + if (this.navigatorSeries) { + this.navigatorSeries.setVisible(false, false); + } + }); + // Respond to updated data in the base series, unless explicitily + // not adapting to data changes. + if (this.navigatorOptions.adaptToUpdatedData !== false) { + if (base.xAxis) { + addEvent(base, 'updatedData', this.updatedDataHandler); + } + } + // Handle series removal + addEvent(base, 'remove', function () { + if (this.navigatorSeries) { + erase(navigator.series, this.navigatorSeries); + if (defined(this.navigatorSeries.options)) { + this.navigatorSeries.remove(false); + } + delete this.navigatorSeries; + } + }); + }, this); + }; + /** + * Get minimum from all base series connected to the navigator + * @private + * @param {number} currentSeriesMin + * Minium from the current series + * @return {number} Minimum from all series + */ + Navigator.prototype.getBaseSeriesMin = function (currentSeriesMin) { + return this.baseSeries.reduce(function (min, series) { + // (#10193) + return Math.min(min, series.xData ? series.xData[0] : min); + }, currentSeriesMin); + }; + /** + * Set the navigator x axis extremes to reflect the total. The navigator + * extremes should always be the extremes of the union of all series in the + * chart as well as the navigator series. + * + * @private + * @function Highcharts.Navigator#modifyNavigatorAxisExtremes + */ + Navigator.prototype.modifyNavigatorAxisExtremes = function () { + var xAxis = this.xAxis, unionExtremes; + if (typeof xAxis.getExtremes !== 'undefined') { + unionExtremes = this.getUnionExtremes(true); + if (unionExtremes && + (unionExtremes.dataMin !== xAxis.min || + unionExtremes.dataMax !== xAxis.max)) { + xAxis.min = unionExtremes.dataMin; + xAxis.max = unionExtremes.dataMax; + } + } + }; + /** + * Hook to modify the base axis extremes with information from the Navigator + * + * @private + * @function Highcharts.Navigator#modifyBaseAxisExtremes + */ + Navigator.prototype.modifyBaseAxisExtremes = function () { + var baseXAxis = this, navigator = baseXAxis.chart.navigator, baseExtremes = baseXAxis.getExtremes(), baseMin = baseExtremes.min, baseMax = baseExtremes.max, baseDataMin = baseExtremes.dataMin, baseDataMax = baseExtremes.dataMax, range = baseMax - baseMin, stickToMin = navigator.stickToMin, stickToMax = navigator.stickToMax, overscroll = pick(baseXAxis.options.overscroll, 0), newMax, newMin, navigatorSeries = navigator.series && navigator.series[0], hasSetExtremes = !!baseXAxis.setExtremes, + // When the extremes have been set by range selector button, don't + // stick to min or max. The range selector buttons will handle the + // extremes. (#5489) + unmutable = baseXAxis.eventArgs && + baseXAxis.eventArgs.trigger === 'rangeSelectorButton'; + if (!unmutable) { + // If the zoomed range is already at the min, move it to the right + // as new data comes in + if (stickToMin) { + newMin = baseDataMin; + newMax = newMin + range; + } + // If the zoomed range is already at the max, move it to the right + // as new data comes in + if (stickToMax) { + newMax = baseDataMax + overscroll; + // If stickToMin is true, the new min value is set above + if (!stickToMin) { + newMin = Math.max(baseDataMin, // don't go below data extremes (#13184) + newMax - range, navigator.getBaseSeriesMin(navigatorSeries && navigatorSeries.xData ? + navigatorSeries.xData[0] : + -Number.MAX_VALUE)); + } + } + // Update the extremes + if (hasSetExtremes && (stickToMin || stickToMax)) { + if (isNumber(newMin)) { + baseXAxis.min = baseXAxis.userMin = newMin; + baseXAxis.max = baseXAxis.userMax = newMax; + } + } + } + // Reset + navigator.stickToMin = + navigator.stickToMax = null; + }; + /** + * Handler for updated data on the base series. When data is modified, the + * navigator series must reflect it. This is called from the Chart.redraw + * function before axis and series extremes are computed. + * + * @private + * @function Highcharts.Navigator#updateDataHandler + */ + Navigator.prototype.updatedDataHandler = function () { + var navigator = this.chart.navigator, baseSeries = this, navigatorSeries = this.navigatorSeries, xDataMin = navigator.getBaseSeriesMin(baseSeries.xData[0]); + // If the scrollbar is scrolled all the way to the right, keep right as + // new data comes in. + navigator.stickToMax = navigator.reversedExtremes ? + Math.round(navigator.zoomedMin) === 0 : + Math.round(navigator.zoomedMax) >= Math.round(navigator.size); + // Detect whether the zoomed area should stick to the minimum or + // maximum. If the current axis minimum falls outside the new updated + // dataset, we must adjust. + navigator.stickToMin = isNumber(baseSeries.xAxis.min) && + (baseSeries.xAxis.min <= xDataMin) && + (!this.chart.fixedRange || !navigator.stickToMax); + // Set the navigator series data to the new data of the base series + if (navigatorSeries && !navigator.hasNavigatorData) { + navigatorSeries.options.pointStart = baseSeries.xData[0]; + navigatorSeries.setData(baseSeries.options.data, false, null, false); // #5414 + } + }; + /** + * Add chart events, like redrawing navigator, when chart requires that. + * + * @private + * @function Highcharts.Navigator#addChartEvents + * @return {void} + */ + Navigator.prototype.addChartEvents = function () { + if (!this.eventsToUnbind) { + this.eventsToUnbind = []; + } + this.eventsToUnbind.push( + // Move the scrollbar after redraw, like after data updata even if + // axes don't redraw + addEvent(this.chart, 'redraw', function () { + var navigator = this.navigator, xAxis = navigator && (navigator.baseSeries && + navigator.baseSeries[0] && + navigator.baseSeries[0].xAxis || + this.xAxis[0]); // #5709, #13114 + if (xAxis) { + navigator.render(xAxis.min, xAxis.max); + } + }), + // Make room for the navigator, can be placed around the chart: + addEvent(this.chart, 'getMargins', function () { + var chart = this, navigator = chart.navigator, marginName = navigator.opposite ? + 'plotTop' : 'marginBottom'; + if (chart.inverted) { + marginName = navigator.opposite ? + 'marginRight' : 'plotLeft'; + } + chart[marginName] = + (chart[marginName] || 0) + (navigator.navigatorEnabled || !chart.inverted ? + navigator.outlineHeight : + 0) + navigator.navigatorOptions.margin; + })); + }; + /** + * Destroys allocated elements. + * + * @private + * @function Highcharts.Navigator#destroy + */ + Navigator.prototype.destroy = function () { + // Disconnect events added in addEvents + this.removeEvents(); + if (this.xAxis) { + erase(this.chart.xAxis, this.xAxis); + erase(this.chart.axes, this.xAxis); + } + if (this.yAxis) { + erase(this.chart.yAxis, this.yAxis); + erase(this.chart.axes, this.yAxis); + } + // Destroy series + (this.series || []).forEach(function (s) { + if (s.destroy) { + s.destroy(); + } + }); + // Destroy properties + [ + 'series', 'xAxis', 'yAxis', 'shades', 'outline', 'scrollbarTrack', + 'scrollbarRifles', 'scrollbarGroup', 'scrollbar', 'navigatorGroup', + 'rendered' + ].forEach(function (prop) { + if (this[prop] && this[prop].destroy) { + this[prop].destroy(); + } + this[prop] = null; + }, this); + // Destroy elements in collection + [this.handles].forEach(function (coll) { + destroyObjectProperties(coll); + }, this); + }; + return Navigator; +}()); +// End of prototype +if (!H.Navigator) { + H.Navigator = Navigator; + NavigatorAxis.compose(Axis); + // For Stock charts. For x only zooming, do not to create the zoom button + // because X axis zooming is already allowed by the Navigator and Range + // selector. (#9285) + addEvent(Chart, 'beforeShowResetZoom', function () { + var chartOptions = this.options, navigator = chartOptions.navigator, rangeSelector = chartOptions.rangeSelector; + if (((navigator && navigator.enabled) || + (rangeSelector && rangeSelector.enabled)) && + ((!isTouchDevice && chartOptions.chart.zoomType === 'x') || + (isTouchDevice && chartOptions.chart.pinchType === 'x'))) { + return false; + } + }); + // Initialize navigator for stock charts + addEvent(Chart, 'beforeRender', function () { + var options = this.options; + if (options.navigator.enabled || + options.scrollbar.enabled) { + this.scroller = this.navigator = new Navigator(this); + } + }); + // For stock charts, extend the Chart.setChartSize method so that we can set + // the final top position of the navigator once the height of the chart, + // including the legend, is determined. #367. We can't use Chart.getMargins, + // because labels offsets are not calculated yet. + addEvent(Chart, 'afterSetChartSize', function () { + var legend = this.legend, navigator = this.navigator, scrollbarHeight, legendOptions, xAxis, yAxis; + if (navigator) { + legendOptions = legend && legend.options; + xAxis = navigator.xAxis; + yAxis = navigator.yAxis; + scrollbarHeight = navigator.scrollbarHeight; + // Compute the top position + if (this.inverted) { + navigator.left = navigator.opposite ? + this.chartWidth - scrollbarHeight - + navigator.height : + this.spacing[3] + scrollbarHeight; + navigator.top = this.plotTop + scrollbarHeight; + } + else { + navigator.left = this.plotLeft + scrollbarHeight; + navigator.top = navigator.navigatorOptions.top || + this.chartHeight - + navigator.height - + scrollbarHeight - + this.spacing[2] - + (this.rangeSelector && this.extraBottomMargin ? + this.rangeSelector.getHeight() : + 0) - + ((legendOptions && + legendOptions.verticalAlign === 'bottom' && + legendOptions.enabled && + !legendOptions.floating) ? + legend.legendHeight + + pick(legendOptions.margin, 10) : + 0) - + (this.titleOffset ? this.titleOffset[2] : 0); + } + if (xAxis && yAxis) { // false if navigator is disabled (#904) + if (this.inverted) { + xAxis.options.left = yAxis.options.left = navigator.left; + } + else { + xAxis.options.top = yAxis.options.top = navigator.top; + } + xAxis.setAxisSize(); + yAxis.setAxisSize(); + } + } + }); + // Merge options, if no scrolling exists yet + addEvent(Chart, 'update', function (e) { + var navigatorOptions = (e.options.navigator || {}), scrollbarOptions = (e.options.scrollbar || {}); + if (!this.navigator && !this.scroller && + (navigatorOptions.enabled || scrollbarOptions.enabled)) { + merge(true, this.options.navigator, navigatorOptions); + merge(true, this.options.scrollbar, scrollbarOptions); + delete e.options.navigator; + delete e.options.scrollbar; + } + }); + // Initialize navigator, if no scrolling exists yet + addEvent(Chart, 'afterUpdate', function (event) { + if (!this.navigator && !this.scroller && + (this.options.navigator.enabled || + this.options.scrollbar.enabled)) { + this.scroller = this.navigator = new Navigator(this); + if (pick(event.redraw, true)) { + this.redraw(event.animation); // #7067 + } + } + }); + // Handle adding new series + addEvent(Chart, 'afterAddSeries', function () { + if (this.navigator) { + // Recompute which series should be shown in navigator, and add them + this.navigator.setBaseSeries(null, false); + } + }); + // Handle updating series + addEvent(Series, 'afterUpdate', function () { + if (this.chart.navigator && !this.options.isInternal) { + this.chart.navigator.setBaseSeries(null, false); + } + }); + Chart.prototype.callbacks.push(function (chart) { + var extremes, navigator = chart.navigator; + // Initialize the navigator + if (navigator && chart.xAxis[0]) { + extremes = chart.xAxis[0].getExtremes(); + navigator.render(extremes.min, extremes.max); + } + }); +} +H.Navigator = Navigator; +export default H.Navigator; diff --git a/librerias/gantt/code/es-modules/parts/NavigatorAxis.js b/librerias/gantt/code/es-modules/parts/NavigatorAxis.js new file mode 100644 index 0000000..5f09455 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/NavigatorAxis.js @@ -0,0 +1,164 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +var isTouchDevice = H.isTouchDevice; +import U from './Utilities.js'; +var addEvent = U.addEvent, correctFloat = U.correctFloat, defined = U.defined, isNumber = U.isNumber, pick = U.pick; +/* eslint-disable valid-jsdoc */ +/** + * @private + * @class + */ +var NavigatorAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function NavigatorAxisAdditions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * @private + */ + NavigatorAxisAdditions.prototype.destroy = function () { + this.axis = void 0; + }; + /** + * Add logic to normalize the zoomed range in order to preserve the pressed + * state of range selector buttons + * + * @private + * @function Highcharts.Axis#toFixedRange + * @param {number} [pxMin] + * @param {number} [pxMax] + * @param {number} [fixedMin] + * @param {number} [fixedMax] + * @return {*} + */ + NavigatorAxisAdditions.prototype.toFixedRange = function (pxMin, pxMax, fixedMin, fixedMax) { + var navigator = this; + var axis = navigator.axis; + var chart = axis.chart; + var fixedRange = chart && chart.fixedRange, halfPointRange = (axis.pointRange || 0) / 2, newMin = pick(fixedMin, axis.translate(pxMin, true, !axis.horiz)), newMax = pick(fixedMax, axis.translate(pxMax, true, !axis.horiz)), changeRatio = fixedRange && (newMax - newMin) / fixedRange; + // Add/remove half point range to/from the extremes (#1172) + if (!defined(fixedMin)) { + newMin = correctFloat(newMin + halfPointRange); + } + if (!defined(fixedMax)) { + newMax = correctFloat(newMax - halfPointRange); + } + // If the difference between the fixed range and the actual requested + // range is too great, the user is dragging across an ordinal gap, and + // we need to release the range selector button. + if (changeRatio > 0.7 && changeRatio < 1.3) { + if (fixedMax) { + newMin = newMax - fixedRange; + } + else { + newMax = newMin + fixedRange; + } + } + if (!isNumber(newMin) || !isNumber(newMax)) { // #1195, #7411 + newMin = newMax = void 0; + } + return { + min: newMin, + max: newMax + }; + }; + return NavigatorAxisAdditions; +}()); +/** + * @private + * @class + */ +var NavigatorAxis = /** @class */ (function () { + function NavigatorAxis() { + } + /* * + * + * Static Functions + * + * */ + /** + * @private + */ + NavigatorAxis.compose = function (AxisClass) { + AxisClass.keepProps.push('navigatorAxis'); + /* eslint-disable no-invalid-this */ + addEvent(AxisClass, 'init', function () { + var axis = this; + if (!axis.navigatorAxis) { + axis.navigatorAxis = new NavigatorAxisAdditions(axis); + } + }); + // For Stock charts, override selection zooming with some special + // features because X axis zooming is already allowed by the Navigator + // and Range selector. + addEvent(AxisClass, 'zoom', function (e) { + var axis = this; + var chart = axis.chart; + var chartOptions = chart.options; + var navigator = chartOptions.navigator; + var navigatorAxis = axis.navigatorAxis; + var pinchType = chartOptions.chart.pinchType; + var rangeSelector = chartOptions.rangeSelector; + var zoomType = chartOptions.chart.zoomType; + var previousZoom; + if (axis.isXAxis && ((navigator && navigator.enabled) || + (rangeSelector && rangeSelector.enabled))) { + // For y only zooming, ignore the X axis completely + if (zoomType === 'y') { + e.zoomed = false; + // For xy zooming, record the state of the zoom before zoom + // selection, then when the reset button is pressed, revert to + // this state. This should apply only if the chart is + // initialized with a range (#6612), otherwise zoom all the way + // out. + } + else if (((!isTouchDevice && zoomType === 'xy') || + (isTouchDevice && pinchType === 'xy')) && + axis.options.range) { + previousZoom = navigatorAxis.previousZoom; + if (defined(e.newMin)) { + navigatorAxis.previousZoom = [axis.min, axis.max]; + } + else if (previousZoom) { + e.newMin = previousZoom[0]; + e.newMax = previousZoom[1]; + navigatorAxis.previousZoom = void 0; + } + } + } + if (typeof e.zoomed !== 'undefined') { + e.preventDefault(); + } + }); + /* eslint-enable no-invalid-this */ + }; + /* * + * + * Static Properties + * + * */ + /** + * @private + */ + NavigatorAxis.AdditionsClass = NavigatorAxisAdditions; + return NavigatorAxis; +}()); +export default NavigatorAxis; diff --git a/librerias/gantt/code/es-modules/parts/OHLCSeries.js b/librerias/gantt/code/es-modules/parts/OHLCSeries.js new file mode 100644 index 0000000..7ced577 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/OHLCSeries.js @@ -0,0 +1,355 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +import Point from './Point.js'; +import U from './Utilities.js'; +var seriesType = U.seriesType; +var seriesTypes = H.seriesTypes; +/** + * The ohlc series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.ohlc + * + * @augments Highcharts.Series + */ +seriesType('ohlc', 'column' +/** + * An OHLC chart is a style of financial chart used to describe price + * movements over time. It displays open, high, low and close values per + * data point. + * + * @sample stock/demo/ohlc/ + * OHLC chart + * + * @extends plotOptions.column + * @excluding borderColor, borderRadius, borderWidth, crisp, stacking, + * stack + * @product highstock + * @optionparent plotOptions.ohlc + */ +, { + /** + * The approximate pixel width of each group. If for example a series + * with 30 points is displayed over a 600 pixel wide plot area, no + * grouping is performed. If however the series contains so many points + * that the spacing is less than the groupPixelWidth, Highcharts will + * try to group it into appropriate groups so that each is more or less + * two pixels wide. Defaults to `5`. + * + * @type {number} + * @default 5 + * @product highstock + * @apioption plotOptions.ohlc.dataGrouping.groupPixelWidth + */ + /** + * The pixel width of the line/border. Defaults to `1`. + * + * @sample {highstock} stock/plotoptions/ohlc-linewidth/ + * A greater line width + * + * @type {number} + * @default 1 + * @product highstock + * + * @private + */ + lineWidth: 1, + tooltip: { + pointFormat: '\u25CF ' + + ' {series.name}
' + + 'Open: {point.open}
' + + 'High: {point.high}
' + + 'Low: {point.low}
' + + 'Close: {point.close}
' + }, + threshold: null, + states: { + /** + * @extends plotOptions.column.states.hover + * @product highstock + */ + hover: { + /** + * The pixel width of the line representing the OHLC point. + * + * @type {number} + * @default 3 + * @product highstock + */ + lineWidth: 3 + } + }, + /** + * Determines which one of `open`, `high`, `low`, `close` values should + * be represented as `point.y`, which is later used to set dataLabel + * position and [compare](#plotOptions.series.compare). + * + * @sample {highstock} stock/plotoptions/ohlc-pointvalkey/ + * Possible values + * + * @type {string} + * @default close + * @validvalue ["open", "high", "low", "close"] + * @product highstock + * @apioption plotOptions.ohlc.pointValKey + */ + /** + * @default close + * @apioption plotOptions.ohlc.colorKey + */ + /** + * Line color for up points. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highstock + * @apioption plotOptions.ohlc.upColor + */ + stickyTracking: true +}, +/** + * @lends Highcharts.seriesTypes.ohlc + */ +{ + /* eslint-disable valid-jsdoc */ + directTouch: false, + pointArrayMap: ['open', 'high', 'low', 'close'], + toYData: function (point) { + // return a plain array for speedy calculation + return [point.open, point.high, point.low, point.close]; + }, + pointValKey: 'close', + pointAttrToOptions: { + stroke: 'color', + 'stroke-width': 'lineWidth' + }, + /** + * @private + * @function Highcarts.seriesTypes.ohlc#init + * @return {void} + */ + init: function () { + seriesTypes.column.prototype.init.apply(this, arguments); + this.options.stacking = void 0; // #8817 + }, + /** + * Postprocess mapping between options and SVG attributes + * + * @private + * @function Highcharts.seriesTypes.ohlc#pointAttribs + * @param {Highcharts.OHLCPoint} point + * @param {string} state + * @return {Highcharts.SVGAttributes} + */ + pointAttribs: function (point, state) { + var attribs = seriesTypes.column.prototype.pointAttribs.call(this, point, state), options = this.options; + delete attribs.fill; + if (!point.options.color && + options.upColor && + point.open < point.close) { + attribs.stroke = options.upColor; + } + return attribs; + }, + /** + * Translate data points from raw values x and y to plotX and plotY + * + * @private + * @function Highcharts.seriesTypes.ohlc#translate + * @return {void} + */ + translate: function () { + var series = this, yAxis = series.yAxis, hasModifyValue = !!series.modifyValue, translated = [ + 'plotOpen', + 'plotHigh', + 'plotLow', + 'plotClose', + 'yBottom' + ]; // translate OHLC for + seriesTypes.column.prototype.translate.apply(series); + // Do the translation + series.points.forEach(function (point) { + [point.open, point.high, point.low, point.close, point.low] + .forEach(function (value, i) { + if (value !== null) { + if (hasModifyValue) { + value = series.modifyValue(value); + } + point[translated[i]] = + yAxis.toPixels(value, true); + } + }); + // Align the tooltip to the high value to avoid covering the + // point + point.tooltipPos[1] = + point.plotHigh + yAxis.pos - series.chart.plotTop; + }); + }, + /** + * Draw the data points + * + * @private + * @function Highcharts.seriesTypes.ohlc#drawPoints + * @return {void} + */ + drawPoints: function () { + var series = this, points = series.points, chart = series.chart, + /** + * Extend vertical stem to open and close values. + */ + extendStem = function (path, halfStrokeWidth, openOrClose) { + var start = path[0]; + var end = path[1]; + // We don't need to worry about crisp - openOrClose value + // is already crisped and halfStrokeWidth should remove it. + if (typeof start[2] === 'number') { + start[2] = Math.max(openOrClose + halfStrokeWidth, start[2]); + } + if (typeof end[2] === 'number') { + end[2] = Math.min(openOrClose - halfStrokeWidth, end[2]); + } + }; + points.forEach(function (point) { + var plotOpen, plotClose, crispCorr, halfWidth, path, graphic = point.graphic, crispX, isNew = !graphic, strokeWidth; + if (typeof point.plotY !== 'undefined') { + // Create and/or update the graphic + if (!graphic) { + point.graphic = graphic = chart.renderer.path() + .add(series.group); + } + if (!chart.styledMode) { + graphic.attr(series.pointAttribs(point, (point.selected && 'select'))); // #3897 + } + // crisp vector coordinates + strokeWidth = graphic.strokeWidth(); + crispCorr = (strokeWidth % 2) / 2; + // #2596: + crispX = Math.round(point.plotX) - crispCorr; + halfWidth = Math.round(point.shapeArgs.width / 2); + // the vertical stem + path = [ + ['M', crispX, Math.round(point.yBottom)], + ['L', crispX, Math.round(point.plotHigh)] + ]; + // open + if (point.open !== null) { + plotOpen = Math.round(point.plotOpen) + crispCorr; + path.push(['M', crispX, plotOpen], ['L', crispX - halfWidth, plotOpen]); + extendStem(path, strokeWidth / 2, plotOpen); + } + // close + if (point.close !== null) { + plotClose = Math.round(point.plotClose) + crispCorr; + path.push(['M', crispX, plotClose], ['L', crispX + halfWidth, plotClose]); + extendStem(path, strokeWidth / 2, plotClose); + } + graphic[isNew ? 'attr' : 'animate']({ d: path }) + .addClass(point.getClassName(), true); + } + }); + }, + animate: null // Disable animation + /* eslint-enable valid-jsdoc */ +}, +/** + * @lends Highcharts.seriesTypes.ohlc.prototype.pointClass.prototype + */ +{ + /* eslint-disable valid-jsdoc */ + /** + * Extend the parent method by adding up or down to the class name. + * @private + * @function Highcharts.seriesTypes.ohlc#getClassName + * @return {string} + */ + getClassName: function () { + return Point.prototype.getClassName.call(this) + + (this.open < this.close ? + ' highcharts-point-up' : + ' highcharts-point-down'); + } + /* eslint-enable valid-jsdoc */ +}); +/** + * A `ohlc` series. If the [type](#series.ohlc.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.ohlc + * @excluding dataParser, dataURL + * @product highstock + * @apioption series.ohlc + */ +/** + * An array of data points for the series. For the `ohlc` series type, + * points can be given in the following ways: + * + * 1. An array of arrays with 5 or 4 values. In this case, the values correspond + * to `x,open,high,low,close`. If the first value is a string, it is applied + * as the name of the point, and the `x` value is inferred. The `x` value can + * also be omitted, in which case the inner arrays should be of length 4\. + * Then the `x` value is automatically calculated, either starting at 0 and + * incremented by 1, or from `pointStart` and `pointInterval` given in the + * series options. + * ```js + * data: [ + * [0, 6, 5, 6, 7], + * [1, 9, 4, 8, 2], + * [2, 6, 3, 4, 10] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.ohlc.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * open: 3, + * high: 4, + * low: 5, + * close: 2, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * open: 4, + * high: 3, + * low: 6, + * close: 7, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @type {Array|Array<(number|string),number,number,number,number>|*>} + * @extends series.arearange.data + * @excluding y, marker + * @product highstock + * @apioption series.ohlc.data + */ +/** + * The closing value of each data point. + * + * @type {number} + * @product highstock + * @apioption series.ohlc.data.close + */ +/** + * The opening value of each data point. + * + * @type {number} + * @product highstock + * @apioption series.ohlc.data.open + */ +''; // adds doclets above to transpilat diff --git a/librerias/gantt/code/es-modules/parts/Options.js b/librerias/gantt/code/es-modules/parts/Options.js new file mode 100644 index 0000000..758e4e3 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/Options.js @@ -0,0 +1,3635 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +/** + * @typedef {"plotBox"|"spacingBox"} Highcharts.ButtonRelativeToValue + */ +/** + * Gets fired when a series is added to the chart after load time, using the + * `addSeries` method. Returning `false` prevents the series from being added. + * + * @callback Highcharts.ChartAddSeriesCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart on which the event occured. + * + * @param {Highcharts.ChartAddSeriesEventObject} event + * The event that occured. + * + * @return {void} + */ +/** + * Contains common event information. Through the `options` property you can + * access the series options that were passed to the `addSeries` method. + * + * @interface Highcharts.ChartAddSeriesEventObject + */ /** +* The series options that were passed to the `addSeries` method. +* @name Highcharts.ChartAddSeriesEventObject#options +* @type {Highcharts.SeriesOptionsType} +*/ /** +* Prevents the default behaviour of the event. +* @name Highcharts.ChartAddSeriesEventObject#preventDefault +* @type {Function} +*/ /** +* The event target. +* @name Highcharts.ChartAddSeriesEventObject#target +* @type {Highcharts.Chart} +*/ /** +* The event type. +* @name Highcharts.ChartAddSeriesEventObject#type +* @type {"addSeries"} +*/ +/** + * Gets fired when clicking on the plot background. + * + * @callback Highcharts.ChartClickCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart on which the event occured. + * + * @param {Highcharts.PointerEventObject} event + * The event that occured. + * + * @return {void} + */ +/** + * Contains an axes of the clicked spot. + * + * @interface Highcharts.ChartClickEventAxisObject + */ /** +* Axis at the clicked spot. +* @name Highcharts.ChartClickEventAxisObject#axis +* @type {Highcharts.Axis} +*/ /** +* Axis value at the clicked spot. +* @name Highcharts.ChartClickEventAxisObject#value +* @type {number} +*/ +/** + * Contains information about the clicked spot on the chart. Remember the unit + * of a datetime axis is milliseconds since 1970-01-01 00:00:00. + * + * @interface Highcharts.ChartClickEventObject + * @extends Highcharts.PointerEventObject + */ /** +* Information about the x-axis on the clicked spot. +* @name Highcharts.ChartClickEventObject#xAxis +* @type {Array} +*/ /** +* Information about the y-axis on the clicked spot. +* @name Highcharts.ChartClickEventObject#yAxis +* @type {Array} +*/ /** +* Information about the z-axis on the clicked spot. +* @name Highcharts.ChartClickEventObject#zAxis +* @type {Array|undefined} +*/ +/** + * Gets fired when the chart is finished loading. + * + * @callback Highcharts.ChartLoadCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart on which the event occured. + * + * @param {global.Event} event + * The event that occured. + * + * @return {void} + */ +/** + * Fires when the chart is redrawn, either after a call to `chart.redraw()` or + * after an axis, series or point is modified with the `redraw` option set to + * `true`. + * + * @callback Highcharts.ChartRedrawCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart on which the event occured. + * + * @param {global.Event} event + * The event that occured. + * + * @return {void} + */ +/** + * Gets fired after initial load of the chart (directly after the `load` event), + * and after each redraw (directly after the `redraw` event). + * + * @callback Highcharts.ChartRenderCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart on which the event occured. + * + * @param {global.Event} event + * The event that occured. + * + * @return {void} + */ +/** + * Gets fired when an area of the chart has been selected. The default action + * for the selection event is to zoom the chart to the selected area. It can be + * prevented by calling `event.preventDefault()` or return false. + * + * @callback Highcharts.ChartSelectionCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart on which the event occured. + * + * @param {global.ChartSelectionContextObject} event + * Event informations + * + * @return {boolean|undefined} + * Return false to prevent the default action, usually zoom. + */ +/** + * The primary axes are `xAxis[0]` and `yAxis[0]`. Remember the unit of a + * datetime axis is milliseconds since 1970-01-01 00:00:00. + * + * @interface Highcharts.ChartSelectionContextObject + * @extends global.Event + */ /** +* Arrays containing the axes of each dimension and each axis' min and max +* values. +* @name Highcharts.ChartSelectionContextObject#xAxis +* @type {Array} +*/ /** +* Arrays containing the axes of each dimension and each axis' min and max +* values. +* @name Highcharts.ChartSelectionContextObject#yAxis +* @type {Array} +*/ +/** + * Axis context of the selection. + * + * @interface Highcharts.ChartSelectionAxisContextObject + */ /** +* The selected Axis. +* @name Highcharts.ChartSelectionAxisContextObject#axis +* @type {Highcharts.Axis} +*/ /** +* The maximum axis value, either automatic or set manually. +* @name Highcharts.ChartSelectionAxisContextObject#max +* @type {number} +*/ /** +* The minimum axis value, either automatic or set manually. +* @name Highcharts.ChartSelectionAxisContextObject#min +* @type {number} +*/ +import Time from './Time.js'; +import Color from './Color.js'; +var color = Color.parse; +import U from './Utilities.js'; +var merge = U.merge; +var isTouchDevice = H.isTouchDevice, svg = H.svg; +/* ************************************************************************** * + * Handle the options * + * ************************************************************************** */ +/** + * Global default settings. + * + * @name Highcharts.defaultOptions + * @type {Highcharts.Options} + */ /** +* @optionparent +*/ +H.defaultOptions = { + /** + * An array containing the default colors for the chart's series. When + * all colors are used, new colors are pulled from the start again. + * + * Default colors can also be set on a series or series.type basis, + * see [column.colors](#plotOptions.column.colors), + * [pie.colors](#plotOptions.pie.colors). + * + * In styled mode, the colors option doesn't exist. Instead, colors + * are defined in CSS and applied either through series or point class + * names, or through the [chart.colorCount](#chart.colorCount) option. + * + * + * ### Legacy + * + * In Highcharts 3.x, the default colors were: + * ```js + * colors: ['#2f7ed8', '#0d233a', '#8bbc21', '#910000', '#1aadce', + * '#492970', '#f28f43', '#77a1e5', '#c42525', '#a6c96a'] + * ``` + * + * In Highcharts 2.x, the default colors were: + * ```js + * colors: ['#4572A7', '#AA4643', '#89A54E', '#80699B', '#3D96AE', + * '#DB843D', '#92A8CD', '#A47D7C', '#B5CA92'] + * ``` + * + * @sample {highcharts} highcharts/chart/colors/ + * Assign a global color theme + * + * @type {Array} + * @default ["#7cb5ec", "#434348", "#90ed7d", "#f7a35c", "#8085e9", + * "#f15c80", "#e4d354", "#2b908f", "#f45b5b", "#91e8e1"] + */ + colors: '#7cb5ec #434348 #90ed7d #f7a35c #8085e9 #f15c80 #e4d354 #2b908f #f45b5b #91e8e1'.split(' '), + /** + * Styled mode only. Configuration object for adding SVG definitions for + * reusable elements. See [gradients, shadows and + * patterns](https://www.highcharts.com/docs/chart-design-and-style/gradients-shadows-and-patterns) + * for more information and code examples. + * + * @type {*} + * @since 5.0.0 + * @apioption defs + */ + /** + * @ignore-option + */ + symbols: ['circle', 'diamond', 'square', 'triangle', 'triangle-down'], + /** + * The language object is global and it can't be set on each chart + * initialization. Instead, use `Highcharts.setOptions` to set it before any + * chart is initialized. + * + * ```js + * Highcharts.setOptions({ + * lang: { + * months: [ + * 'Janvier', 'Février', 'Mars', 'Avril', + * 'Mai', 'Juin', 'Juillet', 'Août', + * 'Septembre', 'Octobre', 'Novembre', 'Décembre' + * ], + * weekdays: [ + * 'Dimanche', 'Lundi', 'Mardi', 'Mercredi', + * 'Jeudi', 'Vendredi', 'Samedi' + * ] + * } + * }); + * ``` + */ + lang: { + /** + * The loading text that appears when the chart is set into the loading + * state following a call to `chart.showLoading`. + */ + loading: 'Loading...', + /** + * An array containing the months names. Corresponds to the `%B` format + * in `Highcharts.dateFormat()`. + * + * @type {Array} + * @default ["January", "February", "March", "April", "May", "June", + * "July", "August", "September", "October", "November", + * "December"] + */ + months: [ + 'January', 'February', 'March', 'April', 'May', 'June', 'July', + 'August', 'September', 'October', 'November', 'December' + ], + /** + * An array containing the months names in abbreviated form. Corresponds + * to the `%b` format in `Highcharts.dateFormat()`. + * + * @type {Array} + * @default ["Jan", "Feb", "Mar", "Apr", "May", "Jun", + * "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] + */ + shortMonths: [ + 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', + 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' + ], + /** + * An array containing the weekday names. + * + * @type {Array} + * @default ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", + * "Friday", "Saturday"] + */ + weekdays: [ + 'Sunday', 'Monday', 'Tuesday', 'Wednesday', + 'Thursday', 'Friday', 'Saturday' + ], + /** + * Short week days, starting Sunday. If not specified, Highcharts uses + * the first three letters of the `lang.weekdays` option. + * + * @sample highcharts/lang/shortweekdays/ + * Finnish two-letter abbreviations + * + * @type {Array} + * @since 4.2.4 + * @apioption lang.shortWeekdays + */ + /** + * What to show in a date field for invalid dates. Defaults to an empty + * string. + * + * @type {string} + * @since 4.1.8 + * @product highcharts highstock + * @apioption lang.invalidDate + */ + /** + * The title appearing on hovering the zoom in button. The text itself + * defaults to "+" and can be changed in the button options. + * + * @type {string} + * @default Zoom in + * @product highmaps + * @apioption lang.zoomIn + */ + /** + * The title appearing on hovering the zoom out button. The text itself + * defaults to "-" and can be changed in the button options. + * + * @type {string} + * @default Zoom out + * @product highmaps + * @apioption lang.zoomOut + */ + /** + * The default decimal point used in the `Highcharts.numberFormat` + * method unless otherwise specified in the function arguments. + * + * @since 1.2.2 + */ + decimalPoint: '.', + /** + * [Metric prefixes](https://en.wikipedia.org/wiki/Metric_prefix) used + * to shorten high numbers in axis labels. Replacing any of the + * positions with `null` causes the full number to be written. Setting + * `numericSymbols` to `null` disables shortening altogether. + * + * @sample {highcharts} highcharts/lang/numericsymbols/ + * Replacing the symbols with text + * @sample {highstock} highcharts/lang/numericsymbols/ + * Replacing the symbols with text + * + * @type {Array} + * @default ["k", "M", "G", "T", "P", "E"] + * @since 2.3.0 + */ + numericSymbols: ['k', 'M', 'G', 'T', 'P', 'E'], + /** + * The magnitude of [numericSymbols](#lang.numericSymbol) replacements. + * Use 10000 for Japanese, Korean and various Chinese locales, which + * use symbols for 10^4, 10^8 and 10^12. + * + * @sample highcharts/lang/numericsymbolmagnitude/ + * 10000 magnitude for Japanese + * + * @type {number} + * @default 1000 + * @since 5.0.3 + * @apioption lang.numericSymbolMagnitude + */ + /** + * The text for the label appearing when a chart is zoomed. + * + * @since 1.2.4 + */ + resetZoom: 'Reset zoom', + /** + * The tooltip title for the label appearing when a chart is zoomed. + * + * @since 1.2.4 + */ + resetZoomTitle: 'Reset zoom level 1:1', + /** + * The default thousands separator used in the `Highcharts.numberFormat` + * method unless otherwise specified in the function arguments. Defaults + * to a single space character, which is recommended in + * [ISO 31-0](https://en.wikipedia.org/wiki/ISO_31-0#Numbers) and works + * across Anglo-American and continental European languages. + * + * @default \u0020 + * @since 1.2.2 + */ + thousandsSep: ' ' + }, + /** + * Global options that don't apply to each chart. These options, like + * the `lang` options, must be set using the `Highcharts.setOptions` + * method. + * + * ```js + * Highcharts.setOptions({ + * global: { + * useUTC: false + * } + * }); + * ``` + */ + /** + * _Canvg rendering for Android 2.x is removed as of Highcharts 5.0\. + * Use the [libURL](#exporting.libURL) option to configure exporting._ + * + * The URL to the additional file to lazy load for Android 2.x devices. + * These devices don't support SVG, so we download a helper file that + * contains [canvg](https://github.com/canvg/canvg), its dependency + * rbcolor, and our own CanVG Renderer class. To avoid hotlinking to + * our site, you can install canvas-tools.js on your own server and + * change this option accordingly. + * + * @deprecated + * + * @type {string} + * @default https://code.highcharts.com/{version}/modules/canvas-tools.js + * @product highcharts highmaps + * @apioption global.canvasToolsURL + */ + /** + * This option is deprecated since v6.0.5. Instead, use + * [time.useUTC](#time.useUTC) that supports individual time settings + * per chart. + * + * @deprecated + * + * @type {boolean} + * @apioption global.useUTC + */ + /** + * This option is deprecated since v6.0.5. Instead, use + * [time.Date](#time.Date) that supports individual time settings + * per chart. + * + * @deprecated + * + * @type {Function} + * @product highcharts highstock + * @apioption global.Date + */ + /** + * This option is deprecated since v6.0.5. Instead, use + * [time.getTimezoneOffset](#time.getTimezoneOffset) that supports + * individual time settings per chart. + * + * @deprecated + * + * @type {Function} + * @product highcharts highstock + * @apioption global.getTimezoneOffset + */ + /** + * This option is deprecated since v6.0.5. Instead, use + * [time.timezone](#time.timezone) that supports individual time + * settings per chart. + * + * @deprecated + * + * @type {string} + * @product highcharts highstock + * @apioption global.timezone + */ + /** + * This option is deprecated since v6.0.5. Instead, use + * [time.timezoneOffset](#time.timezoneOffset) that supports individual + * time settings per chart. + * + * @deprecated + * + * @type {number} + * @product highcharts highstock + * @apioption global.timezoneOffset + */ + global: {}, + time: Time.defaultOptions, + /** + * General options for the chart. + */ + chart: { + /** + * Default `mapData` for all series. If set to a string, it functions + * as an index into the `Highcharts.maps` array. Otherwise it is + * interpreted as map data. + * + * @see [mapData](#series.map.mapData) + * + * @sample maps/demo/geojson + * Loading geoJSON data + * @sample maps/chart/topojson + * Loading topoJSON converted to geoJSON + * + * @type {string|Array<*>} + * @since 5.0.0 + * @product highmaps + * @apioption chart.map + */ + /** + * Set lat/lon transformation definitions for the chart. If not defined, + * these are extracted from the map data. + * + * @type {*} + * @since 5.0.0 + * @product highmaps + * @apioption chart.mapTransforms + */ + /** + * When using multiple axis, the ticks of two or more opposite axes + * will automatically be aligned by adding ticks to the axis or axes + * with the least ticks, as if `tickAmount` were specified. + * + * This can be prevented by setting `alignTicks` to false. If the grid + * lines look messy, it's a good idea to hide them for the secondary + * axis by setting `gridLineWidth` to 0. + * + * If `startOnTick` or `endOnTick` in an Axis options are set to false, + * then the `alignTicks ` will be disabled for the Axis. + * + * Disabled for logarithmic axes. + * + * @sample {highcharts} highcharts/chart/alignticks-true/ + * True by default + * @sample {highcharts} highcharts/chart/alignticks-false/ + * False + * @sample {highstock} stock/chart/alignticks-true/ + * True by default + * @sample {highstock} stock/chart/alignticks-false/ + * False + * + * @type {boolean} + * @default true + * @product highcharts highstock gantt + * @apioption chart.alignTicks + */ + /** + * Set the overall animation for all chart updating. Animation can be + * disabled throughout the chart by setting it to false here. It can + * be overridden for each individual API method as a function parameter. + * The only animation not affected by this option is the initial series + * animation, see [plotOptions.series.animation]( + * #plotOptions.series.animation). + * + * The animation can either be set as a boolean or a configuration + * object. If `true`, it will use the 'swing' jQuery easing and a + * duration of 500 ms. If used as a configuration object, the following + * properties are supported: + * + * - **duration**: The duration of the animation in milliseconds. + * + * - **easing**: A string reference to an easing function set on the + * `Math` object. See + * [the easing demo](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-animation-easing/). + * + * When zooming on a series with less than 100 points, the chart redraw + * will be done with animation, but in case of more data points, it is + * necessary to set this option to ensure animation on zoom. + * + * @sample {highcharts} highcharts/chart/animation-none/ + * Updating with no animation + * @sample {highcharts} highcharts/chart/animation-duration/ + * With a longer duration + * @sample {highcharts} highcharts/chart/animation-easing/ + * With a jQuery UI easing + * @sample {highmaps} maps/chart/animation-none/ + * Updating with no animation + * @sample {highmaps} maps/chart/animation-duration/ + * With a longer duration + * + * @type {boolean|Highcharts.AnimationOptionsObject} + * @default undefined + * @apioption chart.animation + */ + /** + * A CSS class name to apply to the charts container `div`, allowing + * unique CSS styling for each chart. + * + * @type {string} + * @apioption chart.className + */ + /** + * Event listeners for the chart. + * + * @apioption chart.events + */ + /** + * Fires when a series is added to the chart after load time, using the + * `addSeries` method. One parameter, `event`, is passed to the + * function, containing common event information. Through + * `event.options` you can access the series options that were passed to + * the `addSeries` method. Returning false prevents the series from + * being added. + * + * @sample {highcharts} highcharts/chart/events-addseries/ + * Alert on add series + * @sample {highstock} stock/chart/events-addseries/ + * Alert on add series + * + * @type {Highcharts.ChartAddSeriesCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Chart + * @apioption chart.events.addSeries + */ + /** + * Fires when clicking on the plot background. One parameter, `event`, + * is passed to the function, containing common event information. + * + * Information on the clicked spot can be found through `event.xAxis` + * and `event.yAxis`, which are arrays containing the axes of each + * dimension and each axis' value at the clicked spot. The primary axes + * are `event.xAxis[0]` and `event.yAxis[0]`. Remember the unit of a + * datetime axis is milliseconds since 1970-01-01 00:00:00. + * + * ```js + * click: function(e) { + * console.log( + * Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', e.xAxis[0].value), + * e.yAxis[0].value + * ) + * } + * ``` + * + * @sample {highcharts} highcharts/chart/events-click/ + * Alert coordinates on click + * @sample {highcharts} highcharts/chart/events-container/ + * Alternatively, attach event to container + * @sample {highstock} stock/chart/events-click/ + * Alert coordinates on click + * @sample {highstock} highcharts/chart/events-container/ + * Alternatively, attach event to container + * @sample {highmaps} maps/chart/events-click/ + * Record coordinates on click + * @sample {highmaps} highcharts/chart/events-container/ + * Alternatively, attach event to container + * + * @type {Highcharts.ChartClickCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Chart + * @apioption chart.events.click + */ + /** + * Fires when the chart is finished loading. Since v4.2.2, it also waits + * for images to be loaded, for example from point markers. One + * parameter, `event`, is passed to the function, containing common + * event information. + * + * There is also a second parameter to the chart constructor where a + * callback function can be passed to be executed on chart.load. + * + * @sample {highcharts} highcharts/chart/events-load/ + * Alert on chart load + * @sample {highstock} stock/chart/events-load/ + * Alert on chart load + * @sample {highmaps} maps/chart/events-load/ + * Add series on chart load + * + * @type {Highcharts.ChartLoadCallbackFunction} + * @context Highcharts.Chart + * @apioption chart.events.load + */ + /** + * Fires when the chart is redrawn, either after a call to + * `chart.redraw()` or after an axis, series or point is modified with + * the `redraw` option set to `true`. One parameter, `event`, is passed + * to the function, containing common event information. + * + * @sample {highcharts} highcharts/chart/events-redraw/ + * Alert on chart redraw + * @sample {highstock} stock/chart/events-redraw/ + * Alert on chart redraw when adding a series or moving the + * zoomed range + * @sample {highmaps} maps/chart/events-redraw/ + * Set subtitle on chart redraw + * + * @type {Highcharts.ChartRedrawCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Chart + * @apioption chart.events.redraw + */ + /** + * Fires after initial load of the chart (directly after the `load` + * event), and after each redraw (directly after the `redraw` event). + * + * @type {Highcharts.ChartRenderCallbackFunction} + * @since 5.0.7 + * @context Highcharts.Chart + * @apioption chart.events.render + */ + /** + * Fires when an area of the chart has been selected. Selection is + * enabled by setting the chart's zoomType. One parameter, `event`, is + * passed to the function, containing common event information. The + * default action for the selection event is to zoom the chart to the + * selected area. It can be prevented by calling + * `event.preventDefault()` or return false. + * + * Information on the selected area can be found through `event.xAxis` + * and `event.yAxis`, which are arrays containing the axes of each + * dimension and each axis' min and max values. The primary axes are + * `event.xAxis[0]` and `event.yAxis[0]`. Remember the unit of a + * datetime axis is milliseconds since 1970-01-01 00:00:00. + * + * ```js + * selection: function(event) { + * // log the min and max of the primary, datetime x-axis + * console.log( + * Highcharts.dateFormat( + * '%Y-%m-%d %H:%M:%S', + * event.xAxis[0].min + * ), + * Highcharts.dateFormat( + * '%Y-%m-%d %H:%M:%S', + * event.xAxis[0].max + * ) + * ); + * // log the min and max of the y axis + * console.log(event.yAxis[0].min, event.yAxis[0].max); + * } + * ``` + * + * @sample {highcharts} highcharts/chart/events-selection/ + * Report on selection and reset + * @sample {highcharts} highcharts/chart/events-selection-points/ + * Select a range of points through a drag selection + * @sample {highstock} stock/chart/events-selection/ + * Report on selection and reset + * @sample {highstock} highcharts/chart/events-selection-points/ + * Select a range of points through a drag selection + * (Highcharts) + * + * @type {Highcharts.ChartSelectionCallbackFunction} + * @apioption chart.events.selection + */ + /** + * The margin between the outer edge of the chart and the plot area. + * The numbers in the array designate top, right, bottom and left + * respectively. Use the options `marginTop`, `marginRight`, + * `marginBottom` and `marginLeft` for shorthand setting of one option. + * + * By default there is no margin. The actual space is dynamically + * calculated from the offset of axis labels, axis title, title, + * subtitle and legend in addition to the `spacingTop`, `spacingRight`, + * `spacingBottom` and `spacingLeft` options. + * + * @sample {highcharts} highcharts/chart/margins-zero/ + * Zero margins + * @sample {highstock} stock/chart/margin-zero/ + * Zero margins + * + * @type {number|Array} + * @apioption chart.margin + */ + /** + * The margin between the bottom outer edge of the chart and the plot + * area. Use this to set a fixed pixel value for the margin as opposed + * to the default dynamic margin. See also `spacingBottom`. + * + * @sample {highcharts} highcharts/chart/marginbottom/ + * 100px bottom margin + * @sample {highstock} stock/chart/marginbottom/ + * 100px bottom margin + * @sample {highmaps} maps/chart/margin/ + * 100px margins + * + * @type {number} + * @since 2.0 + * @apioption chart.marginBottom + */ + /** + * The margin between the left outer edge of the chart and the plot + * area. Use this to set a fixed pixel value for the margin as opposed + * to the default dynamic margin. See also `spacingLeft`. + * + * @sample {highcharts} highcharts/chart/marginleft/ + * 150px left margin + * @sample {highstock} stock/chart/marginleft/ + * 150px left margin + * @sample {highmaps} maps/chart/margin/ + * 100px margins + * + * @type {number} + * @since 2.0 + * @apioption chart.marginLeft + */ + /** + * The margin between the right outer edge of the chart and the plot + * area. Use this to set a fixed pixel value for the margin as opposed + * to the default dynamic margin. See also `spacingRight`. + * + * @sample {highcharts} highcharts/chart/marginright/ + * 100px right margin + * @sample {highstock} stock/chart/marginright/ + * 100px right margin + * @sample {highmaps} maps/chart/margin/ + * 100px margins + * + * @type {number} + * @since 2.0 + * @apioption chart.marginRight + */ + /** + * The margin between the top outer edge of the chart and the plot area. + * Use this to set a fixed pixel value for the margin as opposed to + * the default dynamic margin. See also `spacingTop`. + * + * @sample {highcharts} highcharts/chart/margintop/ 100px top margin + * @sample {highstock} stock/chart/margintop/ + * 100px top margin + * @sample {highmaps} maps/chart/margin/ + * 100px margins + * + * @type {number} + * @since 2.0 + * @apioption chart.marginTop + */ + /** + * Callback function to override the default function that formats all + * the numbers in the chart. Returns a string with the formatted number. + * + * @sample highcharts/members/highcharts-numberformat + * Arabic digits in Highcharts + * @type {Highcharts.NumberFormatterCallbackFunction} + * @since 8.0.0 + * @apioption chart.numberFormatter + */ + /** + * Allows setting a key to switch between zooming and panning. Can be + * one of `alt`, `ctrl`, `meta` (the command key on Mac and Windows + * key on Windows) or `shift`. The keys are mapped directly to the key + * properties of the click event argument (`event.altKey`, + * `event.ctrlKey`, `event.metaKey` and `event.shiftKey`). + * + * @type {string} + * @since 4.0.3 + * @product highcharts gantt + * @validvalue ["alt", "ctrl", "meta", "shift"] + * @apioption chart.panKey + */ + /** + * Allow panning in a chart. Best used with [panKey](#chart.panKey) + * to combine zooming and panning. + * + * On touch devices, when the [tooltip.followTouchMove]( + * #tooltip.followTouchMove) option is `true` (default), panning + * requires two fingers. To allow panning with one finger, set + * `followTouchMove` to `false`. + * + * @sample {highcharts} highcharts/chart/pankey/ Zooming and panning + * @sample {highstock} stock/chart/panning/ Zooming and xy panning + * + * @product highcharts highstock gantt + * @apioption chart.panning + */ + /** + * Enable or disable chart panning. + * + * @type {boolean} + * @default {highcharts} false + * @default {highstock} true + * @apioption chart.panning.enabled + */ + /** + * Decides in what dimensions the user can pan the chart. Can be + * one of `x`, `y`, or `xy`. + * + * @sample {highcharts} highcharts/chart/panning-type + * Zooming and xy panning + * + * @type {string} + * @validvalue ["x", "y", "xy"] + * @default x + * @apioption chart.panning.type + */ + /** + * Equivalent to [zoomType](#chart.zoomType), but for multitouch + * gestures only. By default, the `pinchType` is the same as the + * `zoomType` setting. However, pinching can be enabled separately in + * some cases, for example in stock charts where a mouse drag pans the + * chart, while pinching is enabled. When [tooltip.followTouchMove]( + * #tooltip.followTouchMove) is true, pinchType only applies to + * two-finger touches. + * + * @type {string} + * @default {highcharts} undefined + * @default {highstock} x + * @since 3.0 + * @product highcharts highstock gantt + * @validvalue ["x", "y", "xy"] + * @apioption chart.pinchType + */ + /** + * Whether to apply styled mode. When in styled mode, no presentational + * attributes or CSS are applied to the chart SVG. Instead, CSS rules + * are required to style the chart. The default style sheet is + * available from `https://code.highcharts.com/css/highcharts.css`. + * + * @type {boolean} + * @default false + * @since 7.0 + * @apioption chart.styledMode + */ + styledMode: false, + /** + * The corner radius of the outer chart border. + * + * @sample {highcharts} highcharts/chart/borderradius/ + * 20px radius + * @sample {highstock} stock/chart/border/ + * 10px radius + * @sample {highmaps} maps/chart/border/ + * Border options + * + */ + borderRadius: 0, + /** + * In styled mode, this sets how many colors the class names + * should rotate between. With ten colors, series (or points) are + * given class names like `highcharts-color-0`, `highcharts-color-0` + * [...] `highcharts-color-9`. The equivalent in non-styled mode + * is to set colors using the [colors](#colors) setting. + * + * @since 5.0.0 + */ + colorCount: 10, + /** + * Alias of `type`. + * + * @sample {highcharts} highcharts/chart/defaultseriestype/ + * Bar + * + * @deprecated + * + * @product highcharts + */ + defaultSeriesType: 'line', + /** + * If true, the axes will scale to the remaining visible series once + * one series is hidden. If false, hiding and showing a series will + * not affect the axes or the other series. For stacks, once one series + * within the stack is hidden, the rest of the stack will close in + * around it even if the axis is not affected. + * + * @sample {highcharts} highcharts/chart/ignorehiddenseries-true/ + * True by default + * @sample {highcharts} highcharts/chart/ignorehiddenseries-false/ + * False + * @sample {highcharts} highcharts/chart/ignorehiddenseries-true-stacked/ + * True with stack + * @sample {highstock} stock/chart/ignorehiddenseries-true/ + * True by default + * @sample {highstock} stock/chart/ignorehiddenseries-false/ + * False + * + * @since 1.2.0 + * @product highcharts highstock gantt + */ + ignoreHiddenSeries: true, + /** + * Whether to invert the axes so that the x axis is vertical and y axis + * is horizontal. When `true`, the x axis is [reversed](#xAxis.reversed) + * by default. + * + * @productdesc {highcharts} + * If a bar series is present in the chart, it will be inverted + * automatically. Inverting the chart doesn't have an effect if there + * are no cartesian series in the chart, or if the chart is + * [polar](#chart.polar). + * + * @sample {highcharts} highcharts/chart/inverted/ + * Inverted line + * @sample {highstock} stock/navigator/inverted/ + * Inverted stock chart + * + * @type {boolean} + * @default false + * @product highcharts highstock gantt + * @apioption chart.inverted + */ + /** + * The distance between the outer edge of the chart and the content, + * like title or legend, or axis title and labels if present. The + * numbers in the array designate top, right, bottom and left + * respectively. Use the options spacingTop, spacingRight, spacingBottom + * and spacingLeft options for shorthand setting of one option. + * + * @type {Array} + * @see [chart.margin](#chart.margin) + * @default [10, 10, 15, 10] + * @since 3.0.6 + */ + spacing: [10, 10, 15, 10], + /** + * The button that appears after a selection zoom, allowing the user + * to reset zoom. + */ + resetZoomButton: { + /** + * What frame the button placement should be related to. Can be + * either `plotBox` or `spacingBox`. + * + * @sample {highcharts} highcharts/chart/resetzoombutton-relativeto/ + * Relative to the chart + * @sample {highstock} highcharts/chart/resetzoombutton-relativeto/ + * Relative to the chart + * + * @type {Highcharts.ButtonRelativeToValue} + * @default plot + * @since 2.2 + * @apioption chart.resetZoomButton.relativeTo + */ + /** + * A collection of attributes for the button. The object takes SVG + * attributes like `fill`, `stroke`, `stroke-width` or `r`, the + * border radius. The theme also supports `style`, a collection of + * CSS properties for the text. Equivalent attributes for the hover + * state are given in `theme.states.hover`. + * + * @sample {highcharts} highcharts/chart/resetzoombutton-theme/ + * Theming the button + * @sample {highstock} highcharts/chart/resetzoombutton-theme/ + * Theming the button + * + * @type {Highcharts.SVGAttributes} + * @since 2.2 + */ + theme: { + /** @internal */ + zIndex: 6 + }, + /** + * The position of the button. + * + * @sample {highcharts} highcharts/chart/resetzoombutton-position/ + * Above the plot area + * @sample {highstock} highcharts/chart/resetzoombutton-position/ + * Above the plot area + * @sample {highmaps} highcharts/chart/resetzoombutton-position/ + * Above the plot area + * + * @type {Highcharts.AlignObject} + * @since 2.2 + */ + position: { + /** + * The horizontal alignment of the button. + */ + align: 'right', + /** + * The horizontal offset of the button. + */ + x: -10, + /** + * The vertical alignment of the button. + * + * @type {Highcharts.VerticalAlignValue} + * @default top + * @apioption chart.resetZoomButton.position.verticalAlign + */ + /** + * The vertical offset of the button. + */ + y: 10 + } + }, + /** + * The pixel width of the plot area border. + * + * @sample {highcharts} highcharts/chart/plotborderwidth/ + * 1px border + * @sample {highstock} stock/chart/plotborder/ + * 2px border + * @sample {highmaps} maps/chart/plotborder/ + * Plot border options + * + * @type {number} + * @default 0 + * @apioption chart.plotBorderWidth + */ + /** + * Whether to apply a drop shadow to the plot area. Requires that + * plotBackgroundColor be set. The shadow can be an object configuration + * containing `color`, `offsetX`, `offsetY`, `opacity` and `width`. + * + * @sample {highcharts} highcharts/chart/plotshadow/ + * Plot shadow + * @sample {highstock} stock/chart/plotshadow/ + * Plot shadow + * @sample {highmaps} maps/chart/plotborder/ + * Plot border options + * + * @type {boolean|Highcharts.CSSObject} + * @default false + * @apioption chart.plotShadow + */ + /** + * When true, cartesian charts like line, spline, area and column are + * transformed into the polar coordinate system. This produces _polar + * charts_, also known as _radar charts_. + * + * @sample {highcharts} highcharts/demo/polar/ + * Polar chart + * @sample {highcharts} highcharts/demo/polar-wind-rose/ + * Wind rose, stacked polar column chart + * @sample {highcharts} highcharts/demo/polar-spider/ + * Spider web chart + * @sample {highcharts} highcharts/parallel-coordinates/polar/ + * Star plot, multivariate data in a polar chart + * + * @type {boolean} + * @default false + * @since 2.3.0 + * @product highcharts + * @requires highcharts-more + * @apioption chart.polar + */ + /** + * Whether to reflow the chart to fit the width of the container div + * on resizing the window. + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * True by default + * @sample {highcharts} highcharts/chart/reflow-false/ + * False + * @sample {highstock} stock/chart/reflow-true/ + * True by default + * @sample {highstock} stock/chart/reflow-false/ + * False + * @sample {highmaps} maps/chart/reflow-true/ + * True by default + * @sample {highmaps} maps/chart/reflow-false/ + * False + * + * @type {boolean} + * @default true + * @since 2.1 + * @apioption chart.reflow + */ + /** + * The HTML element where the chart will be rendered. If it is a string, + * the element by that id is used. The HTML element can also be passed + * by direct reference, or as the first argument of the chart + * constructor, in which case the option is not needed. + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * String + * @sample {highcharts} highcharts/chart/renderto-object/ + * Object reference + * @sample {highcharts} highcharts/chart/renderto-jquery/ + * Object reference through jQuery + * @sample {highstock} stock/chart/renderto-string/ + * String + * @sample {highstock} stock/chart/renderto-object/ + * Object reference + * @sample {highstock} stock/chart/renderto-jquery/ + * Object reference through jQuery + * + * @type {string|Highcharts.HTMLDOMElement} + * @apioption chart.renderTo + */ + /** + * The background color of the marker square when selecting (zooming + * in on) an area of the chart. + * + * @see In styled mode, the selection marker fill is set with the + * `.highcharts-selection-marker` class. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default rgba(51,92,173,0.25) + * @since 2.1.7 + * @apioption chart.selectionMarkerFill + */ + /** + * Whether to apply a drop shadow to the outer chart area. Requires + * that backgroundColor be set. The shadow can be an object + * configuration containing `color`, `offsetX`, `offsetY`, `opacity` and + * `width`. + * + * @sample {highcharts} highcharts/chart/shadow/ + * Shadow + * @sample {highstock} stock/chart/shadow/ + * Shadow + * @sample {highmaps} maps/chart/border/ + * Chart border and shadow + * + * @type {boolean|Highcharts.CSSObject} + * @default false + * @apioption chart.shadow + */ + /** + * Whether to show the axes initially. This only applies to empty charts + * where series are added dynamically, as axes are automatically added + * to cartesian series. + * + * @sample {highcharts} highcharts/chart/showaxes-false/ + * False by default + * @sample {highcharts} highcharts/chart/showaxes-true/ + * True + * + * @type {boolean} + * @since 1.2.5 + * @product highcharts gantt + * @apioption chart.showAxes + */ + /** + * The space between the bottom edge of the chart and the content (plot + * area, axis title and labels, title, subtitle or legend in top + * position). + * + * @sample {highcharts} highcharts/chart/spacingbottom/ + * Spacing bottom set to 100 + * @sample {highstock} stock/chart/spacingbottom/ + * Spacing bottom set to 100 + * @sample {highmaps} maps/chart/spacing/ + * Spacing 100 all around + * + * @type {number} + * @default 15 + * @since 2.1 + * @apioption chart.spacingBottom + */ + /** + * The space between the left edge of the chart and the content (plot + * area, axis title and labels, title, subtitle or legend in top + * position). + * + * @sample {highcharts} highcharts/chart/spacingleft/ + * Spacing left set to 100 + * @sample {highstock} stock/chart/spacingleft/ + * Spacing left set to 100 + * @sample {highmaps} maps/chart/spacing/ + * Spacing 100 all around + * + * @type {number} + * @default 10 + * @since 2.1 + * @apioption chart.spacingLeft + */ + /** + * The space between the right edge of the chart and the content (plot + * area, axis title and labels, title, subtitle or legend in top + * position). + * + * @sample {highcharts} highcharts/chart/spacingright-100/ + * Spacing set to 100 + * @sample {highcharts} highcharts/chart/spacingright-legend/ + * Legend in right position with default spacing + * @sample {highstock} stock/chart/spacingright/ + * Spacing set to 100 + * @sample {highmaps} maps/chart/spacing/ + * Spacing 100 all around + * + * @type {number} + * @default 10 + * @since 2.1 + * @apioption chart.spacingRight + */ + /** + * The space between the top edge of the chart and the content (plot + * area, axis title and labels, title, subtitle or legend in top + * position). + * + * @sample {highcharts} highcharts/chart/spacingtop-100/ + * A top spacing of 100 + * @sample {highcharts} highcharts/chart/spacingtop-10/ + * Floating chart title makes the plot area align to the default + * spacingTop of 10. + * @sample {highstock} stock/chart/spacingtop/ + * A top spacing of 100 + * @sample {highmaps} maps/chart/spacing/ + * Spacing 100 all around + * + * @type {number} + * @default 10 + * @since 2.1 + * @apioption chart.spacingTop + */ + /** + * Additional CSS styles to apply inline to the container `div`. Note + * that since the default font styles are applied in the renderer, it + * is ignorant of the individual chart options and must be set globally. + * + * @see In styled mode, general chart styles can be set with the + * `.highcharts-root` class. + * @sample {highcharts} highcharts/chart/style-serif-font/ + * Using a serif type font + * @sample {highcharts} highcharts/css/em/ + * Styled mode with relative font sizes + * @sample {highstock} stock/chart/style/ + * Using a serif type font + * @sample {highmaps} maps/chart/style-serif-font/ + * Using a serif type font + * + * @type {Highcharts.CSSObject} + * @default {"fontFamily": "\"Lucida Grande\", \"Lucida Sans Unicode\", Verdana, Arial, Helvetica, sans-serif","fontSize":"12px"} + * @apioption chart.style + */ + /** + * The default series type for the chart. Can be any of the chart types + * listed under [plotOptions](#plotOptions) and [series](#series) or can + * be a series provided by an additional module. + * + * In TypeScript this option has no effect in sense of typing and + * instead the `type` option must always be set in the series. + * + * @sample {highcharts} highcharts/chart/type-bar/ + * Bar + * @sample {highstock} stock/chart/type/ + * Areaspline + * @sample {highmaps} maps/chart/type-mapline/ + * Mapline + * + * @type {string} + * @default {highcharts} line + * @default {highstock} line + * @default {highmaps} map + * @since 2.1.0 + * @apioption chart.type + */ + /** + * Decides in what dimensions the user can zoom by dragging the mouse. + * Can be one of `x`, `y` or `xy`. + * + * @see [panKey](#chart.panKey) + * + * @sample {highcharts} highcharts/chart/zoomtype-none/ + * None by default + * @sample {highcharts} highcharts/chart/zoomtype-x/ + * X + * @sample {highcharts} highcharts/chart/zoomtype-y/ + * Y + * @sample {highcharts} highcharts/chart/zoomtype-xy/ + * Xy + * @sample {highstock} stock/demo/basic-line/ + * None by default + * @sample {highstock} stock/chart/zoomtype-x/ + * X + * @sample {highstock} stock/chart/zoomtype-y/ + * Y + * @sample {highstock} stock/chart/zoomtype-xy/ + * Xy + * + * @type {string} + * @product highcharts highstock gantt + * @validvalue ["x", "y", "xy"] + * @apioption chart.zoomType + */ + /** + * An explicit width for the chart. By default (when `null`) the width + * is calculated from the offset width of the containing element. + * + * @sample {highcharts} highcharts/chart/width/ + * 800px wide + * @sample {highstock} stock/chart/width/ + * 800px wide + * @sample {highmaps} maps/chart/size/ + * Chart with explicit size + * + * @type {null|number|string} + */ + width: null, + /** + * An explicit height for the chart. If a _number_, the height is + * given in pixels. If given a _percentage string_ (for example + * `'56%'`), the height is given as the percentage of the actual chart + * width. This allows for preserving the aspect ratio across responsive + * sizes. + * + * By default (when `null`) the height is calculated from the offset + * height of the containing element, or 400 pixels if the containing + * element's height is 0. + * + * @sample {highcharts} highcharts/chart/height/ + * 500px height + * @sample {highstock} stock/chart/height/ + * 300px height + * @sample {highmaps} maps/chart/size/ + * Chart with explicit size + * @sample highcharts/chart/height-percent/ + * Highcharts with percentage height + * + * @type {null|number|string} + */ + height: null, + /** + * The color of the outer chart border. + * + * @see In styled mode, the stroke is set with the + * `.highcharts-background` class. + * + * @sample {highcharts} highcharts/chart/bordercolor/ + * Brown border + * @sample {highstock} stock/chart/border/ + * Brown border + * @sample {highmaps} maps/chart/border/ + * Border options + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + borderColor: '#335cad', + /** + * The pixel width of the outer chart border. + * + * @see In styled mode, the stroke is set with the + * `.highcharts-background` class. + * + * @sample {highcharts} highcharts/chart/borderwidth/ + * 5px border + * @sample {highstock} stock/chart/border/ + * 2px border + * @sample {highmaps} maps/chart/border/ + * Border options + * + * @type {number} + * @default 0 + * @apioption chart.borderWidth + */ + /** + * The background color or gradient for the outer chart area. + * + * @see In styled mode, the background is set with the + * `.highcharts-background` class. + * + * @sample {highcharts} highcharts/chart/backgroundcolor-color/ + * Color + * @sample {highcharts} highcharts/chart/backgroundcolor-gradient/ + * Gradient + * @sample {highstock} stock/chart/backgroundcolor-color/ + * Color + * @sample {highstock} stock/chart/backgroundcolor-gradient/ + * Gradient + * @sample {highmaps} maps/chart/backgroundcolor-color/ + * Color + * @sample {highmaps} maps/chart/backgroundcolor-gradient/ + * Gradient + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + backgroundColor: '#ffffff', + /** + * The background color or gradient for the plot area. + * + * @see In styled mode, the plot background is set with the + * `.highcharts-plot-background` class. + * + * @sample {highcharts} highcharts/chart/plotbackgroundcolor-color/ + * Color + * @sample {highcharts} highcharts/chart/plotbackgroundcolor-gradient/ + * Gradient + * @sample {highstock} stock/chart/plotbackgroundcolor-color/ + * Color + * @sample {highstock} stock/chart/plotbackgroundcolor-gradient/ + * Gradient + * @sample {highmaps} maps/chart/plotbackgroundcolor-color/ + * Color + * @sample {highmaps} maps/chart/plotbackgroundcolor-gradient/ + * Gradient + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption chart.plotBackgroundColor + */ + /** + * The URL for an image to use as the plot background. To set an image + * as the background for the entire chart, set a CSS background image + * to the container element. Note that for the image to be applied to + * exported charts, its URL needs to be accessible by the export server. + * + * @see In styled mode, a plot background image can be set with the + * `.highcharts-plot-background` class and a [custom pattern]( + * https://www.highcharts.com/docs/chart-design-and-style/ + * gradients-shadows-and-patterns). + * + * @sample {highcharts} highcharts/chart/plotbackgroundimage/ + * Skies + * @sample {highstock} stock/chart/plotbackgroundimage/ + * Skies + * + * @type {string} + * @apioption chart.plotBackgroundImage + */ + /** + * The color of the inner chart or plot area border. + * + * @see In styled mode, a plot border stroke can be set with the + * `.highcharts-plot-border` class. + * + * @sample {highcharts} highcharts/chart/plotbordercolor/ + * Blue border + * @sample {highstock} stock/chart/plotborder/ + * Blue border + * @sample {highmaps} maps/chart/plotborder/ + * Plot border options + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + plotBorderColor: '#cccccc' + }, + /** + * The chart's main title. + * + * @sample {highmaps} maps/title/title/ + * Title options demonstrated + */ + title: { + /** + * When the title is floating, the plot area will not move to make space + * for it. + * + * @sample {highcharts} highcharts/chart/zoomtype-none/ + * False by default + * @sample {highcharts} highcharts/title/floating/ + * True - title on top of the plot area + * @sample {highstock} stock/chart/title-floating/ + * True - title on top of the plot area + * + * @type {boolean} + * @default false + * @since 2.1 + * @apioption title.floating + */ + /** + * CSS styles for the title. Use this for font styling, but use `align`, + * `x` and `y` for text alignment. + * + * In styled mode, the title style is given in the `.highcharts-title` + * class. + * + * @sample {highcharts} highcharts/title/style/ + * Custom color and weight + * @sample {highstock} stock/chart/title-style/ + * Custom color and weight + * @sample highcharts/css/titles/ + * Styled mode + * + * @type {Highcharts.CSSObject} + * @default {highcharts|highmaps} { "color": "#333333", "fontSize": "18px" } + * @default {highstock} { "color": "#333333", "fontSize": "16px" } + * @apioption title.style + */ + /** + * Whether to + * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the text. + * + * @type {boolean} + * @default false + * @apioption title.useHTML + */ + /** + * The vertical alignment of the title. Can be one of `"top"`, + * `"middle"` and `"bottom"`. When a value is given, the title behaves + * as if [floating](#title.floating) were `true`. + * + * @sample {highcharts} highcharts/title/verticalalign/ + * Chart title in bottom right corner + * @sample {highstock} stock/chart/title-verticalalign/ + * Chart title in bottom right corner + * + * @type {Highcharts.VerticalAlignValue} + * @since 2.1 + * @apioption title.verticalAlign + */ + /** + * The x position of the title relative to the alignment within + * `chart.spacingLeft` and `chart.spacingRight`. + * + * @sample {highcharts} highcharts/title/align/ + * Aligned to the plot area (x = 70px = margin left - spacing + * left) + * @sample {highstock} stock/chart/title-align/ + * Aligned to the plot area (x = 50px = margin left - spacing + * left) + * + * @type {number} + * @default 0 + * @since 2.0 + * @apioption title.x + */ + /** + * The y position of the title relative to the alignment within + * [chart.spacingTop](#chart.spacingTop) and [chart.spacingBottom]( + * #chart.spacingBottom). By default it depends on the font size. + * + * @sample {highcharts} highcharts/title/y/ + * Title inside the plot area + * @sample {highstock} stock/chart/title-verticalalign/ + * Chart title in bottom right corner + * + * @type {number} + * @since 2.0 + * @apioption title.y + */ + /** + * The title of the chart. To disable the title, set the `text` to + * `undefined`. + * + * @sample {highcharts} highcharts/title/text/ + * Custom title + * @sample {highstock} stock/chart/title-text/ + * Custom title + * + * @default {highcharts|highmaps} Chart title + * @default {highstock} undefined + */ + text: 'Chart title', + /** + * The horizontal alignment of the title. Can be one of "left", "center" + * and "right". + * + * @sample {highcharts} highcharts/title/align/ + * Aligned to the plot area (x = 70px = margin left - spacing + * left) + * @sample {highstock} stock/chart/title-align/ + * Aligned to the plot area (x = 50px = margin left - spacing + * left) + * + * @type {Highcharts.AlignValue} + * @since 2.0 + */ + align: 'center', + /** + * The margin between the title and the plot area, or if a subtitle + * is present, the margin between the subtitle and the plot area. + * + * @sample {highcharts} highcharts/title/margin-50/ + * A chart title margin of 50 + * @sample {highcharts} highcharts/title/margin-subtitle/ + * The same margin applied with a subtitle + * @sample {highstock} stock/chart/title-margin/ + * A chart title margin of 50 + * + * @since 2.1 + */ + margin: 15, + /** + * Adjustment made to the title width, normally to reserve space for + * the exporting burger menu. + * + * @sample highcharts/title/widthadjust/ + * Wider menu, greater padding + * + * @since 4.2.5 + */ + widthAdjust: -44 + }, + /** + * The chart's subtitle. This can be used both to display a subtitle below + * the main title, and to display random text anywhere in the chart. The + * subtitle can be updated after chart initialization through the + * `Chart.setTitle` method. + * + * @sample {highmaps} maps/title/subtitle/ + * Subtitle options demonstrated + */ + subtitle: { + /** + * When the subtitle is floating, the plot area will not move to make + * space for it. + * + * @sample {highcharts} highcharts/subtitle/floating/ + * Floating title and subtitle + * @sample {highstock} stock/chart/subtitle-footnote + * Footnote floating at bottom right of plot area + * + * @type {boolean} + * @default false + * @since 2.1 + * @apioption subtitle.floating + */ + /** + * CSS styles for the title. + * + * In styled mode, the subtitle style is given in the + * `.highcharts-subtitle` class. + * + * @sample {highcharts} highcharts/subtitle/style/ + * Custom color and weight + * @sample {highcharts} highcharts/css/titles/ + * Styled mode + * @sample {highstock} stock/chart/subtitle-style + * Custom color and weight + * @sample {highstock} highcharts/css/titles/ + * Styled mode + * @sample {highmaps} highcharts/css/titles/ + * Styled mode + * + * @type {Highcharts.CSSObject} + * @default {"color": "#666666"} + * @apioption subtitle.style + */ + /** + * Whether to + * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the text. + * + * @type {boolean} + * @default false + * @apioption subtitle.useHTML + */ + /** + * The vertical alignment of the title. Can be one of `"top"`, + * `"middle"` and `"bottom"`. When middle, the subtitle behaves as + * floating. + * + * @sample {highcharts} highcharts/subtitle/verticalalign/ + * Footnote at the bottom right of plot area + * @sample {highstock} stock/chart/subtitle-footnote + * Footnote at the bottom right of plot area + * + * @type {Highcharts.VerticalAlignValue} + * @since 2.1 + * @apioption subtitle.verticalAlign + */ + /** + * The x position of the subtitle relative to the alignment within + * `chart.spacingLeft` and `chart.spacingRight`. + * + * @sample {highcharts} highcharts/subtitle/align/ + * Footnote at right of plot area + * @sample {highstock} stock/chart/subtitle-footnote + * Footnote at the bottom right of plot area + * + * @type {number} + * @default 0 + * @since 2.0 + * @apioption subtitle.x + */ + /** + * The y position of the subtitle relative to the alignment within + * `chart.spacingTop` and `chart.spacingBottom`. By default the subtitle + * is laid out below the title unless the title is floating. + * + * @sample {highcharts} highcharts/subtitle/verticalalign/ + * Footnote at the bottom right of plot area + * @sample {highstock} stock/chart/subtitle-footnote + * Footnote at the bottom right of plot area + * + * @type {number} + * @since 2.0 + * @apioption subtitle.y + */ + /** + * The subtitle of the chart. + * + * @sample {highcharts|highstock} highcharts/subtitle/text/ + * Custom subtitle + * @sample {highcharts|highstock} highcharts/subtitle/text-formatted/ + * Formatted and linked text. + */ + text: '', + /** + * The horizontal alignment of the subtitle. Can be one of "left", + * "center" and "right". + * + * @sample {highcharts} highcharts/subtitle/align/ + * Footnote at right of plot area + * @sample {highstock} stock/chart/subtitle-footnote + * Footnote at bottom right of plot area + * + * @type {Highcharts.AlignValue} + * @since 2.0 + */ + align: 'center', + /** + * Adjustment made to the subtitle width, normally to reserve space + * for the exporting burger menu. + * + * @see [title.widthAdjust](#title.widthAdjust) + * + * @sample highcharts/title/widthadjust/ + * Wider menu, greater padding + * + * @since 4.2.5 + */ + widthAdjust: -44 + }, + /** + * The chart's caption, which will render below the chart and will be part + * of exported charts. The caption can be updated after chart initialization + * through the `Chart.update` or `Chart.caption.update` methods. + * + * @sample highcharts/caption/text/ + * A chart with a caption + * @since 7.2.0 + */ + caption: { + /** + * When the caption is floating, the plot area will not move to make + * space for it. + * + * @type {boolean} + * @default false + * @apioption caption.floating + */ + /** + * The margin between the caption and the plot area. + */ + margin: 15, + /** + * CSS styles for the caption. + * + * In styled mode, the caption style is given in the + * `.highcharts-caption` class. + * + * @sample {highcharts} highcharts/css/titles/ + * Styled mode + * + * @type {Highcharts.CSSObject} + * @default {"color": "#666666"} + * @apioption caption.style + */ + /** + * Whether to + * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the text. + * + * @type {boolean} + * @default false + * @apioption caption.useHTML + */ + /** + * The x position of the caption relative to the alignment within + * `chart.spacingLeft` and `chart.spacingRight`. + * + * @type {number} + * @default 0 + * @apioption caption.x + */ + /** + * The y position of the caption relative to the alignment within + * `chart.spacingTop` and `chart.spacingBottom`. + * + * @type {number} + * @apioption caption.y + */ + /** + * The caption text of the chart. + * + * @sample {highcharts} highcharts/caption/text/ + * Custom caption + */ + text: '', + /** + * The horizontal alignment of the caption. Can be one of "left", + * "center" and "right". + * + * @type {Highcharts.AlignValue} + */ + align: 'left', + /** + * The vertical alignment of the caption. Can be one of `"top"`, + * `"middle"` and `"bottom"`. When middle, the caption behaves as + * floating. + * + * @type {Highcharts.VerticalAlignValue} + */ + verticalAlign: 'bottom' + }, + /** + * The plotOptions is a wrapper object for config objects for each series + * type. The config objects for each series can also be overridden for + * each series item as given in the series array. + * + * Configuration options for the series are given in three levels. Options + * for all series in a chart are given in the [plotOptions.series]( + * #plotOptions.series) object. Then options for all series of a specific + * type are given in the plotOptions of that type, for example + * `plotOptions.line`. Next, options for one single series are given in + * [the series array](#series). + */ + plotOptions: {}, + /** + * HTML labels that can be positioned anywhere in the chart area. + * + * This option is deprecated since v7.1.2. Instead, use + * [annotations](#annotations) that support labels. + * + * @deprecated + * @product highcharts highstock + */ + labels: { + /** + * An HTML label that can be positioned anywhere in the chart area. + * + * @deprecated + * @type {Array<*>} + * @apioption labels.items + */ + /** + * Inner HTML or text for the label. + * + * @deprecated + * @type {string} + * @apioption labels.items.html + */ + /** + * CSS styles for each label. To position the label, use left and top + * like this: + * ```js + * style: { + * left: '100px', + * top: '100px' + * } + * ``` + * + * @deprecated + * @type {Highcharts.CSSObject} + * @apioption labels.items.style + */ + /** + * Shared CSS styles for all labels. + * + * @deprecated + * @type {Highcharts.CSSObject} + * @default {"color": "#333333", "position": "absolute"} + */ + style: { + /** + * @ignore-option + */ + position: 'absolute', + /** + * @ignore-option + */ + color: '#333333' + } + }, + /** + * The legend is a box containing a symbol and name for each series + * item or point item in the chart. Each series (or points in case + * of pie charts) is represented by a symbol and its name in the legend. + * + * It is possible to override the symbol creator function and create + * [custom legend symbols](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/studies/legend-custom-symbol/). + * + * @productdesc {highmaps} + * A Highmaps legend by default contains one legend item per series, but if + * a `colorAxis` is defined, the axis will be displayed in the legend. + * Either as a gradient, or as multiple legend items for `dataClasses`. + */ + legend: { + /** + * The background color of the legend. + * + * @see In styled mode, the legend background fill can be applied with + * the `.highcharts-legend-box` class. + * + * @sample {highcharts} highcharts/legend/backgroundcolor/ + * Yellowish background + * @sample {highstock} stock/legend/align/ + * Various legend options + * @sample {highmaps} maps/legend/border-background/ + * Border and background options + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption legend.backgroundColor + */ + /** + * The width of the drawn border around the legend. + * + * @see In styled mode, the legend border stroke width can be applied + * with the `.highcharts-legend-box` class. + * + * @sample {highcharts} highcharts/legend/borderwidth/ + * 2px border width + * @sample {highstock} stock/legend/align/ + * Various legend options + * @sample {highmaps} maps/legend/border-background/ + * Border and background options + * + * @type {number} + * @default 0 + * @apioption legend.borderWidth + */ + /** + * Enable or disable the legend. There is also a series-specific option, + * [showInLegend](#plotOptions.series.showInLegend), that can hide the + * series from the legend. In some series types this is `false` by + * default, so it must set to `true` in order to show the legend for the + * series. + * + * @sample {highcharts} highcharts/legend/enabled-false/ Legend disabled + * @sample {highstock} stock/legend/align/ Various legend options + * @sample {highmaps} maps/legend/enabled-false/ Legend disabled + * + * @default {highstock} false + * @default {highmaps} true + * @default {gantt} false + */ + enabled: true, + /** + * The horizontal alignment of the legend box within the chart area. + * Valid values are `left`, `center` and `right`. + * + * In the case that the legend is aligned in a corner position, the + * `layout` option will determine whether to place it above/below + * or on the side of the plot area. + * + * @sample {highcharts} highcharts/legend/align/ + * Legend at the right of the chart + * @sample {highstock} stock/legend/align/ + * Various legend options + * @sample {highmaps} maps/legend/alignment/ + * Legend alignment + * + * @type {Highcharts.AlignValue} + * @since 2.0 + */ + align: 'center', + /** + * If the [layout](legend.layout) is `horizontal` and the legend items + * span over two lines or more, whether to align the items into vertical + * columns. Setting this to `false` makes room for more items, but will + * look more messy. + * + * @since 6.1.0 + */ + alignColumns: true, + /** + * When the legend is floating, the plot area ignores it and is allowed + * to be placed below it. + * + * @sample {highcharts} highcharts/legend/floating-false/ + * False by default + * @sample {highcharts} highcharts/legend/floating-true/ + * True + * @sample {highmaps} maps/legend/alignment/ + * Floating legend + * + * @type {boolean} + * @default false + * @since 2.1 + * @apioption legend.floating + */ + /** + * The layout of the legend items. Can be one of `horizontal` or + * `vertical` or `proximate`. When `proximate`, the legend items will be + * placed as close as possible to the graphs they're representing, + * except in inverted charts or when the legend position doesn't allow + * it. + * + * @sample {highcharts} highcharts/legend/layout-horizontal/ + * Horizontal by default + * @sample {highcharts} highcharts/legend/layout-vertical/ + * Vertical + * @sample highcharts/legend/layout-proximate + * Labels proximate to the data + * @sample {highstock} stock/legend/layout-horizontal/ + * Horizontal by default + * @sample {highmaps} maps/legend/padding-itemmargin/ + * Vertical with data classes + * @sample {highmaps} maps/legend/layout-vertical/ + * Vertical with color axis gradient + * + * @validvalue ["horizontal", "vertical", "proximate"] + */ + layout: 'horizontal', + /** + * In a legend with horizontal layout, the itemDistance defines the + * pixel distance between each item. + * + * @sample {highcharts} highcharts/legend/layout-horizontal/ + * 50px item distance + * @sample {highstock} highcharts/legend/layout-horizontal/ + * 50px item distance + * + * @type {number} + * @default {highcharts} 20 + * @default {highstock} 20 + * @default {highmaps} 8 + * @since 3.0.3 + * @apioption legend.itemDistance + */ + /** + * The pixel bottom margin for each legend item. + * + * @sample {highcharts|highstock} highcharts/legend/padding-itemmargin/ + * Padding and item margins demonstrated + * @sample {highmaps} maps/legend/padding-itemmargin/ + * Padding and item margins demonstrated + * + * @type {number} + * @default 0 + * @since 2.2.0 + * @apioption legend.itemMarginBottom + */ + /** + * The pixel top margin for each legend item. + * + * @sample {highcharts|highstock} highcharts/legend/padding-itemmargin/ + * Padding and item margins demonstrated + * @sample {highmaps} maps/legend/padding-itemmargin/ + * Padding and item margins demonstrated + * + * @type {number} + * @default 0 + * @since 2.2.0 + * @apioption legend.itemMarginTop + */ + /** + * The width for each legend item. By default the items are laid out + * successively. In a [horizontal layout](legend.layout), if the items + * are laid out across two rows or more, they will be vertically aligned + * depending on the [legend.alignColumns](legend.alignColumns) option. + * + * @sample {highcharts} highcharts/legend/itemwidth-default/ + * Undefined by default + * @sample {highcharts} highcharts/legend/itemwidth-80/ + * 80 for aligned legend items + * + * @type {number} + * @since 2.0 + * @apioption legend.itemWidth + */ + /** + * A [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) + * for each legend label. Available variables relates to properties on + * the series, or the point in case of pies. + * + * @type {string} + * @default {name} + * @since 1.3 + * @apioption legend.labelFormat + */ + /* eslint-disable valid-jsdoc */ + /** + * Callback function to format each of the series' labels. The `this` + * keyword refers to the series object, or the point object in case of + * pie charts. By default the series or point name is printed. + * + * @productdesc {highmaps} + * In Highmaps the context can also be a data class in case of a + * `colorAxis`. + * + * @sample {highcharts} highcharts/legend/labelformatter/ + * Add text + * @sample {highmaps} maps/legend/labelformatter/ + * Data classes with label formatter + * + * @type {Highcharts.FormatterCallbackFunction} + */ + labelFormatter: function () { + /** eslint-enable valid-jsdoc */ + return this.name; + }, + /** + * Line height for the legend items. Deprecated as of 2.1\. Instead, + * the line height for each item can be set using + * `itemStyle.lineHeight`, and the padding between items using + * `itemMarginTop` and `itemMarginBottom`. + * + * @sample {highcharts} highcharts/legend/lineheight/ + * Setting padding + * + * @deprecated + * + * @type {number} + * @default 16 + * @since 2.0 + * @product highcharts gantt + * @apioption legend.lineHeight + */ + /** + * If the plot area sized is calculated automatically and the legend is + * not floating, the legend margin is the space between the legend and + * the axis labels or plot area. + * + * @sample {highcharts} highcharts/legend/margin-default/ + * 12 pixels by default + * @sample {highcharts} highcharts/legend/margin-30/ + * 30 pixels + * + * @type {number} + * @default 12 + * @since 2.1 + * @apioption legend.margin + */ + /** + * Maximum pixel height for the legend. When the maximum height is + * extended, navigation will show. + * + * @type {number} + * @since 2.3.0 + * @apioption legend.maxHeight + */ + /** + * The color of the drawn border around the legend. + * + * @see In styled mode, the legend border stroke can be applied with the + * `.highcharts-legend-box` class. + * + * @sample {highcharts} highcharts/legend/bordercolor/ + * Brown border + * @sample {highstock} stock/legend/align/ + * Various legend options + * @sample {highmaps} maps/legend/border-background/ + * Border and background options + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + borderColor: '#999999', + /** + * The border corner radius of the legend. + * + * @sample {highcharts} highcharts/legend/borderradius-default/ + * Square by default + * @sample {highcharts} highcharts/legend/borderradius-round/ + * 5px rounded + * @sample {highmaps} maps/legend/border-background/ + * Border and background options + */ + borderRadius: 0, + /** + * Options for the paging or navigation appearing when the legend is + * overflown. Navigation works well on screen, but not in static + * exported images. One way of working around that is to + * [increase the chart height in + * export](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/legend/navigation-enabled-false/). + */ + navigation: { + /** + * How to animate the pages when navigating up or down. A value of + * `true` applies the default navigation given in the + * `chart.animation` option. Additional options can be given as an + * object containing values for easing and duration. + * + * @sample {highcharts} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * @sample {highstock} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * + * @type {boolean|Highcharts.AnimationOptionsObject} + * @default true + * @since 2.2.4 + * @apioption legend.navigation.animation + */ + /** + * The pixel size of the up and down arrows in the legend paging + * navigation. + * + * @sample {highcharts} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * @sample {highstock} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * + * @type {number} + * @default 12 + * @since 2.2.4 + * @apioption legend.navigation.arrowSize + */ + /** + * Whether to enable the legend navigation. In most cases, disabling + * the navigation results in an unwanted overflow. + * + * See also the [adapt chart to legend]( + * https://www.highcharts.com/products/plugin-registry/single/8/Adapt-Chart-To-Legend) + * plugin for a solution to extend the chart height to make room for + * the legend, optionally in exported charts only. + * + * @type {boolean} + * @default true + * @since 4.2.4 + * @apioption legend.navigation.enabled + */ + /** + * Text styles for the legend page navigation. + * + * @see In styled mode, the navigation items are styled with the + * `.highcharts-legend-navigation` class. + * + * @sample {highcharts} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * @sample {highstock} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * + * @type {Highcharts.CSSObject} + * @since 2.2.4 + * @apioption legend.navigation.style + */ + /** + * The color for the active up or down arrow in the legend page + * navigation. + * + * @see In styled mode, the active arrow be styled with the + * `.highcharts-legend-nav-active` class. + * + * @sample {highcharts} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * @sample {highstock} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.2.4 + */ + activeColor: '#003399', + /** + * The color of the inactive up or down arrow in the legend page + * navigation. . + * + * @see In styled mode, the inactive arrow be styled with the + * `.highcharts-legend-nav-inactive` class. + * + * @sample {highcharts} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * @sample {highstock} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.2.4 + */ + inactiveColor: '#cccccc' + }, + /** + * The inner padding of the legend box. + * + * @sample {highcharts|highstock} highcharts/legend/padding-itemmargin/ + * Padding and item margins demonstrated + * @sample {highmaps} maps/legend/padding-itemmargin/ + * Padding and item margins demonstrated + * + * @type {number} + * @default 8 + * @since 2.2.0 + * @apioption legend.padding + */ + /** + * Whether to reverse the order of the legend items compared to the + * order of the series or points as defined in the configuration object. + * + * @see [yAxis.reversedStacks](#yAxis.reversedStacks), + * [series.legendIndex](#series.legendIndex) + * + * @sample {highcharts} highcharts/legend/reversed/ + * Stacked bar with reversed legend + * + * @type {boolean} + * @default false + * @since 1.2.5 + * @apioption legend.reversed + */ + /** + * Whether to show the symbol on the right side of the text rather than + * the left side. This is common in Arabic and Hebraic. + * + * @sample {highcharts} highcharts/legend/rtl/ + * Symbol to the right + * + * @type {boolean} + * @default false + * @since 2.2 + * @apioption legend.rtl + */ + /** + * CSS styles for the legend area. In the 1.x versions the position + * of the legend area was determined by CSS. In 2.x, the position is + * determined by properties like `align`, `verticalAlign`, `x` and `y`, + * but the styles are still parsed for backwards compatibility. + * + * @deprecated + * + * @type {Highcharts.CSSObject} + * @product highcharts highstock + * @apioption legend.style + */ + /** + * CSS styles for each legend item. Only a subset of CSS is supported, + * notably those options related to text. The default `textOverflow` + * property makes long texts truncate. Set it to `undefined` to wrap + * text instead. A `width` property can be added to control the text + * width. + * + * @see In styled mode, the legend items can be styled with the + * `.highcharts-legend-item` class. + * + * @sample {highcharts} highcharts/legend/itemstyle/ + * Bold black text + * @sample {highmaps} maps/legend/itemstyle/ + * Item text styles + * + * @type {Highcharts.CSSObject} + * @default {"color": "#333333", "cursor": "pointer", "fontSize": "12px", "fontWeight": "bold", "textOverflow": "ellipsis"} + */ + itemStyle: { + /** + * @ignore + */ + color: '#333333', + /** + * @ignore + */ + cursor: 'pointer', + /** + * @ignore + */ + fontSize: '12px', + /** + * @ignore + */ + fontWeight: 'bold', + /** + * @ignore + */ + textOverflow: 'ellipsis' + }, + /** + * CSS styles for each legend item in hover mode. Only a subset of + * CSS is supported, notably those options related to text. Properties + * are inherited from `style` unless overridden here. + * + * @see In styled mode, the hovered legend items can be styled with + * the `.highcharts-legend-item:hover` pesudo-class. + * + * @sample {highcharts} highcharts/legend/itemhoverstyle/ + * Red on hover + * @sample {highmaps} maps/legend/itemstyle/ + * Item text styles + * + * @type {Highcharts.CSSObject} + * @default {"color": "#000000"} + */ + itemHoverStyle: { + /** + * @ignore + */ + color: '#000000' + }, + /** + * CSS styles for each legend item when the corresponding series or + * point is hidden. Only a subset of CSS is supported, notably those + * options related to text. Properties are inherited from `style` + * unless overridden here. + * + * @see In styled mode, the hidden legend items can be styled with + * the `.highcharts-legend-item-hidden` class. + * + * @sample {highcharts} highcharts/legend/itemhiddenstyle/ + * Darker gray color + * + * @type {Highcharts.CSSObject} + * @default {"color": "#cccccc"} + */ + itemHiddenStyle: { + /** + * @ignore + */ + color: '#cccccc' + }, + /** + * Whether to apply a drop shadow to the legend. A `backgroundColor` + * also needs to be applied for this to take effect. The shadow can be + * an object configuration containing `color`, `offsetX`, `offsetY`, + * `opacity` and `width`. + * + * @sample {highcharts} highcharts/legend/shadow/ + * White background and drop shadow + * @sample {highstock} stock/legend/align/ + * Various legend options + * @sample {highmaps} maps/legend/border-background/ + * Border and background options + * + * @type {boolean|Highcharts.CSSObject} + */ + shadow: false, + /** + * Default styling for the checkbox next to a legend item when + * `showCheckbox` is true. + * + * @type {Highcharts.CSSObject} + * @default {"width": "13px", "height": "13px", "position":"absolute"} + */ + itemCheckboxStyle: { + /** + * @ignore + */ + position: 'absolute', + /** + * @ignore + */ + width: '13px', + /** + * @ignore + */ + height: '13px' + }, + // itemWidth: undefined, + /** + * When this is true, the legend symbol width will be the same as + * the symbol height, which in turn defaults to the font size of the + * legend items. + * + * @since 5.0.0 + */ + squareSymbol: true, + /** + * The pixel height of the symbol for series types that use a rectangle + * in the legend. Defaults to the font size of legend items. + * + * @productdesc {highmaps} + * In Highmaps, when the symbol is the gradient of a vertical color + * axis, the height defaults to 200. + * + * @sample {highmaps} maps/legend/layout-vertical-sized/ + * Sized vertical gradient + * @sample {highmaps} maps/legend/padding-itemmargin/ + * No distance between data classes + * + * @type {number} + * @since 3.0.8 + * @apioption legend.symbolHeight + */ + /** + * The border radius of the symbol for series types that use a rectangle + * in the legend. Defaults to half the `symbolHeight`. + * + * @sample {highcharts} highcharts/legend/symbolradius/ + * Round symbols + * @sample {highstock} highcharts/legend/symbolradius/ + * Round symbols + * @sample {highmaps} highcharts/legend/symbolradius/ + * Round symbols + * + * @type {number} + * @since 3.0.8 + * @apioption legend.symbolRadius + */ + /** + * The pixel width of the legend item symbol. When the `squareSymbol` + * option is set, this defaults to the `symbolHeight`, otherwise 16. + * + * @productdesc {highmaps} + * In Highmaps, when the symbol is the gradient of a horizontal color + * axis, the width defaults to 200. + * + * @sample {highcharts} highcharts/legend/symbolwidth/ + * Greater symbol width and padding + * @sample {highmaps} maps/legend/padding-itemmargin/ + * Padding and item margins demonstrated + * @sample {highmaps} maps/legend/layout-vertical-sized/ + * Sized vertical gradient + * + * @type {number} + * @apioption legend.symbolWidth + */ + /** + * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the legend item texts. + * + * Prior to 4.1.7, when using HTML, [legend.navigation]( + * #legend.navigation) was disabled. + * + * @type {boolean} + * @default false + * @apioption legend.useHTML + */ + /** + * The width of the legend box. If a number is set, it translates to + * pixels. Since v7.0.2 it allows setting a percent string of the full + * chart width, for example `40%`. + * + * Defaults to the full chart width from legends below or above the + * chart, half the chart width for legends to the left and right. + * + * @sample {highcharts} highcharts/legend/width/ + * Aligned to the plot area + * @sample {highcharts} highcharts/legend/width-percent/ + * A percent of the chart width + * + * @type {number|string} + * @since 2.0 + * @apioption legend.width + */ + /** + * The pixel padding between the legend item symbol and the legend + * item text. + * + * @sample {highcharts} highcharts/legend/symbolpadding/ + * Greater symbol width and padding + */ + symbolPadding: 5, + /** + * The vertical alignment of the legend box. Can be one of `top`, + * `middle` or `bottom`. Vertical position can be further determined + * by the `y` option. + * + * In the case that the legend is aligned in a corner position, the + * `layout` option will determine whether to place it above/below + * or on the side of the plot area. + * + * When the [layout](#legend.layout) option is `proximate`, the + * `verticalAlign` option doesn't apply. + * + * @sample {highcharts} highcharts/legend/verticalalign/ + * Legend 100px from the top of the chart + * @sample {highstock} stock/legend/align/ + * Various legend options + * @sample {highmaps} maps/legend/alignment/ + * Legend alignment + * + * @type {Highcharts.VerticalAlignValue} + * @since 2.0 + */ + verticalAlign: 'bottom', + // width: undefined, + /** + * The x offset of the legend relative to its horizontal alignment + * `align` within chart.spacingLeft and chart.spacingRight. Negative + * x moves it to the left, positive x moves it to the right. + * + * @sample {highcharts} highcharts/legend/width/ + * Aligned to the plot area + * + * @since 2.0 + */ + x: 0, + /** + * The vertical offset of the legend relative to it's vertical alignment + * `verticalAlign` within chart.spacingTop and chart.spacingBottom. + * Negative y moves it up, positive y moves it down. + * + * @sample {highcharts} highcharts/legend/verticalalign/ + * Legend 100px from the top of the chart + * @sample {highstock} stock/legend/align/ + * Various legend options + * @sample {highmaps} maps/legend/alignment/ + * Legend alignment + * + * @since 2.0 + */ + y: 0, + /** + * A title to be added on top of the legend. + * + * @sample {highcharts} highcharts/legend/title/ + * Legend title + * @sample {highmaps} maps/legend/alignment/ + * Legend with title + * + * @since 3.0 + */ + title: { + /** + * A text or HTML string for the title. + * + * @type {string} + * @since 3.0 + * @apioption legend.title.text + */ + /** + * Generic CSS styles for the legend title. + * + * @see In styled mode, the legend title is styled with the + * `.highcharts-legend-title` class. + * + * @type {Highcharts.CSSObject} + * @default {"fontWeight": "bold"} + * @since 3.0 + */ + style: { + /** + * @ignore + */ + fontWeight: 'bold' + } + } + }, + /** + * The loading options control the appearance of the loading screen + * that covers the plot area on chart operations. This screen only + * appears after an explicit call to `chart.showLoading()`. It is a + * utility for developers to communicate to the end user that something + * is going on, for example while retrieving new data via an XHR connection. + * The "Loading..." text itself is not part of this configuration + * object, but part of the `lang` object. + */ + loading: { + /** + * The duration in milliseconds of the fade out effect. + * + * @sample highcharts/loading/hideduration/ + * Fade in and out over a second + * + * @type {number} + * @default 100 + * @since 1.2.0 + * @apioption loading.hideDuration + */ + /** + * The duration in milliseconds of the fade in effect. + * + * @sample highcharts/loading/hideduration/ + * Fade in and out over a second + * + * @type {number} + * @default 100 + * @since 1.2.0 + * @apioption loading.showDuration + */ + /** + * CSS styles for the loading label `span`. + * + * @see In styled mode, the loading label is styled with the + * `.highcharts-loading-inner` class. + * + * @sample {highcharts|highmaps} highcharts/loading/labelstyle/ + * Vertically centered + * @sample {highstock} stock/loading/general/ + * Label styles + * + * @type {Highcharts.CSSObject} + * @default {"fontWeight": "bold", "position": "relative", "top": "45%"} + * @since 1.2.0 + */ + labelStyle: { + /** + * @ignore + */ + fontWeight: 'bold', + /** + * @ignore + */ + position: 'relative', + /** + * @ignore + */ + top: '45%' + }, + /** + * CSS styles for the loading screen that covers the plot area. + * + * In styled mode, the loading label is styled with the + * `.highcharts-loading` class. + * + * @sample {highcharts|highmaps} highcharts/loading/style/ + * Gray plot area, white text + * @sample {highstock} stock/loading/general/ + * Gray plot area, white text + * + * @type {Highcharts.CSSObject} + * @default {"position": "absolute", "backgroundColor": "#ffffff", "opacity": 0.5, "textAlign": "center"} + * @since 1.2.0 + */ + style: { + /** + * @ignore + */ + position: 'absolute', + /** + * @ignore + */ + backgroundColor: '#ffffff', + /** + * @ignore + */ + opacity: 0.5, + /** + * @ignore + */ + textAlign: 'center' + } + }, + /** + * Options for the tooltip that appears when the user hovers over a + * series or point. + * + * @declare Highcharts.TooltipOptions + */ + tooltip: { + /** + * The color of the tooltip border. When `undefined`, the border takes + * the color of the corresponding series or point. + * + * @sample {highcharts} highcharts/tooltip/bordercolor-default/ + * Follow series by default + * @sample {highcharts} highcharts/tooltip/bordercolor-black/ + * Black border + * @sample {highstock} stock/tooltip/general/ + * Styled tooltip + * @sample {highmaps} maps/tooltip/background-border/ + * Background and border demo + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption tooltip.borderColor + */ + /** + * A CSS class name to apply to the tooltip's container div, + * allowing unique CSS styling for each chart. + * + * @type {string} + * @apioption tooltip.className + */ + /** + * Since 4.1, the crosshair definitions are moved to the Axis object + * in order for a better separation from the tooltip. See + * [xAxis.crosshair](#xAxis.crosshair). + * + * @sample {highcharts} highcharts/tooltip/crosshairs-x/ + * Enable a crosshair for the x value + * + * @deprecated + * + * @type {*} + * @default true + * @apioption tooltip.crosshairs + */ + /** + * Distance from point to tooltip in pixels. + * + * @type {number} + * @default 16 + * @apioption tooltip.distance + */ + /** + * Whether the tooltip should follow the mouse as it moves across + * columns, pie slices and other point types with an extent. + * By default it behaves this way for pie, polygon, map, sankey + * and wordcloud series by override in the `plotOptions` + * for those series types. + * + * For touch moves to behave the same way, [followTouchMove]( + * #tooltip.followTouchMove) must be `true` also. + * + * @type {boolean} + * @default {highcharts} false + * @default {highstock} false + * @default {highmaps} true + * @since 3.0 + * @apioption tooltip.followPointer + */ + /** + * Whether the tooltip should update as the finger moves on a touch + * device. If this is `true` and [chart.panning](#chart.panning) is + * set,`followTouchMove` will take over one-finger touches, so the user + * needs to use two fingers for zooming and panning. + * + * Note the difference to [followPointer](#tooltip.followPointer) that + * only defines the _position_ of the tooltip. If `followPointer` is + * false in for example a column series, the tooltip will show above or + * below the column, but as `followTouchMove` is true, the tooltip will + * jump from column to column as the user swipes across the plot area. + * + * @type {boolean} + * @default {highcharts} true + * @default {highstock} true + * @default {highmaps} false + * @since 3.0.1 + * @apioption tooltip.followTouchMove + */ + /** + * Callback function to format the text of the tooltip from scratch. In + * case of single or [shared](#tooltip.shared) tooltips, a string should + * be returned. In case of [split](#tooltip.split) tooltips, it should + * return an array where the first item is the header, and subsequent + * items are mapped to the points. Return `false` to disable tooltip for + * a specific point on series. + * + * A subset of HTML is supported. Unless `useHTML` is true, the HTML of + * the tooltip is parsed and converted to SVG, therefore this isn't a + * complete HTML renderer. The following HTML tags are supported: `b`, + * `br`, `em`, `i`, `span`, `strong`. Spans can be styled with a `style` + * attribute, but only text-related CSS, that is shared with SVG, is + * handled. + * + * The available data in the formatter differ a bit depending on whether + * the tooltip is shared or split, or belongs to a single point. In a + * shared/split tooltip, all properties except `x`, which is common for + * all points, are kept in an array, `this.points`. + * + * Available data are: + * + * - **this.percentage (not shared) /** + * **this.points[i].percentage (shared)**: + * Stacked series and pies only. The point's percentage of the total. + * + * - **this.point (not shared) / this.points[i].point (shared)**: + * The point object. The point name, if defined, is available through + * `this.point.name`. + * + * - **this.points**: + * In a shared tooltip, this is an array containing all other + * properties for each point. + * + * - **this.series (not shared) / this.points[i].series (shared)**: + * The series object. The series name is available through + * `this.series.name`. + * + * - **this.total (not shared) / this.points[i].total (shared)**: + * Stacked series only. The total value at this point's x value. + * + * - **this.x**: + * The x value. This property is the same regardless of the tooltip + * being shared or not. + * + * - **this.y (not shared) / this.points[i].y (shared)**: + * The y value. + * + * @sample {highcharts} highcharts/tooltip/formatter-simple/ + * Simple string formatting + * @sample {highcharts} highcharts/tooltip/formatter-shared/ + * Formatting with shared tooltip + * @sample {highcharts|highstock} highcharts/tooltip/formatter-split/ + * Formatting with split tooltip + * @sample highcharts/tooltip/formatter-conditional-default/ + * Extending default formatter + * @sample {highstock} stock/tooltip/formatter/ + * Formatting with shared tooltip + * @sample {highmaps} maps/tooltip/formatter/ + * String formatting + * + * @type {Highcharts.TooltipFormatterCallbackFunction} + * @apioption tooltip.formatter + */ + /** + * Callback function to format the text of the tooltip for + * visible null points. + * Works analogously to [formatter](#tooltip.formatter). + * + * @sample highcharts/plotoptions/series-nullformat + * Format data label and tooltip for null point. + * + * @type {Highcharts.TooltipFormatterCallbackFunction} + * @apioption tooltip.nullFormatter + */ + /** + * The number of milliseconds to wait until the tooltip is hidden when + * mouse out from a point or chart. + * + * @type {number} + * @default 500 + * @since 3.0 + * @apioption tooltip.hideDelay + */ + /** + * Whether to allow the tooltip to render outside the chart's SVG + * element box. By default (`false`), the tooltip is rendered within the + * chart's SVG element, which results in the tooltip being aligned + * inside the chart area. For small charts, this may result in clipping + * or overlapping. When `true`, a separate SVG element is created and + * overlaid on the page, allowing the tooltip to be aligned inside the + * page itself. + * + * Defaults to `true` if `chart.scrollablePlotArea` is activated, + * otherwise `false`. + * + * @sample highcharts/tooltip/outside + * Small charts with tooltips outside + * + * @type {boolean|undefined} + * @default undefined + * @since 6.1.1 + * @apioption tooltip.outside + */ + /** + * A callback function for formatting the HTML output for a single point + * in the tooltip. Like the `pointFormat` string, but with more + * flexibility. + * + * @type {Highcharts.FormatterCallbackFunction} + * @since 4.1.0 + * @context Highcharts.Point + * @apioption tooltip.pointFormatter + */ + /** + * A callback function to place the tooltip in a default position. The + * callback receives three parameters: `labelWidth`, `labelHeight` and + * `point`, where point contains values for `plotX` and `plotY` telling + * where the reference point is in the plot area. Add `chart.plotLeft` + * and `chart.plotTop` to get the full coordinates. + * + * Since v7, when [tooltip.split](#tooltip.split) option is enabled, + * positioner is called for each of the boxes separately, including + * xAxis header. xAxis header is not a point, instead `point` argument + * contains info: + * `{ plotX: Number, plotY: Number, isHeader: Boolean }` + * + * + * The return should be an object containing x and y values, for example + * `{ x: 100, y: 100 }`. + * + * @sample {highcharts} highcharts/tooltip/positioner/ + * A fixed tooltip position + * @sample {highstock} stock/tooltip/positioner/ + * A fixed tooltip position on top of the chart + * @sample {highmaps} maps/tooltip/positioner/ + * A fixed tooltip position + * @sample {highstock} stock/tooltip/split-positioner/ + * Split tooltip with fixed positions + * @sample {highstock} stock/tooltip/positioner-scrollable-plotarea/ + * Scrollable plot area combined with tooltip positioner + * + * @type {Highcharts.TooltipPositionerCallbackFunction} + * @since 2.2.4 + * @apioption tooltip.positioner + */ + /** + * The name of a symbol to use for the border around the tooltip. Can + * be one of: `"callout"`, `"circle"`, or `"square"`. When + * [tooltip.split](#tooltip.split) + * option is enabled, shape is applied to all boxes except header, which + * is controlled by + * [tooltip.headerShape](#tooltip.headerShape). + * + * Custom callbacks for symbol path generation can also be added to + * `Highcharts.SVGRenderer.prototype.symbols` the same way as for + * [series.marker.symbol](plotOptions.line.marker.symbol). + * + * @type {Highcharts.TooltipShapeValue} + * @default callout + * @since 4.0 + * @apioption tooltip.shape + */ + /** + * The name of a symbol to use for the border around the tooltip + * header. Applies only when [tooltip.split](#tooltip.split) is + * enabled. + * + * Custom callbacks for symbol path generation can also be added to + * `Highcharts.SVGRenderer.prototype.symbols` the same way as for + * [series.marker.symbol](plotOptions.line.marker.symbol). + * + * @see [tooltip.shape](#tooltip.shape) + * + * @sample {highstock} stock/tooltip/split-positioner/ + * Different shapes for header and split boxes + * + * @type {Highcharts.TooltipShapeValue} + * @default callout + * @validvalue ["callout", "square"] + * @since 7.0 + * @apioption tooltip.headerShape + */ + /** + * When the tooltip is shared, the entire plot area will capture mouse + * movement or touch events. Tooltip texts for series types with ordered + * data (not pie, scatter, flags etc) will be shown in a single bubble. + * This is recommended for single series charts and for tablet/mobile + * optimized charts. + * + * See also [tooltip.split](#tooltip.split), that is better suited for + * charts with many series, especially line-type series. The + * `tooltip.split` option takes precedence over `tooltip.shared`. + * + * @sample {highcharts} highcharts/tooltip/shared-false/ + * False by default + * @sample {highcharts} highcharts/tooltip/shared-true/ + * True + * @sample {highcharts} highcharts/tooltip/shared-x-crosshair/ + * True with x axis crosshair + * @sample {highcharts} highcharts/tooltip/shared-true-mixed-types/ + * True with mixed series types + * + * @type {boolean} + * @default false + * @since 2.1 + * @product highcharts highstock + * @apioption tooltip.shared + */ + /** + * Split the tooltip into one label per series, with the header close + * to the axis. This is recommended over [shared](#tooltip.shared) + * tooltips for charts with multiple line series, generally making them + * easier to read. This option takes precedence over `tooltip.shared`. + * + * @productdesc {highstock} In Highstock, tooltips are split by default + * since v6.0.0. Stock charts typically contain multi-dimension points + * and multiple panes, making split tooltips the preferred layout over + * the previous `shared` tooltip. + * + * @sample highcharts/tooltip/split/ + * Split tooltip + * @sample {highcharts|highstock} highcharts/tooltip/formatter-split/ + * Split tooltip and custom formatter callback + * + * @type {boolean} + * @default {highcharts} false + * @default {highstock} true + * @since 5.0.0 + * @product highcharts highstock + * @apioption tooltip.split + */ + /** + * Prevents the tooltip from switching or closing, when touched or + * pointed. + * + * @sample highcharts/tooltip/stickoncontact/ + * Tooltip sticks on pointer contact + * + * @type {boolean} + * @since 8.0.1 + * @apioption tooltip.stickOnContact + */ + /** + * Use HTML to render the contents of the tooltip instead of SVG. Using + * HTML allows advanced formatting like tables and images in the + * tooltip. It is also recommended for rtl languages as it works around + * rtl bugs in early Firefox. + * + * @sample {highcharts|highstock} highcharts/tooltip/footerformat/ + * A table for value alignment + * @sample {highcharts|highstock} highcharts/tooltip/fullhtml/ + * Full HTML tooltip + * @sample {highmaps} maps/tooltip/usehtml/ + * Pure HTML tooltip + * + * @type {boolean} + * @default false + * @since 2.2 + * @apioption tooltip.useHTML + */ + /** + * How many decimals to show in each series' y value. This is + * overridable in each series' tooltip options object. The default is to + * preserve all decimals. + * + * @sample {highcharts|highstock} highcharts/tooltip/valuedecimals/ + * Set decimals, prefix and suffix for the value + * @sample {highmaps} maps/tooltip/valuedecimals/ + * Set decimals, prefix and suffix for the value + * + * @type {number} + * @since 2.2 + * @apioption tooltip.valueDecimals + */ + /** + * A string to prepend to each series' y value. Overridable in each + * series' tooltip options object. + * + * @sample {highcharts|highstock} highcharts/tooltip/valuedecimals/ + * Set decimals, prefix and suffix for the value + * @sample {highmaps} maps/tooltip/valuedecimals/ + * Set decimals, prefix and suffix for the value + * + * @type {string} + * @since 2.2 + * @apioption tooltip.valuePrefix + */ + /** + * A string to append to each series' y value. Overridable in each + * series' tooltip options object. + * + * @sample {highcharts|highstock} highcharts/tooltip/valuedecimals/ + * Set decimals, prefix and suffix for the value + * @sample {highmaps} maps/tooltip/valuedecimals/ + * Set decimals, prefix and suffix for the value + * + * @type {string} + * @since 2.2 + * @apioption tooltip.valueSuffix + */ + /** + * The format for the date in the tooltip header if the X axis is a + * datetime axis. The default is a best guess based on the smallest + * distance between points in the chart. + * + * @sample {highcharts} highcharts/tooltip/xdateformat/ + * A different format + * + * @type {string} + * @product highcharts highstock gantt + * @apioption tooltip.xDateFormat + */ + /** + * How many decimals to show for the `point.change` value when the + * `series.compare` option is set. This is overridable in each series' + * tooltip options object. The default is to preserve all decimals. + * + * @type {number} + * @since 1.0.1 + * @product highstock + * @apioption tooltip.changeDecimals + */ + /** + * Enable or disable the tooltip. + * + * @sample {highcharts} highcharts/tooltip/enabled/ + * Disabled + * @sample {highcharts} highcharts/plotoptions/series-point-events-mouseover/ + * Disable tooltip and show values on chart instead + */ + enabled: true, + /** + * Enable or disable animation of the tooltip. + * + * @type {boolean} + * @default true + * @since 2.3.0 + */ + animation: svg, + /** + * The radius of the rounded border corners. + * + * @sample {highcharts} highcharts/tooltip/bordercolor-default/ + * 5px by default + * @sample {highcharts} highcharts/tooltip/borderradius-0/ + * Square borders + * @sample {highmaps} maps/tooltip/background-border/ + * Background and border demo + */ + borderRadius: 3, + /** + * For series on a datetime axes, the date format in the tooltip's + * header will by default be guessed based on the closest data points. + * This member gives the default string representations used for + * each unit. For an overview of the replacement codes, see + * [dateFormat](/class-reference/Highcharts#dateFormat). + * + * @see [xAxis.dateTimeLabelFormats](#xAxis.dateTimeLabelFormats) + * + * @type {Highcharts.Dictionary} + * @product highcharts highstock gantt + */ + dateTimeLabelFormats: { + /** @internal */ + millisecond: '%A, %b %e, %H:%M:%S.%L', + /** @internal */ + second: '%A, %b %e, %H:%M:%S', + /** @internal */ + minute: '%A, %b %e, %H:%M', + /** @internal */ + hour: '%A, %b %e, %H:%M', + /** @internal */ + day: '%A, %b %e, %Y', + /** @internal */ + week: 'Week from %A, %b %e, %Y', + /** @internal */ + month: '%B %Y', + /** @internal */ + year: '%Y' + }, + /** + * A string to append to the tooltip format. + * + * @sample {highcharts} highcharts/tooltip/footerformat/ + * A table for value alignment + * @sample {highmaps} maps/tooltip/format/ + * Format demo + * + * @since 2.2 + */ + footerFormat: '', + /** + * Padding inside the tooltip, in pixels. + * + * @since 5.0.0 + */ + padding: 8, + /** + * Proximity snap for graphs or single points. It defaults to 10 for + * mouse-powered devices and 25 for touch devices. + * + * Note that in most cases the whole plot area captures the mouse + * movement, and in these cases `tooltip.snap` doesn't make sense. This + * applies when [stickyTracking](#plotOptions.series.stickyTracking) + * is `true` (default) and when the tooltip is [shared](#tooltip.shared) + * or [split](#tooltip.split). + * + * @sample {highcharts} highcharts/tooltip/bordercolor-default/ + * 10 px by default + * @sample {highcharts} highcharts/tooltip/snap-50/ + * 50 px on graph + * + * @type {number} + * @default 10/25 + * @since 1.2.0 + * @product highcharts highstock + */ + snap: isTouchDevice ? 25 : 10, + /** + * The HTML of the tooltip header line. Variables are enclosed by + * curly brackets. Available variables are `point.key`, `series.name`, + * `series.color` and other members from the `point` and `series` + * objects. The `point.key` variable contains the category name, x + * value or datetime string depending on the type of axis. For datetime + * axes, the `point.key` date format can be set using + * `tooltip.xDateFormat`. + * + * @sample {highcharts} highcharts/tooltip/footerformat/ + * An HTML table in the tooltip + * @sample {highstock} highcharts/tooltip/footerformat/ + * An HTML table in the tooltip + * @sample {highmaps} maps/tooltip/format/ + * Format demo + * + * @type {string} + * @apioption tooltip.headerFormat + */ + headerFormat: '{point.key}
', + /** + * The HTML of the null point's line in the tooltip. Works analogously + * to [pointFormat](#tooltip.pointFormat). + * + * @sample {highcharts} highcharts/plotoptions/series-nullformat + * Format data label and tooltip for null point. + * + * @type {string} + * @apioption tooltip.nullFormat + */ + /** + * The HTML of the point's line in the tooltip. Variables are enclosed + * by curly brackets. Available variables are point.x, point.y, series. + * name and series.color and other properties on the same form. + * Furthermore, `point.y` can be extended by the `tooltip.valuePrefix` + * and `tooltip.valueSuffix` variables. This can also be overridden for + * each series, which makes it a good hook for displaying units. + * + * In styled mode, the dot is colored by a class name rather + * than the point color. + * + * @sample {highcharts} highcharts/tooltip/pointformat/ + * A different point format with value suffix + * @sample {highmaps} maps/tooltip/format/ + * Format demo + * + * @type {string} + * @since 2.2 + * @apioption tooltip.pointFormat + */ + pointFormat: '\u25CF {series.name}: {point.y}
', + /** + * The background color or gradient for the tooltip. + * + * In styled mode, the stroke width is set in the + * `.highcharts-tooltip-box` class. + * + * @sample {highcharts} highcharts/tooltip/backgroundcolor-solid/ + * Yellowish background + * @sample {highcharts} highcharts/tooltip/backgroundcolor-gradient/ + * Gradient + * @sample {highcharts} highcharts/css/tooltip-border-background/ + * Tooltip in styled mode + * @sample {highstock} stock/tooltip/general/ + * Custom tooltip + * @sample {highstock} highcharts/css/tooltip-border-background/ + * Tooltip in styled mode + * @sample {highmaps} maps/tooltip/background-border/ + * Background and border demo + * @sample {highmaps} highcharts/css/tooltip-border-background/ + * Tooltip in styled mode + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + backgroundColor: color('#f7f7f7') + .setOpacity(0.85).get(), + /** + * The pixel width of the tooltip border. + * + * In styled mode, the stroke width is set in the + * `.highcharts-tooltip-box` class. + * + * @sample {highcharts} highcharts/tooltip/bordercolor-default/ + * 2px by default + * @sample {highcharts} highcharts/tooltip/borderwidth/ + * No border (shadow only) + * @sample {highcharts} highcharts/css/tooltip-border-background/ + * Tooltip in styled mode + * @sample {highstock} stock/tooltip/general/ + * Custom tooltip + * @sample {highstock} highcharts/css/tooltip-border-background/ + * Tooltip in styled mode + * @sample {highmaps} maps/tooltip/background-border/ + * Background and border demo + * @sample {highmaps} highcharts/css/tooltip-border-background/ + * Tooltip in styled mode + */ + borderWidth: 1, + /** + * Whether to apply a drop shadow to the tooltip. + * + * @sample {highcharts} highcharts/tooltip/bordercolor-default/ + * True by default + * @sample {highcharts} highcharts/tooltip/shadow/ + * False + * @sample {highmaps} maps/tooltip/positioner/ + * Fixed tooltip position, border and shadow disabled + * + * @type {boolean|Highcharts.ShadowOptionsObject} + */ + shadow: true, + /** + * CSS styles for the tooltip. The tooltip can also be styled through + * the CSS class `.highcharts-tooltip`. + * + * Note that the default `pointerEvents` style makes the tooltip ignore + * mouse events, so in order to use clickable tooltips, this value must + * be set to `auto`. + * + * @sample {highcharts} highcharts/tooltip/style/ + * Greater padding, bold text + * + * @type {Highcharts.CSSObject} + */ + style: { + /** @internal */ + color: '#333333', + /** @internal */ + cursor: 'default', + /** @internal */ + fontSize: '12px', + /** @internal */ + whiteSpace: 'nowrap' + } + }, + /** + * Highchart by default puts a credits label in the lower right corner + * of the chart. This can be changed using these options. + */ + credits: { + /** + * Credits for map source to be concatenated with conventional credit + * text. By default this is a format string that collects copyright + * information from the map if available. + * + * @see [mapTextFull](#credits.mapTextFull) + * @see [text](#credits.text) + * + * @type {string} + * @default \u00a9 {geojson.copyrightShort} + * @since 4.2.2 + * @product highmaps + * @apioption credits.mapText + */ + /** + * Detailed credits for map source to be displayed on hover of credits + * text. By default this is a format string that collects copyright + * information from the map if available. + * + * @see [mapText](#credits.mapText) + * @see [text](#credits.text) + * + * @type {string} + * @default {geojson.copyright} + * @since 4.2.2 + * @product highmaps + * @apioption credits.mapTextFull + */ + /** + * Whether to show the credits text. + * + * @sample {highcharts} highcharts/credits/enabled-false/ + * Credits disabled + * @sample {highstock} stock/credits/enabled/ + * Credits disabled + * @sample {highmaps} maps/credits/enabled-false/ + * Credits disabled + */ + enabled: true, + /** + * The URL for the credits label. + * + * @sample {highcharts} highcharts/credits/href/ + * Custom URL and text + * @sample {highmaps} maps/credits/customized/ + * Custom URL and text + */ + href: 'https://www.highcharts.com?credits', + /** + * Position configuration for the credits label. + * + * @sample {highcharts} highcharts/credits/position-left/ + * Left aligned + * @sample {highcharts} highcharts/credits/position-left/ + * Left aligned + * @sample {highmaps} maps/credits/customized/ + * Left aligned + * @sample {highmaps} maps/credits/customized/ + * Left aligned + * + * @type {Highcharts.AlignObject} + * @since 2.1 + */ + position: { + /** @internal */ + align: 'right', + /** @internal */ + x: -10, + /** @internal */ + verticalAlign: 'bottom', + /** @internal */ + y: -5 + }, + /** + * CSS styles for the credits label. + * + * @see In styled mode, credits styles can be set with the + * `.highcharts-credits` class. + * + * @type {Highcharts.CSSObject} + */ + style: { + /** @internal */ + cursor: 'pointer', + /** @internal */ + color: '#999999', + /** @internal */ + fontSize: '9px' + }, + /** + * The text for the credits label. + * + * @productdesc {highmaps} + * If a map is loaded as GeoJSON, the text defaults to + * `Highcharts @ {map-credits}`. Otherwise, it defaults to + * `Highcharts.com`. + * + * @sample {highcharts} highcharts/credits/href/ + * Custom URL and text + * @sample {highmaps} maps/credits/customized/ + * Custom URL and text + */ + text: 'Highcharts.com' + } +}; +/** + * Merge the default options with custom options and return the new options + * structure. Commonly used for defining reusable templates. + * + * @sample highcharts/global/useutc-false Setting a global option + * @sample highcharts/members/setoptions Applying a global theme + * + * @function Highcharts.setOptions + * + * @param {Highcharts.Options} options + * The new custom chart options. + * + * @return {Highcharts.Options} + * Updated options. + */ +H.setOptions = function (options) { + // Copy in the default options + H.defaultOptions = merge(true, H.defaultOptions, options); + // Update the time object + if (options.time || options.global) { + H.time.update(merge(H.defaultOptions.global, H.defaultOptions.time, options.global, options.time)); + } + return H.defaultOptions; +}; +/** + * Get the updated default options. Until 3.0.7, merely exposing defaultOptions + * for outside modules wasn't enough because the setOptions method created a new + * object. + * + * @function Highcharts.getOptions + * + * @return {Highcharts.Options} + */ +H.getOptions = function () { + return H.defaultOptions; +}; +// Series defaults +H.defaultPlotOptions = H.defaultOptions.plotOptions; +/** + * Global `Time` object with default options. Since v6.0.5, time settings can be + * applied individually for each chart. If no individual settings apply, this + * `Time` object is shared by all instances. + * + * @name Highcharts.time + * @type {Highcharts.Time} + */ +H.time = new Time(merge(H.defaultOptions.global, H.defaultOptions.time)); +/** + * Formats a JavaScript date timestamp (milliseconds since Jan 1st 1970) into a + * human readable date string. The format is a subset of the formats for PHP's + * [strftime](https://www.php.net/manual/en/function.strftime.php) function. + * Additional formats can be given in the {@link Highcharts.dateFormats} hook. + * + * Since v6.0.5, all internal dates are formatted through the + * {@link Highcharts.Chart#time} instance to respect chart-level time settings. + * The `Highcharts.dateFormat` function only reflects global time settings set + * with `setOptions`. + * + * Supported format keys: + * - `%a`: Short weekday, like 'Mon' + * - `%A`: Long weekday, like 'Monday' + * - `%d`: Two digit day of the month, 01 to 31 + * - `%e`: Day of the month, 1 through 31 + * - `%w`: Day of the week, 0 through 6 + * - `%b`: Short month, like 'Jan' + * - `%B`: Long month, like 'January' + * - `%m`: Two digit month number, 01 through 12 + * - `%y`: Two digits year, like 09 for 2009 + * - `%Y`: Four digits year, like 2009 + * - `%H`: Two digits hours in 24h format, 00 through 23 + * - `%k`: Hours in 24h format, 0 through 23 + * - `%I`: Two digits hours in 12h format, 00 through 11 + * - `%l`: Hours in 12h format, 1 through 12 + * - `%M`: Two digits minutes, 00 through 59 + * - `%p`: Upper case AM or PM + * - `%P`: Lower case AM or PM + * - `%S`: Two digits seconds, 00 through 59 + * - `%L`: Milliseconds (naming from Ruby) + * + * @function Highcharts.dateFormat + * + * @param {string} format + * The desired format where various time representations are prefixed + * with `%`. + * + * @param {number} timestamp + * The JavaScript timestamp. + * + * @param {boolean} [capitalize=false] + * Upper case first letter in the return. + * + * @return {string} + * The formatted date. + */ +H.dateFormat = function (format, timestamp, capitalize) { + return H.time.dateFormat(format, timestamp, capitalize); +}; +/* eslint-disable spaced-comment */ + +''; diff --git a/librerias/gantt/code/es-modules/parts/OrdinalAxis.js b/librerias/gantt/code/es-modules/parts/OrdinalAxis.js new file mode 100644 index 0000000..7953cf4 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/OrdinalAxis.js @@ -0,0 +1,759 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Axis from './Axis.js'; +import H from './Globals.js'; +import U from './Utilities.js'; +var addEvent = U.addEvent, css = U.css, defined = U.defined, pick = U.pick, timeUnits = U.timeUnits; +import './Chart.js'; +// Has a dependency on Navigator due to the use of Axis.toFixedRange +import './Navigator.js'; +import './Series.js'; +var Chart = H.Chart, Series = H.Series; +/* eslint-disable valid-jsdoc */ +var OrdinalAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + /** + * @private + */ + function OrdinalAxisAdditions(axis) { + this.index = {}; + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Get the ordinal positions for the entire data set. This is necessary + * in chart panning because we need to find out what points or data + * groups are available outside the visible range. When a panning + * operation starts, if an index for the given grouping does not exists, + * it is created and cached. This index is deleted on updated data, so + * it will be regenerated the next time a panning operation starts. + * + * @private + */ + OrdinalAxisAdditions.prototype.getExtendedPositions = function () { + var ordinal = this, axis = ordinal.axis, axisProto = axis.constructor.prototype, chart = axis.chart, grouping = axis.series[0].currentDataGrouping, ordinalIndex = ordinal.index, key = grouping ? + grouping.count + grouping.unitName : + 'raw', overscroll = axis.options.overscroll, extremes = axis.getExtremes(), fakeAxis, fakeSeries; + // If this is the first time, or the ordinal index is deleted by + // updatedData, + // create it. + if (!ordinalIndex) { + ordinalIndex = ordinal.index = {}; + } + if (!ordinalIndex[key]) { + // Create a fake axis object where the extended ordinal + // positions are emulated + fakeAxis = { + series: [], + chart: chart, + getExtremes: function () { + return { + min: extremes.dataMin, + max: extremes.dataMax + overscroll + }; + }, + options: { + ordinal: true + }, + ordinal: {}, + ordinal2lin: axisProto.ordinal2lin, + val2lin: axisProto.val2lin // #2590 + }; + fakeAxis.ordinal.axis = fakeAxis; + // Add the fake series to hold the full data, then apply + // processData to it + axis.series.forEach(function (series) { + fakeSeries = { + xAxis: fakeAxis, + xData: series.xData.slice(), + chart: chart, + destroyGroupedData: H.noop, + getProcessedData: H.Series.prototype.getProcessedData + }; + fakeSeries.xData = fakeSeries.xData.concat(ordinal.getOverscrollPositions()); + fakeSeries.options = { + dataGrouping: grouping ? { + enabled: true, + forced: true, + // doesn't matter which, use the fastest + approximation: 'open', + units: [[ + grouping.unitName, + [grouping.count] + ]] + } : { + enabled: false + } + }; + series.processData.apply(fakeSeries); + fakeAxis.series.push(fakeSeries); + }); + // Run beforeSetTickPositions to compute the ordinalPositions + axis.beforeSetTickPositions.apply(fakeAxis); + // Cache it + ordinalIndex[key] = fakeAxis.ordinal.positions; + } + return ordinalIndex[key]; + }; + /** + * Find the factor to estimate how wide the plot area would have been if + * ordinal gaps were included. This value is used to compute an imagined + * plot width in order to establish the data grouping interval. + * + * A real world case is the intraday-candlestick example. Without this + * logic, it would show the correct data grouping when viewing a range + * within each day, but once moving the range to include the gap between + * two days, the interval would include the cut-away night hours and the + * data grouping would be wrong. So the below method tries to compensate + * by identifying the most common point interval, in this case days. + * + * An opposite case is presented in issue #718. We have a long array of + * daily data, then one point is appended one hour after the last point. + * We expect the data grouping not to change. + * + * In the future, if we find cases where this estimation doesn't work + * optimally, we might need to add a second pass to the data grouping + * logic, where we do another run with a greater interval if the number + * of data groups is more than a certain fraction of the desired group + * count. + * + * @private + */ + OrdinalAxisAdditions.prototype.getGroupIntervalFactor = function (xMin, xMax, series) { + var ordinal = this, axis = ordinal.axis, i, processedXData = series.processedXData, len = processedXData.length, distances = [], median, groupIntervalFactor = ordinal.groupIntervalFactor; + // Only do this computation for the first series, let the other + // inherit it (#2416) + if (!groupIntervalFactor) { + // Register all the distances in an array + for (i = 0; i < len - 1; i++) { + distances[i] = + processedXData[i + 1] - processedXData[i]; + } + // Sort them and find the median + distances.sort(function (a, b) { + return a - b; + }); + median = distances[Math.floor(len / 2)]; + // Compensate for series that don't extend through the entire + // axis extent. #1675. + xMin = Math.max(xMin, processedXData[0]); + xMax = Math.min(xMax, processedXData[len - 1]); + ordinal.groupIntervalFactor = groupIntervalFactor = + (len * median) / (xMax - xMin); + } + // Return the factor needed for data grouping + return groupIntervalFactor; + }; + /** + * Get ticks for an ordinal axis within a range where points don't + * exist. It is required when overscroll is enabled. We can't base on + * points, because we may not have any, so we use approximated + * pointRange and generate these ticks between Axis.dataMax, + * Axis.dataMax + Axis.overscroll evenly spaced. Used in panning and + * navigator scrolling. + * + * @private + */ + OrdinalAxisAdditions.prototype.getOverscrollPositions = function () { + var ordinal = this, axis = ordinal.axis, extraRange = axis.options.overscroll, distance = ordinal.overscrollPointsRange, positions = [], max = axis.dataMax; + if (defined(distance)) { + // Max + pointRange because we need to scroll to the last + positions.push(max); + while (max <= axis.dataMax + extraRange) { + max += distance; + positions.push(max); + } + } + return positions; + }; + /** + * Make the tick intervals closer because the ordinal gaps make the + * ticks spread out or cluster. + * + * @private + */ + OrdinalAxisAdditions.prototype.postProcessTickInterval = function (tickInterval) { + // Problem: https://jsfiddle.net/highcharts/FQm4E/1/ + // This is a case where this algorithm doesn't work optimally. In + // this case, the tick labels are spread out per week, but all the + // gaps reside within weeks. So we have a situation where the labels + // are courser than the ordinal gaps, and thus the tick interval + // should not be altered. + var ordinal = this, axis = ordinal.axis, ordinalSlope = ordinal.slope, ret; + if (ordinalSlope) { + if (!axis.options.breaks) { + ret = tickInterval / (ordinalSlope / axis.closestPointRange); + } + else { + ret = axis.closestPointRange || tickInterval; // #7275 + } + } + else { + ret = tickInterval; + } + return ret; + }; + return OrdinalAxisAdditions; +}()); +/** + * Extends the axis with ordinal support. + * + * @private + */ +var OrdinalAxis = /** @class */ (function () { + function OrdinalAxis() { + } + /** + * Extends the axis with ordinal support. + * + * @private + * + * @param AxisClass + * Axis class to extend. + * + * @param ChartClass + * Chart class to use. + * + * @param SeriesClass + * Series class to use. + */ + OrdinalAxis.compose = function (AxisClass, ChartClass, SeriesClass) { + AxisClass.keepProps.push('ordinal'); + var axisProto = AxisClass.prototype; + /** + * Calculate the ordinal positions before tick positions are calculated. + * + * @private + */ + axisProto.beforeSetTickPositions = function () { + var axis = this, ordinal = axis.ordinal, len, ordinalPositions = [], uniqueOrdinalPositions, useOrdinal = false, dist, extremes = axis.getExtremes(), min = extremes.min, max = extremes.max, minIndex, maxIndex, slope, hasBreaks = axis.isXAxis && !!axis.options.breaks, isOrdinal = axis.options.ordinal, overscrollPointsRange = Number.MAX_VALUE, ignoreHiddenSeries = axis.chart.options.chart.ignoreHiddenSeries, i, hasBoostedSeries; + // Apply the ordinal logic + if (isOrdinal || hasBreaks) { // #4167 YAxis is never ordinal ? + axis.series.forEach(function (series, i) { + uniqueOrdinalPositions = []; + if ((!ignoreHiddenSeries || series.visible !== false) && + (series.takeOrdinalPosition !== false || hasBreaks)) { + // concatenate the processed X data into the existing + // positions, or the empty array + ordinalPositions = ordinalPositions.concat(series.processedXData); + len = ordinalPositions.length; + // remove duplicates (#1588) + ordinalPositions.sort(function (a, b) { + // without a custom function it is sorted as strings + return a - b; + }); + overscrollPointsRange = Math.min(overscrollPointsRange, pick( + // Check for a single-point series: + series.closestPointRange, overscrollPointsRange)); + if (len) { + i = 0; + while (i < len - 1) { + if (ordinalPositions[i] !== ordinalPositions[i + 1]) { + uniqueOrdinalPositions.push(ordinalPositions[i + 1]); + } + i++; + } + // Check first item: + if (uniqueOrdinalPositions[0] !== ordinalPositions[0]) { + uniqueOrdinalPositions.unshift(ordinalPositions[0]); + } + ordinalPositions = uniqueOrdinalPositions; + } + } + if (series.isSeriesBoosting) { + hasBoostedSeries = true; + } + }); + if (hasBoostedSeries) { + ordinalPositions.length = 0; + } + // cache the length + len = ordinalPositions.length; + // Check if we really need the overhead of mapping axis data + // against the ordinal positions. If the series consist of + // evenly spaced data any way, we don't need any ordinal logic. + if (len > 2) { // two points have equal distance by default + dist = ordinalPositions[1] - ordinalPositions[0]; + i = len - 1; + while (i-- && !useOrdinal) { + if (ordinalPositions[i + 1] - ordinalPositions[i] !== dist) { + useOrdinal = true; + } + } + // When zooming in on a week, prevent axis padding for + // weekends even though the data within the week is evenly + // spaced. + if (!axis.options.keepOrdinalPadding && + (ordinalPositions[0] - min > dist || + max - ordinalPositions[ordinalPositions.length - 1] > + dist)) { + useOrdinal = true; + } + } + else if (axis.options.overscroll) { + if (len === 2) { + // Exactly two points, distance for overscroll is fixed: + overscrollPointsRange = + ordinalPositions[1] - ordinalPositions[0]; + } + else if (len === 1) { + // We have just one point, closest distance is unknown. + // Assume then it is last point and overscrolled range: + overscrollPointsRange = axis.options.overscroll; + ordinalPositions = [ + ordinalPositions[0], + ordinalPositions[0] + overscrollPointsRange + ]; + } + else { + // In case of zooming in on overscrolled range, stick to + // the old range: + overscrollPointsRange = ordinal.overscrollPointsRange; + } + } + // Record the slope and offset to compute the linear values from + // the array index. Since the ordinal positions may exceed the + // current range, get the start and end positions within it + // (#719, #665b) + if (useOrdinal) { + if (axis.options.overscroll) { + ordinal.overscrollPointsRange = overscrollPointsRange; + ordinalPositions = ordinalPositions.concat(ordinal.getOverscrollPositions()); + } + // Register + ordinal.positions = ordinalPositions; + // This relies on the ordinalPositions being set. Use + // Math.max and Math.min to prevent padding on either sides + // of the data. + minIndex = axis.ordinal2lin(// #5979 + Math.max(min, ordinalPositions[0]), true); + maxIndex = Math.max(axis.ordinal2lin(Math.min(max, ordinalPositions[ordinalPositions.length - 1]), true), 1); // #3339 + // Set the slope and offset of the values compared to the + // indices in the ordinal positions + ordinal.slope = slope = (max - min) / (maxIndex - minIndex); + ordinal.offset = min - (minIndex * slope); + } + else { + ordinal.overscrollPointsRange = pick(axis.closestPointRange, ordinal.overscrollPointsRange); + ordinal.positions = axis.ordinal.slope = ordinal.offset = + void 0; + } + } + axis.isOrdinal = isOrdinal && useOrdinal; // #3818, #4196, #4926 + ordinal.groupIntervalFactor = null; // reset for next run + }; + /** + * In an ordinal axis, there might be areas with dense consentrations of + * points, then large gaps between some. Creating equally distributed + * ticks over this entire range may lead to a huge number of ticks that + * will later be removed. So instead, break the positions up in + * segments, find the tick positions for each segment then concatenize + * them. This method is used from both data grouping logic and X axis + * tick position logic. + * + * @private + */ + AxisClass.prototype.getTimeTicks = function (normalizedInterval, min, max, startOfWeek, positions, closestDistance, findHigherRanks) { + if (positions === void 0) { positions = []; } + if (closestDistance === void 0) { closestDistance = 0; } + var start = 0, end, segmentPositions, higherRanks = {}, hasCrossedHigherRank, info, posLength, outsideMax, groupPositions = [], lastGroupPosition = -Number.MAX_VALUE, tickPixelIntervalOption = this.options.tickPixelInterval, time = this.chart.time, + // Record all the start positions of a segment, to use when + // deciding what's a gap in the data. + segmentStarts = []; + // The positions are not always defined, for example for ordinal + // positions when data has regular interval (#1557, #2090) + if ((!this.options.ordinal && !this.options.breaks) || + !positions || + positions.length < 3 || + typeof min === 'undefined') { + return time.getTimeTicks.apply(time, arguments); + } + // Analyze the positions array to split it into segments on gaps + // larger than 5 times the closest distance. The closest distance is + // already found at this point, so we reuse that instead of + // computing it again. + posLength = positions.length; + for (end = 0; end < posLength; end++) { + outsideMax = end && positions[end - 1] > max; + if (positions[end] < min) { // Set the last position before min + start = end; + } + if (end === posLength - 1 || + positions[end + 1] - positions[end] > closestDistance * 5 || + outsideMax) { + // For each segment, calculate the tick positions from the + // getTimeTicks utility function. The interval will be the + // same regardless of how long the segment is. + if (positions[end] > lastGroupPosition) { // #1475 + segmentPositions = time.getTimeTicks(normalizedInterval, positions[start], positions[end], startOfWeek); + // Prevent duplicate groups, for example for multiple + // segments within one larger time frame (#1475) + while (segmentPositions.length && + segmentPositions[0] <= lastGroupPosition) { + segmentPositions.shift(); + } + if (segmentPositions.length) { + lastGroupPosition = + segmentPositions[segmentPositions.length - 1]; + } + segmentStarts.push(groupPositions.length); + groupPositions = groupPositions.concat(segmentPositions); + } + // Set start of next segment + start = end + 1; + } + if (outsideMax) { + break; + } + } + // Get the grouping info from the last of the segments. The info is + // the same for all segments. + info = segmentPositions.info; + // Optionally identify ticks with higher rank, for example when the + // ticks have crossed midnight. + if (findHigherRanks && info.unitRange <= timeUnits.hour) { + end = groupPositions.length - 1; + // Compare points two by two + for (start = 1; start < end; start++) { + if (time.dateFormat('%d', groupPositions[start]) !== + time.dateFormat('%d', groupPositions[start - 1])) { + higherRanks[groupPositions[start]] = 'day'; + hasCrossedHigherRank = true; + } + } + // If the complete array has crossed midnight, we want to mark + // the first positions also as higher rank + if (hasCrossedHigherRank) { + higherRanks[groupPositions[0]] = 'day'; + } + info.higherRanks = higherRanks; + } + // Save the info + info.segmentStarts = segmentStarts; + groupPositions.info = info; + // Don't show ticks within a gap in the ordinal axis, where the + // space between two points is greater than a portion of the tick + // pixel interval + if (findHigherRanks && defined(tickPixelIntervalOption)) { + var length = groupPositions.length, i = length, itemToRemove, translated, translatedArr = [], lastTranslated, medianDistance, distance, distances = []; + // Find median pixel distance in order to keep a reasonably even + // distance between ticks (#748) + while (i--) { + translated = this.translate(groupPositions[i]); + if (lastTranslated) { + distances[i] = lastTranslated - translated; + } + translatedArr[i] = lastTranslated = translated; + } + distances.sort(); + medianDistance = distances[Math.floor(distances.length / 2)]; + if (medianDistance < tickPixelIntervalOption * 0.6) { + medianDistance = null; + } + // Now loop over again and remove ticks where needed + i = groupPositions[length - 1] > max ? length - 1 : length; // #817 + lastTranslated = void 0; + while (i--) { + translated = translatedArr[i]; + distance = Math.abs(lastTranslated - translated); + // #4175 - when axis is reversed, the distance, is negative + // but tickPixelIntervalOption positive, so we need to + // compare the same values + // Remove ticks that are closer than 0.6 times the pixel + // interval from the one to the right, but not if it is + // close to the median distance (#748). + if (lastTranslated && + distance < tickPixelIntervalOption * 0.8 && + (medianDistance === null || distance < medianDistance * 0.8)) { + // Is this a higher ranked position with a normal + // position to the right? + if (higherRanks[groupPositions[i]] && + !higherRanks[groupPositions[i + 1]]) { + // Yes: remove the lower ranked neighbour to the + // right + itemToRemove = i + 1; + lastTranslated = translated; // #709 + } + else { + // No: remove this one + itemToRemove = i; + } + groupPositions.splice(itemToRemove, 1); + } + else { + lastTranslated = translated; + } + } + } + return groupPositions; + }; + /** + * Translate from linear (internal) to axis value. + * + * @private + * @function Highcharts.Axis#lin2val + * + * @param {number} val + * The linear abstracted value. + * + * @param {boolean} [fromIndex] + * Translate from an index in the ordinal positions rather than a + * value. + * + * @return {number} + */ + axisProto.lin2val = function (val, fromIndex) { + var axis = this, ordinal = axis.ordinal, ordinalPositions = ordinal.positions, ret; + // the visible range contains only equally spaced values + if (!ordinalPositions) { + ret = val; + } + else { + var ordinalSlope = ordinal.slope, ordinalOffset = ordinal.offset, i = ordinalPositions.length - 1, linearEquivalentLeft, linearEquivalentRight, distance; + // Handle the case where we translate from the index directly, + // used only when panning an ordinal axis + if (fromIndex) { + if (val < 0) { // out of range, in effect panning to the left + val = ordinalPositions[0]; + } + else if (val > i) { // out of range, panning to the right + val = ordinalPositions[i]; + } + else { // split it up + i = Math.floor(val); + distance = val - i; // the decimal + } + // Loop down along the ordinal positions. When the linear + // equivalent of i matches an ordinal position, interpolate + // between the left and right values. + } + else { + while (i--) { + linearEquivalentLeft = + (ordinalSlope * i) + ordinalOffset; + if (val >= linearEquivalentLeft) { + linearEquivalentRight = + (ordinalSlope * + (i + 1)) + + ordinalOffset; + // something between 0 and 1 + distance = (val - linearEquivalentLeft) / + (linearEquivalentRight - linearEquivalentLeft); + break; + } + } + } + // If the index is within the range of the ordinal positions, + // return the associated or interpolated value. If not, just + // return the value. + return (typeof distance !== 'undefined' && + typeof ordinalPositions[i] !== 'undefined' ? + ordinalPositions[i] + (distance ? + distance * + (ordinalPositions[i + 1] - ordinalPositions[i]) : + 0) : + val); + } + return ret; + }; + /** + * Translate from a linear axis value to the corresponding ordinal axis + * position. If there are no gaps in the ordinal axis this will be the + * same. The translated value is the value that the point would have if + * the axis were linear, using the same min and max. + * + * @private + * @function Highcharts.Axis#val2lin + * + * @param {number} val + * The axis value. + * + * @param {boolean} [toIndex] + * Whether to return the index in the ordinalPositions or the new value. + * + * @return {number} + */ + axisProto.val2lin = function (val, toIndex) { + var axis = this, ordinal = axis.ordinal, ordinalPositions = ordinal.positions, ret; + if (!ordinalPositions) { + ret = val; + } + else { + var ordinalLength = ordinalPositions.length, i, distance, ordinalIndex; + // first look for an exact match in the ordinalpositions array + i = ordinalLength; + while (i--) { + if (ordinalPositions[i] === val) { + ordinalIndex = i; + break; + } + } + // if that failed, find the intermediate position between the + // two nearest values + i = ordinalLength - 1; + while (i--) { + if (val > ordinalPositions[i] || i === 0) { // interpolate + // something between 0 and 1 + distance = (val - ordinalPositions[i]) / + (ordinalPositions[i + 1] - ordinalPositions[i]); + ordinalIndex = i + distance; + break; + } + } + ret = toIndex ? + ordinalIndex : + ordinal.slope * + (ordinalIndex || 0) + + ordinal.offset; + } + return ret; + }; + // Record this to prevent overwriting by broken-axis module (#5979) + axisProto.ordinal2lin = axisProto.val2lin; + /* eslint-disable no-invalid-this */ + addEvent(AxisClass, 'afterInit', function () { + var axis = this; + if (!axis.ordinal) { + axis.ordinal = new OrdinalAxisAdditions(axis); + } + }); + addEvent(AxisClass, 'foundExtremes', function () { + var axis = this; + if (axis.isXAxis && + defined(axis.options.overscroll) && + axis.max === axis.dataMax && + ( + // Panning is an execption. We don't want to apply + // overscroll when panning over the dataMax + !axis.chart.mouseIsDown || + axis.isInternal) && ( + // Scrollbar buttons are the other execption: + !axis.eventArgs || + axis.eventArgs && axis.eventArgs.trigger !== 'navigator')) { + axis.max += axis.options.overscroll; + // Live data and buttons require translation for the min: + if (!axis.isInternal && defined(axis.userMin)) { + axis.min += axis.options.overscroll; + } + } + }); + // For ordinal axis, that loads data async, redraw axis after data is + // loaded. If we don't do that, axis will have the same extremes as + // previously, but ordinal positions won't be calculated. See #10290 + addEvent(AxisClass, 'afterSetScale', function () { + var axis = this; + if (axis.horiz && !axis.isDirty) { + axis.isDirty = axis.isOrdinal && + axis.chart.navigator && + !axis.chart.navigator.adaptToUpdatedData; + } + }); + // Extending the Chart.pan method for ordinal axes + addEvent(ChartClass, 'pan', function (e) { + var chart = this, xAxis = chart.xAxis[0], overscroll = xAxis.options.overscroll, chartX = e.originalEvent.chartX, panning = chart.options.chart && + chart.options.chart.panning, runBase = false; + if (panning && + panning.type !== 'y' && + xAxis.options.ordinal && + xAxis.series.length) { + var mouseDownX = chart.mouseDownX, extremes = xAxis.getExtremes(), dataMax = extremes.dataMax, min = extremes.min, max = extremes.max, trimmedRange, hoverPoints = chart.hoverPoints, closestPointRange = (xAxis.closestPointRange || + (xAxis.ordinal && xAxis.ordinal.overscrollPointsRange)), pointPixelWidth = (xAxis.translationSlope * + (xAxis.ordinal.slope || closestPointRange)), + // how many ordinal units did we move? + movedUnits = (mouseDownX - chartX) / pointPixelWidth, + // get index of all the chart's points + extendedAxis = { ordinal: { positions: xAxis.ordinal.getExtendedPositions() } }, ordinalPositions, searchAxisLeft, lin2val = xAxis.lin2val, val2lin = xAxis.val2lin, searchAxisRight; + // we have an ordinal axis, but the data is equally spaced + if (!extendedAxis.ordinal.positions) { + runBase = true; + } + else if (Math.abs(movedUnits) > 1) { + // Remove active points for shared tooltip + if (hoverPoints) { + hoverPoints.forEach(function (point) { + point.setState(); + }); + } + if (movedUnits < 0) { + searchAxisLeft = extendedAxis; + searchAxisRight = xAxis.ordinal.positions ? xAxis : extendedAxis; + } + else { + searchAxisLeft = xAxis.ordinal.positions ? xAxis : extendedAxis; + searchAxisRight = extendedAxis; + } + // In grouped data series, the last ordinal position + // represents the grouped data, which is to the left of the + // real data max. If we don't compensate for this, we will + // be allowed to pan grouped data series passed the right of + // the plot area. + ordinalPositions = searchAxisRight.ordinal.positions; + if (dataMax > + ordinalPositions[ordinalPositions.length - 1]) { + ordinalPositions.push(dataMax); + } + // Get the new min and max values by getting the ordinal + // index for the current extreme, then add the moved units + // and translate back to values. This happens on the + // extended ordinal positions if the new position is out of + // range, else it happens on the current x axis which is + // smaller and faster. + chart.fixedRange = max - min; + trimmedRange = xAxis.navigatorAxis.toFixedRange(null, null, lin2val.apply(searchAxisLeft, [ + val2lin.apply(searchAxisLeft, [min, true]) + movedUnits, + true // translate from index + ]), lin2val.apply(searchAxisRight, [ + val2lin.apply(searchAxisRight, [max, true]) + movedUnits, + true // translate from index + ])); + // Apply it if it is within the available data range + if (trimmedRange.min >= Math.min(extremes.dataMin, min) && + trimmedRange.max <= Math.max(dataMax, max) + overscroll) { + xAxis.setExtremes(trimmedRange.min, trimmedRange.max, true, false, { trigger: 'pan' }); + } + chart.mouseDownX = chartX; // set new reference for next run + css(chart.container, { cursor: 'move' }); + } + } + else { + runBase = true; + } + // revert to the linear chart.pan version + if (runBase || (panning && /y/.test(panning.type))) { + if (overscroll) { + xAxis.max = xAxis.dataMax + overscroll; + } + } + else { + e.preventDefault(); + } + }); + addEvent(SeriesClass, 'updatedData', function () { + var xAxis = this.xAxis; + // Destroy the extended ordinal index on updated data + if (xAxis && xAxis.options.ordinal) { + delete xAxis.ordinal.index; + } + }); + /* eslint-enable no-invalid-this */ + }; + return OrdinalAxis; +}()); +OrdinalAxis.compose(Axis, Chart, Series); // @todo move to StockChart, remove from master +export default OrdinalAxis; diff --git a/librerias/gantt/code/es-modules/parts/PieSeries.js b/librerias/gantt/code/es-modules/parts/PieSeries.js new file mode 100644 index 0000000..27c795b --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/PieSeries.js @@ -0,0 +1,1246 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +import LegendSymbolMixin from '../mixins/legend-symbol.js'; +import Point from './Point.js'; +import U from './Utilities.js'; +var addEvent = U.addEvent, clamp = U.clamp, defined = U.defined, fireEvent = U.fireEvent, isNumber = U.isNumber, merge = U.merge, pick = U.pick, relativeLength = U.relativeLength, seriesType = U.seriesType, setAnimation = U.setAnimation; +import './ColumnSeries.js'; +import '../mixins/centered-series.js'; +import './Options.js'; +import './Series.js'; +var CenteredSeriesMixin = H.CenteredSeriesMixin, getStartAndEndRadians = CenteredSeriesMixin.getStartAndEndRadians, noop = H.noop, Series = H.Series, seriesTypes = H.seriesTypes; +/** + * Pie series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.pie + * + * @augments Highcharts.Series + */ +seriesType('pie', 'line', +/** + * A pie chart is a circular graphic which is divided into slices to + * illustrate numerical proportion. + * + * @sample highcharts/demo/pie-basic/ + * Pie chart + * + * @extends plotOptions.line + * @excluding animationLimit, boostThreshold, connectEnds, connectNulls, + * cropThreshold, dashStyle, dataSorting, dragDrop, + * findNearestPointBy, getExtremesFromAll, label, lineWidth, + * marker, negativeColor, pointInterval, pointIntervalUnit, + * pointPlacement, pointStart, softThreshold, stacking, step, + * threshold, turboThreshold, zoneAxis, zones, dataSorting + * @product highcharts + * @optionparent plotOptions.pie + */ +{ + /** + * @excluding legendItemClick + * @apioption plotOptions.pie.events + */ + /** + * Fires when the checkbox next to the point name in the legend is + * clicked. One parameter, event, is passed to the function. The state + * of the checkbox is found by event.checked. The checked item is found + * by event.item. Return false to prevent the default action which is to + * toggle the select state of the series. + * + * @sample {highcharts} highcharts/plotoptions/series-events-checkboxclick/ + * Alert checkbox status + * + * @type {Function} + * @since 1.2.0 + * @product highcharts + * @context Highcharts.Point + * @apioption plotOptions.pie.events.checkboxClick + */ + /** + * Fires when the legend item belonging to the pie point (slice) is + * clicked. The `this` keyword refers to the point itself. One + * parameter, `event`, is passed to the function, containing common + * event information. The default action is to toggle the visibility of + * the point. This can be prevented by calling `event.preventDefault()`. + * + * @sample {highcharts} highcharts/plotoptions/pie-point-events-legenditemclick/ + * Confirm toggle visibility + * + * @type {Highcharts.PointLegendItemClickCallbackFunction} + * @since 1.2.0 + * @product highcharts + * @apioption plotOptions.pie.point.events.legendItemClick + */ + /** + * The center of the pie chart relative to the plot area. Can be + * percentages or pixel values. The default behaviour (as of 3.0) is to + * center the pie so that all slices and data labels are within the plot + * area. As a consequence, the pie may actually jump around in a chart + * with dynamic values, as the data labels move. In that case, the + * center should be explicitly set, for example to `["50%", "50%"]`. + * + * @sample {highcharts} highcharts/plotoptions/pie-center/ + * Centered at 100, 100 + * + * @type {Array<(number|string|null),(number|string|null)>} + * @default [null, null] + * @product highcharts + * + * @private + */ + center: [null, null], + /** + * The color of the pie series. A pie series is represented as an empty + * circle if the total sum of its values is 0. Use this property to + * define the color of its border. + * + * In styled mode, the color can be defined by the + * [colorIndex](#plotOptions.series.colorIndex) option. Also, the series + * color can be set with the `.highcharts-series`, + * `.highcharts-color-{n}`, `.highcharts-{type}-series` or + * `.highcharts-series-{n}` class, or individual classes given by the + * `className` option. + * + * @sample {highcharts} highcharts/plotoptions/pie-emptyseries/ + * Empty pie series + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #cccccc + * @apioption plotOptions.pie.color + */ + /** + * @product highcharts + * + * @private + */ + clip: false, + /** + * @ignore-option + * + * @private + */ + colorByPoint: true, + /** + * A series specific or series type specific color set to use instead + * of the global [colors](#colors). + * + * @sample {highcharts} highcharts/demo/pie-monochrome/ + * Set default colors for all pies + * + * @type {Array} + * @since 3.0 + * @product highcharts + * @apioption plotOptions.pie.colors + */ + /** + * @declare Highcharts.SeriesPieDataLabelsOptionsObject + * @extends plotOptions.series.dataLabels + * @excluding align, allowOverlap, inside, staggerLines, step + * @private + */ + dataLabels: { + /** + * Alignment method for data labels. Possible values are: + * + * - `toPlotEdges`: Each label touches the nearest vertical edge of + * the plot area. + * + * - `connectors`: Connectors have the same x position and the + * widest label of each half (left & right) touches the nearest + * vertical edge of the plot area. + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-alignto-connectors/ + * alignTo: connectors + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-alignto-plotedges/ + * alignTo: plotEdges + * + * @type {string} + * @since 7.0.0 + * @product highcharts + * @apioption plotOptions.pie.dataLabels.alignTo + */ + allowOverlap: true, + /** + * The color of the line connecting the data label to the pie slice. + * The default color is the same as the point's color. + * + * In styled mode, the connector stroke is given in the + * `.highcharts-data-label-connector` class. + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorcolor/ + * Blue connectors + * @sample {highcharts} highcharts/css/pie-point/ + * Styled connectors + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.1 + * @product highcharts + * @apioption plotOptions.pie.dataLabels.connectorColor + */ + /** + * The distance from the data label to the connector. Note that + * data labels also have a default `padding`, so in order for the + * connector to touch the text, the `padding` must also be 0. + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorpadding/ + * No padding + * + * @since 2.1 + * @product highcharts + */ + connectorPadding: 5, + /** + * Specifies the method that is used to generate the connector path. + * Highcharts provides 3 built-in connector shapes: `'fixedOffset'` + * (default), `'straight'` and `'crookedLine'`. Using + * `'crookedLine'` has the most sense (in most of the cases) when + * `'alignTo'` is set. + * + * Users can provide their own method by passing a function instead + * of a String. 3 arguments are passed to the callback: + * + * - Object that holds the information about the coordinates of the + * label (`x` & `y` properties) and how the label is located in + * relation to the pie (`alignment` property). `alignment` can by + * one of the following: + * `'left'` (pie on the left side of the data label), + * `'right'` (pie on the right side of the data label) or + * `'center'` (data label overlaps the pie). + * + * - Object that holds the information about the position of the + * connector. Its `touchingSliceAt` porperty tells the position + * of the place where the connector touches the slice. + * + * - Data label options + * + * The function has to return an SVG path definition in array form + * (see the example). + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorshape-string/ + * connectorShape is a String + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorshape-function/ + * connectorShape is a function + * + * @type {string|Function} + * @since 7.0.0 + * @product highcharts + */ + connectorShape: 'fixedOffset', + /** + * The width of the line connecting the data label to the pie slice. + * + * In styled mode, the connector stroke width is given in the + * `.highcharts-data-label-connector` class. + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorwidth-disabled/ + * Disable the connector + * @sample {highcharts} highcharts/css/pie-point/ + * Styled connectors + * + * @type {number} + * @default 1 + * @since 2.1 + * @product highcharts + * @apioption plotOptions.pie.dataLabels.connectorWidth + */ + /** + * Works only if `connectorShape` is `'crookedLine'`. It defines how + * far from the vertical plot edge the coonnector path should be + * crooked. + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-crookdistance/ + * crookDistance set to 90% + * + * @since 7.0.0 + * @product highcharts + */ + crookDistance: '70%', + /** + * The distance of the data label from the pie's edge. Negative + * numbers put the data label on top of the pie slices. Can also be + * defined as a percentage of pie's radius. Connectors are only + * shown for data labels outside the pie. + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-distance/ + * Data labels on top of the pie + * + * @type {number|string} + * @since 2.1 + * @product highcharts + */ + distance: 30, + enabled: true, + formatter: function () { + return this.point.isNull ? void 0 : this.point.name; + }, + /** + * Whether to render the connector as a soft arc or a line with + * sharp break. Works only if `connectorShape` equals to + * `fixedOffset`. + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-softconnector-true/ + * Soft + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-softconnector-false/ + * Non soft + * + * @since 2.1.7 + * @product highcharts + */ + softConnector: true, + /** + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow + * Long labels truncated with an ellipsis + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow-wrap + * Long labels are wrapped + * + * @type {Highcharts.CSSObject} + * @apioption plotOptions.pie.dataLabels.style + */ + x: 0 + }, + /** + * If the total sum of the pie's values is 0, the series is represented + * as an empty circle . The `fillColor` option defines the color of that + * circle. Use [pie.borderWidth](#plotOptions.pie.borderWidth) to set + * the border thickness. + * + * @sample {highcharts} highcharts/plotoptions/pie-emptyseries/ + * Empty pie series + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @private + */ + fillColor: void 0, + /** + * The end angle of the pie in degrees where 0 is top and 90 is right. + * Defaults to `startAngle` plus 360. + * + * @sample {highcharts} highcharts/demo/pie-semi-circle/ + * Semi-circle donut + * + * @type {number} + * @since 1.3.6 + * @product highcharts + * @apioption plotOptions.pie.endAngle + */ + /** + * Equivalent to [chart.ignoreHiddenSeries](#chart.ignoreHiddenSeries), + * this option tells whether the series shall be redrawn as if the + * hidden point were `null`. + * + * The default value changed from `false` to `true` with Highcharts + * 3.0. + * + * @sample {highcharts} highcharts/plotoptions/pie-ignorehiddenpoint/ + * True, the hiddden point is ignored + * + * @since 2.3.0 + * @product highcharts + * + * @private + */ + ignoreHiddenPoint: true, + /** + * @ignore-option + * + * @private + */ + inactiveOtherPoints: true, + /** + * The size of the inner diameter for the pie. A size greater than 0 + * renders a donut chart. Can be a percentage or pixel value. + * Percentages are relative to the pie size. Pixel values are given as + * integers. + * + * + * Note: in Highcharts < 4.1.2, the percentage was relative to the plot + * area, not the pie size. + * + * @sample {highcharts} highcharts/plotoptions/pie-innersize-80px/ + * 80px inner size + * @sample {highcharts} highcharts/plotoptions/pie-innersize-50percent/ + * 50% of the plot area + * @sample {highcharts} highcharts/demo/3d-pie-donut/ + * 3D donut + * + * @type {number|string} + * @default 0 + * @since 2.0 + * @product highcharts + * @apioption plotOptions.pie.innerSize + */ + /** + * @ignore-option + * + * @private + */ + legendType: 'point', + /** + * @ignore-option + * + * @private + */ + marker: null, + /** + * The minimum size for a pie in response to auto margins. The pie will + * try to shrink to make room for data labels in side the plot area, + * but only to this size. + * + * @type {number|string} + * @default 80 + * @since 3.0 + * @product highcharts + * @apioption plotOptions.pie.minSize + */ + /** + * The diameter of the pie relative to the plot area. Can be a + * percentage or pixel value. Pixel values are given as integers. The + * default behaviour (as of 3.0) is to scale to the plot area and give + * room for data labels within the plot area. + * [slicedOffset](#plotOptions.pie.slicedOffset) is also included in the + * default size calculation. As a consequence, the size of the pie may + * vary when points are updated and data labels more around. In that + * case it is best to set a fixed value, for example `"75%"`. + * + * @sample {highcharts} highcharts/plotoptions/pie-size/ + * Smaller pie + * + * @type {number|string|null} + * @product highcharts + * + * @private + */ + size: null, + /** + * Whether to display this particular series or series type in the + * legend. Since 2.1, pies are not shown in the legend by default. + * + * @sample {highcharts} highcharts/plotoptions/series-showinlegend/ + * One series in the legend, one hidden + * + * @product highcharts + * + * @private + */ + showInLegend: false, + /** + * If a point is sliced, moved out from the center, how many pixels + * should it be moved?. + * + * @sample {highcharts} highcharts/plotoptions/pie-slicedoffset-20/ + * 20px offset + * + * @product highcharts + * + * @private + */ + slicedOffset: 10, + /** + * The start angle of the pie slices in degrees where 0 is top and 90 + * right. + * + * @sample {highcharts} highcharts/plotoptions/pie-startangle-90/ + * Start from right + * + * @type {number} + * @default 0 + * @since 2.3.4 + * @product highcharts + * @apioption plotOptions.pie.startAngle + */ + /** + * Sticky tracking of mouse events. When true, the `mouseOut` event + * on a series isn't triggered until the mouse moves over another + * series, or out of the plot area. When false, the `mouseOut` event on + * a series is triggered when the mouse leaves the area around the + * series' graph or markers. This also implies the tooltip. When + * `stickyTracking` is false and `tooltip.shared` is false, the tooltip + * will be hidden when moving the mouse between series. + * + * @product highcharts + * + * @private + */ + stickyTracking: false, + tooltip: { + followPointer: true + }, + /** + * The color of the border surrounding each slice. When `null`, the + * border takes the same color as the slice fill. This can be used + * together with a `borderWidth` to fill drawing gaps created by + * antialiazing artefacts in borderless pies. + * + * In styled mode, the border stroke is given in the `.highcharts-point` + * class. + * + * @sample {highcharts} highcharts/plotoptions/pie-bordercolor-black/ + * Black border + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #ffffff + * @product highcharts + * + * @private + */ + borderColor: '#ffffff', + /** + * The width of the border surrounding each slice. + * + * When setting the border width to 0, there may be small gaps between + * the slices due to SVG antialiasing artefacts. To work around this, + * keep the border width at 0.5 or 1, but set the `borderColor` to + * `null` instead. + * + * In styled mode, the border stroke width is given in the + * `.highcharts-point` class. + * + * @sample {highcharts} highcharts/plotoptions/pie-borderwidth/ + * 3px border + * + * @product highcharts + * + * @private + */ + borderWidth: 1, + /** + * @ignore-options + * @private + */ + lineWidth: void 0, + states: { + /** + * @extends plotOptions.series.states.hover + * @excluding marker, lineWidth, lineWidthPlus + * @product highcharts + */ + hover: { + /** + * How much to brighten the point on interaction. Requires the + * main color to be defined in hex or rgb(a) format. + * + * In styled mode, the hover brightness is by default replaced + * by a fill-opacity given in the `.highcharts-point-hover` + * class. + * + * @sample {highcharts} highcharts/plotoptions/pie-states-hover-brightness/ + * Brightened by 0.5 + * + * @product highcharts + */ + brightness: 0.1 + } + } +}, +/* eslint-disable valid-jsdoc */ +/** + * @lends seriesTypes.pie.prototype + */ +{ + isCartesian: false, + requireSorting: false, + directTouch: true, + noSharedTooltip: true, + trackerGroups: ['group', 'dataLabelsGroup'], + axisTypes: [], + pointAttribs: seriesTypes.column.prototype.pointAttribs, + /** + * Animate the pies in + * + * @private + * @function Highcharts.seriesTypes.pie#animate + * + * @param {boolean} [init=false] + */ + animate: function (init) { + var series = this, points = series.points, startAngleRad = series.startAngleRad; + if (!init) { + points.forEach(function (point) { + var graphic = point.graphic, args = point.shapeArgs; + if (graphic && args) { + // start values + graphic.attr({ + // animate from inner radius (#779) + r: pick(point.startR, (series.center && series.center[3] / 2)), + start: startAngleRad, + end: startAngleRad + }); + // animate + graphic.animate({ + r: args.r, + start: args.start, + end: args.end + }, series.options.animation); + } + }); + } + }, + // Define hasData function for non-cartesian series. + // Returns true if the series has points at all. + hasData: function () { + return !!this.processedXData.length; // != 0 + }, + /** + * Recompute total chart sum and update percentages of points. + * + * @private + * @function Highcharts.seriesTypes.pie#updateTotals + * @return {void} + */ + updateTotals: function () { + var i, total = 0, points = this.points, len = points.length, point, ignoreHiddenPoint = this.options.ignoreHiddenPoint; + // Get the total sum + for (i = 0; i < len; i++) { + point = points[i]; + total += (ignoreHiddenPoint && !point.visible) ? + 0 : + point.isNull ? + 0 : + point.y; + } + this.total = total; + // Set each point's properties + for (i = 0; i < len; i++) { + point = points[i]; + point.percentage = + (total > 0 && (point.visible || !ignoreHiddenPoint)) ? + point.y / total * 100 : + 0; + point.total = total; + } + }, + /** + * Extend the generatePoints method by adding total and percentage + * properties to each point + * + * @private + * @function Highcharts.seriesTypes.pie#generatePoints + * @return {void} + */ + generatePoints: function () { + Series.prototype.generatePoints.call(this); + this.updateTotals(); + }, + /** + * Utility for getting the x value from a given y, used for + * anticollision logic in data labels. Added point for using specific + * points' label distance. + * @private + */ + getX: function (y, left, point) { + var center = this.center, + // Variable pie has individual radius + radius = this.radii ? + this.radii[point.index] : + center[2] / 2, angle, x; + angle = Math.asin(clamp((y - center[1]) / (radius + point.labelDistance), -1, 1)); + x = center[0] + + (left ? -1 : 1) * + (Math.cos(angle) * (radius + point.labelDistance)) + + (point.labelDistance > 0 ? + (left ? -1 : 1) * this.options.dataLabels.padding : + 0); + return x; + }, + /** + * Do translation for pie slices + * + * @private + * @function Highcharts.seriesTypes.pie#translate + * @param {Array} [positions] + * @return {void} + */ + translate: function (positions) { + this.generatePoints(); + var series = this, cumulative = 0, precision = 1000, // issue #172 + options = series.options, slicedOffset = options.slicedOffset, connectorOffset = slicedOffset + (options.borderWidth || 0), finalConnectorOffset, start, end, angle, radians = getStartAndEndRadians(options.startAngle, options.endAngle), startAngleRad = series.startAngleRad = radians.start, endAngleRad = series.endAngleRad = radians.end, circ = endAngleRad - startAngleRad, // 2 * Math.PI, + points = series.points, + // the x component of the radius vector for a given point + radiusX, radiusY, labelDistance = options.dataLabels.distance, ignoreHiddenPoint = options.ignoreHiddenPoint, i, len = points.length, point; + // Get positions - either an integer or a percentage string must be + // given. If positions are passed as a parameter, we're in a + // recursive loop for adjusting space for data labels. + if (!positions) { + series.center = positions = series.getCenter(); + } + // Calculate the geometry for each point + for (i = 0; i < len; i++) { + point = points[i]; + // set start and end angle + start = startAngleRad + (cumulative * circ); + if (!ignoreHiddenPoint || point.visible) { + cumulative += point.percentage / 100; + } + end = startAngleRad + (cumulative * circ); + // set the shape + point.shapeType = 'arc'; + point.shapeArgs = { + x: positions[0], + y: positions[1], + r: positions[2] / 2, + innerR: positions[3] / 2, + start: Math.round(start * precision) / precision, + end: Math.round(end * precision) / precision + }; + // Used for distance calculation for specific point. + point.labelDistance = pick((point.options.dataLabels && + point.options.dataLabels.distance), labelDistance); + // Compute point.labelDistance if it's defined as percentage + // of slice radius (#8854) + point.labelDistance = relativeLength(point.labelDistance, point.shapeArgs.r); + // Saved for later dataLabels distance calculation. + series.maxLabelDistance = Math.max(series.maxLabelDistance || 0, point.labelDistance); + // The angle must stay within -90 and 270 (#2645) + angle = (end + start) / 2; + if (angle > 1.5 * Math.PI) { + angle -= 2 * Math.PI; + } + else if (angle < -Math.PI / 2) { + angle += 2 * Math.PI; + } + // Center for the sliced out slice + point.slicedTranslation = { + translateX: Math.round(Math.cos(angle) * slicedOffset), + translateY: Math.round(Math.sin(angle) * slicedOffset) + }; + // set the anchor point for tooltips + radiusX = Math.cos(angle) * positions[2] / 2; + radiusY = Math.sin(angle) * positions[2] / 2; + point.tooltipPos = [ + positions[0] + radiusX * 0.7, + positions[1] + radiusY * 0.7 + ]; + point.half = angle < -Math.PI / 2 || angle > Math.PI / 2 ? + 1 : + 0; + point.angle = angle; + // Set the anchor point for data labels. Use point.labelDistance + // instead of labelDistance // #1174 + // finalConnectorOffset - not override connectorOffset value. + finalConnectorOffset = Math.min(connectorOffset, point.labelDistance / 5); // #1678 + point.labelPosition = { + natural: { + // initial position of the data label - it's utilized for + // finding the final position for the label + x: positions[0] + radiusX + Math.cos(angle) * + point.labelDistance, + y: positions[1] + radiusY + Math.sin(angle) * + point.labelDistance + }, + 'final': { + // used for generating connector path - + // initialized later in drawDataLabels function + // x: undefined, + // y: undefined + }, + // left - pie on the left side of the data label + // right - pie on the right side of the data label + // center - data label overlaps the pie + alignment: point.labelDistance < 0 ? + 'center' : point.half ? 'right' : 'left', + connectorPosition: { + breakAt: { + x: positions[0] + radiusX + Math.cos(angle) * + finalConnectorOffset, + y: positions[1] + radiusY + Math.sin(angle) * + finalConnectorOffset + }, + touchingSliceAt: { + x: positions[0] + radiusX, + y: positions[1] + radiusY + } + } + }; + } + fireEvent(series, 'afterTranslate'); + }, + /** + * Called internally to draw auxiliary graph in pie-like series in + * situtation when the default graph is not sufficient enough to present + * the data well. Auxiliary graph is saved in the same object as + * regular graph. + * + * @private + * @function Highcharts.seriesTypes.pie#drawEmpty + */ + drawEmpty: function () { + var centerX, centerY, options = this.options; + // Draw auxiliary graph if there're no visible points. + if (this.total === 0) { + centerX = this.center[0]; + centerY = this.center[1]; + if (!this.graph) { // Auxiliary graph doesn't exist yet. + this.graph = this.chart.renderer.circle(centerX, centerY, 0) + .addClass('highcharts-graph') + .add(this.group); + } + this.graph.animate({ + 'stroke-width': options.borderWidth, + cx: centerX, + cy: centerY, + r: this.center[2] / 2, + fill: options.fillColor || 'none', + stroke: options.color || + '#cccccc' + }, this.options.animation); + } + else if (this.graph) { // Destroy the graph object. + this.graph = this.graph.destroy(); + } + }, + /** + * Draw the data points + * + * @private + * @function Highcharts.seriesTypes.pie#drawPoints + * @return {void} + */ + redrawPoints: function () { + var series = this, chart = series.chart, renderer = chart.renderer, groupTranslation, graphic, pointAttr, shapeArgs, shadow = series.options.shadow; + this.drawEmpty(); + if (shadow && !series.shadowGroup && !chart.styledMode) { + series.shadowGroup = renderer.g('shadow') + .attr({ zIndex: -1 }) + .add(series.group); + } + // draw the slices + series.points.forEach(function (point) { + var animateTo = {}; + graphic = point.graphic; + if (!point.isNull && graphic) { + shapeArgs = point.shapeArgs; + // If the point is sliced, use special translation, else use + // plot area translation + groupTranslation = point.getTranslate(); + if (!chart.styledMode) { + // Put the shadow behind all points + var shadowGroup = point.shadowGroup; + if (shadow && !shadowGroup) { + shadowGroup = point.shadowGroup = renderer + .g('shadow') + .add(series.shadowGroup); + } + if (shadowGroup) { + shadowGroup.attr(groupTranslation); + } + pointAttr = series.pointAttribs(point, (point.selected && 'select')); + } + // Draw the slice + if (!point.delayedRendering) { + graphic + .setRadialReference(series.center); + if (!chart.styledMode) { + merge(true, animateTo, pointAttr); + } + merge(true, animateTo, shapeArgs, groupTranslation); + graphic.animate(animateTo); + } + else { + graphic + .setRadialReference(series.center) + .attr(shapeArgs) + .attr(groupTranslation); + if (!chart.styledMode) { + graphic + .attr(pointAttr) + .attr({ 'stroke-linejoin': 'round' }) + .shadow(shadow, shadowGroup); + } + point.delayedRendering = false; + } + graphic.attr({ + visibility: point.visible ? 'inherit' : 'hidden' + }); + graphic.addClass(point.getClassName()); + } + else if (graphic) { + point.graphic = graphic.destroy(); + } + }); + }, + /** + * Slices in pie chart are initialized in DOM, but it's shapes and + * animations are normally run in `drawPoints()`. + * @private + */ + drawPoints: function () { + var renderer = this.chart.renderer; + this.points.forEach(function (point) { + // When updating a series between 2d and 3d or cartesian and + // polar, the shape type changes. + if (point.graphic && point.hasNewShapeType()) { + point.graphic = point.graphic.destroy(); + } + if (!point.graphic) { + point.graphic = renderer[point.shapeType](point.shapeArgs) + .add(point.series.group); + point.delayedRendering = true; + } + }); + }, + /** + * @private + * @deprecated + * @function Highcharts.seriesTypes.pie#searchPoint + */ + searchPoint: noop, + /** + * Utility for sorting data labels + * + * @private + * @function Highcharts.seriesTypes.pie#sortByAngle + * @param {Array} points + * @param {number} sign + * @return {void} + */ + sortByAngle: function (points, sign) { + points.sort(function (a, b) { + return ((typeof a.angle !== 'undefined') && + (b.angle - a.angle) * sign); + }); + }, + /** + * Use a simple symbol from LegendSymbolMixin. + * + * @private + * @borrows Highcharts.LegendSymbolMixin.drawRectangle as Highcharts.seriesTypes.pie#drawLegendSymbol + */ + drawLegendSymbol: LegendSymbolMixin.drawRectangle, + /** + * Use the getCenter method from drawLegendSymbol. + * + * @private + * @borrows Highcharts.CenteredSeriesMixin.getCenter as Highcharts.seriesTypes.pie#getCenter + */ + getCenter: CenteredSeriesMixin.getCenter, + /** + * Pies don't have point marker symbols. + * + * @deprecated + * @private + * @function Highcharts.seriesTypes.pie#getSymbol + */ + getSymbol: noop, + /** + * @private + * @type {null} + */ + drawGraph: null +}, +/** + * @lends seriesTypes.pie.prototype.pointClass.prototype + */ +{ + /** + * Initialize the pie slice + * + * @private + * @function Highcharts.seriesTypes.pie#pointClass#init + * @return {Highcharts.Point} + */ + init: function () { + Point.prototype.init.apply(this, arguments); + var point = this, toggleSlice; + point.name = pick(point.name, 'Slice'); + // add event listener for select + toggleSlice = function (e) { + point.slice(e.type === 'select'); + }; + addEvent(point, 'select', toggleSlice); + addEvent(point, 'unselect', toggleSlice); + return point; + }, + /** + * Negative points are not valid (#1530, #3623, #5322) + * + * @private + * @function Highcharts.seriesTypes.pie#pointClass#isValid + * @return {boolean} + */ + isValid: function () { + return isNumber(this.y) && this.y >= 0; + }, + /** + * Toggle the visibility of the pie slice + * + * @private + * @function Highcharts.seriesTypes.pie#pointClass#setVisible + * @param {boolean} vis + * Whether to show the slice or not. If undefined, the visibility + * is toggled. + * @param {boolean} [redraw=false] + * @return {void} + */ + setVisible: function (vis, redraw) { + var point = this, series = point.series, chart = series.chart, ignoreHiddenPoint = series.options.ignoreHiddenPoint; + redraw = pick(redraw, ignoreHiddenPoint); + if (vis !== point.visible) { + // If called without an argument, toggle visibility + point.visible = point.options.visible = vis = + typeof vis === 'undefined' ? !point.visible : vis; + // update userOptions.data + series.options.data[series.data.indexOf(point)] = + point.options; + // Show and hide associated elements. This is performed + // regardless of redraw or not, because chart.redraw only + // handles full series. + ['graphic', 'dataLabel', 'connector', 'shadowGroup'].forEach(function (key) { + if (point[key]) { + point[key][vis ? 'show' : 'hide'](true); + } + }); + if (point.legendItem) { + chart.legend.colorizeItem(point, vis); + } + // #4170, hide halo after hiding point + if (!vis && point.state === 'hover') { + point.setState(''); + } + // Handle ignore hidden slices + if (ignoreHiddenPoint) { + series.isDirty = true; + } + if (redraw) { + chart.redraw(); + } + } + }, + /** + * Set or toggle whether the slice is cut out from the pie + * + * @private + * @function Highcharts.seriesTypes.pie#pointClass#slice + * @param {boolean} sliced + * When undefined, the slice state is toggled. + * @param {boolean} redraw + * Whether to redraw the chart. True by default. + * @param {boolean|Highcharts.AnimationOptionsObject} + * Animation options. + * @return {void} + */ + slice: function (sliced, redraw, animation) { + var point = this, series = point.series, chart = series.chart; + setAnimation(animation, chart); + // redraw is true by default + redraw = pick(redraw, true); + /** + * Pie series only. Whether to display a slice offset from the + * center. + * @name Highcharts.Point#sliced + * @type {boolean|undefined} + */ + // if called without an argument, toggle + point.sliced = point.options.sliced = sliced = + defined(sliced) ? sliced : !point.sliced; + // update userOptions.data + series.options.data[series.data.indexOf(point)] = + point.options; + if (point.graphic) { + point.graphic.animate(this.getTranslate()); + } + if (point.shadowGroup) { + point.shadowGroup.animate(this.getTranslate()); + } + }, + /** + * @private + * @function Highcharts.seriesTypes.pie#pointClass#getTranslate + * @return {Highcharts.TranslationAttributes} + */ + getTranslate: function () { + return this.sliced ? this.slicedTranslation : { + translateX: 0, + translateY: 0 + }; + }, + /** + * @private + * @function Highcharts.seriesTypes.pie#pointClass#haloPath + * @param {number} size + * @return {Highcharts.SVGPathArray} + */ + haloPath: function (size) { + var shapeArgs = this.shapeArgs; + return this.sliced || !this.visible ? + [] : + this.series.chart.renderer.symbols.arc(shapeArgs.x, shapeArgs.y, shapeArgs.r + size, shapeArgs.r + size, { + // Substract 1px to ensure the background is not bleeding + // through between the halo and the slice (#7495). + innerR: shapeArgs.r - 1, + start: shapeArgs.start, + end: shapeArgs.end + }); + }, + connectorShapes: { + // only one available before v7.0.0 + fixedOffset: function (labelPosition, connectorPosition, options) { + var breakAt = connectorPosition.breakAt, touchingSliceAt = connectorPosition.touchingSliceAt, lineSegment = options.softConnector ? [ + 'C', + // 1st control point (of the curve) + labelPosition.x + + // 5 gives the connector a little horizontal bend + (labelPosition.alignment === 'left' ? -5 : 5), + labelPosition.y, + 2 * breakAt.x - touchingSliceAt.x, + 2 * breakAt.y - touchingSliceAt.y, + breakAt.x, + breakAt.y // + ] : [ + 'L', + breakAt.x, + breakAt.y + ]; + // assemble the path + return ([ + ['M', labelPosition.x, labelPosition.y], + lineSegment, + ['L', touchingSliceAt.x, touchingSliceAt.y] + ]); + }, + straight: function (labelPosition, connectorPosition) { + var touchingSliceAt = connectorPosition.touchingSliceAt; + // direct line to the slice + return [ + ['M', labelPosition.x, labelPosition.y], + ['L', touchingSliceAt.x, touchingSliceAt.y] + ]; + }, + crookedLine: function (labelPosition, connectorPosition, options) { + var touchingSliceAt = connectorPosition.touchingSliceAt, series = this.series, pieCenterX = series.center[0], plotWidth = series.chart.plotWidth, plotLeft = series.chart.plotLeft, alignment = labelPosition.alignment, radius = this.shapeArgs.r, crookDistance = relativeLength(// % to fraction + options.crookDistance, 1), crookX = alignment === 'left' ? + pieCenterX + radius + (plotWidth + plotLeft - + pieCenterX - radius) * (1 - crookDistance) : + plotLeft + (pieCenterX - radius) * crookDistance, segmentWithCrook = [ + 'L', + crookX, + labelPosition.y + ], useCrook = true; + // crookedLine formula doesn't make sense if the path overlaps + // the label - use straight line instead in that case + if (alignment === 'left' ? + (crookX > labelPosition.x || crookX < touchingSliceAt.x) : + (crookX < labelPosition.x || crookX > touchingSliceAt.x)) { + useCrook = false; + } + // assemble the path + var path = [ + ['M', labelPosition.x, labelPosition.y] + ]; + if (useCrook) { + path.push(segmentWithCrook); + } + path.push(['L', touchingSliceAt.x, touchingSliceAt.y]); + return path; + } + }, + /** + * Extendable method for getting the path of the connector between the + * data label and the pie slice. + */ + getConnectorPath: function () { + var labelPosition = this.labelPosition, options = this.series.options.dataLabels, connectorShape = options.connectorShape, predefinedShapes = this.connectorShapes; + // find out whether to use the predefined shape + if (predefinedShapes[connectorShape]) { + connectorShape = predefinedShapes[connectorShape]; + } + return connectorShape.call(this, { + // pass simplified label position object for user's convenience + x: labelPosition.final.x, + y: labelPosition.final.y, + alignment: labelPosition.alignment + }, labelPosition.connectorPosition, options); + } +} +/* eslint-enable valid-jsdoc */ +); +/** + * A `pie` series. If the [type](#series.pie.type) option is not specified, + * it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.pie + * @excluding dataParser, dataURL, stack, xAxis, yAxis, dataSorting, step + * @product highcharts + * @apioption series.pie + */ +/** + * An array of data points for the series. For the `pie` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.pie.turboThreshold), + * this option is not available. + * ```js + * data: [{ + * y: 1, + * name: "Point2", + * color: "#00FF00" + * }, { + * y: 7, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @excluding marker, x + * @product highcharts + * @apioption series.pie.data + */ +/** + * @type {Highcharts.SeriesPieDataLabelsOptionsObject} + * @product highcharts + * @apioption series.pie.data.dataLabels + */ +/** + * The sequential index of the data point in the legend. + * + * @type {number} + * @product highcharts + * @apioption series.pie.data.legendIndex + */ +/** + * Whether to display a slice offset from the center. + * + * @sample {highcharts} highcharts/point/sliced/ + * One sliced point + * + * @type {boolean} + * @product highcharts + * @apioption series.pie.data.sliced + */ +/** + * @excluding legendItemClick + * @product highcharts + * @apioption series.pie.events + */ +''; // placeholder for transpiled doclets above diff --git a/librerias/gantt/code/es-modules/parts/PlotLineOrBand.js b/librerias/gantt/code/es-modules/parts/PlotLineOrBand.js new file mode 100644 index 0000000..bcc0292 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/PlotLineOrBand.js @@ -0,0 +1,1030 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +import Axis from './Axis.js'; +/** + * Options for plot bands on axes. + * + * @typedef {Highcharts.XAxisPlotBandsOptions|Highcharts.YAxisPlotBandsOptions|Highcharts.ZAxisPlotBandsOptions} Highcharts.AxisPlotBandsOptions + */ +/** + * Options for plot band labels on axes. + * + * @typedef {Highcharts.XAxisPlotBandsLabelOptions|Highcharts.YAxisPlotBandsLabelOptions|Highcharts.ZAxisPlotBandsLabelOptions} Highcharts.AxisPlotBandsLabelOptions + */ +/** + * Options for plot lines on axes. + * + * @typedef {Highcharts.XAxisPlotLinesOptions|Highcharts.YAxisPlotLinesOptions|Highcharts.ZAxisPlotLinesOptions} Highcharts.AxisPlotLinesOptions + */ +/** + * Options for plot line labels on axes. + * + * @typedef {Highcharts.XAxisPlotLinesLabelOptions|Highcharts.YAxisPlotLinesLabelOptions|Highcharts.ZAxisPlotLinesLabelOptions} Highcharts.AxisPlotLinesLabelOptions + */ +import U from './Utilities.js'; +var arrayMax = U.arrayMax, arrayMin = U.arrayMin, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, erase = U.erase, extend = U.extend, fireEvent = U.fireEvent, merge = U.merge, objectEach = U.objectEach, pick = U.pick; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * The object wrapper for plot lines and plot bands + * + * @class + * @name Highcharts.PlotLineOrBand + * + * @param {Highcharts.Axis} axis + * + * @param {Highcharts.AxisPlotLinesOptions|Highcharts.AxisPlotBandsOptions} [options] + */ +var PlotLineOrBand = /** @class */ (function () { + function PlotLineOrBand(axis, options) { + this.axis = axis; + if (options) { + this.options = options; + this.id = options.id; + } + } + /** + * Render the plot line or plot band. If it is already existing, + * move it. + * + * @private + * @function Highcharts.PlotLineOrBand#render + * @return {Highcharts.PlotLineOrBand|undefined} + */ + PlotLineOrBand.prototype.render = function () { + H.fireEvent(this, 'render'); + var plotLine = this, axis = plotLine.axis, horiz = axis.horiz, log = axis.logarithmic, options = plotLine.options, optionsLabel = options.label, label = plotLine.label, to = options.to, from = options.from, value = options.value, isBand = defined(from) && defined(to), isLine = defined(value), svgElem = plotLine.svgElem, isNew = !svgElem, path = [], color = options.color, zIndex = pick(options.zIndex, 0), events = options.events, attribs = { + 'class': 'highcharts-plot-' + (isBand ? 'band ' : 'line ') + + (options.className || '') + }, groupAttribs = {}, renderer = axis.chart.renderer, groupName = isBand ? 'bands' : 'lines', group; + // logarithmic conversion + if (log) { + from = log.log2lin(from); + to = log.log2lin(to); + value = log.log2lin(value); + } + // Set the presentational attributes + if (!axis.chart.styledMode) { + if (isLine) { + attribs.stroke = color || '#999999'; + attribs['stroke-width'] = pick(options.width, 1); + if (options.dashStyle) { + attribs.dashstyle = + options.dashStyle; + } + } + else if (isBand) { // plot band + attribs.fill = color || '#e6ebf5'; + if (options.borderWidth) { + attribs.stroke = options.borderColor; + attribs['stroke-width'] = options.borderWidth; + } + } + } + // Grouping and zIndex + groupAttribs.zIndex = zIndex; + groupName += '-' + zIndex; + group = axis.plotLinesAndBandsGroups[groupName]; + if (!group) { + axis.plotLinesAndBandsGroups[groupName] = group = + renderer.g('plot-' + groupName) + .attr(groupAttribs).add(); + } + // Create the path + if (isNew) { + /** + * SVG element of the plot line or band. + * + * @name Highcharts.PlotLineOrBand#svgElement + * @type {Highcharts.SVGElement} + */ + plotLine.svgElem = svgElem = renderer + .path() + .attr(attribs) + .add(group); + } + // Set the path or return + if (isLine) { + path = axis.getPlotLinePath({ + value: value, + lineWidth: svgElem.strokeWidth(), + acrossPanes: options.acrossPanes + }); + } + else if (isBand) { // plot band + path = axis.getPlotBandPath(from, to, options); + } + else { + return; + } + // common for lines and bands + if ((isNew || !svgElem.d) && path && path.length) { + svgElem.attr({ d: path }); + // events + if (events) { + objectEach(events, function (event, eventType) { + svgElem.on(eventType, function (e) { + events[eventType].apply(plotLine, [e]); + }); + }); + } + } + else if (svgElem) { + if (path) { + svgElem.show(true); + svgElem.animate({ d: path }); + } + else if (svgElem.d) { + svgElem.hide(); + if (label) { + plotLine.label = label = label.destroy(); + } + } + } + // the plot band/line label + if (optionsLabel && + (defined(optionsLabel.text) || defined(optionsLabel.formatter)) && + path && + path.length && + axis.width > 0 && + axis.height > 0 && + !path.isFlat) { + // apply defaults + optionsLabel = merge({ + align: horiz && isBand && 'center', + x: horiz ? !isBand && 4 : 10, + verticalAlign: !horiz && isBand && 'middle', + y: horiz ? isBand ? 16 : 10 : isBand ? 6 : -4, + rotation: horiz && !isBand && 90 + }, optionsLabel); + this.renderLabel(optionsLabel, path, isBand, zIndex); + } + else if (label) { // move out of sight + label.hide(); + } + // chainable + return plotLine; + }; + /** + * Render and align label for plot line or band. + * + * @private + * @function Highcharts.PlotLineOrBand#renderLabel + * @param {Highcharts.AxisPlotLinesLabelOptions|Highcharts.AxisPlotBandsLabelOptions} optionsLabel + * @param {Highcharts.SVGPathArray} path + * @param {boolean} [isBand] + * @param {number} [zIndex] + * @return {void} + */ + PlotLineOrBand.prototype.renderLabel = function (optionsLabel, path, isBand, zIndex) { + var plotLine = this, label = plotLine.label, renderer = plotLine.axis.chart.renderer, attribs, xBounds, yBounds, x, y, labelText; + // add the SVG element + if (!label) { + attribs = { + align: optionsLabel.textAlign || optionsLabel.align, + rotation: optionsLabel.rotation, + 'class': 'highcharts-plot-' + (isBand ? 'band' : 'line') + + '-label ' + (optionsLabel.className || '') + }; + attribs.zIndex = zIndex; + labelText = this.getLabelText(optionsLabel); + /** + * SVG element of the label. + * + * @name Highcharts.PlotLineOrBand#label + * @type {Highcharts.SVGElement} + */ + plotLine.label = label = renderer + .text(labelText, 0, 0, optionsLabel.useHTML) + .attr(attribs) + .add(); + if (!this.axis.chart.styledMode) { + label.css(optionsLabel.style); + } + } + // get the bounding box and align the label + // #3000 changed to better handle choice between plotband or plotline + xBounds = path.xBounds || + [path[0][1], path[1][1], (isBand ? path[2][1] : path[0][1])]; + yBounds = path.yBounds || + [path[0][2], path[1][2], (isBand ? path[2][2] : path[0][2])]; + x = arrayMin(xBounds); + y = arrayMin(yBounds); + label.align(optionsLabel, false, { + x: x, + y: y, + width: arrayMax(xBounds) - x, + height: arrayMax(yBounds) - y + }); + label.show(true); + }; + /** + * Get label's text content. + * + * @private + * @function Highcharts.PlotLineOrBand#getLabelText + * @param {Highcharts.AxisPlotLinesLabelOptions|Highcharts.AxisPlotBandsLabelOptions} optionsLabel + * @return {string} + */ + PlotLineOrBand.prototype.getLabelText = function (optionsLabel) { + return defined(optionsLabel.formatter) ? + optionsLabel.formatter + .call(this) : + optionsLabel.text; + }; + /** + * Remove the plot line or band. + * + * @function Highcharts.PlotLineOrBand#destroy + * @return {void} + */ + PlotLineOrBand.prototype.destroy = function () { + // remove it from the lookup + erase(this.axis.plotLinesAndBands, this); + delete this.axis; + destroyObjectProperties(this); + }; + return PlotLineOrBand; +}()); +/* eslint-enable no-invalid-this, valid-jsdoc */ +// Object with members for extending the Axis prototype +extend(Axis.prototype, /** @lends Highcharts.Axis.prototype */ { + /** + * An array of colored bands stretching across the plot area marking an + * interval on the axis. + * + * In styled mode, the plot bands are styled by the `.highcharts-plot-band` + * class in addition to the `className` option. + * + * @productdesc {highcharts} + * In a gauge, a plot band on the Y axis (value axis) will stretch along the + * perimeter of the gauge. + * + * @type {Array<*>} + * @product highcharts highstock gantt + * @apioption xAxis.plotBands + */ + /** + * Flag to decide if plotBand should be rendered across all panes. + * + * @since 7.1.2 + * @product highstock + * @type {boolean} + * @default true + * @apioption xAxis.plotBands.acrossPanes + */ + /** + * Border color for the plot band. Also requires `borderWidth` to be set. + * + * @type {Highcharts.ColorString} + * @apioption xAxis.plotBands.borderColor + */ + /** + * Border width for the plot band. Also requires `borderColor` to be set. + * + * @type {number} + * @default 0 + * @apioption xAxis.plotBands.borderWidth + */ + /** + * A custom class name, in addition to the default `highcharts-plot-band`, + * to apply to each individual band. + * + * @type {string} + * @since 5.0.0 + * @apioption xAxis.plotBands.className + */ + /** + * The color of the plot band. + * + * @sample {highcharts} highcharts/xaxis/plotbands-color/ + * Color band + * @sample {highstock} stock/xaxis/plotbands/ + * Plot band on Y axis + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #e6ebf5 + * @apioption xAxis.plotBands.color + */ + /** + * An object defining mouse events for the plot band. Supported properties + * are `click`, `mouseover`, `mouseout`, `mousemove`. + * + * @sample {highcharts} highcharts/xaxis/plotbands-events/ + * Mouse events demonstrated + * + * @since 1.2 + * @apioption xAxis.plotBands.events + */ + /** + * Click event on a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotBands.events.click + */ + /** + * Mouse move event on a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotBands.events.mousemove + */ + /** + * Mouse out event on the corner of a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotBands.events.mouseout + */ + /** + * Mouse over event on a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotBands.events.mouseover + */ + /** + * The start position of the plot band in axis units. + * + * @sample {highcharts} highcharts/xaxis/plotbands-color/ + * Datetime axis + * @sample {highcharts} highcharts/xaxis/plotbands-from/ + * Categorized axis + * @sample {highstock} stock/xaxis/plotbands/ + * Plot band on Y axis + * + * @type {number} + * @apioption xAxis.plotBands.from + */ + /** + * An id used for identifying the plot band in Axis.removePlotBand. + * + * @sample {highcharts} highcharts/xaxis/plotbands-id/ + * Remove plot band by id + * @sample {highstock} highcharts/xaxis/plotbands-id/ + * Remove plot band by id + * + * @type {string} + * @apioption xAxis.plotBands.id + */ + /** + * The end position of the plot band in axis units. + * + * @sample {highcharts} highcharts/xaxis/plotbands-color/ + * Datetime axis + * @sample {highcharts} highcharts/xaxis/plotbands-from/ + * Categorized axis + * @sample {highstock} stock/xaxis/plotbands/ + * Plot band on Y axis + * + * @type {number} + * @apioption xAxis.plotBands.to + */ + /** + * The z index of the plot band within the chart, relative to other + * elements. Using the same z index as another element may give + * unpredictable results, as the last rendered element will be on top. + * Values from 0 to 20 make sense. + * + * @sample {highcharts} highcharts/xaxis/plotbands-color/ + * Behind plot lines by default + * @sample {highcharts} highcharts/xaxis/plotbands-zindex/ + * Above plot lines + * @sample {highcharts} highcharts/xaxis/plotbands-zindex-above-series/ + * Above plot lines and series + * + * @type {number} + * @since 1.2 + * @apioption xAxis.plotBands.zIndex + */ + /** + * Text labels for the plot bands + * + * @product highcharts highstock gantt + * @apioption xAxis.plotBands.label + */ + /** + * Horizontal alignment of the label. Can be one of "left", "center" or + * "right". + * + * @sample {highcharts} highcharts/xaxis/plotbands-label-align/ + * Aligned to the right + * @sample {highstock} stock/xaxis/plotbands-label/ + * Plot band with labels + * + * @type {Highcharts.AlignValue} + * @default center + * @since 2.1 + * @apioption xAxis.plotBands.label.align + */ + /** + * Rotation of the text label in degrees . + * + * @sample {highcharts} highcharts/xaxis/plotbands-label-rotation/ + * Vertical text + * + * @type {number} + * @default 0 + * @since 2.1 + * @apioption xAxis.plotBands.label.rotation + */ + /** + * CSS styles for the text label. + * + * In styled mode, the labels are styled by the + * `.highcharts-plot-band-label` class. + * + * @sample {highcharts} highcharts/xaxis/plotbands-label-style/ + * Blue and bold label + * + * @type {Highcharts.CSSObject} + * @since 2.1 + * @apioption xAxis.plotBands.label.style + */ + /** + * The string text itself. A subset of HTML is supported. + * + * @type {string} + * @since 2.1 + * @apioption xAxis.plotBands.label.text + */ + /** + * The text alignment for the label. While `align` determines where the + * texts anchor point is placed within the plot band, `textAlign` determines + * how the text is aligned against its anchor point. Possible values are + * "left", "center" and "right". Defaults to the same as the `align` option. + * + * @sample {highcharts} highcharts/xaxis/plotbands-label-rotation/ + * Vertical text in center position but text-aligned left + * + * @type {Highcharts.AlignValue} + * @since 2.1 + * @apioption xAxis.plotBands.label.textAlign + */ + /** + * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the labels. + * + * @type {boolean} + * @default false + * @since 3.0.3 + * @apioption xAxis.plotBands.label.useHTML + */ + /** + * Vertical alignment of the label relative to the plot band. Can be one of + * "top", "middle" or "bottom". + * + * @sample {highcharts} highcharts/xaxis/plotbands-label-verticalalign/ + * Vertically centered label + * @sample {highstock} stock/xaxis/plotbands-label/ + * Plot band with labels + * + * @type {Highcharts.VerticalAlignValue} + * @default top + * @since 2.1 + * @apioption xAxis.plotBands.label.verticalAlign + */ + /** + * Horizontal position relative the alignment. Default varies by + * orientation. + * + * @sample {highcharts} highcharts/xaxis/plotbands-label-align/ + * Aligned 10px from the right edge + * @sample {highstock} stock/xaxis/plotbands-label/ + * Plot band with labels + * + * @type {number} + * @since 2.1 + * @apioption xAxis.plotBands.label.x + */ + /** + * Vertical position of the text baseline relative to the alignment. Default + * varies by orientation. + * + * @sample {highcharts} highcharts/xaxis/plotbands-label-y/ + * Label on x axis + * @sample {highstock} stock/xaxis/plotbands-label/ + * Plot band with labels + * + * @type {number} + * @since 2.1 + * @apioption xAxis.plotBands.label.y + */ + /** + * An array of lines stretching across the plot area, marking a specific + * value on one of the axes. + * + * In styled mode, the plot lines are styled by the + * `.highcharts-plot-line` class in addition to the `className` option. + * + * @type {Array<*>} + * @product highcharts highstock gantt + * @sample {highcharts} highcharts/xaxis/plotlines-color/ + * Basic plot line + * @sample {highcharts} highcharts/series-solidgauge/labels-auto-aligned/ + * Solid gauge plot line + * @apioption xAxis.plotLines + */ + /** + * Flag to decide if plotLine should be rendered across all panes. + * + * @sample {highstock} stock/xaxis/plotlines-acrosspanes/ + * Plot lines on different panes + * + * @since 7.1.2 + * @product highstock + * @type {boolean} + * @default true + * @apioption xAxis.plotLines.acrossPanes + */ + /** + * A custom class name, in addition to the default `highcharts-plot-line`, + * to apply to each individual line. + * + * @type {string} + * @since 5.0.0 + * @apioption xAxis.plotLines.className + */ + /** + * The color of the line. + * + * @sample {highcharts} highcharts/xaxis/plotlines-color/ + * A red line from X axis + * @sample {highstock} stock/xaxis/plotlines/ + * Plot line on Y axis + * + * @type {Highcharts.ColorString} + * @default #999999 + * @apioption xAxis.plotLines.color + */ + /** + * The dashing or dot style for the plot line. For possible values see + * [this overview](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/). + * + * @sample {highcharts} highcharts/xaxis/plotlines-dashstyle/ + * Dash and dot pattern + * @sample {highstock} stock/xaxis/plotlines/ + * Plot line on Y axis + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 1.2 + * @apioption xAxis.plotLines.dashStyle + */ + /** + * An object defining mouse events for the plot line. Supported + * properties are `click`, `mouseover`, `mouseout`, `mousemove`. + * + * @sample {highcharts} highcharts/xaxis/plotlines-events/ + * Mouse events demonstrated + * + * @since 1.2 + * @apioption xAxis.plotLines.events + */ + /** + * Click event on a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotLines.events.click + */ + /** + * Mouse move event on a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotLines.events.mousemove + */ + /** + * Mouse out event on the corner of a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotLines.events.mouseout + */ + /** + * Mouse over event on a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotLines.events.mouseover + */ + /** + * An id used for identifying the plot line in Axis.removePlotLine. + * + * @sample {highcharts} highcharts/xaxis/plotlines-id/ + * Remove plot line by id + * + * @type {string} + * @apioption xAxis.plotLines.id + */ + /** + * The position of the line in axis units. + * + * @sample {highcharts} highcharts/xaxis/plotlines-color/ + * Between two categories on X axis + * @sample {highstock} stock/xaxis/plotlines/ + * Plot line on Y axis + * + * @type {number} + * @apioption xAxis.plotLines.value + */ + /** + * The width or thickness of the plot line. + * + * @sample {highcharts} highcharts/xaxis/plotlines-color/ + * 2px wide line from X axis + * @sample {highstock} stock/xaxis/plotlines/ + * Plot line on Y axis + * + * @type {number} + * @default 2 + * @apioption xAxis.plotLines.width + */ + /** + * The z index of the plot line within the chart. + * + * @sample {highcharts} highcharts/xaxis/plotlines-zindex-behind/ + * Behind plot lines by default + * @sample {highcharts} highcharts/xaxis/plotlines-zindex-above/ + * Above plot lines + * @sample {highcharts} highcharts/xaxis/plotlines-zindex-above-all/ + * Above plot lines and series + * + * @type {number} + * @since 1.2 + * @apioption xAxis.plotLines.zIndex + */ + /** + * Text labels for the plot bands + * + * @apioption xAxis.plotLines.label + */ + /** + * Horizontal alignment of the label. Can be one of "left", "center" or + * "right". + * + * @sample {highcharts} highcharts/xaxis/plotlines-label-align-right/ + * Aligned to the right + * @sample {highstock} stock/xaxis/plotlines/ + * Plot line on Y axis + * + * @type {Highcharts.AlignValue} + * @default left + * @since 2.1 + * @apioption xAxis.plotLines.label.align + */ + /** + * Callback JavaScript function to format the label. Useful properties like + * the value of plot line or the range of plot band (`from` & `to` + * properties) can be found in `this.options` object. + * + * @sample {highcharts} highcharts/xaxis/plotlines-plotbands-label-formatter + * Label formatters for plot line and plot band. + * @type {Highcharts.FormatterCallbackFunction} + * @apioption xAxis.plotLines.label.formatter + */ + /** + * Rotation of the text label in degrees. Defaults to 0 for horizontal plot + * lines and 90 for vertical lines. + * + * @sample {highcharts} highcharts/xaxis/plotlines-label-verticalalign-middle/ + * Slanted text + * + * @type {number} + * @since 2.1 + * @apioption xAxis.plotLines.label.rotation + */ + /** + * CSS styles for the text label. + * + * In styled mode, the labels are styled by the + * `.highcharts-plot-line-label` class. + * + * @sample {highcharts} highcharts/xaxis/plotlines-label-style/ + * Blue and bold label + * + * @type {Highcharts.CSSObject} + * @since 2.1 + * @apioption xAxis.plotLines.label.style + */ + /** + * The text itself. A subset of HTML is supported. + * + * @type {string} + * @since 2.1 + * @apioption xAxis.plotLines.label.text + */ + /** + * The text alignment for the label. While `align` determines where the + * texts anchor point is placed within the plot band, `textAlign` determines + * how the text is aligned against its anchor point. Possible values are + * "left", "center" and "right". Defaults to the same as the `align` option. + * + * @sample {highcharts} highcharts/xaxis/plotlines-label-textalign/ + * Text label in bottom position + * + * @type {Highcharts.AlignValue} + * @since 2.1 + * @apioption xAxis.plotLines.label.textAlign + */ + /** + * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the labels. + * + * @type {boolean} + * @default false + * @since 3.0.3 + * @apioption xAxis.plotLines.label.useHTML + */ + /** + * Vertical alignment of the label relative to the plot line. Can be + * one of "top", "middle" or "bottom". + * + * @sample {highcharts} highcharts/xaxis/plotlines-label-verticalalign-middle/ + * Vertically centered label + * + * @type {Highcharts.VerticalAlignValue} + * @default {highcharts} top + * @default {highstock} top + * @since 2.1 + * @apioption xAxis.plotLines.label.verticalAlign + */ + /** + * Horizontal position relative the alignment. Default varies by + * orientation. + * + * @sample {highcharts} highcharts/xaxis/plotlines-label-align-right/ + * Aligned 10px from the right edge + * @sample {highstock} stock/xaxis/plotlines/ + * Plot line on Y axis + * + * @type {number} + * @since 2.1 + * @apioption xAxis.plotLines.label.x + */ + /** + * Vertical position of the text baseline relative to the alignment. Default + * varies by orientation. + * + * @sample {highcharts} highcharts/xaxis/plotlines-label-y/ + * Label below the plot line + * @sample {highstock} stock/xaxis/plotlines/ + * Plot line on Y axis + * + * @type {number} + * @since 2.1 + * @apioption xAxis.plotLines.label.y + */ + /** + * + * @type {Array<*>} + * @extends xAxis.plotBands + * @apioption yAxis.plotBands + */ + /** + * In a gauge chart, this option determines the inner radius of the + * plot band that stretches along the perimeter. It can be given as + * a percentage string, like `"100%"`, or as a pixel number, like `100`. + * By default, the inner radius is controlled by the [thickness]( + * #yAxis.plotBands.thickness) option. + * + * @sample {highcharts} highcharts/xaxis/plotbands-gauge + * Gauge plot band + * + * @type {number|string} + * @since 2.3 + * @product highcharts + * @apioption yAxis.plotBands.innerRadius + */ + /** + * In a gauge chart, this option determines the outer radius of the + * plot band that stretches along the perimeter. It can be given as + * a percentage string, like `"100%"`, or as a pixel number, like `100`. + * + * @sample {highcharts} highcharts/xaxis/plotbands-gauge + * Gauge plot band + * + * @type {number|string} + * @default 100% + * @since 2.3 + * @product highcharts + * @apioption yAxis.plotBands.outerRadius + */ + /** + * In a gauge chart, this option sets the width of the plot band + * stretching along the perimeter. It can be given as a percentage + * string, like `"10%"`, or as a pixel number, like `10`. The default + * value 10 is the same as the default [tickLength](#yAxis.tickLength), + * thus making the plot band act as a background for the tick markers. + * + * @sample {highcharts} highcharts/xaxis/plotbands-gauge + * Gauge plot band + * + * @type {number|string} + * @default 10 + * @since 2.3 + * @product highcharts + * @apioption yAxis.plotBands.thickness + */ + /** + * @type {Array<*>} + * @extends xAxis.plotLines + * @apioption yAxis.plotLines + */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Internal function to create the SVG path definition for a plot band. + * + * @function Highcharts.Axis#getPlotBandPath + * + * @param {number} from + * The axis value to start from. + * + * @param {number} to + * The axis value to end on. + * + * @return {Highcharts.SVGPathArray} + * The SVG path definition in array form. + */ + getPlotBandPath: function (from, to) { + var toPath = this.getPlotLinePath({ + value: to, + force: true, + acrossPanes: this.options.acrossPanes + }), path = this.getPlotLinePath({ + value: from, + force: true, + acrossPanes: this.options.acrossPanes + }), result = [], i, + // #4964 check if chart is inverted or plotband is on yAxis + horiz = this.horiz, plus = 1, isFlat, outside = (from < this.min && to < this.min) || + (from > this.max && to > this.max); + if (path && toPath) { + // Flat paths don't need labels (#3836) + if (outside) { + isFlat = path.toString() === toPath.toString(); + plus = 0; + } + // Go over each subpath - for panes in Highstock + for (i = 0; i < path.length; i += 2) { + var pathStart = path[i], pathEnd = path[i + 1], toPathStart = toPath[i], toPathEnd = toPath[i + 1]; + // Type checking all affected path segments. Consider something + // smarter. + if ((pathStart[0] === 'M' || pathStart[0] === 'L') && + (pathEnd[0] === 'M' || pathEnd[0] === 'L') && + (toPathStart[0] === 'M' || toPathStart[0] === 'L') && + (toPathEnd[0] === 'M' || toPathEnd[0] === 'L')) { + // Add 1 pixel when coordinates are the same + if (horiz && toPathStart[1] === pathStart[1]) { + toPathStart[1] += plus; + toPathEnd[1] += plus; + } + else if (!horiz && toPathStart[2] === pathStart[2]) { + toPathStart[2] += plus; + toPathEnd[2] += plus; + } + result.push(['M', pathStart[1], pathStart[2]], ['L', pathEnd[1], pathEnd[2]], ['L', toPathEnd[1], toPathEnd[2]], ['L', toPathStart[1], toPathStart[2]], ['Z']); + } + result.isFlat = isFlat; + } + } + else { // outside the axis area + path = null; + } + return result; + }, + /** + * Add a plot band after render time. + * + * @sample highcharts/members/axis-addplotband/ + * Toggle the plot band from a button + * + * @function Highcharts.Axis#addPlotBand + * + * @param {Highcharts.AxisPlotBandsOptions} options + * A configuration object for the plot band, as defined in + * [xAxis.plotBands](https://api.highcharts.com/highcharts/xAxis.plotBands). + * + * @return {Highcharts.PlotLineOrBand|undefined} + * The added plot band. + */ + addPlotBand: function (options) { + return this.addPlotBandOrLine(options, 'plotBands'); + }, + /** + * Add a plot line after render time. + * + * @sample highcharts/members/axis-addplotline/ + * Toggle the plot line from a button + * + * @function Highcharts.Axis#addPlotLine + * + * @param {Highcharts.AxisPlotLinesOptions} options + * A configuration object for the plot line, as defined in + * [xAxis.plotLines](https://api.highcharts.com/highcharts/xAxis.plotLines). + * + * @return {Highcharts.PlotLineOrBand|undefined} + * The added plot line. + */ + addPlotLine: function (options) { + return this.addPlotBandOrLine(options, 'plotLines'); + }, + /** + * Add a plot band or plot line after render time. Called from addPlotBand + * and addPlotLine internally. + * + * @private + * @function Highcharts.Axis#addPlotBandOrLine + * + * @param {Highcharts.AxisPlotBandsOptions|Highcharts.AxisPlotLinesOptions} options + * The plotBand or plotLine configuration object. + * + * @param {"plotBands"|"plotLines"} [coll] + * + * @return {Highcharts.PlotLineOrBand|undefined} + */ + addPlotBandOrLine: function (options, coll) { + var obj = new PlotLineOrBand(this, options).render(), userOptions = this.userOptions; + if (obj) { // #2189 + // Add it to the user options for exporting and Axis.update + if (coll) { + // Workaround Microsoft/TypeScript issue #32693 + var updatedOptions = (userOptions[coll] || []); + updatedOptions.push(options); + userOptions[coll] = updatedOptions; + } + this.plotLinesAndBands.push(obj); + } + return obj; + }, + /** + * Remove a plot band or plot line from the chart by id. Called internally + * from `removePlotBand` and `removePlotLine`. + * + * @private + * @function Highcharts.Axis#removePlotBandOrLine + * @param {string} id + * @return {void} + */ + removePlotBandOrLine: function (id) { + var plotLinesAndBands = this.plotLinesAndBands, options = this.options, userOptions = this.userOptions, i = plotLinesAndBands.length; + while (i--) { + if (plotLinesAndBands[i].id === id) { + plotLinesAndBands[i].destroy(); + } + } + ([ + options.plotLines || [], + userOptions.plotLines || [], + options.plotBands || [], + userOptions.plotBands || [] + ]).forEach(function (arr) { + i = arr.length; + while (i--) { + if ((arr[i] || {}).id === id) { + erase(arr, arr[i]); + } + } + }); + }, + /** + * Remove a plot band by its id. + * + * @sample highcharts/members/axis-removeplotband/ + * Remove plot band by id + * @sample highcharts/members/axis-addplotband/ + * Toggle the plot band from a button + * + * @function Highcharts.Axis#removePlotBand + * + * @param {string} id + * The plot band's `id` as given in the original configuration + * object or in the `addPlotBand` option. + * + * @return {void} + */ + removePlotBand: function (id) { + this.removePlotBandOrLine(id); + }, + /** + * Remove a plot line by its id. + * + * @sample highcharts/xaxis/plotlines-id/ + * Remove plot line by id + * @sample highcharts/members/axis-addplotline/ + * Toggle the plot line from a button + * + * @function Highcharts.Axis#removePlotLine + * + * @param {string} id + * The plot line's `id` as given in the original configuration + * object or in the `addPlotLine` option. + */ + removePlotLine: function (id) { + this.removePlotBandOrLine(id); + } +}); +H.PlotLineOrBand = PlotLineOrBand; +export default H.PlotLineOrBand; diff --git a/librerias/gantt/code/es-modules/parts/Point.js b/librerias/gantt/code/es-modules/parts/Point.js new file mode 100644 index 0000000..d9b6c26 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/Point.js @@ -0,0 +1,806 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Highcharts from './Globals.js'; +/** + * Function callback when a series point is clicked. Return false to cancel the + * action. + * + * @callback Highcharts.PointClickCallbackFunction + * + * @param {Highcharts.Point} this + * The point where the event occured. + * + * @param {Highcharts.PointClickEventObject} event + * Event arguments. + */ +/** + * Common information for a click event on a series point. + * + * @interface Highcharts.PointClickEventObject + * @extends Highcharts.PointerEventObject + */ /** +* Clicked point. +* @name Highcharts.PointClickEventObject#point +* @type {Highcharts.Point} +*/ +/** + * Configuration hash for the data label and tooltip formatters. + * + * @interface Highcharts.PointLabelObject + */ /** +* The point's current color. +* @name Highcharts.PointLabelObject#color +* @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined} +*/ /** +* The point's current color index, used in styled mode instead of `color`. The +* color index is inserted in class names used for styling. +* @name Highcharts.PointLabelObject#colorIndex +* @type {number} +*/ /** +* The name of the related point. +* @name Highcharts.PointLabelObject#key +* @type {string|undefined} +*/ /** +* The percentage for related points in a stacked series or pies. +* @name Highcharts.PointLabelObject#percentage +* @type {number} +*/ /** +* The related point. The point name, if defined, is available through +* `this.point.name`. +* @name Highcharts.PointLabelObject#point +* @type {Highcharts.Point} +*/ /** +* The related series. The series name is available through `this.series.name`. +* @name Highcharts.PointLabelObject#series +* @type {Highcharts.Series} +*/ /** +* The total of values in either a stack for stacked series, or a pie in a pie +* series. +* @name Highcharts.PointLabelObject#total +* @type {number|undefined} +*/ /** +* For categorized axes this property holds the category name for the point. For +* other axes it holds the X value. +* @name Highcharts.PointLabelObject#x +* @type {number|string|undefined} +*/ /** +* The y value of the point. +* @name Highcharts.PointLabelObject#y +* @type {number|undefined} +*/ +/** + * Gets fired when the mouse leaves the area close to the point. + * + * @callback Highcharts.PointMouseOutCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {global.PointerEvent} event + * Event that occured. + */ +/** + * Gets fired when the mouse enters the area close to the point. + * + * @callback Highcharts.PointMouseOverCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {global.Event} event + * Event that occured. + */ +/** + * The generic point options for all series. + * + * In TypeScript you have to extend `PointOptionsObject` with an additional + * declaration to allow custom data options: + * + * ``` + * declare interface PointOptionsObject { + * customProperty: string; + * } + * ``` + * + * @interface Highcharts.PointOptionsObject + */ +/** + * Possible option types for a data point. + * + * @typedef {number|string|Array<(number|string)>|Highcharts.PointOptionsObject|null} Highcharts.PointOptionsType + */ +/** + * Gets fired when the point is removed using the `.remove()` method. + * + * @callback Highcharts.PointRemoveCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {global.Event} event + * Event that occured. + */ +/** + * Possible key values for the point state options. + * + * @typedef {"hover"|"inactive"|"normal"|"select"} Highcharts.PointStateValue + */ +/** + * Gets fired when the point is updated programmatically through the `.update()` + * method. + * + * @callback Highcharts.PointUpdateCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {Highcharts.PointUpdateEventObject} event + * Event that occured. + */ +/** + * Information about the update event. + * + * @interface Highcharts.PointUpdateEventObject + * @extends global.Event + */ /** +* Options data of the update event. +* @name Highcharts.PointUpdateEventObject#options +* @type {Highcharts.PointOptionsType} +*/ +''; // detach doclet above +import U from './Utilities.js'; +var animObject = U.animObject, defined = U.defined, erase = U.erase, extend = U.extend, fireEvent = U.fireEvent, format = U.format, getNestedProperty = U.getNestedProperty, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, syncTimeout = U.syncTimeout, pick = U.pick, removeEvent = U.removeEvent, uniqueKey = U.uniqueKey; +var H = Highcharts; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * The Point object. The point objects are generated from the `series.data` + * configuration objects or raw numbers. They can be accessed from the + * `Series.points` array. Other ways to instantiate points are through {@link + * Highcharts.Series#addPoint} or {@link Highcharts.Series#setData}. + * + * @class + * @name Highcharts.Point + */ +var Point = /** @class */ (function () { + function Point() { + /* * + * + * Properties + * + * */ + /** + * For categorized axes this property holds the category name for the + * point. For other axes it holds the X value. + * + * @name Highcharts.Point#category + * @type {string} + */ + this.category = void 0; + /** + * The point's current color index, used in styled mode instead of + * `color`. The color index is inserted in class names used for styling. + * + * @name Highcharts.Point#colorIndex + * @type {number} + */ + this.colorIndex = void 0; + this.formatPrefix = 'point'; + this.id = void 0; + this.isNull = false; + /** + * The name of the point. The name can be given as the first position of the + * point configuration array, or as a `name` property in the configuration: + * + * @example + * // Array config + * data: [ + * ['John', 1], + * ['Jane', 2] + * ] + * + * // Object config + * data: [{ + * name: 'John', + * y: 1 + * }, { + * name: 'Jane', + * y: 2 + * }] + * + * @name Highcharts.Point#name + * @type {string} + */ + this.name = void 0; + /** + * The point's options as applied in the initial configuration, or + * extended through `Point.update`. + * + * In TypeScript you have to extend `PointOptionsObject` via an + * additional interface to allow custom data options: + * + * ``` + * declare interface PointOptionsObject { + * customProperty: string; + * } + * ``` + * + * @name Highcharts.Point#options + * @type {Highcharts.PointOptionsObject} + */ + this.options = void 0; + /** + * The percentage for points in a stacked series or pies. + * + * @name Highcharts.Point#percentage + * @type {number|undefined} + */ + this.percentage = void 0; + this.selected = false; + /** + * The series object associated with the point. + * + * @name Highcharts.Point#series + * @type {Highcharts.Series} + */ + this.series = void 0; + /** + * The total of values in either a stack for stacked series, or a pie in a + * pie series. + * + * @name Highcharts.Point#total + * @type {number|undefined} + */ + this.total = void 0; + /** + * For certain series types, like pie charts, where individual points can + * be shown or hidden. + * + * @name Highcharts.Point#visible + * @type {boolean} + * @default true + */ + this.visible = true; + this.x = void 0; + } + /* * + * + * Functions + * + * */ + /** + * Animate SVG elements associated with the point. + * + * @private + * @function Highcharts.Point#animateBeforeDestroy + * @return {void} + */ + Point.prototype.animateBeforeDestroy = function () { + var point = this, animateParams = { x: point.startXPos, opacity: 0 }, isDataLabel, graphicalProps = point.getGraphicalProps(); + graphicalProps.singular.forEach(function (prop) { + isDataLabel = prop === 'dataLabel'; + point[prop] = point[prop].animate(isDataLabel ? { + x: point[prop].startXPos, + y: point[prop].startYPos, + opacity: 0 + } : animateParams); + }); + graphicalProps.plural.forEach(function (plural) { + point[plural].forEach(function (item) { + if (item.element) { + item.animate(extend({ x: point.startXPos }, (item.startYPos ? { + x: item.startXPos, + y: item.startYPos + } : {}))); + } + }); + }); + }; + /** + * Apply the options containing the x and y data and possible some extra + * properties. Called on point init or from point.update. + * + * @private + * @function Highcharts.Point#applyOptions + * + * @param {Highcharts.PointOptionsType} options + * The point options as defined in series.data. + * + * @param {number} [x] + * Optionally, the x value. + * + * @return {Highcharts.Point} + * The Point instance. + */ + Point.prototype.applyOptions = function (options, x) { + var point = this, series = point.series, pointValKey = series.options.pointValKey || series.pointValKey; + options = Point.prototype.optionsToObject.call(this, options); + // copy options directly to point + extend(point, options); + point.options = point.options ? extend(point.options, options) : options; + // Since options are copied into the Point instance, some accidental + // options must be shielded (#5681) + if (options.group) { + delete point.group; + } + if (options.dataLabels) { + delete point.dataLabels; + } + /** + * The y value of the point. + * @name Highcharts.Point#y + * @type {number|undefined} + */ + // For higher dimension series types. For instance, for ranges, point.y + // is mapped to point.low. + if (pointValKey) { + point.y = Point.prototype.getNestedProperty.call(point, pointValKey); + } + point.isNull = pick(point.isValid && !point.isValid(), point.x === null || !isNumber(point.y)); // #3571, check for NaN + point.formatPrefix = point.isNull ? 'null' : 'point'; // #9233, #10874 + // The point is initially selected by options (#5777) + if (point.selected) { + point.state = 'select'; + } + /** + * The x value of the point. + * @name Highcharts.Point#x + * @type {number} + */ + // If no x is set by now, get auto incremented value. All points must + // have an x value, however the y value can be null to create a gap in + // the series + if ('name' in point && + typeof x === 'undefined' && + series.xAxis && + series.xAxis.hasNames) { + point.x = series.xAxis.nameToX(point); + } + if (typeof point.x === 'undefined' && series) { + if (typeof x === 'undefined') { + point.x = series.autoIncrement(point); + } + else { + point.x = x; + } + } + return point; + }; + /** + * Destroy a point to clear memory. Its reference still stays in + * `series.data`. + * + * @private + * @function Highcharts.Point#destroy + * @return {void} + */ + Point.prototype.destroy = function () { + var point = this, series = point.series, chart = series.chart, dataSorting = series.options.dataSorting, hoverPoints = chart.hoverPoints, globalAnimation = point.series.chart.renderer.globalAnimation, animation = animObject(globalAnimation), prop; + /** + * Allow to call after animation. + * @private + */ + function destroyPoint() { + // Remove all events and elements + if (point.graphic || point.dataLabel || point.dataLabels) { + removeEvent(point); + point.destroyElements(); + } + for (prop in point) { // eslint-disable-line guard-for-in + point[prop] = null; + } + } + if (point.legendItem) { // pies have legend items + chart.legend.destroyItem(point); + } + if (hoverPoints) { + point.setState(); + erase(hoverPoints, point); + if (!hoverPoints.length) { + chart.hoverPoints = null; + } + } + if (point === chart.hoverPoint) { + point.onMouseOut(); + } + // Remove properties after animation + if (!dataSorting || !dataSorting.enabled) { + destroyPoint(); + } + else { + this.animateBeforeDestroy(); + syncTimeout(destroyPoint, animation.duration); + } + chart.pointCount--; + }; + /** + * Destroy SVG elements associated with the point. + * + * @private + * @function Highcharts.Point#destroyElements + * @param {Highcharts.Dictionary} [kinds] + * @return {void} + */ + Point.prototype.destroyElements = function (kinds) { + var point = this, props = point.getGraphicalProps(kinds); + props.singular.forEach(function (prop) { + point[prop] = point[prop].destroy(); + }); + props.plural.forEach(function (plural) { + point[plural].forEach(function (item) { + if (item.element) { + item.destroy(); + } + }); + delete point[plural]; + }); + }; + /** + * Fire an event on the Point object. + * + * @private + * @function Highcharts.Point#firePointEvent + * + * @param {string} eventType + * Type of the event. + * + * @param {Highcharts.Dictionary|Event} [eventArgs] + * Additional event arguments. + * + * @param {Highcharts.EventCallbackFunction|Function} [defaultFunction] + * Default event handler. + * + * @fires Highcharts.Point#event:* + */ + Point.prototype.firePointEvent = function (eventType, eventArgs, defaultFunction) { + var point = this, series = this.series, seriesOptions = series.options; + // load event handlers on demand to save time on mouseover/out + if (seriesOptions.point.events[eventType] || + (point.options && + point.options.events && + point.options.events[eventType])) { + point.importEvents(); + } + // add default handler if in selection mode + if (eventType === 'click' && seriesOptions.allowPointSelect) { + defaultFunction = function (event) { + // Control key is for Windows, meta (= Cmd key) for Mac, Shift + // for Opera. + if (point.select) { // #2911 + point.select(null, event.ctrlKey || event.metaKey || event.shiftKey); + } + }; + } + fireEvent(point, eventType, eventArgs, defaultFunction); + }; + /** + * Get the CSS class names for individual points. Used internally where the + * returned value is set on every point. + * + * @function Highcharts.Point#getClassName + * + * @return {string} + * The class names. + */ + Point.prototype.getClassName = function () { + var point = this; + return 'highcharts-point' + + (point.selected ? ' highcharts-point-select' : '') + + (point.negative ? ' highcharts-negative' : '') + + (point.isNull ? ' highcharts-null-point' : '') + + (typeof point.colorIndex !== 'undefined' ? + ' highcharts-color-' + point.colorIndex : '') + + (point.options.className ? ' ' + point.options.className : '') + + (point.zone && point.zone.className ? ' ' + + point.zone.className.replace('highcharts-negative', '') : ''); + }; + /** + * Get props of all existing graphical point elements. + * + * @private + * @function Highcharts.Point#getGraphicalProps + * @param {Highcharts.Dictionary} [kinds] + * @return {Highcharts.PointGraphicalProps} + */ + Point.prototype.getGraphicalProps = function (kinds) { + var point = this, props = [], prop, i, graphicalProps = { singular: [], plural: [] }; + kinds = kinds || { graphic: 1, dataLabel: 1 }; + if (kinds.graphic) { + props.push('graphic', 'shadowGroup'); + } + if (kinds.dataLabel) { + props.push('dataLabel', 'dataLabelUpper', 'connector'); + } + i = props.length; + while (i--) { + prop = props[i]; + if (point[prop]) { + graphicalProps.singular.push(prop); + } + } + ['dataLabel', 'connector'].forEach(function (prop) { + var plural = prop + 's'; + if (kinds[prop] && point[plural]) { + graphicalProps.plural.push(plural); + } + }); + return graphicalProps; + }; + /** + * Return the configuration hash needed for the data label and tooltip + * formatters. + * + * @function Highcharts.Point#getLabelConfig + * + * @return {Highcharts.PointLabelObject} + * Abstract object used in formatters and formats. + */ + Point.prototype.getLabelConfig = function () { + return { + x: this.category, + y: this.y, + color: this.color, + colorIndex: this.colorIndex, + key: this.name || this.category, + series: this.series, + point: this, + percentage: this.percentage, + total: this.total || this.stackTotal + }; + }; + /** + * Returns the value of the point property for a given value. + * @private + */ + Point.prototype.getNestedProperty = function (key) { + if (!key) { + return; + } + if (key.indexOf('custom.') === 0) { + return getNestedProperty(key, this.options); + } + return this[key]; + }; + /** + * In a series with `zones`, return the zone that the point belongs to. + * + * @function Highcharts.Point#getZone + * + * @return {Highcharts.SeriesZonesOptionsObject} + * The zone item. + */ + Point.prototype.getZone = function () { + var series = this.series, zones = series.zones, zoneAxis = series.zoneAxis || 'y', i = 0, zone; + zone = zones[i]; + while (this[zoneAxis] >= zone.value) { + zone = zones[++i]; + } + // For resetting or reusing the point (#8100) + if (!this.nonZonedColor) { + this.nonZonedColor = this.color; + } + if (zone && zone.color && !this.options.color) { + this.color = zone.color; + } + else { + this.color = this.nonZonedColor; + } + return zone; + }; + /** + * Utility to check if point has new shape type. Used in column series and + * all others that are based on column series. + * + * @return boolean|undefined + */ + Point.prototype.hasNewShapeType = function () { + var point = this; + var oldShapeType = point.graphic && + (point.graphic.symbolName || point.graphic.element.nodeName); + return oldShapeType !== this.shapeType; + }; + /** + * Initialize the point. Called internally based on the `series.data` + * option. + * + * @function Highcharts.Point#init + * + * @param {Highcharts.Series} series + * The series object containing this point. + * + * @param {Highcharts.PointOptionsType} options + * The data in either number, array or object format. + * + * @param {number} [x] + * Optionally, the X value of the point. + * + * @return {Highcharts.Point} + * The Point instance. + * + * @fires Highcharts.Point#event:afterInit + */ + Point.prototype.init = function (series, options, x) { + this.series = series; + this.applyOptions(options, x); + // Add a unique ID to the point if none is assigned + this.id = defined(this.id) ? this.id : uniqueKey(); + this.resolveColor(); + series.chart.pointCount++; + fireEvent(this, 'afterInit'); + return this; + }; + /** + * Transform number or array configs into objects. Also called for object + * configs. Used internally to unify the different configuration formats for + * points. For example, a simple number `10` in a line series will be + * transformed to `{ y: 10 }`, and an array config like `[1, 10]` in a + * scatter series will be transformed to `{ x: 1, y: 10 }`. + * + * @function Highcharts.Point#optionsToObject + * + * @param {Highcharts.PointOptionsType} options + * The input option. + * + * @return {Highcharts.Dictionary<*>} + * Transformed options. + */ + Point.prototype.optionsToObject = function (options) { + var ret = {}, series = this.series, keys = series.options.keys, pointArrayMap = keys || series.pointArrayMap || ['y'], valueCount = pointArrayMap.length, firstItemType, i = 0, j = 0; + if (isNumber(options) || options === null) { + ret[pointArrayMap[0]] = options; + } + else if (isArray(options)) { + // with leading x value + if (!keys && options.length > valueCount) { + firstItemType = typeof options[0]; + if (firstItemType === 'string') { + ret.name = options[0]; + } + else if (firstItemType === 'number') { + ret.x = options[0]; + } + i++; + } + while (j < valueCount) { + // Skip undefined positions for keys + if (!keys || typeof options[i] !== 'undefined') { + if (pointArrayMap[j].indexOf('.') > 0) { + // Handle nested keys, e.g. ['color.pattern.image'] + // Avoid function call unless necessary. + Point.prototype.setNestedProperty(ret, options[i], pointArrayMap[j]); + } + else { + ret[pointArrayMap[j]] = options[i]; + } + } + i++; + j++; + } + } + else if (typeof options === 'object') { + ret = options; + // This is the fastest way to detect if there are individual point + // dataLabels that need to be considered in drawDataLabels. These + // can only occur in object configs. + if (options.dataLabels) { + series._hasPointLabels = true; + } + // Same approach as above for markers + if (options.marker) { + series._hasPointMarkers = true; + } + } + return ret; + }; + /** + * @private + * @function Highcharts.Point#resolveColor + * @return {void} + */ + Point.prototype.resolveColor = function () { + var series = this.series, colors, optionsChart = series.chart.options.chart, colorCount = optionsChart.colorCount, styledMode = series.chart.styledMode, colorIndex; + // remove points nonZonedColor for later recalculation + delete this.nonZonedColor; + /** + * The point's current color. + * + * @name Highcharts.Point#color + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined} + */ + if (!styledMode && !this.options.color) { + this.color = series.color; // #3445 + } + if (series.options.colorByPoint) { + if (!styledMode) { + colors = series.options.colors || series.chart.options.colors; + this.color = this.color || colors[series.colorCounter]; + colorCount = colors.length; + } + colorIndex = series.colorCounter; + series.colorCounter++; + // loop back to zero + if (series.colorCounter === colorCount) { + series.colorCounter = 0; + } + } + else { + colorIndex = series.colorIndex; + } + this.colorIndex = pick(this.colorIndex, colorIndex); + }; + /** + * Set a value in an object, on the property defined by key. The key + * supports nested properties using dot notation. The function modifies the + * input object and does not make a copy. + * + * @function Highcharts.Point#setNestedProperty + * + * @param {T} object + * The object to set the value on. + * + * @param {*} value + * The value to set. + * + * @param {string} key + * Key to the property to set. + * + * @return {T} + * The modified object. + */ + Point.prototype.setNestedProperty = function (object, value, key) { + var nestedKeys = key.split('.'); + nestedKeys.reduce(function (result, key, i, arr) { + var isLastKey = arr.length - 1 === i; + result[key] = (isLastKey ? + value : + isObject(result[key], true) ? + result[key] : + {}); + return result[key]; + }, object); + return object; + }; + /** + * Extendable method for formatting each point's tooltip line. + * + * @function Highcharts.Point#tooltipFormatter + * + * @param {string} pointFormat + * The point format. + * + * @return {string} + * A string to be concatenated in to the common tooltip text. + */ + Point.prototype.tooltipFormatter = function (pointFormat) { + // Insert options for valueDecimals, valuePrefix, and valueSuffix + var series = this.series, seriesTooltipOptions = series.tooltipOptions, valueDecimals = pick(seriesTooltipOptions.valueDecimals, ''), valuePrefix = seriesTooltipOptions.valuePrefix || '', valueSuffix = seriesTooltipOptions.valueSuffix || ''; + // Replace default point style with class name + if (series.chart.styledMode) { + pointFormat = + series.chart.tooltip.styledModeFormat(pointFormat); + } + // Loop over the point array map and replace unformatted values with + // sprintf formatting markup + (series.pointArrayMap || ['y']).forEach(function (key) { + key = '{point.' + key; // without the closing bracket + if (valuePrefix || valueSuffix) { + pointFormat = pointFormat.replace(RegExp(key + '}', 'g'), valuePrefix + key + '}' + valueSuffix); + } + pointFormat = pointFormat.replace(RegExp(key + '}', 'g'), key + ':,.' + valueDecimals + 'f}'); + }); + return format(pointFormat, { + point: this, + series: this.series + }, series.chart); + }; + return Point; +}()); +H.Point = Point; +export default H.Point; diff --git a/librerias/gantt/code/es-modules/parts/Pointer.js b/librerias/gantt/code/es-modules/parts/Pointer.js new file mode 100644 index 0000000..b896f18 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/Pointer.js @@ -0,0 +1,1497 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Highcharts from './Globals.js'; +/** + * One position in relation to an axis. + * + * @interface Highcharts.PointerAxisCoordinateObject + */ /** +* Related axis. +* +* @name Highcharts.PointerAxisCoordinateObject#axis +* @type {Highcharts.Axis} +*/ /** +* Axis value. +* +* @name Highcharts.PointerAxisCoordinateObject#value +* @type {number} +*/ +/** + * Positions in terms of axis values. + * + * @interface Highcharts.PointerAxisCoordinatesObject + */ /** +* Positions on the x-axis. +* @name Highcharts.PointerAxisCoordinatesObject#xAxis +* @type {Array} +*/ /** +* Positions on the y-axis. +* @name Highcharts.PointerAxisCoordinatesObject#yAxis +* @type {Array} +*/ +/** + * Pointer coordinates. + * + * @interface Highcharts.PointerCoordinatesObject + */ /** +* @name Highcharts.PointerCoordinatesObject#chartX +* @type {number} +*/ /** +* @name Highcharts.PointerCoordinatesObject#chartY +* @type {number} +*/ +/** + * A native browser mouse or touch event, extended with position information + * relative to the {@link Chart.container}. + * + * @interface Highcharts.PointerEventObject + * @extends global.PointerEvent + */ /** +* The X coordinate of the pointer interaction relative to the chart. +* +* @name Highcharts.PointerEventObject#chartX +* @type {number} +*/ /** +* The Y coordinate of the pointer interaction relative to the chart. +* +* @name Highcharts.PointerEventObject#chartY +* @type {number} +*/ +/** + * Axis-specific data of a selection. + * + * @interface Highcharts.SelectDataObject + */ /** +* @name Highcharts.SelectDataObject#axis +* @type {Highcharts.Axis} +*/ /** +* @name Highcharts.SelectDataObject#max +* @type {number} +*/ /** +* @name Highcharts.SelectDataObject#min +* @type {number} +*/ +/** + * Object for select events. + * + * @interface Highcharts.SelectEventObject + */ /** +* @name Highcharts.SelectEventObject#originalEvent +* @type {global.Event} +*/ /** +* @name Highcharts.SelectEventObject#xAxis +* @type {Array} +*/ /** +* @name Highcharts.SelectEventObject#yAxis +* @type {Array} +*/ +import U from './Utilities.js'; +var addEvent = U.addEvent, attr = U.attr, css = U.css, defined = U.defined, extend = U.extend, find = U.find, fireEvent = U.fireEvent, isNumber = U.isNumber, isObject = U.isObject, objectEach = U.objectEach, offset = U.offset, pick = U.pick, splat = U.splat; +import Tooltip from './Tooltip.js'; +import Color from './Color.js'; +var color = Color.parse; +var H = Highcharts, charts = H.charts, noop = H.noop; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * The mouse and touch tracker object. Each {@link Chart} item has one + * assosiated Pointer item that can be accessed from the {@link Chart.pointer} + * property. + * + * @class + * @name Highcharts.Pointer + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @param {Highcharts.Options} options + * The root options object. The pointer uses options from the chart and + * tooltip structures. + */ +var Pointer = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Pointer(chart, options) { + this.lastValidTouch = {}; + this.pinchDown = []; + this.runChartClick = false; + this.chart = chart; + this.hasDragged = false; + this.options = options; + this.unbindContainerMouseLeave = function () { }; + this.init(chart, options); + } + /* * + * + * Functions + * + * */ + /** + * Set inactive state to all series that are not currently hovered, + * or, if `inactiveOtherPoints` is set to true, set inactive state to + * all points within that series. + * + * @function Highcharts.Pointer#applyInactiveState + * + * @private + * + * @param {Array} points + * Currently hovered points + * + */ + Pointer.prototype.applyInactiveState = function (points) { + var activeSeries = [], series; + // Get all active series from the hovered points + (points || []).forEach(function (item) { + series = item.series; + // Include itself + activeSeries.push(series); + // Include parent series + if (series.linkedParent) { + activeSeries.push(series.linkedParent); + } + // Include all child series + if (series.linkedSeries) { + activeSeries = activeSeries.concat(series.linkedSeries); + } + // Include navigator series + if (series.navigatorSeries) { + activeSeries.push(series.navigatorSeries); + } + }); + // Now loop over all series, filtering out active series + this.chart.series.forEach(function (inactiveSeries) { + if (activeSeries.indexOf(inactiveSeries) === -1) { + // Inactive series + inactiveSeries.setState('inactive', true); + } + else if (inactiveSeries.options.inactiveOtherPoints) { + // Active series, but other points should be inactivated + inactiveSeries.setAllPointsToState('inactive'); + } + }); + }; + /** + * Destroys the Pointer object and disconnects DOM events. + * + * @function Highcharts.Pointer#destroy + * + * @return {void} + */ + Pointer.prototype.destroy = function () { + var pointer = this; + if (typeof pointer.unDocMouseMove !== 'undefined') { + pointer.unDocMouseMove(); + } + this.unbindContainerMouseLeave(); + if (!H.chartCount) { + if (H.unbindDocumentMouseUp) { + H.unbindDocumentMouseUp = H.unbindDocumentMouseUp(); + } + if (H.unbindDocumentTouchEnd) { + H.unbindDocumentTouchEnd = H.unbindDocumentTouchEnd(); + } + } + // memory and CPU leak + clearInterval(pointer.tooltipTimeout); + objectEach(pointer, function (val, prop) { + pointer[prop] = null; + }); + }; + /** + * Perform a drag operation in response to a mousemove event while the mouse + * is down. + * + * @private + * @function Highcharts.Pointer#drag + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + Pointer.prototype.drag = function (e) { + var chart = this.chart, chartOptions = chart.options.chart, chartX = e.chartX, chartY = e.chartY, zoomHor = this.zoomHor, zoomVert = this.zoomVert, plotLeft = chart.plotLeft, plotTop = chart.plotTop, plotWidth = chart.plotWidth, plotHeight = chart.plotHeight, clickedInside, size, selectionMarker = this.selectionMarker, mouseDownX = (this.mouseDownX || 0), mouseDownY = (this.mouseDownY || 0), panningEnabled = isObject(chartOptions.panning) ? + chartOptions.panning && chartOptions.panning.enabled : + chartOptions.panning, panKey = (chartOptions.panKey && e[chartOptions.panKey + 'Key']); + // If the device supports both touch and mouse (like IE11), and we are + // touch-dragging inside the plot area, don't handle the mouse event. + // #4339. + if (selectionMarker && selectionMarker.touch) { + return; + } + // If the mouse is outside the plot area, adjust to cooordinates + // inside to prevent the selection marker from going outside + if (chartX < plotLeft) { + chartX = plotLeft; + } + else if (chartX > plotLeft + plotWidth) { + chartX = plotLeft + plotWidth; + } + if (chartY < plotTop) { + chartY = plotTop; + } + else if (chartY > plotTop + plotHeight) { + chartY = plotTop + plotHeight; + } + // determine if the mouse has moved more than 10px + this.hasDragged = Math.sqrt(Math.pow(mouseDownX - chartX, 2) + + Math.pow(mouseDownY - chartY, 2)); + if (this.hasDragged > 10) { + clickedInside = chart.isInsidePlot(mouseDownX - plotLeft, mouseDownY - plotTop); + // make a selection + if (chart.hasCartesianSeries && + (this.zoomX || this.zoomY) && + clickedInside && + !panKey) { + if (!selectionMarker) { + this.selectionMarker = selectionMarker = + chart.renderer.rect(plotLeft, plotTop, zoomHor ? 1 : plotWidth, zoomVert ? 1 : plotHeight, 0) + .attr({ + 'class': 'highcharts-selection-marker', + zIndex: 7 + }) + .add(); + if (!chart.styledMode) { + selectionMarker.attr({ + fill: (chartOptions.selectionMarkerFill || + color('#335cad') + .setOpacity(0.25).get()) + }); + } + } + } + // adjust the width of the selection marker + if (selectionMarker && zoomHor) { + size = chartX - mouseDownX; + selectionMarker.attr({ + width: Math.abs(size), + x: (size > 0 ? 0 : size) + mouseDownX + }); + } + // adjust the height of the selection marker + if (selectionMarker && zoomVert) { + size = chartY - mouseDownY; + selectionMarker.attr({ + height: Math.abs(size), + y: (size > 0 ? 0 : size) + mouseDownY + }); + } + // panning + if (clickedInside && + !selectionMarker && + panningEnabled) { + chart.pan(e, chartOptions.panning); + } + } + }; + /** + * Start a drag operation. + * + * @private + * @function Highcharts.Pointer#dragStart + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + Pointer.prototype.dragStart = function (e) { + var chart = this.chart; + // Record the start position + chart.mouseIsDown = e.type; + chart.cancelClick = false; + chart.mouseDownX = this.mouseDownX = e.chartX; + chart.mouseDownY = this.mouseDownY = e.chartY; + }; + /** + * On mouse up or touch end across the entire document, drop the selection. + * + * @private + * @function Highcharts.Pointer#drop + * + * @param {global.Event} e + */ + Pointer.prototype.drop = function (e) { + var pointer = this, chart = this.chart, hasPinched = this.hasPinched; + if (this.selectionMarker) { + var selectionData = { + originalEvent: e, + xAxis: [], + yAxis: [] + }, selectionBox = this.selectionMarker, selectionLeft = selectionBox.attr ? + selectionBox.attr('x') : + selectionBox.x, selectionTop = selectionBox.attr ? + selectionBox.attr('y') : + selectionBox.y, selectionWidth = selectionBox.attr ? + selectionBox.attr('width') : + selectionBox.width, selectionHeight = selectionBox.attr ? + selectionBox.attr('height') : + selectionBox.height, runZoom; + // a selection has been made + if (this.hasDragged || hasPinched) { + // record each axis' min and max + chart.axes.forEach(function (axis) { + if (axis.zoomEnabled && + defined(axis.min) && + (hasPinched || + pointer[{ + xAxis: 'zoomX', + yAxis: 'zoomY' + }[axis.coll]])) { // #859, #3569 + var horiz = axis.horiz, minPixelPadding = e.type === 'touchend' ? + axis.minPixelPadding : + 0, // #1207, #3075 + selectionMin = axis.toValue((horiz ? selectionLeft : selectionTop) + + minPixelPadding), selectionMax = axis.toValue((horiz ? + selectionLeft + selectionWidth : + selectionTop + selectionHeight) - minPixelPadding); + selectionData[axis.coll].push({ + axis: axis, + // Min/max for reversed axes + min: Math.min(selectionMin, selectionMax), + max: Math.max(selectionMin, selectionMax) + }); + runZoom = true; + } + }); + if (runZoom) { + fireEvent(chart, 'selection', selectionData, function (args) { + chart.zoom(extend(args, hasPinched ? + { animation: false } : + null)); + }); + } + } + if (isNumber(chart.index)) { + this.selectionMarker = this.selectionMarker.destroy(); + } + // Reset scaling preview + if (hasPinched) { + this.scaleGroups(); + } + } + // Reset all. Check isNumber because it may be destroyed on mouse up + // (#877) + if (chart && isNumber(chart.index)) { + css(chart.container, { cursor: chart._cursor }); + chart.cancelClick = this.hasDragged > 10; // #370 + chart.mouseIsDown = this.hasDragged = this.hasPinched = false; + this.pinchDown = []; + } + }; + /** + * Finds the closest point to a set of coordinates, using the k-d-tree + * algorithm. + * + * @function Highcharts.Pointer#findNearestKDPoints + * + * @param {Array} series + * All the series to search in. + * + * @param {boolean|undefined} shared + * Whether it is a shared tooltip or not. + * + * @param {Highcharts.PointerEventObject} e + * The pointer event object, containing chart coordinates of the + * pointer. + * + * @return {Highcharts.Point|undefined} + * The point closest to given coordinates. + */ + Pointer.prototype.findNearestKDPoint = function (series, shared, e) { + var chart = this.chart; + var hoverPoint = chart.hoverPoint; + var tooltip = chart.tooltip; + if (hoverPoint && + tooltip && + tooltip.isStickyOnContact()) { + return hoverPoint; + } + var closest; + /** @private */ + function sort(p1, p2) { + var isCloserX = p1.distX - p2.distX, isCloser = p1.dist - p2.dist, isAbove = (p2.series.group && p2.series.group.zIndex) - + (p1.series.group && p1.series.group.zIndex), result; + // We have two points which are not in the same place on xAxis + // and shared tooltip: + if (isCloserX !== 0 && shared) { // #5721 + result = isCloserX; + // Points are not exactly in the same place on x/yAxis: + } + else if (isCloser !== 0) { + result = isCloser; + // The same xAxis and yAxis position, sort by z-index: + } + else if (isAbove !== 0) { + result = isAbove; + // The same zIndex, sort by array index: + } + else { + result = + p1.series.index > p2.series.index ? + -1 : + 1; + } + return result; + } + series.forEach(function (s) { + var noSharedTooltip = s.noSharedTooltip && shared, compareX = (!noSharedTooltip && + s.options.findNearestPointBy.indexOf('y') < 0), point = s.searchPoint(e, compareX); + if ( // Check that we actually found a point on the series. + isObject(point, true) && + // Use the new point if it is closer. + (!isObject(closest, true) || + (sort(closest, point) > 0))) { + closest = point; + } + }); + return closest; + }; + /** + * @private + * @function Highcharts.Pointer#getChartCoordinatesFromPoint + * @param {Highcharts.Point} point + * @param {boolean} [inverted] + * @return {Highcharts.PointerCoordinatesObject|undefined} + */ + Pointer.prototype.getChartCoordinatesFromPoint = function (point, inverted) { + var series = point.series, xAxis = series.xAxis, yAxis = series.yAxis, plotX = pick(point.clientX, point.plotX), shapeArgs = point.shapeArgs; + if (xAxis && yAxis) { + return inverted ? { + chartX: xAxis.len + xAxis.pos - plotX, + chartY: yAxis.len + yAxis.pos - point.plotY + } : { + chartX: plotX + xAxis.pos, + chartY: point.plotY + yAxis.pos + }; + } + if (shapeArgs && shapeArgs.x && shapeArgs.y) { + // E.g. pies do not have axes + return { + chartX: shapeArgs.x, + chartY: shapeArgs.y + }; + } + }; + /** + * Return the cached chartPosition if it is available on the Pointer, + * otherwise find it. Running offset is quite expensive, so it should be + * avoided when we know the chart hasn't moved. + * + * @function Highcharts.Pointer#getChartPosition + * + * @return {Highcharts.OffsetObject} + * The offset of the chart container within the page + */ + Pointer.prototype.getChartPosition = function () { + return (this.chartPosition || + (this.chartPosition = offset(this.chart.container))); + }; + /** + * Get the click position in terms of axis values. + * + * @function Highcharts.Pointer#getCoordinates + * + * @param {Highcharts.PointerEventObject} e + * Pointer event, extended with `chartX` and `chartY` properties. + * + * @return {Highcharts.PointerAxisCoordinatesObject} + */ + Pointer.prototype.getCoordinates = function (e) { + var coordinates = { + xAxis: [], + yAxis: [] + }; + this.chart.axes.forEach(function (axis) { + coordinates[axis.isXAxis ? 'xAxis' : 'yAxis'].push({ + axis: axis, + value: axis.toValue(e[axis.horiz ? 'chartX' : 'chartY']) + }); + }); + return coordinates; + }; + /** + * Calculates what is the current hovered point/points and series. + * + * @private + * @function Highcharts.Pointer#getHoverData + * + * @param {Highcharts.Point|undefined} existingHoverPoint + * The point currrently beeing hovered. + * + * @param {Highcharts.Series|undefined} existingHoverSeries + * The series currently beeing hovered. + * + * @param {Array} series + * All the series in the chart. + * + * @param {boolean} isDirectTouch + * Is the pointer directly hovering the point. + * + * @param {boolean|undefined} shared + * Whether it is a shared tooltip or not. + * + * @param {Highcharts.PointerEventObject} [e] + * The triggering event, containing chart coordinates of the pointer. + * + * @return {object} + * Object containing resulting hover data: hoverPoint, hoverSeries, + * and hoverPoints. + */ + Pointer.prototype.getHoverData = function (existingHoverPoint, existingHoverSeries, series, isDirectTouch, shared, e) { + var hoverPoint, hoverPoints = [], hoverSeries = existingHoverSeries, useExisting = !!(isDirectTouch && existingHoverPoint), notSticky = hoverSeries && !hoverSeries.stickyTracking, + // Which series to look in for the hover point + searchSeries, + // Parameters needed for beforeGetHoverData event. + eventArgs = { + chartX: e ? e.chartX : void 0, + chartY: e ? e.chartY : void 0, + shared: shared + }, filter = function (s) { + return (s.visible && + !(!shared && s.directTouch) && // #3821 + pick(s.options.enableMouseTracking, true)); + }; + // Find chart.hoverPane and update filter method in polar. + fireEvent(this, 'beforeGetHoverData', eventArgs); + searchSeries = notSticky ? + // Only search on hovered series if it has stickyTracking false + [hoverSeries] : + // Filter what series to look in. + series.filter(function (s) { + return eventArgs.filter ? eventArgs.filter(s) : filter(s) && + s.stickyTracking; + }); + // Use existing hovered point or find the one closest to coordinates. + hoverPoint = useExisting || !e ? + existingHoverPoint : + this.findNearestKDPoint(searchSeries, shared, e); + // Assign hover series + hoverSeries = hoverPoint && hoverPoint.series; + // If we have a hoverPoint, assign hoverPoints. + if (hoverPoint) { + // When tooltip is shared, it displays more than one point + if (shared && !hoverSeries.noSharedTooltip) { + searchSeries = series.filter(function (s) { + return eventArgs.filter ? + eventArgs.filter(s) : filter(s) && !s.noSharedTooltip; + }); + // Get all points with the same x value as the hoverPoint + searchSeries.forEach(function (s) { + var point = find(s.points, function (p) { + return p.x === hoverPoint.x && !p.isNull; + }); + if (isObject(point)) { + /* + * Boost returns a minimal point. Convert it to a usable + * point for tooltip and states. + */ + if (s.chart.isBoosting) { + point = s.getPoint(point); + } + hoverPoints.push(point); + } + }); + } + else { + hoverPoints.push(hoverPoint); + } + } + // Check whether the hoverPoint is inside pane we are hovering over. + eventArgs = { hoverPoint: hoverPoint }; + fireEvent(this, 'afterGetHoverData', eventArgs); + return { + hoverPoint: eventArgs.hoverPoint, + hoverSeries: hoverSeries, + hoverPoints: hoverPoints + }; + }; + /** + * @private + * @function Highcharts.Pointer#getPointFromEvent + * + * @param {global.Event} e + * + * @return {Highcharts.Point|undefined} + */ + Pointer.prototype.getPointFromEvent = function (e) { + var target = e.target, point; + while (target && !point) { + point = target.point; + target = target.parentNode; + } + return point; + }; + /** + * @private + * @function Highcharts.Pointer#onTrackerMouseOut + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + Pointer.prototype.onTrackerMouseOut = function (e) { + var chart = this.chart; + var relatedTarget = e.relatedTarget || e.toElement; + var series = chart.hoverSeries; + this.isDirectTouch = false; + if (series && + relatedTarget && + !series.stickyTracking && + !this.inClass(relatedTarget, 'highcharts-tooltip') && + (!this.inClass(relatedTarget, 'highcharts-series-' + series.index) || // #2499, #4465, #5553 + !this.inClass(relatedTarget, 'highcharts-tracker'))) { + series.onMouseOut(); + } + }; + /** + * Utility to detect whether an element has, or has a parent with, a + * specificclass name. Used on detection of tracker objects and on deciding + * whether hovering the tooltip should cause the active series to mouse out. + * + * @function Highcharts.Pointer#inClass + * + * @param {Highcharts.SVGDOMElement|Highcharts.HTMLDOMElement} element + * The element to investigate. + * + * @param {string} className + * The class name to look for. + * + * @return {boolean|undefined} + * True if either the element or one of its parents has the given + * class name. + */ + Pointer.prototype.inClass = function (element, className) { + var elemClassName; + while (element) { + elemClassName = attr(element, 'class'); + if (elemClassName) { + if (elemClassName.indexOf(className) !== -1) { + return true; + } + if (elemClassName.indexOf('highcharts-container') !== -1) { + return false; + } + } + element = element.parentNode; + } + }; + /** + * Initialize the Pointer. + * + * @private + * @function Highcharts.Pointer#init + * + * @param {Highcharts.Chart} chart + * The Chart instance. + * + * @param {Highcharts.Options} options + * The root options object. The pointer uses options from the chart + * and tooltip structures. + * + * @return {void} + */ + Pointer.prototype.init = function (chart, options) { + // Store references + this.options = options; + this.chart = chart; + // Do we need to handle click on a touch device? + this.runChartClick = + options.chart.events && + !!options.chart.events.click; + this.pinchDown = []; + this.lastValidTouch = {}; + if (Tooltip) { + /** + * Tooltip object for points of series. + * + * @name Highcharts.Chart#tooltip + * @type {Highcharts.Tooltip} + */ + chart.tooltip = new Tooltip(chart, options.tooltip); + this.followTouchMove = pick(options.tooltip.followTouchMove, true); + } + this.setDOMEvents(); + }; + /** + * Takes a browser event object and extends it with custom Highcharts + * properties `chartX` and `chartY` in order to work on the internal + * coordinate system. + * + * @function Highcharts.Pointer#normalize + * + * @param {global.MouseEvent|global.PointerEvent|global.TouchEvent} e + * Event object in standard browsers. + * + * @param {Highcharts.OffsetObject} [chartPosition] + * Additional chart offset. + * + * @return {Highcharts.PointerEventObject} + * A browser event with extended properties `chartX` and `chartY`. + */ + Pointer.prototype.normalize = function (e, chartPosition) { + var touches = e.touches; + // iOS (#2757) + var ePos = (touches ? + touches.length ? + touches.item(0) : + touches.changedTouches[0] : + e); + // Get mouse position + if (!chartPosition) { + chartPosition = this.getChartPosition(); + } + var chartX = ePos.pageX - chartPosition.left, chartY = ePos.pageY - chartPosition.top; + // #11329 - when there is scaling on a parent element, we need to take + // this into account + var containerScaling = this.chart.containerScaling; + if (containerScaling) { + chartX /= containerScaling.scaleX; + chartY /= containerScaling.scaleY; + } + return extend(e, { + chartX: Math.round(chartX), + chartY: Math.round(chartY) + }); + }; + /** + * @private + * @function Highcharts.Pointer#onContainerClick + * + * @param {global.MouseEvent} e + * + * @return {void} + */ + Pointer.prototype.onContainerClick = function (e) { + var chart = this.chart; + var hoverPoint = chart.hoverPoint; + var pEvt = this.normalize(e); + var plotLeft = chart.plotLeft; + var plotTop = chart.plotTop; + if (!chart.cancelClick) { + // On tracker click, fire the series and point events. #783, #1583 + if (hoverPoint && + this.inClass(pEvt.target, 'highcharts-tracker')) { + // the series click event + fireEvent(hoverPoint.series, 'click', extend(pEvt, { + point: hoverPoint + })); + // the point click event + if (chart.hoverPoint) { // it may be destroyed (#1844) + hoverPoint.firePointEvent('click', pEvt); + } + // When clicking outside a tracker, fire a chart event + } + else { + extend(pEvt, this.getCoordinates(pEvt)); + // fire a click event in the chart + if (chart.isInsidePlot((pEvt.chartX - plotLeft), (pEvt.chartY - plotTop))) { + fireEvent(chart, 'click', pEvt); + } + } + } + }; + /** + * @private + * @function Highcharts.Pointer#onContainerMouseDown + * + * @param {global.MouseEvent} e + */ + Pointer.prototype.onContainerMouseDown = function (e) { + // Normalize before the 'if' for the legacy IE (#7850) + e = this.normalize(e); + // #11635, Firefox does not reliable fire move event after click scroll + if (H.isFirefox && + e.button !== 0) { + this.onContainerMouseMove(e); + } + // #11635, limiting to primary button (incl. IE 8 support) + if (typeof e.button === 'undefined' || + ((e.buttons || e.button) & 1) === 1) { + this.zoomOption(e); + this.dragStart(e); + } + }; + /** + * When mouse leaves the container, hide the tooltip. + * + * @private + * @function Highcharts.Pointer#onContainerMouseLeave + * + * @param {global.MouseEvent} e + * + * @return {void} + */ + Pointer.prototype.onContainerMouseLeave = function (e) { + var chart = charts[pick(H.hoverChartIndex, -1)]; + var tooltip = this.chart.tooltip; + e = this.normalize(e); + // #4886, MS Touch end fires mouseleave but with no related target + if (chart && + (e.relatedTarget || e.toElement)) { + chart.pointer.reset(); + // Also reset the chart position, used in #149 fix + chart.pointer.chartPosition = void 0; + } + if ( // #11635, Firefox wheel scroll does not fire out events consistently + tooltip && + !tooltip.isHidden) { + this.reset(); + } + }; + /** + * The mousemove, touchmove and touchstart event handler + * + * @private + * @function Highcharts.Pointer#onContainerMouseMove + * + * @param {global.MouseEvent} e + * + * @return {void} + */ + Pointer.prototype.onContainerMouseMove = function (e) { + var chart = this.chart; + var pEvt = this.normalize(e); + this.setHoverChartIndex(); + // In IE8 we apparently need this returnValue set to false in order to + // avoid text being selected. But in Chrome, e.returnValue is prevented, + // plus we don't need to run e.preventDefault to prevent selected text + // in modern browsers. So we set it conditionally. Remove it when IE8 is + // no longer needed. #2251, #3224. + if (!pEvt.preventDefault) { + pEvt.returnValue = false; + } + if (chart.mouseIsDown === 'mousedown') { + this.drag(pEvt); + } + // Show the tooltip and run mouse over events (#977) + if (!chart.openMenu && + (this.inClass(pEvt.target, 'highcharts-tracker') || + chart.isInsidePlot((pEvt.chartX - chart.plotLeft), (pEvt.chartY - chart.plotTop)))) { + this.runPointActions(pEvt); + } + }; + /** + * @private + * @function Highcharts.Pointer#onDocumentTouchEnd + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + Pointer.prototype.onDocumentTouchEnd = function (e) { + if (charts[H.hoverChartIndex]) { + charts[H.hoverChartIndex].pointer.drop(e); + } + }; + /** + * @private + * @function Highcharts.Pointer#onContainerTouchMove + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + Pointer.prototype.onContainerTouchMove = function (e) { + this.touch(e); + }; + /** + * @private + * @function Highcharts.Pointer#onContainerTouchStart + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + Pointer.prototype.onContainerTouchStart = function (e) { + this.zoomOption(e); + this.touch(e, true); + }; + /** + * Special handler for mouse move that will hide the tooltip when the mouse + * leaves the plotarea. Issue #149 workaround. The mouseleave event does not + * always fire. + * + * @private + * @function Highcharts.Pointer#onDocumentMouseMove + * + * @param {global.MouseEvent} e + * + * @return {void} + */ + Pointer.prototype.onDocumentMouseMove = function (e) { + var chart = this.chart; + var chartPosition = this.chartPosition; + var pEvt = this.normalize(e, chartPosition); + var tooltip = chart.tooltip; + // If we're outside, hide the tooltip + if (chartPosition && + (!tooltip || + !tooltip.isStickyOnContact()) && + !chart.isInsidePlot(pEvt.chartX - chart.plotLeft, pEvt.chartY - chart.plotTop) && + !this.inClass(pEvt.target, 'highcharts-tracker')) { + this.reset(); + } + }; + /** + * @private + * @function Highcharts.Pointer#onDocumentMouseUp + * + * @param {global.MouseEvent} e + * + * @return {void} + */ + Pointer.prototype.onDocumentMouseUp = function (e) { + var chart = charts[pick(H.hoverChartIndex, -1)]; + if (chart) { + chart.pointer.drop(e); + } + }; + /** + * Handle touch events with two touches + * + * @private + * @function Highcharts.Pointer#pinch + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + Pointer.prototype.pinch = function (e) { + var self = this, chart = self.chart, pinchDown = self.pinchDown, touches = (e.touches || []), touchesLength = touches.length, lastValidTouch = self.lastValidTouch, hasZoom = self.hasZoom, selectionMarker = self.selectionMarker, transform = {}, fireClickEvent = touchesLength === 1 && ((self.inClass(e.target, 'highcharts-tracker') && + chart.runTrackerClick) || + self.runChartClick), clip = {}; + // Don't initiate panning until the user has pinched. This prevents us + // from blocking page scrolling as users scroll down a long page + // (#4210). + if (touchesLength > 1) { + self.initiated = true; + } + // On touch devices, only proceed to trigger click if a handler is + // defined + if (hasZoom && self.initiated && !fireClickEvent) { + e.preventDefault(); + } + // Normalize each touch + [].map.call(touches, function (e) { + return self.normalize(e); + }); + // Register the touch start position + if (e.type === 'touchstart') { + [].forEach.call(touches, function (e, i) { + pinchDown[i] = { chartX: e.chartX, chartY: e.chartY }; + }); + lastValidTouch.x = [pinchDown[0].chartX, pinchDown[1] && + pinchDown[1].chartX]; + lastValidTouch.y = [pinchDown[0].chartY, pinchDown[1] && + pinchDown[1].chartY]; + // Identify the data bounds in pixels + chart.axes.forEach(function (axis) { + if (axis.zoomEnabled) { + var bounds = chart.bounds[axis.horiz ? 'h' : 'v'], minPixelPadding = axis.minPixelPadding, min = axis.toPixels(Math.min(pick(axis.options.min, axis.dataMin), axis.dataMin)), max = axis.toPixels(Math.max(pick(axis.options.max, axis.dataMax), axis.dataMax)), absMin = Math.min(min, max), absMax = Math.max(min, max); + // Store the bounds for use in the touchmove handler + bounds.min = Math.min(axis.pos, absMin - minPixelPadding); + bounds.max = Math.max(axis.pos + axis.len, absMax + minPixelPadding); + } + }); + self.res = true; // reset on next move + // Optionally move the tooltip on touchmove + } + else if (self.followTouchMove && touchesLength === 1) { + this.runPointActions(self.normalize(e)); + // Event type is touchmove, handle panning and pinching + } + else if (pinchDown.length) { // can be 0 when releasing, if touchend + // fires first + // Set the marker + if (!selectionMarker) { + self.selectionMarker = selectionMarker = extend({ + destroy: noop, + touch: true + }, chart.plotBox); + } + self.pinchTranslate(pinchDown, touches, transform, selectionMarker, clip, lastValidTouch); + self.hasPinched = hasZoom; + // Scale and translate the groups to provide visual feedback during + // pinching + self.scaleGroups(transform, clip); + if (self.res) { + self.res = false; + this.reset(false, 0); + } + } + }; + /** + * Run translation operations + * + * @private + * @function Highcharts.Pointer#pinchTranslate + * + * @param {Array<*>} pinchDown + * + * @param {Array} touches + * + * @param {*} transform + * + * @param {*} selectionMarker + * + * @param {*} clip + * + * @param {*} lastValidTouch + * + * @return {void} + */ + Pointer.prototype.pinchTranslate = function (pinchDown, touches, transform, selectionMarker, clip, lastValidTouch) { + if (this.zoomHor) { + this.pinchTranslateDirection(true, pinchDown, touches, transform, selectionMarker, clip, lastValidTouch); + } + if (this.zoomVert) { + this.pinchTranslateDirection(false, pinchDown, touches, transform, selectionMarker, clip, lastValidTouch); + } + }; + /** + * Run translation operations for each direction (horizontal and vertical) + * independently. + * + * @private + * @function Highcharts.Pointer#pinchTranslateDirection + * + * @param {boolean} horiz + * + * @param {Array<*>} pinchDown + * + * @param {Array} touches + * + * @param {*} transform + * + * @param {*} selectionMarker + * + * @param {*} clip + * + * @param {*} lastValidTouch + * + * @param {number|undefined} [forcedScale=1] + * + * @return {void} + */ + Pointer.prototype.pinchTranslateDirection = function (horiz, pinchDown, touches, transform, selectionMarker, clip, lastValidTouch, forcedScale) { + var chart = this.chart, xy = horiz ? 'x' : 'y', XY = horiz ? 'X' : 'Y', sChartXY = ('chart' + XY), wh = horiz ? 'width' : 'height', plotLeftTop = chart['plot' + (horiz ? 'Left' : 'Top')], selectionWH, selectionXY, clipXY, scale = forcedScale || 1, inverted = chart.inverted, bounds = chart.bounds[horiz ? 'h' : 'v'], singleTouch = pinchDown.length === 1, touch0Start = pinchDown[0][sChartXY], touch0Now = touches[0][sChartXY], touch1Start = !singleTouch && pinchDown[1][sChartXY], touch1Now = !singleTouch && touches[1][sChartXY], outOfBounds, transformScale, scaleKey, setScale = function () { + // Don't zoom if fingers are too close on this axis + if (typeof touch1Now === 'number' && + Math.abs(touch0Start - touch1Start) > 20) { + scale = forcedScale || + Math.abs(touch0Now - touch1Now) / + Math.abs(touch0Start - touch1Start); + } + clipXY = ((plotLeftTop - touch0Now) / scale) + touch0Start; + selectionWH = chart['plot' + (horiz ? 'Width' : 'Height')] / scale; + }; + // Set the scale, first pass + setScale(); + // The clip position (x or y) is altered if out of bounds, the selection + // position is not + selectionXY = clipXY; + // Out of bounds + if (selectionXY < bounds.min) { + selectionXY = bounds.min; + outOfBounds = true; + } + else if (selectionXY + selectionWH > bounds.max) { + selectionXY = bounds.max - selectionWH; + outOfBounds = true; + } + // Is the chart dragged off its bounds, determined by dataMin and + // dataMax? + if (outOfBounds) { + // Modify the touchNow position in order to create an elastic drag + // movement. This indicates to the user that the chart is responsive + // but can't be dragged further. + touch0Now -= 0.8 * (touch0Now - lastValidTouch[xy][0]); + if (typeof touch1Now === 'number') { + touch1Now -= 0.8 * (touch1Now - lastValidTouch[xy][1]); + } + // Set the scale, second pass to adapt to the modified touchNow + // positions + setScale(); + } + else { + lastValidTouch[xy] = [touch0Now, touch1Now]; + } + // Set geometry for clipping, selection and transformation + if (!inverted) { + clip[xy] = clipXY - plotLeftTop; + clip[wh] = selectionWH; + } + scaleKey = inverted ? (horiz ? 'scaleY' : 'scaleX') : 'scale' + XY; + transformScale = inverted ? 1 / scale : scale; + selectionMarker[wh] = selectionWH; + selectionMarker[xy] = selectionXY; + transform[scaleKey] = scale; + transform['translate' + XY] = (transformScale * plotLeftTop) + + (touch0Now - (transformScale * touch0Start)); + }; + /** + * Reset the tracking by hiding the tooltip, the hover series state and the + * hover point + * + * @function Highcharts.Pointer#reset + * + * @param {boolean} [allowMove] + * Instead of destroying the tooltip altogether, allow moving it if + * possible. + * + * @param {number} [delay] + * + * @return {void} + */ + Pointer.prototype.reset = function (allowMove, delay) { + var pointer = this, chart = pointer.chart, hoverSeries = chart.hoverSeries, hoverPoint = chart.hoverPoint, hoverPoints = chart.hoverPoints, tooltip = chart.tooltip, tooltipPoints = tooltip && tooltip.shared ? + hoverPoints : + hoverPoint; + // Check if the points have moved outside the plot area (#1003, #4736, + // #5101) + if (allowMove && tooltipPoints) { + splat(tooltipPoints).forEach(function (point) { + if (point.series.isCartesian && + typeof point.plotX === 'undefined') { + allowMove = false; + } + }); + } + // Just move the tooltip, #349 + if (allowMove) { + if (tooltip && tooltipPoints && splat(tooltipPoints).length) { + tooltip.refresh(tooltipPoints); + if (tooltip.shared && hoverPoints) { // #8284 + hoverPoints.forEach(function (point) { + point.setState(point.state, true); + if (point.series.isCartesian) { + if (point.series.xAxis.crosshair) { + point.series.xAxis + .drawCrosshair(null, point); + } + if (point.series.yAxis.crosshair) { + point.series.yAxis + .drawCrosshair(null, point); + } + } + }); + } + else if (hoverPoint) { // #2500 + hoverPoint.setState(hoverPoint.state, true); + chart.axes.forEach(function (axis) { + if (axis.crosshair && + hoverPoint.series[axis.coll] === axis) { + axis.drawCrosshair(null, hoverPoint); + } + }); + } + } + // Full reset + } + else { + if (hoverPoint) { + hoverPoint.onMouseOut(); + } + if (hoverPoints) { + hoverPoints.forEach(function (point) { + point.setState(); + }); + } + if (hoverSeries) { + hoverSeries.onMouseOut(); + } + if (tooltip) { + tooltip.hide(delay); + } + if (pointer.unDocMouseMove) { + pointer.unDocMouseMove = pointer.unDocMouseMove(); + } + // Remove crosshairs + chart.axes.forEach(function (axis) { + axis.hideCrosshair(); + }); + pointer.hoverX = chart.hoverPoints = chart.hoverPoint = null; + } + }; + /** + * With line type charts with a single tracker, get the point closest to the + * mouse. Run Point.onMouseOver and display tooltip for the point or points. + * + * @private + * @function Highcharts.Pointer#runPointActions + * + * @param {global.Event} e + * + * @param {Highcharts.PointerEventObject} [p] + * + * @return {void} + * + * @fires Highcharts.Point#event:mouseOut + * @fires Highcharts.Point#event:mouseOver + */ + Pointer.prototype.runPointActions = function (e, p) { + var pointer = this, chart = pointer.chart, series = chart.series, tooltip = (chart.tooltip && chart.tooltip.options.enabled ? + chart.tooltip : + void 0), shared = (tooltip ? + tooltip.shared : + false), hoverPoint = p || chart.hoverPoint, hoverSeries = hoverPoint && hoverPoint.series || chart.hoverSeries, + // onMouseOver or already hovering a series with directTouch + isDirectTouch = (!e || e.type !== 'touchmove') && (!!p || ((hoverSeries && hoverSeries.directTouch) && + pointer.isDirectTouch)), hoverData = this.getHoverData(hoverPoint, hoverSeries, series, isDirectTouch, shared, e), useSharedTooltip, followPointer, anchor, points; + // Update variables from hoverData. + hoverPoint = hoverData.hoverPoint; + points = hoverData.hoverPoints; + hoverSeries = hoverData.hoverSeries; + followPointer = hoverSeries && hoverSeries.tooltipOptions.followPointer; + useSharedTooltip = (shared && + hoverSeries && + !hoverSeries.noSharedTooltip); + // Refresh tooltip for kdpoint if new hover point or tooltip was hidden + // #3926, #4200 + if (hoverPoint && + // !(hoverSeries && hoverSeries.directTouch) && + (hoverPoint !== chart.hoverPoint || (tooltip && tooltip.isHidden))) { + (chart.hoverPoints || []).forEach(function (p) { + if (points.indexOf(p) === -1) { + p.setState(); + } + }); + // Set normal state to previous series + if (chart.hoverSeries !== hoverSeries) { + hoverSeries.onMouseOver(); + } + pointer.applyInactiveState(points); + // Do mouseover on all points (#3919, #3985, #4410, #5622) + (points || []).forEach(function (p) { + p.setState('hover'); + }); + // If tracking is on series in stead of on each point, + // fire mouseOver on hover point. // #4448 + if (chart.hoverPoint) { + chart.hoverPoint.firePointEvent('mouseOut'); + } + // Hover point may have been destroyed in the event handlers (#7127) + if (!hoverPoint.series) { + return; + } + hoverPoint.firePointEvent('mouseOver'); + /** + * Contains all hovered points. + * + * @name Highcharts.Chart#hoverPoints + * @type {Array|null} + */ + chart.hoverPoints = points; + /** + * Contains the original hovered point. + * + * @name Highcharts.Chart#hoverPoint + * @type {Highcharts.Point|null} + */ + chart.hoverPoint = hoverPoint; + // Draw tooltip if necessary + if (tooltip) { + tooltip.refresh(useSharedTooltip ? points : hoverPoint, e); + } + // Update positions (regardless of kdpoint or hoverPoint) + } + else if (followPointer && tooltip && !tooltip.isHidden) { + anchor = tooltip.getAnchor([{}], e); + tooltip.updatePosition({ plotX: anchor[0], plotY: anchor[1] }); + } + // Start the event listener to pick up the tooltip and crosshairs + if (!pointer.unDocMouseMove) { + pointer.unDocMouseMove = addEvent(chart.container.ownerDocument, 'mousemove', function (e) { + var chart = charts[H.hoverChartIndex]; + if (chart) { + chart.pointer.onDocumentMouseMove(e); + } + }); + } + // Issues related to crosshair #4927, #5269 #5066, #5658 + chart.axes.forEach(function drawAxisCrosshair(axis) { + var snap = pick((axis.crosshair || {}).snap, true); + var point; + if (snap) { + point = chart.hoverPoint; // #13002 + if (!point || point.series[axis.coll] !== axis) { + point = find(points, function (p) { + return p.series[axis.coll] === axis; + }); + } + } + // Axis has snapping crosshairs, and one of the hover points belongs + // to axis. Always call drawCrosshair when it is not snap. + if (point || !snap) { + axis.drawCrosshair(e, point); + // Axis has snapping crosshairs, but no hover point belongs to axis + } + else { + axis.hideCrosshair(); + } + }); + }; + /** + * Scale series groups to a certain scale and translation. + * + * @private + * @function Highcharts.Pointer#scaleGroups + * + * @param {Highcharts.SeriesPlotBoxObject} [attribs] + * + * @param {boolean} [clip] + * + * @return {void} + */ + Pointer.prototype.scaleGroups = function (attribs, clip) { + var chart = this.chart, seriesAttribs; + // Scale each series + chart.series.forEach(function (series) { + seriesAttribs = attribs || series.getPlotBox(); // #1701 + if (series.xAxis && series.xAxis.zoomEnabled && series.group) { + series.group.attr(seriesAttribs); + if (series.markerGroup) { + series.markerGroup.attr(seriesAttribs); + series.markerGroup.clip(clip ? chart.clipRect : null); + } + if (series.dataLabelsGroup) { + series.dataLabelsGroup.attr(seriesAttribs); + } + } + }); + // Clip + chart.clipRect.attr(clip || chart.clipBox); + }; + /** + * Set the JS DOM events on the container and document. This method should + * contain a one-to-one assignment between methods and their handlers. Any + * advanced logic should be moved to the handler reflecting the event's + * name. + * + * @private + * @function Highcharts.Pointer#setDOMEvents + * + * @return {void} + */ + Pointer.prototype.setDOMEvents = function () { + var container = this.chart.container, ownerDoc = container.ownerDocument; + container.onmousedown = this.onContainerMouseDown.bind(this); + container.onmousemove = this.onContainerMouseMove.bind(this); + container.onclick = this.onContainerClick.bind(this); + this.unbindContainerMouseLeave = addEvent(container, 'mouseleave', this.onContainerMouseLeave.bind(this)); + if (!H.unbindDocumentMouseUp) { + H.unbindDocumentMouseUp = addEvent(ownerDoc, 'mouseup', this.onDocumentMouseUp.bind(this)); + } + if (H.hasTouch) { + addEvent(container, 'touchstart', this.onContainerTouchStart.bind(this)); + addEvent(container, 'touchmove', this.onContainerTouchMove.bind(this)); + if (!H.unbindDocumentTouchEnd) { + H.unbindDocumentTouchEnd = addEvent(ownerDoc, 'touchend', this.onDocumentTouchEnd.bind(this)); + } + } + }; + /** + * Sets the index of the hovered chart and leaves the previous hovered + * chart, to reset states like tooltip. + * + * @private + * @function Highcharts.Pointer#setHoverChartIndex + */ + Pointer.prototype.setHoverChartIndex = function () { + var chart = this.chart; + var hoverChart = H.charts[pick(H.hoverChartIndex, -1)]; + if (hoverChart && + hoverChart !== chart) { + hoverChart.pointer.onContainerMouseLeave({ relatedTarget: true }); + } + if (!hoverChart || + !hoverChart.mouseIsDown) { + H.hoverChartIndex = chart.index; + } + }; + /** + * General touch handler shared by touchstart and touchmove. + * + * @private + * @function Highcharts.Pointer#touch + * + * @param {Highcharts.PointerEventObject} e + * + * @param {boolean} [start] + * + * @return {void} + */ + Pointer.prototype.touch = function (e, start) { + var chart = this.chart, hasMoved, pinchDown, isInside; + this.setHoverChartIndex(); + if (e.touches.length === 1) { + e = this.normalize(e); + isInside = chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop); + if (isInside && !chart.openMenu) { + // Run mouse events and display tooltip etc + if (start) { + this.runPointActions(e); + } + // Android fires touchmove events after the touchstart even if + // the finger hasn't moved, or moved only a pixel or two. In iOS + // however, the touchmove doesn't fire unless the finger moves + // more than ~4px. So we emulate this behaviour in Android by + // checking how much it moved, and cancelling on small + // distances. #3450. + if (e.type === 'touchmove') { + pinchDown = this.pinchDown; + hasMoved = pinchDown[0] ? Math.sqrt(// #5266 + Math.pow(pinchDown[0].chartX - e.chartX, 2) + + Math.pow(pinchDown[0].chartY - e.chartY, 2)) >= 4 : false; + } + if (pick(hasMoved, true)) { + this.pinch(e); + } + } + else if (start) { + // Hide the tooltip on touching outside the plot area (#1203) + this.reset(); + } + } + else if (e.touches.length === 2) { + this.pinch(e); + } + }; + /** + * Resolve the zoomType option, this is reset on all touch start and mouse + * down events. + * + * @private + * @function Highcharts.Pointer#zoomOption + * + * @param {global.Event} e + * Event object. + * + * @param {void} + */ + Pointer.prototype.zoomOption = function (e) { + var chart = this.chart, options = chart.options.chart, zoomType = options.zoomType || '', inverted = chart.inverted, zoomX, zoomY; + // Look for the pinchType option + if (/touch/.test(e.type)) { + zoomType = pick(options.pinchType, zoomType); + } + this.zoomX = zoomX = /x/.test(zoomType); + this.zoomY = zoomY = /y/.test(zoomType); + this.zoomHor = (zoomX && !inverted) || (zoomY && inverted); + this.zoomVert = (zoomY && !inverted) || (zoomX && inverted); + this.hasZoom = zoomX || zoomY; + }; + return Pointer; +}()); +H.Pointer = Pointer; +export default H.Pointer; diff --git a/librerias/gantt/code/es-modules/parts/RangeSelector.js b/librerias/gantt/code/es-modules/parts/RangeSelector.js new file mode 100644 index 0000000..f87f4b8 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/RangeSelector.js @@ -0,0 +1,1597 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +/** + * Define the time span for the button + * + * @typedef {"all"|"day"|"hour"|"millisecond"|"minute"|"month"|"second"|"week"|"year"|"ytd"} Highcharts.RangeSelectorButtonTypeValue + */ +/** + * Callback function to react on button clicks. + * + * @callback Highcharts.RangeSelectorClickCallbackFunction + * + * @param {global.Event} e + * Event arguments. + * + * @param {boolean|undefined} + * Return false to cancel the default button event. + */ +/** + * Callback function to parse values entered in the input boxes and return a + * valid JavaScript time as milliseconds since 1970. + * + * @callback Highcharts.RangeSelectorParseCallbackFunction + * + * @param {string} value + * Input value to parse. + * + * @return {number} + * Parsed JavaScript time value. + */ +import U from './Utilities.js'; +var addEvent = U.addEvent, createElement = U.createElement, css = U.css, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, discardElement = U.discardElement, extend = U.extend, fireEvent = U.fireEvent, isNumber = U.isNumber, merge = U.merge, objectEach = U.objectEach, pick = U.pick, pInt = U.pInt, splat = U.splat; +import './Axis.js'; +import './Chart.js'; +var Axis = H.Axis, Chart = H.Chart, defaultOptions = H.defaultOptions; +/* ************************************************************************** * + * Start Range Selector code * + * ************************************************************************** */ +extend(defaultOptions, { + /** + * The range selector is a tool for selecting ranges to display within + * the chart. It provides buttons to select preconfigured ranges in + * the chart, like 1 day, 1 week, 1 month etc. It also provides input + * boxes where min and max dates can be manually input. + * + * @product highstock gantt + * @optionparent rangeSelector + */ + rangeSelector: { + /** + * Whether to enable all buttons from the start. By default buttons are + * only enabled if the corresponding time range exists on the X axis, + * but enabling all buttons allows for dynamically loading different + * time ranges. + * + * @sample {highstock} stock/rangeselector/allbuttonsenabled-true/ + * All buttons enabled + * + * @type {boolean} + * @default false + * @since 2.0.3 + * @apioption rangeSelector.allButtonsEnabled + */ + /** + * An array of configuration objects for the buttons. + * + * Defaults to: + * ```js + * buttons: [{ + * type: 'month', + * count: 1, + * text: '1m' + * }, { + * type: 'month', + * count: 3, + * text: '3m' + * }, { + * type: 'month', + * count: 6, + * text: '6m' + * }, { + * type: 'ytd', + * text: 'YTD' + * }, { + * type: 'year', + * count: 1, + * text: '1y' + * }, { + * type: 'all', + * text: 'All' + * }] + * ``` + * + * @sample {highstock} stock/rangeselector/datagrouping/ + * Data grouping by buttons + * + * @type {Array<*>} + * @apioption rangeSelector.buttons + */ + /** + * How many units of the defined type the button should span. If `type` + * is "month" and `count` is 3, the button spans three months. + * + * @type {number} + * @default 1 + * @apioption rangeSelector.buttons.count + */ + /** + * Fires when clicking on the rangeSelector button. One parameter, + * event, is passed to the function, containing common event + * information. + * + * ```js + * click: function(e) { + * console.log(this); + * } + * ``` + * + * Return false to stop default button's click action. + * + * @sample {highstock} stock/rangeselector/button-click/ + * Click event on the button + * + * @type {Highcharts.RangeSelectorClickCallbackFunction} + * @apioption rangeSelector.buttons.events.click + */ + /** + * Additional range (in milliseconds) added to the end of the calculated + * time span. + * + * @sample {highstock} stock/rangeselector/min-max-offsets/ + * Button offsets + * + * @type {number} + * @default 0 + * @since 6.0.0 + * @apioption rangeSelector.buttons.offsetMax + */ + /** + * Additional range (in milliseconds) added to the start of the + * calculated time span. + * + * @sample {highstock} stock/rangeselector/min-max-offsets/ + * Button offsets + * + * @type {number} + * @default 0 + * @since 6.0.0 + * @apioption rangeSelector.buttons.offsetMin + */ + /** + * When buttons apply dataGrouping on a series, by default zooming + * in/out will deselect buttons and unset dataGrouping. Enable this + * option to keep buttons selected when extremes change. + * + * @sample {highstock} stock/rangeselector/preserve-datagrouping/ + * Different preserveDataGrouping settings + * + * @type {boolean} + * @default false + * @since 6.1.2 + * @apioption rangeSelector.buttons.preserveDataGrouping + */ + /** + * A custom data grouping object for each button. + * + * @see [series.dataGrouping](#plotOptions.series.dataGrouping) + * + * @sample {highstock} stock/rangeselector/datagrouping/ + * Data grouping by range selector buttons + * + * @type {*} + * @extends plotOptions.series.dataGrouping + * @apioption rangeSelector.buttons.dataGrouping + */ + /** + * The text for the button itself. + * + * @type {string} + * @apioption rangeSelector.buttons.text + */ + /** + * Defined the time span for the button. Can be one of `millisecond`, + * `second`, `minute`, `hour`, `day`, `week`, `month`, `year`, `ytd`, + * and `all`. + * + * @type {Highcharts.RangeSelectorButtonTypeValue} + * @apioption rangeSelector.buttons.type + */ + /** + * The space in pixels between the buttons in the range selector. + * + * @type {number} + * @default 0 + * @apioption rangeSelector.buttonSpacing + */ + /** + * Enable or disable the range selector. + * + * @sample {highstock} stock/rangeselector/enabled/ + * Disable the range selector + * + * @type {boolean} + * @default true + * @apioption rangeSelector.enabled + */ + /** + * The vertical alignment of the rangeselector box. Allowed properties + * are `top`, `middle`, `bottom`. + * + * @sample {highstock} stock/rangeselector/vertical-align-middle/ + * Middle + * @sample {highstock} stock/rangeselector/vertical-align-bottom/ + * Bottom + * + * @type {Highcharts.VerticalAlignValue} + * @since 6.0.0 + */ + verticalAlign: 'top', + /** + * A collection of attributes for the buttons. The object takes SVG + * attributes like `fill`, `stroke`, `stroke-width`, as well as `style`, + * a collection of CSS properties for the text. + * + * The object can also be extended with states, so you can set + * presentational options for `hover`, `select` or `disabled` button + * states. + * + * CSS styles for the text label. + * + * In styled mode, the buttons are styled by the + * `.highcharts-range-selector-buttons .highcharts-button` rule with its + * different states. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {Highcharts.SVGAttributes} + */ + buttonTheme: { + /** @ignore */ + width: 28, + /** @ignore */ + height: 18, + /** @ignore */ + padding: 2, + /** @ignore */ + zIndex: 7 // #484, #852 + }, + /** + * When the rangeselector is floating, the plot area does not reserve + * space for it. This opens for positioning anywhere on the chart. + * + * @sample {highstock} stock/rangeselector/floating/ + * Placing the range selector between the plot area and the + * navigator + * + * @since 6.0.0 + */ + floating: false, + /** + * The x offset of the range selector relative to its horizontal + * alignment within `chart.spacingLeft` and `chart.spacingRight`. + * + * @since 6.0.0 + */ + x: 0, + /** + * The y offset of the range selector relative to its horizontal + * alignment within `chart.spacingLeft` and `chart.spacingRight`. + * + * @since 6.0.0 + */ + y: 0, + /** + * Deprecated. The height of the range selector. Currently it is + * calculated dynamically. + * + * @deprecated + * @type {number|undefined} + * @since 2.1.9 + */ + height: void 0, + /** + * The border color of the date input boxes. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {Highcharts.ColorString} + * @default #cccccc + * @since 1.3.7 + * @apioption rangeSelector.inputBoxBorderColor + */ + /** + * The pixel height of the date input boxes. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {number} + * @default 17 + * @since 1.3.7 + * @apioption rangeSelector.inputBoxHeight + */ + /** + * CSS for the container DIV holding the input boxes. Deprecated as + * of 1.2.5\. Use [inputPosition](#rangeSelector.inputPosition) instead. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @deprecated + * @type {Highcharts.CSSObject} + * @apioption rangeSelector.inputBoxStyle + */ + /** + * The pixel width of the date input boxes. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {number} + * @default 90 + * @since 1.3.7 + * @apioption rangeSelector.inputBoxWidth + */ + /** + * The date format in the input boxes when not selected for editing. + * Defaults to `%b %e, %Y`. + * + * @sample {highstock} stock/rangeselector/input-format/ + * Milliseconds in the range selector + * + * @type {string} + * @default %b %e, %Y + * @apioption rangeSelector.inputDateFormat + */ + /** + * A custom callback function to parse values entered in the input boxes + * and return a valid JavaScript time as milliseconds since 1970. + * + * @sample {highstock} stock/rangeselector/input-format/ + * Milliseconds in the range selector + * + * @type {Highcharts.RangeSelectorParseCallbackFunction} + * @since 1.3.3 + * @apioption rangeSelector.inputDateParser + */ + /** + * The date format in the input boxes when they are selected for + * editing. This must be a format that is recognized by JavaScript + * Date.parse. + * + * @sample {highstock} stock/rangeselector/input-format/ + * Milliseconds in the range selector + * + * @type {string} + * @default %Y-%m-%d + * @apioption rangeSelector.inputEditDateFormat + */ + /** + * Enable or disable the date input boxes. Defaults to enabled when + * there is enough space, disabled if not (typically mobile). + * + * @sample {highstock} stock/rangeselector/input-datepicker/ + * Extending the input with a jQuery UI datepicker + * + * @type {boolean} + * @default true + * @apioption rangeSelector.inputEnabled + */ + /** + * Positioning for the input boxes. Allowed properties are `align`, + * `x` and `y`. + * + * @since 1.2.4 + */ + inputPosition: { + /** + * The alignment of the input box. Allowed properties are `left`, + * `center`, `right`. + * + * @sample {highstock} stock/rangeselector/input-button-position/ + * Alignment + * + * @type {Highcharts.AlignValue} + * @since 6.0.0 + */ + align: 'right', + /** + * X offset of the input row. + */ + x: 0, + /** + * Y offset of the input row. + */ + y: 0 + }, + /** + * The index of the button to appear pre-selected. + * + * @type {number} + * @apioption rangeSelector.selected + */ + /** + * Positioning for the button row. + * + * @since 1.2.4 + */ + buttonPosition: { + /** + * The alignment of the input box. Allowed properties are `left`, + * `center`, `right`. + * + * @sample {highstock} stock/rangeselector/input-button-position/ + * Alignment + * + * @type {Highcharts.AlignValue} + * @since 6.0.0 + */ + align: 'left', + /** + * X offset of the button row. + */ + x: 0, + /** + * Y offset of the button row. + */ + y: 0 + }, + /** + * CSS for the HTML inputs in the range selector. + * + * In styled mode, the inputs are styled by the + * `.highcharts-range-input text` rule in SVG mode, and + * `input.highcharts-range-selector` when active. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {Highcharts.CSSObject} + * @apioption rangeSelector.inputStyle + */ + /** + * CSS styles for the labels - the Zoom, From and To texts. + * + * In styled mode, the labels are styled by the + * `.highcharts-range-label` class. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {Highcharts.CSSObject} + */ + labelStyle: { + /** @ignore */ + color: '#666666' + } + } +}); +defaultOptions.lang = merge(defaultOptions.lang, +/** + * Language object. The language object is global and it can't be set + * on each chart initialization. Instead, use `Highcharts.setOptions` to + * set it before any chart is initialized. + * + * ```js + * Highcharts.setOptions({ + * lang: { + * months: [ + * 'Janvier', 'Février', 'Mars', 'Avril', + * 'Mai', 'Juin', 'Juillet', 'Août', + * 'Septembre', 'Octobre', 'Novembre', 'Décembre' + * ], + * weekdays: [ + * 'Dimanche', 'Lundi', 'Mardi', 'Mercredi', + * 'Jeudi', 'Vendredi', 'Samedi' + * ] + * } + * }); + * ``` + * + * @optionparent lang + */ +{ + /** + * The text for the label for the range selector buttons. + * + * @product highstock gantt + */ + rangeSelectorZoom: 'Zoom', + /** + * The text for the label for the "from" input box in the range + * selector. + * + * @product highstock gantt + */ + rangeSelectorFrom: 'From', + /** + * The text for the label for the "to" input box in the range selector. + * + * @product highstock gantt + */ + rangeSelectorTo: 'To' +}); +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * The range selector. + * + * @private + * @class + * @name Highcharts.RangeSelector + * @param {Highcharts.Chart} chart + */ +function RangeSelector(chart) { + // Run RangeSelector + this.init(chart); +} +RangeSelector.prototype = { + /** + * The method to run when one of the buttons in the range selectors is + * clicked + * + * @private + * @function Highcharts.RangeSelector#clickButton + * @param {number} i + * The index of the button + * @param {boolean} [redraw] + * @return {void} + */ + clickButton: function (i, redraw) { + var rangeSelector = this, chart = rangeSelector.chart, rangeOptions = rangeSelector.buttonOptions[i], baseAxis = chart.xAxis[0], unionExtremes = (chart.scroller && chart.scroller.getUnionExtremes()) || baseAxis || {}, dataMin = unionExtremes.dataMin, dataMax = unionExtremes.dataMax, newMin, newMax = baseAxis && Math.round(Math.min(baseAxis.max, pick(dataMax, baseAxis.max))), // #1568 + type = rangeOptions.type, baseXAxisOptions, range = rangeOptions._range, rangeMin, minSetting, rangeSetting, ctx, ytdExtremes, dataGrouping = rangeOptions.dataGrouping; + // chart has no data, base series is removed + if (dataMin === null || dataMax === null) { + return; + } + // Set the fixed range before range is altered + chart.fixedRange = range; + // Apply dataGrouping associated to button + if (dataGrouping) { + this.forcedDataGrouping = true; + Axis.prototype.setDataGrouping.call(baseAxis || { chart: this.chart }, dataGrouping, false); + this.frozenStates = rangeOptions.preserveDataGrouping; + } + // Apply range + if (type === 'month' || type === 'year') { + if (!baseAxis) { + // This is set to the user options and picked up later when the + // axis is instantiated so that we know the min and max. + range = rangeOptions; + } + else { + ctx = { + range: rangeOptions, + max: newMax, + chart: chart, + dataMin: dataMin, + dataMax: dataMax + }; + newMin = baseAxis.minFromRange.call(ctx); + if (isNumber(ctx.newMax)) { + newMax = ctx.newMax; + } + } + // Fixed times like minutes, hours, days + } + else if (range) { + newMin = Math.max(newMax - range, dataMin); + newMax = Math.min(newMin + range, dataMax); + } + else if (type === 'ytd') { + // On user clicks on the buttons, or a delayed action running from + // the beforeRender event (below), the baseAxis is defined. + if (baseAxis) { + // When "ytd" is the pre-selected button for the initial view, + // its calculation is delayed and rerun in the beforeRender + // event (below). When the series are initialized, but before + // the chart is rendered, we have access to the xData array + // (#942). + if (typeof dataMax === 'undefined') { + dataMin = Number.MAX_VALUE; + dataMax = Number.MIN_VALUE; + chart.series.forEach(function (series) { + // reassign it to the last item + var xData = series.xData; + dataMin = Math.min(xData[0], dataMin); + dataMax = Math.max(xData[xData.length - 1], dataMax); + }); + redraw = false; + } + ytdExtremes = rangeSelector.getYTDExtremes(dataMax, dataMin, chart.time.useUTC); + newMin = rangeMin = ytdExtremes.min; + newMax = ytdExtremes.max; + // "ytd" is pre-selected. We don't yet have access to processed + // point and extremes data (things like pointStart and pointInterval + // are missing), so we delay the process (#942) + } + else { + rangeSelector.deferredYTDClick = i; + return; + } + } + else if (type === 'all' && baseAxis) { + newMin = dataMin; + newMax = dataMax; + } + newMin += rangeOptions._offsetMin; + newMax += rangeOptions._offsetMax; + rangeSelector.setSelected(i); + // Update the chart + if (!baseAxis) { + // Axis not yet instanciated. Temporarily set min and range + // options and remove them on chart load (#4317). + baseXAxisOptions = splat(chart.options.xAxis)[0]; + rangeSetting = baseXAxisOptions.range; + baseXAxisOptions.range = range; + minSetting = baseXAxisOptions.min; + baseXAxisOptions.min = rangeMin; + addEvent(chart, 'load', function resetMinAndRange() { + baseXAxisOptions.range = rangeSetting; + baseXAxisOptions.min = minSetting; + }); + } + else { + // Existing axis object. Set extremes after render time. + baseAxis.setExtremes(newMin, newMax, pick(redraw, 1), null, // auto animation + { + trigger: 'rangeSelectorButton', + rangeSelectorButton: rangeOptions + }); + } + }, + /** + * Set the selected option. This method only sets the internal flag, it + * doesn't update the buttons or the actual zoomed range. + * + * @private + * @function Highcharts.RangeSelector#setSelected + * @param {number} [selected] + * @return {void} + */ + setSelected: function (selected) { + this.selected = this.options.selected = selected; + }, + /** + * The default buttons for pre-selecting time frames + */ + defaultButtons: [{ + type: 'month', + count: 1, + text: '1m' + }, { + type: 'month', + count: 3, + text: '3m' + }, { + type: 'month', + count: 6, + text: '6m' + }, { + type: 'ytd', + text: 'YTD' + }, { + type: 'year', + count: 1, + text: '1y' + }, { + type: 'all', + text: 'All' + }], + /** + * Initialize the range selector + * + * @private + * @function Highcharts.RangeSelector#init + * @param {Highcharts.Chart} chart + * @return {void} + */ + init: function (chart) { + var rangeSelector = this, options = chart.options.rangeSelector, buttonOptions = options.buttons || + [].concat(rangeSelector.defaultButtons), selectedOption = options.selected, blurInputs = function () { + var minInput = rangeSelector.minInput, maxInput = rangeSelector.maxInput; + // #3274 in some case blur is not defined + if (minInput && minInput.blur) { + fireEvent(minInput, 'blur'); + } + if (maxInput && maxInput.blur) { + fireEvent(maxInput, 'blur'); + } + }; + rangeSelector.chart = chart; + rangeSelector.options = options; + rangeSelector.buttons = []; + rangeSelector.buttonOptions = buttonOptions; + this.unMouseDown = addEvent(chart.container, 'mousedown', blurInputs); + this.unResize = addEvent(chart, 'resize', blurInputs); + // Extend the buttonOptions with actual range + buttonOptions.forEach(rangeSelector.computeButtonRange); + // zoomed range based on a pre-selected button index + if (typeof selectedOption !== 'undefined' && + buttonOptions[selectedOption]) { + this.clickButton(selectedOption, false); + } + addEvent(chart, 'load', function () { + // If a data grouping is applied to the current button, release it + // when extremes change + if (chart.xAxis && chart.xAxis[0]) { + addEvent(chart.xAxis[0], 'setExtremes', function (e) { + if (this.max - this.min !== + chart.fixedRange && + e.trigger !== 'rangeSelectorButton' && + e.trigger !== 'updatedData' && + rangeSelector.forcedDataGrouping && + !rangeSelector.frozenStates) { + this.setDataGrouping(false, false); + } + }); + } + }); + }, + /** + * Dynamically update the range selector buttons after a new range has been + * set + * + * @private + * @function Highcharts.RangeSelector#updateButtonStates + * @return {void} + */ + updateButtonStates: function () { + var rangeSelector = this, chart = this.chart, baseAxis = chart.xAxis[0], actualRange = Math.round(baseAxis.max - baseAxis.min), hasNoData = !baseAxis.hasVisibleSeries, day = 24 * 36e5, // A single day in milliseconds + unionExtremes = (chart.scroller && + chart.scroller.getUnionExtremes()) || baseAxis, dataMin = unionExtremes.dataMin, dataMax = unionExtremes.dataMax, ytdExtremes = rangeSelector.getYTDExtremes(dataMax, dataMin, chart.time.useUTC), ytdMin = ytdExtremes.min, ytdMax = ytdExtremes.max, selected = rangeSelector.selected, selectedExists = isNumber(selected), allButtonsEnabled = rangeSelector.options.allButtonsEnabled, buttons = rangeSelector.buttons; + rangeSelector.buttonOptions.forEach(function (rangeOptions, i) { + var range = rangeOptions._range, type = rangeOptions.type, count = rangeOptions.count || 1, button = buttons[i], state = 0, disable, select, offsetRange = rangeOptions._offsetMax - + rangeOptions._offsetMin, isSelected = i === selected, + // Disable buttons where the range exceeds what is allowed in + // the current view + isTooGreatRange = range > + dataMax - dataMin, + // Disable buttons where the range is smaller than the minimum + // range + isTooSmallRange = range < baseAxis.minRange, + // Do not select the YTD button if not explicitly told so + isYTDButNotSelected = false, + // Disable the All button if we're already showing all + isAllButAlreadyShowingAll = false, isSameRange = range === actualRange; + // Months and years have a variable range so we check the extremes + if ((type === 'month' || type === 'year') && + (actualRange + 36e5 >= + { month: 28, year: 365 }[type] * day * count - offsetRange) && + (actualRange - 36e5 <= + { month: 31, year: 366 }[type] * day * count + offsetRange)) { + isSameRange = true; + } + else if (type === 'ytd') { + isSameRange = (ytdMax - ytdMin + offsetRange) === actualRange; + isYTDButNotSelected = !isSelected; + } + else if (type === 'all') { + isSameRange = (baseAxis.max - baseAxis.min >= + dataMax - dataMin); + isAllButAlreadyShowingAll = (!isSelected && + selectedExists && + isSameRange); + } + // The new zoom area happens to match the range for a button - mark + // it selected. This happens when scrolling across an ordinal gap. + // It can be seen in the intraday demos when selecting 1h and scroll + // across the night gap. + disable = (!allButtonsEnabled && + (isTooGreatRange || + isTooSmallRange || + isAllButAlreadyShowingAll || + hasNoData)); + select = ((isSelected && isSameRange) || + (isSameRange && !selectedExists && !isYTDButNotSelected) || + (isSelected && rangeSelector.frozenStates)); + if (disable) { + state = 3; + } + else if (select) { + selectedExists = true; // Only one button can be selected + state = 2; + } + // If state has changed, update the button + if (button.state !== state) { + button.setState(state); + // Reset (#9209) + if (state === 0 && selected === i) { + rangeSelector.setSelected(null); + } + } + }); + }, + /** + * Compute and cache the range for an individual button + * + * @private + * @function Highcharts.RangeSelector#computeButtonRange + * @param {Highcharts.RangeSelectorButtonsOptions} rangeOptions + * @return {void} + */ + computeButtonRange: function (rangeOptions) { + var type = rangeOptions.type, count = rangeOptions.count || 1, + // these time intervals have a fixed number of milliseconds, as + // opposed to month, ytd and year + fixedTimes = { + millisecond: 1, + second: 1000, + minute: 60 * 1000, + hour: 3600 * 1000, + day: 24 * 3600 * 1000, + week: 7 * 24 * 3600 * 1000 + }; + // Store the range on the button object + if (fixedTimes[type]) { + rangeOptions._range = fixedTimes[type] * count; + } + else if (type === 'month' || type === 'year') { + rangeOptions._range = { + month: 30, + year: 365 + }[type] * 24 * 36e5 * count; + } + rangeOptions._offsetMin = pick(rangeOptions.offsetMin, 0); + rangeOptions._offsetMax = pick(rangeOptions.offsetMax, 0); + rangeOptions._range += + rangeOptions._offsetMax - rangeOptions._offsetMin; + }, + /** + * Set the internal and displayed value of a HTML input for the dates + * + * @private + * @function Highcharts.RangeSelector#setInputValue + * @param {string} name + * @param {number} [inputTime] + * @return {void} + */ + setInputValue: function (name, inputTime) { + var options = this.chart.options.rangeSelector, time = this.chart.time, input = this[name + 'Input']; + if (defined(inputTime)) { + input.previousValue = input.HCTime; + input.HCTime = inputTime; + } + input.value = time.dateFormat(options.inputEditDateFormat || '%Y-%m-%d', input.HCTime); + this[name + 'DateBox'].attr({ + text: time.dateFormat(options.inputDateFormat || '%b %e, %Y', input.HCTime) + }); + }, + /** + * @private + * @function Highcharts.RangeSelector#showInput + * @param {string} name + * @return {void} + */ + showInput: function (name) { + var inputGroup = this.inputGroup, dateBox = this[name + 'DateBox']; + css(this[name + 'Input'], { + left: (inputGroup.translateX + dateBox.x) + 'px', + top: inputGroup.translateY + 'px', + width: (dateBox.width - 2) + 'px', + height: (dateBox.height - 2) + 'px', + border: '2px solid silver' + }); + }, + /** + * @private + * @function Highcharts.RangeSelector#hideInput + * @param {string} name + * @return {void} + */ + hideInput: function (name) { + css(this[name + 'Input'], { + border: 0, + width: '1px', + height: '1px' + }); + this.setInputValue(name); + }, + /** + * Draw either the 'from' or the 'to' HTML input box of the range selector + * + * @private + * @function Highcharts.RangeSelector#drawInput + * @param {string} name + * @return {void} + */ + drawInput: function (name) { + var rangeSelector = this, chart = rangeSelector.chart, chartStyle = chart.renderer.style || {}, renderer = chart.renderer, options = chart.options.rangeSelector, lang = defaultOptions.lang, div = rangeSelector.div, isMin = name === 'min', input, label, dateBox, inputGroup = this.inputGroup; + /** + * @private + */ + function updateExtremes() { + var inputValue = input.value, value = (options.inputDateParser || Date.parse)(inputValue), chartAxis = chart.xAxis[0], dataAxis = chart.scroller && chart.scroller.xAxis ? + chart.scroller.xAxis : + chartAxis, dataMin = dataAxis.dataMin, dataMax = dataAxis.dataMax; + if (value !== input.previousValue) { + input.previousValue = value; + // If the value isn't parsed directly to a value by the + // browser's Date.parse method, like YYYY-MM-DD in IE, try + // parsing it a different way + if (!isNumber(value)) { + value = inputValue.split('-'); + value = Date.UTC(pInt(value[0]), pInt(value[1]) - 1, pInt(value[2])); + } + if (isNumber(value)) { + // Correct for timezone offset (#433) + if (!chart.time.useUTC) { + value = + value + new Date().getTimezoneOffset() * 60 * 1000; + } + // Validate the extremes. If it goes beyound the data min or + // max, use the actual data extreme (#2438). + if (isMin) { + if (value > rangeSelector.maxInput.HCTime) { + value = void 0; + } + else if (value < dataMin) { + value = dataMin; + } + } + else { + if (value < rangeSelector.minInput.HCTime) { + value = void 0; + } + else if (value > dataMax) { + value = dataMax; + } + } + // Set the extremes + if (typeof value !== 'undefined') { // @todo typof undefined + chartAxis.setExtremes(isMin ? value : chartAxis.min, isMin ? chartAxis.max : value, void 0, void 0, { trigger: 'rangeSelectorInput' }); + } + } + } + } + // Create the text label + this[name + 'Label'] = label = renderer + .label(lang[isMin ? 'rangeSelectorFrom' : 'rangeSelectorTo'], this.inputGroup.offset) + .addClass('highcharts-range-label') + .attr({ + padding: 2 + }) + .add(inputGroup); + inputGroup.offset += label.width + 5; + // Create an SVG label that shows updated date ranges and and records + // click events that bring in the HTML input. + this[name + 'DateBox'] = dateBox = renderer + .label('', inputGroup.offset) + .addClass('highcharts-range-input') + .attr({ + padding: 2, + width: options.inputBoxWidth || 90, + height: options.inputBoxHeight || 17, + 'text-align': 'center' + }) + .on('click', function () { + // If it is already focused, the onfocus event doesn't fire + // (#3713) + rangeSelector.showInput(name); + rangeSelector[name + 'Input'].focus(); + }); + if (!chart.styledMode) { + dateBox.attr({ + stroke: options.inputBoxBorderColor || '#cccccc', + 'stroke-width': 1 + }); + } + dateBox.add(inputGroup); + inputGroup.offset += dateBox.width + (isMin ? 10 : 0); + // Create the HTML input element. This is rendered as 1x1 pixel then set + // to the right size when focused. + this[name + 'Input'] = input = createElement('input', { + name: name, + className: 'highcharts-range-selector', + type: 'text' + }, { + top: chart.plotTop + 'px' // prevent jump on focus in Firefox + }, div); + if (!chart.styledMode) { + // Styles + label.css(merge(chartStyle, options.labelStyle)); + dateBox.css(merge({ + color: '#333333' + }, chartStyle, options.inputStyle)); + css(input, extend({ + position: 'absolute', + border: 0, + width: '1px', + height: '1px', + padding: 0, + textAlign: 'center', + fontSize: chartStyle.fontSize, + fontFamily: chartStyle.fontFamily, + top: '-9999em' // #4798 + }, options.inputStyle)); + } + // Blow up the input box + input.onfocus = function () { + rangeSelector.showInput(name); + }; + // Hide away the input box + input.onblur = function () { + // update extermes only when inputs are active + if (input === H.doc.activeElement) { // Only when focused + // Update also when no `change` event is triggered, like when + // clicking inside the SVG (#4710) + updateExtremes(); + } + // #10404 - move hide and blur outside focus + rangeSelector.hideInput(name); + input.blur(); // #4606 + }; + // handle changes in the input boxes + input.onchange = updateExtremes; + input.onkeypress = function (event) { + // IE does not fire onchange on enter + if (event.keyCode === 13) { + updateExtremes(); + } + }; + }, + /** + * Get the position of the range selector buttons and inputs. This can be + * overridden from outside for custom positioning. + * + * @private + * @function Highcharts.RangeSelector#getPosition + * + * @return {Highcharts.Dictionary} + */ + getPosition: function () { + var chart = this.chart, options = chart.options.rangeSelector, top = options.verticalAlign === 'top' ? + chart.plotTop - chart.axisOffset[0] : + 0; // set offset only for varticalAlign top + return { + buttonTop: top + options.buttonPosition.y, + inputTop: top + options.inputPosition.y - 10 + }; + }, + /** + * Get the extremes of YTD. Will choose dataMax if its value is lower than + * the current timestamp. Will choose dataMin if its value is higher than + * the timestamp for the start of current year. + * + * @private + * @function Highcharts.RangeSelector#getYTDExtremes + * + * @param {number} dataMax + * + * @param {number} dataMin + * + * @return {*} + * Returns min and max for the YTD + */ + getYTDExtremes: function (dataMax, dataMin, useUTC) { + var time = this.chart.time, min, now = new time.Date(dataMax), year = time.get('FullYear', now), startOfYear = useUTC ? + time.Date.UTC(year, 0, 1) : // eslint-disable-line new-cap + +new time.Date(year, 0, 1); + min = Math.max(dataMin || 0, startOfYear); + now = now.getTime(); + return { + max: Math.min(dataMax || now, now), + min: min + }; + }, + /** + * Render the range selector including the buttons and the inputs. The first + * time render is called, the elements are created and positioned. On + * subsequent calls, they are moved and updated. + * + * @private + * @function Highcharts.RangeSelector#render + * @param {number} [min] + * X axis minimum + * @param {number} [max] + * X axis maximum + * @return {void} + */ + render: function (min, max) { + var rangeSelector = this, chart = rangeSelector.chart, renderer = chart.renderer, container = chart.container, chartOptions = chart.options, navButtonOptions = (chartOptions.exporting && + chartOptions.exporting.enabled !== false && + chartOptions.navigation && + chartOptions.navigation.buttonOptions), lang = defaultOptions.lang, div = rangeSelector.div, options = chartOptions.rangeSelector, + // Place inputs above the container + inputsZIndex = pick(chartOptions.chart.style && + chartOptions.chart.style.zIndex, 0) + 1, floating = options.floating, buttons = rangeSelector.buttons, inputGroup = rangeSelector.inputGroup, buttonTheme = options.buttonTheme, buttonPosition = options.buttonPosition, inputPosition = options.inputPosition, inputEnabled = options.inputEnabled, states = buttonTheme && buttonTheme.states, plotLeft = chart.plotLeft, buttonLeft, buttonGroup = rangeSelector.buttonGroup, group, groupHeight, rendered = rangeSelector.rendered, verticalAlign = rangeSelector.options.verticalAlign, legend = chart.legend, legendOptions = legend && legend.options, buttonPositionY = buttonPosition.y, inputPositionY = inputPosition.y, animate = chart.hasLoaded, verb = animate ? 'animate' : 'attr', exportingX = 0, alignTranslateY, legendHeight, minPosition, translateY = 0, translateX; + if (options.enabled === false) { + return; + } + // create the elements + if (!rendered) { + rangeSelector.group = group = renderer.g('range-selector-group') + .attr({ + zIndex: 7 + }) + .add(); + rangeSelector.buttonGroup = buttonGroup = + renderer.g('range-selector-buttons').add(group); + rangeSelector.zoomText = renderer + .text(lang.rangeSelectorZoom, 0, 15) + .add(buttonGroup); + if (!chart.styledMode) { + rangeSelector.zoomText.css(options.labelStyle); + buttonTheme['stroke-width'] = + pick(buttonTheme['stroke-width'], 0); + } + rangeSelector.buttonOptions.forEach(function (rangeOptions, i) { + buttons[i] = renderer + .button(rangeOptions.text, 0, 0, function (e) { + // extract events from button object and call + var buttonEvents = (rangeOptions.events && + rangeOptions.events.click), callDefaultEvent; + if (buttonEvents) { + callDefaultEvent = + buttonEvents.call(rangeOptions, e); + } + if (callDefaultEvent !== false) { + rangeSelector.clickButton(i); + } + rangeSelector.isActive = true; + }, buttonTheme, states && states.hover, states && states.select, states && states.disabled) + .attr({ + 'text-align': 'center' + }) + .add(buttonGroup); + }); + // first create a wrapper outside the container in order to make + // the inputs work and make export correct + if (inputEnabled !== false) { + rangeSelector.div = div = createElement('div', null, { + position: 'relative', + height: 0, + zIndex: inputsZIndex + }); + container.parentNode.insertBefore(div, container); + // Create the group to keep the inputs + rangeSelector.inputGroup = inputGroup = + renderer.g('input-group').add(group); + inputGroup.offset = 0; + rangeSelector.drawInput('min'); + rangeSelector.drawInput('max'); + } + } + // #8769, allow dynamically updating margins + rangeSelector.zoomText[verb]({ + x: pick(plotLeft + buttonPosition.x, plotLeft) + }); + // button start position + buttonLeft = pick(plotLeft + buttonPosition.x, plotLeft) + + rangeSelector.zoomText.getBBox().width + 5; + rangeSelector.buttonOptions.forEach(function (rangeOptions, i) { + buttons[i][verb]({ x: buttonLeft }); + // increase button position for the next button + buttonLeft += buttons[i].width + pick(options.buttonSpacing, 5); + }); + plotLeft = chart.plotLeft - chart.spacing[3]; + rangeSelector.updateButtonStates(); + // detect collisiton with exporting + if (navButtonOptions && + this.titleCollision(chart) && + verticalAlign === 'top' && + buttonPosition.align === 'right' && ((buttonPosition.y + + buttonGroup.getBBox().height - 12) < + ((navButtonOptions.y || 0) + + navButtonOptions.height))) { + exportingX = -40; + } + translateX = buttonPosition.x - chart.spacing[3]; + if (buttonPosition.align === 'right') { + translateX += exportingX - plotLeft; // (#13014) + } + else if (buttonPosition.align === 'center') { + translateX -= plotLeft / 2; + } + // align button group + buttonGroup.align({ + y: buttonPosition.y, + width: buttonGroup.getBBox().width, + align: buttonPosition.align, + x: translateX + }, true, chart.spacingBox); + // skip animation + rangeSelector.group.placed = animate; + rangeSelector.buttonGroup.placed = animate; + if (inputEnabled !== false) { + var inputGroupX, inputGroupWidth, buttonGroupX, buttonGroupWidth; + // detect collision with exporting + if (navButtonOptions && + this.titleCollision(chart) && + verticalAlign === 'top' && + inputPosition.align === 'right' && ((inputPosition.y - + inputGroup.getBBox().height - 12) < + ((navButtonOptions.y || 0) + + navButtonOptions.height + + chart.spacing[0]))) { + exportingX = -40; + } + else { + exportingX = 0; + } + if (inputPosition.align === 'left') { + translateX = plotLeft; + } + else if (inputPosition.align === 'right') { + translateX = -Math.max(chart.axisOffset[1], -exportingX); + } + // Update the alignment to the updated spacing box + inputGroup.align({ + y: inputPosition.y, + width: inputGroup.getBBox().width, + align: inputPosition.align, + // fix wrong getBBox() value on right align + x: inputPosition.x + translateX - 2 + }, true, chart.spacingBox); + // detect collision + inputGroupX = (inputGroup.alignAttr.translateX + + inputGroup.alignOptions.x - + exportingX + + // getBBox for detecing left margin + inputGroup.getBBox().x + + // 2px padding to not overlap input and label + 2); + inputGroupWidth = inputGroup.alignOptions.width; + buttonGroupX = buttonGroup.alignAttr.translateX + + buttonGroup.getBBox().x; + // 20 is minimal spacing between elements + buttonGroupWidth = buttonGroup.getBBox().width + 20; + if ((inputPosition.align === + buttonPosition.align) || ((buttonGroupX + buttonGroupWidth > inputGroupX) && + (inputGroupX + inputGroupWidth > buttonGroupX) && + (buttonPositionY < + (inputPositionY + + inputGroup.getBBox().height)))) { + inputGroup.attr({ + translateX: inputGroup.alignAttr.translateX + + (chart.axisOffset[1] >= -exportingX ? 0 : -exportingX), + translateY: inputGroup.alignAttr.translateY + + buttonGroup.getBBox().height + 10 + }); + } + // Set or reset the input values + rangeSelector.setInputValue('min', min); + rangeSelector.setInputValue('max', max); + // skip animation + rangeSelector.inputGroup.placed = animate; + } + // vertical align + rangeSelector.group.align({ + verticalAlign: verticalAlign + }, true, chart.spacingBox); + // set position + groupHeight = + rangeSelector.group.getBBox().height + 20; // # 20 padding + alignTranslateY = + rangeSelector.group.alignAttr.translateY; + // calculate bottom position + if (verticalAlign === 'bottom') { + legendHeight = (legendOptions && + legendOptions.verticalAlign === 'bottom' && + legendOptions.enabled && + !legendOptions.floating ? + legend.legendHeight + pick(legendOptions.margin, 10) : + 0); + groupHeight = groupHeight + legendHeight - 20; + translateY = (alignTranslateY - + groupHeight - + (floating ? 0 : options.y) - + (chart.titleOffset ? chart.titleOffset[2] : 0) - + 10 // 10 spacing + ); + } + if (verticalAlign === 'top') { + if (floating) { + translateY = 0; + } + if (chart.titleOffset && chart.titleOffset[0]) { + translateY = chart.titleOffset[0]; + } + translateY += ((chart.margin[0] - chart.spacing[0]) || 0); + } + else if (verticalAlign === 'middle') { + if (inputPositionY === buttonPositionY) { + if (inputPositionY < 0) { + translateY = alignTranslateY + minPosition; + } + else { + translateY = alignTranslateY; + } + } + else if (inputPositionY || buttonPositionY) { + if (inputPositionY < 0 || + buttonPositionY < 0) { + translateY -= Math.min(inputPositionY, buttonPositionY); + } + else { + translateY = + alignTranslateY - groupHeight + minPosition; + } + } + } + rangeSelector.group.translate(options.x, options.y + Math.floor(translateY)); + // translate HTML inputs + if (inputEnabled !== false) { + rangeSelector.minInput.style.marginTop = + rangeSelector.group.translateY + 'px'; + rangeSelector.maxInput.style.marginTop = + rangeSelector.group.translateY + 'px'; + } + rangeSelector.rendered = true; + }, + /** + * Extracts height of range selector + * + * @private + * @function Highcharts.RangeSelector#getHeight + * @return {number} + * Returns rangeSelector height + */ + getHeight: function () { + var rangeSelector = this, options = rangeSelector.options, rangeSelectorGroup = rangeSelector.group, inputPosition = options.inputPosition, buttonPosition = options.buttonPosition, yPosition = options.y, buttonPositionY = buttonPosition.y, inputPositionY = inputPosition.y, rangeSelectorHeight = 0, minPosition; + if (options.height) { + return options.height; + } + rangeSelectorHeight = rangeSelectorGroup ? + // 13px to keep back compatibility + (rangeSelectorGroup.getBBox(true).height) + 13 + + yPosition : + 0; + minPosition = Math.min(inputPositionY, buttonPositionY); + if ((inputPositionY < 0 && buttonPositionY < 0) || + (inputPositionY > 0 && buttonPositionY > 0)) { + rangeSelectorHeight += Math.abs(minPosition); + } + return rangeSelectorHeight; + }, + /** + * Detect collision with title or subtitle + * + * @private + * @function Highcharts.RangeSelector#titleCollision + * + * @param {Highcharts.Chart} chart + * + * @return {boolean} + * Returns collision status + */ + titleCollision: function (chart) { + return !(chart.options.title.text || + chart.options.subtitle.text); + }, + /** + * Update the range selector with new options + * + * @private + * @function Highcharts.RangeSelector#update + * @param {Highcharts.RangeSelectorOptions} options + * @return {void} + */ + update: function (options) { + var chart = this.chart; + merge(true, chart.options.rangeSelector, options); + this.destroy(); + this.init(chart); + chart.rangeSelector.render(); + }, + /** + * Destroys allocated elements. + * + * @private + * @function Highcharts.RangeSelector#destroy + */ + destroy: function () { + var rSelector = this, minInput = rSelector.minInput, maxInput = rSelector.maxInput; + rSelector.unMouseDown(); + rSelector.unResize(); + // Destroy elements in collections + destroyObjectProperties(rSelector.buttons); + // Clear input element events + if (minInput) { + minInput.onfocus = minInput.onblur = minInput.onchange = null; + } + if (maxInput) { + maxInput.onfocus = maxInput.onblur = maxInput.onchange = null; + } + // Destroy HTML and SVG elements + objectEach(rSelector, function (val, key) { + if (val && key !== 'chart') { + if (val.destroy) { + // SVGElement + val.destroy(); + } + else if (val.nodeType) { + // HTML element + discardElement(this[key]); + } + } + if (val !== RangeSelector.prototype[key]) { + rSelector[key] = null; + } + }, this); + } +}; +/** + * Get the axis min value based on the range option and the current max. For + * stock charts this is extended via the {@link RangeSelector} so that if the + * selected range is a multiple of months or years, it is compensated for + * various month lengths. + * + * @private + * @function Highcharts.Axis#minFromRange + * @return {number|undefined} + * The new minimum value. + */ +Axis.prototype.minFromRange = function () { + var rangeOptions = this.range, type = rangeOptions.type, min, max = this.max, dataMin, range, time = this.chart.time, + // Get the true range from a start date + getTrueRange = function (base, count) { + var timeName = type === 'year' ? 'FullYear' : 'Month'; + var date = new time.Date(base); + var basePeriod = time.get(timeName, date); + time.set(timeName, date, basePeriod + count); + if (basePeriod === time.get(timeName, date)) { + time.set('Date', date, 0); // #6537 + } + return date.getTime() - base; + }; + if (isNumber(rangeOptions)) { + min = max - rangeOptions; + range = rangeOptions; + } + else { + min = max + getTrueRange(max, -rangeOptions.count); + // Let the fixedRange reflect initial settings (#5930) + if (this.chart) { + this.chart.fixedRange = max - min; + } + } + dataMin = pick(this.dataMin, Number.MIN_VALUE); + if (!isNumber(min)) { + min = dataMin; + } + if (min <= dataMin) { + min = dataMin; + if (typeof range === 'undefined') { // #4501 + range = getTrueRange(min, rangeOptions.count); + } + this.newMax = Math.min(min + range, this.dataMax); + } + if (!isNumber(max)) { + min = void 0; + } + return min; +}; +if (!H.RangeSelector) { + // Initialize rangeselector for stock charts + addEvent(Chart, 'afterGetContainer', function () { + if (this.options.rangeSelector.enabled) { + this.rangeSelector = new RangeSelector(this); + } + }); + addEvent(Chart, 'beforeRender', function () { + var chart = this, axes = chart.axes, rangeSelector = chart.rangeSelector, verticalAlign; + if (rangeSelector) { + if (isNumber(rangeSelector.deferredYTDClick)) { + rangeSelector.clickButton(rangeSelector.deferredYTDClick); + delete rangeSelector.deferredYTDClick; + } + axes.forEach(function (axis) { + axis.updateNames(); + axis.setScale(); + }); + chart.getAxisMargins(); + rangeSelector.render(); + verticalAlign = rangeSelector.options.verticalAlign; + if (!rangeSelector.options.floating) { + if (verticalAlign === 'bottom') { + this.extraBottomMargin = true; + } + else if (verticalAlign !== 'middle') { + this.extraTopMargin = true; + } + } + } + }); + addEvent(Chart, 'update', function (e) { + var chart = this, options = e.options, optionsRangeSelector = options.rangeSelector, rangeSelector = chart.rangeSelector, verticalAlign, extraBottomMarginWas = this.extraBottomMargin, extraTopMarginWas = this.extraTopMargin; + if (optionsRangeSelector && + optionsRangeSelector.enabled && + !defined(rangeSelector)) { + this.options.rangeSelector.enabled = true; + this.rangeSelector = new RangeSelector(this); + } + this.extraBottomMargin = false; + this.extraTopMargin = false; + if (rangeSelector) { + rangeSelector.render(); + verticalAlign = (optionsRangeSelector && + optionsRangeSelector.verticalAlign) || (rangeSelector.options && rangeSelector.options.verticalAlign); + if (!rangeSelector.options.floating) { + if (verticalAlign === 'bottom') { + this.extraBottomMargin = true; + } + else if (verticalAlign !== 'middle') { + this.extraTopMargin = true; + } + } + if (this.extraBottomMargin !== extraBottomMarginWas || + this.extraTopMargin !== extraTopMarginWas) { + this.isDirtyBox = true; + } + } + }); + addEvent(Chart, 'render', function () { + var chart = this, rangeSelector = chart.rangeSelector, verticalAlign; + if (rangeSelector && !rangeSelector.options.floating) { + rangeSelector.render(); + verticalAlign = rangeSelector.options.verticalAlign; + if (verticalAlign === 'bottom') { + this.extraBottomMargin = true; + } + else if (verticalAlign !== 'middle') { + this.extraTopMargin = true; + } + } + }); + addEvent(Chart, 'getMargins', function () { + var rangeSelector = this.rangeSelector, rangeSelectorHeight; + if (rangeSelector) { + rangeSelectorHeight = rangeSelector.getHeight(); + if (this.extraTopMargin) { + this.plotTop += rangeSelectorHeight; + } + if (this.extraBottomMargin) { + this.marginBottom += rangeSelectorHeight; + } + } + }); + Chart.prototype.callbacks.push(function (chart) { + var extremes, rangeSelector = chart.rangeSelector, unbindRender, unbindSetExtremes, legend, alignTo, verticalAlign; + /** + * @private + */ + function renderRangeSelector() { + extremes = chart.xAxis[0].getExtremes(); + legend = chart.legend; + verticalAlign = rangeSelector === null || rangeSelector === void 0 ? void 0 : rangeSelector.options.verticalAlign; + if (isNumber(extremes.min)) { + rangeSelector.render(extremes.min, extremes.max); + } + // Re-align the legend so that it's below the rangeselector + if (rangeSelector && legend.display && + verticalAlign === 'top' && + verticalAlign === legend.options.verticalAlign) { + // Create a new alignment box for the legend. + alignTo = merge(chart.spacingBox); + if (legend.options.layout === 'vertical') { + alignTo.y = chart.plotTop; + } + else { + alignTo.y += rangeSelector.getHeight(); + } + legend.group.placed = false; // Don't animate the alignment. + legend.align(alignTo); + } + } + if (rangeSelector) { + // redraw the scroller on setExtremes + unbindSetExtremes = addEvent(chart.xAxis[0], 'afterSetExtremes', function (e) { + rangeSelector.render(e.min, e.max); + }); + // redraw the scroller chart resize + unbindRender = addEvent(chart, 'redraw', renderRangeSelector); + // do it now + renderRangeSelector(); + } + // Remove resize/afterSetExtremes at chart destroy + addEvent(chart, 'destroy', function destroyEvents() { + if (rangeSelector) { + unbindRender(); + unbindSetExtremes(); + } + }); + }); + H.RangeSelector = RangeSelector; +} diff --git a/librerias/gantt/code/es-modules/parts/Responsive.js b/librerias/gantt/code/es-modules/parts/Responsive.js new file mode 100644 index 0000000..258a0da --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/Responsive.js @@ -0,0 +1,258 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +/** + * A callback function to gain complete control on when the responsive rule + * applies. + * + * @callback Highcharts.ResponsiveCallbackFunction + * + * @param {Highcharts.Chart} this + * Chart context. + * + * @return {boolean} + * Return `true` if it applies. + */ +import './Chart.js'; +import U from './Utilities.js'; +var find = U.find, isArray = U.isArray, isObject = U.isObject, merge = U.merge, objectEach = U.objectEach, pick = U.pick, splat = U.splat, uniqueKey = U.uniqueKey; +var Chart = H.Chart; +/** + * Allows setting a set of rules to apply for different screen or chart + * sizes. Each rule specifies additional chart options. + * + * @sample {highstock} stock/demo/responsive/ + * Stock chart + * @sample highcharts/responsive/axis/ + * Axis + * @sample highcharts/responsive/legend/ + * Legend + * @sample highcharts/responsive/classname/ + * Class name + * + * @since 5.0.0 + * @apioption responsive + */ +/** + * A set of rules for responsive settings. The rules are executed from + * the top down. + * + * @sample {highcharts} highcharts/responsive/axis/ + * Axis changes + * @sample {highstock} highcharts/responsive/axis/ + * Axis changes + * @sample {highmaps} highcharts/responsive/axis/ + * Axis changes + * + * @type {Array<*>} + * @since 5.0.0 + * @apioption responsive.rules + */ +/** + * A full set of chart options to apply as overrides to the general + * chart options. The chart options are applied when the given rule + * is active. + * + * A special case is configuration objects that take arrays, for example + * [xAxis](#xAxis), [yAxis](#yAxis) or [series](#series). For these + * collections, an `id` option is used to map the new option set to + * an existing object. If an existing object of the same id is not found, + * the item of the same indexupdated. So for example, setting `chartOptions` + * with two series items without an `id`, will cause the existing chart's + * two series to be updated with respective options. + * + * @sample {highstock} stock/demo/responsive/ + * Stock chart + * @sample highcharts/responsive/axis/ + * Axis + * @sample highcharts/responsive/legend/ + * Legend + * @sample highcharts/responsive/classname/ + * Class name + * + * @type {Highcharts.Options} + * @since 5.0.0 + * @apioption responsive.rules.chartOptions + */ +/** + * Under which conditions the rule applies. + * + * @since 5.0.0 + * @apioption responsive.rules.condition + */ +/** + * A callback function to gain complete control on when the responsive + * rule applies. Return `true` if it applies. This opens for checking + * against other metrics than the chart size, for example the document + * size or other elements. + * + * @type {Highcharts.ResponsiveCallbackFunction} + * @since 5.0.0 + * @context Highcharts.Chart + * @apioption responsive.rules.condition.callback + */ +/** + * The responsive rule applies if the chart height is less than this. + * + * @type {number} + * @since 5.0.0 + * @apioption responsive.rules.condition.maxHeight + */ +/** + * The responsive rule applies if the chart width is less than this. + * + * @sample highcharts/responsive/axis/ + * Max width is 500 + * + * @type {number} + * @since 5.0.0 + * @apioption responsive.rules.condition.maxWidth + */ +/** + * The responsive rule applies if the chart height is greater than this. + * + * @type {number} + * @default 0 + * @since 5.0.0 + * @apioption responsive.rules.condition.minHeight + */ +/** + * The responsive rule applies if the chart width is greater than this. + * + * @type {number} + * @default 0 + * @since 5.0.0 + * @apioption responsive.rules.condition.minWidth + */ +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * Update the chart based on the current chart/document size and options for + * responsiveness. + * + * @private + * @function Highcharts.Chart#setResponsive + * @param {boolean} [redraw=true] + * @param {boolean} [reset=false] + * Reset by un-applying all rules. Chart.update resets all rules before + * applying updated options. + * @return {void} + */ +Chart.prototype.setResponsive = function (redraw, reset) { + var options = this.options.responsive, ruleIds = [], currentResponsive = this.currentResponsive, currentRuleIds, undoOptions; + if (!reset && options && options.rules) { + options.rules.forEach(function (rule) { + if (typeof rule._id === 'undefined') { + rule._id = uniqueKey(); + } + this.matchResponsiveRule(rule, ruleIds /* , redraw */); + }, this); + } + // Merge matching rules + var mergedOptions = merge.apply(0, ruleIds.map(function (ruleId) { + return find(options.rules, function (rule) { + return rule._id === ruleId; + }).chartOptions; + })); + mergedOptions.isResponsiveOptions = true; + // Stringified key for the rules that currently apply. + ruleIds = (ruleIds.toString() || void 0); + currentRuleIds = currentResponsive && currentResponsive.ruleIds; + // Changes in what rules apply + if (ruleIds !== currentRuleIds) { + // Undo previous rules. Before we apply a new set of rules, we need to + // roll back completely to base options (#6291). + if (currentResponsive) { + this.update(currentResponsive.undoOptions, redraw, true); + } + if (ruleIds) { + // Get undo-options for matching rules + undoOptions = this.currentOptions(mergedOptions); + undoOptions.isResponsiveOptions = true; + this.currentResponsive = { + ruleIds: ruleIds, + mergedOptions: mergedOptions, + undoOptions: undoOptions + }; + this.update(mergedOptions, redraw, true); + } + else { + this.currentResponsive = void 0; + } + } +}; +/** + * Handle a single responsiveness rule. + * + * @private + * @function Highcharts.Chart#matchResponsiveRule + * @param {Highcharts.ResponsiveRulesOptions} rule + * @param {Array} matches + * @return {void} + */ +Chart.prototype.matchResponsiveRule = function (rule, matches) { + var condition = rule.condition, fn = condition.callback || function () { + return (this.chartWidth <= pick(condition.maxWidth, Number.MAX_VALUE) && + this.chartHeight <= + pick(condition.maxHeight, Number.MAX_VALUE) && + this.chartWidth >= pick(condition.minWidth, 0) && + this.chartHeight >= pick(condition.minHeight, 0)); + }; + if (fn.call(this)) { + matches.push(rule._id); + } +}; +/** + * Get the current values for a given set of options. Used before we update + * the chart with a new responsiveness rule. + * TODO: Restore axis options (by id?) + * + * @private + * @function Highcharts.Chart#currentOptions + * @param {Highcharts.Options} options + * @return {Highcharts.Options} + */ +Chart.prototype.currentOptions = function (options) { + var chart = this, ret = {}; + /** + * Recurse over a set of options and its current values, + * and store the current values in the ret object. + */ + function getCurrent(options, curr, ret, depth) { + var i; + objectEach(options, function (val, key) { + if (!depth && + chart.collectionsWithUpdate.indexOf(key) > -1) { + val = splat(val); + ret[key] = []; + // Iterate over collections like series, xAxis or yAxis and map + // the items by index. + for (i = 0; i < val.length; i++) { + if (curr[key][i]) { // Item exists in current data (#6347) + ret[key][i] = {}; + getCurrent(val[i], curr[key][i], ret[key][i], depth + 1); + } + } + } + else if (isObject(val)) { + ret[key] = isArray(val) ? [] : {}; + getCurrent(val, curr[key] || {}, ret[key], depth + 1); + } + else if (typeof curr[key] === 'undefined') { // #10286 + ret[key] = null; + } + else { + ret[key] = curr[key]; + } + }); + } + getCurrent(options, this.options, ret, 0); + return ret; +}; diff --git a/librerias/gantt/code/es-modules/parts/SVGElement.js b/librerias/gantt/code/es-modules/parts/SVGElement.js new file mode 100644 index 0000000..0cfdfb7 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/SVGElement.js @@ -0,0 +1,2049 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Color from './Color.js'; +import H from './Globals.js'; +var deg2rad = H.deg2rad, doc = H.doc, hasTouch = H.hasTouch, isFirefox = H.isFirefox, noop = H.noop, svg = H.svg, SVG_NS = H.SVG_NS, win = H.win; +import U from './Utilities.js'; +var animate = U.animate, animObject = U.animObject, attr = U.attr, createElement = U.createElement, css = U.css, defined = U.defined, erase = U.erase, extend = U.extend, fireEvent = U.fireEvent, inArray = U.inArray, isArray = U.isArray, isFunction = U.isFunction, isNumber = U.isNumber, isString = U.isString, merge = U.merge, objectEach = U.objectEach, pick = U.pick, pInt = U.pInt, stop = U.stop, uniqueKey = U.uniqueKey; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * The SVGElement prototype is a JavaScript wrapper for SVG elements used in the + * rendering layer of Highcharts. Combined with the + * {@link Highcharts.SVGRenderer} + * object, these prototypes allow freeform annotation in the charts or even in + * HTML pages without instanciating a chart. The SVGElement can also wrap HTML + * labels, when `text` or `label` elements are created with the `useHTML` + * parameter. + * + * The SVGElement instances are created through factory functions on the + * {@link Highcharts.SVGRenderer} + * object, like + * {@link Highcharts.SVGRenderer#rect|rect}, + * {@link Highcharts.SVGRenderer#path|path}, + * {@link Highcharts.SVGRenderer#text|text}, + * {@link Highcharts.SVGRenderer#label|label}, + * {@link Highcharts.SVGRenderer#g|g} + * and more. + * + * @class + * @name Highcharts.SVGElement + */ +var SVGElement = /** @class */ (function () { + function SVGElement() { + /* * + * + * Properties + * + * */ + this.element = void 0; + this.height = void 0; + this.opacity = 1; // Default base for animation + this.renderer = void 0; + this.SVG_NS = SVG_NS; + // Custom attributes used for symbols, these should be filtered out when + // setting SVGElement attributes (#9375). + this.symbolCustomAttribs = [ + 'x', + 'y', + 'width', + 'height', + 'r', + 'start', + 'end', + 'innerR', + 'anchorX', + 'anchorY', + 'rounded' + ]; + /** + * For labels, these CSS properties are applied to the `text` node directly. + * + * @private + * @name Highcharts.SVGElement#textProps + * @type {Array} + */ + this.textProps = [ + 'color', 'cursor', 'direction', 'fontFamily', 'fontSize', 'fontStyle', + 'fontWeight', 'lineHeight', 'textAlign', 'textDecoration', + 'textOutline', 'textOverflow', 'width' + ]; + this.width = void 0; + } + /* * + * + * Functions + * + * */ + /** + * Get the current value of an attribute or pseudo attribute, + * used mainly for animation. Called internally from + * the {@link Highcharts.SVGRenderer#attr} function. + * + * @private + * @function Highcharts.SVGElement#_defaultGetter + * + * @param {string} key + * Property key. + * + * @return {number|string} + * Property value. + */ + SVGElement.prototype._defaultGetter = function (key) { + var ret = pick(this[key + 'Value'], // align getter + this[key], this.element ? this.element.getAttribute(key) : null, 0); + if (/^[\-0-9\.]+$/.test(ret)) { // is numerical + ret = parseFloat(ret); + } + return ret; + }; + /** + * @private + * @function Highcharts.SVGElement#_defaultSetter + * + * @param {string} value + * + * @param {string} key + * + * @param {Highcharts.SVGDOMElement} element + * + * @return {void} + */ + SVGElement.prototype._defaultSetter = function (value, key, element) { + element.setAttribute(key, value); + }; + /** + * Add the element to the DOM. All elements must be added this way. + * + * @sample highcharts/members/renderer-g + * Elements added to a group + * + * @function Highcharts.SVGElement#add + * + * @param {Highcharts.SVGElement} [parent] + * The parent item to add it to. If undefined, the element is added + * to the {@link Highcharts.SVGRenderer.box}. + * + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.add = function (parent) { + var renderer = this.renderer, element = this.element, inserted; + if (parent) { + this.parentGroup = parent; + } + // mark as inverted + this.parentInverted = parent && parent.inverted; + // build formatted text + if (typeof this.textStr !== 'undefined') { + renderer.buildText(this); + } + // Mark as added + this.added = true; + // If we're adding to renderer root, or other elements in the group + // have a z index, we need to handle it + if (!parent || parent.handleZ || this.zIndex) { + inserted = this.zIndexSetter(); + } + // If zIndex is not handled, append at the end + if (!inserted) { + (parent ? + parent.element : + renderer.box).appendChild(element); + } + // fire an event for internal hooks + if (this.onAdd) { + this.onAdd(); + } + return this; + }; + /** + * Add a class name to an element. + * + * @function Highcharts.SVGElement#addClass + * + * @param {string} className + * The new class name to add. + * + * @param {boolean} [replace=false] + * When true, the existing class name(s) will be overwritten with the new + * one. When false, the new one is added. + * + * @return {Highcharts.SVGElement} + * Return the SVG element for chainability. + */ + SVGElement.prototype.addClass = function (className, replace) { + var currentClassName = replace ? '' : (this.attr('class') || ''); + // Trim the string and remove duplicates + className = (className || '') + .split(/ /g) + .reduce(function (newClassName, name) { + if (currentClassName.indexOf(name) === -1) { + newClassName.push(name); + } + return newClassName; + }, (currentClassName ? + [currentClassName] : + [])) + .join(' '); + if (className !== currentClassName) { + this.attr('class', className); + } + return this; + }; + /** + * This method is executed in the end of `attr()`, after setting all + * attributes in the hash. In can be used to efficiently consolidate + * multiple attributes in one SVG property -- e.g., translate, rotate and + * scale are merged in one "transform" attribute in the SVG node. + * + * @private + * @function Highcharts.SVGElement#afterSetters + */ + SVGElement.prototype.afterSetters = function () { + // Update transform. Do this outside the loop to prevent redundant + // updating for batch setting of attributes. + if (this.doTransform) { + this.updateTransform(); + this.doTransform = false; + } + }; + /** + * Align the element relative to the chart or another box. + * + * @function Highcharts.SVGElement#align + * + * @param {Highcharts.AlignObject} [alignOptions] + * The alignment options. The function can be called without this + * parameter in order to re-align an element after the box has been + * updated. + * + * @param {boolean} [alignByTranslate] + * Align element by translation. + * + * @param {string|Highcharts.BBoxObject} [box] + * The box to align to, needs a width and height. When the box is a + * string, it refers to an object in the Renderer. For example, when + * box is `spacingBox`, it refers to `Renderer.spacingBox` which + * holds `width`, `height`, `x` and `y` properties. + * + * @return {Highcharts.SVGElement} Returns the SVGElement for chaining. + */ + SVGElement.prototype.align = function (alignOptions, alignByTranslate, box) { + var align, vAlign, x, y, attribs = {}, alignTo, renderer = this.renderer, alignedObjects = renderer.alignedObjects, alignFactor, vAlignFactor; + // First call on instanciate + if (alignOptions) { + this.alignOptions = alignOptions; + this.alignByTranslate = alignByTranslate; + if (!box || isString(box)) { + this.alignTo = alignTo = box || 'renderer'; + // prevent duplicates, like legendGroup after resize + erase(alignedObjects, this); + alignedObjects.push(this); + box = void 0; // reassign it below + } + // When called on resize, no arguments are supplied + } + else { + alignOptions = this.alignOptions; + alignByTranslate = this.alignByTranslate; + alignTo = this.alignTo; + } + box = pick(box, renderer[alignTo], renderer); + // Assign variables + align = alignOptions.align; + vAlign = alignOptions.verticalAlign; + // default: left align + x = (box.x || 0) + (alignOptions.x || 0); + // default: top align + y = (box.y || 0) + (alignOptions.y || 0); + // Align + if (align === 'right') { + alignFactor = 1; + } + else if (align === 'center') { + alignFactor = 2; + } + if (alignFactor) { + x += (box.width - (alignOptions.width || 0)) / + alignFactor; + } + attribs[alignByTranslate ? 'translateX' : 'x'] = Math.round(x); + // Vertical align + if (vAlign === 'bottom') { + vAlignFactor = 1; + } + else if (vAlign === 'middle') { + vAlignFactor = 2; + } + if (vAlignFactor) { + y += (box.height - (alignOptions.height || 0)) / + vAlignFactor; + } + attribs[alignByTranslate ? 'translateY' : 'y'] = Math.round(y); + // Animate only if already placed + this[this.placed ? 'animate' : 'attr'](attribs); + this.placed = true; + this.alignAttr = attribs; + return this; + }; + /** + * @private + * @function Highcharts.SVGElement#alignSetter + * @param {"left"|"center"|"right"} value + */ + SVGElement.prototype.alignSetter = function (value) { + var convert = { + left: 'start', + center: 'middle', + right: 'end' + }; + if (convert[value]) { + this.alignValue = value; + this.element.setAttribute('text-anchor', convert[value]); + } + }; + /** + * Animate to given attributes or CSS properties. + * + * @sample highcharts/members/element-on/ + * Setting some attributes by animation + * + * @function Highcharts.SVGElement#animate + * + * @param {Highcharts.SVGAttributes} params + * SVG attributes or CSS to animate. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [options] + * Animation options. + * + * @param {Function} [complete] + * Function to perform at the end of animation. + * + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.animate = function (params, options, complete) { + var animOptions = animObject(pick(options, this.renderer.globalAnimation, true)); + // When the page is hidden save resources in the background by not + // running animation at all (#9749). + if (pick(doc.hidden, doc.msHidden, doc.webkitHidden, false)) { + animOptions.duration = 0; + } + if (animOptions.duration !== 0) { + // allows using a callback with the global animation without + // overwriting it + if (complete) { + animOptions.complete = complete; + } + animate(this, params, animOptions); + } + else { + this.attr(params, void 0, complete); + // Call the end step synchronously + objectEach(params, function (val, prop) { + if (animOptions.step) { + animOptions.step.call(this, val, { prop: prop, pos: 1 }); + } + }, this); + } + return this; + }; + /** + * Apply a text outline through a custom CSS property, by copying the text + * element and apply stroke to the copy. Used internally. Contrast checks at + * [example](https://jsfiddle.net/highcharts/43soe9m1/2/). + * + * @example + * // Specific color + * text.css({ + * textOutline: '1px black' + * }); + * // Automatic contrast + * text.css({ + * color: '#000000', // black text + * textOutline: '1px contrast' // => white outline + * }); + * + * @private + * @function Highcharts.SVGElement#applyTextOutline + * + * @param {string} textOutline + * A custom CSS `text-outline` setting, defined by `width color`. + */ + SVGElement.prototype.applyTextOutline = function (textOutline) { + var elem = this.element, tspans, hasContrast = textOutline.indexOf('contrast') !== -1, styles = {}, color, strokeWidth, firstRealChild; + // When the text shadow is set to contrast, use dark stroke for light + // text and vice versa. + if (hasContrast) { + styles.textOutline = textOutline = textOutline.replace(/contrast/g, this.renderer.getContrast(elem.style.fill)); + } + // Extract the stroke width and color + textOutline = textOutline.split(' '); + color = textOutline[textOutline.length - 1]; + strokeWidth = textOutline[0]; + if (strokeWidth && strokeWidth !== 'none' && H.svg) { + this.fakeTS = true; // Fake text shadow + tspans = [].slice.call(elem.getElementsByTagName('tspan')); + // In order to get the right y position of the clone, + // copy over the y setter + this.ySetter = this.xSetter; + // Since the stroke is applied on center of the actual outline, we + // need to double it to get the correct stroke-width outside the + // glyphs. + strokeWidth = strokeWidth.replace(/(^[\d\.]+)(.*?)$/g, function (match, digit, unit) { + return (2 * digit) + unit; + }); + // Remove shadows from previous runs. + this.removeTextOutline(tspans); + // Check if the element contains RTL characters. + // Comparing against Hebrew and Arabic characters, + // excluding Arabic digits. Source: + // https://www.unicode.org/Public/UNIDATA/extracted/DerivedBidiClass.txt + var isRTL_1 = elem.textContent ? + /^[\u0591-\u065F\u066A-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC]/ + .test(elem.textContent) : false; + // For each of the tspans, create a stroked copy behind it. + firstRealChild = elem.firstChild; + tspans.forEach(function (tspan, y) { + var clone; + // Let the first line start at the correct X position + if (y === 0) { + tspan.setAttribute('x', elem.getAttribute('x')); + y = elem.getAttribute('y'); + tspan.setAttribute('y', y || 0); + if (y === null) { + elem.setAttribute('y', 0); + } + } + // Create the clone and apply outline properties. + // For RTL elements apply outline properties for orginal element + // to prevent outline from overlapping the text. + // For RTL in Firefox keep the orginal order (#10162). + clone = tspan.cloneNode(true); + attr((isRTL_1 && !isFirefox) ? tspan : clone, { + 'class': 'highcharts-text-outline', + fill: color, + stroke: color, + 'stroke-width': strokeWidth, + 'stroke-linejoin': 'round' + }); + elem.insertBefore(clone, firstRealChild); + }); + // Create a whitespace between tspan and clone, + // to fix the display of Arabic characters in Firefox. + if (isRTL_1 && isFirefox && tspans[0]) { + var whitespace = tspans[0].cloneNode(true); + whitespace.textContent = ' '; + elem.insertBefore(whitespace, firstRealChild); + } + } + }; + /** + * @function Highcharts.SVGElement#attr + * @param {string} key + * @return {number|string} + */ /** + * Apply native and custom attributes to the SVG elements. + * + * In order to set the rotation center for rotation, set x and y to 0 and + * use `translateX` and `translateY` attributes to position the element + * instead. + * + * Attributes frequently used in Highcharts are `fill`, `stroke`, + * `stroke-width`. + * + * @sample highcharts/members/renderer-rect/ + * Setting some attributes + * + * @example + * // Set multiple attributes + * element.attr({ + * stroke: 'red', + * fill: 'blue', + * x: 10, + * y: 10 + * }); + * + * // Set a single attribute + * element.attr('stroke', 'red'); + * + * // Get an attribute + * element.attr('stroke'); // => 'red' + * + * @function Highcharts.SVGElement#attr + * + * @param {string|Highcharts.SVGAttributes} [hash] + * The native and custom SVG attributes. + * + * @param {number|string|Highcharts.SVGPathArray} [val] + * If the type of the first argument is `string`, the second can be a + * value, which will serve as a single attribute setter. If the first + * argument is a string and the second is undefined, the function + * serves as a getter and the current value of the property is + * returned. + * + * @param {Function} [complete] + * A callback function to execute after setting the attributes. This + * makes the function compliant and interchangeable with the + * {@link SVGElement#animate} function. + * + * @param {boolean} [continueAnimation=true] + * Used internally when `.attr` is called as part of an animation + * step. Otherwise, calling `.attr` for an attribute will stop + * animation for that attribute. + * + * @return {Highcharts.SVGElement} + * If used as a setter, it returns the current + * {@link Highcharts.SVGElement} so the calls can be chained. If + * used as a getter, the current value of the attribute is returned. + */ + SVGElement.prototype.attr = function (hash, val, complete, continueAnimation) { + var key, element = this.element, hasSetSymbolSize, ret = this, skipAttr, setter, symbolCustomAttribs = this.symbolCustomAttribs; + // single key-value pair + if (typeof hash === 'string' && typeof val !== 'undefined') { + key = hash; + hash = {}; + hash[key] = val; + } + // used as a getter: first argument is a string, second is undefined + if (typeof hash === 'string') { + ret = (this[hash + 'Getter'] || + this._defaultGetter).call(this, hash, element); + // setter + } + else { + objectEach(hash, function eachAttribute(val, key) { + skipAttr = false; + // Unless .attr is from the animator update, stop current + // running animation of this property + if (!continueAnimation) { + stop(this, key); + } + // Special handling of symbol attributes + if (this.symbolName && + inArray(key, symbolCustomAttribs) !== -1) { + if (!hasSetSymbolSize) { + this.symbolAttr(hash); + hasSetSymbolSize = true; + } + skipAttr = true; + } + if (this.rotation && (key === 'x' || key === 'y')) { + this.doTransform = true; + } + if (!skipAttr) { + setter = (this[key + 'Setter'] || + this._defaultSetter); + setter.call(this, val, key, element); + // Let the shadow follow the main element + if (!this.styledMode && + this.shadows && + /^(width|height|visibility|x|y|d|transform|cx|cy|r)$/.test(key)) { + this.updateShadows(key, val, setter); + } + } + }, this); + this.afterSetters(); + } + // In accordance with animate, run a complete callback + if (complete) { + complete.call(this); + } + return ret; + }; + /** + * Apply a clipping rectangle to this element. + * + * @function Highcharts.SVGElement#clip + * + * @param {Highcharts.ClipRectElement} [clipRect] + * The clipping rectangle. If skipped, the current clip is removed. + * + * @return {Highcharts.SVGElement} + * Returns the SVG element to allow chaining. + */ + SVGElement.prototype.clip = function (clipRect) { + return this.attr('clip-path', clipRect ? + 'url(' + this.renderer.url + '#' + clipRect.id + ')' : + 'none'); + }; + /** + * Calculate the coordinates needed for drawing a rectangle crisply and + * return the calculated attributes. + * + * @function Highcharts.SVGElement#crisp + * + * @param {Highcharts.RectangleObject} rect + * Rectangle to crisp. + * + * @param {number} [strokeWidth] + * The stroke width to consider when computing crisp positioning. It can + * also be set directly on the rect parameter. + * + * @return {Highcharts.RectangleObject} + * The modified rectangle arguments. + */ + SVGElement.prototype.crisp = function (rect, strokeWidth) { + var wrapper = this, normalizer; + strokeWidth = strokeWidth || rect.strokeWidth || 0; + // Math.round because strokeWidth can sometimes have roundoff errors + normalizer = Math.round(strokeWidth) % 2 / 2; + // normalize for crisp edges + rect.x = Math.floor(rect.x || wrapper.x || 0) + normalizer; + rect.y = Math.floor(rect.y || wrapper.y || 0) + normalizer; + rect.width = Math.floor((rect.width || wrapper.width || 0) - 2 * normalizer); + rect.height = Math.floor((rect.height || wrapper.height || 0) - 2 * normalizer); + if (defined(rect.strokeWidth)) { + rect.strokeWidth = strokeWidth; + } + return rect; + }; + /** + * Build and apply an SVG gradient out of a common JavaScript configuration + * object. This function is called from the attribute setters. An event + * hook is added for supporting other complex color types. + * + * @private + * @function Highcharts.SVGElement#complexColor + * + * @param {Highcharts.GradientColorObject|Highcharts.PatternObject} colorOptions + * The gradient or pattern options structure. + * + * @param {string} prop + * The property to apply, can either be `fill` or `stroke`. + * + * @param {Highcharts.SVGDOMElement} elem + * SVG element to apply the gradient on. + */ + SVGElement.prototype.complexColor = function (colorOptions, prop, elem) { + var renderer = this.renderer, colorObject, gradName, gradAttr, radAttr, gradients, stops, stopColor, stopOpacity, radialReference, id, key = [], value; + fireEvent(this.renderer, 'complexColor', { + args: arguments + }, function () { + // Apply linear or radial gradients + if (colorOptions.radialGradient) { + gradName = 'radialGradient'; + } + else if (colorOptions.linearGradient) { + gradName = 'linearGradient'; + } + if (gradName) { + gradAttr = colorOptions[gradName]; + gradients = renderer.gradients; + stops = colorOptions.stops; + radialReference = elem.radialReference; + // Keep < 2.2 kompatibility + if (isArray(gradAttr)) { + colorOptions[gradName] = gradAttr = { + x1: gradAttr[0], + y1: gradAttr[1], + x2: gradAttr[2], + y2: gradAttr[3], + gradientUnits: 'userSpaceOnUse' + }; + } + // Correct the radial gradient for the radial reference system + if (gradName === 'radialGradient' && + radialReference && + !defined(gradAttr.gradientUnits)) { + // Save the radial attributes for updating + radAttr = gradAttr; + gradAttr = merge(gradAttr, renderer.getRadialAttr(radialReference, radAttr), { gradientUnits: 'userSpaceOnUse' }); + } + // Build the unique key to detect whether we need to create a + // new element (#1282) + objectEach(gradAttr, function (val, n) { + if (n !== 'id') { + key.push(n, val); + } + }); + objectEach(stops, function (val) { + key.push(val); + }); + key = key.join(','); + // Check if a gradient object with the same config object is + // created within this renderer + if (gradients[key]) { + id = gradients[key].attr('id'); + } + else { + // Set the id and create the element + gradAttr.id = id = uniqueKey(); + var gradientObject_1 = gradients[key] = + renderer.createElement(gradName) + .attr(gradAttr) + .add(renderer.defs); + gradientObject_1.radAttr = radAttr; + // The gradient needs to keep a list of stops to be able to + // destroy them + gradientObject_1.stops = []; + stops.forEach(function (stop) { + var stopObject; + if (stop[1].indexOf('rgba') === 0) { + colorObject = Color.parse(stop[1]); + stopColor = colorObject.get('rgb'); + stopOpacity = colorObject.get('a'); + } + else { + stopColor = stop[1]; + stopOpacity = 1; + } + stopObject = renderer.createElement('stop').attr({ + offset: stop[0], + 'stop-color': stopColor, + 'stop-opacity': stopOpacity + }).add(gradientObject_1); + // Add the stop element to the gradient + gradientObject_1.stops.push(stopObject); + }); + } + // Set the reference to the gradient object + value = 'url(' + renderer.url + '#' + id + ')'; + elem.setAttribute(prop, value); + elem.gradient = key; + // Allow the color to be concatenated into tooltips formatters + // etc. (#2995) + colorOptions.toString = function () { + return value; + }; + } + }); + }; + /** + * Set styles for the element. In addition to CSS styles supported by + * native SVG and HTML elements, there are also some custom made for + * Highcharts, like `width`, `ellipsis` and `textOverflow` for SVG text + * elements. + * + * @sample highcharts/members/renderer-text-on-chart/ + * Styled text + * + * @function Highcharts.SVGElement#css + * + * @param {Highcharts.CSSObject} styles + * The new CSS styles. + * + * @return {Highcharts.SVGElement} + * Return the SVG element for chaining. + */ + SVGElement.prototype.css = function (styles) { + var oldStyles = this.styles, newStyles = {}, elem = this.element, textWidth, serializedCss = '', hyphenate, hasNew = !oldStyles, + // These CSS properties are interpreted internally by the SVG + // renderer, but are not supported by SVG and should not be added to + // the DOM. In styled mode, no CSS should find its way to the DOM + // whatsoever (#6173, #6474). + svgPseudoProps = ['textOutline', 'textOverflow', 'width']; + // convert legacy + if (styles && styles.color) { + styles.fill = styles.color; + } + // Filter out existing styles to increase performance (#2640) + if (oldStyles) { + objectEach(styles, function (style, n) { + if (oldStyles && oldStyles[n] !== style) { + newStyles[n] = style; + hasNew = true; + } + }); + } + if (hasNew) { + // Merge the new styles with the old ones + if (oldStyles) { + styles = extend(oldStyles, newStyles); + } + // Get the text width from style + if (styles) { + // Previously set, unset it (#8234) + if (styles.width === null || styles.width === 'auto') { + delete this.textWidth; + // Apply new + } + else if (elem.nodeName.toLowerCase() === 'text' && + styles.width) { + textWidth = this.textWidth = pInt(styles.width); + } + } + // store object + this.styles = styles; + if (textWidth && (!svg && this.renderer.forExport)) { + delete styles.width; + } + // Serialize and set style attribute + if (elem.namespaceURI === this.SVG_NS) { // #7633 + hyphenate = function (a, b) { + return '-' + b.toLowerCase(); + }; + objectEach(styles, function (style, n) { + if (svgPseudoProps.indexOf(n) === -1) { + serializedCss += + n.replace(/([A-Z])/g, hyphenate) + ':' + + style + ';'; + } + }); + if (serializedCss) { + attr(elem, 'style', serializedCss); // #1881 + } + } + else { + css(elem, styles); + } + if (this.added) { + // Rebuild text after added. Cache mechanisms in the buildText + // will prevent building if there are no significant changes. + if (this.element.nodeName === 'text') { + this.renderer.buildText(this); + } + // Apply text outline after added + if (styles && styles.textOutline) { + this.applyTextOutline(styles.textOutline); + } + } + } + return this; + }; + /** + * @private + * @function Highcharts.SVGElement#dashstyleSetter + * @param {string} value + */ + SVGElement.prototype.dashstyleSetter = function (value) { + var i, strokeWidth = this['stroke-width']; + // If "inherit", like maps in IE, assume 1 (#4981). With HC5 and the new + // strokeWidth function, we should be able to use that instead. + if (strokeWidth === 'inherit') { + strokeWidth = 1; + } + value = value && value.toLowerCase(); + if (value) { + var v = value + .replace('shortdashdotdot', '3,1,1,1,1,1,') + .replace('shortdashdot', '3,1,1,1') + .replace('shortdot', '1,1,') + .replace('shortdash', '3,1,') + .replace('longdash', '8,3,') + .replace(/dot/g, '1,3,') + .replace('dash', '4,3,') + .replace(/,$/, '') + .split(','); // ending comma + i = v.length; + while (i--) { + v[i] = '' + (pInt(v[i]) * pick(strokeWidth, NaN)); + } + value = v.join(',').replace(/NaN/g, 'none'); // #3226 + this.element.setAttribute('stroke-dasharray', value); + } + }; + /** + * Destroy the element and element wrapper and clear up the DOM and event + * hooks. + * + * @function Highcharts.SVGElement#destroy + */ + SVGElement.prototype.destroy = function () { + var wrapper = this, element = wrapper.element || {}, renderer = wrapper.renderer, parentToClean = (renderer.isSVG && + element.nodeName === 'SPAN' && + wrapper.parentGroup || + void 0), grandParent, ownerSVGElement = element.ownerSVGElement, i; + // remove events + element.onclick = element.onmouseout = element.onmouseover = + element.onmousemove = element.point = null; + stop(wrapper); // stop running animations + if (wrapper.clipPath && ownerSVGElement) { + var clipPath_1 = wrapper.clipPath; + // Look for existing references to this clipPath and remove them + // before destroying the element (#6196). + // The upper case version is for Edge + [].forEach.call(ownerSVGElement.querySelectorAll('[clip-path],[CLIP-PATH]'), function (el) { + var clipPathAttr = el.getAttribute('clip-path'); + if (clipPathAttr.indexOf(clipPath_1.element.id) > -1) { + el.removeAttribute('clip-path'); + } + }); + wrapper.clipPath = clipPath_1.destroy(); + } + // Destroy stops in case this is a gradient object @todo old code? + if (wrapper.stops) { + for (i = 0; i < wrapper.stops.length; i++) { + wrapper.stops[i].destroy(); + } + wrapper.stops.length = 0; + wrapper.stops = void 0; + } + // remove element + wrapper.safeRemoveChild(element); + if (!renderer.styledMode) { + wrapper.destroyShadows(); + } + // In case of useHTML, clean up empty containers emulating SVG groups + // (#1960, #2393, #2697). + while (parentToClean && + parentToClean.div && + parentToClean.div.childNodes.length === 0) { + grandParent = parentToClean.parentGroup; + wrapper.safeRemoveChild(parentToClean.div); + delete parentToClean.div; + parentToClean = grandParent; + } + // remove from alignObjects + if (wrapper.alignTo) { + erase(renderer.alignedObjects, wrapper); + } + objectEach(wrapper, function (val, key) { + // Destroy child elements of a group + if (wrapper[key] && + wrapper[key].parentGroup === wrapper && + wrapper[key].destroy) { + wrapper[key].destroy(); + } + // Delete all properties + delete wrapper[key]; + }); + return; + }; + /** + * Destroy shadows on the element. + * + * @private + * @function Highcharts.SVGElement#destroyShadows + * + * @return {void} + */ + SVGElement.prototype.destroyShadows = function () { + (this.shadows || []).forEach(function (shadow) { + this.safeRemoveChild(shadow); + }, this); + this.shadows = void 0; + }; + /** + * @private + */ + SVGElement.prototype.destroyTextPath = function (elem, path) { + var textElement = elem.getElementsByTagName('text')[0]; + var tspans; + if (textElement) { + // Remove textPath attributes + textElement.removeAttribute('dx'); + textElement.removeAttribute('dy'); + // Remove ID's: + path.element.setAttribute('id', ''); + // Check if textElement includes textPath, + if (this.textPathWrapper && + textElement.getElementsByTagName('textPath').length) { + // Move nodes to + tspans = this.textPathWrapper.element.childNodes; + // Now move all 's to the node + while (tspans.length) { + textElement.appendChild(tspans[0]); + } + // Remove from the DOM + textElement.removeChild(this.textPathWrapper.element); + } + } + else if (elem.getAttribute('dx') || elem.getAttribute('dy')) { + // Remove textPath attributes from elem + // to get correct text-outline position + elem.removeAttribute('dx'); + elem.removeAttribute('dy'); + } + if (this.textPathWrapper) { + // Set textPathWrapper to undefined and destroy it + this.textPathWrapper = this.textPathWrapper.destroy(); + } + }; + /** + * @private + * @function Highcharts.SVGElement#dSettter + * @param {number|string|Highcharts.SVGPathArray} value + * @param {string} key + * @param {Highcharts.SVGDOMElement} element + */ + SVGElement.prototype.dSetter = function (value, key, element) { + if (isArray(value)) { + // Backwards compatibility, convert one-dimensional array into an + // array of segments + if (typeof value[0] === 'string') { + value = this.renderer.pathToSegments(value); + } + this.pathArray = value; + value = value.reduce(function (acc, seg, i) { + if (!seg || !seg.join) { + return (seg || '').toString(); + } + return (i ? acc + ' ' : '') + seg.join(' '); + }, ''); + } + if (/(NaN| {2}|^$)/.test(value)) { + value = 'M 0 0'; + } + // Check for cache before resetting. Resetting causes disturbance in the + // DOM, causing flickering in some cases in Edge/IE (#6747). Also + // possible performance gain. + if (this[key] !== value) { + element.setAttribute(key, value); + this[key] = value; + } + }; + /** + * Fade out an element by animating its opacity down to 0, and hide it on + * complete. Used internally for the tooltip. + * + * @function Highcharts.SVGElement#fadeOut + * + * @param {number} [duration=150] + * The fade duration in milliseconds. + */ + SVGElement.prototype.fadeOut = function (duration) { + var elemWrapper = this; + elemWrapper.animate({ + opacity: 0 + }, { + duration: pick(duration, 150), + complete: function () { + // #3088, assuming we're only using this for tooltips + elemWrapper.attr({ y: -9999 }).hide(); + } + }); + }; + /** + * @private + * @function Highcharts.SVGElement#fillSetter + * @param {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} value + * @param {string} key + * @param {Highcharts.SVGDOMElement} element + */ + SVGElement.prototype.fillSetter = function (value, key, element) { + if (typeof value === 'string') { + element.setAttribute(key, value); + } + else if (value) { + this.complexColor(value, key, element); + } + }; + /** + * Get the bounding box (width, height, x and y) for the element. Generally + * used to get rendered text size. Since this is called a lot in charts, + * the results are cached based on text properties, in order to save DOM + * traffic. The returned bounding box includes the rotation, so for example + * a single text line of rotation 90 will report a greater height, and a + * width corresponding to the line-height. + * + * @sample highcharts/members/renderer-on-chart/ + * Draw a rectangle based on a text's bounding box + * + * @function Highcharts.SVGElement#getBBox + * + * @param {boolean} [reload] + * Skip the cache and get the updated DOM bouding box. + * + * @param {number} [rot] + * Override the element's rotation. This is internally used on axis + * labels with a value of 0 to find out what the bounding box would + * be have been if it were not rotated. + * + * @return {Highcharts.BBoxObject} + * The bounding box with `x`, `y`, `width` and `height` properties. + */ + SVGElement.prototype.getBBox = function (reload, rot) { + var wrapper = this, bBox, // = wrapper.bBox, + renderer = wrapper.renderer, width, height, element = wrapper.element, styles = wrapper.styles, fontSize, textStr = wrapper.textStr, toggleTextShadowShim, cache = renderer.cache, cacheKeys = renderer.cacheKeys, isSVG = element.namespaceURI === wrapper.SVG_NS, cacheKey; + var rotation = pick(rot, wrapper.rotation, 0); + fontSize = renderer.styledMode ? (element && + SVGElement.prototype.getStyle.call(element, 'font-size')) : (styles && styles.fontSize); + // Avoid undefined and null (#7316) + if (defined(textStr)) { + cacheKey = textStr.toString(); + // Since numbers are monospaced, and numerical labels appear a lot + // in a chart, we assume that a label of n characters has the same + // bounding box as others of the same length. Unless there is inner + // HTML in the label. In that case, leave the numbers as is (#5899). + if (cacheKey.indexOf('<') === -1) { + cacheKey = cacheKey.replace(/[0-9]/g, '0'); + } + // Properties that affect bounding box + cacheKey += [ + '', + rotation, + fontSize, + wrapper.textWidth, + styles && styles.textOverflow, + styles && styles.fontWeight // #12163 + ].join(','); + } + if (cacheKey && !reload) { + bBox = cache[cacheKey]; + } + // No cache found + if (!bBox) { + // SVG elements + if (isSVG || renderer.forExport) { + try { // Fails in Firefox if the container has display: none. + // When the text shadow shim is used, we need to hide the + // fake shadows to get the correct bounding box (#3872) + toggleTextShadowShim = this.fakeTS && function (display) { + [].forEach.call(element.querySelectorAll('.highcharts-text-outline'), function (tspan) { + tspan.style.display = display; + }); + }; + // Workaround for #3842, Firefox reporting wrong bounding + // box for shadows + if (isFunction(toggleTextShadowShim)) { + toggleTextShadowShim('none'); + } + bBox = element.getBBox ? + // SVG: use extend because IE9 is not allowed to change + // width and height in case of rotation (below) + extend({}, element.getBBox()) : { + // Legacy IE in export mode + width: element.offsetWidth, + height: element.offsetHeight + }; + // #3842 + if (isFunction(toggleTextShadowShim)) { + toggleTextShadowShim(''); + } + } + catch (e) { + ''; + } + // If the bBox is not set, the try-catch block above failed. The + // other condition is for Opera that returns a width of + // -Infinity on hidden elements. + if (!bBox || bBox.width < 0) { + bBox = { width: 0, height: 0 }; + } + // VML Renderer or useHTML within SVG + } + else { + bBox = wrapper.htmlGetBBox(); + } + // True SVG elements as well as HTML elements in modern browsers + // using the .useHTML option need to compensated for rotation + if (renderer.isSVG) { + width = bBox.width; + height = bBox.height; + // Workaround for wrong bounding box in IE, Edge and Chrome on + // Windows. With Highcharts' default font, IE and Edge report + // a box height of 16.899 and Chrome rounds it to 17. If this + // stands uncorrected, it results in more padding added below + // the text than above when adding a label border or background. + // Also vertical positioning is affected. + // https://jsfiddle.net/highcharts/em37nvuj/ + // (#1101, #1505, #1669, #2568, #6213). + if (isSVG) { + bBox.height = height = ({ + '11px,17': 14, + '13px,20': 16 + }[styles && + styles.fontSize + ',' + Math.round(height)] || + height); + } + // Adjust for rotated text + if (rotation) { + var rad = rotation * deg2rad; + bBox.width = Math.abs(height * Math.sin(rad)) + + Math.abs(width * Math.cos(rad)); + bBox.height = Math.abs(height * Math.cos(rad)) + + Math.abs(width * Math.sin(rad)); + } + } + // Cache it. When loading a chart in a hidden iframe in Firefox and + // IE/Edge, the bounding box height is 0, so don't cache it (#5620). + if (cacheKey && bBox.height > 0) { + // Rotate (#4681) + while (cacheKeys.length > 250) { + delete cache[cacheKeys.shift()]; + } + if (!cache[cacheKey]) { + cacheKeys.push(cacheKey); + } + cache[cacheKey] = bBox; + } + } + return bBox; + }; + /** + * Get the computed style. Only in styled mode. + * + * @example + * chart.series[0].points[0].graphic.getStyle('stroke-width'); // => '1px' + * + * @function Highcharts.SVGElement#getStyle + * + * @param {string} prop + * The property name to check for. + * + * @return {string} + * The current computed value. + */ + SVGElement.prototype.getStyle = function (prop) { + return win + .getComputedStyle(this.element || this, '') + .getPropertyValue(prop); + }; + /** + * Check if an element has the given class name. + * + * @function Highcharts.SVGElement#hasClass + * + * @param {string} className + * The class name to check for. + * + * @return {boolean} + * Whether the class name is found. + */ + SVGElement.prototype.hasClass = function (className) { + return ('' + this.attr('class')) + .split(' ') + .indexOf(className) !== -1; + }; + /** + * Hide the element, similar to setting the `visibility` attribute to + * `hidden`. + * + * @function Highcharts.SVGElement#hide + * + * @param {boolean} [hideByTranslation=false] + * The flag to determine if element should be hidden by moving out + * of the viewport. Used for example for dataLabels. + * + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.hide = function (hideByTranslation) { + if (hideByTranslation) { + this.attr({ y: -9999 }); + } + else { + this.attr({ visibility: 'hidden' }); + } + return this; + }; + /** + * @private + */ + SVGElement.prototype.htmlGetBBox = function () { + return { height: 0, width: 0, x: 0, y: 0 }; + }; + /** + * Initialize the SVG element. This function only exists to make the + * initialization process overridable. It should not be called directly. + * + * @function Highcharts.SVGElement#init + * + * @param {Highcharts.SVGRenderer} renderer + * The SVGRenderer instance to initialize to. + * + * @param {string} nodeName + * The SVG node name. + */ + SVGElement.prototype.init = function (renderer, nodeName) { + /** + * The primary DOM node. Each `SVGElement` instance wraps a main DOM + * node, but may also represent more nodes. + * + * @name Highcharts.SVGElement#element + * @type {Highcharts.SVGDOMElement|Highcharts.HTMLDOMElement} + */ + this.element = nodeName === 'span' ? + createElement(nodeName) : + doc.createElementNS(this.SVG_NS, nodeName); + /** + * The renderer that the SVGElement belongs to. + * + * @name Highcharts.SVGElement#renderer + * @type {Highcharts.SVGRenderer} + */ + this.renderer = renderer; + fireEvent(this, 'afterInit'); + }; + /** + * Invert a group, rotate and flip. This is used internally on inverted + * charts, where the points and graphs are drawn as if not inverted, then + * the series group elements are inverted. + * + * @function Highcharts.SVGElement#invert + * + * @param {boolean} inverted + * Whether to invert or not. An inverted shape can be un-inverted by + * setting it to false. + * + * @return {Highcharts.SVGElement} + * Return the SVGElement for chaining. + */ + SVGElement.prototype.invert = function (inverted) { + var wrapper = this; + wrapper.inverted = inverted; + wrapper.updateTransform(); + return wrapper; + }; + /** + * Add an event listener. This is a simple setter that replaces all other + * events of the same type, opposed to the {@link Highcharts#addEvent} + * function. + * + * @sample highcharts/members/element-on/ + * A clickable rectangle + * + * @function Highcharts.SVGElement#on + * + * @param {string} eventType + * The event type. If the type is `click`, Highcharts will internally + * translate it to a `touchstart` event on touch devices, to prevent the + * browser from waiting for a click event from firing. + * + * @param {Function} handler + * The handler callback. + * + * @return {Highcharts.SVGElement} + * The SVGElement for chaining. + */ + SVGElement.prototype.on = function (eventType, handler) { + var svgElement = this, element = svgElement.element, touchStartPos, touchEventFired; + // touch + if (hasTouch && eventType === 'click') { + element.ontouchstart = function (e) { + // save touch position for later calculation + touchStartPos = { + clientX: e.touches[0].clientX, + clientY: e.touches[0].clientY + }; + }; + // Instead of ontouchstart, event handlers should be called + // on touchend - similar to how current mouseup events are called + element.ontouchend = function (e) { + // hasMoved is a boolean variable containing logic if page + // was scrolled, so if touch position changed more than + // ~4px (value borrowed from general touch handler) + var hasMoved = touchStartPos.clientX ? Math.sqrt(Math.pow(touchStartPos.clientX - e.changedTouches[0].clientX, 2) + + Math.pow(touchStartPos.clientY - e.changedTouches[0].clientY, 2)) >= 4 : false; + if (!hasMoved) { // only call handlers if page was not scrolled + handler.call(element, e); + } + touchEventFired = true; + // prevent other events from being fired. #9682 + e.preventDefault(); + }; + element.onclick = function (e) { + // Do not call onclick handler if touch event was fired already. + if (!touchEventFired) { + handler.call(element, e); + } + }; + } + else { + // simplest possible event model for internal use + element['on' + eventType] = handler; + } + return this; + }; + /** + * @private + * @function Highcharts.SVGElement#opacitySetter + * @param {string} value + * @param {string} key + * @param {Highcharts.SVGDOMElement} element + */ + SVGElement.prototype.opacitySetter = function (value, key, element) { + this[key] = value; + element.setAttribute(key, value); + }; + /** + * Remove a class name from the element. + * + * @function Highcharts.SVGElement#removeClass + * + * @param {string|RegExp} className + * The class name to remove. + * + * @return {Highcharts.SVGElement} Returns the SVG element for chainability. + */ + SVGElement.prototype.removeClass = function (className) { + return this.attr('class', ('' + this.attr('class')).replace(isString(className) ? + new RegExp(" ?" + className + " ?") : // #12064 + className, '')); + }; + /** + * @private + * @param {Array} tspans + * Text spans. + */ + SVGElement.prototype.removeTextOutline = function (tspans) { + // Iterate from the end to + // support removing items inside the cycle (#6472). + var i = tspans.length, tspan; + while (i--) { + tspan = tspans[i]; + if (tspan.getAttribute('class') === 'highcharts-text-outline') { + // Remove then erase + erase(tspans, this.element.removeChild(tspan)); + } + } + }; + /** + * Removes an element from the DOM. + * + * @private + * @function Highcharts.SVGElement#safeRemoveChild + * + * @param {Highcharts.SVGDOMElement|Highcharts.HTMLDOMElement} element + * The DOM node to remove. + */ + SVGElement.prototype.safeRemoveChild = function (element) { + var parentNode = element.parentNode; + if (parentNode) { + parentNode.removeChild(element); + } + }; + /** + * Set the coordinates needed to draw a consistent radial gradient across + * a shape regardless of positioning inside the chart. Used on pie slices + * to make all the slices have the same radial reference point. + * + * @function Highcharts.SVGElement#setRadialReference + * + * @param {Array} coordinates + * The center reference. The format is `[centerX, centerY, diameter]` in + * pixels. + * + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.setRadialReference = function (coordinates) { + var existingGradient = (this.element.gradient && + this.renderer.gradients[this.element.gradient]); + this.element.radialReference = coordinates; + // On redrawing objects with an existing gradient, the gradient needs + // to be repositioned (#3801) + if (existingGradient && existingGradient.radAttr) { + existingGradient.animate(this.renderer.getRadialAttr(coordinates, existingGradient.radAttr)); + } + return this; + }; + /** + * @private + * @function Highcharts.SVGElement#setTextPath + * @param {Highcharts.SVGElement} path + * Path to follow. + * @param {Highcharts.DataLabelsTextPathOptionsObject} textPathOptions + * Options. + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.setTextPath = function (path, textPathOptions) { + var elem = this.element, attribsMap = { + textAnchor: 'text-anchor' + }, attrs, adder = false, textPathElement, textPathId, textPathWrapper = this.textPathWrapper, tspans, firstTime = !textPathWrapper; + // Defaults + textPathOptions = merge(true, { + enabled: true, + attributes: { + dy: -5, + startOffset: '50%', + textAnchor: 'middle' + } + }, textPathOptions); + attrs = textPathOptions.attributes; + if (path && textPathOptions && textPathOptions.enabled) { + // In case of fixed width for a text, string is rebuilt + // (e.g. ellipsis is applied), so we need to rebuild textPath too + if (textPathWrapper && + textPathWrapper.element.parentNode === null) { + // When buildText functionality was triggered again + // and deletes textPathWrapper parentNode + firstTime = true; + textPathWrapper = textPathWrapper.destroy(); + } + else if (textPathWrapper) { + // Case after drillup when spans were added into + // the DOM outside the textPathWrapper parentGroup + this.removeTextOutline.call(textPathWrapper.parentGroup, [].slice.call(elem.getElementsByTagName('tspan'))); + } + // label() has padding, text() doesn't + if (this.options && this.options.padding) { + attrs.dx = -this.options.padding; + } + if (!textPathWrapper) { + // Create , defer the DOM adder + this.textPathWrapper = textPathWrapper = + this.renderer.createElement('textPath'); + adder = true; + } + textPathElement = textPathWrapper.element; + // Set ID for the path + textPathId = path.element.getAttribute('id'); + if (!textPathId) { + path.element.setAttribute('id', textPathId = uniqueKey()); + } + // Change DOM structure, by placing tag in + if (firstTime) { + tspans = elem.getElementsByTagName('tspan'); + // Now move all 's to the node + while (tspans.length) { + // Remove "y" from tspans, as Firefox translates them + tspans[0].setAttribute('y', 0); + // Remove "x" from tspans + if (isNumber(attrs.dx)) { + tspans[0].setAttribute('x', -attrs.dx); + } + textPathElement.appendChild(tspans[0]); + } + } + // Add to the DOM + if (adder && + textPathWrapper) { + textPathWrapper.add({ + // label() is placed in a group, text() is standalone + element: this.text ? this.text.element : elem + }); + } + // Set basic options: + // Use `setAttributeNS` because Safari needs this.. + textPathElement.setAttributeNS('http://www.w3.org/1999/xlink', 'href', this.renderer.url + '#' + textPathId); + // Presentation attributes: + // dx/dy options must by set on (parent), + // the rest should be set on + if (defined(attrs.dy)) { + textPathElement.parentNode + .setAttribute('dy', attrs.dy); + delete attrs.dy; + } + if (defined(attrs.dx)) { + textPathElement.parentNode + .setAttribute('dx', attrs.dx); + delete attrs.dx; + } + // Additional attributes + objectEach(attrs, function (val, key) { + textPathElement.setAttribute(attribsMap[key] || key, val); + }); + // Remove translation, text that follows path does not need that + elem.removeAttribute('transform'); + // Remove shadows and text outlines + this.removeTextOutline.call(textPathWrapper, [].slice.call(elem.getElementsByTagName('tspan'))); + // Remove background and border for label(), see #10545 + // Alternatively, we can disable setting background rects in + // series.drawDataLabels() + if (this.text && !this.renderer.styledMode) { + this.attr({ + fill: 'none', + 'stroke-width': 0 + }); + } + // Disable some functions + this.updateTransform = noop; + this.applyTextOutline = noop; + } + else if (textPathWrapper) { + // Reset to prototype + delete this.updateTransform; + delete this.applyTextOutline; + // Restore DOM structure: + this.destroyTextPath(elem, path); + // Bring attributes back + this.updateTransform(); + // Set textOutline back for text() + if (this.options && this.options.rotation) { + this.applyTextOutline(this.options.style.textOutline); + } + } + return this; + }; + /** + * Add a shadow to the element. Must be called after the element is added to + * the DOM. In styled mode, this method is not used, instead use `defs` and + * filters. + * + * @example + * renderer.rect(10, 100, 100, 100) + * .attr({ fill: 'red' }) + * .shadow(true); + * + * @function Highcharts.SVGElement#shadow + * + * @param {boolean|Highcharts.ShadowOptionsObject} [shadowOptions] + * The shadow options. If `true`, the default options are applied. If + * `false`, the current shadow will be removed. + * + * @param {Highcharts.SVGElement} [group] + * The SVG group element where the shadows will be applied. The + * default is to add it to the same parent as the current element. + * Internally, this is ised for pie slices, where all the shadows are + * added to an element behind all the slices. + * + * @param {boolean} [cutOff] + * Used internally for column shadows. + * + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.shadow = function (shadowOptions, group, cutOff) { + var shadows = [], i, shadow, element = this.element, strokeWidth, shadowElementOpacity, update = false, oldShadowOptions = this.oldShadowOptions, + // compensate for inverted plot area + transform; + var defaultShadowOptions = { + color: '#000000', + offsetX: 1, + offsetY: 1, + opacity: 0.15, + width: 3 + }; + var options; + if (shadowOptions === true) { + options = defaultShadowOptions; + } + else if (typeof shadowOptions === 'object') { + options = extend(defaultShadowOptions, shadowOptions); + } + // Update shadow when options change (#12091). + if (options) { + // Go over each key to look for change + if (options && oldShadowOptions) { + objectEach(options, function (value, key) { + if (value !== oldShadowOptions[key]) { + update = true; + } + }); + } + if (update) { + this.destroyShadows(); + } + this.oldShadowOptions = options; + } + if (!options) { + this.destroyShadows(); + } + else if (!this.shadows) { + shadowElementOpacity = options.opacity / options.width; + transform = this.parentInverted ? + 'translate(-1,-1)' : + "translate(" + options.offsetX + ", " + options.offsetY + ")"; + for (i = 1; i <= options.width; i++) { + shadow = element.cloneNode(false); + strokeWidth = (options.width * 2) + 1 - (2 * i); + attr(shadow, { + stroke: (shadowOptions.color || + '#000000'), + 'stroke-opacity': shadowElementOpacity * i, + 'stroke-width': strokeWidth, + transform: transform, + fill: 'none' + }); + shadow.setAttribute('class', (shadow.getAttribute('class') || '') + ' highcharts-shadow'); + if (cutOff) { + attr(shadow, 'height', Math.max(attr(shadow, 'height') - strokeWidth, 0)); + shadow.cutHeight = strokeWidth; + } + if (group) { + group.element.appendChild(shadow); + } + else if (element.parentNode) { + element.parentNode.insertBefore(shadow, element); + } + shadows.push(shadow); + } + this.shadows = shadows; + } + return this; + }; + /** + * Show the element after it has been hidden. + * + * @function Highcharts.SVGElement#show + * + * @param {boolean} [inherit=false] + * Set the visibility attribute to `inherit` rather than `visible`. + * The difference is that an element with `visibility="visible"` + * will be visible even if the parent is hidden. + * + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.show = function (inherit) { + return this.attr({ visibility: inherit ? 'inherit' : 'visible' }); + }; + /** + * WebKit and Batik have problems with a stroke-width of zero, so in this + * case we remove the stroke attribute altogether. #1270, #1369, #3065, + * #3072. + * + * @private + * @function Highcharts.SVGElement#strokeSetter + * @param {number|string} value + * @param {string} key + * @param {Highcharts.SVGDOMElement} element + */ + SVGElement.prototype.strokeSetter = function (value, key, element) { + this[key] = value; + // Only apply the stroke attribute if the stroke width is defined and + // larger than 0 + if (this.stroke && this['stroke-width']) { + // Use prototype as instance may be overridden + SVGElement.prototype.fillSetter.call(this, this.stroke, 'stroke', element); + element.setAttribute('stroke-width', this['stroke-width']); + this.hasStroke = true; + } + else if (key === 'stroke-width' && value === 0 && this.hasStroke) { + element.removeAttribute('stroke'); + this.hasStroke = false; + } + else if (this.renderer.styledMode && this['stroke-width']) { + element.setAttribute('stroke-width', this['stroke-width']); + this.hasStroke = true; + } + }; + /** + * Get the computed stroke width in pixel values. This is used extensively + * when drawing shapes to ensure the shapes are rendered crisp and + * positioned correctly relative to each other. Using + * `shape-rendering: crispEdges` leaves us less control over positioning, + * for example when we want to stack columns next to each other, or position + * things pixel-perfectly within the plot box. + * + * The common pattern when placing a shape is: + * - Create the SVGElement and add it to the DOM. In styled mode, it will + * now receive a stroke width from the style sheet. In classic mode we + * will add the `stroke-width` attribute. + * - Read the computed `elem.strokeWidth()`. + * - Place it based on the stroke width. + * + * @function Highcharts.SVGElement#strokeWidth + * + * @return {number} + * The stroke width in pixels. Even if the given stroke widtch (in CSS or by + * attributes) is based on `em` or other units, the pixel size is returned. + */ + SVGElement.prototype.strokeWidth = function () { + // In non-styled mode, read the stroke width as set by .attr + if (!this.renderer.styledMode) { + return this['stroke-width'] || 0; + } + // In styled mode, read computed stroke width + var val = this.getStyle('stroke-width'), ret = 0, dummy; + // Read pixel values directly + if (val.indexOf('px') === val.length - 2) { + ret = pInt(val); + // Other values like em, pt etc need to be measured + } + else if (val !== '') { + dummy = doc.createElementNS(SVG_NS, 'rect'); + attr(dummy, { + width: val, + 'stroke-width': 0 + }); + this.element.parentNode.appendChild(dummy); + ret = dummy.getBBox().width; + dummy.parentNode.removeChild(dummy); + } + return ret; + }; + /** + * If one of the symbol size affecting parameters are changed, + * check all the others only once for each call to an element's + * .attr() method + * + * @private + * @function Highcharts.SVGElement#symbolAttr + * + * @param {Highcharts.SVGAttributes} hash + * The attributes to set. + */ + SVGElement.prototype.symbolAttr = function (hash) { + var wrapper = this; + [ + 'x', + 'y', + 'r', + 'start', + 'end', + 'width', + 'height', + 'innerR', + 'anchorX', + 'anchorY', + 'clockwise' + ].forEach(function (key) { + wrapper[key] = pick(hash[key], wrapper[key]); + }); + wrapper.attr({ + d: wrapper.renderer.symbols[wrapper.symbolName](wrapper.x, wrapper.y, wrapper.width, wrapper.height, wrapper) + }); + }; + /** + * @private + * @function Highcharts.SVGElement#textSetter + * @param {string} value + */ + SVGElement.prototype.textSetter = function (value) { + if (value !== this.textStr) { + // Delete size caches when the text changes + // delete this.bBox; // old code in series-label + delete this.textPxLength; + this.textStr = value; + if (this.added) { + this.renderer.buildText(this); + } + } + }; + /** + * @private + * @function Highcharts.SVGElement#titleSetter + * @param {string} value + */ + SVGElement.prototype.titleSetter = function (value) { + var titleNode = this.element.getElementsByTagName('title')[0]; + if (!titleNode) { + titleNode = doc.createElementNS(this.SVG_NS, 'title'); + this.element.appendChild(titleNode); + } + // Remove text content if it exists + if (titleNode.firstChild) { + titleNode.removeChild(titleNode.firstChild); + } + titleNode.appendChild(doc.createTextNode( + // #3276, #3895 + String(pick(value, '')) + .replace(/<[^>]*>/g, '') + .replace(/</g, '<') + .replace(/>/g, '>'))); + }; + /** + * Bring the element to the front. Alternatively, a new zIndex can be set. + * + * @sample highcharts/members/element-tofront/ + * Click an element to bring it to front + * + * @function Highcharts.SVGElement#toFront + * + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.toFront = function () { + var element = this.element; + element.parentNode.appendChild(element); + return this; + }; + /** + * Move an object and its children by x and y values. + * + * @function Highcharts.SVGElement#translate + * + * @param {number} x + * The x value. + * + * @param {number} y + * The y value. + * + * @return {Highcharts.SVGElement} + */ + SVGElement.prototype.translate = function (x, y) { + return this.attr({ + translateX: x, + translateY: y + }); + }; + /** + * Update the shadow elements with new attributes. + * + * @private + * @function Highcharts.SVGElement#updateShadows + * + * @param {string} key + * The attribute name. + * + * @param {number} value + * The value of the attribute. + * + * @param {Function} setter + * The setter function, inherited from the parent wrapper. + */ + SVGElement.prototype.updateShadows = function (key, value, setter) { + var shadows = this.shadows; + if (shadows) { + var i = shadows.length; + while (i--) { + setter.call(shadows[i], key === 'height' ? + Math.max(value - (shadows[i].cutHeight || 0), 0) : + key === 'd' ? this.d : value, key, shadows[i]); + } + } + }; + /** + * Update the transform attribute based on internal properties. Deals with + * the custom `translateX`, `translateY`, `rotation`, `scaleX` and `scaleY` + * attributes and updates the SVG `transform` attribute. + * + * @private + * @function Highcharts.SVGElement#updateTransform + */ + SVGElement.prototype.updateTransform = function () { + var wrapper = this, translateX = wrapper.translateX || 0, translateY = wrapper.translateY || 0, scaleX = wrapper.scaleX, scaleY = wrapper.scaleY, inverted = wrapper.inverted, rotation = wrapper.rotation, matrix = wrapper.matrix, element = wrapper.element, transform; + // Flipping affects translate as adjustment for flipping around the + // group's axis + if (inverted) { + translateX += wrapper.width; + translateY += wrapper.height; + } + // Apply translate. Nearly all transformed elements have translation, + // so instead of checking for translate = 0, do it always (#1767, + // #1846). + transform = ['translate(' + translateX + ',' + translateY + ')']; + // apply matrix + if (defined(matrix)) { + transform.push('matrix(' + matrix.join(',') + ')'); + } + // apply rotation + if (inverted) { + transform.push('rotate(90) scale(-1,1)'); + } + else if (rotation) { // text rotation + transform.push('rotate(' + rotation + ' ' + + pick(this.rotationOriginX, element.getAttribute('x'), 0) + + ' ' + + pick(this.rotationOriginY, element.getAttribute('y') || 0) + ')'); + } + // apply scale + if (defined(scaleX) || defined(scaleY)) { + transform.push('scale(' + pick(scaleX, 1) + ' ' + pick(scaleY, 1) + ')'); + } + if (transform.length) { + element.setAttribute('transform', transform.join(' ')); + } + }; + /** + * @private + * @function Highcharts.SVGElement#visibilitySetter + * + * @param {string} value + * + * @param {string} key + * + * @param {Highcharts.SVGDOMElement} element + * + * @return {void} + */ + SVGElement.prototype.visibilitySetter = function (value, key, element) { + // IE9-11 doesn't handle visibilty:inherit well, so we remove the + // attribute instead (#2881, #3909) + if (value === 'inherit') { + element.removeAttribute(key); + } + else if (this[key] !== value) { // #6747 + element.setAttribute(key, value); + } + this[key] = value; + }; + /** + * @private + * @function Highcharts.SVGElement#xGetter + * + * @param {string} key + * + * @return {number|string|null} + */ + SVGElement.prototype.xGetter = function (key) { + if (this.element.nodeName === 'circle') { + if (key === 'x') { + key = 'cx'; + } + else if (key === 'y') { + key = 'cy'; + } + } + return this._defaultGetter(key); + }; + /** + * @private + * @function Highcharts.SVGElement#zIndexSetter + * @param {number} [value] + * @param {string} [key] + * @return {boolean} + */ + SVGElement.prototype.zIndexSetter = function (value, key) { + var renderer = this.renderer, parentGroup = this.parentGroup, parentWrapper = parentGroup || renderer, parentNode = parentWrapper.element || renderer.box, childNodes, otherElement, otherZIndex, element = this.element, inserted = false, undefinedOtherZIndex, svgParent = parentNode === renderer.box, run = this.added, i; + if (defined(value)) { + // So we can read it for other elements in the group + element.setAttribute('data-z-index', value); + value = +value; + if (this[key] === value) { + // Only update when needed (#3865) + run = false; + } + } + else if (defined(this[key])) { + element.removeAttribute('data-z-index'); + } + this[key] = value; + // Insert according to this and other elements' zIndex. Before .add() is + // called, nothing is done. Then on add, or by later calls to + // zIndexSetter, the node is placed on the right place in the DOM. + if (run) { + value = this.zIndex; + if (value && parentGroup) { + parentGroup.handleZ = true; + } + childNodes = parentNode.childNodes; + for (i = childNodes.length - 1; i >= 0 && !inserted; i--) { + otherElement = childNodes[i]; + otherZIndex = otherElement.getAttribute('data-z-index'); + undefinedOtherZIndex = !defined(otherZIndex); + if (otherElement !== element) { + if ( + // Negative zIndex versus no zIndex: + // On all levels except the highest. If the parent is + // , then we don't want to put items before + // or + value < 0 && + undefinedOtherZIndex && + !svgParent && + !i) { + parentNode.insertBefore(element, childNodes[i]); + inserted = true; + } + else if ( + // Insert after the first element with a lower zIndex + pInt(otherZIndex) <= value || + // If negative zIndex, add this before first undefined + // zIndex element + (undefinedOtherZIndex && + (!defined(value) || value >= 0))) { + parentNode.insertBefore(element, childNodes[i + 1] || null // null for oldIE export + ); + inserted = true; + } + } + } + if (!inserted) { + parentNode.insertBefore(element, childNodes[svgParent ? 3 : 0] || null // null for oldIE + ); + inserted = true; + } + } + return inserted; + }; + return SVGElement; +}()); +// Some shared setters and getters +SVGElement.prototype['stroke-widthSetter'] = SVGElement.prototype.strokeSetter; +SVGElement.prototype.yGetter = SVGElement.prototype.xGetter; +SVGElement.prototype.matrixSetter = + SVGElement.prototype.rotationOriginXSetter = + SVGElement.prototype.rotationOriginYSetter = + SVGElement.prototype.rotationSetter = + SVGElement.prototype.scaleXSetter = + SVGElement.prototype.scaleYSetter = + SVGElement.prototype.translateXSetter = + SVGElement.prototype.translateYSetter = + SVGElement.prototype.verticalAlignSetter = function (value, key) { + this[key] = value; + this.doTransform = true; + }; +H.SVGElement = SVGElement; +export default H.SVGElement; diff --git a/librerias/gantt/code/es-modules/parts/ScatterSeries.js b/librerias/gantt/code/es-modules/parts/ScatterSeries.js new file mode 100644 index 0000000..3ad8448 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/ScatterSeries.js @@ -0,0 +1,252 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +import U from './Utilities.js'; +var addEvent = U.addEvent, seriesType = U.seriesType; +import './Options.js'; +import './Series.js'; +var Series = H.Series; +/** + * Scatter series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.scatter + * + * @augments Highcharts.Series + */ +seriesType('scatter', 'line', +/** + * A scatter plot uses cartesian coordinates to display values for two + * variables for a set of data. + * + * @sample {highcharts} highcharts/demo/scatter/ + * Scatter plot + * + * @extends plotOptions.line + * @excluding pointPlacement, shadow, useOhlcData + * @product highcharts highstock + * @optionparent plotOptions.scatter + */ +{ + /** + * The width of the line connecting the data points. + * + * @sample {highcharts} highcharts/plotoptions/scatter-linewidth-none/ + * 0 by default + * @sample {highcharts} highcharts/plotoptions/scatter-linewidth-1/ + * 1px + * + * @product highcharts highstock + */ + lineWidth: 0, + findNearestPointBy: 'xy', + /** + * Apply a jitter effect for the rendered markers. When plotting + * discrete values, a little random noise may help telling the points + * apart. The jitter setting applies a random displacement of up to `n` + * axis units in either direction. So for example on a horizontal X + * axis, setting the `jitter.x` to 0.24 will render the point in a + * random position between 0.24 units to the left and 0.24 units to the + * right of the true axis position. On a category axis, setting it to + * 0.5 will fill up the bin and make the data appear continuous. + * + * When rendered on top of a box plot or a column series, a jitter value + * of 0.24 will correspond to the underlying series' default + * [groupPadding]( + * https://api.highcharts.com/highcharts/plotOptions.column.groupPadding) + * and [pointPadding]( + * https://api.highcharts.com/highcharts/plotOptions.column.pointPadding) + * settings. + * + * @sample {highcharts} highcharts/series-scatter/jitter + * Jitter on a scatter plot + * + * @sample {highcharts} highcharts/series-scatter/jitter-boxplot + * Jittered scatter plot on top of a box plot + * + * @product highcharts highstock + * @since 7.0.2 + */ + jitter: { + /** + * The maximal X offset for the random jitter effect. + */ + x: 0, + /** + * The maximal Y offset for the random jitter effect. + */ + y: 0 + }, + marker: { + enabled: true // Overrides auto-enabling in line series (#3647) + }, + /** + * Sticky tracking of mouse events. When true, the `mouseOut` event + * on a series isn't triggered until the mouse moves over another + * series, or out of the plot area. When false, the `mouseOut` event on + * a series is triggered when the mouse leaves the area around the + * series' graph or markers. This also implies the tooltip. When + * `stickyTracking` is false and `tooltip.shared` is false, the tooltip + * will be hidden when moving the mouse between series. + * + * @type {boolean} + * @default false + * @product highcharts highstock + * @apioption plotOptions.scatter.stickyTracking + */ + /** + * A configuration object for the tooltip rendering of each single + * series. Properties are inherited from [tooltip](#tooltip). + * Overridable properties are `headerFormat`, `pointFormat`, + * `yDecimals`, `xDateFormat`, `yPrefix` and `ySuffix`. Unlike other + * series, in a scatter plot the series.name by default shows in the + * headerFormat and point.x and point.y in the pointFormat. + * + * @product highcharts highstock + */ + tooltip: { + headerFormat: '\u25CF ' + + ' {series.name}
', + pointFormat: 'x: {point.x}
y: {point.y}
' + } + // Prototype members +}, { + sorted: false, + requireSorting: false, + noSharedTooltip: true, + trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'], + takeOrdinalPosition: false, + /* eslint-disable valid-jsdoc */ + /** + * @private + * @function Highcharts.seriesTypes.scatter#drawGraph + */ + drawGraph: function () { + if (this.options.lineWidth) { + Series.prototype.drawGraph.call(this); + } + }, + // Optionally add the jitter effect + applyJitter: function () { + var series = this, jitter = this.options.jitter, len = this.points.length; + /** + * Return a repeatable, pseudo-random number based on an integer + * seed. + * @private + */ + function unrandom(seed) { + var rand = Math.sin(seed) * 10000; + return rand - Math.floor(rand); + } + if (jitter) { + this.points.forEach(function (point, i) { + ['x', 'y'].forEach(function (dim, j) { + var axis, plotProp = 'plot' + dim.toUpperCase(), min, max, translatedJitter; + if (jitter[dim] && !point.isNull) { + axis = series[dim + 'Axis']; + translatedJitter = + jitter[dim] * axis.transA; + if (axis && !axis.isLog) { + // Identify the outer bounds of the jitter range + min = Math.max(0, point[plotProp] - translatedJitter); + max = Math.min(axis.len, point[plotProp] + translatedJitter); + // Find a random position within this range + point[plotProp] = min + + (max - min) * unrandom(i + j * len); + // Update clientX for the tooltip k-d-tree + if (dim === 'x') { + point.clientX = point.plotX; + } + } + } + }); + }); + } + } + /* eslint-enable valid-jsdoc */ +}); +/* eslint-disable no-invalid-this */ +addEvent(Series, 'afterTranslate', function () { + if (this.applyJitter) { + this.applyJitter(); + } +}); +/* eslint-enable no-invalid-this */ +/** + * A `scatter` series. If the [type](#series.scatter.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.scatter + * @excluding dataParser, dataURL, useOhlcData + * @product highcharts highstock + * @apioption series.scatter + */ +/** + * An array of data points for the series. For the `scatter` series + * type, points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 0], + * [1, 8], + * [2, 9] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.scatter.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 2, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 4, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @product highcharts highstock + * @apioption series.scatter.data + */ +''; // adds doclets above to transpilat diff --git a/librerias/gantt/code/es-modules/parts/ScrollablePlotArea.js b/librerias/gantt/code/es-modules/parts/ScrollablePlotArea.js new file mode 100644 index 0000000..d7c707e --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/ScrollablePlotArea.js @@ -0,0 +1,357 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * Highcharts feature to make the Y axis stay fixed when scrolling the chart + * horizontally on mobile devices. Supports left and right side axes. + */ +/* +WIP on vertical scrollable plot area (#9378). To do: +- Bottom axis positioning +- Test with Gantt +- Look for size optimizing the code +- API and demos + */ +'use strict'; +import H from './Globals.js'; +import U from './Utilities.js'; +var addEvent = U.addEvent, createElement = U.createElement, pick = U.pick, stop = U.stop; +var Chart = H.Chart; +/** + * Options for a scrollable plot area. This feature provides a minimum size for + * the plot area of the chart. If the size gets smaller than this, typically + * on mobile devices, a native browser scrollbar is presented. This scrollbar + * provides smooth scrolling for the contents of the plot area, whereas the + * title, legend and unaffected axes are fixed. + * + * Since v7.1.2, a scrollable plot area can be defined for either horizontal or + * vertical scrolling, depending on whether the `minWidth` or `minHeight` + * option is set. + * + * @sample highcharts/chart/scrollable-plotarea + * Scrollable plot area + * @sample highcharts/chart/scrollable-plotarea-vertical + * Vertically scrollable plot area + * @sample {gantt} highcharts/chart/scrollable-plotarea-vertical + * Gantt chart with vertically scrollable plot area + * + * @since 6.1.0 + * @product highcharts gantt + * @apioption chart.scrollablePlotArea + */ +/** + * The minimum height for the plot area. If it gets smaller than this, the plot + * area will become scrollable. + * + * @type {number} + * @apioption chart.scrollablePlotArea.minHeight + */ +/** + * The minimum width for the plot area. If it gets smaller than this, the plot + * area will become scrollable. + * + * @type {number} + * @apioption chart.scrollablePlotArea.minWidth + */ +/** + * The initial scrolling position of the scrollable plot area. Ranges from 0 to + * 1, where 0 aligns the plot area to the left and 1 aligns it to the right. + * Typically we would use 1 if the chart has right aligned Y axes. + * + * @type {number} + * @apioption chart.scrollablePlotArea.scrollPositionX + */ +/** + * The initial scrolling position of the scrollable plot area. Ranges from 0 to + * 1, where 0 aligns the plot area to the top and 1 aligns it to the bottom. + * + * @type {number} + * @apioption chart.scrollablePlotArea.scrollPositionY + */ +/** + * The opacity of mask applied on one of the sides of the plot + * area. + * + * @sample {highcharts} highcharts/chart/scrollable-plotarea-opacity + * Disabled opacity for the mask + * + * @type {number} + * @default 0.85 + * @since 7.1.1 + * @apioption chart.scrollablePlotArea.opacity + */ +''; // detach API doclets +/* eslint-disable no-invalid-this, valid-jsdoc */ +addEvent(Chart, 'afterSetChartSize', function (e) { + var scrollablePlotArea = this.options.chart.scrollablePlotArea, scrollableMinWidth = scrollablePlotArea && scrollablePlotArea.minWidth, scrollableMinHeight = scrollablePlotArea && scrollablePlotArea.minHeight, scrollablePixelsX, scrollablePixelsY, corrections; + if (!this.renderer.forExport) { + // The amount of pixels to scroll, the difference between chart + // width and scrollable width + if (scrollableMinWidth) { + this.scrollablePixelsX = scrollablePixelsX = Math.max(0, scrollableMinWidth - this.chartWidth); + if (scrollablePixelsX) { + this.plotWidth += scrollablePixelsX; + if (this.inverted) { + this.clipBox.height += scrollablePixelsX; + this.plotBox.height += scrollablePixelsX; + } + else { + this.clipBox.width += scrollablePixelsX; + this.plotBox.width += scrollablePixelsX; + } + corrections = { + // Corrections for right side + 1: { name: 'right', value: scrollablePixelsX } + }; + } + // Currently we can only do either X or Y + } + else if (scrollableMinHeight) { + this.scrollablePixelsY = scrollablePixelsY = Math.max(0, scrollableMinHeight - this.chartHeight); + if (scrollablePixelsY) { + this.plotHeight += scrollablePixelsY; + if (this.inverted) { + this.clipBox.width += scrollablePixelsY; + this.plotBox.width += scrollablePixelsY; + } + else { + this.clipBox.height += scrollablePixelsY; + this.plotBox.height += scrollablePixelsY; + } + corrections = { + 2: { name: 'bottom', value: scrollablePixelsY } + }; + } + } + if (corrections && !e.skipAxes) { + this.axes.forEach(function (axis) { + // For right and bottom axes, only fix the plot line length + if (corrections[axis.side]) { + // Get the plot lines right in getPlotLinePath, + // temporarily set it to the adjusted plot width. + axis.getPlotLinePath = function () { + var marginName = corrections[axis.side].name, correctionValue = corrections[axis.side].value, + // axis.right or axis.bottom + margin = this[marginName], path; + // Temporarily adjust + this[marginName] = margin - correctionValue; + path = H.Axis.prototype.getPlotLinePath.apply(this, arguments); + // Reset + this[marginName] = margin; + return path; + }; + } + else { + // Apply the corrected plotWidth + axis.setAxisSize(); + axis.setAxisTranslation(); + } + }); + } + } +}); +addEvent(Chart, 'render', function () { + if (this.scrollablePixelsX || this.scrollablePixelsY) { + if (this.setUpScrolling) { + this.setUpScrolling(); + } + this.applyFixed(); + } + else if (this.fixedDiv) { // Has been in scrollable mode + this.applyFixed(); + } +}); +/** + * @private + * @function Highcharts.Chart#setUpScrolling + * @return {void} + */ +Chart.prototype.setUpScrolling = function () { + var _this = this; + var attribs = { + WebkitOverflowScrolling: 'touch', + overflowX: 'hidden', + overflowY: 'hidden' + }; + if (this.scrollablePixelsX) { + attribs.overflowX = 'auto'; + } + if (this.scrollablePixelsY) { + attribs.overflowY = 'auto'; + } + // Add the necessary divs to provide scrolling + this.scrollingContainer = createElement('div', { + 'className': 'highcharts-scrolling' + }, attribs, this.renderTo); + // On scroll, reset the chart position because it applies to the scrolled + // container + addEvent(this.scrollingContainer, 'scroll', function () { + if (_this.pointer) { + delete _this.pointer.chartPosition; + } + }); + this.innerContainer = createElement('div', { + 'className': 'highcharts-inner-container' + }, null, this.scrollingContainer); + // Now move the container inside + this.innerContainer.appendChild(this.container); + // Don't run again + this.setUpScrolling = null; +}; +/** + * These elements are moved over to the fixed renderer and stay fixed when the + * user scrolls the chart + * @private + */ +Chart.prototype.moveFixedElements = function () { + var container = this.container, fixedRenderer = this.fixedRenderer, fixedSelectors = [ + '.highcharts-contextbutton', + '.highcharts-credits', + '.highcharts-legend', + '.highcharts-legend-checkbox', + '.highcharts-navigator-series', + '.highcharts-navigator-xaxis', + '.highcharts-navigator-yaxis', + '.highcharts-navigator', + '.highcharts-reset-zoom', + '.highcharts-scrollbar', + '.highcharts-subtitle', + '.highcharts-title' + ], axisClass; + if (this.scrollablePixelsX && !this.inverted) { + axisClass = '.highcharts-yaxis'; + } + else if (this.scrollablePixelsX && this.inverted) { + axisClass = '.highcharts-xaxis'; + } + else if (this.scrollablePixelsY && !this.inverted) { + axisClass = '.highcharts-xaxis'; + } + else if (this.scrollablePixelsY && this.inverted) { + axisClass = '.highcharts-yaxis'; + } + fixedSelectors.push(axisClass, axisClass + '-labels'); + fixedSelectors.forEach(function (className) { + [].forEach.call(container.querySelectorAll(className), function (elem) { + (elem.namespaceURI === fixedRenderer.SVG_NS ? + fixedRenderer.box : + fixedRenderer.box.parentNode).appendChild(elem); + elem.style.pointerEvents = 'auto'; + }); + }); +}; +/** + * @private + * @function Highcharts.Chart#applyFixed + * @return {void} + */ +Chart.prototype.applyFixed = function () { + var _a; + var fixedRenderer, scrollableWidth, scrollableHeight, firstTime = !this.fixedDiv, scrollableOptions = this.options.chart.scrollablePlotArea; + // First render + if (firstTime) { + this.fixedDiv = createElement('div', { + className: 'highcharts-fixed' + }, { + position: 'absolute', + overflow: 'hidden', + pointerEvents: 'none', + zIndex: 2 + }, null, true); + this.renderTo.insertBefore(this.fixedDiv, this.renderTo.firstChild); + this.renderTo.style.overflow = 'visible'; + this.fixedRenderer = fixedRenderer = new H.Renderer(this.fixedDiv, this.chartWidth, this.chartHeight, (_a = this.options.chart) === null || _a === void 0 ? void 0 : _a.style); + // Mask + this.scrollableMask = fixedRenderer + .path() + .attr({ + fill: this.options.chart.backgroundColor || '#fff', + 'fill-opacity': pick(scrollableOptions.opacity, 0.85), + zIndex: -1 + }) + .addClass('highcharts-scrollable-mask') + .add(); + this.moveFixedElements(); + addEvent(this, 'afterShowResetZoom', this.moveFixedElements); + addEvent(this, 'afterLayOutTitles', this.moveFixedElements); + } + else { + // Set the size of the fixed renderer to the visible width + this.fixedRenderer.setSize(this.chartWidth, this.chartHeight); + } + // Increase the size of the scrollable renderer and background + scrollableWidth = this.chartWidth + (this.scrollablePixelsX || 0); + scrollableHeight = this.chartHeight + (this.scrollablePixelsY || 0); + stop(this.container); + this.container.style.width = scrollableWidth + 'px'; + this.container.style.height = scrollableHeight + 'px'; + this.renderer.boxWrapper.attr({ + width: scrollableWidth, + height: scrollableHeight, + viewBox: [0, 0, scrollableWidth, scrollableHeight].join(' ') + }); + this.chartBackground.attr({ + width: scrollableWidth, + height: scrollableHeight + }); + this.scrollingContainer.style.height = this.chartHeight + 'px'; + // Set scroll position + if (firstTime) { + if (scrollableOptions.scrollPositionX) { + this.scrollingContainer.scrollLeft = + this.scrollablePixelsX * + scrollableOptions.scrollPositionX; + } + if (scrollableOptions.scrollPositionY) { + this.scrollingContainer.scrollTop = + this.scrollablePixelsY * + scrollableOptions.scrollPositionY; + } + } + // Mask behind the left and right side + var axisOffset = this.axisOffset, maskTop = this.plotTop - axisOffset[0] - 1, maskLeft = this.plotLeft - axisOffset[3] - 1, maskBottom = this.plotTop + this.plotHeight + axisOffset[2] + 1, maskRight = this.plotLeft + this.plotWidth + axisOffset[1] + 1, maskPlotRight = this.plotLeft + this.plotWidth - + (this.scrollablePixelsX || 0), maskPlotBottom = this.plotTop + this.plotHeight - + (this.scrollablePixelsY || 0), d; + if (this.scrollablePixelsX) { + d = [ + // Left side + ['M', 0, maskTop], + ['L', this.plotLeft - 1, maskTop], + ['L', this.plotLeft - 1, maskBottom], + ['L', 0, maskBottom], + ['Z'], + // Right side + ['M', maskPlotRight, maskTop], + ['L', this.chartWidth, maskTop], + ['L', this.chartWidth, maskBottom], + ['L', maskPlotRight, maskBottom], + ['Z'] + ]; + } + else if (this.scrollablePixelsY) { + d = [ + // Top side + ['M', maskLeft, 0], + ['L', maskLeft, this.plotTop - 1], + ['L', maskRight, this.plotTop - 1], + ['L', maskRight, 0], + ['Z'], + // Bottom side + ['M', maskLeft, maskPlotBottom], + ['L', maskLeft, this.chartHeight], + ['L', maskRight, this.chartHeight], + ['L', maskRight, maskPlotBottom], + ['Z'] + ]; + } + else { + d = [['M', 0, 0]]; + } + if (this.redrawTrigger !== 'adjustHeight') { + this.scrollableMask.attr({ d: d }); + } +}; diff --git a/librerias/gantt/code/es-modules/parts/Scrollbar.js b/librerias/gantt/code/es-modules/parts/Scrollbar.js new file mode 100644 index 0000000..2375f6a --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/Scrollbar.js @@ -0,0 +1,812 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Axis from './Axis.js'; +import H from './Globals.js'; +import ScrollbarAxis from './ScrollbarAxis.js'; +import U from './Utilities.js'; +var addEvent = U.addEvent, correctFloat = U.correctFloat, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, fireEvent = U.fireEvent, merge = U.merge, pick = U.pick, removeEvent = U.removeEvent; +import './Options.js'; +var defaultOptions = H.defaultOptions, hasTouch = H.hasTouch, isTouchDevice = H.isTouchDevice; +/** + * When we have vertical scrollbar, rifles and arrow in buttons should be + * rotated. The same method is used in Navigator's handles, to rotate them. + * + * @function Highcharts.swapXY + * + * @param {Highcharts.SVGPathArray} path + * Path to be rotated. + * + * @param {boolean} [vertical] + * If vertical scrollbar, swap x-y values. + * + * @return {Highcharts.SVGPathArray} + * Rotated path. + * + * @requires modules/stock + */ +var swapXY = H.swapXY = function (path, vertical) { + if (vertical) { + path.forEach(function (seg) { + var len = seg.length; + var temp; + for (var i = 0; i < len; i += 2) { + temp = seg[i + 1]; + if (typeof temp === 'number') { + seg[i + 1] = seg[i + 2]; + seg[i + 2] = temp; + } + } + }); + } + return path; +}; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * A reusable scrollbar, internally used in Highstock's navigator and optionally + * on individual axes. + * + * @private + * @class + * @name Highcharts.Scrollbar + * @param {Highcharts.SVGRenderer} renderer + * @param {Highcharts.ScrollbarOptions} options + * @param {Highcharts.Chart} chart + */ +var Scrollbar = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Scrollbar(renderer, options, chart) { + /* * + * + * Properties + * + * */ + this._events = []; + this.chartX = 0; + this.chartY = 0; + this.from = 0; + this.group = void 0; + this.scrollbar = void 0; + this.scrollbarButtons = []; + this.scrollbarGroup = void 0; + this.scrollbarLeft = 0; + this.scrollbarRifles = void 0; + this.scrollbarStrokeWidth = 1; + this.scrollbarTop = 0; + this.size = 0; + this.to = 0; + this.track = void 0; + this.trackBorderWidth = 1; + this.userOptions = {}; + this.x = 0; + this.y = 0; + this.chart = chart; + this.options = options; + this.renderer = chart.renderer; + this.init(renderer, options, chart); + } + /* * + * + * Functions + * + * */ + /** + * Set up the mouse and touch events for the Scrollbar + * + * @private + * @function Highcharts.Scrollbar#addEvents + * @return {void} + */ + Scrollbar.prototype.addEvents = function () { + var buttonsOrder = this.options.inverted ? [1, 0] : [0, 1], buttons = this.scrollbarButtons, bar = this.scrollbarGroup.element, track = this.track.element, mouseDownHandler = this.mouseDownHandler.bind(this), mouseMoveHandler = this.mouseMoveHandler.bind(this), mouseUpHandler = this.mouseUpHandler.bind(this), _events; + // Mouse events + _events = [ + [buttons[buttonsOrder[0]].element, 'click', this.buttonToMinClick.bind(this)], + [buttons[buttonsOrder[1]].element, 'click', this.buttonToMaxClick.bind(this)], + [track, 'click', this.trackClick.bind(this)], + [bar, 'mousedown', mouseDownHandler], + [bar.ownerDocument, 'mousemove', mouseMoveHandler], + [bar.ownerDocument, 'mouseup', mouseUpHandler] + ]; + // Touch events + if (hasTouch) { + _events.push([bar, 'touchstart', mouseDownHandler], [bar.ownerDocument, 'touchmove', mouseMoveHandler], [bar.ownerDocument, 'touchend', mouseUpHandler]); + } + // Add them all + _events.forEach(function (args) { + addEvent.apply(null, args); + }); + this._events = _events; + }; + Scrollbar.prototype.buttonToMaxClick = function (e) { + var scroller = this; + var range = (scroller.to - scroller.from) * pick(scroller.options.step, 0.2); + scroller.updatePosition(scroller.from + range, scroller.to + range); + fireEvent(scroller, 'changed', { + from: scroller.from, + to: scroller.to, + trigger: 'scrollbar', + DOMEvent: e + }); + }; + Scrollbar.prototype.buttonToMinClick = function (e) { + var scroller = this; + var range = correctFloat(scroller.to - scroller.from) * + pick(scroller.options.step, 0.2); + scroller.updatePosition(correctFloat(scroller.from - range), correctFloat(scroller.to - range)); + fireEvent(scroller, 'changed', { + from: scroller.from, + to: scroller.to, + trigger: 'scrollbar', + DOMEvent: e + }); + }; + /** + * Get normalized (0-1) cursor position over the scrollbar + * + * @private + * @function Highcharts.Scrollbar#cursorToScrollbarPosition + * + * @param {*} normalizedEvent + * normalized event, with chartX and chartY values + * + * @return {Highcharts.Dictionary} + * Local position {chartX, chartY} + */ + Scrollbar.prototype.cursorToScrollbarPosition = function (normalizedEvent) { + var scroller = this, options = scroller.options, minWidthDifference = options.minWidth > scroller.calculatedWidth ? + options.minWidth : + 0; // minWidth distorts translation + return { + chartX: (normalizedEvent.chartX - scroller.x - + scroller.xOffset) / + (scroller.barWidth - minWidthDifference), + chartY: (normalizedEvent.chartY - scroller.y - + scroller.yOffset) / + (scroller.barWidth - minWidthDifference) + }; + }; + /** + * Destroys allocated elements. + * + * @private + * @function Highcharts.Scrollbar#destroy + * @return {void} + */ + Scrollbar.prototype.destroy = function () { + var scroller = this.chart.scroller; + // Disconnect events added in addEvents + this.removeEvents(); + // Destroy properties + [ + 'track', + 'scrollbarRifles', + 'scrollbar', + 'scrollbarGroup', + 'group' + ].forEach(function (prop) { + if (this[prop] && this[prop].destroy) { + this[prop] = this[prop].destroy(); + } + }, this); + // #6421, chart may have more scrollbars + if (scroller && this === scroller.scrollbar) { + scroller.scrollbar = null; + // Destroy elements in collection + destroyObjectProperties(scroller.scrollbarButtons); + } + }; + /** + * Draw the scrollbar buttons with arrows + * + * @private + * @function Highcharts.Scrollbar#drawScrollbarButton + * @param {number} index + * 0 is left, 1 is right + * @return {void} + */ + Scrollbar.prototype.drawScrollbarButton = function (index) { + var scroller = this, renderer = scroller.renderer, scrollbarButtons = scroller.scrollbarButtons, options = scroller.options, size = scroller.size, group, tempElem; + group = renderer.g().add(scroller.group); + scrollbarButtons.push(group); + // Create a rectangle for the scrollbar button + tempElem = renderer.rect() + .addClass('highcharts-scrollbar-button') + .add(group); + // Presentational attributes + if (!this.chart.styledMode) { + tempElem.attr({ + stroke: options.buttonBorderColor, + 'stroke-width': options.buttonBorderWidth, + fill: options.buttonBackgroundColor + }); + } + // Place the rectangle based on the rendered stroke width + tempElem.attr(tempElem.crisp({ + x: -0.5, + y: -0.5, + width: size + 1, + height: size + 1, + r: options.buttonBorderRadius + }, tempElem.strokeWidth())); + // Button arrow + tempElem = renderer + .path(swapXY([[ + 'M', + size / 2 + (index ? -1 : 1), + size / 2 - 3 + ], [ + 'L', + size / 2 + (index ? -1 : 1), + size / 2 + 3 + ], [ + 'L', + size / 2 + (index ? 2 : -2), + size / 2 + ]], options.vertical)) + .addClass('highcharts-scrollbar-arrow') + .add(scrollbarButtons[index]); + if (!this.chart.styledMode) { + tempElem.attr({ + fill: options.buttonArrowColor + }); + } + }; + /** + * @private + * @function Highcharts.Scrollbar#init + * @param {Highcharts.SVGRenderer} renderer + * @param {Highcharts.ScrollbarOptions} options + * @param {Highcharts.Chart} chart + */ + Scrollbar.prototype.init = function (renderer, options, chart) { + this.scrollbarButtons = []; + this.renderer = renderer; + this.userOptions = options; + this.options = merge(Scrollbar.defaultOptions, options); + this.chart = chart; + // backward compatibility + this.size = pick(this.options.size, this.options.height); + // Init + if (options.enabled) { + this.render(); + this.addEvents(); + } + }; + Scrollbar.prototype.mouseDownHandler = function (e) { + var scroller = this; + var normalizedEvent = scroller.chart.pointer.normalize(e), mousePosition = scroller.cursorToScrollbarPosition(normalizedEvent); + scroller.chartX = mousePosition.chartX; + scroller.chartY = mousePosition.chartY; + scroller.initPositions = [scroller.from, scroller.to]; + scroller.grabbedCenter = true; + }; + /** + * Event handler for the mouse move event. + * @private + */ + Scrollbar.prototype.mouseMoveHandler = function (e) { + var scroller = this; + var normalizedEvent = scroller.chart.pointer.normalize(e), options = scroller.options, direction = options.vertical ? 'chartY' : 'chartX', initPositions = scroller.initPositions || [], scrollPosition, chartPosition, change; + // In iOS, a mousemove event with e.pageX === 0 is fired when + // holding the finger down in the center of the scrollbar. This + // should be ignored. + if (scroller.grabbedCenter && + // #4696, scrollbar failed on Android + (!e.touches || e.touches[0][direction] !== 0)) { + chartPosition = scroller.cursorToScrollbarPosition(normalizedEvent)[direction]; + scrollPosition = scroller[direction]; + change = chartPosition - scrollPosition; + scroller.hasDragged = true; + scroller.updatePosition(initPositions[0] + change, initPositions[1] + change); + if (scroller.hasDragged) { + fireEvent(scroller, 'changed', { + from: scroller.from, + to: scroller.to, + trigger: 'scrollbar', + DOMType: e.type, + DOMEvent: e + }); + } + } + }; + /** + * Event handler for the mouse up event. + * @private + */ + Scrollbar.prototype.mouseUpHandler = function (e) { + var scroller = this; + if (scroller.hasDragged) { + fireEvent(scroller, 'changed', { + from: scroller.from, + to: scroller.to, + trigger: 'scrollbar', + DOMType: e.type, + DOMEvent: e + }); + } + scroller.grabbedCenter = + scroller.hasDragged = + scroller.chartX = + scroller.chartY = null; + }; + /** + * Position the scrollbar, method called from a parent with defined + * dimensions. + * + * @private + * @function Highcharts.Scrollbar#position + * @param {number} x + * x-position on the chart + * @param {number} y + * y-position on the chart + * @param {number} width + * width of the scrollbar + * @param {number} height + * height of the scorllbar + * @return {void} + */ + Scrollbar.prototype.position = function (x, y, width, height) { + var scroller = this, options = scroller.options, vertical = options.vertical, xOffset = height, yOffset = 0, method = scroller.rendered ? 'animate' : 'attr'; + scroller.x = x; + scroller.y = y + this.trackBorderWidth; + scroller.width = width; // width with buttons + scroller.height = height; + scroller.xOffset = xOffset; + scroller.yOffset = yOffset; + // If Scrollbar is a vertical type, swap options: + if (vertical) { + scroller.width = scroller.yOffset = width = yOffset = scroller.size; + scroller.xOffset = xOffset = 0; + scroller.barWidth = height - width * 2; // width without buttons + scroller.x = x = x + scroller.options.margin; + } + else { + scroller.height = scroller.xOffset = height = xOffset = + scroller.size; + scroller.barWidth = width - height * 2; // width without buttons + scroller.y = scroller.y + scroller.options.margin; + } + // Set general position for a group: + scroller.group[method]({ + translateX: x, + translateY: scroller.y + }); + // Resize background/track: + scroller.track[method]({ + width: width, + height: height + }); + // Move right/bottom button ot it's place: + scroller.scrollbarButtons[1][method]({ + translateX: vertical ? 0 : width - xOffset, + translateY: vertical ? height - yOffset : 0 + }); + }; + /** + * Removes the event handlers attached previously with addEvents. + * + * @private + * @function Highcharts.Scrollbar#removeEvents + * @return {void} + */ + Scrollbar.prototype.removeEvents = function () { + this._events.forEach(function (args) { + removeEvent.apply(null, args); + }); + this._events.length = 0; + }; + /** + * Render scrollbar with all required items. + * + * @private + * @function Highcharts.Scrollbar#render + */ + Scrollbar.prototype.render = function () { + var scroller = this, renderer = scroller.renderer, options = scroller.options, size = scroller.size, styledMode = this.chart.styledMode, group; + // Draw the scrollbar group + scroller.group = group = renderer.g('scrollbar').attr({ + zIndex: options.zIndex, + translateY: -99999 + }).add(); + // Draw the scrollbar track: + scroller.track = renderer.rect() + .addClass('highcharts-scrollbar-track') + .attr({ + x: 0, + r: options.trackBorderRadius || 0, + height: size, + width: size + }).add(group); + if (!styledMode) { + scroller.track.attr({ + fill: options.trackBackgroundColor, + stroke: options.trackBorderColor, + 'stroke-width': options.trackBorderWidth + }); + } + this.trackBorderWidth = scroller.track.strokeWidth(); + scroller.track.attr({ + y: -this.trackBorderWidth % 2 / 2 + }); + // Draw the scrollbar itself + scroller.scrollbarGroup = renderer.g().add(group); + scroller.scrollbar = renderer.rect() + .addClass('highcharts-scrollbar-thumb') + .attr({ + height: size, + width: size, + r: options.barBorderRadius || 0 + }).add(scroller.scrollbarGroup); + scroller.scrollbarRifles = renderer + .path(swapXY([ + ['M', -3, size / 4], + ['L', -3, 2 * size / 3], + ['M', 0, size / 4], + ['L', 0, 2 * size / 3], + ['M', 3, size / 4], + ['L', 3, 2 * size / 3] + ], options.vertical)) + .addClass('highcharts-scrollbar-rifles') + .add(scroller.scrollbarGroup); + if (!styledMode) { + scroller.scrollbar.attr({ + fill: options.barBackgroundColor, + stroke: options.barBorderColor, + 'stroke-width': options.barBorderWidth + }); + scroller.scrollbarRifles.attr({ + stroke: options.rifleColor, + 'stroke-width': 1 + }); + } + scroller.scrollbarStrokeWidth = scroller.scrollbar.strokeWidth(); + scroller.scrollbarGroup.translate(-scroller.scrollbarStrokeWidth % 2 / 2, -scroller.scrollbarStrokeWidth % 2 / 2); + // Draw the buttons: + scroller.drawScrollbarButton(0); + scroller.drawScrollbarButton(1); + }; + /** + * Set scrollbar size, with a given scale. + * + * @private + * @function Highcharts.Scrollbar#setRange + * @param {number} from + * scale (0-1) where bar should start + * @param {number} to + * scale (0-1) where bar should end + * @return {void} + */ + Scrollbar.prototype.setRange = function (from, to) { + var scroller = this, options = scroller.options, vertical = options.vertical, minWidth = options.minWidth, fullWidth = scroller.barWidth, fromPX, toPX, newPos, newSize, newRiflesPos, method = (this.rendered && + !this.hasDragged && + !(this.chart.navigator && this.chart.navigator.hasDragged)) ? 'animate' : 'attr'; + if (!defined(fullWidth)) { + return; + } + from = Math.max(from, 0); + fromPX = Math.ceil(fullWidth * from); + toPX = fullWidth * Math.min(to, 1); + scroller.calculatedWidth = newSize = correctFloat(toPX - fromPX); + // We need to recalculate position, if minWidth is used + if (newSize < minWidth) { + fromPX = (fullWidth - minWidth + newSize) * from; + newSize = minWidth; + } + newPos = Math.floor(fromPX + scroller.xOffset + scroller.yOffset); + newRiflesPos = newSize / 2 - 0.5; // -0.5 -> rifle line width / 2 + // Store current position: + scroller.from = from; + scroller.to = to; + if (!vertical) { + scroller.scrollbarGroup[method]({ + translateX: newPos + }); + scroller.scrollbar[method]({ + width: newSize + }); + scroller.scrollbarRifles[method]({ + translateX: newRiflesPos + }); + scroller.scrollbarLeft = newPos; + scroller.scrollbarTop = 0; + } + else { + scroller.scrollbarGroup[method]({ + translateY: newPos + }); + scroller.scrollbar[method]({ + height: newSize + }); + scroller.scrollbarRifles[method]({ + translateY: newRiflesPos + }); + scroller.scrollbarTop = newPos; + scroller.scrollbarLeft = 0; + } + if (newSize <= 12) { + scroller.scrollbarRifles.hide(); + } + else { + scroller.scrollbarRifles.show(true); + } + // Show or hide the scrollbar based on the showFull setting + if (options.showFull === false) { + if (from <= 0 && to >= 1) { + scroller.group.hide(); + } + else { + scroller.group.show(); + } + } + scroller.rendered = true; + }; + Scrollbar.prototype.trackClick = function (e) { + var scroller = this; + var normalizedEvent = scroller.chart.pointer.normalize(e), range = scroller.to - scroller.from, top = scroller.y + scroller.scrollbarTop, left = scroller.x + scroller.scrollbarLeft; + if ((scroller.options.vertical && normalizedEvent.chartY > top) || + (!scroller.options.vertical && normalizedEvent.chartX > left)) { + // On the top or on the left side of the track: + scroller.updatePosition(scroller.from + range, scroller.to + range); + } + else { + // On the bottom or the right side of the track: + scroller.updatePosition(scroller.from - range, scroller.to - range); + } + fireEvent(scroller, 'changed', { + from: scroller.from, + to: scroller.to, + trigger: 'scrollbar', + DOMEvent: e + }); + }; + /** + * Update the scrollbar with new options + * + * @private + * @function Highcharts.Scrollbar#update + * @param {Highcharts.ScrollbarOptions} options + * @return {void} + */ + Scrollbar.prototype.update = function (options) { + this.destroy(); + this.init(this.chart.renderer, merge(true, this.options, options), this.chart); + }; + /** + * Update position option in the Scrollbar, with normalized 0-1 scale + * + * @private + * @function Highcharts.Scrollbar#updatePosition + * @param {number} from + * @param {number} to + * @return {void} + */ + Scrollbar.prototype.updatePosition = function (from, to) { + if (to > 1) { + from = correctFloat(1 - correctFloat(to - from)); + to = 1; + } + if (from < 0) { + to = correctFloat(to - from); + from = 0; + } + this.from = from; + this.to = to; + }; + /* * + * + * Static Properties + * + * */ + /** + * + * The scrollbar is a means of panning over the X axis of a stock chart. + * Scrollbars can also be applied to other types of axes. + * + * Another approach to scrollable charts is the [chart.scrollablePlotArea]( + * https://api.highcharts.com/highcharts/chart.scrollablePlotArea) option that + * is especially suitable for simpler cartesian charts on mobile. + * + * In styled mode, all the presentational options for the + * scrollbar are replaced by the classes `.highcharts-scrollbar-thumb`, + * `.highcharts-scrollbar-arrow`, `.highcharts-scrollbar-button`, + * `.highcharts-scrollbar-rifles` and `.highcharts-scrollbar-track`. + * + * @sample stock/yaxis/inverted-bar-scrollbar/ + * A scrollbar on a simple bar chart + * + * @product highstock gantt + * @optionparent scrollbar + * + * @private + */ + Scrollbar.defaultOptions = { + /** + * The height of the scrollbar. The height also applies to the width + * of the scroll arrows so that they are always squares. Defaults to + * 20 for touch devices and 14 for mouse devices. + * + * @sample stock/scrollbar/height/ + * A 30px scrollbar + * + * @type {number} + * @default 20/14 + */ + height: isTouchDevice ? 20 : 14, + /** + * The border rounding radius of the bar. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + */ + barBorderRadius: 0, + /** + * The corner radius of the scrollbar buttons. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + */ + buttonBorderRadius: 0, + /** + * Enable or disable the scrollbar. + * + * @sample stock/scrollbar/enabled/ + * Disable the scrollbar, only use navigator + * + * @type {boolean} + * @default true + * @apioption scrollbar.enabled + */ + /** + * Whether to redraw the main chart as the scrollbar or the navigator + * zoomed window is moved. Defaults to `true` for modern browsers and + * `false` for legacy IE browsers as well as mobile devices. + * + * @sample stock/scrollbar/liveredraw + * Setting live redraw to false + * + * @type {boolean} + * @since 1.3 + */ + liveRedraw: void 0, + /** + * The margin between the scrollbar and its axis when the scrollbar is + * applied directly to an axis. + */ + margin: 10, + /** + * The minimum width of the scrollbar. + * + * @since 1.2.5 + */ + minWidth: 6, + /** + * Whether to show or hide the scrollbar when the scrolled content is + * zoomed out to it full extent. + * + * @type {boolean} + * @default true + * @apioption scrollbar.showFull + */ + step: 0.2, + /** + * The z index of the scrollbar group. + */ + zIndex: 3, + /** + * The background color of the scrollbar itself. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + barBackgroundColor: '#cccccc', + /** + * The width of the bar's border. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + */ + barBorderWidth: 1, + /** + * The color of the scrollbar's border. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + barBorderColor: '#cccccc', + /** + * The color of the small arrow inside the scrollbar buttons. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + buttonArrowColor: '#333333', + /** + * The color of scrollbar buttons. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + buttonBackgroundColor: '#e6e6e6', + /** + * The color of the border of the scrollbar buttons. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + buttonBorderColor: '#cccccc', + /** + * The border width of the scrollbar buttons. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + */ + buttonBorderWidth: 1, + /** + * The color of the small rifles in the middle of the scrollbar. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + rifleColor: '#333333', + /** + * The color of the track background. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + trackBackgroundColor: '#f2f2f2', + /** + * The color of the border of the scrollbar track. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + trackBorderColor: '#f2f2f2', + /** + * The corner radius of the border of the scrollbar track. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {number} + * @default 0 + * @apioption scrollbar.trackBorderRadius + */ + /** + * The width of the border of the scrollbar track. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + */ + trackBorderWidth: 1 + }; + return Scrollbar; +}()); +if (!H.Scrollbar) { + defaultOptions.scrollbar = merge(true, Scrollbar.defaultOptions, defaultOptions.scrollbar); + H.Scrollbar = Scrollbar; + ScrollbarAxis.compose(Axis, Scrollbar); +} +export default H.Scrollbar; diff --git a/librerias/gantt/code/es-modules/parts/ScrollbarAxis.js b/librerias/gantt/code/es-modules/parts/ScrollbarAxis.js new file mode 100644 index 0000000..1c66a60 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/ScrollbarAxis.js @@ -0,0 +1,151 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +import H from './Globals.js'; +import U from './Utilities.js'; +var addEvent = U.addEvent, defined = U.defined, pick = U.pick; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * Creates scrollbars if enabled. + * + * @private + */ +var ScrollbarAxis = /** @class */ (function () { + function ScrollbarAxis() { + } + /** + * Attaches to axis events to create scrollbars if enabled. + * + * @private + * + * @param AxisClass + * Axis class to extend. + * + * @param ScrollbarClass + * Scrollbar class to use. + */ + ScrollbarAxis.compose = function (AxisClass, ScrollbarClass) { + // Wrap axis initialization and create scrollbar if enabled: + addEvent(AxisClass, 'afterInit', function () { + var axis = this; + if (axis.options && + axis.options.scrollbar && + axis.options.scrollbar.enabled) { + // Predefined options: + axis.options.scrollbar.vertical = !axis.horiz; + axis.options.startOnTick = axis.options.endOnTick = false; + axis.scrollbar = new ScrollbarClass(axis.chart.renderer, axis.options.scrollbar, axis.chart); + addEvent(axis.scrollbar, 'changed', function (e) { + var axisMin = pick(axis.options && axis.options.min, axis.min), axisMax = pick(axis.options && axis.options.max, axis.max), unitedMin = defined(axis.dataMin) ? + Math.min(axisMin, axis.min, axis.dataMin) : axisMin, unitedMax = defined(axis.dataMax) ? + Math.max(axisMax, axis.max, axis.dataMax) : axisMax, range = unitedMax - unitedMin, to, from; + // #12834, scroll when show/hide series, wrong extremes + if (!defined(axisMin) || !defined(axisMax)) { + return; + } + if ((axis.horiz && !axis.reversed) || + (!axis.horiz && axis.reversed)) { + to = unitedMin + range * this.to; + from = unitedMin + range * this.from; + } + else { + // y-values in browser are reversed, but this also + // applies for reversed horizontal axis: + to = unitedMin + range * (1 - this.from); + from = unitedMin + range * (1 - this.to); + } + if (pick(this.options.liveRedraw, H.svg && !H.isTouchDevice && !this.chart.isBoosting) || + // Mouseup always should change extremes + e.DOMType === 'mouseup' || + // Internal events + !defined(e.DOMType)) { + axis.setExtremes(from, to, true, e.DOMType !== 'mousemove', e); + } + else { + // When live redraw is disabled, don't change extremes + // Only change the position of the scollbar thumb + this.setRange(this.from, this.to); + } + }); + } + }); + // Wrap rendering axis, and update scrollbar if one is created: + addEvent(AxisClass, 'afterRender', function () { + var axis = this, scrollMin = Math.min(pick(axis.options.min, axis.min), axis.min, pick(axis.dataMin, axis.min) // #6930 + ), scrollMax = Math.max(pick(axis.options.max, axis.max), axis.max, pick(axis.dataMax, axis.max) // #6930 + ), scrollbar = axis.scrollbar, offset = axis.axisTitleMargin + (axis.titleOffset || 0), scrollbarsOffsets = axis.chart.scrollbarsOffsets, axisMargin = axis.options.margin || 0, offsetsIndex, from, to; + if (scrollbar) { + if (axis.horiz) { + // Reserve space for labels/title + if (!axis.opposite) { + scrollbarsOffsets[1] += offset; + } + scrollbar.position(axis.left, axis.top + axis.height + 2 + scrollbarsOffsets[1] - + (axis.opposite ? axisMargin : 0), axis.width, axis.height); + // Next scrollbar should reserve space for margin (if set) + if (!axis.opposite) { + scrollbarsOffsets[1] += axisMargin; + } + offsetsIndex = 1; + } + else { + // Reserve space for labels/title + if (axis.opposite) { + scrollbarsOffsets[0] += offset; + } + scrollbar.position(axis.left + axis.width + 2 + scrollbarsOffsets[0] - + (axis.opposite ? 0 : axisMargin), axis.top, axis.width, axis.height); + // Next scrollbar should reserve space for margin (if set) + if (axis.opposite) { + scrollbarsOffsets[0] += axisMargin; + } + offsetsIndex = 0; + } + scrollbarsOffsets[offsetsIndex] += scrollbar.size + + scrollbar.options.margin; + if (isNaN(scrollMin) || + isNaN(scrollMax) || + !defined(axis.min) || + !defined(axis.max) || + axis.min === axis.max // #10733 + ) { + // default action: when extremes are the same or there is + // not extremes on the axis, but scrollbar exists, make it + // full size + scrollbar.setRange(0, 1); + } + else { + from = + (axis.min - scrollMin) / (scrollMax - scrollMin); + to = + (axis.max - scrollMin) / (scrollMax - scrollMin); + if ((axis.horiz && !axis.reversed) || + (!axis.horiz && axis.reversed)) { + scrollbar.setRange(from, to); + } + else { + // inverse vertical axis + scrollbar.setRange(1 - to, 1 - from); + } + } + } + }); + // Make space for a scrollbar: + addEvent(AxisClass, 'afterGetOffset', function () { + var axis = this, index = axis.horiz ? 2 : 1, scrollbar = axis.scrollbar; + if (scrollbar) { + axis.chart.scrollbarsOffsets = [0, 0]; // reset scrollbars offsets + axis.chart.axisOffset[index] += + scrollbar.size + scrollbar.options.margin; + } + }); + }; + return ScrollbarAxis; +}()); +export default ScrollbarAxis; diff --git a/librerias/gantt/code/es-modules/parts/Series.js b/librerias/gantt/code/es-modules/parts/Series.js new file mode 100644 index 0000000..4d4742c --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/Series.js @@ -0,0 +1,5489 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import LegendSymbolMixin from '../mixins/legend-symbol.js'; +import H from './Globals.js'; +import './Options.js'; +import Point from './Point.js'; +import './SvgRenderer.js'; +import U from './Utilities.js'; +/** + * This is a placeholder type of the possible series options for + * [Highcharts](../highcharts/series), [Highstock](../highstock/series), + * [Highmaps](../highmaps/series), and [Gantt](../gantt/series). + * + * In TypeScript is this dynamically generated to reference all possible types + * of series options. + * + * @ignore-declaration + * @typedef {Highcharts.SeriesOptions|Highcharts.Dictionary<*>} Highcharts.SeriesOptionsType + */ +/** + * Options for `dataSorting`. + * + * @interface Highcharts.DataSortingOptionsObject + * @since 8.0.0 + */ /** +* Enable or disable data sorting for the series. +* @name Highcharts.DataSortingOptionsObject#enabled +* @type {boolean|undefined} +*/ /** +* Whether to allow matching points by name in an update. +* @name Highcharts.DataSortingOptionsObject#matchByName +* @type {boolean|undefined} +*/ /** +* Determines what data value should be used to sort by. +* @name Highcharts.DataSortingOptionsObject#sortKey +* @type {string|undefined} +*/ +/** + * Function callback when a series has been animated. + * + * @callback Highcharts.SeriesAfterAnimateCallbackFunction + * + * @param {Highcharts.Series} this + * The series where the event occured. + * + * @param {Highcharts.SeriesAfterAnimateEventObject} event + * Event arguments. + */ +/** + * Event information regarding completed animation of a series. + * + * @interface Highcharts.SeriesAfterAnimateEventObject + */ /** +* Animated series. +* @name Highcharts.SeriesAfterAnimateEventObject#target +* @type {Highcharts.Series} +*/ /** +* Event type. +* @name Highcharts.SeriesAfterAnimateEventObject#type +* @type {"afterAnimate"} +*/ +/** + * Function callback when the checkbox next to the series' name in the legend is + * clicked. + * + * @callback Highcharts.SeriesCheckboxClickCallbackFunction + * + * @param {Highcharts.Series} this + * The series where the event occured. + * + * @param {Highcharts.SeriesCheckboxClickEventObject} event + * Event arguments. + */ +/** + * Event information regarding check of a series box. + * + * @interface Highcharts.SeriesCheckboxClickEventObject + */ /** +* Whether the box has been checked. +* @name Highcharts.SeriesCheckboxClickEventObject#checked +* @type {boolean} +*/ /** +* Related series. +* @name Highcharts.SeriesCheckboxClickEventObject#item +* @type {Highcharts.Series} +*/ /** +* Related series. +* @name Highcharts.SeriesCheckboxClickEventObject#target +* @type {Highcharts.Series} +*/ /** +* Event type. +* @name Highcharts.SeriesCheckboxClickEventObject#type +* @type {"checkboxClick"} +*/ +/** + * Function callback when a series is clicked. Return false to cancel toogle + * actions. + * + * @callback Highcharts.SeriesClickCallbackFunction + * + * @param {Highcharts.Series} this + * The series where the event occured. + * + * @param {Highcharts.SeriesClickEventObject} event + * Event arguments. + */ +/** + * Common information for a click event on a series. + * + * @interface Highcharts.SeriesClickEventObject + * @extends global.Event + */ /** +* Nearest point on the graph. +* @name Highcharts.SeriesClickEventObject#point +* @type {Highcharts.Point} +*/ +/** + * Gets fired when the series is hidden after chart generation time, either by + * clicking the legend item or by calling `.hide()`. + * + * @callback Highcharts.SeriesHideCallbackFunction + * + * @param {Highcharts.Series} this + * The series where the event occured. + * + * @param {global.Event} event + * The event that occured. + */ +/** + * The SVG value used for the `stroke-linecap` and `stroke-linejoin` of a line + * graph. + * + * @typedef {"butt"|"round"|"square"|string} Highcharts.SeriesLinecapValue + */ +/** + * Gets fired when the legend item belonging to the series is clicked. The + * default action is to toggle the visibility of the series. This can be + * prevented by returning `false` or calling `event.preventDefault()`. + * + * @callback Highcharts.SeriesLegendItemClickCallbackFunction + * + * @param {Highcharts.Series} this + * The series where the event occured. + * + * @param {Highcharts.SeriesLegendItemClickEventObject} event + * The event that occured. + */ +/** + * Information about the event. + * + * @interface Highcharts.SeriesLegendItemClickEventObject + */ /** +* Related browser event. +* @name Highcharts.SeriesLegendItemClickEventObject#browserEvent +* @type {global.PointerEvent} +*/ /** +* Prevent the default action of toggle the visibility of the series. +* @name Highcharts.SeriesLegendItemClickEventObject#preventDefault +* @type {Function} +*/ /** +* Related series. +* @name Highcharts.SeriesCheckboxClickEventObject#target +* @type {Highcharts.Series} +*/ /** +* Event type. +* @name Highcharts.SeriesCheckboxClickEventObject#type +* @type {"checkboxClick"} +*/ +/** + * Gets fired when the mouse leaves the graph. + * + * @callback Highcharts.SeriesMouseOutCallbackFunction + * + * @param {Highcharts.Series} this + * Series where the event occured. + * + * @param {global.PointerEvent} event + * Event that occured. + */ +/** + * Gets fired when the mouse enters the graph. + * + * @callback Highcharts.SeriesMouseOverCallbackFunction + * + * @param {Highcharts.Series} this + * Series where the event occured. + * + * @param {global.PointerEvent} event + * Event that occured. + */ +/** + * Translation and scale for the plot area of a series. + * + * @interface Highcharts.SeriesPlotBoxObject + */ /** +* @name Highcharts.SeriesPlotBoxObject#scaleX +* @type {number} +*/ /** +* @name Highcharts.SeriesPlotBoxObject#scaleY +* @type {number} +*/ /** +* @name Highcharts.SeriesPlotBoxObject#translateX +* @type {number} +*/ /** +* @name Highcharts.SeriesPlotBoxObject#translateY +* @type {number} +*/ +/** + * Gets fired when the series is shown after chart generation time, either by + * clicking the legend item or by calling `.show()`. + * + * @callback Highcharts.SeriesShowCallbackFunction + * + * @param {Highcharts.Series} this + * Series where the event occured. + * + * @param {global.Event} event + * Event that occured. + */ +/** + * Possible key values for the series state options. + * + * @typedef {"hover"|"inactive"|"normal"|"select"} Highcharts.SeriesStateValue + */ +''; // detach doclets above +var addEvent = U.addEvent, animObject = U.animObject, arrayMax = U.arrayMax, arrayMin = U.arrayMin, clamp = U.clamp, correctFloat = U.correctFloat, defined = U.defined, erase = U.erase, error = U.error, extend = U.extend, find = U.find, fireEvent = U.fireEvent, getNestedProperty = U.getNestedProperty, isArray = U.isArray, isFunction = U.isFunction, isNumber = U.isNumber, isString = U.isString, merge = U.merge, objectEach = U.objectEach, pick = U.pick, removeEvent = U.removeEvent, seriesType = U.seriesType, splat = U.splat, syncTimeout = U.syncTimeout; +var defaultOptions = H.defaultOptions, defaultPlotOptions = H.defaultPlotOptions, seriesTypes = H.seriesTypes, SVGElement = H.SVGElement, win = H.win; +/** + * This is the base series prototype that all other series types inherit from. + * A new series is initialized either through the + * [series](https://api.highcharts.com/highcharts/series) + * option structure, or after the chart is initialized, through + * {@link Highcharts.Chart#addSeries}. + * + * The object can be accessed in a number of ways. All series and point event + * handlers give a reference to the `series` object. The chart object has a + * {@link Highcharts.Chart#series|series} property that is a collection of all + * the chart's series. The point objects and axis objects also have the same + * reference. + * + * Another way to reference the series programmatically is by `id`. Add an id + * in the series configuration options, and get the series object by + * {@link Highcharts.Chart#get}. + * + * Configuration options for the series are given in three levels. Options for + * all series in a chart are given in the + * [plotOptions.series](https://api.highcharts.com/highcharts/plotOptions.series) + * object. Then options for all series of a specific type + * are given in the plotOptions of that type, for example `plotOptions.line`. + * Next, options for one single series are given in the series array, or as + * arguments to `chart.addSeries`. + * + * The data in the series is stored in various arrays. + * + * - First, `series.options.data` contains all the original config options for + * each point whether added by options or methods like `series.addPoint`. + * + * - Next, `series.data` contains those values converted to points, but in case + * the series data length exceeds the `cropThreshold`, or if the data is + * grouped, `series.data` doesn't contain all the points. It only contains the + * points that have been created on demand. + * + * - Then there's `series.points` that contains all currently visible point + * objects. In case of cropping, the cropped-away points are not part of this + * array. The `series.points` array starts at `series.cropStart` compared to + * `series.data` and `series.options.data`. If however the series data is + * grouped, these can't be correlated one to one. + * + * - `series.xData` and `series.processedXData` contain clean x values, + * equivalent to `series.data` and `series.points`. + * + * - `series.yData` and `series.processedYData` contain clean y values, + * equivalent to `series.data` and `series.points`. + * + * @class + * @name Highcharts.Series + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @param {Highcharts.SeriesOptionsType|object} options + * The series options. + */ /** +* The line series is the base type and is therefor the series base prototype. +* +* @private +* @class +* @name Highcharts.seriesTypes.line +* +* @augments Highcharts.Series +*/ +H.Series = seriesType('line', +/** + * Series options for specific data and the data itself. In TypeScript you + * have to cast the series options to specific series types, to get all + * possible options for a series. + * + * @example + * // TypeScript example + * Highcharts.chart('container', { + * series: [{ + * color: '#06C', + * data: [[0, 1], [2, 3]] + * } as Highcharts.SeriesLineOptions ] + * }); + * + * @type {Array<*>} + * @apioption series + */ +/** + * An id for the series. This can be used after render time to get a pointer + * to the series object through `chart.get()`. + * + * @sample {highcharts} highcharts/plotoptions/series-id/ + * Get series by id + * + * @type {string} + * @since 1.2.0 + * @apioption series.id + */ +/** + * The index of the series in the chart, affecting the internal index in the + * `chart.series` array, the visible Z index as well as the order in the + * legend. + * + * @type {number} + * @since 2.3.0 + * @apioption series.index + */ +/** + * The sequential index of the series in the legend. + * + * @see [legend.reversed](#legend.reversed), + * [yAxis.reversedStacks](#yAxis.reversedStacks) + * + * @sample {highcharts|highstock} highcharts/series/legendindex/ + * Legend in opposite order + * + * @type {number} + * @apioption series.legendIndex + */ +/** + * The name of the series as shown in the legend, tooltip etc. + * + * @sample {highcharts} highcharts/series/name/ + * Series name + * @sample {highmaps} maps/demo/category-map/ + * Series name + * + * @type {string} + * @apioption series.name + */ +/** + * This option allows grouping series in a stacked chart. The stack option + * can be a string or anything else, as long as the grouped series' stack + * options match each other after conversion into a string. + * + * @sample {highcharts} highcharts/series/stack/ + * Stacked and grouped columns + * + * @type {number|string} + * @since 2.1 + * @product highcharts highstock + * @apioption series.stack + */ +/** + * The type of series, for example `line` or `column`. By default, the + * series type is inherited from [chart.type](#chart.type), so unless the + * chart is a combination of series types, there is no need to set it on the + * series level. + * + * @sample {highcharts} highcharts/series/type/ + * Line and column in the same chart + * @sample highcharts/series/type-dynamic/ + * Dynamic types with button selector + * @sample {highmaps} maps/demo/mapline-mappoint/ + * Multiple types in the same map + * + * @type {string} + * @apioption series.type + */ +/** + * When using dual or multiple x axes, this number defines which xAxis the + * particular series is connected to. It refers to either the + * {@link #xAxis.id|axis id} + * or the index of the axis in the xAxis array, with 0 being the first. + * + * @type {number|string} + * @default 0 + * @product highcharts highstock + * @apioption series.xAxis + */ +/** + * When using dual or multiple y axes, this number defines which yAxis the + * particular series is connected to. It refers to either the + * {@link #yAxis.id|axis id} + * or the index of the axis in the yAxis array, with 0 being the first. + * + * @sample {highcharts} highcharts/series/yaxis/ + * Apply the column series to the secondary Y axis + * + * @type {number|string} + * @default 0 + * @product highcharts highstock + * @apioption series.yAxis + */ +/** + * Define the visual z index of the series. + * + * @sample {highcharts} highcharts/plotoptions/series-zindex-default/ + * With no z index, the series defined last are on top + * @sample {highcharts} highcharts/plotoptions/series-zindex/ + * With a z index, the series with the highest z index is on top + * @sample {highstock} highcharts/plotoptions/series-zindex-default/ + * With no z index, the series defined last are on top + * @sample {highstock} highcharts/plotoptions/series-zindex/ + * With a z index, the series with the highest z index is on top + * + * @type {number} + * @product highcharts highstock + * @apioption series.zIndex + */ +null, +/** + * General options for all series types. + * + * @optionparent plotOptions.series + */ +{ + /** + * The SVG value used for the `stroke-linecap` and `stroke-linejoin` + * of a line graph. Round means that lines are rounded in the ends and + * bends. + * + * @type {Highcharts.SeriesLinecapValue} + * @default round + * @since 3.0.7 + * @apioption plotOptions.line.linecap + */ + /** + * Pixel width of the graph line. + * + * @see In styled mode, the line stroke-width can be set with the + * `.highcharts-graph` class name. + * + * @sample {highcharts} highcharts/plotoptions/series-linewidth-general/ + * On all series + * @sample {highcharts} highcharts/plotoptions/series-linewidth-specific/ + * On one single series + * + * @product highcharts highstock + * + * @private + */ + lineWidth: 2, + /** + * For some series, there is a limit that shuts down initial animation + * by default when the total number of points in the chart is too high. + * For example, for a column chart and its derivatives, animation does + * not run if there is more than 250 points totally. To disable this + * cap, set `animationLimit` to `Infinity`. + * + * @type {number} + * @apioption plotOptions.series.animationLimit + */ + /** + * Allow this series' points to be selected by clicking on the graphic + * (columns, point markers, pie slices, map areas etc). + * + * The selected points can be handled by point select and unselect + * events, or collectively by the [getSelectedPoints + * ](/class-reference/Highcharts.Chart#getSelectedPoints) function. + * + * And alternative way of selecting points is through dragging. + * + * @sample {highcharts} highcharts/plotoptions/series-allowpointselect-line/ + * Line + * @sample {highcharts} highcharts/plotoptions/series-allowpointselect-column/ + * Column + * @sample {highcharts} highcharts/plotoptions/series-allowpointselect-pie/ + * Pie + * @sample {highcharts} highcharts/chart/events-selection-points/ + * Select a range of points through a drag selection + * @sample {highmaps} maps/plotoptions/series-allowpointselect/ + * Map area + * @sample {highmaps} maps/plotoptions/mapbubble-allowpointselect/ + * Map bubble + * + * @since 1.2.0 + * + * @private + */ + allowPointSelect: false, + /** + * When true, each point or column edge is rounded to its nearest pixel + * in order to render sharp on screen. In some cases, when there are a + * lot of densely packed columns, this leads to visible difference + * in column widths or distance between columns. In these cases, + * setting `crisp` to `false` may look better, even though each column + * is rendered blurry. + * + * @sample {highcharts} highcharts/plotoptions/column-crisp-false/ + * Crisp is false + * + * @since 5.0.10 + * @product highcharts highstock gantt + * + * @private + */ + crisp: true, + /** + * If true, a checkbox is displayed next to the legend item to allow + * selecting the series. The state of the checkbox is determined by + * the `selected` option. + * + * @productdesc {highmaps} + * Note that if a `colorAxis` is defined, the color axis is represented + * in the legend, not the series. + * + * @sample {highcharts} highcharts/plotoptions/series-showcheckbox-true/ + * Show select box + * + * @since 1.2.0 + * + * @private + */ + showCheckbox: false, + /** + * Enable or disable the initial animation when a series is displayed. + * The animation can also be set as a configuration object. Please + * note that this option only applies to the initial animation of the + * series itself. For other animations, see [chart.animation]( + * #chart.animation) and the animation parameter under the API methods. + * The following properties are supported: + * + * - `duration`: The duration of the animation in milliseconds. + * + * - `easing`: Can be a string reference to an easing function set on + * the `Math` object or a function. See the _Custom easing function_ + * demo below. + * + * Due to poor performance, animation is disabled in old IE browsers + * for several chart types. + * + * @sample {highcharts} highcharts/plotoptions/series-animation-disabled/ + * Animation disabled + * @sample {highcharts} highcharts/plotoptions/series-animation-slower/ + * Slower animation + * @sample {highcharts} highcharts/plotoptions/series-animation-easing/ + * Custom easing function + * @sample {highstock} stock/plotoptions/animation-slower/ + * Slower animation + * @sample {highstock} stock/plotoptions/animation-easing/ + * Custom easing function + * @sample {highmaps} maps/plotoptions/series-animation-true/ + * Animation enabled on map series + * @sample {highmaps} maps/plotoptions/mapbubble-animation-false/ + * Disabled on mapbubble series + * + * @type {boolean|Highcharts.AnimationOptionsObject} + * @default {highcharts} true + * @default {highstock} true + * @default {highmaps} false + * + * @private + */ + animation: { + /** @internal */ + duration: 1000 + }, + /** + * An additional class name to apply to the series' graphical elements. + * This option does not replace default class names of the graphical + * element. + * + * @type {string} + * @since 5.0.0 + * @apioption plotOptions.series.className + */ + /** + * Disable this option to allow series rendering in the whole plotting + * area. + * + * **Note:** Clipping should be always enabled when + * [chart.zoomType](#chart.zoomType) is set + * + * @sample {highcharts} highcharts/plotoptions/series-clip/ + * Disabled clipping + * + * @default true + * @type {boolean} + * @since 3.0.0 + * @apioption plotOptions.series.clip + */ + /** + * The main color of the series. In line type series it applies to the + * line and the point markers unless otherwise specified. In bar type + * series it applies to the bars unless a color is specified per point. + * The default value is pulled from the `options.colors` array. + * + * In styled mode, the color can be defined by the + * [colorIndex](#plotOptions.series.colorIndex) option. Also, the series + * color can be set with the `.highcharts-series`, + * `.highcharts-color-{n}`, `.highcharts-{type}-series` or + * `.highcharts-series-{n}` class, or individual classes given by the + * `className` option. + * + * @productdesc {highmaps} + * In maps, the series color is rarely used, as most choropleth maps use + * the color to denote the value of each point. The series color can + * however be used in a map with multiple series holding categorized + * data. + * + * @sample {highcharts} highcharts/plotoptions/series-color-general/ + * General plot option + * @sample {highcharts} highcharts/plotoptions/series-color-specific/ + * One specific series + * @sample {highcharts} highcharts/plotoptions/series-color-area/ + * Area color + * @sample {highcharts} highcharts/series/infographic/ + * Pattern fill + * @sample {highmaps} maps/demo/category-map/ + * Category map by multiple series + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.series.color + */ + /** + * Styled mode only. A specific color index to use for the series, so + * its graphic representations are given the class name + * `highcharts-color-{n}`. + * + * @type {number} + * @since 5.0.0 + * @apioption plotOptions.series.colorIndex + */ + /** + * Whether to connect a graph line across null points, or render a gap + * between the two points on either side of the null. + * + * @sample {highcharts} highcharts/plotoptions/series-connectnulls-false/ + * False by default + * @sample {highcharts} highcharts/plotoptions/series-connectnulls-true/ + * True + * + * @type {boolean} + * @default false + * @product highcharts highstock + * @apioption plotOptions.series.connectNulls + */ + /** + * You can set the cursor to "pointer" if you have click events attached + * to the series, to signal to the user that the points and lines can + * be clicked. + * + * In styled mode, the series cursor can be set with the same classes + * as listed under [series.color](#plotOptions.series.color). + * + * @sample {highcharts} highcharts/plotoptions/series-cursor-line/ + * On line graph + * @sample {highcharts} highcharts/plotoptions/series-cursor-column/ + * On columns + * @sample {highcharts} highcharts/plotoptions/series-cursor-scatter/ + * On scatter markers + * @sample {highstock} stock/plotoptions/cursor/ + * Pointer on a line graph + * @sample {highmaps} maps/plotoptions/series-allowpointselect/ + * Map area + * @sample {highmaps} maps/plotoptions/mapbubble-allowpointselect/ + * Map bubble + * + * @type {string|Highcharts.CursorValue} + * @apioption plotOptions.series.cursor + */ + /** + * A reserved subspace to store options and values for customized + * functionality. Here you can add additional data for your own event + * callbacks and formatter callbacks. + * + * @sample {highcharts} highcharts/point/custom/ + * Point and series with custom data + * + * @type {Highcharts.Dictionary<*>} + * @apioption plotOptions.series.custom + */ + /** + * Name of the dash style to use for the graph, or for some series types + * the outline of each shape. + * + * In styled mode, the + * [stroke dash-array](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/css/series-dashstyle/) + * can be set with the same classes as listed under + * [series.color](#plotOptions.series.color). + * + * @sample {highcharts} highcharts/plotoptions/series-dashstyle-all/ + * Possible values demonstrated + * @sample {highcharts} highcharts/plotoptions/series-dashstyle/ + * Chart suitable for printing in black and white + * @sample {highstock} highcharts/plotoptions/series-dashstyle-all/ + * Possible values demonstrated + * @sample {highmaps} highcharts/plotoptions/series-dashstyle-all/ + * Possible values demonstrated + * @sample {highmaps} maps/plotoptions/series-dashstyle/ + * Dotted borders on a map + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 2.1 + * @apioption plotOptions.series.dashStyle + */ + /** + * A description of the series to add to the screen reader information + * about the series. + * + * @type {string} + * @since 5.0.0 + * @requires modules/accessibility + * @apioption plotOptions.series.description + */ + /** + * Options for the series data sorting. + * + * @type {Highcharts.DataSortingOptionsObject} + * @since 8.0.0 + * @product highcharts highstock + * @apioption plotOptions.series.dataSorting + */ + /** + * Enable or disable data sorting for the series. Use [xAxis.reversed]( + * #xAxis.reversed) to change the sorting order. + * + * @sample {highcharts} highcharts/datasorting/animation/ + * Data sorting in scatter-3d + * @sample {highcharts} highcharts/datasorting/labels-animation/ + * Axis labels animation + * @sample {highcharts} highcharts/datasorting/dependent-sorting/ + * Dependent series sorting + * @sample {highcharts} highcharts/datasorting/independent-sorting/ + * Independent series sorting + * + * @type {boolean} + * @since 8.0.0 + * @apioption plotOptions.series.dataSorting.enabled + */ + /** + * Whether to allow matching points by name in an update. If this option + * is disabled, points will be matched by order. + * + * @sample {highcharts} highcharts/datasorting/match-by-name/ + * Enabled match by name + * + * @type {boolean} + * @since 8.0.0 + * @apioption plotOptions.series.dataSorting.matchByName + */ + /** + * Determines what data value should be used to sort by. + * + * @sample {highcharts} highcharts/datasorting/sort-key/ + * Sort key as `z` value + * + * @type {string} + * @since 8.0.0 + * @default y + * @apioption plotOptions.series.dataSorting.sortKey + */ + /** + * Enable or disable the mouse tracking for a specific series. This + * includes point tooltips and click events on graphs and points. For + * large datasets it improves performance. + * + * @sample {highcharts} highcharts/plotoptions/series-enablemousetracking-false/ + * No mouse tracking + * @sample {highmaps} maps/plotoptions/series-enablemousetracking-false/ + * No mouse tracking + * + * @type {boolean} + * @default true + * @apioption plotOptions.series.enableMouseTracking + */ + /** + * Whether to use the Y extremes of the total chart width or only the + * zoomed area when zooming in on parts of the X axis. By default, the + * Y axis adjusts to the min and max of the visible data. Cartesian + * series only. + * + * @type {boolean} + * @default false + * @since 4.1.6 + * @product highcharts highstock gantt + * @apioption plotOptions.series.getExtremesFromAll + */ + /** + * An array specifying which option maps to which key in the data point + * array. This makes it convenient to work with unstructured data arrays + * from different sources. + * + * @see [series.data](#series.line.data) + * + * @sample {highcharts|highstock} highcharts/series/data-keys/ + * An extended data array with keys + * @sample {highcharts|highstock} highcharts/series/data-nested-keys/ + * Nested keys used to access object properties + * + * @type {Array} + * @since 4.1.6 + * @apioption plotOptions.series.keys + */ + /** + * The line cap used for line ends and line joins on the graph. + * + * @type {Highcharts.SeriesLinecapValue} + * @default round + * @product highcharts highstock + * @apioption plotOptions.series.linecap + */ + /** + * The [id](#series.id) of another series to link to. Additionally, + * the value can be ":previous" to link to the previous series. When + * two series are linked, only the first one appears in the legend. + * Toggling the visibility of this also toggles the linked series. + * + * If master series uses data sorting and linked series does not have + * its own sorting definition, the linked series will be sorted in the + * same order as the master one. + * + * @sample {highcharts|highstock} highcharts/demo/arearange-line/ + * Linked series + * + * @type {string} + * @since 3.0 + * @product highcharts highstock gantt + * @apioption plotOptions.series.linkedTo + */ + /** + * Options for the corresponding navigator series if `showInNavigator` + * is `true` for this series. Available options are the same as any + * series, documented at [plotOptions](#plotOptions.series) and + * [series](#series). + * + * These options are merged with options in [navigator.series]( + * #navigator.series), and will take precedence if the same option is + * defined both places. + * + * @see [navigator.series](#navigator.series) + * + * @type {Highcharts.PlotSeriesOptions} + * @since 5.0.0 + * @product highstock + * @apioption plotOptions.series.navigatorOptions + */ + /** + * The color for the parts of the graph or points that are below the + * [threshold](#plotOptions.series.threshold). Note that `zones` takes + * precedence over the negative color. Using `negativeColor` is + * equivalent to applying a zone with value of 0. + * + * @see In styled mode, a negative color is applied by setting this option + * to `true` combined with the `.highcharts-negative` class name. + * + * @sample {highcharts} highcharts/plotoptions/series-negative-color/ + * Spline, area and column + * @sample {highcharts} highcharts/plotoptions/arearange-negativecolor/ + * Arearange + * @sample {highcharts} highcharts/css/series-negative-color/ + * Styled mode + * @sample {highstock} highcharts/plotoptions/series-negative-color/ + * Spline, area and column + * @sample {highstock} highcharts/plotoptions/arearange-negativecolor/ + * Arearange + * @sample {highmaps} highcharts/plotoptions/series-negative-color/ + * Spline, area and column + * @sample {highmaps} highcharts/plotoptions/arearange-negativecolor/ + * Arearange + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 3.0 + * @apioption plotOptions.series.negativeColor + */ + /** + * Same as + * [accessibility.pointDescriptionFormatter](#accessibility.pointDescriptionFormatter), + * but for an individual series. Overrides the chart wide configuration. + * + * @type {Function} + * @since 5.0.12 + * @apioption plotOptions.series.pointDescriptionFormatter + */ + /** + * If no x values are given for the points in a series, `pointInterval` + * defines the interval of the x values. For example, if a series + * contains one value every decade starting from year 0, set + * `pointInterval` to `10`. In true `datetime` axes, the `pointInterval` + * is set in milliseconds. + * + * It can be also be combined with `pointIntervalUnit` to draw irregular + * time intervals. + * + * Please note that this options applies to the _series data_, not the + * interval of the axis ticks, which is independent. + * + * @sample {highcharts} highcharts/plotoptions/series-pointstart-datetime/ + * Datetime X axis + * @sample {highstock} stock/plotoptions/pointinterval-pointstart/ + * Using pointStart and pointInterval + * + * @type {number} + * @default 1 + * @product highcharts highstock gantt + * @apioption plotOptions.series.pointInterval + */ + /** + * On datetime series, this allows for setting the + * [pointInterval](#plotOptions.series.pointInterval) to irregular time + * units, `day`, `month` and `year`. A day is usually the same as 24 + * hours, but `pointIntervalUnit` also takes the DST crossover into + * consideration when dealing with local time. Combine this option with + * `pointInterval` to draw weeks, quarters, 6 months, 10 years etc. + * + * Please note that this options applies to the _series data_, not the + * interval of the axis ticks, which is independent. + * + * @sample {highcharts} highcharts/plotoptions/series-pointintervalunit/ + * One point a month + * @sample {highstock} highcharts/plotoptions/series-pointintervalunit/ + * One point a month + * + * @type {string} + * @since 4.1.0 + * @product highcharts highstock gantt + * @validvalue ["day", "month", "year"] + * @apioption plotOptions.series.pointIntervalUnit + */ + /** + * Possible values: `"on"`, `"between"`, `number`. + * + * In a column chart, when pointPlacement is `"on"`, the point will not + * create any padding of the X axis. In a polar column chart this means + * that the first column points directly north. If the pointPlacement is + * `"between"`, the columns will be laid out between ticks. This is + * useful for example for visualising an amount between two points in + * time or in a certain sector of a polar chart. + * + * Since Highcharts 3.0.2, the point placement can also be numeric, + * where 0 is on the axis value, -0.5 is between this value and the + * previous, and 0.5 is between this value and the next. Unlike the + * textual options, numeric point placement options won't affect axis + * padding. + * + * Note that pointPlacement needs a [pointRange]( + * #plotOptions.series.pointRange) to work. For column series this is + * computed, but for line-type series it needs to be set. + * + * For the `xrange` series type and gantt charts, if the Y axis is a + * category axis, the `pointPlacement` applies to the Y axis rather than + * the (typically datetime) X axis. + * + * Defaults to `undefined` in cartesian charts, `"between"` in polar + * charts. + * + * @see [xAxis.tickmarkPlacement](#xAxis.tickmarkPlacement) + * + * @sample {highcharts|highstock} highcharts/plotoptions/series-pointplacement-between/ + * Between in a column chart + * @sample {highcharts|highstock} highcharts/plotoptions/series-pointplacement-numeric/ + * Numeric placement for custom layout + * @sample {highcharts|highstock} maps/plotoptions/heatmap-pointplacement/ + * Placement in heatmap + * + * @type {string|number} + * @since 2.3.0 + * @product highcharts highstock gantt + * @apioption plotOptions.series.pointPlacement + */ + /** + * If no x values are given for the points in a series, pointStart + * defines on what value to start. For example, if a series contains one + * yearly value starting from 1945, set pointStart to 1945. + * + * @sample {highcharts} highcharts/plotoptions/series-pointstart-linear/ + * Linear + * @sample {highcharts} highcharts/plotoptions/series-pointstart-datetime/ + * Datetime + * @sample {highstock} stock/plotoptions/pointinterval-pointstart/ + * Using pointStart and pointInterval + * + * @type {number} + * @default 0 + * @product highcharts highstock gantt + * @apioption plotOptions.series.pointStart + */ + /** + * Whether to select the series initially. If `showCheckbox` is true, + * the checkbox next to the series name in the legend will be checked + * for a selected series. + * + * @sample {highcharts} highcharts/plotoptions/series-selected/ + * One out of two series selected + * + * @type {boolean} + * @default false + * @since 1.2.0 + * @apioption plotOptions.series.selected + */ + /** + * Whether to apply a drop shadow to the graph line. Since 2.3 the + * shadow can be an object configuration containing `color`, `offsetX`, + * `offsetY`, `opacity` and `width`. + * + * @sample {highcharts} highcharts/plotoptions/series-shadow/ + * Shadow enabled + * + * @type {boolean|Highcharts.ShadowOptionsObject} + * @default false + * @apioption plotOptions.series.shadow + */ + /** + * Whether to display this particular series or series type in the + * legend. Standalone series are shown in legend by default, and linked + * series are not. Since v7.2.0 it is possible to show series that use + * colorAxis by setting this option to `true`. + * + * @sample {highcharts} highcharts/plotoptions/series-showinlegend/ + * One series in the legend, one hidden + * + * @type {boolean} + * @apioption plotOptions.series.showInLegend + */ + /** + * Whether or not to show the series in the navigator. Takes precedence + * over [navigator.baseSeries](#navigator.baseSeries) if defined. + * + * @type {boolean} + * @since 5.0.0 + * @product highstock + * @apioption plotOptions.series.showInNavigator + */ + /** + * If set to `true`, the accessibility module will skip past the points + * in this series for keyboard navigation. + * + * @type {boolean} + * @since 5.0.12 + * @apioption plotOptions.series.skipKeyboardNavigation + */ + /** + * Whether to stack the values of each series on top of each other. + * Possible values are `undefined` to disable, `"normal"` to stack by + * value or `"percent"`. When stacking is enabled, data must be sorted + * in ascending X order. A special stacking option is with the + * streamgraph series type, where the stacking option is set to + * `"stream"`. The second one is `"overlap"`, which only applies to + * waterfall series. + * + * @see [yAxis.reversedStacks](#yAxis.reversedStacks) + * + * @sample {highcharts} highcharts/plotoptions/series-stacking-line/ + * Line + * @sample {highcharts} highcharts/plotoptions/series-stacking-column/ + * Column + * @sample {highcharts} highcharts/plotoptions/series-stacking-bar/ + * Bar + * @sample {highcharts} highcharts/plotoptions/series-stacking-area/ + * Area + * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-line/ + * Line + * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-column/ + * Column + * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-bar/ + * Bar + * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-area/ + * Area + * @sample {highcharts} highcharts/plotoptions/series-waterfall-with-normal-stacking + * Waterfall with normal stacking + * @sample {highcharts} highcharts/plotoptions/series-waterfall-with-overlap-stacking + * Waterfall with overlap stacking + * @sample {highstock} stock/plotoptions/stacking/ + * Area + * + * @type {string} + * @product highcharts highstock + * @validvalue ["normal", "overlap", "percent", "stream"] + * @apioption plotOptions.series.stacking + */ + /** + * Whether to apply steps to the line. Possible values are `left`, + * `center` and `right`. + * + * @sample {highcharts} highcharts/plotoptions/line-step/ + * Different step line options + * @sample {highcharts} highcharts/plotoptions/area-step/ + * Stepped, stacked area + * @sample {highstock} stock/plotoptions/line-step/ + * Step line + * + * @type {string} + * @since 1.2.5 + * @product highcharts highstock + * @validvalue ["left", "center", "right"] + * @apioption plotOptions.series.step + */ + /** + * The threshold, also called zero level or base level. For line type + * series this is only used in conjunction with + * [negativeColor](#plotOptions.series.negativeColor). + * + * @see [softThreshold](#plotOptions.series.softThreshold). + * + * @type {number} + * @default 0 + * @since 3.0 + * @product highcharts highstock + * @apioption plotOptions.series.threshold + */ + /** + * Set the initial visibility of the series. + * + * @sample {highcharts} highcharts/plotoptions/series-visible/ + * Two series, one hidden and one visible + * @sample {highstock} stock/plotoptions/series-visibility/ + * Hidden series + * + * @type {boolean} + * @default true + * @apioption plotOptions.series.visible + */ + /** + * Defines the Axis on which the zones are applied. + * + * @see [zones](#plotOptions.series.zones) + * + * @sample {highcharts} highcharts/series/color-zones-zoneaxis-x/ + * Zones on the X-Axis + * @sample {highstock} highcharts/series/color-zones-zoneaxis-x/ + * Zones on the X-Axis + * + * @type {string} + * @default y + * @since 4.1.0 + * @product highcharts highstock + * @apioption plotOptions.series.zoneAxis + */ + /** + * General event handlers for the series items. These event hooks can + * also be attached to the series at run time using the + * `Highcharts.addEvent` function. + * + * @declare Highcharts.SeriesEventsOptionsObject + * + * @private + */ + events: {}, + /** + * Fires after the series has finished its initial animation, or in case + * animation is disabled, immediately as the series is displayed. + * + * @sample {highcharts} highcharts/plotoptions/series-events-afteranimate/ + * Show label after animate + * @sample {highstock} highcharts/plotoptions/series-events-afteranimate/ + * Show label after animate + * + * @type {Highcharts.SeriesAfterAnimateCallbackFunction} + * @since 4.0 + * @product highcharts highstock gantt + * @context Highcharts.Series + * @apioption plotOptions.series.events.afterAnimate + */ + /** + * Fires when the checkbox next to the series' name in the legend is + * clicked. One parameter, `event`, is passed to the function. The state + * of the checkbox is found by `event.checked`. The checked item is + * found by `event.item`. Return `false` to prevent the default action + * which is to toggle the select state of the series. + * + * @sample {highcharts} highcharts/plotoptions/series-events-checkboxclick/ + * Alert checkbox status + * + * @type {Highcharts.SeriesCheckboxClickCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Series + * @apioption plotOptions.series.events.checkboxClick + */ + /** + * Fires when the series is clicked. One parameter, `event`, is passed + * to the function, containing common event information. Additionally, + * `event.point` holds a pointer to the nearest point on the graph. + * + * @sample {highcharts} highcharts/plotoptions/series-events-click/ + * Alert click info + * @sample {highstock} stock/plotoptions/series-events-click/ + * Alert click info + * @sample {highmaps} maps/plotoptions/series-events-click/ + * Display click info in subtitle + * + * @type {Highcharts.SeriesClickCallbackFunction} + * @context Highcharts.Series + * @apioption plotOptions.series.events.click + */ + /** + * Fires when the series is hidden after chart generation time, either + * by clicking the legend item or by calling `.hide()`. + * + * @sample {highcharts} highcharts/plotoptions/series-events-hide/ + * Alert when the series is hidden by clicking the legend item + * + * @type {Highcharts.SeriesHideCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Series + * @apioption plotOptions.series.events.hide + */ + /** + * Fires when the legend item belonging to the series is clicked. One + * parameter, `event`, is passed to the function. The default action + * is to toggle the visibility of the series. This can be prevented + * by returning `false` or calling `event.preventDefault()`. + * + * @sample {highcharts} highcharts/plotoptions/series-events-legenditemclick/ + * Confirm hiding and showing + * + * @type {Highcharts.SeriesLegendItemClickCallbackFunction} + * @context Highcharts.Series + * @apioption plotOptions.series.events.legendItemClick + */ + /** + * Fires when the mouse leaves the graph. One parameter, `event`, is + * passed to the function, containing common event information. If the + * [stickyTracking](#plotOptions.series) option is true, `mouseOut` + * doesn't happen before the mouse enters another graph or leaves the + * plot area. + * + * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-sticky/ + * With sticky tracking by default + * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-no-sticky/ + * Without sticky tracking + * + * @type {Highcharts.SeriesMouseOutCallbackFunction} + * @context Highcharts.Series + * @apioption plotOptions.series.events.mouseOut + */ + /** + * Fires when the mouse enters the graph. One parameter, `event`, is + * passed to the function, containing common event information. + * + * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-sticky/ + * With sticky tracking by default + * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-no-sticky/ + * Without sticky tracking + * + * @type {Highcharts.SeriesMouseOverCallbackFunction} + * @context Highcharts.Series + * @apioption plotOptions.series.events.mouseOver + */ + /** + * Fires when the series is shown after chart generation time, either + * by clicking the legend item or by calling `.show()`. + * + * @sample {highcharts} highcharts/plotoptions/series-events-show/ + * Alert when the series is shown by clicking the legend item. + * + * @type {Highcharts.SeriesShowCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Series + * @apioption plotOptions.series.events.show + */ + /** + * Options for the point markers of line-like series. Properties like + * `fillColor`, `lineColor` and `lineWidth` define the visual appearance + * of the markers. Other series types, like column series, don't have + * markers, but have visual options on the series level instead. + * + * In styled mode, the markers can be styled with the + * `.highcharts-point`, `.highcharts-point-hover` and + * `.highcharts-point-select` class names. + * + * @declare Highcharts.PointMarkerOptionsObject + * + * @private + */ + marker: { + /** + * Enable or disable the point marker. If `undefined`, the markers + * are hidden when the data is dense, and shown for more widespread + * data points. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-enabled/ + * Disabled markers + * @sample {highcharts} highcharts/plotoptions/series-marker-enabled-false/ + * Disabled in normal state but enabled on hover + * @sample {highstock} stock/plotoptions/series-marker/ + * Enabled markers + * + * @type {boolean} + * @default {highcharts} undefined + * @default {highstock} false + * @apioption plotOptions.series.marker.enabled + */ + /** + * The threshold for how dense the point markers should be before + * they are hidden, given that `enabled` is not defined. The number + * indicates the horizontal distance between the two closest points + * in the series, as multiples of the `marker.radius`. In other + * words, the default value of 2 means points are hidden if + * overlapping horizontally. + * + * @sample highcharts/plotoptions/series-marker-enabledthreshold + * A higher threshold + * + * @since 6.0.5 + */ + enabledThreshold: 2, + /** + * The fill color of the point marker. When `undefined`, the series' + * or point's color is used. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-fillcolor/ + * White fill + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.series.marker.fillColor + */ + /** + * Image markers only. Set the image width explicitly. When using + * this option, a `width` must also be set. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-width-height/ + * Fixed width and height + * @sample {highstock} highcharts/plotoptions/series-marker-width-height/ + * Fixed width and height + * + * @type {number} + * @since 4.0.4 + * @apioption plotOptions.series.marker.height + */ + /** + * The color of the point marker's outline. When `undefined`, the + * series' or point's color is used. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-fillcolor/ + * Inherit from series color (undefined) + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + lineColor: '#ffffff', + /** + * The width of the point marker's outline. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-fillcolor/ + * 2px blue marker + */ + lineWidth: 0, + /** + * The radius of the point marker. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-radius/ + * Bigger markers + * + * @default {highstock} 2 + */ + radius: 4, + /** + * A predefined shape or symbol for the marker. When undefined, the + * symbol is pulled from options.symbols. Other possible values are + * `'circle'`, `'square'`,`'diamond'`, `'triangle'` and + * `'triangle-down'`. + * + * Additionally, the URL to a graphic can be given on this form: + * `'url(graphic.png)'`. Note that for the image to be applied to + * exported charts, its URL needs to be accessible by the export + * server. + * + * Custom callbacks for symbol path generation can also be added to + * `Highcharts.SVGRenderer.prototype.symbols`. The callback is then + * used by its method name, as shown in the demo. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-symbol/ + * Predefined, graphic and custom markers + * @sample {highstock} highcharts/plotoptions/series-marker-symbol/ + * Predefined, graphic and custom markers + * + * @type {string} + * @apioption plotOptions.series.marker.symbol + */ + /** + * Image markers only. Set the image width explicitly. When using + * this option, a `height` must also be set. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-width-height/ + * Fixed width and height + * @sample {highstock} highcharts/plotoptions/series-marker-width-height/ + * Fixed width and height + * + * @type {number} + * @since 4.0.4 + * @apioption plotOptions.series.marker.width + */ + /** + * States for a single point marker. + * + * @declare Highcharts.PointStatesOptionsObject + */ + states: { + /** + * The normal state of a single point marker. Currently only + * used for setting animation when returning to normal state + * from hover. + * + * @declare Highcharts.PointStatesNormalOptionsObject + */ + normal: { + /** + * Animation when returning to normal state after hovering. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + */ + animation: true + }, + /** + * The hover state for a single point marker. + * + * @declare Highcharts.PointStatesHoverOptionsObject + */ + hover: { + /** + * Animation when hovering over the marker. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + */ + animation: { + /** @internal */ + duration: 50 + }, + /** + * Enable or disable the point marker. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-enabled/ + * Disabled hover state + */ + enabled: true, + /** + * The fill color of the marker in hover state. When + * `undefined`, the series' or point's fillColor for normal + * state is used. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.series.marker.states.hover.fillColor + */ + /** + * The color of the point marker's outline. When + * `undefined`, the series' or point's lineColor for normal + * state is used. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-linecolor/ + * White fill color, black line color + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.series.marker.states.hover.lineColor + */ + /** + * The width of the point marker's outline. When + * `undefined`, the series' or point's lineWidth for normal + * state is used. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-linewidth/ + * 3px line width + * + * @type {number} + * @apioption plotOptions.series.marker.states.hover.lineWidth + */ + /** + * The radius of the point marker. In hover state, it + * defaults to the normal state's radius + 2 as per the + * [radiusPlus](#plotOptions.series.marker.states.hover.radiusPlus) + * option. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-radius/ + * 10px radius + * + * @type {number} + * @apioption plotOptions.series.marker.states.hover.radius + */ + /** + * The number of pixels to increase the radius of the + * hovered point. + * + * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidthplus/ + * 5 pixels greater radius on hover + * @sample {highstock} highcharts/plotoptions/series-states-hover-linewidthplus/ + * 5 pixels greater radius on hover + * + * @since 4.0.3 + */ + radiusPlus: 2, + /** + * The additional line width for a hovered point. + * + * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidthplus/ + * 2 pixels wider on hover + * @sample {highstock} highcharts/plotoptions/series-states-hover-linewidthplus/ + * 2 pixels wider on hover + * + * @since 4.0.3 + */ + lineWidthPlus: 1 + }, + /** + * The appearance of the point marker when selected. In order to + * allow a point to be selected, set the + * `series.allowPointSelect` option to true. + * + * @declare Highcharts.PointStatesSelectOptionsObject + */ + select: { + /** + * Enable or disable visible feedback for selection. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-enabled/ + * Disabled select state + * + * @type {boolean} + * @default true + * @apioption plotOptions.series.marker.states.select.enabled + */ + /** + * The radius of the point marker. In hover state, it + * defaults to the normal state's radius + 2. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-radius/ + * 10px radius for selected points + * + * @type {number} + * @apioption plotOptions.series.marker.states.select.radius + */ + /** + * The fill color of the point marker. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-fillcolor/ + * Solid red discs for selected points + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + fillColor: '#cccccc', + /** + * The color of the point marker's outline. When + * `undefined`, the series' or point's color is used. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-linecolor/ + * Red line color for selected points + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + lineColor: '#000000', + /** + * The width of the point marker's outline. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-linewidth/ + * 3px line width for selected points + */ + lineWidth: 2 + } + } + }, + /** + * Properties for each single point. + * + * @declare Highcharts.PlotSeriesPointOptions + * + * @private + */ + point: { + /** + * Fires when a point is clicked. One parameter, `event`, is passed + * to the function, containing common event information. + * + * If the `series.allowPointSelect` option is true, the default + * action for the point's click event is to toggle the point's + * select state. Returning `false` cancels this action. + * + * @sample {highcharts} highcharts/plotoptions/series-point-events-click/ + * Click marker to alert values + * @sample {highcharts} highcharts/plotoptions/series-point-events-click-column/ + * Click column + * @sample {highcharts} highcharts/plotoptions/series-point-events-click-url/ + * Go to URL + * @sample {highmaps} maps/plotoptions/series-point-events-click/ + * Click marker to display values + * @sample {highmaps} maps/plotoptions/series-point-events-click-url/ + * Go to URL + * + * @type {Highcharts.PointClickCallbackFunction} + * @context Highcharts.Point + * @apioption plotOptions.series.point.events.click + */ + /** + * Fires when the mouse leaves the area close to the point. One + * parameter, `event`, is passed to the function, containing common + * event information. + * + * @sample {highcharts} highcharts/plotoptions/series-point-events-mouseover/ + * Show values in the chart's corner on mouse over + * + * @type {Highcharts.PointMouseOutCallbackFunction} + * @context Highcharts.Point + * @apioption plotOptions.series.point.events.mouseOut + */ + /** + * Fires when the mouse enters the area close to the point. One + * parameter, `event`, is passed to the function, containing common + * event information. + * + * @sample {highcharts} highcharts/plotoptions/series-point-events-mouseover/ + * Show values in the chart's corner on mouse over + * + * @type {Highcharts.PointMouseOverCallbackFunction} + * @context Highcharts.Point + * @apioption plotOptions.series.point.events.mouseOver + */ + /** + * Fires when the point is removed using the `.remove()` method. One + * parameter, `event`, is passed to the function. Returning `false` + * cancels the operation. + * + * @sample {highcharts} highcharts/plotoptions/series-point-events-remove/ + * Remove point and confirm + * + * @type {Highcharts.PointRemoveCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Point + * @apioption plotOptions.series.point.events.remove + */ + /** + * Fires when the point is selected either programmatically or + * following a click on the point. One parameter, `event`, is passed + * to the function. Returning `false` cancels the operation. + * + * @sample {highcharts} highcharts/plotoptions/series-point-events-select/ + * Report the last selected point + * @sample {highmaps} maps/plotoptions/series-allowpointselect/ + * Report select and unselect + * + * @type {Highcharts.PointSelectCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Point + * @apioption plotOptions.series.point.events.select + */ + /** + * Fires when the point is unselected either programmatically or + * following a click on the point. One parameter, `event`, is passed + * to the function. + * Returning `false` cancels the operation. + * + * @sample {highcharts} highcharts/plotoptions/series-point-events-unselect/ + * Report the last unselected point + * @sample {highmaps} maps/plotoptions/series-allowpointselect/ + * Report select and unselect + * + * @type {Highcharts.PointUnselectCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Point + * @apioption plotOptions.series.point.events.unselect + */ + /** + * Fires when the point is updated programmatically through the + * `.update()` method. One parameter, `event`, is passed to the + * function. The new point options can be accessed through + * `event.options`. Returning `false` cancels the operation. + * + * @sample {highcharts} highcharts/plotoptions/series-point-events-update/ + * Confirm point updating + * + * @type {Highcharts.PointUpdateCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Point + * @apioption plotOptions.series.point.events.update + */ + /** + * Events for each single point. + * + * @declare Highcharts.PointEventsOptionsObject + */ + events: {} + }, + /** + * Options for the series data labels, appearing next to each data + * point. + * + * Since v6.2.0, multiple data labels can be applied to each single + * point by defining them as an array of configs. + * + * In styled mode, the data labels can be styled with the + * `.highcharts-data-label-box` and `.highcharts-data-label` class names + * ([see example](https://www.highcharts.com/samples/highcharts/css/series-datalabels)). + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-enabled + * Data labels enabled + * @sample {highcharts} highcharts/plotoptions/series-datalabels-multiple + * Multiple data labels on a bar series + * @sample {highcharts} highcharts/css/series-datalabels + * Style mode example + * + * @type {*|Array<*>} + * @product highcharts highstock highmaps gantt + * + * @private + */ + dataLabels: { + /** + * The alignment of the data label compared to the point. If + * `right`, the right side of the label should be touching the + * point. For points with an extent, like columns, the alignments + * also dictates how to align it inside the box, as given with the + * [inside](#plotOptions.column.dataLabels.inside) + * option. Can be one of `left`, `center` or `right`. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-align-left/ + * Left aligned + * @sample {highcharts} highcharts/plotoptions/bar-datalabels-align-inside-bar/ + * Data labels inside the bar + * + * @type {Highcharts.AlignValue|null} + */ + align: 'center', + /** + * Whether to allow data labels to overlap. To make the labels less + * sensitive for overlapping, the + * [dataLabels.padding](#plotOptions.series.dataLabels.padding) + * can be set to 0. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-allowoverlap-false/ + * Don't allow overlap + * + * @type {boolean} + * @default false + * @since 4.1.0 + * @apioption plotOptions.series.dataLabels.allowOverlap + */ + /** + * The background color or gradient for the data label. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/ + * Data labels box options + * @sample {highmaps} maps/plotoptions/series-datalabels-box/ + * Data labels box options + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.2.1 + * @apioption plotOptions.series.dataLabels.backgroundColor + */ + /** + * The border color for the data label. Defaults to `undefined`. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/ + * Data labels box options + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.2.1 + * @apioption plotOptions.series.dataLabels.borderColor + */ + /** + * The border radius in pixels for the data label. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/ + * Data labels box options + * @sample {highmaps} maps/plotoptions/series-datalabels-box/ + * Data labels box options + * + * @type {number} + * @default 0 + * @since 2.2.1 + * @apioption plotOptions.series.dataLabels.borderRadius + */ + /** + * The border width in pixels for the data label. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/ + * Data labels box options + * + * @type {number} + * @default 0 + * @since 2.2.1 + * @apioption plotOptions.series.dataLabels.borderWidth + */ + /** + * A class name for the data label. Particularly in styled mode, + * this can be used to give each series' or point's data label + * unique styling. In addition to this option, a default color class + * name is added so that we can give the labels a contrast text + * shadow. + * + * @sample {highcharts} highcharts/css/data-label-contrast/ + * Contrast text shadow + * @sample {highcharts} highcharts/css/series-datalabels/ + * Styling by CSS + * + * @type {string} + * @since 5.0.0 + * @apioption plotOptions.series.dataLabels.className + */ + /** + * The text color for the data labels. Defaults to `undefined`. For + * certain series types, like column or map, the data labels can be + * drawn inside the points. In this case the data label will be + * drawn with maximum contrast by default. Additionally, it will be + * given a `text-outline` style with the opposite color, to further + * increase the contrast. This can be overridden by setting the + * `text-outline` style to `none` in the `dataLabels.style` option. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-color/ + * Red data labels + * @sample {highmaps} maps/demo/color-axis/ + * White data labels + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.series.dataLabels.color + */ + /** + * Whether to hide data labels that are outside the plot area. By + * default, the data label is moved inside the plot area according + * to the + * [overflow](#plotOptions.series.dataLabels.overflow) + * option. + * + * @type {boolean} + * @default true + * @since 2.3.3 + * @apioption plotOptions.series.dataLabels.crop + */ + /** + * Whether to defer displaying the data labels until the initial + * series animation has finished. + * + * @type {boolean} + * @default true + * @since 4.0.0 + * @product highcharts highstock gantt + * @apioption plotOptions.series.dataLabels.defer + */ + /** + * Enable or disable the data labels. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-enabled/ + * Data labels enabled + * @sample {highmaps} maps/demo/color-axis/ + * Data labels enabled + * + * @type {boolean} + * @default false + * @apioption plotOptions.series.dataLabels.enabled + */ + /** + * A declarative filter to control of which data labels to display. + * The declarative filter is designed for use when callback + * functions are not available, like when the chart options require + * a pure JSON structure or for use with graphical editors. For + * programmatic control, use the `formatter` instead, and return + * `undefined` to disable a single data label. + * + * @example + * filter: { + * property: 'percentage', + * operator: '>', + * value: 4 + * } + * + * @sample {highcharts} highcharts/demo/pie-monochrome + * Data labels filtered by percentage + * + * @declare Highcharts.DataLabelsFilterOptionsObject + * @since 6.0.3 + * @apioption plotOptions.series.dataLabels.filter + */ + /** + * The operator to compare by. Can be one of `>`, `<`, `>=`, `<=`, + * `==`, and `===`. + * + * @type {string} + * @validvalue [">", "<", ">=", "<=", "==", "==="] + * @apioption plotOptions.series.dataLabels.filter.operator + */ + /** + * The point property to filter by. Point options are passed + * directly to properties, additionally there are `y` value, + * `percentage` and others listed under {@link Highcharts.Point} + * members. + * + * @type {string} + * @apioption plotOptions.series.dataLabels.filter.property + */ + /** + * The value to compare against. + * + * @type {number} + * @apioption plotOptions.series.dataLabels.filter.value + */ + /** + * A + * [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) + * for the data label. Available variables are the same as for + * `formatter`. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-format/ + * Add a unit + * @sample {highmaps} maps/plotoptions/series-datalabels-format/ + * Formatted value in the data label + * + * @type {string} + * @default y + * @default point.value + * @since 3.0 + * @apioption plotOptions.series.dataLabels.format + */ + // eslint-disable-next-line valid-jsdoc + /** + * Callback JavaScript function to format the data label. Note that + * if a `format` is defined, the format takes precedence and the + * formatter is ignored. + * + * @sample {highmaps} maps/plotoptions/series-datalabels-format/ + * Formatted value + * + * @type {Highcharts.DataLabelsFormatterCallbackFunction} + */ + formatter: function () { + var numberFormatter = this.series.chart.numberFormatter; + return typeof this.y !== 'number' ? '' : numberFormatter(this.y, -1); + }, + /** + * For points with an extent, like columns or map areas, whether to + * align the data label inside the box or to the actual value point. + * Defaults to `false` in most cases, `true` in stacked columns. + * + * @type {boolean} + * @since 3.0 + * @apioption plotOptions.series.dataLabels.inside + */ + /** + * Format for points with the value of null. Works analogously to + * [format](#plotOptions.series.dataLabels.format). `nullFormat` can + * be applied only to series which support displaying null points. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-format/ + * Format data label and tooltip for null point. + * + * @type {boolean|string} + * @since 7.1.0 + * @apioption plotOptions.series.dataLabels.nullFormat + */ + /** + * Callback JavaScript function that defines formatting for points + * with the value of null. Works analogously to + * [formatter](#plotOptions.series.dataLabels.formatter). + * `nullPointFormatter` can be applied only to series which support + * displaying null points. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-format/ + * Format data label and tooltip for null point. + * + * @type {Highcharts.DataLabelsFormatterCallbackFunction} + * @since 7.1.0 + * @apioption plotOptions.series.dataLabels.nullFormatter + */ + /** + * How to handle data labels that flow outside the plot area. The + * default is `"justify"`, which aligns them inside the plot area. + * For columns and bars, this means it will be moved inside the bar. + * To display data labels outside the plot area, set `crop` to + * `false` and `overflow` to `"allow"`. + * + * @type {Highcharts.DataLabelsOverflowValue} + * @default justify + * @since 3.0.6 + * @apioption plotOptions.series.dataLabels.overflow + */ + /** + * When either the `borderWidth` or the `backgroundColor` is set, + * this is the padding within the box. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/ + * Data labels box options + * @sample {highmaps} maps/plotoptions/series-datalabels-box/ + * Data labels box options + * + * @since 2.2.1 + */ + padding: 5, + /** + * Aligns data labels relative to points. If `center` alignment is + * not possible, it defaults to `right`. + * + * @type {Highcharts.AlignValue} + * @default center + * @apioption plotOptions.series.dataLabels.position + */ + /** + * Text rotation in degrees. Note that due to a more complex + * structure, backgrounds, borders and padding will be lost on a + * rotated data label. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-rotation/ + * Vertical labels + * + * @type {number} + * @default 0 + * @apioption plotOptions.series.dataLabels.rotation + */ + /** + * The shadow of the box. Works best with `borderWidth` or + * `backgroundColor`. Since 2.3 the shadow can be an object + * configuration containing `color`, `offsetX`, `offsetY`, `opacity` + * and `width`. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/ + * Data labels box options + * + * @type {boolean|Highcharts.ShadowOptionsObject} + * @default false + * @since 2.2.1 + * @apioption plotOptions.series.dataLabels.shadow + */ + /** + * The name of a symbol to use for the border around the label. + * Symbols are predefined functions on the Renderer object. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-shape/ + * A callout for annotations + * + * @type {string} + * @default square + * @since 4.1.2 + * @apioption plotOptions.series.dataLabels.shape + */ + /** + * Styles for the label. The default `color` setting is + * `"contrast"`, which is a pseudo color that Highcharts picks up + * and applies the maximum contrast to the underlying point item, + * for example the bar in a bar chart. + * + * The `textOutline` is a pseudo property that applies an outline of + * the given width with the given color, which by default is the + * maximum contrast to the text. So a bright text color will result + * in a black text outline for maximum readability on a mixed + * background. In some cases, especially with grayscale text, the + * text outline doesn't work well, in which cases it can be disabled + * by setting it to `"none"`. When `useHTML` is true, the + * `textOutline` will not be picked up. In this, case, the same + * effect can be acheived through the `text-shadow` CSS property. + * + * For some series types, where each point has an extent, like for + * example tree maps, the data label may overflow the point. There + * are two strategies for handling overflow. By default, the text + * will wrap to multiple lines. The other strategy is to set + * `style.textOverflow` to `ellipsis`, which will keep the text on + * one line plus it will break inside long words. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-style/ + * Bold labels + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow/ + * Long labels truncated with an ellipsis in a pie + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow-wrap/ + * Long labels are wrapped in a pie + * @sample {highmaps} maps/demo/color-axis/ + * Bold labels + * + * @type {Highcharts.CSSObject} + * @since 4.1.0 + * @apioption plotOptions.series.dataLabels.style + */ + style: { + /** @internal */ + fontSize: '11px', + /** @internal */ + fontWeight: 'bold', + /** @internal */ + color: 'contrast', + /** @internal */ + textOutline: '1px contrast' + }, + /** + * Options for a label text which should follow marker's shape. + * Border and background are disabled for a label that follows a + * path. + * + * **Note:** Only SVG-based renderer supports this option. Setting + * `useHTML` to true will disable this option. + * + * @declare Highcharts.DataLabelsTextPathOptionsObject + * @since 7.1.0 + * @apioption plotOptions.series.dataLabels.textPath + */ + /** + * Presentation attributes for the text path. + * + * @type {Highcharts.SVGAttributes} + * @since 7.1.0 + * @apioption plotOptions.series.dataLabels.textPath.attributes + */ + /** + * Enable or disable `textPath` option for link's or marker's data + * labels. + * + * @type {boolean} + * @since 7.1.0 + * @apioption plotOptions.series.dataLabels.textPath.enabled + */ + /** + * Whether to + * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the labels. + * + * @type {boolean} + * @default false + * @apioption plotOptions.series.dataLabels.useHTML + */ + /** + * The vertical alignment of a data label. Can be one of `top`, + * `middle` or `bottom`. The default value depends on the data, for + * instance in a column chart, the label is above positive values + * and below negative values. + * + * @type {Highcharts.VerticalAlignValue|null} + * @since 2.3.3 + */ + verticalAlign: 'bottom', + /** + * The x position offset of the label relative to the point in + * pixels. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-rotation/ + * Vertical and positioned + * @sample {highcharts} highcharts/plotoptions/bar-datalabels-align-inside-bar/ + * Data labels inside the bar + */ + x: 0, + /** + * The Z index of the data labels. The default Z index puts it above + * the series. Use a Z index of 2 to display it behind the series. + * + * @type {number} + * @default 6 + * @since 2.3.5 + * @apioption plotOptions.series.dataLabels.z + */ + /** + * The y position offset of the label relative to the point in + * pixels. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-rotation/ + * Vertical and positioned + */ + y: 0 + }, + /** + * When the series contains less points than the crop threshold, all + * points are drawn, even if the points fall outside the visible plot + * area at the current zoom. The advantage of drawing all points + * (including markers and columns), is that animation is performed on + * updates. On the other hand, when the series contains more points than + * the crop threshold, the series data is cropped to only contain points + * that fall within the plot area. The advantage of cropping away + * invisible points is to increase performance on large series. + * + * @since 2.2 + * @product highcharts highstock + * + * @private + */ + cropThreshold: 300, + /** + * Opacity of a series parts: line, fill (e.g. area) and dataLabels. + * + * @see [states.inactive.opacity](#plotOptions.series.states.inactive.opacity) + * + * @since 7.1.0 + * + * @private + */ + opacity: 1, + /** + * The width of each point on the x axis. For example in a column chart + * with one value each day, the pointRange would be 1 day (= 24 * 3600 + * * 1000 milliseconds). This is normally computed automatically, but + * this option can be used to override the automatic value. + * + * @product highstock + * + * @private + */ + pointRange: 0, + /** + * When this is true, the series will not cause the Y axis to cross + * the zero plane (or [threshold](#plotOptions.series.threshold) option) + * unless the data actually crosses the plane. + * + * For example, if `softThreshold` is `false`, a series of 0, 1, 2, + * 3 will make the Y axis show negative values according to the + * `minPadding` option. If `softThreshold` is `true`, the Y axis starts + * at 0. + * + * @since 4.1.9 + * @product highcharts highstock + * + * @private + */ + softThreshold: true, + /** + * @declare Highcharts.SeriesStatesOptionsObject + * + * @private + */ + states: { + /** + * The normal state of a series, or for point items in column, pie + * and similar series. Currently only used for setting animation + * when returning to normal state from hover. + * + * @declare Highcharts.SeriesStatesNormalOptionsObject + */ + normal: { + /** + * Animation when returning to normal state after hovering. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + */ + animation: true + }, + /** + * Options for the hovered series. These settings override the + * normal state options when a series is moused over or touched. + * + * @declare Highcharts.SeriesStatesHoverOptionsObject + */ + hover: { + /** + * Enable separate styles for the hovered series to visualize + * that the user hovers either the series itself or the legend. + * + * @sample {highcharts} highcharts/plotoptions/series-states-hover-enabled/ + * Line + * @sample {highcharts} highcharts/plotoptions/series-states-hover-enabled-column/ + * Column + * @sample {highcharts} highcharts/plotoptions/series-states-hover-enabled-pie/ + * Pie + * + * @type {boolean} + * @default true + * @since 1.2 + * @apioption plotOptions.series.states.hover.enabled + */ + /** + * Animation setting for hovering the graph in line-type series. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + * @since 5.0.8 + * @product highcharts highstock + */ + animation: { + /** + * The duration of the hover animation in milliseconds. By + * default the hover state animates quickly in, and slowly + * back to normal. + * + * @internal + */ + duration: 50 + }, + /** + * Pixel width of the graph line. By default this property is + * undefined, and the `lineWidthPlus` property dictates how much + * to increase the linewidth from normal state. + * + * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidth/ + * 5px line on hover + * + * @type {number} + * @product highcharts highstock + * @apioption plotOptions.series.states.hover.lineWidth + */ + /** + * The additional line width for the graph of a hovered series. + * + * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidthplus/ + * 5 pixels wider + * @sample {highstock} highcharts/plotoptions/series-states-hover-linewidthplus/ + * 5 pixels wider + * + * @since 4.0.3 + * @product highcharts highstock + */ + lineWidthPlus: 1, + /** + * In Highcharts 1.0, the appearance of all markers belonging + * to the hovered series. For settings on the hover state of the + * individual point, see + * [marker.states.hover](#plotOptions.series.marker.states.hover). + * + * @deprecated + * + * @extends plotOptions.series.marker + * @excluding states + * @product highcharts highstock + */ + marker: { + // lineWidth: base + 1, + // radius: base + 1 + }, + /** + * Options for the halo appearing around the hovered point in + * line-type series as well as outside the hovered slice in pie + * charts. By default the halo is filled by the current point or + * series color with an opacity of 0.25\. The halo can be + * disabled by setting the `halo` option to `null`. + * + * In styled mode, the halo is styled with the + * `.highcharts-halo` class, with colors inherited from + * `.highcharts-color-{n}`. + * + * @sample {highcharts} highcharts/plotoptions/halo/ + * Halo options + * @sample {highstock} highcharts/plotoptions/halo/ + * Halo options + * + * @declare Highcharts.SeriesStatesHoverHaloOptionsObject + * @type {null|*} + * @since 4.0 + * @product highcharts highstock + */ + halo: { + /** + * A collection of SVG attributes to override the appearance + * of the halo, for example `fill`, `stroke` and + * `stroke-width`. + * + * @type {Highcharts.SVGAttributes} + * @since 4.0 + * @product highcharts highstock + * @apioption plotOptions.series.states.hover.halo.attributes + */ + /** + * The pixel size of the halo. For point markers this is the + * radius of the halo. For pie slices it is the width of the + * halo outside the slice. For bubbles it defaults to 5 and + * is the width of the halo outside the bubble. + * + * @since 4.0 + * @product highcharts highstock + */ + size: 10, + /** + * Opacity for the halo unless a specific fill is overridden + * using the `attributes` setting. Note that Highcharts is + * only able to apply opacity to colors of hex or rgb(a) + * formats. + * + * @since 4.0 + * @product highcharts highstock + */ + opacity: 0.25 + } + }, + /** + * Specific options for point in selected states, after being + * selected by + * [allowPointSelect](#plotOptions.series.allowPointSelect) + * or programmatically. + * + * @sample maps/plotoptions/series-allowpointselect/ + * Allow point select demo + * + * @declare Highcharts.SeriesStatesSelectOptionsObject + * @extends plotOptions.series.states.hover + * @excluding brightness + */ + select: { + animation: { + /** @internal */ + duration: 0 + } + }, + /** + * The opposite state of a hover for series. + * + * @sample highcharts/plotoptions/series-states-inactive-disabled + * Disabled inactive state + * + * @declare Highcharts.SeriesStatesInactiveOptionsObject + */ + inactive: { + /** + * Enable or disable the inactive state for a series + * + * @sample highcharts/plotoptions/series-states-inactive-disabled + * Disabled inactive state + * + * @type {boolean} + * @default true + * @apioption plotOptions.series.states.inactive.enabled + */ + /** + * The animation for entering the inactive state. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + */ + animation: { + /** @internal */ + duration: 50 + }, + /** + * Opacity of series elements (dataLabels, line, area). + * + * @type {number} + */ + opacity: 0.2 + } + }, + /** + * Sticky tracking of mouse events. When true, the `mouseOut` event on a + * series isn't triggered until the mouse moves over another series, or + * out of the plot area. When false, the `mouseOut` event on a series is + * triggered when the mouse leaves the area around the series' graph or + * markers. This also implies the tooltip when not shared. When + * `stickyTracking` is false and `tooltip.shared` is false, the tooltip + * will be hidden when moving the mouse between series. Defaults to true + * for line and area type series, but to false for columns, pies etc. + * + * **Note:** The boost module will force this option because of + * technical limitations. + * + * @sample {highcharts} highcharts/plotoptions/series-stickytracking-true/ + * True by default + * @sample {highcharts} highcharts/plotoptions/series-stickytracking-false/ + * False + * + * @default {highcharts} true + * @default {highstock} true + * @default {highmaps} false + * @since 2.0 + * + * @private + */ + stickyTracking: true, + /** + * A configuration object for the tooltip rendering of each single + * series. Properties are inherited from [tooltip](#tooltip), but only + * the following properties can be defined on a series level. + * + * @declare Highcharts.SeriesTooltipOptionsObject + * @since 2.3 + * @extends tooltip + * @excluding animation, backgroundColor, borderColor, borderRadius, + * borderWidth, className, crosshairs, enabled, formatter, + * headerShape, hideDelay, outside, padding, positioner, + * shadow, shape, shared, snap, split, style, useHTML + * @apioption plotOptions.series.tooltip + */ + /** + * When a series contains a data array that is longer than this, only + * one dimensional arrays of numbers, or two dimensional arrays with + * x and y values are allowed. Also, only the first point is tested, + * and the rest are assumed to be the same format. This saves expensive + * data checking and indexing in long series. Set it to `0` disable. + * + * Note: + * In boost mode turbo threshold is forced. Only array of numbers or + * two dimensional arrays are allowed. + * + * @since 2.2 + * @product highcharts highstock gantt + * + * @private + */ + turboThreshold: 1000, + /** + * An array defining zones within a series. Zones can be applied to the + * X axis, Y axis or Z axis for bubbles, according to the `zoneAxis` + * option. The zone definitions have to be in ascending order regarding + * to the value. + * + * In styled mode, the color zones are styled with the + * `.highcharts-zone-{n}` class, or custom classed from the `className` + * option + * ([view live demo](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/css/color-zones/)). + * + * @see [zoneAxis](#plotOptions.series.zoneAxis) + * + * @sample {highcharts} highcharts/series/color-zones-simple/ + * Color zones + * @sample {highstock} highcharts/series/color-zones-simple/ + * Color zones + * + * @declare Highcharts.SeriesZonesOptionsObject + * @type {Array<*>} + * @since 4.1.0 + * @product highcharts highstock + * @apioption plotOptions.series.zones + */ + /** + * Styled mode only. A custom class name for the zone. + * + * @sample highcharts/css/color-zones/ + * Zones styled by class name + * + * @type {string} + * @since 5.0.0 + * @apioption plotOptions.series.zones.className + */ + /** + * Defines the color of the series. + * + * @see [series color](#plotOptions.series.color) + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 4.1.0 + * @product highcharts highstock + * @apioption plotOptions.series.zones.color + */ + /** + * A name for the dash style to use for the graph. + * + * @see [plotOptions.series.dashStyle](#plotOptions.series.dashStyle) + * + * @sample {highcharts|highstock} highcharts/series/color-zones-dashstyle-dot/ + * Dashed line indicates prognosis + * + * @type {Highcharts.DashStyleValue} + * @since 4.1.0 + * @product highcharts highstock + * @apioption plotOptions.series.zones.dashStyle + */ + /** + * Defines the fill color for the series (in area type series) + * + * @see [fillColor](#plotOptions.area.fillColor) + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 4.1.0 + * @product highcharts highstock + * @apioption plotOptions.series.zones.fillColor + */ + /** + * The value up to where the zone extends, if undefined the zones + * stretches to the last value in the series. + * + * @type {number} + * @since 4.1.0 + * @product highcharts highstock + * @apioption plotOptions.series.zones.value + */ + /** + * When using dual or multiple color axes, this number defines which + * colorAxis the particular series is connected to. It refers to + * either the + * {@link #colorAxis.id|axis id} + * or the index of the axis in the colorAxis array, with 0 being the + * first. Set this option to false to prevent a series from connecting + * to the default color axis. + * + * Since v7.2.0 the option can also be an axis id or an axis index + * instead of a boolean flag. + * + * @sample highcharts/coloraxis/coloraxis-with-pie/ + * Color axis with pie series + * @sample highcharts/coloraxis/multiple-coloraxis/ + * Multiple color axis + * + * @type {number|string|boolean} + * @default 0 + * @product highcharts highstock highmaps + * @apioption plotOptions.series.colorAxis + */ + /** + * Determines what data value should be used to calculate point color + * if `colorAxis` is used. Requires to set `min` and `max` if some + * custom point property is used or if approximation for data grouping + * is set to `'sum'`. + * + * @sample highcharts/coloraxis/custom-color-key/ + * Custom color key + * @sample highcharts/coloraxis/changed-default-color-key/ + * Changed default color key + * + * @type {string} + * @default y + * @since 7.2.0 + * @product highcharts highstock highmaps + * @apioption plotOptions.series.colorKey + */ + /** + * Determines whether the series should look for the nearest point + * in both dimensions or just the x-dimension when hovering the series. + * Defaults to `'xy'` for scatter series and `'x'` for most other + * series. If the data has duplicate x-values, it is recommended to + * set this to `'xy'` to allow hovering over all points. + * + * Applies only to series types using nearest neighbor search (not + * direct hover) for tooltip. + * + * @sample {highcharts} highcharts/series/findnearestpointby/ + * Different hover behaviors + * @sample {highstock} highcharts/series/findnearestpointby/ + * Different hover behaviors + * @sample {highmaps} highcharts/series/findnearestpointby/ + * Different hover behaviors + * + * @since 5.0.10 + * @validvalue ["x", "xy"] + * + * @private + */ + findNearestPointBy: 'x' +}, +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** @lends Highcharts.Series.prototype */ +{ + axisTypes: ['xAxis', 'yAxis'], + coll: 'series', + colorCounter: 0, + cropShoulder: 1, + directTouch: false, + eventsToUnbind: [], + isCartesian: true, + // each point's x and y values are stored in this.xData and this.yData + parallelArrays: ['x', 'y'], + pointClass: Point, + requireSorting: true, + sorted: true, + init: function (chart, options) { + fireEvent(this, 'init', { options: options }); + var series = this, events, chartSeries = chart.series, lastSeries; + // A lookup over those events that are added by _options_ (not + // programmatically). These are updated through Series.update() + // (#10861). + this.eventOptions = this.eventOptions || {}; + /** + * Read only. The chart that the series belongs to. + * + * @name Highcharts.Series#chart + * @type {Highcharts.Chart} + */ + series.chart = chart; + /** + * Read only. The series' type, like "line", "area", "column" etc. + * The type in the series options anc can be altered using + * {@link Series#update}. + * + * @name Highcharts.Series#type + * @type {string} + */ + /** + * Read only. The series' current options. To update, use + * {@link Series#update}. + * + * @name Highcharts.Series#options + * @type {Highcharts.SeriesOptionsType} + */ + series.options = options = series.setOptions(options); + series.linkedSeries = []; + // bind the axes + series.bindAxes(); + // set some variables + extend(series, { + /** + * The series name as given in the options. Defaults to + * "Series {n}". + * + * @name Highcharts.Series#name + * @type {string} + */ + name: options.name, + state: '', + /** + * Read only. The series' visibility state as set by {@link + * Series#show}, {@link Series#hide}, or in the initial + * configuration. + * + * @name Highcharts.Series#visible + * @type {boolean} + */ + visible: options.visible !== false, + /** + * Read only. The series' selected state as set by {@link + * Highcharts.Series#select}. + * + * @name Highcharts.Series#selected + * @type {boolean} + */ + selected: options.selected === true // false by default + }); + // Register event listeners + events = options.events; + objectEach(events, function (event, eventType) { + if (isFunction(event)) { + // If event does not exist, or is changed by Series.update + if (series.eventOptions[eventType] !== event) { + // Remove existing if set by option + if (isFunction(series.eventOptions[eventType])) { + removeEvent(series, eventType, series.eventOptions[eventType]); + } + series.eventOptions[eventType] = event; + addEvent(series, eventType, event); + } + } + }); + if ((events && events.click) || + (options.point && + options.point.events && + options.point.events.click) || + options.allowPointSelect) { + chart.runTrackerClick = true; + } + series.getColor(); + series.getSymbol(); + // Initialize the parallel data arrays + series.parallelArrays.forEach(function (key) { + if (!series[key + 'Data']) { + series[key + 'Data'] = []; + } + }); + // Mark cartesian + if (series.isCartesian) { + chart.hasCartesianSeries = true; + } + // Get the index and register the series in the chart. The index is + // one more than the current latest series index (#5960). + if (chartSeries.length) { + lastSeries = chartSeries[chartSeries.length - 1]; + } + series._i = pick(lastSeries && lastSeries._i, -1) + 1; + // Insert the series and re-order all series above the insertion + // point. + chart.orderSeries(this.insert(chartSeries)); + // Set options for series with sorting and set data later. + if (options.dataSorting && options.dataSorting.enabled) { + series.setDataSortingOptions(); + } + else if (!series.points && !series.data) { + series.setData(options.data, false); + } + fireEvent(this, 'afterInit'); + }, + /** + * Check whether the series item is itself or inherits from a certain + * series type. + * + * @function Highcharts.Series#is + * @param {string} type The type of series to check for, can be either + * featured or custom series types. For example `column`, `pie`, + * `ohlc` etc. + * + * @return {boolean} + * True if this item is or inherits from the given type. + */ + is: function (type) { + return seriesTypes[type] && this instanceof seriesTypes[type]; + }, + /** + * Insert the series in a collection with other series, either the chart + * series or yAxis series, in the correct order according to the index + * option. Used internally when adding series. + * + * @private + * @function Highcharts.Series#insert + * @param {Array} collection + * A collection of series, like `chart.series` or `xAxis.series`. + * @return {number} + * The index of the series in the collection. + */ + insert: function (collection) { + var indexOption = this.options.index, i; + // Insert by index option + if (isNumber(indexOption)) { + i = collection.length; + while (i--) { + // Loop down until the interted element has higher index + if (indexOption >= + pick(collection[i].options.index, collection[i]._i)) { + collection.splice(i + 1, 0, this); + break; + } + } + if (i === -1) { + collection.unshift(this); + } + i = i + 1; + // Or just push it to the end + } + else { + collection.push(this); + } + return pick(i, collection.length - 1); + }, + /** + * Set the xAxis and yAxis properties of cartesian series, and register + * the series in the `axis.series` array. + * + * @private + * @function Highcharts.Series#bindAxes + * @return {void} + * @exception 18 + */ + bindAxes: function () { + var series = this, seriesOptions = series.options, chart = series.chart, axisOptions; + fireEvent(this, 'bindAxes', null, function () { + // repeat for xAxis and yAxis + (series.axisTypes || []).forEach(function (AXIS) { + // loop through the chart's axis objects + chart[AXIS].forEach(function (axis) { + axisOptions = axis.options; + // apply if the series xAxis or yAxis option mathches + // the number of the axis, or if undefined, use the + // first axis + if (seriesOptions[AXIS] === + axisOptions.index || + (typeof seriesOptions[AXIS] !== + 'undefined' && + seriesOptions[AXIS] === axisOptions.id) || + (typeof seriesOptions[AXIS] === + 'undefined' && + axisOptions.index === 0)) { + // register this series in the axis.series lookup + series.insert(axis.series); + // set this series.xAxis or series.yAxis reference + /** + * Read only. The unique xAxis object associated + * with the series. + * + * @name Highcharts.Series#xAxis + * @type {Highcharts.Axis} + */ + /** + * Read only. The unique yAxis object associated + * with the series. + * + * @name Highcharts.Series#yAxis + * @type {Highcharts.Axis} + */ + series[AXIS] = axis; + // mark dirty for redraw + axis.isDirty = true; + } + }); + // The series needs an X and an Y axis + if (!series[AXIS] && + series.optionalAxis !== AXIS) { + error(18, true, chart); + } + }); + }); + fireEvent(this, 'afterBindAxes'); + }, + /** + * For simple series types like line and column, the data values are + * held in arrays like xData and yData for quick lookup to find extremes + * and more. For multidimensional series like bubble and map, this can + * be extended with arrays like zData and valueData by adding to the + * `series.parallelArrays` array. + * + * @private + * @function Highcharts.Series#updateParallelArrays + * @param {Highcharts.Point} point + * @param {number|string} i + * @return {void} + */ + updateParallelArrays: function (point, i) { + var series = point.series, args = arguments, fn = isNumber(i) ? + // Insert the value in the given position + function (key) { + var val = key === 'y' && series.toYData ? + series.toYData(point) : + point[key]; + series[key + 'Data'][i] = val; + } : + // Apply the method specified in i with the following + // arguments as arguments + function (key) { + Array.prototype[i].apply(series[key + 'Data'], Array.prototype.slice.call(args, 2)); + }; + series.parallelArrays.forEach(fn); + }, + /** + * Define hasData functions for series. These return true if there + * are data points on this series within the plot area. + * + * @private + * @function Highcharts.Series#hasData + * @return {boolean} + */ + hasData: function () { + return ((this.visible && + typeof this.dataMax !== 'undefined' && + typeof this.dataMin !== 'undefined') || ( // #3703 + this.visible && + this.yData && + this.yData.length > 0) // #9758 + ); + }, + /** + * Return an auto incremented x value based on the pointStart and + * pointInterval options. This is only used if an x value is not given + * for the point that calls autoIncrement. + * + * @private + * @function Highcharts.Series#autoIncrement + * @return {number} + */ + autoIncrement: function () { + var options = this.options, xIncrement = this.xIncrement, date, pointInterval, pointIntervalUnit = options.pointIntervalUnit, time = this.chart.time; + xIncrement = pick(xIncrement, options.pointStart, 0); + this.pointInterval = pointInterval = pick(this.pointInterval, options.pointInterval, 1); + // Added code for pointInterval strings + if (pointIntervalUnit) { + date = new time.Date(xIncrement); + if (pointIntervalUnit === 'day') { + time.set('Date', date, time.get('Date', date) + pointInterval); + } + else if (pointIntervalUnit === 'month') { + time.set('Month', date, time.get('Month', date) + pointInterval); + } + else if (pointIntervalUnit === 'year') { + time.set('FullYear', date, time.get('FullYear', date) + pointInterval); + } + pointInterval = date.getTime() - xIncrement; + } + this.xIncrement = xIncrement + pointInterval; + return xIncrement; + }, + /** + * Internal function to set properties for series if data sorting is + * enabled. + * + * @private + * @function Highcharts.Series#setDataSortingOptions + * @return {void} + */ + setDataSortingOptions: function () { + var options = this.options; + extend(this, { + requireSorting: false, + sorted: false, + enabledDataSorting: true, + allowDG: false + }); + // To allow unsorted data for column series. + if (!defined(options.pointRange)) { + options.pointRange = 1; + } + }, + /** + * Set the series options by merging from the options tree. Called + * internally on initializing and updating series. This function will + * not redraw the series. For API usage, use {@link Series#update}. + * @private + * @function Highcharts.Series#setOptions + * @param {Highcharts.SeriesOptionsType} itemOptions + * The series options. + * @return {Highcharts.SeriesOptionsType} + * @fires Highcharts.Series#event:afterSetOptions + */ + setOptions: function (itemOptions) { + var chart = this.chart, chartOptions = chart.options, plotOptions = chartOptions.plotOptions, userOptions = chart.userOptions || {}, seriesUserOptions = merge(itemOptions), options, zones, zone, styledMode = chart.styledMode, e = { + plotOptions: plotOptions, + userOptions: seriesUserOptions + }; + fireEvent(this, 'setOptions', e); + // These may be modified by the event + var typeOptions = e.plotOptions[this.type], userPlotOptions = (userOptions.plotOptions || {}); + // use copy to prevent undetected changes (#9762) + this.userOptions = e.userOptions; + options = merge(typeOptions, plotOptions.series, + // #3881, chart instance plotOptions[type] should trump + // plotOptions.series + userOptions.plotOptions && + userOptions.plotOptions[this.type], seriesUserOptions); + // The tooltip options are merged between global and series specific + // options. Importance order asscendingly: + // globals: (1)tooltip, (2)plotOptions.series, + // (3)plotOptions[this.type] + // init userOptions with possible later updates: 4-6 like 1-3 and + // (7)this series options + this.tooltipOptions = merge(defaultOptions.tooltip, // 1 + defaultOptions.plotOptions.series && + defaultOptions.plotOptions.series.tooltip, // 2 + defaultOptions.plotOptions[this.type].tooltip, // 3 + chartOptions.tooltip.userOptions, // 4 + plotOptions.series && + plotOptions.series.tooltip, // 5 + plotOptions[this.type].tooltip, // 6 + seriesUserOptions.tooltip // 7 + ); + // When shared tooltip, stickyTracking is true by default, + // unless user says otherwise. + this.stickyTracking = pick(seriesUserOptions.stickyTracking, userPlotOptions[this.type] && + userPlotOptions[this.type].stickyTracking, userPlotOptions.series && userPlotOptions.series.stickyTracking, (this.tooltipOptions.shared && !this.noSharedTooltip ? + true : + options.stickyTracking)); + // Delete marker object if not allowed (#1125) + if (typeOptions.marker === null) { + delete options.marker; + } + // Handle color zones + this.zoneAxis = options.zoneAxis; + zones = this.zones = (options.zones || []).slice(); + if ((options.negativeColor || options.negativeFillColor) && + !options.zones) { + zone = { + value: options[this.zoneAxis + 'Threshold'] || + options.threshold || + 0, + className: 'highcharts-negative' + }; + if (!styledMode) { + zone.color = options.negativeColor; + zone.fillColor = options.negativeFillColor; + } + zones.push(zone); + } + if (zones.length) { // Push one extra zone for the rest + if (defined(zones[zones.length - 1].value)) { + zones.push(styledMode ? {} : { + color: this.color, + fillColor: this.fillColor + }); + } + } + fireEvent(this, 'afterSetOptions', { options: options }); + return options; + }, + /** + * Return series name in "Series {Number}" format or the one defined by + * a user. This method can be simply overridden as series name format + * can vary (e.g. technical indicators). + * + * @function Highcharts.Series#getName + * @return {string} + * The series name. + */ + getName: function () { + // #4119 + return pick(this.options.name, 'Series ' + (this.index + 1)); + }, + /** + * @private + * @function Highcharts.Series#getCyclic + * @param {string} prop + * @param {*} [value] + * @param {Highcharts.Dictionary} [defaults] + * @return {void} + */ + getCyclic: function (prop, value, defaults) { + var i, chart = this.chart, userOptions = this.userOptions, indexName = prop + 'Index', counterName = prop + 'Counter', len = defaults ? defaults.length : pick(chart.options.chart[prop + 'Count'], chart[prop + 'Count']), setting; + if (!value) { + // Pick up either the colorIndex option, or the _colorIndex + // after Series.update() + setting = pick(userOptions[indexName], userOptions['_' + indexName]); + if (defined(setting)) { // after Series.update() + i = setting; + } + else { + // #6138 + if (!chart.series.length) { + chart[counterName] = 0; + } + userOptions['_' + indexName] = i = + chart[counterName] % len; + chart[counterName] += 1; + } + if (defaults) { + value = defaults[i]; + } + } + // Set the colorIndex + if (typeof i !== 'undefined') { + this[indexName] = i; + } + this[prop] = value; + }, + /** + * Get the series' color based on either the options or pulled from + * global options. + * + * @private + * @function Highcharts.Series#getColor + * @return {void} + */ + getColor: function () { + if (this.chart.styledMode) { + this.getCyclic('color'); + } + else if (this.options.colorByPoint) { + // #4359, selected slice got series.color even when colorByPoint + // was set. + this.options.color = null; + } + else { + this.getCyclic('color', this.options.color || + defaultPlotOptions[this.type].color, this.chart.options.colors); + } + }, + /** + * Get all points' instances created for this series. + * + * @private + * @function Highcharts.Series#getPointsCollection + * @return {Array} + */ + getPointsCollection: function () { + return (this.hasGroupedData ? this.points : this.data) || []; + }, + /** + * Get the series' symbol based on either the options or pulled from + * global options. + * + * @private + * @function Highcharts.Series#getSymbol + * @return {void} + */ + getSymbol: function () { + var seriesMarkerOption = this.options.marker; + this.getCyclic('symbol', seriesMarkerOption.symbol, this.chart.options.symbols); + }, + /** + * Finds the index of an existing point that matches the given point + * options. + * + * @private + * @function Highcharts.Series#findPointIndex + * @param {Highcharts.PointOptionsObject} optionsObject + * The options of the point. + * @param {number} fromIndex + * The index to start searching from, used for optimizing + * series with required sorting. + * @returns {number|undefined} + * Returns the index of a matching point, or undefined if no + * match is found. + */ + findPointIndex: function (optionsObject, fromIndex) { + var id = optionsObject.id, x = optionsObject.x, oldData = this.points, matchingPoint, matchedById, pointIndex, matchKey, dataSorting = this.options.dataSorting; + if (id) { + matchingPoint = this.chart.get(id); + } + else if (this.linkedParent || this.enabledDataSorting) { + matchKey = (dataSorting && dataSorting.matchByName) ? + 'name' : 'index'; + matchingPoint = find(oldData, function (oldPoint) { + return !oldPoint.touched && oldPoint[matchKey] === + optionsObject[matchKey]; + }); + // Add unmatched point as a new point + if (!matchingPoint) { + return void 0; + } + } + if (matchingPoint) { + pointIndex = matchingPoint && matchingPoint.index; + if (typeof pointIndex !== 'undefined') { + matchedById = true; + } + } + // Search for the same X in the existing data set + if (typeof pointIndex === 'undefined' && isNumber(x)) { + pointIndex = this.xData.indexOf(x, fromIndex); + } + // Reduce pointIndex if data is cropped + if (pointIndex !== -1 && + typeof pointIndex !== 'undefined' && + this.cropped) { + pointIndex = (pointIndex >= this.cropStart) ? + pointIndex - this.cropStart : pointIndex; + } + if (!matchedById && + oldData[pointIndex] && oldData[pointIndex].touched) { + pointIndex = void 0; + } + return pointIndex; + }, + /** + * @private + * @borrows LegendSymbolMixin.drawLineMarker as Highcharts.Series#drawLegendSymbol + */ + drawLegendSymbol: LegendSymbolMixin.drawLineMarker, + /** + * Internal function called from setData. If the point count is the same + * as is was, or if there are overlapping X values, just run + * Point.update which is cheaper, allows animation, and keeps references + * to points. This also allows adding or removing points if the X-es + * don't match. + * + * @private + * @function Highcharts.Series#updateData + * + * @param {Array} data + * + * @return {boolean} + */ + updateData: function (data, animation) { + var options = this.options, dataSorting = options.dataSorting, oldData = this.points, pointsToAdd = [], hasUpdatedByKey, i, point, lastIndex, requireSorting = this.requireSorting, equalLength = data.length === oldData.length, succeeded = true; + this.xIncrement = null; + // Iterate the new data + data.forEach(function (pointOptions, i) { + var id, x, pointIndex, optionsObject = (defined(pointOptions) && + this.pointClass.prototype.optionsToObject.call({ series: this }, pointOptions)) || {}; + // Get the x of the new data point + x = optionsObject.x; + id = optionsObject.id; + if (id || isNumber(x)) { + pointIndex = this.findPointIndex(optionsObject, lastIndex); + // Matching X not found + // or used already due to ununique x values (#8995), + // add point (but later) + if (pointIndex === -1 || + typeof pointIndex === 'undefined') { + pointsToAdd.push(pointOptions); + // Matching X found, update + } + else if (oldData[pointIndex] && + pointOptions !== options.data[pointIndex]) { + oldData[pointIndex].update(pointOptions, false, null, false); + // Mark it touched, below we will remove all points that + // are not touched. + oldData[pointIndex].touched = true; + // Speed optimize by only searching after last known + // index. Performs ~20% bettor on large data sets. + if (requireSorting) { + lastIndex = pointIndex + 1; + } + // Point exists, no changes, don't remove it + } + else if (oldData[pointIndex]) { + oldData[pointIndex].touched = true; + } + // If the length is equal and some of the nodes had a + // match in the same position, we don't want to remove + // non-matches. + if (!equalLength || + i !== pointIndex || + (dataSorting && dataSorting.enabled) || + this.hasDerivedData) { + hasUpdatedByKey = true; + } + } + else { + // Gather all points that are not matched + pointsToAdd.push(pointOptions); + } + }, this); + // Remove points that don't exist in the updated data set + if (hasUpdatedByKey) { + i = oldData.length; + while (i--) { + point = oldData[i]; + if (point && !point.touched && point.remove) { + point.remove(false, animation); + } + } + // If we did not find keys (ids or x-values), and the length is the + // same, update one-to-one + } + else if (equalLength && (!dataSorting || !dataSorting.enabled)) { + data.forEach(function (point, i) { + // .update doesn't exist on a linked, hidden series (#3709) + // (#10187) + if (oldData[i].update && point !== oldData[i].y) { + oldData[i].update(point, false, null, false); + } + }); + // Don't add new points since those configs are used above + pointsToAdd.length = 0; + // Did not succeed in updating data + } + else { + succeeded = false; + } + oldData.forEach(function (point) { + if (point) { + point.touched = false; + } + }); + if (!succeeded) { + return false; + } + // Add new points + pointsToAdd.forEach(function (point) { + this.addPoint(point, false, null, null, false); + }, this); + if (this.xIncrement === null && + this.xData && + this.xData.length) { + this.xIncrement = arrayMax(this.xData); + this.autoIncrement(); + } + return true; + }, + /** + * Apply a new set of data to the series and optionally redraw it. The + * new data array is passed by reference (except in case of + * `updatePoints`), and may later be mutated when updating the chart + * data. + * + * Note the difference in behaviour when setting the same amount of + * points, or a different amount of points, as handled by the + * `updatePoints` parameter. + * + * @sample highcharts/members/series-setdata/ + * Set new data from a button + * @sample highcharts/members/series-setdata-pie/ + * Set data in a pie + * @sample stock/members/series-setdata/ + * Set new data in Highstock + * @sample maps/members/series-setdata/ + * Set new data in Highmaps + * + * @function Highcharts.Series#setData + * + * @param {Array} data + * Takes an array of data in the same format as described under + * `series.{type}.data` for the given series type, for example a + * line series would take data in the form described under + * [series.line.data](https://api.highcharts.com/highcharts/series.line.data). + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the series is altered. If + * doing more operations on the chart, it is a good idea to set + * redraw to false and call {@link Chart#redraw} after. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * When the updated data is the same length as the existing data, + * points will be updated by default, and animation visualizes + * how the points are changed. Set false to disable animation, or + * a configuration object to set duration or easing. + * + * @param {boolean} [updatePoints=true] + * When this is true, points will be updated instead of replaced + * whenever possible. This occurs a) when the updated data is the + * same length as the existing data, b) when points are matched + * by their id's, or c) when points can be matched by X values. + * This allows updating with animation and performs better. In + * this case, the original array is not passed by reference. Set + * `false` to prevent. + * + * @return {void} + */ + setData: function (data, redraw, animation, updatePoints) { + var series = this, oldData = series.points, oldDataLength = (oldData && oldData.length) || 0, dataLength, options = series.options, chart = series.chart, dataSorting = options.dataSorting, firstPoint = null, xAxis = series.xAxis, i, turboThreshold = options.turboThreshold, pt, xData = this.xData, yData = this.yData, pointArrayMap = series.pointArrayMap, valueCount = pointArrayMap && pointArrayMap.length, keys = options.keys, indexOfX = 0, indexOfY = 1, updatedData; + data = data || []; + dataLength = data.length; + redraw = pick(redraw, true); + if (dataSorting && dataSorting.enabled) { + data = this.sortData(data); + } + // First try to run Point.update which is cheaper, allows animation, + // and keeps references to points. + if (updatePoints !== false && + dataLength && + oldDataLength && + !series.cropped && + !series.hasGroupedData && + series.visible && + // Soft updating has no benefit in boost, and causes JS error + // (#8355) + !series.isSeriesBoosting) { + updatedData = this.updateData(data, animation); + } + if (!updatedData) { + // Reset properties + series.xIncrement = null; + series.colorCounter = 0; // for series with colorByPoint (#1547) + // Update parallel arrays + this.parallelArrays.forEach(function (key) { + series[key + 'Data'].length = 0; + }); + // In turbo mode, only one- or twodimensional arrays of numbers + // are allowed. The first value is tested, and we assume that + // all the rest are defined the same way. Although the 'for' + // loops are similar, they are repeated inside each if-else + // conditional for max performance. + if (turboThreshold && dataLength > turboThreshold) { + firstPoint = series.getFirstValidPoint(data); + if (isNumber(firstPoint)) { // assume all points are numbers + for (i = 0; i < dataLength; i++) { + xData[i] = this.autoIncrement(); + yData[i] = data[i]; + } + // Assume all points are arrays when first point is + } + else if (isArray(firstPoint)) { + if (valueCount) { // [x, low, high] or [x, o, h, l, c] + for (i = 0; i < dataLength; i++) { + pt = data[i]; + xData[i] = pt[0]; + yData[i] = + pt.slice(1, valueCount + 1); + } + } + else { // [x, y] + if (keys) { + indexOfX = keys.indexOf('x'); + indexOfY = keys.indexOf('y'); + indexOfX = indexOfX >= 0 ? indexOfX : 0; + indexOfY = indexOfY >= 0 ? indexOfY : 1; + } + for (i = 0; i < dataLength; i++) { + pt = data[i]; + xData[i] = pt[indexOfX]; + yData[i] = pt[indexOfY]; + } + } + } + else { + // Highcharts expects configs to be numbers or arrays in + // turbo mode + error(12, false, chart); + } + } + else { + for (i = 0; i < dataLength; i++) { + // stray commas in oldIE: + if (typeof data[i] !== 'undefined') { + pt = { series: series }; + series.pointClass.prototype.applyOptions.apply(pt, [data[i]]); + series.updateParallelArrays(pt, i); + } + } + } + // Forgetting to cast strings to numbers is a common caveat when + // handling CSV or JSON + if (yData && isString(yData[0])) { + error(14, true, chart); + } + series.data = []; + series.options.data = series.userOptions.data = data; + // destroy old points + i = oldDataLength; + while (i--) { + if (oldData[i] && oldData[i].destroy) { + oldData[i].destroy(); + } + } + // reset minRange (#878) + if (xAxis) { + xAxis.minRange = xAxis.userMinRange; + } + // redraw + series.isDirty = chart.isDirtyBox = true; + series.isDirtyData = !!oldData; + animation = false; + } + // Typically for pie series, points need to be processed and + // generated prior to rendering the legend + if (options.legendType === 'point') { + this.processData(); + this.generatePoints(); + } + if (redraw) { + chart.redraw(animation); + } + }, + /** + * Internal function to sort series data + * + * @private + * @function Highcharts.Series#sortData + * @param {Array} data + * Force data grouping. + * @return {Array} + */ + sortData: function (data) { + var series = this, options = series.options, dataSorting = options.dataSorting, sortKey = dataSorting.sortKey || 'y', sortedData, getPointOptionsObject = function (series, pointOptions) { + return (defined(pointOptions) && + series.pointClass.prototype.optionsToObject.call({ + series: series + }, pointOptions)) || {}; + }; + data.forEach(function (pointOptions, i) { + data[i] = getPointOptionsObject(series, pointOptions); + data[i].index = i; + }, this); + // Sorting + sortedData = data.concat().sort(function (a, b) { + var aValue = getNestedProperty(sortKey, a); + var bValue = getNestedProperty(sortKey, b); + return bValue < aValue ? -1 : bValue > aValue ? 1 : 0; + }); + // Set x value depending on the position in the array + sortedData.forEach(function (point, i) { + point.x = i; + }, this); + // Set the same x for linked series points if they don't have their + // own sorting + if (series.linkedSeries) { + series.linkedSeries.forEach(function (linkedSeries) { + var options = linkedSeries.options, seriesData = options.data; + if ((!options.dataSorting || + !options.dataSorting.enabled) && + seriesData) { + seriesData.forEach(function (pointOptions, i) { + seriesData[i] = getPointOptionsObject(linkedSeries, pointOptions); + if (data[i]) { + seriesData[i].x = data[i].x; + seriesData[i].index = i; + } + }); + linkedSeries.setData(seriesData, false); + } + }); + } + return data; + }, + /** + * Internal function to process the data by cropping away unused data + * points if the series is longer than the crop threshold. This saves + * computing time for large series. + * + * @private + * @function Highcharts.Series#getProcessedData + * @param {boolean} [forceExtremesFromAll] + * Force getting extremes of a total series data range. + * @return {Highcharts.SeriesProcessedDataObject} + */ + getProcessedData: function (forceExtremesFromAll) { + var series = this, + // copied during slice operation: + processedXData = series.xData, processedYData = series.yData, dataLength = processedXData.length, croppedData, cropStart = 0, cropped, distance, closestPointRange, xAxis = series.xAxis, i, // loop variable + options = series.options, cropThreshold = options.cropThreshold, getExtremesFromAll = forceExtremesFromAll || + series.getExtremesFromAll || + options.getExtremesFromAll, // #4599 + isCartesian = series.isCartesian, xExtremes, val2lin = xAxis && xAxis.val2lin, isLog = !!(xAxis && xAxis.logarithmic), throwOnUnsorted = series.requireSorting, min, max; + if (xAxis) { + // corrected for log axis (#3053) + xExtremes = xAxis.getExtremes(); + min = xExtremes.min; + max = xExtremes.max; + } + // optionally filter out points outside the plot area + if (isCartesian && + series.sorted && + !getExtremesFromAll && + (!cropThreshold || + dataLength > cropThreshold || + series.forceCrop)) { + // it's outside current extremes + if (processedXData[dataLength - 1] < min || + processedXData[0] > max) { + processedXData = []; + processedYData = []; + // only crop if it's actually spilling out + } + else if (series.yData && (processedXData[0] < min || + processedXData[dataLength - 1] > max)) { + croppedData = this.cropData(series.xData, series.yData, min, max); + processedXData = croppedData.xData; + processedYData = croppedData.yData; + cropStart = croppedData.start; + cropped = true; + } + } + // Find the closest distance between processed points + i = processedXData.length || 1; + while (--i) { + distance = (isLog ? + (val2lin(processedXData[i]) - + val2lin(processedXData[i - 1])) : + (processedXData[i] - + processedXData[i - 1])); + if (distance > 0 && + (typeof closestPointRange === 'undefined' || + distance < closestPointRange)) { + closestPointRange = distance; + // Unsorted data is not supported by the line tooltip, as well + // as data grouping and navigation in Stock charts (#725) and + // width calculation of columns (#1900) + } + else if (distance < 0 && throwOnUnsorted) { + error(15, false, series.chart); + throwOnUnsorted = false; // Only once + } + } + return { + xData: processedXData, + yData: processedYData, + cropped: cropped, + cropStart: cropStart, + closestPointRange: closestPointRange + }; + }, + /** + * Internal function to apply processed data. + * In Highstock, this function is extended to provide data grouping. + * + * @private + * @function Highcharts.Series#processData + * @param {boolean} [force] + * Force data grouping. + * @return {boolean|undefined} + */ + processData: function (force) { + var series = this, xAxis = series.xAxis, processedData; + // If the series data or axes haven't changed, don't go through + // this. Return false to pass the message on to override methods + // like in data grouping. + if (series.isCartesian && + !series.isDirty && + !xAxis.isDirty && + !series.yAxis.isDirty && + !force) { + return false; + } + processedData = series.getProcessedData(); + // Record the properties + series.cropped = processedData.cropped; // undefined or true + series.cropStart = processedData.cropStart; + series.processedXData = processedData.xData; + series.processedYData = processedData.yData; + series.closestPointRange = + series.basePointRange = processedData.closestPointRange; + }, + /** + * Iterate over xData and crop values between min and max. Returns + * object containing crop start/end cropped xData with corresponding + * part of yData, dataMin and dataMax within the cropped range. + * + * @private + * @function Highcharts.Series#cropData + * @param {Array} xData + * @param {Array} yData + * @param {number} min + * @param {number} max + * @param {number} [cropShoulder] + * @return {Highcharts.SeriesCropDataObject} + */ + cropData: function (xData, yData, min, max, cropShoulder) { + var dataLength = xData.length, cropStart = 0, cropEnd = dataLength, i, j; + // line-type series need one point outside + cropShoulder = pick(cropShoulder, this.cropShoulder); + // iterate up to find slice start + for (i = 0; i < dataLength; i++) { + if (xData[i] >= min) { + cropStart = Math.max(0, i - cropShoulder); + break; + } + } + // proceed to find slice end + for (j = i; j < dataLength; j++) { + if (xData[j] > max) { + cropEnd = j + cropShoulder; + break; + } + } + return { + xData: xData.slice(cropStart, cropEnd), + yData: yData.slice(cropStart, cropEnd), + start: cropStart, + end: cropEnd + }; + }, + /** + * Generate the data point after the data has been processed by cropping + * away unused points and optionally grouped in Highcharts Stock. + * + * @private + * @function Highcharts.Series#generatePoints + * @return {void} + */ + generatePoints: function () { + var series = this, options = series.options, dataOptions = options.data, data = series.data, dataLength, processedXData = series.processedXData, processedYData = series.processedYData, PointClass = series.pointClass, processedDataLength = processedXData.length, cropStart = series.cropStart || 0, cursor, hasGroupedData = series.hasGroupedData, keys = options.keys, point, points = [], i; + if (!data && !hasGroupedData) { + var arr = []; + arr.length = dataOptions.length; + data = series.data = arr; + } + if (keys && hasGroupedData) { + // grouped data has already applied keys (#6590) + series.options.keys = false; + } + for (i = 0; i < processedDataLength; i++) { + cursor = cropStart + i; + if (!hasGroupedData) { + point = data[cursor]; + // #970: + if (!point && + typeof dataOptions[cursor] !== 'undefined') { + data[cursor] = point = (new PointClass()).init(series, dataOptions[cursor], processedXData[i]); + } + } + else { + // splat the y data in case of ohlc data array + point = (new PointClass()).init(series, [processedXData[i]].concat(splat(processedYData[i]))); + /** + * Highstock only. If a point object is created by data + * grouping, it doesn't reflect actual points in the raw + * data. In this case, the `dataGroup` property holds + * information that points back to the raw data. + * + * - `dataGroup.start` is the index of the first raw data + * point in the group. + * + * - `dataGroup.length` is the amount of points in the + * group. + * + * @product highstock + * + * @name Highcharts.Point#dataGroup + * @type {Highcharts.DataGroupingInfoObject|undefined} + */ + point.dataGroup = series.groupMap[i]; + if (point.dataGroup.options) { + point.options = point.dataGroup.options; + extend(point, point.dataGroup.options); + // Collision of props and options (#9770) + delete point.dataLabels; + } + } + if (point) { // #6279 + /** + * Contains the point's index in the `Series.points` array. + * + * @name Highcharts.Point#index + * @type {number} + * @readonly + */ + point.index = cursor; // For faster access in Point.update + points[i] = point; + } + } + // restore keys options (#6590) + series.options.keys = keys; + // Hide cropped-away points - this only runs when the number of + // points is above cropThreshold, or when swithching view from + // non-grouped data to grouped data (#637) + if (data && + (processedDataLength !== (dataLength = data.length) || + hasGroupedData)) { + for (i = 0; i < dataLength; i++) { + // when has grouped data, clear all points + if (i === cropStart && !hasGroupedData) { + i += processedDataLength; + } + if (data[i]) { + data[i].destroyElements(); + data[i].plotX = void 0; // #1003 + } + } + } + /** + * Read only. An array containing those values converted to points. + * In case the series data length exceeds the `cropThreshold`, or if + * the data is grouped, `series.data` doesn't contain all the + * points. Also, in case a series is hidden, the `data` array may be + * empty. To access raw values, `series.options.data` will always be + * up to date. `Series.data` only contains the points that have been + * created on demand. To modify the data, use + * {@link Highcharts.Series#setData} or + * {@link Highcharts.Point#update}. + * + * @see Series.points + * + * @name Highcharts.Series#data + * @type {Array} + */ + series.data = data; + /** + * An array containing all currently visible point objects. In case + * of cropping, the cropped-away points are not part of this array. + * The `series.points` array starts at `series.cropStart` compared + * to `series.data` and `series.options.data`. If however the series + * data is grouped, these can't be correlated one to one. To modify + * the data, use {@link Highcharts.Series#setData} or + * {@link Highcharts.Point#update}. + * + * @name Highcharts.Series#points + * @type {Array} + */ + series.points = points; + fireEvent(this, 'afterGeneratePoints'); + }, + /** + * Get current X extremes for the visible data. + * + * @private + * @function Highcharts.Series#getXExtremes + * + * @param {Array} xData + * The data to inspect. Defaults to the current data within the + * visible range. + * @return {Highcharts.RangeObject} + */ + getXExtremes: function (xData) { + return { + min: arrayMin(xData), + max: arrayMax(xData) + }; + }, + /** + * Calculate Y extremes for the visible data. The result is returned + * as an object with `dataMin` and `dataMax` properties. + * + * @private + * @function Highcharts.Series#getExtremes + * @param {Array} [yData] + * The data to inspect. Defaults to the current data within the + * visible range. + * @param {boolean} [forceExtremesFromAll] + * Force getting extremes of a total series data range. + * @return {Highcharts.DataExtremesObject} + */ + getExtremes: function (yData, forceExtremesFromAll) { + var xAxis = this.xAxis, yAxis = this.yAxis, xData = this.processedXData || this.xData, yDataLength, activeYData = [], activeCounter = 0, + // #2117, need to compensate for log X axis + xExtremes, xMin = 0, xMax = 0, validValue, withinRange, + // Handle X outside the viewed area. This does not work with + // non-sorted data like scatter (#7639). + shoulder = this.requireSorting ? this.cropShoulder : 0, positiveValuesOnly = yAxis ? yAxis.positiveValuesOnly : false, x, y, i, j; + yData = yData || this.stackedYData || this.processedYData || []; + yDataLength = yData.length; + if (xAxis) { + xExtremes = xAxis.getExtremes(); + xMin = xExtremes.min; + xMax = xExtremes.max; + } + for (i = 0; i < yDataLength; i++) { + x = xData[i]; + y = yData[i]; + // For points within the visible range, including the first + // point outside the visible range (#7061), consider y extremes. + validValue = ((isNumber(y) || isArray(y)) && + ((y.length || y > 0) || !positiveValuesOnly)); + withinRange = (forceExtremesFromAll || + this.getExtremesFromAll || + this.options.getExtremesFromAll || + this.cropped || + !xAxis || // for colorAxis support + ((xData[i + shoulder] || x) >= xMin && + (xData[i - shoulder] || x) <= xMax)); + if (validValue && withinRange) { + j = y.length; + if (j) { // array, like ohlc or range data + while (j--) { + if (isNumber(y[j])) { // #7380, #11513 + activeYData[activeCounter++] = y[j]; + } + } + } + else { + activeYData[activeCounter++] = y; + } + } + } + var dataExtremes = { + dataMin: arrayMin(activeYData), + dataMax: arrayMax(activeYData) + }; + fireEvent(this, 'afterGetExtremes', { dataExtremes: dataExtremes }); + return dataExtremes; + }, + /** + * Set the current data extremes as `dataMin` and `dataMax` on the + * Series item. Use this only when the series properties should be + * updated. + * + * @private + * @function Highcharts.Series#applyExtremes + * @return {void} + */ + applyExtremes: function () { + var dataExtremes = this.getExtremes(); + /** + * Contains the minimum value of the series' data point. + * @name Highcharts.Series#dataMin + * @type {number} + * @readonly + */ + this.dataMin = dataExtremes.dataMin; + /* * + * Contains the maximum value of the series' data point. + * @name Highcharts.Series#dataMax + * @type {number} + * @readonly + */ + this.dataMax = dataExtremes.dataMax; + return dataExtremes; + }, + /** + * Find and return the first non null point in the data + * + * @private + * @function Highcharts.Series.getFirstValidPoint + * @param {Array} data + * Array of options for points + * + * @return {Highcharts.PointOptionsType} + */ + getFirstValidPoint: function (data) { + var firstPoint = null, dataLength = data.length, i = 0; + while (firstPoint === null && i < dataLength) { + firstPoint = data[i]; + i++; + } + return firstPoint; + }, + /** + * Translate data points from raw data values to chart specific + * positioning data needed later in the `drawPoints` and `drawGraph` + * functions. This function can be overridden in plugins and custom + * series type implementations. + * + * @function Highcharts.Series#translate + * @return {void} + * @fires Highcharts.Series#events:translate + */ + translate: function () { + if (!this.processedXData) { // hidden series + this.processData(); + } + this.generatePoints(); + var series = this, options = series.options, stacking = options.stacking, xAxis = series.xAxis, categories = xAxis.categories, enabledDataSorting = series.enabledDataSorting, yAxis = series.yAxis, points = series.points, dataLength = points.length, hasModifyValue = !!series.modifyValue, i, pointPlacement = series.pointPlacementToXValue(), // #7860 + dynamicallyPlaced = Boolean(pointPlacement), threshold = options.threshold, stackThreshold = options.startFromThreshold ? threshold : 0, plotX, lastPlotX, stackIndicator, zoneAxis = this.zoneAxis || 'y', closestPointRangePx = Number.MAX_VALUE; + /** + * Plotted coordinates need to be within a limited range. Drawing + * too far outside the viewport causes various rendering issues + * (#3201, #3923, #7555). + * @private + */ + function limitedRange(val) { + return clamp(val, -1e5, 1e5); + } + // Translate each point + for (i = 0; i < dataLength; i++) { + var point = points[i], xValue = point.x, yValue = point.y, yBottom = point.low, stack = stacking && yAxis.stacking && yAxis.stacking.stacks[(series.negStacks && + yValue < + (stackThreshold ? 0 : threshold) ? + '-' : + '') + series.stackKey], pointStack, stackValues; + // Discard disallowed y values for log axes (#3434) + if (yAxis.positiveValuesOnly && + yValue !== null && + yValue <= 0) { + point.isNull = true; + } + // Get the plotX translation + point.plotX = plotX = correctFloat(// #5236 + limitedRange(xAxis.translate(// #3923 + xValue, 0, 0, 0, 1, pointPlacement, this.type === 'flags')) // #3923 + ); + // Calculate the bottom y value for stacked series + if (stacking && + series.visible && + stack && + stack[xValue]) { + stackIndicator = series.getStackIndicator(stackIndicator, xValue, series.index); + if (!point.isNull) { + pointStack = stack[xValue]; + stackValues = + pointStack.points[stackIndicator.key]; + } + } + if (isArray(stackValues)) { + yBottom = stackValues[0]; + yValue = stackValues[1]; + if (yBottom === stackThreshold && + stackIndicator.key === + stack[xValue].base) { + yBottom = pick((isNumber(threshold) && threshold), yAxis.min); + } + // #1200, #1232 + if (yAxis.positiveValuesOnly && yBottom <= 0) { + yBottom = null; + } + point.total = point.stackTotal = pointStack.total; + point.percentage = + pointStack.total && + (point.y / pointStack.total * 100); + point.stackY = yValue; + // Place the stack label + // in case of variwide series (where widths of points are + // different in most cases), stack labels are positioned + // wrongly, so the call of the setOffset is omited here and + // labels are correctly positioned later, at the end of the + // variwide's translate function (#10962) + if (!series.irregularWidths) { + pointStack.setOffset(series.pointXOffset || 0, series.barW || 0); + } + } + // Set translated yBottom or remove it + point.yBottom = defined(yBottom) ? + limitedRange(yAxis.translate(yBottom, 0, 1, 0, 1)) : + null; + // general hook, used for Highstock compare mode + if (hasModifyValue) { + yValue = series.modifyValue(yValue, point); + } + // Set the the plotY value, reset it for redraws + // #3201 + point.plotY = ((typeof yValue === 'number' && yValue !== Infinity) ? + limitedRange(yAxis.translate(yValue, 0, 1, 0, 1)) : + void 0); + point.isInside = this.isPointInside(point); + // Set client related positions for mouse tracking + point.clientX = dynamicallyPlaced ? + correctFloat(xAxis.translate(xValue, 0, 0, 0, 1, pointPlacement)) : + plotX; // #1514, #5383, #5518 + // Negative points. For bubble charts, this means negative z + // values (#9728) + point.negative = point[zoneAxis] < (options[zoneAxis + 'Threshold'] || + threshold || + 0); + // some API data + point.category = (categories && + typeof categories[point.x] !== 'undefined' ? + categories[point.x] : + point.x); + // Determine auto enabling of markers (#3635, #5099) + if (!point.isNull && point.visible !== false) { + if (typeof lastPlotX !== 'undefined') { + closestPointRangePx = Math.min(closestPointRangePx, Math.abs(plotX - lastPlotX)); + } + lastPlotX = plotX; + } + // Find point zone + point.zone = (this.zones.length && point.getZone()); + // Animate new points with data sorting + if (!point.graphic && series.group && enabledDataSorting) { + point.isNew = true; + } + } + series.closestPointRangePx = closestPointRangePx; + fireEvent(this, 'afterTranslate'); + }, + /** + * Return the series points with null points filtered out. + * + * @function Highcharts.Series#getValidPoints + * + * @param {Array} [points] + * The points to inspect, defaults to {@link Series.points}. + * + * @param {boolean} [insideOnly=false] + * Whether to inspect only the points that are inside the visible + * view. + * + * @param {boolean} [allowNull=false] + * Whether to allow null points to pass as valid points. + * + * @return {Array} + * The valid points. + */ + getValidPoints: function (points, insideOnly, allowNull) { + var chart = this.chart; + // #3916, #5029, #5085 + return (points || this.points || []).filter(function isValidPoint(point) { + if (insideOnly && !chart.isInsidePlot(point.plotX, point.plotY, chart.inverted)) { + return false; + } + return point.visible !== false && + (allowNull || !point.isNull); + }); + }, + /** + * Get the clipping for the series. Could be called for a series to + * initiate animating the clip or to set the final clip (only width + * and x). + * + * @private + * @function Highcharts.Series#getClip + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * Initialize the animation. + * @param {boolean} [finalBox] + * Final size for the clip - end state for the animation. + * @return {Highcharts.Dictionary} + */ + getClipBox: function (animation, finalBox) { + var series = this, options = series.options, chart = series.chart, inverted = chart.inverted, xAxis = series.xAxis, yAxis = xAxis && series.yAxis, clipBox; + if (animation && options.clip === false && yAxis) { + // support for not clipped series animation (#10450) + clipBox = inverted ? { + y: -chart.chartWidth + yAxis.len + yAxis.pos, + height: chart.chartWidth, + width: chart.chartHeight, + x: -chart.chartHeight + xAxis.len + xAxis.pos + } : { + y: -yAxis.pos, + height: chart.chartHeight, + width: chart.chartWidth, + x: -xAxis.pos + }; + // x and width will be changed later when setting for animation + // initial state in Series.setClip + } + else { + clipBox = series.clipBox || chart.clipBox; + if (finalBox) { + clipBox.width = chart.plotSizeX; + clipBox.x = 0; + } + } + return !finalBox ? clipBox : { + width: clipBox.width, + x: clipBox.x + }; + }, + /** + * Set the clipping for the series. For animated series it is called + * twice, first to initiate animating the clip then the second time + * without the animation to set the final clip. + * + * @private + * @function Highcharts.Series#setClip + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * @return {void} + */ + setClip: function (animation) { + var chart = this.chart, options = this.options, renderer = chart.renderer, inverted = chart.inverted, seriesClipBox = this.clipBox, clipBox = this.getClipBox(animation), sharedClipKey = this.sharedClipKey || + [ + '_sharedClip', + animation && animation.duration, + animation && animation.easing, + clipBox.height, + options.xAxis, + options.yAxis + ].join(','), // #4526 + clipRect = chart[sharedClipKey], markerClipRect = chart[sharedClipKey + 'm']; + if (animation) { + clipBox.width = 0; + if (inverted) { + clipBox.x = chart.plotHeight + + (options.clip !== false ? 0 : chart.plotTop); + } + } + // If a clipping rectangle with the same properties is currently + // present in the chart, use that. + if (!clipRect) { + // When animation is set, prepare the initial positions + if (animation) { + chart[sharedClipKey + 'm'] = markerClipRect = + renderer.clipRect( + // include the width of the first marker + inverted ? chart.plotSizeX + 99 : -99, inverted ? -chart.plotLeft : -chart.plotTop, 99, inverted ? chart.chartWidth : chart.chartHeight); + } + chart[sharedClipKey] = clipRect = renderer.clipRect(clipBox); + // Create hashmap for series indexes + clipRect.count = { length: 0 }; + // When the series is rendered again before starting animating, in + // compliance to a responsive rule + } + else if (!chart.hasLoaded) { + clipRect.attr(clipBox); + } + if (animation) { + if (!clipRect.count[this.index]) { + clipRect.count[this.index] = true; + clipRect.count.length += 1; + } + } + if (options.clip !== false || animation) { + this.group.clip(animation || seriesClipBox ? clipRect : chart.clipRect); + this.markerGroup.clip(markerClipRect); + this.sharedClipKey = sharedClipKey; + } + // Remove the shared clipping rectangle when all series are shown + if (!animation) { + if (clipRect.count[this.index]) { + delete clipRect.count[this.index]; + clipRect.count.length -= 1; + } + if (clipRect.count.length === 0 && + sharedClipKey && + chart[sharedClipKey]) { + if (!seriesClipBox) { + chart[sharedClipKey] = + chart[sharedClipKey].destroy(); + } + if (chart[sharedClipKey + 'm']) { + chart[sharedClipKey + 'm'] = + chart[sharedClipKey + 'm'].destroy(); + } + } + } + }, + /** + * Animate in the series. Called internally twice. First with the `init` + * parameter set to true, which sets up the initial state of the + * animation. Then when ready, it is called with the `init` parameter + * undefined, in order to perform the actual animation. After the + * second run, the function is removed. + * + * @function Highcharts.Series#animate + * + * @param {boolean} [init] + * Initialize the animation. + * + * @return {void} + */ + animate: function (init) { + var series = this, chart = series.chart, animation = animObject(series.options.animation), clipRect, sharedClipKey, finalBox; + // Initialize the animation. Set up the clipping rectangle. + if (!chart.hasRendered) { + if (init) { + series.setClip(animation); + // Run the animation + } + else { + sharedClipKey = this.sharedClipKey; + clipRect = chart[sharedClipKey]; + finalBox = series.getClipBox(animation, true); + if (clipRect) { + clipRect.animate(finalBox, animation); + } + if (chart[sharedClipKey + 'm']) { + chart[sharedClipKey + 'm'].animate({ + width: finalBox.width + 99, + x: finalBox.x - (chart.inverted ? 0 : 99) + }, animation); + } + } + } + }, + /** + * This runs after animation to land on the final plot clipping. + * + * @private + * @function Highcharts.Series#afterAnimate + * @return {void} + * @fires Highcharts.Series#event:afterAnimate + */ + afterAnimate: function () { + this.setClip(); + fireEvent(this, 'afterAnimate'); + this.finishedAnimating = true; + }, + /** + * Draw the markers for line-like series types, and columns or other + * graphical representation for {@link Point} objects for other series + * types. The resulting element is typically stored as + * {@link Point.graphic}, and is created on the first call and updated + * and moved on subsequent calls. + * + * @function Highcharts.Series#drawPoints + */ + drawPoints: function () { + var series = this, points = series.points, chart = series.chart, i, point, graphic, verb, options = series.options, seriesMarkerOptions = options.marker, pointMarkerOptions, hasPointMarker, markerGroup = (series[series.specialGroup] || + series.markerGroup), xAxis = series.xAxis, markerAttribs, globallyEnabled = pick(seriesMarkerOptions.enabled, !xAxis || xAxis.isRadial ? true : null, + // Use larger or equal as radius is null in bubbles (#6321) + series.closestPointRangePx >= (seriesMarkerOptions.enabledThreshold * + seriesMarkerOptions.radius)); + if (seriesMarkerOptions.enabled !== false || + series._hasPointMarkers) { + for (i = 0; i < points.length; i++) { + point = points[i]; + graphic = point.graphic; + verb = graphic ? 'animate' : 'attr'; + pointMarkerOptions = point.marker || {}; + hasPointMarker = !!point.marker; + var shouldDrawMarker = ((globallyEnabled && + typeof pointMarkerOptions.enabled === 'undefined') || pointMarkerOptions.enabled) && !point.isNull && point.visible !== false; + // only draw the point if y is defined + if (shouldDrawMarker) { + // Shortcuts + var symbol = pick(pointMarkerOptions.symbol, series.symbol); + markerAttribs = series.markerAttribs(point, (point.selected && 'select')); + // Set starting position for point sliding animation. + if (series.enabledDataSorting) { + point.startXPos = xAxis.reversed ? + -markerAttribs.width : + xAxis.width; + } + var isInside = point.isInside !== false; + if (graphic) { // update + // Since the marker group isn't clipped, each + // individual marker must be toggled + graphic[isInside ? 'show' : 'hide'](isInside) + .animate(markerAttribs); + } + else if (isInside && + (markerAttribs.width > 0 || point.hasImage)) { + /** + * The graphic representation of the point. + * Typically this is a simple shape, like a `rect` + * for column charts or `path` for line markers, but + * for some complex series types like boxplot or 3D + * charts, the graphic may be a `g` element + * containing other shapes. The graphic is generated + * the first time {@link Series#drawPoints} runs, + * and updated and moved on subsequent runs. + * + * @name Point#graphic + * @type {SVGElement} + */ + point.graphic = graphic = chart.renderer + .symbol(symbol, markerAttribs.x, markerAttribs.y, markerAttribs.width, markerAttribs.height, hasPointMarker ? + pointMarkerOptions : + seriesMarkerOptions) + .add(markerGroup); + // Sliding animation for new points + if (series.enabledDataSorting && + chart.hasRendered) { + graphic.attr({ + x: point.startXPos + }); + verb = 'animate'; + } + } + if (graphic && verb === 'animate') { // update + // Since the marker group isn't clipped, each + // individual marker must be toggled + graphic[isInside ? 'show' : 'hide'](isInside) + .animate(markerAttribs); + } + // Presentational attributes + if (graphic && !chart.styledMode) { + graphic[verb](series.pointAttribs(point, (point.selected && 'select'))); + } + if (graphic) { + graphic.addClass(point.getClassName(), true); + } + } + else if (graphic) { + point.graphic = graphic.destroy(); // #1269 + } + } + } + }, + /** + * Get non-presentational attributes for a point. Used internally for + * both styled mode and classic. Can be overridden for different series + * types. + * + * @see Series#pointAttribs + * + * @function Highcharts.Series#markerAttribs + * + * @param {Highcharts.Point} point + * The Point to inspect. + * + * @param {string} [state] + * The state, can be either `hover`, `select` or undefined. + * + * @return {Highcharts.SVGAttributes} + * A hash containing those attributes that are not settable from + * CSS. + */ + markerAttribs: function (point, state) { + var seriesOptions = this.options, seriesMarkerOptions = seriesOptions.marker, seriesStateOptions, pointMarkerOptions = point.marker || {}, symbol = (pointMarkerOptions.symbol || + seriesMarkerOptions.symbol), pointStateOptions, radius = pick(pointMarkerOptions.radius, seriesMarkerOptions.radius), attribs; + // Handle hover and select states + if (state) { + seriesStateOptions = seriesMarkerOptions.states[state]; + pointStateOptions = pointMarkerOptions.states && + pointMarkerOptions.states[state]; + radius = pick(pointStateOptions && pointStateOptions.radius, seriesStateOptions && seriesStateOptions.radius, radius + (seriesStateOptions && seriesStateOptions.radiusPlus || + 0)); + } + point.hasImage = symbol && symbol.indexOf('url') === 0; + if (point.hasImage) { + radius = 0; // and subsequently width and height is not set + } + attribs = { + // Math.floor for #1843: + x: seriesOptions.crisp ? + Math.floor(point.plotX) - radius : + point.plotX - radius, + y: point.plotY - radius + }; + if (radius) { + attribs.width = attribs.height = 2 * radius; + } + return attribs; + }, + /** + * Internal function to get presentational attributes for each point. + * Unlike {@link Series#markerAttribs}, this function should return + * those attributes that can also be set in CSS. In styled mode, + * `pointAttribs` won't be called. + * + * @private + * @function Highcharts.Series#pointAttribs + * + * @param {Highcharts.Point} [point] + * The point instance to inspect. + * + * @param {string} [state] + * The point state, can be either `hover`, `select` or 'normal'. + * If undefined, normal state is assumed. + * + * @return {Highcharts.SVGAttributes} + * The presentational attributes to be set on the point. + */ + pointAttribs: function (point, state) { + var seriesMarkerOptions = this.options.marker, seriesStateOptions, pointOptions = point && point.options, pointMarkerOptions = ((pointOptions && pointOptions.marker) || {}), pointStateOptions, color = this.color, pointColorOption = pointOptions && pointOptions.color, pointColor = point && point.color, strokeWidth = pick(pointMarkerOptions.lineWidth, seriesMarkerOptions.lineWidth), zoneColor = point && point.zone && point.zone.color, fill, stroke, opacity = 1; + color = (pointColorOption || + zoneColor || + pointColor || + color); + fill = (pointMarkerOptions.fillColor || + seriesMarkerOptions.fillColor || + color); + stroke = (pointMarkerOptions.lineColor || + seriesMarkerOptions.lineColor || + color); + // Handle hover and select states + state = state || 'normal'; + if (state) { + seriesStateOptions = seriesMarkerOptions.states[state]; + pointStateOptions = (pointMarkerOptions.states && + pointMarkerOptions.states[state]) || {}; + strokeWidth = pick(pointStateOptions.lineWidth, seriesStateOptions.lineWidth, strokeWidth + pick(pointStateOptions.lineWidthPlus, seriesStateOptions.lineWidthPlus, 0)); + fill = (pointStateOptions.fillColor || + seriesStateOptions.fillColor || + fill); + stroke = (pointStateOptions.lineColor || + seriesStateOptions.lineColor || + stroke); + opacity = pick(pointStateOptions.opacity, seriesStateOptions.opacity, opacity); + } + return { + 'stroke': stroke, + 'stroke-width': strokeWidth, + 'fill': fill, + 'opacity': opacity + }; + }, + /** + * Clear DOM objects and free up memory. + * + * @private + * @function Highcharts.Series#destroy + * @param {boolean} [keepEventsForUpdate] + * @return {void} + * @fires Highcharts.Series#event:destroy + */ + destroy: function (keepEventsForUpdate) { + var series = this, chart = series.chart, issue134 = /AppleWebKit\/533/.test(win.navigator.userAgent), destroy, i, data = series.data || [], point, axis; + // add event hook + fireEvent(series, 'destroy'); + // remove events + this.removeEvents(keepEventsForUpdate); + // erase from axes + (series.axisTypes || []).forEach(function (AXIS) { + axis = series[AXIS]; + if (axis && axis.series) { + erase(axis.series, series); + axis.isDirty = axis.forceRedraw = true; + } + }); + // remove legend items + if (series.legendItem) { + series.chart.legend.destroyItem(series); + } + // destroy all points with their elements + i = data.length; + while (i--) { + point = data[i]; + if (point && point.destroy) { + point.destroy(); + } + } + series.points = null; + // Clear the animation timeout if we are destroying the series + // during initial animation + U.clearTimeout(series.animationTimeout); + // Destroy all SVGElements associated to the series + objectEach(series, function (val, prop) { + // Survive provides a hook for not destroying + if (val instanceof SVGElement && !val.survive) { + // issue 134 workaround + destroy = issue134 && prop === 'group' ? + 'hide' : + 'destroy'; + val[destroy](); + } + }); + // remove from hoverSeries + if (chart.hoverSeries === series) { + chart.hoverSeries = null; + } + erase(chart.series, series); + chart.orderSeries(); + // clear all members + objectEach(series, function (val, prop) { + if (!keepEventsForUpdate || prop !== 'hcEvents') { + delete series[prop]; + } + }); + }, + /** + * Get the graph path. + * + * @private + * @function Highcharts.Series#getGraphPath + * @param {Array} points + * @param {boolean} [nullsAsZeroes] + * @param {boolean} [connectCliffs] + * @return {Highcharts.SVGPathArray} + */ + getGraphPath: function (points, nullsAsZeroes, connectCliffs) { + var series = this, options = series.options, step = options.step, reversed, graphPath = [], xMap = [], gap; + points = points || series.points; + // Bottom of a stack is reversed + reversed = points.reversed; + if (reversed) { + points.reverse(); + } + // Reverse the steps (#5004) + step = { + right: 1, + center: 2 + }[step] || (step && 3); + if (step && reversed) { + step = 4 - step; + } + // Remove invalid points, especially in spline (#5015) + points = this.getValidPoints(points, false, !(options.connectNulls && !nullsAsZeroes && !connectCliffs)); + // Build the line + points.forEach(function (point, i) { + var plotX = point.plotX, plotY = point.plotY, lastPoint = points[i - 1], + // the path to this point from the previous + pathToPoint; + if ((point.leftCliff || (lastPoint && lastPoint.rightCliff)) && + !connectCliffs) { + gap = true; // ... and continue + } + // Line series, nullsAsZeroes is not handled + if (point.isNull && !defined(nullsAsZeroes) && i > 0) { + gap = !options.connectNulls; + // Area series, nullsAsZeroes is set + } + else if (point.isNull && !nullsAsZeroes) { + gap = true; + } + else { + if (i === 0 || gap) { + pathToPoint = [[ + 'M', + point.plotX, + point.plotY + ]]; + // Generate the spline as defined in the SplineSeries object + } + else if (series.getPointSpline) { + pathToPoint = [series.getPointSpline(points, point, i)]; + } + else if (step) { + if (step === 1) { // right + pathToPoint = [[ + 'L', + lastPoint.plotX, + plotY + ]]; + } + else if (step === 2) { // center + pathToPoint = [[ + 'L', + (lastPoint.plotX + plotX) / 2, + lastPoint.plotY + ], [ + 'L', + (lastPoint.plotX + plotX) / 2, + plotY + ]]; + } + else { + pathToPoint = [[ + 'L', + plotX, + lastPoint.plotY + ]]; + } + pathToPoint.push([ + 'L', + plotX, + plotY + ]); + } + else { + // normal line to next point + pathToPoint = [[ + 'L', + plotX, + plotY + ]]; + } + // Prepare for animation. When step is enabled, there are + // two path nodes for each x value. + xMap.push(point.x); + if (step) { + xMap.push(point.x); + if (step === 2) { // step = center (#8073) + xMap.push(point.x); + } + } + graphPath.push.apply(graphPath, pathToPoint); + gap = false; + } + }); + graphPath.xMap = xMap; + series.graphPath = graphPath; + return graphPath; + }, + /** + * Draw the graph. Called internally when rendering line-like series + * types. The first time it generates the `series.graph` item and + * optionally other series-wide items like `series.area` for area + * charts. On subsequent calls these items are updated with new + * positions and attributes. + * + * @function Highcharts.Series#drawGraph + * + * @return {void} + */ + drawGraph: function () { + var series = this, options = this.options, graphPath = (this.gappedPath || this.getGraphPath).call(this), styledMode = this.chart.styledMode, props = [[ + 'graph', + 'highcharts-graph' + ]]; + // Presentational properties + if (!styledMode) { + props[0].push((options.lineColor || + this.color || + '#cccccc' // when colorByPoint = true + ), options.dashStyle); + } + props = series.getZonesGraphs(props); + // Draw the graph + props.forEach(function (prop, i) { + var graphKey = prop[0], graph = series[graphKey], verb = graph ? 'animate' : 'attr', attribs; + if (graph) { + graph.endX = series.preventGraphAnimation ? + null : + graphPath.xMap; + graph.animate({ d: graphPath }); + } + else if (graphPath.length) { // #1487 + /** + * SVG element of area-based charts. Can be used for styling + * purposes. If zones are configured, this element will be + * hidden and replaced by multiple zone areas, accessible + * via `series['zone-area-x']` (where x is a number, + * starting with 0). + * + * @name Highcharts.Series#area + * @type {Highcharts.SVGElement|undefined} + */ + /** + * SVG element of line-based charts. Can be used for styling + * purposes. If zones are configured, this element will be + * hidden and replaced by multiple zone lines, accessible + * via `series['zone-graph-x']` (where x is a number, + * starting with 0). + * + * @name Highcharts.Series#graph + * @type {Highcharts.SVGElement|undefined} + */ + series[graphKey] = graph = series.chart.renderer + .path(graphPath) + .addClass(prop[1]) + .attr({ zIndex: 1 }) // #1069 + .add(series.group); + } + if (graph && !styledMode) { + attribs = { + 'stroke': prop[2], + 'stroke-width': options.lineWidth, + // Polygon series use filled graph + 'fill': (series.fillGraph && series.color) || 'none' + }; + if (prop[3]) { + attribs.dashstyle = prop[3]; + } + else if (options.linecap !== 'square') { + attribs['stroke-linecap'] = + attribs['stroke-linejoin'] = 'round'; + } + graph[verb](attribs) + // Add shadow to normal series (0) or to first + // zone (1) #3932 + .shadow((i < 2) && options.shadow); + } + // Helpers for animation + if (graph) { + graph.startX = graphPath.xMap; + graph.isArea = graphPath.isArea; // For arearange animation + } + }); + }, + /** + * Get zones properties for building graphs. Extendable by series with + * multiple lines within one series. + * + * @private + * @function Highcharts.Series#getZonesGraphs + * + * @param {Array>} props + * + * @return {Array>} + */ + getZonesGraphs: function (props) { + // Add the zone properties if any + this.zones.forEach(function (zone, i) { + var propset = [ + 'zone-graph-' + i, + 'highcharts-graph highcharts-zone-graph-' + i + ' ' + + (zone.className || '') + ]; + if (!this.chart.styledMode) { + propset.push((zone.color || this.color), (zone.dashStyle || this.options.dashStyle)); + } + props.push(propset); + }, this); + return props; + }, + /** + * Clip the graphs into zones for colors and styling. + * + * @private + * @function Highcharts.Series#applyZones + * @return {void} + */ + applyZones: function () { + var series = this, chart = this.chart, renderer = chart.renderer, zones = this.zones, translatedFrom, translatedTo, clips = (this.clips || []), clipAttr, graph = this.graph, area = this.area, chartSizeMax = Math.max(chart.chartWidth, chart.chartHeight), axis = this[(this.zoneAxis || 'y') + 'Axis'], extremes, reversed, inverted = chart.inverted, horiz, pxRange, pxPosMin, pxPosMax, ignoreZones = false, zoneArea, zoneGraph; + if (zones.length && + (graph || area) && + axis && + typeof axis.min !== 'undefined') { + reversed = axis.reversed; + horiz = axis.horiz; + // The use of the Color Threshold assumes there are no gaps + // so it is safe to hide the original graph and area + // unless it is not waterfall series, then use showLine property + // to set lines between columns to be visible (#7862) + if (graph && !this.showLine) { + graph.hide(); + } + if (area) { + area.hide(); + } + // Create the clips + extremes = axis.getExtremes(); + zones.forEach(function (threshold, i) { + translatedFrom = reversed ? + (horiz ? chart.plotWidth : 0) : + (horiz ? 0 : (axis.toPixels(extremes.min) || 0)); + translatedFrom = clamp(pick(translatedTo, translatedFrom), 0, chartSizeMax); + translatedTo = clamp(Math.round(axis.toPixels(pick(threshold.value, extremes.max), true) || 0), 0, chartSizeMax); + if (ignoreZones) { + translatedFrom = translatedTo = + axis.toPixels(extremes.max); + } + pxRange = Math.abs(translatedFrom - translatedTo); + pxPosMin = Math.min(translatedFrom, translatedTo); + pxPosMax = Math.max(translatedFrom, translatedTo); + if (axis.isXAxis) { + clipAttr = { + x: inverted ? pxPosMax : pxPosMin, + y: 0, + width: pxRange, + height: chartSizeMax + }; + if (!horiz) { + clipAttr.x = chart.plotHeight - clipAttr.x; + } + } + else { + clipAttr = { + x: 0, + y: inverted ? pxPosMax : pxPosMin, + width: chartSizeMax, + height: pxRange + }; + if (horiz) { + clipAttr.y = chart.plotWidth - clipAttr.y; + } + } + // VML SUPPPORT + if (inverted && renderer.isVML) { + if (axis.isXAxis) { + clipAttr = { + x: 0, + y: reversed ? pxPosMin : pxPosMax, + height: clipAttr.width, + width: chart.chartWidth + }; + } + else { + clipAttr = { + x: (clipAttr.y - + chart.plotLeft - + chart.spacingBox.x), + y: 0, + width: clipAttr.height, + height: chart.chartHeight + }; + } + } + // END OF VML SUPPORT + if (clips[i]) { + clips[i].animate(clipAttr); + } + else { + clips[i] = renderer.clipRect(clipAttr); + } + // when no data, graph zone is not applied and after setData + // clip was ignored. As a result, it should be applied each + // time. + zoneArea = series['zone-area-' + i]; + zoneGraph = series['zone-graph-' + i]; + if (graph && zoneGraph) { + zoneGraph.clip(clips[i]); + } + if (area && zoneArea) { + zoneArea.clip(clips[i]); + } + // if this zone extends out of the axis, ignore the others + ignoreZones = threshold.value > extremes.max; + // Clear translatedTo for indicators + if (series.resetZones && translatedTo === 0) { + translatedTo = void 0; + } + }); + this.clips = clips; + } + else if (series.visible) { + // If zones were removed, restore graph and area + if (graph) { + graph.show(true); + } + if (area) { + area.show(true); + } + } + }, + /** + * Initialize and perform group inversion on series.group and + * series.markerGroup. + * + * @private + * @function Highcharts.Series#invertGroups + * @param {boolean} [inverted] + * @return {void} + */ + invertGroups: function (inverted) { + var series = this, chart = series.chart; + /** + * @private + */ + function setInvert() { + ['group', 'markerGroup'].forEach(function (groupName) { + if (series[groupName]) { + // VML/HTML needs explicit attributes for flipping + if (chart.renderer.isVML) { + series[groupName].attr({ + width: series.yAxis.len, + height: series.xAxis.len + }); + } + series[groupName].width = series.yAxis.len; + series[groupName].height = series.xAxis.len; + // If inverted polar, don't invert series group + series[groupName].invert(series.isRadialSeries ? false : inverted); + } + }); + } + // Pie, go away (#1736) + if (!series.xAxis) { + return; + } + // A fixed size is needed for inversion to work + series.eventsToUnbind.push(addEvent(chart, 'resize', setInvert)); + // Do it now + setInvert(); + // On subsequent render and redraw, just do setInvert without + // setting up events again + series.invertGroups = setInvert; + }, + /** + * General abstraction for creating plot groups like series.group, + * series.dataLabelsGroup and series.markerGroup. On subsequent calls, + * the group will only be adjusted to the updated plot size. + * + * @private + * @function Highcharts.Series#plotGroup + * @param {string} prop + * @param {string} name + * @param {string} visibility + * @param {number} [zIndex] + * @param {Highcharts.SVGElement} [parent] + * @return {Highcharts.SVGElement} + */ + plotGroup: function (prop, name, visibility, zIndex, parent) { + var group = this[prop], isNew = !group; + // Generate it on first call + if (isNew) { + this[prop] = group = this.chart.renderer + .g() + .attr({ + zIndex: zIndex || 0.1 // IE8 and pointer logic use this + }) + .add(parent); + } + // Add the class names, and replace existing ones as response to + // Series.update (#6660) + group.addClass(('highcharts-' + name + + ' highcharts-series-' + this.index + + ' highcharts-' + this.type + '-series ' + + (defined(this.colorIndex) ? + 'highcharts-color-' + this.colorIndex + ' ' : + '') + + (this.options.className || '') + + (group.hasClass('highcharts-tracker') ? + ' highcharts-tracker' : + '')), true); + // Place it on first and subsequent (redraw) calls + group.attr({ visibility: visibility })[isNew ? 'attr' : 'animate'](this.getPlotBox()); + return group; + }, + /** + * Get the translation and scale for the plot area of this series. + * + * @function Highcharts.Series#getPlotBox + * + * @return {Highcharts.SeriesPlotBoxObject} + */ + getPlotBox: function () { + var chart = this.chart, xAxis = this.xAxis, yAxis = this.yAxis; + // Swap axes for inverted (#2339) + if (chart.inverted) { + xAxis = yAxis; + yAxis = this.xAxis; + } + return { + translateX: xAxis ? xAxis.left : chart.plotLeft, + translateY: yAxis ? yAxis.top : chart.plotTop, + scaleX: 1, + scaleY: 1 + }; + }, + /** + * Removes the event handlers attached previously with addEvents. + * + * @private + * @function Highcharts.Series#removeEvents + * @param {boolean} [keepEventsForUpdate] + * @return {void} + */ + removeEvents: function (keepEventsForUpdate) { + var series = this; + if (!keepEventsForUpdate) { + // remove all events + removeEvent(series); + } + else if (series.eventsToUnbind.length) { + // remove only internal events for proper update + // #12355 - solves problem with multiple destroy events + series.eventsToUnbind.forEach(function (unbind) { + unbind(); + }); + series.eventsToUnbind.length = 0; + } + }, + /** + * Render the graph and markers. Called internally when first rendering + * and later when redrawing the chart. This function can be extended in + * plugins, but normally shouldn't be called directly. + * + * @function Highcharts.Series#render + * + * @return {void} + * + * @fires Highcharts.Series#event:afterRender + */ + render: function () { + var series = this, chart = series.chart, group, options = series.options, + // Animation doesn't work in IE8 quirks when the group div is + // hidden, and looks bad in other oldIE + animDuration = (!series.finishedAnimating && + chart.renderer.isSVG && + animObject(options.animation).duration), visibility = series.visible ? 'inherit' : 'hidden', // #2597 + zIndex = options.zIndex, hasRendered = series.hasRendered, chartSeriesGroup = chart.seriesGroup, inverted = chart.inverted; + fireEvent(this, 'render'); + // the group + group = series.plotGroup('group', 'series', visibility, zIndex, chartSeriesGroup); + series.markerGroup = series.plotGroup('markerGroup', 'markers', visibility, zIndex, chartSeriesGroup); + // initiate the animation + if (animDuration && series.animate) { + series.animate(true); + } + // SVGRenderer needs to know this before drawing elements (#1089, + // #1795) + group.inverted = series.isCartesian || series.invertable ? + inverted : false; + // Draw the graph if any + if (series.drawGraph) { + series.drawGraph(); + series.applyZones(); + } + // Draw the points + if (series.visible) { + series.drawPoints(); + } + /* series.points.forEach(function (point) { + if (point.redraw) { + point.redraw(); + } + }); */ + // Draw the data labels + if (series.drawDataLabels) { + series.drawDataLabels(); + } + // In pie charts, slices are added to the DOM, but actual rendering + // is postponed until labels reserved their space + if (series.redrawPoints) { + series.redrawPoints(); + } + // draw the mouse tracking area + if (series.drawTracker && + series.options.enableMouseTracking !== false) { + series.drawTracker(); + } + // Handle inverted series and tracker groups + series.invertGroups(inverted); + // Initial clipping, must be defined after inverting groups for VML. + // Applies to columns etc. (#3839). + if (options.clip !== false && + !series.sharedClipKey && + !hasRendered) { + group.clip(chart.clipRect); + } + // Run the animation + if (animDuration && series.animate) { + series.animate(); + } + // Call the afterAnimate function on animation complete (but don't + // overwrite the animation.complete option which should be available + // to the user). + if (!hasRendered) { + series.animationTimeout = syncTimeout(function () { + series.afterAnimate(); + }, animDuration || 0); + } + // Means data is in accordance with what you see + series.isDirty = false; + // (See #322) series.isDirty = series.isDirtyData = false; // means + // data is in accordance with what you see + series.hasRendered = true; + fireEvent(series, 'afterRender'); + }, + /** + * Redraw the series. This function is called internally from + * `chart.redraw` and normally shouldn't be called directly. + * + * @private + * @function Highcharts.Series#redraw + * @return {void} + */ + redraw: function () { + var series = this, chart = series.chart, + // cache it here as it is set to false in render, but used after + wasDirty = series.isDirty || series.isDirtyData, group = series.group, xAxis = series.xAxis, yAxis = series.yAxis; + // reposition on resize + if (group) { + if (chart.inverted) { + group.attr({ + width: chart.plotWidth, + height: chart.plotHeight + }); + } + group.animate({ + translateX: pick(xAxis && xAxis.left, chart.plotLeft), + translateY: pick(yAxis && yAxis.top, chart.plotTop) + }); + } + series.translate(); + series.render(); + if (wasDirty) { // #3868, #3945 + delete this.kdTree; + } + }, + kdAxisArray: ['clientX', 'plotY'], + /** + * @private + * @function Highcharts.Series#searchPoint + * @param {Highcharts.PointerEventObject} e + * @param {boolean} [compareX] + * @return {Highcharts.Point} + */ + searchPoint: function (e, compareX) { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, inverted = series.chart.inverted; + return this.searchKDTree({ + clientX: inverted ? + xAxis.len - e.chartY + xAxis.pos : + e.chartX - xAxis.pos, + plotY: inverted ? + yAxis.len - e.chartX + yAxis.pos : + e.chartY - yAxis.pos + }, compareX, e); + }, + /** + * Build the k-d-tree that is used by mouse and touch interaction to get + * the closest point. Line-like series typically have a one-dimensional + * tree where points are searched along the X axis, while scatter-like + * series typically search in two dimensions, X and Y. + * + * @private + * @function Highcharts.Series#buildKDTree + * @param {Highcharts.PointerEventObject} [e] + * @return {void} + */ + buildKDTree: function (e) { + // Prevent multiple k-d-trees from being built simultaneously + // (#6235) + this.buildingKdTree = true; + var series = this, dimensions = series.options.findNearestPointBy + .indexOf('y') > -1 ? 2 : 1; + /** + * Internal function + * @private + */ + function _kdtree(points, depth, dimensions) { + var axis, median, length = points && points.length; + if (length) { + // alternate between the axis + axis = series.kdAxisArray[depth % dimensions]; + // sort point array + points.sort(function (a, b) { + return a[axis] - b[axis]; + }); + median = Math.floor(length / 2); + // build and return nod + return { + point: points[median], + left: _kdtree(points.slice(0, median), depth + 1, dimensions), + right: _kdtree(points.slice(median + 1), depth + 1, dimensions) + }; + } + } + /** + * Start the recursive build process with a clone of the points + * array and null points filtered out. (#3873) + * @private + */ + function startRecursive() { + series.kdTree = _kdtree(series.getValidPoints(null, + // For line-type series restrict to plot area, but + // column-type series not (#3916, #4511) + !series.directTouch), dimensions, dimensions); + series.buildingKdTree = false; + } + delete series.kdTree; + // For testing tooltips, don't build async. Also if touchstart, we + // may be dealing with click events on mobile, so don't delay + // (#6817). + syncTimeout(startRecursive, series.options.kdNow || (e && e.type === 'touchstart') ? 0 : 1); + }, + /** + * @private + * @function Highcharts.Series#searchKDTree + * @param {Highcharts.KDPointSearchObject} point + * @param {boolean} [compareX] + * @param {Highcharts.PointerEventObject} [e] + * @return {Highcharts.Point|undefined} + */ + searchKDTree: function (point, compareX, e) { + var series = this, kdX = this.kdAxisArray[0], kdY = this.kdAxisArray[1], kdComparer = compareX ? 'distX' : 'dist', kdDimensions = series.options.findNearestPointBy + .indexOf('y') > -1 ? 2 : 1; + /** + * Set the one and two dimensional distance on the point object. + * @private + */ + function setDistance(p1, p2) { + var x = (defined(p1[kdX]) && + defined(p2[kdX])) ? + Math.pow(p1[kdX] - p2[kdX], 2) : + null, y = (defined(p1[kdY]) && + defined(p2[kdY])) ? + Math.pow(p1[kdY] - p2[kdY], 2) : + null, r = (x || 0) + (y || 0); + p2.dist = defined(r) ? Math.sqrt(r) : Number.MAX_VALUE; + p2.distX = defined(x) ? Math.sqrt(x) : Number.MAX_VALUE; + } + /** + * @private + */ + function _search(search, tree, depth, dimensions) { + var point = tree.point, axis = series.kdAxisArray[depth % dimensions], tdist, sideA, sideB, ret = point, nPoint1, nPoint2; + setDistance(search, point); + // Pick side based on distance to splitting point + tdist = search[axis] - point[axis]; + sideA = tdist < 0 ? 'left' : 'right'; + sideB = tdist < 0 ? 'right' : 'left'; + // End of tree + if (tree[sideA]) { + nPoint1 = _search(search, tree[sideA], depth + 1, dimensions); + ret = (nPoint1[kdComparer] < + ret[kdComparer] ? + nPoint1 : + point); + } + if (tree[sideB]) { + // compare distance to current best to splitting point to + // decide wether to check side B or not + if (Math.sqrt(tdist * tdist) < ret[kdComparer]) { + nPoint2 = _search(search, tree[sideB], depth + 1, dimensions); + ret = (nPoint2[kdComparer] < + ret[kdComparer] ? + nPoint2 : + ret); + } + } + return ret; + } + if (!this.kdTree && !this.buildingKdTree) { + this.buildKDTree(e); + } + if (this.kdTree) { + return _search(point, this.kdTree, kdDimensions, kdDimensions); + } + }, + /** + * @private + * @function Highcharts.Series#pointPlacementToXValue + * @return {number} + */ + pointPlacementToXValue: function () { + var _a = this, _b = _a.options, pointPlacement = _b.pointPlacement, pointRange = _b.pointRange, axis = _a.xAxis; + var factor = pointPlacement; + // Point placement is relative to each series pointRange (#5889) + if (factor === 'between') { + factor = axis.reversed ? -0.5 : 0.5; // #11955 + } + return isNumber(factor) ? + factor * pick(pointRange, axis.pointRange) : + 0; + }, + /** + * @private + * @function Highcharts.Series#isPointInside + * @param {Highcharts.Point} point + * @return {boolean} + */ + isPointInside: function (point) { + var isInside = typeof point.plotY !== 'undefined' && + typeof point.plotX !== 'undefined' && + point.plotY >= 0 && + point.plotY <= this.yAxis.len && // #3519 + point.plotX >= 0 && + point.plotX <= this.xAxis.len; + return isInside; + } +}); // end Series prototype +/** + * A line series displays information as a series of data points connected by + * straight line segments. + * + * @sample {highcharts} highcharts/demo/line-basic/ + * Line chart + * @sample {highstock} stock/demo/basic-line/ + * Line chart + * + * @extends plotOptions.series + * @product highcharts highstock + * @apioption plotOptions.line + */ +/** + * The SVG value used for the `stroke-linecap` and `stroke-linejoin` + * of a line graph. Round means that lines are rounded in the ends and + * bends. + * + * @type {Highcharts.SeriesLinecapValue} + * @default round + * @since 3.0.7 + * @apioption plotOptions.line.linecap + */ +/** + * A `line` series. If the [type](#series.line.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.line + * @excluding dataParser,dataURL + * @product highcharts highstock + * @apioption series.line + */ +/** + * An array of data points for the series. For the `line` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 1], + * [1, 2], + * [2, 8] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.line.turboThreshold), + * this option is not available. + * ```js + * data: [{ + * x: 1, + * y: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * **Note:** In TypeScript you have to extend `PointOptionsObject` with an + * additional declaration to allow custom data types: + * ```ts + * declare module `highcharts` { + * interface PointOptionsObject { + * custom: Record; + * } + * } + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @declare Highcharts.PointOptionsObject + * @type {Array|null|*>} + * @apioption series.line.data + */ +/** + * An additional, individual class name for the data point's graphic + * representation. + * + * @type {string} + * @since 5.0.0 + * @product highcharts gantt + * @apioption series.line.data.className + */ +/** + * Individual color for the point. By default the color is pulled from + * the global `colors` array. + * + * In styled mode, the `color` option doesn't take effect. Instead, use + * `colorIndex`. + * + * @sample {highcharts} highcharts/point/color/ + * Mark the highest point + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock gantt + * @apioption series.line.data.color + */ +/** + * A specific color index to use for the point, so its graphic representations + * are given the class name `highcharts-color-{n}`. In styled mode this will + * change the color of the graphic. In non-styled mode, the color by is set by + * the `fill` attribute, so the change in class name won't have a visual effect + * by default. + * + * @type {number} + * @since 5.0.0 + * @product highcharts gantt + * @apioption series.line.data.colorIndex + */ +/** + * A reserved subspace to store options and values for customized functionality. + * Here you can add additional data for your own event callbacks and formatter + * callbacks. + * + * @sample {highcharts} highcharts/point/custom/ + * Point and series with custom data + * + * @type {Highcharts.Dictionary<*>} + * @apioption series.line.data.custom + */ +/** + * Individual data label for each point. The options are the same as + * the ones for [plotOptions.series.dataLabels]( + * #plotOptions.series.dataLabels). + * + * @sample highcharts/point/datalabels/ + * Show a label for the last value + * + * @declare Highcharts.DataLabelsOptions + * @extends plotOptions.line.dataLabels + * @product highcharts highstock gantt + * @apioption series.line.data.dataLabels + */ +/** + * A description of the point to add to the screen reader information + * about the point. + * + * @type {string} + * @since 5.0.0 + * @requires modules/accessibility + * @apioption series.line.data.description + */ +/** + * An id for the point. This can be used after render time to get a + * pointer to the point object through `chart.get()`. + * + * @sample {highcharts} highcharts/point/id/ + * Remove an id'd point + * + * @type {string} + * @since 1.2.0 + * @product highcharts highstock gantt + * @apioption series.line.data.id + */ +/** + * The rank for this point's data label in case of collision. If two + * data labels are about to overlap, only the one with the highest `labelrank` + * will be drawn. + * + * @type {number} + * @apioption series.line.data.labelrank + */ +/** + * The name of the point as shown in the legend, tooltip, dataLabels, etc. + * + * @see [xAxis.uniqueNames](#xAxis.uniqueNames) + * + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Point names + * + * @type {string} + * @apioption series.line.data.name + */ +/** + * Whether the data point is selected initially. + * + * @type {boolean} + * @default false + * @product highcharts highstock gantt + * @apioption series.line.data.selected + */ +/** + * The x value of the point. For datetime axes, the X value is the timestamp + * in milliseconds since 1970. + * + * @type {number} + * @product highcharts highstock + * @apioption series.line.data.x + */ +/** + * The y value of the point. + * + * @type {number|null} + * @product highcharts highstock + * @apioption series.line.data.y + */ +/** + * The individual point events. + * + * @extends plotOptions.series.point.events + * @product highcharts highstock gantt + * @apioption series.line.data.events + */ +/** + * Options for the point markers of line-like series. + * + * @declare Highcharts.PointMarkerOptionsObject + * @extends plotOptions.series.marker + * @product highcharts highstock + * @apioption series.line.data.marker + */ +''; // include precedent doclets in transpilat diff --git a/librerias/gantt/code/es-modules/parts/SplineSeries.js b/librerias/gantt/code/es-modules/parts/SplineSeries.js new file mode 100644 index 0000000..4763c1f --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/SplineSeries.js @@ -0,0 +1,246 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import U from './Utilities.js'; +var pick = U.pick, seriesType = U.seriesType; +import './Options.js'; +import './Series.js'; +/** + * Spline series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.spline + * + * @augments Highcarts.Series + */ +seriesType('spline', 'line', +/** + * A spline series is a special type of line series, where the segments + * between the data points are smoothed. + * + * @sample {highcharts} highcharts/demo/spline-irregular-time/ + * Spline chart + * @sample {highstock} stock/demo/spline/ + * Spline chart + * + * @extends plotOptions.series + * @excluding step + * @product highcharts highstock + * @optionparent plotOptions.spline + */ +{}, +/** + * @lends seriesTypes.spline.prototype + */ +{ + /* eslint-disable valid-jsdoc */ + /** + * Get the spline segment from a given point's previous neighbour to the + * given point. + * + * @private + * @function Highcharts.seriesTypes.spline#getPointSpline + * + * @param {Array} + * + * @param {Highcharts.Point} point + * + * @param {number} i + * + * @return {Highcharts.SVGPathArray} + */ + getPointSpline: function (points, point, i) { + var + // 1 means control points midway between points, 2 means 1/3 + // from the point, 3 is 1/4 etc + smoothing = 1.5, denom = smoothing + 1, plotX = point.plotX || 0, plotY = point.plotY || 0, lastPoint = points[i - 1], nextPoint = points[i + 1], leftContX, leftContY, rightContX, rightContY, ret; + /** + * @private + */ + function doCurve(otherPoint) { + return otherPoint && + !otherPoint.isNull && + otherPoint.doCurve !== false && + // #6387, area splines next to null: + !point.isCliff; + } + // Find control points + if (doCurve(lastPoint) && doCurve(nextPoint)) { + var lastX = lastPoint.plotX || 0, lastY = lastPoint.plotY || 0, nextX = nextPoint.plotX || 0, nextY = nextPoint.plotY || 0, correction = 0; + leftContX = (smoothing * plotX + lastX) / denom; + leftContY = (smoothing * plotY + lastY) / denom; + rightContX = (smoothing * plotX + nextX) / denom; + rightContY = (smoothing * plotY + nextY) / denom; + // Have the two control points make a straight line through main + // point + if (rightContX !== leftContX) { // #5016, division by zero + correction = (((rightContY - leftContY) * + (rightContX - plotX)) / + (rightContX - leftContX) + plotY - rightContY); + } + leftContY += correction; + rightContY += correction; + // to prevent false extremes, check that control points are + // between neighbouring points' y values + if (leftContY > lastY && leftContY > plotY) { + leftContY = Math.max(lastY, plotY); + // mirror of left control point + rightContY = 2 * plotY - leftContY; + } + else if (leftContY < lastY && leftContY < plotY) { + leftContY = Math.min(lastY, plotY); + rightContY = 2 * plotY - leftContY; + } + if (rightContY > nextY && rightContY > plotY) { + rightContY = Math.max(nextY, plotY); + leftContY = 2 * plotY - rightContY; + } + else if (rightContY < nextY && rightContY < plotY) { + rightContY = Math.min(nextY, plotY); + leftContY = 2 * plotY - rightContY; + } + // record for drawing in next point + point.rightContX = rightContX; + point.rightContY = rightContY; + } + // Visualize control points for debugging + /* + if (leftContX) { + this.chart.renderer.circle( + leftContX + this.chart.plotLeft, + leftContY + this.chart.plotTop, + 2 + ) + .attr({ + stroke: 'red', + 'stroke-width': 2, + fill: 'none', + zIndex: 9 + }) + .add(); + this.chart.renderer.path(['M', leftContX + this.chart.plotLeft, + leftContY + this.chart.plotTop, + 'L', plotX + this.chart.plotLeft, plotY + this.chart.plotTop]) + .attr({ + stroke: 'red', + 'stroke-width': 2, + zIndex: 9 + }) + .add(); + } + if (rightContX) { + this.chart.renderer.circle( + rightContX + this.chart.plotLeft, + rightContY + this.chart.plotTop, + 2 + ) + .attr({ + stroke: 'green', + 'stroke-width': 2, + fill: 'none', + zIndex: 9 + }) + .add(); + this.chart.renderer.path(['M', rightContX + this.chart.plotLeft, + rightContY + this.chart.plotTop, + 'L', plotX + this.chart.plotLeft, plotY + this.chart.plotTop]) + .attr({ + stroke: 'green', + 'stroke-width': 2, + zIndex: 9 + }) + .add(); + } + // */ + ret = [ + 'C', + pick(lastPoint.rightContX, lastPoint.plotX, 0), + pick(lastPoint.rightContY, lastPoint.plotY, 0), + pick(leftContX, plotX, 0), + pick(leftContY, plotY, 0), + plotX, + plotY + ]; + // reset for updating series later + lastPoint.rightContX = lastPoint.rightContY = void 0; + return ret; + } + /* eslint-enable valid-jsdoc */ +}); +/** + * A `spline` series. If the [type](#series.spline.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.spline + * @excluding dataParser, dataURL, step + * @product highcharts highstock + * @apioption series.spline + */ +/** + * An array of data points for the series. For the `spline` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 9], + * [1, 2], + * [2, 8] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.spline.turboThreshold), + * this option is not available. + * ```js + * data: [{ + * x: 1, + * y: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 0, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @product highcharts highstock + * @apioption series.spline.data + */ +''; // adds doclets above intro transpilat diff --git a/librerias/gantt/code/es-modules/parts/Stacking.js b/librerias/gantt/code/es-modules/parts/Stacking.js new file mode 100644 index 0000000..9799317 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/Stacking.js @@ -0,0 +1,475 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Axis from './Axis.js'; +import H from './Globals.js'; +import StackingAxis from './StackingAxis.js'; +import U from './Utilities.js'; +var correctFloat = U.correctFloat, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, format = U.format, pick = U.pick; +/** + * Stack of data points + * + * @product highcharts + * + * @interface Highcharts.StackItemObject + */ /** +* Alignment settings +* @name Highcharts.StackItemObject#alignOptions +* @type {Highcharts.AlignObject} +*/ /** +* Related axis +* @name Highcharts.StackItemObject#axis +* @type {Highcharts.Axis} +*/ /** +* Cumulative value of the stacked data points +* @name Highcharts.StackItemObject#cumulative +* @type {number} +*/ /** +* True if on the negative side +* @name Highcharts.StackItemObject#isNegative +* @type {boolean} +*/ /** +* Related SVG element +* @name Highcharts.StackItemObject#label +* @type {Highcharts.SVGElement} +*/ /** +* Related stack options +* @name Highcharts.StackItemObject#options +* @type {Highcharts.YAxisStackLabelsOptions} +*/ /** +* Total value of the stacked data points +* @name Highcharts.StackItemObject#total +* @type {number} +*/ /** +* Shared x value of the stack +* @name Highcharts.StackItemObject#x +* @type {number} +*/ +''; // detached doclets above +import './Chart.js'; +import './Series.js'; +var Chart = H.Chart, Series = H.Series; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * The class for stacks. Each stack, on a specific X value and either negative + * or positive, has its own stack item. + * + * @private + * @class + * @name Highcharts.StackItem + * @param {Highcharts.Axis} axis + * @param {Highcharts.YAxisStackLabelsOptions} options + * @param {boolean} isNegative + * @param {number} x + * @param {Highcharts.OptionsStackingValue} [stackOption] + */ +var StackItem = /** @class */ (function () { + function StackItem(axis, options, isNegative, x, stackOption) { + var inverted = axis.chart.inverted; + this.axis = axis; + // Tells if the stack is negative + this.isNegative = isNegative; + // Save the options to be able to style the label + this.options = options = options || {}; + // Save the x value to be able to position the label later + this.x = x; + // Initialize total value + this.total = null; + // This will keep each points' extremes stored by series.index and point + // index + this.points = {}; + // Save the stack option on the series configuration object, + // and whether to treat it as percent + this.stack = stackOption; + this.leftCliff = 0; + this.rightCliff = 0; + // The align options and text align varies on whether the stack is + // negative and if the chart is inverted or not. + // First test the user supplied value, then use the dynamic. + this.alignOptions = { + align: options.align || + (inverted ? (isNegative ? 'left' : 'right') : 'center'), + verticalAlign: options.verticalAlign || + (inverted ? 'middle' : (isNegative ? 'bottom' : 'top')), + y: options.y, + x: options.x + }; + this.textAlign = options.textAlign || + (inverted ? (isNegative ? 'right' : 'left') : 'center'); + } + /** + * @private + * @function Highcharts.StackItem#destroy + */ + StackItem.prototype.destroy = function () { + destroyObjectProperties(this, this.axis); + }; + /** + * Renders the stack total label and adds it to the stack label group. + * + * @private + * @function Highcharts.StackItem#render + * @param {Highcharts.SVGElement} group + */ + StackItem.prototype.render = function (group) { + var chart = this.axis.chart, options = this.options, formatOption = options.format, attr = {}, str = formatOption ? // format the text in the label + format(formatOption, this, chart) : + options.formatter.call(this); + // Change the text to reflect the new total and set visibility to hidden + // in case the serie is hidden + if (this.label) { + this.label.attr({ text: str, visibility: 'hidden' }); + } + else { + // Create new label + this.label = chart.renderer + .label(str, null, null, options.shape, null, null, options.useHTML, false, 'stack-labels'); + attr = { + r: options.borderRadius || 0, + text: str, + rotation: options.rotation, + padding: pick(options.padding, 5), + visibility: 'hidden' // hidden until setOffset is called + }; + if (!chart.styledMode) { + attr.fill = options.backgroundColor; + attr.stroke = options.borderColor; + attr['stroke-width'] = options.borderWidth; + this.label.css(options.style); + } + this.label.attr(attr); + if (!this.label.added) { + this.label.add(group); // add to the labels-group + } + } + // Rank it higher than data labels (#8742) + this.label.labelrank = chart.plotHeight; + }; + /** + * Sets the offset that the stack has from the x value and repositions the + * label. + * + * @private + * @function Highcarts.StackItem#setOffset + * @param {number} xOffset + * @param {number} xWidth + * @param {number} [boxBottom] + * @param {number} [boxTop] + * @param {number} [defaultX] + */ + StackItem.prototype.setOffset = function (xOffset, xWidth, boxBottom, boxTop, defaultX) { + var stackItem = this, axis = stackItem.axis, chart = axis.chart, + // stack value translated mapped to chart coordinates + y = axis.translate(axis.stacking.usePercentage ? + 100 : + (boxTop ? + boxTop : + stackItem.total), 0, 0, 0, 1), yZero = axis.translate(boxBottom ? boxBottom : 0), // stack origin + // stack height: + h = defined(y) && Math.abs(y - yZero), + // x position: + x = pick(defaultX, chart.xAxis[0].translate(stackItem.x)) + + xOffset, stackBox = defined(y) && stackItem.getStackBox(chart, stackItem, x, y, xWidth, h, axis), label = stackItem.label, isNegative = stackItem.isNegative, isJustify = pick(stackItem.options.overflow, 'justify') === 'justify', textAlign = stackItem.textAlign, visible; + if (label && stackBox) { + var bBox = label.getBBox(), padding = label.padding, boxOffsetX, boxOffsetY; + if (textAlign === 'left') { + boxOffsetX = chart.inverted ? -padding : padding; + } + else if (textAlign === 'right') { + boxOffsetX = bBox.width; + } + else { + if (chart.inverted && textAlign === 'center') { + boxOffsetX = bBox.width / 2; + } + else { + boxOffsetX = chart.inverted ? + (isNegative ? bBox.width + padding : -padding) : bBox.width / 2; + } + } + boxOffsetY = chart.inverted ? + bBox.height / 2 : (isNegative ? -padding : bBox.height); + // Reset alignOptions property after justify #12337 + stackItem.alignOptions.x = pick(stackItem.options.x, 0); + stackItem.alignOptions.y = pick(stackItem.options.y, 0); + // Set the stackBox position + stackBox.x -= boxOffsetX; + stackBox.y -= boxOffsetY; + // Align the label to the box + label.align(stackItem.alignOptions, null, stackBox); + // Check if label is inside the plotArea #12294 + if (chart.isInsidePlot(label.alignAttr.x + boxOffsetX - stackItem.alignOptions.x, label.alignAttr.y + boxOffsetY - stackItem.alignOptions.y)) { + label.show(); + } + else { + // Move label away to avoid the overlapping issues + label.alignAttr.y = -9999; + isJustify = false; + } + if (isJustify) { + // Justify stackLabel into the stackBox + Series.prototype.justifyDataLabel.call(this.axis, label, stackItem.alignOptions, label.alignAttr, bBox, stackBox); + } + label.attr({ + x: label.alignAttr.x, + y: label.alignAttr.y + }); + if (pick(!isJustify && stackItem.options.crop, true)) { + visible = chart.isInsidePlot(label.x - padding + label.width, label.y) && + chart.isInsidePlot(label.x + padding, label.y); + if (!visible) { + label.hide(); + } + } + } + }; + /** + * @private + * @function Highcharts.StackItem#getStackBox + * + * @param {Highcharts.Chart} chart + * + * @param {Highcharts.StackItem} stackItem + * + * @param {number} x + * + * @param {number} y + * + * @param {number} xWidth + * + * @param {number} h + * + * @param {Highcharts.Axis} axis + * + * @return {Highcharts.BBoxObject} + */ + StackItem.prototype.getStackBox = function (chart, stackItem, x, y, xWidth, h, axis) { + var reversed = stackItem.axis.reversed, inverted = chart.inverted, axisPos = axis.height + axis.pos - + (inverted ? chart.plotLeft : chart.plotTop), neg = (stackItem.isNegative && !reversed) || + (!stackItem.isNegative && reversed); // #4056 + return { + x: inverted ? (neg ? y - axis.right : y - h + axis.pos - chart.plotLeft) : + x + chart.xAxis[0].transB - chart.plotLeft, + y: inverted ? + axis.height - x - xWidth : + (neg ? + (axisPos - y - h) : + axisPos - y), + width: inverted ? h : xWidth, + height: inverted ? xWidth : h + }; + }; + return StackItem; +}()); +/** + * Generate stacks for each series and calculate stacks total values + * + * @private + * @function Highcharts.Chart#getStacks + * @return {void} + */ +Chart.prototype.getStacks = function () { + var chart = this, inverted = chart.inverted; + // reset stacks for each yAxis + chart.yAxis.forEach(function (axis) { + if (axis.stacking && axis.stacking.stacks && axis.hasVisibleSeries) { + axis.stacking.oldStacks = axis.stacking.stacks; + } + }); + chart.series.forEach(function (series) { + var xAxisOptions = series.xAxis && series.xAxis.options || {}; + if (series.options.stacking && + (series.visible === true || + chart.options.chart.ignoreHiddenSeries === false)) { + series.stackKey = [ + series.type, + pick(series.options.stack, ''), + inverted ? xAxisOptions.top : xAxisOptions.left, + inverted ? xAxisOptions.height : xAxisOptions.width + ].join(','); + } + }); +}; +// Stacking methods defined on the Axis prototype +StackingAxis.compose(Axis); +// Stacking methods defnied for Series prototype +/** + * Adds series' points value to corresponding stack + * + * @private + * @function Highcharts.Series#setStackedPoints + */ +Series.prototype.setStackedPoints = function () { + if (!this.options.stacking || + (this.visible !== true && + this.chart.options.chart.ignoreHiddenSeries !== false)) { + return; + } + var series = this, xData = series.processedXData, yData = series.processedYData, stackedYData = [], yDataLength = yData.length, seriesOptions = series.options, threshold = seriesOptions.threshold, stackThreshold = pick(seriesOptions.startFromThreshold && threshold, 0), stackOption = seriesOptions.stack, stacking = seriesOptions.stacking, stackKey = series.stackKey, negKey = '-' + stackKey, negStacks = series.negStacks, yAxis = series.yAxis, stacks = yAxis.stacking.stacks, oldStacks = yAxis.stacking.oldStacks, stackIndicator, isNegative, stack, other, key, pointKey, i, x, y; + yAxis.stacking.stacksTouched += 1; + // loop over the non-null y values and read them into a local array + for (i = 0; i < yDataLength; i++) { + x = xData[i]; + y = yData[i]; + stackIndicator = series.getStackIndicator(stackIndicator, x, series.index); + pointKey = stackIndicator.key; + // Read stacked values into a stack based on the x value, + // the sign of y and the stack key. Stacking is also handled for null + // values (#739) + isNegative = negStacks && y < (stackThreshold ? 0 : threshold); + key = isNegative ? negKey : stackKey; + // Create empty object for this stack if it doesn't exist yet + if (!stacks[key]) { + stacks[key] = + {}; + } + // Initialize StackItem for this x + if (!stacks[key][x]) { + if (oldStacks[key] && + oldStacks[key][x]) { + stacks[key][x] = oldStacks[key][x]; + stacks[key][x].total = null; + } + else { + stacks[key][x] = new StackItem(yAxis, yAxis.options.stackLabels, isNegative, x, stackOption); + } + } + // If the StackItem doesn't exist, create it first + stack = stacks[key][x]; + if (y !== null) { + stack.points[pointKey] = stack.points[series.index] = + [pick(stack.cumulative, stackThreshold)]; + // Record the base of the stack + if (!defined(stack.cumulative)) { + stack.base = pointKey; + } + stack.touched = yAxis.stacking.stacksTouched; + // In area charts, if there are multiple points on the same X value, + // let the area fill the full span of those points + if (stackIndicator.index > 0 && series.singleStacks === false) { + stack.points[pointKey][0] = + stack.points[series.index + ',' + x + ',0'][0]; + } + // When updating to null, reset the point stack (#7493) + } + else { + stack.points[pointKey] = stack.points[series.index] = + null; + } + // Add value to the stack total + if (stacking === 'percent') { + // Percent stacked column, totals are the same for the positive and + // negative stacks + other = isNegative ? stackKey : negKey; + if (negStacks && stacks[other] && stacks[other][x]) { + other = stacks[other][x]; + stack.total = other.total = + Math.max(other.total, stack.total) + + Math.abs(y) || + 0; + // Percent stacked areas + } + else { + stack.total = + correctFloat(stack.total + (Math.abs(y) || 0)); + } + } + else { + stack.total = correctFloat(stack.total + (y || 0)); + } + stack.cumulative = + pick(stack.cumulative, stackThreshold) + (y || 0); + if (y !== null) { + stack.points[pointKey].push(stack.cumulative); + stackedYData[i] = stack.cumulative; + } + } + if (stacking === 'percent') { + yAxis.stacking.usePercentage = true; + } + this.stackedYData = stackedYData; // To be used in getExtremes + // Reset old stacks + yAxis.stacking.oldStacks = {}; +}; +/** + * Iterate over all stacks and compute the absolute values to percent + * + * @private + * @function Highcharts.Series#modifyStacks + */ +Series.prototype.modifyStacks = function () { + var series = this, yAxis = series.yAxis, stackKey = series.stackKey, stacks = yAxis.stacking.stacks, processedXData = series.processedXData, stackIndicator, stacking = series.options.stacking; + if (series[stacking + 'Stacker']) { // Modifier function exists + [stackKey, '-' + stackKey].forEach(function (key) { + var i = processedXData.length, x, stack, pointExtremes; + while (i--) { + x = processedXData[i]; + stackIndicator = series.getStackIndicator(stackIndicator, x, series.index, key); + stack = stacks[key] && stacks[key][x]; + pointExtremes = + stack && stack.points[stackIndicator.key]; + if (pointExtremes) { + series[stacking + 'Stacker'](pointExtremes, stack, i); + } + } + }); + } +}; +/** + * Modifier function for percent stacks. Blows up the stack to 100%. + * + * @private + * @function Highcharts.Series#percentStacker + * @param {Array} pointExtremes + * @param {Highcharts.StackItem} stack + * @param {number} i + */ +Series.prototype.percentStacker = function (pointExtremes, stack, i) { + var totalFactor = stack.total ? 100 / stack.total : 0; + // Y bottom value + pointExtremes[0] = correctFloat(pointExtremes[0] * totalFactor); + // Y value + pointExtremes[1] = correctFloat(pointExtremes[1] * totalFactor); + this.stackedYData[i] = pointExtremes[1]; +}; +/** + * Get stack indicator, according to it's x-value, to determine points with the + * same x-value + * + * @private + * @function Highcharts.Series#getStackIndicator + * @param {Highcharts.StackItemIndicatorObject|undefined} stackIndicator + * @param {number} x + * @param {number} index + * @param {string} [key] + * @return {Highcharts.StackItemIndicatorObject} + */ +Series.prototype.getStackIndicator = function (stackIndicator, x, index, key) { + // Update stack indicator, when: + // first point in a stack || x changed || stack type (negative vs positive) + // changed: + if (!defined(stackIndicator) || + stackIndicator.x !== x || + (key && stackIndicator.key !== key)) { + stackIndicator = { + x: x, + index: 0, + key: key + }; + } + else { + (stackIndicator).index++; + } + stackIndicator.key = + [index, x, stackIndicator.index].join(','); + return stackIndicator; +}; +H.StackItem = StackItem; +export default H.StackItem; diff --git a/librerias/gantt/code/es-modules/parts/StackingAxis.js b/librerias/gantt/code/es-modules/parts/StackingAxis.js new file mode 100644 index 0000000..918ff92 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/StackingAxis.js @@ -0,0 +1,186 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +import U from './Utilities.js'; +var addEvent = U.addEvent, destroyObjectProperties = U.destroyObjectProperties, fireEvent = U.fireEvent, objectEach = U.objectEach, pick = U.pick; +/* eslint-disable valid-jsdoc */ +/** + * Adds stacking support to axes. + * @private + * @class + */ +var StackingAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function StackingAxisAdditions(axis) { + this.oldStacks = {}; + this.stacks = {}; + this.stacksTouched = 0; + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Build the stacks from top down + * @private + */ + StackingAxisAdditions.prototype.buildStacks = function () { + var stacking = this; + var axis = stacking.axis; + var axisSeries = axis.series; + var reversedStacks = pick(axis.options.reversedStacks, true); + var len = axisSeries.length; + var actualSeries, i; + if (!axis.isXAxis) { + stacking.usePercentage = false; + i = len; + while (i--) { + actualSeries = axisSeries[reversedStacks ? i : len - i - 1]; + actualSeries.setStackedPoints(); + } + // Loop up again to compute percent and stream stack + for (i = 0; i < len; i++) { + axisSeries[i].modifyStacks(); + } + fireEvent(axis, 'afterBuildStacks'); + } + }; + /** + * @private + */ + StackingAxisAdditions.prototype.cleanStacks = function () { + var stacking = this; + var axis = stacking.axis; + var stacks; + if (!axis.isXAxis) { + if (stacking.oldStacks) { + stacks = stacking.stacks = stacking.oldStacks; + } + // reset stacks + objectEach(stacks, function (type) { + objectEach(type, function (stack) { + stack.cumulative = stack.total; + }); + }); + } + }; + /** + * Set all the stacks to initial states and destroy unused ones. + * @private + */ + StackingAxisAdditions.prototype.resetStacks = function () { + var stacking = this; + var axis = stacking.axis; + var stacks = stacking.stacks; + if (!axis.isXAxis) { + objectEach(stacks, function (type) { + objectEach(type, function (stack, key) { + // Clean up memory after point deletion (#1044, #4320) + if (stack.touched < stacking.stacksTouched) { + stack.destroy(); + delete type[key]; + // Reset stacks + } + else { + stack.total = null; + stack.cumulative = null; + } + }); + }); + } + }; + /** + * @private + */ + StackingAxisAdditions.prototype.renderStackTotals = function () { + var stacking = this; + var axis = stacking.axis; + var chart = axis.chart; + var renderer = chart.renderer; + var stacks = stacking.stacks; + var stackTotalGroup = stacking.stackTotalGroup = (stacking.stackTotalGroup || + renderer + .g('stack-labels') + .attr({ + visibility: 'visible', + zIndex: 6 + }) + .add()); + // plotLeft/Top will change when y axis gets wider so we need to + // translate the stackTotalGroup at every render call. See bug #506 + // and #516 + stackTotalGroup.translate(chart.plotLeft, chart.plotTop); + // Render each stack total + objectEach(stacks, function (type) { + objectEach(type, function (stack) { + stack.render(stackTotalGroup); + }); + }); + }; + return StackingAxisAdditions; +}()); +/** + * Axis with stacking support. + * @private + * @class + */ +var StackingAxis = /** @class */ (function () { + function StackingAxis() { + } + /* * + * + * Static Functions + * + * */ + /** + * Extends axis with stacking support. + * @private + */ + StackingAxis.compose = function (AxisClass) { + var axisProto = AxisClass.prototype; + addEvent(AxisClass, 'init', StackingAxis.onInit); + addEvent(AxisClass, 'destroy', StackingAxis.onDestroy); + }; + /** + * @private + */ + StackingAxis.onDestroy = function () { + var stacking = this.stacking; + if (!stacking) { + return; + } + var stacks = stacking.stacks; + // Destroy each stack total + objectEach(stacks, function (stack, stackKey) { + destroyObjectProperties(stack); + stacks[stackKey] = null; + }); + if (stacking && + stacking.stackTotalGroup) { + stacking.stackTotalGroup.destroy(); + } + }; + /** + * @private + */ + StackingAxis.onInit = function () { + var axis = this; + if (!axis.stacking) { + axis.stacking = new StackingAxisAdditions(axis); + } + }; + return StackingAxis; +}()); +export default StackingAxis; diff --git a/librerias/gantt/code/es-modules/parts/StockChart.js b/librerias/gantt/code/es-modules/parts/StockChart.js new file mode 100644 index 0000000..e7b11ee --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/StockChart.js @@ -0,0 +1,758 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Axis from './Axis.js'; +import H from './Globals.js'; +import Point from './Point.js'; +import U from './Utilities.js'; +var addEvent = U.addEvent, arrayMax = U.arrayMax, arrayMin = U.arrayMin, clamp = U.clamp, defined = U.defined, extend = U.extend, find = U.find, format = U.format, isNumber = U.isNumber, isString = U.isString, merge = U.merge, pick = U.pick, splat = U.splat; +import './Chart.js'; +import './Pointer.js'; +import './Series.js'; +import './SvgRenderer.js'; +// Has a dependency on Navigator due to the use of +// defaultOptions.navigator +import './Navigator.js'; +// Has a dependency on Scrollbar due to the use of +// defaultOptions.scrollbar +import './Scrollbar.js'; +// Has a dependency on RangeSelector due to the use of +// defaultOptions.rangeSelector +import './RangeSelector.js'; +var Chart = H.Chart, Renderer = H.Renderer, Series = H.Series, SVGRenderer = H.SVGRenderer, seriesProto = Series.prototype, seriesInit = seriesProto.init, seriesProcessData = seriesProto.processData, pointTooltipFormatter = Point.prototype.tooltipFormatter; +/** + * Compare the values of the series against the first non-null, non- + * zero value in the visible range. The y axis will show percentage + * or absolute change depending on whether `compare` is set to `"percent"` + * or `"value"`. When this is applied to multiple series, it allows + * comparing the development of the series against each other. Adds + * a `change` field to every point object. + * + * @see [compareBase](#plotOptions.series.compareBase) + * @see [Axis.setCompare()](/class-reference/Highcharts.Axis#setCompare) + * + * @sample {highstock} stock/plotoptions/series-compare-percent/ + * Percent + * @sample {highstock} stock/plotoptions/series-compare-value/ + * Value + * + * @type {string} + * @since 1.0.1 + * @product highstock + * @apioption plotOptions.series.compare + */ +/** + * Defines if comparison should start from the first point within the visible + * range or should start from the first point **before** the range. + * + * In other words, this flag determines if first point within the visible range + * will have 0% (`compareStart=true`) or should have been already calculated + * according to the previous point (`compareStart=false`). + * + * @sample {highstock} stock/plotoptions/series-comparestart/ + * Calculate compare within visible range + * + * @type {boolean} + * @default false + * @since 6.0.0 + * @product highstock + * @apioption plotOptions.series.compareStart + */ +/** + * When [compare](#plotOptions.series.compare) is `percent`, this option + * dictates whether to use 0 or 100 as the base of comparison. + * + * @sample {highstock} stock/plotoptions/series-comparebase/ + * Compare base is 100 + * + * @type {number} + * @default 0 + * @since 5.0.6 + * @product highstock + * @validvalue [0, 100] + * @apioption plotOptions.series.compareBase + */ +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * Factory function for creating new stock charts. Creates a new + * {@link Highcharts.Chart|Chart} object with different default options than the + * basic Chart. + * + * @example + * var chart = Highcharts.stockChart('container', { + * series: [{ + * data: [1, 2, 3, 4, 5, 6, 7, 8, 9], + * pointInterval: 24 * 60 * 60 * 1000 + * }] + * }); + * + * @function Highcharts.stockChart + * + * @param {string|Highcharts.HTMLDOMElement} [renderTo] + * The DOM element to render to, or its id. + * + * @param {Highcharts.Options} options + * The chart options structure as described in the + * [options reference](https://api.highcharts.com/highstock). + * + * @param {Highcharts.ChartCallbackFunction} [callback] + * A function to execute when the chart object is finished loading and + * rendering. In most cases the chart is built in one thread, but in + * Internet Explorer version 8 or less the chart is sometimes + * initialized before the document is ready, and in these cases the + * chart object will not be finished synchronously. As a consequence, + * code that relies on the newly built Chart object should always run in + * the callback. Defining a + * [chart.events.load](https://api.highcharts.com/highstock/chart.events.load) + * handler is equivalent. + * + * @return {Highcharts.Chart} + * The chart object. + */ +H.StockChart = H.stockChart = function (a, b, c) { + var hasRenderToArg = isString(a) || a.nodeName, options = arguments[hasRenderToArg ? 1 : 0], userOptions = options, + // to increase performance, don't merge the data + seriesOptions = options.series, defaultOptions = H.getOptions(), opposite, + // Always disable startOnTick:true on the main axis when the navigator + // is enabled (#1090) + navigatorEnabled = pick(options.navigator && options.navigator.enabled, defaultOptions.navigator.enabled, true); + // apply X axis options to both single and multi y axes + options.xAxis = splat(options.xAxis || {}).map(function (xAxisOptions, i) { + return merge({ + minPadding: 0, + maxPadding: 0, + overscroll: 0, + ordinal: true, + title: { + text: null + }, + labels: { + overflow: 'justify' + }, + showLastLabel: true + }, defaultOptions.xAxis, // #3802 + defaultOptions.xAxis && defaultOptions.xAxis[i], // #7690 + xAxisOptions, // user options + { + type: 'datetime', + categories: null + }, (navigatorEnabled ? { + startOnTick: false, + endOnTick: false + } : null)); + }); + // apply Y axis options to both single and multi y axes + options.yAxis = splat(options.yAxis || {}).map(function (yAxisOptions, i) { + opposite = pick(yAxisOptions.opposite, true); + return merge({ + labels: { + y: -2 + }, + opposite: opposite, + /** + * @default {highcharts} true + * @default {highstock} false + * @apioption yAxis.showLastLabel + * + * @private + */ + showLastLabel: !!( + // #6104, show last label by default for category axes + yAxisOptions.categories || + yAxisOptions.type === 'category'), + title: { + text: null + } + }, defaultOptions.yAxis, // #3802 + defaultOptions.yAxis && defaultOptions.yAxis[i], // #7690 + yAxisOptions // user options + ); + }); + options.series = null; + options = merge({ + chart: { + panning: { + enabled: true, + type: 'x' + }, + pinchType: 'x' + }, + navigator: { + enabled: navigatorEnabled + }, + scrollbar: { + // #4988 - check if setOptions was called + enabled: pick(defaultOptions.scrollbar.enabled, true) + }, + rangeSelector: { + // #4988 - check if setOptions was called + enabled: pick(defaultOptions.rangeSelector.enabled, true) + }, + title: { + text: null + }, + tooltip: { + split: pick(defaultOptions.tooltip.split, true), + crosshairs: true + }, + legend: { + enabled: false + } + }, options, // user's options + { + isStock: true // internal flag + }); + options.series = userOptions.series = seriesOptions; + return hasRenderToArg ? + new Chart(a, options, c) : + new Chart(options, b); +}; +// Handle som Stock-specific series defaults, override the plotOptions before +// series options are handled. +addEvent(Series, 'setOptions', function (e) { + var overrides; + if (this.chart.options.isStock) { + if (this.is('column') || this.is('columnrange')) { + overrides = { + borderWidth: 0, + shadow: false + }; + } + else if (!this.is('scatter') && !this.is('sma')) { + overrides = { + marker: { + enabled: false, + radius: 2 + } + }; + } + if (overrides) { + e.plotOptions[this.type] = merge(e.plotOptions[this.type], overrides); + } + } +}); +// Override the automatic label alignment so that the first Y axis' labels +// are drawn on top of the grid line, and subsequent axes are drawn outside +addEvent(Axis, 'autoLabelAlign', function (e) { + var chart = this.chart, options = this.options, panes = chart._labelPanes = chart._labelPanes || {}, key, labelOptions = this.options.labels; + if (this.chart.options.isStock && this.coll === 'yAxis') { + key = options.top + ',' + options.height; + // do it only for the first Y axis of each pane + if (!panes[key] && labelOptions.enabled) { + if (labelOptions.x === 15) { // default + labelOptions.x = 0; + } + if (typeof labelOptions.align === 'undefined') { + labelOptions.align = 'right'; + } + panes[key] = this; + e.align = 'right'; + e.preventDefault(); + } + } +}); +// Clear axis from label panes (#6071) +addEvent(Axis, 'destroy', function () { + var chart = this.chart, key = this.options && (this.options.top + ',' + this.options.height); + if (key && chart._labelPanes && chart._labelPanes[key] === this) { + delete chart._labelPanes[key]; + } +}); +// Override getPlotLinePath to allow for multipane charts +addEvent(Axis, 'getPlotLinePath', function (e) { + var axis = this, series = (this.isLinked && !this.series ? + this.linkedParent.series : + this.series), chart = axis.chart, renderer = chart.renderer, axisLeft = axis.left, axisTop = axis.top, x1, y1, x2, y2, result = [], axes = [], // #3416 need a default array + axes2, uniqueAxes, translatedValue = e.translatedValue, value = e.value, force = e.force, transVal; + /** + * Return the other axis based on either the axis option or on related + * series. + * @private + */ + function getAxis(coll) { + var otherColl = coll === 'xAxis' ? 'yAxis' : 'xAxis', opt = axis.options[otherColl]; + // Other axis indexed by number + if (isNumber(opt)) { + return [chart[otherColl][opt]]; + } + // Other axis indexed by id (like navigator) + if (isString(opt)) { + return [chart.get(opt)]; + } + // Auto detect based on existing series + return series.map(function (s) { + return s[otherColl]; + }); + } + if ( // For stock chart, by default render paths across the panes + // except the case when `acrossPanes` is disabled by user (#6644) + (chart.options.isStock && e.acrossPanes !== false) && + // Ignore in case of colorAxis or zAxis. #3360, #3524, #6720 + axis.coll === 'xAxis' || axis.coll === 'yAxis') { + e.preventDefault(); + // Get the related axes based on series + axes = getAxis(axis.coll); + // Get the related axes based options.*Axis setting #2810 + axes2 = (axis.isXAxis ? chart.yAxis : chart.xAxis); + axes2.forEach(function (A) { + if (defined(A.options.id) ? + A.options.id.indexOf('navigator') === -1 : + true) { + var a = (A.isXAxis ? 'yAxis' : 'xAxis'), rax = (defined(A.options[a]) ? + chart[a][A.options[a]] : + chart[a][0]); + if (axis === rax) { + axes.push(A); + } + } + }); + // Remove duplicates in the axes array. If there are no axes in the axes + // array, we are adding an axis without data, so we need to populate + // this with grid lines (#2796). + uniqueAxes = axes.length ? + [] : + [axis.isXAxis ? chart.yAxis[0] : chart.xAxis[0]]; // #3742 + axes.forEach(function (axis2) { + if (uniqueAxes.indexOf(axis2) === -1 && + // Do not draw on axis which overlap completely. #5424 + !find(uniqueAxes, function (unique) { + return unique.pos === axis2.pos && unique.len === axis2.len; + })) { + uniqueAxes.push(axis2); + } + }); + transVal = pick(translatedValue, axis.translate(value, null, null, e.old)); + if (isNumber(transVal)) { + if (axis.horiz) { + uniqueAxes.forEach(function (axis2) { + var skip; + y1 = axis2.pos; + y2 = y1 + axis2.len; + x1 = x2 = Math.round(transVal + axis.transB); + // outside plot area + if (force !== 'pass' && + (x1 < axisLeft || x1 > axisLeft + axis.width)) { + if (force) { + x1 = x2 = clamp(x1, axisLeft, axisLeft + axis.width); + } + else { + skip = true; + } + } + if (!skip) { + result.push(['M', x1, y1], ['L', x2, y2]); + } + }); + } + else { + uniqueAxes.forEach(function (axis2) { + var skip; + x1 = axis2.pos; + x2 = x1 + axis2.len; + y1 = y2 = Math.round(axisTop + axis.height - transVal); + // outside plot area + if (force !== 'pass' && + (y1 < axisTop || y1 > axisTop + axis.height)) { + if (force) { + y1 = y2 = clamp(y1, axisTop, axisTop + axis.height); + } + else { + skip = true; + } + } + if (!skip) { + result.push(['M', x1, y1], ['L', x2, y2]); + } + }); + } + } + e.path = result.length > 0 ? + renderer.crispPolyLine(result, e.lineWidth || 1) : + // #3557 getPlotLinePath in regular Highcharts also returns null + null; + } +}); +/** + * Function to crisp a line with multiple segments + * + * @private + * @function Highcharts.SVGRenderer#crispPolyLine + * @param {Highcharts.SVGPathArray} points + * @param {number} width + * @return {Highcharts.SVGPathArray} + */ +SVGRenderer.prototype.crispPolyLine = function (points, width) { + // points format: [['M', 0, 0], ['L', 100, 0]] + // normalize to a crisp line + for (var i = 0; i < points.length; i = i + 2) { + var start = points[i], end = points[i + 1]; + if (start[1] === end[1]) { + // Substract due to #1129. Now bottom and left axis gridlines behave + // the same. + start[1] = end[1] = + Math.round(start[1]) - (width % 2 / 2); + } + if (start[2] === end[2]) { + start[2] = end[2] = + Math.round(start[2]) + (width % 2 / 2); + } + } + return points; +}; +// Wrapper to hide the label +addEvent(Axis, 'afterHideCrosshair', function () { + if (this.crossLabel) { + this.crossLabel = this.crossLabel.hide(); + } +}); +// Extend crosshairs to also draw the label +addEvent(Axis, 'afterDrawCrosshair', function (event) { + // Check if the label has to be drawn + if (!defined(this.crosshair.label) || + !this.crosshair.label.enabled || + !this.cross) { + return; + } + var chart = this.chart, log = this.logarithmic, options = this.options.crosshair.label, // the label's options + horiz = this.horiz, // axis orientation + opposite = this.opposite, // axis position + left = this.left, // left position + top = this.top, // top position + crossLabel = this.crossLabel, // the svgElement + posx, posy, crossBox, formatOption = options.format, formatFormat = '', limit, align, tickInside = this.options.tickPosition === 'inside', snap = this.crosshair.snap !== false, value, offset = 0, + // Use last available event (#5287) + e = event.e || (this.cross && this.cross.e), point = event.point, min = this.min, max = this.max; + if (log) { + min = log.lin2log(min); + max = log.lin2log(max); + } + align = (horiz ? 'center' : opposite ? + (this.labelAlign === 'right' ? 'right' : 'left') : + (this.labelAlign === 'left' ? 'left' : 'center')); + // If the label does not exist yet, create it. + if (!crossLabel) { + crossLabel = this.crossLabel = chart.renderer + .label(null, null, null, options.shape || 'callout') + .addClass('highcharts-crosshair-label' + (this.series[0] && + ' highcharts-color-' + this.series[0].colorIndex)) + .attr({ + align: options.align || align, + padding: pick(options.padding, 8), + r: pick(options.borderRadius, 3), + zIndex: 2 + }) + .add(this.labelGroup); + // Presentational + if (!chart.styledMode) { + crossLabel + .attr({ + fill: options.backgroundColor || + (this.series[0] && this.series[0].color) || + '#666666', + stroke: options.borderColor || '', + 'stroke-width': options.borderWidth || 0 + }) + .css(extend({ + color: '#ffffff', + fontWeight: 'normal', + fontSize: '11px', + textAlign: 'center' + }, options.style)); + } + } + if (horiz) { + posx = snap ? point.plotX + left : e.chartX; + posy = top + (opposite ? 0 : this.height); + } + else { + posx = opposite ? this.width + left : 0; + posy = snap ? point.plotY + top : e.chartY; + } + if (!formatOption && !options.formatter) { + if (this.dateTime) { + formatFormat = '%b %d, %Y'; + } + formatOption = + '{value' + (formatFormat ? ':' + formatFormat : '') + '}'; + } + // Show the label + value = snap ? + point[this.isXAxis ? 'x' : 'y'] : + this.toValue(horiz ? e.chartX : e.chartY); + crossLabel.attr({ + text: formatOption ? + format(formatOption, { value: value }, chart) : + options.formatter.call(this, value), + x: posx, + y: posy, + // Crosshair should be rendered within Axis range (#7219) + visibility: value < min || value > max ? + 'hidden' : + 'visible' + }); + crossBox = crossLabel.getBBox(); + // now it is placed we can correct its position + if (horiz) { + if ((tickInside && !opposite) || (!tickInside && opposite)) { + posy = crossLabel.y - crossBox.height; + } + } + else { + posy = crossLabel.y - (crossBox.height / 2); + } + // check the edges + if (horiz) { + limit = { + left: left - crossBox.x, + right: left + this.width - crossBox.x + }; + } + else { + limit = { + left: this.labelAlign === 'left' ? left : 0, + right: this.labelAlign === 'right' ? + left + this.width : + chart.chartWidth + }; + } + // left edge + if (crossLabel.translateX < limit.left) { + offset = limit.left - crossLabel.translateX; + } + // right edge + if (crossLabel.translateX + crossBox.width >= limit.right) { + offset = -(crossLabel.translateX + crossBox.width - limit.right); + } + // show the crosslabel + crossLabel.attr({ + x: posx + offset, + y: posy, + // First set x and y, then anchorX and anchorY, when box is actually + // calculated, #5702 + anchorX: horiz ? + posx : + (this.opposite ? 0 : chart.chartWidth), + anchorY: horiz ? + (this.opposite ? chart.chartHeight : 0) : + posy + crossBox.height / 2 + }); +}); +/* ************************************************************************** * + * Start value compare logic * + * ************************************************************************** */ +/** + * Extend series.init by adding a method to modify the y value used for plotting + * on the y axis. This method is called both from the axis when finding dataMin + * and dataMax, and from the series.translate method. + * + * @ignore + * @function Highcharts.Series#init + */ +seriesProto.init = function () { + // Call base method + seriesInit.apply(this, arguments); + // Set comparison mode + this.setCompare(this.options.compare); +}; +/** + * Highstock only. Set the + * [compare](https://api.highcharts.com/highstock/plotOptions.series.compare) + * mode of the series after render time. In most cases it is more useful running + * {@link Axis#setCompare} on the X axis to update all its series. + * + * @function Highcharts.Series#setCompare + * + * @param {string} [compare] + * Can be one of `null` (default), `"percent"` or `"value"`. + */ +seriesProto.setCompare = function (compare) { + // Set or unset the modifyValue method + this.modifyValue = (compare === 'value' || compare === 'percent') ? + function (value, point) { + var compareValue = this.compareValue; + if (typeof value !== 'undefined' && + typeof compareValue !== 'undefined') { // #2601, #5814 + // Get the modified value + if (compare === 'value') { + value -= compareValue; + // Compare percent + } + else { + value = 100 * (value / compareValue) - + (this.options.compareBase === 100 ? 0 : 100); + } + // record for tooltip etc. + if (point) { + point.change = value; + } + return value; + } + return 0; + } : + null; + // Survive to export, #5485 + this.userOptions.compare = compare; + // Mark dirty + if (this.chart.hasRendered) { + this.isDirty = true; + } +}; +/** + * Extend series.processData by finding the first y value in the plot area, + * used for comparing the following values + * + * @ignore + * @function Highcharts.Series#processData + */ +seriesProto.processData = function (force) { + var series = this, i, keyIndex = -1, processedXData, processedYData, compareStart = series.options.compareStart === true ? 0 : 1, length, compareValue; + // call base method + seriesProcessData.apply(this, arguments); + if (series.xAxis && series.processedYData) { // not pies + // local variables + processedXData = series.processedXData; + processedYData = series.processedYData; + length = processedYData.length; + // For series with more than one value (range, OHLC etc), compare + // against close or the pointValKey (#4922, #3112, #9854) + if (series.pointArrayMap) { + keyIndex = series.pointArrayMap.indexOf(series.options.pointValKey || series.pointValKey || 'y'); + } + // find the first value for comparison + for (i = 0; i < length - compareStart; i++) { + compareValue = processedYData[i] && keyIndex > -1 ? + processedYData[i][keyIndex] : + processedYData[i]; + if (isNumber(compareValue) && + processedXData[i + compareStart] >= + series.xAxis.min && + compareValue !== 0) { + series.compareValue = compareValue; + break; + } + } + } + return; +}; +// Modify series extremes +addEvent(Series, 'afterGetExtremes', function (e) { + var dataExtremes = e.dataExtremes; + if (this.modifyValue && dataExtremes) { + var extremes = [ + this.modifyValue(dataExtremes.dataMin), + this.modifyValue(dataExtremes.dataMax) + ]; + dataExtremes.dataMin = arrayMin(extremes); + dataExtremes.dataMax = arrayMax(extremes); + } +}); +/** + * Highstock only. Set the compare mode on all series belonging to an Y axis + * after render time. + * + * @see [series.plotOptions.compare](https://api.highcharts.com/highstock/series.plotOptions.compare) + * + * @sample stock/members/axis-setcompare/ + * Set compoare + * + * @function Highcharts.Axis#setCompare + * + * @param {string} [compare] + * The compare mode. Can be one of `null` (default), `"value"` or + * `"percent"`. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or to wait for a later call to + * {@link Chart#redraw}. + */ +Axis.prototype.setCompare = function (compare, redraw) { + if (!this.isXAxis) { + this.series.forEach(function (series) { + series.setCompare(compare); + }); + if (pick(redraw, true)) { + this.chart.redraw(); + } + } +}; +/** + * Extend the tooltip formatter by adding support for the point.change variable + * as well as the changeDecimals option. + * + * @ignore + * @function Highcharts.Point#tooltipFormatter + * + * @param {string} pointFormat + */ +Point.prototype.tooltipFormatter = function (pointFormat) { + var point = this; + var numberFormatter = point.series.chart.numberFormatter; + pointFormat = pointFormat.replace('{point.change}', (point.change > 0 ? '+' : '') + numberFormatter(point.change, pick(point.series.tooltipOptions.changeDecimals, 2))); + return pointTooltipFormatter.apply(this, [pointFormat]); +}; +/* ************************************************************************** * + * End value compare logic * + * ************************************************************************** */ +// Extend the Series prototype to create a separate series clip box. This is +// related to using multiple panes, and a future pane logic should incorporate +// this feature (#2754). +addEvent(Series, 'render', function () { + var chart = this.chart, clipHeight; + // Only do this on not 3d (#2939, #5904) nor polar (#6057) charts, and only + // if the series type handles clipping in the animate method (#2975). + if (!(chart.is3d && chart.is3d()) && + !chart.polar && + this.xAxis && + !this.xAxis.isRadial // Gauge, #6192 + ) { + clipHeight = this.yAxis.len; + // Include xAxis line width (#8031) but only if the Y axis ends on the + // edge of the X axis (#11005). + if (this.xAxis.axisLine) { + var dist = chart.plotTop + chart.plotHeight - + this.yAxis.pos - this.yAxis.len, lineHeightCorrection = Math.floor(this.xAxis.axisLine.strokeWidth() / 2); + if (dist >= 0) { + clipHeight -= Math.max(lineHeightCorrection - dist, 0); + } + } + // First render, initial clip box + if (!this.clipBox && this.animate) { + this.clipBox = merge(chart.clipBox); + this.clipBox.width = this.xAxis.len; + this.clipBox.height = clipHeight; + // On redrawing, resizing etc, update the clip rectangle + } + else if (chart[this.sharedClipKey]) { + // animate in case resize is done during initial animation + chart[this.sharedClipKey].animate({ + width: this.xAxis.len, + height: clipHeight + }); + // also change markers clip animation for consistency + // (marker clip rects should exist only on chart init) + if (chart[this.sharedClipKey + 'm']) { + chart[this.sharedClipKey + 'm'].animate({ + width: this.xAxis.len + }); + } + } + } +}); +addEvent(Chart, 'update', function (e) { + var options = e.options; + // Use case: enabling scrollbar from a disabled state. + // Scrollbar needs to be initialized from a controller, Navigator in this + // case (#6615) + if ('scrollbar' in options && this.navigator) { + merge(true, this.options.scrollbar, options.scrollbar); + this.navigator.update({}, false); + delete options.scrollbar; + } +}); diff --git a/librerias/gantt/code/es-modules/parts/SvgRenderer.js b/librerias/gantt/code/es-modules/parts/SvgRenderer.js new file mode 100644 index 0000000..7d1386f --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/SvgRenderer.js @@ -0,0 +1,2791 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Color from './Color.js'; +var color = Color.parse; +import H from './Globals.js'; +import SVGElement from './SVGElement.js'; +import U from './Utilities.js'; +var addEvent = U.addEvent, attr = U.attr, createElement = U.createElement, css = U.css, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, erase = U.erase, extend = U.extend, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, isString = U.isString, merge = U.merge, objectEach = U.objectEach, pick = U.pick, pInt = U.pInt, removeEvent = U.removeEvent, splat = U.splat, stop = U.stop, uniqueKey = U.uniqueKey; +/** + * The horizontal alignment of an element. + * + * @typedef {"center"|"left"|"right"} Highcharts.AlignValue + */ +/** + * Options to align the element relative to the chart or another box. + * + * @interface Highcharts.AlignObject + */ /** +* Horizontal alignment. Can be one of `left`, `center` and `right`. +* +* @name Highcharts.AlignObject#align +* @type {Highcharts.AlignValue|undefined} +* +* @default left +*/ /** +* Vertical alignment. Can be one of `top`, `middle` and `bottom`. +* +* @name Highcharts.AlignObject#verticalAlign +* @type {Highcharts.VerticalAlignValue|undefined} +* +* @default top +*/ /** +* Horizontal pixel offset from alignment. +* +* @name Highcharts.AlignObject#x +* @type {number|undefined} +* +* @default 0 +*/ /** +* Vertical pixel offset from alignment. +* +* @name Highcharts.AlignObject#y +* @type {number|undefined} +* +* @default 0 +*/ /** +* Use the `transform` attribute with translateX and translateY custom +* attributes to align this elements rather than `x` and `y` attributes. +* +* @name Highcharts.AlignObject#alignByTranslate +* @type {boolean|undefined} +* +* @default false +*/ +/** + * Bounding box of an element. + * + * @interface Highcharts.BBoxObject + * @extends Highcharts.PositionObject + */ /** +* Height of the bounding box. +* +* @name Highcharts.BBoxObject#height +* @type {number} +*/ /** +* Width of the bounding box. +* +* @name Highcharts.BBoxObject#width +* @type {number} +*/ /** +* Horizontal position of the bounding box. +* +* @name Highcharts.BBoxObject#x +* @type {number} +*/ /** +* Vertical position of the bounding box. +* +* @name Highcharts.BBoxObject#y +* @type {number} +*/ +/** + * A clipping rectangle that can be applied to one or more {@link SVGElement} + * instances. It is instanciated with the {@link SVGRenderer#clipRect} function + * and applied with the {@link SVGElement#clip} function. + * + * @example + * var circle = renderer.circle(100, 100, 100) + * .attr({ fill: 'red' }) + * .add(); + * var clipRect = renderer.clipRect(100, 100, 100, 100); + * + * // Leave only the lower right quarter visible + * circle.clip(clipRect); + * + * @typedef {Highcharts.SVGElement} Highcharts.ClipRectElement + */ +/** + * The font metrics. + * + * @interface Highcharts.FontMetricsObject + */ /** +* The baseline relative to the top of the box. +* +* @name Highcharts.FontMetricsObject#b +* @type {number} +*/ /** +* The font size. +* +* @name Highcharts.FontMetricsObject#f +* @type {number} +*/ /** +* The line height. +* +* @name Highcharts.FontMetricsObject#h +* @type {number} +*/ +/** + * An object containing `x` and `y` properties for the position of an element. + * + * @interface Highcharts.PositionObject + */ /** +* X position of the element. +* @name Highcharts.PositionObject#x +* @type {number} +*/ /** +* Y position of the element. +* @name Highcharts.PositionObject#y +* @type {number} +*/ +/** + * A rectangle. + * + * @interface Highcharts.RectangleObject + */ /** +* Height of the rectangle. +* @name Highcharts.RectangleObject#height +* @type {number} +*/ /** +* Width of the rectangle. +* @name Highcharts.RectangleObject#width +* @type {number} +*/ /** +* Horizontal position of the rectangle. +* @name Highcharts.RectangleObject#x +* @type {number} +*/ /** +* Vertical position of the rectangle. +* @name Highcharts.RectangleObject#y +* @type {number} +*/ +/** + * The shadow options. + * + * @interface Highcharts.ShadowOptionsObject + */ /** +* The shadow color. +* @name Highcharts.ShadowOptionsObject#color +* @type {Highcharts.ColorString|undefined} +* @default #000000 +*/ /** +* The horizontal offset from the element. +* +* @name Highcharts.ShadowOptionsObject#offsetX +* @type {number|undefined} +* @default 1 +*/ /** +* The vertical offset from the element. +* @name Highcharts.ShadowOptionsObject#offsetY +* @type {number|undefined} +* @default 1 +*/ /** +* The shadow opacity. +* +* @name Highcharts.ShadowOptionsObject#opacity +* @type {number|undefined} +* @default 0.15 +*/ /** +* The shadow width or distance from the element. +* @name Highcharts.ShadowOptionsObject#width +* @type {number|undefined} +* @default 3 +*/ +/** + * @interface Highcharts.SizeObject + */ /** +* @name Highcharts.SizeObject#height +* @type {number} +*/ /** +* @name Highcharts.SizeObject#width +* @type {number} +*/ +/** + * An object of key-value pairs for SVG attributes. Attributes in Highcharts + * elements for the most parts correspond to SVG, but some are specific to + * Highcharts, like `zIndex`, `rotation`, `rotationOriginX`, + * `rotationOriginY`, `translateX`, `translateY`, `scaleX` and `scaleY`. SVG + * attributes containing a hyphen are _not_ camel-cased, they should be + * quoted to preserve the hyphen. + * + * @example + * { + * 'stroke': '#ff0000', // basic + * 'stroke-width': 2, // hyphenated + * 'rotation': 45 // custom + * 'd': ['M', 10, 10, 'L', 30, 30, 'z'] // path definition, note format + * } + * + * @interface Highcharts.SVGAttributes + */ /** +* @name Highcharts.SVGAttributes#[key:string] +* @type {*} +*/ /** +* @name Highcharts.SVGAttributes#d +* @type {string|Highcharts.SVGPathArray|undefined} +*/ /** +* @name Highcharts.SVGAttributes#fill +* @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined} +*/ /** +* @name Highcharts.SVGAttributes#inverted +* @type {boolean|undefined} +*/ /** +* @name Highcharts.SVGAttributes#matrix +* @type {Array|undefined} +*/ /** +* @name Highcharts.SVGAttributes#rotation +* @type {number|undefined} +*/ /** +* @name Highcharts.SVGAttributes#rotationOriginX +* @type {number|undefined} +*/ /** +* @name Highcharts.SVGAttributes#rotationOriginY +* @type {number|undefined} +*/ /** +* @name Highcharts.SVGAttributes#scaleX +* @type {number|undefined} +*/ /** +* @name Highcharts.SVGAttributes#scaleY +* @type {number|undefined} +*/ /** +* @name Highcharts.SVGAttributes#stroke +* @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined} +*/ /** +* @name Highcharts.SVGAttributes#style +* @type {string|Highcharts.CSSObject|undefined} +*/ /** +* @name Highcharts.SVGAttributes#translateX +* @type {number|undefined} +*/ /** +* @name Highcharts.SVGAttributes#translateY +* @type {number|undefined} +*/ /** +* @name Highcharts.SVGAttributes#zIndex +* @type {number|undefined} +*/ +/** + * Serialized form of an SVG definition, including children. Some key + * property names are reserved: tagName, textContent, and children. + * + * @interface Highcharts.SVGDefinitionObject + */ /** +* @name Highcharts.SVGDefinitionObject#[key:string] +* @type {boolean|number|string|Array|undefined} +*/ /** +* @name Highcharts.SVGDefinitionObject#children +* @type {Array|undefined} +*/ /** +* @name Highcharts.SVGDefinitionObject#tagName +* @type {string|undefined} +*/ /** +* @name Highcharts.SVGDefinitionObject#textContent +* @type {string|undefined} +*/ +/** + * An SVG DOM element. The type is a reference to the regular SVGElement in the + * global scope. + * + * @typedef {globals.GlobalSVGElement} Highcharts.SVGDOMElement + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/SVGElement + */ +/** + * Array of path commands, that will go into the `d` attribute of an SVG + * element. + * + * @typedef {Array} Highcharts.SVGPathArray + */ +/** + * Possible path commands in a SVG path array. + * + * @typedef {string} Highcharts.SVGPathCommand + * @validvalue ["a","c","h","l","m","q","s","t","v","z","A","C","H","L","M","Q","S","T","V","Z"] + */ +/** + * An extendable collection of functions for defining symbol paths. Symbols are + * used internally for point markers, button and label borders and backgrounds, + * or custom shapes. Extendable by adding to {@link SVGRenderer#symbols}. + * + * @interface Highcharts.SymbolDictionary + */ /** +* @name Highcharts.SymbolDictionary#[key:string] +* @type {Function|undefined} +*/ /** +* @name Highcharts.SymbolDictionary#arc +* @type {Function|undefined} +*/ /** +* @name Highcharts.SymbolDictionary#callout +* @type {Function|undefined} +*/ /** +* @name Highcharts.SymbolDictionary#circle +* @type {Function|undefined} +*/ /** +* @name Highcharts.SymbolDictionary#diamond +* @type {Function|undefined} +*/ /** +* @name Highcharts.SymbolDictionary#square +* @type {Function|undefined} +*/ /** +* @name Highcharts.SymbolDictionary#triangle +* @type {Function|undefined} +*/ +/** + * Can be one of `arc`, `callout`, `circle`, `diamond`, `square`, `triangle`, + * and `triangle-down`. Symbols are used internally for point markers, button + * and label borders and backgrounds, or custom shapes. Extendable by adding to + * {@link SVGRenderer#symbols}. + * + * @typedef {"arc"|"callout"|"circle"|"diamond"|"square"|"triangle"|"triangle-down"} Highcharts.SymbolKeyValue + */ +/** + * Additional options, depending on the actual symbol drawn. + * + * @interface Highcharts.SymbolOptionsObject + */ /** +* The anchor X position for the `callout` symbol. This is where the chevron +* points to. +* +* @name Highcharts.SymbolOptionsObject#anchorX +* @type {number|undefined} +*/ /** +* The anchor Y position for the `callout` symbol. This is where the chevron +* points to. +* +* @name Highcharts.SymbolOptionsObject#anchorY +* @type {number|undefined} +*/ /** +* The end angle of an `arc` symbol. +* +* @name Highcharts.SymbolOptionsObject#end +* @type {number|undefined} +*/ /** +* Whether to draw `arc` symbol open or closed. +* +* @name Highcharts.SymbolOptionsObject#open +* @type {boolean|undefined} +*/ /** +* The radius of an `arc` symbol, or the border radius for the `callout` symbol. +* +* @name Highcharts.SymbolOptionsObject#r +* @type {number|undefined} +*/ /** +* The start angle of an `arc` symbol. +* +* @name Highcharts.SymbolOptionsObject#start +* @type {number|undefined} +*/ +/** + * The vertical alignment of an element. + * + * @typedef {"bottom"|"middle"|"top"} Highcharts.VerticalAlignValue + */ +/* eslint-disable no-invalid-this, valid-jsdoc */ +var SVGRenderer, charts = H.charts, deg2rad = H.deg2rad, doc = H.doc, hasTouch = H.hasTouch, isFirefox = H.isFirefox, isMS = H.isMS, isWebKit = H.isWebKit, noop = H.noop, svg = H.svg, SVG_NS = H.SVG_NS, symbolSizes = H.symbolSizes, win = H.win; +/** + * Allows direct access to the Highcharts rendering layer in order to draw + * primitive shapes like circles, rectangles, paths or text directly on a chart, + * or independent from any chart. The SVGRenderer represents a wrapper object + * for SVG in modern browsers. Through the VMLRenderer, part of the `oldie.js` + * module, it also brings vector graphics to IE <= 8. + * + * An existing chart's renderer can be accessed through {@link Chart.renderer}. + * The renderer can also be used completely decoupled from a chart. + * + * @sample highcharts/members/renderer-on-chart + * Annotating a chart programmatically. + * @sample highcharts/members/renderer-basic + * Independent SVG drawing. + * + * @example + * // Use directly without a chart object. + * var renderer = new Highcharts.Renderer(parentNode, 600, 400); + * + * @class + * @name Highcharts.SVGRenderer + * + * @param {Highcharts.HTMLDOMElement} container + * Where to put the SVG in the web page. + * + * @param {number} width + * The width of the SVG. + * + * @param {number} height + * The height of the SVG. + * + * @param {Highcharts.CSSObject} [style] + * The box style, if not in styleMode + * + * @param {boolean} [forExport=false] + * Whether the rendered content is intended for export. + * + * @param {boolean} [allowHTML=true] + * Whether the renderer is allowed to include HTML text, which will be + * projected on top of the SVG. + * + * @param {boolean} [styledMode=false] + * Whether the renderer belongs to a chart that is in styled mode. + * If it does, it will avoid setting presentational attributes in + * some cases, but not when set explicitly through `.attr` and `.css` + * etc. + */ +SVGRenderer = H.SVGRenderer = function () { + this.init.apply(this, arguments); +}; +extend(SVGRenderer.prototype, /** @lends Highcharts.SVGRenderer.prototype */ { + /** + * A pointer to the renderer's associated Element class. The VMLRenderer + * will have a pointer to VMLElement here. + * + * @name Highcharts.SVGRenderer#Element + * @type {Highcharts.SVGElement} + */ + Element: SVGElement, + SVG_NS: SVG_NS, + /** + * Initialize the SVGRenderer. Overridable initializer function that takes + * the same parameters as the constructor. + * + * @function Highcharts.SVGRenderer#init + * + * @param {Highcharts.HTMLDOMElement} container + * Where to put the SVG in the web page. + * + * @param {number} width + * The width of the SVG. + * + * @param {number} height + * The height of the SVG. + * + * @param {Highcharts.CSSObject} [style] + * The box style, if not in styleMode + * + * @param {boolean} [forExport=false] + * Whether the rendered content is intended for export. + * + * @param {boolean} [allowHTML=true] + * Whether the renderer is allowed to include HTML text, which will + * be projected on top of the SVG. + * + * @param {boolean} [styledMode=false] + * Whether the renderer belongs to a chart that is in styled mode. + * If it does, it will avoid setting presentational attributes in + * some cases, but not when set explicitly through `.attr` and `.css` + * etc. + * + * @return {void} + */ + init: function (container, width, height, style, forExport, allowHTML, styledMode) { + var renderer = this, boxWrapper, element, desc; + boxWrapper = renderer.createElement('svg') + .attr({ + version: '1.1', + 'class': 'highcharts-root' + }); + if (!styledMode) { + boxWrapper.css(this.getStyle(style)); + } + element = boxWrapper.element; + container.appendChild(element); + // Always use ltr on the container, otherwise text-anchor will be + // flipped and text appear outside labels, buttons, tooltip etc (#3482) + attr(container, 'dir', 'ltr'); + // For browsers other than IE, add the namespace attribute (#1978) + if (container.innerHTML.indexOf('xmlns') === -1) { + attr(element, 'xmlns', this.SVG_NS); + } + // object properties + renderer.isSVG = true; + /** + * The root `svg` node of the renderer. + * + * @name Highcharts.SVGRenderer#box + * @type {Highcharts.SVGDOMElement} + */ + this.box = element; + /** + * The wrapper for the root `svg` node of the renderer. + * + * @name Highcharts.SVGRenderer#boxWrapper + * @type {Highcharts.SVGElement} + */ + this.boxWrapper = boxWrapper; + renderer.alignedObjects = []; + /** + * Page url used for internal references. + * + * @private + * @name Highcharts.SVGRenderer#url + * @type {string} + */ + // #24, #672, #1070 + this.url = ((isFirefox || isWebKit) && + doc.getElementsByTagName('base').length) ? + win.location.href + .split('#')[0] // remove the hash + .replace(/<[^>]*>/g, '') // wing cut HTML + // escape parantheses and quotes + .replace(/([\('\)])/g, '\\$1') + // replace spaces (needed for Safari only) + .replace(/ /g, '%20') : + ''; + // Add description + desc = this.createElement('desc').add(); + desc.element.appendChild(doc.createTextNode('Created with Highcharts 8.1.0')); + /** + * A pointer to the `defs` node of the root SVG. + * + * @name Highcharts.SVGRenderer#defs + * @type {Highcharts.SVGElement} + */ + renderer.defs = this.createElement('defs').add(); + renderer.allowHTML = allowHTML; + renderer.forExport = forExport; + renderer.styledMode = styledMode; + renderer.gradients = {}; // Object where gradient SvgElements are stored + renderer.cache = {}; // Cache for numerical bounding boxes + renderer.cacheKeys = []; + renderer.imgCount = 0; + renderer.setSize(width, height, false); + // Issue 110 workaround: + // In Firefox, if a div is positioned by percentage, its pixel position + // may land between pixels. The container itself doesn't display this, + // but an SVG element inside this container will be drawn at subpixel + // precision. In order to draw sharp lines, this must be compensated + // for. This doesn't seem to work inside iframes though (like in + // jsFiddle). + var subPixelFix, rect; + if (isFirefox && container.getBoundingClientRect) { + subPixelFix = function () { + css(container, { left: 0, top: 0 }); + rect = container.getBoundingClientRect(); + css(container, { + left: (Math.ceil(rect.left) - rect.left) + 'px', + top: (Math.ceil(rect.top) - rect.top) + 'px' + }); + }; + // run the fix now + subPixelFix(); + // run it on resize + renderer.unSubPixelFix = addEvent(win, 'resize', subPixelFix); + } + }, + /** + * General method for adding a definition to the SVG `defs` tag. Can be used + * for gradients, fills, filters etc. Styled mode only. A hook for adding + * general definitions to the SVG's defs tag. Definitions can be referenced + * from the CSS by its `id`. Read more in + * [gradients, shadows and patterns](https://www.highcharts.com/docs/chart-design-and-style/gradients-shadows-and-patterns). + * Styled mode only. + * + * @function Highcharts.SVGRenderer#definition + * + * @param {Highcharts.SVGDefinitionObject} def + * A serialized form of an SVG definition, including children. + * + * @return {Highcharts.SVGElement} + * The inserted node. + */ + definition: function (def) { + var ren = this; + /** + * @private + * @param {Highcharts.SVGDefinitionObject} config - SVG definition + * @param {Highcharts.SVGElement} [parent] - parent node + */ + function recurse(config, parent) { + var ret; + splat(config).forEach(function (item) { + var node = ren.createElement(item.tagName), attr = {}; + // Set attributes + objectEach(item, function (val, key) { + if (key !== 'tagName' && + key !== 'children' && + key !== 'textContent') { + attr[key] = val; + } + }); + node.attr(attr); + // Add to the tree + node.add(parent || ren.defs); + // Add text content + if (item.textContent) { + node.element.appendChild(doc.createTextNode(item.textContent)); + } + // Recurse + recurse(item.children || [], node); + ret = node; + }); + // Return last node added (on top level it's the only one) + return ret; + } + return recurse(def); + }, + /** + * Get the global style setting for the renderer. + * + * @private + * @function Highcharts.SVGRenderer#getStyle + * + * @param {Highcharts.CSSObject} style + * Style settings. + * + * @return {Highcharts.CSSObject} + * The style settings mixed with defaults. + */ + getStyle: function (style) { + this.style = extend({ + fontFamily: '"Lucida Grande", "Lucida Sans Unicode", ' + + 'Arial, Helvetica, sans-serif', + fontSize: '12px' + }, style); + return this.style; + }, + /** + * Apply the global style on the renderer, mixed with the default styles. + * + * @function Highcharts.SVGRenderer#setStyle + * + * @param {Highcharts.CSSObject} style + * CSS to apply. + */ + setStyle: function (style) { + this.boxWrapper.css(this.getStyle(style)); + }, + /** + * Detect whether the renderer is hidden. This happens when one of the + * parent elements has `display: none`. Used internally to detect when we + * needto render preliminarily in another div to get the text bounding boxes + * right. + * + * @function Highcharts.SVGRenderer#isHidden + * + * @return {boolean} + * True if it is hidden. + */ + isHidden: function () { + return !this.boxWrapper.getBBox().width; + }, + /** + * Destroys the renderer and its allocated members. + * + * @function Highcharts.SVGRenderer#destroy + * + * @return {null} + */ + destroy: function () { + var renderer = this, rendererDefs = renderer.defs; + renderer.box = null; + renderer.boxWrapper = renderer.boxWrapper.destroy(); + // Call destroy on all gradient elements + destroyObjectProperties(renderer.gradients || {}); + renderer.gradients = null; + // Defs are null in VMLRenderer + // Otherwise, destroy them here. + if (rendererDefs) { + renderer.defs = rendererDefs.destroy(); + } + // Remove sub pixel fix handler (#982) + if (renderer.unSubPixelFix) { + renderer.unSubPixelFix(); + } + renderer.alignedObjects = null; + return null; + }, + /** + * Create a wrapper for an SVG element. Serves as a factory for + * {@link SVGElement}, but this function is itself mostly called from + * primitive factories like {@link SVGRenderer#path}, {@link + * SVGRenderer#rect} or {@link SVGRenderer#text}. + * + * @function Highcharts.SVGRenderer#createElement + * + * @param {string} nodeName + * The node name, for example `rect`, `g` etc. + * + * @return {Highcharts.SVGElement} + * The generated SVGElement. + */ + createElement: function (nodeName) { + var wrapper = new this.Element(); + wrapper.init(this, nodeName); + return wrapper; + }, + /** + * Dummy function for plugins, called every time the renderer is updated. + * Prior to Highcharts 5, this was used for the canvg renderer. + * + * @deprecated + * @function Highcharts.SVGRenderer#draw + */ + draw: noop, + /** + * Get converted radial gradient attributes according to the radial + * reference. Used internally from the {@link SVGElement#colorGradient} + * function. + * + * @private + * @function Highcharts.SVGRenderer#getRadialAttr + * + * @param {Array} radialReference + * + * @param {Highcharts.SVGAttributes} gradAttr + * + * @return {Highcharts.SVGAttributes} + */ + getRadialAttr: function (radialReference, gradAttr) { + return { + cx: (radialReference[0] - radialReference[2] / 2) + + gradAttr.cx * radialReference[2], + cy: (radialReference[1] - radialReference[2] / 2) + + gradAttr.cy * radialReference[2], + r: gradAttr.r * radialReference[2] + }; + }, + /** + * Truncate the text node contents to a given length. Used when the css + * width is set. If the `textOverflow` is `ellipsis`, the text is truncated + * character by character to the given length. If not, the text is + * word-wrapped line by line. + * + * @private + * @function Highcharts.SVGRenderer#truncate + * + * @param {Highcharts.SVGElement} wrapper + * + * @param {Highcharts.HTMLDOMElement} tspan + * + * @param {string|undefined} text + * + * @param {Array|undefined} words + * + * @param {number} startAt + * + * @param {number} width + * + * @param {Function} getString + * + * @return {boolean} + * True if tspan is too long. + */ + truncate: function (wrapper, tspan, text, words, startAt, width, getString) { + var renderer = this, rotation = wrapper.rotation, str, + // Word wrap can not be truncated to shorter than one word, ellipsis + // text can be completely blank. + minIndex = words ? 1 : 0, maxIndex = (text || words).length, currentIndex = maxIndex, + // Cache the lengths to avoid checking the same twice + lengths = [], updateTSpan = function (s) { + if (tspan.firstChild) { + tspan.removeChild(tspan.firstChild); + } + if (s) { + tspan.appendChild(doc.createTextNode(s)); + } + }, getSubStringLength = function (charEnd, concatenatedEnd) { + // charEnd is useed when finding the character-by-character + // break for ellipsis, concatenatedEnd is used for word-by-word + // break for word wrapping. + var end = concatenatedEnd || charEnd; + if (typeof lengths[end] === 'undefined') { + // Modern browsers + if (tspan.getSubStringLength) { + // Fails with DOM exception on unit-tests/legend/members + // of unknown reason. Desired width is 0, text content + // is "5" and end is 1. + try { + lengths[end] = startAt + + tspan.getSubStringLength(0, words ? end + 1 : end); + } + catch (e) { + ''; + } + // Legacy + } + else if (renderer.getSpanWidth) { // #9058 jsdom + updateTSpan(getString(text || words, charEnd)); + lengths[end] = startAt + + renderer.getSpanWidth(wrapper, tspan); + } + } + return lengths[end]; + }, actualWidth, truncated; + wrapper.rotation = 0; // discard rotation when computing box + actualWidth = getSubStringLength(tspan.textContent.length); + truncated = startAt + actualWidth > width; + if (truncated) { + // Do a binary search for the index where to truncate the text + while (minIndex <= maxIndex) { + currentIndex = Math.ceil((minIndex + maxIndex) / 2); + // When checking words for word-wrap, we need to build the + // string and measure the subStringLength at the concatenated + // word length. + if (words) { + str = getString(words, currentIndex); + } + actualWidth = getSubStringLength(currentIndex, str && str.length - 1); + if (minIndex === maxIndex) { + // Complete + minIndex = maxIndex + 1; + } + else if (actualWidth > width) { + // Too large. Set max index to current. + maxIndex = currentIndex - 1; + } + else { + // Within width. Set min index to current. + minIndex = currentIndex; + } + } + // If max index was 0 it means the shortest possible text was also + // too large. For ellipsis that means only the ellipsis, while for + // word wrap it means the whole first word. + if (maxIndex === 0) { + // Remove ellipsis + updateTSpan(''); + // If the new text length is one less than the original, we don't + // need the ellipsis + } + else if (!(text && maxIndex === text.length - 1)) { + updateTSpan(str || getString(text || words, currentIndex)); + } + } + // When doing line wrapping, prepare for the next line by removing the + // items from this line. + if (words) { + words.splice(0, currentIndex); + } + wrapper.actualWidth = actualWidth; + wrapper.rotation = rotation; // Apply rotation again. + return truncated; + }, + /** + * A collection of characters mapped to HTML entities. When `useHTML` on an + * element is true, these entities will be rendered correctly by HTML. In + * the SVG pseudo-HTML, they need to be unescaped back to simple characters, + * so for example `<` will render as `<`. + * + * @example + * // Add support for unescaping quotes + * Highcharts.SVGRenderer.prototype.escapes['"'] = '"'; + * + * @name Highcharts.SVGRenderer#escapes + * @type {Highcharts.Dictionary} + */ + escapes: { + '&': '&', + '<': '<', + '>': '>', + "'": ''', + '"': '"' + }, + /** + * Parse a simple HTML string into SVG tspans. Called internally when text + * is set on an SVGElement. The function supports a subset of HTML tags, CSS + * text features like `width`, `text-overflow`, `white-space`, and also + * attributes like `href` and `style`. + * + * @private + * @function Highcharts.SVGRenderer#buildText + * + * @param {Highcharts.SVGElement} wrapper + * The parent SVGElement. + * + * @return {void} + */ + buildText: function (wrapper) { + var textNode = wrapper.element, renderer = this, forExport = renderer.forExport, textStr = pick(wrapper.textStr, '').toString(), hasMarkup = textStr.indexOf('<') !== -1, lines, childNodes = textNode.childNodes, truncated, parentX = attr(textNode, 'x'), textStyles = wrapper.styles, width = wrapper.textWidth, textLineHeight = textStyles && textStyles.lineHeight, textOutline = textStyles && textStyles.textOutline, ellipsis = textStyles && textStyles.textOverflow === 'ellipsis', noWrap = textStyles && textStyles.whiteSpace === 'nowrap', fontSize = textStyles && textStyles.fontSize, textCache, isSubsequentLine, i = childNodes.length, tempParent = width && !wrapper.added && this.box, getLineHeight = function (tspan) { + var fontSizeStyle; + if (!renderer.styledMode) { + fontSizeStyle = + /(px|em)$/.test(tspan && tspan.style.fontSize) ? + tspan.style.fontSize : + (fontSize || renderer.style.fontSize || 12); + } + return textLineHeight ? + pInt(textLineHeight) : + renderer.fontMetrics(fontSizeStyle, + // Get the computed size from parent if not explicit + (tspan.getAttribute('style') ? tspan : textNode)).h; + }, unescapeEntities = function (inputStr, except) { + objectEach(renderer.escapes, function (value, key) { + if (!except || except.indexOf(value) === -1) { + inputStr = inputStr.toString().replace(new RegExp(value, 'g'), key); + } + }); + return inputStr; + }, parseAttribute = function (s, attr) { + var start, delimiter; + start = s.indexOf('<'); + s = s.substring(start, s.indexOf('>') - start); + start = s.indexOf(attr + '='); + if (start !== -1) { + start = start + attr.length + 1; + delimiter = s.charAt(start); + if (delimiter === '"' || delimiter === "'") { // eslint-disable-line quotes + s = s.substring(start + 1); + return s.substring(0, s.indexOf(delimiter)); + } + } + }; + var regexMatchBreaks = //g; + // The buildText code is quite heavy, so if we're not changing something + // that affects the text, skip it (#6113). + textCache = [ + textStr, + ellipsis, + noWrap, + textLineHeight, + textOutline, + fontSize, + width + ].join(','); + if (textCache === wrapper.textCache) { + return; + } + wrapper.textCache = textCache; + // Remove old text + while (i--) { + textNode.removeChild(childNodes[i]); + } + // Skip tspans, add text directly to text node. The forceTSpan is a hook + // used in text outline hack. + if (!hasMarkup && + !textOutline && + !ellipsis && + !width && + (textStr.indexOf(' ') === -1 || + (noWrap && !regexMatchBreaks.test(textStr)))) { + textNode.appendChild(doc.createTextNode(unescapeEntities(textStr))); + // Complex strings, add more logic + } + else { + if (tempParent) { + // attach it to the DOM to read offset width + tempParent.appendChild(textNode); + } + if (hasMarkup) { + lines = renderer.styledMode ? (textStr + .replace(/<(b|strong)>/g, '') + .replace(/<(i|em)>/g, '')) : (textStr + .replace(/<(b|strong)>/g, '') + .replace(/<(i|em)>/g, '')); + lines = lines + .replace(//g, '') + .split(regexMatchBreaks); + } + else { + lines = [textStr]; + } + // Trim empty lines (#5261) + lines = lines.filter(function (line) { + return line !== ''; + }); + // build the lines + lines.forEach(function (line, lineNo) { + var spans, spanNo = 0, lineLength = 0; + line = line + // Trim to prevent useless/costly process on the spaces + // (#5258) + .replace(/^\s+|\s+$/g, '') + .replace(//g, '|||'); + spans = line.split('|||'); + spans.forEach(function buildTextSpans(span) { + if (span !== '' || spans.length === 1) { + var attributes = {}, tspan = doc.createElementNS(renderer.SVG_NS, 'tspan'), classAttribute, styleAttribute, // #390 + hrefAttribute; + classAttribute = parseAttribute(span, 'class'); + if (classAttribute) { + attr(tspan, 'class', classAttribute); + } + styleAttribute = parseAttribute(span, 'style'); + if (styleAttribute) { + styleAttribute = styleAttribute.replace(/(;| |^)color([ :])/, '$1fill$2'); + attr(tspan, 'style', styleAttribute); + } + // Not for export - #1529 + hrefAttribute = parseAttribute(span, 'href'); + if (hrefAttribute && !forExport) { + attr(tspan, 'onclick', 'location.href=\"' + hrefAttribute + '\"'); + attr(tspan, 'class', 'highcharts-anchor'); + if (!renderer.styledMode) { + css(tspan, { cursor: 'pointer' }); + } + } + // Strip away unsupported HTML tags (#7126) + span = unescapeEntities(span.replace(/<[a-zA-Z\/](.|\n)*?>/g, '') || ' '); + // Nested tags aren't supported, and cause crash in + // Safari (#1596) + if (span !== ' ') { + // add the text node + tspan.appendChild(doc.createTextNode(span)); + // First span in a line, align it to the left + if (!spanNo) { + if (lineNo && parentX !== null) { + attributes.x = parentX; + } + } + else { + attributes.dx = 0; // #16 + } + // add attributes + attr(tspan, attributes); + // Append it + textNode.appendChild(tspan); + // first span on subsequent line, add the line + // height + if (!spanNo && isSubsequentLine) { + // allow getting the right offset height in + // exporting in IE + if (!svg && forExport) { + css(tspan, { display: 'block' }); + } + // Set the line height based on the font size of + // either the text element or the tspan element + attr(tspan, 'dy', getLineHeight(tspan)); + } + // Check width and apply soft breaks or ellipsis + if (width) { + var words = span.replace(/([^\^])-/g, '$1- ').split(' '), // #1273 + hasWhiteSpace = !noWrap && (spans.length > 1 || + lineNo || + words.length > 1), wrapLineNo = 0, dy = getLineHeight(tspan); + if (ellipsis) { + truncated = renderer.truncate(wrapper, tspan, span, void 0, 0, + // Target width + Math.max(0, + // Substract the font face to make + // room for the ellipsis itself + width - parseInt(fontSize || 12, 10)), + // Build the text to test for + function (text, currentIndex) { + return text.substring(0, currentIndex) + '\u2026'; + }); + } + else if (hasWhiteSpace) { + while (words.length) { + // For subsequent lines, create tspans + // with the same style attributes as the + // parent text node. + if (words.length && + !noWrap && + wrapLineNo > 0) { + tspan = doc.createElementNS(SVG_NS, 'tspan'); + attr(tspan, { + dy: dy, + x: parentX + }); + if (styleAttribute) { // #390 + attr(tspan, 'style', styleAttribute); + } + // Start by appending the full + // remaining text + tspan.appendChild(doc.createTextNode(words.join(' ') + .replace(/- /g, '-'))); + textNode.appendChild(tspan); + } + // For each line, truncate the remaining + // words into the line length. + renderer.truncate(wrapper, tspan, null, words, wrapLineNo === 0 ? lineLength : 0, width, + // Build the text to test for + function (text, currentIndex) { + return words + .slice(0, currentIndex) + .join(' ') + .replace(/- /g, '-'); + }); + lineLength = wrapper.actualWidth; + wrapLineNo++; + } + } + } + spanNo++; + } + } + }); + // To avoid beginning lines that doesn't add to the textNode + // (#6144) + isSubsequentLine = (isSubsequentLine || + textNode.childNodes.length); + }); + if (ellipsis && truncated) { + wrapper.attr('title', unescapeEntities(wrapper.textStr, ['<', '>']) // #7179 + ); + } + if (tempParent) { + tempParent.removeChild(textNode); + } + // Apply the text outline + if (textOutline && wrapper.applyTextOutline) { + wrapper.applyTextOutline(textOutline); + } + } + }, + /** + * Returns white for dark colors and black for bright colors. + * + * @function Highcharts.SVGRenderer#getContrast + * + * @param {Highcharts.ColorString} rgba + * The color to get the contrast for. + * + * @return {Highcharts.ColorString} + * The contrast color, either `#000000` or `#FFFFFF`. + */ + getContrast: function (rgba) { + rgba = color(rgba).rgba; + // The threshold may be discussed. Here's a proposal for adding + // different weight to the color channels (#6216) + rgba[0] *= 1; // red + rgba[1] *= 1.2; // green + rgba[2] *= 0.5; // blue + return rgba[0] + rgba[1] + rgba[2] > + 1.8 * 255 ? + '#000000' : + '#FFFFFF'; + }, + /** + * Create a button with preset states. + * + * @function Highcharts.SVGRenderer#button + * + * @param {string} text + * The text or HTML to draw. + * + * @param {number} x + * The x position of the button's left side. + * + * @param {number} y + * The y position of the button's top side. + * + * @param {Highcharts.EventCallbackFunction} callback + * The function to execute on button click or touch. + * + * @param {Highcharts.SVGAttributes} [normalState] + * SVG attributes for the normal state. + * + * @param {Highcharts.SVGAttributes} [hoverState] + * SVG attributes for the hover state. + * + * @param {Highcharts.SVGAttributes} [pressedState] + * SVG attributes for the pressed state. + * + * @param {Highcharts.SVGAttributes} [disabledState] + * SVG attributes for the disabled state. + * + * @param {Highcharts.SymbolKeyValue} [shape=rect] + * The shape type. + * + * @param {boolean} [useHTML=false] + * Wether to use HTML to render the label. + * + * @return {Highcharts.SVGElement} + * The button element. + */ + button: function (text, x, y, callback, normalState, hoverState, pressedState, disabledState, shape, useHTML) { + var label = this.label(text, x, y, shape, void 0, void 0, useHTML, void 0, 'button'), curState = 0, styledMode = this.styledMode; + // Default, non-stylable attributes + label.attr(merge({ padding: 8, r: 2 }, normalState)); + if (!styledMode) { + // Presentational + var normalStyle, hoverStyle, pressedStyle, disabledStyle; + // Normal state - prepare the attributes + normalState = merge({ + fill: '#f7f7f7', + stroke: '#cccccc', + 'stroke-width': 1, + style: { + color: '#333333', + cursor: 'pointer', + fontWeight: 'normal' + } + }, normalState); + normalStyle = normalState.style; + delete normalState.style; + // Hover state + hoverState = merge(normalState, { + fill: '#e6e6e6' + }, hoverState); + hoverStyle = hoverState.style; + delete hoverState.style; + // Pressed state + pressedState = merge(normalState, { + fill: '#e6ebf5', + style: { + color: '#000000', + fontWeight: 'bold' + } + }, pressedState); + pressedStyle = pressedState.style; + delete pressedState.style; + // Disabled state + disabledState = merge(normalState, { + style: { + color: '#cccccc' + } + }, disabledState); + disabledStyle = disabledState.style; + delete disabledState.style; + } + // Add the events. IE9 and IE10 need mouseover and mouseout to funciton + // (#667). + addEvent(label.element, isMS ? 'mouseover' : 'mouseenter', function () { + if (curState !== 3) { + label.setState(1); + } + }); + addEvent(label.element, isMS ? 'mouseout' : 'mouseleave', function () { + if (curState !== 3) { + label.setState(curState); + } + }); + label.setState = function (state) { + // Hover state is temporary, don't record it + if (state !== 1) { + label.state = curState = state; + } + // Update visuals + label + .removeClass(/highcharts-button-(normal|hover|pressed|disabled)/) + .addClass('highcharts-button-' + + ['normal', 'hover', 'pressed', 'disabled'][state || 0]); + if (!styledMode) { + label + .attr([ + normalState, + hoverState, + pressedState, + disabledState + ][state || 0]) + .css([ + normalStyle, + hoverStyle, + pressedStyle, + disabledStyle + ][state || 0]); + } + }; + // Presentational attributes + if (!styledMode) { + label + .attr(normalState) + .css(extend({ cursor: 'default' }, normalStyle)); + } + return label + .on('click', function (e) { + if (curState !== 3) { + callback.call(label, e); + } + }); + }, + /** + * Make a straight line crisper by not spilling out to neighbour pixels. + * + * @function Highcharts.SVGRenderer#crispLine + * + * @param {Highcharts.SVGPathArray} points + * The original points on the format `[['M', 0, 0], ['L', 100, 0]]`. + * + * @param {number} width + * The width of the line. + * + * @param {string} roundingFunction + * The rounding function name on the `Math` object, can be one of + * `round`, `floor` or `ceil`. + * + * @return {Highcharts.SVGPathArray} + * The original points array, but modified to render crisply. + */ + crispLine: function (points, width, roundingFunction) { + if (roundingFunction === void 0) { roundingFunction = 'round'; } + var start = points[0]; + var end = points[1]; + // Normalize to a crisp line + if (start[1] === end[1]) { + // Substract due to #1129. Now bottom and left axis gridlines behave + // the same. + start[1] = end[1] = + Math[roundingFunction](start[1]) - (width % 2 / 2); + } + if (start[2] === end[2]) { + start[2] = end[2] = + Math[roundingFunction](start[2]) + (width % 2 / 2); + } + return points; + }, + /** + * Draw a path, wraps the SVG `path` element. + * + * @sample highcharts/members/renderer-path-on-chart/ + * Draw a path in a chart + * @sample highcharts/members/renderer-path/ + * Draw a path independent from a chart + * + * @example + * var path = renderer.path(['M', 10, 10, 'L', 30, 30, 'z']) + * .attr({ stroke: '#ff00ff' }) + * .add(); + * + * @function Highcharts.SVGRenderer#path + * + * @param {Highcharts.SVGPathArray} [path] + * An SVG path definition in array form. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + * + */ /** + * Draw a path, wraps the SVG `path` element. + * + * @function Highcharts.SVGRenderer#path + * + * @param {Highcharts.SVGAttributes} [attribs] + * The initial attributes. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ + path: function (path) { + var attribs = (this.styledMode ? {} : { + fill: 'none' + }); + if (isArray(path)) { + attribs.d = path; + } + else if (isObject(path)) { // attributes + extend(attribs, path); + } + return this.createElement('path').attr(attribs); + }, + /** + * Draw a circle, wraps the SVG `circle` element. + * + * @sample highcharts/members/renderer-circle/ + * Drawing a circle + * + * @function Highcharts.SVGRenderer#circle + * + * @param {number} [x] + * The center x position. + * + * @param {number} [y] + * The center y position. + * + * @param {number} [r] + * The radius. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ /** + * Draw a circle, wraps the SVG `circle` element. + * + * @function Highcharts.SVGRenderer#circle + * + * @param {Highcharts.SVGAttributes} [attribs] + * The initial attributes. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ + circle: function (x, y, r) { + var attribs = (isObject(x) ? + x : + typeof x === 'undefined' ? {} : { x: x, y: y, r: r }), wrapper = this.createElement('circle'); + // Setting x or y translates to cx and cy + wrapper.xSetter = wrapper.ySetter = function (value, key, element) { + element.setAttribute('c' + key, value); + }; + return wrapper.attr(attribs); + }, + /** + * Draw and return an arc. + * + * @sample highcharts/members/renderer-arc/ + * Drawing an arc + * + * @function Highcharts.SVGRenderer#arc + * + * @param {number} [x=0] + * Center X position. + * + * @param {number} [y=0] + * Center Y position. + * + * @param {number} [r=0] + * The outer radius' of the arc. + * + * @param {number} [innerR=0] + * Inner radius like used in donut charts. + * + * @param {number} [start=0] + * The starting angle of the arc in radians, where 0 is to the right + * and `-Math.PI/2` is up. + * + * @param {number} [end=0] + * The ending angle of the arc in radians, where 0 is to the right + * and `-Math.PI/2` is up. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ /** + * Draw and return an arc. Overloaded function that takes arguments object. + * + * @function Highcharts.SVGRenderer#arc + * + * @param {Highcharts.SVGAttributes} attribs + * Initial SVG attributes. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ + arc: function (x, y, r, innerR, start, end) { + var arc, options; + if (isObject(x)) { + options = x; + y = options.y; + r = options.r; + innerR = options.innerR; + start = options.start; + end = options.end; + x = options.x; + } + else { + options = { + innerR: innerR, + start: start, + end: end + }; + } + // Arcs are defined as symbols for the ability to set + // attributes in attr and animate + arc = this.symbol('arc', x, y, r, r, options); + arc.r = r; // #959 + return arc; + }, + /** + * Draw and return a rectangle. + * + * @function Highcharts.SVGRenderer#rect + * + * @param {number} [x] + * Left position. + * + * @param {number} [y] + * Top position. + * + * @param {number} [width] + * Width of the rectangle. + * + * @param {number} [height] + * Height of the rectangle. + * + * @param {number} [r] + * Border corner radius. + * + * @param {number} [strokeWidth] + * A stroke width can be supplied to allow crisp drawing. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ /** + * Draw and return a rectangle. + * + * @sample highcharts/members/renderer-rect-on-chart/ + * Draw a rectangle in a chart + * @sample highcharts/members/renderer-rect/ + * Draw a rectangle independent from a chart + * + * @function Highcharts.SVGRenderer#rect + * + * @param {Highcharts.SVGAttributes} [attributes] + * General SVG attributes for the rectangle. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ + rect: function (x, y, width, height, r, strokeWidth) { + r = isObject(x) ? x.r : r; + var wrapper = this.createElement('rect'), attribs = isObject(x) ? + x : + typeof x === 'undefined' ? + {} : + { + x: x, + y: y, + width: Math.max(width, 0), + height: Math.max(height, 0) + }; + if (!this.styledMode) { + if (typeof strokeWidth !== 'undefined') { + attribs.strokeWidth = strokeWidth; + attribs = wrapper.crisp(attribs); + } + attribs.fill = 'none'; + } + if (r) { + attribs.r = r; + } + wrapper.rSetter = function (value, key, element) { + wrapper.r = value; + attr(element, { + rx: value, + ry: value + }); + }; + wrapper.rGetter = function () { + return wrapper.r; + }; + return wrapper.attr(attribs); + }, + /** + * Resize the {@link SVGRenderer#box} and re-align all aligned child + * elements. + * + * @sample highcharts/members/renderer-g/ + * Show and hide grouped objects + * + * @function Highcharts.SVGRenderer#setSize + * + * @param {number} width + * The new pixel width. + * + * @param {number} height + * The new pixel height. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animate=true] + * Whether and how to animate. + * + * @return {void} + */ + setSize: function (width, height, animate) { + var renderer = this, alignedObjects = renderer.alignedObjects, i = alignedObjects.length; + renderer.width = width; + renderer.height = height; + renderer.boxWrapper.animate({ + width: width, + height: height + }, { + step: function () { + this.attr({ + viewBox: '0 0 ' + this.attr('width') + ' ' + + this.attr('height') + }); + }, + duration: pick(animate, true) ? void 0 : 0 + }); + while (i--) { + alignedObjects[i].align(); + } + }, + /** + * Create and return an svg group element. Child + * {@link Highcharts.SVGElement} objects are added to the group by using the + * group as the first parameter in {@link Highcharts.SVGElement#add|add()}. + * + * @function Highcharts.SVGRenderer#g + * + * @param {string} [name] + * The group will be given a class name of `highcharts-{name}`. This + * can be used for styling and scripting. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ + g: function (name) { + var elem = this.createElement('g'); + return name ? + elem.attr({ 'class': 'highcharts-' + name }) : + elem; + }, + /** + * Display an image. + * + * @sample highcharts/members/renderer-image-on-chart/ + * Add an image in a chart + * @sample highcharts/members/renderer-image/ + * Add an image independent of a chart + * + * @function Highcharts.SVGRenderer#image + * + * @param {string} src + * The image source. + * + * @param {number} [x] + * The X position. + * + * @param {number} [y] + * The Y position. + * + * @param {number} [width] + * The image width. If omitted, it defaults to the image file width. + * + * @param {number} [height] + * The image height. If omitted it defaults to the image file + * height. + * + * @param {Function} [onload] + * Event handler for image load. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ + image: function (src, x, y, width, height, onload) { + var attribs = { preserveAspectRatio: 'none' }, elemWrapper, dummy, setSVGImageSource = function (el, src) { + // Set the href in the xlink namespace + if (el.setAttributeNS) { + el.setAttributeNS('http://www.w3.org/1999/xlink', 'href', src); + } + else { + // could be exporting in IE + // using href throws "not supported" in ie7 and under, + // requries regex shim to fix later + el.setAttribute('hc-svg-href', src); + } + }, onDummyLoad = function (e) { + setSVGImageSource(elemWrapper.element, src); + onload.call(elemWrapper, e); + }; + // optional properties + if (arguments.length > 1) { + extend(attribs, { + x: x, + y: y, + width: width, + height: height + }); + } + elemWrapper = this.createElement('image').attr(attribs); + // Add load event if supplied + if (onload) { + // We have to use a dummy HTML image since IE support for SVG image + // load events is very buggy. First set a transparent src, wait for + // dummy to load, and then add the real src to the SVG image. + setSVGImageSource(elemWrapper.element, 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==' /* eslint-disable-line */); + dummy = new win.Image(); + addEvent(dummy, 'load', onDummyLoad); + dummy.src = src; + if (dummy.complete) { + onDummyLoad({}); + } + } + else { + setSVGImageSource(elemWrapper.element, src); + } + return elemWrapper; + }, + /** + * Draw a symbol out of pre-defined shape paths from + * {@link SVGRenderer#symbols}. + * It is used in Highcharts for point makers, which cake a `symbol` option, + * and label and button backgrounds like in the tooltip and stock flags. + * + * @function Highcharts.SVGRenderer#symbol + * + * @param {string} symbol + * The symbol name. + * + * @param {number} [x] + * The X coordinate for the top left position. + * + * @param {number} [y] + * The Y coordinate for the top left position. + * + * @param {number} [width] + * The pixel width. + * + * @param {number} [height] + * The pixel height. + * + * @param {Highcharts.SymbolOptionsObject} [options] + * Additional options, depending on the actual symbol drawn. + * + * @return {Highcharts.SVGElement} + */ + symbol: function (symbol, x, y, width, height, options) { + var ren = this, obj, imageRegex = /^url\((.*?)\)$/, isImage = imageRegex.test(symbol), sym = (!isImage && (this.symbols[symbol] ? symbol : 'circle')), + // get the symbol definition function + symbolFn = (sym && this.symbols[sym]), path, imageSrc, centerImage; + if (symbolFn) { + // Check if there's a path defined for this symbol + if (typeof x === 'number') { + path = symbolFn.call(this.symbols, Math.round(x || 0), Math.round(y || 0), width, height, options); + } + obj = this.path(path); + if (!ren.styledMode) { + obj.attr('fill', 'none'); + } + // expando properties for use in animate and attr + extend(obj, { + symbolName: sym, + x: x, + y: y, + width: width, + height: height + }); + if (options) { + extend(obj, options); + } + // Image symbols + } + else if (isImage) { + imageSrc = symbol.match(imageRegex)[1]; + // Create the image synchronously, add attribs async + obj = this.image(imageSrc); + // The image width is not always the same as the symbol width. The + // image may be centered within the symbol, as is the case when + // image shapes are used as label backgrounds, for example in flags. + obj.imgwidth = pick(symbolSizes[imageSrc] && symbolSizes[imageSrc].width, options && options.width); + obj.imgheight = pick(symbolSizes[imageSrc] && symbolSizes[imageSrc].height, options && options.height); + /** + * Set the size and position + */ + centerImage = function () { + obj.attr({ + width: obj.width, + height: obj.height + }); + }; + /** + * Width and height setters that take both the image's physical size + * and the label size into consideration, and translates the image + * to center within the label. + */ + ['width', 'height'].forEach(function (key) { + obj[key + 'Setter'] = function (value, key) { + var attribs = {}, imgSize = this['img' + key], trans = key === 'width' ? 'translateX' : 'translateY'; + this[key] = value; + if (defined(imgSize)) { + // Scale and center the image within its container. + // The name `backgroundSize` is taken from the CSS spec, + // but the value `within` is made up. Other possible + // values in the spec, `cover` and `contain`, can be + // implemented if needed. + if (options && + options.backgroundSize === 'within' && + this.width && + this.height) { + imgSize = Math.round(imgSize * Math.min(this.width / this.imgwidth, this.height / this.imgheight)); + } + if (this.element) { + this.element.setAttribute(key, imgSize); + } + if (!this.alignByTranslate) { + attribs[trans] = ((this[key] || 0) - imgSize) / 2; + this.attr(attribs); + } + } + }; + }); + if (defined(x)) { + obj.attr({ + x: x, + y: y + }); + } + obj.isImg = true; + if (defined(obj.imgwidth) && defined(obj.imgheight)) { + centerImage(); + } + else { + // Initialize image to be 0 size so export will still function + // if there's no cached sizes. + obj.attr({ width: 0, height: 0 }); + // Create a dummy JavaScript image to get the width and height. + createElement('img', { + onload: function () { + var chart = charts[ren.chartIndex]; + // Special case for SVGs on IE11, the width is not + // accessible until the image is part of the DOM + // (#2854). + if (this.width === 0) { + css(this, { + position: 'absolute', + top: '-999em' + }); + doc.body.appendChild(this); + } + // Center the image + symbolSizes[imageSrc] = { + width: this.width, + height: this.height + }; + obj.imgwidth = this.width; + obj.imgheight = this.height; + if (obj.element) { + centerImage(); + } + // Clean up after #2854 workaround. + if (this.parentNode) { + this.parentNode.removeChild(this); + } + // Fire the load event when all external images are + // loaded + ren.imgCount--; + if (!ren.imgCount && chart && !chart.hasLoaded) { + chart.onload(); + } + }, + src: imageSrc + }); + this.imgCount++; + } + } + return obj; + }, + /** + * An extendable collection of functions for defining symbol paths. + * + * @name Highcharts.SVGRenderer#symbols + * @type {Highcharts.SymbolDictionary} + */ + symbols: { + circle: function (x, y, w, h) { + // Return a full arc + return this.arc(x + w / 2, y + h / 2, w / 2, h / 2, { + start: Math.PI * 0.5, + end: Math.PI * 2.5, + open: false + }); + }, + square: function (x, y, w, h) { + return [ + ['M', x, y], + ['L', x + w, y], + ['L', x + w, y + h], + ['L', x, y + h], + ['Z'] + ]; + }, + triangle: function (x, y, w, h) { + return [ + ['M', x + w / 2, y], + ['L', x + w, y + h], + ['L', x, y + h], + ['Z'] + ]; + }, + 'triangle-down': function (x, y, w, h) { + return [ + ['M', x, y], + ['L', x + w, y], + ['L', x + w / 2, y + h], + ['Z'] + ]; + }, + diamond: function (x, y, w, h) { + return [ + ['M', x + w / 2, y], + ['L', x + w, y + h / 2], + ['L', x + w / 2, y + h], + ['L', x, y + h / 2], + ['Z'] + ]; + }, + arc: function (x, y, w, h, options) { + var start = options.start, rx = options.r || w, ry = options.r || h || w, proximity = 0.001, fullCircle = Math.abs(options.end - options.start - 2 * Math.PI) < + proximity, + // Substract a small number to prevent cos and sin of start and + // end from becoming equal on 360 arcs (related: #1561) + end = options.end - proximity, innerRadius = options.innerR, open = pick(options.open, fullCircle), cosStart = Math.cos(start), sinStart = Math.sin(start), cosEnd = Math.cos(end), sinEnd = Math.sin(end), + // Proximity takes care of rounding errors around PI (#6971) + longArc = pick(options.longArc, options.end - start - Math.PI < proximity ? 0 : 1), arc; + arc = [ + [ + 'M', + x + rx * cosStart, + y + ry * sinStart + ], + [ + 'A', + rx, + ry, + 0, + longArc, + pick(options.clockwise, 1), + x + rx * cosEnd, + y + ry * sinEnd + ] + ]; + if (defined(innerRadius)) { + arc.push(open ? + [ + 'M', + x + innerRadius * cosEnd, + y + innerRadius * sinEnd + ] : [ + 'L', + x + innerRadius * cosEnd, + y + innerRadius * sinEnd + ], [ + 'A', + innerRadius, + innerRadius, + 0, + longArc, + // Clockwise - opposite to the outer arc clockwise + defined(options.clockwise) ? 1 - options.clockwise : 0, + x + innerRadius * cosStart, + y + innerRadius * sinStart + ]); + } + if (!open) { + arc.push(['Z']); + } + return arc; + }, + /** + * Callout shape used for default tooltips, also used for rounded + * rectangles in VML + */ + callout: function (x, y, w, h, options) { + var arrowLength = 6, halfDistance = 6, r = Math.min((options && options.r) || 0, w, h), safeDistance = r + halfDistance, anchorX = options && options.anchorX, anchorY = options && options.anchorY, path; + path = [ + ['M', x + r, y], + ['L', x + w - r, y], + ['C', x + w, y, x + w, y, x + w, y + r], + ['L', x + w, y + h - r], + ['C', x + w, y + h, x + w, y + h, x + w - r, y + h], + ['L', x + r, y + h], + ['C', x, y + h, x, y + h, x, y + h - r], + ['L', x, y + r], + ['C', x, y, x, y, x + r, y] // top-left corner + ]; + // Anchor on right side + if (anchorX && anchorX > w) { + // Chevron + if (anchorY > y + safeDistance && + anchorY < y + h - safeDistance) { + path.splice(3, 1, ['L', x + w, anchorY - halfDistance], ['L', x + w + arrowLength, anchorY], ['L', x + w, anchorY + halfDistance], ['L', x + w, y + h - r]); + // Simple connector + } + else { + path.splice(3, 1, ['L', x + w, h / 2], ['L', anchorX, anchorY], ['L', x + w, h / 2], ['L', x + w, y + h - r]); + } + // Anchor on left side + } + else if (anchorX && anchorX < 0) { + // Chevron + if (anchorY > y + safeDistance && + anchorY < y + h - safeDistance) { + path.splice(7, 1, ['L', x, anchorY + halfDistance], ['L', x - arrowLength, anchorY], ['L', x, anchorY - halfDistance], ['L', x, y + r]); + // Simple connector + } + else { + path.splice(7, 1, ['L', x, h / 2], ['L', anchorX, anchorY], ['L', x, h / 2], ['L', x, y + r]); + } + } + else if ( // replace bottom + anchorY && + anchorY > h && + anchorX > x + safeDistance && + anchorX < x + w - safeDistance) { + path.splice(5, 1, ['L', anchorX + halfDistance, y + h], ['L', anchorX, y + h + arrowLength], ['L', anchorX - halfDistance, y + h], ['L', x + r, y + h]); + } + else if ( // replace top + anchorY && + anchorY < 0 && + anchorX > x + safeDistance && + anchorX < x + w - safeDistance) { + path.splice(1, 1, ['L', anchorX - halfDistance, y], ['L', anchorX, y - arrowLength], ['L', anchorX + halfDistance, y], ['L', w - r, y]); + } + return path; + } + }, + /** + * Define a clipping rectangle. The clipping rectangle is later applied + * to {@link SVGElement} objects through the {@link SVGElement#clip} + * function. + * + * @example + * var circle = renderer.circle(100, 100, 100) + * .attr({ fill: 'red' }) + * .add(); + * var clipRect = renderer.clipRect(100, 100, 100, 100); + * + * // Leave only the lower right quarter visible + * circle.clip(clipRect); + * + * @function Highcharts.SVGRenderer#clipRect + * + * @param {number} [x] + * + * @param {number} [y] + * + * @param {number} [width] + * + * @param {number} [height] + * + * @return {Highcharts.ClipRectElement} + * A clipping rectangle. + */ + clipRect: function (x, y, width, height) { + var wrapper, + // Add a hyphen at the end to avoid confusion in testing indexes + // -1 and -10, -11 etc (#6550) + id = uniqueKey() + '-', clipPath = this.createElement('clipPath').attr({ + id: id + }).add(this.defs); + wrapper = this.rect(x, y, width, height, 0).add(clipPath); + wrapper.id = id; + wrapper.clipPath = clipPath; + wrapper.count = 0; + return wrapper; + }, + /** + * Draw text. The text can contain a subset of HTML, like spans and anchors + * and some basic text styling of these. For more advanced features like + * border and background, use {@link Highcharts.SVGRenderer#label} instead. + * To update the text after render, run `text.attr({ text: 'New text' })`. + * + * @sample highcharts/members/renderer-text-on-chart/ + * Annotate the chart freely + * @sample highcharts/members/renderer-on-chart/ + * Annotate with a border and in response to the data + * @sample highcharts/members/renderer-text/ + * Formatted text + * + * @function Highcharts.SVGRenderer#text + * + * @param {string} [str] + * The text of (subset) HTML to draw. + * + * @param {number} [x] + * The x position of the text's lower left corner. + * + * @param {number} [y] + * The y position of the text's lower left corner. + * + * @param {boolean} [useHTML=false] + * Use HTML to render the text. + * + * @return {Highcharts.SVGElement} + * The text object. + */ + text: function (str, x, y, useHTML) { + // declare variables + var renderer = this, wrapper, attribs = {}; + if (useHTML && (renderer.allowHTML || !renderer.forExport)) { + return renderer.html(str, x, y); + } + attribs.x = Math.round(x || 0); // X always needed for line-wrap logic + if (y) { + attribs.y = Math.round(y); + } + if (defined(str)) { + attribs.text = str; + } + wrapper = renderer.createElement('text') + .attr(attribs); + if (!useHTML) { + wrapper.xSetter = function (value, key, element) { + var tspans = element.getElementsByTagName('tspan'), tspan, parentVal = element.getAttribute(key), i; + for (i = 0; i < tspans.length; i++) { + tspan = tspans[i]; + // If the x values are equal, the tspan represents a + // linebreak + if (tspan.getAttribute(key) === parentVal) { + tspan.setAttribute(key, value); + } + } + element.setAttribute(key, value); + }; + } + return wrapper; + }, + /** + * Utility to return the baseline offset and total line height from the font + * size. + * + * @function Highcharts.SVGRenderer#fontMetrics + * + * @param {number|string} [fontSize] + * The current font size to inspect. If not given, the font size + * will be found from the DOM element. + * + * @param {Highcharts.SVGElement|Highcharts.SVGDOMElement} [elem] + * The element to inspect for a current font size. + * + * @return {Highcharts.FontMetricsObject} + * The font metrics. + */ + fontMetrics: function (fontSize, elem) { + var lineHeight, baseline; + if ((this.styledMode || !/px/.test(fontSize)) && + win.getComputedStyle // old IE doesn't support it + ) { + fontSize = elem && SVGElement.prototype.getStyle.call(elem, 'font-size'); + } + else { + fontSize = fontSize || + // When the elem is a DOM element (#5932) + (elem && elem.style && elem.style.fontSize) || + // Fall back on the renderer style default + (this.style && this.style.fontSize); + } + // Handle different units + if (/px/.test(fontSize)) { + fontSize = pInt(fontSize); + } + else { + fontSize = 12; + } + // Empirical values found by comparing font size and bounding box + // height. Applies to the default font family. + // https://jsfiddle.net/highcharts/7xvn7/ + lineHeight = fontSize < 24 ? fontSize + 3 : Math.round(fontSize * 1.2); + baseline = Math.round(lineHeight * 0.8); + return { + h: lineHeight, + b: baseline, + f: fontSize + }; + }, + /** + * Correct X and Y positioning of a label for rotation (#1764). + * + * @private + * @function Highcharts.SVGRenderer#rotCorr + * + * @param {number} baseline + * + * @param {number} rotation + * + * @param {boolean} [alterY] + * + * @param {Highcharts.PositionObject} + */ + rotCorr: function (baseline, rotation, alterY) { + var y = baseline; + if (rotation && alterY) { + y = Math.max(y * Math.cos(rotation * deg2rad), 4); + } + return { + x: (-baseline / 3) * Math.sin(rotation * deg2rad), + y: y + }; + }, + /** + * Compatibility function to convert the legacy one-dimensional path array + * into an array of segments. + * + * It is used in maps to parse the `path` option, and in SVGRenderer.dSetter + * to support legacy paths from demos. + * + * @param path @private + * @function Highcharts.SVGRenderer#pathToSegments + * + * @param {Array} + * + * @return {Highcharts.SVGPathArray} + */ + pathToSegments: function (path) { + var ret = []; + var segment = []; + var commandLength = { + A: 8, + C: 7, + H: 2, + L: 3, + M: 3, + Q: 5, + S: 5, + T: 3, + V: 2 + }; + // Short, non-typesafe parsing of the one-dimensional array. It splits + // the path on any string. This is not type checked against the tuple + // types, but is shorter, and doesn't require specific checks for any + // command type in SVG. + for (var i = 0; i < path.length; i++) { + // Command skipped, repeat previous or insert L/l for M/m + if (isString(segment[0]) && + isNumber(path[i]) && + segment.length === commandLength[(segment[0].toUpperCase())]) { + path.splice(i, 0, segment[0].replace('M', 'L').replace('m', 'l')); + } + // Split on string + if (typeof path[i] === 'string') { + if (segment.length) { + ret.push(segment.slice(0)); + } + segment.length = 0; + } + segment.push(path[i]); + } + ret.push(segment.slice(0)); + return ret; + /* + // Fully type-safe version where each tuple type is checked. The + // downside is filesize and a lack of flexibility for unsupported + // commands + const ret: Highcharts.SVGPathArray = [], + commands = { + A: 7, + C: 6, + H: 1, + L: 2, + M: 2, + Q: 4, + S: 4, + T: 2, + V: 1, + Z: 0 + }; + + let i = 0, + lastI = 0, + lastCommand; + + while (i < path.length) { + const item = path[i]; + + let command; + + if (typeof item === 'string') { + command = item; + i += 1; + } else { + command = lastCommand || 'M'; + } + + // Upper case + const commandUC = command.toUpperCase(); + + if (commandUC in commands) { + + // No numeric parameters + if (command === 'Z' || command === 'z') { + ret.push([command]); + + // One numeric parameter + } else { + const val0 = path[i]; + if (typeof val0 === 'number') { + + // Horizontal line to + if (command === 'H' || command === 'h') { + ret.push([command, val0]); + i += 1; + + // Vertical line to + } else if (command === 'V' || command === 'v') { + ret.push([command, val0]); + i += 1; + + // Two numeric parameters + } else { + const val1 = path[i + 1]; + if (typeof val1 === 'number') { + // lineTo + if (command === 'L' || command === 'l') { + ret.push([command, val0, val1]); + i += 2; + + // moveTo + } else if (command === 'M' || command === 'm') { + ret.push([command, val0, val1]); + i += 2; + + // Smooth quadratic bezier + } else if (command === 'T' || command === 't') { + ret.push([command, val0, val1]); + i += 2; + + // Four numeric parameters + } else { + const val2 = path[i + 2], + val3 = path[i + 3]; + if ( + typeof val2 === 'number' && + typeof val3 === 'number' + ) { + // Quadratic bezier to + if ( + command === 'Q' || + command === 'q' + ) { + ret.push([ + command, + val0, + val1, + val2, + val3 + ]); + i += 4; + + // Smooth cubic bezier to + } else if ( + command === 'S' || + command === 's' + ) { + ret.push([ + command, + val0, + val1, + val2, + val3 + ]); + i += 4; + + // Six numeric parameters + } else { + const val4 = path[i + 4], + val5 = path[i + 5]; + + if ( + typeof val4 === 'number' && + typeof val5 === 'number' + ) { + // Curve to + if ( + command === 'C' || + command === 'c' + ) { + ret.push([ + command, + val0, + val1, + val2, + val3, + val4, + val5 + ]); + i += 6; + + // Seven numeric parameters + } else { + const val6 = path[i + 6]; + + // Arc to + if ( + typeof val6 === + 'number' && + ( + command === 'A' || + command === 'a' + ) + ) { + ret.push([ + command, + val0, + val1, + val2, + val3, + val4, + val5, + val6 + ]); + i += 7; + + } + + } + } + } + } + } + } + + } + } + } + } + + // An unmarked command following a moveTo is a lineTo + lastCommand = command === 'M' ? 'L' : command; + + if (i === lastI) { + break; + } + lastI = i; + } + return ret; + */ + }, + /** + * Draw a label, which is an extended text element with support for border + * and background. Highcharts creates a `g` element with a text and a `path` + * or `rect` inside, to make it behave somewhat like a HTML div. Border and + * background are set through `stroke`, `stroke-width` and `fill` attributes + * using the {@link Highcharts.SVGElement#attr|attr} method. To update the + * text after render, run `label.attr({ text: 'New text' })`. + * + * @sample highcharts/members/renderer-label-on-chart/ + * A label on the chart + * + * @function Highcharts.SVGRenderer#label + * + * @param {string} str + * The initial text string or (subset) HTML to render. + * + * @param {number} x + * The x position of the label's left side. + * + * @param {number} [y] + * The y position of the label's top side or baseline, depending on + * the `baseline` parameter. + * + * @param {string} [shape='rect'] + * The shape of the label's border/background, if any. Defaults to + * `rect`. Other possible values are `callout` or other shapes + * defined in {@link Highcharts.SVGRenderer#symbols}. + * + * @param {number} [anchorX] + * In case the `shape` has a pointer, like a flag, this is the + * coordinates it should be pinned to. + * + * @param {number} [anchorY] + * In case the `shape` has a pointer, like a flag, this is the + * coordinates it should be pinned to. + * + * @param {boolean} [useHTML=false] + * Wether to use HTML to render the label. + * + * @param {boolean} [baseline=false] + * Whether to position the label relative to the text baseline, + * like {@link Highcharts.SVGRenderer#text|renderer.text}, or to the + * upper border of the rectangle. + * + * @param {string} [className] + * Class name for the group. + * + * @return {Highcharts.SVGElement} + * The generated label. + */ + label: function (str, x, y, shape, anchorX, anchorY, useHTML, baseline, className) { + var renderer = this, styledMode = renderer.styledMode, wrapper = renderer.g((className !== 'button' && 'label')), text = wrapper.text = renderer.text('', 0, 0, useHTML) + .attr({ + zIndex: 1 + }), box, emptyBBox = { width: 0, height: 0, x: 0, y: 0 }, bBox = emptyBBox, alignFactor = 0, padding = 3, paddingLeft = 0, width, height, wrapperX, wrapperY, textAlign, deferredAttr = {}, strokeWidth, baselineOffset, hasBGImage = /^url\((.*?)\)$/.test(shape), needsBox = styledMode || hasBGImage, getCrispAdjust = function () { + return styledMode ? + box.strokeWidth() % 2 / 2 : + (strokeWidth ? parseInt(strokeWidth, 10) : 0) % 2 / 2; + }, updateBoxSize, updateTextPadding, boxAttr; + if (className) { + wrapper.addClass('highcharts-' + className); + } + /* This function runs after the label is added to the DOM (when the + bounding box is available), and after the text of the label is + updated to detect the new bounding box and reflect it in the border + box. */ + updateBoxSize = function () { + var style = text.element.style, crispAdjust, attribs = {}; + // #12165 error when width is null (auto) + // #12163 when fontweight: bold, recalculate bBox withot cache + // #3295 && 3514 box failure when string equals 0 + bBox = ((!isNumber(width) || !isNumber(height) || textAlign) && + defined(text.textStr)) ? + text.getBBox() : emptyBBox; + wrapper.width = ((width || bBox.width || 0) + + 2 * padding + + paddingLeft); + wrapper.height = (height || bBox.height || 0) + 2 * padding; + // Update the label-scoped y offset. Math.min because of inline + // style (#9400) + baselineOffset = padding + Math.min(renderer + .fontMetrics(style && style.fontSize, text).b, + // When the height is 0, there is no bBox, so go with the font + // metrics. Highmaps CSS demos. + bBox.height || Infinity); + if (needsBox) { + // Create the border box if it is not already present + if (!box) { + // Symbol definition exists (#5324) + wrapper.box = box = + renderer.symbols[shape] || hasBGImage ? + renderer.symbol(shape) : + renderer.rect(); + box.addClass(// Don't use label className for buttons + (className === 'button' ? '' : 'highcharts-label-box') + + (className ? ' highcharts-' + className + '-box' : '')); + box.add(wrapper); + crispAdjust = getCrispAdjust(); + attribs.x = crispAdjust; + attribs.y = (baseline ? -baselineOffset : 0) + crispAdjust; + } + // Apply the box attributes + attribs.width = Math.round(wrapper.width); + attribs.height = Math.round(wrapper.height); + box.attr(extend(attribs, deferredAttr)); + deferredAttr = {}; + } + }; + /* + * This function runs after setting text or padding, but only if padding + * is changed. + */ + updateTextPadding = function () { + var textX = paddingLeft + padding, textY; + // determin y based on the baseline + textY = baseline ? 0 : baselineOffset; + // compensate for alignment + if (defined(width) && + bBox && + (textAlign === 'center' || textAlign === 'right')) { + textX += { center: 0.5, right: 1 }[textAlign] * + (width - bBox.width); + } + // update if anything changed + if (textX !== text.x || textY !== text.y) { + text.attr('x', textX); + // #8159 - prevent misplaced data labels in treemap + // (useHTML: true) + if (text.hasBoxWidthChanged) { + bBox = text.getBBox(true); + updateBoxSize(); + } + if (typeof textY !== 'undefined') { + text.attr('y', textY); + } + } + // record current values + text.x = textX; + text.y = textY; + }; + /* + * Set a box attribute, or defer it if the box is not yet created + */ + boxAttr = function (key, value) { + if (box) { + box.attr(key, value); + } + else { + deferredAttr[key] = value; + } + }; + /* + * After the text element is added, get the desired size of the border + * box and add it before the text in the DOM. + */ + wrapper.onAdd = function () { + text.add(wrapper); + wrapper.attr({ + // Alignment is available now (#3295, 0 not rendered if given + // as a value) + text: (str || str === 0) ? str : '', + x: x, + y: y + }); + if (box && defined(anchorX)) { + wrapper.attr({ + anchorX: anchorX, + anchorY: anchorY + }); + } + }; + /* + * Add specific attribute setters. + */ + // only change local variables + wrapper.widthSetter = function (value) { + // width:auto => null + width = isNumber(value) ? value : null; + }; + wrapper.heightSetter = function (value) { + height = value; + }; + wrapper['text-alignSetter'] = function (value) { + textAlign = value; + }; + wrapper.paddingSetter = function (value) { + if (defined(value) && value !== padding) { + padding = wrapper.padding = value; + updateTextPadding(); + } + }; + wrapper.paddingLeftSetter = function (value) { + if (defined(value) && value !== paddingLeft) { + paddingLeft = value; + updateTextPadding(); + } + }; + // change local variable and prevent setting attribute on the group + wrapper.alignSetter = function (value) { + value = { + left: 0, + center: 0.5, + right: 1 + }[value]; + if (value !== alignFactor) { + alignFactor = value; + // Bounding box exists, means we're dynamically changing + if (bBox) { + wrapper.attr({ x: wrapperX }); // #5134 + } + } + }; + // apply these to the box and the text alike + wrapper.textSetter = function (value) { + if (typeof value !== 'undefined') { + // Must use .attr to ensure transforms are done (#10009) + text.attr({ + text: value + }); + } + updateBoxSize(); + updateTextPadding(); + }; + // apply these to the box but not to the text + wrapper['stroke-widthSetter'] = function (value, key) { + if (value) { + needsBox = true; + } + strokeWidth = this['stroke-width'] = value; + boxAttr(key, value); + }; + if (styledMode) { + wrapper.rSetter = function (value, key) { + boxAttr(key, value); + }; + } + else { + wrapper.strokeSetter = + wrapper.fillSetter = + wrapper.rSetter = function (value, key) { + if (key !== 'r') { + if (key === 'fill' && value) { + needsBox = true; + } + // for animation getter (#6776) + wrapper[key] = value; + } + boxAttr(key, value); + }; + } + wrapper.anchorXSetter = function (value, key) { + anchorX = wrapper.anchorX = value; + boxAttr(key, Math.round(value) - getCrispAdjust() - wrapperX); + }; + wrapper.anchorYSetter = function (value, key) { + anchorY = wrapper.anchorY = value; + boxAttr(key, value - wrapperY); + }; + // rename attributes + wrapper.xSetter = function (value) { + wrapper.x = value; // for animation getter + if (alignFactor) { + value -= alignFactor * ((width || bBox.width) + 2 * padding); + // Force animation even when setting to the same value (#7898) + wrapper['forceAnimate:x'] = true; + } + wrapperX = Math.round(value); + wrapper.attr('translateX', wrapperX); + }; + wrapper.ySetter = function (value) { + wrapperY = wrapper.y = Math.round(value); + wrapper.attr('translateY', wrapperY); + }; + wrapper.isLabel = true; + // Redirect certain methods to either the box or the text + var baseCss = wrapper.css; + var wrapperExtension = { + /** + * Pick up some properties and apply them to the text instead of the + * wrapper. + */ + css: function (styles) { + if (styles) { + var textStyles = {}, isWidth, isFontStyle; + // Create a copy to avoid altering the original object + // (#537) + styles = merge(styles); + wrapper.textProps.forEach(function (prop) { + if (typeof styles[prop] !== 'undefined') { + textStyles[prop] = styles[prop]; + delete styles[prop]; + } + }); + text.css(textStyles); + isWidth = 'width' in textStyles; + isFontStyle = 'fontSize' in textStyles || + 'fontWeight' in textStyles; + // Update existing text, box (#9400, #12163) + if (isWidth || isFontStyle) { + updateBoxSize(); + // Keep updated (#9400, #12163) + if (isFontStyle) { + updateTextPadding(); + } + } + } + return baseCss.call(wrapper, styles); + }, + /* + * Return the bounding box of the box, not the group. + */ + getBBox: function () { + return { + width: bBox.width + 2 * padding, + height: bBox.height + 2 * padding, + x: bBox.x - padding, + y: bBox.y - padding + }; + }, + /** + * Destroy and release memory. + */ + destroy: function () { + // Added by button implementation + removeEvent(wrapper.element, 'mouseenter'); + removeEvent(wrapper.element, 'mouseleave'); + if (text) { + text.destroy(); + } + if (box) { + box = box.destroy(); + } + // Call base implementation to destroy the rest + SVGElement.prototype.destroy.call(wrapper); + // Release local pointers (#1298) + wrapper = + renderer = + text = + updateBoxSize = + updateTextPadding = + boxAttr = null; + } + }; + // Event handling. In case of useHTML, we need to make sure that events + // are captured on the span as well, and that mouseenter/mouseleave + // between the SVG group and the HTML span are not treated as real + // enter/leave events. #13310. + wrapper.on = function (eventType, handler) { + var span = text && text.element.tagName === 'SPAN' ? text : void 0; + var selectiveHandler; + if (span) { + selectiveHandler = function (e) { + if ((eventType === 'mouseenter' || + eventType === 'mouseleave') && + e.relatedTarget instanceof Element && + (wrapper.element.contains(e.relatedTarget) || + span.element.contains(e.relatedTarget))) { + return; + } + handler.call(wrapper.element, e); + }; + span.on(eventType, selectiveHandler); + } + SVGElement.prototype.on.call(wrapper, eventType, selectiveHandler || handler); + return wrapper; + }; + if (!styledMode) { + /** + * Apply the shadow to the box. + * + * @ignore + * @function Highcharts.SVGElement#shadow + * + * @return {Highcharts.SVGElement} + */ + wrapperExtension.shadow = function (b) { + if (b) { + updateBoxSize(); + if (box) { + box.shadow(b); + } + } + return wrapper; + }; + } + return extend(wrapper, wrapperExtension); + } +}); // end SVGRenderer +// general renderer +H.Renderer = SVGRenderer; diff --git a/librerias/gantt/code/es-modules/parts/Tick.js b/librerias/gantt/code/es-modules/parts/Tick.js new file mode 100644 index 0000000..1db0da5 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/Tick.js @@ -0,0 +1,667 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +/** + * Optional parameters for the tick. + * @private + * @interface Highcharts.TickParametersObject + */ /** +* Set category for the tick. +* @name Highcharts.TickParametersObject#category +* @type {string|undefined} +*/ /** +* @name Highcharts.TickParametersObject#options +* @type {Highcharts.Dictionary|undefined} +*/ /** +* Set tickmarkOffset for the tick. +* @name Highcharts.TickParametersObject#tickmarkOffset +* @type {number|undefined} +*/ +import U from './Utilities.js'; +var clamp = U.clamp, correctFloat = U.correctFloat, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, extend = U.extend, fireEvent = U.fireEvent, isNumber = U.isNumber, merge = U.merge, objectEach = U.objectEach, pick = U.pick; +var deg2rad = H.deg2rad; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * The Tick class. + * + * @class + * @name Highcharts.Tick + * + * @param {Highcharts.Axis} axis + * The axis of the tick. + * + * @param {number} pos + * The position of the tick on the axis in terms of axis values. + * + * @param {string} [type] + * The type of tick, either 'minor' or an empty string + * + * @param {boolean} [noLabel=false] + * Whether to disable the label or not. Defaults to false. + * + * @param {object} [parameters] + * Optional parameters for the tick. + */ +var Tick = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Tick(axis, pos, type, noLabel, parameters) { + this.isNew = true; + this.isNewLabel = true; + /** + * The related axis of the tick. + * @name Highcharts.Tick#axis + * @type {Highcharts.Axis} + */ + this.axis = axis; + /** + * The logical position of the tick on the axis in terms of axis values. + * @name Highcharts.Tick#pos + * @type {number} + */ + this.pos = pos; + /** + * The tick type, which can be `"minor"`, or an empty string. + * @name Highcharts.Tick#type + * @type {string} + */ + this.type = type || ''; + this.parameters = parameters || {}; + /** + * The mark offset of the tick on the axis. Usually `undefined`, numeric + * for grid axes. + * @name Highcharts.Tick#tickmarkOffset + * @type {number|undefined} + */ + this.tickmarkOffset = this.parameters.tickmarkOffset; + this.options = this.parameters.options; + fireEvent(this, 'init'); + if (!type && !noLabel) { + this.addLabel(); + } + } + /* * + * + * Functions + * + * */ + /** + * Write the tick label. + * + * @private + * @function Highcharts.Tick#addLabel + * @return {void} + */ + Tick.prototype.addLabel = function () { + var tick = this, axis = tick.axis, options = axis.options, chart = axis.chart, categories = axis.categories, log = axis.logarithmic, names = axis.names, pos = tick.pos, labelOptions = pick(tick.options && tick.options.labels, options.labels), str, tickPositions = axis.tickPositions, isFirst = pos === tickPositions[0], isLast = pos === tickPositions[tickPositions.length - 1], value = this.parameters.category || (categories ? + pick(categories[pos], names[pos], pos) : + pos), label = tick.label, animateLabels = (!labelOptions.step || labelOptions.step === 1) && + axis.tickInterval === 1, tickPositionInfo = tickPositions.info, dateTimeLabelFormat, dateTimeLabelFormats, i, list; + // Set the datetime label format. If a higher rank is set for this + // position, use that. If not, use the general format. + if (axis.dateTime && tickPositionInfo) { + dateTimeLabelFormats = chart.time.resolveDTLFormat(options.dateTimeLabelFormats[(!options.grid && + tickPositionInfo.higherRanks[pos]) || + tickPositionInfo.unitName]); + dateTimeLabelFormat = dateTimeLabelFormats.main; + } + // set properties for access in render method + /** + * True if the tick is the first one on the axis. + * @name Highcharts.Tick#isFirst + * @readonly + * @type {boolean|undefined} + */ + tick.isFirst = isFirst; + /** + * True if the tick is the last one on the axis. + * @name Highcharts.Tick#isLast + * @readonly + * @type {boolean|undefined} + */ + tick.isLast = isLast; + // Get the string + tick.formatCtx = { + axis: axis, + chart: chart, + isFirst: isFirst, + isLast: isLast, + dateTimeLabelFormat: dateTimeLabelFormat, + tickPositionInfo: tickPositionInfo, + value: log ? correctFloat(log.lin2log(value)) : value, + pos: pos + }; + str = axis.labelFormatter.call(tick.formatCtx, this.formatCtx); + // Set up conditional formatting based on the format list if existing. + list = dateTimeLabelFormats && dateTimeLabelFormats.list; + if (list) { + tick.shortenLabel = function () { + for (i = 0; i < list.length; i++) { + label.attr({ + text: axis.labelFormatter.call(extend(tick.formatCtx, { dateTimeLabelFormat: list[i] })) + }); + if (label.getBBox().width < + axis.getSlotWidth(tick) - 2 * + pick(labelOptions.padding, 5)) { + return; + } + } + label.attr({ + text: '' + }); + }; + } + // Call only after first render + if (animateLabels && axis._addedPlotLB && axis.isXAxis) { + tick.moveLabel(str, labelOptions); + } + // First call + if (!defined(label) && !tick.movedLabel) { + /** + * The rendered text label of the tick. + * @name Highcharts.Tick#label + * @type {Highcharts.SVGElement|undefined} + */ + tick.label = label = tick.createLabel({ x: 0, y: 0 }, str, labelOptions); + // Base value to detect change for new calls to getBBox + tick.rotation = 0; + // update + } + else if (label && label.textStr !== str && !animateLabels) { + // When resetting text, also reset the width if dynamically set + // (#8809) + if (label.textWidth && + !(labelOptions.style && labelOptions.style.width) && + !label.styles.width) { + label.css({ width: null }); + } + label.attr({ text: str }); + label.textPxLength = label.getBBox().width; + } + }; + /** + * Render and return the label of the tick. + * + * @private + * @function Highcharts.Tick#createLabel + * @param {Highcharts.PositionObject} xy + * @param {string} str + * @param {Highcharts.XAxisLabelsOptions} labelOptions + * @return {Highcharts.SVGElement|undefined} + */ + Tick.prototype.createLabel = function (xy, str, labelOptions) { + var axis = this.axis, chart = axis.chart, label = defined(str) && labelOptions.enabled ? + chart.renderer + .text(str, xy.x, xy.y, labelOptions.useHTML) + .add(axis.labelGroup) : + null; + // Un-rotated length + if (label) { + // Without position absolute, IE export sometimes is wrong + if (!chart.styledMode) { + label.css(merge(labelOptions.style)); + } + label.textPxLength = label.getBBox().width; + } + return label; + }; + /** + * Destructor for the tick prototype + * + * @private + * @function Highcharts.Tick#destroy + * @return {void} + */ + Tick.prototype.destroy = function () { + destroyObjectProperties(this, this.axis); + }; + /** + * Gets the x and y positions for ticks in terms of pixels. + * + * @private + * @function Highcharts.Tick#getPosition + * + * @param {boolean} horiz + * Whether the tick is on an horizontal axis or not. + * + * @param {number} tickPos + * Position of the tick. + * + * @param {number} tickmarkOffset + * Tickmark offset for all ticks. + * + * @param {boolean} [old] + * Whether the axis has changed or not. + * + * @return {Highcharts.PositionObject} + * The tick position. + * + * @fires Highcharts.Tick#event:afterGetPosition + */ + Tick.prototype.getPosition = function (horiz, tickPos, tickmarkOffset, old) { + var axis = this.axis, chart = axis.chart, cHeight = (old && chart.oldChartHeight) || chart.chartHeight, pos; + pos = { + x: horiz ? + correctFloat(axis.translate(tickPos + tickmarkOffset, null, null, old) + + axis.transB) : + (axis.left + + axis.offset + + (axis.opposite ? + (((old && chart.oldChartWidth) || + chart.chartWidth) - + axis.right - + axis.left) : + 0)), + y: horiz ? + (cHeight - + axis.bottom + + axis.offset - + (axis.opposite ? axis.height : 0)) : + correctFloat(cHeight - + axis.translate(tickPos + tickmarkOffset, null, null, old) - + axis.transB) + }; + // Chrome workaround for #10516 + pos.y = clamp(pos.y, -1e5, 1e5); + fireEvent(this, 'afterGetPosition', { pos: pos }); + return pos; + }; + /** + * Get the x, y position of the tick label + * + * @private + * @return {Highcharts.PositionObject} + */ + Tick.prototype.getLabelPosition = function (x, y, label, horiz, labelOptions, tickmarkOffset, index, step) { + var axis = this.axis, transA = axis.transA, reversed = ( // #7911 + axis.isLinked && axis.linkedParent ? + axis.linkedParent.reversed : + axis.reversed), staggerLines = axis.staggerLines, rotCorr = axis.tickRotCorr || { x: 0, y: 0 }, yOffset = labelOptions.y, + // Adjust for label alignment if we use reserveSpace: true (#5286) + labelOffsetCorrection = (!horiz && !axis.reserveSpaceDefault ? + -axis.labelOffset * (axis.labelAlign === 'center' ? 0.5 : 1) : + 0), line, pos = {}; + if (!defined(yOffset)) { + if (axis.side === 0) { + yOffset = label.rotation ? -8 : -label.getBBox().height; + } + else if (axis.side === 2) { + yOffset = rotCorr.y + 8; + } + else { + // #3140, #3140 + yOffset = Math.cos(label.rotation * deg2rad) * + (rotCorr.y - label.getBBox(false, 0).height / 2); + } + } + x = x + + labelOptions.x + + labelOffsetCorrection + + rotCorr.x - + (tickmarkOffset && horiz ? + tickmarkOffset * transA * (reversed ? -1 : 1) : + 0); + y = y + yOffset - (tickmarkOffset && !horiz ? + tickmarkOffset * transA * (reversed ? 1 : -1) : 0); + // Correct for staggered labels + if (staggerLines) { + line = (index / (step || 1) % staggerLines); + if (axis.opposite) { + line = staggerLines - line - 1; + } + y += line * (axis.labelOffset / staggerLines); + } + pos.x = x; + pos.y = Math.round(y); + fireEvent(this, 'afterGetLabelPosition', { pos: pos, tickmarkOffset: tickmarkOffset, index: index }); + return pos; + }; + /** + * Get the offset height or width of the label + * + * @private + * @function Highcharts.Tick#getLabelSize + * @return {number} + */ + Tick.prototype.getLabelSize = function () { + return this.label ? + this.label.getBBox()[this.axis.horiz ? 'height' : 'width'] : + 0; + }; + /** + * Extendible method to return the path of the marker + * + * @private + * + */ + Tick.prototype.getMarkPath = function (x, y, tickLength, tickWidth, horiz, renderer) { + return renderer.crispLine([[ + 'M', + x, + y + ], [ + 'L', + x + (horiz ? 0 : -tickLength), + y + (horiz ? tickLength : 0) + ]], tickWidth); + }; + /** + * Handle the label overflow by adjusting the labels to the left and right + * edge, or hide them if they collide into the neighbour label. + * + * @private + * @function Highcharts.Tick#handleOverflow + * @param {Highcharts.PositionObject} xy + * @return {void} + */ + Tick.prototype.handleOverflow = function (xy) { + var tick = this, axis = this.axis, labelOptions = axis.options.labels, pxPos = xy.x, chartWidth = axis.chart.chartWidth, spacing = axis.chart.spacing, leftBound = pick(axis.labelLeft, Math.min(axis.pos, spacing[3])), rightBound = pick(axis.labelRight, Math.max(!axis.isRadial ? axis.pos + axis.len : 0, chartWidth - spacing[1])), label = this.label, rotation = this.rotation, factor = { + left: 0, + center: 0.5, + right: 1 + }[axis.labelAlign || label.attr('align')], labelWidth = label.getBBox().width, slotWidth = axis.getSlotWidth(tick), modifiedSlotWidth = slotWidth, xCorrection = factor, goRight = 1, leftPos, rightPos, textWidth, css = {}; + // Check if the label overshoots the chart spacing box. If it does, move + // it. If it now overshoots the slotWidth, add ellipsis. + if (!rotation && + pick(labelOptions.overflow, 'justify') === 'justify') { + leftPos = pxPos - factor * labelWidth; + rightPos = pxPos + (1 - factor) * labelWidth; + if (leftPos < leftBound) { + modifiedSlotWidth = + xy.x + modifiedSlotWidth * (1 - factor) - leftBound; + } + else if (rightPos > rightBound) { + modifiedSlotWidth = + rightBound - xy.x + modifiedSlotWidth * factor; + goRight = -1; + } + modifiedSlotWidth = Math.min(slotWidth, modifiedSlotWidth); // #4177 + if (modifiedSlotWidth < slotWidth && axis.labelAlign === 'center') { + xy.x += (goRight * + (slotWidth - + modifiedSlotWidth - + xCorrection * (slotWidth - Math.min(labelWidth, modifiedSlotWidth)))); + } + // If the label width exceeds the available space, set a text width + // to be picked up below. Also, if a width has been set before, we + // need to set a new one because the reported labelWidth will be + // limited by the box (#3938). + if (labelWidth > modifiedSlotWidth || + (axis.autoRotation && (label.styles || {}).width)) { + textWidth = modifiedSlotWidth; + } + // Add ellipsis to prevent rotated labels to be clipped against the edge + // of the chart + } + else if (rotation < 0 && + pxPos - factor * labelWidth < leftBound) { + textWidth = Math.round(pxPos / Math.cos(rotation * deg2rad) - leftBound); + } + else if (rotation > 0 && + pxPos + factor * labelWidth > rightBound) { + textWidth = Math.round((chartWidth - pxPos) / + Math.cos(rotation * deg2rad)); + } + if (textWidth) { + if (tick.shortenLabel) { + tick.shortenLabel(); + } + else { + css.width = Math.floor(textWidth) + 'px'; + if (!(labelOptions.style || {}).textOverflow) { + css.textOverflow = 'ellipsis'; + } + label.css(css); + } + } + }; + /** + * Try to replace the label if the same one already exists. + * + * @private + * @function Highcharts.Tick#moveLabel + * @param {string} str + * @param {Highcharts.XAxisLabelsOptions} labelOptions + * + * @return {void} + */ + Tick.prototype.moveLabel = function (str, labelOptions) { + var tick = this, label = tick.label, moved = false, xAxis = tick.axis, chart = xAxis.chart, labelPos, reversed = xAxis.reversed, inverted = chart.inverted, xPos, yPos; + if (label && label.textStr === str) { + tick.movedLabel = label; + moved = true; + delete tick.label; + } + else { // Find a label with the same string + objectEach(xAxis.ticks, function (currentTick) { + if (!moved && + !currentTick.isNew && + currentTick !== tick && + currentTick.label && + currentTick.label.textStr === str) { + tick.movedLabel = currentTick.label; + moved = true; + currentTick.labelPos = tick.movedLabel.xy; + delete currentTick.label; + } + }); + } + // Create new label if the actual one is moved + if (!moved && (tick.labelPos || label)) { + labelPos = tick.labelPos || label.xy; + xPos = inverted ? + labelPos.x : (reversed ? 0 : xAxis.width + xAxis.left); + yPos = inverted ? + (reversed ? (xAxis.width + xAxis.left) : 0) : labelPos.y; + tick.movedLabel = tick.createLabel({ x: xPos, y: yPos }, str, labelOptions); + if (tick.movedLabel) { + tick.movedLabel.attr({ opacity: 0 }); + } + } + }; + /** + * Put everything in place + * + * @private + * @param {number} index + * @param {boolean} [old] + * Use old coordinates to prepare an animation into new position + * @param {number} [opacity] + * @return {voids} + */ + Tick.prototype.render = function (index, old, opacity) { + var tick = this, axis = tick.axis, horiz = axis.horiz, pos = tick.pos, tickmarkOffset = pick(tick.tickmarkOffset, axis.tickmarkOffset), xy = tick.getPosition(horiz, pos, tickmarkOffset, old), x = xy.x, y = xy.y, reverseCrisp = ((horiz && x === axis.pos + axis.len) || + (!horiz && y === axis.pos)) ? -1 : 1; // #1480, #1687 + opacity = pick(opacity, 1); + this.isActive = true; + // Create the grid line + this.renderGridLine(old, opacity, reverseCrisp); + // create the tick mark + this.renderMark(xy, opacity, reverseCrisp); + // the label is created on init - now move it into place + this.renderLabel(xy, old, opacity, index); + tick.isNew = false; + fireEvent(this, 'afterRender'); + }; + /** + * Renders the gridLine. + * + * @private + * @param {boolean} old Whether or not the tick is old + * @param {number} opacity The opacity of the grid line + * @param {number} reverseCrisp Modifier for avoiding overlapping 1 or -1 + * @return {void} + */ + Tick.prototype.renderGridLine = function (old, opacity, reverseCrisp) { + var tick = this, axis = tick.axis, options = axis.options, gridLine = tick.gridLine, gridLinePath, attribs = {}, pos = tick.pos, type = tick.type, tickmarkOffset = pick(tick.tickmarkOffset, axis.tickmarkOffset), renderer = axis.chart.renderer, gridPrefix = type ? type + 'Grid' : 'grid', gridLineWidth = options[gridPrefix + 'LineWidth'], gridLineColor = options[gridPrefix + 'LineColor'], dashStyle = options[gridPrefix + 'LineDashStyle']; + if (!gridLine) { + if (!axis.chart.styledMode) { + attribs.stroke = gridLineColor; + attribs['stroke-width'] = gridLineWidth; + if (dashStyle) { + attribs.dashstyle = dashStyle; + } + } + if (!type) { + attribs.zIndex = 1; + } + if (old) { + opacity = 0; + } + /** + * The rendered grid line of the tick. + * @name Highcharts.Tick#gridLine + * @type {Highcharts.SVGElement|undefined} + */ + tick.gridLine = gridLine = renderer.path() + .attr(attribs) + .addClass('highcharts-' + (type ? type + '-' : '') + 'grid-line') + .add(axis.gridGroup); + } + if (gridLine) { + gridLinePath = axis.getPlotLinePath({ + value: pos + tickmarkOffset, + lineWidth: gridLine.strokeWidth() * reverseCrisp, + force: 'pass', + old: old + }); + // If the parameter 'old' is set, the current call will be followed + // by another call, therefore do not do any animations this time + if (gridLinePath) { + gridLine[old || tick.isNew ? 'attr' : 'animate']({ + d: gridLinePath, + opacity: opacity + }); + } + } + }; + /** + * Renders the tick mark. + * + * @private + * @param {Highcharts.PositionObject} xy The position vector of the mark + * @param {number} opacity The opacity of the mark + * @param {number} reverseCrisp Modifier for avoiding overlapping 1 or -1 + * @return {void} + */ + Tick.prototype.renderMark = function (xy, opacity, reverseCrisp) { + var tick = this, axis = tick.axis, options = axis.options, renderer = axis.chart.renderer, type = tick.type, tickPrefix = type ? type + 'Tick' : 'tick', tickSize = axis.tickSize(tickPrefix), mark = tick.mark, isNewMark = !mark, x = xy.x, y = xy.y, tickWidth = pick(options[tickPrefix + 'Width'], !type && axis.isXAxis ? 1 : 0), // X axis defaults to 1 + tickColor = options[tickPrefix + 'Color']; + if (tickSize) { + // negate the length + if (axis.opposite) { + tickSize[0] = -tickSize[0]; + } + // First time, create it + if (isNewMark) { + /** + * The rendered mark of the tick. + * @name Highcharts.Tick#mark + * @type {Highcharts.SVGElement|undefined} + */ + tick.mark = mark = renderer.path() + .addClass('highcharts-' + (type ? type + '-' : '') + 'tick') + .add(axis.axisGroup); + if (!axis.chart.styledMode) { + mark.attr({ + stroke: tickColor, + 'stroke-width': tickWidth + }); + } + } + mark[isNewMark ? 'attr' : 'animate']({ + d: tick.getMarkPath(x, y, tickSize[0], mark.strokeWidth() * reverseCrisp, axis.horiz, renderer), + opacity: opacity + }); + } + }; + /** + * Renders the tick label. + * Note: The label should already be created in init(), so it should only + * have to be moved into place. + * + * @private + * @param {Highcharts.PositionObject} xy The position vector of the label + * @param {boolean} old Whether or not the tick is old + * @param {number} opacity The opacity of the label + * @param {number} index The index of the tick + * @return {void} + */ + Tick.prototype.renderLabel = function (xy, old, opacity, index) { + var tick = this, axis = tick.axis, horiz = axis.horiz, options = axis.options, label = tick.label, labelOptions = options.labels, step = labelOptions.step, tickmarkOffset = pick(tick.tickmarkOffset, axis.tickmarkOffset), show = true, x = xy.x, y = xy.y; + if (label && isNumber(x)) { + label.xy = xy = tick.getLabelPosition(x, y, label, horiz, labelOptions, tickmarkOffset, index, step); + // Apply show first and show last. If the tick is both first and + // last, it is a single centered tick, in which case we show the + // label anyway (#2100). + if ((tick.isFirst && + !tick.isLast && + !pick(options.showFirstLabel, 1)) || + (tick.isLast && + !tick.isFirst && + !pick(options.showLastLabel, 1))) { + show = false; + // Handle label overflow and show or hide accordingly + } + else if (horiz && + !labelOptions.step && + !labelOptions.rotation && + !old && + opacity !== 0) { + tick.handleOverflow(xy); + } + // apply step + if (step && index % step) { + // show those indices dividable by step + show = false; + } + // Set the new position, and show or hide + if (show && isNumber(xy.y)) { + xy.opacity = opacity; + label[tick.isNewLabel ? 'attr' : 'animate'](xy); + tick.isNewLabel = false; + } + else { + label.attr('y', -9999); // #1338 + tick.isNewLabel = true; + } + } + }; + /** + * Replace labels with the moved ones to perform animation. Additionally + * destroy unused labels. + * + * @private + * @function Highcharts.Tick#replaceMovedLabel + * @return {void} + */ + Tick.prototype.replaceMovedLabel = function () { + var tick = this, label = tick.label, axis = tick.axis, reversed = axis.reversed, chart = tick.axis.chart, inverted = chart.inverted, x, y; + // Animate and destroy + if (label && !tick.isNew) { + x = inverted ? label.xy.x : (reversed ? axis.left : axis.width + axis.left); + y = inverted ? + (reversed ? axis.width + axis.top : axis.top) : + label.xy.y; + label.animate({ x: x, y: y, opacity: 0 }, void 0, label.destroy); + delete tick.label; + } + axis.isDirty = true; + tick.label = tick.movedLabel; + delete tick.movedLabel; + }; + return Tick; +}()); +H.Tick = Tick; +export default H.Tick; diff --git a/librerias/gantt/code/es-modules/parts/Time.js b/librerias/gantt/code/es-modules/parts/Time.js new file mode 100644 index 0000000..2c939a8 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/Time.js @@ -0,0 +1,778 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Highcharts from './Globals.js'; +/** + * Normalized interval. + * + * @interface Highcharts.TimeNormalizedObject + */ /** +* The count. +* +* @name Highcharts.TimeNormalizedObject#count +* @type {number} +*/ /** +* The interval in axis values (ms). +* +* @name Highcharts.TimeNormalizedObject#unitRange +* @type {number} +*/ +/** + * Function of an additional date format specifier. + * + * @callback Highcharts.TimeFormatCallbackFunction + * + * @param {number} timestamp + * The time to format. + * + * @return {string} + * The formatted portion of the date. + */ +/** + * Additonal time tick information. + * + * @interface Highcharts.TimeTicksInfoObject + * @extends Highcharts.TimeNormalizedObject + */ /** +* @name Highcharts.TimeTicksInfoObject#higherRanks +* @type {Array} +*/ /** +* @name Highcharts.TimeTicksInfoObject#totalRange +* @type {number} +*/ +/** + * Time ticks. + * + * @interface Highcharts.AxisTickPositionsArray + * @extends global.Array + */ /** +* @name Highcharts.AxisTickPositionsArray#info +* @type {Highcharts.TimeTicksInfoObject|undefined} +*/ +/** + * A callback to return the time zone offset for a given datetime. It + * takes the timestamp in terms of milliseconds since January 1 1970, + * and returns the timezone offset in minutes. This provides a hook + * for drawing time based charts in specific time zones using their + * local DST crossover dates, with the help of external libraries. + * + * @callback Highcharts.TimezoneOffsetCallbackFunction + * + * @param {number} timestamp + * Timestamp in terms of milliseconds since January 1 1970. + * + * @return {number} + * Timezone offset in minutes. + */ +import U from './Utilities.js'; +var defined = U.defined, error = U.error, extend = U.extend, isObject = U.isObject, merge = U.merge, objectEach = U.objectEach, pad = U.pad, pick = U.pick, splat = U.splat, timeUnits = U.timeUnits; +var H = Highcharts, win = H.win; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * The Time class. Time settings are applied in general for each page using + * `Highcharts.setOptions`, or individually for each Chart item through the + * [time](https://api.highcharts.com/highcharts/time) options set. + * + * The Time object is available from {@link Highcharts.Chart#time}, + * which refers to `Highcharts.time` if no individual time settings are + * applied. + * + * @example + * // Apply time settings globally + * Highcharts.setOptions({ + * time: { + * timezone: 'Europe/London' + * } + * }); + * + * // Apply time settings by instance + * var chart = Highcharts.chart('container', { + * time: { + * timezone: 'America/New_York' + * }, + * series: [{ + * data: [1, 4, 3, 5] + * }] + * }); + * + * // Use the Time object + * console.log( + * 'Current time in New York', + * chart.time.dateFormat('%Y-%m-%d %H:%M:%S', Date.now()) + * ); + * + * @since 6.0.5 + * + * @class + * @name Highcharts.Time + * + * @param {Highcharts.TimeOptions} options + * Time options as defined in [chart.options.time](/highcharts/time). + */ +var Time = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Time(options) { + /* * + * + * Properties + * + * */ + this.options = {}; + this.useUTC = false; + this.variableTimezone = false; + this.Date = win.Date; + /** + * Get the time zone offset based on the current timezone information as + * set in the global options. + * + * @function Highcharts.Time#getTimezoneOffset + * + * @param {number} timestamp + * The JavaScript timestamp to inspect. + * + * @return {number} + * The timezone offset in minutes compared to UTC. + */ + this.getTimezoneOffset = this.timezoneOffsetFunction(); + this.update(options); + } + /* * + * + * Functions + * + * */ + /** + * Time units used in `Time.get` and `Time.set` + * + * @typedef {"Date"|"Day"|"FullYear"|"Hours"|"Milliseconds"|"Minutes"|"Month"|"Seconds"} Highcharts.TimeUnitValue + */ + /** + * Get the value of a date object in given units, and subject to the Time + * object's current timezone settings. This function corresponds directly to + * JavaScripts `Date.getXXX / Date.getUTCXXX`, so instead of calling + * `date.getHours()` or `date.getUTCHours()` we will call + * `time.get('Hours')`. + * + * @function Highcharts.Time#get + * + * @param {Highcharts.TimeUnitValue} unit + * @param {Date} date + * + * @return {number} + * The given time unit + */ + Time.prototype.get = function (unit, date) { + if (this.variableTimezone || this.timezoneOffset) { + var realMs = date.getTime(); + var ms = realMs - this.getTimezoneOffset(date); + date.setTime(ms); // Temporary adjust to timezone + var ret = date['getUTC' + unit](); + date.setTime(realMs); // Reset + return ret; + } + // UTC time with no timezone handling + if (this.useUTC) { + return date['getUTC' + unit](); + } + // Else, local time + return date['get' + unit](); + }; + /** + * Set the value of a date object in given units, and subject to the Time + * object's current timezone settings. This function corresponds directly to + * JavaScripts `Date.setXXX / Date.setUTCXXX`, so instead of calling + * `date.setHours(0)` or `date.setUTCHours(0)` we will call + * `time.set('Hours', 0)`. + * + * @function Highcharts.Time#set + * + * @param {Highcharts.TimeUnitValue} unit + * @param {Date} date + * @param {number} value + * + * @return {number} + * The epoch milliseconds of the updated date + */ + Time.prototype.set = function (unit, date, value) { + // UTC time with timezone handling + if (this.variableTimezone || this.timezoneOffset) { + // For lower order time units, just set it directly using UTC + // time + if (unit === 'Milliseconds' || + unit === 'Seconds' || + unit === 'Minutes') { + return date['setUTC' + unit](value); + } + // Higher order time units need to take the time zone into + // account + // Adjust by timezone + var offset = this.getTimezoneOffset(date); + var ms = date.getTime() - offset; + date.setTime(ms); + date['setUTC' + unit](value); + var newOffset = this.getTimezoneOffset(date); + ms = date.getTime() + newOffset; + return date.setTime(ms); + } + // UTC time with no timezone handling + if (this.useUTC) { + return date['setUTC' + unit](value); + } + // Else, local time + return date['set' + unit](value); + }; + /** + * Update the Time object with current options. It is called internally on + * initializing Highcharts, after running `Highcharts.setOptions` and on + * `Chart.update`. + * + * @private + * @function Highcharts.Time#update + * + * @param {Highcharts.TimeOptions} options + * + * @return {void} + */ + Time.prototype.update = function (options) { + var useUTC = pick(options && options.useUTC, true), time = this; + this.options = options = merge(true, this.options || {}, options); + // Allow using a different Date class + this.Date = options.Date || win.Date || Date; + this.useUTC = useUTC; + this.timezoneOffset = (useUTC && options.timezoneOffset); + this.getTimezoneOffset = this.timezoneOffsetFunction(); + /* + * The time object has options allowing for variable time zones, meaning + * the axis ticks or series data needs to consider this. + */ + this.variableTimezone = !!(!useUTC || + options.getTimezoneOffset || + options.timezone); + }; + /** + * Make a time and returns milliseconds. Interprets the inputs as UTC time, + * local time or a specific timezone time depending on the current time + * settings. + * + * @function Highcharts.Time#makeTime + * + * @param {number} year + * The year + * + * @param {number} month + * The month. Zero-based, so January is 0. + * + * @param {number} [date=1] + * The day of the month + * + * @param {number} [hours=0] + * The hour of the day, 0-23. + * + * @param {number} [minutes=0] + * The minutes + * + * @param {number} [seconds=0] + * The seconds + * + * @return {number} + * The time in milliseconds since January 1st 1970. + */ + Time.prototype.makeTime = function (year, month, date, hours, minutes, seconds) { + var d, offset, newOffset; + if (this.useUTC) { + d = this.Date.UTC.apply(0, arguments); + offset = this.getTimezoneOffset(d); + d += offset; + newOffset = this.getTimezoneOffset(d); + if (offset !== newOffset) { + d += newOffset - offset; + // A special case for transitioning from summer time to winter time. + // When the clock is set back, the same time is repeated twice, i.e. + // 02:30 am is repeated since the clock is set back from 3 am to + // 2 am. We need to make the same time as local Date does. + } + else if (offset - 36e5 === this.getTimezoneOffset(d - 36e5) && + !H.isSafari) { + d -= 36e5; + } + } + else { + d = new this.Date(year, month, pick(date, 1), pick(hours, 0), pick(minutes, 0), pick(seconds, 0)).getTime(); + } + return d; + }; + /** + * Sets the getTimezoneOffset function. If the `timezone` option is set, a + * default getTimezoneOffset function with that timezone is returned. If + * a `getTimezoneOffset` option is defined, it is returned. If neither are + * specified, the function using the `timezoneOffset` option or 0 offset is + * returned. + * + * @private + * @function Highcharts.Time#timezoneOffsetFunction + * + * @return {Function} + * A getTimezoneOffset function + */ + Time.prototype.timezoneOffsetFunction = function () { + var time = this, options = this.options, moment = win.moment; + if (!this.useUTC) { + return function (timestamp) { + return new Date(timestamp.toString()).getTimezoneOffset() * 60000; + }; + } + if (options.timezone) { + if (!moment) { + // getTimezoneOffset-function stays undefined because it depends + // on Moment.js + error(25); + } + else { + return function (timestamp) { + return -moment.tz(timestamp, options.timezone).utcOffset() * 60000; + }; + } + } + // If not timezone is set, look for the getTimezoneOffset callback + if (this.useUTC && options.getTimezoneOffset) { + return function (timestamp) { + return options.getTimezoneOffset(timestamp.valueOf()) * 60000; + }; + } + // Last, use the `timezoneOffset` option if set + return function () { + return (time.timezoneOffset || 0) * 60000; + }; + }; + /** + * Formats a JavaScript date timestamp (milliseconds since Jan 1st 1970) + * into a human readable date string. The available format keys are listed + * below. Additional formats can be given in the + * {@link Highcharts.dateFormats} hook. + * + * Supported format keys: + * - `%a`: Short weekday, like 'Mon' + * - `%A`: Long weekday, like 'Monday' + * - `%d`: Two digit day of the month, 01 to 31 + * - `%e`: Day of the month, 1 through 31 + * - `%w`: Day of the week, 0 through 6 + * - `%b`: Short month, like 'Jan' + * - `%B`: Long month, like 'January' + * - `%m`: Two digit month number, 01 through 12 + * - `%y`: Two digits year, like 09 for 2009 + * - `%Y`: Four digits year, like 2009 + * - `%H`: Two digits hours in 24h format, 00 through 23 + * - `%k`: Hours in 24h format, 0 through 23 + * - `%I`: Two digits hours in 12h format, 00 through 11 + * - `%l`: Hours in 12h format, 1 through 12 + * - `%M`: Two digits minutes, 00 through 59 + * - `%p`: Upper case AM or PM + * - `%P`: Lower case AM or PM + * - `%S`: Two digits seconds, 00 through 59 + * - `%L`: Milliseconds (naming from Ruby) + * + * @example + * const time = new Highcharts.Time(); + * const s = time.dateFormat('%Y-%m-%d %H:%M:%S', Date.UTC(2020, 0, 1)); + * console.log(s); // => 2020-01-01 00:00:00 + * + * @function Highcharts.Time#dateFormat + * + * @param {string} format + * The desired format where various time representations are + * prefixed with %. + * + * @param {number} timestamp + * The JavaScript timestamp. + * + * @param {boolean} [capitalize=false] + * Upper case first letter in the return. + * + * @return {string} + * The formatted date. + */ + Time.prototype.dateFormat = function (format, timestamp, capitalize) { + var _a; + if (!defined(timestamp) || isNaN(timestamp)) { + return ((_a = H.defaultOptions.lang) === null || _a === void 0 ? void 0 : _a.invalidDate) || ''; + } + format = pick(format, '%Y-%m-%d %H:%M:%S'); + var time = this, date = new this.Date(timestamp), + // get the basic time values + hours = this.get('Hours', date), day = this.get('Day', date), dayOfMonth = this.get('Date', date), month = this.get('Month', date), fullYear = this.get('FullYear', date), lang = H.defaultOptions.lang, langWeekdays = lang === null || lang === void 0 ? void 0 : lang.weekdays, shortWeekdays = lang === null || lang === void 0 ? void 0 : lang.shortWeekdays, + // List all format keys. Custom formats can be added from the + // outside. + replacements = extend({ + // Day + // Short weekday, like 'Mon' + a: shortWeekdays ? + shortWeekdays[day] : + langWeekdays[day].substr(0, 3), + // Long weekday, like 'Monday' + A: langWeekdays[day], + // Two digit day of the month, 01 to 31 + d: pad(dayOfMonth), + // Day of the month, 1 through 31 + e: pad(dayOfMonth, 2, ' '), + // Day of the week, 0 through 6 + w: day, + // Week (none implemented) + // 'W': weekNumber(), + // Month + // Short month, like 'Jan' + b: lang.shortMonths[month], + // Long month, like 'January' + B: lang.months[month], + // Two digit month number, 01 through 12 + m: pad(month + 1), + // Month number, 1 through 12 (#8150) + o: month + 1, + // Year + // Two digits year, like 09 for 2009 + y: fullYear.toString().substr(2, 2), + // Four digits year, like 2009 + Y: fullYear, + // Time + // Two digits hours in 24h format, 00 through 23 + H: pad(hours), + // Hours in 24h format, 0 through 23 + k: hours, + // Two digits hours in 12h format, 00 through 11 + I: pad((hours % 12) || 12), + // Hours in 12h format, 1 through 12 + l: (hours % 12) || 12, + // Two digits minutes, 00 through 59 + M: pad(this.get('Minutes', date)), + // Upper case AM or PM + p: hours < 12 ? 'AM' : 'PM', + // Lower case AM or PM + P: hours < 12 ? 'am' : 'pm', + // Two digits seconds, 00 through 59 + S: pad(date.getSeconds()), + // Milliseconds (naming from Ruby) + L: pad(Math.floor(timestamp % 1000), 3) + }, H.dateFormats); + // Do the replaces + objectEach(replacements, function (val, key) { + // Regex would do it in one line, but this is faster + while (format.indexOf('%' + key) !== -1) { + format = format.replace('%' + key, typeof val === 'function' ? val.call(time, timestamp) : val); + } + }); + // Optionally capitalize the string and return + return capitalize ? + (format.substr(0, 1).toUpperCase() + + format.substr(1)) : + format; + }; + /** + * Resolve legacy formats of dateTimeLabelFormats (strings and arrays) into + * an object. + * @private + * @param {string|Array|Highcharts.Dictionary} f - General format description + * @return {Highcharts.Dictionary} - The object definition + */ + Time.prototype.resolveDTLFormat = function (f) { + if (!isObject(f, true)) { // check for string or array + f = splat(f); + return { + main: f[0], + from: f[1], + to: f[2] + }; + } + return f; + }; + /** + * Return an array with time positions distributed on round time values + * right and right after min and max. Used in datetime axes as well as for + * grouping data on a datetime axis. + * + * @function Highcharts.Time#getTimeTicks + * + * @param {Highcharts.TimeNormalizedObject} normalizedInterval + * The interval in axis values (ms) and the count + * + * @param {number} [min] + * The minimum in axis values + * + * @param {number} [max] + * The maximum in axis values + * + * @param {number} [startOfWeek=1] + * + * @return {Highcharts.AxisTickPositionsArray} + */ + Time.prototype.getTimeTicks = function (normalizedInterval, min, max, startOfWeek) { + var time = this, Date = time.Date, tickPositions = [], i, higherRanks = {}, minYear, // used in months and years as a basis for Date.UTC() + // When crossing DST, use the max. Resolves #6278. + minDate = new Date(min), interval = normalizedInterval.unitRange, count = normalizedInterval.count || 1, variableDayLength, minDay; + startOfWeek = pick(startOfWeek, 1); + if (defined(min)) { // #1300 + time.set('Milliseconds', minDate, interval >= timeUnits.second ? + 0 : // #3935 + count * Math.floor(time.get('Milliseconds', minDate) / count)); // #3652, #3654 + if (interval >= timeUnits.second) { // second + time.set('Seconds', minDate, interval >= timeUnits.minute ? + 0 : // #3935 + count * Math.floor(time.get('Seconds', minDate) / count)); + } + if (interval >= timeUnits.minute) { // minute + time.set('Minutes', minDate, interval >= timeUnits.hour ? + 0 : + count * Math.floor(time.get('Minutes', minDate) / count)); + } + if (interval >= timeUnits.hour) { // hour + time.set('Hours', minDate, interval >= timeUnits.day ? + 0 : + count * Math.floor(time.get('Hours', minDate) / count)); + } + if (interval >= timeUnits.day) { // day + time.set('Date', minDate, interval >= timeUnits.month ? + 1 : + Math.max(1, count * Math.floor(time.get('Date', minDate) / count))); + } + if (interval >= timeUnits.month) { // month + time.set('Month', minDate, interval >= timeUnits.year ? 0 : + count * Math.floor(time.get('Month', minDate) / count)); + minYear = time.get('FullYear', minDate); + } + if (interval >= timeUnits.year) { // year + minYear -= minYear % count; + time.set('FullYear', minDate, minYear); + } + // week is a special case that runs outside the hierarchy + if (interval === timeUnits.week) { + // get start of current week, independent of count + minDay = time.get('Day', minDate); + time.set('Date', minDate, (time.get('Date', minDate) - + minDay + startOfWeek + + // We don't want to skip days that are before + // startOfWeek (#7051) + (minDay < startOfWeek ? -7 : 0))); + } + // Get basics for variable time spans + minYear = time.get('FullYear', minDate); + var minMonth = time.get('Month', minDate), minDateDate = time.get('Date', minDate), minHours = time.get('Hours', minDate); + // Redefine min to the floored/rounded minimum time (#7432) + min = minDate.getTime(); + // Handle local timezone offset + if (time.variableTimezone) { + // Detect whether we need to take the DST crossover into + // consideration. If we're crossing over DST, the day length may + // be 23h or 25h and we need to compute the exact clock time for + // each tick instead of just adding hours. This comes at a cost, + // so first we find out if it is needed (#4951). + variableDayLength = ( + // Long range, assume we're crossing over. + max - min > 4 * timeUnits.month || + // Short range, check if min and max are in different time + // zones. + time.getTimezoneOffset(min) !== + time.getTimezoneOffset(max)); + } + // Iterate and add tick positions at appropriate values + var t = minDate.getTime(); + i = 1; + while (t < max) { + tickPositions.push(t); + // if the interval is years, use Date.UTC to increase years + if (interval === timeUnits.year) { + t = time.makeTime(minYear + i * count, 0); + // if the interval is months, use Date.UTC to increase months + } + else if (interval === timeUnits.month) { + t = time.makeTime(minYear, minMonth + i * count); + // if we're using global time, the interval is not fixed as it + // jumps one hour at the DST crossover + } + else if (variableDayLength && + (interval === timeUnits.day || interval === timeUnits.week)) { + t = time.makeTime(minYear, minMonth, minDateDate + + i * count * (interval === timeUnits.day ? 1 : 7)); + } + else if (variableDayLength && + interval === timeUnits.hour && + count > 1) { + // make sure higher ranks are preserved across DST (#6797, + // #7621) + t = time.makeTime(minYear, minMonth, minDateDate, minHours + i * count); + // else, the interval is fixed and we use simple addition + } + else { + t += interval * count; + } + i++; + } + // push the last time + tickPositions.push(t); + // Handle higher ranks. Mark new days if the time is on midnight + // (#950, #1649, #1760, #3349). Use a reasonable dropout threshold + // to prevent looping over dense data grouping (#6156). + if (interval <= timeUnits.hour && tickPositions.length < 10000) { + tickPositions.forEach(function (t) { + if ( + // Speed optimization, no need to run dateFormat unless + // we're on a full or half hour + t % 1800000 === 0 && + // Check for local or global midnight + time.dateFormat('%H%M%S%L', t) === '000000000') { + higherRanks[t] = 'day'; + } + }); + } + } + // record information on the chosen unit - for dynamic label formatter + tickPositions.info = extend(normalizedInterval, { + higherRanks: higherRanks, + totalRange: interval * count + }); + return tickPositions; + }; + /* * + * + * Static Properties + * + * */ + /** + * Time options that can apply globally or to individual charts. These + * settings affect how `datetime` axes are laid out, how tooltips are + * formatted, how series + * [pointIntervalUnit](#plotOptions.series.pointIntervalUnit) works and how + * the Highstock range selector handles time. + * + * The common use case is that all charts in the same Highcharts object + * share the same time settings, in which case the global settings are set + * using `setOptions`. + * + * ```js + * // Apply time settings globally + * Highcharts.setOptions({ + * time: { + * timezone: 'Europe/London' + * } + * }); + * // Apply time settings by instance + * var chart = Highcharts.chart('container', { + * time: { + * timezone: 'America/New_York' + * }, + * series: [{ + * data: [1, 4, 3, 5] + * }] + * }); + * + * // Use the Time object + * console.log( + * 'Current time in New York', + * chart.time.dateFormat('%Y-%m-%d %H:%M:%S', Date.now()) + * ); + * ``` + * + * Since v6.0.5, the time options were moved from the `global` obect to the + * `time` object, and time options can be set on each individual chart. + * + * @sample {highcharts|highstock} + * highcharts/time/timezone/ + * Set the timezone globally + * @sample {highcharts} + * highcharts/time/individual/ + * Set the timezone per chart instance + * @sample {highstock} + * stock/time/individual/ + * Set the timezone per chart instance + * + * @since 6.0.5 + * @optionparent time + */ + Time.defaultOptions = { + /** + * A custom `Date` class for advanced date handling. For example, + * [JDate](https://github.com/tahajahangir/jdate) can be hooked in to + * handle Jalali dates. + * + * @type {*} + * @since 4.0.4 + * @product highcharts highstock gantt + */ + Date: void 0, + /** + * A callback to return the time zone offset for a given datetime. It + * takes the timestamp in terms of milliseconds since January 1 1970, + * and returns the timezone offset in minutes. This provides a hook + * for drawing time based charts in specific time zones using their + * local DST crossover dates, with the help of external libraries. + * + * @see [global.timezoneOffset](#global.timezoneOffset) + * + * @sample {highcharts|highstock} highcharts/time/gettimezoneoffset/ + * Use moment.js to draw Oslo time regardless of browser locale + * + * @type {Highcharts.TimezoneOffsetCallbackFunction} + * @since 4.1.0 + * @product highcharts highstock gantt + */ + getTimezoneOffset: void 0, + /** + * Requires [moment.js](https://momentjs.com/). If the timezone option + * is specified, it creates a default + * [getTimezoneOffset](#time.getTimezoneOffset) function that looks + * up the specified timezone in moment.js. If moment.js is not included, + * this throws a Highcharts error in the console, but does not crash the + * chart. + * + * @see [getTimezoneOffset](#time.getTimezoneOffset) + * + * @sample {highcharts|highstock} highcharts/time/timezone/ + * Europe/Oslo + * + * @type {string} + * @since 5.0.7 + * @product highcharts highstock gantt + */ + timezone: void 0, + /** + * The timezone offset in minutes. Positive values are west, negative + * values are east of UTC, as in the ECMAScript + * [getTimezoneOffset](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset) + * method. Use this to display UTC based data in a predefined time zone. + * + * @see [time.getTimezoneOffset](#time.getTimezoneOffset) + * + * @sample {highcharts|highstock} highcharts/time/timezoneoffset/ + * Timezone offset + * + * @since 3.0.8 + * @product highcharts highstock gantt + */ + timezoneOffset: 0, + /** + * Whether to use UTC time for axis scaling, tickmark placement and + * time display in `Highcharts.dateFormat`. Advantages of using UTC + * is that the time displays equally regardless of the user agent's + * time zone settings. Local time can be used when the data is loaded + * in real time or when correct Daylight Saving Time transitions are + * required. + * + * @sample {highcharts} highcharts/time/useutc-true/ + * True by default + * @sample {highcharts} highcharts/time/useutc-false/ + * False + */ + useUTC: true + }; + return Time; +}()); +H.Time = Time; +export default H.Time; diff --git a/librerias/gantt/code/es-modules/parts/Tooltip.js b/librerias/gantt/code/es-modules/parts/Tooltip.js new file mode 100644 index 0000000..84b5033 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/Tooltip.js @@ -0,0 +1,1330 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +import U from './Utilities.js'; +var clamp = U.clamp, css = U.css, defined = U.defined, discardElement = U.discardElement, extend = U.extend, fireEvent = U.fireEvent, format = U.format, isNumber = U.isNumber, isString = U.isString, merge = U.merge, offset = U.offset, pick = U.pick, splat = U.splat, syncTimeout = U.syncTimeout, timeUnits = U.timeUnits; +/** + * Callback function to format the text of the tooltip from scratch. + * + * In case of single or shared tooltips, a string should be be returned. In case + * of splitted tooltips, it should return an array where the first item is the + * header, and subsequent items are mapped to the points. Return `false` to + * disable tooltip for a specific point on series. + * + * @callback Highcharts.TooltipFormatterCallbackFunction + * + * @param {Highcharts.TooltipFormatterContextObject} this + * Context to format + * + * @param {Highcharts.Tooltip} tooltip + * The tooltip instance + * + * @return {false|string|Array<(string|null|undefined)>|null|undefined} + * Formatted text or false + */ +/** + * @interface Highcharts.TooltipFormatterContextObject + */ /** +* @name Highcharts.TooltipFormatterContextObject#color +* @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} +*/ /** +* @name Highcharts.TooltipFormatterContextObject#colorIndex +* @type {number|undefined} +*/ /** +* @name Highcharts.TooltipFormatterContextObject#key +* @type {number} +*/ /** +* @name Highcharts.TooltipFormatterContextObject#percentage +* @type {number|undefined} +*/ /** +* @name Highcharts.TooltipFormatterContextObject#point +* @type {Highcharts.Point} +*/ /** +* @name Highcharts.TooltipFormatterContextObject#points +* @type {Array|undefined} +*/ /** +* @name Highcharts.TooltipFormatterContextObject#series +* @type {Highcharts.Series} +*/ /** +* @name Highcharts.TooltipFormatterContextObject#total +* @type {number|undefined} +*/ /** +* @name Highcharts.TooltipFormatterContextObject#x +* @type {number} +*/ /** +* @name Highcharts.TooltipFormatterContextObject#y +* @type {number} +*/ +/** + * A callback function to place the tooltip in a specific position. + * + * @callback Highcharts.TooltipPositionerCallbackFunction + * + * @param {number} labelWidth + * Width of the tooltip. + * + * @param {number} labelHeight + * Height of the tooltip. + * + * @param {Highcharts.Point} point + * Point information for positioning a tooltip. + * + * @return {Highcharts.PositionObject} + * New position for the tooltip. + */ +/** + * Point information for positioning a tooltip. + * + * @interface Highcharts.TooltipPositionerPointObject + */ /** +* If `tooltip.split` option is enabled and positioner is called for each of the +* boxes separately, this property indicates the call on the xAxis header, which +* is not a point itself. +* @name Highcharts.TooltipPositionerPointObject#isHeader +* @type {boolean} +*/ /** +* @name Highcharts.TooltipPositionerPointObject#negative +* @type {boolean} +*/ /** +* The reference point relative to the plot area. Add chart.plotLeft to get the +* full coordinates. +* @name Highcharts.TooltipPositionerPointObject#plotX +* @type {number} +*/ /** +* The reference point relative to the plot area. Add chart.plotTop to get the +* full coordinates. +* @name Highcharts.TooltipPositionerPointObject#plotY +* @type {number} +*/ +/** + * @typedef {"callout"|"circle"|"square"} Highcharts.TooltipShapeValue + */ +''; // separates doclets above from variables below +var doc = H.doc; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * Tooltip of a chart. + * + * @class + * @name Highcharts.Tooltip + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @param {Highcharts.TooltipOptions} options + * Tooltip options. + */ +var Tooltip = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Tooltip(chart, options) { + this.crosshairs = []; + this.distance = 0; + this.isHidden = true; + this.isSticky = false; + this.now = {}; + this.options = {}; + this.outside = false; + this.chart = chart; + this.init(chart, options); + } + /* * + * + * Functions + * + * */ + /** + * In styled mode, apply the default filter for the tooltip drop-shadow. It + * needs to have an id specific to the chart, otherwise there will be issues + * when one tooltip adopts the filter of a different chart, specifically one + * where the container is hidden. + * + * @private + * @function Highcharts.Tooltip#applyFilter + */ + Tooltip.prototype.applyFilter = function () { + var chart = this.chart; + chart.renderer.definition({ + tagName: 'filter', + id: 'drop-shadow-' + chart.index, + opacity: 0.5, + children: [{ + tagName: 'feGaussianBlur', + 'in': 'SourceAlpha', + stdDeviation: 1 + }, { + tagName: 'feOffset', + dx: 1, + dy: 1 + }, { + tagName: 'feComponentTransfer', + children: [{ + tagName: 'feFuncA', + type: 'linear', + slope: 0.3 + }] + }, { + tagName: 'feMerge', + children: [{ + tagName: 'feMergeNode' + }, { + tagName: 'feMergeNode', + 'in': 'SourceGraphic' + }] + }] + }); + chart.renderer.definition({ + tagName: 'style', + textContent: '.highcharts-tooltip-' + chart.index + '{' + + 'filter:url(#drop-shadow-' + chart.index + ')' + + '}' + }); + }; + /** + * Build the body (lines) of the tooltip by iterating over the items and + * returning one entry for each item, abstracting this functionality allows + * to easily overwrite and extend it. + * + * @private + * @function Highcharts.Tooltip#bodyFormatter + * @param {Array<(Highcharts.Point|Highcharts.Series)>} items + * @return {Array} + */ + Tooltip.prototype.bodyFormatter = function (items) { + return items.map(function (item) { + var tooltipOptions = item.series.tooltipOptions; + return (tooltipOptions[(item.point.formatPrefix || 'point') + 'Formatter'] || + item.point.tooltipFormatter).call(item.point, tooltipOptions[(item.point.formatPrefix || 'point') + 'Format'] || ''); + }); + }; + /** + * Destroy the single tooltips in a split tooltip. + * If the tooltip is active then it is not destroyed, unless forced to. + * + * @private + * @function Highcharts.Tooltip#cleanSplit + * + * @param {boolean} [force] + * Force destroy all tooltips. + */ + Tooltip.prototype.cleanSplit = function (force) { + this.chart.series.forEach(function (series) { + var tt = series && series.tt; + if (tt) { + if (!tt.isActive || force) { + series.tt = tt.destroy(); + } + else { + tt.isActive = false; + } + } + }); + }; + /** + * In case no user defined formatter is given, this will be used. Note that + * the context here is an object holding point, series, x, y etc. + * + * @function Highcharts.Tooltip#defaultFormatter + * + * @param {Highcharts.Tooltip} tooltip + * + * @return {Array} + */ + Tooltip.prototype.defaultFormatter = function (tooltip) { + var items = this.points || splat(this), s; + // Build the header + s = [tooltip.tooltipFooterHeaderFormatter(items[0])]; + // build the values + s = s.concat(tooltip.bodyFormatter(items)); + // footer + s.push(tooltip.tooltipFooterHeaderFormatter(items[0], true)); + return s; + }; + /** + * Removes and destroys the tooltip and its elements. + * + * @function Highcharts.Tooltip#destroy + */ + Tooltip.prototype.destroy = function () { + // Destroy and clear local variables + if (this.label) { + this.label = this.label.destroy(); + } + if (this.split && this.tt) { + this.cleanSplit(this.chart, true); + this.tt = this.tt.destroy(); + } + if (this.renderer) { + this.renderer = this.renderer.destroy(); + discardElement(this.container); + } + U.clearTimeout(this.hideTimer); + U.clearTimeout(this.tooltipTimeout); + }; + /** + * Extendable method to get the anchor position of the tooltip + * from a point or set of points + * + * @private + * @function Highcharts.Tooltip#getAnchor + * + * @param {Highcharts.Point|Array} points + * + * @param {Highcharts.PointerEventObject} [mouseEvent] + * + * @return {Array} + */ + Tooltip.prototype.getAnchor = function (points, mouseEvent) { + var ret, chart = this.chart, pointer = chart.pointer, inverted = chart.inverted, plotTop = chart.plotTop, plotLeft = chart.plotLeft, plotX = 0, plotY = 0, yAxis, xAxis; + points = splat(points); + // When tooltip follows mouse, relate the position to the mouse + if (this.followPointer && mouseEvent) { + if (typeof mouseEvent.chartX === 'undefined') { + mouseEvent = pointer.normalize(mouseEvent); + } + ret = [ + mouseEvent.chartX - plotLeft, + mouseEvent.chartY - plotTop + ]; + // Some series types use a specificly calculated tooltip position for + // each point + } + else if (points[0].tooltipPos) { + ret = points[0].tooltipPos; + // When shared, use the average position + } + else { + points.forEach(function (point) { + yAxis = point.series.yAxis; + xAxis = point.series.xAxis; + plotX += point.plotX + + (!inverted && xAxis ? xAxis.left - plotLeft : 0); + plotY += (point.plotLow ? + (point.plotLow + point.plotHigh) / 2 : + point.plotY) + (!inverted && yAxis ? yAxis.top - plotTop : 0); // #1151 + }); + plotX /= points.length; + plotY /= points.length; + ret = [ + inverted ? chart.plotWidth - plotY : plotX, + this.shared && !inverted && points.length > 1 && mouseEvent ? + // place shared tooltip next to the mouse (#424) + mouseEvent.chartY - plotTop : + inverted ? chart.plotHeight - plotX : plotY + ]; + } + return ret.map(Math.round); + }; + /** + * Get the optimal date format for a point, based on a range. + * + * @private + * @function Highcharts.Tooltip#getDateFormat + * + * @param {number} range + * The time range + * + * @param {number} date + * The date of the point in question + * + * @param {number} startOfWeek + * An integer representing the first day of the week, where 0 is + * Sunday. + * + * @param {Highcharts.Dictionary} dateTimeLabelFormats + * A map of time units to formats. + * + * @return {string} + * The optimal date format for a point. + */ + Tooltip.prototype.getDateFormat = function (range, date, startOfWeek, dateTimeLabelFormats) { + var time = this.chart.time, dateStr = time.dateFormat('%m-%d %H:%M:%S.%L', date), format, n, blank = '01-01 00:00:00.000', strpos = { + millisecond: 15, + second: 12, + minute: 9, + hour: 6, + day: 3 + }, lastN = 'millisecond'; // for sub-millisecond data, #4223 + for (n in timeUnits) { // eslint-disable-line guard-for-in + // If the range is exactly one week and we're looking at a + // Sunday/Monday, go for the week format + if (range === timeUnits.week && + +time.dateFormat('%w', date) === startOfWeek && + dateStr.substr(6) === blank.substr(6)) { + n = 'week'; + break; + } + // The first format that is too great for the range + if (timeUnits[n] > range) { + n = lastN; + break; + } + // If the point is placed every day at 23:59, we need to show + // the minutes as well. #2637. + if (strpos[n] && + dateStr.substr(strpos[n]) !== blank.substr(strpos[n])) { + break; + } + // Weeks are outside the hierarchy, only apply them on + // Mondays/Sundays like in the first condition + if (n !== 'week') { + lastN = n; + } + } + if (n) { + format = time.resolveDTLFormat(dateTimeLabelFormats[n]).main; + } + return format; + }; + /** + * Creates the Tooltip label element if it does not exist, then returns it. + * + * @function Highcharts.Tooltip#getLabel + * @return {Highcharts.SVGElement} + */ + Tooltip.prototype.getLabel = function () { + var _a, _b; + var tooltip = this, renderer = this.chart.renderer, styledMode = this.chart.styledMode, options = this.options, className = ('tooltip' + (defined(options.className) ? + ' ' + options.className : + '')), pointerEvents = (((_a = options.style) === null || _a === void 0 ? void 0 : _a.pointerEvents) || + (!this.followPointer && options.stickOnContact ? 'auto' : 'none')), container, set, onMouseEnter = function () { + tooltip.inContact = true; + }, onMouseLeave = function () { + var series = tooltip.chart.hoverSeries; + tooltip.inContact = false; + if (series && + series.onMouseOut) { + series.onMouseOut(); + } + }; + if (!this.label) { + if (this.outside) { + /** + * Reference to the tooltip's container, when + * [Highcharts.Tooltip#outside] is set to true, otherwise + * it's undefined. + * + * @name Highcharts.Tooltip#container + * @type {Highcharts.HTMLDOMElement|undefined} + */ + this.container = container = H.doc.createElement('div'); + container.className = 'highcharts-tooltip-container'; + css(container, { + position: 'absolute', + top: '1px', + pointerEvents: pointerEvents, + zIndex: 3 + }); + H.doc.body.appendChild(container); + /** + * Reference to the tooltip's renderer, when + * [Highcharts.Tooltip#outside] is set to true, otherwise + * it's undefined. + * + * @name Highcharts.Tooltip#renderer + * @type {Highcharts.SVGRenderer|undefined} + */ + this.renderer = renderer = new H.Renderer(container, 0, 0, (_b = this.chart.options.chart) === null || _b === void 0 ? void 0 : _b.style, void 0, void 0, renderer.styledMode); + } + // Create the label + if (this.split) { + this.label = renderer.g(className); + } + else { + this.label = renderer + .label('', 0, 0, options.shape || 'callout', null, null, options.useHTML, null, className) + .attr({ + padding: options.padding, + r: options.borderRadius + }); + if (!styledMode) { + this.label + .attr({ + fill: options.backgroundColor, + 'stroke-width': options.borderWidth + }) + // #2301, #2657 + .css(options.style) + .css({ pointerEvents: pointerEvents }) + .shadow(options.shadow); + } + } + if (styledMode) { + // Apply the drop-shadow filter + this.applyFilter(); + this.label.addClass('highcharts-tooltip-' + this.chart.index); + } + // Split tooltip use updateTooltipContainer to position the tooltip + // container. + if (tooltip.outside && !tooltip.split) { + set = { + x: this.label.xSetter, + y: this.label.ySetter + }; + this.label.xSetter = function (value, key) { + set[key].call(this.label, tooltip.distance); + container.style.left = value + 'px'; + }; + this.label.ySetter = function (value, key) { + set[key].call(this.label, tooltip.distance); + container.style.top = value + 'px'; + }; + } + this.label + .on('mouseenter', onMouseEnter) + .on('mouseleave', onMouseLeave) + .attr({ zIndex: 8 }) + .add(); + } + return this.label; + }; + /** + * Place the tooltip in a chart without spilling over + * and not covering the point it self. + * + * @private + * @function Highcharts.Tooltip#getPosition + * + * @param {number} boxWidth + * + * @param {number} boxHeight + * + * @param {Highcharts.Point} point + * + * @return {Highcharts.PositionObject} + */ + Tooltip.prototype.getPosition = function (boxWidth, boxHeight, point) { + var chart = this.chart, distance = this.distance, ret = {}, + // Don't use h if chart isn't inverted (#7242) ??? + h = (chart.inverted && point.h) || 0, // #4117 ??? + swapped, outside = this.outside, outerWidth = outside ? + // substract distance to prevent scrollbars + doc.documentElement.clientWidth - 2 * distance : + chart.chartWidth, outerHeight = outside ? + Math.max(doc.body.scrollHeight, doc.documentElement.scrollHeight, doc.body.offsetHeight, doc.documentElement.offsetHeight, doc.documentElement.clientHeight) : + chart.chartHeight, chartPosition = chart.pointer.getChartPosition(), containerScaling = chart.containerScaling, scaleX = function (val) { return ( // eslint-disable-line no-confusing-arrow + containerScaling ? val * containerScaling.scaleX : val); }, scaleY = function (val) { return ( // eslint-disable-line no-confusing-arrow + containerScaling ? val * containerScaling.scaleY : val); }, + // Build parameter arrays for firstDimension()/secondDimension() + buildDimensionArray = function (dim) { + var isX = dim === 'x'; + return [ + dim, + isX ? outerWidth : outerHeight, + isX ? boxWidth : boxHeight + ].concat(outside ? [ + // If we are using tooltip.outside, we need to scale the + // position to match scaling of the container in case there + // is a transform/zoom on the container. #11329 + isX ? scaleX(boxWidth) : scaleY(boxHeight), + isX ? chartPosition.left - distance + + scaleX(point.plotX + chart.plotLeft) : + chartPosition.top - distance + + scaleY(point.plotY + chart.plotTop), + 0, + isX ? outerWidth : outerHeight + ] : [ + // Not outside, no scaling is needed + isX ? boxWidth : boxHeight, + isX ? point.plotX + chart.plotLeft : + point.plotY + chart.plotTop, + isX ? chart.plotLeft : chart.plotTop, + isX ? chart.plotLeft + chart.plotWidth : + chart.plotTop + chart.plotHeight + ]); + }, first = buildDimensionArray('y'), second = buildDimensionArray('x'), + // The far side is right or bottom + preferFarSide = !this.followPointer && pick(point.ttBelow, !chart.inverted === !!point.negative), // #4984 + /* + * Handle the preferred dimension. When the preferred dimension is + * tooltip on top or bottom of the point, it will look for space + * there. + * + * @private + */ + firstDimension = function (dim, outerSize, innerSize, scaledInnerSize, // #11329 + point, min, max) { + var scaledDist = dim === 'y' ? + scaleY(distance) : scaleX(distance), scaleDiff = (innerSize - scaledInnerSize) / 2, roomLeft = scaledInnerSize < point - distance, roomRight = point + distance + scaledInnerSize < outerSize, alignedLeft = point - scaledDist - innerSize + scaleDiff, alignedRight = point + scaledDist - scaleDiff; + if (preferFarSide && roomRight) { + ret[dim] = alignedRight; + } + else if (!preferFarSide && roomLeft) { + ret[dim] = alignedLeft; + } + else if (roomLeft) { + ret[dim] = Math.min(max - scaledInnerSize, alignedLeft - h < 0 ? alignedLeft : alignedLeft - h); + } + else if (roomRight) { + ret[dim] = Math.max(min, alignedRight + h + innerSize > outerSize ? + alignedRight : + alignedRight + h); + } + else { + return false; + } + }, + /* + * Handle the secondary dimension. If the preferred dimension is + * tooltip on top or bottom of the point, the second dimension is to + * align the tooltip above the point, trying to align center but + * allowing left or right align within the chart box. + * + * @private + */ + secondDimension = function (dim, outerSize, innerSize, scaledInnerSize, // #11329 + point) { + var retVal; + // Too close to the edge, return false and swap dimensions + if (point < distance || point > outerSize - distance) { + retVal = false; + // Align left/top + } + else if (point < innerSize / 2) { + ret[dim] = 1; + // Align right/bottom + } + else if (point > outerSize - scaledInnerSize / 2) { + ret[dim] = outerSize - scaledInnerSize - 2; + // Align center + } + else { + ret[dim] = point - innerSize / 2; + } + return retVal; + }, + /* + * Swap the dimensions + */ + swap = function (count) { + var temp = first; + first = second; + second = temp; + swapped = count; + }, run = function () { + if (firstDimension.apply(0, first) !== false) { + if (secondDimension.apply(0, second) === false && + !swapped) { + swap(true); + run(); + } + } + else if (!swapped) { + swap(true); + run(); + } + else { + ret.x = ret.y = 0; + } + }; + // Under these conditions, prefer the tooltip on the side of the point + if (chart.inverted || this.len > 1) { + swap(); + } + run(); + return ret; + }; + /** + * Get the best X date format based on the closest point range on the axis. + * + * @private + * @function Highcharts.Tooltip#getXDateFormat + * + * @param {Highcharts.Point} point + * + * @param {Highcharts.TooltipOptions} options + * + * @param {Highcharts.Axis} xAxis + * + * @return {string} + */ + Tooltip.prototype.getXDateFormat = function (point, options, xAxis) { + var xDateFormat, dateTimeLabelFormats = options.dateTimeLabelFormats, closestPointRange = xAxis && xAxis.closestPointRange; + if (closestPointRange) { + xDateFormat = this.getDateFormat(closestPointRange, point.x, xAxis.options.startOfWeek, dateTimeLabelFormats); + } + else { + xDateFormat = dateTimeLabelFormats.day; + } + return xDateFormat || dateTimeLabelFormats.year; // #2546, 2581 + }; + /** + * Hides the tooltip with a fade out animation. + * + * @function Highcharts.Tooltip#hide + * + * @param {number} [delay] + * The fade out in milliseconds. If no value is provided the value + * of the tooltip.hideDelay option is used. A value of 0 disables + * the fade out animation. + */ + Tooltip.prototype.hide = function (delay) { + var tooltip = this; + // disallow duplicate timers (#1728, #1766) + U.clearTimeout(this.hideTimer); + delay = pick(delay, this.options.hideDelay, 500); + if (!this.isHidden) { + this.hideTimer = syncTimeout(function () { + // If there is a delay, do fadeOut with the default duration. If + // the hideDelay is 0, we assume no animation is wanted, so we + // pass 0 duration. #12994. + tooltip.getLabel().fadeOut(delay ? void 0 : delay); + tooltip.isHidden = true; + }, delay); + } + }; + /** + * @private + * @function Highcharts.Tooltip#init + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @param {Highcharts.TooltipOptions} options + * Tooltip options. + */ + Tooltip.prototype.init = function (chart, options) { + /** + * Chart of the tooltip. + * + * @readonly + * @name Highcharts.Tooltip#chart + * @type {Highcharts.Chart} + */ + this.chart = chart; + /** + * Used tooltip options. + * + * @readonly + * @name Highcharts.Tooltip#options + * @type {Highcharts.TooltipOptions} + */ + this.options = options; + /** + * List of crosshairs. + * + * @private + * @readonly + * @name Highcharts.Tooltip#crosshairs + * @type {Array} + */ + this.crosshairs = []; + /** + * Current values of x and y when animating. + * + * @private + * @readonly + * @name Highcharts.Tooltip#now + * @type {Highcharts.PositionObject} + */ + this.now = { x: 0, y: 0 }; + /** + * Tooltips are initially hidden. + * + * @private + * @readonly + * @name Highcharts.Tooltip#isHidden + * @type {boolean} + */ + this.isHidden = true; + /** + * True, if the tooltip is split into one label per series, with the + * header close to the axis. + * + * @readonly + * @name Highcharts.Tooltip#split + * @type {boolean|undefined} + */ + this.split = options.split && !chart.inverted && !chart.polar; + /** + * When the tooltip is shared, the entire plot area will capture mouse + * movement or touch events. + * + * @readonly + * @name Highcharts.Tooltip#shared + * @type {boolean|undefined} + */ + this.shared = options.shared || this.split; + /** + * Whether to allow the tooltip to render outside the chart's SVG + * element box. By default (false), the tooltip is rendered within the + * chart's SVG element, which results in the tooltip being aligned + * inside the chart area. + * + * @readonly + * @name Highcharts.Tooltip#outside + * @type {boolean} + * + * @todo + * Split tooltip does not support outside in the first iteration. Should + * not be too complicated to implement. + */ + this.outside = pick(options.outside, Boolean(chart.scrollablePixelsX || chart.scrollablePixelsY)); + }; + /** + * Returns true, if the pointer is in contact with the tooltip tracker. + */ + Tooltip.prototype.isStickyOnContact = function () { + return !!(!this.followPointer && + this.options.stickOnContact && + this.inContact); + }; + /** + * Moves the tooltip with a soft animation to a new position. + * + * @private + * @function Highcharts.Tooltip#move + * + * @param {number} x + * + * @param {number} y + * + * @param {number} anchorX + * + * @param {number} anchorY + */ + Tooltip.prototype.move = function (x, y, anchorX, anchorY) { + var tooltip = this, now = tooltip.now, animate = tooltip.options.animation !== false && + !tooltip.isHidden && + // When we get close to the target position, abort animation and + // land on the right place (#3056) + (Math.abs(x - now.x) > 1 || Math.abs(y - now.y) > 1), skipAnchor = tooltip.followPointer || tooltip.len > 1; + // Get intermediate values for animation + extend(now, { + x: animate ? (2 * now.x + x) / 3 : x, + y: animate ? (now.y + y) / 2 : y, + anchorX: skipAnchor ? + void 0 : + animate ? (2 * now.anchorX + anchorX) / 3 : anchorX, + anchorY: skipAnchor ? + void 0 : + animate ? (now.anchorY + anchorY) / 2 : anchorY + }); + // Move to the intermediate value + tooltip.getLabel().attr(now); + tooltip.drawTracker(); + // Run on next tick of the mouse tracker + if (animate) { + // Never allow two timeouts + U.clearTimeout(this.tooltipTimeout); + // Set the fixed interval ticking for the smooth tooltip + this.tooltipTimeout = setTimeout(function () { + // The interval function may still be running during destroy, + // so check that the chart is really there before calling. + if (tooltip) { + tooltip.move(x, y, anchorX, anchorY); + } + }, 32); + } + }; + /** + * Refresh the tooltip's text and position. + * + * @function Highcharts.Tooltip#refresh + * + * @param {Highcharts.Point|Array} pointOrPoints + * Either a point or an array of points. + * + * @param {Highcharts.PointerEventObject} [mouseEvent] + * Mouse event, that is responsible for the refresh and should be + * used for the tooltip update. + */ + Tooltip.prototype.refresh = function (pointOrPoints, mouseEvent) { + var tooltip = this, chart = this.chart, options = tooltip.options, x, y, point = pointOrPoints, anchor, textConfig = {}, text, pointConfig = [], formatter = options.formatter || tooltip.defaultFormatter, shared = tooltip.shared, currentSeries, styledMode = chart.styledMode; + if (!options.enabled) { + return; + } + U.clearTimeout(this.hideTimer); + // get the reference point coordinates (pie charts use tooltipPos) + tooltip.followPointer = splat(point)[0].series.tooltipOptions + .followPointer; + anchor = tooltip.getAnchor(point, mouseEvent); + x = anchor[0]; + y = anchor[1]; + // shared tooltip, array is sent over + if (shared && + !(point.series && + point.series.noSharedTooltip)) { + chart.pointer.applyInactiveState(point); + // Now set hover state for the choosen ones: + point.forEach(function (item) { + item.setState('hover'); + pointConfig.push(item.getLabelConfig()); + }); + textConfig = { + x: point[0].category, + y: point[0].y + }; + textConfig.points = pointConfig; + point = point[0]; + // single point tooltip + } + else { + textConfig = point.getLabelConfig(); + } + this.len = pointConfig.length; // #6128 + text = formatter.call(textConfig, tooltip); + // register the current series + currentSeries = point.series; + this.distance = pick(currentSeries.tooltipOptions.distance, 16); + // update the inner HTML + if (text === false) { + this.hide(); + } + else { + // update text + if (tooltip.split) { + this.renderSplit(text, splat(pointOrPoints)); + } + else { + var label = tooltip.getLabel(); + // Prevent the tooltip from flowing over the chart box (#6659) + if (!options.style.width || styledMode) { + label.css({ + width: this.chart.spacingBox.width + 'px' + }); + } + label.attr({ + text: text && text.join ? + text.join('') : + text + }); + // Set the stroke color of the box to reflect the point + label.removeClass(/highcharts-color-[\d]+/g) + .addClass('highcharts-color-' + + pick(point.colorIndex, currentSeries.colorIndex)); + if (!styledMode) { + label.attr({ + stroke: (options.borderColor || + point.color || + currentSeries.color || + '#666666') + }); + } + tooltip.updatePosition({ + plotX: x, + plotY: y, + negative: point.negative, + ttBelow: point.ttBelow, + h: anchor[2] || 0 + }); + } + // show it + if (tooltip.isHidden && tooltip.label) { + tooltip.label.attr({ + opacity: 1 + }).show(); + } + tooltip.isHidden = false; + } + fireEvent(this, 'refresh'); + }; + /** + * Render the split tooltip. Loops over each point's text and adds + * a label next to the point, then uses the distribute function to + * find best non-overlapping positions. + * + * @private + * @function Highcharts.Tooltip#renderSplit + * + * @param {string|Array<(boolean|string)>} labels + * + * @param {Array} points + */ + Tooltip.prototype.renderSplit = function (labels, points) { + var tooltip = this; + var chart = tooltip.chart, _a = tooltip.chart, chartWidth = _a.chartWidth, chartHeight = _a.chartHeight, plotHeight = _a.plotHeight, plotLeft = _a.plotLeft, plotTop = _a.plotTop, pointer = _a.pointer, ren = _a.renderer, _b = _a.scrollablePixelsY, scrollablePixelsY = _b === void 0 ? 0 : _b, _c = _a.scrollingContainer, _d = _c === void 0 ? { scrollLeft: 0, scrollTop: 0 } : _c, scrollLeft = _d.scrollLeft, scrollTop = _d.scrollTop, styledMode = _a.styledMode, distance = tooltip.distance, options = tooltip.options, positioner = tooltip.options.positioner; + // The area which the tooltip should be limited to. Limit to scrollable + // plot area if enabled, otherwise limit to the chart container. + var bounds = { + left: scrollLeft, + right: scrollLeft + chartWidth, + top: scrollTop, + bottom: scrollTop + chartHeight + }; + var tooltipLabel = tooltip.getLabel(); + var headerTop = Boolean(chart.xAxis[0] && chart.xAxis[0].opposite); + var distributionBoxTop = plotTop + scrollTop; + var headerHeight = 0; + var adjustedPlotHeight = plotHeight - scrollablePixelsY; + /** + * Calculates the anchor position for the partial tooltip + * + * @private + * @param {Highcharts.Point} point The point related to the tooltip + * @return {object} Returns an object with anchorX and anchorY + */ + function getAnchor(point) { + var isHeader = point.isHeader, _a = point.plotX, plotX = _a === void 0 ? 0 : _a, _b = point.plotY, plotY = _b === void 0 ? 0 : _b, series = point.series; + var anchorX; + var anchorY; + if (isHeader) { + // Set anchorX to plotX + anchorX = plotLeft + plotX; + // Set anchorY to center of visible plot area. + anchorY = plotTop + plotHeight / 2; + } + else { + var xAxis = series.xAxis, yAxis = series.yAxis; + // Set anchorX to plotX. Limit to within xAxis. + anchorX = xAxis.pos + clamp(plotX, -distance, xAxis.len + distance); + // Set anchorY, limit to the scrollable plot area + if (yAxis.pos + plotY >= scrollTop + plotTop && + yAxis.pos + plotY <= scrollTop + plotTop + plotHeight - scrollablePixelsY) { + anchorY = yAxis.pos + plotY; + } + } + // Limit values to plot area + anchorX = clamp(anchorX, bounds.left - distance, bounds.right + distance); + return { anchorX: anchorX, anchorY: anchorY }; + } + /** + * Calculates the position of the partial tooltip + * + * @private + * @param {number} anchorX The partial tooltip anchor x position + * @param {number} anchorY The partial tooltip anchor y position + * @param {boolean} isHeader Whether the partial tooltip is a header + * @param {number} boxWidth Width of the partial tooltip + * @return {Highcharts.PositionObject} Returns the partial tooltip x and + * y position + */ + function defaultPositioner(anchorX, anchorY, isHeader, boxWidth, alignedLeft) { + if (alignedLeft === void 0) { alignedLeft = true; } + var y; + var x; + if (isHeader) { + y = headerTop ? 0 : adjustedPlotHeight; + x = clamp(anchorX - (boxWidth / 2), bounds.left, bounds.right - boxWidth); + } + else { + y = anchorY - distributionBoxTop; + x = alignedLeft ? + anchorX - boxWidth - distance : + anchorX + distance; + x = clamp(x, alignedLeft ? x : bounds.left, bounds.right); + } + // NOTE: y is relative to distributionBoxTop + return { x: x, y: y }; + } + /** + * Updates the attributes and styling of the partial tooltip. Creates a + * new partial tooltip if it does not exists. + * + * @private + * @param {Highcharts.SVGElement|undefined} partialTooltip + * The partial tooltip to update + * @param {Highcharts.Point} point + * The point related to the partial tooltip + * @param {boolean|string} str The text for the partial tooltip + * @return {Highcharts.SVGElement} Returns the updated partial tooltip + */ + function updatePartialTooltip(partialTooltip, point, str) { + var tt = partialTooltip; + var isHeader = point.isHeader, series = point.series; + var colorClass = 'highcharts-color-' + pick(point.colorIndex, series.colorIndex, 'none'); + if (!tt) { + var attribs = { + padding: options.padding, + r: options.borderRadius + }; + if (!styledMode) { + attribs.fill = options.backgroundColor; + attribs['stroke-width'] = options.borderWidth; + } + tt = ren + .label('', 0, 0, (options[isHeader ? 'headerShape' : 'shape']) || + 'callout', void 0, void 0, options.useHTML) + .addClass((isHeader ? 'highcharts-tooltip-header ' : '') + + 'highcharts-tooltip-box ' + + colorClass) + .attr(attribs) + .add(tooltipLabel); + } + tt.isActive = true; + tt.attr({ + text: str + }); + if (!styledMode) { + tt.css(options.style) + .shadow(options.shadow) + .attr({ + stroke: (options.borderColor || + point.color || + series.color || + '#333333') + }); + } + return tt; + } + // Graceful degradation for legacy formatters + if (isString(labels)) { + labels = [false, labels]; + } + // Create the individual labels for header and points, ignore footer + var boxes = labels.slice(0, points.length + 1).reduce(function (boxes, str, i) { + if (str !== false && str !== '') { + var point = points[i - 1] || { + // Item 0 is the header. Instead of this, we could also + // use the crosshair label + isHeader: true, + plotX: points[0].plotX, + plotY: plotHeight, + series: {} + }; + var isHeader = point.isHeader; + // Store the tooltip label referance on the series + var owner = isHeader ? tooltip : point.series; + var tt = owner.tt = updatePartialTooltip(owner.tt, point, str); + // Get X position now, so we can move all to the other side in + // case of overflow + var bBox = tt.getBBox(); + var boxWidth = bBox.width + tt.strokeWidth(); + if (isHeader) { + headerHeight = bBox.height; + adjustedPlotHeight += headerHeight; + if (headerTop) { + distributionBoxTop -= headerHeight; + } + } + var _a = getAnchor(point), anchorX = _a.anchorX, anchorY = _a.anchorY; + if (typeof anchorY === 'number') { + var size = bBox.height + 1; + var boxPosition = positioner ? positioner.call(tooltip, boxWidth, size, point) : defaultPositioner(anchorX, anchorY, isHeader, boxWidth); + boxes.push({ + // 0-align to the top, 1-align to the bottom + align: positioner ? 0 : void 0, + anchorX: anchorX, + anchorY: anchorY, + boxWidth: boxWidth, + point: point, + rank: pick(boxPosition.rank, isHeader ? 1 : 0), + size: size, + target: boxPosition.y, + tt: tt, + x: boxPosition.x + }); + } + else { + // Hide tooltips which anchorY is outside the visible plot + // area + tt.isActive = false; + } + } + return boxes; + }, []); + // If overflow left then align all labels to the right + if (!positioner && boxes.some(function (box) { return box.x < bounds.left; })) { + boxes = boxes.map(function (box) { + var _a = defaultPositioner(box.anchorX, box.anchorY, box.point.isHeader, box.boxWidth, false), x = _a.x, y = _a.y; + return extend(box, { + target: y, + x: x + }); + }); + } + // Clean previous run (for missing points) + tooltip.cleanSplit(); + // Distribute and put in place + H.distribute(boxes, adjustedPlotHeight); + boxes.forEach(function (box) { + var anchorX = box.anchorX, anchorY = box.anchorY, pos = box.pos, x = box.x; + // Put the label in place + box.tt.attr({ + visibility: typeof pos === 'undefined' ? 'hidden' : 'inherit', + x: x, + /* NOTE: y should equal pos to be consistent with !split + * tooltip, but is currently relative to plotTop. Is left as is + * to avoid breaking change. Remove distributionBoxTop to make + * it consistent. + */ + y: pos + distributionBoxTop, + anchorX: anchorX, + anchorY: anchorY + }); + }); + /* If we have a seperate tooltip container, then update the necessary + * container properties. + * Test that tooltip has its own container and renderer before executing + * the operation. + */ + var container = tooltip.container, outside = tooltip.outside, renderer = tooltip.renderer; + if (outside && container && renderer) { + // Set container size to fit the tooltip + var _e = tooltipLabel.getBBox(), width = _e.width, height = _e.height, x = _e.x, y = _e.y; + renderer.setSize(width + x, height + y, false); + // Position the tooltip container to the chart container + var chartPosition = pointer.getChartPosition(); + container.style.left = chartPosition.left + 'px'; + container.style.top = chartPosition.top + 'px'; + } + }; + /** + * If the `stickOnContact` option is active, this will add a tracker shape. + * + * @private + * @function Highcharts.Tooltip#drawTracker + */ + Tooltip.prototype.drawTracker = function () { + var tooltip = this; + if (tooltip.followPointer || + !tooltip.options.stickOnContact) { + if (tooltip.tracker) { + tooltip.tracker.destroy(); + } + return; + } + var chart = tooltip.chart; + var label = tooltip.label; + var point = chart.hoverPoint; + if (!label || !point) { + return; + } + var box = { + x: 0, + y: 0, + width: 0, + height: 0 + }; + // Combine anchor and tooltip + var anchorPos = this.getAnchor(point); + var labelBBox = label.getBBox(); + anchorPos[0] += chart.plotLeft - label.translateX; + anchorPos[1] += chart.plotTop - label.translateY; + // When the mouse pointer is between the anchor point and the label, + // the label should stick. + box.x = Math.min(0, anchorPos[0]); + box.y = Math.min(0, anchorPos[1]); + box.width = (anchorPos[0] < 0 ? + Math.max(Math.abs(anchorPos[0]), (labelBBox.width - anchorPos[0])) : + Math.max(Math.abs(anchorPos[0]), labelBBox.width)); + box.height = (anchorPos[1] < 0 ? + Math.max(Math.abs(anchorPos[1]), (labelBBox.height - Math.abs(anchorPos[1]))) : + Math.max(Math.abs(anchorPos[1]), labelBBox.height)); + if (tooltip.tracker) { + tooltip.tracker.attr(box); + } + else { + tooltip.tracker = label.renderer + .rect(box) + .addClass('highcharts-tracker') + .add(label); + if (!chart.styledMode) { + tooltip.tracker.attr({ + fill: 'rgba(0,0,0,0)' + }); + } + } + }; + /** + * @private + */ + Tooltip.prototype.styledModeFormat = function (formatString) { + return formatString + .replace('style="font-size: 10px"', 'class="highcharts-header"') + .replace(/style="color:{(point|series)\.color}"/g, 'class="highcharts-color-{$1.colorIndex}"'); + }; + /** + * Format the footer/header of the tooltip + * #3397: abstraction to enable formatting of footer and header + * + * @private + * @function Highcharts.Tooltip#tooltipFooterHeaderFormatter + * @param {Highcharts.PointLabelObject} labelConfig + * @param {boolean} [isFooter] + * @return {string} + */ + Tooltip.prototype.tooltipFooterHeaderFormatter = function (labelConfig, isFooter) { + var footOrHead = isFooter ? 'footer' : 'header', series = labelConfig.series, tooltipOptions = series.tooltipOptions, xDateFormat = tooltipOptions.xDateFormat, xAxis = series.xAxis, isDateTime = (xAxis && + xAxis.options.type === 'datetime' && + isNumber(labelConfig.key)), formatString = tooltipOptions[footOrHead + 'Format'], e = { + isFooter: isFooter, + labelConfig: labelConfig + }; + fireEvent(this, 'headerFormatter', e, function (e) { + // Guess the best date format based on the closest point distance + // (#568, #3418) + if (isDateTime && !xDateFormat) { + xDateFormat = this.getXDateFormat(labelConfig, tooltipOptions, xAxis); + } + // Insert the footer date format if any + if (isDateTime && xDateFormat) { + ((labelConfig.point && labelConfig.point.tooltipDateKeys) || + ['key']).forEach(function (key) { + formatString = formatString.replace('{point.' + key + '}', '{point.' + key + ':' + xDateFormat + '}'); + }); + } + // Replace default header style with class name + if (series.chart.styledMode) { + formatString = this.styledModeFormat(formatString); + } + e.text = format(formatString, { + point: labelConfig, + series: series + }, this.chart); + }); + return e.text; + }; + /** + * Updates the tooltip with the provided tooltip options. + * + * @function Highcharts.Tooltip#update + * + * @param {Highcharts.TooltipOptions} options + * The tooltip options to update. + */ + Tooltip.prototype.update = function (options) { + this.destroy(); + // Update user options (#6218) + merge(true, this.chart.options.tooltip.userOptions, options); + this.init(this.chart, merge(true, this.options, options)); + }; + /** + * Find the new position and perform the move + * + * @private + * @function Highcharts.Tooltip#updatePosition + * + * @param {Highcharts.Point} point + */ + Tooltip.prototype.updatePosition = function (point) { + var chart = this.chart, pointer = chart.pointer, label = this.getLabel(), pos, anchorX = point.plotX + chart.plotLeft, anchorY = point.plotY + chart.plotTop, pad; + // Needed for outside: true (#11688) + var chartPosition = pointer.getChartPosition(); + pos = (this.options.positioner || this.getPosition).call(this, label.width, label.height, point); + // Set the renderer size dynamically to prevent document size to change + if (this.outside) { + pad = (this.options.borderWidth || 0) + 2 * this.distance; + this.renderer.setSize(label.width + pad, label.height + pad, false); + // Anchor and tooltip container need scaling if chart container has + // scale transform/css zoom. #11329. + var containerScaling = chart.containerScaling; + if (containerScaling) { + css(this.container, { + transform: "scale(" + containerScaling.scaleX + ", " + containerScaling.scaleY + ")" + }); + anchorX *= containerScaling.scaleX; + anchorY *= containerScaling.scaleY; + } + anchorX += chartPosition.left - pos.x; + anchorY += chartPosition.top - pos.y; + } + // do the move + this.move(Math.round(pos.x), Math.round(pos.y || 0), // can be undefined (#3977) + anchorX, anchorY); + }; + return Tooltip; +}()); +H.Tooltip = Tooltip; +export default H.Tooltip; diff --git a/librerias/gantt/code/es-modules/parts/Utilities.js b/librerias/gantt/code/es-modules/parts/Utilities.js new file mode 100644 index 0000000..a2bf667 --- /dev/null +++ b/librerias/gantt/code/es-modules/parts/Utilities.js @@ -0,0 +1,2562 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import H from './Globals.js'; +/** + * An animation configuration. Animation configurations can also be defined as + * booleans, where `false` turns off animation and `true` defaults to a duration + * of 500ms. + * + * @interface Highcharts.AnimationOptionsObject + */ /** +* A callback function to exectute when the animation finishes. +* @name Highcharts.AnimationOptionsObject#complete +* @type {Function|undefined} +*/ /** +* The animation duration in milliseconds. +* @name Highcharts.AnimationOptionsObject#duration +* @type {number|undefined} +*/ /** +* The name of an easing function as defined on the `Math` object. +* @name Highcharts.AnimationOptionsObject#easing +* @type {string|Function|undefined} +*/ /** +* A callback function to execute on each step of each attribute or CSS property +* that's being animated. The first argument contains information about the +* animation and progress. +* @name Highcharts.AnimationOptionsObject#step +* @type {Function|undefined} +*/ +/** + * Creates a frame for the animated SVG element. + * + * @callback Highcharts.AnimationStepCallbackFunction + * + * @param {Highcharts.SVGElement} this + * The SVG element to animate. + * + * @return {void} + */ +/** + * Interface description for a class. + * + * @interface Highcharts.Class + * @extends Function + */ /** +* Class costructor. +* @function Highcharts.Class#new +* @param {...Array<*>} args +* Constructor arguments. +* @return {T} +* Class instance. +*/ +/** + * A style object with camel case property names to define visual appearance of + * a SVG element or HTML element. The properties can be whatever styles are + * supported on the given SVG or HTML element. + * + * @example + * { + * fontFamily: 'monospace', + * fontSize: '1.2em' + * } + * + * @interface Highcharts.CSSObject + */ /** +* @name Highcharts.CSSObject#[key:string] +* @type {boolean|number|string|undefined} +*/ /** +* Background style for the element. +* @name Highcharts.CSSObject#background +* @type {string|undefined} +*/ /** +* Background color of the element. +* @name Highcharts.CSSObject#backgroundColor +* @type {Highcharts.ColorString|undefined} +*/ /** +* Border style for the element. +* @name Highcharts.CSSObject#border +* @type {string|undefined} +*/ /** +* Radius of the element border. +* @name Highcharts.CSSObject#borderRadius +* @type {number|undefined} +*/ /** +* Color used in the element. The 'contrast' option is a Highcharts custom +* property that results in black or white, depending on the background of the +* element. +* @name Highcharts.CSSObject#color +* @type {'contrast'|Highcharts.ColorString|undefined} +*/ /** +* Style of the mouse cursor when resting over the element. +* @name Highcharts.CSSObject#cursor +* @type {Highcharts.CursorValue|undefined} +*/ /** +* Font family of the element text. Multiple values have to be in decreasing +* preference order and separated by comma. +* @name Highcharts.CSSObject#fontFamily +* @type {string|undefined} +*/ /** +* Font size of the element text. +* @name Highcharts.CSSObject#fontSize +* @type {string|undefined} +*/ /** +* Font weight of the element text. +* @name Highcharts.CSSObject#fontWeight +* @type {string|undefined} +*/ /** +* Height of the element. +* @name Highcharts.CSSObject#height +* @type {number|undefined} +*/ /** +* Width of the element border. +* @name Highcharts.CSSObject#lineWidth +* @type {number|undefined} +*/ /** +* Opacity of the element. +* @name Highcharts.CSSObject#opacity +* @type {number|undefined} +*/ /** +* Space around the element content. +* @name Highcharts.CSSObject#padding +* @type {string|undefined} +*/ /** +* Behaviour of the element when the mouse cursor rests over it. +* @name Highcharts.CSSObject#pointerEvents +* @type {string|undefined} +*/ /** +* Positioning of the element. +* @name Highcharts.CSSObject#position +* @type {string|undefined} +*/ /** +* Alignment of the element text. +* @name Highcharts.CSSObject#textAlign +* @type {string|undefined} +*/ /** +* Additional decoration of the element text. +* @name Highcharts.CSSObject#textDecoration +* @type {string|undefined} +*/ /** +* Outline style of the element text. +* @name Highcharts.CSSObject#textOutline +* @type {string|undefined} +*/ /** +* Line break style of the element text. Highcharts SVG elements support +* `ellipsis` when a `width` is set. +* @name Highcharts.CSSObject#textOverflow +* @type {string|undefined} +*/ /** +* Top spacing of the element relative to the parent element. +* @name Highcharts.CSSObject#top +* @type {string|undefined} +*/ /** +* Animated transition of selected element properties. +* @name Highcharts.CSSObject#transition +* @type {string|undefined} +*/ /** +* Line break style of the element text. +* @name Highcharts.CSSObject#whiteSpace +* @type {string|undefined} +*/ /** +* Width of the element. +* @name Highcharts.CSSObject#width +* @type {number|undefined} +*/ +/** + * All possible cursor styles. + * + * @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 + */ +/** + * All possible dash styles. + * + * @typedef {'Dash'|'DashDot'|'Dot'|'LongDash'|'LongDashDot'|'LongDashDotDot'|'ShortDash'|'ShortDashDot'|'ShortDashDotDot'|'ShortDot'|'Solid'} Highcharts.DashStyleValue + */ +/** + * Generic dictionary in TypeScript notation. + * + * @interface Highcharts.Dictionary + */ /** +* @name Highcharts.Dictionary#[key:string] +* @type {T} +*/ +/** + * The function callback to execute when the event is fired. The `this` context + * contains the instance, that fired the event. + * + * @callback Highcharts.EventCallbackFunction + * + * @param {T} this + * + * @param {Highcharts.Dictionary<*>|Event} [eventArguments] + * Event arguments. + * + * @return {boolean|void} + */ +/** + * The event options for adding function callback. + * + * @interface Highcharts.EventOptionsObject + */ /** +* The order the event handler should be called. This opens for having one +* handler be called before another, independent of in which order they were +* added. +* @name Highcharts.EventOptionsObject#order +* @type {number} +*/ +/** + * Formats data as a string. Usually the data is accessible throught the `this` + * keyword. + * + * @callback Highcharts.FormatterCallbackFunction + * + * @param {T} this + * Context to format + * + * @return {string} + * Formatted text + */ +/** + * An object of key-value pairs for HTML attributes. + * + * @typedef {Highcharts.Dictionary} Highcharts.HTMLAttributes + */ +/** + * An HTML DOM element. The type is a reference to the regular HTMLElement in + * the global scope. + * + * @typedef {global.HTMLElement} Highcharts.HTMLDOMElement + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement + */ +/** + * The iterator callback. + * + * @callback Highcharts.ObjectEachCallbackFunction + * + * @param {T} this + * The context. + * + * @param {*} value + * The property value. + * + * @param {string} key + * The property key. + * + * @param {*} obj + * The object that objectEach is being applied to. + */ +/** + * An object containing `left` and `top` properties for the position in the + * page. + * + * @interface Highcharts.OffsetObject + */ /** +* Left distance to the page border. +* @name Highcharts.OffsetObject#left +* @type {number} +*/ /** +* Top distance to the page border. +* @name Highcharts.OffsetObject#top +* @type {number} +*/ +/** + * Describes a range. + * + * @interface Highcharts.RangeObject + */ /** +* Maximum number of the range. +* @name Highcharts.RangeObject#max +* @type {number} +*/ /** +* Minimum number of the range. +* @name Highcharts.RangeObject#min +* @type {number} +*/ +/** + * If a number is given, it defines the pixel length. If a percentage string is + * given, like for example `'50%'`, the setting defines a length relative to a + * base size, for example the size of a container. + * + * @typedef {number|string} Highcharts.RelativeSize + */ +/** + * Proceed function to call original (wrapped) function. + * + * @callback Highcharts.WrapProceedFunction + * + * @param {*} [arg1] + * Optional argument. Without any arguments defaults to first argument of + * the wrapping function. + * + * @param {*} [arg2] + * Optional argument. Without any arguments defaults to second argument + * of the wrapping function. + * + * @param {*} [arg3] + * Optional argument. Without any arguments defaults to third argument of + * the wrapping function. + * + * @return {*} + * Return value of the original function. + */ +/** + * The Highcharts object is the placeholder for all other members, and various + * utility functions. The most important member of the namespace would be the + * chart constructor. + * + * @example + * var chart = Highcharts.chart('container', { ... }); + * + * @namespace Highcharts + */ +H.timers = []; +var charts = H.charts, doc = H.doc, win = H.win; +/** + * Provide error messages for debugging, with links to online explanation. This + * function can be overridden to provide custom error handling. + * + * @sample highcharts/chart/highcharts-error/ + * Custom error handler + * + * @function Highcharts.error + * + * @param {number|string} code + * The error code. See + * [errors.xml](https://github.com/highcharts/highcharts/blob/master/errors/errors.xml) + * for available codes. If it is a string, the error message is printed + * directly in the console. + * + * @param {boolean} [stop=false] + * Whether to throw an error or just log a warning in the console. + * + * @param {Highcharts.Chart} [chart] + * Reference to the chart that causes the error. Used in 'debugger' + * module to display errors directly on the chart. + * Important note: This argument is undefined for errors that lack + * access to the Chart instance. + * + * @param {Highcharts.Dictionary} [params] + * Additional parameters for the generated message. + * + * @return {void} + */ +var error = H.error = function (code, stop, chart, params) { + var isCode = isNumber(code), message = isCode ? + "Highcharts error #" + code + ": www.highcharts.com/errors/" + code + "/" : + code.toString(), defaultHandler = function () { + if (stop) { + throw new Error(message); + } + // else ... + if (win.console) { + console.log(message); // eslint-disable-line no-console + } + }; + if (typeof params !== 'undefined') { + var additionalMessages_1 = ''; + if (isCode) { + message += '?'; + } + objectEach(params, function (value, key) { + additionalMessages_1 += ('\n' + key + ': ' + value); + if (isCode) { + message += encodeURI(key) + '=' + encodeURI(value); + } + }); + message += additionalMessages_1; + } + if (chart) { + fireEvent(chart, 'displayError', { code: code, message: message, params: params }, defaultHandler); + } + else { + defaultHandler(); + } +}; +/* eslint-disable no-invalid-this, valid-jsdoc */ +/** + * An animator object used internally. One instance applies to one property + * (attribute or style prop) on one element. Animation is always initiated + * through {@link SVGElement#animate}. + * + * @example + * var rect = renderer.rect(0, 0, 10, 10).add(); + * rect.animate({ width: 100 }); + * + * @private + * @class + * @name Highcharts.Fx + */ +var Fx = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + /** + * + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGElement} elem + * The element to animate. + * + * @param {Highcharts.AnimationOptionsObject} options + * Animation options. + * + * @param {string} prop + * The single attribute or CSS property to animate. + */ + function Fx(elem, options, prop) { + this.options = options; + this.elem = elem; + this.prop = prop; + } + /* * + * + * Functions + * + * */ + /** + * Set the current step of a path definition on SVGElement. + * + * @function Highcharts.Fx#dSetter + * + * @return {void} + */ + Fx.prototype.dSetter = function () { + var paths = this.paths, start = paths && paths[0], end = paths && paths[1], path = [], now = this.now || 0; + // Land on the final path without adjustment points appended in the ends + if (now === 1 || !start || !end) { + path = this.toD || []; + } + else if (start.length === end.length && now < 1) { + for (var i = 0; i < end.length; i++) { + // Tween between the start segment and the end segment. Start + // with a copy of the end segment and tween the appropriate + // numerics + var startSeg = start[i]; + var endSeg = end[i]; + var tweenSeg = []; + for (var j = 0; j < endSeg.length; j++) { + var startItem = startSeg[j]; + var endItem = endSeg[j]; + // Tween numbers + if (typeof startItem === 'number' && + typeof endItem === 'number' && + // Arc boolean flags + !(endSeg[0] === 'A' && (j === 4 || j === 5))) { + tweenSeg[j] = startItem + now * (endItem - startItem); + // Strings, take directly from the end segment + } + else { + tweenSeg[j] = endItem; + } + } + path.push(tweenSeg); + } + // If animation is finished or length not matching, land on right value + } + else { + path = end; + } + this.elem.attr('d', path, void 0, true); + }; + /** + * Update the element with the current animation step. + * + * @function Highcharts.Fx#update + * + * @return {void} + */ + Fx.prototype.update = function () { + var elem = this.elem, prop = this.prop, // if destroyed, it is null + now = this.now, step = this.options.step; + // Animation setter defined from outside + if (this[prop + 'Setter']) { + this[prop + 'Setter'](); + // Other animations on SVGElement + } + else if (elem.attr) { + if (elem.element) { + elem.attr(prop, now, null, true); + } + // HTML styles, raw HTML content like container size + } + else { + elem.style[prop] = now + this.unit; + } + if (step) { + step.call(elem, now, this); + } + }; + /** + * Run an animation. + * + * @function Highcharts.Fx#run + * + * @param {number} from + * The current value, value to start from. + * + * @param {number} to + * The end value, value to land on. + * + * @param {string} unit + * The property unit, for example `px`. + * + * @return {void} + */ + Fx.prototype.run = function (from, to, unit) { + var self = this, options = self.options, timer = function (gotoEnd) { + return timer.stopped ? false : self.step(gotoEnd); + }, requestAnimationFrame = win.requestAnimationFrame || + function (step) { + setTimeout(step, 13); + }, step = function () { + for (var i = 0; i < H.timers.length; i++) { + if (!H.timers[i]()) { + H.timers.splice(i--, 1); + } + } + if (H.timers.length) { + requestAnimationFrame(step); + } + }; + if (from === to && !this.elem['forceAnimate:' + this.prop]) { + delete options.curAnim[this.prop]; + if (options.complete && Object.keys(options.curAnim).length === 0) { + options.complete.call(this.elem); + } + } + else { // #7166 + this.startTime = +new Date(); + this.start = from; + this.end = to; + this.unit = unit; + this.now = this.start; + this.pos = 0; + timer.elem = this.elem; + timer.prop = this.prop; + if (timer() && H.timers.push(timer) === 1) { + requestAnimationFrame(step); + } + } + }; + /** + * Run a single step in the animation. + * + * @function Highcharts.Fx#step + * + * @param {boolean} [gotoEnd] + * Whether to go to the endpoint of the animation after abort. + * + * @return {boolean} + * Returns `true` if animation continues. + */ + Fx.prototype.step = function (gotoEnd) { + var t = +new Date(), ret, done, options = this.options, elem = this.elem, complete = options.complete, duration = options.duration, curAnim = options.curAnim; + if (elem.attr && !elem.element) { // #2616, element is destroyed + ret = false; + } + else if (gotoEnd || t >= duration + this.startTime) { + this.now = this.end; + this.pos = 1; + this.update(); + curAnim[this.prop] = true; + done = true; + objectEach(curAnim, function (val) { + if (val !== true) { + done = false; + } + }); + if (done && complete) { + complete.call(elem); + } + ret = false; + } + else { + this.pos = options.easing((t - this.startTime) / duration); + this.now = this.start + ((this.end - this.start) * this.pos); + this.update(); + ret = true; + } + return ret; + }; + /** + * Prepare start and end values so that the path can be animated one to one. + * + * @function Highcharts.Fx#initPath + * + * @param {Highcharts.SVGElement} elem + * The SVGElement item. + * + * @param {Highcharts.SVGPathArray|undefined} fromD + * Starting path definition. + * + * @param {Highcharts.SVGPathArray} toD + * Ending path definition. + * + * @return {Array} + * An array containing start and end paths in array form so that + * they can be animated in parallel. + */ + Fx.prototype.initPath = function (elem, fromD, toD) { + var shift, startX = elem.startX, endX = elem.endX, fullLength, i, start = fromD && fromD.slice(), // copy + end = toD.slice(), // copy + isArea = elem.isArea, positionFactor = isArea ? 2 : 1, reverse; + if (!start) { + return [end, end]; + } + /** + * If shifting points, prepend a dummy point to the end path. + * @private + * @param {Highcharts.SVGPathArray} arr - array + * @param {Highcharts.SVGPathArray} other - array + * @return {void} + */ + function prepend(arr, other) { + while (arr.length < fullLength) { + // Move to, line to or curve to? + var moveSegment = arr[0], otherSegment = other[fullLength - arr.length]; + if (otherSegment && moveSegment[0] === 'M') { + if (otherSegment[0] === 'C') { + arr[0] = [ + 'C', + moveSegment[1], + moveSegment[2], + moveSegment[1], + moveSegment[2], + moveSegment[1], + moveSegment[2] + ]; + } + else { + arr[0] = ['L', moveSegment[1], moveSegment[2]]; + } + } + // Prepend a copy of the first point + arr.unshift(moveSegment); + // For areas, the bottom path goes back again to the left, so we + // need to append a copy of the last point. + if (isArea) { + arr.push(arr[arr.length - 1]); + } + } + } + /** + * Copy and append last point until the length matches the end length. + * @private + * @param {Highcharts.SVGPathArray} arr - array + * @param {Highcharts.SVGPathArray} other - array + * @return {void} + */ + function append(arr, other) { + while (arr.length < fullLength) { + // Pull out the slice that is going to be appended or inserted. + // In a line graph, the positionFactor is 1, and the last point + // is sliced out. In an area graph, the positionFactor is 2, + // causing the middle two points to be sliced out, since an area + // path starts at left, follows the upper path then turns and + // follows the bottom back. + var segmentToAdd = arr[arr.length / positionFactor - 1].slice(); + // Disable the first control point of curve segments + if (segmentToAdd[0] === 'C') { + segmentToAdd[1] = segmentToAdd[5]; + segmentToAdd[2] = segmentToAdd[6]; + } + if (!isArea) { + arr.push(segmentToAdd); + } + else { + var lowerSegmentToAdd = arr[arr.length / positionFactor].slice(); + arr.splice(arr.length / 2, 0, segmentToAdd, lowerSegmentToAdd); + } + } + } + // For sideways animation, find out how much we need to shift to get the + // start path Xs to match the end path Xs. + if (startX && endX) { + for (i = 0; i < startX.length; i++) { + // Moving left, new points coming in on right + if (startX[i] === endX[0]) { + shift = i; + break; + // Moving right + } + else if (startX[0] === + endX[endX.length - startX.length + i]) { + shift = i; + reverse = true; + break; + // Fixed from the right side, "scaling" left + } + else if (startX[startX.length - 1] === + endX[endX.length - startX.length + i]) { + shift = startX.length - i; + break; + } + } + if (typeof shift === 'undefined') { + start = []; + } + } + if (start.length && isNumber(shift)) { + // The common target length for the start and end array, where both + // arrays are padded in opposite ends + fullLength = end.length + shift * positionFactor; + if (!reverse) { + prepend(end, start); + append(start, end); + } + else { + prepend(start, end); + append(end, start); + } + } + return [start, end]; + }; + /** + * Handle animation of the color attributes directly. + * + * @function Highcharts.Fx#fillSetter + * + * @return {void} + */ + Fx.prototype.fillSetter = function () { + Fx.prototype.strokeSetter.apply(this, arguments); + }; + /** + * Handle animation of the color attributes directly. + * + * @function Highcharts.Fx#strokeSetter + * + * @return {void} + */ + Fx.prototype.strokeSetter = function () { + this.elem.attr(this.prop, H.color(this.start).tweenTo(H.color(this.end), this.pos), null, true); + }; + return Fx; +}()); +H.Fx = Fx; +/* eslint-disable valid-jsdoc */ +/** + * Utility function to deep merge two or more objects and return a third object. + * If the first argument is true, the contents of the second object is copied + * into the first object. The merge function can also be used with a single + * object argument to create a deep copy of an object. + * + * @function Highcharts.merge + * + * @param {boolean} extend + * Whether to extend the left-side object (a) or return a whole new + * object. + * + * @param {T|undefined} a + * The first object to extend. When only this is given, the function + * returns a deep copy. + * + * @param {...Array} [n] + * An object to merge into the previous one. + * + * @return {T} + * The merged object. If the first argument is true, the return is the + * same as the second argument. + */ /** +* Utility function to deep merge two or more objects and return a third object. +* The merge function can also be used with a single object argument to create a +* deep copy of an object. +* +* @function Highcharts.merge +* +* @param {T|undefined} a +* The first object to extend. When only this is given, the function +* returns a deep copy. +* +* @param {...Array} [n] +* An object to merge into the previous one. +* +* @return {T} +* The merged object. If the first argument is true, the return is the +* same as the second argument. +*/ +function merge() { + /* eslint-enable valid-jsdoc */ + var i, args = arguments, len, ret = {}, doCopy = function (copy, original) { + // An object is replacing a primitive + if (typeof copy !== 'object') { + copy = {}; + } + objectEach(original, function (value, key) { + // Copy the contents of objects, but not arrays or DOM nodes + if (isObject(value, true) && + !isClass(value) && + !isDOMElement(value)) { + copy[key] = doCopy(copy[key] || {}, value); + // Primitives and arrays are copied over directly + } + else { + copy[key] = original[key]; + } + }); + return copy; + }; + // If first argument is true, copy into the existing object. Used in + // setOptions. + if (args[0] === true) { + ret = args[1]; + args = Array.prototype.slice.call(args, 2); + } + // For each argument, extend the return + len = args.length; + for (i = 0; i < len; i++) { + ret = doCopy(ret, args[i]); + } + return ret; +} +H.merge = merge; +/** + * Constrain a value to within a lower and upper threshold. + * + * @private + * @param {number} value The initial value + * @param {number} min The lower threshold + * @param {number} max The upper threshold + * @return {number} Returns a number value within min and max. + */ +function clamp(value, min, max) { + return value > min ? value < max ? value : max : min; +} +/** + * Shortcut for parseInt + * + * @private + * @function Highcharts.pInt + * + * @param {*} s + * any + * + * @param {number} [mag] + * Magnitude + * + * @return {number} + * number + */ +var pInt = H.pInt = function pInt(s, mag) { + return parseInt(s, mag || 10); +}; +/** + * Utility function to check for string type. + * + * @function Highcharts.isString + * + * @param {*} s + * The item to check. + * + * @return {boolean} + * True if the argument is a string. + */ +var isString = H.isString = function isString(s) { + return typeof s === 'string'; +}; +/** + * Utility function to check if an item is an array. + * + * @function Highcharts.isArray + * + * @param {*} obj + * The item to check. + * + * @return {boolean} + * True if the argument is an array. + */ +var isArray = H.isArray = function isArray(obj) { + var str = Object.prototype.toString.call(obj); + return str === '[object Array]' || str === '[object Array Iterator]'; +}; +/** + * Utility function to check if an item is of type object. + * + * @function Highcharts.isObject + * + * @param {*} obj + * The item to check. + * + * @param {boolean} [strict=false] + * Also checks that the object is not an array. + * + * @return {boolean} + * True if the argument is an object. + */ +function isObject(obj, strict) { + return (!!obj && + typeof obj === 'object' && + (!strict || !isArray(obj))); // eslint-disable-line @typescript-eslint/no-explicit-any +} +H.isObject = isObject; +/** + * Utility function to check if an Object is a HTML Element. + * + * @function Highcharts.isDOMElement + * + * @param {*} obj + * The item to check. + * + * @return {boolean} + * True if the argument is a HTML Element. + */ +var isDOMElement = H.isDOMElement = function isDOMElement(obj) { + return isObject(obj) && typeof obj.nodeType === 'number'; +}; +/** + * Utility function to check if an Object is a class. + * + * @function Highcharts.isClass + * + * @param {object|undefined} obj + * The item to check. + * + * @return {boolean} + * True if the argument is a class. + */ +var isClass = H.isClass = function isClass(obj) { + var c = obj && obj.constructor; + return !!(isObject(obj, true) && + !isDOMElement(obj) && + (c && c.name && c.name !== 'Object')); +}; +/** + * Utility function to check if an item is a number and it is finite (not NaN, + * Infinity or -Infinity). + * + * @function Highcharts.isNumber + * + * @param {*} n + * The item to check. + * + * @return {boolean} + * True if the item is a finite number + */ +var isNumber = H.isNumber = function isNumber(n) { + return typeof n === 'number' && !isNaN(n) && n < Infinity && n > -Infinity; +}; +/** + * Remove the last occurence of an item from an array. + * + * @function Highcharts.erase + * + * @param {Array<*>} arr + * The array. + * + * @param {*} item + * The item to remove. + * + * @return {void} + */ +var erase = H.erase = function erase(arr, item) { + var i = arr.length; + while (i--) { + if (arr[i] === item) { + arr.splice(i, 1); + break; + } + } +}; +/** + * Check if an object is null or undefined. + * + * @function Highcharts.defined + * + * @param {*} obj + * The object to check. + * + * @return {boolean} + * False if the object is null or undefined, otherwise true. + */ +var defined = H.defined = function defined(obj) { + return typeof obj !== 'undefined' && obj !== null; +}; +/** + * Set or get an attribute or an object of attributes. To use as a setter, pass + * a key and a value, or let the second argument be a collection of keys and + * values. To use as a getter, pass only a string as the second argument. + * + * @function Highcharts.attr + * + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} elem + * The DOM element to receive the attribute(s). + * + * @param {string|Highcharts.HTMLAttributes|Highcharts.SVGAttributes} [prop] + * The property or an object of key-value pairs. + * + * @param {number|string} [value] + * The value if a single property is set. + * + * @return {string|null|undefined} + * When used as a getter, return the value. + */ +function attr(elem, prop, value) { + var ret; + // if the prop is a string + if (isString(prop)) { + // set the value + if (defined(value)) { + elem.setAttribute(prop, value); + // get the value + } + else if (elem && elem.getAttribute) { + ret = elem.getAttribute(prop); + // IE7 and below cannot get class through getAttribute (#7850) + if (!ret && prop === 'class') { + ret = elem.getAttribute(prop + 'Name'); + } + } + // else if prop is defined, it is a hash of key/value pairs + } + else { + objectEach(prop, function (val, key) { + elem.setAttribute(key, val); + }); + } + return ret; +} +H.attr = attr; +/** + * Check if an element is an array, and if not, make it into an array. + * + * @function Highcharts.splat + * + * @param {*} obj + * The object to splat. + * + * @return {Array} + * The produced or original array. + */ +var splat = H.splat = function splat(obj) { + return isArray(obj) ? obj : [obj]; +}; +/** + * Set a timeout if the delay is given, otherwise perform the function + * synchronously. + * + * @function Highcharts.syncTimeout + * + * @param {Function} fn + * The function callback. + * + * @param {number} delay + * Delay in milliseconds. + * + * @param {*} [context] + * An optional context to send to the function callback. + * + * @return {number} + * An identifier for the timeout that can later be cleared with + * Highcharts.clearTimeout. Returns -1 if there is no timeout. + */ +var syncTimeout = H.syncTimeout = function syncTimeout(fn, delay, context) { + if (delay > 0) { + return setTimeout(fn, delay, context); + } + fn.call(0, context); + return -1; +}; +/** + * Internal clear timeout. The function checks that the `id` was not removed + * (e.g. by `chart.destroy()`). For the details see + * [issue #7901](https://github.com/highcharts/highcharts/issues/7901). + * + * @function Highcharts.clearTimeout + * + * @param {number} id + * Id of a timeout. + * + * @return {void} + */ +var internalClearTimeout = H.clearTimeout = function (id) { + if (defined(id)) { + clearTimeout(id); + } +}; +/* eslint-disable valid-jsdoc */ +/** + * Utility function to extend an object with the members of another. + * + * @function Highcharts.extend + * + * @param {T|undefined} a + * The object to be extended. + * + * @param {object} b + * The object to add to the first one. + * + * @return {T} + * Object a, the original object. + */ +var extend = H.extend = function extend(a, b) { + /* eslint-enable valid-jsdoc */ + var n; + if (!a) { + a = {}; + } + for (n in b) { // eslint-disable-line guard-for-in + a[n] = b[n]; + } + return a; +}; +/* eslint-disable valid-jsdoc */ +/** + * Return the first value that is not null or undefined. + * + * @function Highcharts.pick + * + * @param {...Array} items + * Variable number of arguments to inspect. + * + * @return {T} + * The value of the first argument that is not null or undefined. + */ +function pick() { + var args = arguments; + var length = args.length; + for (var i = 0; i < length; i++) { + var arg = args[i]; + if (typeof arg !== 'undefined' && arg !== null) { + return arg; + } + } +} +H.pick = pick; +/** + * Set CSS on a given element. + * + * @function Highcharts.css + * + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} el + * An HTML DOM element. + * + * @param {Highcharts.CSSObject} styles + * Style object with camel case property names. + * + * @return {void} + */ +var css = H.css = function css(el, styles) { + if (H.isMS && !H.svg) { // #2686 + if (styles && typeof styles.opacity !== 'undefined') { + styles.filter = + 'alpha(opacity=' + (styles.opacity * 100) + ')'; + } + } + extend(el.style, styles); +}; +/** + * Utility function to create an HTML element with attributes and styles. + * + * @function Highcharts.createElement + * + * @param {string} tag + * The HTML tag. + * + * @param {Highcharts.HTMLAttributes} [attribs] + * Attributes as an object of key-value pairs. + * + * @param {Highcharts.CSSObject} [styles] + * Styles as an object of key-value pairs. + * + * @param {Highcharts.HTMLDOMElement} [parent] + * The parent HTML object. + * + * @param {boolean} [nopad=false] + * If true, remove all padding, border and margin. + * + * @return {Highcharts.HTMLDOMElement} + * The created DOM element. + */ +var createElement = H.createElement = function createElement(tag, attribs, styles, parent, nopad) { + var el = doc.createElement(tag); + if (attribs) { + extend(el, attribs); + } + if (nopad) { + css(el, { padding: '0', border: 'none', margin: '0' }); + } + if (styles) { + css(el, styles); + } + if (parent) { + parent.appendChild(el); + } + return el; +}; +// eslint-disable-next-line valid-jsdoc +/** + * Extend a prototyped class by new members. + * + * @function Highcharts.extendClass + * + * @param {Highcharts.Class} parent + * The parent prototype to inherit. + * + * @param {Highcharts.Dictionary<*>} members + * A collection of prototype members to add or override compared to the + * parent prototype. + * + * @return {Highcharts.Class} + * A new prototype. + */ +var extendClass = H.extendClass = function extendClass(parent, members) { + var obj = (function () { }); + obj.prototype = new parent(); // eslint-disable-line new-cap + extend(obj.prototype, members); + return obj; +}; +/** + * Left-pad a string to a given length by adding a character repetetively. + * + * @function Highcharts.pad + * + * @param {number} number + * The input string or number. + * + * @param {number} [length] + * The desired string length. + * + * @param {string} [padder=0] + * The character to pad with. + * + * @return {string} + * The padded string. + */ +var pad = H.pad = function pad(number, length, padder) { + return new Array((length || 2) + + 1 - + String(number) + .replace('-', '') + .length).join(padder || '0') + number; +}; +/** + * Return a length based on either the integer value, or a percentage of a base. + * + * @function Highcharts.relativeLength + * + * @param {Highcharts.RelativeSize} value + * A percentage string or a number. + * + * @param {number} base + * The full length that represents 100%. + * + * @param {number} [offset=0] + * A pixel offset to apply for percentage values. Used internally in + * axis positioning. + * + * @return {number} + * The computed length. + */ +var relativeLength = H.relativeLength = function relativeLength(value, base, offset) { + return (/%$/).test(value) ? + (base * parseFloat(value) / 100) + (offset || 0) : + parseFloat(value); +}; +/** + * Wrap a method with extended functionality, preserving the original function. + * +' * @function Highcharts.wrap + * + * @param {*} obj + * The context object that the method belongs to. In real cases, this is + * often a prototype. + * + * @param {string} method + * The name of the method to extend. + * + * @param {Highcharts.WrapProceedFunction} func + * A wrapper function callback. This function is called with the same + * arguments as the original function, except that the original function + * is unshifted and passed as the first argument. + * + * @return {void} + */ +var wrap = H.wrap = function wrap(obj, method, func) { + var proceed = obj[method]; + obj[method] = function () { + var args = Array.prototype.slice.call(arguments), outerArgs = arguments, ctx = this, ret; + ctx.proceed = function () { + proceed.apply(ctx, arguments.length ? arguments : outerArgs); + }; + args.unshift(proceed); + ret = func.apply(this, args); + ctx.proceed = null; + return ret; + }; +}; +/** + * Format a string according to a subset of the rules of Python's String.format + * method. + * + * @example + * var s = Highcharts.format( + * 'The {color} fox was {len:.2f} feet long', + * { color: 'red', len: Math.PI } + * ); + * // => The red fox was 3.14 feet long + * + * @function Highcharts.format + * + * @param {string} str + * The string to format. + * + * @param {Record} ctx + * The context, a collection of key-value pairs where each key is + * replaced by its value. + * + * @param {Highcharts.Chart} [chart] + * A `Chart` instance used to get numberFormatter and time. + * + * @return {string} + * The formatted string. + */ +var format = H.format = function (str, ctx, chart) { + var splitter = '{', isInside = false, segment, valueAndFormat, ret = [], val, index; + var floatRegex = /f$/; + var decRegex = /\.([0-9])/; + var lang = H.defaultOptions.lang; + var time = chart && chart.time || H.time; + var numberFormatter = chart && chart.numberFormatter || numberFormat; + while (str) { + index = str.indexOf(splitter); + if (index === -1) { + break; + } + segment = str.slice(0, index); + if (isInside) { // we're on the closing bracket looking back + valueAndFormat = segment.split(':'); + val = getNestedProperty(valueAndFormat.shift() || '', ctx); + // Format the replacement + if (valueAndFormat.length && typeof val === 'number') { + segment = valueAndFormat.join(':'); + if (floatRegex.test(segment)) { // float + var decimals = parseInt((segment.match(decRegex) || ['', '-1'])[1], 10); + if (val !== null) { + val = numberFormatter(val, decimals, lang.decimalPoint, segment.indexOf(',') > -1 ? lang.thousandsSep : ''); + } + } + else { + val = time.dateFormat(segment, val); + } + } + // Push the result and advance the cursor + ret.push(val); + } + else { + ret.push(segment); + } + str = str.slice(index + 1); // the rest + isInside = !isInside; // toggle + splitter = isInside ? '}' : '{'; // now look for next matching bracket + } + ret.push(str); + return ret.join(''); +}; +/** + * Get the magnitude of a number. + * + * @function Highcharts.getMagnitude + * + * @param {number} num + * The number. + * + * @return {number} + * The magnitude, where 1-9 are magnitude 1, 10-99 magnitude 2 etc. + */ +var getMagnitude = H.getMagnitude = function (num) { + return Math.pow(10, Math.floor(Math.log(num) / Math.LN10)); +}; +/** + * Take an interval and normalize it to multiples of round numbers. + * + * @deprecated + * @function Highcharts.normalizeTickInterval + * + * @param {number} interval + * The raw, un-rounded interval. + * + * @param {Array<*>} [multiples] + * Allowed multiples. + * + * @param {number} [magnitude] + * The magnitude of the number. + * + * @param {boolean} [allowDecimals] + * Whether to allow decimals. + * + * @param {boolean} [hasTickAmount] + * If it has tickAmount, avoid landing on tick intervals lower than + * original. + * + * @return {number} + * The normalized interval. + * + * @todo + * Move this function to the Axis prototype. It is here only for historical + * reasons. + */ +var normalizeTickInterval = H.normalizeTickInterval = function (interval, multiples, magnitude, allowDecimals, hasTickAmount) { + var normalized, i, retInterval = interval; + // round to a tenfold of 1, 2, 2.5 or 5 + magnitude = pick(magnitude, 1); + normalized = interval / magnitude; + // multiples for a linear scale + if (!multiples) { + multiples = hasTickAmount ? + // Finer grained ticks when the tick amount is hard set, including + // when alignTicks is true on multiple axes (#4580). + [1, 1.2, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10] : + // Else, let ticks fall on rounder numbers + [1, 2, 2.5, 5, 10]; + // the allowDecimals option + if (allowDecimals === false) { + if (magnitude === 1) { + multiples = multiples.filter(function (num) { + return num % 1 === 0; + }); + } + else if (magnitude <= 0.1) { + multiples = [1 / magnitude]; + } + } + } + // normalize the interval to the nearest multiple + for (i = 0; i < multiples.length; i++) { + retInterval = multiples[i]; + // only allow tick amounts smaller than natural + if ((hasTickAmount && + retInterval * magnitude >= interval) || + (!hasTickAmount && + (normalized <= + (multiples[i] + + (multiples[i + 1] || multiples[i])) / 2))) { + break; + } + } + // Multiply back to the correct magnitude. Correct floats to appropriate + // precision (#6085). + retInterval = correctFloat(retInterval * magnitude, -Math.round(Math.log(0.001) / Math.LN10)); + return retInterval; +}; +/** + * Sort an object array and keep the order of equal items. The ECMAScript + * standard does not specify the behaviour when items are equal. + * + * @function Highcharts.stableSort + * + * @param {Array<*>} arr + * The array to sort. + * + * @param {Function} sortFunction + * The function to sort it with, like with regular Array.prototype.sort. + * + * @return {void} + */ +var stableSort = H.stableSort = function stableSort(arr, sortFunction) { + // @todo It seems like Chrome since v70 sorts in a stable way internally, + // plus all other browsers do it, so over time we may be able to remove this + // function + var length = arr.length, sortValue, i; + // Add index to each item + for (i = 0; i < length; i++) { + arr[i].safeI = i; // stable sort index + } + arr.sort(function (a, b) { + sortValue = sortFunction(a, b); + return sortValue === 0 ? a.safeI - b.safeI : sortValue; + }); + // Remove index from items + for (i = 0; i < length; i++) { + delete arr[i].safeI; // stable sort index + } +}; +/** + * Non-recursive method to find the lowest member of an array. `Math.min` raises + * a maximum call stack size exceeded error in Chrome when trying to apply more + * than 150.000 points. This method is slightly slower, but safe. + * + * @function Highcharts.arrayMin + * + * @param {Array<*>} data + * An array of numbers. + * + * @return {number} + * The lowest number. + */ +var arrayMin = H.arrayMin = function arrayMin(data) { + var i = data.length, min = data[0]; + while (i--) { + if (data[i] < min) { + min = data[i]; + } + } + return min; +}; +/** + * Non-recursive method to find the lowest member of an array. `Math.max` raises + * a maximum call stack size exceeded error in Chrome when trying to apply more + * than 150.000 points. This method is slightly slower, but safe. + * + * @function Highcharts.arrayMax + * + * @param {Array<*>} data + * An array of numbers. + * + * @return {number} + * The highest number. + */ +var arrayMax = H.arrayMax = function arrayMax(data) { + var i = data.length, max = data[0]; + while (i--) { + if (data[i] > max) { + max = data[i]; + } + } + return max; +}; +/** + * Utility method that destroys any SVGElement instances that are properties on + * the given object. It loops all properties and invokes destroy if there is a + * destroy method. The property is then delete. + * + * @function Highcharts.destroyObjectProperties + * + * @param {*} obj + * The object to destroy properties on. + * + * @param {*} [except] + * Exception, do not destroy this property, only delete it. + * + * @return {void} + */ +var destroyObjectProperties = H.destroyObjectProperties = + function destroyObjectProperties(obj, except) { + objectEach(obj, function (val, n) { + // If the object is non-null and destroy is defined + if (val && val !== except && val.destroy) { + // Invoke the destroy + val.destroy(); + } + // Delete the property from the object. + delete obj[n]; + }); + }; +/** + * Discard a HTML element by moving it to the bin and delete. + * + * @function Highcharts.discardElement + * + * @param {Highcharts.HTMLDOMElement} element + * The HTML node to discard. + * + * @return {void} + */ +var discardElement = H.discardElement = function discardElement(element) { + var garbageBin = H.garbageBin; + // create a garbage bin element, not part of the DOM + if (!garbageBin) { + garbageBin = createElement('div'); + } + // move the node and empty bin + if (element) { + garbageBin.appendChild(element); + } + garbageBin.innerHTML = ''; +}; +/** + * Fix JS round off float errors. + * + * @function Highcharts.correctFloat + * + * @param {number} num + * A float number to fix. + * + * @param {number} [prec=14] + * The precision. + * + * @return {number} + * The corrected float number. + */ +var correctFloat = H.correctFloat = function correctFloat(num, prec) { + return parseFloat(num.toPrecision(prec || 14)); +}; +/** + * Set the global animation to either a given value, or fall back to the given + * chart's animation option. + * + * @function Highcharts.setAnimation + * + * @param {boolean|Highcharts.AnimationOptionsObject|undefined} animation + * The animation object. + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @return {void} + * + * @todo + * This function always relates to a chart, and sets a property on the renderer, + * so it should be moved to the SVGRenderer. + */ +var setAnimation = H.setAnimation = function setAnimation(animation, chart) { + chart.renderer.globalAnimation = pick(animation, chart.options.chart.animation, true); +}; +/** + * Get the animation in object form, where a disabled animation is always + * returned as `{ duration: 0 }`. + * + * @function Highcharts.animObject + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=0] + * An animation setting. Can be an object with duration, complete and + * easing properties, or a boolean to enable or disable. + * + * @return {Highcharts.AnimationOptionsObject} + * An object with at least a duration property. + */ +var animObject = H.animObject = function animObject(animation) { + return isObject(animation) ? + merge(animation) : + { duration: animation ? 500 : 0 }; +}; +/** + * The time unit lookup + * + * @ignore + */ +var timeUnits = H.timeUnits = { + millisecond: 1, + second: 1000, + minute: 60000, + hour: 3600000, + day: 24 * 3600000, + week: 7 * 24 * 3600000, + month: 28 * 24 * 3600000, + year: 364 * 24 * 3600000 +}; +/** + * Format a number and return a string based on input settings. + * + * @sample highcharts/members/highcharts-numberformat/ + * Custom number format + * + * @function Highcharts.numberFormat + * + * @param {number} number + * The input number to format. + * + * @param {number} decimals + * The amount of decimals. A value of -1 preserves the amount in the + * input number. + * + * @param {string} [decimalPoint] + * The decimal point, defaults to the one given in the lang options, or + * a dot. + * + * @param {string} [thousandsSep] + * The thousands separator, defaults to the one given in the lang + * options, or a space character. + * + * @return {string} + * The formatted number. + */ +var numberFormat = H.numberFormat = function numberFormat(number, decimals, decimalPoint, thousandsSep) { + number = +number || 0; + decimals = +decimals; + var lang = H.defaultOptions.lang, origDec = (number.toString().split('.')[1] || '').split('e')[0].length, strinteger, thousands, ret, roundedNumber, exponent = number.toString().split('e'), fractionDigits; + if (decimals === -1) { + // Preserve decimals. Not huge numbers (#3793). + decimals = Math.min(origDec, 20); + } + else if (!isNumber(decimals)) { + decimals = 2; + } + else if (decimals && exponent[1] && exponent[1] < 0) { + // Expose decimals from exponential notation (#7042) + fractionDigits = decimals + +exponent[1]; + if (fractionDigits >= 0) { + // remove too small part of the number while keeping the notation + exponent[0] = (+exponent[0]).toExponential(fractionDigits) + .split('e')[0]; + decimals = fractionDigits; + } + else { + // fractionDigits < 0 + exponent[0] = exponent[0].split('.')[0] || 0; + if (decimals < 20) { + // use number instead of exponential notation (#7405) + number = (exponent[0] * Math.pow(10, exponent[1])) + .toFixed(decimals); + } + else { + // or zero + number = 0; + } + exponent[1] = 0; + } + } + // Add another decimal to avoid rounding errors of float numbers. (#4573) + // Then use toFixed to handle rounding. + roundedNumber = (Math.abs(exponent[1] ? exponent[0] : number) + + Math.pow(10, -Math.max(decimals, origDec) - 1)).toFixed(decimals); + // A string containing the positive integer component of the number + strinteger = String(pInt(roundedNumber)); + // Leftover after grouping into thousands. Can be 0, 1 or 2. + thousands = strinteger.length > 3 ? strinteger.length % 3 : 0; + // Language + decimalPoint = pick(decimalPoint, lang.decimalPoint); + thousandsSep = pick(thousandsSep, lang.thousandsSep); + // Start building the return + ret = number < 0 ? '-' : ''; + // Add the leftover after grouping into thousands. For example, in the + // number 42 000 000, this line adds 42. + ret += thousands ? strinteger.substr(0, thousands) + thousandsSep : ''; + // Add the remaining thousands groups, joined by the thousands separator + ret += strinteger + .substr(thousands) + .replace(/(\d{3})(?=\d)/g, '$1' + thousandsSep); + // Add the decimal point and the decimal component + if (decimals) { + // Get the decimal component + ret += decimalPoint + roundedNumber.slice(-decimals); + } + if (exponent[1] && +ret !== 0) { + ret += 'e' + exponent[1]; + } + return ret; +}; +/** + * Easing definition + * + * @private + * @function Math.easeInOutSine + * + * @param {number} pos + * Current position, ranging from 0 to 1. + * + * @return {number} + * Ease result + */ +Math.easeInOutSine = function (pos) { + return -0.5 * (Math.cos(Math.PI * pos) - 1); +}; +/** + * Returns the value of a property path on a given object. + * + * @private + * @function getNestedProperty + * + * @param {string} path + * Path to the property, for example `custom.myValue`. + * + * @param {unknown} obj + * Instance containing the property on the specific path. + * + * @return {unknown} + * The unknown property value. + */ +function getNestedProperty(path, obj) { + if (!path) { + return obj; + } + var pathElements = path.split('.').reverse(); + var subProperty = obj; + if (pathElements.length === 1) { + return subProperty[path]; + } + var pathElement = pathElements.pop(); + while (typeof pathElement !== 'undefined' && + typeof subProperty !== 'undefined' && + subProperty !== null) { + subProperty = subProperty[pathElement]; + pathElement = pathElements.pop(); + } + return subProperty; +} +/** + * Get the computed CSS value for given element and property, only for numerical + * properties. For width and height, the dimension of the inner box (excluding + * padding) is returned. Used for fitting the chart within the container. + * + * @function Highcharts.getStyle + * + * @param {Highcharts.HTMLDOMElement} el + * An HTML element. + * + * @param {string} prop + * The property name. + * + * @param {boolean} [toInt=true] + * Parse to integer. + * + * @return {number|string} + * The numeric value. + */ +var getStyle = H.getStyle = function (el, prop, toInt) { + var style; + // For width and height, return the actual inner pixel size (#4913) + if (prop === 'width') { + var offsetWidth = Math.min(el.offsetWidth, el.scrollWidth); + // In flex boxes, we need to use getBoundingClientRect and floor it, + // because scrollWidth doesn't support subpixel precision (#6427) ... + var boundingClientRectWidth = el.getBoundingClientRect && + el.getBoundingClientRect().width; + // ...unless if the containing div or its parents are transform-scaled + // down, in which case the boundingClientRect can't be used as it is + // also scaled down (#9871, #10498). + if (boundingClientRectWidth < offsetWidth && + boundingClientRectWidth >= offsetWidth - 1) { + offsetWidth = Math.floor(boundingClientRectWidth); + } + return Math.max(0, // #8377 + (offsetWidth - + H.getStyle(el, 'padding-left') - + H.getStyle(el, 'padding-right'))); + } + if (prop === 'height') { + return Math.max(0, // #8377 + Math.min(el.offsetHeight, el.scrollHeight) - + H.getStyle(el, 'padding-top') - + H.getStyle(el, 'padding-bottom')); + } + if (!win.getComputedStyle) { + // SVG not supported, forgot to load oldie.js? + error(27, true); + } + // Otherwise, get the computed style + style = win.getComputedStyle(el, undefined); // eslint-disable-line no-undefined + if (style) { + style = style.getPropertyValue(prop); + if (pick(toInt, prop !== 'opacity')) { + style = pInt(style); + } + } + return style; +}; +/** + * Search for an item in an array. + * + * @function Highcharts.inArray + * + * @deprecated + * + * @param {*} item + * The item to search for. + * + * @param {Array<*>} arr + * The array or node collection to search in. + * + * @param {number} [fromIndex=0] + * The index to start searching from. + * + * @return {number} + * The index within the array, or -1 if not found. + */ +var inArray = H.inArray = function (item, arr, fromIndex) { + return arr.indexOf(item, fromIndex); +}; +/* eslint-disable valid-jsdoc */ +/** + * Return the value of the first element in the array that satisfies the + * provided testing function. + * + * @function Highcharts.find + * + * @param {Array} arr + * The array to test. + * + * @param {Function} callback + * The callback function. The function receives the item as the first + * argument. Return `true` if this item satisfies the condition. + * + * @return {T|undefined} + * The value of the element. + */ +var find = H.find = Array.prototype.find ? + /* eslint-enable valid-jsdoc */ + function (arr, callback) { + return arr.find(callback); + } : + // Legacy implementation. PhantomJS, IE <= 11 etc. #7223. + function (arr, callback) { + var i, length = arr.length; + for (i = 0; i < length; i++) { + if (callback(arr[i], i)) { // eslint-disable-line callback-return + return arr[i]; + } + } + }; +/** + * Returns an array of a given object's own properties. + * + * @function Highcharts.keys + * @deprecated + * + * @param {*} obj + * The object of which the properties are to be returned. + * + * @return {Array} + * An array of strings that represents all the properties. + */ +H.keys = Object.keys; +/** + * Get the element's offset position, corrected for `overflow: auto`. + * + * @function Highcharts.offset + * + * @param {global.Element} el + * The DOM element. + * + * @return {Highcharts.OffsetObject} + * An object containing `left` and `top` properties for the position in + * the page. + */ +var offset = H.offset = function offset(el) { + var docElem = doc.documentElement, box = (el.parentElement || el.parentNode) ? + el.getBoundingClientRect() : + { top: 0, left: 0 }; + return { + top: box.top + (win.pageYOffset || docElem.scrollTop) - + (docElem.clientTop || 0), + left: box.left + (win.pageXOffset || docElem.scrollLeft) - + (docElem.clientLeft || 0) + }; +}; +/** + * Stop running animation. + * + * @function Highcharts.stop + * + * @param {Highcharts.SVGElement} el + * The SVGElement to stop animation on. + * + * @param {string} [prop] + * The property to stop animating. If given, the stop method will stop a + * single property from animating, while others continue. + * + * @return {void} + * + * @todo + * A possible extension to this would be to stop a single property, when + * we want to continue animating others. Then assign the prop to the timer + * in the Fx.run method, and check for the prop here. This would be an + * improvement in all cases where we stop the animation from .attr. Instead of + * stopping everything, we can just stop the actual attributes we're setting. + */ +var stop = H.stop = function (el, prop) { + var i = H.timers.length; + // Remove timers related to this element (#4519) + while (i--) { + if (H.timers[i].elem === el && (!prop || prop === H.timers[i].prop)) { + H.timers[i].stopped = true; // #4667 + } + } +}; +/* eslint-disable valid-jsdoc */ +/** + * Iterate over object key pairs in an object. + * + * @function Highcharts.objectEach + * + * @param {*} obj + * The object to iterate over. + * + * @param {Highcharts.ObjectEachCallbackFunction} fn + * The iterator callback. It passes three arguments: + * * value - The property value. + * * key - The property key. + * * obj - The object that objectEach is being applied to. + * + * @param {T} [ctx] + * The context. + * + * @return {void} + */ +var objectEach = H.objectEach = function objectEach(obj, fn, ctx) { + /* eslint-enable valid-jsdoc */ + for (var key in obj) { + if (Object.hasOwnProperty.call(obj, key)) { + fn.call(ctx || obj[key], obj[key], key, obj); + } + } +}; +/** + * Iterate over an array. + * + * @deprecated + * @function Highcharts.each + * + * @param {Array<*>} arr + * The array to iterate over. + * + * @param {Function} fn + * The iterator callback. It passes three arguments: + * - `item`: The array item. + * - `index`: The item's index in the array. + * - `arr`: The array that each is being applied to. + * + * @param {*} [ctx] + * The context. + * + * @return {void} + */ +/** + * Filter an array by a callback. + * + * @deprecated + * @function Highcharts.grep + * + * @param {Array<*>} arr + * The array to filter. + * + * @param {Function} callback + * The callback function. The function receives the item as the first + * argument. Return `true` if the item is to be preserved. + * + * @return {Array<*>} + * A new, filtered array. + */ +/** + * Map an array by a callback. + * + * @deprecated + * @function Highcharts.map + * + * @param {Array<*>} arr + * The array to map. + * + * @param {Function} fn + * The callback function. Return the new value for the new array. + * + * @return {Array<*>} + * A new array item with modified items. + */ +/** + * Reduce an array to a single value. + * + * @deprecated + * @function Highcharts.reduce + * + * @param {Array<*>} arr + * The array to reduce. + * + * @param {Function} fn + * The callback function. Return the reduced value. Receives 4 + * arguments: Accumulated/reduced value, current value, current array + * index, and the array. + * + * @param {*} initialValue + * The initial value of the accumulator. + * + * @return {*} + * The reduced value. + */ +/** + * Test whether at least one element in the array passes the test implemented by + * the provided function. + * + * @deprecated + * @function Highcharts.some + * + * @param {Array<*>} arr + * The array to test + * + * @param {Function} fn + * The function to run on each item. Return truty to pass the test. + * Receives arguments `currentValue`, `index` and `array`. + * + * @param {*} ctx + * The context. + * + * @return {boolean} + */ +objectEach({ + map: 'map', + each: 'forEach', + grep: 'filter', + reduce: 'reduce', + some: 'some' +}, function (val, key) { + H[key] = function (arr) { + return Array.prototype[val].apply(arr, [].slice.call(arguments, 1)); + }; +}); +/* eslint-disable valid-jsdoc */ +/** + * Add an event listener. + * + * @function Highcharts.addEvent + * + * @param {Highcharts.Class|T} el + * The element or object to add a listener to. It can be a + * {@link HTMLDOMElement}, an {@link SVGElement} or any other object. + * + * @param {string} type + * The event type. + * + * @param {Highcharts.EventCallbackFunction|Function} fn + * The function callback to execute when the event is fired. + * + * @param {Highcharts.EventOptionsObject} [options] + * Options for adding the event. + * + * @return {Function} + * A callback function to remove the added event. + */ +var addEvent = H.addEvent = function (el, type, fn, options) { + if (options === void 0) { options = {}; } + /* eslint-enable valid-jsdoc */ + var events, addEventListener = (el.addEventListener || H.addEventListenerPolyfill); + // If we're setting events directly on the constructor, use a separate + // collection, `protoEvents` to distinguish it from the item events in + // `hcEvents`. + if (typeof el === 'function' && el.prototype) { + events = el.prototype.protoEvents = el.prototype.protoEvents || {}; + } + else { + events = el.hcEvents = el.hcEvents || {}; + } + // Allow click events added to points, otherwise they will be prevented by + // the TouchPointer.pinch function after a pinch zoom operation (#7091). + if (H.Point && + el instanceof H.Point && + el.series && + el.series.chart) { + el.series.chart.runTrackerClick = true; + } + // Handle DOM events + if (addEventListener) { + addEventListener.call(el, type, fn, false); + } + if (!events[type]) { + events[type] = []; + } + var eventObject = { + fn: fn, + order: typeof options.order === 'number' ? options.order : Infinity + }; + events[type].push(eventObject); + // Order the calls + events[type].sort(function (a, b) { + return a.order - b.order; + }); + // Return a function that can be called to remove this event. + return function () { + removeEvent(el, type, fn); + }; +}; +/* eslint-disable valid-jsdoc */ +/** + * Remove an event that was added with {@link Highcharts#addEvent}. + * + * @function Highcharts.removeEvent + * + * @param {Highcharts.Class|T} el + * The element to remove events on. + * + * @param {string} [type] + * The type of events to remove. If undefined, all events are removed + * from the element. + * + * @param {Highcharts.EventCallbackFunction} [fn] + * The specific callback to remove. If undefined, all events that match + * the element and optionally the type are removed. + * + * @return {void} + */ +var removeEvent = H.removeEvent = function removeEvent(el, type, fn) { + /* eslint-enable valid-jsdoc */ + var events; + /** + * @private + * @param {string} type - event type + * @param {Highcharts.EventCallbackFunction} fn - callback + * @return {void} + */ + function removeOneEvent(type, fn) { + var removeEventListener = (el.removeEventListener || H.removeEventListenerPolyfill); + if (removeEventListener) { + removeEventListener.call(el, type, fn, false); + } + } + /** + * @private + * @param {any} eventCollection - collection + * @return {void} + */ + function removeAllEvents(eventCollection) { + var types, len; + if (!el.nodeName) { + return; // break on non-DOM events + } + if (type) { + types = {}; + types[type] = true; + } + else { + types = eventCollection; + } + objectEach(types, function (val, n) { + if (eventCollection[n]) { + len = eventCollection[n].length; + while (len--) { + removeOneEvent(n, eventCollection[n][len].fn); + } + } + }); + } + ['protoEvents', 'hcEvents'].forEach(function (coll, i) { + var eventElem = i ? el : el.prototype; + var eventCollection = eventElem && eventElem[coll]; + if (eventCollection) { + if (type) { + events = (eventCollection[type] || []); + if (fn) { + eventCollection[type] = events.filter(function (obj) { + return fn !== obj.fn; + }); + removeOneEvent(type, fn); + } + else { + removeAllEvents(eventCollection); + eventCollection[type] = []; + } + } + else { + removeAllEvents(eventCollection); + eventElem[coll] = {}; + } + } + }); +}; +/* eslint-disable valid-jsdoc */ +/** + * Fire an event that was registered with {@link Highcharts#addEvent}. + * + * @function Highcharts.fireEvent + * + * @param {T} el + * The object to fire the event on. It can be a {@link HTMLDOMElement}, + * an {@link SVGElement} or any other object. + * + * @param {string} type + * The type of event. + * + * @param {Highcharts.Dictionary<*>|Event} [eventArguments] + * Custom event arguments that are passed on as an argument to the event + * handler. + * + * @param {Highcharts.EventCallbackFunction|Function} [defaultFunction] + * The default function to execute if the other listeners haven't + * returned false. + * + * @return {void} + */ +var fireEvent = H.fireEvent = function (el, type, eventArguments, defaultFunction) { + /* eslint-enable valid-jsdoc */ + var e, i; + eventArguments = eventArguments || {}; + if (doc.createEvent && + (el.dispatchEvent || el.fireEvent)) { + e = doc.createEvent('Events'); + e.initEvent(type, true, true); + extend(e, eventArguments); + if (el.dispatchEvent) { + el.dispatchEvent(e); + } + else { + el.fireEvent(type, e); + } + } + else { + if (!eventArguments.target) { + // We're running a custom event + extend(eventArguments, { + // Attach a simple preventDefault function to skip + // default handler if called. The built-in + // defaultPrevented property is not overwritable (#5112) + preventDefault: function () { + eventArguments.defaultPrevented = true; + }, + // Setting target to native events fails with clicking + // the zoom-out button in Chrome. + target: el, + // If the type is not set, we're running a custom event + // (#2297). If it is set, we're running a browser event, + // and setting it will cause en error in IE8 (#2465). + type: type + }); + } + var fireInOrder = function (protoEvents, hcEvents) { + if (protoEvents === void 0) { protoEvents = []; } + if (hcEvents === void 0) { hcEvents = []; } + var iA = 0; + var iB = 0; + var length = protoEvents.length + hcEvents.length; + for (i = 0; i < length; i++) { + var obj = (!protoEvents[iA] ? + hcEvents[iB++] : + !hcEvents[iB] ? + protoEvents[iA++] : + protoEvents[iA].order <= hcEvents[iB].order ? + protoEvents[iA++] : + hcEvents[iB++]); + // If the event handler return false, prevent the default + // handler from executing + if (obj.fn.call(el, eventArguments) === false) { + eventArguments.preventDefault(); + } + } + }; + fireInOrder(el.protoEvents && el.protoEvents[type], el.hcEvents && el.hcEvents[type]); + } + // Run the default if not prevented + if (defaultFunction && !eventArguments.defaultPrevented) { + defaultFunction.call(el, eventArguments); + } +}; +/** + * The global animate method, which uses Fx to create individual animators. + * + * @function Highcharts.animate + * + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGElement} el + * The element to animate. + * + * @param {Highcharts.CSSObject|Highcharts.SVGAttributes} params + * An object containing key-value pairs of the properties to animate. + * Supports numeric as pixel-based CSS properties for HTML objects and + * attributes for SVGElements. + * + * @param {Highcharts.AnimationOptionsObject} [opt] + * Animation options. + * + * @return {void} + */ +var animate = H.animate = function (el, params, opt) { + var start, unit = '', end, fx, args; + if (!isObject(opt)) { // Number or undefined/null + args = arguments; + opt = { + duration: args[2], + easing: args[3], + complete: args[4] + }; + } + if (!isNumber(opt.duration)) { + opt.duration = 400; + } + opt.easing = typeof opt.easing === 'function' ? + opt.easing : + (Math[opt.easing] || Math.easeInOutSine); + opt.curAnim = merge(params); + objectEach(params, function (val, prop) { + // Stop current running animation of this property + stop(el, prop); + fx = new Fx(el, opt, prop); + end = null; + if (prop === 'd' && isArray(params.d)) { + fx.paths = fx.initPath(el, el.pathArray, params.d); + fx.toD = params.d; + start = 0; + end = 1; + } + else if (el.attr) { + start = el.attr(prop); + } + else { + start = parseFloat(getStyle(el, prop)) || 0; + if (prop !== 'opacity') { + unit = 'px'; + } + } + if (!end) { + end = val; + } + if (end && end.match && end.match('px')) { + end = end.replace(/px/g, ''); // #4351 + } + fx.run(start, end, unit); + }); +}; +/** + * Factory to create new series prototypes. + * + * @function Highcharts.seriesType + * + * @param {string} type + * The series type name. + * + * @param {string} parent + * The parent series type name. Use `line` to inherit from the basic + * {@link Series} object. + * + * @param {Highcharts.SeriesOptionsType|Highcharts.Dictionary<*>} options + * The additional default options that are merged with the parent's + * options. + * + * @param {Highcharts.Dictionary<*>} [props] + * The properties (functions and primitives) to set on the new + * prototype. + * + * @param {Highcharts.Dictionary<*>} [pointProps] + * Members for a series-specific extension of the {@link Point} + * prototype if needed. + * + * @return {Highcharts.Series} + * The newly created prototype as extended from {@link Series} or its + * derivatives. + */ +// docs: add to API + extending Highcharts +var seriesType = H.seriesType = function (type, parent, options, props, pointProps) { + var defaultOptions = H.getOptions(), seriesTypes = H.seriesTypes; + // Merge the options + defaultOptions.plotOptions[type] = merge(defaultOptions.plotOptions[parent], options); + // Create the class + seriesTypes[type] = extendClass(seriesTypes[parent] || function () { }, props); + seriesTypes[type].prototype.type = type; + // Create the point class if needed + if (pointProps) { + seriesTypes[type].prototype.pointClass = + extendClass(H.Point, pointProps); + } + return seriesTypes[type]; +}; +/** + * Get a unique key for using in internal element id's and pointers. The key is + * composed of a random hash specific to this Highcharts instance, and a + * counter. + * + * @example + * var id = uniqueKey(); // => 'highcharts-x45f6hp-0' + * + * @function Highcharts.uniqueKey + * + * @return {string} + * A unique key. + */ +var uniqueKey = H.uniqueKey = (function () { + var uniqueKeyHash = Math.random().toString(36).substring(2, 9), idCounter = 0; + return function () { + return 'highcharts-' + uniqueKeyHash + '-' + idCounter++; + }; +}()); +var isFunction = H.isFunction = function (obj) { + return typeof obj === 'function'; +}; +// Register Highcharts as a plugin in jQuery +if (win.jQuery) { + /** + * Highcharts-extended JQuery. + * + * @external JQuery + */ + /** + * Helper function to return the chart of the current JQuery selector + * element. + * + * @function external:JQuery#highcharts + * + * @return {Highcharts.Chart} + * The chart that is linked to the JQuery selector element. + */ /** + * Factory function to create a chart in the current JQuery selector + * element. + * + * @function external:JQuery#highcharts + * + * @param {'Chart'|'Map'|'StockChart'|string} [className] + * Name of the factory class in the Highcharts namespace. + * + * @param {Highcharts.Options} [options] + * The chart options structure. + * + * @param {Highcharts.ChartCallbackFunction} [callback] + * Function to run when the chart has loaded and and all external + * images are loaded. Defining a + * [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load) + * handler is equivalent. + * + * @return {JQuery} + * The current JQuery selector. + */ + win.jQuery.fn.highcharts = function () { + var args = [].slice.call(arguments); + if (this[0]) { // this[0] is the renderTo div + // Create the chart + if (args[0]) { + new H[ // eslint-disable-line computed-property-spacing, no-new + // Constructor defaults to Chart + isString(args[0]) ? args.shift() : 'Chart'](this[0], args[0], args[1]); + return this; + } + // When called without parameters or with the return argument, + // return an existing chart + return charts[attr(this[0], 'data-highcharts-chart')]; + } + }; +} +// TODO use named exports when supported. +var utilitiesModule = { + Fx: H.Fx, + addEvent: addEvent, + animate: animate, + animObject: animObject, + arrayMax: arrayMax, + arrayMin: arrayMin, + attr: attr, + clamp: clamp, + clearTimeout: internalClearTimeout, + correctFloat: correctFloat, + createElement: createElement, + css: css, + defined: defined, + destroyObjectProperties: destroyObjectProperties, + discardElement: discardElement, + erase: erase, + error: error, + extend: extend, + extendClass: extendClass, + find: find, + fireEvent: fireEvent, + format: format, + getMagnitude: getMagnitude, + getNestedProperty: getNestedProperty, + getStyle: getStyle, + inArray: inArray, + isArray: isArray, + isClass: isClass, + isDOMElement: isDOMElement, + isFunction: isFunction, + isNumber: isNumber, + isObject: isObject, + isString: isString, + merge: merge, + normalizeTickInterval: normalizeTickInterval, + numberFormat: numberFormat, + objectEach: objectEach, + offset: offset, + pad: pad, + pick: pick, + pInt: pInt, + relativeLength: relativeLength, + removeEvent: removeEvent, + seriesType: seriesType, + setAnimation: setAnimation, + splat: splat, + stableSort: stableSort, + stop: stop, + syncTimeout: syncTimeout, + timeUnits: timeUnits, + uniqueKey: uniqueKey, + wrap: wrap +}; +export default utilitiesModule; diff --git a/librerias/gantt/code/es-modules/themes/avocado.js b/librerias/gantt/code/es-modules/themes/avocado.js new file mode 100644 index 0000000..0280590 --- /dev/null +++ b/librerias/gantt/code/es-modules/themes/avocado.js @@ -0,0 +1,37 @@ +/* * + * + * (c) 2010-2020 Highsoft AS + * + * Author: Øystein Moseng + * + * License: www.highcharts.com/license + * + * Accessible high-contrast theme for Highcharts. Considers colorblindness and + * monochrome rendering. + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Highcharts from '../parts/Globals.js'; +Highcharts.theme = { + colors: ['#F3E796', '#95C471', '#35729E', '#251735'], + colorAxis: { + maxColor: '#05426E', + minColor: '#F3E796' + }, + plotOptions: { + map: { + nullColor: '#FCFEFE' + } + }, + navigator: { + maskFill: 'rgba(170, 205, 170, 0.5)', + series: { + color: '#95C471', + lineColor: '#35729E' + } + } +}; +// Apply the theme +Highcharts.setOptions(Highcharts.theme); diff --git a/librerias/gantt/code/es-modules/themes/dark-blue.js b/librerias/gantt/code/es-modules/themes/dark-blue.js new file mode 100644 index 0000000..c2715b2 --- /dev/null +++ b/librerias/gantt/code/es-modules/themes/dark-blue.js @@ -0,0 +1,254 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * Dark blue theme for Highcharts JS + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Highcharts from '../parts/Globals.js'; +Highcharts.theme = { + colors: ['#DDDF0D', '#55BF3B', '#DF5353', '#7798BF', '#aaeeee', + '#ff0066', '#eeaaee', '#55BF3B', '#DF5353', '#7798BF', '#aaeeee'], + chart: { + backgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 }, + stops: [ + [0, 'rgb(48, 48, 96)'], + [1, 'rgb(0, 0, 0)'] + ] + }, + borderColor: '#000000', + borderWidth: 2, + className: 'dark-container', + plotBackgroundColor: 'rgba(255, 255, 255, .1)', + plotBorderColor: '#CCCCCC', + plotBorderWidth: 1 + }, + title: { + style: { + color: '#C0C0C0', + font: 'bold 16px "Trebuchet MS", Verdana, sans-serif' + } + }, + subtitle: { + style: { + color: '#666666', + font: 'bold 12px "Trebuchet MS", Verdana, sans-serif' + } + }, + xAxis: { + gridLineColor: '#333333', + gridLineWidth: 1, + labels: { + style: { + color: '#A0A0A0' + } + }, + lineColor: '#A0A0A0', + tickColor: '#A0A0A0', + title: { + style: { + color: '#CCC', + fontWeight: 'bold', + fontSize: '12px', + fontFamily: 'Trebuchet MS, Verdana, sans-serif' + } + } + }, + yAxis: { + gridLineColor: '#333333', + labels: { + style: { + color: '#A0A0A0' + } + }, + lineColor: '#A0A0A0', + minorTickInterval: null, + tickColor: '#A0A0A0', + tickWidth: 1, + title: { + style: { + color: '#CCC', + fontWeight: 'bold', + fontSize: '12px', + fontFamily: 'Trebuchet MS, Verdana, sans-serif' + } + } + }, + tooltip: { + backgroundColor: 'rgba(0, 0, 0, 0.75)', + style: { + color: '#F0F0F0' + } + }, + toolbar: { + itemStyle: { + color: 'silver' + } + }, + plotOptions: { + line: { + dataLabels: { + color: '#CCC' + }, + marker: { + lineColor: '#333' + } + }, + spline: { + marker: { + lineColor: '#333' + } + }, + scatter: { + marker: { + lineColor: '#333' + } + }, + candlestick: { + lineColor: 'white' + } + }, + legend: { + backgroundColor: 'rgba(0, 0, 0, 0.5)', + itemStyle: { + font: '9pt Trebuchet MS, Verdana, sans-serif', + color: '#A0A0A0' + }, + itemHoverStyle: { + color: '#FFF' + }, + itemHiddenStyle: { + color: '#444' + }, + title: { + style: { + color: '#C0C0C0' + } + } + }, + credits: { + style: { + color: '#666' + } + }, + labels: { + style: { + color: '#CCC' + } + }, + navigation: { + buttonOptions: { + symbolStroke: '#DDDDDD', + theme: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#606060'], + [0.6, '#333333'] + ] + }, + stroke: '#000000' + } + } + }, + // scroll charts + rangeSelector: { + buttonTheme: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + stroke: '#000000', + style: { + color: '#CCC', + fontWeight: 'bold' + }, + states: { + hover: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#BBB'], + [0.6, '#888'] + ] + }, + stroke: '#000000', + style: { + color: 'white' + } + }, + select: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.1, '#000'], + [0.3, '#333'] + ] + }, + stroke: '#000000', + style: { + color: 'yellow' + } + } + } + }, + inputStyle: { + backgroundColor: '#333', + color: 'silver' + }, + labelStyle: { + color: 'silver' + } + }, + navigator: { + handles: { + backgroundColor: '#666', + borderColor: '#AAA' + }, + outlineColor: '#CCC', + maskFill: 'rgba(16, 16, 16, 0.5)', + series: { + color: '#7798BF', + lineColor: '#A6C7ED' + } + }, + scrollbar: { + barBackgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + barBorderColor: '#CCC', + buttonArrowColor: '#CCC', + buttonBackgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + buttonBorderColor: '#CCC', + rifleColor: '#FFF', + trackBackgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0, '#000'], + [1, '#333'] + ] + }, + trackBorderColor: '#666' + } +}; +// Apply the theme +Highcharts.setOptions(Highcharts.theme); diff --git a/librerias/gantt/code/es-modules/themes/dark-green.js b/librerias/gantt/code/es-modules/themes/dark-green.js new file mode 100644 index 0000000..9f2ca5e --- /dev/null +++ b/librerias/gantt/code/es-modules/themes/dark-green.js @@ -0,0 +1,254 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * Dark blue theme for Highcharts JS + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Highcharts from '../parts/Globals.js'; +Highcharts.theme = { + colors: ['#DDDF0D', '#55BF3B', '#DF5353', '#7798BF', '#aaeeee', + '#ff0066', '#eeaaee', '#55BF3B', '#DF5353', '#7798BF', '#aaeeee'], + chart: { + backgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 }, + stops: [ + [0, 'rgb(48, 96, 48)'], + [1, 'rgb(0, 0, 0)'] + ] + }, + borderColor: '#000000', + borderWidth: 2, + className: 'dark-container', + plotBackgroundColor: 'rgba(255, 255, 255, .1)', + plotBorderColor: '#CCCCCC', + plotBorderWidth: 1 + }, + title: { + style: { + color: '#C0C0C0', + font: 'bold 16px "Trebuchet MS", Verdana, sans-serif' + } + }, + subtitle: { + style: { + color: '#666666', + font: 'bold 12px "Trebuchet MS", Verdana, sans-serif' + } + }, + xAxis: { + gridLineColor: '#333333', + gridLineWidth: 1, + labels: { + style: { + color: '#A0A0A0' + } + }, + lineColor: '#A0A0A0', + tickColor: '#A0A0A0', + title: { + style: { + color: '#CCC', + fontWeight: 'bold', + fontSize: '12px', + fontFamily: 'Trebuchet MS, Verdana, sans-serif' + } + } + }, + yAxis: { + gridLineColor: '#333333', + labels: { + style: { + color: '#A0A0A0' + } + }, + lineColor: '#A0A0A0', + minorTickInterval: null, + tickColor: '#A0A0A0', + tickWidth: 1, + title: { + style: { + color: '#CCC', + fontWeight: 'bold', + fontSize: '12px', + fontFamily: 'Trebuchet MS, Verdana, sans-serif' + } + } + }, + tooltip: { + backgroundColor: 'rgba(0, 0, 0, 0.75)', + style: { + color: '#F0F0F0' + } + }, + toolbar: { + itemStyle: { + color: 'silver' + } + }, + plotOptions: { + line: { + dataLabels: { + color: '#CCC' + }, + marker: { + lineColor: '#333' + } + }, + spline: { + marker: { + lineColor: '#333' + } + }, + scatter: { + marker: { + lineColor: '#333' + } + }, + candlestick: { + lineColor: 'white' + } + }, + legend: { + backgroundColor: 'rgba(0, 0, 0, 0.5)', + itemStyle: { + font: '9pt Trebuchet MS, Verdana, sans-serif', + color: '#A0A0A0' + }, + itemHoverStyle: { + color: '#FFF' + }, + itemHiddenStyle: { + color: '#444' + }, + title: { + style: { + color: '#C0C0C0' + } + } + }, + credits: { + style: { + color: '#666' + } + }, + labels: { + style: { + color: '#CCC' + } + }, + navigation: { + buttonOptions: { + symbolStroke: '#DDDDDD', + theme: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#606060'], + [0.6, '#333333'] + ] + }, + stroke: '#000000' + } + } + }, + // scroll charts + rangeSelector: { + buttonTheme: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + stroke: '#000000', + style: { + color: '#CCC', + fontWeight: 'bold' + }, + states: { + hover: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#BBB'], + [0.6, '#888'] + ] + }, + stroke: '#000000', + style: { + color: 'white' + } + }, + select: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.1, '#000'], + [0.3, '#333'] + ] + }, + stroke: '#000000', + style: { + color: 'yellow' + } + } + } + }, + inputStyle: { + backgroundColor: '#333', + color: 'silver' + }, + labelStyle: { + color: 'silver' + } + }, + navigator: { + handles: { + backgroundColor: '#666', + borderColor: '#AAA' + }, + outlineColor: '#CCC', + maskFill: 'rgba(16, 16, 16, 0.5)', + series: { + color: '#7798BF', + lineColor: '#A6C7ED' + } + }, + scrollbar: { + barBackgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + barBorderColor: '#CCC', + buttonArrowColor: '#CCC', + buttonBackgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + buttonBorderColor: '#CCC', + rifleColor: '#FFF', + trackBackgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0, '#000'], + [1, '#333'] + ] + }, + trackBorderColor: '#666' + } +}; +// Apply the theme +Highcharts.setOptions(Highcharts.theme); diff --git a/librerias/gantt/code/es-modules/themes/dark-unica.js b/librerias/gantt/code/es-modules/themes/dark-unica.js new file mode 100644 index 0000000..60ae2bb --- /dev/null +++ b/librerias/gantt/code/es-modules/themes/dark-unica.js @@ -0,0 +1,215 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * Dark theme for Highcharts JS + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +/* global document */ +// Load the fonts +import Highcharts from '../parts/Globals.js'; +Highcharts.createElement('link', { + href: 'https://fonts.googleapis.com/css?family=Unica+One', + rel: 'stylesheet', + type: 'text/css' +}, null, document.getElementsByTagName('head')[0]); +Highcharts.theme = { + colors: ['#2b908f', '#90ee7e', '#f45b5b', '#7798BF', '#aaeeee', '#ff0066', + '#eeaaee', '#55BF3B', '#DF5353', '#7798BF', '#aaeeee'], + chart: { + backgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 }, + stops: [ + [0, '#2a2a2b'], + [1, '#3e3e40'] + ] + }, + style: { + fontFamily: '\'Unica One\', sans-serif' + }, + plotBorderColor: '#606063' + }, + title: { + style: { + color: '#E0E0E3', + textTransform: 'uppercase', + fontSize: '20px' + } + }, + subtitle: { + style: { + color: '#E0E0E3', + textTransform: 'uppercase' + } + }, + xAxis: { + gridLineColor: '#707073', + labels: { + style: { + color: '#E0E0E3' + } + }, + lineColor: '#707073', + minorGridLineColor: '#505053', + tickColor: '#707073', + title: { + style: { + color: '#A0A0A3' + } + } + }, + yAxis: { + gridLineColor: '#707073', + labels: { + style: { + color: '#E0E0E3' + } + }, + lineColor: '#707073', + minorGridLineColor: '#505053', + tickColor: '#707073', + tickWidth: 1, + title: { + style: { + color: '#A0A0A3' + } + } + }, + tooltip: { + backgroundColor: 'rgba(0, 0, 0, 0.85)', + style: { + color: '#F0F0F0' + } + }, + plotOptions: { + series: { + dataLabels: { + color: '#F0F0F3', + style: { + fontSize: '13px' + } + }, + marker: { + lineColor: '#333' + } + }, + boxplot: { + fillColor: '#505053' + }, + candlestick: { + lineColor: 'white' + }, + errorbar: { + color: 'white' + } + }, + legend: { + backgroundColor: 'rgba(0, 0, 0, 0.5)', + itemStyle: { + color: '#E0E0E3' + }, + itemHoverStyle: { + color: '#FFF' + }, + itemHiddenStyle: { + color: '#606063' + }, + title: { + style: { + color: '#C0C0C0' + } + } + }, + credits: { + style: { + color: '#666' + } + }, + labels: { + style: { + color: '#707073' + } + }, + drilldown: { + activeAxisLabelStyle: { + color: '#F0F0F3' + }, + activeDataLabelStyle: { + color: '#F0F0F3' + } + }, + navigation: { + buttonOptions: { + symbolStroke: '#DDDDDD', + theme: { + fill: '#505053' + } + } + }, + // scroll charts + rangeSelector: { + buttonTheme: { + fill: '#505053', + stroke: '#000000', + style: { + color: '#CCC' + }, + states: { + hover: { + fill: '#707073', + stroke: '#000000', + style: { + color: 'white' + } + }, + select: { + fill: '#000003', + stroke: '#000000', + style: { + color: 'white' + } + } + } + }, + inputBoxBorderColor: '#505053', + inputStyle: { + backgroundColor: '#333', + color: 'silver' + }, + labelStyle: { + color: 'silver' + } + }, + navigator: { + handles: { + backgroundColor: '#666', + borderColor: '#AAA' + }, + outlineColor: '#CCC', + maskFill: 'rgba(255,255,255,0.1)', + series: { + color: '#7798BF', + lineColor: '#A6C7ED' + }, + xAxis: { + gridLineColor: '#505053' + } + }, + scrollbar: { + barBackgroundColor: '#808083', + barBorderColor: '#808083', + buttonArrowColor: '#CCC', + buttonBackgroundColor: '#606063', + buttonBorderColor: '#606063', + rifleColor: '#FFF', + trackBackgroundColor: '#404043', + trackBorderColor: '#404043' + } +}; +// Apply the theme +Highcharts.setOptions(Highcharts.theme); diff --git a/librerias/gantt/code/es-modules/themes/gray.js b/librerias/gantt/code/es-modules/themes/gray.js new file mode 100644 index 0000000..9aa9b24 --- /dev/null +++ b/librerias/gantt/code/es-modules/themes/gray.js @@ -0,0 +1,262 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * Gray theme for Highcharts JS + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Highcharts from '../parts/Globals.js'; +Highcharts.theme = { + colors: ['#DDDF0D', '#7798BF', '#55BF3B', '#DF5353', '#aaeeee', + '#ff0066', '#eeaaee', '#55BF3B', '#DF5353', '#7798BF', '#aaeeee'], + chart: { + backgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0, 'rgb(96, 96, 96)'], + [1, 'rgb(16, 16, 16)'] + ] + }, + borderWidth: 0, + borderRadius: 0, + plotBackgroundColor: null, + plotShadow: false, + plotBorderWidth: 0 + }, + title: { + style: { + color: '#FFF', + font: '16px Lucida Grande, Lucida Sans Unicode,' + + ' Verdana, Arial, Helvetica, sans-serif' + } + }, + subtitle: { + style: { + color: '#DDD', + font: '12px Lucida Grande, Lucida Sans Unicode,' + + ' Verdana, Arial, Helvetica, sans-serif' + } + }, + xAxis: { + gridLineWidth: 0, + lineColor: '#999', + tickColor: '#999', + labels: { + style: { + color: '#999', + fontWeight: 'bold' + } + }, + title: { + style: { + color: '#AAA', + font: 'bold 12px Lucida Grande, Lucida Sans Unicode,' + + ' Verdana, Arial, Helvetica, sans-serif' + } + } + }, + yAxis: { + alternateGridColor: null, + minorTickInterval: null, + gridLineColor: 'rgba(255, 255, 255, .1)', + minorGridLineColor: 'rgba(255,255,255,0.07)', + lineWidth: 0, + tickWidth: 0, + labels: { + style: { + color: '#999', + fontWeight: 'bold' + } + }, + title: { + style: { + color: '#AAA', + font: 'bold 12px Lucida Grande, Lucida Sans Unicode,' + + ' Verdana, Arial, Helvetica, sans-serif' + } + } + }, + legend: { + backgroundColor: 'rgba(48, 48, 48, 0.8)', + itemStyle: { + color: '#CCC' + }, + itemHoverStyle: { + color: '#FFF' + }, + itemHiddenStyle: { + color: '#333' + }, + title: { + style: { + color: '#E0E0E0' + } + } + }, + labels: { + style: { + color: '#CCC' + } + }, + tooltip: { + backgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0, 'rgba(96, 96, 96, .8)'], + [1, 'rgba(16, 16, 16, .8)'] + ] + }, + borderWidth: 0, + style: { + color: '#FFF' + } + }, + plotOptions: { + series: { + dataLabels: { + color: '#444' + }, + nullColor: '#444444' + }, + line: { + dataLabels: { + color: '#CCC' + }, + marker: { + lineColor: '#333' + } + }, + spline: { + marker: { + lineColor: '#333' + } + }, + scatter: { + marker: { + lineColor: '#333' + } + }, + candlestick: { + lineColor: 'white' + } + }, + toolbar: { + itemStyle: { + color: '#CCC' + } + }, + navigation: { + buttonOptions: { + symbolStroke: '#DDDDDD', + theme: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#606060'], + [0.6, '#333333'] + ] + }, + stroke: '#000000' + } + } + }, + // scroll charts + rangeSelector: { + buttonTheme: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + stroke: '#000000', + style: { + color: '#CCC', + fontWeight: 'bold' + }, + states: { + hover: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#BBB'], + [0.6, '#888'] + ] + }, + stroke: '#000000', + style: { + color: 'white' + } + }, + select: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.1, '#000'], + [0.3, '#333'] + ] + }, + stroke: '#000000', + style: { + color: 'yellow' + } + } + } + }, + inputStyle: { + backgroundColor: '#333', + color: 'silver' + }, + labelStyle: { + color: 'silver' + } + }, + navigator: { + handles: { + backgroundColor: '#666', + borderColor: '#AAA' + }, + outlineColor: '#CCC', + maskFill: 'rgba(16, 16, 16, 0.5)', + series: { + color: '#7798BF', + lineColor: '#A6C7ED' + } + }, + scrollbar: { + barBackgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + barBorderColor: '#CCC', + buttonArrowColor: '#CCC', + buttonBackgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + buttonBorderColor: '#CCC', + rifleColor: '#FFF', + trackBackgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0, '#000'], + [1, '#333'] + ] + }, + trackBorderColor: '#666' + } +}; +// Apply the theme +Highcharts.setOptions(Highcharts.theme); diff --git a/librerias/gantt/code/es-modules/themes/grid-light.js b/librerias/gantt/code/es-modules/themes/grid-light.js new file mode 100644 index 0000000..cad72e5 --- /dev/null +++ b/librerias/gantt/code/es-modules/themes/grid-light.js @@ -0,0 +1,77 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * Grid-light theme for Highcharts JS + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +/* global document */ +import Highcharts from '../parts/Globals.js'; +// Load the fonts +Highcharts.createElement('link', { + href: 'https://fonts.googleapis.com/css?family=Dosis:400,600', + rel: 'stylesheet', + type: 'text/css' +}, null, document.getElementsByTagName('head')[0]); +Highcharts.theme = { + colors: ['#7cb5ec', '#f7a35c', '#90ee7e', '#7798BF', '#aaeeee', '#ff0066', + '#eeaaee', '#55BF3B', '#DF5353', '#7798BF', '#aaeeee'], + chart: { + backgroundColor: null, + style: { + fontFamily: 'Dosis, sans-serif' + } + }, + title: { + style: { + fontSize: '16px', + fontWeight: 'bold', + textTransform: 'uppercase' + } + }, + tooltip: { + borderWidth: 0, + backgroundColor: 'rgba(219,219,216,0.8)', + shadow: false + }, + legend: { + backgroundColor: '#F0F0EA', + itemStyle: { + fontWeight: 'bold', + fontSize: '13px' + } + }, + xAxis: { + gridLineWidth: 1, + labels: { + style: { + fontSize: '12px' + } + } + }, + yAxis: { + minorTickInterval: 'auto', + title: { + style: { + textTransform: 'uppercase' + } + }, + labels: { + style: { + fontSize: '12px' + } + } + }, + plotOptions: { + candlestick: { + lineColor: '#404048' + } + } +}; +// Apply the theme +Highcharts.setOptions(Highcharts.theme); diff --git a/librerias/gantt/code/es-modules/themes/grid.js b/librerias/gantt/code/es-modules/themes/grid.js new file mode 100644 index 0000000..adad178 --- /dev/null +++ b/librerias/gantt/code/es-modules/themes/grid.js @@ -0,0 +1,108 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * Grid theme for Highcharts JS + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Highcharts from '../parts/Globals.js'; +Highcharts.theme = { + colors: ['#058DC7', '#50B432', '#ED561B', '#DDDF00', '#24CBE5', '#64E572', + '#FF9655', '#FFF263', '#6AF9C4'], + chart: { + backgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 }, + stops: [ + [0, 'rgb(255, 255, 255)'], + [1, 'rgb(240, 240, 255)'] + ] + }, + borderWidth: 2, + plotBackgroundColor: 'rgba(255, 255, 255, .9)', + plotShadow: true, + plotBorderWidth: 1 + }, + title: { + style: { + color: '#000', + font: 'bold 16px "Trebuchet MS", Verdana, sans-serif' + } + }, + subtitle: { + style: { + color: '#666666', + font: 'bold 12px "Trebuchet MS", Verdana, sans-serif' + } + }, + xAxis: { + gridLineWidth: 1, + lineColor: '#000', + tickColor: '#000', + labels: { + style: { + color: '#000', + font: '11px Trebuchet MS, Verdana, sans-serif' + } + }, + title: { + style: { + color: '#333', + fontWeight: 'bold', + fontSize: '12px', + fontFamily: 'Trebuchet MS, Verdana, sans-serif' + } + } + }, + yAxis: { + minorTickInterval: 'auto', + lineColor: '#000', + lineWidth: 1, + tickWidth: 1, + tickColor: '#000', + labels: { + style: { + color: '#000', + font: '11px Trebuchet MS, Verdana, sans-serif' + } + }, + title: { + style: { + color: '#333', + fontWeight: 'bold', + fontSize: '12px', + fontFamily: 'Trebuchet MS, Verdana, sans-serif' + } + } + }, + legend: { + itemStyle: { + font: '9pt Trebuchet MS, Verdana, sans-serif', + color: 'black' + }, + itemHoverStyle: { + color: '#039' + }, + itemHiddenStyle: { + color: 'gray' + } + }, + labels: { + style: { + color: '#99b' + } + }, + navigation: { + buttonOptions: { + theme: { + stroke: '#CCCCCC' + } + } + } +}; +// Apply the theme +Highcharts.setOptions(Highcharts.theme); diff --git a/librerias/gantt/code/es-modules/themes/high-contrast-dark.js b/librerias/gantt/code/es-modules/themes/high-contrast-dark.js new file mode 100644 index 0000000..02fc622 --- /dev/null +++ b/librerias/gantt/code/es-modules/themes/high-contrast-dark.js @@ -0,0 +1,209 @@ +/* * + * + * (c) 2010-2020 Highsoft AS + * + * Author: Øystein Moseng + * + * License: www.highcharts.com/license + * + * Accessible high-contrast dark theme for Highcharts. Specifically tailored + * towards 3:1 contrast against black/off-black backgrounds. Neighboring + * colors are tested for color blindness. + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Highcharts from '../parts/Globals.js'; +var textBright = '#F0F0F3'; +Highcharts.theme = { + colors: [ + '#a6f0ff', + '#70d49e', + '#e898a5', + '#007faa', + '#f9db72', + '#f45b5b', + '#1e824c', + '#e7934c', + '#dadfe1', + '#a0618b' + ], + chart: { + backgroundColor: '#1f1f20', + plotBorderColor: '#606063' + }, + title: { + style: { + color: textBright + } + }, + subtitle: { + style: { + color: textBright + } + }, + xAxis: { + gridLineColor: '#707073', + labels: { + style: { + color: textBright + } + }, + lineColor: '#707073', + minorGridLineColor: '#505053', + tickColor: '#707073', + title: { + style: { + color: textBright + } + } + }, + yAxis: { + gridLineColor: '#707073', + labels: { + style: { + color: textBright + } + }, + lineColor: '#707073', + minorGridLineColor: '#505053', + tickColor: '#707073', + title: { + style: { + color: textBright + } + } + }, + tooltip: { + backgroundColor: 'rgba(0, 0, 0, 0.85)', + style: { + color: textBright + } + }, + plotOptions: { + series: { + dataLabels: { + color: textBright + }, + marker: { + lineColor: '#333' + } + }, + boxplot: { + fillColor: '#505053' + }, + candlestick: { + lineColor: 'white' + }, + errorbar: { + color: 'white' + }, + map: { + nullColor: '#353535' + } + }, + legend: { + backgroundColor: 'transparent', + itemStyle: { + color: textBright + }, + itemHoverStyle: { + color: '#FFF' + }, + itemHiddenStyle: { + color: '#606063' + }, + title: { + style: { + color: '#D0D0D0' + } + } + }, + credits: { + style: { + color: textBright + } + }, + labels: { + style: { + color: '#707073' + } + }, + drilldown: { + activeAxisLabelStyle: { + color: textBright + }, + activeDataLabelStyle: { + color: textBright + } + }, + navigation: { + buttonOptions: { + symbolStroke: '#DDDDDD', + theme: { + fill: '#505053' + } + } + }, + rangeSelector: { + buttonTheme: { + fill: '#505053', + stroke: '#000000', + style: { + color: '#eee' + }, + states: { + hover: { + fill: '#707073', + stroke: '#000000', + style: { + color: textBright + } + }, + select: { + fill: '#303030', + stroke: '#101010', + style: { + color: textBright + } + } + } + }, + inputBoxBorderColor: '#505053', + inputStyle: { + backgroundColor: '#333', + color: textBright + }, + labelStyle: { + color: textBright + } + }, + navigator: { + handles: { + backgroundColor: '#666', + borderColor: '#AAA' + }, + outlineColor: '#CCC', + maskFill: 'rgba(180,180,255,0.2)', + series: { + color: '#7798BF', + lineColor: '#A6C7ED' + }, + xAxis: { + gridLineColor: '#505053' + } + }, + scrollbar: { + barBackgroundColor: '#808083', + barBorderColor: '#808083', + buttonArrowColor: '#CCC', + buttonBackgroundColor: '#606063', + buttonBorderColor: '#606063', + rifleColor: '#FFF', + trackBackgroundColor: '#404043', + trackBorderColor: '#404043' + } +}; +// Apply the theme +Highcharts.setOptions(Highcharts.theme); diff --git a/librerias/gantt/code/es-modules/themes/high-contrast-light.js b/librerias/gantt/code/es-modules/themes/high-contrast-light.js new file mode 100644 index 0000000..8e16e09 --- /dev/null +++ b/librerias/gantt/code/es-modules/themes/high-contrast-light.js @@ -0,0 +1,39 @@ +/* * + * + * (c) 2010-2020 Highsoft AS + * + * Author: Øystein Moseng + * + * License: www.highcharts.com/license + * + * Accessible high-contrast theme for Highcharts. Specifically tailored + * towards 3:1 contrast against white/off-white backgrounds. Neighboring + * colors are tested for color blindness. + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Highcharts from '../parts/Globals.js'; +Highcharts.theme = { + colors: [ + '#5f98cf', + '#434348', + '#49a65e', + '#f45b5b', + '#708090', + '#b68c51', + '#397550', + '#c0493d', + '#4f4a7a', + '#b381b3' + ], + navigator: { + series: { + color: '#5f98cf', + lineColor: '#5f98cf' + } + } +}; +// Apply the theme +Highcharts.setOptions(Highcharts.theme); diff --git a/librerias/gantt/code/es-modules/themes/sand-signika.js b/librerias/gantt/code/es-modules/themes/sand-signika.js new file mode 100644 index 0000000..588abac --- /dev/null +++ b/librerias/gantt/code/es-modules/themes/sand-signika.js @@ -0,0 +1,111 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * Sand-Signika theme for Highcharts JS + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +/* global document */ +import Highcharts from '../parts/Globals.js'; +// Load the fonts +Highcharts.createElement('link', { + href: 'https://fonts.googleapis.com/css?family=Signika:400,700', + rel: 'stylesheet', + type: 'text/css' +}, null, document.getElementsByTagName('head')[0]); +// Add the background image to the container +Highcharts.addEvent(Highcharts.Chart, 'afterGetContainer', function () { + // eslint-disable-next-line no-invalid-this + this.container.style.background = + 'url(https://www.highcharts.com/samples/graphics/sand.png)'; +}); +Highcharts.theme = { + colors: ['#f45b5b', '#8085e9', '#8d4654', '#7798BF', '#aaeeee', + '#ff0066', '#eeaaee', '#55BF3B', '#DF5353', '#7798BF', '#aaeeee'], + chart: { + backgroundColor: null, + style: { + fontFamily: 'Signika, serif' + } + }, + title: { + style: { + color: 'black', + fontSize: '16px', + fontWeight: 'bold' + } + }, + subtitle: { + style: { + color: 'black' + } + }, + tooltip: { + borderWidth: 0 + }, + labels: { + style: { + color: '#6e6e70' + } + }, + legend: { + backgroundColor: '#E0E0E8', + itemStyle: { + fontWeight: 'bold', + fontSize: '13px' + } + }, + xAxis: { + labels: { + style: { + color: '#6e6e70' + } + } + }, + yAxis: { + labels: { + style: { + color: '#6e6e70' + } + } + }, + plotOptions: { + series: { + shadow: true + }, + candlestick: { + lineColor: '#404048' + }, + map: { + shadow: false + } + }, + // Highstock specific + navigator: { + xAxis: { + gridLineColor: '#D0D0D8' + } + }, + rangeSelector: { + buttonTheme: { + fill: 'white', + stroke: '#C0C0C8', + 'stroke-width': 1, + states: { + select: { + fill: '#D0D0D8' + } + } + } + }, + scrollbar: { + trackBorderColor: '#C0C0C8' + } +}; +// Apply the theme +Highcharts.setOptions(Highcharts.theme); diff --git a/librerias/gantt/code/es-modules/themes/skies.js b/librerias/gantt/code/es-modules/themes/skies.js new file mode 100644 index 0000000..0e07a4f --- /dev/null +++ b/librerias/gantt/code/es-modules/themes/skies.js @@ -0,0 +1,101 @@ +/* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * Skies theme for Highcharts JS + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Highcharts from '../parts/Globals.js'; +Highcharts.theme = { + colors: ['#514F78', '#42A07B', '#9B5E4A', '#72727F', '#1F949A', + '#82914E', '#86777F', '#42A07B'], + chart: { + className: 'skies', + borderWidth: 0, + plotShadow: true, + plotBackgroundImage: 'https://www.highcharts.com/demo/gfx/skies.jpg', + plotBackgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 }, + stops: [ + [0, 'rgba(255, 255, 255, 1)'], + [1, 'rgba(255, 255, 255, 0)'] + ] + }, + plotBorderWidth: 1 + }, + title: { + style: { + color: '#3E576F', + font: '16px Lucida Grande, Lucida Sans Unicode,' + + ' Verdana, Arial, Helvetica, sans-serif' + } + }, + subtitle: { + style: { + color: '#6D869F', + font: '12px Lucida Grande, Lucida Sans Unicode,' + + ' Verdana, Arial, Helvetica, sans-serif' + } + }, + xAxis: { + gridLineWidth: 0, + lineColor: '#C0D0E0', + tickColor: '#C0D0E0', + labels: { + style: { + color: '#666', + fontWeight: 'bold' + } + }, + title: { + style: { + color: '#666', + font: '12px Lucida Grande, Lucida Sans Unicode,' + + ' Verdana, Arial, Helvetica, sans-serif' + } + } + }, + yAxis: { + alternateGridColor: 'rgba(255, 255, 255, .5)', + lineColor: '#C0D0E0', + tickColor: '#C0D0E0', + tickWidth: 1, + labels: { + style: { + color: '#666', + fontWeight: 'bold' + } + }, + title: { + style: { + color: '#666', + font: '12px Lucida Grande, Lucida Sans Unicode,' + + ' Verdana, Arial, Helvetica, sans-serif' + } + } + }, + legend: { + itemStyle: { + font: '9pt Trebuchet MS, Verdana, sans-serif', + color: '#3E576F' + }, + itemHoverStyle: { + color: 'black' + }, + itemHiddenStyle: { + color: 'silver' + } + }, + labels: { + style: { + color: '#3E576F' + } + } +}; +// Apply the theme +Highcharts.setOptions(Highcharts.theme); diff --git a/librerias/gantt/code/es-modules/themes/sunset.js b/librerias/gantt/code/es-modules/themes/sunset.js new file mode 100644 index 0000000..7c0b2c0 --- /dev/null +++ b/librerias/gantt/code/es-modules/themes/sunset.js @@ -0,0 +1,36 @@ +/* * + * + * (c) 2010-2020 Highsoft AS + * + * Author: Øystein Moseng + * + * License: www.highcharts.com/license + * + * Accessible high-contrast theme for Highcharts. Considers colorblindness and + * monochrome rendering. + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ +'use strict'; +import Highcharts from '../parts/Globals.js'; +Highcharts.theme = { + colors: ['#FDD089', '#FF7F79', '#A0446E', '#251535'], + colorAxis: { + maxColor: '#60042E', + minColor: '#FDD089' + }, + plotOptions: { + map: { + nullColor: '#fefefc' + } + }, + navigator: { + series: { + color: '#FF7F79', + lineColor: '#A0446E' + } + } +}; +// Apply the theme +Highcharts.setOptions(Highcharts.theme); diff --git a/librerias/gantt/code/highcharts-gantt.js b/librerias/gantt/code/highcharts-gantt.js new file mode 100644 index 0000000..2e73482 --- /dev/null +++ b/librerias/gantt/code/highcharts-gantt.js @@ -0,0 +1,704 @@ +/* + Highcharts Gantt JS v8.1.0 (2020-05-05) + + (c) 2017-2018 Lars Cabrera, Torstein Honsi, Jon Arild Nygard & Oystein Moseng + + License: www.highcharts.com/license +*/ +(function(T,P){"object"===typeof module&&module.exports?(P["default"]=P,module.exports=T.document?P(T):P):"function"===typeof define&&define.amd?define("highcharts/highcharts-gantt",function(){return P(T)}):(T.Highcharts&&T.Highcharts.error(16,!0),T.Highcharts=P(T))})("undefined"!==typeof window?window:this,function(T){function P(l,e,B,t){l.hasOwnProperty(e)||(l[e]=t.apply(null,B))}var x={};P(x,"parts/Globals.js",[],function(){var l="undefined"!==typeof T?T:"undefined"!==typeof window?window:{},e= +l.document,B=l.navigator&&l.navigator.userAgent||"",t=e&&e.createElementNS&&!!e.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect,N=/(edge|msie|trident)/i.test(B)&&!l.opera,H=-1!==B.indexOf("Firefox"),L=-1!==B.indexOf("Chrome"),K=H&&4>parseInt(B.split("Firefox/")[1],10);return{product:"Highcharts",version:"8.1.0",deg2rad:2*Math.PI/360,doc:e,hasBidiBug:K,hasTouch:!!l.TouchEvent,isMS:N,isWebKit:-1!==B.indexOf("AppleWebKit"),isFirefox:H,isChrome:L,isSafari:!L&&-1!==B.indexOf("Safari"), +isTouchDevice:/(Mobile|Android|Windows Phone)/.test(B),SVG_NS:"http://www.w3.org/2000/svg",chartCount:0,seriesTypes:{},symbolSizes:{},svg:t,win:l,marginNames:["plotTop","marginRight","marginBottom","plotLeft"],noop:function(){},charts:[],dateFormats:{}}});P(x,"parts/Utilities.js",[x["parts/Globals.js"]],function(l){function e(){var d,h=arguments,a={},b=function(d,h){"object"!==typeof d&&(d={});R(h,function(a,c){!B(a,!0)||m(a)||q(a)?d[c]=h[c]:d[c]=b(d[c]||{},a)});return d};!0===h[0]&&(a=h[1],h=Array.prototype.slice.call(h, +2));var c=h.length;for(d=0;dc)for(var b=0;b=G+this.startTime){this.now=this.end;this.pos=1;this.update();var f=M[this.prop]=!0;R(M,function(d){!0!==d&&(f=!1)}); +f&&b&&b.call(c);d=!1}else this.pos=a.easing((h-this.startTime)/G),this.now=this.start+(this.end-this.start)*this.pos,this.update(),d=!0;return d};d.prototype.initPath=function(d,h,a){function c(d,h){for(;d.lengthd&&-Infinity=a&&(h=[1/a])));for(c=0;c=d||!b&&M<=(h[c]+(h[c+1]||h[c]))/2);c++);return G=S(G*a,-Math.round(Math.log(.001)/Math.LN10))},h=l.stableSort=function(d,h){var a=d.length,c,b;for(b=0;ba&&(a=d[h]);return a},M=l.destroyObjectProperties=function(d,h){R(d,function(a,c){a&&a!==h&&a.destroy&&a.destroy();delete d[c]})},Q=l.discardElement=function(d){var h=l.garbageBin;h||(h=p("div"));d&&h.appendChild(d);h.innerHTML=""},S=l.correctFloat=function(d,h){return parseFloat(d.toPrecision(h||14))},Z=l.setAnimation=function(d,h){h.renderer.globalAnimation=N(d,h.options.chart.animation, +!0)},U=l.animObject=function(d){return B(d)?e(d):{duration:d?500:0}},W=l.timeUnits={millisecond:1,second:1E3,minute:6E4,hour:36E5,day:864E5,week:6048E5,month:24192E5,year:314496E5},V=l.numberFormat=function(d,h,a,c){d=+d||0;h=+h;var b=l.defaultOptions.lang,G=(d.toString().split(".")[1]||"").split("e")[0].length,M=d.toString().split("e");if(-1===h)h=Math.min(G,20);else if(!u(h))h=2;else if(h&&M[1]&&0>M[1]){var f=h+ +M[1];0<=f?(M[0]=(+M[0]).toExponential(f).split("e")[0],h=f):(M[0]=M[0].split(".")[0]|| +0,d=20>h?(M[0]*Math.pow(10,M[1])).toFixed(h):0,M[1]=0)}var g=(Math.abs(M[1]?M[0]:d)+Math.pow(10,-Math.max(h,G)-1)).toFixed(h);G=String(y(g));f=3d?"-":"")+(f?G.substr(0,f)+c:"");d+=G.substr(f).replace(/(\d{3})(?=\d)/g,"$1"+c);h&&(d+=a+g.slice(-h));M[1]&&0!==+d&&(d+="e"+M[1]);return d};Math.easeInOutSine=function(d){return-.5*(Math.cos(Math.PI*d)-1)};var ea=l.getStyle=function(d,h,a){if("width"===h)return h=Math.min(d.offsetWidth, +d.scrollWidth),a=d.getBoundingClientRect&&d.getBoundingClientRect().width,a=h-1&&(h=Math.floor(a)),Math.max(0,h-l.getStyle(d,"padding-left")-l.getStyle(d,"padding-right"));if("height"===h)return Math.max(0,Math.min(d.offsetHeight,d.scrollHeight)-l.getStyle(d,"padding-top")-l.getStyle(d,"padding-bottom"));E.getComputedStyle||C(27,!0);if(d=E.getComputedStyle(d,void 0))d=d.getPropertyValue(h),N(a,"opacity"!==h)&&(d=y(d));return d},ca=l.inArray=function(d,h,a){return h.indexOf(d,a)},X=l.find=Array.prototype.find? +function(d,h){return d.find(h)}:function(d,h){var a,c=d.length;for(a=0;ah?d>16,(e&65280)>>8,e&255,1]:4===C&&(t=[(e&3840)>>4|(e&3840)>>8,(e&240)>>4|e&240,(e&15)<<4|e&15,1])}if(!t)for(E=this.parsers.length;E--&& +!t;){var J=this.parsers[E];(C=J.regex.exec(e))&&(t=J.parse(C))}}this.rgba=t||[]};l.prototype.get=function(e){var l=this.input,E=this.rgba;if("undefined"!==typeof this.stops){var C=t(l);C.stops=[].concat(C.stops);this.stops.forEach(function(l,y){C.stops[y]=[C.stops[y][0],l.get(e)]})}else C=E&&B(E[0])?"rgb"===e||!e&&1===E[3]?"rgb("+E[0]+","+E[1]+","+E[2]+")":"a"===e?E[3]:"rgba("+E.join(",")+")":l;return C};l.prototype.brighten=function(e){var l,E=this.rgba;if(this.stops)this.stops.forEach(function(l){l.brighten(e)}); +else if(B(e)&&0!==e)for(l=0;3>l;l++)E[l]+=N(255*e),0>E[l]&&(E[l]=0),255a.width)a={width:0,height:0}}else a=this.htmlGetBBox();b.isSVG&& +(h=a.width,b=a.height,w&&(a.height=b={"11px,17":14,"13px,20":16}[p&&p.fontSize+","+Math.round(b)]||b),d&&(p=d*t,a.width=Math.abs(b*Math.sin(p))+Math.abs(h*Math.cos(p)),a.height=Math.abs(b*Math.cos(p))+Math.abs(h*Math.sin(p))));if(I&&0]*>/g,"").replace(/</g,"<").replace(/>/g,">")))};D.prototype.toFront=function(){var h=this.element;h.parentNode.appendChild(h);return this};D.prototype.translate=function(h,d){return this.attr({translateX:h,translateY:d})};D.prototype.updateShadows=function(h,d,a){var c=this.shadows; +if(c)for(var b=c.length;b--;)a.call(c[b],"height"===h?Math.max(d-(c[b].cutHeight||0),0):"d"===h?this.d:d,h,c[b])};D.prototype.updateTransform=function(){var h=this.translateX||0,d=this.translateY||0,a=this.scaleX,c=this.scaleY,b=this.inverted,f=this.rotation,g=this.matrix,p=this.element;b&&(h+=this.width,d+=this.height);h=["translate("+h+","+d+")"];u(g)&&h.push("matrix("+g.join(",")+")");b?h.push("rotate(90) scale(-1,1)"):f&&h.push("rotate("+f+" "+v(this.rotationOriginX,p.getAttribute("x"),0)+" "+ +v(this.rotationOriginY,p.getAttribute("y")||0)+")");(u(a)||u(c))&&h.push("scale("+v(a,1)+" "+v(c,1)+")");h.length&&p.setAttribute("transform",h.join(" "))};D.prototype.visibilitySetter=function(h,d,a){"inherit"===h?a.removeAttribute(d):this[d]!==h&&a.setAttribute(d,h);this[d]=h};D.prototype.xGetter=function(h){"circle"===this.element.nodeName&&("x"===h?h="cx":"y"===h&&(h="cy"));return this._defaultGetter(h)};D.prototype.zIndexSetter=function(h,d){var a=this.renderer,c=this.parentGroup,b=(c||a).element|| +a.box,f=this.element,g=!1;a=b===a.box;var p=this.added;var r;u(h)?(f.setAttribute("data-z-index",h),h=+h,this[d]===h&&(p=!1)):u(this[d])&&f.removeAttribute("data-z-index");this[d]=h;if(p){(h=this.zIndex)&&c&&(c.handleZ=!0);d=b.childNodes;for(r=d.length-1;0<=r&&!g;r--){c=d[r];p=c.getAttribute("data-z-index");var k=!u(p);if(c!==f)if(0>h&&k&&!a&&!r)b.insertBefore(f,d[r]),g=!0;else if(n(p)<=h||k&&(!u(h)||0<=h))b.insertBefore(f,d[r+1]||null),g=!0}g||(b.insertBefore(f,d[a?3:0]||null),g=!0)}return g};return D}(); +B.prototype["stroke-widthSetter"]=B.prototype.strokeSetter;B.prototype.yGetter=B.prototype.xGetter;B.prototype.matrixSetter=B.prototype.rotationOriginXSetter=B.prototype.rotationOriginYSetter=B.prototype.rotationSetter=B.prototype.scaleXSetter=B.prototype.scaleYSetter=B.prototype.translateXSetter=B.prototype.translateYSetter=B.prototype.verticalAlignSetter=function(a,h){this[h]=a;this.doTransform=!0};e.SVGElement=B;return e.SVGElement});P(x,"parts/SvgRenderer.js",[x["parts/Color.js"],x["parts/Globals.js"], +x["parts/SVGElement.js"],x["parts/Utilities.js"]],function(l,e,B,t){var N=l.parse,H=t.addEvent,L=t.attr,K=t.createElement,E=t.css,C=t.defined,J=t.destroyObjectProperties,y=t.extend,A=t.isArray,z=t.isNumber,q=t.isObject,m=t.isString,u=t.merge,k=t.objectEach,g=t.pick,b=t.pInt,f=t.removeEvent,a=t.splat,c=t.uniqueKey,r=e.charts,p=e.deg2rad,I=e.doc,w=e.isFirefox,v=e.isMS,n=e.isWebKit;t=e.noop;var F=e.svg,O=e.SVG_NS,D=e.symbolSizes,h=e.win;l=e.SVGRenderer=function(){this.init.apply(this,arguments)};y(l.prototype, +{Element:B,SVG_NS:O,init:function(d,a,c,b,f,g,p){var G=this.createElement("svg").attr({version:"1.1","class":"highcharts-root"});p||G.css(this.getStyle(b));b=G.element;d.appendChild(b);L(d,"dir","ltr");-1===d.innerHTML.indexOf("xmlns")&&L(b,"xmlns",this.SVG_NS);this.isSVG=!0;this.box=b;this.boxWrapper=G;this.alignedObjects=[];this.url=(w||n)&&I.getElementsByTagName("base").length?h.location.href.split("#")[0].replace(/<[^>]*>/g,"").replace(/([\('\)])/g,"\\$1").replace(/ /g,"%20"):"";this.createElement("desc").add().element.appendChild(I.createTextNode("Created with Highcharts 8.1.0")); +this.defs=this.createElement("defs").add();this.allowHTML=g;this.forExport=f;this.styledMode=p;this.gradients={};this.cache={};this.cacheKeys=[];this.imgCount=0;this.setSize(a,c,!1);var M;w&&d.getBoundingClientRect&&(a=function(){E(d,{left:0,top:0});M=d.getBoundingClientRect();E(d,{left:Math.ceil(M.left)-M.left+"px",top:Math.ceil(M.top)-M.top+"px"})},a(),this.unSubPixelFix=H(h,"resize",a))},definition:function(d){function h(d,b){var f;a(d).forEach(function(d){var a=c.createElement(d.tagName),G={}; +k(d,function(d,h){"tagName"!==h&&"children"!==h&&"textContent"!==h&&(G[h]=d)});a.attr(G);a.add(b||c.defs);d.textContent&&a.element.appendChild(I.createTextNode(d.textContent));h(d.children||[],a);f=a});return f}var c=this;return h(d)},getStyle:function(d){return this.style=y({fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif',fontSize:"12px"},d)},setStyle:function(d){this.boxWrapper.css(this.getStyle(d))},isHidden:function(){return!this.boxWrapper.getBBox().width},destroy:function(){var d= +this.defs;this.box=null;this.boxWrapper=this.boxWrapper.destroy();J(this.gradients||{});this.gradients=null;d&&(this.defs=d.destroy());this.unSubPixelFix&&this.unSubPixelFix();return this.alignedObjects=null},createElement:function(d){var h=new this.Element;h.init(this,d);return h},draw:t,getRadialAttr:function(d,h){return{cx:d[0]-d[2]/2+h.cx*d[2],cy:d[1]-d[2]/2+h.cy*d[2],r:h.r*d[2]}},truncate:function(d,h,a,c,b,f,g){var G=this,M=d.rotation,p,r=c?1:0,k=(a||c).length,n=k,w=[],v=function(d){h.firstChild&& +h.removeChild(h.firstChild);d&&h.appendChild(I.createTextNode(d))},F=function(f,M){M=M||f;if("undefined"===typeof w[M])if(h.getSubStringLength)try{w[M]=b+h.getSubStringLength(0,c?M+1:M)}catch(ha){""}else G.getSpanWidth&&(v(g(a||c,f)),w[M]=b+G.getSpanWidth(d,h));return w[M]},Q;d.rotation=0;var S=F(h.textContent.length);if(Q=b+S>f){for(;r<=k;)n=Math.ceil((r+k)/2),c&&(p=g(c,n)),S=F(n,p&&p.length-1),r===k?r=k+1:S>f?k=n-1:r=n;0===k?v(""):a&&k===a.length-1||v(p||g(a||c,n))}c&&c.splice(0,n);d.actualWidth= +S;d.rotation=M;return Q},escapes:{"&":"&","<":"<",">":">","'":"'",'"':"""},buildText:function(d){var h=d.element,a=this,c=a.forExport,f=g(d.textStr,"").toString(),p=-1!==f.indexOf("<"),r=h.childNodes,n,w=L(h,"x"),v=d.styles,m=d.textWidth,D=v&&v.lineHeight,q=v&&v.textOutline,u=v&&"ellipsis"===v.textOverflow,z=v&&"nowrap"===v.whiteSpace,l=v&&v.fontSize,e,y=r.length;v=m&&!d.added&&this.box;var A=function(d){var c;a.styledMode||(c=/(px|em)$/.test(d&&d.style.fontSize)?d.style.fontSize: +l||a.style.fontSize||12);return D?b(D):a.fontMetrics(c,d.getAttribute("style")?d:h).h},C=function(d,h){k(a.escapes,function(a,c){h&&-1!==h.indexOf(a)||(d=d.toString().replace(new RegExp(a,"g"),c))});return d},J=function(d,h){var a=d.indexOf("<");d=d.substring(a,d.indexOf(">")-a);a=d.indexOf(h+"=");if(-1!==a&&(a=a+h.length+1,h=d.charAt(a),'"'===h||"'"===h))return d=d.substring(a+1),d.substring(0,d.indexOf(h))},t=//g;var K=[f,u,z,D,q,l,m].join();if(K!==d.textCache){for(d.textCache=K;y--;)h.removeChild(r[y]); +p||q||u||m||-1!==f.indexOf(" ")&&(!z||t.test(f))?(v&&v.appendChild(h),p?(f=a.styledMode?f.replace(/<(b|strong)>/g,'').replace(/<(i|em)>/g,''):f.replace(/<(b|strong)>/g,'').replace(/<(i|em)>/g,''),f=f.replace(//g,"").split(t)):f=[f],f=f.filter(function(d){return""!==d}),f.forEach(function(b,f){var G=0,M=0;b=b.replace(/^\s+|\s+$/g, +"").replace(//g,"|||");var g=b.split("|||");g.forEach(function(b){if(""!==b||1===g.length){var p={},r=I.createElementNS(a.SVG_NS,"tspan"),k,v;(k=J(b,"class"))&&L(r,"class",k);if(k=J(b,"style"))k=k.replace(/(;| |^)color([ :])/,"$1fill$2"),L(r,"style",k);(v=J(b,"href"))&&!c&&(L(r,"onclick",'location.href="'+v+'"'),L(r,"class","highcharts-anchor"),a.styledMode||E(r,{cursor:"pointer"}));b=C(b.replace(/<[a-zA-Z\/](.|\n)*?>/g,"")||" ");if(" "!==b){r.appendChild(I.createTextNode(b)); +G?p.dx=0:f&&null!==w&&(p.x=w);L(r,p);h.appendChild(r);!G&&e&&(!F&&c&&E(r,{display:"block"}),L(r,"dy",A(r)));if(m){var Q=b.replace(/([^\^])-/g,"$1- ").split(" ");p=!z&&(1Math.abs(b.end-b.start-2*Math.PI));var M=Math.cos(f),k=Math.sin(f),n=Math.cos(r);r=Math.sin(r);f=g(b.longArc,.001>b.end-f-Math.PI?0:1);G=[["M",d+G*M,h+p*k],["A",G,p,0,f,g(b.clockwise,1),d+G*n,h+p*r]];C(a)&&G.push(c?["M",d+a*n,h+a*r]:["L",d+a*n,h+a*r],["A",a,a,0,f,C(b.clockwise)?1-b.clockwise:0,d+a*M,h+a*k]);c||G.push(["Z"]);return G},callout:function(d,h,a,c,b){var f=Math.min(b&&b.r||0,a,c),p=f+6,g= +b&&b.anchorX;b=b&&b.anchorY;var r=[["M",d+f,h],["L",d+a-f,h],["C",d+a,h,d+a,h,d+a,h+f],["L",d+a,h+c-f],["C",d+a,h+c,d+a,h+c,d+a-f,h+c],["L",d+f,h+c],["C",d,h+c,d,h+c,d,h+c-f],["L",d,h+f],["C",d,h,d,h,d+f,h]];g&&g>a?b>h+p&&bg?b>h+p&&bc&&g>d+p&&gb&&g>d+p&&gd?d+3:Math.round(1.2*d);return{h:a, +b:Math.round(.8*a),f:d}},rotCorr:function(d,h,a){var c=d;h&&a&&(c=Math.max(c*Math.cos(h*p),4));return{x:-d/3*Math.sin(h*p),y:c}},pathToSegments:function(d){for(var h=[],a=[],c={A:8,C:7,H:2,L:3,M:3,Q:5,S:5,T:3,V:2},b=0;bthis.oldTextWidth)&&((w=this.textPxLength)||(N(m,{width:"",whiteSpace:r||"nowrap"}),w=m.offsetWidth),w=w>p);w&&(/[ \-]/.test(m.textContent||m.innerText)||"ellipsis"===m.style.textOverflow)?(N(m,{width:p+"px",display:"block",whiteSpace:r||"normal"}),this.oldTextWidth=p,this.hasBoxWidthChanged=!0):this.hasBoxWidthChanged=!1;I!==this.cTT&& +(r=q.fontMetrics(m.style.fontSize,m).b,!H(c)||c===(this.oldRotation||0)&&f===this.oldAlign||this.setSpanRotation(c,a,r),this.getSpanCorrection(!H(c)&&this.textPxLength||m.offsetWidth,r,a,c,f));N(m,{left:g+(this.xCorr||0)+"px",top:b+(this.yCorr||0)+"px"});this.cTT=I;this.oldRotation=c;this.oldAlign=f}}else this.alignOnAdd=!0},setSpanRotation:function(q,m,u){var k={},g=this.renderer.getTransformKey();k[g]=k.transform="rotate("+q+"deg)";k[g+(C?"Origin":"-origin")]=k.transformOrigin=100*m+"% "+u+"px"; +N(this.element,k)},getSpanCorrection:function(q,m,u){this.xCorr=-q*u;this.yCorr=-m}});L(e.prototype,{getTransformKey:function(){return J&&!/Edge/.test(z.navigator.userAgent)?"-ms-transform":y?"-webkit-transform":C?"MozTransform":z.opera?"-o-transform":""},html:function(q,m,u){var k=this.createElement("span"),g=k.element,b=k.renderer,f=b.isSVG,a=function(a,b){["opacity","visibility"].forEach(function(c){a[c+"Setter"]=function(f,g,p){var r=a.div?a.div.style:b;A.prototype[c+"Setter"].call(this,f,g,p); +r&&(r[g]=f)}});a.addedSetters=!0};k.textSetter=function(a){a!==g.innerHTML&&(delete this.bBox,delete this.oldTextWidth);this.textStr=a;g.innerHTML=K(a,"");k.doTransform=!0};f&&a(k,k.element.style);k.xSetter=k.ySetter=k.alignSetter=k.rotationSetter=function(a,b){"align"===b&&(b="textAlign");k[b]=a;k.doTransform=!0};k.afterSetters=function(){this.doTransform&&(this.htmlUpdateTransform(),this.doTransform=!1)};k.attr({text:q,x:Math.round(m),y:Math.round(u)}).css({position:"absolute"});b.styledMode||k.css({fontFamily:this.style.fontFamily, +fontSize:this.style.fontSize});g.style.whiteSpace="nowrap";k.css=k.htmlCss;f&&(k.add=function(c){var f=b.box.parentNode,p=[];if(this.parentGroup=c){var I=c.div;if(!I){for(;c;)p.push(c),c=c.parentGroup;p.reverse().forEach(function(c){function b(a,b){c[b]=a;"translateX"===b?r.left=a+"px":r.top=a+"px";c.doTransform=!0}var g=B(c.element,"class");I=c.div=c.div||t("div",g?{className:g}:void 0,{position:"absolute",left:(c.translateX||0)+"px",top:(c.translateY||0)+"px",display:c.display,opacity:c.opacity, +pointerEvents:c.styles&&c.styles.pointerEvents},I||f);var r=I.style;L(c,{classSetter:function(a){return function(c){this.element.setAttribute("class",c);a.className=c}}(I),on:function(){p[0].div&&k.on.apply({element:p[0].div},arguments);return c},translateXSetter:b,translateYSetter:b});c.addedSetters||a(c)})}}else I=f;I.appendChild(g);k.added=!0;k.alignOnAdd&&k.htmlUpdateTransform();return k});return k}})});P(x,"parts/Tick.js",[x["parts/Globals.js"],x["parts/Utilities.js"]],function(l,e){var B=e.clamp, +t=e.correctFloat,N=e.defined,H=e.destroyObjectProperties,L=e.extend,K=e.fireEvent,E=e.isNumber,C=e.merge,J=e.objectEach,y=e.pick,A=l.deg2rad;e=function(){function z(q,m,u,k,g){this.isNewLabel=this.isNew=!0;this.axis=q;this.pos=m;this.type=u||"";this.parameters=g||{};this.tickmarkOffset=this.parameters.tickmarkOffset;this.options=this.parameters.options;K(this,"init");u||k||this.addLabel()}z.prototype.addLabel=function(){var q=this,m=q.axis,u=m.options,k=m.chart,g=m.categories,b=m.logarithmic,f=m.names, +a=q.pos,c=y(q.options&&q.options.labels,u.labels),r=m.tickPositions,p=a===r[0],I=a===r[r.length-1];f=this.parameters.category||(g?y(g[a],f[a],a):a);var w=q.label;g=(!c.step||1===c.step)&&1===m.tickInterval;r=r.info;var v,n;if(m.dateTime&&r){var F=k.time.resolveDTLFormat(u.dateTimeLabelFormats[!u.grid&&r.higherRanks[a]||r.unitName]);var O=F.main}q.isFirst=p;q.isLast=I;q.formatCtx={axis:m,chart:k,isFirst:p,isLast:I,dateTimeLabelFormat:O,tickPositionInfo:r,value:b?t(b.lin2log(f)):f,pos:a};u=m.labelFormatter.call(q.formatCtx, +this.formatCtx);if(n=F&&F.list)q.shortenLabel=function(){for(v=0;vc&&k-r*pb&&(n=Math.round((g-k)/Math.cos(c* +A)));else if(g=k+(1-r)*p,k-r*pb&&(w=b-q.x+w*r,v=-1),w=Math.min(I,w),ww||m.autoRotation&&(a.styles||{}).width)n=w;n&&(this.shortenLabel?this.shortenLabel():(F.width=Math.floor(n)+"px",(u.style||{}).textOverflow||(F.textOverflow="ellipsis"),a.css(F)))};z.prototype.moveLabel=function(q,m){var u=this,k=u.label,g=!1,b=u.axis,f=b.reversed,a=b.chart.inverted;k&&k.textStr===q?(u.movedLabel=k,g=!0,delete u.label):J(b.ticks, +function(a){g||a.isNew||a===u||!a.label||a.label.textStr!==q||(u.movedLabel=a.label,g=!0,a.labelPos=u.movedLabel.xy,delete a.label)});if(!g&&(u.labelPos||k)){var c=u.labelPos||k.xy;k=a?c.x:f?0:b.width+b.left;b=a?f?b.width+b.left:0:c.y;u.movedLabel=u.createLabel({x:k,y:b},q,m);u.movedLabel&&u.movedLabel.attr({opacity:0})}};z.prototype.render=function(q,m,u){var k=this.axis,g=k.horiz,b=this.pos,f=y(this.tickmarkOffset,k.tickmarkOffset);b=this.getPosition(g,b,f,m);f=b.x;var a=b.y;k=g&&f===k.pos+k.len|| +!g&&a===k.pos?-1:1;u=y(u,1);this.isActive=!0;this.renderGridLine(m,u,k);this.renderMark(b,u,k);this.renderLabel(b,m,u,q);this.isNew=!1;K(this,"afterRender")};z.prototype.renderGridLine=function(q,m,u){var k=this.axis,g=k.options,b=this.gridLine,f={},a=this.pos,c=this.type,r=y(this.tickmarkOffset,k.tickmarkOffset),p=k.chart.renderer,I=c?c+"Grid":"grid",w=g[I+"LineWidth"],v=g[I+"LineColor"];g=g[I+"LineDashStyle"];b||(k.chart.styledMode||(f.stroke=v,f["stroke-width"]=w,g&&(f.dashstyle=g)),c||(f.zIndex= +1),q&&(m=0),this.gridLine=b=p.path().attr(f).addClass("highcharts-"+(c?c+"-":"")+"grid-line").add(k.gridGroup));if(b&&(u=k.getPlotLinePath({value:a+r,lineWidth:b.strokeWidth()*u,force:"pass",old:q})))b[q||this.isNew?"attr":"animate"]({d:u,opacity:m})};z.prototype.renderMark=function(q,m,u){var k=this.axis,g=k.options,b=k.chart.renderer,f=this.type,a=f?f+"Tick":"tick",c=k.tickSize(a),r=this.mark,p=!r,I=q.x;q=q.y;var w=y(g[a+"Width"],!f&&k.isXAxis?1:0);g=g[a+"Color"];c&&(k.opposite&&(c[0]=-c[0]),p&& +(this.mark=r=b.path().addClass("highcharts-"+(f?f+"-":"")+"tick").add(k.axisGroup),k.chart.styledMode||r.attr({stroke:g,"stroke-width":w})),r[p?"attr":"animate"]({d:this.getMarkPath(I,q,c[0],r.strokeWidth()*u,k.horiz,b),opacity:m}))};z.prototype.renderLabel=function(q,m,u,k){var g=this.axis,b=g.horiz,f=g.options,a=this.label,c=f.labels,r=c.step;g=y(this.tickmarkOffset,g.tickmarkOffset);var p=!0,I=q.x;q=q.y;a&&E(I)&&(a.xy=q=this.getLabelPosition(I,q,a,b,c,g,k,r),this.isFirst&&!this.isLast&&!y(f.showFirstLabel, +1)||this.isLast&&!this.isFirst&&!y(f.showLastLabel,1)?p=!1:!b||c.step||c.rotation||m||0===u||this.handleOverflow(q),r&&k%r&&(p=!1),p&&E(q.y)?(q.opacity=u,a[this.isNewLabel?"attr":"animate"](q),this.isNewLabel=!1):(a.attr("y",-9999),this.isNewLabel=!0))};z.prototype.replaceMovedLabel=function(){var q=this.label,m=this.axis,u=m.reversed,k=this.axis.chart.inverted;if(q&&!this.isNew){var g=k?q.xy.x:u?m.left:m.width+m.left;u=k?u?m.width+m.top:m.top:q.xy.y;q.animate({x:g,y:u,opacity:0},void 0,q.destroy); +delete this.label}m.isDirty=!0;this.label=this.movedLabel;delete this.movedLabel};return z}();l.Tick=e;return l.Tick});P(x,"parts/Time.js",[x["parts/Globals.js"],x["parts/Utilities.js"]],function(l,e){var B=e.defined,t=e.error,N=e.extend,H=e.isObject,L=e.merge,K=e.objectEach,E=e.pad,C=e.pick,J=e.splat,y=e.timeUnits,A=l.win;e=function(){function z(q){this.options={};this.variableTimezone=this.useUTC=!1;this.Date=A.Date;this.getTimezoneOffset=this.timezoneOffsetFunction();this.update(q)}z.prototype.get= +function(q,m){if(this.variableTimezone||this.timezoneOffset){var u=m.getTime(),k=u-this.getTimezoneOffset(m);m.setTime(k);q=m["getUTC"+q]();m.setTime(u);return q}return this.useUTC?m["getUTC"+q]():m["get"+q]()};z.prototype.set=function(q,m,u){if(this.variableTimezone||this.timezoneOffset){if("Milliseconds"===q||"Seconds"===q||"Minutes"===q)return m["setUTC"+q](u);var k=this.getTimezoneOffset(m);k=m.getTime()-k;m.setTime(k);m["setUTC"+q](u);q=this.getTimezoneOffset(m);k=m.getTime()+q;return m.setTime(k)}return this.useUTC? +m["setUTC"+q](u):m["set"+q](u)};z.prototype.update=function(q){var m=C(q&&q.useUTC,!0);this.options=q=L(!0,this.options||{},q);this.Date=q.Date||A.Date||Date;this.timezoneOffset=(this.useUTC=m)&&q.timezoneOffset;this.getTimezoneOffset=this.timezoneOffsetFunction();this.variableTimezone=!(m&&!q.getTimezoneOffset&&!q.timezone)};z.prototype.makeTime=function(q,m,u,k,g,b){if(this.useUTC){var f=this.Date.UTC.apply(0,arguments);var a=this.getTimezoneOffset(f);f+=a;var c=this.getTimezoneOffset(f);a!==c? +f+=c-a:a-36E5!==this.getTimezoneOffset(f-36E5)||l.isSafari||(f-=36E5)}else f=(new this.Date(q,m,C(u,1),C(k,0),C(g,0),C(b,0))).getTime();return f};z.prototype.timezoneOffsetFunction=function(){var q=this,m=this.options,u=A.moment;if(!this.useUTC)return function(k){return 6E4*(new Date(k.toString())).getTimezoneOffset()};if(m.timezone){if(u)return function(k){return 6E4*-u.tz(k,m.timezone).utcOffset()};t(25)}return this.useUTC&&m.getTimezoneOffset?function(k){return 6E4*m.getTimezoneOffset(k.valueOf())}: +function(){return 6E4*(q.timezoneOffset||0)}};z.prototype.dateFormat=function(q,m,u){var k;if(!B(m)||isNaN(m))return(null===(k=l.defaultOptions.lang)||void 0===k?void 0:k.invalidDate)||"";q=C(q,"%Y-%m-%d %H:%M:%S");var g=this;k=new this.Date(m);var b=this.get("Hours",k),f=this.get("Day",k),a=this.get("Date",k),c=this.get("Month",k),r=this.get("FullYear",k),p=l.defaultOptions.lang,I=null===p||void 0===p?void 0:p.weekdays,w=null===p||void 0===p?void 0:p.shortWeekdays;k=N({a:w?w[f]:I[f].substr(0,3), +A:I[f],d:E(a),e:E(a,2," "),w:f,b:p.shortMonths[c],B:p.months[c],m:E(c+1),o:c+1,y:r.toString().substr(2,2),Y:r,H:E(b),k:b,I:E(b%12||12),l:b%12||12,M:E(this.get("Minutes",k)),p:12>b?"AM":"PM",P:12>b?"am":"pm",S:E(k.getSeconds()),L:E(Math.floor(m%1E3),3)},l.dateFormats);K(k,function(a,c){for(;-1!==q.indexOf("%"+c);)q=q.replace("%"+c,"function"===typeof a?a.call(g,m):a)});return u?q.substr(0,1).toUpperCase()+q.substr(1):q};z.prototype.resolveDTLFormat=function(q){return H(q,!0)?q:(q=J(q),{main:q[0],from:q[1], +to:q[2]})};z.prototype.getTimeTicks=function(q,m,u,k){var g=this,b=[],f={};var a=new g.Date(m);var c=q.unitRange,r=q.count||1,p;k=C(k,1);if(B(m)){g.set("Milliseconds",a,c>=y.second?0:r*Math.floor(g.get("Milliseconds",a)/r));c>=y.second&&g.set("Seconds",a,c>=y.minute?0:r*Math.floor(g.get("Seconds",a)/r));c>=y.minute&&g.set("Minutes",a,c>=y.hour?0:r*Math.floor(g.get("Minutes",a)/r));c>=y.hour&&g.set("Hours",a,c>=y.day?0:r*Math.floor(g.get("Hours",a)/r));c>=y.day&&g.set("Date",a,c>=y.month?1:Math.max(1, +r*Math.floor(g.get("Date",a)/r)));if(c>=y.month){g.set("Month",a,c>=y.year?0:r*Math.floor(g.get("Month",a)/r));var I=g.get("FullYear",a)}c>=y.year&&g.set("FullYear",a,I-I%r);c===y.week&&(I=g.get("Day",a),g.set("Date",a,g.get("Date",a)-I+k+(I4*y.month||g.getTimezoneOffset(m)!==g.getTimezoneOffset(u));m=a.getTime();for(a=1;mb.length&&b.forEach(function(a){0===a%18E5&&"000000000"===g.dateFormat("%H%M%S%L",a)&&(f[a]="day")})}b.info=N(q,{higherRanks:f,totalRange:c*r});return b};z.defaultOptions={Date:void 0,getTimezoneOffset:void 0,timezone:void 0,timezoneOffset:0,useUTC:!0};return z}();l.Time=e;return l.Time});P(x,"parts/Options.js",[x["parts/Globals.js"], +x["parts/Time.js"],x["parts/Color.js"],x["parts/Utilities.js"]],function(l,e,B,t){B=B.parse;var N=t.merge;l.defaultOptions={colors:"#7cb5ec #434348 #90ed7d #f7a35c #8085e9 #f15c80 #e4d354 #2b908f #f45b5b #91e8e1".split(" "),symbols:["circle","diamond","square","triangle","triangle-down"],lang:{loading:"Loading...",months:"January February March April May June July August September October November December".split(" "),shortMonths:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),weekdays:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "), +decimalPoint:".",numericSymbols:"kMGTPE".split(""),resetZoom:"Reset zoom",resetZoomTitle:"Reset zoom level 1:1",thousandsSep:" "},global:{},time:e.defaultOptions,chart:{styledMode:!1,borderRadius:0,colorCount:10,defaultSeriesType:"line",ignoreHiddenSeries:!0,spacing:[10,10,15,10],resetZoomButton:{theme:{zIndex:6},position:{align:"right",x:-10,y:10}},width:null,height:null,borderColor:"#335cad",backgroundColor:"#ffffff",plotBorderColor:"#cccccc"},title:{text:"Chart title",align:"center",margin:15, +widthAdjust:-44},subtitle:{text:"",align:"center",widthAdjust:-44},caption:{margin:15,text:"",align:"left",verticalAlign:"bottom"},plotOptions:{},labels:{style:{position:"absolute",color:"#333333"}},legend:{enabled:!0,align:"center",alignColumns:!0,layout:"horizontal",labelFormatter:function(){return this.name},borderColor:"#999999",borderRadius:0,navigation:{activeColor:"#003399",inactiveColor:"#cccccc"},itemStyle:{color:"#333333",cursor:"pointer",fontSize:"12px",fontWeight:"bold",textOverflow:"ellipsis"}, +itemHoverStyle:{color:"#000000"},itemHiddenStyle:{color:"#cccccc"},shadow:!1,itemCheckboxStyle:{position:"absolute",width:"13px",height:"13px"},squareSymbol:!0,symbolPadding:5,verticalAlign:"bottom",x:0,y:0,title:{style:{fontWeight:"bold"}}},loading:{labelStyle:{fontWeight:"bold",position:"relative",top:"45%"},style:{position:"absolute",backgroundColor:"#ffffff",opacity:.5,textAlign:"center"}},tooltip:{enabled:!0,animation:l.svg,borderRadius:3,dateTimeLabelFormats:{millisecond:"%A, %b %e, %H:%M:%S.%L", +second:"%A, %b %e, %H:%M:%S",minute:"%A, %b %e, %H:%M",hour:"%A, %b %e, %H:%M",day:"%A, %b %e, %Y",week:"Week from %A, %b %e, %Y",month:"%B %Y",year:"%Y"},footerFormat:"",padding:8,snap:l.isTouchDevice?25:10,headerFormat:'{point.key}
',pointFormat:'\u25cf {series.name}: {point.y}
',backgroundColor:B("#f7f7f7").setOpacity(.85).get(),borderWidth:1,shadow:!0,style:{color:"#333333",cursor:"default",fontSize:"12px", +whiteSpace:"nowrap"}},credits:{enabled:!0,href:"https://www.highcharts.com?credits",position:{align:"right",x:-10,verticalAlign:"bottom",y:-5},style:{cursor:"pointer",color:"#999999",fontSize:"9px"},text:"Highcharts.com"}};l.setOptions=function(e){l.defaultOptions=N(!0,l.defaultOptions,e);(e.time||e.global)&&l.time.update(N(l.defaultOptions.global,l.defaultOptions.time,e.global,e.time));return l.defaultOptions};l.getOptions=function(){return l.defaultOptions};l.defaultPlotOptions=l.defaultOptions.plotOptions; +l.time=new e(N(l.defaultOptions.global,l.defaultOptions.time));l.dateFormat=function(e,t,K){return l.time.dateFormat(e,t,K)};""});P(x,"parts/Axis.js",[x["parts/Color.js"],x["parts/Globals.js"],x["parts/Tick.js"],x["parts/Utilities.js"]],function(l,e,B,t){var N=t.addEvent,H=t.animObject,L=t.arrayMax,K=t.arrayMin,E=t.clamp,C=t.correctFloat,J=t.defined,y=t.destroyObjectProperties,A=t.error,z=t.extend,q=t.fireEvent,m=t.format,u=t.getMagnitude,k=t.isArray,g=t.isFunction,b=t.isNumber,f=t.isString,a=t.merge, +c=t.normalizeTickInterval,r=t.objectEach,p=t.pick,I=t.relativeLength,w=t.removeEvent,v=t.splat,n=t.syncTimeout,F=e.defaultOptions,O=e.deg2rad;t=function(){function D(h,d){this.zoomEnabled=this.width=this.visible=this.userOptions=this.translationSlope=this.transB=this.transA=this.top=this.ticks=this.tickRotCorr=this.tickPositions=this.tickmarkOffset=this.tickInterval=this.tickAmount=this.side=this.series=this.right=this.positiveValuesOnly=this.pos=this.pointRangePadding=this.pointRange=this.plotLinesAndBandsGroups= +this.plotLinesAndBands=this.paddedTicks=this.overlap=this.options=this.oldMin=this.oldMax=this.offset=this.names=this.minPixelPadding=this.minorTicks=this.minorTickInterval=this.min=this.maxLabelLength=this.max=this.len=this.left=this.labelFormatter=this.labelEdge=this.isLinked=this.height=this.hasVisibleSeries=this.hasNames=this.coll=this.closestPointRange=this.chart=this.categories=this.bottom=this.alternateBands=void 0;this.init(h,d)}D.prototype.init=function(h,d){var a=d.isX,c=this;c.chart=h; +c.horiz=h.inverted&&!c.isZAxis?!a:a;c.isXAxis=a;c.coll=c.coll||(a?"xAxis":"yAxis");q(this,"init",{userOptions:d});c.opposite=d.opposite;c.side=d.side||(c.horiz?c.opposite?0:2:c.opposite?1:3);c.setOptions(d);var b=this.options,f=b.type;c.labelFormatter=b.labels.formatter||c.defaultLabelFormatter;c.userOptions=d;c.minPixelPadding=0;c.reversed=b.reversed;c.visible=!1!==b.visible;c.zoomEnabled=!1!==b.zoomEnabled;c.hasNames="category"===f||!0===b.categories;c.categories=b.categories||c.hasNames;c.names|| +(c.names=[],c.names.keys={});c.plotLinesAndBandsGroups={};c.positiveValuesOnly=!(!c.logarithmic||b.allowNegativeLog);c.isLinked=J(b.linkedTo);c.ticks={};c.labelEdge=[];c.minorTicks={};c.plotLinesAndBands=[];c.alternateBands={};c.len=0;c.minRange=c.userMinRange=b.minRange||b.maxZoom;c.range=b.range;c.offset=b.offset||0;c.max=null;c.min=null;c.crosshair=p(b.crosshair,v(h.options.tooltip.crosshairs)[a?0:1],!1);d=c.options.events;-1===h.axes.indexOf(c)&&(a?h.axes.splice(h.xAxis.length,0,c):h.axes.push(c), +h[c.coll].push(c));c.series=c.series||[];h.inverted&&!c.isZAxis&&a&&"undefined"===typeof c.reversed&&(c.reversed=!0);c.labelRotation=c.options.labels.rotation;r(d,function(d,h){g(d)&&N(c,h,d)});q(this,"afterInit")};D.prototype.setOptions=function(h){this.options=a(D.defaultOptions,"yAxis"===this.coll&&D.defaultYAxisOptions,[D.defaultTopAxisOptions,D.defaultRightAxisOptions,D.defaultBottomAxisOptions,D.defaultLeftAxisOptions][this.side],a(F[this.coll],h));q(this,"afterSetOptions",{userOptions:h})}; +D.prototype.defaultLabelFormatter=function(){var h=this.axis,d=this.value,a=h.chart.time,c=h.categories,b=this.dateTimeLabelFormat,f=F.lang,g=f.numericSymbols;f=f.numericSymbolMagnitude||1E3;var p=g&&g.length,r=h.options.labels.format;h=h.logarithmic?Math.abs(d):h.tickInterval;var k=this.chart,n=k.numberFormatter;if(r)var w=m(r,this,k);else if(c)w=d;else if(b)w=a.dateFormat(b,d);else if(p&&1E3<=h)for(;p--&&"undefined"===typeof w;)a=Math.pow(f,p+1),h>=a&&0===10*d%a&&null!==g[p]&&0!==d&&(w=n(d/a,-1)+ +g[p]);"undefined"===typeof w&&(w=1E4<=Math.abs(d)?n(d,-1):n(d,-1,void 0,""));return w};D.prototype.getSeriesExtremes=function(){var h=this,d=h.chart,a;q(this,"getSeriesExtremes",null,function(){h.hasVisibleSeries=!1;h.dataMin=h.dataMax=h.threshold=null;h.softThreshold=!h.isXAxis;h.stacking&&h.stacking.buildStacks();h.series.forEach(function(c){if(c.visible||!d.options.chart.ignoreHiddenSeries){var f=c.options,g=f.threshold;h.hasVisibleSeries=!0;h.positiveValuesOnly&&0>=g&&(g=null);if(h.isXAxis){if(f= +c.xData,f.length){a=c.getXExtremes(f);var r=a.min;var G=a.max;b(r)||r instanceof Date||(f=f.filter(b),a=c.getXExtremes(f),r=a.min,G=a.max);f.length&&(h.dataMin=Math.min(p(h.dataMin,r),r),h.dataMax=Math.max(p(h.dataMax,G),G))}}else if(c=c.applyExtremes(),b(c.dataMin)&&(r=c.dataMin,h.dataMin=Math.min(p(h.dataMin,r),r)),b(c.dataMax)&&(G=c.dataMax,h.dataMax=Math.max(p(h.dataMax,G),G)),J(g)&&(h.threshold=g),!f.softThreshold||h.positiveValuesOnly)h.softThreshold=!1}})});q(this,"afterGetSeriesExtremes")}; +D.prototype.translate=function(h,d,a,c,f,g){var p=this.linkedParent||this,r=1,G=0,k=c?p.oldTransA:p.transA;c=c?p.oldMin:p.min;var n=p.minPixelPadding;f=(p.isOrdinal||p.brokenAxis&&p.brokenAxis.hasBreaks||p.logarithmic&&f)&&p.lin2val;k||(k=p.transA);a&&(r*=-1,G=p.len);p.reversed&&(r*=-1,G-=r*(p.sector||p.len));d?(h=(h*r+G-n)/k+c,f&&(h=p.lin2val(h))):(f&&(h=p.val2lin(h)),h=b(c)?r*(h-c)*k+G+r*n+(b(g)?k*g:0):void 0);return h};D.prototype.toPixels=function(h,d){return this.translate(h,!1,!this.horiz,null, +!0)+(d?0:this.pos)};D.prototype.toValue=function(h,d){return this.translate(h-(d?0:this.pos),!0,!this.horiz,null,!0)};D.prototype.getPlotLinePath=function(h){function d(d,h,a){if("pass"!==v&&da)v?d=E(d,h,a):z=!0;return d}var a=this,c=a.chart,f=a.left,g=a.top,r=h.old,k=h.value,n=h.translatedValue,w=h.lineWidth,v=h.force,F,I,m,D,O=r&&c.oldChartHeight||c.chartHeight,u=r&&c.oldChartWidth||c.chartWidth,z,e=a.transB;h={value:k,lineWidth:w,old:r,force:v,acrossPanes:h.acrossPanes,translatedValue:n}; +q(this,"getPlotLinePath",h,function(h){n=p(n,a.translate(k,null,null,r));n=E(n,-1E5,1E5);F=m=Math.round(n+e);I=D=Math.round(O-n-e);b(n)?a.horiz?(I=g,D=O-a.bottom,F=m=d(F,f,f+a.width)):(F=f,m=u-a.right,I=D=d(I,g,g+a.height)):(z=!0,v=!1);h.path=z&&!v?null:c.renderer.crispLine([["M",F,I],["L",m,D]],w||1)});return h.path};D.prototype.getLinearTickPositions=function(h,d,a){var c=C(Math.floor(d/h)*h);a=C(Math.ceil(a/h)*h);var b=[],f;C(c+h)===c&&(f=20);if(this.single)return[d];for(d=c;d<=a;){b.push(d);d= +C(d+h,f);if(d===g)break;var g=d}return b};D.prototype.getMinorTickInterval=function(){var h=this.options;return!0===h.minorTicks?p(h.minorTickInterval,"auto"):!1===h.minorTicks?null:h.minorTickInterval};D.prototype.getMinorTickPositions=function(){var h=this.options,d=this.tickPositions,a=this.minorTickInterval,c=[],b=this.pointRangePadding||0,f=this.min-b;b=this.max+b;var g=b-f;if(g&&g/a=this.minRange;var w=this.minRange;var v=(w-a+d)/2;v=[d-v,p(h.min,d-v)];n&&(v[2]=this.logarithmic?this.logarithmic.log2lin(this.dataMin):this.dataMin);d=L(v);a=[d+w,p(h.max,d+w)];n&&(a[2]=c?c.log2lin(this.dataMax):this.dataMax);a=K(a);a-d=m)e=m,w=0;else if(d.dataMax<=m){var l=m;n=0}d.min= +p(O,e,d.dataMin);d.max=p(z,l,d.dataMax)}f&&(d.positiveValuesOnly&&!a&&0>=Math.min(d.min,p(d.dataMin,d.min))&&A(10,1,h),d.min=C(f.log2lin(d.min),16),d.max=C(f.log2lin(d.max),16));d.range&&J(d.max)&&(d.userMin=d.min=O=Math.max(d.dataMin,d.minFromRange()),d.userMax=z=d.max,d.range=null);q(d,"foundExtremes");d.beforePadding&&d.beforePadding();d.adjustForMinRange();!(I||d.axisPointRange||d.stacking&&d.stacking.usePercentage||k)&&J(d.min)&&J(d.max)&&(h=d.max-d.min)&&(!J(O)&&w&&(d.min-=h*w),!J(z)&&n&&(d.max+= +h*n));b(d.userMin)||(b(g.softMin)&&g.softMind.max&&(d.max=z=g.softMax),b(g.ceiling)&&(d.max=Math.min(d.max,g.ceiling)));D&&J(d.dataMin)&&(m=m||0,!J(O)&&d.min=m?d.min=d.options.minRange?Math.min(m,d.max-d.minRange):m:!J(z)&&d.max>m&&d.dataMax<=m&&(d.max=d.options.minRange?Math.max(m,d.min+d.minRange):m));d.tickInterval=d.min===d.max||"undefined"===typeof d.min||"undefined"=== +typeof d.max?1:k&&!v&&F===d.linkedParent.options.tickPixelInterval?v=d.linkedParent.tickInterval:p(v,this.tickAmount?(d.max-d.min)/Math.max(this.tickAmount-1,1):void 0,I?1:(d.max-d.min)*F/Math.max(d.len,F));r&&!a&&d.series.forEach(function(a){a.processData(d.min!==d.oldMin||d.max!==d.oldMax)});d.setAxisTranslation(!0);d.beforeSetTickPositions&&d.beforeSetTickPositions();d.ordinal&&(d.tickInterval=d.ordinal.postProcessTickInterval(d.tickInterval));d.pointRange&&!v&&(d.tickInterval=Math.max(d.pointRange, +d.tickInterval));a=p(g.minTickInterval,d.dateTime&&d.closestPointRange);!v&&d.tickIntervald.tickInterval||void 0!==this.tickAmount),!!this.tickAmount));this.tickAmount||(d.tickInterval=d.unsquish());this.setTickPositions()};D.prototype.setTickPositions=function(){var a=this.options,d=a.tickPositions;var c=this.getMinorTickInterval();var b=a.tickPositioner,f=this.hasVerticalPanning(), +g="colorAxis"===this.coll,p=(g||!f)&&a.startOnTick;f=(g||!f)&&a.endOnTick;this.tickmarkOffset=this.categories&&"between"===a.tickmarkPlacement&&1===this.tickInterval?.5:0;this.minorTickInterval="auto"===c&&this.tickInterval?this.tickInterval/5:c;this.single=this.min===this.max&&J(this.min)&&!this.tickAmount&&(parseInt(this.min,10)===this.min||!1!==a.allowDecimals);this.tickPositions=c=d&&d.slice();!c&&(this.ordinal&&this.ordinal.positions||!((this.max-this.min)/this.tickInterval>Math.max(2*this.len, +200))?c=this.dateTime?this.getTimeTicks(this.dateTime.normalizeTimeTickInterval(this.tickInterval,a.units),this.min,this.max,a.startOfWeek,this.ordinal&&this.ordinal.positions,this.closestPointRange,!0):this.logarithmic?this.logarithmic.getLogTickPositions(this.tickInterval,this.min,this.max):this.getLinearTickPositions(this.tickInterval,this.min,this.max):(c=[this.min,this.max],A(19,!1,this.chart)),c.length>this.len&&(c=[c[0],c.pop()],c[0]===c[1]&&(c.length=1)),this.tickPositions=c,b&&(b=b.apply(this, +[this.min,this.max])))&&(this.tickPositions=c=b);this.paddedTicks=c.slice(0);this.trimTicks(c,p,f);this.isLinked||(this.single&&2>c.length&&!this.categories&&!this.series.some(function(d){return d.is("heatmap")&&"between"===d.options.pointPlacement})&&(this.min-=.5,this.max+=.5),d||b||this.adjustTickAmount());q(this,"afterSetTickPositions")};D.prototype.trimTicks=function(a,d,c){var h=a[0],b=a[a.length-1],f=!this.isOrdinal&&this.minPointOffset||0;q(this,"trimTicks");if(!this.isLinked){if(d&&-Infinity!== +h)this.min=h;else for(;this.min-f>a[0];)a.shift();if(c)this.max=b;else for(;this.max+fd&&(this.finalTickAmt=d,d=5);this.tickAmount=d};D.prototype.adjustTickAmount=function(){var a=this.options,d=this.tickInterval,c=this.tickPositions,b=this.tickAmount,f=this.finalTickAmt,g=c&&c.length,r=p(this.threshold,this.softThreshold? +0:null),k;if(this.hasData()){if(gb&&(this.tickInterval*=2,this.setTickPositions());if(J(f)){for(d=a=c.length;d--;)(3===f&&1===d%2||2>=f&&0r&&(a=r)),J(b)&&(fr&&(f=r))),h.displayBtn="undefined"!==typeof a||"undefined"!==typeof f,h.setExtremes(a,f,!1,void 0,{trigger:"zoom"});d.zoomed=!0});return a.zoomed};D.prototype.setAxisSize=function(){var a=this.chart,d=this.options,c=d.offsets||[0,0,0,0],b=this.horiz,f=this.width=Math.round(I(p(d.width, +a.plotWidth-c[3]+c[1]),a.plotWidth)),g=this.height=Math.round(I(p(d.height,a.plotHeight-c[0]+c[2]),a.plotHeight)),r=this.top=Math.round(I(p(d.top,a.plotTop+c[0]),a.plotHeight,a.plotTop));d=this.left=Math.round(I(p(d.left,a.plotLeft+c[3]),a.plotWidth,a.plotLeft));this.bottom=a.chartHeight-g-r;this.right=a.chartWidth-f-d;this.len=Math.max(b?f:g,0);this.pos=b?d:r};D.prototype.getExtremes=function(){var a=this.logarithmic;return{min:a?C(a.lin2log(this.min)):this.min,max:a?C(a.lin2log(this.max)):this.max, +dataMin:this.dataMin,dataMax:this.dataMax,userMin:this.userMin,userMax:this.userMax}};D.prototype.getThreshold=function(a){var d=this.logarithmic,h=d?d.lin2log(this.min):this.min;d=d?d.lin2log(this.max):this.max;null===a||-Infinity===a?a=h:Infinity===a?a=d:h>a?a=h:dd?a.align="right":195d&&(a.align="left")}); +return a.align};D.prototype.tickSize=function(a){var d=this.options,h=d["tick"===a?"tickLength":"minorTickLength"],c=p(d["tick"===a?"tickWidth":"minorTickWidth"],"tick"===a&&this.isXAxis&&!this.categories?1:0);if(c&&h){"inside"===d[a+"Position"]&&(h=-h);var b=[h,c]}a={tickSize:b};q(this,"afterTickSize",a);return a.tickSize};D.prototype.labelMetrics=function(){var a=this.tickPositions&&this.tickPositions[0]||0;return this.chart.renderer.fontMetrics(this.options.labels.style&&this.options.labels.style.fontSize, +this.ticks[a]&&this.ticks[a].label)};D.prototype.unsquish=function(){var a=this.options.labels,d=this.horiz,c=this.tickInterval,b=c,f=this.len/(((this.categories?1:0)+this.max-this.min)/c),g,r=a.rotation,k=this.labelMetrics(),n,w=Number.MAX_VALUE,v,F=this.max-this.min,I=function(d){var a=d/(f||1);a=1F&&Infinity!==d&&Infinity!==f&&F&&(a=Math.ceil(F/c));return C(a*c)};d?(v=!a.staggerLines&&!a.step&&(J(r)?[r]:f=d){n=I(Math.abs(k.h/Math.sin(O*d)));var a=n+Math.abs(d/360);a(f.step||0))return f.rotation?0:(this.staggerLines||1)*this.len/g;if(!c){a=null===(d=null===f||void 0===f?void 0: +f.style)||void 0===d?void 0:d.width;if(void 0!==a)return parseInt(a,10);if(p)return p-h.spacing[3]}return.33*h.chartWidth};D.prototype.renderUnsquish=function(){var a=this.chart,d=a.renderer,c=this.tickPositions,b=this.ticks,g=this.options.labels,p=g&&g.style||{},r=this.horiz,k=this.getSlotWidth(),n=Math.max(1,Math.round(k-2*(g.padding||5))),w={},v=this.labelMetrics(),F=g.style&&g.style.textOverflow,I=0;f(g.rotation)||(w.rotation=g.rotation||0);c.forEach(function(d){d=b[d];d.movedLabel&&d.replaceMovedLabel(); +d&&d.label&&d.label.textPxLength>I&&(I=d.label.textPxLength)});this.maxLabelLength=I;if(this.autoRotation)I>n&&I>v.h?w.rotation=this.labelRotation:this.labelRotation=0;else if(k){var m=n;if(!F){var D="clip";for(n=c.length;!r&&n--;){var O=c[n];if(O=b[O].label)O.styles&&"ellipsis"===O.styles.textOverflow?O.css({textOverflow:"clip"}):O.textPxLength>k&&O.css({width:k+"px"}),O.getBBox().height>this.len/c.length-(v.h-v.f)&&(O.specificTextOverflow="ellipsis")}}}w.rotation&&(m=I>.5*a.chartHeight?.33*a.chartHeight: +I,F||(D="ellipsis"));if(this.labelAlign=g.align||this.autoLabelAlign(this.labelRotation))w.align=this.labelAlign;c.forEach(function(d){var a=(d=b[d])&&d.label,h=p.width,c={};a&&(a.attr(w),d.shortenLabel?d.shortenLabel():m&&!h&&"nowrap"!==p.whiteSpace&&(m=this.min&&a<=this.max)h[a]||(h[a]=new B(this,a)),f&&h[a].isNew&&h[a].render(d,!0,-1),h[a].render(d)};D.prototype.render=function(){var a=this,d=a.chart,c=a.logarithmic,f=a.options,g=a.isLinked,p=a.tickPositions,k=a.axisTitle,w=a.ticks,v=a.minorTicks,F=a.alternateBands,I=f.stackLabels,m=f.alternateGridColor, +O=a.tickmarkOffset,D=a.axisLine,u=a.showAxis,z=H(d.renderer.globalAnimation),l,y;a.labelEdge.length=0;a.overlap=!1;[w,v,F].forEach(function(d){r(d,function(d){d.isActive=!1})});if(a.hasData()||g)a.minorTickInterval&&!a.categories&&a.getMinorTickPositions().forEach(function(d){a.renderMinorTick(d)}),p.length&&(p.forEach(function(d,c){a.renderTick(d,c)}),O&&(0===a.min||a.single)&&(w[-1]||(w[-1]=new B(a,-1,null,!0)),w[-1].render(-1))),m&&p.forEach(function(h,b){y="undefined"!==typeof p[b+1]?p[b+1]+O: +a.max-O;0===b%2&&hl&&(!y||f<=J)&&"undefined"!==typeof f&&m.push(f);f>J&&(k=!0);var f=b}}}else l=this.lin2log(l),J=this.lin2log(J),e=y?A.getMinorTickInterval():q.tickInterval,e=H("auto"===e?null:e,this.minorAutoInterval,q.tickPixelInterval/(y?5:1)*(J-l)/((y?z/A.tickPositions.length:z)||1)),e=N(e,void 0,t(e)),m=A.getLinearTickPositions(e,l,J).map(this.log2lin), +y||(this.minorAutoInterval=e/5);y||(A.tickInterval=e);return m};e.prototype.lin2log=function(e){return Math.pow(10,e)};e.prototype.log2lin=function(e){return Math.log(e)/Math.LN10};return e}();e=function(){function e(){}e.compose=function(e){e.keepProps.push("logarithmic");var l=e.prototype,E=L.prototype;l.log2lin=E.log2lin;l.lin2log=E.lin2log;B(e,"init",function(e){var l=this.logarithmic;"logarithmic"!==e.userOptions.type?this.logarithmic=void 0:(l||(l=this.logarithmic=new L(this)),this.log2lin!== +l.log2lin&&(l.log2lin=this.log2lin.bind(this)),this.lin2log!==l.lin2log&&(l.lin2log=this.lin2log.bind(this)))});B(e,"afterInit",function(){var e=this.logarithmic;e&&(this.lin2val=function(l){return e.lin2log(l)},this.val2lin=function(l){return e.log2lin(l)})})};return e}();e.compose(l);return e});P(x,"parts/PlotLineOrBand.js",[x["parts/Globals.js"],x["parts/Axis.js"],x["parts/Utilities.js"]],function(l,e,B){var t=B.arrayMax,N=B.arrayMin,H=B.defined,L=B.destroyObjectProperties,K=B.erase,E=B.extend, +C=B.merge,J=B.objectEach,y=B.pick,A=function(){function e(q,m){this.axis=q;m&&(this.options=m,this.id=m.id)}e.prototype.render=function(){l.fireEvent(this,"render");var q=this,m=q.axis,e=m.horiz,k=m.logarithmic,g=q.options,b=g.label,f=q.label,a=g.to,c=g.from,r=g.value,p=H(c)&&H(a),I=H(r),w=q.svgElem,v=!w,n=[],F=g.color,O=y(g.zIndex,0),D=g.events;n={"class":"highcharts-plot-"+(p?"band ":"line ")+(g.className||"")};var h={},d=m.chart.renderer,G=p?"bands":"lines";k&&(c=k.log2lin(c),a=k.log2lin(a),r= +k.log2lin(r));m.chart.styledMode||(I?(n.stroke=F||"#999999",n["stroke-width"]=y(g.width,1),g.dashStyle&&(n.dashstyle=g.dashStyle)):p&&(n.fill=F||"#e6ebf5",g.borderWidth&&(n.stroke=g.borderColor,n["stroke-width"]=g.borderWidth)));h.zIndex=O;G+="-"+O;(k=m.plotLinesAndBandsGroups[G])||(m.plotLinesAndBandsGroups[G]=k=d.g("plot-"+G).attr(h).add());v&&(q.svgElem=w=d.path().attr(n).add(k));if(I)n=m.getPlotLinePath({value:r,lineWidth:w.strokeWidth(),acrossPanes:g.acrossPanes});else if(p)n=m.getPlotBandPath(c, +a,g);else return;(v||!w.d)&&n&&n.length?(w.attr({d:n}),D&&J(D,function(a,d){w.on(d,function(a){D[d].apply(q,[a])})})):w&&(n?(w.show(!0),w.animate({d:n})):w.d&&(w.hide(),f&&(q.label=f=f.destroy())));b&&(H(b.text)||H(b.formatter))&&n&&n.length&&0this.max&&q>this.max;if(u&&m){if(e){var f=u.toString()===m.toString();b=0}for(e=0;eb){v=w;break}if(k[v]&&p.substr(k[v])!=="01-01 00:00:00.000".substr(k[v]))break;"week"!==v&&(w=v)}if(v)var n=g.resolveDTLFormat(c[v]).main;return n};g.prototype.getLabel=function(){var b,f,a=this,c=this.chart.renderer,g=this.chart.styledMode,p=this.options,k="tooltip"+(N(p.className)?" "+p.className:""),w=(null===(b=p.style)||void 0===b?void 0:b.pointerEvents)||(!this.followPointer&& +p.stickOnContact?"auto":"none"),v;b=function(){a.inContact=!0};var n=function(){var c=a.chart.hoverSeries;a.inContact=!1;if(c&&c.onMouseOut)c.onMouseOut()};if(!this.label){this.outside&&(this.container=v=l.doc.createElement("div"),v.className="highcharts-tooltip-container",t(v,{position:"absolute",top:"1px",pointerEvents:w,zIndex:3}),l.doc.body.appendChild(v),this.renderer=c=new l.Renderer(v,0,0,null===(f=this.chart.options.chart)||void 0===f?void 0:f.style,void 0,void 0,c.styledMode));this.split? +this.label=c.g(k):(this.label=c.label("",0,0,p.shape||"callout",null,null,p.useHTML,null,k).attr({padding:p.padding,r:p.borderRadius}),g||this.label.attr({fill:p.backgroundColor,"stroke-width":p.borderWidth}).css(p.style).css({pointerEvents:w}).shadow(p.shadow));g&&(this.applyFilter(),this.label.addClass("highcharts-tooltip-"+this.chart.index));if(a.outside&&!a.split){var F={x:this.label.xSetter,y:this.label.ySetter};this.label.xSetter=function(c,b){F[b].call(this.label,a.distance);v.style.left=c+ +"px"};this.label.ySetter=function(c,b){F[b].call(this.label,a.distance);v.style.top=c+"px"}}this.label.on("mouseenter",b).on("mouseleave",n).attr({zIndex:8}).add()}return this.label};g.prototype.getPosition=function(b,f,a){var c=this.chart,g=this.distance,p={},k=c.inverted&&a.h||0,w,v=this.outside,n=v?u.documentElement.clientWidth-2*g:c.chartWidth,F=v?Math.max(u.body.scrollHeight,u.documentElement.scrollHeight,u.body.offsetHeight,u.documentElement.offsetHeight,u.documentElement.clientHeight):c.chartHeight, +m=c.pointer.getChartPosition(),e=c.containerScaling,h=function(a){return e?a*e.scaleX:a},d=function(a){return e?a*e.scaleY:a},G=function(p){var r="x"===p;return[p,r?n:F,r?b:f].concat(v?[r?h(b):d(f),r?m.left-g+h(a.plotX+c.plotLeft):m.top-g+d(a.plotY+c.plotTop),0,r?n:F]:[r?b:f,r?a.plotX+c.plotLeft:a.plotY+c.plotTop,r?c.plotLeft:c.plotTop,r?c.plotLeft+c.plotWidth:c.plotTop+c.plotHeight])},M=G("y"),q=G("x"),l=!this.followPointer&&A(a.ttBelow,!c.inverted===!!a.negative),z=function(a,c,b,f,r,n,w){var v= +"y"===a?d(g):h(g),F=(b-f)/2,G=fm-k?m:m-k);else if(M)p[a]=Math.max(n,r+k+b>c?r:r+k);else return!1},y=function(a,d,c,h,b){var f;bd-g?f=!1:p[a]=bd-h/2?d-h-2:b-c/2;return f},E=function(a){var d=M;M=q;q=d;w=a},C=function(){!1!==z.apply(0,M)?!1!==y.apply(0,q)||w||(E(!0),C()):w?p.x=p.y=0:(E(!0),C())};(c.inverted||1=d+v&&O.pos+D<=d+v+k-e&&(l=O.pos+D);I=B(I,z.left-M,z.right+M);"number"===typeof l?(m=m.height+1,D=u?u.call(c,r,m,g):a(I,l,p,r),h.push({align:u?0:void 0,anchorX:I,anchorY:l,boxWidth:r,point:g,rank:A(D.rank,p?1:0),size:m,target:D.y,tt:b,x:D.x})):b.isActive=!1}return h},[]);!u&&b.some(function(a){return a.xa[0]?Math.max(Math.abs(a[0]),g.width-a[0]):Math.max(Math.abs(a[0]),g.width);c.height=0>a[1]?Math.max(Math.abs(a[1]),g.height-Math.abs(a[1])):Math.max(Math.abs(a[1]),g.height);this.tracker?this.tracker.attr(c): +(this.tracker=f.renderer.rect(c).addClass("highcharts-tracker").add(f),b.styledMode||this.tracker.attr({fill:"rgba(0,0,0,0)"}))}}};g.prototype.styledModeFormat=function(b){return b.replace('style="font-size: 10px"','class="highcharts-header"').replace(/style="color:{(point|series)\.color}"/g,'class="highcharts-color-{$1.colorIndex}"')};g.prototype.tooltipFooterHeaderFormatter=function(b,f){var a=f?"footer":"header",c=b.series,g=c.tooltipOptions,p=g.xDateFormat,k=c.xAxis,w=k&&"datetime"===k.options.type&& +C(b.key),v=g[a+"Format"];f={isFooter:f,labelConfig:b};K(this,"headerFormatter",f,function(a){w&&!p&&(p=this.getXDateFormat(b,g,k));w&&p&&(b.point&&b.point.tooltipDateKeys||["key"]).forEach(function(a){v=v.replace("{point."+a+"}","{point."+a+":"+p+"}")});c.chart.styledMode&&(v=this.styledModeFormat(v));a.text=E(v,{point:b,series:c},this.chart)});return f.text};g.prototype.update=function(b){this.destroy();y(!0,this.chart.options.tooltip.userOptions,b);this.init(this.chart,y(!0,this.options,b))};g.prototype.updatePosition= +function(b){var f=this.chart,a=f.pointer,c=this.getLabel(),g=b.plotX+f.plotLeft,p=b.plotY+f.plotTop;a=a.getChartPosition();b=(this.options.positioner||this.getPosition).call(this,c.width,c.height,b);if(this.outside){var k=(this.options.borderWidth||0)+2*this.distance;this.renderer.setSize(c.width+k,c.height+k,!1);if(f=f.containerScaling)t(this.container,{transform:"scale("+f.scaleX+", "+f.scaleY+")"}),g*=f.scaleX,p*=f.scaleY;g+=a.left-b.x;p+=a.top-b.y}this.move(Math.round(b.x),Math.round(b.y||0), +g,p)};return g}();l.Tooltip=k;return l.Tooltip});P(x,"parts/Pointer.js",[x["parts/Globals.js"],x["parts/Utilities.js"],x["parts/Tooltip.js"],x["parts/Color.js"]],function(l,e,B,t){var N=e.addEvent,H=e.attr,L=e.css,K=e.defined,E=e.extend,C=e.find,J=e.fireEvent,y=e.isNumber,A=e.isObject,z=e.objectEach,q=e.offset,m=e.pick,u=e.splat,k=t.parse,g=l.charts,b=l.noop;e=function(){function f(a,c){this.lastValidTouch={};this.pinchDown=[];this.runChartClick=!1;this.chart=a;this.hasDragged=!1;this.options=c;this.unbindContainerMouseLeave= +function(){};this.init(a,c)}f.prototype.applyInactiveState=function(a){var c=[],b;(a||[]).forEach(function(a){b=a.series;c.push(b);b.linkedParent&&c.push(b.linkedParent);b.linkedSeries&&(c=c.concat(b.linkedSeries));b.navigatorSeries&&c.push(b.navigatorSeries)});this.chart.series.forEach(function(a){-1===c.indexOf(a)?a.setState("inactive",!0):a.options.inactiveOtherPoints&&a.setAllPointsToState("inactive")})};f.prototype.destroy=function(){var a=this;"undefined"!==typeof a.unDocMouseMove&&a.unDocMouseMove(); +this.unbindContainerMouseLeave();l.chartCount||(l.unbindDocumentMouseUp&&(l.unbindDocumentMouseUp=l.unbindDocumentMouseUp()),l.unbindDocumentTouchEnd&&(l.unbindDocumentTouchEnd=l.unbindDocumentTouchEnd()));clearInterval(a.tooltipTimeout);z(a,function(c,b){a[b]=null})};f.prototype.drag=function(a){var c=this.chart,b=c.options.chart,f=a.chartX,g=a.chartY,w=this.zoomHor,v=this.zoomVert,n=c.plotLeft,F=c.plotTop,m=c.plotWidth,e=c.plotHeight,h=this.selectionMarker,d=this.mouseDownX||0,G=this.mouseDownY|| +0,M=A(b.panning)?b.panning&&b.panning.enabled:b.panning,q=b.panKey&&a[b.panKey+"Key"];if(!h||!h.touch)if(fn+m&&(f=n+m),gF+e&&(g=F+e),this.hasDragged=Math.sqrt(Math.pow(d-f,2)+Math.pow(G-g,2)),10a.options.findNearestPointBy.indexOf("y");a=a.searchPoint(b,f);if((f=A(a,!0))&&!(f=!A(k,!0))){f=k.distX-a.distX;var g=k.dist-a.dist,p=(a.series.group&& +a.series.group.zIndex)-(k.series.group&&k.series.group.zIndex);f=0<(0!==f&&c?f:0!==g?g:0!==p?p:k.series.index>a.series.index?-1:1)}f&&(k=a)});return k};f.prototype.getChartCoordinatesFromPoint=function(a,c){var b=a.series,f=b.xAxis;b=b.yAxis;var g=m(a.clientX,a.plotX),k=a.shapeArgs;if(f&&b)return c?{chartX:f.len+f.pos-g,chartY:b.len+b.pos-a.plotY}:{chartX:g+f.pos,chartY:a.plotY+b.pos};if(k&&k.x&&k.y)return{chartX:k.x,chartY:k.y}};f.prototype.getChartPosition=function(){return this.chartPosition|| +(this.chartPosition=q(this.chart.container))};f.prototype.getCoordinates=function(a){var c={xAxis:[],yAxis:[]};this.chart.axes.forEach(function(b){c[b.isXAxis?"xAxis":"yAxis"].push({axis:b,value:b.toValue(a[b.horiz?"chartX":"chartY"])})});return c};f.prototype.getHoverData=function(a,c,b,f,g,k){var p,n=[];f=!(!f||!a);var r=c&&!c.stickyTracking,w={chartX:k?k.chartX:void 0,chartY:k?k.chartY:void 0,shared:g};J(this,"beforeGetHoverData",w);r=r?[c]:b.filter(function(a){return w.filter?w.filter(a):a.visible&& +!(!g&&a.directTouch)&&m(a.options.enableMouseTracking,!0)&&a.stickyTracking});c=(p=f||!k?a:this.findNearestKDPoint(r,g,k))&&p.series;p&&(g&&!c.noSharedTooltip?(r=b.filter(function(a){return w.filter?w.filter(a):a.visible&&!(!g&&a.directTouch)&&m(a.options.enableMouseTracking,!0)&&!a.noSharedTooltip}),r.forEach(function(a){var c=C(a.points,function(a){return a.x===p.x&&!a.isNull});A(c)&&(a.chart.isBoosting&&(c=a.getPoint(c)),n.push(c))})):n.push(p));w={hoverPoint:p};J(this,"afterGetHoverData",w);return{hoverPoint:w.hoverPoint, +hoverSeries:c,hoverPoints:n}};f.prototype.getPointFromEvent=function(a){a=a.target;for(var c;a&&!c;)c=a.point,a=a.parentNode;return c};f.prototype.onTrackerMouseOut=function(a){a=a.relatedTarget||a.toElement;var c=this.chart.hoverSeries;this.isDirectTouch=!1;if(!(!c||!a||c.stickyTracking||this.inClass(a,"highcharts-tooltip")||this.inClass(a,"highcharts-series-"+c.index)&&this.inClass(a,"highcharts-tracker")))c.onMouseOut()};f.prototype.inClass=function(a,c){for(var b;a;){if(b=H(a,"class")){if(-1!== +b.indexOf(c))return!0;if(-1!==b.indexOf("highcharts-container"))return!1}a=a.parentNode}};f.prototype.init=function(a,c){this.options=c;this.chart=a;this.runChartClick=c.chart.events&&!!c.chart.events.click;this.pinchDown=[];this.lastValidTouch={};B&&(a.tooltip=new B(a,c.tooltip),this.followTouchMove=m(c.tooltip.followTouchMove,!0));this.setDOMEvents()};f.prototype.normalize=function(a,c){var b=a.touches,f=b?b.length?b.item(0):b.changedTouches[0]:a;c||(c=this.getChartPosition());b=f.pageX-c.left; +c=f.pageY-c.top;if(f=this.chart.containerScaling)b/=f.scaleX,c/=f.scaleY;return E(a,{chartX:Math.round(b),chartY:Math.round(c)})};f.prototype.onContainerClick=function(a){var c=this.chart,b=c.hoverPoint;a=this.normalize(a);var f=c.plotLeft,g=c.plotTop;c.cancelClick||(b&&this.inClass(a.target,"highcharts-tracker")?(J(b.series,"click",E(a,{point:b})),c.hoverPoint&&b.firePointEvent("click",a)):(E(a,this.getCoordinates(a)),c.isInsidePlot(a.chartX-f,a.chartY-g)&&J(c,"click",a)))};f.prototype.onContainerMouseDown= +function(a){a=this.normalize(a);if(l.isFirefox&&0!==a.button)this.onContainerMouseMove(a);if("undefined"===typeof a.button||1===((a.buttons||a.button)&1))this.zoomOption(a),this.dragStart(a)};f.prototype.onContainerMouseLeave=function(a){var c=g[m(l.hoverChartIndex,-1)],b=this.chart.tooltip;a=this.normalize(a);c&&(a.relatedTarget||a.toElement)&&(c.pointer.reset(),c.pointer.chartPosition=void 0);b&&!b.isHidden&&this.reset()};f.prototype.onContainerMouseMove=function(a){var c=this.chart;a=this.normalize(a); +this.setHoverChartIndex();a.preventDefault||(a.returnValue=!1);"mousedown"===c.mouseIsDown&&this.drag(a);c.openMenu||!this.inClass(a.target,"highcharts-tracker")&&!c.isInsidePlot(a.chartX-c.plotLeft,a.chartY-c.plotTop)||this.runPointActions(a)};f.prototype.onDocumentTouchEnd=function(a){g[l.hoverChartIndex]&&g[l.hoverChartIndex].pointer.drop(a)};f.prototype.onContainerTouchMove=function(a){this.touch(a)};f.prototype.onContainerTouchStart=function(a){this.zoomOption(a);this.touch(a,!0)};f.prototype.onDocumentMouseMove= +function(a){var c=this.chart,b=this.chartPosition;a=this.normalize(a,b);var f=c.tooltip;!b||f&&f.isStickyOnContact()||c.isInsidePlot(a.chartX-c.plotLeft,a.chartY-c.plotTop)||this.inClass(a.target,"highcharts-tracker")||this.reset()};f.prototype.onDocumentMouseUp=function(a){var c=g[m(l.hoverChartIndex,-1)];c&&c.pointer.drop(a)};f.prototype.pinch=function(a){var c=this,f=c.chart,g=c.pinchDown,k=a.touches||[],w=k.length,v=c.lastValidTouch,n=c.hasZoom,F=c.selectionMarker,e={},D=1===w&&(c.inClass(a.target, +"highcharts-tracker")&&f.runTrackerClick||c.runChartClick),h={};1u.max&&(c=u.max-m,C=!0);C?(y-=.8*(y-v[r][0]),"number"===typeof E&&(E-=.8*(E-v[r][1])),b()):v[r]=[y,E];q||(k[r]=e-G,k[d]=m);k=q?1/I:I;g[d]=m;g[r]=c;f[q?a?"scaleY":"scaleX":"scale"+w]=I;f["translate"+w]=k*G+(y-k*z)};f.prototype.reset=function(a,c){var b=this.chart,f=b.hoverSeries,g=b.hoverPoint,k=b.hoverPoints,v=b.tooltip,n=v&&v.shared?k:g;a&&n&&u(n).forEach(function(c){c.series.isCartesian&&"undefined"===typeof c.plotX&&(a=!1)});if(a)v&&n&&u(n).length&&(v.refresh(n),v.shared&&k?k.forEach(function(a){a.setState(a.state, +!0);a.series.isCartesian&&(a.series.xAxis.crosshair&&a.series.xAxis.drawCrosshair(null,a),a.series.yAxis.crosshair&&a.series.yAxis.drawCrosshair(null,a))}):g&&(g.setState(g.state,!0),b.axes.forEach(function(a){a.crosshair&&g.series[a.coll]===a&&a.drawCrosshair(null,g)})));else{if(g)g.onMouseOut();k&&k.forEach(function(a){a.setState()});if(f)f.onMouseOut();v&&v.hide(c);this.unDocMouseMove&&(this.unDocMouseMove=this.unDocMouseMove());b.axes.forEach(function(a){a.hideCrosshair()});this.hoverX=b.hoverPoints= +b.hoverPoint=null}};f.prototype.runPointActions=function(a,c){var b=this.chart,f=b.tooltip&&b.tooltip.options.enabled?b.tooltip:void 0,k=f?f.shared:!1,w=c||b.hoverPoint,v=w&&w.series||b.hoverSeries;v=this.getHoverData(w,v,b.series,(!a||"touchmove"!==a.type)&&(!!c||v&&v.directTouch&&this.isDirectTouch),k,a);w=v.hoverPoint;var n=v.hoverPoints;c=(v=v.hoverSeries)&&v.tooltipOptions.followPointer;k=k&&v&&!v.noSharedTooltip;if(w&&(w!==b.hoverPoint||f&&f.isHidden)){(b.hoverPoints||[]).forEach(function(a){-1=== +n.indexOf(a)&&a.setState()});if(b.hoverSeries!==v)v.onMouseOver();this.applyInactiveState(n);(n||[]).forEach(function(a){a.setState("hover")});b.hoverPoint&&b.hoverPoint.firePointEvent("mouseOut");if(!w.series)return;w.firePointEvent("mouseOver");b.hoverPoints=n;b.hoverPoint=w;f&&f.refresh(k?n:w,a)}else c&&f&&!f.isHidden&&(w=f.getAnchor([{}],a),f.updatePosition({plotX:w[0],plotY:w[1]}));this.unDocMouseMove||(this.unDocMouseMove=N(b.container.ownerDocument,"mousemove",function(a){var c=g[l.hoverChartIndex]; +if(c)c.pointer.onDocumentMouseMove(a)}));b.axes.forEach(function(c){var f=m((c.crosshair||{}).snap,!0),g;f&&((g=b.hoverPoint)&&g.series[c.coll]===c||(g=C(n,function(a){return a.series[c.coll]===c})));g||!f?c.drawCrosshair(a,g):c.hideCrosshair()})};f.prototype.scaleGroups=function(a,c){var b=this.chart,f;b.series.forEach(function(g){f=a||g.getPlotBox();g.xAxis&&g.xAxis.zoomEnabled&&g.group&&(g.group.attr(f),g.markerGroup&&(g.markerGroup.attr(f),g.markerGroup.clip(c?b.clipRect:null)),g.dataLabelsGroup&& +g.dataLabelsGroup.attr(f))});b.clipRect.attr(c||b.clipBox)};f.prototype.setDOMEvents=function(){var a=this.chart.container,c=a.ownerDocument;a.onmousedown=this.onContainerMouseDown.bind(this);a.onmousemove=this.onContainerMouseMove.bind(this);a.onclick=this.onContainerClick.bind(this);this.unbindContainerMouseLeave=N(a,"mouseleave",this.onContainerMouseLeave.bind(this));l.unbindDocumentMouseUp||(l.unbindDocumentMouseUp=N(c,"mouseup",this.onDocumentMouseUp.bind(this)));l.hasTouch&&(N(a,"touchstart", +this.onContainerTouchStart.bind(this)),N(a,"touchmove",this.onContainerTouchMove.bind(this)),l.unbindDocumentTouchEnd||(l.unbindDocumentTouchEnd=N(c,"touchend",this.onDocumentTouchEnd.bind(this))))};f.prototype.setHoverChartIndex=function(){var a=this.chart,c=l.charts[m(l.hoverChartIndex,-1)];if(c&&c!==a)c.pointer.onContainerMouseLeave({relatedTarget:!0});c&&c.mouseIsDown||(l.hoverChartIndex=a.index)};f.prototype.touch=function(a,c){var b=this.chart,f;this.setHoverChartIndex();if(1===a.touches.length)if(a= +this.normalize(a),(f=b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop))&&!b.openMenu){c&&this.runPointActions(a);if("touchmove"===a.type){c=this.pinchDown;var g=c[0]?4<=Math.sqrt(Math.pow(c[0].chartX-a.chartX,2)+Math.pow(c[0].chartY-a.chartY,2)):!1}m(g,!0)&&this.pinch(a)}else c&&this.reset();else 2===a.touches.length&&this.pinch(a)};f.prototype.zoomOption=function(a){var c=this.chart,b=c.options.chart,f=b.zoomType||"";c=c.inverted;/touch/.test(a.type)&&(f=m(b.pinchType,f));this.zoomX=a=/x/.test(f); +this.zoomY=f=/y/.test(f);this.zoomHor=a&&!c||f&&c;this.zoomVert=f&&!c||a&&c;this.hasZoom=a||f};return f}();l.Pointer=e;return l.Pointer});P(x,"parts/MSPointer.js",[x["parts/Globals.js"],x["parts/Pointer.js"],x["parts/Utilities.js"]],function(l,e,B){function t(){var m=[];m.item=function(m){return this[m]};E(z,function(e){m.push({pageX:e.pageX,pageY:e.pageY,target:e.target})});return m}function N(m,e,k,g){"touch"!==m.pointerType&&m.pointerType!==m.MSPOINTER_TYPE_TOUCH||!J[l.hoverChartIndex]||(g(m), +g=J[l.hoverChartIndex].pointer,g[e]({type:k,target:m.currentTarget,preventDefault:A,touches:t()}))}var H=this&&this.__extends||function(){var m=function(e,k){m=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(g,b){g.__proto__=b}||function(g,b){for(var f in b)b.hasOwnProperty(f)&&(g[f]=b[f])};return m(e,k)};return function(e,k){function g(){this.constructor=e}m(e,k);e.prototype=null===k?Object.create(k):(g.prototype=k.prototype,new g)}}(),L=B.addEvent,K=B.css,E=B.objectEach,C=B.removeEvent, +J=l.charts,y=l.doc,A=l.noop,z={},q=!!l.win.PointerEvent;return function(m){function e(){return null!==m&&m.apply(this,arguments)||this}H(e,m);e.prototype.batchMSEvents=function(k){k(this.chart.container,q?"pointerdown":"MSPointerDown",this.onContainerPointerDown);k(this.chart.container,q?"pointermove":"MSPointerMove",this.onContainerPointerMove);k(y,q?"pointerup":"MSPointerUp",this.onDocumentPointerUp)};e.prototype.destroy=function(){this.batchMSEvents(C);m.prototype.destroy.call(this)};e.prototype.init= +function(k,g){m.prototype.init.call(this,k,g);this.hasZoom&&K(k.container,{"-ms-touch-action":"none","touch-action":"none"})};e.prototype.onContainerPointerDown=function(k){N(k,"onContainerTouchStart","touchstart",function(g){z[g.pointerId]={pageX:g.pageX,pageY:g.pageY,target:g.currentTarget}})};e.prototype.onContainerPointerMove=function(k){N(k,"onContainerTouchMove","touchmove",function(g){z[g.pointerId]={pageX:g.pageX,pageY:g.pageY};z[g.pointerId].target||(z[g.pointerId].target=g.currentTarget)})}; +e.prototype.onDocumentPointerUp=function(k){N(k,"onDocumentTouchEnd","touchend",function(g){delete z[g.pointerId]})};e.prototype.setDOMEvents=function(){m.prototype.setDOMEvents.call(this);(this.hasZoom||this.followTouchMove)&&this.batchMSEvents(L)};return e}(e)});P(x,"parts/Legend.js",[x["parts/Globals.js"],x["parts/Utilities.js"]],function(l,e){var B=e.addEvent,t=e.animObject,N=e.css,H=e.defined,L=e.discardElement,K=e.find,E=e.fireEvent,C=e.format,J=e.isNumber,y=e.merge,A=e.pick,z=e.relativeLength, +q=e.setAnimation,m=e.stableSort,u=e.syncTimeout;e=e.wrap;var k=l.isFirefox,g=l.marginNames,b=l.win,f=function(){function a(a,b){this.allItems=[];this.contentGroup=this.box=void 0;this.display=!1;this.group=void 0;this.offsetWidth=this.maxLegendWidth=this.maxItemWidth=this.legendWidth=this.legendHeight=this.lastLineHeight=this.lastItemY=this.itemY=this.itemX=this.itemMarginTop=this.itemMarginBottom=this.itemHeight=this.initialItemY=0;this.options={};this.padding=0;this.pages=[];this.proximate=!1;this.scrollGroup= +void 0;this.widthOption=this.totalItemWidth=this.titleHeight=this.symbolWidth=this.symbolHeight=0;this.chart=a;this.init(a,b)}a.prototype.init=function(a,b){this.chart=a;this.setOptions(b);b.enabled&&(this.render(),B(this.chart,"endResize",function(){this.legend.positionCheckboxes()}),this.proximate?this.unchartrender=B(this.chart,"render",function(){this.legend.proximatePositions();this.legend.positionItems()}):this.unchartrender&&this.unchartrender())};a.prototype.setOptions=function(a){var c=A(a.padding, +8);this.options=a;this.chart.styledMode||(this.itemStyle=a.itemStyle,this.itemHiddenStyle=y(this.itemStyle,a.itemHiddenStyle));this.itemMarginTop=a.itemMarginTop||0;this.itemMarginBottom=a.itemMarginBottom||0;this.padding=c;this.initialItemY=c-5;this.symbolWidth=A(a.symbolWidth,16);this.pages=[];this.proximate="proximate"===a.layout&&!this.chart.inverted;this.baseline=void 0};a.prototype.update=function(a,b){var c=this.chart;this.setOptions(y(!0,this.options,a));this.destroy();c.isDirtyLegend=c.isDirtyBox= +!0;A(b,!0)&&c.redraw();E(this,"afterUpdate")};a.prototype.colorizeItem=function(a,b){a.legendGroup[b?"removeClass":"addClass"]("highcharts-legend-item-hidden");if(!this.chart.styledMode){var c=this.options,f=a.legendItem,g=a.legendLine,k=a.legendSymbol,n=this.itemHiddenStyle.color;c=b?c.itemStyle.color:n;var r=b?a.color||n:n,m=a.options&&a.options.marker,e={fill:r};f&&f.css({fill:c,color:c});g&&g.attr({stroke:r});k&&(m&&k.isMarker&&(e=a.pointAttribs(),b||(e.stroke=e.fill=n)),k.attr(e))}E(this,"afterColorizeItem", +{item:a,visible:b})};a.prototype.positionItems=function(){this.allItems.forEach(this.positionItem,this);this.chart.isResizing||this.positionCheckboxes()};a.prototype.positionItem=function(a){var c=this.options,b=c.symbolPadding;c=!c.rtl;var f=a._legendItemPos,g=f[0];f=f[1];var k=a.checkbox;if((a=a.legendGroup)&&a.element)a[H(a.translateY)?"animate":"attr"]({translateX:c?g:this.legendWidth-g-2*b-4,translateY:f});k&&(k.x=g,k.y=f)};a.prototype.destroyItem=function(a){var c=a.checkbox;["legendItem","legendLine", +"legendSymbol","legendGroup"].forEach(function(c){a[c]&&(a[c]=a[c].destroy())});c&&L(a.checkbox)};a.prototype.destroy=function(){function a(a){this[a]&&(this[a]=this[a].destroy())}this.getAllItems().forEach(function(c){["legendItem","legendGroup"].forEach(a,c)});"clipRect up down pager nav box title group".split(" ").forEach(a,this);this.display=null};a.prototype.positionCheckboxes=function(){var a=this.group&&this.group.alignAttr,b=this.clipHeight||this.legendHeight,f=this.titleHeight;if(a){var g= +a.translateY;this.allItems.forEach(function(c){var k=c.checkbox;if(k){var p=g+f+k.y+(this.scrollOffset||0)+3;N(k,{left:a.translateX+c.checkboxOffset+k.x-20+"px",top:p+"px",display:this.proximate||p>g-6&&pm?this.maxItemWidth:a.itemWidth;f&&this.itemX-c+b>m&&(this.itemX=c,this.lastLineHeight&&(this.itemY+=n+this.lastLineHeight+k),this.lastLineHeight=0);this.lastItemY=n+this.itemY+k;this.lastLineHeight=Math.max(g,this.lastLineHeight);a._legendItemPos=[this.itemX,this.itemY];f?this.itemX+=b:(this.itemY+=n+g+k,this.lastLineHeight=g);this.offsetWidth=this.widthOption||Math.max((f?this.itemX-c-(a.checkbox?0:F):b)+c,this.offsetWidth)};a.prototype.getAllItems= +function(){var a=[];this.chart.series.forEach(function(b){var c=b&&b.options;b&&A(c.showInLegend,H(c.linkedTo)?!1:void 0,!0)&&(a=a.concat(b.legendItems||("point"===c.legendType?b.data:b)))});E(this,"afterGetAllItems",{allItems:a});return a};a.prototype.getAlignment=function(){var a=this.options;return this.proximate?a.align.charAt(0)+"tv":a.floating?"":a.align.charAt(0)+a.verticalAlign.charAt(0)+a.layout.charAt(0)};a.prototype.adjustMargins=function(a,b){var c=this.chart,f=this.options,k=this.getAlignment(); +k&&[/(lth|ct|rth)/,/(rtv|rm|rbv)/,/(rbh|cb|lbh)/,/(lbv|lm|ltv)/].forEach(function(p,n){p.test(k)&&!H(a[n])&&(c[g[n]]=Math.max(c[g[n]],c.legend[(n+1)%2?"legendHeight":"legendWidth"]+[1,-1,-1,1][n]*f[n%2?"x":"y"]+A(f.margin,12)+b[n]+(c.titleOffset[n]||0)))})};a.prototype.proximatePositions=function(){var a=this.chart,b=[],f="left"===this.options.align;this.allItems.forEach(function(c){var g=f;if(c.yAxis&&c.points){c.xAxis.options.reversed&&(g=!g);var k=K(g?c.points:c.points.slice(0).reverse(),function(a){return J(a.plotY)}); +g=this.itemMarginTop+c.legendItem.getBBox().height+this.itemMarginBottom;var n=c.yAxis.top-a.plotTop;c.visible?(k=k?k.plotY:c.yAxis.height,k+=n-.3*g):k=n+c.yAxis.height;b.push({target:k,size:g,item:c})}},this);l.distribute(b,a.plotHeight);b.forEach(function(b){b.item._legendItemPos[1]=a.plotTop-a.spacing[0]+b.pos})};a.prototype.render=function(){var a=this.chart,b=a.renderer,f=this.group,g=this.box,k=this.options,v=this.padding;this.itemX=v;this.itemY=this.initialItemY;this.lastItemY=this.offsetWidth= +0;this.widthOption=z(k.width,a.spacingBox.width-v);var n=a.spacingBox.width-2*v-k.x;-1<["rm","lm"].indexOf(this.getAlignment().substring(0,2))&&(n/=2);this.maxLegendWidth=this.widthOption||n;f||(this.group=f=b.g("legend").attr({zIndex:7}).add(),this.contentGroup=b.g().attr({zIndex:1}).add(f),this.scrollGroup=b.g().add(this.contentGroup));this.renderTitle();var F=this.getAllItems();m(F,function(a,b){return(a.options&&a.options.legendIndex||0)-(b.options&&b.options.legendIndex||0)});k.reversed&&F.reverse(); +this.allItems=F;this.display=n=!!F.length;this.itemHeight=this.totalItemWidth=this.maxItemWidth=this.lastLineHeight=0;F.forEach(this.renderItem,this);F.forEach(this.layoutItem,this);F=(this.widthOption||this.offsetWidth)+v;var e=this.lastItemY+this.lastLineHeight+this.titleHeight;e=this.handleOverflow(e);e+=v;g||(this.box=g=b.rect().addClass("highcharts-legend-box").attr({r:k.borderRadius}).add(f),g.isNew=!0);a.styledMode||g.attr({stroke:k.borderColor,"stroke-width":k.borderWidth||0,fill:k.backgroundColor|| +"none"}).shadow(k.shadow);0k&&!1!==h.enabled?(this.clipHeight= +m=Math.max(k-20-this.titleHeight-n,0),this.currentPage=A(this.currentPage,1),this.fullHeight=a,l.forEach(function(a,d){var b=a._legendItemPos[1],c=Math.round(a.legendItem.getBBox().height),h=q.length;if(!h||b-q[h-1]>m&&(u||b)!==q[h-1])q.push(u||b),h++;a.pageIx=h-1;u&&(l[d-1].pageIx=h-1);d===l.length-1&&b+c-q[h-1]>m&&b!==u&&(q.push(b),a.pageIx=h);b!==u&&(u=b)}),e||(e=b.clipRect=f.clipRect(0,n,9999,0),b.contentGroup.clip(e)),z(m),M||(this.nav=M=f.g().attr({zIndex:1}).add(this.group),this.up=f.symbol("triangle", +0,0,G,G).add(M),y("upTracker").on("click",function(){b.scroll(-1,d)}),this.pager=f.text("",15,10).addClass("highcharts-legend-navigation"),c.styledMode||this.pager.css(h.style),this.pager.add(M),this.down=f.symbol("triangle-down",0,0,G,G).add(M),y("downTracker").on("click",function(){b.scroll(1,d)})),b.scroll(0),a=k):M&&(z(),this.nav=M.destroy(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0);return a};a.prototype.scroll=function(a,b){var c=this,f=this.chart,g=this.pages,k=g.length,n=this.currentPage+ +a;a=this.clipHeight;var r=this.options.navigation,m=this.pager,e=this.padding;n>k&&(n=k);0=f.value;)f=g[++b];this.nonZonedColor||(this.nonZonedColor=this.color);this.color=f&&f.color&&!this.options.color?f.color:this.nonZonedColor;return f};e.prototype.hasNewShapeType=function(){return(this.graphic&&(this.graphic.symbolName||this.graphic.element.nodeName))!==this.shapeType};e.prototype.init=function(k,g,b){this.series=k;this.applyOptions(g,b);this.id=t(this.id)?this.id:m();this.resolveColor();k.chart.pointCount++;L(this,"afterInit");return this};e.prototype.optionsToObject= +function(k){var g={},b=this.series,f=b.options.keys,a=f||b.pointArrayMap||["y"],c=a.length,r=0,p=0;if(J(k)||null===k)g[a[0]]=k;else if(C(k))for(!f&&k.length>c&&(b=typeof k[0],"string"===b?g.name=k[0]:"number"===b&&(g.x=k[0]),r++);p=r(a[c].options.index,a[c]._i)){a.splice(c+1,0,this);break}-1===c&&a.unshift(this);c+=1}else a.push(this);return r(c,a.length-1)},bindAxes:function(){var a=this,b=a.options,c=a.chart,h;m(this,"bindAxes",null,function(){(a.axisTypes||[]).forEach(function(d){c[d].forEach(function(c){h=c.options;if(b[d]===h.index||"undefined"!==typeof b[d]&&b[d]===h.id||"undefined"===typeof b[d]&&0===h.index)a.insert(c.series), +a[d]=c,c.isDirty=!0});a[d]||a.optionalAxis===d||A(18,!0,c)})});m(this,"afterBindAxes")},updateParallelArrays:function(a,c){var d=a.series,h=arguments,f=b(c)?function(b){var h="y"===b&&d.toYData?d.toYData(a):a[b];d[b+"Data"][c]=h}:function(a){Array.prototype[c].apply(d[a+"Data"],Array.prototype.slice.call(h,2))};d.parallelArrays.forEach(f)},hasData:function(){return this.visible&&"undefined"!==typeof this.dataMax&&"undefined"!==typeof this.dataMin||this.visible&&this.yData&&0=this.cropStart?e-this.cropStart:e);!g&&f[e]&&f[e].touched&&(e=void 0);return e},drawLegendSymbol:l.drawLineMarker,updateData:function(a,c){var d=this.options,h=d.dataSorting,f=this.points,g=[],k,n,p,e=this.requireSorting,v=a.length===f.length, +w=!0;this.xIncrement=null;a.forEach(function(a,c){var n=J(a)&&this.pointClass.prototype.optionsToObject.call({series:this},a)||{};var w=n.x;if(n.id||b(w)){if(w=this.findPointIndex(n,p),-1===w||"undefined"===typeof w?g.push(a):f[w]&&a!==d.data[w]?(f[w].update(a,!1,null,!1),f[w].touched=!0,e&&(p=w+1)):f[w]&&(f[w].touched=!0),!v||c!==w||h&&h.enabled||this.hasDerivedData)k=!0}else g.push(a)},this);if(k)for(a=f.length;a--;)(n=f[a])&&!n.touched&&n.remove&&n.remove(!1,c);else!v||h&&h.enabled?w=!1:(a.forEach(function(a, +d){f[d].update&&a!==f[d].y&&f[d].update(a,!1,null,!1)}),g.length=0);f.forEach(function(a){a&&(a.touched=!1)});if(!w)return!1;g.forEach(function(a){this.addPoint(a,!1,null,null,!1)},this);null===this.xIncrement&&this.xData&&this.xData.length&&(this.xIncrement=L(this.xData),this.autoIncrement());return!0},setData:function(a,c,h,g){var d=this,n=d.points,p=n&&n.length||0,e,w=d.options,v=d.chart,F=w.dataSorting,m=null,G=d.xAxis;m=w.turboThreshold;var q=this.xData,l=this.yData,D=(e=d.pointArrayMap)&&e.length, +M=w.keys,u=0,O=1,z;a=a||[];e=a.length;c=r(c,!0);F&&F.enabled&&(a=this.sortData(a));!1!==g&&e&&p&&!d.cropped&&!d.hasGroupedData&&d.visible&&!d.isSeriesBoosting&&(z=this.updateData(a,h));if(!z){d.xIncrement=null;d.colorCounter=0;this.parallelArrays.forEach(function(a){d[a+"Data"].length=0});if(m&&e>m)if(m=d.getFirstValidPoint(a),b(m))for(h=0;ha?1:0}).forEach(function(a,d){a.x=d},this);d.linkedSeries&&d.linkedSeries.forEach(function(d){var b=d.options,h=b.data;b.dataSorting&&b.dataSorting.enabled||!h||(h.forEach(function(b,f){h[f]=c(d,b);a[f]&&(h[f].x=a[f].x,h[f].index= +f)}),d.setData(h,!1))});return a},getProcessedData:function(a){var d=this.xData,b=this.yData,c=d.length;var h=0;var f=this.xAxis,g=this.options;var k=g.cropThreshold;var n=a||this.getExtremesFromAll||g.getExtremesFromAll,p=this.isCartesian;a=f&&f.val2lin;g=!(!f||!f.logarithmic);var e=this.requireSorting;if(f){f=f.getExtremes();var w=f.min;var v=f.max}if(p&&this.sorted&&!n&&(!k||c>k||this.forceCrop))if(d[c-1]v)d=[],b=[];else if(this.yData&&(d[0]v)){h=this.cropData(this.xData,this.yData, +w,v);d=h.xData;b=h.yData;h=h.start;var r=!0}for(k=d.length||1;--k;)if(c=g?a(d[k])-a(d[k-1]):d[k]-d[k-1],0c&&e&&(A(15,!1,this.chart),e=!1);return{xData:d,yData:b,cropped:r,cropStart:h,closestPointRange:F}},processData:function(a){var d=this.xAxis;if(this.isCartesian&&!this.isDirty&&!d.isDirty&&!this.yAxis.isDirty&&!a)return!1;a=this.getProcessedData();this.cropped=a.cropped;this.cropStart=a.cropStart;this.processedXData=a.xData;this.processedYData=a.yData; +this.closestPointRange=this.basePointRange=a.closestPointRange},cropData:function(a,b,c,h,f){var d=a.length,g=0,k=d,n;f=r(f,this.cropShoulder);for(n=0;n=c){g=Math.max(0,n-f);break}for(c=n;ch){k=c+f;break}return{xData:a.slice(g,k),yData:b.slice(g,k),start:g,end:k}},generatePoints:function(){var a=this.options,b=a.data,c=this.data,h,f=this.processedXData,g=this.processedYData,k=this.pointClass,n=f.length,p=this.cropStart||0,e=this.hasGroupedData;a=a.keys;var v=[],r;c|| +e||(c=[],c.length=b.length,c=this.data=c);a&&e&&(this.options.keys=!1);for(r=0;r=p&&(f[r-v]||F)<=e;if(q&&F)if(q=G.length)for(;q--;)b(G[q])&&(g[n++]=G[q]);else g[n++]=G}a={dataMin:K(g),dataMax:L(g)};m(this,"afterGetExtremes",{dataExtremes:a});return a},applyExtremes:function(){var a=this.getExtremes();this.dataMin=a.dataMin;this.dataMax=a.dataMax;return a},getFirstValidPoint:function(a){for(var d=null,b=a.length,c=0;null===d&&c=A&&(I.isNull=!0);I.plotX=u=C(E(h.translate(y,0,0,0,1,F,"flags"=== +this.type),-1E5,1E5));if(c&&this.visible&&B&&B[y]){var K=this.getStackIndicator(K,y,this.index);if(!I.isNull){var L=B[y];var H=L.points[K.key]}}k(H)&&(t=H[0],A=H[1],t===D&&K.key===B[y].base&&(t=r(b(l)&&l,n.min)),n.positiveValuesOnly&&0>=t&&(t=null),I.total=I.stackTotal=L.total,I.percentage=L.total&&I.y/L.total*100,I.stackY=A,this.irregularWidths||L.setOffset(this.pointXOffset||0,this.barW||0));I.yBottom=J(t)?E(n.translate(t,0,1,0,1),-1E5,1E5):null;v&&(A=this.modifyValue(A,I));I.plotY="number"===typeof A&& +Infinity!==A?E(n.translate(A,0,1,0,1),-1E5,1E5):void 0;I.isInside=this.isPointInside(I);I.clientX=q?C(h.translate(y,0,0,0,1,F)):u;I.negative=I[O]<(a[O+"Threshold"]||l||0);I.category=f&&"undefined"!==typeof f[I.x]?f[I.x]:I.x;if(!I.isNull&&!1!==I.visible){"undefined"!==typeof x&&(z=Math.min(z,Math.abs(u-x)));var x=u}I.zone=this.zones.length&&I.getZone();!I.graphic&&this.group&&g&&(I.isNew=!0)}this.closestPointRangePx=z;m(this,"afterTranslate")},getValidPoints:function(a,b,c){var d=this.chart;return(a|| +this.points||[]).filter(function(a){return b&&!d.isInsidePlot(a.plotX,a.plotY,d.inverted)?!1:!1!==a.visible&&(c||!a.isNull)})},getClipBox:function(a,b){var d=this.options,c=this.chart,h=c.inverted,f=this.xAxis,g=f&&this.yAxis;a&&!1===d.clip&&g?a=h?{y:-c.chartWidth+g.len+g.pos,height:c.chartWidth,width:c.chartHeight,x:-c.chartHeight+f.len+f.pos}:{y:-g.pos,height:c.chartHeight,width:c.chartWidth,x:-f.pos}:(a=this.clipBox||c.clipBox,b&&(a.width=c.plotSizeX,a.x=0));return b?{width:a.width,x:a.x}:a},setClip:function(a){var d= +this.chart,b=this.options,c=d.renderer,h=d.inverted,f=this.clipBox,g=this.getClipBox(a),k=this.sharedClipKey||["_sharedClip",a&&a.duration,a&&a.easing,g.height,b.xAxis,b.yAxis].join(),n=d[k],p=d[k+"m"];a&&(g.width=0,h&&(g.x=d.plotHeight+(!1!==b.clip?0:d.plotTop)));n?d.hasLoaded||n.attr(g):(a&&(d[k+"m"]=p=c.clipRect(h?d.plotSizeX+99:-99,h?-d.plotLeft:-d.plotTop,99,h?d.chartWidth:d.chartHeight)),d[k]=n=c.clipRect(g),n.count={length:0});a&&!n.count[this.index]&&(n.count[this.index]=!0,n.count.length+= +1);if(!1!==b.clip||a)this.group.clip(a||f?n:d.clipRect),this.markerGroup.clip(p),this.sharedClipKey=k;a||(n.count[this.index]&&(delete n.count[this.index],--n.count.length),0===n.count.length&&k&&d[k]&&(f||(d[k]=d[k].destroy()),d[k+"m"]&&(d[k+"m"]=d[k+"m"].destroy())))},animate:function(a){var d=this.chart,b=H(this.options.animation);if(!d.hasRendered)if(a)this.setClip(b);else{var c=this.sharedClipKey;a=d[c];var h=this.getClipBox(b,!0);a&&a.animate(h,b);d[c+"m"]&&d[c+"m"].animate({width:h.width+99, +x:h.x-(d.inverted?0:99)},b)}},afterAnimate:function(){this.setClip();m(this,"afterAnimate");this.finishedAnimating=!0},drawPoints:function(){var a=this.points,b=this.chart,c,h,f=this.options.marker,g=this[this.specialGroup]||this.markerGroup,k=this.xAxis,n=r(f.enabled,!k||k.isRadial?!0:null,this.closestPointRangePx>=f.enabledThreshold*f.radius);if(!1!==f.enabled||this._hasPointMarkers)for(c=0;cf&&b.shadow));k&&(k.startX=c.xMap,k.isArea=c.isArea)})},getZonesGraphs:function(a){this.zones.forEach(function(d, +b){b=["zone-graph-"+b,"highcharts-graph highcharts-zone-graph-"+b+" "+(d.className||"")];this.chart.styledMode||b.push(d.color||this.color,d.dashStyle||this.options.dashStyle);a.push(b)},this);return a},applyZones:function(){var a=this,b=this.chart,c=b.renderer,h=this.zones,f,g,k=this.clips||[],n,p=this.graph,e=this.area,w=Math.max(b.chartWidth,b.chartHeight),v=this[(this.zoneAxis||"y")+"Axis"],F=b.inverted,m,q,l,D=!1,u,O;if(h.length&&(p||e)&&v&&"undefined"!==typeof v.min){var I=v.reversed;var z= +v.horiz;p&&!this.showLine&&p.hide();e&&e.hide();var y=v.getExtremes();h.forEach(function(d,h){f=I?z?b.plotWidth:0:z?0:v.toPixels(y.min)||0;f=E(r(g,f),0,w);g=E(Math.round(v.toPixels(r(d.value,y.max),!0)||0),0,w);D&&(f=g=v.toPixels(y.max));m=Math.abs(f-g);q=Math.min(f,g);l=Math.max(f,g);v.isXAxis?(n={x:F?l:q,y:0,width:m,height:w},z||(n.x=b.plotHeight-n.x)):(n={x:0,y:F?l:q,width:w,height:m},z&&(n.y=b.plotWidth-n.y));F&&c.isVML&&(n=v.isXAxis?{x:0,y:I?q:l,height:n.width,width:b.chartWidth}:{x:n.y-b.plotLeft- +b.spacingBox.x,y:0,width:n.height,height:b.chartHeight});k[h]?k[h].animate(n):k[h]=c.clipRect(n);u=a["zone-area-"+h];O=a["zone-graph-"+h];p&&O&&O.clip(k[h]);e&&u&&u.clip(k[h]);D=d.value>y.max;a.resetZones&&0===g&&(g=void 0)});this.clips=k}else a.visible&&(p&&p.show(!0),e&&e.show(!0))},invertGroups:function(a){function d(){["group","markerGroup"].forEach(function(d){b[d]&&(c.renderer.isVML&&b[d].attr({width:b.yAxis.len,height:b.xAxis.len}),b[d].width=b.yAxis.len,b[d].height=b.xAxis.len,b[d].invert(b.isRadialSeries? +!1:a))})}var b=this,c=b.chart;b.xAxis&&(b.eventsToUnbind.push(x(c,"resize",d)),d(),b.invertGroups=d)},plotGroup:function(a,b,c,h,f){var d=this[a],g=!d;g&&(this[a]=d=this.chart.renderer.g().attr({zIndex:h||.1}).add(f));d.addClass("highcharts-"+b+" highcharts-series-"+this.index+" highcharts-"+this.type+"-series "+(J(this.colorIndex)?"highcharts-color-"+this.colorIndex+" ":"")+(this.options.className||"")+(d.hasClass("highcharts-tracker")?" highcharts-tracker":""),!0);d.attr({visibility:c})[g?"attr": +"animate"](this.getPlotBox());return d},getPlotBox:function(){var a=this.chart,b=this.xAxis,c=this.yAxis;a.inverted&&(b=c,c=this.xAxis);return{translateX:b?b.left:a.plotLeft,translateY:c?c.top:a.plotTop,scaleX:1,scaleY:1}},removeEvents:function(a){a?this.eventsToUnbind.length&&(this.eventsToUnbind.forEach(function(a){a()}),this.eventsToUnbind.length=0):p(this)},render:function(){var a=this,b=a.chart,c=a.options,h=!a.finishedAnimating&&b.renderer.isSVG&&H(c.animation).duration,f=a.visible?"inherit": +"hidden",g=c.zIndex,k=a.hasRendered,n=b.seriesGroup,p=b.inverted;m(this,"render");var e=a.plotGroup("group","series",f,g,n);a.markerGroup=a.plotGroup("markerGroup","markers",f,g,n);h&&a.animate&&a.animate(!0);e.inverted=a.isCartesian||a.invertable?p:!1;a.drawGraph&&(a.drawGraph(),a.applyZones());a.visible&&a.drawPoints();a.drawDataLabels&&a.drawDataLabels();a.redrawPoints&&a.redrawPoints();a.drawTracker&&!1!==a.options.enableMouseTracking&&a.drawTracker();a.invertGroups(p);!1===c.clip||a.sharedClipKey|| +k||e.clip(b.clipRect);h&&a.animate&&a.animate();k||(a.animationTimeout=v(function(){a.afterAnimate()},h||0));a.isDirty=!1;a.hasRendered=!0;m(a,"afterRender")},redraw:function(){var a=this.chart,b=this.isDirty||this.isDirtyData,c=this.group,h=this.xAxis,f=this.yAxis;c&&(a.inverted&&c.attr({width:a.plotWidth,height:a.plotHeight}),c.animate({translateX:r(h&&h.left,a.plotLeft),translateY:r(f&&f.top,a.plotTop)}));this.translate();this.render();b&&delete this.kdTree},kdAxisArray:["clientX","plotY"],searchPoint:function(a, +b){var d=this.xAxis,c=this.yAxis,h=this.chart.inverted;return this.searchKDTree({clientX:h?d.len-a.chartY+d.pos:a.chartX-d.pos,plotY:h?c.len-a.chartX+c.pos:a.chartY-c.pos},b,a)},buildKDTree:function(a){function d(a,c,h){var f;if(f=a&&a.length){var g=b.kdAxisArray[c%h];a.sort(function(a,d){return a[g]-d[g]});f=Math.floor(f/2);return{point:a[f],left:d(a.slice(0,f),c+1,h),right:d(a.slice(f+1),c+1,h)}}}this.buildingKdTree=!0;var b=this,c=-1e?"left":"right";w=0>e?"right":"left";b[r]&&(r=d(a,b[r],c+1, +n),v=r[k]m;)F--;this.updateParallelArrays(w,"splice",F,0,0);this.updateParallelArrays(w,F);p&&w.name&&(p[m]=w.name);e.splice(F,0,a);v&&(this.data.splice(F,0,null),this.processData());"point"===n.legendType&&this.generatePoints();f&&(h[0]&&h[0].remove?h[0].remove(!1):(h.shift(),this.updateParallelArrays(w,"shift"),e.shift()));!1!==k&&A(this,"addPoint",{point:w});this.isDirtyData=this.isDirty=!0;c&&d.redraw(g)},removePoint:function(c, +f,g){var k=this,n=k.data,p=n[c],h=k.points,d=k.chart,e=function(){h&&h.length===n.length&&h.splice(c,1);n.splice(c,1);k.options.data.splice(c,1);k.updateParallelArrays(p||{series:k},"splice",c,1);p&&p.destroy();k.isDirty=!0;k.isDirtyData=!0;f&&d.redraw()};a(g,d);f=b(f,!0);p?p.firePointEvent("remove",null,e):e()},remove:function(a,c,f,g){function k(){n.destroy(g);n.remove=null;h.isDirtyLegend=h.isDirtyBox=!0;h.linkSeries();b(a,!0)&&h.redraw(c)}var n=this,h=n.chart;!1!==f?A(n,"remove",null,k):k()}, +update:function(a,c){a=l.cleanRecursively(a,this.userOptions);A(this,"update",{options:a});var f=this,g=f.chart,p=f.userOptions,e=f.initialType||f.type,h=a.type||p.type||g.options.chart.type,d=!(this.hasDerivedData||a.dataGrouping||h&&h!==this.type||"undefined"!==typeof a.pointStart||a.pointInterval||a.pointIntervalUnit||a.keys),r=I[e].prototype,v,w=["group","markerGroup","dataLabelsGroup","transformGroup"],m=["eventOptions","navigatorSeries","baseSeries"],q=f.finishedAnimating&&{animation:!1},u= +{};d&&(m.push("data","isDirtyData","points","processedXData","processedYData","xIncrement","_hasPointMarkers","_hasPointLabels","mapMap","mapData","minY","maxY","minX","maxX"),!1!==a.visible&&m.push("area","graph"),f.parallelArrays.forEach(function(a){m.push(a+"Data")}),a.data&&(a.dataSorting&&y(f.options.dataSorting,a.dataSorting),this.setData(a.data,!1)));a=k(p,q,{index:"undefined"===typeof p.index?f.index:p.index,pointStart:b(p.pointStart,f.xData[0])},!d&&{data:f.options.data},a);d&&a.data&&(a.data= +f.options.data);m=w.concat(m);m.forEach(function(a){m[a]=f[a];delete f[a]});f.remove(!1,null,!1,!0);for(v in r)f[v]=void 0;I[h||e]?y(f,I[h||e].prototype):J(17,!0,g,{missingModuleFor:h||e});m.forEach(function(a){f[a]=m[a]});f.init(g,a);if(d&&this.points){var z=f.options;!1===z.visible?(u.graphic=1,u.dataLabel=1):f._hasPointLabels||(h=z.marker,r=z.dataLabels,h&&(!1===h.enabled||"symbol"in h)&&(u.graphic=1),r&&!1===r.enabled&&(u.dataLabel=1));this.points.forEach(function(a){a&&a.series&&(a.resolveColor(), +Object.keys(u).length&&a.destroyElements(u),!1===z.showInLegend&&a.legendItem&&g.legend.destroyItem(a))},this)}a.zIndex!==p.zIndex&&w.forEach(function(d){f[d]&&f[d].attr({zIndex:a.zIndex})});f.initialType=e;g.linkSeries();A(this,"afterUpdate");b(c,!0)&&g.redraw(d?void 0:!1)},setName:function(a){this.name=this.options.name=this.userOptions.name=a;this.chart.isDirtyLegend=!0}});y(r.prototype,{update:function(a,c){var f=this.chart,p=a&&a.events||{};a=k(this.userOptions,a);f.options[this.coll].indexOf&& +(f.options[this.coll][f.options[this.coll].indexOf(this.userOptions)]=a);g(f.options[this.coll].events,function(a,b){"undefined"===typeof p[b]&&(p[b]=void 0)});this.destroy(!0);this.init(f,y(a,{events:p}));f.isDirtyBox=!0;b(c,!0)&&f.redraw()},remove:function(a){for(var c=this.chart,f=this.coll,g=this.series,k=g.length;k--;)g[k]&&g[k].remove(!1);C(c.axes,this);C(c[f],this);z(c.options[f])?c.options[f].splice(this.options.index,1):delete c.options[f];c[f].forEach(function(a,b){a.options.index=a.userOptions.index= +b});this.destroy();c.isDirtyBox=!0;b(a,!0)&&c.redraw()},setTitle:function(a,b){this.update({title:a},b)},setCategories:function(a,b){this.update({categories:a},b)}})});P(x,"parts/AreaSeries.js",[x["parts/Globals.js"],x["parts/Color.js"],x["mixins/legend-symbol.js"],x["parts/Utilities.js"]],function(l,e,B,t){var x=e.parse,H=t.objectEach,L=t.pick;e=t.seriesType;var K=l.Series;e("area","line",{softThreshold:!1,threshold:0},{singleStacks:!1,getStackPoints:function(e){var l=[],t=[],y=this.xAxis,A=this.yAxis, +z=A.stacking.stacks[this.stackKey],q={},m=this.index,u=A.series,k=u.length,g=L(A.options.reversedStacks,!0)?1:-1,b;e=e||this.points;if(this.options.stacking){for(b=0;bl&&y>L?(y=Math.max(l,L),A=2*L-y):yx&&A>L?(A=Math.max(x,L),y=2*L-A):A=Math.abs(l)&&.5e.closestPointRange*e.xAxis.transA;u=e.borderWidth=y(m.borderWidth,u?0:1);var k=e.xAxis,g=e.yAxis,b=m.threshold,f=e.translatedThreshold=g.getThreshold(b),a=y(m.minPointLength,5),c=e.getColumnMetrics(),r=c.width,p=e.barW=Math.max(r,1+2*u),I=e.pointXOffset=c.offset,w=e.dataMin, +v=e.dataMax;l.inverted&&(f-=.5);m.pointPadding&&(p=Math.ceil(p));A.prototype.translate.apply(e);e.points.forEach(function(c){var n=y(c.yBottom,f),m=999+Math.abs(n),q=r,h=c.plotX;m=L(c.plotY,-m,g.len+m);var d=c.plotX+I,u=p,z=Math.min(m,n),t=Math.max(m,n)-z;if(a&&Math.abs(t)a?n-a:f-(A?a:0)}K(c.options.pointWidth)&&(q=u=Math.ceil(c.options.pointWidth),d-=Math.round((q- +r)/2));c.barX=d;c.pointWidth=q;c.tooltipPos=l.inverted?[g.len+g.pos-l.plotLeft-m,k.len+k.pos-l.plotTop-(h||0)-I-u/2,t]:[d+u/2,m+g.pos-l.plotTop,t];c.shapeType=e.pointClass.prototype.shapeType||"rect";c.shapeArgs=e.crispCol.apply(e,c.isNull?[d,f,u,0]:[d,z,u,t])})},getSymbol:l.noop,drawLegendSymbol:B.drawRectangle,drawGraph:function(){this.group[this.dense?"addClass":"removeClass"]("highcharts-dense-data")},pointAttribs:function(e,l){var m=this.options,q=this.pointAttrToOptions||{};var k=q.stroke|| +"borderColor";var g=q["stroke-width"]||"borderWidth",b=e&&e.color||this.color,f=e&&e[k]||m[k]||this.color||b,a=e&&e[g]||m[g]||this[g]||0;q=e&&e.options.dashStyle||m.dashStyle;var c=y(e&&e.opacity,m.opacity,1);if(e&&this.zones.length){var r=e.getZone();b=e.options.color||r&&(r.color||e.nonZonedColor)||this.color;r&&(f=r.borderColor||f,q=r.dashStyle||q,a=r.borderWidth||a)}l&&e&&(e=J(m.states[l],e.options.states&&e.options.states[l]||{}),l=e.brightness,b=e.color||"undefined"!==typeof l&&x(b).brighten(e.brightness).get()|| +b,f=e[k]||f,a=e[g]||a,q=e.dashStyle||q,c=y(e.opacity,c));k={fill:b,stroke:f,"stroke-width":a,opacity:c};q&&(k.dashstyle=q);return k},drawPoints:function(){var e=this,l=this.chart,m=e.options,u=l.renderer,k=m.animationLimit||250,g;e.points.forEach(function(b){var f=b.graphic,a=!!f,c=f&&l.pointCount\u25cf
{series.name}
',pointFormat:"x: {point.x}
y: {point.y}
"}},{sorted:!1,requireSorting:!1,noSharedTooltip:!0,trackerGroups:["group", +"markerGroup","dataLabelsGroup"],takeOrdinalPosition:!1,drawGraph:function(){this.options.lineWidth&&t.prototype.drawGraph.call(this)},applyJitter:function(){var e=this,l=this.options.jitter,t=this.points.length;l&&this.points.forEach(function(B,E){["x","y"].forEach(function(C,J){var y="plot"+C.toUpperCase();if(l[C]&&!B.isNull){var A=e[C+"Axis"];var z=l[C]*A.transA;if(A&&!A.isLog){var q=Math.max(0,B[y]-z);A=Math.min(A.len,B[y]+z);J=1E4*Math.sin(E+J*t);B[y]=q+(A-q)*(J-Math.floor(J));"x"===C&&(B.clientX= +B.plotX)}}})})}});B(t,"afterTranslate",function(){this.applyJitter&&this.applyJitter()});""});P(x,"mixins/centered-series.js",[x["parts/Globals.js"],x["parts/Utilities.js"]],function(l,e){var B=e.isNumber,t=e.pick,x=e.relativeLength,H=l.deg2rad;l.CenteredSeriesMixin={getCenter:function(){var e=this.options,l=this.chart,E=2*(e.slicedOffset||0),C=l.plotWidth-2*E,J=l.plotHeight-2*E,y=e.center,A=Math.min(C,J),z=e.size,q=e.innerSize||0;"string"===typeof z&&(z=parseFloat(z));"string"===typeof q&&(q=parseFloat(q)); +e=[t(y[0],"50%"),t(y[1],"50%"),t(z&&0>z?void 0:e.size,"100%"),t(q&&0>q?void 0:e.innerSize||0,"0%")];l.angular&&(e[3]=0);for(y=0;4>y;++y)z=e[y],l=2>y||2===y&&/%$/.test(z),e[y]=x(z,[C,J,A,e[2]][y])+(l?E:0);e[3]>e[2]&&(e[3]=e[2]);return e},getStartAndEndRadians:function(e,l){e=B(e)?e:0;l=B(l)&&l>e&&360>l-e?l:e+360;return{start:H*(e+-90),end:H*(l+-90)}}}});P(x,"parts/PieSeries.js",[x["parts/Globals.js"],x["mixins/legend-symbol.js"],x["parts/Point.js"],x["parts/Utilities.js"]],function(l,e,B,t){var x= +t.addEvent,H=t.clamp,L=t.defined,K=t.fireEvent,E=t.isNumber,C=t.merge,J=t.pick,y=t.relativeLength,A=t.seriesType,z=t.setAnimation;t=l.CenteredSeriesMixin;var q=t.getStartAndEndRadians,m=l.noop,u=l.Series;A("pie","line",{center:[null,null],clip:!1,colorByPoint:!0,dataLabels:{allowOverlap:!0,connectorPadding:5,connectorShape:"fixedOffset",crookDistance:"70%",distance:30,enabled:!0,formatter:function(){return this.point.isNull?void 0:this.point.name},softConnector:!0,x:0},fillColor:void 0,ignoreHiddenPoint:!0, +inactiveOtherPoints:!0,legendType:"point",marker:null,size:null,showInLegend:!1,slicedOffset:10,stickyTracking:!1,tooltip:{followPointer:!0},borderColor:"#ffffff",borderWidth:1,lineWidth:void 0,states:{hover:{brightness:.1}}},{isCartesian:!1,requireSorting:!1,directTouch:!0,noSharedTooltip:!0,trackerGroups:["group","dataLabelsGroup"],axisTypes:[],pointAttribs:l.seriesTypes.column.prototype.pointAttribs,animate:function(k){var g=this,b=g.points,f=g.startAngleRad;k||b.forEach(function(a){var b=a.graphic, +k=a.shapeArgs;b&&k&&(b.attr({r:J(a.startR,g.center&&g.center[3]/2),start:f,end:f}),b.animate({r:k.r,start:k.start,end:k.end},g.options.animation))})},hasData:function(){return!!this.processedXData.length},updateTotals:function(){var k,g=0,b=this.points,f=b.length,a=this.options.ignoreHiddenPoint;for(k=0;k1.5*Math.PI? +u-=2*Math.PI:u<-Math.PI/2&&(u+=2*Math.PI);n.slicedTranslation={translateX:Math.round(Math.cos(u)*f),translateY:Math.round(Math.sin(u)*f)};var D=Math.cos(u)*k[2]/2;var h=Math.sin(u)*k[2]/2;n.tooltipPos=[k[0]+.7*D,k[1]+.7*h];n.half=u<-Math.PI/2||u>Math.PI/2?1:0;n.angle=u;F=Math.min(a,n.labelDistance/5);n.labelPosition={natural:{x:k[0]+D+Math.cos(u)*n.labelDistance,y:k[1]+h+Math.sin(u)*n.labelDistance},"final":{},alignment:0>n.labelDistance?"center":n.half?"right":"left",connectorPosition:{breakAt:{x:k[0]+ +D+Math.cos(u)*F,y:k[1]+h+Math.sin(u)*F},touchingSliceAt:{x:k[0]+D,y:k[1]+h}}}}K(this,"afterTranslate")},drawEmpty:function(){var k=this.options;if(0===this.total){var g=this.center[0];var b=this.center[1];this.graph||(this.graph=this.chart.renderer.circle(g,b,0).addClass("highcharts-graph").add(this.group));this.graph.animate({"stroke-width":k.borderWidth,cx:g,cy:b,r:this.center[2]/2,fill:k.fillColor||"none",stroke:k.color||"#cccccc"},this.options.animation)}else this.graph&&(this.graph=this.graph.destroy())}, +redrawPoints:function(){var k=this,g=k.chart,b=g.renderer,f,a,c,e,p=k.options.shadow;this.drawEmpty();!p||k.shadowGroup||g.styledMode||(k.shadowGroup=b.g("shadow").attr({zIndex:-1}).add(k.group));k.points.forEach(function(r){var l={};a=r.graphic;if(!r.isNull&&a){e=r.shapeArgs;f=r.getTranslate();if(!g.styledMode){var v=r.shadowGroup;p&&!v&&(v=r.shadowGroup=b.g("shadow").add(k.shadowGroup));v&&v.attr(f);c=k.pointAttribs(r,r.selected&&"select")}r.delayedRendering?(a.setRadialReference(k.center).attr(e).attr(f), +g.styledMode||a.attr(c).attr({"stroke-linejoin":"round"}).shadow(p,v),r.delayedRendering=!1):(a.setRadialReference(k.center),g.styledMode||C(!0,l,c),C(!0,l,e,f),a.animate(l));a.attr({visibility:r.visible?"inherit":"hidden"});a.addClass(r.getClassName())}else a&&(r.graphic=a.destroy())})},drawPoints:function(){var k=this.chart.renderer;this.points.forEach(function(g){g.graphic&&g.hasNewShapeType()&&(g.graphic=g.graphic.destroy());g.graphic||(g.graphic=k[g.shapeType](g.shapeArgs).add(g.series.group), +g.delayedRendering=!0)})},searchPoint:m,sortByAngle:function(k,g){k.sort(function(b,f){return"undefined"!==typeof b.angle&&(f.angle-b.angle)*g})},drawLegendSymbol:e.drawRectangle,getCenter:t.getCenter,getSymbol:m,drawGraph:null},{init:function(){B.prototype.init.apply(this,arguments);var k=this;k.name=J(k.name,"Slice");var g=function(b){k.slice("select"===b.type)};x(k,"select",g);x(k,"unselect",g);return k},isValid:function(){return E(this.y)&&0<=this.y},setVisible:function(k,g){var b=this,f=b.series, +a=f.chart,c=f.options.ignoreHiddenPoint;g=J(g,c);k!==b.visible&&(b.visible=b.options.visible=k="undefined"===typeof k?!b.visible:k,f.options.data[f.data.indexOf(b)]=b.options,["graphic","dataLabel","connector","shadowGroup"].forEach(function(a){if(b[a])b[a][k?"show":"hide"](!0)}),b.legendItem&&a.legend.colorizeItem(b,k),k||"hover"!==b.state||b.setState(""),c&&(f.isDirty=!0),g&&a.redraw())},slice:function(k,g,b){var f=this.series;z(b,f.chart);J(g,!0);this.sliced=this.options.sliced=L(k)?k:!this.sliced; +f.options.data[f.data.indexOf(this)]=this.options;this.graphic&&this.graphic.animate(this.getTranslate());this.shadowGroup&&this.shadowGroup.animate(this.getTranslate())},getTranslate:function(){return this.sliced?this.slicedTranslation:{translateX:0,translateY:0}},haloPath:function(k){var g=this.shapeArgs;return this.sliced||!this.visible?[]:this.series.chart.renderer.symbols.arc(g.x,g.y,g.r+k,g.r+k,{innerR:g.r-1,start:g.start,end:g.end})},connectorShapes:{fixedOffset:function(k,g,b){var f=g.breakAt; +g=g.touchingSliceAt;return[["M",k.x,k.y],b.softConnector?["C",k.x+("left"===k.alignment?-5:5),k.y,2*f.x-g.x,2*f.y-g.y,f.x,f.y]:["L",f.x,f.y],["L",g.x,g.y]]},straight:function(k,g){g=g.touchingSliceAt;return[["M",k.x,k.y],["L",g.x,g.y]]},crookedLine:function(k,g,b){g=g.touchingSliceAt;var f=this.series,a=f.center[0],c=f.chart.plotWidth,e=f.chart.plotLeft;f=k.alignment;var p=this.shapeArgs.r;b=y(b.crookDistance,1);c="left"===f?a+p+(c+e-a-p)*(1-b):e+(a-p)*b;b=["L",c,k.y];a=!0;if("left"===f?c>k.x||c< +g.x:cg.x)a=!1;k=[["M",k.x,k.y]];a&&k.push(b);k.push(["L",g.x,g.y]);return k}},getConnectorPath:function(){var k=this.labelPosition,g=this.series.options.dataLabels,b=g.connectorShape,f=this.connectorShapes;f[b]&&(b=f[b]);return b.call(this,{x:k.final.x,y:k.final.y,alignment:k.alignment},k.connectorPosition,g)}});""});P(x,"parts/DataLabels.js",[x["parts/Globals.js"],x["parts/Utilities.js"]],function(l,e){var B=e.animObject,t=e.arrayMax,x=e.clamp,H=e.defined,L=e.extend,K=e.fireEvent,E=e.format, +C=e.isArray,J=e.merge,y=e.objectEach,A=e.pick,z=e.relativeLength,q=e.splat,m=e.stableSort;e=l.noop;var u=l.Series,k=l.seriesTypes;l.distribute=function(g,b,f){function a(a,b){return a.target-b.target}var c,k=!0,e=g,q=[];var w=0;var v=e.reducedLen||b;for(c=g.length;c--;)w+=g[c].size;if(w>v){m(g,function(a,b){return(b.rank||0)-(a.rank||0)});for(w=c=0;w<=v;)w+=g[c].size,c++;q=g.splice(c-1,g.length)}m(g,a);for(g=g.map(function(a){return{size:a.size,targets:[a.target],align:A(a.align,.5)}});k;){for(c= +g.length;c--;)k=g[c],w=(Math.min.apply(0,k.targets)+Math.max.apply(0,k.targets))/2,k.pos=x(w-k.size*k.align,0,b-k.size);c=g.length;for(k=!1;c--;)0g[c].pos&&(g[c-1].size+=g[c].size,g[c-1].targets=g[c-1].targets.concat(g[c].targets),g[c-1].align=.5,g[c-1].pos+g[c-1].size>b&&(g[c-1].pos=b-g[c-1].size),g.splice(c,1),k=!0)}e.push.apply(e,q);c=0;g.some(function(a){var g=0;if(a.targets.some(function(){e[c].pos=a.pos+g;if("undefined"!==typeof f&&Math.abs(e[c].pos-e[c].target)>f)return e.slice(0, +c+1).forEach(function(a){delete a.pos}),e.reducedLen=(e.reducedLen||b)-.1*b,e.reducedLen>.1*b&&l.distribute(e,b,f),!0;g+=e[c].size;c++}))return!0});m(e,a)};u.prototype.drawDataLabels=function(){function g(a,d){var b=d.filter;return b?(d=b.operator,a=a[b.property],b=b.value,">"===d&&a>b||"<"===d&&a="===d&&a>=b||"<="===d&&a<=b||"=="===d&&a==b||"==="===d&&a===b?!0:!1):!0}function b(a,d){var b=[],c;if(C(a)&&!C(d))b=a.map(function(a){return J(a,d)});else if(C(d)&&!C(a))b=d.map(function(d){return J(a, +d)});else if(C(a)||C(d))for(c=Math.max(a.length,d.length);c--;)b[c]=J(a[c],d[c]);else b=J(a,d);return b}var f=this,a=f.chart,c=f.options,k=c.dataLabels,e=f.points,l,m=f.hasRendered||0,v=B(c.animation).duration,n=Math.min(v,200),F=!a.renderer.forExport&&A(k.defer,0n||c.stacking?h.contrastColor:"#000000"):delete h.contrastColor,c.cursor&&(m.cursor=c.cursor));var w={r:d.borderRadius|| +0,rotation:v,padding:d.padding,zIndex:1};a.styledMode||(w.fill=d.backgroundColor,w.stroke=d.borderColor,w["stroke-width"]=d.borderWidth);y(w,function(a,d){"undefined"===typeof a&&delete w[d]})}!e||k&&H(l)?k&&H(l)&&(e?w.text=l:(h.dataLabels=h.dataLabels||[],e=h.dataLabels[b]=v?u.text(l,0,-9999,d.useHTML).addClass("highcharts-data-label"):u.label(l,0,-9999,d.shape,null,null,d.useHTML,null,"data-label"),b||(h.dataLabel=e),e.addClass(" highcharts-data-label-color-"+h.colorIndex+" "+(d.className||"")+ +(d.useHTML?" highcharts-tracker":""))),e.options=d,e.attr(w),a.styledMode||e.css(m).shadow(d.shadow),e.added||e.add(D),d.textPath&&!d.useHTML&&(e.setTextPath(h.getDataLabelPath&&h.getDataLabelPath(e)||h.graphic,d.textPath),h.dataLabelPath&&!d.textPath.enabled&&(h.dataLabelPath=h.dataLabelPath.destroy())),f.alignDataLabel(h,e,d,null,r)):(h.dataLabel=h.dataLabel&&h.dataLabel.destroy(),h.dataLabels&&(1===h.dataLabels.length?delete h.dataLabels:delete h.dataLabels[b]),b||delete h.dataLabel,p&&(h.connector= +h.connector.destroy(),h.connectors&&(1===h.connectors.length?delete h.connectors:delete h.connectors[b])))})})}K(this,"afterDrawDataLabels")};u.prototype.alignDataLabel=function(g,b,f,a,c){var k=this,e=this.chart,l=this.isCartesian&&e.inverted,m=this.enabledDataSorting,v=A(g.dlBox&&g.dlBox.centerX,g.plotX,-9999),n=A(g.plotY,-9999),F=b.getBBox(),q=f.rotation,u=f.align,h=e.isInsidePlot(v,Math.round(n),l),d="justify"===A(f.overflow,m?"none":"justify"),G=this.visible&&!1!==g.visible&&(g.series.forceDL|| +m&&!d||h||f.inside&&a&&e.isInsidePlot(v,l?a.x+1:a.y+a.height-1,l));var y=function(a){m&&k.xAxis&&!d&&k.setDataLabelStartPos(g,b,c,h,a)};if(G){var t=e.renderer.fontMetrics(e.styledMode?void 0:f.style.fontSize,b).b;a=L({x:l?this.yAxis.len-n:v,y:Math.round(l?this.xAxis.len-v:n),width:0,height:0},a);L(f,{width:F.width,height:F.height});q?(d=!1,v=e.renderer.rotCorr(t,q),v={x:a.x+f.x+a.width/2+v.x,y:a.y+f.y+{top:0,middle:.5,bottom:1}[f.verticalAlign]*a.height},y(v),b[c?"attr":"animate"](v).attr({align:u}), +y=(q+720)%360,y=180y,"left"===u?v.y-=y?F.height:0:"center"===u?(v.x-=F.width/2,v.y-=F.height/2):"right"===u&&(v.x-=F.width,v.y-=y?0:F.height),b.placed=!0,b.alignAttr=v):(y(a),b.align(f,null,a),v=b.alignAttr);d&&0<=a.height?this.justifyDataLabel(b,f,v,F,a,c):A(f.crop,!0)&&(G=e.isInsidePlot(v.x,v.y)&&e.isInsidePlot(v.x+F.width,v.y+F.height));if(f.shape&&!q)b[c?"attr":"animate"]({anchorX:l?e.plotWidth-g.plotY:g.plotX,anchorY:l?e.plotHeight-g.plotX:g.plotY})}c&&m&&(b.placed=!1);G||m&&!d||(b.hide(!0), +b.placed=!1)};u.prototype.setDataLabelStartPos=function(g,b,f,a,c){var k=this.chart,e=k.inverted,l=this.xAxis,m=l.reversed,v=e?b.height/2:b.width/2;g=(g=g.pointWidth)?g/2:0;l=e?c.x:m?-v-g:l.width-v+g;c=e?m?this.yAxis.height-v+g:-v-g:c.y;b.startXPos=l;b.startYPos=c;a?"hidden"===b.visibility&&(b.show(),b.attr({opacity:0}).animate({opacity:1})):b.attr({opacity:1}).animate({opacity:0},void 0,b.hide);k.hasRendered&&(f&&b.attr({x:b.startXPos,y:b.startYPos}),b.placed=!0)};u.prototype.justifyDataLabel=function(g, +b,f,a,c,k){var e=this.chart,r=b.align,l=b.verticalAlign,m=g.box?0:g.padding||0;var n=f.x+m;if(0>n){"right"===r?(b.align="left",b.inside=!0):b.x=-n;var F=!0}n=f.x+a.width-m;n>e.plotWidth&&("left"===r?(b.align="right",b.inside=!0):b.x=e.plotWidth-n,F=!0);n=f.y+m;0>n&&("bottom"===l?(b.verticalAlign="top",b.inside=!0):b.y=-n,F=!0);n=f.y+a.height-m;n>e.plotHeight&&("top"===l?(b.verticalAlign="bottom",b.inside=!0):b.y=e.plotHeight-n,F=!0);F&&(g.placed=!k,g.align(b,null,c));return F};k.pie&&(k.pie.prototype.dataLabelPositioners= +{radialDistributionY:function(g){return g.top+g.distributeBox.pos},radialDistributionX:function(g,b,f,a){return g.getX(fb.bottom-2?a:f,b.half,b)},justify:function(g,b,f){return f[0]+(g.half?-1:1)*(b+g.labelDistance)},alignToPlotEdges:function(g,b,f,a){g=g.getBBox().width;return b?g+a:f-g-a},alignToConnectors:function(g,b,f,a){var c=0,k;g.forEach(function(a){k=a.dataLabel.getBBox().width;k>c&&(c=k)});return b?c+a:f-c-a}},k.pie.prototype.drawDataLabels=function(){var g=this,b=g.data,f,a= +g.chart,c=g.options.dataLabels||{},k=c.connectorPadding,e,m=a.plotWidth,w=a.plotHeight,v=a.plotLeft,n=Math.round(a.chartWidth/3),F,q=g.center,D=q[2]/2,h=q[1],d,y,z,C,E=[[],[]],B,x,K,L,N=[0,0,0,0],P=g.dataLabelPositioners,X;g.visible&&(c.enabled||g._hasPointLabels)&&(b.forEach(function(a){a.dataLabel&&a.visible&&a.dataLabel.shortened&&(a.dataLabel.attr({width:"auto"}).css({width:"auto",textOverflow:"clip"}),a.dataLabel.shortened=!1)}),u.prototype.drawDataLabels.apply(g),b.forEach(function(a){a.dataLabel&& +(a.visible?(E[a.half].push(a),a.dataLabel._pos=null,!H(c.style.width)&&!H(a.options.dataLabels&&a.options.dataLabels.style&&a.options.dataLabels.style.width)&&a.dataLabel.getBBox().width>n&&(a.dataLabel.css({width:Math.round(.7*n)+"px"}),a.dataLabel.shortened=!0)):(a.dataLabel=a.dataLabel.destroy(),a.dataLabels&&1===a.dataLabels.length&&delete a.dataLabels))}),E.forEach(function(b,e){var n=b.length,p=[],r;if(n){g.sortByAngle(b,e-.5);if(0m-k&&0===e&&(F=Math.round(B+y-m+k),N[1]=Math.max(F,N[1])),0>x-C/2?N[0]=Math.max(Math.round(-x+C/2),N[0]):x+C/2>w&&(N[2]=Math.max(Math.round(x+C/2-w),N[2])),d.sideOverflow=F)}}}),0===t(N)||this.verifyDataLabelOverflow(N))&&(this.placeDataLabels(),this.points.forEach(function(b){X=J(c,b.options.dataLabels);if(e=A(X.connectorWidth,1)){var h;F=b.connector;if((d=b.dataLabel)&&d._pos&&b.visible&&0A(this.translatedThreshold,e.yAxis.len)),v= +A(f.inside,!!this.options.stacking);l&&(a=J(l),0>a.y&&(a.height+=a.y,a.y=0),l=a.y+a.height-e.yAxis.len,0u.x+u.width||k.x+k.widthu.y+u.height||k.y+k.height=d&&k<=e||n||!K(k))p=!0;f[n?"zoomX":"zoomY"]&&p&&(c=h.zoom(a.min,a.max),h.displayBtn&&(g=!0))});var e=b.resetZoomButton;g&&!e? +b.showResetZoom():!g&&z(e)&&(b.resetZoomButton=e.destroy());c&&b.redraw(u(b.options.chart.animation,a&&a.animation,100>b.pointCount))},pan:function(a,b){var c=this,f=c.hoverPoints,g=c.options.chart,k=c.options.mapNavigation&&c.options.mapNavigation.enabled,e;b="object"===typeof b?b:{enabled:b,type:"x"};g&&g.panning&&(g.panning=b);var p=b.type;C(this,"pan",{originalEvent:a},function(){f&&f.forEach(function(a){a.setState()});var b=[1];"xy"===p?b=[1,0]:"y"===p&&(b=[0]);b.forEach(function(d){var b=c[d? +"xAxis":"yAxis"][0],h=b.options,f=b.horiz,g=a[f?"chartX":"chartY"];f=f?"mouseDownX":"mouseDownY";var n=c[f],r=(b.pointRange||0)/2,m=b.reversed&&!c.inverted||!b.reversed&&c.inverted?-1:1,v=b.getExtremes(),w=b.toValue(n-g,!0)+r*m;m=b.toValue(n+b.len-g,!0)-r*m;var F=m=m&&w<=r)b.setExtremes(n, +w,!1,!1,{trigger:"pan"}),c.resetZoomButton||k||!p.match("y")||(c.showResetZoom(),b.displayBtn=!1),e=!0;c[f]=g}});e&&c.redraw(!1);L(c.container,{cursor:"move"})})}});E(B.prototype,{select:function(a,b){var c=this,f=c.series,g=f.chart;this.selectedStaging=a=u(a,!c.selected);c.firePointEvent(a?"select":"unselect",{accumulate:b},function(){c.selected=c.options.selected=a;f.options.data[f.data.indexOf(c)]=c.options;c.setState(a&&"select");b||g.getSelectedPoints().forEach(function(a){var b=a.series;a.selected&& +a!==c&&(a.selected=a.options.selected=!1,b.options.data[b.data.indexOf(a)]=a.options,a.setState(g.hoverPoints&&b.options.inactiveOtherPoints?"inactive":""),a.firePointEvent("unselect"))})});delete this.selectedStaging},onMouseOver:function(a){var b=this.series.chart,c=b.pointer;a=a?c.normalize(a):c.getChartCoordinatesFromPoint(this,b.inverted);c.runPointActions(a,this)},onMouseOut:function(){var a=this.series.chart;this.firePointEvent("mouseOut");this.series.options.inactiveOtherPoints||(a.hoverPoints|| +[]).forEach(function(a){a.setState()});a.hoverPoints=a.hoverPoint=null},importEvents:function(){if(!this.hasImportedEvents){var a=this,b=q(a.series.options.point,a.options).events;a.events=b;m(b,function(b,c){y(b)&&x(a,c,b)});this.hasImportedEvents=!0}},setState:function(a,b){var c=this.series,f=this.state,k=c.options.states[a||"normal"]||{},e=g[c.type].marker&&c.options.marker,p=e&&!1===e.enabled,l=e&&e.states&&e.states[a||"normal"]||{},h=!1===l.enabled,d=c.stateMarkerGraphic,r=this.marker||{},m= +c.chart,q=c.halo,y,t=e&&c.markerAttribs;a=a||"";if(!(a===this.state&&!b||this.selected&&"select"!==a||!1===k.enabled||a&&(h||p&&!1===l.enabled)||a&&r.states&&r.states[a]&&!1===r.states[a].enabled)){this.state=a;t&&(y=c.markerAttribs(this,a));if(this.graphic){f&&this.graphic.removeClass("highcharts-point-"+f);a&&this.graphic.addClass("highcharts-point-"+a);if(!m.styledMode){var I=c.pointAttribs(this,a);var z=u(m.options.chart.animation,k.animation);c.options.inactiveOtherPoints&&I.opacity&&((this.dataLabels|| +[]).forEach(function(a){a&&a.animate({opacity:I.opacity},z)}),this.connector&&this.connector.animate({opacity:I.opacity},z));this.graphic.animate(I,z)}y&&this.graphic.animate(y,u(m.options.chart.animation,l.animation,e.animation));d&&d.hide()}else{if(a&&l){f=r.symbol||c.symbol;d&&d.currentSymbol!==f&&(d=d.destroy());if(y)if(d)d[b?"animate":"attr"]({x:y.x,y:y.y});else f&&(c.stateMarkerGraphic=d=m.renderer.symbol(f,y.x,y.y,y.width,y.height).add(c.markerGroup),d.currentSymbol=f);!m.styledMode&&d&&d.attr(c.pointAttribs(this, +a))}d&&(d[a&&this.isInside?"show":"hide"](),d.element.point=this)}a=k.halo;k=(d=this.graphic||d)&&d.visibility||"inherit";a&&a.size&&d&&"hidden"!==k&&!this.isCluster?(q||(c.halo=q=m.renderer.path().add(d.parentGroup)),q.show()[b?"animate":"attr"]({d:this.haloPath(a.size)}),q.attr({"class":"highcharts-halo highcharts-color-"+u(this.colorIndex,c.colorIndex)+(this.className?" "+this.className:""),visibility:k,zIndex:-1}),q.point=this,m.styledMode||q.attr(E({fill:this.color||c.color,"fill-opacity":a.opacity}, +a.attributes))):q&&q.point&&q.point.haloPath&&q.animate({d:q.point.haloPath(0)},null,q.hide);C(this,"afterSetState")}},haloPath:function(a){return this.series.chart.renderer.symbols.circle(Math.floor(this.plotX)-a,this.plotY-a,2*a,2*a)}});E(f.prototype,{onMouseOver:function(){var a=this.chart,b=a.hoverSeries;a.pointer.setHoverChartIndex();if(b&&b!==this)b.onMouseOut();this.options.events.mouseOver&&C(this,"mouseOver");this.setState("hover");a.hoverSeries=this},onMouseOut:function(){var a=this.options, +b=this.chart,c=b.tooltip,f=b.hoverPoint;b.hoverSeries=null;if(f)f.onMouseOut();this&&a.events.mouseOut&&C(this,"mouseOut");!c||this.stickyTracking||c.shared&&!this.noSharedTooltip||c.hide();b.series.forEach(function(a){a.setState("",!0)})},setState:function(a,b){var c=this,f=c.options,g=c.graph,k=f.inactiveOtherPoints,e=f.states,l=f.lineWidth,h=f.opacity,d=u(e[a||"normal"]&&e[a||"normal"].animation,c.chart.options.chart.animation);f=0;a=a||"";if(c.state!==a&&([c.group,c.markerGroup,c.dataLabelsGroup].forEach(function(d){d&& +(c.state&&d.removeClass("highcharts-series-"+c.state),a&&d.addClass("highcharts-series-"+a))}),c.state=a,!c.chart.styledMode)){if(e[a]&&!1===e[a].enabled)return;a&&(l=e[a].lineWidth||l+(e[a].lineWidthPlus||0),h=u(e[a].opacity,h));if(g&&!g.dashstyle)for(e={"stroke-width":l},g.animate(e,d);c["zone-graph-"+f];)c["zone-graph-"+f].attr(e),f+=1;k||[c.group,c.markerGroup,c.dataLabelsGroup,c.labelBySeries].forEach(function(a){a&&a.animate({opacity:h},d)})}b&&k&&c.points&&c.setAllPointsToState(a)},setAllPointsToState:function(a){this.points.forEach(function(b){b.setState&& +b.setState(a)})},setVisible:function(a,b){var c=this,f=c.chart,g=c.legendItem,k=f.options.chart.ignoreHiddenSeries,e=c.visible;var l=(c.visible=a=c.options.visible=c.userOptions.visible="undefined"===typeof a?!e:a)?"show":"hide";["group","dataLabelsGroup","markerGroup","tracker","tt"].forEach(function(a){if(c[a])c[a][l]()});if(f.hoverSeries===c||(f.hoverPoint&&f.hoverPoint.series)===c)c.onMouseOut();g&&f.legend.colorizeItem(c,a);c.isDirty=!0;c.options.stacking&&f.series.forEach(function(a){a.options.stacking&& +a.visible&&(a.isDirty=!0)});c.linkedSeries.forEach(function(b){b.setVisible(a,!1)});k&&(f.isDirtyBox=!0);C(c,l);!1!==b&&f.redraw()},show:function(){this.setVisible(!0)},hide:function(){this.setVisible(!1)},select:function(a){this.selected=a=this.options.selected="undefined"===typeof a?!this.selected:a;this.checkbox&&(this.checkbox.checked=a);C(this,a?"select":"unselect")},drawTracker:r.drawTrackerGraph})});P(x,"parts/Responsive.js",[x["parts/Globals.js"],x["parts/Utilities.js"]],function(l,e){var x= +e.find,t=e.isArray,N=e.isObject,H=e.merge,L=e.objectEach,K=e.pick,E=e.splat,C=e.uniqueKey;l=l.Chart;l.prototype.setResponsive=function(e,l){var y=this.options.responsive,t=[],q=this.currentResponsive;!l&&y&&y.rules&&y.rules.forEach(function(e){"undefined"===typeof e._id&&(e._id=C());this.matchResponsiveRule(e,t)},this);l=H.apply(0,t.map(function(e){return x(y.rules,function(l){return l._id===e}).chartOptions}));l.isResponsiveOptions=!0;t=t.toString()||void 0;t!==(q&&q.ruleIds)&&(q&&this.update(q.undoOptions, +e,!0),t?(q=this.currentOptions(l),q.isResponsiveOptions=!0,this.currentResponsive={ruleIds:t,mergedOptions:l,undoOptions:q},this.update(l,e,!0)):this.currentResponsive=void 0)};l.prototype.matchResponsiveRule=function(e,l){var y=e.condition;(y.callback||function(){return this.chartWidth<=K(y.maxWidth,Number.MAX_VALUE)&&this.chartHeight<=K(y.maxHeight,Number.MAX_VALUE)&&this.chartWidth>=K(y.minWidth,0)&&this.chartHeight>=K(y.minHeight,0)}).call(this)&&l.push(e._id)};l.prototype.currentOptions=function(e){function l(e, +m,u,k){var g;L(e,function(b,f){if(!k&&-1k?g:k;A=A+1+b.descendants;z=Math.max(b.height+1,z);return b});C&&(C.start=t(C.start,u),C.end=t(C.end,k));e(B,{children:m,descendants:A,height:z}); +"function"===typeof q&&q(B,y);return B};return{getListOfParents:N,getNode:H,getTree:function(e,l){var t=e.map(function(e){return e.id});e=N(e,t);return H("",null,1,null,e,l)}}});P(x,"parts-gantt/TreeGridTick.js",[x["parts/Utilities.js"]],function(l){var e=l.addEvent,x=l.defined,t=l.isObject,N=l.isNumber,H=l.pick,L=l.wrap,K;(function(l){function C(){this.treeGrid||(this.treeGrid=new q(this))}function E(e,l){e=e.treeGrid;var k=!e.labelIcon,g=l.renderer,b=l.xy,f=l.options,a=f.width,c=f.height,r=b.x- +a/2-f.padding;b=b.y-c/2;var p=l.collapsed?90:180,m=l.show&&N(b),q=e.labelIcon;q||(e.labelIcon=q=g.path(g.symbols[f.type](f.x,f.y,a,c)).addClass("highcharts-label-icon").add(l.group));m||q.attr({y:-9999});g.styledMode||q.attr({"stroke-width":1,fill:H(l.color,"#666666")}).css({cursor:"pointer",stroke:f.lineColor,strokeWidth:f.lineWidth});q[k?"attr":"animate"]({translateX:r,translateY:b,rotation:p})}function y(e,l,k,g,b,f,a,c,r){var p=H(this.options&&this.options.labels,f);f=this.pos;var m=this.axis, +q="treegrid"===m.options.type;e=e.apply(this,[l,k,g,b,p,a,c,r]);q&&(l=p&&t(p.symbol,!0)?p.symbol:{},p=p&&N(p.indentation)?p.indentation:0,f=(f=(m=m.treeGrid.mapOfPosToGridNode)&&m[f])&&f.depth||1,e.x+=l.width+2*l.padding+(f-1)*p);return e}function A(l){var m=this,k=m.pos,g=m.axis,b=m.label,f=g.treeGrid.mapOfPosToGridNode,a=g.options,c=H(m.options&&m.options.labels,a&&a.labels),r=c&&t(c.symbol,!0)?c.symbol:{},p=(f=f&&f[k])&&f.depth;a="treegrid"===a.type;var q=-1k&&!b.startOnTick&&(c[0]=k),e> +l&&e-m=q?(l-q)%m:m-(q-l)%m;return e.inclusive?l<=k:l=l)break;else u.to=l)break;else if(e.isInBreak(k,l)){m-=l-k.from;break}}return m};e.prototype.findBreakAt=function(e,l){return H(l,function(l){return l.fromk;)n-=c;for(;nf.to||a>f.from&&lf.from&&lf.from&&l>f.to&&le&&k>=this.basePointRange&&(e=k),a=void 0;b--;)a&&!1!==a.visible||(a=g[b+1]),k=g[b],!1!==a.visible&& +!1!==k.visible&&(a.x-k.x>e&&(a=(k.x+a.x)/2,g.splice(b+1,0,{isNull:!0,x:a}),f.stacking&&this.options.stacking&&(a=f.stacking.stacks[this.stackKey][a]=new t(f,f.options.stackLabels,!1,a,this.stack),a.total=0)),a=k);return this.getGraphPath(g)};B(e,"init",function(){this.brokenAxis||(this.brokenAxis=new y(this))});B(e,"afterInit",function(){"undefined"!==typeof this.brokenAxis&&this.brokenAxis.setBreaks(this.options.breaks,!1)});B(e,"afterSetTickPositions",function(){var e=this.brokenAxis;if(e&&e.hasBreaks){var k= +this.tickPositions,g=this.tickPositions.info,b=[],f;for(f=0;f=b&&(c-=.5);return{from:c,to:a,showPoints:!1}}function g(a,b,c){var f=[],g=[],e={},h={},d=-1,k="boolean"===typeof b?b:!1;a=x.getTree(a,{after:function(a){a=h[a.pos];var b=0,d=0;a.children.forEach(function(a){d+=(a.descendants||0)+1;b=Math.max((a.height||0)+1,b)});a.descendants=d;a.height=b;a.collapsed&&g.push(a)},before:function(a){var b=J(a.data,!0)?a.data:{},c=y(b.name)? +b.name:"",g=e[a.parent];g=J(g,!0)?h[g.pos]:null;var l=function(a){return a.name===c},n;k&&J(g,!0)&&(n=K(g.children,l))?(l=n.pos,n.nodes.push(a)):l=d++;h[l]||(h[l]=n={depth:g?g.depth+1:0,name:c,nodes:[a],children:[],pos:l},-1!==l&&f.push(c),J(g,!0)&&g.children.push(n));y(a.id)&&(e[a.id]=a);n&&!0===b.collapsed&&(n.collapsed=!0);a.pos=l}});h=function(a,b){var d=function(a,c,h){var f=c+(-1===c?0:b-1),g=(f-c)/2,e=c+g;a.nodes.forEach(function(a){var b=a.data;J(b,!0)&&(b.y=c+(b.seriesIndex||0),delete b.seriesIndex); +a.pos=e});h[e]=a;a.pos=e;a.tickmarkOffset=g+.5;a.collapseStart=f+.5;a.children.forEach(function(a){d(a,f+1,h);f=(a.collapseEnd||0)-.5});a.collapseEnd=f+.5;return h};return d(a["-1"],-1,{})}(h,c);return{categories:f,mapOfIdToNode:e,mapOfPosToGridNode:h,collapsedNodes:g,tree:a}}function b(a){a.target.axes.filter(function(a){return"treegrid"===a.options.type}).forEach(function(b){var c=b.options||{},f=c.labels,e=c.uniqueNames,k=0;if(!b.treeGrid.mapOfPosToGridNode||b.series.some(function(a){return!a.hasRendered|| +a.isDirtyData||a.isDirty}))c=b.series.reduce(function(a,b){b.visible&&((b.options.data||[]).forEach(function(b){J(b,!0)&&(b.seriesIndex=k,a.push(b))}),!0===e&&k++);return a},[]),c=g(c,e||!1,!0===e?k:1),b.categories=c.categories,b.treeGrid.mapOfPosToGridNode=c.mapOfPosToGridNode,b.hasNames=!0,b.treeGrid.tree=c.tree,b.series.forEach(function(a){var b=(a.options.data||[]).map(function(a){return J(a,!0)?A(a):a});a.visible&&a.setData(b,!1)}),b.treeGrid.mapOptionsToLevel=N.getLevelOptions({defaults:f,from:1, +levels:f&&f.levels,to:b.treeGrid.tree&&b.treeGrid.tree.height}),"beforeRender"===a.type&&(b.treeGrid.collapsedNodes=c.collapsedNodes)})}function f(a,b){var c=this.treeGrid.mapOptionsToLevel||{},f=this.ticks,g=f[b],k;if("treegrid"===this.options.type&&this.treeGrid.mapOfPosToGridNode){var h=this.treeGrid.mapOfPosToGridNode[b];(c=c[h.depth])&&(k={labels:c});g?(g.parameters.category=h.name,g.options=k,g.addLabel()):f[b]=new e(this,b,void 0,void 0,{category:h.name,tickmarkOffset:h.tickmarkOffset,options:k})}else a.apply(this, +Array.prototype.slice.call(arguments,1))}function a(a){var b=this.options;b=(b=b&&b.labels)&&C(b.indentation)?b.indentation:0;var c=a.apply(this,Array.prototype.slice.call(arguments,1));if("treegrid"===this.options.type&&this.treeGrid.mapOfPosToGridNode){var f=this.treeGrid.mapOfPosToGridNode[-1].height||0;c.width+=b*(f-1)}return c}function c(a,c,f){var e=this,k="treegrid"===f.type;e.treeGrid||(e.treeGrid=new u(e));k&&(B(c,"beforeRender",b),B(c,"beforeRedraw",b),B(c,"addSeries",function(a){a.options.data&& +(a=g(a.options.data,f.uniqueNames||!1,1),e.treeGrid.collapsedNodes=(e.treeGrid.collapsedNodes||[]).concat(a.collapsedNodes))}),B(e,"foundExtremes",function(){e.treeGrid.collapsedNodes&&e.treeGrid.collapsedNodes.forEach(function(a){var b=e.treeGrid.collapse(a);e.brokenAxis&&(e.brokenAxis.setBreaks(b,!1),e.treeGrid.collapsedNodes&&(e.treeGrid.collapsedNodes=e.treeGrid.collapsedNodes.filter(function(b){return a.collapseStart!==b.collapseStart||a.collapseEnd!==b.collapseEnd})))})}),f=A({grid:{enabled:!0}, +labels:{align:"left",levels:[{level:void 0},{level:1,style:{fontWeight:"bold"}}],symbol:{type:"triangle",x:-5,y:-5,height:10,width:10,padding:5}},uniqueNames:!1},f,{reversed:!0,grid:{columns:void 0}}));a.apply(e,[c,f]);k&&(e.hasNames=!0,e.options.showLastLabel=!0)}function m(a){var b=this.options;"treegrid"===b.type?(this.min=z(this.userMin,b.min,this.dataMin),this.max=z(this.userMax,b.max,this.dataMax),E(this,"foundExtremes"),this.setAxisTranslation(!0),this.tickmarkOffset=.5,this.tickInterval=1, +this.tickPositions=this.treeGrid.mapOfPosToGridNode?this.treeGrid.getTickPositions():[]):a.apply(this,Array.prototype.slice.call(arguments,1))}var p=!1;l.compose=function(b){p||(q(b.prototype,"generateTick",f),q(b.prototype,"getMaxLabelDimensions",a),q(b.prototype,"init",c),q(b.prototype,"setTickInterval",m),t.compose(e),p=!0)};var u=function(){function a(a){this.axis=a}a.prototype.collapse=function(a){var b=this.axis,c=b.options.breaks||[];a=k(a,b.max);c.push(a);return c};a.prototype.expand=function(a){var b= +this.axis,c=b.options.breaks||[],f=k(a,b.max);return c.reduce(function(a,b){b.to===f.to&&b.from===f.from||a.push(b);return a},[])};a.prototype.getTickPositions=function(){var a=this.axis;return Object.keys(a.treeGrid.mapOfPosToGridNode||{}).reduce(function(b,c){c=+c;!(a.min<=c&&a.max>=c)||a.brokenAxis&&a.brokenAxis.isInAnyBreak(c)||b.push(c);return b},[])};a.prototype.isCollapsed=function(a){var b=this.axis,c=b.options.breaks||[],f=k(a,b.max);return c.some(function(a){return a.from===f.from&&a.to=== +f.to})};a.prototype.toggleCollapse=function(a){return this.isCollapsed(a)?this.expand(a):this.collapse(a)};return a}();l.Additions=u})(m||(m={}));l.prototype.utils={getNode:x.getNode};m.compose(l);return m});P(x,"parts-gantt/PathfinderAlgorithms.js",[x["parts/Utilities.js"]],function(l){function e(e,l,t){t=t||0;var y=e.length-1;l-=1e-7;for(var q,m;t<=y;)if(q=y+t>>1,m=l-e[q].xMin,0m)y=q-1;else return q;return 0= +t.x)z=l[y],z=t.x<=z.xMax&&t.x>=z.xMin&&t.y<=z.yMax&&t.y>=z.yMin;if(z)return y}return-1}function t(e){var l=[];if(e.length){l.push(["M",e[0].start.x,e[0].start.y]);for(var t=0;tC(b[f]-a[f+"Max"]);return y(b,f,a,f+(c?"Max":"Min"),c?1:-1)}var m=[],u=L(A.startDirectionX,C(l.x-e.x)>C(l.y-e.y))?"x":"y",k=A.chartObstacles,g=x(k,e);A=x(k,l);if(-1=e[u]===A[u]>=f[u]&&(u="y"===u?"x":"y",l=e[u]d?K(e(w,k.x),w.length-1):0;w[f]&&(0d&&w[f].xMax>=g.x);){if(w[f].xMin<=k.x&&w[f].xMax>=g.x&&w[f].yMin<= +n.y&&w[f].yMax>=l.y)return c?{y:a.y,x:a.x=h[e+"Max"];h=a[e+"Min"]<=h[e+"Min"];var n=a[e+"Max"]>=g[e+"Max"];g=a[e+"Min"]<=g[e+"Min"];var m=C(a[e+"Min"]-b[e]),p=C(a[e+"Max"]-b[e]);c=10>C(m-p)?b[e]C(y.y-l.y)),g=k?"x":"y",b=[],f=!1,a=A.obstacleMetrics,c=K(l.x,y.x)-a.maxWidth-10,r=E(l.x,y.x)+a.maxWidth+10,p=K(l.y,y.y)-a.maxHeight-10,I=E(l.y,y.y)+a.maxHeight+10,w=A.chartObstacles;var v=e(w,c);a=e(w,r);w=w.slice(v,a+1);if(-1<(a=x(w,y))){var n=u(w[a],y,l);b.push({end:y,start:n});y=n}for(;-1<(a=x(w,y));)v=0>y[g]-l[g], +n={x:y.x,y:y.y},n[g]=w[a][v?g+"Max":g+"Min"]+(v?1:-1),b.push({end:y,start:n}),y=n;l=m(l,y,k);l=l.concat(b.reverse());return{path:t(l),obstacles:l}},{requiresObstacles:!0})}});P(x,"parts-gantt/ArrowSymbols.js",[x["parts/Globals.js"]],function(l){l.SVGRenderer.prototype.symbols.arrow=function(e,l,t,x){return[["M",e,l+x/2],["L",e+t,l],["L",e,l+x/2],["L",e+t,l+x]]};l.SVGRenderer.prototype.symbols["arrow-half"]=function(e,x,t,N){return l.SVGRenderer.prototype.symbols.arrow(e,x,t/2,N)};l.SVGRenderer.prototype.symbols["triangle-left"]= +function(e,l,t,x){return[["M",e+t,l],["L",e,l+x/2],["L",e+t,l+x],["Z"]]};l.SVGRenderer.prototype.symbols["arrow-filled"]=l.SVGRenderer.prototype.symbols["triangle-left"];l.SVGRenderer.prototype.symbols["triangle-left-half"]=function(e,x,t,N){return l.SVGRenderer.prototype.symbols["triangle-left"](e,x,t/2,N)};l.SVGRenderer.prototype.symbols["arrow-filled-half"]=l.SVGRenderer.prototype.symbols["triangle-left-half"]});P(x,"parts-gantt/Pathfinder.js",[x["parts/Globals.js"],x["parts/Point.js"],x["parts/Utilities.js"], +x["parts-gantt/PathfinderAlgorithms.js"]],function(l,e,x,t){function B(b){var a=b.shapeArgs;return a?{xMin:a.x,xMax:a.x+a.width,yMin:a.y,yMax:a.y+a.height}:(a=b.graphic&&b.graphic.getBBox())?{xMin:b.plotX-a.width/2,xMax:b.plotX+a.width/2,yMin:b.plotY-a.height/2,yMax:b.plotY+a.height/2}:null}function H(f){for(var a=f.length,c=0,e,k,l=[],q=function(a,c,f){f=m(f,10);var e=a.yMax+f>c.yMin-f&&a.yMin-fc.xMin-f&&a.xMin-fc.xMax?a.xMin-c.xMax:c.xMin-a.xMax:Infinity, +d=g?a.yMin>c.yMax?a.yMin-c.yMax:c.yMin-a.yMax:Infinity;return g&&e?f?q(a,c,Math.floor(f/2)):Infinity:b(h,d)};ck&&l.push(k);l.push(80);return g(Math.floor(l.sort(function(a,b){return a-b})[Math.floor(l.length/10)]/2-1),1)}function L(b,a,c){this.init(b,a,c)}function K(b){this.init(b)}function E(b){if(b.options.pathfinder||b.series.reduce(function(a,b){b.options&&z(!0,b.options.connectors=b.options.connectors||{},b.options.pathfinder);return a||b.options&&b.options.pathfinder}, +!1))z(!0,b.options.connectors=b.options.connectors||{},b.options.pathfinder),y('WARNING: Pathfinder options have been renamed. Use "chart.connectors" or "series.connectors" instead.')}"";var C=x.addEvent,J=x.defined,y=x.error,A=x.extend,z=x.merge,q=x.objectEach,m=x.pick,u=x.splat,k=l.deg2rad,g=Math.max,b=Math.min;A(l.defaultOptions,{connectors:{type:"straight",lineWidth:1,marker:{enabled:!1,align:"center",verticalAlign:"middle",inside:!1,lineWidth:1},startMarker:{symbol:"diamond"},endMarker:{symbol:"arrow-filled"}}}); +L.prototype={init:function(b,a,c){this.fromPoint=b;this.toPoint=a;this.options=c;this.chart=b.series.chart;this.pathfinder=this.chart.pathfinder},renderPath:function(b,a,c){var f=this.chart,e=f.styledMode,g=f.pathfinder,k=!f.options.chart.forExport&&!1!==c,l=this.graphics&&this.graphics.path;g.group||(g.group=f.renderer.g().addClass("highcharts-pathfinder-group").attr({zIndex:-1}).add(f.seriesGroup));g.group.translate(f.plotLeft,f.plotTop);l&&l.renderer||(l=f.renderer.path().add(g.group),e||l.attr({opacity:0})); +l.attr(a);b={d:b};e||(b.opacity=1);l[k?"animate":"attr"](b,c);this.graphics=this.graphics||{};this.graphics.path=l},addMarker:function(b,a,c){var f=this.fromPoint.series.chart,e=f.pathfinder;f=f.renderer;var g="start"===b?this.fromPoint:this.toPoint,l=g.getPathfinderAnchorPoint(a);if(a.enabled&&((c="start"===b?c[1]:c[c.length-2])&&"M"===c[0]||"L"===c[0])){c={x:c[1],y:c[2]};c=g.getRadiansToVector(c,l);l=g.getMarkerVector(c,a.radius,l);c=-c/k;if(a.width&&a.height){var m=a.width;var n=a.height}else m= +n=2*a.radius;this.graphics=this.graphics||{};l={x:l.x-m/2,y:l.y-n/2,width:m,height:n,rotation:c,rotationOriginX:l.x,rotationOriginY:l.y};this.graphics[b]?this.graphics[b].animate(l):(this.graphics[b]=f.symbol(a.symbol).addClass("highcharts-point-connecting-path-"+b+"-marker").attr(l).add(e.group),f.styledMode||this.graphics[b].attr({fill:a.color||this.fromPoint.color,stroke:a.lineColor,"stroke-width":a.lineWidth,opacity:0}).animate({opacity:1},g.series.options.animation))}},getPath:function(b){var a= +this.pathfinder,c=this.chart,f=a.algorithms[b.type],e=a.chartObstacles;if("function"!==typeof f)y('"'+b.type+'" is not a Pathfinder algorithm.');else return f.requiresObstacles&&!e&&(e=a.chartObstacles=a.getChartObstacles(b),c.options.connectors.algorithmMargin=b.algorithmMargin,a.chartObstacleMetrics=a.getObstacleMetrics(e)),f(this.fromPoint.getPathfinderAnchorPoint(b.startMarker),this.toPoint.getPathfinderAnchorPoint(b.endMarker),z({chartObstacles:e,lineObstacles:a.lineObstacles||[],obstacleMetrics:a.chartObstacleMetrics, +hardBounds:{xMin:0,xMax:c.plotWidth,yMin:0,yMax:c.plotHeight},obstacleOptions:{margin:b.algorithmMargin},startDirectionX:a.getAlgorithmStartDirection(b.startMarker)},b))},render:function(){var f=this.fromPoint,a=f.series,c=a.chart,e=c.pathfinder,k=z(c.options.connectors,a.options.connectors,f.options.connectors,this.options),l={};c.styledMode||(l.stroke=k.lineColor||f.color,l["stroke-width"]=k.lineWidth,k.dashStyle&&(l.dashstyle=k.dashStyle));l["class"]="highcharts-point-connecting-path highcharts-color-"+ +f.colorIndex;k=z(l,k);J(k.marker.radius)||(k.marker.radius=b(g(Math.ceil((k.algorithmMargin||8)/2)-1,1),5));f=this.getPath(k);c=f.path;f.obstacles&&(e.lineObstacles=e.lineObstacles||[],e.lineObstacles=e.lineObstacles.concat(f.obstacles));this.renderPath(c,l,a.options.animation);this.addMarker("start",z(k.marker,k.startMarker),c);this.addMarker("end",z(k.marker,k.endMarker),c)},destroy:function(){this.graphics&&(q(this.graphics,function(b){b.destroy()}),delete this.graphics)}};K.prototype={algorithms:t, +init:function(b){this.chart=b;this.connections=[];C(b,"redraw",function(){this.pathfinder.update()})},update:function(b){var a=this.chart,c=this,f=c.connections;c.connections=[];a.series.forEach(function(b){b.visible&&!b.options.isInternal&&b.points.forEach(function(b){var f,h=b.options&&b.options.connect&&u(b.options.connect);b.visible&&!1!==b.isInside&&h&&h.forEach(function(d){f=a.get("string"===typeof d?d:d.to);f instanceof e&&f.series.visible&&f.visible&&!1!==f.isInside&&c.connections.push(new L(b, +f,"string"===typeof d?{}:d))})})});for(var g=0,k,l,m=f.length,n=c.connections.length;gMath.PI;)b-=f;f=Math.tan(b);b>-l&&b<=l?(y=-1,n=!0):b>l&&b<=Math.PI-l?y=-1:b>Math.PI-l||b<=-(Math.PI-l)?(t=-1,n=!0):t=-1;n?(u+=t*g,h+=y*g*f):(u+=k/(2*f)*t,h+=y*m);c.x!==q&&(u=c.x);c.y!==e&&(h=c.y);d.x=u+a*Math.cos(b);d.y=h-a*Math.sin(b);return d}});l.Chart.prototype.callbacks.push(function(b){!1!== +b.options.connectors.enabled&&(E(b),this.pathfinder=new K(this),this.pathfinder.update(!0))})});P(x,"modules/xrange.src.js",[x["parts/Globals.js"],x["parts/Color.js"],x["parts/Point.js"],x["parts/Utilities.js"]],function(l,e,x,t){var B=e.parse;e=t.addEvent;var H=t.clamp,L=t.correctFloat,K=t.defined,E=t.find,C=t.isNumber,J=t.isObject,y=t.merge,A=t.pick;t=t.seriesType;var z=l.seriesTypes.column,q=l.seriesTypes,m=l.Axis,u=l.Series;t("xrange","column",{colorByPoint:!0,dataLabels:{formatter:function(){var e= +this.point.partialFill;J(e)&&(e=e.amount);if(C(e)&&0{point.x} - {point.x2}

',pointFormat:'\u25cf {series.name}: {point.yCategory}
'},borderRadius:3,pointRange:0},{type:"xrange",parallelArrays:["x","x2","y"],requireSorting:!1,animate:q.line.prototype.animate,cropShoulder:1,getExtremesFromAll:!0,autoIncrement:l.noop,buildKDTree:l.noop, +init:function(){q.column.prototype.init.apply(this,arguments);this.options.stacking=void 0},getColumnMetrics:function(){function e(){g.series.forEach(function(b){var a=b.xAxis;b.xAxis=b.yAxis;b.yAxis=a})}var g=this.chart;e();var b=z.prototype.getColumnMetrics.call(this);e();return b},cropData:function(e,g,b,f){g=u.prototype.cropData.call(this,this.x2Data,g,b,f);g.xData=e.slice(g.start,g.end);return g},findPointIndex:function(e){var g=this.cropped,b=this.cropStart,f=this.points,a=e.id;if(a)var c=(c= +E(f,function(b){return b.id===a}))?c.index:void 0;"undefined"===typeof c&&(c=(c=E(f,function(a){return a.x===e.x&&a.x2===e.x2&&!a.touched}))?c.index:void 0);g&&C(c)&&C(b)&&c>=b&&(c-=b);return c},translatePoint:function(e){var g=this.xAxis,b=this.yAxis,f=this.columnMetrics,a=this.options,c=a.minPointLength||0,k=e.plotX,l=A(e.x2,e.x+(e.len||0)),m=g.translate(l,0,0,0,1);l=Math.abs(m-k);var q=this.chart.inverted,u=A(a.borderWidth,1)%2/2,n=f.offset,t=Math.round(f.width);c&&(c-=l,0>c&&(c=0),k-=c/2,m+=c/ +2);k=Math.max(k,-10);m=H(m,-10,g.len+10);K(e.options.pointWidth)&&(n-=(Math.ceil(e.options.pointWidth)-t)/2,t=Math.ceil(e.options.pointWidth));a.pointPlacement&&C(e.plotY)&&b.categories&&(e.plotY=b.translate(e.y,0,1,0,1,a.pointPlacement));e.shapeArgs={x:Math.floor(Math.min(k,m))+u,y:Math.floor(e.plotY+n)+u,width:Math.round(Math.abs(m-k)),height:t,r:this.options.borderRadius};a=e.shapeArgs.x;c=a+e.shapeArgs.width;0>a||c>g.len?(a=H(a,0,g.len),c=H(c,0,g.len),m=c-a,e.dlBox=y(e.shapeArgs,{x:a,width:c- +a,centerX:m?m/2:null})):e.dlBox=null;a=e.tooltipPos;c=q?1:0;m=q?0:1;f=this.columnMetrics?this.columnMetrics.offset:-f.width/2;a[c]=H(a[c]+l/2*(g.reversed?-1:1)*(q?-1:1),0,g.len-1);a[m]=H(a[m]+(q?-1:1)*f,0,b.len-1);if(f=e.partialFill)J(f)&&(f=f.amount),C(f)||(f=0),b=e.shapeArgs,e.partShapeArgs={x:b.x,y:b.y,width:b.width,height:b.height,r:this.options.borderRadius},k=Math.max(Math.round(l*f+e.plotX-k),0),e.clipRectArgs={x:g.reversed?b.x+l-k:b.x,y:b.y,width:k,height:b.height}},translate:function(){z.prototype.translate.apply(this, +arguments);this.points.forEach(function(e){this.translatePoint(e)},this)},drawPoint:function(e,g){var b=this.options,f=this.chart.renderer,a=e.graphic,c=e.shapeType,k=e.shapeArgs,l=e.partShapeArgs,m=e.clipRectArgs,q=e.partialFill,u=b.stacking&&!b.borderRadius,n=e.state,t=b.states[n||"normal"]||{},x="undefined"===typeof n?"attr":g;n=this.pointAttribs(e,n);t=A(this.chart.options.chart.animation,t.animation);if(e.isNull||!1===e.visible)a&&(e.graphic=a.destroy());else{if(a)a.rect[g](k);else e.graphic= +a=f.g("point").addClass(e.getClassName()).add(e.group||this.group),a.rect=f[c](y(k)).addClass(e.getClassName()).addClass("highcharts-partfill-original").add(a);l&&(a.partRect?(a.partRect[g](y(l)),a.partialClipRect[g](y(m))):(a.partialClipRect=f.clipRect(m.x,m.y,m.width,m.height),a.partRect=f[c](l).addClass("highcharts-partfill-overlay").add(a).clip(a.partialClipRect)));this.chart.styledMode||(a.rect[g](n,t).shadow(b.shadow,null,u),l&&(J(q)||(q={}),J(b.partialFill)&&(q=y(q,b.partialFill)),e=q.fill|| +B(n.fill).brighten(-.3).get()||B(e.color||this.color).brighten(-.3).get(),n.fill=e,a.partRect[x](n,t).shadow(b.shadow,null,u)))}},drawPoints:function(){var e=this,g=e.getAnimationVerb();e.points.forEach(function(b){e.drawPoint(b,g)})},getAnimationVerb:function(){return this.chart.pointCount<(this.options.animationLimit||250)?"animate":"attr"}},{resolveColor:function(){var e=this.series;if(e.options.colorByPoint&&!this.options.color){var g=e.options.colors||e.chart.options.colors;var b=this.y%(g?g.length: +e.chart.options.chart.colorCount);g=g&&g[b];e.chart.styledMode||(this.color=g);this.options.colorIndex||(this.colorIndex=b)}else this.color||(this.color=e.color)},init:function(){x.prototype.init.apply(this,arguments);this.y||(this.y=0);return this},setState:function(){x.prototype.setState.apply(this,arguments);this.series.drawPoint(this,this.series.getAnimationVerb())},getLabelConfig:function(){var e=x.prototype.getLabelConfig.call(this),g=this.series.yAxis.categories;e.x2=this.x2;e.yCategory=this.yCategory= +g&&g[this.y];return e},tooltipDateKeys:["x","x2"],isValid:function(){return"number"===typeof this.x&&"number"===typeof this.x2}});e(m,"afterGetSeriesExtremes",function(){var e=this.series,g;if(this.isXAxis){var b=A(this.dataMax,-Number.MAX_VALUE);e.forEach(function(e){e.x2Data&&e.x2Data.forEach(function(a){a>b&&(b=a,g=!0)})});g&&(this.dataMax=b)}});""});P(x,"parts-gantt/GanttSeries.js",[x["parts/Globals.js"],x["parts/Utilities.js"]],function(l,e){var x=e.isNumber,t=e.merge,N=e.pick,H=e.seriesType, +L=e.splat,K=l.dateFormat,E=l.seriesTypes.xrange;H("gantt","xrange",{grouping:!1,dataLabels:{enabled:!0},tooltip:{headerFormat:'{series.name}
',pointFormat:null,pointFormatter:function(){var e=this.series,l=e.chart.tooltip,t=e.xAxis,x=e.tooltipOptions.dateTimeLabelFormats,z=t.options.startOfWeek,q=e.tooltipOptions,m=q.xDateFormat;e=this.options.milestone;var u=""+(this.name||this.yCategory)+"";if(q.pointFormat)return this.tooltipFormatter(q.pointFormat); +m||(m=L(l.getDateFormat(t.closestPointRange,this.start,z,x))[0]);l=K(m,this.start);t=K(m,this.end);u+="
";return e?u+(l+"
"):u+("Start: "+l+"
End: ")+(t+"
")}},connectors:{type:"simpleConnect",animation:{reversed:!0},startMarker:{enabled:!0,symbol:"arrow-filled",radius:4,fill:"#fa0",align:"left"},endMarker:{enabled:!1,align:"right"}}},{pointArrayMap:["start","end","y"],keyboardMoveVertical:!1,translatePoint:function(e){E.prototype.translatePoint.call(this,e);if(e.options.milestone){var l= +e.shapeArgs;var t=l.height;e.shapeArgs={x:l.x-t/2,y:l.y,width:t,height:t}}},drawPoint:function(e,l){var t=this.options,A=this.chart.renderer,z=e.shapeArgs,q=e.plotY,m=e.graphic,u=e.selected&&"select",k=t.stacking&&!t.borderRadius;if(e.options.milestone)if(x(q)&&null!==e.y&&!1!==e.visible){z=A.symbols.diamond(z.x,z.y,z.width,z.height);if(m)m[l]({d:z});else e.graphic=A.path(z).addClass(e.getClassName(),!0).add(e.group||this.group);this.chart.styledMode||e.graphic.attr(this.pointAttribs(e,u)).shadow(t.shadow, +null,k)}else m&&(e.graphic=m.destroy());else E.prototype.drawPoint.call(this,e,l)},setData:l.Series.prototype.setData,setGanttPointAliases:function(e){function l(l,t){"undefined"!==typeof t&&(e[l]=t)}l("x",N(e.start,e.x));l("x2",N(e.end,e.x2));l("partialFill",N(e.completed,e.partialFill));l("connect",N(e.dependency,e.connect))}},t(E.prototype.pointClass.prototype,{applyOptions:function(e,x){e=t(e);l.seriesTypes.gantt.prototype.setGanttPointAliases(e);return e=E.prototype.pointClass.prototype.applyOptions.call(this, +e,x)},isValid:function(){return("number"===typeof this.start||"number"===typeof this.x)&&("number"===typeof this.end||"number"===typeof this.x2||this.milestone)}}));""});P(x,"parts-gantt/GanttChart.js",[x["parts/Globals.js"],x["parts/Utilities.js"]],function(l,e){var x=e.isArray,t=e.merge,N=e.splat,H=l.Chart;l.ganttChart=function(e,B,E){var C="string"===typeof e||e.nodeName,J=B.series,y=l.getOptions(),A,z=B;B=arguments[C?1:0];x(B.xAxis)||(B.xAxis=[B.xAxis||{},{}]);B.xAxis=B.xAxis.map(function(e,l){1=== +l&&(A=0);return t(y.xAxis,{grid:{enabled:!0},opposite:!0,linkedTo:A},e,{type:"datetime"})});B.yAxis=N(B.yAxis||{}).map(function(e){return t(y.yAxis,{grid:{enabled:!0},staticScale:50,reversed:!0,type:e.categories?e.type:"treegrid"},e)});B.series=null;B=t(!0,{chart:{type:"gantt"},title:{text:null},legend:{enabled:!1}},B,{isGantt:!0});B.series=z.series=J;B.series.forEach(function(e){e.data.forEach(function(e){l.seriesTypes.gantt.prototype.setGanttPointAliases(e)})});return C?new H(e,B,E):new H(B,B)}}); +P(x,"parts/ScrollbarAxis.js",[x["parts/Globals.js"],x["parts/Utilities.js"]],function(l,e){var x=e.addEvent,t=e.defined,N=e.pick;return function(){function e(){}e.compose=function(e,B){x(e,"afterInit",function(){var e=this;e.options&&e.options.scrollbar&&e.options.scrollbar.enabled&&(e.options.scrollbar.vertical=!e.horiz,e.options.startOnTick=e.options.endOnTick=!1,e.scrollbar=new B(e.chart.renderer,e.options.scrollbar,e.chart),x(e.scrollbar,"changed",function(x){var B=N(e.options&&e.options.min, +e.min),y=N(e.options&&e.options.max,e.max),A=t(e.dataMin)?Math.min(B,e.min,e.dataMin):B,z=(t(e.dataMax)?Math.max(y,e.max,e.dataMax):y)-A;t(B)&&t(y)&&(e.horiz&&!e.reversed||!e.horiz&&e.reversed?(B=A+z*this.to,A+=z*this.from):(B=A+z*(1-this.from),A+=z*(1-this.to)),N(this.options.liveRedraw,l.svg&&!l.isTouchDevice&&!this.chart.isBoosting)||"mouseup"===x.DOMType||!t(x.DOMType)?e.setExtremes(A,B,!0,"mousemove"!==x.DOMType,x):this.setRange(this.from,this.to))}))});x(e,"afterRender",function(){var e=Math.min(N(this.options.min, +this.min),this.min,N(this.dataMin,this.min)),l=Math.max(N(this.options.max,this.max),this.max,N(this.dataMax,this.max)),x=this.scrollbar,y=this.axisTitleMargin+(this.titleOffset||0),A=this.chart.scrollbarsOffsets,z=this.options.margin||0;x&&(this.horiz?(this.opposite||(A[1]+=y),x.position(this.left,this.top+this.height+2+A[1]-(this.opposite?z:0),this.width,this.height),this.opposite||(A[1]+=z),y=1):(this.opposite&&(A[0]+=y),x.position(this.left+this.width+2+A[0]-(this.opposite?0:z),this.top,this.width, +this.height),this.opposite&&(A[0]+=z),y=0),A[y]+=x.size+x.options.margin,isNaN(e)||isNaN(l)||!t(this.min)||!t(this.max)||this.min===this.max?x.setRange(0,1):(A=(this.min-e)/(l-e),e=(this.max-e)/(l-e),this.horiz&&!this.reversed||!this.horiz&&this.reversed?x.setRange(A,e):x.setRange(1-e,1-A)))});x(e,"afterGetOffset",function(){var e=this.horiz?2:1,l=this.scrollbar;l&&(this.chart.scrollbarsOffsets=[0,0],this.chart.axisOffset[e]+=l.size+l.options.margin)})};return e}()});P(x,"parts/Scrollbar.js",[x["parts/Axis.js"], +x["parts/Globals.js"],x["parts/ScrollbarAxis.js"],x["parts/Utilities.js"]],function(l,e,x,t){var B=t.addEvent,H=t.correctFloat,L=t.defined,K=t.destroyObjectProperties,E=t.fireEvent,C=t.merge,J=t.pick,y=t.removeEvent;t=e.defaultOptions;var A=e.hasTouch,z=e.isTouchDevice,q=e.swapXY=function(e,k){k&&e.forEach(function(e){for(var b=e.length,f,a=0;athis.calculatedWidth?g.minWidth:0;return{chartX:(e.chartX- +this.x-this.xOffset)/(this.barWidth-g),chartY:(e.chartY-this.y-this.yOffset)/(this.barWidth-g)}};e.prototype.destroy=function(){var e=this.chart.scroller;this.removeEvents();["track","scrollbarRifles","scrollbar","scrollbarGroup","group"].forEach(function(e){this[e]&&this[e].destroy&&(this[e]=this[e].destroy())},this);e&&this===e.scrollbar&&(e.scrollbar=null,K(e.scrollbarButtons))};e.prototype.drawScrollbarButton=function(e){var g=this.renderer,b=this.scrollbarButtons,f=this.options,a=this.size;var c= +g.g().add(this.group);b.push(c);c=g.rect().addClass("highcharts-scrollbar-button").add(c);this.chart.styledMode||c.attr({stroke:f.buttonBorderColor,"stroke-width":f.buttonBorderWidth,fill:f.buttonBackgroundColor});c.attr(c.crisp({x:-.5,y:-.5,width:a+1,height:a+1,r:f.buttonBorderRadius},c.strokeWidth()));c=g.path(q([["M",a/2+(e?-1:1),a/2-3],["L",a/2+(e?-1:1),a/2+3],["L",a/2+(e?2:-2),a/2]],f.vertical)).addClass("highcharts-scrollbar-arrow").add(b[e]);this.chart.styledMode||c.attr({fill:f.buttonArrowColor})}; +e.prototype.init=function(k,g,b){this.scrollbarButtons=[];this.renderer=k;this.userOptions=g;this.options=C(e.defaultOptions,g);this.chart=b;this.size=J(this.options.size,this.options.height);g.enabled&&(this.render(),this.addEvents())};e.prototype.mouseDownHandler=function(e){e=this.chart.pointer.normalize(e);e=this.cursorToScrollbarPosition(e);this.chartX=e.chartX;this.chartY=e.chartY;this.initPositions=[this.from,this.to];this.grabbedCenter=!0};e.prototype.mouseMoveHandler=function(e){var g=this.chart.pointer.normalize(e), +b=this.options.vertical?"chartY":"chartX",f=this.initPositions||[];!this.grabbedCenter||e.touches&&0===e.touches[0][b]||(g=this.cursorToScrollbarPosition(g)[b],b=this[b],b=g-b,this.hasDragged=!0,this.updatePosition(f[0]+b,f[1]+b),this.hasDragged&&E(this,"changed",{from:this.from,to:this.to,trigger:"scrollbar",DOMType:e.type,DOMEvent:e}))};e.prototype.mouseUpHandler=function(e){this.hasDragged&&E(this,"changed",{from:this.from,to:this.to,trigger:"scrollbar",DOMType:e.type,DOMEvent:e});this.grabbedCenter= +this.hasDragged=this.chartX=this.chartY=null};e.prototype.position=function(e,g,b,f){var a=this.options.vertical,c=0,k=this.rendered?"animate":"attr";this.x=e;this.y=g+this.trackBorderWidth;this.width=b;this.xOffset=this.height=f;this.yOffset=c;a?(this.width=this.yOffset=b=c=this.size,this.xOffset=g=0,this.barWidth=f-2*b,this.x=e+=this.options.margin):(this.height=this.xOffset=f=g=this.size,this.barWidth=b-2*f,this.y+=this.options.margin);this.group[k]({translateX:e,translateY:this.y});this.track[k]({width:b, +height:f});this.scrollbarButtons[1][k]({translateX:a?0:b-g,translateY:a?f-c:0})};e.prototype.removeEvents=function(){this._events.forEach(function(e){y.apply(null,e)});this._events.length=0};e.prototype.render=function(){var e=this.renderer,g=this.options,b=this.size,f=this.chart.styledMode,a;this.group=a=e.g("scrollbar").attr({zIndex:g.zIndex,translateY:-99999}).add();this.track=e.rect().addClass("highcharts-scrollbar-track").attr({x:0,r:g.trackBorderRadius||0,height:b,width:b}).add(a);f||this.track.attr({fill:g.trackBackgroundColor, +stroke:g.trackBorderColor,"stroke-width":g.trackBorderWidth});this.trackBorderWidth=this.track.strokeWidth();this.track.attr({y:-this.trackBorderWidth%2/2});this.scrollbarGroup=e.g().add(a);this.scrollbar=e.rect().addClass("highcharts-scrollbar-thumb").attr({height:b,width:b,r:g.barBorderRadius||0}).add(this.scrollbarGroup);this.scrollbarRifles=e.path(q([["M",-3,b/4],["L",-3,2*b/3],["M",0,b/4],["L",0,2*b/3],["M",3,b/4],["L",3,2*b/3]],g.vertical)).addClass("highcharts-scrollbar-rifles").add(this.scrollbarGroup); +f||(this.scrollbar.attr({fill:g.barBackgroundColor,stroke:g.barBorderColor,"stroke-width":g.barBorderWidth}),this.scrollbarRifles.attr({stroke:g.rifleColor,"stroke-width":1}));this.scrollbarStrokeWidth=this.scrollbar.strokeWidth();this.scrollbarGroup.translate(-this.scrollbarStrokeWidth%2/2,-this.scrollbarStrokeWidth%2/2);this.drawScrollbarButton(0);this.drawScrollbarButton(1)};e.prototype.setRange=function(e,g){var b=this.options,f=b.vertical,a=b.minWidth,c=this.barWidth,k,l=!this.rendered||this.hasDragged|| +this.chart.navigator&&this.chart.navigator.hasDragged?"attr":"animate";if(L(c)){e=Math.max(e,0);var m=Math.ceil(c*e);this.calculatedWidth=k=H(c*Math.min(g,1)-m);k=k?this.scrollbarRifles.hide():this.scrollbarRifles.show(!0);!1===b.showFull&&(0>=e&&1<=g?this.group.hide():this.group.show());this.rendered=!0}};e.prototype.trackClick=function(e){var g=this.chart.pointer.normalize(e),b=this.to-this.from,f=this.y+this.scrollbarTop,a=this.x+this.scrollbarLeft;this.options.vertical&&g.chartY>f||!this.options.vertical&&g.chartX>a?this.updatePosition(this.from+b,this.to+b):this.updatePosition(this.from-b,this.to-b);E(this, +"changed",{from:this.from,to:this.to,trigger:"scrollbar",DOMEvent:e})};e.prototype.update=function(e){this.destroy();this.init(this.chart.renderer,C(!0,this.options,e),this.chart)};e.prototype.updatePosition=function(e,g){1e&&(g=H(g-e),e=0);this.from=e;this.to=g};e.defaultOptions={height:z?20:14,barBorderRadius:0,buttonBorderRadius:0,liveRedraw:void 0,margin:10,minWidth:6,step:.2,zIndex:3,barBackgroundColor:"#cccccc",barBorderWidth:1,barBorderColor:"#cccccc",buttonArrowColor:"#333333", +buttonBackgroundColor:"#e6e6e6",buttonBorderColor:"#cccccc",buttonBorderWidth:1,rifleColor:"#333333",trackBackgroundColor:"#f2f2f2",trackBorderColor:"#f2f2f2",trackBorderWidth:1};return e}();e.Scrollbar||(t.scrollbar=C(!0,m.defaultOptions,t.scrollbar),e.Scrollbar=m,x.compose(l,m));return e.Scrollbar});P(x,"parts/RangeSelector.js",[x["parts/Globals.js"],x["parts/Utilities.js"]],function(l,e){function x(b){this.init(b)}var t=e.addEvent,N=e.createElement,H=e.css,L=e.defined,K=e.destroyObjectProperties, +E=e.discardElement,C=e.extend,J=e.fireEvent,y=e.isNumber,A=e.merge,z=e.objectEach,q=e.pick,m=e.pInt,u=e.splat,k=l.Axis;e=l.Chart;var g=l.defaultOptions;C(g,{rangeSelector:{verticalAlign:"top",buttonTheme:{width:28,height:18,padding:2,zIndex:7},floating:!1,x:0,y:0,height:void 0,inputPosition:{align:"right",x:0,y:0},buttonPosition:{align:"left",x:0,y:0},labelStyle:{color:"#666666"}}});g.lang=A(g.lang,{rangeSelectorZoom:"Zoom",rangeSelectorFrom:"From",rangeSelectorTo:"To"});x.prototype={clickButton:function(b, +e){var a=this.chart,c=this.buttonOptions[b],f=a.xAxis[0],g=a.scroller&&a.scroller.getUnionExtremes()||f||{},l=g.dataMin,m=g.dataMax,v=f&&Math.round(Math.min(f.max,q(m,f.max))),n=c.type;g=c._range;var F,x=c.dataGrouping;if(null!==l&&null!==m){a.fixedRange=g;x&&(this.forcedDataGrouping=!0,k.prototype.setDataGrouping.call(f||{chart:this.chart},x,!1),this.frozenStates=c.preserveDataGrouping);if("month"===n||"year"===n)if(f){n={range:c,max:v,chart:a,dataMin:l,dataMax:m};var D=f.minFromRange.call(n);y(n.newMax)&& +(v=n.newMax)}else g=c;else if(g)D=Math.max(v-g,l),v=Math.min(D+g,m);else if("ytd"===n)if(f)"undefined"===typeof m&&(l=Number.MAX_VALUE,m=Number.MIN_VALUE,a.series.forEach(function(a){a=a.xData;l=Math.min(a[0],l);m=Math.max(a[a.length-1],m)}),e=!1),v=this.getYTDExtremes(m,l,a.time.useUTC),D=F=v.min,v=v.max;else{this.deferredYTDClick=b;return}else"all"===n&&f&&(D=l,v=m);D+=c._offsetMin;v+=c._offsetMax;this.setSelected(b);if(f)f.setExtremes(D,v,q(e,1),null,{trigger:"rangeSelectorButton",rangeSelectorButton:c}); +else{var h=u(a.options.xAxis)[0];var d=h.range;h.range=g;var z=h.min;h.min=F;t(a,"load",function(){h.range=d;h.min=z})}}},setSelected:function(b){this.selected=this.options.selected=b},defaultButtons:[{type:"month",count:1,text:"1m"},{type:"month",count:3,text:"3m"},{type:"month",count:6,text:"6m"},{type:"ytd",text:"YTD"},{type:"year",count:1,text:"1y"},{type:"all",text:"All"}],init:function(b){var e=this,a=b.options.rangeSelector,c=a.buttons||[].concat(e.defaultButtons),g=a.selected,k=function(){var a= +e.minInput,b=e.maxInput;a&&a.blur&&J(a,"blur");b&&b.blur&&J(b,"blur")};e.chart=b;e.options=a;e.buttons=[];e.buttonOptions=c;this.unMouseDown=t(b.container,"mousedown",k);this.unResize=t(b,"resize",k);c.forEach(e.computeButtonRange);"undefined"!==typeof g&&c[g]&&this.clickButton(g,!1);t(b,"load",function(){b.xAxis&&b.xAxis[0]&&t(b.xAxis[0],"setExtremes",function(a){this.max-this.min!==b.fixedRange&&"rangeSelectorButton"!==a.trigger&&"updatedData"!==a.trigger&&e.forcedDataGrouping&&!e.frozenStates&& +this.setDataGrouping(!1,!1)})})},updateButtonStates:function(){var b=this,e=this.chart,a=e.xAxis[0],c=Math.round(a.max-a.min),g=!a.hasVisibleSeries,k=e.scroller&&e.scroller.getUnionExtremes()||a,l=k.dataMin,m=k.dataMax;e=b.getYTDExtremes(m,l,e.time.useUTC);var q=e.min,n=e.max,u=b.selected,t=y(u),x=b.options.allButtonsEnabled,h=b.buttons;b.buttonOptions.forEach(function(d,e){var f=d._range,k=d.type,p=d.count||1,r=h[e],v=0,w=d._offsetMax-d._offsetMin;d=e===u;var F=f>m-l,y=f=864E5*{month:28,year:365}[k]*p-w&&c-36E5<=864E5*{month:31,year:366}[k]*p+w?f=!0:"ytd"===k?(f=n-q+w===c,D=!d):"all"===k&&(f=a.max-a.min>=m-l,z=!d&&t&&f);k=!x&&(F||y||z||g);p=d&&f||f&&!t&&!D||d&&b.frozenStates;k?v=3:p&&(t=!0,v=2);r.state!==v&&(r.setState(v),0===v&&u===e&&b.setSelected(null))})},computeButtonRange:function(b){var e=b.type,a=b.count||1,c={millisecond:1,second:1E3,minute:6E4,hour:36E5,day:864E5,week:6048E5};if(c[e])b._range=c[e]*a;else if("month"=== +e||"year"===e)b._range=864E5*{month:30,year:365}[e]*a;b._offsetMin=q(b.offsetMin,0);b._offsetMax=q(b.offsetMax,0);b._range+=b._offsetMax-b._offsetMin},setInputValue:function(b,e){var a=this.chart.options.rangeSelector,c=this.chart.time,f=this[b+"Input"];L(e)&&(f.previousValue=f.HCTime,f.HCTime=e);f.value=c.dateFormat(a.inputEditDateFormat||"%Y-%m-%d",f.HCTime);this[b+"DateBox"].attr({text:c.dateFormat(a.inputDateFormat||"%b %e, %Y",f.HCTime)})},showInput:function(b){var e=this.inputGroup,a=this[b+ +"DateBox"];H(this[b+"Input"],{left:e.translateX+a.x+"px",top:e.translateY+"px",width:a.width-2+"px",height:a.height-2+"px",border:"2px solid silver"})},hideInput:function(b){H(this[b+"Input"],{border:0,width:"1px",height:"1px"});this.setInputValue(b)},drawInput:function(b){function e(){var b=n.value,e=(q.inputDateParser||Date.parse)(b),d=c.xAxis[0],f=c.scroller&&c.scroller.xAxis?c.scroller.xAxis:d,g=f.dataMin;f=f.dataMax;e!==n.previousValue&&(n.previousValue=e,y(e)||(e=b.split("-"),e=Date.UTC(m(e[0]), +m(e[1])-1,m(e[2]))),y(e)&&(c.time.useUTC||(e+=6E4*(new Date).getTimezoneOffset()),v?e>a.maxInput.HCTime?e=void 0:ef&&(e=f),"undefined"!==typeof e&&d.setExtremes(v?e:d.min,v?d.max:e,void 0,void 0,{trigger:"rangeSelectorInput"})))}var a=this,c=a.chart,k=c.renderer.style||{},p=c.renderer,q=c.options.rangeSelector,u=a.div,v="min"===b,n,t,x=this.inputGroup;this[b+"Label"]=t=p.label(g.lang[v?"rangeSelectorFrom":"rangeSelectorTo"],this.inputGroup.offset).addClass("highcharts-range-label").attr({padding:2}).add(x); +x.offset+=t.width+5;this[b+"DateBox"]=p=p.label("",x.offset).addClass("highcharts-range-input").attr({padding:2,width:q.inputBoxWidth||90,height:q.inputBoxHeight||17,"text-align":"center"}).on("click",function(){a.showInput(b);a[b+"Input"].focus()});c.styledMode||p.attr({stroke:q.inputBoxBorderColor||"#cccccc","stroke-width":1});p.add(x);x.offset+=p.width+(v?10:0);this[b+"Input"]=n=N("input",{name:b,className:"highcharts-range-selector",type:"text"},{top:c.plotTop+"px"},u);c.styledMode||(t.css(A(k, +q.labelStyle)),p.css(A({color:"#333333"},k,q.inputStyle)),H(n,C({position:"absolute",border:0,width:"1px",height:"1px",padding:0,textAlign:"center",fontSize:k.fontSize,fontFamily:k.fontFamily,top:"-9999em"},q.inputStyle)));n.onfocus=function(){a.showInput(b)};n.onblur=function(){n===l.doc.activeElement&&e();a.hideInput(b);n.blur()};n.onchange=e;n.onkeypress=function(a){13===a.keyCode&&e()}},getPosition:function(){var b=this.chart,e=b.options.rangeSelector;b="top"===e.verticalAlign?b.plotTop-b.axisOffset[0]: +0;return{buttonTop:b+e.buttonPosition.y,inputTop:b+e.inputPosition.y-10}},getYTDExtremes:function(b,e,a){var c=this.chart.time,f=new c.Date(b),g=c.get("FullYear",f);a=a?c.Date.UTC(g,0,1):+new c.Date(g,0,1);e=Math.max(e||0,a);f=f.getTime();return{max:Math.min(b||f,f),min:e}},render:function(b,e){var a=this,c=a.chart,f=c.renderer,k=c.container,l=c.options,m=l.exporting&&!1!==l.exporting.enabled&&l.navigation&&l.navigation.buttonOptions,v=g.lang,n=a.div,u=l.rangeSelector,t=q(l.chart.style&&l.chart.style.zIndex, +0)+1;l=u.floating;var y=a.buttons;n=a.inputGroup;var h=u.buttonTheme,d=u.buttonPosition,x=u.inputPosition,z=u.inputEnabled,A=h&&h.states,B=c.plotLeft,C=a.buttonGroup,E,H=a.options.verticalAlign,J=c.legend,L=J&&J.options,K=d.y,P=x.y,T=c.hasLoaded,aa=T?"animate":"attr",R=0,Y=0;if(!1!==u.enabled){a.rendered||(a.group=E=f.g("range-selector-group").attr({zIndex:7}).add(),a.buttonGroup=C=f.g("range-selector-buttons").add(E),a.zoomText=f.text(v.rangeSelectorZoom,0,15).add(C),c.styledMode||(a.zoomText.css(u.labelStyle), +h["stroke-width"]=q(h["stroke-width"],0)),a.buttonOptions.forEach(function(b,d){y[d]=f.button(b.text,0,0,function(c){var e=b.events&&b.events.click,f;e&&(f=e.call(b,c));!1!==f&&a.clickButton(d);a.isActive=!0},h,A&&A.hover,A&&A.select,A&&A.disabled).attr({"text-align":"center"}).add(C)}),!1!==z&&(a.div=n=N("div",null,{position:"relative",height:0,zIndex:t}),k.parentNode.insertBefore(n,k),a.inputGroup=n=f.g("input-group").add(E),n.offset=0,a.drawInput("min"),a.drawInput("max")));a.zoomText[aa]({x:q(B+ +d.x,B)});var ba=q(B+d.x,B)+a.zoomText.getBBox().width+5;a.buttonOptions.forEach(function(a,b){y[b][aa]({x:ba});ba+=y[b].width+q(u.buttonSpacing,5)});B=c.plotLeft-c.spacing[3];a.updateButtonStates();m&&this.titleCollision(c)&&"top"===H&&"right"===d.align&&d.y+C.getBBox().height-12<(m.y||0)+m.height&&(R=-40);k=d.x-c.spacing[3];"right"===d.align?k+=R-B:"center"===d.align&&(k-=B/2);C.align({y:d.y,width:C.getBBox().width,align:d.align,x:k},!0,c.spacingBox);a.group.placed=T;a.buttonGroup.placed=T;!1!== +z&&(R=m&&this.titleCollision(c)&&"top"===H&&"right"===x.align&&x.y-n.getBBox().height-12<(m.y||0)+m.height+c.spacing[0]?-40:0,"left"===x.align?k=B:"right"===x.align&&(k=-Math.max(c.axisOffset[1],-R)),n.align({y:x.y,width:n.getBBox().width,align:x.align,x:x.x+k-2},!0,c.spacingBox),m=n.alignAttr.translateX+n.alignOptions.x-R+n.getBBox().x+2,k=n.alignOptions.width,v=C.alignAttr.translateX+C.getBBox().x,B=C.getBBox().width+20,(x.align===d.align||v+B>m&&m+k>v&&K=-R?0:-R),translateY:n.alignAttr.translateY+C.getBBox().height+10}),a.setInputValue("min",b),a.setInputValue("max",e),a.inputGroup.placed=T);a.group.align({verticalAlign:H},!0,c.spacingBox);b=a.group.getBBox().height+20;e=a.group.alignAttr.translateY;"bottom"===H&&(J=L&&"bottom"===L.verticalAlign&&L.enabled&&!L.floating?J.legendHeight+q(L.margin,10):0,b=b+J-20,Y=e-b-(l?0:u.y)-(c.titleOffset?c.titleOffset[2]:0)-10);if("top"===H)l&&(Y=0),c.titleOffset&&c.titleOffset[0]&&(Y=c.titleOffset[0]), +Y+=c.margin[0]-c.spacing[0]||0;else if("middle"===H)if(P===K)Y=0>P?e+void 0:e;else if(P||K)Y=0>P||0>K?Y-Math.min(P,K):e-b+NaN;a.group.translate(u.x,u.y+Math.floor(Y));!1!==z&&(a.minInput.style.marginTop=a.group.translateY+"px",a.maxInput.style.marginTop=a.group.translateY+"px");a.rendered=!0}},getHeight:function(){var b=this.options,e=this.group,a=b.y,c=b.buttonPosition.y,g=b.inputPosition.y;if(b.height)return b.height;b=e?e.getBBox(!0).height+13+a:0;e=Math.min(g,c);if(0>g&&0>c||0q&&(x?e=l-m:l=e+m);L(e)&&L(l)||(e=l=void 0);return{min:e,max:l}};return e}();return function(){function e(){}e.compose= +function(e){e.keepProps.push("navigatorAxis");t(e,"init",function(){this.navigatorAxis||(this.navigatorAxis=new E(this))});t(e,"zoom",function(e){var l=this.chart.options,t=l.navigator,q=this.navigatorAxis,m=l.chart.pinchType,u=l.rangeSelector;l=l.chart.zoomType;this.isXAxis&&(t&&t.enabled||u&&u.enabled)&&("y"===l?e.zoomed=!1:(!x&&"xy"===l||x&&"xy"===m)&&this.options.range&&(t=q.previousZoom,H(e.newMin)?q.previousZoom=[this.min,this.max]:t&&(e.newMin=t[0],e.newMax=t[1],q.previousZoom=void 0)));"undefined"!== +typeof e.zoomed&&e.preventDefault()})};e.AdditionsClass=E;return e}()});P(x,"parts/Navigator.js",[x["parts/Axis.js"],x["parts/Color.js"],x["parts/Globals.js"],x["parts/NavigatorAxis.js"],x["parts/Scrollbar.js"],x["parts/Utilities.js"]],function(l,e,x,t,N,H){e=e.parse;var B=H.addEvent,K=H.clamp,E=H.correctFloat,C=H.defined,J=H.destroyObjectProperties,y=H.erase,A=H.extend,z=H.find,q=H.isArray,m=H.isNumber,u=H.merge,k=H.pick,g=H.removeEvent,b=H.splat;H=x.Chart;var f=x.defaultOptions,a=x.hasTouch,c=x.isTouchDevice, +r=x.Series,p=function(a){for(var b=[],c=1;cw&&(this.grabbedLeft?c=l.toPixels(b-w-n,!0):this.grabbedRight&&(e=l.toPixels(a+w+n,!0)));this.zoomedMax=K(Math.max(c,e),0,r);this.zoomedMin=K(this.fixedWidth?this.zoomedMax-this.fixedWidth:Math.min(c,e),0,r);this.range=this.zoomedMax-this.zoomedMin;r=Math.round(this.zoomedMax);c=Math.round(this.zoomedMin);q&&(this.navigatorGroup.attr({visibility:"visible"}),u=u&&!this.hasDragged?"animate":"attr",this.drawMasks(c,r,t,u),this.drawOutline(c, +r,t,u),this.navigatorOptions.handles.enabled&&(this.drawHandle(c,0,t,u),this.drawHandle(r,1,t,u)));this.scrollbar&&(t?(t=this.top-d,p=this.left-d+(q||!p.opposite?0:(p.titleOffset||0)+p.axisTitleMargin),d=g+2*d):(t=this.top+(q?this.height:-d),p=this.left-d),this.scrollbar.position(p,t,f,d),this.scrollbar.setRange(this.zoomedMin/(g||1),this.zoomedMax/(g||1)));this.rendered=!0}};e.prototype.addMouseEvents=function(){var b=this,c=b.chart,e=c.container,f=[],g,d;b.mouseMoveHandler=g=function(a){b.onMouseMove(a)}; +b.mouseUpHandler=d=function(a){b.onMouseUp(a)};f=b.getPartsEvents("mousedown");f.push(B(c.renderTo,"mousemove",g),B(e.ownerDocument,"mouseup",d));a&&(f.push(B(c.renderTo,"touchmove",g),B(e.ownerDocument,"touchend",d)),f.concat(b.getPartsEvents("touchstart")));b.eventsToUnbind=f;b.series&&b.series[0]&&f.push(B(b.series[0].xAxis,"foundExtremes",function(){c.navigator.modifyNavigatorAxisExtremes()}))};e.prototype.getPartsEvents=function(a){var b=this,c=[];["shades","handles"].forEach(function(e){b[e].forEach(function(f, +d){c.push(B(f.element,a,function(a){b[e+"Mousedown"](a,d)}))})});return c};e.prototype.shadesMousedown=function(a,b){a=this.chart.pointer.normalize(a);var c=this.chart,e=this.xAxis,f=this.zoomedMin,d=this.left,g=this.size,k=this.range,l=a.chartX;c.inverted&&(l=a.chartY,d=this.top);if(1===b)this.grabbedCenter=l,this.fixedWidth=k,this.dragOffset=l-f;else{a=l-d-k/2;if(0===b)a=Math.max(0,a);else if(2===b&&a+k>=g)if(a=g-k,this.reversedExtremes){a-=k;var m=this.getUnionExtremes().dataMin}else var n=this.getUnionExtremes().dataMax; +a!==f&&(this.fixedWidth=k,b=e.navigatorAxis.toFixedRange(a,a+k,m,n),C(b.min)&&c.xAxis[0].setExtremes(Math.min(b.min,b.max),Math.max(b.min,b.max),!0,null,{trigger:"navigator"}))}};e.prototype.handlesMousedown=function(a,b){this.chart.pointer.normalize(a);a=this.chart;var c=a.xAxis[0],e=this.reversedExtremes;0===b?(this.grabbedLeft=!0,this.otherHandlePos=this.zoomedMax,this.fixedExtreme=e?c.min:c.max):(this.grabbedRight=!0,this.otherHandlePos=this.zoomedMin,this.fixedExtreme=e?c.max:c.min);a.fixedRange= +null};e.prototype.onMouseMove=function(a){var b=this,e=b.chart,f=b.left,g=b.navigatorSize,d=b.range,l=b.dragOffset,m=e.inverted;a.touches&&0===a.touches[0].pageX||(a=e.pointer.normalize(a),e=a.chartX,m&&(f=b.top,e=a.chartY),b.grabbedLeft?(b.hasDragged=!0,b.render(0,0,e-f,b.otherHandlePos)):b.grabbedRight?(b.hasDragged=!0,b.render(0,0,b.otherHandlePos,e-f)):b.grabbedCenter&&(b.hasDragged=!0,eg+l-d&&(e=g+l-d),b.render(0,0,e-l,e-l+d)),b.hasDragged&&b.scrollbar&&k(b.scrollbar.options.liveRedraw, +x.svg&&!c&&!this.chart.isBoosting)&&(a.DOMType=a.type,setTimeout(function(){b.onMouseUp(a)},0)))};e.prototype.onMouseUp=function(a){var b=this.chart,c=this.xAxis,e=this.scrollbar,f=a.DOMEvent||a,d=b.inverted,g=this.rendered&&!this.hasDragged?"animate":"attr",k=Math.round(this.zoomedMax),l=Math.round(this.zoomedMin);if(this.hasDragged&&(!e||!e.hasDragged)||"scrollbar"===a.trigger){e=this.getUnionExtremes();if(this.zoomedMin===this.otherHandlePos)var m=this.fixedExtreme;else if(this.zoomedMax===this.otherHandlePos)var n= +this.fixedExtreme;this.zoomedMax===this.size&&(n=this.reversedExtremes?e.dataMin:e.dataMax);0===this.zoomedMin&&(m=this.reversedExtremes?e.dataMax:e.dataMin);c=c.navigatorAxis.toFixedRange(this.zoomedMin,this.zoomedMax,m,n);C(c.min)&&b.xAxis[0].setExtremes(Math.min(c.min,c.max),Math.max(c.min,c.max),!0,this.hasDragged?!1:null,{trigger:"navigator",triggerOp:"navigator-drag",DOMEvent:f})}"mousemove"!==a.DOMType&&"touchmove"!==a.DOMType&&(this.grabbedLeft=this.grabbedRight=this.grabbedCenter=this.fixedWidth= +this.fixedExtreme=this.otherHandlePos=this.hasDragged=this.dragOffset=null);this.navigatorEnabled&&(this.shades&&this.drawMasks(l,k,d,g),this.outline&&this.drawOutline(l,k,d,g),this.navigatorOptions.handles.enabled&&Object.keys(this.handles).length===this.handles.length&&(this.drawHandle(l,0,d,g),this.drawHandle(k,1,d,g)))};e.prototype.removeEvents=function(){this.eventsToUnbind&&(this.eventsToUnbind.forEach(function(a){a()}),this.eventsToUnbind=void 0);this.removeBaseSeriesEvents()};e.prototype.removeBaseSeriesEvents= +function(){var a=this.baseSeries||[];this.navigatorEnabled&&a[0]&&(!1!==this.navigatorOptions.adaptToUpdatedData&&a.forEach(function(a){g(a,"updatedData",this.updatedDataHandler)},this),a[0].xAxis&&g(a[0].xAxis,"foundExtremes",this.modifyBaseAxisExtremes))};e.prototype.init=function(a){var b=a.options,c=b.navigator,e=c.enabled,f=b.scrollbar,d=f.enabled;b=e?c.height:0;var g=d?f.height:0;this.handles=[];this.shades=[];this.chart=a;this.setBaseSeries();this.height=b;this.scrollbarHeight=g;this.scrollbarEnabled= +d;this.navigatorEnabled=e;this.navigatorOptions=c;this.scrollbarOptions=f;this.outlineHeight=b+g;this.opposite=k(c.opposite,!(e||!a.inverted));var m=this;e=m.baseSeries;f=a.xAxis.length;d=a.yAxis.length;var n=e&&e[0]&&e[0].xAxis||a.xAxis[0]||{options:{}};a.isDirtyBox=!0;m.navigatorEnabled?(m.xAxis=new l(a,u({breaks:n.options.breaks,ordinal:n.options.ordinal},c.xAxis,{id:"navigator-x-axis",yAxis:"navigator-y-axis",isX:!0,type:"datetime",index:f,isInternal:!0,offset:0,keepOrdinalPadding:!0,startOnTick:!1, +endOnTick:!1,minPadding:0,maxPadding:0,zoomEnabled:!1},a.inverted?{offsets:[g,0,-g,0],width:b}:{offsets:[0,-g,0,g],height:b})),m.yAxis=new l(a,u(c.yAxis,{id:"navigator-y-axis",alignTicks:!1,offset:0,index:d,isInternal:!0,zoomEnabled:!1},a.inverted?{width:b}:{height:b})),e||c.series.data?m.updateNavigatorSeries(!1):0===a.series.length&&(m.unbindRedraw=B(a,"beforeRedraw",function(){0h.indexOf(b)?(b&&(g(b,"updatedData",e.updatedDataHandler),delete b.navigatorSeries),a.chart&&a.destroy(),!1):!0});h&&h.length&&h.forEach(function(a){var b=a.navigatorSeries,g=A({color:a.color,visible:a.visible},q(n)?f.navigator.series:n);b&&!1===e.navigatorOptions.adaptToUpdatedData||(r.name="Navigator "+h.length,d=a.options||{},p=d.navigatorOptions||{},m=u(d,r,g,p),m.pointRange=k(g.pointRange,p.pointRange,f.plotOptions[m.type||"line"].pointRange),g=p.data||g.data,e.hasNavigatorData=e.hasNavigatorData|| +!!g,m.data=g||d.data&&d.data.slice(0),b&&b.options?b.update(m,c):(a.navigatorSeries=l.initSeries(m),a.navigatorSeries.baseSeries=a,t.push(a.navigatorSeries)))});if(n.data&&(!h||!h.length)||q(n))e.hasNavigatorData=!1,n=b(n),n.forEach(function(a,b){r.name="Navigator "+(t.length+1);m=u(f.navigator.series,{color:l.series[b]&&!l.series[b].options.isInternal&&l.series[b].color||l.options.colors[b]||l.options.colors[0]},r,a);m.data=a.data;m.data&&(e.hasNavigatorData=!0,t.push(l.initSeries(m)))});a&&this.addBaseSeriesEvents()}; +e.prototype.addBaseSeriesEvents=function(){var a=this,b=a.baseSeries||[];b[0]&&b[0].xAxis&&B(b[0].xAxis,"foundExtremes",this.modifyBaseAxisExtremes);b.forEach(function(b){B(b,"show",function(){this.navigatorSeries&&this.navigatorSeries.setVisible(!0,!1)});B(b,"hide",function(){this.navigatorSeries&&this.navigatorSeries.setVisible(!1,!1)});!1!==this.navigatorOptions.adaptToUpdatedData&&b.xAxis&&B(b,"updatedData",this.updatedDataHandler);B(b,"remove",function(){this.navigatorSeries&&(y(a.series,this.navigatorSeries), +C(this.navigatorSeries.options)&&this.navigatorSeries.remove(!1),delete this.navigatorSeries)})},this)};e.prototype.getBaseSeriesMin=function(a){return this.baseSeries.reduce(function(a,b){return Math.min(a,b.xData?b.xData[0]:a)},a)};e.prototype.modifyNavigatorAxisExtremes=function(){var a=this.xAxis,b;"undefined"!==typeof a.getExtremes&&(!(b=this.getUnionExtremes(!0))||b.dataMin===a.min&&b.dataMax===a.max||(a.min=b.dataMin,a.max=b.dataMax))};e.prototype.modifyBaseAxisExtremes=function(){var a=this.chart.navigator, +b=this.getExtremes(),c=b.dataMin,e=b.dataMax;b=b.max-b.min;var f=a.stickToMin,d=a.stickToMax,g=k(this.options.overscroll,0),l=a.series&&a.series[0],p=!!this.setExtremes;if(!this.eventArgs||"rangeSelectorButton"!==this.eventArgs.trigger){if(f){var q=c;var r=q+b}d&&(r=e+g,f||(q=Math.max(c,r-b,a.getBaseSeriesMin(l&&l.xData?l.xData[0]:-Number.MAX_VALUE))));p&&(f||d)&&m(q)&&(this.min=this.userMin=q,this.max=this.userMax=r)}a.stickToMin=a.stickToMax=null};e.prototype.updatedDataHandler=function(){var a= +this.chart.navigator,b=this.navigatorSeries,c=a.getBaseSeriesMin(this.xData[0]);a.stickToMax=a.reversedExtremes?0===Math.round(a.zoomedMin):Math.round(a.zoomedMax)>=Math.round(a.size);a.stickToMin=m(this.xAxis.min)&&this.xAxis.min<=c&&(!this.chart.fixedRange||!a.stickToMax);b&&!a.hasNavigatorData&&(b.options.pointStart=this.xData[0],b.setData(this.options.data,!1,null,!1))};e.prototype.addChartEvents=function(){this.eventsToUnbind||(this.eventsToUnbind=[]);this.eventsToUnbind.push(B(this.chart,"redraw", +function(){var a=this.navigator,b=a&&(a.baseSeries&&a.baseSeries[0]&&a.baseSeries[0].xAxis||this.xAxis[0]);b&&a.render(b.min,b.max)}),B(this.chart,"getMargins",function(){var a=this.navigator,b=a.opposite?"plotTop":"marginBottom";this.inverted&&(b=a.opposite?"marginRight":"plotLeft");this[b]=(this[b]||0)+(a.navigatorEnabled||!this.inverted?a.outlineHeight:0)+a.navigatorOptions.margin}))};e.prototype.destroy=function(){this.removeEvents();this.xAxis&&(y(this.chart.xAxis,this.xAxis),y(this.chart.axes, +this.xAxis));this.yAxis&&(y(this.chart.yAxis,this.yAxis),y(this.chart.axes,this.yAxis));(this.series||[]).forEach(function(a){a.destroy&&a.destroy()});"series xAxis yAxis shades outline scrollbarTrack scrollbarRifles scrollbarGroup scrollbar navigatorGroup rendered".split(" ").forEach(function(a){this[a]&&this[a].destroy&&this[a].destroy();this[a]=null},this);[this.handles].forEach(function(a){J(a)},this)};return e}();x.Navigator||(x.Navigator=w,t.compose(l),B(H,"beforeShowResetZoom",function(){var a= +this.options,b=a.navigator,e=a.rangeSelector;if((b&&b.enabled||e&&e.enabled)&&(!c&&"x"===a.chart.zoomType||c&&"x"===a.chart.pinchType))return!1}),B(H,"beforeRender",function(){var a=this.options;if(a.navigator.enabled||a.scrollbar.enabled)this.scroller=this.navigator=new w(this)}),B(H,"afterSetChartSize",function(){var a=this.legend,b=this.navigator;if(b){var c=a&&a.options;var e=b.xAxis;var f=b.yAxis;var g=b.scrollbarHeight;this.inverted?(b.left=b.opposite?this.chartWidth-g-b.height:this.spacing[3]+ +g,b.top=this.plotTop+g):(b.left=this.plotLeft+g,b.top=b.navigatorOptions.top||this.chartHeight-b.height-g-this.spacing[2]-(this.rangeSelector&&this.extraBottomMargin?this.rangeSelector.getHeight():0)-(c&&"bottom"===c.verticalAlign&&c.enabled&&!c.floating?a.legendHeight+k(c.margin,10):0)-(this.titleOffset?this.titleOffset[2]:0));e&&f&&(this.inverted?e.options.left=f.options.left=b.left:e.options.top=f.options.top=b.top,e.setAxisSize(),f.setAxisSize())}}),B(H,"update",function(a){var b=a.options.navigator|| +{},c=a.options.scrollbar||{};this.navigator||this.scroller||!b.enabled&&!c.enabled||(u(!0,this.options.navigator,b),u(!0,this.options.scrollbar,c),delete a.options.navigator,delete a.options.scrollbar)}),B(H,"afterUpdate",function(a){this.navigator||this.scroller||!this.options.navigator.enabled&&!this.options.scrollbar.enabled||(this.scroller=this.navigator=new w(this),k(a.redraw,!0)&&this.redraw(a.animation))}),B(H,"afterAddSeries",function(){this.navigator&&this.navigator.setBaseSeries(null,!1)}), +B(r,"afterUpdate",function(){this.chart.navigator&&!this.options.isInternal&&this.chart.navigator.setBaseSeries(null,!1)}),H.prototype.callbacks.push(function(a){var b=a.navigator;b&&a.xAxis[0]&&(a=a.xAxis[0].getExtremes(),b.render(a.min,a.max))}));x.Navigator=w;return x.Navigator});P(x,"masters/modules/gantt.src.js",[],function(){});P(x,"masters/highcharts-gantt.src.js",[x["masters/highcharts.src.js"]],function(l){l.product="Highcharts Gantt";return l});x["masters/highcharts-gantt.src.js"]._modules= +x;return x["masters/highcharts-gantt.src.js"]}); +//# sourceMappingURL=highcharts-gantt.js.map \ No newline at end of file diff --git a/librerias/gantt/code/highcharts-gantt.js.map b/librerias/gantt/code/highcharts-gantt.js.map new file mode 100644 index 0000000..bebf737 --- /dev/null +++ b/librerias/gantt/code/highcharts-gantt.js.map @@ -0,0 +1 @@ +{"version":3,"file":"highcharts-gantt.js.map","lineCount":703,"mappings":"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","sources":["highcharts-gantt.src.js"],"names":["root","factory","module","exports","document","define","amd","Highcharts","error","window","win","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","glob","doc","userAgent","navigator","svg","createElementNS","SVG_NS","createSVGRect","isMS","test","opera","isFirefox","indexOf","isChrome","hasBidiBug","parseInt","split","H","product","version","deg2rad","Math","PI","hasTouch","TouchEvent","isWebKit","isSafari","isTouchDevice","chartCount","seriesTypes","symbolSizes","marginNames","noop","charts","dateFormats","merge","i","arguments","ret","doCopy","copy","original","objectEach","value","key","isObject","isClass","isDOMElement","Array","prototype","slice","call","len","length","strict","isArray","attr","elem","prop","isString","defined","setAttribute","getAttribute","val","pick","arg","getNestedProperty","pathElements","reverse","subProperty","pathElement","pop","timers","H.error","code","stop","chart","params","isCode","isNumber","message","toString","defaultHandler","Error","console","log","additionalMessages_1","encodeURI","fireEvent","Fx","options","dSetter","Fx.prototype.dSetter","paths","start","end","now","startSeg","endSeg","tweenSeg","j","startItem","endItem","push","toD","update","Fx.prototype.update","step","element","style","unit","run","Fx.prototype.run","from","to","self","timer","gotoEnd","stopped","requestAnimationFrame","setTimeout","splice","startTime","Date","pos","curAnim","complete","Object","keys","Fx.prototype.step","t","duration","done","easing","initPath","Fx.prototype.initPath","fromD","prepend","arr","other","fullLength","moveSegment","otherSegment","unshift","isArea","append","segmentToAdd","positionFactor","lowerSegmentToAdd","startX","endX","shift","fillSetter","Fx.prototype.fillSetter","strokeSetter","Fx.prototype.strokeSetter","color","tweenTo","pInt","H.pInt","s","mag","H.isString","H.isArray","str","H.isDOMElement","nodeType","H.isClass","c","constructor","name","H.isNumber","n","isNaN","Infinity","erase","H.erase","item","H.defined","splat","H.splat","syncTimeout","H.syncTimeout","delay","context","internalClearTimeout","clearTimeout","H.clearTimeout","id","extend","H.extend","a","b","css","H.css","el","styles","opacity","filter","createElement","H.createElement","tag","attribs","parent","nopad","padding","border","margin","appendChild","extendClass","H.extendClass","members","pad","H.pad","number","padder","String","replace","join","relativeLength","H.relativeLength","base","offset","parseFloat","wrap","H.wrap","method","func","proceed","outerArgs","ctx","ctx.proceed","format","H.format","splitter","isInside","floatRegex","decRegex","lang","defaultOptions","time","numberFormatter","numberFormat","index","segment","valueAndFormat","decimals","match","decimalPoint","thousandsSep","dateFormat","getMagnitude","H.getMagnitude","num","pow","floor","LN10","normalizeTickInterval","H.normalizeTickInterval","interval","multiples","magnitude","allowDecimals","hasTickAmount","retInterval","normalized","correctFloat","round","stableSort","H.stableSort","sortFunction","sortValue","safeI","sort","arrayMin","H.arrayMin","data","min","arrayMax","H.arrayMax","max","destroyObjectProperties","H.destroyObjectProperties","except","destroy","discardElement","H.discardElement","garbageBin","innerHTML","H.correctFloat","prec","toPrecision","setAnimation","H.setAnimation","animation","renderer","globalAnimation","animObject","H.animObject","timeUnits","millisecond","second","minute","hour","day","week","month","year","H.numberFormat","origDec","exponent","fractionDigits","toExponential","toFixed","roundedNumber","abs","strinteger","thousands","substr","easeInOutSine","Math.easeInOutSine","cos","getStyle","H.getStyle","toInt","offsetWidth","scrollWidth","boundingClientRectWidth","getBoundingClientRect","width","offsetHeight","scrollHeight","getComputedStyle","undefined","getPropertyValue","inArray","H.inArray","fromIndex","find","callback","H.offset","docElem","documentElement","box","parentElement","parentNode","top","left","pageYOffset","scrollTop","clientTop","pageXOffset","scrollLeft","clientLeft","H.stop","H.objectEach","map","each","grep","reduce","some","addEvent","H.addEvent","type","addEventListener","addEventListenerPolyfill","events","protoEvents","hcEvents","Point","series","runTrackerClick","eventObject","order","removeEvent","H.removeEvent","removeOneEvent","removeEventListener","removeEventListenerPolyfill","removeAllEvents","eventCollection","nodeName","types","forEach","coll","eventElem","H.fireEvent","eventArguments","defaultFunction","createEvent","dispatchEvent","e","initEvent","target","preventDefault","defaultPrevented","fireInOrder","iA","iB","animate","H.animate","opt","fx","d","pathArray","seriesType","H.seriesType","props","pointProps","getOptions","plotOptions","pointClass","uniqueKey","uniqueKeyHash","random","substring","idCounter","isFunction","H.isFunction","jQuery","highcharts","win.jQuery.fn.highcharts","utilitiesModule","clamp","U","Color","input","parsers","regex","parse","result","rgba","init","Color.parse","Color.prototype.init","names","toLowerCase","stops","charAt","parser","exec","get","Color.prototype.get","concat","brighten","Color.prototype.brighten","alpha","setOpacity","Color.prototype.setOpacity","Color.prototype.tweenTo","fromRgba","toRgba","hasAlpha","white","black","SVGElement","height","symbolCustomAttribs","textProps","_defaultGetter","SVGElement.prototype._defaultGetter","_defaultSetter","SVGElement.prototype._defaultSetter","add","SVGElement.prototype.add","parentGroup","parentInverted","inverted","textStr","buildText","added","handleZ","zIndex","inserted","zIndexSetter","onAdd","addClass","SVGElement.prototype.addClass","className","currentClassName","newClassName","afterSetters","SVGElement.prototype.afterSetters","doTransform","updateTransform","align","SVGElement.prototype.align","alignOptions","alignByTranslate","alignedObjects","alignFactor","vAlignFactor","alignTo","vAlign","verticalAlign","x","y","placed","alignAttr","alignSetter","SVGElement.prototype.alignSetter","convert","center","right","alignValue","SVGElement.prototype.animate","animOptions","hidden","msHidden","webkitHidden","applyTextOutline","SVGElement.prototype.applyTextOutline","textOutline","strokeWidth","getContrast","fill","fakeTS","tspans","getElementsByTagName","ySetter","xSetter","digit","removeTextOutline","isRTL_1","textContent","firstRealChild","firstChild","tspan","clone","cloneNode","stroke","insertBefore","whitespace","SVGElement.prototype.attr","hash","continueAnimation","hasSetSymbolSize","skipAttr","setter","eachAttribute","symbolName","symbolAttr","rotation","styledMode","shadows","updateShadows","clip","SVGElement.prototype.clip","clipRect","url","crisp","SVGElement.prototype.crisp","rect","normalizer","wrapper","complexColor","SVGElement.prototype.complexColor","colorOptions","colorObject","gradName","gradAttr","radAttr","gradients","stopColor","stopOpacity","radialReference","radialGradient","linearGradient","x1","y1","x2","y2","gradientUnits","getRadialAttr","gradientObject_1","defs","stopObject","gradient","colorOptions.toString","SVGElement.prototype.css","oldStyles","newStyles","serializedCss","hasNew","svgPseudoProps","textWidth","forExport","namespaceURI","hyphenate","dashstyleSetter","SVGElement.prototype.dashstyleSetter","v","NaN","SVGElement.prototype.destroy","parentToClean","isSVG","ownerSVGElement","onclick","onmouseout","onmouseover","onmousemove","point","clipPath","clipPath_1","querySelectorAll","clipPathAttr","removeAttribute","safeRemoveChild","destroyShadows","div","childNodes","grandParent","SVGElement.prototype.destroyShadows","shadow","destroyTextPath","SVGElement.prototype.destroyTextPath","textElement","textPathWrapper","removeChild","SVGElement.prototype.dSetter","pathToSegments","acc","seg","fadeOut","SVGElement.prototype.fadeOut","elemWrapper","hide","SVGElement.prototype.fillSetter","getBBox","SVGElement.prototype.getBBox","reload","rot","bBox","cache","cacheKeys","fontSize","cacheKey","textOverflow","fontWeight","toggleTextShadowShim","display","htmlGetBBox","rad","sin","SVGElement.prototype.getStyle","hasClass","SVGElement.prototype.hasClass","SVGElement.prototype.hide","hideByTranslation","visibility","SVGElement.prototype.htmlGetBBox","SVGElement.prototype.init","invert","SVGElement.prototype.invert","on","SVGElement.prototype.on","eventType","handler","svgElement","touchEventFired","ontouchstart","element.ontouchstart","touches","clientX","clientY","ontouchend","element.ontouchend","sqrt","changedTouches","element.onclick","opacitySetter","SVGElement.prototype.opacitySetter","removeClass","SVGElement.prototype.removeClass","RegExp","SVGElement.prototype.removeTextOutline","SVGElement.prototype.safeRemoveChild","setRadialReference","SVGElement.prototype.setRadialReference","coordinates","existingGradient","setTextPath","SVGElement.prototype.setTextPath","textPathOptions","attribsMap","textAnchor","adder","firstTime","enabled","attributes","dy","startOffset","attrs","dx","textPathElement","textPathId","text","setAttributeNS","SVGElement.prototype.shadow","shadowOptions","group","cutOff","oldShadowOptions","defaultShadowOptions","offsetX","offsetY","shadowElementOpacity","transform","cutHeight","show","SVGElement.prototype.show","inherit","SVGElement.prototype.strokeSetter","hasStroke","SVGElement.prototype.strokeWidth","dummy","SVGElement.prototype.symbolAttr","symbols","textSetter","SVGElement.prototype.textSetter","textPxLength","titleSetter","SVGElement.prototype.titleSetter","titleNode","createTextNode","toFront","SVGElement.prototype.toFront","translate","SVGElement.prototype.translate","translateX","translateY","SVGElement.prototype.updateShadows","SVGElement.prototype.updateTransform","scaleX","scaleY","matrix","rotationOriginX","rotationOriginY","visibilitySetter","SVGElement.prototype.visibilitySetter","xGetter","SVGElement.prototype.xGetter","SVGElement.prototype.zIndexSetter","svgParent","otherElement","otherZIndex","undefinedOtherZIndex","yGetter","matrixSetter","rotationOriginXSetter","rotationOriginYSetter","rotationSetter","scaleXSetter","scaleYSetter","translateXSetter","translateYSetter","verticalAlignSetter","SVGElement.prototype.verticalAlignSetter","SVGRenderer","H.SVGRenderer","Element","container","allowHTML","boxWrapper","location","href","desc","imgCount","setSize","subPixelFix","ceil","unSubPixelFix","definition","def","recurse","config","node","ren","tagName","children","fontFamily","setStyle","isHidden","rendererDefs","draw","cx","cy","r","truncate","words","startAt","getString","minIndex","maxIndex","currentIndex","lengths","updateTSpan","getSubStringLength","charEnd","concatenatedEnd","getSpanWidth","truncated","actualWidth","escapes","textNode","hasMarkup","parentX","textStyles","textLineHeight","lineHeight","ellipsis","noWrap","whiteSpace","isSubsequentLine","tempParent","getLineHeight","fontSizeStyle","fontMetrics","h","unescapeEntities","inputStr","parseAttribute","delimiter","regexMatchBreaks","textCache","lines","line","lineNo","spanNo","lineLength","spans","buildTextSpans","span","classAttribute","hrefAttribute","styleAttribute","cursor","hasWhiteSpace","wrapLineNo","button","normalState","hoverState","pressedState","disabledState","shape","useHTML","label","curState","normalStyle","hoverStyle","pressedStyle","disabledStyle","setState","label.setState","state","crispLine","points","roundingFunction","circle","wrapper.ySetter","arc","innerR","symbol","rSetter","wrapper.rSetter","rx","ry","rGetter","wrapper.rGetter","viewBox","g","image","src","onload","preserveAspectRatio","setSVGImageSource","onDummyLoad","Image","imageRegex","isImage","sym","symbolFn","imageSrc","imgwidth","imgheight","centerImage","imgSize","trans","backgroundSize","isImg","chartIndex","position","body","hasLoaded","w","open","square","triangle","triangle-down","diamond","proximity","innerRadius","cosStart","sinStart","cosEnd","sinEnd","longArc","clockwise","callout","safeDistance","halfDistance","anchorX","anchorY","arrowLength","count","html","wrapper.xSetter","parentVal","baseline","f","rotCorr","alterY","commandLength","A","C","L","M","Q","S","T","V","toUpperCase","emptyBBox","paddingLeft","wrapperX","wrapperY","textAlign","deferredAttr","baselineOffset","hasBGImage","needsBox","getCrispAdjust","updateBoxSize","crispAdjust","updateTextPadding","textX","textY","hasBoxWidthChanged","boxAttr","wrapper.onAdd","widthSetter","wrapper.widthSetter","heightSetter","wrapper.heightSetter","paddingSetter","wrapper.paddingSetter","paddingLeftSetter","wrapper.paddingLeftSetter","wrapper.alignSetter","wrapper.textSetter","anchorXSetter","wrapper.anchorXSetter","anchorYSetter","wrapper.anchorYSetter","isLabel","baseCss","wrapperExtension","isFontStyle","wrapper.on","selectiveHandler","relatedTarget","contains","wrapperExtension.shadow","Renderer","htmlCss","isSettingWidth","overflow","htmlUpdateTransform","offsetLeft","offsetTop","alignCorrection","marginLeft","marginTop","child","invertChild","currentTextTransform","innerText","oldTextWidth","cTT","oldRotation","oldAlign","setSpanRotation","getSpanCorrection","xCorr","yCorr","alignOnAdd","rotationStyle","cssTransformKey","getTransformKey","transformOrigin","addSetters","gWrapper","styleObject","addedSetters","wrapper.rotationSetter","wrapper.afterSetters","wrapper.add","svgGroupWrapper","parents","htmlGroup","translateSetter","htmlGroupStyle","cls","pointerEvents","classSetter","Tick","axis","noLabel","parameters","isNewLabel","isNew","tickmarkOffset","addLabel","Tick.prototype.addLabel","tick","categories","logarithmic","labelOptions","labels","tickPositions","isFirst","isLast","category","animateLabels","tickInterval","tickPositionInfo","info","list","dateTime","dateTimeLabelFormats","resolveDTLFormat","grid","higherRanks","unitName","dateTimeLabelFormat","main","formatCtx","lin2log","labelFormatter","shortenLabel","tick.shortenLabel","getSlotWidth","_addedPlotLB","isXAxis","moveLabel","movedLabel","createLabel","Tick.prototype.createLabel","xy","labelGroup","Tick.prototype.destroy","getPosition","Tick.prototype.getPosition","horiz","tickPos","old","cHeight","oldChartHeight","chartHeight","transB","opposite","oldChartWidth","chartWidth","bottom","getLabelPosition","Tick.prototype.getLabelPosition","transA","reversed","isLinked","linkedParent","staggerLines","tickRotCorr","yOffset","labelOffsetCorrection","reserveSpaceDefault","labelOffset","labelAlign","side","getLabelSize","Tick.prototype.getLabelSize","getMarkPath","Tick.prototype.getMarkPath","tickLength","tickWidth","handleOverflow","Tick.prototype.handleOverflow","pxPos","spacing","leftBound","labelLeft","rightBound","labelRight","isRadial","factor","labelWidth","slotWidth","modifiedSlotWidth","goRight","rightPos","autoRotation","Tick.prototype.moveLabel","moved","xAxis","ticks","currentTick","labelPos","xPos","yPos","render","Tick.prototype.render","reverseCrisp","isActive","renderGridLine","renderMark","renderLabel","Tick.prototype.renderGridLine","gridLine","gridPrefix","gridLineWidth","gridLineColor","dashStyle","dashstyle","gridGroup","gridLinePath","getPlotLinePath","lineWidth","force","Tick.prototype.renderMark","tickPrefix","tickSize","mark","isNewMark","tickColor","axisGroup","Tick.prototype.renderLabel","showFirstLabel","showLastLabel","replaceMovedLabel","Tick.prototype.replaceMovedLabel","isDirty","Time","variableTimezone","useUTC","getTimezoneOffset","timezoneOffsetFunction","Time.prototype.get","date","timezoneOffset","realMs","getTime","ms","setTime","set","Time.prototype.set","newOffset","Time.prototype.update","timezone","makeTime","Time.prototype.makeTime","hours","minutes","seconds","UTC","Time.prototype.timezoneOffsetFunction","moment","timestamp","tz","utcOffset","valueOf","Time.prototype.dateFormat","capitalize","_a","invalidDate","dayOfMonth","fullYear","langWeekdays","weekdays","shortWeekdays","replacements","shortMonths","B","months","m","o","Y","k","I","l","p","P","getSeconds","Time.prototype.resolveDTLFormat","getTimeTicks","Time.prototype.getTimeTicks","normalizedInterval","startOfWeek","minDate","unitRange","variableDayLength","minYear","minDay","minMonth","minDateDate","minHours","totalRange","colors","loading","numericSymbols","resetZoom","resetZoomTitle","global","borderRadius","colorCount","defaultSeriesType","ignoreHiddenSeries","resetZoomButton","theme","borderColor","backgroundColor","plotBorderColor","title","widthAdjust","subtitle","caption","legend","alignColumns","layout","navigation","activeColor","inactiveColor","itemStyle","itemHoverStyle","itemHiddenStyle","itemCheckboxStyle","squareSymbol","symbolPadding","labelStyle","tooltip","footerFormat","snap","headerFormat","pointFormat","borderWidth","credits","setOptions","H.setOptions","H.getOptions","defaultPlotOptions","H.dateFormat","Axis","userOptions","zoomEnabled","visible","translationSlope","tickAmount","positiveValuesOnly","pointRangePadding","pointRange","plotLinesAndBandsGroups","plotLinesAndBands","paddedTicks","overlap","oldMin","oldMax","minPixelPadding","minorTicks","minorTickInterval","maxLabelLength","labelEdge","hasVisibleSeries","hasNames","closestPointRange","alternateBands","Axis.prototype.init","isX","isZAxis","formatter","defaultLabelFormatter","allowNegativeLog","linkedTo","minRange","userMinRange","maxZoom","range","crosshair","crosshairs","axes","labelRotation","event","Axis.prototype.setOptions","defaultYAxisOptions","defaultTopAxisOptions","defaultRightAxisOptions","defaultBottomAxisOptions","defaultLeftAxisOptions","Axis.prototype.defaultLabelFormatter","numSymMagnitude","numericSymbolMagnitude","formatOption","numericSymbolDetector","multi","getSeriesExtremes","Axis.prototype.getSeriesExtremes","xExtremes","dataMin","dataMax","threshold","softThreshold","stacking","buildStacks","seriesOptions","xData","getXExtremes","seriesDataMin","seriesDataMax","dataExtremes","applyExtremes","Axis.prototype.translate","backwards","cvsCoord","handleLog","pointPlacement","sign","cvsOffset","localA","oldTransA","localMin","doPostTranslate","isOrdinal","brokenAxis","hasBreaks","lin2val","sector","returnValue","val2lin","toPixels","Axis.prototype.toPixels","paneCoordinates","toValue","Axis.prototype.toValue","pixel","Axis.prototype.getPlotLinePath","between","skip","axisLeft","axisTop","translatedValue","cWidth","evt","acrossPanes","getLinearTickPositions","Axis.prototype.getLinearTickPositions","roundedMin","roundedMax","precision","single","lastPos","getMinorTickInterval","Axis.prototype.getMinorTickInterval","getMinorTickPositions","Axis.prototype.getMinorTickPositions","minorTickPositions","logarithmic_1","_pos","getLogTickPositions","normalizeTimeTickInterval","trimTicks","adjustForMinRange","Axis.prototype.adjustForMinRange","closestDataRange","distance","loopLength","xIncrement","spaceAvailable","zoomOffset","minArgs","log2lin","maxArgs","getClosest","Axis.prototype.getClosest","seriesClosest","noSharedTooltip","nameToX","Axis.prototype.nameToX","explicitCategories","nameX","requireSorting","uniqueNames","autoIncrement","updateNames","Axis.prototype.updateNames","isDirtyData","processData","generatePoints","setAxisTranslation","Axis.prototype.setAxisTranslation","saveOld","axisPointRange","minPointOffset","hasCategories","seriesPointRange","isPointPlacementAxis","is","ordinalCorrection","ordinal","slope","staticScale","minFromRange","Axis.prototype.minFromRange","setTickInterval","Axis.prototype.setTickInterval","secondPass","maxPadding","minPadding","tickIntervalOption","tickPixelIntervalOption","tickPixelInterval","getTickAmount","hardMin","userMin","hardMax","userMax","linkedParentExtremes","getExtremes","thresholdMin","thresholdMax","beforePadding","usePercentage","softMin","softMax","ceiling","beforeSetTickPositions","postProcessTickInterval","minTickInterval","unsquish","setTickPositions","Axis.prototype.setTickPositions","tickPositionsOption","minorTickIntervalOption","tickPositioner","hasVerticalPanning","isColorAxis","startOnTick","endOnTick","tickmarkPlacement","positions","units","adjustTickAmount","Axis.prototype.trimTicks","alignToOthers","Axis.prototype.alignToOthers","others","hasOther","alignTicks","otherOptions","pane","Axis.prototype.getTickAmount","finalTickAmt","Axis.prototype.adjustTickAmount","axisOptions","currentTickAmount","hasData","setScale","Axis.prototype.setScale","isDirtyAxisLength","isXAxisDirty","oldAxisLength","setAxisSize","forceRedraw","oldUserMin","oldUserMax","resetStacks","cleanStacks","panningState","setExtremes","Axis.prototype.setExtremes","newMin","newMax","redraw","serie","kdTree","eventArgs","zoom","Axis.prototype.zoom","allowZoomOutside","displayBtn","trigger","zoomed","Axis.prototype.setAxisSize","offsets","plotWidth","plotHeight","plotTop","plotLeft","Axis.prototype.getExtremes","getThreshold","Axis.prototype.getThreshold","realMin","realMax","autoLabelAlign","Axis.prototype.autoLabelAlign","angle","Axis.prototype.tickSize","prefix","labelMetrics","Axis.prototype.labelMetrics","Axis.prototype.unsquish","newTickInterval","slotSize","rotationOption","bestScore","Number","MAX_VALUE","getStep","spaceNeeded","autoRotationLimit","score","Axis.prototype.getSlotWidth","slotCount","cssWidth","renderUnsquish","Axis.prototype.renderUnsquish","labelStyleOptions","innerWidth","textOverflowOption","commonWidth","commonTextOverflow","specificTextOverflow","widthOption","Axis.prototype.hasData","showEmpty","addTitle","Axis.prototype.addTitle","axisTitleOptions","axisTitle","low","middle","high","generateTick","Axis.prototype.generateTick","getOffset","Axis.prototype.getOffset","invertedSide","showAxis","titleOffset","titleMargin","axisOffset","clipOffset","directionFactor","axisParent","gridZIndex","reserveSpace","titleOffsetOption","renderLine","lineHeightCorrection","labelOffsetPadded","axisTitleMargin","getMaxLabelDimensions","maxLabelDimensions","axisLine","getLinePath","Axis.prototype.getLinePath","lineLeft","lineTop","Axis.prototype.renderLine","lineColor","getTitlePosition","Axis.prototype.getTitlePosition","axisLength","xOption","yOption","textHeightOvershoot","alongAxis","offAxis","titlePosition","renderMinorTick","Axis.prototype.renderMinorTick","slideInTicks","hasRendered","renderTick","Axis.prototype.renderTick","Axis.prototype.render","stackLabelOptions","stackLabels","alternateGridColor","polar","PlotLineOrBand","plotLines","plotBands","plotLineOptions","addPlotBandOrLine","forDestruction","destroyInactiveItems","isPlaced","titleXy","renderStackTotals","Axis.prototype.redraw","plotLine","getKeepProps","Axis.prototype.getKeepProps","keepProps","Axis.prototype.destroy","keepEvents","plotGroup","drawCrosshair","Axis.prototype.drawCrosshair","graphic","cross","crosshairPos","plotX","plotY","chartX","chartY","crossOptions","stackY","isCrosshair","hideCrosshair","categorized","Axis.prototype.hideCrosshair","Axis.prototype.hasVerticalPanning","_b","panning","indentation","minorTickLength","minorTickPosition","tickPosition","minorGridLineColor","minorGridLineWidth","minorTickColor","allowOverlap","crop","total","DateTimeAxisAdditions","DateTimeAxisAdditions.prototype.normalizeTimeTickInterval","unitsOption","DateTimeAxis","compose","DateTimeAxis.compose","AxisClass","axisProto.getTimeTicks","AdditionsClass","LogarithmicAxisAdditions","LogarithmicAxisAdditions.prototype.getLogTickPositions","minor","minorAutoInterval","break2","intermediate","filteredTickIntervalOption","totalPixelLength","LogarithmicAxisAdditions.prototype.lin2log","LogarithmicAxisAdditions.prototype.log2lin","LogarithmicAxis","LogarithmicAxis.compose","axisProto","logAxisProto","bind","axis.lin2val","axis.val2lin","PlotLineOrBand.prototype.render","optionsLabel","isBand","isLine","svgElem","groupAttribs","groupName","getPlotBandPath","isFlat","PlotLineOrBand.prototype.renderLabel","labelText","getLabelText","xBounds","yBounds","PlotLineOrBand.prototype.getLabelText","PlotLineOrBand.prototype.destroy","toPath","plus","outside","pathStart","pathEnd","toPathStart","toPathEnd","addPlotBand","addPlotLine","updatedOptions","removePlotBandOrLine","removePlotBand","removePlotLine","Tooltip","isSticky","applyFilter","Tooltip.prototype.applyFilter","stdDeviation","bodyFormatter","Tooltip.prototype.bodyFormatter","items","tooltipOptions","formatPrefix","tooltipFormatter","cleanSplit","Tooltip.prototype.cleanSplit","tt","defaultFormatter","Tooltip.prototype.defaultFormatter","tooltipFooterHeaderFormatter","Tooltip.prototype.destroy","hideTimer","tooltipTimeout","getAnchor","Tooltip.prototype.getAnchor","mouseEvent","pointer","yAxis","followPointer","normalize","tooltipPos","plotLow","plotHigh","shared","getDateFormat","Tooltip.prototype.getDateFormat","dateStr","strpos","lastN","blank","getLabel","Tooltip.prototype.getLabel","stickOnContact","onMouseEnter","inContact","onMouseLeave","hoverSeries","onMouseOut","this.label.xSetter","this.label.ySetter","Tooltip.prototype.getPosition","boxWidth","boxHeight","swapped","outerWidth","clientWidth","outerHeight","clientHeight","chartPosition","getChartPosition","containerScaling","buildDimensionArray","dim","first","preferFarSide","ttBelow","negative","firstDimension","outerSize","innerSize","scaledInnerSize","scaledDist","scaleDiff","roomLeft","roomRight","alignedLeft","alignedRight","secondDimension","retVal","swap","temp","getXDateFormat","Tooltip.prototype.getXDateFormat","xDateFormat","Tooltip.prototype.hide","hideDelay","Tooltip.prototype.init","scrollablePixelsX","scrollablePixelsY","isStickyOnContact","Tooltip.prototype.isStickyOnContact","move","Tooltip.prototype.move","skipAnchor","drawTracker","refresh","Tooltip.prototype.refresh","pointOrPoints","textConfig","pointConfig","anchor","getLabelConfig","applyInactiveState","currentSeries","renderSplit","spacingBox","colorIndex","updatePosition","Tooltip.prototype.renderSplit","defaultPositioner","isHeader","headerTop","adjustedPlotHeight","bounds","distributionBoxTop","_c","scrollingContainer","_d","positioner","tooltipLabel","headerHeight","boxes","owner","colorClass","size","boxPosition","rank","distribute","_e","Tooltip.prototype.drawTracker","tracker","hoverPoint","anchorPos","labelBBox","styledModeFormat","Tooltip.prototype.styledModeFormat","formatString","Tooltip.prototype.tooltipFooterHeaderFormatter","labelConfig","isFooter","footOrHead","isDateTime","tooltipDateKeys","Tooltip.prototype.update","Tooltip.prototype.updatePosition","Pointer","lastValidTouch","pinchDown","runChartClick","hasDragged","unbindContainerMouseLeave","this.unbindContainerMouseLeave","Pointer.prototype.applyInactiveState","activeSeries","linkedSeries","navigatorSeries","inactiveSeries","inactiveOtherPoints","setAllPointsToState","Pointer.prototype.destroy","unDocMouseMove","unbindDocumentMouseUp","unbindDocumentTouchEnd","clearInterval","drag","Pointer.prototype.drag","chartOptions","zoomHor","zoomVert","selectionMarker","mouseDownX","mouseDownY","panningEnabled","panKey","touch","clickedInside","isInsidePlot","hasCartesianSeries","zoomX","zoomY","selectionMarkerFill","pan","dragStart","Pointer.prototype.dragStart","mouseIsDown","cancelClick","drop","Pointer.prototype.drop","hasPinched","selectionData","originalEvent","selectionBox","selectionLeft","selectionTop","selectionWidth","selectionHeight","runZoom","selectionMin","selectionMax","scaleGroups","_cursor","findNearestKDPoint","Pointer.prototype.findNearestKDPoint","closest","compareX","findNearestPointBy","searchPoint","isCloserX","p1","distX","p2","isCloser","dist","isAbove","getChartCoordinatesFromPoint","Pointer.prototype.getChartCoordinatesFromPoint","shapeArgs","Pointer.prototype.getChartPosition","getCoordinates","Pointer.prototype.getCoordinates","getHoverData","Pointer.prototype.getHoverData","existingHoverPoint","existingHoverSeries","isDirectTouch","hoverPoints","useExisting","notSticky","stickyTracking","searchSeries","directTouch","enableMouseTracking","isNull","isBoosting","getPoint","getPointFromEvent","Pointer.prototype.getPointFromEvent","onTrackerMouseOut","Pointer.prototype.onTrackerMouseOut","toElement","inClass","Pointer.prototype.inClass","elemClassName","Pointer.prototype.init","click","followTouchMove","setDOMEvents","Pointer.prototype.normalize","ePos","pageX","pageY","onContainerClick","Pointer.prototype.onContainerClick","pEvt","firePointEvent","onContainerMouseDown","Pointer.prototype.onContainerMouseDown","onContainerMouseMove","buttons","zoomOption","onContainerMouseLeave","Pointer.prototype.onContainerMouseLeave","hoverChartIndex","reset","Pointer.prototype.onContainerMouseMove","setHoverChartIndex","openMenu","runPointActions","onDocumentTouchEnd","Pointer.prototype.onDocumentTouchEnd","onContainerTouchMove","Pointer.prototype.onContainerTouchMove","onContainerTouchStart","Pointer.prototype.onContainerTouchStart","onDocumentMouseMove","Pointer.prototype.onDocumentMouseMove","onDocumentMouseUp","Pointer.prototype.onDocumentMouseUp","pinch","Pointer.prototype.pinch","touchesLength","hasZoom","fireClickEvent","initiated","absMax","absMin","res","plotBox","pinchTranslate","Pointer.prototype.pinchTranslate","pinchTranslateDirection","Pointer.prototype.pinchTranslateDirection","forcedScale","XY","sChartXY","wh","plotLeftTop","selectionWH","clipXY","scale","singleTouch","touch0Start","touch0Now","touch1Start","touch1Now","selectionXY","outOfBounds","transformScale","scaleKey","Pointer.prototype.reset","allowMove","tooltipPoints","isCartesian","hoverX","Pointer.prototype.runPointActions","hoverData","useSharedTooltip","onMouseOver","ownerDocument","drawAxisCrosshair","Pointer.prototype.scaleGroups","seriesAttribs","getPlotBox","markerGroup","dataLabelsGroup","clipBox","Pointer.prototype.setDOMEvents","ownerDoc","onmousedown","Pointer.prototype.setHoverChartIndex","hoverChart","Pointer.prototype.touch","hasMoved","Pointer.prototype.zoomOption","zoomType","pinchType","getWebkitTouches","fake","fake.item","translateMSPointer","wktype","pointerType","MSPOINTER_TYPE_TOUCH","currentTarget","__extends","extendStatics","setPrototypeOf","__proto__","__","create","hasPointerEvent","PointerEvent","_super","MSPointer","batchMSEvents","MSPointer.prototype.batchMSEvents","onContainerPointerDown","onContainerPointerMove","onDocumentPointerUp","MSPointer.prototype.destroy","MSPointer.prototype.init","MSPointer.prototype.onContainerPointerDown","pointerId","MSPointer.prototype.onContainerPointerMove","MSPointer.prototype.onDocumentPointerUp","MSPointer.prototype.setDOMEvents","Legend","allItems","contentGroup","maxLegendWidth","maxItemWidth","legendWidth","legendHeight","lastLineHeight","lastItemY","itemY","itemX","itemMarginTop","itemMarginBottom","itemHeight","initialItemY","pages","proximate","scrollGroup","totalItemWidth","titleHeight","symbolWidth","symbolHeight","Legend.prototype.init","positionCheckboxes","unchartrender","proximatePositions","positionItems","Legend.prototype.setOptions","Legend.prototype.update","isDirtyLegend","isDirtyBox","colorizeItem","Legend.prototype.colorizeItem","legendGroup","legendItem","legendLine","legendSymbol","hiddenColor","textColor","symbolColor","markerOptions","marker","isMarker","pointAttribs","Legend.prototype.positionItems","positionItem","isResizing","Legend.prototype.positionItem","ltr","rtl","legendItemPos","_legendItemPos","checkbox","destroyItem","Legend.prototype.destroyItem","Legend.prototype.destroy","destroyItems","getAllItems","Legend.prototype.positionCheckboxes","clipHeight","scrollOffset","checkboxOffset","renderTitle","Legend.prototype.renderTitle","titleOptions","setText","Legend.prototype.setText","labelFormat","renderItem","Legend.prototype.renderItem","itemDistance","li","isSeries","drawLegendSymbol","showCheckbox","createCheckboxForItem","itemExtraWidth","itemClassName","setItemEvents","itemWidth","legendItemWidth","legendItemHeight","layoutItem","Legend.prototype.layoutItem","horizontal","Legend.prototype.getAllItems","showInLegend","legendItems","legendType","getAlignment","Legend.prototype.getAlignment","floating","adjustMargins","Legend.prototype.adjustMargins","alignment","alignments","Legend.prototype.proximatePositions","alignLeft","useFirstPoint","lastPoint","Legend.prototype.render","allowedWidth","legendIndex","Legend.prototype.align","Legend.prototype.handleOverflow","optionsY","spaceHeight","maxHeight","navOptions","arrowSize","nav","lastY","clipToHeight","addTracker","currentPage","fullHeight","pageIx","up","scroll","pager","down","Legend.prototype.scroll","scrollBy","_this","pageCount","upTracker","downTracker","runPositionItem","bubbleLegend","Chart","H.Chart","getArgs","H.chart","callbacks","renderTo","userPlotOptions","optionsChart","typeOptions","chartEvents","labelCollectors","showAxes","pointCount","colorCounter","symbolCounter","firstRender","initSeries","Constr","missingModuleFor","setSeriesData","getSeriesOrderByLinks","enabledDataSorting","setData","orderSeries","getName","legendUserOptions","redrawLegend","isHiddenChart","afterRedraw","setResponsive","temporaryDisplay","layOutTitles","hasStackedSeries","hasDirtyStacks","updateTotals","getStacks","getMargins","extKey","drawChartBox","itemById","getAxes","xAxisOptions","yAxisOptions","optionsArray","getSelectedPoints","getPointsCollection","selectedStaging","selected","getSelectedSeries","setTitle","subtitleOptions","applyDescription","explicitOptions","isStock","elem.update","updateOptions","titleSize","requiresDirtyBox","getChartSize","heightOption","containerWidth","containerHeight","revert","hcOrigStyle","hcOrigDetached","hcOricDetached","tempStyle","setProperty","setClassName","getContainer","containerId","containerStyle","getElementById","oldChartIndex","indexAttrName","skipClone","exporting","skipAxes","resetMargins","marginBottom","getAxisMargins","colorAxis","setChartSize","reflow","hasUserSize","isPrinting","reflowTimeout","setReflow","unbindReflow","marginRight","plotSizeX","plotSizeY","plotBorderWidth","clipX","clipY","splashArrays","values","sideName","chartBackground","plotBackground","plotBorder","plotBGImage","chartBackgroundColor","plotBackgroundColor","plotBackgroundImage","mgn","verb","chartBorderWidth","bgAttr","plotShadow","propFromSeries","klass","linkSeries","chartSeries","setDataSortingOptions","renderSeries","renderLabels","correction","renderAxes","tempWidth","tempHeight","redoHorizontal","redoVertical","seriesGroup","addCredits","updateContainerScaling","mapCredits","this.credits.update","bb","scroller","isReadyToRender","serieOptions","MSPointerEvent","scrollablePlotArea","scrollableMinWidth","minWidth","scrollableMinHeight","minHeight","corrections","axis.getPlotLinePath","marginName","setUpScrolling","applyFixed","fixedDiv","Chart.prototype.setUpScrolling","WebkitOverflowScrolling","overflowX","overflowY","innerContainer","moveFixedElements","Chart.prototype.moveFixedElements","fixedRenderer","fixedSelectors","axisClass","Chart.prototype.applyFixed","scrollableOptions","scrollableMask","scrollableWidth","scrollableHeight","scrollPositionX","scrollPositionY","maskTop","maskLeft","maskBottom","maskRight","maskPlotRight","maskPlotBottom","redrawTrigger","StackingAxisAdditions","oldStacks","stacks","stacksTouched","StackingAxisAdditions.prototype.buildStacks","axisSeries","reversedStacks","actualSeries","setStackedPoints","modifyStacks","StackingAxisAdditions.prototype.cleanStacks","stack","cumulative","StackingAxisAdditions.prototype.resetStacks","touched","StackingAxisAdditions.prototype.renderStackTotals","stackTotalGroup","StackingAxis","StackingAxis.compose","onInit","onDestroy","StackingAxis.onDestroy","stackKey","StackingAxis.onInit","LegendSymbolMixin","drawRectangle","symbolRadius","drawLineMarker","generalRadius","legendItemGroup","verticalCenter","radius","percentage","animateBeforeDestroy","Point.prototype.animateBeforeDestroy","animateParams","startXPos","isDataLabel","graphicalProps","getGraphicalProps","singular","startYPos","plural","applyOptions","Point.prototype.applyOptions","pointValKey","optionsToObject","dataLabels","isValid","Point.prototype.destroy","destroyPoint","dataLabel","destroyElements","dataSorting","Point.prototype.destroyElements","kinds","Point.prototype.firePointEvent","importEvents","allowPointSelect","select","ctrlKey","metaKey","shiftKey","getClassName","Point.prototype.getClassName","zone","Point.prototype.getGraphicalProps","Point.prototype.getLabelConfig","stackTotal","Point.prototype.getNestedProperty","getZone","Point.prototype.getZone","zones","zoneAxis","nonZonedColor","hasNewShapeType","Point.prototype.hasNewShapeType","shapeType","Point.prototype.init","resolveColor","Point.prototype.optionsToObject","pointArrayMap","valueCount","firstItemType","setNestedProperty","_hasPointLabels","_hasPointMarkers","Point.prototype.resolveColor","colorByPoint","Point.prototype.setNestedProperty","object","nestedKeys","Point.prototype.tooltipFormatter","seriesTooltipOptions","valueDecimals","valuePrefix","valueSuffix","Series","enabledThreshold","states","normal","hover","radiusPlus","lineWidthPlus","fillColor","cropThreshold","halo","inactive","turboThreshold","axisTypes","cropShoulder","eventsToUnbind","parallelArrays","sorted","lastSeries","eventOptions","bindAxes","getColor","getSymbol","_i","insert","collection","indexOption","AXIS","optionalAxis","updateParallelArrays","toYData","yData","pointInterval","pointIntervalUnit","pointStart","allowDG","itemOptions","seriesUserOptions","negativeColor","negativeFillColor","getCyclic","defaults","indexName","counterName","setting","hasGroupedData","findPointIndex","optionsObject","oldData","matchedById","matchingPoint","matchKey","matchByName","oldPoint","pointIndex","cropped","cropStart","updateData","pointsToAdd","hasUpdatedByKey","lastIndex","equalLength","succeeded","pointOptions","hasDerivedData","remove","addPoint","updatePoints","oldDataLength","dataLength","firstPoint","indexOfX","indexOfY","updatedData","sortData","isSeriesBoosting","getFirstValidPoint","pt","sortKey","getPointOptionsObject","sortedData","aValue","bValue","seriesData","getProcessedData","forceExtremesFromAll","processedXData","processedYData","getExtremesFromAll","isLog","throwOnUnsorted","forceCrop","croppedData","cropData","processedData","basePointRange","cropEnd","dataOptions","PointClass","processedDataLength","dataGroup","groupMap","activeYData","activeCounter","xMin","xMax","shoulder","stackedYData","yDataLength","validValue","withinRange","hasModifyValue","modifyValue","pointPlacementToXValue","dynamicallyPlaced","stackThreshold","startFromThreshold","closestPointRangePx","xValue","yValue","yBottom","negStacks","stackIndicator","getStackIndicator","pointStack","stackValues","irregularWidths","setOffset","pointXOffset","barW","isPointInside","lastPlotX","getValidPoints","insideOnly","allowNull","isValidPoint","getClipBox","finalBox","setClip","seriesClipBox","sharedClipKey","markerClipRect","afterAnimate","finishedAnimating","drawPoints","seriesMarkerOptions","specialGroup","globallyEnabled","pointMarkerOptions","hasPointMarker","markerAttribs","hasImage","seriesStateOptions","pointStateOptions","pointColorOption","pointColor","zoneColor","keepEventsForUpdate","issue134","removeEvents","animationTimeout","survive","getGraphPath","nullsAsZeroes","connectCliffs","graphPath","xMap","gap","connectNulls","leftCliff","rightCliff","pathToPoint","getPointSpline","drawGraph","gappedPath","getZonesGraphs","graphKey","graph","preventGraphAnimation","fillGraph","linecap","propset","applyZones","translatedFrom","translatedTo","clips","clipAttr","area","chartSizeMax","pxRange","pxPosMin","pxPosMax","ignoreZones","zoneArea","zoneGraph","showLine","extremes","isVML","resetZones","invertGroups","setInvert","isRadialSeries","unbind","animDuration","chartSeriesGroup","invertable","drawDataLabels","redrawPoints","wasDirty","kdAxisArray","searchKDTree","buildKDTree","_kdtree","depth","dimensions","median","buildingKdTree","startRecursive","kdNow","_search","search","tree","kdX","kdY","tdist","sideA","sideB","nPoint1","kdComparer","nPoint2","kdDimensions","StackItem","isNegative","stackOption","StackItem.prototype.destroy","StackItem.prototype.render","labelrank","StackItem.prototype.setOffset","xOffset","xWidth","boxBottom","boxTop","defaultX","stackItem","yZero","stackBox","getStackBox","isJustify","boxOffsetX","boxOffsetY","justifyDataLabel","StackItem.prototype.getStackBox","axisPos","neg","Chart.prototype.getStacks","Series.prototype.setStackedPoints","negKey","pointKey","singleStacks","Series.prototype.modifyStacks","pointExtremes","percentStacker","Series.prototype.percentStacker","totalFactor","Series.prototype.getStackIndicator","cleanRecursively","H.cleanRecursively","newer","older","ob","addSeries","addAxis","createAxis","addColorAxis","ColorAxis","showLoading","loadingDiv","loadingOptions","setLoadingSize","loadingSpan","loadingShown","showDuration","hideLoading","hideDuration","propsRequireDirtyBox","propsRequireReflow","propsRequireUpdateSeries","collectionsWithUpdate","oneToOne","adders","updateAllSeries","runSetSize","isResponsiveOptions","itemsForRemoval","updateAllAxes","indexMap","isInternal","newOptions","collectionsWithInit","newWidth","newHeight","setSubtitle","setCaption","runEvent","hasDummyGraphic","shouldDestroyGraphic","connector","fixedBox","removePoint","withEvent","isInTheMiddle","oldOptions","initialType","newType","keepPoints","dataGrouping","initialSeriesProto","groups","preserve","setName","newEvents","ev","setCategories","getStackPoints","pointMap","seriesIndex","yAxisSeries","seriesLength","upOrDown","leftNull","rightNull","stackX","visibleSeries","idx","stackPoint","stackedValues","direction","nullName","cliff","otherStack","cliffName","topPath","bottomPoints","graphPoints","translatedThreshold","addDummyPoints","otherI","nullVal","cliffVal","isCliff","doCurve","rectPlotX","bottomPath","firstBottomPoint","areaPath","areaKey","fillOpacity","shiftUnit","nextPoint","nextX","nextY","leftContX","smoothing","denom","leftContY","rightContX","rightContY","areaProto","groupPadding","pointPadding","minPointLength","brightness","trackerGroups","otherSeries","getColumnMetrics","reverseStacks","stackGroups","columnCount","grouping","otherYAxis","columnIndex","categoryWidth","pointOffsetWidth","pointWidth","maxPointWidth","columnMetrics","crispCol","xCrisp","yCrisp","fromTop","dense","metrics","seriesPointWidth","seriesBarW","seriesXOffset","barX","barY","barH","p2o","pointAttrToOptions","strokeOption","strokeWidthOption","stateOptions","animationLimit","hasGraphic","allowShadow","translateProp","translateStart","jitter","takeOrdinalPosition","applyJitter","plotProp","translatedJitter","rand","CenteredSeriesMixin","getCenter","slicingRoom","slicedOffset","centerOption","smallestSize","angular","handleSlicingRoom","getStartAndEndRadians","startAngle","endAngle","connectorPadding","connectorShape","crookDistance","softConnector","ignoreHiddenPoint","column","startAngleRad","startR","getX","radii","asin","labelDistance","connectorOffset","radians","circ","endAngleRad","maxLabelDistance","slicedTranslation","radiusX","radiusY","half","finalConnectorOffset","labelPosition","natural","connectorPosition","breakAt","touchingSliceAt","drawEmpty","centerX","centerY","groupTranslation","pointAttr","shadowGroup","animateTo","getTranslate","delayedRendering","sortByAngle","toggleSlice","setVisible","vis","sliced","haloPath","connectorShapes","fixedOffset","lineSegment","straight","crookedLine","pieCenterX","crookX","segmentWithCrook","useCrook","getConnectorPath","predefinedShapes","final","H.distribute","maxDistance","sortByTarget","overlapping","origBoxes","restBoxes","reducedLen","targets","posInCompositeBox","Series.prototype.drawDataLabels","op","operator","property","mergeArrays","one","two","seriesDlOptions","seriesAnimDuration","fadeInDuration","defer","dlOptions","labelEnabled","dataLabelOnNull","connectors","contrastColor","inside","textPath","getDataLabelPath","dataLabelPath","alignDataLabel","Series.prototype.alignDataLabel","dlBox","justify","forceDL","setStartPos","setDataLabelStartPos","normRotation","negRotation","Series.prototype.setDataLabelStartPos","labelCenter","halfWidth","Series.prototype.justifyDataLabel","off","justified","pie","dataLabelPositioners","radialDistributionY","distributeBox","radialDistributionX","naturalY","seriesCenter","alignToPlotEdges","dataLabelWidth","alignToConnectors","maxDataLabelWidth","seriesTypes.pie.prototype.drawDataLabels","connectorWidth","maxWidth","labelHeight","halves","pointDataLabelsOptions","shortened","distributionLength","positionIndex","_attr","sideOverflow","verifyDataLabelOverflow","placeDataLabels","connectorColor","seriesTypes.pie.prototype.placeDataLabels","seriesTypes.pie.prototype.verifyDataLabelOverflow","minSize","newSize","seriesTypes.column.prototype.alignDataLabel","below","overshoot","collectAndHide","collector","nodes","hideOverlappingLabels","Chart.prototype.hideOverlappingLabels","label2","isLabelAffected","getAbsoluteBox","oldOpacity","newOpacity","absoluteBox","box1","label1","box2","isOld","TrackerMixin","drawTrackerPoint","_hasTracking","drawTrackerGraph","trackByArea","trackerPath","TRACKER_FILL","scatter","isPoint","activeClass","inactiveItem","fnLegendItemClick","browserEvent","strLegendItemClick","checked","defaultChecked","showResetZoom","zoomOut","btnOptions","relativeTo","resetSelection","hasZoomed","displayButton","mouseDownPos","axisData","axisStartPos","axisEndPos","isWithinPane","hasMapNavigation","mapNavigation","doRedraw","panningOptions","axisOpt","mousePos","mouseDown","startPos","halfPointRange","pointRangeDirection","panMin","panMax","flipped","startMin","startMax","paddedMin","paddedMax","spill","accumulate","loopPoint","loopSeries","hasImportedEvents","previousState","normalDisabled","markerStateOptions","stateDisabled","stateMarkerGraphic","pointMarker","hasMarkers","pointAttribsAnimation","newSymbol","currentSymbol","haloOptions","markerVisibility","markerGraphic","isCluster","mouseOver","mouseOut","stateAnimation","labelBySeries","oldVisibility","showOrHide","Chart.prototype.setResponsive","responsive","ruleIds","currentResponsive","rules","rule","_id","matchResponsiveRule","mergedOptions","ruleId","undoOptions","currentOptions","Chart.prototype.matchResponsiveRule","matches","condition","Chart.prototype.currentOptions","getCurrent","curr","defaultConfig","currentDateIndicator","cdiOptions","defaultMethod","defaultLabelOptions","adjustHeight","Chart.prototype.adjustHeight","initiatedScale","unitLength","diff","getListOfParents","ids","listOfParents","prev","getNode","level","mapOfIdToChildren","descendants","after","before","childStart","childEnd","milestone","Tree","getTree","TreeGridTick","treeGrid","Additions","renderLabelIcon","labelIcon","labelBox","collapsed","shouldRender","icon","wrapGetLabelPosition","lbOptions","isTreeGrid","symbolOptions","mapOfPosToGridNode","wrapRenderLabel","isCollapsed","removeClassName","prefixClassName","attachedTreeGridEvents","textDecoration","toggleCollapse","applied","TickClass","collapse","TickClass.prototype.collapse","expand","TickClass.prototype.expand","TickClass.prototype.toggleCollapse","Additions.prototype.collapse","breaks","setBreaks","Additions.prototype.expand","Additions.prototype.toggleCollapse","mapOptionsToLevel","parentColor","parentColorIndex","siblings","chartOptionsChart","getColorByPoint","colorIndexByPoint","colorVariation","getLevelOptions","levels","converted","levelIsConstant","setTreeValues","idRoot","nodeRoot","mapIdToNode","optionsPoint","childrenTotal","levelDynamic","isLeaf","updateRootId","rootId","rootNode","applyGridOptions","Axis.prototype.getMaxLabelDimensions","tickHeight","W","H.dateFormats.W","firstDay","thursday","firstThursday","E","H.dateFormats.E","columns","gridOptions","labelOpts","GridAxis","Side","nextTickPos","crispCorr","lblMetrics","GridAxisAdditions","isOuterAxis","GridAxisAdditions.prototype.isOuterAxis","parentAxis","thisIndex","otherAxis","GridAxis.compose","wrapUnsquish","onAfterGetOffset","onAfterGetTitlePosition","onAfterInit","onAfterRender","onAfterSetAxisTranslation","onAfterSetOptions","onAfterSetOptions2","onAfterSetScale","onAfterTickSize","onTrimTicks","GridAxis.onAfterGetOffset","GridAxis.onAfterGetTitlePosition","axisHeight","axisWidth","titleWidth","titleFontSize","GridAxis.onAfterInit","columnOptions","isColumn","GridAxis.onAfterRender","rightWall","linePath","startPoint","endPoint","axisLineExtra","GridAxis.onAfterSetAxisTranslation","tickInfo","userLabels","GridAxis.onAfterSetOptions","gridAxisOptions","gridAxisOptions.tickPositioner","parentInfo","unitIdx","GridAxis.onAfterSetOptions2","GridAxis.onAfterSetScale","GridAxis.onAfterTickSize","labelPadding","cellHeight","GridAxis.onDestroy","GridAxis.onInit","GridAxis.onTrimTicks","categoryAxis","firstPos","GridAxis.wrapUnsquish","BrokenAxisAdditions","isInBreak","BrokenAxisAdditions.isInBreak","brk","repeat","inclusive","lin2Val","BrokenAxisAdditions.lin2Val","breakArray","nval","val2Lin","BrokenAxisAdditions.val2Lin","findBreakAt","BrokenAxisAdditions.prototype.findBreakAt","isInAnyBreak","BrokenAxisAdditions.prototype.isInAnyBreak","testKeep","keep","inbrk","showPoints","BrokenAxisAdditions.prototype.setBreaks","axis.setExtremes","axisBreak","axis.setAxisTranslation","breakArrayT","breakSize","inBrk","BrokenAxis","BrokenAxis.compose","SeriesClass","seriesProto","drawBreaks","seriesProto.drawBreaks","eventName","brokenAxis_1","seriesProto.gappedPath","currentDataGrouping","groupingSize","gapSize","next","gapUnit","current","xRange","newPositions","isPointInBreak","drawPointsWrapped","TreeSeriesMixin","TreeGridAxis","getBreakFromNode","collapseStart","collapseEnd","getTreeGridFromData","numberOfSeries","collapsedNodes","mapOfIdToNode","posIterator","uniqueNamesEnabled","treeParams","gridNode","parentGridNode","hasSameName","updateYValuesAndTickPos","setValues","onBeforeRender","wrapGenerateTick","levelOptions","wrapGetMaxLabelDimensions","treeDepth","wrapInit","wrapSetTickInterval","getTickPositions","Additions.prototype.getTickPositions","Additions.prototype.isCollapsed","utils","findLastObstacleBefore","obstacles","startIx","cmp","findObstacleFromPoint","obstacle","yMax","yMin","pathFromSegments","segments","limitObstacleToBounds","algorithms","simpleConnect","copyFromPoint","fromKey","toKey","getMeOut","useMax","dir","startDirectionX","chartObstacles","startObstacleIx","endObstacleIx","endObstacle","waypoint","endSegment","startObstacle","prevWaypoint","waypoint2","requiresObstacles","fastAvoid","pivotPoint","fromPoint","toPoint","directionIsX","searchDirection","lowestPoint","highestPoint","getDodgeDirection","dirIsX","softBounds","soft","hardBounds","hard","toPointMax","toPointMin","maxOutOfSoftBounds","minOutOfSoftBounds","maxOutOfHardBounds","minOutOfHardBounds","minDistance","minPivot","maxPivot","clearPathTo","obstacleMargin","obstacleOptions","softMinX","softMaxX","softMinY","softMaxY","envelopingObstacle","waypointUseMax","envelopWaypoint","secondEnvelopingObstacle","forceObstacleBreak","pivot","extractFromObstacle","goalPoint","endSegments","obstacleMetrics","extractedEndPoint","arrow","H.SVGRenderer.prototype.symbols.arrow","pathfinderAlgorithms","getPointBB","calculateObstacleMargin","obstacleDistance","distances","bbMargin","yOverlap","xOverlap","xDistance","yDistance","Connection","Pathfinder","warnLegacy","pathfinder","startMarker","endMarker","renderPath","pathGraphic","connection","graphics","anim","addMarker","getPathfinderAnchorPoint","pathVector","getRadiansToVector","markerVector","getMarkerVector","getPath","algorithm","getChartObstacles","algorithmMargin","chartObstacleMetrics","getObstacleMetrics","lineObstacles","getAlgorithmStartDirection","pathResult","connections","deferRender","oldConnections","connects","connect","found","lenOld","lenNew","renderConnections","pathfinderRemoveRenderEvent","calculatedMargin","sLen","pLen","yCenter","undef","v1","v2","atan2","markerRadius","twoPI","rectWidth","rectHeight","rAtan","leftOrRightRegion","rectHalfWidth","rectHalfHeight","rectHorizontalCenter","rectVerticalCenter","markerPoint","xFactor","yFactor","theta","tanTheta","tan","columnType","amount","partialFill","swapAxes","x2Data","translatePoint","posX","plotX2","crisper","pointHeight","widthDifference","dlLeft","dlRight","dlWidth","xIndex","yIndex","tooltipYOffset","partShapeArgs","clipRectWidth","clipRectArgs","drawPoint","seriesOpts","pfOptions","pointState","stateOpts","pointStateVerb","partRect","partialClipRect","getAnimationVerb","cfg","yCats","yCategory","modMax","xrange","pointFormatter","formats","ttOptions","keyboardMoveVertical","diamondShape","setGanttPointAliases","addIfExists","completed","dependency","gantt","ganttChart","H.ganttChart","hasRenderToArg","defaultLinkedTo","isGantt","ScrollbarAxis","ScrollbarAxis.compose","ScrollbarClass","scrollbar","vertical","axisMin","axisMax","unitedMin","unitedMax","liveRedraw","DOMType","setRange","scrollMin","scrollMax","scrollbarsOffsets","axisMargin","offsetsIndex","swapXY","H.swapXY","Scrollbar","_events","scrollbarButtons","scrollbarGroup","scrollbarLeft","scrollbarRifles","scrollbarStrokeWidth","scrollbarTop","track","trackBorderWidth","addEvents","Scrollbar.prototype.addEvents","buttonsOrder","bar","mouseDownHandler","mouseMoveHandler","mouseUpHandler","buttonToMinClick","buttonToMaxClick","trackClick","Scrollbar.prototype.buttonToMaxClick","DOMEvent","Scrollbar.prototype.buttonToMinClick","cursorToScrollbarPosition","Scrollbar.prototype.cursorToScrollbarPosition","normalizedEvent","minWidthDifference","calculatedWidth","barWidth","Scrollbar.prototype.destroy","drawScrollbarButton","Scrollbar.prototype.drawScrollbarButton","tempElem","buttonBorderColor","buttonBorderWidth","buttonBackgroundColor","buttonBorderRadius","buttonArrowColor","Scrollbar.prototype.init","Scrollbar.prototype.mouseDownHandler","mousePosition","initPositions","grabbedCenter","Scrollbar.prototype.mouseMoveHandler","scrollPosition","change","Scrollbar.prototype.mouseUpHandler","Scrollbar.prototype.position","rendered","Scrollbar.prototype.removeEvents","Scrollbar.prototype.render","trackBorderRadius","trackBackgroundColor","trackBorderColor","barBorderRadius","barBackgroundColor","barBorderColor","barBorderWidth","rifleColor","Scrollbar.prototype.setRange","fullWidth","fromPX","newPos","newRiflesPos","showFull","Scrollbar.prototype.trackClick","Scrollbar.prototype.update","Scrollbar.prototype.updatePosition","RangeSelector","rangeSelector","buttonTheme","inputPosition","buttonPosition","rangeSelectorZoom","rangeSelectorFrom","rangeSelectorTo","clickButton","rangeOptions","buttonOptions","baseAxis","unionExtremes","getUnionExtremes","_range","rangeMin","fixedRange","forcedDataGrouping","setDataGrouping","frozenStates","preserveDataGrouping","MIN_VALUE","ytdExtremes","getYTDExtremes","deferredYTDClick","_offsetMin","_offsetMax","setSelected","rangeSelectorButton","baseXAxisOptions","rangeSetting","minSetting","resetMinAndRange","defaultButtons","selectedOption","blurInputs","minInput","maxInput","blur","unMouseDown","unResize","computeButtonRange","updateButtonStates","actualRange","hasNoData","ytdMin","ytdMax","selectedExists","allButtonsEnabled","offsetRange","isSelected","isTooGreatRange","isTooSmallRange","isYTDButNotSelected","isAllButAlreadyShowingAll","isSameRange","disable","fixedTimes","offsetMin","offsetMax","setInputValue","inputTime","previousValue","HCTime","inputEditDateFormat","inputDateFormat","showInput","inputGroup","dateBox","hideInput","drawInput","updateExtremes","inputValue","inputDateParser","chartAxis","dataAxis","isMin","chartStyle","inputBoxWidth","inputBoxHeight","focus","inputBoxBorderColor","inputStyle","onfocus","input.onfocus","onblur","input.onblur","activeElement","onchange","onkeypress","input.onkeypress","keyCode","buttonTop","inputTop","startOfYear","navButtonOptions","inputsZIndex","inputEnabled","buttonGroup","legendOptions","buttonPositionY","inputPositionY","exportingX","zoomText","buttonEvents","callDefaultEvent","disabled","buttonLeft","buttonSpacing","titleCollision","inputGroupX","inputGroupWidth","buttonGroupX","buttonGroupWidth","groupHeight","alignTranslateY","minPosition","getHeight","rangeSelectorGroup","yPosition","rangeSelectorHeight","rSelector","getTrueRange","timeName","basePeriod","extraBottomMargin","extraTopMargin","optionsRangeSelector","extraBottomMarginWas","extraTopMarginWas","renderRangeSelector","unbindSetExtremes","unbindRender","destroyEvents","NavigatorAxisAdditions","NavigatorAxisAdditions.prototype.destroy","toFixedRange","NavigatorAxisAdditions.prototype.toFixedRange","pxMin","pxMax","fixedMin","fixedMax","changeRatio","NavigatorAxis","NavigatorAxis.compose","navigatorAxis","previousZoom","numExt","extreme","numbers","areaspline","maskInside","handles","maskFill","outlineColor","outlineWidth","compare","approximation","groupPixelWidth","smoothed","overscroll","markerPosition","Navigator","zoomedMin","zoomedMax","shades","outlineHeight","outline","navigatorSize","navigatorOptions","navigatorGroup","navigatorEnabled","baseSeries","drawHandle","Navigator.prototype.drawHandle","drawOutline","Navigator.prototype.drawOutline","halfOutline","outlineCorrection","scrollbarHeight","navigatorTop","verticalMin","drawMasks","Navigator.prototype.drawMasks","navigatorHeight","shade","renderElements","Navigator.prototype.renderElements","mouseCursor","hasMask","handlesOptions","Navigator.prototype.update","Navigator.prototype.render","scrollbarXAxis","maxRange","navigatorWidth","currentRange","grabbedLeft","grabbedRight","fixedWidth","addMouseEvents","Navigator.prototype.addMouseEvents","onMouseMove","onMouseUp","getPartsEvents","modifyNavigatorAxisExtremes","Navigator.prototype.getPartsEvents","navigatorItem","shadesMousedown","Navigator.prototype.shadesMousedown","navigatorPosition","dragOffset","reversedExtremes","ext","handlesMousedown","Navigator.prototype.handlesMousedown","baseXAxis","otherHandlePos","fixedExtreme","Navigator.prototype.onMouseMove","Navigator.prototype.onMouseUp","triggerOp","Navigator.prototype.removeEvents","removeBaseSeriesEvents","Navigator.prototype.removeBaseSeriesEvents","adaptToUpdatedData","updatedDataHandler","modifyBaseAxisExtremes","Navigator.prototype.init","scrollbarOptions","scrollbarEnabled","setBaseSeries","xAxisIndex","yAxisIndex","baseXaxis","keepOrdinalPadding","updateNavigatorSeries","unbindRedraw","scrollTrackWidth","valueRange","addBaseSeriesEvents","addChartEvents","Navigator.prototype.getUnionExtremes","returnFalseOnNoBaseSeries","navAxis","navAxisOptions","baseAxisOptions","Navigator.prototype.setBaseSeries","baseSeriesOptions","showInNavigator","Navigator.prototype.updateNavigatorSeries","baseOptions","mergedNavSeriesOptions","chartNavigatorSeriesOptions","baseNavigatorOptions","navSeriesMixin","padXAxis","navSeries","eachBaseSeries","linkedNavSeries","userNavOptions","navigatorSeriesData","hasNavigatorData","userSeriesOptions","Navigator.prototype.addBaseSeriesEvents","getBaseSeriesMin","Navigator.prototype.getBaseSeriesMin","currentSeriesMin","Navigator.prototype.modifyNavigatorAxisExtremes","Navigator.prototype.modifyBaseAxisExtremes","baseExtremes","baseDataMin","baseDataMax","stickToMin","stickToMax","hasSetExtremes","Navigator.prototype.updatedDataHandler","xDataMin","Navigator.prototype.addChartEvents","Navigator.prototype.destroy"]} \ No newline at end of file diff --git a/librerias/gantt/code/highcharts-gantt.src.js b/librerias/gantt/code/highcharts-gantt.src.js new file mode 100644 index 0000000..7bcac27 --- /dev/null +++ b/librerias/gantt/code/highcharts-gantt.src.js @@ -0,0 +1,52328 @@ +/** + * @license Highcharts Gantt JS v8.1.0 (2020-05-05) + * + * (c) 2017-2018 Lars Cabrera, Torstein Honsi, Jon Arild Nygard & Oystein Moseng + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (root, factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = root.document ? + factory(root) : + factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/highcharts-gantt', function () { + return factory(root); + }); + } else { + if (root.Highcharts) { + root.Highcharts.error(16, true); + } + root.Highcharts = factory(root); + } +}(typeof window !== 'undefined' ? window : this, function (win) { + var _modules = {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'parts/Globals.js', [], function () { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /* globals Image, window */ + /** + * Reference to the global SVGElement class as a workaround for a name conflict + * in the Highcharts namespace. + * + * @global + * @typedef {global.SVGElement} GlobalSVGElement + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/SVGElement + */ + // glob is a temporary fix to allow our es-modules to work. + var glob = ( // @todo UMD variable named `window`, and glob named `win` + typeof win !== 'undefined' ? + win : + typeof window !== 'undefined' ? + window : + {}), doc = glob.document, SVG_NS = 'http://www.w3.org/2000/svg', userAgent = (glob.navigator && glob.navigator.userAgent) || '', svg = (doc && + doc.createElementNS && + !!doc.createElementNS(SVG_NS, 'svg').createSVGRect), isMS = /(edge|msie|trident)/i.test(userAgent) && !glob.opera, isFirefox = userAgent.indexOf('Firefox') !== -1, isChrome = userAgent.indexOf('Chrome') !== -1, hasBidiBug = (isFirefox && + parseInt(userAgent.split('Firefox/')[1], 10) < 4 // issue #38 + ); + var H = { + product: 'Highcharts', + version: '8.1.0', + deg2rad: Math.PI * 2 / 360, + doc: doc, + hasBidiBug: hasBidiBug, + hasTouch: !!glob.TouchEvent, + isMS: isMS, + isWebKit: userAgent.indexOf('AppleWebKit') !== -1, + isFirefox: isFirefox, + isChrome: isChrome, + isSafari: !isChrome && userAgent.indexOf('Safari') !== -1, + isTouchDevice: /(Mobile|Android|Windows Phone)/.test(userAgent), + SVG_NS: SVG_NS, + chartCount: 0, + seriesTypes: {}, + symbolSizes: {}, + svg: svg, + win: glob, + marginNames: ['plotTop', 'marginRight', 'marginBottom', 'plotLeft'], + noop: function () { }, + /** + * An array containing the current chart objects in the page. A chart's + * position in the array is preserved throughout the page's lifetime. When + * a chart is destroyed, the array item becomes `undefined`. + * + * @name Highcharts.charts + * @type {Array} + */ + charts: [], + /** + * A hook for defining additional date format specifiers. New + * specifiers are defined as key-value pairs by using the + * specifier as key, and a function which takes the timestamp as + * value. This function returns the formatted portion of the + * date. + * + * @sample highcharts/global/dateformats/ + * Adding support for week number + * + * @name Highcharts.dateFormats + * @type {Highcharts.Dictionary} + */ + dateFormats: {} + }; + + return H; + }); + _registerModule(_modules, 'parts/Utilities.js', [_modules['parts/Globals.js']], function (H) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * An animation configuration. Animation configurations can also be defined as + * booleans, where `false` turns off animation and `true` defaults to a duration + * of 500ms. + * + * @interface Highcharts.AnimationOptionsObject + */ /** + * A callback function to exectute when the animation finishes. + * @name Highcharts.AnimationOptionsObject#complete + * @type {Function|undefined} + */ /** + * The animation duration in milliseconds. + * @name Highcharts.AnimationOptionsObject#duration + * @type {number|undefined} + */ /** + * The name of an easing function as defined on the `Math` object. + * @name Highcharts.AnimationOptionsObject#easing + * @type {string|Function|undefined} + */ /** + * A callback function to execute on each step of each attribute or CSS property + * that's being animated. The first argument contains information about the + * animation and progress. + * @name Highcharts.AnimationOptionsObject#step + * @type {Function|undefined} + */ + /** + * Creates a frame for the animated SVG element. + * + * @callback Highcharts.AnimationStepCallbackFunction + * + * @param {Highcharts.SVGElement} this + * The SVG element to animate. + * + * @return {void} + */ + /** + * Interface description for a class. + * + * @interface Highcharts.Class + * @extends Function + */ /** + * Class costructor. + * @function Highcharts.Class#new + * @param {...Array<*>} args + * Constructor arguments. + * @return {T} + * Class instance. + */ + /** + * A style object with camel case property names to define visual appearance of + * a SVG element or HTML element. The properties can be whatever styles are + * supported on the given SVG or HTML element. + * + * @example + * { + * fontFamily: 'monospace', + * fontSize: '1.2em' + * } + * + * @interface Highcharts.CSSObject + */ /** + * @name Highcharts.CSSObject#[key:string] + * @type {boolean|number|string|undefined} + */ /** + * Background style for the element. + * @name Highcharts.CSSObject#background + * @type {string|undefined} + */ /** + * Background color of the element. + * @name Highcharts.CSSObject#backgroundColor + * @type {Highcharts.ColorString|undefined} + */ /** + * Border style for the element. + * @name Highcharts.CSSObject#border + * @type {string|undefined} + */ /** + * Radius of the element border. + * @name Highcharts.CSSObject#borderRadius + * @type {number|undefined} + */ /** + * Color used in the element. The 'contrast' option is a Highcharts custom + * property that results in black or white, depending on the background of the + * element. + * @name Highcharts.CSSObject#color + * @type {'contrast'|Highcharts.ColorString|undefined} + */ /** + * Style of the mouse cursor when resting over the element. + * @name Highcharts.CSSObject#cursor + * @type {Highcharts.CursorValue|undefined} + */ /** + * Font family of the element text. Multiple values have to be in decreasing + * preference order and separated by comma. + * @name Highcharts.CSSObject#fontFamily + * @type {string|undefined} + */ /** + * Font size of the element text. + * @name Highcharts.CSSObject#fontSize + * @type {string|undefined} + */ /** + * Font weight of the element text. + * @name Highcharts.CSSObject#fontWeight + * @type {string|undefined} + */ /** + * Height of the element. + * @name Highcharts.CSSObject#height + * @type {number|undefined} + */ /** + * Width of the element border. + * @name Highcharts.CSSObject#lineWidth + * @type {number|undefined} + */ /** + * Opacity of the element. + * @name Highcharts.CSSObject#opacity + * @type {number|undefined} + */ /** + * Space around the element content. + * @name Highcharts.CSSObject#padding + * @type {string|undefined} + */ /** + * Behaviour of the element when the mouse cursor rests over it. + * @name Highcharts.CSSObject#pointerEvents + * @type {string|undefined} + */ /** + * Positioning of the element. + * @name Highcharts.CSSObject#position + * @type {string|undefined} + */ /** + * Alignment of the element text. + * @name Highcharts.CSSObject#textAlign + * @type {string|undefined} + */ /** + * Additional decoration of the element text. + * @name Highcharts.CSSObject#textDecoration + * @type {string|undefined} + */ /** + * Outline style of the element text. + * @name Highcharts.CSSObject#textOutline + * @type {string|undefined} + */ /** + * Line break style of the element text. Highcharts SVG elements support + * `ellipsis` when a `width` is set. + * @name Highcharts.CSSObject#textOverflow + * @type {string|undefined} + */ /** + * Top spacing of the element relative to the parent element. + * @name Highcharts.CSSObject#top + * @type {string|undefined} + */ /** + * Animated transition of selected element properties. + * @name Highcharts.CSSObject#transition + * @type {string|undefined} + */ /** + * Line break style of the element text. + * @name Highcharts.CSSObject#whiteSpace + * @type {string|undefined} + */ /** + * Width of the element. + * @name Highcharts.CSSObject#width + * @type {number|undefined} + */ + /** + * All possible cursor styles. + * + * @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 + */ + /** + * All possible dash styles. + * + * @typedef {'Dash'|'DashDot'|'Dot'|'LongDash'|'LongDashDot'|'LongDashDotDot'|'ShortDash'|'ShortDashDot'|'ShortDashDotDot'|'ShortDot'|'Solid'} Highcharts.DashStyleValue + */ + /** + * Generic dictionary in TypeScript notation. + * + * @interface Highcharts.Dictionary + */ /** + * @name Highcharts.Dictionary#[key:string] + * @type {T} + */ + /** + * The function callback to execute when the event is fired. The `this` context + * contains the instance, that fired the event. + * + * @callback Highcharts.EventCallbackFunction + * + * @param {T} this + * + * @param {Highcharts.Dictionary<*>|Event} [eventArguments] + * Event arguments. + * + * @return {boolean|void} + */ + /** + * The event options for adding function callback. + * + * @interface Highcharts.EventOptionsObject + */ /** + * The order the event handler should be called. This opens for having one + * handler be called before another, independent of in which order they were + * added. + * @name Highcharts.EventOptionsObject#order + * @type {number} + */ + /** + * Formats data as a string. Usually the data is accessible throught the `this` + * keyword. + * + * @callback Highcharts.FormatterCallbackFunction + * + * @param {T} this + * Context to format + * + * @return {string} + * Formatted text + */ + /** + * An object of key-value pairs for HTML attributes. + * + * @typedef {Highcharts.Dictionary} Highcharts.HTMLAttributes + */ + /** + * An HTML DOM element. The type is a reference to the regular HTMLElement in + * the global scope. + * + * @typedef {global.HTMLElement} Highcharts.HTMLDOMElement + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement + */ + /** + * The iterator callback. + * + * @callback Highcharts.ObjectEachCallbackFunction + * + * @param {T} this + * The context. + * + * @param {*} value + * The property value. + * + * @param {string} key + * The property key. + * + * @param {*} obj + * The object that objectEach is being applied to. + */ + /** + * An object containing `left` and `top` properties for the position in the + * page. + * + * @interface Highcharts.OffsetObject + */ /** + * Left distance to the page border. + * @name Highcharts.OffsetObject#left + * @type {number} + */ /** + * Top distance to the page border. + * @name Highcharts.OffsetObject#top + * @type {number} + */ + /** + * Describes a range. + * + * @interface Highcharts.RangeObject + */ /** + * Maximum number of the range. + * @name Highcharts.RangeObject#max + * @type {number} + */ /** + * Minimum number of the range. + * @name Highcharts.RangeObject#min + * @type {number} + */ + /** + * If a number is given, it defines the pixel length. If a percentage string is + * given, like for example `'50%'`, the setting defines a length relative to a + * base size, for example the size of a container. + * + * @typedef {number|string} Highcharts.RelativeSize + */ + /** + * Proceed function to call original (wrapped) function. + * + * @callback Highcharts.WrapProceedFunction + * + * @param {*} [arg1] + * Optional argument. Without any arguments defaults to first argument of + * the wrapping function. + * + * @param {*} [arg2] + * Optional argument. Without any arguments defaults to second argument + * of the wrapping function. + * + * @param {*} [arg3] + * Optional argument. Without any arguments defaults to third argument of + * the wrapping function. + * + * @return {*} + * Return value of the original function. + */ + /** + * The Highcharts object is the placeholder for all other members, and various + * utility functions. The most important member of the namespace would be the + * chart constructor. + * + * @example + * var chart = Highcharts.chart('container', { ... }); + * + * @namespace Highcharts + */ + H.timers = []; + var charts = H.charts, doc = H.doc, win = H.win; + /** + * Provide error messages for debugging, with links to online explanation. This + * function can be overridden to provide custom error handling. + * + * @sample highcharts/chart/highcharts-error/ + * Custom error handler + * + * @function Highcharts.error + * + * @param {number|string} code + * The error code. See + * [errors.xml](https://github.com/highcharts/highcharts/blob/master/errors/errors.xml) + * for available codes. If it is a string, the error message is printed + * directly in the console. + * + * @param {boolean} [stop=false] + * Whether to throw an error or just log a warning in the console. + * + * @param {Highcharts.Chart} [chart] + * Reference to the chart that causes the error. Used in 'debugger' + * module to display errors directly on the chart. + * Important note: This argument is undefined for errors that lack + * access to the Chart instance. + * + * @param {Highcharts.Dictionary} [params] + * Additional parameters for the generated message. + * + * @return {void} + */ + var error = H.error = function (code, stop, chart, params) { + var isCode = isNumber(code), message = isCode ? + "Highcharts error #" + code + ": www.highcharts.com/errors/" + code + "/" : + code.toString(), defaultHandler = function () { + if (stop) { + throw new Error(message); + } + // else ... + if (win.console) { + console.log(message); // eslint-disable-line no-console + } + }; + if (typeof params !== 'undefined') { + var additionalMessages_1 = ''; + if (isCode) { + message += '?'; + } + objectEach(params, function (value, key) { + additionalMessages_1 += ('\n' + key + ': ' + value); + if (isCode) { + message += encodeURI(key) + '=' + encodeURI(value); + } + }); + message += additionalMessages_1; + } + if (chart) { + fireEvent(chart, 'displayError', { code: code, message: message, params: params }, defaultHandler); + } + else { + defaultHandler(); + } + }; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * An animator object used internally. One instance applies to one property + * (attribute or style prop) on one element. Animation is always initiated + * through {@link SVGElement#animate}. + * + * @example + * var rect = renderer.rect(0, 0, 10, 10).add(); + * rect.animate({ width: 100 }); + * + * @private + * @class + * @name Highcharts.Fx + */ + var Fx = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + /** + * + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGElement} elem + * The element to animate. + * + * @param {Highcharts.AnimationOptionsObject} options + * Animation options. + * + * @param {string} prop + * The single attribute or CSS property to animate. + */ + function Fx(elem, options, prop) { + this.options = options; + this.elem = elem; + this.prop = prop; + } + /* * + * + * Functions + * + * */ + /** + * Set the current step of a path definition on SVGElement. + * + * @function Highcharts.Fx#dSetter + * + * @return {void} + */ + Fx.prototype.dSetter = function () { + var paths = this.paths, start = paths && paths[0], end = paths && paths[1], path = [], now = this.now || 0; + // Land on the final path without adjustment points appended in the ends + if (now === 1 || !start || !end) { + path = this.toD || []; + } + else if (start.length === end.length && now < 1) { + for (var i = 0; i < end.length; i++) { + // Tween between the start segment and the end segment. Start + // with a copy of the end segment and tween the appropriate + // numerics + var startSeg = start[i]; + var endSeg = end[i]; + var tweenSeg = []; + for (var j = 0; j < endSeg.length; j++) { + var startItem = startSeg[j]; + var endItem = endSeg[j]; + // Tween numbers + if (typeof startItem === 'number' && + typeof endItem === 'number' && + // Arc boolean flags + !(endSeg[0] === 'A' && (j === 4 || j === 5))) { + tweenSeg[j] = startItem + now * (endItem - startItem); + // Strings, take directly from the end segment + } + else { + tweenSeg[j] = endItem; + } + } + path.push(tweenSeg); + } + // If animation is finished or length not matching, land on right value + } + else { + path = end; + } + this.elem.attr('d', path, void 0, true); + }; + /** + * Update the element with the current animation step. + * + * @function Highcharts.Fx#update + * + * @return {void} + */ + Fx.prototype.update = function () { + var elem = this.elem, prop = this.prop, // if destroyed, it is null + now = this.now, step = this.options.step; + // Animation setter defined from outside + if (this[prop + 'Setter']) { + this[prop + 'Setter'](); + // Other animations on SVGElement + } + else if (elem.attr) { + if (elem.element) { + elem.attr(prop, now, null, true); + } + // HTML styles, raw HTML content like container size + } + else { + elem.style[prop] = now + this.unit; + } + if (step) { + step.call(elem, now, this); + } + }; + /** + * Run an animation. + * + * @function Highcharts.Fx#run + * + * @param {number} from + * The current value, value to start from. + * + * @param {number} to + * The end value, value to land on. + * + * @param {string} unit + * The property unit, for example `px`. + * + * @return {void} + */ + Fx.prototype.run = function (from, to, unit) { + var self = this, options = self.options, timer = function (gotoEnd) { + return timer.stopped ? false : self.step(gotoEnd); + }, requestAnimationFrame = win.requestAnimationFrame || + function (step) { + setTimeout(step, 13); + }, step = function () { + for (var i = 0; i < H.timers.length; i++) { + if (!H.timers[i]()) { + H.timers.splice(i--, 1); + } + } + if (H.timers.length) { + requestAnimationFrame(step); + } + }; + if (from === to && !this.elem['forceAnimate:' + this.prop]) { + delete options.curAnim[this.prop]; + if (options.complete && Object.keys(options.curAnim).length === 0) { + options.complete.call(this.elem); + } + } + else { // #7166 + this.startTime = +new Date(); + this.start = from; + this.end = to; + this.unit = unit; + this.now = this.start; + this.pos = 0; + timer.elem = this.elem; + timer.prop = this.prop; + if (timer() && H.timers.push(timer) === 1) { + requestAnimationFrame(step); + } + } + }; + /** + * Run a single step in the animation. + * + * @function Highcharts.Fx#step + * + * @param {boolean} [gotoEnd] + * Whether to go to the endpoint of the animation after abort. + * + * @return {boolean} + * Returns `true` if animation continues. + */ + Fx.prototype.step = function (gotoEnd) { + var t = +new Date(), ret, done, options = this.options, elem = this.elem, complete = options.complete, duration = options.duration, curAnim = options.curAnim; + if (elem.attr && !elem.element) { // #2616, element is destroyed + ret = false; + } + else if (gotoEnd || t >= duration + this.startTime) { + this.now = this.end; + this.pos = 1; + this.update(); + curAnim[this.prop] = true; + done = true; + objectEach(curAnim, function (val) { + if (val !== true) { + done = false; + } + }); + if (done && complete) { + complete.call(elem); + } + ret = false; + } + else { + this.pos = options.easing((t - this.startTime) / duration); + this.now = this.start + ((this.end - this.start) * this.pos); + this.update(); + ret = true; + } + return ret; + }; + /** + * Prepare start and end values so that the path can be animated one to one. + * + * @function Highcharts.Fx#initPath + * + * @param {Highcharts.SVGElement} elem + * The SVGElement item. + * + * @param {Highcharts.SVGPathArray|undefined} fromD + * Starting path definition. + * + * @param {Highcharts.SVGPathArray} toD + * Ending path definition. + * + * @return {Array} + * An array containing start and end paths in array form so that + * they can be animated in parallel. + */ + Fx.prototype.initPath = function (elem, fromD, toD) { + var shift, startX = elem.startX, endX = elem.endX, fullLength, i, start = fromD && fromD.slice(), // copy + end = toD.slice(), // copy + isArea = elem.isArea, positionFactor = isArea ? 2 : 1, reverse; + if (!start) { + return [end, end]; + } + /** + * If shifting points, prepend a dummy point to the end path. + * @private + * @param {Highcharts.SVGPathArray} arr - array + * @param {Highcharts.SVGPathArray} other - array + * @return {void} + */ + function prepend(arr, other) { + while (arr.length < fullLength) { + // Move to, line to or curve to? + var moveSegment = arr[0], otherSegment = other[fullLength - arr.length]; + if (otherSegment && moveSegment[0] === 'M') { + if (otherSegment[0] === 'C') { + arr[0] = [ + 'C', + moveSegment[1], + moveSegment[2], + moveSegment[1], + moveSegment[2], + moveSegment[1], + moveSegment[2] + ]; + } + else { + arr[0] = ['L', moveSegment[1], moveSegment[2]]; + } + } + // Prepend a copy of the first point + arr.unshift(moveSegment); + // For areas, the bottom path goes back again to the left, so we + // need to append a copy of the last point. + if (isArea) { + arr.push(arr[arr.length - 1]); + } + } + } + /** + * Copy and append last point until the length matches the end length. + * @private + * @param {Highcharts.SVGPathArray} arr - array + * @param {Highcharts.SVGPathArray} other - array + * @return {void} + */ + function append(arr, other) { + while (arr.length < fullLength) { + // Pull out the slice that is going to be appended or inserted. + // In a line graph, the positionFactor is 1, and the last point + // is sliced out. In an area graph, the positionFactor is 2, + // causing the middle two points to be sliced out, since an area + // path starts at left, follows the upper path then turns and + // follows the bottom back. + var segmentToAdd = arr[arr.length / positionFactor - 1].slice(); + // Disable the first control point of curve segments + if (segmentToAdd[0] === 'C') { + segmentToAdd[1] = segmentToAdd[5]; + segmentToAdd[2] = segmentToAdd[6]; + } + if (!isArea) { + arr.push(segmentToAdd); + } + else { + var lowerSegmentToAdd = arr[arr.length / positionFactor].slice(); + arr.splice(arr.length / 2, 0, segmentToAdd, lowerSegmentToAdd); + } + } + } + // For sideways animation, find out how much we need to shift to get the + // start path Xs to match the end path Xs. + if (startX && endX) { + for (i = 0; i < startX.length; i++) { + // Moving left, new points coming in on right + if (startX[i] === endX[0]) { + shift = i; + break; + // Moving right + } + else if (startX[0] === + endX[endX.length - startX.length + i]) { + shift = i; + reverse = true; + break; + // Fixed from the right side, "scaling" left + } + else if (startX[startX.length - 1] === + endX[endX.length - startX.length + i]) { + shift = startX.length - i; + break; + } + } + if (typeof shift === 'undefined') { + start = []; + } + } + if (start.length && isNumber(shift)) { + // The common target length for the start and end array, where both + // arrays are padded in opposite ends + fullLength = end.length + shift * positionFactor; + if (!reverse) { + prepend(end, start); + append(start, end); + } + else { + prepend(start, end); + append(end, start); + } + } + return [start, end]; + }; + /** + * Handle animation of the color attributes directly. + * + * @function Highcharts.Fx#fillSetter + * + * @return {void} + */ + Fx.prototype.fillSetter = function () { + Fx.prototype.strokeSetter.apply(this, arguments); + }; + /** + * Handle animation of the color attributes directly. + * + * @function Highcharts.Fx#strokeSetter + * + * @return {void} + */ + Fx.prototype.strokeSetter = function () { + this.elem.attr(this.prop, H.color(this.start).tweenTo(H.color(this.end), this.pos), null, true); + }; + return Fx; + }()); + H.Fx = Fx; + /* eslint-disable valid-jsdoc */ + /** + * Utility function to deep merge two or more objects and return a third object. + * If the first argument is true, the contents of the second object is copied + * into the first object. The merge function can also be used with a single + * object argument to create a deep copy of an object. + * + * @function Highcharts.merge + * + * @param {boolean} extend + * Whether to extend the left-side object (a) or return a whole new + * object. + * + * @param {T|undefined} a + * The first object to extend. When only this is given, the function + * returns a deep copy. + * + * @param {...Array} [n] + * An object to merge into the previous one. + * + * @return {T} + * The merged object. If the first argument is true, the return is the + * same as the second argument. + */ /** + * Utility function to deep merge two or more objects and return a third object. + * The merge function can also be used with a single object argument to create a + * deep copy of an object. + * + * @function Highcharts.merge + * + * @param {T|undefined} a + * The first object to extend. When only this is given, the function + * returns a deep copy. + * + * @param {...Array} [n] + * An object to merge into the previous one. + * + * @return {T} + * The merged object. If the first argument is true, the return is the + * same as the second argument. + */ + function merge() { + /* eslint-enable valid-jsdoc */ + var i, args = arguments, len, ret = {}, doCopy = function (copy, original) { + // An object is replacing a primitive + if (typeof copy !== 'object') { + copy = {}; + } + objectEach(original, function (value, key) { + // Copy the contents of objects, but not arrays or DOM nodes + if (isObject(value, true) && + !isClass(value) && + !isDOMElement(value)) { + copy[key] = doCopy(copy[key] || {}, value); + // Primitives and arrays are copied over directly + } + else { + copy[key] = original[key]; + } + }); + return copy; + }; + // If first argument is true, copy into the existing object. Used in + // setOptions. + if (args[0] === true) { + ret = args[1]; + args = Array.prototype.slice.call(args, 2); + } + // For each argument, extend the return + len = args.length; + for (i = 0; i < len; i++) { + ret = doCopy(ret, args[i]); + } + return ret; + } + H.merge = merge; + /** + * Constrain a value to within a lower and upper threshold. + * + * @private + * @param {number} value The initial value + * @param {number} min The lower threshold + * @param {number} max The upper threshold + * @return {number} Returns a number value within min and max. + */ + function clamp(value, min, max) { + return value > min ? value < max ? value : max : min; + } + /** + * Shortcut for parseInt + * + * @private + * @function Highcharts.pInt + * + * @param {*} s + * any + * + * @param {number} [mag] + * Magnitude + * + * @return {number} + * number + */ + var pInt = H.pInt = function pInt(s, mag) { + return parseInt(s, mag || 10); + }; + /** + * Utility function to check for string type. + * + * @function Highcharts.isString + * + * @param {*} s + * The item to check. + * + * @return {boolean} + * True if the argument is a string. + */ + var isString = H.isString = function isString(s) { + return typeof s === 'string'; + }; + /** + * Utility function to check if an item is an array. + * + * @function Highcharts.isArray + * + * @param {*} obj + * The item to check. + * + * @return {boolean} + * True if the argument is an array. + */ + var isArray = H.isArray = function isArray(obj) { + var str = Object.prototype.toString.call(obj); + return str === '[object Array]' || str === '[object Array Iterator]'; + }; + /** + * Utility function to check if an item is of type object. + * + * @function Highcharts.isObject + * + * @param {*} obj + * The item to check. + * + * @param {boolean} [strict=false] + * Also checks that the object is not an array. + * + * @return {boolean} + * True if the argument is an object. + */ + function isObject(obj, strict) { + return (!!obj && + typeof obj === 'object' && + (!strict || !isArray(obj))); // eslint-disable-line @typescript-eslint/no-explicit-any + } + H.isObject = isObject; + /** + * Utility function to check if an Object is a HTML Element. + * + * @function Highcharts.isDOMElement + * + * @param {*} obj + * The item to check. + * + * @return {boolean} + * True if the argument is a HTML Element. + */ + var isDOMElement = H.isDOMElement = function isDOMElement(obj) { + return isObject(obj) && typeof obj.nodeType === 'number'; + }; + /** + * Utility function to check if an Object is a class. + * + * @function Highcharts.isClass + * + * @param {object|undefined} obj + * The item to check. + * + * @return {boolean} + * True if the argument is a class. + */ + var isClass = H.isClass = function isClass(obj) { + var c = obj && obj.constructor; + return !!(isObject(obj, true) && + !isDOMElement(obj) && + (c && c.name && c.name !== 'Object')); + }; + /** + * Utility function to check if an item is a number and it is finite (not NaN, + * Infinity or -Infinity). + * + * @function Highcharts.isNumber + * + * @param {*} n + * The item to check. + * + * @return {boolean} + * True if the item is a finite number + */ + var isNumber = H.isNumber = function isNumber(n) { + return typeof n === 'number' && !isNaN(n) && n < Infinity && n > -Infinity; + }; + /** + * Remove the last occurence of an item from an array. + * + * @function Highcharts.erase + * + * @param {Array<*>} arr + * The array. + * + * @param {*} item + * The item to remove. + * + * @return {void} + */ + var erase = H.erase = function erase(arr, item) { + var i = arr.length; + while (i--) { + if (arr[i] === item) { + arr.splice(i, 1); + break; + } + } + }; + /** + * Check if an object is null or undefined. + * + * @function Highcharts.defined + * + * @param {*} obj + * The object to check. + * + * @return {boolean} + * False if the object is null or undefined, otherwise true. + */ + var defined = H.defined = function defined(obj) { + return typeof obj !== 'undefined' && obj !== null; + }; + /** + * Set or get an attribute or an object of attributes. To use as a setter, pass + * a key and a value, or let the second argument be a collection of keys and + * values. To use as a getter, pass only a string as the second argument. + * + * @function Highcharts.attr + * + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} elem + * The DOM element to receive the attribute(s). + * + * @param {string|Highcharts.HTMLAttributes|Highcharts.SVGAttributes} [prop] + * The property or an object of key-value pairs. + * + * @param {number|string} [value] + * The value if a single property is set. + * + * @return {string|null|undefined} + * When used as a getter, return the value. + */ + function attr(elem, prop, value) { + var ret; + // if the prop is a string + if (isString(prop)) { + // set the value + if (defined(value)) { + elem.setAttribute(prop, value); + // get the value + } + else if (elem && elem.getAttribute) { + ret = elem.getAttribute(prop); + // IE7 and below cannot get class through getAttribute (#7850) + if (!ret && prop === 'class') { + ret = elem.getAttribute(prop + 'Name'); + } + } + // else if prop is defined, it is a hash of key/value pairs + } + else { + objectEach(prop, function (val, key) { + elem.setAttribute(key, val); + }); + } + return ret; + } + H.attr = attr; + /** + * Check if an element is an array, and if not, make it into an array. + * + * @function Highcharts.splat + * + * @param {*} obj + * The object to splat. + * + * @return {Array} + * The produced or original array. + */ + var splat = H.splat = function splat(obj) { + return isArray(obj) ? obj : [obj]; + }; + /** + * Set a timeout if the delay is given, otherwise perform the function + * synchronously. + * + * @function Highcharts.syncTimeout + * + * @param {Function} fn + * The function callback. + * + * @param {number} delay + * Delay in milliseconds. + * + * @param {*} [context] + * An optional context to send to the function callback. + * + * @return {number} + * An identifier for the timeout that can later be cleared with + * Highcharts.clearTimeout. Returns -1 if there is no timeout. + */ + var syncTimeout = H.syncTimeout = function syncTimeout(fn, delay, context) { + if (delay > 0) { + return setTimeout(fn, delay, context); + } + fn.call(0, context); + return -1; + }; + /** + * Internal clear timeout. The function checks that the `id` was not removed + * (e.g. by `chart.destroy()`). For the details see + * [issue #7901](https://github.com/highcharts/highcharts/issues/7901). + * + * @function Highcharts.clearTimeout + * + * @param {number} id + * Id of a timeout. + * + * @return {void} + */ + var internalClearTimeout = H.clearTimeout = function (id) { + if (defined(id)) { + clearTimeout(id); + } + }; + /* eslint-disable valid-jsdoc */ + /** + * Utility function to extend an object with the members of another. + * + * @function Highcharts.extend + * + * @param {T|undefined} a + * The object to be extended. + * + * @param {object} b + * The object to add to the first one. + * + * @return {T} + * Object a, the original object. + */ + var extend = H.extend = function extend(a, b) { + /* eslint-enable valid-jsdoc */ + var n; + if (!a) { + a = {}; + } + for (n in b) { // eslint-disable-line guard-for-in + a[n] = b[n]; + } + return a; + }; + /* eslint-disable valid-jsdoc */ + /** + * Return the first value that is not null or undefined. + * + * @function Highcharts.pick + * + * @param {...Array} items + * Variable number of arguments to inspect. + * + * @return {T} + * The value of the first argument that is not null or undefined. + */ + function pick() { + var args = arguments; + var length = args.length; + for (var i = 0; i < length; i++) { + var arg = args[i]; + if (typeof arg !== 'undefined' && arg !== null) { + return arg; + } + } + } + H.pick = pick; + /** + * Set CSS on a given element. + * + * @function Highcharts.css + * + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} el + * An HTML DOM element. + * + * @param {Highcharts.CSSObject} styles + * Style object with camel case property names. + * + * @return {void} + */ + var css = H.css = function css(el, styles) { + if (H.isMS && !H.svg) { // #2686 + if (styles && typeof styles.opacity !== 'undefined') { + styles.filter = + 'alpha(opacity=' + (styles.opacity * 100) + ')'; + } + } + extend(el.style, styles); + }; + /** + * Utility function to create an HTML element with attributes and styles. + * + * @function Highcharts.createElement + * + * @param {string} tag + * The HTML tag. + * + * @param {Highcharts.HTMLAttributes} [attribs] + * Attributes as an object of key-value pairs. + * + * @param {Highcharts.CSSObject} [styles] + * Styles as an object of key-value pairs. + * + * @param {Highcharts.HTMLDOMElement} [parent] + * The parent HTML object. + * + * @param {boolean} [nopad=false] + * If true, remove all padding, border and margin. + * + * @return {Highcharts.HTMLDOMElement} + * The created DOM element. + */ + var createElement = H.createElement = function createElement(tag, attribs, styles, parent, nopad) { + var el = doc.createElement(tag); + if (attribs) { + extend(el, attribs); + } + if (nopad) { + css(el, { padding: '0', border: 'none', margin: '0' }); + } + if (styles) { + css(el, styles); + } + if (parent) { + parent.appendChild(el); + } + return el; + }; + // eslint-disable-next-line valid-jsdoc + /** + * Extend a prototyped class by new members. + * + * @function Highcharts.extendClass + * + * @param {Highcharts.Class} parent + * The parent prototype to inherit. + * + * @param {Highcharts.Dictionary<*>} members + * A collection of prototype members to add or override compared to the + * parent prototype. + * + * @return {Highcharts.Class} + * A new prototype. + */ + var extendClass = H.extendClass = function extendClass(parent, members) { + var obj = (function () { }); + obj.prototype = new parent(); // eslint-disable-line new-cap + extend(obj.prototype, members); + return obj; + }; + /** + * Left-pad a string to a given length by adding a character repetetively. + * + * @function Highcharts.pad + * + * @param {number} number + * The input string or number. + * + * @param {number} [length] + * The desired string length. + * + * @param {string} [padder=0] + * The character to pad with. + * + * @return {string} + * The padded string. + */ + var pad = H.pad = function pad(number, length, padder) { + return new Array((length || 2) + + 1 - + String(number) + .replace('-', '') + .length).join(padder || '0') + number; + }; + /** + * Return a length based on either the integer value, or a percentage of a base. + * + * @function Highcharts.relativeLength + * + * @param {Highcharts.RelativeSize} value + * A percentage string or a number. + * + * @param {number} base + * The full length that represents 100%. + * + * @param {number} [offset=0] + * A pixel offset to apply for percentage values. Used internally in + * axis positioning. + * + * @return {number} + * The computed length. + */ + var relativeLength = H.relativeLength = function relativeLength(value, base, offset) { + return (/%$/).test(value) ? + (base * parseFloat(value) / 100) + (offset || 0) : + parseFloat(value); + }; + /** + * Wrap a method with extended functionality, preserving the original function. + * + ' * @function Highcharts.wrap + * + * @param {*} obj + * The context object that the method belongs to. In real cases, this is + * often a prototype. + * + * @param {string} method + * The name of the method to extend. + * + * @param {Highcharts.WrapProceedFunction} func + * A wrapper function callback. This function is called with the same + * arguments as the original function, except that the original function + * is unshifted and passed as the first argument. + * + * @return {void} + */ + var wrap = H.wrap = function wrap(obj, method, func) { + var proceed = obj[method]; + obj[method] = function () { + var args = Array.prototype.slice.call(arguments), outerArgs = arguments, ctx = this, ret; + ctx.proceed = function () { + proceed.apply(ctx, arguments.length ? arguments : outerArgs); + }; + args.unshift(proceed); + ret = func.apply(this, args); + ctx.proceed = null; + return ret; + }; + }; + /** + * Format a string according to a subset of the rules of Python's String.format + * method. + * + * @example + * var s = Highcharts.format( + * 'The {color} fox was {len:.2f} feet long', + * { color: 'red', len: Math.PI } + * ); + * // => The red fox was 3.14 feet long + * + * @function Highcharts.format + * + * @param {string} str + * The string to format. + * + * @param {Record} ctx + * The context, a collection of key-value pairs where each key is + * replaced by its value. + * + * @param {Highcharts.Chart} [chart] + * A `Chart` instance used to get numberFormatter and time. + * + * @return {string} + * The formatted string. + */ + var format = H.format = function (str, ctx, chart) { + var splitter = '{', isInside = false, segment, valueAndFormat, ret = [], val, index; + var floatRegex = /f$/; + var decRegex = /\.([0-9])/; + var lang = H.defaultOptions.lang; + var time = chart && chart.time || H.time; + var numberFormatter = chart && chart.numberFormatter || numberFormat; + while (str) { + index = str.indexOf(splitter); + if (index === -1) { + break; + } + segment = str.slice(0, index); + if (isInside) { // we're on the closing bracket looking back + valueAndFormat = segment.split(':'); + val = getNestedProperty(valueAndFormat.shift() || '', ctx); + // Format the replacement + if (valueAndFormat.length && typeof val === 'number') { + segment = valueAndFormat.join(':'); + if (floatRegex.test(segment)) { // float + var decimals = parseInt((segment.match(decRegex) || ['', '-1'])[1], 10); + if (val !== null) { + val = numberFormatter(val, decimals, lang.decimalPoint, segment.indexOf(',') > -1 ? lang.thousandsSep : ''); + } + } + else { + val = time.dateFormat(segment, val); + } + } + // Push the result and advance the cursor + ret.push(val); + } + else { + ret.push(segment); + } + str = str.slice(index + 1); // the rest + isInside = !isInside; // toggle + splitter = isInside ? '}' : '{'; // now look for next matching bracket + } + ret.push(str); + return ret.join(''); + }; + /** + * Get the magnitude of a number. + * + * @function Highcharts.getMagnitude + * + * @param {number} num + * The number. + * + * @return {number} + * The magnitude, where 1-9 are magnitude 1, 10-99 magnitude 2 etc. + */ + var getMagnitude = H.getMagnitude = function (num) { + return Math.pow(10, Math.floor(Math.log(num) / Math.LN10)); + }; + /** + * Take an interval and normalize it to multiples of round numbers. + * + * @deprecated + * @function Highcharts.normalizeTickInterval + * + * @param {number} interval + * The raw, un-rounded interval. + * + * @param {Array<*>} [multiples] + * Allowed multiples. + * + * @param {number} [magnitude] + * The magnitude of the number. + * + * @param {boolean} [allowDecimals] + * Whether to allow decimals. + * + * @param {boolean} [hasTickAmount] + * If it has tickAmount, avoid landing on tick intervals lower than + * original. + * + * @return {number} + * The normalized interval. + * + * @todo + * Move this function to the Axis prototype. It is here only for historical + * reasons. + */ + var normalizeTickInterval = H.normalizeTickInterval = function (interval, multiples, magnitude, allowDecimals, hasTickAmount) { + var normalized, i, retInterval = interval; + // round to a tenfold of 1, 2, 2.5 or 5 + magnitude = pick(magnitude, 1); + normalized = interval / magnitude; + // multiples for a linear scale + if (!multiples) { + multiples = hasTickAmount ? + // Finer grained ticks when the tick amount is hard set, including + // when alignTicks is true on multiple axes (#4580). + [1, 1.2, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10] : + // Else, let ticks fall on rounder numbers + [1, 2, 2.5, 5, 10]; + // the allowDecimals option + if (allowDecimals === false) { + if (magnitude === 1) { + multiples = multiples.filter(function (num) { + return num % 1 === 0; + }); + } + else if (magnitude <= 0.1) { + multiples = [1 / magnitude]; + } + } + } + // normalize the interval to the nearest multiple + for (i = 0; i < multiples.length; i++) { + retInterval = multiples[i]; + // only allow tick amounts smaller than natural + if ((hasTickAmount && + retInterval * magnitude >= interval) || + (!hasTickAmount && + (normalized <= + (multiples[i] + + (multiples[i + 1] || multiples[i])) / 2))) { + break; + } + } + // Multiply back to the correct magnitude. Correct floats to appropriate + // precision (#6085). + retInterval = correctFloat(retInterval * magnitude, -Math.round(Math.log(0.001) / Math.LN10)); + return retInterval; + }; + /** + * Sort an object array and keep the order of equal items. The ECMAScript + * standard does not specify the behaviour when items are equal. + * + * @function Highcharts.stableSort + * + * @param {Array<*>} arr + * The array to sort. + * + * @param {Function} sortFunction + * The function to sort it with, like with regular Array.prototype.sort. + * + * @return {void} + */ + var stableSort = H.stableSort = function stableSort(arr, sortFunction) { + // @todo It seems like Chrome since v70 sorts in a stable way internally, + // plus all other browsers do it, so over time we may be able to remove this + // function + var length = arr.length, sortValue, i; + // Add index to each item + for (i = 0; i < length; i++) { + arr[i].safeI = i; // stable sort index + } + arr.sort(function (a, b) { + sortValue = sortFunction(a, b); + return sortValue === 0 ? a.safeI - b.safeI : sortValue; + }); + // Remove index from items + for (i = 0; i < length; i++) { + delete arr[i].safeI; // stable sort index + } + }; + /** + * Non-recursive method to find the lowest member of an array. `Math.min` raises + * a maximum call stack size exceeded error in Chrome when trying to apply more + * than 150.000 points. This method is slightly slower, but safe. + * + * @function Highcharts.arrayMin + * + * @param {Array<*>} data + * An array of numbers. + * + * @return {number} + * The lowest number. + */ + var arrayMin = H.arrayMin = function arrayMin(data) { + var i = data.length, min = data[0]; + while (i--) { + if (data[i] < min) { + min = data[i]; + } + } + return min; + }; + /** + * Non-recursive method to find the lowest member of an array. `Math.max` raises + * a maximum call stack size exceeded error in Chrome when trying to apply more + * than 150.000 points. This method is slightly slower, but safe. + * + * @function Highcharts.arrayMax + * + * @param {Array<*>} data + * An array of numbers. + * + * @return {number} + * The highest number. + */ + var arrayMax = H.arrayMax = function arrayMax(data) { + var i = data.length, max = data[0]; + while (i--) { + if (data[i] > max) { + max = data[i]; + } + } + return max; + }; + /** + * Utility method that destroys any SVGElement instances that are properties on + * the given object. It loops all properties and invokes destroy if there is a + * destroy method. The property is then delete. + * + * @function Highcharts.destroyObjectProperties + * + * @param {*} obj + * The object to destroy properties on. + * + * @param {*} [except] + * Exception, do not destroy this property, only delete it. + * + * @return {void} + */ + var destroyObjectProperties = H.destroyObjectProperties = + function destroyObjectProperties(obj, except) { + objectEach(obj, function (val, n) { + // If the object is non-null and destroy is defined + if (val && val !== except && val.destroy) { + // Invoke the destroy + val.destroy(); + } + // Delete the property from the object. + delete obj[n]; + }); + }; + /** + * Discard a HTML element by moving it to the bin and delete. + * + * @function Highcharts.discardElement + * + * @param {Highcharts.HTMLDOMElement} element + * The HTML node to discard. + * + * @return {void} + */ + var discardElement = H.discardElement = function discardElement(element) { + var garbageBin = H.garbageBin; + // create a garbage bin element, not part of the DOM + if (!garbageBin) { + garbageBin = createElement('div'); + } + // move the node and empty bin + if (element) { + garbageBin.appendChild(element); + } + garbageBin.innerHTML = ''; + }; + /** + * Fix JS round off float errors. + * + * @function Highcharts.correctFloat + * + * @param {number} num + * A float number to fix. + * + * @param {number} [prec=14] + * The precision. + * + * @return {number} + * The corrected float number. + */ + var correctFloat = H.correctFloat = function correctFloat(num, prec) { + return parseFloat(num.toPrecision(prec || 14)); + }; + /** + * Set the global animation to either a given value, or fall back to the given + * chart's animation option. + * + * @function Highcharts.setAnimation + * + * @param {boolean|Highcharts.AnimationOptionsObject|undefined} animation + * The animation object. + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @return {void} + * + * @todo + * This function always relates to a chart, and sets a property on the renderer, + * so it should be moved to the SVGRenderer. + */ + var setAnimation = H.setAnimation = function setAnimation(animation, chart) { + chart.renderer.globalAnimation = pick(animation, chart.options.chart.animation, true); + }; + /** + * Get the animation in object form, where a disabled animation is always + * returned as `{ duration: 0 }`. + * + * @function Highcharts.animObject + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=0] + * An animation setting. Can be an object with duration, complete and + * easing properties, or a boolean to enable or disable. + * + * @return {Highcharts.AnimationOptionsObject} + * An object with at least a duration property. + */ + var animObject = H.animObject = function animObject(animation) { + return isObject(animation) ? + merge(animation) : + { duration: animation ? 500 : 0 }; + }; + /** + * The time unit lookup + * + * @ignore + */ + var timeUnits = H.timeUnits = { + millisecond: 1, + second: 1000, + minute: 60000, + hour: 3600000, + day: 24 * 3600000, + week: 7 * 24 * 3600000, + month: 28 * 24 * 3600000, + year: 364 * 24 * 3600000 + }; + /** + * Format a number and return a string based on input settings. + * + * @sample highcharts/members/highcharts-numberformat/ + * Custom number format + * + * @function Highcharts.numberFormat + * + * @param {number} number + * The input number to format. + * + * @param {number} decimals + * The amount of decimals. A value of -1 preserves the amount in the + * input number. + * + * @param {string} [decimalPoint] + * The decimal point, defaults to the one given in the lang options, or + * a dot. + * + * @param {string} [thousandsSep] + * The thousands separator, defaults to the one given in the lang + * options, or a space character. + * + * @return {string} + * The formatted number. + */ + var numberFormat = H.numberFormat = function numberFormat(number, decimals, decimalPoint, thousandsSep) { + number = +number || 0; + decimals = +decimals; + var lang = H.defaultOptions.lang, origDec = (number.toString().split('.')[1] || '').split('e')[0].length, strinteger, thousands, ret, roundedNumber, exponent = number.toString().split('e'), fractionDigits; + if (decimals === -1) { + // Preserve decimals. Not huge numbers (#3793). + decimals = Math.min(origDec, 20); + } + else if (!isNumber(decimals)) { + decimals = 2; + } + else if (decimals && exponent[1] && exponent[1] < 0) { + // Expose decimals from exponential notation (#7042) + fractionDigits = decimals + +exponent[1]; + if (fractionDigits >= 0) { + // remove too small part of the number while keeping the notation + exponent[0] = (+exponent[0]).toExponential(fractionDigits) + .split('e')[0]; + decimals = fractionDigits; + } + else { + // fractionDigits < 0 + exponent[0] = exponent[0].split('.')[0] || 0; + if (decimals < 20) { + // use number instead of exponential notation (#7405) + number = (exponent[0] * Math.pow(10, exponent[1])) + .toFixed(decimals); + } + else { + // or zero + number = 0; + } + exponent[1] = 0; + } + } + // Add another decimal to avoid rounding errors of float numbers. (#4573) + // Then use toFixed to handle rounding. + roundedNumber = (Math.abs(exponent[1] ? exponent[0] : number) + + Math.pow(10, -Math.max(decimals, origDec) - 1)).toFixed(decimals); + // A string containing the positive integer component of the number + strinteger = String(pInt(roundedNumber)); + // Leftover after grouping into thousands. Can be 0, 1 or 2. + thousands = strinteger.length > 3 ? strinteger.length % 3 : 0; + // Language + decimalPoint = pick(decimalPoint, lang.decimalPoint); + thousandsSep = pick(thousandsSep, lang.thousandsSep); + // Start building the return + ret = number < 0 ? '-' : ''; + // Add the leftover after grouping into thousands. For example, in the + // number 42 000 000, this line adds 42. + ret += thousands ? strinteger.substr(0, thousands) + thousandsSep : ''; + // Add the remaining thousands groups, joined by the thousands separator + ret += strinteger + .substr(thousands) + .replace(/(\d{3})(?=\d)/g, '$1' + thousandsSep); + // Add the decimal point and the decimal component + if (decimals) { + // Get the decimal component + ret += decimalPoint + roundedNumber.slice(-decimals); + } + if (exponent[1] && +ret !== 0) { + ret += 'e' + exponent[1]; + } + return ret; + }; + /** + * Easing definition + * + * @private + * @function Math.easeInOutSine + * + * @param {number} pos + * Current position, ranging from 0 to 1. + * + * @return {number} + * Ease result + */ + Math.easeInOutSine = function (pos) { + return -0.5 * (Math.cos(Math.PI * pos) - 1); + }; + /** + * Returns the value of a property path on a given object. + * + * @private + * @function getNestedProperty + * + * @param {string} path + * Path to the property, for example `custom.myValue`. + * + * @param {unknown} obj + * Instance containing the property on the specific path. + * + * @return {unknown} + * The unknown property value. + */ + function getNestedProperty(path, obj) { + if (!path) { + return obj; + } + var pathElements = path.split('.').reverse(); + var subProperty = obj; + if (pathElements.length === 1) { + return subProperty[path]; + } + var pathElement = pathElements.pop(); + while (typeof pathElement !== 'undefined' && + typeof subProperty !== 'undefined' && + subProperty !== null) { + subProperty = subProperty[pathElement]; + pathElement = pathElements.pop(); + } + return subProperty; + } + /** + * Get the computed CSS value for given element and property, only for numerical + * properties. For width and height, the dimension of the inner box (excluding + * padding) is returned. Used for fitting the chart within the container. + * + * @function Highcharts.getStyle + * + * @param {Highcharts.HTMLDOMElement} el + * An HTML element. + * + * @param {string} prop + * The property name. + * + * @param {boolean} [toInt=true] + * Parse to integer. + * + * @return {number|string} + * The numeric value. + */ + var getStyle = H.getStyle = function (el, prop, toInt) { + var style; + // For width and height, return the actual inner pixel size (#4913) + if (prop === 'width') { + var offsetWidth = Math.min(el.offsetWidth, el.scrollWidth); + // In flex boxes, we need to use getBoundingClientRect and floor it, + // because scrollWidth doesn't support subpixel precision (#6427) ... + var boundingClientRectWidth = el.getBoundingClientRect && + el.getBoundingClientRect().width; + // ...unless if the containing div or its parents are transform-scaled + // down, in which case the boundingClientRect can't be used as it is + // also scaled down (#9871, #10498). + if (boundingClientRectWidth < offsetWidth && + boundingClientRectWidth >= offsetWidth - 1) { + offsetWidth = Math.floor(boundingClientRectWidth); + } + return Math.max(0, // #8377 + (offsetWidth - + H.getStyle(el, 'padding-left') - + H.getStyle(el, 'padding-right'))); + } + if (prop === 'height') { + return Math.max(0, // #8377 + Math.min(el.offsetHeight, el.scrollHeight) - + H.getStyle(el, 'padding-top') - + H.getStyle(el, 'padding-bottom')); + } + if (!win.getComputedStyle) { + // SVG not supported, forgot to load oldie.js? + error(27, true); + } + // Otherwise, get the computed style + style = win.getComputedStyle(el, undefined); // eslint-disable-line no-undefined + if (style) { + style = style.getPropertyValue(prop); + if (pick(toInt, prop !== 'opacity')) { + style = pInt(style); + } + } + return style; + }; + /** + * Search for an item in an array. + * + * @function Highcharts.inArray + * + * @deprecated + * + * @param {*} item + * The item to search for. + * + * @param {Array<*>} arr + * The array or node collection to search in. + * + * @param {number} [fromIndex=0] + * The index to start searching from. + * + * @return {number} + * The index within the array, or -1 if not found. + */ + var inArray = H.inArray = function (item, arr, fromIndex) { + return arr.indexOf(item, fromIndex); + }; + /* eslint-disable valid-jsdoc */ + /** + * Return the value of the first element in the array that satisfies the + * provided testing function. + * + * @function Highcharts.find + * + * @param {Array} arr + * The array to test. + * + * @param {Function} callback + * The callback function. The function receives the item as the first + * argument. Return `true` if this item satisfies the condition. + * + * @return {T|undefined} + * The value of the element. + */ + var find = H.find = Array.prototype.find ? + /* eslint-enable valid-jsdoc */ + function (arr, callback) { + return arr.find(callback); + } : + // Legacy implementation. PhantomJS, IE <= 11 etc. #7223. + function (arr, callback) { + var i, length = arr.length; + for (i = 0; i < length; i++) { + if (callback(arr[i], i)) { // eslint-disable-line callback-return + return arr[i]; + } + } + }; + /** + * Returns an array of a given object's own properties. + * + * @function Highcharts.keys + * @deprecated + * + * @param {*} obj + * The object of which the properties are to be returned. + * + * @return {Array} + * An array of strings that represents all the properties. + */ + H.keys = Object.keys; + /** + * Get the element's offset position, corrected for `overflow: auto`. + * + * @function Highcharts.offset + * + * @param {global.Element} el + * The DOM element. + * + * @return {Highcharts.OffsetObject} + * An object containing `left` and `top` properties for the position in + * the page. + */ + var offset = H.offset = function offset(el) { + var docElem = doc.documentElement, box = (el.parentElement || el.parentNode) ? + el.getBoundingClientRect() : + { top: 0, left: 0 }; + return { + top: box.top + (win.pageYOffset || docElem.scrollTop) - + (docElem.clientTop || 0), + left: box.left + (win.pageXOffset || docElem.scrollLeft) - + (docElem.clientLeft || 0) + }; + }; + /** + * Stop running animation. + * + * @function Highcharts.stop + * + * @param {Highcharts.SVGElement} el + * The SVGElement to stop animation on. + * + * @param {string} [prop] + * The property to stop animating. If given, the stop method will stop a + * single property from animating, while others continue. + * + * @return {void} + * + * @todo + * A possible extension to this would be to stop a single property, when + * we want to continue animating others. Then assign the prop to the timer + * in the Fx.run method, and check for the prop here. This would be an + * improvement in all cases where we stop the animation from .attr. Instead of + * stopping everything, we can just stop the actual attributes we're setting. + */ + var stop = H.stop = function (el, prop) { + var i = H.timers.length; + // Remove timers related to this element (#4519) + while (i--) { + if (H.timers[i].elem === el && (!prop || prop === H.timers[i].prop)) { + H.timers[i].stopped = true; // #4667 + } + } + }; + /* eslint-disable valid-jsdoc */ + /** + * Iterate over object key pairs in an object. + * + * @function Highcharts.objectEach + * + * @param {*} obj + * The object to iterate over. + * + * @param {Highcharts.ObjectEachCallbackFunction} fn + * The iterator callback. It passes three arguments: + * * value - The property value. + * * key - The property key. + * * obj - The object that objectEach is being applied to. + * + * @param {T} [ctx] + * The context. + * + * @return {void} + */ + var objectEach = H.objectEach = function objectEach(obj, fn, ctx) { + /* eslint-enable valid-jsdoc */ + for (var key in obj) { + if (Object.hasOwnProperty.call(obj, key)) { + fn.call(ctx || obj[key], obj[key], key, obj); + } + } + }; + /** + * Iterate over an array. + * + * @deprecated + * @function Highcharts.each + * + * @param {Array<*>} arr + * The array to iterate over. + * + * @param {Function} fn + * The iterator callback. It passes three arguments: + * - `item`: The array item. + * - `index`: The item's index in the array. + * - `arr`: The array that each is being applied to. + * + * @param {*} [ctx] + * The context. + * + * @return {void} + */ + /** + * Filter an array by a callback. + * + * @deprecated + * @function Highcharts.grep + * + * @param {Array<*>} arr + * The array to filter. + * + * @param {Function} callback + * The callback function. The function receives the item as the first + * argument. Return `true` if the item is to be preserved. + * + * @return {Array<*>} + * A new, filtered array. + */ + /** + * Map an array by a callback. + * + * @deprecated + * @function Highcharts.map + * + * @param {Array<*>} arr + * The array to map. + * + * @param {Function} fn + * The callback function. Return the new value for the new array. + * + * @return {Array<*>} + * A new array item with modified items. + */ + /** + * Reduce an array to a single value. + * + * @deprecated + * @function Highcharts.reduce + * + * @param {Array<*>} arr + * The array to reduce. + * + * @param {Function} fn + * The callback function. Return the reduced value. Receives 4 + * arguments: Accumulated/reduced value, current value, current array + * index, and the array. + * + * @param {*} initialValue + * The initial value of the accumulator. + * + * @return {*} + * The reduced value. + */ + /** + * Test whether at least one element in the array passes the test implemented by + * the provided function. + * + * @deprecated + * @function Highcharts.some + * + * @param {Array<*>} arr + * The array to test + * + * @param {Function} fn + * The function to run on each item. Return truty to pass the test. + * Receives arguments `currentValue`, `index` and `array`. + * + * @param {*} ctx + * The context. + * + * @return {boolean} + */ + objectEach({ + map: 'map', + each: 'forEach', + grep: 'filter', + reduce: 'reduce', + some: 'some' + }, function (val, key) { + H[key] = function (arr) { + return Array.prototype[val].apply(arr, [].slice.call(arguments, 1)); + }; + }); + /* eslint-disable valid-jsdoc */ + /** + * Add an event listener. + * + * @function Highcharts.addEvent + * + * @param {Highcharts.Class|T} el + * The element or object to add a listener to. It can be a + * {@link HTMLDOMElement}, an {@link SVGElement} or any other object. + * + * @param {string} type + * The event type. + * + * @param {Highcharts.EventCallbackFunction|Function} fn + * The function callback to execute when the event is fired. + * + * @param {Highcharts.EventOptionsObject} [options] + * Options for adding the event. + * + * @return {Function} + * A callback function to remove the added event. + */ + var addEvent = H.addEvent = function (el, type, fn, options) { + if (options === void 0) { options = {}; } + /* eslint-enable valid-jsdoc */ + var events, addEventListener = (el.addEventListener || H.addEventListenerPolyfill); + // If we're setting events directly on the constructor, use a separate + // collection, `protoEvents` to distinguish it from the item events in + // `hcEvents`. + if (typeof el === 'function' && el.prototype) { + events = el.prototype.protoEvents = el.prototype.protoEvents || {}; + } + else { + events = el.hcEvents = el.hcEvents || {}; + } + // Allow click events added to points, otherwise they will be prevented by + // the TouchPointer.pinch function after a pinch zoom operation (#7091). + if (H.Point && + el instanceof H.Point && + el.series && + el.series.chart) { + el.series.chart.runTrackerClick = true; + } + // Handle DOM events + if (addEventListener) { + addEventListener.call(el, type, fn, false); + } + if (!events[type]) { + events[type] = []; + } + var eventObject = { + fn: fn, + order: typeof options.order === 'number' ? options.order : Infinity + }; + events[type].push(eventObject); + // Order the calls + events[type].sort(function (a, b) { + return a.order - b.order; + }); + // Return a function that can be called to remove this event. + return function () { + removeEvent(el, type, fn); + }; + }; + /* eslint-disable valid-jsdoc */ + /** + * Remove an event that was added with {@link Highcharts#addEvent}. + * + * @function Highcharts.removeEvent + * + * @param {Highcharts.Class|T} el + * The element to remove events on. + * + * @param {string} [type] + * The type of events to remove. If undefined, all events are removed + * from the element. + * + * @param {Highcharts.EventCallbackFunction} [fn] + * The specific callback to remove. If undefined, all events that match + * the element and optionally the type are removed. + * + * @return {void} + */ + var removeEvent = H.removeEvent = function removeEvent(el, type, fn) { + /* eslint-enable valid-jsdoc */ + var events; + /** + * @private + * @param {string} type - event type + * @param {Highcharts.EventCallbackFunction} fn - callback + * @return {void} + */ + function removeOneEvent(type, fn) { + var removeEventListener = (el.removeEventListener || H.removeEventListenerPolyfill); + if (removeEventListener) { + removeEventListener.call(el, type, fn, false); + } + } + /** + * @private + * @param {any} eventCollection - collection + * @return {void} + */ + function removeAllEvents(eventCollection) { + var types, len; + if (!el.nodeName) { + return; // break on non-DOM events + } + if (type) { + types = {}; + types[type] = true; + } + else { + types = eventCollection; + } + objectEach(types, function (val, n) { + if (eventCollection[n]) { + len = eventCollection[n].length; + while (len--) { + removeOneEvent(n, eventCollection[n][len].fn); + } + } + }); + } + ['protoEvents', 'hcEvents'].forEach(function (coll, i) { + var eventElem = i ? el : el.prototype; + var eventCollection = eventElem && eventElem[coll]; + if (eventCollection) { + if (type) { + events = (eventCollection[type] || []); + if (fn) { + eventCollection[type] = events.filter(function (obj) { + return fn !== obj.fn; + }); + removeOneEvent(type, fn); + } + else { + removeAllEvents(eventCollection); + eventCollection[type] = []; + } + } + else { + removeAllEvents(eventCollection); + eventElem[coll] = {}; + } + } + }); + }; + /* eslint-disable valid-jsdoc */ + /** + * Fire an event that was registered with {@link Highcharts#addEvent}. + * + * @function Highcharts.fireEvent + * + * @param {T} el + * The object to fire the event on. It can be a {@link HTMLDOMElement}, + * an {@link SVGElement} or any other object. + * + * @param {string} type + * The type of event. + * + * @param {Highcharts.Dictionary<*>|Event} [eventArguments] + * Custom event arguments that are passed on as an argument to the event + * handler. + * + * @param {Highcharts.EventCallbackFunction|Function} [defaultFunction] + * The default function to execute if the other listeners haven't + * returned false. + * + * @return {void} + */ + var fireEvent = H.fireEvent = function (el, type, eventArguments, defaultFunction) { + /* eslint-enable valid-jsdoc */ + var e, i; + eventArguments = eventArguments || {}; + if (doc.createEvent && + (el.dispatchEvent || el.fireEvent)) { + e = doc.createEvent('Events'); + e.initEvent(type, true, true); + extend(e, eventArguments); + if (el.dispatchEvent) { + el.dispatchEvent(e); + } + else { + el.fireEvent(type, e); + } + } + else { + if (!eventArguments.target) { + // We're running a custom event + extend(eventArguments, { + // Attach a simple preventDefault function to skip + // default handler if called. The built-in + // defaultPrevented property is not overwritable (#5112) + preventDefault: function () { + eventArguments.defaultPrevented = true; + }, + // Setting target to native events fails with clicking + // the zoom-out button in Chrome. + target: el, + // If the type is not set, we're running a custom event + // (#2297). If it is set, we're running a browser event, + // and setting it will cause en error in IE8 (#2465). + type: type + }); + } + var fireInOrder = function (protoEvents, hcEvents) { + if (protoEvents === void 0) { protoEvents = []; } + if (hcEvents === void 0) { hcEvents = []; } + var iA = 0; + var iB = 0; + var length = protoEvents.length + hcEvents.length; + for (i = 0; i < length; i++) { + var obj = (!protoEvents[iA] ? + hcEvents[iB++] : + !hcEvents[iB] ? + protoEvents[iA++] : + protoEvents[iA].order <= hcEvents[iB].order ? + protoEvents[iA++] : + hcEvents[iB++]); + // If the event handler return false, prevent the default + // handler from executing + if (obj.fn.call(el, eventArguments) === false) { + eventArguments.preventDefault(); + } + } + }; + fireInOrder(el.protoEvents && el.protoEvents[type], el.hcEvents && el.hcEvents[type]); + } + // Run the default if not prevented + if (defaultFunction && !eventArguments.defaultPrevented) { + defaultFunction.call(el, eventArguments); + } + }; + /** + * The global animate method, which uses Fx to create individual animators. + * + * @function Highcharts.animate + * + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGElement} el + * The element to animate. + * + * @param {Highcharts.CSSObject|Highcharts.SVGAttributes} params + * An object containing key-value pairs of the properties to animate. + * Supports numeric as pixel-based CSS properties for HTML objects and + * attributes for SVGElements. + * + * @param {Highcharts.AnimationOptionsObject} [opt] + * Animation options. + * + * @return {void} + */ + var animate = H.animate = function (el, params, opt) { + var start, unit = '', end, fx, args; + if (!isObject(opt)) { // Number or undefined/null + args = arguments; + opt = { + duration: args[2], + easing: args[3], + complete: args[4] + }; + } + if (!isNumber(opt.duration)) { + opt.duration = 400; + } + opt.easing = typeof opt.easing === 'function' ? + opt.easing : + (Math[opt.easing] || Math.easeInOutSine); + opt.curAnim = merge(params); + objectEach(params, function (val, prop) { + // Stop current running animation of this property + stop(el, prop); + fx = new Fx(el, opt, prop); + end = null; + if (prop === 'd' && isArray(params.d)) { + fx.paths = fx.initPath(el, el.pathArray, params.d); + fx.toD = params.d; + start = 0; + end = 1; + } + else if (el.attr) { + start = el.attr(prop); + } + else { + start = parseFloat(getStyle(el, prop)) || 0; + if (prop !== 'opacity') { + unit = 'px'; + } + } + if (!end) { + end = val; + } + if (end && end.match && end.match('px')) { + end = end.replace(/px/g, ''); // #4351 + } + fx.run(start, end, unit); + }); + }; + /** + * Factory to create new series prototypes. + * + * @function Highcharts.seriesType + * + * @param {string} type + * The series type name. + * + * @param {string} parent + * The parent series type name. Use `line` to inherit from the basic + * {@link Series} object. + * + * @param {Highcharts.SeriesOptionsType|Highcharts.Dictionary<*>} options + * The additional default options that are merged with the parent's + * options. + * + * @param {Highcharts.Dictionary<*>} [props] + * The properties (functions and primitives) to set on the new + * prototype. + * + * @param {Highcharts.Dictionary<*>} [pointProps] + * Members for a series-specific extension of the {@link Point} + * prototype if needed. + * + * @return {Highcharts.Series} + * The newly created prototype as extended from {@link Series} or its + * derivatives. + */ + // docs: add to API + extending Highcharts + var seriesType = H.seriesType = function (type, parent, options, props, pointProps) { + var defaultOptions = H.getOptions(), seriesTypes = H.seriesTypes; + // Merge the options + defaultOptions.plotOptions[type] = merge(defaultOptions.plotOptions[parent], options); + // Create the class + seriesTypes[type] = extendClass(seriesTypes[parent] || function () { }, props); + seriesTypes[type].prototype.type = type; + // Create the point class if needed + if (pointProps) { + seriesTypes[type].prototype.pointClass = + extendClass(H.Point, pointProps); + } + return seriesTypes[type]; + }; + /** + * Get a unique key for using in internal element id's and pointers. The key is + * composed of a random hash specific to this Highcharts instance, and a + * counter. + * + * @example + * var id = uniqueKey(); // => 'highcharts-x45f6hp-0' + * + * @function Highcharts.uniqueKey + * + * @return {string} + * A unique key. + */ + var uniqueKey = H.uniqueKey = (function () { + var uniqueKeyHash = Math.random().toString(36).substring(2, 9), idCounter = 0; + return function () { + return 'highcharts-' + uniqueKeyHash + '-' + idCounter++; + }; + }()); + var isFunction = H.isFunction = function (obj) { + return typeof obj === 'function'; + }; + // Register Highcharts as a plugin in jQuery + if (win.jQuery) { + /** + * Highcharts-extended JQuery. + * + * @external JQuery + */ + /** + * Helper function to return the chart of the current JQuery selector + * element. + * + * @function external:JQuery#highcharts + * + * @return {Highcharts.Chart} + * The chart that is linked to the JQuery selector element. + */ /** + * Factory function to create a chart in the current JQuery selector + * element. + * + * @function external:JQuery#highcharts + * + * @param {'Chart'|'Map'|'StockChart'|string} [className] + * Name of the factory class in the Highcharts namespace. + * + * @param {Highcharts.Options} [options] + * The chart options structure. + * + * @param {Highcharts.ChartCallbackFunction} [callback] + * Function to run when the chart has loaded and and all external + * images are loaded. Defining a + * [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load) + * handler is equivalent. + * + * @return {JQuery} + * The current JQuery selector. + */ + win.jQuery.fn.highcharts = function () { + var args = [].slice.call(arguments); + if (this[0]) { // this[0] is the renderTo div + // Create the chart + if (args[0]) { + new H[ // eslint-disable-line computed-property-spacing, no-new + // Constructor defaults to Chart + isString(args[0]) ? args.shift() : 'Chart'](this[0], args[0], args[1]); + return this; + } + // When called without parameters or with the return argument, + // return an existing chart + return charts[attr(this[0], 'data-highcharts-chart')]; + } + }; + } + // TODO use named exports when supported. + var utilitiesModule = { + Fx: H.Fx, + addEvent: addEvent, + animate: animate, + animObject: animObject, + arrayMax: arrayMax, + arrayMin: arrayMin, + attr: attr, + clamp: clamp, + clearTimeout: internalClearTimeout, + correctFloat: correctFloat, + createElement: createElement, + css: css, + defined: defined, + destroyObjectProperties: destroyObjectProperties, + discardElement: discardElement, + erase: erase, + error: error, + extend: extend, + extendClass: extendClass, + find: find, + fireEvent: fireEvent, + format: format, + getMagnitude: getMagnitude, + getNestedProperty: getNestedProperty, + getStyle: getStyle, + inArray: inArray, + isArray: isArray, + isClass: isClass, + isDOMElement: isDOMElement, + isFunction: isFunction, + isNumber: isNumber, + isObject: isObject, + isString: isString, + merge: merge, + normalizeTickInterval: normalizeTickInterval, + numberFormat: numberFormat, + objectEach: objectEach, + offset: offset, + pad: pad, + pick: pick, + pInt: pInt, + relativeLength: relativeLength, + removeEvent: removeEvent, + seriesType: seriesType, + setAnimation: setAnimation, + splat: splat, + stableSort: stableSort, + stop: stop, + syncTimeout: syncTimeout, + timeUnits: timeUnits, + uniqueKey: uniqueKey, + wrap: wrap + }; + + return utilitiesModule; + }); + _registerModule(_modules, 'parts/Color.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * A valid color to be parsed and handled by Highcharts. Highcharts internally + * supports hex colors like `#ffffff`, rgb colors like `rgb(255,255,255)` and + * rgba colors like `rgba(255,255,255,1)`. Other colors may be supported by the + * browsers and displayed correctly, but Highcharts is not able to process them + * and apply concepts like opacity and brightening. + * + * @typedef {string} Highcharts.ColorString + */ + /** + * A valid color type than can be parsed and handled by Highcharts. It can be a + * color string, a gradient object, or a pattern object. + * + * @typedef {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} Highcharts.ColorType + */ + /** + * Gradient options instead of a solid color. + * + * @example + * // Linear gradient used as a color option + * color: { + * linearGradient: { x1: 0, x2: 0, y1: 0, y2: 1 }, + * stops: [ + * [0, '#003399'], // start + * [0.5, '#ffffff'], // middle + * [1, '#3366AA'] // end + * ] + * } + * + * @interface Highcharts.GradientColorObject + */ /** + * Holds an object that defines the start position and the end position relative + * to the shape. + * @name Highcharts.GradientColorObject#linearGradient + * @type {Highcharts.LinearGradientColorObject|undefined} + */ /** + * Holds an object that defines the center position and the radius. + * @name Highcharts.GradientColorObject#radialGradient + * @type {Highcharts.RadialGradientColorObject|undefined} + */ /** + * The first item in each tuple is the position in the gradient, where 0 is the + * start of the gradient and 1 is the end of the gradient. Multiple stops can be + * applied. The second item is the color for each stop. This color can also be + * given in the rgba format. + * @name Highcharts.GradientColorObject#stops + * @type {Array} + */ + /** + * Color stop tuple. + * + * @see Highcharts.GradientColorObject + * + * @interface Highcharts.GradientColorStopObject + */ /** + * @name Highcharts.GradientColorStopObject#0 + * @type {number} + */ /** + * @name Highcharts.GradientColorStopObject#1 + * @type {Highcharts.ColorString} + */ /** + * @name Highcharts.GradoentColorStopObject#color + * @type {Highcharts.Color|undefined} + */ + /** + * Defines the start position and the end position for a gradient relative + * to the shape. Start position (x1, y1) and end position (x2, y2) are relative + * to the shape, where 0 means top/left and 1 is bottom/right. + * + * @interface Highcharts.LinearGradientColorObject + */ /** + * Start horizontal position of the gradient. Float ranges 0-1. + * @name Highcharts.LinearGradientColorObject#x1 + * @type {number} + */ /** + * End horizontal position of the gradient. Float ranges 0-1. + * @name Highcharts.LinearGradientColorObject#x2 + * @type {number} + */ /** + * Start vertical position of the gradient. Float ranges 0-1. + * @name Highcharts.LinearGradientColorObject#y1 + * @type {number} + */ /** + * End vertical position of the gradient. Float ranges 0-1. + * @name Highcharts.LinearGradientColorObject#y2 + * @type {number} + */ + /** + * Defines the center position and the radius for a gradient. + * + * @interface Highcharts.RadialGradientColorObject + */ /** + * Center horizontal position relative to the shape. Float ranges 0-1. + * @name Highcharts.RadialGradientColorObject#cx + * @type {number} + */ /** + * Center vertical position relative to the shape. Float ranges 0-1. + * @name Highcharts.RadialGradientColorObject#cy + * @type {number} + */ /** + * Radius relative to the shape. Float ranges 0-1. + * @name Highcharts.RadialGradientColorObject#r + * @type {number} + */ + var isNumber = U.isNumber, merge = U.merge, pInt = U.pInt; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Handle color operations. Some object methods are chainable. + * + * @class + * @name Highcharts.Color + * + * @param {Highcharts.ColorType} input + * The input color in either rbga or hex format + */ + var Color = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Color(input) { + // Collection of parsers. This can be extended from the outside by pushing + // parsers to Highcharts.Color.prototype.parsers. + this.parsers = [{ + // RGBA color + // eslint-disable-next-line max-len + regex: /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/, + parse: function (result) { + return [ + pInt(result[1]), + pInt(result[2]), + pInt(result[3]), + parseFloat(result[4], 10) + ]; + } + }, { + // RGB color + regex: /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/, + parse: function (result) { + return [pInt(result[1]), pInt(result[2]), pInt(result[3]), 1]; + } + }]; + this.rgba = []; + // Backwards compatibility, allow instanciation without new (#13053) + if (!(this instanceof Color)) { + return new Color(input); + } + this.init(input); + } + /* * + * + * Static Functions + * + * */ + /** + * Creates a color instance out of a color string or object. + * + * @function Highcharts.Color.parse + * + * @param {Highcharts.ColorType} input + * The input color in either rbga or hex format. + * + * @return {Highcharts.Color} + * Color instance. + */ + Color.parse = function (input) { + return new Color(input); + }; + /* * + * + * Functions + * + * */ + /** + * Parse the input color to rgba array + * + * @private + * @function Highcharts.Color#init + * + * @param {Highcharts.ColorType} input + * The input color in either rbga or hex format + * + * @return {void} + */ + Color.prototype.init = function (input) { + var result, rgba, i, parser, len; + this.input = input = Color.names[input && input.toLowerCase ? + input.toLowerCase() : + ''] || input; + // Gradients + if (input && input.stops) { + this.stops = input.stops.map(function (stop) { + return new Color(stop[1]); + }); + // Solid colors + } + else { + // Bitmasking as input[0] is not working for legacy IE. + if (input && + input.charAt && + input.charAt() === '#') { + len = input.length; + input = parseInt(input.substr(1), 16); + // Handle long-form, e.g. #AABBCC + if (len === 7) { + rgba = [ + (input & 0xFF0000) >> 16, + (input & 0xFF00) >> 8, + (input & 0xFF), + 1 + ]; + // Handle short-form, e.g. #ABC + // In short form, the value is assumed to be the same + // for both nibbles for each component. e.g. #ABC = #AABBCC + } + else if (len === 4) { + rgba = [ + (((input & 0xF00) >> 4) | + (input & 0xF00) >> 8), + (((input & 0xF0) >> 4) | + (input & 0xF0)), + ((input & 0xF) << 4) | (input & 0xF), + 1 + ]; + } + } + // Otherwise, check regex parsers + if (!rgba) { + i = this.parsers.length; + while (i-- && !rgba) { + parser = this.parsers[i]; + result = parser.regex.exec(input); + if (result) { + rgba = parser.parse(result); + } + } + } + } + this.rgba = rgba || []; + }; + /** + * Return the color or gradient stops in the specified format + * + * @function Highcharts.Color#get + * + * @param {string} [format] + * Possible values are 'a', 'rgb', 'rgba' (default). + * + * @return {Highcharts.ColorType} + * This color as a string or gradient stops. + */ + Color.prototype.get = function (format) { + var input = this.input, rgba = this.rgba, ret; + if (typeof this.stops !== 'undefined') { + ret = merge(input); + ret.stops = [].concat(ret.stops); + this.stops.forEach(function (stop, i) { + ret.stops[i] = [ + ret.stops[i][0], + stop.get(format) + ]; + }); + // it's NaN if gradient colors on a column chart + } + else if (rgba && isNumber(rgba[0])) { + if (format === 'rgb' || (!format && rgba[3] === 1)) { + ret = 'rgb(' + rgba[0] + ',' + rgba[1] + ',' + rgba[2] + ')'; + } + else if (format === 'a') { + ret = rgba[3]; + } + else { + ret = 'rgba(' + rgba.join(',') + ')'; + } + } + else { + ret = input; + } + return ret; + }; + /** + * Brighten the color instance. + * + * @function Highcharts.Color#brighten + * + * @param {number} alpha + * The alpha value. + * + * @return {Highcharts.Color} + * This color with modifications. + */ + Color.prototype.brighten = function (alpha) { + var i, rgba = this.rgba; + if (this.stops) { + this.stops.forEach(function (stop) { + stop.brighten(alpha); + }); + } + else if (isNumber(alpha) && alpha !== 0) { + for (i = 0; i < 3; i++) { + rgba[i] += pInt(alpha * 255); + if (rgba[i] < 0) { + rgba[i] = 0; + } + if (rgba[i] > 255) { + rgba[i] = 255; + } + } + } + return this; + }; + /** + * Set the color's opacity to a given alpha value. + * + * @function Highcharts.Color#setOpacity + * + * @param {number} alpha + * Opacity between 0 and 1. + * + * @return {Highcharts.Color} + * Color with modifications. + */ + Color.prototype.setOpacity = function (alpha) { + this.rgba[3] = alpha; + return this; + }; + /** + * Return an intermediate color between two colors. + * + * @function Highcharts.Color#tweenTo + * + * @param {Highcharts.Color} to + * The color object to tween to. + * + * @param {number} pos + * The intermediate position, where 0 is the from color (current + * color item), and 1 is the `to` color. + * + * @return {Highcharts.ColorString} + * The intermediate color in rgba notation. + */ + Color.prototype.tweenTo = function (to, pos) { + // Check for has alpha, because rgba colors perform worse due to lack of + // support in WebKit. + var fromRgba = this.rgba, toRgba = to.rgba, hasAlpha, ret; + // Unsupported color, return to-color (#3920, #7034) + if (!toRgba.length || !fromRgba || !fromRgba.length) { + ret = to.input || 'none'; + // Interpolate + } + else { + hasAlpha = (toRgba[3] !== 1 || fromRgba[3] !== 1); + ret = (hasAlpha ? 'rgba(' : 'rgb(') + + Math.round(toRgba[0] + (fromRgba[0] - toRgba[0]) * (1 - pos)) + + ',' + + Math.round(toRgba[1] + (fromRgba[1] - toRgba[1]) * (1 - pos)) + + ',' + + Math.round(toRgba[2] + (fromRgba[2] - toRgba[2]) * (1 - pos)) + + (hasAlpha ? + (',' + + (toRgba[3] + (fromRgba[3] - toRgba[3]) * (1 - pos))) : + '') + + ')'; + } + return ret; + }; + /* * + * + * Static Properties + * + * */ + // Collection of named colors. Can be extended from the outside by adding + // colors to Highcharts.Color.names. + Color.names = { + white: '#ffffff', + black: '#000000' + }; + return Color; + }()); + H.Color = Color; + /** + * Creates a color instance out of a color string. + * + * @function Highcharts.color + * + * @param {Highcharts.ColorType} input + * The input color in either rbga or hex format + * + * @return {Highcharts.Color} + * Color instance + */ + H.color = Color.parse; + + return H.Color; + }); + _registerModule(_modules, 'parts/SVGElement.js', [_modules['parts/Color.js'], _modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (Color, H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var deg2rad = H.deg2rad, doc = H.doc, hasTouch = H.hasTouch, isFirefox = H.isFirefox, noop = H.noop, svg = H.svg, SVG_NS = H.SVG_NS, win = H.win; + var animate = U.animate, animObject = U.animObject, attr = U.attr, createElement = U.createElement, css = U.css, defined = U.defined, erase = U.erase, extend = U.extend, fireEvent = U.fireEvent, inArray = U.inArray, isArray = U.isArray, isFunction = U.isFunction, isNumber = U.isNumber, isString = U.isString, merge = U.merge, objectEach = U.objectEach, pick = U.pick, pInt = U.pInt, stop = U.stop, uniqueKey = U.uniqueKey; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The SVGElement prototype is a JavaScript wrapper for SVG elements used in the + * rendering layer of Highcharts. Combined with the + * {@link Highcharts.SVGRenderer} + * object, these prototypes allow freeform annotation in the charts or even in + * HTML pages without instanciating a chart. The SVGElement can also wrap HTML + * labels, when `text` or `label` elements are created with the `useHTML` + * parameter. + * + * The SVGElement instances are created through factory functions on the + * {@link Highcharts.SVGRenderer} + * object, like + * {@link Highcharts.SVGRenderer#rect|rect}, + * {@link Highcharts.SVGRenderer#path|path}, + * {@link Highcharts.SVGRenderer#text|text}, + * {@link Highcharts.SVGRenderer#label|label}, + * {@link Highcharts.SVGRenderer#g|g} + * and more. + * + * @class + * @name Highcharts.SVGElement + */ + var SVGElement = /** @class */ (function () { + function SVGElement() { + /* * + * + * Properties + * + * */ + this.element = void 0; + this.height = void 0; + this.opacity = 1; // Default base for animation + this.renderer = void 0; + this.SVG_NS = SVG_NS; + // Custom attributes used for symbols, these should be filtered out when + // setting SVGElement attributes (#9375). + this.symbolCustomAttribs = [ + 'x', + 'y', + 'width', + 'height', + 'r', + 'start', + 'end', + 'innerR', + 'anchorX', + 'anchorY', + 'rounded' + ]; + /** + * For labels, these CSS properties are applied to the `text` node directly. + * + * @private + * @name Highcharts.SVGElement#textProps + * @type {Array} + */ + this.textProps = [ + 'color', 'cursor', 'direction', 'fontFamily', 'fontSize', 'fontStyle', + 'fontWeight', 'lineHeight', 'textAlign', 'textDecoration', + 'textOutline', 'textOverflow', 'width' + ]; + this.width = void 0; + } + /* * + * + * Functions + * + * */ + /** + * Get the current value of an attribute or pseudo attribute, + * used mainly for animation. Called internally from + * the {@link Highcharts.SVGRenderer#attr} function. + * + * @private + * @function Highcharts.SVGElement#_defaultGetter + * + * @param {string} key + * Property key. + * + * @return {number|string} + * Property value. + */ + SVGElement.prototype._defaultGetter = function (key) { + var ret = pick(this[key + 'Value'], // align getter + this[key], this.element ? this.element.getAttribute(key) : null, 0); + if (/^[\-0-9\.]+$/.test(ret)) { // is numerical + ret = parseFloat(ret); + } + return ret; + }; + /** + * @private + * @function Highcharts.SVGElement#_defaultSetter + * + * @param {string} value + * + * @param {string} key + * + * @param {Highcharts.SVGDOMElement} element + * + * @return {void} + */ + SVGElement.prototype._defaultSetter = function (value, key, element) { + element.setAttribute(key, value); + }; + /** + * Add the element to the DOM. All elements must be added this way. + * + * @sample highcharts/members/renderer-g + * Elements added to a group + * + * @function Highcharts.SVGElement#add + * + * @param {Highcharts.SVGElement} [parent] + * The parent item to add it to. If undefined, the element is added + * to the {@link Highcharts.SVGRenderer.box}. + * + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.add = function (parent) { + var renderer = this.renderer, element = this.element, inserted; + if (parent) { + this.parentGroup = parent; + } + // mark as inverted + this.parentInverted = parent && parent.inverted; + // build formatted text + if (typeof this.textStr !== 'undefined') { + renderer.buildText(this); + } + // Mark as added + this.added = true; + // If we're adding to renderer root, or other elements in the group + // have a z index, we need to handle it + if (!parent || parent.handleZ || this.zIndex) { + inserted = this.zIndexSetter(); + } + // If zIndex is not handled, append at the end + if (!inserted) { + (parent ? + parent.element : + renderer.box).appendChild(element); + } + // fire an event for internal hooks + if (this.onAdd) { + this.onAdd(); + } + return this; + }; + /** + * Add a class name to an element. + * + * @function Highcharts.SVGElement#addClass + * + * @param {string} className + * The new class name to add. + * + * @param {boolean} [replace=false] + * When true, the existing class name(s) will be overwritten with the new + * one. When false, the new one is added. + * + * @return {Highcharts.SVGElement} + * Return the SVG element for chainability. + */ + SVGElement.prototype.addClass = function (className, replace) { + var currentClassName = replace ? '' : (this.attr('class') || ''); + // Trim the string and remove duplicates + className = (className || '') + .split(/ /g) + .reduce(function (newClassName, name) { + if (currentClassName.indexOf(name) === -1) { + newClassName.push(name); + } + return newClassName; + }, (currentClassName ? + [currentClassName] : + [])) + .join(' '); + if (className !== currentClassName) { + this.attr('class', className); + } + return this; + }; + /** + * This method is executed in the end of `attr()`, after setting all + * attributes in the hash. In can be used to efficiently consolidate + * multiple attributes in one SVG property -- e.g., translate, rotate and + * scale are merged in one "transform" attribute in the SVG node. + * + * @private + * @function Highcharts.SVGElement#afterSetters + */ + SVGElement.prototype.afterSetters = function () { + // Update transform. Do this outside the loop to prevent redundant + // updating for batch setting of attributes. + if (this.doTransform) { + this.updateTransform(); + this.doTransform = false; + } + }; + /** + * Align the element relative to the chart or another box. + * + * @function Highcharts.SVGElement#align + * + * @param {Highcharts.AlignObject} [alignOptions] + * The alignment options. The function can be called without this + * parameter in order to re-align an element after the box has been + * updated. + * + * @param {boolean} [alignByTranslate] + * Align element by translation. + * + * @param {string|Highcharts.BBoxObject} [box] + * The box to align to, needs a width and height. When the box is a + * string, it refers to an object in the Renderer. For example, when + * box is `spacingBox`, it refers to `Renderer.spacingBox` which + * holds `width`, `height`, `x` and `y` properties. + * + * @return {Highcharts.SVGElement} Returns the SVGElement for chaining. + */ + SVGElement.prototype.align = function (alignOptions, alignByTranslate, box) { + var align, vAlign, x, y, attribs = {}, alignTo, renderer = this.renderer, alignedObjects = renderer.alignedObjects, alignFactor, vAlignFactor; + // First call on instanciate + if (alignOptions) { + this.alignOptions = alignOptions; + this.alignByTranslate = alignByTranslate; + if (!box || isString(box)) { + this.alignTo = alignTo = box || 'renderer'; + // prevent duplicates, like legendGroup after resize + erase(alignedObjects, this); + alignedObjects.push(this); + box = void 0; // reassign it below + } + // When called on resize, no arguments are supplied + } + else { + alignOptions = this.alignOptions; + alignByTranslate = this.alignByTranslate; + alignTo = this.alignTo; + } + box = pick(box, renderer[alignTo], renderer); + // Assign variables + align = alignOptions.align; + vAlign = alignOptions.verticalAlign; + // default: left align + x = (box.x || 0) + (alignOptions.x || 0); + // default: top align + y = (box.y || 0) + (alignOptions.y || 0); + // Align + if (align === 'right') { + alignFactor = 1; + } + else if (align === 'center') { + alignFactor = 2; + } + if (alignFactor) { + x += (box.width - (alignOptions.width || 0)) / + alignFactor; + } + attribs[alignByTranslate ? 'translateX' : 'x'] = Math.round(x); + // Vertical align + if (vAlign === 'bottom') { + vAlignFactor = 1; + } + else if (vAlign === 'middle') { + vAlignFactor = 2; + } + if (vAlignFactor) { + y += (box.height - (alignOptions.height || 0)) / + vAlignFactor; + } + attribs[alignByTranslate ? 'translateY' : 'y'] = Math.round(y); + // Animate only if already placed + this[this.placed ? 'animate' : 'attr'](attribs); + this.placed = true; + this.alignAttr = attribs; + return this; + }; + /** + * @private + * @function Highcharts.SVGElement#alignSetter + * @param {"left"|"center"|"right"} value + */ + SVGElement.prototype.alignSetter = function (value) { + var convert = { + left: 'start', + center: 'middle', + right: 'end' + }; + if (convert[value]) { + this.alignValue = value; + this.element.setAttribute('text-anchor', convert[value]); + } + }; + /** + * Animate to given attributes or CSS properties. + * + * @sample highcharts/members/element-on/ + * Setting some attributes by animation + * + * @function Highcharts.SVGElement#animate + * + * @param {Highcharts.SVGAttributes} params + * SVG attributes or CSS to animate. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [options] + * Animation options. + * + * @param {Function} [complete] + * Function to perform at the end of animation. + * + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.animate = function (params, options, complete) { + var animOptions = animObject(pick(options, this.renderer.globalAnimation, true)); + // When the page is hidden save resources in the background by not + // running animation at all (#9749). + if (pick(doc.hidden, doc.msHidden, doc.webkitHidden, false)) { + animOptions.duration = 0; + } + if (animOptions.duration !== 0) { + // allows using a callback with the global animation without + // overwriting it + if (complete) { + animOptions.complete = complete; + } + animate(this, params, animOptions); + } + else { + this.attr(params, void 0, complete); + // Call the end step synchronously + objectEach(params, function (val, prop) { + if (animOptions.step) { + animOptions.step.call(this, val, { prop: prop, pos: 1 }); + } + }, this); + } + return this; + }; + /** + * Apply a text outline through a custom CSS property, by copying the text + * element and apply stroke to the copy. Used internally. Contrast checks at + * [example](https://jsfiddle.net/highcharts/43soe9m1/2/). + * + * @example + * // Specific color + * text.css({ + * textOutline: '1px black' + * }); + * // Automatic contrast + * text.css({ + * color: '#000000', // black text + * textOutline: '1px contrast' // => white outline + * }); + * + * @private + * @function Highcharts.SVGElement#applyTextOutline + * + * @param {string} textOutline + * A custom CSS `text-outline` setting, defined by `width color`. + */ + SVGElement.prototype.applyTextOutline = function (textOutline) { + var elem = this.element, tspans, hasContrast = textOutline.indexOf('contrast') !== -1, styles = {}, color, strokeWidth, firstRealChild; + // When the text shadow is set to contrast, use dark stroke for light + // text and vice versa. + if (hasContrast) { + styles.textOutline = textOutline = textOutline.replace(/contrast/g, this.renderer.getContrast(elem.style.fill)); + } + // Extract the stroke width and color + textOutline = textOutline.split(' '); + color = textOutline[textOutline.length - 1]; + strokeWidth = textOutline[0]; + if (strokeWidth && strokeWidth !== 'none' && H.svg) { + this.fakeTS = true; // Fake text shadow + tspans = [].slice.call(elem.getElementsByTagName('tspan')); + // In order to get the right y position of the clone, + // copy over the y setter + this.ySetter = this.xSetter; + // Since the stroke is applied on center of the actual outline, we + // need to double it to get the correct stroke-width outside the + // glyphs. + strokeWidth = strokeWidth.replace(/(^[\d\.]+)(.*?)$/g, function (match, digit, unit) { + return (2 * digit) + unit; + }); + // Remove shadows from previous runs. + this.removeTextOutline(tspans); + // Check if the element contains RTL characters. + // Comparing against Hebrew and Arabic characters, + // excluding Arabic digits. Source: + // https://www.unicode.org/Public/UNIDATA/extracted/DerivedBidiClass.txt + var isRTL_1 = elem.textContent ? + /^[\u0591-\u065F\u066A-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC]/ + .test(elem.textContent) : false; + // For each of the tspans, create a stroked copy behind it. + firstRealChild = elem.firstChild; + tspans.forEach(function (tspan, y) { + var clone; + // Let the first line start at the correct X position + if (y === 0) { + tspan.setAttribute('x', elem.getAttribute('x')); + y = elem.getAttribute('y'); + tspan.setAttribute('y', y || 0); + if (y === null) { + elem.setAttribute('y', 0); + } + } + // Create the clone and apply outline properties. + // For RTL elements apply outline properties for orginal element + // to prevent outline from overlapping the text. + // For RTL in Firefox keep the orginal order (#10162). + clone = tspan.cloneNode(true); + attr((isRTL_1 && !isFirefox) ? tspan : clone, { + 'class': 'highcharts-text-outline', + fill: color, + stroke: color, + 'stroke-width': strokeWidth, + 'stroke-linejoin': 'round' + }); + elem.insertBefore(clone, firstRealChild); + }); + // Create a whitespace between tspan and clone, + // to fix the display of Arabic characters in Firefox. + if (isRTL_1 && isFirefox && tspans[0]) { + var whitespace = tspans[0].cloneNode(true); + whitespace.textContent = ' '; + elem.insertBefore(whitespace, firstRealChild); + } + } + }; + /** + * @function Highcharts.SVGElement#attr + * @param {string} key + * @return {number|string} + */ /** + * Apply native and custom attributes to the SVG elements. + * + * In order to set the rotation center for rotation, set x and y to 0 and + * use `translateX` and `translateY` attributes to position the element + * instead. + * + * Attributes frequently used in Highcharts are `fill`, `stroke`, + * `stroke-width`. + * + * @sample highcharts/members/renderer-rect/ + * Setting some attributes + * + * @example + * // Set multiple attributes + * element.attr({ + * stroke: 'red', + * fill: 'blue', + * x: 10, + * y: 10 + * }); + * + * // Set a single attribute + * element.attr('stroke', 'red'); + * + * // Get an attribute + * element.attr('stroke'); // => 'red' + * + * @function Highcharts.SVGElement#attr + * + * @param {string|Highcharts.SVGAttributes} [hash] + * The native and custom SVG attributes. + * + * @param {number|string|Highcharts.SVGPathArray} [val] + * If the type of the first argument is `string`, the second can be a + * value, which will serve as a single attribute setter. If the first + * argument is a string and the second is undefined, the function + * serves as a getter and the current value of the property is + * returned. + * + * @param {Function} [complete] + * A callback function to execute after setting the attributes. This + * makes the function compliant and interchangeable with the + * {@link SVGElement#animate} function. + * + * @param {boolean} [continueAnimation=true] + * Used internally when `.attr` is called as part of an animation + * step. Otherwise, calling `.attr` for an attribute will stop + * animation for that attribute. + * + * @return {Highcharts.SVGElement} + * If used as a setter, it returns the current + * {@link Highcharts.SVGElement} so the calls can be chained. If + * used as a getter, the current value of the attribute is returned. + */ + SVGElement.prototype.attr = function (hash, val, complete, continueAnimation) { + var key, element = this.element, hasSetSymbolSize, ret = this, skipAttr, setter, symbolCustomAttribs = this.symbolCustomAttribs; + // single key-value pair + if (typeof hash === 'string' && typeof val !== 'undefined') { + key = hash; + hash = {}; + hash[key] = val; + } + // used as a getter: first argument is a string, second is undefined + if (typeof hash === 'string') { + ret = (this[hash + 'Getter'] || + this._defaultGetter).call(this, hash, element); + // setter + } + else { + objectEach(hash, function eachAttribute(val, key) { + skipAttr = false; + // Unless .attr is from the animator update, stop current + // running animation of this property + if (!continueAnimation) { + stop(this, key); + } + // Special handling of symbol attributes + if (this.symbolName && + inArray(key, symbolCustomAttribs) !== -1) { + if (!hasSetSymbolSize) { + this.symbolAttr(hash); + hasSetSymbolSize = true; + } + skipAttr = true; + } + if (this.rotation && (key === 'x' || key === 'y')) { + this.doTransform = true; + } + if (!skipAttr) { + setter = (this[key + 'Setter'] || + this._defaultSetter); + setter.call(this, val, key, element); + // Let the shadow follow the main element + if (!this.styledMode && + this.shadows && + /^(width|height|visibility|x|y|d|transform|cx|cy|r)$/.test(key)) { + this.updateShadows(key, val, setter); + } + } + }, this); + this.afterSetters(); + } + // In accordance with animate, run a complete callback + if (complete) { + complete.call(this); + } + return ret; + }; + /** + * Apply a clipping rectangle to this element. + * + * @function Highcharts.SVGElement#clip + * + * @param {Highcharts.ClipRectElement} [clipRect] + * The clipping rectangle. If skipped, the current clip is removed. + * + * @return {Highcharts.SVGElement} + * Returns the SVG element to allow chaining. + */ + SVGElement.prototype.clip = function (clipRect) { + return this.attr('clip-path', clipRect ? + 'url(' + this.renderer.url + '#' + clipRect.id + ')' : + 'none'); + }; + /** + * Calculate the coordinates needed for drawing a rectangle crisply and + * return the calculated attributes. + * + * @function Highcharts.SVGElement#crisp + * + * @param {Highcharts.RectangleObject} rect + * Rectangle to crisp. + * + * @param {number} [strokeWidth] + * The stroke width to consider when computing crisp positioning. It can + * also be set directly on the rect parameter. + * + * @return {Highcharts.RectangleObject} + * The modified rectangle arguments. + */ + SVGElement.prototype.crisp = function (rect, strokeWidth) { + var wrapper = this, normalizer; + strokeWidth = strokeWidth || rect.strokeWidth || 0; + // Math.round because strokeWidth can sometimes have roundoff errors + normalizer = Math.round(strokeWidth) % 2 / 2; + // normalize for crisp edges + rect.x = Math.floor(rect.x || wrapper.x || 0) + normalizer; + rect.y = Math.floor(rect.y || wrapper.y || 0) + normalizer; + rect.width = Math.floor((rect.width || wrapper.width || 0) - 2 * normalizer); + rect.height = Math.floor((rect.height || wrapper.height || 0) - 2 * normalizer); + if (defined(rect.strokeWidth)) { + rect.strokeWidth = strokeWidth; + } + return rect; + }; + /** + * Build and apply an SVG gradient out of a common JavaScript configuration + * object. This function is called from the attribute setters. An event + * hook is added for supporting other complex color types. + * + * @private + * @function Highcharts.SVGElement#complexColor + * + * @param {Highcharts.GradientColorObject|Highcharts.PatternObject} colorOptions + * The gradient or pattern options structure. + * + * @param {string} prop + * The property to apply, can either be `fill` or `stroke`. + * + * @param {Highcharts.SVGDOMElement} elem + * SVG element to apply the gradient on. + */ + SVGElement.prototype.complexColor = function (colorOptions, prop, elem) { + var renderer = this.renderer, colorObject, gradName, gradAttr, radAttr, gradients, stops, stopColor, stopOpacity, radialReference, id, key = [], value; + fireEvent(this.renderer, 'complexColor', { + args: arguments + }, function () { + // Apply linear or radial gradients + if (colorOptions.radialGradient) { + gradName = 'radialGradient'; + } + else if (colorOptions.linearGradient) { + gradName = 'linearGradient'; + } + if (gradName) { + gradAttr = colorOptions[gradName]; + gradients = renderer.gradients; + stops = colorOptions.stops; + radialReference = elem.radialReference; + // Keep < 2.2 kompatibility + if (isArray(gradAttr)) { + colorOptions[gradName] = gradAttr = { + x1: gradAttr[0], + y1: gradAttr[1], + x2: gradAttr[2], + y2: gradAttr[3], + gradientUnits: 'userSpaceOnUse' + }; + } + // Correct the radial gradient for the radial reference system + if (gradName === 'radialGradient' && + radialReference && + !defined(gradAttr.gradientUnits)) { + // Save the radial attributes for updating + radAttr = gradAttr; + gradAttr = merge(gradAttr, renderer.getRadialAttr(radialReference, radAttr), { gradientUnits: 'userSpaceOnUse' }); + } + // Build the unique key to detect whether we need to create a + // new element (#1282) + objectEach(gradAttr, function (val, n) { + if (n !== 'id') { + key.push(n, val); + } + }); + objectEach(stops, function (val) { + key.push(val); + }); + key = key.join(','); + // Check if a gradient object with the same config object is + // created within this renderer + if (gradients[key]) { + id = gradients[key].attr('id'); + } + else { + // Set the id and create the element + gradAttr.id = id = uniqueKey(); + var gradientObject_1 = gradients[key] = + renderer.createElement(gradName) + .attr(gradAttr) + .add(renderer.defs); + gradientObject_1.radAttr = radAttr; + // The gradient needs to keep a list of stops to be able to + // destroy them + gradientObject_1.stops = []; + stops.forEach(function (stop) { + var stopObject; + if (stop[1].indexOf('rgba') === 0) { + colorObject = Color.parse(stop[1]); + stopColor = colorObject.get('rgb'); + stopOpacity = colorObject.get('a'); + } + else { + stopColor = stop[1]; + stopOpacity = 1; + } + stopObject = renderer.createElement('stop').attr({ + offset: stop[0], + 'stop-color': stopColor, + 'stop-opacity': stopOpacity + }).add(gradientObject_1); + // Add the stop element to the gradient + gradientObject_1.stops.push(stopObject); + }); + } + // Set the reference to the gradient object + value = 'url(' + renderer.url + '#' + id + ')'; + elem.setAttribute(prop, value); + elem.gradient = key; + // Allow the color to be concatenated into tooltips formatters + // etc. (#2995) + colorOptions.toString = function () { + return value; + }; + } + }); + }; + /** + * Set styles for the element. In addition to CSS styles supported by + * native SVG and HTML elements, there are also some custom made for + * Highcharts, like `width`, `ellipsis` and `textOverflow` for SVG text + * elements. + * + * @sample highcharts/members/renderer-text-on-chart/ + * Styled text + * + * @function Highcharts.SVGElement#css + * + * @param {Highcharts.CSSObject} styles + * The new CSS styles. + * + * @return {Highcharts.SVGElement} + * Return the SVG element for chaining. + */ + SVGElement.prototype.css = function (styles) { + var oldStyles = this.styles, newStyles = {}, elem = this.element, textWidth, serializedCss = '', hyphenate, hasNew = !oldStyles, + // These CSS properties are interpreted internally by the SVG + // renderer, but are not supported by SVG and should not be added to + // the DOM. In styled mode, no CSS should find its way to the DOM + // whatsoever (#6173, #6474). + svgPseudoProps = ['textOutline', 'textOverflow', 'width']; + // convert legacy + if (styles && styles.color) { + styles.fill = styles.color; + } + // Filter out existing styles to increase performance (#2640) + if (oldStyles) { + objectEach(styles, function (style, n) { + if (oldStyles && oldStyles[n] !== style) { + newStyles[n] = style; + hasNew = true; + } + }); + } + if (hasNew) { + // Merge the new styles with the old ones + if (oldStyles) { + styles = extend(oldStyles, newStyles); + } + // Get the text width from style + if (styles) { + // Previously set, unset it (#8234) + if (styles.width === null || styles.width === 'auto') { + delete this.textWidth; + // Apply new + } + else if (elem.nodeName.toLowerCase() === 'text' && + styles.width) { + textWidth = this.textWidth = pInt(styles.width); + } + } + // store object + this.styles = styles; + if (textWidth && (!svg && this.renderer.forExport)) { + delete styles.width; + } + // Serialize and set style attribute + if (elem.namespaceURI === this.SVG_NS) { // #7633 + hyphenate = function (a, b) { + return '-' + b.toLowerCase(); + }; + objectEach(styles, function (style, n) { + if (svgPseudoProps.indexOf(n) === -1) { + serializedCss += + n.replace(/([A-Z])/g, hyphenate) + ':' + + style + ';'; + } + }); + if (serializedCss) { + attr(elem, 'style', serializedCss); // #1881 + } + } + else { + css(elem, styles); + } + if (this.added) { + // Rebuild text after added. Cache mechanisms in the buildText + // will prevent building if there are no significant changes. + if (this.element.nodeName === 'text') { + this.renderer.buildText(this); + } + // Apply text outline after added + if (styles && styles.textOutline) { + this.applyTextOutline(styles.textOutline); + } + } + } + return this; + }; + /** + * @private + * @function Highcharts.SVGElement#dashstyleSetter + * @param {string} value + */ + SVGElement.prototype.dashstyleSetter = function (value) { + var i, strokeWidth = this['stroke-width']; + // If "inherit", like maps in IE, assume 1 (#4981). With HC5 and the new + // strokeWidth function, we should be able to use that instead. + if (strokeWidth === 'inherit') { + strokeWidth = 1; + } + value = value && value.toLowerCase(); + if (value) { + var v = value + .replace('shortdashdotdot', '3,1,1,1,1,1,') + .replace('shortdashdot', '3,1,1,1') + .replace('shortdot', '1,1,') + .replace('shortdash', '3,1,') + .replace('longdash', '8,3,') + .replace(/dot/g, '1,3,') + .replace('dash', '4,3,') + .replace(/,$/, '') + .split(','); // ending comma + i = v.length; + while (i--) { + v[i] = '' + (pInt(v[i]) * pick(strokeWidth, NaN)); + } + value = v.join(',').replace(/NaN/g, 'none'); // #3226 + this.element.setAttribute('stroke-dasharray', value); + } + }; + /** + * Destroy the element and element wrapper and clear up the DOM and event + * hooks. + * + * @function Highcharts.SVGElement#destroy + */ + SVGElement.prototype.destroy = function () { + var wrapper = this, element = wrapper.element || {}, renderer = wrapper.renderer, parentToClean = (renderer.isSVG && + element.nodeName === 'SPAN' && + wrapper.parentGroup || + void 0), grandParent, ownerSVGElement = element.ownerSVGElement, i; + // remove events + element.onclick = element.onmouseout = element.onmouseover = + element.onmousemove = element.point = null; + stop(wrapper); // stop running animations + if (wrapper.clipPath && ownerSVGElement) { + var clipPath_1 = wrapper.clipPath; + // Look for existing references to this clipPath and remove them + // before destroying the element (#6196). + // The upper case version is for Edge + [].forEach.call(ownerSVGElement.querySelectorAll('[clip-path],[CLIP-PATH]'), function (el) { + var clipPathAttr = el.getAttribute('clip-path'); + if (clipPathAttr.indexOf(clipPath_1.element.id) > -1) { + el.removeAttribute('clip-path'); + } + }); + wrapper.clipPath = clipPath_1.destroy(); + } + // Destroy stops in case this is a gradient object @todo old code? + if (wrapper.stops) { + for (i = 0; i < wrapper.stops.length; i++) { + wrapper.stops[i].destroy(); + } + wrapper.stops.length = 0; + wrapper.stops = void 0; + } + // remove element + wrapper.safeRemoveChild(element); + if (!renderer.styledMode) { + wrapper.destroyShadows(); + } + // In case of useHTML, clean up empty containers emulating SVG groups + // (#1960, #2393, #2697). + while (parentToClean && + parentToClean.div && + parentToClean.div.childNodes.length === 0) { + grandParent = parentToClean.parentGroup; + wrapper.safeRemoveChild(parentToClean.div); + delete parentToClean.div; + parentToClean = grandParent; + } + // remove from alignObjects + if (wrapper.alignTo) { + erase(renderer.alignedObjects, wrapper); + } + objectEach(wrapper, function (val, key) { + // Destroy child elements of a group + if (wrapper[key] && + wrapper[key].parentGroup === wrapper && + wrapper[key].destroy) { + wrapper[key].destroy(); + } + // Delete all properties + delete wrapper[key]; + }); + return; + }; + /** + * Destroy shadows on the element. + * + * @private + * @function Highcharts.SVGElement#destroyShadows + * + * @return {void} + */ + SVGElement.prototype.destroyShadows = function () { + (this.shadows || []).forEach(function (shadow) { + this.safeRemoveChild(shadow); + }, this); + this.shadows = void 0; + }; + /** + * @private + */ + SVGElement.prototype.destroyTextPath = function (elem, path) { + var textElement = elem.getElementsByTagName('text')[0]; + var tspans; + if (textElement) { + // Remove textPath attributes + textElement.removeAttribute('dx'); + textElement.removeAttribute('dy'); + // Remove ID's: + path.element.setAttribute('id', ''); + // Check if textElement includes textPath, + if (this.textPathWrapper && + textElement.getElementsByTagName('textPath').length) { + // Move nodes to + tspans = this.textPathWrapper.element.childNodes; + // Now move all 's to the node + while (tspans.length) { + textElement.appendChild(tspans[0]); + } + // Remove from the DOM + textElement.removeChild(this.textPathWrapper.element); + } + } + else if (elem.getAttribute('dx') || elem.getAttribute('dy')) { + // Remove textPath attributes from elem + // to get correct text-outline position + elem.removeAttribute('dx'); + elem.removeAttribute('dy'); + } + if (this.textPathWrapper) { + // Set textPathWrapper to undefined and destroy it + this.textPathWrapper = this.textPathWrapper.destroy(); + } + }; + /** + * @private + * @function Highcharts.SVGElement#dSettter + * @param {number|string|Highcharts.SVGPathArray} value + * @param {string} key + * @param {Highcharts.SVGDOMElement} element + */ + SVGElement.prototype.dSetter = function (value, key, element) { + if (isArray(value)) { + // Backwards compatibility, convert one-dimensional array into an + // array of segments + if (typeof value[0] === 'string') { + value = this.renderer.pathToSegments(value); + } + this.pathArray = value; + value = value.reduce(function (acc, seg, i) { + if (!seg || !seg.join) { + return (seg || '').toString(); + } + return (i ? acc + ' ' : '') + seg.join(' '); + }, ''); + } + if (/(NaN| {2}|^$)/.test(value)) { + value = 'M 0 0'; + } + // Check for cache before resetting. Resetting causes disturbance in the + // DOM, causing flickering in some cases in Edge/IE (#6747). Also + // possible performance gain. + if (this[key] !== value) { + element.setAttribute(key, value); + this[key] = value; + } + }; + /** + * Fade out an element by animating its opacity down to 0, and hide it on + * complete. Used internally for the tooltip. + * + * @function Highcharts.SVGElement#fadeOut + * + * @param {number} [duration=150] + * The fade duration in milliseconds. + */ + SVGElement.prototype.fadeOut = function (duration) { + var elemWrapper = this; + elemWrapper.animate({ + opacity: 0 + }, { + duration: pick(duration, 150), + complete: function () { + // #3088, assuming we're only using this for tooltips + elemWrapper.attr({ y: -9999 }).hide(); + } + }); + }; + /** + * @private + * @function Highcharts.SVGElement#fillSetter + * @param {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} value + * @param {string} key + * @param {Highcharts.SVGDOMElement} element + */ + SVGElement.prototype.fillSetter = function (value, key, element) { + if (typeof value === 'string') { + element.setAttribute(key, value); + } + else if (value) { + this.complexColor(value, key, element); + } + }; + /** + * Get the bounding box (width, height, x and y) for the element. Generally + * used to get rendered text size. Since this is called a lot in charts, + * the results are cached based on text properties, in order to save DOM + * traffic. The returned bounding box includes the rotation, so for example + * a single text line of rotation 90 will report a greater height, and a + * width corresponding to the line-height. + * + * @sample highcharts/members/renderer-on-chart/ + * Draw a rectangle based on a text's bounding box + * + * @function Highcharts.SVGElement#getBBox + * + * @param {boolean} [reload] + * Skip the cache and get the updated DOM bouding box. + * + * @param {number} [rot] + * Override the element's rotation. This is internally used on axis + * labels with a value of 0 to find out what the bounding box would + * be have been if it were not rotated. + * + * @return {Highcharts.BBoxObject} + * The bounding box with `x`, `y`, `width` and `height` properties. + */ + SVGElement.prototype.getBBox = function (reload, rot) { + var wrapper = this, bBox, // = wrapper.bBox, + renderer = wrapper.renderer, width, height, element = wrapper.element, styles = wrapper.styles, fontSize, textStr = wrapper.textStr, toggleTextShadowShim, cache = renderer.cache, cacheKeys = renderer.cacheKeys, isSVG = element.namespaceURI === wrapper.SVG_NS, cacheKey; + var rotation = pick(rot, wrapper.rotation, 0); + fontSize = renderer.styledMode ? (element && + SVGElement.prototype.getStyle.call(element, 'font-size')) : (styles && styles.fontSize); + // Avoid undefined and null (#7316) + if (defined(textStr)) { + cacheKey = textStr.toString(); + // Since numbers are monospaced, and numerical labels appear a lot + // in a chart, we assume that a label of n characters has the same + // bounding box as others of the same length. Unless there is inner + // HTML in the label. In that case, leave the numbers as is (#5899). + if (cacheKey.indexOf('<') === -1) { + cacheKey = cacheKey.replace(/[0-9]/g, '0'); + } + // Properties that affect bounding box + cacheKey += [ + '', + rotation, + fontSize, + wrapper.textWidth, + styles && styles.textOverflow, + styles && styles.fontWeight // #12163 + ].join(','); + } + if (cacheKey && !reload) { + bBox = cache[cacheKey]; + } + // No cache found + if (!bBox) { + // SVG elements + if (isSVG || renderer.forExport) { + try { // Fails in Firefox if the container has display: none. + // When the text shadow shim is used, we need to hide the + // fake shadows to get the correct bounding box (#3872) + toggleTextShadowShim = this.fakeTS && function (display) { + [].forEach.call(element.querySelectorAll('.highcharts-text-outline'), function (tspan) { + tspan.style.display = display; + }); + }; + // Workaround for #3842, Firefox reporting wrong bounding + // box for shadows + if (isFunction(toggleTextShadowShim)) { + toggleTextShadowShim('none'); + } + bBox = element.getBBox ? + // SVG: use extend because IE9 is not allowed to change + // width and height in case of rotation (below) + extend({}, element.getBBox()) : { + // Legacy IE in export mode + width: element.offsetWidth, + height: element.offsetHeight + }; + // #3842 + if (isFunction(toggleTextShadowShim)) { + toggleTextShadowShim(''); + } + } + catch (e) { + ''; + } + // If the bBox is not set, the try-catch block above failed. The + // other condition is for Opera that returns a width of + // -Infinity on hidden elements. + if (!bBox || bBox.width < 0) { + bBox = { width: 0, height: 0 }; + } + // VML Renderer or useHTML within SVG + } + else { + bBox = wrapper.htmlGetBBox(); + } + // True SVG elements as well as HTML elements in modern browsers + // using the .useHTML option need to compensated for rotation + if (renderer.isSVG) { + width = bBox.width; + height = bBox.height; + // Workaround for wrong bounding box in IE, Edge and Chrome on + // Windows. With Highcharts' default font, IE and Edge report + // a box height of 16.899 and Chrome rounds it to 17. If this + // stands uncorrected, it results in more padding added below + // the text than above when adding a label border or background. + // Also vertical positioning is affected. + // https://jsfiddle.net/highcharts/em37nvuj/ + // (#1101, #1505, #1669, #2568, #6213). + if (isSVG) { + bBox.height = height = ({ + '11px,17': 14, + '13px,20': 16 + }[styles && + styles.fontSize + ',' + Math.round(height)] || + height); + } + // Adjust for rotated text + if (rotation) { + var rad = rotation * deg2rad; + bBox.width = Math.abs(height * Math.sin(rad)) + + Math.abs(width * Math.cos(rad)); + bBox.height = Math.abs(height * Math.cos(rad)) + + Math.abs(width * Math.sin(rad)); + } + } + // Cache it. When loading a chart in a hidden iframe in Firefox and + // IE/Edge, the bounding box height is 0, so don't cache it (#5620). + if (cacheKey && bBox.height > 0) { + // Rotate (#4681) + while (cacheKeys.length > 250) { + delete cache[cacheKeys.shift()]; + } + if (!cache[cacheKey]) { + cacheKeys.push(cacheKey); + } + cache[cacheKey] = bBox; + } + } + return bBox; + }; + /** + * Get the computed style. Only in styled mode. + * + * @example + * chart.series[0].points[0].graphic.getStyle('stroke-width'); // => '1px' + * + * @function Highcharts.SVGElement#getStyle + * + * @param {string} prop + * The property name to check for. + * + * @return {string} + * The current computed value. + */ + SVGElement.prototype.getStyle = function (prop) { + return win + .getComputedStyle(this.element || this, '') + .getPropertyValue(prop); + }; + /** + * Check if an element has the given class name. + * + * @function Highcharts.SVGElement#hasClass + * + * @param {string} className + * The class name to check for. + * + * @return {boolean} + * Whether the class name is found. + */ + SVGElement.prototype.hasClass = function (className) { + return ('' + this.attr('class')) + .split(' ') + .indexOf(className) !== -1; + }; + /** + * Hide the element, similar to setting the `visibility` attribute to + * `hidden`. + * + * @function Highcharts.SVGElement#hide + * + * @param {boolean} [hideByTranslation=false] + * The flag to determine if element should be hidden by moving out + * of the viewport. Used for example for dataLabels. + * + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.hide = function (hideByTranslation) { + if (hideByTranslation) { + this.attr({ y: -9999 }); + } + else { + this.attr({ visibility: 'hidden' }); + } + return this; + }; + /** + * @private + */ + SVGElement.prototype.htmlGetBBox = function () { + return { height: 0, width: 0, x: 0, y: 0 }; + }; + /** + * Initialize the SVG element. This function only exists to make the + * initialization process overridable. It should not be called directly. + * + * @function Highcharts.SVGElement#init + * + * @param {Highcharts.SVGRenderer} renderer + * The SVGRenderer instance to initialize to. + * + * @param {string} nodeName + * The SVG node name. + */ + SVGElement.prototype.init = function (renderer, nodeName) { + /** + * The primary DOM node. Each `SVGElement` instance wraps a main DOM + * node, but may also represent more nodes. + * + * @name Highcharts.SVGElement#element + * @type {Highcharts.SVGDOMElement|Highcharts.HTMLDOMElement} + */ + this.element = nodeName === 'span' ? + createElement(nodeName) : + doc.createElementNS(this.SVG_NS, nodeName); + /** + * The renderer that the SVGElement belongs to. + * + * @name Highcharts.SVGElement#renderer + * @type {Highcharts.SVGRenderer} + */ + this.renderer = renderer; + fireEvent(this, 'afterInit'); + }; + /** + * Invert a group, rotate and flip. This is used internally on inverted + * charts, where the points and graphs are drawn as if not inverted, then + * the series group elements are inverted. + * + * @function Highcharts.SVGElement#invert + * + * @param {boolean} inverted + * Whether to invert or not. An inverted shape can be un-inverted by + * setting it to false. + * + * @return {Highcharts.SVGElement} + * Return the SVGElement for chaining. + */ + SVGElement.prototype.invert = function (inverted) { + var wrapper = this; + wrapper.inverted = inverted; + wrapper.updateTransform(); + return wrapper; + }; + /** + * Add an event listener. This is a simple setter that replaces all other + * events of the same type, opposed to the {@link Highcharts#addEvent} + * function. + * + * @sample highcharts/members/element-on/ + * A clickable rectangle + * + * @function Highcharts.SVGElement#on + * + * @param {string} eventType + * The event type. If the type is `click`, Highcharts will internally + * translate it to a `touchstart` event on touch devices, to prevent the + * browser from waiting for a click event from firing. + * + * @param {Function} handler + * The handler callback. + * + * @return {Highcharts.SVGElement} + * The SVGElement for chaining. + */ + SVGElement.prototype.on = function (eventType, handler) { + var svgElement = this, element = svgElement.element, touchStartPos, touchEventFired; + // touch + if (hasTouch && eventType === 'click') { + element.ontouchstart = function (e) { + // save touch position for later calculation + touchStartPos = { + clientX: e.touches[0].clientX, + clientY: e.touches[0].clientY + }; + }; + // Instead of ontouchstart, event handlers should be called + // on touchend - similar to how current mouseup events are called + element.ontouchend = function (e) { + // hasMoved is a boolean variable containing logic if page + // was scrolled, so if touch position changed more than + // ~4px (value borrowed from general touch handler) + var hasMoved = touchStartPos.clientX ? Math.sqrt(Math.pow(touchStartPos.clientX - e.changedTouches[0].clientX, 2) + + Math.pow(touchStartPos.clientY - e.changedTouches[0].clientY, 2)) >= 4 : false; + if (!hasMoved) { // only call handlers if page was not scrolled + handler.call(element, e); + } + touchEventFired = true; + // prevent other events from being fired. #9682 + e.preventDefault(); + }; + element.onclick = function (e) { + // Do not call onclick handler if touch event was fired already. + if (!touchEventFired) { + handler.call(element, e); + } + }; + } + else { + // simplest possible event model for internal use + element['on' + eventType] = handler; + } + return this; + }; + /** + * @private + * @function Highcharts.SVGElement#opacitySetter + * @param {string} value + * @param {string} key + * @param {Highcharts.SVGDOMElement} element + */ + SVGElement.prototype.opacitySetter = function (value, key, element) { + this[key] = value; + element.setAttribute(key, value); + }; + /** + * Remove a class name from the element. + * + * @function Highcharts.SVGElement#removeClass + * + * @param {string|RegExp} className + * The class name to remove. + * + * @return {Highcharts.SVGElement} Returns the SVG element for chainability. + */ + SVGElement.prototype.removeClass = function (className) { + return this.attr('class', ('' + this.attr('class')).replace(isString(className) ? + new RegExp(" ?" + className + " ?") : // #12064 + className, '')); + }; + /** + * @private + * @param {Array} tspans + * Text spans. + */ + SVGElement.prototype.removeTextOutline = function (tspans) { + // Iterate from the end to + // support removing items inside the cycle (#6472). + var i = tspans.length, tspan; + while (i--) { + tspan = tspans[i]; + if (tspan.getAttribute('class') === 'highcharts-text-outline') { + // Remove then erase + erase(tspans, this.element.removeChild(tspan)); + } + } + }; + /** + * Removes an element from the DOM. + * + * @private + * @function Highcharts.SVGElement#safeRemoveChild + * + * @param {Highcharts.SVGDOMElement|Highcharts.HTMLDOMElement} element + * The DOM node to remove. + */ + SVGElement.prototype.safeRemoveChild = function (element) { + var parentNode = element.parentNode; + if (parentNode) { + parentNode.removeChild(element); + } + }; + /** + * Set the coordinates needed to draw a consistent radial gradient across + * a shape regardless of positioning inside the chart. Used on pie slices + * to make all the slices have the same radial reference point. + * + * @function Highcharts.SVGElement#setRadialReference + * + * @param {Array} coordinates + * The center reference. The format is `[centerX, centerY, diameter]` in + * pixels. + * + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.setRadialReference = function (coordinates) { + var existingGradient = (this.element.gradient && + this.renderer.gradients[this.element.gradient]); + this.element.radialReference = coordinates; + // On redrawing objects with an existing gradient, the gradient needs + // to be repositioned (#3801) + if (existingGradient && existingGradient.radAttr) { + existingGradient.animate(this.renderer.getRadialAttr(coordinates, existingGradient.radAttr)); + } + return this; + }; + /** + * @private + * @function Highcharts.SVGElement#setTextPath + * @param {Highcharts.SVGElement} path + * Path to follow. + * @param {Highcharts.DataLabelsTextPathOptionsObject} textPathOptions + * Options. + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.setTextPath = function (path, textPathOptions) { + var elem = this.element, attribsMap = { + textAnchor: 'text-anchor' + }, attrs, adder = false, textPathElement, textPathId, textPathWrapper = this.textPathWrapper, tspans, firstTime = !textPathWrapper; + // Defaults + textPathOptions = merge(true, { + enabled: true, + attributes: { + dy: -5, + startOffset: '50%', + textAnchor: 'middle' + } + }, textPathOptions); + attrs = textPathOptions.attributes; + if (path && textPathOptions && textPathOptions.enabled) { + // In case of fixed width for a text, string is rebuilt + // (e.g. ellipsis is applied), so we need to rebuild textPath too + if (textPathWrapper && + textPathWrapper.element.parentNode === null) { + // When buildText functionality was triggered again + // and deletes textPathWrapper parentNode + firstTime = true; + textPathWrapper = textPathWrapper.destroy(); + } + else if (textPathWrapper) { + // Case after drillup when spans were added into + // the DOM outside the textPathWrapper parentGroup + this.removeTextOutline.call(textPathWrapper.parentGroup, [].slice.call(elem.getElementsByTagName('tspan'))); + } + // label() has padding, text() doesn't + if (this.options && this.options.padding) { + attrs.dx = -this.options.padding; + } + if (!textPathWrapper) { + // Create , defer the DOM adder + this.textPathWrapper = textPathWrapper = + this.renderer.createElement('textPath'); + adder = true; + } + textPathElement = textPathWrapper.element; + // Set ID for the path + textPathId = path.element.getAttribute('id'); + if (!textPathId) { + path.element.setAttribute('id', textPathId = uniqueKey()); + } + // Change DOM structure, by placing tag in + if (firstTime) { + tspans = elem.getElementsByTagName('tspan'); + // Now move all 's to the node + while (tspans.length) { + // Remove "y" from tspans, as Firefox translates them + tspans[0].setAttribute('y', 0); + // Remove "x" from tspans + if (isNumber(attrs.dx)) { + tspans[0].setAttribute('x', -attrs.dx); + } + textPathElement.appendChild(tspans[0]); + } + } + // Add to the DOM + if (adder && + textPathWrapper) { + textPathWrapper.add({ + // label() is placed in a group, text() is standalone + element: this.text ? this.text.element : elem + }); + } + // Set basic options: + // Use `setAttributeNS` because Safari needs this.. + textPathElement.setAttributeNS('http://www.w3.org/1999/xlink', 'href', this.renderer.url + '#' + textPathId); + // Presentation attributes: + // dx/dy options must by set on (parent), + // the rest should be set on + if (defined(attrs.dy)) { + textPathElement.parentNode + .setAttribute('dy', attrs.dy); + delete attrs.dy; + } + if (defined(attrs.dx)) { + textPathElement.parentNode + .setAttribute('dx', attrs.dx); + delete attrs.dx; + } + // Additional attributes + objectEach(attrs, function (val, key) { + textPathElement.setAttribute(attribsMap[key] || key, val); + }); + // Remove translation, text that follows path does not need that + elem.removeAttribute('transform'); + // Remove shadows and text outlines + this.removeTextOutline.call(textPathWrapper, [].slice.call(elem.getElementsByTagName('tspan'))); + // Remove background and border for label(), see #10545 + // Alternatively, we can disable setting background rects in + // series.drawDataLabels() + if (this.text && !this.renderer.styledMode) { + this.attr({ + fill: 'none', + 'stroke-width': 0 + }); + } + // Disable some functions + this.updateTransform = noop; + this.applyTextOutline = noop; + } + else if (textPathWrapper) { + // Reset to prototype + delete this.updateTransform; + delete this.applyTextOutline; + // Restore DOM structure: + this.destroyTextPath(elem, path); + // Bring attributes back + this.updateTransform(); + // Set textOutline back for text() + if (this.options && this.options.rotation) { + this.applyTextOutline(this.options.style.textOutline); + } + } + return this; + }; + /** + * Add a shadow to the element. Must be called after the element is added to + * the DOM. In styled mode, this method is not used, instead use `defs` and + * filters. + * + * @example + * renderer.rect(10, 100, 100, 100) + * .attr({ fill: 'red' }) + * .shadow(true); + * + * @function Highcharts.SVGElement#shadow + * + * @param {boolean|Highcharts.ShadowOptionsObject} [shadowOptions] + * The shadow options. If `true`, the default options are applied. If + * `false`, the current shadow will be removed. + * + * @param {Highcharts.SVGElement} [group] + * The SVG group element where the shadows will be applied. The + * default is to add it to the same parent as the current element. + * Internally, this is ised for pie slices, where all the shadows are + * added to an element behind all the slices. + * + * @param {boolean} [cutOff] + * Used internally for column shadows. + * + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.shadow = function (shadowOptions, group, cutOff) { + var shadows = [], i, shadow, element = this.element, strokeWidth, shadowElementOpacity, update = false, oldShadowOptions = this.oldShadowOptions, + // compensate for inverted plot area + transform; + var defaultShadowOptions = { + color: '#000000', + offsetX: 1, + offsetY: 1, + opacity: 0.15, + width: 3 + }; + var options; + if (shadowOptions === true) { + options = defaultShadowOptions; + } + else if (typeof shadowOptions === 'object') { + options = extend(defaultShadowOptions, shadowOptions); + } + // Update shadow when options change (#12091). + if (options) { + // Go over each key to look for change + if (options && oldShadowOptions) { + objectEach(options, function (value, key) { + if (value !== oldShadowOptions[key]) { + update = true; + } + }); + } + if (update) { + this.destroyShadows(); + } + this.oldShadowOptions = options; + } + if (!options) { + this.destroyShadows(); + } + else if (!this.shadows) { + shadowElementOpacity = options.opacity / options.width; + transform = this.parentInverted ? + 'translate(-1,-1)' : + "translate(" + options.offsetX + ", " + options.offsetY + ")"; + for (i = 1; i <= options.width; i++) { + shadow = element.cloneNode(false); + strokeWidth = (options.width * 2) + 1 - (2 * i); + attr(shadow, { + stroke: (shadowOptions.color || + '#000000'), + 'stroke-opacity': shadowElementOpacity * i, + 'stroke-width': strokeWidth, + transform: transform, + fill: 'none' + }); + shadow.setAttribute('class', (shadow.getAttribute('class') || '') + ' highcharts-shadow'); + if (cutOff) { + attr(shadow, 'height', Math.max(attr(shadow, 'height') - strokeWidth, 0)); + shadow.cutHeight = strokeWidth; + } + if (group) { + group.element.appendChild(shadow); + } + else if (element.parentNode) { + element.parentNode.insertBefore(shadow, element); + } + shadows.push(shadow); + } + this.shadows = shadows; + } + return this; + }; + /** + * Show the element after it has been hidden. + * + * @function Highcharts.SVGElement#show + * + * @param {boolean} [inherit=false] + * Set the visibility attribute to `inherit` rather than `visible`. + * The difference is that an element with `visibility="visible"` + * will be visible even if the parent is hidden. + * + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.show = function (inherit) { + return this.attr({ visibility: inherit ? 'inherit' : 'visible' }); + }; + /** + * WebKit and Batik have problems with a stroke-width of zero, so in this + * case we remove the stroke attribute altogether. #1270, #1369, #3065, + * #3072. + * + * @private + * @function Highcharts.SVGElement#strokeSetter + * @param {number|string} value + * @param {string} key + * @param {Highcharts.SVGDOMElement} element + */ + SVGElement.prototype.strokeSetter = function (value, key, element) { + this[key] = value; + // Only apply the stroke attribute if the stroke width is defined and + // larger than 0 + if (this.stroke && this['stroke-width']) { + // Use prototype as instance may be overridden + SVGElement.prototype.fillSetter.call(this, this.stroke, 'stroke', element); + element.setAttribute('stroke-width', this['stroke-width']); + this.hasStroke = true; + } + else if (key === 'stroke-width' && value === 0 && this.hasStroke) { + element.removeAttribute('stroke'); + this.hasStroke = false; + } + else if (this.renderer.styledMode && this['stroke-width']) { + element.setAttribute('stroke-width', this['stroke-width']); + this.hasStroke = true; + } + }; + /** + * Get the computed stroke width in pixel values. This is used extensively + * when drawing shapes to ensure the shapes are rendered crisp and + * positioned correctly relative to each other. Using + * `shape-rendering: crispEdges` leaves us less control over positioning, + * for example when we want to stack columns next to each other, or position + * things pixel-perfectly within the plot box. + * + * The common pattern when placing a shape is: + * - Create the SVGElement and add it to the DOM. In styled mode, it will + * now receive a stroke width from the style sheet. In classic mode we + * will add the `stroke-width` attribute. + * - Read the computed `elem.strokeWidth()`. + * - Place it based on the stroke width. + * + * @function Highcharts.SVGElement#strokeWidth + * + * @return {number} + * The stroke width in pixels. Even if the given stroke widtch (in CSS or by + * attributes) is based on `em` or other units, the pixel size is returned. + */ + SVGElement.prototype.strokeWidth = function () { + // In non-styled mode, read the stroke width as set by .attr + if (!this.renderer.styledMode) { + return this['stroke-width'] || 0; + } + // In styled mode, read computed stroke width + var val = this.getStyle('stroke-width'), ret = 0, dummy; + // Read pixel values directly + if (val.indexOf('px') === val.length - 2) { + ret = pInt(val); + // Other values like em, pt etc need to be measured + } + else if (val !== '') { + dummy = doc.createElementNS(SVG_NS, 'rect'); + attr(dummy, { + width: val, + 'stroke-width': 0 + }); + this.element.parentNode.appendChild(dummy); + ret = dummy.getBBox().width; + dummy.parentNode.removeChild(dummy); + } + return ret; + }; + /** + * If one of the symbol size affecting parameters are changed, + * check all the others only once for each call to an element's + * .attr() method + * + * @private + * @function Highcharts.SVGElement#symbolAttr + * + * @param {Highcharts.SVGAttributes} hash + * The attributes to set. + */ + SVGElement.prototype.symbolAttr = function (hash) { + var wrapper = this; + [ + 'x', + 'y', + 'r', + 'start', + 'end', + 'width', + 'height', + 'innerR', + 'anchorX', + 'anchorY', + 'clockwise' + ].forEach(function (key) { + wrapper[key] = pick(hash[key], wrapper[key]); + }); + wrapper.attr({ + d: wrapper.renderer.symbols[wrapper.symbolName](wrapper.x, wrapper.y, wrapper.width, wrapper.height, wrapper) + }); + }; + /** + * @private + * @function Highcharts.SVGElement#textSetter + * @param {string} value + */ + SVGElement.prototype.textSetter = function (value) { + if (value !== this.textStr) { + // Delete size caches when the text changes + // delete this.bBox; // old code in series-label + delete this.textPxLength; + this.textStr = value; + if (this.added) { + this.renderer.buildText(this); + } + } + }; + /** + * @private + * @function Highcharts.SVGElement#titleSetter + * @param {string} value + */ + SVGElement.prototype.titleSetter = function (value) { + var titleNode = this.element.getElementsByTagName('title')[0]; + if (!titleNode) { + titleNode = doc.createElementNS(this.SVG_NS, 'title'); + this.element.appendChild(titleNode); + } + // Remove text content if it exists + if (titleNode.firstChild) { + titleNode.removeChild(titleNode.firstChild); + } + titleNode.appendChild(doc.createTextNode( + // #3276, #3895 + String(pick(value, '')) + .replace(/<[^>]*>/g, '') + .replace(/</g, '<') + .replace(/>/g, '>'))); + }; + /** + * Bring the element to the front. Alternatively, a new zIndex can be set. + * + * @sample highcharts/members/element-tofront/ + * Click an element to bring it to front + * + * @function Highcharts.SVGElement#toFront + * + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.toFront = function () { + var element = this.element; + element.parentNode.appendChild(element); + return this; + }; + /** + * Move an object and its children by x and y values. + * + * @function Highcharts.SVGElement#translate + * + * @param {number} x + * The x value. + * + * @param {number} y + * The y value. + * + * @return {Highcharts.SVGElement} + */ + SVGElement.prototype.translate = function (x, y) { + return this.attr({ + translateX: x, + translateY: y + }); + }; + /** + * Update the shadow elements with new attributes. + * + * @private + * @function Highcharts.SVGElement#updateShadows + * + * @param {string} key + * The attribute name. + * + * @param {number} value + * The value of the attribute. + * + * @param {Function} setter + * The setter function, inherited from the parent wrapper. + */ + SVGElement.prototype.updateShadows = function (key, value, setter) { + var shadows = this.shadows; + if (shadows) { + var i = shadows.length; + while (i--) { + setter.call(shadows[i], key === 'height' ? + Math.max(value - (shadows[i].cutHeight || 0), 0) : + key === 'd' ? this.d : value, key, shadows[i]); + } + } + }; + /** + * Update the transform attribute based on internal properties. Deals with + * the custom `translateX`, `translateY`, `rotation`, `scaleX` and `scaleY` + * attributes and updates the SVG `transform` attribute. + * + * @private + * @function Highcharts.SVGElement#updateTransform + */ + SVGElement.prototype.updateTransform = function () { + var wrapper = this, translateX = wrapper.translateX || 0, translateY = wrapper.translateY || 0, scaleX = wrapper.scaleX, scaleY = wrapper.scaleY, inverted = wrapper.inverted, rotation = wrapper.rotation, matrix = wrapper.matrix, element = wrapper.element, transform; + // Flipping affects translate as adjustment for flipping around the + // group's axis + if (inverted) { + translateX += wrapper.width; + translateY += wrapper.height; + } + // Apply translate. Nearly all transformed elements have translation, + // so instead of checking for translate = 0, do it always (#1767, + // #1846). + transform = ['translate(' + translateX + ',' + translateY + ')']; + // apply matrix + if (defined(matrix)) { + transform.push('matrix(' + matrix.join(',') + ')'); + } + // apply rotation + if (inverted) { + transform.push('rotate(90) scale(-1,1)'); + } + else if (rotation) { // text rotation + transform.push('rotate(' + rotation + ' ' + + pick(this.rotationOriginX, element.getAttribute('x'), 0) + + ' ' + + pick(this.rotationOriginY, element.getAttribute('y') || 0) + ')'); + } + // apply scale + if (defined(scaleX) || defined(scaleY)) { + transform.push('scale(' + pick(scaleX, 1) + ' ' + pick(scaleY, 1) + ')'); + } + if (transform.length) { + element.setAttribute('transform', transform.join(' ')); + } + }; + /** + * @private + * @function Highcharts.SVGElement#visibilitySetter + * + * @param {string} value + * + * @param {string} key + * + * @param {Highcharts.SVGDOMElement} element + * + * @return {void} + */ + SVGElement.prototype.visibilitySetter = function (value, key, element) { + // IE9-11 doesn't handle visibilty:inherit well, so we remove the + // attribute instead (#2881, #3909) + if (value === 'inherit') { + element.removeAttribute(key); + } + else if (this[key] !== value) { // #6747 + element.setAttribute(key, value); + } + this[key] = value; + }; + /** + * @private + * @function Highcharts.SVGElement#xGetter + * + * @param {string} key + * + * @return {number|string|null} + */ + SVGElement.prototype.xGetter = function (key) { + if (this.element.nodeName === 'circle') { + if (key === 'x') { + key = 'cx'; + } + else if (key === 'y') { + key = 'cy'; + } + } + return this._defaultGetter(key); + }; + /** + * @private + * @function Highcharts.SVGElement#zIndexSetter + * @param {number} [value] + * @param {string} [key] + * @return {boolean} + */ + SVGElement.prototype.zIndexSetter = function (value, key) { + var renderer = this.renderer, parentGroup = this.parentGroup, parentWrapper = parentGroup || renderer, parentNode = parentWrapper.element || renderer.box, childNodes, otherElement, otherZIndex, element = this.element, inserted = false, undefinedOtherZIndex, svgParent = parentNode === renderer.box, run = this.added, i; + if (defined(value)) { + // So we can read it for other elements in the group + element.setAttribute('data-z-index', value); + value = +value; + if (this[key] === value) { + // Only update when needed (#3865) + run = false; + } + } + else if (defined(this[key])) { + element.removeAttribute('data-z-index'); + } + this[key] = value; + // Insert according to this and other elements' zIndex. Before .add() is + // called, nothing is done. Then on add, or by later calls to + // zIndexSetter, the node is placed on the right place in the DOM. + if (run) { + value = this.zIndex; + if (value && parentGroup) { + parentGroup.handleZ = true; + } + childNodes = parentNode.childNodes; + for (i = childNodes.length - 1; i >= 0 && !inserted; i--) { + otherElement = childNodes[i]; + otherZIndex = otherElement.getAttribute('data-z-index'); + undefinedOtherZIndex = !defined(otherZIndex); + if (otherElement !== element) { + if ( + // Negative zIndex versus no zIndex: + // On all levels except the highest. If the parent is + // , then we don't want to put items before + // or + value < 0 && + undefinedOtherZIndex && + !svgParent && + !i) { + parentNode.insertBefore(element, childNodes[i]); + inserted = true; + } + else if ( + // Insert after the first element with a lower zIndex + pInt(otherZIndex) <= value || + // If negative zIndex, add this before first undefined + // zIndex element + (undefinedOtherZIndex && + (!defined(value) || value >= 0))) { + parentNode.insertBefore(element, childNodes[i + 1] || null // null for oldIE export + ); + inserted = true; + } + } + } + if (!inserted) { + parentNode.insertBefore(element, childNodes[svgParent ? 3 : 0] || null // null for oldIE + ); + inserted = true; + } + } + return inserted; + }; + return SVGElement; + }()); + // Some shared setters and getters + SVGElement.prototype['stroke-widthSetter'] = SVGElement.prototype.strokeSetter; + SVGElement.prototype.yGetter = SVGElement.prototype.xGetter; + SVGElement.prototype.matrixSetter = + SVGElement.prototype.rotationOriginXSetter = + SVGElement.prototype.rotationOriginYSetter = + SVGElement.prototype.rotationSetter = + SVGElement.prototype.scaleXSetter = + SVGElement.prototype.scaleYSetter = + SVGElement.prototype.translateXSetter = + SVGElement.prototype.translateYSetter = + SVGElement.prototype.verticalAlignSetter = function (value, key) { + this[key] = value; + this.doTransform = true; + }; + H.SVGElement = SVGElement; + + return H.SVGElement; + }); + _registerModule(_modules, 'parts/SvgRenderer.js', [_modules['parts/Color.js'], _modules['parts/Globals.js'], _modules['parts/SVGElement.js'], _modules['parts/Utilities.js']], function (Color, H, SVGElement, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var color = Color.parse; + var addEvent = U.addEvent, attr = U.attr, createElement = U.createElement, css = U.css, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, erase = U.erase, extend = U.extend, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, isString = U.isString, merge = U.merge, objectEach = U.objectEach, pick = U.pick, pInt = U.pInt, removeEvent = U.removeEvent, splat = U.splat, stop = U.stop, uniqueKey = U.uniqueKey; + /** + * The horizontal alignment of an element. + * + * @typedef {"center"|"left"|"right"} Highcharts.AlignValue + */ + /** + * Options to align the element relative to the chart or another box. + * + * @interface Highcharts.AlignObject + */ /** + * Horizontal alignment. Can be one of `left`, `center` and `right`. + * + * @name Highcharts.AlignObject#align + * @type {Highcharts.AlignValue|undefined} + * + * @default left + */ /** + * Vertical alignment. Can be one of `top`, `middle` and `bottom`. + * + * @name Highcharts.AlignObject#verticalAlign + * @type {Highcharts.VerticalAlignValue|undefined} + * + * @default top + */ /** + * Horizontal pixel offset from alignment. + * + * @name Highcharts.AlignObject#x + * @type {number|undefined} + * + * @default 0 + */ /** + * Vertical pixel offset from alignment. + * + * @name Highcharts.AlignObject#y + * @type {number|undefined} + * + * @default 0 + */ /** + * Use the `transform` attribute with translateX and translateY custom + * attributes to align this elements rather than `x` and `y` attributes. + * + * @name Highcharts.AlignObject#alignByTranslate + * @type {boolean|undefined} + * + * @default false + */ + /** + * Bounding box of an element. + * + * @interface Highcharts.BBoxObject + * @extends Highcharts.PositionObject + */ /** + * Height of the bounding box. + * + * @name Highcharts.BBoxObject#height + * @type {number} + */ /** + * Width of the bounding box. + * + * @name Highcharts.BBoxObject#width + * @type {number} + */ /** + * Horizontal position of the bounding box. + * + * @name Highcharts.BBoxObject#x + * @type {number} + */ /** + * Vertical position of the bounding box. + * + * @name Highcharts.BBoxObject#y + * @type {number} + */ + /** + * A clipping rectangle that can be applied to one or more {@link SVGElement} + * instances. It is instanciated with the {@link SVGRenderer#clipRect} function + * and applied with the {@link SVGElement#clip} function. + * + * @example + * var circle = renderer.circle(100, 100, 100) + * .attr({ fill: 'red' }) + * .add(); + * var clipRect = renderer.clipRect(100, 100, 100, 100); + * + * // Leave only the lower right quarter visible + * circle.clip(clipRect); + * + * @typedef {Highcharts.SVGElement} Highcharts.ClipRectElement + */ + /** + * The font metrics. + * + * @interface Highcharts.FontMetricsObject + */ /** + * The baseline relative to the top of the box. + * + * @name Highcharts.FontMetricsObject#b + * @type {number} + */ /** + * The font size. + * + * @name Highcharts.FontMetricsObject#f + * @type {number} + */ /** + * The line height. + * + * @name Highcharts.FontMetricsObject#h + * @type {number} + */ + /** + * An object containing `x` and `y` properties for the position of an element. + * + * @interface Highcharts.PositionObject + */ /** + * X position of the element. + * @name Highcharts.PositionObject#x + * @type {number} + */ /** + * Y position of the element. + * @name Highcharts.PositionObject#y + * @type {number} + */ + /** + * A rectangle. + * + * @interface Highcharts.RectangleObject + */ /** + * Height of the rectangle. + * @name Highcharts.RectangleObject#height + * @type {number} + */ /** + * Width of the rectangle. + * @name Highcharts.RectangleObject#width + * @type {number} + */ /** + * Horizontal position of the rectangle. + * @name Highcharts.RectangleObject#x + * @type {number} + */ /** + * Vertical position of the rectangle. + * @name Highcharts.RectangleObject#y + * @type {number} + */ + /** + * The shadow options. + * + * @interface Highcharts.ShadowOptionsObject + */ /** + * The shadow color. + * @name Highcharts.ShadowOptionsObject#color + * @type {Highcharts.ColorString|undefined} + * @default #000000 + */ /** + * The horizontal offset from the element. + * + * @name Highcharts.ShadowOptionsObject#offsetX + * @type {number|undefined} + * @default 1 + */ /** + * The vertical offset from the element. + * @name Highcharts.ShadowOptionsObject#offsetY + * @type {number|undefined} + * @default 1 + */ /** + * The shadow opacity. + * + * @name Highcharts.ShadowOptionsObject#opacity + * @type {number|undefined} + * @default 0.15 + */ /** + * The shadow width or distance from the element. + * @name Highcharts.ShadowOptionsObject#width + * @type {number|undefined} + * @default 3 + */ + /** + * @interface Highcharts.SizeObject + */ /** + * @name Highcharts.SizeObject#height + * @type {number} + */ /** + * @name Highcharts.SizeObject#width + * @type {number} + */ + /** + * An object of key-value pairs for SVG attributes. Attributes in Highcharts + * elements for the most parts correspond to SVG, but some are specific to + * Highcharts, like `zIndex`, `rotation`, `rotationOriginX`, + * `rotationOriginY`, `translateX`, `translateY`, `scaleX` and `scaleY`. SVG + * attributes containing a hyphen are _not_ camel-cased, they should be + * quoted to preserve the hyphen. + * + * @example + * { + * 'stroke': '#ff0000', // basic + * 'stroke-width': 2, // hyphenated + * 'rotation': 45 // custom + * 'd': ['M', 10, 10, 'L', 30, 30, 'z'] // path definition, note format + * } + * + * @interface Highcharts.SVGAttributes + */ /** + * @name Highcharts.SVGAttributes#[key:string] + * @type {*} + */ /** + * @name Highcharts.SVGAttributes#d + * @type {string|Highcharts.SVGPathArray|undefined} + */ /** + * @name Highcharts.SVGAttributes#fill + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined} + */ /** + * @name Highcharts.SVGAttributes#inverted + * @type {boolean|undefined} + */ /** + * @name Highcharts.SVGAttributes#matrix + * @type {Array|undefined} + */ /** + * @name Highcharts.SVGAttributes#rotation + * @type {number|undefined} + */ /** + * @name Highcharts.SVGAttributes#rotationOriginX + * @type {number|undefined} + */ /** + * @name Highcharts.SVGAttributes#rotationOriginY + * @type {number|undefined} + */ /** + * @name Highcharts.SVGAttributes#scaleX + * @type {number|undefined} + */ /** + * @name Highcharts.SVGAttributes#scaleY + * @type {number|undefined} + */ /** + * @name Highcharts.SVGAttributes#stroke + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined} + */ /** + * @name Highcharts.SVGAttributes#style + * @type {string|Highcharts.CSSObject|undefined} + */ /** + * @name Highcharts.SVGAttributes#translateX + * @type {number|undefined} + */ /** + * @name Highcharts.SVGAttributes#translateY + * @type {number|undefined} + */ /** + * @name Highcharts.SVGAttributes#zIndex + * @type {number|undefined} + */ + /** + * Serialized form of an SVG definition, including children. Some key + * property names are reserved: tagName, textContent, and children. + * + * @interface Highcharts.SVGDefinitionObject + */ /** + * @name Highcharts.SVGDefinitionObject#[key:string] + * @type {boolean|number|string|Array|undefined} + */ /** + * @name Highcharts.SVGDefinitionObject#children + * @type {Array|undefined} + */ /** + * @name Highcharts.SVGDefinitionObject#tagName + * @type {string|undefined} + */ /** + * @name Highcharts.SVGDefinitionObject#textContent + * @type {string|undefined} + */ + /** + * An SVG DOM element. The type is a reference to the regular SVGElement in the + * global scope. + * + * @typedef {globals.GlobalSVGElement} Highcharts.SVGDOMElement + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/SVGElement + */ + /** + * Array of path commands, that will go into the `d` attribute of an SVG + * element. + * + * @typedef {Array} Highcharts.SVGPathArray + */ + /** + * Possible path commands in a SVG path array. + * + * @typedef {string} Highcharts.SVGPathCommand + * @validvalue ["a","c","h","l","m","q","s","t","v","z","A","C","H","L","M","Q","S","T","V","Z"] + */ + /** + * An extendable collection of functions for defining symbol paths. Symbols are + * used internally for point markers, button and label borders and backgrounds, + * or custom shapes. Extendable by adding to {@link SVGRenderer#symbols}. + * + * @interface Highcharts.SymbolDictionary + */ /** + * @name Highcharts.SymbolDictionary#[key:string] + * @type {Function|undefined} + */ /** + * @name Highcharts.SymbolDictionary#arc + * @type {Function|undefined} + */ /** + * @name Highcharts.SymbolDictionary#callout + * @type {Function|undefined} + */ /** + * @name Highcharts.SymbolDictionary#circle + * @type {Function|undefined} + */ /** + * @name Highcharts.SymbolDictionary#diamond + * @type {Function|undefined} + */ /** + * @name Highcharts.SymbolDictionary#square + * @type {Function|undefined} + */ /** + * @name Highcharts.SymbolDictionary#triangle + * @type {Function|undefined} + */ + /** + * Can be one of `arc`, `callout`, `circle`, `diamond`, `square`, `triangle`, + * and `triangle-down`. Symbols are used internally for point markers, button + * and label borders and backgrounds, or custom shapes. Extendable by adding to + * {@link SVGRenderer#symbols}. + * + * @typedef {"arc"|"callout"|"circle"|"diamond"|"square"|"triangle"|"triangle-down"} Highcharts.SymbolKeyValue + */ + /** + * Additional options, depending on the actual symbol drawn. + * + * @interface Highcharts.SymbolOptionsObject + */ /** + * The anchor X position for the `callout` symbol. This is where the chevron + * points to. + * + * @name Highcharts.SymbolOptionsObject#anchorX + * @type {number|undefined} + */ /** + * The anchor Y position for the `callout` symbol. This is where the chevron + * points to. + * + * @name Highcharts.SymbolOptionsObject#anchorY + * @type {number|undefined} + */ /** + * The end angle of an `arc` symbol. + * + * @name Highcharts.SymbolOptionsObject#end + * @type {number|undefined} + */ /** + * Whether to draw `arc` symbol open or closed. + * + * @name Highcharts.SymbolOptionsObject#open + * @type {boolean|undefined} + */ /** + * The radius of an `arc` symbol, or the border radius for the `callout` symbol. + * + * @name Highcharts.SymbolOptionsObject#r + * @type {number|undefined} + */ /** + * The start angle of an `arc` symbol. + * + * @name Highcharts.SymbolOptionsObject#start + * @type {number|undefined} + */ + /** + * The vertical alignment of an element. + * + * @typedef {"bottom"|"middle"|"top"} Highcharts.VerticalAlignValue + */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + var SVGRenderer, charts = H.charts, deg2rad = H.deg2rad, doc = H.doc, hasTouch = H.hasTouch, isFirefox = H.isFirefox, isMS = H.isMS, isWebKit = H.isWebKit, noop = H.noop, svg = H.svg, SVG_NS = H.SVG_NS, symbolSizes = H.symbolSizes, win = H.win; + /** + * Allows direct access to the Highcharts rendering layer in order to draw + * primitive shapes like circles, rectangles, paths or text directly on a chart, + * or independent from any chart. The SVGRenderer represents a wrapper object + * for SVG in modern browsers. Through the VMLRenderer, part of the `oldie.js` + * module, it also brings vector graphics to IE <= 8. + * + * An existing chart's renderer can be accessed through {@link Chart.renderer}. + * The renderer can also be used completely decoupled from a chart. + * + * @sample highcharts/members/renderer-on-chart + * Annotating a chart programmatically. + * @sample highcharts/members/renderer-basic + * Independent SVG drawing. + * + * @example + * // Use directly without a chart object. + * var renderer = new Highcharts.Renderer(parentNode, 600, 400); + * + * @class + * @name Highcharts.SVGRenderer + * + * @param {Highcharts.HTMLDOMElement} container + * Where to put the SVG in the web page. + * + * @param {number} width + * The width of the SVG. + * + * @param {number} height + * The height of the SVG. + * + * @param {Highcharts.CSSObject} [style] + * The box style, if not in styleMode + * + * @param {boolean} [forExport=false] + * Whether the rendered content is intended for export. + * + * @param {boolean} [allowHTML=true] + * Whether the renderer is allowed to include HTML text, which will be + * projected on top of the SVG. + * + * @param {boolean} [styledMode=false] + * Whether the renderer belongs to a chart that is in styled mode. + * If it does, it will avoid setting presentational attributes in + * some cases, but not when set explicitly through `.attr` and `.css` + * etc. + */ + SVGRenderer = H.SVGRenderer = function () { + this.init.apply(this, arguments); + }; + extend(SVGRenderer.prototype, /** @lends Highcharts.SVGRenderer.prototype */ { + /** + * A pointer to the renderer's associated Element class. The VMLRenderer + * will have a pointer to VMLElement here. + * + * @name Highcharts.SVGRenderer#Element + * @type {Highcharts.SVGElement} + */ + Element: SVGElement, + SVG_NS: SVG_NS, + /** + * Initialize the SVGRenderer. Overridable initializer function that takes + * the same parameters as the constructor. + * + * @function Highcharts.SVGRenderer#init + * + * @param {Highcharts.HTMLDOMElement} container + * Where to put the SVG in the web page. + * + * @param {number} width + * The width of the SVG. + * + * @param {number} height + * The height of the SVG. + * + * @param {Highcharts.CSSObject} [style] + * The box style, if not in styleMode + * + * @param {boolean} [forExport=false] + * Whether the rendered content is intended for export. + * + * @param {boolean} [allowHTML=true] + * Whether the renderer is allowed to include HTML text, which will + * be projected on top of the SVG. + * + * @param {boolean} [styledMode=false] + * Whether the renderer belongs to a chart that is in styled mode. + * If it does, it will avoid setting presentational attributes in + * some cases, but not when set explicitly through `.attr` and `.css` + * etc. + * + * @return {void} + */ + init: function (container, width, height, style, forExport, allowHTML, styledMode) { + var renderer = this, boxWrapper, element, desc; + boxWrapper = renderer.createElement('svg') + .attr({ + version: '1.1', + 'class': 'highcharts-root' + }); + if (!styledMode) { + boxWrapper.css(this.getStyle(style)); + } + element = boxWrapper.element; + container.appendChild(element); + // Always use ltr on the container, otherwise text-anchor will be + // flipped and text appear outside labels, buttons, tooltip etc (#3482) + attr(container, 'dir', 'ltr'); + // For browsers other than IE, add the namespace attribute (#1978) + if (container.innerHTML.indexOf('xmlns') === -1) { + attr(element, 'xmlns', this.SVG_NS); + } + // object properties + renderer.isSVG = true; + /** + * The root `svg` node of the renderer. + * + * @name Highcharts.SVGRenderer#box + * @type {Highcharts.SVGDOMElement} + */ + this.box = element; + /** + * The wrapper for the root `svg` node of the renderer. + * + * @name Highcharts.SVGRenderer#boxWrapper + * @type {Highcharts.SVGElement} + */ + this.boxWrapper = boxWrapper; + renderer.alignedObjects = []; + /** + * Page url used for internal references. + * + * @private + * @name Highcharts.SVGRenderer#url + * @type {string} + */ + // #24, #672, #1070 + this.url = ((isFirefox || isWebKit) && + doc.getElementsByTagName('base').length) ? + win.location.href + .split('#')[0] // remove the hash + .replace(/<[^>]*>/g, '') // wing cut HTML + // escape parantheses and quotes + .replace(/([\('\)])/g, '\\$1') + // replace spaces (needed for Safari only) + .replace(/ /g, '%20') : + ''; + // Add description + desc = this.createElement('desc').add(); + desc.element.appendChild(doc.createTextNode('Created with Highcharts 8.1.0')); + /** + * A pointer to the `defs` node of the root SVG. + * + * @name Highcharts.SVGRenderer#defs + * @type {Highcharts.SVGElement} + */ + renderer.defs = this.createElement('defs').add(); + renderer.allowHTML = allowHTML; + renderer.forExport = forExport; + renderer.styledMode = styledMode; + renderer.gradients = {}; // Object where gradient SvgElements are stored + renderer.cache = {}; // Cache for numerical bounding boxes + renderer.cacheKeys = []; + renderer.imgCount = 0; + renderer.setSize(width, height, false); + // Issue 110 workaround: + // In Firefox, if a div is positioned by percentage, its pixel position + // may land between pixels. The container itself doesn't display this, + // but an SVG element inside this container will be drawn at subpixel + // precision. In order to draw sharp lines, this must be compensated + // for. This doesn't seem to work inside iframes though (like in + // jsFiddle). + var subPixelFix, rect; + if (isFirefox && container.getBoundingClientRect) { + subPixelFix = function () { + css(container, { left: 0, top: 0 }); + rect = container.getBoundingClientRect(); + css(container, { + left: (Math.ceil(rect.left) - rect.left) + 'px', + top: (Math.ceil(rect.top) - rect.top) + 'px' + }); + }; + // run the fix now + subPixelFix(); + // run it on resize + renderer.unSubPixelFix = addEvent(win, 'resize', subPixelFix); + } + }, + /** + * General method for adding a definition to the SVG `defs` tag. Can be used + * for gradients, fills, filters etc. Styled mode only. A hook for adding + * general definitions to the SVG's defs tag. Definitions can be referenced + * from the CSS by its `id`. Read more in + * [gradients, shadows and patterns](https://www.highcharts.com/docs/chart-design-and-style/gradients-shadows-and-patterns). + * Styled mode only. + * + * @function Highcharts.SVGRenderer#definition + * + * @param {Highcharts.SVGDefinitionObject} def + * A serialized form of an SVG definition, including children. + * + * @return {Highcharts.SVGElement} + * The inserted node. + */ + definition: function (def) { + var ren = this; + /** + * @private + * @param {Highcharts.SVGDefinitionObject} config - SVG definition + * @param {Highcharts.SVGElement} [parent] - parent node + */ + function recurse(config, parent) { + var ret; + splat(config).forEach(function (item) { + var node = ren.createElement(item.tagName), attr = {}; + // Set attributes + objectEach(item, function (val, key) { + if (key !== 'tagName' && + key !== 'children' && + key !== 'textContent') { + attr[key] = val; + } + }); + node.attr(attr); + // Add to the tree + node.add(parent || ren.defs); + // Add text content + if (item.textContent) { + node.element.appendChild(doc.createTextNode(item.textContent)); + } + // Recurse + recurse(item.children || [], node); + ret = node; + }); + // Return last node added (on top level it's the only one) + return ret; + } + return recurse(def); + }, + /** + * Get the global style setting for the renderer. + * + * @private + * @function Highcharts.SVGRenderer#getStyle + * + * @param {Highcharts.CSSObject} style + * Style settings. + * + * @return {Highcharts.CSSObject} + * The style settings mixed with defaults. + */ + getStyle: function (style) { + this.style = extend({ + fontFamily: '"Lucida Grande", "Lucida Sans Unicode", ' + + 'Arial, Helvetica, sans-serif', + fontSize: '12px' + }, style); + return this.style; + }, + /** + * Apply the global style on the renderer, mixed with the default styles. + * + * @function Highcharts.SVGRenderer#setStyle + * + * @param {Highcharts.CSSObject} style + * CSS to apply. + */ + setStyle: function (style) { + this.boxWrapper.css(this.getStyle(style)); + }, + /** + * Detect whether the renderer is hidden. This happens when one of the + * parent elements has `display: none`. Used internally to detect when we + * needto render preliminarily in another div to get the text bounding boxes + * right. + * + * @function Highcharts.SVGRenderer#isHidden + * + * @return {boolean} + * True if it is hidden. + */ + isHidden: function () { + return !this.boxWrapper.getBBox().width; + }, + /** + * Destroys the renderer and its allocated members. + * + * @function Highcharts.SVGRenderer#destroy + * + * @return {null} + */ + destroy: function () { + var renderer = this, rendererDefs = renderer.defs; + renderer.box = null; + renderer.boxWrapper = renderer.boxWrapper.destroy(); + // Call destroy on all gradient elements + destroyObjectProperties(renderer.gradients || {}); + renderer.gradients = null; + // Defs are null in VMLRenderer + // Otherwise, destroy them here. + if (rendererDefs) { + renderer.defs = rendererDefs.destroy(); + } + // Remove sub pixel fix handler (#982) + if (renderer.unSubPixelFix) { + renderer.unSubPixelFix(); + } + renderer.alignedObjects = null; + return null; + }, + /** + * Create a wrapper for an SVG element. Serves as a factory for + * {@link SVGElement}, but this function is itself mostly called from + * primitive factories like {@link SVGRenderer#path}, {@link + * SVGRenderer#rect} or {@link SVGRenderer#text}. + * + * @function Highcharts.SVGRenderer#createElement + * + * @param {string} nodeName + * The node name, for example `rect`, `g` etc. + * + * @return {Highcharts.SVGElement} + * The generated SVGElement. + */ + createElement: function (nodeName) { + var wrapper = new this.Element(); + wrapper.init(this, nodeName); + return wrapper; + }, + /** + * Dummy function for plugins, called every time the renderer is updated. + * Prior to Highcharts 5, this was used for the canvg renderer. + * + * @deprecated + * @function Highcharts.SVGRenderer#draw + */ + draw: noop, + /** + * Get converted radial gradient attributes according to the radial + * reference. Used internally from the {@link SVGElement#colorGradient} + * function. + * + * @private + * @function Highcharts.SVGRenderer#getRadialAttr + * + * @param {Array} radialReference + * + * @param {Highcharts.SVGAttributes} gradAttr + * + * @return {Highcharts.SVGAttributes} + */ + getRadialAttr: function (radialReference, gradAttr) { + return { + cx: (radialReference[0] - radialReference[2] / 2) + + gradAttr.cx * radialReference[2], + cy: (radialReference[1] - radialReference[2] / 2) + + gradAttr.cy * radialReference[2], + r: gradAttr.r * radialReference[2] + }; + }, + /** + * Truncate the text node contents to a given length. Used when the css + * width is set. If the `textOverflow` is `ellipsis`, the text is truncated + * character by character to the given length. If not, the text is + * word-wrapped line by line. + * + * @private + * @function Highcharts.SVGRenderer#truncate + * + * @param {Highcharts.SVGElement} wrapper + * + * @param {Highcharts.HTMLDOMElement} tspan + * + * @param {string|undefined} text + * + * @param {Array|undefined} words + * + * @param {number} startAt + * + * @param {number} width + * + * @param {Function} getString + * + * @return {boolean} + * True if tspan is too long. + */ + truncate: function (wrapper, tspan, text, words, startAt, width, getString) { + var renderer = this, rotation = wrapper.rotation, str, + // Word wrap can not be truncated to shorter than one word, ellipsis + // text can be completely blank. + minIndex = words ? 1 : 0, maxIndex = (text || words).length, currentIndex = maxIndex, + // Cache the lengths to avoid checking the same twice + lengths = [], updateTSpan = function (s) { + if (tspan.firstChild) { + tspan.removeChild(tspan.firstChild); + } + if (s) { + tspan.appendChild(doc.createTextNode(s)); + } + }, getSubStringLength = function (charEnd, concatenatedEnd) { + // charEnd is useed when finding the character-by-character + // break for ellipsis, concatenatedEnd is used for word-by-word + // break for word wrapping. + var end = concatenatedEnd || charEnd; + if (typeof lengths[end] === 'undefined') { + // Modern browsers + if (tspan.getSubStringLength) { + // Fails with DOM exception on unit-tests/legend/members + // of unknown reason. Desired width is 0, text content + // is "5" and end is 1. + try { + lengths[end] = startAt + + tspan.getSubStringLength(0, words ? end + 1 : end); + } + catch (e) { + ''; + } + // Legacy + } + else if (renderer.getSpanWidth) { // #9058 jsdom + updateTSpan(getString(text || words, charEnd)); + lengths[end] = startAt + + renderer.getSpanWidth(wrapper, tspan); + } + } + return lengths[end]; + }, actualWidth, truncated; + wrapper.rotation = 0; // discard rotation when computing box + actualWidth = getSubStringLength(tspan.textContent.length); + truncated = startAt + actualWidth > width; + if (truncated) { + // Do a binary search for the index where to truncate the text + while (minIndex <= maxIndex) { + currentIndex = Math.ceil((minIndex + maxIndex) / 2); + // When checking words for word-wrap, we need to build the + // string and measure the subStringLength at the concatenated + // word length. + if (words) { + str = getString(words, currentIndex); + } + actualWidth = getSubStringLength(currentIndex, str && str.length - 1); + if (minIndex === maxIndex) { + // Complete + minIndex = maxIndex + 1; + } + else if (actualWidth > width) { + // Too large. Set max index to current. + maxIndex = currentIndex - 1; + } + else { + // Within width. Set min index to current. + minIndex = currentIndex; + } + } + // If max index was 0 it means the shortest possible text was also + // too large. For ellipsis that means only the ellipsis, while for + // word wrap it means the whole first word. + if (maxIndex === 0) { + // Remove ellipsis + updateTSpan(''); + // If the new text length is one less than the original, we don't + // need the ellipsis + } + else if (!(text && maxIndex === text.length - 1)) { + updateTSpan(str || getString(text || words, currentIndex)); + } + } + // When doing line wrapping, prepare for the next line by removing the + // items from this line. + if (words) { + words.splice(0, currentIndex); + } + wrapper.actualWidth = actualWidth; + wrapper.rotation = rotation; // Apply rotation again. + return truncated; + }, + /** + * A collection of characters mapped to HTML entities. When `useHTML` on an + * element is true, these entities will be rendered correctly by HTML. In + * the SVG pseudo-HTML, they need to be unescaped back to simple characters, + * so for example `<` will render as `<`. + * + * @example + * // Add support for unescaping quotes + * Highcharts.SVGRenderer.prototype.escapes['"'] = '"'; + * + * @name Highcharts.SVGRenderer#escapes + * @type {Highcharts.Dictionary} + */ + escapes: { + '&': '&', + '<': '<', + '>': '>', + "'": ''', + '"': '"' + }, + /** + * Parse a simple HTML string into SVG tspans. Called internally when text + * is set on an SVGElement. The function supports a subset of HTML tags, CSS + * text features like `width`, `text-overflow`, `white-space`, and also + * attributes like `href` and `style`. + * + * @private + * @function Highcharts.SVGRenderer#buildText + * + * @param {Highcharts.SVGElement} wrapper + * The parent SVGElement. + * + * @return {void} + */ + buildText: function (wrapper) { + var textNode = wrapper.element, renderer = this, forExport = renderer.forExport, textStr = pick(wrapper.textStr, '').toString(), hasMarkup = textStr.indexOf('<') !== -1, lines, childNodes = textNode.childNodes, truncated, parentX = attr(textNode, 'x'), textStyles = wrapper.styles, width = wrapper.textWidth, textLineHeight = textStyles && textStyles.lineHeight, textOutline = textStyles && textStyles.textOutline, ellipsis = textStyles && textStyles.textOverflow === 'ellipsis', noWrap = textStyles && textStyles.whiteSpace === 'nowrap', fontSize = textStyles && textStyles.fontSize, textCache, isSubsequentLine, i = childNodes.length, tempParent = width && !wrapper.added && this.box, getLineHeight = function (tspan) { + var fontSizeStyle; + if (!renderer.styledMode) { + fontSizeStyle = + /(px|em)$/.test(tspan && tspan.style.fontSize) ? + tspan.style.fontSize : + (fontSize || renderer.style.fontSize || 12); + } + return textLineHeight ? + pInt(textLineHeight) : + renderer.fontMetrics(fontSizeStyle, + // Get the computed size from parent if not explicit + (tspan.getAttribute('style') ? tspan : textNode)).h; + }, unescapeEntities = function (inputStr, except) { + objectEach(renderer.escapes, function (value, key) { + if (!except || except.indexOf(value) === -1) { + inputStr = inputStr.toString().replace(new RegExp(value, 'g'), key); + } + }); + return inputStr; + }, parseAttribute = function (s, attr) { + var start, delimiter; + start = s.indexOf('<'); + s = s.substring(start, s.indexOf('>') - start); + start = s.indexOf(attr + '='); + if (start !== -1) { + start = start + attr.length + 1; + delimiter = s.charAt(start); + if (delimiter === '"' || delimiter === "'") { // eslint-disable-line quotes + s = s.substring(start + 1); + return s.substring(0, s.indexOf(delimiter)); + } + } + }; + var regexMatchBreaks = //g; + // The buildText code is quite heavy, so if we're not changing something + // that affects the text, skip it (#6113). + textCache = [ + textStr, + ellipsis, + noWrap, + textLineHeight, + textOutline, + fontSize, + width + ].join(','); + if (textCache === wrapper.textCache) { + return; + } + wrapper.textCache = textCache; + // Remove old text + while (i--) { + textNode.removeChild(childNodes[i]); + } + // Skip tspans, add text directly to text node. The forceTSpan is a hook + // used in text outline hack. + if (!hasMarkup && + !textOutline && + !ellipsis && + !width && + (textStr.indexOf(' ') === -1 || + (noWrap && !regexMatchBreaks.test(textStr)))) { + textNode.appendChild(doc.createTextNode(unescapeEntities(textStr))); + // Complex strings, add more logic + } + else { + if (tempParent) { + // attach it to the DOM to read offset width + tempParent.appendChild(textNode); + } + if (hasMarkup) { + lines = renderer.styledMode ? (textStr + .replace(/<(b|strong)>/g, '') + .replace(/<(i|em)>/g, '')) : (textStr + .replace(/<(b|strong)>/g, '') + .replace(/<(i|em)>/g, '')); + lines = lines + .replace(//g, '') + .split(regexMatchBreaks); + } + else { + lines = [textStr]; + } + // Trim empty lines (#5261) + lines = lines.filter(function (line) { + return line !== ''; + }); + // build the lines + lines.forEach(function (line, lineNo) { + var spans, spanNo = 0, lineLength = 0; + line = line + // Trim to prevent useless/costly process on the spaces + // (#5258) + .replace(/^\s+|\s+$/g, '') + .replace(//g, '|||'); + spans = line.split('|||'); + spans.forEach(function buildTextSpans(span) { + if (span !== '' || spans.length === 1) { + var attributes = {}, tspan = doc.createElementNS(renderer.SVG_NS, 'tspan'), classAttribute, styleAttribute, // #390 + hrefAttribute; + classAttribute = parseAttribute(span, 'class'); + if (classAttribute) { + attr(tspan, 'class', classAttribute); + } + styleAttribute = parseAttribute(span, 'style'); + if (styleAttribute) { + styleAttribute = styleAttribute.replace(/(;| |^)color([ :])/, '$1fill$2'); + attr(tspan, 'style', styleAttribute); + } + // Not for export - #1529 + hrefAttribute = parseAttribute(span, 'href'); + if (hrefAttribute && !forExport) { + attr(tspan, 'onclick', 'location.href=\"' + hrefAttribute + '\"'); + attr(tspan, 'class', 'highcharts-anchor'); + if (!renderer.styledMode) { + css(tspan, { cursor: 'pointer' }); + } + } + // Strip away unsupported HTML tags (#7126) + span = unescapeEntities(span.replace(/<[a-zA-Z\/](.|\n)*?>/g, '') || ' '); + // Nested tags aren't supported, and cause crash in + // Safari (#1596) + if (span !== ' ') { + // add the text node + tspan.appendChild(doc.createTextNode(span)); + // First span in a line, align it to the left + if (!spanNo) { + if (lineNo && parentX !== null) { + attributes.x = parentX; + } + } + else { + attributes.dx = 0; // #16 + } + // add attributes + attr(tspan, attributes); + // Append it + textNode.appendChild(tspan); + // first span on subsequent line, add the line + // height + if (!spanNo && isSubsequentLine) { + // allow getting the right offset height in + // exporting in IE + if (!svg && forExport) { + css(tspan, { display: 'block' }); + } + // Set the line height based on the font size of + // either the text element or the tspan element + attr(tspan, 'dy', getLineHeight(tspan)); + } + // Check width and apply soft breaks or ellipsis + if (width) { + var words = span.replace(/([^\^])-/g, '$1- ').split(' '), // #1273 + hasWhiteSpace = !noWrap && (spans.length > 1 || + lineNo || + words.length > 1), wrapLineNo = 0, dy = getLineHeight(tspan); + if (ellipsis) { + truncated = renderer.truncate(wrapper, tspan, span, void 0, 0, + // Target width + Math.max(0, + // Substract the font face to make + // room for the ellipsis itself + width - parseInt(fontSize || 12, 10)), + // Build the text to test for + function (text, currentIndex) { + return text.substring(0, currentIndex) + '\u2026'; + }); + } + else if (hasWhiteSpace) { + while (words.length) { + // For subsequent lines, create tspans + // with the same style attributes as the + // parent text node. + if (words.length && + !noWrap && + wrapLineNo > 0) { + tspan = doc.createElementNS(SVG_NS, 'tspan'); + attr(tspan, { + dy: dy, + x: parentX + }); + if (styleAttribute) { // #390 + attr(tspan, 'style', styleAttribute); + } + // Start by appending the full + // remaining text + tspan.appendChild(doc.createTextNode(words.join(' ') + .replace(/- /g, '-'))); + textNode.appendChild(tspan); + } + // For each line, truncate the remaining + // words into the line length. + renderer.truncate(wrapper, tspan, null, words, wrapLineNo === 0 ? lineLength : 0, width, + // Build the text to test for + function (text, currentIndex) { + return words + .slice(0, currentIndex) + .join(' ') + .replace(/- /g, '-'); + }); + lineLength = wrapper.actualWidth; + wrapLineNo++; + } + } + } + spanNo++; + } + } + }); + // To avoid beginning lines that doesn't add to the textNode + // (#6144) + isSubsequentLine = (isSubsequentLine || + textNode.childNodes.length); + }); + if (ellipsis && truncated) { + wrapper.attr('title', unescapeEntities(wrapper.textStr, ['<', '>']) // #7179 + ); + } + if (tempParent) { + tempParent.removeChild(textNode); + } + // Apply the text outline + if (textOutline && wrapper.applyTextOutline) { + wrapper.applyTextOutline(textOutline); + } + } + }, + /** + * Returns white for dark colors and black for bright colors. + * + * @function Highcharts.SVGRenderer#getContrast + * + * @param {Highcharts.ColorString} rgba + * The color to get the contrast for. + * + * @return {Highcharts.ColorString} + * The contrast color, either `#000000` or `#FFFFFF`. + */ + getContrast: function (rgba) { + rgba = color(rgba).rgba; + // The threshold may be discussed. Here's a proposal for adding + // different weight to the color channels (#6216) + rgba[0] *= 1; // red + rgba[1] *= 1.2; // green + rgba[2] *= 0.5; // blue + return rgba[0] + rgba[1] + rgba[2] > + 1.8 * 255 ? + '#000000' : + '#FFFFFF'; + }, + /** + * Create a button with preset states. + * + * @function Highcharts.SVGRenderer#button + * + * @param {string} text + * The text or HTML to draw. + * + * @param {number} x + * The x position of the button's left side. + * + * @param {number} y + * The y position of the button's top side. + * + * @param {Highcharts.EventCallbackFunction} callback + * The function to execute on button click or touch. + * + * @param {Highcharts.SVGAttributes} [normalState] + * SVG attributes for the normal state. + * + * @param {Highcharts.SVGAttributes} [hoverState] + * SVG attributes for the hover state. + * + * @param {Highcharts.SVGAttributes} [pressedState] + * SVG attributes for the pressed state. + * + * @param {Highcharts.SVGAttributes} [disabledState] + * SVG attributes for the disabled state. + * + * @param {Highcharts.SymbolKeyValue} [shape=rect] + * The shape type. + * + * @param {boolean} [useHTML=false] + * Wether to use HTML to render the label. + * + * @return {Highcharts.SVGElement} + * The button element. + */ + button: function (text, x, y, callback, normalState, hoverState, pressedState, disabledState, shape, useHTML) { + var label = this.label(text, x, y, shape, void 0, void 0, useHTML, void 0, 'button'), curState = 0, styledMode = this.styledMode; + // Default, non-stylable attributes + label.attr(merge({ padding: 8, r: 2 }, normalState)); + if (!styledMode) { + // Presentational + var normalStyle, hoverStyle, pressedStyle, disabledStyle; + // Normal state - prepare the attributes + normalState = merge({ + fill: '#f7f7f7', + stroke: '#cccccc', + 'stroke-width': 1, + style: { + color: '#333333', + cursor: 'pointer', + fontWeight: 'normal' + } + }, normalState); + normalStyle = normalState.style; + delete normalState.style; + // Hover state + hoverState = merge(normalState, { + fill: '#e6e6e6' + }, hoverState); + hoverStyle = hoverState.style; + delete hoverState.style; + // Pressed state + pressedState = merge(normalState, { + fill: '#e6ebf5', + style: { + color: '#000000', + fontWeight: 'bold' + } + }, pressedState); + pressedStyle = pressedState.style; + delete pressedState.style; + // Disabled state + disabledState = merge(normalState, { + style: { + color: '#cccccc' + } + }, disabledState); + disabledStyle = disabledState.style; + delete disabledState.style; + } + // Add the events. IE9 and IE10 need mouseover and mouseout to funciton + // (#667). + addEvent(label.element, isMS ? 'mouseover' : 'mouseenter', function () { + if (curState !== 3) { + label.setState(1); + } + }); + addEvent(label.element, isMS ? 'mouseout' : 'mouseleave', function () { + if (curState !== 3) { + label.setState(curState); + } + }); + label.setState = function (state) { + // Hover state is temporary, don't record it + if (state !== 1) { + label.state = curState = state; + } + // Update visuals + label + .removeClass(/highcharts-button-(normal|hover|pressed|disabled)/) + .addClass('highcharts-button-' + + ['normal', 'hover', 'pressed', 'disabled'][state || 0]); + if (!styledMode) { + label + .attr([ + normalState, + hoverState, + pressedState, + disabledState + ][state || 0]) + .css([ + normalStyle, + hoverStyle, + pressedStyle, + disabledStyle + ][state || 0]); + } + }; + // Presentational attributes + if (!styledMode) { + label + .attr(normalState) + .css(extend({ cursor: 'default' }, normalStyle)); + } + return label + .on('click', function (e) { + if (curState !== 3) { + callback.call(label, e); + } + }); + }, + /** + * Make a straight line crisper by not spilling out to neighbour pixels. + * + * @function Highcharts.SVGRenderer#crispLine + * + * @param {Highcharts.SVGPathArray} points + * The original points on the format `[['M', 0, 0], ['L', 100, 0]]`. + * + * @param {number} width + * The width of the line. + * + * @param {string} roundingFunction + * The rounding function name on the `Math` object, can be one of + * `round`, `floor` or `ceil`. + * + * @return {Highcharts.SVGPathArray} + * The original points array, but modified to render crisply. + */ + crispLine: function (points, width, roundingFunction) { + if (roundingFunction === void 0) { roundingFunction = 'round'; } + var start = points[0]; + var end = points[1]; + // Normalize to a crisp line + if (start[1] === end[1]) { + // Substract due to #1129. Now bottom and left axis gridlines behave + // the same. + start[1] = end[1] = + Math[roundingFunction](start[1]) - (width % 2 / 2); + } + if (start[2] === end[2]) { + start[2] = end[2] = + Math[roundingFunction](start[2]) + (width % 2 / 2); + } + return points; + }, + /** + * Draw a path, wraps the SVG `path` element. + * + * @sample highcharts/members/renderer-path-on-chart/ + * Draw a path in a chart + * @sample highcharts/members/renderer-path/ + * Draw a path independent from a chart + * + * @example + * var path = renderer.path(['M', 10, 10, 'L', 30, 30, 'z']) + * .attr({ stroke: '#ff00ff' }) + * .add(); + * + * @function Highcharts.SVGRenderer#path + * + * @param {Highcharts.SVGPathArray} [path] + * An SVG path definition in array form. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + * + */ /** + * Draw a path, wraps the SVG `path` element. + * + * @function Highcharts.SVGRenderer#path + * + * @param {Highcharts.SVGAttributes} [attribs] + * The initial attributes. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ + path: function (path) { + var attribs = (this.styledMode ? {} : { + fill: 'none' + }); + if (isArray(path)) { + attribs.d = path; + } + else if (isObject(path)) { // attributes + extend(attribs, path); + } + return this.createElement('path').attr(attribs); + }, + /** + * Draw a circle, wraps the SVG `circle` element. + * + * @sample highcharts/members/renderer-circle/ + * Drawing a circle + * + * @function Highcharts.SVGRenderer#circle + * + * @param {number} [x] + * The center x position. + * + * @param {number} [y] + * The center y position. + * + * @param {number} [r] + * The radius. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ /** + * Draw a circle, wraps the SVG `circle` element. + * + * @function Highcharts.SVGRenderer#circle + * + * @param {Highcharts.SVGAttributes} [attribs] + * The initial attributes. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ + circle: function (x, y, r) { + var attribs = (isObject(x) ? + x : + typeof x === 'undefined' ? {} : { x: x, y: y, r: r }), wrapper = this.createElement('circle'); + // Setting x or y translates to cx and cy + wrapper.xSetter = wrapper.ySetter = function (value, key, element) { + element.setAttribute('c' + key, value); + }; + return wrapper.attr(attribs); + }, + /** + * Draw and return an arc. + * + * @sample highcharts/members/renderer-arc/ + * Drawing an arc + * + * @function Highcharts.SVGRenderer#arc + * + * @param {number} [x=0] + * Center X position. + * + * @param {number} [y=0] + * Center Y position. + * + * @param {number} [r=0] + * The outer radius' of the arc. + * + * @param {number} [innerR=0] + * Inner radius like used in donut charts. + * + * @param {number} [start=0] + * The starting angle of the arc in radians, where 0 is to the right + * and `-Math.PI/2` is up. + * + * @param {number} [end=0] + * The ending angle of the arc in radians, where 0 is to the right + * and `-Math.PI/2` is up. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ /** + * Draw and return an arc. Overloaded function that takes arguments object. + * + * @function Highcharts.SVGRenderer#arc + * + * @param {Highcharts.SVGAttributes} attribs + * Initial SVG attributes. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ + arc: function (x, y, r, innerR, start, end) { + var arc, options; + if (isObject(x)) { + options = x; + y = options.y; + r = options.r; + innerR = options.innerR; + start = options.start; + end = options.end; + x = options.x; + } + else { + options = { + innerR: innerR, + start: start, + end: end + }; + } + // Arcs are defined as symbols for the ability to set + // attributes in attr and animate + arc = this.symbol('arc', x, y, r, r, options); + arc.r = r; // #959 + return arc; + }, + /** + * Draw and return a rectangle. + * + * @function Highcharts.SVGRenderer#rect + * + * @param {number} [x] + * Left position. + * + * @param {number} [y] + * Top position. + * + * @param {number} [width] + * Width of the rectangle. + * + * @param {number} [height] + * Height of the rectangle. + * + * @param {number} [r] + * Border corner radius. + * + * @param {number} [strokeWidth] + * A stroke width can be supplied to allow crisp drawing. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ /** + * Draw and return a rectangle. + * + * @sample highcharts/members/renderer-rect-on-chart/ + * Draw a rectangle in a chart + * @sample highcharts/members/renderer-rect/ + * Draw a rectangle independent from a chart + * + * @function Highcharts.SVGRenderer#rect + * + * @param {Highcharts.SVGAttributes} [attributes] + * General SVG attributes for the rectangle. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ + rect: function (x, y, width, height, r, strokeWidth) { + r = isObject(x) ? x.r : r; + var wrapper = this.createElement('rect'), attribs = isObject(x) ? + x : + typeof x === 'undefined' ? + {} : + { + x: x, + y: y, + width: Math.max(width, 0), + height: Math.max(height, 0) + }; + if (!this.styledMode) { + if (typeof strokeWidth !== 'undefined') { + attribs.strokeWidth = strokeWidth; + attribs = wrapper.crisp(attribs); + } + attribs.fill = 'none'; + } + if (r) { + attribs.r = r; + } + wrapper.rSetter = function (value, key, element) { + wrapper.r = value; + attr(element, { + rx: value, + ry: value + }); + }; + wrapper.rGetter = function () { + return wrapper.r; + }; + return wrapper.attr(attribs); + }, + /** + * Resize the {@link SVGRenderer#box} and re-align all aligned child + * elements. + * + * @sample highcharts/members/renderer-g/ + * Show and hide grouped objects + * + * @function Highcharts.SVGRenderer#setSize + * + * @param {number} width + * The new pixel width. + * + * @param {number} height + * The new pixel height. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animate=true] + * Whether and how to animate. + * + * @return {void} + */ + setSize: function (width, height, animate) { + var renderer = this, alignedObjects = renderer.alignedObjects, i = alignedObjects.length; + renderer.width = width; + renderer.height = height; + renderer.boxWrapper.animate({ + width: width, + height: height + }, { + step: function () { + this.attr({ + viewBox: '0 0 ' + this.attr('width') + ' ' + + this.attr('height') + }); + }, + duration: pick(animate, true) ? void 0 : 0 + }); + while (i--) { + alignedObjects[i].align(); + } + }, + /** + * Create and return an svg group element. Child + * {@link Highcharts.SVGElement} objects are added to the group by using the + * group as the first parameter in {@link Highcharts.SVGElement#add|add()}. + * + * @function Highcharts.SVGRenderer#g + * + * @param {string} [name] + * The group will be given a class name of `highcharts-{name}`. This + * can be used for styling and scripting. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ + g: function (name) { + var elem = this.createElement('g'); + return name ? + elem.attr({ 'class': 'highcharts-' + name }) : + elem; + }, + /** + * Display an image. + * + * @sample highcharts/members/renderer-image-on-chart/ + * Add an image in a chart + * @sample highcharts/members/renderer-image/ + * Add an image independent of a chart + * + * @function Highcharts.SVGRenderer#image + * + * @param {string} src + * The image source. + * + * @param {number} [x] + * The X position. + * + * @param {number} [y] + * The Y position. + * + * @param {number} [width] + * The image width. If omitted, it defaults to the image file width. + * + * @param {number} [height] + * The image height. If omitted it defaults to the image file + * height. + * + * @param {Function} [onload] + * Event handler for image load. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ + image: function (src, x, y, width, height, onload) { + var attribs = { preserveAspectRatio: 'none' }, elemWrapper, dummy, setSVGImageSource = function (el, src) { + // Set the href in the xlink namespace + if (el.setAttributeNS) { + el.setAttributeNS('http://www.w3.org/1999/xlink', 'href', src); + } + else { + // could be exporting in IE + // using href throws "not supported" in ie7 and under, + // requries regex shim to fix later + el.setAttribute('hc-svg-href', src); + } + }, onDummyLoad = function (e) { + setSVGImageSource(elemWrapper.element, src); + onload.call(elemWrapper, e); + }; + // optional properties + if (arguments.length > 1) { + extend(attribs, { + x: x, + y: y, + width: width, + height: height + }); + } + elemWrapper = this.createElement('image').attr(attribs); + // Add load event if supplied + if (onload) { + // We have to use a dummy HTML image since IE support for SVG image + // load events is very buggy. First set a transparent src, wait for + // dummy to load, and then add the real src to the SVG image. + setSVGImageSource(elemWrapper.element, 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==' /* eslint-disable-line */); + dummy = new win.Image(); + addEvent(dummy, 'load', onDummyLoad); + dummy.src = src; + if (dummy.complete) { + onDummyLoad({}); + } + } + else { + setSVGImageSource(elemWrapper.element, src); + } + return elemWrapper; + }, + /** + * Draw a symbol out of pre-defined shape paths from + * {@link SVGRenderer#symbols}. + * It is used in Highcharts for point makers, which cake a `symbol` option, + * and label and button backgrounds like in the tooltip and stock flags. + * + * @function Highcharts.SVGRenderer#symbol + * + * @param {string} symbol + * The symbol name. + * + * @param {number} [x] + * The X coordinate for the top left position. + * + * @param {number} [y] + * The Y coordinate for the top left position. + * + * @param {number} [width] + * The pixel width. + * + * @param {number} [height] + * The pixel height. + * + * @param {Highcharts.SymbolOptionsObject} [options] + * Additional options, depending on the actual symbol drawn. + * + * @return {Highcharts.SVGElement} + */ + symbol: function (symbol, x, y, width, height, options) { + var ren = this, obj, imageRegex = /^url\((.*?)\)$/, isImage = imageRegex.test(symbol), sym = (!isImage && (this.symbols[symbol] ? symbol : 'circle')), + // get the symbol definition function + symbolFn = (sym && this.symbols[sym]), path, imageSrc, centerImage; + if (symbolFn) { + // Check if there's a path defined for this symbol + if (typeof x === 'number') { + path = symbolFn.call(this.symbols, Math.round(x || 0), Math.round(y || 0), width, height, options); + } + obj = this.path(path); + if (!ren.styledMode) { + obj.attr('fill', 'none'); + } + // expando properties for use in animate and attr + extend(obj, { + symbolName: sym, + x: x, + y: y, + width: width, + height: height + }); + if (options) { + extend(obj, options); + } + // Image symbols + } + else if (isImage) { + imageSrc = symbol.match(imageRegex)[1]; + // Create the image synchronously, add attribs async + obj = this.image(imageSrc); + // The image width is not always the same as the symbol width. The + // image may be centered within the symbol, as is the case when + // image shapes are used as label backgrounds, for example in flags. + obj.imgwidth = pick(symbolSizes[imageSrc] && symbolSizes[imageSrc].width, options && options.width); + obj.imgheight = pick(symbolSizes[imageSrc] && symbolSizes[imageSrc].height, options && options.height); + /** + * Set the size and position + */ + centerImage = function () { + obj.attr({ + width: obj.width, + height: obj.height + }); + }; + /** + * Width and height setters that take both the image's physical size + * and the label size into consideration, and translates the image + * to center within the label. + */ + ['width', 'height'].forEach(function (key) { + obj[key + 'Setter'] = function (value, key) { + var attribs = {}, imgSize = this['img' + key], trans = key === 'width' ? 'translateX' : 'translateY'; + this[key] = value; + if (defined(imgSize)) { + // Scale and center the image within its container. + // The name `backgroundSize` is taken from the CSS spec, + // but the value `within` is made up. Other possible + // values in the spec, `cover` and `contain`, can be + // implemented if needed. + if (options && + options.backgroundSize === 'within' && + this.width && + this.height) { + imgSize = Math.round(imgSize * Math.min(this.width / this.imgwidth, this.height / this.imgheight)); + } + if (this.element) { + this.element.setAttribute(key, imgSize); + } + if (!this.alignByTranslate) { + attribs[trans] = ((this[key] || 0) - imgSize) / 2; + this.attr(attribs); + } + } + }; + }); + if (defined(x)) { + obj.attr({ + x: x, + y: y + }); + } + obj.isImg = true; + if (defined(obj.imgwidth) && defined(obj.imgheight)) { + centerImage(); + } + else { + // Initialize image to be 0 size so export will still function + // if there's no cached sizes. + obj.attr({ width: 0, height: 0 }); + // Create a dummy JavaScript image to get the width and height. + createElement('img', { + onload: function () { + var chart = charts[ren.chartIndex]; + // Special case for SVGs on IE11, the width is not + // accessible until the image is part of the DOM + // (#2854). + if (this.width === 0) { + css(this, { + position: 'absolute', + top: '-999em' + }); + doc.body.appendChild(this); + } + // Center the image + symbolSizes[imageSrc] = { + width: this.width, + height: this.height + }; + obj.imgwidth = this.width; + obj.imgheight = this.height; + if (obj.element) { + centerImage(); + } + // Clean up after #2854 workaround. + if (this.parentNode) { + this.parentNode.removeChild(this); + } + // Fire the load event when all external images are + // loaded + ren.imgCount--; + if (!ren.imgCount && chart && !chart.hasLoaded) { + chart.onload(); + } + }, + src: imageSrc + }); + this.imgCount++; + } + } + return obj; + }, + /** + * An extendable collection of functions for defining symbol paths. + * + * @name Highcharts.SVGRenderer#symbols + * @type {Highcharts.SymbolDictionary} + */ + symbols: { + circle: function (x, y, w, h) { + // Return a full arc + return this.arc(x + w / 2, y + h / 2, w / 2, h / 2, { + start: Math.PI * 0.5, + end: Math.PI * 2.5, + open: false + }); + }, + square: function (x, y, w, h) { + return [ + ['M', x, y], + ['L', x + w, y], + ['L', x + w, y + h], + ['L', x, y + h], + ['Z'] + ]; + }, + triangle: function (x, y, w, h) { + return [ + ['M', x + w / 2, y], + ['L', x + w, y + h], + ['L', x, y + h], + ['Z'] + ]; + }, + 'triangle-down': function (x, y, w, h) { + return [ + ['M', x, y], + ['L', x + w, y], + ['L', x + w / 2, y + h], + ['Z'] + ]; + }, + diamond: function (x, y, w, h) { + return [ + ['M', x + w / 2, y], + ['L', x + w, y + h / 2], + ['L', x + w / 2, y + h], + ['L', x, y + h / 2], + ['Z'] + ]; + }, + arc: function (x, y, w, h, options) { + var start = options.start, rx = options.r || w, ry = options.r || h || w, proximity = 0.001, fullCircle = Math.abs(options.end - options.start - 2 * Math.PI) < + proximity, + // Substract a small number to prevent cos and sin of start and + // end from becoming equal on 360 arcs (related: #1561) + end = options.end - proximity, innerRadius = options.innerR, open = pick(options.open, fullCircle), cosStart = Math.cos(start), sinStart = Math.sin(start), cosEnd = Math.cos(end), sinEnd = Math.sin(end), + // Proximity takes care of rounding errors around PI (#6971) + longArc = pick(options.longArc, options.end - start - Math.PI < proximity ? 0 : 1), arc; + arc = [ + [ + 'M', + x + rx * cosStart, + y + ry * sinStart + ], + [ + 'A', + rx, + ry, + 0, + longArc, + pick(options.clockwise, 1), + x + rx * cosEnd, + y + ry * sinEnd + ] + ]; + if (defined(innerRadius)) { + arc.push(open ? + [ + 'M', + x + innerRadius * cosEnd, + y + innerRadius * sinEnd + ] : [ + 'L', + x + innerRadius * cosEnd, + y + innerRadius * sinEnd + ], [ + 'A', + innerRadius, + innerRadius, + 0, + longArc, + // Clockwise - opposite to the outer arc clockwise + defined(options.clockwise) ? 1 - options.clockwise : 0, + x + innerRadius * cosStart, + y + innerRadius * sinStart + ]); + } + if (!open) { + arc.push(['Z']); + } + return arc; + }, + /** + * Callout shape used for default tooltips, also used for rounded + * rectangles in VML + */ + callout: function (x, y, w, h, options) { + var arrowLength = 6, halfDistance = 6, r = Math.min((options && options.r) || 0, w, h), safeDistance = r + halfDistance, anchorX = options && options.anchorX, anchorY = options && options.anchorY, path; + path = [ + ['M', x + r, y], + ['L', x + w - r, y], + ['C', x + w, y, x + w, y, x + w, y + r], + ['L', x + w, y + h - r], + ['C', x + w, y + h, x + w, y + h, x + w - r, y + h], + ['L', x + r, y + h], + ['C', x, y + h, x, y + h, x, y + h - r], + ['L', x, y + r], + ['C', x, y, x, y, x + r, y] // top-left corner + ]; + // Anchor on right side + if (anchorX && anchorX > w) { + // Chevron + if (anchorY > y + safeDistance && + anchorY < y + h - safeDistance) { + path.splice(3, 1, ['L', x + w, anchorY - halfDistance], ['L', x + w + arrowLength, anchorY], ['L', x + w, anchorY + halfDistance], ['L', x + w, y + h - r]); + // Simple connector + } + else { + path.splice(3, 1, ['L', x + w, h / 2], ['L', anchorX, anchorY], ['L', x + w, h / 2], ['L', x + w, y + h - r]); + } + // Anchor on left side + } + else if (anchorX && anchorX < 0) { + // Chevron + if (anchorY > y + safeDistance && + anchorY < y + h - safeDistance) { + path.splice(7, 1, ['L', x, anchorY + halfDistance], ['L', x - arrowLength, anchorY], ['L', x, anchorY - halfDistance], ['L', x, y + r]); + // Simple connector + } + else { + path.splice(7, 1, ['L', x, h / 2], ['L', anchorX, anchorY], ['L', x, h / 2], ['L', x, y + r]); + } + } + else if ( // replace bottom + anchorY && + anchorY > h && + anchorX > x + safeDistance && + anchorX < x + w - safeDistance) { + path.splice(5, 1, ['L', anchorX + halfDistance, y + h], ['L', anchorX, y + h + arrowLength], ['L', anchorX - halfDistance, y + h], ['L', x + r, y + h]); + } + else if ( // replace top + anchorY && + anchorY < 0 && + anchorX > x + safeDistance && + anchorX < x + w - safeDistance) { + path.splice(1, 1, ['L', anchorX - halfDistance, y], ['L', anchorX, y - arrowLength], ['L', anchorX + halfDistance, y], ['L', w - r, y]); + } + return path; + } + }, + /** + * Define a clipping rectangle. The clipping rectangle is later applied + * to {@link SVGElement} objects through the {@link SVGElement#clip} + * function. + * + * @example + * var circle = renderer.circle(100, 100, 100) + * .attr({ fill: 'red' }) + * .add(); + * var clipRect = renderer.clipRect(100, 100, 100, 100); + * + * // Leave only the lower right quarter visible + * circle.clip(clipRect); + * + * @function Highcharts.SVGRenderer#clipRect + * + * @param {number} [x] + * + * @param {number} [y] + * + * @param {number} [width] + * + * @param {number} [height] + * + * @return {Highcharts.ClipRectElement} + * A clipping rectangle. + */ + clipRect: function (x, y, width, height) { + var wrapper, + // Add a hyphen at the end to avoid confusion in testing indexes + // -1 and -10, -11 etc (#6550) + id = uniqueKey() + '-', clipPath = this.createElement('clipPath').attr({ + id: id + }).add(this.defs); + wrapper = this.rect(x, y, width, height, 0).add(clipPath); + wrapper.id = id; + wrapper.clipPath = clipPath; + wrapper.count = 0; + return wrapper; + }, + /** + * Draw text. The text can contain a subset of HTML, like spans and anchors + * and some basic text styling of these. For more advanced features like + * border and background, use {@link Highcharts.SVGRenderer#label} instead. + * To update the text after render, run `text.attr({ text: 'New text' })`. + * + * @sample highcharts/members/renderer-text-on-chart/ + * Annotate the chart freely + * @sample highcharts/members/renderer-on-chart/ + * Annotate with a border and in response to the data + * @sample highcharts/members/renderer-text/ + * Formatted text + * + * @function Highcharts.SVGRenderer#text + * + * @param {string} [str] + * The text of (subset) HTML to draw. + * + * @param {number} [x] + * The x position of the text's lower left corner. + * + * @param {number} [y] + * The y position of the text's lower left corner. + * + * @param {boolean} [useHTML=false] + * Use HTML to render the text. + * + * @return {Highcharts.SVGElement} + * The text object. + */ + text: function (str, x, y, useHTML) { + // declare variables + var renderer = this, wrapper, attribs = {}; + if (useHTML && (renderer.allowHTML || !renderer.forExport)) { + return renderer.html(str, x, y); + } + attribs.x = Math.round(x || 0); // X always needed for line-wrap logic + if (y) { + attribs.y = Math.round(y); + } + if (defined(str)) { + attribs.text = str; + } + wrapper = renderer.createElement('text') + .attr(attribs); + if (!useHTML) { + wrapper.xSetter = function (value, key, element) { + var tspans = element.getElementsByTagName('tspan'), tspan, parentVal = element.getAttribute(key), i; + for (i = 0; i < tspans.length; i++) { + tspan = tspans[i]; + // If the x values are equal, the tspan represents a + // linebreak + if (tspan.getAttribute(key) === parentVal) { + tspan.setAttribute(key, value); + } + } + element.setAttribute(key, value); + }; + } + return wrapper; + }, + /** + * Utility to return the baseline offset and total line height from the font + * size. + * + * @function Highcharts.SVGRenderer#fontMetrics + * + * @param {number|string} [fontSize] + * The current font size to inspect. If not given, the font size + * will be found from the DOM element. + * + * @param {Highcharts.SVGElement|Highcharts.SVGDOMElement} [elem] + * The element to inspect for a current font size. + * + * @return {Highcharts.FontMetricsObject} + * The font metrics. + */ + fontMetrics: function (fontSize, elem) { + var lineHeight, baseline; + if ((this.styledMode || !/px/.test(fontSize)) && + win.getComputedStyle // old IE doesn't support it + ) { + fontSize = elem && SVGElement.prototype.getStyle.call(elem, 'font-size'); + } + else { + fontSize = fontSize || + // When the elem is a DOM element (#5932) + (elem && elem.style && elem.style.fontSize) || + // Fall back on the renderer style default + (this.style && this.style.fontSize); + } + // Handle different units + if (/px/.test(fontSize)) { + fontSize = pInt(fontSize); + } + else { + fontSize = 12; + } + // Empirical values found by comparing font size and bounding box + // height. Applies to the default font family. + // https://jsfiddle.net/highcharts/7xvn7/ + lineHeight = fontSize < 24 ? fontSize + 3 : Math.round(fontSize * 1.2); + baseline = Math.round(lineHeight * 0.8); + return { + h: lineHeight, + b: baseline, + f: fontSize + }; + }, + /** + * Correct X and Y positioning of a label for rotation (#1764). + * + * @private + * @function Highcharts.SVGRenderer#rotCorr + * + * @param {number} baseline + * + * @param {number} rotation + * + * @param {boolean} [alterY] + * + * @param {Highcharts.PositionObject} + */ + rotCorr: function (baseline, rotation, alterY) { + var y = baseline; + if (rotation && alterY) { + y = Math.max(y * Math.cos(rotation * deg2rad), 4); + } + return { + x: (-baseline / 3) * Math.sin(rotation * deg2rad), + y: y + }; + }, + /** + * Compatibility function to convert the legacy one-dimensional path array + * into an array of segments. + * + * It is used in maps to parse the `path` option, and in SVGRenderer.dSetter + * to support legacy paths from demos. + * + * @param path @private + * @function Highcharts.SVGRenderer#pathToSegments + * + * @param {Array} + * + * @return {Highcharts.SVGPathArray} + */ + pathToSegments: function (path) { + var ret = []; + var segment = []; + var commandLength = { + A: 8, + C: 7, + H: 2, + L: 3, + M: 3, + Q: 5, + S: 5, + T: 3, + V: 2 + }; + // Short, non-typesafe parsing of the one-dimensional array. It splits + // the path on any string. This is not type checked against the tuple + // types, but is shorter, and doesn't require specific checks for any + // command type in SVG. + for (var i = 0; i < path.length; i++) { + // Command skipped, repeat previous or insert L/l for M/m + if (isString(segment[0]) && + isNumber(path[i]) && + segment.length === commandLength[(segment[0].toUpperCase())]) { + path.splice(i, 0, segment[0].replace('M', 'L').replace('m', 'l')); + } + // Split on string + if (typeof path[i] === 'string') { + if (segment.length) { + ret.push(segment.slice(0)); + } + segment.length = 0; + } + segment.push(path[i]); + } + ret.push(segment.slice(0)); + return ret; + /* + // Fully type-safe version where each tuple type is checked. The + // downside is filesize and a lack of flexibility for unsupported + // commands + const ret: Highcharts.SVGPathArray = [], + commands = { + A: 7, + C: 6, + H: 1, + L: 2, + M: 2, + Q: 4, + S: 4, + T: 2, + V: 1, + Z: 0 + }; + + let i = 0, + lastI = 0, + lastCommand; + + while (i < path.length) { + const item = path[i]; + + let command; + + if (typeof item === 'string') { + command = item; + i += 1; + } else { + command = lastCommand || 'M'; + } + + // Upper case + const commandUC = command.toUpperCase(); + + if (commandUC in commands) { + + // No numeric parameters + if (command === 'Z' || command === 'z') { + ret.push([command]); + + // One numeric parameter + } else { + const val0 = path[i]; + if (typeof val0 === 'number') { + + // Horizontal line to + if (command === 'H' || command === 'h') { + ret.push([command, val0]); + i += 1; + + // Vertical line to + } else if (command === 'V' || command === 'v') { + ret.push([command, val0]); + i += 1; + + // Two numeric parameters + } else { + const val1 = path[i + 1]; + if (typeof val1 === 'number') { + // lineTo + if (command === 'L' || command === 'l') { + ret.push([command, val0, val1]); + i += 2; + + // moveTo + } else if (command === 'M' || command === 'm') { + ret.push([command, val0, val1]); + i += 2; + + // Smooth quadratic bezier + } else if (command === 'T' || command === 't') { + ret.push([command, val0, val1]); + i += 2; + + // Four numeric parameters + } else { + const val2 = path[i + 2], + val3 = path[i + 3]; + if ( + typeof val2 === 'number' && + typeof val3 === 'number' + ) { + // Quadratic bezier to + if ( + command === 'Q' || + command === 'q' + ) { + ret.push([ + command, + val0, + val1, + val2, + val3 + ]); + i += 4; + + // Smooth cubic bezier to + } else if ( + command === 'S' || + command === 's' + ) { + ret.push([ + command, + val0, + val1, + val2, + val3 + ]); + i += 4; + + // Six numeric parameters + } else { + const val4 = path[i + 4], + val5 = path[i + 5]; + + if ( + typeof val4 === 'number' && + typeof val5 === 'number' + ) { + // Curve to + if ( + command === 'C' || + command === 'c' + ) { + ret.push([ + command, + val0, + val1, + val2, + val3, + val4, + val5 + ]); + i += 6; + + // Seven numeric parameters + } else { + const val6 = path[i + 6]; + + // Arc to + if ( + typeof val6 === + 'number' && + ( + command === 'A' || + command === 'a' + ) + ) { + ret.push([ + command, + val0, + val1, + val2, + val3, + val4, + val5, + val6 + ]); + i += 7; + + } + + } + } + } + } + } + } + + } + } + } + } + + // An unmarked command following a moveTo is a lineTo + lastCommand = command === 'M' ? 'L' : command; + + if (i === lastI) { + break; + } + lastI = i; + } + return ret; + */ + }, + /** + * Draw a label, which is an extended text element with support for border + * and background. Highcharts creates a `g` element with a text and a `path` + * or `rect` inside, to make it behave somewhat like a HTML div. Border and + * background are set through `stroke`, `stroke-width` and `fill` attributes + * using the {@link Highcharts.SVGElement#attr|attr} method. To update the + * text after render, run `label.attr({ text: 'New text' })`. + * + * @sample highcharts/members/renderer-label-on-chart/ + * A label on the chart + * + * @function Highcharts.SVGRenderer#label + * + * @param {string} str + * The initial text string or (subset) HTML to render. + * + * @param {number} x + * The x position of the label's left side. + * + * @param {number} [y] + * The y position of the label's top side or baseline, depending on + * the `baseline` parameter. + * + * @param {string} [shape='rect'] + * The shape of the label's border/background, if any. Defaults to + * `rect`. Other possible values are `callout` or other shapes + * defined in {@link Highcharts.SVGRenderer#symbols}. + * + * @param {number} [anchorX] + * In case the `shape` has a pointer, like a flag, this is the + * coordinates it should be pinned to. + * + * @param {number} [anchorY] + * In case the `shape` has a pointer, like a flag, this is the + * coordinates it should be pinned to. + * + * @param {boolean} [useHTML=false] + * Wether to use HTML to render the label. + * + * @param {boolean} [baseline=false] + * Whether to position the label relative to the text baseline, + * like {@link Highcharts.SVGRenderer#text|renderer.text}, or to the + * upper border of the rectangle. + * + * @param {string} [className] + * Class name for the group. + * + * @return {Highcharts.SVGElement} + * The generated label. + */ + label: function (str, x, y, shape, anchorX, anchorY, useHTML, baseline, className) { + var renderer = this, styledMode = renderer.styledMode, wrapper = renderer.g((className !== 'button' && 'label')), text = wrapper.text = renderer.text('', 0, 0, useHTML) + .attr({ + zIndex: 1 + }), box, emptyBBox = { width: 0, height: 0, x: 0, y: 0 }, bBox = emptyBBox, alignFactor = 0, padding = 3, paddingLeft = 0, width, height, wrapperX, wrapperY, textAlign, deferredAttr = {}, strokeWidth, baselineOffset, hasBGImage = /^url\((.*?)\)$/.test(shape), needsBox = styledMode || hasBGImage, getCrispAdjust = function () { + return styledMode ? + box.strokeWidth() % 2 / 2 : + (strokeWidth ? parseInt(strokeWidth, 10) : 0) % 2 / 2; + }, updateBoxSize, updateTextPadding, boxAttr; + if (className) { + wrapper.addClass('highcharts-' + className); + } + /* This function runs after the label is added to the DOM (when the + bounding box is available), and after the text of the label is + updated to detect the new bounding box and reflect it in the border + box. */ + updateBoxSize = function () { + var style = text.element.style, crispAdjust, attribs = {}; + // #12165 error when width is null (auto) + // #12163 when fontweight: bold, recalculate bBox withot cache + // #3295 && 3514 box failure when string equals 0 + bBox = ((!isNumber(width) || !isNumber(height) || textAlign) && + defined(text.textStr)) ? + text.getBBox() : emptyBBox; + wrapper.width = ((width || bBox.width || 0) + + 2 * padding + + paddingLeft); + wrapper.height = (height || bBox.height || 0) + 2 * padding; + // Update the label-scoped y offset. Math.min because of inline + // style (#9400) + baselineOffset = padding + Math.min(renderer + .fontMetrics(style && style.fontSize, text).b, + // When the height is 0, there is no bBox, so go with the font + // metrics. Highmaps CSS demos. + bBox.height || Infinity); + if (needsBox) { + // Create the border box if it is not already present + if (!box) { + // Symbol definition exists (#5324) + wrapper.box = box = + renderer.symbols[shape] || hasBGImage ? + renderer.symbol(shape) : + renderer.rect(); + box.addClass(// Don't use label className for buttons + (className === 'button' ? '' : 'highcharts-label-box') + + (className ? ' highcharts-' + className + '-box' : '')); + box.add(wrapper); + crispAdjust = getCrispAdjust(); + attribs.x = crispAdjust; + attribs.y = (baseline ? -baselineOffset : 0) + crispAdjust; + } + // Apply the box attributes + attribs.width = Math.round(wrapper.width); + attribs.height = Math.round(wrapper.height); + box.attr(extend(attribs, deferredAttr)); + deferredAttr = {}; + } + }; + /* + * This function runs after setting text or padding, but only if padding + * is changed. + */ + updateTextPadding = function () { + var textX = paddingLeft + padding, textY; + // determin y based on the baseline + textY = baseline ? 0 : baselineOffset; + // compensate for alignment + if (defined(width) && + bBox && + (textAlign === 'center' || textAlign === 'right')) { + textX += { center: 0.5, right: 1 }[textAlign] * + (width - bBox.width); + } + // update if anything changed + if (textX !== text.x || textY !== text.y) { + text.attr('x', textX); + // #8159 - prevent misplaced data labels in treemap + // (useHTML: true) + if (text.hasBoxWidthChanged) { + bBox = text.getBBox(true); + updateBoxSize(); + } + if (typeof textY !== 'undefined') { + text.attr('y', textY); + } + } + // record current values + text.x = textX; + text.y = textY; + }; + /* + * Set a box attribute, or defer it if the box is not yet created + */ + boxAttr = function (key, value) { + if (box) { + box.attr(key, value); + } + else { + deferredAttr[key] = value; + } + }; + /* + * After the text element is added, get the desired size of the border + * box and add it before the text in the DOM. + */ + wrapper.onAdd = function () { + text.add(wrapper); + wrapper.attr({ + // Alignment is available now (#3295, 0 not rendered if given + // as a value) + text: (str || str === 0) ? str : '', + x: x, + y: y + }); + if (box && defined(anchorX)) { + wrapper.attr({ + anchorX: anchorX, + anchorY: anchorY + }); + } + }; + /* + * Add specific attribute setters. + */ + // only change local variables + wrapper.widthSetter = function (value) { + // width:auto => null + width = isNumber(value) ? value : null; + }; + wrapper.heightSetter = function (value) { + height = value; + }; + wrapper['text-alignSetter'] = function (value) { + textAlign = value; + }; + wrapper.paddingSetter = function (value) { + if (defined(value) && value !== padding) { + padding = wrapper.padding = value; + updateTextPadding(); + } + }; + wrapper.paddingLeftSetter = function (value) { + if (defined(value) && value !== paddingLeft) { + paddingLeft = value; + updateTextPadding(); + } + }; + // change local variable and prevent setting attribute on the group + wrapper.alignSetter = function (value) { + value = { + left: 0, + center: 0.5, + right: 1 + }[value]; + if (value !== alignFactor) { + alignFactor = value; + // Bounding box exists, means we're dynamically changing + if (bBox) { + wrapper.attr({ x: wrapperX }); // #5134 + } + } + }; + // apply these to the box and the text alike + wrapper.textSetter = function (value) { + if (typeof value !== 'undefined') { + // Must use .attr to ensure transforms are done (#10009) + text.attr({ + text: value + }); + } + updateBoxSize(); + updateTextPadding(); + }; + // apply these to the box but not to the text + wrapper['stroke-widthSetter'] = function (value, key) { + if (value) { + needsBox = true; + } + strokeWidth = this['stroke-width'] = value; + boxAttr(key, value); + }; + if (styledMode) { + wrapper.rSetter = function (value, key) { + boxAttr(key, value); + }; + } + else { + wrapper.strokeSetter = + wrapper.fillSetter = + wrapper.rSetter = function (value, key) { + if (key !== 'r') { + if (key === 'fill' && value) { + needsBox = true; + } + // for animation getter (#6776) + wrapper[key] = value; + } + boxAttr(key, value); + }; + } + wrapper.anchorXSetter = function (value, key) { + anchorX = wrapper.anchorX = value; + boxAttr(key, Math.round(value) - getCrispAdjust() - wrapperX); + }; + wrapper.anchorYSetter = function (value, key) { + anchorY = wrapper.anchorY = value; + boxAttr(key, value - wrapperY); + }; + // rename attributes + wrapper.xSetter = function (value) { + wrapper.x = value; // for animation getter + if (alignFactor) { + value -= alignFactor * ((width || bBox.width) + 2 * padding); + // Force animation even when setting to the same value (#7898) + wrapper['forceAnimate:x'] = true; + } + wrapperX = Math.round(value); + wrapper.attr('translateX', wrapperX); + }; + wrapper.ySetter = function (value) { + wrapperY = wrapper.y = Math.round(value); + wrapper.attr('translateY', wrapperY); + }; + wrapper.isLabel = true; + // Redirect certain methods to either the box or the text + var baseCss = wrapper.css; + var wrapperExtension = { + /** + * Pick up some properties and apply them to the text instead of the + * wrapper. + */ + css: function (styles) { + if (styles) { + var textStyles = {}, isWidth, isFontStyle; + // Create a copy to avoid altering the original object + // (#537) + styles = merge(styles); + wrapper.textProps.forEach(function (prop) { + if (typeof styles[prop] !== 'undefined') { + textStyles[prop] = styles[prop]; + delete styles[prop]; + } + }); + text.css(textStyles); + isWidth = 'width' in textStyles; + isFontStyle = 'fontSize' in textStyles || + 'fontWeight' in textStyles; + // Update existing text, box (#9400, #12163) + if (isWidth || isFontStyle) { + updateBoxSize(); + // Keep updated (#9400, #12163) + if (isFontStyle) { + updateTextPadding(); + } + } + } + return baseCss.call(wrapper, styles); + }, + /* + * Return the bounding box of the box, not the group. + */ + getBBox: function () { + return { + width: bBox.width + 2 * padding, + height: bBox.height + 2 * padding, + x: bBox.x - padding, + y: bBox.y - padding + }; + }, + /** + * Destroy and release memory. + */ + destroy: function () { + // Added by button implementation + removeEvent(wrapper.element, 'mouseenter'); + removeEvent(wrapper.element, 'mouseleave'); + if (text) { + text.destroy(); + } + if (box) { + box = box.destroy(); + } + // Call base implementation to destroy the rest + SVGElement.prototype.destroy.call(wrapper); + // Release local pointers (#1298) + wrapper = + renderer = + text = + updateBoxSize = + updateTextPadding = + boxAttr = null; + } + }; + // Event handling. In case of useHTML, we need to make sure that events + // are captured on the span as well, and that mouseenter/mouseleave + // between the SVG group and the HTML span are not treated as real + // enter/leave events. #13310. + wrapper.on = function (eventType, handler) { + var span = text && text.element.tagName === 'SPAN' ? text : void 0; + var selectiveHandler; + if (span) { + selectiveHandler = function (e) { + if ((eventType === 'mouseenter' || + eventType === 'mouseleave') && + e.relatedTarget instanceof Element && + (wrapper.element.contains(e.relatedTarget) || + span.element.contains(e.relatedTarget))) { + return; + } + handler.call(wrapper.element, e); + }; + span.on(eventType, selectiveHandler); + } + SVGElement.prototype.on.call(wrapper, eventType, selectiveHandler || handler); + return wrapper; + }; + if (!styledMode) { + /** + * Apply the shadow to the box. + * + * @ignore + * @function Highcharts.SVGElement#shadow + * + * @return {Highcharts.SVGElement} + */ + wrapperExtension.shadow = function (b) { + if (b) { + updateBoxSize(); + if (box) { + box.shadow(b); + } + } + return wrapper; + }; + } + return extend(wrapper, wrapperExtension); + } + }); // end SVGRenderer + // general renderer + H.Renderer = SVGRenderer; + + }); + _registerModule(_modules, 'parts/Html.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var attr = U.attr, createElement = U.createElement, css = U.css, defined = U.defined, extend = U.extend, pick = U.pick, pInt = U.pInt; + var isFirefox = H.isFirefox, isMS = H.isMS, isWebKit = H.isWebKit, SVGElement = H.SVGElement, SVGRenderer = H.SVGRenderer, win = H.win; + /* eslint-disable valid-jsdoc */ + // Extend SvgElement for useHTML option. + extend(SVGElement.prototype, /** @lends SVGElement.prototype */ { + /** + * Apply CSS to HTML elements. This is used in text within SVG rendering and + * by the VML renderer + * + * @private + * @function Highcharts.SVGElement#htmlCss + * + * @param {Highcharts.CSSObject} styles + * + * @return {Highcharts.SVGElement} + */ + htmlCss: function (styles) { + var wrapper = this, element = wrapper.element, + // When setting or unsetting the width style, we need to update + // transform (#8809) + isSettingWidth = (element.tagName === 'SPAN' && + styles && + 'width' in styles), textWidth = pick(isSettingWidth && styles.width, void 0), doTransform; + if (isSettingWidth) { + delete styles.width; + wrapper.textWidth = textWidth; + doTransform = true; + } + if (styles && styles.textOverflow === 'ellipsis') { + styles.whiteSpace = 'nowrap'; + styles.overflow = 'hidden'; + } + wrapper.styles = extend(wrapper.styles, styles); + css(wrapper.element, styles); + // Now that all styles are applied, to the transform + if (doTransform) { + wrapper.htmlUpdateTransform(); + } + return wrapper; + }, + /** + * VML and useHTML method for calculating the bounding box based on offsets. + * + * @private + * @function Highcharts.SVGElement#htmlGetBBox + * + * @param {boolean} refresh + * Whether to force a fresh value from the DOM or to use the cached + * value. + * + * @return {Highcharts.BBoxObject} + * A hash containing values for x, y, width and height. + */ + htmlGetBBox: function () { + var wrapper = this, element = wrapper.element; + return { + x: element.offsetLeft, + y: element.offsetTop, + width: element.offsetWidth, + height: element.offsetHeight + }; + }, + /** + * VML override private method to update elements based on internal + * properties based on SVG transform. + * + * @private + * @function Highcharts.SVGElement#htmlUpdateTransform + * @return {void} + */ + htmlUpdateTransform: function () { + // aligning non added elements is expensive + if (!this.added) { + this.alignOnAdd = true; + return; + } + var wrapper = this, renderer = wrapper.renderer, elem = wrapper.element, translateX = wrapper.translateX || 0, translateY = wrapper.translateY || 0, x = wrapper.x || 0, y = wrapper.y || 0, align = wrapper.textAlign || 'left', alignCorrection = { + left: 0, center: 0.5, right: 1 + }[align], styles = wrapper.styles, whiteSpace = styles && styles.whiteSpace; + /** + * @private + * @return {number} + */ + function getTextPxLength() { + // Reset multiline/ellipsis in order to read width (#4928, + // #5417) + css(elem, { + width: '', + whiteSpace: whiteSpace || 'nowrap' + }); + return elem.offsetWidth; + } + // apply translate + css(elem, { + marginLeft: translateX, + marginTop: translateY + }); + if (!renderer.styledMode && wrapper.shadows) { // used in labels/tooltip + wrapper.shadows.forEach(function (shadow) { + css(shadow, { + marginLeft: translateX + 1, + marginTop: translateY + 1 + }); + }); + } + // apply inversion + if (wrapper.inverted) { // wrapper is a group + [].forEach.call(elem.childNodes, function (child) { + renderer.invertChild(child, elem); + }); + } + if (elem.tagName === 'SPAN') { + var rotation = wrapper.rotation, baseline, textWidth = wrapper.textWidth && pInt(wrapper.textWidth), currentTextTransform = [ + rotation, + align, + elem.innerHTML, + wrapper.textWidth, + wrapper.textAlign + ].join(','); + // Update textWidth. Use the memoized textPxLength if possible, to + // avoid the getTextPxLength function using elem.offsetWidth. + // Calling offsetWidth affects rendering time as it forces layout + // (#7656). + if (textWidth !== wrapper.oldTextWidth && + ((textWidth > wrapper.oldTextWidth) || + (wrapper.textPxLength || getTextPxLength()) > textWidth) && ( + // Only set the width if the text is able to word-wrap, or + // text-overflow is ellipsis (#9537) + /[ \-]/.test(elem.textContent || elem.innerText) || + elem.style.textOverflow === 'ellipsis')) { // #983, #1254 + css(elem, { + width: textWidth + 'px', + display: 'block', + whiteSpace: whiteSpace || 'normal' // #3331 + }); + wrapper.oldTextWidth = textWidth; + wrapper.hasBoxWidthChanged = true; // #8159 + } + else { + wrapper.hasBoxWidthChanged = false; // #8159 + } + // Do the calculations and DOM access only if properties changed + if (currentTextTransform !== wrapper.cTT) { + baseline = renderer.fontMetrics(elem.style.fontSize, elem).b; + // Renderer specific handling of span rotation, but only if we + // have something to update. + if (defined(rotation) && + ((rotation !== (wrapper.oldRotation || 0)) || + (align !== wrapper.oldAlign))) { + wrapper.setSpanRotation(rotation, alignCorrection, baseline); + } + wrapper.getSpanCorrection( + // Avoid elem.offsetWidth if we can, it affects rendering + // time heavily (#7656) + ((!defined(rotation) && wrapper.textPxLength) || // #7920 + elem.offsetWidth), baseline, alignCorrection, rotation, align); + } + // apply position with correction + css(elem, { + left: (x + (wrapper.xCorr || 0)) + 'px', + top: (y + (wrapper.yCorr || 0)) + 'px' + }); + // record current text transform + wrapper.cTT = currentTextTransform; + wrapper.oldRotation = rotation; + wrapper.oldAlign = align; + } + }, + /** + * Set the rotation of an individual HTML span. + * + * @private + * @function Highcharts.SVGElement#setSpanRotation + * @param {number} rotation + * @param {number} alignCorrection + * @param {number} baseline + * @return {void} + */ + setSpanRotation: function (rotation, alignCorrection, baseline) { + var rotationStyle = {}, cssTransformKey = this.renderer.getTransformKey(); + rotationStyle[cssTransformKey] = rotationStyle.transform = + 'rotate(' + rotation + 'deg)'; + rotationStyle[cssTransformKey + (isFirefox ? 'Origin' : '-origin')] = + rotationStyle.transformOrigin = + (alignCorrection * 100) + '% ' + baseline + 'px'; + css(this.element, rotationStyle); + }, + /** + * Get the correction in X and Y positioning as the element is rotated. + * + * @private + * @function Highcharts.SVGElement#getSpanCorrection + * @param {number} width + * @param {number} baseline + * @param {number} alignCorrection + * @return {void} + */ + getSpanCorrection: function (width, baseline, alignCorrection) { + this.xCorr = -width * alignCorrection; + this.yCorr = -baseline; + } + }); + // Extend SvgRenderer for useHTML option. + extend(SVGRenderer.prototype, /** @lends SVGRenderer.prototype */ { + /** + * @private + * @function Highcharts.SVGRenderer#getTransformKey + * + * @return {string} + */ + getTransformKey: function () { + return isMS && !/Edge/.test(win.navigator.userAgent) ? + '-ms-transform' : + isWebKit ? + '-webkit-transform' : + isFirefox ? + 'MozTransform' : + win.opera ? + '-o-transform' : + ''; + }, + /** + * Create HTML text node. This is used by the VML renderer as well as the + * SVG renderer through the useHTML option. + * + * @private + * @function Highcharts.SVGRenderer#html + * + * @param {string} str + * The text of (subset) HTML to draw. + * + * @param {number} x + * The x position of the text's lower left corner. + * + * @param {number} y + * The y position of the text's lower left corner. + * + * @return {Highcharts.HTMLDOMElement} + */ + html: function (str, x, y) { + var wrapper = this.createElement('span'), element = wrapper.element, renderer = wrapper.renderer, isSVG = renderer.isSVG, addSetters = function (gWrapper, style) { + // These properties are set as attributes on the SVG group, and + // as identical CSS properties on the div. (#3542) + ['opacity', 'visibility'].forEach(function (prop) { + gWrapper[prop + 'Setter'] = function (value, key, elem) { + var styleObject = gWrapper.div ? + gWrapper.div.style : + style; + SVGElement.prototype[prop + 'Setter'] + .call(this, value, key, elem); + if (styleObject) { + styleObject[key] = value; + } + }; + }); + gWrapper.addedSetters = true; + }; + // Text setter + wrapper.textSetter = function (value) { + if (value !== element.innerHTML) { + delete this.bBox; + delete this.oldTextWidth; + } + this.textStr = value; + element.innerHTML = pick(value, ''); + wrapper.doTransform = true; + }; + // Add setters for the element itself (#4938) + if (isSVG) { // #4938, only for HTML within SVG + addSetters(wrapper, wrapper.element.style); + } + // Various setters which rely on update transform + wrapper.xSetter = + wrapper.ySetter = + wrapper.alignSetter = + wrapper.rotationSetter = + function (value, key) { + if (key === 'align') { + // Do not overwrite the SVGElement.align method. Same as VML. + key = 'textAlign'; + } + wrapper[key] = value; + wrapper.doTransform = true; + }; + // Runs at the end of .attr() + wrapper.afterSetters = function () { + // Update transform. Do this outside the loop to prevent redundant + // updating for batch setting of attributes. + if (this.doTransform) { + this.htmlUpdateTransform(); + this.doTransform = false; + } + }; + // Set the default attributes + wrapper + .attr({ + text: str, + x: Math.round(x), + y: Math.round(y) + }) + .css({ + position: 'absolute' + }); + if (!renderer.styledMode) { + wrapper.css({ + fontFamily: this.style.fontFamily, + fontSize: this.style.fontSize + }); + } + // Keep the whiteSpace style outside the wrapper.styles collection + element.style.whiteSpace = 'nowrap'; + // Use the HTML specific .css method + wrapper.css = wrapper.htmlCss; + // This is specific for HTML within SVG + if (isSVG) { + wrapper.add = function (svgGroupWrapper) { + var htmlGroup, container = renderer.box.parentNode, parentGroup, parents = []; + this.parentGroup = svgGroupWrapper; + // Create a mock group to hold the HTML elements + if (svgGroupWrapper) { + htmlGroup = svgGroupWrapper.div; + if (!htmlGroup) { + // Read the parent chain into an array and read from top + // down + parentGroup = svgGroupWrapper; + while (parentGroup) { + parents.push(parentGroup); + // Move up to the next parent group + parentGroup = parentGroup.parentGroup; + } + // Ensure dynamically updating position when any parent + // is translated + parents.reverse().forEach(function (parentGroup) { + var htmlGroupStyle, cls = attr(parentGroup.element, 'class'); + /** + * Common translate setter for X and Y on the HTML + * group. Reverted the fix for #6957 du to + * positioning problems and offline export (#7254, + * #7280, #7529) + * @private + * @param {*} value + * @param {string} key + * @return {void} + */ + function translateSetter(value, key) { + parentGroup[key] = value; + if (key === 'translateX') { + htmlGroupStyle.left = value + 'px'; + } + else { + htmlGroupStyle.top = value + 'px'; + } + parentGroup.doTransform = true; + } + // Create a HTML div and append it to the parent div + // to emulate the SVG group structure + htmlGroup = + parentGroup.div = + parentGroup.div || createElement('div', cls ? { className: cls } : void 0, { + position: 'absolute', + left: (parentGroup.translateX || 0) + 'px', + top: (parentGroup.translateY || 0) + 'px', + display: parentGroup.display, + opacity: parentGroup.opacity, + pointerEvents: (parentGroup.styles && + parentGroup.styles.pointerEvents) // #5595 + // the top group is appended to container + }, htmlGroup || container); + // Shortcut + htmlGroupStyle = htmlGroup.style; + // Set listeners to update the HTML div's position + // whenever the SVG group position is changed. + extend(parentGroup, { + // (#7287) Pass htmlGroup to use + // the related group + classSetter: (function (htmlGroup) { + return function (value) { + this.element.setAttribute('class', value); + htmlGroup.className = value; + }; + }(htmlGroup)), + on: function () { + if (parents[0].div) { // #6418 + wrapper.on.apply({ element: parents[0].div }, arguments); + } + return parentGroup; + }, + translateXSetter: translateSetter, + translateYSetter: translateSetter + }); + if (!parentGroup.addedSetters) { + addSetters(parentGroup); + } + }); + } + } + else { + htmlGroup = container; + } + htmlGroup.appendChild(element); + // Shared with VML: + wrapper.added = true; + if (wrapper.alignOnAdd) { + wrapper.htmlUpdateTransform(); + } + return wrapper; + }; + } + return wrapper; + } + }); + + }); + _registerModule(_modules, 'parts/Tick.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Optional parameters for the tick. + * @private + * @interface Highcharts.TickParametersObject + */ /** + * Set category for the tick. + * @name Highcharts.TickParametersObject#category + * @type {string|undefined} + */ /** + * @name Highcharts.TickParametersObject#options + * @type {Highcharts.Dictionary|undefined} + */ /** + * Set tickmarkOffset for the tick. + * @name Highcharts.TickParametersObject#tickmarkOffset + * @type {number|undefined} + */ + var clamp = U.clamp, correctFloat = U.correctFloat, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, extend = U.extend, fireEvent = U.fireEvent, isNumber = U.isNumber, merge = U.merge, objectEach = U.objectEach, pick = U.pick; + var deg2rad = H.deg2rad; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The Tick class. + * + * @class + * @name Highcharts.Tick + * + * @param {Highcharts.Axis} axis + * The axis of the tick. + * + * @param {number} pos + * The position of the tick on the axis in terms of axis values. + * + * @param {string} [type] + * The type of tick, either 'minor' or an empty string + * + * @param {boolean} [noLabel=false] + * Whether to disable the label or not. Defaults to false. + * + * @param {object} [parameters] + * Optional parameters for the tick. + */ + var Tick = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Tick(axis, pos, type, noLabel, parameters) { + this.isNew = true; + this.isNewLabel = true; + /** + * The related axis of the tick. + * @name Highcharts.Tick#axis + * @type {Highcharts.Axis} + */ + this.axis = axis; + /** + * The logical position of the tick on the axis in terms of axis values. + * @name Highcharts.Tick#pos + * @type {number} + */ + this.pos = pos; + /** + * The tick type, which can be `"minor"`, or an empty string. + * @name Highcharts.Tick#type + * @type {string} + */ + this.type = type || ''; + this.parameters = parameters || {}; + /** + * The mark offset of the tick on the axis. Usually `undefined`, numeric + * for grid axes. + * @name Highcharts.Tick#tickmarkOffset + * @type {number|undefined} + */ + this.tickmarkOffset = this.parameters.tickmarkOffset; + this.options = this.parameters.options; + fireEvent(this, 'init'); + if (!type && !noLabel) { + this.addLabel(); + } + } + /* * + * + * Functions + * + * */ + /** + * Write the tick label. + * + * @private + * @function Highcharts.Tick#addLabel + * @return {void} + */ + Tick.prototype.addLabel = function () { + var tick = this, axis = tick.axis, options = axis.options, chart = axis.chart, categories = axis.categories, log = axis.logarithmic, names = axis.names, pos = tick.pos, labelOptions = pick(tick.options && tick.options.labels, options.labels), str, tickPositions = axis.tickPositions, isFirst = pos === tickPositions[0], isLast = pos === tickPositions[tickPositions.length - 1], value = this.parameters.category || (categories ? + pick(categories[pos], names[pos], pos) : + pos), label = tick.label, animateLabels = (!labelOptions.step || labelOptions.step === 1) && + axis.tickInterval === 1, tickPositionInfo = tickPositions.info, dateTimeLabelFormat, dateTimeLabelFormats, i, list; + // Set the datetime label format. If a higher rank is set for this + // position, use that. If not, use the general format. + if (axis.dateTime && tickPositionInfo) { + dateTimeLabelFormats = chart.time.resolveDTLFormat(options.dateTimeLabelFormats[(!options.grid && + tickPositionInfo.higherRanks[pos]) || + tickPositionInfo.unitName]); + dateTimeLabelFormat = dateTimeLabelFormats.main; + } + // set properties for access in render method + /** + * True if the tick is the first one on the axis. + * @name Highcharts.Tick#isFirst + * @readonly + * @type {boolean|undefined} + */ + tick.isFirst = isFirst; + /** + * True if the tick is the last one on the axis. + * @name Highcharts.Tick#isLast + * @readonly + * @type {boolean|undefined} + */ + tick.isLast = isLast; + // Get the string + tick.formatCtx = { + axis: axis, + chart: chart, + isFirst: isFirst, + isLast: isLast, + dateTimeLabelFormat: dateTimeLabelFormat, + tickPositionInfo: tickPositionInfo, + value: log ? correctFloat(log.lin2log(value)) : value, + pos: pos + }; + str = axis.labelFormatter.call(tick.formatCtx, this.formatCtx); + // Set up conditional formatting based on the format list if existing. + list = dateTimeLabelFormats && dateTimeLabelFormats.list; + if (list) { + tick.shortenLabel = function () { + for (i = 0; i < list.length; i++) { + label.attr({ + text: axis.labelFormatter.call(extend(tick.formatCtx, { dateTimeLabelFormat: list[i] })) + }); + if (label.getBBox().width < + axis.getSlotWidth(tick) - 2 * + pick(labelOptions.padding, 5)) { + return; + } + } + label.attr({ + text: '' + }); + }; + } + // Call only after first render + if (animateLabels && axis._addedPlotLB && axis.isXAxis) { + tick.moveLabel(str, labelOptions); + } + // First call + if (!defined(label) && !tick.movedLabel) { + /** + * The rendered text label of the tick. + * @name Highcharts.Tick#label + * @type {Highcharts.SVGElement|undefined} + */ + tick.label = label = tick.createLabel({ x: 0, y: 0 }, str, labelOptions); + // Base value to detect change for new calls to getBBox + tick.rotation = 0; + // update + } + else if (label && label.textStr !== str && !animateLabels) { + // When resetting text, also reset the width if dynamically set + // (#8809) + if (label.textWidth && + !(labelOptions.style && labelOptions.style.width) && + !label.styles.width) { + label.css({ width: null }); + } + label.attr({ text: str }); + label.textPxLength = label.getBBox().width; + } + }; + /** + * Render and return the label of the tick. + * + * @private + * @function Highcharts.Tick#createLabel + * @param {Highcharts.PositionObject} xy + * @param {string} str + * @param {Highcharts.XAxisLabelsOptions} labelOptions + * @return {Highcharts.SVGElement|undefined} + */ + Tick.prototype.createLabel = function (xy, str, labelOptions) { + var axis = this.axis, chart = axis.chart, label = defined(str) && labelOptions.enabled ? + chart.renderer + .text(str, xy.x, xy.y, labelOptions.useHTML) + .add(axis.labelGroup) : + null; + // Un-rotated length + if (label) { + // Without position absolute, IE export sometimes is wrong + if (!chart.styledMode) { + label.css(merge(labelOptions.style)); + } + label.textPxLength = label.getBBox().width; + } + return label; + }; + /** + * Destructor for the tick prototype + * + * @private + * @function Highcharts.Tick#destroy + * @return {void} + */ + Tick.prototype.destroy = function () { + destroyObjectProperties(this, this.axis); + }; + /** + * Gets the x and y positions for ticks in terms of pixels. + * + * @private + * @function Highcharts.Tick#getPosition + * + * @param {boolean} horiz + * Whether the tick is on an horizontal axis or not. + * + * @param {number} tickPos + * Position of the tick. + * + * @param {number} tickmarkOffset + * Tickmark offset for all ticks. + * + * @param {boolean} [old] + * Whether the axis has changed or not. + * + * @return {Highcharts.PositionObject} + * The tick position. + * + * @fires Highcharts.Tick#event:afterGetPosition + */ + Tick.prototype.getPosition = function (horiz, tickPos, tickmarkOffset, old) { + var axis = this.axis, chart = axis.chart, cHeight = (old && chart.oldChartHeight) || chart.chartHeight, pos; + pos = { + x: horiz ? + correctFloat(axis.translate(tickPos + tickmarkOffset, null, null, old) + + axis.transB) : + (axis.left + + axis.offset + + (axis.opposite ? + (((old && chart.oldChartWidth) || + chart.chartWidth) - + axis.right - + axis.left) : + 0)), + y: horiz ? + (cHeight - + axis.bottom + + axis.offset - + (axis.opposite ? axis.height : 0)) : + correctFloat(cHeight - + axis.translate(tickPos + tickmarkOffset, null, null, old) - + axis.transB) + }; + // Chrome workaround for #10516 + pos.y = clamp(pos.y, -1e5, 1e5); + fireEvent(this, 'afterGetPosition', { pos: pos }); + return pos; + }; + /** + * Get the x, y position of the tick label + * + * @private + * @return {Highcharts.PositionObject} + */ + Tick.prototype.getLabelPosition = function (x, y, label, horiz, labelOptions, tickmarkOffset, index, step) { + var axis = this.axis, transA = axis.transA, reversed = ( // #7911 + axis.isLinked && axis.linkedParent ? + axis.linkedParent.reversed : + axis.reversed), staggerLines = axis.staggerLines, rotCorr = axis.tickRotCorr || { x: 0, y: 0 }, yOffset = labelOptions.y, + // Adjust for label alignment if we use reserveSpace: true (#5286) + labelOffsetCorrection = (!horiz && !axis.reserveSpaceDefault ? + -axis.labelOffset * (axis.labelAlign === 'center' ? 0.5 : 1) : + 0), line, pos = {}; + if (!defined(yOffset)) { + if (axis.side === 0) { + yOffset = label.rotation ? -8 : -label.getBBox().height; + } + else if (axis.side === 2) { + yOffset = rotCorr.y + 8; + } + else { + // #3140, #3140 + yOffset = Math.cos(label.rotation * deg2rad) * + (rotCorr.y - label.getBBox(false, 0).height / 2); + } + } + x = x + + labelOptions.x + + labelOffsetCorrection + + rotCorr.x - + (tickmarkOffset && horiz ? + tickmarkOffset * transA * (reversed ? -1 : 1) : + 0); + y = y + yOffset - (tickmarkOffset && !horiz ? + tickmarkOffset * transA * (reversed ? 1 : -1) : 0); + // Correct for staggered labels + if (staggerLines) { + line = (index / (step || 1) % staggerLines); + if (axis.opposite) { + line = staggerLines - line - 1; + } + y += line * (axis.labelOffset / staggerLines); + } + pos.x = x; + pos.y = Math.round(y); + fireEvent(this, 'afterGetLabelPosition', { pos: pos, tickmarkOffset: tickmarkOffset, index: index }); + return pos; + }; + /** + * Get the offset height or width of the label + * + * @private + * @function Highcharts.Tick#getLabelSize + * @return {number} + */ + Tick.prototype.getLabelSize = function () { + return this.label ? + this.label.getBBox()[this.axis.horiz ? 'height' : 'width'] : + 0; + }; + /** + * Extendible method to return the path of the marker + * + * @private + * + */ + Tick.prototype.getMarkPath = function (x, y, tickLength, tickWidth, horiz, renderer) { + return renderer.crispLine([[ + 'M', + x, + y + ], [ + 'L', + x + (horiz ? 0 : -tickLength), + y + (horiz ? tickLength : 0) + ]], tickWidth); + }; + /** + * Handle the label overflow by adjusting the labels to the left and right + * edge, or hide them if they collide into the neighbour label. + * + * @private + * @function Highcharts.Tick#handleOverflow + * @param {Highcharts.PositionObject} xy + * @return {void} + */ + Tick.prototype.handleOverflow = function (xy) { + var tick = this, axis = this.axis, labelOptions = axis.options.labels, pxPos = xy.x, chartWidth = axis.chart.chartWidth, spacing = axis.chart.spacing, leftBound = pick(axis.labelLeft, Math.min(axis.pos, spacing[3])), rightBound = pick(axis.labelRight, Math.max(!axis.isRadial ? axis.pos + axis.len : 0, chartWidth - spacing[1])), label = this.label, rotation = this.rotation, factor = { + left: 0, + center: 0.5, + right: 1 + }[axis.labelAlign || label.attr('align')], labelWidth = label.getBBox().width, slotWidth = axis.getSlotWidth(tick), modifiedSlotWidth = slotWidth, xCorrection = factor, goRight = 1, leftPos, rightPos, textWidth, css = {}; + // Check if the label overshoots the chart spacing box. If it does, move + // it. If it now overshoots the slotWidth, add ellipsis. + if (!rotation && + pick(labelOptions.overflow, 'justify') === 'justify') { + leftPos = pxPos - factor * labelWidth; + rightPos = pxPos + (1 - factor) * labelWidth; + if (leftPos < leftBound) { + modifiedSlotWidth = + xy.x + modifiedSlotWidth * (1 - factor) - leftBound; + } + else if (rightPos > rightBound) { + modifiedSlotWidth = + rightBound - xy.x + modifiedSlotWidth * factor; + goRight = -1; + } + modifiedSlotWidth = Math.min(slotWidth, modifiedSlotWidth); // #4177 + if (modifiedSlotWidth < slotWidth && axis.labelAlign === 'center') { + xy.x += (goRight * + (slotWidth - + modifiedSlotWidth - + xCorrection * (slotWidth - Math.min(labelWidth, modifiedSlotWidth)))); + } + // If the label width exceeds the available space, set a text width + // to be picked up below. Also, if a width has been set before, we + // need to set a new one because the reported labelWidth will be + // limited by the box (#3938). + if (labelWidth > modifiedSlotWidth || + (axis.autoRotation && (label.styles || {}).width)) { + textWidth = modifiedSlotWidth; + } + // Add ellipsis to prevent rotated labels to be clipped against the edge + // of the chart + } + else if (rotation < 0 && + pxPos - factor * labelWidth < leftBound) { + textWidth = Math.round(pxPos / Math.cos(rotation * deg2rad) - leftBound); + } + else if (rotation > 0 && + pxPos + factor * labelWidth > rightBound) { + textWidth = Math.round((chartWidth - pxPos) / + Math.cos(rotation * deg2rad)); + } + if (textWidth) { + if (tick.shortenLabel) { + tick.shortenLabel(); + } + else { + css.width = Math.floor(textWidth) + 'px'; + if (!(labelOptions.style || {}).textOverflow) { + css.textOverflow = 'ellipsis'; + } + label.css(css); + } + } + }; + /** + * Try to replace the label if the same one already exists. + * + * @private + * @function Highcharts.Tick#moveLabel + * @param {string} str + * @param {Highcharts.XAxisLabelsOptions} labelOptions + * + * @return {void} + */ + Tick.prototype.moveLabel = function (str, labelOptions) { + var tick = this, label = tick.label, moved = false, xAxis = tick.axis, chart = xAxis.chart, labelPos, reversed = xAxis.reversed, inverted = chart.inverted, xPos, yPos; + if (label && label.textStr === str) { + tick.movedLabel = label; + moved = true; + delete tick.label; + } + else { // Find a label with the same string + objectEach(xAxis.ticks, function (currentTick) { + if (!moved && + !currentTick.isNew && + currentTick !== tick && + currentTick.label && + currentTick.label.textStr === str) { + tick.movedLabel = currentTick.label; + moved = true; + currentTick.labelPos = tick.movedLabel.xy; + delete currentTick.label; + } + }); + } + // Create new label if the actual one is moved + if (!moved && (tick.labelPos || label)) { + labelPos = tick.labelPos || label.xy; + xPos = inverted ? + labelPos.x : (reversed ? 0 : xAxis.width + xAxis.left); + yPos = inverted ? + (reversed ? (xAxis.width + xAxis.left) : 0) : labelPos.y; + tick.movedLabel = tick.createLabel({ x: xPos, y: yPos }, str, labelOptions); + if (tick.movedLabel) { + tick.movedLabel.attr({ opacity: 0 }); + } + } + }; + /** + * Put everything in place + * + * @private + * @param {number} index + * @param {boolean} [old] + * Use old coordinates to prepare an animation into new position + * @param {number} [opacity] + * @return {voids} + */ + Tick.prototype.render = function (index, old, opacity) { + var tick = this, axis = tick.axis, horiz = axis.horiz, pos = tick.pos, tickmarkOffset = pick(tick.tickmarkOffset, axis.tickmarkOffset), xy = tick.getPosition(horiz, pos, tickmarkOffset, old), x = xy.x, y = xy.y, reverseCrisp = ((horiz && x === axis.pos + axis.len) || + (!horiz && y === axis.pos)) ? -1 : 1; // #1480, #1687 + opacity = pick(opacity, 1); + this.isActive = true; + // Create the grid line + this.renderGridLine(old, opacity, reverseCrisp); + // create the tick mark + this.renderMark(xy, opacity, reverseCrisp); + // the label is created on init - now move it into place + this.renderLabel(xy, old, opacity, index); + tick.isNew = false; + fireEvent(this, 'afterRender'); + }; + /** + * Renders the gridLine. + * + * @private + * @param {boolean} old Whether or not the tick is old + * @param {number} opacity The opacity of the grid line + * @param {number} reverseCrisp Modifier for avoiding overlapping 1 or -1 + * @return {void} + */ + Tick.prototype.renderGridLine = function (old, opacity, reverseCrisp) { + var tick = this, axis = tick.axis, options = axis.options, gridLine = tick.gridLine, gridLinePath, attribs = {}, pos = tick.pos, type = tick.type, tickmarkOffset = pick(tick.tickmarkOffset, axis.tickmarkOffset), renderer = axis.chart.renderer, gridPrefix = type ? type + 'Grid' : 'grid', gridLineWidth = options[gridPrefix + 'LineWidth'], gridLineColor = options[gridPrefix + 'LineColor'], dashStyle = options[gridPrefix + 'LineDashStyle']; + if (!gridLine) { + if (!axis.chart.styledMode) { + attribs.stroke = gridLineColor; + attribs['stroke-width'] = gridLineWidth; + if (dashStyle) { + attribs.dashstyle = dashStyle; + } + } + if (!type) { + attribs.zIndex = 1; + } + if (old) { + opacity = 0; + } + /** + * The rendered grid line of the tick. + * @name Highcharts.Tick#gridLine + * @type {Highcharts.SVGElement|undefined} + */ + tick.gridLine = gridLine = renderer.path() + .attr(attribs) + .addClass('highcharts-' + (type ? type + '-' : '') + 'grid-line') + .add(axis.gridGroup); + } + if (gridLine) { + gridLinePath = axis.getPlotLinePath({ + value: pos + tickmarkOffset, + lineWidth: gridLine.strokeWidth() * reverseCrisp, + force: 'pass', + old: old + }); + // If the parameter 'old' is set, the current call will be followed + // by another call, therefore do not do any animations this time + if (gridLinePath) { + gridLine[old || tick.isNew ? 'attr' : 'animate']({ + d: gridLinePath, + opacity: opacity + }); + } + } + }; + /** + * Renders the tick mark. + * + * @private + * @param {Highcharts.PositionObject} xy The position vector of the mark + * @param {number} opacity The opacity of the mark + * @param {number} reverseCrisp Modifier for avoiding overlapping 1 or -1 + * @return {void} + */ + Tick.prototype.renderMark = function (xy, opacity, reverseCrisp) { + var tick = this, axis = tick.axis, options = axis.options, renderer = axis.chart.renderer, type = tick.type, tickPrefix = type ? type + 'Tick' : 'tick', tickSize = axis.tickSize(tickPrefix), mark = tick.mark, isNewMark = !mark, x = xy.x, y = xy.y, tickWidth = pick(options[tickPrefix + 'Width'], !type && axis.isXAxis ? 1 : 0), // X axis defaults to 1 + tickColor = options[tickPrefix + 'Color']; + if (tickSize) { + // negate the length + if (axis.opposite) { + tickSize[0] = -tickSize[0]; + } + // First time, create it + if (isNewMark) { + /** + * The rendered mark of the tick. + * @name Highcharts.Tick#mark + * @type {Highcharts.SVGElement|undefined} + */ + tick.mark = mark = renderer.path() + .addClass('highcharts-' + (type ? type + '-' : '') + 'tick') + .add(axis.axisGroup); + if (!axis.chart.styledMode) { + mark.attr({ + stroke: tickColor, + 'stroke-width': tickWidth + }); + } + } + mark[isNewMark ? 'attr' : 'animate']({ + d: tick.getMarkPath(x, y, tickSize[0], mark.strokeWidth() * reverseCrisp, axis.horiz, renderer), + opacity: opacity + }); + } + }; + /** + * Renders the tick label. + * Note: The label should already be created in init(), so it should only + * have to be moved into place. + * + * @private + * @param {Highcharts.PositionObject} xy The position vector of the label + * @param {boolean} old Whether or not the tick is old + * @param {number} opacity The opacity of the label + * @param {number} index The index of the tick + * @return {void} + */ + Tick.prototype.renderLabel = function (xy, old, opacity, index) { + var tick = this, axis = tick.axis, horiz = axis.horiz, options = axis.options, label = tick.label, labelOptions = options.labels, step = labelOptions.step, tickmarkOffset = pick(tick.tickmarkOffset, axis.tickmarkOffset), show = true, x = xy.x, y = xy.y; + if (label && isNumber(x)) { + label.xy = xy = tick.getLabelPosition(x, y, label, horiz, labelOptions, tickmarkOffset, index, step); + // Apply show first and show last. If the tick is both first and + // last, it is a single centered tick, in which case we show the + // label anyway (#2100). + if ((tick.isFirst && + !tick.isLast && + !pick(options.showFirstLabel, 1)) || + (tick.isLast && + !tick.isFirst && + !pick(options.showLastLabel, 1))) { + show = false; + // Handle label overflow and show or hide accordingly + } + else if (horiz && + !labelOptions.step && + !labelOptions.rotation && + !old && + opacity !== 0) { + tick.handleOverflow(xy); + } + // apply step + if (step && index % step) { + // show those indices dividable by step + show = false; + } + // Set the new position, and show or hide + if (show && isNumber(xy.y)) { + xy.opacity = opacity; + label[tick.isNewLabel ? 'attr' : 'animate'](xy); + tick.isNewLabel = false; + } + else { + label.attr('y', -9999); // #1338 + tick.isNewLabel = true; + } + } + }; + /** + * Replace labels with the moved ones to perform animation. Additionally + * destroy unused labels. + * + * @private + * @function Highcharts.Tick#replaceMovedLabel + * @return {void} + */ + Tick.prototype.replaceMovedLabel = function () { + var tick = this, label = tick.label, axis = tick.axis, reversed = axis.reversed, chart = tick.axis.chart, inverted = chart.inverted, x, y; + // Animate and destroy + if (label && !tick.isNew) { + x = inverted ? label.xy.x : (reversed ? axis.left : axis.width + axis.left); + y = inverted ? + (reversed ? axis.width + axis.top : axis.top) : + label.xy.y; + label.animate({ x: x, y: y, opacity: 0 }, void 0, label.destroy); + delete tick.label; + } + axis.isDirty = true; + tick.label = tick.movedLabel; + delete tick.movedLabel; + }; + return Tick; + }()); + H.Tick = Tick; + + return H.Tick; + }); + _registerModule(_modules, 'parts/Time.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (Highcharts, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Normalized interval. + * + * @interface Highcharts.TimeNormalizedObject + */ /** + * The count. + * + * @name Highcharts.TimeNormalizedObject#count + * @type {number} + */ /** + * The interval in axis values (ms). + * + * @name Highcharts.TimeNormalizedObject#unitRange + * @type {number} + */ + /** + * Function of an additional date format specifier. + * + * @callback Highcharts.TimeFormatCallbackFunction + * + * @param {number} timestamp + * The time to format. + * + * @return {string} + * The formatted portion of the date. + */ + /** + * Additonal time tick information. + * + * @interface Highcharts.TimeTicksInfoObject + * @extends Highcharts.TimeNormalizedObject + */ /** + * @name Highcharts.TimeTicksInfoObject#higherRanks + * @type {Array} + */ /** + * @name Highcharts.TimeTicksInfoObject#totalRange + * @type {number} + */ + /** + * Time ticks. + * + * @interface Highcharts.AxisTickPositionsArray + * @extends global.Array + */ /** + * @name Highcharts.AxisTickPositionsArray#info + * @type {Highcharts.TimeTicksInfoObject|undefined} + */ + /** + * A callback to return the time zone offset for a given datetime. It + * takes the timestamp in terms of milliseconds since January 1 1970, + * and returns the timezone offset in minutes. This provides a hook + * for drawing time based charts in specific time zones using their + * local DST crossover dates, with the help of external libraries. + * + * @callback Highcharts.TimezoneOffsetCallbackFunction + * + * @param {number} timestamp + * Timestamp in terms of milliseconds since January 1 1970. + * + * @return {number} + * Timezone offset in minutes. + */ + var defined = U.defined, error = U.error, extend = U.extend, isObject = U.isObject, merge = U.merge, objectEach = U.objectEach, pad = U.pad, pick = U.pick, splat = U.splat, timeUnits = U.timeUnits; + var H = Highcharts, win = H.win; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The Time class. Time settings are applied in general for each page using + * `Highcharts.setOptions`, or individually for each Chart item through the + * [time](https://api.highcharts.com/highcharts/time) options set. + * + * The Time object is available from {@link Highcharts.Chart#time}, + * which refers to `Highcharts.time` if no individual time settings are + * applied. + * + * @example + * // Apply time settings globally + * Highcharts.setOptions({ + * time: { + * timezone: 'Europe/London' + * } + * }); + * + * // Apply time settings by instance + * var chart = Highcharts.chart('container', { + * time: { + * timezone: 'America/New_York' + * }, + * series: [{ + * data: [1, 4, 3, 5] + * }] + * }); + * + * // Use the Time object + * console.log( + * 'Current time in New York', + * chart.time.dateFormat('%Y-%m-%d %H:%M:%S', Date.now()) + * ); + * + * @since 6.0.5 + * + * @class + * @name Highcharts.Time + * + * @param {Highcharts.TimeOptions} options + * Time options as defined in [chart.options.time](/highcharts/time). + */ + var Time = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Time(options) { + /* * + * + * Properties + * + * */ + this.options = {}; + this.useUTC = false; + this.variableTimezone = false; + this.Date = win.Date; + /** + * Get the time zone offset based on the current timezone information as + * set in the global options. + * + * @function Highcharts.Time#getTimezoneOffset + * + * @param {number} timestamp + * The JavaScript timestamp to inspect. + * + * @return {number} + * The timezone offset in minutes compared to UTC. + */ + this.getTimezoneOffset = this.timezoneOffsetFunction(); + this.update(options); + } + /* * + * + * Functions + * + * */ + /** + * Time units used in `Time.get` and `Time.set` + * + * @typedef {"Date"|"Day"|"FullYear"|"Hours"|"Milliseconds"|"Minutes"|"Month"|"Seconds"} Highcharts.TimeUnitValue + */ + /** + * Get the value of a date object in given units, and subject to the Time + * object's current timezone settings. This function corresponds directly to + * JavaScripts `Date.getXXX / Date.getUTCXXX`, so instead of calling + * `date.getHours()` or `date.getUTCHours()` we will call + * `time.get('Hours')`. + * + * @function Highcharts.Time#get + * + * @param {Highcharts.TimeUnitValue} unit + * @param {Date} date + * + * @return {number} + * The given time unit + */ + Time.prototype.get = function (unit, date) { + if (this.variableTimezone || this.timezoneOffset) { + var realMs = date.getTime(); + var ms = realMs - this.getTimezoneOffset(date); + date.setTime(ms); // Temporary adjust to timezone + var ret = date['getUTC' + unit](); + date.setTime(realMs); // Reset + return ret; + } + // UTC time with no timezone handling + if (this.useUTC) { + return date['getUTC' + unit](); + } + // Else, local time + return date['get' + unit](); + }; + /** + * Set the value of a date object in given units, and subject to the Time + * object's current timezone settings. This function corresponds directly to + * JavaScripts `Date.setXXX / Date.setUTCXXX`, so instead of calling + * `date.setHours(0)` or `date.setUTCHours(0)` we will call + * `time.set('Hours', 0)`. + * + * @function Highcharts.Time#set + * + * @param {Highcharts.TimeUnitValue} unit + * @param {Date} date + * @param {number} value + * + * @return {number} + * The epoch milliseconds of the updated date + */ + Time.prototype.set = function (unit, date, value) { + // UTC time with timezone handling + if (this.variableTimezone || this.timezoneOffset) { + // For lower order time units, just set it directly using UTC + // time + if (unit === 'Milliseconds' || + unit === 'Seconds' || + unit === 'Minutes') { + return date['setUTC' + unit](value); + } + // Higher order time units need to take the time zone into + // account + // Adjust by timezone + var offset = this.getTimezoneOffset(date); + var ms = date.getTime() - offset; + date.setTime(ms); + date['setUTC' + unit](value); + var newOffset = this.getTimezoneOffset(date); + ms = date.getTime() + newOffset; + return date.setTime(ms); + } + // UTC time with no timezone handling + if (this.useUTC) { + return date['setUTC' + unit](value); + } + // Else, local time + return date['set' + unit](value); + }; + /** + * Update the Time object with current options. It is called internally on + * initializing Highcharts, after running `Highcharts.setOptions` and on + * `Chart.update`. + * + * @private + * @function Highcharts.Time#update + * + * @param {Highcharts.TimeOptions} options + * + * @return {void} + */ + Time.prototype.update = function (options) { + var useUTC = pick(options && options.useUTC, true), time = this; + this.options = options = merge(true, this.options || {}, options); + // Allow using a different Date class + this.Date = options.Date || win.Date || Date; + this.useUTC = useUTC; + this.timezoneOffset = (useUTC && options.timezoneOffset); + this.getTimezoneOffset = this.timezoneOffsetFunction(); + /* + * The time object has options allowing for variable time zones, meaning + * the axis ticks or series data needs to consider this. + */ + this.variableTimezone = !!(!useUTC || + options.getTimezoneOffset || + options.timezone); + }; + /** + * Make a time and returns milliseconds. Interprets the inputs as UTC time, + * local time or a specific timezone time depending on the current time + * settings. + * + * @function Highcharts.Time#makeTime + * + * @param {number} year + * The year + * + * @param {number} month + * The month. Zero-based, so January is 0. + * + * @param {number} [date=1] + * The day of the month + * + * @param {number} [hours=0] + * The hour of the day, 0-23. + * + * @param {number} [minutes=0] + * The minutes + * + * @param {number} [seconds=0] + * The seconds + * + * @return {number} + * The time in milliseconds since January 1st 1970. + */ + Time.prototype.makeTime = function (year, month, date, hours, minutes, seconds) { + var d, offset, newOffset; + if (this.useUTC) { + d = this.Date.UTC.apply(0, arguments); + offset = this.getTimezoneOffset(d); + d += offset; + newOffset = this.getTimezoneOffset(d); + if (offset !== newOffset) { + d += newOffset - offset; + // A special case for transitioning from summer time to winter time. + // When the clock is set back, the same time is repeated twice, i.e. + // 02:30 am is repeated since the clock is set back from 3 am to + // 2 am. We need to make the same time as local Date does. + } + else if (offset - 36e5 === this.getTimezoneOffset(d - 36e5) && + !H.isSafari) { + d -= 36e5; + } + } + else { + d = new this.Date(year, month, pick(date, 1), pick(hours, 0), pick(minutes, 0), pick(seconds, 0)).getTime(); + } + return d; + }; + /** + * Sets the getTimezoneOffset function. If the `timezone` option is set, a + * default getTimezoneOffset function with that timezone is returned. If + * a `getTimezoneOffset` option is defined, it is returned. If neither are + * specified, the function using the `timezoneOffset` option or 0 offset is + * returned. + * + * @private + * @function Highcharts.Time#timezoneOffsetFunction + * + * @return {Function} + * A getTimezoneOffset function + */ + Time.prototype.timezoneOffsetFunction = function () { + var time = this, options = this.options, moment = win.moment; + if (!this.useUTC) { + return function (timestamp) { + return new Date(timestamp.toString()).getTimezoneOffset() * 60000; + }; + } + if (options.timezone) { + if (!moment) { + // getTimezoneOffset-function stays undefined because it depends + // on Moment.js + error(25); + } + else { + return function (timestamp) { + return -moment.tz(timestamp, options.timezone).utcOffset() * 60000; + }; + } + } + // If not timezone is set, look for the getTimezoneOffset callback + if (this.useUTC && options.getTimezoneOffset) { + return function (timestamp) { + return options.getTimezoneOffset(timestamp.valueOf()) * 60000; + }; + } + // Last, use the `timezoneOffset` option if set + return function () { + return (time.timezoneOffset || 0) * 60000; + }; + }; + /** + * Formats a JavaScript date timestamp (milliseconds since Jan 1st 1970) + * into a human readable date string. The available format keys are listed + * below. Additional formats can be given in the + * {@link Highcharts.dateFormats} hook. + * + * Supported format keys: + * - `%a`: Short weekday, like 'Mon' + * - `%A`: Long weekday, like 'Monday' + * - `%d`: Two digit day of the month, 01 to 31 + * - `%e`: Day of the month, 1 through 31 + * - `%w`: Day of the week, 0 through 6 + * - `%b`: Short month, like 'Jan' + * - `%B`: Long month, like 'January' + * - `%m`: Two digit month number, 01 through 12 + * - `%y`: Two digits year, like 09 for 2009 + * - `%Y`: Four digits year, like 2009 + * - `%H`: Two digits hours in 24h format, 00 through 23 + * - `%k`: Hours in 24h format, 0 through 23 + * - `%I`: Two digits hours in 12h format, 00 through 11 + * - `%l`: Hours in 12h format, 1 through 12 + * - `%M`: Two digits minutes, 00 through 59 + * - `%p`: Upper case AM or PM + * - `%P`: Lower case AM or PM + * - `%S`: Two digits seconds, 00 through 59 + * - `%L`: Milliseconds (naming from Ruby) + * + * @example + * const time = new Highcharts.Time(); + * const s = time.dateFormat('%Y-%m-%d %H:%M:%S', Date.UTC(2020, 0, 1)); + * console.log(s); // => 2020-01-01 00:00:00 + * + * @function Highcharts.Time#dateFormat + * + * @param {string} format + * The desired format where various time representations are + * prefixed with %. + * + * @param {number} timestamp + * The JavaScript timestamp. + * + * @param {boolean} [capitalize=false] + * Upper case first letter in the return. + * + * @return {string} + * The formatted date. + */ + Time.prototype.dateFormat = function (format, timestamp, capitalize) { + var _a; + if (!defined(timestamp) || isNaN(timestamp)) { + return ((_a = H.defaultOptions.lang) === null || _a === void 0 ? void 0 : _a.invalidDate) || ''; + } + format = pick(format, '%Y-%m-%d %H:%M:%S'); + var time = this, date = new this.Date(timestamp), + // get the basic time values + hours = this.get('Hours', date), day = this.get('Day', date), dayOfMonth = this.get('Date', date), month = this.get('Month', date), fullYear = this.get('FullYear', date), lang = H.defaultOptions.lang, langWeekdays = lang === null || lang === void 0 ? void 0 : lang.weekdays, shortWeekdays = lang === null || lang === void 0 ? void 0 : lang.shortWeekdays, + // List all format keys. Custom formats can be added from the + // outside. + replacements = extend({ + // Day + // Short weekday, like 'Mon' + a: shortWeekdays ? + shortWeekdays[day] : + langWeekdays[day].substr(0, 3), + // Long weekday, like 'Monday' + A: langWeekdays[day], + // Two digit day of the month, 01 to 31 + d: pad(dayOfMonth), + // Day of the month, 1 through 31 + e: pad(dayOfMonth, 2, ' '), + // Day of the week, 0 through 6 + w: day, + // Week (none implemented) + // 'W': weekNumber(), + // Month + // Short month, like 'Jan' + b: lang.shortMonths[month], + // Long month, like 'January' + B: lang.months[month], + // Two digit month number, 01 through 12 + m: pad(month + 1), + // Month number, 1 through 12 (#8150) + o: month + 1, + // Year + // Two digits year, like 09 for 2009 + y: fullYear.toString().substr(2, 2), + // Four digits year, like 2009 + Y: fullYear, + // Time + // Two digits hours in 24h format, 00 through 23 + H: pad(hours), + // Hours in 24h format, 0 through 23 + k: hours, + // Two digits hours in 12h format, 00 through 11 + I: pad((hours % 12) || 12), + // Hours in 12h format, 1 through 12 + l: (hours % 12) || 12, + // Two digits minutes, 00 through 59 + M: pad(this.get('Minutes', date)), + // Upper case AM or PM + p: hours < 12 ? 'AM' : 'PM', + // Lower case AM or PM + P: hours < 12 ? 'am' : 'pm', + // Two digits seconds, 00 through 59 + S: pad(date.getSeconds()), + // Milliseconds (naming from Ruby) + L: pad(Math.floor(timestamp % 1000), 3) + }, H.dateFormats); + // Do the replaces + objectEach(replacements, function (val, key) { + // Regex would do it in one line, but this is faster + while (format.indexOf('%' + key) !== -1) { + format = format.replace('%' + key, typeof val === 'function' ? val.call(time, timestamp) : val); + } + }); + // Optionally capitalize the string and return + return capitalize ? + (format.substr(0, 1).toUpperCase() + + format.substr(1)) : + format; + }; + /** + * Resolve legacy formats of dateTimeLabelFormats (strings and arrays) into + * an object. + * @private + * @param {string|Array|Highcharts.Dictionary} f - General format description + * @return {Highcharts.Dictionary} - The object definition + */ + Time.prototype.resolveDTLFormat = function (f) { + if (!isObject(f, true)) { // check for string or array + f = splat(f); + return { + main: f[0], + from: f[1], + to: f[2] + }; + } + return f; + }; + /** + * Return an array with time positions distributed on round time values + * right and right after min and max. Used in datetime axes as well as for + * grouping data on a datetime axis. + * + * @function Highcharts.Time#getTimeTicks + * + * @param {Highcharts.TimeNormalizedObject} normalizedInterval + * The interval in axis values (ms) and the count + * + * @param {number} [min] + * The minimum in axis values + * + * @param {number} [max] + * The maximum in axis values + * + * @param {number} [startOfWeek=1] + * + * @return {Highcharts.AxisTickPositionsArray} + */ + Time.prototype.getTimeTicks = function (normalizedInterval, min, max, startOfWeek) { + var time = this, Date = time.Date, tickPositions = [], i, higherRanks = {}, minYear, // used in months and years as a basis for Date.UTC() + // When crossing DST, use the max. Resolves #6278. + minDate = new Date(min), interval = normalizedInterval.unitRange, count = normalizedInterval.count || 1, variableDayLength, minDay; + startOfWeek = pick(startOfWeek, 1); + if (defined(min)) { // #1300 + time.set('Milliseconds', minDate, interval >= timeUnits.second ? + 0 : // #3935 + count * Math.floor(time.get('Milliseconds', minDate) / count)); // #3652, #3654 + if (interval >= timeUnits.second) { // second + time.set('Seconds', minDate, interval >= timeUnits.minute ? + 0 : // #3935 + count * Math.floor(time.get('Seconds', minDate) / count)); + } + if (interval >= timeUnits.minute) { // minute + time.set('Minutes', minDate, interval >= timeUnits.hour ? + 0 : + count * Math.floor(time.get('Minutes', minDate) / count)); + } + if (interval >= timeUnits.hour) { // hour + time.set('Hours', minDate, interval >= timeUnits.day ? + 0 : + count * Math.floor(time.get('Hours', minDate) / count)); + } + if (interval >= timeUnits.day) { // day + time.set('Date', minDate, interval >= timeUnits.month ? + 1 : + Math.max(1, count * Math.floor(time.get('Date', minDate) / count))); + } + if (interval >= timeUnits.month) { // month + time.set('Month', minDate, interval >= timeUnits.year ? 0 : + count * Math.floor(time.get('Month', minDate) / count)); + minYear = time.get('FullYear', minDate); + } + if (interval >= timeUnits.year) { // year + minYear -= minYear % count; + time.set('FullYear', minDate, minYear); + } + // week is a special case that runs outside the hierarchy + if (interval === timeUnits.week) { + // get start of current week, independent of count + minDay = time.get('Day', minDate); + time.set('Date', minDate, (time.get('Date', minDate) - + minDay + startOfWeek + + // We don't want to skip days that are before + // startOfWeek (#7051) + (minDay < startOfWeek ? -7 : 0))); + } + // Get basics for variable time spans + minYear = time.get('FullYear', minDate); + var minMonth = time.get('Month', minDate), minDateDate = time.get('Date', minDate), minHours = time.get('Hours', minDate); + // Redefine min to the floored/rounded minimum time (#7432) + min = minDate.getTime(); + // Handle local timezone offset + if (time.variableTimezone) { + // Detect whether we need to take the DST crossover into + // consideration. If we're crossing over DST, the day length may + // be 23h or 25h and we need to compute the exact clock time for + // each tick instead of just adding hours. This comes at a cost, + // so first we find out if it is needed (#4951). + variableDayLength = ( + // Long range, assume we're crossing over. + max - min > 4 * timeUnits.month || + // Short range, check if min and max are in different time + // zones. + time.getTimezoneOffset(min) !== + time.getTimezoneOffset(max)); + } + // Iterate and add tick positions at appropriate values + var t = minDate.getTime(); + i = 1; + while (t < max) { + tickPositions.push(t); + // if the interval is years, use Date.UTC to increase years + if (interval === timeUnits.year) { + t = time.makeTime(minYear + i * count, 0); + // if the interval is months, use Date.UTC to increase months + } + else if (interval === timeUnits.month) { + t = time.makeTime(minYear, minMonth + i * count); + // if we're using global time, the interval is not fixed as it + // jumps one hour at the DST crossover + } + else if (variableDayLength && + (interval === timeUnits.day || interval === timeUnits.week)) { + t = time.makeTime(minYear, minMonth, minDateDate + + i * count * (interval === timeUnits.day ? 1 : 7)); + } + else if (variableDayLength && + interval === timeUnits.hour && + count > 1) { + // make sure higher ranks are preserved across DST (#6797, + // #7621) + t = time.makeTime(minYear, minMonth, minDateDate, minHours + i * count); + // else, the interval is fixed and we use simple addition + } + else { + t += interval * count; + } + i++; + } + // push the last time + tickPositions.push(t); + // Handle higher ranks. Mark new days if the time is on midnight + // (#950, #1649, #1760, #3349). Use a reasonable dropout threshold + // to prevent looping over dense data grouping (#6156). + if (interval <= timeUnits.hour && tickPositions.length < 10000) { + tickPositions.forEach(function (t) { + if ( + // Speed optimization, no need to run dateFormat unless + // we're on a full or half hour + t % 1800000 === 0 && + // Check for local or global midnight + time.dateFormat('%H%M%S%L', t) === '000000000') { + higherRanks[t] = 'day'; + } + }); + } + } + // record information on the chosen unit - for dynamic label formatter + tickPositions.info = extend(normalizedInterval, { + higherRanks: higherRanks, + totalRange: interval * count + }); + return tickPositions; + }; + /* * + * + * Static Properties + * + * */ + /** + * Time options that can apply globally or to individual charts. These + * settings affect how `datetime` axes are laid out, how tooltips are + * formatted, how series + * [pointIntervalUnit](#plotOptions.series.pointIntervalUnit) works and how + * the Highstock range selector handles time. + * + * The common use case is that all charts in the same Highcharts object + * share the same time settings, in which case the global settings are set + * using `setOptions`. + * + * ```js + * // Apply time settings globally + * Highcharts.setOptions({ + * time: { + * timezone: 'Europe/London' + * } + * }); + * // Apply time settings by instance + * var chart = Highcharts.chart('container', { + * time: { + * timezone: 'America/New_York' + * }, + * series: [{ + * data: [1, 4, 3, 5] + * }] + * }); + * + * // Use the Time object + * console.log( + * 'Current time in New York', + * chart.time.dateFormat('%Y-%m-%d %H:%M:%S', Date.now()) + * ); + * ``` + * + * Since v6.0.5, the time options were moved from the `global` obect to the + * `time` object, and time options can be set on each individual chart. + * + * @sample {highcharts|highstock} + * highcharts/time/timezone/ + * Set the timezone globally + * @sample {highcharts} + * highcharts/time/individual/ + * Set the timezone per chart instance + * @sample {highstock} + * stock/time/individual/ + * Set the timezone per chart instance + * + * @since 6.0.5 + * @optionparent time + */ + Time.defaultOptions = { + /** + * A custom `Date` class for advanced date handling. For example, + * [JDate](https://github.com/tahajahangir/jdate) can be hooked in to + * handle Jalali dates. + * + * @type {*} + * @since 4.0.4 + * @product highcharts highstock gantt + */ + Date: void 0, + /** + * A callback to return the time zone offset for a given datetime. It + * takes the timestamp in terms of milliseconds since January 1 1970, + * and returns the timezone offset in minutes. This provides a hook + * for drawing time based charts in specific time zones using their + * local DST crossover dates, with the help of external libraries. + * + * @see [global.timezoneOffset](#global.timezoneOffset) + * + * @sample {highcharts|highstock} highcharts/time/gettimezoneoffset/ + * Use moment.js to draw Oslo time regardless of browser locale + * + * @type {Highcharts.TimezoneOffsetCallbackFunction} + * @since 4.1.0 + * @product highcharts highstock gantt + */ + getTimezoneOffset: void 0, + /** + * Requires [moment.js](https://momentjs.com/). If the timezone option + * is specified, it creates a default + * [getTimezoneOffset](#time.getTimezoneOffset) function that looks + * up the specified timezone in moment.js. If moment.js is not included, + * this throws a Highcharts error in the console, but does not crash the + * chart. + * + * @see [getTimezoneOffset](#time.getTimezoneOffset) + * + * @sample {highcharts|highstock} highcharts/time/timezone/ + * Europe/Oslo + * + * @type {string} + * @since 5.0.7 + * @product highcharts highstock gantt + */ + timezone: void 0, + /** + * The timezone offset in minutes. Positive values are west, negative + * values are east of UTC, as in the ECMAScript + * [getTimezoneOffset](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset) + * method. Use this to display UTC based data in a predefined time zone. + * + * @see [time.getTimezoneOffset](#time.getTimezoneOffset) + * + * @sample {highcharts|highstock} highcharts/time/timezoneoffset/ + * Timezone offset + * + * @since 3.0.8 + * @product highcharts highstock gantt + */ + timezoneOffset: 0, + /** + * Whether to use UTC time for axis scaling, tickmark placement and + * time display in `Highcharts.dateFormat`. Advantages of using UTC + * is that the time displays equally regardless of the user agent's + * time zone settings. Local time can be used when the data is loaded + * in real time or when correct Daylight Saving Time transitions are + * required. + * + * @sample {highcharts} highcharts/time/useutc-true/ + * True by default + * @sample {highcharts} highcharts/time/useutc-false/ + * False + */ + useUTC: true + }; + return Time; + }()); + H.Time = Time; + + return H.Time; + }); + _registerModule(_modules, 'parts/Options.js', [_modules['parts/Globals.js'], _modules['parts/Time.js'], _modules['parts/Color.js'], _modules['parts/Utilities.js']], function (H, Time, Color, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * @typedef {"plotBox"|"spacingBox"} Highcharts.ButtonRelativeToValue + */ + /** + * Gets fired when a series is added to the chart after load time, using the + * `addSeries` method. Returning `false` prevents the series from being added. + * + * @callback Highcharts.ChartAddSeriesCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart on which the event occured. + * + * @param {Highcharts.ChartAddSeriesEventObject} event + * The event that occured. + * + * @return {void} + */ + /** + * Contains common event information. Through the `options` property you can + * access the series options that were passed to the `addSeries` method. + * + * @interface Highcharts.ChartAddSeriesEventObject + */ /** + * The series options that were passed to the `addSeries` method. + * @name Highcharts.ChartAddSeriesEventObject#options + * @type {Highcharts.SeriesOptionsType} + */ /** + * Prevents the default behaviour of the event. + * @name Highcharts.ChartAddSeriesEventObject#preventDefault + * @type {Function} + */ /** + * The event target. + * @name Highcharts.ChartAddSeriesEventObject#target + * @type {Highcharts.Chart} + */ /** + * The event type. + * @name Highcharts.ChartAddSeriesEventObject#type + * @type {"addSeries"} + */ + /** + * Gets fired when clicking on the plot background. + * + * @callback Highcharts.ChartClickCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart on which the event occured. + * + * @param {Highcharts.PointerEventObject} event + * The event that occured. + * + * @return {void} + */ + /** + * Contains an axes of the clicked spot. + * + * @interface Highcharts.ChartClickEventAxisObject + */ /** + * Axis at the clicked spot. + * @name Highcharts.ChartClickEventAxisObject#axis + * @type {Highcharts.Axis} + */ /** + * Axis value at the clicked spot. + * @name Highcharts.ChartClickEventAxisObject#value + * @type {number} + */ + /** + * Contains information about the clicked spot on the chart. Remember the unit + * of a datetime axis is milliseconds since 1970-01-01 00:00:00. + * + * @interface Highcharts.ChartClickEventObject + * @extends Highcharts.PointerEventObject + */ /** + * Information about the x-axis on the clicked spot. + * @name Highcharts.ChartClickEventObject#xAxis + * @type {Array} + */ /** + * Information about the y-axis on the clicked spot. + * @name Highcharts.ChartClickEventObject#yAxis + * @type {Array} + */ /** + * Information about the z-axis on the clicked spot. + * @name Highcharts.ChartClickEventObject#zAxis + * @type {Array|undefined} + */ + /** + * Gets fired when the chart is finished loading. + * + * @callback Highcharts.ChartLoadCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart on which the event occured. + * + * @param {global.Event} event + * The event that occured. + * + * @return {void} + */ + /** + * Fires when the chart is redrawn, either after a call to `chart.redraw()` or + * after an axis, series or point is modified with the `redraw` option set to + * `true`. + * + * @callback Highcharts.ChartRedrawCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart on which the event occured. + * + * @param {global.Event} event + * The event that occured. + * + * @return {void} + */ + /** + * Gets fired after initial load of the chart (directly after the `load` event), + * and after each redraw (directly after the `redraw` event). + * + * @callback Highcharts.ChartRenderCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart on which the event occured. + * + * @param {global.Event} event + * The event that occured. + * + * @return {void} + */ + /** + * Gets fired when an area of the chart has been selected. The default action + * for the selection event is to zoom the chart to the selected area. It can be + * prevented by calling `event.preventDefault()` or return false. + * + * @callback Highcharts.ChartSelectionCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart on which the event occured. + * + * @param {global.ChartSelectionContextObject} event + * Event informations + * + * @return {boolean|undefined} + * Return false to prevent the default action, usually zoom. + */ + /** + * The primary axes are `xAxis[0]` and `yAxis[0]`. Remember the unit of a + * datetime axis is milliseconds since 1970-01-01 00:00:00. + * + * @interface Highcharts.ChartSelectionContextObject + * @extends global.Event + */ /** + * Arrays containing the axes of each dimension and each axis' min and max + * values. + * @name Highcharts.ChartSelectionContextObject#xAxis + * @type {Array} + */ /** + * Arrays containing the axes of each dimension and each axis' min and max + * values. + * @name Highcharts.ChartSelectionContextObject#yAxis + * @type {Array} + */ + /** + * Axis context of the selection. + * + * @interface Highcharts.ChartSelectionAxisContextObject + */ /** + * The selected Axis. + * @name Highcharts.ChartSelectionAxisContextObject#axis + * @type {Highcharts.Axis} + */ /** + * The maximum axis value, either automatic or set manually. + * @name Highcharts.ChartSelectionAxisContextObject#max + * @type {number} + */ /** + * The minimum axis value, either automatic or set manually. + * @name Highcharts.ChartSelectionAxisContextObject#min + * @type {number} + */ + var color = Color.parse; + var merge = U.merge; + var isTouchDevice = H.isTouchDevice, svg = H.svg; + /* ************************************************************************** * + * Handle the options * + * ************************************************************************** */ + /** + * Global default settings. + * + * @name Highcharts.defaultOptions + * @type {Highcharts.Options} + */ /** + * @optionparent + */ + H.defaultOptions = { + /** + * An array containing the default colors for the chart's series. When + * all colors are used, new colors are pulled from the start again. + * + * Default colors can also be set on a series or series.type basis, + * see [column.colors](#plotOptions.column.colors), + * [pie.colors](#plotOptions.pie.colors). + * + * In styled mode, the colors option doesn't exist. Instead, colors + * are defined in CSS and applied either through series or point class + * names, or through the [chart.colorCount](#chart.colorCount) option. + * + * + * ### Legacy + * + * In Highcharts 3.x, the default colors were: + * ```js + * colors: ['#2f7ed8', '#0d233a', '#8bbc21', '#910000', '#1aadce', + * '#492970', '#f28f43', '#77a1e5', '#c42525', '#a6c96a'] + * ``` + * + * In Highcharts 2.x, the default colors were: + * ```js + * colors: ['#4572A7', '#AA4643', '#89A54E', '#80699B', '#3D96AE', + * '#DB843D', '#92A8CD', '#A47D7C', '#B5CA92'] + * ``` + * + * @sample {highcharts} highcharts/chart/colors/ + * Assign a global color theme + * + * @type {Array} + * @default ["#7cb5ec", "#434348", "#90ed7d", "#f7a35c", "#8085e9", + * "#f15c80", "#e4d354", "#2b908f", "#f45b5b", "#91e8e1"] + */ + colors: '#7cb5ec #434348 #90ed7d #f7a35c #8085e9 #f15c80 #e4d354 #2b908f #f45b5b #91e8e1'.split(' '), + /** + * Styled mode only. Configuration object for adding SVG definitions for + * reusable elements. See [gradients, shadows and + * patterns](https://www.highcharts.com/docs/chart-design-and-style/gradients-shadows-and-patterns) + * for more information and code examples. + * + * @type {*} + * @since 5.0.0 + * @apioption defs + */ + /** + * @ignore-option + */ + symbols: ['circle', 'diamond', 'square', 'triangle', 'triangle-down'], + /** + * The language object is global and it can't be set on each chart + * initialization. Instead, use `Highcharts.setOptions` to set it before any + * chart is initialized. + * + * ```js + * Highcharts.setOptions({ + * lang: { + * months: [ + * 'Janvier', 'Février', 'Mars', 'Avril', + * 'Mai', 'Juin', 'Juillet', 'Août', + * 'Septembre', 'Octobre', 'Novembre', 'Décembre' + * ], + * weekdays: [ + * 'Dimanche', 'Lundi', 'Mardi', 'Mercredi', + * 'Jeudi', 'Vendredi', 'Samedi' + * ] + * } + * }); + * ``` + */ + lang: { + /** + * The loading text that appears when the chart is set into the loading + * state following a call to `chart.showLoading`. + */ + loading: 'Loading...', + /** + * An array containing the months names. Corresponds to the `%B` format + * in `Highcharts.dateFormat()`. + * + * @type {Array} + * @default ["January", "February", "March", "April", "May", "June", + * "July", "August", "September", "October", "November", + * "December"] + */ + months: [ + 'January', 'February', 'March', 'April', 'May', 'June', 'July', + 'August', 'September', 'October', 'November', 'December' + ], + /** + * An array containing the months names in abbreviated form. Corresponds + * to the `%b` format in `Highcharts.dateFormat()`. + * + * @type {Array} + * @default ["Jan", "Feb", "Mar", "Apr", "May", "Jun", + * "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] + */ + shortMonths: [ + 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', + 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' + ], + /** + * An array containing the weekday names. + * + * @type {Array} + * @default ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", + * "Friday", "Saturday"] + */ + weekdays: [ + 'Sunday', 'Monday', 'Tuesday', 'Wednesday', + 'Thursday', 'Friday', 'Saturday' + ], + /** + * Short week days, starting Sunday. If not specified, Highcharts uses + * the first three letters of the `lang.weekdays` option. + * + * @sample highcharts/lang/shortweekdays/ + * Finnish two-letter abbreviations + * + * @type {Array} + * @since 4.2.4 + * @apioption lang.shortWeekdays + */ + /** + * What to show in a date field for invalid dates. Defaults to an empty + * string. + * + * @type {string} + * @since 4.1.8 + * @product highcharts highstock + * @apioption lang.invalidDate + */ + /** + * The title appearing on hovering the zoom in button. The text itself + * defaults to "+" and can be changed in the button options. + * + * @type {string} + * @default Zoom in + * @product highmaps + * @apioption lang.zoomIn + */ + /** + * The title appearing on hovering the zoom out button. The text itself + * defaults to "-" and can be changed in the button options. + * + * @type {string} + * @default Zoom out + * @product highmaps + * @apioption lang.zoomOut + */ + /** + * The default decimal point used in the `Highcharts.numberFormat` + * method unless otherwise specified in the function arguments. + * + * @since 1.2.2 + */ + decimalPoint: '.', + /** + * [Metric prefixes](https://en.wikipedia.org/wiki/Metric_prefix) used + * to shorten high numbers in axis labels. Replacing any of the + * positions with `null` causes the full number to be written. Setting + * `numericSymbols` to `null` disables shortening altogether. + * + * @sample {highcharts} highcharts/lang/numericsymbols/ + * Replacing the symbols with text + * @sample {highstock} highcharts/lang/numericsymbols/ + * Replacing the symbols with text + * + * @type {Array} + * @default ["k", "M", "G", "T", "P", "E"] + * @since 2.3.0 + */ + numericSymbols: ['k', 'M', 'G', 'T', 'P', 'E'], + /** + * The magnitude of [numericSymbols](#lang.numericSymbol) replacements. + * Use 10000 for Japanese, Korean and various Chinese locales, which + * use symbols for 10^4, 10^8 and 10^12. + * + * @sample highcharts/lang/numericsymbolmagnitude/ + * 10000 magnitude for Japanese + * + * @type {number} + * @default 1000 + * @since 5.0.3 + * @apioption lang.numericSymbolMagnitude + */ + /** + * The text for the label appearing when a chart is zoomed. + * + * @since 1.2.4 + */ + resetZoom: 'Reset zoom', + /** + * The tooltip title for the label appearing when a chart is zoomed. + * + * @since 1.2.4 + */ + resetZoomTitle: 'Reset zoom level 1:1', + /** + * The default thousands separator used in the `Highcharts.numberFormat` + * method unless otherwise specified in the function arguments. Defaults + * to a single space character, which is recommended in + * [ISO 31-0](https://en.wikipedia.org/wiki/ISO_31-0#Numbers) and works + * across Anglo-American and continental European languages. + * + * @default \u0020 + * @since 1.2.2 + */ + thousandsSep: ' ' + }, + /** + * Global options that don't apply to each chart. These options, like + * the `lang` options, must be set using the `Highcharts.setOptions` + * method. + * + * ```js + * Highcharts.setOptions({ + * global: { + * useUTC: false + * } + * }); + * ``` + */ + /** + * _Canvg rendering for Android 2.x is removed as of Highcharts 5.0\. + * Use the [libURL](#exporting.libURL) option to configure exporting._ + * + * The URL to the additional file to lazy load for Android 2.x devices. + * These devices don't support SVG, so we download a helper file that + * contains [canvg](https://github.com/canvg/canvg), its dependency + * rbcolor, and our own CanVG Renderer class. To avoid hotlinking to + * our site, you can install canvas-tools.js on your own server and + * change this option accordingly. + * + * @deprecated + * + * @type {string} + * @default https://code.highcharts.com/{version}/modules/canvas-tools.js + * @product highcharts highmaps + * @apioption global.canvasToolsURL + */ + /** + * This option is deprecated since v6.0.5. Instead, use + * [time.useUTC](#time.useUTC) that supports individual time settings + * per chart. + * + * @deprecated + * + * @type {boolean} + * @apioption global.useUTC + */ + /** + * This option is deprecated since v6.0.5. Instead, use + * [time.Date](#time.Date) that supports individual time settings + * per chart. + * + * @deprecated + * + * @type {Function} + * @product highcharts highstock + * @apioption global.Date + */ + /** + * This option is deprecated since v6.0.5. Instead, use + * [time.getTimezoneOffset](#time.getTimezoneOffset) that supports + * individual time settings per chart. + * + * @deprecated + * + * @type {Function} + * @product highcharts highstock + * @apioption global.getTimezoneOffset + */ + /** + * This option is deprecated since v6.0.5. Instead, use + * [time.timezone](#time.timezone) that supports individual time + * settings per chart. + * + * @deprecated + * + * @type {string} + * @product highcharts highstock + * @apioption global.timezone + */ + /** + * This option is deprecated since v6.0.5. Instead, use + * [time.timezoneOffset](#time.timezoneOffset) that supports individual + * time settings per chart. + * + * @deprecated + * + * @type {number} + * @product highcharts highstock + * @apioption global.timezoneOffset + */ + global: {}, + time: Time.defaultOptions, + /** + * General options for the chart. + */ + chart: { + /** + * Default `mapData` for all series. If set to a string, it functions + * as an index into the `Highcharts.maps` array. Otherwise it is + * interpreted as map data. + * + * @see [mapData](#series.map.mapData) + * + * @sample maps/demo/geojson + * Loading geoJSON data + * @sample maps/chart/topojson + * Loading topoJSON converted to geoJSON + * + * @type {string|Array<*>} + * @since 5.0.0 + * @product highmaps + * @apioption chart.map + */ + /** + * Set lat/lon transformation definitions for the chart. If not defined, + * these are extracted from the map data. + * + * @type {*} + * @since 5.0.0 + * @product highmaps + * @apioption chart.mapTransforms + */ + /** + * When using multiple axis, the ticks of two or more opposite axes + * will automatically be aligned by adding ticks to the axis or axes + * with the least ticks, as if `tickAmount` were specified. + * + * This can be prevented by setting `alignTicks` to false. If the grid + * lines look messy, it's a good idea to hide them for the secondary + * axis by setting `gridLineWidth` to 0. + * + * If `startOnTick` or `endOnTick` in an Axis options are set to false, + * then the `alignTicks ` will be disabled for the Axis. + * + * Disabled for logarithmic axes. + * + * @sample {highcharts} highcharts/chart/alignticks-true/ + * True by default + * @sample {highcharts} highcharts/chart/alignticks-false/ + * False + * @sample {highstock} stock/chart/alignticks-true/ + * True by default + * @sample {highstock} stock/chart/alignticks-false/ + * False + * + * @type {boolean} + * @default true + * @product highcharts highstock gantt + * @apioption chart.alignTicks + */ + /** + * Set the overall animation for all chart updating. Animation can be + * disabled throughout the chart by setting it to false here. It can + * be overridden for each individual API method as a function parameter. + * The only animation not affected by this option is the initial series + * animation, see [plotOptions.series.animation]( + * #plotOptions.series.animation). + * + * The animation can either be set as a boolean or a configuration + * object. If `true`, it will use the 'swing' jQuery easing and a + * duration of 500 ms. If used as a configuration object, the following + * properties are supported: + * + * - **duration**: The duration of the animation in milliseconds. + * + * - **easing**: A string reference to an easing function set on the + * `Math` object. See + * [the easing demo](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-animation-easing/). + * + * When zooming on a series with less than 100 points, the chart redraw + * will be done with animation, but in case of more data points, it is + * necessary to set this option to ensure animation on zoom. + * + * @sample {highcharts} highcharts/chart/animation-none/ + * Updating with no animation + * @sample {highcharts} highcharts/chart/animation-duration/ + * With a longer duration + * @sample {highcharts} highcharts/chart/animation-easing/ + * With a jQuery UI easing + * @sample {highmaps} maps/chart/animation-none/ + * Updating with no animation + * @sample {highmaps} maps/chart/animation-duration/ + * With a longer duration + * + * @type {boolean|Highcharts.AnimationOptionsObject} + * @default undefined + * @apioption chart.animation + */ + /** + * A CSS class name to apply to the charts container `div`, allowing + * unique CSS styling for each chart. + * + * @type {string} + * @apioption chart.className + */ + /** + * Event listeners for the chart. + * + * @apioption chart.events + */ + /** + * Fires when a series is added to the chart after load time, using the + * `addSeries` method. One parameter, `event`, is passed to the + * function, containing common event information. Through + * `event.options` you can access the series options that were passed to + * the `addSeries` method. Returning false prevents the series from + * being added. + * + * @sample {highcharts} highcharts/chart/events-addseries/ + * Alert on add series + * @sample {highstock} stock/chart/events-addseries/ + * Alert on add series + * + * @type {Highcharts.ChartAddSeriesCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Chart + * @apioption chart.events.addSeries + */ + /** + * Fires when clicking on the plot background. One parameter, `event`, + * is passed to the function, containing common event information. + * + * Information on the clicked spot can be found through `event.xAxis` + * and `event.yAxis`, which are arrays containing the axes of each + * dimension and each axis' value at the clicked spot. The primary axes + * are `event.xAxis[0]` and `event.yAxis[0]`. Remember the unit of a + * datetime axis is milliseconds since 1970-01-01 00:00:00. + * + * ```js + * click: function(e) { + * console.log( + * Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', e.xAxis[0].value), + * e.yAxis[0].value + * ) + * } + * ``` + * + * @sample {highcharts} highcharts/chart/events-click/ + * Alert coordinates on click + * @sample {highcharts} highcharts/chart/events-container/ + * Alternatively, attach event to container + * @sample {highstock} stock/chart/events-click/ + * Alert coordinates on click + * @sample {highstock} highcharts/chart/events-container/ + * Alternatively, attach event to container + * @sample {highmaps} maps/chart/events-click/ + * Record coordinates on click + * @sample {highmaps} highcharts/chart/events-container/ + * Alternatively, attach event to container + * + * @type {Highcharts.ChartClickCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Chart + * @apioption chart.events.click + */ + /** + * Fires when the chart is finished loading. Since v4.2.2, it also waits + * for images to be loaded, for example from point markers. One + * parameter, `event`, is passed to the function, containing common + * event information. + * + * There is also a second parameter to the chart constructor where a + * callback function can be passed to be executed on chart.load. + * + * @sample {highcharts} highcharts/chart/events-load/ + * Alert on chart load + * @sample {highstock} stock/chart/events-load/ + * Alert on chart load + * @sample {highmaps} maps/chart/events-load/ + * Add series on chart load + * + * @type {Highcharts.ChartLoadCallbackFunction} + * @context Highcharts.Chart + * @apioption chart.events.load + */ + /** + * Fires when the chart is redrawn, either after a call to + * `chart.redraw()` or after an axis, series or point is modified with + * the `redraw` option set to `true`. One parameter, `event`, is passed + * to the function, containing common event information. + * + * @sample {highcharts} highcharts/chart/events-redraw/ + * Alert on chart redraw + * @sample {highstock} stock/chart/events-redraw/ + * Alert on chart redraw when adding a series or moving the + * zoomed range + * @sample {highmaps} maps/chart/events-redraw/ + * Set subtitle on chart redraw + * + * @type {Highcharts.ChartRedrawCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Chart + * @apioption chart.events.redraw + */ + /** + * Fires after initial load of the chart (directly after the `load` + * event), and after each redraw (directly after the `redraw` event). + * + * @type {Highcharts.ChartRenderCallbackFunction} + * @since 5.0.7 + * @context Highcharts.Chart + * @apioption chart.events.render + */ + /** + * Fires when an area of the chart has been selected. Selection is + * enabled by setting the chart's zoomType. One parameter, `event`, is + * passed to the function, containing common event information. The + * default action for the selection event is to zoom the chart to the + * selected area. It can be prevented by calling + * `event.preventDefault()` or return false. + * + * Information on the selected area can be found through `event.xAxis` + * and `event.yAxis`, which are arrays containing the axes of each + * dimension and each axis' min and max values. The primary axes are + * `event.xAxis[0]` and `event.yAxis[0]`. Remember the unit of a + * datetime axis is milliseconds since 1970-01-01 00:00:00. + * + * ```js + * selection: function(event) { + * // log the min and max of the primary, datetime x-axis + * console.log( + * Highcharts.dateFormat( + * '%Y-%m-%d %H:%M:%S', + * event.xAxis[0].min + * ), + * Highcharts.dateFormat( + * '%Y-%m-%d %H:%M:%S', + * event.xAxis[0].max + * ) + * ); + * // log the min and max of the y axis + * console.log(event.yAxis[0].min, event.yAxis[0].max); + * } + * ``` + * + * @sample {highcharts} highcharts/chart/events-selection/ + * Report on selection and reset + * @sample {highcharts} highcharts/chart/events-selection-points/ + * Select a range of points through a drag selection + * @sample {highstock} stock/chart/events-selection/ + * Report on selection and reset + * @sample {highstock} highcharts/chart/events-selection-points/ + * Select a range of points through a drag selection + * (Highcharts) + * + * @type {Highcharts.ChartSelectionCallbackFunction} + * @apioption chart.events.selection + */ + /** + * The margin between the outer edge of the chart and the plot area. + * The numbers in the array designate top, right, bottom and left + * respectively. Use the options `marginTop`, `marginRight`, + * `marginBottom` and `marginLeft` for shorthand setting of one option. + * + * By default there is no margin. The actual space is dynamically + * calculated from the offset of axis labels, axis title, title, + * subtitle and legend in addition to the `spacingTop`, `spacingRight`, + * `spacingBottom` and `spacingLeft` options. + * + * @sample {highcharts} highcharts/chart/margins-zero/ + * Zero margins + * @sample {highstock} stock/chart/margin-zero/ + * Zero margins + * + * @type {number|Array} + * @apioption chart.margin + */ + /** + * The margin between the bottom outer edge of the chart and the plot + * area. Use this to set a fixed pixel value for the margin as opposed + * to the default dynamic margin. See also `spacingBottom`. + * + * @sample {highcharts} highcharts/chart/marginbottom/ + * 100px bottom margin + * @sample {highstock} stock/chart/marginbottom/ + * 100px bottom margin + * @sample {highmaps} maps/chart/margin/ + * 100px margins + * + * @type {number} + * @since 2.0 + * @apioption chart.marginBottom + */ + /** + * The margin between the left outer edge of the chart and the plot + * area. Use this to set a fixed pixel value for the margin as opposed + * to the default dynamic margin. See also `spacingLeft`. + * + * @sample {highcharts} highcharts/chart/marginleft/ + * 150px left margin + * @sample {highstock} stock/chart/marginleft/ + * 150px left margin + * @sample {highmaps} maps/chart/margin/ + * 100px margins + * + * @type {number} + * @since 2.0 + * @apioption chart.marginLeft + */ + /** + * The margin between the right outer edge of the chart and the plot + * area. Use this to set a fixed pixel value for the margin as opposed + * to the default dynamic margin. See also `spacingRight`. + * + * @sample {highcharts} highcharts/chart/marginright/ + * 100px right margin + * @sample {highstock} stock/chart/marginright/ + * 100px right margin + * @sample {highmaps} maps/chart/margin/ + * 100px margins + * + * @type {number} + * @since 2.0 + * @apioption chart.marginRight + */ + /** + * The margin between the top outer edge of the chart and the plot area. + * Use this to set a fixed pixel value for the margin as opposed to + * the default dynamic margin. See also `spacingTop`. + * + * @sample {highcharts} highcharts/chart/margintop/ 100px top margin + * @sample {highstock} stock/chart/margintop/ + * 100px top margin + * @sample {highmaps} maps/chart/margin/ + * 100px margins + * + * @type {number} + * @since 2.0 + * @apioption chart.marginTop + */ + /** + * Callback function to override the default function that formats all + * the numbers in the chart. Returns a string with the formatted number. + * + * @sample highcharts/members/highcharts-numberformat + * Arabic digits in Highcharts + * @type {Highcharts.NumberFormatterCallbackFunction} + * @since 8.0.0 + * @apioption chart.numberFormatter + */ + /** + * Allows setting a key to switch between zooming and panning. Can be + * one of `alt`, `ctrl`, `meta` (the command key on Mac and Windows + * key on Windows) or `shift`. The keys are mapped directly to the key + * properties of the click event argument (`event.altKey`, + * `event.ctrlKey`, `event.metaKey` and `event.shiftKey`). + * + * @type {string} + * @since 4.0.3 + * @product highcharts gantt + * @validvalue ["alt", "ctrl", "meta", "shift"] + * @apioption chart.panKey + */ + /** + * Allow panning in a chart. Best used with [panKey](#chart.panKey) + * to combine zooming and panning. + * + * On touch devices, when the [tooltip.followTouchMove]( + * #tooltip.followTouchMove) option is `true` (default), panning + * requires two fingers. To allow panning with one finger, set + * `followTouchMove` to `false`. + * + * @sample {highcharts} highcharts/chart/pankey/ Zooming and panning + * @sample {highstock} stock/chart/panning/ Zooming and xy panning + * + * @product highcharts highstock gantt + * @apioption chart.panning + */ + /** + * Enable or disable chart panning. + * + * @type {boolean} + * @default {highcharts} false + * @default {highstock} true + * @apioption chart.panning.enabled + */ + /** + * Decides in what dimensions the user can pan the chart. Can be + * one of `x`, `y`, or `xy`. + * + * @sample {highcharts} highcharts/chart/panning-type + * Zooming and xy panning + * + * @type {string} + * @validvalue ["x", "y", "xy"] + * @default x + * @apioption chart.panning.type + */ + /** + * Equivalent to [zoomType](#chart.zoomType), but for multitouch + * gestures only. By default, the `pinchType` is the same as the + * `zoomType` setting. However, pinching can be enabled separately in + * some cases, for example in stock charts where a mouse drag pans the + * chart, while pinching is enabled. When [tooltip.followTouchMove]( + * #tooltip.followTouchMove) is true, pinchType only applies to + * two-finger touches. + * + * @type {string} + * @default {highcharts} undefined + * @default {highstock} x + * @since 3.0 + * @product highcharts highstock gantt + * @validvalue ["x", "y", "xy"] + * @apioption chart.pinchType + */ + /** + * Whether to apply styled mode. When in styled mode, no presentational + * attributes or CSS are applied to the chart SVG. Instead, CSS rules + * are required to style the chart. The default style sheet is + * available from `https://code.highcharts.com/css/highcharts.css`. + * + * @type {boolean} + * @default false + * @since 7.0 + * @apioption chart.styledMode + */ + styledMode: false, + /** + * The corner radius of the outer chart border. + * + * @sample {highcharts} highcharts/chart/borderradius/ + * 20px radius + * @sample {highstock} stock/chart/border/ + * 10px radius + * @sample {highmaps} maps/chart/border/ + * Border options + * + */ + borderRadius: 0, + /** + * In styled mode, this sets how many colors the class names + * should rotate between. With ten colors, series (or points) are + * given class names like `highcharts-color-0`, `highcharts-color-0` + * [...] `highcharts-color-9`. The equivalent in non-styled mode + * is to set colors using the [colors](#colors) setting. + * + * @since 5.0.0 + */ + colorCount: 10, + /** + * Alias of `type`. + * + * @sample {highcharts} highcharts/chart/defaultseriestype/ + * Bar + * + * @deprecated + * + * @product highcharts + */ + defaultSeriesType: 'line', + /** + * If true, the axes will scale to the remaining visible series once + * one series is hidden. If false, hiding and showing a series will + * not affect the axes or the other series. For stacks, once one series + * within the stack is hidden, the rest of the stack will close in + * around it even if the axis is not affected. + * + * @sample {highcharts} highcharts/chart/ignorehiddenseries-true/ + * True by default + * @sample {highcharts} highcharts/chart/ignorehiddenseries-false/ + * False + * @sample {highcharts} highcharts/chart/ignorehiddenseries-true-stacked/ + * True with stack + * @sample {highstock} stock/chart/ignorehiddenseries-true/ + * True by default + * @sample {highstock} stock/chart/ignorehiddenseries-false/ + * False + * + * @since 1.2.0 + * @product highcharts highstock gantt + */ + ignoreHiddenSeries: true, + /** + * Whether to invert the axes so that the x axis is vertical and y axis + * is horizontal. When `true`, the x axis is [reversed](#xAxis.reversed) + * by default. + * + * @productdesc {highcharts} + * If a bar series is present in the chart, it will be inverted + * automatically. Inverting the chart doesn't have an effect if there + * are no cartesian series in the chart, or if the chart is + * [polar](#chart.polar). + * + * @sample {highcharts} highcharts/chart/inverted/ + * Inverted line + * @sample {highstock} stock/navigator/inverted/ + * Inverted stock chart + * + * @type {boolean} + * @default false + * @product highcharts highstock gantt + * @apioption chart.inverted + */ + /** + * The distance between the outer edge of the chart and the content, + * like title or legend, or axis title and labels if present. The + * numbers in the array designate top, right, bottom and left + * respectively. Use the options spacingTop, spacingRight, spacingBottom + * and spacingLeft options for shorthand setting of one option. + * + * @type {Array} + * @see [chart.margin](#chart.margin) + * @default [10, 10, 15, 10] + * @since 3.0.6 + */ + spacing: [10, 10, 15, 10], + /** + * The button that appears after a selection zoom, allowing the user + * to reset zoom. + */ + resetZoomButton: { + /** + * What frame the button placement should be related to. Can be + * either `plotBox` or `spacingBox`. + * + * @sample {highcharts} highcharts/chart/resetzoombutton-relativeto/ + * Relative to the chart + * @sample {highstock} highcharts/chart/resetzoombutton-relativeto/ + * Relative to the chart + * + * @type {Highcharts.ButtonRelativeToValue} + * @default plot + * @since 2.2 + * @apioption chart.resetZoomButton.relativeTo + */ + /** + * A collection of attributes for the button. The object takes SVG + * attributes like `fill`, `stroke`, `stroke-width` or `r`, the + * border radius. The theme also supports `style`, a collection of + * CSS properties for the text. Equivalent attributes for the hover + * state are given in `theme.states.hover`. + * + * @sample {highcharts} highcharts/chart/resetzoombutton-theme/ + * Theming the button + * @sample {highstock} highcharts/chart/resetzoombutton-theme/ + * Theming the button + * + * @type {Highcharts.SVGAttributes} + * @since 2.2 + */ + theme: { + /** @internal */ + zIndex: 6 + }, + /** + * The position of the button. + * + * @sample {highcharts} highcharts/chart/resetzoombutton-position/ + * Above the plot area + * @sample {highstock} highcharts/chart/resetzoombutton-position/ + * Above the plot area + * @sample {highmaps} highcharts/chart/resetzoombutton-position/ + * Above the plot area + * + * @type {Highcharts.AlignObject} + * @since 2.2 + */ + position: { + /** + * The horizontal alignment of the button. + */ + align: 'right', + /** + * The horizontal offset of the button. + */ + x: -10, + /** + * The vertical alignment of the button. + * + * @type {Highcharts.VerticalAlignValue} + * @default top + * @apioption chart.resetZoomButton.position.verticalAlign + */ + /** + * The vertical offset of the button. + */ + y: 10 + } + }, + /** + * The pixel width of the plot area border. + * + * @sample {highcharts} highcharts/chart/plotborderwidth/ + * 1px border + * @sample {highstock} stock/chart/plotborder/ + * 2px border + * @sample {highmaps} maps/chart/plotborder/ + * Plot border options + * + * @type {number} + * @default 0 + * @apioption chart.plotBorderWidth + */ + /** + * Whether to apply a drop shadow to the plot area. Requires that + * plotBackgroundColor be set. The shadow can be an object configuration + * containing `color`, `offsetX`, `offsetY`, `opacity` and `width`. + * + * @sample {highcharts} highcharts/chart/plotshadow/ + * Plot shadow + * @sample {highstock} stock/chart/plotshadow/ + * Plot shadow + * @sample {highmaps} maps/chart/plotborder/ + * Plot border options + * + * @type {boolean|Highcharts.CSSObject} + * @default false + * @apioption chart.plotShadow + */ + /** + * When true, cartesian charts like line, spline, area and column are + * transformed into the polar coordinate system. This produces _polar + * charts_, also known as _radar charts_. + * + * @sample {highcharts} highcharts/demo/polar/ + * Polar chart + * @sample {highcharts} highcharts/demo/polar-wind-rose/ + * Wind rose, stacked polar column chart + * @sample {highcharts} highcharts/demo/polar-spider/ + * Spider web chart + * @sample {highcharts} highcharts/parallel-coordinates/polar/ + * Star plot, multivariate data in a polar chart + * + * @type {boolean} + * @default false + * @since 2.3.0 + * @product highcharts + * @requires highcharts-more + * @apioption chart.polar + */ + /** + * Whether to reflow the chart to fit the width of the container div + * on resizing the window. + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * True by default + * @sample {highcharts} highcharts/chart/reflow-false/ + * False + * @sample {highstock} stock/chart/reflow-true/ + * True by default + * @sample {highstock} stock/chart/reflow-false/ + * False + * @sample {highmaps} maps/chart/reflow-true/ + * True by default + * @sample {highmaps} maps/chart/reflow-false/ + * False + * + * @type {boolean} + * @default true + * @since 2.1 + * @apioption chart.reflow + */ + /** + * The HTML element where the chart will be rendered. If it is a string, + * the element by that id is used. The HTML element can also be passed + * by direct reference, or as the first argument of the chart + * constructor, in which case the option is not needed. + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * String + * @sample {highcharts} highcharts/chart/renderto-object/ + * Object reference + * @sample {highcharts} highcharts/chart/renderto-jquery/ + * Object reference through jQuery + * @sample {highstock} stock/chart/renderto-string/ + * String + * @sample {highstock} stock/chart/renderto-object/ + * Object reference + * @sample {highstock} stock/chart/renderto-jquery/ + * Object reference through jQuery + * + * @type {string|Highcharts.HTMLDOMElement} + * @apioption chart.renderTo + */ + /** + * The background color of the marker square when selecting (zooming + * in on) an area of the chart. + * + * @see In styled mode, the selection marker fill is set with the + * `.highcharts-selection-marker` class. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default rgba(51,92,173,0.25) + * @since 2.1.7 + * @apioption chart.selectionMarkerFill + */ + /** + * Whether to apply a drop shadow to the outer chart area. Requires + * that backgroundColor be set. The shadow can be an object + * configuration containing `color`, `offsetX`, `offsetY`, `opacity` and + * `width`. + * + * @sample {highcharts} highcharts/chart/shadow/ + * Shadow + * @sample {highstock} stock/chart/shadow/ + * Shadow + * @sample {highmaps} maps/chart/border/ + * Chart border and shadow + * + * @type {boolean|Highcharts.CSSObject} + * @default false + * @apioption chart.shadow + */ + /** + * Whether to show the axes initially. This only applies to empty charts + * where series are added dynamically, as axes are automatically added + * to cartesian series. + * + * @sample {highcharts} highcharts/chart/showaxes-false/ + * False by default + * @sample {highcharts} highcharts/chart/showaxes-true/ + * True + * + * @type {boolean} + * @since 1.2.5 + * @product highcharts gantt + * @apioption chart.showAxes + */ + /** + * The space between the bottom edge of the chart and the content (plot + * area, axis title and labels, title, subtitle or legend in top + * position). + * + * @sample {highcharts} highcharts/chart/spacingbottom/ + * Spacing bottom set to 100 + * @sample {highstock} stock/chart/spacingbottom/ + * Spacing bottom set to 100 + * @sample {highmaps} maps/chart/spacing/ + * Spacing 100 all around + * + * @type {number} + * @default 15 + * @since 2.1 + * @apioption chart.spacingBottom + */ + /** + * The space between the left edge of the chart and the content (plot + * area, axis title and labels, title, subtitle or legend in top + * position). + * + * @sample {highcharts} highcharts/chart/spacingleft/ + * Spacing left set to 100 + * @sample {highstock} stock/chart/spacingleft/ + * Spacing left set to 100 + * @sample {highmaps} maps/chart/spacing/ + * Spacing 100 all around + * + * @type {number} + * @default 10 + * @since 2.1 + * @apioption chart.spacingLeft + */ + /** + * The space between the right edge of the chart and the content (plot + * area, axis title and labels, title, subtitle or legend in top + * position). + * + * @sample {highcharts} highcharts/chart/spacingright-100/ + * Spacing set to 100 + * @sample {highcharts} highcharts/chart/spacingright-legend/ + * Legend in right position with default spacing + * @sample {highstock} stock/chart/spacingright/ + * Spacing set to 100 + * @sample {highmaps} maps/chart/spacing/ + * Spacing 100 all around + * + * @type {number} + * @default 10 + * @since 2.1 + * @apioption chart.spacingRight + */ + /** + * The space between the top edge of the chart and the content (plot + * area, axis title and labels, title, subtitle or legend in top + * position). + * + * @sample {highcharts} highcharts/chart/spacingtop-100/ + * A top spacing of 100 + * @sample {highcharts} highcharts/chart/spacingtop-10/ + * Floating chart title makes the plot area align to the default + * spacingTop of 10. + * @sample {highstock} stock/chart/spacingtop/ + * A top spacing of 100 + * @sample {highmaps} maps/chart/spacing/ + * Spacing 100 all around + * + * @type {number} + * @default 10 + * @since 2.1 + * @apioption chart.spacingTop + */ + /** + * Additional CSS styles to apply inline to the container `div`. Note + * that since the default font styles are applied in the renderer, it + * is ignorant of the individual chart options and must be set globally. + * + * @see In styled mode, general chart styles can be set with the + * `.highcharts-root` class. + * @sample {highcharts} highcharts/chart/style-serif-font/ + * Using a serif type font + * @sample {highcharts} highcharts/css/em/ + * Styled mode with relative font sizes + * @sample {highstock} stock/chart/style/ + * Using a serif type font + * @sample {highmaps} maps/chart/style-serif-font/ + * Using a serif type font + * + * @type {Highcharts.CSSObject} + * @default {"fontFamily": "\"Lucida Grande\", \"Lucida Sans Unicode\", Verdana, Arial, Helvetica, sans-serif","fontSize":"12px"} + * @apioption chart.style + */ + /** + * The default series type for the chart. Can be any of the chart types + * listed under [plotOptions](#plotOptions) and [series](#series) or can + * be a series provided by an additional module. + * + * In TypeScript this option has no effect in sense of typing and + * instead the `type` option must always be set in the series. + * + * @sample {highcharts} highcharts/chart/type-bar/ + * Bar + * @sample {highstock} stock/chart/type/ + * Areaspline + * @sample {highmaps} maps/chart/type-mapline/ + * Mapline + * + * @type {string} + * @default {highcharts} line + * @default {highstock} line + * @default {highmaps} map + * @since 2.1.0 + * @apioption chart.type + */ + /** + * Decides in what dimensions the user can zoom by dragging the mouse. + * Can be one of `x`, `y` or `xy`. + * + * @see [panKey](#chart.panKey) + * + * @sample {highcharts} highcharts/chart/zoomtype-none/ + * None by default + * @sample {highcharts} highcharts/chart/zoomtype-x/ + * X + * @sample {highcharts} highcharts/chart/zoomtype-y/ + * Y + * @sample {highcharts} highcharts/chart/zoomtype-xy/ + * Xy + * @sample {highstock} stock/demo/basic-line/ + * None by default + * @sample {highstock} stock/chart/zoomtype-x/ + * X + * @sample {highstock} stock/chart/zoomtype-y/ + * Y + * @sample {highstock} stock/chart/zoomtype-xy/ + * Xy + * + * @type {string} + * @product highcharts highstock gantt + * @validvalue ["x", "y", "xy"] + * @apioption chart.zoomType + */ + /** + * An explicit width for the chart. By default (when `null`) the width + * is calculated from the offset width of the containing element. + * + * @sample {highcharts} highcharts/chart/width/ + * 800px wide + * @sample {highstock} stock/chart/width/ + * 800px wide + * @sample {highmaps} maps/chart/size/ + * Chart with explicit size + * + * @type {null|number|string} + */ + width: null, + /** + * An explicit height for the chart. If a _number_, the height is + * given in pixels. If given a _percentage string_ (for example + * `'56%'`), the height is given as the percentage of the actual chart + * width. This allows for preserving the aspect ratio across responsive + * sizes. + * + * By default (when `null`) the height is calculated from the offset + * height of the containing element, or 400 pixels if the containing + * element's height is 0. + * + * @sample {highcharts} highcharts/chart/height/ + * 500px height + * @sample {highstock} stock/chart/height/ + * 300px height + * @sample {highmaps} maps/chart/size/ + * Chart with explicit size + * @sample highcharts/chart/height-percent/ + * Highcharts with percentage height + * + * @type {null|number|string} + */ + height: null, + /** + * The color of the outer chart border. + * + * @see In styled mode, the stroke is set with the + * `.highcharts-background` class. + * + * @sample {highcharts} highcharts/chart/bordercolor/ + * Brown border + * @sample {highstock} stock/chart/border/ + * Brown border + * @sample {highmaps} maps/chart/border/ + * Border options + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + borderColor: '#335cad', + /** + * The pixel width of the outer chart border. + * + * @see In styled mode, the stroke is set with the + * `.highcharts-background` class. + * + * @sample {highcharts} highcharts/chart/borderwidth/ + * 5px border + * @sample {highstock} stock/chart/border/ + * 2px border + * @sample {highmaps} maps/chart/border/ + * Border options + * + * @type {number} + * @default 0 + * @apioption chart.borderWidth + */ + /** + * The background color or gradient for the outer chart area. + * + * @see In styled mode, the background is set with the + * `.highcharts-background` class. + * + * @sample {highcharts} highcharts/chart/backgroundcolor-color/ + * Color + * @sample {highcharts} highcharts/chart/backgroundcolor-gradient/ + * Gradient + * @sample {highstock} stock/chart/backgroundcolor-color/ + * Color + * @sample {highstock} stock/chart/backgroundcolor-gradient/ + * Gradient + * @sample {highmaps} maps/chart/backgroundcolor-color/ + * Color + * @sample {highmaps} maps/chart/backgroundcolor-gradient/ + * Gradient + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + backgroundColor: '#ffffff', + /** + * The background color or gradient for the plot area. + * + * @see In styled mode, the plot background is set with the + * `.highcharts-plot-background` class. + * + * @sample {highcharts} highcharts/chart/plotbackgroundcolor-color/ + * Color + * @sample {highcharts} highcharts/chart/plotbackgroundcolor-gradient/ + * Gradient + * @sample {highstock} stock/chart/plotbackgroundcolor-color/ + * Color + * @sample {highstock} stock/chart/plotbackgroundcolor-gradient/ + * Gradient + * @sample {highmaps} maps/chart/plotbackgroundcolor-color/ + * Color + * @sample {highmaps} maps/chart/plotbackgroundcolor-gradient/ + * Gradient + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption chart.plotBackgroundColor + */ + /** + * The URL for an image to use as the plot background. To set an image + * as the background for the entire chart, set a CSS background image + * to the container element. Note that for the image to be applied to + * exported charts, its URL needs to be accessible by the export server. + * + * @see In styled mode, a plot background image can be set with the + * `.highcharts-plot-background` class and a [custom pattern]( + * https://www.highcharts.com/docs/chart-design-and-style/ + * gradients-shadows-and-patterns). + * + * @sample {highcharts} highcharts/chart/plotbackgroundimage/ + * Skies + * @sample {highstock} stock/chart/plotbackgroundimage/ + * Skies + * + * @type {string} + * @apioption chart.plotBackgroundImage + */ + /** + * The color of the inner chart or plot area border. + * + * @see In styled mode, a plot border stroke can be set with the + * `.highcharts-plot-border` class. + * + * @sample {highcharts} highcharts/chart/plotbordercolor/ + * Blue border + * @sample {highstock} stock/chart/plotborder/ + * Blue border + * @sample {highmaps} maps/chart/plotborder/ + * Plot border options + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + plotBorderColor: '#cccccc' + }, + /** + * The chart's main title. + * + * @sample {highmaps} maps/title/title/ + * Title options demonstrated + */ + title: { + /** + * When the title is floating, the plot area will not move to make space + * for it. + * + * @sample {highcharts} highcharts/chart/zoomtype-none/ + * False by default + * @sample {highcharts} highcharts/title/floating/ + * True - title on top of the plot area + * @sample {highstock} stock/chart/title-floating/ + * True - title on top of the plot area + * + * @type {boolean} + * @default false + * @since 2.1 + * @apioption title.floating + */ + /** + * CSS styles for the title. Use this for font styling, but use `align`, + * `x` and `y` for text alignment. + * + * In styled mode, the title style is given in the `.highcharts-title` + * class. + * + * @sample {highcharts} highcharts/title/style/ + * Custom color and weight + * @sample {highstock} stock/chart/title-style/ + * Custom color and weight + * @sample highcharts/css/titles/ + * Styled mode + * + * @type {Highcharts.CSSObject} + * @default {highcharts|highmaps} { "color": "#333333", "fontSize": "18px" } + * @default {highstock} { "color": "#333333", "fontSize": "16px" } + * @apioption title.style + */ + /** + * Whether to + * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the text. + * + * @type {boolean} + * @default false + * @apioption title.useHTML + */ + /** + * The vertical alignment of the title. Can be one of `"top"`, + * `"middle"` and `"bottom"`. When a value is given, the title behaves + * as if [floating](#title.floating) were `true`. + * + * @sample {highcharts} highcharts/title/verticalalign/ + * Chart title in bottom right corner + * @sample {highstock} stock/chart/title-verticalalign/ + * Chart title in bottom right corner + * + * @type {Highcharts.VerticalAlignValue} + * @since 2.1 + * @apioption title.verticalAlign + */ + /** + * The x position of the title relative to the alignment within + * `chart.spacingLeft` and `chart.spacingRight`. + * + * @sample {highcharts} highcharts/title/align/ + * Aligned to the plot area (x = 70px = margin left - spacing + * left) + * @sample {highstock} stock/chart/title-align/ + * Aligned to the plot area (x = 50px = margin left - spacing + * left) + * + * @type {number} + * @default 0 + * @since 2.0 + * @apioption title.x + */ + /** + * The y position of the title relative to the alignment within + * [chart.spacingTop](#chart.spacingTop) and [chart.spacingBottom]( + * #chart.spacingBottom). By default it depends on the font size. + * + * @sample {highcharts} highcharts/title/y/ + * Title inside the plot area + * @sample {highstock} stock/chart/title-verticalalign/ + * Chart title in bottom right corner + * + * @type {number} + * @since 2.0 + * @apioption title.y + */ + /** + * The title of the chart. To disable the title, set the `text` to + * `undefined`. + * + * @sample {highcharts} highcharts/title/text/ + * Custom title + * @sample {highstock} stock/chart/title-text/ + * Custom title + * + * @default {highcharts|highmaps} Chart title + * @default {highstock} undefined + */ + text: 'Chart title', + /** + * The horizontal alignment of the title. Can be one of "left", "center" + * and "right". + * + * @sample {highcharts} highcharts/title/align/ + * Aligned to the plot area (x = 70px = margin left - spacing + * left) + * @sample {highstock} stock/chart/title-align/ + * Aligned to the plot area (x = 50px = margin left - spacing + * left) + * + * @type {Highcharts.AlignValue} + * @since 2.0 + */ + align: 'center', + /** + * The margin between the title and the plot area, or if a subtitle + * is present, the margin between the subtitle and the plot area. + * + * @sample {highcharts} highcharts/title/margin-50/ + * A chart title margin of 50 + * @sample {highcharts} highcharts/title/margin-subtitle/ + * The same margin applied with a subtitle + * @sample {highstock} stock/chart/title-margin/ + * A chart title margin of 50 + * + * @since 2.1 + */ + margin: 15, + /** + * Adjustment made to the title width, normally to reserve space for + * the exporting burger menu. + * + * @sample highcharts/title/widthadjust/ + * Wider menu, greater padding + * + * @since 4.2.5 + */ + widthAdjust: -44 + }, + /** + * The chart's subtitle. This can be used both to display a subtitle below + * the main title, and to display random text anywhere in the chart. The + * subtitle can be updated after chart initialization through the + * `Chart.setTitle` method. + * + * @sample {highmaps} maps/title/subtitle/ + * Subtitle options demonstrated + */ + subtitle: { + /** + * When the subtitle is floating, the plot area will not move to make + * space for it. + * + * @sample {highcharts} highcharts/subtitle/floating/ + * Floating title and subtitle + * @sample {highstock} stock/chart/subtitle-footnote + * Footnote floating at bottom right of plot area + * + * @type {boolean} + * @default false + * @since 2.1 + * @apioption subtitle.floating + */ + /** + * CSS styles for the title. + * + * In styled mode, the subtitle style is given in the + * `.highcharts-subtitle` class. + * + * @sample {highcharts} highcharts/subtitle/style/ + * Custom color and weight + * @sample {highcharts} highcharts/css/titles/ + * Styled mode + * @sample {highstock} stock/chart/subtitle-style + * Custom color and weight + * @sample {highstock} highcharts/css/titles/ + * Styled mode + * @sample {highmaps} highcharts/css/titles/ + * Styled mode + * + * @type {Highcharts.CSSObject} + * @default {"color": "#666666"} + * @apioption subtitle.style + */ + /** + * Whether to + * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the text. + * + * @type {boolean} + * @default false + * @apioption subtitle.useHTML + */ + /** + * The vertical alignment of the title. Can be one of `"top"`, + * `"middle"` and `"bottom"`. When middle, the subtitle behaves as + * floating. + * + * @sample {highcharts} highcharts/subtitle/verticalalign/ + * Footnote at the bottom right of plot area + * @sample {highstock} stock/chart/subtitle-footnote + * Footnote at the bottom right of plot area + * + * @type {Highcharts.VerticalAlignValue} + * @since 2.1 + * @apioption subtitle.verticalAlign + */ + /** + * The x position of the subtitle relative to the alignment within + * `chart.spacingLeft` and `chart.spacingRight`. + * + * @sample {highcharts} highcharts/subtitle/align/ + * Footnote at right of plot area + * @sample {highstock} stock/chart/subtitle-footnote + * Footnote at the bottom right of plot area + * + * @type {number} + * @default 0 + * @since 2.0 + * @apioption subtitle.x + */ + /** + * The y position of the subtitle relative to the alignment within + * `chart.spacingTop` and `chart.spacingBottom`. By default the subtitle + * is laid out below the title unless the title is floating. + * + * @sample {highcharts} highcharts/subtitle/verticalalign/ + * Footnote at the bottom right of plot area + * @sample {highstock} stock/chart/subtitle-footnote + * Footnote at the bottom right of plot area + * + * @type {number} + * @since 2.0 + * @apioption subtitle.y + */ + /** + * The subtitle of the chart. + * + * @sample {highcharts|highstock} highcharts/subtitle/text/ + * Custom subtitle + * @sample {highcharts|highstock} highcharts/subtitle/text-formatted/ + * Formatted and linked text. + */ + text: '', + /** + * The horizontal alignment of the subtitle. Can be one of "left", + * "center" and "right". + * + * @sample {highcharts} highcharts/subtitle/align/ + * Footnote at right of plot area + * @sample {highstock} stock/chart/subtitle-footnote + * Footnote at bottom right of plot area + * + * @type {Highcharts.AlignValue} + * @since 2.0 + */ + align: 'center', + /** + * Adjustment made to the subtitle width, normally to reserve space + * for the exporting burger menu. + * + * @see [title.widthAdjust](#title.widthAdjust) + * + * @sample highcharts/title/widthadjust/ + * Wider menu, greater padding + * + * @since 4.2.5 + */ + widthAdjust: -44 + }, + /** + * The chart's caption, which will render below the chart and will be part + * of exported charts. The caption can be updated after chart initialization + * through the `Chart.update` or `Chart.caption.update` methods. + * + * @sample highcharts/caption/text/ + * A chart with a caption + * @since 7.2.0 + */ + caption: { + /** + * When the caption is floating, the plot area will not move to make + * space for it. + * + * @type {boolean} + * @default false + * @apioption caption.floating + */ + /** + * The margin between the caption and the plot area. + */ + margin: 15, + /** + * CSS styles for the caption. + * + * In styled mode, the caption style is given in the + * `.highcharts-caption` class. + * + * @sample {highcharts} highcharts/css/titles/ + * Styled mode + * + * @type {Highcharts.CSSObject} + * @default {"color": "#666666"} + * @apioption caption.style + */ + /** + * Whether to + * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the text. + * + * @type {boolean} + * @default false + * @apioption caption.useHTML + */ + /** + * The x position of the caption relative to the alignment within + * `chart.spacingLeft` and `chart.spacingRight`. + * + * @type {number} + * @default 0 + * @apioption caption.x + */ + /** + * The y position of the caption relative to the alignment within + * `chart.spacingTop` and `chart.spacingBottom`. + * + * @type {number} + * @apioption caption.y + */ + /** + * The caption text of the chart. + * + * @sample {highcharts} highcharts/caption/text/ + * Custom caption + */ + text: '', + /** + * The horizontal alignment of the caption. Can be one of "left", + * "center" and "right". + * + * @type {Highcharts.AlignValue} + */ + align: 'left', + /** + * The vertical alignment of the caption. Can be one of `"top"`, + * `"middle"` and `"bottom"`. When middle, the caption behaves as + * floating. + * + * @type {Highcharts.VerticalAlignValue} + */ + verticalAlign: 'bottom' + }, + /** + * The plotOptions is a wrapper object for config objects for each series + * type. The config objects for each series can also be overridden for + * each series item as given in the series array. + * + * Configuration options for the series are given in three levels. Options + * for all series in a chart are given in the [plotOptions.series]( + * #plotOptions.series) object. Then options for all series of a specific + * type are given in the plotOptions of that type, for example + * `plotOptions.line`. Next, options for one single series are given in + * [the series array](#series). + */ + plotOptions: {}, + /** + * HTML labels that can be positioned anywhere in the chart area. + * + * This option is deprecated since v7.1.2. Instead, use + * [annotations](#annotations) that support labels. + * + * @deprecated + * @product highcharts highstock + */ + labels: { + /** + * An HTML label that can be positioned anywhere in the chart area. + * + * @deprecated + * @type {Array<*>} + * @apioption labels.items + */ + /** + * Inner HTML or text for the label. + * + * @deprecated + * @type {string} + * @apioption labels.items.html + */ + /** + * CSS styles for each label. To position the label, use left and top + * like this: + * ```js + * style: { + * left: '100px', + * top: '100px' + * } + * ``` + * + * @deprecated + * @type {Highcharts.CSSObject} + * @apioption labels.items.style + */ + /** + * Shared CSS styles for all labels. + * + * @deprecated + * @type {Highcharts.CSSObject} + * @default {"color": "#333333", "position": "absolute"} + */ + style: { + /** + * @ignore-option + */ + position: 'absolute', + /** + * @ignore-option + */ + color: '#333333' + } + }, + /** + * The legend is a box containing a symbol and name for each series + * item or point item in the chart. Each series (or points in case + * of pie charts) is represented by a symbol and its name in the legend. + * + * It is possible to override the symbol creator function and create + * [custom legend symbols](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/studies/legend-custom-symbol/). + * + * @productdesc {highmaps} + * A Highmaps legend by default contains one legend item per series, but if + * a `colorAxis` is defined, the axis will be displayed in the legend. + * Either as a gradient, or as multiple legend items for `dataClasses`. + */ + legend: { + /** + * The background color of the legend. + * + * @see In styled mode, the legend background fill can be applied with + * the `.highcharts-legend-box` class. + * + * @sample {highcharts} highcharts/legend/backgroundcolor/ + * Yellowish background + * @sample {highstock} stock/legend/align/ + * Various legend options + * @sample {highmaps} maps/legend/border-background/ + * Border and background options + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption legend.backgroundColor + */ + /** + * The width of the drawn border around the legend. + * + * @see In styled mode, the legend border stroke width can be applied + * with the `.highcharts-legend-box` class. + * + * @sample {highcharts} highcharts/legend/borderwidth/ + * 2px border width + * @sample {highstock} stock/legend/align/ + * Various legend options + * @sample {highmaps} maps/legend/border-background/ + * Border and background options + * + * @type {number} + * @default 0 + * @apioption legend.borderWidth + */ + /** + * Enable or disable the legend. There is also a series-specific option, + * [showInLegend](#plotOptions.series.showInLegend), that can hide the + * series from the legend. In some series types this is `false` by + * default, so it must set to `true` in order to show the legend for the + * series. + * + * @sample {highcharts} highcharts/legend/enabled-false/ Legend disabled + * @sample {highstock} stock/legend/align/ Various legend options + * @sample {highmaps} maps/legend/enabled-false/ Legend disabled + * + * @default {highstock} false + * @default {highmaps} true + * @default {gantt} false + */ + enabled: true, + /** + * The horizontal alignment of the legend box within the chart area. + * Valid values are `left`, `center` and `right`. + * + * In the case that the legend is aligned in a corner position, the + * `layout` option will determine whether to place it above/below + * or on the side of the plot area. + * + * @sample {highcharts} highcharts/legend/align/ + * Legend at the right of the chart + * @sample {highstock} stock/legend/align/ + * Various legend options + * @sample {highmaps} maps/legend/alignment/ + * Legend alignment + * + * @type {Highcharts.AlignValue} + * @since 2.0 + */ + align: 'center', + /** + * If the [layout](legend.layout) is `horizontal` and the legend items + * span over two lines or more, whether to align the items into vertical + * columns. Setting this to `false` makes room for more items, but will + * look more messy. + * + * @since 6.1.0 + */ + alignColumns: true, + /** + * When the legend is floating, the plot area ignores it and is allowed + * to be placed below it. + * + * @sample {highcharts} highcharts/legend/floating-false/ + * False by default + * @sample {highcharts} highcharts/legend/floating-true/ + * True + * @sample {highmaps} maps/legend/alignment/ + * Floating legend + * + * @type {boolean} + * @default false + * @since 2.1 + * @apioption legend.floating + */ + /** + * The layout of the legend items. Can be one of `horizontal` or + * `vertical` or `proximate`. When `proximate`, the legend items will be + * placed as close as possible to the graphs they're representing, + * except in inverted charts or when the legend position doesn't allow + * it. + * + * @sample {highcharts} highcharts/legend/layout-horizontal/ + * Horizontal by default + * @sample {highcharts} highcharts/legend/layout-vertical/ + * Vertical + * @sample highcharts/legend/layout-proximate + * Labels proximate to the data + * @sample {highstock} stock/legend/layout-horizontal/ + * Horizontal by default + * @sample {highmaps} maps/legend/padding-itemmargin/ + * Vertical with data classes + * @sample {highmaps} maps/legend/layout-vertical/ + * Vertical with color axis gradient + * + * @validvalue ["horizontal", "vertical", "proximate"] + */ + layout: 'horizontal', + /** + * In a legend with horizontal layout, the itemDistance defines the + * pixel distance between each item. + * + * @sample {highcharts} highcharts/legend/layout-horizontal/ + * 50px item distance + * @sample {highstock} highcharts/legend/layout-horizontal/ + * 50px item distance + * + * @type {number} + * @default {highcharts} 20 + * @default {highstock} 20 + * @default {highmaps} 8 + * @since 3.0.3 + * @apioption legend.itemDistance + */ + /** + * The pixel bottom margin for each legend item. + * + * @sample {highcharts|highstock} highcharts/legend/padding-itemmargin/ + * Padding and item margins demonstrated + * @sample {highmaps} maps/legend/padding-itemmargin/ + * Padding and item margins demonstrated + * + * @type {number} + * @default 0 + * @since 2.2.0 + * @apioption legend.itemMarginBottom + */ + /** + * The pixel top margin for each legend item. + * + * @sample {highcharts|highstock} highcharts/legend/padding-itemmargin/ + * Padding and item margins demonstrated + * @sample {highmaps} maps/legend/padding-itemmargin/ + * Padding and item margins demonstrated + * + * @type {number} + * @default 0 + * @since 2.2.0 + * @apioption legend.itemMarginTop + */ + /** + * The width for each legend item. By default the items are laid out + * successively. In a [horizontal layout](legend.layout), if the items + * are laid out across two rows or more, they will be vertically aligned + * depending on the [legend.alignColumns](legend.alignColumns) option. + * + * @sample {highcharts} highcharts/legend/itemwidth-default/ + * Undefined by default + * @sample {highcharts} highcharts/legend/itemwidth-80/ + * 80 for aligned legend items + * + * @type {number} + * @since 2.0 + * @apioption legend.itemWidth + */ + /** + * A [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) + * for each legend label. Available variables relates to properties on + * the series, or the point in case of pies. + * + * @type {string} + * @default {name} + * @since 1.3 + * @apioption legend.labelFormat + */ + /* eslint-disable valid-jsdoc */ + /** + * Callback function to format each of the series' labels. The `this` + * keyword refers to the series object, or the point object in case of + * pie charts. By default the series or point name is printed. + * + * @productdesc {highmaps} + * In Highmaps the context can also be a data class in case of a + * `colorAxis`. + * + * @sample {highcharts} highcharts/legend/labelformatter/ + * Add text + * @sample {highmaps} maps/legend/labelformatter/ + * Data classes with label formatter + * + * @type {Highcharts.FormatterCallbackFunction} + */ + labelFormatter: function () { + /** eslint-enable valid-jsdoc */ + return this.name; + }, + /** + * Line height for the legend items. Deprecated as of 2.1\. Instead, + * the line height for each item can be set using + * `itemStyle.lineHeight`, and the padding between items using + * `itemMarginTop` and `itemMarginBottom`. + * + * @sample {highcharts} highcharts/legend/lineheight/ + * Setting padding + * + * @deprecated + * + * @type {number} + * @default 16 + * @since 2.0 + * @product highcharts gantt + * @apioption legend.lineHeight + */ + /** + * If the plot area sized is calculated automatically and the legend is + * not floating, the legend margin is the space between the legend and + * the axis labels or plot area. + * + * @sample {highcharts} highcharts/legend/margin-default/ + * 12 pixels by default + * @sample {highcharts} highcharts/legend/margin-30/ + * 30 pixels + * + * @type {number} + * @default 12 + * @since 2.1 + * @apioption legend.margin + */ + /** + * Maximum pixel height for the legend. When the maximum height is + * extended, navigation will show. + * + * @type {number} + * @since 2.3.0 + * @apioption legend.maxHeight + */ + /** + * The color of the drawn border around the legend. + * + * @see In styled mode, the legend border stroke can be applied with the + * `.highcharts-legend-box` class. + * + * @sample {highcharts} highcharts/legend/bordercolor/ + * Brown border + * @sample {highstock} stock/legend/align/ + * Various legend options + * @sample {highmaps} maps/legend/border-background/ + * Border and background options + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + borderColor: '#999999', + /** + * The border corner radius of the legend. + * + * @sample {highcharts} highcharts/legend/borderradius-default/ + * Square by default + * @sample {highcharts} highcharts/legend/borderradius-round/ + * 5px rounded + * @sample {highmaps} maps/legend/border-background/ + * Border and background options + */ + borderRadius: 0, + /** + * Options for the paging or navigation appearing when the legend is + * overflown. Navigation works well on screen, but not in static + * exported images. One way of working around that is to + * [increase the chart height in + * export](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/legend/navigation-enabled-false/). + */ + navigation: { + /** + * How to animate the pages when navigating up or down. A value of + * `true` applies the default navigation given in the + * `chart.animation` option. Additional options can be given as an + * object containing values for easing and duration. + * + * @sample {highcharts} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * @sample {highstock} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * + * @type {boolean|Highcharts.AnimationOptionsObject} + * @default true + * @since 2.2.4 + * @apioption legend.navigation.animation + */ + /** + * The pixel size of the up and down arrows in the legend paging + * navigation. + * + * @sample {highcharts} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * @sample {highstock} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * + * @type {number} + * @default 12 + * @since 2.2.4 + * @apioption legend.navigation.arrowSize + */ + /** + * Whether to enable the legend navigation. In most cases, disabling + * the navigation results in an unwanted overflow. + * + * See also the [adapt chart to legend]( + * https://www.highcharts.com/products/plugin-registry/single/8/Adapt-Chart-To-Legend) + * plugin for a solution to extend the chart height to make room for + * the legend, optionally in exported charts only. + * + * @type {boolean} + * @default true + * @since 4.2.4 + * @apioption legend.navigation.enabled + */ + /** + * Text styles for the legend page navigation. + * + * @see In styled mode, the navigation items are styled with the + * `.highcharts-legend-navigation` class. + * + * @sample {highcharts} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * @sample {highstock} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * + * @type {Highcharts.CSSObject} + * @since 2.2.4 + * @apioption legend.navigation.style + */ + /** + * The color for the active up or down arrow in the legend page + * navigation. + * + * @see In styled mode, the active arrow be styled with the + * `.highcharts-legend-nav-active` class. + * + * @sample {highcharts} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * @sample {highstock} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.2.4 + */ + activeColor: '#003399', + /** + * The color of the inactive up or down arrow in the legend page + * navigation. . + * + * @see In styled mode, the inactive arrow be styled with the + * `.highcharts-legend-nav-inactive` class. + * + * @sample {highcharts} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * @sample {highstock} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.2.4 + */ + inactiveColor: '#cccccc' + }, + /** + * The inner padding of the legend box. + * + * @sample {highcharts|highstock} highcharts/legend/padding-itemmargin/ + * Padding and item margins demonstrated + * @sample {highmaps} maps/legend/padding-itemmargin/ + * Padding and item margins demonstrated + * + * @type {number} + * @default 8 + * @since 2.2.0 + * @apioption legend.padding + */ + /** + * Whether to reverse the order of the legend items compared to the + * order of the series or points as defined in the configuration object. + * + * @see [yAxis.reversedStacks](#yAxis.reversedStacks), + * [series.legendIndex](#series.legendIndex) + * + * @sample {highcharts} highcharts/legend/reversed/ + * Stacked bar with reversed legend + * + * @type {boolean} + * @default false + * @since 1.2.5 + * @apioption legend.reversed + */ + /** + * Whether to show the symbol on the right side of the text rather than + * the left side. This is common in Arabic and Hebraic. + * + * @sample {highcharts} highcharts/legend/rtl/ + * Symbol to the right + * + * @type {boolean} + * @default false + * @since 2.2 + * @apioption legend.rtl + */ + /** + * CSS styles for the legend area. In the 1.x versions the position + * of the legend area was determined by CSS. In 2.x, the position is + * determined by properties like `align`, `verticalAlign`, `x` and `y`, + * but the styles are still parsed for backwards compatibility. + * + * @deprecated + * + * @type {Highcharts.CSSObject} + * @product highcharts highstock + * @apioption legend.style + */ + /** + * CSS styles for each legend item. Only a subset of CSS is supported, + * notably those options related to text. The default `textOverflow` + * property makes long texts truncate. Set it to `undefined` to wrap + * text instead. A `width` property can be added to control the text + * width. + * + * @see In styled mode, the legend items can be styled with the + * `.highcharts-legend-item` class. + * + * @sample {highcharts} highcharts/legend/itemstyle/ + * Bold black text + * @sample {highmaps} maps/legend/itemstyle/ + * Item text styles + * + * @type {Highcharts.CSSObject} + * @default {"color": "#333333", "cursor": "pointer", "fontSize": "12px", "fontWeight": "bold", "textOverflow": "ellipsis"} + */ + itemStyle: { + /** + * @ignore + */ + color: '#333333', + /** + * @ignore + */ + cursor: 'pointer', + /** + * @ignore + */ + fontSize: '12px', + /** + * @ignore + */ + fontWeight: 'bold', + /** + * @ignore + */ + textOverflow: 'ellipsis' + }, + /** + * CSS styles for each legend item in hover mode. Only a subset of + * CSS is supported, notably those options related to text. Properties + * are inherited from `style` unless overridden here. + * + * @see In styled mode, the hovered legend items can be styled with + * the `.highcharts-legend-item:hover` pesudo-class. + * + * @sample {highcharts} highcharts/legend/itemhoverstyle/ + * Red on hover + * @sample {highmaps} maps/legend/itemstyle/ + * Item text styles + * + * @type {Highcharts.CSSObject} + * @default {"color": "#000000"} + */ + itemHoverStyle: { + /** + * @ignore + */ + color: '#000000' + }, + /** + * CSS styles for each legend item when the corresponding series or + * point is hidden. Only a subset of CSS is supported, notably those + * options related to text. Properties are inherited from `style` + * unless overridden here. + * + * @see In styled mode, the hidden legend items can be styled with + * the `.highcharts-legend-item-hidden` class. + * + * @sample {highcharts} highcharts/legend/itemhiddenstyle/ + * Darker gray color + * + * @type {Highcharts.CSSObject} + * @default {"color": "#cccccc"} + */ + itemHiddenStyle: { + /** + * @ignore + */ + color: '#cccccc' + }, + /** + * Whether to apply a drop shadow to the legend. A `backgroundColor` + * also needs to be applied for this to take effect. The shadow can be + * an object configuration containing `color`, `offsetX`, `offsetY`, + * `opacity` and `width`. + * + * @sample {highcharts} highcharts/legend/shadow/ + * White background and drop shadow + * @sample {highstock} stock/legend/align/ + * Various legend options + * @sample {highmaps} maps/legend/border-background/ + * Border and background options + * + * @type {boolean|Highcharts.CSSObject} + */ + shadow: false, + /** + * Default styling for the checkbox next to a legend item when + * `showCheckbox` is true. + * + * @type {Highcharts.CSSObject} + * @default {"width": "13px", "height": "13px", "position":"absolute"} + */ + itemCheckboxStyle: { + /** + * @ignore + */ + position: 'absolute', + /** + * @ignore + */ + width: '13px', + /** + * @ignore + */ + height: '13px' + }, + // itemWidth: undefined, + /** + * When this is true, the legend symbol width will be the same as + * the symbol height, which in turn defaults to the font size of the + * legend items. + * + * @since 5.0.0 + */ + squareSymbol: true, + /** + * The pixel height of the symbol for series types that use a rectangle + * in the legend. Defaults to the font size of legend items. + * + * @productdesc {highmaps} + * In Highmaps, when the symbol is the gradient of a vertical color + * axis, the height defaults to 200. + * + * @sample {highmaps} maps/legend/layout-vertical-sized/ + * Sized vertical gradient + * @sample {highmaps} maps/legend/padding-itemmargin/ + * No distance between data classes + * + * @type {number} + * @since 3.0.8 + * @apioption legend.symbolHeight + */ + /** + * The border radius of the symbol for series types that use a rectangle + * in the legend. Defaults to half the `symbolHeight`. + * + * @sample {highcharts} highcharts/legend/symbolradius/ + * Round symbols + * @sample {highstock} highcharts/legend/symbolradius/ + * Round symbols + * @sample {highmaps} highcharts/legend/symbolradius/ + * Round symbols + * + * @type {number} + * @since 3.0.8 + * @apioption legend.symbolRadius + */ + /** + * The pixel width of the legend item symbol. When the `squareSymbol` + * option is set, this defaults to the `symbolHeight`, otherwise 16. + * + * @productdesc {highmaps} + * In Highmaps, when the symbol is the gradient of a horizontal color + * axis, the width defaults to 200. + * + * @sample {highcharts} highcharts/legend/symbolwidth/ + * Greater symbol width and padding + * @sample {highmaps} maps/legend/padding-itemmargin/ + * Padding and item margins demonstrated + * @sample {highmaps} maps/legend/layout-vertical-sized/ + * Sized vertical gradient + * + * @type {number} + * @apioption legend.symbolWidth + */ + /** + * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the legend item texts. + * + * Prior to 4.1.7, when using HTML, [legend.navigation]( + * #legend.navigation) was disabled. + * + * @type {boolean} + * @default false + * @apioption legend.useHTML + */ + /** + * The width of the legend box. If a number is set, it translates to + * pixels. Since v7.0.2 it allows setting a percent string of the full + * chart width, for example `40%`. + * + * Defaults to the full chart width from legends below or above the + * chart, half the chart width for legends to the left and right. + * + * @sample {highcharts} highcharts/legend/width/ + * Aligned to the plot area + * @sample {highcharts} highcharts/legend/width-percent/ + * A percent of the chart width + * + * @type {number|string} + * @since 2.0 + * @apioption legend.width + */ + /** + * The pixel padding between the legend item symbol and the legend + * item text. + * + * @sample {highcharts} highcharts/legend/symbolpadding/ + * Greater symbol width and padding + */ + symbolPadding: 5, + /** + * The vertical alignment of the legend box. Can be one of `top`, + * `middle` or `bottom`. Vertical position can be further determined + * by the `y` option. + * + * In the case that the legend is aligned in a corner position, the + * `layout` option will determine whether to place it above/below + * or on the side of the plot area. + * + * When the [layout](#legend.layout) option is `proximate`, the + * `verticalAlign` option doesn't apply. + * + * @sample {highcharts} highcharts/legend/verticalalign/ + * Legend 100px from the top of the chart + * @sample {highstock} stock/legend/align/ + * Various legend options + * @sample {highmaps} maps/legend/alignment/ + * Legend alignment + * + * @type {Highcharts.VerticalAlignValue} + * @since 2.0 + */ + verticalAlign: 'bottom', + // width: undefined, + /** + * The x offset of the legend relative to its horizontal alignment + * `align` within chart.spacingLeft and chart.spacingRight. Negative + * x moves it to the left, positive x moves it to the right. + * + * @sample {highcharts} highcharts/legend/width/ + * Aligned to the plot area + * + * @since 2.0 + */ + x: 0, + /** + * The vertical offset of the legend relative to it's vertical alignment + * `verticalAlign` within chart.spacingTop and chart.spacingBottom. + * Negative y moves it up, positive y moves it down. + * + * @sample {highcharts} highcharts/legend/verticalalign/ + * Legend 100px from the top of the chart + * @sample {highstock} stock/legend/align/ + * Various legend options + * @sample {highmaps} maps/legend/alignment/ + * Legend alignment + * + * @since 2.0 + */ + y: 0, + /** + * A title to be added on top of the legend. + * + * @sample {highcharts} highcharts/legend/title/ + * Legend title + * @sample {highmaps} maps/legend/alignment/ + * Legend with title + * + * @since 3.0 + */ + title: { + /** + * A text or HTML string for the title. + * + * @type {string} + * @since 3.0 + * @apioption legend.title.text + */ + /** + * Generic CSS styles for the legend title. + * + * @see In styled mode, the legend title is styled with the + * `.highcharts-legend-title` class. + * + * @type {Highcharts.CSSObject} + * @default {"fontWeight": "bold"} + * @since 3.0 + */ + style: { + /** + * @ignore + */ + fontWeight: 'bold' + } + } + }, + /** + * The loading options control the appearance of the loading screen + * that covers the plot area on chart operations. This screen only + * appears after an explicit call to `chart.showLoading()`. It is a + * utility for developers to communicate to the end user that something + * is going on, for example while retrieving new data via an XHR connection. + * The "Loading..." text itself is not part of this configuration + * object, but part of the `lang` object. + */ + loading: { + /** + * The duration in milliseconds of the fade out effect. + * + * @sample highcharts/loading/hideduration/ + * Fade in and out over a second + * + * @type {number} + * @default 100 + * @since 1.2.0 + * @apioption loading.hideDuration + */ + /** + * The duration in milliseconds of the fade in effect. + * + * @sample highcharts/loading/hideduration/ + * Fade in and out over a second + * + * @type {number} + * @default 100 + * @since 1.2.0 + * @apioption loading.showDuration + */ + /** + * CSS styles for the loading label `span`. + * + * @see In styled mode, the loading label is styled with the + * `.highcharts-loading-inner` class. + * + * @sample {highcharts|highmaps} highcharts/loading/labelstyle/ + * Vertically centered + * @sample {highstock} stock/loading/general/ + * Label styles + * + * @type {Highcharts.CSSObject} + * @default {"fontWeight": "bold", "position": "relative", "top": "45%"} + * @since 1.2.0 + */ + labelStyle: { + /** + * @ignore + */ + fontWeight: 'bold', + /** + * @ignore + */ + position: 'relative', + /** + * @ignore + */ + top: '45%' + }, + /** + * CSS styles for the loading screen that covers the plot area. + * + * In styled mode, the loading label is styled with the + * `.highcharts-loading` class. + * + * @sample {highcharts|highmaps} highcharts/loading/style/ + * Gray plot area, white text + * @sample {highstock} stock/loading/general/ + * Gray plot area, white text + * + * @type {Highcharts.CSSObject} + * @default {"position": "absolute", "backgroundColor": "#ffffff", "opacity": 0.5, "textAlign": "center"} + * @since 1.2.0 + */ + style: { + /** + * @ignore + */ + position: 'absolute', + /** + * @ignore + */ + backgroundColor: '#ffffff', + /** + * @ignore + */ + opacity: 0.5, + /** + * @ignore + */ + textAlign: 'center' + } + }, + /** + * Options for the tooltip that appears when the user hovers over a + * series or point. + * + * @declare Highcharts.TooltipOptions + */ + tooltip: { + /** + * The color of the tooltip border. When `undefined`, the border takes + * the color of the corresponding series or point. + * + * @sample {highcharts} highcharts/tooltip/bordercolor-default/ + * Follow series by default + * @sample {highcharts} highcharts/tooltip/bordercolor-black/ + * Black border + * @sample {highstock} stock/tooltip/general/ + * Styled tooltip + * @sample {highmaps} maps/tooltip/background-border/ + * Background and border demo + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption tooltip.borderColor + */ + /** + * A CSS class name to apply to the tooltip's container div, + * allowing unique CSS styling for each chart. + * + * @type {string} + * @apioption tooltip.className + */ + /** + * Since 4.1, the crosshair definitions are moved to the Axis object + * in order for a better separation from the tooltip. See + * [xAxis.crosshair](#xAxis.crosshair). + * + * @sample {highcharts} highcharts/tooltip/crosshairs-x/ + * Enable a crosshair for the x value + * + * @deprecated + * + * @type {*} + * @default true + * @apioption tooltip.crosshairs + */ + /** + * Distance from point to tooltip in pixels. + * + * @type {number} + * @default 16 + * @apioption tooltip.distance + */ + /** + * Whether the tooltip should follow the mouse as it moves across + * columns, pie slices and other point types with an extent. + * By default it behaves this way for pie, polygon, map, sankey + * and wordcloud series by override in the `plotOptions` + * for those series types. + * + * For touch moves to behave the same way, [followTouchMove]( + * #tooltip.followTouchMove) must be `true` also. + * + * @type {boolean} + * @default {highcharts} false + * @default {highstock} false + * @default {highmaps} true + * @since 3.0 + * @apioption tooltip.followPointer + */ + /** + * Whether the tooltip should update as the finger moves on a touch + * device. If this is `true` and [chart.panning](#chart.panning) is + * set,`followTouchMove` will take over one-finger touches, so the user + * needs to use two fingers for zooming and panning. + * + * Note the difference to [followPointer](#tooltip.followPointer) that + * only defines the _position_ of the tooltip. If `followPointer` is + * false in for example a column series, the tooltip will show above or + * below the column, but as `followTouchMove` is true, the tooltip will + * jump from column to column as the user swipes across the plot area. + * + * @type {boolean} + * @default {highcharts} true + * @default {highstock} true + * @default {highmaps} false + * @since 3.0.1 + * @apioption tooltip.followTouchMove + */ + /** + * Callback function to format the text of the tooltip from scratch. In + * case of single or [shared](#tooltip.shared) tooltips, a string should + * be returned. In case of [split](#tooltip.split) tooltips, it should + * return an array where the first item is the header, and subsequent + * items are mapped to the points. Return `false` to disable tooltip for + * a specific point on series. + * + * A subset of HTML is supported. Unless `useHTML` is true, the HTML of + * the tooltip is parsed and converted to SVG, therefore this isn't a + * complete HTML renderer. The following HTML tags are supported: `b`, + * `br`, `em`, `i`, `span`, `strong`. Spans can be styled with a `style` + * attribute, but only text-related CSS, that is shared with SVG, is + * handled. + * + * The available data in the formatter differ a bit depending on whether + * the tooltip is shared or split, or belongs to a single point. In a + * shared/split tooltip, all properties except `x`, which is common for + * all points, are kept in an array, `this.points`. + * + * Available data are: + * + * - **this.percentage (not shared) /** + * **this.points[i].percentage (shared)**: + * Stacked series and pies only. The point's percentage of the total. + * + * - **this.point (not shared) / this.points[i].point (shared)**: + * The point object. The point name, if defined, is available through + * `this.point.name`. + * + * - **this.points**: + * In a shared tooltip, this is an array containing all other + * properties for each point. + * + * - **this.series (not shared) / this.points[i].series (shared)**: + * The series object. The series name is available through + * `this.series.name`. + * + * - **this.total (not shared) / this.points[i].total (shared)**: + * Stacked series only. The total value at this point's x value. + * + * - **this.x**: + * The x value. This property is the same regardless of the tooltip + * being shared or not. + * + * - **this.y (not shared) / this.points[i].y (shared)**: + * The y value. + * + * @sample {highcharts} highcharts/tooltip/formatter-simple/ + * Simple string formatting + * @sample {highcharts} highcharts/tooltip/formatter-shared/ + * Formatting with shared tooltip + * @sample {highcharts|highstock} highcharts/tooltip/formatter-split/ + * Formatting with split tooltip + * @sample highcharts/tooltip/formatter-conditional-default/ + * Extending default formatter + * @sample {highstock} stock/tooltip/formatter/ + * Formatting with shared tooltip + * @sample {highmaps} maps/tooltip/formatter/ + * String formatting + * + * @type {Highcharts.TooltipFormatterCallbackFunction} + * @apioption tooltip.formatter + */ + /** + * Callback function to format the text of the tooltip for + * visible null points. + * Works analogously to [formatter](#tooltip.formatter). + * + * @sample highcharts/plotoptions/series-nullformat + * Format data label and tooltip for null point. + * + * @type {Highcharts.TooltipFormatterCallbackFunction} + * @apioption tooltip.nullFormatter + */ + /** + * The number of milliseconds to wait until the tooltip is hidden when + * mouse out from a point or chart. + * + * @type {number} + * @default 500 + * @since 3.0 + * @apioption tooltip.hideDelay + */ + /** + * Whether to allow the tooltip to render outside the chart's SVG + * element box. By default (`false`), the tooltip is rendered within the + * chart's SVG element, which results in the tooltip being aligned + * inside the chart area. For small charts, this may result in clipping + * or overlapping. When `true`, a separate SVG element is created and + * overlaid on the page, allowing the tooltip to be aligned inside the + * page itself. + * + * Defaults to `true` if `chart.scrollablePlotArea` is activated, + * otherwise `false`. + * + * @sample highcharts/tooltip/outside + * Small charts with tooltips outside + * + * @type {boolean|undefined} + * @default undefined + * @since 6.1.1 + * @apioption tooltip.outside + */ + /** + * A callback function for formatting the HTML output for a single point + * in the tooltip. Like the `pointFormat` string, but with more + * flexibility. + * + * @type {Highcharts.FormatterCallbackFunction} + * @since 4.1.0 + * @context Highcharts.Point + * @apioption tooltip.pointFormatter + */ + /** + * A callback function to place the tooltip in a default position. The + * callback receives three parameters: `labelWidth`, `labelHeight` and + * `point`, where point contains values for `plotX` and `plotY` telling + * where the reference point is in the plot area. Add `chart.plotLeft` + * and `chart.plotTop` to get the full coordinates. + * + * Since v7, when [tooltip.split](#tooltip.split) option is enabled, + * positioner is called for each of the boxes separately, including + * xAxis header. xAxis header is not a point, instead `point` argument + * contains info: + * `{ plotX: Number, plotY: Number, isHeader: Boolean }` + * + * + * The return should be an object containing x and y values, for example + * `{ x: 100, y: 100 }`. + * + * @sample {highcharts} highcharts/tooltip/positioner/ + * A fixed tooltip position + * @sample {highstock} stock/tooltip/positioner/ + * A fixed tooltip position on top of the chart + * @sample {highmaps} maps/tooltip/positioner/ + * A fixed tooltip position + * @sample {highstock} stock/tooltip/split-positioner/ + * Split tooltip with fixed positions + * @sample {highstock} stock/tooltip/positioner-scrollable-plotarea/ + * Scrollable plot area combined with tooltip positioner + * + * @type {Highcharts.TooltipPositionerCallbackFunction} + * @since 2.2.4 + * @apioption tooltip.positioner + */ + /** + * The name of a symbol to use for the border around the tooltip. Can + * be one of: `"callout"`, `"circle"`, or `"square"`. When + * [tooltip.split](#tooltip.split) + * option is enabled, shape is applied to all boxes except header, which + * is controlled by + * [tooltip.headerShape](#tooltip.headerShape). + * + * Custom callbacks for symbol path generation can also be added to + * `Highcharts.SVGRenderer.prototype.symbols` the same way as for + * [series.marker.symbol](plotOptions.line.marker.symbol). + * + * @type {Highcharts.TooltipShapeValue} + * @default callout + * @since 4.0 + * @apioption tooltip.shape + */ + /** + * The name of a symbol to use for the border around the tooltip + * header. Applies only when [tooltip.split](#tooltip.split) is + * enabled. + * + * Custom callbacks for symbol path generation can also be added to + * `Highcharts.SVGRenderer.prototype.symbols` the same way as for + * [series.marker.symbol](plotOptions.line.marker.symbol). + * + * @see [tooltip.shape](#tooltip.shape) + * + * @sample {highstock} stock/tooltip/split-positioner/ + * Different shapes for header and split boxes + * + * @type {Highcharts.TooltipShapeValue} + * @default callout + * @validvalue ["callout", "square"] + * @since 7.0 + * @apioption tooltip.headerShape + */ + /** + * When the tooltip is shared, the entire plot area will capture mouse + * movement or touch events. Tooltip texts for series types with ordered + * data (not pie, scatter, flags etc) will be shown in a single bubble. + * This is recommended for single series charts and for tablet/mobile + * optimized charts. + * + * See also [tooltip.split](#tooltip.split), that is better suited for + * charts with many series, especially line-type series. The + * `tooltip.split` option takes precedence over `tooltip.shared`. + * + * @sample {highcharts} highcharts/tooltip/shared-false/ + * False by default + * @sample {highcharts} highcharts/tooltip/shared-true/ + * True + * @sample {highcharts} highcharts/tooltip/shared-x-crosshair/ + * True with x axis crosshair + * @sample {highcharts} highcharts/tooltip/shared-true-mixed-types/ + * True with mixed series types + * + * @type {boolean} + * @default false + * @since 2.1 + * @product highcharts highstock + * @apioption tooltip.shared + */ + /** + * Split the tooltip into one label per series, with the header close + * to the axis. This is recommended over [shared](#tooltip.shared) + * tooltips for charts with multiple line series, generally making them + * easier to read. This option takes precedence over `tooltip.shared`. + * + * @productdesc {highstock} In Highstock, tooltips are split by default + * since v6.0.0. Stock charts typically contain multi-dimension points + * and multiple panes, making split tooltips the preferred layout over + * the previous `shared` tooltip. + * + * @sample highcharts/tooltip/split/ + * Split tooltip + * @sample {highcharts|highstock} highcharts/tooltip/formatter-split/ + * Split tooltip and custom formatter callback + * + * @type {boolean} + * @default {highcharts} false + * @default {highstock} true + * @since 5.0.0 + * @product highcharts highstock + * @apioption tooltip.split + */ + /** + * Prevents the tooltip from switching or closing, when touched or + * pointed. + * + * @sample highcharts/tooltip/stickoncontact/ + * Tooltip sticks on pointer contact + * + * @type {boolean} + * @since 8.0.1 + * @apioption tooltip.stickOnContact + */ + /** + * Use HTML to render the contents of the tooltip instead of SVG. Using + * HTML allows advanced formatting like tables and images in the + * tooltip. It is also recommended for rtl languages as it works around + * rtl bugs in early Firefox. + * + * @sample {highcharts|highstock} highcharts/tooltip/footerformat/ + * A table for value alignment + * @sample {highcharts|highstock} highcharts/tooltip/fullhtml/ + * Full HTML tooltip + * @sample {highmaps} maps/tooltip/usehtml/ + * Pure HTML tooltip + * + * @type {boolean} + * @default false + * @since 2.2 + * @apioption tooltip.useHTML + */ + /** + * How many decimals to show in each series' y value. This is + * overridable in each series' tooltip options object. The default is to + * preserve all decimals. + * + * @sample {highcharts|highstock} highcharts/tooltip/valuedecimals/ + * Set decimals, prefix and suffix for the value + * @sample {highmaps} maps/tooltip/valuedecimals/ + * Set decimals, prefix and suffix for the value + * + * @type {number} + * @since 2.2 + * @apioption tooltip.valueDecimals + */ + /** + * A string to prepend to each series' y value. Overridable in each + * series' tooltip options object. + * + * @sample {highcharts|highstock} highcharts/tooltip/valuedecimals/ + * Set decimals, prefix and suffix for the value + * @sample {highmaps} maps/tooltip/valuedecimals/ + * Set decimals, prefix and suffix for the value + * + * @type {string} + * @since 2.2 + * @apioption tooltip.valuePrefix + */ + /** + * A string to append to each series' y value. Overridable in each + * series' tooltip options object. + * + * @sample {highcharts|highstock} highcharts/tooltip/valuedecimals/ + * Set decimals, prefix and suffix for the value + * @sample {highmaps} maps/tooltip/valuedecimals/ + * Set decimals, prefix and suffix for the value + * + * @type {string} + * @since 2.2 + * @apioption tooltip.valueSuffix + */ + /** + * The format for the date in the tooltip header if the X axis is a + * datetime axis. The default is a best guess based on the smallest + * distance between points in the chart. + * + * @sample {highcharts} highcharts/tooltip/xdateformat/ + * A different format + * + * @type {string} + * @product highcharts highstock gantt + * @apioption tooltip.xDateFormat + */ + /** + * How many decimals to show for the `point.change` value when the + * `series.compare` option is set. This is overridable in each series' + * tooltip options object. The default is to preserve all decimals. + * + * @type {number} + * @since 1.0.1 + * @product highstock + * @apioption tooltip.changeDecimals + */ + /** + * Enable or disable the tooltip. + * + * @sample {highcharts} highcharts/tooltip/enabled/ + * Disabled + * @sample {highcharts} highcharts/plotoptions/series-point-events-mouseover/ + * Disable tooltip and show values on chart instead + */ + enabled: true, + /** + * Enable or disable animation of the tooltip. + * + * @type {boolean} + * @default true + * @since 2.3.0 + */ + animation: svg, + /** + * The radius of the rounded border corners. + * + * @sample {highcharts} highcharts/tooltip/bordercolor-default/ + * 5px by default + * @sample {highcharts} highcharts/tooltip/borderradius-0/ + * Square borders + * @sample {highmaps} maps/tooltip/background-border/ + * Background and border demo + */ + borderRadius: 3, + /** + * For series on a datetime axes, the date format in the tooltip's + * header will by default be guessed based on the closest data points. + * This member gives the default string representations used for + * each unit. For an overview of the replacement codes, see + * [dateFormat](/class-reference/Highcharts#dateFormat). + * + * @see [xAxis.dateTimeLabelFormats](#xAxis.dateTimeLabelFormats) + * + * @type {Highcharts.Dictionary} + * @product highcharts highstock gantt + */ + dateTimeLabelFormats: { + /** @internal */ + millisecond: '%A, %b %e, %H:%M:%S.%L', + /** @internal */ + second: '%A, %b %e, %H:%M:%S', + /** @internal */ + minute: '%A, %b %e, %H:%M', + /** @internal */ + hour: '%A, %b %e, %H:%M', + /** @internal */ + day: '%A, %b %e, %Y', + /** @internal */ + week: 'Week from %A, %b %e, %Y', + /** @internal */ + month: '%B %Y', + /** @internal */ + year: '%Y' + }, + /** + * A string to append to the tooltip format. + * + * @sample {highcharts} highcharts/tooltip/footerformat/ + * A table for value alignment + * @sample {highmaps} maps/tooltip/format/ + * Format demo + * + * @since 2.2 + */ + footerFormat: '', + /** + * Padding inside the tooltip, in pixels. + * + * @since 5.0.0 + */ + padding: 8, + /** + * Proximity snap for graphs or single points. It defaults to 10 for + * mouse-powered devices and 25 for touch devices. + * + * Note that in most cases the whole plot area captures the mouse + * movement, and in these cases `tooltip.snap` doesn't make sense. This + * applies when [stickyTracking](#plotOptions.series.stickyTracking) + * is `true` (default) and when the tooltip is [shared](#tooltip.shared) + * or [split](#tooltip.split). + * + * @sample {highcharts} highcharts/tooltip/bordercolor-default/ + * 10 px by default + * @sample {highcharts} highcharts/tooltip/snap-50/ + * 50 px on graph + * + * @type {number} + * @default 10/25 + * @since 1.2.0 + * @product highcharts highstock + */ + snap: isTouchDevice ? 25 : 10, + /** + * The HTML of the tooltip header line. Variables are enclosed by + * curly brackets. Available variables are `point.key`, `series.name`, + * `series.color` and other members from the `point` and `series` + * objects. The `point.key` variable contains the category name, x + * value or datetime string depending on the type of axis. For datetime + * axes, the `point.key` date format can be set using + * `tooltip.xDateFormat`. + * + * @sample {highcharts} highcharts/tooltip/footerformat/ + * An HTML table in the tooltip + * @sample {highstock} highcharts/tooltip/footerformat/ + * An HTML table in the tooltip + * @sample {highmaps} maps/tooltip/format/ + * Format demo + * + * @type {string} + * @apioption tooltip.headerFormat + */ + headerFormat: '{point.key}
', + /** + * The HTML of the null point's line in the tooltip. Works analogously + * to [pointFormat](#tooltip.pointFormat). + * + * @sample {highcharts} highcharts/plotoptions/series-nullformat + * Format data label and tooltip for null point. + * + * @type {string} + * @apioption tooltip.nullFormat + */ + /** + * The HTML of the point's line in the tooltip. Variables are enclosed + * by curly brackets. Available variables are point.x, point.y, series. + * name and series.color and other properties on the same form. + * Furthermore, `point.y` can be extended by the `tooltip.valuePrefix` + * and `tooltip.valueSuffix` variables. This can also be overridden for + * each series, which makes it a good hook for displaying units. + * + * In styled mode, the dot is colored by a class name rather + * than the point color. + * + * @sample {highcharts} highcharts/tooltip/pointformat/ + * A different point format with value suffix + * @sample {highmaps} maps/tooltip/format/ + * Format demo + * + * @type {string} + * @since 2.2 + * @apioption tooltip.pointFormat + */ + pointFormat: '\u25CF {series.name}: {point.y}
', + /** + * The background color or gradient for the tooltip. + * + * In styled mode, the stroke width is set in the + * `.highcharts-tooltip-box` class. + * + * @sample {highcharts} highcharts/tooltip/backgroundcolor-solid/ + * Yellowish background + * @sample {highcharts} highcharts/tooltip/backgroundcolor-gradient/ + * Gradient + * @sample {highcharts} highcharts/css/tooltip-border-background/ + * Tooltip in styled mode + * @sample {highstock} stock/tooltip/general/ + * Custom tooltip + * @sample {highstock} highcharts/css/tooltip-border-background/ + * Tooltip in styled mode + * @sample {highmaps} maps/tooltip/background-border/ + * Background and border demo + * @sample {highmaps} highcharts/css/tooltip-border-background/ + * Tooltip in styled mode + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + backgroundColor: color('#f7f7f7') + .setOpacity(0.85).get(), + /** + * The pixel width of the tooltip border. + * + * In styled mode, the stroke width is set in the + * `.highcharts-tooltip-box` class. + * + * @sample {highcharts} highcharts/tooltip/bordercolor-default/ + * 2px by default + * @sample {highcharts} highcharts/tooltip/borderwidth/ + * No border (shadow only) + * @sample {highcharts} highcharts/css/tooltip-border-background/ + * Tooltip in styled mode + * @sample {highstock} stock/tooltip/general/ + * Custom tooltip + * @sample {highstock} highcharts/css/tooltip-border-background/ + * Tooltip in styled mode + * @sample {highmaps} maps/tooltip/background-border/ + * Background and border demo + * @sample {highmaps} highcharts/css/tooltip-border-background/ + * Tooltip in styled mode + */ + borderWidth: 1, + /** + * Whether to apply a drop shadow to the tooltip. + * + * @sample {highcharts} highcharts/tooltip/bordercolor-default/ + * True by default + * @sample {highcharts} highcharts/tooltip/shadow/ + * False + * @sample {highmaps} maps/tooltip/positioner/ + * Fixed tooltip position, border and shadow disabled + * + * @type {boolean|Highcharts.ShadowOptionsObject} + */ + shadow: true, + /** + * CSS styles for the tooltip. The tooltip can also be styled through + * the CSS class `.highcharts-tooltip`. + * + * Note that the default `pointerEvents` style makes the tooltip ignore + * mouse events, so in order to use clickable tooltips, this value must + * be set to `auto`. + * + * @sample {highcharts} highcharts/tooltip/style/ + * Greater padding, bold text + * + * @type {Highcharts.CSSObject} + */ + style: { + /** @internal */ + color: '#333333', + /** @internal */ + cursor: 'default', + /** @internal */ + fontSize: '12px', + /** @internal */ + whiteSpace: 'nowrap' + } + }, + /** + * Highchart by default puts a credits label in the lower right corner + * of the chart. This can be changed using these options. + */ + credits: { + /** + * Credits for map source to be concatenated with conventional credit + * text. By default this is a format string that collects copyright + * information from the map if available. + * + * @see [mapTextFull](#credits.mapTextFull) + * @see [text](#credits.text) + * + * @type {string} + * @default \u00a9
{geojson.copyrightShort} + * @since 4.2.2 + * @product highmaps + * @apioption credits.mapText + */ + /** + * Detailed credits for map source to be displayed on hover of credits + * text. By default this is a format string that collects copyright + * information from the map if available. + * + * @see [mapText](#credits.mapText) + * @see [text](#credits.text) + * + * @type {string} + * @default {geojson.copyright} + * @since 4.2.2 + * @product highmaps + * @apioption credits.mapTextFull + */ + /** + * Whether to show the credits text. + * + * @sample {highcharts} highcharts/credits/enabled-false/ + * Credits disabled + * @sample {highstock} stock/credits/enabled/ + * Credits disabled + * @sample {highmaps} maps/credits/enabled-false/ + * Credits disabled + */ + enabled: true, + /** + * The URL for the credits label. + * + * @sample {highcharts} highcharts/credits/href/ + * Custom URL and text + * @sample {highmaps} maps/credits/customized/ + * Custom URL and text + */ + href: 'https://www.highcharts.com?credits', + /** + * Position configuration for the credits label. + * + * @sample {highcharts} highcharts/credits/position-left/ + * Left aligned + * @sample {highcharts} highcharts/credits/position-left/ + * Left aligned + * @sample {highmaps} maps/credits/customized/ + * Left aligned + * @sample {highmaps} maps/credits/customized/ + * Left aligned + * + * @type {Highcharts.AlignObject} + * @since 2.1 + */ + position: { + /** @internal */ + align: 'right', + /** @internal */ + x: -10, + /** @internal */ + verticalAlign: 'bottom', + /** @internal */ + y: -5 + }, + /** + * CSS styles for the credits label. + * + * @see In styled mode, credits styles can be set with the + * `.highcharts-credits` class. + * + * @type {Highcharts.CSSObject} + */ + style: { + /** @internal */ + cursor: 'pointer', + /** @internal */ + color: '#999999', + /** @internal */ + fontSize: '9px' + }, + /** + * The text for the credits label. + * + * @productdesc {highmaps} + * If a map is loaded as GeoJSON, the text defaults to + * `Highcharts @ {map-credits}`. Otherwise, it defaults to + * `Highcharts.com`. + * + * @sample {highcharts} highcharts/credits/href/ + * Custom URL and text + * @sample {highmaps} maps/credits/customized/ + * Custom URL and text + */ + text: 'Highcharts.com' + } + }; + /** + * Merge the default options with custom options and return the new options + * structure. Commonly used for defining reusable templates. + * + * @sample highcharts/global/useutc-false Setting a global option + * @sample highcharts/members/setoptions Applying a global theme + * + * @function Highcharts.setOptions + * + * @param {Highcharts.Options} options + * The new custom chart options. + * + * @return {Highcharts.Options} + * Updated options. + */ + H.setOptions = function (options) { + // Copy in the default options + H.defaultOptions = merge(true, H.defaultOptions, options); + // Update the time object + if (options.time || options.global) { + H.time.update(merge(H.defaultOptions.global, H.defaultOptions.time, options.global, options.time)); + } + return H.defaultOptions; + }; + /** + * Get the updated default options. Until 3.0.7, merely exposing defaultOptions + * for outside modules wasn't enough because the setOptions method created a new + * object. + * + * @function Highcharts.getOptions + * + * @return {Highcharts.Options} + */ + H.getOptions = function () { + return H.defaultOptions; + }; + // Series defaults + H.defaultPlotOptions = H.defaultOptions.plotOptions; + /** + * Global `Time` object with default options. Since v6.0.5, time settings can be + * applied individually for each chart. If no individual settings apply, this + * `Time` object is shared by all instances. + * + * @name Highcharts.time + * @type {Highcharts.Time} + */ + H.time = new Time(merge(H.defaultOptions.global, H.defaultOptions.time)); + /** + * Formats a JavaScript date timestamp (milliseconds since Jan 1st 1970) into a + * human readable date string. The format is a subset of the formats for PHP's + * [strftime](https://www.php.net/manual/en/function.strftime.php) function. + * Additional formats can be given in the {@link Highcharts.dateFormats} hook. + * + * Since v6.0.5, all internal dates are formatted through the + * {@link Highcharts.Chart#time} instance to respect chart-level time settings. + * The `Highcharts.dateFormat` function only reflects global time settings set + * with `setOptions`. + * + * Supported format keys: + * - `%a`: Short weekday, like 'Mon' + * - `%A`: Long weekday, like 'Monday' + * - `%d`: Two digit day of the month, 01 to 31 + * - `%e`: Day of the month, 1 through 31 + * - `%w`: Day of the week, 0 through 6 + * - `%b`: Short month, like 'Jan' + * - `%B`: Long month, like 'January' + * - `%m`: Two digit month number, 01 through 12 + * - `%y`: Two digits year, like 09 for 2009 + * - `%Y`: Four digits year, like 2009 + * - `%H`: Two digits hours in 24h format, 00 through 23 + * - `%k`: Hours in 24h format, 0 through 23 + * - `%I`: Two digits hours in 12h format, 00 through 11 + * - `%l`: Hours in 12h format, 1 through 12 + * - `%M`: Two digits minutes, 00 through 59 + * - `%p`: Upper case AM or PM + * - `%P`: Lower case AM or PM + * - `%S`: Two digits seconds, 00 through 59 + * - `%L`: Milliseconds (naming from Ruby) + * + * @function Highcharts.dateFormat + * + * @param {string} format + * The desired format where various time representations are prefixed + * with `%`. + * + * @param {number} timestamp + * The JavaScript timestamp. + * + * @param {boolean} [capitalize=false] + * Upper case first letter in the return. + * + * @return {string} + * The formatted date. + */ + H.dateFormat = function (format, timestamp, capitalize) { + return H.time.dateFormat(format, timestamp, capitalize); + }; + /* eslint-disable spaced-comment */ + + ''; + + }); + _registerModule(_modules, 'parts/Axis.js', [_modules['parts/Color.js'], _modules['parts/Globals.js'], _modules['parts/Tick.js'], _modules['parts/Utilities.js']], function (Color, H, Tick, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, animObject = U.animObject, arrayMax = U.arrayMax, arrayMin = U.arrayMin, clamp = U.clamp, correctFloat = U.correctFloat, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, error = U.error, extend = U.extend, fireEvent = U.fireEvent, format = U.format, getMagnitude = U.getMagnitude, isArray = U.isArray, isFunction = U.isFunction, isNumber = U.isNumber, isString = U.isString, merge = U.merge, normalizeTickInterval = U.normalizeTickInterval, objectEach = U.objectEach, pick = U.pick, relativeLength = U.relativeLength, removeEvent = U.removeEvent, splat = U.splat, syncTimeout = U.syncTimeout; + /** + * Options for the path on the Axis to be calculated. + * @interface Highcharts.AxisPlotLinePathOptionsObject + */ /** + * Axis value. + * @name Highcharts.AxisPlotLinePathOptionsObject#value + * @type {number|undefined} + */ /** + * Line width used for calculation crisp line coordinates. Defaults to 1. + * @name Highcharts.AxisPlotLinePathOptionsObject#lineWidth + * @type {number|undefined} + */ /** + * If `false`, the function will return null when it falls outside the axis + * bounds. If `true`, the function will return a path aligned to the plot area + * sides if it falls outside. If `pass`, it will return a path outside. + * @name Highcharts.AxisPlotLinePathOptionsObject#force + * @type {string|boolean|undefined} + */ /** + * Used in Highstock. When `true`, plot paths (crosshair, plotLines, gridLines) + * will be rendered on all axes when defined on the first axis. + * @name Highcharts.AxisPlotLinePathOptionsObject#acrossPanes + * @type {boolean|undefined} + */ /** + * Use old coordinates (for resizing and rescaling). + * If not set, defaults to `false`. + * @name Highcharts.AxisPlotLinePathOptionsObject#old + * @type {boolean|undefined} + */ /** + * If given, return the plot line path of a pixel position on the axis. + * @name Highcharts.AxisPlotLinePathOptionsObject#translatedValue + * @type {number|undefined} + */ /** + * Used in Polar axes. Reverse the positions for concatenation of polygonal + * plot bands + * @name Highcharts.AxisPlotLinePathOptionsObject#reverse + * @type {boolean|undefined} + */ + /** + * Options for crosshairs on axes. + * + * @product highstock + * + * @typedef {Highcharts.XAxisCrosshairOptions|Highcharts.YAxisCrosshairOptions} Highcharts.AxisCrosshairOptions + */ + /** + * @typedef {"navigator"|"pan"|"rangeSelectorButton"|"rangeSelectorInput"|"scrollbar"|"traverseUpButton"|"zoom"} Highcharts.AxisExtremesTriggerValue + */ + /** + * @callback Highcharts.AxisEventCallbackFunction + * + * @param {Highcharts.Axis} this + */ + /** + * @interface Highcharts.AxisLabelsFormatterContextObject + */ /** + * @name Highcharts.AxisLabelsFormatterContextObject#axis + * @type {Highcharts.Axis} + */ /** + * @name Highcharts.AxisLabelsFormatterContextObject#chart + * @type {Highcharts.Chart} + */ /** + * @name Highcharts.AxisLabelsFormatterContextObject#isFirst + * @type {boolean} + */ /** + * @name Highcharts.AxisLabelsFormatterContextObject#isLast + * @type {boolean} + */ /** + * @name Highcharts.AxisLabelsFormatterContextObject#pos + * @type {number} + */ /** + * @name Highcharts.AxisLabelsFormatterContextObject#value + * @type {number} + */ + /** + * Options for axes. + * + * @typedef {Highcharts.XAxisOptions|Highcharts.YAxisOptions|Highcharts.ZAxisOptions} Highcharts.AxisOptions + */ + /** + * @callback Highcharts.AxisPointBreakEventCallbackFunction + * + * @param {Highcharts.Axis} this + * + * @param {Highcharts.AxisPointBreakEventObject} evt + */ + /** + * @interface Highcharts.AxisPointBreakEventObject + */ /** + * @name Highcharts.AxisPointBreakEventObject#brk + * @type {Highcharts.Dictionary} + */ /** + * @name Highcharts.AxisPointBreakEventObject#point + * @type {Highcharts.Point} + */ /** + * @name Highcharts.AxisPointBreakEventObject#preventDefault + * @type {Function} + */ /** + * @name Highcharts.AxisPointBreakEventObject#target + * @type {Highcharts.SVGElement} + */ /** + * @name Highcharts.AxisPointBreakEventObject#type + * @type {"pointBreak"|"pointInBreak"} + */ + /** + * @callback Highcharts.AxisSetExtremesEventCallbackFunction + * + * @param {Highcharts.Axis} this + * + * @param {Highcharts.AxisSetExtremesEventObject} evt + */ + /** + * @interface Highcharts.AxisSetExtremesEventObject + * @extends Highcharts.ExtremesObject + */ /** + * @name Highcharts.AxisSetExtremesEventObject#preventDefault + * @type {Function} + */ /** + * @name Highcharts.AxisSetExtremesEventObject#target + * @type {Highcharts.SVGElement} + */ /** + * @name Highcharts.AxisSetExtremesEventObject#trigger + * @type {Highcharts.AxisExtremesTriggerValue|string} + */ /** + * @name Highcharts.AxisSetExtremesEventObject#type + * @type {"setExtremes"} + */ + /** + * @callback Highcharts.AxisTickPositionerCallbackFunction + * + * @param {Highcharts.Axis} this + * + * @return {Array} + */ + /** + * @interface Highcharts.AxisTickPositionsArray + * @augments Array + */ + /** + * @typedef {"high"|"low"|"middle"} Highcharts.AxisTitleAlignValue + */ + /** + * @typedef {Highcharts.XAxisTitleOptions|Highcharts.YAxisTitleOptions|Highcharts.ZAxisTitleOptions} Highcharts.AxisTitleOptions + */ + /** + * @typedef {"linear"|"logarithmic"|"datetime"|"category"|"treegrid"} Highcharts.AxisTypeValue + */ + /** + * The returned object literal from the {@link Highcharts.Axis#getExtremes} + * function. + * + * @interface Highcharts.ExtremesObject + */ /** + * The maximum value of the axis' associated series. + * @name Highcharts.ExtremesObject#dataMax + * @type {number} + */ /** + * The minimum value of the axis' associated series. + * @name Highcharts.ExtremesObject#dataMin + * @type {number} + */ /** + * The maximum axis value, either automatic or set manually. If the `max` option + * is not set, `maxPadding` is 0 and `endOnTick` is false, this value will be + * the same as `dataMax`. + * @name Highcharts.ExtremesObject#max + * @type {number} + */ /** + * The minimum axis value, either automatic or set manually. If the `min` option + * is not set, `minPadding` is 0 and `startOnTick` is false, this value will be + * the same as `dataMin`. + * @name Highcharts.ExtremesObject#min + * @type {number} + */ /** + * The user defined maximum, either from the `max` option or from a zoom or + * `setExtremes` action. + * @name Highcharts.ExtremesObject#userMax + * @type {number} + */ /** + * The user defined minimum, either from the `min` option or from a zoom or + * `setExtremes` action. + * @name Highcharts.ExtremesObject#userMin + * @type {number} + */ + /** + * Formatter function for the text of a crosshair label. + * + * @callback Highcharts.XAxisCrosshairLabelFormatterCallbackFunction + * + * @param {Highcharts.Axis} this + * Axis context + * + * @param {number} value + * Y value of the data point + * + * @return {string} + */ + var defaultOptions = H.defaultOptions, deg2rad = H.deg2rad; + /** + * Create a new axis object. Called internally when instanciating a new chart or + * adding axes by {@link Highcharts.Chart#addAxis}. + * + * A chart can have from 0 axes (pie chart) to multiples. In a normal, single + * series cartesian chart, there is one X axis and one Y axis. + * + * The X axis or axes are referenced by {@link Highcharts.Chart.xAxis}, which is + * an array of Axis objects. If there is only one axis, it can be referenced + * through `chart.xAxis[0]`, and multiple axes have increasing indices. The same + * pattern goes for Y axes. + * + * If you need to get the axes from a series object, use the `series.xAxis` and + * `series.yAxis` properties. These are not arrays, as one series can only be + * associated to one X and one Y axis. + * + * A third way to reference the axis programmatically is by `id`. Add an `id` in + * the axis configuration options, and get the axis by + * {@link Highcharts.Chart#get}. + * + * Configuration options for the axes are given in options.xAxis and + * options.yAxis. + * + * @class + * @name Highcharts.Axis + * + * @param {Highcharts.Chart} chart + * The Chart instance to apply the axis on. + * + * @param {Highcharts.AxisOptions} userOptions + * Axis options. + */ + var Axis = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Axis(chart, userOptions) { + this.alternateBands = void 0; + this.bottom = void 0; + this.categories = void 0; + this.chart = void 0; + this.closestPointRange = void 0; + this.coll = void 0; + this.hasNames = void 0; + this.hasVisibleSeries = void 0; + this.height = void 0; + this.isLinked = void 0; + this.labelEdge = void 0; // @todo + this.labelFormatter = void 0; + this.left = void 0; + this.len = void 0; + this.max = void 0; + this.maxLabelLength = void 0; + this.min = void 0; + this.minorTickInterval = void 0; + this.minorTicks = void 0; + this.minPixelPadding = void 0; + this.names = void 0; + this.offset = void 0; + this.oldMax = void 0; + this.oldMin = void 0; + this.options = void 0; + this.overlap = void 0; + this.paddedTicks = void 0; + this.plotLinesAndBands = void 0; + this.plotLinesAndBandsGroups = void 0; + this.pointRange = void 0; + this.pointRangePadding = void 0; + this.pos = void 0; + this.positiveValuesOnly = void 0; + this.right = void 0; + this.series = void 0; + this.side = void 0; + this.tickAmount = void 0; + this.tickInterval = void 0; + this.tickmarkOffset = void 0; + this.tickPositions = void 0; + this.tickRotCorr = void 0; + this.ticks = void 0; + this.top = void 0; + this.transA = void 0; + this.transB = void 0; + this.translationSlope = void 0; + this.userOptions = void 0; + this.visible = void 0; + this.width = void 0; + this.zoomEnabled = void 0; + this.init(chart, userOptions); + } + /* * + * + * Functions + * + * */ + /** + * Overrideable function to initialize the axis. + * + * @see {@link Axis} + * + * @function Highcharts.Axis#init + * + * @param {Highcharts.Chart} chart + * The Chart instance to apply the axis on. + * + * @param {Highcharts.AxisOptions} userOptions + * Axis options. + * + * @fires Highcharts.Axis#event:afterInit + * @fires Highcharts.Axis#event:init + */ + Axis.prototype.init = function (chart, userOptions) { + var isXAxis = userOptions.isX, axis = this; + /** + * The Chart that the axis belongs to. + * + * @name Highcharts.Axis#chart + * @type {Highcharts.Chart} + */ + axis.chart = chart; + /** + * Whether the axis is horizontal. + * + * @name Highcharts.Axis#horiz + * @type {boolean|undefined} + */ + axis.horiz = chart.inverted && !axis.isZAxis ? !isXAxis : isXAxis; + /** + * Whether the axis is the x-axis. + * + * @name Highcharts.Axis#isXAxis + * @type {boolean|undefined} + */ + axis.isXAxis = isXAxis; + /** + * The collection where the axis belongs, for example `xAxis`, `yAxis` + * or `colorAxis`. Corresponds to properties on Chart, for example + * {@link Chart.xAxis}. + * + * @name Highcharts.Axis#coll + * @type {string} + */ + axis.coll = axis.coll || (isXAxis ? 'xAxis' : 'yAxis'); + fireEvent(this, 'init', { userOptions: userOptions }); + axis.opposite = userOptions.opposite; // needed in setOptions + /** + * The side on which the axis is rendered. 0 is top, 1 is right, 2 + * is bottom and 3 is left. + * + * @name Highcharts.Axis#side + * @type {number} + */ + axis.side = userOptions.side || (axis.horiz ? + (axis.opposite ? 0 : 2) : // top : bottom + (axis.opposite ? 1 : 3)); // right : left + /** + * Current options for the axis after merge of defaults and user's + * options. + * + * @name Highcharts.Axis#options + * @type {Highcharts.AxisOptions} + */ + axis.setOptions(userOptions); + var options = this.options, type = options.type; + axis.labelFormatter = (options.labels.formatter || + // can be overwritten by dynamic format + axis.defaultLabelFormatter); + /** + * User's options for this axis without defaults. + * + * @name Highcharts.Axis#userOptions + * @type {Highcharts.AxisOptions} + */ + axis.userOptions = userOptions; + axis.minPixelPadding = 0; + /** + * Whether the axis is reversed. Based on the `axis.reversed`, + * option, but inverted charts have reversed xAxis by default. + * + * @name Highcharts.Axis#reversed + * @type {boolean} + */ + axis.reversed = options.reversed; + axis.visible = options.visible !== false; + axis.zoomEnabled = options.zoomEnabled !== false; + // Initial categories + axis.hasNames = + type === 'category' || options.categories === true; + /** + * If categories are present for the axis, names are used instead of + * numbers for that axis. + * + * Since Highcharts 3.0, categories can also be extracted by giving each + * point a name and setting axis type to `category`. However, if you + * have multiple series, best practice remains defining the `categories` + * array. + * + * @see [xAxis.categories](/highcharts/xAxis.categories) + * + * @name Highcharts.Axis#categories + * @type {Array} + * @readonly + */ + axis.categories = options.categories || axis.hasNames; + if (!axis.names) { // Preserve on update (#3830) + axis.names = []; + axis.names.keys = {}; + } + // Placeholder for plotlines and plotbands groups + axis.plotLinesAndBandsGroups = {}; + // Shorthand types + axis.positiveValuesOnly = !!(axis.logarithmic && !options.allowNegativeLog); + // Flag, if axis is linked to another axis + axis.isLinked = defined(options.linkedTo); + /** + * List of major ticks mapped by postition on axis. + * + * @see {@link Highcharts.Tick} + * + * @name Highcharts.Axis#ticks + * @type {Highcharts.Dictionary} + */ + axis.ticks = {}; + axis.labelEdge = []; + /** + * List of minor ticks mapped by position on the axis. + * + * @see {@link Highcharts.Tick} + * + * @name Highcharts.Axis#minorTicks + * @type {Highcharts.Dictionary} + */ + axis.minorTicks = {}; + // List of plotLines/Bands + axis.plotLinesAndBands = []; + // Alternate bands + axis.alternateBands = {}; + // Axis metrics + axis.len = 0; + axis.minRange = axis.userMinRange = options.minRange || options.maxZoom; + axis.range = options.range; + axis.offset = options.offset || 0; + /** + * The maximum value of the axis. In a logarithmic axis, this is the + * logarithm of the real value, and the real value can be obtained from + * {@link Axis#getExtremes}. + * + * @name Highcharts.Axis#max + * @type {number|null} + */ + axis.max = null; + /** + * The minimum value of the axis. In a logarithmic axis, this is the + * logarithm of the real value, and the real value can be obtained from + * {@link Axis#getExtremes}. + * + * @name Highcharts.Axis#min + * @type {number|null} + */ + axis.min = null; + /** + * The processed crosshair options. + * + * @name Highcharts.Axis#crosshair + * @type {boolean|Highcharts.AxisCrosshairOptions} + */ + axis.crosshair = pick(options.crosshair, splat(chart.options.tooltip.crosshairs)[isXAxis ? 0 : 1], false); + var events = axis.options.events; + // Register. Don't add it again on Axis.update(). + if (chart.axes.indexOf(axis) === -1) { // + if (isXAxis) { // #2713 + chart.axes.splice(chart.xAxis.length, 0, axis); + } + else { + chart.axes.push(axis); + } + chart[axis.coll].push(axis); + } + /** + * All series associated to the axis. + * + * @name Highcharts.Axis#series + * @type {Array} + */ + axis.series = axis.series || []; // populated by Series + // Reversed axis + if (chart.inverted && + !axis.isZAxis && + isXAxis && + typeof axis.reversed === 'undefined') { + axis.reversed = true; + } + axis.labelRotation = axis.options.labels.rotation; + // register event listeners + objectEach(events, function (event, eventType) { + if (isFunction(event)) { + addEvent(axis, eventType, event); + } + }); + fireEvent(this, 'afterInit'); + }; + /** + * Merge and set options. + * + * @private + * @function Highcharts.Axis#setOptions + * + * @param {Highcharts.AxisOptions} userOptions + * Axis options. + * + * @fires Highcharts.Axis#event:afterSetOptions + */ + Axis.prototype.setOptions = function (userOptions) { + this.options = merge(Axis.defaultOptions, (this.coll === 'yAxis') && Axis.defaultYAxisOptions, [ + Axis.defaultTopAxisOptions, + Axis.defaultRightAxisOptions, + Axis.defaultBottomAxisOptions, + Axis.defaultLeftAxisOptions + ][this.side], merge( + // if set in setOptions (#1053): + defaultOptions[this.coll], userOptions)); + fireEvent(this, 'afterSetOptions', { userOptions: userOptions }); + }; + /** + * The default label formatter. The context is a special config object for + * the label. In apps, use the + * [labels.formatter](https://api.highcharts.com/highcharts/xAxis.labels.formatter) + * instead, except when a modification is needed. + * + * @function Highcharts.Axis#defaultLabelFormatter + * + * @param {Highcharts.AxisLabelsFormatterContextObject} this + * Formatter context of axis label. + * + * @return {string} + * The formatted label content. + */ + Axis.prototype.defaultLabelFormatter = function () { + var axis = this.axis, value = this.value, time = axis.chart.time, categories = axis.categories, dateTimeLabelFormat = this.dateTimeLabelFormat, lang = defaultOptions.lang, numericSymbols = lang.numericSymbols, numSymMagnitude = lang.numericSymbolMagnitude || 1000, i = numericSymbols && numericSymbols.length, multi, ret, formatOption = axis.options.labels.format, + // make sure the same symbol is added for all labels on a linear + // axis + numericSymbolDetector = axis.logarithmic ? + Math.abs(value) : + axis.tickInterval; + var chart = this.chart; + var numberFormatter = chart.numberFormatter; + if (formatOption) { + ret = format(formatOption, this, chart); + } + else if (categories) { + ret = value; + } + else if (dateTimeLabelFormat) { // datetime axis + ret = time.dateFormat(dateTimeLabelFormat, value); + } + else if (i && numericSymbolDetector >= 1000) { + // Decide whether we should add a numeric symbol like k (thousands) + // or M (millions). If we are to enable this in tooltip or other + // places as well, we can move this logic to the numberFormatter and + // enable it by a parameter. + while (i-- && typeof ret === 'undefined') { + multi = Math.pow(numSymMagnitude, i + 1); + if ( + // Only accept a numeric symbol when the distance is more + // than a full unit. So for example if the symbol is k, we + // don't accept numbers like 0.5k. + numericSymbolDetector >= multi && + // Accept one decimal before the symbol. Accepts 0.5k but + // not 0.25k. How does this work with the previous? + (value * 10) % multi === 0 && + numericSymbols[i] !== null && + value !== 0) { // #5480 + ret = numberFormatter(value / multi, -1) + + numericSymbols[i]; + } + } + } + if (typeof ret === 'undefined') { + if (Math.abs(value) >= 10000) { // add thousands separators + ret = numberFormatter(value, -1); + } + else { // small numbers + ret = numberFormatter(value, -1, void 0, ''); // #2466 + } + } + return ret; + }; + /** + * Get the minimum and maximum for the series of each axis. The function + * analyzes the axis series and updates `this.dataMin` and `this.dataMax`. + * + * @private + * @function Highcharts.Axis#getSeriesExtremes + * + * @fires Highcharts.Axis#event:afterGetSeriesExtremes + * @fires Highcharts.Axis#event:getSeriesExtremes + */ + Axis.prototype.getSeriesExtremes = function () { + var axis = this, chart = axis.chart, xExtremes; + fireEvent(this, 'getSeriesExtremes', null, function () { + axis.hasVisibleSeries = false; + // Reset properties in case we're redrawing (#3353) + axis.dataMin = axis.dataMax = axis.threshold = null; + axis.softThreshold = !axis.isXAxis; + if (axis.stacking) { + axis.stacking.buildStacks(); + } + // loop through this axis' series + axis.series.forEach(function (series) { + if (series.visible || + !chart.options.chart.ignoreHiddenSeries) { + var seriesOptions = series.options, xData, threshold = seriesOptions.threshold, seriesDataMin, seriesDataMax; + axis.hasVisibleSeries = true; + // Validate threshold in logarithmic axes + if (axis.positiveValuesOnly && threshold <= 0) { + threshold = null; + } + // Get dataMin and dataMax for X axes + if (axis.isXAxis) { + xData = series.xData; + if (xData.length) { + xExtremes = series.getXExtremes(xData); + // If xData contains values which is not numbers, + // then filter them out. To prevent performance hit, + // we only do this after we have already found + // seriesDataMin because in most cases all data is + // valid. #5234. + seriesDataMin = xExtremes.min; + seriesDataMax = xExtremes.max; + if (!isNumber(seriesDataMin) && + // #5010: + !(seriesDataMin instanceof Date)) { + xData = xData.filter(isNumber); + xExtremes = series.getXExtremes(xData); + // Do it again with valid data + seriesDataMin = xExtremes.min; + seriesDataMax = xExtremes.max; + } + if (xData.length) { + axis.dataMin = Math.min(pick(axis.dataMin, seriesDataMin), seriesDataMin); + axis.dataMax = Math.max(pick(axis.dataMax, seriesDataMax), seriesDataMax); + } + } + // Get dataMin and dataMax for Y axes, as well as handle + // stacking and processed data + } + else { + // Get this particular series extremes + var dataExtremes = series.applyExtremes(); + // Get the dataMin and dataMax so far. If percentage is + // used, the min and max are always 0 and 100. If + // seriesDataMin and seriesDataMax is null, then series + // doesn't have active y data, we continue with nulls + if (isNumber(dataExtremes.dataMin)) { + seriesDataMin = dataExtremes.dataMin; + axis.dataMin = Math.min(pick(axis.dataMin, seriesDataMin), seriesDataMin); + } + if (isNumber(dataExtremes.dataMax)) { + seriesDataMax = dataExtremes.dataMax; + axis.dataMax = Math.max(pick(axis.dataMax, seriesDataMax), seriesDataMax); + } + // Adjust to threshold + if (defined(threshold)) { + axis.threshold = threshold; + } + // If any series has a hard threshold, it takes + // precedence + if (!seriesOptions.softThreshold || + axis.positiveValuesOnly) { + axis.softThreshold = false; + } + } + } + }); + }); + fireEvent(this, 'afterGetSeriesExtremes'); + }; + /** + * Translate from axis value to pixel position on the chart, or back. Use + * the `toPixels` and `toValue` functions in applications. + * + * @private + * @function Highcharts.Axis#translate + * + * @param {number} val + * TO-DO: parameter description + * + * @param {boolean|null} [backwards] + * TO-DO: parameter description + * + * @param {boolean|null} [cvsCoord] + * TO-DO: parameter description + * + * @param {boolean|null} [old] + * TO-DO: parameter description + * + * @param {boolean} [handleLog] + * TO-DO: parameter description + * + * @param {number} [pointPlacement] + * TO-DO: parameter description + * + * @return {number|undefined} + */ + Axis.prototype.translate = function (val, backwards, cvsCoord, old, handleLog, pointPlacement) { + var axis = this.linkedParent || this, // #1417 + sign = 1, cvsOffset = 0, localA = old ? axis.oldTransA : axis.transA, localMin = old ? axis.oldMin : axis.min, returnValue = 0, minPixelPadding = axis.minPixelPadding, doPostTranslate = (axis.isOrdinal || + axis.brokenAxis && axis.brokenAxis.hasBreaks || + (axis.logarithmic && handleLog)) && axis.lin2val; + if (!localA) { + localA = axis.transA; + } + // In vertical axes, the canvas coordinates start from 0 at the top like + // in SVG. + if (cvsCoord) { + sign *= -1; // canvas coordinates inverts the value + cvsOffset = axis.len; + } + // Handle reversed axis + if (axis.reversed) { + sign *= -1; + cvsOffset -= sign * (axis.sector || axis.len); + } + // From pixels to value + if (backwards) { // reverse translation + val = val * sign + cvsOffset; + val -= minPixelPadding; + // from chart pixel to value: + returnValue = val / localA + localMin; + if (doPostTranslate) { // log and ordinal axes + returnValue = axis.lin2val(returnValue); + } + // From value to pixels + } + else { + if (doPostTranslate) { // log and ordinal axes + val = axis.val2lin(val); + } + returnValue = isNumber(localMin) ? + (sign * (val - localMin) * localA + + cvsOffset + + (sign * minPixelPadding) + + (isNumber(pointPlacement) ? + localA * pointPlacement : + 0)) : + void 0; + } + return returnValue; + }; + /** + * Translate a value in terms of axis units into pixels within the chart. + * + * @function Highcharts.Axis#toPixels + * + * @param {number} value + * A value in terms of axis units. + * + * @param {boolean} paneCoordinates + * Whether to return the pixel coordinate relative to the chart or just the + * axis/pane itself. + * + * @return {number} + * Pixel position of the value on the chart or axis. + */ + Axis.prototype.toPixels = function (value, paneCoordinates) { + return this.translate(value, false, !this.horiz, null, true) + + (paneCoordinates ? 0 : this.pos); + }; + /** + * Translate a pixel position along the axis to a value in terms of axis + * units. + * + * @function Highcharts.Axis#toValue + * + * @param {number} pixel + * The pixel value coordinate. + * + * @param {boolean} [paneCoordinates=false] + * Whether the input pixel is relative to the chart or just the axis/pane + * itself. + * + * @return {number} + * The axis value. + */ + Axis.prototype.toValue = function (pixel, paneCoordinates) { + return this.translate(pixel - (paneCoordinates ? 0 : this.pos), true, !this.horiz, null, true); + }; + /** + * Create the path for a plot line that goes from the given value on + * this axis, across the plot to the opposite side. Also used internally for + * grid lines and crosshairs. + * + * @function Highcharts.Axis#getPlotLinePath + * + * @param {Highcharts.AxisPlotLinePathOptionsObject} options + * Options for the path. + * + * @return {Highcharts.SVGPathArray|null} + * The SVG path definition for the plot line. + */ + Axis.prototype.getPlotLinePath = function (options) { + var axis = this, chart = axis.chart, axisLeft = axis.left, axisTop = axis.top, old = options.old, value = options.value, translatedValue = options.translatedValue, lineWidth = options.lineWidth, force = options.force, x1, y1, x2, y2, cHeight = (old && chart.oldChartHeight) || chart.chartHeight, cWidth = (old && chart.oldChartWidth) || chart.chartWidth, skip, transB = axis.transB, evt; + // eslint-disable-next-line valid-jsdoc + /** + * Check if x is between a and b. If not, either move to a/b + * or skip, depending on the force parameter. + * @private + */ + function between(x, a, b) { + if (force !== 'pass' && x < a || x > b) { + if (force) { + x = clamp(x, a, b); + } + else { + skip = true; + } + } + return x; + } + evt = { + value: value, + lineWidth: lineWidth, + old: old, + force: force, + acrossPanes: options.acrossPanes, + translatedValue: translatedValue + }; + fireEvent(this, 'getPlotLinePath', evt, function (e) { + translatedValue = pick(translatedValue, axis.translate(value, null, null, old)); + // Keep the translated value within sane bounds, and avoid Infinity + // to fail the isNumber test (#7709). + translatedValue = clamp(translatedValue, -1e5, 1e5); + x1 = x2 = Math.round(translatedValue + transB); + y1 = y2 = Math.round(cHeight - translatedValue - transB); + if (!isNumber(translatedValue)) { // no min or max + skip = true; + force = false; // #7175, don't force it when path is invalid + } + else if (axis.horiz) { + y1 = axisTop; + y2 = cHeight - axis.bottom; + x1 = x2 = between(x1, axisLeft, axisLeft + axis.width); + } + else { + x1 = axisLeft; + x2 = cWidth - axis.right; + y1 = y2 = between(y1, axisTop, axisTop + axis.height); + } + e.path = skip && !force ? + null : + chart.renderer.crispLine([['M', x1, y1], ['L', x2, y2]], lineWidth || 1); + }); + return evt.path; + }; + /** + * Internal function to et the tick positions of a linear axis to round + * values like whole tens or every five. + * + * @function Highcharts.Axis#getLinearTickPositions + * + * @param {number} tickInterval + * The normalized tick interval. + * + * @param {number} min + * Axis minimum. + * + * @param {number} max + * Axis maximum. + * + * @return {Array} + * An array of axis values where ticks should be placed. + */ + Axis.prototype.getLinearTickPositions = function (tickInterval, min, max) { + var pos, lastPos, roundedMin = correctFloat(Math.floor(min / tickInterval) * tickInterval), roundedMax = correctFloat(Math.ceil(max / tickInterval) * tickInterval), tickPositions = [], precision; + // When the precision is higher than what we filter out in + // correctFloat, skip it (#6183). + if (correctFloat(roundedMin + tickInterval) === roundedMin) { + precision = 20; + } + // For single points, add a tick regardless of the relative position + // (#2662, #6274) + if (this.single) { + return [min]; + } + // Populate the intermediate values + pos = roundedMin; + while (pos <= roundedMax) { + // Place the tick on the rounded value + tickPositions.push(pos); + // Always add the raw tickInterval, not the corrected one. + pos = correctFloat(pos + tickInterval, precision); + // If the interval is not big enough in the current min - max range + // to actually increase the loop variable, we need to break out to + // prevent endless loop. Issue #619 + if (pos === lastPos) { + break; + } + // Record the last value + lastPos = pos; + } + return tickPositions; + }; + /** + * Resolve the new minorTicks/minorTickInterval options into the legacy + * loosely typed minorTickInterval option. + * + * @function Highcharts.Axis#getMinorTickInterval + * + * @return {number|"auto"|null} + */ + Axis.prototype.getMinorTickInterval = function () { + var options = this.options; + if (options.minorTicks === true) { + return pick(options.minorTickInterval, 'auto'); + } + if (options.minorTicks === false) { + return null; + } + return options.minorTickInterval; + }; + /** + * Internal function to return the minor tick positions. For logarithmic + * axes, the same logic as for major ticks is reused. + * + * @function Highcharts.Axis#getMinorTickPositions + * + * @return {Array} + * An array of axis values where ticks should be placed. + */ + Axis.prototype.getMinorTickPositions = function () { + var axis = this, options = axis.options, tickPositions = axis.tickPositions, minorTickInterval = axis.minorTickInterval, minorTickPositions = [], pos, pointRangePadding = axis.pointRangePadding || 0, min = axis.min - pointRangePadding, // #1498 + max = axis.max + pointRangePadding, // #1498 + range = max - min; + // If minor ticks get too dense, they are hard to read, and may cause + // long running script. So we don't draw them. + if (range && range / minorTickInterval < axis.len / 3) { // #3875 + var logarithmic_1 = axis.logarithmic; + if (logarithmic_1) { + // For each interval in the major ticks, compute the minor ticks + // separately. + this.paddedTicks.forEach(function (_pos, i, paddedTicks) { + if (i) { + minorTickPositions.push.apply(minorTickPositions, logarithmic_1.getLogTickPositions(minorTickInterval, paddedTicks[i - 1], paddedTicks[i], true)); + } + }); + } + else if (axis.dateTime && + this.getMinorTickInterval() === 'auto') { // #1314 + minorTickPositions = minorTickPositions.concat(axis.getTimeTicks(axis.dateTime.normalizeTimeTickInterval(minorTickInterval), min, max, options.startOfWeek)); + } + else { + for (pos = min + (tickPositions[0] - min) % minorTickInterval; pos <= max; pos += minorTickInterval) { + // Very, very, tight grid lines (#5771) + if (pos === minorTickPositions[0]) { + break; + } + minorTickPositions.push(pos); + } + } + } + if (minorTickPositions.length !== 0) { + axis.trimTicks(minorTickPositions); // #3652 #3743 #1498 #6330 + } + return minorTickPositions; + }; + /** + * Adjust the min and max for the minimum range. Keep in mind that the + * series data is not yet processed, so we don't have information on data + * cropping and grouping, or updated `axis.pointRange` or + * `series.pointRange`. The data can't be processed until we have finally + * established min and max. + * + * @private + * @function Highcharts.Axis#adjustForMinRange + */ + Axis.prototype.adjustForMinRange = function () { + var axis = this, options = axis.options, min = axis.min, max = axis.max, log = axis.logarithmic, zoomOffset, spaceAvailable, closestDataRange, i, distance, xData, loopLength, minArgs, maxArgs, minRange; + // Set the automatic minimum range based on the closest point distance + if (axis.isXAxis && + typeof axis.minRange === 'undefined' && + !log) { + if (defined(options.min) || defined(options.max)) { + axis.minRange = null; // don't do this again + } + else { + // Find the closest distance between raw data points, as opposed + // to closestPointRange that applies to processed points + // (cropped and grouped) + axis.series.forEach(function (series) { + xData = series.xData; + loopLength = series.xIncrement ? 1 : xData.length - 1; + for (i = loopLength; i > 0; i--) { + distance = xData[i] - xData[i - 1]; + if (typeof closestDataRange === 'undefined' || + distance < closestDataRange) { + closestDataRange = distance; + } + } + }); + axis.minRange = Math.min(closestDataRange * 5, axis.dataMax - axis.dataMin); + } + } + // if minRange is exceeded, adjust + if (max - min < axis.minRange) { + spaceAvailable = + axis.dataMax - axis.dataMin >= + axis.minRange; + minRange = axis.minRange; + zoomOffset = (minRange - max + min) / 2; + // if min and max options have been set, don't go beyond it + minArgs = [ + min - zoomOffset, + pick(options.min, min - zoomOffset) + ]; + // If space is available, stay within the data range + if (spaceAvailable) { + minArgs[2] = axis.logarithmic ? + axis.logarithmic.log2lin(axis.dataMin) : + axis.dataMin; + } + min = arrayMax(minArgs); + maxArgs = [ + min + minRange, + pick(options.max, min + minRange) + ]; + // If space is availabe, stay within the data range + if (spaceAvailable) { + maxArgs[2] = log ? + log.log2lin(axis.dataMax) : + axis.dataMax; + } + max = arrayMin(maxArgs); + // now if the max is adjusted, adjust the min back + if (max - min < minRange) { + minArgs[0] = max - minRange; + minArgs[1] = pick(options.min, max - minRange); + min = arrayMax(minArgs); + } + } + // Record modified extremes + axis.min = min; + axis.max = max; + }; + // eslint-disable-next-line valid-jsdoc + /** + * Find the closestPointRange across all series. + * + * @private + * @function Highcharts.Axis#getClosest + */ + Axis.prototype.getClosest = function () { + var ret; + if (this.categories) { + ret = 1; + } + else { + this.series.forEach(function (series) { + var seriesClosest = series.closestPointRange, visible = series.visible || + !series.chart.options.chart.ignoreHiddenSeries; + if (!series.noSharedTooltip && + defined(seriesClosest) && + visible) { + ret = defined(ret) ? + Math.min(ret, seriesClosest) : + seriesClosest; + } + }); + } + return ret; + }; + /** + * When a point name is given and no x, search for the name in the existing + * categories, or if categories aren't provided, search names or create a + * new category (#2522). + * @private + * @function Highcharts.Axis#nameToX + * + * @param {Highcharts.Point} point + * The point to inspect. + * + * @return {number} + * The X value that the point is given. + */ + Axis.prototype.nameToX = function (point) { + var explicitCategories = isArray(this.categories), names = explicitCategories ? this.categories : this.names, nameX = point.options.x, x; + point.series.requireSorting = false; + if (!defined(nameX)) { + nameX = this.options.uniqueNames === false ? + point.series.autoIncrement() : + (explicitCategories ? + names.indexOf(point.name) : + pick(names.keys[point.name], -1)); + } + if (nameX === -1) { // Not found in currenct categories + if (!explicitCategories) { + x = names.length; + } + } + else { + x = nameX; + } + // Write the last point's name to the names array + if (typeof x !== 'undefined') { + this.names[x] = point.name; + // Backwards mapping is much faster than array searching (#7725) + this.names.keys[point.name] = x; + } + return x; + }; + /** + * When changes have been done to series data, update the axis.names. + * + * @private + * @function Highcharts.Axis#updateNames + */ + Axis.prototype.updateNames = function () { + var axis = this, names = this.names, i = names.length; + if (i > 0) { + Object.keys(names.keys).forEach(function (key) { + delete (names.keys)[key]; + }); + names.length = 0; + this.minRange = this.userMinRange; // Reset + (this.series || []).forEach(function (series) { + // Reset incrementer (#5928) + series.xIncrement = null; + // When adding a series, points are not yet generated + if (!series.points || series.isDirtyData) { + // When we're updating the series with data that is longer + // than it was, and cropThreshold is passed, we need to make + // sure that the axis.max is increased _before_ running the + // premature processData. Otherwise this early iteration of + // processData will crop the points to axis.max, and the + // names array will be too short (#5857). + axis.max = Math.max(axis.max, series.xData.length - 1); + series.processData(); + series.generatePoints(); + } + series.data.forEach(function (point, i) { + var x; + if (point && + point.options && + typeof point.name !== 'undefined' // #9562 + ) { + x = axis.nameToX(point); + if (typeof x !== 'undefined' && x !== point.x) { + point.x = x; + series.xData[i] = x; + } + } + }); + }); + } + }; + /** + * Update translation information. + * + * @private + * @function Highcharts.Axis#setAxisTranslation + * + * @param {boolean} [saveOld] + * TO-DO: parameter description + * + * @fires Highcharts.Axis#event:afterSetAxisTranslation + */ + Axis.prototype.setAxisTranslation = function (saveOld) { + var axis = this, range = axis.max - axis.min, pointRange = axis.axisPointRange || 0, closestPointRange, minPointOffset = 0, pointRangePadding = 0, linkedParent = axis.linkedParent, ordinalCorrection, hasCategories = !!axis.categories, transA = axis.transA, isXAxis = axis.isXAxis; + // Adjust translation for padding. Y axis with categories need to go + // through the same (#1784). + if (isXAxis || hasCategories || pointRange) { + // Get the closest points + closestPointRange = axis.getClosest(); + if (linkedParent) { + minPointOffset = linkedParent.minPointOffset; + pointRangePadding = linkedParent.pointRangePadding; + } + else { + axis.series.forEach(function (series) { + var seriesPointRange = hasCategories ? + 1 : + (isXAxis ? + pick(series.options.pointRange, closestPointRange, 0) : + (axis.axisPointRange || 0)), // #2806 + pointPlacement = series.options.pointPlacement; + pointRange = Math.max(pointRange, seriesPointRange); + if (!axis.single || hasCategories) { + // TODO: series should internally set x- and y- + // pointPlacement to simplify this logic. + var isPointPlacementAxis = series.is('xrange') ? !isXAxis : isXAxis; + // minPointOffset is the value padding to the left of + // the axis in order to make room for points with a + // pointRange, typically columns. When the + // pointPlacement option is 'between' or 'on', this + // padding does not apply. + minPointOffset = Math.max(minPointOffset, isPointPlacementAxis && isString(pointPlacement) ? + 0 : + seriesPointRange / 2); + // Determine the total padding needed to the length of + // the axis to make room for the pointRange. If the + // series' pointPlacement is 'on', no padding is added. + pointRangePadding = Math.max(pointRangePadding, isPointPlacementAxis && pointPlacement === 'on' ? + 0 : + seriesPointRange); + } + }); + } + // Record minPointOffset and pointRangePadding + ordinalCorrection = axis.ordinal && axis.ordinal.slope && closestPointRange ? + axis.ordinal.slope / closestPointRange : + 1; // #988, #1853 + axis.minPointOffset = minPointOffset = + minPointOffset * ordinalCorrection; + axis.pointRangePadding = + pointRangePadding = pointRangePadding * ordinalCorrection; + // pointRange means the width reserved for each point, like in a + // column chart + axis.pointRange = Math.min(pointRange, axis.single && hasCategories ? 1 : range); + // closestPointRange means the closest distance between points. In + // columns it is mostly equal to pointRange, but in lines pointRange + // is 0 while closestPointRange is some other value + if (isXAxis) { + axis.closestPointRange = closestPointRange; + } + } + // Secondary values + if (saveOld) { + axis.oldTransA = transA; + } + axis.translationSlope = axis.transA = transA = + axis.staticScale || + axis.len / ((range + pointRangePadding) || 1); + // Translation addend + axis.transB = axis.horiz ? axis.left : axis.bottom; + axis.minPixelPadding = transA * minPointOffset; + fireEvent(this, 'afterSetAxisTranslation'); + }; + /** + * @private + * @function Highcharts.Axis#minFromRange + * + * @return {number} + */ + Axis.prototype.minFromRange = function () { + var axis = this; + return axis.max - axis.range; + }; + /** + * Set the tick positions to round values and optionally extend the extremes + * to the nearest tick. + * + * @private + * @function Highcharts.Axis#setTickInterval + * + * @param {boolean} secondPass + * TO-DO: parameter description + * + * @fires Highcharts.Axis#event:foundExtremes + */ + Axis.prototype.setTickInterval = function (secondPass) { + var axis = this, chart = axis.chart, log = axis.logarithmic, options = axis.options, isXAxis = axis.isXAxis, isLinked = axis.isLinked, maxPadding = options.maxPadding, minPadding = options.minPadding, length, linkedParentExtremes, tickIntervalOption = options.tickInterval, minTickInterval, tickPixelIntervalOption = options.tickPixelInterval, categories = axis.categories, threshold = isNumber(axis.threshold) ? axis.threshold : null, softThreshold = axis.softThreshold, thresholdMin, thresholdMax, hardMin, hardMax; + if (!axis.dateTime && !categories && !isLinked) { + this.getTickAmount(); + } + // Min or max set either by zooming/setExtremes or initial options + hardMin = pick(axis.userMin, options.min); + hardMax = pick(axis.userMax, options.max); + // Linked axis gets the extremes from the parent axis + if (isLinked) { + axis.linkedParent = chart[axis.coll][options.linkedTo]; + linkedParentExtremes = axis.linkedParent.getExtremes(); + axis.min = pick(linkedParentExtremes.min, linkedParentExtremes.dataMin); + axis.max = pick(linkedParentExtremes.max, linkedParentExtremes.dataMax); + if (options.type !== axis.linkedParent.options.type) { + // Can't link axes of different type + error(11, 1, chart); + } + // Initial min and max from the extreme data values + } + else { + // Adjust to hard threshold + if (!softThreshold && defined(threshold)) { + if (axis.dataMin >= threshold) { + thresholdMin = threshold; + minPadding = 0; + } + else if (axis.dataMax <= threshold) { + thresholdMax = threshold; + maxPadding = 0; + } + } + axis.min = pick(hardMin, thresholdMin, axis.dataMin); + axis.max = pick(hardMax, thresholdMax, axis.dataMax); + } + if (log) { + if (axis.positiveValuesOnly && + !secondPass && + Math.min(axis.min, pick(axis.dataMin, axis.min)) <= 0) { // #978 + // Can't plot negative values on log axis + error(10, 1, chart); + } + // The correctFloat cures #934, float errors on full tens. But it + // was too aggressive for #4360 because of conversion back to lin, + // therefore use precision 15. + axis.min = correctFloat(log.log2lin(axis.min), 16); + axis.max = correctFloat(log.log2lin(axis.max), 16); + } + // handle zoomed range + if (axis.range && defined(axis.max)) { + // #618, #6773: + axis.userMin = axis.min = hardMin = + Math.max(axis.dataMin, axis.minFromRange()); + axis.userMax = hardMax = axis.max; + axis.range = null; // don't use it when running setExtremes + } + // Hook for Highstock Scroller. Consider combining with beforePadding. + fireEvent(axis, 'foundExtremes'); + // Hook for adjusting this.min and this.max. Used by bubble series. + if (axis.beforePadding) { + axis.beforePadding(); + } + // adjust min and max for the minimum range + axis.adjustForMinRange(); + // Pad the values to get clear of the chart's edges. To avoid + // tickInterval taking the padding into account, we do this after + // computing tick interval (#1337). + if (!categories && + !axis.axisPointRange && + !(axis.stacking && axis.stacking.usePercentage) && + !isLinked && + defined(axis.min) && + defined(axis.max)) { + length = axis.max - axis.min; + if (length) { + if (!defined(hardMin) && minPadding) { + axis.min -= length * minPadding; + } + if (!defined(hardMax) && maxPadding) { + axis.max += length * maxPadding; + } + } + } + // Handle options for floor, ceiling, softMin and softMax (#6359) + if (!isNumber(axis.userMin)) { + if (isNumber(options.softMin) && options.softMin < axis.min) { + axis.min = hardMin = options.softMin; // #6894 + } + if (isNumber(options.floor)) { + axis.min = Math.max(axis.min, options.floor); + } + } + if (!isNumber(axis.userMax)) { + if (isNumber(options.softMax) && options.softMax > axis.max) { + axis.max = hardMax = options.softMax; // #6894 + } + if (isNumber(options.ceiling)) { + axis.max = Math.min(axis.max, options.ceiling); + } + } + // When the threshold is soft, adjust the extreme value only if the data + // extreme and the padded extreme land on either side of the threshold. + // For example, a series of [0, 1, 2, 3] would make the yAxis add a tick + // for -1 because of the default minPadding and startOnTick options. + // This is prevented by the softThreshold option. + if (softThreshold && defined(axis.dataMin)) { + threshold = threshold || 0; + if (!defined(hardMin) && + axis.min < threshold && + axis.dataMin >= threshold) { + axis.min = axis.options.minRange ? + Math.min(threshold, axis.max - + axis.minRange) : + threshold; + } + else if (!defined(hardMax) && + axis.max > threshold && + axis.dataMax <= threshold) { + axis.max = axis.options.minRange ? + Math.max(threshold, axis.min + + axis.minRange) : + threshold; + } + } + // get tickInterval + if (axis.min === axis.max || + typeof axis.min === 'undefined' || + typeof axis.max === 'undefined') { + axis.tickInterval = 1; + } + else if (isLinked && + !tickIntervalOption && + tickPixelIntervalOption === + axis.linkedParent.options.tickPixelInterval) { + axis.tickInterval = tickIntervalOption = + axis.linkedParent.tickInterval; + } + else { + axis.tickInterval = pick(tickIntervalOption, this.tickAmount ? + ((axis.max - axis.min) / + Math.max(this.tickAmount - 1, 1)) : + void 0, + // For categoried axis, 1 is default, for linear axis use + // tickPix + categories ? + 1 : + // don't let it be more than the data range + (axis.max - axis.min) * + tickPixelIntervalOption / + Math.max(axis.len, tickPixelIntervalOption)); + } + // Now we're finished detecting min and max, crop and group series data. + // This is in turn needed in order to find tick positions in ordinal + // axes. + if (isXAxis && !secondPass) { + axis.series.forEach(function (series) { + series.processData(axis.min !== axis.oldMin || axis.max !== axis.oldMax); + }); + } + // set the translation factor used in translate function + axis.setAxisTranslation(true); + // hook for ordinal axes and radial axes + if (axis.beforeSetTickPositions) { + axis.beforeSetTickPositions(); + } + // hook for extensions, used in Highstock ordinal axes + if (axis.ordinal) { + axis.tickInterval = axis.ordinal.postProcessTickInterval(axis.tickInterval); + } + // In column-like charts, don't cramp in more ticks than there are + // points (#1943, #4184) + if (axis.pointRange && !tickIntervalOption) { + axis.tickInterval = Math.max(axis.pointRange, axis.tickInterval); + } + // Before normalizing the tick interval, handle minimum tick interval. + // This applies only if tickInterval is not defined. + minTickInterval = pick(options.minTickInterval, (axis.dateTime && axis.closestPointRange)); + if (!tickIntervalOption && axis.tickInterval < minTickInterval) { + axis.tickInterval = minTickInterval; + } + // for linear axes, get magnitude and normalize the interval + if (!axis.dateTime && !axis.logarithmic && !tickIntervalOption) { + axis.tickInterval = normalizeTickInterval(axis.tickInterval, void 0, getMagnitude(axis.tickInterval), pick(options.allowDecimals, + // If the tick interval is greather than 0.5, avoid + // decimals, as linear axes are often used to render + // discrete values. #3363. If a tick amount is set, allow + // decimals by default, as it increases the chances for a + // good fit. + axis.tickInterval < 0.5 || this.tickAmount !== void 0), !!this.tickAmount); + } + // Prevent ticks from getting so close that we can't draw the labels + if (!this.tickAmount) { + axis.tickInterval = axis.unsquish(); + } + this.setTickPositions(); + }; + /** + * Now we have computed the normalized tickInterval, get the tick positions + * + * @function Highcharts.Axis#setTickPositions + * + * @fires Highcharts.Axis#event:afterSetTickPositions + */ + Axis.prototype.setTickPositions = function () { + var axis = this, options = this.options, tickPositions, tickPositionsOption = options.tickPositions, minorTickIntervalOption = this.getMinorTickInterval(), tickPositioner = options.tickPositioner, hasVerticalPanning = this.hasVerticalPanning(), isColorAxis = this.coll === 'colorAxis', startOnTick = (isColorAxis || !hasVerticalPanning) && options.startOnTick, endOnTick = (isColorAxis || !hasVerticalPanning) && options.endOnTick; + // Set the tickmarkOffset + this.tickmarkOffset = (this.categories && + options.tickmarkPlacement === 'between' && + this.tickInterval === 1) ? 0.5 : 0; // #3202 + // get minorTickInterval + this.minorTickInterval = + minorTickIntervalOption === 'auto' && + this.tickInterval ? + this.tickInterval / 5 : + minorTickIntervalOption; + // When there is only one point, or all points have the same value on + // this axis, then min and max are equal and tickPositions.length is 0 + // or 1. In this case, add some padding in order to center the point, + // but leave it with one tick. #1337. + this.single = + this.min === this.max && + defined(this.min) && + !this.tickAmount && + ( + // Data is on integer (#6563) + parseInt(this.min, 10) === this.min || + // Between integers and decimals are not allowed (#6274) + options.allowDecimals !== false); + /** + * Contains the current positions that are laid out on the axis. The + * positions are numbers in terms of axis values. In a category axis + * they are integers, in a datetime axis they are also integers, but + * designating milliseconds. + * + * This property is read only - for modifying the tick positions, use + * the `tickPositioner` callback or [axis.tickPositions( + * https://api.highcharts.com/highcharts/xAxis.tickPositions) option + * instead. + * + * @name Highcharts.Axis#tickPositions + * @type {Highcharts.AxisTickPositionsArray|undefined} + */ + this.tickPositions = + // Find the tick positions. Work on a copy (#1565) + tickPositions = + (tickPositionsOption && tickPositionsOption.slice()); + if (!tickPositions) { + // Too many ticks (#6405). Create a friendly warning and provide two + // ticks so at least we can show the data series. + if ((!axis.ordinal || !axis.ordinal.positions) && + ((this.max - this.min) / + this.tickInterval > + Math.max(2 * this.len, 200))) { + tickPositions = [this.min, this.max]; + error(19, false, this.chart); + } + else if (axis.dateTime) { + tickPositions = axis.getTimeTicks(axis.dateTime.normalizeTimeTickInterval(this.tickInterval, options.units), this.min, this.max, options.startOfWeek, axis.ordinal && axis.ordinal.positions, this.closestPointRange, true); + } + else if (axis.logarithmic) { + tickPositions = axis.logarithmic.getLogTickPositions(this.tickInterval, this.min, this.max); + } + else { + tickPositions = this.getLinearTickPositions(this.tickInterval, this.min, this.max); + } + // Too dense ticks, keep only the first and last (#4477) + if (tickPositions.length > this.len) { + tickPositions = [tickPositions[0], tickPositions.pop()]; + // Reduce doubled value (#7339) + if (tickPositions[0] === tickPositions[1]) { + tickPositions.length = 1; + } + } + this.tickPositions = tickPositions; + // Run the tick positioner callback, that allows modifying auto tick + // positions. + if (tickPositioner) { + tickPositioner = tickPositioner.apply(axis, [this.min, this.max]); + if (tickPositioner) { + this.tickPositions = tickPositions = tickPositioner; + } + } + } + // Reset min/max or remove extremes based on start/end on tick + this.paddedTicks = tickPositions.slice(0); // Used for logarithmic minor + this.trimTicks(tickPositions, startOnTick, endOnTick); + if (!this.isLinked) { + // Substract half a unit (#2619, #2846, #2515, #3390), + // but not in case of multiple ticks (#6897) + if (this.single && + tickPositions.length < 2 && + !this.categories && + !this.series.some(function (s) { + return (s.is('heatmap') && s.options.pointPlacement === 'between'); + })) { + this.min -= 0.5; + this.max += 0.5; + } + if (!tickPositionsOption && !tickPositioner) { + this.adjustTickAmount(); + } + } + fireEvent(this, 'afterSetTickPositions'); + }; + /** + * Handle startOnTick and endOnTick by either adapting to padding min/max or + * rounded min/max. Also handle single data points. + * + * @private + * @function Highcharts.Axis#trimTicks + * + * @param {Array} tickPositions + * TO-DO: parameter description + * + * @param {boolean} [startOnTick] + * TO-DO: parameter description + * + * @param {boolean} [endOnTick] + * TO-DO: parameter description + */ + Axis.prototype.trimTicks = function (tickPositions, startOnTick, endOnTick) { + var roundedMin = tickPositions[0], roundedMax = tickPositions[tickPositions.length - 1], minPointOffset = (!this.isOrdinal && this.minPointOffset) || 0; // (#12716) + fireEvent(this, 'trimTicks'); + if (!this.isLinked) { + if (startOnTick && roundedMin !== -Infinity) { // #6502 + this.min = roundedMin; + } + else { + while (this.min - minPointOffset > tickPositions[0]) { + tickPositions.shift(); + } + } + if (endOnTick) { + this.max = roundedMax; + } + else { + while (this.max + minPointOffset < + tickPositions[tickPositions.length - 1]) { + tickPositions.pop(); + } + } + // If no tick are left, set one tick in the middle (#3195) + if (tickPositions.length === 0 && + defined(roundedMin) && + !this.options.tickPositions) { + tickPositions.push((roundedMax + roundedMin) / 2); + } + } + }; + /** + * Check if there are multiple axes in the same pane. + * + * @private + * @function Highcharts.Axis#alignToOthers + * + * @return {boolean|undefined} + * True if there are other axes. + */ + Axis.prototype.alignToOthers = function () { + var axis = this, others = // Whether there is another axis to pair with this one + {}, hasOther, options = axis.options; + if ( + // Only if alignTicks is true + this.chart.options.chart.alignTicks !== false && + options.alignTicks !== false && + // Disabled when startOnTick or endOnTick are false (#7604) + options.startOnTick !== false && + options.endOnTick !== false && + // Don't try to align ticks on a log axis, they are not evenly + // spaced (#6021) + !axis.logarithmic) { + this.chart[this.coll].forEach(function (axis) { + var otherOptions = axis.options, horiz = axis.horiz, key = [ + horiz ? otherOptions.left : otherOptions.top, + otherOptions.width, + otherOptions.height, + otherOptions.pane + ].join(','); + if (axis.series.length) { // #4442 + if (others[key]) { + hasOther = true; // #4201 + } + else { + others[key] = 1; + } + } + }); + } + return hasOther; + }; + /** + * Find the max ticks of either the x and y axis collection, and record it + * in `this.tickAmount`. + * + * @private + * @function Highcharts.Axis#getTickAmount + */ + Axis.prototype.getTickAmount = function () { + var axis = this, options = this.options, tickAmount = options.tickAmount, tickPixelInterval = options.tickPixelInterval; + if (!defined(options.tickInterval) && + !tickAmount && this.len < tickPixelInterval && + !this.isRadial && + !axis.logarithmic && + options.startOnTick && + options.endOnTick) { + tickAmount = 2; + } + if (!tickAmount && this.alignToOthers()) { + // Add 1 because 4 tick intervals require 5 ticks (including first + // and last) + tickAmount = Math.ceil(this.len / tickPixelInterval) + 1; + } + // For tick amounts of 2 and 3, compute five ticks and remove the + // intermediate ones. This prevents the axis from adding ticks that are + // too far away from the data extremes. + if (tickAmount < 4) { + this.finalTickAmt = tickAmount; + tickAmount = 5; + } + this.tickAmount = tickAmount; + }; + /** + * When using multiple axes, adjust the number of ticks to match the highest + * number of ticks in that group. + * + * @private + * @function Highcharts.Axis#adjustTickAmount + */ + Axis.prototype.adjustTickAmount = function () { + var axis = this, axisOptions = axis.options, tickInterval = axis.tickInterval, tickPositions = axis.tickPositions, tickAmount = axis.tickAmount, finalTickAmt = axis.finalTickAmt, currentTickAmount = tickPositions && tickPositions.length, threshold = pick(axis.threshold, axis.softThreshold ? 0 : null), min, len, i; + if (axis.hasData()) { + if (currentTickAmount < tickAmount) { + min = axis.min; + while (tickPositions.length < tickAmount) { + // Extend evenly for both sides unless we're on the + // threshold (#3965) + if (tickPositions.length % 2 || + min === threshold) { + // to the end + tickPositions.push(correctFloat(tickPositions[tickPositions.length - 1] + + tickInterval)); + } + else { + // to the start + tickPositions.unshift(correctFloat(tickPositions[0] - tickInterval)); + } + } + axis.transA *= (currentTickAmount - 1) / (tickAmount - 1); + // Do not crop when ticks are not extremes (#9841) + axis.min = axisOptions.startOnTick ? + tickPositions[0] : + Math.min(axis.min, tickPositions[0]); + axis.max = axisOptions.endOnTick ? + tickPositions[tickPositions.length - 1] : + Math.max(axis.max, tickPositions[tickPositions.length - 1]); + // We have too many ticks, run second pass to try to reduce ticks + } + else if (currentTickAmount > tickAmount) { + axis.tickInterval *= 2; + axis.setTickPositions(); + } + // The finalTickAmt property is set in getTickAmount + if (defined(finalTickAmt)) { + i = len = tickPositions.length; + while (i--) { + if ( + // Remove every other tick + (finalTickAmt === 3 && i % 2 === 1) || + // Remove all but first and last + (finalTickAmt <= 2 && i > 0 && i < len - 1)) { + tickPositions.splice(i, 1); + } + } + axis.finalTickAmt = void 0; + } + } + }; + /** + * Set the scale based on data min and max, user set min and max or options. + * + * @private + * @function Highcharts.Axis#setScale + * + * @fires Highcharts.Axis#event:afterSetScale + */ + Axis.prototype.setScale = function () { + var axis = this, isDirtyAxisLength, isDirtyData = false, isXAxisDirty = false; + axis.series.forEach(function (series) { + var _a; + isDirtyData = isDirtyData || series.isDirtyData || series.isDirty; + // When x axis is dirty, we need new data extremes for y as + // well: + isXAxisDirty = isXAxisDirty || ((_a = series.xAxis) === null || _a === void 0 ? void 0 : _a.isDirty) || false; + }); + axis.oldMin = axis.min; + axis.oldMax = axis.max; + axis.oldAxisLength = axis.len; + // set the new axisLength + axis.setAxisSize(); + isDirtyAxisLength = axis.len !== axis.oldAxisLength; + // do we really need to go through all this? + if (isDirtyAxisLength || + isDirtyData || + isXAxisDirty || + axis.isLinked || + axis.forceRedraw || + axis.userMin !== axis.oldUserMin || + axis.userMax !== axis.oldUserMax || + axis.alignToOthers()) { + if (axis.stacking) { + axis.stacking.resetStacks(); + } + axis.forceRedraw = false; + // get data extremes if needed + axis.getSeriesExtremes(); + // get fixed positions based on tickInterval + axis.setTickInterval(); + // record old values to decide whether a rescale is necessary later + // on (#540) + axis.oldUserMin = axis.userMin; + axis.oldUserMax = axis.userMax; + // Mark as dirty if it is not already set to dirty and extremes have + // changed. #595. + if (!axis.isDirty) { + axis.isDirty = + isDirtyAxisLength || + axis.min !== axis.oldMin || + axis.max !== axis.oldMax; + } + } + else if (axis.stacking) { + axis.stacking.cleanStacks(); + } + // Recalculate panning state object, when the data + // has changed. It is required when vertical panning is enabled. + if (isDirtyData && axis.panningState) { + axis.panningState.isDirty = true; + } + fireEvent(this, 'afterSetScale'); + }; + /** + * Set the minimum and maximum of the axes after render time. If the + * `startOnTick` and `endOnTick` options are true, the minimum and maximum + * values are rounded off to the nearest tick. To prevent this, these + * options can be set to false before calling setExtremes. Also, setExtremes + * will not allow a range lower than the `minRange` option, which by default + * is the range of five points. + * + * @sample highcharts/members/axis-setextremes/ + * Set extremes from a button + * @sample highcharts/members/axis-setextremes-datetime/ + * Set extremes on a datetime axis + * @sample highcharts/members/axis-setextremes-off-ticks/ + * Set extremes off ticks + * @sample stock/members/axis-setextremes/ + * Set extremes in Highstock + * @sample maps/members/axis-setextremes/ + * Set extremes in Highmaps + * + * @function Highcharts.Axis#setExtremes + * + * @param {number} [newMin] + * The new minimum value. + * + * @param {number} [newMax] + * The new maximum value. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call to + * {@link Highcharts.Chart#redraw} + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=true] + * Enable or modify animations. + * + * @param {*} [eventArguments] + * Arguments to be accessed in event handler. + * + * @fires Highcharts.Axis#event:setExtremes + */ + Axis.prototype.setExtremes = function (newMin, newMax, redraw, animation, eventArguments) { + var axis = this, chart = axis.chart; + redraw = pick(redraw, true); // defaults to true + axis.series.forEach(function (serie) { + delete serie.kdTree; + }); + // Extend the arguments with min and max + eventArguments = extend(eventArguments, { + min: newMin, + max: newMax + }); + // Fire the event + fireEvent(axis, 'setExtremes', eventArguments, function () { + axis.userMin = newMin; + axis.userMax = newMax; + axis.eventArgs = eventArguments; + if (redraw) { + chart.redraw(animation); + } + }); + }; + /** + * Overridable method for zooming chart. Pulled out in a separate method to + * allow overriding in stock charts. + * @private + * @function Highcharts.Axis#zoom + * + * @param {number} newMin + * TO-DO: parameter description + * + * @param {number} newMax + * TO-DO: parameter description + * + * @return {boolean} + */ + Axis.prototype.zoom = function (newMin, newMax) { + var axis = this, dataMin = this.dataMin, dataMax = this.dataMax, options = this.options, min = Math.min(dataMin, pick(options.min, dataMin)), max = Math.max(dataMax, pick(options.max, dataMax)), evt = { + newMin: newMin, + newMax: newMax + }; + fireEvent(this, 'zoom', evt, function (e) { + // Use e.newMin and e.newMax - event handlers may have altered them + var newMin = e.newMin, newMax = e.newMax; + if (newMin !== axis.min || newMax !== axis.max) { // #5790 + // Prevent pinch zooming out of range. Check for defined is for + // #1946. #1734. + if (!axis.allowZoomOutside) { + // #6014, sometimes newMax will be smaller than min (or + // newMin will be larger than max). + if (defined(dataMin)) { + if (newMin < min) { + newMin = min; + } + if (newMin > max) { + newMin = max; + } + } + if (defined(dataMax)) { + if (newMax < min) { + newMax = min; + } + if (newMax > max) { + newMax = max; + } + } + } + // In full view, displaying the reset zoom button is not + // required + axis.displayBtn = (typeof newMin !== 'undefined' || + typeof newMax !== 'undefined'); + // Do it + axis.setExtremes(newMin, newMax, false, void 0, { trigger: 'zoom' }); + } + e.zoomed = true; + }); + return evt.zoomed; + }; + /** + * Update the axis metrics. + * + * @private + * @function Highcharts.Axis#setAxisSize + */ + Axis.prototype.setAxisSize = function () { + var chart = this.chart, options = this.options, + // [top, right, bottom, left] + offsets = options.offsets || [0, 0, 0, 0], horiz = this.horiz, + // Check for percentage based input values. Rounding fixes problems + // with column overflow and plot line filtering (#4898, #4899) + width = this.width = Math.round(relativeLength(pick(options.width, chart.plotWidth - offsets[3] + offsets[1]), chart.plotWidth)), height = this.height = Math.round(relativeLength(pick(options.height, chart.plotHeight - offsets[0] + offsets[2]), chart.plotHeight)), top = this.top = Math.round(relativeLength(pick(options.top, chart.plotTop + offsets[0]), chart.plotHeight, chart.plotTop)), left = this.left = Math.round(relativeLength(pick(options.left, chart.plotLeft + offsets[3]), chart.plotWidth, chart.plotLeft)); + // Expose basic values to use in Series object and navigator + this.bottom = chart.chartHeight - height - top; + this.right = chart.chartWidth - width - left; + // Direction agnostic properties + this.len = Math.max(horiz ? width : height, 0); // Math.max fixes #905 + this.pos = horiz ? left : top; // distance from SVG origin + }; + /** + * Get the current extremes for the axis. + * + * @sample highcharts/members/axis-getextremes/ + * Report extremes by click on a button + * @sample maps/members/axis-getextremes/ + * Get extremes in Highmaps + * + * @function Highcharts.Axis#getExtremes + * + * @return {Highcharts.ExtremesObject} + * An object containing extremes information. + */ + Axis.prototype.getExtremes = function () { + var axis = this; + var log = axis.logarithmic; + return { + min: log ? + correctFloat(log.lin2log(axis.min)) : + axis.min, + max: log ? + correctFloat(log.lin2log(axis.max)) : + axis.max, + dataMin: axis.dataMin, + dataMax: axis.dataMax, + userMin: axis.userMin, + userMax: axis.userMax + }; + }; + /** + * Get the zero plane either based on zero or on the min or max value. + * Used in bar and area plots. + * + * @function Highcharts.Axis#getThreshold + * + * @param {number} threshold + * The threshold in axis values. + * + * @return {number|undefined} + * The translated threshold position in terms of pixels, and corrected to + * stay within the axis bounds. + */ + Axis.prototype.getThreshold = function (threshold) { + var axis = this, log = axis.logarithmic, realMin = log ? log.lin2log(axis.min) : axis.min, realMax = log ? log.lin2log(axis.max) : axis.max; + if (threshold === null || threshold === -Infinity) { + threshold = realMin; + } + else if (threshold === Infinity) { + threshold = realMax; + } + else if (realMin > threshold) { + threshold = realMin; + } + else if (realMax < threshold) { + threshold = realMax; + } + return axis.translate(threshold, 0, 1, 0, 1); + }; + /** + * Compute auto alignment for the axis label based on which side the axis is + * on and the given rotation for the label. + * + * @private + * @function Highcharts.Axis#autoLabelAlign + * + * @param {number} rotation + * The rotation in degrees as set by either the `rotation` or `autoRotation` + * options. + * + * @return {Highcharts.AlignValue} + * Can be `"center"`, `"left"` or `"right"`. + */ + Axis.prototype.autoLabelAlign = function (rotation) { + var angle = (pick(rotation, 0) - (this.side * 90) + 720) % 360, evt = { align: 'center' }; + fireEvent(this, 'autoLabelAlign', evt, function (e) { + if (angle > 15 && angle < 165) { + e.align = 'right'; + } + else if (angle > 195 && angle < 345) { + e.align = 'left'; + } + }); + return evt.align; + }; + /** + * Get the tick length and width for the axis based on axis options. + * @private + * @function Highcharts.Axis#tickSize + * + * @param {string} [prefix] + * 'tick' or 'minorTick' + * + * @return {Array|undefined} + * An array of tickLength and tickWidth + */ + Axis.prototype.tickSize = function (prefix) { + var options = this.options, tickLength = options[prefix === 'tick' ? 'tickLength' : 'minorTickLength'], tickWidth = pick(options[prefix === 'tick' ? 'tickWidth' : 'minorTickWidth'], + // Default to 1 on linear and datetime X axes + prefix === 'tick' && this.isXAxis && !this.categories ? 1 : 0), e, tickSize; + if (tickWidth && tickLength) { + // Negate the length + if (options[prefix + 'Position'] === 'inside') { + tickLength = -tickLength; + } + tickSize = [tickLength, tickWidth]; + } + e = { tickSize: tickSize }; + fireEvent(this, 'afterTickSize', e); + return e.tickSize; + }; + /** + * Return the size of the labels. + * + * @private + * @function Highcharts.Axis#labelMetrics + * + * @return {Highcharts.FontMetricsObject} + */ + Axis.prototype.labelMetrics = function () { + var index = this.tickPositions && this.tickPositions[0] || 0; + return this.chart.renderer.fontMetrics(this.options.labels.style && + this.options.labels.style.fontSize, this.ticks[index] && this.ticks[index].label); + }; + /** + * Prevent the ticks from getting so close we can't draw the labels. On a + * horizontal axis, this is handled by rotating the labels, removing ticks + * and adding ellipsis. On a vertical axis remove ticks and add ellipsis. + * + * @private + * @function Highcharts.Axis#unsquish + * + * @return {number} + */ + Axis.prototype.unsquish = function () { + var labelOptions = this.options.labels, horiz = this.horiz, tickInterval = this.tickInterval, newTickInterval = tickInterval, slotSize = this.len / (((this.categories ? 1 : 0) + + this.max - + this.min) / + tickInterval), rotation, rotationOption = labelOptions.rotation, labelMetrics = this.labelMetrics(), step, bestScore = Number.MAX_VALUE, autoRotation, range = this.max - this.min, + // Return the multiple of tickInterval that is needed to avoid + // collision + getStep = function (spaceNeeded) { + var step = spaceNeeded / (slotSize || 1); + step = step > 1 ? Math.ceil(step) : 1; + // Guard for very small or negative angles (#9835) + if (step * tickInterval > range && + spaceNeeded !== Infinity && + slotSize !== Infinity && + range) { + step = Math.ceil(range / tickInterval); + } + return correctFloat(step * tickInterval); + }; + if (horiz) { + autoRotation = !labelOptions.staggerLines && + !labelOptions.step && + ( // #3971 + defined(rotationOption) ? + [rotationOption] : + slotSize < pick(labelOptions.autoRotationLimit, 80) && labelOptions.autoRotation); + if (autoRotation) { + // Loop over the given autoRotation options, and determine + // which gives the best score. The best score is that with + // the lowest number of steps and a rotation closest + // to horizontal. + autoRotation.forEach(function (rot) { + var score; + if (rot === rotationOption || + (rot && rot >= -90 && rot <= 90)) { // #3891 + step = getStep(Math.abs(labelMetrics.h / Math.sin(deg2rad * rot))); + score = step + Math.abs(rot / 360); + if (score < bestScore) { + bestScore = score; + rotation = rot; + newTickInterval = step; + } + } + }); + } + } + else if (!labelOptions.step) { // #4411 + newTickInterval = getStep(labelMetrics.h); + } + this.autoRotation = autoRotation; + this.labelRotation = pick(rotation, rotationOption); + return newTickInterval; + }; + /** + * Get the general slot width for labels/categories on this axis. This may + * change between the pre-render (from Axis.getOffset) and the final tick + * rendering and placement. + * + * @private + * @function Highcharts.Axis#getSlotWidth + * + * @param {Highcharts.Tick} [tick] Optionally, calculate the slot width + * basing on tick label. It is used in highcharts-3d module, where the slots + * has different widths depending on perspective angles. + * + * @return {number} + * The pixel width allocated to each axis label. + */ + Axis.prototype.getSlotWidth = function (tick) { + var _a; + // #5086, #1580, #1931 + var chart = this.chart, horiz = this.horiz, labelOptions = this.options.labels, slotCount = Math.max(this.tickPositions.length - (this.categories ? 0 : 1), 1), marginLeft = chart.margin[3]; + // Used by grid axis + if (tick && isNumber(tick.slotWidth)) { // #13221, can be 0 + return tick.slotWidth; + } + if (horiz && + labelOptions && + (labelOptions.step || 0) < 2) { + if (labelOptions.rotation) { // #4415 + return 0; + } + return ((this.staggerLines || 1) * this.len) / slotCount; + } + if (!horiz) { + // #7028 + var cssWidth = (_a = labelOptions === null || labelOptions === void 0 ? void 0 : labelOptions.style) === null || _a === void 0 ? void 0 : _a.width; + if (cssWidth !== void 0) { + return parseInt(cssWidth, 10); + } + if (marginLeft) { + return marginLeft - chart.spacing[3]; + } + } + // Last resort, a fraction of the available size + return chart.chartWidth * 0.33; + }; + /** + * Render the axis labels and determine whether ellipsis or rotation need to + * be applied. + * + * @private + * @function Highcharts.Axis#renderUnsquish + */ + Axis.prototype.renderUnsquish = function () { + var chart = this.chart, renderer = chart.renderer, tickPositions = this.tickPositions, ticks = this.ticks, labelOptions = this.options.labels, labelStyleOptions = (labelOptions && labelOptions.style || {}), horiz = this.horiz, slotWidth = this.getSlotWidth(), innerWidth = Math.max(1, Math.round(slotWidth - 2 * (labelOptions.padding || 5))), attr = {}, labelMetrics = this.labelMetrics(), textOverflowOption = (labelOptions.style && + labelOptions.style.textOverflow), commonWidth, commonTextOverflow, maxLabelLength = 0, label, i, pos; + // Set rotation option unless it is "auto", like in gauges + if (!isString(labelOptions.rotation)) { + // #4443: + attr.rotation = labelOptions.rotation || 0; + } + // Get the longest label length + tickPositions.forEach(function (tick) { + tick = ticks[tick]; + // Replace label - sorting animation + if (tick.movedLabel) { + tick.replaceMovedLabel(); + } + if (tick && + tick.label && + tick.label.textPxLength > maxLabelLength) { + maxLabelLength = tick.label.textPxLength; + } + }); + this.maxLabelLength = maxLabelLength; + // Handle auto rotation on horizontal axis + if (this.autoRotation) { + // Apply rotation only if the label is too wide for the slot, and + // the label is wider than its height. + if (maxLabelLength > innerWidth && + maxLabelLength > labelMetrics.h) { + attr.rotation = this.labelRotation; + } + else { + this.labelRotation = 0; + } + // Handle word-wrap or ellipsis on vertical axis + } + else if (slotWidth) { + // For word-wrap or ellipsis + commonWidth = innerWidth; + if (!textOverflowOption) { + commonTextOverflow = 'clip'; + // On vertical axis, only allow word wrap if there is room + // for more lines. + i = tickPositions.length; + while (!horiz && i--) { + pos = tickPositions[i]; + label = ticks[pos].label; + if (label) { + // Reset ellipsis in order to get the correct + // bounding box (#4070) + if (label.styles && + label.styles.textOverflow === 'ellipsis') { + label.css({ textOverflow: 'clip' }); + // Set the correct width in order to read + // the bounding box height (#4678, #5034) + } + else if (label.textPxLength > slotWidth) { + label.css({ width: slotWidth + 'px' }); + } + if (label.getBBox().height > (this.len / tickPositions.length - + (labelMetrics.h - labelMetrics.f))) { + label.specificTextOverflow = 'ellipsis'; + } + } + } + } + } + // Add ellipsis if the label length is significantly longer than ideal + if (attr.rotation) { + commonWidth = (maxLabelLength > chart.chartHeight * 0.5 ? + chart.chartHeight * 0.33 : + maxLabelLength); + if (!textOverflowOption) { + commonTextOverflow = 'ellipsis'; + } + } + // Set the explicit or automatic label alignment + this.labelAlign = labelOptions.align || + this.autoLabelAlign(this.labelRotation); + if (this.labelAlign) { + attr.align = this.labelAlign; + } + // Apply general and specific CSS + tickPositions.forEach(function (pos) { + var tick = ticks[pos], label = tick && tick.label, widthOption = labelStyleOptions.width, css = {}; + if (label) { + // This needs to go before the CSS in old IE (#4502) + label.attr(attr); + if (tick.shortenLabel) { + tick.shortenLabel(); + } + else if (commonWidth && + !widthOption && + // Setting width in this case messes with the bounding box + // (#7975) + labelStyleOptions.whiteSpace !== 'nowrap' && + ( + // Speed optimizing, #7656 + commonWidth < label.textPxLength || + // Resetting CSS, #4928 + label.element.tagName === 'SPAN')) { + css.width = commonWidth + 'px'; + if (!textOverflowOption) { + css.textOverflow = (label.specificTextOverflow || + commonTextOverflow); + } + label.css(css); + // Reset previously shortened label (#8210) + } + else if (label.styles && + label.styles.width && + !css.width && + !widthOption) { + label.css({ width: null }); + } + delete label.specificTextOverflow; + tick.rotation = attr.rotation; + } + }, this); + // Note: Why is this not part of getLabelPosition? + this.tickRotCorr = renderer.rotCorr(labelMetrics.b, this.labelRotation || 0, this.side !== 0); + }; + /** + * Return true if the axis has associated data. + * + * @function Highcharts.Axis#hasData + * + * @return {boolean} + * True if the axis has associated visible series and those series have + * either valid data points or explicit `min` and `max` settings. + */ + Axis.prototype.hasData = function () { + return this.series.some(function (s) { + return s.hasData(); + }) || + (this.options.showEmpty && + defined(this.min) && + defined(this.max)); + }; + /** + * Adds the title defined in axis.options.title. + * + * @function Highcharts.Axis#addTitle + * + * @param {boolean} [display] + * Whether or not to display the title. + */ + Axis.prototype.addTitle = function (display) { + var axis = this, renderer = axis.chart.renderer, horiz = axis.horiz, opposite = axis.opposite, options = axis.options, axisTitleOptions = options.title, textAlign, styledMode = axis.chart.styledMode; + if (!axis.axisTitle) { + textAlign = axisTitleOptions.textAlign; + if (!textAlign) { + textAlign = (horiz ? { + low: 'left', + middle: 'center', + high: 'right' + } : { + low: opposite ? 'right' : 'left', + middle: 'center', + high: opposite ? 'left' : 'right' + })[axisTitleOptions.align]; + } + axis.axisTitle = renderer + .text(axisTitleOptions.text, 0, 0, axisTitleOptions.useHTML) + .attr({ + zIndex: 7, + rotation: axisTitleOptions.rotation || 0, + align: textAlign + }) + .addClass('highcharts-axis-title'); + // #7814, don't mutate style option + if (!styledMode) { + axis.axisTitle.css(merge(axisTitleOptions.style)); + } + axis.axisTitle.add(axis.axisGroup); + axis.axisTitle.isNew = true; + } + // Max width defaults to the length of the axis + if (!styledMode && + !axisTitleOptions.style.width && + !axis.isRadial) { + axis.axisTitle.css({ + width: axis.len + 'px' + }); + } + // hide or show the title depending on whether showEmpty is set + axis.axisTitle[display ? 'show' : 'hide'](display); + }; + /** + * Generates a tick for initial positioning. + * + * @private + * @function Highcharts.Axis#generateTick + * + * @param {number} pos + * The tick position in axis values. + * + * @param {number} [i] + * The index of the tick in {@link Axis.tickPositions}. + */ + Axis.prototype.generateTick = function (pos) { + var axis = this; + var ticks = axis.ticks; + if (!ticks[pos]) { + ticks[pos] = new Tick(axis, pos); + } + else { + ticks[pos].addLabel(); // update labels depending on tick interval + } + }; + /** + * Render the tick labels to a preliminary position to get their sizes + * + * @private + * @function Highcharts.Axis#getOffset + * + * @fires Highcharts.Axis#event:afterGetOffset + */ + Axis.prototype.getOffset = function () { + var axis = this, chart = axis.chart, renderer = chart.renderer, options = axis.options, tickPositions = axis.tickPositions, ticks = axis.ticks, horiz = axis.horiz, side = axis.side, invertedSide = chart.inverted && + !axis.isZAxis ? [1, 0, 3, 2][side] : side, hasData, showAxis, titleOffset = 0, titleOffsetOption, titleMargin = 0, axisTitleOptions = options.title, labelOptions = options.labels, labelOffset = 0, // reset + labelOffsetPadded, axisOffset = chart.axisOffset, clipOffset = chart.clipOffset, clip, directionFactor = [-1, 1, 1, -1][side], className = options.className, axisParent = axis.axisParent, // Used in color axis + lineHeightCorrection; + // For reuse in Axis.render + hasData = axis.hasData(); + axis.showAxis = showAxis = hasData || pick(options.showEmpty, true); + // Set/reset staggerLines + axis.staggerLines = axis.horiz && labelOptions.staggerLines; + // Create the axisGroup and gridGroup elements on first iteration + if (!axis.axisGroup) { + axis.gridGroup = renderer.g('grid') + .attr({ zIndex: options.gridZIndex || 1 }) + .addClass('highcharts-' + this.coll.toLowerCase() + '-grid ' + + (className || '')) + .add(axisParent); + axis.axisGroup = renderer.g('axis') + .attr({ zIndex: options.zIndex || 2 }) + .addClass('highcharts-' + this.coll.toLowerCase() + ' ' + + (className || '')) + .add(axisParent); + axis.labelGroup = renderer.g('axis-labels') + .attr({ zIndex: labelOptions.zIndex || 7 }) + .addClass('highcharts-' + axis.coll.toLowerCase() + '-labels ' + + (className || '')) + .add(axisParent); + } + if (hasData || axis.isLinked) { + // Generate ticks + tickPositions.forEach(function (pos, i) { + // i is not used here, but may be used in overrides + axis.generateTick(pos, i); + }); + axis.renderUnsquish(); + // Left side must be align: right and right side must + // have align: left for labels + axis.reserveSpaceDefault = (side === 0 || + side === 2 || + { 1: 'left', 3: 'right' }[side] === axis.labelAlign); + if (pick(labelOptions.reserveSpace, axis.labelAlign === 'center' ? true : null, axis.reserveSpaceDefault)) { + tickPositions.forEach(function (pos) { + // get the highest offset + labelOffset = Math.max(ticks[pos].getLabelSize(), labelOffset); + }); + } + if (axis.staggerLines) { + labelOffset *= axis.staggerLines; + } + axis.labelOffset = labelOffset * (axis.opposite ? -1 : 1); + } + else { // doesn't have data + objectEach(ticks, function (tick, n) { + tick.destroy(); + delete ticks[n]; + }); + } + if (axisTitleOptions && + axisTitleOptions.text && + axisTitleOptions.enabled !== false) { + axis.addTitle(showAxis); + if (showAxis && axisTitleOptions.reserveSpace !== false) { + axis.titleOffset = titleOffset = + axis.axisTitle.getBBox()[horiz ? 'height' : 'width']; + titleOffsetOption = axisTitleOptions.offset; + titleMargin = defined(titleOffsetOption) ? + 0 : + pick(axisTitleOptions.margin, horiz ? 5 : 10); + } + } + // Render the axis line + axis.renderLine(); + // handle automatic or user set offset + axis.offset = directionFactor * pick(options.offset, axisOffset[side] ? axisOffset[side] + (options.margin || 0) : 0); + axis.tickRotCorr = axis.tickRotCorr || { x: 0, y: 0 }; // polar + if (side === 0) { + lineHeightCorrection = -axis.labelMetrics().h; + } + else if (side === 2) { + lineHeightCorrection = axis.tickRotCorr.y; + } + else { + lineHeightCorrection = 0; + } + // Find the padded label offset + labelOffsetPadded = Math.abs(labelOffset) + titleMargin; + if (labelOffset) { + labelOffsetPadded -= lineHeightCorrection; + labelOffsetPadded += directionFactor * (horiz ? + pick(labelOptions.y, axis.tickRotCorr.y + directionFactor * 8) : + labelOptions.x); + } + axis.axisTitleMargin = pick(titleOffsetOption, labelOffsetPadded); + if (axis.getMaxLabelDimensions) { + axis.maxLabelDimensions = axis.getMaxLabelDimensions(ticks, tickPositions); + } + // Due to GridAxis.tickSize, tickSize should be calculated after ticks + // has rendered. + var tickSize = this.tickSize('tick'); + axisOffset[side] = Math.max(axisOffset[side], axis.axisTitleMargin + titleOffset + + directionFactor * axis.offset, labelOffsetPadded, // #3027 + tickPositions && tickPositions.length && tickSize ? + tickSize[0] + directionFactor * axis.offset : + 0 // #4866 + ); + // Decide the clipping needed to keep the graph inside + // the plot area and axis lines + clip = options.offset ? + 0 : + // #4308, #4371: + Math.floor(axis.axisLine.strokeWidth() / 2) * 2; + clipOffset[invertedSide] = + Math.max(clipOffset[invertedSide], clip); + fireEvent(this, 'afterGetOffset'); + }; + /** + * Internal function to get the path for the axis line. Extended for polar + * charts. + * + * @function Highcharts.Axis#getLinePath + * + * @param {number} lineWidth + * The line width in pixels. + * + * @return {Highcharts.SVGPathArray} + * The SVG path definition in array form. + */ + Axis.prototype.getLinePath = function (lineWidth) { + var chart = this.chart, opposite = this.opposite, offset = this.offset, horiz = this.horiz, lineLeft = this.left + (opposite ? this.width : 0) + offset, lineTop = chart.chartHeight - this.bottom - + (opposite ? this.height : 0) + offset; + if (opposite) { + lineWidth *= -1; // crispify the other way - #1480, #1687 + } + return chart.renderer + .crispLine([ + [ + 'M', + horiz ? + this.left : + lineLeft, + horiz ? + lineTop : + this.top + ], + [ + 'L', + horiz ? + chart.chartWidth - this.right : + lineLeft, + horiz ? + lineTop : + chart.chartHeight - this.bottom + ] + ], lineWidth); + }; + /** + * Render the axis line. Called internally when rendering and redrawing the + * axis. + * + * @function Highcharts.Axis#renderLine + */ + Axis.prototype.renderLine = function () { + if (!this.axisLine) { + this.axisLine = this.chart.renderer.path() + .addClass('highcharts-axis-line') + .add(this.axisGroup); + if (!this.chart.styledMode) { + this.axisLine.attr({ + stroke: this.options.lineColor, + 'stroke-width': this.options.lineWidth, + zIndex: 7 + }); + } + } + }; + /** + * Position the axis title. + * + * @private + * @function Highcharts.Axis#getTitlePosition + * + * @return {Highcharts.PositionObject} + * X and Y positions for the title. + */ + Axis.prototype.getTitlePosition = function () { + // compute anchor points for each of the title align options + var horiz = this.horiz, axisLeft = this.left, axisTop = this.top, axisLength = this.len, axisTitleOptions = this.options.title, margin = horiz ? axisLeft : axisTop, opposite = this.opposite, offset = this.offset, xOption = axisTitleOptions.x || 0, yOption = axisTitleOptions.y || 0, axisTitle = this.axisTitle, fontMetrics = this.chart.renderer.fontMetrics(axisTitleOptions.style && + axisTitleOptions.style.fontSize, axisTitle), + // The part of a multiline text that is below the baseline of the + // first line. Subtract 1 to preserve pixel-perfectness from the + // old behaviour (v5.0.12), where only one line was allowed. + textHeightOvershoot = Math.max(axisTitle.getBBox(null, 0).height - fontMetrics.h - 1, 0), + // the position in the length direction of the axis + alongAxis = { + low: margin + (horiz ? 0 : axisLength), + middle: margin + axisLength / 2, + high: margin + (horiz ? axisLength : 0) + }[axisTitleOptions.align], + // the position in the perpendicular direction of the axis + offAxis = (horiz ? axisTop + this.height : axisLeft) + + (horiz ? 1 : -1) * // horizontal axis reverses the margin + (opposite ? -1 : 1) * // so does opposite axes + this.axisTitleMargin + + [ + -textHeightOvershoot, + textHeightOvershoot, + fontMetrics.f, + -textHeightOvershoot // left + ][this.side], titlePosition = { + x: horiz ? + alongAxis + xOption : + offAxis + (opposite ? this.width : 0) + offset + xOption, + y: horiz ? + offAxis + yOption - (opposite ? this.height : 0) + offset : + alongAxis + yOption + }; + fireEvent(this, 'afterGetTitlePosition', { titlePosition: titlePosition }); + return titlePosition; + }; + /** + * Render a minor tick into the given position. If a minor tick already + * exists in this position, move it. + * + * @function Highcharts.Axis#renderMinorTick + * + * @param {number} pos + * The position in axis values. + */ + Axis.prototype.renderMinorTick = function (pos) { + var axis = this; + var slideInTicks = axis.chart.hasRendered && isNumber(axis.oldMin); + var minorTicks = axis.minorTicks; + if (!minorTicks[pos]) { + minorTicks[pos] = new Tick(axis, pos, 'minor'); + } + // Render new ticks in old position + if (slideInTicks && minorTicks[pos].isNew) { + minorTicks[pos].render(null, true); + } + minorTicks[pos].render(null, false, 1); + }; + /** + * Render a major tick into the given position. If a tick already exists + * in this position, move it. + * + * @function Highcharts.Axis#renderTick + * + * @param {number} pos + * The position in axis values. + * + * @param {number} i + * The tick index. + */ + Axis.prototype.renderTick = function (pos, i) { + var axis = this; + var isLinked = axis.isLinked; + var ticks = axis.ticks; + var slideInTicks = axis.chart.hasRendered && isNumber(axis.oldMin); + // Linked axes need an extra check to find out if + if (!isLinked || + (pos >= axis.min && pos <= axis.max)) { + if (!ticks[pos]) { + ticks[pos] = new Tick(axis, pos); + } + // NOTE this seems like overkill. Could be handled in tick.render by + // setting old position in attr, then set new position in animate. + // render new ticks in old position + if (slideInTicks && ticks[pos].isNew) { + // Start with negative opacity so that it is visible from + // halfway into the animation + ticks[pos].render(i, true, -1); + } + ticks[pos].render(i); + } + }; + /** + * Render the axis. + * + * @private + * @function Highcharts.Axis#render + * + * @fires Highcharts.Axis#event:afterRender + */ + Axis.prototype.render = function () { + var axis = this, chart = axis.chart, log = axis.logarithmic, renderer = chart.renderer, options = axis.options, isLinked = axis.isLinked, tickPositions = axis.tickPositions, axisTitle = axis.axisTitle, ticks = axis.ticks, minorTicks = axis.minorTicks, alternateBands = axis.alternateBands, stackLabelOptions = options.stackLabels, alternateGridColor = options.alternateGridColor, tickmarkOffset = axis.tickmarkOffset, axisLine = axis.axisLine, showAxis = axis.showAxis, animation = animObject(renderer.globalAnimation), from, to; + // Reset + axis.labelEdge.length = 0; + axis.overlap = false; + // Mark all elements inActive before we go over and mark the active ones + [ticks, minorTicks, alternateBands].forEach(function (coll) { + objectEach(coll, function (tick) { + tick.isActive = false; + }); + }); + // If the series has data draw the ticks. Else only the line and title + if (axis.hasData() || isLinked) { + // minor ticks + if (axis.minorTickInterval && !axis.categories) { + axis.getMinorTickPositions().forEach(function (pos) { + axis.renderMinorTick(pos); + }); + } + // Major ticks. Pull out the first item and render it last so that + // we can get the position of the neighbour label. #808. + if (tickPositions.length) { // #1300 + tickPositions.forEach(function (pos, i) { + axis.renderTick(pos, i); + }); + // In a categorized axis, the tick marks are displayed + // between labels. So we need to add a tick mark and + // grid line at the left edge of the X axis. + if (tickmarkOffset && (axis.min === 0 || axis.single)) { + if (!ticks[-1]) { + ticks[-1] = new Tick(axis, -1, null, true); + } + ticks[-1].render(-1); + } + } + // alternate grid color + if (alternateGridColor) { + tickPositions.forEach(function (pos, i) { + to = typeof tickPositions[i + 1] !== 'undefined' ? + tickPositions[i + 1] + tickmarkOffset : + axis.max - tickmarkOffset; + if (i % 2 === 0 && + pos < axis.max && + to <= axis.max + (chart.polar ? + -tickmarkOffset : + tickmarkOffset)) { // #2248, #4660 + if (!alternateBands[pos]) { + // Should be imported from PlotLineOrBand.js, but + // the dependency cycle with axis is a problem + alternateBands[pos] = new H.PlotLineOrBand(axis); + } + from = pos + tickmarkOffset; // #949 + alternateBands[pos].options = { + from: log ? log.lin2log(from) : from, + to: log ? log.lin2log(to) : to, + color: alternateGridColor + }; + alternateBands[pos].render(); + alternateBands[pos].isActive = true; + } + }); + } + // custom plot lines and bands + if (!axis._addedPlotLB) { // only first time + (options.plotLines || []) + .concat(options.plotBands || []) + .forEach(function (plotLineOptions) { + axis.addPlotBandOrLine(plotLineOptions); + }); + axis._addedPlotLB = true; + } + } // end if hasData + // Remove inactive ticks + [ticks, minorTicks, alternateBands].forEach(function (coll) { + var i, forDestruction = [], delay = animation.duration, destroyInactiveItems = function () { + i = forDestruction.length; + while (i--) { + // When resizing rapidly, the same items + // may be destroyed in different timeouts, + // or the may be reactivated + if (coll[forDestruction[i]] && + !coll[forDestruction[i]].isActive) { + coll[forDestruction[i]].destroy(); + delete coll[forDestruction[i]]; + } + } + }; + objectEach(coll, function (tick, pos) { + if (!tick.isActive) { + // Render to zero opacity + tick.render(pos, false, 0); + tick.isActive = false; + forDestruction.push(pos); + } + }); + // When the objects are finished fading out, destroy them + syncTimeout(destroyInactiveItems, coll === alternateBands || + !chart.hasRendered || + !delay ? + 0 : + delay); + }); + // Set the axis line path + if (axisLine) { + axisLine[axisLine.isPlaced ? 'animate' : 'attr']({ + d: this.getLinePath(axisLine.strokeWidth()) + }); + axisLine.isPlaced = true; + // Show or hide the line depending on options.showEmpty + axisLine[showAxis ? 'show' : 'hide'](showAxis); + } + if (axisTitle && showAxis) { + var titleXy = axis.getTitlePosition(); + if (isNumber(titleXy.y)) { + axisTitle[axisTitle.isNew ? 'attr' : 'animate'](titleXy); + axisTitle.isNew = false; + } + else { + axisTitle.attr('y', -9999); + axisTitle.isNew = true; + } + } + // Stacked totals: + if (stackLabelOptions && stackLabelOptions.enabled && axis.stacking) { + axis.stacking.renderStackTotals(); + } + // End stacked totals + axis.isDirty = false; + fireEvent(this, 'afterRender'); + }; + /** + * Redraw the axis to reflect changes in the data or axis extremes. Called + * internally from Highcharts.Chart#redraw. + * + * @private + * @function Highcharts.Axis#redraw + */ + Axis.prototype.redraw = function () { + if (this.visible) { + // render the axis + this.render(); + // move plot lines and bands + this.plotLinesAndBands.forEach(function (plotLine) { + plotLine.render(); + }); + } + // mark associated series as dirty and ready for redraw + this.series.forEach(function (series) { + series.isDirty = true; + }); + }; + /** + * Returns an array of axis properties, that should be untouched during + * reinitialization. + * + * @private + * @function Highcharts.Axis#getKeepProps + * + * @return {Array} + */ + Axis.prototype.getKeepProps = function () { + return (this.keepProps || Axis.keepProps); + }; + /** + * Destroys an Axis instance. See {@link Axis#remove} for the API endpoint + * to fully remove the axis. + * + * @private + * @function Highcharts.Axis#destroy + * + * @param {boolean} [keepEvents] + * Whether to preserve events, used internally in Axis.update. + */ + Axis.prototype.destroy = function (keepEvents) { + var axis = this, plotLinesAndBands = axis.plotLinesAndBands, plotGroup, i; + fireEvent(this, 'destroy', { keepEvents: keepEvents }); + // Remove the events + if (!keepEvents) { + removeEvent(axis); + } + // Destroy collections + [axis.ticks, axis.minorTicks, axis.alternateBands].forEach(function (coll) { + destroyObjectProperties(coll); + }); + if (plotLinesAndBands) { + i = plotLinesAndBands.length; + while (i--) { // #1975 + plotLinesAndBands[i].destroy(); + } + } + // Destroy elements + ['axisLine', 'axisTitle', 'axisGroup', + 'gridGroup', 'labelGroup', 'cross', 'scrollbar'].forEach(function (prop) { + if (axis[prop]) { + axis[prop] = axis[prop].destroy(); + } + }); + // Destroy each generated group for plotlines and plotbands + for (plotGroup in axis.plotLinesAndBandsGroups) { // eslint-disable-line guard-for-in + axis.plotLinesAndBandsGroups[plotGroup] = + axis.plotLinesAndBandsGroups[plotGroup].destroy(); + } + // Delete all properties and fall back to the prototype. + objectEach(axis, function (val, key) { + if (axis.getKeepProps().indexOf(key) === -1) { + delete axis[key]; + } + }); + }; + /** + * Internal function to draw a crosshair. + * + * @function Highcharts.Axis#drawCrosshair + * + * @param {Highcharts.PointerEventObject} [e] + * The event arguments from the modified pointer event, extended with + * `chartX` and `chartY` + * + * @param {Highcharts.Point} [point] + * The Point object if the crosshair snaps to points. + * + * @fires Highcharts.Axis#event:afterDrawCrosshair + * @fires Highcharts.Axis#event:drawCrosshair + */ + Axis.prototype.drawCrosshair = function (e, point) { + var path, options = this.crosshair, snap = pick(options.snap, true), pos, categorized, graphic = this.cross, crossOptions, chart = this.chart; + fireEvent(this, 'drawCrosshair', { e: e, point: point }); + // Use last available event when updating non-snapped crosshairs without + // mouse interaction (#5287) + if (!e) { + e = this.cross && this.cross.e; + } + if ( + // Disabled in options + !this.crosshair || + // Snap + ((defined(point) || !snap) === false)) { + this.hideCrosshair(); + } + else { + // Get the path + if (!snap) { + pos = e && + (this.horiz ? + e.chartX - this.pos : + this.len - e.chartY + this.pos); + } + else if (defined(point)) { + // #3834 + pos = pick(this.coll !== 'colorAxis' ? + point.crosshairPos : // 3D axis extension + null, this.isXAxis ? + point.plotX : + this.len - point.plotY); + } + if (defined(pos)) { + crossOptions = { + // value, only used on radial + value: point && (this.isXAxis ? + point.x : + pick(point.stackY, point.y)), + translatedValue: pos + }; + if (chart.polar) { + // Additional information required for crosshairs in + // polar chart + extend(crossOptions, { + isCrosshair: true, + chartX: e && e.chartX, + chartY: e && e.chartY, + point: point + }); + } + path = this.getPlotLinePath(crossOptions) || + null; // #3189 + } + if (!defined(path)) { + this.hideCrosshair(); + return; + } + categorized = this.categories && !this.isRadial; + // Draw the cross + if (!graphic) { + this.cross = graphic = chart.renderer + .path() + .addClass('highcharts-crosshair highcharts-crosshair-' + + (categorized ? 'category ' : 'thin ') + + options.className) + .attr({ + zIndex: pick(options.zIndex, 2) + }) + .add(); + // Presentational attributes + if (!chart.styledMode) { + graphic.attr({ + stroke: options.color || + (categorized ? + Color + .parse('#ccd6eb') + .setOpacity(0.25) + .get() : + '#cccccc'), + 'stroke-width': pick(options.width, 1) + }).css({ + 'pointer-events': 'none' + }); + if (options.dashStyle) { + graphic.attr({ + dashstyle: options.dashStyle + }); + } + } + } + graphic.show().attr({ + d: path + }); + if (categorized && !options.width) { + graphic.attr({ + 'stroke-width': this.transA + }); + } + this.cross.e = e; + } + fireEvent(this, 'afterDrawCrosshair', { e: e, point: point }); + }; + /** + * Hide the crosshair if visible. + * + * @function Highcharts.Axis#hideCrosshair + */ + Axis.prototype.hideCrosshair = function () { + if (this.cross) { + this.cross.hide(); + } + fireEvent(this, 'afterHideCrosshair'); + }; + /** + * Check whether the chart has vertical panning ('y' or 'xy' type). + * + * @private + * @function Highcharts.Axis#hasVerticalPanning + * @return {boolean} + * + */ + Axis.prototype.hasVerticalPanning = function () { + var _a, _b; + return /y/.test(((_b = (_a = this.chart.options.chart) === null || _a === void 0 ? void 0 : _a.panning) === null || _b === void 0 ? void 0 : _b.type) || ''); + }; + /* * + * + * Static Properties + * + * */ + /** + * The X axis or category axis. Normally this is the horizontal axis, + * though if the chart is inverted this is the vertical axis. In case of + * multiple axes, the xAxis node is an array of configuration objects. + * + * See the [Axis class](/class-reference/Highcharts.Axis) for programmatic + * access to the axis. + * + * @productdesc {highmaps} + * In Highmaps, the axis is hidden, but it is used behind the scenes to + * control features like zooming and panning. Zooming is in effect the same + * as setting the extremes of one of the exes. + * + * @type {*|Array<*>} + * @optionparent xAxis + * + * @private + */ + Axis.defaultOptions = { + /** + * When using multiple axis, the ticks of two or more opposite axes + * will automatically be aligned by adding ticks to the axis or axes + * with the least ticks, as if `tickAmount` were specified. + * + * This can be prevented by setting `alignTicks` to false. If the grid + * lines look messy, it's a good idea to hide them for the secondary + * axis by setting `gridLineWidth` to 0. + * + * If `startOnTick` or `endOnTick` in an Axis options are set to false, + * then the `alignTicks ` will be disabled for the Axis. + * + * Disabled for logarithmic axes. + * + * @type {boolean} + * @default true + * @product highcharts highstock gantt + * @apioption xAxis.alignTicks + */ + /** + * Whether to allow decimals in this axis' ticks. When counting + * integers, like persons or hits on a web page, decimals should + * be avoided in the labels. + * + * @see [minTickInterval](#xAxis.minTickInterval) + * + * @sample {highcharts|highstock} highcharts/yaxis/allowdecimals-true/ + * True by default + * @sample {highcharts|highstock} highcharts/yaxis/allowdecimals-false/ + * False + * + * @type {boolean} + * @default true + * @since 2.0 + * @apioption xAxis.allowDecimals + */ + /** + * When using an alternate grid color, a band is painted across the + * plot area between every other grid line. + * + * @sample {highcharts} highcharts/yaxis/alternategridcolor/ + * Alternate grid color on the Y axis + * @sample {highstock} stock/xaxis/alternategridcolor/ + * Alternate grid color on the Y axis + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption xAxis.alternateGridColor + */ + /** + * An array defining breaks in the axis, the sections defined will be + * left out and all the points shifted closer to each other. + * + * @productdesc {highcharts} + * Requires that the broken-axis.js module is loaded. + * + * @sample {highcharts} highcharts/axisbreak/break-simple/ + * Simple break + * @sample {highcharts|highstock} highcharts/axisbreak/break-visualized/ + * Advanced with callback + * @sample {highstock} stock/demo/intraday-breaks/ + * Break on nights and weekends + * + * @type {Array<*>} + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption xAxis.breaks + */ + /** + * A number indicating how much space should be left between the start + * and the end of the break. The break size is given in axis units, + * so for instance on a `datetime` axis, a break size of 3600000 would + * indicate the equivalent of an hour. + * + * @type {number} + * @default 0 + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption xAxis.breaks.breakSize + */ + /** + * The point where the break starts. + * + * @type {number} + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption xAxis.breaks.from + */ + /** + * Defines an interval after which the break appears again. By default + * the breaks do not repeat. + * + * @type {number} + * @default 0 + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption xAxis.breaks.repeat + */ + /** + * The point where the break ends. + * + * @type {number} + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption xAxis.breaks.to + */ + /** + * If categories are present for the xAxis, names are used instead of + * numbers for that axis. + * + * Since Highcharts 3.0, categories can also + * be extracted by giving each point a [name](#series.data) and setting + * axis [type](#xAxis.type) to `category`. However, if you have multiple + * series, best practice remains defining the `categories` array. + * + * Example: `categories: ['Apples', 'Bananas', 'Oranges']` + * + * @sample {highcharts} highcharts/demo/line-labels/ + * With + * @sample {highcharts} highcharts/xaxis/categories/ + * Without + * + * @type {Array} + * @product highcharts gantt + * @apioption xAxis.categories + */ + /** + * The highest allowed value for automatically computed axis extremes. + * + * @see [floor](#xAxis.floor) + * + * @sample {highcharts|highstock} highcharts/yaxis/floor-ceiling/ + * Floor and ceiling + * + * @type {number} + * @since 4.0 + * @product highcharts highstock gantt + * @apioption xAxis.ceiling + */ + /** + * A class name that opens for styling the axis by CSS, especially in + * Highcharts styled mode. The class name is applied to group elements + * for the grid, axis elements and labels. + * + * @sample {highcharts|highstock|highmaps} highcharts/css/axis/ + * Multiple axes with separate styling + * + * @type {string} + * @since 5.0.0 + * @apioption xAxis.className + */ + /** + * Configure a crosshair that follows either the mouse pointer or the + * hovered point. + * + * In styled mode, the crosshairs are styled in the + * `.highcharts-crosshair`, `.highcharts-crosshair-thin` or + * `.highcharts-xaxis-category` classes. + * + * @productdesc {highstock} + * In Highstock, by default, the crosshair is enabled on the X axis and + * disabled on the Y axis. + * + * @sample {highcharts} highcharts/xaxis/crosshair-both/ + * Crosshair on both axes + * @sample {highstock} stock/xaxis/crosshairs-xy/ + * Crosshair on both axes + * @sample {highmaps} highcharts/xaxis/crosshair-both/ + * Crosshair on both axes + * + * @declare Highcharts.AxisCrosshairOptions + * @type {boolean|*} + * @default false + * @since 4.1 + * @apioption xAxis.crosshair + */ + /** + * A class name for the crosshair, especially as a hook for styling. + * + * @type {string} + * @since 5.0.0 + * @apioption xAxis.crosshair.className + */ + /** + * The color of the crosshair. Defaults to `#cccccc` for numeric and + * datetime axes, and `rgba(204,214,235,0.25)` for category axes, where + * the crosshair by default highlights the whole category. + * + * @sample {highcharts|highstock|highmaps} highcharts/xaxis/crosshair-customized/ + * Customized crosshairs + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #cccccc + * @since 4.1 + * @apioption xAxis.crosshair.color + */ + /** + * The dash style for the crosshair. See + * [plotOptions.series.dashStyle](#plotOptions.series.dashStyle) + * for possible values. + * + * @sample {highcharts|highmaps} highcharts/xaxis/crosshair-dotted/ + * Dotted crosshair + * @sample {highstock} stock/xaxis/crosshair-dashed/ + * Dashed X axis crosshair + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 4.1 + * @apioption xAxis.crosshair.dashStyle + */ + /** + * A label on the axis next to the crosshair. + * + * In styled mode, the label is styled with the + * `.highcharts-crosshair-label` class. + * + * @sample {highstock} stock/xaxis/crosshair-label/ + * Crosshair labels + * @sample {highstock} highcharts/css/crosshair-label/ + * Style mode + * + * @declare Highcharts.AxisCrosshairLabelOptions + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label + */ + /** + * Alignment of the label compared to the axis. Defaults to `"left"` for + * right-side axes, `"right"` for left-side axes and `"center"` for + * horizontal axes. + * + * @type {Highcharts.AlignValue} + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.align + */ + /** + * The background color for the label. Defaults to the related series + * color, or `#666666` if that is not available. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.backgroundColor + */ + /** + * The border color for the crosshair label + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.borderColor + */ + /** + * The border corner radius of the crosshair label. + * + * @type {number} + * @default 3 + * @since 2.1.10 + * @product highstock + * @apioption xAxis.crosshair.label.borderRadius + */ + /** + * The border width for the crosshair label. + * + * @type {number} + * @default 0 + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.borderWidth + */ + /** + * Flag to enable crosshair's label. + * + * @sample {highstock} stock/xaxis/crosshairs-xy/ + * Enabled label for yAxis' crosshair + * + * @type {boolean} + * @default false + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.enabled + */ + /** + * A format string for the crosshair label. Defaults to `{value}` for + * numeric axes and `{value:%b %d, %Y}` for datetime axes. + * + * @type {string} + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.format + */ + /** + * Formatter function for the label text. + * + * @type {Highcharts.XAxisCrosshairLabelFormatterCallbackFunction} + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.formatter + */ + /** + * Padding inside the crosshair label. + * + * @type {number} + * @default 8 + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.padding + */ + /** + * The shape to use for the label box. + * + * @type {string} + * @default callout + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.shape + */ + /** + * Text styles for the crosshair label. + * + * @type {Highcharts.CSSObject} + * @default {"color": "white", "fontWeight": "normal", "fontSize": "11px", "textAlign": "center"} + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.style + */ + /** + * Whether the crosshair should snap to the point or follow the pointer + * independent of points. + * + * @sample {highcharts|highstock} highcharts/xaxis/crosshair-snap-false/ + * True by default + * @sample {highmaps} maps/demo/latlon-advanced/ + * Snap is false + * + * @type {boolean} + * @default true + * @since 4.1 + * @apioption xAxis.crosshair.snap + */ + /** + * The pixel width of the crosshair. Defaults to 1 for numeric or + * datetime axes, and for one category width for category axes. + * + * @sample {highcharts} highcharts/xaxis/crosshair-customized/ + * Customized crosshairs + * @sample {highstock} highcharts/xaxis/crosshair-customized/ + * Customized crosshairs + * @sample {highmaps} highcharts/xaxis/crosshair-customized/ + * Customized crosshairs + * + * @type {number} + * @default 1 + * @since 4.1 + * @apioption xAxis.crosshair.width + */ + /** + * The Z index of the crosshair. Higher Z indices allow drawing the + * crosshair on top of the series or behind the grid lines. + * + * @type {number} + * @default 2 + * @since 4.1 + * @apioption xAxis.crosshair.zIndex + */ + /** + * Whether to zoom axis. If `chart.zoomType` is set, the option allows + * to disable zooming on an individual axis. + * + * @sample {highcharts} highcharts/xaxis/zoomenabled/ + * Zoom enabled is false + * + * + * @type {boolean} + * @default enabled + * @apioption xAxis.zoomEnabled + */ + /** + * For a datetime axis, the scale will automatically adjust to the + * appropriate unit. This member gives the default string + * representations used for each unit. For intermediate values, + * different units may be used, for example the `day` unit can be used + * on midnight and `hour` unit be used for intermediate values on the + * same axis. For an overview of the replacement codes, see + * [dateFormat](/class-reference/Highcharts#dateFormat). + * + * Defaults to: + * ```js + * { + * millisecond: '%H:%M:%S.%L', + * second: '%H:%M:%S', + * minute: '%H:%M', + * hour: '%H:%M', + * day: '%e. %b', + * week: '%e. %b', + * month: '%b \'%y', + * year: '%Y' + * } + * ``` + * + * @sample {highcharts} highcharts/xaxis/datetimelabelformats/ + * Different day format on X axis + * @sample {highstock} stock/xaxis/datetimelabelformats/ + * More information in x axis labels + * + * @declare Highcharts.AxisDateTimeLabelFormatsOptions + * @product highcharts highstock gantt + */ + dateTimeLabelFormats: { + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + millisecond: { + main: '%H:%M:%S.%L', + range: false + }, + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + second: { + main: '%H:%M:%S', + range: false + }, + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + minute: { + main: '%H:%M', + range: false + }, + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + hour: { + main: '%H:%M', + range: false + }, + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + day: { + main: '%e. %b' + }, + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + week: { + main: '%e. %b' + }, + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + month: { + main: '%b \'%y' + }, + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + year: { + main: '%Y' + } + }, + /** + * Whether to force the axis to end on a tick. Use this option with + * the `maxPadding` option to control the axis end. + * + * @productdesc {highstock} + * In Highstock, `endOnTick` is always `false` when the navigator + * is enabled, to prevent jumpy scrolling. + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * True by default + * @sample {highcharts} highcharts/yaxis/endontick/ + * False + * @sample {highstock} stock/demo/basic-line/ + * True by default + * @sample {highstock} stock/xaxis/endontick/ + * False + * + * @since 1.2.0 + */ + endOnTick: false, + /** + * Event handlers for the axis. + * + * @type {*} + * @apioption xAxis.events + */ + /** + * An event fired after the breaks have rendered. + * + * @see [breaks](#xAxis.breaks) + * + * @sample {highcharts} highcharts/axisbreak/break-event/ + * AfterBreak Event + * + * @type {Highcharts.AxisEventCallbackFunction} + * @since 4.1.0 + * @product highcharts gantt + * @apioption xAxis.events.afterBreaks + */ + /** + * As opposed to the `setExtremes` event, this event fires after the + * final min and max values are computed and corrected for `minRange`. + * + * Fires when the minimum and maximum is set for the axis, either by + * calling the `.setExtremes()` method or by selecting an area in the + * chart. One parameter, `event`, is passed to the function, containing + * common event information. + * + * The new user set minimum and maximum values can be found by + * `event.min` and `event.max`. These reflect the axis minimum and + * maximum in axis values. The actual data extremes are found in + * `event.dataMin` and `event.dataMax`. + * + * @type {Highcharts.AxisSetExtremesEventCallbackFunction} + * @since 2.3 + * @context Highcharts.Axis + * @apioption xAxis.events.afterSetExtremes + */ + /** + * An event fired when a break from this axis occurs on a point. + * + * @see [breaks](#xAxis.breaks) + * + * @sample {highcharts} highcharts/axisbreak/break-visualized/ + * Visualization of a Break + * + * @type {Highcharts.AxisPointBreakEventCallbackFunction} + * @since 4.1.0 + * @product highcharts gantt + * @context Highcharts.Axis + * @apioption xAxis.events.pointBreak + */ + /** + * An event fired when a point falls inside a break from this axis. + * + * @type {Highcharts.AxisPointBreakEventCallbackFunction} + * @product highcharts highstock gantt + * @context Highcharts.Axis + * @apioption xAxis.events.pointInBreak + */ + /** + * Fires when the minimum and maximum is set for the axis, either by + * calling the `.setExtremes()` method or by selecting an area in the + * chart. One parameter, `event`, is passed to the function, + * containing common event information. + * + * The new user set minimum and maximum values can be found by + * `event.min` and `event.max`. These reflect the axis minimum and + * maximum in data values. When an axis is zoomed all the way out from + * the "Reset zoom" button, `event.min` and `event.max` are null, and + * the new extremes are set based on `this.dataMin` and `this.dataMax`. + * + * @sample {highstock} stock/xaxis/events-setextremes/ + * Log new extremes on x axis + * + * @type {Highcharts.AxisSetExtremesEventCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Axis + * @apioption xAxis.events.setExtremes + */ + /** + * The lowest allowed value for automatically computed axis extremes. + * + * @see [ceiling](#yAxis.ceiling) + * + * @sample {highcharts} highcharts/yaxis/floor-ceiling/ + * Floor and ceiling + * @sample {highstock} stock/demo/lazy-loading/ + * Prevent negative stock price on Y axis + * + * @type {number} + * @since 4.0 + * @product highcharts highstock gantt + * @apioption xAxis.floor + */ + /** + * The dash or dot style of the grid lines. For possible values, see + * [this demonstration](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/). + * + * @sample {highcharts} highcharts/yaxis/gridlinedashstyle/ + * Long dashes + * @sample {highstock} stock/xaxis/gridlinedashstyle/ + * Long dashes + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 1.2 + * @apioption xAxis.gridLineDashStyle + */ + /** + * The Z index of the grid lines. + * + * @sample {highcharts|highstock} highcharts/xaxis/gridzindex/ + * A Z index of 4 renders the grid above the graph + * + * @type {number} + * @default 1 + * @product highcharts highstock gantt + * @apioption xAxis.gridZIndex + */ + /** + * An id for the axis. This can be used after render time to get + * a pointer to the axis object through `chart.get()`. + * + * @sample {highcharts} highcharts/xaxis/id/ + * Get the object + * @sample {highstock} stock/xaxis/id/ + * Get the object + * + * @type {string} + * @since 1.2.0 + * @apioption xAxis.id + */ + /** + * The axis labels show the number or category for each tick. + * + * Since v8.0.0: Labels are animated in categorized x-axis with + * updating data if `tickInterval` and `step` is set to 1. + * + * @productdesc {highmaps} + * X and Y axis labels are by default disabled in Highmaps, but the + * functionality is inherited from Highcharts and used on `colorAxis`, + * and can be enabled on X and Y axes too. + */ + labels: { + /** + * What part of the string the given position is anchored to. + * If `left`, the left side of the string is at the axis position. + * Can be one of `"left"`, `"center"` or `"right"`. Defaults to + * an intelligent guess based on which side of the chart the axis + * is on and the rotation of the label. + * + * @see [reserveSpace](#xAxis.labels.reserveSpace) + * + * @sample {highcharts} highcharts/xaxis/labels-align-left/ + * Left + * @sample {highcharts} highcharts/xaxis/labels-align-right/ + * Right + * @sample {highcharts} highcharts/xaxis/labels-reservespace-true/ + * Left-aligned labels on a vertical category axis + * + * @type {Highcharts.AlignValue} + * @apioption xAxis.labels.align + */ + /** + * For horizontal axes, the allowed degrees of label rotation + * to prevent overlapping labels. If there is enough space, + * labels are not rotated. As the chart gets narrower, it + * will start rotating the labels -45 degrees, then remove + * every second label and try again with rotations 0 and -45 etc. + * Set it to `false` to disable rotation, which will + * cause the labels to word-wrap if possible. + * + * @sample {highcharts|highstock} highcharts/xaxis/labels-autorotation-default/ + * Default auto rotation of 0 or -45 + * @sample {highcharts|highstock} highcharts/xaxis/labels-autorotation-0-90/ + * Custom graded auto rotation + * + * @type {Array|false} + * @default [-45] + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption xAxis.labels.autoRotation + */ + /** + * When each category width is more than this many pixels, we don't + * apply auto rotation. Instead, we lay out the axis label with word + * wrap. A lower limit makes sense when the label contains multiple + * short words that don't extend the available horizontal space for + * each label. + * + * @sample {highcharts} highcharts/xaxis/labels-autorotationlimit/ + * Lower limit + * + * @type {number} + * @default 80 + * @since 4.1.5 + * @product highcharts gantt + * @apioption xAxis.labels.autoRotationLimit + */ + /** + * Polar charts only. The label's pixel distance from the perimeter + * of the plot area. + * + * @type {number} + * @default 15 + * @product highcharts gantt + * @apioption xAxis.labels.distance + */ + /** + * Enable or disable the axis labels. + * + * @sample {highcharts} highcharts/xaxis/labels-enabled/ + * X axis labels disabled + * @sample {highstock} stock/xaxis/labels-enabled/ + * X axis labels disabled + * + * @default {highcharts|highstock|gantt} true + * @default {highmaps} false + */ + enabled: true, + /** + * A [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) + * for the axis label. + * + * @sample {highcharts|highstock} highcharts/yaxis/labels-format/ + * Add units to Y axis label + * + * @type {string} + * @default {value} + * @since 3.0 + * @apioption xAxis.labels.format + */ + /** + * Callback JavaScript function to format the label. The value + * is given by `this.value`. Additional properties for `this` are + * `axis`, `chart`, `isFirst` and `isLast`. The value of the default + * label formatter can be retrieved by calling + * `this.axis.defaultLabelFormatter.call(this)` within the function. + * + * Defaults to: + * ```js + * function() { + * return this.value; + * } + * ``` + * + * @sample {highcharts} highcharts/xaxis/labels-formatter-linked/ + * Linked category names + * @sample {highcharts} highcharts/xaxis/labels-formatter-extended/ + * Modified numeric labels + * @sample {highstock} stock/xaxis/labels-formatter/ + * Added units on Y axis + * + * @type {Highcharts.FormatterCallbackFunction} + * @apioption xAxis.labels.formatter + */ + /** + * The number of pixels to indent the labels per level in a treegrid + * axis. + * + * @sample gantt/treegrid-axis/demo + * Indentation 10px by default. + * @sample gantt/treegrid-axis/indentation-0px + * Indentation set to 0px. + * + * @product gantt + */ + indentation: 10, + /** + * Horizontal axis only. When `staggerLines` is not set, + * `maxStaggerLines` defines how many lines the axis is allowed to + * add to automatically avoid overlapping X labels. Set to `1` to + * disable overlap detection. + * + * @deprecated + * @type {number} + * @default 5 + * @since 1.3.3 + * @apioption xAxis.labels.maxStaggerLines + */ + /** + * How to handle overflowing labels on horizontal axis. If set to + * `"allow"`, it will not be aligned at all. By default it + * `"justify"` labels inside the chart area. If there is room to + * move it, it will be aligned to the edge, else it will be removed. + * + * @type {string} + * @default justify + * @since 2.2.5 + * @validvalue ["allow", "justify"] + * @apioption xAxis.labels.overflow + */ + /** + * The pixel padding for axis labels, to ensure white space between + * them. + * + * @type {number} + * @default 5 + * @product highcharts gantt + * @apioption xAxis.labels.padding + */ + /** + * Whether to reserve space for the labels. By default, space is + * reserved for the labels in these cases: + * + * * On all horizontal axes. + * * On vertical axes if `label.align` is `right` on a left-side + * axis or `left` on a right-side axis. + * * On vertical axes if `label.align` is `center`. + * + * This can be turned off when for example the labels are rendered + * inside the plot area instead of outside. + * + * @see [labels.align](#xAxis.labels.align) + * + * @sample {highcharts} highcharts/xaxis/labels-reservespace/ + * No reserved space, labels inside plot + * @sample {highcharts} highcharts/xaxis/labels-reservespace-true/ + * Left-aligned labels on a vertical category axis + * + * @type {boolean} + * @since 4.1.10 + * @product highcharts gantt + * @apioption xAxis.labels.reserveSpace + */ + /** + * Rotation of the labels in degrees. + * + * @sample {highcharts} highcharts/xaxis/labels-rotation/ + * X axis labels rotated 90° + * + * @type {number} + * @default 0 + * @apioption xAxis.labels.rotation + */ + /** + * Horizontal axes only. The number of lines to spread the labels + * over to make room or tighter labels. + * + * @sample {highcharts} highcharts/xaxis/labels-staggerlines/ + * Show labels over two lines + * @sample {highstock} stock/xaxis/labels-staggerlines/ + * Show labels over two lines + * + * @type {number} + * @since 2.1 + * @apioption xAxis.labels.staggerLines + */ + /** + * To show only every _n_'th label on the axis, set the step to _n_. + * Setting the step to 2 shows every other label. + * + * By default, the step is calculated automatically to avoid + * overlap. To prevent this, set it to 1\. This usually only + * happens on a category axis, and is often a sign that you have + * chosen the wrong axis type. + * + * Read more at + * [Axis docs](https://www.highcharts.com/docs/chart-concepts/axes) + * => What axis should I use? + * + * @sample {highcharts} highcharts/xaxis/labels-step/ + * Showing only every other axis label on a categorized + * x-axis + * @sample {highcharts} highcharts/xaxis/labels-step-auto/ + * Auto steps on a category axis + * + * @type {number} + * @since 2.1 + * @apioption xAxis.labels.step + */ + /** + * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the labels. + * + * @type {boolean} + * @default false + * @apioption xAxis.labels.useHTML + */ + /** + * The x position offset of the label relative to the tick position + * on the axis. + * + * @sample {highcharts} highcharts/xaxis/labels-x/ + * Y axis labels placed on grid lines + */ + x: 0, + /** + * The y position offset of the label relative to the tick position + * on the axis. The default makes it adapt to the font size on + * bottom axis. + * + * @sample {highcharts} highcharts/xaxis/labels-x/ + * Y axis labels placed on grid lines + * + * @type {number} + * @apioption xAxis.labels.y + */ + /** + * The Z index for the axis labels. + * + * @type {number} + * @default 7 + * @apioption xAxis.labels.zIndex + */ + /** + * CSS styles for the label. Use `whiteSpace: 'nowrap'` to prevent + * wrapping of category labels. Use `textOverflow: 'none'` to + * prevent ellipsis (dots). + * + * In styled mode, the labels are styled with the + * `.highcharts-axis-labels` class. + * + * @sample {highcharts} highcharts/xaxis/labels-style/ + * Red X axis labels + * + * @type {Highcharts.CSSObject} + */ + style: { + /** @internal */ + color: '#666666', + /** @internal */ + cursor: 'default', + /** @internal */ + fontSize: '11px' + } + }, + /** + * The left position as the horizontal axis. If it's a number, it is + * interpreted as pixel position relative to the chart. + * + * Since Highcharts v5.0.13: If it's a percentage string, it is + * interpreted as percentages of the plot width, offset from plot area + * left. + * + * @type {number|string} + * @product highcharts highstock + * @apioption xAxis.left + */ + /** + * The top position as the vertical axis. If it's a number, it is + * interpreted as pixel position relative to the chart. + * + * Since Highcharts 2: If it's a percentage string, it is interpreted + * as percentages of the plot height, offset from plot area top. + * + * @type {number|string} + * @product highcharts highstock + * @apioption xAxis.top + */ + /** + * Index of another axis that this axis is linked to. When an axis is + * linked to a master axis, it will take the same extremes as + * the master, but as assigned by min or max or by setExtremes. + * It can be used to show additional info, or to ease reading the + * chart by duplicating the scales. + * + * @sample {highcharts} highcharts/xaxis/linkedto/ + * Different string formats of the same date + * @sample {highcharts} highcharts/yaxis/linkedto/ + * Y values on both sides + * + * @type {number} + * @since 2.0.2 + * @product highcharts highstock gantt + * @apioption xAxis.linkedTo + */ + /** + * The maximum value of the axis. If `null`, the max value is + * automatically calculated. + * + * If the [endOnTick](#yAxis.endOnTick) option is true, the `max` value + * might be rounded up. + * + * If a [tickAmount](#yAxis.tickAmount) is set, the axis may be extended + * beyond the set max in order to reach the given number of ticks. The + * same may happen in a chart with multiple axes, determined by [chart. + * alignTicks](#chart), where a `tickAmount` is applied internally. + * + * @sample {highcharts} highcharts/yaxis/max-200/ + * Y axis max of 200 + * @sample {highcharts} highcharts/yaxis/max-logarithmic/ + * Y axis max on logarithmic axis + * @sample {highstock} stock/xaxis/min-max/ + * Fixed min and max on X axis + * @sample {highmaps} maps/axis/min-max/ + * Pre-zoomed to a specific area + * + * @type {number|null} + * @apioption xAxis.max + */ + /** + * Padding of the max value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. This is useful + * when you don't want the highest data value to appear on the edge + * of the plot area. When the axis' `max` option is set or a max extreme + * is set using `axis.setExtremes()`, the maxPadding will be ignored. + * + * @sample {highcharts} highcharts/yaxis/maxpadding/ + * Max padding of 0.25 on y axis + * @sample {highstock} stock/xaxis/minpadding-maxpadding/ + * Greater min- and maxPadding + * @sample {highmaps} maps/chart/plotbackgroundcolor-gradient/ + * Add some padding + * + * @default {highcharts} 0.01 + * @default {highstock|highmaps} 0 + * @since 1.2.0 + */ + maxPadding: 0.01, + /** + * Deprecated. Use `minRange` instead. + * + * @deprecated + * @type {number} + * @product highcharts highstock + * @apioption xAxis.maxZoom + */ + /** + * The minimum value of the axis. If `null` the min value is + * automatically calculated. + * + * If the [startOnTick](#yAxis.startOnTick) option is true (default), + * the `min` value might be rounded down. + * + * The automatically calculated minimum value is also affected by + * [floor](#yAxis.floor), [softMin](#yAxis.softMin), + * [minPadding](#yAxis.minPadding), [minRange](#yAxis.minRange) + * as well as [series.threshold](#plotOptions.series.threshold) + * and [series.softThreshold](#plotOptions.series.softThreshold). + * + * @sample {highcharts} highcharts/yaxis/min-startontick-false/ + * -50 with startOnTick to false + * @sample {highcharts} highcharts/yaxis/min-startontick-true/ + * -50 with startOnTick true by default + * @sample {highstock} stock/xaxis/min-max/ + * Set min and max on X axis + * @sample {highmaps} maps/axis/min-max/ + * Pre-zoomed to a specific area + * + * @type {number|null} + * @apioption xAxis.min + */ + /** + * The dash or dot style of the minor grid lines. For possible values, + * see [this demonstration](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/). + * + * @sample {highcharts} highcharts/yaxis/minorgridlinedashstyle/ + * Long dashes on minor grid lines + * @sample {highstock} stock/xaxis/minorgridlinedashstyle/ + * Long dashes on minor grid lines + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 1.2 + * @apioption xAxis.minorGridLineDashStyle + */ + /** + * Specific tick interval in axis units for the minor ticks. On a linear + * axis, if `"auto"`, the minor tick interval is calculated as a fifth + * of the tickInterval. If `null` or `undefined`, minor ticks are not + * shown. + * + * On logarithmic axes, the unit is the power of the value. For example, + * setting the minorTickInterval to 1 puts one tick on each of 0.1, 1, + * 10, 100 etc. Setting the minorTickInterval to 0.1 produces 9 ticks + * between 1 and 10, 10 and 100 etc. + * + * If user settings dictate minor ticks to become too dense, they don't + * make sense, and will be ignored to prevent performance problems. + * + * @sample {highcharts} highcharts/yaxis/minortickinterval-null/ + * Null by default + * @sample {highcharts} highcharts/yaxis/minortickinterval-5/ + * 5 units + * @sample {highcharts} highcharts/yaxis/minortickinterval-log-auto/ + * "auto" + * @sample {highcharts} highcharts/yaxis/minortickinterval-log/ + * 0.1 + * @sample {highstock} stock/demo/basic-line/ + * Null by default + * @sample {highstock} stock/xaxis/minortickinterval-auto/ + * "auto" + * + * @type {number|string|null} + * @apioption xAxis.minorTickInterval + */ + /** + * The pixel length of the minor tick marks. + * + * @sample {highcharts} highcharts/yaxis/minorticklength/ + * 10px on Y axis + * @sample {highstock} stock/xaxis/minorticks/ + * 10px on Y axis + */ + minorTickLength: 2, + /** + * The position of the minor tick marks relative to the axis line. + * Can be one of `inside` and `outside`. + * + * @sample {highcharts} highcharts/yaxis/minortickposition-outside/ + * Outside by default + * @sample {highcharts} highcharts/yaxis/minortickposition-inside/ + * Inside + * @sample {highstock} stock/xaxis/minorticks/ + * Inside + * + * @validvalue ["inside", "outside"] + */ + minorTickPosition: 'outside', + /** + * Enable or disable minor ticks. Unless + * [minorTickInterval](#xAxis.minorTickInterval) is set, the tick + * interval is calculated as a fifth of the `tickInterval`. + * + * On a logarithmic axis, minor ticks are laid out based on a best + * guess, attempting to enter approximately 5 minor ticks between + * each major tick. + * + * Prior to v6.0.0, ticks were unabled in auto layout by setting + * `minorTickInterval` to `"auto"`. + * + * @productdesc {highcharts} + * On axes using [categories](#xAxis.categories), minor ticks are not + * supported. + * + * @sample {highcharts} highcharts/yaxis/minorticks-true/ + * Enabled on linear Y axis + * + * @type {boolean} + * @default false + * @since 6.0.0 + * @apioption xAxis.minorTicks + */ + /** + * The pixel width of the minor tick mark. + * + * @sample {highcharts} highcharts/yaxis/minortickwidth/ + * 3px width + * @sample {highstock} stock/xaxis/minorticks/ + * 1px width + * + * @type {number} + * @default 0 + * @apioption xAxis.minorTickWidth + */ + /** + * Padding of the min value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. This is useful + * when you don't want the lowest data value to appear on the edge + * of the plot area. When the axis' `min` option is set or a min extreme + * is set using `axis.setExtremes()`, the minPadding will be ignored. + * + * @sample {highcharts} highcharts/yaxis/minpadding/ + * Min padding of 0.2 + * @sample {highstock} stock/xaxis/minpadding-maxpadding/ + * Greater min- and maxPadding + * @sample {highmaps} maps/chart/plotbackgroundcolor-gradient/ + * Add some padding + * + * @default {highcharts} 0.01 + * @default {highstock|highmaps} 0 + * @since 1.2.0 + * @product highcharts highstock gantt + */ + minPadding: 0.01, + /** + * The minimum range to display on this axis. The entire axis will not + * be allowed to span over a smaller interval than this. For example, + * for a datetime axis the main unit is milliseconds. If minRange is + * set to 3600000, you can't zoom in more than to one hour. + * + * The default minRange for the x axis is five times the smallest + * interval between any of the data points. + * + * On a logarithmic axis, the unit for the minimum range is the power. + * So a minRange of 1 means that the axis can be zoomed to 10-100, + * 100-1000, 1000-10000 etc. + * + * Note that the `minPadding`, `maxPadding`, `startOnTick` and + * `endOnTick` settings also affect how the extremes of the axis + * are computed. + * + * @sample {highcharts} highcharts/xaxis/minrange/ + * Minimum range of 5 + * @sample {highstock} stock/xaxis/minrange/ + * Max zoom of 6 months overrides user selections + * @sample {highmaps} maps/axis/minrange/ + * Minimum range of 1000 + * + * @type {number} + * @apioption xAxis.minRange + */ + /** + * The minimum tick interval allowed in axis values. For example on + * zooming in on an axis with daily data, this can be used to prevent + * the axis from showing hours. Defaults to the closest distance between + * two points on the axis. + * + * @type {number} + * @since 2.3.0 + * @apioption xAxis.minTickInterval + */ + /** + * The distance in pixels from the plot area to the axis line. + * A positive offset moves the axis with it's line, labels and ticks + * away from the plot area. This is typically used when two or more + * axes are displayed on the same side of the plot. With multiple + * axes the offset is dynamically adjusted to avoid collision, this + * can be overridden by setting offset explicitly. + * + * @sample {highcharts} highcharts/yaxis/offset/ + * Y axis offset of 70 + * @sample {highcharts} highcharts/yaxis/offset-centered/ + * Axes positioned in the center of the plot + * @sample {highstock} stock/xaxis/offset/ + * Y axis offset by 70 px + * + * @type {number} + * @default 0 + * @apioption xAxis.offset + */ + /** + * Whether to display the axis on the opposite side of the normal. The + * normal is on the left side for vertical axes and bottom for + * horizontal, so the opposite sides will be right and top respectively. + * This is typically used with dual or multiple axes. + * + * @sample {highcharts} highcharts/yaxis/opposite/ + * Secondary Y axis opposite + * @sample {highstock} stock/xaxis/opposite/ + * Y axis on left side + * + * @type {boolean} + * @default false + * @apioption xAxis.opposite + */ + /** + * In an ordinal axis, the points are equally spaced in the chart + * regardless of the actual time or x distance between them. This means + * that missing data periods (e.g. nights or weekends for a stock chart) + * will not take up space in the chart. + * Having `ordinal: false` will show any gaps created by the `gapSize` + * setting proportionate to their duration. + * + * In stock charts the X axis is ordinal by default, unless + * the boost module is used and at least one of the series' data length + * exceeds the [boostThreshold](#series.line.boostThreshold). + * + * @sample {highstock} stock/xaxis/ordinal-true/ + * True by default + * @sample {highstock} stock/xaxis/ordinal-false/ + * False + * + * @type {boolean} + * @default true + * @since 1.1 + * @product highstock + * @apioption xAxis.ordinal + */ + /** + * Additional range on the right side of the xAxis. Works similar to + * `xAxis.maxPadding`, but value is set in milliseconds. Can be set for + * both main `xAxis` and the navigator's `xAxis`. + * + * @sample {highstock} stock/xaxis/overscroll/ + * One minute overscroll with live data + * + * @type {number} + * @default 0 + * @since 6.0.0 + * @product highstock + * @apioption xAxis.overscroll + */ + /** + * Refers to the index in the [panes](#panes) array. Used for circular + * gauges and polar charts. When the option is not set then first pane + * will be used. + * + * @sample highcharts/demo/gauge-vu-meter + * Two gauges with different center + * + * @type {number} + * @product highcharts + * @apioption xAxis.pane + */ + /** + * The zoomed range to display when only defining one or none of `min` + * or `max`. For example, to show the latest month, a range of one month + * can be set. + * + * @sample {highstock} stock/xaxis/range/ + * Setting a zoomed range when the rangeSelector is disabled + * + * @type {number} + * @product highstock + * @apioption xAxis.range + */ + /** + * Whether to reverse the axis so that the highest number is closest + * to the origin. If the chart is inverted, the x axis is reversed by + * default. + * + * @sample {highcharts} highcharts/yaxis/reversed/ + * Reversed Y axis + * @sample {highstock} stock/xaxis/reversed/ + * Reversed Y axis + * + * @type {boolean} + * @default false + * @apioption xAxis.reversed + */ + // reversed: false, + /** + * This option determines how stacks should be ordered within a group. + * For example reversed xAxis also reverses stacks, so first series + * comes last in a group. To keep order like for non-reversed xAxis + * enable this option. + * + * @sample {highcharts} highcharts/xaxis/reversedstacks/ + * Reversed stacks comparison + * @sample {highstock} highcharts/xaxis/reversedstacks/ + * Reversed stacks comparison + * + * @type {boolean} + * @default false + * @since 6.1.1 + * @product highcharts highstock + * @apioption xAxis.reversedStacks + */ + /** + * An optional scrollbar to display on the X axis in response to + * limiting the minimum and maximum of the axis values. + * + * In styled mode, all the presentational options for the scrollbar are + * replaced by the classes `.highcharts-scrollbar-thumb`, + * `.highcharts-scrollbar-arrow`, `.highcharts-scrollbar-button`, + * `.highcharts-scrollbar-rifles` and `.highcharts-scrollbar-track`. + * + * @sample {highstock} stock/yaxis/heatmap-scrollbars/ + * Heatmap with both scrollbars + * + * @extends scrollbar + * @since 4.2.6 + * @product highstock + * @apioption xAxis.scrollbar + */ + /** + * Whether to show the axis line and title when the axis has no data. + * + * @sample {highcharts} highcharts/yaxis/showempty/ + * When clicking the legend to hide series, one axis preserves + * line and title, the other doesn't + * @sample {highstock} highcharts/yaxis/showempty/ + * When clicking the legend to hide series, one axis preserves + * line and title, the other doesn't + * + * @since 1.1 + */ + showEmpty: true, + /** + * Whether to show the first tick label. + * + * @sample {highcharts} highcharts/xaxis/showfirstlabel-false/ + * Set to false on X axis + * @sample {highstock} stock/xaxis/showfirstlabel/ + * Labels below plot lines on Y axis + * + * @type {boolean} + * @default true + * @apioption xAxis.showFirstLabel + */ + /** + * Whether to show the last tick label. Defaults to `true` on cartesian + * charts, and `false` on polar charts. + * + * @sample {highcharts} highcharts/xaxis/showlastlabel-true/ + * Set to true on X axis + * @sample {highstock} stock/xaxis/showfirstlabel/ + * Labels below plot lines on Y axis + * + * @type {boolean} + * @default true + * @product highcharts highstock gantt + * @apioption xAxis.showLastLabel + */ + /** + * A soft maximum for the axis. If the series data maximum is less than + * this, the axis will stay at this maximum, but if the series data + * maximum is higher, the axis will flex to show all data. + * + * @sample highcharts/yaxis/softmin-softmax/ + * Soft min and max + * + * @type {number} + * @since 5.0.1 + * @product highcharts highstock gantt + * @apioption xAxis.softMax + */ + /** + * A soft minimum for the axis. If the series data minimum is greater + * than this, the axis will stay at this minimum, but if the series + * data minimum is lower, the axis will flex to show all data. + * + * @sample highcharts/yaxis/softmin-softmax/ + * Soft min and max + * + * @type {number} + * @since 5.0.1 + * @product highcharts highstock gantt + * @apioption xAxis.softMin + */ + /** + * For datetime axes, this decides where to put the tick between weeks. + * 0 = Sunday, 1 = Monday. + * + * @sample {highcharts} highcharts/xaxis/startofweek-monday/ + * Monday by default + * @sample {highcharts} highcharts/xaxis/startofweek-sunday/ + * Sunday + * @sample {highstock} stock/xaxis/startofweek-1 + * Monday by default + * @sample {highstock} stock/xaxis/startofweek-0 + * Sunday + * + * @product highcharts highstock gantt + */ + startOfWeek: 1, + /** + * Whether to force the axis to start on a tick. Use this option with + * the `minPadding` option to control the axis start. + * + * @productdesc {highstock} + * In Highstock, `startOnTick` is always `false` when the navigator + * is enabled, to prevent jumpy scrolling. + * + * @sample {highcharts} highcharts/xaxis/startontick-false/ + * False by default + * @sample {highcharts} highcharts/xaxis/startontick-true/ + * True + * + * @since 1.2.0 + */ + startOnTick: false, + /** + * The amount of ticks to draw on the axis. This opens up for aligning + * the ticks of multiple charts or panes within a chart. This option + * overrides the `tickPixelInterval` option. + * + * This option only has an effect on linear axes. Datetime, logarithmic + * or category axes are not affected. + * + * @sample {highcharts} highcharts/yaxis/tickamount/ + * 8 ticks on Y axis + * @sample {highstock} highcharts/yaxis/tickamount/ + * 8 ticks on Y axis + * + * @type {number} + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption xAxis.tickAmount + */ + /** + * The interval of the tick marks in axis units. When `undefined`, the + * tick interval is computed to approximately follow the + * [tickPixelInterval](#xAxis.tickPixelInterval) on linear and datetime + * axes. On categorized axes, a `undefined` tickInterval will default to + * 1, one category. Note that datetime axes are based on milliseconds, + * so for example an interval of one day is expressed as + * `24 * 3600 * 1000`. + * + * On logarithmic axes, the tickInterval is based on powers, so a + * tickInterval of 1 means one tick on each of 0.1, 1, 10, 100 etc. A + * tickInterval of 2 means a tick of 0.1, 10, 1000 etc. A tickInterval + * of 0.2 puts a tick on 0.1, 0.2, 0.4, 0.6, 0.8, 1, 2, 4, 6, 8, 10, 20, + * 40 etc. + * + * + * If the tickInterval is too dense for labels to be drawn, Highcharts + * may remove ticks. + * + * If the chart has multiple axes, the [alignTicks](#chart.alignTicks) + * option may interfere with the `tickInterval` setting. + * + * @see [tickPixelInterval](#xAxis.tickPixelInterval) + * @see [tickPositions](#xAxis.tickPositions) + * @see [tickPositioner](#xAxis.tickPositioner) + * + * @sample {highcharts} highcharts/xaxis/tickinterval-5/ + * Tick interval of 5 on a linear axis + * @sample {highstock} stock/xaxis/tickinterval/ + * Tick interval of 0.01 on Y axis + * + * @type {number} + * @apioption xAxis.tickInterval + */ + /** + * The pixel length of the main tick marks. + * + * @sample {highcharts} highcharts/xaxis/ticklength/ + * 20 px tick length on the X axis + * @sample {highstock} stock/xaxis/ticks/ + * Formatted ticks on X axis + */ + tickLength: 10, + /** + * If tickInterval is `null` this option sets the approximate pixel + * interval of the tick marks. Not applicable to categorized axis. + * + * The tick interval is also influenced by the [minTickInterval]( + * #xAxis.minTickInterval) option, that, by default prevents ticks from + * being denser than the data points. + * + * @see [tickInterval](#xAxis.tickInterval) + * @see [tickPositioner](#xAxis.tickPositioner) + * @see [tickPositions](#xAxis.tickPositions) + * + * @sample {highcharts} highcharts/xaxis/tickpixelinterval-50/ + * 50 px on X axis + * @sample {highstock} stock/xaxis/tickpixelinterval/ + * 200 px on X axis + */ + tickPixelInterval: 100, + /** + * For categorized axes only. If `on` the tick mark is placed in the + * center of the category, if `between` the tick mark is placed between + * categories. The default is `between` if the `tickInterval` is 1, else + * `on`. + * + * @sample {highcharts} highcharts/xaxis/tickmarkplacement-between/ + * "between" by default + * @sample {highcharts} highcharts/xaxis/tickmarkplacement-on/ + * "on" + * + * @product highcharts gantt + * @validvalue ["on", "between"] + */ + tickmarkPlacement: 'between', + /** + * The position of the major tick marks relative to the axis line. + * Can be one of `inside` and `outside`. + * + * @sample {highcharts} highcharts/xaxis/tickposition-outside/ + * "outside" by default + * @sample {highcharts} highcharts/xaxis/tickposition-inside/ + * "inside" + * @sample {highstock} stock/xaxis/ticks/ + * Formatted ticks on X axis + * + * @validvalue ["inside", "outside"] + */ + tickPosition: 'outside', + /** + * A callback function returning array defining where the ticks are + * laid out on the axis. This overrides the default behaviour of + * [tickPixelInterval](#xAxis.tickPixelInterval) and [tickInterval]( + * #xAxis.tickInterval). The automatic tick positions are accessible + * through `this.tickPositions` and can be modified by the callback. + * + * @see [tickPositions](#xAxis.tickPositions) + * + * @sample {highcharts} highcharts/xaxis/tickpositions-tickpositioner/ + * Demo of tickPositions and tickPositioner + * @sample {highstock} highcharts/xaxis/tickpositions-tickpositioner/ + * Demo of tickPositions and tickPositioner + * + * @type {Highcharts.AxisTickPositionerCallbackFunction} + * @apioption xAxis.tickPositioner + */ + /** + * An array defining where the ticks are laid out on the axis. This + * overrides the default behaviour of [tickPixelInterval]( + * #xAxis.tickPixelInterval) and [tickInterval](#xAxis.tickInterval). + * + * @see [tickPositioner](#xAxis.tickPositioner) + * + * @sample {highcharts} highcharts/xaxis/tickpositions-tickpositioner/ + * Demo of tickPositions and tickPositioner + * @sample {highstock} highcharts/xaxis/tickpositions-tickpositioner/ + * Demo of tickPositions and tickPositioner + * + * @type {Array} + * @apioption xAxis.tickPositions + */ + /** + * The pixel width of the major tick marks. Defaults to 0 on category + * axes, otherwise 1. + * + * In styled mode, the stroke width is given in the `.highcharts-tick` + * class, but in order for the element to be generated on category axes, + * the option must be explicitly set to 1. + * + * @sample {highcharts} highcharts/xaxis/tickwidth/ + * 10 px width + * @sample {highcharts} highcharts/css/axis-grid/ + * Styled mode + * @sample {highstock} stock/xaxis/ticks/ + * Formatted ticks on X axis + * @sample {highstock} highcharts/css/axis-grid/ + * Styled mode + * + * @type {undefined|number} + * @default {highstock} 1 + * @default {highmaps} 0 + * @apioption xAxis.tickWidth + */ + /** + * The axis title, showing next to the axis line. + * + * @productdesc {highmaps} + * In Highmaps, the axis is hidden by default, but adding an axis title + * is still possible. X axis and Y axis titles will appear at the bottom + * and left by default. + */ + title: { + /** + * Deprecated. Set the `text` to `null` to disable the title. + * + * @deprecated + * @type {boolean} + * @product highcharts + * @apioption xAxis.title.enabled + */ + /** + * The pixel distance between the axis labels or line and the title. + * Defaults to 0 for horizontal axes, 10 for vertical + * + * @sample {highcharts} highcharts/xaxis/title-margin/ + * Y axis title margin of 60 + * + * @type {number} + * @apioption xAxis.title.margin + */ + /** + * The distance of the axis title from the axis line. By default, + * this distance is computed from the offset width of the labels, + * the labels' distance from the axis and the title's margin. + * However when the offset option is set, it overrides all this. + * + * @sample {highcharts} highcharts/yaxis/title-offset/ + * Place the axis title on top of the axis + * @sample {highstock} highcharts/yaxis/title-offset/ + * Place the axis title on top of the Y axis + * + * @type {number} + * @since 2.2.0 + * @apioption xAxis.title.offset + */ + /** + * Whether to reserve space for the title when laying out the axis. + * + * @type {boolean} + * @default true + * @since 5.0.11 + * @product highcharts highstock gantt + * @apioption xAxis.title.reserveSpace + */ + /** + * The rotation of the text in degrees. 0 is horizontal, 270 is + * vertical reading from bottom to top. + * + * @sample {highcharts} highcharts/yaxis/title-offset/ + * Horizontal + * + * @type {number} + * @default 0 + * @apioption xAxis.title.rotation + */ + /** + * The actual text of the axis title. It can contain basic HTML tags + * like `b`, `i` and `span` with style. + * + * @sample {highcharts} highcharts/xaxis/title-text/ + * Custom HTML + * @sample {highstock} stock/xaxis/title-text/ + * Titles for both axes + * + * @type {string|null} + * @apioption xAxis.title.text + */ + /** + * Alignment of the text, can be `"left"`, `"right"` or `"center"`. + * Default alignment depends on the + * [title.align](xAxis.title.align): + * + * Horizontal axes: + * - for `align` = `"low"`, `textAlign` is set to `left` + * - for `align` = `"middle"`, `textAlign` is set to `center` + * - for `align` = `"high"`, `textAlign` is set to `right` + * + * Vertical axes: + * - for `align` = `"low"` and `opposite` = `true`, `textAlign` is + * set to `right` + * - for `align` = `"low"` and `opposite` = `false`, `textAlign` is + * set to `left` + * - for `align` = `"middle"`, `textAlign` is set to `center` + * - for `align` = `"high"` and `opposite` = `true` `textAlign` is + * set to `left` + * - for `align` = `"high"` and `opposite` = `false` `textAlign` is + * set to `right` + * + * @type {Highcharts.AlignValue} + * @apioption xAxis.title.textAlign + */ + /** + * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the axis title. + * + * @type {boolean} + * @default false + * @product highcharts highstock gantt + * @apioption xAxis.title.useHTML + */ + /** + * Horizontal pixel offset of the title position. + * + * @type {number} + * @default 0 + * @since 4.1.6 + * @product highcharts highstock gantt + * @apioption xAxis.title.x + */ + /** + * Vertical pixel offset of the title position. + * + * @type {number} + * @product highcharts highstock gantt + * @apioption xAxis.title.y + */ + /** + * Alignment of the title relative to the axis values. Possible + * values are "low", "middle" or "high". + * + * @sample {highcharts} highcharts/xaxis/title-align-low/ + * "low" + * @sample {highcharts} highcharts/xaxis/title-align-center/ + * "middle" by default + * @sample {highcharts} highcharts/xaxis/title-align-high/ + * "high" + * @sample {highcharts} highcharts/yaxis/title-offset/ + * Place the Y axis title on top of the axis + * @sample {highstock} stock/xaxis/title-align/ + * Aligned to "high" value + * + * @type {Highcharts.AxisTitleAlignValue} + */ + align: 'middle', + /** + * CSS styles for the title. If the title text is longer than the + * axis length, it will wrap to multiple lines by default. This can + * be customized by setting `textOverflow: 'ellipsis'`, by + * setting a specific `width` or by setting `whiteSpace: 'nowrap'`. + * + * In styled mode, the stroke width is given in the + * `.highcharts-axis-title` class. + * + * @sample {highcharts} highcharts/xaxis/title-style/ + * Red + * @sample {highcharts} highcharts/css/axis/ + * Styled mode + * + * @type {Highcharts.CSSObject} + */ + style: { + /** @internal */ + color: '#666666' + } + }, + /** + * The type of axis. Can be one of `linear`, `logarithmic`, `datetime` + * or `category`. In a datetime axis, the numbers are given in + * milliseconds, and tick marks are placed on appropriate values like + * full hours or days. In a category axis, the + * [point names](#series.line.data.name) of the chart's series are used + * for categories, if not a [categories](#xAxis.categories) array is + * defined. + * + * @sample {highcharts} highcharts/xaxis/type-linear/ + * Linear + * @sample {highcharts} highcharts/yaxis/type-log/ + * Logarithmic + * @sample {highcharts} highcharts/yaxis/type-log-minorgrid/ + * Logarithmic with minor grid lines + * @sample {highcharts} highcharts/xaxis/type-log-both/ + * Logarithmic on two axes + * @sample {highcharts} highcharts/yaxis/type-log-negative/ + * Logarithmic with extension to emulate negative values + * + * @type {Highcharts.AxisTypeValue} + * @product highcharts gantt + */ + type: 'linear', + /** + * If there are multiple axes on the same side of the chart, the pixel + * margin between the axes. Defaults to 0 on vertical axes, 15 on + * horizontal axes. + * + * @type {number} + * @since 7.0.3 + * @apioption xAxis.margin + */ + /** + * Applies only when the axis `type` is `category`. When `uniqueNames` + * is true, points are placed on the X axis according to their names. + * If the same point name is repeated in the same or another series, + * the point is placed on the same X position as other points of the + * same name. When `uniqueNames` is false, the points are laid out in + * increasing X positions regardless of their names, and the X axis + * category will take the name of the last point in each position. + * + * @sample {highcharts} highcharts/xaxis/uniquenames-true/ + * True by default + * @sample {highcharts} highcharts/xaxis/uniquenames-false/ + * False + * + * @type {boolean} + * @default true + * @since 4.2.7 + * @product highcharts gantt + * @apioption xAxis.uniqueNames + */ + /** + * Datetime axis only. An array determining what time intervals the + * ticks are allowed to fall on. Each array item is an array where the + * first value is the time unit and the second value another array of + * allowed multiples. + * + * Defaults to: + * ```js + * units: [[ + * 'millisecond', // unit name + * [1, 2, 5, 10, 20, 25, 50, 100, 200, 500] // allowed multiples + * ], [ + * 'second', + * [1, 2, 5, 10, 15, 30] + * ], [ + * 'minute', + * [1, 2, 5, 10, 15, 30] + * ], [ + * 'hour', + * [1, 2, 3, 4, 6, 8, 12] + * ], [ + * 'day', + * [1] + * ], [ + * 'week', + * [1] + * ], [ + * 'month', + * [1, 3, 6] + * ], [ + * 'year', + * null + * ]] + * ``` + * + * @type {Array|null)>>} + * @product highcharts highstock gantt + * @apioption xAxis.units + */ + /** + * Whether axis, including axis title, line, ticks and labels, should + * be visible. + * + * @type {boolean} + * @default true + * @since 4.1.9 + * @product highcharts highstock gantt + * @apioption xAxis.visible + */ + /** + * Color of the minor, secondary grid lines. + * + * In styled mode, the stroke width is given in the + * `.highcharts-minor-grid-line` class. + * + * @sample {highcharts} highcharts/yaxis/minorgridlinecolor/ + * Bright grey lines from Y axis + * @sample {highcharts|highstock} highcharts/css/axis-grid/ + * Styled mode + * @sample {highstock} stock/xaxis/minorgridlinecolor/ + * Bright grey lines from Y axis + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #f2f2f2 + */ + minorGridLineColor: '#f2f2f2', + /** + * Width of the minor, secondary grid lines. + * + * In styled mode, the stroke width is given in the + * `.highcharts-grid-line` class. + * + * @sample {highcharts} highcharts/yaxis/minorgridlinewidth/ + * 2px lines from Y axis + * @sample {highcharts|highstock} highcharts/css/axis-grid/ + * Styled mode + * @sample {highstock} stock/xaxis/minorgridlinewidth/ + * 2px lines from Y axis + */ + minorGridLineWidth: 1, + /** + * Color for the minor tick marks. + * + * @sample {highcharts} highcharts/yaxis/minortickcolor/ + * Black tick marks on Y axis + * @sample {highstock} stock/xaxis/minorticks/ + * Black tick marks on Y axis + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #999999 + */ + minorTickColor: '#999999', + /** + * The color of the line marking the axis itself. + * + * In styled mode, the line stroke is given in the + * `.highcharts-axis-line` or `.highcharts-xaxis-line` class. + * + * @productdesc {highmaps} + * In Highmaps, the axis line is hidden by default, because the axis is + * not visible by default. + * + * @sample {highcharts} highcharts/yaxis/linecolor/ + * A red line on Y axis + * @sample {highcharts|highstock} highcharts/css/axis/ + * Axes in styled mode + * @sample {highstock} stock/xaxis/linecolor/ + * A red line on X axis + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #ccd6eb + */ + lineColor: '#ccd6eb', + /** + * The width of the line marking the axis itself. + * + * In styled mode, the stroke width is given in the + * `.highcharts-axis-line` or `.highcharts-xaxis-line` class. + * + * @sample {highcharts} highcharts/yaxis/linecolor/ + * A 1px line on Y axis + * @sample {highcharts|highstock} highcharts/css/axis/ + * Axes in styled mode + * @sample {highstock} stock/xaxis/linewidth/ + * A 2px line on X axis + * + * @default {highcharts|highstock} 1 + * @default {highmaps} 0 + */ + lineWidth: 1, + /** + * Color of the grid lines extending the ticks across the plot area. + * + * In styled mode, the stroke is given in the `.highcharts-grid-line` + * class. + * + * @productdesc {highmaps} + * In Highmaps, the grid lines are hidden by default. + * + * @sample {highcharts} highcharts/yaxis/gridlinecolor/ + * Green lines + * @sample {highcharts|highstock} highcharts/css/axis-grid/ + * Styled mode + * @sample {highstock} stock/xaxis/gridlinecolor/ + * Green lines + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #e6e6e6 + */ + gridLineColor: '#e6e6e6', + // gridLineDashStyle: 'solid', + /** + * The width of the grid lines extending the ticks across the plot area. + * + * In styled mode, the stroke width is given in the + * `.highcharts-grid-line` class. + * + * @sample {highcharts} highcharts/yaxis/gridlinewidth/ + * 2px lines + * @sample {highcharts|highstock} highcharts/css/axis-grid/ + * Styled mode + * @sample {highstock} stock/xaxis/gridlinewidth/ + * 2px lines + * + * @type {number} + * @default 0 + * @apioption xAxis.gridLineWidth + */ + // gridLineWidth: 0, + /** + * The height as the vertical axis. If it's a number, it is + * interpreted as pixels. + * + * Since Highcharts 2: If it's a percentage string, it is interpreted + * as percentages of the total plot height. + * + * @type {number|string} + * @product highcharts highstock + * @apioption xAxis.height + */ + /** + * The width as the horizontal axis. If it's a number, it is interpreted + * as pixels. + * + * Since Highcharts v5.0.13: If it's a percentage string, it is + * interpreted as percentages of the total plot width. + * + * @type {number|string} + * @product highcharts highstock + * @apioption xAxis.width + */ + /** + * Color for the main tick marks. + * + * In styled mode, the stroke is given in the `.highcharts-tick` + * class. + * + * @sample {highcharts} highcharts/xaxis/tickcolor/ + * Red ticks on X axis + * @sample {highcharts|highstock} highcharts/css/axis-grid/ + * Styled mode + * @sample {highstock} stock/xaxis/ticks/ + * Formatted ticks on X axis + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #ccd6eb + */ + tickColor: '#ccd6eb' + // tickWidth: 1 + }; + /** + * The Y axis or value axis. Normally this is the vertical axis, + * though if the chart is inverted this is the horizontal axis. + * In case of multiple axes, the yAxis node is an array of + * configuration objects. + * + * See [the Axis object](/class-reference/Highcharts.Axis) for programmatic + * access to the axis. + * + * @type {*|Array<*>} + * @extends xAxis + * @excluding currentDateIndicator,ordinal,overscroll + * @optionparent yAxis + * + * @private + */ + Axis.defaultYAxisOptions = { + /** + * The type of axis. Can be one of `linear`, `logarithmic`, `datetime`, + * `category` or `treegrid`. Defaults to `treegrid` for Gantt charts, + * `linear` for other chart types. + * + * In a datetime axis, the numbers are given in milliseconds, and tick + * marks are placed on appropriate values, like full hours or days. In a + * category or treegrid axis, the [point names](#series.line.data.name) + * of the chart's series are used for categories, if a + * [categories](#xAxis.categories) array is not defined. + * + * @sample {highcharts} highcharts/yaxis/type-log-minorgrid/ + * Logarithmic with minor grid lines + * @sample {highcharts} highcharts/yaxis/type-log-negative/ + * Logarithmic with extension to emulate negative values + * @sample {gantt} gantt/treegrid-axis/demo + * Treegrid axis + * + * @type {Highcharts.AxisTypeValue} + * @default {highcharts} linear + * @default {gantt} treegrid + * @product highcharts gantt + * @apioption yAxis.type + */ + /** + * The height of the Y axis. If it's a number, it is interpreted as + * pixels. + * + * Since Highcharts 2: If it's a percentage string, it is interpreted as + * percentages of the total plot height. + * + * @see [yAxis.top](#yAxis.top) + * + * @sample {highstock} stock/demo/candlestick-and-volume/ + * Percentage height panes + * + * @type {number|string} + * @product highcharts highstock + * @apioption yAxis.height + */ + /** + * Solid gauge only. Unless [stops](#yAxis.stops) are set, the color + * to represent the maximum value of the Y axis. + * + * @sample {highcharts} highcharts/yaxis/mincolor-maxcolor/ + * Min and max colors + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #003399 + * @since 4.0 + * @product highcharts + * @apioption yAxis.maxColor + */ + /** + * Solid gauge only. Unless [stops](#yAxis.stops) are set, the color + * to represent the minimum value of the Y axis. + * + * @sample {highcharts} highcharts/yaxis/mincolor-maxcolor/ + * Min and max color + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #e6ebf5 + * @since 4.0 + * @product highcharts + * @apioption yAxis.minColor + */ + /** + * Whether to reverse the axis so that the highest number is closest + * to the origin. + * + * @sample {highcharts} highcharts/yaxis/reversed/ + * Reversed Y axis + * @sample {highstock} stock/xaxis/reversed/ + * Reversed Y axis + * + * @type {boolean} + * @default {highcharts} false + * @default {highstock} false + * @default {highmaps} true + * @default {gantt} true + * @apioption yAxis.reversed + */ + /** + * If `true`, the first series in a stack will be drawn on top in a + * positive, non-reversed Y axis. If `false`, the first series is in + * the base of the stack. + * + * @sample {highcharts} highcharts/yaxis/reversedstacks-false/ + * Non-reversed stacks + * @sample {highstock} highcharts/yaxis/reversedstacks-false/ + * Non-reversed stacks + * + * @type {boolean} + * @default true + * @since 3.0.10 + * @product highcharts highstock + * @apioption yAxis.reversedStacks + */ + /** + * Solid gauge series only. Color stops for the solid gauge. Use this + * in cases where a linear gradient between a `minColor` and `maxColor` + * is not sufficient. The stops is an array of tuples, where the first + * item is a float between 0 and 1 assigning the relative position in + * the gradient, and the second item is the color. + * + * For solid gauges, the Y axis also inherits the concept of + * [data classes](https://api.highcharts.com/highmaps#colorAxis.dataClasses) + * from the Highmaps color axis. + * + * @see [minColor](#yAxis.minColor) + * @see [maxColor](#yAxis.maxColor) + * + * @sample {highcharts} highcharts/demo/gauge-solid/ + * True by default + * + * @type {Array} + * @since 4.0 + * @product highcharts + * @apioption yAxis.stops + */ + /** + * The pixel width of the major tick marks. + * + * @sample {highcharts} highcharts/xaxis/tickwidth/ 10 px width + * @sample {highstock} stock/xaxis/ticks/ Formatted ticks on X axis + * + * @type {number} + * @default 0 + * @product highcharts highstock gantt + * @apioption yAxis.tickWidth + */ + /** + * Angular gauges and solid gauges only. + * The label's pixel distance from the perimeter of the plot area. + * + * Since v7.1.2: If it's a percentage string, it is interpreted the + * same as [series.radius](#plotOptions.gauge.radius), so label can be + * aligned under the gauge's shape. + * + * @sample {highcharts} highcharts/yaxis/labels-distance/ + * Labels centered under the arc + * + * @type {number|string} + * @default -25 + * @product highcharts + * @apioption yAxis.labels.distance + */ + /** + * The y position offset of the label relative to the tick position + * on the axis. + * + * @sample {highcharts} highcharts/xaxis/labels-x/ + * Y axis labels placed on grid lines + * + * @type {number} + * @default {highcharts} 3 + * @default {highstock} -2 + * @default {highmaps} 3 + * @apioption yAxis.labels.y + */ + /** + * Whether to force the axis to end on a tick. Use this option with + * the `maxPadding` option to control the axis end. + * + * This option is always disabled, when panning type is + * either `y` or `xy`. + * + * @see [type](#chart.panning.type) + * + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * True by default + * @sample {highcharts} highcharts/yaxis/endontick/ + * False + * @sample {highstock} stock/demo/basic-line/ + * True by default + * @sample {highstock} stock/xaxis/endontick/ + * False for Y axis + * + * @since 1.2.0 + */ + endOnTick: true, + /** + * Padding of the max value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. This is useful + * when you don't want the highest data value to appear on the edge + * of the plot area. When the axis' `max` option is set or a max extreme + * is set using `axis.setExtremes()`, the maxPadding will be ignored. + * + * Also the `softThreshold` option takes precedence over `maxPadding`, + * so if the data is tangent to the threshold, `maxPadding` may not + * apply unless `softThreshold` is set to false. + * + * @sample {highcharts} highcharts/yaxis/maxpadding-02/ + * Max padding of 0.2 + * @sample {highstock} stock/xaxis/minpadding-maxpadding/ + * Greater min- and maxPadding + * + * @since 1.2.0 + * @product highcharts highstock gantt + */ + maxPadding: 0.05, + /** + * Padding of the min value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. This is useful + * when you don't want the lowest data value to appear on the edge + * of the plot area. When the axis' `min` option is set or a max extreme + * is set using `axis.setExtremes()`, the maxPadding will be ignored. + * + * Also the `softThreshold` option takes precedence over `minPadding`, + * so if the data is tangent to the threshold, `minPadding` may not + * apply unless `softThreshold` is set to false. + * + * @sample {highcharts} highcharts/yaxis/minpadding/ + * Min padding of 0.2 + * @sample {highstock} stock/xaxis/minpadding-maxpadding/ + * Greater min- and maxPadding + * + * @since 1.2.0 + * @product highcharts highstock gantt + */ + minPadding: 0.05, + /** + * @productdesc {highstock} + * In Highstock 1.x, the Y axis was placed on the left side by default. + * + * @sample {highcharts} highcharts/yaxis/opposite/ + * Secondary Y axis opposite + * @sample {highstock} stock/xaxis/opposite/ + * Y axis on left side + * + * @type {boolean} + * @default {highstock} true + * @default {highcharts} false + * @product highstock highcharts gantt + * @apioption yAxis.opposite + */ + /** + * @see [tickInterval](#xAxis.tickInterval) + * @see [tickPositioner](#xAxis.tickPositioner) + * @see [tickPositions](#xAxis.tickPositions) + */ + tickPixelInterval: 72, + showLastLabel: true, + /** + * @extends xAxis.labels + */ + labels: { + /** + * What part of the string the given position is anchored to. Can + * be one of `"left"`, `"center"` or `"right"`. The exact position + * also depends on the `labels.x` setting. + * + * Angular gauges and solid gauges defaults to `"center"`. + * Solid gauges with two labels have additional option `"auto"` + * for automatic horizontal and vertical alignment. + * + * @see [yAxis.labels.distance](#yAxis.labels.distance) + * + * @sample {highcharts} highcharts/yaxis/labels-align-left/ + * Left + * @sample {highcharts} highcharts/series-solidgauge/labels-auto-aligned/ + * Solid gauge labels auto aligned + * + * @type {Highcharts.AlignValue} + * @default {highcharts|highmaps} right + * @default {highstock} left + * @apioption yAxis.labels.align + */ + /** + * The x position offset of the label relative to the tick position + * on the axis. Defaults to -15 for left axis, 15 for right axis. + * + * @sample {highcharts} highcharts/xaxis/labels-x/ + * Y axis labels placed on grid lines + */ + x: -8 + }, + /** + * @productdesc {highmaps} + * In Highmaps, the axis line is hidden by default, because the axis is + * not visible by default. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption yAxis.lineColor + */ + /** + * @sample {highcharts} highcharts/yaxis/max-200/ + * Y axis max of 200 + * @sample {highcharts} highcharts/yaxis/max-logarithmic/ + * Y axis max on logarithmic axis + * @sample {highstock} stock/yaxis/min-max/ + * Fixed min and max on Y axis + * @sample {highmaps} maps/axis/min-max/ + * Pre-zoomed to a specific area + * + * @apioption yAxis.max + */ + /** + * @sample {highcharts} highcharts/yaxis/min-startontick-false/ + * -50 with startOnTick to false + * @sample {highcharts} highcharts/yaxis/min-startontick-true/ + * -50 with startOnTick true by default + * @sample {highstock} stock/yaxis/min-max/ + * Fixed min and max on Y axis + * @sample {highmaps} maps/axis/min-max/ + * Pre-zoomed to a specific area + * + * @apioption yAxis.min + */ + /** + * An optional scrollbar to display on the Y axis in response to + * limiting the minimum an maximum of the axis values. + * + * In styled mode, all the presentational options for the scrollbar + * are replaced by the classes `.highcharts-scrollbar-thumb`, + * `.highcharts-scrollbar-arrow`, `.highcharts-scrollbar-button`, + * `.highcharts-scrollbar-rifles` and `.highcharts-scrollbar-track`. + * + * @sample {highstock} stock/yaxis/scrollbar/ + * Scrollbar on the Y axis + * + * @extends scrollbar + * @since 4.2.6 + * @product highstock + * @excluding height + * @apioption yAxis.scrollbar + */ + /** + * Enable the scrollbar on the Y axis. + * + * @sample {highstock} stock/yaxis/scrollbar/ + * Enabled on Y axis + * + * @type {boolean} + * @default false + * @since 4.2.6 + * @product highstock + * @apioption yAxis.scrollbar.enabled + */ + /** + * Pixel margin between the scrollbar and the axis elements. + * + * @type {number} + * @default 10 + * @since 4.2.6 + * @product highstock + * @apioption yAxis.scrollbar.margin + */ + /** + * Whether to show the scrollbar when it is fully zoomed out at max + * range. Setting it to `false` on the Y axis makes the scrollbar stay + * hidden until the user zooms in, like common in browsers. + * + * @type {boolean} + * @default true + * @since 4.2.6 + * @product highstock + * @apioption yAxis.scrollbar.showFull + */ + /** + * The width of a vertical scrollbar or height of a horizontal + * scrollbar. Defaults to 20 on touch devices. + * + * @type {number} + * @default 14 + * @since 4.2.6 + * @product highstock + * @apioption yAxis.scrollbar.size + */ + /** + * Z index of the scrollbar elements. + * + * @type {number} + * @default 3 + * @since 4.2.6 + * @product highstock + * @apioption yAxis.scrollbar.zIndex + */ + /** + * A soft maximum for the axis. If the series data maximum is less + * than this, the axis will stay at this maximum, but if the series + * data maximum is higher, the axis will flex to show all data. + * + * **Note**: The [series.softThreshold]( + * #plotOptions.series.softThreshold) option takes precedence over this + * option. + * + * @sample highcharts/yaxis/softmin-softmax/ + * Soft min and max + * + * @type {number} + * @since 5.0.1 + * @product highcharts highstock gantt + * @apioption yAxis.softMax + */ + /** + * A soft minimum for the axis. If the series data minimum is greater + * than this, the axis will stay at this minimum, but if the series + * data minimum is lower, the axis will flex to show all data. + * + * **Note**: The [series.softThreshold]( + * #plotOptions.series.softThreshold) option takes precedence over this + * option. + * + * @sample highcharts/yaxis/softmin-softmax/ + * Soft min and max + * + * @type {number} + * @since 5.0.1 + * @product highcharts highstock gantt + * @apioption yAxis.softMin + */ + /** + * Defines the horizontal alignment of the stack total label. Can be one + * of `"left"`, `"center"` or `"right"`. The default value is calculated + * at runtime and depends on orientation and whether the stack is + * positive or negative. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-align-left/ + * Aligned to the left + * @sample {highcharts} highcharts/yaxis/stacklabels-align-center/ + * Aligned in center + * @sample {highcharts} highcharts/yaxis/stacklabels-align-right/ + * Aligned to the right + * + * @type {Highcharts.AlignValue} + * @since 2.1.5 + * @product highcharts + * @apioption yAxis.stackLabels.align + */ + /** + * A format string for the data label. Available variables are the same + * as for `formatter`. + * + * @type {string} + * @default {total} + * @since 3.0.2 + * @product highcharts highstock + * @apioption yAxis.stackLabels.format + */ + /** + * Rotation of the labels in degrees. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-rotation/ + * Labels rotated 45° + * + * @type {number} + * @default 0 + * @since 2.1.5 + * @product highcharts + * @apioption yAxis.stackLabels.rotation + */ + /** + * The text alignment for the label. While `align` determines where the + * texts anchor point is placed with regards to the stack, `textAlign` + * determines how the text is aligned against its anchor point. Possible + * values are `"left"`, `"center"` and `"right"`. The default value is + * calculated at runtime and depends on orientation and whether the + * stack is positive or negative. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-textalign-left/ + * Label in center position but text-aligned left + * + * @type {Highcharts.AlignValue} + * @since 2.1.5 + * @product highcharts + * @apioption yAxis.stackLabels.textAlign + */ + /** + * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the labels. + * + * @type {boolean} + * @default false + * @since 3.0 + * @product highcharts highstock + * @apioption yAxis.stackLabels.useHTML + */ + /** + * Defines the vertical alignment of the stack total label. Can be one + * of `"top"`, `"middle"` or `"bottom"`. The default value is calculated + * at runtime and depends on orientation and whether the stack is + * positive or negative. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-verticalalign-top/ + * Vertically aligned top + * @sample {highcharts} highcharts/yaxis/stacklabels-verticalalign-middle/ + * Vertically aligned middle + * @sample {highcharts} highcharts/yaxis/stacklabels-verticalalign-bottom/ + * Vertically aligned bottom + * + * @type {Highcharts.VerticalAlignValue} + * @since 2.1.5 + * @product highcharts + * @apioption yAxis.stackLabels.verticalAlign + */ + /** + * The x position offset of the label relative to the left of the + * stacked bar. The default value is calculated at runtime and depends + * on orientation and whether the stack is positive or negative. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-x/ + * Stack total labels with x offset + * + * @type {number} + * @since 2.1.5 + * @product highcharts + * @apioption yAxis.stackLabels.x + */ + /** + * The y position offset of the label relative to the tick position + * on the axis. The default value is calculated at runtime and depends + * on orientation and whether the stack is positive or negative. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-y/ + * Stack total labels with y offset + * + * @type {number} + * @since 2.1.5 + * @product highcharts + * @apioption yAxis.stackLabels.y + */ + /** + * Whether to force the axis to start on a tick. Use this option with + * the `maxPadding` option to control the axis start. + * + * This option is always disabled, when panning type is + * either `y` or `xy`. + * + * @see [type](#chart.panning.type) + * + * @sample {highcharts} highcharts/xaxis/startontick-false/ + * False by default + * @sample {highcharts} highcharts/xaxis/startontick-true/ + * True + * @sample {highstock} stock/xaxis/endontick/ + * False for Y axis + * + * @since 1.2.0 + * @product highcharts highstock gantt + */ + startOnTick: true, + title: { + /** + * The pixel distance between the axis labels and the title. + * Positive values are outside the axis line, negative are inside. + * + * @sample {highcharts} highcharts/xaxis/title-margin/ + * Y axis title margin of 60 + * + * @type {number} + * @default 40 + * @apioption yAxis.title.margin + */ + /** + * The rotation of the text in degrees. 0 is horizontal, 270 is + * vertical reading from bottom to top. + * + * @sample {highcharts} highcharts/yaxis/title-offset/ + * Horizontal + */ + rotation: 270, + /** + * The actual text of the axis title. Horizontal texts can contain + * HTML, but rotated texts are painted using vector techniques and + * must be clean text. The Y axis title is disabled by setting the + * `text` option to `undefined`. + * + * @sample {highcharts} highcharts/xaxis/title-text/ + * Custom HTML + * + * @type {string|null} + * @default {highcharts} Values + * @default {highstock} undefined + * @product highcharts highstock gantt + */ + text: 'Values' + }, + /** + * The top position of the Y axis. If it's a number, it is interpreted + * as pixel position relative to the chart. + * + * Since Highcharts 2: If it's a percentage string, it is interpreted as + * percentages of the plot height, offset from plot area top. + * + * @see [yAxis.height](#yAxis.height) + * + * @sample {highstock} stock/demo/candlestick-and-volume/ + * Percentage height panes + * + * @type {number|string} + * @product highcharts highstock + * @apioption yAxis.top + */ + /** + * The stack labels show the total value for each bar in a stacked + * column or bar chart. The label will be placed on top of positive + * columns and below negative columns. In case of an inverted column + * chart or a bar chart the label is placed to the right of positive + * bars and to the left of negative bars. + * + * @product highcharts + */ + stackLabels: { + /** + * Allow the stack labels to overlap. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-allowoverlap-false/ + * Default false + * + * @since 5.0.13 + * @product highcharts + */ + allowOverlap: false, + /** + * The background color or gradient for the stack label. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-box/ + * Stack labels box options + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 8.1.0 + * @apioption yAxis.stackLabels.backgroundColor + */ + /** + * The border color for the stack label. Defaults to `undefined`. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-box/ + * Stack labels box options + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 8.1.0 + * @apioption yAxis.stackLabels.borderColor + */ + /** + * The border radius in pixels for the stack label. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-box/ + * Stack labels box options + * @type {number} + * @default 0 + * @since 8.1.0 + * @apioption yAxis.stackLabels.borderRadius + */ + /** + * The border width in pixels for the stack label. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-box/ + * Stack labels box options + * @type {number} + * @default 0 + * @since 8.1.0 + * @apioption yAxis.stackLabels.borderWidth + */ + /** + * Enable or disable the stack total labels. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-enabled/ + * Enabled stack total labels + * @sample {highcharts} highcharts/yaxis/stacklabels-enabled-waterfall/ + * Enabled stack labels in waterfall chart + * + * @since 2.1.5 + * @product highcharts + */ + enabled: false, + /** + * Whether to hide stack labels that are outside the plot area. + * By default, the stack label is moved + * inside the plot area according to the + * [overflow](/highcharts/#yAxis/stackLabels/overflow) + * option. + * + * @type {boolean} + * @since 7.1.3 + */ + crop: true, + /** + * How to handle stack total labels that flow outside the plot area. + * The default is set to `"justify"`, + * which aligns them inside the plot area. + * For columns and bars, this means it will be moved inside the bar. + * To display stack labels outside the plot area, + * set `crop` to `false` and `overflow` to `"allow"`. + * + * @sample highcharts/yaxis/stacklabels-overflow/ + * Stack labels flows outside the plot area. + * + * @type {Highcharts.DataLabelsOverflowValue} + * @since 7.1.3 + */ + overflow: 'justify', + /* eslint-disable valid-jsdoc */ + /** + * Callback JavaScript function to format the label. The value is + * given by `this.total`. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-formatter/ + * Added units to stack total value + * + * @type {Highcharts.FormatterCallbackFunction} + * @since 2.1.5 + * @product highcharts + */ + formatter: function () { + var numberFormatter = this.axis.chart.numberFormatter; + /* eslint-enable valid-jsdoc */ + return numberFormatter(this.total, -1); + }, + /** + * CSS styles for the label. + * + * In styled mode, the styles are set in the + * `.highcharts-stack-label` class. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-style/ + * Red stack total labels + * + * @type {Highcharts.CSSObject} + * @since 2.1.5 + * @product highcharts + */ + style: { + /** @internal */ + color: '#000000', + /** @internal */ + fontSize: '11px', + /** @internal */ + fontWeight: 'bold', + /** @internal */ + textOutline: '1px contrast' + } + }, + gridLineWidth: 1, + lineWidth: 0 + // tickWidth: 0 + }; + /** + * The Z axis or depth axis for 3D plots. + * + * See the [Axis class](/class-reference/Highcharts.Axis) for programmatic + * access to the axis. + * + * @sample {highcharts} highcharts/3d/scatter-zaxis-categories/ + * Z-Axis with Categories + * @sample {highcharts} highcharts/3d/scatter-zaxis-grid/ + * Z-Axis with styling + * + * @type {*|Array<*>} + * @extends xAxis + * @since 5.0.0 + * @product highcharts + * @excluding breaks, crosshair, height, left, lineColor, lineWidth, + * nameToX, showEmpty, top, width + * @apioption zAxis + * + * @private + */ + // This variable extends the defaultOptions for left axes. + Axis.defaultLeftAxisOptions = { + labels: { + x: -15 + }, + title: { + rotation: 270 + } + }; + // This variable extends the defaultOptions for right axes. + Axis.defaultRightAxisOptions = { + labels: { + x: 15 + }, + title: { + rotation: 90 + } + }; + // This variable extends the defaultOptions for bottom axes. + Axis.defaultBottomAxisOptions = { + labels: { + autoRotation: [-45], + x: 0 + // overflow: undefined, + // staggerLines: null + }, + margin: 15, + title: { + rotation: 0 + } + }; + // This variable extends the defaultOptions for top axes. + Axis.defaultTopAxisOptions = { + labels: { + autoRotation: [-45], + x: 0 + // overflow: undefined + // staggerLines: null + }, + margin: 15, + title: { + rotation: 0 + } + }; + // Properties to survive after destroy, needed for Axis.update (#4317, + // #5773, #5881). + Axis.keepProps = ['extKey', 'hcEvents', 'names', 'series', 'userMax', 'userMin']; + return Axis; + }()); + H.Axis = Axis; + + return H.Axis; + }); + _registerModule(_modules, 'parts/DateTimeAxis.js', [_modules['parts/Axis.js'], _modules['parts/Utilities.js']], function (Axis, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, getMagnitude = U.getMagnitude, normalizeTickInterval = U.normalizeTickInterval, timeUnits = U.timeUnits; + /* eslint-disable valid-jsdoc */ + var DateTimeAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function DateTimeAxisAdditions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Get a normalized tick interval for dates. Returns a configuration object + * with unit range (interval), count and name. Used to prepare data for + * `getTimeTicks`. Previously this logic was part of getTimeTicks, but as + * `getTimeTicks` now runs of segments in stock charts, the normalizing + * logic was extracted in order to prevent it for running over again for + * each segment having the same interval. #662, #697. + * @private + */ + /** + * Get a normalized tick interval for dates. Returns a configuration object + * with unit range (interval), count and name. Used to prepare data for + * `getTimeTicks`. Previously this logic was part of getTimeTicks, but as + * `getTimeTicks` now runs of segments in stock charts, the normalizing + * logic was extracted in order to prevent it for running over again for + * each segment having the same interval. #662, #697. + * @private + */ + DateTimeAxisAdditions.prototype.normalizeTimeTickInterval = function (tickInterval, unitsOption) { + var units = unitsOption || [[ + 'millisecond', + [1, 2, 5, 10, 20, 25, 50, 100, 200, 500] // allowed multiples + ], [ + 'second', + [1, 2, 5, 10, 15, 30] + ], [ + 'minute', + [1, 2, 5, 10, 15, 30] + ], [ + 'hour', + [1, 2, 3, 4, 6, 8, 12] + ], [ + 'day', + [1, 2] + ], [ + 'week', + [1, 2] + ], [ + 'month', + [1, 2, 3, 4, 6] + ], [ + 'year', + null + ]], unit = units[units.length - 1], // default unit is years + interval = timeUnits[unit[0]], multiples = unit[1], count, i; + // loop through the units to find the one that best fits the + // tickInterval + for (i = 0; i < units.length; i++) { + unit = units[i]; + interval = timeUnits[unit[0]]; + multiples = unit[1]; + if (units[i + 1]) { + // lessThan is in the middle between the highest multiple and + // the next unit. + var lessThan = (interval * + multiples[multiples.length - 1] + + timeUnits[units[i + 1][0]]) / 2; + // break and keep the current unit + if (tickInterval <= lessThan) { + break; + } + } + } + // prevent 2.5 years intervals, though 25, 250 etc. are allowed + if (interval === timeUnits.year && tickInterval < 5 * interval) { + multiples = [1, 2, 5]; + } + // get the count + count = normalizeTickInterval(tickInterval / interval, multiples, unit[0] === 'year' ? // #1913, #2360 + Math.max(getMagnitude(tickInterval / interval), 1) : + 1); + return { + unitRange: interval, + count: count, + unitName: unit[0] + }; + }; + return DateTimeAxisAdditions; + }()); + /** + * Date and time support for axes. + * + * @private + * @class + */ + var DateTimeAxis = /** @class */ (function () { + function DateTimeAxis() { + } + /* * + * + * Static Functions + * + * */ + /** + * Extends axis class with date and time support. + * @private + */ + DateTimeAxis.compose = function (AxisClass) { + AxisClass.keepProps.push('dateTime'); + var axisProto = AxisClass.prototype; + /** + * Set the tick positions to a time unit that makes sense, for example + * on the first of each month or on every Monday. Return an array with + * the time positions. Used in datetime axes as well as for grouping + * data on a datetime axis. + * + * @private + * @function Highcharts.Axis#getTimeTicks + * + * @param {Highcharts.TimeNormalizeObject} normalizedInterval + * The interval in axis values (ms) and thecount. + * + * @param {number} min + * The minimum in axis values. + * + * @param {number} max + * The maximum in axis values. + * + * @param {number} startOfWeek + * + * @return {Highcharts.AxisTickPositionsArray} + */ + axisProto.getTimeTicks = function () { + return this.chart.time.getTimeTicks.apply(this.chart.time, arguments); + }; + /* eslint-disable no-invalid-this */ + addEvent(AxisClass, 'init', function (e) { + var axis = this; + var options = e.userOptions; + if (options.type !== 'datetime') { + axis.dateTime = void 0; + return; + } + if (!axis.dateTime) { + axis.dateTime = new DateTimeAxisAdditions(axis); + } + }); + /* eslint-enable no-invalid-this */ + }; + /* * + * + * Static Properties + * + * */ + DateTimeAxis.AdditionsClass = DateTimeAxisAdditions; + return DateTimeAxis; + }()); + DateTimeAxis.compose(Axis); + + return DateTimeAxis; + }); + _registerModule(_modules, 'parts/LogarithmicAxis.js', [_modules['parts/Axis.js'], _modules['parts/Utilities.js']], function (Axis, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, getMagnitude = U.getMagnitude, normalizeTickInterval = U.normalizeTickInterval, pick = U.pick; + /* eslint-disable valid-jsdoc */ + /** + * Provides logarithmic support for axes. + * + * @private + * @class + */ + var LogarithmicAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function LogarithmicAxisAdditions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Set the tick positions of a logarithmic axis. + */ + LogarithmicAxisAdditions.prototype.getLogTickPositions = function (interval, min, max, minor) { + var log = this; + var axis = log.axis; + var axisLength = axis.len; + var options = axis.options; + // Since we use this method for both major and minor ticks, + // use a local variable and return the result + var positions = []; + // Reset + if (!minor) { + log.minorAutoInterval = void 0; + } + // First case: All ticks fall on whole logarithms: 1, 10, 100 etc. + if (interval >= 0.5) { + interval = Math.round(interval); + positions = axis.getLinearTickPositions(interval, min, max); + // Second case: We need intermediary ticks. For example + // 1, 2, 4, 6, 8, 10, 20, 40 etc. + } + else if (interval >= 0.08) { + var roundedMin = Math.floor(min), intermediate, i, j, len, pos, lastPos, break2; + if (interval > 0.3) { + intermediate = [1, 2, 4]; + // 0.2 equals five minor ticks per 1, 10, 100 etc + } + else if (interval > 0.15) { + intermediate = [1, 2, 4, 6, 8]; + } + else { // 0.1 equals ten minor ticks per 1, 10, 100 etc + intermediate = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + } + for (i = roundedMin; i < max + 1 && !break2; i++) { + len = intermediate.length; + for (j = 0; j < len && !break2; j++) { + pos = log.log2lin(log.lin2log(i) * intermediate[j]); + // #1670, lastPos is #3113 + if (pos > min && + (!minor || lastPos <= max) && + typeof lastPos !== 'undefined') { + positions.push(lastPos); + } + if (lastPos > max) { + break2 = true; + } + lastPos = pos; + } + } + // Third case: We are so deep in between whole logarithmic values that + // we might as well handle the tick positions like a linear axis. For + // example 1.01, 1.02, 1.03, 1.04. + } + else { + var realMin = log.lin2log(min), realMax = log.lin2log(max), tickIntervalOption = minor ? + axis.getMinorTickInterval() : + options.tickInterval, filteredTickIntervalOption = tickIntervalOption === 'auto' ? + null : + tickIntervalOption, tickPixelIntervalOption = options.tickPixelInterval / (minor ? 5 : 1), totalPixelLength = minor ? + axisLength / axis.tickPositions.length : + axisLength; + interval = pick(filteredTickIntervalOption, log.minorAutoInterval, (realMax - realMin) * + tickPixelIntervalOption / (totalPixelLength || 1)); + interval = normalizeTickInterval(interval, void 0, getMagnitude(interval)); + positions = axis.getLinearTickPositions(interval, realMin, realMax).map(log.log2lin); + if (!minor) { + log.minorAutoInterval = interval / 5; + } + } + // Set the axis-level tickInterval variable + if (!minor) { + axis.tickInterval = interval; + } + return positions; + }; + LogarithmicAxisAdditions.prototype.lin2log = function (num) { + return Math.pow(10, num); + }; + LogarithmicAxisAdditions.prototype.log2lin = function (num) { + return Math.log(num) / Math.LN10; + }; + return LogarithmicAxisAdditions; + }()); + var LogarithmicAxis = /** @class */ (function () { + function LogarithmicAxis() { + } + /** + * Provides logarithmic support for axes. + * + * @private + */ + LogarithmicAxis.compose = function (AxisClass) { + AxisClass.keepProps.push('logarithmic'); + // HC <= 8 backwards compatibility, allow wrapping + // Axis.prototype.lin2log and log2lin + // @todo Remove this in next major + var axisProto = AxisClass.prototype; + var logAxisProto = LogarithmicAxisAdditions.prototype; + axisProto.log2lin = logAxisProto.log2lin; + axisProto.lin2log = logAxisProto.lin2log; + /* eslint-disable no-invalid-this */ + addEvent(AxisClass, 'init', function (e) { + var axis = this; + var options = e.userOptions; + var logarithmic = axis.logarithmic; + if (options.type !== 'logarithmic') { + axis.logarithmic = void 0; + } + else { + if (!logarithmic) { + logarithmic = axis.logarithmic = new LogarithmicAxisAdditions(axis); + } + // HC <= 8 backwards compatibility, allow wrapping + // Axis.prototype.lin2log and log2lin + // @todo Remove this in next major + if (axis.log2lin !== logarithmic.log2lin) { + logarithmic.log2lin = axis.log2lin.bind(axis); + } + if (axis.lin2log !== logarithmic.lin2log) { + logarithmic.lin2log = axis.lin2log.bind(axis); + } + } + }); + addEvent(AxisClass, 'afterInit', function () { + var axis = this; + var log = axis.logarithmic; + // extend logarithmic axis + if (log) { + axis.lin2val = function (num) { + return log.lin2log(num); + }; + axis.val2lin = function (num) { + return log.log2lin(num); + }; + } + }); + }; + return LogarithmicAxis; + }()); + LogarithmicAxis.compose(Axis); // @todo move to factory functions + + return LogarithmicAxis; + }); + _registerModule(_modules, 'parts/PlotLineOrBand.js', [_modules['parts/Globals.js'], _modules['parts/Axis.js'], _modules['parts/Utilities.js']], function (H, Axis, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Options for plot bands on axes. + * + * @typedef {Highcharts.XAxisPlotBandsOptions|Highcharts.YAxisPlotBandsOptions|Highcharts.ZAxisPlotBandsOptions} Highcharts.AxisPlotBandsOptions + */ + /** + * Options for plot band labels on axes. + * + * @typedef {Highcharts.XAxisPlotBandsLabelOptions|Highcharts.YAxisPlotBandsLabelOptions|Highcharts.ZAxisPlotBandsLabelOptions} Highcharts.AxisPlotBandsLabelOptions + */ + /** + * Options for plot lines on axes. + * + * @typedef {Highcharts.XAxisPlotLinesOptions|Highcharts.YAxisPlotLinesOptions|Highcharts.ZAxisPlotLinesOptions} Highcharts.AxisPlotLinesOptions + */ + /** + * Options for plot line labels on axes. + * + * @typedef {Highcharts.XAxisPlotLinesLabelOptions|Highcharts.YAxisPlotLinesLabelOptions|Highcharts.ZAxisPlotLinesLabelOptions} Highcharts.AxisPlotLinesLabelOptions + */ + var arrayMax = U.arrayMax, arrayMin = U.arrayMin, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, erase = U.erase, extend = U.extend, fireEvent = U.fireEvent, merge = U.merge, objectEach = U.objectEach, pick = U.pick; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The object wrapper for plot lines and plot bands + * + * @class + * @name Highcharts.PlotLineOrBand + * + * @param {Highcharts.Axis} axis + * + * @param {Highcharts.AxisPlotLinesOptions|Highcharts.AxisPlotBandsOptions} [options] + */ + var PlotLineOrBand = /** @class */ (function () { + function PlotLineOrBand(axis, options) { + this.axis = axis; + if (options) { + this.options = options; + this.id = options.id; + } + } + /** + * Render the plot line or plot band. If it is already existing, + * move it. + * + * @private + * @function Highcharts.PlotLineOrBand#render + * @return {Highcharts.PlotLineOrBand|undefined} + */ + PlotLineOrBand.prototype.render = function () { + H.fireEvent(this, 'render'); + var plotLine = this, axis = plotLine.axis, horiz = axis.horiz, log = axis.logarithmic, options = plotLine.options, optionsLabel = options.label, label = plotLine.label, to = options.to, from = options.from, value = options.value, isBand = defined(from) && defined(to), isLine = defined(value), svgElem = plotLine.svgElem, isNew = !svgElem, path = [], color = options.color, zIndex = pick(options.zIndex, 0), events = options.events, attribs = { + 'class': 'highcharts-plot-' + (isBand ? 'band ' : 'line ') + + (options.className || '') + }, groupAttribs = {}, renderer = axis.chart.renderer, groupName = isBand ? 'bands' : 'lines', group; + // logarithmic conversion + if (log) { + from = log.log2lin(from); + to = log.log2lin(to); + value = log.log2lin(value); + } + // Set the presentational attributes + if (!axis.chart.styledMode) { + if (isLine) { + attribs.stroke = color || '#999999'; + attribs['stroke-width'] = pick(options.width, 1); + if (options.dashStyle) { + attribs.dashstyle = + options.dashStyle; + } + } + else if (isBand) { // plot band + attribs.fill = color || '#e6ebf5'; + if (options.borderWidth) { + attribs.stroke = options.borderColor; + attribs['stroke-width'] = options.borderWidth; + } + } + } + // Grouping and zIndex + groupAttribs.zIndex = zIndex; + groupName += '-' + zIndex; + group = axis.plotLinesAndBandsGroups[groupName]; + if (!group) { + axis.plotLinesAndBandsGroups[groupName] = group = + renderer.g('plot-' + groupName) + .attr(groupAttribs).add(); + } + // Create the path + if (isNew) { + /** + * SVG element of the plot line or band. + * + * @name Highcharts.PlotLineOrBand#svgElement + * @type {Highcharts.SVGElement} + */ + plotLine.svgElem = svgElem = renderer + .path() + .attr(attribs) + .add(group); + } + // Set the path or return + if (isLine) { + path = axis.getPlotLinePath({ + value: value, + lineWidth: svgElem.strokeWidth(), + acrossPanes: options.acrossPanes + }); + } + else if (isBand) { // plot band + path = axis.getPlotBandPath(from, to, options); + } + else { + return; + } + // common for lines and bands + if ((isNew || !svgElem.d) && path && path.length) { + svgElem.attr({ d: path }); + // events + if (events) { + objectEach(events, function (event, eventType) { + svgElem.on(eventType, function (e) { + events[eventType].apply(plotLine, [e]); + }); + }); + } + } + else if (svgElem) { + if (path) { + svgElem.show(true); + svgElem.animate({ d: path }); + } + else if (svgElem.d) { + svgElem.hide(); + if (label) { + plotLine.label = label = label.destroy(); + } + } + } + // the plot band/line label + if (optionsLabel && + (defined(optionsLabel.text) || defined(optionsLabel.formatter)) && + path && + path.length && + axis.width > 0 && + axis.height > 0 && + !path.isFlat) { + // apply defaults + optionsLabel = merge({ + align: horiz && isBand && 'center', + x: horiz ? !isBand && 4 : 10, + verticalAlign: !horiz && isBand && 'middle', + y: horiz ? isBand ? 16 : 10 : isBand ? 6 : -4, + rotation: horiz && !isBand && 90 + }, optionsLabel); + this.renderLabel(optionsLabel, path, isBand, zIndex); + } + else if (label) { // move out of sight + label.hide(); + } + // chainable + return plotLine; + }; + /** + * Render and align label for plot line or band. + * + * @private + * @function Highcharts.PlotLineOrBand#renderLabel + * @param {Highcharts.AxisPlotLinesLabelOptions|Highcharts.AxisPlotBandsLabelOptions} optionsLabel + * @param {Highcharts.SVGPathArray} path + * @param {boolean} [isBand] + * @param {number} [zIndex] + * @return {void} + */ + PlotLineOrBand.prototype.renderLabel = function (optionsLabel, path, isBand, zIndex) { + var plotLine = this, label = plotLine.label, renderer = plotLine.axis.chart.renderer, attribs, xBounds, yBounds, x, y, labelText; + // add the SVG element + if (!label) { + attribs = { + align: optionsLabel.textAlign || optionsLabel.align, + rotation: optionsLabel.rotation, + 'class': 'highcharts-plot-' + (isBand ? 'band' : 'line') + + '-label ' + (optionsLabel.className || '') + }; + attribs.zIndex = zIndex; + labelText = this.getLabelText(optionsLabel); + /** + * SVG element of the label. + * + * @name Highcharts.PlotLineOrBand#label + * @type {Highcharts.SVGElement} + */ + plotLine.label = label = renderer + .text(labelText, 0, 0, optionsLabel.useHTML) + .attr(attribs) + .add(); + if (!this.axis.chart.styledMode) { + label.css(optionsLabel.style); + } + } + // get the bounding box and align the label + // #3000 changed to better handle choice between plotband or plotline + xBounds = path.xBounds || + [path[0][1], path[1][1], (isBand ? path[2][1] : path[0][1])]; + yBounds = path.yBounds || + [path[0][2], path[1][2], (isBand ? path[2][2] : path[0][2])]; + x = arrayMin(xBounds); + y = arrayMin(yBounds); + label.align(optionsLabel, false, { + x: x, + y: y, + width: arrayMax(xBounds) - x, + height: arrayMax(yBounds) - y + }); + label.show(true); + }; + /** + * Get label's text content. + * + * @private + * @function Highcharts.PlotLineOrBand#getLabelText + * @param {Highcharts.AxisPlotLinesLabelOptions|Highcharts.AxisPlotBandsLabelOptions} optionsLabel + * @return {string} + */ + PlotLineOrBand.prototype.getLabelText = function (optionsLabel) { + return defined(optionsLabel.formatter) ? + optionsLabel.formatter + .call(this) : + optionsLabel.text; + }; + /** + * Remove the plot line or band. + * + * @function Highcharts.PlotLineOrBand#destroy + * @return {void} + */ + PlotLineOrBand.prototype.destroy = function () { + // remove it from the lookup + erase(this.axis.plotLinesAndBands, this); + delete this.axis; + destroyObjectProperties(this); + }; + return PlotLineOrBand; + }()); + /* eslint-enable no-invalid-this, valid-jsdoc */ + // Object with members for extending the Axis prototype + extend(Axis.prototype, /** @lends Highcharts.Axis.prototype */ { + /** + * An array of colored bands stretching across the plot area marking an + * interval on the axis. + * + * In styled mode, the plot bands are styled by the `.highcharts-plot-band` + * class in addition to the `className` option. + * + * @productdesc {highcharts} + * In a gauge, a plot band on the Y axis (value axis) will stretch along the + * perimeter of the gauge. + * + * @type {Array<*>} + * @product highcharts highstock gantt + * @apioption xAxis.plotBands + */ + /** + * Flag to decide if plotBand should be rendered across all panes. + * + * @since 7.1.2 + * @product highstock + * @type {boolean} + * @default true + * @apioption xAxis.plotBands.acrossPanes + */ + /** + * Border color for the plot band. Also requires `borderWidth` to be set. + * + * @type {Highcharts.ColorString} + * @apioption xAxis.plotBands.borderColor + */ + /** + * Border width for the plot band. Also requires `borderColor` to be set. + * + * @type {number} + * @default 0 + * @apioption xAxis.plotBands.borderWidth + */ + /** + * A custom class name, in addition to the default `highcharts-plot-band`, + * to apply to each individual band. + * + * @type {string} + * @since 5.0.0 + * @apioption xAxis.plotBands.className + */ + /** + * The color of the plot band. + * + * @sample {highcharts} highcharts/xaxis/plotbands-color/ + * Color band + * @sample {highstock} stock/xaxis/plotbands/ + * Plot band on Y axis + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #e6ebf5 + * @apioption xAxis.plotBands.color + */ + /** + * An object defining mouse events for the plot band. Supported properties + * are `click`, `mouseover`, `mouseout`, `mousemove`. + * + * @sample {highcharts} highcharts/xaxis/plotbands-events/ + * Mouse events demonstrated + * + * @since 1.2 + * @apioption xAxis.plotBands.events + */ + /** + * Click event on a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotBands.events.click + */ + /** + * Mouse move event on a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotBands.events.mousemove + */ + /** + * Mouse out event on the corner of a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotBands.events.mouseout + */ + /** + * Mouse over event on a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotBands.events.mouseover + */ + /** + * The start position of the plot band in axis units. + * + * @sample {highcharts} highcharts/xaxis/plotbands-color/ + * Datetime axis + * @sample {highcharts} highcharts/xaxis/plotbands-from/ + * Categorized axis + * @sample {highstock} stock/xaxis/plotbands/ + * Plot band on Y axis + * + * @type {number} + * @apioption xAxis.plotBands.from + */ + /** + * An id used for identifying the plot band in Axis.removePlotBand. + * + * @sample {highcharts} highcharts/xaxis/plotbands-id/ + * Remove plot band by id + * @sample {highstock} highcharts/xaxis/plotbands-id/ + * Remove plot band by id + * + * @type {string} + * @apioption xAxis.plotBands.id + */ + /** + * The end position of the plot band in axis units. + * + * @sample {highcharts} highcharts/xaxis/plotbands-color/ + * Datetime axis + * @sample {highcharts} highcharts/xaxis/plotbands-from/ + * Categorized axis + * @sample {highstock} stock/xaxis/plotbands/ + * Plot band on Y axis + * + * @type {number} + * @apioption xAxis.plotBands.to + */ + /** + * The z index of the plot band within the chart, relative to other + * elements. Using the same z index as another element may give + * unpredictable results, as the last rendered element will be on top. + * Values from 0 to 20 make sense. + * + * @sample {highcharts} highcharts/xaxis/plotbands-color/ + * Behind plot lines by default + * @sample {highcharts} highcharts/xaxis/plotbands-zindex/ + * Above plot lines + * @sample {highcharts} highcharts/xaxis/plotbands-zindex-above-series/ + * Above plot lines and series + * + * @type {number} + * @since 1.2 + * @apioption xAxis.plotBands.zIndex + */ + /** + * Text labels for the plot bands + * + * @product highcharts highstock gantt + * @apioption xAxis.plotBands.label + */ + /** + * Horizontal alignment of the label. Can be one of "left", "center" or + * "right". + * + * @sample {highcharts} highcharts/xaxis/plotbands-label-align/ + * Aligned to the right + * @sample {highstock} stock/xaxis/plotbands-label/ + * Plot band with labels + * + * @type {Highcharts.AlignValue} + * @default center + * @since 2.1 + * @apioption xAxis.plotBands.label.align + */ + /** + * Rotation of the text label in degrees . + * + * @sample {highcharts} highcharts/xaxis/plotbands-label-rotation/ + * Vertical text + * + * @type {number} + * @default 0 + * @since 2.1 + * @apioption xAxis.plotBands.label.rotation + */ + /** + * CSS styles for the text label. + * + * In styled mode, the labels are styled by the + * `.highcharts-plot-band-label` class. + * + * @sample {highcharts} highcharts/xaxis/plotbands-label-style/ + * Blue and bold label + * + * @type {Highcharts.CSSObject} + * @since 2.1 + * @apioption xAxis.plotBands.label.style + */ + /** + * The string text itself. A subset of HTML is supported. + * + * @type {string} + * @since 2.1 + * @apioption xAxis.plotBands.label.text + */ + /** + * The text alignment for the label. While `align` determines where the + * texts anchor point is placed within the plot band, `textAlign` determines + * how the text is aligned against its anchor point. Possible values are + * "left", "center" and "right". Defaults to the same as the `align` option. + * + * @sample {highcharts} highcharts/xaxis/plotbands-label-rotation/ + * Vertical text in center position but text-aligned left + * + * @type {Highcharts.AlignValue} + * @since 2.1 + * @apioption xAxis.plotBands.label.textAlign + */ + /** + * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the labels. + * + * @type {boolean} + * @default false + * @since 3.0.3 + * @apioption xAxis.plotBands.label.useHTML + */ + /** + * Vertical alignment of the label relative to the plot band. Can be one of + * "top", "middle" or "bottom". + * + * @sample {highcharts} highcharts/xaxis/plotbands-label-verticalalign/ + * Vertically centered label + * @sample {highstock} stock/xaxis/plotbands-label/ + * Plot band with labels + * + * @type {Highcharts.VerticalAlignValue} + * @default top + * @since 2.1 + * @apioption xAxis.plotBands.label.verticalAlign + */ + /** + * Horizontal position relative the alignment. Default varies by + * orientation. + * + * @sample {highcharts} highcharts/xaxis/plotbands-label-align/ + * Aligned 10px from the right edge + * @sample {highstock} stock/xaxis/plotbands-label/ + * Plot band with labels + * + * @type {number} + * @since 2.1 + * @apioption xAxis.plotBands.label.x + */ + /** + * Vertical position of the text baseline relative to the alignment. Default + * varies by orientation. + * + * @sample {highcharts} highcharts/xaxis/plotbands-label-y/ + * Label on x axis + * @sample {highstock} stock/xaxis/plotbands-label/ + * Plot band with labels + * + * @type {number} + * @since 2.1 + * @apioption xAxis.plotBands.label.y + */ + /** + * An array of lines stretching across the plot area, marking a specific + * value on one of the axes. + * + * In styled mode, the plot lines are styled by the + * `.highcharts-plot-line` class in addition to the `className` option. + * + * @type {Array<*>} + * @product highcharts highstock gantt + * @sample {highcharts} highcharts/xaxis/plotlines-color/ + * Basic plot line + * @sample {highcharts} highcharts/series-solidgauge/labels-auto-aligned/ + * Solid gauge plot line + * @apioption xAxis.plotLines + */ + /** + * Flag to decide if plotLine should be rendered across all panes. + * + * @sample {highstock} stock/xaxis/plotlines-acrosspanes/ + * Plot lines on different panes + * + * @since 7.1.2 + * @product highstock + * @type {boolean} + * @default true + * @apioption xAxis.plotLines.acrossPanes + */ + /** + * A custom class name, in addition to the default `highcharts-plot-line`, + * to apply to each individual line. + * + * @type {string} + * @since 5.0.0 + * @apioption xAxis.plotLines.className + */ + /** + * The color of the line. + * + * @sample {highcharts} highcharts/xaxis/plotlines-color/ + * A red line from X axis + * @sample {highstock} stock/xaxis/plotlines/ + * Plot line on Y axis + * + * @type {Highcharts.ColorString} + * @default #999999 + * @apioption xAxis.plotLines.color + */ + /** + * The dashing or dot style for the plot line. For possible values see + * [this overview](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/). + * + * @sample {highcharts} highcharts/xaxis/plotlines-dashstyle/ + * Dash and dot pattern + * @sample {highstock} stock/xaxis/plotlines/ + * Plot line on Y axis + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 1.2 + * @apioption xAxis.plotLines.dashStyle + */ + /** + * An object defining mouse events for the plot line. Supported + * properties are `click`, `mouseover`, `mouseout`, `mousemove`. + * + * @sample {highcharts} highcharts/xaxis/plotlines-events/ + * Mouse events demonstrated + * + * @since 1.2 + * @apioption xAxis.plotLines.events + */ + /** + * Click event on a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotLines.events.click + */ + /** + * Mouse move event on a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotLines.events.mousemove + */ + /** + * Mouse out event on the corner of a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotLines.events.mouseout + */ + /** + * Mouse over event on a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotLines.events.mouseover + */ + /** + * An id used for identifying the plot line in Axis.removePlotLine. + * + * @sample {highcharts} highcharts/xaxis/plotlines-id/ + * Remove plot line by id + * + * @type {string} + * @apioption xAxis.plotLines.id + */ + /** + * The position of the line in axis units. + * + * @sample {highcharts} highcharts/xaxis/plotlines-color/ + * Between two categories on X axis + * @sample {highstock} stock/xaxis/plotlines/ + * Plot line on Y axis + * + * @type {number} + * @apioption xAxis.plotLines.value + */ + /** + * The width or thickness of the plot line. + * + * @sample {highcharts} highcharts/xaxis/plotlines-color/ + * 2px wide line from X axis + * @sample {highstock} stock/xaxis/plotlines/ + * Plot line on Y axis + * + * @type {number} + * @default 2 + * @apioption xAxis.plotLines.width + */ + /** + * The z index of the plot line within the chart. + * + * @sample {highcharts} highcharts/xaxis/plotlines-zindex-behind/ + * Behind plot lines by default + * @sample {highcharts} highcharts/xaxis/plotlines-zindex-above/ + * Above plot lines + * @sample {highcharts} highcharts/xaxis/plotlines-zindex-above-all/ + * Above plot lines and series + * + * @type {number} + * @since 1.2 + * @apioption xAxis.plotLines.zIndex + */ + /** + * Text labels for the plot bands + * + * @apioption xAxis.plotLines.label + */ + /** + * Horizontal alignment of the label. Can be one of "left", "center" or + * "right". + * + * @sample {highcharts} highcharts/xaxis/plotlines-label-align-right/ + * Aligned to the right + * @sample {highstock} stock/xaxis/plotlines/ + * Plot line on Y axis + * + * @type {Highcharts.AlignValue} + * @default left + * @since 2.1 + * @apioption xAxis.plotLines.label.align + */ + /** + * Callback JavaScript function to format the label. Useful properties like + * the value of plot line or the range of plot band (`from` & `to` + * properties) can be found in `this.options` object. + * + * @sample {highcharts} highcharts/xaxis/plotlines-plotbands-label-formatter + * Label formatters for plot line and plot band. + * @type {Highcharts.FormatterCallbackFunction} + * @apioption xAxis.plotLines.label.formatter + */ + /** + * Rotation of the text label in degrees. Defaults to 0 for horizontal plot + * lines and 90 for vertical lines. + * + * @sample {highcharts} highcharts/xaxis/plotlines-label-verticalalign-middle/ + * Slanted text + * + * @type {number} + * @since 2.1 + * @apioption xAxis.plotLines.label.rotation + */ + /** + * CSS styles for the text label. + * + * In styled mode, the labels are styled by the + * `.highcharts-plot-line-label` class. + * + * @sample {highcharts} highcharts/xaxis/plotlines-label-style/ + * Blue and bold label + * + * @type {Highcharts.CSSObject} + * @since 2.1 + * @apioption xAxis.plotLines.label.style + */ + /** + * The text itself. A subset of HTML is supported. + * + * @type {string} + * @since 2.1 + * @apioption xAxis.plotLines.label.text + */ + /** + * The text alignment for the label. While `align` determines where the + * texts anchor point is placed within the plot band, `textAlign` determines + * how the text is aligned against its anchor point. Possible values are + * "left", "center" and "right". Defaults to the same as the `align` option. + * + * @sample {highcharts} highcharts/xaxis/plotlines-label-textalign/ + * Text label in bottom position + * + * @type {Highcharts.AlignValue} + * @since 2.1 + * @apioption xAxis.plotLines.label.textAlign + */ + /** + * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the labels. + * + * @type {boolean} + * @default false + * @since 3.0.3 + * @apioption xAxis.plotLines.label.useHTML + */ + /** + * Vertical alignment of the label relative to the plot line. Can be + * one of "top", "middle" or "bottom". + * + * @sample {highcharts} highcharts/xaxis/plotlines-label-verticalalign-middle/ + * Vertically centered label + * + * @type {Highcharts.VerticalAlignValue} + * @default {highcharts} top + * @default {highstock} top + * @since 2.1 + * @apioption xAxis.plotLines.label.verticalAlign + */ + /** + * Horizontal position relative the alignment. Default varies by + * orientation. + * + * @sample {highcharts} highcharts/xaxis/plotlines-label-align-right/ + * Aligned 10px from the right edge + * @sample {highstock} stock/xaxis/plotlines/ + * Plot line on Y axis + * + * @type {number} + * @since 2.1 + * @apioption xAxis.plotLines.label.x + */ + /** + * Vertical position of the text baseline relative to the alignment. Default + * varies by orientation. + * + * @sample {highcharts} highcharts/xaxis/plotlines-label-y/ + * Label below the plot line + * @sample {highstock} stock/xaxis/plotlines/ + * Plot line on Y axis + * + * @type {number} + * @since 2.1 + * @apioption xAxis.plotLines.label.y + */ + /** + * + * @type {Array<*>} + * @extends xAxis.plotBands + * @apioption yAxis.plotBands + */ + /** + * In a gauge chart, this option determines the inner radius of the + * plot band that stretches along the perimeter. It can be given as + * a percentage string, like `"100%"`, or as a pixel number, like `100`. + * By default, the inner radius is controlled by the [thickness]( + * #yAxis.plotBands.thickness) option. + * + * @sample {highcharts} highcharts/xaxis/plotbands-gauge + * Gauge plot band + * + * @type {number|string} + * @since 2.3 + * @product highcharts + * @apioption yAxis.plotBands.innerRadius + */ + /** + * In a gauge chart, this option determines the outer radius of the + * plot band that stretches along the perimeter. It can be given as + * a percentage string, like `"100%"`, or as a pixel number, like `100`. + * + * @sample {highcharts} highcharts/xaxis/plotbands-gauge + * Gauge plot band + * + * @type {number|string} + * @default 100% + * @since 2.3 + * @product highcharts + * @apioption yAxis.plotBands.outerRadius + */ + /** + * In a gauge chart, this option sets the width of the plot band + * stretching along the perimeter. It can be given as a percentage + * string, like `"10%"`, or as a pixel number, like `10`. The default + * value 10 is the same as the default [tickLength](#yAxis.tickLength), + * thus making the plot band act as a background for the tick markers. + * + * @sample {highcharts} highcharts/xaxis/plotbands-gauge + * Gauge plot band + * + * @type {number|string} + * @default 10 + * @since 2.3 + * @product highcharts + * @apioption yAxis.plotBands.thickness + */ + /** + * @type {Array<*>} + * @extends xAxis.plotLines + * @apioption yAxis.plotLines + */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Internal function to create the SVG path definition for a plot band. + * + * @function Highcharts.Axis#getPlotBandPath + * + * @param {number} from + * The axis value to start from. + * + * @param {number} to + * The axis value to end on. + * + * @return {Highcharts.SVGPathArray} + * The SVG path definition in array form. + */ + getPlotBandPath: function (from, to) { + var toPath = this.getPlotLinePath({ + value: to, + force: true, + acrossPanes: this.options.acrossPanes + }), path = this.getPlotLinePath({ + value: from, + force: true, + acrossPanes: this.options.acrossPanes + }), result = [], i, + // #4964 check if chart is inverted or plotband is on yAxis + horiz = this.horiz, plus = 1, isFlat, outside = (from < this.min && to < this.min) || + (from > this.max && to > this.max); + if (path && toPath) { + // Flat paths don't need labels (#3836) + if (outside) { + isFlat = path.toString() === toPath.toString(); + plus = 0; + } + // Go over each subpath - for panes in Highstock + for (i = 0; i < path.length; i += 2) { + var pathStart = path[i], pathEnd = path[i + 1], toPathStart = toPath[i], toPathEnd = toPath[i + 1]; + // Type checking all affected path segments. Consider something + // smarter. + if ((pathStart[0] === 'M' || pathStart[0] === 'L') && + (pathEnd[0] === 'M' || pathEnd[0] === 'L') && + (toPathStart[0] === 'M' || toPathStart[0] === 'L') && + (toPathEnd[0] === 'M' || toPathEnd[0] === 'L')) { + // Add 1 pixel when coordinates are the same + if (horiz && toPathStart[1] === pathStart[1]) { + toPathStart[1] += plus; + toPathEnd[1] += plus; + } + else if (!horiz && toPathStart[2] === pathStart[2]) { + toPathStart[2] += plus; + toPathEnd[2] += plus; + } + result.push(['M', pathStart[1], pathStart[2]], ['L', pathEnd[1], pathEnd[2]], ['L', toPathEnd[1], toPathEnd[2]], ['L', toPathStart[1], toPathStart[2]], ['Z']); + } + result.isFlat = isFlat; + } + } + else { // outside the axis area + path = null; + } + return result; + }, + /** + * Add a plot band after render time. + * + * @sample highcharts/members/axis-addplotband/ + * Toggle the plot band from a button + * + * @function Highcharts.Axis#addPlotBand + * + * @param {Highcharts.AxisPlotBandsOptions} options + * A configuration object for the plot band, as defined in + * [xAxis.plotBands](https://api.highcharts.com/highcharts/xAxis.plotBands). + * + * @return {Highcharts.PlotLineOrBand|undefined} + * The added plot band. + */ + addPlotBand: function (options) { + return this.addPlotBandOrLine(options, 'plotBands'); + }, + /** + * Add a plot line after render time. + * + * @sample highcharts/members/axis-addplotline/ + * Toggle the plot line from a button + * + * @function Highcharts.Axis#addPlotLine + * + * @param {Highcharts.AxisPlotLinesOptions} options + * A configuration object for the plot line, as defined in + * [xAxis.plotLines](https://api.highcharts.com/highcharts/xAxis.plotLines). + * + * @return {Highcharts.PlotLineOrBand|undefined} + * The added plot line. + */ + addPlotLine: function (options) { + return this.addPlotBandOrLine(options, 'plotLines'); + }, + /** + * Add a plot band or plot line after render time. Called from addPlotBand + * and addPlotLine internally. + * + * @private + * @function Highcharts.Axis#addPlotBandOrLine + * + * @param {Highcharts.AxisPlotBandsOptions|Highcharts.AxisPlotLinesOptions} options + * The plotBand or plotLine configuration object. + * + * @param {"plotBands"|"plotLines"} [coll] + * + * @return {Highcharts.PlotLineOrBand|undefined} + */ + addPlotBandOrLine: function (options, coll) { + var obj = new PlotLineOrBand(this, options).render(), userOptions = this.userOptions; + if (obj) { // #2189 + // Add it to the user options for exporting and Axis.update + if (coll) { + // Workaround Microsoft/TypeScript issue #32693 + var updatedOptions = (userOptions[coll] || []); + updatedOptions.push(options); + userOptions[coll] = updatedOptions; + } + this.plotLinesAndBands.push(obj); + } + return obj; + }, + /** + * Remove a plot band or plot line from the chart by id. Called internally + * from `removePlotBand` and `removePlotLine`. + * + * @private + * @function Highcharts.Axis#removePlotBandOrLine + * @param {string} id + * @return {void} + */ + removePlotBandOrLine: function (id) { + var plotLinesAndBands = this.plotLinesAndBands, options = this.options, userOptions = this.userOptions, i = plotLinesAndBands.length; + while (i--) { + if (plotLinesAndBands[i].id === id) { + plotLinesAndBands[i].destroy(); + } + } + ([ + options.plotLines || [], + userOptions.plotLines || [], + options.plotBands || [], + userOptions.plotBands || [] + ]).forEach(function (arr) { + i = arr.length; + while (i--) { + if ((arr[i] || {}).id === id) { + erase(arr, arr[i]); + } + } + }); + }, + /** + * Remove a plot band by its id. + * + * @sample highcharts/members/axis-removeplotband/ + * Remove plot band by id + * @sample highcharts/members/axis-addplotband/ + * Toggle the plot band from a button + * + * @function Highcharts.Axis#removePlotBand + * + * @param {string} id + * The plot band's `id` as given in the original configuration + * object or in the `addPlotBand` option. + * + * @return {void} + */ + removePlotBand: function (id) { + this.removePlotBandOrLine(id); + }, + /** + * Remove a plot line by its id. + * + * @sample highcharts/xaxis/plotlines-id/ + * Remove plot line by id + * @sample highcharts/members/axis-addplotline/ + * Toggle the plot line from a button + * + * @function Highcharts.Axis#removePlotLine + * + * @param {string} id + * The plot line's `id` as given in the original configuration + * object or in the `addPlotLine` option. + */ + removePlotLine: function (id) { + this.removePlotBandOrLine(id); + } + }); + H.PlotLineOrBand = PlotLineOrBand; + + return H.PlotLineOrBand; + }); + _registerModule(_modules, 'parts/Tooltip.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var clamp = U.clamp, css = U.css, defined = U.defined, discardElement = U.discardElement, extend = U.extend, fireEvent = U.fireEvent, format = U.format, isNumber = U.isNumber, isString = U.isString, merge = U.merge, offset = U.offset, pick = U.pick, splat = U.splat, syncTimeout = U.syncTimeout, timeUnits = U.timeUnits; + /** + * Callback function to format the text of the tooltip from scratch. + * + * In case of single or shared tooltips, a string should be be returned. In case + * of splitted tooltips, it should return an array where the first item is the + * header, and subsequent items are mapped to the points. Return `false` to + * disable tooltip for a specific point on series. + * + * @callback Highcharts.TooltipFormatterCallbackFunction + * + * @param {Highcharts.TooltipFormatterContextObject} this + * Context to format + * + * @param {Highcharts.Tooltip} tooltip + * The tooltip instance + * + * @return {false|string|Array<(string|null|undefined)>|null|undefined} + * Formatted text or false + */ + /** + * @interface Highcharts.TooltipFormatterContextObject + */ /** + * @name Highcharts.TooltipFormatterContextObject#color + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ /** + * @name Highcharts.TooltipFormatterContextObject#colorIndex + * @type {number|undefined} + */ /** + * @name Highcharts.TooltipFormatterContextObject#key + * @type {number} + */ /** + * @name Highcharts.TooltipFormatterContextObject#percentage + * @type {number|undefined} + */ /** + * @name Highcharts.TooltipFormatterContextObject#point + * @type {Highcharts.Point} + */ /** + * @name Highcharts.TooltipFormatterContextObject#points + * @type {Array|undefined} + */ /** + * @name Highcharts.TooltipFormatterContextObject#series + * @type {Highcharts.Series} + */ /** + * @name Highcharts.TooltipFormatterContextObject#total + * @type {number|undefined} + */ /** + * @name Highcharts.TooltipFormatterContextObject#x + * @type {number} + */ /** + * @name Highcharts.TooltipFormatterContextObject#y + * @type {number} + */ + /** + * A callback function to place the tooltip in a specific position. + * + * @callback Highcharts.TooltipPositionerCallbackFunction + * + * @param {number} labelWidth + * Width of the tooltip. + * + * @param {number} labelHeight + * Height of the tooltip. + * + * @param {Highcharts.Point} point + * Point information for positioning a tooltip. + * + * @return {Highcharts.PositionObject} + * New position for the tooltip. + */ + /** + * Point information for positioning a tooltip. + * + * @interface Highcharts.TooltipPositionerPointObject + */ /** + * If `tooltip.split` option is enabled and positioner is called for each of the + * boxes separately, this property indicates the call on the xAxis header, which + * is not a point itself. + * @name Highcharts.TooltipPositionerPointObject#isHeader + * @type {boolean} + */ /** + * @name Highcharts.TooltipPositionerPointObject#negative + * @type {boolean} + */ /** + * The reference point relative to the plot area. Add chart.plotLeft to get the + * full coordinates. + * @name Highcharts.TooltipPositionerPointObject#plotX + * @type {number} + */ /** + * The reference point relative to the plot area. Add chart.plotTop to get the + * full coordinates. + * @name Highcharts.TooltipPositionerPointObject#plotY + * @type {number} + */ + /** + * @typedef {"callout"|"circle"|"square"} Highcharts.TooltipShapeValue + */ + ''; // separates doclets above from variables below + var doc = H.doc; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Tooltip of a chart. + * + * @class + * @name Highcharts.Tooltip + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @param {Highcharts.TooltipOptions} options + * Tooltip options. + */ + var Tooltip = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Tooltip(chart, options) { + this.crosshairs = []; + this.distance = 0; + this.isHidden = true; + this.isSticky = false; + this.now = {}; + this.options = {}; + this.outside = false; + this.chart = chart; + this.init(chart, options); + } + /* * + * + * Functions + * + * */ + /** + * In styled mode, apply the default filter for the tooltip drop-shadow. It + * needs to have an id specific to the chart, otherwise there will be issues + * when one tooltip adopts the filter of a different chart, specifically one + * where the container is hidden. + * + * @private + * @function Highcharts.Tooltip#applyFilter + */ + Tooltip.prototype.applyFilter = function () { + var chart = this.chart; + chart.renderer.definition({ + tagName: 'filter', + id: 'drop-shadow-' + chart.index, + opacity: 0.5, + children: [{ + tagName: 'feGaussianBlur', + 'in': 'SourceAlpha', + stdDeviation: 1 + }, { + tagName: 'feOffset', + dx: 1, + dy: 1 + }, { + tagName: 'feComponentTransfer', + children: [{ + tagName: 'feFuncA', + type: 'linear', + slope: 0.3 + }] + }, { + tagName: 'feMerge', + children: [{ + tagName: 'feMergeNode' + }, { + tagName: 'feMergeNode', + 'in': 'SourceGraphic' + }] + }] + }); + chart.renderer.definition({ + tagName: 'style', + textContent: '.highcharts-tooltip-' + chart.index + '{' + + 'filter:url(#drop-shadow-' + chart.index + ')' + + '}' + }); + }; + /** + * Build the body (lines) of the tooltip by iterating over the items and + * returning one entry for each item, abstracting this functionality allows + * to easily overwrite and extend it. + * + * @private + * @function Highcharts.Tooltip#bodyFormatter + * @param {Array<(Highcharts.Point|Highcharts.Series)>} items + * @return {Array} + */ + Tooltip.prototype.bodyFormatter = function (items) { + return items.map(function (item) { + var tooltipOptions = item.series.tooltipOptions; + return (tooltipOptions[(item.point.formatPrefix || 'point') + 'Formatter'] || + item.point.tooltipFormatter).call(item.point, tooltipOptions[(item.point.formatPrefix || 'point') + 'Format'] || ''); + }); + }; + /** + * Destroy the single tooltips in a split tooltip. + * If the tooltip is active then it is not destroyed, unless forced to. + * + * @private + * @function Highcharts.Tooltip#cleanSplit + * + * @param {boolean} [force] + * Force destroy all tooltips. + */ + Tooltip.prototype.cleanSplit = function (force) { + this.chart.series.forEach(function (series) { + var tt = series && series.tt; + if (tt) { + if (!tt.isActive || force) { + series.tt = tt.destroy(); + } + else { + tt.isActive = false; + } + } + }); + }; + /** + * In case no user defined formatter is given, this will be used. Note that + * the context here is an object holding point, series, x, y etc. + * + * @function Highcharts.Tooltip#defaultFormatter + * + * @param {Highcharts.Tooltip} tooltip + * + * @return {Array} + */ + Tooltip.prototype.defaultFormatter = function (tooltip) { + var items = this.points || splat(this), s; + // Build the header + s = [tooltip.tooltipFooterHeaderFormatter(items[0])]; + // build the values + s = s.concat(tooltip.bodyFormatter(items)); + // footer + s.push(tooltip.tooltipFooterHeaderFormatter(items[0], true)); + return s; + }; + /** + * Removes and destroys the tooltip and its elements. + * + * @function Highcharts.Tooltip#destroy + */ + Tooltip.prototype.destroy = function () { + // Destroy and clear local variables + if (this.label) { + this.label = this.label.destroy(); + } + if (this.split && this.tt) { + this.cleanSplit(this.chart, true); + this.tt = this.tt.destroy(); + } + if (this.renderer) { + this.renderer = this.renderer.destroy(); + discardElement(this.container); + } + U.clearTimeout(this.hideTimer); + U.clearTimeout(this.tooltipTimeout); + }; + /** + * Extendable method to get the anchor position of the tooltip + * from a point or set of points + * + * @private + * @function Highcharts.Tooltip#getAnchor + * + * @param {Highcharts.Point|Array} points + * + * @param {Highcharts.PointerEventObject} [mouseEvent] + * + * @return {Array} + */ + Tooltip.prototype.getAnchor = function (points, mouseEvent) { + var ret, chart = this.chart, pointer = chart.pointer, inverted = chart.inverted, plotTop = chart.plotTop, plotLeft = chart.plotLeft, plotX = 0, plotY = 0, yAxis, xAxis; + points = splat(points); + // When tooltip follows mouse, relate the position to the mouse + if (this.followPointer && mouseEvent) { + if (typeof mouseEvent.chartX === 'undefined') { + mouseEvent = pointer.normalize(mouseEvent); + } + ret = [ + mouseEvent.chartX - plotLeft, + mouseEvent.chartY - plotTop + ]; + // Some series types use a specificly calculated tooltip position for + // each point + } + else if (points[0].tooltipPos) { + ret = points[0].tooltipPos; + // When shared, use the average position + } + else { + points.forEach(function (point) { + yAxis = point.series.yAxis; + xAxis = point.series.xAxis; + plotX += point.plotX + + (!inverted && xAxis ? xAxis.left - plotLeft : 0); + plotY += (point.plotLow ? + (point.plotLow + point.plotHigh) / 2 : + point.plotY) + (!inverted && yAxis ? yAxis.top - plotTop : 0); // #1151 + }); + plotX /= points.length; + plotY /= points.length; + ret = [ + inverted ? chart.plotWidth - plotY : plotX, + this.shared && !inverted && points.length > 1 && mouseEvent ? + // place shared tooltip next to the mouse (#424) + mouseEvent.chartY - plotTop : + inverted ? chart.plotHeight - plotX : plotY + ]; + } + return ret.map(Math.round); + }; + /** + * Get the optimal date format for a point, based on a range. + * + * @private + * @function Highcharts.Tooltip#getDateFormat + * + * @param {number} range + * The time range + * + * @param {number} date + * The date of the point in question + * + * @param {number} startOfWeek + * An integer representing the first day of the week, where 0 is + * Sunday. + * + * @param {Highcharts.Dictionary} dateTimeLabelFormats + * A map of time units to formats. + * + * @return {string} + * The optimal date format for a point. + */ + Tooltip.prototype.getDateFormat = function (range, date, startOfWeek, dateTimeLabelFormats) { + var time = this.chart.time, dateStr = time.dateFormat('%m-%d %H:%M:%S.%L', date), format, n, blank = '01-01 00:00:00.000', strpos = { + millisecond: 15, + second: 12, + minute: 9, + hour: 6, + day: 3 + }, lastN = 'millisecond'; // for sub-millisecond data, #4223 + for (n in timeUnits) { // eslint-disable-line guard-for-in + // If the range is exactly one week and we're looking at a + // Sunday/Monday, go for the week format + if (range === timeUnits.week && + +time.dateFormat('%w', date) === startOfWeek && + dateStr.substr(6) === blank.substr(6)) { + n = 'week'; + break; + } + // The first format that is too great for the range + if (timeUnits[n] > range) { + n = lastN; + break; + } + // If the point is placed every day at 23:59, we need to show + // the minutes as well. #2637. + if (strpos[n] && + dateStr.substr(strpos[n]) !== blank.substr(strpos[n])) { + break; + } + // Weeks are outside the hierarchy, only apply them on + // Mondays/Sundays like in the first condition + if (n !== 'week') { + lastN = n; + } + } + if (n) { + format = time.resolveDTLFormat(dateTimeLabelFormats[n]).main; + } + return format; + }; + /** + * Creates the Tooltip label element if it does not exist, then returns it. + * + * @function Highcharts.Tooltip#getLabel + * @return {Highcharts.SVGElement} + */ + Tooltip.prototype.getLabel = function () { + var _a, _b; + var tooltip = this, renderer = this.chart.renderer, styledMode = this.chart.styledMode, options = this.options, className = ('tooltip' + (defined(options.className) ? + ' ' + options.className : + '')), pointerEvents = (((_a = options.style) === null || _a === void 0 ? void 0 : _a.pointerEvents) || + (!this.followPointer && options.stickOnContact ? 'auto' : 'none')), container, set, onMouseEnter = function () { + tooltip.inContact = true; + }, onMouseLeave = function () { + var series = tooltip.chart.hoverSeries; + tooltip.inContact = false; + if (series && + series.onMouseOut) { + series.onMouseOut(); + } + }; + if (!this.label) { + if (this.outside) { + /** + * Reference to the tooltip's container, when + * [Highcharts.Tooltip#outside] is set to true, otherwise + * it's undefined. + * + * @name Highcharts.Tooltip#container + * @type {Highcharts.HTMLDOMElement|undefined} + */ + this.container = container = H.doc.createElement('div'); + container.className = 'highcharts-tooltip-container'; + css(container, { + position: 'absolute', + top: '1px', + pointerEvents: pointerEvents, + zIndex: 3 + }); + H.doc.body.appendChild(container); + /** + * Reference to the tooltip's renderer, when + * [Highcharts.Tooltip#outside] is set to true, otherwise + * it's undefined. + * + * @name Highcharts.Tooltip#renderer + * @type {Highcharts.SVGRenderer|undefined} + */ + this.renderer = renderer = new H.Renderer(container, 0, 0, (_b = this.chart.options.chart) === null || _b === void 0 ? void 0 : _b.style, void 0, void 0, renderer.styledMode); + } + // Create the label + if (this.split) { + this.label = renderer.g(className); + } + else { + this.label = renderer + .label('', 0, 0, options.shape || 'callout', null, null, options.useHTML, null, className) + .attr({ + padding: options.padding, + r: options.borderRadius + }); + if (!styledMode) { + this.label + .attr({ + fill: options.backgroundColor, + 'stroke-width': options.borderWidth + }) + // #2301, #2657 + .css(options.style) + .css({ pointerEvents: pointerEvents }) + .shadow(options.shadow); + } + } + if (styledMode) { + // Apply the drop-shadow filter + this.applyFilter(); + this.label.addClass('highcharts-tooltip-' + this.chart.index); + } + // Split tooltip use updateTooltipContainer to position the tooltip + // container. + if (tooltip.outside && !tooltip.split) { + set = { + x: this.label.xSetter, + y: this.label.ySetter + }; + this.label.xSetter = function (value, key) { + set[key].call(this.label, tooltip.distance); + container.style.left = value + 'px'; + }; + this.label.ySetter = function (value, key) { + set[key].call(this.label, tooltip.distance); + container.style.top = value + 'px'; + }; + } + this.label + .on('mouseenter', onMouseEnter) + .on('mouseleave', onMouseLeave) + .attr({ zIndex: 8 }) + .add(); + } + return this.label; + }; + /** + * Place the tooltip in a chart without spilling over + * and not covering the point it self. + * + * @private + * @function Highcharts.Tooltip#getPosition + * + * @param {number} boxWidth + * + * @param {number} boxHeight + * + * @param {Highcharts.Point} point + * + * @return {Highcharts.PositionObject} + */ + Tooltip.prototype.getPosition = function (boxWidth, boxHeight, point) { + var chart = this.chart, distance = this.distance, ret = {}, + // Don't use h if chart isn't inverted (#7242) ??? + h = (chart.inverted && point.h) || 0, // #4117 ??? + swapped, outside = this.outside, outerWidth = outside ? + // substract distance to prevent scrollbars + doc.documentElement.clientWidth - 2 * distance : + chart.chartWidth, outerHeight = outside ? + Math.max(doc.body.scrollHeight, doc.documentElement.scrollHeight, doc.body.offsetHeight, doc.documentElement.offsetHeight, doc.documentElement.clientHeight) : + chart.chartHeight, chartPosition = chart.pointer.getChartPosition(), containerScaling = chart.containerScaling, scaleX = function (val) { return ( // eslint-disable-line no-confusing-arrow + containerScaling ? val * containerScaling.scaleX : val); }, scaleY = function (val) { return ( // eslint-disable-line no-confusing-arrow + containerScaling ? val * containerScaling.scaleY : val); }, + // Build parameter arrays for firstDimension()/secondDimension() + buildDimensionArray = function (dim) { + var isX = dim === 'x'; + return [ + dim, + isX ? outerWidth : outerHeight, + isX ? boxWidth : boxHeight + ].concat(outside ? [ + // If we are using tooltip.outside, we need to scale the + // position to match scaling of the container in case there + // is a transform/zoom on the container. #11329 + isX ? scaleX(boxWidth) : scaleY(boxHeight), + isX ? chartPosition.left - distance + + scaleX(point.plotX + chart.plotLeft) : + chartPosition.top - distance + + scaleY(point.plotY + chart.plotTop), + 0, + isX ? outerWidth : outerHeight + ] : [ + // Not outside, no scaling is needed + isX ? boxWidth : boxHeight, + isX ? point.plotX + chart.plotLeft : + point.plotY + chart.plotTop, + isX ? chart.plotLeft : chart.plotTop, + isX ? chart.plotLeft + chart.plotWidth : + chart.plotTop + chart.plotHeight + ]); + }, first = buildDimensionArray('y'), second = buildDimensionArray('x'), + // The far side is right or bottom + preferFarSide = !this.followPointer && pick(point.ttBelow, !chart.inverted === !!point.negative), // #4984 + /* + * Handle the preferred dimension. When the preferred dimension is + * tooltip on top or bottom of the point, it will look for space + * there. + * + * @private + */ + firstDimension = function (dim, outerSize, innerSize, scaledInnerSize, // #11329 + point, min, max) { + var scaledDist = dim === 'y' ? + scaleY(distance) : scaleX(distance), scaleDiff = (innerSize - scaledInnerSize) / 2, roomLeft = scaledInnerSize < point - distance, roomRight = point + distance + scaledInnerSize < outerSize, alignedLeft = point - scaledDist - innerSize + scaleDiff, alignedRight = point + scaledDist - scaleDiff; + if (preferFarSide && roomRight) { + ret[dim] = alignedRight; + } + else if (!preferFarSide && roomLeft) { + ret[dim] = alignedLeft; + } + else if (roomLeft) { + ret[dim] = Math.min(max - scaledInnerSize, alignedLeft - h < 0 ? alignedLeft : alignedLeft - h); + } + else if (roomRight) { + ret[dim] = Math.max(min, alignedRight + h + innerSize > outerSize ? + alignedRight : + alignedRight + h); + } + else { + return false; + } + }, + /* + * Handle the secondary dimension. If the preferred dimension is + * tooltip on top or bottom of the point, the second dimension is to + * align the tooltip above the point, trying to align center but + * allowing left or right align within the chart box. + * + * @private + */ + secondDimension = function (dim, outerSize, innerSize, scaledInnerSize, // #11329 + point) { + var retVal; + // Too close to the edge, return false and swap dimensions + if (point < distance || point > outerSize - distance) { + retVal = false; + // Align left/top + } + else if (point < innerSize / 2) { + ret[dim] = 1; + // Align right/bottom + } + else if (point > outerSize - scaledInnerSize / 2) { + ret[dim] = outerSize - scaledInnerSize - 2; + // Align center + } + else { + ret[dim] = point - innerSize / 2; + } + return retVal; + }, + /* + * Swap the dimensions + */ + swap = function (count) { + var temp = first; + first = second; + second = temp; + swapped = count; + }, run = function () { + if (firstDimension.apply(0, first) !== false) { + if (secondDimension.apply(0, second) === false && + !swapped) { + swap(true); + run(); + } + } + else if (!swapped) { + swap(true); + run(); + } + else { + ret.x = ret.y = 0; + } + }; + // Under these conditions, prefer the tooltip on the side of the point + if (chart.inverted || this.len > 1) { + swap(); + } + run(); + return ret; + }; + /** + * Get the best X date format based on the closest point range on the axis. + * + * @private + * @function Highcharts.Tooltip#getXDateFormat + * + * @param {Highcharts.Point} point + * + * @param {Highcharts.TooltipOptions} options + * + * @param {Highcharts.Axis} xAxis + * + * @return {string} + */ + Tooltip.prototype.getXDateFormat = function (point, options, xAxis) { + var xDateFormat, dateTimeLabelFormats = options.dateTimeLabelFormats, closestPointRange = xAxis && xAxis.closestPointRange; + if (closestPointRange) { + xDateFormat = this.getDateFormat(closestPointRange, point.x, xAxis.options.startOfWeek, dateTimeLabelFormats); + } + else { + xDateFormat = dateTimeLabelFormats.day; + } + return xDateFormat || dateTimeLabelFormats.year; // #2546, 2581 + }; + /** + * Hides the tooltip with a fade out animation. + * + * @function Highcharts.Tooltip#hide + * + * @param {number} [delay] + * The fade out in milliseconds. If no value is provided the value + * of the tooltip.hideDelay option is used. A value of 0 disables + * the fade out animation. + */ + Tooltip.prototype.hide = function (delay) { + var tooltip = this; + // disallow duplicate timers (#1728, #1766) + U.clearTimeout(this.hideTimer); + delay = pick(delay, this.options.hideDelay, 500); + if (!this.isHidden) { + this.hideTimer = syncTimeout(function () { + // If there is a delay, do fadeOut with the default duration. If + // the hideDelay is 0, we assume no animation is wanted, so we + // pass 0 duration. #12994. + tooltip.getLabel().fadeOut(delay ? void 0 : delay); + tooltip.isHidden = true; + }, delay); + } + }; + /** + * @private + * @function Highcharts.Tooltip#init + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @param {Highcharts.TooltipOptions} options + * Tooltip options. + */ + Tooltip.prototype.init = function (chart, options) { + /** + * Chart of the tooltip. + * + * @readonly + * @name Highcharts.Tooltip#chart + * @type {Highcharts.Chart} + */ + this.chart = chart; + /** + * Used tooltip options. + * + * @readonly + * @name Highcharts.Tooltip#options + * @type {Highcharts.TooltipOptions} + */ + this.options = options; + /** + * List of crosshairs. + * + * @private + * @readonly + * @name Highcharts.Tooltip#crosshairs + * @type {Array} + */ + this.crosshairs = []; + /** + * Current values of x and y when animating. + * + * @private + * @readonly + * @name Highcharts.Tooltip#now + * @type {Highcharts.PositionObject} + */ + this.now = { x: 0, y: 0 }; + /** + * Tooltips are initially hidden. + * + * @private + * @readonly + * @name Highcharts.Tooltip#isHidden + * @type {boolean} + */ + this.isHidden = true; + /** + * True, if the tooltip is split into one label per series, with the + * header close to the axis. + * + * @readonly + * @name Highcharts.Tooltip#split + * @type {boolean|undefined} + */ + this.split = options.split && !chart.inverted && !chart.polar; + /** + * When the tooltip is shared, the entire plot area will capture mouse + * movement or touch events. + * + * @readonly + * @name Highcharts.Tooltip#shared + * @type {boolean|undefined} + */ + this.shared = options.shared || this.split; + /** + * Whether to allow the tooltip to render outside the chart's SVG + * element box. By default (false), the tooltip is rendered within the + * chart's SVG element, which results in the tooltip being aligned + * inside the chart area. + * + * @readonly + * @name Highcharts.Tooltip#outside + * @type {boolean} + * + * @todo + * Split tooltip does not support outside in the first iteration. Should + * not be too complicated to implement. + */ + this.outside = pick(options.outside, Boolean(chart.scrollablePixelsX || chart.scrollablePixelsY)); + }; + /** + * Returns true, if the pointer is in contact with the tooltip tracker. + */ + Tooltip.prototype.isStickyOnContact = function () { + return !!(!this.followPointer && + this.options.stickOnContact && + this.inContact); + }; + /** + * Moves the tooltip with a soft animation to a new position. + * + * @private + * @function Highcharts.Tooltip#move + * + * @param {number} x + * + * @param {number} y + * + * @param {number} anchorX + * + * @param {number} anchorY + */ + Tooltip.prototype.move = function (x, y, anchorX, anchorY) { + var tooltip = this, now = tooltip.now, animate = tooltip.options.animation !== false && + !tooltip.isHidden && + // When we get close to the target position, abort animation and + // land on the right place (#3056) + (Math.abs(x - now.x) > 1 || Math.abs(y - now.y) > 1), skipAnchor = tooltip.followPointer || tooltip.len > 1; + // Get intermediate values for animation + extend(now, { + x: animate ? (2 * now.x + x) / 3 : x, + y: animate ? (now.y + y) / 2 : y, + anchorX: skipAnchor ? + void 0 : + animate ? (2 * now.anchorX + anchorX) / 3 : anchorX, + anchorY: skipAnchor ? + void 0 : + animate ? (now.anchorY + anchorY) / 2 : anchorY + }); + // Move to the intermediate value + tooltip.getLabel().attr(now); + tooltip.drawTracker(); + // Run on next tick of the mouse tracker + if (animate) { + // Never allow two timeouts + U.clearTimeout(this.tooltipTimeout); + // Set the fixed interval ticking for the smooth tooltip + this.tooltipTimeout = setTimeout(function () { + // The interval function may still be running during destroy, + // so check that the chart is really there before calling. + if (tooltip) { + tooltip.move(x, y, anchorX, anchorY); + } + }, 32); + } + }; + /** + * Refresh the tooltip's text and position. + * + * @function Highcharts.Tooltip#refresh + * + * @param {Highcharts.Point|Array} pointOrPoints + * Either a point or an array of points. + * + * @param {Highcharts.PointerEventObject} [mouseEvent] + * Mouse event, that is responsible for the refresh and should be + * used for the tooltip update. + */ + Tooltip.prototype.refresh = function (pointOrPoints, mouseEvent) { + var tooltip = this, chart = this.chart, options = tooltip.options, x, y, point = pointOrPoints, anchor, textConfig = {}, text, pointConfig = [], formatter = options.formatter || tooltip.defaultFormatter, shared = tooltip.shared, currentSeries, styledMode = chart.styledMode; + if (!options.enabled) { + return; + } + U.clearTimeout(this.hideTimer); + // get the reference point coordinates (pie charts use tooltipPos) + tooltip.followPointer = splat(point)[0].series.tooltipOptions + .followPointer; + anchor = tooltip.getAnchor(point, mouseEvent); + x = anchor[0]; + y = anchor[1]; + // shared tooltip, array is sent over + if (shared && + !(point.series && + point.series.noSharedTooltip)) { + chart.pointer.applyInactiveState(point); + // Now set hover state for the choosen ones: + point.forEach(function (item) { + item.setState('hover'); + pointConfig.push(item.getLabelConfig()); + }); + textConfig = { + x: point[0].category, + y: point[0].y + }; + textConfig.points = pointConfig; + point = point[0]; + // single point tooltip + } + else { + textConfig = point.getLabelConfig(); + } + this.len = pointConfig.length; // #6128 + text = formatter.call(textConfig, tooltip); + // register the current series + currentSeries = point.series; + this.distance = pick(currentSeries.tooltipOptions.distance, 16); + // update the inner HTML + if (text === false) { + this.hide(); + } + else { + // update text + if (tooltip.split) { + this.renderSplit(text, splat(pointOrPoints)); + } + else { + var label = tooltip.getLabel(); + // Prevent the tooltip from flowing over the chart box (#6659) + if (!options.style.width || styledMode) { + label.css({ + width: this.chart.spacingBox.width + 'px' + }); + } + label.attr({ + text: text && text.join ? + text.join('') : + text + }); + // Set the stroke color of the box to reflect the point + label.removeClass(/highcharts-color-[\d]+/g) + .addClass('highcharts-color-' + + pick(point.colorIndex, currentSeries.colorIndex)); + if (!styledMode) { + label.attr({ + stroke: (options.borderColor || + point.color || + currentSeries.color || + '#666666') + }); + } + tooltip.updatePosition({ + plotX: x, + plotY: y, + negative: point.negative, + ttBelow: point.ttBelow, + h: anchor[2] || 0 + }); + } + // show it + if (tooltip.isHidden && tooltip.label) { + tooltip.label.attr({ + opacity: 1 + }).show(); + } + tooltip.isHidden = false; + } + fireEvent(this, 'refresh'); + }; + /** + * Render the split tooltip. Loops over each point's text and adds + * a label next to the point, then uses the distribute function to + * find best non-overlapping positions. + * + * @private + * @function Highcharts.Tooltip#renderSplit + * + * @param {string|Array<(boolean|string)>} labels + * + * @param {Array} points + */ + Tooltip.prototype.renderSplit = function (labels, points) { + var tooltip = this; + var chart = tooltip.chart, _a = tooltip.chart, chartWidth = _a.chartWidth, chartHeight = _a.chartHeight, plotHeight = _a.plotHeight, plotLeft = _a.plotLeft, plotTop = _a.plotTop, pointer = _a.pointer, ren = _a.renderer, _b = _a.scrollablePixelsY, scrollablePixelsY = _b === void 0 ? 0 : _b, _c = _a.scrollingContainer, _d = _c === void 0 ? { scrollLeft: 0, scrollTop: 0 } : _c, scrollLeft = _d.scrollLeft, scrollTop = _d.scrollTop, styledMode = _a.styledMode, distance = tooltip.distance, options = tooltip.options, positioner = tooltip.options.positioner; + // The area which the tooltip should be limited to. Limit to scrollable + // plot area if enabled, otherwise limit to the chart container. + var bounds = { + left: scrollLeft, + right: scrollLeft + chartWidth, + top: scrollTop, + bottom: scrollTop + chartHeight + }; + var tooltipLabel = tooltip.getLabel(); + var headerTop = Boolean(chart.xAxis[0] && chart.xAxis[0].opposite); + var distributionBoxTop = plotTop + scrollTop; + var headerHeight = 0; + var adjustedPlotHeight = plotHeight - scrollablePixelsY; + /** + * Calculates the anchor position for the partial tooltip + * + * @private + * @param {Highcharts.Point} point The point related to the tooltip + * @return {object} Returns an object with anchorX and anchorY + */ + function getAnchor(point) { + var isHeader = point.isHeader, _a = point.plotX, plotX = _a === void 0 ? 0 : _a, _b = point.plotY, plotY = _b === void 0 ? 0 : _b, series = point.series; + var anchorX; + var anchorY; + if (isHeader) { + // Set anchorX to plotX + anchorX = plotLeft + plotX; + // Set anchorY to center of visible plot area. + anchorY = plotTop + plotHeight / 2; + } + else { + var xAxis = series.xAxis, yAxis = series.yAxis; + // Set anchorX to plotX. Limit to within xAxis. + anchorX = xAxis.pos + clamp(plotX, -distance, xAxis.len + distance); + // Set anchorY, limit to the scrollable plot area + if (yAxis.pos + plotY >= scrollTop + plotTop && + yAxis.pos + plotY <= scrollTop + plotTop + plotHeight - scrollablePixelsY) { + anchorY = yAxis.pos + plotY; + } + } + // Limit values to plot area + anchorX = clamp(anchorX, bounds.left - distance, bounds.right + distance); + return { anchorX: anchorX, anchorY: anchorY }; + } + /** + * Calculates the position of the partial tooltip + * + * @private + * @param {number} anchorX The partial tooltip anchor x position + * @param {number} anchorY The partial tooltip anchor y position + * @param {boolean} isHeader Whether the partial tooltip is a header + * @param {number} boxWidth Width of the partial tooltip + * @return {Highcharts.PositionObject} Returns the partial tooltip x and + * y position + */ + function defaultPositioner(anchorX, anchorY, isHeader, boxWidth, alignedLeft) { + if (alignedLeft === void 0) { alignedLeft = true; } + var y; + var x; + if (isHeader) { + y = headerTop ? 0 : adjustedPlotHeight; + x = clamp(anchorX - (boxWidth / 2), bounds.left, bounds.right - boxWidth); + } + else { + y = anchorY - distributionBoxTop; + x = alignedLeft ? + anchorX - boxWidth - distance : + anchorX + distance; + x = clamp(x, alignedLeft ? x : bounds.left, bounds.right); + } + // NOTE: y is relative to distributionBoxTop + return { x: x, y: y }; + } + /** + * Updates the attributes and styling of the partial tooltip. Creates a + * new partial tooltip if it does not exists. + * + * @private + * @param {Highcharts.SVGElement|undefined} partialTooltip + * The partial tooltip to update + * @param {Highcharts.Point} point + * The point related to the partial tooltip + * @param {boolean|string} str The text for the partial tooltip + * @return {Highcharts.SVGElement} Returns the updated partial tooltip + */ + function updatePartialTooltip(partialTooltip, point, str) { + var tt = partialTooltip; + var isHeader = point.isHeader, series = point.series; + var colorClass = 'highcharts-color-' + pick(point.colorIndex, series.colorIndex, 'none'); + if (!tt) { + var attribs = { + padding: options.padding, + r: options.borderRadius + }; + if (!styledMode) { + attribs.fill = options.backgroundColor; + attribs['stroke-width'] = options.borderWidth; + } + tt = ren + .label('', 0, 0, (options[isHeader ? 'headerShape' : 'shape']) || + 'callout', void 0, void 0, options.useHTML) + .addClass((isHeader ? 'highcharts-tooltip-header ' : '') + + 'highcharts-tooltip-box ' + + colorClass) + .attr(attribs) + .add(tooltipLabel); + } + tt.isActive = true; + tt.attr({ + text: str + }); + if (!styledMode) { + tt.css(options.style) + .shadow(options.shadow) + .attr({ + stroke: (options.borderColor || + point.color || + series.color || + '#333333') + }); + } + return tt; + } + // Graceful degradation for legacy formatters + if (isString(labels)) { + labels = [false, labels]; + } + // Create the individual labels for header and points, ignore footer + var boxes = labels.slice(0, points.length + 1).reduce(function (boxes, str, i) { + if (str !== false && str !== '') { + var point = points[i - 1] || { + // Item 0 is the header. Instead of this, we could also + // use the crosshair label + isHeader: true, + plotX: points[0].plotX, + plotY: plotHeight, + series: {} + }; + var isHeader = point.isHeader; + // Store the tooltip label referance on the series + var owner = isHeader ? tooltip : point.series; + var tt = owner.tt = updatePartialTooltip(owner.tt, point, str); + // Get X position now, so we can move all to the other side in + // case of overflow + var bBox = tt.getBBox(); + var boxWidth = bBox.width + tt.strokeWidth(); + if (isHeader) { + headerHeight = bBox.height; + adjustedPlotHeight += headerHeight; + if (headerTop) { + distributionBoxTop -= headerHeight; + } + } + var _a = getAnchor(point), anchorX = _a.anchorX, anchorY = _a.anchorY; + if (typeof anchorY === 'number') { + var size = bBox.height + 1; + var boxPosition = positioner ? positioner.call(tooltip, boxWidth, size, point) : defaultPositioner(anchorX, anchorY, isHeader, boxWidth); + boxes.push({ + // 0-align to the top, 1-align to the bottom + align: positioner ? 0 : void 0, + anchorX: anchorX, + anchorY: anchorY, + boxWidth: boxWidth, + point: point, + rank: pick(boxPosition.rank, isHeader ? 1 : 0), + size: size, + target: boxPosition.y, + tt: tt, + x: boxPosition.x + }); + } + else { + // Hide tooltips which anchorY is outside the visible plot + // area + tt.isActive = false; + } + } + return boxes; + }, []); + // If overflow left then align all labels to the right + if (!positioner && boxes.some(function (box) { return box.x < bounds.left; })) { + boxes = boxes.map(function (box) { + var _a = defaultPositioner(box.anchorX, box.anchorY, box.point.isHeader, box.boxWidth, false), x = _a.x, y = _a.y; + return extend(box, { + target: y, + x: x + }); + }); + } + // Clean previous run (for missing points) + tooltip.cleanSplit(); + // Distribute and put in place + H.distribute(boxes, adjustedPlotHeight); + boxes.forEach(function (box) { + var anchorX = box.anchorX, anchorY = box.anchorY, pos = box.pos, x = box.x; + // Put the label in place + box.tt.attr({ + visibility: typeof pos === 'undefined' ? 'hidden' : 'inherit', + x: x, + /* NOTE: y should equal pos to be consistent with !split + * tooltip, but is currently relative to plotTop. Is left as is + * to avoid breaking change. Remove distributionBoxTop to make + * it consistent. + */ + y: pos + distributionBoxTop, + anchorX: anchorX, + anchorY: anchorY + }); + }); + /* If we have a seperate tooltip container, then update the necessary + * container properties. + * Test that tooltip has its own container and renderer before executing + * the operation. + */ + var container = tooltip.container, outside = tooltip.outside, renderer = tooltip.renderer; + if (outside && container && renderer) { + // Set container size to fit the tooltip + var _e = tooltipLabel.getBBox(), width = _e.width, height = _e.height, x = _e.x, y = _e.y; + renderer.setSize(width + x, height + y, false); + // Position the tooltip container to the chart container + var chartPosition = pointer.getChartPosition(); + container.style.left = chartPosition.left + 'px'; + container.style.top = chartPosition.top + 'px'; + } + }; + /** + * If the `stickOnContact` option is active, this will add a tracker shape. + * + * @private + * @function Highcharts.Tooltip#drawTracker + */ + Tooltip.prototype.drawTracker = function () { + var tooltip = this; + if (tooltip.followPointer || + !tooltip.options.stickOnContact) { + if (tooltip.tracker) { + tooltip.tracker.destroy(); + } + return; + } + var chart = tooltip.chart; + var label = tooltip.label; + var point = chart.hoverPoint; + if (!label || !point) { + return; + } + var box = { + x: 0, + y: 0, + width: 0, + height: 0 + }; + // Combine anchor and tooltip + var anchorPos = this.getAnchor(point); + var labelBBox = label.getBBox(); + anchorPos[0] += chart.plotLeft - label.translateX; + anchorPos[1] += chart.plotTop - label.translateY; + // When the mouse pointer is between the anchor point and the label, + // the label should stick. + box.x = Math.min(0, anchorPos[0]); + box.y = Math.min(0, anchorPos[1]); + box.width = (anchorPos[0] < 0 ? + Math.max(Math.abs(anchorPos[0]), (labelBBox.width - anchorPos[0])) : + Math.max(Math.abs(anchorPos[0]), labelBBox.width)); + box.height = (anchorPos[1] < 0 ? + Math.max(Math.abs(anchorPos[1]), (labelBBox.height - Math.abs(anchorPos[1]))) : + Math.max(Math.abs(anchorPos[1]), labelBBox.height)); + if (tooltip.tracker) { + tooltip.tracker.attr(box); + } + else { + tooltip.tracker = label.renderer + .rect(box) + .addClass('highcharts-tracker') + .add(label); + if (!chart.styledMode) { + tooltip.tracker.attr({ + fill: 'rgba(0,0,0,0)' + }); + } + } + }; + /** + * @private + */ + Tooltip.prototype.styledModeFormat = function (formatString) { + return formatString + .replace('style="font-size: 10px"', 'class="highcharts-header"') + .replace(/style="color:{(point|series)\.color}"/g, 'class="highcharts-color-{$1.colorIndex}"'); + }; + /** + * Format the footer/header of the tooltip + * #3397: abstraction to enable formatting of footer and header + * + * @private + * @function Highcharts.Tooltip#tooltipFooterHeaderFormatter + * @param {Highcharts.PointLabelObject} labelConfig + * @param {boolean} [isFooter] + * @return {string} + */ + Tooltip.prototype.tooltipFooterHeaderFormatter = function (labelConfig, isFooter) { + var footOrHead = isFooter ? 'footer' : 'header', series = labelConfig.series, tooltipOptions = series.tooltipOptions, xDateFormat = tooltipOptions.xDateFormat, xAxis = series.xAxis, isDateTime = (xAxis && + xAxis.options.type === 'datetime' && + isNumber(labelConfig.key)), formatString = tooltipOptions[footOrHead + 'Format'], e = { + isFooter: isFooter, + labelConfig: labelConfig + }; + fireEvent(this, 'headerFormatter', e, function (e) { + // Guess the best date format based on the closest point distance + // (#568, #3418) + if (isDateTime && !xDateFormat) { + xDateFormat = this.getXDateFormat(labelConfig, tooltipOptions, xAxis); + } + // Insert the footer date format if any + if (isDateTime && xDateFormat) { + ((labelConfig.point && labelConfig.point.tooltipDateKeys) || + ['key']).forEach(function (key) { + formatString = formatString.replace('{point.' + key + '}', '{point.' + key + ':' + xDateFormat + '}'); + }); + } + // Replace default header style with class name + if (series.chart.styledMode) { + formatString = this.styledModeFormat(formatString); + } + e.text = format(formatString, { + point: labelConfig, + series: series + }, this.chart); + }); + return e.text; + }; + /** + * Updates the tooltip with the provided tooltip options. + * + * @function Highcharts.Tooltip#update + * + * @param {Highcharts.TooltipOptions} options + * The tooltip options to update. + */ + Tooltip.prototype.update = function (options) { + this.destroy(); + // Update user options (#6218) + merge(true, this.chart.options.tooltip.userOptions, options); + this.init(this.chart, merge(true, this.options, options)); + }; + /** + * Find the new position and perform the move + * + * @private + * @function Highcharts.Tooltip#updatePosition + * + * @param {Highcharts.Point} point + */ + Tooltip.prototype.updatePosition = function (point) { + var chart = this.chart, pointer = chart.pointer, label = this.getLabel(), pos, anchorX = point.plotX + chart.plotLeft, anchorY = point.plotY + chart.plotTop, pad; + // Needed for outside: true (#11688) + var chartPosition = pointer.getChartPosition(); + pos = (this.options.positioner || this.getPosition).call(this, label.width, label.height, point); + // Set the renderer size dynamically to prevent document size to change + if (this.outside) { + pad = (this.options.borderWidth || 0) + 2 * this.distance; + this.renderer.setSize(label.width + pad, label.height + pad, false); + // Anchor and tooltip container need scaling if chart container has + // scale transform/css zoom. #11329. + var containerScaling = chart.containerScaling; + if (containerScaling) { + css(this.container, { + transform: "scale(" + containerScaling.scaleX + ", " + containerScaling.scaleY + ")" + }); + anchorX *= containerScaling.scaleX; + anchorY *= containerScaling.scaleY; + } + anchorX += chartPosition.left - pos.x; + anchorY += chartPosition.top - pos.y; + } + // do the move + this.move(Math.round(pos.x), Math.round(pos.y || 0), // can be undefined (#3977) + anchorX, anchorY); + }; + return Tooltip; + }()); + H.Tooltip = Tooltip; + + return H.Tooltip; + }); + _registerModule(_modules, 'parts/Pointer.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['parts/Tooltip.js'], _modules['parts/Color.js']], function (Highcharts, U, Tooltip, Color) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * One position in relation to an axis. + * + * @interface Highcharts.PointerAxisCoordinateObject + */ /** + * Related axis. + * + * @name Highcharts.PointerAxisCoordinateObject#axis + * @type {Highcharts.Axis} + */ /** + * Axis value. + * + * @name Highcharts.PointerAxisCoordinateObject#value + * @type {number} + */ + /** + * Positions in terms of axis values. + * + * @interface Highcharts.PointerAxisCoordinatesObject + */ /** + * Positions on the x-axis. + * @name Highcharts.PointerAxisCoordinatesObject#xAxis + * @type {Array} + */ /** + * Positions on the y-axis. + * @name Highcharts.PointerAxisCoordinatesObject#yAxis + * @type {Array} + */ + /** + * Pointer coordinates. + * + * @interface Highcharts.PointerCoordinatesObject + */ /** + * @name Highcharts.PointerCoordinatesObject#chartX + * @type {number} + */ /** + * @name Highcharts.PointerCoordinatesObject#chartY + * @type {number} + */ + /** + * A native browser mouse or touch event, extended with position information + * relative to the {@link Chart.container}. + * + * @interface Highcharts.PointerEventObject + * @extends global.PointerEvent + */ /** + * The X coordinate of the pointer interaction relative to the chart. + * + * @name Highcharts.PointerEventObject#chartX + * @type {number} + */ /** + * The Y coordinate of the pointer interaction relative to the chart. + * + * @name Highcharts.PointerEventObject#chartY + * @type {number} + */ + /** + * Axis-specific data of a selection. + * + * @interface Highcharts.SelectDataObject + */ /** + * @name Highcharts.SelectDataObject#axis + * @type {Highcharts.Axis} + */ /** + * @name Highcharts.SelectDataObject#max + * @type {number} + */ /** + * @name Highcharts.SelectDataObject#min + * @type {number} + */ + /** + * Object for select events. + * + * @interface Highcharts.SelectEventObject + */ /** + * @name Highcharts.SelectEventObject#originalEvent + * @type {global.Event} + */ /** + * @name Highcharts.SelectEventObject#xAxis + * @type {Array} + */ /** + * @name Highcharts.SelectEventObject#yAxis + * @type {Array} + */ + var addEvent = U.addEvent, attr = U.attr, css = U.css, defined = U.defined, extend = U.extend, find = U.find, fireEvent = U.fireEvent, isNumber = U.isNumber, isObject = U.isObject, objectEach = U.objectEach, offset = U.offset, pick = U.pick, splat = U.splat; + var color = Color.parse; + var H = Highcharts, charts = H.charts, noop = H.noop; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The mouse and touch tracker object. Each {@link Chart} item has one + * assosiated Pointer item that can be accessed from the {@link Chart.pointer} + * property. + * + * @class + * @name Highcharts.Pointer + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @param {Highcharts.Options} options + * The root options object. The pointer uses options from the chart and + * tooltip structures. + */ + var Pointer = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Pointer(chart, options) { + this.lastValidTouch = {}; + this.pinchDown = []; + this.runChartClick = false; + this.chart = chart; + this.hasDragged = false; + this.options = options; + this.unbindContainerMouseLeave = function () { }; + this.init(chart, options); + } + /* * + * + * Functions + * + * */ + /** + * Set inactive state to all series that are not currently hovered, + * or, if `inactiveOtherPoints` is set to true, set inactive state to + * all points within that series. + * + * @function Highcharts.Pointer#applyInactiveState + * + * @private + * + * @param {Array} points + * Currently hovered points + * + */ + Pointer.prototype.applyInactiveState = function (points) { + var activeSeries = [], series; + // Get all active series from the hovered points + (points || []).forEach(function (item) { + series = item.series; + // Include itself + activeSeries.push(series); + // Include parent series + if (series.linkedParent) { + activeSeries.push(series.linkedParent); + } + // Include all child series + if (series.linkedSeries) { + activeSeries = activeSeries.concat(series.linkedSeries); + } + // Include navigator series + if (series.navigatorSeries) { + activeSeries.push(series.navigatorSeries); + } + }); + // Now loop over all series, filtering out active series + this.chart.series.forEach(function (inactiveSeries) { + if (activeSeries.indexOf(inactiveSeries) === -1) { + // Inactive series + inactiveSeries.setState('inactive', true); + } + else if (inactiveSeries.options.inactiveOtherPoints) { + // Active series, but other points should be inactivated + inactiveSeries.setAllPointsToState('inactive'); + } + }); + }; + /** + * Destroys the Pointer object and disconnects DOM events. + * + * @function Highcharts.Pointer#destroy + * + * @return {void} + */ + Pointer.prototype.destroy = function () { + var pointer = this; + if (typeof pointer.unDocMouseMove !== 'undefined') { + pointer.unDocMouseMove(); + } + this.unbindContainerMouseLeave(); + if (!H.chartCount) { + if (H.unbindDocumentMouseUp) { + H.unbindDocumentMouseUp = H.unbindDocumentMouseUp(); + } + if (H.unbindDocumentTouchEnd) { + H.unbindDocumentTouchEnd = H.unbindDocumentTouchEnd(); + } + } + // memory and CPU leak + clearInterval(pointer.tooltipTimeout); + objectEach(pointer, function (val, prop) { + pointer[prop] = null; + }); + }; + /** + * Perform a drag operation in response to a mousemove event while the mouse + * is down. + * + * @private + * @function Highcharts.Pointer#drag + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + Pointer.prototype.drag = function (e) { + var chart = this.chart, chartOptions = chart.options.chart, chartX = e.chartX, chartY = e.chartY, zoomHor = this.zoomHor, zoomVert = this.zoomVert, plotLeft = chart.plotLeft, plotTop = chart.plotTop, plotWidth = chart.plotWidth, plotHeight = chart.plotHeight, clickedInside, size, selectionMarker = this.selectionMarker, mouseDownX = (this.mouseDownX || 0), mouseDownY = (this.mouseDownY || 0), panningEnabled = isObject(chartOptions.panning) ? + chartOptions.panning && chartOptions.panning.enabled : + chartOptions.panning, panKey = (chartOptions.panKey && e[chartOptions.panKey + 'Key']); + // If the device supports both touch and mouse (like IE11), and we are + // touch-dragging inside the plot area, don't handle the mouse event. + // #4339. + if (selectionMarker && selectionMarker.touch) { + return; + } + // If the mouse is outside the plot area, adjust to cooordinates + // inside to prevent the selection marker from going outside + if (chartX < plotLeft) { + chartX = plotLeft; + } + else if (chartX > plotLeft + plotWidth) { + chartX = plotLeft + plotWidth; + } + if (chartY < plotTop) { + chartY = plotTop; + } + else if (chartY > plotTop + plotHeight) { + chartY = plotTop + plotHeight; + } + // determine if the mouse has moved more than 10px + this.hasDragged = Math.sqrt(Math.pow(mouseDownX - chartX, 2) + + Math.pow(mouseDownY - chartY, 2)); + if (this.hasDragged > 10) { + clickedInside = chart.isInsidePlot(mouseDownX - plotLeft, mouseDownY - plotTop); + // make a selection + if (chart.hasCartesianSeries && + (this.zoomX || this.zoomY) && + clickedInside && + !panKey) { + if (!selectionMarker) { + this.selectionMarker = selectionMarker = + chart.renderer.rect(plotLeft, plotTop, zoomHor ? 1 : plotWidth, zoomVert ? 1 : plotHeight, 0) + .attr({ + 'class': 'highcharts-selection-marker', + zIndex: 7 + }) + .add(); + if (!chart.styledMode) { + selectionMarker.attr({ + fill: (chartOptions.selectionMarkerFill || + color('#335cad') + .setOpacity(0.25).get()) + }); + } + } + } + // adjust the width of the selection marker + if (selectionMarker && zoomHor) { + size = chartX - mouseDownX; + selectionMarker.attr({ + width: Math.abs(size), + x: (size > 0 ? 0 : size) + mouseDownX + }); + } + // adjust the height of the selection marker + if (selectionMarker && zoomVert) { + size = chartY - mouseDownY; + selectionMarker.attr({ + height: Math.abs(size), + y: (size > 0 ? 0 : size) + mouseDownY + }); + } + // panning + if (clickedInside && + !selectionMarker && + panningEnabled) { + chart.pan(e, chartOptions.panning); + } + } + }; + /** + * Start a drag operation. + * + * @private + * @function Highcharts.Pointer#dragStart + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + Pointer.prototype.dragStart = function (e) { + var chart = this.chart; + // Record the start position + chart.mouseIsDown = e.type; + chart.cancelClick = false; + chart.mouseDownX = this.mouseDownX = e.chartX; + chart.mouseDownY = this.mouseDownY = e.chartY; + }; + /** + * On mouse up or touch end across the entire document, drop the selection. + * + * @private + * @function Highcharts.Pointer#drop + * + * @param {global.Event} e + */ + Pointer.prototype.drop = function (e) { + var pointer = this, chart = this.chart, hasPinched = this.hasPinched; + if (this.selectionMarker) { + var selectionData = { + originalEvent: e, + xAxis: [], + yAxis: [] + }, selectionBox = this.selectionMarker, selectionLeft = selectionBox.attr ? + selectionBox.attr('x') : + selectionBox.x, selectionTop = selectionBox.attr ? + selectionBox.attr('y') : + selectionBox.y, selectionWidth = selectionBox.attr ? + selectionBox.attr('width') : + selectionBox.width, selectionHeight = selectionBox.attr ? + selectionBox.attr('height') : + selectionBox.height, runZoom; + // a selection has been made + if (this.hasDragged || hasPinched) { + // record each axis' min and max + chart.axes.forEach(function (axis) { + if (axis.zoomEnabled && + defined(axis.min) && + (hasPinched || + pointer[{ + xAxis: 'zoomX', + yAxis: 'zoomY' + }[axis.coll]])) { // #859, #3569 + var horiz = axis.horiz, minPixelPadding = e.type === 'touchend' ? + axis.minPixelPadding : + 0, // #1207, #3075 + selectionMin = axis.toValue((horiz ? selectionLeft : selectionTop) + + minPixelPadding), selectionMax = axis.toValue((horiz ? + selectionLeft + selectionWidth : + selectionTop + selectionHeight) - minPixelPadding); + selectionData[axis.coll].push({ + axis: axis, + // Min/max for reversed axes + min: Math.min(selectionMin, selectionMax), + max: Math.max(selectionMin, selectionMax) + }); + runZoom = true; + } + }); + if (runZoom) { + fireEvent(chart, 'selection', selectionData, function (args) { + chart.zoom(extend(args, hasPinched ? + { animation: false } : + null)); + }); + } + } + if (isNumber(chart.index)) { + this.selectionMarker = this.selectionMarker.destroy(); + } + // Reset scaling preview + if (hasPinched) { + this.scaleGroups(); + } + } + // Reset all. Check isNumber because it may be destroyed on mouse up + // (#877) + if (chart && isNumber(chart.index)) { + css(chart.container, { cursor: chart._cursor }); + chart.cancelClick = this.hasDragged > 10; // #370 + chart.mouseIsDown = this.hasDragged = this.hasPinched = false; + this.pinchDown = []; + } + }; + /** + * Finds the closest point to a set of coordinates, using the k-d-tree + * algorithm. + * + * @function Highcharts.Pointer#findNearestKDPoints + * + * @param {Array} series + * All the series to search in. + * + * @param {boolean|undefined} shared + * Whether it is a shared tooltip or not. + * + * @param {Highcharts.PointerEventObject} e + * The pointer event object, containing chart coordinates of the + * pointer. + * + * @return {Highcharts.Point|undefined} + * The point closest to given coordinates. + */ + Pointer.prototype.findNearestKDPoint = function (series, shared, e) { + var chart = this.chart; + var hoverPoint = chart.hoverPoint; + var tooltip = chart.tooltip; + if (hoverPoint && + tooltip && + tooltip.isStickyOnContact()) { + return hoverPoint; + } + var closest; + /** @private */ + function sort(p1, p2) { + var isCloserX = p1.distX - p2.distX, isCloser = p1.dist - p2.dist, isAbove = (p2.series.group && p2.series.group.zIndex) - + (p1.series.group && p1.series.group.zIndex), result; + // We have two points which are not in the same place on xAxis + // and shared tooltip: + if (isCloserX !== 0 && shared) { // #5721 + result = isCloserX; + // Points are not exactly in the same place on x/yAxis: + } + else if (isCloser !== 0) { + result = isCloser; + // The same xAxis and yAxis position, sort by z-index: + } + else if (isAbove !== 0) { + result = isAbove; + // The same zIndex, sort by array index: + } + else { + result = + p1.series.index > p2.series.index ? + -1 : + 1; + } + return result; + } + series.forEach(function (s) { + var noSharedTooltip = s.noSharedTooltip && shared, compareX = (!noSharedTooltip && + s.options.findNearestPointBy.indexOf('y') < 0), point = s.searchPoint(e, compareX); + if ( // Check that we actually found a point on the series. + isObject(point, true) && + // Use the new point if it is closer. + (!isObject(closest, true) || + (sort(closest, point) > 0))) { + closest = point; + } + }); + return closest; + }; + /** + * @private + * @function Highcharts.Pointer#getChartCoordinatesFromPoint + * @param {Highcharts.Point} point + * @param {boolean} [inverted] + * @return {Highcharts.PointerCoordinatesObject|undefined} + */ + Pointer.prototype.getChartCoordinatesFromPoint = function (point, inverted) { + var series = point.series, xAxis = series.xAxis, yAxis = series.yAxis, plotX = pick(point.clientX, point.plotX), shapeArgs = point.shapeArgs; + if (xAxis && yAxis) { + return inverted ? { + chartX: xAxis.len + xAxis.pos - plotX, + chartY: yAxis.len + yAxis.pos - point.plotY + } : { + chartX: plotX + xAxis.pos, + chartY: point.plotY + yAxis.pos + }; + } + if (shapeArgs && shapeArgs.x && shapeArgs.y) { + // E.g. pies do not have axes + return { + chartX: shapeArgs.x, + chartY: shapeArgs.y + }; + } + }; + /** + * Return the cached chartPosition if it is available on the Pointer, + * otherwise find it. Running offset is quite expensive, so it should be + * avoided when we know the chart hasn't moved. + * + * @function Highcharts.Pointer#getChartPosition + * + * @return {Highcharts.OffsetObject} + * The offset of the chart container within the page + */ + Pointer.prototype.getChartPosition = function () { + return (this.chartPosition || + (this.chartPosition = offset(this.chart.container))); + }; + /** + * Get the click position in terms of axis values. + * + * @function Highcharts.Pointer#getCoordinates + * + * @param {Highcharts.PointerEventObject} e + * Pointer event, extended with `chartX` and `chartY` properties. + * + * @return {Highcharts.PointerAxisCoordinatesObject} + */ + Pointer.prototype.getCoordinates = function (e) { + var coordinates = { + xAxis: [], + yAxis: [] + }; + this.chart.axes.forEach(function (axis) { + coordinates[axis.isXAxis ? 'xAxis' : 'yAxis'].push({ + axis: axis, + value: axis.toValue(e[axis.horiz ? 'chartX' : 'chartY']) + }); + }); + return coordinates; + }; + /** + * Calculates what is the current hovered point/points and series. + * + * @private + * @function Highcharts.Pointer#getHoverData + * + * @param {Highcharts.Point|undefined} existingHoverPoint + * The point currrently beeing hovered. + * + * @param {Highcharts.Series|undefined} existingHoverSeries + * The series currently beeing hovered. + * + * @param {Array} series + * All the series in the chart. + * + * @param {boolean} isDirectTouch + * Is the pointer directly hovering the point. + * + * @param {boolean|undefined} shared + * Whether it is a shared tooltip or not. + * + * @param {Highcharts.PointerEventObject} [e] + * The triggering event, containing chart coordinates of the pointer. + * + * @return {object} + * Object containing resulting hover data: hoverPoint, hoverSeries, + * and hoverPoints. + */ + Pointer.prototype.getHoverData = function (existingHoverPoint, existingHoverSeries, series, isDirectTouch, shared, e) { + var hoverPoint, hoverPoints = [], hoverSeries = existingHoverSeries, useExisting = !!(isDirectTouch && existingHoverPoint), notSticky = hoverSeries && !hoverSeries.stickyTracking, + // Which series to look in for the hover point + searchSeries, + // Parameters needed for beforeGetHoverData event. + eventArgs = { + chartX: e ? e.chartX : void 0, + chartY: e ? e.chartY : void 0, + shared: shared + }, filter = function (s) { + return (s.visible && + !(!shared && s.directTouch) && // #3821 + pick(s.options.enableMouseTracking, true)); + }; + // Find chart.hoverPane and update filter method in polar. + fireEvent(this, 'beforeGetHoverData', eventArgs); + searchSeries = notSticky ? + // Only search on hovered series if it has stickyTracking false + [hoverSeries] : + // Filter what series to look in. + series.filter(function (s) { + return eventArgs.filter ? eventArgs.filter(s) : filter(s) && + s.stickyTracking; + }); + // Use existing hovered point or find the one closest to coordinates. + hoverPoint = useExisting || !e ? + existingHoverPoint : + this.findNearestKDPoint(searchSeries, shared, e); + // Assign hover series + hoverSeries = hoverPoint && hoverPoint.series; + // If we have a hoverPoint, assign hoverPoints. + if (hoverPoint) { + // When tooltip is shared, it displays more than one point + if (shared && !hoverSeries.noSharedTooltip) { + searchSeries = series.filter(function (s) { + return eventArgs.filter ? + eventArgs.filter(s) : filter(s) && !s.noSharedTooltip; + }); + // Get all points with the same x value as the hoverPoint + searchSeries.forEach(function (s) { + var point = find(s.points, function (p) { + return p.x === hoverPoint.x && !p.isNull; + }); + if (isObject(point)) { + /* + * Boost returns a minimal point. Convert it to a usable + * point for tooltip and states. + */ + if (s.chart.isBoosting) { + point = s.getPoint(point); + } + hoverPoints.push(point); + } + }); + } + else { + hoverPoints.push(hoverPoint); + } + } + // Check whether the hoverPoint is inside pane we are hovering over. + eventArgs = { hoverPoint: hoverPoint }; + fireEvent(this, 'afterGetHoverData', eventArgs); + return { + hoverPoint: eventArgs.hoverPoint, + hoverSeries: hoverSeries, + hoverPoints: hoverPoints + }; + }; + /** + * @private + * @function Highcharts.Pointer#getPointFromEvent + * + * @param {global.Event} e + * + * @return {Highcharts.Point|undefined} + */ + Pointer.prototype.getPointFromEvent = function (e) { + var target = e.target, point; + while (target && !point) { + point = target.point; + target = target.parentNode; + } + return point; + }; + /** + * @private + * @function Highcharts.Pointer#onTrackerMouseOut + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + Pointer.prototype.onTrackerMouseOut = function (e) { + var chart = this.chart; + var relatedTarget = e.relatedTarget || e.toElement; + var series = chart.hoverSeries; + this.isDirectTouch = false; + if (series && + relatedTarget && + !series.stickyTracking && + !this.inClass(relatedTarget, 'highcharts-tooltip') && + (!this.inClass(relatedTarget, 'highcharts-series-' + series.index) || // #2499, #4465, #5553 + !this.inClass(relatedTarget, 'highcharts-tracker'))) { + series.onMouseOut(); + } + }; + /** + * Utility to detect whether an element has, or has a parent with, a + * specificclass name. Used on detection of tracker objects and on deciding + * whether hovering the tooltip should cause the active series to mouse out. + * + * @function Highcharts.Pointer#inClass + * + * @param {Highcharts.SVGDOMElement|Highcharts.HTMLDOMElement} element + * The element to investigate. + * + * @param {string} className + * The class name to look for. + * + * @return {boolean|undefined} + * True if either the element or one of its parents has the given + * class name. + */ + Pointer.prototype.inClass = function (element, className) { + var elemClassName; + while (element) { + elemClassName = attr(element, 'class'); + if (elemClassName) { + if (elemClassName.indexOf(className) !== -1) { + return true; + } + if (elemClassName.indexOf('highcharts-container') !== -1) { + return false; + } + } + element = element.parentNode; + } + }; + /** + * Initialize the Pointer. + * + * @private + * @function Highcharts.Pointer#init + * + * @param {Highcharts.Chart} chart + * The Chart instance. + * + * @param {Highcharts.Options} options + * The root options object. The pointer uses options from the chart + * and tooltip structures. + * + * @return {void} + */ + Pointer.prototype.init = function (chart, options) { + // Store references + this.options = options; + this.chart = chart; + // Do we need to handle click on a touch device? + this.runChartClick = + options.chart.events && + !!options.chart.events.click; + this.pinchDown = []; + this.lastValidTouch = {}; + if (Tooltip) { + /** + * Tooltip object for points of series. + * + * @name Highcharts.Chart#tooltip + * @type {Highcharts.Tooltip} + */ + chart.tooltip = new Tooltip(chart, options.tooltip); + this.followTouchMove = pick(options.tooltip.followTouchMove, true); + } + this.setDOMEvents(); + }; + /** + * Takes a browser event object and extends it with custom Highcharts + * properties `chartX` and `chartY` in order to work on the internal + * coordinate system. + * + * @function Highcharts.Pointer#normalize + * + * @param {global.MouseEvent|global.PointerEvent|global.TouchEvent} e + * Event object in standard browsers. + * + * @param {Highcharts.OffsetObject} [chartPosition] + * Additional chart offset. + * + * @return {Highcharts.PointerEventObject} + * A browser event with extended properties `chartX` and `chartY`. + */ + Pointer.prototype.normalize = function (e, chartPosition) { + var touches = e.touches; + // iOS (#2757) + var ePos = (touches ? + touches.length ? + touches.item(0) : + touches.changedTouches[0] : + e); + // Get mouse position + if (!chartPosition) { + chartPosition = this.getChartPosition(); + } + var chartX = ePos.pageX - chartPosition.left, chartY = ePos.pageY - chartPosition.top; + // #11329 - when there is scaling on a parent element, we need to take + // this into account + var containerScaling = this.chart.containerScaling; + if (containerScaling) { + chartX /= containerScaling.scaleX; + chartY /= containerScaling.scaleY; + } + return extend(e, { + chartX: Math.round(chartX), + chartY: Math.round(chartY) + }); + }; + /** + * @private + * @function Highcharts.Pointer#onContainerClick + * + * @param {global.MouseEvent} e + * + * @return {void} + */ + Pointer.prototype.onContainerClick = function (e) { + var chart = this.chart; + var hoverPoint = chart.hoverPoint; + var pEvt = this.normalize(e); + var plotLeft = chart.plotLeft; + var plotTop = chart.plotTop; + if (!chart.cancelClick) { + // On tracker click, fire the series and point events. #783, #1583 + if (hoverPoint && + this.inClass(pEvt.target, 'highcharts-tracker')) { + // the series click event + fireEvent(hoverPoint.series, 'click', extend(pEvt, { + point: hoverPoint + })); + // the point click event + if (chart.hoverPoint) { // it may be destroyed (#1844) + hoverPoint.firePointEvent('click', pEvt); + } + // When clicking outside a tracker, fire a chart event + } + else { + extend(pEvt, this.getCoordinates(pEvt)); + // fire a click event in the chart + if (chart.isInsidePlot((pEvt.chartX - plotLeft), (pEvt.chartY - plotTop))) { + fireEvent(chart, 'click', pEvt); + } + } + } + }; + /** + * @private + * @function Highcharts.Pointer#onContainerMouseDown + * + * @param {global.MouseEvent} e + */ + Pointer.prototype.onContainerMouseDown = function (e) { + // Normalize before the 'if' for the legacy IE (#7850) + e = this.normalize(e); + // #11635, Firefox does not reliable fire move event after click scroll + if (H.isFirefox && + e.button !== 0) { + this.onContainerMouseMove(e); + } + // #11635, limiting to primary button (incl. IE 8 support) + if (typeof e.button === 'undefined' || + ((e.buttons || e.button) & 1) === 1) { + this.zoomOption(e); + this.dragStart(e); + } + }; + /** + * When mouse leaves the container, hide the tooltip. + * + * @private + * @function Highcharts.Pointer#onContainerMouseLeave + * + * @param {global.MouseEvent} e + * + * @return {void} + */ + Pointer.prototype.onContainerMouseLeave = function (e) { + var chart = charts[pick(H.hoverChartIndex, -1)]; + var tooltip = this.chart.tooltip; + e = this.normalize(e); + // #4886, MS Touch end fires mouseleave but with no related target + if (chart && + (e.relatedTarget || e.toElement)) { + chart.pointer.reset(); + // Also reset the chart position, used in #149 fix + chart.pointer.chartPosition = void 0; + } + if ( // #11635, Firefox wheel scroll does not fire out events consistently + tooltip && + !tooltip.isHidden) { + this.reset(); + } + }; + /** + * The mousemove, touchmove and touchstart event handler + * + * @private + * @function Highcharts.Pointer#onContainerMouseMove + * + * @param {global.MouseEvent} e + * + * @return {void} + */ + Pointer.prototype.onContainerMouseMove = function (e) { + var chart = this.chart; + var pEvt = this.normalize(e); + this.setHoverChartIndex(); + // In IE8 we apparently need this returnValue set to false in order to + // avoid text being selected. But in Chrome, e.returnValue is prevented, + // plus we don't need to run e.preventDefault to prevent selected text + // in modern browsers. So we set it conditionally. Remove it when IE8 is + // no longer needed. #2251, #3224. + if (!pEvt.preventDefault) { + pEvt.returnValue = false; + } + if (chart.mouseIsDown === 'mousedown') { + this.drag(pEvt); + } + // Show the tooltip and run mouse over events (#977) + if (!chart.openMenu && + (this.inClass(pEvt.target, 'highcharts-tracker') || + chart.isInsidePlot((pEvt.chartX - chart.plotLeft), (pEvt.chartY - chart.plotTop)))) { + this.runPointActions(pEvt); + } + }; + /** + * @private + * @function Highcharts.Pointer#onDocumentTouchEnd + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + Pointer.prototype.onDocumentTouchEnd = function (e) { + if (charts[H.hoverChartIndex]) { + charts[H.hoverChartIndex].pointer.drop(e); + } + }; + /** + * @private + * @function Highcharts.Pointer#onContainerTouchMove + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + Pointer.prototype.onContainerTouchMove = function (e) { + this.touch(e); + }; + /** + * @private + * @function Highcharts.Pointer#onContainerTouchStart + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + Pointer.prototype.onContainerTouchStart = function (e) { + this.zoomOption(e); + this.touch(e, true); + }; + /** + * Special handler for mouse move that will hide the tooltip when the mouse + * leaves the plotarea. Issue #149 workaround. The mouseleave event does not + * always fire. + * + * @private + * @function Highcharts.Pointer#onDocumentMouseMove + * + * @param {global.MouseEvent} e + * + * @return {void} + */ + Pointer.prototype.onDocumentMouseMove = function (e) { + var chart = this.chart; + var chartPosition = this.chartPosition; + var pEvt = this.normalize(e, chartPosition); + var tooltip = chart.tooltip; + // If we're outside, hide the tooltip + if (chartPosition && + (!tooltip || + !tooltip.isStickyOnContact()) && + !chart.isInsidePlot(pEvt.chartX - chart.plotLeft, pEvt.chartY - chart.plotTop) && + !this.inClass(pEvt.target, 'highcharts-tracker')) { + this.reset(); + } + }; + /** + * @private + * @function Highcharts.Pointer#onDocumentMouseUp + * + * @param {global.MouseEvent} e + * + * @return {void} + */ + Pointer.prototype.onDocumentMouseUp = function (e) { + var chart = charts[pick(H.hoverChartIndex, -1)]; + if (chart) { + chart.pointer.drop(e); + } + }; + /** + * Handle touch events with two touches + * + * @private + * @function Highcharts.Pointer#pinch + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + Pointer.prototype.pinch = function (e) { + var self = this, chart = self.chart, pinchDown = self.pinchDown, touches = (e.touches || []), touchesLength = touches.length, lastValidTouch = self.lastValidTouch, hasZoom = self.hasZoom, selectionMarker = self.selectionMarker, transform = {}, fireClickEvent = touchesLength === 1 && ((self.inClass(e.target, 'highcharts-tracker') && + chart.runTrackerClick) || + self.runChartClick), clip = {}; + // Don't initiate panning until the user has pinched. This prevents us + // from blocking page scrolling as users scroll down a long page + // (#4210). + if (touchesLength > 1) { + self.initiated = true; + } + // On touch devices, only proceed to trigger click if a handler is + // defined + if (hasZoom && self.initiated && !fireClickEvent) { + e.preventDefault(); + } + // Normalize each touch + [].map.call(touches, function (e) { + return self.normalize(e); + }); + // Register the touch start position + if (e.type === 'touchstart') { + [].forEach.call(touches, function (e, i) { + pinchDown[i] = { chartX: e.chartX, chartY: e.chartY }; + }); + lastValidTouch.x = [pinchDown[0].chartX, pinchDown[1] && + pinchDown[1].chartX]; + lastValidTouch.y = [pinchDown[0].chartY, pinchDown[1] && + pinchDown[1].chartY]; + // Identify the data bounds in pixels + chart.axes.forEach(function (axis) { + if (axis.zoomEnabled) { + var bounds = chart.bounds[axis.horiz ? 'h' : 'v'], minPixelPadding = axis.minPixelPadding, min = axis.toPixels(Math.min(pick(axis.options.min, axis.dataMin), axis.dataMin)), max = axis.toPixels(Math.max(pick(axis.options.max, axis.dataMax), axis.dataMax)), absMin = Math.min(min, max), absMax = Math.max(min, max); + // Store the bounds for use in the touchmove handler + bounds.min = Math.min(axis.pos, absMin - minPixelPadding); + bounds.max = Math.max(axis.pos + axis.len, absMax + minPixelPadding); + } + }); + self.res = true; // reset on next move + // Optionally move the tooltip on touchmove + } + else if (self.followTouchMove && touchesLength === 1) { + this.runPointActions(self.normalize(e)); + // Event type is touchmove, handle panning and pinching + } + else if (pinchDown.length) { // can be 0 when releasing, if touchend + // fires first + // Set the marker + if (!selectionMarker) { + self.selectionMarker = selectionMarker = extend({ + destroy: noop, + touch: true + }, chart.plotBox); + } + self.pinchTranslate(pinchDown, touches, transform, selectionMarker, clip, lastValidTouch); + self.hasPinched = hasZoom; + // Scale and translate the groups to provide visual feedback during + // pinching + self.scaleGroups(transform, clip); + if (self.res) { + self.res = false; + this.reset(false, 0); + } + } + }; + /** + * Run translation operations + * + * @private + * @function Highcharts.Pointer#pinchTranslate + * + * @param {Array<*>} pinchDown + * + * @param {Array} touches + * + * @param {*} transform + * + * @param {*} selectionMarker + * + * @param {*} clip + * + * @param {*} lastValidTouch + * + * @return {void} + */ + Pointer.prototype.pinchTranslate = function (pinchDown, touches, transform, selectionMarker, clip, lastValidTouch) { + if (this.zoomHor) { + this.pinchTranslateDirection(true, pinchDown, touches, transform, selectionMarker, clip, lastValidTouch); + } + if (this.zoomVert) { + this.pinchTranslateDirection(false, pinchDown, touches, transform, selectionMarker, clip, lastValidTouch); + } + }; + /** + * Run translation operations for each direction (horizontal and vertical) + * independently. + * + * @private + * @function Highcharts.Pointer#pinchTranslateDirection + * + * @param {boolean} horiz + * + * @param {Array<*>} pinchDown + * + * @param {Array} touches + * + * @param {*} transform + * + * @param {*} selectionMarker + * + * @param {*} clip + * + * @param {*} lastValidTouch + * + * @param {number|undefined} [forcedScale=1] + * + * @return {void} + */ + Pointer.prototype.pinchTranslateDirection = function (horiz, pinchDown, touches, transform, selectionMarker, clip, lastValidTouch, forcedScale) { + var chart = this.chart, xy = horiz ? 'x' : 'y', XY = horiz ? 'X' : 'Y', sChartXY = ('chart' + XY), wh = horiz ? 'width' : 'height', plotLeftTop = chart['plot' + (horiz ? 'Left' : 'Top')], selectionWH, selectionXY, clipXY, scale = forcedScale || 1, inverted = chart.inverted, bounds = chart.bounds[horiz ? 'h' : 'v'], singleTouch = pinchDown.length === 1, touch0Start = pinchDown[0][sChartXY], touch0Now = touches[0][sChartXY], touch1Start = !singleTouch && pinchDown[1][sChartXY], touch1Now = !singleTouch && touches[1][sChartXY], outOfBounds, transformScale, scaleKey, setScale = function () { + // Don't zoom if fingers are too close on this axis + if (typeof touch1Now === 'number' && + Math.abs(touch0Start - touch1Start) > 20) { + scale = forcedScale || + Math.abs(touch0Now - touch1Now) / + Math.abs(touch0Start - touch1Start); + } + clipXY = ((plotLeftTop - touch0Now) / scale) + touch0Start; + selectionWH = chart['plot' + (horiz ? 'Width' : 'Height')] / scale; + }; + // Set the scale, first pass + setScale(); + // The clip position (x or y) is altered if out of bounds, the selection + // position is not + selectionXY = clipXY; + // Out of bounds + if (selectionXY < bounds.min) { + selectionXY = bounds.min; + outOfBounds = true; + } + else if (selectionXY + selectionWH > bounds.max) { + selectionXY = bounds.max - selectionWH; + outOfBounds = true; + } + // Is the chart dragged off its bounds, determined by dataMin and + // dataMax? + if (outOfBounds) { + // Modify the touchNow position in order to create an elastic drag + // movement. This indicates to the user that the chart is responsive + // but can't be dragged further. + touch0Now -= 0.8 * (touch0Now - lastValidTouch[xy][0]); + if (typeof touch1Now === 'number') { + touch1Now -= 0.8 * (touch1Now - lastValidTouch[xy][1]); + } + // Set the scale, second pass to adapt to the modified touchNow + // positions + setScale(); + } + else { + lastValidTouch[xy] = [touch0Now, touch1Now]; + } + // Set geometry for clipping, selection and transformation + if (!inverted) { + clip[xy] = clipXY - plotLeftTop; + clip[wh] = selectionWH; + } + scaleKey = inverted ? (horiz ? 'scaleY' : 'scaleX') : 'scale' + XY; + transformScale = inverted ? 1 / scale : scale; + selectionMarker[wh] = selectionWH; + selectionMarker[xy] = selectionXY; + transform[scaleKey] = scale; + transform['translate' + XY] = (transformScale * plotLeftTop) + + (touch0Now - (transformScale * touch0Start)); + }; + /** + * Reset the tracking by hiding the tooltip, the hover series state and the + * hover point + * + * @function Highcharts.Pointer#reset + * + * @param {boolean} [allowMove] + * Instead of destroying the tooltip altogether, allow moving it if + * possible. + * + * @param {number} [delay] + * + * @return {void} + */ + Pointer.prototype.reset = function (allowMove, delay) { + var pointer = this, chart = pointer.chart, hoverSeries = chart.hoverSeries, hoverPoint = chart.hoverPoint, hoverPoints = chart.hoverPoints, tooltip = chart.tooltip, tooltipPoints = tooltip && tooltip.shared ? + hoverPoints : + hoverPoint; + // Check if the points have moved outside the plot area (#1003, #4736, + // #5101) + if (allowMove && tooltipPoints) { + splat(tooltipPoints).forEach(function (point) { + if (point.series.isCartesian && + typeof point.plotX === 'undefined') { + allowMove = false; + } + }); + } + // Just move the tooltip, #349 + if (allowMove) { + if (tooltip && tooltipPoints && splat(tooltipPoints).length) { + tooltip.refresh(tooltipPoints); + if (tooltip.shared && hoverPoints) { // #8284 + hoverPoints.forEach(function (point) { + point.setState(point.state, true); + if (point.series.isCartesian) { + if (point.series.xAxis.crosshair) { + point.series.xAxis + .drawCrosshair(null, point); + } + if (point.series.yAxis.crosshair) { + point.series.yAxis + .drawCrosshair(null, point); + } + } + }); + } + else if (hoverPoint) { // #2500 + hoverPoint.setState(hoverPoint.state, true); + chart.axes.forEach(function (axis) { + if (axis.crosshair && + hoverPoint.series[axis.coll] === axis) { + axis.drawCrosshair(null, hoverPoint); + } + }); + } + } + // Full reset + } + else { + if (hoverPoint) { + hoverPoint.onMouseOut(); + } + if (hoverPoints) { + hoverPoints.forEach(function (point) { + point.setState(); + }); + } + if (hoverSeries) { + hoverSeries.onMouseOut(); + } + if (tooltip) { + tooltip.hide(delay); + } + if (pointer.unDocMouseMove) { + pointer.unDocMouseMove = pointer.unDocMouseMove(); + } + // Remove crosshairs + chart.axes.forEach(function (axis) { + axis.hideCrosshair(); + }); + pointer.hoverX = chart.hoverPoints = chart.hoverPoint = null; + } + }; + /** + * With line type charts with a single tracker, get the point closest to the + * mouse. Run Point.onMouseOver and display tooltip for the point or points. + * + * @private + * @function Highcharts.Pointer#runPointActions + * + * @param {global.Event} e + * + * @param {Highcharts.PointerEventObject} [p] + * + * @return {void} + * + * @fires Highcharts.Point#event:mouseOut + * @fires Highcharts.Point#event:mouseOver + */ + Pointer.prototype.runPointActions = function (e, p) { + var pointer = this, chart = pointer.chart, series = chart.series, tooltip = (chart.tooltip && chart.tooltip.options.enabled ? + chart.tooltip : + void 0), shared = (tooltip ? + tooltip.shared : + false), hoverPoint = p || chart.hoverPoint, hoverSeries = hoverPoint && hoverPoint.series || chart.hoverSeries, + // onMouseOver or already hovering a series with directTouch + isDirectTouch = (!e || e.type !== 'touchmove') && (!!p || ((hoverSeries && hoverSeries.directTouch) && + pointer.isDirectTouch)), hoverData = this.getHoverData(hoverPoint, hoverSeries, series, isDirectTouch, shared, e), useSharedTooltip, followPointer, anchor, points; + // Update variables from hoverData. + hoverPoint = hoverData.hoverPoint; + points = hoverData.hoverPoints; + hoverSeries = hoverData.hoverSeries; + followPointer = hoverSeries && hoverSeries.tooltipOptions.followPointer; + useSharedTooltip = (shared && + hoverSeries && + !hoverSeries.noSharedTooltip); + // Refresh tooltip for kdpoint if new hover point or tooltip was hidden + // #3926, #4200 + if (hoverPoint && + // !(hoverSeries && hoverSeries.directTouch) && + (hoverPoint !== chart.hoverPoint || (tooltip && tooltip.isHidden))) { + (chart.hoverPoints || []).forEach(function (p) { + if (points.indexOf(p) === -1) { + p.setState(); + } + }); + // Set normal state to previous series + if (chart.hoverSeries !== hoverSeries) { + hoverSeries.onMouseOver(); + } + pointer.applyInactiveState(points); + // Do mouseover on all points (#3919, #3985, #4410, #5622) + (points || []).forEach(function (p) { + p.setState('hover'); + }); + // If tracking is on series in stead of on each point, + // fire mouseOver on hover point. // #4448 + if (chart.hoverPoint) { + chart.hoverPoint.firePointEvent('mouseOut'); + } + // Hover point may have been destroyed in the event handlers (#7127) + if (!hoverPoint.series) { + return; + } + hoverPoint.firePointEvent('mouseOver'); + /** + * Contains all hovered points. + * + * @name Highcharts.Chart#hoverPoints + * @type {Array|null} + */ + chart.hoverPoints = points; + /** + * Contains the original hovered point. + * + * @name Highcharts.Chart#hoverPoint + * @type {Highcharts.Point|null} + */ + chart.hoverPoint = hoverPoint; + // Draw tooltip if necessary + if (tooltip) { + tooltip.refresh(useSharedTooltip ? points : hoverPoint, e); + } + // Update positions (regardless of kdpoint or hoverPoint) + } + else if (followPointer && tooltip && !tooltip.isHidden) { + anchor = tooltip.getAnchor([{}], e); + tooltip.updatePosition({ plotX: anchor[0], plotY: anchor[1] }); + } + // Start the event listener to pick up the tooltip and crosshairs + if (!pointer.unDocMouseMove) { + pointer.unDocMouseMove = addEvent(chart.container.ownerDocument, 'mousemove', function (e) { + var chart = charts[H.hoverChartIndex]; + if (chart) { + chart.pointer.onDocumentMouseMove(e); + } + }); + } + // Issues related to crosshair #4927, #5269 #5066, #5658 + chart.axes.forEach(function drawAxisCrosshair(axis) { + var snap = pick((axis.crosshair || {}).snap, true); + var point; + if (snap) { + point = chart.hoverPoint; // #13002 + if (!point || point.series[axis.coll] !== axis) { + point = find(points, function (p) { + return p.series[axis.coll] === axis; + }); + } + } + // Axis has snapping crosshairs, and one of the hover points belongs + // to axis. Always call drawCrosshair when it is not snap. + if (point || !snap) { + axis.drawCrosshair(e, point); + // Axis has snapping crosshairs, but no hover point belongs to axis + } + else { + axis.hideCrosshair(); + } + }); + }; + /** + * Scale series groups to a certain scale and translation. + * + * @private + * @function Highcharts.Pointer#scaleGroups + * + * @param {Highcharts.SeriesPlotBoxObject} [attribs] + * + * @param {boolean} [clip] + * + * @return {void} + */ + Pointer.prototype.scaleGroups = function (attribs, clip) { + var chart = this.chart, seriesAttribs; + // Scale each series + chart.series.forEach(function (series) { + seriesAttribs = attribs || series.getPlotBox(); // #1701 + if (series.xAxis && series.xAxis.zoomEnabled && series.group) { + series.group.attr(seriesAttribs); + if (series.markerGroup) { + series.markerGroup.attr(seriesAttribs); + series.markerGroup.clip(clip ? chart.clipRect : null); + } + if (series.dataLabelsGroup) { + series.dataLabelsGroup.attr(seriesAttribs); + } + } + }); + // Clip + chart.clipRect.attr(clip || chart.clipBox); + }; + /** + * Set the JS DOM events on the container and document. This method should + * contain a one-to-one assignment between methods and their handlers. Any + * advanced logic should be moved to the handler reflecting the event's + * name. + * + * @private + * @function Highcharts.Pointer#setDOMEvents + * + * @return {void} + */ + Pointer.prototype.setDOMEvents = function () { + var container = this.chart.container, ownerDoc = container.ownerDocument; + container.onmousedown = this.onContainerMouseDown.bind(this); + container.onmousemove = this.onContainerMouseMove.bind(this); + container.onclick = this.onContainerClick.bind(this); + this.unbindContainerMouseLeave = addEvent(container, 'mouseleave', this.onContainerMouseLeave.bind(this)); + if (!H.unbindDocumentMouseUp) { + H.unbindDocumentMouseUp = addEvent(ownerDoc, 'mouseup', this.onDocumentMouseUp.bind(this)); + } + if (H.hasTouch) { + addEvent(container, 'touchstart', this.onContainerTouchStart.bind(this)); + addEvent(container, 'touchmove', this.onContainerTouchMove.bind(this)); + if (!H.unbindDocumentTouchEnd) { + H.unbindDocumentTouchEnd = addEvent(ownerDoc, 'touchend', this.onDocumentTouchEnd.bind(this)); + } + } + }; + /** + * Sets the index of the hovered chart and leaves the previous hovered + * chart, to reset states like tooltip. + * + * @private + * @function Highcharts.Pointer#setHoverChartIndex + */ + Pointer.prototype.setHoverChartIndex = function () { + var chart = this.chart; + var hoverChart = H.charts[pick(H.hoverChartIndex, -1)]; + if (hoverChart && + hoverChart !== chart) { + hoverChart.pointer.onContainerMouseLeave({ relatedTarget: true }); + } + if (!hoverChart || + !hoverChart.mouseIsDown) { + H.hoverChartIndex = chart.index; + } + }; + /** + * General touch handler shared by touchstart and touchmove. + * + * @private + * @function Highcharts.Pointer#touch + * + * @param {Highcharts.PointerEventObject} e + * + * @param {boolean} [start] + * + * @return {void} + */ + Pointer.prototype.touch = function (e, start) { + var chart = this.chart, hasMoved, pinchDown, isInside; + this.setHoverChartIndex(); + if (e.touches.length === 1) { + e = this.normalize(e); + isInside = chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop); + if (isInside && !chart.openMenu) { + // Run mouse events and display tooltip etc + if (start) { + this.runPointActions(e); + } + // Android fires touchmove events after the touchstart even if + // the finger hasn't moved, or moved only a pixel or two. In iOS + // however, the touchmove doesn't fire unless the finger moves + // more than ~4px. So we emulate this behaviour in Android by + // checking how much it moved, and cancelling on small + // distances. #3450. + if (e.type === 'touchmove') { + pinchDown = this.pinchDown; + hasMoved = pinchDown[0] ? Math.sqrt(// #5266 + Math.pow(pinchDown[0].chartX - e.chartX, 2) + + Math.pow(pinchDown[0].chartY - e.chartY, 2)) >= 4 : false; + } + if (pick(hasMoved, true)) { + this.pinch(e); + } + } + else if (start) { + // Hide the tooltip on touching outside the plot area (#1203) + this.reset(); + } + } + else if (e.touches.length === 2) { + this.pinch(e); + } + }; + /** + * Resolve the zoomType option, this is reset on all touch start and mouse + * down events. + * + * @private + * @function Highcharts.Pointer#zoomOption + * + * @param {global.Event} e + * Event object. + * + * @param {void} + */ + Pointer.prototype.zoomOption = function (e) { + var chart = this.chart, options = chart.options.chart, zoomType = options.zoomType || '', inverted = chart.inverted, zoomX, zoomY; + // Look for the pinchType option + if (/touch/.test(e.type)) { + zoomType = pick(options.pinchType, zoomType); + } + this.zoomX = zoomX = /x/.test(zoomType); + this.zoomY = zoomY = /y/.test(zoomType); + this.zoomHor = (zoomX && !inverted) || (zoomY && inverted); + this.zoomVert = (zoomY && !inverted) || (zoomX && inverted); + this.hasZoom = zoomX || zoomY; + }; + return Pointer; + }()); + H.Pointer = Pointer; + + return H.Pointer; + }); + _registerModule(_modules, 'parts/MSPointer.js', [_modules['parts/Globals.js'], _modules['parts/Pointer.js'], _modules['parts/Utilities.js']], function (H, Pointer, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; + })(); + /* globals MSPointerEvent, PointerEvent */ + var addEvent = U.addEvent, css = U.css, objectEach = U.objectEach, removeEvent = U.removeEvent; + var charts = H.charts, doc = H.doc, noop = H.noop, win = H.win; + // The touches object keeps track of the points being touched at all times + var touches = {}; + var hasPointerEvent = !!win.PointerEvent; + /* eslint-disable valid-jsdoc */ + /** @private */ + function getWebkitTouches() { + var fake = []; + fake.item = function (i) { + return this[i]; + }; + objectEach(touches, function (touch) { + fake.push({ + pageX: touch.pageX, + pageY: touch.pageY, + target: touch.target + }); + }); + return fake; + } + /** @private */ + function translateMSPointer(e, method, wktype, func) { + var p; + if ((e.pointerType === 'touch' || + e.pointerType === e.MSPOINTER_TYPE_TOUCH) && charts[H.hoverChartIndex]) { + func(e); + p = charts[H.hoverChartIndex].pointer; + p[method]({ + type: wktype, + target: e.currentTarget, + preventDefault: noop, + touches: getWebkitTouches() + }); + } + } + /** @private */ + var MSPointer = /** @class */ (function (_super) { + __extends(MSPointer, _super); + function MSPointer() { + return _super !== null && _super.apply(this, arguments) || this; + } + /* * + * + * Functions + * + * */ + /** + * Add or remove the MS Pointer specific events + * + * @private + * @function Highcharts.Pointer#batchMSEvents + * + * @param {Function} fn + * + * @return {void} + */ + MSPointer.prototype.batchMSEvents = function (fn) { + fn(this.chart.container, hasPointerEvent ? 'pointerdown' : 'MSPointerDown', this.onContainerPointerDown); + fn(this.chart.container, hasPointerEvent ? 'pointermove' : 'MSPointerMove', this.onContainerPointerMove); + fn(doc, hasPointerEvent ? 'pointerup' : 'MSPointerUp', this.onDocumentPointerUp); + }; + // Destroy MS events also + MSPointer.prototype.destroy = function () { + this.batchMSEvents(removeEvent); + _super.prototype.destroy.call(this); + }; + // Disable default IE actions for pinch and such on chart element + MSPointer.prototype.init = function (chart, options) { + _super.prototype.init.call(this, chart, options); + if (this.hasZoom) { // #4014 + css(chart.container, { + '-ms-touch-action': 'none', + 'touch-action': 'none' + }); + } + }; + /** + * @private + * @function Highcharts.Pointer#onContainerPointerDown + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + MSPointer.prototype.onContainerPointerDown = function (e) { + translateMSPointer(e, 'onContainerTouchStart', 'touchstart', function (e) { + touches[e.pointerId] = { + pageX: e.pageX, + pageY: e.pageY, + target: e.currentTarget + }; + }); + }; + /** + * @private + * @function Highcharts.Pointer#onContainerPointerMove + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + MSPointer.prototype.onContainerPointerMove = function (e) { + translateMSPointer(e, 'onContainerTouchMove', 'touchmove', function (e) { + touches[e.pointerId] = ({ pageX: e.pageX, pageY: e.pageY }); + if (!touches[e.pointerId].target) { + touches[e.pointerId].target = e.currentTarget; + } + }); + }; + /** + * @private + * @function Highcharts.Pointer#onDocumentPointerUp + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + MSPointer.prototype.onDocumentPointerUp = function (e) { + translateMSPointer(e, 'onDocumentTouchEnd', 'touchend', function (e) { + delete touches[e.pointerId]; + }); + }; + // Add IE specific touch events to chart + MSPointer.prototype.setDOMEvents = function () { + _super.prototype.setDOMEvents.call(this); + if (this.hasZoom || this.followTouchMove) { + this.batchMSEvents(addEvent); + } + }; + return MSPointer; + }(Pointer)); + + return MSPointer; + }); + _registerModule(_modules, 'parts/Legend.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Gets fired when the legend item belonging to a point is clicked. The default + * action is to toggle the visibility of the point. This can be prevented by + * returning `false` or calling `event.preventDefault()`. + * + * @callback Highcharts.PointLegendItemClickCallbackFunction + * + * @param {Highcharts.Point} this + * The point on which the event occured. + * + * @param {Highcharts.PointLegendItemClickEventObject} event + * The event that occured. + */ + /** + * Information about the legend click event. + * + * @interface Highcharts.PointLegendItemClickEventObject + */ /** + * Related browser event. + * @name Highcharts.PointLegendItemClickEventObject#browserEvent + * @type {Highcharts.PointerEvent} + */ /** + * Prevent the default action of toggle the visibility of the point. + * @name Highcharts.PointLegendItemClickEventObject#preventDefault + * @type {Function} + */ /** + * Related point. + * @name Highcharts.PointLegendItemClickEventObject#target + * @type {Highcharts.Point} + */ /** + * Event type. + * @name Highcharts.PointLegendItemClickEventObject#type + * @type {"legendItemClick"} + */ + /** + * Gets fired when the legend item belonging to a series is clicked. The default + * action is to toggle the visibility of the series. This can be prevented by + * returning `false` or calling `event.preventDefault()`. + * + * @callback Highcharts.SeriesLegendItemClickCallbackFunction + * + * @param {Highcharts.Series} this + * The series where the event occured. + * + * @param {Highcharts.SeriesLegendItemClickEventObject} event + * The event that occured. + */ + /** + * Information about the legend click event. + * + * @interface Highcharts.SeriesLegendItemClickEventObject + */ /** + * Related browser event. + * @name Highcharts.SeriesLegendItemClickEventObject#browserEvent + * @type {Highcharts.PointerEvent} + */ /** + * Prevent the default action of toggle the visibility of the series. + * @name Highcharts.SeriesLegendItemClickEventObject#preventDefault + * @type {Function} + */ /** + * Related series. + * @name Highcharts.SeriesLegendItemClickEventObject#target + * @type {Highcharts.Series} + */ /** + * Event type. + * @name Highcharts.SeriesLegendItemClickEventObject#type + * @type {"legendItemClick"} + */ + var addEvent = U.addEvent, animObject = U.animObject, css = U.css, defined = U.defined, discardElement = U.discardElement, find = U.find, fireEvent = U.fireEvent, format = U.format, isNumber = U.isNumber, merge = U.merge, pick = U.pick, relativeLength = U.relativeLength, setAnimation = U.setAnimation, stableSort = U.stableSort, syncTimeout = U.syncTimeout, wrap = U.wrap; + var isFirefox = H.isFirefox, marginNames = H.marginNames, win = H.win; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The overview of the chart's series. The legend object is instanciated + * internally in the chart constructor, and is available from the `chart.legend` + * property. Each chart has only one legend. + * + * @class + * @name Highcharts.Legend + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @param {Highcharts.LegendOptions} options + * Legend options. + */ + var Legend = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Legend(chart, options) { + /* * + * + * Properties + * + * */ + this.allItems = []; + this.box = void 0; + this.contentGroup = void 0; + this.display = false; + this.group = void 0; + this.initialItemY = 0; + this.itemHeight = 0; + this.itemMarginBottom = 0; + this.itemMarginTop = 0; + this.itemX = 0; + this.itemY = 0; + this.lastItemY = 0; + this.lastLineHeight = 0; + this.legendHeight = 0; + this.legendWidth = 0; + this.maxItemWidth = 0; + this.maxLegendWidth = 0; + this.offsetWidth = 0; + this.options = {}; + this.padding = 0; + this.pages = []; + this.proximate = false; + this.scrollGroup = void 0; + this.symbolHeight = 0; + this.symbolWidth = 0; + this.titleHeight = 0; + this.totalItemWidth = 0; + this.widthOption = 0; + this.chart = chart; + this.init(chart, options); + } + /* * + * + * Functions + * + * */ + /** + * Initialize the legend. + * + * @private + * @function Highcharts.Legend#init + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @param {Highcharts.LegendOptions} options + * Legend options. + */ + Legend.prototype.init = function (chart, options) { + /** + * Chart of this legend. + * + * @readonly + * @name Highcharts.Legend#chart + * @type {Highcharts.Chart} + */ + this.chart = chart; + this.setOptions(options); + if (options.enabled) { + // Render it + this.render(); + // move checkboxes + addEvent(this.chart, 'endResize', function () { + this.legend.positionCheckboxes(); + }); + if (this.proximate) { + this.unchartrender = addEvent(this.chart, 'render', function () { + this.legend.proximatePositions(); + this.legend.positionItems(); + }); + } + else if (this.unchartrender) { + this.unchartrender(); + } + } + }; + /** + * @private + * @function Highcharts.Legend#setOptions + * @param {Highcharts.LegendOptions} options + */ + Legend.prototype.setOptions = function (options) { + var padding = pick(options.padding, 8); + /** + * Legend options. + * + * @readonly + * @name Highcharts.Legend#options + * @type {Highcharts.LegendOptions} + */ + this.options = options; + if (!this.chart.styledMode) { + this.itemStyle = options.itemStyle; + this.itemHiddenStyle = merge(this.itemStyle, options.itemHiddenStyle); + } + this.itemMarginTop = options.itemMarginTop || 0; + this.itemMarginBottom = options.itemMarginBottom || 0; + this.padding = padding; + this.initialItemY = padding - 5; // 5 is pixels above the text + this.symbolWidth = pick(options.symbolWidth, 16); + this.pages = []; + this.proximate = options.layout === 'proximate' && !this.chart.inverted; + this.baseline = void 0; // #12705: baseline has to be reset on every update + }; + /** + * Update the legend with new options. Equivalent to running `chart.update` + * with a legend configuration option. + * + * @sample highcharts/legend/legend-update/ + * Legend update + * + * @function Highcharts.Legend#update + * + * @param {Highcharts.LegendOptions} options + * Legend options. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the axis is altered. If doing more + * operations on the chart, it is a good idea to set redraw to false and + * call {@link Chart#redraw} after. Whether to redraw the chart. + * + * @fires Highcharts.Legends#event:afterUpdate + */ + Legend.prototype.update = function (options, redraw) { + var chart = this.chart; + this.setOptions(merge(true, this.options, options)); + this.destroy(); + chart.isDirtyLegend = chart.isDirtyBox = true; + if (pick(redraw, true)) { + chart.redraw(); + } + fireEvent(this, 'afterUpdate'); + }; + /** + * Set the colors for the legend item. + * + * @private + * @function Highcharts.Legend#colorizeItem + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + * A Series or Point instance + * @param {boolean} [visible=false] + * Dimmed or colored + * + * @todo + * Make events official: Fires the event `afterColorizeItem`. + */ + Legend.prototype.colorizeItem = function (item, visible) { + item.legendGroup[visible ? 'removeClass' : 'addClass']('highcharts-legend-item-hidden'); + if (!this.chart.styledMode) { + var legend = this, options = legend.options, legendItem = item.legendItem, legendLine = item.legendLine, legendSymbol = item.legendSymbol, hiddenColor = legend.itemHiddenStyle.color, textColor = visible ? + options.itemStyle.color : + hiddenColor, symbolColor = visible ? + (item.color || hiddenColor) : + hiddenColor, markerOptions = item.options && item.options.marker, symbolAttr = { fill: symbolColor }; + if (legendItem) { + legendItem.css({ + fill: textColor, + color: textColor // #1553, oldIE + }); + } + if (legendLine) { + legendLine.attr({ stroke: symbolColor }); + } + if (legendSymbol) { + // Apply marker options + if (markerOptions && legendSymbol.isMarker) { // #585 + symbolAttr = item.pointAttribs(); + if (!visible) { + // #6769 + symbolAttr.stroke = symbolAttr.fill = hiddenColor; + } + } + legendSymbol.attr(symbolAttr); + } + } + fireEvent(this, 'afterColorizeItem', { item: item, visible: visible }); + }; + /** + * @private + * @function Highcharts.Legend#positionItems + */ + Legend.prototype.positionItems = function () { + // Now that the legend width and height are established, put the items + // in the final position + this.allItems.forEach(this.positionItem, this); + if (!this.chart.isResizing) { + this.positionCheckboxes(); + } + }; + /** + * Position the legend item. + * + * @private + * @function Highcharts.Legend#positionItem + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + * The item to position + */ + Legend.prototype.positionItem = function (item) { + var legend = this, options = legend.options, symbolPadding = options.symbolPadding, ltr = !options.rtl, legendItemPos = item._legendItemPos, itemX = legendItemPos[0], itemY = legendItemPos[1], checkbox = item.checkbox, legendGroup = item.legendGroup; + if (legendGroup && legendGroup.element) { + legendGroup[defined(legendGroup.translateY) ? 'animate' : 'attr']({ + translateX: ltr ? + itemX : + legend.legendWidth - itemX - 2 * symbolPadding - 4, + translateY: itemY + }); + } + if (checkbox) { + checkbox.x = itemX; + checkbox.y = itemY; + } + }; + /** + * Destroy a single legend item, used internally on removing series items. + * + * @private + * @function Highcharts.Legend#destroyItem + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + * The item to remove + */ + Legend.prototype.destroyItem = function (item) { + var checkbox = item.checkbox; + // destroy SVG elements + ['legendItem', 'legendLine', 'legendSymbol', 'legendGroup'].forEach(function (key) { + if (item[key]) { + item[key] = item[key].destroy(); + } + }); + if (checkbox) { + discardElement(item.checkbox); + } + }; + /** + * Destroy the legend. Used internally. To reflow objects, `chart.redraw` + * must be called after destruction. + * + * @private + * @function Highcharts.Legend#destroy + */ + Legend.prototype.destroy = function () { + /** + * @private + * @param {string} key + * @return {void} + */ + function destroyItems(key) { + if (this[key]) { + this[key] = this[key].destroy(); + } + } + // Destroy items + this.getAllItems().forEach(function (item) { + ['legendItem', 'legendGroup'].forEach(destroyItems, item); + }); + // Destroy legend elements + [ + 'clipRect', + 'up', + 'down', + 'pager', + 'nav', + 'box', + 'title', + 'group' + ].forEach(destroyItems, this); + this.display = null; // Reset in .render on update. + }; + /** + * Position the checkboxes after the width is determined. + * + * @private + * @function Highcharts.Legend#positionCheckboxes + */ + Legend.prototype.positionCheckboxes = function () { + var alignAttr = this.group && this.group.alignAttr, translateY, clipHeight = this.clipHeight || this.legendHeight, titleHeight = this.titleHeight; + if (alignAttr) { + translateY = alignAttr.translateY; + this.allItems.forEach(function (item) { + var checkbox = item.checkbox, top; + if (checkbox) { + top = translateY + titleHeight + checkbox.y + + (this.scrollOffset || 0) + 3; + css(checkbox, { + left: (alignAttr.translateX + item.checkboxOffset + + checkbox.x - 20) + 'px', + top: top + 'px', + display: this.proximate || (top > translateY - 6 && + top < translateY + clipHeight - 6) ? + '' : + 'none' + }); + } + }, this); + } + }; + /** + * Render the legend title on top of the legend. + * + * @private + * @function Highcharts.Legend#renderTitle + */ + Legend.prototype.renderTitle = function () { + var options = this.options, padding = this.padding, titleOptions = options.title, titleHeight = 0, bBox; + if (titleOptions.text) { + if (!this.title) { + /** + * SVG element of the legend title. + * + * @readonly + * @name Highcharts.Legend#title + * @type {Highcharts.SVGElement} + */ + this.title = this.chart.renderer.label(titleOptions.text, padding - 3, padding - 4, null, null, null, options.useHTML, null, 'legend-title') + .attr({ zIndex: 1 }); + if (!this.chart.styledMode) { + this.title.css(titleOptions.style); + } + this.title.add(this.group); + } + // Set the max title width (#7253) + if (!titleOptions.width) { + this.title.css({ + width: this.maxLegendWidth + 'px' + }); + } + bBox = this.title.getBBox(); + titleHeight = bBox.height; + this.offsetWidth = bBox.width; // #1717 + this.contentGroup.attr({ translateY: titleHeight }); + } + this.titleHeight = titleHeight; + }; + /** + * Set the legend item text. + * + * @function Highcharts.Legend#setText + * @param {Highcharts.Point|Highcharts.Series} item + * The item for which to update the text in the legend. + */ + Legend.prototype.setText = function (item) { + var options = this.options; + item.legendItem.attr({ + text: options.labelFormat ? + format(options.labelFormat, item, this.chart) : + options.labelFormatter.call(item) + }); + }; + /** + * Render a single specific legend item. Called internally from the `render` + * function. + * + * @private + * @function Highcharts.Legend#renderItem + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + * The item to render. + */ + Legend.prototype.renderItem = function (item) { + var legend = this, chart = legend.chart, renderer = chart.renderer, options = legend.options, horizontal = options.layout === 'horizontal', symbolWidth = legend.symbolWidth, symbolPadding = options.symbolPadding, itemStyle = legend.itemStyle, itemHiddenStyle = legend.itemHiddenStyle, itemDistance = horizontal ? pick(options.itemDistance, 20) : 0, ltr = !options.rtl, bBox, li = item.legendItem, isSeries = !item.series, series = !isSeries && item.series.drawLegendSymbol ? + item.series : + item, seriesOptions = series.options, showCheckbox = legend.createCheckboxForItem && + seriesOptions && + seriesOptions.showCheckbox, + // full width minus text width + itemExtraWidth = symbolWidth + symbolPadding + + itemDistance + (showCheckbox ? 20 : 0), useHTML = options.useHTML, itemClassName = item.options.className; + if (!li) { // generate it once, later move it + // Generate the group box, a group to hold the symbol and text. Text + // is to be appended in Legend class. + item.legendGroup = renderer + .g('legend-item') + .addClass('highcharts-' + series.type + '-series ' + + 'highcharts-color-' + item.colorIndex + + (itemClassName ? ' ' + itemClassName : '') + + (isSeries ? + ' highcharts-series-' + item.index : + '')) + .attr({ zIndex: 1 }) + .add(legend.scrollGroup); + // Generate the list item text and add it to the group + item.legendItem = li = renderer.text('', ltr ? + symbolWidth + symbolPadding : + -symbolPadding, legend.baseline || 0, useHTML); + if (!chart.styledMode) { + // merge to prevent modifying original (#1021) + li.css(merge(item.visible ? + itemStyle : + itemHiddenStyle)); + } + li + .attr({ + align: ltr ? 'left' : 'right', + zIndex: 2 + }) + .add(item.legendGroup); + // Get the baseline for the first item - the font size is equal for + // all + if (!legend.baseline) { + legend.fontMetrics = renderer.fontMetrics(chart.styledMode ? 12 : itemStyle.fontSize, li); + legend.baseline = + legend.fontMetrics.f + 3 + legend.itemMarginTop; + li.attr('y', legend.baseline); + } + // Draw the legend symbol inside the group box + legend.symbolHeight = + options.symbolHeight || legend.fontMetrics.f; + series.drawLegendSymbol(legend, item); + if (legend.setItemEvents) { + legend.setItemEvents(item, li, useHTML); + } + } + // Add the HTML checkbox on top + if (showCheckbox && !item.checkbox && legend.createCheckboxForItem) { + legend.createCheckboxForItem(item); + } + // Colorize the items + legend.colorizeItem(item, item.visible); + // Take care of max width and text overflow (#6659) + if (chart.styledMode || !itemStyle.width) { + li.css({ + width: ((options.itemWidth || + legend.widthOption || + chart.spacingBox.width) - itemExtraWidth) + 'px' + }); + } + // Always update the text + legend.setText(item); + // calculate the positions for the next line + bBox = li.getBBox(); + item.itemWidth = item.checkboxOffset = + options.itemWidth || + item.legendItemWidth || + bBox.width + itemExtraWidth; + legend.maxItemWidth = Math.max(legend.maxItemWidth, item.itemWidth); + legend.totalItemWidth += item.itemWidth; + legend.itemHeight = item.itemHeight = Math.round(item.legendItemHeight || bBox.height || legend.symbolHeight); + }; + /** + * Get the position of the item in the layout. We now know the + * maxItemWidth from the previous loop. + * + * @private + * @function Highcharts.Legend#layoutItem + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + */ + Legend.prototype.layoutItem = function (item) { + var options = this.options, padding = this.padding, horizontal = options.layout === 'horizontal', itemHeight = item.itemHeight, itemMarginBottom = this.itemMarginBottom, itemMarginTop = this.itemMarginTop, itemDistance = horizontal ? pick(options.itemDistance, 20) : 0, maxLegendWidth = this.maxLegendWidth, itemWidth = (options.alignColumns && + this.totalItemWidth > maxLegendWidth) ? + this.maxItemWidth : + item.itemWidth; + // If the item exceeds the width, start a new line + if (horizontal && + this.itemX - padding + itemWidth > maxLegendWidth) { + this.itemX = padding; + if (this.lastLineHeight) { // Not for the first line (#10167) + this.itemY += (itemMarginTop + + this.lastLineHeight + + itemMarginBottom); + } + this.lastLineHeight = 0; // reset for next line (#915, #3976) + } + // Set the edge positions + this.lastItemY = itemMarginTop + this.itemY + itemMarginBottom; + this.lastLineHeight = Math.max(// #915 + itemHeight, this.lastLineHeight); + // cache the position of the newly generated or reordered items + item._legendItemPos = [this.itemX, this.itemY]; + // advance + if (horizontal) { + this.itemX += itemWidth; + } + else { + this.itemY += + itemMarginTop + itemHeight + itemMarginBottom; + this.lastLineHeight = itemHeight; + } + // the width of the widest item + this.offsetWidth = this.widthOption || Math.max((horizontal ? this.itemX - padding - (item.checkbox ? + // decrease by itemDistance only when no checkbox #4853 + 0 : + itemDistance) : itemWidth) + padding, this.offsetWidth); + }; + /** + * Get all items, which is one item per series for most series and one + * item per point for pie series and its derivatives. Fires the event + * `afterGetAllItems`. + * + * @private + * @function Highcharts.Legend#getAllItems + * @return {Array<(Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series)>} + * The current items in the legend. + * @fires Highcharts.Legend#event:afterGetAllItems + */ + Legend.prototype.getAllItems = function () { + var allItems = []; + this.chart.series.forEach(function (series) { + var seriesOptions = series && series.options; + // Handle showInLegend. If the series is linked to another series, + // defaults to false. + if (series && pick(seriesOptions.showInLegend, !defined(seriesOptions.linkedTo) ? void 0 : false, true)) { + // Use points or series for the legend item depending on + // legendType + allItems = allItems.concat(series.legendItems || + (seriesOptions.legendType === 'point' ? + series.data : + series)); + } + }); + fireEvent(this, 'afterGetAllItems', { allItems: allItems }); + return allItems; + }; + /** + * Get a short, three letter string reflecting the alignment and layout. + * + * @private + * @function Highcharts.Legend#getAlignment + * @return {string} + * The alignment, empty string if floating + */ + Legend.prototype.getAlignment = function () { + var options = this.options; + // Use the first letter of each alignment option in order to detect + // the side. (#4189 - use charAt(x) notation instead of [x] for IE7) + if (this.proximate) { + return options.align.charAt(0) + 'tv'; + } + return options.floating ? '' : (options.align.charAt(0) + + options.verticalAlign.charAt(0) + + options.layout.charAt(0)); + }; + /** + * Adjust the chart margins by reserving space for the legend on only one + * side of the chart. If the position is set to a corner, top or bottom is + * reserved for horizontal legends and left or right for vertical ones. + * + * @private + * @function Highcharts.Legend#adjustMargins + * @param {Array} margin + * @param {Array} spacing + */ + Legend.prototype.adjustMargins = function (margin, spacing) { + var chart = this.chart, options = this.options, alignment = this.getAlignment(); + if (alignment) { + ([ + /(lth|ct|rth)/, + /(rtv|rm|rbv)/, + /(rbh|cb|lbh)/, + /(lbv|lm|ltv)/ + ]).forEach(function (alignments, side) { + if (alignments.test(alignment) && !defined(margin[side])) { + // Now we have detected on which side of the chart we should + // reserve space for the legend + chart[marginNames[side]] = Math.max(chart[marginNames[side]], (chart.legend[(side + 1) % 2 ? 'legendHeight' : 'legendWidth'] + + [1, -1, -1, 1][side] * options[(side % 2) ? 'x' : 'y'] + + pick(options.margin, 12) + + spacing[side] + + (chart.titleOffset[side] || 0))); + } + }); + } + }; + /** + * @private + * @function Highcharts.Legend#proximatePositions + */ + Legend.prototype.proximatePositions = function () { + var chart = this.chart, boxes = [], alignLeft = this.options.align === 'left'; + this.allItems.forEach(function (item) { + var lastPoint, height, useFirstPoint = alignLeft, target, top; + if (item.yAxis && item.points) { + if (item.xAxis.options.reversed) { + useFirstPoint = !useFirstPoint; + } + lastPoint = find(useFirstPoint ? + item.points : + item.points.slice(0).reverse(), function (item) { + return isNumber(item.plotY); + }); + height = this.itemMarginTop + + item.legendItem.getBBox().height + + this.itemMarginBottom; + top = item.yAxis.top - chart.plotTop; + if (item.visible) { + target = lastPoint ? + lastPoint.plotY : + item.yAxis.height; + target += top - 0.3 * height; + } + else { + target = top + item.yAxis.height; + } + boxes.push({ + target: target, + size: height, + item: item + }); + } + }, this); + H.distribute(boxes, chart.plotHeight); + boxes.forEach(function (box) { + box.item._legendItemPos[1] = + chart.plotTop - chart.spacing[0] + box.pos; + }); + }; + /** + * Render the legend. This method can be called both before and after + * `chart.render`. If called after, it will only rearrange items instead + * of creating new ones. Called internally on initial render and after + * redraws. + * + * @private + * @function Highcharts.Legend#render + */ + Legend.prototype.render = function () { + var legend = this, chart = legend.chart, renderer = chart.renderer, legendGroup = legend.group, allItems, display, legendWidth, legendHeight, box = legend.box, options = legend.options, padding = legend.padding, allowedWidth; + legend.itemX = padding; + legend.itemY = legend.initialItemY; + legend.offsetWidth = 0; + legend.lastItemY = 0; + legend.widthOption = relativeLength(options.width, chart.spacingBox.width - padding); + // Compute how wide the legend is allowed to be + allowedWidth = + chart.spacingBox.width - 2 * padding - options.x; + if (['rm', 'lm'].indexOf(legend.getAlignment().substring(0, 2)) > -1) { + allowedWidth /= 2; + } + legend.maxLegendWidth = legend.widthOption || allowedWidth; + if (!legendGroup) { + /** + * SVG group of the legend. + * + * @readonly + * @name Highcharts.Legend#group + * @type {Highcharts.SVGElement} + */ + legend.group = legendGroup = renderer.g('legend') + .attr({ zIndex: 7 }) + .add(); + legend.contentGroup = renderer.g() + .attr({ zIndex: 1 }) // above background + .add(legendGroup); + legend.scrollGroup = renderer.g() + .add(legend.contentGroup); + } + legend.renderTitle(); + // add each series or point + allItems = legend.getAllItems(); + // sort by legendIndex + stableSort(allItems, function (a, b) { + return ((a.options && a.options.legendIndex) || 0) - + ((b.options && b.options.legendIndex) || 0); + }); + // reversed legend + if (options.reversed) { + allItems.reverse(); + } + /** + * All items for the legend, which is an array of series for most series + * and an array of points for pie series and its derivatives. + * + * @readonly + * @name Highcharts.Legend#allItems + * @type {Array<(Highcharts.Point|Highcharts.Series)>} + */ + legend.allItems = allItems; + legend.display = display = !!allItems.length; + // Render the items. First we run a loop to set the text and properties + // and read all the bounding boxes. The next loop computes the item + // positions based on the bounding boxes. + legend.lastLineHeight = 0; + legend.maxItemWidth = 0; + legend.totalItemWidth = 0; + legend.itemHeight = 0; + allItems.forEach(legend.renderItem, legend); + allItems.forEach(legend.layoutItem, legend); + // Get the box + legendWidth = (legend.widthOption || legend.offsetWidth) + padding; + legendHeight = legend.lastItemY + legend.lastLineHeight + + legend.titleHeight; + legendHeight = legend.handleOverflow(legendHeight); + legendHeight += padding; + // Draw the border and/or background + if (!box) { + /** + * SVG element of the legend box. + * + * @readonly + * @name Highcharts.Legend#box + * @type {Highcharts.SVGElement} + */ + legend.box = box = renderer.rect() + .addClass('highcharts-legend-box') + .attr({ + r: options.borderRadius + }) + .add(legendGroup); + box.isNew = true; + } + // Presentational + if (!chart.styledMode) { + box + .attr({ + stroke: options.borderColor, + 'stroke-width': options.borderWidth || 0, + fill: options.backgroundColor || 'none' + }) + .shadow(options.shadow); + } + if (legendWidth > 0 && legendHeight > 0) { + box[box.isNew ? 'attr' : 'animate'](box.crisp.call({}, { + x: 0, + y: 0, + width: legendWidth, + height: legendHeight + }, box.strokeWidth())); + box.isNew = false; + } + // hide the border if no items + box[display ? 'show' : 'hide'](); + // Open for responsiveness + if (chart.styledMode && legendGroup.getStyle('display') === 'none') { + legendWidth = legendHeight = 0; + } + legend.legendWidth = legendWidth; + legend.legendHeight = legendHeight; + if (display) { + legend.align(); + } + if (!this.proximate) { + this.positionItems(); + } + fireEvent(this, 'afterRender'); + }; + /** + * Align the legend to chart's box. + * + * @private + * @function Highcharts.align + * @param {Highcharts.BBoxObject} alignTo + * @return {void} + */ + Legend.prototype.align = function (alignTo) { + if (alignTo === void 0) { alignTo = this.chart.spacingBox; } + var chart = this.chart, options = this.options; + // If aligning to the top and the layout is horizontal, adjust for + // the title (#7428) + var y = alignTo.y; + if (/(lth|ct|rth)/.test(this.getAlignment()) && + chart.titleOffset[0] > 0) { + y += chart.titleOffset[0]; + } + else if (/(lbh|cb|rbh)/.test(this.getAlignment()) && + chart.titleOffset[2] > 0) { + y -= chart.titleOffset[2]; + } + if (y !== alignTo.y) { + alignTo = merge(alignTo, { y: y }); + } + this.group.align(merge(options, { + width: this.legendWidth, + height: this.legendHeight, + verticalAlign: this.proximate ? 'top' : options.verticalAlign + }), true, alignTo); + }; + /** + * Set up the overflow handling by adding navigation with up and down arrows + * below the legend. + * + * @private + * @function Highcharts.Legend#handleOverflow + * @param {number} legendHeight + * @return {number} + */ + Legend.prototype.handleOverflow = function (legendHeight) { + var legend = this, chart = this.chart, renderer = chart.renderer, options = this.options, optionsY = options.y, alignTop = options.verticalAlign === 'top', padding = this.padding, spaceHeight = (chart.spacingBox.height + + (alignTop ? -optionsY : optionsY) - padding), maxHeight = options.maxHeight, clipHeight, clipRect = this.clipRect, navOptions = options.navigation, animation = pick(navOptions.animation, true), arrowSize = navOptions.arrowSize || 12, nav = this.nav, pages = this.pages, lastY, allItems = this.allItems, clipToHeight = function (height) { + if (typeof height === 'number') { + clipRect.attr({ + height: height + }); + } + else if (clipRect) { // Reset (#5912) + legend.clipRect = clipRect.destroy(); + legend.contentGroup.clip(); + } + // useHTML + if (legend.contentGroup.div) { + legend.contentGroup.div.style.clip = height ? + 'rect(' + padding + 'px,9999px,' + + (padding + height) + 'px,0)' : + 'auto'; + } + }, addTracker = function (key) { + legend[key] = renderer + .circle(0, 0, arrowSize * 1.3) + .translate(arrowSize / 2, arrowSize / 2) + .add(nav); + if (!chart.styledMode) { + legend[key].attr('fill', 'rgba(0,0,0,0.0001)'); + } + return legend[key]; + }; + // Adjust the height + if (options.layout === 'horizontal' && + options.verticalAlign !== 'middle' && + !options.floating) { + spaceHeight /= 2; + } + if (maxHeight) { + spaceHeight = Math.min(spaceHeight, maxHeight); + } + // Reset the legend height and adjust the clipping rectangle + pages.length = 0; + if (legendHeight > spaceHeight && + navOptions.enabled !== false) { + this.clipHeight = clipHeight = + Math.max(spaceHeight - 20 - this.titleHeight - padding, 0); + this.currentPage = pick(this.currentPage, 1); + this.fullHeight = legendHeight; + // Fill pages with Y positions so that the top of each a legend item + // defines the scroll top for each page (#2098) + allItems.forEach(function (item, i) { + var y = item._legendItemPos[1], h = Math.round(item.legendItem.getBBox().height), len = pages.length; + if (!len || (y - pages[len - 1] > clipHeight && + (lastY || y) !== pages[len - 1])) { + pages.push(lastY || y); + len++; + } + // Keep track of which page each item is on + item.pageIx = len - 1; + if (lastY) { + allItems[i - 1].pageIx = len - 1; + } + if (i === allItems.length - 1 && + y + h - pages[len - 1] > clipHeight && + y !== lastY // #2617 + ) { + pages.push(y); + item.pageIx = len; + } + if (y !== lastY) { + lastY = y; + } + }); + // Only apply clipping if needed. Clipping causes blurred legend in + // PDF export (#1787) + if (!clipRect) { + clipRect = legend.clipRect = + renderer.clipRect(0, padding, 9999, 0); + legend.contentGroup.clip(clipRect); + } + clipToHeight(clipHeight); + // Add navigation elements + if (!nav) { + this.nav = nav = renderer.g() + .attr({ zIndex: 1 }) + .add(this.group); + this.up = renderer + .symbol('triangle', 0, 0, arrowSize, arrowSize) + .add(nav); + addTracker('upTracker') + .on('click', function () { + legend.scroll(-1, animation); + }); + this.pager = renderer.text('', 15, 10) + .addClass('highcharts-legend-navigation'); + if (!chart.styledMode) { + this.pager.css(navOptions.style); + } + this.pager.add(nav); + this.down = renderer + .symbol('triangle-down', 0, 0, arrowSize, arrowSize) + .add(nav); + addTracker('downTracker') + .on('click', function () { + legend.scroll(1, animation); + }); + } + // Set initial position + legend.scroll(0); + legendHeight = spaceHeight; + // Reset + } + else if (nav) { + clipToHeight(); + this.nav = nav.destroy(); // #6322 + this.scrollGroup.attr({ + translateY: 1 + }); + this.clipHeight = 0; // #1379 + } + return legendHeight; + }; + /** + * Scroll the legend by a number of pages. + * + * @private + * @function Highcharts.Legend#scroll + * + * @param {number} scrollBy + * The number of pages to scroll. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * Whether and how to apply animation. + * + * @return {void} + */ + Legend.prototype.scroll = function (scrollBy, animation) { + var _this = this; + var chart = this.chart, pages = this.pages, pageCount = pages.length, currentPage = this.currentPage + scrollBy, clipHeight = this.clipHeight, navOptions = this.options.navigation, pager = this.pager, padding = this.padding; + // When resizing while looking at the last page + if (currentPage > pageCount) { + currentPage = pageCount; + } + if (currentPage > 0) { + if (typeof animation !== 'undefined') { + setAnimation(animation, chart); + } + this.nav.attr({ + translateX: padding, + translateY: clipHeight + this.padding + 7 + this.titleHeight, + visibility: 'visible' + }); + [this.up, this.upTracker].forEach(function (elem) { + elem.attr({ + 'class': currentPage === 1 ? + 'highcharts-legend-nav-inactive' : + 'highcharts-legend-nav-active' + }); + }); + pager.attr({ + text: currentPage + '/' + pageCount + }); + [this.down, this.downTracker].forEach(function (elem) { + elem.attr({ + // adjust to text width + x: 18 + this.pager.getBBox().width, + 'class': currentPage === pageCount ? + 'highcharts-legend-nav-inactive' : + 'highcharts-legend-nav-active' + }); + }, this); + if (!chart.styledMode) { + this.up + .attr({ + fill: currentPage === 1 ? + navOptions.inactiveColor : + navOptions.activeColor + }); + this.upTracker + .css({ + cursor: currentPage === 1 ? 'default' : 'pointer' + }); + this.down + .attr({ + fill: currentPage === pageCount ? + navOptions.inactiveColor : + navOptions.activeColor + }); + this.downTracker + .css({ + cursor: currentPage === pageCount ? + 'default' : + 'pointer' + }); + } + this.scrollOffset = -pages[currentPage - 1] + this.initialItemY; + this.scrollGroup.animate({ + translateY: this.scrollOffset + }); + this.currentPage = currentPage; + this.positionCheckboxes(); + // Fire event after scroll animation is complete + var animOptions = animObject(pick(animation, chart.renderer.globalAnimation, true)); + syncTimeout(function () { + fireEvent(_this, 'afterScroll', { currentPage: currentPage }); + }, animOptions.duration || 0); + } + }; + return Legend; + }()); + // Workaround for #2030, horizontal legend items not displaying in IE11 Preview, + // and for #2580, a similar drawing flaw in Firefox 26. + // Explore if there's a general cause for this. The problem may be related + // to nested group elements, as the legend item texts are within 4 group + // elements. + if (/Trident\/7\.0/.test(win.navigator && win.navigator.userAgent) || + isFirefox) { + wrap(Legend.prototype, 'positionItem', function (proceed, item) { + var legend = this, + // If chart destroyed in sync, this is undefined (#2030) + runPositionItem = function () { + if (item._legendItemPos) { + proceed.call(legend, item); + } + }; + // Do it now, for export and to get checkbox placement + runPositionItem(); + // Do it after to work around the core issue + if (!legend.bubbleLegend) { + setTimeout(runPositionItem); + } + }); + } + H.Legend = Legend; + + return H.Legend; + }); + _registerModule(_modules, 'parts/Chart.js', [_modules['parts/Globals.js'], _modules['parts/Legend.js'], _modules['parts/MSPointer.js'], _modules['parts/Pointer.js'], _modules['parts/Time.js'], _modules['parts/Utilities.js']], function (H, Legend, MSPointer, Pointer, Time, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Callback for chart constructors. + * + * @callback Highcharts.ChartCallbackFunction + * + * @param {Highcharts.Chart} chart + * Created chart. + */ + /** + * Format a number and return a string based on input settings. + * + * @callback Highcharts.NumberFormatterCallbackFunction + * + * @param {number} number + * The input number to format. + * + * @param {number} decimals + * The amount of decimals. A value of -1 preserves the amount in the + * input number. + * + * @param {string} [decimalPoint] + * The decimal point, defaults to the one given in the lang options, or + * a dot. + * + * @param {string} [thousandsSep] + * The thousands separator, defaults to the one given in the lang + * options, or a space character. + * + * @return {string} The formatted number. + */ + /** + * The chart title. The title has an `update` method that allows modifying the + * options directly or indirectly via `chart.update`. + * + * @interface Highcharts.TitleObject + * @extends Highcharts.SVGElement + */ /** + * Modify options for the title. + * + * @function Highcharts.TitleObject#update + * + * @param {Highcharts.TitleOptions} titleOptions + * Options to modify. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the title is altered. If doing more + * operations on the chart, it is a good idea to set redraw to false and + * call {@link Chart#redraw} after. + */ + /** + * The chart subtitle. The subtitle has an `update` method that + * allows modifying the options directly or indirectly via + * `chart.update`. + * + * @interface Highcharts.SubtitleObject + * @extends Highcharts.SVGElement + */ /** + * Modify options for the subtitle. + * + * @function Highcharts.SubtitleObject#update + * + * @param {Highcharts.SubtitleOptions} subtitleOptions + * Options to modify. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the subtitle is altered. If doing + * more operations on the chart, it is a good idea to set redraw to false + * and call {@link Chart#redraw} after. + */ + /** + * The chart caption. The caption has an `update` method that + * allows modifying the options directly or indirectly via + * `chart.update`. + * + * @interface Highcharts.CaptionObject + * @extends Highcharts.SVGElement + */ /** + * Modify options for the caption. + * + * @function Highcharts.CaptionObject#update + * + * @param {Highcharts.CaptionOptions} captionOptions + * Options to modify. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the caption is altered. If doing + * more operations on the chart, it is a good idea to set redraw to false + * and call {@link Chart#redraw} after. + */ + var addEvent = U.addEvent, animate = U.animate, animObject = U.animObject, attr = U.attr, createElement = U.createElement, css = U.css, defined = U.defined, discardElement = U.discardElement, erase = U.erase, error = U.error, extend = U.extend, find = U.find, fireEvent = U.fireEvent, getStyle = U.getStyle, isArray = U.isArray, isFunction = U.isFunction, isNumber = U.isNumber, isObject = U.isObject, isString = U.isString, merge = U.merge, numberFormat = U.numberFormat, objectEach = U.objectEach, pick = U.pick, pInt = U.pInt, relativeLength = U.relativeLength, removeEvent = U.removeEvent, setAnimation = U.setAnimation, splat = U.splat, syncTimeout = U.syncTimeout, uniqueKey = U.uniqueKey; + var doc = H.doc, Axis = H.Axis, // @todo add as requirement + defaultOptions = H.defaultOptions, charts = H.charts, marginNames = H.marginNames, seriesTypes = H.seriesTypes, win = H.win; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The Chart class. The recommended constructor is {@link Highcharts#chart}. + * + * @example + * var chart = Highcharts.chart('container', { + * title: { + * text: 'My chart' + * }, + * series: [{ + * data: [1, 3, 2, 4] + * }] + * }) + * + * @class + * @name Highcharts.Chart + * + * @param {string|Highcharts.HTMLDOMElement} [renderTo] + * The DOM element to render to, or its id. + * + * @param {Highcharts.Options} options + * The chart options structure. + * + * @param {Highcharts.ChartCallbackFunction} [callback] + * Function to run when the chart has loaded and and all external images + * are loaded. Defining a + * [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load) + * handler is equivalent. + */ + var Chart = H.Chart = function () { + this.getArgs.apply(this, arguments); + }; + /** + * Factory function for basic charts. + * + * @example + * // Render a chart in to div#container + * var chart = Highcharts.chart('container', { + * title: { + * text: 'My chart' + * }, + * series: [{ + * data: [1, 3, 2, 4] + * }] + * }); + * + * @function Highcharts.chart + * + * @param {string|Highcharts.HTMLDOMElement} [renderTo] + * The DOM element to render to, or its id. + * + * @param {Highcharts.Options} options + * The chart options structure. + * + * @param {Highcharts.ChartCallbackFunction} [callback] + * Function to run when the chart has loaded and and all external images + * are loaded. Defining a + * [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load) + * handler is equivalent. + * + * @return {Highcharts.Chart} + * Returns the Chart object. + */ + H.chart = function (a, b, c) { + return new Chart(a, b, c); + }; + extend(Chart.prototype, /** @lends Highcharts.Chart.prototype */ { + // Hook for adding callbacks in modules + callbacks: [], + /** + * Handle the arguments passed to the constructor. + * + * @private + * @function Highcharts.Chart#getArgs + * + * @param {...Array<*>} arguments + * All arguments for the constructor. + * + * @return {Array<*>} + * Passed arguments without renderTo. + * + * @fires Highcharts.Chart#event:init + * @fires Highcharts.Chart#event:afterInit + */ + getArgs: function () { + var args = [].slice.call(arguments); + // Remove the optional first argument, renderTo, and + // set it on this. + if (isString(args[0]) || args[0].nodeName) { + this.renderTo = args.shift(); + } + this.init(args[0], args[1]); + }, + /** + * Overridable function that initializes the chart. The constructor's + * arguments are passed on directly. + * + * @function Highcharts.Chart#init + * + * @param {Highcharts.Options} userOptions + * Custom options. + * + * @param {Function} [callback] + * Function to run when the chart has loaded and and all external + * images are loaded. + * + * @return {void} + * + * @fires Highcharts.Chart#event:init + * @fires Highcharts.Chart#event:afterInit + */ + init: function (userOptions, callback) { + // Handle regular options + var options, + // skip merging data points to increase performance + seriesOptions = userOptions.series, userPlotOptions = userOptions.plotOptions || {}; + // Fire the event with a default function + fireEvent(this, 'init', { args: arguments }, function () { + userOptions.series = null; + options = merge(defaultOptions, userOptions); // do the merge + var optionsChart = options.chart || {}; + // Override (by copy of user options) or clear tooltip options + // in chart.options.plotOptions (#6218) + objectEach(options.plotOptions, function (typeOptions, type) { + if (isObject(typeOptions)) { // #8766 + typeOptions.tooltip = (userPlotOptions[type] && // override by copy: + merge(userPlotOptions[type].tooltip)) || void 0; // or clear + } + }); + // User options have higher priority than default options + // (#6218). In case of exporting: path is changed + options.tooltip.userOptions = (userOptions.chart && + userOptions.chart.forExport && + userOptions.tooltip.userOptions) || userOptions.tooltip; + // set back the series data + options.series = userOptions.series = seriesOptions; + /** + * The original options given to the constructor or a chart factory + * like {@link Highcharts.chart} and {@link Highcharts.stockChart}. + * + * @name Highcharts.Chart#userOptions + * @type {Highcharts.Options} + */ + this.userOptions = userOptions; + var chartEvents = optionsChart.events; + this.margin = []; + this.spacing = []; + // Pixel data bounds for touch zoom + this.bounds = { h: {}, v: {} }; + // An array of functions that returns labels that should be + // considered for anti-collision + this.labelCollectors = []; + this.callback = callback; + this.isResizing = 0; + /** + * The options structure for the chart after merging + * {@link #defaultOptions} and {@link #userOptions}. It contains + * members for the sub elements like series, legend, tooltip etc. + * + * @name Highcharts.Chart#options + * @type {Highcharts.Options} + */ + this.options = options; + /** + * All the axes in the chart. + * + * @see Highcharts.Chart.xAxis + * @see Highcharts.Chart.yAxis + * + * @name Highcharts.Chart#axes + * @type {Array} + */ + this.axes = []; + /** + * All the current series in the chart. + * + * @name Highcharts.Chart#series + * @type {Array} + */ + this.series = []; + /** + * The `Time` object associated with the chart. Since v6.0.5, + * time settings can be applied individually for each chart. If + * no individual settings apply, the `Time` object is shared by + * all instances. + * + * @name Highcharts.Chart#time + * @type {Highcharts.Time} + */ + this.time = + userOptions.time && Object.keys(userOptions.time).length ? + new Time(userOptions.time) : + H.time; + /** + * Callback function to override the default function that formats + * all the numbers in the chart. Returns a string with the formatted + * number. + * + * @name Highcharts.Chart#numberFormatter + * @type {Highcharts.NumberFormatterCallbackFunction} + */ + this.numberFormatter = optionsChart.numberFormatter || numberFormat; + /** + * Whether the chart is in styled mode, meaning all presentatinoal + * attributes are avoided. + * + * @name Highcharts.Chart#styledMode + * @type {boolean} + */ + this.styledMode = optionsChart.styledMode; + this.hasCartesianSeries = optionsChart.showAxes; + var chart = this; + /** + * Index position of the chart in the {@link Highcharts#charts} + * property. + * + * @name Highcharts.Chart#index + * @type {number} + * @readonly + */ + chart.index = charts.length; // Add the chart to the global lookup + charts.push(chart); + H.chartCount++; + // Chart event handlers + if (chartEvents) { + objectEach(chartEvents, function (event, eventType) { + if (isFunction(event)) { + addEvent(chart, eventType, event); + } + }); + } + /** + * A collection of the X axes in the chart. + * + * @name Highcharts.Chart#xAxis + * @type {Array} + */ + chart.xAxis = []; + /** + * A collection of the Y axes in the chart. + * + * @name Highcharts.Chart#yAxis + * @type {Array} + * + * @todo + * Make events official: Fire the event `afterInit`. + */ + chart.yAxis = []; + chart.pointCount = chart.colorCounter = chart.symbolCounter = 0; + // Fire after init but before first render, before axes and series + // have been initialized. + fireEvent(chart, 'afterInit'); + chart.firstRender(); + }); + }, + /** + * Internal function to unitialize an individual series. + * + * @private + * @function Highcharts.Chart#initSeries + * + * @param {Highcharts.SeriesOptions} options + * + * @return {Highcharts.Series} + */ + initSeries: function (options) { + var chart = this, optionsChart = chart.options.chart, type = (options.type || + optionsChart.type || + optionsChart.defaultSeriesType), series, Constr = seriesTypes[type]; + // No such series type + if (!Constr) { + error(17, true, chart, { missingModuleFor: type }); + } + series = new Constr(); + series.init(this, options); + return series; + }, + /** + * Internal function to set data for all series with enabled sorting. + * + * @private + * @function Highcharts.Chart#setSeriesData + * + * @param {Highcharts.SeriesOptions} options + * + * @return {void} + */ + setSeriesData: function () { + this.getSeriesOrderByLinks().forEach(function (series) { + // We need to set data for series with sorting after series init + if (!series.points && !series.data && series.enabledDataSorting) { + series.setData(series.options.data, false); + } + }); + }, + /** + * Sort and return chart series in order depending on the number of linked + * series. + * + * @private + * @function Highcharts.Series#getSeriesOrderByLinks + * + * @return {Array} + */ + getSeriesOrderByLinks: function () { + return this.series.concat().sort(function (a, b) { + if (a.linkedSeries.length || b.linkedSeries.length) { + return b.linkedSeries.length - a.linkedSeries.length; + } + return 0; + }); + }, + /** + * Order all series above a given index. When series are added and ordered + * by configuration, only the last series is handled (#248, #1123, #2456, + * #6112). This function is called on series initialization and destroy. + * + * @private + * @function Highcharts.Series#orderSeries + * @param {number} [fromIndex] + * If this is given, only the series above this index are handled. + * @return {void} + */ + orderSeries: function (fromIndex) { + var series = this.series, i = fromIndex || 0; + for (; i < series.length; i++) { + if (series[i]) { + /** + * Contains the series' index in the `Chart.series` array. + * + * @name Highcharts.Series#index + * @type {number} + * @readonly + */ + series[i].index = i; + series[i].name = series[i].getName(); + } + } + }, + /** + * Check whether a given point is within the plot area. + * + * @function Highcharts.Chart#isInsidePlot + * + * @param {number} plotX + * Pixel x relative to the plot area. + * + * @param {number} plotY + * Pixel y relative to the plot area. + * + * @param {boolean} [inverted] + * Whether the chart is inverted. + * + * @return {boolean} + * Returns true if the given point is inside the plot area. + */ + isInsidePlot: function (plotX, plotY, inverted) { + var x = inverted ? plotY : plotX, y = inverted ? plotX : plotY, e = { + x: x, + y: y, + isInsidePlot: x >= 0 && + x <= this.plotWidth && + y >= 0 && + y <= this.plotHeight + }; + fireEvent(this, 'afterIsInsidePlot', e); + return e.isInsidePlot; + }, + /** + * Redraw the chart after changes have been done to the data, axis extremes + * chart size or chart elements. All methods for updating axes, series or + * points have a parameter for redrawing the chart. This is `true` by + * default. But in many cases you want to do more than one operation on the + * chart before redrawing, for example add a number of points. In those + * cases it is a waste of resources to redraw the chart for each new point + * added. So you add the points and call `chart.redraw()` after. + * + * @function Highcharts.Chart#redraw + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * If or how to apply animation to the redraw. + * + * @return {void} + * + * @fires Highcharts.Chart#event:afterSetExtremes + * @fires Highcharts.Chart#event:beforeRedraw + * @fires Highcharts.Chart#event:predraw + * @fires Highcharts.Chart#event:redraw + * @fires Highcharts.Chart#event:render + * @fires Highcharts.Chart#event:updatedData + */ + redraw: function (animation) { + fireEvent(this, 'beforeRedraw'); + var chart = this, axes = chart.axes, series = chart.series, pointer = chart.pointer, legend = chart.legend, legendUserOptions = chart.userOptions.legend, redrawLegend = chart.isDirtyLegend, hasStackedSeries, hasDirtyStacks, hasCartesianSeries = chart.hasCartesianSeries, isDirtyBox = chart.isDirtyBox, i, serie, renderer = chart.renderer, isHiddenChart = renderer.isHidden(), afterRedraw = []; + // Handle responsive rules, not only on resize (#6130) + if (chart.setResponsive) { + chart.setResponsive(false); + } + // Set the global animation. When chart.hasRendered is not true, the + // redraw call comes from a responsive rule and animation should not + // occur. + setAnimation(chart.hasRendered ? animation : false, chart); + if (isHiddenChart) { + chart.temporaryDisplay(); + } + // Adjust title layout (reflow multiline text) + chart.layOutTitles(); + // link stacked series + i = series.length; + while (i--) { + serie = series[i]; + if (serie.options.stacking) { + hasStackedSeries = true; + if (serie.isDirty) { + hasDirtyStacks = true; + break; + } + } + } + if (hasDirtyStacks) { // mark others as dirty + i = series.length; + while (i--) { + serie = series[i]; + if (serie.options.stacking) { + serie.isDirty = true; + } + } + } + // Handle updated data in the series + series.forEach(function (serie) { + if (serie.isDirty) { + if (serie.options.legendType === 'point') { + if (serie.updateTotals) { + serie.updateTotals(); + } + redrawLegend = true; + } + else if (legendUserOptions && + (legendUserOptions.labelFormatter || + legendUserOptions.labelFormat)) { + redrawLegend = true; // #2165 + } + } + if (serie.isDirtyData) { + fireEvent(serie, 'updatedData'); + } + }); + // handle added or removed series + if (redrawLegend && legend && legend.options.enabled) { + // draw legend graphics + legend.render(); + chart.isDirtyLegend = false; + } + // reset stacks + if (hasStackedSeries) { + chart.getStacks(); + } + if (hasCartesianSeries) { + // set axes scales + axes.forEach(function (axis) { + axis.updateNames(); + axis.setScale(); + }); + } + chart.getMargins(); // #3098 + if (hasCartesianSeries) { + // If one axis is dirty, all axes must be redrawn (#792, #2169) + axes.forEach(function (axis) { + if (axis.isDirty) { + isDirtyBox = true; + } + }); + // redraw axes + axes.forEach(function (axis) { + // Fire 'afterSetExtremes' only if extremes are set + var key = axis.min + ',' + axis.max; + if (axis.extKey !== key) { // #821, #4452 + axis.extKey = key; + // prevent a recursive call to chart.redraw() (#1119) + afterRedraw.push(function () { + fireEvent(axis, 'afterSetExtremes', extend(axis.eventArgs, axis.getExtremes())); // #747, #751 + delete axis.eventArgs; + }); + } + if (isDirtyBox || hasStackedSeries) { + axis.redraw(); + } + }); + } + // the plot areas size has changed + if (isDirtyBox) { + chart.drawChartBox(); + } + // Fire an event before redrawing series, used by the boost module to + // clear previous series renderings. + fireEvent(chart, 'predraw'); + // redraw affected series + series.forEach(function (serie) { + if ((isDirtyBox || serie.isDirty) && serie.visible) { + serie.redraw(); + } + // Set it here, otherwise we will have unlimited 'updatedData' calls + // for a hidden series after setData(). Fixes #6012 + serie.isDirtyData = false; + }); + // move tooltip or reset + if (pointer) { + pointer.reset(true); + } + // redraw if canvas + renderer.draw(); + // Fire the events + fireEvent(chart, 'redraw'); + fireEvent(chart, 'render'); + if (isHiddenChart) { + chart.temporaryDisplay(true); + } + // Fire callbacks that are put on hold until after the redraw + afterRedraw.forEach(function (callback) { + callback.call(); + }); + }, + /** + * Get an axis, series or point object by `id` as given in the configuration + * options. Returns `undefined` if no item is found. + * + * @sample highcharts/plotoptions/series-id/ + * Get series by id + * + * @function Highcharts.Chart#get + * + * @param {string} id + * The id as given in the configuration options. + * + * @return {Highcharts.Axis|Highcharts.Series|Highcharts.Point|undefined} + * The retrieved item. + */ + get: function (id) { + var ret, series = this.series, i; + /** + * @private + * @param {Highcharts.Axis|Highcharts.Series} item + * @return {boolean} + */ + function itemById(item) { + return (item.id === id || + (item.options && item.options.id === id)); + } + ret = + // Search axes + find(this.axes, itemById) || + // Search series + find(this.series, itemById); + // Search points + for (i = 0; !ret && i < series.length; i++) { + ret = find(series[i].points || [], itemById); + } + return ret; + }, + /** + * Create the Axis instances based on the config options. + * + * @private + * @function Highcharts.Chart#getAxes + * + * @return {void} + * + * @fires Highcharts.Chart#event:afterGetAxes + * @fires Highcharts.Chart#event:getAxes + */ + getAxes: function () { + var chart = this, options = this.options, xAxisOptions = options.xAxis = splat(options.xAxis || {}), yAxisOptions = options.yAxis = splat(options.yAxis || {}), optionsArray; + fireEvent(this, 'getAxes'); + // make sure the options are arrays and add some members + xAxisOptions.forEach(function (axis, i) { + axis.index = i; + axis.isX = true; + }); + yAxisOptions.forEach(function (axis, i) { + axis.index = i; + }); + // concatenate all axis options into one array + optionsArray = xAxisOptions.concat(yAxisOptions); + optionsArray.forEach(function (axisOptions) { + new Axis(chart, axisOptions); // eslint-disable-line no-new + }); + fireEvent(this, 'afterGetAxes'); + }, + /** + * Returns an array of all currently selected points in the chart. Points + * can be selected by clicking or programmatically by the + * {@link Highcharts.Point#select} + * function. + * + * @sample highcharts/plotoptions/series-allowpointselect-line/ + * Get selected points + * + * @function Highcharts.Chart#getSelectedPoints + * + * @return {Array} + * The currently selected points. + */ + getSelectedPoints: function () { + var points = []; + this.series.forEach(function (serie) { + // For one-to-one points inspect series.data in order to retrieve + // points outside the visible range (#6445). For grouped data, + // inspect the generated series.points. + points = points.concat(serie.getPointsCollection().filter(function (point) { + return pick(point.selectedStaging, point.selected); + })); + }); + return points; + }, + /** + * Returns an array of all currently selected series in the chart. Series + * can be selected either programmatically by the + * {@link Highcharts.Series#select} + * function or by checking the checkbox next to the legend item if + * [series.showCheckBox](https://api.highcharts.com/highcharts/plotOptions.series.showCheckbox) + * is true. + * + * @sample highcharts/members/chart-getselectedseries/ + * Get selected series + * + * @function Highcharts.Chart#getSelectedSeries + * + * @return {Array} + * The currently selected series. + */ + getSelectedSeries: function () { + return this.series.filter(function (serie) { + return serie.selected; + }); + }, + /** + * Set a new title or subtitle for the chart. + * + * @sample highcharts/members/chart-settitle/ + * Set title text and styles + * + * @function Highcharts.Chart#setTitle + * + * @param {Highcharts.TitleOptions} [titleOptions] + * New title options. The title text itself is set by the + * `titleOptions.text` property. + * + * @param {Highcharts.SubtitleOptions} [subtitleOptions] + * New subtitle options. The subtitle text itself is set by the + * `subtitleOptions.text` property. + * + * @param {boolean} [redraw] + * Whether to redraw the chart or wait for a later call to + * `chart.redraw()`. + * + * @return {void} + */ + setTitle: function (titleOptions, subtitleOptions, redraw) { + this.applyDescription('title', titleOptions); + this.applyDescription('subtitle', subtitleOptions); + // The initial call also adds the caption. On update, chart.update will + // relay to Chart.setCaption. + this.applyDescription('caption', void 0); + this.layOutTitles(redraw); + }, + /** + * Apply a title, subtitle or caption for the chart + * + * @private + * @function Highcharts.Chart#applyDescription + * + * @param name {string} + * Either title, subtitle or caption + * @param {Highcharts.TitleOptions|Highcharts.SubtitleOptions|Highcharts.CaptionOptions|undefined} explicitOptions + * The options to set, will be merged with default options. + * + * @return {void} + */ + applyDescription: function (name, explicitOptions) { + var chart = this; + // Default style + var style = name === 'title' ? { + color: '#333333', + fontSize: this.options.isStock ? '16px' : '18px' // #2944 + } : { + color: '#666666' + }; + // Merge default options with explicit options + var options = this.options[name] = merge( + // Default styles + (!this.styledMode && { style: style }), this.options[name], explicitOptions); + var elem = this[name]; + if (elem && explicitOptions) { + this[name] = elem = elem.destroy(); // remove old + } + if (options && !elem) { + elem = this.renderer.text(options.text, 0, 0, options.useHTML) + .attr({ + align: options.align, + 'class': 'highcharts-' + name, + zIndex: options.zIndex || 4 + }) + .add(); + // Update methods, shortcut to Chart.setTitle, Chart.setSubtitle and + // Chart.setCaption + elem.update = function (updateOptions) { + var fn = { + title: 'setTitle', + subtitle: 'setSubtitle', + caption: 'setCaption' + }[name]; + chart[fn](updateOptions); + }; + // Presentational + if (!this.styledMode) { + elem.css(options.style); + } + /** + * The chart title. The title has an `update` method that allows + * modifying the options directly or indirectly via + * `chart.update`. + * + * @sample highcharts/members/title-update/ + * Updating titles + * + * @name Highcharts.Chart#title + * @type {Highcharts.TitleObject} + */ + /** + * The chart subtitle. The subtitle has an `update` method that + * allows modifying the options directly or indirectly via + * `chart.update`. + * + * @name Highcharts.Chart#subtitle + * @type {Highcharts.SubtitleObject} + */ + this[name] = elem; + } + }, + /** + * Internal function to lay out the chart title, subtitle and caption, and + * cache the full offset height for use in `getMargins`. The result is + * stored in `this.titleOffset`. + * + * @private + * @function Highcharts.Chart#layOutTitles + * + * @param {boolean} [redraw=true] + * + * @return {void} + * + * @fires Highcharts.Chart#event:afterLayOutTitles + */ + layOutTitles: function (redraw) { + var titleOffset = [0, 0, 0], requiresDirtyBox, renderer = this.renderer, spacingBox = this.spacingBox; + // Lay out the title and the subtitle respectively + ['title', 'subtitle', 'caption'].forEach(function (key) { + var title = this[key], titleOptions = this.options[key], verticalAlign = titleOptions.verticalAlign || 'top', offset = key === 'title' ? -3 : + // Floating subtitle (#6574) + verticalAlign === 'top' ? titleOffset[0] + 2 : 0, titleSize, height; + if (title) { + if (!this.styledMode) { + titleSize = titleOptions.style.fontSize; + } + titleSize = renderer.fontMetrics(titleSize, title).b; + title + .css({ + width: (titleOptions.width || + spacingBox.width + (titleOptions.widthAdjust || 0)) + 'px' + }); + // Skip the cache for HTML (#3481, #11666) + height = Math.round(title.getBBox(titleOptions.useHTML).height); + title.align(extend({ + y: verticalAlign === 'bottom' ? + titleSize : + offset + titleSize, + height: height + }, titleOptions), false, 'spacingBox'); + if (!titleOptions.floating) { + if (verticalAlign === 'top') { + titleOffset[0] = Math.ceil(titleOffset[0] + + height); + } + else if (verticalAlign === 'bottom') { + titleOffset[2] = Math.ceil(titleOffset[2] + + height); + } + } + } + }, this); + // Handle title.margin and caption.margin + if (titleOffset[0] && + (this.options.title.verticalAlign || 'top') === 'top') { + titleOffset[0] += this.options.title.margin; + } + if (titleOffset[2] && + this.options.caption.verticalAlign === 'bottom') { + titleOffset[2] += this.options.caption.margin; + } + requiresDirtyBox = (!this.titleOffset || + this.titleOffset.join(',') !== titleOffset.join(',')); + // Used in getMargins + this.titleOffset = titleOffset; + fireEvent(this, 'afterLayOutTitles'); + if (!this.isDirtyBox && requiresDirtyBox) { + this.isDirtyBox = this.isDirtyLegend = requiresDirtyBox; + // Redraw if necessary (#2719, #2744) + if (this.hasRendered && pick(redraw, true) && this.isDirtyBox) { + this.redraw(); + } + } + }, + /** + * Internal function to get the chart width and height according to options + * and container size. Sets {@link Chart.chartWidth} and + * {@link Chart.chartHeight}. + * + * @private + * @function Highcharts.Chart#getChartSize + * + * @return {void} + */ + getChartSize: function () { + var chart = this, optionsChart = chart.options.chart, widthOption = optionsChart.width, heightOption = optionsChart.height, renderTo = chart.renderTo; + // Get inner width and height + if (!defined(widthOption)) { + chart.containerWidth = getStyle(renderTo, 'width'); + } + if (!defined(heightOption)) { + chart.containerHeight = getStyle(renderTo, 'height'); + } + /** + * The current pixel width of the chart. + * + * @name Highcharts.Chart#chartWidth + * @type {number} + */ + chart.chartWidth = Math.max(// #1393 + 0, widthOption || chart.containerWidth || 600 // #1460 + ); + /** + * The current pixel height of the chart. + * + * @name Highcharts.Chart#chartHeight + * @type {number} + */ + chart.chartHeight = Math.max(0, relativeLength(heightOption, chart.chartWidth) || + (chart.containerHeight > 1 ? + chart.containerHeight : + 400)); + }, + /** + * If the renderTo element has no offsetWidth, most likely one or more of + * its parents are hidden. Loop up the DOM tree to temporarily display the + * parents, then save the original display properties, and when the true + * size is retrieved, reset them. Used on first render and on redraws. + * + * @private + * @function Highcharts.Chart#temporaryDisplay + * + * @param {boolean} [revert] + * Revert to the saved original styles. + * + * @return {void} + */ + temporaryDisplay: function (revert) { + var node = this.renderTo, tempStyle; + if (!revert) { + while (node && node.style) { + // When rendering to a detached node, it needs to be temporarily + // attached in order to read styling and bounding boxes (#5783, + // #7024). + if (!doc.body.contains(node) && !node.parentNode) { + node.hcOrigDetached = true; + doc.body.appendChild(node); + } + if (getStyle(node, 'display', false) === 'none' || + node.hcOricDetached) { + node.hcOrigStyle = { + display: node.style.display, + height: node.style.height, + overflow: node.style.overflow + }; + tempStyle = { + display: 'block', + overflow: 'hidden' + }; + if (node !== this.renderTo) { + tempStyle.height = 0; + } + css(node, tempStyle); + // If it still doesn't have an offset width after setting + // display to block, it probably has an !important priority + // #2631, 6803 + if (!node.offsetWidth) { + node.style.setProperty('display', 'block', 'important'); + } + } + node = node.parentNode; + if (node === doc.body) { + break; + } + } + } + else { + while (node && node.style) { + if (node.hcOrigStyle) { + css(node, node.hcOrigStyle); + delete node.hcOrigStyle; + } + if (node.hcOrigDetached) { + doc.body.removeChild(node); + node.hcOrigDetached = false; + } + node = node.parentNode; + } + } + }, + /** + * Set the {@link Chart.container|chart container's} class name, in + * addition to `highcharts-container`. + * + * @function Highcharts.Chart#setClassName + * + * @param {string} [className] + * + * @return {void} + */ + setClassName: function (className) { + this.container.className = 'highcharts-container ' + (className || ''); + }, + /** + * Get the containing element, determine the size and create the inner + * container div to hold the chart. + * + * @private + * @function Highcharts.Chart#afterGetContainer + * + * @return {void} + * + * @fires Highcharts.Chart#event:afterGetContainer + */ + getContainer: function () { + var chart = this, container, options = chart.options, optionsChart = options.chart, chartWidth, chartHeight, renderTo = chart.renderTo, indexAttrName = 'data-highcharts-chart', oldChartIndex, Ren, containerId = uniqueKey(), containerStyle, key; + if (!renderTo) { + chart.renderTo = renderTo = + optionsChart.renderTo; + } + if (isString(renderTo)) { + chart.renderTo = renderTo = + doc.getElementById(renderTo); + } + // Display an error if the renderTo is wrong + if (!renderTo) { + error(13, true, chart); + } + // If the container already holds a chart, destroy it. The check for + // hasRendered is there because web pages that are saved to disk from + // the browser, will preserve the data-highcharts-chart attribute and + // the SVG contents, but not an interactive chart. So in this case, + // charts[oldChartIndex] will point to the wrong chart if any (#2609). + oldChartIndex = pInt(attr(renderTo, indexAttrName)); + if (isNumber(oldChartIndex) && + charts[oldChartIndex] && + charts[oldChartIndex].hasRendered) { + charts[oldChartIndex].destroy(); + } + // Make a reference to the chart from the div + attr(renderTo, indexAttrName, chart.index); + // remove previous chart + renderTo.innerHTML = ''; + // If the container doesn't have an offsetWidth, it has or is a child of + // a node that has display:none. We need to temporarily move it out to a + // visible state to determine the size, else the legend and tooltips + // won't render properly. The skipClone option is used in sparklines as + // a micro optimization, saving about 1-2 ms each chart. + if (!optionsChart.skipClone && !renderTo.offsetWidth) { + chart.temporaryDisplay(); + } + // get the width and height + chart.getChartSize(); + chartWidth = chart.chartWidth; + chartHeight = chart.chartHeight; + // Allow table cells and flex-boxes to shrink without the chart blocking + // them out (#6427) + css(renderTo, { overflow: 'hidden' }); + // Create the inner container + if (!chart.styledMode) { + containerStyle = extend({ + position: 'relative', + // needed for context menu (avoidscrollbars) and content + // overflow in IE + overflow: 'hidden', + width: chartWidth + 'px', + height: chartHeight + 'px', + textAlign: 'left', + lineHeight: 'normal', + zIndex: 0, + '-webkit-tap-highlight-color': 'rgba(0,0,0,0)' + }, optionsChart.style); + } + /** + * The containing HTML element of the chart. The container is + * dynamically inserted into the element given as the `renderTo` + * parameter in the {@link Highcharts#chart} constructor. + * + * @name Highcharts.Chart#container + * @type {Highcharts.HTMLDOMElement} + */ + container = createElement('div', { + id: containerId + }, containerStyle, renderTo); + chart.container = container; + // cache the cursor (#1650) + chart._cursor = container.style.cursor; + // Initialize the renderer + Ren = H[optionsChart.renderer] || H.Renderer; + /** + * The renderer instance of the chart. Each chart instance has only one + * associated renderer. + * + * @name Highcharts.Chart#renderer + * @type {Highcharts.SVGRenderer} + */ + chart.renderer = new Ren(container, chartWidth, chartHeight, null, optionsChart.forExport, options.exporting && options.exporting.allowHTML, chart.styledMode); + // Set the initial animation from the options + setAnimation(void 0, chart); + chart.setClassName(optionsChart.className); + if (!chart.styledMode) { + chart.renderer.setStyle(optionsChart.style); + } + else { + // Initialize definitions + for (key in options.defs) { // eslint-disable-line guard-for-in + this.renderer.definition(options.defs[key]); + } + } + // Add a reference to the charts index + chart.renderer.chartIndex = chart.index; + fireEvent(this, 'afterGetContainer'); + }, + /** + * Calculate margins by rendering axis labels in a preliminary position. + * Title, subtitle and legend have already been rendered at this stage, but + * will be moved into their final positions. + * + * @private + * @function Highcharts.Chart#getMargins + * @param {boolean} skipAxes + * @return {void} + * @fires Highcharts.Chart#event:getMargins + */ + getMargins: function (skipAxes) { + var _a = this, spacing = _a.spacing, margin = _a.margin, titleOffset = _a.titleOffset; + this.resetMargins(); + // Adjust for title and subtitle + if (titleOffset[0] && !defined(margin[0])) { + this.plotTop = Math.max(this.plotTop, titleOffset[0] + spacing[0]); + } + if (titleOffset[2] && !defined(margin[2])) { + this.marginBottom = Math.max(this.marginBottom, titleOffset[2] + spacing[2]); + } + // Adjust for legend + if (this.legend && this.legend.display) { + this.legend.adjustMargins(margin, spacing); + } + fireEvent(this, 'getMargins'); + if (!skipAxes) { + this.getAxisMargins(); + } + }, + /** + * @private + * @function Highcharts.Chart#getAxisMargins + * @return {void} + */ + getAxisMargins: function () { + var chart = this, + // [top, right, bottom, left] + axisOffset = chart.axisOffset = [0, 0, 0, 0], colorAxis = chart.colorAxis, margin = chart.margin, getOffset = function (axes) { + axes.forEach(function (axis) { + if (axis.visible) { + axis.getOffset(); + } + }); + }; + // pre-render axes to get labels offset width + if (chart.hasCartesianSeries) { + getOffset(chart.axes); + } + else if (colorAxis && colorAxis.length) { + getOffset(colorAxis); + } + // Add the axis offsets + marginNames.forEach(function (m, side) { + if (!defined(margin[side])) { + chart[m] += axisOffset[side]; + } + }); + chart.setChartSize(); + }, + /** + * Reflows the chart to its container. By default, the chart reflows + * automatically to its container following a `window.resize` event, as per + * the [chart.reflow](https://api.highcharts.com/highcharts/chart.reflow) + * option. However, there are no reliable events for div resize, so if the + * container is resized without a window resize event, this must be called + * explicitly. + * + * @sample highcharts/members/chart-reflow/ + * Resize div and reflow + * @sample highcharts/chart/events-container/ + * Pop up and reflow + * + * @function Highcharts.Chart#reflow + * + * @param {global.Event} [e] + * Event arguments. Used primarily when the function is called + * internally as a response to window resize. + */ + reflow: function (e) { + var chart = this, optionsChart = chart.options.chart, renderTo = chart.renderTo, hasUserSize = (defined(optionsChart.width) && + defined(optionsChart.height)), width = optionsChart.width || getStyle(renderTo, 'width'), height = optionsChart.height || getStyle(renderTo, 'height'), target = e ? e.target : win; + // Width and height checks for display:none. Target is doc in IE8 and + // Opera, win in Firefox, Chrome and IE9. + if (!hasUserSize && + !chart.isPrinting && + width && + height && + (target === win || target === doc)) { + if (width !== chart.containerWidth || + height !== chart.containerHeight) { + U.clearTimeout(chart.reflowTimeout); + // When called from window.resize, e is set, else it's called + // directly (#2224) + chart.reflowTimeout = syncTimeout(function () { + // Set size, it may have been destroyed in the meantime + // (#1257) + if (chart.container) { + chart.setSize(void 0, void 0, false); + } + }, e ? 100 : 0); + } + chart.containerWidth = width; + chart.containerHeight = height; + } + }, + /** + * Toggle the event handlers necessary for auto resizing, depending on the + * `chart.reflow` option. + * + * @private + * @function Highcharts.Chart#setReflow + * @param {boolean} [reflow] + * @return {void} + */ + setReflow: function (reflow) { + var chart = this; + if (reflow !== false && !this.unbindReflow) { + this.unbindReflow = addEvent(win, 'resize', function (e) { + // a removed event listener still runs in Edge and IE if the + // listener was removed while the event runs, so check if the + // chart is not destroyed (#11609) + if (chart.options) { + chart.reflow(e); + } + }); + addEvent(this, 'destroy', this.unbindReflow); + } + else if (reflow === false && this.unbindReflow) { + // Unbind and unset + this.unbindReflow = this.unbindReflow(); + } + // The following will add listeners to re-fit the chart before and after + // printing (#2284). However it only works in WebKit. Should have worked + // in Firefox, but not supported in IE. + /* + if (win.matchMedia) { + win.matchMedia('print').addListener(function reflow() { + chart.reflow(); + }); + } + //*/ + }, + /** + * Resize the chart to a given width and height. In order to set the width + * only, the height argument may be skipped. To set the height only, pass + * `undefined` for the width. + * + * @sample highcharts/members/chart-setsize-button/ + * Test resizing from buttons + * @sample highcharts/members/chart-setsize-jquery-resizable/ + * Add a jQuery UI resizable + * @sample stock/members/chart-setsize/ + * Highstock with UI resizable + * + * @function Highcharts.Chart#setSize + * + * @param {number|null} [width] + * The new pixel width of the chart. Since v4.2.6, the argument can + * be `undefined` in order to preserve the current value (when + * setting height only), or `null` to adapt to the width of the + * containing element. + * + * @param {number|null} [height] + * The new pixel height of the chart. Since v4.2.6, the argument can + * be `undefined` in order to preserve the current value, or `null` + * in order to adapt to the height of the containing element. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=true] + * Whether and how to apply animation. + * + * @return {void} + * + * @fires Highcharts.Chart#event:endResize + * @fires Highcharts.Chart#event:resize + */ + setSize: function (width, height, animation) { + var chart = this, renderer = chart.renderer, globalAnimation; + // Handle the isResizing counter + chart.isResizing += 1; + // set the animation for the current process + setAnimation(animation, chart); + globalAnimation = renderer.globalAnimation; + chart.oldChartHeight = chart.chartHeight; + chart.oldChartWidth = chart.chartWidth; + if (typeof width !== 'undefined') { + chart.options.chart.width = width; + } + if (typeof height !== 'undefined') { + chart.options.chart.height = height; + } + chart.getChartSize(); + // Resize the container with the global animation applied if enabled + // (#2503) + if (!chart.styledMode) { + (globalAnimation ? animate : css)(chart.container, { + width: chart.chartWidth + 'px', + height: chart.chartHeight + 'px' + }, globalAnimation); + } + chart.setChartSize(true); + renderer.setSize(chart.chartWidth, chart.chartHeight, globalAnimation); + // handle axes + chart.axes.forEach(function (axis) { + axis.isDirty = true; + axis.setScale(); + }); + chart.isDirtyLegend = true; // force legend redraw + chart.isDirtyBox = true; // force redraw of plot and chart border + chart.layOutTitles(); // #2857 + chart.getMargins(); + chart.redraw(globalAnimation); + chart.oldChartHeight = null; + fireEvent(chart, 'resize'); + // Fire endResize and set isResizing back. If animation is disabled, + // fire without delay + syncTimeout(function () { + if (chart) { + fireEvent(chart, 'endResize', null, function () { + chart.isResizing -= 1; + }); + } + }, animObject(globalAnimation).duration || 0); + }, + /** + * Set the public chart properties. This is done before and after the + * pre-render to determine margin sizes. + * + * @private + * @function Highcharts.Chart#setChartSize + * + * @param {boolean} skipAxes + * + * @return {void} + * + * @fires Highcharts.Chart#event:afterSetChartSize + */ + setChartSize: function (skipAxes) { + var chart = this, inverted = chart.inverted, renderer = chart.renderer, chartWidth = chart.chartWidth, chartHeight = chart.chartHeight, optionsChart = chart.options.chart, spacing = chart.spacing, clipOffset = chart.clipOffset, clipX, clipY, plotLeft, plotTop, plotWidth, plotHeight, plotBorderWidth; + /** + * The current left position of the plot area in pixels. + * + * @name Highcharts.Chart#plotLeft + * @type {number} + */ + chart.plotLeft = plotLeft = Math.round(chart.plotLeft); + /** + * The current top position of the plot area in pixels. + * + * @name Highcharts.Chart#plotTop + * @type {number} + */ + chart.plotTop = plotTop = Math.round(chart.plotTop); + /** + * The current width of the plot area in pixels. + * + * @name Highcharts.Chart#plotWidth + * @type {number} + */ + chart.plotWidth = plotWidth = Math.max(0, Math.round(chartWidth - plotLeft - chart.marginRight)); + /** + * The current height of the plot area in pixels. + * + * @name Highcharts.Chart#plotHeight + * @type {number} + */ + chart.plotHeight = plotHeight = Math.max(0, Math.round(chartHeight - plotTop - chart.marginBottom)); + chart.plotSizeX = inverted ? plotHeight : plotWidth; + chart.plotSizeY = inverted ? plotWidth : plotHeight; + chart.plotBorderWidth = optionsChart.plotBorderWidth || 0; + // Set boxes used for alignment + chart.spacingBox = renderer.spacingBox = { + x: spacing[3], + y: spacing[0], + width: chartWidth - spacing[3] - spacing[1], + height: chartHeight - spacing[0] - spacing[2] + }; + chart.plotBox = renderer.plotBox = { + x: plotLeft, + y: plotTop, + width: plotWidth, + height: plotHeight + }; + plotBorderWidth = 2 * Math.floor(chart.plotBorderWidth / 2); + clipX = Math.ceil(Math.max(plotBorderWidth, clipOffset[3]) / 2); + clipY = Math.ceil(Math.max(plotBorderWidth, clipOffset[0]) / 2); + chart.clipBox = { + x: clipX, + y: clipY, + width: Math.floor(chart.plotSizeX - + Math.max(plotBorderWidth, clipOffset[1]) / 2 - + clipX), + height: Math.max(0, Math.floor(chart.plotSizeY - + Math.max(plotBorderWidth, clipOffset[2]) / 2 - + clipY)) + }; + if (!skipAxes) { + chart.axes.forEach(function (axis) { + axis.setAxisSize(); + axis.setAxisTranslation(); + }); + } + fireEvent(chart, 'afterSetChartSize', { skipAxes: skipAxes }); + }, + /** + * Initial margins before auto size margins are applied. + * + * @private + * @function Highcharts.Chart#resetMargins + * @return {void} + */ + resetMargins: function () { + fireEvent(this, 'resetMargins'); + var chart = this, chartOptions = chart.options.chart; + // Create margin and spacing array + ['margin', 'spacing'].forEach(function splashArrays(target) { + var value = chartOptions[target], values = isObject(value) ? value : [value, value, value, value]; + [ + 'Top', + 'Right', + 'Bottom', + 'Left' + ].forEach(function (sideName, side) { + chart[target][side] = pick(chartOptions[target + sideName], values[side]); + }); + }); + // Set margin names like chart.plotTop, chart.plotLeft, + // chart.marginRight, chart.marginBottom. + marginNames.forEach(function (m, side) { + chart[m] = pick(chart.margin[side], chart.spacing[side]); + }); + chart.axisOffset = [0, 0, 0, 0]; // top, right, bottom, left + chart.clipOffset = [0, 0, 0, 0]; + }, + /** + * Internal function to draw or redraw the borders and backgrounds for chart + * and plot area. + * + * @private + * @function Highcharts.Chart#drawChartBox + * @return {void} + * @fires Highcharts.Chart#event:afterDrawChartBox + */ + drawChartBox: function () { + var chart = this, optionsChart = chart.options.chart, renderer = chart.renderer, chartWidth = chart.chartWidth, chartHeight = chart.chartHeight, chartBackground = chart.chartBackground, plotBackground = chart.plotBackground, plotBorder = chart.plotBorder, chartBorderWidth, styledMode = chart.styledMode, plotBGImage = chart.plotBGImage, chartBackgroundColor = optionsChart.backgroundColor, plotBackgroundColor = optionsChart.plotBackgroundColor, plotBackgroundImage = optionsChart.plotBackgroundImage, mgn, bgAttr, plotLeft = chart.plotLeft, plotTop = chart.plotTop, plotWidth = chart.plotWidth, plotHeight = chart.plotHeight, plotBox = chart.plotBox, clipRect = chart.clipRect, clipBox = chart.clipBox, verb = 'animate'; + // Chart area + if (!chartBackground) { + chart.chartBackground = chartBackground = renderer.rect() + .addClass('highcharts-background') + .add(); + verb = 'attr'; + } + if (!styledMode) { + // Presentational + chartBorderWidth = optionsChart.borderWidth || 0; + mgn = chartBorderWidth + (optionsChart.shadow ? 8 : 0); + bgAttr = { + fill: chartBackgroundColor || 'none' + }; + if (chartBorderWidth || chartBackground['stroke-width']) { // #980 + bgAttr.stroke = optionsChart.borderColor; + bgAttr['stroke-width'] = chartBorderWidth; + } + chartBackground + .attr(bgAttr) + .shadow(optionsChart.shadow); + } + else { + chartBorderWidth = mgn = chartBackground.strokeWidth(); + } + chartBackground[verb]({ + x: mgn / 2, + y: mgn / 2, + width: chartWidth - mgn - chartBorderWidth % 2, + height: chartHeight - mgn - chartBorderWidth % 2, + r: optionsChart.borderRadius + }); + // Plot background + verb = 'animate'; + if (!plotBackground) { + verb = 'attr'; + chart.plotBackground = plotBackground = renderer.rect() + .addClass('highcharts-plot-background') + .add(); + } + plotBackground[verb](plotBox); + if (!styledMode) { + // Presentational attributes for the background + plotBackground + .attr({ + fill: plotBackgroundColor || 'none' + }) + .shadow(optionsChart.plotShadow); + // Create the background image + if (plotBackgroundImage) { + if (!plotBGImage) { + chart.plotBGImage = renderer.image(plotBackgroundImage, plotLeft, plotTop, plotWidth, plotHeight).add(); + } + else { + if (plotBackgroundImage !== plotBGImage.attr('href')) { + plotBGImage.attr('href', plotBackgroundImage); + } + plotBGImage.animate(plotBox); + } + } + } + // Plot clip + if (!clipRect) { + chart.clipRect = renderer.clipRect(clipBox); + } + else { + clipRect.animate({ + width: clipBox.width, + height: clipBox.height + }); + } + // Plot area border + verb = 'animate'; + if (!plotBorder) { + verb = 'attr'; + chart.plotBorder = plotBorder = renderer.rect() + .addClass('highcharts-plot-border') + .attr({ + zIndex: 1 // Above the grid + }) + .add(); + } + if (!styledMode) { + // Presentational + plotBorder.attr({ + stroke: optionsChart.plotBorderColor, + 'stroke-width': optionsChart.plotBorderWidth || 0, + fill: 'none' + }); + } + plotBorder[verb](plotBorder.crisp({ + x: plotLeft, + y: plotTop, + width: plotWidth, + height: plotHeight + }, -plotBorder.strokeWidth())); // #3282 plotBorder should be negative; + // reset + chart.isDirtyBox = false; + fireEvent(this, 'afterDrawChartBox'); + }, + /** + * Detect whether a certain chart property is needed based on inspecting its + * options and series. This mainly applies to the chart.inverted property, + * and in extensions to the chart.angular and chart.polar properties. + * + * @private + * @function Highcharts.Chart#propFromSeries + * @return {void} + */ + propFromSeries: function () { + var chart = this, optionsChart = chart.options.chart, klass, seriesOptions = chart.options.series, i, value; + /** + * The flag is set to `true` if a series of the chart is inverted. + * + * @name Highcharts.Chart#inverted + * @type {boolean|undefined} + */ + ['inverted', 'angular', 'polar'].forEach(function (key) { + // The default series type's class + klass = seriesTypes[(optionsChart.type || + optionsChart.defaultSeriesType)]; + // Get the value from available chart-wide properties + value = + // It is set in the options: + optionsChart[key] || + // The default series class: + (klass && klass.prototype[key]); + // requires it + // 4. Check if any the chart's series require it + i = seriesOptions && seriesOptions.length; + while (!value && i--) { + klass = seriesTypes[seriesOptions[i].type]; + if (klass && klass.prototype[key]) { + value = true; + } + } + // Set the chart property + chart[key] = value; + }); + }, + /** + * Internal function to link two or more series together, based on the + * `linkedTo` option. This is done from `Chart.render`, and after + * `Chart.addSeries` and `Series.remove`. + * + * @private + * @function Highcharts.Chart#linkSeries + * @return {void} + * @fires Highcharts.Chart#event:afterLinkSeries + */ + linkSeries: function () { + var chart = this, chartSeries = chart.series; + // Reset links + chartSeries.forEach(function (series) { + series.linkedSeries.length = 0; + }); + // Apply new links + chartSeries.forEach(function (series) { + var linkedTo = series.options.linkedTo; + if (isString(linkedTo)) { + if (linkedTo === ':previous') { + linkedTo = chart.series[series.index - 1]; + } + else { + linkedTo = chart.get(linkedTo); + } + // #3341 avoid mutual linking + if (linkedTo && linkedTo.linkedParent !== series) { + linkedTo.linkedSeries.push(series); + series.linkedParent = linkedTo; + if (linkedTo.enabledDataSorting) { + series.setDataSortingOptions(); + } + series.visible = pick(series.options.visible, linkedTo.options.visible, series.visible); // #3879 + } + } + }); + fireEvent(this, 'afterLinkSeries'); + }, + /** + * Render series for the chart. + * + * @private + * @function Highcharts.Chart#renderSeries + * @return {void} + */ + renderSeries: function () { + this.series.forEach(function (serie) { + serie.translate(); + serie.render(); + }); + }, + /** + * Render labels for the chart. + * + * @private + * @function Highcharts.Chart#renderLabels + * @return {void} + */ + renderLabels: function () { + var chart = this, labels = chart.options.labels; + if (labels.items) { + labels.items.forEach(function (label) { + var style = extend(labels.style, label.style), x = pInt(style.left) + chart.plotLeft, y = pInt(style.top) + chart.plotTop + 12; + // delete to prevent rewriting in IE + delete style.left; + delete style.top; + chart.renderer.text(label.html, x, y) + .attr({ zIndex: 2 }) + .css(style) + .add(); + }); + } + }, + /** + * Render all graphics for the chart. Runs internally on initialization. + * + * @private + * @function Highcharts.Chart#render + * @return {void} + */ + render: function () { + var chart = this, axes = chart.axes, colorAxis = chart.colorAxis, renderer = chart.renderer, options = chart.options, correction = 0, // correction for X axis labels + tempWidth, tempHeight, redoHorizontal, redoVertical, renderAxes = function (axes) { + axes.forEach(function (axis) { + if (axis.visible) { + axis.render(); + } + }); + }; + // Title + chart.setTitle(); + /** + * The overview of the chart's series. + * + * @name Highcharts.Chart#legend + * @type {Highcharts.Legend} + */ + chart.legend = new Legend(chart, options.legend); + // Get stacks + if (chart.getStacks) { + chart.getStacks(); + } + // Get chart margins + chart.getMargins(true); + chart.setChartSize(); + // Record preliminary dimensions for later comparison + tempWidth = chart.plotWidth; + axes.some(function (axis) { + if (axis.horiz && + axis.visible && + axis.options.labels.enabled && + axis.series.length) { + // 21 is the most common correction for X axis labels + correction = 21; + return true; + } + }); + // use Math.max to prevent negative plotHeight + chart.plotHeight = Math.max(chart.plotHeight - correction, 0); + tempHeight = chart.plotHeight; + // Get margins by pre-rendering axes + axes.forEach(function (axis) { + axis.setScale(); + }); + chart.getAxisMargins(); + // If the plot area size has changed significantly, calculate tick + // positions again + redoHorizontal = tempWidth / chart.plotWidth > 1.1; + // Height is more sensitive, use lower threshold + redoVertical = tempHeight / chart.plotHeight > 1.05; + if (redoHorizontal || redoVertical) { + axes.forEach(function (axis) { + if ((axis.horiz && redoHorizontal) || + (!axis.horiz && redoVertical)) { + // update to reflect the new margins + axis.setTickInterval(true); + } + }); + chart.getMargins(); // second pass to check for new labels + } + // Draw the borders and backgrounds + chart.drawChartBox(); + // Axes + if (chart.hasCartesianSeries) { + renderAxes(axes); + } + else if (colorAxis && colorAxis.length) { + renderAxes(colorAxis); + } + // The series + if (!chart.seriesGroup) { + chart.seriesGroup = renderer.g('series-group') + .attr({ zIndex: 3 }) + .add(); + } + chart.renderSeries(); + // Labels + chart.renderLabels(); + // Credits + chart.addCredits(); + // Handle responsiveness + if (chart.setResponsive) { + chart.setResponsive(); + } + // Handle scaling + chart.updateContainerScaling(); + // Set flag + chart.hasRendered = true; + }, + /** + * Set a new credits label for the chart. + * + * @sample highcharts/credits/credits-update/ + * Add and update credits + * + * @function Highcharts.Chart#addCredits + * + * @param {Highcharts.CreditsOptions} credits + * A configuration object for the new credits. + * + * @return {void} + */ + addCredits: function (credits) { + var chart = this; + credits = merge(true, this.options.credits, credits); + if (credits.enabled && !this.credits) { + /** + * The chart's credits label. The label has an `update` method that + * allows setting new options as per the + * [credits options set](https://api.highcharts.com/highcharts/credits). + * + * @name Highcharts.Chart#credits + * @type {Highcharts.SVGElement} + */ + this.credits = this.renderer.text(credits.text + (this.mapCredits || ''), 0, 0) + .addClass('highcharts-credits') + .on('click', function () { + if (credits.href) { + win.location.href = credits.href; + } + }) + .attr({ + align: credits.position.align, + zIndex: 8 + }); + if (!chart.styledMode) { + this.credits.css(credits.style); + } + this.credits + .add() + .align(credits.position); + // Dynamically update + this.credits.update = function (options) { + chart.credits = chart.credits.destroy(); + chart.addCredits(options); + }; + } + }, + /** + * Handle scaling, #11329 - when there is scaling/transform on the container + * or on a parent element, we need to take this into account. We calculate + * the scaling once here and it is picked up where we need to use it + * (Pointer, Tooltip). + * + * @private + * @function Highcharts.Chart#updateContainerScaling + * @return {void} + */ + updateContainerScaling: function () { + var container = this.container; + if (container.offsetWidth && + container.offsetHeight && + container.getBoundingClientRect) { + var bb = container.getBoundingClientRect(), scaleX = bb.width / container.offsetWidth, scaleY = bb.height / container.offsetHeight; + if (scaleX !== 1 || scaleY !== 1) { + this.containerScaling = { scaleX: scaleX, scaleY: scaleY }; + } + else { + delete this.containerScaling; + } + } + }, + /** + * Remove the chart and purge memory. This method is called internally + * before adding a second chart into the same container, as well as on + * window unload to prevent leaks. + * + * @sample highcharts/members/chart-destroy/ + * Destroy the chart from a button + * @sample stock/members/chart-destroy/ + * Destroy with Highstock + * + * @function Highcharts.Chart#destroy + * + * @return {void} + * + * @fires Highcharts.Chart#event:destroy + */ + destroy: function () { + var chart = this, axes = chart.axes, series = chart.series, container = chart.container, i, parentNode = container && container.parentNode; + // fire the chart.destoy event + fireEvent(chart, 'destroy'); + // Delete the chart from charts lookup array + if (chart.renderer.forExport) { + erase(charts, chart); // #6569 + } + else { + charts[chart.index] = void 0; + } + H.chartCount--; + chart.renderTo.removeAttribute('data-highcharts-chart'); + // remove events + removeEvent(chart); + // ==== Destroy collections: + // Destroy axes + i = axes.length; + while (i--) { + axes[i] = axes[i].destroy(); + } + // Destroy scroller & scroller series before destroying base series + if (this.scroller && this.scroller.destroy) { + this.scroller.destroy(); + } + // Destroy each series + i = series.length; + while (i--) { + series[i] = series[i].destroy(); + } + // ==== Destroy chart properties: + [ + 'title', 'subtitle', 'chartBackground', 'plotBackground', + 'plotBGImage', 'plotBorder', 'seriesGroup', 'clipRect', 'credits', + 'pointer', 'rangeSelector', 'legend', 'resetZoomButton', 'tooltip', + 'renderer' + ].forEach(function (name) { + var prop = chart[name]; + if (prop && prop.destroy) { + chart[name] = prop.destroy(); + } + }); + // Remove container and all SVG, check container as it can break in IE + // when destroyed before finished loading + if (container) { + container.innerHTML = ''; + removeEvent(container); + if (parentNode) { + discardElement(container); + } + } + // clean it all up + objectEach(chart, function (val, key) { + delete chart[key]; + }); + }, + /** + * Prepare for first rendering after all data are loaded. + * + * @private + * @function Highcharts.Chart#firstRender + * @return {void} + * + * @fires Highcharts.Chart#event:beforeRender + */ + firstRender: function () { + var chart = this, options = chart.options; + // Hook for oldIE to check whether the chart is ready to render + if (chart.isReadyToRender && !chart.isReadyToRender()) { + return; + } + // Create the container + chart.getContainer(); + chart.resetMargins(); + chart.setChartSize(); + // Set the common chart properties (mainly invert) from the given series + chart.propFromSeries(); + // get axes + chart.getAxes(); + // Initialize the series + (isArray(options.series) ? options.series : []).forEach( + // #9680 + function (serieOptions) { + chart.initSeries(serieOptions); + }); + chart.linkSeries(); + chart.setSeriesData(); + // Run an event after axes and series are initialized, but before + // render. At this stage, the series data is indexed and cached in the + // xData and yData arrays, so we can access those before rendering. Used + // in Highstock. + fireEvent(chart, 'beforeRender'); + // depends on inverted and on margins being set + if (Pointer) { + if (!H.hasTouch && (win.PointerEvent || win.MSPointerEvent)) { + chart.pointer = new MSPointer(chart, options); + } + else { + /** + * The Pointer that keeps track of mouse and touch interaction. + * + * @memberof Highcharts.Chart + * @name pointer + * @type {Highcharts.Pointer} + * @instance + */ + chart.pointer = new Pointer(chart, options); + } + } + chart.render(); + // Fire the load event if there are no external images + if (!chart.renderer.imgCount && !chart.hasLoaded) { + chart.onload(); + } + // If the chart was rendered outside the top container, put it back in + // (#3679) + chart.temporaryDisplay(true); + }, + /** + * Internal function that runs on chart load, async if any images are loaded + * in the chart. Runs the callbacks and triggers the `load` and `render` + * events. + * + * @private + * @function Highcharts.Chart#onload + * @return {void} + * @fires Highcharts.Chart#event:load + * @fires Highcharts.Chart#event:render + */ + onload: function () { + // Run callbacks, first the ones registered by modules, then user's one + this.callbacks.concat([this.callback]).forEach(function (fn) { + // Chart destroyed in its own callback (#3600) + if (fn && typeof this.index !== 'undefined') { + fn.apply(this, [this]); + } + }, this); + fireEvent(this, 'load'); + fireEvent(this, 'render'); + // Set up auto resize, check for not destroyed (#6068) + if (defined(this.index)) { + this.setReflow(this.options.chart.reflow); + } + // Don't run again + this.hasLoaded = true; + } + }); // end Chart + + }); + _registerModule(_modules, 'parts/ScrollablePlotArea.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * Highcharts feature to make the Y axis stay fixed when scrolling the chart + * horizontally on mobile devices. Supports left and right side axes. + */ + /* + WIP on vertical scrollable plot area (#9378). To do: + - Bottom axis positioning + - Test with Gantt + - Look for size optimizing the code + - API and demos + */ + var addEvent = U.addEvent, createElement = U.createElement, pick = U.pick, stop = U.stop; + var Chart = H.Chart; + /** + * Options for a scrollable plot area. This feature provides a minimum size for + * the plot area of the chart. If the size gets smaller than this, typically + * on mobile devices, a native browser scrollbar is presented. This scrollbar + * provides smooth scrolling for the contents of the plot area, whereas the + * title, legend and unaffected axes are fixed. + * + * Since v7.1.2, a scrollable plot area can be defined for either horizontal or + * vertical scrolling, depending on whether the `minWidth` or `minHeight` + * option is set. + * + * @sample highcharts/chart/scrollable-plotarea + * Scrollable plot area + * @sample highcharts/chart/scrollable-plotarea-vertical + * Vertically scrollable plot area + * @sample {gantt} highcharts/chart/scrollable-plotarea-vertical + * Gantt chart with vertically scrollable plot area + * + * @since 6.1.0 + * @product highcharts gantt + * @apioption chart.scrollablePlotArea + */ + /** + * The minimum height for the plot area. If it gets smaller than this, the plot + * area will become scrollable. + * + * @type {number} + * @apioption chart.scrollablePlotArea.minHeight + */ + /** + * The minimum width for the plot area. If it gets smaller than this, the plot + * area will become scrollable. + * + * @type {number} + * @apioption chart.scrollablePlotArea.minWidth + */ + /** + * The initial scrolling position of the scrollable plot area. Ranges from 0 to + * 1, where 0 aligns the plot area to the left and 1 aligns it to the right. + * Typically we would use 1 if the chart has right aligned Y axes. + * + * @type {number} + * @apioption chart.scrollablePlotArea.scrollPositionX + */ + /** + * The initial scrolling position of the scrollable plot area. Ranges from 0 to + * 1, where 0 aligns the plot area to the top and 1 aligns it to the bottom. + * + * @type {number} + * @apioption chart.scrollablePlotArea.scrollPositionY + */ + /** + * The opacity of mask applied on one of the sides of the plot + * area. + * + * @sample {highcharts} highcharts/chart/scrollable-plotarea-opacity + * Disabled opacity for the mask + * + * @type {number} + * @default 0.85 + * @since 7.1.1 + * @apioption chart.scrollablePlotArea.opacity + */ + ''; // detach API doclets + /* eslint-disable no-invalid-this, valid-jsdoc */ + addEvent(Chart, 'afterSetChartSize', function (e) { + var scrollablePlotArea = this.options.chart.scrollablePlotArea, scrollableMinWidth = scrollablePlotArea && scrollablePlotArea.minWidth, scrollableMinHeight = scrollablePlotArea && scrollablePlotArea.minHeight, scrollablePixelsX, scrollablePixelsY, corrections; + if (!this.renderer.forExport) { + // The amount of pixels to scroll, the difference between chart + // width and scrollable width + if (scrollableMinWidth) { + this.scrollablePixelsX = scrollablePixelsX = Math.max(0, scrollableMinWidth - this.chartWidth); + if (scrollablePixelsX) { + this.plotWidth += scrollablePixelsX; + if (this.inverted) { + this.clipBox.height += scrollablePixelsX; + this.plotBox.height += scrollablePixelsX; + } + else { + this.clipBox.width += scrollablePixelsX; + this.plotBox.width += scrollablePixelsX; + } + corrections = { + // Corrections for right side + 1: { name: 'right', value: scrollablePixelsX } + }; + } + // Currently we can only do either X or Y + } + else if (scrollableMinHeight) { + this.scrollablePixelsY = scrollablePixelsY = Math.max(0, scrollableMinHeight - this.chartHeight); + if (scrollablePixelsY) { + this.plotHeight += scrollablePixelsY; + if (this.inverted) { + this.clipBox.width += scrollablePixelsY; + this.plotBox.width += scrollablePixelsY; + } + else { + this.clipBox.height += scrollablePixelsY; + this.plotBox.height += scrollablePixelsY; + } + corrections = { + 2: { name: 'bottom', value: scrollablePixelsY } + }; + } + } + if (corrections && !e.skipAxes) { + this.axes.forEach(function (axis) { + // For right and bottom axes, only fix the plot line length + if (corrections[axis.side]) { + // Get the plot lines right in getPlotLinePath, + // temporarily set it to the adjusted plot width. + axis.getPlotLinePath = function () { + var marginName = corrections[axis.side].name, correctionValue = corrections[axis.side].value, + // axis.right or axis.bottom + margin = this[marginName], path; + // Temporarily adjust + this[marginName] = margin - correctionValue; + path = H.Axis.prototype.getPlotLinePath.apply(this, arguments); + // Reset + this[marginName] = margin; + return path; + }; + } + else { + // Apply the corrected plotWidth + axis.setAxisSize(); + axis.setAxisTranslation(); + } + }); + } + } + }); + addEvent(Chart, 'render', function () { + if (this.scrollablePixelsX || this.scrollablePixelsY) { + if (this.setUpScrolling) { + this.setUpScrolling(); + } + this.applyFixed(); + } + else if (this.fixedDiv) { // Has been in scrollable mode + this.applyFixed(); + } + }); + /** + * @private + * @function Highcharts.Chart#setUpScrolling + * @return {void} + */ + Chart.prototype.setUpScrolling = function () { + var _this = this; + var attribs = { + WebkitOverflowScrolling: 'touch', + overflowX: 'hidden', + overflowY: 'hidden' + }; + if (this.scrollablePixelsX) { + attribs.overflowX = 'auto'; + } + if (this.scrollablePixelsY) { + attribs.overflowY = 'auto'; + } + // Add the necessary divs to provide scrolling + this.scrollingContainer = createElement('div', { + 'className': 'highcharts-scrolling' + }, attribs, this.renderTo); + // On scroll, reset the chart position because it applies to the scrolled + // container + addEvent(this.scrollingContainer, 'scroll', function () { + if (_this.pointer) { + delete _this.pointer.chartPosition; + } + }); + this.innerContainer = createElement('div', { + 'className': 'highcharts-inner-container' + }, null, this.scrollingContainer); + // Now move the container inside + this.innerContainer.appendChild(this.container); + // Don't run again + this.setUpScrolling = null; + }; + /** + * These elements are moved over to the fixed renderer and stay fixed when the + * user scrolls the chart + * @private + */ + Chart.prototype.moveFixedElements = function () { + var container = this.container, fixedRenderer = this.fixedRenderer, fixedSelectors = [ + '.highcharts-contextbutton', + '.highcharts-credits', + '.highcharts-legend', + '.highcharts-legend-checkbox', + '.highcharts-navigator-series', + '.highcharts-navigator-xaxis', + '.highcharts-navigator-yaxis', + '.highcharts-navigator', + '.highcharts-reset-zoom', + '.highcharts-scrollbar', + '.highcharts-subtitle', + '.highcharts-title' + ], axisClass; + if (this.scrollablePixelsX && !this.inverted) { + axisClass = '.highcharts-yaxis'; + } + else if (this.scrollablePixelsX && this.inverted) { + axisClass = '.highcharts-xaxis'; + } + else if (this.scrollablePixelsY && !this.inverted) { + axisClass = '.highcharts-xaxis'; + } + else if (this.scrollablePixelsY && this.inverted) { + axisClass = '.highcharts-yaxis'; + } + fixedSelectors.push(axisClass, axisClass + '-labels'); + fixedSelectors.forEach(function (className) { + [].forEach.call(container.querySelectorAll(className), function (elem) { + (elem.namespaceURI === fixedRenderer.SVG_NS ? + fixedRenderer.box : + fixedRenderer.box.parentNode).appendChild(elem); + elem.style.pointerEvents = 'auto'; + }); + }); + }; + /** + * @private + * @function Highcharts.Chart#applyFixed + * @return {void} + */ + Chart.prototype.applyFixed = function () { + var _a; + var fixedRenderer, scrollableWidth, scrollableHeight, firstTime = !this.fixedDiv, scrollableOptions = this.options.chart.scrollablePlotArea; + // First render + if (firstTime) { + this.fixedDiv = createElement('div', { + className: 'highcharts-fixed' + }, { + position: 'absolute', + overflow: 'hidden', + pointerEvents: 'none', + zIndex: 2 + }, null, true); + this.renderTo.insertBefore(this.fixedDiv, this.renderTo.firstChild); + this.renderTo.style.overflow = 'visible'; + this.fixedRenderer = fixedRenderer = new H.Renderer(this.fixedDiv, this.chartWidth, this.chartHeight, (_a = this.options.chart) === null || _a === void 0 ? void 0 : _a.style); + // Mask + this.scrollableMask = fixedRenderer + .path() + .attr({ + fill: this.options.chart.backgroundColor || '#fff', + 'fill-opacity': pick(scrollableOptions.opacity, 0.85), + zIndex: -1 + }) + .addClass('highcharts-scrollable-mask') + .add(); + this.moveFixedElements(); + addEvent(this, 'afterShowResetZoom', this.moveFixedElements); + addEvent(this, 'afterLayOutTitles', this.moveFixedElements); + } + else { + // Set the size of the fixed renderer to the visible width + this.fixedRenderer.setSize(this.chartWidth, this.chartHeight); + } + // Increase the size of the scrollable renderer and background + scrollableWidth = this.chartWidth + (this.scrollablePixelsX || 0); + scrollableHeight = this.chartHeight + (this.scrollablePixelsY || 0); + stop(this.container); + this.container.style.width = scrollableWidth + 'px'; + this.container.style.height = scrollableHeight + 'px'; + this.renderer.boxWrapper.attr({ + width: scrollableWidth, + height: scrollableHeight, + viewBox: [0, 0, scrollableWidth, scrollableHeight].join(' ') + }); + this.chartBackground.attr({ + width: scrollableWidth, + height: scrollableHeight + }); + this.scrollingContainer.style.height = this.chartHeight + 'px'; + // Set scroll position + if (firstTime) { + if (scrollableOptions.scrollPositionX) { + this.scrollingContainer.scrollLeft = + this.scrollablePixelsX * + scrollableOptions.scrollPositionX; + } + if (scrollableOptions.scrollPositionY) { + this.scrollingContainer.scrollTop = + this.scrollablePixelsY * + scrollableOptions.scrollPositionY; + } + } + // Mask behind the left and right side + var axisOffset = this.axisOffset, maskTop = this.plotTop - axisOffset[0] - 1, maskLeft = this.plotLeft - axisOffset[3] - 1, maskBottom = this.plotTop + this.plotHeight + axisOffset[2] + 1, maskRight = this.plotLeft + this.plotWidth + axisOffset[1] + 1, maskPlotRight = this.plotLeft + this.plotWidth - + (this.scrollablePixelsX || 0), maskPlotBottom = this.plotTop + this.plotHeight - + (this.scrollablePixelsY || 0), d; + if (this.scrollablePixelsX) { + d = [ + // Left side + ['M', 0, maskTop], + ['L', this.plotLeft - 1, maskTop], + ['L', this.plotLeft - 1, maskBottom], + ['L', 0, maskBottom], + ['Z'], + // Right side + ['M', maskPlotRight, maskTop], + ['L', this.chartWidth, maskTop], + ['L', this.chartWidth, maskBottom], + ['L', maskPlotRight, maskBottom], + ['Z'] + ]; + } + else if (this.scrollablePixelsY) { + d = [ + // Top side + ['M', maskLeft, 0], + ['L', maskLeft, this.plotTop - 1], + ['L', maskRight, this.plotTop - 1], + ['L', maskRight, 0], + ['Z'], + // Bottom side + ['M', maskLeft, maskPlotBottom], + ['L', maskLeft, this.chartHeight], + ['L', maskRight, this.chartHeight], + ['L', maskRight, maskPlotBottom], + ['Z'] + ]; + } + else { + d = [['M', 0, 0]]; + } + if (this.redrawTrigger !== 'adjustHeight') { + this.scrollableMask.attr({ d: d }); + } + }; + + }); + _registerModule(_modules, 'parts/StackingAxis.js', [_modules['parts/Utilities.js']], function (U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, destroyObjectProperties = U.destroyObjectProperties, fireEvent = U.fireEvent, objectEach = U.objectEach, pick = U.pick; + /* eslint-disable valid-jsdoc */ + /** + * Adds stacking support to axes. + * @private + * @class + */ + var StackingAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function StackingAxisAdditions(axis) { + this.oldStacks = {}; + this.stacks = {}; + this.stacksTouched = 0; + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Build the stacks from top down + * @private + */ + StackingAxisAdditions.prototype.buildStacks = function () { + var stacking = this; + var axis = stacking.axis; + var axisSeries = axis.series; + var reversedStacks = pick(axis.options.reversedStacks, true); + var len = axisSeries.length; + var actualSeries, i; + if (!axis.isXAxis) { + stacking.usePercentage = false; + i = len; + while (i--) { + actualSeries = axisSeries[reversedStacks ? i : len - i - 1]; + actualSeries.setStackedPoints(); + } + // Loop up again to compute percent and stream stack + for (i = 0; i < len; i++) { + axisSeries[i].modifyStacks(); + } + fireEvent(axis, 'afterBuildStacks'); + } + }; + /** + * @private + */ + StackingAxisAdditions.prototype.cleanStacks = function () { + var stacking = this; + var axis = stacking.axis; + var stacks; + if (!axis.isXAxis) { + if (stacking.oldStacks) { + stacks = stacking.stacks = stacking.oldStacks; + } + // reset stacks + objectEach(stacks, function (type) { + objectEach(type, function (stack) { + stack.cumulative = stack.total; + }); + }); + } + }; + /** + * Set all the stacks to initial states and destroy unused ones. + * @private + */ + StackingAxisAdditions.prototype.resetStacks = function () { + var stacking = this; + var axis = stacking.axis; + var stacks = stacking.stacks; + if (!axis.isXAxis) { + objectEach(stacks, function (type) { + objectEach(type, function (stack, key) { + // Clean up memory after point deletion (#1044, #4320) + if (stack.touched < stacking.stacksTouched) { + stack.destroy(); + delete type[key]; + // Reset stacks + } + else { + stack.total = null; + stack.cumulative = null; + } + }); + }); + } + }; + /** + * @private + */ + StackingAxisAdditions.prototype.renderStackTotals = function () { + var stacking = this; + var axis = stacking.axis; + var chart = axis.chart; + var renderer = chart.renderer; + var stacks = stacking.stacks; + var stackTotalGroup = stacking.stackTotalGroup = (stacking.stackTotalGroup || + renderer + .g('stack-labels') + .attr({ + visibility: 'visible', + zIndex: 6 + }) + .add()); + // plotLeft/Top will change when y axis gets wider so we need to + // translate the stackTotalGroup at every render call. See bug #506 + // and #516 + stackTotalGroup.translate(chart.plotLeft, chart.plotTop); + // Render each stack total + objectEach(stacks, function (type) { + objectEach(type, function (stack) { + stack.render(stackTotalGroup); + }); + }); + }; + return StackingAxisAdditions; + }()); + /** + * Axis with stacking support. + * @private + * @class + */ + var StackingAxis = /** @class */ (function () { + function StackingAxis() { + } + /* * + * + * Static Functions + * + * */ + /** + * Extends axis with stacking support. + * @private + */ + StackingAxis.compose = function (AxisClass) { + var axisProto = AxisClass.prototype; + addEvent(AxisClass, 'init', StackingAxis.onInit); + addEvent(AxisClass, 'destroy', StackingAxis.onDestroy); + }; + /** + * @private + */ + StackingAxis.onDestroy = function () { + var stacking = this.stacking; + if (!stacking) { + return; + } + var stacks = stacking.stacks; + // Destroy each stack total + objectEach(stacks, function (stack, stackKey) { + destroyObjectProperties(stack); + stacks[stackKey] = null; + }); + if (stacking && + stacking.stackTotalGroup) { + stacking.stackTotalGroup.destroy(); + } + }; + /** + * @private + */ + StackingAxis.onInit = function () { + var axis = this; + if (!axis.stacking) { + axis.stacking = new StackingAxisAdditions(axis); + } + }; + return StackingAxis; + }()); + + return StackingAxis; + }); + _registerModule(_modules, 'mixins/legend-symbol.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var merge = U.merge, pick = U.pick; + /* eslint-disable valid-jsdoc */ + /** + * Legend symbol mixin. + * + * @private + * @mixin Highcharts.LegendSymbolMixin + */ + H.LegendSymbolMixin = { + /** + * Get the series' symbol in the legend + * + * @private + * @function Highcharts.LegendSymbolMixin.drawRectangle + * + * @param {Highcharts.Legend} legend + * The legend object + * + * @param {Highcharts.Point|Highcharts.Series} item + * The series (this) or point + */ + drawRectangle: function (legend, item) { + var options = legend.options, symbolHeight = legend.symbolHeight, square = options.squareSymbol, symbolWidth = square ? symbolHeight : legend.symbolWidth; + item.legendSymbol = this.chart.renderer.rect(square ? (legend.symbolWidth - symbolHeight) / 2 : 0, legend.baseline - symbolHeight + 1, // #3988 + symbolWidth, symbolHeight, pick(legend.options.symbolRadius, symbolHeight / 2)) + .addClass('highcharts-point') + .attr({ + zIndex: 3 + }).add(item.legendGroup); + }, + /** + * Get the series' symbol in the legend. This method should be overridable + * to create custom symbols through + * Highcharts.seriesTypes[type].prototype.drawLegendSymbols. + * + * @private + * @function Highcharts.LegendSymbolMixin.drawLineMarker + * + * @param {Highcharts.Legend} legend + * The legend object. + */ + drawLineMarker: function (legend) { + var options = this.options, markerOptions = options.marker, radius, legendSymbol, symbolWidth = legend.symbolWidth, symbolHeight = legend.symbolHeight, generalRadius = symbolHeight / 2, renderer = this.chart.renderer, legendItemGroup = this.legendGroup, verticalCenter = legend.baseline - + Math.round(legend.fontMetrics.b * 0.3), attr = {}; + // Draw the line + if (!this.chart.styledMode) { + attr = { + 'stroke-width': options.lineWidth || 0 + }; + if (options.dashStyle) { + attr.dashstyle = options.dashStyle; + } + } + this.legendLine = renderer + .path([ + 'M', + 0, + verticalCenter, + 'L', + symbolWidth, + verticalCenter + ]) + .addClass('highcharts-graph') + .attr(attr) + .add(legendItemGroup); + // Draw the marker + if (markerOptions && markerOptions.enabled !== false && symbolWidth) { + // Do not allow the marker to be larger than the symbolHeight + radius = Math.min(pick(markerOptions.radius, generalRadius), generalRadius); + // Restrict symbol markers size + if (this.symbol.indexOf('url') === 0) { + markerOptions = merge(markerOptions, { + width: symbolHeight, + height: symbolHeight + }); + radius = 0; + } + this.legendSymbol = legendSymbol = renderer.symbol(this.symbol, (symbolWidth / 2) - radius, verticalCenter - radius, 2 * radius, 2 * radius, markerOptions) + .addClass('highcharts-point') + .add(legendItemGroup); + legendSymbol.isMarker = true; + } + } + }; + + return H.LegendSymbolMixin; + }); + _registerModule(_modules, 'parts/Point.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (Highcharts, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Function callback when a series point is clicked. Return false to cancel the + * action. + * + * @callback Highcharts.PointClickCallbackFunction + * + * @param {Highcharts.Point} this + * The point where the event occured. + * + * @param {Highcharts.PointClickEventObject} event + * Event arguments. + */ + /** + * Common information for a click event on a series point. + * + * @interface Highcharts.PointClickEventObject + * @extends Highcharts.PointerEventObject + */ /** + * Clicked point. + * @name Highcharts.PointClickEventObject#point + * @type {Highcharts.Point} + */ + /** + * Configuration hash for the data label and tooltip formatters. + * + * @interface Highcharts.PointLabelObject + */ /** + * The point's current color. + * @name Highcharts.PointLabelObject#color + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined} + */ /** + * The point's current color index, used in styled mode instead of `color`. The + * color index is inserted in class names used for styling. + * @name Highcharts.PointLabelObject#colorIndex + * @type {number} + */ /** + * The name of the related point. + * @name Highcharts.PointLabelObject#key + * @type {string|undefined} + */ /** + * The percentage for related points in a stacked series or pies. + * @name Highcharts.PointLabelObject#percentage + * @type {number} + */ /** + * The related point. The point name, if defined, is available through + * `this.point.name`. + * @name Highcharts.PointLabelObject#point + * @type {Highcharts.Point} + */ /** + * The related series. The series name is available through `this.series.name`. + * @name Highcharts.PointLabelObject#series + * @type {Highcharts.Series} + */ /** + * The total of values in either a stack for stacked series, or a pie in a pie + * series. + * @name Highcharts.PointLabelObject#total + * @type {number|undefined} + */ /** + * For categorized axes this property holds the category name for the point. For + * other axes it holds the X value. + * @name Highcharts.PointLabelObject#x + * @type {number|string|undefined} + */ /** + * The y value of the point. + * @name Highcharts.PointLabelObject#y + * @type {number|undefined} + */ + /** + * Gets fired when the mouse leaves the area close to the point. + * + * @callback Highcharts.PointMouseOutCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {global.PointerEvent} event + * Event that occured. + */ + /** + * Gets fired when the mouse enters the area close to the point. + * + * @callback Highcharts.PointMouseOverCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {global.Event} event + * Event that occured. + */ + /** + * The generic point options for all series. + * + * In TypeScript you have to extend `PointOptionsObject` with an additional + * declaration to allow custom data options: + * + * ``` + * declare interface PointOptionsObject { + * customProperty: string; + * } + * ``` + * + * @interface Highcharts.PointOptionsObject + */ + /** + * Possible option types for a data point. + * + * @typedef {number|string|Array<(number|string)>|Highcharts.PointOptionsObject|null} Highcharts.PointOptionsType + */ + /** + * Gets fired when the point is removed using the `.remove()` method. + * + * @callback Highcharts.PointRemoveCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {global.Event} event + * Event that occured. + */ + /** + * Possible key values for the point state options. + * + * @typedef {"hover"|"inactive"|"normal"|"select"} Highcharts.PointStateValue + */ + /** + * Gets fired when the point is updated programmatically through the `.update()` + * method. + * + * @callback Highcharts.PointUpdateCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {Highcharts.PointUpdateEventObject} event + * Event that occured. + */ + /** + * Information about the update event. + * + * @interface Highcharts.PointUpdateEventObject + * @extends global.Event + */ /** + * Options data of the update event. + * @name Highcharts.PointUpdateEventObject#options + * @type {Highcharts.PointOptionsType} + */ + ''; // detach doclet above + var animObject = U.animObject, defined = U.defined, erase = U.erase, extend = U.extend, fireEvent = U.fireEvent, format = U.format, getNestedProperty = U.getNestedProperty, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, syncTimeout = U.syncTimeout, pick = U.pick, removeEvent = U.removeEvent, uniqueKey = U.uniqueKey; + var H = Highcharts; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The Point object. The point objects are generated from the `series.data` + * configuration objects or raw numbers. They can be accessed from the + * `Series.points` array. Other ways to instantiate points are through {@link + * Highcharts.Series#addPoint} or {@link Highcharts.Series#setData}. + * + * @class + * @name Highcharts.Point + */ + var Point = /** @class */ (function () { + function Point() { + /* * + * + * Properties + * + * */ + /** + * For categorized axes this property holds the category name for the + * point. For other axes it holds the X value. + * + * @name Highcharts.Point#category + * @type {string} + */ + this.category = void 0; + /** + * The point's current color index, used in styled mode instead of + * `color`. The color index is inserted in class names used for styling. + * + * @name Highcharts.Point#colorIndex + * @type {number} + */ + this.colorIndex = void 0; + this.formatPrefix = 'point'; + this.id = void 0; + this.isNull = false; + /** + * The name of the point. The name can be given as the first position of the + * point configuration array, or as a `name` property in the configuration: + * + * @example + * // Array config + * data: [ + * ['John', 1], + * ['Jane', 2] + * ] + * + * // Object config + * data: [{ + * name: 'John', + * y: 1 + * }, { + * name: 'Jane', + * y: 2 + * }] + * + * @name Highcharts.Point#name + * @type {string} + */ + this.name = void 0; + /** + * The point's options as applied in the initial configuration, or + * extended through `Point.update`. + * + * In TypeScript you have to extend `PointOptionsObject` via an + * additional interface to allow custom data options: + * + * ``` + * declare interface PointOptionsObject { + * customProperty: string; + * } + * ``` + * + * @name Highcharts.Point#options + * @type {Highcharts.PointOptionsObject} + */ + this.options = void 0; + /** + * The percentage for points in a stacked series or pies. + * + * @name Highcharts.Point#percentage + * @type {number|undefined} + */ + this.percentage = void 0; + this.selected = false; + /** + * The series object associated with the point. + * + * @name Highcharts.Point#series + * @type {Highcharts.Series} + */ + this.series = void 0; + /** + * The total of values in either a stack for stacked series, or a pie in a + * pie series. + * + * @name Highcharts.Point#total + * @type {number|undefined} + */ + this.total = void 0; + /** + * For certain series types, like pie charts, where individual points can + * be shown or hidden. + * + * @name Highcharts.Point#visible + * @type {boolean} + * @default true + */ + this.visible = true; + this.x = void 0; + } + /* * + * + * Functions + * + * */ + /** + * Animate SVG elements associated with the point. + * + * @private + * @function Highcharts.Point#animateBeforeDestroy + * @return {void} + */ + Point.prototype.animateBeforeDestroy = function () { + var point = this, animateParams = { x: point.startXPos, opacity: 0 }, isDataLabel, graphicalProps = point.getGraphicalProps(); + graphicalProps.singular.forEach(function (prop) { + isDataLabel = prop === 'dataLabel'; + point[prop] = point[prop].animate(isDataLabel ? { + x: point[prop].startXPos, + y: point[prop].startYPos, + opacity: 0 + } : animateParams); + }); + graphicalProps.plural.forEach(function (plural) { + point[plural].forEach(function (item) { + if (item.element) { + item.animate(extend({ x: point.startXPos }, (item.startYPos ? { + x: item.startXPos, + y: item.startYPos + } : {}))); + } + }); + }); + }; + /** + * Apply the options containing the x and y data and possible some extra + * properties. Called on point init or from point.update. + * + * @private + * @function Highcharts.Point#applyOptions + * + * @param {Highcharts.PointOptionsType} options + * The point options as defined in series.data. + * + * @param {number} [x] + * Optionally, the x value. + * + * @return {Highcharts.Point} + * The Point instance. + */ + Point.prototype.applyOptions = function (options, x) { + var point = this, series = point.series, pointValKey = series.options.pointValKey || series.pointValKey; + options = Point.prototype.optionsToObject.call(this, options); + // copy options directly to point + extend(point, options); + point.options = point.options ? extend(point.options, options) : options; + // Since options are copied into the Point instance, some accidental + // options must be shielded (#5681) + if (options.group) { + delete point.group; + } + if (options.dataLabels) { + delete point.dataLabels; + } + /** + * The y value of the point. + * @name Highcharts.Point#y + * @type {number|undefined} + */ + // For higher dimension series types. For instance, for ranges, point.y + // is mapped to point.low. + if (pointValKey) { + point.y = Point.prototype.getNestedProperty.call(point, pointValKey); + } + point.isNull = pick(point.isValid && !point.isValid(), point.x === null || !isNumber(point.y)); // #3571, check for NaN + point.formatPrefix = point.isNull ? 'null' : 'point'; // #9233, #10874 + // The point is initially selected by options (#5777) + if (point.selected) { + point.state = 'select'; + } + /** + * The x value of the point. + * @name Highcharts.Point#x + * @type {number} + */ + // If no x is set by now, get auto incremented value. All points must + // have an x value, however the y value can be null to create a gap in + // the series + if ('name' in point && + typeof x === 'undefined' && + series.xAxis && + series.xAxis.hasNames) { + point.x = series.xAxis.nameToX(point); + } + if (typeof point.x === 'undefined' && series) { + if (typeof x === 'undefined') { + point.x = series.autoIncrement(point); + } + else { + point.x = x; + } + } + return point; + }; + /** + * Destroy a point to clear memory. Its reference still stays in + * `series.data`. + * + * @private + * @function Highcharts.Point#destroy + * @return {void} + */ + Point.prototype.destroy = function () { + var point = this, series = point.series, chart = series.chart, dataSorting = series.options.dataSorting, hoverPoints = chart.hoverPoints, globalAnimation = point.series.chart.renderer.globalAnimation, animation = animObject(globalAnimation), prop; + /** + * Allow to call after animation. + * @private + */ + function destroyPoint() { + // Remove all events and elements + if (point.graphic || point.dataLabel || point.dataLabels) { + removeEvent(point); + point.destroyElements(); + } + for (prop in point) { // eslint-disable-line guard-for-in + point[prop] = null; + } + } + if (point.legendItem) { // pies have legend items + chart.legend.destroyItem(point); + } + if (hoverPoints) { + point.setState(); + erase(hoverPoints, point); + if (!hoverPoints.length) { + chart.hoverPoints = null; + } + } + if (point === chart.hoverPoint) { + point.onMouseOut(); + } + // Remove properties after animation + if (!dataSorting || !dataSorting.enabled) { + destroyPoint(); + } + else { + this.animateBeforeDestroy(); + syncTimeout(destroyPoint, animation.duration); + } + chart.pointCount--; + }; + /** + * Destroy SVG elements associated with the point. + * + * @private + * @function Highcharts.Point#destroyElements + * @param {Highcharts.Dictionary} [kinds] + * @return {void} + */ + Point.prototype.destroyElements = function (kinds) { + var point = this, props = point.getGraphicalProps(kinds); + props.singular.forEach(function (prop) { + point[prop] = point[prop].destroy(); + }); + props.plural.forEach(function (plural) { + point[plural].forEach(function (item) { + if (item.element) { + item.destroy(); + } + }); + delete point[plural]; + }); + }; + /** + * Fire an event on the Point object. + * + * @private + * @function Highcharts.Point#firePointEvent + * + * @param {string} eventType + * Type of the event. + * + * @param {Highcharts.Dictionary|Event} [eventArgs] + * Additional event arguments. + * + * @param {Highcharts.EventCallbackFunction|Function} [defaultFunction] + * Default event handler. + * + * @fires Highcharts.Point#event:* + */ + Point.prototype.firePointEvent = function (eventType, eventArgs, defaultFunction) { + var point = this, series = this.series, seriesOptions = series.options; + // load event handlers on demand to save time on mouseover/out + if (seriesOptions.point.events[eventType] || + (point.options && + point.options.events && + point.options.events[eventType])) { + point.importEvents(); + } + // add default handler if in selection mode + if (eventType === 'click' && seriesOptions.allowPointSelect) { + defaultFunction = function (event) { + // Control key is for Windows, meta (= Cmd key) for Mac, Shift + // for Opera. + if (point.select) { // #2911 + point.select(null, event.ctrlKey || event.metaKey || event.shiftKey); + } + }; + } + fireEvent(point, eventType, eventArgs, defaultFunction); + }; + /** + * Get the CSS class names for individual points. Used internally where the + * returned value is set on every point. + * + * @function Highcharts.Point#getClassName + * + * @return {string} + * The class names. + */ + Point.prototype.getClassName = function () { + var point = this; + return 'highcharts-point' + + (point.selected ? ' highcharts-point-select' : '') + + (point.negative ? ' highcharts-negative' : '') + + (point.isNull ? ' highcharts-null-point' : '') + + (typeof point.colorIndex !== 'undefined' ? + ' highcharts-color-' + point.colorIndex : '') + + (point.options.className ? ' ' + point.options.className : '') + + (point.zone && point.zone.className ? ' ' + + point.zone.className.replace('highcharts-negative', '') : ''); + }; + /** + * Get props of all existing graphical point elements. + * + * @private + * @function Highcharts.Point#getGraphicalProps + * @param {Highcharts.Dictionary} [kinds] + * @return {Highcharts.PointGraphicalProps} + */ + Point.prototype.getGraphicalProps = function (kinds) { + var point = this, props = [], prop, i, graphicalProps = { singular: [], plural: [] }; + kinds = kinds || { graphic: 1, dataLabel: 1 }; + if (kinds.graphic) { + props.push('graphic', 'shadowGroup'); + } + if (kinds.dataLabel) { + props.push('dataLabel', 'dataLabelUpper', 'connector'); + } + i = props.length; + while (i--) { + prop = props[i]; + if (point[prop]) { + graphicalProps.singular.push(prop); + } + } + ['dataLabel', 'connector'].forEach(function (prop) { + var plural = prop + 's'; + if (kinds[prop] && point[plural]) { + graphicalProps.plural.push(plural); + } + }); + return graphicalProps; + }; + /** + * Return the configuration hash needed for the data label and tooltip + * formatters. + * + * @function Highcharts.Point#getLabelConfig + * + * @return {Highcharts.PointLabelObject} + * Abstract object used in formatters and formats. + */ + Point.prototype.getLabelConfig = function () { + return { + x: this.category, + y: this.y, + color: this.color, + colorIndex: this.colorIndex, + key: this.name || this.category, + series: this.series, + point: this, + percentage: this.percentage, + total: this.total || this.stackTotal + }; + }; + /** + * Returns the value of the point property for a given value. + * @private + */ + Point.prototype.getNestedProperty = function (key) { + if (!key) { + return; + } + if (key.indexOf('custom.') === 0) { + return getNestedProperty(key, this.options); + } + return this[key]; + }; + /** + * In a series with `zones`, return the zone that the point belongs to. + * + * @function Highcharts.Point#getZone + * + * @return {Highcharts.SeriesZonesOptionsObject} + * The zone item. + */ + Point.prototype.getZone = function () { + var series = this.series, zones = series.zones, zoneAxis = series.zoneAxis || 'y', i = 0, zone; + zone = zones[i]; + while (this[zoneAxis] >= zone.value) { + zone = zones[++i]; + } + // For resetting or reusing the point (#8100) + if (!this.nonZonedColor) { + this.nonZonedColor = this.color; + } + if (zone && zone.color && !this.options.color) { + this.color = zone.color; + } + else { + this.color = this.nonZonedColor; + } + return zone; + }; + /** + * Utility to check if point has new shape type. Used in column series and + * all others that are based on column series. + * + * @return boolean|undefined + */ + Point.prototype.hasNewShapeType = function () { + var point = this; + var oldShapeType = point.graphic && + (point.graphic.symbolName || point.graphic.element.nodeName); + return oldShapeType !== this.shapeType; + }; + /** + * Initialize the point. Called internally based on the `series.data` + * option. + * + * @function Highcharts.Point#init + * + * @param {Highcharts.Series} series + * The series object containing this point. + * + * @param {Highcharts.PointOptionsType} options + * The data in either number, array or object format. + * + * @param {number} [x] + * Optionally, the X value of the point. + * + * @return {Highcharts.Point} + * The Point instance. + * + * @fires Highcharts.Point#event:afterInit + */ + Point.prototype.init = function (series, options, x) { + this.series = series; + this.applyOptions(options, x); + // Add a unique ID to the point if none is assigned + this.id = defined(this.id) ? this.id : uniqueKey(); + this.resolveColor(); + series.chart.pointCount++; + fireEvent(this, 'afterInit'); + return this; + }; + /** + * Transform number or array configs into objects. Also called for object + * configs. Used internally to unify the different configuration formats for + * points. For example, a simple number `10` in a line series will be + * transformed to `{ y: 10 }`, and an array config like `[1, 10]` in a + * scatter series will be transformed to `{ x: 1, y: 10 }`. + * + * @function Highcharts.Point#optionsToObject + * + * @param {Highcharts.PointOptionsType} options + * The input option. + * + * @return {Highcharts.Dictionary<*>} + * Transformed options. + */ + Point.prototype.optionsToObject = function (options) { + var ret = {}, series = this.series, keys = series.options.keys, pointArrayMap = keys || series.pointArrayMap || ['y'], valueCount = pointArrayMap.length, firstItemType, i = 0, j = 0; + if (isNumber(options) || options === null) { + ret[pointArrayMap[0]] = options; + } + else if (isArray(options)) { + // with leading x value + if (!keys && options.length > valueCount) { + firstItemType = typeof options[0]; + if (firstItemType === 'string') { + ret.name = options[0]; + } + else if (firstItemType === 'number') { + ret.x = options[0]; + } + i++; + } + while (j < valueCount) { + // Skip undefined positions for keys + if (!keys || typeof options[i] !== 'undefined') { + if (pointArrayMap[j].indexOf('.') > 0) { + // Handle nested keys, e.g. ['color.pattern.image'] + // Avoid function call unless necessary. + Point.prototype.setNestedProperty(ret, options[i], pointArrayMap[j]); + } + else { + ret[pointArrayMap[j]] = options[i]; + } + } + i++; + j++; + } + } + else if (typeof options === 'object') { + ret = options; + // This is the fastest way to detect if there are individual point + // dataLabels that need to be considered in drawDataLabels. These + // can only occur in object configs. + if (options.dataLabels) { + series._hasPointLabels = true; + } + // Same approach as above for markers + if (options.marker) { + series._hasPointMarkers = true; + } + } + return ret; + }; + /** + * @private + * @function Highcharts.Point#resolveColor + * @return {void} + */ + Point.prototype.resolveColor = function () { + var series = this.series, colors, optionsChart = series.chart.options.chart, colorCount = optionsChart.colorCount, styledMode = series.chart.styledMode, colorIndex; + // remove points nonZonedColor for later recalculation + delete this.nonZonedColor; + /** + * The point's current color. + * + * @name Highcharts.Point#color + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined} + */ + if (!styledMode && !this.options.color) { + this.color = series.color; // #3445 + } + if (series.options.colorByPoint) { + if (!styledMode) { + colors = series.options.colors || series.chart.options.colors; + this.color = this.color || colors[series.colorCounter]; + colorCount = colors.length; + } + colorIndex = series.colorCounter; + series.colorCounter++; + // loop back to zero + if (series.colorCounter === colorCount) { + series.colorCounter = 0; + } + } + else { + colorIndex = series.colorIndex; + } + this.colorIndex = pick(this.colorIndex, colorIndex); + }; + /** + * Set a value in an object, on the property defined by key. The key + * supports nested properties using dot notation. The function modifies the + * input object and does not make a copy. + * + * @function Highcharts.Point#setNestedProperty + * + * @param {T} object + * The object to set the value on. + * + * @param {*} value + * The value to set. + * + * @param {string} key + * Key to the property to set. + * + * @return {T} + * The modified object. + */ + Point.prototype.setNestedProperty = function (object, value, key) { + var nestedKeys = key.split('.'); + nestedKeys.reduce(function (result, key, i, arr) { + var isLastKey = arr.length - 1 === i; + result[key] = (isLastKey ? + value : + isObject(result[key], true) ? + result[key] : + {}); + return result[key]; + }, object); + return object; + }; + /** + * Extendable method for formatting each point's tooltip line. + * + * @function Highcharts.Point#tooltipFormatter + * + * @param {string} pointFormat + * The point format. + * + * @return {string} + * A string to be concatenated in to the common tooltip text. + */ + Point.prototype.tooltipFormatter = function (pointFormat) { + // Insert options for valueDecimals, valuePrefix, and valueSuffix + var series = this.series, seriesTooltipOptions = series.tooltipOptions, valueDecimals = pick(seriesTooltipOptions.valueDecimals, ''), valuePrefix = seriesTooltipOptions.valuePrefix || '', valueSuffix = seriesTooltipOptions.valueSuffix || ''; + // Replace default point style with class name + if (series.chart.styledMode) { + pointFormat = + series.chart.tooltip.styledModeFormat(pointFormat); + } + // Loop over the point array map and replace unformatted values with + // sprintf formatting markup + (series.pointArrayMap || ['y']).forEach(function (key) { + key = '{point.' + key; // without the closing bracket + if (valuePrefix || valueSuffix) { + pointFormat = pointFormat.replace(RegExp(key + '}', 'g'), valuePrefix + key + '}' + valueSuffix); + } + pointFormat = pointFormat.replace(RegExp(key + '}', 'g'), key + ':,.' + valueDecimals + 'f}'); + }); + return format(pointFormat, { + point: this, + series: this.series + }, series.chart); + }; + return Point; + }()); + H.Point = Point; + + return H.Point; + }); + _registerModule(_modules, 'parts/Series.js', [_modules['mixins/legend-symbol.js'], _modules['parts/Globals.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js']], function (LegendSymbolMixin, H, Point, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * This is a placeholder type of the possible series options for + * [Highcharts](../highcharts/series), [Highstock](../highstock/series), + * [Highmaps](../highmaps/series), and [Gantt](../gantt/series). + * + * In TypeScript is this dynamically generated to reference all possible types + * of series options. + * + * @ignore-declaration + * @typedef {Highcharts.SeriesOptions|Highcharts.Dictionary<*>} Highcharts.SeriesOptionsType + */ + /** + * Options for `dataSorting`. + * + * @interface Highcharts.DataSortingOptionsObject + * @since 8.0.0 + */ /** + * Enable or disable data sorting for the series. + * @name Highcharts.DataSortingOptionsObject#enabled + * @type {boolean|undefined} + */ /** + * Whether to allow matching points by name in an update. + * @name Highcharts.DataSortingOptionsObject#matchByName + * @type {boolean|undefined} + */ /** + * Determines what data value should be used to sort by. + * @name Highcharts.DataSortingOptionsObject#sortKey + * @type {string|undefined} + */ + /** + * Function callback when a series has been animated. + * + * @callback Highcharts.SeriesAfterAnimateCallbackFunction + * + * @param {Highcharts.Series} this + * The series where the event occured. + * + * @param {Highcharts.SeriesAfterAnimateEventObject} event + * Event arguments. + */ + /** + * Event information regarding completed animation of a series. + * + * @interface Highcharts.SeriesAfterAnimateEventObject + */ /** + * Animated series. + * @name Highcharts.SeriesAfterAnimateEventObject#target + * @type {Highcharts.Series} + */ /** + * Event type. + * @name Highcharts.SeriesAfterAnimateEventObject#type + * @type {"afterAnimate"} + */ + /** + * Function callback when the checkbox next to the series' name in the legend is + * clicked. + * + * @callback Highcharts.SeriesCheckboxClickCallbackFunction + * + * @param {Highcharts.Series} this + * The series where the event occured. + * + * @param {Highcharts.SeriesCheckboxClickEventObject} event + * Event arguments. + */ + /** + * Event information regarding check of a series box. + * + * @interface Highcharts.SeriesCheckboxClickEventObject + */ /** + * Whether the box has been checked. + * @name Highcharts.SeriesCheckboxClickEventObject#checked + * @type {boolean} + */ /** + * Related series. + * @name Highcharts.SeriesCheckboxClickEventObject#item + * @type {Highcharts.Series} + */ /** + * Related series. + * @name Highcharts.SeriesCheckboxClickEventObject#target + * @type {Highcharts.Series} + */ /** + * Event type. + * @name Highcharts.SeriesCheckboxClickEventObject#type + * @type {"checkboxClick"} + */ + /** + * Function callback when a series is clicked. Return false to cancel toogle + * actions. + * + * @callback Highcharts.SeriesClickCallbackFunction + * + * @param {Highcharts.Series} this + * The series where the event occured. + * + * @param {Highcharts.SeriesClickEventObject} event + * Event arguments. + */ + /** + * Common information for a click event on a series. + * + * @interface Highcharts.SeriesClickEventObject + * @extends global.Event + */ /** + * Nearest point on the graph. + * @name Highcharts.SeriesClickEventObject#point + * @type {Highcharts.Point} + */ + /** + * Gets fired when the series is hidden after chart generation time, either by + * clicking the legend item or by calling `.hide()`. + * + * @callback Highcharts.SeriesHideCallbackFunction + * + * @param {Highcharts.Series} this + * The series where the event occured. + * + * @param {global.Event} event + * The event that occured. + */ + /** + * The SVG value used for the `stroke-linecap` and `stroke-linejoin` of a line + * graph. + * + * @typedef {"butt"|"round"|"square"|string} Highcharts.SeriesLinecapValue + */ + /** + * Gets fired when the legend item belonging to the series is clicked. The + * default action is to toggle the visibility of the series. This can be + * prevented by returning `false` or calling `event.preventDefault()`. + * + * @callback Highcharts.SeriesLegendItemClickCallbackFunction + * + * @param {Highcharts.Series} this + * The series where the event occured. + * + * @param {Highcharts.SeriesLegendItemClickEventObject} event + * The event that occured. + */ + /** + * Information about the event. + * + * @interface Highcharts.SeriesLegendItemClickEventObject + */ /** + * Related browser event. + * @name Highcharts.SeriesLegendItemClickEventObject#browserEvent + * @type {global.PointerEvent} + */ /** + * Prevent the default action of toggle the visibility of the series. + * @name Highcharts.SeriesLegendItemClickEventObject#preventDefault + * @type {Function} + */ /** + * Related series. + * @name Highcharts.SeriesCheckboxClickEventObject#target + * @type {Highcharts.Series} + */ /** + * Event type. + * @name Highcharts.SeriesCheckboxClickEventObject#type + * @type {"checkboxClick"} + */ + /** + * Gets fired when the mouse leaves the graph. + * + * @callback Highcharts.SeriesMouseOutCallbackFunction + * + * @param {Highcharts.Series} this + * Series where the event occured. + * + * @param {global.PointerEvent} event + * Event that occured. + */ + /** + * Gets fired when the mouse enters the graph. + * + * @callback Highcharts.SeriesMouseOverCallbackFunction + * + * @param {Highcharts.Series} this + * Series where the event occured. + * + * @param {global.PointerEvent} event + * Event that occured. + */ + /** + * Translation and scale for the plot area of a series. + * + * @interface Highcharts.SeriesPlotBoxObject + */ /** + * @name Highcharts.SeriesPlotBoxObject#scaleX + * @type {number} + */ /** + * @name Highcharts.SeriesPlotBoxObject#scaleY + * @type {number} + */ /** + * @name Highcharts.SeriesPlotBoxObject#translateX + * @type {number} + */ /** + * @name Highcharts.SeriesPlotBoxObject#translateY + * @type {number} + */ + /** + * Gets fired when the series is shown after chart generation time, either by + * clicking the legend item or by calling `.show()`. + * + * @callback Highcharts.SeriesShowCallbackFunction + * + * @param {Highcharts.Series} this + * Series where the event occured. + * + * @param {global.Event} event + * Event that occured. + */ + /** + * Possible key values for the series state options. + * + * @typedef {"hover"|"inactive"|"normal"|"select"} Highcharts.SeriesStateValue + */ + ''; // detach doclets above + var addEvent = U.addEvent, animObject = U.animObject, arrayMax = U.arrayMax, arrayMin = U.arrayMin, clamp = U.clamp, correctFloat = U.correctFloat, defined = U.defined, erase = U.erase, error = U.error, extend = U.extend, find = U.find, fireEvent = U.fireEvent, getNestedProperty = U.getNestedProperty, isArray = U.isArray, isFunction = U.isFunction, isNumber = U.isNumber, isString = U.isString, merge = U.merge, objectEach = U.objectEach, pick = U.pick, removeEvent = U.removeEvent, seriesType = U.seriesType, splat = U.splat, syncTimeout = U.syncTimeout; + var defaultOptions = H.defaultOptions, defaultPlotOptions = H.defaultPlotOptions, seriesTypes = H.seriesTypes, SVGElement = H.SVGElement, win = H.win; + /** + * This is the base series prototype that all other series types inherit from. + * A new series is initialized either through the + * [series](https://api.highcharts.com/highcharts/series) + * option structure, or after the chart is initialized, through + * {@link Highcharts.Chart#addSeries}. + * + * The object can be accessed in a number of ways. All series and point event + * handlers give a reference to the `series` object. The chart object has a + * {@link Highcharts.Chart#series|series} property that is a collection of all + * the chart's series. The point objects and axis objects also have the same + * reference. + * + * Another way to reference the series programmatically is by `id`. Add an id + * in the series configuration options, and get the series object by + * {@link Highcharts.Chart#get}. + * + * Configuration options for the series are given in three levels. Options for + * all series in a chart are given in the + * [plotOptions.series](https://api.highcharts.com/highcharts/plotOptions.series) + * object. Then options for all series of a specific type + * are given in the plotOptions of that type, for example `plotOptions.line`. + * Next, options for one single series are given in the series array, or as + * arguments to `chart.addSeries`. + * + * The data in the series is stored in various arrays. + * + * - First, `series.options.data` contains all the original config options for + * each point whether added by options or methods like `series.addPoint`. + * + * - Next, `series.data` contains those values converted to points, but in case + * the series data length exceeds the `cropThreshold`, or if the data is + * grouped, `series.data` doesn't contain all the points. It only contains the + * points that have been created on demand. + * + * - Then there's `series.points` that contains all currently visible point + * objects. In case of cropping, the cropped-away points are not part of this + * array. The `series.points` array starts at `series.cropStart` compared to + * `series.data` and `series.options.data`. If however the series data is + * grouped, these can't be correlated one to one. + * + * - `series.xData` and `series.processedXData` contain clean x values, + * equivalent to `series.data` and `series.points`. + * + * - `series.yData` and `series.processedYData` contain clean y values, + * equivalent to `series.data` and `series.points`. + * + * @class + * @name Highcharts.Series + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @param {Highcharts.SeriesOptionsType|object} options + * The series options. + */ /** + * The line series is the base type and is therefor the series base prototype. + * + * @private + * @class + * @name Highcharts.seriesTypes.line + * + * @augments Highcharts.Series + */ + H.Series = seriesType('line', + /** + * Series options for specific data and the data itself. In TypeScript you + * have to cast the series options to specific series types, to get all + * possible options for a series. + * + * @example + * // TypeScript example + * Highcharts.chart('container', { + * series: [{ + * color: '#06C', + * data: [[0, 1], [2, 3]] + * } as Highcharts.SeriesLineOptions ] + * }); + * + * @type {Array<*>} + * @apioption series + */ + /** + * An id for the series. This can be used after render time to get a pointer + * to the series object through `chart.get()`. + * + * @sample {highcharts} highcharts/plotoptions/series-id/ + * Get series by id + * + * @type {string} + * @since 1.2.0 + * @apioption series.id + */ + /** + * The index of the series in the chart, affecting the internal index in the + * `chart.series` array, the visible Z index as well as the order in the + * legend. + * + * @type {number} + * @since 2.3.0 + * @apioption series.index + */ + /** + * The sequential index of the series in the legend. + * + * @see [legend.reversed](#legend.reversed), + * [yAxis.reversedStacks](#yAxis.reversedStacks) + * + * @sample {highcharts|highstock} highcharts/series/legendindex/ + * Legend in opposite order + * + * @type {number} + * @apioption series.legendIndex + */ + /** + * The name of the series as shown in the legend, tooltip etc. + * + * @sample {highcharts} highcharts/series/name/ + * Series name + * @sample {highmaps} maps/demo/category-map/ + * Series name + * + * @type {string} + * @apioption series.name + */ + /** + * This option allows grouping series in a stacked chart. The stack option + * can be a string or anything else, as long as the grouped series' stack + * options match each other after conversion into a string. + * + * @sample {highcharts} highcharts/series/stack/ + * Stacked and grouped columns + * + * @type {number|string} + * @since 2.1 + * @product highcharts highstock + * @apioption series.stack + */ + /** + * The type of series, for example `line` or `column`. By default, the + * series type is inherited from [chart.type](#chart.type), so unless the + * chart is a combination of series types, there is no need to set it on the + * series level. + * + * @sample {highcharts} highcharts/series/type/ + * Line and column in the same chart + * @sample highcharts/series/type-dynamic/ + * Dynamic types with button selector + * @sample {highmaps} maps/demo/mapline-mappoint/ + * Multiple types in the same map + * + * @type {string} + * @apioption series.type + */ + /** + * When using dual or multiple x axes, this number defines which xAxis the + * particular series is connected to. It refers to either the + * {@link #xAxis.id|axis id} + * or the index of the axis in the xAxis array, with 0 being the first. + * + * @type {number|string} + * @default 0 + * @product highcharts highstock + * @apioption series.xAxis + */ + /** + * When using dual or multiple y axes, this number defines which yAxis the + * particular series is connected to. It refers to either the + * {@link #yAxis.id|axis id} + * or the index of the axis in the yAxis array, with 0 being the first. + * + * @sample {highcharts} highcharts/series/yaxis/ + * Apply the column series to the secondary Y axis + * + * @type {number|string} + * @default 0 + * @product highcharts highstock + * @apioption series.yAxis + */ + /** + * Define the visual z index of the series. + * + * @sample {highcharts} highcharts/plotoptions/series-zindex-default/ + * With no z index, the series defined last are on top + * @sample {highcharts} highcharts/plotoptions/series-zindex/ + * With a z index, the series with the highest z index is on top + * @sample {highstock} highcharts/plotoptions/series-zindex-default/ + * With no z index, the series defined last are on top + * @sample {highstock} highcharts/plotoptions/series-zindex/ + * With a z index, the series with the highest z index is on top + * + * @type {number} + * @product highcharts highstock + * @apioption series.zIndex + */ + null, + /** + * General options for all series types. + * + * @optionparent plotOptions.series + */ + { + /** + * The SVG value used for the `stroke-linecap` and `stroke-linejoin` + * of a line graph. Round means that lines are rounded in the ends and + * bends. + * + * @type {Highcharts.SeriesLinecapValue} + * @default round + * @since 3.0.7 + * @apioption plotOptions.line.linecap + */ + /** + * Pixel width of the graph line. + * + * @see In styled mode, the line stroke-width can be set with the + * `.highcharts-graph` class name. + * + * @sample {highcharts} highcharts/plotoptions/series-linewidth-general/ + * On all series + * @sample {highcharts} highcharts/plotoptions/series-linewidth-specific/ + * On one single series + * + * @product highcharts highstock + * + * @private + */ + lineWidth: 2, + /** + * For some series, there is a limit that shuts down initial animation + * by default when the total number of points in the chart is too high. + * For example, for a column chart and its derivatives, animation does + * not run if there is more than 250 points totally. To disable this + * cap, set `animationLimit` to `Infinity`. + * + * @type {number} + * @apioption plotOptions.series.animationLimit + */ + /** + * Allow this series' points to be selected by clicking on the graphic + * (columns, point markers, pie slices, map areas etc). + * + * The selected points can be handled by point select and unselect + * events, or collectively by the [getSelectedPoints + * ](/class-reference/Highcharts.Chart#getSelectedPoints) function. + * + * And alternative way of selecting points is through dragging. + * + * @sample {highcharts} highcharts/plotoptions/series-allowpointselect-line/ + * Line + * @sample {highcharts} highcharts/plotoptions/series-allowpointselect-column/ + * Column + * @sample {highcharts} highcharts/plotoptions/series-allowpointselect-pie/ + * Pie + * @sample {highcharts} highcharts/chart/events-selection-points/ + * Select a range of points through a drag selection + * @sample {highmaps} maps/plotoptions/series-allowpointselect/ + * Map area + * @sample {highmaps} maps/plotoptions/mapbubble-allowpointselect/ + * Map bubble + * + * @since 1.2.0 + * + * @private + */ + allowPointSelect: false, + /** + * When true, each point or column edge is rounded to its nearest pixel + * in order to render sharp on screen. In some cases, when there are a + * lot of densely packed columns, this leads to visible difference + * in column widths or distance between columns. In these cases, + * setting `crisp` to `false` may look better, even though each column + * is rendered blurry. + * + * @sample {highcharts} highcharts/plotoptions/column-crisp-false/ + * Crisp is false + * + * @since 5.0.10 + * @product highcharts highstock gantt + * + * @private + */ + crisp: true, + /** + * If true, a checkbox is displayed next to the legend item to allow + * selecting the series. The state of the checkbox is determined by + * the `selected` option. + * + * @productdesc {highmaps} + * Note that if a `colorAxis` is defined, the color axis is represented + * in the legend, not the series. + * + * @sample {highcharts} highcharts/plotoptions/series-showcheckbox-true/ + * Show select box + * + * @since 1.2.0 + * + * @private + */ + showCheckbox: false, + /** + * Enable or disable the initial animation when a series is displayed. + * The animation can also be set as a configuration object. Please + * note that this option only applies to the initial animation of the + * series itself. For other animations, see [chart.animation]( + * #chart.animation) and the animation parameter under the API methods. + * The following properties are supported: + * + * - `duration`: The duration of the animation in milliseconds. + * + * - `easing`: Can be a string reference to an easing function set on + * the `Math` object or a function. See the _Custom easing function_ + * demo below. + * + * Due to poor performance, animation is disabled in old IE browsers + * for several chart types. + * + * @sample {highcharts} highcharts/plotoptions/series-animation-disabled/ + * Animation disabled + * @sample {highcharts} highcharts/plotoptions/series-animation-slower/ + * Slower animation + * @sample {highcharts} highcharts/plotoptions/series-animation-easing/ + * Custom easing function + * @sample {highstock} stock/plotoptions/animation-slower/ + * Slower animation + * @sample {highstock} stock/plotoptions/animation-easing/ + * Custom easing function + * @sample {highmaps} maps/plotoptions/series-animation-true/ + * Animation enabled on map series + * @sample {highmaps} maps/plotoptions/mapbubble-animation-false/ + * Disabled on mapbubble series + * + * @type {boolean|Highcharts.AnimationOptionsObject} + * @default {highcharts} true + * @default {highstock} true + * @default {highmaps} false + * + * @private + */ + animation: { + /** @internal */ + duration: 1000 + }, + /** + * An additional class name to apply to the series' graphical elements. + * This option does not replace default class names of the graphical + * element. + * + * @type {string} + * @since 5.0.0 + * @apioption plotOptions.series.className + */ + /** + * Disable this option to allow series rendering in the whole plotting + * area. + * + * **Note:** Clipping should be always enabled when + * [chart.zoomType](#chart.zoomType) is set + * + * @sample {highcharts} highcharts/plotoptions/series-clip/ + * Disabled clipping + * + * @default true + * @type {boolean} + * @since 3.0.0 + * @apioption plotOptions.series.clip + */ + /** + * The main color of the series. In line type series it applies to the + * line and the point markers unless otherwise specified. In bar type + * series it applies to the bars unless a color is specified per point. + * The default value is pulled from the `options.colors` array. + * + * In styled mode, the color can be defined by the + * [colorIndex](#plotOptions.series.colorIndex) option. Also, the series + * color can be set with the `.highcharts-series`, + * `.highcharts-color-{n}`, `.highcharts-{type}-series` or + * `.highcharts-series-{n}` class, or individual classes given by the + * `className` option. + * + * @productdesc {highmaps} + * In maps, the series color is rarely used, as most choropleth maps use + * the color to denote the value of each point. The series color can + * however be used in a map with multiple series holding categorized + * data. + * + * @sample {highcharts} highcharts/plotoptions/series-color-general/ + * General plot option + * @sample {highcharts} highcharts/plotoptions/series-color-specific/ + * One specific series + * @sample {highcharts} highcharts/plotoptions/series-color-area/ + * Area color + * @sample {highcharts} highcharts/series/infographic/ + * Pattern fill + * @sample {highmaps} maps/demo/category-map/ + * Category map by multiple series + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.series.color + */ + /** + * Styled mode only. A specific color index to use for the series, so + * its graphic representations are given the class name + * `highcharts-color-{n}`. + * + * @type {number} + * @since 5.0.0 + * @apioption plotOptions.series.colorIndex + */ + /** + * Whether to connect a graph line across null points, or render a gap + * between the two points on either side of the null. + * + * @sample {highcharts} highcharts/plotoptions/series-connectnulls-false/ + * False by default + * @sample {highcharts} highcharts/plotoptions/series-connectnulls-true/ + * True + * + * @type {boolean} + * @default false + * @product highcharts highstock + * @apioption plotOptions.series.connectNulls + */ + /** + * You can set the cursor to "pointer" if you have click events attached + * to the series, to signal to the user that the points and lines can + * be clicked. + * + * In styled mode, the series cursor can be set with the same classes + * as listed under [series.color](#plotOptions.series.color). + * + * @sample {highcharts} highcharts/plotoptions/series-cursor-line/ + * On line graph + * @sample {highcharts} highcharts/plotoptions/series-cursor-column/ + * On columns + * @sample {highcharts} highcharts/plotoptions/series-cursor-scatter/ + * On scatter markers + * @sample {highstock} stock/plotoptions/cursor/ + * Pointer on a line graph + * @sample {highmaps} maps/plotoptions/series-allowpointselect/ + * Map area + * @sample {highmaps} maps/plotoptions/mapbubble-allowpointselect/ + * Map bubble + * + * @type {string|Highcharts.CursorValue} + * @apioption plotOptions.series.cursor + */ + /** + * A reserved subspace to store options and values for customized + * functionality. Here you can add additional data for your own event + * callbacks and formatter callbacks. + * + * @sample {highcharts} highcharts/point/custom/ + * Point and series with custom data + * + * @type {Highcharts.Dictionary<*>} + * @apioption plotOptions.series.custom + */ + /** + * Name of the dash style to use for the graph, or for some series types + * the outline of each shape. + * + * In styled mode, the + * [stroke dash-array](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/css/series-dashstyle/) + * can be set with the same classes as listed under + * [series.color](#plotOptions.series.color). + * + * @sample {highcharts} highcharts/plotoptions/series-dashstyle-all/ + * Possible values demonstrated + * @sample {highcharts} highcharts/plotoptions/series-dashstyle/ + * Chart suitable for printing in black and white + * @sample {highstock} highcharts/plotoptions/series-dashstyle-all/ + * Possible values demonstrated + * @sample {highmaps} highcharts/plotoptions/series-dashstyle-all/ + * Possible values demonstrated + * @sample {highmaps} maps/plotoptions/series-dashstyle/ + * Dotted borders on a map + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 2.1 + * @apioption plotOptions.series.dashStyle + */ + /** + * A description of the series to add to the screen reader information + * about the series. + * + * @type {string} + * @since 5.0.0 + * @requires modules/accessibility + * @apioption plotOptions.series.description + */ + /** + * Options for the series data sorting. + * + * @type {Highcharts.DataSortingOptionsObject} + * @since 8.0.0 + * @product highcharts highstock + * @apioption plotOptions.series.dataSorting + */ + /** + * Enable or disable data sorting for the series. Use [xAxis.reversed]( + * #xAxis.reversed) to change the sorting order. + * + * @sample {highcharts} highcharts/datasorting/animation/ + * Data sorting in scatter-3d + * @sample {highcharts} highcharts/datasorting/labels-animation/ + * Axis labels animation + * @sample {highcharts} highcharts/datasorting/dependent-sorting/ + * Dependent series sorting + * @sample {highcharts} highcharts/datasorting/independent-sorting/ + * Independent series sorting + * + * @type {boolean} + * @since 8.0.0 + * @apioption plotOptions.series.dataSorting.enabled + */ + /** + * Whether to allow matching points by name in an update. If this option + * is disabled, points will be matched by order. + * + * @sample {highcharts} highcharts/datasorting/match-by-name/ + * Enabled match by name + * + * @type {boolean} + * @since 8.0.0 + * @apioption plotOptions.series.dataSorting.matchByName + */ + /** + * Determines what data value should be used to sort by. + * + * @sample {highcharts} highcharts/datasorting/sort-key/ + * Sort key as `z` value + * + * @type {string} + * @since 8.0.0 + * @default y + * @apioption plotOptions.series.dataSorting.sortKey + */ + /** + * Enable or disable the mouse tracking for a specific series. This + * includes point tooltips and click events on graphs and points. For + * large datasets it improves performance. + * + * @sample {highcharts} highcharts/plotoptions/series-enablemousetracking-false/ + * No mouse tracking + * @sample {highmaps} maps/plotoptions/series-enablemousetracking-false/ + * No mouse tracking + * + * @type {boolean} + * @default true + * @apioption plotOptions.series.enableMouseTracking + */ + /** + * Whether to use the Y extremes of the total chart width or only the + * zoomed area when zooming in on parts of the X axis. By default, the + * Y axis adjusts to the min and max of the visible data. Cartesian + * series only. + * + * @type {boolean} + * @default false + * @since 4.1.6 + * @product highcharts highstock gantt + * @apioption plotOptions.series.getExtremesFromAll + */ + /** + * An array specifying which option maps to which key in the data point + * array. This makes it convenient to work with unstructured data arrays + * from different sources. + * + * @see [series.data](#series.line.data) + * + * @sample {highcharts|highstock} highcharts/series/data-keys/ + * An extended data array with keys + * @sample {highcharts|highstock} highcharts/series/data-nested-keys/ + * Nested keys used to access object properties + * + * @type {Array} + * @since 4.1.6 + * @apioption plotOptions.series.keys + */ + /** + * The line cap used for line ends and line joins on the graph. + * + * @type {Highcharts.SeriesLinecapValue} + * @default round + * @product highcharts highstock + * @apioption plotOptions.series.linecap + */ + /** + * The [id](#series.id) of another series to link to. Additionally, + * the value can be ":previous" to link to the previous series. When + * two series are linked, only the first one appears in the legend. + * Toggling the visibility of this also toggles the linked series. + * + * If master series uses data sorting and linked series does not have + * its own sorting definition, the linked series will be sorted in the + * same order as the master one. + * + * @sample {highcharts|highstock} highcharts/demo/arearange-line/ + * Linked series + * + * @type {string} + * @since 3.0 + * @product highcharts highstock gantt + * @apioption plotOptions.series.linkedTo + */ + /** + * Options for the corresponding navigator series if `showInNavigator` + * is `true` for this series. Available options are the same as any + * series, documented at [plotOptions](#plotOptions.series) and + * [series](#series). + * + * These options are merged with options in [navigator.series]( + * #navigator.series), and will take precedence if the same option is + * defined both places. + * + * @see [navigator.series](#navigator.series) + * + * @type {Highcharts.PlotSeriesOptions} + * @since 5.0.0 + * @product highstock + * @apioption plotOptions.series.navigatorOptions + */ + /** + * The color for the parts of the graph or points that are below the + * [threshold](#plotOptions.series.threshold). Note that `zones` takes + * precedence over the negative color. Using `negativeColor` is + * equivalent to applying a zone with value of 0. + * + * @see In styled mode, a negative color is applied by setting this option + * to `true` combined with the `.highcharts-negative` class name. + * + * @sample {highcharts} highcharts/plotoptions/series-negative-color/ + * Spline, area and column + * @sample {highcharts} highcharts/plotoptions/arearange-negativecolor/ + * Arearange + * @sample {highcharts} highcharts/css/series-negative-color/ + * Styled mode + * @sample {highstock} highcharts/plotoptions/series-negative-color/ + * Spline, area and column + * @sample {highstock} highcharts/plotoptions/arearange-negativecolor/ + * Arearange + * @sample {highmaps} highcharts/plotoptions/series-negative-color/ + * Spline, area and column + * @sample {highmaps} highcharts/plotoptions/arearange-negativecolor/ + * Arearange + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 3.0 + * @apioption plotOptions.series.negativeColor + */ + /** + * Same as + * [accessibility.pointDescriptionFormatter](#accessibility.pointDescriptionFormatter), + * but for an individual series. Overrides the chart wide configuration. + * + * @type {Function} + * @since 5.0.12 + * @apioption plotOptions.series.pointDescriptionFormatter + */ + /** + * If no x values are given for the points in a series, `pointInterval` + * defines the interval of the x values. For example, if a series + * contains one value every decade starting from year 0, set + * `pointInterval` to `10`. In true `datetime` axes, the `pointInterval` + * is set in milliseconds. + * + * It can be also be combined with `pointIntervalUnit` to draw irregular + * time intervals. + * + * Please note that this options applies to the _series data_, not the + * interval of the axis ticks, which is independent. + * + * @sample {highcharts} highcharts/plotoptions/series-pointstart-datetime/ + * Datetime X axis + * @sample {highstock} stock/plotoptions/pointinterval-pointstart/ + * Using pointStart and pointInterval + * + * @type {number} + * @default 1 + * @product highcharts highstock gantt + * @apioption plotOptions.series.pointInterval + */ + /** + * On datetime series, this allows for setting the + * [pointInterval](#plotOptions.series.pointInterval) to irregular time + * units, `day`, `month` and `year`. A day is usually the same as 24 + * hours, but `pointIntervalUnit` also takes the DST crossover into + * consideration when dealing with local time. Combine this option with + * `pointInterval` to draw weeks, quarters, 6 months, 10 years etc. + * + * Please note that this options applies to the _series data_, not the + * interval of the axis ticks, which is independent. + * + * @sample {highcharts} highcharts/plotoptions/series-pointintervalunit/ + * One point a month + * @sample {highstock} highcharts/plotoptions/series-pointintervalunit/ + * One point a month + * + * @type {string} + * @since 4.1.0 + * @product highcharts highstock gantt + * @validvalue ["day", "month", "year"] + * @apioption plotOptions.series.pointIntervalUnit + */ + /** + * Possible values: `"on"`, `"between"`, `number`. + * + * In a column chart, when pointPlacement is `"on"`, the point will not + * create any padding of the X axis. In a polar column chart this means + * that the first column points directly north. If the pointPlacement is + * `"between"`, the columns will be laid out between ticks. This is + * useful for example for visualising an amount between two points in + * time or in a certain sector of a polar chart. + * + * Since Highcharts 3.0.2, the point placement can also be numeric, + * where 0 is on the axis value, -0.5 is between this value and the + * previous, and 0.5 is between this value and the next. Unlike the + * textual options, numeric point placement options won't affect axis + * padding. + * + * Note that pointPlacement needs a [pointRange]( + * #plotOptions.series.pointRange) to work. For column series this is + * computed, but for line-type series it needs to be set. + * + * For the `xrange` series type and gantt charts, if the Y axis is a + * category axis, the `pointPlacement` applies to the Y axis rather than + * the (typically datetime) X axis. + * + * Defaults to `undefined` in cartesian charts, `"between"` in polar + * charts. + * + * @see [xAxis.tickmarkPlacement](#xAxis.tickmarkPlacement) + * + * @sample {highcharts|highstock} highcharts/plotoptions/series-pointplacement-between/ + * Between in a column chart + * @sample {highcharts|highstock} highcharts/plotoptions/series-pointplacement-numeric/ + * Numeric placement for custom layout + * @sample {highcharts|highstock} maps/plotoptions/heatmap-pointplacement/ + * Placement in heatmap + * + * @type {string|number} + * @since 2.3.0 + * @product highcharts highstock gantt + * @apioption plotOptions.series.pointPlacement + */ + /** + * If no x values are given for the points in a series, pointStart + * defines on what value to start. For example, if a series contains one + * yearly value starting from 1945, set pointStart to 1945. + * + * @sample {highcharts} highcharts/plotoptions/series-pointstart-linear/ + * Linear + * @sample {highcharts} highcharts/plotoptions/series-pointstart-datetime/ + * Datetime + * @sample {highstock} stock/plotoptions/pointinterval-pointstart/ + * Using pointStart and pointInterval + * + * @type {number} + * @default 0 + * @product highcharts highstock gantt + * @apioption plotOptions.series.pointStart + */ + /** + * Whether to select the series initially. If `showCheckbox` is true, + * the checkbox next to the series name in the legend will be checked + * for a selected series. + * + * @sample {highcharts} highcharts/plotoptions/series-selected/ + * One out of two series selected + * + * @type {boolean} + * @default false + * @since 1.2.0 + * @apioption plotOptions.series.selected + */ + /** + * Whether to apply a drop shadow to the graph line. Since 2.3 the + * shadow can be an object configuration containing `color`, `offsetX`, + * `offsetY`, `opacity` and `width`. + * + * @sample {highcharts} highcharts/plotoptions/series-shadow/ + * Shadow enabled + * + * @type {boolean|Highcharts.ShadowOptionsObject} + * @default false + * @apioption plotOptions.series.shadow + */ + /** + * Whether to display this particular series or series type in the + * legend. Standalone series are shown in legend by default, and linked + * series are not. Since v7.2.0 it is possible to show series that use + * colorAxis by setting this option to `true`. + * + * @sample {highcharts} highcharts/plotoptions/series-showinlegend/ + * One series in the legend, one hidden + * + * @type {boolean} + * @apioption plotOptions.series.showInLegend + */ + /** + * Whether or not to show the series in the navigator. Takes precedence + * over [navigator.baseSeries](#navigator.baseSeries) if defined. + * + * @type {boolean} + * @since 5.0.0 + * @product highstock + * @apioption plotOptions.series.showInNavigator + */ + /** + * If set to `true`, the accessibility module will skip past the points + * in this series for keyboard navigation. + * + * @type {boolean} + * @since 5.0.12 + * @apioption plotOptions.series.skipKeyboardNavigation + */ + /** + * Whether to stack the values of each series on top of each other. + * Possible values are `undefined` to disable, `"normal"` to stack by + * value or `"percent"`. When stacking is enabled, data must be sorted + * in ascending X order. A special stacking option is with the + * streamgraph series type, where the stacking option is set to + * `"stream"`. The second one is `"overlap"`, which only applies to + * waterfall series. + * + * @see [yAxis.reversedStacks](#yAxis.reversedStacks) + * + * @sample {highcharts} highcharts/plotoptions/series-stacking-line/ + * Line + * @sample {highcharts} highcharts/plotoptions/series-stacking-column/ + * Column + * @sample {highcharts} highcharts/plotoptions/series-stacking-bar/ + * Bar + * @sample {highcharts} highcharts/plotoptions/series-stacking-area/ + * Area + * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-line/ + * Line + * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-column/ + * Column + * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-bar/ + * Bar + * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-area/ + * Area + * @sample {highcharts} highcharts/plotoptions/series-waterfall-with-normal-stacking + * Waterfall with normal stacking + * @sample {highcharts} highcharts/plotoptions/series-waterfall-with-overlap-stacking + * Waterfall with overlap stacking + * @sample {highstock} stock/plotoptions/stacking/ + * Area + * + * @type {string} + * @product highcharts highstock + * @validvalue ["normal", "overlap", "percent", "stream"] + * @apioption plotOptions.series.stacking + */ + /** + * Whether to apply steps to the line. Possible values are `left`, + * `center` and `right`. + * + * @sample {highcharts} highcharts/plotoptions/line-step/ + * Different step line options + * @sample {highcharts} highcharts/plotoptions/area-step/ + * Stepped, stacked area + * @sample {highstock} stock/plotoptions/line-step/ + * Step line + * + * @type {string} + * @since 1.2.5 + * @product highcharts highstock + * @validvalue ["left", "center", "right"] + * @apioption plotOptions.series.step + */ + /** + * The threshold, also called zero level or base level. For line type + * series this is only used in conjunction with + * [negativeColor](#plotOptions.series.negativeColor). + * + * @see [softThreshold](#plotOptions.series.softThreshold). + * + * @type {number} + * @default 0 + * @since 3.0 + * @product highcharts highstock + * @apioption plotOptions.series.threshold + */ + /** + * Set the initial visibility of the series. + * + * @sample {highcharts} highcharts/plotoptions/series-visible/ + * Two series, one hidden and one visible + * @sample {highstock} stock/plotoptions/series-visibility/ + * Hidden series + * + * @type {boolean} + * @default true + * @apioption plotOptions.series.visible + */ + /** + * Defines the Axis on which the zones are applied. + * + * @see [zones](#plotOptions.series.zones) + * + * @sample {highcharts} highcharts/series/color-zones-zoneaxis-x/ + * Zones on the X-Axis + * @sample {highstock} highcharts/series/color-zones-zoneaxis-x/ + * Zones on the X-Axis + * + * @type {string} + * @default y + * @since 4.1.0 + * @product highcharts highstock + * @apioption plotOptions.series.zoneAxis + */ + /** + * General event handlers for the series items. These event hooks can + * also be attached to the series at run time using the + * `Highcharts.addEvent` function. + * + * @declare Highcharts.SeriesEventsOptionsObject + * + * @private + */ + events: {}, + /** + * Fires after the series has finished its initial animation, or in case + * animation is disabled, immediately as the series is displayed. + * + * @sample {highcharts} highcharts/plotoptions/series-events-afteranimate/ + * Show label after animate + * @sample {highstock} highcharts/plotoptions/series-events-afteranimate/ + * Show label after animate + * + * @type {Highcharts.SeriesAfterAnimateCallbackFunction} + * @since 4.0 + * @product highcharts highstock gantt + * @context Highcharts.Series + * @apioption plotOptions.series.events.afterAnimate + */ + /** + * Fires when the checkbox next to the series' name in the legend is + * clicked. One parameter, `event`, is passed to the function. The state + * of the checkbox is found by `event.checked`. The checked item is + * found by `event.item`. Return `false` to prevent the default action + * which is to toggle the select state of the series. + * + * @sample {highcharts} highcharts/plotoptions/series-events-checkboxclick/ + * Alert checkbox status + * + * @type {Highcharts.SeriesCheckboxClickCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Series + * @apioption plotOptions.series.events.checkboxClick + */ + /** + * Fires when the series is clicked. One parameter, `event`, is passed + * to the function, containing common event information. Additionally, + * `event.point` holds a pointer to the nearest point on the graph. + * + * @sample {highcharts} highcharts/plotoptions/series-events-click/ + * Alert click info + * @sample {highstock} stock/plotoptions/series-events-click/ + * Alert click info + * @sample {highmaps} maps/plotoptions/series-events-click/ + * Display click info in subtitle + * + * @type {Highcharts.SeriesClickCallbackFunction} + * @context Highcharts.Series + * @apioption plotOptions.series.events.click + */ + /** + * Fires when the series is hidden after chart generation time, either + * by clicking the legend item or by calling `.hide()`. + * + * @sample {highcharts} highcharts/plotoptions/series-events-hide/ + * Alert when the series is hidden by clicking the legend item + * + * @type {Highcharts.SeriesHideCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Series + * @apioption plotOptions.series.events.hide + */ + /** + * Fires when the legend item belonging to the series is clicked. One + * parameter, `event`, is passed to the function. The default action + * is to toggle the visibility of the series. This can be prevented + * by returning `false` or calling `event.preventDefault()`. + * + * @sample {highcharts} highcharts/plotoptions/series-events-legenditemclick/ + * Confirm hiding and showing + * + * @type {Highcharts.SeriesLegendItemClickCallbackFunction} + * @context Highcharts.Series + * @apioption plotOptions.series.events.legendItemClick + */ + /** + * Fires when the mouse leaves the graph. One parameter, `event`, is + * passed to the function, containing common event information. If the + * [stickyTracking](#plotOptions.series) option is true, `mouseOut` + * doesn't happen before the mouse enters another graph or leaves the + * plot area. + * + * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-sticky/ + * With sticky tracking by default + * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-no-sticky/ + * Without sticky tracking + * + * @type {Highcharts.SeriesMouseOutCallbackFunction} + * @context Highcharts.Series + * @apioption plotOptions.series.events.mouseOut + */ + /** + * Fires when the mouse enters the graph. One parameter, `event`, is + * passed to the function, containing common event information. + * + * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-sticky/ + * With sticky tracking by default + * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-no-sticky/ + * Without sticky tracking + * + * @type {Highcharts.SeriesMouseOverCallbackFunction} + * @context Highcharts.Series + * @apioption plotOptions.series.events.mouseOver + */ + /** + * Fires when the series is shown after chart generation time, either + * by clicking the legend item or by calling `.show()`. + * + * @sample {highcharts} highcharts/plotoptions/series-events-show/ + * Alert when the series is shown by clicking the legend item. + * + * @type {Highcharts.SeriesShowCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Series + * @apioption plotOptions.series.events.show + */ + /** + * Options for the point markers of line-like series. Properties like + * `fillColor`, `lineColor` and `lineWidth` define the visual appearance + * of the markers. Other series types, like column series, don't have + * markers, but have visual options on the series level instead. + * + * In styled mode, the markers can be styled with the + * `.highcharts-point`, `.highcharts-point-hover` and + * `.highcharts-point-select` class names. + * + * @declare Highcharts.PointMarkerOptionsObject + * + * @private + */ + marker: { + /** + * Enable or disable the point marker. If `undefined`, the markers + * are hidden when the data is dense, and shown for more widespread + * data points. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-enabled/ + * Disabled markers + * @sample {highcharts} highcharts/plotoptions/series-marker-enabled-false/ + * Disabled in normal state but enabled on hover + * @sample {highstock} stock/plotoptions/series-marker/ + * Enabled markers + * + * @type {boolean} + * @default {highcharts} undefined + * @default {highstock} false + * @apioption plotOptions.series.marker.enabled + */ + /** + * The threshold for how dense the point markers should be before + * they are hidden, given that `enabled` is not defined. The number + * indicates the horizontal distance between the two closest points + * in the series, as multiples of the `marker.radius`. In other + * words, the default value of 2 means points are hidden if + * overlapping horizontally. + * + * @sample highcharts/plotoptions/series-marker-enabledthreshold + * A higher threshold + * + * @since 6.0.5 + */ + enabledThreshold: 2, + /** + * The fill color of the point marker. When `undefined`, the series' + * or point's color is used. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-fillcolor/ + * White fill + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.series.marker.fillColor + */ + /** + * Image markers only. Set the image width explicitly. When using + * this option, a `width` must also be set. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-width-height/ + * Fixed width and height + * @sample {highstock} highcharts/plotoptions/series-marker-width-height/ + * Fixed width and height + * + * @type {number} + * @since 4.0.4 + * @apioption plotOptions.series.marker.height + */ + /** + * The color of the point marker's outline. When `undefined`, the + * series' or point's color is used. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-fillcolor/ + * Inherit from series color (undefined) + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + lineColor: '#ffffff', + /** + * The width of the point marker's outline. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-fillcolor/ + * 2px blue marker + */ + lineWidth: 0, + /** + * The radius of the point marker. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-radius/ + * Bigger markers + * + * @default {highstock} 2 + */ + radius: 4, + /** + * A predefined shape or symbol for the marker. When undefined, the + * symbol is pulled from options.symbols. Other possible values are + * `'circle'`, `'square'`,`'diamond'`, `'triangle'` and + * `'triangle-down'`. + * + * Additionally, the URL to a graphic can be given on this form: + * `'url(graphic.png)'`. Note that for the image to be applied to + * exported charts, its URL needs to be accessible by the export + * server. + * + * Custom callbacks for symbol path generation can also be added to + * `Highcharts.SVGRenderer.prototype.symbols`. The callback is then + * used by its method name, as shown in the demo. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-symbol/ + * Predefined, graphic and custom markers + * @sample {highstock} highcharts/plotoptions/series-marker-symbol/ + * Predefined, graphic and custom markers + * + * @type {string} + * @apioption plotOptions.series.marker.symbol + */ + /** + * Image markers only. Set the image width explicitly. When using + * this option, a `height` must also be set. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-width-height/ + * Fixed width and height + * @sample {highstock} highcharts/plotoptions/series-marker-width-height/ + * Fixed width and height + * + * @type {number} + * @since 4.0.4 + * @apioption plotOptions.series.marker.width + */ + /** + * States for a single point marker. + * + * @declare Highcharts.PointStatesOptionsObject + */ + states: { + /** + * The normal state of a single point marker. Currently only + * used for setting animation when returning to normal state + * from hover. + * + * @declare Highcharts.PointStatesNormalOptionsObject + */ + normal: { + /** + * Animation when returning to normal state after hovering. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + */ + animation: true + }, + /** + * The hover state for a single point marker. + * + * @declare Highcharts.PointStatesHoverOptionsObject + */ + hover: { + /** + * Animation when hovering over the marker. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + */ + animation: { + /** @internal */ + duration: 50 + }, + /** + * Enable or disable the point marker. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-enabled/ + * Disabled hover state + */ + enabled: true, + /** + * The fill color of the marker in hover state. When + * `undefined`, the series' or point's fillColor for normal + * state is used. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.series.marker.states.hover.fillColor + */ + /** + * The color of the point marker's outline. When + * `undefined`, the series' or point's lineColor for normal + * state is used. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-linecolor/ + * White fill color, black line color + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.series.marker.states.hover.lineColor + */ + /** + * The width of the point marker's outline. When + * `undefined`, the series' or point's lineWidth for normal + * state is used. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-linewidth/ + * 3px line width + * + * @type {number} + * @apioption plotOptions.series.marker.states.hover.lineWidth + */ + /** + * The radius of the point marker. In hover state, it + * defaults to the normal state's radius + 2 as per the + * [radiusPlus](#plotOptions.series.marker.states.hover.radiusPlus) + * option. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-radius/ + * 10px radius + * + * @type {number} + * @apioption plotOptions.series.marker.states.hover.radius + */ + /** + * The number of pixels to increase the radius of the + * hovered point. + * + * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidthplus/ + * 5 pixels greater radius on hover + * @sample {highstock} highcharts/plotoptions/series-states-hover-linewidthplus/ + * 5 pixels greater radius on hover + * + * @since 4.0.3 + */ + radiusPlus: 2, + /** + * The additional line width for a hovered point. + * + * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidthplus/ + * 2 pixels wider on hover + * @sample {highstock} highcharts/plotoptions/series-states-hover-linewidthplus/ + * 2 pixels wider on hover + * + * @since 4.0.3 + */ + lineWidthPlus: 1 + }, + /** + * The appearance of the point marker when selected. In order to + * allow a point to be selected, set the + * `series.allowPointSelect` option to true. + * + * @declare Highcharts.PointStatesSelectOptionsObject + */ + select: { + /** + * Enable or disable visible feedback for selection. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-enabled/ + * Disabled select state + * + * @type {boolean} + * @default true + * @apioption plotOptions.series.marker.states.select.enabled + */ + /** + * The radius of the point marker. In hover state, it + * defaults to the normal state's radius + 2. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-radius/ + * 10px radius for selected points + * + * @type {number} + * @apioption plotOptions.series.marker.states.select.radius + */ + /** + * The fill color of the point marker. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-fillcolor/ + * Solid red discs for selected points + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + fillColor: '#cccccc', + /** + * The color of the point marker's outline. When + * `undefined`, the series' or point's color is used. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-linecolor/ + * Red line color for selected points + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + lineColor: '#000000', + /** + * The width of the point marker's outline. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-linewidth/ + * 3px line width for selected points + */ + lineWidth: 2 + } + } + }, + /** + * Properties for each single point. + * + * @declare Highcharts.PlotSeriesPointOptions + * + * @private + */ + point: { + /** + * Fires when a point is clicked. One parameter, `event`, is passed + * to the function, containing common event information. + * + * If the `series.allowPointSelect` option is true, the default + * action for the point's click event is to toggle the point's + * select state. Returning `false` cancels this action. + * + * @sample {highcharts} highcharts/plotoptions/series-point-events-click/ + * Click marker to alert values + * @sample {highcharts} highcharts/plotoptions/series-point-events-click-column/ + * Click column + * @sample {highcharts} highcharts/plotoptions/series-point-events-click-url/ + * Go to URL + * @sample {highmaps} maps/plotoptions/series-point-events-click/ + * Click marker to display values + * @sample {highmaps} maps/plotoptions/series-point-events-click-url/ + * Go to URL + * + * @type {Highcharts.PointClickCallbackFunction} + * @context Highcharts.Point + * @apioption plotOptions.series.point.events.click + */ + /** + * Fires when the mouse leaves the area close to the point. One + * parameter, `event`, is passed to the function, containing common + * event information. + * + * @sample {highcharts} highcharts/plotoptions/series-point-events-mouseover/ + * Show values in the chart's corner on mouse over + * + * @type {Highcharts.PointMouseOutCallbackFunction} + * @context Highcharts.Point + * @apioption plotOptions.series.point.events.mouseOut + */ + /** + * Fires when the mouse enters the area close to the point. One + * parameter, `event`, is passed to the function, containing common + * event information. + * + * @sample {highcharts} highcharts/plotoptions/series-point-events-mouseover/ + * Show values in the chart's corner on mouse over + * + * @type {Highcharts.PointMouseOverCallbackFunction} + * @context Highcharts.Point + * @apioption plotOptions.series.point.events.mouseOver + */ + /** + * Fires when the point is removed using the `.remove()` method. One + * parameter, `event`, is passed to the function. Returning `false` + * cancels the operation. + * + * @sample {highcharts} highcharts/plotoptions/series-point-events-remove/ + * Remove point and confirm + * + * @type {Highcharts.PointRemoveCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Point + * @apioption plotOptions.series.point.events.remove + */ + /** + * Fires when the point is selected either programmatically or + * following a click on the point. One parameter, `event`, is passed + * to the function. Returning `false` cancels the operation. + * + * @sample {highcharts} highcharts/plotoptions/series-point-events-select/ + * Report the last selected point + * @sample {highmaps} maps/plotoptions/series-allowpointselect/ + * Report select and unselect + * + * @type {Highcharts.PointSelectCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Point + * @apioption plotOptions.series.point.events.select + */ + /** + * Fires when the point is unselected either programmatically or + * following a click on the point. One parameter, `event`, is passed + * to the function. + * Returning `false` cancels the operation. + * + * @sample {highcharts} highcharts/plotoptions/series-point-events-unselect/ + * Report the last unselected point + * @sample {highmaps} maps/plotoptions/series-allowpointselect/ + * Report select and unselect + * + * @type {Highcharts.PointUnselectCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Point + * @apioption plotOptions.series.point.events.unselect + */ + /** + * Fires when the point is updated programmatically through the + * `.update()` method. One parameter, `event`, is passed to the + * function. The new point options can be accessed through + * `event.options`. Returning `false` cancels the operation. + * + * @sample {highcharts} highcharts/plotoptions/series-point-events-update/ + * Confirm point updating + * + * @type {Highcharts.PointUpdateCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Point + * @apioption plotOptions.series.point.events.update + */ + /** + * Events for each single point. + * + * @declare Highcharts.PointEventsOptionsObject + */ + events: {} + }, + /** + * Options for the series data labels, appearing next to each data + * point. + * + * Since v6.2.0, multiple data labels can be applied to each single + * point by defining them as an array of configs. + * + * In styled mode, the data labels can be styled with the + * `.highcharts-data-label-box` and `.highcharts-data-label` class names + * ([see example](https://www.highcharts.com/samples/highcharts/css/series-datalabels)). + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-enabled + * Data labels enabled + * @sample {highcharts} highcharts/plotoptions/series-datalabels-multiple + * Multiple data labels on a bar series + * @sample {highcharts} highcharts/css/series-datalabels + * Style mode example + * + * @type {*|Array<*>} + * @product highcharts highstock highmaps gantt + * + * @private + */ + dataLabels: { + /** + * The alignment of the data label compared to the point. If + * `right`, the right side of the label should be touching the + * point. For points with an extent, like columns, the alignments + * also dictates how to align it inside the box, as given with the + * [inside](#plotOptions.column.dataLabels.inside) + * option. Can be one of `left`, `center` or `right`. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-align-left/ + * Left aligned + * @sample {highcharts} highcharts/plotoptions/bar-datalabels-align-inside-bar/ + * Data labels inside the bar + * + * @type {Highcharts.AlignValue|null} + */ + align: 'center', + /** + * Whether to allow data labels to overlap. To make the labels less + * sensitive for overlapping, the + * [dataLabels.padding](#plotOptions.series.dataLabels.padding) + * can be set to 0. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-allowoverlap-false/ + * Don't allow overlap + * + * @type {boolean} + * @default false + * @since 4.1.0 + * @apioption plotOptions.series.dataLabels.allowOverlap + */ + /** + * The background color or gradient for the data label. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/ + * Data labels box options + * @sample {highmaps} maps/plotoptions/series-datalabels-box/ + * Data labels box options + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.2.1 + * @apioption plotOptions.series.dataLabels.backgroundColor + */ + /** + * The border color for the data label. Defaults to `undefined`. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/ + * Data labels box options + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.2.1 + * @apioption plotOptions.series.dataLabels.borderColor + */ + /** + * The border radius in pixels for the data label. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/ + * Data labels box options + * @sample {highmaps} maps/plotoptions/series-datalabels-box/ + * Data labels box options + * + * @type {number} + * @default 0 + * @since 2.2.1 + * @apioption plotOptions.series.dataLabels.borderRadius + */ + /** + * The border width in pixels for the data label. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/ + * Data labels box options + * + * @type {number} + * @default 0 + * @since 2.2.1 + * @apioption plotOptions.series.dataLabels.borderWidth + */ + /** + * A class name for the data label. Particularly in styled mode, + * this can be used to give each series' or point's data label + * unique styling. In addition to this option, a default color class + * name is added so that we can give the labels a contrast text + * shadow. + * + * @sample {highcharts} highcharts/css/data-label-contrast/ + * Contrast text shadow + * @sample {highcharts} highcharts/css/series-datalabels/ + * Styling by CSS + * + * @type {string} + * @since 5.0.0 + * @apioption plotOptions.series.dataLabels.className + */ + /** + * The text color for the data labels. Defaults to `undefined`. For + * certain series types, like column or map, the data labels can be + * drawn inside the points. In this case the data label will be + * drawn with maximum contrast by default. Additionally, it will be + * given a `text-outline` style with the opposite color, to further + * increase the contrast. This can be overridden by setting the + * `text-outline` style to `none` in the `dataLabels.style` option. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-color/ + * Red data labels + * @sample {highmaps} maps/demo/color-axis/ + * White data labels + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.series.dataLabels.color + */ + /** + * Whether to hide data labels that are outside the plot area. By + * default, the data label is moved inside the plot area according + * to the + * [overflow](#plotOptions.series.dataLabels.overflow) + * option. + * + * @type {boolean} + * @default true + * @since 2.3.3 + * @apioption plotOptions.series.dataLabels.crop + */ + /** + * Whether to defer displaying the data labels until the initial + * series animation has finished. + * + * @type {boolean} + * @default true + * @since 4.0.0 + * @product highcharts highstock gantt + * @apioption plotOptions.series.dataLabels.defer + */ + /** + * Enable or disable the data labels. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-enabled/ + * Data labels enabled + * @sample {highmaps} maps/demo/color-axis/ + * Data labels enabled + * + * @type {boolean} + * @default false + * @apioption plotOptions.series.dataLabels.enabled + */ + /** + * A declarative filter to control of which data labels to display. + * The declarative filter is designed for use when callback + * functions are not available, like when the chart options require + * a pure JSON structure or for use with graphical editors. For + * programmatic control, use the `formatter` instead, and return + * `undefined` to disable a single data label. + * + * @example + * filter: { + * property: 'percentage', + * operator: '>', + * value: 4 + * } + * + * @sample {highcharts} highcharts/demo/pie-monochrome + * Data labels filtered by percentage + * + * @declare Highcharts.DataLabelsFilterOptionsObject + * @since 6.0.3 + * @apioption plotOptions.series.dataLabels.filter + */ + /** + * The operator to compare by. Can be one of `>`, `<`, `>=`, `<=`, + * `==`, and `===`. + * + * @type {string} + * @validvalue [">", "<", ">=", "<=", "==", "==="] + * @apioption plotOptions.series.dataLabels.filter.operator + */ + /** + * The point property to filter by. Point options are passed + * directly to properties, additionally there are `y` value, + * `percentage` and others listed under {@link Highcharts.Point} + * members. + * + * @type {string} + * @apioption plotOptions.series.dataLabels.filter.property + */ + /** + * The value to compare against. + * + * @type {number} + * @apioption plotOptions.series.dataLabels.filter.value + */ + /** + * A + * [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) + * for the data label. Available variables are the same as for + * `formatter`. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-format/ + * Add a unit + * @sample {highmaps} maps/plotoptions/series-datalabels-format/ + * Formatted value in the data label + * + * @type {string} + * @default y + * @default point.value + * @since 3.0 + * @apioption plotOptions.series.dataLabels.format + */ + // eslint-disable-next-line valid-jsdoc + /** + * Callback JavaScript function to format the data label. Note that + * if a `format` is defined, the format takes precedence and the + * formatter is ignored. + * + * @sample {highmaps} maps/plotoptions/series-datalabels-format/ + * Formatted value + * + * @type {Highcharts.DataLabelsFormatterCallbackFunction} + */ + formatter: function () { + var numberFormatter = this.series.chart.numberFormatter; + return typeof this.y !== 'number' ? '' : numberFormatter(this.y, -1); + }, + /** + * For points with an extent, like columns or map areas, whether to + * align the data label inside the box or to the actual value point. + * Defaults to `false` in most cases, `true` in stacked columns. + * + * @type {boolean} + * @since 3.0 + * @apioption plotOptions.series.dataLabels.inside + */ + /** + * Format for points with the value of null. Works analogously to + * [format](#plotOptions.series.dataLabels.format). `nullFormat` can + * be applied only to series which support displaying null points. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-format/ + * Format data label and tooltip for null point. + * + * @type {boolean|string} + * @since 7.1.0 + * @apioption plotOptions.series.dataLabels.nullFormat + */ + /** + * Callback JavaScript function that defines formatting for points + * with the value of null. Works analogously to + * [formatter](#plotOptions.series.dataLabels.formatter). + * `nullPointFormatter` can be applied only to series which support + * displaying null points. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-format/ + * Format data label and tooltip for null point. + * + * @type {Highcharts.DataLabelsFormatterCallbackFunction} + * @since 7.1.0 + * @apioption plotOptions.series.dataLabels.nullFormatter + */ + /** + * How to handle data labels that flow outside the plot area. The + * default is `"justify"`, which aligns them inside the plot area. + * For columns and bars, this means it will be moved inside the bar. + * To display data labels outside the plot area, set `crop` to + * `false` and `overflow` to `"allow"`. + * + * @type {Highcharts.DataLabelsOverflowValue} + * @default justify + * @since 3.0.6 + * @apioption plotOptions.series.dataLabels.overflow + */ + /** + * When either the `borderWidth` or the `backgroundColor` is set, + * this is the padding within the box. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/ + * Data labels box options + * @sample {highmaps} maps/plotoptions/series-datalabels-box/ + * Data labels box options + * + * @since 2.2.1 + */ + padding: 5, + /** + * Aligns data labels relative to points. If `center` alignment is + * not possible, it defaults to `right`. + * + * @type {Highcharts.AlignValue} + * @default center + * @apioption plotOptions.series.dataLabels.position + */ + /** + * Text rotation in degrees. Note that due to a more complex + * structure, backgrounds, borders and padding will be lost on a + * rotated data label. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-rotation/ + * Vertical labels + * + * @type {number} + * @default 0 + * @apioption plotOptions.series.dataLabels.rotation + */ + /** + * The shadow of the box. Works best with `borderWidth` or + * `backgroundColor`. Since 2.3 the shadow can be an object + * configuration containing `color`, `offsetX`, `offsetY`, `opacity` + * and `width`. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/ + * Data labels box options + * + * @type {boolean|Highcharts.ShadowOptionsObject} + * @default false + * @since 2.2.1 + * @apioption plotOptions.series.dataLabels.shadow + */ + /** + * The name of a symbol to use for the border around the label. + * Symbols are predefined functions on the Renderer object. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-shape/ + * A callout for annotations + * + * @type {string} + * @default square + * @since 4.1.2 + * @apioption plotOptions.series.dataLabels.shape + */ + /** + * Styles for the label. The default `color` setting is + * `"contrast"`, which is a pseudo color that Highcharts picks up + * and applies the maximum contrast to the underlying point item, + * for example the bar in a bar chart. + * + * The `textOutline` is a pseudo property that applies an outline of + * the given width with the given color, which by default is the + * maximum contrast to the text. So a bright text color will result + * in a black text outline for maximum readability on a mixed + * background. In some cases, especially with grayscale text, the + * text outline doesn't work well, in which cases it can be disabled + * by setting it to `"none"`. When `useHTML` is true, the + * `textOutline` will not be picked up. In this, case, the same + * effect can be acheived through the `text-shadow` CSS property. + * + * For some series types, where each point has an extent, like for + * example tree maps, the data label may overflow the point. There + * are two strategies for handling overflow. By default, the text + * will wrap to multiple lines. The other strategy is to set + * `style.textOverflow` to `ellipsis`, which will keep the text on + * one line plus it will break inside long words. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-style/ + * Bold labels + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow/ + * Long labels truncated with an ellipsis in a pie + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow-wrap/ + * Long labels are wrapped in a pie + * @sample {highmaps} maps/demo/color-axis/ + * Bold labels + * + * @type {Highcharts.CSSObject} + * @since 4.1.0 + * @apioption plotOptions.series.dataLabels.style + */ + style: { + /** @internal */ + fontSize: '11px', + /** @internal */ + fontWeight: 'bold', + /** @internal */ + color: 'contrast', + /** @internal */ + textOutline: '1px contrast' + }, + /** + * Options for a label text which should follow marker's shape. + * Border and background are disabled for a label that follows a + * path. + * + * **Note:** Only SVG-based renderer supports this option. Setting + * `useHTML` to true will disable this option. + * + * @declare Highcharts.DataLabelsTextPathOptionsObject + * @since 7.1.0 + * @apioption plotOptions.series.dataLabels.textPath + */ + /** + * Presentation attributes for the text path. + * + * @type {Highcharts.SVGAttributes} + * @since 7.1.0 + * @apioption plotOptions.series.dataLabels.textPath.attributes + */ + /** + * Enable or disable `textPath` option for link's or marker's data + * labels. + * + * @type {boolean} + * @since 7.1.0 + * @apioption plotOptions.series.dataLabels.textPath.enabled + */ + /** + * Whether to + * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the labels. + * + * @type {boolean} + * @default false + * @apioption plotOptions.series.dataLabels.useHTML + */ + /** + * The vertical alignment of a data label. Can be one of `top`, + * `middle` or `bottom`. The default value depends on the data, for + * instance in a column chart, the label is above positive values + * and below negative values. + * + * @type {Highcharts.VerticalAlignValue|null} + * @since 2.3.3 + */ + verticalAlign: 'bottom', + /** + * The x position offset of the label relative to the point in + * pixels. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-rotation/ + * Vertical and positioned + * @sample {highcharts} highcharts/plotoptions/bar-datalabels-align-inside-bar/ + * Data labels inside the bar + */ + x: 0, + /** + * The Z index of the data labels. The default Z index puts it above + * the series. Use a Z index of 2 to display it behind the series. + * + * @type {number} + * @default 6 + * @since 2.3.5 + * @apioption plotOptions.series.dataLabels.z + */ + /** + * The y position offset of the label relative to the point in + * pixels. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-rotation/ + * Vertical and positioned + */ + y: 0 + }, + /** + * When the series contains less points than the crop threshold, all + * points are drawn, even if the points fall outside the visible plot + * area at the current zoom. The advantage of drawing all points + * (including markers and columns), is that animation is performed on + * updates. On the other hand, when the series contains more points than + * the crop threshold, the series data is cropped to only contain points + * that fall within the plot area. The advantage of cropping away + * invisible points is to increase performance on large series. + * + * @since 2.2 + * @product highcharts highstock + * + * @private + */ + cropThreshold: 300, + /** + * Opacity of a series parts: line, fill (e.g. area) and dataLabels. + * + * @see [states.inactive.opacity](#plotOptions.series.states.inactive.opacity) + * + * @since 7.1.0 + * + * @private + */ + opacity: 1, + /** + * The width of each point on the x axis. For example in a column chart + * with one value each day, the pointRange would be 1 day (= 24 * 3600 + * * 1000 milliseconds). This is normally computed automatically, but + * this option can be used to override the automatic value. + * + * @product highstock + * + * @private + */ + pointRange: 0, + /** + * When this is true, the series will not cause the Y axis to cross + * the zero plane (or [threshold](#plotOptions.series.threshold) option) + * unless the data actually crosses the plane. + * + * For example, if `softThreshold` is `false`, a series of 0, 1, 2, + * 3 will make the Y axis show negative values according to the + * `minPadding` option. If `softThreshold` is `true`, the Y axis starts + * at 0. + * + * @since 4.1.9 + * @product highcharts highstock + * + * @private + */ + softThreshold: true, + /** + * @declare Highcharts.SeriesStatesOptionsObject + * + * @private + */ + states: { + /** + * The normal state of a series, or for point items in column, pie + * and similar series. Currently only used for setting animation + * when returning to normal state from hover. + * + * @declare Highcharts.SeriesStatesNormalOptionsObject + */ + normal: { + /** + * Animation when returning to normal state after hovering. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + */ + animation: true + }, + /** + * Options for the hovered series. These settings override the + * normal state options when a series is moused over or touched. + * + * @declare Highcharts.SeriesStatesHoverOptionsObject + */ + hover: { + /** + * Enable separate styles for the hovered series to visualize + * that the user hovers either the series itself or the legend. + * + * @sample {highcharts} highcharts/plotoptions/series-states-hover-enabled/ + * Line + * @sample {highcharts} highcharts/plotoptions/series-states-hover-enabled-column/ + * Column + * @sample {highcharts} highcharts/plotoptions/series-states-hover-enabled-pie/ + * Pie + * + * @type {boolean} + * @default true + * @since 1.2 + * @apioption plotOptions.series.states.hover.enabled + */ + /** + * Animation setting for hovering the graph in line-type series. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + * @since 5.0.8 + * @product highcharts highstock + */ + animation: { + /** + * The duration of the hover animation in milliseconds. By + * default the hover state animates quickly in, and slowly + * back to normal. + * + * @internal + */ + duration: 50 + }, + /** + * Pixel width of the graph line. By default this property is + * undefined, and the `lineWidthPlus` property dictates how much + * to increase the linewidth from normal state. + * + * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidth/ + * 5px line on hover + * + * @type {number} + * @product highcharts highstock + * @apioption plotOptions.series.states.hover.lineWidth + */ + /** + * The additional line width for the graph of a hovered series. + * + * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidthplus/ + * 5 pixels wider + * @sample {highstock} highcharts/plotoptions/series-states-hover-linewidthplus/ + * 5 pixels wider + * + * @since 4.0.3 + * @product highcharts highstock + */ + lineWidthPlus: 1, + /** + * In Highcharts 1.0, the appearance of all markers belonging + * to the hovered series. For settings on the hover state of the + * individual point, see + * [marker.states.hover](#plotOptions.series.marker.states.hover). + * + * @deprecated + * + * @extends plotOptions.series.marker + * @excluding states + * @product highcharts highstock + */ + marker: { + // lineWidth: base + 1, + // radius: base + 1 + }, + /** + * Options for the halo appearing around the hovered point in + * line-type series as well as outside the hovered slice in pie + * charts. By default the halo is filled by the current point or + * series color with an opacity of 0.25\. The halo can be + * disabled by setting the `halo` option to `null`. + * + * In styled mode, the halo is styled with the + * `.highcharts-halo` class, with colors inherited from + * `.highcharts-color-{n}`. + * + * @sample {highcharts} highcharts/plotoptions/halo/ + * Halo options + * @sample {highstock} highcharts/plotoptions/halo/ + * Halo options + * + * @declare Highcharts.SeriesStatesHoverHaloOptionsObject + * @type {null|*} + * @since 4.0 + * @product highcharts highstock + */ + halo: { + /** + * A collection of SVG attributes to override the appearance + * of the halo, for example `fill`, `stroke` and + * `stroke-width`. + * + * @type {Highcharts.SVGAttributes} + * @since 4.0 + * @product highcharts highstock + * @apioption plotOptions.series.states.hover.halo.attributes + */ + /** + * The pixel size of the halo. For point markers this is the + * radius of the halo. For pie slices it is the width of the + * halo outside the slice. For bubbles it defaults to 5 and + * is the width of the halo outside the bubble. + * + * @since 4.0 + * @product highcharts highstock + */ + size: 10, + /** + * Opacity for the halo unless a specific fill is overridden + * using the `attributes` setting. Note that Highcharts is + * only able to apply opacity to colors of hex or rgb(a) + * formats. + * + * @since 4.0 + * @product highcharts highstock + */ + opacity: 0.25 + } + }, + /** + * Specific options for point in selected states, after being + * selected by + * [allowPointSelect](#plotOptions.series.allowPointSelect) + * or programmatically. + * + * @sample maps/plotoptions/series-allowpointselect/ + * Allow point select demo + * + * @declare Highcharts.SeriesStatesSelectOptionsObject + * @extends plotOptions.series.states.hover + * @excluding brightness + */ + select: { + animation: { + /** @internal */ + duration: 0 + } + }, + /** + * The opposite state of a hover for series. + * + * @sample highcharts/plotoptions/series-states-inactive-disabled + * Disabled inactive state + * + * @declare Highcharts.SeriesStatesInactiveOptionsObject + */ + inactive: { + /** + * Enable or disable the inactive state for a series + * + * @sample highcharts/plotoptions/series-states-inactive-disabled + * Disabled inactive state + * + * @type {boolean} + * @default true + * @apioption plotOptions.series.states.inactive.enabled + */ + /** + * The animation for entering the inactive state. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + */ + animation: { + /** @internal */ + duration: 50 + }, + /** + * Opacity of series elements (dataLabels, line, area). + * + * @type {number} + */ + opacity: 0.2 + } + }, + /** + * Sticky tracking of mouse events. When true, the `mouseOut` event on a + * series isn't triggered until the mouse moves over another series, or + * out of the plot area. When false, the `mouseOut` event on a series is + * triggered when the mouse leaves the area around the series' graph or + * markers. This also implies the tooltip when not shared. When + * `stickyTracking` is false and `tooltip.shared` is false, the tooltip + * will be hidden when moving the mouse between series. Defaults to true + * for line and area type series, but to false for columns, pies etc. + * + * **Note:** The boost module will force this option because of + * technical limitations. + * + * @sample {highcharts} highcharts/plotoptions/series-stickytracking-true/ + * True by default + * @sample {highcharts} highcharts/plotoptions/series-stickytracking-false/ + * False + * + * @default {highcharts} true + * @default {highstock} true + * @default {highmaps} false + * @since 2.0 + * + * @private + */ + stickyTracking: true, + /** + * A configuration object for the tooltip rendering of each single + * series. Properties are inherited from [tooltip](#tooltip), but only + * the following properties can be defined on a series level. + * + * @declare Highcharts.SeriesTooltipOptionsObject + * @since 2.3 + * @extends tooltip + * @excluding animation, backgroundColor, borderColor, borderRadius, + * borderWidth, className, crosshairs, enabled, formatter, + * headerShape, hideDelay, outside, padding, positioner, + * shadow, shape, shared, snap, split, style, useHTML + * @apioption plotOptions.series.tooltip + */ + /** + * When a series contains a data array that is longer than this, only + * one dimensional arrays of numbers, or two dimensional arrays with + * x and y values are allowed. Also, only the first point is tested, + * and the rest are assumed to be the same format. This saves expensive + * data checking and indexing in long series. Set it to `0` disable. + * + * Note: + * In boost mode turbo threshold is forced. Only array of numbers or + * two dimensional arrays are allowed. + * + * @since 2.2 + * @product highcharts highstock gantt + * + * @private + */ + turboThreshold: 1000, + /** + * An array defining zones within a series. Zones can be applied to the + * X axis, Y axis or Z axis for bubbles, according to the `zoneAxis` + * option. The zone definitions have to be in ascending order regarding + * to the value. + * + * In styled mode, the color zones are styled with the + * `.highcharts-zone-{n}` class, or custom classed from the `className` + * option + * ([view live demo](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/css/color-zones/)). + * + * @see [zoneAxis](#plotOptions.series.zoneAxis) + * + * @sample {highcharts} highcharts/series/color-zones-simple/ + * Color zones + * @sample {highstock} highcharts/series/color-zones-simple/ + * Color zones + * + * @declare Highcharts.SeriesZonesOptionsObject + * @type {Array<*>} + * @since 4.1.0 + * @product highcharts highstock + * @apioption plotOptions.series.zones + */ + /** + * Styled mode only. A custom class name for the zone. + * + * @sample highcharts/css/color-zones/ + * Zones styled by class name + * + * @type {string} + * @since 5.0.0 + * @apioption plotOptions.series.zones.className + */ + /** + * Defines the color of the series. + * + * @see [series color](#plotOptions.series.color) + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 4.1.0 + * @product highcharts highstock + * @apioption plotOptions.series.zones.color + */ + /** + * A name for the dash style to use for the graph. + * + * @see [plotOptions.series.dashStyle](#plotOptions.series.dashStyle) + * + * @sample {highcharts|highstock} highcharts/series/color-zones-dashstyle-dot/ + * Dashed line indicates prognosis + * + * @type {Highcharts.DashStyleValue} + * @since 4.1.0 + * @product highcharts highstock + * @apioption plotOptions.series.zones.dashStyle + */ + /** + * Defines the fill color for the series (in area type series) + * + * @see [fillColor](#plotOptions.area.fillColor) + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 4.1.0 + * @product highcharts highstock + * @apioption plotOptions.series.zones.fillColor + */ + /** + * The value up to where the zone extends, if undefined the zones + * stretches to the last value in the series. + * + * @type {number} + * @since 4.1.0 + * @product highcharts highstock + * @apioption plotOptions.series.zones.value + */ + /** + * When using dual or multiple color axes, this number defines which + * colorAxis the particular series is connected to. It refers to + * either the + * {@link #colorAxis.id|axis id} + * or the index of the axis in the colorAxis array, with 0 being the + * first. Set this option to false to prevent a series from connecting + * to the default color axis. + * + * Since v7.2.0 the option can also be an axis id or an axis index + * instead of a boolean flag. + * + * @sample highcharts/coloraxis/coloraxis-with-pie/ + * Color axis with pie series + * @sample highcharts/coloraxis/multiple-coloraxis/ + * Multiple color axis + * + * @type {number|string|boolean} + * @default 0 + * @product highcharts highstock highmaps + * @apioption plotOptions.series.colorAxis + */ + /** + * Determines what data value should be used to calculate point color + * if `colorAxis` is used. Requires to set `min` and `max` if some + * custom point property is used or if approximation for data grouping + * is set to `'sum'`. + * + * @sample highcharts/coloraxis/custom-color-key/ + * Custom color key + * @sample highcharts/coloraxis/changed-default-color-key/ + * Changed default color key + * + * @type {string} + * @default y + * @since 7.2.0 + * @product highcharts highstock highmaps + * @apioption plotOptions.series.colorKey + */ + /** + * Determines whether the series should look for the nearest point + * in both dimensions or just the x-dimension when hovering the series. + * Defaults to `'xy'` for scatter series and `'x'` for most other + * series. If the data has duplicate x-values, it is recommended to + * set this to `'xy'` to allow hovering over all points. + * + * Applies only to series types using nearest neighbor search (not + * direct hover) for tooltip. + * + * @sample {highcharts} highcharts/series/findnearestpointby/ + * Different hover behaviors + * @sample {highstock} highcharts/series/findnearestpointby/ + * Different hover behaviors + * @sample {highmaps} highcharts/series/findnearestpointby/ + * Different hover behaviors + * + * @since 5.0.10 + * @validvalue ["x", "xy"] + * + * @private + */ + findNearestPointBy: 'x' + }, + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** @lends Highcharts.Series.prototype */ + { + axisTypes: ['xAxis', 'yAxis'], + coll: 'series', + colorCounter: 0, + cropShoulder: 1, + directTouch: false, + eventsToUnbind: [], + isCartesian: true, + // each point's x and y values are stored in this.xData and this.yData + parallelArrays: ['x', 'y'], + pointClass: Point, + requireSorting: true, + sorted: true, + init: function (chart, options) { + fireEvent(this, 'init', { options: options }); + var series = this, events, chartSeries = chart.series, lastSeries; + // A lookup over those events that are added by _options_ (not + // programmatically). These are updated through Series.update() + // (#10861). + this.eventOptions = this.eventOptions || {}; + /** + * Read only. The chart that the series belongs to. + * + * @name Highcharts.Series#chart + * @type {Highcharts.Chart} + */ + series.chart = chart; + /** + * Read only. The series' type, like "line", "area", "column" etc. + * The type in the series options anc can be altered using + * {@link Series#update}. + * + * @name Highcharts.Series#type + * @type {string} + */ + /** + * Read only. The series' current options. To update, use + * {@link Series#update}. + * + * @name Highcharts.Series#options + * @type {Highcharts.SeriesOptionsType} + */ + series.options = options = series.setOptions(options); + series.linkedSeries = []; + // bind the axes + series.bindAxes(); + // set some variables + extend(series, { + /** + * The series name as given in the options. Defaults to + * "Series {n}". + * + * @name Highcharts.Series#name + * @type {string} + */ + name: options.name, + state: '', + /** + * Read only. The series' visibility state as set by {@link + * Series#show}, {@link Series#hide}, or in the initial + * configuration. + * + * @name Highcharts.Series#visible + * @type {boolean} + */ + visible: options.visible !== false, + /** + * Read only. The series' selected state as set by {@link + * Highcharts.Series#select}. + * + * @name Highcharts.Series#selected + * @type {boolean} + */ + selected: options.selected === true // false by default + }); + // Register event listeners + events = options.events; + objectEach(events, function (event, eventType) { + if (isFunction(event)) { + // If event does not exist, or is changed by Series.update + if (series.eventOptions[eventType] !== event) { + // Remove existing if set by option + if (isFunction(series.eventOptions[eventType])) { + removeEvent(series, eventType, series.eventOptions[eventType]); + } + series.eventOptions[eventType] = event; + addEvent(series, eventType, event); + } + } + }); + if ((events && events.click) || + (options.point && + options.point.events && + options.point.events.click) || + options.allowPointSelect) { + chart.runTrackerClick = true; + } + series.getColor(); + series.getSymbol(); + // Initialize the parallel data arrays + series.parallelArrays.forEach(function (key) { + if (!series[key + 'Data']) { + series[key + 'Data'] = []; + } + }); + // Mark cartesian + if (series.isCartesian) { + chart.hasCartesianSeries = true; + } + // Get the index and register the series in the chart. The index is + // one more than the current latest series index (#5960). + if (chartSeries.length) { + lastSeries = chartSeries[chartSeries.length - 1]; + } + series._i = pick(lastSeries && lastSeries._i, -1) + 1; + // Insert the series and re-order all series above the insertion + // point. + chart.orderSeries(this.insert(chartSeries)); + // Set options for series with sorting and set data later. + if (options.dataSorting && options.dataSorting.enabled) { + series.setDataSortingOptions(); + } + else if (!series.points && !series.data) { + series.setData(options.data, false); + } + fireEvent(this, 'afterInit'); + }, + /** + * Check whether the series item is itself or inherits from a certain + * series type. + * + * @function Highcharts.Series#is + * @param {string} type The type of series to check for, can be either + * featured or custom series types. For example `column`, `pie`, + * `ohlc` etc. + * + * @return {boolean} + * True if this item is or inherits from the given type. + */ + is: function (type) { + return seriesTypes[type] && this instanceof seriesTypes[type]; + }, + /** + * Insert the series in a collection with other series, either the chart + * series or yAxis series, in the correct order according to the index + * option. Used internally when adding series. + * + * @private + * @function Highcharts.Series#insert + * @param {Array} collection + * A collection of series, like `chart.series` or `xAxis.series`. + * @return {number} + * The index of the series in the collection. + */ + insert: function (collection) { + var indexOption = this.options.index, i; + // Insert by index option + if (isNumber(indexOption)) { + i = collection.length; + while (i--) { + // Loop down until the interted element has higher index + if (indexOption >= + pick(collection[i].options.index, collection[i]._i)) { + collection.splice(i + 1, 0, this); + break; + } + } + if (i === -1) { + collection.unshift(this); + } + i = i + 1; + // Or just push it to the end + } + else { + collection.push(this); + } + return pick(i, collection.length - 1); + }, + /** + * Set the xAxis and yAxis properties of cartesian series, and register + * the series in the `axis.series` array. + * + * @private + * @function Highcharts.Series#bindAxes + * @return {void} + * @exception 18 + */ + bindAxes: function () { + var series = this, seriesOptions = series.options, chart = series.chart, axisOptions; + fireEvent(this, 'bindAxes', null, function () { + // repeat for xAxis and yAxis + (series.axisTypes || []).forEach(function (AXIS) { + // loop through the chart's axis objects + chart[AXIS].forEach(function (axis) { + axisOptions = axis.options; + // apply if the series xAxis or yAxis option mathches + // the number of the axis, or if undefined, use the + // first axis + if (seriesOptions[AXIS] === + axisOptions.index || + (typeof seriesOptions[AXIS] !== + 'undefined' && + seriesOptions[AXIS] === axisOptions.id) || + (typeof seriesOptions[AXIS] === + 'undefined' && + axisOptions.index === 0)) { + // register this series in the axis.series lookup + series.insert(axis.series); + // set this series.xAxis or series.yAxis reference + /** + * Read only. The unique xAxis object associated + * with the series. + * + * @name Highcharts.Series#xAxis + * @type {Highcharts.Axis} + */ + /** + * Read only. The unique yAxis object associated + * with the series. + * + * @name Highcharts.Series#yAxis + * @type {Highcharts.Axis} + */ + series[AXIS] = axis; + // mark dirty for redraw + axis.isDirty = true; + } + }); + // The series needs an X and an Y axis + if (!series[AXIS] && + series.optionalAxis !== AXIS) { + error(18, true, chart); + } + }); + }); + fireEvent(this, 'afterBindAxes'); + }, + /** + * For simple series types like line and column, the data values are + * held in arrays like xData and yData for quick lookup to find extremes + * and more. For multidimensional series like bubble and map, this can + * be extended with arrays like zData and valueData by adding to the + * `series.parallelArrays` array. + * + * @private + * @function Highcharts.Series#updateParallelArrays + * @param {Highcharts.Point} point + * @param {number|string} i + * @return {void} + */ + updateParallelArrays: function (point, i) { + var series = point.series, args = arguments, fn = isNumber(i) ? + // Insert the value in the given position + function (key) { + var val = key === 'y' && series.toYData ? + series.toYData(point) : + point[key]; + series[key + 'Data'][i] = val; + } : + // Apply the method specified in i with the following + // arguments as arguments + function (key) { + Array.prototype[i].apply(series[key + 'Data'], Array.prototype.slice.call(args, 2)); + }; + series.parallelArrays.forEach(fn); + }, + /** + * Define hasData functions for series. These return true if there + * are data points on this series within the plot area. + * + * @private + * @function Highcharts.Series#hasData + * @return {boolean} + */ + hasData: function () { + return ((this.visible && + typeof this.dataMax !== 'undefined' && + typeof this.dataMin !== 'undefined') || ( // #3703 + this.visible && + this.yData && + this.yData.length > 0) // #9758 + ); + }, + /** + * Return an auto incremented x value based on the pointStart and + * pointInterval options. This is only used if an x value is not given + * for the point that calls autoIncrement. + * + * @private + * @function Highcharts.Series#autoIncrement + * @return {number} + */ + autoIncrement: function () { + var options = this.options, xIncrement = this.xIncrement, date, pointInterval, pointIntervalUnit = options.pointIntervalUnit, time = this.chart.time; + xIncrement = pick(xIncrement, options.pointStart, 0); + this.pointInterval = pointInterval = pick(this.pointInterval, options.pointInterval, 1); + // Added code for pointInterval strings + if (pointIntervalUnit) { + date = new time.Date(xIncrement); + if (pointIntervalUnit === 'day') { + time.set('Date', date, time.get('Date', date) + pointInterval); + } + else if (pointIntervalUnit === 'month') { + time.set('Month', date, time.get('Month', date) + pointInterval); + } + else if (pointIntervalUnit === 'year') { + time.set('FullYear', date, time.get('FullYear', date) + pointInterval); + } + pointInterval = date.getTime() - xIncrement; + } + this.xIncrement = xIncrement + pointInterval; + return xIncrement; + }, + /** + * Internal function to set properties for series if data sorting is + * enabled. + * + * @private + * @function Highcharts.Series#setDataSortingOptions + * @return {void} + */ + setDataSortingOptions: function () { + var options = this.options; + extend(this, { + requireSorting: false, + sorted: false, + enabledDataSorting: true, + allowDG: false + }); + // To allow unsorted data for column series. + if (!defined(options.pointRange)) { + options.pointRange = 1; + } + }, + /** + * Set the series options by merging from the options tree. Called + * internally on initializing and updating series. This function will + * not redraw the series. For API usage, use {@link Series#update}. + * @private + * @function Highcharts.Series#setOptions + * @param {Highcharts.SeriesOptionsType} itemOptions + * The series options. + * @return {Highcharts.SeriesOptionsType} + * @fires Highcharts.Series#event:afterSetOptions + */ + setOptions: function (itemOptions) { + var chart = this.chart, chartOptions = chart.options, plotOptions = chartOptions.plotOptions, userOptions = chart.userOptions || {}, seriesUserOptions = merge(itemOptions), options, zones, zone, styledMode = chart.styledMode, e = { + plotOptions: plotOptions, + userOptions: seriesUserOptions + }; + fireEvent(this, 'setOptions', e); + // These may be modified by the event + var typeOptions = e.plotOptions[this.type], userPlotOptions = (userOptions.plotOptions || {}); + // use copy to prevent undetected changes (#9762) + this.userOptions = e.userOptions; + options = merge(typeOptions, plotOptions.series, + // #3881, chart instance plotOptions[type] should trump + // plotOptions.series + userOptions.plotOptions && + userOptions.plotOptions[this.type], seriesUserOptions); + // The tooltip options are merged between global and series specific + // options. Importance order asscendingly: + // globals: (1)tooltip, (2)plotOptions.series, + // (3)plotOptions[this.type] + // init userOptions with possible later updates: 4-6 like 1-3 and + // (7)this series options + this.tooltipOptions = merge(defaultOptions.tooltip, // 1 + defaultOptions.plotOptions.series && + defaultOptions.plotOptions.series.tooltip, // 2 + defaultOptions.plotOptions[this.type].tooltip, // 3 + chartOptions.tooltip.userOptions, // 4 + plotOptions.series && + plotOptions.series.tooltip, // 5 + plotOptions[this.type].tooltip, // 6 + seriesUserOptions.tooltip // 7 + ); + // When shared tooltip, stickyTracking is true by default, + // unless user says otherwise. + this.stickyTracking = pick(seriesUserOptions.stickyTracking, userPlotOptions[this.type] && + userPlotOptions[this.type].stickyTracking, userPlotOptions.series && userPlotOptions.series.stickyTracking, (this.tooltipOptions.shared && !this.noSharedTooltip ? + true : + options.stickyTracking)); + // Delete marker object if not allowed (#1125) + if (typeOptions.marker === null) { + delete options.marker; + } + // Handle color zones + this.zoneAxis = options.zoneAxis; + zones = this.zones = (options.zones || []).slice(); + if ((options.negativeColor || options.negativeFillColor) && + !options.zones) { + zone = { + value: options[this.zoneAxis + 'Threshold'] || + options.threshold || + 0, + className: 'highcharts-negative' + }; + if (!styledMode) { + zone.color = options.negativeColor; + zone.fillColor = options.negativeFillColor; + } + zones.push(zone); + } + if (zones.length) { // Push one extra zone for the rest + if (defined(zones[zones.length - 1].value)) { + zones.push(styledMode ? {} : { + color: this.color, + fillColor: this.fillColor + }); + } + } + fireEvent(this, 'afterSetOptions', { options: options }); + return options; + }, + /** + * Return series name in "Series {Number}" format or the one defined by + * a user. This method can be simply overridden as series name format + * can vary (e.g. technical indicators). + * + * @function Highcharts.Series#getName + * @return {string} + * The series name. + */ + getName: function () { + // #4119 + return pick(this.options.name, 'Series ' + (this.index + 1)); + }, + /** + * @private + * @function Highcharts.Series#getCyclic + * @param {string} prop + * @param {*} [value] + * @param {Highcharts.Dictionary} [defaults] + * @return {void} + */ + getCyclic: function (prop, value, defaults) { + var i, chart = this.chart, userOptions = this.userOptions, indexName = prop + 'Index', counterName = prop + 'Counter', len = defaults ? defaults.length : pick(chart.options.chart[prop + 'Count'], chart[prop + 'Count']), setting; + if (!value) { + // Pick up either the colorIndex option, or the _colorIndex + // after Series.update() + setting = pick(userOptions[indexName], userOptions['_' + indexName]); + if (defined(setting)) { // after Series.update() + i = setting; + } + else { + // #6138 + if (!chart.series.length) { + chart[counterName] = 0; + } + userOptions['_' + indexName] = i = + chart[counterName] % len; + chart[counterName] += 1; + } + if (defaults) { + value = defaults[i]; + } + } + // Set the colorIndex + if (typeof i !== 'undefined') { + this[indexName] = i; + } + this[prop] = value; + }, + /** + * Get the series' color based on either the options or pulled from + * global options. + * + * @private + * @function Highcharts.Series#getColor + * @return {void} + */ + getColor: function () { + if (this.chart.styledMode) { + this.getCyclic('color'); + } + else if (this.options.colorByPoint) { + // #4359, selected slice got series.color even when colorByPoint + // was set. + this.options.color = null; + } + else { + this.getCyclic('color', this.options.color || + defaultPlotOptions[this.type].color, this.chart.options.colors); + } + }, + /** + * Get all points' instances created for this series. + * + * @private + * @function Highcharts.Series#getPointsCollection + * @return {Array} + */ + getPointsCollection: function () { + return (this.hasGroupedData ? this.points : this.data) || []; + }, + /** + * Get the series' symbol based on either the options or pulled from + * global options. + * + * @private + * @function Highcharts.Series#getSymbol + * @return {void} + */ + getSymbol: function () { + var seriesMarkerOption = this.options.marker; + this.getCyclic('symbol', seriesMarkerOption.symbol, this.chart.options.symbols); + }, + /** + * Finds the index of an existing point that matches the given point + * options. + * + * @private + * @function Highcharts.Series#findPointIndex + * @param {Highcharts.PointOptionsObject} optionsObject + * The options of the point. + * @param {number} fromIndex + * The index to start searching from, used for optimizing + * series with required sorting. + * @returns {number|undefined} + * Returns the index of a matching point, or undefined if no + * match is found. + */ + findPointIndex: function (optionsObject, fromIndex) { + var id = optionsObject.id, x = optionsObject.x, oldData = this.points, matchingPoint, matchedById, pointIndex, matchKey, dataSorting = this.options.dataSorting; + if (id) { + matchingPoint = this.chart.get(id); + } + else if (this.linkedParent || this.enabledDataSorting) { + matchKey = (dataSorting && dataSorting.matchByName) ? + 'name' : 'index'; + matchingPoint = find(oldData, function (oldPoint) { + return !oldPoint.touched && oldPoint[matchKey] === + optionsObject[matchKey]; + }); + // Add unmatched point as a new point + if (!matchingPoint) { + return void 0; + } + } + if (matchingPoint) { + pointIndex = matchingPoint && matchingPoint.index; + if (typeof pointIndex !== 'undefined') { + matchedById = true; + } + } + // Search for the same X in the existing data set + if (typeof pointIndex === 'undefined' && isNumber(x)) { + pointIndex = this.xData.indexOf(x, fromIndex); + } + // Reduce pointIndex if data is cropped + if (pointIndex !== -1 && + typeof pointIndex !== 'undefined' && + this.cropped) { + pointIndex = (pointIndex >= this.cropStart) ? + pointIndex - this.cropStart : pointIndex; + } + if (!matchedById && + oldData[pointIndex] && oldData[pointIndex].touched) { + pointIndex = void 0; + } + return pointIndex; + }, + /** + * @private + * @borrows LegendSymbolMixin.drawLineMarker as Highcharts.Series#drawLegendSymbol + */ + drawLegendSymbol: LegendSymbolMixin.drawLineMarker, + /** + * Internal function called from setData. If the point count is the same + * as is was, or if there are overlapping X values, just run + * Point.update which is cheaper, allows animation, and keeps references + * to points. This also allows adding or removing points if the X-es + * don't match. + * + * @private + * @function Highcharts.Series#updateData + * + * @param {Array} data + * + * @return {boolean} + */ + updateData: function (data, animation) { + var options = this.options, dataSorting = options.dataSorting, oldData = this.points, pointsToAdd = [], hasUpdatedByKey, i, point, lastIndex, requireSorting = this.requireSorting, equalLength = data.length === oldData.length, succeeded = true; + this.xIncrement = null; + // Iterate the new data + data.forEach(function (pointOptions, i) { + var id, x, pointIndex, optionsObject = (defined(pointOptions) && + this.pointClass.prototype.optionsToObject.call({ series: this }, pointOptions)) || {}; + // Get the x of the new data point + x = optionsObject.x; + id = optionsObject.id; + if (id || isNumber(x)) { + pointIndex = this.findPointIndex(optionsObject, lastIndex); + // Matching X not found + // or used already due to ununique x values (#8995), + // add point (but later) + if (pointIndex === -1 || + typeof pointIndex === 'undefined') { + pointsToAdd.push(pointOptions); + // Matching X found, update + } + else if (oldData[pointIndex] && + pointOptions !== options.data[pointIndex]) { + oldData[pointIndex].update(pointOptions, false, null, false); + // Mark it touched, below we will remove all points that + // are not touched. + oldData[pointIndex].touched = true; + // Speed optimize by only searching after last known + // index. Performs ~20% bettor on large data sets. + if (requireSorting) { + lastIndex = pointIndex + 1; + } + // Point exists, no changes, don't remove it + } + else if (oldData[pointIndex]) { + oldData[pointIndex].touched = true; + } + // If the length is equal and some of the nodes had a + // match in the same position, we don't want to remove + // non-matches. + if (!equalLength || + i !== pointIndex || + (dataSorting && dataSorting.enabled) || + this.hasDerivedData) { + hasUpdatedByKey = true; + } + } + else { + // Gather all points that are not matched + pointsToAdd.push(pointOptions); + } + }, this); + // Remove points that don't exist in the updated data set + if (hasUpdatedByKey) { + i = oldData.length; + while (i--) { + point = oldData[i]; + if (point && !point.touched && point.remove) { + point.remove(false, animation); + } + } + // If we did not find keys (ids or x-values), and the length is the + // same, update one-to-one + } + else if (equalLength && (!dataSorting || !dataSorting.enabled)) { + data.forEach(function (point, i) { + // .update doesn't exist on a linked, hidden series (#3709) + // (#10187) + if (oldData[i].update && point !== oldData[i].y) { + oldData[i].update(point, false, null, false); + } + }); + // Don't add new points since those configs are used above + pointsToAdd.length = 0; + // Did not succeed in updating data + } + else { + succeeded = false; + } + oldData.forEach(function (point) { + if (point) { + point.touched = false; + } + }); + if (!succeeded) { + return false; + } + // Add new points + pointsToAdd.forEach(function (point) { + this.addPoint(point, false, null, null, false); + }, this); + if (this.xIncrement === null && + this.xData && + this.xData.length) { + this.xIncrement = arrayMax(this.xData); + this.autoIncrement(); + } + return true; + }, + /** + * Apply a new set of data to the series and optionally redraw it. The + * new data array is passed by reference (except in case of + * `updatePoints`), and may later be mutated when updating the chart + * data. + * + * Note the difference in behaviour when setting the same amount of + * points, or a different amount of points, as handled by the + * `updatePoints` parameter. + * + * @sample highcharts/members/series-setdata/ + * Set new data from a button + * @sample highcharts/members/series-setdata-pie/ + * Set data in a pie + * @sample stock/members/series-setdata/ + * Set new data in Highstock + * @sample maps/members/series-setdata/ + * Set new data in Highmaps + * + * @function Highcharts.Series#setData + * + * @param {Array} data + * Takes an array of data in the same format as described under + * `series.{type}.data` for the given series type, for example a + * line series would take data in the form described under + * [series.line.data](https://api.highcharts.com/highcharts/series.line.data). + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the series is altered. If + * doing more operations on the chart, it is a good idea to set + * redraw to false and call {@link Chart#redraw} after. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * When the updated data is the same length as the existing data, + * points will be updated by default, and animation visualizes + * how the points are changed. Set false to disable animation, or + * a configuration object to set duration or easing. + * + * @param {boolean} [updatePoints=true] + * When this is true, points will be updated instead of replaced + * whenever possible. This occurs a) when the updated data is the + * same length as the existing data, b) when points are matched + * by their id's, or c) when points can be matched by X values. + * This allows updating with animation and performs better. In + * this case, the original array is not passed by reference. Set + * `false` to prevent. + * + * @return {void} + */ + setData: function (data, redraw, animation, updatePoints) { + var series = this, oldData = series.points, oldDataLength = (oldData && oldData.length) || 0, dataLength, options = series.options, chart = series.chart, dataSorting = options.dataSorting, firstPoint = null, xAxis = series.xAxis, i, turboThreshold = options.turboThreshold, pt, xData = this.xData, yData = this.yData, pointArrayMap = series.pointArrayMap, valueCount = pointArrayMap && pointArrayMap.length, keys = options.keys, indexOfX = 0, indexOfY = 1, updatedData; + data = data || []; + dataLength = data.length; + redraw = pick(redraw, true); + if (dataSorting && dataSorting.enabled) { + data = this.sortData(data); + } + // First try to run Point.update which is cheaper, allows animation, + // and keeps references to points. + if (updatePoints !== false && + dataLength && + oldDataLength && + !series.cropped && + !series.hasGroupedData && + series.visible && + // Soft updating has no benefit in boost, and causes JS error + // (#8355) + !series.isSeriesBoosting) { + updatedData = this.updateData(data, animation); + } + if (!updatedData) { + // Reset properties + series.xIncrement = null; + series.colorCounter = 0; // for series with colorByPoint (#1547) + // Update parallel arrays + this.parallelArrays.forEach(function (key) { + series[key + 'Data'].length = 0; + }); + // In turbo mode, only one- or twodimensional arrays of numbers + // are allowed. The first value is tested, and we assume that + // all the rest are defined the same way. Although the 'for' + // loops are similar, they are repeated inside each if-else + // conditional for max performance. + if (turboThreshold && dataLength > turboThreshold) { + firstPoint = series.getFirstValidPoint(data); + if (isNumber(firstPoint)) { // assume all points are numbers + for (i = 0; i < dataLength; i++) { + xData[i] = this.autoIncrement(); + yData[i] = data[i]; + } + // Assume all points are arrays when first point is + } + else if (isArray(firstPoint)) { + if (valueCount) { // [x, low, high] or [x, o, h, l, c] + for (i = 0; i < dataLength; i++) { + pt = data[i]; + xData[i] = pt[0]; + yData[i] = + pt.slice(1, valueCount + 1); + } + } + else { // [x, y] + if (keys) { + indexOfX = keys.indexOf('x'); + indexOfY = keys.indexOf('y'); + indexOfX = indexOfX >= 0 ? indexOfX : 0; + indexOfY = indexOfY >= 0 ? indexOfY : 1; + } + for (i = 0; i < dataLength; i++) { + pt = data[i]; + xData[i] = pt[indexOfX]; + yData[i] = pt[indexOfY]; + } + } + } + else { + // Highcharts expects configs to be numbers or arrays in + // turbo mode + error(12, false, chart); + } + } + else { + for (i = 0; i < dataLength; i++) { + // stray commas in oldIE: + if (typeof data[i] !== 'undefined') { + pt = { series: series }; + series.pointClass.prototype.applyOptions.apply(pt, [data[i]]); + series.updateParallelArrays(pt, i); + } + } + } + // Forgetting to cast strings to numbers is a common caveat when + // handling CSV or JSON + if (yData && isString(yData[0])) { + error(14, true, chart); + } + series.data = []; + series.options.data = series.userOptions.data = data; + // destroy old points + i = oldDataLength; + while (i--) { + if (oldData[i] && oldData[i].destroy) { + oldData[i].destroy(); + } + } + // reset minRange (#878) + if (xAxis) { + xAxis.minRange = xAxis.userMinRange; + } + // redraw + series.isDirty = chart.isDirtyBox = true; + series.isDirtyData = !!oldData; + animation = false; + } + // Typically for pie series, points need to be processed and + // generated prior to rendering the legend + if (options.legendType === 'point') { + this.processData(); + this.generatePoints(); + } + if (redraw) { + chart.redraw(animation); + } + }, + /** + * Internal function to sort series data + * + * @private + * @function Highcharts.Series#sortData + * @param {Array} data + * Force data grouping. + * @return {Array} + */ + sortData: function (data) { + var series = this, options = series.options, dataSorting = options.dataSorting, sortKey = dataSorting.sortKey || 'y', sortedData, getPointOptionsObject = function (series, pointOptions) { + return (defined(pointOptions) && + series.pointClass.prototype.optionsToObject.call({ + series: series + }, pointOptions)) || {}; + }; + data.forEach(function (pointOptions, i) { + data[i] = getPointOptionsObject(series, pointOptions); + data[i].index = i; + }, this); + // Sorting + sortedData = data.concat().sort(function (a, b) { + var aValue = getNestedProperty(sortKey, a); + var bValue = getNestedProperty(sortKey, b); + return bValue < aValue ? -1 : bValue > aValue ? 1 : 0; + }); + // Set x value depending on the position in the array + sortedData.forEach(function (point, i) { + point.x = i; + }, this); + // Set the same x for linked series points if they don't have their + // own sorting + if (series.linkedSeries) { + series.linkedSeries.forEach(function (linkedSeries) { + var options = linkedSeries.options, seriesData = options.data; + if ((!options.dataSorting || + !options.dataSorting.enabled) && + seriesData) { + seriesData.forEach(function (pointOptions, i) { + seriesData[i] = getPointOptionsObject(linkedSeries, pointOptions); + if (data[i]) { + seriesData[i].x = data[i].x; + seriesData[i].index = i; + } + }); + linkedSeries.setData(seriesData, false); + } + }); + } + return data; + }, + /** + * Internal function to process the data by cropping away unused data + * points if the series is longer than the crop threshold. This saves + * computing time for large series. + * + * @private + * @function Highcharts.Series#getProcessedData + * @param {boolean} [forceExtremesFromAll] + * Force getting extremes of a total series data range. + * @return {Highcharts.SeriesProcessedDataObject} + */ + getProcessedData: function (forceExtremesFromAll) { + var series = this, + // copied during slice operation: + processedXData = series.xData, processedYData = series.yData, dataLength = processedXData.length, croppedData, cropStart = 0, cropped, distance, closestPointRange, xAxis = series.xAxis, i, // loop variable + options = series.options, cropThreshold = options.cropThreshold, getExtremesFromAll = forceExtremesFromAll || + series.getExtremesFromAll || + options.getExtremesFromAll, // #4599 + isCartesian = series.isCartesian, xExtremes, val2lin = xAxis && xAxis.val2lin, isLog = !!(xAxis && xAxis.logarithmic), throwOnUnsorted = series.requireSorting, min, max; + if (xAxis) { + // corrected for log axis (#3053) + xExtremes = xAxis.getExtremes(); + min = xExtremes.min; + max = xExtremes.max; + } + // optionally filter out points outside the plot area + if (isCartesian && + series.sorted && + !getExtremesFromAll && + (!cropThreshold || + dataLength > cropThreshold || + series.forceCrop)) { + // it's outside current extremes + if (processedXData[dataLength - 1] < min || + processedXData[0] > max) { + processedXData = []; + processedYData = []; + // only crop if it's actually spilling out + } + else if (series.yData && (processedXData[0] < min || + processedXData[dataLength - 1] > max)) { + croppedData = this.cropData(series.xData, series.yData, min, max); + processedXData = croppedData.xData; + processedYData = croppedData.yData; + cropStart = croppedData.start; + cropped = true; + } + } + // Find the closest distance between processed points + i = processedXData.length || 1; + while (--i) { + distance = (isLog ? + (val2lin(processedXData[i]) - + val2lin(processedXData[i - 1])) : + (processedXData[i] - + processedXData[i - 1])); + if (distance > 0 && + (typeof closestPointRange === 'undefined' || + distance < closestPointRange)) { + closestPointRange = distance; + // Unsorted data is not supported by the line tooltip, as well + // as data grouping and navigation in Stock charts (#725) and + // width calculation of columns (#1900) + } + else if (distance < 0 && throwOnUnsorted) { + error(15, false, series.chart); + throwOnUnsorted = false; // Only once + } + } + return { + xData: processedXData, + yData: processedYData, + cropped: cropped, + cropStart: cropStart, + closestPointRange: closestPointRange + }; + }, + /** + * Internal function to apply processed data. + * In Highstock, this function is extended to provide data grouping. + * + * @private + * @function Highcharts.Series#processData + * @param {boolean} [force] + * Force data grouping. + * @return {boolean|undefined} + */ + processData: function (force) { + var series = this, xAxis = series.xAxis, processedData; + // If the series data or axes haven't changed, don't go through + // this. Return false to pass the message on to override methods + // like in data grouping. + if (series.isCartesian && + !series.isDirty && + !xAxis.isDirty && + !series.yAxis.isDirty && + !force) { + return false; + } + processedData = series.getProcessedData(); + // Record the properties + series.cropped = processedData.cropped; // undefined or true + series.cropStart = processedData.cropStart; + series.processedXData = processedData.xData; + series.processedYData = processedData.yData; + series.closestPointRange = + series.basePointRange = processedData.closestPointRange; + }, + /** + * Iterate over xData and crop values between min and max. Returns + * object containing crop start/end cropped xData with corresponding + * part of yData, dataMin and dataMax within the cropped range. + * + * @private + * @function Highcharts.Series#cropData + * @param {Array} xData + * @param {Array} yData + * @param {number} min + * @param {number} max + * @param {number} [cropShoulder] + * @return {Highcharts.SeriesCropDataObject} + */ + cropData: function (xData, yData, min, max, cropShoulder) { + var dataLength = xData.length, cropStart = 0, cropEnd = dataLength, i, j; + // line-type series need one point outside + cropShoulder = pick(cropShoulder, this.cropShoulder); + // iterate up to find slice start + for (i = 0; i < dataLength; i++) { + if (xData[i] >= min) { + cropStart = Math.max(0, i - cropShoulder); + break; + } + } + // proceed to find slice end + for (j = i; j < dataLength; j++) { + if (xData[j] > max) { + cropEnd = j + cropShoulder; + break; + } + } + return { + xData: xData.slice(cropStart, cropEnd), + yData: yData.slice(cropStart, cropEnd), + start: cropStart, + end: cropEnd + }; + }, + /** + * Generate the data point after the data has been processed by cropping + * away unused points and optionally grouped in Highcharts Stock. + * + * @private + * @function Highcharts.Series#generatePoints + * @return {void} + */ + generatePoints: function () { + var series = this, options = series.options, dataOptions = options.data, data = series.data, dataLength, processedXData = series.processedXData, processedYData = series.processedYData, PointClass = series.pointClass, processedDataLength = processedXData.length, cropStart = series.cropStart || 0, cursor, hasGroupedData = series.hasGroupedData, keys = options.keys, point, points = [], i; + if (!data && !hasGroupedData) { + var arr = []; + arr.length = dataOptions.length; + data = series.data = arr; + } + if (keys && hasGroupedData) { + // grouped data has already applied keys (#6590) + series.options.keys = false; + } + for (i = 0; i < processedDataLength; i++) { + cursor = cropStart + i; + if (!hasGroupedData) { + point = data[cursor]; + // #970: + if (!point && + typeof dataOptions[cursor] !== 'undefined') { + data[cursor] = point = (new PointClass()).init(series, dataOptions[cursor], processedXData[i]); + } + } + else { + // splat the y data in case of ohlc data array + point = (new PointClass()).init(series, [processedXData[i]].concat(splat(processedYData[i]))); + /** + * Highstock only. If a point object is created by data + * grouping, it doesn't reflect actual points in the raw + * data. In this case, the `dataGroup` property holds + * information that points back to the raw data. + * + * - `dataGroup.start` is the index of the first raw data + * point in the group. + * + * - `dataGroup.length` is the amount of points in the + * group. + * + * @product highstock + * + * @name Highcharts.Point#dataGroup + * @type {Highcharts.DataGroupingInfoObject|undefined} + */ + point.dataGroup = series.groupMap[i]; + if (point.dataGroup.options) { + point.options = point.dataGroup.options; + extend(point, point.dataGroup.options); + // Collision of props and options (#9770) + delete point.dataLabels; + } + } + if (point) { // #6279 + /** + * Contains the point's index in the `Series.points` array. + * + * @name Highcharts.Point#index + * @type {number} + * @readonly + */ + point.index = cursor; // For faster access in Point.update + points[i] = point; + } + } + // restore keys options (#6590) + series.options.keys = keys; + // Hide cropped-away points - this only runs when the number of + // points is above cropThreshold, or when swithching view from + // non-grouped data to grouped data (#637) + if (data && + (processedDataLength !== (dataLength = data.length) || + hasGroupedData)) { + for (i = 0; i < dataLength; i++) { + // when has grouped data, clear all points + if (i === cropStart && !hasGroupedData) { + i += processedDataLength; + } + if (data[i]) { + data[i].destroyElements(); + data[i].plotX = void 0; // #1003 + } + } + } + /** + * Read only. An array containing those values converted to points. + * In case the series data length exceeds the `cropThreshold`, or if + * the data is grouped, `series.data` doesn't contain all the + * points. Also, in case a series is hidden, the `data` array may be + * empty. To access raw values, `series.options.data` will always be + * up to date. `Series.data` only contains the points that have been + * created on demand. To modify the data, use + * {@link Highcharts.Series#setData} or + * {@link Highcharts.Point#update}. + * + * @see Series.points + * + * @name Highcharts.Series#data + * @type {Array} + */ + series.data = data; + /** + * An array containing all currently visible point objects. In case + * of cropping, the cropped-away points are not part of this array. + * The `series.points` array starts at `series.cropStart` compared + * to `series.data` and `series.options.data`. If however the series + * data is grouped, these can't be correlated one to one. To modify + * the data, use {@link Highcharts.Series#setData} or + * {@link Highcharts.Point#update}. + * + * @name Highcharts.Series#points + * @type {Array} + */ + series.points = points; + fireEvent(this, 'afterGeneratePoints'); + }, + /** + * Get current X extremes for the visible data. + * + * @private + * @function Highcharts.Series#getXExtremes + * + * @param {Array} xData + * The data to inspect. Defaults to the current data within the + * visible range. + * @return {Highcharts.RangeObject} + */ + getXExtremes: function (xData) { + return { + min: arrayMin(xData), + max: arrayMax(xData) + }; + }, + /** + * Calculate Y extremes for the visible data. The result is returned + * as an object with `dataMin` and `dataMax` properties. + * + * @private + * @function Highcharts.Series#getExtremes + * @param {Array} [yData] + * The data to inspect. Defaults to the current data within the + * visible range. + * @param {boolean} [forceExtremesFromAll] + * Force getting extremes of a total series data range. + * @return {Highcharts.DataExtremesObject} + */ + getExtremes: function (yData, forceExtremesFromAll) { + var xAxis = this.xAxis, yAxis = this.yAxis, xData = this.processedXData || this.xData, yDataLength, activeYData = [], activeCounter = 0, + // #2117, need to compensate for log X axis + xExtremes, xMin = 0, xMax = 0, validValue, withinRange, + // Handle X outside the viewed area. This does not work with + // non-sorted data like scatter (#7639). + shoulder = this.requireSorting ? this.cropShoulder : 0, positiveValuesOnly = yAxis ? yAxis.positiveValuesOnly : false, x, y, i, j; + yData = yData || this.stackedYData || this.processedYData || []; + yDataLength = yData.length; + if (xAxis) { + xExtremes = xAxis.getExtremes(); + xMin = xExtremes.min; + xMax = xExtremes.max; + } + for (i = 0; i < yDataLength; i++) { + x = xData[i]; + y = yData[i]; + // For points within the visible range, including the first + // point outside the visible range (#7061), consider y extremes. + validValue = ((isNumber(y) || isArray(y)) && + ((y.length || y > 0) || !positiveValuesOnly)); + withinRange = (forceExtremesFromAll || + this.getExtremesFromAll || + this.options.getExtremesFromAll || + this.cropped || + !xAxis || // for colorAxis support + ((xData[i + shoulder] || x) >= xMin && + (xData[i - shoulder] || x) <= xMax)); + if (validValue && withinRange) { + j = y.length; + if (j) { // array, like ohlc or range data + while (j--) { + if (isNumber(y[j])) { // #7380, #11513 + activeYData[activeCounter++] = y[j]; + } + } + } + else { + activeYData[activeCounter++] = y; + } + } + } + var dataExtremes = { + dataMin: arrayMin(activeYData), + dataMax: arrayMax(activeYData) + }; + fireEvent(this, 'afterGetExtremes', { dataExtremes: dataExtremes }); + return dataExtremes; + }, + /** + * Set the current data extremes as `dataMin` and `dataMax` on the + * Series item. Use this only when the series properties should be + * updated. + * + * @private + * @function Highcharts.Series#applyExtremes + * @return {void} + */ + applyExtremes: function () { + var dataExtremes = this.getExtremes(); + /** + * Contains the minimum value of the series' data point. + * @name Highcharts.Series#dataMin + * @type {number} + * @readonly + */ + this.dataMin = dataExtremes.dataMin; + /* * + * Contains the maximum value of the series' data point. + * @name Highcharts.Series#dataMax + * @type {number} + * @readonly + */ + this.dataMax = dataExtremes.dataMax; + return dataExtremes; + }, + /** + * Find and return the first non null point in the data + * + * @private + * @function Highcharts.Series.getFirstValidPoint + * @param {Array} data + * Array of options for points + * + * @return {Highcharts.PointOptionsType} + */ + getFirstValidPoint: function (data) { + var firstPoint = null, dataLength = data.length, i = 0; + while (firstPoint === null && i < dataLength) { + firstPoint = data[i]; + i++; + } + return firstPoint; + }, + /** + * Translate data points from raw data values to chart specific + * positioning data needed later in the `drawPoints` and `drawGraph` + * functions. This function can be overridden in plugins and custom + * series type implementations. + * + * @function Highcharts.Series#translate + * @return {void} + * @fires Highcharts.Series#events:translate + */ + translate: function () { + if (!this.processedXData) { // hidden series + this.processData(); + } + this.generatePoints(); + var series = this, options = series.options, stacking = options.stacking, xAxis = series.xAxis, categories = xAxis.categories, enabledDataSorting = series.enabledDataSorting, yAxis = series.yAxis, points = series.points, dataLength = points.length, hasModifyValue = !!series.modifyValue, i, pointPlacement = series.pointPlacementToXValue(), // #7860 + dynamicallyPlaced = Boolean(pointPlacement), threshold = options.threshold, stackThreshold = options.startFromThreshold ? threshold : 0, plotX, lastPlotX, stackIndicator, zoneAxis = this.zoneAxis || 'y', closestPointRangePx = Number.MAX_VALUE; + /** + * Plotted coordinates need to be within a limited range. Drawing + * too far outside the viewport causes various rendering issues + * (#3201, #3923, #7555). + * @private + */ + function limitedRange(val) { + return clamp(val, -1e5, 1e5); + } + // Translate each point + for (i = 0; i < dataLength; i++) { + var point = points[i], xValue = point.x, yValue = point.y, yBottom = point.low, stack = stacking && yAxis.stacking && yAxis.stacking.stacks[(series.negStacks && + yValue < + (stackThreshold ? 0 : threshold) ? + '-' : + '') + series.stackKey], pointStack, stackValues; + // Discard disallowed y values for log axes (#3434) + if (yAxis.positiveValuesOnly && + yValue !== null && + yValue <= 0) { + point.isNull = true; + } + // Get the plotX translation + point.plotX = plotX = correctFloat(// #5236 + limitedRange(xAxis.translate(// #3923 + xValue, 0, 0, 0, 1, pointPlacement, this.type === 'flags')) // #3923 + ); + // Calculate the bottom y value for stacked series + if (stacking && + series.visible && + stack && + stack[xValue]) { + stackIndicator = series.getStackIndicator(stackIndicator, xValue, series.index); + if (!point.isNull) { + pointStack = stack[xValue]; + stackValues = + pointStack.points[stackIndicator.key]; + } + } + if (isArray(stackValues)) { + yBottom = stackValues[0]; + yValue = stackValues[1]; + if (yBottom === stackThreshold && + stackIndicator.key === + stack[xValue].base) { + yBottom = pick((isNumber(threshold) && threshold), yAxis.min); + } + // #1200, #1232 + if (yAxis.positiveValuesOnly && yBottom <= 0) { + yBottom = null; + } + point.total = point.stackTotal = pointStack.total; + point.percentage = + pointStack.total && + (point.y / pointStack.total * 100); + point.stackY = yValue; + // Place the stack label + // in case of variwide series (where widths of points are + // different in most cases), stack labels are positioned + // wrongly, so the call of the setOffset is omited here and + // labels are correctly positioned later, at the end of the + // variwide's translate function (#10962) + if (!series.irregularWidths) { + pointStack.setOffset(series.pointXOffset || 0, series.barW || 0); + } + } + // Set translated yBottom or remove it + point.yBottom = defined(yBottom) ? + limitedRange(yAxis.translate(yBottom, 0, 1, 0, 1)) : + null; + // general hook, used for Highstock compare mode + if (hasModifyValue) { + yValue = series.modifyValue(yValue, point); + } + // Set the the plotY value, reset it for redraws + // #3201 + point.plotY = ((typeof yValue === 'number' && yValue !== Infinity) ? + limitedRange(yAxis.translate(yValue, 0, 1, 0, 1)) : + void 0); + point.isInside = this.isPointInside(point); + // Set client related positions for mouse tracking + point.clientX = dynamicallyPlaced ? + correctFloat(xAxis.translate(xValue, 0, 0, 0, 1, pointPlacement)) : + plotX; // #1514, #5383, #5518 + // Negative points. For bubble charts, this means negative z + // values (#9728) + point.negative = point[zoneAxis] < (options[zoneAxis + 'Threshold'] || + threshold || + 0); + // some API data + point.category = (categories && + typeof categories[point.x] !== 'undefined' ? + categories[point.x] : + point.x); + // Determine auto enabling of markers (#3635, #5099) + if (!point.isNull && point.visible !== false) { + if (typeof lastPlotX !== 'undefined') { + closestPointRangePx = Math.min(closestPointRangePx, Math.abs(plotX - lastPlotX)); + } + lastPlotX = plotX; + } + // Find point zone + point.zone = (this.zones.length && point.getZone()); + // Animate new points with data sorting + if (!point.graphic && series.group && enabledDataSorting) { + point.isNew = true; + } + } + series.closestPointRangePx = closestPointRangePx; + fireEvent(this, 'afterTranslate'); + }, + /** + * Return the series points with null points filtered out. + * + * @function Highcharts.Series#getValidPoints + * + * @param {Array} [points] + * The points to inspect, defaults to {@link Series.points}. + * + * @param {boolean} [insideOnly=false] + * Whether to inspect only the points that are inside the visible + * view. + * + * @param {boolean} [allowNull=false] + * Whether to allow null points to pass as valid points. + * + * @return {Array} + * The valid points. + */ + getValidPoints: function (points, insideOnly, allowNull) { + var chart = this.chart; + // #3916, #5029, #5085 + return (points || this.points || []).filter(function isValidPoint(point) { + if (insideOnly && !chart.isInsidePlot(point.plotX, point.plotY, chart.inverted)) { + return false; + } + return point.visible !== false && + (allowNull || !point.isNull); + }); + }, + /** + * Get the clipping for the series. Could be called for a series to + * initiate animating the clip or to set the final clip (only width + * and x). + * + * @private + * @function Highcharts.Series#getClip + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * Initialize the animation. + * @param {boolean} [finalBox] + * Final size for the clip - end state for the animation. + * @return {Highcharts.Dictionary} + */ + getClipBox: function (animation, finalBox) { + var series = this, options = series.options, chart = series.chart, inverted = chart.inverted, xAxis = series.xAxis, yAxis = xAxis && series.yAxis, clipBox; + if (animation && options.clip === false && yAxis) { + // support for not clipped series animation (#10450) + clipBox = inverted ? { + y: -chart.chartWidth + yAxis.len + yAxis.pos, + height: chart.chartWidth, + width: chart.chartHeight, + x: -chart.chartHeight + xAxis.len + xAxis.pos + } : { + y: -yAxis.pos, + height: chart.chartHeight, + width: chart.chartWidth, + x: -xAxis.pos + }; + // x and width will be changed later when setting for animation + // initial state in Series.setClip + } + else { + clipBox = series.clipBox || chart.clipBox; + if (finalBox) { + clipBox.width = chart.plotSizeX; + clipBox.x = 0; + } + } + return !finalBox ? clipBox : { + width: clipBox.width, + x: clipBox.x + }; + }, + /** + * Set the clipping for the series. For animated series it is called + * twice, first to initiate animating the clip then the second time + * without the animation to set the final clip. + * + * @private + * @function Highcharts.Series#setClip + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * @return {void} + */ + setClip: function (animation) { + var chart = this.chart, options = this.options, renderer = chart.renderer, inverted = chart.inverted, seriesClipBox = this.clipBox, clipBox = this.getClipBox(animation), sharedClipKey = this.sharedClipKey || + [ + '_sharedClip', + animation && animation.duration, + animation && animation.easing, + clipBox.height, + options.xAxis, + options.yAxis + ].join(','), // #4526 + clipRect = chart[sharedClipKey], markerClipRect = chart[sharedClipKey + 'm']; + if (animation) { + clipBox.width = 0; + if (inverted) { + clipBox.x = chart.plotHeight + + (options.clip !== false ? 0 : chart.plotTop); + } + } + // If a clipping rectangle with the same properties is currently + // present in the chart, use that. + if (!clipRect) { + // When animation is set, prepare the initial positions + if (animation) { + chart[sharedClipKey + 'm'] = markerClipRect = + renderer.clipRect( + // include the width of the first marker + inverted ? chart.plotSizeX + 99 : -99, inverted ? -chart.plotLeft : -chart.plotTop, 99, inverted ? chart.chartWidth : chart.chartHeight); + } + chart[sharedClipKey] = clipRect = renderer.clipRect(clipBox); + // Create hashmap for series indexes + clipRect.count = { length: 0 }; + // When the series is rendered again before starting animating, in + // compliance to a responsive rule + } + else if (!chart.hasLoaded) { + clipRect.attr(clipBox); + } + if (animation) { + if (!clipRect.count[this.index]) { + clipRect.count[this.index] = true; + clipRect.count.length += 1; + } + } + if (options.clip !== false || animation) { + this.group.clip(animation || seriesClipBox ? clipRect : chart.clipRect); + this.markerGroup.clip(markerClipRect); + this.sharedClipKey = sharedClipKey; + } + // Remove the shared clipping rectangle when all series are shown + if (!animation) { + if (clipRect.count[this.index]) { + delete clipRect.count[this.index]; + clipRect.count.length -= 1; + } + if (clipRect.count.length === 0 && + sharedClipKey && + chart[sharedClipKey]) { + if (!seriesClipBox) { + chart[sharedClipKey] = + chart[sharedClipKey].destroy(); + } + if (chart[sharedClipKey + 'm']) { + chart[sharedClipKey + 'm'] = + chart[sharedClipKey + 'm'].destroy(); + } + } + } + }, + /** + * Animate in the series. Called internally twice. First with the `init` + * parameter set to true, which sets up the initial state of the + * animation. Then when ready, it is called with the `init` parameter + * undefined, in order to perform the actual animation. After the + * second run, the function is removed. + * + * @function Highcharts.Series#animate + * + * @param {boolean} [init] + * Initialize the animation. + * + * @return {void} + */ + animate: function (init) { + var series = this, chart = series.chart, animation = animObject(series.options.animation), clipRect, sharedClipKey, finalBox; + // Initialize the animation. Set up the clipping rectangle. + if (!chart.hasRendered) { + if (init) { + series.setClip(animation); + // Run the animation + } + else { + sharedClipKey = this.sharedClipKey; + clipRect = chart[sharedClipKey]; + finalBox = series.getClipBox(animation, true); + if (clipRect) { + clipRect.animate(finalBox, animation); + } + if (chart[sharedClipKey + 'm']) { + chart[sharedClipKey + 'm'].animate({ + width: finalBox.width + 99, + x: finalBox.x - (chart.inverted ? 0 : 99) + }, animation); + } + } + } + }, + /** + * This runs after animation to land on the final plot clipping. + * + * @private + * @function Highcharts.Series#afterAnimate + * @return {void} + * @fires Highcharts.Series#event:afterAnimate + */ + afterAnimate: function () { + this.setClip(); + fireEvent(this, 'afterAnimate'); + this.finishedAnimating = true; + }, + /** + * Draw the markers for line-like series types, and columns or other + * graphical representation for {@link Point} objects for other series + * types. The resulting element is typically stored as + * {@link Point.graphic}, and is created on the first call and updated + * and moved on subsequent calls. + * + * @function Highcharts.Series#drawPoints + */ + drawPoints: function () { + var series = this, points = series.points, chart = series.chart, i, point, graphic, verb, options = series.options, seriesMarkerOptions = options.marker, pointMarkerOptions, hasPointMarker, markerGroup = (series[series.specialGroup] || + series.markerGroup), xAxis = series.xAxis, markerAttribs, globallyEnabled = pick(seriesMarkerOptions.enabled, !xAxis || xAxis.isRadial ? true : null, + // Use larger or equal as radius is null in bubbles (#6321) + series.closestPointRangePx >= (seriesMarkerOptions.enabledThreshold * + seriesMarkerOptions.radius)); + if (seriesMarkerOptions.enabled !== false || + series._hasPointMarkers) { + for (i = 0; i < points.length; i++) { + point = points[i]; + graphic = point.graphic; + verb = graphic ? 'animate' : 'attr'; + pointMarkerOptions = point.marker || {}; + hasPointMarker = !!point.marker; + var shouldDrawMarker = ((globallyEnabled && + typeof pointMarkerOptions.enabled === 'undefined') || pointMarkerOptions.enabled) && !point.isNull && point.visible !== false; + // only draw the point if y is defined + if (shouldDrawMarker) { + // Shortcuts + var symbol = pick(pointMarkerOptions.symbol, series.symbol); + markerAttribs = series.markerAttribs(point, (point.selected && 'select')); + // Set starting position for point sliding animation. + if (series.enabledDataSorting) { + point.startXPos = xAxis.reversed ? + -markerAttribs.width : + xAxis.width; + } + var isInside = point.isInside !== false; + if (graphic) { // update + // Since the marker group isn't clipped, each + // individual marker must be toggled + graphic[isInside ? 'show' : 'hide'](isInside) + .animate(markerAttribs); + } + else if (isInside && + (markerAttribs.width > 0 || point.hasImage)) { + /** + * The graphic representation of the point. + * Typically this is a simple shape, like a `rect` + * for column charts or `path` for line markers, but + * for some complex series types like boxplot or 3D + * charts, the graphic may be a `g` element + * containing other shapes. The graphic is generated + * the first time {@link Series#drawPoints} runs, + * and updated and moved on subsequent runs. + * + * @name Point#graphic + * @type {SVGElement} + */ + point.graphic = graphic = chart.renderer + .symbol(symbol, markerAttribs.x, markerAttribs.y, markerAttribs.width, markerAttribs.height, hasPointMarker ? + pointMarkerOptions : + seriesMarkerOptions) + .add(markerGroup); + // Sliding animation for new points + if (series.enabledDataSorting && + chart.hasRendered) { + graphic.attr({ + x: point.startXPos + }); + verb = 'animate'; + } + } + if (graphic && verb === 'animate') { // update + // Since the marker group isn't clipped, each + // individual marker must be toggled + graphic[isInside ? 'show' : 'hide'](isInside) + .animate(markerAttribs); + } + // Presentational attributes + if (graphic && !chart.styledMode) { + graphic[verb](series.pointAttribs(point, (point.selected && 'select'))); + } + if (graphic) { + graphic.addClass(point.getClassName(), true); + } + } + else if (graphic) { + point.graphic = graphic.destroy(); // #1269 + } + } + } + }, + /** + * Get non-presentational attributes for a point. Used internally for + * both styled mode and classic. Can be overridden for different series + * types. + * + * @see Series#pointAttribs + * + * @function Highcharts.Series#markerAttribs + * + * @param {Highcharts.Point} point + * The Point to inspect. + * + * @param {string} [state] + * The state, can be either `hover`, `select` or undefined. + * + * @return {Highcharts.SVGAttributes} + * A hash containing those attributes that are not settable from + * CSS. + */ + markerAttribs: function (point, state) { + var seriesOptions = this.options, seriesMarkerOptions = seriesOptions.marker, seriesStateOptions, pointMarkerOptions = point.marker || {}, symbol = (pointMarkerOptions.symbol || + seriesMarkerOptions.symbol), pointStateOptions, radius = pick(pointMarkerOptions.radius, seriesMarkerOptions.radius), attribs; + // Handle hover and select states + if (state) { + seriesStateOptions = seriesMarkerOptions.states[state]; + pointStateOptions = pointMarkerOptions.states && + pointMarkerOptions.states[state]; + radius = pick(pointStateOptions && pointStateOptions.radius, seriesStateOptions && seriesStateOptions.radius, radius + (seriesStateOptions && seriesStateOptions.radiusPlus || + 0)); + } + point.hasImage = symbol && symbol.indexOf('url') === 0; + if (point.hasImage) { + radius = 0; // and subsequently width and height is not set + } + attribs = { + // Math.floor for #1843: + x: seriesOptions.crisp ? + Math.floor(point.plotX) - radius : + point.plotX - radius, + y: point.plotY - radius + }; + if (radius) { + attribs.width = attribs.height = 2 * radius; + } + return attribs; + }, + /** + * Internal function to get presentational attributes for each point. + * Unlike {@link Series#markerAttribs}, this function should return + * those attributes that can also be set in CSS. In styled mode, + * `pointAttribs` won't be called. + * + * @private + * @function Highcharts.Series#pointAttribs + * + * @param {Highcharts.Point} [point] + * The point instance to inspect. + * + * @param {string} [state] + * The point state, can be either `hover`, `select` or 'normal'. + * If undefined, normal state is assumed. + * + * @return {Highcharts.SVGAttributes} + * The presentational attributes to be set on the point. + */ + pointAttribs: function (point, state) { + var seriesMarkerOptions = this.options.marker, seriesStateOptions, pointOptions = point && point.options, pointMarkerOptions = ((pointOptions && pointOptions.marker) || {}), pointStateOptions, color = this.color, pointColorOption = pointOptions && pointOptions.color, pointColor = point && point.color, strokeWidth = pick(pointMarkerOptions.lineWidth, seriesMarkerOptions.lineWidth), zoneColor = point && point.zone && point.zone.color, fill, stroke, opacity = 1; + color = (pointColorOption || + zoneColor || + pointColor || + color); + fill = (pointMarkerOptions.fillColor || + seriesMarkerOptions.fillColor || + color); + stroke = (pointMarkerOptions.lineColor || + seriesMarkerOptions.lineColor || + color); + // Handle hover and select states + state = state || 'normal'; + if (state) { + seriesStateOptions = seriesMarkerOptions.states[state]; + pointStateOptions = (pointMarkerOptions.states && + pointMarkerOptions.states[state]) || {}; + strokeWidth = pick(pointStateOptions.lineWidth, seriesStateOptions.lineWidth, strokeWidth + pick(pointStateOptions.lineWidthPlus, seriesStateOptions.lineWidthPlus, 0)); + fill = (pointStateOptions.fillColor || + seriesStateOptions.fillColor || + fill); + stroke = (pointStateOptions.lineColor || + seriesStateOptions.lineColor || + stroke); + opacity = pick(pointStateOptions.opacity, seriesStateOptions.opacity, opacity); + } + return { + 'stroke': stroke, + 'stroke-width': strokeWidth, + 'fill': fill, + 'opacity': opacity + }; + }, + /** + * Clear DOM objects and free up memory. + * + * @private + * @function Highcharts.Series#destroy + * @param {boolean} [keepEventsForUpdate] + * @return {void} + * @fires Highcharts.Series#event:destroy + */ + destroy: function (keepEventsForUpdate) { + var series = this, chart = series.chart, issue134 = /AppleWebKit\/533/.test(win.navigator.userAgent), destroy, i, data = series.data || [], point, axis; + // add event hook + fireEvent(series, 'destroy'); + // remove events + this.removeEvents(keepEventsForUpdate); + // erase from axes + (series.axisTypes || []).forEach(function (AXIS) { + axis = series[AXIS]; + if (axis && axis.series) { + erase(axis.series, series); + axis.isDirty = axis.forceRedraw = true; + } + }); + // remove legend items + if (series.legendItem) { + series.chart.legend.destroyItem(series); + } + // destroy all points with their elements + i = data.length; + while (i--) { + point = data[i]; + if (point && point.destroy) { + point.destroy(); + } + } + series.points = null; + // Clear the animation timeout if we are destroying the series + // during initial animation + U.clearTimeout(series.animationTimeout); + // Destroy all SVGElements associated to the series + objectEach(series, function (val, prop) { + // Survive provides a hook for not destroying + if (val instanceof SVGElement && !val.survive) { + // issue 134 workaround + destroy = issue134 && prop === 'group' ? + 'hide' : + 'destroy'; + val[destroy](); + } + }); + // remove from hoverSeries + if (chart.hoverSeries === series) { + chart.hoverSeries = null; + } + erase(chart.series, series); + chart.orderSeries(); + // clear all members + objectEach(series, function (val, prop) { + if (!keepEventsForUpdate || prop !== 'hcEvents') { + delete series[prop]; + } + }); + }, + /** + * Get the graph path. + * + * @private + * @function Highcharts.Series#getGraphPath + * @param {Array} points + * @param {boolean} [nullsAsZeroes] + * @param {boolean} [connectCliffs] + * @return {Highcharts.SVGPathArray} + */ + getGraphPath: function (points, nullsAsZeroes, connectCliffs) { + var series = this, options = series.options, step = options.step, reversed, graphPath = [], xMap = [], gap; + points = points || series.points; + // Bottom of a stack is reversed + reversed = points.reversed; + if (reversed) { + points.reverse(); + } + // Reverse the steps (#5004) + step = { + right: 1, + center: 2 + }[step] || (step && 3); + if (step && reversed) { + step = 4 - step; + } + // Remove invalid points, especially in spline (#5015) + points = this.getValidPoints(points, false, !(options.connectNulls && !nullsAsZeroes && !connectCliffs)); + // Build the line + points.forEach(function (point, i) { + var plotX = point.plotX, plotY = point.plotY, lastPoint = points[i - 1], + // the path to this point from the previous + pathToPoint; + if ((point.leftCliff || (lastPoint && lastPoint.rightCliff)) && + !connectCliffs) { + gap = true; // ... and continue + } + // Line series, nullsAsZeroes is not handled + if (point.isNull && !defined(nullsAsZeroes) && i > 0) { + gap = !options.connectNulls; + // Area series, nullsAsZeroes is set + } + else if (point.isNull && !nullsAsZeroes) { + gap = true; + } + else { + if (i === 0 || gap) { + pathToPoint = [[ + 'M', + point.plotX, + point.plotY + ]]; + // Generate the spline as defined in the SplineSeries object + } + else if (series.getPointSpline) { + pathToPoint = [series.getPointSpline(points, point, i)]; + } + else if (step) { + if (step === 1) { // right + pathToPoint = [[ + 'L', + lastPoint.plotX, + plotY + ]]; + } + else if (step === 2) { // center + pathToPoint = [[ + 'L', + (lastPoint.plotX + plotX) / 2, + lastPoint.plotY + ], [ + 'L', + (lastPoint.plotX + plotX) / 2, + plotY + ]]; + } + else { + pathToPoint = [[ + 'L', + plotX, + lastPoint.plotY + ]]; + } + pathToPoint.push([ + 'L', + plotX, + plotY + ]); + } + else { + // normal line to next point + pathToPoint = [[ + 'L', + plotX, + plotY + ]]; + } + // Prepare for animation. When step is enabled, there are + // two path nodes for each x value. + xMap.push(point.x); + if (step) { + xMap.push(point.x); + if (step === 2) { // step = center (#8073) + xMap.push(point.x); + } + } + graphPath.push.apply(graphPath, pathToPoint); + gap = false; + } + }); + graphPath.xMap = xMap; + series.graphPath = graphPath; + return graphPath; + }, + /** + * Draw the graph. Called internally when rendering line-like series + * types. The first time it generates the `series.graph` item and + * optionally other series-wide items like `series.area` for area + * charts. On subsequent calls these items are updated with new + * positions and attributes. + * + * @function Highcharts.Series#drawGraph + * + * @return {void} + */ + drawGraph: function () { + var series = this, options = this.options, graphPath = (this.gappedPath || this.getGraphPath).call(this), styledMode = this.chart.styledMode, props = [[ + 'graph', + 'highcharts-graph' + ]]; + // Presentational properties + if (!styledMode) { + props[0].push((options.lineColor || + this.color || + '#cccccc' // when colorByPoint = true + ), options.dashStyle); + } + props = series.getZonesGraphs(props); + // Draw the graph + props.forEach(function (prop, i) { + var graphKey = prop[0], graph = series[graphKey], verb = graph ? 'animate' : 'attr', attribs; + if (graph) { + graph.endX = series.preventGraphAnimation ? + null : + graphPath.xMap; + graph.animate({ d: graphPath }); + } + else if (graphPath.length) { // #1487 + /** + * SVG element of area-based charts. Can be used for styling + * purposes. If zones are configured, this element will be + * hidden and replaced by multiple zone areas, accessible + * via `series['zone-area-x']` (where x is a number, + * starting with 0). + * + * @name Highcharts.Series#area + * @type {Highcharts.SVGElement|undefined} + */ + /** + * SVG element of line-based charts. Can be used for styling + * purposes. If zones are configured, this element will be + * hidden and replaced by multiple zone lines, accessible + * via `series['zone-graph-x']` (where x is a number, + * starting with 0). + * + * @name Highcharts.Series#graph + * @type {Highcharts.SVGElement|undefined} + */ + series[graphKey] = graph = series.chart.renderer + .path(graphPath) + .addClass(prop[1]) + .attr({ zIndex: 1 }) // #1069 + .add(series.group); + } + if (graph && !styledMode) { + attribs = { + 'stroke': prop[2], + 'stroke-width': options.lineWidth, + // Polygon series use filled graph + 'fill': (series.fillGraph && series.color) || 'none' + }; + if (prop[3]) { + attribs.dashstyle = prop[3]; + } + else if (options.linecap !== 'square') { + attribs['stroke-linecap'] = + attribs['stroke-linejoin'] = 'round'; + } + graph[verb](attribs) + // Add shadow to normal series (0) or to first + // zone (1) #3932 + .shadow((i < 2) && options.shadow); + } + // Helpers for animation + if (graph) { + graph.startX = graphPath.xMap; + graph.isArea = graphPath.isArea; // For arearange animation + } + }); + }, + /** + * Get zones properties for building graphs. Extendable by series with + * multiple lines within one series. + * + * @private + * @function Highcharts.Series#getZonesGraphs + * + * @param {Array>} props + * + * @return {Array>} + */ + getZonesGraphs: function (props) { + // Add the zone properties if any + this.zones.forEach(function (zone, i) { + var propset = [ + 'zone-graph-' + i, + 'highcharts-graph highcharts-zone-graph-' + i + ' ' + + (zone.className || '') + ]; + if (!this.chart.styledMode) { + propset.push((zone.color || this.color), (zone.dashStyle || this.options.dashStyle)); + } + props.push(propset); + }, this); + return props; + }, + /** + * Clip the graphs into zones for colors and styling. + * + * @private + * @function Highcharts.Series#applyZones + * @return {void} + */ + applyZones: function () { + var series = this, chart = this.chart, renderer = chart.renderer, zones = this.zones, translatedFrom, translatedTo, clips = (this.clips || []), clipAttr, graph = this.graph, area = this.area, chartSizeMax = Math.max(chart.chartWidth, chart.chartHeight), axis = this[(this.zoneAxis || 'y') + 'Axis'], extremes, reversed, inverted = chart.inverted, horiz, pxRange, pxPosMin, pxPosMax, ignoreZones = false, zoneArea, zoneGraph; + if (zones.length && + (graph || area) && + axis && + typeof axis.min !== 'undefined') { + reversed = axis.reversed; + horiz = axis.horiz; + // The use of the Color Threshold assumes there are no gaps + // so it is safe to hide the original graph and area + // unless it is not waterfall series, then use showLine property + // to set lines between columns to be visible (#7862) + if (graph && !this.showLine) { + graph.hide(); + } + if (area) { + area.hide(); + } + // Create the clips + extremes = axis.getExtremes(); + zones.forEach(function (threshold, i) { + translatedFrom = reversed ? + (horiz ? chart.plotWidth : 0) : + (horiz ? 0 : (axis.toPixels(extremes.min) || 0)); + translatedFrom = clamp(pick(translatedTo, translatedFrom), 0, chartSizeMax); + translatedTo = clamp(Math.round(axis.toPixels(pick(threshold.value, extremes.max), true) || 0), 0, chartSizeMax); + if (ignoreZones) { + translatedFrom = translatedTo = + axis.toPixels(extremes.max); + } + pxRange = Math.abs(translatedFrom - translatedTo); + pxPosMin = Math.min(translatedFrom, translatedTo); + pxPosMax = Math.max(translatedFrom, translatedTo); + if (axis.isXAxis) { + clipAttr = { + x: inverted ? pxPosMax : pxPosMin, + y: 0, + width: pxRange, + height: chartSizeMax + }; + if (!horiz) { + clipAttr.x = chart.plotHeight - clipAttr.x; + } + } + else { + clipAttr = { + x: 0, + y: inverted ? pxPosMax : pxPosMin, + width: chartSizeMax, + height: pxRange + }; + if (horiz) { + clipAttr.y = chart.plotWidth - clipAttr.y; + } + } + // VML SUPPPORT + if (inverted && renderer.isVML) { + if (axis.isXAxis) { + clipAttr = { + x: 0, + y: reversed ? pxPosMin : pxPosMax, + height: clipAttr.width, + width: chart.chartWidth + }; + } + else { + clipAttr = { + x: (clipAttr.y - + chart.plotLeft - + chart.spacingBox.x), + y: 0, + width: clipAttr.height, + height: chart.chartHeight + }; + } + } + // END OF VML SUPPORT + if (clips[i]) { + clips[i].animate(clipAttr); + } + else { + clips[i] = renderer.clipRect(clipAttr); + } + // when no data, graph zone is not applied and after setData + // clip was ignored. As a result, it should be applied each + // time. + zoneArea = series['zone-area-' + i]; + zoneGraph = series['zone-graph-' + i]; + if (graph && zoneGraph) { + zoneGraph.clip(clips[i]); + } + if (area && zoneArea) { + zoneArea.clip(clips[i]); + } + // if this zone extends out of the axis, ignore the others + ignoreZones = threshold.value > extremes.max; + // Clear translatedTo for indicators + if (series.resetZones && translatedTo === 0) { + translatedTo = void 0; + } + }); + this.clips = clips; + } + else if (series.visible) { + // If zones were removed, restore graph and area + if (graph) { + graph.show(true); + } + if (area) { + area.show(true); + } + } + }, + /** + * Initialize and perform group inversion on series.group and + * series.markerGroup. + * + * @private + * @function Highcharts.Series#invertGroups + * @param {boolean} [inverted] + * @return {void} + */ + invertGroups: function (inverted) { + var series = this, chart = series.chart; + /** + * @private + */ + function setInvert() { + ['group', 'markerGroup'].forEach(function (groupName) { + if (series[groupName]) { + // VML/HTML needs explicit attributes for flipping + if (chart.renderer.isVML) { + series[groupName].attr({ + width: series.yAxis.len, + height: series.xAxis.len + }); + } + series[groupName].width = series.yAxis.len; + series[groupName].height = series.xAxis.len; + // If inverted polar, don't invert series group + series[groupName].invert(series.isRadialSeries ? false : inverted); + } + }); + } + // Pie, go away (#1736) + if (!series.xAxis) { + return; + } + // A fixed size is needed for inversion to work + series.eventsToUnbind.push(addEvent(chart, 'resize', setInvert)); + // Do it now + setInvert(); + // On subsequent render and redraw, just do setInvert without + // setting up events again + series.invertGroups = setInvert; + }, + /** + * General abstraction for creating plot groups like series.group, + * series.dataLabelsGroup and series.markerGroup. On subsequent calls, + * the group will only be adjusted to the updated plot size. + * + * @private + * @function Highcharts.Series#plotGroup + * @param {string} prop + * @param {string} name + * @param {string} visibility + * @param {number} [zIndex] + * @param {Highcharts.SVGElement} [parent] + * @return {Highcharts.SVGElement} + */ + plotGroup: function (prop, name, visibility, zIndex, parent) { + var group = this[prop], isNew = !group; + // Generate it on first call + if (isNew) { + this[prop] = group = this.chart.renderer + .g() + .attr({ + zIndex: zIndex || 0.1 // IE8 and pointer logic use this + }) + .add(parent); + } + // Add the class names, and replace existing ones as response to + // Series.update (#6660) + group.addClass(('highcharts-' + name + + ' highcharts-series-' + this.index + + ' highcharts-' + this.type + '-series ' + + (defined(this.colorIndex) ? + 'highcharts-color-' + this.colorIndex + ' ' : + '') + + (this.options.className || '') + + (group.hasClass('highcharts-tracker') ? + ' highcharts-tracker' : + '')), true); + // Place it on first and subsequent (redraw) calls + group.attr({ visibility: visibility })[isNew ? 'attr' : 'animate'](this.getPlotBox()); + return group; + }, + /** + * Get the translation and scale for the plot area of this series. + * + * @function Highcharts.Series#getPlotBox + * + * @return {Highcharts.SeriesPlotBoxObject} + */ + getPlotBox: function () { + var chart = this.chart, xAxis = this.xAxis, yAxis = this.yAxis; + // Swap axes for inverted (#2339) + if (chart.inverted) { + xAxis = yAxis; + yAxis = this.xAxis; + } + return { + translateX: xAxis ? xAxis.left : chart.plotLeft, + translateY: yAxis ? yAxis.top : chart.plotTop, + scaleX: 1, + scaleY: 1 + }; + }, + /** + * Removes the event handlers attached previously with addEvents. + * + * @private + * @function Highcharts.Series#removeEvents + * @param {boolean} [keepEventsForUpdate] + * @return {void} + */ + removeEvents: function (keepEventsForUpdate) { + var series = this; + if (!keepEventsForUpdate) { + // remove all events + removeEvent(series); + } + else if (series.eventsToUnbind.length) { + // remove only internal events for proper update + // #12355 - solves problem with multiple destroy events + series.eventsToUnbind.forEach(function (unbind) { + unbind(); + }); + series.eventsToUnbind.length = 0; + } + }, + /** + * Render the graph and markers. Called internally when first rendering + * and later when redrawing the chart. This function can be extended in + * plugins, but normally shouldn't be called directly. + * + * @function Highcharts.Series#render + * + * @return {void} + * + * @fires Highcharts.Series#event:afterRender + */ + render: function () { + var series = this, chart = series.chart, group, options = series.options, + // Animation doesn't work in IE8 quirks when the group div is + // hidden, and looks bad in other oldIE + animDuration = (!series.finishedAnimating && + chart.renderer.isSVG && + animObject(options.animation).duration), visibility = series.visible ? 'inherit' : 'hidden', // #2597 + zIndex = options.zIndex, hasRendered = series.hasRendered, chartSeriesGroup = chart.seriesGroup, inverted = chart.inverted; + fireEvent(this, 'render'); + // the group + group = series.plotGroup('group', 'series', visibility, zIndex, chartSeriesGroup); + series.markerGroup = series.plotGroup('markerGroup', 'markers', visibility, zIndex, chartSeriesGroup); + // initiate the animation + if (animDuration && series.animate) { + series.animate(true); + } + // SVGRenderer needs to know this before drawing elements (#1089, + // #1795) + group.inverted = series.isCartesian || series.invertable ? + inverted : false; + // Draw the graph if any + if (series.drawGraph) { + series.drawGraph(); + series.applyZones(); + } + // Draw the points + if (series.visible) { + series.drawPoints(); + } + /* series.points.forEach(function (point) { + if (point.redraw) { + point.redraw(); + } + }); */ + // Draw the data labels + if (series.drawDataLabels) { + series.drawDataLabels(); + } + // In pie charts, slices are added to the DOM, but actual rendering + // is postponed until labels reserved their space + if (series.redrawPoints) { + series.redrawPoints(); + } + // draw the mouse tracking area + if (series.drawTracker && + series.options.enableMouseTracking !== false) { + series.drawTracker(); + } + // Handle inverted series and tracker groups + series.invertGroups(inverted); + // Initial clipping, must be defined after inverting groups for VML. + // Applies to columns etc. (#3839). + if (options.clip !== false && + !series.sharedClipKey && + !hasRendered) { + group.clip(chart.clipRect); + } + // Run the animation + if (animDuration && series.animate) { + series.animate(); + } + // Call the afterAnimate function on animation complete (but don't + // overwrite the animation.complete option which should be available + // to the user). + if (!hasRendered) { + series.animationTimeout = syncTimeout(function () { + series.afterAnimate(); + }, animDuration || 0); + } + // Means data is in accordance with what you see + series.isDirty = false; + // (See #322) series.isDirty = series.isDirtyData = false; // means + // data is in accordance with what you see + series.hasRendered = true; + fireEvent(series, 'afterRender'); + }, + /** + * Redraw the series. This function is called internally from + * `chart.redraw` and normally shouldn't be called directly. + * + * @private + * @function Highcharts.Series#redraw + * @return {void} + */ + redraw: function () { + var series = this, chart = series.chart, + // cache it here as it is set to false in render, but used after + wasDirty = series.isDirty || series.isDirtyData, group = series.group, xAxis = series.xAxis, yAxis = series.yAxis; + // reposition on resize + if (group) { + if (chart.inverted) { + group.attr({ + width: chart.plotWidth, + height: chart.plotHeight + }); + } + group.animate({ + translateX: pick(xAxis && xAxis.left, chart.plotLeft), + translateY: pick(yAxis && yAxis.top, chart.plotTop) + }); + } + series.translate(); + series.render(); + if (wasDirty) { // #3868, #3945 + delete this.kdTree; + } + }, + kdAxisArray: ['clientX', 'plotY'], + /** + * @private + * @function Highcharts.Series#searchPoint + * @param {Highcharts.PointerEventObject} e + * @param {boolean} [compareX] + * @return {Highcharts.Point} + */ + searchPoint: function (e, compareX) { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, inverted = series.chart.inverted; + return this.searchKDTree({ + clientX: inverted ? + xAxis.len - e.chartY + xAxis.pos : + e.chartX - xAxis.pos, + plotY: inverted ? + yAxis.len - e.chartX + yAxis.pos : + e.chartY - yAxis.pos + }, compareX, e); + }, + /** + * Build the k-d-tree that is used by mouse and touch interaction to get + * the closest point. Line-like series typically have a one-dimensional + * tree where points are searched along the X axis, while scatter-like + * series typically search in two dimensions, X and Y. + * + * @private + * @function Highcharts.Series#buildKDTree + * @param {Highcharts.PointerEventObject} [e] + * @return {void} + */ + buildKDTree: function (e) { + // Prevent multiple k-d-trees from being built simultaneously + // (#6235) + this.buildingKdTree = true; + var series = this, dimensions = series.options.findNearestPointBy + .indexOf('y') > -1 ? 2 : 1; + /** + * Internal function + * @private + */ + function _kdtree(points, depth, dimensions) { + var axis, median, length = points && points.length; + if (length) { + // alternate between the axis + axis = series.kdAxisArray[depth % dimensions]; + // sort point array + points.sort(function (a, b) { + return a[axis] - b[axis]; + }); + median = Math.floor(length / 2); + // build and return nod + return { + point: points[median], + left: _kdtree(points.slice(0, median), depth + 1, dimensions), + right: _kdtree(points.slice(median + 1), depth + 1, dimensions) + }; + } + } + /** + * Start the recursive build process with a clone of the points + * array and null points filtered out. (#3873) + * @private + */ + function startRecursive() { + series.kdTree = _kdtree(series.getValidPoints(null, + // For line-type series restrict to plot area, but + // column-type series not (#3916, #4511) + !series.directTouch), dimensions, dimensions); + series.buildingKdTree = false; + } + delete series.kdTree; + // For testing tooltips, don't build async. Also if touchstart, we + // may be dealing with click events on mobile, so don't delay + // (#6817). + syncTimeout(startRecursive, series.options.kdNow || (e && e.type === 'touchstart') ? 0 : 1); + }, + /** + * @private + * @function Highcharts.Series#searchKDTree + * @param {Highcharts.KDPointSearchObject} point + * @param {boolean} [compareX] + * @param {Highcharts.PointerEventObject} [e] + * @return {Highcharts.Point|undefined} + */ + searchKDTree: function (point, compareX, e) { + var series = this, kdX = this.kdAxisArray[0], kdY = this.kdAxisArray[1], kdComparer = compareX ? 'distX' : 'dist', kdDimensions = series.options.findNearestPointBy + .indexOf('y') > -1 ? 2 : 1; + /** + * Set the one and two dimensional distance on the point object. + * @private + */ + function setDistance(p1, p2) { + var x = (defined(p1[kdX]) && + defined(p2[kdX])) ? + Math.pow(p1[kdX] - p2[kdX], 2) : + null, y = (defined(p1[kdY]) && + defined(p2[kdY])) ? + Math.pow(p1[kdY] - p2[kdY], 2) : + null, r = (x || 0) + (y || 0); + p2.dist = defined(r) ? Math.sqrt(r) : Number.MAX_VALUE; + p2.distX = defined(x) ? Math.sqrt(x) : Number.MAX_VALUE; + } + /** + * @private + */ + function _search(search, tree, depth, dimensions) { + var point = tree.point, axis = series.kdAxisArray[depth % dimensions], tdist, sideA, sideB, ret = point, nPoint1, nPoint2; + setDistance(search, point); + // Pick side based on distance to splitting point + tdist = search[axis] - point[axis]; + sideA = tdist < 0 ? 'left' : 'right'; + sideB = tdist < 0 ? 'right' : 'left'; + // End of tree + if (tree[sideA]) { + nPoint1 = _search(search, tree[sideA], depth + 1, dimensions); + ret = (nPoint1[kdComparer] < + ret[kdComparer] ? + nPoint1 : + point); + } + if (tree[sideB]) { + // compare distance to current best to splitting point to + // decide wether to check side B or not + if (Math.sqrt(tdist * tdist) < ret[kdComparer]) { + nPoint2 = _search(search, tree[sideB], depth + 1, dimensions); + ret = (nPoint2[kdComparer] < + ret[kdComparer] ? + nPoint2 : + ret); + } + } + return ret; + } + if (!this.kdTree && !this.buildingKdTree) { + this.buildKDTree(e); + } + if (this.kdTree) { + return _search(point, this.kdTree, kdDimensions, kdDimensions); + } + }, + /** + * @private + * @function Highcharts.Series#pointPlacementToXValue + * @return {number} + */ + pointPlacementToXValue: function () { + var _a = this, _b = _a.options, pointPlacement = _b.pointPlacement, pointRange = _b.pointRange, axis = _a.xAxis; + var factor = pointPlacement; + // Point placement is relative to each series pointRange (#5889) + if (factor === 'between') { + factor = axis.reversed ? -0.5 : 0.5; // #11955 + } + return isNumber(factor) ? + factor * pick(pointRange, axis.pointRange) : + 0; + }, + /** + * @private + * @function Highcharts.Series#isPointInside + * @param {Highcharts.Point} point + * @return {boolean} + */ + isPointInside: function (point) { + var isInside = typeof point.plotY !== 'undefined' && + typeof point.plotX !== 'undefined' && + point.plotY >= 0 && + point.plotY <= this.yAxis.len && // #3519 + point.plotX >= 0 && + point.plotX <= this.xAxis.len; + return isInside; + } + }); // end Series prototype + /** + * A line series displays information as a series of data points connected by + * straight line segments. + * + * @sample {highcharts} highcharts/demo/line-basic/ + * Line chart + * @sample {highstock} stock/demo/basic-line/ + * Line chart + * + * @extends plotOptions.series + * @product highcharts highstock + * @apioption plotOptions.line + */ + /** + * The SVG value used for the `stroke-linecap` and `stroke-linejoin` + * of a line graph. Round means that lines are rounded in the ends and + * bends. + * + * @type {Highcharts.SeriesLinecapValue} + * @default round + * @since 3.0.7 + * @apioption plotOptions.line.linecap + */ + /** + * A `line` series. If the [type](#series.line.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.line + * @excluding dataParser,dataURL + * @product highcharts highstock + * @apioption series.line + */ + /** + * An array of data points for the series. For the `line` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 1], + * [1, 2], + * [2, 8] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.line.turboThreshold), + * this option is not available. + * ```js + * data: [{ + * x: 1, + * y: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * **Note:** In TypeScript you have to extend `PointOptionsObject` with an + * additional declaration to allow custom data types: + * ```ts + * declare module `highcharts` { + * interface PointOptionsObject { + * custom: Record; + * } + * } + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @declare Highcharts.PointOptionsObject + * @type {Array|null|*>} + * @apioption series.line.data + */ + /** + * An additional, individual class name for the data point's graphic + * representation. + * + * @type {string} + * @since 5.0.0 + * @product highcharts gantt + * @apioption series.line.data.className + */ + /** + * Individual color for the point. By default the color is pulled from + * the global `colors` array. + * + * In styled mode, the `color` option doesn't take effect. Instead, use + * `colorIndex`. + * + * @sample {highcharts} highcharts/point/color/ + * Mark the highest point + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock gantt + * @apioption series.line.data.color + */ + /** + * A specific color index to use for the point, so its graphic representations + * are given the class name `highcharts-color-{n}`. In styled mode this will + * change the color of the graphic. In non-styled mode, the color by is set by + * the `fill` attribute, so the change in class name won't have a visual effect + * by default. + * + * @type {number} + * @since 5.0.0 + * @product highcharts gantt + * @apioption series.line.data.colorIndex + */ + /** + * A reserved subspace to store options and values for customized functionality. + * Here you can add additional data for your own event callbacks and formatter + * callbacks. + * + * @sample {highcharts} highcharts/point/custom/ + * Point and series with custom data + * + * @type {Highcharts.Dictionary<*>} + * @apioption series.line.data.custom + */ + /** + * Individual data label for each point. The options are the same as + * the ones for [plotOptions.series.dataLabels]( + * #plotOptions.series.dataLabels). + * + * @sample highcharts/point/datalabels/ + * Show a label for the last value + * + * @declare Highcharts.DataLabelsOptions + * @extends plotOptions.line.dataLabels + * @product highcharts highstock gantt + * @apioption series.line.data.dataLabels + */ + /** + * A description of the point to add to the screen reader information + * about the point. + * + * @type {string} + * @since 5.0.0 + * @requires modules/accessibility + * @apioption series.line.data.description + */ + /** + * An id for the point. This can be used after render time to get a + * pointer to the point object through `chart.get()`. + * + * @sample {highcharts} highcharts/point/id/ + * Remove an id'd point + * + * @type {string} + * @since 1.2.0 + * @product highcharts highstock gantt + * @apioption series.line.data.id + */ + /** + * The rank for this point's data label in case of collision. If two + * data labels are about to overlap, only the one with the highest `labelrank` + * will be drawn. + * + * @type {number} + * @apioption series.line.data.labelrank + */ + /** + * The name of the point as shown in the legend, tooltip, dataLabels, etc. + * + * @see [xAxis.uniqueNames](#xAxis.uniqueNames) + * + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Point names + * + * @type {string} + * @apioption series.line.data.name + */ + /** + * Whether the data point is selected initially. + * + * @type {boolean} + * @default false + * @product highcharts highstock gantt + * @apioption series.line.data.selected + */ + /** + * The x value of the point. For datetime axes, the X value is the timestamp + * in milliseconds since 1970. + * + * @type {number} + * @product highcharts highstock + * @apioption series.line.data.x + */ + /** + * The y value of the point. + * + * @type {number|null} + * @product highcharts highstock + * @apioption series.line.data.y + */ + /** + * The individual point events. + * + * @extends plotOptions.series.point.events + * @product highcharts highstock gantt + * @apioption series.line.data.events + */ + /** + * Options for the point markers of line-like series. + * + * @declare Highcharts.PointMarkerOptionsObject + * @extends plotOptions.series.marker + * @product highcharts highstock + * @apioption series.line.data.marker + */ + ''; // include precedent doclets in transpilat + + }); + _registerModule(_modules, 'parts/Stacking.js', [_modules['parts/Axis.js'], _modules['parts/Globals.js'], _modules['parts/StackingAxis.js'], _modules['parts/Utilities.js']], function (Axis, H, StackingAxis, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var correctFloat = U.correctFloat, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, format = U.format, pick = U.pick; + /** + * Stack of data points + * + * @product highcharts + * + * @interface Highcharts.StackItemObject + */ /** + * Alignment settings + * @name Highcharts.StackItemObject#alignOptions + * @type {Highcharts.AlignObject} + */ /** + * Related axis + * @name Highcharts.StackItemObject#axis + * @type {Highcharts.Axis} + */ /** + * Cumulative value of the stacked data points + * @name Highcharts.StackItemObject#cumulative + * @type {number} + */ /** + * True if on the negative side + * @name Highcharts.StackItemObject#isNegative + * @type {boolean} + */ /** + * Related SVG element + * @name Highcharts.StackItemObject#label + * @type {Highcharts.SVGElement} + */ /** + * Related stack options + * @name Highcharts.StackItemObject#options + * @type {Highcharts.YAxisStackLabelsOptions} + */ /** + * Total value of the stacked data points + * @name Highcharts.StackItemObject#total + * @type {number} + */ /** + * Shared x value of the stack + * @name Highcharts.StackItemObject#x + * @type {number} + */ + ''; // detached doclets above + var Chart = H.Chart, Series = H.Series; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The class for stacks. Each stack, on a specific X value and either negative + * or positive, has its own stack item. + * + * @private + * @class + * @name Highcharts.StackItem + * @param {Highcharts.Axis} axis + * @param {Highcharts.YAxisStackLabelsOptions} options + * @param {boolean} isNegative + * @param {number} x + * @param {Highcharts.OptionsStackingValue} [stackOption] + */ + var StackItem = /** @class */ (function () { + function StackItem(axis, options, isNegative, x, stackOption) { + var inverted = axis.chart.inverted; + this.axis = axis; + // Tells if the stack is negative + this.isNegative = isNegative; + // Save the options to be able to style the label + this.options = options = options || {}; + // Save the x value to be able to position the label later + this.x = x; + // Initialize total value + this.total = null; + // This will keep each points' extremes stored by series.index and point + // index + this.points = {}; + // Save the stack option on the series configuration object, + // and whether to treat it as percent + this.stack = stackOption; + this.leftCliff = 0; + this.rightCliff = 0; + // The align options and text align varies on whether the stack is + // negative and if the chart is inverted or not. + // First test the user supplied value, then use the dynamic. + this.alignOptions = { + align: options.align || + (inverted ? (isNegative ? 'left' : 'right') : 'center'), + verticalAlign: options.verticalAlign || + (inverted ? 'middle' : (isNegative ? 'bottom' : 'top')), + y: options.y, + x: options.x + }; + this.textAlign = options.textAlign || + (inverted ? (isNegative ? 'right' : 'left') : 'center'); + } + /** + * @private + * @function Highcharts.StackItem#destroy + */ + StackItem.prototype.destroy = function () { + destroyObjectProperties(this, this.axis); + }; + /** + * Renders the stack total label and adds it to the stack label group. + * + * @private + * @function Highcharts.StackItem#render + * @param {Highcharts.SVGElement} group + */ + StackItem.prototype.render = function (group) { + var chart = this.axis.chart, options = this.options, formatOption = options.format, attr = {}, str = formatOption ? // format the text in the label + format(formatOption, this, chart) : + options.formatter.call(this); + // Change the text to reflect the new total and set visibility to hidden + // in case the serie is hidden + if (this.label) { + this.label.attr({ text: str, visibility: 'hidden' }); + } + else { + // Create new label + this.label = chart.renderer + .label(str, null, null, options.shape, null, null, options.useHTML, false, 'stack-labels'); + attr = { + r: options.borderRadius || 0, + text: str, + rotation: options.rotation, + padding: pick(options.padding, 5), + visibility: 'hidden' // hidden until setOffset is called + }; + if (!chart.styledMode) { + attr.fill = options.backgroundColor; + attr.stroke = options.borderColor; + attr['stroke-width'] = options.borderWidth; + this.label.css(options.style); + } + this.label.attr(attr); + if (!this.label.added) { + this.label.add(group); // add to the labels-group + } + } + // Rank it higher than data labels (#8742) + this.label.labelrank = chart.plotHeight; + }; + /** + * Sets the offset that the stack has from the x value and repositions the + * label. + * + * @private + * @function Highcarts.StackItem#setOffset + * @param {number} xOffset + * @param {number} xWidth + * @param {number} [boxBottom] + * @param {number} [boxTop] + * @param {number} [defaultX] + */ + StackItem.prototype.setOffset = function (xOffset, xWidth, boxBottom, boxTop, defaultX) { + var stackItem = this, axis = stackItem.axis, chart = axis.chart, + // stack value translated mapped to chart coordinates + y = axis.translate(axis.stacking.usePercentage ? + 100 : + (boxTop ? + boxTop : + stackItem.total), 0, 0, 0, 1), yZero = axis.translate(boxBottom ? boxBottom : 0), // stack origin + // stack height: + h = defined(y) && Math.abs(y - yZero), + // x position: + x = pick(defaultX, chart.xAxis[0].translate(stackItem.x)) + + xOffset, stackBox = defined(y) && stackItem.getStackBox(chart, stackItem, x, y, xWidth, h, axis), label = stackItem.label, isNegative = stackItem.isNegative, isJustify = pick(stackItem.options.overflow, 'justify') === 'justify', textAlign = stackItem.textAlign, visible; + if (label && stackBox) { + var bBox = label.getBBox(), padding = label.padding, boxOffsetX, boxOffsetY; + if (textAlign === 'left') { + boxOffsetX = chart.inverted ? -padding : padding; + } + else if (textAlign === 'right') { + boxOffsetX = bBox.width; + } + else { + if (chart.inverted && textAlign === 'center') { + boxOffsetX = bBox.width / 2; + } + else { + boxOffsetX = chart.inverted ? + (isNegative ? bBox.width + padding : -padding) : bBox.width / 2; + } + } + boxOffsetY = chart.inverted ? + bBox.height / 2 : (isNegative ? -padding : bBox.height); + // Reset alignOptions property after justify #12337 + stackItem.alignOptions.x = pick(stackItem.options.x, 0); + stackItem.alignOptions.y = pick(stackItem.options.y, 0); + // Set the stackBox position + stackBox.x -= boxOffsetX; + stackBox.y -= boxOffsetY; + // Align the label to the box + label.align(stackItem.alignOptions, null, stackBox); + // Check if label is inside the plotArea #12294 + if (chart.isInsidePlot(label.alignAttr.x + boxOffsetX - stackItem.alignOptions.x, label.alignAttr.y + boxOffsetY - stackItem.alignOptions.y)) { + label.show(); + } + else { + // Move label away to avoid the overlapping issues + label.alignAttr.y = -9999; + isJustify = false; + } + if (isJustify) { + // Justify stackLabel into the stackBox + Series.prototype.justifyDataLabel.call(this.axis, label, stackItem.alignOptions, label.alignAttr, bBox, stackBox); + } + label.attr({ + x: label.alignAttr.x, + y: label.alignAttr.y + }); + if (pick(!isJustify && stackItem.options.crop, true)) { + visible = chart.isInsidePlot(label.x - padding + label.width, label.y) && + chart.isInsidePlot(label.x + padding, label.y); + if (!visible) { + label.hide(); + } + } + } + }; + /** + * @private + * @function Highcharts.StackItem#getStackBox + * + * @param {Highcharts.Chart} chart + * + * @param {Highcharts.StackItem} stackItem + * + * @param {number} x + * + * @param {number} y + * + * @param {number} xWidth + * + * @param {number} h + * + * @param {Highcharts.Axis} axis + * + * @return {Highcharts.BBoxObject} + */ + StackItem.prototype.getStackBox = function (chart, stackItem, x, y, xWidth, h, axis) { + var reversed = stackItem.axis.reversed, inverted = chart.inverted, axisPos = axis.height + axis.pos - + (inverted ? chart.plotLeft : chart.plotTop), neg = (stackItem.isNegative && !reversed) || + (!stackItem.isNegative && reversed); // #4056 + return { + x: inverted ? (neg ? y - axis.right : y - h + axis.pos - chart.plotLeft) : + x + chart.xAxis[0].transB - chart.plotLeft, + y: inverted ? + axis.height - x - xWidth : + (neg ? + (axisPos - y - h) : + axisPos - y), + width: inverted ? h : xWidth, + height: inverted ? xWidth : h + }; + }; + return StackItem; + }()); + /** + * Generate stacks for each series and calculate stacks total values + * + * @private + * @function Highcharts.Chart#getStacks + * @return {void} + */ + Chart.prototype.getStacks = function () { + var chart = this, inverted = chart.inverted; + // reset stacks for each yAxis + chart.yAxis.forEach(function (axis) { + if (axis.stacking && axis.stacking.stacks && axis.hasVisibleSeries) { + axis.stacking.oldStacks = axis.stacking.stacks; + } + }); + chart.series.forEach(function (series) { + var xAxisOptions = series.xAxis && series.xAxis.options || {}; + if (series.options.stacking && + (series.visible === true || + chart.options.chart.ignoreHiddenSeries === false)) { + series.stackKey = [ + series.type, + pick(series.options.stack, ''), + inverted ? xAxisOptions.top : xAxisOptions.left, + inverted ? xAxisOptions.height : xAxisOptions.width + ].join(','); + } + }); + }; + // Stacking methods defined on the Axis prototype + StackingAxis.compose(Axis); + // Stacking methods defnied for Series prototype + /** + * Adds series' points value to corresponding stack + * + * @private + * @function Highcharts.Series#setStackedPoints + */ + Series.prototype.setStackedPoints = function () { + if (!this.options.stacking || + (this.visible !== true && + this.chart.options.chart.ignoreHiddenSeries !== false)) { + return; + } + var series = this, xData = series.processedXData, yData = series.processedYData, stackedYData = [], yDataLength = yData.length, seriesOptions = series.options, threshold = seriesOptions.threshold, stackThreshold = pick(seriesOptions.startFromThreshold && threshold, 0), stackOption = seriesOptions.stack, stacking = seriesOptions.stacking, stackKey = series.stackKey, negKey = '-' + stackKey, negStacks = series.negStacks, yAxis = series.yAxis, stacks = yAxis.stacking.stacks, oldStacks = yAxis.stacking.oldStacks, stackIndicator, isNegative, stack, other, key, pointKey, i, x, y; + yAxis.stacking.stacksTouched += 1; + // loop over the non-null y values and read them into a local array + for (i = 0; i < yDataLength; i++) { + x = xData[i]; + y = yData[i]; + stackIndicator = series.getStackIndicator(stackIndicator, x, series.index); + pointKey = stackIndicator.key; + // Read stacked values into a stack based on the x value, + // the sign of y and the stack key. Stacking is also handled for null + // values (#739) + isNegative = negStacks && y < (stackThreshold ? 0 : threshold); + key = isNegative ? negKey : stackKey; + // Create empty object for this stack if it doesn't exist yet + if (!stacks[key]) { + stacks[key] = + {}; + } + // Initialize StackItem for this x + if (!stacks[key][x]) { + if (oldStacks[key] && + oldStacks[key][x]) { + stacks[key][x] = oldStacks[key][x]; + stacks[key][x].total = null; + } + else { + stacks[key][x] = new StackItem(yAxis, yAxis.options.stackLabels, isNegative, x, stackOption); + } + } + // If the StackItem doesn't exist, create it first + stack = stacks[key][x]; + if (y !== null) { + stack.points[pointKey] = stack.points[series.index] = + [pick(stack.cumulative, stackThreshold)]; + // Record the base of the stack + if (!defined(stack.cumulative)) { + stack.base = pointKey; + } + stack.touched = yAxis.stacking.stacksTouched; + // In area charts, if there are multiple points on the same X value, + // let the area fill the full span of those points + if (stackIndicator.index > 0 && series.singleStacks === false) { + stack.points[pointKey][0] = + stack.points[series.index + ',' + x + ',0'][0]; + } + // When updating to null, reset the point stack (#7493) + } + else { + stack.points[pointKey] = stack.points[series.index] = + null; + } + // Add value to the stack total + if (stacking === 'percent') { + // Percent stacked column, totals are the same for the positive and + // negative stacks + other = isNegative ? stackKey : negKey; + if (negStacks && stacks[other] && stacks[other][x]) { + other = stacks[other][x]; + stack.total = other.total = + Math.max(other.total, stack.total) + + Math.abs(y) || + 0; + // Percent stacked areas + } + else { + stack.total = + correctFloat(stack.total + (Math.abs(y) || 0)); + } + } + else { + stack.total = correctFloat(stack.total + (y || 0)); + } + stack.cumulative = + pick(stack.cumulative, stackThreshold) + (y || 0); + if (y !== null) { + stack.points[pointKey].push(stack.cumulative); + stackedYData[i] = stack.cumulative; + } + } + if (stacking === 'percent') { + yAxis.stacking.usePercentage = true; + } + this.stackedYData = stackedYData; // To be used in getExtremes + // Reset old stacks + yAxis.stacking.oldStacks = {}; + }; + /** + * Iterate over all stacks and compute the absolute values to percent + * + * @private + * @function Highcharts.Series#modifyStacks + */ + Series.prototype.modifyStacks = function () { + var series = this, yAxis = series.yAxis, stackKey = series.stackKey, stacks = yAxis.stacking.stacks, processedXData = series.processedXData, stackIndicator, stacking = series.options.stacking; + if (series[stacking + 'Stacker']) { // Modifier function exists + [stackKey, '-' + stackKey].forEach(function (key) { + var i = processedXData.length, x, stack, pointExtremes; + while (i--) { + x = processedXData[i]; + stackIndicator = series.getStackIndicator(stackIndicator, x, series.index, key); + stack = stacks[key] && stacks[key][x]; + pointExtremes = + stack && stack.points[stackIndicator.key]; + if (pointExtremes) { + series[stacking + 'Stacker'](pointExtremes, stack, i); + } + } + }); + } + }; + /** + * Modifier function for percent stacks. Blows up the stack to 100%. + * + * @private + * @function Highcharts.Series#percentStacker + * @param {Array} pointExtremes + * @param {Highcharts.StackItem} stack + * @param {number} i + */ + Series.prototype.percentStacker = function (pointExtremes, stack, i) { + var totalFactor = stack.total ? 100 / stack.total : 0; + // Y bottom value + pointExtremes[0] = correctFloat(pointExtremes[0] * totalFactor); + // Y value + pointExtremes[1] = correctFloat(pointExtremes[1] * totalFactor); + this.stackedYData[i] = pointExtremes[1]; + }; + /** + * Get stack indicator, according to it's x-value, to determine points with the + * same x-value + * + * @private + * @function Highcharts.Series#getStackIndicator + * @param {Highcharts.StackItemIndicatorObject|undefined} stackIndicator + * @param {number} x + * @param {number} index + * @param {string} [key] + * @return {Highcharts.StackItemIndicatorObject} + */ + Series.prototype.getStackIndicator = function (stackIndicator, x, index, key) { + // Update stack indicator, when: + // first point in a stack || x changed || stack type (negative vs positive) + // changed: + if (!defined(stackIndicator) || + stackIndicator.x !== x || + (key && stackIndicator.key !== key)) { + stackIndicator = { + x: x, + index: 0, + key: key + }; + } + else { + (stackIndicator).index++; + } + stackIndicator.key = + [index, x, stackIndicator.index].join(','); + return stackIndicator; + }; + H.StackItem = StackItem; + + return H.StackItem; + }); + _registerModule(_modules, 'parts/Dynamics.js', [_modules['parts/Globals.js'], _modules['parts/Point.js'], _modules['parts/Time.js'], _modules['parts/Utilities.js']], function (H, Point, Time, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, animate = U.animate, createElement = U.createElement, css = U.css, defined = U.defined, erase = U.erase, error = U.error, extend = U.extend, fireEvent = U.fireEvent, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, isString = U.isString, merge = U.merge, objectEach = U.objectEach, pick = U.pick, relativeLength = U.relativeLength, setAnimation = U.setAnimation, splat = U.splat; + var Axis = H.Axis, Chart = H.Chart, Series = H.Series, seriesTypes = H.seriesTypes; + /* eslint-disable valid-jsdoc */ + /** + * Remove settings that have not changed, to avoid unnecessary rendering or + * computing (#9197). + * @private + */ + H.cleanRecursively = function (newer, older) { + var result = {}; + objectEach(newer, function (val, key) { + var ob; + // Dive into objects (except DOM nodes) + if (isObject(newer[key], true) && + !newer.nodeType && // #10044 + older[key]) { + ob = H.cleanRecursively(newer[key], older[key]); + if (Object.keys(ob).length) { + result[key] = ob; + } + // Arrays, primitives and DOM nodes are copied directly + } + else if (isObject(newer[key]) || + newer[key] !== older[key]) { + result[key] = newer[key]; + } + }); + return result; + }; + // Extend the Chart prototype for dynamic methods + extend(Chart.prototype, /** @lends Highcharts.Chart.prototype */ { + /** + * Add a series to the chart after render time. Note that this method should + * never be used when adding data synchronously at chart render time, as it + * adds expense to the calculations and rendering. When adding data at the + * same time as the chart is initialized, add the series as a configuration + * option instead. With multiple axes, the `offset` is dynamically adjusted. + * + * @sample highcharts/members/chart-addseries/ + * Add a series from a button + * @sample stock/members/chart-addseries/ + * Add a series in Highstock + * + * @function Highcharts.Chart#addSeries + * + * @param {Highcharts.SeriesOptionsType} options + * The config options for the series. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after adding. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * Whether to apply animation, and optionally animation + * configuration. + * + * @return {Highcharts.Series} + * The newly created series object. + * + * @fires Highcharts.Chart#event:addSeries + * @fires Highcharts.Chart#event:afterAddSeries + */ + addSeries: function (options, redraw, animation) { + var series, chart = this; + if (options) { // <- not necessary + redraw = pick(redraw, true); // defaults to true + fireEvent(chart, 'addSeries', { options: options }, function () { + series = chart.initSeries(options); + chart.isDirtyLegend = true; + chart.linkSeries(); + if (series.enabledDataSorting) { + // We need to call `setData` after `linkSeries` + series.setData(options.data, false); + } + fireEvent(chart, 'afterAddSeries', { series: series }); + if (redraw) { + chart.redraw(animation); + } + }); + } + return series; + }, + /** + * Add an axis to the chart after render time. Note that this method should + * never be used when adding data synchronously at chart render time, as it + * adds expense to the calculations and rendering. When adding data at the + * same time as the chart is initialized, add the axis as a configuration + * option instead. + * + * @sample highcharts/members/chart-addaxis/ + * Add and remove axes + * + * @function Highcharts.Chart#addAxis + * + * @param {Highcharts.AxisOptions} options + * The axis options. + * + * @param {boolean} [isX=false] + * Whether it is an X axis or a value axis. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after adding. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=true] + * Whether and how to apply animation in the redraw. + * + * @return {Highcharts.Axis} + * The newly generated Axis object. + */ + addAxis: function (options, isX, redraw, animation) { + return this.createAxis(isX ? 'xAxis' : 'yAxis', { axis: options, redraw: redraw, animation: animation }); + }, + /** + * Add a color axis to the chart after render time. Note that this method + * should never be used when adding data synchronously at chart render time, + * as it adds expense to the calculations and rendering. When adding data at + * the same time as the chart is initialized, add the axis as a + * configuration option instead. + * + * @sample highcharts/members/chart-addaxis/ + * Add and remove axes + * + * @function Highcharts.Chart#addColorAxis + * + * @param {Highcharts.ColorAxisOptions} options + * The axis options. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after adding. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=true] + * Whether and how to apply animation in the redraw. + * + * @return {Highcharts.ColorAxis} + * The newly generated Axis object. + */ + addColorAxis: function (options, redraw, animation) { + return this.createAxis('colorAxis', { axis: options, redraw: redraw, animation: animation }); + }, + /** + * Factory for creating different axis types. + * + * @private + * @function Highcharts.Chart#createAxis + * + * @param {string} type + * An axis type. + * + * @param {...Array<*>} arguments + * All arguments for the constructor. + * + * @return {Highcharts.Axis | Highcharts.ColorAxis} + * The newly generated Axis object. + */ + createAxis: function (type, options) { + var chartOptions = this.options, isColorAxis = type === 'colorAxis', axisOptions = options.axis, redraw = options.redraw, animation = options.animation, userOptions = merge(axisOptions, { + index: this[type].length, + isX: type === 'xAxis' + }), axis; + if (isColorAxis) { + axis = new H.ColorAxis(this, userOptions); + } + else { + axis = new Axis(this, userOptions); + } + // Push the new axis options to the chart options + chartOptions[type] = splat(chartOptions[type] || {}); + chartOptions[type].push(userOptions); + if (isColorAxis) { + this.isDirtyLegend = true; + // Clear before 'bindAxes' (#11924) + this.axes.forEach(function (axis) { + axis.series = []; + }); + this.series.forEach(function (series) { + series.bindAxes(); + series.isDirtyData = true; + }); + } + if (pick(redraw, true)) { + this.redraw(animation); + } + return axis; + }, + /** + * Dim the chart and show a loading text or symbol. Options for the loading + * screen are defined in {@link + * https://api.highcharts.com/highcharts/loading|the loading options}. + * + * @sample highcharts/members/chart-hideloading/ + * Show and hide loading from a button + * @sample highcharts/members/chart-showloading/ + * Apply different text labels + * @sample stock/members/chart-show-hide-loading/ + * Toggle loading in Highstock + * + * @function Highcharts.Chart#showLoading + * + * @param {string} [str] + * An optional text to show in the loading label instead of the + * default one. The default text is set in + * [lang.loading](https://api.highcharts.com/highcharts/lang.loading). + * + * @return {void} + */ + showLoading: function (str) { + var chart = this, options = chart.options, loadingDiv = chart.loadingDiv, loadingOptions = options.loading, setLoadingSize = function () { + if (loadingDiv) { + css(loadingDiv, { + left: chart.plotLeft + 'px', + top: chart.plotTop + 'px', + width: chart.plotWidth + 'px', + height: chart.plotHeight + 'px' + }); + } + }; + // create the layer at the first call + if (!loadingDiv) { + chart.loadingDiv = loadingDiv = createElement('div', { + className: 'highcharts-loading highcharts-loading-hidden' + }, null, chart.container); + chart.loadingSpan = createElement('span', { className: 'highcharts-loading-inner' }, null, loadingDiv); + addEvent(chart, 'redraw', setLoadingSize); // #1080 + } + loadingDiv.className = 'highcharts-loading'; + // Update text + chart.loadingSpan.innerHTML = + pick(str, options.lang.loading, ''); + if (!chart.styledMode) { + // Update visuals + css(loadingDiv, extend(loadingOptions.style, { + zIndex: 10 + })); + css(chart.loadingSpan, loadingOptions.labelStyle); + // Show it + if (!chart.loadingShown) { + css(loadingDiv, { + opacity: 0, + display: '' + }); + animate(loadingDiv, { + opacity: loadingOptions.style.opacity || 0.5 + }, { + duration: loadingOptions.showDuration || 0 + }); + } + } + chart.loadingShown = true; + setLoadingSize(); + }, + /** + * Hide the loading layer. + * + * @see Highcharts.Chart#showLoading + * + * @sample highcharts/members/chart-hideloading/ + * Show and hide loading from a button + * @sample stock/members/chart-show-hide-loading/ + * Toggle loading in Highstock + * + * @function Highcharts.Chart#hideLoading + * + * @return {void} + */ + hideLoading: function () { + var options = this.options, loadingDiv = this.loadingDiv; + if (loadingDiv) { + loadingDiv.className = + 'highcharts-loading highcharts-loading-hidden'; + if (!this.styledMode) { + animate(loadingDiv, { + opacity: 0 + }, { + duration: options.loading.hideDuration || 100, + complete: function () { + css(loadingDiv, { display: 'none' }); + } + }); + } + } + this.loadingShown = false; + }, + /** + * These properties cause isDirtyBox to be set to true when updating. Can be + * extended from plugins. + */ + propsRequireDirtyBox: [ + 'backgroundColor', + 'borderColor', + 'borderWidth', + 'borderRadius', + 'plotBackgroundColor', + 'plotBackgroundImage', + 'plotBorderColor', + 'plotBorderWidth', + 'plotShadow', + 'shadow' + ], + /** + * These properties require a full reflow of chart elements, best + * implemented through running `Chart.setSize` internally (#8190). + * @type {Array} + */ + propsRequireReflow: [ + 'margin', + 'marginTop', + 'marginRight', + 'marginBottom', + 'marginLeft', + 'spacing', + 'spacingTop', + 'spacingRight', + 'spacingBottom', + 'spacingLeft' + ], + /** + * These properties cause all series to be updated when updating. Can be + * extended from plugins. + */ + propsRequireUpdateSeries: [ + 'chart.inverted', + 'chart.polar', + 'chart.ignoreHiddenSeries', + 'chart.type', + 'colors', + 'plotOptions', + 'time', + 'tooltip' + ], + /** + * These collections (arrays) implement update() methods with support for + * one-to-one option. + */ + collectionsWithUpdate: [ + 'xAxis', + 'yAxis', + 'zAxis', + 'series' + ], + /** + * A generic function to update any element of the chart. Elements can be + * enabled and disabled, moved, re-styled, re-formatted etc. + * + * A special case is configuration objects that take arrays, for example + * [xAxis](https://api.highcharts.com/highcharts/xAxis), + * [yAxis](https://api.highcharts.com/highcharts/yAxis) or + * [series](https://api.highcharts.com/highcharts/series). For these + * collections, an `id` option is used to map the new option set to an + * existing object. If an existing object of the same id is not found, the + * corresponding item is updated. So for example, running `chart.update` + * with a series item without an id, will cause the existing chart's series + * with the same index in the series array to be updated. When the + * `oneToOne` parameter is true, `chart.update` will also take care of + * adding and removing items from the collection. Read more under the + * parameter description below. + * + * Note that when changing series data, `chart.update` may mutate the passed + * data options. + * + * See also the + * [responsive option set](https://api.highcharts.com/highcharts/responsive). + * Switching between `responsive.rules` basically runs `chart.update` under + * the hood. + * + * @sample highcharts/members/chart-update/ + * Update chart geometry + * + * @function Highcharts.Chart#update + * + * @param {Highcharts.Options} options + * A configuration object for the new chart options. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart. + * + * @param {boolean} [oneToOne=false] + * When `true`, the `series`, `xAxis`, `yAxis` and `annotations` + * collections will be updated one to one, and items will be either + * added or removed to match the new updated options. For example, + * if the chart has two series and we call `chart.update` with a + * configuration containing three series, one will be added. If we + * call `chart.update` with one series, one will be removed. Setting + * an empty `series` array will remove all series, but leaving out + * the`series` property will leave all series untouched. If the + * series have id's, the new series options will be matched by id, + * and the remaining ones removed. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=true] + * Whether to apply animation, and optionally animation + * configuration. + * + * @return {void} + * + * @fires Highcharts.Chart#event:update + * @fires Highcharts.Chart#event:afterUpdate + */ + update: function (options, redraw, oneToOne, animation) { + var chart = this, adders = { + credits: 'addCredits', + title: 'setTitle', + subtitle: 'setSubtitle', + caption: 'setCaption' + }, optionsChart, updateAllAxes, updateAllSeries, newWidth, newHeight, runSetSize, isResponsiveOptions = options.isResponsiveOptions, itemsForRemoval = []; + fireEvent(chart, 'update', { options: options }); + // If there are responsive rules in action, undo the responsive rules + // before we apply the updated options and replay the responsive rules + // on top from the chart.redraw function (#9617). + if (!isResponsiveOptions) { + chart.setResponsive(false, true); + } + options = H.cleanRecursively(options, chart.options); + merge(true, chart.userOptions, options); + // If the top-level chart option is present, some special updates are + // required + optionsChart = options.chart; + if (optionsChart) { + merge(true, chart.options.chart, optionsChart); + // Setter function + if ('className' in optionsChart) { + chart.setClassName(optionsChart.className); + } + if ('reflow' in optionsChart) { + chart.setReflow(optionsChart.reflow); + } + if ('inverted' in optionsChart || + 'polar' in optionsChart || + 'type' in optionsChart) { + // Parse options.chart.inverted and options.chart.polar together + // with the available series. + chart.propFromSeries(); + updateAllAxes = true; + } + if ('alignTicks' in optionsChart) { // #6452 + updateAllAxes = true; + } + objectEach(optionsChart, function (val, key) { + if (chart.propsRequireUpdateSeries.indexOf('chart.' + key) !== + -1) { + updateAllSeries = true; + } + // Only dirty box + if (chart.propsRequireDirtyBox.indexOf(key) !== -1) { + chart.isDirtyBox = true; + } + // Chart setSize + if (!isResponsiveOptions && + chart.propsRequireReflow.indexOf(key) !== -1) { + runSetSize = true; + } + }); + if (!chart.styledMode && 'style' in optionsChart) { + chart.renderer.setStyle(optionsChart.style); + } + } + // Moved up, because tooltip needs updated plotOptions (#6218) + if (!chart.styledMode && options.colors) { + this.options.colors = options.colors; + } + if (options.plotOptions) { + merge(true, this.options.plotOptions, options.plotOptions); + } + // Maintaining legacy global time. If the chart is instanciated first + // with global time, then updated with time options, we need to create a + // new Time instance to avoid mutating the global time (#10536). + if (options.time && this.time === H.time) { + this.time = new Time(options.time); + } + // Some option stuctures correspond one-to-one to chart objects that + // have update methods, for example + // options.credits => chart.credits + // options.legend => chart.legend + // options.title => chart.title + // options.tooltip => chart.tooltip + // options.subtitle => chart.subtitle + // options.mapNavigation => chart.mapNavigation + // options.navigator => chart.navigator + // options.scrollbar => chart.scrollbar + objectEach(options, function (val, key) { + if (chart[key] && + typeof chart[key].update === 'function') { + chart[key].update(val, false); + // If a one-to-one object does not exist, look for an adder function + } + else if (typeof chart[adders[key]] === 'function') { + chart[adders[key]](val); + } + if (key !== 'chart' && + chart.propsRequireUpdateSeries.indexOf(key) !== -1) { + updateAllSeries = true; + } + }); + // Setters for collections. For axes and series, each item is referred + // by an id. If the id is not found, it defaults to the corresponding + // item in the collection, so setting one series without an id, will + // update the first series in the chart. Setting two series without + // an id will update the first and the second respectively (#6019) + // chart.update and responsive. + this.collectionsWithUpdate.forEach(function (coll) { + var indexMap; + if (options[coll]) { + // In stock charts, the navigator series are also part of the + // chart.series array, but those series should not be handled + // here (#8196). + if (coll === 'series') { + indexMap = []; + chart[coll].forEach(function (s, i) { + if (!s.options.isInternal) { + indexMap.push(pick(s.options.index, i)); + } + }); + } + splat(options[coll]).forEach(function (newOptions, i) { + var item = (defined(newOptions.id) && + chart.get(newOptions.id)) || chart[coll][indexMap ? indexMap[i] : i]; + if (item && item.coll === coll) { + item.update(newOptions, false); + if (oneToOne) { + item.touched = true; + } + } + // If oneToOne and no matching item is found, add one + if (!item && oneToOne && chart.collectionsWithInit[coll]) { + chart.collectionsWithInit[coll][0].apply(chart, + // [newOptions, ...extraArguments, redraw=false] + [ + newOptions + ].concat( + // Not all initializers require extra args + chart.collectionsWithInit[coll][1] || []).concat([ + false + ])).touched = true; + } + }); + // Add items for removal + if (oneToOne) { + chart[coll].forEach(function (item) { + if (!item.touched && !item.options.isInternal) { + itemsForRemoval.push(item); + } + else { + delete item.touched; + } + }); + } + } + }); + itemsForRemoval.forEach(function (item) { + if (item.remove) { + item.remove(false); + } + }); + if (updateAllAxes) { + chart.axes.forEach(function (axis) { + axis.update({}, false); + }); + } + // Certain options require the whole series structure to be thrown away + // and rebuilt + if (updateAllSeries) { + chart.getSeriesOrderByLinks().forEach(function (series) { + // Avoid removed navigator series + if (series.chart) { + series.update({}, false); + } + }, this); + } + // For loading, just update the options, do not redraw + if (options.loading) { + merge(true, chart.options.loading, options.loading); + } + // Update size. Redraw is forced. + newWidth = optionsChart && optionsChart.width; + newHeight = optionsChart && optionsChart.height; + if (isString(newHeight)) { + newHeight = relativeLength(newHeight, newWidth || chart.chartWidth); + } + if ( + // In this case, run chart.setSize with newWidth and newHeight which + // are undefined, only for reflowing chart elements because margin + // or spacing has been set (#8190) + runSetSize || + // In this case, the size is actually set + (isNumber(newWidth) && newWidth !== chart.chartWidth) || + (isNumber(newHeight) && newHeight !== chart.chartHeight)) { + chart.setSize(newWidth, newHeight, animation); + } + else if (pick(redraw, true)) { + chart.redraw(animation); + } + fireEvent(chart, 'afterUpdate', { + options: options, + redraw: redraw, + animation: animation + }); + }, + /** + * Shortcut to set the subtitle options. This can also be done from {@link + * Chart#update} or {@link Chart#setTitle}. + * + * @function Highcharts.Chart#setSubtitle + * + * @param {Highcharts.SubtitleOptions} options + * New subtitle options. The subtitle text itself is set by the + * `options.text` property. + * + * @return {void} + */ + setSubtitle: function (options, redraw) { + this.applyDescription('subtitle', options); + this.layOutTitles(redraw); + }, + /** + * Set the caption options. This can also be done from {@link + * Chart#update}. + * + * @function Highcharts.Chart#setCaption + * + * @param {Highcharts.CaptionOptions} options + * New caption options. The caption text itself is set by the + * `options.text` property. + * + * @return {void} + */ + setCaption: function (options, redraw) { + this.applyDescription('caption', options); + this.layOutTitles(redraw); + } + }); + /** + * These collections (arrays) implement `Chart.addSomethig` method used in + * chart.update() to create new object in the collection. Equivalent for + * deleting is resolved by simple `Somethig.remove()`. + * + * Note: We need to define these references after initializers are bound to + * chart's prototype. + */ + Chart.prototype.collectionsWithInit = { + // collectionName: [ initializingMethod, [extraArguments] ] + xAxis: [Chart.prototype.addAxis, [true]], + yAxis: [Chart.prototype.addAxis, [false]], + series: [Chart.prototype.addSeries] + }; + // extend the Point prototype for dynamic methods + extend(Point.prototype, /** @lends Highcharts.Point.prototype */ { + /** + * Update point with new options (typically x/y data) and optionally redraw + * the series. + * + * @sample highcharts/members/point-update-column/ + * Update column value + * @sample highcharts/members/point-update-pie/ + * Update pie slice + * @sample maps/members/point-update/ + * Update map area value in Highmaps + * + * @function Highcharts.Point#update + * + * @param {Highcharts.PointOptionsType} options + * The point options. Point options are handled as described under + * the `series.type.data` item for each series type. For example + * for a line series, if options is a single number, the point will + * be given that number as the marin y value. If it is an array, it + * will be interpreted as x and y values respectively. If it is an + * object, advanced options are applied. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the point is updated. If doing + * more operations on the chart, it is best practice to set + * `redraw` to false and call `chart.redraw()` after. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=true] + * Whether to apply animation, and optionally animation + * configuration. + * + * @return {void} + * + * @fires Highcharts.Point#event:update + */ + update: function (options, redraw, animation, runEvent) { + var point = this, series = point.series, graphic = point.graphic, i, chart = series.chart, seriesOptions = series.options; + redraw = pick(redraw, true); + /** + * @private + */ + function update() { + point.applyOptions(options); + // Update visuals, #4146 + // Handle dummy graphic elements for a11y, #12718 + var hasDummyGraphic = graphic && point.hasDummyGraphic; + var shouldDestroyGraphic = point.y === null ? !hasDummyGraphic : hasDummyGraphic; + if (graphic && shouldDestroyGraphic) { + point.graphic = graphic.destroy(); + delete point.hasDummyGraphic; + } + if (isObject(options, true)) { + // Destroy so we can get new elements + if (graphic && graphic.element) { + // "null" is also a valid symbol + if (options && + options.marker && + typeof options.marker.symbol !== 'undefined') { + point.graphic = graphic.destroy(); + } + } + if (options && options.dataLabels && point.dataLabel) { + point.dataLabel = point.dataLabel.destroy(); // #2468 + } + if (point.connector) { + point.connector = point.connector.destroy(); // #7243 + } + } + // record changes in the parallel arrays + i = point.index; + series.updateParallelArrays(point, i); + // Record the options to options.data. If the old or the new config + // is an object, use point options, otherwise use raw options + // (#4701, #4916). + seriesOptions.data[i] = (isObject(seriesOptions.data[i], true) || + isObject(options, true)) ? + point.options : + pick(options, seriesOptions.data[i]); + // redraw + series.isDirty = series.isDirtyData = true; + if (!series.fixedBox && series.hasCartesianSeries) { // #1906, #2320 + chart.isDirtyBox = true; + } + if (seriesOptions.legendType === 'point') { // #1831, #1885 + chart.isDirtyLegend = true; + } + if (redraw) { + chart.redraw(animation); + } + } + // Fire the event with a default handler of doing the update + if (runEvent === false) { // When called from setData + update(); + } + else { + point.firePointEvent('update', { options: options }, update); + } + }, + /** + * Remove a point and optionally redraw the series and if necessary the axes + * + * @sample highcharts/plotoptions/series-point-events-remove/ + * Remove point and confirm + * @sample highcharts/members/point-remove/ + * Remove pie slice + * @sample maps/members/point-remove/ + * Remove selected points in Highmaps + * + * @function Highcharts.Point#remove + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call. When + * doing more operations on the chart, for example running + * `point.remove()` in a loop, it is best practice to set `redraw` + * to false and call `chart.redraw()` after. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=false] + * Whether to apply animation, and optionally animation + * configuration. + * + * @return {void} + */ + remove: function (redraw, animation) { + this.series.removePoint(this.series.data.indexOf(this), redraw, animation); + } + }); + // Extend the series prototype for dynamic methods + extend(Series.prototype, /** @lends Series.prototype */ { + /** + * Add a point to the series after render time. The point can be added at + * the end, or by giving it an X value, to the start or in the middle of the + * series. + * + * @sample highcharts/members/series-addpoint-append/ + * Append point + * @sample highcharts/members/series-addpoint-append-and-shift/ + * Append and shift + * @sample highcharts/members/series-addpoint-x-and-y/ + * Both X and Y values given + * @sample highcharts/members/series-addpoint-pie/ + * Append pie slice + * @sample stock/members/series-addpoint/ + * Append 100 points in Highstock + * @sample stock/members/series-addpoint-shift/ + * Append and shift in Highstock + * @sample maps/members/series-addpoint/ + * Add a point in Highmaps + * + * @function Highcharts.Series#addPoint + * + * @param {Highcharts.PointOptionsType} options + * The point options. If options is a single number, a point with + * that y value is appended to the series. If it is an array, it will + * be interpreted as x and y values respectively. If it is an + * object, advanced options as outlined under `series.data` are + * applied. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the point is added. When adding + * more than one point, it is highly recommended that the redraw + * option be set to false, and instead {@link Chart#redraw} is + * explicitly called after the adding of points is finished. + * Otherwise, the chart will redraw after adding each point. + * + * @param {boolean} [shift=false] + * If true, a point is shifted off the start of the series as one is + * appended to the end. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * Whether to apply animation, and optionally animation + * configuration. + * + * @param {boolean} [withEvent=true] + * Used internally, whether to fire the series `addPoint` event. + * + * @return {void} + * + * @fires Highcharts.Series#event:addPoint + */ + addPoint: function (options, redraw, shift, animation, withEvent) { + var series = this, seriesOptions = series.options, data = series.data, chart = series.chart, xAxis = series.xAxis, names = xAxis && xAxis.hasNames && xAxis.names, dataOptions = seriesOptions.data, point, xData = series.xData, isInTheMiddle, i, x; + // Optional redraw, defaults to true + redraw = pick(redraw, true); + // Get options and push the point to xData, yData and series.options. In + // series.generatePoints the Point instance will be created on demand + // and pushed to the series.data array. + point = { series: series }; + series.pointClass.prototype.applyOptions.apply(point, [options]); + x = point.x; + // Get the insertion point + i = xData.length; + if (series.requireSorting && x < xData[i - 1]) { + isInTheMiddle = true; + while (i && xData[i - 1] > x) { + i--; + } + } + // Insert undefined item + series.updateParallelArrays(point, 'splice', i, 0, 0); + // Update it + series.updateParallelArrays(point, i); + if (names && point.name) { + names[x] = point.name; + } + dataOptions.splice(i, 0, options); + if (isInTheMiddle) { + series.data.splice(i, 0, null); + series.processData(); + } + // Generate points to be added to the legend (#1329) + if (seriesOptions.legendType === 'point') { + series.generatePoints(); + } + // Shift the first point off the parallel arrays + if (shift) { + if (data[0] && data[0].remove) { + data[0].remove(false); + } + else { + data.shift(); + series.updateParallelArrays(point, 'shift'); + dataOptions.shift(); + } + } + // Fire event + if (withEvent !== false) { + fireEvent(series, 'addPoint', { point: point }); + } + // redraw + series.isDirty = true; + series.isDirtyData = true; + if (redraw) { + chart.redraw(animation); // Animation is set anyway on redraw, #5665 + } + }, + /** + * Remove a point from the series. Unlike the + * {@link Highcharts.Point#remove} method, this can also be done on a point + * that is not instanciated because it is outside the view or subject to + * Highstock data grouping. + * + * @sample highcharts/members/series-removepoint/ + * Remove cropped point + * + * @function Highcharts.Series#removePoint + * + * @param {number} i + * The index of the point in the {@link Highcharts.Series.data|data} + * array. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the point is added. When + * removing more than one point, it is highly recommended that the + * `redraw` option be set to `false`, and instead {@link + * Highcharts.Chart#redraw} is explicitly called after the adding of + * points is finished. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * Whether and optionally how the series should be animated. + * + * @return {void} + * + * @fires Highcharts.Point#event:remove + */ + removePoint: function (i, redraw, animation) { + var series = this, data = series.data, point = data[i], points = series.points, chart = series.chart, remove = function () { + if (points && points.length === data.length) { // #4935 + points.splice(i, 1); + } + data.splice(i, 1); + series.options.data.splice(i, 1); + series.updateParallelArrays(point || { series: series }, 'splice', i, 1); + if (point) { + point.destroy(); + } + // redraw + series.isDirty = true; + series.isDirtyData = true; + if (redraw) { + chart.redraw(); + } + }; + setAnimation(animation, chart); + redraw = pick(redraw, true); + // Fire the event with a default handler of removing the point + if (point) { + point.firePointEvent('remove', null, remove); + } + else { + remove(); + } + }, + /** + * Remove a series and optionally redraw the chart. + * + * @sample highcharts/members/series-remove/ + * Remove first series from a button + * + * @function Highcharts.Series#remove + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call to + * {@link Highcharts.Chart#redraw}. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * Whether to apply animation, and optionally animation + * configuration. + * + * @param {boolean} [withEvent=true] + * Used internally, whether to fire the series `remove` event. + * + * @return {void} + * + * @fires Highcharts.Series#event:remove + */ + remove: function (redraw, animation, withEvent, keepEvents) { + var series = this, chart = series.chart; + /** + * @private + */ + function remove() { + // Destroy elements + series.destroy(keepEvents); + series.remove = null; // Prevent from doing again (#9097) + // Redraw + chart.isDirtyLegend = chart.isDirtyBox = true; + chart.linkSeries(); + if (pick(redraw, true)) { + chart.redraw(animation); + } + } + // Fire the event with a default handler of removing the point + if (withEvent !== false) { + fireEvent(series, 'remove', null, remove); + } + else { + remove(); + } + }, + /** + * Update the series with a new set of options. For a clean and precise + * handling of new options, all methods and elements from the series are + * removed, and it is initialized from scratch. Therefore, this method is + * more performance expensive than some other utility methods like {@link + * Series#setData} or {@link Series#setVisible}. + * + * Note that `Series.update` may mutate the passed `data` options. + * + * @sample highcharts/members/series-update/ + * Updating series options + * @sample maps/members/series-update/ + * Update series options in Highmaps + * + * @function Highcharts.Series#update + * + * @param {Highcharts.SeriesOptionsType} options + * New options that will be merged with the series' existing options. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the series is altered. If doing + * more operations on the chart, it is a good idea to set redraw to + * false and call {@link Chart#redraw} after. + * + * @return {void} + * + * @fires Highcharts.Series#event:update + * @fires Highcharts.Series#event:afterUpdate + */ + update: function (options, redraw) { + options = H.cleanRecursively(options, this.userOptions); + fireEvent(this, 'update', { options: options }); + var series = this, chart = series.chart, + // must use user options when changing type because series.options + // is merged in with type specific plotOptions + oldOptions = series.userOptions, seriesOptions, initialType = series.initialType || series.type, newType = (options.type || + oldOptions.type || + chart.options.chart.type), keepPoints = !( + // Indicators, histograms etc recalculate the data. It should be + // possible to omit this. + this.hasDerivedData || + // Changes to data grouping requires new points in new groups + options.dataGrouping || + // New type requires new point classes + (newType && newType !== this.type) || + // New options affecting how the data points are built + typeof options.pointStart !== 'undefined' || + options.pointInterval || + options.pointIntervalUnit || + options.keys), initialSeriesProto = seriesTypes[initialType].prototype, n, groups = [ + 'group', + 'markerGroup', + 'dataLabelsGroup', + 'transformGroup' + ], preserve = [ + 'eventOptions', + 'navigatorSeries', + 'baseSeries' + ], + // Animation must be enabled when calling update before the initial + // animation has first run. This happens when calling update + // directly after chart initialization, or when applying responsive + // rules (#6912). + animation = series.finishedAnimating && { animation: false }, kinds = {}; + if (keepPoints) { + preserve.push('data', 'isDirtyData', 'points', 'processedXData', 'processedYData', 'xIncrement', '_hasPointMarkers', '_hasPointLabels', + // Map specific, consider moving it to series-specific preserve- + // properties (#10617) + 'mapMap', 'mapData', 'minY', 'maxY', 'minX', 'maxX'); + if (options.visible !== false) { + preserve.push('area', 'graph'); + } + series.parallelArrays.forEach(function (key) { + preserve.push(key + 'Data'); + }); + if (options.data) { + // setData uses dataSorting options so we need to update them + // earlier + if (options.dataSorting) { + extend(series.options.dataSorting, options.dataSorting); + } + this.setData(options.data, false); + } + } + // Do the merge, with some forced options + options = merge(oldOptions, animation, { + // When oldOptions.index is null it should't be cleared. + // Otherwise navigator series will have wrong indexes (#10193). + index: typeof oldOptions.index === 'undefined' ? + series.index : oldOptions.index, + pointStart: pick( + // when updating from blank (#7933) + oldOptions.pointStart, + // when updating after addPoint + series.xData[0]) + }, (!keepPoints && { data: series.options.data }), options); + // Merge does not merge arrays, but replaces them. Since points were + // updated, `series.options.data` has correct merged options, use it: + if (keepPoints && options.data) { + options.data = series.options.data; + } + // Make sure preserved properties are not destroyed (#3094) + preserve = groups.concat(preserve); + preserve.forEach(function (prop) { + preserve[prop] = series[prop]; + delete series[prop]; + }); + // Destroy the series and delete all properties. Reinsert all + // methods and properties from the new type prototype (#2270, + // #3719). + series.remove(false, null, false, true); + for (n in initialSeriesProto) { // eslint-disable-line guard-for-in + series[n] = void 0; + } + if (seriesTypes[newType || initialType]) { + extend(series, seriesTypes[newType || initialType].prototype); + } + else { + error(17, true, chart, { missingModuleFor: (newType || initialType) }); + } + // Re-register groups (#3094) and other preserved properties + preserve.forEach(function (prop) { + series[prop] = preserve[prop]; + }); + series.init(chart, options); + // Remove particular elements of the points. Check `series.options` + // because we need to consider the options being set on plotOptions as + // well. + if (keepPoints && this.points) { + seriesOptions = series.options; + // What kind of elements to destroy + if (seriesOptions.visible === false) { + kinds.graphic = 1; + kinds.dataLabel = 1; + } + else if (!series._hasPointLabels) { + var marker = seriesOptions.marker, dataLabels = seriesOptions.dataLabels; + if (marker && (marker.enabled === false || + 'symbol' in marker // #10870 + )) { + kinds.graphic = 1; + } + if (dataLabels && + dataLabels.enabled === false) { + kinds.dataLabel = 1; + } + } + this.points.forEach(function (point) { + if (point && point.series) { + point.resolveColor(); + // Destroy elements in order to recreate based on updated + // series options. + if (Object.keys(kinds).length) { + point.destroyElements(kinds); + } + if (seriesOptions.showInLegend === false && + point.legendItem) { + chart.legend.destroyItem(point); + } + } + }, this); + } + // Update the Z index of groups (#3380, #7397) + if (options.zIndex !== oldOptions.zIndex) { + groups.forEach(function (groupName) { + if (series[groupName]) { + series[groupName].attr({ + zIndex: options.zIndex + }); + } + }); + } + series.initialType = initialType; + chart.linkSeries(); // Links are lost in series.remove (#3028) + fireEvent(this, 'afterUpdate'); + if (pick(redraw, true)) { + chart.redraw(keepPoints ? void 0 : false); + } + }, + /** + * Used from within series.update + * + * @private + * @function Highcharts.Series#setName + * + * @param {string} name + * + * @return {void} + */ + setName: function (name) { + this.name = this.options.name = this.userOptions.name = name; + this.chart.isDirtyLegend = true; + } + }); + // Extend the Axis.prototype for dynamic methods + extend(Axis.prototype, /** @lends Highcharts.Axis.prototype */ { + /** + * Update an axis object with a new set of options. The options are merged + * with the existing options, so only new or altered options need to be + * specified. + * + * @sample highcharts/members/axis-update/ + * Axis update demo + * + * @function Highcharts.Axis#update + * + * @param {Highcharts.AxisOptions} options + * The new options that will be merged in with existing options on + * the axis. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the axis is altered. If doing + * more operations on the chart, it is a good idea to set redraw to + * false and call {@link Chart#redraw} after. + * + * @return {void} + */ + update: function (options, redraw) { + var chart = this.chart, newEvents = ((options && options.events) || {}); + options = merge(this.userOptions, options); + // Color Axis is not an array, + // This change is applied in the ColorAxis wrapper + if (chart.options[this.coll].indexOf) { + // Don't use this.options.index, + // StockChart has Axes in navigator too + chart.options[this.coll][chart.options[this.coll].indexOf(this.userOptions)] = options; + } + // Remove old events, if no new exist (#8161) + objectEach(chart.options[this.coll].events, function (fn, ev) { + if (typeof newEvents[ev] === 'undefined') { + newEvents[ev] = void 0; + } + }); + this.destroy(true); + this.init(chart, extend(options, { events: newEvents })); + chart.isDirtyBox = true; + if (pick(redraw, true)) { + chart.redraw(); + } + }, + /** + * Remove the axis from the chart. + * + * @sample highcharts/members/chart-addaxis/ + * Add and remove axes + * + * @function Highcharts.Axis#remove + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart following the remove. + * + * @return {void} + */ + remove: function (redraw) { + var chart = this.chart, key = this.coll, // xAxis or yAxis + axisSeries = this.series, i = axisSeries.length; + // Remove associated series (#2687) + while (i--) { + if (axisSeries[i]) { + axisSeries[i].remove(false); + } + } + // Remove the axis + erase(chart.axes, this); + erase(chart[key], this); + if (isArray(chart.options[key])) { + chart.options[key].splice(this.options.index, 1); + } + else { // color axis, #6488 + delete chart.options[key]; + } + chart[key].forEach(function (axis, i) { + // Re-index, #1706, #8075 + axis.options.index = axis.userOptions.index = i; + }); + this.destroy(); + chart.isDirtyBox = true; + if (pick(redraw, true)) { + chart.redraw(); + } + }, + /** + * Update the axis title by options after render time. + * + * @sample highcharts/members/axis-settitle/ + * Set a new Y axis title + * + * @function Highcharts.Axis#setTitle + * + * @param {Highcharts.AxisTitleOptions} titleOptions + * The additional title options. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after setting the title. + * + * @return {void} + */ + setTitle: function (titleOptions, redraw) { + this.update({ title: titleOptions }, redraw); + }, + /** + * Set new axis categories and optionally redraw. + * + * @sample highcharts/members/axis-setcategories/ + * Set categories by click on a button + * + * @function Highcharts.Axis#setCategories + * + * @param {Array} categories + * The new categories. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart. + * + * @return {void} + */ + setCategories: function (categories, redraw) { + this.update({ categories: categories }, redraw); + } + }); + + }); + _registerModule(_modules, 'parts/AreaSeries.js', [_modules['parts/Globals.js'], _modules['parts/Color.js'], _modules['mixins/legend-symbol.js'], _modules['parts/Utilities.js']], function (H, Color, LegendSymbolMixin, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var color = Color.parse; + var objectEach = U.objectEach, pick = U.pick, seriesType = U.seriesType; + var Series = H.Series; + /** + * Area series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.area + * + * @augments Highcharts.Series + */ + seriesType('area', 'line', + /** + * The area series type. + * + * @sample {highcharts} highcharts/demo/area-basic/ + * Area chart + * @sample {highstock} stock/demo/area/ + * Area chart + * + * @extends plotOptions.line + * @excluding useOhlcData + * @product highcharts highstock + * @optionparent plotOptions.area + */ + { + /** + * Fill color or gradient for the area. When `null`, the series' `color` + * is used with the series' `fillOpacity`. + * + * In styled mode, the fill color can be set with the `.highcharts-area` + * class name. + * + * @sample {highcharts} highcharts/plotoptions/area-fillcolor-default/ + * Null by default + * @sample {highcharts} highcharts/plotoptions/area-fillcolor-gradient/ + * Gradient + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock + * @apioption plotOptions.area.fillColor + */ + /** + * Fill opacity for the area. When you set an explicit `fillColor`, + * the `fillOpacity` is not applied. Instead, you should define the + * opacity in the `fillColor` with an rgba color definition. The + * `fillOpacity` setting, also the default setting, overrides the alpha + * component of the `color` setting. + * + * In styled mode, the fill opacity can be set with the + * `.highcharts-area` class name. + * + * @sample {highcharts} highcharts/plotoptions/area-fillopacity/ + * Automatic fill color and fill opacity of 0.1 + * + * @type {number} + * @default {highcharts} 0.75 + * @default {highstock} 0.75 + * @product highcharts highstock + * @apioption plotOptions.area.fillOpacity + */ + /** + * A separate color for the graph line. By default the line takes the + * `color` of the series, but the lineColor setting allows setting a + * separate color for the line without altering the `fillColor`. + * + * In styled mode, the line stroke can be set with the + * `.highcharts-graph` class name. + * + * @sample {highcharts} highcharts/plotoptions/area-linecolor/ + * Dark gray line + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock + * @apioption plotOptions.area.lineColor + */ + /** + * A separate color for the negative part of the area. + * + * In styled mode, a negative color is set with the + * `.highcharts-negative` class name. + * + * @see [negativeColor](#plotOptions.area.negativeColor) + * + * @sample {highcharts} highcharts/css/series-negative-color/ + * Negative color in styled mode + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 3.0 + * @product highcharts + * @apioption plotOptions.area.negativeFillColor + */ + /** + * Whether the whole area or just the line should respond to mouseover + * tooltips and other mouse or touch events. + * + * @sample {highcharts|highstock} highcharts/plotoptions/area-trackbyarea/ + * Display the tooltip when the area is hovered + * + * @type {boolean} + * @default false + * @since 1.1.6 + * @product highcharts highstock + * @apioption plotOptions.area.trackByArea + */ + /** + * When this is true, the series will not cause the Y axis to cross + * the zero plane (or [threshold](#plotOptions.series.threshold) option) + * unless the data actually crosses the plane. + * + * For example, if `softThreshold` is `false`, a series of 0, 1, 2, + * 3 will make the Y axis show negative values according to the + * `minPadding` option. If `softThreshold` is `true`, the Y axis starts + * at 0. + * + * @since 4.1.9 + * @product highcharts highstock + */ + softThreshold: false, + /** + * The Y axis value to serve as the base for the area, for + * distinguishing between values above and below a threshold. The area + * between the graph and the threshold is filled. + * + * * If a number is given, the Y axis will scale to the threshold. + * * If `null`, the scaling behaves like a line series with fill between + * the graph and the Y axis minimum. + * * If `Infinity` or `-Infinity`, the area between the graph and the + * corresponing Y axis extreme is filled (since v6.1.0). + * + * @sample {highcharts} highcharts/plotoptions/area-threshold/ + * A threshold of 100 + * @sample {highcharts} highcharts/plotoptions/area-threshold-infinity/ + * A threshold of Infinity + * + * @type {number|null} + * @since 2.0 + * @product highcharts highstock + */ + threshold: 0 + }, + /* eslint-disable valid-jsdoc */ + /** + * @lends seriesTypes.area.prototype + */ + { + singleStacks: false, + /** + * Return an array of stacked points, where null and missing points are + * replaced by dummy points in order for gaps to be drawn correctly in + * stacks. + * @private + */ + getStackPoints: function (points) { + var series = this, segment = [], keys = [], xAxis = this.xAxis, yAxis = this.yAxis, stack = yAxis.stacking.stacks[this.stackKey], pointMap = {}, seriesIndex = series.index, yAxisSeries = yAxis.series, seriesLength = yAxisSeries.length, visibleSeries, upOrDown = pick(yAxis.options.reversedStacks, true) ? 1 : -1, i; + points = points || this.points; + if (this.options.stacking) { + for (i = 0; i < points.length; i++) { + // Reset after point update (#7326) + points[i].leftNull = points[i].rightNull = void 0; + // Create a map where we can quickly look up the points by + // their X values. + pointMap[points[i].x] = points[i]; + } + // Sort the keys (#1651) + objectEach(stack, function (stackX, x) { + // nulled after switching between + // grouping and not (#1651, #2336) + if (stackX.total !== null) { + keys.push(x); + } + }); + keys.sort(function (a, b) { + return a - b; + }); + visibleSeries = yAxisSeries.map(function (s) { + return s.visible; + }); + keys.forEach(function (x, idx) { + var y = 0, stackPoint, stackedValues; + if (pointMap[x] && !pointMap[x].isNull) { + segment.push(pointMap[x]); + // Find left and right cliff. -1 goes left, 1 goes + // right. + [-1, 1].forEach(function (direction) { + var nullName = direction === 1 ? + 'rightNull' : + 'leftNull', cliffName = direction === 1 ? + 'rightCliff' : + 'leftCliff', cliff = 0, otherStack = stack[keys[idx + direction]]; + // If there is a stack next to this one, + // to the left or to the right... + if (otherStack) { + i = seriesIndex; + // Can go either up or down, + // depending on reversedStacks + while (i >= 0 && i < seriesLength) { + stackPoint = otherStack.points[i]; + if (!stackPoint) { + // If the next point in this series + // is missing, mark the point + // with point.leftNull or + // point.rightNull = true. + if (i === seriesIndex) { + pointMap[x][nullName] = + true; + // If there are missing points in + // the next stack in any of the + // series below this one, we need + // to substract the missing values + // and add a hiatus to the left or + // right. + } + else if (visibleSeries[i]) { + stackedValues = + stack[x].points[i]; + if (stackedValues) { + cliff -= + stackedValues[1] - + stackedValues[0]; + } + } + } + // When reversedStacks is true, loop up, + // else loop down + i += upOrDown; + } + } + pointMap[x][cliffName] = cliff; + }); + // There is no point for this X value in this series, so we + // insert a dummy point in order for the areas to be drawn + // correctly. + } + else { + // Loop down the stack to find the series below this + // one that has a value (#1991) + i = seriesIndex; + while (i >= 0 && i < seriesLength) { + stackPoint = stack[x].points[i]; + if (stackPoint) { + y = stackPoint[1]; + break; + } + // When reversedStacks is true, loop up, else loop + // down + i += upOrDown; + } + y = yAxis.translate(// #6272 + y, 0, 1, 0, 1); + segment.push({ + isNull: true, + plotX: xAxis.translate(// #6272 + x, 0, 0, 0, 1), + x: x, + plotY: y, + yBottom: y + }); + } + }); + } + return segment; + }, + /** + * @private + */ + getGraphPath: function (points) { + var getGraphPath = Series.prototype.getGraphPath, graphPath, options = this.options, stacking = options.stacking, yAxis = this.yAxis, topPath, bottomPath, bottomPoints = [], graphPoints = [], seriesIndex = this.index, i, areaPath, plotX, stacks = yAxis.stacking.stacks[this.stackKey], threshold = options.threshold, translatedThreshold = Math.round(// #10909 + yAxis.getThreshold(options.threshold)), isNull, yBottom, connectNulls = pick(// #10574 + options.connectNulls, stacking === 'percent'), + // To display null points in underlying stacked series, this + // series graph must be broken, and the area also fall down to + // fill the gap left by the null point. #2069 + addDummyPoints = function (i, otherI, side) { + var point = points[i], stackedValues = stacking && + stacks[point.x].points[seriesIndex], nullVal = point[side + 'Null'] || 0, cliffVal = point[side + 'Cliff'] || 0, top, bottom, isNull = true; + if (cliffVal || nullVal) { + top = (nullVal ? + stackedValues[0] : + stackedValues[1]) + cliffVal; + bottom = stackedValues[0] + cliffVal; + isNull = !!nullVal; + } + else if (!stacking && + points[otherI] && + points[otherI].isNull) { + top = bottom = threshold; + } + // Add to the top and bottom line of the area + if (typeof top !== 'undefined') { + graphPoints.push({ + plotX: plotX, + plotY: top === null ? + translatedThreshold : + yAxis.getThreshold(top), + isNull: isNull, + isCliff: true + }); + bottomPoints.push({ + plotX: plotX, + plotY: bottom === null ? + translatedThreshold : + yAxis.getThreshold(bottom), + doCurve: false // #1041, gaps in areaspline areas + }); + } + }; + // Find what points to use + points = points || this.points; + // Fill in missing points + if (stacking) { + points = this.getStackPoints(points); + } + for (i = 0; i < points.length; i++) { + // Reset after series.update of stacking property (#12033) + if (!stacking) { + points[i].leftCliff = points[i].rightCliff = + points[i].leftNull = points[i].rightNull = void 0; + } + isNull = points[i].isNull; + plotX = pick(points[i].rectPlotX, points[i].plotX); + yBottom = pick(points[i].yBottom, translatedThreshold); + if (!isNull || connectNulls) { + if (!connectNulls) { + addDummyPoints(i, i - 1, 'left'); + } + // Skip null point when stacking is false and connectNulls + // true + if (!(isNull && !stacking && connectNulls)) { + graphPoints.push(points[i]); + bottomPoints.push({ + x: i, + plotX: plotX, + plotY: yBottom + }); + } + if (!connectNulls) { + addDummyPoints(i, i + 1, 'right'); + } + } + } + topPath = getGraphPath.call(this, graphPoints, true, true); + bottomPoints.reversed = true; + bottomPath = getGraphPath.call(this, bottomPoints, true, true); + var firstBottomPoint = bottomPath[0]; + if (firstBottomPoint && firstBottomPoint[0] === 'M') { + bottomPath[0] = ['L', firstBottomPoint[1], firstBottomPoint[2]]; + } + areaPath = topPath.concat(bottomPath); + // TODO: don't set leftCliff and rightCliff when connectNulls? + graphPath = getGraphPath + .call(this, graphPoints, false, connectNulls); + areaPath.xMap = topPath.xMap; + this.areaPath = areaPath; + return graphPath; + }, + /** + * Draw the graph and the underlying area. This method calls the Series + * base function and adds the area. The areaPath is calculated in the + * getSegmentPath method called from Series.prototype.drawGraph. + * @private + */ + drawGraph: function () { + // Define or reset areaPath + this.areaPath = []; + // Call the base method + Series.prototype.drawGraph.apply(this); + // Define local variables + var series = this, areaPath = this.areaPath, options = this.options, zones = this.zones, props = [[ + 'area', + 'highcharts-area', + this.color, + options.fillColor + ]]; // area name, main color, fill color + zones.forEach(function (zone, i) { + props.push([ + 'zone-area-' + i, + 'highcharts-area highcharts-zone-area-' + i + ' ' + + zone.className, + zone.color || series.color, + zone.fillColor || options.fillColor + ]); + }); + props.forEach(function (prop) { + var areaKey = prop[0], area = series[areaKey], verb = area ? 'animate' : 'attr', attribs = {}; + // Create or update the area + if (area) { // update + area.endX = series.preventGraphAnimation ? + null : + areaPath.xMap; + area.animate({ d: areaPath }); + } + else { // create + attribs.zIndex = 0; // #1069 + area = series[areaKey] = series.chart.renderer + .path(areaPath) + .addClass(prop[1]) + .add(series.group); + area.isArea = true; + } + if (!series.chart.styledMode) { + attribs.fill = pick(prop[3], color(prop[2]) + .setOpacity(pick(options.fillOpacity, 0.75)) + .get()); + } + area[verb](attribs); + area.startX = areaPath.xMap; + area.shiftUnit = options.step ? 2 : 1; + }); + }, + drawLegendSymbol: LegendSymbolMixin.drawRectangle + }); + /* eslint-enable valid-jsdoc */ + /** + * A `area` series. If the [type](#series.area.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.area + * @excluding dataParser, dataURL, useOhlcData + * @product highcharts highstock + * @apioption series.area + */ + /** + * An array of data points for the series. For the `area` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` * and `pointInterval` given in the series options. If the + * axis has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 9], + * [1, 7], + * [2, 6] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.area.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @product highcharts highstock + * @apioption series.area.data + */ + ''; // adds doclets above to transpilat + + }); + _registerModule(_modules, 'parts/SplineSeries.js', [_modules['parts/Utilities.js']], function (U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var pick = U.pick, seriesType = U.seriesType; + /** + * Spline series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.spline + * + * @augments Highcarts.Series + */ + seriesType('spline', 'line', + /** + * A spline series is a special type of line series, where the segments + * between the data points are smoothed. + * + * @sample {highcharts} highcharts/demo/spline-irregular-time/ + * Spline chart + * @sample {highstock} stock/demo/spline/ + * Spline chart + * + * @extends plotOptions.series + * @excluding step + * @product highcharts highstock + * @optionparent plotOptions.spline + */ + {}, + /** + * @lends seriesTypes.spline.prototype + */ + { + /* eslint-disable valid-jsdoc */ + /** + * Get the spline segment from a given point's previous neighbour to the + * given point. + * + * @private + * @function Highcharts.seriesTypes.spline#getPointSpline + * + * @param {Array} + * + * @param {Highcharts.Point} point + * + * @param {number} i + * + * @return {Highcharts.SVGPathArray} + */ + getPointSpline: function (points, point, i) { + var + // 1 means control points midway between points, 2 means 1/3 + // from the point, 3 is 1/4 etc + smoothing = 1.5, denom = smoothing + 1, plotX = point.plotX || 0, plotY = point.plotY || 0, lastPoint = points[i - 1], nextPoint = points[i + 1], leftContX, leftContY, rightContX, rightContY, ret; + /** + * @private + */ + function doCurve(otherPoint) { + return otherPoint && + !otherPoint.isNull && + otherPoint.doCurve !== false && + // #6387, area splines next to null: + !point.isCliff; + } + // Find control points + if (doCurve(lastPoint) && doCurve(nextPoint)) { + var lastX = lastPoint.plotX || 0, lastY = lastPoint.plotY || 0, nextX = nextPoint.plotX || 0, nextY = nextPoint.plotY || 0, correction = 0; + leftContX = (smoothing * plotX + lastX) / denom; + leftContY = (smoothing * plotY + lastY) / denom; + rightContX = (smoothing * plotX + nextX) / denom; + rightContY = (smoothing * plotY + nextY) / denom; + // Have the two control points make a straight line through main + // point + if (rightContX !== leftContX) { // #5016, division by zero + correction = (((rightContY - leftContY) * + (rightContX - plotX)) / + (rightContX - leftContX) + plotY - rightContY); + } + leftContY += correction; + rightContY += correction; + // to prevent false extremes, check that control points are + // between neighbouring points' y values + if (leftContY > lastY && leftContY > plotY) { + leftContY = Math.max(lastY, plotY); + // mirror of left control point + rightContY = 2 * plotY - leftContY; + } + else if (leftContY < lastY && leftContY < plotY) { + leftContY = Math.min(lastY, plotY); + rightContY = 2 * plotY - leftContY; + } + if (rightContY > nextY && rightContY > plotY) { + rightContY = Math.max(nextY, plotY); + leftContY = 2 * plotY - rightContY; + } + else if (rightContY < nextY && rightContY < plotY) { + rightContY = Math.min(nextY, plotY); + leftContY = 2 * plotY - rightContY; + } + // record for drawing in next point + point.rightContX = rightContX; + point.rightContY = rightContY; + } + // Visualize control points for debugging + /* + if (leftContX) { + this.chart.renderer.circle( + leftContX + this.chart.plotLeft, + leftContY + this.chart.plotTop, + 2 + ) + .attr({ + stroke: 'red', + 'stroke-width': 2, + fill: 'none', + zIndex: 9 + }) + .add(); + this.chart.renderer.path(['M', leftContX + this.chart.plotLeft, + leftContY + this.chart.plotTop, + 'L', plotX + this.chart.plotLeft, plotY + this.chart.plotTop]) + .attr({ + stroke: 'red', + 'stroke-width': 2, + zIndex: 9 + }) + .add(); + } + if (rightContX) { + this.chart.renderer.circle( + rightContX + this.chart.plotLeft, + rightContY + this.chart.plotTop, + 2 + ) + .attr({ + stroke: 'green', + 'stroke-width': 2, + fill: 'none', + zIndex: 9 + }) + .add(); + this.chart.renderer.path(['M', rightContX + this.chart.plotLeft, + rightContY + this.chart.plotTop, + 'L', plotX + this.chart.plotLeft, plotY + this.chart.plotTop]) + .attr({ + stroke: 'green', + 'stroke-width': 2, + zIndex: 9 + }) + .add(); + } + // */ + ret = [ + 'C', + pick(lastPoint.rightContX, lastPoint.plotX, 0), + pick(lastPoint.rightContY, lastPoint.plotY, 0), + pick(leftContX, plotX, 0), + pick(leftContY, plotY, 0), + plotX, + plotY + ]; + // reset for updating series later + lastPoint.rightContX = lastPoint.rightContY = void 0; + return ret; + } + /* eslint-enable valid-jsdoc */ + }); + /** + * A `spline` series. If the [type](#series.spline.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.spline + * @excluding dataParser, dataURL, step + * @product highcharts highstock + * @apioption series.spline + */ + /** + * An array of data points for the series. For the `spline` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 9], + * [1, 2], + * [2, 8] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.spline.turboThreshold), + * this option is not available. + * ```js + * data: [{ + * x: 1, + * y: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 0, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @product highcharts highstock + * @apioption series.spline.data + */ + ''; // adds doclets above intro transpilat + + }); + _registerModule(_modules, 'parts/AreaSplineSeries.js', [_modules['parts/Globals.js'], _modules['mixins/legend-symbol.js'], _modules['parts/Utilities.js']], function (H, LegendSymbolMixin, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var seriesType = U.seriesType; + var areaProto = H.seriesTypes.area.prototype, defaultPlotOptions = H.defaultPlotOptions; + /** + * AreaSpline series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.areaspline + * + * @augments Highcharts.Series + */ + seriesType('areaspline', 'spline', + /** + * The area spline series is an area series where the graph between the + * points is smoothed into a spline. + * + * @sample {highcharts} highcharts/demo/areaspline/ + * Area spline chart + * @sample {highstock} stock/demo/areaspline/ + * Area spline chart + * + * @extends plotOptions.area + * @excluding step + * @product highcharts highstock + * @apioption plotOptions.areaspline + */ + defaultPlotOptions.area, { + getStackPoints: areaProto.getStackPoints, + getGraphPath: areaProto.getGraphPath, + drawGraph: areaProto.drawGraph, + drawLegendSymbol: LegendSymbolMixin.drawRectangle + }); + /** + * A `areaspline` series. If the [type](#series.areaspline.type) option + * is not specified, it is inherited from [chart.type](#chart.type). + * + * + * @extends series,plotOptions.areaspline + * @excluding dataParser, dataURL, step + * @product highcharts highstock + * @apioption series.areaspline + */ + /** + * An array of data points for the series. For the `areaspline` series + * type, points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 10], + * [1, 9], + * [2, 3] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.areaspline.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 4, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 4, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @product highcharts highstock + * @apioption series.areaspline.data + */ + ''; // adds doclets above into transpilat + + }); + _registerModule(_modules, 'parts/ColumnSeries.js', [_modules['parts/Globals.js'], _modules['parts/Color.js'], _modules['mixins/legend-symbol.js'], _modules['parts/Utilities.js']], function (H, Color, LegendSymbolMixin, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Adjusted width and x offset of the columns for grouping. + * + * @private + * @interface Highcharts.ColumnMetricsObject + */ /** + * Width of the columns. + * @name Highcharts.ColumnMetricsObject#width + * @type {number} + */ /** + * Offset of the columns. + * @name Highcharts.ColumnMetricsObject#offset + * @type {number} + */ + ''; // detach doclets above + var color = Color.parse; + var animObject = U.animObject, clamp = U.clamp, defined = U.defined, extend = U.extend, isNumber = U.isNumber, merge = U.merge, pick = U.pick, seriesType = U.seriesType; + var noop = H.noop, Series = H.Series, svg = H.svg; + /** + * The column series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.column + * + * @augments Highcharts.Series + */ + seriesType('column', 'line', + /** + * Column series display one column per value along an X axis. + * + * @sample {highcharts} highcharts/demo/column-basic/ + * Column chart + * @sample {highstock} stock/demo/column/ + * Column chart + * + * @extends plotOptions.line + * @excluding connectEnds, connectNulls, gapSize, gapUnit, linecap, + * lineWidth, marker, step, useOhlcData + * @product highcharts highstock + * @optionparent plotOptions.column + */ + { + /** + * The corner radius of the border surrounding each column or bar. + * + * @sample {highcharts} highcharts/plotoptions/column-borderradius/ + * Rounded columns + * + * @product highcharts highstock gantt + * + * @private + */ + borderRadius: 0, + /** + * When using automatic point colors pulled from the global + * [colors](colors) or series-specific + * [plotOptions.column.colors](series.colors) collections, this option + * determines whether the chart should receive one color per series or + * one color per point. + * + * In styled mode, the `colors` or `series.colors` arrays are not + * supported, and instead this option gives the points individual color + * class names on the form `highcharts-color-{n}`. + * + * @see [series colors](#plotOptions.column.colors) + * + * @sample {highcharts} highcharts/plotoptions/column-colorbypoint-false/ + * False by default + * @sample {highcharts} highcharts/plotoptions/column-colorbypoint-true/ + * True + * + * @type {boolean} + * @default false + * @since 2.0 + * @product highcharts highstock gantt + * @apioption plotOptions.column.colorByPoint + */ + /** + * A series specific or series type specific color set to apply instead + * of the global [colors](#colors) when [colorByPoint]( + * #plotOptions.column.colorByPoint) is true. + * + * @type {Array} + * @since 3.0 + * @product highcharts highstock gantt + * @apioption plotOptions.column.colors + */ + /** + * Padding between each value groups, in x axis units. + * + * @sample {highcharts} highcharts/plotoptions/column-grouppadding-default/ + * 0.2 by default + * @sample {highcharts} highcharts/plotoptions/column-grouppadding-none/ + * No group padding - all columns are evenly spaced + * + * @product highcharts highstock gantt + * + * @private + */ + groupPadding: 0.2, + /** + * Whether to group non-stacked columns or to let them render + * independent of each other. Non-grouped columns will be laid out + * individually and overlap each other. + * + * @sample {highcharts} highcharts/plotoptions/column-grouping-false/ + * Grouping disabled + * @sample {highstock} highcharts/plotoptions/column-grouping-false/ + * Grouping disabled + * + * @type {boolean} + * @default true + * @since 2.3.0 + * @product highcharts highstock gantt + * @apioption plotOptions.column.grouping + */ + /** + * @ignore-option + * @private + */ + marker: null, + /** + * The maximum allowed pixel width for a column, translated to the + * height of a bar in a bar chart. This prevents the columns from + * becoming too wide when there is a small number of points in the + * chart. + * + * @see [pointWidth](#plotOptions.column.pointWidth) + * + * @sample {highcharts} highcharts/plotoptions/column-maxpointwidth-20/ + * Limited to 50 + * @sample {highstock} highcharts/plotoptions/column-maxpointwidth-20/ + * Limited to 50 + * + * @type {number} + * @since 4.1.8 + * @product highcharts highstock gantt + * @apioption plotOptions.column.maxPointWidth + */ + /** + * Padding between each column or bar, in x axis units. + * + * @sample {highcharts} highcharts/plotoptions/column-pointpadding-default/ + * 0.1 by default + * @sample {highcharts} highcharts/plotoptions/column-pointpadding-025/ + * 0.25 + * @sample {highcharts} highcharts/plotoptions/column-pointpadding-none/ + * 0 for tightly packed columns + * + * @product highcharts highstock gantt + * + * @private + */ + pointPadding: 0.1, + /** + * A pixel value specifying a fixed width for each column or bar. When + * `null`, the width is calculated from the `pointPadding` and + * `groupPadding`. + * + * @see [maxPointWidth](#plotOptions.column.maxPointWidth) + * + * @sample {highcharts} highcharts/plotoptions/column-pointwidth-20/ + * 20px wide columns regardless of chart width or the amount of + * data points + * + * @type {number} + * @since 1.2.5 + * @product highcharts highstock gantt + * @apioption plotOptions.column.pointWidth + */ + /** + * A pixel value specifying a fixed width for the column or bar. + * Overrides pointWidth on the series. + * + * @see [series.pointWidth](#plotOptions.column.pointWidth) + * + * @type {number} + * @default undefined + * @since 7.0.0 + * @product highcharts highstock gantt + * @apioption series.column.data.pointWidth + */ + /** + * The minimal height for a column or width for a bar. By default, + * 0 values are not shown. To visualize a 0 (or close to zero) point, + * set the minimal point length to a pixel value like 3\. In stacked + * column charts, minPointLength might not be respected for tightly + * packed values. + * + * @sample {highcharts} highcharts/plotoptions/column-minpointlength/ + * Zero base value + * @sample {highcharts} highcharts/plotoptions/column-minpointlength-pos-and-neg/ + * Positive and negative close to zero values + * + * @product highcharts highstock gantt + * + * @private + */ + minPointLength: 0, + /** + * When the series contains less points than the crop threshold, all + * points are drawn, event if the points fall outside the visible plot + * area at the current zoom. The advantage of drawing all points + * (including markers and columns), is that animation is performed on + * updates. On the other hand, when the series contains more points than + * the crop threshold, the series data is cropped to only contain points + * that fall within the plot area. The advantage of cropping away + * invisible points is to increase performance on large series. + * + * @product highcharts highstock gantt + * + * @private + */ + cropThreshold: 50, + /** + * The X axis range that each point is valid for. This determines the + * width of the column. On a categorized axis, the range will be 1 + * by default (one category unit). On linear and datetime axes, the + * range will be computed as the distance between the two closest data + * points. + * + * The default `null` means it is computed automatically, but this + * option can be used to override the automatic value. + * + * This option is set by default to 1 if data sorting is enabled. + * + * @sample {highcharts} highcharts/plotoptions/column-pointrange/ + * Set the point range to one day on a data set with one week + * between the points + * + * @type {number|null} + * @since 2.3 + * @product highcharts highstock gantt + * + * @private + */ + pointRange: null, + states: { + /** + * Options for the hovered point. These settings override the normal + * state options when a point is moused over or touched. + * + * @extends plotOptions.series.states.hover + * @excluding halo, lineWidth, lineWidthPlus, marker + * @product highcharts highstock gantt + */ + hover: { + /** @ignore-option */ + halo: false, + /** + * A specific border color for the hovered point. Defaults to + * inherit the normal state border color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts gantt + * @apioption plotOptions.column.states.hover.borderColor + */ + /** + * A specific color for the hovered point. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts gantt + * @apioption plotOptions.column.states.hover.color + */ + /** + * How much to brighten the point on interaction. Requires the + * main color to be defined in hex or rgb(a) format. + * + * In styled mode, the hover brightening is by default replaced + * with a fill-opacity set in the `.highcharts-point:hover` + * rule. + * + * @sample {highcharts} highcharts/plotoptions/column-states-hover-brightness/ + * Brighten by 0.5 + * + * @product highcharts highstock gantt + */ + brightness: 0.1 + }, + /** + * Options for the selected point. These settings override the + * normal state options when a point is selected. + * + * @extends plotOptions.series.states.select + * @excluding halo, lineWidth, lineWidthPlus, marker + * @product highcharts highstock gantt + */ + select: { + /** + * A specific color for the selected point. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #cccccc + * @product highcharts highstock gantt + */ + color: '#cccccc', + /** + * A specific border color for the selected point. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #000000 + * @product highcharts highstock gantt + */ + borderColor: '#000000' + } + }, + dataLabels: { + align: null, + verticalAlign: null, + y: null + }, + /** + * When this is true, the series will not cause the Y axis to cross + * the zero plane (or [threshold](#plotOptions.series.threshold) option) + * unless the data actually crosses the plane. + * + * For example, if `softThreshold` is `false`, a series of 0, 1, 2, + * 3 will make the Y axis show negative values according to the + * `minPadding` option. If `softThreshold` is `true`, the Y axis starts + * at 0. + * + * @since 4.1.9 + * @product highcharts highstock + * + * @private + */ + softThreshold: false, + // false doesn't work well: https://jsfiddle.net/highcharts/hz8fopan/14/ + /** + * @ignore-option + * @private + */ + startFromThreshold: true, + stickyTracking: false, + tooltip: { + distance: 6 + }, + /** + * The Y axis value to serve as the base for the columns, for + * distinguishing between values above and below a threshold. If `null`, + * the columns extend from the padding Y axis minimum. + * + * @type {number|null} + * @since 2.0 + * @product highcharts + * + * @private + */ + threshold: 0, + /** + * The width of the border surrounding each column or bar. Defaults to + * `1` when there is room for a border, but to `0` when the columns are + * so dense that a border would cover the next column. + * + * In styled mode, the stroke width can be set with the + * `.highcharts-point` rule. + * + * @sample {highcharts} highcharts/plotoptions/column-borderwidth/ + * 2px black border + * + * @type {number} + * @default undefined + * @product highcharts highstock gantt + * @apioption plotOptions.column.borderWidth + */ + /** + * The color of the border surrounding each column or bar. + * + * In styled mode, the border stroke can be set with the + * `.highcharts-point` rule. + * + * @sample {highcharts} highcharts/plotoptions/column-bordercolor/ + * Dark gray border + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #ffffff + * @product highcharts highstock gantt + * + * @private + */ + borderColor: '#ffffff' + }, + /** + * @lends seriesTypes.column.prototype + */ + { + cropShoulder: 0, + // When tooltip is not shared, this series (and derivatives) requires + // direct touch/hover. KD-tree does not apply. + directTouch: true, + trackerGroups: ['group', 'dataLabelsGroup'], + // use separate negative stacks, unlike area stacks where a negative + // point is substracted from previous (#1910) + negStacks: true, + /* eslint-disable valid-jsdoc */ + /** + * Initialize the series. Extends the basic Series.init method by + * marking other series of the same type as dirty. + * + * @private + * @function Highcharts.seriesTypes.column#init + * @return {void} + */ + init: function () { + Series.prototype.init.apply(this, arguments); + var series = this, chart = series.chart; + // if the series is added dynamically, force redraw of other + // series affected by a new column + if (chart.hasRendered) { + chart.series.forEach(function (otherSeries) { + if (otherSeries.type === series.type) { + otherSeries.isDirty = true; + } + }); + } + }, + /** + * Return the width and x offset of the columns adjusted for grouping, + * groupPadding, pointPadding, pointWidth etc. + * + * @private + * @function Highcharts.seriesTypes.column#getColumnMetrics + * @return {Highcharts.ColumnMetricsObject} + */ + getColumnMetrics: function () { + var series = this, options = series.options, xAxis = series.xAxis, yAxis = series.yAxis, reversedStacks = xAxis.options.reversedStacks, + // Keep backward compatibility: reversed xAxis had reversed + // stacks + reverseStacks = (xAxis.reversed && !reversedStacks) || + (!xAxis.reversed && reversedStacks), stackKey, stackGroups = {}, columnCount = 0; + // Get the total number of column type series. This is called on + // every series. Consider moving this logic to a chart.orderStacks() + // function and call it on init, addSeries and removeSeries + if (options.grouping === false) { + columnCount = 1; + } + else { + series.chart.series.forEach(function (otherSeries) { + var otherYAxis = otherSeries.yAxis, otherOptions = otherSeries.options, columnIndex; + if (otherSeries.type === series.type && + (otherSeries.visible || + !series.chart.options.chart + .ignoreHiddenSeries) && + yAxis.len === otherYAxis.len && + yAxis.pos === otherYAxis.pos) { // #642, #2086 + if (otherOptions.stacking) { + stackKey = otherSeries.stackKey; + if (typeof stackGroups[stackKey] === + 'undefined') { + stackGroups[stackKey] = columnCount++; + } + columnIndex = stackGroups[stackKey]; + } + else if (otherOptions.grouping !== false) { // #1162 + columnIndex = columnCount++; + } + otherSeries.columnIndex = columnIndex; + } + }); + } + var categoryWidth = Math.min(Math.abs(xAxis.transA) * ((xAxis.ordinal && xAxis.ordinal.slope) || + options.pointRange || + xAxis.closestPointRange || + xAxis.tickInterval || + 1), // #2610 + xAxis.len // #1535 + ), groupPadding = categoryWidth * options.groupPadding, groupWidth = categoryWidth - 2 * groupPadding, pointOffsetWidth = groupWidth / (columnCount || 1), pointWidth = Math.min(options.maxPointWidth || xAxis.len, pick(options.pointWidth, pointOffsetWidth * (1 - 2 * options.pointPadding))), pointPadding = (pointOffsetWidth - pointWidth) / 2, + // #1251, #3737 + colIndex = (series.columnIndex || 0) + (reverseStacks ? 1 : 0), pointXOffset = pointPadding + + (groupPadding + + colIndex * pointOffsetWidth - + (categoryWidth / 2)) * (reverseStacks ? -1 : 1); + // Save it for reading in linked series (Error bars particularly) + series.columnMetrics = { + width: pointWidth, + offset: pointXOffset + }; + return series.columnMetrics; + }, + /** + * Make the columns crisp. The edges are rounded to the nearest full + * pixel. + * + * @private + * @function Highcharts.seriesTypes.column#crispCol + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @return {Highcharts.BBoxObject} + */ + crispCol: function (x, y, w, h) { + var chart = this.chart, borderWidth = this.borderWidth, xCrisp = -(borderWidth % 2 ? 0.5 : 0), yCrisp = borderWidth % 2 ? 0.5 : 1, right, bottom, fromTop; + if (chart.inverted && chart.renderer.isVML) { + yCrisp += 1; + } + // Horizontal. We need to first compute the exact right edge, then + // round it and compute the width from there. + if (this.options.crisp) { + right = Math.round(x + w) + xCrisp; + x = Math.round(x) + xCrisp; + w = right - x; + } + // Vertical + bottom = Math.round(y + h) + yCrisp; + fromTop = Math.abs(y) <= 0.5 && bottom > 0.5; // #4504, #4656 + y = Math.round(y) + yCrisp; + h = bottom - y; + // Top edges are exceptions + if (fromTop && h) { // #5146 + y -= 1; + h += 1; + } + return { + x: x, + y: y, + width: w, + height: h + }; + }, + /** + * Translate each point to the plot area coordinate system and find + * shape positions + * + * @private + * @function Highcharts.seriesTypes.column#translate + */ + translate: function () { + var series = this, chart = series.chart, options = series.options, dense = series.dense = + series.closestPointRange * series.xAxis.transA < 2, borderWidth = series.borderWidth = pick(options.borderWidth, dense ? 0 : 1 // #3635 + ), xAxis = series.xAxis, yAxis = series.yAxis, threshold = options.threshold, translatedThreshold = series.translatedThreshold = + yAxis.getThreshold(threshold), minPointLength = pick(options.minPointLength, 5), metrics = series.getColumnMetrics(), seriesPointWidth = metrics.width, + // postprocessed for border width + seriesBarW = series.barW = + Math.max(seriesPointWidth, 1 + 2 * borderWidth), seriesXOffset = series.pointXOffset = metrics.offset, dataMin = series.dataMin, dataMax = series.dataMax; + if (chart.inverted) { + translatedThreshold -= 0.5; // #3355 + } + // When the pointPadding is 0, we want the columns to be packed + // tightly, so we allow individual columns to have individual sizes. + // When pointPadding is greater, we strive for equal-width columns + // (#2694). + if (options.pointPadding) { + seriesBarW = Math.ceil(seriesBarW); + } + Series.prototype.translate.apply(series); + // Record the new values + series.points.forEach(function (point) { + var yBottom = pick(point.yBottom, translatedThreshold), safeDistance = 999 + Math.abs(yBottom), pointWidth = seriesPointWidth, plotX = point.plotX, + // Don't draw too far outside plot area (#1303, #2241, + // #4264) + plotY = clamp(point.plotY, -safeDistance, yAxis.len + safeDistance), barX = point.plotX + seriesXOffset, barW = seriesBarW, barY = Math.min(plotY, yBottom), up, barH = Math.max(plotY, yBottom) - barY; + // Handle options.minPointLength + if (minPointLength && Math.abs(barH) < minPointLength) { + barH = minPointLength; + up = (!yAxis.reversed && !point.negative) || + (yAxis.reversed && point.negative); + // Reverse zeros if there's no positive value in the series + // in visible range (#7046) + if (isNumber(threshold) && + isNumber(dataMax) && + point.y === threshold && + dataMax <= threshold && + // and if there's room for it (#7311) + (yAxis.min || 0) < threshold && + // if all points are the same value (i.e zero) not draw + // as negative points (#10646) + dataMin !== dataMax) { + up = !up; + } + // If stacked... + barY = (Math.abs(barY - translatedThreshold) > minPointLength ? + // ...keep position + yBottom - minPointLength : + // #1485, #4051 + translatedThreshold - + (up ? minPointLength : 0)); + } + // Handle point.options.pointWidth + // @todo Handle grouping/stacking too. Calculate offset properly + if (defined(point.options.pointWidth)) { + pointWidth = barW = + Math.ceil(point.options.pointWidth); + barX -= Math.round((pointWidth - seriesPointWidth) / 2); + } + // Cache for access in polar + point.barX = barX; + point.pointWidth = pointWidth; + // Fix the tooltip on center of grouped columns (#1216, #424, + // #3648) + point.tooltipPos = chart.inverted ? + [ + yAxis.len + yAxis.pos - chart.plotLeft - plotY, + xAxis.len + xAxis.pos - chart.plotTop - (plotX || 0) - seriesXOffset - barW / 2, + barH + ] : + [barX + barW / 2, plotY + yAxis.pos - + chart.plotTop, barH]; + // Register shape type and arguments to be used in drawPoints + // Allow shapeType defined on pointClass level + point.shapeType = + series.pointClass.prototype.shapeType || 'rect'; + point.shapeArgs = series.crispCol.apply(series, point.isNull ? + // #3169, drilldown from null must have a position to work + // from #6585, dataLabel should be placed on xAxis, not + // floating in the middle of the chart + [barX, translatedThreshold, barW, 0] : + [barX, barY, barW, barH]); + }); + }, + getSymbol: noop, + /** + * Use a solid rectangle like the area series types + * + * @private + * @function Highcharts.seriesTypes.column#drawLegendSymbol + * + * @param {Highcharts.Legend} legend + * The legend object + * + * @param {Highcharts.Series|Highcharts.Point} item + * The series (this) or point + */ + drawLegendSymbol: LegendSymbolMixin.drawRectangle, + /** + * Columns have no graph + * + * @private + * @function Highcharts.seriesTypes.column#drawGraph + */ + drawGraph: function () { + this.group[this.dense ? 'addClass' : 'removeClass']('highcharts-dense-data'); + }, + /** + * Get presentational attributes + * + * @private + * @function Highcharts.seriesTypes.column#pointAttribs + * + * @param {Highcharts.ColumnPoint} point + * + * @param {string} state + * + * @return {Highcharts.SVGAttributes} + */ + pointAttribs: function (point, state) { + var options = this.options, stateOptions, ret, p2o = this.pointAttrToOptions || {}, strokeOption = p2o.stroke || 'borderColor', strokeWidthOption = p2o['stroke-width'] || 'borderWidth', fill = (point && point.color) || this.color, + // set to fill when borderColor null: + stroke = ((point && point[strokeOption]) || + options[strokeOption] || + this.color || + fill), strokeWidth = (point && point[strokeWidthOption]) || + options[strokeWidthOption] || + this[strokeWidthOption] || 0, dashstyle = (point && point.options.dashStyle) || options.dashStyle, opacity = pick(point && point.opacity, options.opacity, 1), zone, brightness; + // Handle zone colors + if (point && this.zones.length) { + zone = point.getZone(); + // When zones are present, don't use point.color (#4267). + // Changed order (#6527), added support for colorAxis (#10670) + fill = (point.options.color || + (zone && (zone.color || point.nonZonedColor)) || + this.color); + if (zone) { + stroke = zone.borderColor || stroke; + dashstyle = zone.dashStyle || dashstyle; + strokeWidth = zone.borderWidth || strokeWidth; + } + } + // Select or hover states + if (state && point) { + stateOptions = merge(options.states[state], + // #6401 + point.options.states && + point.options.states[state] || + {}); + brightness = stateOptions.brightness; + fill = + stateOptions.color || (typeof brightness !== 'undefined' && + color(fill) + .brighten(stateOptions.brightness) + .get()) || fill; + stroke = stateOptions[strokeOption] || stroke; + strokeWidth = + stateOptions[strokeWidthOption] || strokeWidth; + dashstyle = stateOptions.dashStyle || dashstyle; + opacity = pick(stateOptions.opacity, opacity); + } + ret = { + fill: fill, + stroke: stroke, + 'stroke-width': strokeWidth, + opacity: opacity + }; + if (dashstyle) { + ret.dashstyle = dashstyle; + } + return ret; + }, + /** + * Draw the columns. For bars, the series.group is rotated, so the same + * coordinates apply for columns and bars. This method is inherited by + * scatter series. + * + * @private + * @function Highcharts.seriesTypes.column#drawPoints + */ + drawPoints: function () { + var series = this, chart = this.chart, options = series.options, renderer = chart.renderer, animationLimit = options.animationLimit || 250, shapeArgs; + // draw the columns + series.points.forEach(function (point) { + var plotY = point.plotY, graphic = point.graphic, hasGraphic = !!graphic, verb = graphic && chart.pointCount < animationLimit ? + 'animate' : 'attr'; + if (isNumber(plotY) && point.y !== null) { + shapeArgs = point.shapeArgs; + // When updating a series between 2d and 3d or cartesian and + // polar, the shape type changes. + if (graphic && point.hasNewShapeType()) { + graphic = graphic.destroy(); + } + // Set starting position for point sliding animation. + if (series.enabledDataSorting) { + point.startXPos = series.xAxis.reversed ? + -(shapeArgs ? shapeArgs.width : 0) : + series.xAxis.width; + } + if (!graphic) { + point.graphic = graphic = + renderer[point.shapeType](shapeArgs) + .add(point.group || series.group); + if (graphic && + series.enabledDataSorting && + chart.hasRendered && + chart.pointCount < animationLimit) { + graphic.attr({ + x: point.startXPos + }); + hasGraphic = true; + verb = 'animate'; + } + } + if (graphic && hasGraphic) { // update + graphic[verb](merge(shapeArgs)); + } + // Border radius is not stylable (#6900) + if (options.borderRadius) { + graphic[verb]({ + r: options.borderRadius + }); + } + // Presentational + if (!chart.styledMode) { + graphic[verb](series.pointAttribs(point, (point.selected && 'select'))) + .shadow(point.allowShadow !== false && options.shadow, null, options.stacking && !options.borderRadius); + } + graphic.addClass(point.getClassName(), true); + } + else if (graphic) { + point.graphic = graphic.destroy(); // #1269 + } + }); + }, + /** + * Animate the column heights one by one from zero. + * + * @private + * @function Highcharts.seriesTypes.column#animate + * + * @param {boolean} init + * Whether to initialize the animation or run it + */ + animate: function (init) { + var series = this, yAxis = this.yAxis, options = series.options, inverted = this.chart.inverted, attr = {}, translateProp = inverted ? 'translateX' : 'translateY', translateStart, translatedThreshold; + if (init) { + attr.scaleY = 0.001; + translatedThreshold = clamp(yAxis.toPixels(options.threshold), yAxis.pos, yAxis.pos + yAxis.len); + if (inverted) { + attr.translateX = translatedThreshold - yAxis.len; + } + else { + attr.translateY = translatedThreshold; + } + // apply finnal clipping (used in Highstock) (#7083) + // animation is done by scaleY, so cliping is for panes + if (series.clipBox) { + series.setClip(); + } + series.group.attr(attr); + } + else { // run the animation + translateStart = series.group.attr(translateProp); + series.group.animate({ scaleY: 1 }, extend(animObject(series.options.animation), { + // Do the scale synchronously to ensure smooth + // updating (#5030, #7228) + step: function (val, fx) { + if (series.group) { + attr[translateProp] = translateStart + + fx.pos * (yAxis.pos - translateStart); + series.group.attr(attr); + } + } + })); + } + }, + /** + * Remove this series from the chart + * + * @private + * @function Highcharts.seriesTypes.column#remove + */ + remove: function () { + var series = this, chart = series.chart; + // column and bar series affects other series of the same type + // as they are either stacked or grouped + if (chart.hasRendered) { + chart.series.forEach(function (otherSeries) { + if (otherSeries.type === series.type) { + otherSeries.isDirty = true; + } + }); + } + Series.prototype.remove.apply(series, arguments); + } + }); + /* eslint-enable valid-jsdoc */ + /** + * A `column` series. If the [type](#series.column.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.column + * @excluding connectNulls, dataParser, dataURL, gapSize, gapUnit, linecap, + * lineWidth, marker, connectEnds, step + * @product highcharts highstock + * @apioption series.column + */ + /** + * An array of data points for the series. For the `column` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 6], + * [1, 2], + * [2, 6] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.column.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @excluding marker + * @product highcharts highstock + * @apioption series.column.data + */ + /** + * The color of the border surrounding the column or bar. + * + * In styled mode, the border stroke can be set with the `.highcharts-point` + * rule. + * + * @sample {highcharts} highcharts/plotoptions/column-bordercolor/ + * Dark gray border + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock + * @apioption series.column.data.borderColor + */ + /** + * The width of the border surrounding the column or bar. + * + * In styled mode, the stroke width can be set with the `.highcharts-point` + * rule. + * + * @sample {highcharts} highcharts/plotoptions/column-borderwidth/ + * 2px black border + * + * @type {number} + * @product highcharts highstock + * @apioption series.column.data.borderWidth + */ + /** + * A name for the dash style to use for the column or bar. Overrides + * dashStyle on the series. + * + * In styled mode, the stroke dash-array can be set with the same classes as + * listed under [data.color](#series.column.data.color). + * + * @see [series.pointWidth](#plotOptions.column.dashStyle) + * + * @type {Highcharts.DashStyleValue} + * @apioption series.column.data.dashStyle + */ + /** + * A pixel value specifying a fixed width for the column or bar. Overrides + * pointWidth on the series. + * + * @see [series.pointWidth](#plotOptions.column.pointWidth) + * + * @type {number} + * @apioption series.column.data.pointWidth + */ + /** + * @excluding halo, lineWidth, lineWidthPlus, marker + * @product highcharts highstock + * @apioption series.column.states.hover + */ + /** + * @excluding halo, lineWidth, lineWidthPlus, marker + * @product highcharts highstock + * @apioption series.column.states.select + */ + ''; // includes above doclets in transpilat + + }); + _registerModule(_modules, 'parts/BarSeries.js', [_modules['parts/Utilities.js']], function (U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var seriesType = U.seriesType; + /** + * Bar series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.bar + * + * @augments Highcharts.Series + */ + seriesType('bar', 'column', + /** + * A bar series is a special type of column series where the columns are + * horizontal. + * + * @sample highcharts/demo/bar-basic/ + * Bar chart + * + * @extends plotOptions.column + * @product highcharts + * @apioption plotOptions.bar + */ + /** + * @ignore + */ + null, { + inverted: true + }); + /** + * A `bar` series. If the [type](#series.bar.type) option is not specified, + * it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.bar + * @excluding connectNulls, dashStyle, dataParser, dataURL, gapSize, gapUnit, + * linecap, lineWidth, marker, connectEnds, step + * @product highcharts + * @apioption series.bar + */ + /** + * An array of data points for the series. For the `bar` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 5], + * [1, 10], + * [2, 3] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.bar.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 1, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 10, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.column.data + * @product highcharts + * @apioption series.bar.data + */ + /** + * @excluding halo,lineWidth,lineWidthPlus,marker + * @product highcharts highstock + * @apioption series.bar.states.hover + */ + /** + * @excluding halo,lineWidth,lineWidthPlus,marker + * @product highcharts highstock + * @apioption series.bar.states.select + */ + ''; // gets doclets above into transpilat + + }); + _registerModule(_modules, 'parts/ScatterSeries.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, seriesType = U.seriesType; + var Series = H.Series; + /** + * Scatter series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.scatter + * + * @augments Highcharts.Series + */ + seriesType('scatter', 'line', + /** + * A scatter plot uses cartesian coordinates to display values for two + * variables for a set of data. + * + * @sample {highcharts} highcharts/demo/scatter/ + * Scatter plot + * + * @extends plotOptions.line + * @excluding pointPlacement, shadow, useOhlcData + * @product highcharts highstock + * @optionparent plotOptions.scatter + */ + { + /** + * The width of the line connecting the data points. + * + * @sample {highcharts} highcharts/plotoptions/scatter-linewidth-none/ + * 0 by default + * @sample {highcharts} highcharts/plotoptions/scatter-linewidth-1/ + * 1px + * + * @product highcharts highstock + */ + lineWidth: 0, + findNearestPointBy: 'xy', + /** + * Apply a jitter effect for the rendered markers. When plotting + * discrete values, a little random noise may help telling the points + * apart. The jitter setting applies a random displacement of up to `n` + * axis units in either direction. So for example on a horizontal X + * axis, setting the `jitter.x` to 0.24 will render the point in a + * random position between 0.24 units to the left and 0.24 units to the + * right of the true axis position. On a category axis, setting it to + * 0.5 will fill up the bin and make the data appear continuous. + * + * When rendered on top of a box plot or a column series, a jitter value + * of 0.24 will correspond to the underlying series' default + * [groupPadding]( + * https://api.highcharts.com/highcharts/plotOptions.column.groupPadding) + * and [pointPadding]( + * https://api.highcharts.com/highcharts/plotOptions.column.pointPadding) + * settings. + * + * @sample {highcharts} highcharts/series-scatter/jitter + * Jitter on a scatter plot + * + * @sample {highcharts} highcharts/series-scatter/jitter-boxplot + * Jittered scatter plot on top of a box plot + * + * @product highcharts highstock + * @since 7.0.2 + */ + jitter: { + /** + * The maximal X offset for the random jitter effect. + */ + x: 0, + /** + * The maximal Y offset for the random jitter effect. + */ + y: 0 + }, + marker: { + enabled: true // Overrides auto-enabling in line series (#3647) + }, + /** + * Sticky tracking of mouse events. When true, the `mouseOut` event + * on a series isn't triggered until the mouse moves over another + * series, or out of the plot area. When false, the `mouseOut` event on + * a series is triggered when the mouse leaves the area around the + * series' graph or markers. This also implies the tooltip. When + * `stickyTracking` is false and `tooltip.shared` is false, the tooltip + * will be hidden when moving the mouse between series. + * + * @type {boolean} + * @default false + * @product highcharts highstock + * @apioption plotOptions.scatter.stickyTracking + */ + /** + * A configuration object for the tooltip rendering of each single + * series. Properties are inherited from [tooltip](#tooltip). + * Overridable properties are `headerFormat`, `pointFormat`, + * `yDecimals`, `xDateFormat`, `yPrefix` and `ySuffix`. Unlike other + * series, in a scatter plot the series.name by default shows in the + * headerFormat and point.x and point.y in the pointFormat. + * + * @product highcharts highstock + */ + tooltip: { + headerFormat: '\u25CF ' + + ' {series.name}
', + pointFormat: 'x: {point.x}
y: {point.y}
' + } + // Prototype members + }, { + sorted: false, + requireSorting: false, + noSharedTooltip: true, + trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'], + takeOrdinalPosition: false, + /* eslint-disable valid-jsdoc */ + /** + * @private + * @function Highcharts.seriesTypes.scatter#drawGraph + */ + drawGraph: function () { + if (this.options.lineWidth) { + Series.prototype.drawGraph.call(this); + } + }, + // Optionally add the jitter effect + applyJitter: function () { + var series = this, jitter = this.options.jitter, len = this.points.length; + /** + * Return a repeatable, pseudo-random number based on an integer + * seed. + * @private + */ + function unrandom(seed) { + var rand = Math.sin(seed) * 10000; + return rand - Math.floor(rand); + } + if (jitter) { + this.points.forEach(function (point, i) { + ['x', 'y'].forEach(function (dim, j) { + var axis, plotProp = 'plot' + dim.toUpperCase(), min, max, translatedJitter; + if (jitter[dim] && !point.isNull) { + axis = series[dim + 'Axis']; + translatedJitter = + jitter[dim] * axis.transA; + if (axis && !axis.isLog) { + // Identify the outer bounds of the jitter range + min = Math.max(0, point[plotProp] - translatedJitter); + max = Math.min(axis.len, point[plotProp] + translatedJitter); + // Find a random position within this range + point[plotProp] = min + + (max - min) * unrandom(i + j * len); + // Update clientX for the tooltip k-d-tree + if (dim === 'x') { + point.clientX = point.plotX; + } + } + } + }); + }); + } + } + /* eslint-enable valid-jsdoc */ + }); + /* eslint-disable no-invalid-this */ + addEvent(Series, 'afterTranslate', function () { + if (this.applyJitter) { + this.applyJitter(); + } + }); + /* eslint-enable no-invalid-this */ + /** + * A `scatter` series. If the [type](#series.scatter.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.scatter + * @excluding dataParser, dataURL, useOhlcData + * @product highcharts highstock + * @apioption series.scatter + */ + /** + * An array of data points for the series. For the `scatter` series + * type, points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 0], + * [1, 8], + * [2, 9] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.scatter.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 2, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 4, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @product highcharts highstock + * @apioption series.scatter.data + */ + ''; // adds doclets above to transpilat + + }); + _registerModule(_modules, 'mixins/centered-series.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * @private + * @interface Highcharts.RadianAngles + */ /** + * @name Highcharts.RadianAngles#end + * @type {number} + */ /** + * @name Highcharts.RadianAngles#start + * @type {number} + */ + var isNumber = U.isNumber, pick = U.pick, relativeLength = U.relativeLength; + var deg2rad = H.deg2rad; + /* eslint-disable valid-jsdoc */ + /** + * @private + * @mixin Highcharts.CenteredSeriesMixin + */ + H.CenteredSeriesMixin = { + /** + * Get the center of the pie based on the size and center options relative + * to the plot area. Borrowed by the polar and gauge series types. + * + * @private + * @function Highcharts.CenteredSeriesMixin.getCenter + * + * @return {Array} + */ + getCenter: function () { + var options = this.options, chart = this.chart, slicingRoom = 2 * (options.slicedOffset || 0), handleSlicingRoom, plotWidth = chart.plotWidth - 2 * slicingRoom, plotHeight = chart.plotHeight - 2 * slicingRoom, centerOption = options.center, smallestSize = Math.min(plotWidth, plotHeight), size = options.size, innerSize = options.innerSize || 0, positions, i, value; + if (typeof size === 'string') { + size = parseFloat(size); + } + if (typeof innerSize === 'string') { + innerSize = parseFloat(innerSize); + } + positions = [ + pick(centerOption[0], '50%'), + pick(centerOption[1], '50%'), + // Prevent from negative values + pick(size && size < 0 ? void 0 : options.size, '100%'), + pick(innerSize && innerSize < 0 ? void 0 : options.innerSize || 0, '0%') + ]; + // No need for inner size in angular (gauges) series + if (chart.angular) { + positions[3] = 0; + } + for (i = 0; i < 4; ++i) { + value = positions[i]; + handleSlicingRoom = i < 2 || (i === 2 && /%$/.test(value)); + // i == 0: centerX, relative to width + // i == 1: centerY, relative to height + // i == 2: size, relative to smallestSize + // i == 3: innerSize, relative to size + positions[i] = relativeLength(value, [plotWidth, plotHeight, smallestSize, positions[2]][i]) + (handleSlicingRoom ? slicingRoom : 0); + } + // innerSize cannot be larger than size (#3632) + if (positions[3] > positions[2]) { + positions[3] = positions[2]; + } + return positions; + }, + /** + * getStartAndEndRadians - Calculates start and end angles in radians. + * Used in series types such as pie and sunburst. + * + * @private + * @function Highcharts.CenteredSeriesMixin.getStartAndEndRadians + * + * @param {number} [start] + * Start angle in degrees. + * + * @param {number} [end] + * Start angle in degrees. + * + * @return {Highcharts.RadianAngles} + * Returns an object containing start and end angles as radians. + */ + getStartAndEndRadians: function (start, end) { + var startAngle = isNumber(start) ? start : 0, // must be a number + endAngle = ((isNumber(end) && // must be a number + end > startAngle && // must be larger than the start angle + // difference must be less than 360 degrees + (end - startAngle) < 360) ? + end : + startAngle + 360), correction = -90; + return { + start: deg2rad * (startAngle + correction), + end: deg2rad * (endAngle + correction) + }; + } + }; + + }); + _registerModule(_modules, 'parts/PieSeries.js', [_modules['parts/Globals.js'], _modules['mixins/legend-symbol.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js']], function (H, LegendSymbolMixin, Point, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, clamp = U.clamp, defined = U.defined, fireEvent = U.fireEvent, isNumber = U.isNumber, merge = U.merge, pick = U.pick, relativeLength = U.relativeLength, seriesType = U.seriesType, setAnimation = U.setAnimation; + var CenteredSeriesMixin = H.CenteredSeriesMixin, getStartAndEndRadians = CenteredSeriesMixin.getStartAndEndRadians, noop = H.noop, Series = H.Series, seriesTypes = H.seriesTypes; + /** + * Pie series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.pie + * + * @augments Highcharts.Series + */ + seriesType('pie', 'line', + /** + * A pie chart is a circular graphic which is divided into slices to + * illustrate numerical proportion. + * + * @sample highcharts/demo/pie-basic/ + * Pie chart + * + * @extends plotOptions.line + * @excluding animationLimit, boostThreshold, connectEnds, connectNulls, + * cropThreshold, dashStyle, dataSorting, dragDrop, + * findNearestPointBy, getExtremesFromAll, label, lineWidth, + * marker, negativeColor, pointInterval, pointIntervalUnit, + * pointPlacement, pointStart, softThreshold, stacking, step, + * threshold, turboThreshold, zoneAxis, zones, dataSorting + * @product highcharts + * @optionparent plotOptions.pie + */ + { + /** + * @excluding legendItemClick + * @apioption plotOptions.pie.events + */ + /** + * Fires when the checkbox next to the point name in the legend is + * clicked. One parameter, event, is passed to the function. The state + * of the checkbox is found by event.checked. The checked item is found + * by event.item. Return false to prevent the default action which is to + * toggle the select state of the series. + * + * @sample {highcharts} highcharts/plotoptions/series-events-checkboxclick/ + * Alert checkbox status + * + * @type {Function} + * @since 1.2.0 + * @product highcharts + * @context Highcharts.Point + * @apioption plotOptions.pie.events.checkboxClick + */ + /** + * Fires when the legend item belonging to the pie point (slice) is + * clicked. The `this` keyword refers to the point itself. One + * parameter, `event`, is passed to the function, containing common + * event information. The default action is to toggle the visibility of + * the point. This can be prevented by calling `event.preventDefault()`. + * + * @sample {highcharts} highcharts/plotoptions/pie-point-events-legenditemclick/ + * Confirm toggle visibility + * + * @type {Highcharts.PointLegendItemClickCallbackFunction} + * @since 1.2.0 + * @product highcharts + * @apioption plotOptions.pie.point.events.legendItemClick + */ + /** + * The center of the pie chart relative to the plot area. Can be + * percentages or pixel values. The default behaviour (as of 3.0) is to + * center the pie so that all slices and data labels are within the plot + * area. As a consequence, the pie may actually jump around in a chart + * with dynamic values, as the data labels move. In that case, the + * center should be explicitly set, for example to `["50%", "50%"]`. + * + * @sample {highcharts} highcharts/plotoptions/pie-center/ + * Centered at 100, 100 + * + * @type {Array<(number|string|null),(number|string|null)>} + * @default [null, null] + * @product highcharts + * + * @private + */ + center: [null, null], + /** + * The color of the pie series. A pie series is represented as an empty + * circle if the total sum of its values is 0. Use this property to + * define the color of its border. + * + * In styled mode, the color can be defined by the + * [colorIndex](#plotOptions.series.colorIndex) option. Also, the series + * color can be set with the `.highcharts-series`, + * `.highcharts-color-{n}`, `.highcharts-{type}-series` or + * `.highcharts-series-{n}` class, or individual classes given by the + * `className` option. + * + * @sample {highcharts} highcharts/plotoptions/pie-emptyseries/ + * Empty pie series + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #cccccc + * @apioption plotOptions.pie.color + */ + /** + * @product highcharts + * + * @private + */ + clip: false, + /** + * @ignore-option + * + * @private + */ + colorByPoint: true, + /** + * A series specific or series type specific color set to use instead + * of the global [colors](#colors). + * + * @sample {highcharts} highcharts/demo/pie-monochrome/ + * Set default colors for all pies + * + * @type {Array} + * @since 3.0 + * @product highcharts + * @apioption plotOptions.pie.colors + */ + /** + * @declare Highcharts.SeriesPieDataLabelsOptionsObject + * @extends plotOptions.series.dataLabels + * @excluding align, allowOverlap, inside, staggerLines, step + * @private + */ + dataLabels: { + /** + * Alignment method for data labels. Possible values are: + * + * - `toPlotEdges`: Each label touches the nearest vertical edge of + * the plot area. + * + * - `connectors`: Connectors have the same x position and the + * widest label of each half (left & right) touches the nearest + * vertical edge of the plot area. + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-alignto-connectors/ + * alignTo: connectors + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-alignto-plotedges/ + * alignTo: plotEdges + * + * @type {string} + * @since 7.0.0 + * @product highcharts + * @apioption plotOptions.pie.dataLabels.alignTo + */ + allowOverlap: true, + /** + * The color of the line connecting the data label to the pie slice. + * The default color is the same as the point's color. + * + * In styled mode, the connector stroke is given in the + * `.highcharts-data-label-connector` class. + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorcolor/ + * Blue connectors + * @sample {highcharts} highcharts/css/pie-point/ + * Styled connectors + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.1 + * @product highcharts + * @apioption plotOptions.pie.dataLabels.connectorColor + */ + /** + * The distance from the data label to the connector. Note that + * data labels also have a default `padding`, so in order for the + * connector to touch the text, the `padding` must also be 0. + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorpadding/ + * No padding + * + * @since 2.1 + * @product highcharts + */ + connectorPadding: 5, + /** + * Specifies the method that is used to generate the connector path. + * Highcharts provides 3 built-in connector shapes: `'fixedOffset'` + * (default), `'straight'` and `'crookedLine'`. Using + * `'crookedLine'` has the most sense (in most of the cases) when + * `'alignTo'` is set. + * + * Users can provide their own method by passing a function instead + * of a String. 3 arguments are passed to the callback: + * + * - Object that holds the information about the coordinates of the + * label (`x` & `y` properties) and how the label is located in + * relation to the pie (`alignment` property). `alignment` can by + * one of the following: + * `'left'` (pie on the left side of the data label), + * `'right'` (pie on the right side of the data label) or + * `'center'` (data label overlaps the pie). + * + * - Object that holds the information about the position of the + * connector. Its `touchingSliceAt` porperty tells the position + * of the place where the connector touches the slice. + * + * - Data label options + * + * The function has to return an SVG path definition in array form + * (see the example). + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorshape-string/ + * connectorShape is a String + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorshape-function/ + * connectorShape is a function + * + * @type {string|Function} + * @since 7.0.0 + * @product highcharts + */ + connectorShape: 'fixedOffset', + /** + * The width of the line connecting the data label to the pie slice. + * + * In styled mode, the connector stroke width is given in the + * `.highcharts-data-label-connector` class. + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorwidth-disabled/ + * Disable the connector + * @sample {highcharts} highcharts/css/pie-point/ + * Styled connectors + * + * @type {number} + * @default 1 + * @since 2.1 + * @product highcharts + * @apioption plotOptions.pie.dataLabels.connectorWidth + */ + /** + * Works only if `connectorShape` is `'crookedLine'`. It defines how + * far from the vertical plot edge the coonnector path should be + * crooked. + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-crookdistance/ + * crookDistance set to 90% + * + * @since 7.0.0 + * @product highcharts + */ + crookDistance: '70%', + /** + * The distance of the data label from the pie's edge. Negative + * numbers put the data label on top of the pie slices. Can also be + * defined as a percentage of pie's radius. Connectors are only + * shown for data labels outside the pie. + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-distance/ + * Data labels on top of the pie + * + * @type {number|string} + * @since 2.1 + * @product highcharts + */ + distance: 30, + enabled: true, + formatter: function () { + return this.point.isNull ? void 0 : this.point.name; + }, + /** + * Whether to render the connector as a soft arc or a line with + * sharp break. Works only if `connectorShape` equals to + * `fixedOffset`. + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-softconnector-true/ + * Soft + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-softconnector-false/ + * Non soft + * + * @since 2.1.7 + * @product highcharts + */ + softConnector: true, + /** + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow + * Long labels truncated with an ellipsis + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow-wrap + * Long labels are wrapped + * + * @type {Highcharts.CSSObject} + * @apioption plotOptions.pie.dataLabels.style + */ + x: 0 + }, + /** + * If the total sum of the pie's values is 0, the series is represented + * as an empty circle . The `fillColor` option defines the color of that + * circle. Use [pie.borderWidth](#plotOptions.pie.borderWidth) to set + * the border thickness. + * + * @sample {highcharts} highcharts/plotoptions/pie-emptyseries/ + * Empty pie series + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @private + */ + fillColor: void 0, + /** + * The end angle of the pie in degrees where 0 is top and 90 is right. + * Defaults to `startAngle` plus 360. + * + * @sample {highcharts} highcharts/demo/pie-semi-circle/ + * Semi-circle donut + * + * @type {number} + * @since 1.3.6 + * @product highcharts + * @apioption plotOptions.pie.endAngle + */ + /** + * Equivalent to [chart.ignoreHiddenSeries](#chart.ignoreHiddenSeries), + * this option tells whether the series shall be redrawn as if the + * hidden point were `null`. + * + * The default value changed from `false` to `true` with Highcharts + * 3.0. + * + * @sample {highcharts} highcharts/plotoptions/pie-ignorehiddenpoint/ + * True, the hiddden point is ignored + * + * @since 2.3.0 + * @product highcharts + * + * @private + */ + ignoreHiddenPoint: true, + /** + * @ignore-option + * + * @private + */ + inactiveOtherPoints: true, + /** + * The size of the inner diameter for the pie. A size greater than 0 + * renders a donut chart. Can be a percentage or pixel value. + * Percentages are relative to the pie size. Pixel values are given as + * integers. + * + * + * Note: in Highcharts < 4.1.2, the percentage was relative to the plot + * area, not the pie size. + * + * @sample {highcharts} highcharts/plotoptions/pie-innersize-80px/ + * 80px inner size + * @sample {highcharts} highcharts/plotoptions/pie-innersize-50percent/ + * 50% of the plot area + * @sample {highcharts} highcharts/demo/3d-pie-donut/ + * 3D donut + * + * @type {number|string} + * @default 0 + * @since 2.0 + * @product highcharts + * @apioption plotOptions.pie.innerSize + */ + /** + * @ignore-option + * + * @private + */ + legendType: 'point', + /** + * @ignore-option + * + * @private + */ + marker: null, + /** + * The minimum size for a pie in response to auto margins. The pie will + * try to shrink to make room for data labels in side the plot area, + * but only to this size. + * + * @type {number|string} + * @default 80 + * @since 3.0 + * @product highcharts + * @apioption plotOptions.pie.minSize + */ + /** + * The diameter of the pie relative to the plot area. Can be a + * percentage or pixel value. Pixel values are given as integers. The + * default behaviour (as of 3.0) is to scale to the plot area and give + * room for data labels within the plot area. + * [slicedOffset](#plotOptions.pie.slicedOffset) is also included in the + * default size calculation. As a consequence, the size of the pie may + * vary when points are updated and data labels more around. In that + * case it is best to set a fixed value, for example `"75%"`. + * + * @sample {highcharts} highcharts/plotoptions/pie-size/ + * Smaller pie + * + * @type {number|string|null} + * @product highcharts + * + * @private + */ + size: null, + /** + * Whether to display this particular series or series type in the + * legend. Since 2.1, pies are not shown in the legend by default. + * + * @sample {highcharts} highcharts/plotoptions/series-showinlegend/ + * One series in the legend, one hidden + * + * @product highcharts + * + * @private + */ + showInLegend: false, + /** + * If a point is sliced, moved out from the center, how many pixels + * should it be moved?. + * + * @sample {highcharts} highcharts/plotoptions/pie-slicedoffset-20/ + * 20px offset + * + * @product highcharts + * + * @private + */ + slicedOffset: 10, + /** + * The start angle of the pie slices in degrees where 0 is top and 90 + * right. + * + * @sample {highcharts} highcharts/plotoptions/pie-startangle-90/ + * Start from right + * + * @type {number} + * @default 0 + * @since 2.3.4 + * @product highcharts + * @apioption plotOptions.pie.startAngle + */ + /** + * Sticky tracking of mouse events. When true, the `mouseOut` event + * on a series isn't triggered until the mouse moves over another + * series, or out of the plot area. When false, the `mouseOut` event on + * a series is triggered when the mouse leaves the area around the + * series' graph or markers. This also implies the tooltip. When + * `stickyTracking` is false and `tooltip.shared` is false, the tooltip + * will be hidden when moving the mouse between series. + * + * @product highcharts + * + * @private + */ + stickyTracking: false, + tooltip: { + followPointer: true + }, + /** + * The color of the border surrounding each slice. When `null`, the + * border takes the same color as the slice fill. This can be used + * together with a `borderWidth` to fill drawing gaps created by + * antialiazing artefacts in borderless pies. + * + * In styled mode, the border stroke is given in the `.highcharts-point` + * class. + * + * @sample {highcharts} highcharts/plotoptions/pie-bordercolor-black/ + * Black border + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #ffffff + * @product highcharts + * + * @private + */ + borderColor: '#ffffff', + /** + * The width of the border surrounding each slice. + * + * When setting the border width to 0, there may be small gaps between + * the slices due to SVG antialiasing artefacts. To work around this, + * keep the border width at 0.5 or 1, but set the `borderColor` to + * `null` instead. + * + * In styled mode, the border stroke width is given in the + * `.highcharts-point` class. + * + * @sample {highcharts} highcharts/plotoptions/pie-borderwidth/ + * 3px border + * + * @product highcharts + * + * @private + */ + borderWidth: 1, + /** + * @ignore-options + * @private + */ + lineWidth: void 0, + states: { + /** + * @extends plotOptions.series.states.hover + * @excluding marker, lineWidth, lineWidthPlus + * @product highcharts + */ + hover: { + /** + * How much to brighten the point on interaction. Requires the + * main color to be defined in hex or rgb(a) format. + * + * In styled mode, the hover brightness is by default replaced + * by a fill-opacity given in the `.highcharts-point-hover` + * class. + * + * @sample {highcharts} highcharts/plotoptions/pie-states-hover-brightness/ + * Brightened by 0.5 + * + * @product highcharts + */ + brightness: 0.1 + } + } + }, + /* eslint-disable valid-jsdoc */ + /** + * @lends seriesTypes.pie.prototype + */ + { + isCartesian: false, + requireSorting: false, + directTouch: true, + noSharedTooltip: true, + trackerGroups: ['group', 'dataLabelsGroup'], + axisTypes: [], + pointAttribs: seriesTypes.column.prototype.pointAttribs, + /** + * Animate the pies in + * + * @private + * @function Highcharts.seriesTypes.pie#animate + * + * @param {boolean} [init=false] + */ + animate: function (init) { + var series = this, points = series.points, startAngleRad = series.startAngleRad; + if (!init) { + points.forEach(function (point) { + var graphic = point.graphic, args = point.shapeArgs; + if (graphic && args) { + // start values + graphic.attr({ + // animate from inner radius (#779) + r: pick(point.startR, (series.center && series.center[3] / 2)), + start: startAngleRad, + end: startAngleRad + }); + // animate + graphic.animate({ + r: args.r, + start: args.start, + end: args.end + }, series.options.animation); + } + }); + } + }, + // Define hasData function for non-cartesian series. + // Returns true if the series has points at all. + hasData: function () { + return !!this.processedXData.length; // != 0 + }, + /** + * Recompute total chart sum and update percentages of points. + * + * @private + * @function Highcharts.seriesTypes.pie#updateTotals + * @return {void} + */ + updateTotals: function () { + var i, total = 0, points = this.points, len = points.length, point, ignoreHiddenPoint = this.options.ignoreHiddenPoint; + // Get the total sum + for (i = 0; i < len; i++) { + point = points[i]; + total += (ignoreHiddenPoint && !point.visible) ? + 0 : + point.isNull ? + 0 : + point.y; + } + this.total = total; + // Set each point's properties + for (i = 0; i < len; i++) { + point = points[i]; + point.percentage = + (total > 0 && (point.visible || !ignoreHiddenPoint)) ? + point.y / total * 100 : + 0; + point.total = total; + } + }, + /** + * Extend the generatePoints method by adding total and percentage + * properties to each point + * + * @private + * @function Highcharts.seriesTypes.pie#generatePoints + * @return {void} + */ + generatePoints: function () { + Series.prototype.generatePoints.call(this); + this.updateTotals(); + }, + /** + * Utility for getting the x value from a given y, used for + * anticollision logic in data labels. Added point for using specific + * points' label distance. + * @private + */ + getX: function (y, left, point) { + var center = this.center, + // Variable pie has individual radius + radius = this.radii ? + this.radii[point.index] : + center[2] / 2, angle, x; + angle = Math.asin(clamp((y - center[1]) / (radius + point.labelDistance), -1, 1)); + x = center[0] + + (left ? -1 : 1) * + (Math.cos(angle) * (radius + point.labelDistance)) + + (point.labelDistance > 0 ? + (left ? -1 : 1) * this.options.dataLabels.padding : + 0); + return x; + }, + /** + * Do translation for pie slices + * + * @private + * @function Highcharts.seriesTypes.pie#translate + * @param {Array} [positions] + * @return {void} + */ + translate: function (positions) { + this.generatePoints(); + var series = this, cumulative = 0, precision = 1000, // issue #172 + options = series.options, slicedOffset = options.slicedOffset, connectorOffset = slicedOffset + (options.borderWidth || 0), finalConnectorOffset, start, end, angle, radians = getStartAndEndRadians(options.startAngle, options.endAngle), startAngleRad = series.startAngleRad = radians.start, endAngleRad = series.endAngleRad = radians.end, circ = endAngleRad - startAngleRad, // 2 * Math.PI, + points = series.points, + // the x component of the radius vector for a given point + radiusX, radiusY, labelDistance = options.dataLabels.distance, ignoreHiddenPoint = options.ignoreHiddenPoint, i, len = points.length, point; + // Get positions - either an integer or a percentage string must be + // given. If positions are passed as a parameter, we're in a + // recursive loop for adjusting space for data labels. + if (!positions) { + series.center = positions = series.getCenter(); + } + // Calculate the geometry for each point + for (i = 0; i < len; i++) { + point = points[i]; + // set start and end angle + start = startAngleRad + (cumulative * circ); + if (!ignoreHiddenPoint || point.visible) { + cumulative += point.percentage / 100; + } + end = startAngleRad + (cumulative * circ); + // set the shape + point.shapeType = 'arc'; + point.shapeArgs = { + x: positions[0], + y: positions[1], + r: positions[2] / 2, + innerR: positions[3] / 2, + start: Math.round(start * precision) / precision, + end: Math.round(end * precision) / precision + }; + // Used for distance calculation for specific point. + point.labelDistance = pick((point.options.dataLabels && + point.options.dataLabels.distance), labelDistance); + // Compute point.labelDistance if it's defined as percentage + // of slice radius (#8854) + point.labelDistance = relativeLength(point.labelDistance, point.shapeArgs.r); + // Saved for later dataLabels distance calculation. + series.maxLabelDistance = Math.max(series.maxLabelDistance || 0, point.labelDistance); + // The angle must stay within -90 and 270 (#2645) + angle = (end + start) / 2; + if (angle > 1.5 * Math.PI) { + angle -= 2 * Math.PI; + } + else if (angle < -Math.PI / 2) { + angle += 2 * Math.PI; + } + // Center for the sliced out slice + point.slicedTranslation = { + translateX: Math.round(Math.cos(angle) * slicedOffset), + translateY: Math.round(Math.sin(angle) * slicedOffset) + }; + // set the anchor point for tooltips + radiusX = Math.cos(angle) * positions[2] / 2; + radiusY = Math.sin(angle) * positions[2] / 2; + point.tooltipPos = [ + positions[0] + radiusX * 0.7, + positions[1] + radiusY * 0.7 + ]; + point.half = angle < -Math.PI / 2 || angle > Math.PI / 2 ? + 1 : + 0; + point.angle = angle; + // Set the anchor point for data labels. Use point.labelDistance + // instead of labelDistance // #1174 + // finalConnectorOffset - not override connectorOffset value. + finalConnectorOffset = Math.min(connectorOffset, point.labelDistance / 5); // #1678 + point.labelPosition = { + natural: { + // initial position of the data label - it's utilized for + // finding the final position for the label + x: positions[0] + radiusX + Math.cos(angle) * + point.labelDistance, + y: positions[1] + radiusY + Math.sin(angle) * + point.labelDistance + }, + 'final': { + // used for generating connector path - + // initialized later in drawDataLabels function + // x: undefined, + // y: undefined + }, + // left - pie on the left side of the data label + // right - pie on the right side of the data label + // center - data label overlaps the pie + alignment: point.labelDistance < 0 ? + 'center' : point.half ? 'right' : 'left', + connectorPosition: { + breakAt: { + x: positions[0] + radiusX + Math.cos(angle) * + finalConnectorOffset, + y: positions[1] + radiusY + Math.sin(angle) * + finalConnectorOffset + }, + touchingSliceAt: { + x: positions[0] + radiusX, + y: positions[1] + radiusY + } + } + }; + } + fireEvent(series, 'afterTranslate'); + }, + /** + * Called internally to draw auxiliary graph in pie-like series in + * situtation when the default graph is not sufficient enough to present + * the data well. Auxiliary graph is saved in the same object as + * regular graph. + * + * @private + * @function Highcharts.seriesTypes.pie#drawEmpty + */ + drawEmpty: function () { + var centerX, centerY, options = this.options; + // Draw auxiliary graph if there're no visible points. + if (this.total === 0) { + centerX = this.center[0]; + centerY = this.center[1]; + if (!this.graph) { // Auxiliary graph doesn't exist yet. + this.graph = this.chart.renderer.circle(centerX, centerY, 0) + .addClass('highcharts-graph') + .add(this.group); + } + this.graph.animate({ + 'stroke-width': options.borderWidth, + cx: centerX, + cy: centerY, + r: this.center[2] / 2, + fill: options.fillColor || 'none', + stroke: options.color || + '#cccccc' + }, this.options.animation); + } + else if (this.graph) { // Destroy the graph object. + this.graph = this.graph.destroy(); + } + }, + /** + * Draw the data points + * + * @private + * @function Highcharts.seriesTypes.pie#drawPoints + * @return {void} + */ + redrawPoints: function () { + var series = this, chart = series.chart, renderer = chart.renderer, groupTranslation, graphic, pointAttr, shapeArgs, shadow = series.options.shadow; + this.drawEmpty(); + if (shadow && !series.shadowGroup && !chart.styledMode) { + series.shadowGroup = renderer.g('shadow') + .attr({ zIndex: -1 }) + .add(series.group); + } + // draw the slices + series.points.forEach(function (point) { + var animateTo = {}; + graphic = point.graphic; + if (!point.isNull && graphic) { + shapeArgs = point.shapeArgs; + // If the point is sliced, use special translation, else use + // plot area translation + groupTranslation = point.getTranslate(); + if (!chart.styledMode) { + // Put the shadow behind all points + var shadowGroup = point.shadowGroup; + if (shadow && !shadowGroup) { + shadowGroup = point.shadowGroup = renderer + .g('shadow') + .add(series.shadowGroup); + } + if (shadowGroup) { + shadowGroup.attr(groupTranslation); + } + pointAttr = series.pointAttribs(point, (point.selected && 'select')); + } + // Draw the slice + if (!point.delayedRendering) { + graphic + .setRadialReference(series.center); + if (!chart.styledMode) { + merge(true, animateTo, pointAttr); + } + merge(true, animateTo, shapeArgs, groupTranslation); + graphic.animate(animateTo); + } + else { + graphic + .setRadialReference(series.center) + .attr(shapeArgs) + .attr(groupTranslation); + if (!chart.styledMode) { + graphic + .attr(pointAttr) + .attr({ 'stroke-linejoin': 'round' }) + .shadow(shadow, shadowGroup); + } + point.delayedRendering = false; + } + graphic.attr({ + visibility: point.visible ? 'inherit' : 'hidden' + }); + graphic.addClass(point.getClassName()); + } + else if (graphic) { + point.graphic = graphic.destroy(); + } + }); + }, + /** + * Slices in pie chart are initialized in DOM, but it's shapes and + * animations are normally run in `drawPoints()`. + * @private + */ + drawPoints: function () { + var renderer = this.chart.renderer; + this.points.forEach(function (point) { + // When updating a series between 2d and 3d or cartesian and + // polar, the shape type changes. + if (point.graphic && point.hasNewShapeType()) { + point.graphic = point.graphic.destroy(); + } + if (!point.graphic) { + point.graphic = renderer[point.shapeType](point.shapeArgs) + .add(point.series.group); + point.delayedRendering = true; + } + }); + }, + /** + * @private + * @deprecated + * @function Highcharts.seriesTypes.pie#searchPoint + */ + searchPoint: noop, + /** + * Utility for sorting data labels + * + * @private + * @function Highcharts.seriesTypes.pie#sortByAngle + * @param {Array} points + * @param {number} sign + * @return {void} + */ + sortByAngle: function (points, sign) { + points.sort(function (a, b) { + return ((typeof a.angle !== 'undefined') && + (b.angle - a.angle) * sign); + }); + }, + /** + * Use a simple symbol from LegendSymbolMixin. + * + * @private + * @borrows Highcharts.LegendSymbolMixin.drawRectangle as Highcharts.seriesTypes.pie#drawLegendSymbol + */ + drawLegendSymbol: LegendSymbolMixin.drawRectangle, + /** + * Use the getCenter method from drawLegendSymbol. + * + * @private + * @borrows Highcharts.CenteredSeriesMixin.getCenter as Highcharts.seriesTypes.pie#getCenter + */ + getCenter: CenteredSeriesMixin.getCenter, + /** + * Pies don't have point marker symbols. + * + * @deprecated + * @private + * @function Highcharts.seriesTypes.pie#getSymbol + */ + getSymbol: noop, + /** + * @private + * @type {null} + */ + drawGraph: null + }, + /** + * @lends seriesTypes.pie.prototype.pointClass.prototype + */ + { + /** + * Initialize the pie slice + * + * @private + * @function Highcharts.seriesTypes.pie#pointClass#init + * @return {Highcharts.Point} + */ + init: function () { + Point.prototype.init.apply(this, arguments); + var point = this, toggleSlice; + point.name = pick(point.name, 'Slice'); + // add event listener for select + toggleSlice = function (e) { + point.slice(e.type === 'select'); + }; + addEvent(point, 'select', toggleSlice); + addEvent(point, 'unselect', toggleSlice); + return point; + }, + /** + * Negative points are not valid (#1530, #3623, #5322) + * + * @private + * @function Highcharts.seriesTypes.pie#pointClass#isValid + * @return {boolean} + */ + isValid: function () { + return isNumber(this.y) && this.y >= 0; + }, + /** + * Toggle the visibility of the pie slice + * + * @private + * @function Highcharts.seriesTypes.pie#pointClass#setVisible + * @param {boolean} vis + * Whether to show the slice or not. If undefined, the visibility + * is toggled. + * @param {boolean} [redraw=false] + * @return {void} + */ + setVisible: function (vis, redraw) { + var point = this, series = point.series, chart = series.chart, ignoreHiddenPoint = series.options.ignoreHiddenPoint; + redraw = pick(redraw, ignoreHiddenPoint); + if (vis !== point.visible) { + // If called without an argument, toggle visibility + point.visible = point.options.visible = vis = + typeof vis === 'undefined' ? !point.visible : vis; + // update userOptions.data + series.options.data[series.data.indexOf(point)] = + point.options; + // Show and hide associated elements. This is performed + // regardless of redraw or not, because chart.redraw only + // handles full series. + ['graphic', 'dataLabel', 'connector', 'shadowGroup'].forEach(function (key) { + if (point[key]) { + point[key][vis ? 'show' : 'hide'](true); + } + }); + if (point.legendItem) { + chart.legend.colorizeItem(point, vis); + } + // #4170, hide halo after hiding point + if (!vis && point.state === 'hover') { + point.setState(''); + } + // Handle ignore hidden slices + if (ignoreHiddenPoint) { + series.isDirty = true; + } + if (redraw) { + chart.redraw(); + } + } + }, + /** + * Set or toggle whether the slice is cut out from the pie + * + * @private + * @function Highcharts.seriesTypes.pie#pointClass#slice + * @param {boolean} sliced + * When undefined, the slice state is toggled. + * @param {boolean} redraw + * Whether to redraw the chart. True by default. + * @param {boolean|Highcharts.AnimationOptionsObject} + * Animation options. + * @return {void} + */ + slice: function (sliced, redraw, animation) { + var point = this, series = point.series, chart = series.chart; + setAnimation(animation, chart); + // redraw is true by default + redraw = pick(redraw, true); + /** + * Pie series only. Whether to display a slice offset from the + * center. + * @name Highcharts.Point#sliced + * @type {boolean|undefined} + */ + // if called without an argument, toggle + point.sliced = point.options.sliced = sliced = + defined(sliced) ? sliced : !point.sliced; + // update userOptions.data + series.options.data[series.data.indexOf(point)] = + point.options; + if (point.graphic) { + point.graphic.animate(this.getTranslate()); + } + if (point.shadowGroup) { + point.shadowGroup.animate(this.getTranslate()); + } + }, + /** + * @private + * @function Highcharts.seriesTypes.pie#pointClass#getTranslate + * @return {Highcharts.TranslationAttributes} + */ + getTranslate: function () { + return this.sliced ? this.slicedTranslation : { + translateX: 0, + translateY: 0 + }; + }, + /** + * @private + * @function Highcharts.seriesTypes.pie#pointClass#haloPath + * @param {number} size + * @return {Highcharts.SVGPathArray} + */ + haloPath: function (size) { + var shapeArgs = this.shapeArgs; + return this.sliced || !this.visible ? + [] : + this.series.chart.renderer.symbols.arc(shapeArgs.x, shapeArgs.y, shapeArgs.r + size, shapeArgs.r + size, { + // Substract 1px to ensure the background is not bleeding + // through between the halo and the slice (#7495). + innerR: shapeArgs.r - 1, + start: shapeArgs.start, + end: shapeArgs.end + }); + }, + connectorShapes: { + // only one available before v7.0.0 + fixedOffset: function (labelPosition, connectorPosition, options) { + var breakAt = connectorPosition.breakAt, touchingSliceAt = connectorPosition.touchingSliceAt, lineSegment = options.softConnector ? [ + 'C', + // 1st control point (of the curve) + labelPosition.x + + // 5 gives the connector a little horizontal bend + (labelPosition.alignment === 'left' ? -5 : 5), + labelPosition.y, + 2 * breakAt.x - touchingSliceAt.x, + 2 * breakAt.y - touchingSliceAt.y, + breakAt.x, + breakAt.y // + ] : [ + 'L', + breakAt.x, + breakAt.y + ]; + // assemble the path + return ([ + ['M', labelPosition.x, labelPosition.y], + lineSegment, + ['L', touchingSliceAt.x, touchingSliceAt.y] + ]); + }, + straight: function (labelPosition, connectorPosition) { + var touchingSliceAt = connectorPosition.touchingSliceAt; + // direct line to the slice + return [ + ['M', labelPosition.x, labelPosition.y], + ['L', touchingSliceAt.x, touchingSliceAt.y] + ]; + }, + crookedLine: function (labelPosition, connectorPosition, options) { + var touchingSliceAt = connectorPosition.touchingSliceAt, series = this.series, pieCenterX = series.center[0], plotWidth = series.chart.plotWidth, plotLeft = series.chart.plotLeft, alignment = labelPosition.alignment, radius = this.shapeArgs.r, crookDistance = relativeLength(// % to fraction + options.crookDistance, 1), crookX = alignment === 'left' ? + pieCenterX + radius + (plotWidth + plotLeft - + pieCenterX - radius) * (1 - crookDistance) : + plotLeft + (pieCenterX - radius) * crookDistance, segmentWithCrook = [ + 'L', + crookX, + labelPosition.y + ], useCrook = true; + // crookedLine formula doesn't make sense if the path overlaps + // the label - use straight line instead in that case + if (alignment === 'left' ? + (crookX > labelPosition.x || crookX < touchingSliceAt.x) : + (crookX < labelPosition.x || crookX > touchingSliceAt.x)) { + useCrook = false; + } + // assemble the path + var path = [ + ['M', labelPosition.x, labelPosition.y] + ]; + if (useCrook) { + path.push(segmentWithCrook); + } + path.push(['L', touchingSliceAt.x, touchingSliceAt.y]); + return path; + } + }, + /** + * Extendable method for getting the path of the connector between the + * data label and the pie slice. + */ + getConnectorPath: function () { + var labelPosition = this.labelPosition, options = this.series.options.dataLabels, connectorShape = options.connectorShape, predefinedShapes = this.connectorShapes; + // find out whether to use the predefined shape + if (predefinedShapes[connectorShape]) { + connectorShape = predefinedShapes[connectorShape]; + } + return connectorShape.call(this, { + // pass simplified label position object for user's convenience + x: labelPosition.final.x, + y: labelPosition.final.y, + alignment: labelPosition.alignment + }, labelPosition.connectorPosition, options); + } + } + /* eslint-enable valid-jsdoc */ + ); + /** + * A `pie` series. If the [type](#series.pie.type) option is not specified, + * it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.pie + * @excluding dataParser, dataURL, stack, xAxis, yAxis, dataSorting, step + * @product highcharts + * @apioption series.pie + */ + /** + * An array of data points for the series. For the `pie` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.pie.turboThreshold), + * this option is not available. + * ```js + * data: [{ + * y: 1, + * name: "Point2", + * color: "#00FF00" + * }, { + * y: 7, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @excluding marker, x + * @product highcharts + * @apioption series.pie.data + */ + /** + * @type {Highcharts.SeriesPieDataLabelsOptionsObject} + * @product highcharts + * @apioption series.pie.data.dataLabels + */ + /** + * The sequential index of the data point in the legend. + * + * @type {number} + * @product highcharts + * @apioption series.pie.data.legendIndex + */ + /** + * Whether to display a slice offset from the center. + * + * @sample {highcharts} highcharts/point/sliced/ + * One sliced point + * + * @type {boolean} + * @product highcharts + * @apioption series.pie.data.sliced + */ + /** + * @excluding legendItemClick + * @product highcharts + * @apioption series.pie.events + */ + ''; // placeholder for transpiled doclets above + + }); + _registerModule(_modules, 'parts/DataLabels.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Callback JavaScript function to format the data label as a string. Note that + * if a `format` is defined, the format takes precedence and the formatter is + * ignored. + * + * @callback Highcharts.DataLabelsFormatterCallbackFunction + * + * @param {Highcharts.PointLabelObject} this + * Data label context to format + * + * @param {Highcharts.DataLabelsOptions} options + * [API options](/highcharts/plotOptions.series.dataLabels) of the data label + * + * @return {number|string|null|undefined} + * Formatted data label text + */ + /** + * Values for handling data labels that flow outside the plot area. + * + * @typedef {"allow"|"justify"} Highcharts.DataLabelsOverflowValue + */ + var animObject = U.animObject, arrayMax = U.arrayMax, clamp = U.clamp, defined = U.defined, extend = U.extend, fireEvent = U.fireEvent, format = U.format, isArray = U.isArray, merge = U.merge, objectEach = U.objectEach, pick = U.pick, relativeLength = U.relativeLength, splat = U.splat, stableSort = U.stableSort; + var noop = H.noop, Series = H.Series, seriesTypes = H.seriesTypes; + /* eslint-disable valid-jsdoc */ + /** + * General distribution algorithm for distributing labels of differing size + * along a confined length in two dimensions. The algorithm takes an array of + * objects containing a size, a target and a rank. It will place the labels as + * close as possible to their targets, skipping the lowest ranked labels if + * necessary. + * + * @private + * @function Highcharts.distribute + * @param {Highcharts.DataLabelsBoxArray} boxes + * @param {number} len + * @param {number} [maxDistance] + * @return {void} + */ + H.distribute = function (boxes, len, maxDistance) { + var i, overlapping = true, origBoxes = boxes, // Original array will be altered with added .pos + restBoxes = [], // The outranked overshoot + box, target, total = 0, reducedLen = origBoxes.reducedLen || len; + /** + * @private + */ + function sortByTarget(a, b) { + return a.target - b.target; + } + // If the total size exceeds the len, remove those boxes with the lowest + // rank + i = boxes.length; + while (i--) { + total += boxes[i].size; + } + // Sort by rank, then slice away overshoot + if (total > reducedLen) { + stableSort(boxes, function (a, b) { + return (b.rank || 0) - (a.rank || 0); + }); + i = 0; + total = 0; + while (total <= reducedLen) { + total += boxes[i].size; + i++; + } + restBoxes = boxes.splice(i - 1, boxes.length); + } + // Order by target + stableSort(boxes, sortByTarget); + // So far we have been mutating the original array. Now + // create a copy with target arrays + boxes = boxes.map(function (box) { + return { + size: box.size, + targets: [box.target], + align: pick(box.align, 0.5) + }; + }); + while (overlapping) { + // Initial positions: target centered in box + i = boxes.length; + while (i--) { + box = boxes[i]; + // Composite box, average of targets + target = (Math.min.apply(0, box.targets) + + Math.max.apply(0, box.targets)) / 2; + box.pos = clamp(target - box.size * box.align, 0, len - box.size); + } + // Detect overlap and join boxes + i = boxes.length; + overlapping = false; + while (i--) { + // Overlap + if (i > 0 && + boxes[i - 1].pos + boxes[i - 1].size > + boxes[i].pos) { + // Add this size to the previous box + boxes[i - 1].size += boxes[i].size; + boxes[i - 1].targets = boxes[i - 1] + .targets + .concat(boxes[i].targets); + boxes[i - 1].align = 0.5; + // Overlapping right, push left + if (boxes[i - 1].pos + boxes[i - 1].size > len) { + boxes[i - 1].pos = len - boxes[i - 1].size; + } + boxes.splice(i, 1); // Remove this item + overlapping = true; + } + } + } + // Add the rest (hidden boxes) + origBoxes.push.apply(origBoxes, restBoxes); + // Now the composite boxes are placed, we need to put the original boxes + // within them + i = 0; + boxes.some(function (box) { + var posInCompositeBox = 0; + if (box.targets.some(function () { + origBoxes[i].pos = box.pos + posInCompositeBox; + // If the distance between the position and the target exceeds + // maxDistance, abort the loop and decrease the length in increments + // of 10% to recursively reduce the number of visible boxes by + // rank. Once all boxes are within the maxDistance, we're good. + if (typeof maxDistance !== 'undefined' && + Math.abs(origBoxes[i].pos - origBoxes[i].target) > maxDistance) { + // Reset the positions that are already set + origBoxes.slice(0, i + 1).forEach(function (box) { + delete box.pos; + }); + // Try with a smaller length + origBoxes.reducedLen = + (origBoxes.reducedLen || len) - (len * 0.1); + // Recurse + if (origBoxes.reducedLen > len * 0.1) { + H.distribute(origBoxes, len, maxDistance); + } + // Exceeded maxDistance => abort + return true; + } + posInCompositeBox += origBoxes[i].size; + i++; + })) { + // Exceeded maxDistance => abort + return true; + } + }); + // Add the rest (hidden) boxes and sort by target + stableSort(origBoxes, sortByTarget); + }; + /** + * Draw the data labels + * + * @private + * @function Highcharts.Series#drawDataLabels + * @return {void} + * @fires Highcharts.Series#event:afterDrawDataLabels + */ + Series.prototype.drawDataLabels = function () { + var series = this, chart = series.chart, seriesOptions = series.options, seriesDlOptions = seriesOptions.dataLabels, points = series.points, pointOptions, hasRendered = series.hasRendered || 0, dataLabelsGroup, seriesAnimDuration = animObject(seriesOptions.animation).duration, fadeInDuration = Math.min(seriesAnimDuration, 200), defer = !chart.renderer.forExport && pick(seriesDlOptions.defer, fadeInDuration > 0), renderer = chart.renderer; + /** + * Handle the dataLabels.filter option. + * @private + */ + function applyFilter(point, options) { + var filter = options.filter, op, prop, val; + if (filter) { + op = filter.operator; + prop = point[filter.property]; + val = filter.value; + if ((op === '>' && prop > val) || + (op === '<' && prop < val) || + (op === '>=' && prop >= val) || + (op === '<=' && prop <= val) || + (op === '==' && prop == val) || // eslint-disable-line eqeqeq + (op === '===' && prop === val)) { + return true; + } + return false; + } + return true; + } + /** + * Merge two objects that can be arrays. If one of them is an array, the + * other is merged into each element. If both are arrays, each element is + * merged by index. If neither are arrays, we use normal merge. + * @private + */ + function mergeArrays(one, two) { + var res = [], i; + if (isArray(one) && !isArray(two)) { + res = one.map(function (el) { + return merge(el, two); + }); + } + else if (isArray(two) && !isArray(one)) { + res = two.map(function (el) { + return merge(one, el); + }); + } + else if (!isArray(one) && !isArray(two)) { + res = merge(one, two); + } + else { + i = Math.max(one.length, two.length); + while (i--) { + res[i] = merge(one[i], two[i]); + } + } + return res; + } + // Merge in plotOptions.dataLabels for series + seriesDlOptions = mergeArrays(mergeArrays(chart.options.plotOptions && + chart.options.plotOptions.series && + chart.options.plotOptions.series.dataLabels, chart.options.plotOptions && + chart.options.plotOptions[series.type] && + chart.options.plotOptions[series.type].dataLabels), seriesDlOptions); + fireEvent(this, 'drawDataLabels'); + if (isArray(seriesDlOptions) || + seriesDlOptions.enabled || + series._hasPointLabels) { + // Create a separate group for the data labels to avoid rotation + dataLabelsGroup = series.plotGroup('dataLabelsGroup', 'data-labels', defer && !hasRendered ? 'hidden' : 'inherit', // #5133, #10220 + seriesDlOptions.zIndex || 6); + if (defer) { + dataLabelsGroup.attr({ opacity: +hasRendered }); // #3300 + if (!hasRendered) { + setTimeout(function () { + var group = series.dataLabelsGroup; + if (group) { + if (series.visible) { // #2597, #3023, #3024 + dataLabelsGroup.show(true); + } + group[seriesOptions.animation ? 'animate' : 'attr']({ opacity: 1 }, { duration: fadeInDuration }); + } + }, seriesAnimDuration - fadeInDuration); + } + } + // Make the labels for each point + points.forEach(function (point) { + // Merge in series options for the point. + // @note dataLabelAttribs (like pointAttribs) would eradicate + // the need for dlOptions, and simplify the section below. + pointOptions = splat(mergeArrays(seriesDlOptions, point.dlOptions || // dlOptions is used in treemaps + (point.options && point.options.dataLabels))); + // Handle each individual data label for this point + pointOptions.forEach(function (labelOptions, i) { + // Options for one datalabel + var labelEnabled = (labelOptions.enabled && + // #2282, #4641, #7112, #10049 + (!point.isNull || point.dataLabelOnNull) && + applyFilter(point, labelOptions)), labelConfig, formatString, labelText, style, rotation, attr, dataLabel = point.dataLabels ? point.dataLabels[i] : + point.dataLabel, connector = point.connectors ? point.connectors[i] : + point.connector, labelDistance = pick(labelOptions.distance, point.labelDistance), isNew = !dataLabel; + if (labelEnabled) { + // Create individual options structure that can be extended + // without affecting others + labelConfig = point.getLabelConfig(); + formatString = pick(labelOptions[point.formatPrefix + 'Format'], labelOptions.format); + labelText = defined(formatString) ? + format(formatString, labelConfig, chart) : + (labelOptions[point.formatPrefix + 'Formatter'] || + labelOptions.formatter).call(labelConfig, labelOptions); + style = labelOptions.style; + rotation = labelOptions.rotation; + if (!chart.styledMode) { + // Determine the color + style.color = pick(labelOptions.color, style.color, series.color, '#000000'); + // Get automated contrast color + if (style.color === 'contrast') { + point.contrastColor = renderer.getContrast((point.color || series.color)); + style.color = (!defined(labelDistance) && + labelOptions.inside) || + labelDistance < 0 || + !!seriesOptions.stacking ? + point.contrastColor : + '#000000'; + } + else { + delete point.contrastColor; + } + if (seriesOptions.cursor) { + style.cursor = seriesOptions.cursor; + } + } + attr = { + r: labelOptions.borderRadius || 0, + rotation: rotation, + padding: labelOptions.padding, + zIndex: 1 + }; + if (!chart.styledMode) { + attr.fill = labelOptions.backgroundColor; + attr.stroke = labelOptions.borderColor; + attr['stroke-width'] = labelOptions.borderWidth; + } + // Remove unused attributes (#947) + objectEach(attr, function (val, name) { + if (typeof val === 'undefined') { + delete attr[name]; + } + }); + } + // If the point is outside the plot area, destroy it. #678, #820 + if (dataLabel && (!labelEnabled || !defined(labelText))) { + point.dataLabel = + point.dataLabel && point.dataLabel.destroy(); + if (point.dataLabels) { + // Remove point.dataLabels if this was the last one + if (point.dataLabels.length === 1) { + delete point.dataLabels; + } + else { + delete point.dataLabels[i]; + } + } + if (!i) { + delete point.dataLabel; + } + if (connector) { + point.connector = point.connector.destroy(); + if (point.connectors) { + // Remove point.connectors if this was the last one + if (point.connectors.length === 1) { + delete point.connectors; + } + else { + delete point.connectors[i]; + } + } + } + // Individual labels are disabled if the are explicitly disabled + // in the point options, or if they fall outside the plot area. + } + else if (labelEnabled && defined(labelText)) { + if (!dataLabel) { + // Create new label element + point.dataLabels = point.dataLabels || []; + dataLabel = point.dataLabels[i] = rotation ? + // Labels don't rotate, use text element + renderer.text(labelText, 0, -9999, labelOptions.useHTML) + .addClass('highcharts-data-label') : + // We can use label + renderer.label(labelText, 0, -9999, labelOptions.shape, null, null, labelOptions.useHTML, null, 'data-label'); + // Store for backwards compatibility + if (!i) { + point.dataLabel = dataLabel; + } + dataLabel.addClass(' highcharts-data-label-color-' + point.colorIndex + + ' ' + (labelOptions.className || '') + + ( // #3398 + labelOptions.useHTML ? + ' highcharts-tracker' : + '')); + } + else { + // Use old element and just update text + attr.text = labelText; + } + // Store data label options for later access + dataLabel.options = labelOptions; + dataLabel.attr(attr); + if (!chart.styledMode) { + // Styles must be applied before add in order to read + // text bounding box + dataLabel.css(style).shadow(labelOptions.shadow); + } + if (!dataLabel.added) { + dataLabel.add(dataLabelsGroup); + } + if (labelOptions.textPath && !labelOptions.useHTML) { + dataLabel.setTextPath((point.getDataLabelPath && + point.getDataLabelPath(dataLabel)) || point.graphic, labelOptions.textPath); + if (point.dataLabelPath && + !labelOptions.textPath.enabled) { + // clean the DOM + point.dataLabelPath = point.dataLabelPath.destroy(); + } + } + // Now the data label is created and placed at 0,0, so we + // need to align it + series.alignDataLabel(point, dataLabel, labelOptions, null, isNew); + } + }); + }); + } + fireEvent(this, 'afterDrawDataLabels'); + }; + /** + * Align each individual data label. + * + * @private + * @function Highcharts.Series#alignDataLabel + * @param {Highcharts.Point} point + * @param {Highcharts.SVGElement} dataLabel + * @param {Highcharts.DataLabelsOptions} options + * @param {Highcharts.BBoxObject} alignTo + * @param {boolean} [isNew] + * @return {void} + */ + Series.prototype.alignDataLabel = function (point, dataLabel, options, alignTo, isNew) { + var series = this, chart = this.chart, inverted = this.isCartesian && chart.inverted, enabledDataSorting = this.enabledDataSorting, plotX = pick(point.dlBox && point.dlBox.centerX, point.plotX, -9999), plotY = pick(point.plotY, -9999), bBox = dataLabel.getBBox(), baseline, rotation = options.rotation, normRotation, negRotation, align = options.align, rotCorr, // rotation correction + isInsidePlot = chart.isInsidePlot(plotX, Math.round(plotY), inverted), + // Math.round for rounding errors (#2683), alignTo to allow column + // labels (#2700) + alignAttr, // the final position; + justify = pick(options.overflow, (enabledDataSorting ? 'none' : 'justify')) === 'justify', visible = this.visible && + point.visible !== false && + (point.series.forceDL || + (enabledDataSorting && !justify) || + isInsidePlot || + ( + // If the data label is inside the align box, it is enough + // that parts of the align box is inside the plot area + // (#12370) + options.inside && alignTo && chart.isInsidePlot(plotX, inverted ? + alignTo.x + 1 : + alignTo.y + alignTo.height - 1, inverted))), setStartPos = function (alignOptions) { + if (enabledDataSorting && series.xAxis && !justify) { + series.setDataLabelStartPos(point, dataLabel, isNew, isInsidePlot, alignOptions); + } + }; + if (visible) { + baseline = chart.renderer.fontMetrics(chart.styledMode ? void 0 : options.style.fontSize, dataLabel).b; + // The alignment box is a singular point + alignTo = extend({ + x: inverted ? this.yAxis.len - plotY : plotX, + y: Math.round(inverted ? this.xAxis.len - plotX : plotY), + width: 0, + height: 0 + }, alignTo); + // Add the text size for alignment calculation + extend(options, { + width: bBox.width, + height: bBox.height + }); + // Allow a hook for changing alignment in the last moment, then do the + // alignment + if (rotation) { + justify = false; // Not supported for rotated text + rotCorr = chart.renderer.rotCorr(baseline, rotation); // #3723 + alignAttr = { + x: (alignTo.x + + options.x + + alignTo.width / 2 + + rotCorr.x), + y: (alignTo.y + + options.y + + { top: 0, middle: 0.5, bottom: 1 }[options.verticalAlign] * + alignTo.height) + }; + setStartPos(alignAttr); // data sorting + dataLabel[isNew ? 'attr' : 'animate'](alignAttr) + .attr({ + align: align + }); + // Compensate for the rotated label sticking out on the sides + normRotation = (rotation + 720) % 360; + negRotation = normRotation > 180 && normRotation < 360; + if (align === 'left') { + alignAttr.y -= negRotation ? bBox.height : 0; + } + else if (align === 'center') { + alignAttr.x -= bBox.width / 2; + alignAttr.y -= bBox.height / 2; + } + else if (align === 'right') { + alignAttr.x -= bBox.width; + alignAttr.y -= negRotation ? 0 : bBox.height; + } + dataLabel.placed = true; + dataLabel.alignAttr = alignAttr; + } + else { + setStartPos(alignTo); // data sorting + dataLabel.align(options, null, alignTo); + alignAttr = dataLabel.alignAttr; + } + // Handle justify or crop + if (justify && alignTo.height >= 0) { // #8830 + this.justifyDataLabel(dataLabel, options, alignAttr, bBox, alignTo, isNew); + // Now check that the data label is within the plot area + } + else if (pick(options.crop, true)) { + visible = + chart.isInsidePlot(alignAttr.x, alignAttr.y) && + chart.isInsidePlot(alignAttr.x + bBox.width, alignAttr.y + bBox.height); + } + // When we're using a shape, make it possible with a connector or an + // arrow pointing to thie point + if (options.shape && !rotation) { + dataLabel[isNew ? 'attr' : 'animate']({ + anchorX: inverted ? + chart.plotWidth - point.plotY : + point.plotX, + anchorY: inverted ? + chart.plotHeight - point.plotX : + point.plotY + }); + } + } + // To use alignAttr property in hideOverlappingLabels + if (isNew && enabledDataSorting) { + dataLabel.placed = false; + } + // Show or hide based on the final aligned position + if (!visible && (!enabledDataSorting || justify)) { + dataLabel.hide(true); + dataLabel.placed = false; // don't animate back in + } + }; + /** + * Set starting position for data label sorting animation. + * + * @private + * @function Highcharts.Series#setDataLabelStartPos + * @param {Highcharts.SVGElement} dataLabel + * @param {Highcharts.ColumnPoint} point + * @param {boolean | undefined} [isNew] + * @param {boolean} [isInside] + * @param {Highcharts.AlignObject} [alignOptions] + * + * @return {void} + */ + Series.prototype.setDataLabelStartPos = function (point, dataLabel, isNew, isInside, alignOptions) { + var chart = this.chart, inverted = chart.inverted, xAxis = this.xAxis, reversed = xAxis.reversed, labelCenter = inverted ? dataLabel.height / 2 : dataLabel.width / 2, pointWidth = point.pointWidth, halfWidth = pointWidth ? pointWidth / 2 : 0, startXPos, startYPos; + startXPos = inverted ? + alignOptions.x : + (reversed ? + -labelCenter - halfWidth : + xAxis.width - labelCenter + halfWidth); + startYPos = inverted ? + (reversed ? + this.yAxis.height - labelCenter + halfWidth : + -labelCenter - halfWidth) : alignOptions.y; + dataLabel.startXPos = startXPos; + dataLabel.startYPos = startYPos; + // We need to handle visibility in case of sorting point outside plot area + if (!isInside) { + dataLabel + .attr({ opacity: 1 }) + .animate({ opacity: 0 }, void 0, dataLabel.hide); + } + else if (dataLabel.visibility === 'hidden') { + dataLabel.show(); + dataLabel + .attr({ opacity: 0 }) + .animate({ opacity: 1 }); + } + // Save start position on first render, but do not change position + if (!chart.hasRendered) { + return; + } + // Set start position + if (isNew) { + dataLabel.attr({ x: dataLabel.startXPos, y: dataLabel.startYPos }); + } + dataLabel.placed = true; + }; + /** + * If data labels fall partly outside the plot area, align them back in, in a + * way that doesn't hide the point. + * + * @private + * @function Highcharts.Series#justifyDataLabel + * @param {Highcharts.SVGElement} dataLabel + * @param {Highcharts.DataLabelsOptions} options + * @param {Highcharts.SVGAttributes} alignAttr + * @param {Highcharts.BBoxObject} bBox + * @param {Highcharts.BBoxObject} [alignTo] + * @param {boolean} [isNew] + * @return {boolean|undefined} + */ + Series.prototype.justifyDataLabel = function (dataLabel, options, alignAttr, bBox, alignTo, isNew) { + var chart = this.chart, align = options.align, verticalAlign = options.verticalAlign, off, justified, padding = dataLabel.box ? 0 : (dataLabel.padding || 0); + // Off left + off = alignAttr.x + padding; + if (off < 0) { + if (align === 'right') { + options.align = 'left'; + options.inside = true; + } + else { + options.x = -off; + } + justified = true; + } + // Off right + off = alignAttr.x + bBox.width - padding; + if (off > chart.plotWidth) { + if (align === 'left') { + options.align = 'right'; + options.inside = true; + } + else { + options.x = chart.plotWidth - off; + } + justified = true; + } + // Off top + off = alignAttr.y + padding; + if (off < 0) { + if (verticalAlign === 'bottom') { + options.verticalAlign = 'top'; + options.inside = true; + } + else { + options.y = -off; + } + justified = true; + } + // Off bottom + off = alignAttr.y + bBox.height - padding; + if (off > chart.plotHeight) { + if (verticalAlign === 'top') { + options.verticalAlign = 'bottom'; + options.inside = true; + } + else { + options.y = chart.plotHeight - off; + } + justified = true; + } + if (justified) { + dataLabel.placed = !isNew; + dataLabel.align(options, null, alignTo); + } + return justified; + }; + if (seriesTypes.pie) { + seriesTypes.pie.prototype.dataLabelPositioners = { + // Based on the value computed in Highcharts' distribute algorithm. + radialDistributionY: function (point) { + return point.top + point.distributeBox.pos; + }, + // get the x - use the natural x position for labels near the + // top and bottom, to prevent the top and botton slice + // connectors from touching each other on either side + // Based on the value computed in Highcharts' distribute algorithm. + radialDistributionX: function (series, point, y, naturalY) { + return series.getX(y < point.top + 2 || y > point.bottom - 2 ? + naturalY : + y, point.half, point); + }, + // dataLabels.distance determines the x position of the label + justify: function (point, radius, seriesCenter) { + return seriesCenter[0] + (point.half ? -1 : 1) * + (radius + point.labelDistance); + }, + // Left edges of the left-half labels touch the left edge of the plot + // area. Right edges of the right-half labels touch the right edge of + // the plot area. + alignToPlotEdges: function (dataLabel, half, plotWidth, plotLeft) { + var dataLabelWidth = dataLabel.getBBox().width; + return half ? dataLabelWidth + plotLeft : + plotWidth - dataLabelWidth - plotLeft; + }, + // Connectors of each side end in the same x position. Labels are + // aligned to them. Left edge of the widest left-half label touches the + // left edge of the plot area. Right edge of the widest right-half label + // touches the right edge of the plot area. + alignToConnectors: function (points, half, plotWidth, plotLeft) { + var maxDataLabelWidth = 0, dataLabelWidth; + // find widest data label + points.forEach(function (point) { + dataLabelWidth = point.dataLabel.getBBox().width; + if (dataLabelWidth > maxDataLabelWidth) { + maxDataLabelWidth = dataLabelWidth; + } + }); + return half ? maxDataLabelWidth + plotLeft : + plotWidth - maxDataLabelWidth - plotLeft; + } + }; + /** + * Override the base drawDataLabels method by pie specific functionality + * + * @private + * @function Highcharts.seriesTypes.pie#drawDataLabels + * @return {void} + */ + seriesTypes.pie.prototype.drawDataLabels = function () { + var series = this, data = series.data, point, chart = series.chart, options = series.options.dataLabels || {}, connectorPadding = options.connectorPadding, connectorWidth, plotWidth = chart.plotWidth, plotHeight = chart.plotHeight, plotLeft = chart.plotLeft, maxWidth = Math.round(chart.chartWidth / 3), connector, seriesCenter = series.center, radius = seriesCenter[2] / 2, centerY = seriesCenter[1], dataLabel, dataLabelWidth, + // labelPos, + labelPosition, labelHeight, + // divide the points into right and left halves for anti collision + halves = [ + [], + [] // left + ], x, y, visibility, j, overflow = [0, 0, 0, 0], // top, right, bottom, left + dataLabelPositioners = series.dataLabelPositioners, pointDataLabelsOptions; + // get out if not enabled + if (!series.visible || + (!options.enabled && + !series._hasPointLabels)) { + return; + } + // Reset all labels that have been shortened + data.forEach(function (point) { + if (point.dataLabel && point.visible && point.dataLabel.shortened) { + point.dataLabel + .attr({ + width: 'auto' + }).css({ + width: 'auto', + textOverflow: 'clip' + }); + point.dataLabel.shortened = false; + } + }); + // run parent method + Series.prototype.drawDataLabels.apply(series); + data.forEach(function (point) { + if (point.dataLabel) { + if (point.visible) { // #407, #2510 + // Arrange points for detection collision + halves[point.half].push(point); + // Reset positions (#4905) + point.dataLabel._pos = null; + // Avoid long labels squeezing the pie size too far down + if (!defined(options.style.width) && + !defined(point.options.dataLabels && + point.options.dataLabels.style && + point.options.dataLabels.style.width)) { + if (point.dataLabel.getBBox().width > maxWidth) { + point.dataLabel.css({ + // Use a fraction of the maxWidth to avoid + // wrapping close to the end of the string. + width: Math.round(maxWidth * 0.7) + 'px' + }); + point.dataLabel.shortened = true; + } + } + } + else { + point.dataLabel = point.dataLabel.destroy(); + // Workaround to make pies destroy multiple datalabels + // correctly. This logic needs rewriting to support multiple + // datalabels fully. + if (point.dataLabels && point.dataLabels.length === 1) { + delete point.dataLabels; + } + } + } + }); + /* Loop over the points in each half, starting from the top and bottom + * of the pie to detect overlapping labels. + */ + halves.forEach(function (points, i) { + var top, bottom, length = points.length, positions = [], naturalY, sideOverflow, size, distributionLength; + if (!length) { + return; + } + // Sort by angle + series.sortByAngle(points, i - 0.5); + // Only do anti-collision when we have dataLabels outside the pie + // and have connectors. (#856) + if (series.maxLabelDistance > 0) { + top = Math.max(0, centerY - radius - series.maxLabelDistance); + bottom = Math.min(centerY + radius + series.maxLabelDistance, chart.plotHeight); + points.forEach(function (point) { + // check if specific points' label is outside the pie + if (point.labelDistance > 0 && point.dataLabel) { + // point.top depends on point.labelDistance value + // Used for calculation of y value in getX method + point.top = Math.max(0, centerY - radius - point.labelDistance); + point.bottom = Math.min(centerY + radius + point.labelDistance, chart.plotHeight); + size = point.dataLabel.getBBox().height || 21; + // point.positionsIndex is needed for getting index of + // parameter related to specific point inside positions + // array - not every point is in positions array. + point.distributeBox = { + target: point.labelPosition.natural.y - + point.top + size / 2, + size: size, + rank: point.y + }; + positions.push(point.distributeBox); + } + }); + distributionLength = bottom + size - top; + H.distribute(positions, distributionLength, distributionLength / 5); + } + // Now the used slots are sorted, fill them up sequentially + for (j = 0; j < length; j++) { + point = points[j]; + // labelPos = point.labelPos; + labelPosition = point.labelPosition; + dataLabel = point.dataLabel; + visibility = point.visible === false ? 'hidden' : 'inherit'; + naturalY = labelPosition.natural.y; + y = naturalY; + if (positions && defined(point.distributeBox)) { + if (typeof point.distributeBox.pos === 'undefined') { + visibility = 'hidden'; + } + else { + labelHeight = point.distributeBox.size; + // Find label's y position + y = dataLabelPositioners + .radialDistributionY(point); + } + } + // It is needed to delete point.positionIndex for + // dynamically added points etc. + delete point.positionIndex; // @todo unused + // Find label's x position + // justify is undocumented in the API - preserve support for it + if (options.justify) { + x = dataLabelPositioners.justify(point, radius, seriesCenter); + } + else { + switch (options.alignTo) { + case 'connectors': + x = dataLabelPositioners.alignToConnectors(points, i, plotWidth, plotLeft); + break; + case 'plotEdges': + x = dataLabelPositioners.alignToPlotEdges(dataLabel, i, plotWidth, plotLeft); + break; + default: + x = dataLabelPositioners.radialDistributionX(series, point, y, naturalY); + } + } + // Record the placement and visibility + dataLabel._attr = { + visibility: visibility, + align: labelPosition.alignment + }; + pointDataLabelsOptions = point.options.dataLabels || {}; + dataLabel._pos = { + x: (x + + pick(pointDataLabelsOptions.x, options.x) + // (#12985) + ({ + left: connectorPadding, + right: -connectorPadding + }[labelPosition.alignment] || 0)), + // 10 is for the baseline (label vs text) + y: (y + + pick(pointDataLabelsOptions.y, options.y) - // (#12985) + 10) + }; + // labelPos.x = x; + // labelPos.y = y; + labelPosition.final.x = x; + labelPosition.final.y = y; + // Detect overflowing data labels + if (pick(options.crop, true)) { + dataLabelWidth = dataLabel.getBBox().width; + sideOverflow = null; + // Overflow left + if (x - dataLabelWidth < connectorPadding && + i === 1 // left half + ) { + sideOverflow = Math.round(dataLabelWidth - x + connectorPadding); + overflow[3] = Math.max(sideOverflow, overflow[3]); + // Overflow right + } + else if (x + dataLabelWidth > plotWidth - connectorPadding && + i === 0 // right half + ) { + sideOverflow = Math.round(x + dataLabelWidth - plotWidth + connectorPadding); + overflow[1] = Math.max(sideOverflow, overflow[1]); + } + // Overflow top + if (y - labelHeight / 2 < 0) { + overflow[0] = Math.max(Math.round(-y + labelHeight / 2), overflow[0]); + // Overflow left + } + else if (y + labelHeight / 2 > plotHeight) { + overflow[2] = Math.max(Math.round(y + labelHeight / 2 - plotHeight), overflow[2]); + } + dataLabel.sideOverflow = sideOverflow; + } + } // for each point + }); // for each half + // Do not apply the final placement and draw the connectors until we + // have verified that labels are not spilling over. + if (arrayMax(overflow) === 0 || + this.verifyDataLabelOverflow(overflow)) { + // Place the labels in the final position + this.placeDataLabels(); + this.points.forEach(function (point) { + // #8864: every connector can have individual options + pointDataLabelsOptions = + merge(options, point.options.dataLabels); + connectorWidth = + pick(pointDataLabelsOptions.connectorWidth, 1); + // Draw the connector + if (connectorWidth) { + var isNew; + connector = point.connector; + dataLabel = point.dataLabel; + if (dataLabel && + dataLabel._pos && + point.visible && + point.labelDistance > 0) { + visibility = dataLabel._attr.visibility; + isNew = !connector; + if (isNew) { + point.connector = connector = chart.renderer + .path() + .addClass('highcharts-data-label-connector ' + + ' highcharts-color-' + point.colorIndex + + (point.className ? + ' ' + point.className : + '')) + .add(series.dataLabelsGroup); + if (!chart.styledMode) { + connector.attr({ + 'stroke-width': connectorWidth, + 'stroke': (pointDataLabelsOptions.connectorColor || + point.color || + '#666666') + }); + } + } + connector[isNew ? 'attr' : 'animate']({ + d: point.getConnectorPath() + }); + connector.attr('visibility', visibility); + } + else if (connector) { + point.connector = connector.destroy(); + } + } + }); + } + }; + /** + * Extendable method for getting the path of the connector between the data + * label and the pie slice. + * + * @private + * @function Highcharts.seriesTypes.pie#connectorPath + * + * @param {*} labelPos + * + * @return {Highcharts.SVGPathArray} + */ + // TODO: depracated - remove it + /* + seriesTypes.pie.prototype.connectorPath = function (labelPos) { + var x = labelPos.x, + y = labelPos.y; + return pick(this.options.dataLabels.softConnector, true) ? [ + 'M', + // end of the string at the label + x + (labelPos[6] === 'left' ? 5 : -5), y, + 'C', + x, y, // first break, next to the label + 2 * labelPos[2] - labelPos[4], 2 * labelPos[3] - labelPos[5], + labelPos[2], labelPos[3], // second break + 'L', + labelPos[4], labelPos[5] // base + ] : [ + 'M', + // end of the string at the label + x + (labelPos[6] === 'left' ? 5 : -5), y, + 'L', + labelPos[2], labelPos[3], // second break + 'L', + labelPos[4], labelPos[5] // base + ]; + }; + */ + /** + * Perform the final placement of the data labels after we have verified + * that they fall within the plot area. + * + * @private + * @function Highcharts.seriesTypes.pie#placeDataLabels + * @return {void} + */ + seriesTypes.pie.prototype.placeDataLabels = function () { + this.points.forEach(function (point) { + var dataLabel = point.dataLabel, _pos; + if (dataLabel && point.visible) { + _pos = dataLabel._pos; + if (_pos) { + // Shorten data labels with ellipsis if they still overflow + // after the pie has reached minSize (#223). + if (dataLabel.sideOverflow) { + dataLabel._attr.width = + Math.max(dataLabel.getBBox().width - + dataLabel.sideOverflow, 0); + dataLabel.css({ + width: dataLabel._attr.width + 'px', + textOverflow: ((this.options.dataLabels.style || {}) + .textOverflow || + 'ellipsis') + }); + dataLabel.shortened = true; + } + dataLabel.attr(dataLabel._attr); + dataLabel[dataLabel.moved ? 'animate' : 'attr'](_pos); + dataLabel.moved = true; + } + else if (dataLabel) { + dataLabel.attr({ y: -9999 }); + } + } + // Clear for update + delete point.distributeBox; + }, this); + }; + seriesTypes.pie.prototype.alignDataLabel = noop; + /** + * Verify whether the data labels are allowed to draw, or we should run more + * translation and data label positioning to keep them inside the plot area. + * Returns true when data labels are ready to draw. + * + * @private + * @function Highcharts.seriesTypes.pie#verifyDataLabelOverflow + * @param {Array} overflow + * @return {boolean} + */ + seriesTypes.pie.prototype.verifyDataLabelOverflow = function (overflow) { + var center = this.center, options = this.options, centerOption = options.center, minSize = options.minSize || 80, newSize = minSize, + // If a size is set, return true and don't try to shrink the pie + // to fit the labels. + ret = options.size !== null; + if (!ret) { + // Handle horizontal size and center + if (centerOption[0] !== null) { // Fixed center + newSize = Math.max(center[2] - + Math.max(overflow[1], overflow[3]), minSize); + } + else { // Auto center + newSize = Math.max( + // horizontal overflow + center[2] - overflow[1] - overflow[3], minSize); + // horizontal center + center[0] += (overflow[3] - overflow[1]) / 2; + } + // Handle vertical size and center + if (centerOption[1] !== null) { // Fixed center + newSize = clamp(newSize, minSize, center[2] - Math.max(overflow[0], overflow[2])); + } + else { // Auto center + newSize = clamp(newSize, minSize, + // vertical overflow + center[2] - overflow[0] - overflow[2]); + // vertical center + center[1] += (overflow[0] - overflow[2]) / 2; + } + // If the size must be decreased, we need to run translate and + // drawDataLabels again + if (newSize < center[2]) { + center[2] = newSize; + center[3] = Math.min(// #3632 + relativeLength(options.innerSize || 0, newSize), newSize); + this.translate(center); + if (this.drawDataLabels) { + this.drawDataLabels(); + } + // Else, return true to indicate that the pie and its labels is + // within the plot area + } + else { + ret = true; + } + } + return ret; + }; + } + if (seriesTypes.column) { + /** + * Override the basic data label alignment by adjusting for the position of + * the column. + * + * @private + * @function Highcharts.seriesTypes.column#alignDataLabel + * @param {Highcharts.Point} point + * @param {Highcharts.SVGElement} dataLabel + * @param {Highcharts.DataLabelsOptions} options + * @param {Highcharts.BBoxObject} alignTo + * @param {boolean} [isNew] + * @return {void} + */ + seriesTypes.column.prototype.alignDataLabel = function (point, dataLabel, options, alignTo, isNew) { + var inverted = this.chart.inverted, series = point.series, + // data label box for alignment + dlBox = point.dlBox || point.shapeArgs, below = pick(point.below, // range series + point.plotY > + pick(this.translatedThreshold, series.yAxis.len)), + // draw it inside the box? + inside = pick(options.inside, !!this.options.stacking), overshoot; + // Align to the column itself, or the top of it + if (dlBox) { // Area range uses this method but not alignTo + alignTo = merge(dlBox); + if (alignTo.y < 0) { + alignTo.height += alignTo.y; + alignTo.y = 0; + } + // If parts of the box overshoots outside the plot area, modify the + // box to center the label inside + overshoot = alignTo.y + alignTo.height - series.yAxis.len; + if (overshoot > 0 && overshoot < alignTo.height) { + alignTo.height -= overshoot; + } + if (inverted) { + alignTo = { + x: series.yAxis.len - alignTo.y - alignTo.height, + y: series.xAxis.len - alignTo.x - alignTo.width, + width: alignTo.height, + height: alignTo.width + }; + } + // Compute the alignment box + if (!inside) { + if (inverted) { + alignTo.x += below ? 0 : alignTo.width; + alignTo.width = 0; + } + else { + alignTo.y += below ? alignTo.height : 0; + alignTo.height = 0; + } + } + } + // When alignment is undefined (typically columns and bars), display the + // individual point below or above the point depending on the threshold + options.align = pick(options.align, !inverted || inside ? 'center' : below ? 'right' : 'left'); + options.verticalAlign = pick(options.verticalAlign, inverted || inside ? 'middle' : below ? 'top' : 'bottom'); + // Call the parent method + Series.prototype.alignDataLabel.call(this, point, dataLabel, options, alignTo, isNew); + // If label was justified and we have contrast, set it: + if (options.inside && point.contrastColor) { + dataLabel.css({ + color: point.contrastColor + }); + } + }; + } + + }); + _registerModule(_modules, 'modules/overlapping-datalabels.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * Highcharts module to hide overlapping data labels. + * This module is included in Highcharts. + * + * (c) 2009-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, fireEvent = U.fireEvent, isArray = U.isArray, objectEach = U.objectEach, pick = U.pick; + var Chart = H.Chart; + /* eslint-disable no-invalid-this */ + // Collect potensial overlapping data labels. Stack labels probably don't need + // to be considered because they are usually accompanied by data labels that lie + // inside the columns. + addEvent(Chart, 'render', function collectAndHide() { + var labels = []; + // Consider external label collectors + (this.labelCollectors || []).forEach(function (collector) { + labels = labels.concat(collector()); + }); + (this.yAxis || []).forEach(function (yAxis) { + if (yAxis.stacking && + yAxis.options.stackLabels && + !yAxis.options.stackLabels.allowOverlap) { + objectEach(yAxis.stacking.stacks, function (stack) { + objectEach(stack, function (stackItem) { + labels.push(stackItem.label); + }); + }); + } + }); + (this.series || []).forEach(function (series) { + var dlOptions = series.options.dataLabels; + if (series.visible && + !(dlOptions.enabled === false && !series._hasPointLabels)) { // #3866 + (series.nodes || series.points).forEach(function (point) { + if (point.visible) { + var dataLabels = (isArray(point.dataLabels) ? + point.dataLabels : + (point.dataLabel ? [point.dataLabel] : [])); + dataLabels.forEach(function (label) { + var options = label.options; + label.labelrank = pick(options.labelrank, point.labelrank, point.shapeArgs && point.shapeArgs.height); // #4118 + if (!options.allowOverlap) { + labels.push(label); + } + }); + } + }); + } + }); + this.hideOverlappingLabels(labels); + }); + /** + * Hide overlapping labels. Labels are moved and faded in and out on zoom to + * provide a smooth visual imression. + * + * @private + * @function Highcharts.Chart#hideOverlappingLabels + * @param {Array} labels + * Rendered data labels + * @return {void} + * @requires modules/overlapping-datalabels + */ + Chart.prototype.hideOverlappingLabels = function (labels) { + var chart = this, len = labels.length, ren = chart.renderer, label, i, j, label1, label2, box1, box2, isLabelAffected = false, isIntersectRect = function (box1, box2) { + return !(box2.x > box1.x + box1.width || + box2.x + box2.width < box1.x || + box2.y > box1.y + box1.height || + box2.y + box2.height < box1.y); + }, + // Get the box with its position inside the chart, as opposed to getBBox + // that only reports the position relative to the parent. + getAbsoluteBox = function (label) { + var pos, parent, bBox, + // Substract the padding if no background or border (#4333) + padding = label.box ? 0 : (label.padding || 0), lineHeightCorrection = 0, xOffset = 0, boxWidth, alignValue; + if (label && + (!label.alignAttr || label.placed)) { + pos = label.alignAttr || { + x: label.attr('x'), + y: label.attr('y') + }; + parent = label.parentGroup; + // Get width and height if pure text nodes (stack labels) + if (!label.width) { + bBox = label.getBBox(); + label.width = bBox.width; + label.height = bBox.height; + // Labels positions are computed from top left corner, so + // we need to substract the text height from text nodes too. + lineHeightCorrection = ren + .fontMetrics(null, label.element).h; + } + boxWidth = label.width - 2 * padding; + alignValue = { + left: '0', + center: '0.5', + right: '1' + }[label.alignValue]; + if (alignValue) { + xOffset = +alignValue * boxWidth; + } + else if (Math.round(label.x) !== label.translateX) { + xOffset = label.x - label.translateX; + } + return { + x: pos.x + (parent.translateX || 0) + padding - xOffset, + y: pos.y + (parent.translateY || 0) + padding - + lineHeightCorrection, + width: label.width - 2 * padding, + height: label.height - 2 * padding + }; + } + }; + for (i = 0; i < len; i++) { + label = labels[i]; + if (label) { + // Mark with initial opacity + label.oldOpacity = label.opacity; + label.newOpacity = 1; + label.absoluteBox = getAbsoluteBox(label); + } + } + // Prevent a situation in a gradually rising slope, that each label will + // hide the previous one because the previous one always has lower rank. + labels.sort(function (a, b) { + return (b.labelrank || 0) - (a.labelrank || 0); + }); + // Detect overlapping labels + for (i = 0; i < len; i++) { + label1 = labels[i]; + box1 = label1 && label1.absoluteBox; + for (j = i + 1; j < len; ++j) { + label2 = labels[j]; + box2 = label2 && label2.absoluteBox; + if (box1 && + box2 && + label1 !== label2 && // #6465, polar chart with connectEnds + label1.newOpacity !== 0 && + label2.newOpacity !== 0) { + if (isIntersectRect(box1, box2)) { + (label1.labelrank < label2.labelrank ? label1 : label2) + .newOpacity = 0; + } + } + } + } + // Hide or show + labels.forEach(function (label) { + var complete, newOpacity; + if (label) { + newOpacity = label.newOpacity; + if (label.oldOpacity !== newOpacity) { + // Make sure the label is completely hidden to avoid catching + // clicks (#4362) + if (label.alignAttr && label.placed) { // data labels + label[newOpacity ? 'removeClass' : 'addClass']('highcharts-data-label-hidden'); + complete = function () { + if (!chart.styledMode) { + label.css({ pointerEvents: newOpacity ? 'auto' : 'none' }); + } + label.visibility = newOpacity ? 'inherit' : 'hidden'; + label.placed = !!newOpacity; + }; + isLabelAffected = true; + // Animate or set the opacity + label.alignAttr.opacity = newOpacity; + label[label.isOld ? 'animate' : 'attr'](label.alignAttr, null, complete); + fireEvent(chart, 'afterHideOverlappingLabel'); + } + else { // other labels, tick labels + label.attr({ + opacity: newOpacity + }); + } + } + label.isOld = true; + } + }); + if (isLabelAffected) { + fireEvent(chart, 'afterHideAllOverlappingLabels'); + } + }; + + }); + _registerModule(_modules, 'parts/Interaction.js', [_modules['parts/Globals.js'], _modules['parts/Legend.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js']], function (H, Legend, Point, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * @interface Highcharts.PointEventsOptionsObject + */ /** + * Fires when the point is selected either programmatically or following a click + * on the point. One parameter, `event`, is passed to the function. Returning + * `false` cancels the operation. + * @name Highcharts.PointEventsOptionsObject#select + * @type {Highcharts.PointSelectCallbackFunction|undefined} + */ /** + * Fires when the point is unselected either programmatically or following a + * click on the point. One parameter, `event`, is passed to the function. + * Returning `false` cancels the operation. + * @name Highcharts.PointEventsOptionsObject#unselect + * @type {Highcharts.PointUnselectCallbackFunction|undefined} + */ + /** + * Information about the select/unselect event. + * + * @interface Highcharts.PointInteractionEventObject + * @extends global.Event + */ /** + * @name Highcharts.PointInteractionEventObject#accumulate + * @type {boolean} + */ + /** + * Gets fired when the point is selected either programmatically or following a + * click on the point. + * + * @callback Highcharts.PointSelectCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {Highcharts.PointInteractionEventObject} event + * Event that occured. + */ + /** + * Fires when the point is unselected either programmatically or following a + * click on the point. + * + * @callback Highcharts.PointUnselectCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {Highcharts.PointInteractionEventObject} event + * Event that occured. + */ + var addEvent = U.addEvent, createElement = U.createElement, css = U.css, defined = U.defined, extend = U.extend, fireEvent = U.fireEvent, isArray = U.isArray, isFunction = U.isFunction, isNumber = U.isNumber, isObject = U.isObject, merge = U.merge, objectEach = U.objectEach, pick = U.pick; + var Chart = H.Chart, defaultOptions = H.defaultOptions, defaultPlotOptions = H.defaultPlotOptions, hasTouch = H.hasTouch, Series = H.Series, seriesTypes = H.seriesTypes, svg = H.svg, TrackerMixin; + /* eslint-disable valid-jsdoc */ + /** + * TrackerMixin for points and graphs. + * + * @private + * @mixin Highcharts.TrackerMixin + */ + TrackerMixin = H.TrackerMixin = { + /** + * Draw the tracker for a point. + * + * @private + * @function Highcharts.TrackerMixin.drawTrackerPoint + * @param {Highcharts.Series} this + * @fires Highcharts.Series#event:afterDrawTracker + */ + drawTrackerPoint: function () { + var series = this, chart = series.chart, pointer = chart.pointer, onMouseOver = function (e) { + var point = pointer.getPointFromEvent(e); + // undefined on graph in scatterchart + if (typeof point !== 'undefined') { + pointer.isDirectTouch = true; + point.onMouseOver(e); + } + }, dataLabels; + // Add reference to the point + series.points.forEach(function (point) { + dataLabels = (isArray(point.dataLabels) ? + point.dataLabels : + (point.dataLabel ? [point.dataLabel] : [])); + if (point.graphic) { + point.graphic.element.point = point; + } + dataLabels.forEach(function (dataLabel) { + if (dataLabel.div) { + dataLabel.div.point = point; + } + else { + dataLabel.element.point = point; + } + }); + }); + // Add the event listeners, we need to do this only once + if (!series._hasTracking) { + series.trackerGroups.forEach(function (key) { + if (series[key]) { + // we don't always have dataLabelsGroup + series[key] + .addClass('highcharts-tracker') + .on('mouseover', onMouseOver) + .on('mouseout', function (e) { + pointer.onTrackerMouseOut(e); + }); + if (hasTouch) { + series[key].on('touchstart', onMouseOver); + } + if (!chart.styledMode && series.options.cursor) { + series[key] + .css(css) + .css({ cursor: series.options.cursor }); + } + } + }); + series._hasTracking = true; + } + fireEvent(this, 'afterDrawTracker'); + }, + /** + * Draw the tracker object that sits above all data labels and markers to + * track mouse events on the graph or points. For the line type charts + * the tracker uses the same graphPath, but with a greater stroke width + * for better control. + * + * @private + * @function Highcharts.TrackerMixin.drawTrackerGraph + * @param {Highcharts.Series} this + * @fires Highcharts.Series#event:afterDrawTracker + */ + drawTrackerGraph: function () { + var series = this, options = series.options, trackByArea = options.trackByArea, trackerPath = [].concat(trackByArea ? + series.areaPath : + series.graphPath), + // trackerPathLength = trackerPath.length, + chart = series.chart, pointer = chart.pointer, renderer = chart.renderer, snap = chart.options.tooltip.snap, tracker = series.tracker, i, onMouseOver = function (e) { + if (chart.hoverSeries !== series) { + series.onMouseOver(); + } + }, + /* + * Empirical lowest possible opacities for TRACKER_FILL for an + * element to stay invisible but clickable + * IE6: 0.002 + * IE7: 0.002 + * IE8: 0.002 + * IE9: 0.00000000001 (unlimited) + * IE10: 0.0001 (exporting only) + * FF: 0.00000000001 (unlimited) + * Chrome: 0.000001 + * Safari: 0.000001 + * Opera: 0.00000000001 (unlimited) + */ + TRACKER_FILL = 'rgba(192,192,192,' + (svg ? 0.0001 : 0.002) + ')'; + // Draw the tracker + if (tracker) { + tracker.attr({ d: trackerPath }); + } + else if (series.graph) { // create + series.tracker = renderer.path(trackerPath) + .attr({ + visibility: series.visible ? 'visible' : 'hidden', + zIndex: 2 + }) + .addClass(trackByArea ? + 'highcharts-tracker-area' : + 'highcharts-tracker-line') + .add(series.group); + if (!chart.styledMode) { + series.tracker.attr({ + 'stroke-linecap': 'round', + 'stroke-linejoin': 'round', + stroke: TRACKER_FILL, + fill: trackByArea ? TRACKER_FILL : 'none', + 'stroke-width': series.graph.strokeWidth() + + (trackByArea ? 0 : 2 * snap) + }); + } + // The tracker is added to the series group, which is clipped, but + // is covered by the marker group. So the marker group also needs to + // capture events. + [series.tracker, series.markerGroup].forEach(function (tracker) { + tracker.addClass('highcharts-tracker') + .on('mouseover', onMouseOver) + .on('mouseout', function (e) { + pointer.onTrackerMouseOut(e); + }); + if (options.cursor && !chart.styledMode) { + tracker.css({ cursor: options.cursor }); + } + if (hasTouch) { + tracker.on('touchstart', onMouseOver); + } + }); + } + fireEvent(this, 'afterDrawTracker'); + } + }; + /* End TrackerMixin */ + // Add tracking event listener to the series group, so the point graphics + // themselves act as trackers + if (seriesTypes.column) { + /** + * @private + * @borrows Highcharts.TrackerMixin.drawTrackerPoint as Highcharts.seriesTypes.column#drawTracker + */ + seriesTypes.column.prototype.drawTracker = TrackerMixin.drawTrackerPoint; + } + if (seriesTypes.pie) { + /** + * @private + * @borrows Highcharts.TrackerMixin.drawTrackerPoint as Highcharts.seriesTypes.pie#drawTracker + */ + seriesTypes.pie.prototype.drawTracker = TrackerMixin.drawTrackerPoint; + } + if (seriesTypes.scatter) { + /** + * @private + * @borrows Highcharts.TrackerMixin.drawTrackerPoint as Highcharts.seriesTypes.scatter#drawTracker + */ + seriesTypes.scatter.prototype.drawTracker = TrackerMixin.drawTrackerPoint; + } + // Extend Legend for item events. + extend(Legend.prototype, { + /** + * @private + * @function Highcharts.Legend#setItemEvents + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + * @param {Highcharts.SVGElement} legendItem + * @param {boolean} [useHTML=false] + * @fires Highcharts.Point#event:legendItemClick + * @fires Highcharts.Series#event:legendItemClick + */ + setItemEvents: function (item, legendItem, useHTML) { + var legend = this, boxWrapper = legend.chart.renderer.boxWrapper, isPoint = item instanceof Point, activeClass = 'highcharts-legend-' + + (isPoint ? 'point' : 'series') + '-active', styledMode = legend.chart.styledMode, + // When `useHTML`, the symbol is rendered in other group, so + // we need to apply events listeners to both places + legendItems = useHTML ? + [legendItem, item.legendSymbol] : + [item.legendGroup]; + // Set the events on the item group, or in case of useHTML, the item + // itself (#1249) + legendItems.forEach(function (element) { + if (element) { + element + .on('mouseover', function () { + if (item.visible) { + legend.allItems.forEach(function (inactiveItem) { + if (item !== inactiveItem) { + inactiveItem.setState('inactive', !isPoint); + } + }); + } + item.setState('hover'); + // A CSS class to dim or hide other than the hovered + // series. + // Works only if hovered series is visible (#10071). + if (item.visible) { + boxWrapper.addClass(activeClass); + } + if (!styledMode) { + legendItem.css(legend.options.itemHoverStyle); + } + }) + .on('mouseout', function () { + if (!legend.chart.styledMode) { + legendItem.css(merge(item.visible ? + legend.itemStyle : + legend.itemHiddenStyle)); + } + legend.allItems.forEach(function (inactiveItem) { + if (item !== inactiveItem) { + inactiveItem.setState('', !isPoint); + } + }); + // A CSS class to dim or hide other than the hovered + // series. + boxWrapper.removeClass(activeClass); + item.setState(); + }) + .on('click', function (event) { + var strLegendItemClick = 'legendItemClick', fnLegendItemClick = function () { + if (item.setVisible) { + item.setVisible(); + } + // Reset inactive state + legend.allItems.forEach(function (inactiveItem) { + if (item !== inactiveItem) { + inactiveItem.setState(item.visible ? 'inactive' : '', !isPoint); + } + }); + }; + // A CSS class to dim or hide other than the hovered + // series. Event handling in iOS causes the activeClass + // to be added prior to click in some cases (#7418). + boxWrapper.removeClass(activeClass); + // Pass over the click/touch event. #4. + event = { + browserEvent: event + }; + // click the name or symbol + if (item.firePointEvent) { // point + item.firePointEvent(strLegendItemClick, event, fnLegendItemClick); + } + else { + fireEvent(item, strLegendItemClick, event, fnLegendItemClick); + } + }); + } + }); + }, + /** + * @private + * @function Highcharts.Legend#createCheckboxForItem + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + * @fires Highcharts.Series#event:checkboxClick + */ + createCheckboxForItem: function (item) { + var legend = this; + item.checkbox = createElement('input', { + type: 'checkbox', + className: 'highcharts-legend-checkbox', + checked: item.selected, + defaultChecked: item.selected // required by IE7 + }, legend.options.itemCheckboxStyle, legend.chart.container); + addEvent(item.checkbox, 'click', function (event) { + var target = event.target; + fireEvent(item.series || item, 'checkboxClick', { + checked: target.checked, + item: item + }, function () { + item.select(); + }); + }); + } + }); + // Extend the Chart object with interaction + extend(Chart.prototype, /** @lends Chart.prototype */ { + /** + * Display the zoom button, so users can reset zoom to the default view + * settings. + * + * @function Highcharts.Chart#showResetZoom + * + * @fires Highcharts.Chart#event:afterShowResetZoom + * @fires Highcharts.Chart#event:beforeShowResetZoom + */ + showResetZoom: function () { + var chart = this, lang = defaultOptions.lang, btnOptions = chart.options.chart.resetZoomButton, theme = btnOptions.theme, states = theme.states, alignTo = (btnOptions.relativeTo === 'chart' || + btnOptions.relativeTo === 'spaceBox' ? + null : + 'plotBox'); + /** + * @private + */ + function zoomOut() { + chart.zoomOut(); + } + fireEvent(this, 'beforeShowResetZoom', null, function () { + chart.resetZoomButton = chart.renderer + .button(lang.resetZoom, null, null, zoomOut, theme, states && states.hover) + .attr({ + align: btnOptions.position.align, + title: lang.resetZoomTitle + }) + .addClass('highcharts-reset-zoom') + .add() + .align(btnOptions.position, false, alignTo); + }); + fireEvent(this, 'afterShowResetZoom'); + }, + /** + * Zoom the chart out after a user has zoomed in. See also + * [Axis.setExtremes](/class-reference/Highcharts.Axis#setExtremes). + * + * @function Highcharts.Chart#zoomOut + * + * @fires Highcharts.Chart#event:selection + */ + zoomOut: function () { + fireEvent(this, 'selection', { resetSelection: true }, this.zoom); + }, + /** + * Zoom into a given portion of the chart given by axis coordinates. + * + * @private + * @function Highcharts.Chart#zoom + * @param {Highcharts.SelectEventObject} event + */ + zoom: function (event) { + var chart = this, hasZoomed, pointer = chart.pointer, displayButton = false, mouseDownPos = chart.inverted ? pointer.mouseDownX : pointer.mouseDownY, resetZoomButton; + // If zoom is called with no arguments, reset the axes + if (!event || event.resetSelection) { + chart.axes.forEach(function (axis) { + hasZoomed = axis.zoom(); + }); + pointer.initiated = false; // #6804 + } + else { // else, zoom in on all axes + event.xAxis.concat(event.yAxis).forEach(function (axisData) { + var axis = axisData.axis, axisStartPos = chart.inverted ? axis.left : axis.top, axisEndPos = chart.inverted ? + axisStartPos + axis.width : axisStartPos + axis.height, isXAxis = axis.isXAxis, isWithinPane = false; + // Check if zoomed area is within the pane (#1289). + // In case of multiple panes only one pane should be zoomed. + if ((!isXAxis && + mouseDownPos >= axisStartPos && + mouseDownPos <= axisEndPos) || + isXAxis || + !defined(mouseDownPos)) { + isWithinPane = true; + } + // don't zoom more than minRange + if (pointer[isXAxis ? 'zoomX' : 'zoomY'] && isWithinPane) { + hasZoomed = axis.zoom(axisData.min, axisData.max); + if (axis.displayBtn) { + displayButton = true; + } + } + }); + } + // Show or hide the Reset zoom button + resetZoomButton = chart.resetZoomButton; + if (displayButton && !resetZoomButton) { + chart.showResetZoom(); + } + else if (!displayButton && isObject(resetZoomButton)) { + chart.resetZoomButton = resetZoomButton.destroy(); + } + // Redraw + if (hasZoomed) { + chart.redraw(pick(chart.options.chart.animation, event && event.animation, chart.pointCount < 100)); + } + }, + /** + * Pan the chart by dragging the mouse across the pane. This function is + * called on mouse move, and the distance to pan is computed from chartX + * compared to the first chartX position in the dragging operation. + * + * @private + * @function Highcharts.Chart#pan + * @param {Highcharts.PointerEventObject} e + * @param {string} panning + */ + pan: function (e, panning) { + var chart = this, hoverPoints = chart.hoverPoints, panningOptions, chartOptions = chart.options.chart, hasMapNavigation = chart.options.mapNavigation && + chart.options.mapNavigation.enabled, doRedraw, type; + if (typeof panning === 'object') { + panningOptions = panning; + } + else { + panningOptions = { + enabled: panning, + type: 'x' + }; + } + if (chartOptions && chartOptions.panning) { + chartOptions.panning = panningOptions; + } + type = panningOptions.type; + fireEvent(this, 'pan', { originalEvent: e }, function () { + // remove active points for shared tooltip + if (hoverPoints) { + hoverPoints.forEach(function (point) { + point.setState(); + }); + } + // panning axis mapping + var xy = [1]; // x + if (type === 'xy') { + xy = [1, 0]; + } + else if (type === 'y') { + xy = [0]; + } + xy.forEach(function (isX) { + var axis = chart[isX ? 'xAxis' : 'yAxis'][0], axisOpt = axis.options, horiz = axis.horiz, mousePos = e[horiz ? 'chartX' : 'chartY'], mouseDown = horiz ? 'mouseDownX' : 'mouseDownY', startPos = chart[mouseDown], halfPointRange = (axis.pointRange || 0) / 2, pointRangeDirection = (axis.reversed && !chart.inverted) || + (!axis.reversed && chart.inverted) ? + -1 : + 1, extremes = axis.getExtremes(), panMin = axis.toValue(startPos - mousePos, true) + + halfPointRange * pointRangeDirection, panMax = axis.toValue(startPos + axis.len - mousePos, true) - + halfPointRange * pointRangeDirection, flipped = panMax < panMin, newMin = flipped ? panMax : panMin, newMax = flipped ? panMin : panMax, hasVerticalPanning = axis.hasVerticalPanning(), paddedMin, paddedMax, spill, panningState = axis.panningState; + // General calculations of panning state. + // This is related to using vertical panning. (#11315). + axis.series.forEach(function (series) { + if (hasVerticalPanning && + !isX && (!panningState || panningState.isDirty)) { + var processedData = series.getProcessedData(true), dataExtremes = series.getExtremes(processedData.yData, true); + if (!panningState) { + panningState = { + startMin: Number.MAX_VALUE, + startMax: -Number.MAX_VALUE + }; + } + if (isNumber(dataExtremes.dataMin) && + isNumber(dataExtremes.dataMax)) { + panningState.startMin = Math.min(dataExtremes.dataMin, panningState.startMin); + panningState.startMax = Math.max(dataExtremes.dataMax, panningState.startMax); + } + } + }); + paddedMin = Math.min(H.pick(panningState === null || panningState === void 0 ? void 0 : panningState.startMin, extremes.dataMin), halfPointRange ? + extremes.min : + axis.toValue(axis.toPixels(extremes.min) - + axis.minPixelPadding)); + paddedMax = Math.max(H.pick(panningState === null || panningState === void 0 ? void 0 : panningState.startMax, extremes.dataMax), halfPointRange ? + extremes.max : + axis.toValue(axis.toPixels(extremes.max) + + axis.minPixelPadding)); + axis.panningState = panningState; + // It is not necessary to calculate extremes on ordinal axis, + // because the are already calculated, so we don't want to + // override them. + if (!axisOpt.ordinal) { + // If the new range spills over, either to the min or max, + // adjust the new range. + spill = paddedMin - newMin; + if (spill > 0) { + newMax += spill; + newMin = paddedMin; + } + spill = newMax - paddedMax; + if (spill > 0) { + newMax = paddedMax; + newMin -= spill; + } + // Set new extremes if they are actually new + if (axis.series.length && + newMin !== extremes.min && + newMax !== extremes.max && + isX ? true : (panningState && + newMin >= paddedMin && + newMax <= paddedMax)) { + axis.setExtremes(newMin, newMax, false, false, { trigger: 'pan' }); + if (!chart.resetZoomButton && + !hasMapNavigation && + type.match('y')) { + chart.showResetZoom(); + axis.displayBtn = false; + } + doRedraw = true; + } + // set new reference for next run: + chart[mouseDown] = mousePos; + } + }); + if (doRedraw) { + chart.redraw(false); + } + css(chart.container, { cursor: 'move' }); + }); + } + }); + // Extend the Point object with interaction + extend(Point.prototype, /** @lends Highcharts.Point.prototype */ { + /** + * Toggle the selection status of a point. + * + * @see Highcharts.Chart#getSelectedPoints + * + * @sample highcharts/members/point-select/ + * Select a point from a button + * @sample highcharts/chart/events-selection-points/ + * Select a range of points through a drag selection + * @sample maps/series/data-id/ + * Select a point in Highmaps + * + * @function Highcharts.Point#select + * + * @param {boolean} [selected] + * When `true`, the point is selected. When `false`, the point is + * unselected. When `null` or `undefined`, the selection state is toggled. + * + * @param {boolean} [accumulate=false] + * When `true`, the selection is added to other selected points. + * When `false`, other selected points are deselected. Internally in + * Highcharts, when + * [allowPointSelect](https://api.highcharts.com/highcharts/plotOptions.series.allowPointSelect) + * is `true`, selected points are accumulated on Control, Shift or Cmd + * clicking the point. + * + * @fires Highcharts.Point#event:select + * @fires Highcharts.Point#event:unselect + */ + select: function (selected, accumulate) { + var point = this, series = point.series, chart = series.chart; + selected = pick(selected, !point.selected); + this.selectedStaging = selected; + // fire the event with the default handler + point.firePointEvent(selected ? 'select' : 'unselect', { accumulate: accumulate }, function () { + /** + * Whether the point is selected or not. + * + * @see Point#select + * @see Chart#getSelectedPoints + * + * @name Highcharts.Point#selected + * @type {boolean} + */ + point.selected = point.options.selected = selected; + series.options.data[series.data.indexOf(point)] = + point.options; + point.setState(selected && 'select'); + // unselect all other points unless Ctrl or Cmd + click + if (!accumulate) { + chart.getSelectedPoints().forEach(function (loopPoint) { + var loopSeries = loopPoint.series; + if (loopPoint.selected && loopPoint !== point) { + loopPoint.selected = loopPoint.options.selected = + false; + loopSeries.options.data[loopSeries.data.indexOf(loopPoint)] = loopPoint.options; + // Programatically selecting a point should restore + // normal state, but when click happened on other + // point, set inactive state to match other points + loopPoint.setState(chart.hoverPoints && + loopSeries.options.inactiveOtherPoints ? + 'inactive' : ''); + loopPoint.firePointEvent('unselect'); + } + }); + } + }); + delete this.selectedStaging; + }, + /** + * Runs on mouse over the point. Called internally from mouse and touch + * events. + * + * @function Highcharts.Point#onMouseOver + * + * @param {Highcharts.PointerEventObject} [e] + * The event arguments. + */ + onMouseOver: function (e) { + var point = this, series = point.series, chart = series.chart, pointer = chart.pointer; + e = e ? + pointer.normalize(e) : + // In cases where onMouseOver is called directly without an event + pointer.getChartCoordinatesFromPoint(point, chart.inverted); + pointer.runPointActions(e, point); + }, + /** + * Runs on mouse out from the point. Called internally from mouse and touch + * events. + * + * @function Highcharts.Point#onMouseOut + * @fires Highcharts.Point#event:mouseOut + */ + onMouseOut: function () { + var point = this, chart = point.series.chart; + point.firePointEvent('mouseOut'); + if (!point.series.options.inactiveOtherPoints) { + (chart.hoverPoints || []).forEach(function (p) { + p.setState(); + }); + } + chart.hoverPoints = chart.hoverPoint = null; + }, + /** + * Import events from the series' and point's options. Only do it on + * demand, to save processing time on hovering. + * + * @private + * @function Highcharts.Point#importEvents + */ + importEvents: function () { + if (!this.hasImportedEvents) { + var point = this, options = merge(point.series.options.point, point.options), events = options.events; + point.events = events; + objectEach(events, function (event, eventType) { + if (isFunction(event)) { + addEvent(point, eventType, event); + } + }); + this.hasImportedEvents = true; + } + }, + /** + * Set the point's state. + * + * @function Highcharts.Point#setState + * + * @param {Highcharts.PointStateValue|""} [state] + * The new state, can be one of `'hover'`, `'select'`, `'inactive'`, + * or `''` (an empty string), `'normal'` or `undefined` to set to + * normal state. + * @param {boolean} [move] + * State for animation. + * + * @fires Highcharts.Point#event:afterSetState + */ + setState: function (state, move) { + var point = this, series = point.series, previousState = point.state, stateOptions = (series.options.states[state || 'normal'] || + {}), markerOptions = (defaultPlotOptions[series.type].marker && + series.options.marker), normalDisabled = (markerOptions && markerOptions.enabled === false), markerStateOptions = ((markerOptions && + markerOptions.states && + markerOptions.states[state || 'normal']) || {}), stateDisabled = markerStateOptions.enabled === false, stateMarkerGraphic = series.stateMarkerGraphic, pointMarker = point.marker || {}, chart = series.chart, halo = series.halo, haloOptions, markerAttribs, pointAttribs, pointAttribsAnimation, hasMarkers = (markerOptions && series.markerAttribs), newSymbol; + state = state || ''; // empty string + if ( + // already has this state + (state === point.state && !move) || + // selected points don't respond to hover + (point.selected && state !== 'select') || + // series' state options is disabled + (stateOptions.enabled === false) || + // general point marker's state options is disabled + (state && (stateDisabled || + (normalDisabled && + markerStateOptions.enabled === false))) || + // individual point marker's state options is disabled + (state && + pointMarker.states && + pointMarker.states[state] && + pointMarker.states[state].enabled === false) // #1610 + ) { + return; + } + point.state = state; + if (hasMarkers) { + markerAttribs = series.markerAttribs(point, state); + } + // Apply hover styles to the existing point + if (point.graphic) { + if (previousState) { + point.graphic.removeClass('highcharts-point-' + previousState); + } + if (state) { + point.graphic.addClass('highcharts-point-' + state); + } + if (!chart.styledMode) { + pointAttribs = series.pointAttribs(point, state); + pointAttribsAnimation = pick(chart.options.chart.animation, stateOptions.animation); + // Some inactive points (e.g. slices in pie) should apply + // oppacity also for it's labels + if (series.options.inactiveOtherPoints && pointAttribs.opacity) { + (point.dataLabels || []).forEach(function (label) { + if (label) { + label.animate({ + opacity: pointAttribs.opacity + }, pointAttribsAnimation); + } + }); + if (point.connector) { + point.connector.animate({ + opacity: pointAttribs.opacity + }, pointAttribsAnimation); + } + } + point.graphic.animate(pointAttribs, pointAttribsAnimation); + } + if (markerAttribs) { + point.graphic.animate(markerAttribs, pick( + // Turn off globally: + chart.options.chart.animation, markerStateOptions.animation, markerOptions.animation)); + } + // Zooming in from a range with no markers to a range with markers + if (stateMarkerGraphic) { + stateMarkerGraphic.hide(); + } + } + else { + // if a graphic is not applied to each point in the normal state, + // create a shared graphic for the hover state + if (state && markerStateOptions) { + newSymbol = pointMarker.symbol || series.symbol; + // If the point has another symbol than the previous one, throw + // away the state marker graphic and force a new one (#1459) + if (stateMarkerGraphic && + stateMarkerGraphic.currentSymbol !== newSymbol) { + stateMarkerGraphic = stateMarkerGraphic.destroy(); + } + // Add a new state marker graphic + if (markerAttribs) { + if (!stateMarkerGraphic) { + if (newSymbol) { + series.stateMarkerGraphic = stateMarkerGraphic = + chart.renderer + .symbol(newSymbol, markerAttribs.x, markerAttribs.y, markerAttribs.width, markerAttribs.height) + .add(series.markerGroup); + stateMarkerGraphic.currentSymbol = newSymbol; + } + // Move the existing graphic + } + else { + stateMarkerGraphic[move ? 'animate' : 'attr']({ + x: markerAttribs.x, + y: markerAttribs.y + }); + } + } + if (!chart.styledMode && stateMarkerGraphic) { + stateMarkerGraphic.attr(series.pointAttribs(point, state)); + } + } + if (stateMarkerGraphic) { + stateMarkerGraphic[state && point.isInside ? 'show' : 'hide'](); // #2450 + stateMarkerGraphic.element.point = point; // #4310 + } + } + // Show me your halo + haloOptions = stateOptions.halo; + var markerGraphic = (point.graphic || stateMarkerGraphic); + var markerVisibility = (markerGraphic && markerGraphic.visibility || 'inherit'); + if (haloOptions && + haloOptions.size && + markerGraphic && + markerVisibility !== 'hidden' && + !point.isCluster) { + if (!halo) { + series.halo = halo = chart.renderer.path() + // #5818, #5903, #6705 + .add(markerGraphic.parentGroup); + } + halo.show()[move ? 'animate' : 'attr']({ + d: point.haloPath(haloOptions.size) + }); + halo.attr({ + 'class': 'highcharts-halo highcharts-color-' + + pick(point.colorIndex, series.colorIndex) + + (point.className ? ' ' + point.className : ''), + 'visibility': markerVisibility, + 'zIndex': -1 // #4929, #8276 + }); + halo.point = point; // #6055 + if (!chart.styledMode) { + halo.attr(extend({ + 'fill': point.color || series.color, + 'fill-opacity': haloOptions.opacity + }, haloOptions.attributes)); + } + } + else if (halo && halo.point && halo.point.haloPath) { + // Animate back to 0 on the current halo point (#6055) + halo.animate({ d: halo.point.haloPath(0) }, null, + // Hide after unhovering. The `complete` callback runs in the + // halo's context (#7681). + halo.hide); + } + fireEvent(point, 'afterSetState'); + }, + /** + * Get the path definition for the halo, which is usually a shadow-like + * circle around the currently hovered point. + * + * @function Highcharts.Point#haloPath + * + * @param {number} size + * The radius of the circular halo. + * + * @return {Highcharts.SVGPathArray} + * The path definition. + */ + haloPath: function (size) { + var series = this.series, chart = series.chart; + return chart.renderer.symbols.circle(Math.floor(this.plotX) - size, this.plotY - size, size * 2, size * 2); + } + }); + // Extend the Series object with interaction + extend(Series.prototype, /** @lends Highcharts.Series.prototype */ { + /** + * Runs on mouse over the series graphical items. + * + * @function Highcharts.Series#onMouseOver + * @fires Highcharts.Series#event:mouseOver + */ + onMouseOver: function () { + var series = this, chart = series.chart, hoverSeries = chart.hoverSeries, pointer = chart.pointer; + pointer.setHoverChartIndex(); + // set normal state to previous series + if (hoverSeries && hoverSeries !== series) { + hoverSeries.onMouseOut(); + } + // trigger the event, but to save processing time, + // only if defined + if (series.options.events.mouseOver) { + fireEvent(series, 'mouseOver'); + } + // hover this + series.setState('hover'); + /** + * Contains the original hovered series. + * + * @name Highcharts.Chart#hoverSeries + * @type {Highcharts.Series|null} + */ + chart.hoverSeries = series; + }, + /** + * Runs on mouse out of the series graphical items. + * + * @function Highcharts.Series#onMouseOut + * + * @fires Highcharts.Series#event:mouseOut + */ + onMouseOut: function () { + // trigger the event only if listeners exist + var series = this, options = series.options, chart = series.chart, tooltip = chart.tooltip, hoverPoint = chart.hoverPoint; + // #182, set to null before the mouseOut event fires + chart.hoverSeries = null; + // trigger mouse out on the point, which must be in this series + if (hoverPoint) { + hoverPoint.onMouseOut(); + } + // fire the mouse out event + if (series && options.events.mouseOut) { + fireEvent(series, 'mouseOut'); + } + // hide the tooltip + if (tooltip && + !series.stickyTracking && + (!tooltip.shared || series.noSharedTooltip)) { + tooltip.hide(); + } + // Reset all inactive states + chart.series.forEach(function (s) { + s.setState('', true); + }); + }, + /** + * Set the state of the series. Called internally on mouse interaction + * operations, but it can also be called directly to visually + * highlight a series. + * + * @function Highcharts.Series#setState + * + * @param {Highcharts.SeriesStateValue|""} [state] + * The new state, can be either `'hover'`, `'inactive'`, `'select'`, + * or `''` (an empty string), `'normal'` or `undefined` to set to + * normal state. + * @param {boolean} [inherit] + * Determines if state should be inherited by points too. + */ + setState: function (state, inherit) { + var series = this, options = series.options, graph = series.graph, inactiveOtherPoints = options.inactiveOtherPoints, stateOptions = options.states, lineWidth = options.lineWidth, opacity = options.opacity, + // By default a quick animation to hover/inactive, + // slower to un-hover + stateAnimation = pick((stateOptions[state || 'normal'] && + stateOptions[state || 'normal'].animation), series.chart.options.chart.animation), attribs, i = 0; + state = state || ''; + if (series.state !== state) { + // Toggle class names + [ + series.group, + series.markerGroup, + series.dataLabelsGroup + ].forEach(function (group) { + if (group) { + // Old state + if (series.state) { + group.removeClass('highcharts-series-' + series.state); + } + // New state + if (state) { + group.addClass('highcharts-series-' + state); + } + } + }); + series.state = state; + if (!series.chart.styledMode) { + if (stateOptions[state] && + stateOptions[state].enabled === false) { + return; + } + if (state) { + lineWidth = (stateOptions[state].lineWidth || + lineWidth + (stateOptions[state].lineWidthPlus || 0)); // #4035 + opacity = pick(stateOptions[state].opacity, opacity); + } + if (graph && !graph.dashstyle) { + attribs = { + 'stroke-width': lineWidth + }; + // Animate the graph stroke-width. + graph.animate(attribs, stateAnimation); + while (series['zone-graph-' + i]) { + series['zone-graph-' + i].attr(attribs); + i = i + 1; + } + } + // For some types (pie, networkgraph, sankey) opacity is + // resolved on a point level + if (!inactiveOtherPoints) { + [ + series.group, + series.markerGroup, + series.dataLabelsGroup, + series.labelBySeries + ].forEach(function (group) { + if (group) { + group.animate({ + opacity: opacity + }, stateAnimation); + } + }); + } + } + } + // Don't loop over points on a series that doesn't apply inactive state + // to siblings markers (e.g. line, column) + if (inherit && inactiveOtherPoints && series.points) { + series.setAllPointsToState(state); + } + }, + /** + * Set the state for all points in the series. + * + * @function Highcharts.Series#setAllPointsToState + * + * @private + * + * @param {string} [state] + * Can be either `hover` or undefined to set to normal state. + */ + setAllPointsToState: function (state) { + this.points.forEach(function (point) { + if (point.setState) { + point.setState(state); + } + }); + }, + /** + * Show or hide the series. + * + * @function Highcharts.Series#setVisible + * + * @param {boolean} [visible] + * True to show the series, false to hide. If undefined, the visibility is + * toggled. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the series is altered. If doing more + * operations on the chart, it is a good idea to set redraw to false and + * call {@link Chart#redraw|chart.redraw()} after. + * + * @fires Highcharts.Series#event:hide + * @fires Highcharts.Series#event:show + */ + setVisible: function (vis, redraw) { + var series = this, chart = series.chart, legendItem = series.legendItem, showOrHide, ignoreHiddenSeries = chart.options.chart.ignoreHiddenSeries, oldVisibility = series.visible; + // if called without an argument, toggle visibility + series.visible = + vis = + series.options.visible = + series.userOptions.visible = + typeof vis === 'undefined' ? !oldVisibility : vis; // #5618 + showOrHide = vis ? 'show' : 'hide'; + // show or hide elements + [ + 'group', + 'dataLabelsGroup', + 'markerGroup', + 'tracker', + 'tt' + ].forEach(function (key) { + if (series[key]) { + series[key][showOrHide](); + } + }); + // hide tooltip (#1361) + if (chart.hoverSeries === series || + (chart.hoverPoint && chart.hoverPoint.series) === series) { + series.onMouseOut(); + } + if (legendItem) { + chart.legend.colorizeItem(series, vis); + } + // rescale or adapt to resized chart + series.isDirty = true; + // in a stack, all other series are affected + if (series.options.stacking) { + chart.series.forEach(function (otherSeries) { + if (otherSeries.options.stacking && otherSeries.visible) { + otherSeries.isDirty = true; + } + }); + } + // show or hide linked series + series.linkedSeries.forEach(function (otherSeries) { + otherSeries.setVisible(vis, false); + }); + if (ignoreHiddenSeries) { + chart.isDirtyBox = true; + } + fireEvent(series, showOrHide); + if (redraw !== false) { + chart.redraw(); + } + }, + /** + * Show the series if hidden. + * + * @sample highcharts/members/series-hide/ + * Toggle visibility from a button + * + * @function Highcharts.Series#show + * @fires Highcharts.Series#event:show + */ + show: function () { + this.setVisible(true); + }, + /** + * Hide the series if visible. If the + * [chart.ignoreHiddenSeries](https://api.highcharts.com/highcharts/chart.ignoreHiddenSeries) + * option is true, the chart is redrawn without this series. + * + * @sample highcharts/members/series-hide/ + * Toggle visibility from a button + * + * @function Highcharts.Series#hide + * @fires Highcharts.Series#event:hide + */ + hide: function () { + this.setVisible(false); + }, + /** + * Select or unselect the series. This means its + * {@link Highcharts.Series.selected|selected} + * property is set, the checkbox in the legend is toggled and when selected, + * the series is returned by the {@link Highcharts.Chart#getSelectedSeries} + * function. + * + * @sample highcharts/members/series-select/ + * Select a series from a button + * + * @function Highcharts.Series#select + * + * @param {boolean} [selected] + * True to select the series, false to unselect. If undefined, the selection + * state is toggled. + * + * @fires Highcharts.Series#event:select + * @fires Highcharts.Series#event:unselect + */ + select: function (selected) { + var series = this; + series.selected = + selected = + this.options.selected = (typeof selected === 'undefined' ? + !series.selected : + selected); + if (series.checkbox) { + series.checkbox.checked = selected; + } + fireEvent(series, selected ? 'select' : 'unselect'); + }, + /** + * @private + * @borrows Highcharts.TrackerMixin.drawTrackerGraph as Highcharts.Series#drawTracker + */ + drawTracker: TrackerMixin.drawTrackerGraph + }); + + }); + _registerModule(_modules, 'parts/Responsive.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * A callback function to gain complete control on when the responsive rule + * applies. + * + * @callback Highcharts.ResponsiveCallbackFunction + * + * @param {Highcharts.Chart} this + * Chart context. + * + * @return {boolean} + * Return `true` if it applies. + */ + var find = U.find, isArray = U.isArray, isObject = U.isObject, merge = U.merge, objectEach = U.objectEach, pick = U.pick, splat = U.splat, uniqueKey = U.uniqueKey; + var Chart = H.Chart; + /** + * Allows setting a set of rules to apply for different screen or chart + * sizes. Each rule specifies additional chart options. + * + * @sample {highstock} stock/demo/responsive/ + * Stock chart + * @sample highcharts/responsive/axis/ + * Axis + * @sample highcharts/responsive/legend/ + * Legend + * @sample highcharts/responsive/classname/ + * Class name + * + * @since 5.0.0 + * @apioption responsive + */ + /** + * A set of rules for responsive settings. The rules are executed from + * the top down. + * + * @sample {highcharts} highcharts/responsive/axis/ + * Axis changes + * @sample {highstock} highcharts/responsive/axis/ + * Axis changes + * @sample {highmaps} highcharts/responsive/axis/ + * Axis changes + * + * @type {Array<*>} + * @since 5.0.0 + * @apioption responsive.rules + */ + /** + * A full set of chart options to apply as overrides to the general + * chart options. The chart options are applied when the given rule + * is active. + * + * A special case is configuration objects that take arrays, for example + * [xAxis](#xAxis), [yAxis](#yAxis) or [series](#series). For these + * collections, an `id` option is used to map the new option set to + * an existing object. If an existing object of the same id is not found, + * the item of the same indexupdated. So for example, setting `chartOptions` + * with two series items without an `id`, will cause the existing chart's + * two series to be updated with respective options. + * + * @sample {highstock} stock/demo/responsive/ + * Stock chart + * @sample highcharts/responsive/axis/ + * Axis + * @sample highcharts/responsive/legend/ + * Legend + * @sample highcharts/responsive/classname/ + * Class name + * + * @type {Highcharts.Options} + * @since 5.0.0 + * @apioption responsive.rules.chartOptions + */ + /** + * Under which conditions the rule applies. + * + * @since 5.0.0 + * @apioption responsive.rules.condition + */ + /** + * A callback function to gain complete control on when the responsive + * rule applies. Return `true` if it applies. This opens for checking + * against other metrics than the chart size, for example the document + * size or other elements. + * + * @type {Highcharts.ResponsiveCallbackFunction} + * @since 5.0.0 + * @context Highcharts.Chart + * @apioption responsive.rules.condition.callback + */ + /** + * The responsive rule applies if the chart height is less than this. + * + * @type {number} + * @since 5.0.0 + * @apioption responsive.rules.condition.maxHeight + */ + /** + * The responsive rule applies if the chart width is less than this. + * + * @sample highcharts/responsive/axis/ + * Max width is 500 + * + * @type {number} + * @since 5.0.0 + * @apioption responsive.rules.condition.maxWidth + */ + /** + * The responsive rule applies if the chart height is greater than this. + * + * @type {number} + * @default 0 + * @since 5.0.0 + * @apioption responsive.rules.condition.minHeight + */ + /** + * The responsive rule applies if the chart width is greater than this. + * + * @type {number} + * @default 0 + * @since 5.0.0 + * @apioption responsive.rules.condition.minWidth + */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Update the chart based on the current chart/document size and options for + * responsiveness. + * + * @private + * @function Highcharts.Chart#setResponsive + * @param {boolean} [redraw=true] + * @param {boolean} [reset=false] + * Reset by un-applying all rules. Chart.update resets all rules before + * applying updated options. + * @return {void} + */ + Chart.prototype.setResponsive = function (redraw, reset) { + var options = this.options.responsive, ruleIds = [], currentResponsive = this.currentResponsive, currentRuleIds, undoOptions; + if (!reset && options && options.rules) { + options.rules.forEach(function (rule) { + if (typeof rule._id === 'undefined') { + rule._id = uniqueKey(); + } + this.matchResponsiveRule(rule, ruleIds /* , redraw */); + }, this); + } + // Merge matching rules + var mergedOptions = merge.apply(0, ruleIds.map(function (ruleId) { + return find(options.rules, function (rule) { + return rule._id === ruleId; + }).chartOptions; + })); + mergedOptions.isResponsiveOptions = true; + // Stringified key for the rules that currently apply. + ruleIds = (ruleIds.toString() || void 0); + currentRuleIds = currentResponsive && currentResponsive.ruleIds; + // Changes in what rules apply + if (ruleIds !== currentRuleIds) { + // Undo previous rules. Before we apply a new set of rules, we need to + // roll back completely to base options (#6291). + if (currentResponsive) { + this.update(currentResponsive.undoOptions, redraw, true); + } + if (ruleIds) { + // Get undo-options for matching rules + undoOptions = this.currentOptions(mergedOptions); + undoOptions.isResponsiveOptions = true; + this.currentResponsive = { + ruleIds: ruleIds, + mergedOptions: mergedOptions, + undoOptions: undoOptions + }; + this.update(mergedOptions, redraw, true); + } + else { + this.currentResponsive = void 0; + } + } + }; + /** + * Handle a single responsiveness rule. + * + * @private + * @function Highcharts.Chart#matchResponsiveRule + * @param {Highcharts.ResponsiveRulesOptions} rule + * @param {Array} matches + * @return {void} + */ + Chart.prototype.matchResponsiveRule = function (rule, matches) { + var condition = rule.condition, fn = condition.callback || function () { + return (this.chartWidth <= pick(condition.maxWidth, Number.MAX_VALUE) && + this.chartHeight <= + pick(condition.maxHeight, Number.MAX_VALUE) && + this.chartWidth >= pick(condition.minWidth, 0) && + this.chartHeight >= pick(condition.minHeight, 0)); + }; + if (fn.call(this)) { + matches.push(rule._id); + } + }; + /** + * Get the current values for a given set of options. Used before we update + * the chart with a new responsiveness rule. + * TODO: Restore axis options (by id?) + * + * @private + * @function Highcharts.Chart#currentOptions + * @param {Highcharts.Options} options + * @return {Highcharts.Options} + */ + Chart.prototype.currentOptions = function (options) { + var chart = this, ret = {}; + /** + * Recurse over a set of options and its current values, + * and store the current values in the ret object. + */ + function getCurrent(options, curr, ret, depth) { + var i; + objectEach(options, function (val, key) { + if (!depth && + chart.collectionsWithUpdate.indexOf(key) > -1) { + val = splat(val); + ret[key] = []; + // Iterate over collections like series, xAxis or yAxis and map + // the items by index. + for (i = 0; i < val.length; i++) { + if (curr[key][i]) { // Item exists in current data (#6347) + ret[key][i] = {}; + getCurrent(val[i], curr[key][i], ret[key][i], depth + 1); + } + } + } + else if (isObject(val)) { + ret[key] = isArray(val) ? [] : {}; + getCurrent(val, curr[key] || {}, ret[key], depth + 1); + } + else if (typeof curr[key] === 'undefined') { // #10286 + ret[key] = null; + } + else { + ret[key] = curr[key]; + } + }); + } + getCurrent(options, this.options, ret, 0); + return ret; + }; + + }); + _registerModule(_modules, 'masters/highcharts.src.js', [_modules['parts/Globals.js']], function (Highcharts) { + + + return Highcharts; + }); + _registerModule(_modules, 'parts-gantt/CurrentDateIndicator.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['parts/PlotLineOrBand.js']], function (H, U, PlotLineOrBand) { + /* * + * + * (c) 2016-2020 Highsoft AS + * + * Author: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, merge = U.merge, wrap = U.wrap; + var Axis = H.Axis; + var defaultConfig = { + /** + * Show an indicator on the axis for the current date and time. Can be a + * boolean or a configuration object similar to + * [xAxis.plotLines](#xAxis.plotLines). + * + * @sample gantt/current-date-indicator/demo + * Current date indicator enabled + * @sample gantt/current-date-indicator/object-config + * Current date indicator with custom options + * + * @declare Highcharts.AxisCurrentDateIndicatorOptions + * @type {boolean|*} + * @default true + * @extends xAxis.plotLines + * @excluding value + * @product gantt + * @apioption xAxis.currentDateIndicator + */ + currentDateIndicator: true, + color: '#ccd6eb', + width: 2, + /** + * @declare Highcharts.AxisCurrentDateIndicatorLabelOptions + */ + label: { + /** + * Format of the label. This options is passed as the fist argument to + * [dateFormat](/class-reference/Highcharts#dateFormat) function. + * + * @type {string} + * @default '%a, %b %d %Y, %H:%M' + * @product gantt + * @apioption xAxis.currentDateIndicator.label.format + */ + format: '%a, %b %d %Y, %H:%M', + formatter: function (value, format) { + return H.dateFormat(format, value); + }, + rotation: 0, + /** + * @type {Highcharts.CSSObject} + */ + style: { + /** @internal */ + fontSize: '10px' + } + } + }; + /* eslint-disable no-invalid-this */ + addEvent(Axis, 'afterSetOptions', function () { + var options = this.options, cdiOptions = options.currentDateIndicator; + if (cdiOptions) { + cdiOptions = typeof cdiOptions === 'object' ? + merge(defaultConfig, cdiOptions) : merge(defaultConfig); + cdiOptions.value = new Date(); + if (!options.plotLines) { + options.plotLines = []; + } + options.plotLines.push(cdiOptions); + } + }); + addEvent(PlotLineOrBand, 'render', function () { + // If the label already exists, update its text + if (this.label) { + this.label.attr({ + text: this.getLabelText(this.options.label) + }); + } + }); + wrap(PlotLineOrBand.prototype, 'getLabelText', function (defaultMethod, defaultLabelOptions) { + var options = this.options; + if (options.currentDateIndicator && options.label && + typeof options.label.formatter === 'function') { + options.value = new Date(); + return options.label.formatter + .call(this, options.value, options.label.format); + } + return defaultMethod.call(this, defaultLabelOptions); + }); + + }); + _registerModule(_modules, 'modules/static-scale.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2016-2020 Torstein Honsi, Lars Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, defined = U.defined, isNumber = U.isNumber, pick = U.pick; + var Chart = H.Chart; + /* eslint-disable no-invalid-this */ + /** + * For vertical axes only. Setting the static scale ensures that each tick unit + * is translated into a fixed pixel height. For example, setting the static + * scale to 24 results in each Y axis category taking up 24 pixels, and the + * height of the chart adjusts. Adding or removing items will make the chart + * resize. + * + * @sample gantt/xrange-series/demo/ + * X-range series with static scale + * + * @type {number} + * @default 50 + * @since 6.2.0 + * @product gantt + * @apioption yAxis.staticScale + */ + addEvent(H.Axis, 'afterSetOptions', function () { + var chartOptions = this.chart.options && this.chart.options.chart; + if (!this.horiz && + isNumber(this.options.staticScale) && + (!chartOptions.height || + (chartOptions.scrollablePlotArea && + chartOptions.scrollablePlotArea.minHeight))) { + this.staticScale = this.options.staticScale; + } + }); + Chart.prototype.adjustHeight = function () { + if (this.redrawTrigger !== 'adjustHeight') { + (this.axes || []).forEach(function (axis) { + var chart = axis.chart, animate = !!chart.initiatedScale && + chart.options.animation, staticScale = axis.options.staticScale, height, diff; + if (axis.staticScale && defined(axis.min)) { + height = pick(axis.brokenAxis && axis.brokenAxis.unitLength, axis.max + axis.tickInterval - axis.min) * staticScale; + // Minimum height is 1 x staticScale. + height = Math.max(height, staticScale); + diff = height - chart.plotHeight; + if (Math.abs(diff) >= 1) { + chart.plotHeight = height; + chart.redrawTrigger = 'adjustHeight'; + chart.setSize(void 0, chart.chartHeight + diff, animate); + } + // Make sure clip rects have the right height before initial + // animation. + axis.series.forEach(function (series) { + var clipRect = series.sharedClipKey && + chart[series.sharedClipKey]; + if (clipRect) { + clipRect.attr({ + height: chart.plotHeight + }); + } + }); + } + }); + this.initiatedScale = true; + } + this.redrawTrigger = null; + }; + addEvent(Chart, 'render', Chart.prototype.adjustHeight); + + }); + _registerModule(_modules, 'parts-gantt/Tree.js', [_modules['parts/Utilities.js']], function (U) { + /* * + * + * (c) 2016-2020 Highsoft AS + * + * Authors: Jon Arild Nygard + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /* eslint no-console: 0 */ + var extend = U.extend, isNumber = U.isNumber, pick = U.pick; + /** + * Creates an object map from parent id to childrens index. + * + * @private + * @function Highcharts.Tree#getListOfParents + * + * @param {Array<*>} data + * List of points set in options. `Array.parent` is parent id of point. + * + * @param {Array} ids + * List of all point ids. + * + * @return {Highcharts.Dictionary>} + * Map from parent id to children index in data + */ + var getListOfParents = function (data, ids) { + var listOfParents = data.reduce(function (prev, curr) { + var parent = pick(curr.parent, ''); + if (typeof prev[parent] === 'undefined') { + prev[parent] = []; + } + prev[parent].push(curr); + return prev; + }, {}), parents = Object.keys(listOfParents); + // If parent does not exist, hoist parent to root of tree. + parents.forEach(function (parent, list) { + var children = listOfParents[parent]; + if ((parent !== '') && (ids.indexOf(parent) === -1)) { + children.forEach(function (child) { + list[''].push(child); + }); + delete list[parent]; + } + }); + return listOfParents; + }; + var getNode = function (id, parent, level, data, mapOfIdToChildren, options) { + var descendants = 0, height = 0, after = options && options.after, before = options && options.before, node = { + data: data, + depth: level - 1, + id: id, + level: level, + parent: parent + }, start, end, children; + // Allow custom logic before the children has been created. + if (typeof before === 'function') { + before(node, options); + } + // Call getNode recursively on the children. Calulate the height of the + // node, and the number of descendants. + children = ((mapOfIdToChildren[id] || [])).map(function (child) { + var node = getNode(child.id, id, (level + 1), child, mapOfIdToChildren, options), childStart = child.start, childEnd = (child.milestone === true ? + childStart : + child.end); + // Start should be the lowest child.start. + start = ((!isNumber(start) || childStart < start) ? + childStart : + start); + // End should be the largest child.end. + // If child is milestone, then use start as end. + end = ((!isNumber(end) || childEnd > end) ? + childEnd : + end); + descendants = descendants + 1 + node.descendants; + height = Math.max(node.height + 1, height); + return node; + }); + // Calculate start and end for point if it is not already explicitly set. + if (data) { + data.start = pick(data.start, start); + data.end = pick(data.end, end); + } + extend(node, { + children: children, + descendants: descendants, + height: height + }); + // Allow custom logic after the children has been created. + if (typeof after === 'function') { + after(node, options); + } + return node; + }; + var getTree = function (data, options) { + var ids = data.map(function (d) { + return d.id; + }), mapOfIdToChildren = getListOfParents(data, ids); + return getNode('', null, 1, null, mapOfIdToChildren, options); + }; + var Tree = { + getListOfParents: getListOfParents, + getNode: getNode, + getTree: getTree + }; + + return Tree; + }); + _registerModule(_modules, 'parts-gantt/TreeGridTick.js', [_modules['parts/Utilities.js']], function (U) { + /* * + * + * (c) 2016 Highsoft AS + * Authors: Jon Arild Nygard + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, defined = U.defined, isObject = U.isObject, isNumber = U.isNumber, pick = U.pick, wrap = U.wrap; + /** + * @private + */ + var TreeGridTick; + (function (TreeGridTick) { + /* * + * + * Interfaces + * + * */ + /* * + * + * Variables + * + * */ + var applied = false; + /* * + * + * Functions + * + * */ + /** + * @private + */ + function compose(TickClass) { + if (!applied) { + addEvent(TickClass, 'init', onInit); + wrap(TickClass.prototype, 'getLabelPosition', wrapGetLabelPosition); + wrap(TickClass.prototype, 'renderLabel', wrapRenderLabel); + // backwards compatibility + TickClass.prototype.collapse = function (redraw) { + this.treeGrid.collapse(redraw); + }; + TickClass.prototype.expand = function (redraw) { + this.treeGrid.expand(redraw); + }; + TickClass.prototype.toggleCollapse = function (redraw) { + this.treeGrid.toggleCollapse(redraw); + }; + applied = true; + } + } + TreeGridTick.compose = compose; + /** + * @private + */ + function onInit() { + var tick = this; + if (!tick.treeGrid) { + tick.treeGrid = new Additions(tick); + } + } + /** + * @private + */ + function onTickHover(label) { + label.addClass('highcharts-treegrid-node-active'); + if (!label.renderer.styledMode) { + label.css({ + textDecoration: 'underline' + }); + } + } + /** + * @private + */ + function onTickHoverExit(label, options) { + var css = defined(options.style) ? options.style : {}; + label.removeClass('highcharts-treegrid-node-active'); + if (!label.renderer.styledMode) { + label.css({ textDecoration: css.textDecoration }); + } + } + /** + * @private + */ + function renderLabelIcon(tick, params) { + var treeGrid = tick.treeGrid, isNew = !treeGrid.labelIcon, renderer = params.renderer, labelBox = params.xy, options = params.options, width = options.width, height = options.height, iconCenter = { + x: labelBox.x - (width / 2) - options.padding, + y: labelBox.y - (height / 2) + }, rotation = params.collapsed ? 90 : 180, shouldRender = params.show && isNumber(iconCenter.y); + var icon = treeGrid.labelIcon; + if (!icon) { + treeGrid.labelIcon = icon = renderer + .path(renderer.symbols[options.type](options.x, options.y, width, height)) + .addClass('highcharts-label-icon') + .add(params.group); + } + // Set the new position, and show or hide + if (!shouldRender) { + icon.attr({ y: -9999 }); // #1338 + } + // Presentational attributes + if (!renderer.styledMode) { + icon + .attr({ + 'stroke-width': 1, + 'fill': pick(params.color, '#666666') + }) + .css({ + cursor: 'pointer', + stroke: options.lineColor, + strokeWidth: options.lineWidth + }); + } + // Update the icon positions + icon[isNew ? 'attr' : 'animate']({ + translateX: iconCenter.x, + translateY: iconCenter.y, + rotation: rotation + }); + } + /** + * @private + */ + function wrapGetLabelPosition(proceed, x, y, label, horiz, labelOptions, tickmarkOffset, index, step) { + var tick = this, lbOptions = pick(tick.options && tick.options.labels, labelOptions), pos = tick.pos, axis = tick.axis, options = axis.options, isTreeGrid = options.type === 'treegrid', result = proceed.apply(tick, [x, y, label, horiz, lbOptions, tickmarkOffset, index, step]); + var symbolOptions, indentation, mapOfPosToGridNode, node, level; + if (isTreeGrid) { + symbolOptions = (lbOptions && isObject(lbOptions.symbol, true) ? + lbOptions.symbol : + {}); + indentation = (lbOptions && isNumber(lbOptions.indentation) ? + lbOptions.indentation : + 0); + mapOfPosToGridNode = axis.treeGrid.mapOfPosToGridNode; + node = mapOfPosToGridNode && mapOfPosToGridNode[pos]; + level = (node && node.depth) || 1; + result.x += ( + // Add space for symbols + ((symbolOptions.width) + (symbolOptions.padding * 2)) + + // Apply indentation + ((level - 1) * indentation)); + } + return result; + } + /** + * @private + */ + function wrapRenderLabel(proceed) { + var tick = this, pos = tick.pos, axis = tick.axis, label = tick.label, mapOfPosToGridNode = axis.treeGrid.mapOfPosToGridNode, options = axis.options, labelOptions = pick(tick.options && tick.options.labels, options && options.labels), symbolOptions = (labelOptions && isObject(labelOptions.symbol, true) ? + labelOptions.symbol : + {}), node = mapOfPosToGridNode && mapOfPosToGridNode[pos], level = node && node.depth, isTreeGrid = options.type === 'treegrid', shouldRender = axis.tickPositions.indexOf(pos) > -1, prefixClassName = 'highcharts-treegrid-node-', styledMode = axis.chart.styledMode; + var collapsed, addClassName, removeClassName; + if (isTreeGrid && node) { + // Add class name for hierarchical styling. + if (label && + label.element) { + label.addClass(prefixClassName + 'level-' + level); + } + } + proceed.apply(tick, Array.prototype.slice.call(arguments, 1)); + if (isTreeGrid && + label && + label.element && + node && + node.descendants && + node.descendants > 0) { + collapsed = axis.treeGrid.isCollapsed(node); + renderLabelIcon(tick, { + color: !styledMode && label.styles && label.styles.color || '', + collapsed: collapsed, + group: label.parentGroup, + options: symbolOptions, + renderer: label.renderer, + show: shouldRender, + xy: label.xy + }); + // Add class name for the node. + addClassName = prefixClassName + + (collapsed ? 'collapsed' : 'expanded'); + removeClassName = prefixClassName + + (collapsed ? 'expanded' : 'collapsed'); + label + .addClass(addClassName) + .removeClass(removeClassName); + if (!styledMode) { + label.css({ + cursor: 'pointer' + }); + } + // Add events to both label text and icon + [label, tick.treeGrid.labelIcon].forEach(function (object) { + if (object && !object.attachedTreeGridEvents) { + // On hover + addEvent(object.element, 'mouseover', function () { + onTickHover(label); + }); + // On hover out + addEvent(object.element, 'mouseout', function () { + onTickHoverExit(label, labelOptions); + }); + addEvent(object.element, 'click', function () { + tick.treeGrid.toggleCollapse(); + }); + object.attachedTreeGridEvents = true; + } + }); + } + } + /* * + * + * Classes + * + * */ + /** + * @private + * @class + */ + var Additions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + /** + * @private + */ + function Additions(tick) { + this.tick = tick; + } + /* * + * + * Functions + * + * */ + /** + * Collapse the grid cell. Used when axis is of type treegrid. + * + * @see gantt/treegrid-axis/collapsed-dynamically/demo.js + * + * @private + * @function Highcharts.Tick#collapse + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call to + * {@link Highcharts.Chart#redraw} + */ + Additions.prototype.collapse = function (redraw) { + var tick = this.tick, axis = tick.axis, brokenAxis = axis.brokenAxis; + if (brokenAxis && + axis.treeGrid.mapOfPosToGridNode) { + var pos = tick.pos, node = axis.treeGrid.mapOfPosToGridNode[pos], breaks = axis.treeGrid.collapse(node); + brokenAxis.setBreaks(breaks, pick(redraw, true)); + } + }; + /** + * Expand the grid cell. Used when axis is of type treegrid. + * + * @see gantt/treegrid-axis/collapsed-dynamically/demo.js + * + * @private + * @function Highcharts.Tick#expand + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call to + * {@link Highcharts.Chart#redraw} + */ + Additions.prototype.expand = function (redraw) { + var tick = this.tick, axis = tick.axis, brokenAxis = axis.brokenAxis; + if (brokenAxis && + axis.treeGrid.mapOfPosToGridNode) { + var pos = tick.pos, node = axis.treeGrid.mapOfPosToGridNode[pos], breaks = axis.treeGrid.expand(node); + brokenAxis.setBreaks(breaks, pick(redraw, true)); + } + }; + /** + * Toggle the collapse/expand state of the grid cell. Used when axis is + * of type treegrid. + * + * @see gantt/treegrid-axis/collapsed-dynamically/demo.js + * + * @private + * @function Highcharts.Tick#toggleCollapse + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call to + * {@link Highcharts.Chart#redraw} + */ + Additions.prototype.toggleCollapse = function (redraw) { + var tick = this.tick, axis = tick.axis, brokenAxis = axis.brokenAxis; + if (brokenAxis && + axis.treeGrid.mapOfPosToGridNode) { + var pos = tick.pos, node = axis.treeGrid.mapOfPosToGridNode[pos], breaks = axis.treeGrid.toggleCollapse(node); + brokenAxis.setBreaks(breaks, pick(redraw, true)); + } + }; + return Additions; + }()); + TreeGridTick.Additions = Additions; + })(TreeGridTick || (TreeGridTick = {})); + + return TreeGridTick; + }); + _registerModule(_modules, 'mixins/tree-series.js', [_modules['parts/Color.js'], _modules['parts/Utilities.js']], function (Color, U) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, merge = U.merge, pick = U.pick; + var isBoolean = function (x) { + return typeof x === 'boolean'; + }, isFn = function (x) { + return typeof x === 'function'; + }; + /* eslint-disable valid-jsdoc */ + /** + * @todo Combine buildTree and buildNode with setTreeValues + * @todo Remove logic from Treemap and make it utilize this mixin. + * @private + */ + var setTreeValues = function setTreeValues(tree, options) { + var before = options.before, idRoot = options.idRoot, mapIdToNode = options.mapIdToNode, nodeRoot = mapIdToNode[idRoot], levelIsConstant = (isBoolean(options.levelIsConstant) ? + options.levelIsConstant : + true), points = options.points, point = points[tree.i], optionsPoint = point && point.options || {}, childrenTotal = 0, children = [], value; + extend(tree, { + levelDynamic: tree.level - (levelIsConstant ? 0 : nodeRoot.level), + name: pick(point && point.name, ''), + visible: (idRoot === tree.id || + (isBoolean(options.visible) ? options.visible : false)) + }); + if (isFn(before)) { + tree = before(tree, options); + } + // First give the children some values + tree.children.forEach(function (child, i) { + var newOptions = extend({}, options); + extend(newOptions, { + index: i, + siblings: tree.children.length, + visible: tree.visible + }); + child = setTreeValues(child, newOptions); + children.push(child); + if (child.visible) { + childrenTotal += child.val; + } + }); + tree.visible = childrenTotal > 0 || tree.visible; + // Set the values + value = pick(optionsPoint.value, childrenTotal); + extend(tree, { + children: children, + childrenTotal: childrenTotal, + isLeaf: tree.visible && !childrenTotal, + val: value + }); + return tree; + }; + /** + * @private + */ + var getColor = function getColor(node, options) { + var index = options.index, mapOptionsToLevel = options.mapOptionsToLevel, parentColor = options.parentColor, parentColorIndex = options.parentColorIndex, series = options.series, colors = options.colors, siblings = options.siblings, points = series.points, getColorByPoint, chartOptionsChart = series.chart.options.chart, point, level, colorByPoint, colorIndexByPoint, color, colorIndex; + /** + * @private + */ + function variation(color) { + var colorVariation = level && level.colorVariation; + if (colorVariation) { + if (colorVariation.key === 'brightness') { + return Color.parse(color).brighten(colorVariation.to * (index / siblings)).get(); + } + } + return color; + } + if (node) { + point = points[node.i]; + level = mapOptionsToLevel[node.level] || {}; + getColorByPoint = point && level.colorByPoint; + if (getColorByPoint) { + colorIndexByPoint = point.index % (colors ? + colors.length : + chartOptionsChart.colorCount); + colorByPoint = colors && colors[colorIndexByPoint]; + } + // Select either point color, level color or inherited color. + if (!series.chart.styledMode) { + color = pick(point && point.options.color, level && level.color, colorByPoint, parentColor && variation(parentColor), series.color); + } + colorIndex = pick(point && point.options.colorIndex, level && level.colorIndex, colorIndexByPoint, parentColorIndex, options.colorIndex); + } + return { + color: color, + colorIndex: colorIndex + }; + }; + /** + * Creates a map from level number to its given options. + * + * @private + * @function getLevelOptions + * @param {object} params + * Object containing parameters. + * - `defaults` Object containing default options. The default options + * are merged with the userOptions to get the final options for a + * specific level. + * - `from` The lowest level number. + * - `levels` User options from series.levels. + * - `to` The highest level number. + * @return {Highcharts.Dictionary|null} + * Returns a map from level number to its given options. + */ + var getLevelOptions = function getLevelOptions(params) { + var result = null, defaults, converted, i, from, to, levels; + if (isObject(params)) { + result = {}; + from = isNumber(params.from) ? params.from : 1; + levels = params.levels; + converted = {}; + defaults = isObject(params.defaults) ? params.defaults : {}; + if (isArray(levels)) { + converted = levels.reduce(function (obj, item) { + var level, levelIsConstant, options; + if (isObject(item) && isNumber(item.level)) { + options = merge({}, item); + levelIsConstant = (isBoolean(options.levelIsConstant) ? + options.levelIsConstant : + defaults.levelIsConstant); + // Delete redundant properties. + delete options.levelIsConstant; + delete options.level; + // Calculate which level these options apply to. + level = item.level + (levelIsConstant ? 0 : from - 1); + if (isObject(obj[level])) { + extend(obj[level], options); + } + else { + obj[level] = options; + } + } + return obj; + }, {}); + } + to = isNumber(params.to) ? params.to : 1; + for (i = 0; i <= to; i++) { + result[i] = merge({}, defaults, isObject(converted[i]) ? converted[i] : {}); + } + } + return result; + }; + /** + * Update the rootId property on the series. Also makes sure that it is + * accessible to exporting. + * + * @private + * @function updateRootId + * + * @param {object} series + * The series to operate on. + * + * @return {string} + * Returns the resulting rootId after update. + */ + var updateRootId = function (series) { + var rootId, options; + if (isObject(series)) { + // Get the series options. + options = isObject(series.options) ? series.options : {}; + // Calculate the rootId. + rootId = pick(series.rootNode, options.rootId, ''); + // Set rootId on series.userOptions to pick it up in exporting. + if (isObject(series.userOptions)) { + series.userOptions.rootId = rootId; + } + // Set rootId on series to pick it up on next update. + series.rootNode = rootId; + } + return rootId; + }; + var result = { + getColor: getColor, + getLevelOptions: getLevelOptions, + setTreeValues: setTreeValues, + updateRootId: updateRootId + }; + + return result; + }); + _registerModule(_modules, 'parts-gantt/GridAxis.js', [_modules['parts/Axis.js'], _modules['parts/Globals.js'], _modules['parts/Tick.js'], _modules['parts/Utilities.js']], function (Axis, H, Tick, U) { + /* * + * + * (c) 2016 Highsoft AS + * Authors: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, defined = U.defined, erase = U.erase, find = U.find, isArray = U.isArray, isNumber = U.isNumber, merge = U.merge, pick = U.pick, timeUnits = U.timeUnits, wrap = U.wrap; + var argsToArray = function (args) { + return Array.prototype.slice.call(args, 1); + }, dateFormat = H.dateFormat, isObject = function (x) { + // Always use strict mode + return U.isObject(x, true); + }, Chart = H.Chart; + var applyGridOptions = function applyGridOptions(axis) { + var options = axis.options; + // Center-align by default + if (!options.labels) { + options.labels = {}; + } + options.labels.align = pick(options.labels.align, 'center'); + // @todo: Check against tickLabelPlacement between/on etc + /* Prevents adding the last tick label if the axis is not a category + axis. + Since numeric labels are normally placed at starts and ends of a + range of value, and this module makes the label point at the value, + an "extra" label would appear. */ + if (!axis.categories) { + options.showLastLabel = false; + } + // Prevents rotation of labels when squished, as rotating them would not + // help. + axis.labelRotation = 0; + options.labels.rotation = 0; + }; + /** + * Set grid options for the axis labels. Requires Highcharts Gantt. + * + * @since 6.2.0 + * @product gantt + * @apioption xAxis.grid + */ + /** + * Enable grid on the axis labels. Defaults to true for Gantt charts. + * + * @type {boolean} + * @default true + * @since 6.2.0 + * @product gantt + * @apioption xAxis.grid.enabled + */ + /** + * Set specific options for each column (or row for horizontal axes) in the + * grid. Each extra column/row is its own axis, and the axis options can be set + * here. + * + * @sample gantt/demo/left-axis-table + * Left axis as a table + * + * @type {Array} + * @apioption xAxis.grid.columns + */ + /** + * Set border color for the label grid lines. + * + * @type {Highcharts.ColorString} + * @apioption xAxis.grid.borderColor + */ + /** + * Set border width of the label grid lines. + * + * @type {number} + * @default 1 + * @apioption xAxis.grid.borderWidth + */ + /** + * Set cell height for grid axis labels. By default this is calculated from font + * size. This option only applies to horizontal axes. + * + * @sample gantt/grid-axis/cellheight + * Gant chart with custom cell height + * @type {number} + * @apioption xAxis.grid.cellHeight + */ + ''; // detach doclets above + /** + * Get the largest label width and height. + * + * @private + * @function Highcharts.Axis#getMaxLabelDimensions + * + * @param {Highcharts.Dictionary} ticks + * All the ticks on one axis. + * + * @param {Array} tickPositions + * All the tick positions on one axis. + * + * @return {Highcharts.SizeObject} + * Object containing the properties height and width. + * + * @todo Move this to the generic axis implementation, as it is used there. + */ + Axis.prototype.getMaxLabelDimensions = function (ticks, tickPositions) { + var dimensions = { + width: 0, + height: 0 + }; + tickPositions.forEach(function (pos) { + var tick = ticks[pos], tickHeight = 0, tickWidth = 0, label; + if (isObject(tick)) { + label = isObject(tick.label) ? tick.label : {}; + // Find width and height of tick + tickHeight = label.getBBox ? label.getBBox().height : 0; + if (label.textStr && !isNumber(label.textPxLength)) { + label.textPxLength = label.getBBox().width; + } + tickWidth = isNumber(label.textPxLength) ? + // Math.round ensures crisp lines + Math.round(label.textPxLength) : + 0; + // Update the result if width and/or height are larger + dimensions.height = Math.max(tickHeight, dimensions.height); + dimensions.width = Math.max(tickWidth, dimensions.width); + } + }); + return dimensions; + }; + // Adds week date format + H.dateFormats.W = function (timestamp) { + var d = new this.Date(timestamp); + var firstDay = (this.get('Day', d) + 6) % 7; + var thursday = new this.Date(d.valueOf()); + this.set('Date', thursday, this.get('Date', d) - firstDay + 3); + var firstThursday = new this.Date(this.get('FullYear', thursday), 0, 1); + if (this.get('Day', firstThursday) !== 4) { + this.set('Month', d, 0); + this.set('Date', d, 1 + (11 - this.get('Day', firstThursday)) % 7); + } + return (1 + + Math.floor((thursday.valueOf() - firstThursday.valueOf()) / 604800000)).toString(); + }; + // First letter of the day of the week, e.g. 'M' for 'Monday'. + H.dateFormats.E = function (timestamp) { + return dateFormat('%a', timestamp, true).charAt(0); + }; + /* eslint-disable no-invalid-this */ + addEvent(Chart, 'afterSetChartSize', function () { + this.axes.forEach(function (axis) { + (axis.grid && axis.grid.columns || []).forEach(function (column) { + column.setAxisSize(); + column.setAxisTranslation(); + }); + }); + }); + // Center tick labels in cells. + addEvent(Tick, 'afterGetLabelPosition', function (e) { + var tick = this, label = tick.label, axis = tick.axis, reversed = axis.reversed, chart = axis.chart, options = axis.options, gridOptions = options.grid || {}, labelOpts = axis.options.labels, align = labelOpts.align, + // verticalAlign is currently not supported for axis.labels. + verticalAlign = 'middle', // labelOpts.verticalAlign, + side = GridAxis.Side[axis.side], tickmarkOffset = e.tickmarkOffset, tickPositions = axis.tickPositions, tickPos = tick.pos - tickmarkOffset, nextTickPos = (isNumber(tickPositions[e.index + 1]) ? + tickPositions[e.index + 1] - tickmarkOffset : + axis.max + tickmarkOffset), tickSize = axis.tickSize('tick'), tickWidth = tickSize ? tickSize[0] : 0, crispCorr = tickSize ? tickSize[1] / 2 : 0, labelHeight, lblMetrics, lines, bottom, top, left, right; + // Only center tick labels in grid axes + if (gridOptions.enabled === true) { + // Calculate top and bottom positions of the cell. + if (side === 'top') { + bottom = axis.top + axis.offset; + top = bottom - tickWidth; + } + else if (side === 'bottom') { + top = chart.chartHeight - axis.bottom + axis.offset; + bottom = top + tickWidth; + } + else { + bottom = axis.top + axis.len - axis.translate(reversed ? nextTickPos : tickPos); + top = axis.top + axis.len - axis.translate(reversed ? tickPos : nextTickPos); + } + // Calculate left and right positions of the cell. + if (side === 'right') { + left = chart.chartWidth - axis.right + axis.offset; + right = left + tickWidth; + } + else if (side === 'left') { + right = axis.left + axis.offset; + left = right - tickWidth; + } + else { + left = Math.round(axis.left + axis.translate(reversed ? nextTickPos : tickPos)) - crispCorr; + right = Math.round(axis.left + axis.translate(reversed ? tickPos : nextTickPos)) - crispCorr; + } + tick.slotWidth = right - left; + // Calculate the positioning of the label based on + // alignment. + e.pos.x = (align === 'left' ? + left : + align === 'right' ? + right : + left + ((right - left) / 2) // default to center + ); + e.pos.y = (verticalAlign === 'top' ? + top : + verticalAlign === 'bottom' ? + bottom : + top + ((bottom - top) / 2) // default to middle + ); + lblMetrics = chart.renderer.fontMetrics(labelOpts.style.fontSize, label.element); + labelHeight = label.getBBox().height; + // Adjustment to y position to align the label correctly. + // Would be better to have a setter or similar for this. + if (!labelOpts.useHTML) { + lines = Math.round(labelHeight / lblMetrics.h); + e.pos.y += ( + // Center the label + // TODO: why does this actually center the label? + ((lblMetrics.b - (lblMetrics.h - lblMetrics.f)) / 2) + + // Adjust for height of additional lines. + -(((lines - 1) * lblMetrics.h) / 2)); + } + else { + e.pos.y += ( + // Readjust yCorr in htmlUpdateTransform + lblMetrics.b + + // Adjust for height of html label + -(labelHeight / 2)); + } + e.pos.x += (axis.horiz && labelOpts.x || 0); + } + }); + /* eslint-enable no-invalid-this */ + /** + * Additions for grid axes. + * @private + * @class + */ + var GridAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function GridAxisAdditions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Checks if an axis is the outer axis in its dimension. Since + * axes are placed outwards in order, the axis with the highest + * index is the outermost axis. + * + * Example: If there are multiple x-axes at the top of the chart, + * this function returns true if the axis supplied is the last + * of the x-axes. + * + * @private + * + * @return {boolean} + * True if the axis is the outermost axis in its dimension; false if + * not. + */ + GridAxisAdditions.prototype.isOuterAxis = function () { + var axis = this.axis; + var chart = axis.chart; + var columnIndex = axis.grid.columnIndex; + var columns = (axis.linkedParent && axis.linkedParent.grid.columns || + axis.grid.columns); + var parentAxis = columnIndex ? axis.linkedParent : axis; + var thisIndex = -1, lastIndex = 0; + chart[axis.coll].forEach(function (otherAxis, index) { + if (otherAxis.side === axis.side && !otherAxis.options.isInternal) { + lastIndex = index; + if (otherAxis === parentAxis) { + // Get the index of the axis in question + thisIndex = index; + } + } + }); + return (lastIndex === thisIndex && + (isNumber(columnIndex) ? columns.length === columnIndex : true)); + }; + return GridAxisAdditions; + }()); + /** + * Axis with grid support. + * @private + * @class + */ + var GridAxis = /** @class */ (function () { + function GridAxis() { + } + /* * + * + * Static Functions + * + * */ + /* eslint-disable valid-jsdoc */ + /** + * Extends axis class with grid support. + * @private + */ + GridAxis.compose = function (AxisClass) { + Axis.keepProps.push('grid'); + wrap(AxisClass.prototype, 'unsquish', GridAxis.wrapUnsquish); + // Add event handlers + addEvent(AxisClass, 'init', GridAxis.onInit); + addEvent(AxisClass, 'afterGetOffset', GridAxis.onAfterGetOffset); + addEvent(AxisClass, 'afterGetTitlePosition', GridAxis.onAfterGetTitlePosition); + addEvent(AxisClass, 'afterInit', GridAxis.onAfterInit); + addEvent(AxisClass, 'afterRender', GridAxis.onAfterRender); + addEvent(AxisClass, 'afterSetAxisTranslation', GridAxis.onAfterSetAxisTranslation); + addEvent(AxisClass, 'afterSetOptions', GridAxis.onAfterSetOptions); + addEvent(AxisClass, 'afterSetOptions', GridAxis.onAfterSetOptions2); + addEvent(AxisClass, 'afterSetScale', GridAxis.onAfterSetScale); + addEvent(AxisClass, 'afterTickSize', GridAxis.onAfterTickSize); + addEvent(AxisClass, 'trimTicks', GridAxis.onTrimTicks); + addEvent(AxisClass, 'destroy', GridAxis.onDestroy); + }; + /** + * Handle columns and getOffset. + * @private + */ + GridAxis.onAfterGetOffset = function () { + var grid = this.grid; + (grid && grid.columns || []).forEach(function (column) { + column.getOffset(); + }); + }; + /** + * @private + */ + GridAxis.onAfterGetTitlePosition = function (e) { + var axis = this; + var options = axis.options; + var gridOptions = options.grid || {}; + if (gridOptions.enabled === true) { + // compute anchor points for each of the title align options + var title = axis.axisTitle, axisHeight = axis.height, horiz = axis.horiz, axisLeft = axis.left, offset = axis.offset, opposite = axis.opposite, _a = axis.options.title, axisTitleOptions = _a === void 0 ? {} : _a, axisTop = axis.top, axisWidth = axis.width; + var tickSize = axis.tickSize(); + var titleWidth = title && title.getBBox().width; + var xOption = axisTitleOptions.x || 0; + var yOption = axisTitleOptions.y || 0; + var titleMargin = pick(axisTitleOptions.margin, horiz ? 5 : 10); + var titleFontSize = axis.chart.renderer.fontMetrics(axisTitleOptions.style && + axisTitleOptions.style.fontSize, title).f; + var crispCorr = tickSize ? tickSize[0] / 2 : 0; + // TODO account for alignment + // the position in the perpendicular direction of the axis + var offAxis = ((horiz ? axisTop + axisHeight : axisLeft) + + (horiz ? 1 : -1) * // horizontal axis reverses the margin + (opposite ? -1 : 1) * // so does opposite axes + crispCorr + + (axis.side === GridAxis.Side.bottom ? titleFontSize : 0)); + e.titlePosition.x = horiz ? + axisLeft - titleWidth / 2 - titleMargin + xOption : + offAxis + (opposite ? axisWidth : 0) + offset + xOption; + e.titlePosition.y = horiz ? + (offAxis - + (opposite ? axisHeight : 0) + + (opposite ? titleFontSize : -titleFontSize) / 2 + + offset + + yOption) : + axisTop - titleMargin + yOption; + } + }; + /** + * @private + */ + GridAxis.onAfterInit = function () { + var axis = this; + var chart = axis.chart, _a = axis.options.grid, gridOptions = _a === void 0 ? {} : _a, userOptions = axis.userOptions; + if (gridOptions.enabled) { + applyGridOptions(axis); + /* eslint-disable no-invalid-this */ + // TODO: wrap the axis instead + wrap(axis, 'labelFormatter', function (proceed) { + var _a = this, axis = _a.axis, value = _a.value; + var tickPos = axis.tickPositions; + var series = (axis.isLinked ? + axis.linkedParent : + axis).series[0]; + var isFirst = value === tickPos[0]; + var isLast = value === tickPos[tickPos.length - 1]; + var point = series && find(series.options.data, function (p) { + return p[axis.isXAxis ? 'x' : 'y'] === value; + }); + // Make additional properties available for the + // formatter + this.isFirst = isFirst; + this.isLast = isLast; + this.point = point; + // Call original labelFormatter + return proceed.call(this); + }); + /* eslint-enable no-invalid-this */ + } + if (gridOptions.columns) { + var columns = axis.grid.columns = [], columnIndex = axis.grid.columnIndex = 0; + // Handle columns, each column is a grid axis + while (++columnIndex < gridOptions.columns.length) { + var columnOptions = merge(userOptions, gridOptions.columns[gridOptions.columns.length - columnIndex - 1], { + linkedTo: 0, + // Force to behave like category axis + type: 'category' + }); + delete columnOptions.grid.columns; // Prevent recursion + var column = new Axis(axis.chart, columnOptions); + column.grid.isColumn = true; + column.grid.columnIndex = columnIndex; + // Remove column axis from chart axes array, and place it + // in the columns array. + erase(chart.axes, column); + erase(chart[axis.coll], column); + columns.push(column); + } + } + }; + /** + * Draw an extra line on the far side of the outermost axis, + * creating floor/roof/wall of a grid. And some padding. + * ``` + * Make this: + * (axis.min) __________________________ (axis.max) + * | | | | | + * Into this: + * (axis.min) __________________________ (axis.max) + * ___|____|____|____|____|__ + * ``` + * @private + */ + GridAxis.onAfterRender = function () { + var axis = this; + var grid = axis.grid; + var options = axis.options; + var renderer = axis.chart.renderer; + var gridOptions = options.grid || {}; + var yStartIndex, yEndIndex, xStartIndex, xEndIndex; + if (gridOptions.enabled === true) { + // @todo acutual label padding (top, bottom, left, right) + axis.maxLabelDimensions = axis.getMaxLabelDimensions(axis.ticks, axis.tickPositions); + // Remove right wall before rendering if updating + if (axis.rightWall) { + axis.rightWall.destroy(); + } + /* + Draw an extra axis line on outer axes + > + Make this: |______|______|______|___ + + > _________________________ + Into this: |______|______|______|__| + */ + if (axis.grid && axis.grid.isOuterAxis() && axis.axisLine) { + var lineWidth = options.lineWidth; + if (lineWidth) { + var linePath = axis.getLinePath(lineWidth); + var startPoint = linePath[0]; + var endPoint = linePath[1]; + // Negate distance if top or left axis + // Subtract 1px to draw the line at the end of the tick + var tickLength = (axis.tickSize('tick') || [1])[0]; + var distance = (tickLength - 1) * ((axis.side === GridAxis.Side.top || + axis.side === GridAxis.Side.left) ? -1 : 1); + // If axis is horizontal, reposition line path vertically + if (startPoint[0] === 'M' && endPoint[0] === 'L') { + if (axis.horiz) { + startPoint[2] += distance; + endPoint[2] += distance; + } + else { + // If axis is vertical, reposition line path + // horizontally + startPoint[1] += distance; + endPoint[1] += distance; + } + } + if (!axis.grid.axisLineExtra) { + axis.grid.axisLineExtra = renderer + .path(linePath) + .attr({ + zIndex: 7 + }) + .addClass('highcharts-axis-line') + .add(axis.axisGroup); + if (!renderer.styledMode) { + axis.grid.axisLineExtra.attr({ + stroke: options.lineColor, + 'stroke-width': lineWidth + }); + } + } + else { + axis.grid.axisLineExtra.animate({ + d: linePath + }); + } + // show or hide the line depending on + // options.showEmpty + axis.axisLine[axis.showAxis ? 'show' : 'hide'](true); + } + } + (grid && grid.columns || []).forEach(function (column) { + column.render(); + }); + } + }; + /** + * @private + */ + GridAxis.onAfterSetAxisTranslation = function () { + var axis = this; + var tickInfo = axis.tickPositions && axis.tickPositions.info; + var options = axis.options; + var gridOptions = options.grid || {}; + var userLabels = axis.userOptions.labels || {}; + if (axis.horiz) { + if (gridOptions.enabled === true) { + axis.series.forEach(function (series) { + series.options.pointRange = 0; + }); + } + // Lower level time ticks, like hours or minutes, represent + // points in time and not ranges. These should be aligned + // left in the grid cell by default. The same applies to + // years of higher order. + if (tickInfo && + options.dateTimeLabelFormats && + options.labels && + !defined(userLabels.align) && + (options.dateTimeLabelFormats[tickInfo.unitName].range === false || + tickInfo.count > 1 // years + )) { + options.labels.align = 'left'; + if (!defined(userLabels.x)) { + options.labels.x = 3; + } + } + } + }; + /** + * Creates a left and right wall on horizontal axes: + * - Places leftmost tick at the start of the axis, to create a left + * wall + * - Ensures that the rightmost tick is at the end of the axis, to + * create a right wall. + * @private + */ + GridAxis.onAfterSetOptions = function (e) { + var options = this.options, userOptions = e.userOptions, gridAxisOptions, gridOptions = ((options && isObject(options.grid)) ? options.grid : {}); + if (gridOptions.enabled === true) { + // Merge the user options into default grid axis options so + // that when a user option is set, it takes presedence. + gridAxisOptions = merge(true, { + className: ('highcharts-grid-axis ' + (userOptions.className || '')), + dateTimeLabelFormats: { + hour: { + list: ['%H:%M', '%H'] + }, + day: { + list: ['%A, %e. %B', '%a, %e. %b', '%E'] + }, + week: { + list: ['Week %W', 'W%W'] + }, + month: { + list: ['%B', '%b', '%o'] + } + }, + grid: { + borderWidth: 1 + }, + labels: { + padding: 2, + style: { + fontSize: '13px' + } + }, + margin: 0, + title: { + text: null, + reserveSpace: false, + rotation: 0 + }, + // In a grid axis, only allow one unit of certain types, + // for example we shouln't have one grid cell spanning + // two days. + units: [[ + 'millisecond', + [1, 10, 100] + ], [ + 'second', + [1, 10] + ], [ + 'minute', + [1, 5, 15] + ], [ + 'hour', + [1, 6] + ], [ + 'day', + [1] + ], [ + 'week', + [1] + ], [ + 'month', + [1] + ], [ + 'year', + null + ]] + }, userOptions); + // X-axis specific options + if (this.coll === 'xAxis') { + // For linked axes, tickPixelInterval is used only if + // the tickPositioner below doesn't run or returns + // undefined (like multiple years) + if (defined(userOptions.linkedTo) && + !defined(userOptions.tickPixelInterval)) { + gridAxisOptions.tickPixelInterval = 350; + } + // For the secondary grid axis, use the primary axis' + // tick intervals and return ticks one level higher. + if ( + // Check for tick pixel interval in options + !defined(userOptions.tickPixelInterval) && + // Only for linked axes + defined(userOptions.linkedTo) && + !defined(userOptions.tickPositioner) && + !defined(userOptions.tickInterval)) { + gridAxisOptions.tickPositioner = function (min, max) { + var parentInfo = (this.linkedParent && + this.linkedParent.tickPositions && + this.linkedParent.tickPositions.info); + if (parentInfo) { + var unitIdx, count, unitName, i, units = gridAxisOptions.units, unitRange; + for (i = 0; i < units.length; i++) { + if (units[i][0] === + parentInfo.unitName) { + unitIdx = i; + break; + } + } + // Get the first allowed count on the next + // unit. + if (units[unitIdx + 1]) { + unitName = units[unitIdx + 1][0]; + count = + (units[unitIdx + 1][1] || [1])[0]; + // In case the base X axis shows years, make + // the secondary axis show ten times the + // years (#11427) + } + else if (parentInfo.unitName === 'year') { + unitName = 'year'; + count = parentInfo.count * 10; + } + unitRange = timeUnits[unitName]; + this.tickInterval = unitRange * count; + return this.getTimeTicks({ + unitRange: unitRange, + count: count, + unitName: unitName + }, min, max, this.options.startOfWeek); + } + }; + } + } + // Now merge the combined options into the axis options + merge(true, this.options, gridAxisOptions); + if (this.horiz) { + /* _________________________ + Make this: ___|_____|_____|_____|__| + ^ ^ + _________________________ + Into this: |_____|_____|_____|_____| + ^ ^ */ + options.minPadding = pick(userOptions.minPadding, 0); + options.maxPadding = pick(userOptions.maxPadding, 0); + } + // If borderWidth is set, then use its value for tick and + // line width. + if (isNumber(options.grid.borderWidth)) { + options.tickWidth = options.lineWidth = gridOptions.borderWidth; + } + } + }; + /** + * @private + */ + GridAxis.onAfterSetOptions2 = function (e) { + var axis = this; + var userOptions = e.userOptions; + var gridOptions = userOptions && userOptions.grid || {}; + var columns = gridOptions.columns; + // Add column options to the parent axis. Children has their column + // options set on init in onGridAxisAfterInit. + if (gridOptions.enabled && columns) { + merge(true, axis.options, columns[columns.length - 1]); + } + }; + /** + * Handle columns and setScale. + * @private + */ + GridAxis.onAfterSetScale = function () { + var axis = this; + (axis.grid.columns || []).forEach(function (column) { + column.setScale(); + }); + }; + /** + * Draw vertical axis ticks extra long to create cell floors and roofs. + * Overrides the tickLength for vertical axes. + * @private + */ + GridAxis.onAfterTickSize = function (e) { + var defaultLeftAxisOptions = Axis.defaultLeftAxisOptions; + var _a = this, horiz = _a.horiz, maxLabelDimensions = _a.maxLabelDimensions, _b = _a.options.grid, gridOptions = _b === void 0 ? {} : _b; + if (gridOptions.enabled && maxLabelDimensions) { + var labelPadding = (Math.abs(defaultLeftAxisOptions.labels.x) * 2); + var distance = horiz ? + gridOptions.cellHeight || labelPadding + maxLabelDimensions.height : + labelPadding + maxLabelDimensions.width; + if (isArray(e.tickSize)) { + e.tickSize[0] = distance; + } + else { + e.tickSize = [distance, 0]; + } + } + }; + /** + * @private + */ + GridAxis.onDestroy = function (e) { + var grid = this.grid; + (grid.columns || []).forEach(function (column) { + column.destroy(e.keepEvents); + }); + grid.columns = void 0; + }; + /** + * Wraps axis init to draw cell walls on vertical axes. + * @private + */ + GridAxis.onInit = function (e) { + var axis = this; + var userOptions = e.userOptions || {}; + var gridOptions = userOptions.grid || {}; + if (gridOptions.enabled && defined(gridOptions.borderColor)) { + userOptions.tickColor = userOptions.lineColor = gridOptions.borderColor; + } + if (!axis.grid) { + axis.grid = new GridAxisAdditions(axis); + } + }; + /** + * Makes tick labels which are usually ignored in a linked axis + * displayed if they are within range of linkedParent.min. + * ``` + * _____________________________ + * | | | | | + * Make this: | | 2 | 3 | 4 | + * |___|_______|_______|_______| + * ^ + * _____________________________ + * | | | | | + * Into this: | 1 | 2 | 3 | 4 | + * |___|_______|_______|_______| + * ^ + * ``` + * @private + * @todo Does this function do what the drawing says? Seems to affect + * ticks and not the labels directly? + */ + GridAxis.onTrimTicks = function () { + var axis = this; + var options = axis.options; + var gridOptions = options.grid || {}; + var categoryAxis = axis.categories; + var tickPositions = axis.tickPositions; + var firstPos = tickPositions[0]; + var lastPos = tickPositions[tickPositions.length - 1]; + var linkedMin = axis.linkedParent && axis.linkedParent.min; + var linkedMax = axis.linkedParent && axis.linkedParent.max; + var min = linkedMin || axis.min; + var max = linkedMax || axis.max; + var tickInterval = axis.tickInterval; + var endMoreThanMin = (firstPos < min && + firstPos + tickInterval > min); + var startLessThanMax = (lastPos > max && + lastPos - tickInterval < max); + if (gridOptions.enabled === true && + !categoryAxis && + (axis.horiz || axis.isLinked)) { + if (endMoreThanMin && !options.startOnTick) { + tickPositions[0] = min; + } + if (startLessThanMax && !options.endOnTick) { + tickPositions[tickPositions.length - 1] = max; + } + } + }; + /** + * Avoid altering tickInterval when reserving space. + * @private + */ + GridAxis.wrapUnsquish = function (proceed) { + var axis = this; + var _a = axis.options.grid, gridOptions = _a === void 0 ? {} : _a; + if (gridOptions.enabled === true && axis.categories) { + return axis.tickInterval; + } + return proceed.apply(axis, argsToArray(arguments)); + }; + return GridAxis; + }()); + (function (GridAxis) { + /** + * Enum for which side the axis is on. Maps to axis.side. + * @private + */ + var Side; + (function (Side) { + Side[Side["top"] = 0] = "top"; + Side[Side["right"] = 1] = "right"; + Side[Side["bottom"] = 2] = "bottom"; + Side[Side["left"] = 3] = "left"; + })(Side = GridAxis.Side || (GridAxis.Side = {})); + })(GridAxis || (GridAxis = {})); + GridAxis.compose(Axis); + + return GridAxis; + }); + _registerModule(_modules, 'modules/broken-axis.src.js', [_modules['parts/Axis.js'], _modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['parts/Stacking.js']], function (Axis, H, U, StackItem) { + /* * + * + * (c) 2009-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, find = U.find, fireEvent = U.fireEvent, isArray = U.isArray, isNumber = U.isNumber, pick = U.pick; + var Series = H.Series; + /* eslint-disable valid-jsdoc */ + /** + * Provides support for broken axes. + * @private + * @class + */ + var BrokenAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function BrokenAxisAdditions(axis) { + this.hasBreaks = false; + this.axis = axis; + } + /* * + * + * Static Functions + * + * */ + /** + * @private + */ + BrokenAxisAdditions.isInBreak = function (brk, val) { + var ret, repeat = brk.repeat || Infinity, from = brk.from, length = brk.to - brk.from, test = (val >= from ? + (val - from) % repeat : + repeat - ((from - val) % repeat)); + if (!brk.inclusive) { + ret = test < length && test !== 0; + } + else { + ret = test <= length; + } + return ret; + }; + /** + * @private + */ + BrokenAxisAdditions.lin2Val = function (val) { + var axis = this; + var brokenAxis = axis.brokenAxis; + var breakArray = brokenAxis && brokenAxis.breakArray; + if (!breakArray) { + return val; + } + var nval = val, brk, i; + for (i = 0; i < breakArray.length; i++) { + brk = breakArray[i]; + if (brk.from >= nval) { + break; + } + else if (brk.to < nval) { + nval += brk.len; + } + else if (BrokenAxisAdditions.isInBreak(brk, nval)) { + nval += brk.len; + } + } + return nval; + }; + /** + * @private + */ + BrokenAxisAdditions.val2Lin = function (val) { + var axis = this; + var brokenAxis = axis.brokenAxis; + var breakArray = brokenAxis && brokenAxis.breakArray; + if (!breakArray) { + return val; + } + var nval = val, brk, i; + for (i = 0; i < breakArray.length; i++) { + brk = breakArray[i]; + if (brk.to <= val) { + nval -= brk.len; + } + else if (brk.from >= val) { + break; + } + else if (BrokenAxisAdditions.isInBreak(brk, val)) { + nval -= (val - brk.from); + break; + } + } + return nval; + }; + /* * + * + * Functions + * + * */ + /** + * Returns the first break found where the x is larger then break.from and + * smaller then break.to. + * + * @param {number} x + * The number which should be within a break. + * + * @param {Array} breaks + * The array of breaks to search within. + * + * @return {Highcharts.XAxisBreaksOptions|undefined} + * Returns the first break found that matches, returns false if no break is + * found. + */ + BrokenAxisAdditions.prototype.findBreakAt = function (x, breaks) { + return find(breaks, function (b) { + return b.from < x && x < b.to; + }); + }; + /** + * @private + */ + BrokenAxisAdditions.prototype.isInAnyBreak = function (val, testKeep) { + var brokenAxis = this; + var axis = brokenAxis.axis; + var breaks = axis.options.breaks, i = breaks && breaks.length, inbrk, keep, ret; + if (i) { + while (i--) { + if (BrokenAxisAdditions.isInBreak(breaks[i], val)) { + inbrk = true; + if (!keep) { + keep = pick(breaks[i].showPoints, !axis.isXAxis); + } + } + } + if (inbrk && testKeep) { + ret = inbrk && !keep; + } + else { + ret = inbrk; + } + } + return ret; + }; + /** + * Dynamically set or unset breaks in an axis. This function in lighter than + * usin Axis.update, and it also preserves animation. + * + * @private + * @function Highcharts.Axis#setBreaks + * + * @param {Array} [breaks] + * The breaks to add. When `undefined` it removes existing breaks. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart immediately. + * + * @return {void} + */ + BrokenAxisAdditions.prototype.setBreaks = function (breaks, redraw) { + var brokenAxis = this; + var axis = brokenAxis.axis; + var hasBreaks = (isArray(breaks) && !!breaks.length); + axis.isDirty = brokenAxis.hasBreaks !== hasBreaks; + brokenAxis.hasBreaks = hasBreaks; + axis.options.breaks = axis.userOptions.breaks = breaks; + axis.forceRedraw = true; // Force recalculation in setScale + // Recalculate series related to the axis. + axis.series.forEach(function (series) { + series.isDirty = true; + }); + if (!hasBreaks && axis.val2lin === BrokenAxisAdditions.val2Lin) { + // Revert to prototype functions + delete axis.val2lin; + delete axis.lin2val; + } + if (hasBreaks) { + axis.userOptions.ordinal = false; + axis.lin2val = BrokenAxisAdditions.lin2Val; + axis.val2lin = BrokenAxisAdditions.val2Lin; + axis.setExtremes = function (newMin, newMax, redraw, animation, eventArguments) { + // If trying to set extremes inside a break, extend min to + // after, and max to before the break ( #3857 ) + if (brokenAxis.hasBreaks) { + var axisBreak, breaks = this.options.breaks; + while ((axisBreak = brokenAxis.findBreakAt(newMin, breaks))) { + newMin = axisBreak.to; + } + while ((axisBreak = brokenAxis.findBreakAt(newMax, breaks))) { + newMax = axisBreak.from; + } + // If both min and max is within the same break. + if (newMax < newMin) { + newMax = newMin; + } + } + Axis.prototype.setExtremes.call(this, newMin, newMax, redraw, animation, eventArguments); + }; + axis.setAxisTranslation = function (saveOld) { + Axis.prototype.setAxisTranslation.call(this, saveOld); + brokenAxis.unitLength = null; + if (brokenAxis.hasBreaks) { + var breaks = axis.options.breaks || [], + // Temporary one: + breakArrayT = [], breakArray = [], length = 0, inBrk, repeat, min = axis.userMin || axis.min, max = axis.userMax || axis.max, pointRangePadding = pick(axis.pointRangePadding, 0), start, i; + // Min & max check (#4247) + breaks.forEach(function (brk) { + repeat = brk.repeat || Infinity; + if (BrokenAxisAdditions.isInBreak(brk, min)) { + min += + (brk.to % repeat) - + (min % repeat); + } + if (BrokenAxisAdditions.isInBreak(brk, max)) { + max -= + (max % repeat) - + (brk.from % repeat); + } + }); + // Construct an array holding all breaks in the axis + breaks.forEach(function (brk) { + start = brk.from; + repeat = brk.repeat || Infinity; + while (start - repeat > min) { + start -= repeat; + } + while (start < min) { + start += repeat; + } + for (i = start; i < max; i += repeat) { + breakArrayT.push({ + value: i, + move: 'in' + }); + breakArrayT.push({ + value: i + (brk.to - brk.from), + move: 'out', + size: brk.breakSize + }); + } + }); + breakArrayT.sort(function (a, b) { + return ((a.value === b.value) ? + ((a.move === 'in' ? 0 : 1) - + (b.move === 'in' ? 0 : 1)) : + a.value - b.value); + }); + // Simplify the breaks + inBrk = 0; + start = min; + breakArrayT.forEach(function (brk) { + inBrk += (brk.move === 'in' ? 1 : -1); + if (inBrk === 1 && brk.move === 'in') { + start = brk.value; + } + if (inBrk === 0) { + breakArray.push({ + from: start, + to: brk.value, + len: brk.value - start - (brk.size || 0) + }); + length += brk.value - start - (brk.size || 0); + } + }); + /** + * HC <= 8 backwards compatibility, used by demo samples. + * @deprecated + * @private + * @requires modules/broken-axis + */ + axis.breakArray = brokenAxis.breakArray = breakArray; + // Used with staticScale, and below the actual axis length, + // when breaks are substracted. + brokenAxis.unitLength = max - min - length + pointRangePadding; + fireEvent(axis, 'afterBreaks'); + if (axis.staticScale) { + axis.transA = axis.staticScale; + } + else if (brokenAxis.unitLength) { + axis.transA *= + (max - axis.min + pointRangePadding) / + brokenAxis.unitLength; + } + if (pointRangePadding) { + axis.minPixelPadding = + axis.transA * axis.minPointOffset; + } + axis.min = min; + axis.max = max; + } + }; + } + if (pick(redraw, true)) { + axis.chart.redraw(); + } + }; + return BrokenAxisAdditions; + }()); + /** + * Axis with support of broken data rows. + * @private + * @class + */ + var BrokenAxis = /** @class */ (function () { + function BrokenAxis() { + } + /** + * Adds support for broken axes. + * @private + */ + BrokenAxis.compose = function (AxisClass, SeriesClass) { + AxisClass.keepProps.push('brokenAxis'); + var seriesProto = Series.prototype; + /** + * @private + */ + seriesProto.drawBreaks = function (axis, keys) { + var series = this, points = series.points, breaks, threshold, eventName, y; + if (axis && // #5950 + axis.brokenAxis && + axis.brokenAxis.hasBreaks) { + var brokenAxis_1 = axis.brokenAxis; + keys.forEach(function (key) { + breaks = brokenAxis_1 && brokenAxis_1.breakArray || []; + threshold = axis.isXAxis ? + axis.min : + pick(series.options.threshold, axis.min); + points.forEach(function (point) { + y = pick(point['stack' + key.toUpperCase()], point[key]); + breaks.forEach(function (brk) { + if (isNumber(threshold) && isNumber(y)) { + eventName = false; + if ((threshold < brk.from && y > brk.to) || + (threshold > brk.from && y < brk.from)) { + eventName = 'pointBreak'; + } + else if ((threshold < brk.from && y > brk.from && y < brk.to) || + (threshold > brk.from && y > brk.to && y < brk.from)) { + eventName = 'pointInBreak'; + } + if (eventName) { + fireEvent(axis, eventName, { point: point, brk: brk }); + } + } + }); + }); + }); + } + }; + /** + * Extend getGraphPath by identifying gaps in the data so that we can + * draw a gap in the line or area. This was moved from ordinal axis + * module to broken axis module as of #5045. + * + * @private + * @function Highcharts.Series#gappedPath + * + * @return {Highcharts.SVGPathArray} + * Gapped path + */ + seriesProto.gappedPath = function () { + var currentDataGrouping = this.currentDataGrouping, groupingSize = currentDataGrouping && currentDataGrouping.gapSize, gapSize = this.options.gapSize, points = this.points.slice(), i = points.length - 1, yAxis = this.yAxis, stack; + /** + * Defines when to display a gap in the graph, together with the + * [gapUnit](plotOptions.series.gapUnit) option. + * + * In case when `dataGrouping` is enabled, points can be grouped + * into a larger time span. This can make the grouped points to have + * a greater distance than the absolute value of `gapSize` property, + * which will result in disappearing graph completely. To prevent + * this situation the mentioned distance between grouped points is + * used instead of previously defined `gapSize`. + * + * In practice, this option is most often used to visualize gaps in + * time series. In a stock chart, intraday data is available for + * daytime hours, while gaps will appear in nights and weekends. + * + * @see [gapUnit](plotOptions.series.gapUnit) + * @see [xAxis.breaks](#xAxis.breaks) + * + * @sample {highstock} stock/plotoptions/series-gapsize/ + * Setting the gap size to 2 introduces gaps for weekends + * in daily datasets. + * + * @type {number} + * @default 0 + * @product highstock + * @requires modules/broken-axis + * @apioption plotOptions.series.gapSize + */ + /** + * Together with [gapSize](plotOptions.series.gapSize), this option + * defines where to draw gaps in the graph. + * + * When the `gapUnit` is `"relative"` (default), a gap size of 5 + * means that if the distance between two points is greater than + * 5 times that of the two closest points, the graph will be broken. + * + * When the `gapUnit` is `"value"`, the gap is based on absolute + * axis values, which on a datetime axis is milliseconds. This also + * applies to the navigator series that inherits gap options from + * the base series. + * + * @see [gapSize](plotOptions.series.gapSize) + * + * @type {string} + * @default relative + * @since 5.0.13 + * @product highstock + * @validvalue ["relative", "value"] + * @requires modules/broken-axis + * @apioption plotOptions.series.gapUnit + */ + if (gapSize && i > 0) { // #5008 + // Gap unit is relative + if (this.options.gapUnit !== 'value') { + gapSize *= this.basePointRange; + } + // Setting a new gapSize in case dataGrouping is enabled (#7686) + if (groupingSize && + groupingSize > gapSize && + // Except when DG is forced (e.g. from other series) + // and has lower granularity than actual points (#11351) + groupingSize >= this.basePointRange) { + gapSize = groupingSize; + } + // extension for ordinal breaks + var current = void 0, next = void 0; + while (i--) { + // Reassign next if it is not visible + if (!(next && next.visible !== false)) { + next = points[i + 1]; + } + current = points[i]; + // Skip iteration if one of the points is not visible + if (next.visible === false || current.visible === false) { + continue; + } + if (next.x - current.x > gapSize) { + var xRange = (current.x + next.x) / 2; + points.splice(// insert after this one + i + 1, 0, { + isNull: true, + x: xRange + }); + // For stacked chart generate empty stack items, #6546 + if (yAxis.stacking && this.options.stacking) { + stack = yAxis.stacking.stacks[this.stackKey][xRange] = + new StackItem(yAxis, yAxis.options + .stackLabels, false, xRange, this.stack); + stack.total = 0; + } + } + // Assign current to next for the upcoming iteration + next = current; + } + } + // Call base method + return this.getGraphPath(points); + }; + /* eslint-disable no-invalid-this */ + addEvent(AxisClass, 'init', function () { + var axis = this; + if (!axis.brokenAxis) { + axis.brokenAxis = new BrokenAxisAdditions(axis); + } + }); + addEvent(AxisClass, 'afterInit', function () { + if (typeof this.brokenAxis !== 'undefined') { + this.brokenAxis.setBreaks(this.options.breaks, false); + } + }); + addEvent(AxisClass, 'afterSetTickPositions', function () { + var axis = this; + var brokenAxis = axis.brokenAxis; + if (brokenAxis && + brokenAxis.hasBreaks) { + var tickPositions = this.tickPositions, info = this.tickPositions.info, newPositions = [], i; + for (i = 0; i < tickPositions.length; i++) { + if (!brokenAxis.isInAnyBreak(tickPositions[i])) { + newPositions.push(tickPositions[i]); + } + } + this.tickPositions = newPositions; + this.tickPositions.info = info; + } + }); + // Force Axis to be not-ordinal when breaks are defined + addEvent(AxisClass, 'afterSetOptions', function () { + if (this.brokenAxis && this.brokenAxis.hasBreaks) { + this.options.ordinal = false; + } + }); + addEvent(SeriesClass, 'afterGeneratePoints', function () { + var _a = this, isDirty = _a.isDirty, connectNulls = _a.options.connectNulls, points = _a.points, xAxis = _a.xAxis, yAxis = _a.yAxis; + // Set, or reset visibility of the points. Axis.setBreaks marks the + // series as isDirty + if (isDirty) { + var i = points.length; + while (i--) { + var point = points[i]; + // Respect nulls inside the break (#4275) + var nullGap = point.y === null && connectNulls === false; + var isPointInBreak = (!nullGap && ((xAxis && + xAxis.brokenAxis && + xAxis.brokenAxis.isInAnyBreak(point.x, true)) || (yAxis && + yAxis.brokenAxis && + yAxis.brokenAxis.isInAnyBreak(point.y, true)))); + // Set point.visible if in any break. + // If not in break, reset visible to original value. + point.visible = isPointInBreak ? + false : + point.options.visible !== false; + } + } + }); + addEvent(SeriesClass, 'afterRender', function drawPointsWrapped() { + this.drawBreaks(this.xAxis, ['x']); + this.drawBreaks(this.yAxis, pick(this.pointArrayMap, ['y'])); + }); + }; + return BrokenAxis; + }()); + BrokenAxis.compose(Axis, Series); // @todo remove automatism + + return BrokenAxis; + }); + _registerModule(_modules, 'parts-gantt/TreeGridAxis.js', [_modules['parts/Axis.js'], _modules['parts/Tick.js'], _modules['parts-gantt/Tree.js'], _modules['parts-gantt/TreeGridTick.js'], _modules['mixins/tree-series.js'], _modules['parts/Utilities.js']], function (Axis, Tick, Tree, TreeGridTick, TreeSeriesMixin, U) { + /* * + * + * (c) 2016 Highsoft AS + * Authors: Jon Arild Nygard + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, find = U.find, fireEvent = U.fireEvent, isNumber = U.isNumber, isObject = U.isObject, isString = U.isString, merge = U.merge, pick = U.pick, wrap = U.wrap; + /** + * @private + */ + var TreeGridAxis; + (function (TreeGridAxis) { + /* * + * + * Interfaces + * + * */ + /* * + * + * Variables + * + * */ + var applied = false; + /* * + * + * Functions + * + * */ + /** + * @private + */ + function compose(AxisClass) { + if (!applied) { + wrap(AxisClass.prototype, 'generateTick', wrapGenerateTick); + wrap(AxisClass.prototype, 'getMaxLabelDimensions', wrapGetMaxLabelDimensions); + wrap(AxisClass.prototype, 'init', wrapInit); + wrap(AxisClass.prototype, 'setTickInterval', wrapSetTickInterval); + TreeGridTick.compose(Tick); + applied = true; + } + } + TreeGridAxis.compose = compose; + /** + * @private + */ + function getBreakFromNode(node, max) { + var from = node.collapseStart || 0, to = node.collapseEnd || 0; + // In broken-axis, the axis.max is minimized until it is not within a + // break. Therefore, if break.to is larger than axis.max, the axis.to + // should not add the 0.5 axis.tickMarkOffset, to avoid adding a break + // larger than axis.max. + // TODO consider simplifying broken-axis and this might solve itself + if (to >= max) { + from -= 0.5; + } + return { + from: from, + to: to, + showPoints: false + }; + } + /** + * Creates a tree structure of the data, and the treegrid. Calculates + * categories, and y-values of points based on the tree. + * + * @private + * @function getTreeGridFromData + * + * @param {Array} data + * All the data points to display in the axis. + * + * @param {boolean} uniqueNames + * Wether or not the data node with the same name should share grid cell. If + * true they do share cell. False by default. + * + * @param {number} numberOfSeries + * + * @return {object} + * Returns an object containing categories, mapOfIdToNode, + * mapOfPosToGridNode, and tree. + * + * @todo There should be only one point per line. + * @todo It should be optional to have one category per point, or merge + * cells + * @todo Add unit-tests. + */ + function getTreeGridFromData(data, uniqueNames, numberOfSeries) { + var categories = [], collapsedNodes = [], mapOfIdToNode = {}, mapOfPosToGridNode = {}, posIterator = -1, uniqueNamesEnabled = typeof uniqueNames === 'boolean' ? uniqueNames : false, tree; + // Build the tree from the series data. + var treeParams = { + // After the children has been created. + after: function (node) { + var gridNode = mapOfPosToGridNode[node.pos], height = 0, descendants = 0; + gridNode.children.forEach(function (child) { + descendants += (child.descendants || 0) + 1; + height = Math.max((child.height || 0) + 1, height); + }); + gridNode.descendants = descendants; + gridNode.height = height; + if (gridNode.collapsed) { + collapsedNodes.push(gridNode); + } + }, + // Before the children has been created. + before: function (node) { + var data = isObject(node.data, true) ? node.data : {}, name = isString(data.name) ? data.name : '', parentNode = mapOfIdToNode[node.parent], parentGridNode = (isObject(parentNode, true) ? + mapOfPosToGridNode[parentNode.pos] : + null), hasSameName = function (x) { + return x.name === name; + }, gridNode, pos; + // If not unique names, look for sibling node with the same name + if (uniqueNamesEnabled && + isObject(parentGridNode, true) && + !!(gridNode = find(parentGridNode.children, hasSameName))) { + // If there is a gridNode with the same name, reuse position + pos = gridNode.pos; + // Add data node to list of nodes in the grid node. + gridNode.nodes.push(node); + } + else { + // If it is a new grid node, increment position. + pos = posIterator++; + } + // Add new grid node to map. + if (!mapOfPosToGridNode[pos]) { + mapOfPosToGridNode[pos] = gridNode = { + depth: parentGridNode ? parentGridNode.depth + 1 : 0, + name: name, + nodes: [node], + children: [], + pos: pos + }; + // If not root, then add name to categories. + if (pos !== -1) { + categories.push(name); + } + // Add name to list of children. + if (isObject(parentGridNode, true)) { + parentGridNode.children.push(gridNode); + } + } + // Add data node to map + if (isString(node.id)) { + mapOfIdToNode[node.id] = node; + } + // If one of the points are collapsed, then start the grid node + // in collapsed state. + if (gridNode && + data.collapsed === true) { + gridNode.collapsed = true; + } + // Assign pos to data node + node.pos = pos; + } + }; + var updateYValuesAndTickPos = function (map, numberOfSeries) { + var setValues = function (gridNode, start, result) { + var nodes = gridNode.nodes, end = start + (start === -1 ? 0 : numberOfSeries - 1), diff = (end - start) / 2, padding = 0.5, pos = start + diff; + nodes.forEach(function (node) { + var data = node.data; + if (isObject(data, true)) { + // Update point + data.y = start + (data.seriesIndex || 0); + // Remove the property once used + delete data.seriesIndex; + } + node.pos = pos; + }); + result[pos] = gridNode; + gridNode.pos = pos; + gridNode.tickmarkOffset = diff + padding; + gridNode.collapseStart = end + padding; + gridNode.children.forEach(function (child) { + setValues(child, end + 1, result); + end = (child.collapseEnd || 0) - padding; + }); + // Set collapseEnd to the end of the last child node. + gridNode.collapseEnd = end + padding; + return result; + }; + return setValues(map['-1'], -1, {}); + }; + // Create tree from data + tree = Tree.getTree(data, treeParams); + // Update y values of data, and set calculate tick positions. + mapOfPosToGridNode = updateYValuesAndTickPos(mapOfPosToGridNode, numberOfSeries); + // Return the resulting data. + return { + categories: categories, + mapOfIdToNode: mapOfIdToNode, + mapOfPosToGridNode: mapOfPosToGridNode, + collapsedNodes: collapsedNodes, + tree: tree + }; + } + /** + * Builds the tree of categories and calculates its positions. + * @private + * @param {object} e Event object + * @param {object} e.target The chart instance which the event was fired on. + * @param {object[]} e.target.axes The axes of the chart. + */ + function onBeforeRender(e) { + var chart = e.target, axes = chart.axes; + axes.filter(function (axis) { + return axis.options.type === 'treegrid'; + }).forEach(function (axis) { + var options = axis.options || {}, labelOptions = options.labels, uniqueNames = options.uniqueNames, numberOfSeries = 0, isDirty, data, treeGrid; + // Check whether any of series is rendering for the first time, + // visibility has changed, or its data is dirty, + // and only then update. #10570, #10580 + // Also check if mapOfPosToGridNode exists. #10887 + isDirty = (!axis.treeGrid.mapOfPosToGridNode || + axis.series.some(function (series) { + return !series.hasRendered || + series.isDirtyData || + series.isDirty; + })); + if (isDirty) { + // Concatenate data from all series assigned to this axis. + data = axis.series.reduce(function (arr, s) { + if (s.visible) { + // Push all data to array + (s.options.data || []).forEach(function (data) { + if (isObject(data, true)) { + // Set series index on data. Removed again + // after use. + data.seriesIndex = numberOfSeries; + arr.push(data); + } + }); + // Increment series index + if (uniqueNames === true) { + numberOfSeries++; + } + } + return arr; + }, []); + // setScale is fired after all the series is initialized, + // which is an ideal time to update the axis.categories. + treeGrid = getTreeGridFromData(data, uniqueNames || false, (uniqueNames === true) ? numberOfSeries : 1); + // Assign values to the axis. + axis.categories = treeGrid.categories; + axis.treeGrid.mapOfPosToGridNode = treeGrid.mapOfPosToGridNode; + axis.hasNames = true; + axis.treeGrid.tree = treeGrid.tree; + // Update yData now that we have calculated the y values + axis.series.forEach(function (series) { + var data = (series.options.data || []).map(function (d) { + return isObject(d, true) ? merge(d) : d; + }); + // Avoid destroying points when series is not visible + if (series.visible) { + series.setData(data, false); + } + }); + // Calculate the label options for each level in the tree. + axis.treeGrid.mapOptionsToLevel = + TreeSeriesMixin.getLevelOptions({ + defaults: labelOptions, + from: 1, + levels: labelOptions && labelOptions.levels, + to: axis.treeGrid.tree && axis.treeGrid.tree.height + }); + // Setting initial collapsed nodes + if (e.type === 'beforeRender') { + axis.treeGrid.collapsedNodes = treeGrid.collapsedNodes; + } + } + }); + } + /** + * Generates a tick for initial positioning. + * + * @private + * @function Highcharts.GridAxis#generateTick + * + * @param {Function} proceed + * The original generateTick function. + * + * @param {number} pos + * The tick position in axis values. + */ + function wrapGenerateTick(proceed, pos) { + var axis = this, mapOptionsToLevel = axis.treeGrid.mapOptionsToLevel || {}, isTreeGrid = axis.options.type === 'treegrid', ticks = axis.ticks; + var tick = ticks[pos], levelOptions, options, gridNode; + if (isTreeGrid && + axis.treeGrid.mapOfPosToGridNode) { + gridNode = axis.treeGrid.mapOfPosToGridNode[pos]; + levelOptions = mapOptionsToLevel[gridNode.depth]; + if (levelOptions) { + options = { + labels: levelOptions + }; + } + if (!tick) { + ticks[pos] = tick = + new Tick(axis, pos, void 0, void 0, { + category: gridNode.name, + tickmarkOffset: gridNode.tickmarkOffset, + options: options + }); + } + else { + // update labels depending on tick interval + tick.parameters.category = gridNode.name; + tick.options = options; + tick.addLabel(); + } + } + else { + proceed.apply(axis, Array.prototype.slice.call(arguments, 1)); + } + } + /** + * Override to add indentation to axis.maxLabelDimensions. + * + * @private + * @function Highcharts.GridAxis#getMaxLabelDimensions + * + * @param {Function} proceed + * The original function + */ + function wrapGetMaxLabelDimensions(proceed) { + var axis = this, options = axis.options, labelOptions = options && options.labels, indentation = (labelOptions && isNumber(labelOptions.indentation) ? + labelOptions.indentation : + 0), retVal = proceed.apply(axis, Array.prototype.slice.call(arguments, 1)), isTreeGrid = axis.options.type === 'treegrid'; + var treeDepth; + if (isTreeGrid && axis.treeGrid.mapOfPosToGridNode) { + treeDepth = axis.treeGrid.mapOfPosToGridNode[-1].height || 0; + retVal.width += indentation * (treeDepth - 1); + } + return retVal; + } + /** + * @private + */ + function wrapInit(proceed, chart, userOptions) { + var axis = this, isTreeGrid = userOptions.type === 'treegrid'; + if (!axis.treeGrid) { + axis.treeGrid = new Additions(axis); + } + // Set default and forced options for TreeGrid + if (isTreeGrid) { + // Add event for updating the categories of a treegrid. + // NOTE Preferably these events should be set on the axis. + addEvent(chart, 'beforeRender', onBeforeRender); + addEvent(chart, 'beforeRedraw', onBeforeRender); + // Add new collapsed nodes on addseries + addEvent(chart, 'addSeries', function (e) { + if (e.options.data) { + var treeGrid = getTreeGridFromData(e.options.data, userOptions.uniqueNames || false, 1); + axis.treeGrid.collapsedNodes = (axis.treeGrid.collapsedNodes || []).concat(treeGrid.collapsedNodes); + } + }); + // Collapse all nodes in axis.treegrid.collapsednodes + // where collapsed equals true. + addEvent(axis, 'foundExtremes', function () { + if (axis.treeGrid.collapsedNodes) { + axis.treeGrid.collapsedNodes.forEach(function (node) { + var breaks = axis.treeGrid.collapse(node); + if (axis.brokenAxis) { + axis.brokenAxis.setBreaks(breaks, false); + // remove the node from the axis collapsedNodes + if (axis.treeGrid.collapsedNodes) { + axis.treeGrid.collapsedNodes = axis.treeGrid.collapsedNodes.filter(function (n) { + return node.collapseStart !== n.collapseStart || + node.collapseEnd !== n.collapseEnd; + }); + } + } + }); + } + }); + userOptions = merge({ + // Default options + grid: { + enabled: true + }, + // TODO: add support for align in treegrid. + labels: { + align: 'left', + /** + * Set options on specific levels in a tree grid axis. Takes + * precedence over labels options. + * + * @sample {gantt} gantt/treegrid-axis/labels-levels + * Levels on TreeGrid Labels + * + * @type {Array<*>} + * @product gantt + * @apioption yAxis.labels.levels + * + * @private + */ + levels: [{ + /** + * Specify the level which the options within this object + * applies to. + * + * @type {number} + * @product gantt + * @apioption yAxis.labels.levels.level + * + * @private + */ + level: void 0 + }, { + level: 1, + /** + * @type {Highcharts.CSSObject} + * @product gantt + * @apioption yAxis.labels.levels.style + * + * @private + */ + style: { + /** @ignore-option */ + fontWeight: 'bold' + } + }], + /** + * The symbol for the collapse and expand icon in a + * treegrid. + * + * @product gantt + * @optionparent yAxis.labels.symbol + * + * @private + */ + symbol: { + /** + * The symbol type. Points to a definition function in + * the `Highcharts.Renderer.symbols` collection. + * + * @type {Highcharts.SymbolKeyValue} + * + * @private + */ + type: 'triangle', + x: -5, + y: -5, + height: 10, + width: 10, + padding: 5 + } + }, + uniqueNames: false + }, userOptions, { + // Forced options + reversed: true, + // grid.columns is not supported in treegrid + grid: { + columns: void 0 + } + }); + } + // Now apply the original function with the original arguments, + // which are sliced off this function's arguments + proceed.apply(axis, [chart, userOptions]); + if (isTreeGrid) { + axis.hasNames = true; + axis.options.showLastLabel = true; + } + } + /** + * Set the tick positions, tickInterval, axis min and max. + * + * @private + * @function Highcharts.GridAxis#setTickInterval + * + * @param {Function} proceed + * The original setTickInterval function. + */ + function wrapSetTickInterval(proceed) { + var axis = this, options = axis.options, isTreeGrid = options.type === 'treegrid'; + if (isTreeGrid) { + axis.min = pick(axis.userMin, options.min, axis.dataMin); + axis.max = pick(axis.userMax, options.max, axis.dataMax); + fireEvent(axis, 'foundExtremes'); + // setAxisTranslation modifies the min and max according to + // axis breaks. + axis.setAxisTranslation(true); + axis.tickmarkOffset = 0.5; + axis.tickInterval = 1; + axis.tickPositions = axis.treeGrid.mapOfPosToGridNode ? + axis.treeGrid.getTickPositions() : + []; + } + else { + proceed.apply(axis, Array.prototype.slice.call(arguments, 1)); + } + } + /* * + * + * Classes + * + * */ + /** + * @private + * @class + */ + var Additions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + /** + * @private + */ + function Additions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Calculates the new axis breaks to collapse a node. + * + * @private + * + * @param {Highcharts.Axis} axis + * The axis to check against. + * + * @param {Highcharts.GridNode} node + * The node to collapse. + * + * @param {number} pos + * The tick position to collapse. + * + * @return {Array} + * Returns an array of the new breaks for the axis. + */ + Additions.prototype.collapse = function (node) { + var axis = this.axis, breaks = (axis.options.breaks || []), obj = getBreakFromNode(node, axis.max); + breaks.push(obj); + return breaks; + }; + /** + * Calculates the new axis breaks to expand a node. + * + * @private + * + * @param {Highcharts.Axis} axis + * The axis to check against. + * + * @param {Highcharts.GridNode} node + * The node to expand. + * + * @param {number} pos + * The tick position to expand. + * + * @return {Array} + * Returns an array of the new breaks for the axis. + */ + Additions.prototype.expand = function (node) { + var axis = this.axis, breaks = (axis.options.breaks || []), obj = getBreakFromNode(node, axis.max); + // Remove the break from the axis breaks array. + return breaks.reduce(function (arr, b) { + if (b.to !== obj.to || b.from !== obj.from) { + arr.push(b); + } + return arr; + }, []); + }; + /** + * Creates a list of positions for the ticks on the axis. Filters out + * positions that are outside min and max, or is inside an axis break. + * + * @private + * + * @return {Array} + * List of positions. + */ + Additions.prototype.getTickPositions = function () { + var axis = this.axis; + return Object.keys(axis.treeGrid.mapOfPosToGridNode || {}).reduce(function (arr, key) { + var pos = +key; + if (axis.min <= pos && + axis.max >= pos && + !(axis.brokenAxis && axis.brokenAxis.isInAnyBreak(pos))) { + arr.push(pos); + } + return arr; + }, []); + }; + /** + * Check if a node is collapsed. + * + * @private + * + * @param {Highcharts.Axis} axis + * The axis to check against. + * + * @param {object} node + * The node to check if is collapsed. + * + * @param {number} pos + * The tick position to collapse. + * + * @return {boolean} + * Returns true if collapsed, false if expanded. + */ + Additions.prototype.isCollapsed = function (node) { + var axis = this.axis, breaks = (axis.options.breaks || []), obj = getBreakFromNode(node, axis.max); + return breaks.some(function (b) { + return b.from === obj.from && b.to === obj.to; + }); + }; + /** + * Calculates the new axis breaks after toggling the collapse/expand + * state of a node. If it is collapsed it will be expanded, and if it is + * exapended it will be collapsed. + * + * @private + * + * @param {Highcharts.Axis} axis + * The axis to check against. + * + * @param {Highcharts.GridNode} node + * The node to toggle. + * + * @return {Array} + * Returns an array of the new breaks for the axis. + */ + Additions.prototype.toggleCollapse = function (node) { + return (this.isCollapsed(node) ? + this.expand(node) : + this.collapse(node)); + }; + return Additions; + }()); + TreeGridAxis.Additions = Additions; + })(TreeGridAxis || (TreeGridAxis = {})); + // Make utility functions available for testing. + Axis.prototype.utils = { + getNode: Tree.getNode + }; + TreeGridAxis.compose(Axis); + + return TreeGridAxis; + }); + _registerModule(_modules, 'parts-gantt/PathfinderAlgorithms.js', [_modules['parts/Utilities.js']], function (U) { + /* * + * + * (c) 2016 Highsoft AS + * Author: Øystein Moseng + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend, pick = U.pick; + var min = Math.min, max = Math.max, abs = Math.abs; + /** + * Get index of last obstacle before xMin. Employs a type of binary search, and + * thus requires that obstacles are sorted by xMin value. + * + * @private + * @function findLastObstacleBefore + * + * @param {Array} obstacles + * Array of obstacles to search in. + * + * @param {number} xMin + * The xMin threshold. + * + * @param {number} [startIx] + * Starting index to search from. Must be within array range. + * + * @return {number} + * The index of the last obstacle element before xMin. + */ + function findLastObstacleBefore(obstacles, xMin, startIx) { + var left = startIx || 0, // left limit + right = obstacles.length - 1, // right limit + min = xMin - 0.0000001, // Make sure we include all obstacles at xMin + cursor, cmp; + while (left <= right) { + cursor = (right + left) >> 1; + cmp = min - obstacles[cursor].xMin; + if (cmp > 0) { + left = cursor + 1; + } + else if (cmp < 0) { + right = cursor - 1; + } + else { + return cursor; + } + } + return left > 0 ? left - 1 : 0; + } + /** + * Test if a point lays within an obstacle. + * + * @private + * @function pointWithinObstacle + * + * @param {object} obstacle + * Obstacle to test. + * + * @param {Highcharts.Point} point + * Point with x/y props. + * + * @return {boolean} + * Whether point is within the obstacle or not. + */ + function pointWithinObstacle(obstacle, point) { + return (point.x <= obstacle.xMax && + point.x >= obstacle.xMin && + point.y <= obstacle.yMax && + point.y >= obstacle.yMin); + } + /** + * Find the index of an obstacle that wraps around a point. + * Returns -1 if not found. + * + * @private + * @function findObstacleFromPoint + * + * @param {Array} obstacles + * Obstacles to test. + * + * @param {Highcharts.Point} point + * Point with x/y props. + * + * @return {number} + * Ix of the obstacle in the array, or -1 if not found. + */ + function findObstacleFromPoint(obstacles, point) { + var i = findLastObstacleBefore(obstacles, point.x + 1) + 1; + while (i--) { + if (obstacles[i].xMax >= point.x && + // optimization using lazy evaluation + pointWithinObstacle(obstacles[i], point)) { + return i; + } + } + return -1; + } + /** + * Get SVG path array from array of line segments. + * + * @private + * @function pathFromSegments + * + * @param {Array} segments + * The segments to build the path from. + * + * @return {Highcharts.SVGPathArray} + * SVG path array as accepted by the SVG Renderer. + */ + function pathFromSegments(segments) { + var path = []; + if (segments.length) { + path.push(['M', segments[0].start.x, segments[0].start.y]); + for (var i = 0; i < segments.length; ++i) { + path.push(['L', segments[i].end.x, segments[i].end.y]); + } + } + return path; + } + /** + * Limits obstacle max/mins in all directions to bounds. Modifies input + * obstacle. + * + * @private + * @function limitObstacleToBounds + * + * @param {object} obstacle + * Obstacle to limit. + * + * @param {object} bounds + * Bounds to use as limit. + * + * @return {void} + */ + function limitObstacleToBounds(obstacle, bounds) { + obstacle.yMin = max(obstacle.yMin, bounds.yMin); + obstacle.yMax = min(obstacle.yMax, bounds.yMax); + obstacle.xMin = max(obstacle.xMin, bounds.xMin); + obstacle.xMax = min(obstacle.xMax, bounds.xMax); + } + // Define the available pathfinding algorithms. + // Algorithms take up to 3 arguments: starting point, ending point, and an + // options object. + var algorithms = { + /** + * Get an SVG path from a starting coordinate to an ending coordinate. + * Draws a straight line. + * + * @function Highcharts.Pathfinder.algorithms.straight + * + * @param {Highcharts.PositionObject} start + * Starting coordinate, object with x/y props. + * + * @param {Highcharts.PositionObject} end + * Ending coordinate, object with x/y props. + * + * @return {object} + * An object with the SVG path in Array form as accepted by the SVG + * renderer, as well as an array of new obstacles making up this + * path. + */ + straight: function (start, end) { + return { + path: [ + ['M', start.x, start.y], + ['L', end.x, end.y] + ], + obstacles: [{ start: start, end: end }] + }; + }, + /** + * Find a path from a starting coordinate to an ending coordinate, using + * right angles only, and taking only starting/ending obstacle into + * consideration. + * + * @function Highcharts.Pathfinder.algorithms.simpleConnect + * + * @param {Highcharts.PositionObject} start + * Starting coordinate, object with x/y props. + * + * @param {Highcharts.PositionObject} end + * Ending coordinate, object with x/y props. + * + * @param {object} options + * Options for the algorithm: + * - chartObstacles: Array of chart obstacles to avoid + * - startDirectionX: Optional. True if starting in the X direction. + * If not provided, the algorithm starts in the direction that is + * the furthest between start/end. + * + * @return {object} + * An object with the SVG path in Array form as accepted by the SVG + * renderer, as well as an array of new obstacles making up this + * path. + */ + simpleConnect: extend(function (start, end, options) { + var segments = [], endSegment, dir = pick(options.startDirectionX, abs(end.x - start.x) > abs(end.y - start.y)) ? 'x' : 'y', chartObstacles = options.chartObstacles, startObstacleIx = findObstacleFromPoint(chartObstacles, start), endObstacleIx = findObstacleFromPoint(chartObstacles, end), startObstacle, endObstacle, prevWaypoint, waypoint, waypoint2, useMax, endPoint; + // eslint-disable-next-line valid-jsdoc + /** + * Return a clone of a point with a property set from a target object, + * optionally with an offset + * @private + */ + function copyFromPoint(from, fromKey, to, toKey, offset) { + var point = { + x: from.x, + y: from.y + }; + point[fromKey] = to[toKey || fromKey] + (offset || 0); + return point; + } + // eslint-disable-next-line valid-jsdoc + /** + * Return waypoint outside obstacle. + * @private + */ + function getMeOut(obstacle, point, direction) { + var useMax = abs(point[direction] - obstacle[direction + 'Min']) > + abs(point[direction] - obstacle[direction + 'Max']); + return copyFromPoint(point, direction, obstacle, direction + (useMax ? 'Max' : 'Min'), useMax ? 1 : -1); + } + // Pull out end point + if (endObstacleIx > -1) { + endObstacle = chartObstacles[endObstacleIx]; + waypoint = getMeOut(endObstacle, end, dir); + endSegment = { + start: waypoint, + end: end + }; + endPoint = waypoint; + } + else { + endPoint = end; + } + // If an obstacle envelops the start point, add a segment to get out, + // and around it. + if (startObstacleIx > -1) { + startObstacle = chartObstacles[startObstacleIx]; + waypoint = getMeOut(startObstacle, start, dir); + segments.push({ + start: start, + end: waypoint + }); + // If we are going back again, switch direction to get around start + // obstacle. + if ( + // Going towards max from start: + waypoint[dir] >= start[dir] === + // Going towards min to end: + waypoint[dir] >= endPoint[dir]) { + dir = dir === 'y' ? 'x' : 'y'; + useMax = start[dir] < end[dir]; + segments.push({ + start: waypoint, + end: copyFromPoint(waypoint, dir, startObstacle, dir + (useMax ? 'Max' : 'Min'), useMax ? 1 : -1) + }); + // Switch direction again + dir = dir === 'y' ? 'x' : 'y'; + } + } + // We are around the start obstacle. Go towards the end in one + // direction. + prevWaypoint = segments.length ? + segments[segments.length - 1].end : + start; + waypoint = copyFromPoint(prevWaypoint, dir, endPoint); + segments.push({ + start: prevWaypoint, + end: waypoint + }); + // Final run to end point in the other direction + dir = dir === 'y' ? 'x' : 'y'; + waypoint2 = copyFromPoint(waypoint, dir, endPoint); + segments.push({ + start: waypoint, + end: waypoint2 + }); + // Finally add the endSegment + segments.push(endSegment); + return { + path: pathFromSegments(segments), + obstacles: segments + }; + }, { + requiresObstacles: true + }), + /** + * Find a path from a starting coordinate to an ending coordinate, taking + * obstacles into consideration. Might not always find the optimal path, + * but is fast, and usually good enough. + * + * @function Highcharts.Pathfinder.algorithms.fastAvoid + * + * @param {Highcharts.PositionObject} start + * Starting coordinate, object with x/y props. + * + * @param {Highcharts.PositionObject} end + * Ending coordinate, object with x/y props. + * + * @param {object} options + * Options for the algorithm. + * - chartObstacles: Array of chart obstacles to avoid + * - lineObstacles: Array of line obstacles to jump over + * - obstacleMetrics: Object with metrics of chartObstacles cached + * - hardBounds: Hard boundaries to not cross + * - obstacleOptions: Options for the obstacles, including margin + * - startDirectionX: Optional. True if starting in the X direction. + * If not provided, the algorithm starts in the + * direction that is the furthest between + * start/end. + * + * @return {object} + * An object with the SVG path in Array form as accepted by the SVG + * renderer, as well as an array of new obstacles making up this + * path. + */ + fastAvoid: extend(function (start, end, options) { + /* + Algorithm rules/description + - Find initial direction + - Determine soft/hard max for each direction. + - Move along initial direction until obstacle. + - Change direction. + - If hitting obstacle, first try to change length of previous line + before changing direction again. + + Soft min/max x = start/destination x +/- widest obstacle + margin + Soft min/max y = start/destination y +/- tallest obstacle + margin + + @todo: + - Make retrospective, try changing prev segment to reduce + corners + - Fix logic for breaking out of end-points - not always picking + the best direction currently + - When going around the end obstacle we should not always go the + shortest route, rather pick the one closer to the end point + */ + var dirIsX = pick(options.startDirectionX, abs(end.x - start.x) > abs(end.y - start.y)), dir = dirIsX ? 'x' : 'y', segments, useMax, extractedEndPoint, endSegments = [], forceObstacleBreak = false, // Used in clearPathTo to keep track of + // when to force break through an obstacle. + // Boundaries to stay within. If beyond soft boundary, prefer to + // change direction ASAP. If at hard max, always change immediately. + metrics = options.obstacleMetrics, softMinX = min(start.x, end.x) - metrics.maxWidth - 10, softMaxX = max(start.x, end.x) + metrics.maxWidth + 10, softMinY = min(start.y, end.y) - metrics.maxHeight - 10, softMaxY = max(start.y, end.y) + metrics.maxHeight + 10, + // Obstacles + chartObstacles = options.chartObstacles, startObstacleIx = findLastObstacleBefore(chartObstacles, softMinX), endObstacleIx = findLastObstacleBefore(chartObstacles, softMaxX); + // eslint-disable-next-line valid-jsdoc + /** + * How far can you go between two points before hitting an obstacle? + * Does not work for diagonal lines (because it doesn't have to). + * @private + */ + function pivotPoint(fromPoint, toPoint, directionIsX) { + var firstPoint, lastPoint, highestPoint, lowestPoint, i, searchDirection = fromPoint.x < toPoint.x ? 1 : -1; + if (fromPoint.x < toPoint.x) { + firstPoint = fromPoint; + lastPoint = toPoint; + } + else { + firstPoint = toPoint; + lastPoint = fromPoint; + } + if (fromPoint.y < toPoint.y) { + lowestPoint = fromPoint; + highestPoint = toPoint; + } + else { + lowestPoint = toPoint; + highestPoint = fromPoint; + } + // Go through obstacle range in reverse if toPoint is before + // fromPoint in the X-dimension. + i = searchDirection < 0 ? + // Searching backwards, start at last obstacle before last point + min(findLastObstacleBefore(chartObstacles, lastPoint.x), chartObstacles.length - 1) : + // Forwards. Since we're not sorted by xMax, we have to look + // at all obstacles. + 0; + // Go through obstacles in this X range + while (chartObstacles[i] && (searchDirection > 0 && chartObstacles[i].xMin <= lastPoint.x || + searchDirection < 0 && chartObstacles[i].xMax >= firstPoint.x)) { + // If this obstacle is between from and to points in a straight + // line, pivot at the intersection. + if (chartObstacles[i].xMin <= lastPoint.x && + chartObstacles[i].xMax >= firstPoint.x && + chartObstacles[i].yMin <= highestPoint.y && + chartObstacles[i].yMax >= lowestPoint.y) { + if (directionIsX) { + return { + y: fromPoint.y, + x: fromPoint.x < toPoint.x ? + chartObstacles[i].xMin - 1 : + chartObstacles[i].xMax + 1, + obstacle: chartObstacles[i] + }; + } + // else ... + return { + x: fromPoint.x, + y: fromPoint.y < toPoint.y ? + chartObstacles[i].yMin - 1 : + chartObstacles[i].yMax + 1, + obstacle: chartObstacles[i] + }; + } + i += searchDirection; + } + return toPoint; + } + /** + * Decide in which direction to dodge or get out of an obstacle. + * Considers desired direction, which way is shortest, soft and hard + * bounds. + * + * (? Returns a string, either xMin, xMax, yMin or yMax.) + * + * @private + * @function + * + * @param {object} obstacle + * Obstacle to dodge/escape. + * + * @param {object} fromPoint + * Point with x/y props that's dodging/escaping. + * + * @param {object} toPoint + * Goal point. + * + * @param {boolean} dirIsX + * Dodge in X dimension. + * + * @param {object} bounds + * Hard and soft boundaries. + * + * @return {boolean} + * Use max or not. + */ + function getDodgeDirection(obstacle, fromPoint, toPoint, dirIsX, bounds) { + var softBounds = bounds.soft, hardBounds = bounds.hard, dir = dirIsX ? 'x' : 'y', toPointMax = { x: fromPoint.x, y: fromPoint.y }, toPointMin = { x: fromPoint.x, y: fromPoint.y }, minPivot, maxPivot, maxOutOfSoftBounds = obstacle[dir + 'Max'] >= + softBounds[dir + 'Max'], minOutOfSoftBounds = obstacle[dir + 'Min'] <= + softBounds[dir + 'Min'], maxOutOfHardBounds = obstacle[dir + 'Max'] >= + hardBounds[dir + 'Max'], minOutOfHardBounds = obstacle[dir + 'Min'] <= + hardBounds[dir + 'Min'], + // Find out if we should prefer one direction over the other if + // we can choose freely + minDistance = abs(obstacle[dir + 'Min'] - fromPoint[dir]), maxDistance = abs(obstacle[dir + 'Max'] - fromPoint[dir]), + // If it's a small difference, pick the one leading towards dest + // point. Otherwise pick the shortest distance + useMax = abs(minDistance - maxDistance) < 10 ? + fromPoint[dir] < toPoint[dir] : + maxDistance < minDistance; + // Check if we hit any obstacles trying to go around in either + // direction. + toPointMin[dir] = obstacle[dir + 'Min']; + toPointMax[dir] = obstacle[dir + 'Max']; + minPivot = pivotPoint(fromPoint, toPointMin, dirIsX)[dir] !== + toPointMin[dir]; + maxPivot = pivotPoint(fromPoint, toPointMax, dirIsX)[dir] !== + toPointMax[dir]; + useMax = minPivot ? + (maxPivot ? useMax : true) : + (maxPivot ? false : useMax); + // useMax now contains our preferred choice, bounds not taken into + // account. If both or neither direction is out of bounds we want to + // use this. + // Deal with soft bounds + useMax = minOutOfSoftBounds ? + (maxOutOfSoftBounds ? useMax : true) : // Out on min + (maxOutOfSoftBounds ? false : useMax); // Not out on min + // Deal with hard bounds + useMax = minOutOfHardBounds ? + (maxOutOfHardBounds ? useMax : true) : // Out on min + (maxOutOfHardBounds ? false : useMax); // Not out on min + return useMax; + } + // eslint-disable-next-line valid-jsdoc + /** + * Find a clear path between point. + * @private + */ + function clearPathTo(fromPoint, toPoint, dirIsX) { + // Don't waste time if we've hit goal + if (fromPoint.x === toPoint.x && fromPoint.y === toPoint.y) { + return []; + } + var dir = dirIsX ? 'x' : 'y', pivot, segments, waypoint, waypointUseMax, envelopingObstacle, secondEnvelopingObstacle, envelopWaypoint, obstacleMargin = options.obstacleOptions.margin, bounds = { + soft: { + xMin: softMinX, + xMax: softMaxX, + yMin: softMinY, + yMax: softMaxY + }, + hard: options.hardBounds + }; + // If fromPoint is inside an obstacle we have a problem. Break out + // by just going to the outside of this obstacle. We prefer to go to + // the nearest edge in the chosen direction. + envelopingObstacle = + findObstacleFromPoint(chartObstacles, fromPoint); + if (envelopingObstacle > -1) { + envelopingObstacle = chartObstacles[envelopingObstacle]; + waypointUseMax = getDodgeDirection(envelopingObstacle, fromPoint, toPoint, dirIsX, bounds); + // Cut obstacle to hard bounds to make sure we stay within + limitObstacleToBounds(envelopingObstacle, options.hardBounds); + envelopWaypoint = dirIsX ? { + y: fromPoint.y, + x: envelopingObstacle[waypointUseMax ? 'xMax' : 'xMin'] + + (waypointUseMax ? 1 : -1) + } : { + x: fromPoint.x, + y: envelopingObstacle[waypointUseMax ? 'yMax' : 'yMin'] + + (waypointUseMax ? 1 : -1) + }; + // If we crashed into another obstacle doing this, we put the + // waypoint between them instead + secondEnvelopingObstacle = findObstacleFromPoint(chartObstacles, envelopWaypoint); + if (secondEnvelopingObstacle > -1) { + secondEnvelopingObstacle = chartObstacles[secondEnvelopingObstacle]; + // Cut obstacle to hard bounds + limitObstacleToBounds(secondEnvelopingObstacle, options.hardBounds); + // Modify waypoint to lay between obstacles + envelopWaypoint[dir] = waypointUseMax ? max(envelopingObstacle[dir + 'Max'] - obstacleMargin + 1, (secondEnvelopingObstacle[dir + 'Min'] + + envelopingObstacle[dir + 'Max']) / 2) : + min((envelopingObstacle[dir + 'Min'] + obstacleMargin - 1), ((secondEnvelopingObstacle[dir + 'Max'] + + envelopingObstacle[dir + 'Min']) / 2)); + // We are not going anywhere. If this happens for the first + // time, do nothing. Otherwise, try to go to the extreme of + // the obstacle pair in the current direction. + if (fromPoint.x === envelopWaypoint.x && + fromPoint.y === envelopWaypoint.y) { + if (forceObstacleBreak) { + envelopWaypoint[dir] = waypointUseMax ? + max(envelopingObstacle[dir + 'Max'], secondEnvelopingObstacle[dir + 'Max']) + 1 : + min(envelopingObstacle[dir + 'Min'], secondEnvelopingObstacle[dir + 'Min']) - 1; + } + // Toggle on if off, and the opposite + forceObstacleBreak = !forceObstacleBreak; + } + else { + // This point is not identical to previous. + // Clear break trigger. + forceObstacleBreak = false; + } + } + segments = [{ + start: fromPoint, + end: envelopWaypoint + }]; + } + else { // If not enveloping, use standard pivot calculation + pivot = pivotPoint(fromPoint, { + x: dirIsX ? toPoint.x : fromPoint.x, + y: dirIsX ? fromPoint.y : toPoint.y + }, dirIsX); + segments = [{ + start: fromPoint, + end: { + x: pivot.x, + y: pivot.y + } + }]; + // Pivot before goal, use a waypoint to dodge obstacle + if (pivot[dirIsX ? 'x' : 'y'] !== toPoint[dirIsX ? 'x' : 'y']) { + // Find direction of waypoint + waypointUseMax = getDodgeDirection(pivot.obstacle, pivot, toPoint, !dirIsX, bounds); + // Cut waypoint to hard bounds + limitObstacleToBounds(pivot.obstacle, options.hardBounds); + waypoint = { + x: dirIsX ? + pivot.x : + pivot.obstacle[waypointUseMax ? 'xMax' : 'xMin'] + + (waypointUseMax ? 1 : -1), + y: dirIsX ? + pivot.obstacle[waypointUseMax ? 'yMax' : 'yMin'] + + (waypointUseMax ? 1 : -1) : + pivot.y + }; + // We're changing direction here, store that to make sure we + // also change direction when adding the last segment array + // after handling waypoint. + dirIsX = !dirIsX; + segments = segments.concat(clearPathTo({ + x: pivot.x, + y: pivot.y + }, waypoint, dirIsX)); + } + } + // Get segments for the other direction too + // Recursion is our friend + segments = segments.concat(clearPathTo(segments[segments.length - 1].end, toPoint, !dirIsX)); + return segments; + } + // eslint-disable-next-line valid-jsdoc + /** + * Extract point to outside of obstacle in whichever direction is + * closest. Returns new point outside obstacle. + * @private + */ + function extractFromObstacle(obstacle, point, goalPoint) { + var dirIsX = min(obstacle.xMax - point.x, point.x - obstacle.xMin) < + min(obstacle.yMax - point.y, point.y - obstacle.yMin), bounds = { + soft: options.hardBounds, + hard: options.hardBounds + }, useMax = getDodgeDirection(obstacle, point, goalPoint, dirIsX, bounds); + return dirIsX ? { + y: point.y, + x: obstacle[useMax ? 'xMax' : 'xMin'] + (useMax ? 1 : -1) + } : { + x: point.x, + y: obstacle[useMax ? 'yMax' : 'yMin'] + (useMax ? 1 : -1) + }; + } + // Cut the obstacle array to soft bounds for optimization in large + // datasets. + chartObstacles = + chartObstacles.slice(startObstacleIx, endObstacleIx + 1); + // If an obstacle envelops the end point, move it out of there and add + // a little segment to where it was. + if ((endObstacleIx = findObstacleFromPoint(chartObstacles, end)) > -1) { + extractedEndPoint = extractFromObstacle(chartObstacles[endObstacleIx], end, start); + endSegments.push({ + end: end, + start: extractedEndPoint + }); + end = extractedEndPoint; + } + // If it's still inside one or more obstacles, get out of there by + // force-moving towards the start point. + while ((endObstacleIx = findObstacleFromPoint(chartObstacles, end)) > -1) { + useMax = end[dir] - start[dir] < 0; + extractedEndPoint = { + x: end.x, + y: end.y + }; + extractedEndPoint[dir] = chartObstacles[endObstacleIx][useMax ? dir + 'Max' : dir + 'Min'] + (useMax ? 1 : -1); + endSegments.push({ + end: end, + start: extractedEndPoint + }); + end = extractedEndPoint; + } + // Find the path + segments = clearPathTo(start, end, dirIsX); + // Add the end-point segments + segments = segments.concat(endSegments.reverse()); + return { + path: pathFromSegments(segments), + obstacles: segments + }; + }, { + requiresObstacles: true + }) + }; + + return algorithms; + }); + _registerModule(_modules, 'parts-gantt/ArrowSymbols.js', [_modules['parts/Globals.js']], function (H) { + /* * + * + * (c) 2017 Highsoft AS + * Authors: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Creates an arrow symbol. Like a triangle, except not filled. + * ``` + * o + * o + * o + * o + * o + * o + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols.arrow = function (x, y, w, h) { + return [ + ['M', x, y + h / 2], + ['L', x + w, y], + ['L', x, y + h / 2], + ['L', x + w, y + h] + ]; + }; + /** + * Creates a half-width arrow symbol. Like a triangle, except not filled. + * ``` + * o + * o + * o + * o + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols['arrow-half'] = function (x, y, w, h) { + return H.SVGRenderer.prototype.symbols.arrow(x, y, w / 2, h); + }; + /** + * Creates a left-oriented triangle. + * ``` + * o + * ooooooo + * ooooooooooooo + * ooooooo + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the triangle + * + * @param {number} y + * y position of the triangle + * + * @param {number} w + * width of the triangle + * + * @param {number} h + * height of the triangle + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols['triangle-left'] = function (x, y, w, h) { + return [ + ['M', x + w, y], + ['L', x, y + h / 2], + ['L', x + w, y + h], + ['Z'] + ]; + }; + /** + * Alias function for triangle-left. + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols['arrow-filled'] = + H.SVGRenderer.prototype.symbols['triangle-left']; + /** + * Creates a half-width, left-oriented triangle. + * ``` + * o + * oooo + * ooooooo + * oooo + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the triangle + * + * @param {number} y + * y position of the triangle + * + * @param {number} w + * width of the triangle + * + * @param {number} h + * height of the triangle + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols['triangle-left-half'] = function (x, y, w, h) { + return H.SVGRenderer.prototype.symbols['triangle-left'](x, y, w / 2, h); + }; + /** + * Alias function for triangle-left-half. + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols['arrow-filled-half'] = + H.SVGRenderer.prototype.symbols['triangle-left-half']; + + }); + _registerModule(_modules, 'parts-gantt/Pathfinder.js', [_modules['parts/Globals.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js'], _modules['parts-gantt/PathfinderAlgorithms.js']], function (H, Point, U, pathfinderAlgorithms) { + /* * + * + * (c) 2016 Highsoft AS + * Authors: Øystein Moseng, Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * The default pathfinder algorithm to use for a chart. It is possible to define + * your own algorithms by adding them to the + * `Highcharts.Pathfinder.prototype.algorithms` + * object before the chart has been created. + * + * The default algorithms are as follows: + * + * `straight`: Draws a straight line between the connecting + * points. Does not avoid other points when drawing. + * + * `simpleConnect`: Finds a path between the points using right angles + * only. Takes only starting/ending points into + * account, and will not avoid other points. + * + * `fastAvoid`: Finds a path between the points using right angles + * only. Will attempt to avoid other points, but its + * focus is performance over accuracy. Works well with + * less dense datasets. + * + * @typedef {"fastAvoid"|"simpleConnect"|"straight"|string} Highcharts.PathfinderTypeValue + */ + ''; // detach doclets above + var addEvent = U.addEvent, defined = U.defined, error = U.error, extend = U.extend, merge = U.merge, objectEach = U.objectEach, pick = U.pick, splat = U.splat; + var deg2rad = H.deg2rad, max = Math.max, min = Math.min; + /* + @todo: + - Document how to write your own algorithms + - Consider adding a Point.pathTo method that wraps creating a connection + and rendering it + */ + // Set default Pathfinder options + extend(H.defaultOptions, { + /** + * The Pathfinder module allows you to define connections between any two + * points, represented as lines - optionally with markers for the start + * and/or end points. Multiple algorithms are available for calculating how + * the connecting lines are drawn. + * + * Connector functionality requires Highcharts Gantt to be loaded. In Gantt + * charts, the connectors are used to draw dependencies between tasks. + * + * @see [dependency](series.gantt.data.dependency) + * + * @sample gantt/pathfinder/demo + * Pathfinder connections + * + * @declare Highcharts.ConnectorsOptions + * @product gantt + * @optionparent connectors + */ + connectors: { + /** + * Enable connectors for this chart. Requires Highcharts Gantt. + * + * @type {boolean} + * @default true + * @since 6.2.0 + * @apioption connectors.enabled + */ + /** + * Set the default dash style for this chart's connecting lines. + * + * @type {string} + * @default solid + * @since 6.2.0 + * @apioption connectors.dashStyle + */ + /** + * Set the default color for this chart's Pathfinder connecting lines. + * Defaults to the color of the point being connected. + * + * @type {Highcharts.ColorString} + * @since 6.2.0 + * @apioption connectors.lineColor + */ + /** + * Set the default pathfinder margin to use, in pixels. Some Pathfinder + * algorithms attempt to avoid obstacles, such as other points in the + * chart. These algorithms use this margin to determine how close lines + * can be to an obstacle. The default is to compute this automatically + * from the size of the obstacles in the chart. + * + * To draw connecting lines close to existing points, set this to a low + * number. For more space around existing points, set this number + * higher. + * + * @sample gantt/pathfinder/algorithm-margin + * Small algorithmMargin + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.algorithmMargin + */ + /** + * Set the default pathfinder algorithm to use for this chart. It is + * possible to define your own algorithms by adding them to the + * Highcharts.Pathfinder.prototype.algorithms object before the chart + * has been created. + * + * The default algorithms are as follows: + * + * `straight`: Draws a straight line between the connecting + * points. Does not avoid other points when drawing. + * + * `simpleConnect`: Finds a path between the points using right angles + * only. Takes only starting/ending points into + * account, and will not avoid other points. + * + * `fastAvoid`: Finds a path between the points using right angles + * only. Will attempt to avoid other points, but its + * focus is performance over accuracy. Works well with + * less dense datasets. + * + * Default value: `straight` is used as default for most series types, + * while `simpleConnect` is used as default for Gantt series, to show + * dependencies between points. + * + * @sample gantt/pathfinder/demo + * Different types used + * + * @type {Highcharts.PathfinderTypeValue} + * @default undefined + * @since 6.2.0 + */ + type: 'straight', + /** + * Set the default pixel width for this chart's Pathfinder connecting + * lines. + * + * @since 6.2.0 + */ + lineWidth: 1, + /** + * Marker options for this chart's Pathfinder connectors. Note that + * this option is overridden by the `startMarker` and `endMarker` + * options. + * + * @declare Highcharts.ConnectorsMarkerOptions + * @since 6.2.0 + */ + marker: { + /** + * Set the radius of the connector markers. The default is + * automatically computed based on the algorithmMargin setting. + * + * Setting marker.width and marker.height will override this + * setting. + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.marker.radius + */ + /** + * Set the width of the connector markers. If not supplied, this + * is inferred from the marker radius. + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.marker.width + */ + /** + * Set the height of the connector markers. If not supplied, this + * is inferred from the marker radius. + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.marker.height + */ + /** + * Set the color of the connector markers. By default this is the + * same as the connector color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 6.2.0 + * @apioption connectors.marker.color + */ + /** + * Set the line/border color of the connector markers. By default + * this is the same as the marker color. + * + * @type {Highcharts.ColorString} + * @since 6.2.0 + * @apioption connectors.marker.lineColor + */ + /** + * Enable markers for the connectors. + */ + enabled: false, + /** + * Horizontal alignment of the markers relative to the points. + * + * @type {Highcharts.AlignValue} + */ + align: 'center', + /** + * Vertical alignment of the markers relative to the points. + * + * @type {Highcharts.VerticalAlignValue} + */ + verticalAlign: 'middle', + /** + * Whether or not to draw the markers inside the points. + */ + inside: false, + /** + * Set the line/border width of the pathfinder markers. + */ + lineWidth: 1 + }, + /** + * Marker options specific to the start markers for this chart's + * Pathfinder connectors. Overrides the generic marker options. + * + * @declare Highcharts.ConnectorsStartMarkerOptions + * @extends connectors.marker + * @since 6.2.0 + */ + startMarker: { + /** + * Set the symbol of the connector start markers. + */ + symbol: 'diamond' + }, + /** + * Marker options specific to the end markers for this chart's + * Pathfinder connectors. Overrides the generic marker options. + * + * @declare Highcharts.ConnectorsEndMarkerOptions + * @extends connectors.marker + * @since 6.2.0 + */ + endMarker: { + /** + * Set the symbol of the connector end markers. + */ + symbol: 'arrow-filled' + } + } + }); + /** + * Override Pathfinder connector options for a series. Requires Highcharts Gantt + * to be loaded. + * + * @declare Highcharts.SeriesConnectorsOptionsObject + * @extends connectors + * @since 6.2.0 + * @excluding enabled, algorithmMargin + * @product gantt + * @apioption plotOptions.series.connectors + */ + /** + * Connect to a point. This option can be either a string, referring to the ID + * of another point, or an object, or an array of either. If the option is an + * array, each element defines a connection. + * + * @sample gantt/pathfinder/demo + * Different connection types + * + * @declare Highcharts.XrangePointConnectorsOptionsObject + * @type {string|Array|*} + * @extends plotOptions.series.connectors + * @since 6.2.0 + * @excluding enabled + * @product gantt + * @requires highcharts-gantt + * @apioption series.xrange.data.connect + */ + /** + * The ID of the point to connect to. + * + * @type {string} + * @since 6.2.0 + * @product gantt + * @apioption series.xrange.data.connect.to + */ + /** + * Get point bounding box using plotX/plotY and shapeArgs. If using + * graphic.getBBox() directly, the bbox will be affected by animation. + * + * @private + * @function + * + * @param {Highcharts.Point} point + * The point to get BB of. + * + * @return {Highcharts.Dictionary|null} + * Result xMax, xMin, yMax, yMin. + */ + function getPointBB(point) { + var shapeArgs = point.shapeArgs, bb; + // Prefer using shapeArgs (columns) + if (shapeArgs) { + return { + xMin: shapeArgs.x, + xMax: shapeArgs.x + shapeArgs.width, + yMin: shapeArgs.y, + yMax: shapeArgs.y + shapeArgs.height + }; + } + // Otherwise use plotX/plotY and bb + bb = point.graphic && point.graphic.getBBox(); + return bb ? { + xMin: point.plotX - bb.width / 2, + xMax: point.plotX + bb.width / 2, + yMin: point.plotY - bb.height / 2, + yMax: point.plotY + bb.height / 2 + } : null; + } + /** + * Calculate margin to place around obstacles for the pathfinder in pixels. + * Returns a minimum of 1 pixel margin. + * + * @private + * @function + * + * @param {Array} obstacles + * Obstacles to calculate margin from. + * + * @return {number} + * The calculated margin in pixels. At least 1. + */ + function calculateObstacleMargin(obstacles) { + var len = obstacles.length, i = 0, j, obstacleDistance, distances = [], + // Compute smallest distance between two rectangles + distance = function (a, b, bbMargin) { + // Count the distance even if we are slightly off + var margin = pick(bbMargin, 10), yOverlap = a.yMax + margin > b.yMin - margin && + a.yMin - margin < b.yMax + margin, xOverlap = a.xMax + margin > b.xMin - margin && + a.xMin - margin < b.xMax + margin, xDistance = yOverlap ? (a.xMin > b.xMax ? a.xMin - b.xMax : b.xMin - a.xMax) : Infinity, yDistance = xOverlap ? (a.yMin > b.yMax ? a.yMin - b.yMax : b.yMin - a.yMax) : Infinity; + // If the rectangles collide, try recomputing with smaller margin. + // If they collide anyway, discard the obstacle. + if (xOverlap && yOverlap) { + return (margin ? + distance(a, b, Math.floor(margin / 2)) : + Infinity); + } + return min(xDistance, yDistance); + }; + // Go over all obstacles and compare them to the others. + for (; i < len; ++i) { + // Compare to all obstacles ahead. We will already have compared this + // obstacle to the ones before. + for (j = i + 1; j < len; ++j) { + obstacleDistance = distance(obstacles[i], obstacles[j]); + // TODO: Magic number 80 + if (obstacleDistance < 80) { // Ignore large distances + distances.push(obstacleDistance); + } + } + } + // Ensure we always have at least one value, even in very spaceous charts + distances.push(80); + return max(Math.floor(distances.sort(function (a, b) { + return (a - b); + })[ + // Discard first 10% of the relevant distances, and then grab + // the smallest one. + Math.floor(distances.length / 10)] / 2 - 1 // Divide the distance by 2 and subtract 1. + ), 1 // 1 is the minimum margin + ); + } + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The Connection class. Used internally to represent a connection between two + * points. + * + * @private + * @class + * @name Highcharts.Connection + * + * @param {Highcharts.Point} from + * Connection runs from this Point. + * + * @param {Highcharts.Point} to + * Connection runs to this Point. + * + * @param {Highcharts.ConnectorsOptions} [options] + * Connection options. + */ + function Connection(from, to, options) { + this.init(from, to, options); + } + Connection.prototype = { + /** + * Initialize the Connection object. Used as constructor only. + * + * @function Highcharts.Connection#init + * + * @param {Highcharts.Point} from + * Connection runs from this Point. + * + * @param {Highcharts.Point} to + * Connection runs to this Point. + * + * @param {Highcharts.ConnectorsOptions} [options] + * Connection options. + */ + init: function (from, to, options) { + this.fromPoint = from; + this.toPoint = to; + this.options = options; + this.chart = from.series.chart; + this.pathfinder = this.chart.pathfinder; + }, + /** + * Add (or update) this connection's path on chart. Stores reference to the + * created element on this.graphics.path. + * + * @function Highcharts.Connection#renderPath + * + * @param {Highcharts.SVGPathArray} path + * Path to render, in array format. E.g. ['M', 0, 0, 'L', 10, 10] + * + * @param {Highcharts.SVGAttributes} [attribs] + * SVG attributes for the path. + * + * @param {Highcharts.AnimationOptionsObject} [animation] + * Animation options for the rendering. + */ + renderPath: function (path, attribs, animation) { + var connection = this, chart = this.chart, styledMode = chart.styledMode, pathfinder = chart.pathfinder, animate = !chart.options.chart.forExport && animation !== false, pathGraphic = connection.graphics && connection.graphics.path, anim; + // Add the SVG element of the pathfinder group if it doesn't exist + if (!pathfinder.group) { + pathfinder.group = chart.renderer.g() + .addClass('highcharts-pathfinder-group') + .attr({ zIndex: -1 }) + .add(chart.seriesGroup); + } + // Shift the group to compensate for plot area. + // Note: Do this always (even when redrawing a path) to avoid issues + // when updating chart in a way that changes plot metrics. + pathfinder.group.translate(chart.plotLeft, chart.plotTop); + // Create path if does not exist + if (!(pathGraphic && pathGraphic.renderer)) { + pathGraphic = chart.renderer.path() + .add(pathfinder.group); + if (!styledMode) { + pathGraphic.attr({ + opacity: 0 + }); + } + } + // Set path attribs and animate to the new path + pathGraphic.attr(attribs); + anim = { d: path }; + if (!styledMode) { + anim.opacity = 1; + } + pathGraphic[animate ? 'animate' : 'attr'](anim, animation); + // Store reference on connection + this.graphics = this.graphics || {}; + this.graphics.path = pathGraphic; + }, + /** + * Calculate and add marker graphics for connection to the chart. The + * created/updated elements are stored on this.graphics.start and + * this.graphics.end. + * + * @function Highcharts.Connection#addMarker + * + * @param {string} type + * Marker type, either 'start' or 'end'. + * + * @param {Highcharts.ConnectorsMarkerOptions} options + * All options for this marker. Not calculated or merged with other + * options. + * + * @param {Highcharts.SVGPathArray} path + * Connection path in array format. This is used to calculate the + * rotation angle of the markers. + */ + addMarker: function (type, options, path) { + var connection = this, chart = connection.fromPoint.series.chart, pathfinder = chart.pathfinder, renderer = chart.renderer, point = (type === 'start' ? + connection.fromPoint : + connection.toPoint), anchor = point.getPathfinderAnchorPoint(options), markerVector, radians, rotation, box, width, height, pathVector, segment; + if (!options.enabled) { + return; + } + // Last vector before start/end of path, used to get angle + if (type === 'start') { + segment = path[1]; + } + else { // 'end' + segment = path[path.length - 2]; + } + if (segment && segment[0] === 'M' || segment[0] === 'L') { + pathVector = { + x: segment[1], + y: segment[2] + }; + // Get angle between pathVector and anchor point and use it to + // create marker position. + radians = point.getRadiansToVector(pathVector, anchor); + markerVector = point.getMarkerVector(radians, options.radius, anchor); + // Rotation of marker is calculated from angle between pathVector + // and markerVector. + // (Note: + // Used to recalculate radians between markerVector and pathVector, + // but this should be the same as between pathVector and anchor.) + rotation = -radians / deg2rad; + if (options.width && options.height) { + width = options.width; + height = options.height; + } + else { + width = height = options.radius * 2; + } + // Add graphics object if it does not exist + connection.graphics = connection.graphics || {}; + box = { + x: markerVector.x - (width / 2), + y: markerVector.y - (height / 2), + width: width, + height: height, + rotation: rotation, + rotationOriginX: markerVector.x, + rotationOriginY: markerVector.y + }; + if (!connection.graphics[type]) { + // Create new marker element + connection.graphics[type] = renderer + .symbol(options.symbol) + .addClass('highcharts-point-connecting-path-' + type + '-marker') + .attr(box) + .add(pathfinder.group); + if (!renderer.styledMode) { + connection.graphics[type].attr({ + fill: options.color || connection.fromPoint.color, + stroke: options.lineColor, + 'stroke-width': options.lineWidth, + opacity: 0 + }) + .animate({ + opacity: 1 + }, point.series.options.animation); + } + } + else { + connection.graphics[type].animate(box); + } + } + }, + /** + * Calculate and return connection path. + * Note: Recalculates chart obstacles on demand if they aren't calculated. + * + * @function Highcharts.Connection#getPath + * + * @param {Highcharts.ConnectorsOptions} options + * Connector options. Not calculated or merged with other options. + * + * @return {object|undefined} + * Calculated SVG path data in array format. + */ + getPath: function (options) { + var pathfinder = this.pathfinder, chart = this.chart, algorithm = pathfinder.algorithms[options.type], chartObstacles = pathfinder.chartObstacles; + if (typeof algorithm !== 'function') { + error('"' + options.type + '" is not a Pathfinder algorithm.'); + return; + } + // This function calculates obstacles on demand if they don't exist + if (algorithm.requiresObstacles && !chartObstacles) { + chartObstacles = + pathfinder.chartObstacles = + pathfinder.getChartObstacles(options); + // If the algorithmMargin was computed, store the result in default + // options. + chart.options.connectors.algorithmMargin = + options.algorithmMargin; + // Cache some metrics too + pathfinder.chartObstacleMetrics = + pathfinder.getObstacleMetrics(chartObstacles); + } + // Get the SVG path + return algorithm( + // From + this.fromPoint.getPathfinderAnchorPoint(options.startMarker), + // To + this.toPoint.getPathfinderAnchorPoint(options.endMarker), merge({ + chartObstacles: chartObstacles, + lineObstacles: pathfinder.lineObstacles || [], + obstacleMetrics: pathfinder.chartObstacleMetrics, + hardBounds: { + xMin: 0, + xMax: chart.plotWidth, + yMin: 0, + yMax: chart.plotHeight + }, + obstacleOptions: { + margin: options.algorithmMargin + }, + startDirectionX: pathfinder.getAlgorithmStartDirection(options.startMarker) + }, options)); + }, + /** + * (re)Calculate and (re)draw the connection. + * + * @function Highcharts.Connection#render + */ + render: function () { + var connection = this, fromPoint = connection.fromPoint, series = fromPoint.series, chart = series.chart, pathfinder = chart.pathfinder, pathResult, path, options = merge(chart.options.connectors, series.options.connectors, fromPoint.options.connectors, connection.options), attribs = {}; + // Set path attribs + if (!chart.styledMode) { + attribs.stroke = options.lineColor || fromPoint.color; + attribs['stroke-width'] = options.lineWidth; + if (options.dashStyle) { + attribs.dashstyle = options.dashStyle; + } + } + attribs['class'] = // eslint-disable-line dot-notation + 'highcharts-point-connecting-path ' + + 'highcharts-color-' + fromPoint.colorIndex; + options = merge(attribs, options); + // Set common marker options + if (!defined(options.marker.radius)) { + options.marker.radius = min(max(Math.ceil((options.algorithmMargin || 8) / 2) - 1, 1), 5); + } + // Get the path + pathResult = connection.getPath(options); + path = pathResult.path; + // Always update obstacle storage with obstacles from this path. + // We don't know if future calls will need this for their algorithm. + if (pathResult.obstacles) { + pathfinder.lineObstacles = + pathfinder.lineObstacles || []; + pathfinder.lineObstacles = + pathfinder.lineObstacles.concat(pathResult.obstacles); + } + // Add the calculated path to the pathfinder group + connection.renderPath(path, attribs, series.options.animation); + // Render the markers + connection.addMarker('start', merge(options.marker, options.startMarker), path); + connection.addMarker('end', merge(options.marker, options.endMarker), path); + }, + /** + * Destroy connection by destroying the added graphics elements. + * + * @function Highcharts.Connection#destroy + */ + destroy: function () { + if (this.graphics) { + objectEach(this.graphics, function (val) { + val.destroy(); + }); + delete this.graphics; + } + } + }; + /** + * The Pathfinder class. + * + * @private + * @class + * @name Highcharts.Pathfinder + * + * @param {Highcharts.Chart} chart + * The chart to operate on. + */ + function Pathfinder(chart) { + this.init(chart); + } + Pathfinder.prototype = { + /** + * @name Highcharts.Pathfinder#algorithms + * @type {Highcharts.Dictionary} + */ + algorithms: pathfinderAlgorithms, + /** + * Initialize the Pathfinder object. + * + * @function Highcharts.Pathfinder#init + * + * @param {Highcharts.Chart} chart + * The chart context. + */ + init: function (chart) { + // Initialize pathfinder with chart context + this.chart = chart; + // Init connection reference list + this.connections = []; + // Recalculate paths/obstacles on chart redraw + addEvent(chart, 'redraw', function () { + this.pathfinder.update(); + }); + }, + /** + * Update Pathfinder connections from scratch. + * + * @function Highcharts.Pathfinder#update + * + * @param {boolean} [deferRender] + * Whether or not to defer rendering of connections until + * series.afterAnimate event has fired. Used on first render. + */ + update: function (deferRender) { + var chart = this.chart, pathfinder = this, oldConnections = pathfinder.connections; + // Rebuild pathfinder connections from options + pathfinder.connections = []; + chart.series.forEach(function (series) { + if (series.visible && !series.options.isInternal) { + series.points.forEach(function (point) { + var to, connects = (point.options && + point.options.connect && + splat(point.options.connect)); + if (point.visible && point.isInside !== false && connects) { + connects.forEach(function (connect) { + to = chart.get(typeof connect === 'string' ? + connect : connect.to); + if (to instanceof Point && + to.series.visible && + to.visible && + to.isInside !== false) { + // Add new connection + pathfinder.connections.push(new Connection(point, // from + to, typeof connect === 'string' ? + {} : + connect)); + } + }); + } + }); + } + }); + // Clear connections that should not be updated, and move old info over + // to new connections. + for (var j = 0, k, found, lenOld = oldConnections.length, lenNew = pathfinder.connections.length; j < lenOld; ++j) { + found = false; + for (k = 0; k < lenNew; ++k) { + if (oldConnections[j].fromPoint === + pathfinder.connections[k].fromPoint && + oldConnections[j].toPoint === + pathfinder.connections[k].toPoint) { + pathfinder.connections[k].graphics = + oldConnections[j].graphics; + found = true; + break; + } + } + if (!found) { + oldConnections[j].destroy(); + } + } + // Clear obstacles to force recalculation. This must be done on every + // redraw in case positions have changed. Recalculation is handled in + // Connection.getPath on demand. + delete this.chartObstacles; + delete this.lineObstacles; + // Draw the pending connections + pathfinder.renderConnections(deferRender); + }, + /** + * Draw the chart's connecting paths. + * + * @function Highcharts.Pathfinder#renderConnections + * + * @param {boolean} [deferRender] + * Whether or not to defer render until series animation is finished. + * Used on first render. + */ + renderConnections: function (deferRender) { + if (deferRender) { + // Render after series are done animating + this.chart.series.forEach(function (series) { + var render = function () { + // Find pathfinder connections belonging to this series + // that haven't rendered, and render them now. + var pathfinder = series.chart.pathfinder, conns = pathfinder && pathfinder.connections || []; + conns.forEach(function (connection) { + if (connection.fromPoint && + connection.fromPoint.series === series) { + connection.render(); + } + }); + if (series.pathfinderRemoveRenderEvent) { + series.pathfinderRemoveRenderEvent(); + delete series.pathfinderRemoveRenderEvent; + } + }; + if (series.options.animation === false) { + render(); + } + else { + series.pathfinderRemoveRenderEvent = addEvent(series, 'afterAnimate', render); + } + }); + } + else { + // Go through connections and render them + this.connections.forEach(function (connection) { + connection.render(); + }); + } + }, + /** + * Get obstacles for the points in the chart. Does not include connecting + * lines from Pathfinder. Applies algorithmMargin to the obstacles. + * + * @function Highcharts.Pathfinder#getChartObstacles + * + * @param {object} options + * Options for the calculation. Currenlty only + * options.algorithmMargin. + * + * @return {Array} + * An array of calculated obstacles. Each obstacle is defined as an + * object with xMin, xMax, yMin and yMax properties. + */ + getChartObstacles: function (options) { + var obstacles = [], series = this.chart.series, margin = pick(options.algorithmMargin, 0), calculatedMargin; + for (var i = 0, sLen = series.length; i < sLen; ++i) { + if (series[i].visible && !series[i].options.isInternal) { + for (var j = 0, pLen = series[i].points.length, bb, point; j < pLen; ++j) { + point = series[i].points[j]; + if (point.visible) { + bb = getPointBB(point); + if (bb) { + obstacles.push({ + xMin: bb.xMin - margin, + xMax: bb.xMax + margin, + yMin: bb.yMin - margin, + yMax: bb.yMax + margin + }); + } + } + } + } + } + // Sort obstacles by xMin for optimization + obstacles = obstacles.sort(function (a, b) { + return a.xMin - b.xMin; + }); + // Add auto-calculated margin if the option is not defined + if (!defined(options.algorithmMargin)) { + calculatedMargin = + options.algorithmMargin = + calculateObstacleMargin(obstacles); + obstacles.forEach(function (obstacle) { + obstacle.xMin -= calculatedMargin; + obstacle.xMax += calculatedMargin; + obstacle.yMin -= calculatedMargin; + obstacle.yMax += calculatedMargin; + }); + } + return obstacles; + }, + /** + * Utility function to get metrics for obstacles: + * - Widest obstacle width + * - Tallest obstacle height + * + * @function Highcharts.Pathfinder#getObstacleMetrics + * + * @param {Array} obstacles + * An array of obstacles to inspect. + * + * @return {object} + * The calculated metrics, as an object with maxHeight and maxWidth + * properties. + */ + getObstacleMetrics: function (obstacles) { + var maxWidth = 0, maxHeight = 0, width, height, i = obstacles.length; + while (i--) { + width = obstacles[i].xMax - obstacles[i].xMin; + height = obstacles[i].yMax - obstacles[i].yMin; + if (maxWidth < width) { + maxWidth = width; + } + if (maxHeight < height) { + maxHeight = height; + } + } + return { + maxHeight: maxHeight, + maxWidth: maxWidth + }; + }, + /** + * Utility to get which direction to start the pathfinding algorithm + * (X vs Y), calculated from a set of marker options. + * + * @function Highcharts.Pathfinder#getAlgorithmStartDirection + * + * @param {Highcharts.ConnectorsMarkerOptions} markerOptions + * Marker options to calculate from. + * + * @return {boolean} + * Returns true for X, false for Y, and undefined for autocalculate. + */ + getAlgorithmStartDirection: function (markerOptions) { + var xCenter = markerOptions.align !== 'left' && + markerOptions.align !== 'right', yCenter = markerOptions.verticalAlign !== 'top' && + markerOptions.verticalAlign !== 'bottom', undef; + return xCenter ? + (yCenter ? undef : false) : // x is centered + (yCenter ? true : undef); // x is off-center + } + }; + // Add to Highcharts namespace + H.Connection = Connection; + H.Pathfinder = Pathfinder; + // Add pathfinding capabilities to Points + extend(Point.prototype, /** @lends Point.prototype */ { + /** + * Get coordinates of anchor point for pathfinder connection. + * + * @private + * @function Highcharts.Point#getPathfinderAnchorPoint + * + * @param {Highcharts.ConnectorsMarkerOptions} markerOptions + * Connection options for position on point. + * + * @return {Highcharts.PositionObject} + * An object with x/y properties for the position. Coordinates are + * in plot values, not relative to point. + */ + getPathfinderAnchorPoint: function (markerOptions) { + var bb = getPointBB(this), x, y; + switch (markerOptions.align) { // eslint-disable-line default-case + case 'right': + x = 'xMax'; + break; + case 'left': + x = 'xMin'; + } + switch (markerOptions.verticalAlign) { // eslint-disable-line default-case + case 'top': + y = 'yMin'; + break; + case 'bottom': + y = 'yMax'; + } + return { + x: x ? bb[x] : (bb.xMin + bb.xMax) / 2, + y: y ? bb[y] : (bb.yMin + bb.yMax) / 2 + }; + }, + /** + * Utility to get the angle from one point to another. + * + * @private + * @function Highcharts.Point#getRadiansToVector + * + * @param {Highcharts.PositionObject} v1 + * The first vector, as an object with x/y properties. + * + * @param {Highcharts.PositionObject} v2 + * The second vector, as an object with x/y properties. + * + * @return {number} + * The angle in degrees + */ + getRadiansToVector: function (v1, v2) { + var box; + if (!defined(v2)) { + box = getPointBB(this); + if (box) { + v2 = { + x: (box.xMin + box.xMax) / 2, + y: (box.yMin + box.yMax) / 2 + }; + } + } + return Math.atan2(v2.y - v1.y, v1.x - v2.x); + }, + /** + * Utility to get the position of the marker, based on the path angle and + * the marker's radius. + * + * @private + * @function Highcharts.Point#getMarkerVector + * + * @param {number} radians + * The angle in radians from the point center to another vector. + * + * @param {number} markerRadius + * The radius of the marker, to calculate the additional distance to + * the center of the marker. + * + * @param {object} anchor + * The anchor point of the path and marker as an object with x/y + * properties. + * + * @return {object} + * The marker vector as an object with x/y properties. + */ + getMarkerVector: function (radians, markerRadius, anchor) { + var twoPI = Math.PI * 2.0, theta = radians, bb = getPointBB(this), rectWidth = bb.xMax - bb.xMin, rectHeight = bb.yMax - bb.yMin, rAtan = Math.atan2(rectHeight, rectWidth), tanTheta = 1, leftOrRightRegion = false, rectHalfWidth = rectWidth / 2.0, rectHalfHeight = rectHeight / 2.0, rectHorizontalCenter = bb.xMin + rectHalfWidth, rectVerticalCenter = bb.yMin + rectHalfHeight, edgePoint = { + x: rectHorizontalCenter, + y: rectVerticalCenter + }, markerPoint = {}, xFactor = 1, yFactor = 1; + while (theta < -Math.PI) { + theta += twoPI; + } + while (theta > Math.PI) { + theta -= twoPI; + } + tanTheta = Math.tan(theta); + if ((theta > -rAtan) && (theta <= rAtan)) { + // Right side + yFactor = -1; + leftOrRightRegion = true; + } + else if (theta > rAtan && theta <= (Math.PI - rAtan)) { + // Top side + yFactor = -1; + } + else if (theta > (Math.PI - rAtan) || theta <= -(Math.PI - rAtan)) { + // Left side + xFactor = -1; + leftOrRightRegion = true; + } + else { + // Bottom side + xFactor = -1; + } + // Correct the edgePoint according to the placement of the marker + if (leftOrRightRegion) { + edgePoint.x += xFactor * (rectHalfWidth); + edgePoint.y += yFactor * (rectHalfWidth) * tanTheta; + } + else { + edgePoint.x += xFactor * (rectHeight / (2.0 * tanTheta)); + edgePoint.y += yFactor * (rectHalfHeight); + } + if (anchor.x !== rectHorizontalCenter) { + edgePoint.x = anchor.x; + } + if (anchor.y !== rectVerticalCenter) { + edgePoint.y = anchor.y; + } + markerPoint.x = edgePoint.x + (markerRadius * Math.cos(theta)); + markerPoint.y = edgePoint.y - (markerRadius * Math.sin(theta)); + return markerPoint; + } + }); + /** + * Warn if using legacy options. Copy the options over. Note that this will + * still break if using the legacy options in chart.update, addSeries etc. + * @private + */ + function warnLegacy(chart) { + if (chart.options.pathfinder || + chart.series.reduce(function (acc, series) { + if (series.options) { + merge(true, (series.options.connectors = series.options.connectors || + {}), series.options.pathfinder); + } + return acc || series.options && series.options.pathfinder; + }, false)) { + merge(true, (chart.options.connectors = chart.options.connectors || {}), chart.options.pathfinder); + error('WARNING: Pathfinder options have been renamed. ' + + 'Use "chart.connectors" or "series.connectors" instead.'); + } + } + // Initialize Pathfinder for charts + H.Chart.prototype.callbacks.push(function (chart) { + var options = chart.options; + if (options.connectors.enabled !== false) { + warnLegacy(chart); + this.pathfinder = new Pathfinder(this); + this.pathfinder.update(true); // First draw, defer render + } + }); + + }); + _registerModule(_modules, 'modules/xrange.src.js', [_modules['parts/Globals.js'], _modules['parts/Color.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js']], function (H, Color, Point, U) { + /* * + * + * X-range series module + * + * (c) 2010-2020 Torstein Honsi, Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /* * + * @interface Highcharts.PointOptionsObject in parts/Point.ts + */ /** + * The ending X value of the range point. + * @name Highcharts.PointOptionsObject#x2 + * @type {number|undefined} + * @requires modules/xrange + */ + var color = Color.parse; + var addEvent = U.addEvent, clamp = U.clamp, correctFloat = U.correctFloat, defined = U.defined, find = U.find, isNumber = U.isNumber, isObject = U.isObject, merge = U.merge, pick = U.pick, seriesType = U.seriesType; + var columnType = H.seriesTypes.column, seriesTypes = H.seriesTypes, Axis = H.Axis, Series = H.Series; + /** + * Return color of a point based on its category. + * + * @private + * @function getColorByCategory + * + * @param {object} series + * The series which the point belongs to. + * + * @param {object} point + * The point to calculate its color for. + * + * @return {object} + * Returns an object containing the properties color and colorIndex. + */ + function getColorByCategory(series, point) { + var colors = series.options.colors || series.chart.options.colors, colorCount = colors ? + colors.length : + series.chart.options.chart.colorCount, colorIndex = point.y % colorCount, color = colors && colors[colorIndex]; + return { + colorIndex: colorIndex, + color: color + }; + } + /** + * @private + * @class + * @name Highcharts.seriesTypes.xrange + * + * @augments Highcharts.Series + */ + seriesType('xrange', 'column' + /** + * The X-range series displays ranges on the X axis, typically time + * intervals with a start and end date. + * + * @sample {highcharts} highcharts/demo/x-range/ + * X-range + * @sample {highcharts} highcharts/css/x-range/ + * Styled mode X-range + * @sample {highcharts} highcharts/chart/inverted-xrange/ + * Inverted X-range + * + * @extends plotOptions.column + * @since 6.0.0 + * @product highcharts highstock gantt + * @excluding boostThreshold, crisp, cropThreshold, depth, edgeColor, + * edgeWidth, findNearestPointBy, getExtremesFromAll, + * negativeColor, pointInterval, pointIntervalUnit, + * pointPlacement, pointRange, pointStart, softThreshold, + * stacking, threshold, data, dataSorting + * @requires modules/xrange + * @optionparent plotOptions.xrange + */ + , { + /** + * A partial fill for each point, typically used to visualize how much + * of a task is performed. The partial fill object can be set either on + * series or point level. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range with partial fill + * + * @product highcharts highstock gantt + * @apioption plotOptions.xrange.partialFill + */ + /** + * The fill color to be used for partial fills. Defaults to a darker + * shade of the point color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock gantt + * @apioption plotOptions.xrange.partialFill.fill + */ + /** + * A partial fill for each point, typically used to visualize how much + * of a task is performed. See [completed](series.gantt.data.completed). + * + * @sample gantt/demo/progress-indicator + * Gantt with progress indicator + * + * @product gantt + * @apioption plotOptions.gantt.partialFill + */ + /** + * In an X-range series, this option makes all points of the same Y-axis + * category the same color. + */ + colorByPoint: true, + dataLabels: { + formatter: function () { + var point = this.point, amount = point.partialFill; + if (isObject(amount)) { + amount = amount.amount; + } + if (isNumber(amount) && amount > 0) { + return correctFloat(amount * 100) + '%'; + } + }, + inside: true, + verticalAlign: 'middle' + }, + tooltip: { + headerFormat: '{point.x} - {point.x2}
', + pointFormat: '\u25CF {series.name}: {point.yCategory}
' + }, + borderRadius: 3, + pointRange: 0 + }, { + type: 'xrange', + parallelArrays: ['x', 'x2', 'y'], + requireSorting: false, + animate: seriesTypes.line.prototype.animate, + cropShoulder: 1, + getExtremesFromAll: true, + autoIncrement: H.noop, + buildKDTree: H.noop, + /* eslint-disable valid-jsdoc */ + /** + * @private + * @function Highcarts.seriesTypes.xrange#init + * @return {void} + */ + init: function () { + seriesTypes.column.prototype.init.apply(this, arguments); + this.options.stacking = void 0; // #13161 + }, + /** + * Borrow the column series metrics, but with swapped axes. This gives + * free access to features like groupPadding, grouping, pointWidth etc. + * + * @private + * @function Highcharts.Series#getColumnMetrics + * + * @return {Highcharts.ColumnMetricsObject} + */ + getColumnMetrics: function () { + var metrics, chart = this.chart; + /** + * @private + */ + function swapAxes() { + chart.series.forEach(function (s) { + var xAxis = s.xAxis; + s.xAxis = s.yAxis; + s.yAxis = xAxis; + }); + } + swapAxes(); + metrics = columnType.prototype.getColumnMetrics.call(this); + swapAxes(); + return metrics; + }, + /** + * Override cropData to show a point where x or x2 is outside visible + * range, but one of them is inside. + * + * @private + * @function Highcharts.Series#cropData + * + * @param {Array} xData + * + * @param {Array} yData + * + * @param {number} min + * + * @param {number} max + * + * @param {number} [cropShoulder] + * + * @return {*} + */ + cropData: function (xData, yData, min, max) { + // Replace xData with x2Data to find the appropriate cropStart + var cropData = Series.prototype.cropData, crop = cropData.call(this, this.x2Data, yData, min, max); + // Re-insert the cropped xData + crop.xData = xData.slice(crop.start, crop.end); + return crop; + }, + /** + * Finds the index of an existing point that matches the given point + * options. + * + * @private + * @function Highcharts.Series#findPointIndex + * @param {object} options The options of the point. + * @returns {number|undefined} Returns index of a matching point, + * returns undefined if no match is found. + */ + findPointIndex: function (options) { + var _a = this, cropped = _a.cropped, cropStart = _a.cropStart, points = _a.points; + var id = options.id; + var pointIndex; + if (id) { + var point = find(points, function (point) { + return point.id === id; + }); + pointIndex = point ? point.index : void 0; + } + if (typeof pointIndex === 'undefined') { + var point = find(points, function (point) { + return (point.x === options.x && + point.x2 === options.x2 && + !point.touched); + }); + pointIndex = point ? point.index : void 0; + } + // Reduce pointIndex if data is cropped + if (cropped && + isNumber(pointIndex) && + isNumber(cropStart) && + pointIndex >= cropStart) { + pointIndex -= cropStart; + } + return pointIndex; + }, + /** + * @private + * @function Highcharts.Series#translatePoint + * + * @param {Highcharts.Point} point + */ + translatePoint: function (point) { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, metrics = series.columnMetrics, options = series.options, minPointLength = options.minPointLength || 0, plotX = point.plotX, posX = pick(point.x2, point.x + (point.len || 0)), plotX2 = xAxis.translate(posX, 0, 0, 0, 1), length = Math.abs(plotX2 - plotX), widthDifference, shapeArgs, partialFill, inverted = this.chart.inverted, borderWidth = pick(options.borderWidth, 1), crisper = borderWidth % 2 / 2, yOffset = metrics.offset, pointHeight = Math.round(metrics.width), dlLeft, dlRight, dlWidth, clipRectWidth, tooltipYOffset; + if (minPointLength) { + widthDifference = minPointLength - length; + if (widthDifference < 0) { + widthDifference = 0; + } + plotX -= widthDifference / 2; + plotX2 += widthDifference / 2; + } + plotX = Math.max(plotX, -10); + plotX2 = clamp(plotX2, -10, xAxis.len + 10); + // Handle individual pointWidth + if (defined(point.options.pointWidth)) { + yOffset -= ((Math.ceil(point.options.pointWidth) - pointHeight) / 2); + pointHeight = Math.ceil(point.options.pointWidth); + } + // Apply pointPlacement to the Y axis + if (options.pointPlacement && + isNumber(point.plotY) && + yAxis.categories) { + point.plotY = yAxis.translate(point.y, 0, 1, 0, 1, options.pointPlacement); + } + point.shapeArgs = { + x: Math.floor(Math.min(plotX, plotX2)) + crisper, + y: Math.floor(point.plotY + yOffset) + crisper, + width: Math.round(Math.abs(plotX2 - plotX)), + height: pointHeight, + r: series.options.borderRadius + }; + // Align data labels inside the shape and inside the plot area + dlLeft = point.shapeArgs.x; + dlRight = dlLeft + point.shapeArgs.width; + if (dlLeft < 0 || dlRight > xAxis.len) { + dlLeft = clamp(dlLeft, 0, xAxis.len); + dlRight = clamp(dlRight, 0, xAxis.len); + dlWidth = dlRight - dlLeft; + point.dlBox = merge(point.shapeArgs, { + x: dlLeft, + width: dlRight - dlLeft, + centerX: dlWidth ? dlWidth / 2 : null + }); + } + else { + point.dlBox = null; + } + // Tooltip position + var tooltipPos = point.tooltipPos; + var xIndex = !inverted ? 0 : 1; + var yIndex = !inverted ? 1 : 0; + tooltipYOffset = series.columnMetrics ? + series.columnMetrics.offset : -metrics.width / 2; + // Limit position by the correct axis size (#9727) + tooltipPos[xIndex] = clamp(tooltipPos[xIndex] + ((!inverted ? 1 : -1) * (xAxis.reversed ? -1 : 1) * + (length / 2)), 0, xAxis.len - 1); + tooltipPos[yIndex] = clamp(tooltipPos[yIndex] + ((inverted ? -1 : 1) * tooltipYOffset), 0, yAxis.len - 1); + // Add a partShapeArgs to the point, based on the shapeArgs property + partialFill = point.partialFill; + if (partialFill) { + // Get the partial fill amount + if (isObject(partialFill)) { + partialFill = partialFill.amount; + } + // If it was not a number, assume 0 + if (!isNumber(partialFill)) { + partialFill = 0; + } + shapeArgs = point.shapeArgs; + point.partShapeArgs = { + x: shapeArgs.x, + y: shapeArgs.y, + width: shapeArgs.width, + height: shapeArgs.height, + r: series.options.borderRadius + }; + clipRectWidth = Math.max(Math.round(length * partialFill + point.plotX - + plotX), 0); + point.clipRectArgs = { + x: xAxis.reversed ? // #10717 + shapeArgs.x + length - clipRectWidth : + shapeArgs.x, + y: shapeArgs.y, + width: clipRectWidth, + height: shapeArgs.height + }; + } + }, + /** + * @private + * @function Highcharts.Series#translate + */ + translate: function () { + columnType.prototype.translate.apply(this, arguments); + this.points.forEach(function (point) { + this.translatePoint(point); + }, this); + }, + /** + * Draws a single point in the series. Needed for partial fill. + * + * This override turns point.graphic into a group containing the + * original graphic and an overlay displaying the partial fill. + * + * @private + * @function Highcharts.Series#drawPoint + * + * @param {Highcharts.Point} point + * An instance of Point in the series. + * + * @param {"animate"|"attr"} verb + * 'animate' (animates changes) or 'attr' (sets options) + */ + drawPoint: function (point, verb) { + var series = this, seriesOpts = series.options, renderer = series.chart.renderer, graphic = point.graphic, type = point.shapeType, shapeArgs = point.shapeArgs, partShapeArgs = point.partShapeArgs, clipRectArgs = point.clipRectArgs, pfOptions = point.partialFill, cutOff = seriesOpts.stacking && !seriesOpts.borderRadius, pointState = point.state, stateOpts = (seriesOpts.states[pointState || 'normal'] || + {}), pointStateVerb = typeof pointState === 'undefined' ? + 'attr' : verb, pointAttr = series.pointAttribs(point, pointState), animation = pick(series.chart.options.chart.animation, stateOpts.animation), fill; + if (!point.isNull && point.visible !== false) { + // Original graphic + if (graphic) { // update + graphic.rect[verb](shapeArgs); + } + else { + point.graphic = graphic = renderer.g('point') + .addClass(point.getClassName()) + .add(point.group || series.group); + graphic.rect = renderer[type](merge(shapeArgs)) + .addClass(point.getClassName()) + .addClass('highcharts-partfill-original') + .add(graphic); + } + // Partial fill graphic + if (partShapeArgs) { + if (graphic.partRect) { + graphic.partRect[verb](merge(partShapeArgs)); + graphic.partialClipRect[verb](merge(clipRectArgs)); + } + else { + graphic.partialClipRect = renderer.clipRect(clipRectArgs.x, clipRectArgs.y, clipRectArgs.width, clipRectArgs.height); + graphic.partRect = + renderer[type](partShapeArgs) + .addClass('highcharts-partfill-overlay') + .add(graphic) + .clip(graphic.partialClipRect); + } + } + // Presentational + if (!series.chart.styledMode) { + graphic + .rect[verb](pointAttr, animation) + .shadow(seriesOpts.shadow, null, cutOff); + if (partShapeArgs) { + // Ensure pfOptions is an object + if (!isObject(pfOptions)) { + pfOptions = {}; + } + if (isObject(seriesOpts.partialFill)) { + pfOptions = merge(pfOptions, seriesOpts.partialFill); + } + fill = (pfOptions.fill || + color(pointAttr.fill).brighten(-0.3).get() || + color(point.color || series.color) + .brighten(-0.3).get()); + pointAttr.fill = fill; + graphic + .partRect[pointStateVerb](pointAttr, animation) + .shadow(seriesOpts.shadow, null, cutOff); + } + } + } + else if (graphic) { + point.graphic = graphic.destroy(); // #1269 + } + }, + /** + * @private + * @function Highcharts.Series#drawPoints + */ + drawPoints: function () { + var series = this, verb = series.getAnimationVerb(); + // Draw the columns + series.points.forEach(function (point) { + series.drawPoint(point, verb); + }); + }, + /** + * Returns "animate", or "attr" if the number of points is above the + * animation limit. + * + * @private + * @function Highcharts.Series#getAnimationVerb + * + * @return {string} + */ + getAnimationVerb: function () { + return (this.chart.pointCount < (this.options.animationLimit || 250) ? + 'animate' : + 'attr'); + } + /* + // Override to remove stroke from points. For partial fill. + pointAttribs: function () { + var series = this, + retVal = columnType.prototype.pointAttribs + .apply(series, arguments); + + //retVal['stroke-width'] = 0; + return retVal; + } + //*/ + /* eslint-enable valid-jsdoc */ + }, { + /** + * The ending X value of the range point. + * @name Highcharts.Point#x2 + * @type {number|undefined} + * @requires modules/xrange + */ + /** + * Extend applyOptions so that `colorByPoint` for x-range means that one + * color is applied per Y axis category. + * + * @private + * @function Highcharts.Point#applyOptions + * + * @return {Highcharts.Series} + */ + /* eslint-disable valid-jsdoc */ + /** + * @private + */ + resolveColor: function () { + var series = this.series, colorByPoint; + if (series.options.colorByPoint && !this.options.color) { + colorByPoint = getColorByCategory(series, this); + if (!series.chart.styledMode) { + this.color = colorByPoint.color; + } + if (!this.options.colorIndex) { + this.colorIndex = colorByPoint.colorIndex; + } + } + else if (!this.color) { + this.color = series.color; + } + }, + /** + * Extend init to have y default to 0. + * + * @private + * @function Highcharts.Point#init + * + * @return {Highcharts.Point} + */ + init: function () { + Point.prototype.init.apply(this, arguments); + if (!this.y) { + this.y = 0; + } + return this; + }, + /** + * @private + * @function Highcharts.Point#setState + */ + setState: function () { + Point.prototype.setState.apply(this, arguments); + this.series.drawPoint(this, this.series.getAnimationVerb()); + }, + /** + * @private + * @function Highcharts.Point#getLabelConfig + * + * @return {Highcharts.PointLabelObject} + */ + // Add x2 and yCategory to the available properties for tooltip formats + getLabelConfig: function () { + var point = this, cfg = Point.prototype.getLabelConfig.call(point), yCats = point.series.yAxis.categories; + cfg.x2 = point.x2; + cfg.yCategory = point.yCategory = yCats && yCats[point.y]; + return cfg; + }, + tooltipDateKeys: ['x', 'x2'], + /** + * @private + * @function Highcharts.Point#isValid + * + * @return {boolean} + */ + isValid: function () { + return typeof this.x === 'number' && + typeof this.x2 === 'number'; + } + /* eslint-enable valid-jsdoc */ + }); + /** + * Max x2 should be considered in xAxis extremes + */ + addEvent(Axis, 'afterGetSeriesExtremes', function () { + var axis = this, // eslint-disable-line no-invalid-this + axisSeries = axis.series, dataMax, modMax; + if (axis.isXAxis) { + dataMax = pick(axis.dataMax, -Number.MAX_VALUE); + axisSeries.forEach(function (series) { + if (series.x2Data) { + series.x2Data + .forEach(function (val) { + if (val > dataMax) { + dataMax = val; + modMax = true; + } + }); + } + }); + if (modMax) { + axis.dataMax = dataMax; + } + } + }); + /** + * An `xrange` series. If the [type](#series.xrange.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.xrange + * @excluding boostThreshold, crisp, cropThreshold, depth, edgeColor, edgeWidth, + * findNearestPointBy, getExtremesFromAll, negativeColor, + * pointInterval, pointIntervalUnit, pointPlacement, pointRange, + * pointStart, softThreshold, stacking, threshold, dataSorting + * @product highcharts highstock gantt + * @requires modules/xrange + * @apioption series.xrange + */ + /** + * An array of data points for the series. For the `xrange` series type, + * points can be given in the following ways: + * + * 1. An array of objects with named values. The objects are point configuration + * objects as seen below. + * ```js + * data: [{ + * x: Date.UTC(2017, 0, 1), + * x2: Date.UTC(2017, 0, 3), + * name: "Test", + * y: 0, + * color: "#00FF00" + * }, { + * x: Date.UTC(2017, 0, 4), + * x2: Date.UTC(2017, 0, 5), + * name: "Deploy", + * y: 1, + * color: "#FF0000" + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @declare Highcharts.XrangePointOptionsObject + * @type {Array<*>} + * @extends series.line.data + * @product highcharts highstock gantt + * @apioption series.xrange.data + */ + /** + * The starting X value of the range point. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range + * + * @type {number} + * @product highcharts highstock gantt + * @apioption series.xrange.data.x + */ + /** + * The ending X value of the range point. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range + * + * @type {number} + * @product highcharts highstock gantt + * @apioption series.xrange.data.x2 + */ + /** + * The Y value of the range point. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range + * + * @type {number} + * @product highcharts highstock gantt + * @apioption series.xrange.data.y + */ + /** + * A partial fill for each point, typically used to visualize how much of + * a task is performed. The partial fill object can be set either on series + * or point level. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range with partial fill + * + * @declare Highcharts.XrangePointPartialFillOptionsObject + * @product highcharts highstock gantt + * @apioption series.xrange.data.partialFill + */ + /** + * The amount of the X-range point to be filled. Values can be 0-1 and are + * converted to percentages in the default data label formatter. + * + * @type {number} + * @product highcharts highstock gantt + * @apioption series.xrange.data.partialFill.amount + */ + /** + * The fill color to be used for partial fills. Defaults to a darker shade + * of the point color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock gantt + * @apioption series.xrange.data.partialFill.fill + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'parts-gantt/GanttSeries.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2016-2020 Highsoft AS + * + * Author: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var isNumber = U.isNumber, merge = U.merge, pick = U.pick, seriesType = U.seriesType, splat = U.splat; + var dateFormat = H.dateFormat, seriesTypes = H.seriesTypes, Series = H.Series, parent = seriesTypes.xrange; + /** + * @private + * @class + * @name Highcharts.seriesTypes.gantt + * + * @augments Highcharts.Series + */ + seriesType('gantt', 'xrange' + /** + * A `gantt` series. If the [type](#series.gantt.type) option is not specified, + * it is inherited from [chart.type](#chart.type). + * + * @extends plotOptions.xrange + * @product gantt + * @requires highcharts-gantt + * @optionparent plotOptions.gantt + */ + , { + // options - default options merged with parent + grouping: false, + dataLabels: { + enabled: true + }, + tooltip: { + headerFormat: '{series.name}
', + pointFormat: null, + pointFormatter: function () { + var point = this, series = point.series, tooltip = series.chart.tooltip, xAxis = series.xAxis, formats = series.tooltipOptions.dateTimeLabelFormats, startOfWeek = xAxis.options.startOfWeek, ttOptions = series.tooltipOptions, format = ttOptions.xDateFormat, start, end, milestone = point.options.milestone, retVal = '' + (point.name || point.yCategory) + ''; + if (ttOptions.pointFormat) { + return point.tooltipFormatter(ttOptions.pointFormat); + } + if (!format) { + format = splat(tooltip.getDateFormat(xAxis.closestPointRange, point.start, startOfWeek, formats))[0]; + } + start = dateFormat(format, point.start); + end = dateFormat(format, point.end); + retVal += '
'; + if (!milestone) { + retVal += 'Start: ' + start + '
'; + retVal += 'End: ' + end + '
'; + } + else { + retVal += start + '
'; + } + return retVal; + } + }, + connectors: { + type: 'simpleConnect', + /** + * @declare Highcharts.ConnectorsAnimationOptionsObject + */ + animation: { + reversed: true // Dependencies go from child to parent + }, + startMarker: { + enabled: true, + symbol: 'arrow-filled', + radius: 4, + fill: '#fa0', + align: 'left' + }, + endMarker: { + enabled: false, + align: 'right' + } + } + }, { + pointArrayMap: ['start', 'end', 'y'], + // Keyboard navigation, don't use nearest vertical mode + keyboardMoveVertical: false, + /* eslint-disable valid-jsdoc */ + /** + * Handle milestones, as they have no x2. + * @private + */ + translatePoint: function (point) { + var series = this, shapeArgs, size; + parent.prototype.translatePoint.call(series, point); + if (point.options.milestone) { + shapeArgs = point.shapeArgs; + size = shapeArgs.height; + point.shapeArgs = { + x: shapeArgs.x - (size / 2), + y: shapeArgs.y, + width: size, + height: size + }; + } + }, + /** + * Draws a single point in the series. + * + * This override draws the point as a diamond if point.options.milestone + * is true, and uses the original drawPoint() if it is false or not set. + * + * @requires highcharts-gantt + * + * @private + * @function Highcharts.seriesTypes.gantt#drawPoint + * + * @param {Highcharts.Point} point + * An instance of Point in the series + * + * @param {"animate"|"attr"} verb + * 'animate' (animates changes) or 'attr' (sets options) + * + * @return {void} + */ + drawPoint: function (point, verb) { + var series = this, seriesOpts = series.options, renderer = series.chart.renderer, shapeArgs = point.shapeArgs, plotY = point.plotY, graphic = point.graphic, state = point.selected && 'select', cutOff = seriesOpts.stacking && !seriesOpts.borderRadius, diamondShape; + if (point.options.milestone) { + if (isNumber(plotY) && point.y !== null && point.visible !== false) { + diamondShape = renderer.symbols.diamond(shapeArgs.x, shapeArgs.y, shapeArgs.width, shapeArgs.height); + if (graphic) { + graphic[verb]({ + d: diamondShape + }); + } + else { + point.graphic = graphic = renderer.path(diamondShape) + .addClass(point.getClassName(), true) + .add(point.group || series.group); + } + // Presentational + if (!series.chart.styledMode) { + point.graphic + .attr(series.pointAttribs(point, state)) + .shadow(seriesOpts.shadow, null, cutOff); + } + } + else if (graphic) { + point.graphic = graphic.destroy(); // #1269 + } + } + else { + parent.prototype.drawPoint.call(series, point, verb); + } + }, + setData: Series.prototype.setData, + /** + * @private + */ + setGanttPointAliases: function (options) { + /** + * Add a value to options if the value exists. + * @private + */ + function addIfExists(prop, val) { + if (typeof val !== 'undefined') { + options[prop] = val; + } + } + addIfExists('x', pick(options.start, options.x)); + addIfExists('x2', pick(options.end, options.x2)); + addIfExists('partialFill', pick(options.completed, options.partialFill)); + addIfExists('connect', pick(options.dependency, options.connect)); + } + /* eslint-enable valid-jsdoc */ + }, merge(parent.prototype.pointClass.prototype, { + // pointProps - point member overrides. We inherit from parent as well. + /* eslint-disable valid-jsdoc */ + /** + * Applies the options containing the x and y data and possible some + * extra properties. This is called on point init or from point.update. + * + * @private + * @function Highcharts.Point#applyOptions + * + * @param {object} options + * The point options + * + * @param {number} x + * The x value + * + * @return {Highcharts.Point} + * The Point instance + */ + applyOptions: function (options, x) { + var point = this, retVal = merge(options); + H.seriesTypes.gantt.prototype.setGanttPointAliases(retVal); + retVal = parent.prototype.pointClass.prototype.applyOptions + .call(point, retVal, x); + return retVal; + }, + isValid: function () { + return ((typeof this.start === 'number' || + typeof this.x === 'number') && + (typeof this.end === 'number' || + typeof this.x2 === 'number' || + this.milestone)); + } + /* eslint-enable valid-jsdoc */ + })); + /** + * A `gantt` series. + * + * @extends series,plotOptions.gantt + * @excluding boostThreshold, connectors, dashStyle, findNearestPointBy, + * getExtremesFromAll, marker, negativeColor, pointInterval, + * pointIntervalUnit, pointPlacement, pointStart + * @product gantt + * @requires highcharts-gantt + * @apioption series.gantt + */ + /** + * Data for a Gantt series. + * + * @declare Highcharts.GanttPointOptionsObject + * @type {Array<*>} + * @extends series.xrange.data + * @excluding className, color, colorIndex, connect, dataLabels, events, id, + * partialFill, selected, x, x2 + * @product gantt + * @apioption series.gantt.data + */ + /** + * Whether the grid node belonging to this point should start as collapsed. Used + * in axes of type treegrid. + * + * @sample {gantt} gantt/treegrid-axis/collapsed/ + * Start as collapsed + * + * @type {boolean} + * @default false + * @product gantt + * @apioption series.gantt.data.collapsed + */ + /** + * The start time of a task. + * + * @type {number} + * @product gantt + * @apioption series.gantt.data.start + */ + /** + * The end time of a task. + * + * @type {number} + * @product gantt + * @apioption series.gantt.data.end + */ + /** + * The Y value of a task. + * + * @type {number} + * @product gantt + * @apioption series.gantt.data.y + */ + /** + * The name of a task. If a `treegrid` y-axis is used (default in Gantt charts), + * this will be picked up automatically, and used to calculate the y-value. + * + * @type {string} + * @product gantt + * @apioption series.gantt.data.name + */ + /** + * Progress indicator, how much of the task completed. If it is a number, the + * `fill` will be applied automatically. + * + * @sample {gantt} gantt/demo/progress-indicator + * Progress indicator + * + * @type {number|*} + * @extends series.xrange.data.partialFill + * @product gantt + * @apioption series.gantt.data.completed + */ + /** + * The amount of the progress indicator, ranging from 0 (not started) to 1 + * (finished). + * + * @type {number} + * @default 0 + * @apioption series.gantt.data.completed.amount + */ + /** + * The fill of the progress indicator. Defaults to a darkened variety of the + * main color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption series.gantt.data.completed.fill + */ + /** + * The ID of the point (task) that this point depends on in Gantt charts. + * Aliases [connect](series.xrange.data.connect). Can also be an object, + * specifying further connecting [options](series.gantt.connectors) between the + * points. Multiple connections can be specified by providing an array. + * + * @sample gantt/demo/project-management + * Dependencies + * @sample gantt/pathfinder/demo + * Different connection types + * + * @type {string|Array|*} + * @extends series.xrange.data.connect + * @since 6.2.0 + * @product gantt + * @apioption series.gantt.data.dependency + */ + /** + * Whether this point is a milestone. If so, only the `start` option is handled, + * while `end` is ignored. + * + * @sample gantt/gantt/milestones + * Milestones + * + * @type {boolean} + * @since 6.2.0 + * @product gantt + * @apioption series.gantt.data.milestone + */ + /** + * The ID of the parent point (task) of this point in Gantt charts. + * + * @sample gantt/demo/subtasks + * Gantt chart with subtasks + * + * @type {string} + * @since 6.2.0 + * @product gantt + * @apioption series.gantt.data.parent + */ + /** + * @excluding afterAnimate + * @apioption series.gantt.events + */ + ''; // adds doclets above to the transpiled file + + }); + _registerModule(_modules, 'parts-gantt/GanttChart.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2016-2020 Highsoft AS + * + * Author: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var isArray = U.isArray, merge = U.merge, splat = U.splat; + var Chart = H.Chart; + /** + * Factory function for Gantt charts. + * + * @example + * // Render a chart in to div#container + * var chart = Highcharts.ganttChart('container', { + * title: { + * text: 'My chart' + * }, + * series: [{ + * data: ... + * }] + * }); + * + * @function Highcharts.ganttChart + * + * @param {string|Highcharts.HTMLDOMElement} renderTo + * The DOM element to render to, or its id. + * + * @param {Highcharts.Options} options + * The chart options structure. + * + * @param {Highcharts.ChartCallbackFunction} [callback] + * Function to run when the chart has loaded and and all external images + * are loaded. Defining a + * [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load) + * handler is equivalent. + * + * @return {Highcharts.Chart} + * Returns the Chart object. + */ + H.ganttChart = function (renderTo, options, callback) { + var hasRenderToArg = typeof renderTo === 'string' || renderTo.nodeName, seriesOptions = options.series, defaultOptions = H.getOptions(), defaultLinkedTo, userOptions = options; + options = arguments[hasRenderToArg ? 1 : 0]; + // If user hasn't defined axes as array, make it into an array and add a + // second axis by default. + if (!isArray(options.xAxis)) { + options.xAxis = [options.xAxis || {}, {}]; + } + // apply X axis options to both single and multi x axes + options.xAxis = options.xAxis.map(function (xAxisOptions, i) { + if (i === 1) { // Second xAxis + defaultLinkedTo = 0; + } + return merge(defaultOptions.xAxis, { + grid: { + enabled: true + }, + opposite: true, + linkedTo: defaultLinkedTo + }, xAxisOptions, // user options + { + type: 'datetime' + }); + }); + // apply Y axis options to both single and multi y axes + options.yAxis = (splat(options.yAxis || {})).map(function (yAxisOptions) { + return merge(defaultOptions.yAxis, // #3802 + { + grid: { + enabled: true + }, + staticScale: 50, + reversed: true, + // Set default type treegrid, but only if 'categories' is + // undefined + type: yAxisOptions.categories ? yAxisOptions.type : 'treegrid' + }, yAxisOptions // user options + ); + }); + options.series = null; + options = merge(true, { + chart: { + type: 'gantt' + }, + title: { + text: null + }, + legend: { + enabled: false + } + }, options, // user's options + // forced options + { + isGantt: true + }); + options.series = userOptions.series = seriesOptions; + options.series.forEach(function (series) { + series.data.forEach(function (point) { + H.seriesTypes.gantt.prototype.setGanttPointAliases(point); + }); + }); + return hasRenderToArg ? + new Chart(renderTo, options, callback) : + new Chart(options, options); // @todo does not look correct + }; + + }); + _registerModule(_modules, 'parts/ScrollbarAxis.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, defined = U.defined, pick = U.pick; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Creates scrollbars if enabled. + * + * @private + */ + var ScrollbarAxis = /** @class */ (function () { + function ScrollbarAxis() { + } + /** + * Attaches to axis events to create scrollbars if enabled. + * + * @private + * + * @param AxisClass + * Axis class to extend. + * + * @param ScrollbarClass + * Scrollbar class to use. + */ + ScrollbarAxis.compose = function (AxisClass, ScrollbarClass) { + // Wrap axis initialization and create scrollbar if enabled: + addEvent(AxisClass, 'afterInit', function () { + var axis = this; + if (axis.options && + axis.options.scrollbar && + axis.options.scrollbar.enabled) { + // Predefined options: + axis.options.scrollbar.vertical = !axis.horiz; + axis.options.startOnTick = axis.options.endOnTick = false; + axis.scrollbar = new ScrollbarClass(axis.chart.renderer, axis.options.scrollbar, axis.chart); + addEvent(axis.scrollbar, 'changed', function (e) { + var axisMin = pick(axis.options && axis.options.min, axis.min), axisMax = pick(axis.options && axis.options.max, axis.max), unitedMin = defined(axis.dataMin) ? + Math.min(axisMin, axis.min, axis.dataMin) : axisMin, unitedMax = defined(axis.dataMax) ? + Math.max(axisMax, axis.max, axis.dataMax) : axisMax, range = unitedMax - unitedMin, to, from; + // #12834, scroll when show/hide series, wrong extremes + if (!defined(axisMin) || !defined(axisMax)) { + return; + } + if ((axis.horiz && !axis.reversed) || + (!axis.horiz && axis.reversed)) { + to = unitedMin + range * this.to; + from = unitedMin + range * this.from; + } + else { + // y-values in browser are reversed, but this also + // applies for reversed horizontal axis: + to = unitedMin + range * (1 - this.from); + from = unitedMin + range * (1 - this.to); + } + if (pick(this.options.liveRedraw, H.svg && !H.isTouchDevice && !this.chart.isBoosting) || + // Mouseup always should change extremes + e.DOMType === 'mouseup' || + // Internal events + !defined(e.DOMType)) { + axis.setExtremes(from, to, true, e.DOMType !== 'mousemove', e); + } + else { + // When live redraw is disabled, don't change extremes + // Only change the position of the scollbar thumb + this.setRange(this.from, this.to); + } + }); + } + }); + // Wrap rendering axis, and update scrollbar if one is created: + addEvent(AxisClass, 'afterRender', function () { + var axis = this, scrollMin = Math.min(pick(axis.options.min, axis.min), axis.min, pick(axis.dataMin, axis.min) // #6930 + ), scrollMax = Math.max(pick(axis.options.max, axis.max), axis.max, pick(axis.dataMax, axis.max) // #6930 + ), scrollbar = axis.scrollbar, offset = axis.axisTitleMargin + (axis.titleOffset || 0), scrollbarsOffsets = axis.chart.scrollbarsOffsets, axisMargin = axis.options.margin || 0, offsetsIndex, from, to; + if (scrollbar) { + if (axis.horiz) { + // Reserve space for labels/title + if (!axis.opposite) { + scrollbarsOffsets[1] += offset; + } + scrollbar.position(axis.left, axis.top + axis.height + 2 + scrollbarsOffsets[1] - + (axis.opposite ? axisMargin : 0), axis.width, axis.height); + // Next scrollbar should reserve space for margin (if set) + if (!axis.opposite) { + scrollbarsOffsets[1] += axisMargin; + } + offsetsIndex = 1; + } + else { + // Reserve space for labels/title + if (axis.opposite) { + scrollbarsOffsets[0] += offset; + } + scrollbar.position(axis.left + axis.width + 2 + scrollbarsOffsets[0] - + (axis.opposite ? 0 : axisMargin), axis.top, axis.width, axis.height); + // Next scrollbar should reserve space for margin (if set) + if (axis.opposite) { + scrollbarsOffsets[0] += axisMargin; + } + offsetsIndex = 0; + } + scrollbarsOffsets[offsetsIndex] += scrollbar.size + + scrollbar.options.margin; + if (isNaN(scrollMin) || + isNaN(scrollMax) || + !defined(axis.min) || + !defined(axis.max) || + axis.min === axis.max // #10733 + ) { + // default action: when extremes are the same or there is + // not extremes on the axis, but scrollbar exists, make it + // full size + scrollbar.setRange(0, 1); + } + else { + from = + (axis.min - scrollMin) / (scrollMax - scrollMin); + to = + (axis.max - scrollMin) / (scrollMax - scrollMin); + if ((axis.horiz && !axis.reversed) || + (!axis.horiz && axis.reversed)) { + scrollbar.setRange(from, to); + } + else { + // inverse vertical axis + scrollbar.setRange(1 - to, 1 - from); + } + } + } + }); + // Make space for a scrollbar: + addEvent(AxisClass, 'afterGetOffset', function () { + var axis = this, index = axis.horiz ? 2 : 1, scrollbar = axis.scrollbar; + if (scrollbar) { + axis.chart.scrollbarsOffsets = [0, 0]; // reset scrollbars offsets + axis.chart.axisOffset[index] += + scrollbar.size + scrollbar.options.margin; + } + }); + }; + return ScrollbarAxis; + }()); + + return ScrollbarAxis; + }); + _registerModule(_modules, 'parts/Scrollbar.js', [_modules['parts/Axis.js'], _modules['parts/Globals.js'], _modules['parts/ScrollbarAxis.js'], _modules['parts/Utilities.js']], function (Axis, H, ScrollbarAxis, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, correctFloat = U.correctFloat, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, fireEvent = U.fireEvent, merge = U.merge, pick = U.pick, removeEvent = U.removeEvent; + var defaultOptions = H.defaultOptions, hasTouch = H.hasTouch, isTouchDevice = H.isTouchDevice; + /** + * When we have vertical scrollbar, rifles and arrow in buttons should be + * rotated. The same method is used in Navigator's handles, to rotate them. + * + * @function Highcharts.swapXY + * + * @param {Highcharts.SVGPathArray} path + * Path to be rotated. + * + * @param {boolean} [vertical] + * If vertical scrollbar, swap x-y values. + * + * @return {Highcharts.SVGPathArray} + * Rotated path. + * + * @requires modules/stock + */ + var swapXY = H.swapXY = function (path, vertical) { + if (vertical) { + path.forEach(function (seg) { + var len = seg.length; + var temp; + for (var i = 0; i < len; i += 2) { + temp = seg[i + 1]; + if (typeof temp === 'number') { + seg[i + 1] = seg[i + 2]; + seg[i + 2] = temp; + } + } + }); + } + return path; + }; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * A reusable scrollbar, internally used in Highstock's navigator and optionally + * on individual axes. + * + * @private + * @class + * @name Highcharts.Scrollbar + * @param {Highcharts.SVGRenderer} renderer + * @param {Highcharts.ScrollbarOptions} options + * @param {Highcharts.Chart} chart + */ + var Scrollbar = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Scrollbar(renderer, options, chart) { + /* * + * + * Properties + * + * */ + this._events = []; + this.chartX = 0; + this.chartY = 0; + this.from = 0; + this.group = void 0; + this.scrollbar = void 0; + this.scrollbarButtons = []; + this.scrollbarGroup = void 0; + this.scrollbarLeft = 0; + this.scrollbarRifles = void 0; + this.scrollbarStrokeWidth = 1; + this.scrollbarTop = 0; + this.size = 0; + this.to = 0; + this.track = void 0; + this.trackBorderWidth = 1; + this.userOptions = {}; + this.x = 0; + this.y = 0; + this.chart = chart; + this.options = options; + this.renderer = chart.renderer; + this.init(renderer, options, chart); + } + /* * + * + * Functions + * + * */ + /** + * Set up the mouse and touch events for the Scrollbar + * + * @private + * @function Highcharts.Scrollbar#addEvents + * @return {void} + */ + Scrollbar.prototype.addEvents = function () { + var buttonsOrder = this.options.inverted ? [1, 0] : [0, 1], buttons = this.scrollbarButtons, bar = this.scrollbarGroup.element, track = this.track.element, mouseDownHandler = this.mouseDownHandler.bind(this), mouseMoveHandler = this.mouseMoveHandler.bind(this), mouseUpHandler = this.mouseUpHandler.bind(this), _events; + // Mouse events + _events = [ + [buttons[buttonsOrder[0]].element, 'click', this.buttonToMinClick.bind(this)], + [buttons[buttonsOrder[1]].element, 'click', this.buttonToMaxClick.bind(this)], + [track, 'click', this.trackClick.bind(this)], + [bar, 'mousedown', mouseDownHandler], + [bar.ownerDocument, 'mousemove', mouseMoveHandler], + [bar.ownerDocument, 'mouseup', mouseUpHandler] + ]; + // Touch events + if (hasTouch) { + _events.push([bar, 'touchstart', mouseDownHandler], [bar.ownerDocument, 'touchmove', mouseMoveHandler], [bar.ownerDocument, 'touchend', mouseUpHandler]); + } + // Add them all + _events.forEach(function (args) { + addEvent.apply(null, args); + }); + this._events = _events; + }; + Scrollbar.prototype.buttonToMaxClick = function (e) { + var scroller = this; + var range = (scroller.to - scroller.from) * pick(scroller.options.step, 0.2); + scroller.updatePosition(scroller.from + range, scroller.to + range); + fireEvent(scroller, 'changed', { + from: scroller.from, + to: scroller.to, + trigger: 'scrollbar', + DOMEvent: e + }); + }; + Scrollbar.prototype.buttonToMinClick = function (e) { + var scroller = this; + var range = correctFloat(scroller.to - scroller.from) * + pick(scroller.options.step, 0.2); + scroller.updatePosition(correctFloat(scroller.from - range), correctFloat(scroller.to - range)); + fireEvent(scroller, 'changed', { + from: scroller.from, + to: scroller.to, + trigger: 'scrollbar', + DOMEvent: e + }); + }; + /** + * Get normalized (0-1) cursor position over the scrollbar + * + * @private + * @function Highcharts.Scrollbar#cursorToScrollbarPosition + * + * @param {*} normalizedEvent + * normalized event, with chartX and chartY values + * + * @return {Highcharts.Dictionary} + * Local position {chartX, chartY} + */ + Scrollbar.prototype.cursorToScrollbarPosition = function (normalizedEvent) { + var scroller = this, options = scroller.options, minWidthDifference = options.minWidth > scroller.calculatedWidth ? + options.minWidth : + 0; // minWidth distorts translation + return { + chartX: (normalizedEvent.chartX - scroller.x - + scroller.xOffset) / + (scroller.barWidth - minWidthDifference), + chartY: (normalizedEvent.chartY - scroller.y - + scroller.yOffset) / + (scroller.barWidth - minWidthDifference) + }; + }; + /** + * Destroys allocated elements. + * + * @private + * @function Highcharts.Scrollbar#destroy + * @return {void} + */ + Scrollbar.prototype.destroy = function () { + var scroller = this.chart.scroller; + // Disconnect events added in addEvents + this.removeEvents(); + // Destroy properties + [ + 'track', + 'scrollbarRifles', + 'scrollbar', + 'scrollbarGroup', + 'group' + ].forEach(function (prop) { + if (this[prop] && this[prop].destroy) { + this[prop] = this[prop].destroy(); + } + }, this); + // #6421, chart may have more scrollbars + if (scroller && this === scroller.scrollbar) { + scroller.scrollbar = null; + // Destroy elements in collection + destroyObjectProperties(scroller.scrollbarButtons); + } + }; + /** + * Draw the scrollbar buttons with arrows + * + * @private + * @function Highcharts.Scrollbar#drawScrollbarButton + * @param {number} index + * 0 is left, 1 is right + * @return {void} + */ + Scrollbar.prototype.drawScrollbarButton = function (index) { + var scroller = this, renderer = scroller.renderer, scrollbarButtons = scroller.scrollbarButtons, options = scroller.options, size = scroller.size, group, tempElem; + group = renderer.g().add(scroller.group); + scrollbarButtons.push(group); + // Create a rectangle for the scrollbar button + tempElem = renderer.rect() + .addClass('highcharts-scrollbar-button') + .add(group); + // Presentational attributes + if (!this.chart.styledMode) { + tempElem.attr({ + stroke: options.buttonBorderColor, + 'stroke-width': options.buttonBorderWidth, + fill: options.buttonBackgroundColor + }); + } + // Place the rectangle based on the rendered stroke width + tempElem.attr(tempElem.crisp({ + x: -0.5, + y: -0.5, + width: size + 1, + height: size + 1, + r: options.buttonBorderRadius + }, tempElem.strokeWidth())); + // Button arrow + tempElem = renderer + .path(swapXY([[ + 'M', + size / 2 + (index ? -1 : 1), + size / 2 - 3 + ], [ + 'L', + size / 2 + (index ? -1 : 1), + size / 2 + 3 + ], [ + 'L', + size / 2 + (index ? 2 : -2), + size / 2 + ]], options.vertical)) + .addClass('highcharts-scrollbar-arrow') + .add(scrollbarButtons[index]); + if (!this.chart.styledMode) { + tempElem.attr({ + fill: options.buttonArrowColor + }); + } + }; + /** + * @private + * @function Highcharts.Scrollbar#init + * @param {Highcharts.SVGRenderer} renderer + * @param {Highcharts.ScrollbarOptions} options + * @param {Highcharts.Chart} chart + */ + Scrollbar.prototype.init = function (renderer, options, chart) { + this.scrollbarButtons = []; + this.renderer = renderer; + this.userOptions = options; + this.options = merge(Scrollbar.defaultOptions, options); + this.chart = chart; + // backward compatibility + this.size = pick(this.options.size, this.options.height); + // Init + if (options.enabled) { + this.render(); + this.addEvents(); + } + }; + Scrollbar.prototype.mouseDownHandler = function (e) { + var scroller = this; + var normalizedEvent = scroller.chart.pointer.normalize(e), mousePosition = scroller.cursorToScrollbarPosition(normalizedEvent); + scroller.chartX = mousePosition.chartX; + scroller.chartY = mousePosition.chartY; + scroller.initPositions = [scroller.from, scroller.to]; + scroller.grabbedCenter = true; + }; + /** + * Event handler for the mouse move event. + * @private + */ + Scrollbar.prototype.mouseMoveHandler = function (e) { + var scroller = this; + var normalizedEvent = scroller.chart.pointer.normalize(e), options = scroller.options, direction = options.vertical ? 'chartY' : 'chartX', initPositions = scroller.initPositions || [], scrollPosition, chartPosition, change; + // In iOS, a mousemove event with e.pageX === 0 is fired when + // holding the finger down in the center of the scrollbar. This + // should be ignored. + if (scroller.grabbedCenter && + // #4696, scrollbar failed on Android + (!e.touches || e.touches[0][direction] !== 0)) { + chartPosition = scroller.cursorToScrollbarPosition(normalizedEvent)[direction]; + scrollPosition = scroller[direction]; + change = chartPosition - scrollPosition; + scroller.hasDragged = true; + scroller.updatePosition(initPositions[0] + change, initPositions[1] + change); + if (scroller.hasDragged) { + fireEvent(scroller, 'changed', { + from: scroller.from, + to: scroller.to, + trigger: 'scrollbar', + DOMType: e.type, + DOMEvent: e + }); + } + } + }; + /** + * Event handler for the mouse up event. + * @private + */ + Scrollbar.prototype.mouseUpHandler = function (e) { + var scroller = this; + if (scroller.hasDragged) { + fireEvent(scroller, 'changed', { + from: scroller.from, + to: scroller.to, + trigger: 'scrollbar', + DOMType: e.type, + DOMEvent: e + }); + } + scroller.grabbedCenter = + scroller.hasDragged = + scroller.chartX = + scroller.chartY = null; + }; + /** + * Position the scrollbar, method called from a parent with defined + * dimensions. + * + * @private + * @function Highcharts.Scrollbar#position + * @param {number} x + * x-position on the chart + * @param {number} y + * y-position on the chart + * @param {number} width + * width of the scrollbar + * @param {number} height + * height of the scorllbar + * @return {void} + */ + Scrollbar.prototype.position = function (x, y, width, height) { + var scroller = this, options = scroller.options, vertical = options.vertical, xOffset = height, yOffset = 0, method = scroller.rendered ? 'animate' : 'attr'; + scroller.x = x; + scroller.y = y + this.trackBorderWidth; + scroller.width = width; // width with buttons + scroller.height = height; + scroller.xOffset = xOffset; + scroller.yOffset = yOffset; + // If Scrollbar is a vertical type, swap options: + if (vertical) { + scroller.width = scroller.yOffset = width = yOffset = scroller.size; + scroller.xOffset = xOffset = 0; + scroller.barWidth = height - width * 2; // width without buttons + scroller.x = x = x + scroller.options.margin; + } + else { + scroller.height = scroller.xOffset = height = xOffset = + scroller.size; + scroller.barWidth = width - height * 2; // width without buttons + scroller.y = scroller.y + scroller.options.margin; + } + // Set general position for a group: + scroller.group[method]({ + translateX: x, + translateY: scroller.y + }); + // Resize background/track: + scroller.track[method]({ + width: width, + height: height + }); + // Move right/bottom button ot it's place: + scroller.scrollbarButtons[1][method]({ + translateX: vertical ? 0 : width - xOffset, + translateY: vertical ? height - yOffset : 0 + }); + }; + /** + * Removes the event handlers attached previously with addEvents. + * + * @private + * @function Highcharts.Scrollbar#removeEvents + * @return {void} + */ + Scrollbar.prototype.removeEvents = function () { + this._events.forEach(function (args) { + removeEvent.apply(null, args); + }); + this._events.length = 0; + }; + /** + * Render scrollbar with all required items. + * + * @private + * @function Highcharts.Scrollbar#render + */ + Scrollbar.prototype.render = function () { + var scroller = this, renderer = scroller.renderer, options = scroller.options, size = scroller.size, styledMode = this.chart.styledMode, group; + // Draw the scrollbar group + scroller.group = group = renderer.g('scrollbar').attr({ + zIndex: options.zIndex, + translateY: -99999 + }).add(); + // Draw the scrollbar track: + scroller.track = renderer.rect() + .addClass('highcharts-scrollbar-track') + .attr({ + x: 0, + r: options.trackBorderRadius || 0, + height: size, + width: size + }).add(group); + if (!styledMode) { + scroller.track.attr({ + fill: options.trackBackgroundColor, + stroke: options.trackBorderColor, + 'stroke-width': options.trackBorderWidth + }); + } + this.trackBorderWidth = scroller.track.strokeWidth(); + scroller.track.attr({ + y: -this.trackBorderWidth % 2 / 2 + }); + // Draw the scrollbar itself + scroller.scrollbarGroup = renderer.g().add(group); + scroller.scrollbar = renderer.rect() + .addClass('highcharts-scrollbar-thumb') + .attr({ + height: size, + width: size, + r: options.barBorderRadius || 0 + }).add(scroller.scrollbarGroup); + scroller.scrollbarRifles = renderer + .path(swapXY([ + ['M', -3, size / 4], + ['L', -3, 2 * size / 3], + ['M', 0, size / 4], + ['L', 0, 2 * size / 3], + ['M', 3, size / 4], + ['L', 3, 2 * size / 3] + ], options.vertical)) + .addClass('highcharts-scrollbar-rifles') + .add(scroller.scrollbarGroup); + if (!styledMode) { + scroller.scrollbar.attr({ + fill: options.barBackgroundColor, + stroke: options.barBorderColor, + 'stroke-width': options.barBorderWidth + }); + scroller.scrollbarRifles.attr({ + stroke: options.rifleColor, + 'stroke-width': 1 + }); + } + scroller.scrollbarStrokeWidth = scroller.scrollbar.strokeWidth(); + scroller.scrollbarGroup.translate(-scroller.scrollbarStrokeWidth % 2 / 2, -scroller.scrollbarStrokeWidth % 2 / 2); + // Draw the buttons: + scroller.drawScrollbarButton(0); + scroller.drawScrollbarButton(1); + }; + /** + * Set scrollbar size, with a given scale. + * + * @private + * @function Highcharts.Scrollbar#setRange + * @param {number} from + * scale (0-1) where bar should start + * @param {number} to + * scale (0-1) where bar should end + * @return {void} + */ + Scrollbar.prototype.setRange = function (from, to) { + var scroller = this, options = scroller.options, vertical = options.vertical, minWidth = options.minWidth, fullWidth = scroller.barWidth, fromPX, toPX, newPos, newSize, newRiflesPos, method = (this.rendered && + !this.hasDragged && + !(this.chart.navigator && this.chart.navigator.hasDragged)) ? 'animate' : 'attr'; + if (!defined(fullWidth)) { + return; + } + from = Math.max(from, 0); + fromPX = Math.ceil(fullWidth * from); + toPX = fullWidth * Math.min(to, 1); + scroller.calculatedWidth = newSize = correctFloat(toPX - fromPX); + // We need to recalculate position, if minWidth is used + if (newSize < minWidth) { + fromPX = (fullWidth - minWidth + newSize) * from; + newSize = minWidth; + } + newPos = Math.floor(fromPX + scroller.xOffset + scroller.yOffset); + newRiflesPos = newSize / 2 - 0.5; // -0.5 -> rifle line width / 2 + // Store current position: + scroller.from = from; + scroller.to = to; + if (!vertical) { + scroller.scrollbarGroup[method]({ + translateX: newPos + }); + scroller.scrollbar[method]({ + width: newSize + }); + scroller.scrollbarRifles[method]({ + translateX: newRiflesPos + }); + scroller.scrollbarLeft = newPos; + scroller.scrollbarTop = 0; + } + else { + scroller.scrollbarGroup[method]({ + translateY: newPos + }); + scroller.scrollbar[method]({ + height: newSize + }); + scroller.scrollbarRifles[method]({ + translateY: newRiflesPos + }); + scroller.scrollbarTop = newPos; + scroller.scrollbarLeft = 0; + } + if (newSize <= 12) { + scroller.scrollbarRifles.hide(); + } + else { + scroller.scrollbarRifles.show(true); + } + // Show or hide the scrollbar based on the showFull setting + if (options.showFull === false) { + if (from <= 0 && to >= 1) { + scroller.group.hide(); + } + else { + scroller.group.show(); + } + } + scroller.rendered = true; + }; + Scrollbar.prototype.trackClick = function (e) { + var scroller = this; + var normalizedEvent = scroller.chart.pointer.normalize(e), range = scroller.to - scroller.from, top = scroller.y + scroller.scrollbarTop, left = scroller.x + scroller.scrollbarLeft; + if ((scroller.options.vertical && normalizedEvent.chartY > top) || + (!scroller.options.vertical && normalizedEvent.chartX > left)) { + // On the top or on the left side of the track: + scroller.updatePosition(scroller.from + range, scroller.to + range); + } + else { + // On the bottom or the right side of the track: + scroller.updatePosition(scroller.from - range, scroller.to - range); + } + fireEvent(scroller, 'changed', { + from: scroller.from, + to: scroller.to, + trigger: 'scrollbar', + DOMEvent: e + }); + }; + /** + * Update the scrollbar with new options + * + * @private + * @function Highcharts.Scrollbar#update + * @param {Highcharts.ScrollbarOptions} options + * @return {void} + */ + Scrollbar.prototype.update = function (options) { + this.destroy(); + this.init(this.chart.renderer, merge(true, this.options, options), this.chart); + }; + /** + * Update position option in the Scrollbar, with normalized 0-1 scale + * + * @private + * @function Highcharts.Scrollbar#updatePosition + * @param {number} from + * @param {number} to + * @return {void} + */ + Scrollbar.prototype.updatePosition = function (from, to) { + if (to > 1) { + from = correctFloat(1 - correctFloat(to - from)); + to = 1; + } + if (from < 0) { + to = correctFloat(to - from); + from = 0; + } + this.from = from; + this.to = to; + }; + /* * + * + * Static Properties + * + * */ + /** + * + * The scrollbar is a means of panning over the X axis of a stock chart. + * Scrollbars can also be applied to other types of axes. + * + * Another approach to scrollable charts is the [chart.scrollablePlotArea]( + * https://api.highcharts.com/highcharts/chart.scrollablePlotArea) option that + * is especially suitable for simpler cartesian charts on mobile. + * + * In styled mode, all the presentational options for the + * scrollbar are replaced by the classes `.highcharts-scrollbar-thumb`, + * `.highcharts-scrollbar-arrow`, `.highcharts-scrollbar-button`, + * `.highcharts-scrollbar-rifles` and `.highcharts-scrollbar-track`. + * + * @sample stock/yaxis/inverted-bar-scrollbar/ + * A scrollbar on a simple bar chart + * + * @product highstock gantt + * @optionparent scrollbar + * + * @private + */ + Scrollbar.defaultOptions = { + /** + * The height of the scrollbar. The height also applies to the width + * of the scroll arrows so that they are always squares. Defaults to + * 20 for touch devices and 14 for mouse devices. + * + * @sample stock/scrollbar/height/ + * A 30px scrollbar + * + * @type {number} + * @default 20/14 + */ + height: isTouchDevice ? 20 : 14, + /** + * The border rounding radius of the bar. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + */ + barBorderRadius: 0, + /** + * The corner radius of the scrollbar buttons. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + */ + buttonBorderRadius: 0, + /** + * Enable or disable the scrollbar. + * + * @sample stock/scrollbar/enabled/ + * Disable the scrollbar, only use navigator + * + * @type {boolean} + * @default true + * @apioption scrollbar.enabled + */ + /** + * Whether to redraw the main chart as the scrollbar or the navigator + * zoomed window is moved. Defaults to `true` for modern browsers and + * `false` for legacy IE browsers as well as mobile devices. + * + * @sample stock/scrollbar/liveredraw + * Setting live redraw to false + * + * @type {boolean} + * @since 1.3 + */ + liveRedraw: void 0, + /** + * The margin between the scrollbar and its axis when the scrollbar is + * applied directly to an axis. + */ + margin: 10, + /** + * The minimum width of the scrollbar. + * + * @since 1.2.5 + */ + minWidth: 6, + /** + * Whether to show or hide the scrollbar when the scrolled content is + * zoomed out to it full extent. + * + * @type {boolean} + * @default true + * @apioption scrollbar.showFull + */ + step: 0.2, + /** + * The z index of the scrollbar group. + */ + zIndex: 3, + /** + * The background color of the scrollbar itself. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + barBackgroundColor: '#cccccc', + /** + * The width of the bar's border. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + */ + barBorderWidth: 1, + /** + * The color of the scrollbar's border. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + barBorderColor: '#cccccc', + /** + * The color of the small arrow inside the scrollbar buttons. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + buttonArrowColor: '#333333', + /** + * The color of scrollbar buttons. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + buttonBackgroundColor: '#e6e6e6', + /** + * The color of the border of the scrollbar buttons. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + buttonBorderColor: '#cccccc', + /** + * The border width of the scrollbar buttons. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + */ + buttonBorderWidth: 1, + /** + * The color of the small rifles in the middle of the scrollbar. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + rifleColor: '#333333', + /** + * The color of the track background. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + trackBackgroundColor: '#f2f2f2', + /** + * The color of the border of the scrollbar track. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + trackBorderColor: '#f2f2f2', + /** + * The corner radius of the border of the scrollbar track. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {number} + * @default 0 + * @apioption scrollbar.trackBorderRadius + */ + /** + * The width of the border of the scrollbar track. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + */ + trackBorderWidth: 1 + }; + return Scrollbar; + }()); + if (!H.Scrollbar) { + defaultOptions.scrollbar = merge(true, Scrollbar.defaultOptions, defaultOptions.scrollbar); + H.Scrollbar = Scrollbar; + ScrollbarAxis.compose(Axis, Scrollbar); + } + + return H.Scrollbar; + }); + _registerModule(_modules, 'parts/RangeSelector.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Define the time span for the button + * + * @typedef {"all"|"day"|"hour"|"millisecond"|"minute"|"month"|"second"|"week"|"year"|"ytd"} Highcharts.RangeSelectorButtonTypeValue + */ + /** + * Callback function to react on button clicks. + * + * @callback Highcharts.RangeSelectorClickCallbackFunction + * + * @param {global.Event} e + * Event arguments. + * + * @param {boolean|undefined} + * Return false to cancel the default button event. + */ + /** + * Callback function to parse values entered in the input boxes and return a + * valid JavaScript time as milliseconds since 1970. + * + * @callback Highcharts.RangeSelectorParseCallbackFunction + * + * @param {string} value + * Input value to parse. + * + * @return {number} + * Parsed JavaScript time value. + */ + var addEvent = U.addEvent, createElement = U.createElement, css = U.css, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, discardElement = U.discardElement, extend = U.extend, fireEvent = U.fireEvent, isNumber = U.isNumber, merge = U.merge, objectEach = U.objectEach, pick = U.pick, pInt = U.pInt, splat = U.splat; + var Axis = H.Axis, Chart = H.Chart, defaultOptions = H.defaultOptions; + /* ************************************************************************** * + * Start Range Selector code * + * ************************************************************************** */ + extend(defaultOptions, { + /** + * The range selector is a tool for selecting ranges to display within + * the chart. It provides buttons to select preconfigured ranges in + * the chart, like 1 day, 1 week, 1 month etc. It also provides input + * boxes where min and max dates can be manually input. + * + * @product highstock gantt + * @optionparent rangeSelector + */ + rangeSelector: { + /** + * Whether to enable all buttons from the start. By default buttons are + * only enabled if the corresponding time range exists on the X axis, + * but enabling all buttons allows for dynamically loading different + * time ranges. + * + * @sample {highstock} stock/rangeselector/allbuttonsenabled-true/ + * All buttons enabled + * + * @type {boolean} + * @default false + * @since 2.0.3 + * @apioption rangeSelector.allButtonsEnabled + */ + /** + * An array of configuration objects for the buttons. + * + * Defaults to: + * ```js + * buttons: [{ + * type: 'month', + * count: 1, + * text: '1m' + * }, { + * type: 'month', + * count: 3, + * text: '3m' + * }, { + * type: 'month', + * count: 6, + * text: '6m' + * }, { + * type: 'ytd', + * text: 'YTD' + * }, { + * type: 'year', + * count: 1, + * text: '1y' + * }, { + * type: 'all', + * text: 'All' + * }] + * ``` + * + * @sample {highstock} stock/rangeselector/datagrouping/ + * Data grouping by buttons + * + * @type {Array<*>} + * @apioption rangeSelector.buttons + */ + /** + * How many units of the defined type the button should span. If `type` + * is "month" and `count` is 3, the button spans three months. + * + * @type {number} + * @default 1 + * @apioption rangeSelector.buttons.count + */ + /** + * Fires when clicking on the rangeSelector button. One parameter, + * event, is passed to the function, containing common event + * information. + * + * ```js + * click: function(e) { + * console.log(this); + * } + * ``` + * + * Return false to stop default button's click action. + * + * @sample {highstock} stock/rangeselector/button-click/ + * Click event on the button + * + * @type {Highcharts.RangeSelectorClickCallbackFunction} + * @apioption rangeSelector.buttons.events.click + */ + /** + * Additional range (in milliseconds) added to the end of the calculated + * time span. + * + * @sample {highstock} stock/rangeselector/min-max-offsets/ + * Button offsets + * + * @type {number} + * @default 0 + * @since 6.0.0 + * @apioption rangeSelector.buttons.offsetMax + */ + /** + * Additional range (in milliseconds) added to the start of the + * calculated time span. + * + * @sample {highstock} stock/rangeselector/min-max-offsets/ + * Button offsets + * + * @type {number} + * @default 0 + * @since 6.0.0 + * @apioption rangeSelector.buttons.offsetMin + */ + /** + * When buttons apply dataGrouping on a series, by default zooming + * in/out will deselect buttons and unset dataGrouping. Enable this + * option to keep buttons selected when extremes change. + * + * @sample {highstock} stock/rangeselector/preserve-datagrouping/ + * Different preserveDataGrouping settings + * + * @type {boolean} + * @default false + * @since 6.1.2 + * @apioption rangeSelector.buttons.preserveDataGrouping + */ + /** + * A custom data grouping object for each button. + * + * @see [series.dataGrouping](#plotOptions.series.dataGrouping) + * + * @sample {highstock} stock/rangeselector/datagrouping/ + * Data grouping by range selector buttons + * + * @type {*} + * @extends plotOptions.series.dataGrouping + * @apioption rangeSelector.buttons.dataGrouping + */ + /** + * The text for the button itself. + * + * @type {string} + * @apioption rangeSelector.buttons.text + */ + /** + * Defined the time span for the button. Can be one of `millisecond`, + * `second`, `minute`, `hour`, `day`, `week`, `month`, `year`, `ytd`, + * and `all`. + * + * @type {Highcharts.RangeSelectorButtonTypeValue} + * @apioption rangeSelector.buttons.type + */ + /** + * The space in pixels between the buttons in the range selector. + * + * @type {number} + * @default 0 + * @apioption rangeSelector.buttonSpacing + */ + /** + * Enable or disable the range selector. + * + * @sample {highstock} stock/rangeselector/enabled/ + * Disable the range selector + * + * @type {boolean} + * @default true + * @apioption rangeSelector.enabled + */ + /** + * The vertical alignment of the rangeselector box. Allowed properties + * are `top`, `middle`, `bottom`. + * + * @sample {highstock} stock/rangeselector/vertical-align-middle/ + * Middle + * @sample {highstock} stock/rangeselector/vertical-align-bottom/ + * Bottom + * + * @type {Highcharts.VerticalAlignValue} + * @since 6.0.0 + */ + verticalAlign: 'top', + /** + * A collection of attributes for the buttons. The object takes SVG + * attributes like `fill`, `stroke`, `stroke-width`, as well as `style`, + * a collection of CSS properties for the text. + * + * The object can also be extended with states, so you can set + * presentational options for `hover`, `select` or `disabled` button + * states. + * + * CSS styles for the text label. + * + * In styled mode, the buttons are styled by the + * `.highcharts-range-selector-buttons .highcharts-button` rule with its + * different states. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {Highcharts.SVGAttributes} + */ + buttonTheme: { + /** @ignore */ + width: 28, + /** @ignore */ + height: 18, + /** @ignore */ + padding: 2, + /** @ignore */ + zIndex: 7 // #484, #852 + }, + /** + * When the rangeselector is floating, the plot area does not reserve + * space for it. This opens for positioning anywhere on the chart. + * + * @sample {highstock} stock/rangeselector/floating/ + * Placing the range selector between the plot area and the + * navigator + * + * @since 6.0.0 + */ + floating: false, + /** + * The x offset of the range selector relative to its horizontal + * alignment within `chart.spacingLeft` and `chart.spacingRight`. + * + * @since 6.0.0 + */ + x: 0, + /** + * The y offset of the range selector relative to its horizontal + * alignment within `chart.spacingLeft` and `chart.spacingRight`. + * + * @since 6.0.0 + */ + y: 0, + /** + * Deprecated. The height of the range selector. Currently it is + * calculated dynamically. + * + * @deprecated + * @type {number|undefined} + * @since 2.1.9 + */ + height: void 0, + /** + * The border color of the date input boxes. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {Highcharts.ColorString} + * @default #cccccc + * @since 1.3.7 + * @apioption rangeSelector.inputBoxBorderColor + */ + /** + * The pixel height of the date input boxes. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {number} + * @default 17 + * @since 1.3.7 + * @apioption rangeSelector.inputBoxHeight + */ + /** + * CSS for the container DIV holding the input boxes. Deprecated as + * of 1.2.5\. Use [inputPosition](#rangeSelector.inputPosition) instead. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @deprecated + * @type {Highcharts.CSSObject} + * @apioption rangeSelector.inputBoxStyle + */ + /** + * The pixel width of the date input boxes. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {number} + * @default 90 + * @since 1.3.7 + * @apioption rangeSelector.inputBoxWidth + */ + /** + * The date format in the input boxes when not selected for editing. + * Defaults to `%b %e, %Y`. + * + * @sample {highstock} stock/rangeselector/input-format/ + * Milliseconds in the range selector + * + * @type {string} + * @default %b %e, %Y + * @apioption rangeSelector.inputDateFormat + */ + /** + * A custom callback function to parse values entered in the input boxes + * and return a valid JavaScript time as milliseconds since 1970. + * + * @sample {highstock} stock/rangeselector/input-format/ + * Milliseconds in the range selector + * + * @type {Highcharts.RangeSelectorParseCallbackFunction} + * @since 1.3.3 + * @apioption rangeSelector.inputDateParser + */ + /** + * The date format in the input boxes when they are selected for + * editing. This must be a format that is recognized by JavaScript + * Date.parse. + * + * @sample {highstock} stock/rangeselector/input-format/ + * Milliseconds in the range selector + * + * @type {string} + * @default %Y-%m-%d + * @apioption rangeSelector.inputEditDateFormat + */ + /** + * Enable or disable the date input boxes. Defaults to enabled when + * there is enough space, disabled if not (typically mobile). + * + * @sample {highstock} stock/rangeselector/input-datepicker/ + * Extending the input with a jQuery UI datepicker + * + * @type {boolean} + * @default true + * @apioption rangeSelector.inputEnabled + */ + /** + * Positioning for the input boxes. Allowed properties are `align`, + * `x` and `y`. + * + * @since 1.2.4 + */ + inputPosition: { + /** + * The alignment of the input box. Allowed properties are `left`, + * `center`, `right`. + * + * @sample {highstock} stock/rangeselector/input-button-position/ + * Alignment + * + * @type {Highcharts.AlignValue} + * @since 6.0.0 + */ + align: 'right', + /** + * X offset of the input row. + */ + x: 0, + /** + * Y offset of the input row. + */ + y: 0 + }, + /** + * The index of the button to appear pre-selected. + * + * @type {number} + * @apioption rangeSelector.selected + */ + /** + * Positioning for the button row. + * + * @since 1.2.4 + */ + buttonPosition: { + /** + * The alignment of the input box. Allowed properties are `left`, + * `center`, `right`. + * + * @sample {highstock} stock/rangeselector/input-button-position/ + * Alignment + * + * @type {Highcharts.AlignValue} + * @since 6.0.0 + */ + align: 'left', + /** + * X offset of the button row. + */ + x: 0, + /** + * Y offset of the button row. + */ + y: 0 + }, + /** + * CSS for the HTML inputs in the range selector. + * + * In styled mode, the inputs are styled by the + * `.highcharts-range-input text` rule in SVG mode, and + * `input.highcharts-range-selector` when active. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {Highcharts.CSSObject} + * @apioption rangeSelector.inputStyle + */ + /** + * CSS styles for the labels - the Zoom, From and To texts. + * + * In styled mode, the labels are styled by the + * `.highcharts-range-label` class. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {Highcharts.CSSObject} + */ + labelStyle: { + /** @ignore */ + color: '#666666' + } + } + }); + defaultOptions.lang = merge(defaultOptions.lang, + /** + * Language object. The language object is global and it can't be set + * on each chart initialization. Instead, use `Highcharts.setOptions` to + * set it before any chart is initialized. + * + * ```js + * Highcharts.setOptions({ + * lang: { + * months: [ + * 'Janvier', 'Février', 'Mars', 'Avril', + * 'Mai', 'Juin', 'Juillet', 'Août', + * 'Septembre', 'Octobre', 'Novembre', 'Décembre' + * ], + * weekdays: [ + * 'Dimanche', 'Lundi', 'Mardi', 'Mercredi', + * 'Jeudi', 'Vendredi', 'Samedi' + * ] + * } + * }); + * ``` + * + * @optionparent lang + */ + { + /** + * The text for the label for the range selector buttons. + * + * @product highstock gantt + */ + rangeSelectorZoom: 'Zoom', + /** + * The text for the label for the "from" input box in the range + * selector. + * + * @product highstock gantt + */ + rangeSelectorFrom: 'From', + /** + * The text for the label for the "to" input box in the range selector. + * + * @product highstock gantt + */ + rangeSelectorTo: 'To' + }); + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The range selector. + * + * @private + * @class + * @name Highcharts.RangeSelector + * @param {Highcharts.Chart} chart + */ + function RangeSelector(chart) { + // Run RangeSelector + this.init(chart); + } + RangeSelector.prototype = { + /** + * The method to run when one of the buttons in the range selectors is + * clicked + * + * @private + * @function Highcharts.RangeSelector#clickButton + * @param {number} i + * The index of the button + * @param {boolean} [redraw] + * @return {void} + */ + clickButton: function (i, redraw) { + var rangeSelector = this, chart = rangeSelector.chart, rangeOptions = rangeSelector.buttonOptions[i], baseAxis = chart.xAxis[0], unionExtremes = (chart.scroller && chart.scroller.getUnionExtremes()) || baseAxis || {}, dataMin = unionExtremes.dataMin, dataMax = unionExtremes.dataMax, newMin, newMax = baseAxis && Math.round(Math.min(baseAxis.max, pick(dataMax, baseAxis.max))), // #1568 + type = rangeOptions.type, baseXAxisOptions, range = rangeOptions._range, rangeMin, minSetting, rangeSetting, ctx, ytdExtremes, dataGrouping = rangeOptions.dataGrouping; + // chart has no data, base series is removed + if (dataMin === null || dataMax === null) { + return; + } + // Set the fixed range before range is altered + chart.fixedRange = range; + // Apply dataGrouping associated to button + if (dataGrouping) { + this.forcedDataGrouping = true; + Axis.prototype.setDataGrouping.call(baseAxis || { chart: this.chart }, dataGrouping, false); + this.frozenStates = rangeOptions.preserveDataGrouping; + } + // Apply range + if (type === 'month' || type === 'year') { + if (!baseAxis) { + // This is set to the user options and picked up later when the + // axis is instantiated so that we know the min and max. + range = rangeOptions; + } + else { + ctx = { + range: rangeOptions, + max: newMax, + chart: chart, + dataMin: dataMin, + dataMax: dataMax + }; + newMin = baseAxis.minFromRange.call(ctx); + if (isNumber(ctx.newMax)) { + newMax = ctx.newMax; + } + } + // Fixed times like minutes, hours, days + } + else if (range) { + newMin = Math.max(newMax - range, dataMin); + newMax = Math.min(newMin + range, dataMax); + } + else if (type === 'ytd') { + // On user clicks on the buttons, or a delayed action running from + // the beforeRender event (below), the baseAxis is defined. + if (baseAxis) { + // When "ytd" is the pre-selected button for the initial view, + // its calculation is delayed and rerun in the beforeRender + // event (below). When the series are initialized, but before + // the chart is rendered, we have access to the xData array + // (#942). + if (typeof dataMax === 'undefined') { + dataMin = Number.MAX_VALUE; + dataMax = Number.MIN_VALUE; + chart.series.forEach(function (series) { + // reassign it to the last item + var xData = series.xData; + dataMin = Math.min(xData[0], dataMin); + dataMax = Math.max(xData[xData.length - 1], dataMax); + }); + redraw = false; + } + ytdExtremes = rangeSelector.getYTDExtremes(dataMax, dataMin, chart.time.useUTC); + newMin = rangeMin = ytdExtremes.min; + newMax = ytdExtremes.max; + // "ytd" is pre-selected. We don't yet have access to processed + // point and extremes data (things like pointStart and pointInterval + // are missing), so we delay the process (#942) + } + else { + rangeSelector.deferredYTDClick = i; + return; + } + } + else if (type === 'all' && baseAxis) { + newMin = dataMin; + newMax = dataMax; + } + newMin += rangeOptions._offsetMin; + newMax += rangeOptions._offsetMax; + rangeSelector.setSelected(i); + // Update the chart + if (!baseAxis) { + // Axis not yet instanciated. Temporarily set min and range + // options and remove them on chart load (#4317). + baseXAxisOptions = splat(chart.options.xAxis)[0]; + rangeSetting = baseXAxisOptions.range; + baseXAxisOptions.range = range; + minSetting = baseXAxisOptions.min; + baseXAxisOptions.min = rangeMin; + addEvent(chart, 'load', function resetMinAndRange() { + baseXAxisOptions.range = rangeSetting; + baseXAxisOptions.min = minSetting; + }); + } + else { + // Existing axis object. Set extremes after render time. + baseAxis.setExtremes(newMin, newMax, pick(redraw, 1), null, // auto animation + { + trigger: 'rangeSelectorButton', + rangeSelectorButton: rangeOptions + }); + } + }, + /** + * Set the selected option. This method only sets the internal flag, it + * doesn't update the buttons or the actual zoomed range. + * + * @private + * @function Highcharts.RangeSelector#setSelected + * @param {number} [selected] + * @return {void} + */ + setSelected: function (selected) { + this.selected = this.options.selected = selected; + }, + /** + * The default buttons for pre-selecting time frames + */ + defaultButtons: [{ + type: 'month', + count: 1, + text: '1m' + }, { + type: 'month', + count: 3, + text: '3m' + }, { + type: 'month', + count: 6, + text: '6m' + }, { + type: 'ytd', + text: 'YTD' + }, { + type: 'year', + count: 1, + text: '1y' + }, { + type: 'all', + text: 'All' + }], + /** + * Initialize the range selector + * + * @private + * @function Highcharts.RangeSelector#init + * @param {Highcharts.Chart} chart + * @return {void} + */ + init: function (chart) { + var rangeSelector = this, options = chart.options.rangeSelector, buttonOptions = options.buttons || + [].concat(rangeSelector.defaultButtons), selectedOption = options.selected, blurInputs = function () { + var minInput = rangeSelector.minInput, maxInput = rangeSelector.maxInput; + // #3274 in some case blur is not defined + if (minInput && minInput.blur) { + fireEvent(minInput, 'blur'); + } + if (maxInput && maxInput.blur) { + fireEvent(maxInput, 'blur'); + } + }; + rangeSelector.chart = chart; + rangeSelector.options = options; + rangeSelector.buttons = []; + rangeSelector.buttonOptions = buttonOptions; + this.unMouseDown = addEvent(chart.container, 'mousedown', blurInputs); + this.unResize = addEvent(chart, 'resize', blurInputs); + // Extend the buttonOptions with actual range + buttonOptions.forEach(rangeSelector.computeButtonRange); + // zoomed range based on a pre-selected button index + if (typeof selectedOption !== 'undefined' && + buttonOptions[selectedOption]) { + this.clickButton(selectedOption, false); + } + addEvent(chart, 'load', function () { + // If a data grouping is applied to the current button, release it + // when extremes change + if (chart.xAxis && chart.xAxis[0]) { + addEvent(chart.xAxis[0], 'setExtremes', function (e) { + if (this.max - this.min !== + chart.fixedRange && + e.trigger !== 'rangeSelectorButton' && + e.trigger !== 'updatedData' && + rangeSelector.forcedDataGrouping && + !rangeSelector.frozenStates) { + this.setDataGrouping(false, false); + } + }); + } + }); + }, + /** + * Dynamically update the range selector buttons after a new range has been + * set + * + * @private + * @function Highcharts.RangeSelector#updateButtonStates + * @return {void} + */ + updateButtonStates: function () { + var rangeSelector = this, chart = this.chart, baseAxis = chart.xAxis[0], actualRange = Math.round(baseAxis.max - baseAxis.min), hasNoData = !baseAxis.hasVisibleSeries, day = 24 * 36e5, // A single day in milliseconds + unionExtremes = (chart.scroller && + chart.scroller.getUnionExtremes()) || baseAxis, dataMin = unionExtremes.dataMin, dataMax = unionExtremes.dataMax, ytdExtremes = rangeSelector.getYTDExtremes(dataMax, dataMin, chart.time.useUTC), ytdMin = ytdExtremes.min, ytdMax = ytdExtremes.max, selected = rangeSelector.selected, selectedExists = isNumber(selected), allButtonsEnabled = rangeSelector.options.allButtonsEnabled, buttons = rangeSelector.buttons; + rangeSelector.buttonOptions.forEach(function (rangeOptions, i) { + var range = rangeOptions._range, type = rangeOptions.type, count = rangeOptions.count || 1, button = buttons[i], state = 0, disable, select, offsetRange = rangeOptions._offsetMax - + rangeOptions._offsetMin, isSelected = i === selected, + // Disable buttons where the range exceeds what is allowed in + // the current view + isTooGreatRange = range > + dataMax - dataMin, + // Disable buttons where the range is smaller than the minimum + // range + isTooSmallRange = range < baseAxis.minRange, + // Do not select the YTD button if not explicitly told so + isYTDButNotSelected = false, + // Disable the All button if we're already showing all + isAllButAlreadyShowingAll = false, isSameRange = range === actualRange; + // Months and years have a variable range so we check the extremes + if ((type === 'month' || type === 'year') && + (actualRange + 36e5 >= + { month: 28, year: 365 }[type] * day * count - offsetRange) && + (actualRange - 36e5 <= + { month: 31, year: 366 }[type] * day * count + offsetRange)) { + isSameRange = true; + } + else if (type === 'ytd') { + isSameRange = (ytdMax - ytdMin + offsetRange) === actualRange; + isYTDButNotSelected = !isSelected; + } + else if (type === 'all') { + isSameRange = (baseAxis.max - baseAxis.min >= + dataMax - dataMin); + isAllButAlreadyShowingAll = (!isSelected && + selectedExists && + isSameRange); + } + // The new zoom area happens to match the range for a button - mark + // it selected. This happens when scrolling across an ordinal gap. + // It can be seen in the intraday demos when selecting 1h and scroll + // across the night gap. + disable = (!allButtonsEnabled && + (isTooGreatRange || + isTooSmallRange || + isAllButAlreadyShowingAll || + hasNoData)); + select = ((isSelected && isSameRange) || + (isSameRange && !selectedExists && !isYTDButNotSelected) || + (isSelected && rangeSelector.frozenStates)); + if (disable) { + state = 3; + } + else if (select) { + selectedExists = true; // Only one button can be selected + state = 2; + } + // If state has changed, update the button + if (button.state !== state) { + button.setState(state); + // Reset (#9209) + if (state === 0 && selected === i) { + rangeSelector.setSelected(null); + } + } + }); + }, + /** + * Compute and cache the range for an individual button + * + * @private + * @function Highcharts.RangeSelector#computeButtonRange + * @param {Highcharts.RangeSelectorButtonsOptions} rangeOptions + * @return {void} + */ + computeButtonRange: function (rangeOptions) { + var type = rangeOptions.type, count = rangeOptions.count || 1, + // these time intervals have a fixed number of milliseconds, as + // opposed to month, ytd and year + fixedTimes = { + millisecond: 1, + second: 1000, + minute: 60 * 1000, + hour: 3600 * 1000, + day: 24 * 3600 * 1000, + week: 7 * 24 * 3600 * 1000 + }; + // Store the range on the button object + if (fixedTimes[type]) { + rangeOptions._range = fixedTimes[type] * count; + } + else if (type === 'month' || type === 'year') { + rangeOptions._range = { + month: 30, + year: 365 + }[type] * 24 * 36e5 * count; + } + rangeOptions._offsetMin = pick(rangeOptions.offsetMin, 0); + rangeOptions._offsetMax = pick(rangeOptions.offsetMax, 0); + rangeOptions._range += + rangeOptions._offsetMax - rangeOptions._offsetMin; + }, + /** + * Set the internal and displayed value of a HTML input for the dates + * + * @private + * @function Highcharts.RangeSelector#setInputValue + * @param {string} name + * @param {number} [inputTime] + * @return {void} + */ + setInputValue: function (name, inputTime) { + var options = this.chart.options.rangeSelector, time = this.chart.time, input = this[name + 'Input']; + if (defined(inputTime)) { + input.previousValue = input.HCTime; + input.HCTime = inputTime; + } + input.value = time.dateFormat(options.inputEditDateFormat || '%Y-%m-%d', input.HCTime); + this[name + 'DateBox'].attr({ + text: time.dateFormat(options.inputDateFormat || '%b %e, %Y', input.HCTime) + }); + }, + /** + * @private + * @function Highcharts.RangeSelector#showInput + * @param {string} name + * @return {void} + */ + showInput: function (name) { + var inputGroup = this.inputGroup, dateBox = this[name + 'DateBox']; + css(this[name + 'Input'], { + left: (inputGroup.translateX + dateBox.x) + 'px', + top: inputGroup.translateY + 'px', + width: (dateBox.width - 2) + 'px', + height: (dateBox.height - 2) + 'px', + border: '2px solid silver' + }); + }, + /** + * @private + * @function Highcharts.RangeSelector#hideInput + * @param {string} name + * @return {void} + */ + hideInput: function (name) { + css(this[name + 'Input'], { + border: 0, + width: '1px', + height: '1px' + }); + this.setInputValue(name); + }, + /** + * Draw either the 'from' or the 'to' HTML input box of the range selector + * + * @private + * @function Highcharts.RangeSelector#drawInput + * @param {string} name + * @return {void} + */ + drawInput: function (name) { + var rangeSelector = this, chart = rangeSelector.chart, chartStyle = chart.renderer.style || {}, renderer = chart.renderer, options = chart.options.rangeSelector, lang = defaultOptions.lang, div = rangeSelector.div, isMin = name === 'min', input, label, dateBox, inputGroup = this.inputGroup; + /** + * @private + */ + function updateExtremes() { + var inputValue = input.value, value = (options.inputDateParser || Date.parse)(inputValue), chartAxis = chart.xAxis[0], dataAxis = chart.scroller && chart.scroller.xAxis ? + chart.scroller.xAxis : + chartAxis, dataMin = dataAxis.dataMin, dataMax = dataAxis.dataMax; + if (value !== input.previousValue) { + input.previousValue = value; + // If the value isn't parsed directly to a value by the + // browser's Date.parse method, like YYYY-MM-DD in IE, try + // parsing it a different way + if (!isNumber(value)) { + value = inputValue.split('-'); + value = Date.UTC(pInt(value[0]), pInt(value[1]) - 1, pInt(value[2])); + } + if (isNumber(value)) { + // Correct for timezone offset (#433) + if (!chart.time.useUTC) { + value = + value + new Date().getTimezoneOffset() * 60 * 1000; + } + // Validate the extremes. If it goes beyound the data min or + // max, use the actual data extreme (#2438). + if (isMin) { + if (value > rangeSelector.maxInput.HCTime) { + value = void 0; + } + else if (value < dataMin) { + value = dataMin; + } + } + else { + if (value < rangeSelector.minInput.HCTime) { + value = void 0; + } + else if (value > dataMax) { + value = dataMax; + } + } + // Set the extremes + if (typeof value !== 'undefined') { // @todo typof undefined + chartAxis.setExtremes(isMin ? value : chartAxis.min, isMin ? chartAxis.max : value, void 0, void 0, { trigger: 'rangeSelectorInput' }); + } + } + } + } + // Create the text label + this[name + 'Label'] = label = renderer + .label(lang[isMin ? 'rangeSelectorFrom' : 'rangeSelectorTo'], this.inputGroup.offset) + .addClass('highcharts-range-label') + .attr({ + padding: 2 + }) + .add(inputGroup); + inputGroup.offset += label.width + 5; + // Create an SVG label that shows updated date ranges and and records + // click events that bring in the HTML input. + this[name + 'DateBox'] = dateBox = renderer + .label('', inputGroup.offset) + .addClass('highcharts-range-input') + .attr({ + padding: 2, + width: options.inputBoxWidth || 90, + height: options.inputBoxHeight || 17, + 'text-align': 'center' + }) + .on('click', function () { + // If it is already focused, the onfocus event doesn't fire + // (#3713) + rangeSelector.showInput(name); + rangeSelector[name + 'Input'].focus(); + }); + if (!chart.styledMode) { + dateBox.attr({ + stroke: options.inputBoxBorderColor || '#cccccc', + 'stroke-width': 1 + }); + } + dateBox.add(inputGroup); + inputGroup.offset += dateBox.width + (isMin ? 10 : 0); + // Create the HTML input element. This is rendered as 1x1 pixel then set + // to the right size when focused. + this[name + 'Input'] = input = createElement('input', { + name: name, + className: 'highcharts-range-selector', + type: 'text' + }, { + top: chart.plotTop + 'px' // prevent jump on focus in Firefox + }, div); + if (!chart.styledMode) { + // Styles + label.css(merge(chartStyle, options.labelStyle)); + dateBox.css(merge({ + color: '#333333' + }, chartStyle, options.inputStyle)); + css(input, extend({ + position: 'absolute', + border: 0, + width: '1px', + height: '1px', + padding: 0, + textAlign: 'center', + fontSize: chartStyle.fontSize, + fontFamily: chartStyle.fontFamily, + top: '-9999em' // #4798 + }, options.inputStyle)); + } + // Blow up the input box + input.onfocus = function () { + rangeSelector.showInput(name); + }; + // Hide away the input box + input.onblur = function () { + // update extermes only when inputs are active + if (input === H.doc.activeElement) { // Only when focused + // Update also when no `change` event is triggered, like when + // clicking inside the SVG (#4710) + updateExtremes(); + } + // #10404 - move hide and blur outside focus + rangeSelector.hideInput(name); + input.blur(); // #4606 + }; + // handle changes in the input boxes + input.onchange = updateExtremes; + input.onkeypress = function (event) { + // IE does not fire onchange on enter + if (event.keyCode === 13) { + updateExtremes(); + } + }; + }, + /** + * Get the position of the range selector buttons and inputs. This can be + * overridden from outside for custom positioning. + * + * @private + * @function Highcharts.RangeSelector#getPosition + * + * @return {Highcharts.Dictionary} + */ + getPosition: function () { + var chart = this.chart, options = chart.options.rangeSelector, top = options.verticalAlign === 'top' ? + chart.plotTop - chart.axisOffset[0] : + 0; // set offset only for varticalAlign top + return { + buttonTop: top + options.buttonPosition.y, + inputTop: top + options.inputPosition.y - 10 + }; + }, + /** + * Get the extremes of YTD. Will choose dataMax if its value is lower than + * the current timestamp. Will choose dataMin if its value is higher than + * the timestamp for the start of current year. + * + * @private + * @function Highcharts.RangeSelector#getYTDExtremes + * + * @param {number} dataMax + * + * @param {number} dataMin + * + * @return {*} + * Returns min and max for the YTD + */ + getYTDExtremes: function (dataMax, dataMin, useUTC) { + var time = this.chart.time, min, now = new time.Date(dataMax), year = time.get('FullYear', now), startOfYear = useUTC ? + time.Date.UTC(year, 0, 1) : // eslint-disable-line new-cap + +new time.Date(year, 0, 1); + min = Math.max(dataMin || 0, startOfYear); + now = now.getTime(); + return { + max: Math.min(dataMax || now, now), + min: min + }; + }, + /** + * Render the range selector including the buttons and the inputs. The first + * time render is called, the elements are created and positioned. On + * subsequent calls, they are moved and updated. + * + * @private + * @function Highcharts.RangeSelector#render + * @param {number} [min] + * X axis minimum + * @param {number} [max] + * X axis maximum + * @return {void} + */ + render: function (min, max) { + var rangeSelector = this, chart = rangeSelector.chart, renderer = chart.renderer, container = chart.container, chartOptions = chart.options, navButtonOptions = (chartOptions.exporting && + chartOptions.exporting.enabled !== false && + chartOptions.navigation && + chartOptions.navigation.buttonOptions), lang = defaultOptions.lang, div = rangeSelector.div, options = chartOptions.rangeSelector, + // Place inputs above the container + inputsZIndex = pick(chartOptions.chart.style && + chartOptions.chart.style.zIndex, 0) + 1, floating = options.floating, buttons = rangeSelector.buttons, inputGroup = rangeSelector.inputGroup, buttonTheme = options.buttonTheme, buttonPosition = options.buttonPosition, inputPosition = options.inputPosition, inputEnabled = options.inputEnabled, states = buttonTheme && buttonTheme.states, plotLeft = chart.plotLeft, buttonLeft, buttonGroup = rangeSelector.buttonGroup, group, groupHeight, rendered = rangeSelector.rendered, verticalAlign = rangeSelector.options.verticalAlign, legend = chart.legend, legendOptions = legend && legend.options, buttonPositionY = buttonPosition.y, inputPositionY = inputPosition.y, animate = chart.hasLoaded, verb = animate ? 'animate' : 'attr', exportingX = 0, alignTranslateY, legendHeight, minPosition, translateY = 0, translateX; + if (options.enabled === false) { + return; + } + // create the elements + if (!rendered) { + rangeSelector.group = group = renderer.g('range-selector-group') + .attr({ + zIndex: 7 + }) + .add(); + rangeSelector.buttonGroup = buttonGroup = + renderer.g('range-selector-buttons').add(group); + rangeSelector.zoomText = renderer + .text(lang.rangeSelectorZoom, 0, 15) + .add(buttonGroup); + if (!chart.styledMode) { + rangeSelector.zoomText.css(options.labelStyle); + buttonTheme['stroke-width'] = + pick(buttonTheme['stroke-width'], 0); + } + rangeSelector.buttonOptions.forEach(function (rangeOptions, i) { + buttons[i] = renderer + .button(rangeOptions.text, 0, 0, function (e) { + // extract events from button object and call + var buttonEvents = (rangeOptions.events && + rangeOptions.events.click), callDefaultEvent; + if (buttonEvents) { + callDefaultEvent = + buttonEvents.call(rangeOptions, e); + } + if (callDefaultEvent !== false) { + rangeSelector.clickButton(i); + } + rangeSelector.isActive = true; + }, buttonTheme, states && states.hover, states && states.select, states && states.disabled) + .attr({ + 'text-align': 'center' + }) + .add(buttonGroup); + }); + // first create a wrapper outside the container in order to make + // the inputs work and make export correct + if (inputEnabled !== false) { + rangeSelector.div = div = createElement('div', null, { + position: 'relative', + height: 0, + zIndex: inputsZIndex + }); + container.parentNode.insertBefore(div, container); + // Create the group to keep the inputs + rangeSelector.inputGroup = inputGroup = + renderer.g('input-group').add(group); + inputGroup.offset = 0; + rangeSelector.drawInput('min'); + rangeSelector.drawInput('max'); + } + } + // #8769, allow dynamically updating margins + rangeSelector.zoomText[verb]({ + x: pick(plotLeft + buttonPosition.x, plotLeft) + }); + // button start position + buttonLeft = pick(plotLeft + buttonPosition.x, plotLeft) + + rangeSelector.zoomText.getBBox().width + 5; + rangeSelector.buttonOptions.forEach(function (rangeOptions, i) { + buttons[i][verb]({ x: buttonLeft }); + // increase button position for the next button + buttonLeft += buttons[i].width + pick(options.buttonSpacing, 5); + }); + plotLeft = chart.plotLeft - chart.spacing[3]; + rangeSelector.updateButtonStates(); + // detect collisiton with exporting + if (navButtonOptions && + this.titleCollision(chart) && + verticalAlign === 'top' && + buttonPosition.align === 'right' && ((buttonPosition.y + + buttonGroup.getBBox().height - 12) < + ((navButtonOptions.y || 0) + + navButtonOptions.height))) { + exportingX = -40; + } + translateX = buttonPosition.x - chart.spacing[3]; + if (buttonPosition.align === 'right') { + translateX += exportingX - plotLeft; // (#13014) + } + else if (buttonPosition.align === 'center') { + translateX -= plotLeft / 2; + } + // align button group + buttonGroup.align({ + y: buttonPosition.y, + width: buttonGroup.getBBox().width, + align: buttonPosition.align, + x: translateX + }, true, chart.spacingBox); + // skip animation + rangeSelector.group.placed = animate; + rangeSelector.buttonGroup.placed = animate; + if (inputEnabled !== false) { + var inputGroupX, inputGroupWidth, buttonGroupX, buttonGroupWidth; + // detect collision with exporting + if (navButtonOptions && + this.titleCollision(chart) && + verticalAlign === 'top' && + inputPosition.align === 'right' && ((inputPosition.y - + inputGroup.getBBox().height - 12) < + ((navButtonOptions.y || 0) + + navButtonOptions.height + + chart.spacing[0]))) { + exportingX = -40; + } + else { + exportingX = 0; + } + if (inputPosition.align === 'left') { + translateX = plotLeft; + } + else if (inputPosition.align === 'right') { + translateX = -Math.max(chart.axisOffset[1], -exportingX); + } + // Update the alignment to the updated spacing box + inputGroup.align({ + y: inputPosition.y, + width: inputGroup.getBBox().width, + align: inputPosition.align, + // fix wrong getBBox() value on right align + x: inputPosition.x + translateX - 2 + }, true, chart.spacingBox); + // detect collision + inputGroupX = (inputGroup.alignAttr.translateX + + inputGroup.alignOptions.x - + exportingX + + // getBBox for detecing left margin + inputGroup.getBBox().x + + // 2px padding to not overlap input and label + 2); + inputGroupWidth = inputGroup.alignOptions.width; + buttonGroupX = buttonGroup.alignAttr.translateX + + buttonGroup.getBBox().x; + // 20 is minimal spacing between elements + buttonGroupWidth = buttonGroup.getBBox().width + 20; + if ((inputPosition.align === + buttonPosition.align) || ((buttonGroupX + buttonGroupWidth > inputGroupX) && + (inputGroupX + inputGroupWidth > buttonGroupX) && + (buttonPositionY < + (inputPositionY + + inputGroup.getBBox().height)))) { + inputGroup.attr({ + translateX: inputGroup.alignAttr.translateX + + (chart.axisOffset[1] >= -exportingX ? 0 : -exportingX), + translateY: inputGroup.alignAttr.translateY + + buttonGroup.getBBox().height + 10 + }); + } + // Set or reset the input values + rangeSelector.setInputValue('min', min); + rangeSelector.setInputValue('max', max); + // skip animation + rangeSelector.inputGroup.placed = animate; + } + // vertical align + rangeSelector.group.align({ + verticalAlign: verticalAlign + }, true, chart.spacingBox); + // set position + groupHeight = + rangeSelector.group.getBBox().height + 20; // # 20 padding + alignTranslateY = + rangeSelector.group.alignAttr.translateY; + // calculate bottom position + if (verticalAlign === 'bottom') { + legendHeight = (legendOptions && + legendOptions.verticalAlign === 'bottom' && + legendOptions.enabled && + !legendOptions.floating ? + legend.legendHeight + pick(legendOptions.margin, 10) : + 0); + groupHeight = groupHeight + legendHeight - 20; + translateY = (alignTranslateY - + groupHeight - + (floating ? 0 : options.y) - + (chart.titleOffset ? chart.titleOffset[2] : 0) - + 10 // 10 spacing + ); + } + if (verticalAlign === 'top') { + if (floating) { + translateY = 0; + } + if (chart.titleOffset && chart.titleOffset[0]) { + translateY = chart.titleOffset[0]; + } + translateY += ((chart.margin[0] - chart.spacing[0]) || 0); + } + else if (verticalAlign === 'middle') { + if (inputPositionY === buttonPositionY) { + if (inputPositionY < 0) { + translateY = alignTranslateY + minPosition; + } + else { + translateY = alignTranslateY; + } + } + else if (inputPositionY || buttonPositionY) { + if (inputPositionY < 0 || + buttonPositionY < 0) { + translateY -= Math.min(inputPositionY, buttonPositionY); + } + else { + translateY = + alignTranslateY - groupHeight + minPosition; + } + } + } + rangeSelector.group.translate(options.x, options.y + Math.floor(translateY)); + // translate HTML inputs + if (inputEnabled !== false) { + rangeSelector.minInput.style.marginTop = + rangeSelector.group.translateY + 'px'; + rangeSelector.maxInput.style.marginTop = + rangeSelector.group.translateY + 'px'; + } + rangeSelector.rendered = true; + }, + /** + * Extracts height of range selector + * + * @private + * @function Highcharts.RangeSelector#getHeight + * @return {number} + * Returns rangeSelector height + */ + getHeight: function () { + var rangeSelector = this, options = rangeSelector.options, rangeSelectorGroup = rangeSelector.group, inputPosition = options.inputPosition, buttonPosition = options.buttonPosition, yPosition = options.y, buttonPositionY = buttonPosition.y, inputPositionY = inputPosition.y, rangeSelectorHeight = 0, minPosition; + if (options.height) { + return options.height; + } + rangeSelectorHeight = rangeSelectorGroup ? + // 13px to keep back compatibility + (rangeSelectorGroup.getBBox(true).height) + 13 + + yPosition : + 0; + minPosition = Math.min(inputPositionY, buttonPositionY); + if ((inputPositionY < 0 && buttonPositionY < 0) || + (inputPositionY > 0 && buttonPositionY > 0)) { + rangeSelectorHeight += Math.abs(minPosition); + } + return rangeSelectorHeight; + }, + /** + * Detect collision with title or subtitle + * + * @private + * @function Highcharts.RangeSelector#titleCollision + * + * @param {Highcharts.Chart} chart + * + * @return {boolean} + * Returns collision status + */ + titleCollision: function (chart) { + return !(chart.options.title.text || + chart.options.subtitle.text); + }, + /** + * Update the range selector with new options + * + * @private + * @function Highcharts.RangeSelector#update + * @param {Highcharts.RangeSelectorOptions} options + * @return {void} + */ + update: function (options) { + var chart = this.chart; + merge(true, chart.options.rangeSelector, options); + this.destroy(); + this.init(chart); + chart.rangeSelector.render(); + }, + /** + * Destroys allocated elements. + * + * @private + * @function Highcharts.RangeSelector#destroy + */ + destroy: function () { + var rSelector = this, minInput = rSelector.minInput, maxInput = rSelector.maxInput; + rSelector.unMouseDown(); + rSelector.unResize(); + // Destroy elements in collections + destroyObjectProperties(rSelector.buttons); + // Clear input element events + if (minInput) { + minInput.onfocus = minInput.onblur = minInput.onchange = null; + } + if (maxInput) { + maxInput.onfocus = maxInput.onblur = maxInput.onchange = null; + } + // Destroy HTML and SVG elements + objectEach(rSelector, function (val, key) { + if (val && key !== 'chart') { + if (val.destroy) { + // SVGElement + val.destroy(); + } + else if (val.nodeType) { + // HTML element + discardElement(this[key]); + } + } + if (val !== RangeSelector.prototype[key]) { + rSelector[key] = null; + } + }, this); + } + }; + /** + * Get the axis min value based on the range option and the current max. For + * stock charts this is extended via the {@link RangeSelector} so that if the + * selected range is a multiple of months or years, it is compensated for + * various month lengths. + * + * @private + * @function Highcharts.Axis#minFromRange + * @return {number|undefined} + * The new minimum value. + */ + Axis.prototype.minFromRange = function () { + var rangeOptions = this.range, type = rangeOptions.type, min, max = this.max, dataMin, range, time = this.chart.time, + // Get the true range from a start date + getTrueRange = function (base, count) { + var timeName = type === 'year' ? 'FullYear' : 'Month'; + var date = new time.Date(base); + var basePeriod = time.get(timeName, date); + time.set(timeName, date, basePeriod + count); + if (basePeriod === time.get(timeName, date)) { + time.set('Date', date, 0); // #6537 + } + return date.getTime() - base; + }; + if (isNumber(rangeOptions)) { + min = max - rangeOptions; + range = rangeOptions; + } + else { + min = max + getTrueRange(max, -rangeOptions.count); + // Let the fixedRange reflect initial settings (#5930) + if (this.chart) { + this.chart.fixedRange = max - min; + } + } + dataMin = pick(this.dataMin, Number.MIN_VALUE); + if (!isNumber(min)) { + min = dataMin; + } + if (min <= dataMin) { + min = dataMin; + if (typeof range === 'undefined') { // #4501 + range = getTrueRange(min, rangeOptions.count); + } + this.newMax = Math.min(min + range, this.dataMax); + } + if (!isNumber(max)) { + min = void 0; + } + return min; + }; + if (!H.RangeSelector) { + // Initialize rangeselector for stock charts + addEvent(Chart, 'afterGetContainer', function () { + if (this.options.rangeSelector.enabled) { + this.rangeSelector = new RangeSelector(this); + } + }); + addEvent(Chart, 'beforeRender', function () { + var chart = this, axes = chart.axes, rangeSelector = chart.rangeSelector, verticalAlign; + if (rangeSelector) { + if (isNumber(rangeSelector.deferredYTDClick)) { + rangeSelector.clickButton(rangeSelector.deferredYTDClick); + delete rangeSelector.deferredYTDClick; + } + axes.forEach(function (axis) { + axis.updateNames(); + axis.setScale(); + }); + chart.getAxisMargins(); + rangeSelector.render(); + verticalAlign = rangeSelector.options.verticalAlign; + if (!rangeSelector.options.floating) { + if (verticalAlign === 'bottom') { + this.extraBottomMargin = true; + } + else if (verticalAlign !== 'middle') { + this.extraTopMargin = true; + } + } + } + }); + addEvent(Chart, 'update', function (e) { + var chart = this, options = e.options, optionsRangeSelector = options.rangeSelector, rangeSelector = chart.rangeSelector, verticalAlign, extraBottomMarginWas = this.extraBottomMargin, extraTopMarginWas = this.extraTopMargin; + if (optionsRangeSelector && + optionsRangeSelector.enabled && + !defined(rangeSelector)) { + this.options.rangeSelector.enabled = true; + this.rangeSelector = new RangeSelector(this); + } + this.extraBottomMargin = false; + this.extraTopMargin = false; + if (rangeSelector) { + rangeSelector.render(); + verticalAlign = (optionsRangeSelector && + optionsRangeSelector.verticalAlign) || (rangeSelector.options && rangeSelector.options.verticalAlign); + if (!rangeSelector.options.floating) { + if (verticalAlign === 'bottom') { + this.extraBottomMargin = true; + } + else if (verticalAlign !== 'middle') { + this.extraTopMargin = true; + } + } + if (this.extraBottomMargin !== extraBottomMarginWas || + this.extraTopMargin !== extraTopMarginWas) { + this.isDirtyBox = true; + } + } + }); + addEvent(Chart, 'render', function () { + var chart = this, rangeSelector = chart.rangeSelector, verticalAlign; + if (rangeSelector && !rangeSelector.options.floating) { + rangeSelector.render(); + verticalAlign = rangeSelector.options.verticalAlign; + if (verticalAlign === 'bottom') { + this.extraBottomMargin = true; + } + else if (verticalAlign !== 'middle') { + this.extraTopMargin = true; + } + } + }); + addEvent(Chart, 'getMargins', function () { + var rangeSelector = this.rangeSelector, rangeSelectorHeight; + if (rangeSelector) { + rangeSelectorHeight = rangeSelector.getHeight(); + if (this.extraTopMargin) { + this.plotTop += rangeSelectorHeight; + } + if (this.extraBottomMargin) { + this.marginBottom += rangeSelectorHeight; + } + } + }); + Chart.prototype.callbacks.push(function (chart) { + var extremes, rangeSelector = chart.rangeSelector, unbindRender, unbindSetExtremes, legend, alignTo, verticalAlign; + /** + * @private + */ + function renderRangeSelector() { + extremes = chart.xAxis[0].getExtremes(); + legend = chart.legend; + verticalAlign = rangeSelector === null || rangeSelector === void 0 ? void 0 : rangeSelector.options.verticalAlign; + if (isNumber(extremes.min)) { + rangeSelector.render(extremes.min, extremes.max); + } + // Re-align the legend so that it's below the rangeselector + if (rangeSelector && legend.display && + verticalAlign === 'top' && + verticalAlign === legend.options.verticalAlign) { + // Create a new alignment box for the legend. + alignTo = merge(chart.spacingBox); + if (legend.options.layout === 'vertical') { + alignTo.y = chart.plotTop; + } + else { + alignTo.y += rangeSelector.getHeight(); + } + legend.group.placed = false; // Don't animate the alignment. + legend.align(alignTo); + } + } + if (rangeSelector) { + // redraw the scroller on setExtremes + unbindSetExtremes = addEvent(chart.xAxis[0], 'afterSetExtremes', function (e) { + rangeSelector.render(e.min, e.max); + }); + // redraw the scroller chart resize + unbindRender = addEvent(chart, 'redraw', renderRangeSelector); + // do it now + renderRangeSelector(); + } + // Remove resize/afterSetExtremes at chart destroy + addEvent(chart, 'destroy', function destroyEvents() { + if (rangeSelector) { + unbindRender(); + unbindSetExtremes(); + } + }); + }); + H.RangeSelector = RangeSelector; + } + + }); + _registerModule(_modules, 'parts/NavigatorAxis.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var isTouchDevice = H.isTouchDevice; + var addEvent = U.addEvent, correctFloat = U.correctFloat, defined = U.defined, isNumber = U.isNumber, pick = U.pick; + /* eslint-disable valid-jsdoc */ + /** + * @private + * @class + */ + var NavigatorAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function NavigatorAxisAdditions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * @private + */ + NavigatorAxisAdditions.prototype.destroy = function () { + this.axis = void 0; + }; + /** + * Add logic to normalize the zoomed range in order to preserve the pressed + * state of range selector buttons + * + * @private + * @function Highcharts.Axis#toFixedRange + * @param {number} [pxMin] + * @param {number} [pxMax] + * @param {number} [fixedMin] + * @param {number} [fixedMax] + * @return {*} + */ + NavigatorAxisAdditions.prototype.toFixedRange = function (pxMin, pxMax, fixedMin, fixedMax) { + var navigator = this; + var axis = navigator.axis; + var chart = axis.chart; + var fixedRange = chart && chart.fixedRange, halfPointRange = (axis.pointRange || 0) / 2, newMin = pick(fixedMin, axis.translate(pxMin, true, !axis.horiz)), newMax = pick(fixedMax, axis.translate(pxMax, true, !axis.horiz)), changeRatio = fixedRange && (newMax - newMin) / fixedRange; + // Add/remove half point range to/from the extremes (#1172) + if (!defined(fixedMin)) { + newMin = correctFloat(newMin + halfPointRange); + } + if (!defined(fixedMax)) { + newMax = correctFloat(newMax - halfPointRange); + } + // If the difference between the fixed range and the actual requested + // range is too great, the user is dragging across an ordinal gap, and + // we need to release the range selector button. + if (changeRatio > 0.7 && changeRatio < 1.3) { + if (fixedMax) { + newMin = newMax - fixedRange; + } + else { + newMax = newMin + fixedRange; + } + } + if (!isNumber(newMin) || !isNumber(newMax)) { // #1195, #7411 + newMin = newMax = void 0; + } + return { + min: newMin, + max: newMax + }; + }; + return NavigatorAxisAdditions; + }()); + /** + * @private + * @class + */ + var NavigatorAxis = /** @class */ (function () { + function NavigatorAxis() { + } + /* * + * + * Static Functions + * + * */ + /** + * @private + */ + NavigatorAxis.compose = function (AxisClass) { + AxisClass.keepProps.push('navigatorAxis'); + /* eslint-disable no-invalid-this */ + addEvent(AxisClass, 'init', function () { + var axis = this; + if (!axis.navigatorAxis) { + axis.navigatorAxis = new NavigatorAxisAdditions(axis); + } + }); + // For Stock charts, override selection zooming with some special + // features because X axis zooming is already allowed by the Navigator + // and Range selector. + addEvent(AxisClass, 'zoom', function (e) { + var axis = this; + var chart = axis.chart; + var chartOptions = chart.options; + var navigator = chartOptions.navigator; + var navigatorAxis = axis.navigatorAxis; + var pinchType = chartOptions.chart.pinchType; + var rangeSelector = chartOptions.rangeSelector; + var zoomType = chartOptions.chart.zoomType; + var previousZoom; + if (axis.isXAxis && ((navigator && navigator.enabled) || + (rangeSelector && rangeSelector.enabled))) { + // For y only zooming, ignore the X axis completely + if (zoomType === 'y') { + e.zoomed = false; + // For xy zooming, record the state of the zoom before zoom + // selection, then when the reset button is pressed, revert to + // this state. This should apply only if the chart is + // initialized with a range (#6612), otherwise zoom all the way + // out. + } + else if (((!isTouchDevice && zoomType === 'xy') || + (isTouchDevice && pinchType === 'xy')) && + axis.options.range) { + previousZoom = navigatorAxis.previousZoom; + if (defined(e.newMin)) { + navigatorAxis.previousZoom = [axis.min, axis.max]; + } + else if (previousZoom) { + e.newMin = previousZoom[0]; + e.newMax = previousZoom[1]; + navigatorAxis.previousZoom = void 0; + } + } + } + if (typeof e.zoomed !== 'undefined') { + e.preventDefault(); + } + }); + /* eslint-enable no-invalid-this */ + }; + /* * + * + * Static Properties + * + * */ + /** + * @private + */ + NavigatorAxis.AdditionsClass = NavigatorAxisAdditions; + return NavigatorAxis; + }()); + + return NavigatorAxis; + }); + _registerModule(_modules, 'parts/Navigator.js', [_modules['parts/Axis.js'], _modules['parts/Color.js'], _modules['parts/Globals.js'], _modules['parts/NavigatorAxis.js'], _modules['parts/Scrollbar.js'], _modules['parts/Utilities.js']], function (Axis, Color, H, NavigatorAxis, Scrollbar, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var color = Color.parse; + var addEvent = U.addEvent, clamp = U.clamp, correctFloat = U.correctFloat, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, erase = U.erase, extend = U.extend, find = U.find, isArray = U.isArray, isNumber = U.isNumber, merge = U.merge, pick = U.pick, removeEvent = U.removeEvent, splat = U.splat; + var Chart = H.Chart, defaultOptions = H.defaultOptions, hasTouch = H.hasTouch, isTouchDevice = H.isTouchDevice, Series = H.Series, seriesTypes = H.seriesTypes, defaultSeriesType, + // Finding the min or max of a set of variables where we don't know if they + // are defined, is a pattern that is repeated several places in Highcharts. + // Consider making this a global utility method. + numExt = function (extreme) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + var numbers = [].filter.call(args, isNumber); + if (numbers.length) { + return Math[extreme].apply(0, numbers); + } + }; + defaultSeriesType = typeof seriesTypes.areaspline === 'undefined' ? + 'line' : + 'areaspline'; + extend(defaultOptions, { + /** + * Maximum range which can be set using the navigator's handles. + * Opposite of [xAxis.minRange](#xAxis.minRange). + * + * @sample {highstock} stock/navigator/maxrange/ + * Defined max and min range + * + * @type {number} + * @since 6.0.0 + * @product highstock gantt + * @apioption xAxis.maxRange + */ + /** + * The navigator is a small series below the main series, displaying + * a view of the entire data set. It provides tools to zoom in and + * out on parts of the data as well as panning across the dataset. + * + * @product highstock gantt + * @optionparent navigator + */ + navigator: { + /** + * Whether the navigator and scrollbar should adapt to updated data + * in the base X axis. When loading data async, as in the demo below, + * this should be `false`. Otherwise new data will trigger navigator + * redraw, which will cause unwanted looping. In the demo below, the + * data in the navigator is set only once. On navigating, only the main + * chart content is updated. + * + * @sample {highstock} stock/demo/lazy-loading/ + * Set to false with async data loading + * + * @type {boolean} + * @default true + * @apioption navigator.adaptToUpdatedData + */ + /** + * An integer identifying the index to use for the base series, or a + * string representing the id of the series. + * + * **Note**: As of Highcharts 5.0, this is now a deprecated option. + * Prefer [series.showInNavigator](#plotOptions.series.showInNavigator). + * + * @see [series.showInNavigator](#plotOptions.series.showInNavigator) + * + * @deprecated + * @type {number|string} + * @default 0 + * @apioption navigator.baseSeries + */ + /** + * Enable or disable the navigator. + * + * @sample {highstock} stock/navigator/enabled/ + * Disable the navigator + * + * @type {boolean} + * @default true + * @apioption navigator.enabled + */ + /** + * When the chart is inverted, whether to draw the navigator on the + * opposite side. + * + * @type {boolean} + * @default false + * @since 5.0.8 + * @apioption navigator.opposite + */ + /** + * The height of the navigator. + * + * @sample {highstock} stock/navigator/height/ + * A higher navigator + */ + height: 40, + /** + * The distance from the nearest element, the X axis or X axis labels. + * + * @sample {highstock} stock/navigator/margin/ + * A margin of 2 draws the navigator closer to the X axis labels + */ + margin: 25, + /** + * Whether the mask should be inside the range marking the zoomed + * range, or outside. In Highstock 1.x it was always `false`. + * + * @sample {highstock} stock/navigator/maskinside-false/ + * False, mask outside + * + * @since 2.0 + */ + maskInside: true, + /** + * Options for the handles for dragging the zoomed area. + * + * @sample {highstock} stock/navigator/handles/ + * Colored handles + */ + handles: { + /** + * Width for handles. + * + * @sample {highstock} stock/navigator/styled-handles/ + * Styled handles + * + * @since 6.0.0 + */ + width: 7, + /** + * Height for handles. + * + * @sample {highstock} stock/navigator/styled-handles/ + * Styled handles + * + * @since 6.0.0 + */ + height: 15, + /** + * Array to define shapes of handles. 0-index for left, 1-index for + * right. + * + * Additionally, the URL to a graphic can be given on this form: + * `url(graphic.png)`. Note that for the image to be applied to + * exported charts, its URL needs to be accessible by the export + * server. + * + * Custom callbacks for symbol path generation can also be added to + * `Highcharts.SVGRenderer.prototype.symbols`. The callback is then + * used by its method name, as shown in the demo. + * + * @sample {highstock} stock/navigator/styled-handles/ + * Styled handles + * + * @type {Array} + * @default ["navigator-handle", "navigator-handle"] + * @since 6.0.0 + */ + symbols: ['navigator-handle', 'navigator-handle'], + /** + * Allows to enable/disable handles. + * + * @since 6.0.0 + */ + enabled: true, + /** + * The width for the handle border and the stripes inside. + * + * @sample {highstock} stock/navigator/styled-handles/ + * Styled handles + * + * @since 6.0.0 + * @apioption navigator.handles.lineWidth + */ + lineWidth: 1, + /** + * The fill for the handle. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + backgroundColor: '#f2f2f2', + /** + * The stroke for the handle border and the stripes inside. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + borderColor: '#999999' + }, + /** + * The color of the mask covering the areas of the navigator series + * that are currently not visible in the main series. The default + * color is bluish with an opacity of 0.3 to see the series below. + * + * @see In styled mode, the mask is styled with the + * `.highcharts-navigator-mask` and + * `.highcharts-navigator-mask-inside` classes. + * + * @sample {highstock} stock/navigator/maskfill/ + * Blue, semi transparent mask + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default rgba(102,133,194,0.3) + */ + maskFill: color('#6685c2').setOpacity(0.3).get(), + /** + * The color of the line marking the currently zoomed area in the + * navigator. + * + * @sample {highstock} stock/navigator/outline/ + * 2px blue outline + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #cccccc + */ + outlineColor: '#cccccc', + /** + * The width of the line marking the currently zoomed area in the + * navigator. + * + * @see In styled mode, the outline stroke width is set with the + * `.highcharts-navigator-outline` class. + * + * @sample {highstock} stock/navigator/outline/ + * 2px blue outline + * + * @type {number} + */ + outlineWidth: 1, + /** + * Options for the navigator series. Available options are the same + * as any series, documented at [plotOptions](#plotOptions.series) + * and [series](#series). + * + * Unless data is explicitly defined on navigator.series, the data + * is borrowed from the first series in the chart. + * + * Default series options for the navigator series are: + * ```js + * series: { + * type: 'areaspline', + * fillOpacity: 0.05, + * dataGrouping: { + * smoothed: true + * }, + * lineWidth: 1, + * marker: { + * enabled: false + * } + * } + * ``` + * + * @see In styled mode, the navigator series is styled with the + * `.highcharts-navigator-series` class. + * + * @sample {highstock} stock/navigator/series-data/ + * Using a separate data set for the navigator + * @sample {highstock} stock/navigator/series/ + * A green navigator series + * + * @type {*|Array<*>|Highcharts.SeriesOptionsType|Array} + */ + series: { + /** + * The type of the navigator series. Defaults to `areaspline` if + * defined, otherwise `line`. + * + * Heads up: + * In column-type navigator, zooming is limited to at least one + * point with its `pointRange`. + * + * @sample {highstock} stock/navigator/column/ + * Column type navigator + * + * @type {string} + * @default areaspline + */ + type: defaultSeriesType, + /** + * The fill opacity of the navigator series. + */ + fillOpacity: 0.05, + /** + * The pixel line width of the navigator series. + */ + lineWidth: 1, + /** + * @ignore-option + */ + compare: null, + /** + * Unless data is explicitly defined, the data is borrowed from the + * first series in the chart. + * + * @type {Array|object|null>} + * @product highstock + * @apioption navigator.series.data + */ + /** + * Data grouping options for the navigator series. + * + * @extends plotOptions.series.dataGrouping + */ + dataGrouping: { + approximation: 'average', + enabled: true, + groupPixelWidth: 2, + smoothed: true, + // Day and week differs from plotOptions.series.dataGrouping + units: [ + ['millisecond', [1, 2, 5, 10, 20, 25, 50, 100, 200, 500]], + ['second', [1, 2, 5, 10, 15, 30]], + ['minute', [1, 2, 5, 10, 15, 30]], + ['hour', [1, 2, 3, 4, 6, 8, 12]], + ['day', [1, 2, 3, 4]], + ['week', [1, 2, 3]], + ['month', [1, 3, 6]], + ['year', null] + ] + }, + /** + * Data label options for the navigator series. Data labels are + * disabled by default on the navigator series. + * + * @extends plotOptions.series.dataLabels + */ + dataLabels: { + enabled: false, + zIndex: 2 // #1839 + }, + id: 'highcharts-navigator-series', + className: 'highcharts-navigator-series', + /** + * Sets the fill color of the navigator series. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption navigator.series.color + */ + /** + * Line color for the navigator series. Allows setting the color + * while disallowing the default candlestick setting. + * + * @type {Highcharts.ColorString|null} + */ + lineColor: null, + marker: { + enabled: false + }, + /** + * Since Highstock v8, default value is the same as default + * `pointRange` defined for a specific type (e.g. `null` for + * column type). + * + * In Highstock version < 8, defaults to 0. + * + * @extends plotOptions.series.pointRange + * @type {number|null} + * @apioption navigator.series.pointRange + */ + /** + * The threshold option. Setting it to 0 will make the default + * navigator area series draw its area from the 0 value and up. + * + * @type {number|null} + */ + threshold: null + }, + /** + * Options for the navigator X axis. Default series options for the + * navigator xAxis are: + * ```js + * xAxis: { + * tickWidth: 0, + * lineWidth: 0, + * gridLineWidth: 1, + * tickPixelInterval: 200, + * labels: { + * align: 'left', + * style: { + * color: '#888' + * }, + * x: 3, + * y: -4 + * } + * } + * ``` + * + * @extends xAxis + * @excluding linkedTo, maxZoom, minRange, opposite, range, scrollbar, + * showEmpty, maxRange + */ + xAxis: { + /** + * Additional range on the right side of the xAxis. Works similar to + * xAxis.maxPadding, but value is set in milliseconds. + * Can be set for both, main xAxis and navigator's xAxis. + * + * @since 6.0.0 + */ + overscroll: 0, + className: 'highcharts-navigator-xaxis', + tickLength: 0, + lineWidth: 0, + gridLineColor: '#e6e6e6', + gridLineWidth: 1, + tickPixelInterval: 200, + labels: { + align: 'left', + /** + * @type {Highcharts.CSSObject} + */ + style: { + /** @ignore */ + color: '#999999' + }, + x: 3, + y: -4 + }, + crosshair: false + }, + /** + * Options for the navigator Y axis. Default series options for the + * navigator yAxis are: + * ```js + * yAxis: { + * gridLineWidth: 0, + * startOnTick: false, + * endOnTick: false, + * minPadding: 0.1, + * maxPadding: 0.1, + * labels: { + * enabled: false + * }, + * title: { + * text: null + * }, + * tickWidth: 0 + * } + * ``` + * + * @extends yAxis + * @excluding height, linkedTo, maxZoom, minRange, ordinal, range, + * showEmpty, scrollbar, top, units, maxRange, minLength, + * maxLength, resize + */ + yAxis: { + className: 'highcharts-navigator-yaxis', + gridLineWidth: 0, + startOnTick: false, + endOnTick: false, + minPadding: 0.1, + maxPadding: 0.1, + labels: { + enabled: false + }, + crosshair: false, + title: { + text: null + }, + tickLength: 0, + tickWidth: 0 + } + } + }); + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Draw one of the handles on the side of the zoomed range in the navigator + * + * @private + * @function Highcharts.Renderer#symbols.navigator-handle + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @param {Highcharts.NavigatorHandlesOptions} options + * @return {Highcharts.SVGPathArray} + * Path to be used in a handle + */ + H.Renderer.prototype.symbols['navigator-handle'] = function (x, y, w, h, options) { + var halfWidth = options.width / 2, markerPosition = Math.round(halfWidth / 3) + 0.5, height = options.height || 0; + return [ + ['M', -halfWidth - 1, 0.5], + ['L', halfWidth, 0.5], + ['L', halfWidth, height + 0.5], + ['L', -halfWidth - 1, height + 0.5], + ['L', -halfWidth - 1, 0.5], + ['M', -markerPosition, 4], + ['L', -markerPosition, height - 3], + ['M', markerPosition - 1, 4], + ['L', markerPosition - 1, height - 3] + ]; + }; + /** + * The Navigator class + * + * @private + * @class + * @name Highcharts.Navigator + * + * @param {Highcharts.Chart} chart + * Chart object + */ + var Navigator = /** @class */ (function () { + function Navigator(chart) { + this.baseSeries = void 0; + this.chart = void 0; + this.handles = void 0; + this.height = void 0; + this.left = void 0; + this.navigatorEnabled = void 0; + this.navigatorGroup = void 0; + this.navigatorOptions = void 0; + this.navigatorSeries = void 0; + this.navigatorSize = void 0; + this.opposite = void 0; + this.outline = void 0; + this.outlineHeight = void 0; + this.range = void 0; + this.rendered = void 0; + this.shades = void 0; + this.size = void 0; + this.top = void 0; + this.xAxis = void 0; + this.yAxis = void 0; + this.zoomedMax = void 0; + this.zoomedMin = void 0; + this.init(chart); + } + /** + * Draw one of the handles on the side of the zoomed range in the navigator + * + * @private + * @function Highcharts.Navigator#drawHandle + * + * @param {number} x + * The x center for the handle + * + * @param {number} index + * 0 for left and 1 for right + * + * @param {boolean|undefined} inverted + * flag for chart.inverted + * + * @param {string} verb + * use 'animate' or 'attr' + */ + Navigator.prototype.drawHandle = function (x, index, inverted, verb) { + var navigator = this, height = navigator.navigatorOptions.handles.height; + // Place it + navigator.handles[index][verb](inverted ? { + translateX: Math.round(navigator.left + navigator.height / 2), + translateY: Math.round(navigator.top + parseInt(x, 10) + 0.5 - height) + } : { + translateX: Math.round(navigator.left + parseInt(x, 10)), + translateY: Math.round(navigator.top + navigator.height / 2 - height / 2 - 1) + }); + }; + /** + * Render outline around the zoomed range + * + * @private + * @function Highcharts.Navigator#drawOutline + * + * @param {number} zoomedMin + * in pixels position where zoomed range starts + * + * @param {number} zoomedMax + * in pixels position where zoomed range ends + * + * @param {boolean|undefined} inverted + * flag if chart is inverted + * + * @param {string} verb + * use 'animate' or 'attr' + */ + Navigator.prototype.drawOutline = function (zoomedMin, zoomedMax, inverted, verb) { + var navigator = this, maskInside = navigator.navigatorOptions.maskInside, outlineWidth = navigator.outline.strokeWidth(), halfOutline = outlineWidth / 2, outlineCorrection = (outlineWidth % 2) / 2, // #5800 + outlineHeight = navigator.outlineHeight, scrollbarHeight = navigator.scrollbarHeight || 0, navigatorSize = navigator.size, left = navigator.left - scrollbarHeight, navigatorTop = navigator.top, verticalMin, path; + if (inverted) { + left -= halfOutline; + verticalMin = navigatorTop + zoomedMax + outlineCorrection; + zoomedMax = navigatorTop + zoomedMin + outlineCorrection; + path = [ + ['M', left + outlineHeight, navigatorTop - scrollbarHeight - outlineCorrection], + ['L', left + outlineHeight, verticalMin], + ['L', left, verticalMin], + ['L', left, zoomedMax], + ['L', left + outlineHeight, zoomedMax], + ['L', left + outlineHeight, navigatorTop + navigatorSize + scrollbarHeight] + ]; + if (maskInside) { + path.push(['M', left + outlineHeight, verticalMin - halfOutline], // upper left of zoomed range + ['L', left + outlineHeight, zoomedMax + halfOutline] // upper right of z.r. + ); + } + } + else { + zoomedMin += left + scrollbarHeight - outlineCorrection; + zoomedMax += left + scrollbarHeight - outlineCorrection; + navigatorTop += halfOutline; + path = [ + ['M', left, navigatorTop], + ['L', zoomedMin, navigatorTop], + ['L', zoomedMin, navigatorTop + outlineHeight], + ['L', zoomedMax, navigatorTop + outlineHeight], + ['L', zoomedMax, navigatorTop], + ['L', left + navigatorSize + scrollbarHeight * 2, navigatorTop] // right + ]; + if (maskInside) { + path.push(['M', zoomedMin - halfOutline, navigatorTop], // upper left of zoomed range + ['L', zoomedMax + halfOutline, navigatorTop] // upper right of z.r. + ); + } + } + navigator.outline[verb]({ + d: path + }); + }; + /** + * Render outline around the zoomed range + * + * @private + * @function Highcharts.Navigator#drawMasks + * + * @param {number} zoomedMin + * in pixels position where zoomed range starts + * + * @param {number} zoomedMax + * in pixels position where zoomed range ends + * + * @param {boolean|undefined} inverted + * flag if chart is inverted + * + * @param {string} verb + * use 'animate' or 'attr' + */ + Navigator.prototype.drawMasks = function (zoomedMin, zoomedMax, inverted, verb) { + var navigator = this, left = navigator.left, top = navigator.top, navigatorHeight = navigator.height, height, width, x, y; + // Determine rectangle position & size + // According to (non)inverted position: + if (inverted) { + x = [left, left, left]; + y = [top, top + zoomedMin, top + zoomedMax]; + width = [navigatorHeight, navigatorHeight, navigatorHeight]; + height = [ + zoomedMin, + zoomedMax - zoomedMin, + navigator.size - zoomedMax + ]; + } + else { + x = [left, left + zoomedMin, left + zoomedMax]; + y = [top, top, top]; + width = [ + zoomedMin, + zoomedMax - zoomedMin, + navigator.size - zoomedMax + ]; + height = [navigatorHeight, navigatorHeight, navigatorHeight]; + } + navigator.shades.forEach(function (shade, i) { + shade[verb]({ + x: x[i], + y: y[i], + width: width[i], + height: height[i] + }); + }); + }; + /** + * Generate DOM elements for a navigator: + * + * - main navigator group + * + * - all shades + * + * - outline + * + * - handles + * + * @private + * @function Highcharts.Navigator#renderElements + */ + Navigator.prototype.renderElements = function () { + var navigator = this, navigatorOptions = navigator.navigatorOptions, maskInside = navigatorOptions.maskInside, chart = navigator.chart, inverted = chart.inverted, renderer = chart.renderer, navigatorGroup, mouseCursor = { + cursor: inverted ? 'ns-resize' : 'ew-resize' + }; + // Create the main navigator group + navigator.navigatorGroup = navigatorGroup = renderer.g('navigator') + .attr({ + zIndex: 8, + visibility: 'hidden' + }) + .add(); + // Create masks, each mask will get events and fill: + [ + !maskInside, + maskInside, + !maskInside + ].forEach(function (hasMask, index) { + navigator.shades[index] = renderer.rect() + .addClass('highcharts-navigator-mask' + + (index === 1 ? '-inside' : '-outside')) + .add(navigatorGroup); + if (!chart.styledMode) { + navigator.shades[index] + .attr({ + fill: hasMask ? + navigatorOptions.maskFill : + 'rgba(0,0,0,0)' + }) + .css((index === 1) && mouseCursor); + } + }); + // Create the outline: + navigator.outline = renderer.path() + .addClass('highcharts-navigator-outline') + .add(navigatorGroup); + if (!chart.styledMode) { + navigator.outline.attr({ + 'stroke-width': navigatorOptions.outlineWidth, + stroke: navigatorOptions.outlineColor + }); + } + // Create the handlers: + if (navigatorOptions.handles.enabled) { + [0, 1].forEach(function (index) { + navigatorOptions.handles.inverted = chart.inverted; + navigator.handles[index] = renderer.symbol(navigatorOptions.handles.symbols[index], -navigatorOptions.handles.width / 2 - 1, 0, navigatorOptions.handles.width, navigatorOptions.handles.height, navigatorOptions.handles); + // zIndex = 6 for right handle, 7 for left. + // Can't be 10, because of the tooltip in inverted chart #2908 + navigator.handles[index].attr({ zIndex: 7 - index }) + .addClass('highcharts-navigator-handle ' + + 'highcharts-navigator-handle-' + + ['left', 'right'][index]).add(navigatorGroup); + if (!chart.styledMode) { + var handlesOptions = navigatorOptions.handles; + navigator.handles[index] + .attr({ + fill: handlesOptions.backgroundColor, + stroke: handlesOptions.borderColor, + 'stroke-width': handlesOptions.lineWidth + }) + .css(mouseCursor); + } + }); + } + }; + /** + * Update navigator + * + * @private + * @function Highcharts.Navigator#update + * + * @param {Highcharts.NavigatorOptions} options + * Options to merge in when updating navigator + */ + Navigator.prototype.update = function (options) { + // Remove references to old navigator series in base series + (this.series || []).forEach(function (series) { + if (series.baseSeries) { + delete series.baseSeries.navigatorSeries; + } + }); + // Destroy and rebuild navigator + this.destroy(); + var chartOptions = this.chart.options; + merge(true, chartOptions.navigator, this.options, options); + this.init(this.chart); + }; + /** + * Render the navigator + * + * @private + * @function Highcharts.Navigator#render + * @param {number} min + * X axis value minimum + * @param {number} max + * X axis value maximum + * @param {number} [pxMin] + * Pixel value minimum + * @param {number} [pxMax] + * Pixel value maximum + * @return {void} + */ + Navigator.prototype.render = function (min, max, pxMin, pxMax) { + var navigator = this, chart = navigator.chart, navigatorWidth, scrollbarLeft, scrollbarTop, scrollbarHeight = navigator.scrollbarHeight, navigatorSize, xAxis = navigator.xAxis, pointRange = xAxis.pointRange || 0, scrollbarXAxis = xAxis.navigatorAxis.fake ? chart.xAxis[0] : xAxis, navigatorEnabled = navigator.navigatorEnabled, zoomedMin, zoomedMax, rendered = navigator.rendered, inverted = chart.inverted, verb, newMin, newMax, currentRange, minRange = chart.xAxis[0].minRange, maxRange = chart.xAxis[0].options.maxRange; + // Don't redraw while moving the handles (#4703). + if (this.hasDragged && !defined(pxMin)) { + return; + } + min = correctFloat(min - pointRange / 2); + max = correctFloat(max + pointRange / 2); + // Don't render the navigator until we have data (#486, #4202, #5172). + if (!isNumber(min) || !isNumber(max)) { + // However, if navigator was already rendered, we may need to resize + // it. For example hidden series, but visible navigator (#6022). + if (rendered) { + pxMin = 0; + pxMax = pick(xAxis.width, scrollbarXAxis.width); + } + else { + return; + } + } + navigator.left = pick(xAxis.left, + // in case of scrollbar only, without navigator + chart.plotLeft + scrollbarHeight + + (inverted ? chart.plotWidth : 0)); + navigator.size = zoomedMax = navigatorSize = pick(xAxis.len, (inverted ? chart.plotHeight : chart.plotWidth) - + 2 * scrollbarHeight); + if (inverted) { + navigatorWidth = scrollbarHeight; + } + else { + navigatorWidth = navigatorSize + 2 * scrollbarHeight; + } + // Get the pixel position of the handles + pxMin = pick(pxMin, xAxis.toPixels(min, true)); + pxMax = pick(pxMax, xAxis.toPixels(max, true)); + // Verify (#1851, #2238) + if (!isNumber(pxMin) || Math.abs(pxMin) === Infinity) { + pxMin = 0; + pxMax = navigatorWidth; + } + // Are we below the minRange? (#2618, #6191) + newMin = xAxis.toValue(pxMin, true); + newMax = xAxis.toValue(pxMax, true); + currentRange = Math.abs(correctFloat(newMax - newMin)); + if (currentRange < minRange) { + if (this.grabbedLeft) { + pxMin = xAxis.toPixels(newMax - minRange - pointRange, true); + } + else if (this.grabbedRight) { + pxMax = xAxis.toPixels(newMin + minRange + pointRange, true); + } + } + else if (defined(maxRange) && + correctFloat(currentRange - pointRange) > maxRange) { + if (this.grabbedLeft) { + pxMin = xAxis.toPixels(newMax - maxRange - pointRange, true); + } + else if (this.grabbedRight) { + pxMax = xAxis.toPixels(newMin + maxRange + pointRange, true); + } + } + // Handles are allowed to cross, but never exceed the plot area + navigator.zoomedMax = clamp(Math.max(pxMin, pxMax), 0, zoomedMax); + navigator.zoomedMin = clamp(navigator.fixedWidth ? + navigator.zoomedMax - navigator.fixedWidth : + Math.min(pxMin, pxMax), 0, zoomedMax); + navigator.range = navigator.zoomedMax - navigator.zoomedMin; + zoomedMax = Math.round(navigator.zoomedMax); + zoomedMin = Math.round(navigator.zoomedMin); + if (navigatorEnabled) { + navigator.navigatorGroup.attr({ + visibility: 'visible' + }); + // Place elements + verb = rendered && !navigator.hasDragged ? 'animate' : 'attr'; + navigator.drawMasks(zoomedMin, zoomedMax, inverted, verb); + navigator.drawOutline(zoomedMin, zoomedMax, inverted, verb); + if (navigator.navigatorOptions.handles.enabled) { + navigator.drawHandle(zoomedMin, 0, inverted, verb); + navigator.drawHandle(zoomedMax, 1, inverted, verb); + } + } + if (navigator.scrollbar) { + if (inverted) { + scrollbarTop = navigator.top - scrollbarHeight; + scrollbarLeft = navigator.left - scrollbarHeight + + (navigatorEnabled || !scrollbarXAxis.opposite ? 0 : + // Multiple axes has offsets: + (scrollbarXAxis.titleOffset || 0) + + // Self margin from the axis.title + scrollbarXAxis.axisTitleMargin); + scrollbarHeight = navigatorSize + 2 * scrollbarHeight; + } + else { + scrollbarTop = navigator.top + (navigatorEnabled ? + navigator.height : + -scrollbarHeight); + scrollbarLeft = navigator.left - scrollbarHeight; + } + // Reposition scrollbar + navigator.scrollbar.position(scrollbarLeft, scrollbarTop, navigatorWidth, scrollbarHeight); + // Keep scale 0-1 + navigator.scrollbar.setRange( + // Use real value, not rounded because range can be very small + // (#1716) + navigator.zoomedMin / (navigatorSize || 1), navigator.zoomedMax / (navigatorSize || 1)); + } + navigator.rendered = true; + }; + /** + * Set up the mouse and touch events for the navigator + * + * @private + * @function Highcharts.Navigator#addMouseEvents + */ + Navigator.prototype.addMouseEvents = function () { + var navigator = this, chart = navigator.chart, container = chart.container, eventsToUnbind = [], mouseMoveHandler, mouseUpHandler; + /** + * Create mouse events' handlers. + * Make them as separate functions to enable wrapping them: + */ + navigator.mouseMoveHandler = mouseMoveHandler = function (e) { + navigator.onMouseMove(e); + }; + navigator.mouseUpHandler = mouseUpHandler = function (e) { + navigator.onMouseUp(e); + }; + // Add shades and handles mousedown events + eventsToUnbind = navigator.getPartsEvents('mousedown'); + // Add mouse move and mouseup events. These are bind to doc/container, + // because Navigator.grabbedSomething flags are stored in mousedown + // events + eventsToUnbind.push(addEvent(chart.renderTo, 'mousemove', mouseMoveHandler), addEvent(container.ownerDocument, 'mouseup', mouseUpHandler)); + // Touch events + if (hasTouch) { + eventsToUnbind.push(addEvent(chart.renderTo, 'touchmove', mouseMoveHandler), addEvent(container.ownerDocument, 'touchend', mouseUpHandler)); + eventsToUnbind.concat(navigator.getPartsEvents('touchstart')); + } + navigator.eventsToUnbind = eventsToUnbind; + // Data events + if (navigator.series && navigator.series[0]) { + eventsToUnbind.push(addEvent(navigator.series[0].xAxis, 'foundExtremes', function () { + chart.navigator.modifyNavigatorAxisExtremes(); + })); + } + }; + /** + * Generate events for handles and masks + * + * @private + * @function Highcharts.Navigator#getPartsEvents + * + * @param {string} eventName + * Event name handler, 'mousedown' or 'touchstart' + * + * @return {Array} + * An array of functions to remove navigator functions from the + * events again. + */ + Navigator.prototype.getPartsEvents = function (eventName) { + var navigator = this, events = []; + ['shades', 'handles'].forEach(function (name) { + navigator[name].forEach(function (navigatorItem, index) { + events.push(addEvent(navigatorItem.element, eventName, function (e) { + navigator[name + 'Mousedown'](e, index); + })); + }); + }); + return events; + }; + /** + * Mousedown on a shaded mask, either: + * + * - will be stored for future drag&drop + * + * - will directly shift to a new range + * + * @private + * @function Highcharts.Navigator#shadesMousedown + * + * @param {Highcharts.PointerEventObject} e + * Mouse event + * + * @param {number} index + * Index of a mask in Navigator.shades array + */ + Navigator.prototype.shadesMousedown = function (e, index) { + e = this.chart.pointer.normalize(e); + var navigator = this, chart = navigator.chart, xAxis = navigator.xAxis, zoomedMin = navigator.zoomedMin, navigatorPosition = navigator.left, navigatorSize = navigator.size, range = navigator.range, chartX = e.chartX, fixedMax, fixedMin, ext, left; + // For inverted chart, swap some options: + if (chart.inverted) { + chartX = e.chartY; + navigatorPosition = navigator.top; + } + if (index === 1) { + // Store information for drag&drop + navigator.grabbedCenter = chartX; + navigator.fixedWidth = range; + navigator.dragOffset = chartX - zoomedMin; + } + else { + // Shift the range by clicking on shaded areas + left = chartX - navigatorPosition - range / 2; + if (index === 0) { + left = Math.max(0, left); + } + else if (index === 2 && left + range >= navigatorSize) { + left = navigatorSize - range; + if (navigator.reversedExtremes) { + // #7713 + left -= range; + fixedMin = navigator.getUnionExtremes().dataMin; + } + else { + // #2293, #3543 + fixedMax = navigator.getUnionExtremes().dataMax; + } + } + if (left !== zoomedMin) { // it has actually moved + navigator.fixedWidth = range; // #1370 + ext = xAxis.navigatorAxis.toFixedRange(left, left + range, fixedMin, fixedMax); + if (defined(ext.min)) { // #7411 + chart.xAxis[0].setExtremes(Math.min(ext.min, ext.max), Math.max(ext.min, ext.max), true, null, // auto animation + { trigger: 'navigator' }); + } + } + } + }; + /** + * Mousedown on a handle mask. + * Will store necessary information for drag&drop. + * + * @private + * @function Highcharts.Navigator#handlesMousedown + * @param {Highcharts.PointerEventObject} e + * Mouse event + * @param {number} index + * Index of a handle in Navigator.handles array + * @return {void} + */ + Navigator.prototype.handlesMousedown = function (e, index) { + e = this.chart.pointer.normalize(e); + var navigator = this, chart = navigator.chart, baseXAxis = chart.xAxis[0], + // For reversed axes, min and max are changed, + // so the other extreme should be stored + reverse = navigator.reversedExtremes; + if (index === 0) { + // Grab the left handle + navigator.grabbedLeft = true; + navigator.otherHandlePos = navigator.zoomedMax; + navigator.fixedExtreme = reverse ? baseXAxis.min : baseXAxis.max; + } + else { + // Grab the right handle + navigator.grabbedRight = true; + navigator.otherHandlePos = navigator.zoomedMin; + navigator.fixedExtreme = reverse ? baseXAxis.max : baseXAxis.min; + } + chart.fixedRange = null; + }; + /** + * Mouse move event based on x/y mouse position. + * + * @private + * @function Highcharts.Navigator#onMouseMove + * + * @param {Highcharts.PointerEventObject} e + * Mouse event + */ + Navigator.prototype.onMouseMove = function (e) { + var navigator = this, chart = navigator.chart, left = navigator.left, navigatorSize = navigator.navigatorSize, range = navigator.range, dragOffset = navigator.dragOffset, inverted = chart.inverted, chartX; + // In iOS, a mousemove event with e.pageX === 0 is fired when holding + // the finger down in the center of the scrollbar. This should be + // ignored. + if (!e.touches || e.touches[0].pageX !== 0) { // #4696 + e = chart.pointer.normalize(e); + chartX = e.chartX; + // Swap some options for inverted chart + if (inverted) { + left = navigator.top; + chartX = e.chartY; + } + // Drag left handle or top handle + if (navigator.grabbedLeft) { + navigator.hasDragged = true; + navigator.render(0, 0, chartX - left, navigator.otherHandlePos); + // Drag right handle or bottom handle + } + else if (navigator.grabbedRight) { + navigator.hasDragged = true; + navigator.render(0, 0, navigator.otherHandlePos, chartX - left); + // Drag scrollbar or open area in navigator + } + else if (navigator.grabbedCenter) { + navigator.hasDragged = true; + if (chartX < dragOffset) { // outside left + chartX = dragOffset; + // outside right + } + else if (chartX > + navigatorSize + dragOffset - range) { + chartX = navigatorSize + dragOffset - range; + } + navigator.render(0, 0, chartX - dragOffset, chartX - dragOffset + range); + } + if (navigator.hasDragged && + navigator.scrollbar && + pick(navigator.scrollbar.options.liveRedraw, + // By default, don't run live redraw on VML, on touch + // devices or if the chart is in boost. + H.svg && !isTouchDevice && !this.chart.isBoosting)) { + e.DOMType = e.type; // DOMType is for IE8 + setTimeout(function () { + navigator.onMouseUp(e); + }, 0); + } + } + }; + /** + * Mouse up event based on x/y mouse position. + * + * @private + * @function Highcharts.Navigator#onMouseUp + * @param {Highcharts.PointerEventObject} e + * Mouse event + * @return {void} + */ + Navigator.prototype.onMouseUp = function (e) { + var navigator = this, chart = navigator.chart, xAxis = navigator.xAxis, scrollbar = navigator.scrollbar, DOMEvent = e.DOMEvent || e, inverted = chart.inverted, verb = navigator.rendered && !navigator.hasDragged ? + 'animate' : 'attr', zoomedMax = Math.round(navigator.zoomedMax), zoomedMin = Math.round(navigator.zoomedMin), unionExtremes, fixedMin, fixedMax, ext; + if ( + // MouseUp is called for both, navigator and scrollbar (that order), + // which causes calling afterSetExtremes twice. Prevent first call + // by checking if scrollbar is going to set new extremes (#6334) + (navigator.hasDragged && (!scrollbar || !scrollbar.hasDragged)) || + e.trigger === 'scrollbar') { + unionExtremes = navigator.getUnionExtremes(); + // When dragging one handle, make sure the other one doesn't change + if (navigator.zoomedMin === navigator.otherHandlePos) { + fixedMin = navigator.fixedExtreme; + } + else if (navigator.zoomedMax === navigator.otherHandlePos) { + fixedMax = navigator.fixedExtreme; + } + // Snap to right edge (#4076) + if (navigator.zoomedMax === navigator.size) { + fixedMax = navigator.reversedExtremes ? + unionExtremes.dataMin : + unionExtremes.dataMax; + } + // Snap to left edge (#7576) + if (navigator.zoomedMin === 0) { + fixedMin = navigator.reversedExtremes ? + unionExtremes.dataMax : + unionExtremes.dataMin; + } + ext = xAxis.navigatorAxis.toFixedRange(navigator.zoomedMin, navigator.zoomedMax, fixedMin, fixedMax); + if (defined(ext.min)) { + chart.xAxis[0].setExtremes(Math.min(ext.min, ext.max), Math.max(ext.min, ext.max), true, + // Run animation when clicking buttons, scrollbar track etc, + // but not when dragging handles or scrollbar + navigator.hasDragged ? false : null, { + trigger: 'navigator', + triggerOp: 'navigator-drag', + DOMEvent: DOMEvent // #1838 + }); + } + } + if (e.DOMType !== 'mousemove' && + e.DOMType !== 'touchmove') { + navigator.grabbedLeft = navigator.grabbedRight = + navigator.grabbedCenter = navigator.fixedWidth = + navigator.fixedExtreme = navigator.otherHandlePos = + navigator.hasDragged = navigator.dragOffset = null; + } + // Update position of navigator shades, outline and handles (#12573) + if (navigator.navigatorEnabled) { + if (navigator.shades) { + navigator.drawMasks(zoomedMin, zoomedMax, inverted, verb); + } + if (navigator.outline) { + navigator.drawOutline(zoomedMin, zoomedMax, inverted, verb); + } + if (navigator.navigatorOptions.handles.enabled && + Object.keys(navigator.handles).length === + navigator.handles.length) { + navigator.drawHandle(zoomedMin, 0, inverted, verb); + navigator.drawHandle(zoomedMax, 1, inverted, verb); + } + } + }; + /** + * Removes the event handlers attached previously with addEvents. + * + * @private + * @function Highcharts.Navigator#removeEvents + * @return {void} + */ + Navigator.prototype.removeEvents = function () { + if (this.eventsToUnbind) { + this.eventsToUnbind.forEach(function (unbind) { + unbind(); + }); + this.eventsToUnbind = void 0; + } + this.removeBaseSeriesEvents(); + }; + /** + * Remove data events. + * + * @private + * @function Highcharts.Navigator#removeBaseSeriesEvents + * @return {void} + */ + Navigator.prototype.removeBaseSeriesEvents = function () { + var baseSeries = this.baseSeries || []; + if (this.navigatorEnabled && baseSeries[0]) { + if (this.navigatorOptions.adaptToUpdatedData !== false) { + baseSeries.forEach(function (series) { + removeEvent(series, 'updatedData', this.updatedDataHandler); + }, this); + } + // We only listen for extremes-events on the first baseSeries + if (baseSeries[0].xAxis) { + removeEvent(baseSeries[0].xAxis, 'foundExtremes', this.modifyBaseAxisExtremes); + } + } + }; + /** + * Initialize the Navigator object + * + * @private + * @function Highcharts.Navigator#init + * + * @param {Highcharts.Chart} chart + */ + Navigator.prototype.init = function (chart) { + var chartOptions = chart.options, navigatorOptions = chartOptions.navigator, navigatorEnabled = navigatorOptions.enabled, scrollbarOptions = chartOptions.scrollbar, scrollbarEnabled = scrollbarOptions.enabled, height = navigatorEnabled ? navigatorOptions.height : 0, scrollbarHeight = scrollbarEnabled ? + scrollbarOptions.height : + 0; + this.handles = []; + this.shades = []; + this.chart = chart; + this.setBaseSeries(); + this.height = height; + this.scrollbarHeight = scrollbarHeight; + this.scrollbarEnabled = scrollbarEnabled; + this.navigatorEnabled = navigatorEnabled; + this.navigatorOptions = navigatorOptions; + this.scrollbarOptions = scrollbarOptions; + this.outlineHeight = height + scrollbarHeight; + this.opposite = pick(navigatorOptions.opposite, Boolean(!navigatorEnabled && chart.inverted)); // #6262 + var navigator = this, baseSeries = navigator.baseSeries, xAxisIndex = chart.xAxis.length, yAxisIndex = chart.yAxis.length, baseXaxis = baseSeries && baseSeries[0] && baseSeries[0].xAxis || + chart.xAxis[0] || { options: {} }; + chart.isDirtyBox = true; + if (navigator.navigatorEnabled) { + // an x axis is required for scrollbar also + navigator.xAxis = new Axis(chart, merge({ + // inherit base xAxis' break and ordinal options + breaks: baseXaxis.options.breaks, + ordinal: baseXaxis.options.ordinal + }, navigatorOptions.xAxis, { + id: 'navigator-x-axis', + yAxis: 'navigator-y-axis', + isX: true, + type: 'datetime', + index: xAxisIndex, + isInternal: true, + offset: 0, + keepOrdinalPadding: true, + startOnTick: false, + endOnTick: false, + minPadding: 0, + maxPadding: 0, + zoomEnabled: false + }, chart.inverted ? { + offsets: [scrollbarHeight, 0, -scrollbarHeight, 0], + width: height + } : { + offsets: [0, -scrollbarHeight, 0, scrollbarHeight], + height: height + })); + navigator.yAxis = new Axis(chart, merge(navigatorOptions.yAxis, { + id: 'navigator-y-axis', + alignTicks: false, + offset: 0, + index: yAxisIndex, + isInternal: true, + zoomEnabled: false + }, chart.inverted ? { + width: height + } : { + height: height + })); + // If we have a base series, initialize the navigator series + if (baseSeries || navigatorOptions.series.data) { + navigator.updateNavigatorSeries(false); + // If not, set up an event to listen for added series + } + else if (chart.series.length === 0) { + navigator.unbindRedraw = addEvent(chart, 'beforeRedraw', function () { + // We've got one, now add it as base + if (chart.series.length > 0 && !navigator.series) { + navigator.setBaseSeries(); + navigator.unbindRedraw(); // reset + } + }); + } + navigator.reversedExtremes = (chart.inverted && !navigator.xAxis.reversed) || (!chart.inverted && navigator.xAxis.reversed); + // Render items, so we can bind events to them: + navigator.renderElements(); + // Add mouse events + navigator.addMouseEvents(); + // in case of scrollbar only, fake an x axis to get translation + } + else { + navigator.xAxis = { + chart: chart, + navigatorAxis: { + fake: true + }, + translate: function (value, reverse) { + var axis = chart.xAxis[0], ext = axis.getExtremes(), scrollTrackWidth = axis.len - 2 * scrollbarHeight, min = numExt('min', axis.options.min, ext.dataMin), valueRange = numExt('max', axis.options.max, ext.dataMax) - min; + return reverse ? + // from pixel to value + (value * valueRange / scrollTrackWidth) + min : + // from value to pixel + scrollTrackWidth * (value - min) / valueRange; + }, + toPixels: function (value) { + return this.translate(value); + }, + toValue: function (value) { + return this.translate(value, true); + } + }; + navigator.xAxis.navigatorAxis.axis = navigator.xAxis; + navigator.xAxis.navigatorAxis.toFixedRange = (NavigatorAxis.AdditionsClass.prototype.toFixedRange.bind(navigator.xAxis.navigatorAxis)); + } + // Initialize the scrollbar + if (chart.options.scrollbar.enabled) { + chart.scrollbar = navigator.scrollbar = new Scrollbar(chart.renderer, merge(chart.options.scrollbar, { + margin: navigator.navigatorEnabled ? 0 : 10, + vertical: chart.inverted + }), chart); + addEvent(navigator.scrollbar, 'changed', function (e) { + var range = navigator.size, to = range * this.to, from = range * this.from; + navigator.hasDragged = navigator.scrollbar.hasDragged; + navigator.render(0, 0, from, to); + if (chart.options.scrollbar.liveRedraw || + (e.DOMType !== 'mousemove' && + e.DOMType !== 'touchmove')) { + setTimeout(function () { + navigator.onMouseUp(e); + }); + } + }); + } + // Add data events + navigator.addBaseSeriesEvents(); + // Add redraw events + navigator.addChartEvents(); + }; + /** + * Get the union data extremes of the chart - the outer data extremes of the + * base X axis and the navigator axis. + * + * @private + * @function Highcharts.Navigator#getUnionExtremes + * @param {boolean} [returnFalseOnNoBaseSeries] + * as the param says. + * @return {Highcharts.Dictionary<(number|undefined)>|undefined} + */ + Navigator.prototype.getUnionExtremes = function (returnFalseOnNoBaseSeries) { + var baseAxis = this.chart.xAxis[0], navAxis = this.xAxis, navAxisOptions = navAxis.options, baseAxisOptions = baseAxis.options, ret; + if (!returnFalseOnNoBaseSeries || baseAxis.dataMin !== null) { + ret = { + dataMin: pick(// #4053 + navAxisOptions && navAxisOptions.min, numExt('min', baseAxisOptions.min, baseAxis.dataMin, navAxis.dataMin, navAxis.min)), + dataMax: pick(navAxisOptions && navAxisOptions.max, numExt('max', baseAxisOptions.max, baseAxis.dataMax, navAxis.dataMax, navAxis.max)) + }; + } + return ret; + }; + /** + * Set the base series and update the navigator series from this. With a bit + * of modification we should be able to make this an API method to be called + * from the outside + * + * @private + * @function Highcharts.Navigator#setBaseSeries + * @param {Highcharts.SeriesOptionsType} [baseSeriesOptions] + * Additional series options for a navigator + * @param {boolean} [redraw] + * Whether to redraw after update. + * @return {void} + */ + Navigator.prototype.setBaseSeries = function (baseSeriesOptions, redraw) { + var chart = this.chart, baseSeries = this.baseSeries = []; + baseSeriesOptions = (baseSeriesOptions || + chart.options && chart.options.navigator.baseSeries || + (chart.series.length ? + // Find the first non-navigator series (#8430) + find(chart.series, function (s) { + return !s.options.isInternal; + }).index : + 0)); + // Iterate through series and add the ones that should be shown in + // navigator. + (chart.series || []).forEach(function (series, i) { + if ( + // Don't include existing nav series + !series.options.isInternal && + (series.options.showInNavigator || + (i === baseSeriesOptions || + series.options.id === baseSeriesOptions) && + series.options.showInNavigator !== false)) { + baseSeries.push(series); + } + }); + // When run after render, this.xAxis already exists + if (this.xAxis && !this.xAxis.navigatorAxis.fake) { + this.updateNavigatorSeries(true, redraw); + } + }; + /** + * Update series in the navigator from baseSeries, adding new if does not + * exist. + * + * @private + * @function Highcharts.Navigator.updateNavigatorSeries + * @param {boolean} addEvents + * @param {boolean} [redraw] + * @return {void} + */ + Navigator.prototype.updateNavigatorSeries = function (addEvents, redraw) { + var navigator = this, chart = navigator.chart, baseSeries = navigator.baseSeries, baseOptions, mergedNavSeriesOptions, chartNavigatorSeriesOptions = navigator.navigatorOptions.series, baseNavigatorOptions, navSeriesMixin = { + enableMouseTracking: false, + index: null, + linkedTo: null, + group: 'nav', + padXAxis: false, + xAxis: 'navigator-x-axis', + yAxis: 'navigator-y-axis', + showInLegend: false, + stacking: void 0, + isInternal: true, + states: { + inactive: { + opacity: 1 + } + } + }, + // Remove navigator series that are no longer in the baseSeries + navigatorSeries = navigator.series = + (navigator.series || []).filter(function (navSeries) { + var base = navSeries.baseSeries; + if (baseSeries.indexOf(base) < 0) { // Not in array + // If there is still a base series connected to this + // series, remove event handler and reference. + if (base) { + removeEvent(base, 'updatedData', navigator.updatedDataHandler); + delete base.navigatorSeries; + } + // Kill the nav series. It may already have been + // destroyed (#8715). + if (navSeries.chart) { + navSeries.destroy(); + } + return false; + } + return true; + }); + // Go through each base series and merge the options to create new + // series + if (baseSeries && baseSeries.length) { + baseSeries.forEach(function eachBaseSeries(base) { + var linkedNavSeries = base.navigatorSeries, userNavOptions = extend( + // Grab color and visibility from base as default + { + color: base.color, + visible: base.visible + }, !isArray(chartNavigatorSeriesOptions) ? + chartNavigatorSeriesOptions : + defaultOptions.navigator.series); + // Don't update if the series exists in nav and we have disabled + // adaptToUpdatedData. + if (linkedNavSeries && + navigator.navigatorOptions.adaptToUpdatedData === false) { + return; + } + navSeriesMixin.name = 'Navigator ' + baseSeries.length; + baseOptions = base.options || {}; + baseNavigatorOptions = baseOptions.navigatorOptions || {}; + mergedNavSeriesOptions = merge(baseOptions, navSeriesMixin, userNavOptions, baseNavigatorOptions); + // Once nav series type is resolved, pick correct pointRange + mergedNavSeriesOptions.pointRange = pick( + // Stricte set pointRange in options + userNavOptions.pointRange, baseNavigatorOptions.pointRange, + // Fallback to default values, e.g. `null` for column + defaultOptions.plotOptions[mergedNavSeriesOptions.type || 'line'].pointRange); + // Merge data separately. Do a slice to avoid mutating the + // navigator options from base series (#4923). + var navigatorSeriesData = baseNavigatorOptions.data || userNavOptions.data; + navigator.hasNavigatorData = + navigator.hasNavigatorData || !!navigatorSeriesData; + mergedNavSeriesOptions.data = + navigatorSeriesData || + baseOptions.data && baseOptions.data.slice(0); + // Update or add the series + if (linkedNavSeries && linkedNavSeries.options) { + linkedNavSeries.update(mergedNavSeriesOptions, redraw); + } + else { + base.navigatorSeries = chart.initSeries(mergedNavSeriesOptions); + base.navigatorSeries.baseSeries = base; // Store ref + navigatorSeries.push(base.navigatorSeries); + } + }); + } + // If user has defined data (and no base series) or explicitly defined + // navigator.series as an array, we create these series on top of any + // base series. + if (chartNavigatorSeriesOptions.data && + !(baseSeries && baseSeries.length) || + isArray(chartNavigatorSeriesOptions)) { + navigator.hasNavigatorData = false; + // Allow navigator.series to be an array + chartNavigatorSeriesOptions = + splat(chartNavigatorSeriesOptions); + chartNavigatorSeriesOptions.forEach(function (userSeriesOptions, i) { + navSeriesMixin.name = + 'Navigator ' + (navigatorSeries.length + 1); + mergedNavSeriesOptions = merge(defaultOptions.navigator.series, { + // Since we don't have a base series to pull color from, + // try to fake it by using color from series with same + // index. Otherwise pull from the colors array. We need + // an explicit color as otherwise updates will increment + // color counter and we'll get a new color for each + // update of the nav series. + color: chart.series[i] && + !chart.series[i].options.isInternal && + chart.series[i].color || + chart.options.colors[i] || + chart.options.colors[0] + }, navSeriesMixin, userSeriesOptions); + mergedNavSeriesOptions.data = userSeriesOptions.data; + if (mergedNavSeriesOptions.data) { + navigator.hasNavigatorData = true; + navigatorSeries.push(chart.initSeries(mergedNavSeriesOptions)); + } + }); + } + if (addEvents) { + this.addBaseSeriesEvents(); + } + }; + /** + * Add data events. + * For example when main series is updated we need to recalculate extremes + * + * @private + * @function Highcharts.Navigator#addBaseSeriesEvent + * @return {void} + */ + Navigator.prototype.addBaseSeriesEvents = function () { + var navigator = this, baseSeries = navigator.baseSeries || []; + // Bind modified extremes event to first base's xAxis only. + // In event of > 1 base-xAxes, the navigator will ignore those. + // Adding this multiple times to the same axis is no problem, as + // duplicates should be discarded by the browser. + if (baseSeries[0] && baseSeries[0].xAxis) { + addEvent(baseSeries[0].xAxis, 'foundExtremes', this.modifyBaseAxisExtremes); + } + baseSeries.forEach(function (base) { + // Link base series show/hide to navigator series visibility + addEvent(base, 'show', function () { + if (this.navigatorSeries) { + this.navigatorSeries.setVisible(true, false); + } + }); + addEvent(base, 'hide', function () { + if (this.navigatorSeries) { + this.navigatorSeries.setVisible(false, false); + } + }); + // Respond to updated data in the base series, unless explicitily + // not adapting to data changes. + if (this.navigatorOptions.adaptToUpdatedData !== false) { + if (base.xAxis) { + addEvent(base, 'updatedData', this.updatedDataHandler); + } + } + // Handle series removal + addEvent(base, 'remove', function () { + if (this.navigatorSeries) { + erase(navigator.series, this.navigatorSeries); + if (defined(this.navigatorSeries.options)) { + this.navigatorSeries.remove(false); + } + delete this.navigatorSeries; + } + }); + }, this); + }; + /** + * Get minimum from all base series connected to the navigator + * @private + * @param {number} currentSeriesMin + * Minium from the current series + * @return {number} Minimum from all series + */ + Navigator.prototype.getBaseSeriesMin = function (currentSeriesMin) { + return this.baseSeries.reduce(function (min, series) { + // (#10193) + return Math.min(min, series.xData ? series.xData[0] : min); + }, currentSeriesMin); + }; + /** + * Set the navigator x axis extremes to reflect the total. The navigator + * extremes should always be the extremes of the union of all series in the + * chart as well as the navigator series. + * + * @private + * @function Highcharts.Navigator#modifyNavigatorAxisExtremes + */ + Navigator.prototype.modifyNavigatorAxisExtremes = function () { + var xAxis = this.xAxis, unionExtremes; + if (typeof xAxis.getExtremes !== 'undefined') { + unionExtremes = this.getUnionExtremes(true); + if (unionExtremes && + (unionExtremes.dataMin !== xAxis.min || + unionExtremes.dataMax !== xAxis.max)) { + xAxis.min = unionExtremes.dataMin; + xAxis.max = unionExtremes.dataMax; + } + } + }; + /** + * Hook to modify the base axis extremes with information from the Navigator + * + * @private + * @function Highcharts.Navigator#modifyBaseAxisExtremes + */ + Navigator.prototype.modifyBaseAxisExtremes = function () { + var baseXAxis = this, navigator = baseXAxis.chart.navigator, baseExtremes = baseXAxis.getExtremes(), baseMin = baseExtremes.min, baseMax = baseExtremes.max, baseDataMin = baseExtremes.dataMin, baseDataMax = baseExtremes.dataMax, range = baseMax - baseMin, stickToMin = navigator.stickToMin, stickToMax = navigator.stickToMax, overscroll = pick(baseXAxis.options.overscroll, 0), newMax, newMin, navigatorSeries = navigator.series && navigator.series[0], hasSetExtremes = !!baseXAxis.setExtremes, + // When the extremes have been set by range selector button, don't + // stick to min or max. The range selector buttons will handle the + // extremes. (#5489) + unmutable = baseXAxis.eventArgs && + baseXAxis.eventArgs.trigger === 'rangeSelectorButton'; + if (!unmutable) { + // If the zoomed range is already at the min, move it to the right + // as new data comes in + if (stickToMin) { + newMin = baseDataMin; + newMax = newMin + range; + } + // If the zoomed range is already at the max, move it to the right + // as new data comes in + if (stickToMax) { + newMax = baseDataMax + overscroll; + // If stickToMin is true, the new min value is set above + if (!stickToMin) { + newMin = Math.max(baseDataMin, // don't go below data extremes (#13184) + newMax - range, navigator.getBaseSeriesMin(navigatorSeries && navigatorSeries.xData ? + navigatorSeries.xData[0] : + -Number.MAX_VALUE)); + } + } + // Update the extremes + if (hasSetExtremes && (stickToMin || stickToMax)) { + if (isNumber(newMin)) { + baseXAxis.min = baseXAxis.userMin = newMin; + baseXAxis.max = baseXAxis.userMax = newMax; + } + } + } + // Reset + navigator.stickToMin = + navigator.stickToMax = null; + }; + /** + * Handler for updated data on the base series. When data is modified, the + * navigator series must reflect it. This is called from the Chart.redraw + * function before axis and series extremes are computed. + * + * @private + * @function Highcharts.Navigator#updateDataHandler + */ + Navigator.prototype.updatedDataHandler = function () { + var navigator = this.chart.navigator, baseSeries = this, navigatorSeries = this.navigatorSeries, xDataMin = navigator.getBaseSeriesMin(baseSeries.xData[0]); + // If the scrollbar is scrolled all the way to the right, keep right as + // new data comes in. + navigator.stickToMax = navigator.reversedExtremes ? + Math.round(navigator.zoomedMin) === 0 : + Math.round(navigator.zoomedMax) >= Math.round(navigator.size); + // Detect whether the zoomed area should stick to the minimum or + // maximum. If the current axis minimum falls outside the new updated + // dataset, we must adjust. + navigator.stickToMin = isNumber(baseSeries.xAxis.min) && + (baseSeries.xAxis.min <= xDataMin) && + (!this.chart.fixedRange || !navigator.stickToMax); + // Set the navigator series data to the new data of the base series + if (navigatorSeries && !navigator.hasNavigatorData) { + navigatorSeries.options.pointStart = baseSeries.xData[0]; + navigatorSeries.setData(baseSeries.options.data, false, null, false); // #5414 + } + }; + /** + * Add chart events, like redrawing navigator, when chart requires that. + * + * @private + * @function Highcharts.Navigator#addChartEvents + * @return {void} + */ + Navigator.prototype.addChartEvents = function () { + if (!this.eventsToUnbind) { + this.eventsToUnbind = []; + } + this.eventsToUnbind.push( + // Move the scrollbar after redraw, like after data updata even if + // axes don't redraw + addEvent(this.chart, 'redraw', function () { + var navigator = this.navigator, xAxis = navigator && (navigator.baseSeries && + navigator.baseSeries[0] && + navigator.baseSeries[0].xAxis || + this.xAxis[0]); // #5709, #13114 + if (xAxis) { + navigator.render(xAxis.min, xAxis.max); + } + }), + // Make room for the navigator, can be placed around the chart: + addEvent(this.chart, 'getMargins', function () { + var chart = this, navigator = chart.navigator, marginName = navigator.opposite ? + 'plotTop' : 'marginBottom'; + if (chart.inverted) { + marginName = navigator.opposite ? + 'marginRight' : 'plotLeft'; + } + chart[marginName] = + (chart[marginName] || 0) + (navigator.navigatorEnabled || !chart.inverted ? + navigator.outlineHeight : + 0) + navigator.navigatorOptions.margin; + })); + }; + /** + * Destroys allocated elements. + * + * @private + * @function Highcharts.Navigator#destroy + */ + Navigator.prototype.destroy = function () { + // Disconnect events added in addEvents + this.removeEvents(); + if (this.xAxis) { + erase(this.chart.xAxis, this.xAxis); + erase(this.chart.axes, this.xAxis); + } + if (this.yAxis) { + erase(this.chart.yAxis, this.yAxis); + erase(this.chart.axes, this.yAxis); + } + // Destroy series + (this.series || []).forEach(function (s) { + if (s.destroy) { + s.destroy(); + } + }); + // Destroy properties + [ + 'series', 'xAxis', 'yAxis', 'shades', 'outline', 'scrollbarTrack', + 'scrollbarRifles', 'scrollbarGroup', 'scrollbar', 'navigatorGroup', + 'rendered' + ].forEach(function (prop) { + if (this[prop] && this[prop].destroy) { + this[prop].destroy(); + } + this[prop] = null; + }, this); + // Destroy elements in collection + [this.handles].forEach(function (coll) { + destroyObjectProperties(coll); + }, this); + }; + return Navigator; + }()); + // End of prototype + if (!H.Navigator) { + H.Navigator = Navigator; + NavigatorAxis.compose(Axis); + // For Stock charts. For x only zooming, do not to create the zoom button + // because X axis zooming is already allowed by the Navigator and Range + // selector. (#9285) + addEvent(Chart, 'beforeShowResetZoom', function () { + var chartOptions = this.options, navigator = chartOptions.navigator, rangeSelector = chartOptions.rangeSelector; + if (((navigator && navigator.enabled) || + (rangeSelector && rangeSelector.enabled)) && + ((!isTouchDevice && chartOptions.chart.zoomType === 'x') || + (isTouchDevice && chartOptions.chart.pinchType === 'x'))) { + return false; + } + }); + // Initialize navigator for stock charts + addEvent(Chart, 'beforeRender', function () { + var options = this.options; + if (options.navigator.enabled || + options.scrollbar.enabled) { + this.scroller = this.navigator = new Navigator(this); + } + }); + // For stock charts, extend the Chart.setChartSize method so that we can set + // the final top position of the navigator once the height of the chart, + // including the legend, is determined. #367. We can't use Chart.getMargins, + // because labels offsets are not calculated yet. + addEvent(Chart, 'afterSetChartSize', function () { + var legend = this.legend, navigator = this.navigator, scrollbarHeight, legendOptions, xAxis, yAxis; + if (navigator) { + legendOptions = legend && legend.options; + xAxis = navigator.xAxis; + yAxis = navigator.yAxis; + scrollbarHeight = navigator.scrollbarHeight; + // Compute the top position + if (this.inverted) { + navigator.left = navigator.opposite ? + this.chartWidth - scrollbarHeight - + navigator.height : + this.spacing[3] + scrollbarHeight; + navigator.top = this.plotTop + scrollbarHeight; + } + else { + navigator.left = this.plotLeft + scrollbarHeight; + navigator.top = navigator.navigatorOptions.top || + this.chartHeight - + navigator.height - + scrollbarHeight - + this.spacing[2] - + (this.rangeSelector && this.extraBottomMargin ? + this.rangeSelector.getHeight() : + 0) - + ((legendOptions && + legendOptions.verticalAlign === 'bottom' && + legendOptions.enabled && + !legendOptions.floating) ? + legend.legendHeight + + pick(legendOptions.margin, 10) : + 0) - + (this.titleOffset ? this.titleOffset[2] : 0); + } + if (xAxis && yAxis) { // false if navigator is disabled (#904) + if (this.inverted) { + xAxis.options.left = yAxis.options.left = navigator.left; + } + else { + xAxis.options.top = yAxis.options.top = navigator.top; + } + xAxis.setAxisSize(); + yAxis.setAxisSize(); + } + } + }); + // Merge options, if no scrolling exists yet + addEvent(Chart, 'update', function (e) { + var navigatorOptions = (e.options.navigator || {}), scrollbarOptions = (e.options.scrollbar || {}); + if (!this.navigator && !this.scroller && + (navigatorOptions.enabled || scrollbarOptions.enabled)) { + merge(true, this.options.navigator, navigatorOptions); + merge(true, this.options.scrollbar, scrollbarOptions); + delete e.options.navigator; + delete e.options.scrollbar; + } + }); + // Initialize navigator, if no scrolling exists yet + addEvent(Chart, 'afterUpdate', function (event) { + if (!this.navigator && !this.scroller && + (this.options.navigator.enabled || + this.options.scrollbar.enabled)) { + this.scroller = this.navigator = new Navigator(this); + if (pick(event.redraw, true)) { + this.redraw(event.animation); // #7067 + } + } + }); + // Handle adding new series + addEvent(Chart, 'afterAddSeries', function () { + if (this.navigator) { + // Recompute which series should be shown in navigator, and add them + this.navigator.setBaseSeries(null, false); + } + }); + // Handle updating series + addEvent(Series, 'afterUpdate', function () { + if (this.chart.navigator && !this.options.isInternal) { + this.chart.navigator.setBaseSeries(null, false); + } + }); + Chart.prototype.callbacks.push(function (chart) { + var extremes, navigator = chart.navigator; + // Initialize the navigator + if (navigator && chart.xAxis[0]) { + extremes = chart.xAxis[0].getExtremes(); + navigator.render(extremes.min, extremes.max); + } + }); + } + H.Navigator = Navigator; + + return H.Navigator; + }); + _registerModule(_modules, 'masters/modules/gantt.src.js', [], function () { + + + }); + _registerModule(_modules, 'masters/highcharts-gantt.src.js', [_modules['masters/highcharts.src.js']], function (Highcharts) { + + + Highcharts.product = 'Highcharts Gantt'; + + return Highcharts; + }); + _modules['masters/highcharts-gantt.src.js']._modules = _modules; + return _modules['masters/highcharts-gantt.src.js']; +})); \ No newline at end of file diff --git a/librerias/gantt/code/highcharts.js b/librerias/gantt/code/highcharts.js new file mode 100644 index 0000000..9d39bac --- /dev/null +++ b/librerias/gantt/code/highcharts.js @@ -0,0 +1,522 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2009-2018 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(X,Q){"object"===typeof module&&module.exports?(Q["default"]=Q,module.exports=X.document?Q(X):Q):"function"===typeof define&&define.amd?define("highcharts/highcharts",function(){return Q(X)}):(X.Highcharts&&X.Highcharts.error(16,!0),X.Highcharts=Q(X))})("undefined"!==typeof window?window:this,function(X){function Q(d,f,E,q){d.hasOwnProperty(f)||(d[f]=q.apply(null,E))}var A={};Q(A,"parts/Globals.js",[],function(){var d="undefined"!==typeof X?X:"undefined"!==typeof window?window:{},f=d.document, +E=d.navigator&&d.navigator.userAgent||"",q=f&&f.createElementNS&&!!f.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect,M=/(edge|msie|trident)/i.test(E)&&!d.opera,K=-1!==E.indexOf("Firefox"),J=-1!==E.indexOf("Chrome"),L=K&&4>parseInt(E.split("Firefox/")[1],10);return{product:"Highcharts",version:"8.1.0",deg2rad:2*Math.PI/360,doc:f,hasBidiBug:L,hasTouch:!!d.TouchEvent,isMS:M,isWebKit:-1!==E.indexOf("AppleWebKit"),isFirefox:K,isChrome:J,isSafari:!J&&-1!==E.indexOf("Safari"),isTouchDevice:/(Mobile|Android|Windows Phone)/.test(E), +SVG_NS:"http://www.w3.org/2000/svg",chartCount:0,seriesTypes:{},symbolSizes:{},svg:q,win:d,marginNames:["plotTop","marginRight","marginBottom","plotLeft"],noop:function(){},charts:[],dateFormats:{}}});Q(A,"parts/Utilities.js",[A["parts/Globals.js"]],function(d){function f(){var a,c=arguments,k={},r=function(a,c){"object"!==typeof a&&(a={});Z(c,function(k,e){!E(k,!0)||t(k)||n(k)?a[e]=c[e]:a[e]=r(a[e]||{},k)});return a};!0===c[0]&&(k=c[1],c=Array.prototype.slice.call(c,2));var e=c.length;for(a=0;a< +e;a++)k=r(k,c[a]);return k}function E(a,c){return!!a&&"object"===typeof a&&(!c||!w(a))}function q(a,c,k){var r;D(c)?b(k)?a.setAttribute(c,k):a&&a.getAttribute&&((r=a.getAttribute(c))||"class"!==c||(r=a.getAttribute(c+"Name"))):Z(c,function(c,k){a.setAttribute(k,c)});return r}function M(){for(var a=arguments,c=a.length,k=0;kr)for(var e=0;e=z+this.startTime){this.now=this.end;this.pos=1;this.update();var l=b[this.prop]=!0;Z(b,function(a){!0!==a&&(l=!1)});l&&e&&e.call(r);a=!1}else this.pos=k.easing((c- +this.startTime)/z),this.now=this.start+(this.end-this.start)*this.pos,this.update(),a=!0;return a};a.prototype.initPath=function(a,c,k){function r(a,c){for(;a.lengtha&&-Infinity=k&&(c=[1/k])));for(r=0;r=a||!e&&b<=(c[r]+(c[r+1]||c[r]))/2);r++);return z=P(z*k,-Math.round(Math.log(.001)/Math.LN10))},c=d.stableSort=function(a,c){var k=a.length,r,e;for(e=0;ek&&(k=a[c]);return k},r=d.destroyObjectProperties=function(a,c){Z(a,function(k,r){k&&k!==c&&k.destroy&&k.destroy();delete a[r]})},z=d.discardElement=function(a){var c=d.garbageBin;c||(c=l("div"));a&&c.appendChild(a);c.innerHTML=""},P=d.correctFloat=function(a,c){return parseFloat(a.toPrecision(c||14))},U=d.setAnimation=function(a,c){c.renderer.globalAnimation=M(a,c.options.chart.animation,!0)},W=d.animObject=function(a){return E(a)?f(a): +{duration:a?500:0}},Y=d.timeUnits={millisecond:1,second:1E3,minute:6E4,hour:36E5,day:864E5,week:6048E5,month:24192E5,year:314496E5},T=d.numberFormat=function(a,c,k,r){a=+a||0;c=+c;var e=d.defaultOptions.lang,z=(a.toString().split(".")[1]||"").split("e")[0].length,b=a.toString().split("e");if(-1===c)c=Math.min(z,20);else if(!N(c))c=2;else if(c&&b[1]&&0>b[1]){var l=c+ +b[1];0<=l?(b[0]=(+b[0]).toExponential(l).split("e")[0],c=l):(b[0]=b[0].split(".")[0]||0,a=20>c?(b[0]*Math.pow(10,b[1])).toFixed(c): +0,b[1]=0)}var g=(Math.abs(b[1]?b[0]:a)+Math.pow(10,-Math.max(c,z)-1)).toFixed(c);z=String(C(g));l=3a?"-":"")+(l?z.substr(0,l)+r:"");a+=z.substr(l).replace(/(\d{3})(?=\d)/g,"$1"+r);c&&(a+=k+g.slice(-c));b[1]&&0!==+a&&(a+="e"+b[1]);return a};Math.easeInOutSine=function(a){return-.5*(Math.cos(Math.PI*a)-1)};var ca=d.getStyle=function(a,c,k){if("width"===c)return c=Math.min(a.offsetWidth,a.scrollWidth),k=a.getBoundingClientRect&& +a.getBoundingClientRect().width,k=c-1&&(c=Math.floor(k)),Math.max(0,c-d.getStyle(a,"padding-left")-d.getStyle(a,"padding-right"));if("height"===c)return Math.max(0,Math.min(a.offsetHeight,a.scrollHeight)-d.getStyle(a,"padding-top")-d.getStyle(a,"padding-bottom"));x.getComputedStyle||F(27,!0);if(a=x.getComputedStyle(a,void 0))a=a.getPropertyValue(c),M(k,"opacity"!==c)&&(a=C(a));return a},aa=d.inArray=function(a,c,k){return c.indexOf(a,k)},O=d.find=Array.prototype.find?function(a,c){return a.find(c)}: +function(a,c){var k,r=a.length;for(k=0;kc?a>16,(f&65280)>>8,f&255,1]:4===F&&(q=[(f&3840)>>4|(f&3840)>>8,(f&240)>>4|f&240,(f&15)<<4|f&15,1])}if(!q)for(x=this.parsers.length;x--&&!q;){var H=this.parsers[x];(F=H.regex.exec(f))&&(q=H.parse(F))}}this.rgba=q||[]};d.prototype.get= +function(d){var f=this.input,x=this.rgba;if("undefined"!==typeof this.stops){var F=q(f);F.stops=[].concat(F.stops);this.stops.forEach(function(f,x){F.stops[x]=[F.stops[x][0],f.get(d)]})}else F=x&&E(x[0])?"rgb"===d||!d&&1===x[3]?"rgb("+x[0]+","+x[1]+","+x[2]+")":"a"===d?x[3]:"rgba("+x.join(",")+")":f;return F};d.prototype.brighten=function(d){var f,x=this.rgba;if(this.stops)this.stops.forEach(function(f){f.brighten(d)});else if(E(d)&&0!==d)for(f=0;3>f;f++)x[f]+=M(255*d),0>x[f]&&(x[f]=0),255k.width)k={width:0,height:0}}else k=this.htmlGetBBox();r.isSVG&& +(c=k.width,r=k.height,u&&(k.height=r={"11px,17":14,"13px,20":16}[l&&l.fontSize+","+Math.round(r)]||r),a&&(l=a*q,k.width=Math.abs(r*Math.sin(l))+Math.abs(c*Math.cos(l)),k.height=Math.abs(r*Math.cos(l))+Math.abs(c*Math.sin(l))));if(v&&0]*>/g,"").replace(/</g,"<").replace(/>/g,">")))};B.prototype.toFront=function(){var c=this.element;c.parentNode.appendChild(c);return this};B.prototype.translate=function(c,a){return this.attr({translateX:c,translateY:a})};B.prototype.updateShadows=function(c,a,k){var r=this.shadows; +if(r)for(var e=r.length;e--;)k.call(r[e],"height"===c?Math.max(a-(r[e].cutHeight||0),0):"d"===c?this.d:a,c,r[e])};B.prototype.updateTransform=function(){var c=this.translateX||0,a=this.translateY||0,k=this.scaleX,r=this.scaleY,e=this.inverted,b=this.rotation,l=this.matrix,g=this.element;e&&(c+=this.width,a+=this.height);c=["translate("+c+","+a+")"];N(l)&&c.push("matrix("+l.join(",")+")");e?c.push("rotate(90) scale(-1,1)"):b&&c.push("rotate("+b+" "+y(this.rotationOriginX,g.getAttribute("x"),0)+" "+ +y(this.rotationOriginY,g.getAttribute("y")||0)+")");(N(k)||N(r))&&c.push("scale("+y(k,1)+" "+y(r,1)+")");c.length&&g.setAttribute("transform",c.join(" "))};B.prototype.visibilitySetter=function(c,a,k){"inherit"===c?k.removeAttribute(a):this[a]!==c&&k.setAttribute(a,c);this[a]=c};B.prototype.xGetter=function(c){"circle"===this.element.nodeName&&("x"===c?c="cx":"y"===c&&(c="cy"));return this._defaultGetter(c)};B.prototype.zIndexSetter=function(c,a){var k=this.renderer,r=this.parentGroup,e=(r||k).element|| +k.box,b=this.element,l=!1;k=e===k.box;var g=this.added;var h;N(c)?(b.setAttribute("data-z-index",c),c=+c,this[a]===c&&(g=!1)):N(this[a])&&b.removeAttribute("data-z-index");this[a]=c;if(g){(c=this.zIndex)&&r&&(r.handleZ=!0);a=e.childNodes;for(h=a.length-1;0<=h&&!l;h--){r=a[h];g=r.getAttribute("data-z-index");var p=!N(g);if(r!==b)if(0>c&&p&&!k&&!h)e.insertBefore(b,a[h]),l=!0;else if(G(g)<=c||p&&(!N(c)||0<=c))e.insertBefore(b,a[h+1]||null),l=!0}l||(e.insertBefore(b,a[k?3:0]||null),l=!0)}return l};return B}(); +E.prototype["stroke-widthSetter"]=E.prototype.strokeSetter;E.prototype.yGetter=E.prototype.xGetter;E.prototype.matrixSetter=E.prototype.rotationOriginXSetter=E.prototype.rotationOriginYSetter=E.prototype.rotationSetter=E.prototype.scaleXSetter=E.prototype.scaleYSetter=E.prototype.translateXSetter=E.prototype.translateYSetter=E.prototype.verticalAlignSetter=function(e,c){this[c]=e;this.doTransform=!0};f.SVGElement=E;return f.SVGElement});Q(A,"parts/SvgRenderer.js",[A["parts/Color.js"],A["parts/Globals.js"], +A["parts/SVGElement.js"],A["parts/Utilities.js"]],function(d,f,E,q){var M=d.parse,K=q.addEvent,J=q.attr,L=q.createElement,x=q.css,F=q.defined,H=q.destroyObjectProperties,C=q.extend,D=q.isArray,w=q.isNumber,n=q.isObject,t=q.isString,N=q.merge,m=q.objectEach,b=q.pick,g=q.pInt,v=q.removeEvent,h=q.splat,e=q.uniqueKey,p=f.charts,l=f.deg2rad,I=f.doc,u=f.isFirefox,y=f.isMS,G=f.isWebKit;q=f.noop;var S=f.svg,R=f.SVG_NS,B=f.symbolSizes,c=f.win;d=f.SVGRenderer=function(){this.init.apply(this,arguments)};C(d.prototype, +{Element:E,SVG_NS:R,init:function(a,k,r,e,b,l,g){var z=this.createElement("svg").attr({version:"1.1","class":"highcharts-root"});g||z.css(this.getStyle(e));e=z.element;a.appendChild(e);J(a,"dir","ltr");-1===a.innerHTML.indexOf("xmlns")&&J(e,"xmlns",this.SVG_NS);this.isSVG=!0;this.box=e;this.boxWrapper=z;this.alignedObjects=[];this.url=(u||G)&&I.getElementsByTagName("base").length?c.location.href.split("#")[0].replace(/<[^>]*>/g,"").replace(/([\('\)])/g,"\\$1").replace(/ /g,"%20"):"";this.createElement("desc").add().element.appendChild(I.createTextNode("Created with Highcharts 8.1.0")); +this.defs=this.createElement("defs").add();this.allowHTML=l;this.forExport=b;this.styledMode=g;this.gradients={};this.cache={};this.cacheKeys=[];this.imgCount=0;this.setSize(k,r,!1);var h;u&&a.getBoundingClientRect&&(k=function(){x(a,{left:0,top:0});h=a.getBoundingClientRect();x(a,{left:Math.ceil(h.left)-h.left+"px",top:Math.ceil(h.top)-h.top+"px"})},k(),this.unSubPixelFix=K(c,"resize",k))},definition:function(a){function c(a,k){var e;h(a).forEach(function(a){var b=r.createElement(a.tagName),l={}; +m(a,function(a,c){"tagName"!==c&&"children"!==c&&"textContent"!==c&&(l[c]=a)});b.attr(l);b.add(k||r.defs);a.textContent&&b.element.appendChild(I.createTextNode(a.textContent));c(a.children||[],b);e=b});return e}var r=this;return c(a)},getStyle:function(a){return this.style=C({fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif',fontSize:"12px"},a)},setStyle:function(a){this.boxWrapper.css(this.getStyle(a))},isHidden:function(){return!this.boxWrapper.getBBox().width},destroy:function(){var a= +this.defs;this.box=null;this.boxWrapper=this.boxWrapper.destroy();H(this.gradients||{});this.gradients=null;a&&(this.defs=a.destroy());this.unSubPixelFix&&this.unSubPixelFix();return this.alignedObjects=null},createElement:function(a){var c=new this.Element;c.init(this,a);return c},draw:q,getRadialAttr:function(a,c){return{cx:a[0]-a[2]/2+c.cx*a[2],cy:a[1]-a[2]/2+c.cy*a[2],r:c.r*a[2]}},truncate:function(a,c,r,e,b,l,g){var k=this,z=a.rotation,h,p=e?1:0,u=(r||e).length,P=u,m=[],v=function(a){c.firstChild&& +c.removeChild(c.firstChild);a&&c.appendChild(I.createTextNode(a))},y=function(l,z){z=z||l;if("undefined"===typeof m[z])if(c.getSubStringLength)try{m[z]=b+c.getSubStringLength(0,e?z+1:z)}catch(fa){""}else k.getSpanWidth&&(v(g(r||e,l)),m[z]=b+k.getSpanWidth(a,c));return m[z]},n;a.rotation=0;var U=y(c.textContent.length);if(n=b+U>l){for(;p<=u;)P=Math.ceil((p+u)/2),e&&(h=g(e,P)),U=y(P,h&&h.length-1),p===u?p=u+1:U>l?u=P-1:p=P;0===u?v(""):r&&u===r.length-1||v(h||g(r||e,P))}e&&e.splice(0,P);a.actualWidth= +U;a.rotation=z;return n},escapes:{"&":"&","<":"<",">":">","'":"'",'"':"""},buildText:function(a){var c=a.element,r=this,e=r.forExport,l=b(a.textStr,"").toString(),h=-1!==l.indexOf("<"),p=c.childNodes,u,v=J(c,"x"),y=a.styles,n=a.textWidth,O=y&&y.lineHeight,V=y&&y.textOutline,t=y&&"ellipsis"===y.textOverflow,G=y&&"nowrap"===y.whiteSpace,d=y&&y.fontSize,w,B=p.length;y=n&&!a.added&&this.box;var f=function(a){var k;r.styledMode||(k=/(px|em)$/.test(a&&a.style.fontSize)?a.style.fontSize: +d||r.style.fontSize||12);return O?g(O):r.fontMetrics(k,a.getAttribute("style")?a:c).h},N=function(a,c){m(r.escapes,function(k,r){c&&-1!==c.indexOf(k)||(a=a.toString().replace(new RegExp(k,"g"),r))});return a},C=function(a,c){var k=a.indexOf("<");a=a.substring(k,a.indexOf(">")-k);k=a.indexOf(c+"=");if(-1!==k&&(k=k+c.length+1,c=a.charAt(k),'"'===c||"'"===c))return a=a.substring(k+1),a.substring(0,a.indexOf(c))},D=//g;var q=[l,t,G,O,V,d,n].join();if(q!==a.textCache){for(a.textCache=q;B--;)c.removeChild(p[B]); +h||V||t||n||-1!==l.indexOf(" ")&&(!G||D.test(l))?(y&&y.appendChild(c),h?(l=r.styledMode?l.replace(/<(b|strong)>/g,'').replace(/<(i|em)>/g,''):l.replace(/<(b|strong)>/g,'').replace(/<(i|em)>/g,''),l=l.replace(//g,"").split(D)):l=[l],l=l.filter(function(a){return""!==a}),l.forEach(function(k,b){var l=0,g=0;k=k.replace(/^\s+|\s+$/g, +"").replace(//g,"|||");var z=k.split("|||");z.forEach(function(k){if(""!==k||1===z.length){var h={},p=I.createElementNS(r.SVG_NS,"tspan"),m,P;(m=C(k,"class"))&&J(p,"class",m);if(m=C(k,"style"))m=m.replace(/(;| |^)color([ :])/,"$1fill$2"),J(p,"style",m);(P=C(k,"href"))&&!e&&(J(p,"onclick",'location.href="'+P+'"'),J(p,"class","highcharts-anchor"),r.styledMode||x(p,{cursor:"pointer"}));k=N(k.replace(/<[a-zA-Z\/](.|\n)*?>/g,"")||" ");if(" "!==k){p.appendChild(I.createTextNode(k)); +l?h.dx=0:b&&null!==v&&(h.x=v);J(p,h);c.appendChild(p);!l&&w&&(!S&&e&&x(p,{display:"block"}),J(p,"dy",f(p)));if(n){var O=k.replace(/([^\^])-/g,"$1- ").split(" ");h=!G&&(1Math.abs(l.end-l.start-2*Math.PI));var z=Math.cos(k),u=Math.sin(k),m=Math.cos(p);p=Math.sin(p);k=b(l.longArc,.001>l.end-k-Math.PI?0:1);g=[["M",a+g*z,c+h*u],["A",g,h,0,k,b(l.clockwise,1),a+g*m,c+h*p]];F(r)&&g.push(e?["M",a+r*m,c+r*p]:["L",a+r*m,c+r*p],["A",r,r,0,k,F(l.clockwise)?1-l.clockwise:0,a+r*z,c+r*u]);e||g.push(["Z"]);return g},callout:function(a,c,r,e,b){var k=Math.min(b&&b.r||0,r,e),l=k+6,g= +b&&b.anchorX;b=b&&b.anchorY;var h=[["M",a+k,c],["L",a+r-k,c],["C",a+r,c,a+r,c,a+r,c+k],["L",a+r,c+e-k],["C",a+r,c+e,a+r,c+e,a+r-k,c+e],["L",a+k,c+e],["C",a,c+e,a,c+e,a,c+e-k],["L",a,c+k],["C",a,c,a,c,a+k,c]];g&&g>r?b>c+l&&bg?b>c+l&&be&&g>a+l&&gb&&g>a+l&&ga?a+3:Math.round(1.2*a);return{h:k, +b:Math.round(.8*k),f:a}},rotCorr:function(a,c,e){var k=a;c&&e&&(k=Math.max(k*Math.cos(c*l),4));return{x:-a/3*Math.sin(c*l),y:k}},pathToSegments:function(a){for(var c=[],e=[],b={A:8,C:7,H:2,L:3,M:3,Q:5,S:5,T:3,V:2},l=0;lthis.oldTextWidth)&&((u=this.textPxLength)||(M(t,{width:"",whiteSpace:p||"nowrap"}),u=t.offsetWidth),u=u>l);u&&(/[ \-]/.test(t.textContent||t.innerText)||"ellipsis"===t.style.textOverflow)?(M(t,{width:l+"px",display:"block",whiteSpace:p||"normal"}),this.oldTextWidth=l,this.hasBoxWidthChanged=!0):this.hasBoxWidthChanged=!1;I!==this.cTT&& +(p=n.fontMetrics(t.style.fontSize,t).b,!K(e)||e===(this.oldRotation||0)&&v===this.oldAlign||this.setSpanRotation(e,h,p),this.getSpanCorrection(!K(e)&&this.textPxLength||t.offsetWidth,p,h,e,v));M(t,{left:b+(this.xCorr||0)+"px",top:g+(this.yCorr||0)+"px"});this.cTT=I;this.oldRotation=e;this.oldAlign=v}}else this.alignOnAdd=!0},setSpanRotation:function(n,t,d){var m={},b=this.renderer.getTransformKey();m[b]=m.transform="rotate("+n+"deg)";m[b+(F?"Origin":"-origin")]=m.transformOrigin=100*t+"% "+d+"px"; +M(this.element,m)},getSpanCorrection:function(n,t,d){this.xCorr=-n*d;this.yCorr=-t}});J(f.prototype,{getTransformKey:function(){return H&&!/Edge/.test(w.navigator.userAgent)?"-ms-transform":C?"-webkit-transform":F?"MozTransform":w.opera?"-o-transform":""},html:function(n,t,d){var m=this.createElement("span"),b=m.element,g=m.renderer,v=g.isSVG,h=function(e,b){["opacity","visibility"].forEach(function(l){e[l+"Setter"]=function(g,h,p){var u=e.div?e.div.style:b;D.prototype[l+"Setter"].call(this,g,h,p); +u&&(u[h]=g)}});e.addedSetters=!0};m.textSetter=function(e){e!==b.innerHTML&&(delete this.bBox,delete this.oldTextWidth);this.textStr=e;b.innerHTML=L(e,"");m.doTransform=!0};v&&h(m,m.element.style);m.xSetter=m.ySetter=m.alignSetter=m.rotationSetter=function(e,b){"align"===b&&(b="textAlign");m[b]=e;m.doTransform=!0};m.afterSetters=function(){this.doTransform&&(this.htmlUpdateTransform(),this.doTransform=!1)};m.attr({text:n,x:Math.round(t),y:Math.round(d)}).css({position:"absolute"});g.styledMode||m.css({fontFamily:this.style.fontFamily, +fontSize:this.style.fontSize});b.style.whiteSpace="nowrap";m.css=m.htmlCss;v&&(m.add=function(e){var p=g.box.parentNode,l=[];if(this.parentGroup=e){var v=e.div;if(!v){for(;e;)l.push(e),e=e.parentGroup;l.reverse().forEach(function(e){function b(b,l){e[l]=b;"translateX"===l?u.left=b+"px":u.top=b+"px";e.doTransform=!0}var g=E(e.element,"class");v=e.div=e.div||q("div",g?{className:g}:void 0,{position:"absolute",left:(e.translateX||0)+"px",top:(e.translateY||0)+"px",display:e.display,opacity:e.opacity, +pointerEvents:e.styles&&e.styles.pointerEvents},v||p);var u=v.style;J(e,{classSetter:function(e){return function(b){this.element.setAttribute("class",b);e.className=b}}(v),on:function(){l[0].div&&m.on.apply({element:l[0].div},arguments);return e},translateXSetter:b,translateYSetter:b});e.addedSetters||h(e)})}}else v=p;v.appendChild(b);m.added=!0;m.alignOnAdd&&m.htmlUpdateTransform();return m});return m}})});Q(A,"parts/Tick.js",[A["parts/Globals.js"],A["parts/Utilities.js"]],function(d,f){var E=f.clamp, +q=f.correctFloat,M=f.defined,K=f.destroyObjectProperties,J=f.extend,L=f.fireEvent,x=f.isNumber,F=f.merge,H=f.objectEach,C=f.pick,D=d.deg2rad;f=function(){function d(n,t,d,m,b){this.isNewLabel=this.isNew=!0;this.axis=n;this.pos=t;this.type=d||"";this.parameters=b||{};this.tickmarkOffset=this.parameters.tickmarkOffset;this.options=this.parameters.options;L(this,"init");d||m||this.addLabel()}d.prototype.addLabel=function(){var n=this,t=n.axis,d=t.options,m=t.chart,b=t.categories,g=t.logarithmic,v=t.names, +h=n.pos,e=C(n.options&&n.options.labels,d.labels),p=t.tickPositions,l=h===p[0],I=h===p[p.length-1];v=this.parameters.category||(b?C(b[h],v[h],h):h);var u=n.label;b=(!e.step||1===e.step)&&1===t.tickInterval;p=p.info;var y,G;if(t.dateTime&&p){var f=m.time.resolveDTLFormat(d.dateTimeLabelFormats[!d.grid&&p.higherRanks[h]||p.unitName]);var w=f.main}n.isFirst=l;n.isLast=I;n.formatCtx={axis:t,chart:m,isFirst:l,isLast:I,dateTimeLabelFormat:w,tickPositionInfo:p,value:g?q(g.lin2log(v)):v,pos:h};d=t.labelFormatter.call(n.formatCtx, +this.formatCtx);if(G=f&&f.list)n.shortenLabel=function(){for(y=0;ye&&m-p*lg&&(G=Math.round((b-m)/Math.cos(e* +D)));else if(b=m+(1-p)*l,m-p*lg&&(u=g-n.x+u*p,y=-1),u=Math.min(I,u),uu||d.autoRotation&&(h.styles||{}).width)G=u;G&&(this.shortenLabel?this.shortenLabel():(w.width=Math.floor(G)+"px",(f.style||{}).textOverflow||(w.textOverflow="ellipsis"),h.css(w)))};d.prototype.moveLabel=function(n,d){var t=this,m=t.label,b=!1,g=t.axis,v=g.reversed,h=g.chart.inverted;m&&m.textStr===n?(t.movedLabel=m,b=!0,delete t.label):H(g.ticks, +function(e){b||e.isNew||e===t||!e.label||e.label.textStr!==n||(t.movedLabel=e.label,b=!0,e.labelPos=t.movedLabel.xy,delete e.label)});if(!b&&(t.labelPos||m)){var e=t.labelPos||m.xy;m=h?e.x:v?0:g.width+g.left;g=h?v?g.width+g.left:0:e.y;t.movedLabel=t.createLabel({x:m,y:g},n,d);t.movedLabel&&t.movedLabel.attr({opacity:0})}};d.prototype.render=function(n,d,f){var m=this.axis,b=m.horiz,g=this.pos,v=C(this.tickmarkOffset,m.tickmarkOffset);g=this.getPosition(b,g,v,d);v=g.x;var h=g.y;m=b&&v===m.pos+m.len|| +!b&&h===m.pos?-1:1;f=C(f,1);this.isActive=!0;this.renderGridLine(d,f,m);this.renderMark(g,f,m);this.renderLabel(g,d,f,n);this.isNew=!1;L(this,"afterRender")};d.prototype.renderGridLine=function(n,d,f){var m=this.axis,b=m.options,g=this.gridLine,v={},h=this.pos,e=this.type,p=C(this.tickmarkOffset,m.tickmarkOffset),l=m.chart.renderer,I=e?e+"Grid":"grid",u=b[I+"LineWidth"],y=b[I+"LineColor"];b=b[I+"LineDashStyle"];g||(m.chart.styledMode||(v.stroke=y,v["stroke-width"]=u,b&&(v.dashstyle=b)),e||(v.zIndex= +1),n&&(d=0),this.gridLine=g=l.path().attr(v).addClass("highcharts-"+(e?e+"-":"")+"grid-line").add(m.gridGroup));if(g&&(f=m.getPlotLinePath({value:h+p,lineWidth:g.strokeWidth()*f,force:"pass",old:n})))g[n||this.isNew?"attr":"animate"]({d:f,opacity:d})};d.prototype.renderMark=function(n,d,f){var m=this.axis,b=m.options,g=m.chart.renderer,v=this.type,h=v?v+"Tick":"tick",e=m.tickSize(h),p=this.mark,l=!p,I=n.x;n=n.y;var u=C(b[h+"Width"],!v&&m.isXAxis?1:0);b=b[h+"Color"];e&&(m.opposite&&(e[0]=-e[0]),l&& +(this.mark=p=g.path().addClass("highcharts-"+(v?v+"-":"")+"tick").add(m.axisGroup),m.chart.styledMode||p.attr({stroke:b,"stroke-width":u})),p[l?"attr":"animate"]({d:this.getMarkPath(I,n,e[0],p.strokeWidth()*f,m.horiz,g),opacity:d}))};d.prototype.renderLabel=function(n,d,f,m){var b=this.axis,g=b.horiz,v=b.options,h=this.label,e=v.labels,p=e.step;b=C(this.tickmarkOffset,b.tickmarkOffset);var l=!0,I=n.x;n=n.y;h&&x(I)&&(h.xy=n=this.getLabelPosition(I,n,h,g,e,b,m,p),this.isFirst&&!this.isLast&&!C(v.showFirstLabel, +1)||this.isLast&&!this.isFirst&&!C(v.showLastLabel,1)?l=!1:!g||e.step||e.rotation||d||0===f||this.handleOverflow(n),p&&m%p&&(l=!1),l&&x(n.y)?(n.opacity=f,h[this.isNewLabel?"attr":"animate"](n),this.isNewLabel=!1):(h.attr("y",-9999),this.isNewLabel=!0))};d.prototype.replaceMovedLabel=function(){var n=this.label,d=this.axis,f=d.reversed,m=this.axis.chart.inverted;if(n&&!this.isNew){var b=m?n.xy.x:f?d.left:d.width+d.left;f=m?f?d.width+d.top:d.top:n.xy.y;n.animate({x:b,y:f,opacity:0},void 0,n.destroy); +delete this.label}d.isDirty=!0;this.label=this.movedLabel;delete this.movedLabel};return d}();d.Tick=f;return d.Tick});Q(A,"parts/Time.js",[A["parts/Globals.js"],A["parts/Utilities.js"]],function(d,f){var E=f.defined,q=f.error,M=f.extend,K=f.isObject,J=f.merge,L=f.objectEach,x=f.pad,F=f.pick,H=f.splat,C=f.timeUnits,D=d.win;f=function(){function f(d){this.options={};this.variableTimezone=this.useUTC=!1;this.Date=D.Date;this.getTimezoneOffset=this.timezoneOffsetFunction();this.update(d)}f.prototype.get= +function(d,t){if(this.variableTimezone||this.timezoneOffset){var n=t.getTime(),m=n-this.getTimezoneOffset(t);t.setTime(m);d=t["getUTC"+d]();t.setTime(n);return d}return this.useUTC?t["getUTC"+d]():t["get"+d]()};f.prototype.set=function(d,t,f){if(this.variableTimezone||this.timezoneOffset){if("Milliseconds"===d||"Seconds"===d||"Minutes"===d)return t["setUTC"+d](f);var m=this.getTimezoneOffset(t);m=t.getTime()-m;t.setTime(m);t["setUTC"+d](f);d=this.getTimezoneOffset(t);m=t.getTime()+d;return t.setTime(m)}return this.useUTC? +t["setUTC"+d](f):t["set"+d](f)};f.prototype.update=function(d){var n=F(d&&d.useUTC,!0);this.options=d=J(!0,this.options||{},d);this.Date=d.Date||D.Date||Date;this.timezoneOffset=(this.useUTC=n)&&d.timezoneOffset;this.getTimezoneOffset=this.timezoneOffsetFunction();this.variableTimezone=!(n&&!d.getTimezoneOffset&&!d.timezone)};f.prototype.makeTime=function(n,f,w,m,b,g){if(this.useUTC){var v=this.Date.UTC.apply(0,arguments);var h=this.getTimezoneOffset(v);v+=h;var e=this.getTimezoneOffset(v);h!==e? +v+=e-h:h-36E5!==this.getTimezoneOffset(v-36E5)||d.isSafari||(v-=36E5)}else v=(new this.Date(n,f,F(w,1),F(m,0),F(b,0),F(g,0))).getTime();return v};f.prototype.timezoneOffsetFunction=function(){var d=this,f=this.options,w=D.moment;if(!this.useUTC)return function(m){return 6E4*(new Date(m.toString())).getTimezoneOffset()};if(f.timezone){if(w)return function(m){return 6E4*-w.tz(m,f.timezone).utcOffset()};q(25)}return this.useUTC&&f.getTimezoneOffset?function(m){return 6E4*f.getTimezoneOffset(m.valueOf())}: +function(){return 6E4*(d.timezoneOffset||0)}};f.prototype.dateFormat=function(n,f,w){var m;if(!E(f)||isNaN(f))return(null===(m=d.defaultOptions.lang)||void 0===m?void 0:m.invalidDate)||"";n=F(n,"%Y-%m-%d %H:%M:%S");var b=this;m=new this.Date(f);var g=this.get("Hours",m),v=this.get("Day",m),h=this.get("Date",m),e=this.get("Month",m),p=this.get("FullYear",m),l=d.defaultOptions.lang,I=null===l||void 0===l?void 0:l.weekdays,u=null===l||void 0===l?void 0:l.shortWeekdays;m=M({a:u?u[v]:I[v].substr(0,3), +A:I[v],d:x(h),e:x(h,2," "),w:v,b:l.shortMonths[e],B:l.months[e],m:x(e+1),o:e+1,y:p.toString().substr(2,2),Y:p,H:x(g),k:g,I:x(g%12||12),l:g%12||12,M:x(this.get("Minutes",m)),p:12>g?"AM":"PM",P:12>g?"am":"pm",S:x(m.getSeconds()),L:x(Math.floor(f%1E3),3)},d.dateFormats);L(m,function(e,l){for(;-1!==n.indexOf("%"+l);)n=n.replace("%"+l,"function"===typeof e?e.call(b,f):e)});return w?n.substr(0,1).toUpperCase()+n.substr(1):n};f.prototype.resolveDTLFormat=function(d){return K(d,!0)?d:(d=H(d),{main:d[0],from:d[1], +to:d[2]})};f.prototype.getTimeTicks=function(d,f,w,m){var b=this,g=[],v={};var h=new b.Date(f);var e=d.unitRange,p=d.count||1,l;m=F(m,1);if(E(f)){b.set("Milliseconds",h,e>=C.second?0:p*Math.floor(b.get("Milliseconds",h)/p));e>=C.second&&b.set("Seconds",h,e>=C.minute?0:p*Math.floor(b.get("Seconds",h)/p));e>=C.minute&&b.set("Minutes",h,e>=C.hour?0:p*Math.floor(b.get("Minutes",h)/p));e>=C.hour&&b.set("Hours",h,e>=C.day?0:p*Math.floor(b.get("Hours",h)/p));e>=C.day&&b.set("Date",h,e>=C.month?1:Math.max(1, +p*Math.floor(b.get("Date",h)/p)));if(e>=C.month){b.set("Month",h,e>=C.year?0:p*Math.floor(b.get("Month",h)/p));var n=b.get("FullYear",h)}e>=C.year&&b.set("FullYear",h,n-n%p);e===C.week&&(n=b.get("Day",h),b.set("Date",h,b.get("Date",h)-n+m+(n4*C.month||b.getTimezoneOffset(f)!==b.getTimezoneOffset(w));f=h.getTime();for(h=1;fg.length&&g.forEach(function(e){0===e%18E5&&"000000000"===b.dateFormat("%H%M%S%L",e)&&(v[e]="day")})}g.info=M(d,{higherRanks:v,totalRange:e*p});return g};f.defaultOptions={Date:void 0,getTimezoneOffset:void 0,timezone:void 0,timezoneOffset:0,useUTC:!0};return f}();d.Time=f;return d.Time});Q(A,"parts/Options.js",[A["parts/Globals.js"], +A["parts/Time.js"],A["parts/Color.js"],A["parts/Utilities.js"]],function(d,f,E,q){E=E.parse;var M=q.merge;d.defaultOptions={colors:"#7cb5ec #434348 #90ed7d #f7a35c #8085e9 #f15c80 #e4d354 #2b908f #f45b5b #91e8e1".split(" "),symbols:["circle","diamond","square","triangle","triangle-down"],lang:{loading:"Loading...",months:"January February March April May June July August September October November December".split(" "),shortMonths:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),weekdays:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "), +decimalPoint:".",numericSymbols:"kMGTPE".split(""),resetZoom:"Reset zoom",resetZoomTitle:"Reset zoom level 1:1",thousandsSep:" "},global:{},time:f.defaultOptions,chart:{styledMode:!1,borderRadius:0,colorCount:10,defaultSeriesType:"line",ignoreHiddenSeries:!0,spacing:[10,10,15,10],resetZoomButton:{theme:{zIndex:6},position:{align:"right",x:-10,y:10}},width:null,height:null,borderColor:"#335cad",backgroundColor:"#ffffff",plotBorderColor:"#cccccc"},title:{text:"Chart title",align:"center",margin:15, +widthAdjust:-44},subtitle:{text:"",align:"center",widthAdjust:-44},caption:{margin:15,text:"",align:"left",verticalAlign:"bottom"},plotOptions:{},labels:{style:{position:"absolute",color:"#333333"}},legend:{enabled:!0,align:"center",alignColumns:!0,layout:"horizontal",labelFormatter:function(){return this.name},borderColor:"#999999",borderRadius:0,navigation:{activeColor:"#003399",inactiveColor:"#cccccc"},itemStyle:{color:"#333333",cursor:"pointer",fontSize:"12px",fontWeight:"bold",textOverflow:"ellipsis"}, +itemHoverStyle:{color:"#000000"},itemHiddenStyle:{color:"#cccccc"},shadow:!1,itemCheckboxStyle:{position:"absolute",width:"13px",height:"13px"},squareSymbol:!0,symbolPadding:5,verticalAlign:"bottom",x:0,y:0,title:{style:{fontWeight:"bold"}}},loading:{labelStyle:{fontWeight:"bold",position:"relative",top:"45%"},style:{position:"absolute",backgroundColor:"#ffffff",opacity:.5,textAlign:"center"}},tooltip:{enabled:!0,animation:d.svg,borderRadius:3,dateTimeLabelFormats:{millisecond:"%A, %b %e, %H:%M:%S.%L", +second:"%A, %b %e, %H:%M:%S",minute:"%A, %b %e, %H:%M",hour:"%A, %b %e, %H:%M",day:"%A, %b %e, %Y",week:"Week from %A, %b %e, %Y",month:"%B %Y",year:"%Y"},footerFormat:"",padding:8,snap:d.isTouchDevice?25:10,headerFormat:'{point.key}
',pointFormat:'\u25cf {series.name}: {point.y}
',backgroundColor:E("#f7f7f7").setOpacity(.85).get(),borderWidth:1,shadow:!0,style:{color:"#333333",cursor:"default",fontSize:"12px", +whiteSpace:"nowrap"}},credits:{enabled:!0,href:"https://www.highcharts.com?credits",position:{align:"right",x:-10,verticalAlign:"bottom",y:-5},style:{cursor:"pointer",color:"#999999",fontSize:"9px"},text:"Highcharts.com"}};d.setOptions=function(f){d.defaultOptions=M(!0,d.defaultOptions,f);(f.time||f.global)&&d.time.update(M(d.defaultOptions.global,d.defaultOptions.time,f.global,f.time));return d.defaultOptions};d.getOptions=function(){return d.defaultOptions};d.defaultPlotOptions=d.defaultOptions.plotOptions; +d.time=new f(M(d.defaultOptions.global,d.defaultOptions.time));d.dateFormat=function(f,q,L){return d.time.dateFormat(f,q,L)};""});Q(A,"parts/Axis.js",[A["parts/Color.js"],A["parts/Globals.js"],A["parts/Tick.js"],A["parts/Utilities.js"]],function(d,f,E,q){var M=q.addEvent,K=q.animObject,J=q.arrayMax,L=q.arrayMin,x=q.clamp,F=q.correctFloat,H=q.defined,C=q.destroyObjectProperties,D=q.error,w=q.extend,n=q.fireEvent,t=q.format,N=q.getMagnitude,m=q.isArray,b=q.isFunction,g=q.isNumber,v=q.isString,h=q.merge, +e=q.normalizeTickInterval,p=q.objectEach,l=q.pick,I=q.relativeLength,u=q.removeEvent,y=q.splat,G=q.syncTimeout,S=f.defaultOptions,R=f.deg2rad;q=function(){function B(c,a){this.zoomEnabled=this.width=this.visible=this.userOptions=this.translationSlope=this.transB=this.transA=this.top=this.ticks=this.tickRotCorr=this.tickPositions=this.tickmarkOffset=this.tickInterval=this.tickAmount=this.side=this.series=this.right=this.positiveValuesOnly=this.pos=this.pointRangePadding=this.pointRange=this.plotLinesAndBandsGroups= +this.plotLinesAndBands=this.paddedTicks=this.overlap=this.options=this.oldMin=this.oldMax=this.offset=this.names=this.minPixelPadding=this.minorTicks=this.minorTickInterval=this.min=this.maxLabelLength=this.max=this.len=this.left=this.labelFormatter=this.labelEdge=this.isLinked=this.height=this.hasVisibleSeries=this.hasNames=this.coll=this.closestPointRange=this.chart=this.categories=this.bottom=this.alternateBands=void 0;this.init(c,a)}B.prototype.init=function(c,a){var k=a.isX,e=this;e.chart=c; +e.horiz=c.inverted&&!e.isZAxis?!k:k;e.isXAxis=k;e.coll=e.coll||(k?"xAxis":"yAxis");n(this,"init",{userOptions:a});e.opposite=a.opposite;e.side=a.side||(e.horiz?e.opposite?0:2:e.opposite?1:3);e.setOptions(a);var g=this.options,h=g.type;e.labelFormatter=g.labels.formatter||e.defaultLabelFormatter;e.userOptions=a;e.minPixelPadding=0;e.reversed=g.reversed;e.visible=!1!==g.visible;e.zoomEnabled=!1!==g.zoomEnabled;e.hasNames="category"===h||!0===g.categories;e.categories=g.categories||e.hasNames;e.names|| +(e.names=[],e.names.keys={});e.plotLinesAndBandsGroups={};e.positiveValuesOnly=!(!e.logarithmic||g.allowNegativeLog);e.isLinked=H(g.linkedTo);e.ticks={};e.labelEdge=[];e.minorTicks={};e.plotLinesAndBands=[];e.alternateBands={};e.len=0;e.minRange=e.userMinRange=g.minRange||g.maxZoom;e.range=g.range;e.offset=g.offset||0;e.max=null;e.min=null;e.crosshair=l(g.crosshair,y(c.options.tooltip.crosshairs)[k?0:1],!1);a=e.options.events;-1===c.axes.indexOf(e)&&(k?c.axes.splice(c.xAxis.length,0,e):c.axes.push(e), +c[e.coll].push(e));e.series=e.series||[];c.inverted&&!e.isZAxis&&k&&"undefined"===typeof e.reversed&&(e.reversed=!0);e.labelRotation=e.options.labels.rotation;p(a,function(a,c){b(a)&&M(e,c,a)});n(this,"afterInit")};B.prototype.setOptions=function(c){this.options=h(B.defaultOptions,"yAxis"===this.coll&&B.defaultYAxisOptions,[B.defaultTopAxisOptions,B.defaultRightAxisOptions,B.defaultBottomAxisOptions,B.defaultLeftAxisOptions][this.side],h(S[this.coll],c));n(this,"afterSetOptions",{userOptions:c})}; +B.prototype.defaultLabelFormatter=function(){var c=this.axis,a=this.value,k=c.chart.time,e=c.categories,b=this.dateTimeLabelFormat,l=S.lang,g=l.numericSymbols;l=l.numericSymbolMagnitude||1E3;var h=g&&g.length,p=c.options.labels.format;c=c.logarithmic?Math.abs(a):c.tickInterval;var m=this.chart,u=m.numberFormatter;if(p)var v=t(p,this,m);else if(e)v=a;else if(b)v=k.dateFormat(b,a);else if(h&&1E3<=c)for(;h--&&"undefined"===typeof v;)k=Math.pow(l,h+1),c>=k&&0===10*a%k&&null!==g[h]&&0!==a&&(v=u(a/k,-1)+ +g[h]);"undefined"===typeof v&&(v=1E4<=Math.abs(a)?u(a,-1):u(a,-1,void 0,""));return v};B.prototype.getSeriesExtremes=function(){var c=this,a=c.chart,k;n(this,"getSeriesExtremes",null,function(){c.hasVisibleSeries=!1;c.dataMin=c.dataMax=c.threshold=null;c.softThreshold=!c.isXAxis;c.stacking&&c.stacking.buildStacks();c.series.forEach(function(e){if(e.visible||!a.options.chart.ignoreHiddenSeries){var b=e.options,r=b.threshold;c.hasVisibleSeries=!0;c.positiveValuesOnly&&0>=r&&(r=null);if(c.isXAxis){if(b= +e.xData,b.length){k=e.getXExtremes(b);var h=k.min;var p=k.max;g(h)||h instanceof Date||(b=b.filter(g),k=e.getXExtremes(b),h=k.min,p=k.max);b.length&&(c.dataMin=Math.min(l(c.dataMin,h),h),c.dataMax=Math.max(l(c.dataMax,p),p))}}else if(e=e.applyExtremes(),g(e.dataMin)&&(h=e.dataMin,c.dataMin=Math.min(l(c.dataMin,h),h)),g(e.dataMax)&&(p=e.dataMax,c.dataMax=Math.max(l(c.dataMax,p),p)),H(r)&&(c.threshold=r),!b.softThreshold||c.positiveValuesOnly)c.softThreshold=!1}})});n(this,"afterGetSeriesExtremes")}; +B.prototype.translate=function(c,a,k,e,b,l){var r=this.linkedParent||this,h=1,p=0,z=e?r.oldTransA:r.transA;e=e?r.oldMin:r.min;var m=r.minPixelPadding;b=(r.isOrdinal||r.brokenAxis&&r.brokenAxis.hasBreaks||r.logarithmic&&b)&&r.lin2val;z||(z=r.transA);k&&(h*=-1,p=r.len);r.reversed&&(h*=-1,p-=h*(r.sector||r.len));a?(c=(c*h+p-m)/z+e,b&&(c=r.lin2val(c))):(b&&(c=r.val2lin(c)),c=g(e)?h*(c-e)*z+p+h*m+(g(l)?z*l:0):void 0);return c};B.prototype.toPixels=function(c,a){return this.translate(c,!1,!this.horiz,null, +!0)+(a?0:this.pos)};B.prototype.toValue=function(c,a){return this.translate(c-(a?0:this.pos),!0,!this.horiz,null,!0)};B.prototype.getPlotLinePath=function(c){function a(a,c,k){if("pass"!==d&&ak)d?a=x(a,c,k):B=!0;return a}var k=this,e=k.chart,b=k.left,h=k.top,p=c.old,m=c.value,u=c.translatedValue,v=c.lineWidth,d=c.force,y,O,f,I,G=p&&e.oldChartHeight||e.chartHeight,t=p&&e.oldChartWidth||e.chartWidth,B,w=k.transB;c={value:m,lineWidth:v,old:p,force:d,acrossPanes:c.acrossPanes,translatedValue:u}; +n(this,"getPlotLinePath",c,function(c){u=l(u,k.translate(m,null,null,p));u=x(u,-1E5,1E5);y=f=Math.round(u+w);O=I=Math.round(G-u-w);g(u)?k.horiz?(O=h,I=G-k.bottom,y=f=a(y,b,b+k.width)):(y=b,f=t-k.right,O=I=a(O,h,h+k.height)):(B=!0,d=!1);c.path=B&&!d?null:e.renderer.crispLine([["M",y,O],["L",f,I]],v||1)});return c.path};B.prototype.getLinearTickPositions=function(c,a,k){var e=F(Math.floor(a/c)*c);k=F(Math.ceil(k/c)*c);var b=[],l;F(e+c)===e&&(l=20);if(this.single)return[a];for(a=e;a<=k;){b.push(a);a= +F(a+c,l);if(a===g)break;var g=a}return b};B.prototype.getMinorTickInterval=function(){var c=this.options;return!0===c.minorTicks?l(c.minorTickInterval,"auto"):!1===c.minorTicks?null:c.minorTickInterval};B.prototype.getMinorTickPositions=function(){var c=this.options,a=this.tickPositions,k=this.minorTickInterval,e=[],b=this.pointRangePadding||0,l=this.min-b;b=this.max+b;var g=b-l;if(g&&g/k=this.minRange;var v=this.minRange;var d=(v-k+a)/2;d=[a-d,l(c.min,a-d)];m&&(d[2]=this.logarithmic?this.logarithmic.log2lin(this.dataMin):this.dataMin);a=J(d);k=[a+v,l(c.max,a+v)];m&&(k[2]=e?e.log2lin(this.dataMax):this.dataMax);k=L(k);k-a=O)B=O,v=0;else if(a.dataMax<=O){var w=O;u=0}a.min= +l(G,B,a.dataMin);a.max=l(t,w,a.dataMax)}b&&(a.positiveValuesOnly&&!c&&0>=Math.min(a.min,l(a.dataMin,a.min))&&D(10,1,k),a.min=F(b.log2lin(a.min),16),a.max=F(b.log2lin(a.max),16));a.range&&H(a.max)&&(a.userMin=a.min=G=Math.max(a.dataMin,a.minFromRange()),a.userMax=t=a.max,a.range=null);n(a,"foundExtremes");a.beforePadding&&a.beforePadding();a.adjustForMinRange();!(f||a.axisPointRange||a.stacking&&a.stacking.usePercentage||m)&&H(a.min)&&H(a.max)&&(k=a.max-a.min)&&(!H(G)&&v&&(a.min-=k*v),!H(t)&&u&&(a.max+= +k*u));g(a.userMin)||(g(h.softMin)&&h.softMina.max&&(a.max=t=h.softMax),g(h.ceiling)&&(a.max=Math.min(a.max,h.ceiling)));I&&H(a.dataMin)&&(O=O||0,!H(G)&&a.min=O?a.min=a.options.minRange?Math.min(O,a.max-a.minRange):O:!H(t)&&a.max>O&&a.dataMax<=O&&(a.max=a.options.minRange?Math.max(O,a.min+a.minRange):O));a.tickInterval=a.min===a.max||"undefined"===typeof a.min||"undefined"=== +typeof a.max?1:m&&!d&&y===a.linkedParent.options.tickPixelInterval?d=a.linkedParent.tickInterval:l(d,this.tickAmount?(a.max-a.min)/Math.max(this.tickAmount-1,1):void 0,f?1:(a.max-a.min)*y/Math.max(a.len,y));p&&!c&&a.series.forEach(function(c){c.processData(a.min!==a.oldMin||a.max!==a.oldMax)});a.setAxisTranslation(!0);a.beforeSetTickPositions&&a.beforeSetTickPositions();a.ordinal&&(a.tickInterval=a.ordinal.postProcessTickInterval(a.tickInterval));a.pointRange&&!d&&(a.tickInterval=Math.max(a.pointRange, +a.tickInterval));c=l(h.minTickInterval,a.dateTime&&a.closestPointRange);!d&&a.tickIntervala.tickInterval||void 0!==this.tickAmount),!!this.tickAmount));this.tickAmount||(a.tickInterval=a.unsquish());this.setTickPositions()};B.prototype.setTickPositions=function(){var c=this.options,a=c.tickPositions;var e=this.getMinorTickInterval();var b=c.tickPositioner,l=this.hasVerticalPanning(), +g="colorAxis"===this.coll,h=(g||!l)&&c.startOnTick;l=(g||!l)&&c.endOnTick;this.tickmarkOffset=this.categories&&"between"===c.tickmarkPlacement&&1===this.tickInterval?.5:0;this.minorTickInterval="auto"===e&&this.tickInterval?this.tickInterval/5:e;this.single=this.min===this.max&&H(this.min)&&!this.tickAmount&&(parseInt(this.min,10)===this.min||!1!==c.allowDecimals);this.tickPositions=e=a&&a.slice();!e&&(this.ordinal&&this.ordinal.positions||!((this.max-this.min)/this.tickInterval>Math.max(2*this.len, +200))?e=this.dateTime?this.getTimeTicks(this.dateTime.normalizeTimeTickInterval(this.tickInterval,c.units),this.min,this.max,c.startOfWeek,this.ordinal&&this.ordinal.positions,this.closestPointRange,!0):this.logarithmic?this.logarithmic.getLogTickPositions(this.tickInterval,this.min,this.max):this.getLinearTickPositions(this.tickInterval,this.min,this.max):(e=[this.min,this.max],D(19,!1,this.chart)),e.length>this.len&&(e=[e[0],e.pop()],e[0]===e[1]&&(e.length=1)),this.tickPositions=e,b&&(b=b.apply(this, +[this.min,this.max])))&&(this.tickPositions=e=b);this.paddedTicks=e.slice(0);this.trimTicks(e,h,l);this.isLinked||(this.single&&2>e.length&&!this.categories&&!this.series.some(function(a){return a.is("heatmap")&&"between"===a.options.pointPlacement})&&(this.min-=.5,this.max+=.5),a||b||this.adjustTickAmount());n(this,"afterSetTickPositions")};B.prototype.trimTicks=function(c,a,e){var k=c[0],b=c[c.length-1],l=!this.isOrdinal&&this.minPointOffset||0;n(this,"trimTicks");if(!this.isLinked){if(a&&-Infinity!== +k)this.min=k;else for(;this.min-l>c[0];)c.shift();if(e)this.max=b;else for(;this.max+la&&(this.finalTickAmt=a,a=5);this.tickAmount=a};B.prototype.adjustTickAmount=function(){var c=this.options,a=this.tickInterval,e=this.tickPositions,b=this.tickAmount,g=this.finalTickAmt,h=e&&e.length,p=l(this.threshold,this.softThreshold? +0:null),m;if(this.hasData()){if(hb&&(this.tickInterval*=2,this.setTickPositions());if(H(g)){for(a=c=e.length;a--;)(3===g&&1===a%2||2>=g&&0m&&(c=m)),H(g)&&(km&&(k=m))),e.displayBtn="undefined"!==typeof c||"undefined"!==typeof k,e.setExtremes(c,k,!1,void 0,{trigger:"zoom"});a.zoomed=!0});return c.zoomed};B.prototype.setAxisSize=function(){var c=this.chart,a=this.options,e=a.offsets||[0,0,0,0],b=this.horiz,g=this.width=Math.round(I(l(a.width, +c.plotWidth-e[3]+e[1]),c.plotWidth)),h=this.height=Math.round(I(l(a.height,c.plotHeight-e[0]+e[2]),c.plotHeight)),p=this.top=Math.round(I(l(a.top,c.plotTop+e[0]),c.plotHeight,c.plotTop));a=this.left=Math.round(I(l(a.left,c.plotLeft+e[3]),c.plotWidth,c.plotLeft));this.bottom=c.chartHeight-h-p;this.right=c.chartWidth-g-a;this.len=Math.max(b?g:h,0);this.pos=b?a:p};B.prototype.getExtremes=function(){var c=this.logarithmic;return{min:c?F(c.lin2log(this.min)):this.min,max:c?F(c.lin2log(this.max)):this.max, +dataMin:this.dataMin,dataMax:this.dataMax,userMin:this.userMin,userMax:this.userMax}};B.prototype.getThreshold=function(c){var a=this.logarithmic,e=a?a.lin2log(this.min):this.min;a=a?a.lin2log(this.max):this.max;null===c||-Infinity===c?c=e:Infinity===c?c=a:e>c?c=e:aa?c.align="right":195a&&(c.align="left")}); +return c.align};B.prototype.tickSize=function(c){var a=this.options,e=a["tick"===c?"tickLength":"minorTickLength"],b=l(a["tick"===c?"tickWidth":"minorTickWidth"],"tick"===c&&this.isXAxis&&!this.categories?1:0);if(b&&e){"inside"===a[c+"Position"]&&(e=-e);var g=[e,b]}c={tickSize:g};n(this,"afterTickSize",c);return c.tickSize};B.prototype.labelMetrics=function(){var c=this.tickPositions&&this.tickPositions[0]||0;return this.chart.renderer.fontMetrics(this.options.labels.style&&this.options.labels.style.fontSize, +this.ticks[c]&&this.ticks[c].label)};B.prototype.unsquish=function(){var c=this.options.labels,a=this.horiz,e=this.tickInterval,b=e,g=this.len/(((this.categories?1:0)+this.max-this.min)/e),h,p=c.rotation,m=this.labelMetrics(),u,v=Number.MAX_VALUE,d,y=this.max-this.min,f=function(a){var c=a/(g||1);c=1y&&Infinity!==a&&Infinity!==g&&y&&(c=Math.ceil(y/e));return F(c*e)};a?(d=!c.staggerLines&&!c.step&&(H(p)?[p]:g=a){u=f(Math.abs(m.h/Math.sin(R*a)));var c=u+Math.abs(a/360);c(l.step||0))return l.rotation?0:(this.staggerLines||1)*this.len/h;if(!b){c=null===(a=null===l||void 0===l?void 0: +l.style)||void 0===a?void 0:a.width;if(void 0!==c)return parseInt(c,10);if(p)return p-e.spacing[3]}return.33*e.chartWidth};B.prototype.renderUnsquish=function(){var c=this.chart,a=c.renderer,e=this.tickPositions,b=this.ticks,l=this.options.labels,g=l&&l.style||{},h=this.horiz,p=this.getSlotWidth(),m=Math.max(1,Math.round(p-2*(l.padding||5))),u={},d=this.labelMetrics(),y=l.style&&l.style.textOverflow,f=0;v(l.rotation)||(u.rotation=l.rotation||0);e.forEach(function(a){a=b[a];a.movedLabel&&a.replaceMovedLabel(); +a&&a.label&&a.label.textPxLength>f&&(f=a.label.textPxLength)});this.maxLabelLength=f;if(this.autoRotation)f>m&&f>d.h?u.rotation=this.labelRotation:this.labelRotation=0;else if(p){var n=m;if(!y){var I="clip";for(m=e.length;!h&&m--;){var G=e[m];if(G=b[G].label)G.styles&&"ellipsis"===G.styles.textOverflow?G.css({textOverflow:"clip"}):G.textPxLength>p&&G.css({width:p+"px"}),G.getBBox().height>this.len/e.length-(d.h-d.f)&&(G.specificTextOverflow="ellipsis")}}}u.rotation&&(n=f>.5*c.chartHeight?.33*c.chartHeight: +f,y||(I="ellipsis"));if(this.labelAlign=l.align||this.autoLabelAlign(this.labelRotation))u.align=this.labelAlign;e.forEach(function(a){var c=(a=b[a])&&a.label,e=g.width,k={};c&&(c.attr(u),a.shortenLabel?a.shortenLabel():n&&!e&&"nowrap"!==g.whiteSpace&&(n=this.min&&c<=this.max)b[c]||(b[c]=new E(this,c)),l&&b[c].isNew&&b[c].render(a,!0,-1),b[c].render(a)};B.prototype.render=function(){var c=this,a=c.chart,e=c.logarithmic,b=c.options,l=c.isLinked,h=c.tickPositions,m=c.axisTitle,u=c.ticks,d=c.minorTicks,v=c.alternateBands,y=b.stackLabels,I=b.alternateGridColor, +O=c.tickmarkOffset,t=c.axisLine,B=c.showAxis,w=K(a.renderer.globalAnimation),S,R;c.labelEdge.length=0;c.overlap=!1;[u,d,v].forEach(function(a){p(a,function(a){a.isActive=!1})});if(c.hasData()||l)c.minorTickInterval&&!c.categories&&c.getMinorTickPositions().forEach(function(a){c.renderMinorTick(a)}),h.length&&(h.forEach(function(a,e){c.renderTick(a,e)}),O&&(0===c.min||c.single)&&(u[-1]||(u[-1]=new E(c,-1,null,!0)),u[-1].render(-1))),I&&h.forEach(function(k,b){R="undefined"!==typeof h[b+1]?h[b+1]+O: +c.max-O;0===b%2&&kf&&(!C||v<=H)&&"undefined"!==typeof v&&t.push(v);v>H&&(m=!0);var v=g}}}else f=this.lin2log(f),H=this.lin2log(H),d=C?x.getMinorTickInterval():n.tickInterval,d=K("auto"===d?null:d,this.minorAutoInterval,n.tickPixelInterval/(C?5:1)*(H-f)/((C?w/x.tickPositions.length:w)||1)),d=M(d,void 0,q(d)),t=x.getLinearTickPositions(d,f,H).map(this.log2lin), +C||(this.minorAutoInterval=d/5);C||(x.tickInterval=d);return t};d.prototype.lin2log=function(d){return Math.pow(10,d)};d.prototype.log2lin=function(d){return Math.log(d)/Math.LN10};return d}();f=function(){function d(){}d.compose=function(d){d.keepProps.push("logarithmic");var f=d.prototype,x=J.prototype;f.log2lin=x.log2lin;f.lin2log=x.lin2log;E(d,"init",function(d){var f=this.logarithmic;"logarithmic"!==d.userOptions.type?this.logarithmic=void 0:(f||(f=this.logarithmic=new J(this)),this.log2lin!== +f.log2lin&&(f.log2lin=this.log2lin.bind(this)),this.lin2log!==f.lin2log&&(f.lin2log=this.lin2log.bind(this)))});E(d,"afterInit",function(){var d=this.logarithmic;d&&(this.lin2val=function(f){return d.lin2log(f)},this.val2lin=function(f){return d.log2lin(f)})})};return d}();f.compose(d);return f});Q(A,"parts/PlotLineOrBand.js",[A["parts/Globals.js"],A["parts/Axis.js"],A["parts/Utilities.js"]],function(d,f,E){var q=E.arrayMax,M=E.arrayMin,K=E.defined,J=E.destroyObjectProperties,L=E.erase,x=E.extend, +F=E.merge,H=E.objectEach,C=E.pick,D=function(){function f(d,f){this.axis=d;f&&(this.options=f,this.id=f.id)}f.prototype.render=function(){d.fireEvent(this,"render");var f=this,t=f.axis,w=t.horiz,m=t.logarithmic,b=f.options,g=b.label,v=f.label,h=b.to,e=b.from,p=b.value,l=K(e)&&K(h),I=K(p),u=f.svgElem,y=!u,G=[],S=b.color,R=C(b.zIndex,0),B=b.events;G={"class":"highcharts-plot-"+(l?"band ":"line ")+(b.className||"")};var c={},a=t.chart.renderer,k=l?"bands":"lines";m&&(e=m.log2lin(e),h=m.log2lin(h),p= +m.log2lin(p));t.chart.styledMode||(I?(G.stroke=S||"#999999",G["stroke-width"]=C(b.width,1),b.dashStyle&&(G.dashstyle=b.dashStyle)):l&&(G.fill=S||"#e6ebf5",b.borderWidth&&(G.stroke=b.borderColor,G["stroke-width"]=b.borderWidth)));c.zIndex=R;k+="-"+R;(m=t.plotLinesAndBandsGroups[k])||(t.plotLinesAndBandsGroups[k]=m=a.g("plot-"+k).attr(c).add());y&&(f.svgElem=u=a.path().attr(G).add(m));if(I)G=t.getPlotLinePath({value:p,lineWidth:u.strokeWidth(),acrossPanes:b.acrossPanes});else if(l)G=t.getPlotBandPath(e, +h,b);else return;(y||!u.d)&&G&&G.length?(u.attr({d:G}),B&&H(B,function(a,c){u.on(c,function(a){B[c].apply(f,[a])})})):u&&(G?(u.show(!0),u.animate({d:G})):u.d&&(u.hide(),v&&(f.label=v=v.destroy())));g&&(K(g.text)||K(g.formatter))&&G&&G.length&&0this.max&&f>this.max;if(w&&n){if(d){var v=w.toString()===n.toString();g=0}for(d=0;db){f=u;break}if(m[f]&&l.substr(m[f])!=="01-01 00:00:00.000".substr(m[f]))break;"week"!==f&&(u=f)}if(f)var v=g.resolveDTLFormat(e[f]).main;return v};b.prototype.getLabel=function(){var b,m,h=this,e=this.chart.renderer,p=this.chart.styledMode,l=this.options,f="tooltip"+(M(l.className)?" "+l.className:""),u=(null===(b=l.style)||void 0===b?void 0:b.pointerEvents)||(!this.followPointer&& +l.stickOnContact?"auto":"none"),y;b=function(){h.inContact=!0};var G=function(){var e=h.chart.hoverSeries;h.inContact=!1;if(e&&e.onMouseOut)e.onMouseOut()};if(!this.label){this.outside&&(this.container=y=d.doc.createElement("div"),y.className="highcharts-tooltip-container",q(y,{position:"absolute",top:"1px",pointerEvents:u,zIndex:3}),d.doc.body.appendChild(y),this.renderer=e=new d.Renderer(y,0,0,null===(m=this.chart.options.chart)||void 0===m?void 0:m.style,void 0,void 0,e.styledMode));this.split? +this.label=e.g(f):(this.label=e.label("",0,0,l.shape||"callout",null,null,l.useHTML,null,f).attr({padding:l.padding,r:l.borderRadius}),p||this.label.attr({fill:l.backgroundColor,"stroke-width":l.borderWidth}).css(l.style).css({pointerEvents:u}).shadow(l.shadow));p&&(this.applyFilter(),this.label.addClass("highcharts-tooltip-"+this.chart.index));if(h.outside&&!h.split){var n={x:this.label.xSetter,y:this.label.ySetter};this.label.xSetter=function(e,b){n[b].call(this.label,h.distance);y.style.left=e+ +"px"};this.label.ySetter=function(e,b){n[b].call(this.label,h.distance);y.style.top=e+"px"}}this.label.on("mouseenter",b).on("mouseleave",G).attr({zIndex:8}).add()}return this.label};b.prototype.getPosition=function(b,d,h){var e=this.chart,g=this.distance,l={},m=e.inverted&&h.h||0,u,f=this.outside,v=f?N.documentElement.clientWidth-2*g:e.chartWidth,n=f?Math.max(N.body.scrollHeight,N.documentElement.scrollHeight,N.body.offsetHeight,N.documentElement.offsetHeight,N.documentElement.clientHeight):e.chartHeight, +t=e.pointer.getChartPosition(),B=e.containerScaling,c=function(a){return B?a*B.scaleX:a},a=function(a){return B?a*B.scaleY:a},k=function(k){var l="x"===k;return[k,l?v:n,l?b:d].concat(f?[l?c(b):a(d),l?t.left-g+c(h.plotX+e.plotLeft):t.top-g+a(h.plotY+e.plotTop),0,l?v:n]:[l?b:d,l?h.plotX+e.plotLeft:h.plotY+e.plotTop,l?e.plotLeft:e.plotTop,l?e.plotLeft+e.plotWidth:e.plotTop+e.plotHeight])},r=k("y"),z=k("x"),w=!this.followPointer&&D(h.ttBelow,!e.inverted===!!h.negative),x=function(e,b,k,h,p,r,d){var u= +"y"===e?a(g):c(g),f=(k-h)/2,v=hz-m?z:z-m);else if(y)l[e]=Math.max(r,p+m+k>b?p:p+m);else return!1},C=function(a,c,e,b,k){var h;kc-g?h=!1:l[a]=kc-b/2?c-b-2:k-e/2;return h},q=function(a){var c=r;r=z;z=c;u=a},T=function(){!1!==x.apply(0,r)?!1!==C.apply(0,z)||u||(q(!0),T()):u?l.x=l.y=0:(q(!0),T())};(e.inverted||1=a+v&&O.pos+G<=a+v+f-B&&(I=O.pos+G);n=E(n,x.left-r,x.right+r);"number"===typeof I?(y=y.height+1,G=P?P.call(e,d,y,l):g(n,I,h,d),c.push({align:P?0:void 0,anchorX:n,anchorY:I,boxWidth:d,point:l,rank:D(G.rank,h?1:0),size:y,target:G.y,tt:b,x:G.x})):b.isActive=!1}return c},[]);!P&&b.some(function(a){return a.xh[0]?Math.max(Math.abs(h[0]),p.width-h[0]):Math.max(Math.abs(h[0]),p.width);e.height=0>h[1]?Math.max(Math.abs(h[1]),p.height-Math.abs(h[1])):Math.max(Math.abs(h[1]),p.height);this.tracker?this.tracker.attr(e): +(this.tracker=d.renderer.rect(e).addClass("highcharts-tracker").add(d),b.styledMode||this.tracker.attr({fill:"rgba(0,0,0,0)"}))}}};b.prototype.styledModeFormat=function(b){return b.replace('style="font-size: 10px"','class="highcharts-header"').replace(/style="color:{(point|series)\.color}"/g,'class="highcharts-color-{$1.colorIndex}"')};b.prototype.tooltipFooterHeaderFormatter=function(b,d){var h=d?"footer":"header",e=b.series,g=e.tooltipOptions,l=g.xDateFormat,m=e.xAxis,u=m&&"datetime"===m.options.type&& +F(b.key),f=g[h+"Format"];d={isFooter:d,labelConfig:b};L(this,"headerFormatter",d,function(h){u&&!l&&(l=this.getXDateFormat(b,g,m));u&&l&&(b.point&&b.point.tooltipDateKeys||["key"]).forEach(function(e){f=f.replace("{point."+e+"}","{point."+e+":"+l+"}")});e.chart.styledMode&&(f=this.styledModeFormat(f));h.text=x(f,{point:b,series:e},this.chart)});return d.text};b.prototype.update=function(b){this.destroy();C(!0,this.chart.options.tooltip.userOptions,b);this.init(this.chart,C(!0,this.options,b))};b.prototype.updatePosition= +function(b){var g=this.chart,h=g.pointer,e=this.getLabel(),d=b.plotX+g.plotLeft,l=b.plotY+g.plotTop;h=h.getChartPosition();b=(this.options.positioner||this.getPosition).call(this,e.width,e.height,b);if(this.outside){var m=(this.options.borderWidth||0)+2*this.distance;this.renderer.setSize(e.width+m,e.height+m,!1);if(g=g.containerScaling)q(this.container,{transform:"scale("+g.scaleX+", "+g.scaleY+")"}),d*=g.scaleX,l*=g.scaleY;d+=h.left-b.x;l+=h.top-b.y}this.move(Math.round(b.x),Math.round(b.y||0), +d,l)};return b}();d.Tooltip=m;return d.Tooltip});Q(A,"parts/Pointer.js",[A["parts/Globals.js"],A["parts/Utilities.js"],A["parts/Tooltip.js"],A["parts/Color.js"]],function(d,f,E,q){var M=f.addEvent,K=f.attr,J=f.css,L=f.defined,x=f.extend,F=f.find,H=f.fireEvent,C=f.isNumber,D=f.isObject,w=f.objectEach,n=f.offset,t=f.pick,N=f.splat,m=q.parse,b=d.charts,g=d.noop;f=function(){function f(b,e){this.lastValidTouch={};this.pinchDown=[];this.runChartClick=!1;this.chart=b;this.hasDragged=!1;this.options=e;this.unbindContainerMouseLeave= +function(){};this.init(b,e)}f.prototype.applyInactiveState=function(b){var e=[],h;(b||[]).forEach(function(b){h=b.series;e.push(h);h.linkedParent&&e.push(h.linkedParent);h.linkedSeries&&(e=e.concat(h.linkedSeries));h.navigatorSeries&&e.push(h.navigatorSeries)});this.chart.series.forEach(function(b){-1===e.indexOf(b)?b.setState("inactive",!0):b.options.inactiveOtherPoints&&b.setAllPointsToState("inactive")})};f.prototype.destroy=function(){var b=this;"undefined"!==typeof b.unDocMouseMove&&b.unDocMouseMove(); +this.unbindContainerMouseLeave();d.chartCount||(d.unbindDocumentMouseUp&&(d.unbindDocumentMouseUp=d.unbindDocumentMouseUp()),d.unbindDocumentTouchEnd&&(d.unbindDocumentTouchEnd=d.unbindDocumentTouchEnd()));clearInterval(b.tooltipTimeout);w(b,function(e,h){b[h]=null})};f.prototype.drag=function(b){var e=this.chart,h=e.options.chart,l=b.chartX,g=b.chartY,d=this.zoomHor,f=this.zoomVert,v=e.plotLeft,n=e.plotTop,t=e.plotWidth,B=e.plotHeight,c=this.selectionMarker,a=this.mouseDownX||0,k=this.mouseDownY|| +0,r=D(h.panning)?h.panning&&h.panning.enabled:h.panning,z=h.panKey&&b[h.panKey+"Key"];if(!c||!c.touch)if(lv+t&&(l=v+t),gn+B&&(g=n+B),this.hasDragged=Math.sqrt(Math.pow(a-l,2)+Math.pow(k-g,2)),10b.options.findNearestPointBy.indexOf("y");b=b.searchPoint(g,l);if((l=D(b,!0))&&!(l=!D(d,!0))){l=d.distX-b.distX;var h=d.dist-b.dist,p=(b.series.group&& +b.series.group.zIndex)-(d.series.group&&d.series.group.zIndex);l=0<(0!==l&&e?l:0!==h?h:0!==p?p:d.series.index>b.series.index?-1:1)}l&&(d=b)});return d};f.prototype.getChartCoordinatesFromPoint=function(b,e){var h=b.series,l=h.xAxis;h=h.yAxis;var g=t(b.clientX,b.plotX),d=b.shapeArgs;if(l&&h)return e?{chartX:l.len+l.pos-g,chartY:h.len+h.pos-b.plotY}:{chartX:g+l.pos,chartY:b.plotY+h.pos};if(d&&d.x&&d.y)return{chartX:d.x,chartY:d.y}};f.prototype.getChartPosition=function(){return this.chartPosition|| +(this.chartPosition=n(this.chart.container))};f.prototype.getCoordinates=function(b){var e={xAxis:[],yAxis:[]};this.chart.axes.forEach(function(h){e[h.isXAxis?"xAxis":"yAxis"].push({axis:h,value:h.toValue(b[h.horiz?"chartX":"chartY"])})});return e};f.prototype.getHoverData=function(b,e,g,l,d,m){var h,p=[];l=!(!l||!b);var f=e&&!e.stickyTracking,u={chartX:m?m.chartX:void 0,chartY:m?m.chartY:void 0,shared:d};H(this,"beforeGetHoverData",u);f=f?[e]:g.filter(function(e){return u.filter?u.filter(e):e.visible&& +!(!d&&e.directTouch)&&t(e.options.enableMouseTracking,!0)&&e.stickyTracking});e=(h=l||!m?b:this.findNearestKDPoint(f,d,m))&&h.series;h&&(d&&!e.noSharedTooltip?(f=g.filter(function(e){return u.filter?u.filter(e):e.visible&&!(!d&&e.directTouch)&&t(e.options.enableMouseTracking,!0)&&!e.noSharedTooltip}),f.forEach(function(e){var c=F(e.points,function(a){return a.x===h.x&&!a.isNull});D(c)&&(e.chart.isBoosting&&(c=e.getPoint(c)),p.push(c))})):p.push(h));u={hoverPoint:h};H(this,"afterGetHoverData",u);return{hoverPoint:u.hoverPoint, +hoverSeries:e,hoverPoints:p}};f.prototype.getPointFromEvent=function(b){b=b.target;for(var e;b&&!e;)e=b.point,b=b.parentNode;return e};f.prototype.onTrackerMouseOut=function(b){b=b.relatedTarget||b.toElement;var e=this.chart.hoverSeries;this.isDirectTouch=!1;if(!(!e||!b||e.stickyTracking||this.inClass(b,"highcharts-tooltip")||this.inClass(b,"highcharts-series-"+e.index)&&this.inClass(b,"highcharts-tracker")))e.onMouseOut()};f.prototype.inClass=function(b,e){for(var g;b;){if(g=K(b,"class")){if(-1!== +g.indexOf(e))return!0;if(-1!==g.indexOf("highcharts-container"))return!1}b=b.parentNode}};f.prototype.init=function(b,e){this.options=e;this.chart=b;this.runChartClick=e.chart.events&&!!e.chart.events.click;this.pinchDown=[];this.lastValidTouch={};E&&(b.tooltip=new E(b,e.tooltip),this.followTouchMove=t(e.tooltip.followTouchMove,!0));this.setDOMEvents()};f.prototype.normalize=function(b,e){var g=b.touches,l=g?g.length?g.item(0):g.changedTouches[0]:b;e||(e=this.getChartPosition());g=l.pageX-e.left; +e=l.pageY-e.top;if(l=this.chart.containerScaling)g/=l.scaleX,e/=l.scaleY;return x(b,{chartX:Math.round(g),chartY:Math.round(e)})};f.prototype.onContainerClick=function(b){var e=this.chart,g=e.hoverPoint;b=this.normalize(b);var l=e.plotLeft,h=e.plotTop;e.cancelClick||(g&&this.inClass(b.target,"highcharts-tracker")?(H(g.series,"click",x(b,{point:g})),e.hoverPoint&&g.firePointEvent("click",b)):(x(b,this.getCoordinates(b)),e.isInsidePlot(b.chartX-l,b.chartY-h)&&H(e,"click",b)))};f.prototype.onContainerMouseDown= +function(b){b=this.normalize(b);if(d.isFirefox&&0!==b.button)this.onContainerMouseMove(b);if("undefined"===typeof b.button||1===((b.buttons||b.button)&1))this.zoomOption(b),this.dragStart(b)};f.prototype.onContainerMouseLeave=function(g){var e=b[t(d.hoverChartIndex,-1)],h=this.chart.tooltip;g=this.normalize(g);e&&(g.relatedTarget||g.toElement)&&(e.pointer.reset(),e.pointer.chartPosition=void 0);h&&!h.isHidden&&this.reset()};f.prototype.onContainerMouseMove=function(b){var e=this.chart;b=this.normalize(b); +this.setHoverChartIndex();b.preventDefault||(b.returnValue=!1);"mousedown"===e.mouseIsDown&&this.drag(b);e.openMenu||!this.inClass(b.target,"highcharts-tracker")&&!e.isInsidePlot(b.chartX-e.plotLeft,b.chartY-e.plotTop)||this.runPointActions(b)};f.prototype.onDocumentTouchEnd=function(g){b[d.hoverChartIndex]&&b[d.hoverChartIndex].pointer.drop(g)};f.prototype.onContainerTouchMove=function(b){this.touch(b)};f.prototype.onContainerTouchStart=function(b){this.zoomOption(b);this.touch(b,!0)};f.prototype.onDocumentMouseMove= +function(b){var e=this.chart,g=this.chartPosition;b=this.normalize(b,g);var l=e.tooltip;!g||l&&l.isStickyOnContact()||e.isInsidePlot(b.chartX-e.plotLeft,b.chartY-e.plotTop)||this.inClass(b.target,"highcharts-tracker")||this.reset()};f.prototype.onDocumentMouseUp=function(g){var e=b[t(d.hoverChartIndex,-1)];e&&e.pointer.drop(g)};f.prototype.pinch=function(b){var e=this,h=e.chart,l=e.pinchDown,d=b.touches||[],m=d.length,f=e.lastValidTouch,v=e.hasZoom,n=e.selectionMarker,w={},B=1===m&&(e.inClass(b.target, +"highcharts-tracker")&&h.runTrackerClick||e.runChartClick),c={};1G.max&&(e=G.max-r,V=!0);V?(I-=.8*(I-f[p][0]),"number"===typeof O&&(O-=.8*(O-f[p][1])),g()):f[p]=[I,O];n||(m[p]=z-k,m[a]=r);m=n?1/y:y;d[a]=r;d[p]=e;l[n?b?"scaleY":"scaleX":"scale"+u]=y;l["translate"+u]=m*k+(I-m*w)};f.prototype.reset=function(b,e){var g=this.chart,l=g.hoverSeries,d=g.hoverPoint,h=g.hoverPoints,m=g.tooltip,f=m&&m.shared?h:d;b&&f&&N(f).forEach(function(e){e.series.isCartesian&&"undefined"===typeof e.plotX&&(b=!1)});if(b)m&&f&&N(f).length&&(m.refresh(f),m.shared&&h?h.forEach(function(e){e.setState(e.state, +!0);e.series.isCartesian&&(e.series.xAxis.crosshair&&e.series.xAxis.drawCrosshair(null,e),e.series.yAxis.crosshair&&e.series.yAxis.drawCrosshair(null,e))}):d&&(d.setState(d.state,!0),g.axes.forEach(function(e){e.crosshair&&d.series[e.coll]===e&&e.drawCrosshair(null,d)})));else{if(d)d.onMouseOut();h&&h.forEach(function(e){e.setState()});if(l)l.onMouseOut();m&&m.hide(e);this.unDocMouseMove&&(this.unDocMouseMove=this.unDocMouseMove());g.axes.forEach(function(e){e.hideCrosshair()});this.hoverX=g.hoverPoints= +g.hoverPoint=null}};f.prototype.runPointActions=function(g,e){var h=this.chart,l=h.tooltip&&h.tooltip.options.enabled?h.tooltip:void 0,m=l?l.shared:!1,f=e||h.hoverPoint,y=f&&f.series||h.hoverSeries;y=this.getHoverData(f,y,h.series,(!g||"touchmove"!==g.type)&&(!!e||y&&y.directTouch&&this.isDirectTouch),m,g);f=y.hoverPoint;var v=y.hoverPoints;e=(y=y.hoverSeries)&&y.tooltipOptions.followPointer;m=m&&y&&!y.noSharedTooltip;if(f&&(f!==h.hoverPoint||l&&l.isHidden)){(h.hoverPoints||[]).forEach(function(e){-1=== +v.indexOf(e)&&e.setState()});if(h.hoverSeries!==y)y.onMouseOver();this.applyInactiveState(v);(v||[]).forEach(function(e){e.setState("hover")});h.hoverPoint&&h.hoverPoint.firePointEvent("mouseOut");if(!f.series)return;f.firePointEvent("mouseOver");h.hoverPoints=v;h.hoverPoint=f;l&&l.refresh(m?v:f,g)}else e&&l&&!l.isHidden&&(f=l.getAnchor([{}],g),l.updatePosition({plotX:f[0],plotY:f[1]}));this.unDocMouseMove||(this.unDocMouseMove=M(h.container.ownerDocument,"mousemove",function(e){var l=b[d.hoverChartIndex]; +if(l)l.pointer.onDocumentMouseMove(e)}));h.axes.forEach(function(e){var b=t((e.crosshair||{}).snap,!0),l;b&&((l=h.hoverPoint)&&l.series[e.coll]===e||(l=F(v,function(c){return c.series[e.coll]===e})));l||!b?e.drawCrosshair(g,l):e.hideCrosshair()})};f.prototype.scaleGroups=function(b,e){var g=this.chart,l;g.series.forEach(function(d){l=b||d.getPlotBox();d.xAxis&&d.xAxis.zoomEnabled&&d.group&&(d.group.attr(l),d.markerGroup&&(d.markerGroup.attr(l),d.markerGroup.clip(e?g.clipRect:null)),d.dataLabelsGroup&& +d.dataLabelsGroup.attr(l))});g.clipRect.attr(e||g.clipBox)};f.prototype.setDOMEvents=function(){var b=this.chart.container,e=b.ownerDocument;b.onmousedown=this.onContainerMouseDown.bind(this);b.onmousemove=this.onContainerMouseMove.bind(this);b.onclick=this.onContainerClick.bind(this);this.unbindContainerMouseLeave=M(b,"mouseleave",this.onContainerMouseLeave.bind(this));d.unbindDocumentMouseUp||(d.unbindDocumentMouseUp=M(e,"mouseup",this.onDocumentMouseUp.bind(this)));d.hasTouch&&(M(b,"touchstart", +this.onContainerTouchStart.bind(this)),M(b,"touchmove",this.onContainerTouchMove.bind(this)),d.unbindDocumentTouchEnd||(d.unbindDocumentTouchEnd=M(e,"touchend",this.onDocumentTouchEnd.bind(this))))};f.prototype.setHoverChartIndex=function(){var b=this.chart,e=d.charts[t(d.hoverChartIndex,-1)];if(e&&e!==b)e.pointer.onContainerMouseLeave({relatedTarget:!0});e&&e.mouseIsDown||(d.hoverChartIndex=b.index)};f.prototype.touch=function(b,e){var g=this.chart,l;this.setHoverChartIndex();if(1===b.touches.length)if(b= +this.normalize(b),(l=g.isInsidePlot(b.chartX-g.plotLeft,b.chartY-g.plotTop))&&!g.openMenu){e&&this.runPointActions(b);if("touchmove"===b.type){e=this.pinchDown;var d=e[0]?4<=Math.sqrt(Math.pow(e[0].chartX-b.chartX,2)+Math.pow(e[0].chartY-b.chartY,2)):!1}t(d,!0)&&this.pinch(b)}else e&&this.reset();else 2===b.touches.length&&this.pinch(b)};f.prototype.zoomOption=function(b){var e=this.chart,g=e.options.chart,l=g.zoomType||"";e=e.inverted;/touch/.test(b.type)&&(l=t(g.pinchType,l));this.zoomX=b=/x/.test(l); +this.zoomY=l=/y/.test(l);this.zoomHor=b&&!e||l&&e;this.zoomVert=l&&!e||b&&e;this.hasZoom=b||l};return f}();d.Pointer=f;return d.Pointer});Q(A,"parts/MSPointer.js",[A["parts/Globals.js"],A["parts/Pointer.js"],A["parts/Utilities.js"]],function(d,f,E){function q(){var d=[];d.item=function(d){return this[d]};x(w,function(f){d.push({pageX:f.pageX,pageY:f.pageY,target:f.target})});return d}function M(f,n,m,b){"touch"!==f.pointerType&&f.pointerType!==f.MSPOINTER_TYPE_TOUCH||!H[d.hoverChartIndex]||(b(f), +b=H[d.hoverChartIndex].pointer,b[n]({type:m,target:f.currentTarget,preventDefault:D,touches:q()}))}var K=this&&this.__extends||function(){var d=function(f,m){d=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(b,g){b.__proto__=g}||function(b,g){for(var d in g)g.hasOwnProperty(d)&&(b[d]=g[d])};return d(f,m)};return function(f,m){function b(){this.constructor=f}d(f,m);f.prototype=null===m?Object.create(m):(b.prototype=m.prototype,new b)}}(),J=E.addEvent,L=E.css,x=E.objectEach,F=E.removeEvent, +H=d.charts,C=d.doc,D=d.noop,w={},n=!!d.win.PointerEvent;return function(d){function f(){return null!==d&&d.apply(this,arguments)||this}K(f,d);f.prototype.batchMSEvents=function(d){d(this.chart.container,n?"pointerdown":"MSPointerDown",this.onContainerPointerDown);d(this.chart.container,n?"pointermove":"MSPointerMove",this.onContainerPointerMove);d(C,n?"pointerup":"MSPointerUp",this.onDocumentPointerUp)};f.prototype.destroy=function(){this.batchMSEvents(F);d.prototype.destroy.call(this)};f.prototype.init= +function(m,b){d.prototype.init.call(this,m,b);this.hasZoom&&L(m.container,{"-ms-touch-action":"none","touch-action":"none"})};f.prototype.onContainerPointerDown=function(d){M(d,"onContainerTouchStart","touchstart",function(b){w[b.pointerId]={pageX:b.pageX,pageY:b.pageY,target:b.currentTarget}})};f.prototype.onContainerPointerMove=function(d){M(d,"onContainerTouchMove","touchmove",function(b){w[b.pointerId]={pageX:b.pageX,pageY:b.pageY};w[b.pointerId].target||(w[b.pointerId].target=b.currentTarget)})}; +f.prototype.onDocumentPointerUp=function(d){M(d,"onDocumentTouchEnd","touchend",function(b){delete w[b.pointerId]})};f.prototype.setDOMEvents=function(){d.prototype.setDOMEvents.call(this);(this.hasZoom||this.followTouchMove)&&this.batchMSEvents(J)};return f}(f)});Q(A,"parts/Legend.js",[A["parts/Globals.js"],A["parts/Utilities.js"]],function(d,f){var E=f.addEvent,q=f.animObject,M=f.css,K=f.defined,J=f.discardElement,L=f.find,x=f.fireEvent,F=f.format,H=f.isNumber,C=f.merge,D=f.pick,w=f.relativeLength, +n=f.setAnimation,t=f.stableSort,N=f.syncTimeout;f=f.wrap;var m=d.isFirefox,b=d.marginNames,g=d.win,v=function(){function g(e,b){this.allItems=[];this.contentGroup=this.box=void 0;this.display=!1;this.group=void 0;this.offsetWidth=this.maxLegendWidth=this.maxItemWidth=this.legendWidth=this.legendHeight=this.lastLineHeight=this.lastItemY=this.itemY=this.itemX=this.itemMarginTop=this.itemMarginBottom=this.itemHeight=this.initialItemY=0;this.options={};this.padding=0;this.pages=[];this.proximate=!1;this.scrollGroup= +void 0;this.widthOption=this.totalItemWidth=this.titleHeight=this.symbolWidth=this.symbolHeight=0;this.chart=e;this.init(e,b)}g.prototype.init=function(e,b){this.chart=e;this.setOptions(b);b.enabled&&(this.render(),E(this.chart,"endResize",function(){this.legend.positionCheckboxes()}),this.proximate?this.unchartrender=E(this.chart,"render",function(){this.legend.proximatePositions();this.legend.positionItems()}):this.unchartrender&&this.unchartrender())};g.prototype.setOptions=function(e){var b=D(e.padding, +8);this.options=e;this.chart.styledMode||(this.itemStyle=e.itemStyle,this.itemHiddenStyle=C(this.itemStyle,e.itemHiddenStyle));this.itemMarginTop=e.itemMarginTop||0;this.itemMarginBottom=e.itemMarginBottom||0;this.padding=b;this.initialItemY=b-5;this.symbolWidth=D(e.symbolWidth,16);this.pages=[];this.proximate="proximate"===e.layout&&!this.chart.inverted;this.baseline=void 0};g.prototype.update=function(e,b){var g=this.chart;this.setOptions(C(!0,this.options,e));this.destroy();g.isDirtyLegend=g.isDirtyBox= +!0;D(b,!0)&&g.redraw();x(this,"afterUpdate")};g.prototype.colorizeItem=function(e,b){e.legendGroup[b?"removeClass":"addClass"]("highcharts-legend-item-hidden");if(!this.chart.styledMode){var g=this.options,d=e.legendItem,h=e.legendLine,m=e.legendSymbol,f=this.itemHiddenStyle.color;g=b?g.itemStyle.color:f;var p=b?e.color||f:f,v=e.options&&e.options.marker,n={fill:p};d&&d.css({fill:g,color:g});h&&h.attr({stroke:p});m&&(v&&m.isMarker&&(n=e.pointAttribs(),b||(n.stroke=n.fill=f)),m.attr(n))}x(this,"afterColorizeItem", +{item:e,visible:b})};g.prototype.positionItems=function(){this.allItems.forEach(this.positionItem,this);this.chart.isResizing||this.positionCheckboxes()};g.prototype.positionItem=function(e){var b=this.options,g=b.symbolPadding;b=!b.rtl;var d=e._legendItemPos,h=d[0];d=d[1];var m=e.checkbox;if((e=e.legendGroup)&&e.element)e[K(e.translateY)?"animate":"attr"]({translateX:b?h:this.legendWidth-h-2*g-4,translateY:d});m&&(m.x=h,m.y=d)};g.prototype.destroyItem=function(e){var b=e.checkbox;["legendItem","legendLine", +"legendSymbol","legendGroup"].forEach(function(b){e[b]&&(e[b]=e[b].destroy())});b&&J(e.checkbox)};g.prototype.destroy=function(){function b(b){this[b]&&(this[b]=this[b].destroy())}this.getAllItems().forEach(function(e){["legendItem","legendGroup"].forEach(b,e)});"clipRect up down pager nav box title group".split(" ").forEach(b,this);this.display=null};g.prototype.positionCheckboxes=function(){var b=this.group&&this.group.alignAttr,g=this.clipHeight||this.legendHeight,l=this.titleHeight;if(b){var d= +b.translateY;this.allItems.forEach(function(e){var h=e.checkbox;if(h){var m=d+l+h.y+(this.scrollOffset||0)+3;M(h,{left:b.translateX+e.checkboxOffset+h.x-20+"px",top:m+"px",display:this.proximate||m>d-6&&mn?this.maxItemWidth:b.itemWidth;d&&this.itemX-g+e>n&&(this.itemX=g,this.lastLineHeight&&(this.itemY+=f+this.lastLineHeight+m),this.lastLineHeight=0);this.lastItemY=f+this.itemY+m;this.lastLineHeight=Math.max(h,this.lastLineHeight);b._legendItemPos=[this.itemX,this.itemY];d?this.itemX+=e:(this.itemY+=f+h+m,this.lastLineHeight=h);this.offsetWidth=this.widthOption||Math.max((d?this.itemX-g-(b.checkbox?0:v):e)+g,this.offsetWidth)};g.prototype.getAllItems= +function(){var b=[];this.chart.series.forEach(function(e){var g=e&&e.options;e&&D(g.showInLegend,K(g.linkedTo)?!1:void 0,!0)&&(b=b.concat(e.legendItems||("point"===g.legendType?e.data:e)))});x(this,"afterGetAllItems",{allItems:b});return b};g.prototype.getAlignment=function(){var b=this.options;return this.proximate?b.align.charAt(0)+"tv":b.floating?"":b.align.charAt(0)+b.verticalAlign.charAt(0)+b.layout.charAt(0)};g.prototype.adjustMargins=function(e,g){var l=this.chart,d=this.options,h=this.getAlignment(); +h&&[/(lth|ct|rth)/,/(rtv|rm|rbv)/,/(rbh|cb|lbh)/,/(lbv|lm|ltv)/].forEach(function(m,f){m.test(h)&&!K(e[f])&&(l[b[f]]=Math.max(l[b[f]],l.legend[(f+1)%2?"legendHeight":"legendWidth"]+[1,-1,-1,1][f]*d[f%2?"x":"y"]+D(d.margin,12)+g[f]+(l.titleOffset[f]||0)))})};g.prototype.proximatePositions=function(){var b=this.chart,g=[],l="left"===this.options.align;this.allItems.forEach(function(e){var d=l;if(e.yAxis&&e.points){e.xAxis.options.reversed&&(d=!d);var h=L(d?e.points:e.points.slice(0).reverse(),function(b){return H(b.plotY)}); +d=this.itemMarginTop+e.legendItem.getBBox().height+this.itemMarginBottom;var m=e.yAxis.top-b.plotTop;e.visible?(h=h?h.plotY:e.yAxis.height,h+=m-.3*d):h=m+e.yAxis.height;g.push({target:h,size:d,item:e})}},this);d.distribute(g,b.plotHeight);g.forEach(function(e){e.item._legendItemPos[1]=b.plotTop-b.spacing[0]+e.pos})};g.prototype.render=function(){var b=this.chart,g=b.renderer,l=this.group,d=this.box,h=this.options,m=this.padding;this.itemX=m;this.itemY=this.initialItemY;this.lastItemY=this.offsetWidth= +0;this.widthOption=w(h.width,b.spacingBox.width-m);var f=b.spacingBox.width-2*m-h.x;-1<["rm","lm"].indexOf(this.getAlignment().substring(0,2))&&(f/=2);this.maxLegendWidth=this.widthOption||f;l||(this.group=l=g.g("legend").attr({zIndex:7}).add(),this.contentGroup=g.g().attr({zIndex:1}).add(l),this.scrollGroup=g.g().add(this.contentGroup));this.renderTitle();var v=this.getAllItems();t(v,function(b,c){return(b.options&&b.options.legendIndex||0)-(c.options&&c.options.legendIndex||0)});h.reversed&&v.reverse(); +this.allItems=v;this.display=f=!!v.length;this.itemHeight=this.totalItemWidth=this.maxItemWidth=this.lastLineHeight=0;v.forEach(this.renderItem,this);v.forEach(this.layoutItem,this);v=(this.widthOption||this.offsetWidth)+m;var n=this.lastItemY+this.lastLineHeight+this.titleHeight;n=this.handleOverflow(n);n+=m;d||(this.box=d=g.rect().addClass("highcharts-legend-box").attr({r:h.borderRadius}).add(l),d.isNew=!0);b.styledMode||d.attr({stroke:h.borderColor,"stroke-width":h.borderWidth||0,fill:h.backgroundColor|| +"none"}).shadow(h.shadow);0m&&!1!==c.enabled?(this.clipHeight= +n=Math.max(m-20-this.titleHeight-f,0),this.currentPage=D(this.currentPage,1),this.fullHeight=b,x.forEach(function(a,c){var b=a._legendItemPos[1],e=Math.round(a.legendItem.getBBox().height),k=z.length;if(!k||b-z[k-1]>n&&(t||b)!==z[k-1])z.push(t||b),k++;a.pageIx=k-1;t&&(x[c-1].pageIx=k-1);c===x.length-1&&b+e-z[k-1]>n&&b!==t&&(z.push(b),a.pageIx=k);b!==t&&(t=b)}),w||(w=e.clipRect=d.clipRect(0,f,9999,0),e.contentGroup.clip(w)),q(n),r||(this.nav=r=d.g().attr({zIndex:1}).add(this.group),this.up=d.symbol("triangle", +0,0,k,k).add(r),C("upTracker").on("click",function(){e.scroll(-1,a)}),this.pager=d.text("",15,10).addClass("highcharts-legend-navigation"),g.styledMode||this.pager.css(c.style),this.pager.add(r),this.down=d.symbol("triangle-down",0,0,k,k).add(r),C("downTracker").on("click",function(){e.scroll(1,a)})),e.scroll(0),b=m):r&&(q(),this.nav=r.destroy(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0);return b};g.prototype.scroll=function(b,g){var e=this,d=this.chart,h=this.pages,m=h.length,f=this.currentPage+ +b;b=this.clipHeight;var p=this.options.navigation,v=this.pager,w=this.padding;f>m&&(f=m);0=f.value;)f=b[++g];this.nonZonedColor||(this.nonZonedColor=this.color);this.color=f&&f.color&&!this.options.color?f.color:this.nonZonedColor;return f};d.prototype.hasNewShapeType=function(){return(this.graphic&&(this.graphic.symbolName||this.graphic.element.nodeName))!==this.shapeType};d.prototype.init=function(d,b,g){this.series=d;this.applyOptions(b,g);this.id=q(this.id)?this.id:t();this.resolveColor();d.chart.pointCount++;J(this,"afterInit");return this};d.prototype.optionsToObject= +function(f){var b={},g=this.series,m=g.options.keys,h=m||g.pointArrayMap||["y"],e=h.length,p=0,l=0;if(H(f)||null===f)b[h[0]]=f;else if(F(f))for(!m&&f.length>e&&(g=typeof f[0],"string"===g?b.name=f[0]:"number"===g&&(b.x=f[0]),p++);l=p(a[b].options.index,a[b]._i)){a.splice(b+1,0,this);break}-1===b&&a.unshift(this);b+=1}else a.push(this);return p(b,a.length-1)},bindAxes:function(){var a=this,c=a.options,b=a.chart,e;t(this,"bindAxes",null,function(){(a.axisTypes||[]).forEach(function(d){b[d].forEach(function(b){e=b.options;if(c[d]===e.index||"undefined"!==typeof c[d]&&c[d]===e.id||"undefined"===typeof c[d]&&0===e.index)a.insert(b.series), +a[d]=b,b.isDirty=!0});a[d]||a.optionalAxis===d||D(18,!0,b)})});t(this,"afterBindAxes")},updateParallelArrays:function(a,c){var b=a.series,e=arguments,d=g(c)?function(e){var d="y"===e&&b.toYData?b.toYData(a):a[e];b[e+"Data"][c]=d}:function(a){Array.prototype[c].apply(b[a+"Data"],Array.prototype.slice.call(e,2))};b.parallelArrays.forEach(d)},hasData:function(){return this.visible&&"undefined"!==typeof this.dataMax&&"undefined"!==typeof this.dataMin||this.visible&&this.yData&&0=this.cropStart?m-this.cropStart:m);!k&&d[m]&&d[m].touched&&(m=void 0);return m},drawLegendSymbol:d.drawLineMarker,updateData:function(a,c){var b=this.options,e=b.dataSorting,d=this.points,k=[],l,f,h,m=this.requireSorting,u=a.length===d.length, +p=!0;this.xIncrement=null;a.forEach(function(a,c){var f=H(a)&&this.pointClass.prototype.optionsToObject.call({series:this},a)||{};var r=f.x;if(f.id||g(r)){if(r=this.findPointIndex(f,h),-1===r||"undefined"===typeof r?k.push(a):d[r]&&a!==b.data[r]?(d[r].update(a,!1,null,!1),d[r].touched=!0,m&&(h=r+1)):d[r]&&(d[r].touched=!0),!u||c!==r||e&&e.enabled||this.hasDerivedData)l=!0}else k.push(a)},this);if(l)for(a=d.length;a--;)(f=d[a])&&!f.touched&&f.remove&&f.remove(!1,c);else!u||e&&e.enabled?p=!1:(a.forEach(function(a, +c){d[c].update&&a!==d[c].y&&d[c].update(a,!1,null,!1)}),k.length=0);d.forEach(function(a){a&&(a.touched=!1)});if(!p)return!1;k.forEach(function(a){this.addPoint(a,!1,null,null,!1)},this);null===this.xIncrement&&this.xData&&this.xData.length&&(this.xIncrement=J(this.xData),this.autoIncrement());return!0},setData:function(a,c,b,e){var d=this,k=d.points,l=k&&k.length||0,f,h=d.options,r=d.chart,u=h.dataSorting,n=null,z=d.xAxis;n=h.turboThreshold;var y=this.xData,w=this.yData,t=(f=d.pointArrayMap)&&f.length, +B=h.keys,G=0,q=1,x;a=a||[];f=a.length;c=p(c,!0);u&&u.enabled&&(a=this.sortData(a));!1!==e&&f&&l&&!d.cropped&&!d.hasGroupedData&&d.visible&&!d.isSeriesBoosting&&(x=this.updateData(a,b));if(!x){d.xIncrement=null;d.colorCounter=0;this.parallelArrays.forEach(function(a){d[a+"Data"].length=0});if(n&&f>n)if(n=d.getFirstValidPoint(a),g(n))for(b=0;ba?1:0}).forEach(function(a,c){a.x=c},this);c.linkedSeries&&c.linkedSeries.forEach(function(c){var b=c.options,d=b.data;b.dataSorting&&b.dataSorting.enabled||!d||(d.forEach(function(b,k){d[k]=e(c,b);a[k]&&(d[k].x=a[k].x,d[k].index= +k)}),c.setData(d,!1))});return a},getProcessedData:function(a){var c=this.xData,b=this.yData,e=c.length;var d=0;var g=this.xAxis,f=this.options;var l=f.cropThreshold;var h=a||this.getExtremesFromAll||f.getExtremesFromAll,m=this.isCartesian;a=g&&g.val2lin;f=!(!g||!g.logarithmic);var u=this.requireSorting;if(g){g=g.getExtremes();var p=g.min;var n=g.max}if(m&&this.sorted&&!h&&(!l||e>l||this.forceCrop))if(c[e-1]n)c=[],b=[];else if(this.yData&&(c[0]n)){d=this.cropData(this.xData,this.yData, +p,n);c=d.xData;b=d.yData;d=d.start;var v=!0}for(l=c.length||1;--l;)if(e=f?a(c[l])-a(c[l-1]):c[l]-c[l-1],0e&&u&&(D(15,!1,this.chart),u=!1);return{xData:c,yData:b,cropped:v,cropStart:d,closestPointRange:y}},processData:function(a){var c=this.xAxis;if(this.isCartesian&&!this.isDirty&&!c.isDirty&&!this.yAxis.isDirty&&!a)return!1;a=this.getProcessedData();this.cropped=a.cropped;this.cropStart=a.cropStart;this.processedXData=a.xData;this.processedYData=a.yData; +this.closestPointRange=this.basePointRange=a.closestPointRange},cropData:function(a,c,b,e,d){var g=a.length,k=0,l=g,f;d=p(d,this.cropShoulder);for(f=0;f=b){k=Math.max(0,f-d);break}for(b=f;be){l=b+d;break}return{xData:a.slice(k,l),yData:c.slice(k,l),start:k,end:l}},generatePoints:function(){var a=this.options,c=a.data,b=this.data,e,d=this.processedXData,g=this.processedYData,f=this.pointClass,l=d.length,h=this.cropStart||0,m=this.hasGroupedData;a=a.keys;var p=[],n;b|| +m||(b=[],b.length=c.length,b=this.data=b);a&&m&&(this.options.keys=!1);for(n=0;n=f&&(d[p-u]||v)<=h;if(w&&v)if(w=y.length)for(;w--;)g(y[w])&&(k[l++]=y[w]);else k[l++]=y}a={dataMin:L(k),dataMax:J(k)};t(this,"afterGetExtremes",{dataExtremes:a});return a},applyExtremes:function(){var a=this.getExtremes();this.dataMin=a.dataMin;this.dataMax=a.dataMax;return a},getFirstValidPoint:function(a){for(var c=null,b=a.length,e=0;null===c&&e=R&&(C.isNull=!0);C.plotX=G=F(x(b.translate(D,0,0,0,1,v,"flags"=== +this.type),-1E5,1E5));if(c&&this.visible&&A&&A[D]){var E=this.getStackIndicator(E,D,this.index);if(!C.isNull){var N=A[D];var L=N.points[E.key]}}m(L)&&(S=L[0],R=L[1],S===B&&E.key===A[D].base&&(S=p(g(w)&&w,l.min)),l.positiveValuesOnly&&0>=S&&(S=null),C.total=C.stackTotal=N.total,C.percentage=N.total&&C.y/N.total*100,C.stackY=R,this.irregularWidths||N.setOffset(this.pointXOffset||0,this.barW||0));C.yBottom=H(S)?x(l.translate(S,0,1,0,1),-1E5,1E5):null;u&&(R=this.modifyValue(R,C));C.plotY="number"===typeof R&& +Infinity!==R?x(l.translate(R,0,1,0,1),-1E5,1E5):void 0;C.isInside=this.isPointInside(C);C.clientX=y?F(b.translate(D,0,0,0,1,v)):G;C.negative=C[q]<(a[q+"Threshold"]||w||0);C.category=e&&"undefined"!==typeof e[C.x]?e[C.x]:C.x;if(!C.isNull&&!1!==C.visible){"undefined"!==typeof J&&(I=Math.min(I,Math.abs(G-J)));var J=G}C.zone=this.zones.length&&C.getZone();!C.graphic&&this.group&&d&&(C.isNew=!0)}this.closestPointRangePx=I;t(this,"afterTranslate")},getValidPoints:function(a,c,b){var e=this.chart;return(a|| +this.points||[]).filter(function(a){return c&&!e.isInsidePlot(a.plotX,a.plotY,e.inverted)?!1:!1!==a.visible&&(b||!a.isNull)})},getClipBox:function(a,c){var b=this.options,e=this.chart,d=e.inverted,g=this.xAxis,k=g&&this.yAxis;a&&!1===b.clip&&k?a=d?{y:-e.chartWidth+k.len+k.pos,height:e.chartWidth,width:e.chartHeight,x:-e.chartHeight+g.len+g.pos}:{y:-k.pos,height:e.chartHeight,width:e.chartWidth,x:-g.pos}:(a=this.clipBox||e.clipBox,c&&(a.width=e.plotSizeX,a.x=0));return c?{width:a.width,x:a.x}:a},setClip:function(a){var c= +this.chart,b=this.options,e=c.renderer,d=c.inverted,g=this.clipBox,l=this.getClipBox(a),f=this.sharedClipKey||["_sharedClip",a&&a.duration,a&&a.easing,l.height,b.xAxis,b.yAxis].join(),h=c[f],m=c[f+"m"];a&&(l.width=0,d&&(l.x=c.plotHeight+(!1!==b.clip?0:c.plotTop)));h?c.hasLoaded||h.attr(l):(a&&(c[f+"m"]=m=e.clipRect(d?c.plotSizeX+99:-99,d?-c.plotLeft:-c.plotTop,99,d?c.chartWidth:c.chartHeight)),c[f]=h=e.clipRect(l),h.count={length:0});a&&!h.count[this.index]&&(h.count[this.index]=!0,h.count.length+= +1);if(!1!==b.clip||a)this.group.clip(a||g?h:c.clipRect),this.markerGroup.clip(m),this.sharedClipKey=f;a||(h.count[this.index]&&(delete h.count[this.index],--h.count.length),0===h.count.length&&f&&c[f]&&(g||(c[f]=c[f].destroy()),c[f+"m"]&&(c[f+"m"]=c[f+"m"].destroy())))},animate:function(a){var c=this.chart,b=K(this.options.animation);if(!c.hasRendered)if(a)this.setClip(b);else{var e=this.sharedClipKey;a=c[e];var d=this.getClipBox(b,!0);a&&a.animate(d,b);c[e+"m"]&&c[e+"m"].animate({width:d.width+99, +x:d.x-(c.inverted?0:99)},b)}},afterAnimate:function(){this.setClip();t(this,"afterAnimate");this.finishedAnimating=!0},drawPoints:function(){var a=this.points,c=this.chart,b,e,d=this.options.marker,g=this[this.specialGroup]||this.markerGroup,f=this.xAxis,l=p(d.enabled,!f||f.isRadial?!0:null,this.closestPointRangePx>=d.enabledThreshold*d.radius);if(!1!==d.enabled||this._hasPointMarkers)for(b=0;bg&&c.shadow));f&&(f.startX=b.xMap,f.isArea=b.isArea)})},getZonesGraphs:function(a){this.zones.forEach(function(c, +b){b=["zone-graph-"+b,"highcharts-graph highcharts-zone-graph-"+b+" "+(c.className||"")];this.chart.styledMode||b.push(c.color||this.color,c.dashStyle||this.options.dashStyle);a.push(b)},this);return a},applyZones:function(){var a=this,c=this.chart,b=c.renderer,e=this.zones,d,g,f=this.clips||[],l,h=this.graph,m=this.area,u=Math.max(c.chartWidth,c.chartHeight),n=this[(this.zoneAxis||"y")+"Axis"],v=c.inverted,y,w,t,B=!1,G,q;if(e.length&&(h||m)&&n&&"undefined"!==typeof n.min){var C=n.reversed;var I= +n.horiz;h&&!this.showLine&&h.hide();m&&m.hide();var D=n.getExtremes();e.forEach(function(e,k){d=C?I?c.plotWidth:0:I?0:n.toPixels(D.min)||0;d=x(p(g,d),0,u);g=x(Math.round(n.toPixels(p(e.value,D.max),!0)||0),0,u);B&&(d=g=n.toPixels(D.max));y=Math.abs(d-g);w=Math.min(d,g);t=Math.max(d,g);n.isXAxis?(l={x:v?t:w,y:0,width:y,height:u},I||(l.x=c.plotHeight-l.x)):(l={x:0,y:v?t:w,width:u,height:y},I&&(l.y=c.plotWidth-l.y));v&&b.isVML&&(l=n.isXAxis?{x:0,y:C?w:t,height:l.width,width:c.chartWidth}:{x:l.y-c.plotLeft- +c.spacingBox.x,y:0,width:l.height,height:c.chartHeight});f[k]?f[k].animate(l):f[k]=b.clipRect(l);G=a["zone-area-"+k];q=a["zone-graph-"+k];h&&q&&q.clip(f[k]);m&&G&&G.clip(f[k]);B=e.value>D.max;a.resetZones&&0===g&&(g=void 0)});this.clips=f}else a.visible&&(h&&h.show(!0),m&&m.show(!0))},invertGroups:function(a){function c(){["group","markerGroup"].forEach(function(c){b[c]&&(e.renderer.isVML&&b[c].attr({width:b.yAxis.len,height:b.xAxis.len}),b[c].width=b.yAxis.len,b[c].height=b.xAxis.len,b[c].invert(b.isRadialSeries? +!1:a))})}var b=this,e=b.chart;b.xAxis&&(b.eventsToUnbind.push(E(e,"resize",c)),c(),b.invertGroups=c)},plotGroup:function(a,c,b,e,d){var g=this[a],k=!g;k&&(this[a]=g=this.chart.renderer.g().attr({zIndex:e||.1}).add(d));g.addClass("highcharts-"+c+" highcharts-series-"+this.index+" highcharts-"+this.type+"-series "+(H(this.colorIndex)?"highcharts-color-"+this.colorIndex+" ":"")+(this.options.className||"")+(g.hasClass("highcharts-tracker")?" highcharts-tracker":""),!0);g.attr({visibility:b})[k?"attr": +"animate"](this.getPlotBox());return g},getPlotBox:function(){var a=this.chart,c=this.xAxis,b=this.yAxis;a.inverted&&(c=b,b=this.xAxis);return{translateX:c?c.left:a.plotLeft,translateY:b?b.top:a.plotTop,scaleX:1,scaleY:1}},removeEvents:function(a){a?this.eventsToUnbind.length&&(this.eventsToUnbind.forEach(function(a){a()}),this.eventsToUnbind.length=0):l(this)},render:function(){var a=this,c=a.chart,b=a.options,e=!a.finishedAnimating&&c.renderer.isSVG&&K(b.animation).duration,d=a.visible?"inherit": +"hidden",g=b.zIndex,f=a.hasRendered,l=c.seriesGroup,h=c.inverted;t(this,"render");var m=a.plotGroup("group","series",d,g,l);a.markerGroup=a.plotGroup("markerGroup","markers",d,g,l);e&&a.animate&&a.animate(!0);m.inverted=a.isCartesian||a.invertable?h:!1;a.drawGraph&&(a.drawGraph(),a.applyZones());a.visible&&a.drawPoints();a.drawDataLabels&&a.drawDataLabels();a.redrawPoints&&a.redrawPoints();a.drawTracker&&!1!==a.options.enableMouseTracking&&a.drawTracker();a.invertGroups(h);!1===b.clip||a.sharedClipKey|| +f||m.clip(c.clipRect);e&&a.animate&&a.animate();f||(a.animationTimeout=y(function(){a.afterAnimate()},e||0));a.isDirty=!1;a.hasRendered=!0;t(a,"afterRender")},redraw:function(){var a=this.chart,c=this.isDirty||this.isDirtyData,b=this.group,e=this.xAxis,d=this.yAxis;b&&(a.inverted&&b.attr({width:a.plotWidth,height:a.plotHeight}),b.animate({translateX:p(e&&e.left,a.plotLeft),translateY:p(d&&d.top,a.plotTop)}));this.translate();this.render();c&&delete this.kdTree},kdAxisArray:["clientX","plotY"],searchPoint:function(a, +c){var b=this.xAxis,e=this.yAxis,d=this.chart.inverted;return this.searchKDTree({clientX:d?b.len-a.chartY+b.pos:a.chartX-b.pos,plotY:d?e.len-a.chartX+e.pos:a.chartY-e.pos},c,a)},buildKDTree:function(a){function c(a,e,d){var g;if(g=a&&a.length){var k=b.kdAxisArray[e%d];a.sort(function(a,c){return a[k]-c[k]});g=Math.floor(g/2);return{point:a[g],left:c(a.slice(0,g),e+1,d),right:c(a.slice(g+1),e+1,d)}}}this.buildingKdTree=!0;var b=this,e=-1m?"left":"right";n=0>m?"right":"left";c[p]&&(p=e(a,c[p],b+1, +l),u=p[f]v;)y--;this.updateParallelArrays(p,"splice",y,0,0);this.updateParallelArrays(p,y);k&&p.name&&(k[v]=p.name);m.splice(y,0,b);n&&(this.data.splice(y,0,null),this.processData());"point"===h.legendType&&this.generatePoints();d&&(c[0]&&c[0].remove?c[0].remove(!1):(c.shift(),this.updateParallelArrays(p,"shift"),m.shift()));!1!==l&&D(this,"addPoint",{point:p});this.isDirtyData=this.isDirty=!0;e&&a.redraw(f)},removePoint:function(b, +e,d){var f=this,l=f.data,m=l[b],c=f.points,a=f.chart,k=function(){c&&c.length===l.length&&c.splice(b,1);l.splice(b,1);f.options.data.splice(b,1);f.updateParallelArrays(m||{series:f},"splice",b,1);m&&m.destroy();f.isDirty=!0;f.isDirtyData=!0;e&&a.redraw()};h(d,a);e=g(e,!0);m?m.firePointEvent("remove",null,k):k()},remove:function(b,e,d,f){function l(){h.destroy(f);h.remove=null;c.isDirtyLegend=c.isDirtyBox=!0;c.linkSeries();g(b,!0)&&c.redraw(e)}var h=this,c=h.chart;!1!==d?D(h,"remove",null,l):l()}, +update:function(b,e){b=d.cleanRecursively(b,this.userOptions);D(this,"update",{options:b});var f=this,l=f.chart,h=f.userOptions,n=f.initialType||f.type,c=b.type||h.type||l.options.chart.type,a=!(this.hasDerivedData||b.dataGrouping||c&&c!==this.type||"undefined"!==typeof b.pointStart||b.pointInterval||b.pointIntervalUnit||b.keys),k=I[n].prototype,p,u=["group","markerGroup","dataLabelsGroup","transformGroup"],v=["eventOptions","navigatorSeries","baseSeries"],y=f.finishedAnimating&&{animation:!1},t= +{};a&&(v.push("data","isDirtyData","points","processedXData","processedYData","xIncrement","_hasPointMarkers","_hasPointLabels","mapMap","mapData","minY","maxY","minX","maxX"),!1!==b.visible&&v.push("area","graph"),f.parallelArrays.forEach(function(a){v.push(a+"Data")}),b.data&&(b.dataSorting&&C(f.options.dataSorting,b.dataSorting),this.setData(b.data,!1)));b=m(h,y,{index:"undefined"===typeof h.index?f.index:h.index,pointStart:g(h.pointStart,f.xData[0])},!a&&{data:f.options.data},b);a&&b.data&&(b.data= +f.options.data);v=u.concat(v);v.forEach(function(a){v[a]=f[a];delete f[a]});f.remove(!1,null,!1,!0);for(p in k)f[p]=void 0;I[c||n]?C(f,I[c||n].prototype):H(17,!0,l,{missingModuleFor:c||n});v.forEach(function(a){f[a]=v[a]});f.init(l,b);if(a&&this.points){var w=f.options;!1===w.visible?(t.graphic=1,t.dataLabel=1):f._hasPointLabels||(c=w.marker,k=w.dataLabels,c&&(!1===c.enabled||"symbol"in c)&&(t.graphic=1),k&&!1===k.enabled&&(t.dataLabel=1));this.points.forEach(function(a){a&&a.series&&(a.resolveColor(), +Object.keys(t).length&&a.destroyElements(t),!1===w.showInLegend&&a.legendItem&&l.legend.destroyItem(a))},this)}b.zIndex!==h.zIndex&&u.forEach(function(a){f[a]&&f[a].attr({zIndex:b.zIndex})});f.initialType=n;l.linkSeries();D(this,"afterUpdate");g(e,!0)&&l.redraw(a?void 0:!1)},setName:function(b){this.name=this.options.name=this.userOptions.name=b;this.chart.isDirtyLegend=!0}});C(p.prototype,{update:function(e,d){var f=this.chart,l=e&&e.events||{};e=m(this.userOptions,e);f.options[this.coll].indexOf&& +(f.options[this.coll][f.options[this.coll].indexOf(this.userOptions)]=e);b(f.options[this.coll].events,function(b,e){"undefined"===typeof l[e]&&(l[e]=void 0)});this.destroy(!0);this.init(f,C(e,{events:l}));f.isDirtyBox=!0;g(d,!0)&&f.redraw()},remove:function(b){for(var e=this.chart,d=this.coll,f=this.series,l=f.length;l--;)f[l]&&f[l].remove(!1);F(e.axes,this);F(e[d],this);w(e.options[d])?e.options[d].splice(this.options.index,1):delete e.options[d];e[d].forEach(function(b,c){b.options.index=b.userOptions.index= +c});this.destroy();e.isDirtyBox=!0;g(b,!0)&&e.redraw()},setTitle:function(b,e){this.update({title:b},e)},setCategories:function(b,e){this.update({categories:b},e)}})});Q(A,"parts/AreaSeries.js",[A["parts/Globals.js"],A["parts/Color.js"],A["mixins/legend-symbol.js"],A["parts/Utilities.js"]],function(d,f,A,q){var E=f.parse,K=q.objectEach,J=q.pick;f=q.seriesType;var L=d.Series;f("area","line",{softThreshold:!1,threshold:0},{singleStacks:!1,getStackPoints:function(d){var f=[],q=[],x=this.xAxis,D=this.yAxis, +w=D.stacking.stacks[this.stackKey],n={},t=this.index,A=D.series,m=A.length,b=J(D.options.reversedStacks,!0)?1:-1,g;d=d||this.points;if(this.options.stacking){for(g=0;gd&&C>J?(C=Math.max(d,J),D=2*J-C):CA&&D>J?(D=Math.max(A,J),C=2*J-D):D=Math.abs(f)&&.5d.closestPointRange*d.xAxis.transA;q=d.borderWidth=C(t.borderWidth,q?0:1);var m=d.xAxis,b=d.yAxis,g=t.threshold,v=d.translatedThreshold=b.getThreshold(g),h=C(t.minPointLength,5),e=d.getColumnMetrics(),p=e.width,l=d.barW=Math.max(p,1+2*q),I=d.pointXOffset=e.offset,u=d.dataMin, +y=d.dataMax;f.inverted&&(v-=.5);t.pointPadding&&(l=Math.ceil(l));D.prototype.translate.apply(d);d.points.forEach(function(e){var n=C(e.yBottom,v),t=999+Math.abs(n),q=p,c=e.plotX;t=J(e.plotY,-t,b.len+t);var a=e.plotX+I,k=l,r=Math.min(t,n),w=Math.max(t,n)-r;if(h&&Math.abs(w)h?n-h:v-(x?h:0)}L(e.options.pointWidth)&&(q=k=Math.ceil(e.options.pointWidth),a-=Math.round((q- +p)/2));e.barX=a;e.pointWidth=q;e.tooltipPos=f.inverted?[b.len+b.pos-f.plotLeft-t,m.len+m.pos-f.plotTop-(c||0)-I-k/2,w]:[a+k/2,t+b.pos-f.plotTop,w];e.shapeType=d.pointClass.prototype.shapeType||"rect";e.shapeArgs=d.crispCol.apply(d,e.isNull?[a,v,k,0]:[a,r,k,w])})},getSymbol:d.noop,drawLegendSymbol:A.drawRectangle,drawGraph:function(){this.group[this.dense?"addClass":"removeClass"]("highcharts-dense-data")},pointAttribs:function(d,f){var n=this.options,q=this.pointAttrToOptions||{};var m=q.stroke|| +"borderColor";var b=q["stroke-width"]||"borderWidth",g=d&&d.color||this.color,v=d&&d[m]||n[m]||this.color||g,h=d&&d[b]||n[b]||this[b]||0;q=d&&d.options.dashStyle||n.dashStyle;var e=C(d&&d.opacity,n.opacity,1);if(d&&this.zones.length){var p=d.getZone();g=d.options.color||p&&(p.color||d.nonZonedColor)||this.color;p&&(v=p.borderColor||v,q=p.dashStyle||q,h=p.borderWidth||h)}f&&d&&(d=H(n.states[f],d.options.states&&d.options.states[f]||{}),f=d.brightness,g=d.color||"undefined"!==typeof f&&E(g).brighten(d.brightness).get()|| +g,v=d[m]||v,h=d[b]||h,q=d.dashStyle||q,e=C(d.opacity,e));m={fill:g,stroke:v,"stroke-width":h,opacity:e};q&&(m.dashstyle=q);return m},drawPoints:function(){var d=this,f=this.chart,q=d.options,x=f.renderer,m=q.animationLimit||250,b;d.points.forEach(function(g){var n=g.graphic,h=!!n,e=n&&f.pointCount\u25cf
{series.name}
',pointFormat:"x: {point.x}
y: {point.y}
"}},{sorted:!1,requireSorting:!1,noSharedTooltip:!0,trackerGroups:["group", +"markerGroup","dataLabelsGroup"],takeOrdinalPosition:!1,drawGraph:function(){this.options.lineWidth&&q.prototype.drawGraph.call(this)},applyJitter:function(){var d=this,f=this.options.jitter,q=this.points.length;f&&this.points.forEach(function(A,x){["x","y"].forEach(function(E,H){var C="plot"+E.toUpperCase();if(f[E]&&!A.isNull){var D=d[E+"Axis"];var w=f[E]*D.transA;if(D&&!D.isLog){var n=Math.max(0,A[C]-w);D=Math.min(D.len,A[C]+w);H=1E4*Math.sin(x+H*q);A[C]=n+(D-n)*(H-Math.floor(H));"x"===E&&(A.clientX= +A.plotX)}}})})}});A(q,"afterTranslate",function(){this.applyJitter&&this.applyJitter()});""});Q(A,"mixins/centered-series.js",[A["parts/Globals.js"],A["parts/Utilities.js"]],function(d,f){var A=f.isNumber,q=f.pick,M=f.relativeLength,K=d.deg2rad;d.CenteredSeriesMixin={getCenter:function(){var d=this.options,f=this.chart,x=2*(d.slicedOffset||0),A=f.plotWidth-2*x,E=f.plotHeight-2*x,C=d.center,D=Math.min(A,E),w=d.size,n=d.innerSize||0;"string"===typeof w&&(w=parseFloat(w));"string"===typeof n&&(n=parseFloat(n)); +d=[q(C[0],"50%"),q(C[1],"50%"),q(w&&0>w?void 0:d.size,"100%"),q(n&&0>n?void 0:d.innerSize||0,"0%")];f.angular&&(d[3]=0);for(C=0;4>C;++C)w=d[C],f=2>C||2===C&&/%$/.test(w),d[C]=M(w,[A,E,D,d[2]][C])+(f?x:0);d[3]>d[2]&&(d[3]=d[2]);return d},getStartAndEndRadians:function(d,f){d=A(d)?d:0;f=A(f)&&f>d&&360>f-d?f:d+360;return{start:K*(d+-90),end:K*(f+-90)}}}});Q(A,"parts/PieSeries.js",[A["parts/Globals.js"],A["mixins/legend-symbol.js"],A["parts/Point.js"],A["parts/Utilities.js"]],function(d,f,A,q){var E= +q.addEvent,K=q.clamp,J=q.defined,L=q.fireEvent,x=q.isNumber,F=q.merge,H=q.pick,C=q.relativeLength,D=q.seriesType,w=q.setAnimation;q=d.CenteredSeriesMixin;var n=q.getStartAndEndRadians,t=d.noop,N=d.Series;D("pie","line",{center:[null,null],clip:!1,colorByPoint:!0,dataLabels:{allowOverlap:!0,connectorPadding:5,connectorShape:"fixedOffset",crookDistance:"70%",distance:30,enabled:!0,formatter:function(){return this.point.isNull?void 0:this.point.name},softConnector:!0,x:0},fillColor:void 0,ignoreHiddenPoint:!0, +inactiveOtherPoints:!0,legendType:"point",marker:null,size:null,showInLegend:!1,slicedOffset:10,stickyTracking:!1,tooltip:{followPointer:!0},borderColor:"#ffffff",borderWidth:1,lineWidth:void 0,states:{hover:{brightness:.1}}},{isCartesian:!1,requireSorting:!1,directTouch:!0,noSharedTooltip:!0,trackerGroups:["group","dataLabelsGroup"],axisTypes:[],pointAttribs:d.seriesTypes.column.prototype.pointAttribs,animate:function(d){var b=this,f=b.points,m=b.startAngleRad;d||f.forEach(function(d){var e=d.graphic, +f=d.shapeArgs;e&&f&&(e.attr({r:H(d.startR,b.center&&b.center[3]/2),start:m,end:m}),e.animate({r:f.r,start:f.start,end:f.end},b.options.animation))})},hasData:function(){return!!this.processedXData.length},updateTotals:function(){var d,b=0,f=this.points,n=f.length,h=this.options.ignoreHiddenPoint;for(d=0;d1.5*Math.PI? +x-=2*Math.PI:x<-Math.PI/2&&(x+=2*Math.PI);t.slicedTranslation={translateX:Math.round(Math.cos(x)*m),translateY:Math.round(Math.sin(x)*m)};var B=Math.cos(x)*d[2]/2;var c=Math.sin(x)*d[2]/2;t.tooltipPos=[d[0]+.7*B,d[1]+.7*c];t.half=x<-Math.PI/2||x>Math.PI/2?1:0;t.angle=x;w=Math.min(h,t.labelDistance/5);t.labelPosition={natural:{x:d[0]+B+Math.cos(x)*t.labelDistance,y:d[1]+c+Math.sin(x)*t.labelDistance},"final":{},alignment:0>t.labelDistance?"center":t.half?"right":"left",connectorPosition:{breakAt:{x:d[0]+ +B+Math.cos(x)*w,y:d[1]+c+Math.sin(x)*w},touchingSliceAt:{x:d[0]+B,y:d[1]+c}}}}L(this,"afterTranslate")},drawEmpty:function(){var d=this.options;if(0===this.total){var b=this.center[0];var f=this.center[1];this.graph||(this.graph=this.chart.renderer.circle(b,f,0).addClass("highcharts-graph").add(this.group));this.graph.animate({"stroke-width":d.borderWidth,cx:b,cy:f,r:this.center[2]/2,fill:d.fillColor||"none",stroke:d.color||"#cccccc"},this.options.animation)}else this.graph&&(this.graph=this.graph.destroy())}, +redrawPoints:function(){var d=this,b=d.chart,f=b.renderer,n,h,e,p,l=d.options.shadow;this.drawEmpty();!l||d.shadowGroup||b.styledMode||(d.shadowGroup=f.g("shadow").attr({zIndex:-1}).add(d.group));d.points.forEach(function(g){var m={};h=g.graphic;if(!g.isNull&&h){p=g.shapeArgs;n=g.getTranslate();if(!b.styledMode){var v=g.shadowGroup;l&&!v&&(v=g.shadowGroup=f.g("shadow").add(d.shadowGroup));v&&v.attr(n);e=d.pointAttribs(g,g.selected&&"select")}g.delayedRendering?(h.setRadialReference(d.center).attr(p).attr(n), +b.styledMode||h.attr(e).attr({"stroke-linejoin":"round"}).shadow(l,v),g.delayedRendering=!1):(h.setRadialReference(d.center),b.styledMode||F(!0,m,e),F(!0,m,p,n),h.animate(m));h.attr({visibility:g.visible?"inherit":"hidden"});h.addClass(g.getClassName())}else h&&(g.graphic=h.destroy())})},drawPoints:function(){var d=this.chart.renderer;this.points.forEach(function(b){b.graphic&&b.hasNewShapeType()&&(b.graphic=b.graphic.destroy());b.graphic||(b.graphic=d[b.shapeType](b.shapeArgs).add(b.series.group), +b.delayedRendering=!0)})},searchPoint:t,sortByAngle:function(d,b){d.sort(function(d,f){return"undefined"!==typeof d.angle&&(f.angle-d.angle)*b})},drawLegendSymbol:f.drawRectangle,getCenter:q.getCenter,getSymbol:t,drawGraph:null},{init:function(){A.prototype.init.apply(this,arguments);var d=this;d.name=H(d.name,"Slice");var b=function(b){d.slice("select"===b.type)};E(d,"select",b);E(d,"unselect",b);return d},isValid:function(){return x(this.y)&&0<=this.y},setVisible:function(d,b){var f=this,m=f.series, +h=m.chart,e=m.options.ignoreHiddenPoint;b=H(b,e);d!==f.visible&&(f.visible=f.options.visible=d="undefined"===typeof d?!f.visible:d,m.options.data[m.data.indexOf(f)]=f.options,["graphic","dataLabel","connector","shadowGroup"].forEach(function(b){if(f[b])f[b][d?"show":"hide"](!0)}),f.legendItem&&h.legend.colorizeItem(f,d),d||"hover"!==f.state||f.setState(""),e&&(m.isDirty=!0),b&&h.redraw())},slice:function(d,b,f){var g=this.series;w(f,g.chart);H(b,!0);this.sliced=this.options.sliced=J(d)?d:!this.sliced; +g.options.data[g.data.indexOf(this)]=this.options;this.graphic&&this.graphic.animate(this.getTranslate());this.shadowGroup&&this.shadowGroup.animate(this.getTranslate())},getTranslate:function(){return this.sliced?this.slicedTranslation:{translateX:0,translateY:0}},haloPath:function(d){var b=this.shapeArgs;return this.sliced||!this.visible?[]:this.series.chart.renderer.symbols.arc(b.x,b.y,b.r+d,b.r+d,{innerR:b.r-1,start:b.start,end:b.end})},connectorShapes:{fixedOffset:function(d,b,f){var g=b.breakAt; +b=b.touchingSliceAt;return[["M",d.x,d.y],f.softConnector?["C",d.x+("left"===d.alignment?-5:5),d.y,2*g.x-b.x,2*g.y-b.y,g.x,g.y]:["L",g.x,g.y],["L",b.x,b.y]]},straight:function(d,b){b=b.touchingSliceAt;return[["M",d.x,d.y],["L",b.x,b.y]]},crookedLine:function(d,b,f){b=b.touchingSliceAt;var g=this.series,h=g.center[0],e=g.chart.plotWidth,m=g.chart.plotLeft;g=d.alignment;var l=this.shapeArgs.r;f=C(f.crookDistance,1);e="left"===g?h+l+(e+m-h-l)*(1-f):m+(h-l)*f;f=["L",e,d.y];h=!0;if("left"===g?e>d.x||e< +b.x:eb.x)h=!1;d=[["M",d.x,d.y]];h&&d.push(f);d.push(["L",b.x,b.y]);return d}},getConnectorPath:function(){var d=this.labelPosition,b=this.series.options.dataLabels,f=b.connectorShape,n=this.connectorShapes;n[f]&&(f=n[f]);return f.call(this,{x:d.final.x,y:d.final.y,alignment:d.alignment},d.connectorPosition,b)}});""});Q(A,"parts/DataLabels.js",[A["parts/Globals.js"],A["parts/Utilities.js"]],function(d,f){var A=f.animObject,q=f.arrayMax,M=f.clamp,K=f.defined,J=f.extend,L=f.fireEvent,x=f.format, +F=f.isArray,H=f.merge,C=f.objectEach,D=f.pick,w=f.relativeLength,n=f.splat,t=f.stableSort;f=d.noop;var N=d.Series,m=d.seriesTypes;d.distribute=function(b,f,m){function g(b,e){return b.target-e.target}var e,n=!0,l=b,v=[];var u=0;var q=l.reducedLen||f;for(e=b.length;e--;)u+=b[e].size;if(u>q){t(b,function(b,e){return(e.rank||0)-(b.rank||0)});for(u=e=0;u<=q;)u+=b[e].size,e++;v=b.splice(e-1,b.length)}t(b,g);for(b=b.map(function(b){return{size:b.size,targets:[b.target],align:D(b.align,.5)}});n;){for(e= +b.length;e--;)n=b[e],u=(Math.min.apply(0,n.targets)+Math.max.apply(0,n.targets))/2,n.pos=M(u-n.size*n.align,0,f-n.size);e=b.length;for(n=!1;e--;)0b[e].pos&&(b[e-1].size+=b[e].size,b[e-1].targets=b[e-1].targets.concat(b[e].targets),b[e-1].align=.5,b[e-1].pos+b[e-1].size>f&&(b[e-1].pos=f-b[e-1].size),b.splice(e,1),n=!0)}l.push.apply(l,v);e=0;b.some(function(b){var g=0;if(b.targets.some(function(){l[e].pos=b.pos+g;if("undefined"!==typeof m&&Math.abs(l[e].pos-l[e].target)>m)return l.slice(0, +e+1).forEach(function(b){delete b.pos}),l.reducedLen=(l.reducedLen||f)-.1*f,l.reducedLen>.1*f&&d.distribute(l,f,m),!0;g+=l[e].size;e++}))return!0});t(l,g)};N.prototype.drawDataLabels=function(){function b(c,a){var b=a.filter;return b?(a=b.operator,c=c[b.property],b=b.value,">"===a&&c>b||"<"===a&&c="===a&&c>=b||"<="===a&&c<=b||"=="===a&&c==b||"==="===a&&c===b?!0:!1):!0}function d(c,a){var b=[],e;if(F(c)&&!F(a))b=c.map(function(c){return H(c,a)});else if(F(a)&&!F(c))b=a.map(function(a){return H(c, +a)});else if(F(c)||F(a))for(e=Math.max(c.length,a.length);e--;)b[e]=H(c[e],a[e]);else b=H(c,a);return b}var f=this,h=f.chart,e=f.options,m=e.dataLabels,l=f.points,q,u=f.hasRendered||0,t=A(e.animation).duration,w=Math.min(t,200),E=!h.renderer.forExport&&D(m.defer,0m||e.stacking?c.contrastColor:"#000000"):delete c.contrastColor,e.cursor&&(u.cursor=e.cursor));var q={r:a.borderRadius|| +0,rotation:v,padding:a.padding,zIndex:1};h.styledMode||(q.fill=a.backgroundColor,q.stroke=a.borderColor,q["stroke-width"]=a.borderWidth);C(q,function(a,c){"undefined"===typeof a&&delete q[c]})}!l||g&&K(p)?g&&K(p)&&(l?q.text=p:(c.dataLabels=c.dataLabels||[],l=c.dataLabels[d]=v?J.text(p,0,-9999,a.useHTML).addClass("highcharts-data-label"):J.label(p,0,-9999,a.shape,null,null,a.useHTML,null,"data-label"),d||(c.dataLabel=l),l.addClass(" highcharts-data-label-color-"+c.colorIndex+" "+(a.className||"")+ +(a.useHTML?" highcharts-tracker":""))),l.options=a,l.attr(q),h.styledMode||l.css(u).shadow(a.shadow),l.added||l.add(B),a.textPath&&!a.useHTML&&(l.setTextPath(c.getDataLabelPath&&c.getDataLabelPath(l)||c.graphic,a.textPath),c.dataLabelPath&&!a.textPath.enabled&&(c.dataLabelPath=c.dataLabelPath.destroy())),f.alignDataLabel(c,l,a,null,n)):(c.dataLabel=c.dataLabel&&c.dataLabel.destroy(),c.dataLabels&&(1===c.dataLabels.length?delete c.dataLabels:delete c.dataLabels[d]),d||delete c.dataLabel,k&&(c.connector= +c.connector.destroy(),c.connectors&&(1===c.connectors.length?delete c.connectors:delete c.connectors[d])))})})}L(this,"afterDrawDataLabels")};N.prototype.alignDataLabel=function(b,d,f,h,e){var g=this,l=this.chart,m=this.isCartesian&&l.inverted,n=this.enabledDataSorting,q=D(b.dlBox&&b.dlBox.centerX,b.plotX,-9999),v=D(b.plotY,-9999),t=d.getBBox(),w=f.rotation,x=f.align,c=l.isInsidePlot(q,Math.round(v),m),a="justify"===D(f.overflow,n?"none":"justify"),k=this.visible&&!1!==b.visible&&(b.series.forceDL|| +n&&!a||c||f.inside&&h&&l.isInsidePlot(q,m?h.x+1:h.y+h.height-1,m));var r=function(f){n&&g.xAxis&&!a&&g.setDataLabelStartPos(b,d,e,c,f)};if(k){var z=l.renderer.fontMetrics(l.styledMode?void 0:f.style.fontSize,d).b;h=J({x:m?this.yAxis.len-v:q,y:Math.round(m?this.xAxis.len-q:v),width:0,height:0},h);J(f,{width:t.width,height:t.height});w?(a=!1,q=l.renderer.rotCorr(z,w),q={x:h.x+f.x+h.width/2+q.x,y:h.y+f.y+{top:0,middle:.5,bottom:1}[f.verticalAlign]*h.height},r(q),d[e?"attr":"animate"](q).attr({align:x}), +r=(w+720)%360,r=180r,"left"===x?q.y-=r?t.height:0:"center"===x?(q.x-=t.width/2,q.y-=t.height/2):"right"===x&&(q.x-=t.width,q.y-=r?0:t.height),d.placed=!0,d.alignAttr=q):(r(h),d.align(f,null,h),q=d.alignAttr);a&&0<=h.height?this.justifyDataLabel(d,f,q,t,h,e):D(f.crop,!0)&&(k=l.isInsidePlot(q.x,q.y)&&l.isInsidePlot(q.x+t.width,q.y+t.height));if(f.shape&&!w)d[e?"attr":"animate"]({anchorX:m?l.plotWidth-b.plotY:b.plotX,anchorY:m?l.plotHeight-b.plotX:b.plotY})}e&&n&&(d.placed=!1);k||n&&!a||(d.hide(!0), +d.placed=!1)};N.prototype.setDataLabelStartPos=function(b,d,f,h,e){var g=this.chart,l=g.inverted,m=this.xAxis,n=m.reversed,q=l?d.height/2:d.width/2;b=(b=b.pointWidth)?b/2:0;m=l?e.x:n?-q-b:m.width-q+b;e=l?n?this.yAxis.height-q+b:-q-b:e.y;d.startXPos=m;d.startYPos=e;h?"hidden"===d.visibility&&(d.show(),d.attr({opacity:0}).animate({opacity:1})):d.attr({opacity:1}).animate({opacity:0},void 0,d.hide);g.hasRendered&&(f&&d.attr({x:d.startXPos,y:d.startYPos}),d.placed=!0)};N.prototype.justifyDataLabel=function(b, +d,f,h,e,m){var g=this.chart,n=d.align,p=d.verticalAlign,q=b.box?0:b.padding||0;var v=f.x+q;if(0>v){"right"===n?(d.align="left",d.inside=!0):d.x=-v;var t=!0}v=f.x+h.width-q;v>g.plotWidth&&("left"===n?(d.align="right",d.inside=!0):d.x=g.plotWidth-v,t=!0);v=f.y+q;0>v&&("bottom"===p?(d.verticalAlign="top",d.inside=!0):d.y=-v,t=!0);v=f.y+h.height-q;v>g.plotHeight&&("top"===p?(d.verticalAlign="bottom",d.inside=!0):d.y=g.plotHeight-v,t=!0);t&&(b.placed=!m,b.align(d,null,e));return t};m.pie&&(m.pie.prototype.dataLabelPositioners= +{radialDistributionY:function(b){return b.top+b.distributeBox.pos},radialDistributionX:function(b,d,f,h){return b.getX(fd.bottom-2?h:f,d.half,d)},justify:function(b,d,f){return f[0]+(b.half?-1:1)*(d+b.labelDistance)},alignToPlotEdges:function(b,d,f,h){b=b.getBBox().width;return d?b+h:f-b-h},alignToConnectors:function(b,d,f,h){var e=0,g;b.forEach(function(b){g=b.dataLabel.getBBox().width;g>e&&(e=g)});return d?e+h:f-e-h}},m.pie.prototype.drawDataLabels=function(){var b=this,f=b.data,m,h= +b.chart,e=b.options.dataLabels||{},n=e.connectorPadding,l,t=h.plotWidth,u=h.plotHeight,y=h.plotLeft,w=Math.round(h.chartWidth/3),x,C=b.center,B=C[2]/2,c=C[1],a,k,r,z,A=[[],[]],E,F,L,J,M=[0,0,0,0],Q=b.dataLabelPositioners,O;b.visible&&(e.enabled||b._hasPointLabels)&&(f.forEach(function(a){a.dataLabel&&a.visible&&a.dataLabel.shortened&&(a.dataLabel.attr({width:"auto"}).css({width:"auto",textOverflow:"clip"}),a.dataLabel.shortened=!1)}),N.prototype.drawDataLabels.apply(b),f.forEach(function(a){a.dataLabel&& +(a.visible?(A[a.half].push(a),a.dataLabel._pos=null,!K(e.style.width)&&!K(a.options.dataLabels&&a.options.dataLabels.style&&a.options.dataLabels.style.width)&&a.dataLabel.getBBox().width>w&&(a.dataLabel.css({width:Math.round(.7*w)+"px"}),a.dataLabel.shortened=!0)):(a.dataLabel=a.dataLabel.destroy(),a.dataLabels&&1===a.dataLabels.length&&delete a.dataLabels))}),A.forEach(function(f,g){var l=f.length,p=[],q;if(l){b.sortByAngle(f,g-.5);if(0t-n&&0===g&&(v=Math.round(E+k-t+n),M[1]=Math.max(v,M[1])),0>F-z/2?M[0]=Math.max(Math.round(-F+z/2),M[0]):F+z/2>u&&(M[2]=Math.max(Math.round(F+z/2-u),M[2])),a.sideOverflow=v)}}}),0===q(M)||this.verifyDataLabelOverflow(M))&&(this.placeDataLabels(),this.points.forEach(function(c){O=H(e,c.options.dataLabels);if(l=D(O.connectorWidth,1)){var d;x=c.connector;if((a=c.dataLabel)&&a._pos&&c.visible&&0D(this.translatedThreshold,l.yAxis.len)),q= +D(f.inside,!!this.options.stacking);m&&(h=H(m),0>h.y&&(h.height+=h.y,h.y=0),m=h.y+h.height-l.yAxis.len,0J.x+J.width||m.x+m.widthJ.y+J.height||m.y+m.height=a&&l<=k||h||!L(l))m=!0;f[h?"zoomX":"zoomY"]&&m&&(e=c.zoom(b.min,b.max),c.displayBtn&&(g=!0))});var h=d.resetZoomButton;g&&!h? +d.showResetZoom():!g&&w(h)&&(d.resetZoomButton=h.destroy());e&&d.redraw(N(d.options.chart.animation,b&&b.animation,100>d.pointCount))},pan:function(b,e){var f=this,g=f.hoverPoints,l=f.options.chart,h=f.options.mapNavigation&&f.options.mapNavigation.enabled,m;e="object"===typeof e?e:{enabled:e,type:"x"};l&&l.panning&&(l.panning=e);var n=e.type;F(this,"pan",{originalEvent:b},function(){g&&g.forEach(function(a){a.setState()});var c=[1];"xy"===n?c=[1,0]:"y"===n&&(c=[0]);c.forEach(function(a){var c=f[a? +"xAxis":"yAxis"][0],e=c.options,g=c.horiz,l=b[g?"chartX":"chartY"];g=g?"mouseDownX":"mouseDownY";var p=f[g],q=(c.pointRange||0)/2,u=c.reversed&&!f.inverted||!c.reversed&&f.inverted?-1:1,t=c.getExtremes(),v=c.toValue(p-l,!0)+q*u;u=c.toValue(p+c.len-l,!0)-q*u;var w=u=u&&v<=q)c.setExtremes(p, +v,!1,!1,{trigger:"pan"}),f.resetZoomButton||h||!n.match("y")||(f.showResetZoom(),c.displayBtn=!1),m=!0;f[g]=l}});m&&f.redraw(!1);J(f.container,{cursor:"move"})})}});x(A.prototype,{select:function(b,d){var e=this,f=e.series,g=f.chart;this.selectedStaging=b=N(b,!e.selected);e.firePointEvent(b?"select":"unselect",{accumulate:d},function(){e.selected=e.options.selected=b;f.options.data[f.data.indexOf(e)]=e.options;e.setState(b&&"select");d||g.getSelectedPoints().forEach(function(b){var d=b.series;b.selected&& +b!==e&&(b.selected=b.options.selected=!1,d.options.data[d.data.indexOf(b)]=b.options,b.setState(g.hoverPoints&&d.options.inactiveOtherPoints?"inactive":""),b.firePointEvent("unselect"))})});delete this.selectedStaging},onMouseOver:function(b){var d=this.series.chart,e=d.pointer;b=b?e.normalize(b):e.getChartCoordinatesFromPoint(this,d.inverted);e.runPointActions(b,this)},onMouseOut:function(){var b=this.series.chart;this.firePointEvent("mouseOut");this.series.options.inactiveOtherPoints||(b.hoverPoints|| +[]).forEach(function(b){b.setState()});b.hoverPoints=b.hoverPoint=null},importEvents:function(){if(!this.hasImportedEvents){var b=this,d=n(b.series.options.point,b.options).events;b.events=d;t(d,function(d,e){C(d)&&E(b,e,d)});this.hasImportedEvents=!0}},setState:function(d,e){var f=this.series,g=this.state,l=f.options.states[d||"normal"]||{},h=b[f.type].marker&&f.options.marker,m=h&&!1===h.enabled,n=h&&h.states&&h.states[d||"normal"]||{},c=!1===n.enabled,a=f.stateMarkerGraphic,k=this.marker||{},p= +f.chart,q=f.halo,t,v=h&&f.markerAttribs;d=d||"";if(!(d===this.state&&!e||this.selected&&"select"!==d||!1===l.enabled||d&&(c||m&&!1===n.enabled)||d&&k.states&&k.states[d]&&!1===k.states[d].enabled)){this.state=d;v&&(t=f.markerAttribs(this,d));if(this.graphic){g&&this.graphic.removeClass("highcharts-point-"+g);d&&this.graphic.addClass("highcharts-point-"+d);if(!p.styledMode){var w=f.pointAttribs(this,d);var A=N(p.options.chart.animation,l.animation);f.options.inactiveOtherPoints&&w.opacity&&((this.dataLabels|| +[]).forEach(function(a){a&&a.animate({opacity:w.opacity},A)}),this.connector&&this.connector.animate({opacity:w.opacity},A));this.graphic.animate(w,A)}t&&this.graphic.animate(t,N(p.options.chart.animation,n.animation,h.animation));a&&a.hide()}else{if(d&&n){g=k.symbol||f.symbol;a&&a.currentSymbol!==g&&(a=a.destroy());if(t)if(a)a[e?"animate":"attr"]({x:t.x,y:t.y});else g&&(f.stateMarkerGraphic=a=p.renderer.symbol(g,t.x,t.y,t.width,t.height).add(f.markerGroup),a.currentSymbol=g);!p.styledMode&&a&&a.attr(f.pointAttribs(this, +d))}a&&(a[d&&this.isInside?"show":"hide"](),a.element.point=this)}d=l.halo;l=(a=this.graphic||a)&&a.visibility||"inherit";d&&d.size&&a&&"hidden"!==l&&!this.isCluster?(q||(f.halo=q=p.renderer.path().add(a.parentGroup)),q.show()[e?"animate":"attr"]({d:this.haloPath(d.size)}),q.attr({"class":"highcharts-halo highcharts-color-"+N(this.colorIndex,f.colorIndex)+(this.className?" "+this.className:""),visibility:l,zIndex:-1}),q.point=this,p.styledMode||q.attr(x({fill:this.color||f.color,"fill-opacity":d.opacity}, +d.attributes))):q&&q.point&&q.point.haloPath&&q.animate({d:q.point.haloPath(0)},null,q.hide);F(this,"afterSetState")}},haloPath:function(b){return this.series.chart.renderer.symbols.circle(Math.floor(this.plotX)-b,this.plotY-b,2*b,2*b)}});x(v.prototype,{onMouseOver:function(){var b=this.chart,d=b.hoverSeries;b.pointer.setHoverChartIndex();if(d&&d!==this)d.onMouseOut();this.options.events.mouseOver&&F(this,"mouseOver");this.setState("hover");b.hoverSeries=this},onMouseOut:function(){var b=this.options, +d=this.chart,e=d.tooltip,f=d.hoverPoint;d.hoverSeries=null;if(f)f.onMouseOut();this&&b.events.mouseOut&&F(this,"mouseOut");!e||this.stickyTracking||e.shared&&!this.noSharedTooltip||e.hide();d.series.forEach(function(b){b.setState("",!0)})},setState:function(b,d){var e=this,f=e.options,g=e.graph,l=f.inactiveOtherPoints,h=f.states,m=f.lineWidth,c=f.opacity,a=N(h[b||"normal"]&&h[b||"normal"].animation,e.chart.options.chart.animation);f=0;b=b||"";if(e.state!==b&&([e.group,e.markerGroup,e.dataLabelsGroup].forEach(function(a){a&& +(e.state&&a.removeClass("highcharts-series-"+e.state),b&&a.addClass("highcharts-series-"+b))}),e.state=b,!e.chart.styledMode)){if(h[b]&&!1===h[b].enabled)return;b&&(m=h[b].lineWidth||m+(h[b].lineWidthPlus||0),c=N(h[b].opacity,c));if(g&&!g.dashstyle)for(h={"stroke-width":m},g.animate(h,a);e["zone-graph-"+f];)e["zone-graph-"+f].attr(h),f+=1;l||[e.group,e.markerGroup,e.dataLabelsGroup,e.labelBySeries].forEach(function(b){b&&b.animate({opacity:c},a)})}d&&l&&e.points&&e.setAllPointsToState(b)},setAllPointsToState:function(b){this.points.forEach(function(d){d.setState&& +d.setState(b)})},setVisible:function(b,d){var e=this,f=e.chart,g=e.legendItem,h=f.options.chart.ignoreHiddenSeries,l=e.visible;var m=(e.visible=b=e.options.visible=e.userOptions.visible="undefined"===typeof b?!l:b)?"show":"hide";["group","dataLabelsGroup","markerGroup","tracker","tt"].forEach(function(b){if(e[b])e[b][m]()});if(f.hoverSeries===e||(f.hoverPoint&&f.hoverPoint.series)===e)e.onMouseOut();g&&f.legend.colorizeItem(e,b);e.isDirty=!0;e.options.stacking&&f.series.forEach(function(b){b.options.stacking&& +b.visible&&(b.isDirty=!0)});e.linkedSeries.forEach(function(c){c.setVisible(b,!1)});h&&(f.isDirtyBox=!0);F(e,m);!1!==d&&f.redraw()},show:function(){this.setVisible(!0)},hide:function(){this.setVisible(!1)},select:function(b){this.selected=b=this.options.selected="undefined"===typeof b?!this.selected:b;this.checkbox&&(this.checkbox.checked=b);F(this,b?"select":"unselect")},drawTracker:p.drawTrackerGraph})});Q(A,"parts/Responsive.js",[A["parts/Globals.js"],A["parts/Utilities.js"]],function(d,f){var A= +f.find,q=f.isArray,M=f.isObject,K=f.merge,J=f.objectEach,L=f.pick,x=f.splat,F=f.uniqueKey;d=d.Chart;d.prototype.setResponsive=function(d,f){var q=this.options.responsive,w=[],n=this.currentResponsive;!f&&q&&q.rules&&q.rules.forEach(function(d){"undefined"===typeof d._id&&(d._id=F());this.matchResponsiveRule(d,w)},this);f=K.apply(0,w.map(function(d){return A(q.rules,function(f){return f._id===d}).chartOptions}));f.isResponsiveOptions=!0;w=w.toString()||void 0;w!==(n&&n.ruleIds)&&(n&&this.update(n.undoOptions, +d,!0),w?(n=this.currentOptions(f),n.isResponsiveOptions=!0,this.currentResponsive={ruleIds:w,mergedOptions:f,undoOptions:n},this.update(f,d,!0)):this.currentResponsive=void 0)};d.prototype.matchResponsiveRule=function(d,f){var q=d.condition;(q.callback||function(){return this.chartWidth<=L(q.maxWidth,Number.MAX_VALUE)&&this.chartHeight<=L(q.maxHeight,Number.MAX_VALUE)&&this.chartWidth>=L(q.minWidth,0)&&this.chartHeight>=L(q.minHeight,0)}).call(this)&&f.push(d._id)};d.prototype.currentOptions=function(d){function f(d, +t,w,m){var b;J(d,function(d,n){if(!m&&-1} + */ + charts: [], + /** + * A hook for defining additional date format specifiers. New + * specifiers are defined as key-value pairs by using the + * specifier as key, and a function which takes the timestamp as + * value. This function returns the formatted portion of the + * date. + * + * @sample highcharts/global/dateformats/ + * Adding support for week number + * + * @name Highcharts.dateFormats + * @type {Highcharts.Dictionary} + */ + dateFormats: {} + }; + + return H; + }); + _registerModule(_modules, 'parts/Utilities.js', [_modules['parts/Globals.js']], function (H) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * An animation configuration. Animation configurations can also be defined as + * booleans, where `false` turns off animation and `true` defaults to a duration + * of 500ms. + * + * @interface Highcharts.AnimationOptionsObject + */ /** + * A callback function to exectute when the animation finishes. + * @name Highcharts.AnimationOptionsObject#complete + * @type {Function|undefined} + */ /** + * The animation duration in milliseconds. + * @name Highcharts.AnimationOptionsObject#duration + * @type {number|undefined} + */ /** + * The name of an easing function as defined on the `Math` object. + * @name Highcharts.AnimationOptionsObject#easing + * @type {string|Function|undefined} + */ /** + * A callback function to execute on each step of each attribute or CSS property + * that's being animated. The first argument contains information about the + * animation and progress. + * @name Highcharts.AnimationOptionsObject#step + * @type {Function|undefined} + */ + /** + * Creates a frame for the animated SVG element. + * + * @callback Highcharts.AnimationStepCallbackFunction + * + * @param {Highcharts.SVGElement} this + * The SVG element to animate. + * + * @return {void} + */ + /** + * Interface description for a class. + * + * @interface Highcharts.Class + * @extends Function + */ /** + * Class costructor. + * @function Highcharts.Class#new + * @param {...Array<*>} args + * Constructor arguments. + * @return {T} + * Class instance. + */ + /** + * A style object with camel case property names to define visual appearance of + * a SVG element or HTML element. The properties can be whatever styles are + * supported on the given SVG or HTML element. + * + * @example + * { + * fontFamily: 'monospace', + * fontSize: '1.2em' + * } + * + * @interface Highcharts.CSSObject + */ /** + * @name Highcharts.CSSObject#[key:string] + * @type {boolean|number|string|undefined} + */ /** + * Background style for the element. + * @name Highcharts.CSSObject#background + * @type {string|undefined} + */ /** + * Background color of the element. + * @name Highcharts.CSSObject#backgroundColor + * @type {Highcharts.ColorString|undefined} + */ /** + * Border style for the element. + * @name Highcharts.CSSObject#border + * @type {string|undefined} + */ /** + * Radius of the element border. + * @name Highcharts.CSSObject#borderRadius + * @type {number|undefined} + */ /** + * Color used in the element. The 'contrast' option is a Highcharts custom + * property that results in black or white, depending on the background of the + * element. + * @name Highcharts.CSSObject#color + * @type {'contrast'|Highcharts.ColorString|undefined} + */ /** + * Style of the mouse cursor when resting over the element. + * @name Highcharts.CSSObject#cursor + * @type {Highcharts.CursorValue|undefined} + */ /** + * Font family of the element text. Multiple values have to be in decreasing + * preference order and separated by comma. + * @name Highcharts.CSSObject#fontFamily + * @type {string|undefined} + */ /** + * Font size of the element text. + * @name Highcharts.CSSObject#fontSize + * @type {string|undefined} + */ /** + * Font weight of the element text. + * @name Highcharts.CSSObject#fontWeight + * @type {string|undefined} + */ /** + * Height of the element. + * @name Highcharts.CSSObject#height + * @type {number|undefined} + */ /** + * Width of the element border. + * @name Highcharts.CSSObject#lineWidth + * @type {number|undefined} + */ /** + * Opacity of the element. + * @name Highcharts.CSSObject#opacity + * @type {number|undefined} + */ /** + * Space around the element content. + * @name Highcharts.CSSObject#padding + * @type {string|undefined} + */ /** + * Behaviour of the element when the mouse cursor rests over it. + * @name Highcharts.CSSObject#pointerEvents + * @type {string|undefined} + */ /** + * Positioning of the element. + * @name Highcharts.CSSObject#position + * @type {string|undefined} + */ /** + * Alignment of the element text. + * @name Highcharts.CSSObject#textAlign + * @type {string|undefined} + */ /** + * Additional decoration of the element text. + * @name Highcharts.CSSObject#textDecoration + * @type {string|undefined} + */ /** + * Outline style of the element text. + * @name Highcharts.CSSObject#textOutline + * @type {string|undefined} + */ /** + * Line break style of the element text. Highcharts SVG elements support + * `ellipsis` when a `width` is set. + * @name Highcharts.CSSObject#textOverflow + * @type {string|undefined} + */ /** + * Top spacing of the element relative to the parent element. + * @name Highcharts.CSSObject#top + * @type {string|undefined} + */ /** + * Animated transition of selected element properties. + * @name Highcharts.CSSObject#transition + * @type {string|undefined} + */ /** + * Line break style of the element text. + * @name Highcharts.CSSObject#whiteSpace + * @type {string|undefined} + */ /** + * Width of the element. + * @name Highcharts.CSSObject#width + * @type {number|undefined} + */ + /** + * All possible cursor styles. + * + * @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 + */ + /** + * All possible dash styles. + * + * @typedef {'Dash'|'DashDot'|'Dot'|'LongDash'|'LongDashDot'|'LongDashDotDot'|'ShortDash'|'ShortDashDot'|'ShortDashDotDot'|'ShortDot'|'Solid'} Highcharts.DashStyleValue + */ + /** + * Generic dictionary in TypeScript notation. + * + * @interface Highcharts.Dictionary + */ /** + * @name Highcharts.Dictionary#[key:string] + * @type {T} + */ + /** + * The function callback to execute when the event is fired. The `this` context + * contains the instance, that fired the event. + * + * @callback Highcharts.EventCallbackFunction + * + * @param {T} this + * + * @param {Highcharts.Dictionary<*>|Event} [eventArguments] + * Event arguments. + * + * @return {boolean|void} + */ + /** + * The event options for adding function callback. + * + * @interface Highcharts.EventOptionsObject + */ /** + * The order the event handler should be called. This opens for having one + * handler be called before another, independent of in which order they were + * added. + * @name Highcharts.EventOptionsObject#order + * @type {number} + */ + /** + * Formats data as a string. Usually the data is accessible throught the `this` + * keyword. + * + * @callback Highcharts.FormatterCallbackFunction + * + * @param {T} this + * Context to format + * + * @return {string} + * Formatted text + */ + /** + * An object of key-value pairs for HTML attributes. + * + * @typedef {Highcharts.Dictionary} Highcharts.HTMLAttributes + */ + /** + * An HTML DOM element. The type is a reference to the regular HTMLElement in + * the global scope. + * + * @typedef {global.HTMLElement} Highcharts.HTMLDOMElement + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement + */ + /** + * The iterator callback. + * + * @callback Highcharts.ObjectEachCallbackFunction + * + * @param {T} this + * The context. + * + * @param {*} value + * The property value. + * + * @param {string} key + * The property key. + * + * @param {*} obj + * The object that objectEach is being applied to. + */ + /** + * An object containing `left` and `top` properties for the position in the + * page. + * + * @interface Highcharts.OffsetObject + */ /** + * Left distance to the page border. + * @name Highcharts.OffsetObject#left + * @type {number} + */ /** + * Top distance to the page border. + * @name Highcharts.OffsetObject#top + * @type {number} + */ + /** + * Describes a range. + * + * @interface Highcharts.RangeObject + */ /** + * Maximum number of the range. + * @name Highcharts.RangeObject#max + * @type {number} + */ /** + * Minimum number of the range. + * @name Highcharts.RangeObject#min + * @type {number} + */ + /** + * If a number is given, it defines the pixel length. If a percentage string is + * given, like for example `'50%'`, the setting defines a length relative to a + * base size, for example the size of a container. + * + * @typedef {number|string} Highcharts.RelativeSize + */ + /** + * Proceed function to call original (wrapped) function. + * + * @callback Highcharts.WrapProceedFunction + * + * @param {*} [arg1] + * Optional argument. Without any arguments defaults to first argument of + * the wrapping function. + * + * @param {*} [arg2] + * Optional argument. Without any arguments defaults to second argument + * of the wrapping function. + * + * @param {*} [arg3] + * Optional argument. Without any arguments defaults to third argument of + * the wrapping function. + * + * @return {*} + * Return value of the original function. + */ + /** + * The Highcharts object is the placeholder for all other members, and various + * utility functions. The most important member of the namespace would be the + * chart constructor. + * + * @example + * var chart = Highcharts.chart('container', { ... }); + * + * @namespace Highcharts + */ + H.timers = []; + var charts = H.charts, doc = H.doc, win = H.win; + /** + * Provide error messages for debugging, with links to online explanation. This + * function can be overridden to provide custom error handling. + * + * @sample highcharts/chart/highcharts-error/ + * Custom error handler + * + * @function Highcharts.error + * + * @param {number|string} code + * The error code. See + * [errors.xml](https://github.com/highcharts/highcharts/blob/master/errors/errors.xml) + * for available codes. If it is a string, the error message is printed + * directly in the console. + * + * @param {boolean} [stop=false] + * Whether to throw an error or just log a warning in the console. + * + * @param {Highcharts.Chart} [chart] + * Reference to the chart that causes the error. Used in 'debugger' + * module to display errors directly on the chart. + * Important note: This argument is undefined for errors that lack + * access to the Chart instance. + * + * @param {Highcharts.Dictionary} [params] + * Additional parameters for the generated message. + * + * @return {void} + */ + var error = H.error = function (code, stop, chart, params) { + var isCode = isNumber(code), message = isCode ? + "Highcharts error #" + code + ": www.highcharts.com/errors/" + code + "/" : + code.toString(), defaultHandler = function () { + if (stop) { + throw new Error(message); + } + // else ... + if (win.console) { + console.log(message); // eslint-disable-line no-console + } + }; + if (typeof params !== 'undefined') { + var additionalMessages_1 = ''; + if (isCode) { + message += '?'; + } + objectEach(params, function (value, key) { + additionalMessages_1 += ('\n' + key + ': ' + value); + if (isCode) { + message += encodeURI(key) + '=' + encodeURI(value); + } + }); + message += additionalMessages_1; + } + if (chart) { + fireEvent(chart, 'displayError', { code: code, message: message, params: params }, defaultHandler); + } + else { + defaultHandler(); + } + }; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * An animator object used internally. One instance applies to one property + * (attribute or style prop) on one element. Animation is always initiated + * through {@link SVGElement#animate}. + * + * @example + * var rect = renderer.rect(0, 0, 10, 10).add(); + * rect.animate({ width: 100 }); + * + * @private + * @class + * @name Highcharts.Fx + */ + var Fx = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + /** + * + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGElement} elem + * The element to animate. + * + * @param {Highcharts.AnimationOptionsObject} options + * Animation options. + * + * @param {string} prop + * The single attribute or CSS property to animate. + */ + function Fx(elem, options, prop) { + this.options = options; + this.elem = elem; + this.prop = prop; + } + /* * + * + * Functions + * + * */ + /** + * Set the current step of a path definition on SVGElement. + * + * @function Highcharts.Fx#dSetter + * + * @return {void} + */ + Fx.prototype.dSetter = function () { + var paths = this.paths, start = paths && paths[0], end = paths && paths[1], path = [], now = this.now || 0; + // Land on the final path without adjustment points appended in the ends + if (now === 1 || !start || !end) { + path = this.toD || []; + } + else if (start.length === end.length && now < 1) { + for (var i = 0; i < end.length; i++) { + // Tween between the start segment and the end segment. Start + // with a copy of the end segment and tween the appropriate + // numerics + var startSeg = start[i]; + var endSeg = end[i]; + var tweenSeg = []; + for (var j = 0; j < endSeg.length; j++) { + var startItem = startSeg[j]; + var endItem = endSeg[j]; + // Tween numbers + if (typeof startItem === 'number' && + typeof endItem === 'number' && + // Arc boolean flags + !(endSeg[0] === 'A' && (j === 4 || j === 5))) { + tweenSeg[j] = startItem + now * (endItem - startItem); + // Strings, take directly from the end segment + } + else { + tweenSeg[j] = endItem; + } + } + path.push(tweenSeg); + } + // If animation is finished or length not matching, land on right value + } + else { + path = end; + } + this.elem.attr('d', path, void 0, true); + }; + /** + * Update the element with the current animation step. + * + * @function Highcharts.Fx#update + * + * @return {void} + */ + Fx.prototype.update = function () { + var elem = this.elem, prop = this.prop, // if destroyed, it is null + now = this.now, step = this.options.step; + // Animation setter defined from outside + if (this[prop + 'Setter']) { + this[prop + 'Setter'](); + // Other animations on SVGElement + } + else if (elem.attr) { + if (elem.element) { + elem.attr(prop, now, null, true); + } + // HTML styles, raw HTML content like container size + } + else { + elem.style[prop] = now + this.unit; + } + if (step) { + step.call(elem, now, this); + } + }; + /** + * Run an animation. + * + * @function Highcharts.Fx#run + * + * @param {number} from + * The current value, value to start from. + * + * @param {number} to + * The end value, value to land on. + * + * @param {string} unit + * The property unit, for example `px`. + * + * @return {void} + */ + Fx.prototype.run = function (from, to, unit) { + var self = this, options = self.options, timer = function (gotoEnd) { + return timer.stopped ? false : self.step(gotoEnd); + }, requestAnimationFrame = win.requestAnimationFrame || + function (step) { + setTimeout(step, 13); + }, step = function () { + for (var i = 0; i < H.timers.length; i++) { + if (!H.timers[i]()) { + H.timers.splice(i--, 1); + } + } + if (H.timers.length) { + requestAnimationFrame(step); + } + }; + if (from === to && !this.elem['forceAnimate:' + this.prop]) { + delete options.curAnim[this.prop]; + if (options.complete && Object.keys(options.curAnim).length === 0) { + options.complete.call(this.elem); + } + } + else { // #7166 + this.startTime = +new Date(); + this.start = from; + this.end = to; + this.unit = unit; + this.now = this.start; + this.pos = 0; + timer.elem = this.elem; + timer.prop = this.prop; + if (timer() && H.timers.push(timer) === 1) { + requestAnimationFrame(step); + } + } + }; + /** + * Run a single step in the animation. + * + * @function Highcharts.Fx#step + * + * @param {boolean} [gotoEnd] + * Whether to go to the endpoint of the animation after abort. + * + * @return {boolean} + * Returns `true` if animation continues. + */ + Fx.prototype.step = function (gotoEnd) { + var t = +new Date(), ret, done, options = this.options, elem = this.elem, complete = options.complete, duration = options.duration, curAnim = options.curAnim; + if (elem.attr && !elem.element) { // #2616, element is destroyed + ret = false; + } + else if (gotoEnd || t >= duration + this.startTime) { + this.now = this.end; + this.pos = 1; + this.update(); + curAnim[this.prop] = true; + done = true; + objectEach(curAnim, function (val) { + if (val !== true) { + done = false; + } + }); + if (done && complete) { + complete.call(elem); + } + ret = false; + } + else { + this.pos = options.easing((t - this.startTime) / duration); + this.now = this.start + ((this.end - this.start) * this.pos); + this.update(); + ret = true; + } + return ret; + }; + /** + * Prepare start and end values so that the path can be animated one to one. + * + * @function Highcharts.Fx#initPath + * + * @param {Highcharts.SVGElement} elem + * The SVGElement item. + * + * @param {Highcharts.SVGPathArray|undefined} fromD + * Starting path definition. + * + * @param {Highcharts.SVGPathArray} toD + * Ending path definition. + * + * @return {Array} + * An array containing start and end paths in array form so that + * they can be animated in parallel. + */ + Fx.prototype.initPath = function (elem, fromD, toD) { + var shift, startX = elem.startX, endX = elem.endX, fullLength, i, start = fromD && fromD.slice(), // copy + end = toD.slice(), // copy + isArea = elem.isArea, positionFactor = isArea ? 2 : 1, reverse; + if (!start) { + return [end, end]; + } + /** + * If shifting points, prepend a dummy point to the end path. + * @private + * @param {Highcharts.SVGPathArray} arr - array + * @param {Highcharts.SVGPathArray} other - array + * @return {void} + */ + function prepend(arr, other) { + while (arr.length < fullLength) { + // Move to, line to or curve to? + var moveSegment = arr[0], otherSegment = other[fullLength - arr.length]; + if (otherSegment && moveSegment[0] === 'M') { + if (otherSegment[0] === 'C') { + arr[0] = [ + 'C', + moveSegment[1], + moveSegment[2], + moveSegment[1], + moveSegment[2], + moveSegment[1], + moveSegment[2] + ]; + } + else { + arr[0] = ['L', moveSegment[1], moveSegment[2]]; + } + } + // Prepend a copy of the first point + arr.unshift(moveSegment); + // For areas, the bottom path goes back again to the left, so we + // need to append a copy of the last point. + if (isArea) { + arr.push(arr[arr.length - 1]); + } + } + } + /** + * Copy and append last point until the length matches the end length. + * @private + * @param {Highcharts.SVGPathArray} arr - array + * @param {Highcharts.SVGPathArray} other - array + * @return {void} + */ + function append(arr, other) { + while (arr.length < fullLength) { + // Pull out the slice that is going to be appended or inserted. + // In a line graph, the positionFactor is 1, and the last point + // is sliced out. In an area graph, the positionFactor is 2, + // causing the middle two points to be sliced out, since an area + // path starts at left, follows the upper path then turns and + // follows the bottom back. + var segmentToAdd = arr[arr.length / positionFactor - 1].slice(); + // Disable the first control point of curve segments + if (segmentToAdd[0] === 'C') { + segmentToAdd[1] = segmentToAdd[5]; + segmentToAdd[2] = segmentToAdd[6]; + } + if (!isArea) { + arr.push(segmentToAdd); + } + else { + var lowerSegmentToAdd = arr[arr.length / positionFactor].slice(); + arr.splice(arr.length / 2, 0, segmentToAdd, lowerSegmentToAdd); + } + } + } + // For sideways animation, find out how much we need to shift to get the + // start path Xs to match the end path Xs. + if (startX && endX) { + for (i = 0; i < startX.length; i++) { + // Moving left, new points coming in on right + if (startX[i] === endX[0]) { + shift = i; + break; + // Moving right + } + else if (startX[0] === + endX[endX.length - startX.length + i]) { + shift = i; + reverse = true; + break; + // Fixed from the right side, "scaling" left + } + else if (startX[startX.length - 1] === + endX[endX.length - startX.length + i]) { + shift = startX.length - i; + break; + } + } + if (typeof shift === 'undefined') { + start = []; + } + } + if (start.length && isNumber(shift)) { + // The common target length for the start and end array, where both + // arrays are padded in opposite ends + fullLength = end.length + shift * positionFactor; + if (!reverse) { + prepend(end, start); + append(start, end); + } + else { + prepend(start, end); + append(end, start); + } + } + return [start, end]; + }; + /** + * Handle animation of the color attributes directly. + * + * @function Highcharts.Fx#fillSetter + * + * @return {void} + */ + Fx.prototype.fillSetter = function () { + Fx.prototype.strokeSetter.apply(this, arguments); + }; + /** + * Handle animation of the color attributes directly. + * + * @function Highcharts.Fx#strokeSetter + * + * @return {void} + */ + Fx.prototype.strokeSetter = function () { + this.elem.attr(this.prop, H.color(this.start).tweenTo(H.color(this.end), this.pos), null, true); + }; + return Fx; + }()); + H.Fx = Fx; + /* eslint-disable valid-jsdoc */ + /** + * Utility function to deep merge two or more objects and return a third object. + * If the first argument is true, the contents of the second object is copied + * into the first object. The merge function can also be used with a single + * object argument to create a deep copy of an object. + * + * @function Highcharts.merge + * + * @param {boolean} extend + * Whether to extend the left-side object (a) or return a whole new + * object. + * + * @param {T|undefined} a + * The first object to extend. When only this is given, the function + * returns a deep copy. + * + * @param {...Array} [n] + * An object to merge into the previous one. + * + * @return {T} + * The merged object. If the first argument is true, the return is the + * same as the second argument. + */ /** + * Utility function to deep merge two or more objects and return a third object. + * The merge function can also be used with a single object argument to create a + * deep copy of an object. + * + * @function Highcharts.merge + * + * @param {T|undefined} a + * The first object to extend. When only this is given, the function + * returns a deep copy. + * + * @param {...Array} [n] + * An object to merge into the previous one. + * + * @return {T} + * The merged object. If the first argument is true, the return is the + * same as the second argument. + */ + function merge() { + /* eslint-enable valid-jsdoc */ + var i, args = arguments, len, ret = {}, doCopy = function (copy, original) { + // An object is replacing a primitive + if (typeof copy !== 'object') { + copy = {}; + } + objectEach(original, function (value, key) { + // Copy the contents of objects, but not arrays or DOM nodes + if (isObject(value, true) && + !isClass(value) && + !isDOMElement(value)) { + copy[key] = doCopy(copy[key] || {}, value); + // Primitives and arrays are copied over directly + } + else { + copy[key] = original[key]; + } + }); + return copy; + }; + // If first argument is true, copy into the existing object. Used in + // setOptions. + if (args[0] === true) { + ret = args[1]; + args = Array.prototype.slice.call(args, 2); + } + // For each argument, extend the return + len = args.length; + for (i = 0; i < len; i++) { + ret = doCopy(ret, args[i]); + } + return ret; + } + H.merge = merge; + /** + * Constrain a value to within a lower and upper threshold. + * + * @private + * @param {number} value The initial value + * @param {number} min The lower threshold + * @param {number} max The upper threshold + * @return {number} Returns a number value within min and max. + */ + function clamp(value, min, max) { + return value > min ? value < max ? value : max : min; + } + /** + * Shortcut for parseInt + * + * @private + * @function Highcharts.pInt + * + * @param {*} s + * any + * + * @param {number} [mag] + * Magnitude + * + * @return {number} + * number + */ + var pInt = H.pInt = function pInt(s, mag) { + return parseInt(s, mag || 10); + }; + /** + * Utility function to check for string type. + * + * @function Highcharts.isString + * + * @param {*} s + * The item to check. + * + * @return {boolean} + * True if the argument is a string. + */ + var isString = H.isString = function isString(s) { + return typeof s === 'string'; + }; + /** + * Utility function to check if an item is an array. + * + * @function Highcharts.isArray + * + * @param {*} obj + * The item to check. + * + * @return {boolean} + * True if the argument is an array. + */ + var isArray = H.isArray = function isArray(obj) { + var str = Object.prototype.toString.call(obj); + return str === '[object Array]' || str === '[object Array Iterator]'; + }; + /** + * Utility function to check if an item is of type object. + * + * @function Highcharts.isObject + * + * @param {*} obj + * The item to check. + * + * @param {boolean} [strict=false] + * Also checks that the object is not an array. + * + * @return {boolean} + * True if the argument is an object. + */ + function isObject(obj, strict) { + return (!!obj && + typeof obj === 'object' && + (!strict || !isArray(obj))); // eslint-disable-line @typescript-eslint/no-explicit-any + } + H.isObject = isObject; + /** + * Utility function to check if an Object is a HTML Element. + * + * @function Highcharts.isDOMElement + * + * @param {*} obj + * The item to check. + * + * @return {boolean} + * True if the argument is a HTML Element. + */ + var isDOMElement = H.isDOMElement = function isDOMElement(obj) { + return isObject(obj) && typeof obj.nodeType === 'number'; + }; + /** + * Utility function to check if an Object is a class. + * + * @function Highcharts.isClass + * + * @param {object|undefined} obj + * The item to check. + * + * @return {boolean} + * True if the argument is a class. + */ + var isClass = H.isClass = function isClass(obj) { + var c = obj && obj.constructor; + return !!(isObject(obj, true) && + !isDOMElement(obj) && + (c && c.name && c.name !== 'Object')); + }; + /** + * Utility function to check if an item is a number and it is finite (not NaN, + * Infinity or -Infinity). + * + * @function Highcharts.isNumber + * + * @param {*} n + * The item to check. + * + * @return {boolean} + * True if the item is a finite number + */ + var isNumber = H.isNumber = function isNumber(n) { + return typeof n === 'number' && !isNaN(n) && n < Infinity && n > -Infinity; + }; + /** + * Remove the last occurence of an item from an array. + * + * @function Highcharts.erase + * + * @param {Array<*>} arr + * The array. + * + * @param {*} item + * The item to remove. + * + * @return {void} + */ + var erase = H.erase = function erase(arr, item) { + var i = arr.length; + while (i--) { + if (arr[i] === item) { + arr.splice(i, 1); + break; + } + } + }; + /** + * Check if an object is null or undefined. + * + * @function Highcharts.defined + * + * @param {*} obj + * The object to check. + * + * @return {boolean} + * False if the object is null or undefined, otherwise true. + */ + var defined = H.defined = function defined(obj) { + return typeof obj !== 'undefined' && obj !== null; + }; + /** + * Set or get an attribute or an object of attributes. To use as a setter, pass + * a key and a value, or let the second argument be a collection of keys and + * values. To use as a getter, pass only a string as the second argument. + * + * @function Highcharts.attr + * + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} elem + * The DOM element to receive the attribute(s). + * + * @param {string|Highcharts.HTMLAttributes|Highcharts.SVGAttributes} [prop] + * The property or an object of key-value pairs. + * + * @param {number|string} [value] + * The value if a single property is set. + * + * @return {string|null|undefined} + * When used as a getter, return the value. + */ + function attr(elem, prop, value) { + var ret; + // if the prop is a string + if (isString(prop)) { + // set the value + if (defined(value)) { + elem.setAttribute(prop, value); + // get the value + } + else if (elem && elem.getAttribute) { + ret = elem.getAttribute(prop); + // IE7 and below cannot get class through getAttribute (#7850) + if (!ret && prop === 'class') { + ret = elem.getAttribute(prop + 'Name'); + } + } + // else if prop is defined, it is a hash of key/value pairs + } + else { + objectEach(prop, function (val, key) { + elem.setAttribute(key, val); + }); + } + return ret; + } + H.attr = attr; + /** + * Check if an element is an array, and if not, make it into an array. + * + * @function Highcharts.splat + * + * @param {*} obj + * The object to splat. + * + * @return {Array} + * The produced or original array. + */ + var splat = H.splat = function splat(obj) { + return isArray(obj) ? obj : [obj]; + }; + /** + * Set a timeout if the delay is given, otherwise perform the function + * synchronously. + * + * @function Highcharts.syncTimeout + * + * @param {Function} fn + * The function callback. + * + * @param {number} delay + * Delay in milliseconds. + * + * @param {*} [context] + * An optional context to send to the function callback. + * + * @return {number} + * An identifier for the timeout that can later be cleared with + * Highcharts.clearTimeout. Returns -1 if there is no timeout. + */ + var syncTimeout = H.syncTimeout = function syncTimeout(fn, delay, context) { + if (delay > 0) { + return setTimeout(fn, delay, context); + } + fn.call(0, context); + return -1; + }; + /** + * Internal clear timeout. The function checks that the `id` was not removed + * (e.g. by `chart.destroy()`). For the details see + * [issue #7901](https://github.com/highcharts/highcharts/issues/7901). + * + * @function Highcharts.clearTimeout + * + * @param {number} id + * Id of a timeout. + * + * @return {void} + */ + var internalClearTimeout = H.clearTimeout = function (id) { + if (defined(id)) { + clearTimeout(id); + } + }; + /* eslint-disable valid-jsdoc */ + /** + * Utility function to extend an object with the members of another. + * + * @function Highcharts.extend + * + * @param {T|undefined} a + * The object to be extended. + * + * @param {object} b + * The object to add to the first one. + * + * @return {T} + * Object a, the original object. + */ + var extend = H.extend = function extend(a, b) { + /* eslint-enable valid-jsdoc */ + var n; + if (!a) { + a = {}; + } + for (n in b) { // eslint-disable-line guard-for-in + a[n] = b[n]; + } + return a; + }; + /* eslint-disable valid-jsdoc */ + /** + * Return the first value that is not null or undefined. + * + * @function Highcharts.pick + * + * @param {...Array} items + * Variable number of arguments to inspect. + * + * @return {T} + * The value of the first argument that is not null or undefined. + */ + function pick() { + var args = arguments; + var length = args.length; + for (var i = 0; i < length; i++) { + var arg = args[i]; + if (typeof arg !== 'undefined' && arg !== null) { + return arg; + } + } + } + H.pick = pick; + /** + * Set CSS on a given element. + * + * @function Highcharts.css + * + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} el + * An HTML DOM element. + * + * @param {Highcharts.CSSObject} styles + * Style object with camel case property names. + * + * @return {void} + */ + var css = H.css = function css(el, styles) { + if (H.isMS && !H.svg) { // #2686 + if (styles && typeof styles.opacity !== 'undefined') { + styles.filter = + 'alpha(opacity=' + (styles.opacity * 100) + ')'; + } + } + extend(el.style, styles); + }; + /** + * Utility function to create an HTML element with attributes and styles. + * + * @function Highcharts.createElement + * + * @param {string} tag + * The HTML tag. + * + * @param {Highcharts.HTMLAttributes} [attribs] + * Attributes as an object of key-value pairs. + * + * @param {Highcharts.CSSObject} [styles] + * Styles as an object of key-value pairs. + * + * @param {Highcharts.HTMLDOMElement} [parent] + * The parent HTML object. + * + * @param {boolean} [nopad=false] + * If true, remove all padding, border and margin. + * + * @return {Highcharts.HTMLDOMElement} + * The created DOM element. + */ + var createElement = H.createElement = function createElement(tag, attribs, styles, parent, nopad) { + var el = doc.createElement(tag); + if (attribs) { + extend(el, attribs); + } + if (nopad) { + css(el, { padding: '0', border: 'none', margin: '0' }); + } + if (styles) { + css(el, styles); + } + if (parent) { + parent.appendChild(el); + } + return el; + }; + // eslint-disable-next-line valid-jsdoc + /** + * Extend a prototyped class by new members. + * + * @function Highcharts.extendClass + * + * @param {Highcharts.Class} parent + * The parent prototype to inherit. + * + * @param {Highcharts.Dictionary<*>} members + * A collection of prototype members to add or override compared to the + * parent prototype. + * + * @return {Highcharts.Class} + * A new prototype. + */ + var extendClass = H.extendClass = function extendClass(parent, members) { + var obj = (function () { }); + obj.prototype = new parent(); // eslint-disable-line new-cap + extend(obj.prototype, members); + return obj; + }; + /** + * Left-pad a string to a given length by adding a character repetetively. + * + * @function Highcharts.pad + * + * @param {number} number + * The input string or number. + * + * @param {number} [length] + * The desired string length. + * + * @param {string} [padder=0] + * The character to pad with. + * + * @return {string} + * The padded string. + */ + var pad = H.pad = function pad(number, length, padder) { + return new Array((length || 2) + + 1 - + String(number) + .replace('-', '') + .length).join(padder || '0') + number; + }; + /** + * Return a length based on either the integer value, or a percentage of a base. + * + * @function Highcharts.relativeLength + * + * @param {Highcharts.RelativeSize} value + * A percentage string or a number. + * + * @param {number} base + * The full length that represents 100%. + * + * @param {number} [offset=0] + * A pixel offset to apply for percentage values. Used internally in + * axis positioning. + * + * @return {number} + * The computed length. + */ + var relativeLength = H.relativeLength = function relativeLength(value, base, offset) { + return (/%$/).test(value) ? + (base * parseFloat(value) / 100) + (offset || 0) : + parseFloat(value); + }; + /** + * Wrap a method with extended functionality, preserving the original function. + * + ' * @function Highcharts.wrap + * + * @param {*} obj + * The context object that the method belongs to. In real cases, this is + * often a prototype. + * + * @param {string} method + * The name of the method to extend. + * + * @param {Highcharts.WrapProceedFunction} func + * A wrapper function callback. This function is called with the same + * arguments as the original function, except that the original function + * is unshifted and passed as the first argument. + * + * @return {void} + */ + var wrap = H.wrap = function wrap(obj, method, func) { + var proceed = obj[method]; + obj[method] = function () { + var args = Array.prototype.slice.call(arguments), outerArgs = arguments, ctx = this, ret; + ctx.proceed = function () { + proceed.apply(ctx, arguments.length ? arguments : outerArgs); + }; + args.unshift(proceed); + ret = func.apply(this, args); + ctx.proceed = null; + return ret; + }; + }; + /** + * Format a string according to a subset of the rules of Python's String.format + * method. + * + * @example + * var s = Highcharts.format( + * 'The {color} fox was {len:.2f} feet long', + * { color: 'red', len: Math.PI } + * ); + * // => The red fox was 3.14 feet long + * + * @function Highcharts.format + * + * @param {string} str + * The string to format. + * + * @param {Record} ctx + * The context, a collection of key-value pairs where each key is + * replaced by its value. + * + * @param {Highcharts.Chart} [chart] + * A `Chart` instance used to get numberFormatter and time. + * + * @return {string} + * The formatted string. + */ + var format = H.format = function (str, ctx, chart) { + var splitter = '{', isInside = false, segment, valueAndFormat, ret = [], val, index; + var floatRegex = /f$/; + var decRegex = /\.([0-9])/; + var lang = H.defaultOptions.lang; + var time = chart && chart.time || H.time; + var numberFormatter = chart && chart.numberFormatter || numberFormat; + while (str) { + index = str.indexOf(splitter); + if (index === -1) { + break; + } + segment = str.slice(0, index); + if (isInside) { // we're on the closing bracket looking back + valueAndFormat = segment.split(':'); + val = getNestedProperty(valueAndFormat.shift() || '', ctx); + // Format the replacement + if (valueAndFormat.length && typeof val === 'number') { + segment = valueAndFormat.join(':'); + if (floatRegex.test(segment)) { // float + var decimals = parseInt((segment.match(decRegex) || ['', '-1'])[1], 10); + if (val !== null) { + val = numberFormatter(val, decimals, lang.decimalPoint, segment.indexOf(',') > -1 ? lang.thousandsSep : ''); + } + } + else { + val = time.dateFormat(segment, val); + } + } + // Push the result and advance the cursor + ret.push(val); + } + else { + ret.push(segment); + } + str = str.slice(index + 1); // the rest + isInside = !isInside; // toggle + splitter = isInside ? '}' : '{'; // now look for next matching bracket + } + ret.push(str); + return ret.join(''); + }; + /** + * Get the magnitude of a number. + * + * @function Highcharts.getMagnitude + * + * @param {number} num + * The number. + * + * @return {number} + * The magnitude, where 1-9 are magnitude 1, 10-99 magnitude 2 etc. + */ + var getMagnitude = H.getMagnitude = function (num) { + return Math.pow(10, Math.floor(Math.log(num) / Math.LN10)); + }; + /** + * Take an interval and normalize it to multiples of round numbers. + * + * @deprecated + * @function Highcharts.normalizeTickInterval + * + * @param {number} interval + * The raw, un-rounded interval. + * + * @param {Array<*>} [multiples] + * Allowed multiples. + * + * @param {number} [magnitude] + * The magnitude of the number. + * + * @param {boolean} [allowDecimals] + * Whether to allow decimals. + * + * @param {boolean} [hasTickAmount] + * If it has tickAmount, avoid landing on tick intervals lower than + * original. + * + * @return {number} + * The normalized interval. + * + * @todo + * Move this function to the Axis prototype. It is here only for historical + * reasons. + */ + var normalizeTickInterval = H.normalizeTickInterval = function (interval, multiples, magnitude, allowDecimals, hasTickAmount) { + var normalized, i, retInterval = interval; + // round to a tenfold of 1, 2, 2.5 or 5 + magnitude = pick(magnitude, 1); + normalized = interval / magnitude; + // multiples for a linear scale + if (!multiples) { + multiples = hasTickAmount ? + // Finer grained ticks when the tick amount is hard set, including + // when alignTicks is true on multiple axes (#4580). + [1, 1.2, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10] : + // Else, let ticks fall on rounder numbers + [1, 2, 2.5, 5, 10]; + // the allowDecimals option + if (allowDecimals === false) { + if (magnitude === 1) { + multiples = multiples.filter(function (num) { + return num % 1 === 0; + }); + } + else if (magnitude <= 0.1) { + multiples = [1 / magnitude]; + } + } + } + // normalize the interval to the nearest multiple + for (i = 0; i < multiples.length; i++) { + retInterval = multiples[i]; + // only allow tick amounts smaller than natural + if ((hasTickAmount && + retInterval * magnitude >= interval) || + (!hasTickAmount && + (normalized <= + (multiples[i] + + (multiples[i + 1] || multiples[i])) / 2))) { + break; + } + } + // Multiply back to the correct magnitude. Correct floats to appropriate + // precision (#6085). + retInterval = correctFloat(retInterval * magnitude, -Math.round(Math.log(0.001) / Math.LN10)); + return retInterval; + }; + /** + * Sort an object array and keep the order of equal items. The ECMAScript + * standard does not specify the behaviour when items are equal. + * + * @function Highcharts.stableSort + * + * @param {Array<*>} arr + * The array to sort. + * + * @param {Function} sortFunction + * The function to sort it with, like with regular Array.prototype.sort. + * + * @return {void} + */ + var stableSort = H.stableSort = function stableSort(arr, sortFunction) { + // @todo It seems like Chrome since v70 sorts in a stable way internally, + // plus all other browsers do it, so over time we may be able to remove this + // function + var length = arr.length, sortValue, i; + // Add index to each item + for (i = 0; i < length; i++) { + arr[i].safeI = i; // stable sort index + } + arr.sort(function (a, b) { + sortValue = sortFunction(a, b); + return sortValue === 0 ? a.safeI - b.safeI : sortValue; + }); + // Remove index from items + for (i = 0; i < length; i++) { + delete arr[i].safeI; // stable sort index + } + }; + /** + * Non-recursive method to find the lowest member of an array. `Math.min` raises + * a maximum call stack size exceeded error in Chrome when trying to apply more + * than 150.000 points. This method is slightly slower, but safe. + * + * @function Highcharts.arrayMin + * + * @param {Array<*>} data + * An array of numbers. + * + * @return {number} + * The lowest number. + */ + var arrayMin = H.arrayMin = function arrayMin(data) { + var i = data.length, min = data[0]; + while (i--) { + if (data[i] < min) { + min = data[i]; + } + } + return min; + }; + /** + * Non-recursive method to find the lowest member of an array. `Math.max` raises + * a maximum call stack size exceeded error in Chrome when trying to apply more + * than 150.000 points. This method is slightly slower, but safe. + * + * @function Highcharts.arrayMax + * + * @param {Array<*>} data + * An array of numbers. + * + * @return {number} + * The highest number. + */ + var arrayMax = H.arrayMax = function arrayMax(data) { + var i = data.length, max = data[0]; + while (i--) { + if (data[i] > max) { + max = data[i]; + } + } + return max; + }; + /** + * Utility method that destroys any SVGElement instances that are properties on + * the given object. It loops all properties and invokes destroy if there is a + * destroy method. The property is then delete. + * + * @function Highcharts.destroyObjectProperties + * + * @param {*} obj + * The object to destroy properties on. + * + * @param {*} [except] + * Exception, do not destroy this property, only delete it. + * + * @return {void} + */ + var destroyObjectProperties = H.destroyObjectProperties = + function destroyObjectProperties(obj, except) { + objectEach(obj, function (val, n) { + // If the object is non-null and destroy is defined + if (val && val !== except && val.destroy) { + // Invoke the destroy + val.destroy(); + } + // Delete the property from the object. + delete obj[n]; + }); + }; + /** + * Discard a HTML element by moving it to the bin and delete. + * + * @function Highcharts.discardElement + * + * @param {Highcharts.HTMLDOMElement} element + * The HTML node to discard. + * + * @return {void} + */ + var discardElement = H.discardElement = function discardElement(element) { + var garbageBin = H.garbageBin; + // create a garbage bin element, not part of the DOM + if (!garbageBin) { + garbageBin = createElement('div'); + } + // move the node and empty bin + if (element) { + garbageBin.appendChild(element); + } + garbageBin.innerHTML = ''; + }; + /** + * Fix JS round off float errors. + * + * @function Highcharts.correctFloat + * + * @param {number} num + * A float number to fix. + * + * @param {number} [prec=14] + * The precision. + * + * @return {number} + * The corrected float number. + */ + var correctFloat = H.correctFloat = function correctFloat(num, prec) { + return parseFloat(num.toPrecision(prec || 14)); + }; + /** + * Set the global animation to either a given value, or fall back to the given + * chart's animation option. + * + * @function Highcharts.setAnimation + * + * @param {boolean|Highcharts.AnimationOptionsObject|undefined} animation + * The animation object. + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @return {void} + * + * @todo + * This function always relates to a chart, and sets a property on the renderer, + * so it should be moved to the SVGRenderer. + */ + var setAnimation = H.setAnimation = function setAnimation(animation, chart) { + chart.renderer.globalAnimation = pick(animation, chart.options.chart.animation, true); + }; + /** + * Get the animation in object form, where a disabled animation is always + * returned as `{ duration: 0 }`. + * + * @function Highcharts.animObject + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=0] + * An animation setting. Can be an object with duration, complete and + * easing properties, or a boolean to enable or disable. + * + * @return {Highcharts.AnimationOptionsObject} + * An object with at least a duration property. + */ + var animObject = H.animObject = function animObject(animation) { + return isObject(animation) ? + merge(animation) : + { duration: animation ? 500 : 0 }; + }; + /** + * The time unit lookup + * + * @ignore + */ + var timeUnits = H.timeUnits = { + millisecond: 1, + second: 1000, + minute: 60000, + hour: 3600000, + day: 24 * 3600000, + week: 7 * 24 * 3600000, + month: 28 * 24 * 3600000, + year: 364 * 24 * 3600000 + }; + /** + * Format a number and return a string based on input settings. + * + * @sample highcharts/members/highcharts-numberformat/ + * Custom number format + * + * @function Highcharts.numberFormat + * + * @param {number} number + * The input number to format. + * + * @param {number} decimals + * The amount of decimals. A value of -1 preserves the amount in the + * input number. + * + * @param {string} [decimalPoint] + * The decimal point, defaults to the one given in the lang options, or + * a dot. + * + * @param {string} [thousandsSep] + * The thousands separator, defaults to the one given in the lang + * options, or a space character. + * + * @return {string} + * The formatted number. + */ + var numberFormat = H.numberFormat = function numberFormat(number, decimals, decimalPoint, thousandsSep) { + number = +number || 0; + decimals = +decimals; + var lang = H.defaultOptions.lang, origDec = (number.toString().split('.')[1] || '').split('e')[0].length, strinteger, thousands, ret, roundedNumber, exponent = number.toString().split('e'), fractionDigits; + if (decimals === -1) { + // Preserve decimals. Not huge numbers (#3793). + decimals = Math.min(origDec, 20); + } + else if (!isNumber(decimals)) { + decimals = 2; + } + else if (decimals && exponent[1] && exponent[1] < 0) { + // Expose decimals from exponential notation (#7042) + fractionDigits = decimals + +exponent[1]; + if (fractionDigits >= 0) { + // remove too small part of the number while keeping the notation + exponent[0] = (+exponent[0]).toExponential(fractionDigits) + .split('e')[0]; + decimals = fractionDigits; + } + else { + // fractionDigits < 0 + exponent[0] = exponent[0].split('.')[0] || 0; + if (decimals < 20) { + // use number instead of exponential notation (#7405) + number = (exponent[0] * Math.pow(10, exponent[1])) + .toFixed(decimals); + } + else { + // or zero + number = 0; + } + exponent[1] = 0; + } + } + // Add another decimal to avoid rounding errors of float numbers. (#4573) + // Then use toFixed to handle rounding. + roundedNumber = (Math.abs(exponent[1] ? exponent[0] : number) + + Math.pow(10, -Math.max(decimals, origDec) - 1)).toFixed(decimals); + // A string containing the positive integer component of the number + strinteger = String(pInt(roundedNumber)); + // Leftover after grouping into thousands. Can be 0, 1 or 2. + thousands = strinteger.length > 3 ? strinteger.length % 3 : 0; + // Language + decimalPoint = pick(decimalPoint, lang.decimalPoint); + thousandsSep = pick(thousandsSep, lang.thousandsSep); + // Start building the return + ret = number < 0 ? '-' : ''; + // Add the leftover after grouping into thousands. For example, in the + // number 42 000 000, this line adds 42. + ret += thousands ? strinteger.substr(0, thousands) + thousandsSep : ''; + // Add the remaining thousands groups, joined by the thousands separator + ret += strinteger + .substr(thousands) + .replace(/(\d{3})(?=\d)/g, '$1' + thousandsSep); + // Add the decimal point and the decimal component + if (decimals) { + // Get the decimal component + ret += decimalPoint + roundedNumber.slice(-decimals); + } + if (exponent[1] && +ret !== 0) { + ret += 'e' + exponent[1]; + } + return ret; + }; + /** + * Easing definition + * + * @private + * @function Math.easeInOutSine + * + * @param {number} pos + * Current position, ranging from 0 to 1. + * + * @return {number} + * Ease result + */ + Math.easeInOutSine = function (pos) { + return -0.5 * (Math.cos(Math.PI * pos) - 1); + }; + /** + * Returns the value of a property path on a given object. + * + * @private + * @function getNestedProperty + * + * @param {string} path + * Path to the property, for example `custom.myValue`. + * + * @param {unknown} obj + * Instance containing the property on the specific path. + * + * @return {unknown} + * The unknown property value. + */ + function getNestedProperty(path, obj) { + if (!path) { + return obj; + } + var pathElements = path.split('.').reverse(); + var subProperty = obj; + if (pathElements.length === 1) { + return subProperty[path]; + } + var pathElement = pathElements.pop(); + while (typeof pathElement !== 'undefined' && + typeof subProperty !== 'undefined' && + subProperty !== null) { + subProperty = subProperty[pathElement]; + pathElement = pathElements.pop(); + } + return subProperty; + } + /** + * Get the computed CSS value for given element and property, only for numerical + * properties. For width and height, the dimension of the inner box (excluding + * padding) is returned. Used for fitting the chart within the container. + * + * @function Highcharts.getStyle + * + * @param {Highcharts.HTMLDOMElement} el + * An HTML element. + * + * @param {string} prop + * The property name. + * + * @param {boolean} [toInt=true] + * Parse to integer. + * + * @return {number|string} + * The numeric value. + */ + var getStyle = H.getStyle = function (el, prop, toInt) { + var style; + // For width and height, return the actual inner pixel size (#4913) + if (prop === 'width') { + var offsetWidth = Math.min(el.offsetWidth, el.scrollWidth); + // In flex boxes, we need to use getBoundingClientRect and floor it, + // because scrollWidth doesn't support subpixel precision (#6427) ... + var boundingClientRectWidth = el.getBoundingClientRect && + el.getBoundingClientRect().width; + // ...unless if the containing div or its parents are transform-scaled + // down, in which case the boundingClientRect can't be used as it is + // also scaled down (#9871, #10498). + if (boundingClientRectWidth < offsetWidth && + boundingClientRectWidth >= offsetWidth - 1) { + offsetWidth = Math.floor(boundingClientRectWidth); + } + return Math.max(0, // #8377 + (offsetWidth - + H.getStyle(el, 'padding-left') - + H.getStyle(el, 'padding-right'))); + } + if (prop === 'height') { + return Math.max(0, // #8377 + Math.min(el.offsetHeight, el.scrollHeight) - + H.getStyle(el, 'padding-top') - + H.getStyle(el, 'padding-bottom')); + } + if (!win.getComputedStyle) { + // SVG not supported, forgot to load oldie.js? + error(27, true); + } + // Otherwise, get the computed style + style = win.getComputedStyle(el, undefined); // eslint-disable-line no-undefined + if (style) { + style = style.getPropertyValue(prop); + if (pick(toInt, prop !== 'opacity')) { + style = pInt(style); + } + } + return style; + }; + /** + * Search for an item in an array. + * + * @function Highcharts.inArray + * + * @deprecated + * + * @param {*} item + * The item to search for. + * + * @param {Array<*>} arr + * The array or node collection to search in. + * + * @param {number} [fromIndex=0] + * The index to start searching from. + * + * @return {number} + * The index within the array, or -1 if not found. + */ + var inArray = H.inArray = function (item, arr, fromIndex) { + return arr.indexOf(item, fromIndex); + }; + /* eslint-disable valid-jsdoc */ + /** + * Return the value of the first element in the array that satisfies the + * provided testing function. + * + * @function Highcharts.find + * + * @param {Array} arr + * The array to test. + * + * @param {Function} callback + * The callback function. The function receives the item as the first + * argument. Return `true` if this item satisfies the condition. + * + * @return {T|undefined} + * The value of the element. + */ + var find = H.find = Array.prototype.find ? + /* eslint-enable valid-jsdoc */ + function (arr, callback) { + return arr.find(callback); + } : + // Legacy implementation. PhantomJS, IE <= 11 etc. #7223. + function (arr, callback) { + var i, length = arr.length; + for (i = 0; i < length; i++) { + if (callback(arr[i], i)) { // eslint-disable-line callback-return + return arr[i]; + } + } + }; + /** + * Returns an array of a given object's own properties. + * + * @function Highcharts.keys + * @deprecated + * + * @param {*} obj + * The object of which the properties are to be returned. + * + * @return {Array} + * An array of strings that represents all the properties. + */ + H.keys = Object.keys; + /** + * Get the element's offset position, corrected for `overflow: auto`. + * + * @function Highcharts.offset + * + * @param {global.Element} el + * The DOM element. + * + * @return {Highcharts.OffsetObject} + * An object containing `left` and `top` properties for the position in + * the page. + */ + var offset = H.offset = function offset(el) { + var docElem = doc.documentElement, box = (el.parentElement || el.parentNode) ? + el.getBoundingClientRect() : + { top: 0, left: 0 }; + return { + top: box.top + (win.pageYOffset || docElem.scrollTop) - + (docElem.clientTop || 0), + left: box.left + (win.pageXOffset || docElem.scrollLeft) - + (docElem.clientLeft || 0) + }; + }; + /** + * Stop running animation. + * + * @function Highcharts.stop + * + * @param {Highcharts.SVGElement} el + * The SVGElement to stop animation on. + * + * @param {string} [prop] + * The property to stop animating. If given, the stop method will stop a + * single property from animating, while others continue. + * + * @return {void} + * + * @todo + * A possible extension to this would be to stop a single property, when + * we want to continue animating others. Then assign the prop to the timer + * in the Fx.run method, and check for the prop here. This would be an + * improvement in all cases where we stop the animation from .attr. Instead of + * stopping everything, we can just stop the actual attributes we're setting. + */ + var stop = H.stop = function (el, prop) { + var i = H.timers.length; + // Remove timers related to this element (#4519) + while (i--) { + if (H.timers[i].elem === el && (!prop || prop === H.timers[i].prop)) { + H.timers[i].stopped = true; // #4667 + } + } + }; + /* eslint-disable valid-jsdoc */ + /** + * Iterate over object key pairs in an object. + * + * @function Highcharts.objectEach + * + * @param {*} obj + * The object to iterate over. + * + * @param {Highcharts.ObjectEachCallbackFunction} fn + * The iterator callback. It passes three arguments: + * * value - The property value. + * * key - The property key. + * * obj - The object that objectEach is being applied to. + * + * @param {T} [ctx] + * The context. + * + * @return {void} + */ + var objectEach = H.objectEach = function objectEach(obj, fn, ctx) { + /* eslint-enable valid-jsdoc */ + for (var key in obj) { + if (Object.hasOwnProperty.call(obj, key)) { + fn.call(ctx || obj[key], obj[key], key, obj); + } + } + }; + /** + * Iterate over an array. + * + * @deprecated + * @function Highcharts.each + * + * @param {Array<*>} arr + * The array to iterate over. + * + * @param {Function} fn + * The iterator callback. It passes three arguments: + * - `item`: The array item. + * - `index`: The item's index in the array. + * - `arr`: The array that each is being applied to. + * + * @param {*} [ctx] + * The context. + * + * @return {void} + */ + /** + * Filter an array by a callback. + * + * @deprecated + * @function Highcharts.grep + * + * @param {Array<*>} arr + * The array to filter. + * + * @param {Function} callback + * The callback function. The function receives the item as the first + * argument. Return `true` if the item is to be preserved. + * + * @return {Array<*>} + * A new, filtered array. + */ + /** + * Map an array by a callback. + * + * @deprecated + * @function Highcharts.map + * + * @param {Array<*>} arr + * The array to map. + * + * @param {Function} fn + * The callback function. Return the new value for the new array. + * + * @return {Array<*>} + * A new array item with modified items. + */ + /** + * Reduce an array to a single value. + * + * @deprecated + * @function Highcharts.reduce + * + * @param {Array<*>} arr + * The array to reduce. + * + * @param {Function} fn + * The callback function. Return the reduced value. Receives 4 + * arguments: Accumulated/reduced value, current value, current array + * index, and the array. + * + * @param {*} initialValue + * The initial value of the accumulator. + * + * @return {*} + * The reduced value. + */ + /** + * Test whether at least one element in the array passes the test implemented by + * the provided function. + * + * @deprecated + * @function Highcharts.some + * + * @param {Array<*>} arr + * The array to test + * + * @param {Function} fn + * The function to run on each item. Return truty to pass the test. + * Receives arguments `currentValue`, `index` and `array`. + * + * @param {*} ctx + * The context. + * + * @return {boolean} + */ + objectEach({ + map: 'map', + each: 'forEach', + grep: 'filter', + reduce: 'reduce', + some: 'some' + }, function (val, key) { + H[key] = function (arr) { + return Array.prototype[val].apply(arr, [].slice.call(arguments, 1)); + }; + }); + /* eslint-disable valid-jsdoc */ + /** + * Add an event listener. + * + * @function Highcharts.addEvent + * + * @param {Highcharts.Class|T} el + * The element or object to add a listener to. It can be a + * {@link HTMLDOMElement}, an {@link SVGElement} or any other object. + * + * @param {string} type + * The event type. + * + * @param {Highcharts.EventCallbackFunction|Function} fn + * The function callback to execute when the event is fired. + * + * @param {Highcharts.EventOptionsObject} [options] + * Options for adding the event. + * + * @return {Function} + * A callback function to remove the added event. + */ + var addEvent = H.addEvent = function (el, type, fn, options) { + if (options === void 0) { options = {}; } + /* eslint-enable valid-jsdoc */ + var events, addEventListener = (el.addEventListener || H.addEventListenerPolyfill); + // If we're setting events directly on the constructor, use a separate + // collection, `protoEvents` to distinguish it from the item events in + // `hcEvents`. + if (typeof el === 'function' && el.prototype) { + events = el.prototype.protoEvents = el.prototype.protoEvents || {}; + } + else { + events = el.hcEvents = el.hcEvents || {}; + } + // Allow click events added to points, otherwise they will be prevented by + // the TouchPointer.pinch function after a pinch zoom operation (#7091). + if (H.Point && + el instanceof H.Point && + el.series && + el.series.chart) { + el.series.chart.runTrackerClick = true; + } + // Handle DOM events + if (addEventListener) { + addEventListener.call(el, type, fn, false); + } + if (!events[type]) { + events[type] = []; + } + var eventObject = { + fn: fn, + order: typeof options.order === 'number' ? options.order : Infinity + }; + events[type].push(eventObject); + // Order the calls + events[type].sort(function (a, b) { + return a.order - b.order; + }); + // Return a function that can be called to remove this event. + return function () { + removeEvent(el, type, fn); + }; + }; + /* eslint-disable valid-jsdoc */ + /** + * Remove an event that was added with {@link Highcharts#addEvent}. + * + * @function Highcharts.removeEvent + * + * @param {Highcharts.Class|T} el + * The element to remove events on. + * + * @param {string} [type] + * The type of events to remove. If undefined, all events are removed + * from the element. + * + * @param {Highcharts.EventCallbackFunction} [fn] + * The specific callback to remove. If undefined, all events that match + * the element and optionally the type are removed. + * + * @return {void} + */ + var removeEvent = H.removeEvent = function removeEvent(el, type, fn) { + /* eslint-enable valid-jsdoc */ + var events; + /** + * @private + * @param {string} type - event type + * @param {Highcharts.EventCallbackFunction} fn - callback + * @return {void} + */ + function removeOneEvent(type, fn) { + var removeEventListener = (el.removeEventListener || H.removeEventListenerPolyfill); + if (removeEventListener) { + removeEventListener.call(el, type, fn, false); + } + } + /** + * @private + * @param {any} eventCollection - collection + * @return {void} + */ + function removeAllEvents(eventCollection) { + var types, len; + if (!el.nodeName) { + return; // break on non-DOM events + } + if (type) { + types = {}; + types[type] = true; + } + else { + types = eventCollection; + } + objectEach(types, function (val, n) { + if (eventCollection[n]) { + len = eventCollection[n].length; + while (len--) { + removeOneEvent(n, eventCollection[n][len].fn); + } + } + }); + } + ['protoEvents', 'hcEvents'].forEach(function (coll, i) { + var eventElem = i ? el : el.prototype; + var eventCollection = eventElem && eventElem[coll]; + if (eventCollection) { + if (type) { + events = (eventCollection[type] || []); + if (fn) { + eventCollection[type] = events.filter(function (obj) { + return fn !== obj.fn; + }); + removeOneEvent(type, fn); + } + else { + removeAllEvents(eventCollection); + eventCollection[type] = []; + } + } + else { + removeAllEvents(eventCollection); + eventElem[coll] = {}; + } + } + }); + }; + /* eslint-disable valid-jsdoc */ + /** + * Fire an event that was registered with {@link Highcharts#addEvent}. + * + * @function Highcharts.fireEvent + * + * @param {T} el + * The object to fire the event on. It can be a {@link HTMLDOMElement}, + * an {@link SVGElement} or any other object. + * + * @param {string} type + * The type of event. + * + * @param {Highcharts.Dictionary<*>|Event} [eventArguments] + * Custom event arguments that are passed on as an argument to the event + * handler. + * + * @param {Highcharts.EventCallbackFunction|Function} [defaultFunction] + * The default function to execute if the other listeners haven't + * returned false. + * + * @return {void} + */ + var fireEvent = H.fireEvent = function (el, type, eventArguments, defaultFunction) { + /* eslint-enable valid-jsdoc */ + var e, i; + eventArguments = eventArguments || {}; + if (doc.createEvent && + (el.dispatchEvent || el.fireEvent)) { + e = doc.createEvent('Events'); + e.initEvent(type, true, true); + extend(e, eventArguments); + if (el.dispatchEvent) { + el.dispatchEvent(e); + } + else { + el.fireEvent(type, e); + } + } + else { + if (!eventArguments.target) { + // We're running a custom event + extend(eventArguments, { + // Attach a simple preventDefault function to skip + // default handler if called. The built-in + // defaultPrevented property is not overwritable (#5112) + preventDefault: function () { + eventArguments.defaultPrevented = true; + }, + // Setting target to native events fails with clicking + // the zoom-out button in Chrome. + target: el, + // If the type is not set, we're running a custom event + // (#2297). If it is set, we're running a browser event, + // and setting it will cause en error in IE8 (#2465). + type: type + }); + } + var fireInOrder = function (protoEvents, hcEvents) { + if (protoEvents === void 0) { protoEvents = []; } + if (hcEvents === void 0) { hcEvents = []; } + var iA = 0; + var iB = 0; + var length = protoEvents.length + hcEvents.length; + for (i = 0; i < length; i++) { + var obj = (!protoEvents[iA] ? + hcEvents[iB++] : + !hcEvents[iB] ? + protoEvents[iA++] : + protoEvents[iA].order <= hcEvents[iB].order ? + protoEvents[iA++] : + hcEvents[iB++]); + // If the event handler return false, prevent the default + // handler from executing + if (obj.fn.call(el, eventArguments) === false) { + eventArguments.preventDefault(); + } + } + }; + fireInOrder(el.protoEvents && el.protoEvents[type], el.hcEvents && el.hcEvents[type]); + } + // Run the default if not prevented + if (defaultFunction && !eventArguments.defaultPrevented) { + defaultFunction.call(el, eventArguments); + } + }; + /** + * The global animate method, which uses Fx to create individual animators. + * + * @function Highcharts.animate + * + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGElement} el + * The element to animate. + * + * @param {Highcharts.CSSObject|Highcharts.SVGAttributes} params + * An object containing key-value pairs of the properties to animate. + * Supports numeric as pixel-based CSS properties for HTML objects and + * attributes for SVGElements. + * + * @param {Highcharts.AnimationOptionsObject} [opt] + * Animation options. + * + * @return {void} + */ + var animate = H.animate = function (el, params, opt) { + var start, unit = '', end, fx, args; + if (!isObject(opt)) { // Number or undefined/null + args = arguments; + opt = { + duration: args[2], + easing: args[3], + complete: args[4] + }; + } + if (!isNumber(opt.duration)) { + opt.duration = 400; + } + opt.easing = typeof opt.easing === 'function' ? + opt.easing : + (Math[opt.easing] || Math.easeInOutSine); + opt.curAnim = merge(params); + objectEach(params, function (val, prop) { + // Stop current running animation of this property + stop(el, prop); + fx = new Fx(el, opt, prop); + end = null; + if (prop === 'd' && isArray(params.d)) { + fx.paths = fx.initPath(el, el.pathArray, params.d); + fx.toD = params.d; + start = 0; + end = 1; + } + else if (el.attr) { + start = el.attr(prop); + } + else { + start = parseFloat(getStyle(el, prop)) || 0; + if (prop !== 'opacity') { + unit = 'px'; + } + } + if (!end) { + end = val; + } + if (end && end.match && end.match('px')) { + end = end.replace(/px/g, ''); // #4351 + } + fx.run(start, end, unit); + }); + }; + /** + * Factory to create new series prototypes. + * + * @function Highcharts.seriesType + * + * @param {string} type + * The series type name. + * + * @param {string} parent + * The parent series type name. Use `line` to inherit from the basic + * {@link Series} object. + * + * @param {Highcharts.SeriesOptionsType|Highcharts.Dictionary<*>} options + * The additional default options that are merged with the parent's + * options. + * + * @param {Highcharts.Dictionary<*>} [props] + * The properties (functions and primitives) to set on the new + * prototype. + * + * @param {Highcharts.Dictionary<*>} [pointProps] + * Members for a series-specific extension of the {@link Point} + * prototype if needed. + * + * @return {Highcharts.Series} + * The newly created prototype as extended from {@link Series} or its + * derivatives. + */ + // docs: add to API + extending Highcharts + var seriesType = H.seriesType = function (type, parent, options, props, pointProps) { + var defaultOptions = H.getOptions(), seriesTypes = H.seriesTypes; + // Merge the options + defaultOptions.plotOptions[type] = merge(defaultOptions.plotOptions[parent], options); + // Create the class + seriesTypes[type] = extendClass(seriesTypes[parent] || function () { }, props); + seriesTypes[type].prototype.type = type; + // Create the point class if needed + if (pointProps) { + seriesTypes[type].prototype.pointClass = + extendClass(H.Point, pointProps); + } + return seriesTypes[type]; + }; + /** + * Get a unique key for using in internal element id's and pointers. The key is + * composed of a random hash specific to this Highcharts instance, and a + * counter. + * + * @example + * var id = uniqueKey(); // => 'highcharts-x45f6hp-0' + * + * @function Highcharts.uniqueKey + * + * @return {string} + * A unique key. + */ + var uniqueKey = H.uniqueKey = (function () { + var uniqueKeyHash = Math.random().toString(36).substring(2, 9), idCounter = 0; + return function () { + return 'highcharts-' + uniqueKeyHash + '-' + idCounter++; + }; + }()); + var isFunction = H.isFunction = function (obj) { + return typeof obj === 'function'; + }; + // Register Highcharts as a plugin in jQuery + if (win.jQuery) { + /** + * Highcharts-extended JQuery. + * + * @external JQuery + */ + /** + * Helper function to return the chart of the current JQuery selector + * element. + * + * @function external:JQuery#highcharts + * + * @return {Highcharts.Chart} + * The chart that is linked to the JQuery selector element. + */ /** + * Factory function to create a chart in the current JQuery selector + * element. + * + * @function external:JQuery#highcharts + * + * @param {'Chart'|'Map'|'StockChart'|string} [className] + * Name of the factory class in the Highcharts namespace. + * + * @param {Highcharts.Options} [options] + * The chart options structure. + * + * @param {Highcharts.ChartCallbackFunction} [callback] + * Function to run when the chart has loaded and and all external + * images are loaded. Defining a + * [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load) + * handler is equivalent. + * + * @return {JQuery} + * The current JQuery selector. + */ + win.jQuery.fn.highcharts = function () { + var args = [].slice.call(arguments); + if (this[0]) { // this[0] is the renderTo div + // Create the chart + if (args[0]) { + new H[ // eslint-disable-line computed-property-spacing, no-new + // Constructor defaults to Chart + isString(args[0]) ? args.shift() : 'Chart'](this[0], args[0], args[1]); + return this; + } + // When called without parameters or with the return argument, + // return an existing chart + return charts[attr(this[0], 'data-highcharts-chart')]; + } + }; + } + // TODO use named exports when supported. + var utilitiesModule = { + Fx: H.Fx, + addEvent: addEvent, + animate: animate, + animObject: animObject, + arrayMax: arrayMax, + arrayMin: arrayMin, + attr: attr, + clamp: clamp, + clearTimeout: internalClearTimeout, + correctFloat: correctFloat, + createElement: createElement, + css: css, + defined: defined, + destroyObjectProperties: destroyObjectProperties, + discardElement: discardElement, + erase: erase, + error: error, + extend: extend, + extendClass: extendClass, + find: find, + fireEvent: fireEvent, + format: format, + getMagnitude: getMagnitude, + getNestedProperty: getNestedProperty, + getStyle: getStyle, + inArray: inArray, + isArray: isArray, + isClass: isClass, + isDOMElement: isDOMElement, + isFunction: isFunction, + isNumber: isNumber, + isObject: isObject, + isString: isString, + merge: merge, + normalizeTickInterval: normalizeTickInterval, + numberFormat: numberFormat, + objectEach: objectEach, + offset: offset, + pad: pad, + pick: pick, + pInt: pInt, + relativeLength: relativeLength, + removeEvent: removeEvent, + seriesType: seriesType, + setAnimation: setAnimation, + splat: splat, + stableSort: stableSort, + stop: stop, + syncTimeout: syncTimeout, + timeUnits: timeUnits, + uniqueKey: uniqueKey, + wrap: wrap + }; + + return utilitiesModule; + }); + _registerModule(_modules, 'parts/Color.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * A valid color to be parsed and handled by Highcharts. Highcharts internally + * supports hex colors like `#ffffff`, rgb colors like `rgb(255,255,255)` and + * rgba colors like `rgba(255,255,255,1)`. Other colors may be supported by the + * browsers and displayed correctly, but Highcharts is not able to process them + * and apply concepts like opacity and brightening. + * + * @typedef {string} Highcharts.ColorString + */ + /** + * A valid color type than can be parsed and handled by Highcharts. It can be a + * color string, a gradient object, or a pattern object. + * + * @typedef {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} Highcharts.ColorType + */ + /** + * Gradient options instead of a solid color. + * + * @example + * // Linear gradient used as a color option + * color: { + * linearGradient: { x1: 0, x2: 0, y1: 0, y2: 1 }, + * stops: [ + * [0, '#003399'], // start + * [0.5, '#ffffff'], // middle + * [1, '#3366AA'] // end + * ] + * } + * + * @interface Highcharts.GradientColorObject + */ /** + * Holds an object that defines the start position and the end position relative + * to the shape. + * @name Highcharts.GradientColorObject#linearGradient + * @type {Highcharts.LinearGradientColorObject|undefined} + */ /** + * Holds an object that defines the center position and the radius. + * @name Highcharts.GradientColorObject#radialGradient + * @type {Highcharts.RadialGradientColorObject|undefined} + */ /** + * The first item in each tuple is the position in the gradient, where 0 is the + * start of the gradient and 1 is the end of the gradient. Multiple stops can be + * applied. The second item is the color for each stop. This color can also be + * given in the rgba format. + * @name Highcharts.GradientColorObject#stops + * @type {Array} + */ + /** + * Color stop tuple. + * + * @see Highcharts.GradientColorObject + * + * @interface Highcharts.GradientColorStopObject + */ /** + * @name Highcharts.GradientColorStopObject#0 + * @type {number} + */ /** + * @name Highcharts.GradientColorStopObject#1 + * @type {Highcharts.ColorString} + */ /** + * @name Highcharts.GradoentColorStopObject#color + * @type {Highcharts.Color|undefined} + */ + /** + * Defines the start position and the end position for a gradient relative + * to the shape. Start position (x1, y1) and end position (x2, y2) are relative + * to the shape, where 0 means top/left and 1 is bottom/right. + * + * @interface Highcharts.LinearGradientColorObject + */ /** + * Start horizontal position of the gradient. Float ranges 0-1. + * @name Highcharts.LinearGradientColorObject#x1 + * @type {number} + */ /** + * End horizontal position of the gradient. Float ranges 0-1. + * @name Highcharts.LinearGradientColorObject#x2 + * @type {number} + */ /** + * Start vertical position of the gradient. Float ranges 0-1. + * @name Highcharts.LinearGradientColorObject#y1 + * @type {number} + */ /** + * End vertical position of the gradient. Float ranges 0-1. + * @name Highcharts.LinearGradientColorObject#y2 + * @type {number} + */ + /** + * Defines the center position and the radius for a gradient. + * + * @interface Highcharts.RadialGradientColorObject + */ /** + * Center horizontal position relative to the shape. Float ranges 0-1. + * @name Highcharts.RadialGradientColorObject#cx + * @type {number} + */ /** + * Center vertical position relative to the shape. Float ranges 0-1. + * @name Highcharts.RadialGradientColorObject#cy + * @type {number} + */ /** + * Radius relative to the shape. Float ranges 0-1. + * @name Highcharts.RadialGradientColorObject#r + * @type {number} + */ + var isNumber = U.isNumber, merge = U.merge, pInt = U.pInt; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Handle color operations. Some object methods are chainable. + * + * @class + * @name Highcharts.Color + * + * @param {Highcharts.ColorType} input + * The input color in either rbga or hex format + */ + var Color = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Color(input) { + // Collection of parsers. This can be extended from the outside by pushing + // parsers to Highcharts.Color.prototype.parsers. + this.parsers = [{ + // RGBA color + // eslint-disable-next-line max-len + regex: /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/, + parse: function (result) { + return [ + pInt(result[1]), + pInt(result[2]), + pInt(result[3]), + parseFloat(result[4], 10) + ]; + } + }, { + // RGB color + regex: /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/, + parse: function (result) { + return [pInt(result[1]), pInt(result[2]), pInt(result[3]), 1]; + } + }]; + this.rgba = []; + // Backwards compatibility, allow instanciation without new (#13053) + if (!(this instanceof Color)) { + return new Color(input); + } + this.init(input); + } + /* * + * + * Static Functions + * + * */ + /** + * Creates a color instance out of a color string or object. + * + * @function Highcharts.Color.parse + * + * @param {Highcharts.ColorType} input + * The input color in either rbga or hex format. + * + * @return {Highcharts.Color} + * Color instance. + */ + Color.parse = function (input) { + return new Color(input); + }; + /* * + * + * Functions + * + * */ + /** + * Parse the input color to rgba array + * + * @private + * @function Highcharts.Color#init + * + * @param {Highcharts.ColorType} input + * The input color in either rbga or hex format + * + * @return {void} + */ + Color.prototype.init = function (input) { + var result, rgba, i, parser, len; + this.input = input = Color.names[input && input.toLowerCase ? + input.toLowerCase() : + ''] || input; + // Gradients + if (input && input.stops) { + this.stops = input.stops.map(function (stop) { + return new Color(stop[1]); + }); + // Solid colors + } + else { + // Bitmasking as input[0] is not working for legacy IE. + if (input && + input.charAt && + input.charAt() === '#') { + len = input.length; + input = parseInt(input.substr(1), 16); + // Handle long-form, e.g. #AABBCC + if (len === 7) { + rgba = [ + (input & 0xFF0000) >> 16, + (input & 0xFF00) >> 8, + (input & 0xFF), + 1 + ]; + // Handle short-form, e.g. #ABC + // In short form, the value is assumed to be the same + // for both nibbles for each component. e.g. #ABC = #AABBCC + } + else if (len === 4) { + rgba = [ + (((input & 0xF00) >> 4) | + (input & 0xF00) >> 8), + (((input & 0xF0) >> 4) | + (input & 0xF0)), + ((input & 0xF) << 4) | (input & 0xF), + 1 + ]; + } + } + // Otherwise, check regex parsers + if (!rgba) { + i = this.parsers.length; + while (i-- && !rgba) { + parser = this.parsers[i]; + result = parser.regex.exec(input); + if (result) { + rgba = parser.parse(result); + } + } + } + } + this.rgba = rgba || []; + }; + /** + * Return the color or gradient stops in the specified format + * + * @function Highcharts.Color#get + * + * @param {string} [format] + * Possible values are 'a', 'rgb', 'rgba' (default). + * + * @return {Highcharts.ColorType} + * This color as a string or gradient stops. + */ + Color.prototype.get = function (format) { + var input = this.input, rgba = this.rgba, ret; + if (typeof this.stops !== 'undefined') { + ret = merge(input); + ret.stops = [].concat(ret.stops); + this.stops.forEach(function (stop, i) { + ret.stops[i] = [ + ret.stops[i][0], + stop.get(format) + ]; + }); + // it's NaN if gradient colors on a column chart + } + else if (rgba && isNumber(rgba[0])) { + if (format === 'rgb' || (!format && rgba[3] === 1)) { + ret = 'rgb(' + rgba[0] + ',' + rgba[1] + ',' + rgba[2] + ')'; + } + else if (format === 'a') { + ret = rgba[3]; + } + else { + ret = 'rgba(' + rgba.join(',') + ')'; + } + } + else { + ret = input; + } + return ret; + }; + /** + * Brighten the color instance. + * + * @function Highcharts.Color#brighten + * + * @param {number} alpha + * The alpha value. + * + * @return {Highcharts.Color} + * This color with modifications. + */ + Color.prototype.brighten = function (alpha) { + var i, rgba = this.rgba; + if (this.stops) { + this.stops.forEach(function (stop) { + stop.brighten(alpha); + }); + } + else if (isNumber(alpha) && alpha !== 0) { + for (i = 0; i < 3; i++) { + rgba[i] += pInt(alpha * 255); + if (rgba[i] < 0) { + rgba[i] = 0; + } + if (rgba[i] > 255) { + rgba[i] = 255; + } + } + } + return this; + }; + /** + * Set the color's opacity to a given alpha value. + * + * @function Highcharts.Color#setOpacity + * + * @param {number} alpha + * Opacity between 0 and 1. + * + * @return {Highcharts.Color} + * Color with modifications. + */ + Color.prototype.setOpacity = function (alpha) { + this.rgba[3] = alpha; + return this; + }; + /** + * Return an intermediate color between two colors. + * + * @function Highcharts.Color#tweenTo + * + * @param {Highcharts.Color} to + * The color object to tween to. + * + * @param {number} pos + * The intermediate position, where 0 is the from color (current + * color item), and 1 is the `to` color. + * + * @return {Highcharts.ColorString} + * The intermediate color in rgba notation. + */ + Color.prototype.tweenTo = function (to, pos) { + // Check for has alpha, because rgba colors perform worse due to lack of + // support in WebKit. + var fromRgba = this.rgba, toRgba = to.rgba, hasAlpha, ret; + // Unsupported color, return to-color (#3920, #7034) + if (!toRgba.length || !fromRgba || !fromRgba.length) { + ret = to.input || 'none'; + // Interpolate + } + else { + hasAlpha = (toRgba[3] !== 1 || fromRgba[3] !== 1); + ret = (hasAlpha ? 'rgba(' : 'rgb(') + + Math.round(toRgba[0] + (fromRgba[0] - toRgba[0]) * (1 - pos)) + + ',' + + Math.round(toRgba[1] + (fromRgba[1] - toRgba[1]) * (1 - pos)) + + ',' + + Math.round(toRgba[2] + (fromRgba[2] - toRgba[2]) * (1 - pos)) + + (hasAlpha ? + (',' + + (toRgba[3] + (fromRgba[3] - toRgba[3]) * (1 - pos))) : + '') + + ')'; + } + return ret; + }; + /* * + * + * Static Properties + * + * */ + // Collection of named colors. Can be extended from the outside by adding + // colors to Highcharts.Color.names. + Color.names = { + white: '#ffffff', + black: '#000000' + }; + return Color; + }()); + H.Color = Color; + /** + * Creates a color instance out of a color string. + * + * @function Highcharts.color + * + * @param {Highcharts.ColorType} input + * The input color in either rbga or hex format + * + * @return {Highcharts.Color} + * Color instance + */ + H.color = Color.parse; + + return H.Color; + }); + _registerModule(_modules, 'parts/SVGElement.js', [_modules['parts/Color.js'], _modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (Color, H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var deg2rad = H.deg2rad, doc = H.doc, hasTouch = H.hasTouch, isFirefox = H.isFirefox, noop = H.noop, svg = H.svg, SVG_NS = H.SVG_NS, win = H.win; + var animate = U.animate, animObject = U.animObject, attr = U.attr, createElement = U.createElement, css = U.css, defined = U.defined, erase = U.erase, extend = U.extend, fireEvent = U.fireEvent, inArray = U.inArray, isArray = U.isArray, isFunction = U.isFunction, isNumber = U.isNumber, isString = U.isString, merge = U.merge, objectEach = U.objectEach, pick = U.pick, pInt = U.pInt, stop = U.stop, uniqueKey = U.uniqueKey; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The SVGElement prototype is a JavaScript wrapper for SVG elements used in the + * rendering layer of Highcharts. Combined with the + * {@link Highcharts.SVGRenderer} + * object, these prototypes allow freeform annotation in the charts or even in + * HTML pages without instanciating a chart. The SVGElement can also wrap HTML + * labels, when `text` or `label` elements are created with the `useHTML` + * parameter. + * + * The SVGElement instances are created through factory functions on the + * {@link Highcharts.SVGRenderer} + * object, like + * {@link Highcharts.SVGRenderer#rect|rect}, + * {@link Highcharts.SVGRenderer#path|path}, + * {@link Highcharts.SVGRenderer#text|text}, + * {@link Highcharts.SVGRenderer#label|label}, + * {@link Highcharts.SVGRenderer#g|g} + * and more. + * + * @class + * @name Highcharts.SVGElement + */ + var SVGElement = /** @class */ (function () { + function SVGElement() { + /* * + * + * Properties + * + * */ + this.element = void 0; + this.height = void 0; + this.opacity = 1; // Default base for animation + this.renderer = void 0; + this.SVG_NS = SVG_NS; + // Custom attributes used for symbols, these should be filtered out when + // setting SVGElement attributes (#9375). + this.symbolCustomAttribs = [ + 'x', + 'y', + 'width', + 'height', + 'r', + 'start', + 'end', + 'innerR', + 'anchorX', + 'anchorY', + 'rounded' + ]; + /** + * For labels, these CSS properties are applied to the `text` node directly. + * + * @private + * @name Highcharts.SVGElement#textProps + * @type {Array} + */ + this.textProps = [ + 'color', 'cursor', 'direction', 'fontFamily', 'fontSize', 'fontStyle', + 'fontWeight', 'lineHeight', 'textAlign', 'textDecoration', + 'textOutline', 'textOverflow', 'width' + ]; + this.width = void 0; + } + /* * + * + * Functions + * + * */ + /** + * Get the current value of an attribute or pseudo attribute, + * used mainly for animation. Called internally from + * the {@link Highcharts.SVGRenderer#attr} function. + * + * @private + * @function Highcharts.SVGElement#_defaultGetter + * + * @param {string} key + * Property key. + * + * @return {number|string} + * Property value. + */ + SVGElement.prototype._defaultGetter = function (key) { + var ret = pick(this[key + 'Value'], // align getter + this[key], this.element ? this.element.getAttribute(key) : null, 0); + if (/^[\-0-9\.]+$/.test(ret)) { // is numerical + ret = parseFloat(ret); + } + return ret; + }; + /** + * @private + * @function Highcharts.SVGElement#_defaultSetter + * + * @param {string} value + * + * @param {string} key + * + * @param {Highcharts.SVGDOMElement} element + * + * @return {void} + */ + SVGElement.prototype._defaultSetter = function (value, key, element) { + element.setAttribute(key, value); + }; + /** + * Add the element to the DOM. All elements must be added this way. + * + * @sample highcharts/members/renderer-g + * Elements added to a group + * + * @function Highcharts.SVGElement#add + * + * @param {Highcharts.SVGElement} [parent] + * The parent item to add it to. If undefined, the element is added + * to the {@link Highcharts.SVGRenderer.box}. + * + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.add = function (parent) { + var renderer = this.renderer, element = this.element, inserted; + if (parent) { + this.parentGroup = parent; + } + // mark as inverted + this.parentInverted = parent && parent.inverted; + // build formatted text + if (typeof this.textStr !== 'undefined') { + renderer.buildText(this); + } + // Mark as added + this.added = true; + // If we're adding to renderer root, or other elements in the group + // have a z index, we need to handle it + if (!parent || parent.handleZ || this.zIndex) { + inserted = this.zIndexSetter(); + } + // If zIndex is not handled, append at the end + if (!inserted) { + (parent ? + parent.element : + renderer.box).appendChild(element); + } + // fire an event for internal hooks + if (this.onAdd) { + this.onAdd(); + } + return this; + }; + /** + * Add a class name to an element. + * + * @function Highcharts.SVGElement#addClass + * + * @param {string} className + * The new class name to add. + * + * @param {boolean} [replace=false] + * When true, the existing class name(s) will be overwritten with the new + * one. When false, the new one is added. + * + * @return {Highcharts.SVGElement} + * Return the SVG element for chainability. + */ + SVGElement.prototype.addClass = function (className, replace) { + var currentClassName = replace ? '' : (this.attr('class') || ''); + // Trim the string and remove duplicates + className = (className || '') + .split(/ /g) + .reduce(function (newClassName, name) { + if (currentClassName.indexOf(name) === -1) { + newClassName.push(name); + } + return newClassName; + }, (currentClassName ? + [currentClassName] : + [])) + .join(' '); + if (className !== currentClassName) { + this.attr('class', className); + } + return this; + }; + /** + * This method is executed in the end of `attr()`, after setting all + * attributes in the hash. In can be used to efficiently consolidate + * multiple attributes in one SVG property -- e.g., translate, rotate and + * scale are merged in one "transform" attribute in the SVG node. + * + * @private + * @function Highcharts.SVGElement#afterSetters + */ + SVGElement.prototype.afterSetters = function () { + // Update transform. Do this outside the loop to prevent redundant + // updating for batch setting of attributes. + if (this.doTransform) { + this.updateTransform(); + this.doTransform = false; + } + }; + /** + * Align the element relative to the chart or another box. + * + * @function Highcharts.SVGElement#align + * + * @param {Highcharts.AlignObject} [alignOptions] + * The alignment options. The function can be called without this + * parameter in order to re-align an element after the box has been + * updated. + * + * @param {boolean} [alignByTranslate] + * Align element by translation. + * + * @param {string|Highcharts.BBoxObject} [box] + * The box to align to, needs a width and height. When the box is a + * string, it refers to an object in the Renderer. For example, when + * box is `spacingBox`, it refers to `Renderer.spacingBox` which + * holds `width`, `height`, `x` and `y` properties. + * + * @return {Highcharts.SVGElement} Returns the SVGElement for chaining. + */ + SVGElement.prototype.align = function (alignOptions, alignByTranslate, box) { + var align, vAlign, x, y, attribs = {}, alignTo, renderer = this.renderer, alignedObjects = renderer.alignedObjects, alignFactor, vAlignFactor; + // First call on instanciate + if (alignOptions) { + this.alignOptions = alignOptions; + this.alignByTranslate = alignByTranslate; + if (!box || isString(box)) { + this.alignTo = alignTo = box || 'renderer'; + // prevent duplicates, like legendGroup after resize + erase(alignedObjects, this); + alignedObjects.push(this); + box = void 0; // reassign it below + } + // When called on resize, no arguments are supplied + } + else { + alignOptions = this.alignOptions; + alignByTranslate = this.alignByTranslate; + alignTo = this.alignTo; + } + box = pick(box, renderer[alignTo], renderer); + // Assign variables + align = alignOptions.align; + vAlign = alignOptions.verticalAlign; + // default: left align + x = (box.x || 0) + (alignOptions.x || 0); + // default: top align + y = (box.y || 0) + (alignOptions.y || 0); + // Align + if (align === 'right') { + alignFactor = 1; + } + else if (align === 'center') { + alignFactor = 2; + } + if (alignFactor) { + x += (box.width - (alignOptions.width || 0)) / + alignFactor; + } + attribs[alignByTranslate ? 'translateX' : 'x'] = Math.round(x); + // Vertical align + if (vAlign === 'bottom') { + vAlignFactor = 1; + } + else if (vAlign === 'middle') { + vAlignFactor = 2; + } + if (vAlignFactor) { + y += (box.height - (alignOptions.height || 0)) / + vAlignFactor; + } + attribs[alignByTranslate ? 'translateY' : 'y'] = Math.round(y); + // Animate only if already placed + this[this.placed ? 'animate' : 'attr'](attribs); + this.placed = true; + this.alignAttr = attribs; + return this; + }; + /** + * @private + * @function Highcharts.SVGElement#alignSetter + * @param {"left"|"center"|"right"} value + */ + SVGElement.prototype.alignSetter = function (value) { + var convert = { + left: 'start', + center: 'middle', + right: 'end' + }; + if (convert[value]) { + this.alignValue = value; + this.element.setAttribute('text-anchor', convert[value]); + } + }; + /** + * Animate to given attributes or CSS properties. + * + * @sample highcharts/members/element-on/ + * Setting some attributes by animation + * + * @function Highcharts.SVGElement#animate + * + * @param {Highcharts.SVGAttributes} params + * SVG attributes or CSS to animate. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [options] + * Animation options. + * + * @param {Function} [complete] + * Function to perform at the end of animation. + * + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.animate = function (params, options, complete) { + var animOptions = animObject(pick(options, this.renderer.globalAnimation, true)); + // When the page is hidden save resources in the background by not + // running animation at all (#9749). + if (pick(doc.hidden, doc.msHidden, doc.webkitHidden, false)) { + animOptions.duration = 0; + } + if (animOptions.duration !== 0) { + // allows using a callback with the global animation without + // overwriting it + if (complete) { + animOptions.complete = complete; + } + animate(this, params, animOptions); + } + else { + this.attr(params, void 0, complete); + // Call the end step synchronously + objectEach(params, function (val, prop) { + if (animOptions.step) { + animOptions.step.call(this, val, { prop: prop, pos: 1 }); + } + }, this); + } + return this; + }; + /** + * Apply a text outline through a custom CSS property, by copying the text + * element and apply stroke to the copy. Used internally. Contrast checks at + * [example](https://jsfiddle.net/highcharts/43soe9m1/2/). + * + * @example + * // Specific color + * text.css({ + * textOutline: '1px black' + * }); + * // Automatic contrast + * text.css({ + * color: '#000000', // black text + * textOutline: '1px contrast' // => white outline + * }); + * + * @private + * @function Highcharts.SVGElement#applyTextOutline + * + * @param {string} textOutline + * A custom CSS `text-outline` setting, defined by `width color`. + */ + SVGElement.prototype.applyTextOutline = function (textOutline) { + var elem = this.element, tspans, hasContrast = textOutline.indexOf('contrast') !== -1, styles = {}, color, strokeWidth, firstRealChild; + // When the text shadow is set to contrast, use dark stroke for light + // text and vice versa. + if (hasContrast) { + styles.textOutline = textOutline = textOutline.replace(/contrast/g, this.renderer.getContrast(elem.style.fill)); + } + // Extract the stroke width and color + textOutline = textOutline.split(' '); + color = textOutline[textOutline.length - 1]; + strokeWidth = textOutline[0]; + if (strokeWidth && strokeWidth !== 'none' && H.svg) { + this.fakeTS = true; // Fake text shadow + tspans = [].slice.call(elem.getElementsByTagName('tspan')); + // In order to get the right y position of the clone, + // copy over the y setter + this.ySetter = this.xSetter; + // Since the stroke is applied on center of the actual outline, we + // need to double it to get the correct stroke-width outside the + // glyphs. + strokeWidth = strokeWidth.replace(/(^[\d\.]+)(.*?)$/g, function (match, digit, unit) { + return (2 * digit) + unit; + }); + // Remove shadows from previous runs. + this.removeTextOutline(tspans); + // Check if the element contains RTL characters. + // Comparing against Hebrew and Arabic characters, + // excluding Arabic digits. Source: + // https://www.unicode.org/Public/UNIDATA/extracted/DerivedBidiClass.txt + var isRTL_1 = elem.textContent ? + /^[\u0591-\u065F\u066A-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC]/ + .test(elem.textContent) : false; + // For each of the tspans, create a stroked copy behind it. + firstRealChild = elem.firstChild; + tspans.forEach(function (tspan, y) { + var clone; + // Let the first line start at the correct X position + if (y === 0) { + tspan.setAttribute('x', elem.getAttribute('x')); + y = elem.getAttribute('y'); + tspan.setAttribute('y', y || 0); + if (y === null) { + elem.setAttribute('y', 0); + } + } + // Create the clone and apply outline properties. + // For RTL elements apply outline properties for orginal element + // to prevent outline from overlapping the text. + // For RTL in Firefox keep the orginal order (#10162). + clone = tspan.cloneNode(true); + attr((isRTL_1 && !isFirefox) ? tspan : clone, { + 'class': 'highcharts-text-outline', + fill: color, + stroke: color, + 'stroke-width': strokeWidth, + 'stroke-linejoin': 'round' + }); + elem.insertBefore(clone, firstRealChild); + }); + // Create a whitespace between tspan and clone, + // to fix the display of Arabic characters in Firefox. + if (isRTL_1 && isFirefox && tspans[0]) { + var whitespace = tspans[0].cloneNode(true); + whitespace.textContent = ' '; + elem.insertBefore(whitespace, firstRealChild); + } + } + }; + /** + * @function Highcharts.SVGElement#attr + * @param {string} key + * @return {number|string} + */ /** + * Apply native and custom attributes to the SVG elements. + * + * In order to set the rotation center for rotation, set x and y to 0 and + * use `translateX` and `translateY` attributes to position the element + * instead. + * + * Attributes frequently used in Highcharts are `fill`, `stroke`, + * `stroke-width`. + * + * @sample highcharts/members/renderer-rect/ + * Setting some attributes + * + * @example + * // Set multiple attributes + * element.attr({ + * stroke: 'red', + * fill: 'blue', + * x: 10, + * y: 10 + * }); + * + * // Set a single attribute + * element.attr('stroke', 'red'); + * + * // Get an attribute + * element.attr('stroke'); // => 'red' + * + * @function Highcharts.SVGElement#attr + * + * @param {string|Highcharts.SVGAttributes} [hash] + * The native and custom SVG attributes. + * + * @param {number|string|Highcharts.SVGPathArray} [val] + * If the type of the first argument is `string`, the second can be a + * value, which will serve as a single attribute setter. If the first + * argument is a string and the second is undefined, the function + * serves as a getter and the current value of the property is + * returned. + * + * @param {Function} [complete] + * A callback function to execute after setting the attributes. This + * makes the function compliant and interchangeable with the + * {@link SVGElement#animate} function. + * + * @param {boolean} [continueAnimation=true] + * Used internally when `.attr` is called as part of an animation + * step. Otherwise, calling `.attr` for an attribute will stop + * animation for that attribute. + * + * @return {Highcharts.SVGElement} + * If used as a setter, it returns the current + * {@link Highcharts.SVGElement} so the calls can be chained. If + * used as a getter, the current value of the attribute is returned. + */ + SVGElement.prototype.attr = function (hash, val, complete, continueAnimation) { + var key, element = this.element, hasSetSymbolSize, ret = this, skipAttr, setter, symbolCustomAttribs = this.symbolCustomAttribs; + // single key-value pair + if (typeof hash === 'string' && typeof val !== 'undefined') { + key = hash; + hash = {}; + hash[key] = val; + } + // used as a getter: first argument is a string, second is undefined + if (typeof hash === 'string') { + ret = (this[hash + 'Getter'] || + this._defaultGetter).call(this, hash, element); + // setter + } + else { + objectEach(hash, function eachAttribute(val, key) { + skipAttr = false; + // Unless .attr is from the animator update, stop current + // running animation of this property + if (!continueAnimation) { + stop(this, key); + } + // Special handling of symbol attributes + if (this.symbolName && + inArray(key, symbolCustomAttribs) !== -1) { + if (!hasSetSymbolSize) { + this.symbolAttr(hash); + hasSetSymbolSize = true; + } + skipAttr = true; + } + if (this.rotation && (key === 'x' || key === 'y')) { + this.doTransform = true; + } + if (!skipAttr) { + setter = (this[key + 'Setter'] || + this._defaultSetter); + setter.call(this, val, key, element); + // Let the shadow follow the main element + if (!this.styledMode && + this.shadows && + /^(width|height|visibility|x|y|d|transform|cx|cy|r)$/.test(key)) { + this.updateShadows(key, val, setter); + } + } + }, this); + this.afterSetters(); + } + // In accordance with animate, run a complete callback + if (complete) { + complete.call(this); + } + return ret; + }; + /** + * Apply a clipping rectangle to this element. + * + * @function Highcharts.SVGElement#clip + * + * @param {Highcharts.ClipRectElement} [clipRect] + * The clipping rectangle. If skipped, the current clip is removed. + * + * @return {Highcharts.SVGElement} + * Returns the SVG element to allow chaining. + */ + SVGElement.prototype.clip = function (clipRect) { + return this.attr('clip-path', clipRect ? + 'url(' + this.renderer.url + '#' + clipRect.id + ')' : + 'none'); + }; + /** + * Calculate the coordinates needed for drawing a rectangle crisply and + * return the calculated attributes. + * + * @function Highcharts.SVGElement#crisp + * + * @param {Highcharts.RectangleObject} rect + * Rectangle to crisp. + * + * @param {number} [strokeWidth] + * The stroke width to consider when computing crisp positioning. It can + * also be set directly on the rect parameter. + * + * @return {Highcharts.RectangleObject} + * The modified rectangle arguments. + */ + SVGElement.prototype.crisp = function (rect, strokeWidth) { + var wrapper = this, normalizer; + strokeWidth = strokeWidth || rect.strokeWidth || 0; + // Math.round because strokeWidth can sometimes have roundoff errors + normalizer = Math.round(strokeWidth) % 2 / 2; + // normalize for crisp edges + rect.x = Math.floor(rect.x || wrapper.x || 0) + normalizer; + rect.y = Math.floor(rect.y || wrapper.y || 0) + normalizer; + rect.width = Math.floor((rect.width || wrapper.width || 0) - 2 * normalizer); + rect.height = Math.floor((rect.height || wrapper.height || 0) - 2 * normalizer); + if (defined(rect.strokeWidth)) { + rect.strokeWidth = strokeWidth; + } + return rect; + }; + /** + * Build and apply an SVG gradient out of a common JavaScript configuration + * object. This function is called from the attribute setters. An event + * hook is added for supporting other complex color types. + * + * @private + * @function Highcharts.SVGElement#complexColor + * + * @param {Highcharts.GradientColorObject|Highcharts.PatternObject} colorOptions + * The gradient or pattern options structure. + * + * @param {string} prop + * The property to apply, can either be `fill` or `stroke`. + * + * @param {Highcharts.SVGDOMElement} elem + * SVG element to apply the gradient on. + */ + SVGElement.prototype.complexColor = function (colorOptions, prop, elem) { + var renderer = this.renderer, colorObject, gradName, gradAttr, radAttr, gradients, stops, stopColor, stopOpacity, radialReference, id, key = [], value; + fireEvent(this.renderer, 'complexColor', { + args: arguments + }, function () { + // Apply linear or radial gradients + if (colorOptions.radialGradient) { + gradName = 'radialGradient'; + } + else if (colorOptions.linearGradient) { + gradName = 'linearGradient'; + } + if (gradName) { + gradAttr = colorOptions[gradName]; + gradients = renderer.gradients; + stops = colorOptions.stops; + radialReference = elem.radialReference; + // Keep < 2.2 kompatibility + if (isArray(gradAttr)) { + colorOptions[gradName] = gradAttr = { + x1: gradAttr[0], + y1: gradAttr[1], + x2: gradAttr[2], + y2: gradAttr[3], + gradientUnits: 'userSpaceOnUse' + }; + } + // Correct the radial gradient for the radial reference system + if (gradName === 'radialGradient' && + radialReference && + !defined(gradAttr.gradientUnits)) { + // Save the radial attributes for updating + radAttr = gradAttr; + gradAttr = merge(gradAttr, renderer.getRadialAttr(radialReference, radAttr), { gradientUnits: 'userSpaceOnUse' }); + } + // Build the unique key to detect whether we need to create a + // new element (#1282) + objectEach(gradAttr, function (val, n) { + if (n !== 'id') { + key.push(n, val); + } + }); + objectEach(stops, function (val) { + key.push(val); + }); + key = key.join(','); + // Check if a gradient object with the same config object is + // created within this renderer + if (gradients[key]) { + id = gradients[key].attr('id'); + } + else { + // Set the id and create the element + gradAttr.id = id = uniqueKey(); + var gradientObject_1 = gradients[key] = + renderer.createElement(gradName) + .attr(gradAttr) + .add(renderer.defs); + gradientObject_1.radAttr = radAttr; + // The gradient needs to keep a list of stops to be able to + // destroy them + gradientObject_1.stops = []; + stops.forEach(function (stop) { + var stopObject; + if (stop[1].indexOf('rgba') === 0) { + colorObject = Color.parse(stop[1]); + stopColor = colorObject.get('rgb'); + stopOpacity = colorObject.get('a'); + } + else { + stopColor = stop[1]; + stopOpacity = 1; + } + stopObject = renderer.createElement('stop').attr({ + offset: stop[0], + 'stop-color': stopColor, + 'stop-opacity': stopOpacity + }).add(gradientObject_1); + // Add the stop element to the gradient + gradientObject_1.stops.push(stopObject); + }); + } + // Set the reference to the gradient object + value = 'url(' + renderer.url + '#' + id + ')'; + elem.setAttribute(prop, value); + elem.gradient = key; + // Allow the color to be concatenated into tooltips formatters + // etc. (#2995) + colorOptions.toString = function () { + return value; + }; + } + }); + }; + /** + * Set styles for the element. In addition to CSS styles supported by + * native SVG and HTML elements, there are also some custom made for + * Highcharts, like `width`, `ellipsis` and `textOverflow` for SVG text + * elements. + * + * @sample highcharts/members/renderer-text-on-chart/ + * Styled text + * + * @function Highcharts.SVGElement#css + * + * @param {Highcharts.CSSObject} styles + * The new CSS styles. + * + * @return {Highcharts.SVGElement} + * Return the SVG element for chaining. + */ + SVGElement.prototype.css = function (styles) { + var oldStyles = this.styles, newStyles = {}, elem = this.element, textWidth, serializedCss = '', hyphenate, hasNew = !oldStyles, + // These CSS properties are interpreted internally by the SVG + // renderer, but are not supported by SVG and should not be added to + // the DOM. In styled mode, no CSS should find its way to the DOM + // whatsoever (#6173, #6474). + svgPseudoProps = ['textOutline', 'textOverflow', 'width']; + // convert legacy + if (styles && styles.color) { + styles.fill = styles.color; + } + // Filter out existing styles to increase performance (#2640) + if (oldStyles) { + objectEach(styles, function (style, n) { + if (oldStyles && oldStyles[n] !== style) { + newStyles[n] = style; + hasNew = true; + } + }); + } + if (hasNew) { + // Merge the new styles with the old ones + if (oldStyles) { + styles = extend(oldStyles, newStyles); + } + // Get the text width from style + if (styles) { + // Previously set, unset it (#8234) + if (styles.width === null || styles.width === 'auto') { + delete this.textWidth; + // Apply new + } + else if (elem.nodeName.toLowerCase() === 'text' && + styles.width) { + textWidth = this.textWidth = pInt(styles.width); + } + } + // store object + this.styles = styles; + if (textWidth && (!svg && this.renderer.forExport)) { + delete styles.width; + } + // Serialize and set style attribute + if (elem.namespaceURI === this.SVG_NS) { // #7633 + hyphenate = function (a, b) { + return '-' + b.toLowerCase(); + }; + objectEach(styles, function (style, n) { + if (svgPseudoProps.indexOf(n) === -1) { + serializedCss += + n.replace(/([A-Z])/g, hyphenate) + ':' + + style + ';'; + } + }); + if (serializedCss) { + attr(elem, 'style', serializedCss); // #1881 + } + } + else { + css(elem, styles); + } + if (this.added) { + // Rebuild text after added. Cache mechanisms in the buildText + // will prevent building if there are no significant changes. + if (this.element.nodeName === 'text') { + this.renderer.buildText(this); + } + // Apply text outline after added + if (styles && styles.textOutline) { + this.applyTextOutline(styles.textOutline); + } + } + } + return this; + }; + /** + * @private + * @function Highcharts.SVGElement#dashstyleSetter + * @param {string} value + */ + SVGElement.prototype.dashstyleSetter = function (value) { + var i, strokeWidth = this['stroke-width']; + // If "inherit", like maps in IE, assume 1 (#4981). With HC5 and the new + // strokeWidth function, we should be able to use that instead. + if (strokeWidth === 'inherit') { + strokeWidth = 1; + } + value = value && value.toLowerCase(); + if (value) { + var v = value + .replace('shortdashdotdot', '3,1,1,1,1,1,') + .replace('shortdashdot', '3,1,1,1') + .replace('shortdot', '1,1,') + .replace('shortdash', '3,1,') + .replace('longdash', '8,3,') + .replace(/dot/g, '1,3,') + .replace('dash', '4,3,') + .replace(/,$/, '') + .split(','); // ending comma + i = v.length; + while (i--) { + v[i] = '' + (pInt(v[i]) * pick(strokeWidth, NaN)); + } + value = v.join(',').replace(/NaN/g, 'none'); // #3226 + this.element.setAttribute('stroke-dasharray', value); + } + }; + /** + * Destroy the element and element wrapper and clear up the DOM and event + * hooks. + * + * @function Highcharts.SVGElement#destroy + */ + SVGElement.prototype.destroy = function () { + var wrapper = this, element = wrapper.element || {}, renderer = wrapper.renderer, parentToClean = (renderer.isSVG && + element.nodeName === 'SPAN' && + wrapper.parentGroup || + void 0), grandParent, ownerSVGElement = element.ownerSVGElement, i; + // remove events + element.onclick = element.onmouseout = element.onmouseover = + element.onmousemove = element.point = null; + stop(wrapper); // stop running animations + if (wrapper.clipPath && ownerSVGElement) { + var clipPath_1 = wrapper.clipPath; + // Look for existing references to this clipPath and remove them + // before destroying the element (#6196). + // The upper case version is for Edge + [].forEach.call(ownerSVGElement.querySelectorAll('[clip-path],[CLIP-PATH]'), function (el) { + var clipPathAttr = el.getAttribute('clip-path'); + if (clipPathAttr.indexOf(clipPath_1.element.id) > -1) { + el.removeAttribute('clip-path'); + } + }); + wrapper.clipPath = clipPath_1.destroy(); + } + // Destroy stops in case this is a gradient object @todo old code? + if (wrapper.stops) { + for (i = 0; i < wrapper.stops.length; i++) { + wrapper.stops[i].destroy(); + } + wrapper.stops.length = 0; + wrapper.stops = void 0; + } + // remove element + wrapper.safeRemoveChild(element); + if (!renderer.styledMode) { + wrapper.destroyShadows(); + } + // In case of useHTML, clean up empty containers emulating SVG groups + // (#1960, #2393, #2697). + while (parentToClean && + parentToClean.div && + parentToClean.div.childNodes.length === 0) { + grandParent = parentToClean.parentGroup; + wrapper.safeRemoveChild(parentToClean.div); + delete parentToClean.div; + parentToClean = grandParent; + } + // remove from alignObjects + if (wrapper.alignTo) { + erase(renderer.alignedObjects, wrapper); + } + objectEach(wrapper, function (val, key) { + // Destroy child elements of a group + if (wrapper[key] && + wrapper[key].parentGroup === wrapper && + wrapper[key].destroy) { + wrapper[key].destroy(); + } + // Delete all properties + delete wrapper[key]; + }); + return; + }; + /** + * Destroy shadows on the element. + * + * @private + * @function Highcharts.SVGElement#destroyShadows + * + * @return {void} + */ + SVGElement.prototype.destroyShadows = function () { + (this.shadows || []).forEach(function (shadow) { + this.safeRemoveChild(shadow); + }, this); + this.shadows = void 0; + }; + /** + * @private + */ + SVGElement.prototype.destroyTextPath = function (elem, path) { + var textElement = elem.getElementsByTagName('text')[0]; + var tspans; + if (textElement) { + // Remove textPath attributes + textElement.removeAttribute('dx'); + textElement.removeAttribute('dy'); + // Remove ID's: + path.element.setAttribute('id', ''); + // Check if textElement includes textPath, + if (this.textPathWrapper && + textElement.getElementsByTagName('textPath').length) { + // Move nodes to + tspans = this.textPathWrapper.element.childNodes; + // Now move all 's to the node + while (tspans.length) { + textElement.appendChild(tspans[0]); + } + // Remove from the DOM + textElement.removeChild(this.textPathWrapper.element); + } + } + else if (elem.getAttribute('dx') || elem.getAttribute('dy')) { + // Remove textPath attributes from elem + // to get correct text-outline position + elem.removeAttribute('dx'); + elem.removeAttribute('dy'); + } + if (this.textPathWrapper) { + // Set textPathWrapper to undefined and destroy it + this.textPathWrapper = this.textPathWrapper.destroy(); + } + }; + /** + * @private + * @function Highcharts.SVGElement#dSettter + * @param {number|string|Highcharts.SVGPathArray} value + * @param {string} key + * @param {Highcharts.SVGDOMElement} element + */ + SVGElement.prototype.dSetter = function (value, key, element) { + if (isArray(value)) { + // Backwards compatibility, convert one-dimensional array into an + // array of segments + if (typeof value[0] === 'string') { + value = this.renderer.pathToSegments(value); + } + this.pathArray = value; + value = value.reduce(function (acc, seg, i) { + if (!seg || !seg.join) { + return (seg || '').toString(); + } + return (i ? acc + ' ' : '') + seg.join(' '); + }, ''); + } + if (/(NaN| {2}|^$)/.test(value)) { + value = 'M 0 0'; + } + // Check for cache before resetting. Resetting causes disturbance in the + // DOM, causing flickering in some cases in Edge/IE (#6747). Also + // possible performance gain. + if (this[key] !== value) { + element.setAttribute(key, value); + this[key] = value; + } + }; + /** + * Fade out an element by animating its opacity down to 0, and hide it on + * complete. Used internally for the tooltip. + * + * @function Highcharts.SVGElement#fadeOut + * + * @param {number} [duration=150] + * The fade duration in milliseconds. + */ + SVGElement.prototype.fadeOut = function (duration) { + var elemWrapper = this; + elemWrapper.animate({ + opacity: 0 + }, { + duration: pick(duration, 150), + complete: function () { + // #3088, assuming we're only using this for tooltips + elemWrapper.attr({ y: -9999 }).hide(); + } + }); + }; + /** + * @private + * @function Highcharts.SVGElement#fillSetter + * @param {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} value + * @param {string} key + * @param {Highcharts.SVGDOMElement} element + */ + SVGElement.prototype.fillSetter = function (value, key, element) { + if (typeof value === 'string') { + element.setAttribute(key, value); + } + else if (value) { + this.complexColor(value, key, element); + } + }; + /** + * Get the bounding box (width, height, x and y) for the element. Generally + * used to get rendered text size. Since this is called a lot in charts, + * the results are cached based on text properties, in order to save DOM + * traffic. The returned bounding box includes the rotation, so for example + * a single text line of rotation 90 will report a greater height, and a + * width corresponding to the line-height. + * + * @sample highcharts/members/renderer-on-chart/ + * Draw a rectangle based on a text's bounding box + * + * @function Highcharts.SVGElement#getBBox + * + * @param {boolean} [reload] + * Skip the cache and get the updated DOM bouding box. + * + * @param {number} [rot] + * Override the element's rotation. This is internally used on axis + * labels with a value of 0 to find out what the bounding box would + * be have been if it were not rotated. + * + * @return {Highcharts.BBoxObject} + * The bounding box with `x`, `y`, `width` and `height` properties. + */ + SVGElement.prototype.getBBox = function (reload, rot) { + var wrapper = this, bBox, // = wrapper.bBox, + renderer = wrapper.renderer, width, height, element = wrapper.element, styles = wrapper.styles, fontSize, textStr = wrapper.textStr, toggleTextShadowShim, cache = renderer.cache, cacheKeys = renderer.cacheKeys, isSVG = element.namespaceURI === wrapper.SVG_NS, cacheKey; + var rotation = pick(rot, wrapper.rotation, 0); + fontSize = renderer.styledMode ? (element && + SVGElement.prototype.getStyle.call(element, 'font-size')) : (styles && styles.fontSize); + // Avoid undefined and null (#7316) + if (defined(textStr)) { + cacheKey = textStr.toString(); + // Since numbers are monospaced, and numerical labels appear a lot + // in a chart, we assume that a label of n characters has the same + // bounding box as others of the same length. Unless there is inner + // HTML in the label. In that case, leave the numbers as is (#5899). + if (cacheKey.indexOf('<') === -1) { + cacheKey = cacheKey.replace(/[0-9]/g, '0'); + } + // Properties that affect bounding box + cacheKey += [ + '', + rotation, + fontSize, + wrapper.textWidth, + styles && styles.textOverflow, + styles && styles.fontWeight // #12163 + ].join(','); + } + if (cacheKey && !reload) { + bBox = cache[cacheKey]; + } + // No cache found + if (!bBox) { + // SVG elements + if (isSVG || renderer.forExport) { + try { // Fails in Firefox if the container has display: none. + // When the text shadow shim is used, we need to hide the + // fake shadows to get the correct bounding box (#3872) + toggleTextShadowShim = this.fakeTS && function (display) { + [].forEach.call(element.querySelectorAll('.highcharts-text-outline'), function (tspan) { + tspan.style.display = display; + }); + }; + // Workaround for #3842, Firefox reporting wrong bounding + // box for shadows + if (isFunction(toggleTextShadowShim)) { + toggleTextShadowShim('none'); + } + bBox = element.getBBox ? + // SVG: use extend because IE9 is not allowed to change + // width and height in case of rotation (below) + extend({}, element.getBBox()) : { + // Legacy IE in export mode + width: element.offsetWidth, + height: element.offsetHeight + }; + // #3842 + if (isFunction(toggleTextShadowShim)) { + toggleTextShadowShim(''); + } + } + catch (e) { + ''; + } + // If the bBox is not set, the try-catch block above failed. The + // other condition is for Opera that returns a width of + // -Infinity on hidden elements. + if (!bBox || bBox.width < 0) { + bBox = { width: 0, height: 0 }; + } + // VML Renderer or useHTML within SVG + } + else { + bBox = wrapper.htmlGetBBox(); + } + // True SVG elements as well as HTML elements in modern browsers + // using the .useHTML option need to compensated for rotation + if (renderer.isSVG) { + width = bBox.width; + height = bBox.height; + // Workaround for wrong bounding box in IE, Edge and Chrome on + // Windows. With Highcharts' default font, IE and Edge report + // a box height of 16.899 and Chrome rounds it to 17. If this + // stands uncorrected, it results in more padding added below + // the text than above when adding a label border or background. + // Also vertical positioning is affected. + // https://jsfiddle.net/highcharts/em37nvuj/ + // (#1101, #1505, #1669, #2568, #6213). + if (isSVG) { + bBox.height = height = ({ + '11px,17': 14, + '13px,20': 16 + }[styles && + styles.fontSize + ',' + Math.round(height)] || + height); + } + // Adjust for rotated text + if (rotation) { + var rad = rotation * deg2rad; + bBox.width = Math.abs(height * Math.sin(rad)) + + Math.abs(width * Math.cos(rad)); + bBox.height = Math.abs(height * Math.cos(rad)) + + Math.abs(width * Math.sin(rad)); + } + } + // Cache it. When loading a chart in a hidden iframe in Firefox and + // IE/Edge, the bounding box height is 0, so don't cache it (#5620). + if (cacheKey && bBox.height > 0) { + // Rotate (#4681) + while (cacheKeys.length > 250) { + delete cache[cacheKeys.shift()]; + } + if (!cache[cacheKey]) { + cacheKeys.push(cacheKey); + } + cache[cacheKey] = bBox; + } + } + return bBox; + }; + /** + * Get the computed style. Only in styled mode. + * + * @example + * chart.series[0].points[0].graphic.getStyle('stroke-width'); // => '1px' + * + * @function Highcharts.SVGElement#getStyle + * + * @param {string} prop + * The property name to check for. + * + * @return {string} + * The current computed value. + */ + SVGElement.prototype.getStyle = function (prop) { + return win + .getComputedStyle(this.element || this, '') + .getPropertyValue(prop); + }; + /** + * Check if an element has the given class name. + * + * @function Highcharts.SVGElement#hasClass + * + * @param {string} className + * The class name to check for. + * + * @return {boolean} + * Whether the class name is found. + */ + SVGElement.prototype.hasClass = function (className) { + return ('' + this.attr('class')) + .split(' ') + .indexOf(className) !== -1; + }; + /** + * Hide the element, similar to setting the `visibility` attribute to + * `hidden`. + * + * @function Highcharts.SVGElement#hide + * + * @param {boolean} [hideByTranslation=false] + * The flag to determine if element should be hidden by moving out + * of the viewport. Used for example for dataLabels. + * + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.hide = function (hideByTranslation) { + if (hideByTranslation) { + this.attr({ y: -9999 }); + } + else { + this.attr({ visibility: 'hidden' }); + } + return this; + }; + /** + * @private + */ + SVGElement.prototype.htmlGetBBox = function () { + return { height: 0, width: 0, x: 0, y: 0 }; + }; + /** + * Initialize the SVG element. This function only exists to make the + * initialization process overridable. It should not be called directly. + * + * @function Highcharts.SVGElement#init + * + * @param {Highcharts.SVGRenderer} renderer + * The SVGRenderer instance to initialize to. + * + * @param {string} nodeName + * The SVG node name. + */ + SVGElement.prototype.init = function (renderer, nodeName) { + /** + * The primary DOM node. Each `SVGElement` instance wraps a main DOM + * node, but may also represent more nodes. + * + * @name Highcharts.SVGElement#element + * @type {Highcharts.SVGDOMElement|Highcharts.HTMLDOMElement} + */ + this.element = nodeName === 'span' ? + createElement(nodeName) : + doc.createElementNS(this.SVG_NS, nodeName); + /** + * The renderer that the SVGElement belongs to. + * + * @name Highcharts.SVGElement#renderer + * @type {Highcharts.SVGRenderer} + */ + this.renderer = renderer; + fireEvent(this, 'afterInit'); + }; + /** + * Invert a group, rotate and flip. This is used internally on inverted + * charts, where the points and graphs are drawn as if not inverted, then + * the series group elements are inverted. + * + * @function Highcharts.SVGElement#invert + * + * @param {boolean} inverted + * Whether to invert or not. An inverted shape can be un-inverted by + * setting it to false. + * + * @return {Highcharts.SVGElement} + * Return the SVGElement for chaining. + */ + SVGElement.prototype.invert = function (inverted) { + var wrapper = this; + wrapper.inverted = inverted; + wrapper.updateTransform(); + return wrapper; + }; + /** + * Add an event listener. This is a simple setter that replaces all other + * events of the same type, opposed to the {@link Highcharts#addEvent} + * function. + * + * @sample highcharts/members/element-on/ + * A clickable rectangle + * + * @function Highcharts.SVGElement#on + * + * @param {string} eventType + * The event type. If the type is `click`, Highcharts will internally + * translate it to a `touchstart` event on touch devices, to prevent the + * browser from waiting for a click event from firing. + * + * @param {Function} handler + * The handler callback. + * + * @return {Highcharts.SVGElement} + * The SVGElement for chaining. + */ + SVGElement.prototype.on = function (eventType, handler) { + var svgElement = this, element = svgElement.element, touchStartPos, touchEventFired; + // touch + if (hasTouch && eventType === 'click') { + element.ontouchstart = function (e) { + // save touch position for later calculation + touchStartPos = { + clientX: e.touches[0].clientX, + clientY: e.touches[0].clientY + }; + }; + // Instead of ontouchstart, event handlers should be called + // on touchend - similar to how current mouseup events are called + element.ontouchend = function (e) { + // hasMoved is a boolean variable containing logic if page + // was scrolled, so if touch position changed more than + // ~4px (value borrowed from general touch handler) + var hasMoved = touchStartPos.clientX ? Math.sqrt(Math.pow(touchStartPos.clientX - e.changedTouches[0].clientX, 2) + + Math.pow(touchStartPos.clientY - e.changedTouches[0].clientY, 2)) >= 4 : false; + if (!hasMoved) { // only call handlers if page was not scrolled + handler.call(element, e); + } + touchEventFired = true; + // prevent other events from being fired. #9682 + e.preventDefault(); + }; + element.onclick = function (e) { + // Do not call onclick handler if touch event was fired already. + if (!touchEventFired) { + handler.call(element, e); + } + }; + } + else { + // simplest possible event model for internal use + element['on' + eventType] = handler; + } + return this; + }; + /** + * @private + * @function Highcharts.SVGElement#opacitySetter + * @param {string} value + * @param {string} key + * @param {Highcharts.SVGDOMElement} element + */ + SVGElement.prototype.opacitySetter = function (value, key, element) { + this[key] = value; + element.setAttribute(key, value); + }; + /** + * Remove a class name from the element. + * + * @function Highcharts.SVGElement#removeClass + * + * @param {string|RegExp} className + * The class name to remove. + * + * @return {Highcharts.SVGElement} Returns the SVG element for chainability. + */ + SVGElement.prototype.removeClass = function (className) { + return this.attr('class', ('' + this.attr('class')).replace(isString(className) ? + new RegExp(" ?" + className + " ?") : // #12064 + className, '')); + }; + /** + * @private + * @param {Array} tspans + * Text spans. + */ + SVGElement.prototype.removeTextOutline = function (tspans) { + // Iterate from the end to + // support removing items inside the cycle (#6472). + var i = tspans.length, tspan; + while (i--) { + tspan = tspans[i]; + if (tspan.getAttribute('class') === 'highcharts-text-outline') { + // Remove then erase + erase(tspans, this.element.removeChild(tspan)); + } + } + }; + /** + * Removes an element from the DOM. + * + * @private + * @function Highcharts.SVGElement#safeRemoveChild + * + * @param {Highcharts.SVGDOMElement|Highcharts.HTMLDOMElement} element + * The DOM node to remove. + */ + SVGElement.prototype.safeRemoveChild = function (element) { + var parentNode = element.parentNode; + if (parentNode) { + parentNode.removeChild(element); + } + }; + /** + * Set the coordinates needed to draw a consistent radial gradient across + * a shape regardless of positioning inside the chart. Used on pie slices + * to make all the slices have the same radial reference point. + * + * @function Highcharts.SVGElement#setRadialReference + * + * @param {Array} coordinates + * The center reference. The format is `[centerX, centerY, diameter]` in + * pixels. + * + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.setRadialReference = function (coordinates) { + var existingGradient = (this.element.gradient && + this.renderer.gradients[this.element.gradient]); + this.element.radialReference = coordinates; + // On redrawing objects with an existing gradient, the gradient needs + // to be repositioned (#3801) + if (existingGradient && existingGradient.radAttr) { + existingGradient.animate(this.renderer.getRadialAttr(coordinates, existingGradient.radAttr)); + } + return this; + }; + /** + * @private + * @function Highcharts.SVGElement#setTextPath + * @param {Highcharts.SVGElement} path + * Path to follow. + * @param {Highcharts.DataLabelsTextPathOptionsObject} textPathOptions + * Options. + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.setTextPath = function (path, textPathOptions) { + var elem = this.element, attribsMap = { + textAnchor: 'text-anchor' + }, attrs, adder = false, textPathElement, textPathId, textPathWrapper = this.textPathWrapper, tspans, firstTime = !textPathWrapper; + // Defaults + textPathOptions = merge(true, { + enabled: true, + attributes: { + dy: -5, + startOffset: '50%', + textAnchor: 'middle' + } + }, textPathOptions); + attrs = textPathOptions.attributes; + if (path && textPathOptions && textPathOptions.enabled) { + // In case of fixed width for a text, string is rebuilt + // (e.g. ellipsis is applied), so we need to rebuild textPath too + if (textPathWrapper && + textPathWrapper.element.parentNode === null) { + // When buildText functionality was triggered again + // and deletes textPathWrapper parentNode + firstTime = true; + textPathWrapper = textPathWrapper.destroy(); + } + else if (textPathWrapper) { + // Case after drillup when spans were added into + // the DOM outside the textPathWrapper parentGroup + this.removeTextOutline.call(textPathWrapper.parentGroup, [].slice.call(elem.getElementsByTagName('tspan'))); + } + // label() has padding, text() doesn't + if (this.options && this.options.padding) { + attrs.dx = -this.options.padding; + } + if (!textPathWrapper) { + // Create , defer the DOM adder + this.textPathWrapper = textPathWrapper = + this.renderer.createElement('textPath'); + adder = true; + } + textPathElement = textPathWrapper.element; + // Set ID for the path + textPathId = path.element.getAttribute('id'); + if (!textPathId) { + path.element.setAttribute('id', textPathId = uniqueKey()); + } + // Change DOM structure, by placing tag in + if (firstTime) { + tspans = elem.getElementsByTagName('tspan'); + // Now move all 's to the node + while (tspans.length) { + // Remove "y" from tspans, as Firefox translates them + tspans[0].setAttribute('y', 0); + // Remove "x" from tspans + if (isNumber(attrs.dx)) { + tspans[0].setAttribute('x', -attrs.dx); + } + textPathElement.appendChild(tspans[0]); + } + } + // Add to the DOM + if (adder && + textPathWrapper) { + textPathWrapper.add({ + // label() is placed in a group, text() is standalone + element: this.text ? this.text.element : elem + }); + } + // Set basic options: + // Use `setAttributeNS` because Safari needs this.. + textPathElement.setAttributeNS('http://www.w3.org/1999/xlink', 'href', this.renderer.url + '#' + textPathId); + // Presentation attributes: + // dx/dy options must by set on (parent), + // the rest should be set on + if (defined(attrs.dy)) { + textPathElement.parentNode + .setAttribute('dy', attrs.dy); + delete attrs.dy; + } + if (defined(attrs.dx)) { + textPathElement.parentNode + .setAttribute('dx', attrs.dx); + delete attrs.dx; + } + // Additional attributes + objectEach(attrs, function (val, key) { + textPathElement.setAttribute(attribsMap[key] || key, val); + }); + // Remove translation, text that follows path does not need that + elem.removeAttribute('transform'); + // Remove shadows and text outlines + this.removeTextOutline.call(textPathWrapper, [].slice.call(elem.getElementsByTagName('tspan'))); + // Remove background and border for label(), see #10545 + // Alternatively, we can disable setting background rects in + // series.drawDataLabels() + if (this.text && !this.renderer.styledMode) { + this.attr({ + fill: 'none', + 'stroke-width': 0 + }); + } + // Disable some functions + this.updateTransform = noop; + this.applyTextOutline = noop; + } + else if (textPathWrapper) { + // Reset to prototype + delete this.updateTransform; + delete this.applyTextOutline; + // Restore DOM structure: + this.destroyTextPath(elem, path); + // Bring attributes back + this.updateTransform(); + // Set textOutline back for text() + if (this.options && this.options.rotation) { + this.applyTextOutline(this.options.style.textOutline); + } + } + return this; + }; + /** + * Add a shadow to the element. Must be called after the element is added to + * the DOM. In styled mode, this method is not used, instead use `defs` and + * filters. + * + * @example + * renderer.rect(10, 100, 100, 100) + * .attr({ fill: 'red' }) + * .shadow(true); + * + * @function Highcharts.SVGElement#shadow + * + * @param {boolean|Highcharts.ShadowOptionsObject} [shadowOptions] + * The shadow options. If `true`, the default options are applied. If + * `false`, the current shadow will be removed. + * + * @param {Highcharts.SVGElement} [group] + * The SVG group element where the shadows will be applied. The + * default is to add it to the same parent as the current element. + * Internally, this is ised for pie slices, where all the shadows are + * added to an element behind all the slices. + * + * @param {boolean} [cutOff] + * Used internally for column shadows. + * + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.shadow = function (shadowOptions, group, cutOff) { + var shadows = [], i, shadow, element = this.element, strokeWidth, shadowElementOpacity, update = false, oldShadowOptions = this.oldShadowOptions, + // compensate for inverted plot area + transform; + var defaultShadowOptions = { + color: '#000000', + offsetX: 1, + offsetY: 1, + opacity: 0.15, + width: 3 + }; + var options; + if (shadowOptions === true) { + options = defaultShadowOptions; + } + else if (typeof shadowOptions === 'object') { + options = extend(defaultShadowOptions, shadowOptions); + } + // Update shadow when options change (#12091). + if (options) { + // Go over each key to look for change + if (options && oldShadowOptions) { + objectEach(options, function (value, key) { + if (value !== oldShadowOptions[key]) { + update = true; + } + }); + } + if (update) { + this.destroyShadows(); + } + this.oldShadowOptions = options; + } + if (!options) { + this.destroyShadows(); + } + else if (!this.shadows) { + shadowElementOpacity = options.opacity / options.width; + transform = this.parentInverted ? + 'translate(-1,-1)' : + "translate(" + options.offsetX + ", " + options.offsetY + ")"; + for (i = 1; i <= options.width; i++) { + shadow = element.cloneNode(false); + strokeWidth = (options.width * 2) + 1 - (2 * i); + attr(shadow, { + stroke: (shadowOptions.color || + '#000000'), + 'stroke-opacity': shadowElementOpacity * i, + 'stroke-width': strokeWidth, + transform: transform, + fill: 'none' + }); + shadow.setAttribute('class', (shadow.getAttribute('class') || '') + ' highcharts-shadow'); + if (cutOff) { + attr(shadow, 'height', Math.max(attr(shadow, 'height') - strokeWidth, 0)); + shadow.cutHeight = strokeWidth; + } + if (group) { + group.element.appendChild(shadow); + } + else if (element.parentNode) { + element.parentNode.insertBefore(shadow, element); + } + shadows.push(shadow); + } + this.shadows = shadows; + } + return this; + }; + /** + * Show the element after it has been hidden. + * + * @function Highcharts.SVGElement#show + * + * @param {boolean} [inherit=false] + * Set the visibility attribute to `inherit` rather than `visible`. + * The difference is that an element with `visibility="visible"` + * will be visible even if the parent is hidden. + * + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.show = function (inherit) { + return this.attr({ visibility: inherit ? 'inherit' : 'visible' }); + }; + /** + * WebKit and Batik have problems with a stroke-width of zero, so in this + * case we remove the stroke attribute altogether. #1270, #1369, #3065, + * #3072. + * + * @private + * @function Highcharts.SVGElement#strokeSetter + * @param {number|string} value + * @param {string} key + * @param {Highcharts.SVGDOMElement} element + */ + SVGElement.prototype.strokeSetter = function (value, key, element) { + this[key] = value; + // Only apply the stroke attribute if the stroke width is defined and + // larger than 0 + if (this.stroke && this['stroke-width']) { + // Use prototype as instance may be overridden + SVGElement.prototype.fillSetter.call(this, this.stroke, 'stroke', element); + element.setAttribute('stroke-width', this['stroke-width']); + this.hasStroke = true; + } + else if (key === 'stroke-width' && value === 0 && this.hasStroke) { + element.removeAttribute('stroke'); + this.hasStroke = false; + } + else if (this.renderer.styledMode && this['stroke-width']) { + element.setAttribute('stroke-width', this['stroke-width']); + this.hasStroke = true; + } + }; + /** + * Get the computed stroke width in pixel values. This is used extensively + * when drawing shapes to ensure the shapes are rendered crisp and + * positioned correctly relative to each other. Using + * `shape-rendering: crispEdges` leaves us less control over positioning, + * for example when we want to stack columns next to each other, or position + * things pixel-perfectly within the plot box. + * + * The common pattern when placing a shape is: + * - Create the SVGElement and add it to the DOM. In styled mode, it will + * now receive a stroke width from the style sheet. In classic mode we + * will add the `stroke-width` attribute. + * - Read the computed `elem.strokeWidth()`. + * - Place it based on the stroke width. + * + * @function Highcharts.SVGElement#strokeWidth + * + * @return {number} + * The stroke width in pixels. Even if the given stroke widtch (in CSS or by + * attributes) is based on `em` or other units, the pixel size is returned. + */ + SVGElement.prototype.strokeWidth = function () { + // In non-styled mode, read the stroke width as set by .attr + if (!this.renderer.styledMode) { + return this['stroke-width'] || 0; + } + // In styled mode, read computed stroke width + var val = this.getStyle('stroke-width'), ret = 0, dummy; + // Read pixel values directly + if (val.indexOf('px') === val.length - 2) { + ret = pInt(val); + // Other values like em, pt etc need to be measured + } + else if (val !== '') { + dummy = doc.createElementNS(SVG_NS, 'rect'); + attr(dummy, { + width: val, + 'stroke-width': 0 + }); + this.element.parentNode.appendChild(dummy); + ret = dummy.getBBox().width; + dummy.parentNode.removeChild(dummy); + } + return ret; + }; + /** + * If one of the symbol size affecting parameters are changed, + * check all the others only once for each call to an element's + * .attr() method + * + * @private + * @function Highcharts.SVGElement#symbolAttr + * + * @param {Highcharts.SVGAttributes} hash + * The attributes to set. + */ + SVGElement.prototype.symbolAttr = function (hash) { + var wrapper = this; + [ + 'x', + 'y', + 'r', + 'start', + 'end', + 'width', + 'height', + 'innerR', + 'anchorX', + 'anchorY', + 'clockwise' + ].forEach(function (key) { + wrapper[key] = pick(hash[key], wrapper[key]); + }); + wrapper.attr({ + d: wrapper.renderer.symbols[wrapper.symbolName](wrapper.x, wrapper.y, wrapper.width, wrapper.height, wrapper) + }); + }; + /** + * @private + * @function Highcharts.SVGElement#textSetter + * @param {string} value + */ + SVGElement.prototype.textSetter = function (value) { + if (value !== this.textStr) { + // Delete size caches when the text changes + // delete this.bBox; // old code in series-label + delete this.textPxLength; + this.textStr = value; + if (this.added) { + this.renderer.buildText(this); + } + } + }; + /** + * @private + * @function Highcharts.SVGElement#titleSetter + * @param {string} value + */ + SVGElement.prototype.titleSetter = function (value) { + var titleNode = this.element.getElementsByTagName('title')[0]; + if (!titleNode) { + titleNode = doc.createElementNS(this.SVG_NS, 'title'); + this.element.appendChild(titleNode); + } + // Remove text content if it exists + if (titleNode.firstChild) { + titleNode.removeChild(titleNode.firstChild); + } + titleNode.appendChild(doc.createTextNode( + // #3276, #3895 + String(pick(value, '')) + .replace(/<[^>]*>/g, '') + .replace(/</g, '<') + .replace(/>/g, '>'))); + }; + /** + * Bring the element to the front. Alternatively, a new zIndex can be set. + * + * @sample highcharts/members/element-tofront/ + * Click an element to bring it to front + * + * @function Highcharts.SVGElement#toFront + * + * @return {Highcharts.SVGElement} + * Returns the SVGElement for chaining. + */ + SVGElement.prototype.toFront = function () { + var element = this.element; + element.parentNode.appendChild(element); + return this; + }; + /** + * Move an object and its children by x and y values. + * + * @function Highcharts.SVGElement#translate + * + * @param {number} x + * The x value. + * + * @param {number} y + * The y value. + * + * @return {Highcharts.SVGElement} + */ + SVGElement.prototype.translate = function (x, y) { + return this.attr({ + translateX: x, + translateY: y + }); + }; + /** + * Update the shadow elements with new attributes. + * + * @private + * @function Highcharts.SVGElement#updateShadows + * + * @param {string} key + * The attribute name. + * + * @param {number} value + * The value of the attribute. + * + * @param {Function} setter + * The setter function, inherited from the parent wrapper. + */ + SVGElement.prototype.updateShadows = function (key, value, setter) { + var shadows = this.shadows; + if (shadows) { + var i = shadows.length; + while (i--) { + setter.call(shadows[i], key === 'height' ? + Math.max(value - (shadows[i].cutHeight || 0), 0) : + key === 'd' ? this.d : value, key, shadows[i]); + } + } + }; + /** + * Update the transform attribute based on internal properties. Deals with + * the custom `translateX`, `translateY`, `rotation`, `scaleX` and `scaleY` + * attributes and updates the SVG `transform` attribute. + * + * @private + * @function Highcharts.SVGElement#updateTransform + */ + SVGElement.prototype.updateTransform = function () { + var wrapper = this, translateX = wrapper.translateX || 0, translateY = wrapper.translateY || 0, scaleX = wrapper.scaleX, scaleY = wrapper.scaleY, inverted = wrapper.inverted, rotation = wrapper.rotation, matrix = wrapper.matrix, element = wrapper.element, transform; + // Flipping affects translate as adjustment for flipping around the + // group's axis + if (inverted) { + translateX += wrapper.width; + translateY += wrapper.height; + } + // Apply translate. Nearly all transformed elements have translation, + // so instead of checking for translate = 0, do it always (#1767, + // #1846). + transform = ['translate(' + translateX + ',' + translateY + ')']; + // apply matrix + if (defined(matrix)) { + transform.push('matrix(' + matrix.join(',') + ')'); + } + // apply rotation + if (inverted) { + transform.push('rotate(90) scale(-1,1)'); + } + else if (rotation) { // text rotation + transform.push('rotate(' + rotation + ' ' + + pick(this.rotationOriginX, element.getAttribute('x'), 0) + + ' ' + + pick(this.rotationOriginY, element.getAttribute('y') || 0) + ')'); + } + // apply scale + if (defined(scaleX) || defined(scaleY)) { + transform.push('scale(' + pick(scaleX, 1) + ' ' + pick(scaleY, 1) + ')'); + } + if (transform.length) { + element.setAttribute('transform', transform.join(' ')); + } + }; + /** + * @private + * @function Highcharts.SVGElement#visibilitySetter + * + * @param {string} value + * + * @param {string} key + * + * @param {Highcharts.SVGDOMElement} element + * + * @return {void} + */ + SVGElement.prototype.visibilitySetter = function (value, key, element) { + // IE9-11 doesn't handle visibilty:inherit well, so we remove the + // attribute instead (#2881, #3909) + if (value === 'inherit') { + element.removeAttribute(key); + } + else if (this[key] !== value) { // #6747 + element.setAttribute(key, value); + } + this[key] = value; + }; + /** + * @private + * @function Highcharts.SVGElement#xGetter + * + * @param {string} key + * + * @return {number|string|null} + */ + SVGElement.prototype.xGetter = function (key) { + if (this.element.nodeName === 'circle') { + if (key === 'x') { + key = 'cx'; + } + else if (key === 'y') { + key = 'cy'; + } + } + return this._defaultGetter(key); + }; + /** + * @private + * @function Highcharts.SVGElement#zIndexSetter + * @param {number} [value] + * @param {string} [key] + * @return {boolean} + */ + SVGElement.prototype.zIndexSetter = function (value, key) { + var renderer = this.renderer, parentGroup = this.parentGroup, parentWrapper = parentGroup || renderer, parentNode = parentWrapper.element || renderer.box, childNodes, otherElement, otherZIndex, element = this.element, inserted = false, undefinedOtherZIndex, svgParent = parentNode === renderer.box, run = this.added, i; + if (defined(value)) { + // So we can read it for other elements in the group + element.setAttribute('data-z-index', value); + value = +value; + if (this[key] === value) { + // Only update when needed (#3865) + run = false; + } + } + else if (defined(this[key])) { + element.removeAttribute('data-z-index'); + } + this[key] = value; + // Insert according to this and other elements' zIndex. Before .add() is + // called, nothing is done. Then on add, or by later calls to + // zIndexSetter, the node is placed on the right place in the DOM. + if (run) { + value = this.zIndex; + if (value && parentGroup) { + parentGroup.handleZ = true; + } + childNodes = parentNode.childNodes; + for (i = childNodes.length - 1; i >= 0 && !inserted; i--) { + otherElement = childNodes[i]; + otherZIndex = otherElement.getAttribute('data-z-index'); + undefinedOtherZIndex = !defined(otherZIndex); + if (otherElement !== element) { + if ( + // Negative zIndex versus no zIndex: + // On all levels except the highest. If the parent is + // , then we don't want to put items before + // or + value < 0 && + undefinedOtherZIndex && + !svgParent && + !i) { + parentNode.insertBefore(element, childNodes[i]); + inserted = true; + } + else if ( + // Insert after the first element with a lower zIndex + pInt(otherZIndex) <= value || + // If negative zIndex, add this before first undefined + // zIndex element + (undefinedOtherZIndex && + (!defined(value) || value >= 0))) { + parentNode.insertBefore(element, childNodes[i + 1] || null // null for oldIE export + ); + inserted = true; + } + } + } + if (!inserted) { + parentNode.insertBefore(element, childNodes[svgParent ? 3 : 0] || null // null for oldIE + ); + inserted = true; + } + } + return inserted; + }; + return SVGElement; + }()); + // Some shared setters and getters + SVGElement.prototype['stroke-widthSetter'] = SVGElement.prototype.strokeSetter; + SVGElement.prototype.yGetter = SVGElement.prototype.xGetter; + SVGElement.prototype.matrixSetter = + SVGElement.prototype.rotationOriginXSetter = + SVGElement.prototype.rotationOriginYSetter = + SVGElement.prototype.rotationSetter = + SVGElement.prototype.scaleXSetter = + SVGElement.prototype.scaleYSetter = + SVGElement.prototype.translateXSetter = + SVGElement.prototype.translateYSetter = + SVGElement.prototype.verticalAlignSetter = function (value, key) { + this[key] = value; + this.doTransform = true; + }; + H.SVGElement = SVGElement; + + return H.SVGElement; + }); + _registerModule(_modules, 'parts/SvgRenderer.js', [_modules['parts/Color.js'], _modules['parts/Globals.js'], _modules['parts/SVGElement.js'], _modules['parts/Utilities.js']], function (Color, H, SVGElement, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var color = Color.parse; + var addEvent = U.addEvent, attr = U.attr, createElement = U.createElement, css = U.css, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, erase = U.erase, extend = U.extend, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, isString = U.isString, merge = U.merge, objectEach = U.objectEach, pick = U.pick, pInt = U.pInt, removeEvent = U.removeEvent, splat = U.splat, stop = U.stop, uniqueKey = U.uniqueKey; + /** + * The horizontal alignment of an element. + * + * @typedef {"center"|"left"|"right"} Highcharts.AlignValue + */ + /** + * Options to align the element relative to the chart or another box. + * + * @interface Highcharts.AlignObject + */ /** + * Horizontal alignment. Can be one of `left`, `center` and `right`. + * + * @name Highcharts.AlignObject#align + * @type {Highcharts.AlignValue|undefined} + * + * @default left + */ /** + * Vertical alignment. Can be one of `top`, `middle` and `bottom`. + * + * @name Highcharts.AlignObject#verticalAlign + * @type {Highcharts.VerticalAlignValue|undefined} + * + * @default top + */ /** + * Horizontal pixel offset from alignment. + * + * @name Highcharts.AlignObject#x + * @type {number|undefined} + * + * @default 0 + */ /** + * Vertical pixel offset from alignment. + * + * @name Highcharts.AlignObject#y + * @type {number|undefined} + * + * @default 0 + */ /** + * Use the `transform` attribute with translateX and translateY custom + * attributes to align this elements rather than `x` and `y` attributes. + * + * @name Highcharts.AlignObject#alignByTranslate + * @type {boolean|undefined} + * + * @default false + */ + /** + * Bounding box of an element. + * + * @interface Highcharts.BBoxObject + * @extends Highcharts.PositionObject + */ /** + * Height of the bounding box. + * + * @name Highcharts.BBoxObject#height + * @type {number} + */ /** + * Width of the bounding box. + * + * @name Highcharts.BBoxObject#width + * @type {number} + */ /** + * Horizontal position of the bounding box. + * + * @name Highcharts.BBoxObject#x + * @type {number} + */ /** + * Vertical position of the bounding box. + * + * @name Highcharts.BBoxObject#y + * @type {number} + */ + /** + * A clipping rectangle that can be applied to one or more {@link SVGElement} + * instances. It is instanciated with the {@link SVGRenderer#clipRect} function + * and applied with the {@link SVGElement#clip} function. + * + * @example + * var circle = renderer.circle(100, 100, 100) + * .attr({ fill: 'red' }) + * .add(); + * var clipRect = renderer.clipRect(100, 100, 100, 100); + * + * // Leave only the lower right quarter visible + * circle.clip(clipRect); + * + * @typedef {Highcharts.SVGElement} Highcharts.ClipRectElement + */ + /** + * The font metrics. + * + * @interface Highcharts.FontMetricsObject + */ /** + * The baseline relative to the top of the box. + * + * @name Highcharts.FontMetricsObject#b + * @type {number} + */ /** + * The font size. + * + * @name Highcharts.FontMetricsObject#f + * @type {number} + */ /** + * The line height. + * + * @name Highcharts.FontMetricsObject#h + * @type {number} + */ + /** + * An object containing `x` and `y` properties for the position of an element. + * + * @interface Highcharts.PositionObject + */ /** + * X position of the element. + * @name Highcharts.PositionObject#x + * @type {number} + */ /** + * Y position of the element. + * @name Highcharts.PositionObject#y + * @type {number} + */ + /** + * A rectangle. + * + * @interface Highcharts.RectangleObject + */ /** + * Height of the rectangle. + * @name Highcharts.RectangleObject#height + * @type {number} + */ /** + * Width of the rectangle. + * @name Highcharts.RectangleObject#width + * @type {number} + */ /** + * Horizontal position of the rectangle. + * @name Highcharts.RectangleObject#x + * @type {number} + */ /** + * Vertical position of the rectangle. + * @name Highcharts.RectangleObject#y + * @type {number} + */ + /** + * The shadow options. + * + * @interface Highcharts.ShadowOptionsObject + */ /** + * The shadow color. + * @name Highcharts.ShadowOptionsObject#color + * @type {Highcharts.ColorString|undefined} + * @default #000000 + */ /** + * The horizontal offset from the element. + * + * @name Highcharts.ShadowOptionsObject#offsetX + * @type {number|undefined} + * @default 1 + */ /** + * The vertical offset from the element. + * @name Highcharts.ShadowOptionsObject#offsetY + * @type {number|undefined} + * @default 1 + */ /** + * The shadow opacity. + * + * @name Highcharts.ShadowOptionsObject#opacity + * @type {number|undefined} + * @default 0.15 + */ /** + * The shadow width or distance from the element. + * @name Highcharts.ShadowOptionsObject#width + * @type {number|undefined} + * @default 3 + */ + /** + * @interface Highcharts.SizeObject + */ /** + * @name Highcharts.SizeObject#height + * @type {number} + */ /** + * @name Highcharts.SizeObject#width + * @type {number} + */ + /** + * An object of key-value pairs for SVG attributes. Attributes in Highcharts + * elements for the most parts correspond to SVG, but some are specific to + * Highcharts, like `zIndex`, `rotation`, `rotationOriginX`, + * `rotationOriginY`, `translateX`, `translateY`, `scaleX` and `scaleY`. SVG + * attributes containing a hyphen are _not_ camel-cased, they should be + * quoted to preserve the hyphen. + * + * @example + * { + * 'stroke': '#ff0000', // basic + * 'stroke-width': 2, // hyphenated + * 'rotation': 45 // custom + * 'd': ['M', 10, 10, 'L', 30, 30, 'z'] // path definition, note format + * } + * + * @interface Highcharts.SVGAttributes + */ /** + * @name Highcharts.SVGAttributes#[key:string] + * @type {*} + */ /** + * @name Highcharts.SVGAttributes#d + * @type {string|Highcharts.SVGPathArray|undefined} + */ /** + * @name Highcharts.SVGAttributes#fill + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined} + */ /** + * @name Highcharts.SVGAttributes#inverted + * @type {boolean|undefined} + */ /** + * @name Highcharts.SVGAttributes#matrix + * @type {Array|undefined} + */ /** + * @name Highcharts.SVGAttributes#rotation + * @type {number|undefined} + */ /** + * @name Highcharts.SVGAttributes#rotationOriginX + * @type {number|undefined} + */ /** + * @name Highcharts.SVGAttributes#rotationOriginY + * @type {number|undefined} + */ /** + * @name Highcharts.SVGAttributes#scaleX + * @type {number|undefined} + */ /** + * @name Highcharts.SVGAttributes#scaleY + * @type {number|undefined} + */ /** + * @name Highcharts.SVGAttributes#stroke + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined} + */ /** + * @name Highcharts.SVGAttributes#style + * @type {string|Highcharts.CSSObject|undefined} + */ /** + * @name Highcharts.SVGAttributes#translateX + * @type {number|undefined} + */ /** + * @name Highcharts.SVGAttributes#translateY + * @type {number|undefined} + */ /** + * @name Highcharts.SVGAttributes#zIndex + * @type {number|undefined} + */ + /** + * Serialized form of an SVG definition, including children. Some key + * property names are reserved: tagName, textContent, and children. + * + * @interface Highcharts.SVGDefinitionObject + */ /** + * @name Highcharts.SVGDefinitionObject#[key:string] + * @type {boolean|number|string|Array|undefined} + */ /** + * @name Highcharts.SVGDefinitionObject#children + * @type {Array|undefined} + */ /** + * @name Highcharts.SVGDefinitionObject#tagName + * @type {string|undefined} + */ /** + * @name Highcharts.SVGDefinitionObject#textContent + * @type {string|undefined} + */ + /** + * An SVG DOM element. The type is a reference to the regular SVGElement in the + * global scope. + * + * @typedef {globals.GlobalSVGElement} Highcharts.SVGDOMElement + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/SVGElement + */ + /** + * Array of path commands, that will go into the `d` attribute of an SVG + * element. + * + * @typedef {Array} Highcharts.SVGPathArray + */ + /** + * Possible path commands in a SVG path array. + * + * @typedef {string} Highcharts.SVGPathCommand + * @validvalue ["a","c","h","l","m","q","s","t","v","z","A","C","H","L","M","Q","S","T","V","Z"] + */ + /** + * An extendable collection of functions for defining symbol paths. Symbols are + * used internally for point markers, button and label borders and backgrounds, + * or custom shapes. Extendable by adding to {@link SVGRenderer#symbols}. + * + * @interface Highcharts.SymbolDictionary + */ /** + * @name Highcharts.SymbolDictionary#[key:string] + * @type {Function|undefined} + */ /** + * @name Highcharts.SymbolDictionary#arc + * @type {Function|undefined} + */ /** + * @name Highcharts.SymbolDictionary#callout + * @type {Function|undefined} + */ /** + * @name Highcharts.SymbolDictionary#circle + * @type {Function|undefined} + */ /** + * @name Highcharts.SymbolDictionary#diamond + * @type {Function|undefined} + */ /** + * @name Highcharts.SymbolDictionary#square + * @type {Function|undefined} + */ /** + * @name Highcharts.SymbolDictionary#triangle + * @type {Function|undefined} + */ + /** + * Can be one of `arc`, `callout`, `circle`, `diamond`, `square`, `triangle`, + * and `triangle-down`. Symbols are used internally for point markers, button + * and label borders and backgrounds, or custom shapes. Extendable by adding to + * {@link SVGRenderer#symbols}. + * + * @typedef {"arc"|"callout"|"circle"|"diamond"|"square"|"triangle"|"triangle-down"} Highcharts.SymbolKeyValue + */ + /** + * Additional options, depending on the actual symbol drawn. + * + * @interface Highcharts.SymbolOptionsObject + */ /** + * The anchor X position for the `callout` symbol. This is where the chevron + * points to. + * + * @name Highcharts.SymbolOptionsObject#anchorX + * @type {number|undefined} + */ /** + * The anchor Y position for the `callout` symbol. This is where the chevron + * points to. + * + * @name Highcharts.SymbolOptionsObject#anchorY + * @type {number|undefined} + */ /** + * The end angle of an `arc` symbol. + * + * @name Highcharts.SymbolOptionsObject#end + * @type {number|undefined} + */ /** + * Whether to draw `arc` symbol open or closed. + * + * @name Highcharts.SymbolOptionsObject#open + * @type {boolean|undefined} + */ /** + * The radius of an `arc` symbol, or the border radius for the `callout` symbol. + * + * @name Highcharts.SymbolOptionsObject#r + * @type {number|undefined} + */ /** + * The start angle of an `arc` symbol. + * + * @name Highcharts.SymbolOptionsObject#start + * @type {number|undefined} + */ + /** + * The vertical alignment of an element. + * + * @typedef {"bottom"|"middle"|"top"} Highcharts.VerticalAlignValue + */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + var SVGRenderer, charts = H.charts, deg2rad = H.deg2rad, doc = H.doc, hasTouch = H.hasTouch, isFirefox = H.isFirefox, isMS = H.isMS, isWebKit = H.isWebKit, noop = H.noop, svg = H.svg, SVG_NS = H.SVG_NS, symbolSizes = H.symbolSizes, win = H.win; + /** + * Allows direct access to the Highcharts rendering layer in order to draw + * primitive shapes like circles, rectangles, paths or text directly on a chart, + * or independent from any chart. The SVGRenderer represents a wrapper object + * for SVG in modern browsers. Through the VMLRenderer, part of the `oldie.js` + * module, it also brings vector graphics to IE <= 8. + * + * An existing chart's renderer can be accessed through {@link Chart.renderer}. + * The renderer can also be used completely decoupled from a chart. + * + * @sample highcharts/members/renderer-on-chart + * Annotating a chart programmatically. + * @sample highcharts/members/renderer-basic + * Independent SVG drawing. + * + * @example + * // Use directly without a chart object. + * var renderer = new Highcharts.Renderer(parentNode, 600, 400); + * + * @class + * @name Highcharts.SVGRenderer + * + * @param {Highcharts.HTMLDOMElement} container + * Where to put the SVG in the web page. + * + * @param {number} width + * The width of the SVG. + * + * @param {number} height + * The height of the SVG. + * + * @param {Highcharts.CSSObject} [style] + * The box style, if not in styleMode + * + * @param {boolean} [forExport=false] + * Whether the rendered content is intended for export. + * + * @param {boolean} [allowHTML=true] + * Whether the renderer is allowed to include HTML text, which will be + * projected on top of the SVG. + * + * @param {boolean} [styledMode=false] + * Whether the renderer belongs to a chart that is in styled mode. + * If it does, it will avoid setting presentational attributes in + * some cases, but not when set explicitly through `.attr` and `.css` + * etc. + */ + SVGRenderer = H.SVGRenderer = function () { + this.init.apply(this, arguments); + }; + extend(SVGRenderer.prototype, /** @lends Highcharts.SVGRenderer.prototype */ { + /** + * A pointer to the renderer's associated Element class. The VMLRenderer + * will have a pointer to VMLElement here. + * + * @name Highcharts.SVGRenderer#Element + * @type {Highcharts.SVGElement} + */ + Element: SVGElement, + SVG_NS: SVG_NS, + /** + * Initialize the SVGRenderer. Overridable initializer function that takes + * the same parameters as the constructor. + * + * @function Highcharts.SVGRenderer#init + * + * @param {Highcharts.HTMLDOMElement} container + * Where to put the SVG in the web page. + * + * @param {number} width + * The width of the SVG. + * + * @param {number} height + * The height of the SVG. + * + * @param {Highcharts.CSSObject} [style] + * The box style, if not in styleMode + * + * @param {boolean} [forExport=false] + * Whether the rendered content is intended for export. + * + * @param {boolean} [allowHTML=true] + * Whether the renderer is allowed to include HTML text, which will + * be projected on top of the SVG. + * + * @param {boolean} [styledMode=false] + * Whether the renderer belongs to a chart that is in styled mode. + * If it does, it will avoid setting presentational attributes in + * some cases, but not when set explicitly through `.attr` and `.css` + * etc. + * + * @return {void} + */ + init: function (container, width, height, style, forExport, allowHTML, styledMode) { + var renderer = this, boxWrapper, element, desc; + boxWrapper = renderer.createElement('svg') + .attr({ + version: '1.1', + 'class': 'highcharts-root' + }); + if (!styledMode) { + boxWrapper.css(this.getStyle(style)); + } + element = boxWrapper.element; + container.appendChild(element); + // Always use ltr on the container, otherwise text-anchor will be + // flipped and text appear outside labels, buttons, tooltip etc (#3482) + attr(container, 'dir', 'ltr'); + // For browsers other than IE, add the namespace attribute (#1978) + if (container.innerHTML.indexOf('xmlns') === -1) { + attr(element, 'xmlns', this.SVG_NS); + } + // object properties + renderer.isSVG = true; + /** + * The root `svg` node of the renderer. + * + * @name Highcharts.SVGRenderer#box + * @type {Highcharts.SVGDOMElement} + */ + this.box = element; + /** + * The wrapper for the root `svg` node of the renderer. + * + * @name Highcharts.SVGRenderer#boxWrapper + * @type {Highcharts.SVGElement} + */ + this.boxWrapper = boxWrapper; + renderer.alignedObjects = []; + /** + * Page url used for internal references. + * + * @private + * @name Highcharts.SVGRenderer#url + * @type {string} + */ + // #24, #672, #1070 + this.url = ((isFirefox || isWebKit) && + doc.getElementsByTagName('base').length) ? + win.location.href + .split('#')[0] // remove the hash + .replace(/<[^>]*>/g, '') // wing cut HTML + // escape parantheses and quotes + .replace(/([\('\)])/g, '\\$1') + // replace spaces (needed for Safari only) + .replace(/ /g, '%20') : + ''; + // Add description + desc = this.createElement('desc').add(); + desc.element.appendChild(doc.createTextNode('Created with Highcharts 8.1.0')); + /** + * A pointer to the `defs` node of the root SVG. + * + * @name Highcharts.SVGRenderer#defs + * @type {Highcharts.SVGElement} + */ + renderer.defs = this.createElement('defs').add(); + renderer.allowHTML = allowHTML; + renderer.forExport = forExport; + renderer.styledMode = styledMode; + renderer.gradients = {}; // Object where gradient SvgElements are stored + renderer.cache = {}; // Cache for numerical bounding boxes + renderer.cacheKeys = []; + renderer.imgCount = 0; + renderer.setSize(width, height, false); + // Issue 110 workaround: + // In Firefox, if a div is positioned by percentage, its pixel position + // may land between pixels. The container itself doesn't display this, + // but an SVG element inside this container will be drawn at subpixel + // precision. In order to draw sharp lines, this must be compensated + // for. This doesn't seem to work inside iframes though (like in + // jsFiddle). + var subPixelFix, rect; + if (isFirefox && container.getBoundingClientRect) { + subPixelFix = function () { + css(container, { left: 0, top: 0 }); + rect = container.getBoundingClientRect(); + css(container, { + left: (Math.ceil(rect.left) - rect.left) + 'px', + top: (Math.ceil(rect.top) - rect.top) + 'px' + }); + }; + // run the fix now + subPixelFix(); + // run it on resize + renderer.unSubPixelFix = addEvent(win, 'resize', subPixelFix); + } + }, + /** + * General method for adding a definition to the SVG `defs` tag. Can be used + * for gradients, fills, filters etc. Styled mode only. A hook for adding + * general definitions to the SVG's defs tag. Definitions can be referenced + * from the CSS by its `id`. Read more in + * [gradients, shadows and patterns](https://www.highcharts.com/docs/chart-design-and-style/gradients-shadows-and-patterns). + * Styled mode only. + * + * @function Highcharts.SVGRenderer#definition + * + * @param {Highcharts.SVGDefinitionObject} def + * A serialized form of an SVG definition, including children. + * + * @return {Highcharts.SVGElement} + * The inserted node. + */ + definition: function (def) { + var ren = this; + /** + * @private + * @param {Highcharts.SVGDefinitionObject} config - SVG definition + * @param {Highcharts.SVGElement} [parent] - parent node + */ + function recurse(config, parent) { + var ret; + splat(config).forEach(function (item) { + var node = ren.createElement(item.tagName), attr = {}; + // Set attributes + objectEach(item, function (val, key) { + if (key !== 'tagName' && + key !== 'children' && + key !== 'textContent') { + attr[key] = val; + } + }); + node.attr(attr); + // Add to the tree + node.add(parent || ren.defs); + // Add text content + if (item.textContent) { + node.element.appendChild(doc.createTextNode(item.textContent)); + } + // Recurse + recurse(item.children || [], node); + ret = node; + }); + // Return last node added (on top level it's the only one) + return ret; + } + return recurse(def); + }, + /** + * Get the global style setting for the renderer. + * + * @private + * @function Highcharts.SVGRenderer#getStyle + * + * @param {Highcharts.CSSObject} style + * Style settings. + * + * @return {Highcharts.CSSObject} + * The style settings mixed with defaults. + */ + getStyle: function (style) { + this.style = extend({ + fontFamily: '"Lucida Grande", "Lucida Sans Unicode", ' + + 'Arial, Helvetica, sans-serif', + fontSize: '12px' + }, style); + return this.style; + }, + /** + * Apply the global style on the renderer, mixed with the default styles. + * + * @function Highcharts.SVGRenderer#setStyle + * + * @param {Highcharts.CSSObject} style + * CSS to apply. + */ + setStyle: function (style) { + this.boxWrapper.css(this.getStyle(style)); + }, + /** + * Detect whether the renderer is hidden. This happens when one of the + * parent elements has `display: none`. Used internally to detect when we + * needto render preliminarily in another div to get the text bounding boxes + * right. + * + * @function Highcharts.SVGRenderer#isHidden + * + * @return {boolean} + * True if it is hidden. + */ + isHidden: function () { + return !this.boxWrapper.getBBox().width; + }, + /** + * Destroys the renderer and its allocated members. + * + * @function Highcharts.SVGRenderer#destroy + * + * @return {null} + */ + destroy: function () { + var renderer = this, rendererDefs = renderer.defs; + renderer.box = null; + renderer.boxWrapper = renderer.boxWrapper.destroy(); + // Call destroy on all gradient elements + destroyObjectProperties(renderer.gradients || {}); + renderer.gradients = null; + // Defs are null in VMLRenderer + // Otherwise, destroy them here. + if (rendererDefs) { + renderer.defs = rendererDefs.destroy(); + } + // Remove sub pixel fix handler (#982) + if (renderer.unSubPixelFix) { + renderer.unSubPixelFix(); + } + renderer.alignedObjects = null; + return null; + }, + /** + * Create a wrapper for an SVG element. Serves as a factory for + * {@link SVGElement}, but this function is itself mostly called from + * primitive factories like {@link SVGRenderer#path}, {@link + * SVGRenderer#rect} or {@link SVGRenderer#text}. + * + * @function Highcharts.SVGRenderer#createElement + * + * @param {string} nodeName + * The node name, for example `rect`, `g` etc. + * + * @return {Highcharts.SVGElement} + * The generated SVGElement. + */ + createElement: function (nodeName) { + var wrapper = new this.Element(); + wrapper.init(this, nodeName); + return wrapper; + }, + /** + * Dummy function for plugins, called every time the renderer is updated. + * Prior to Highcharts 5, this was used for the canvg renderer. + * + * @deprecated + * @function Highcharts.SVGRenderer#draw + */ + draw: noop, + /** + * Get converted radial gradient attributes according to the radial + * reference. Used internally from the {@link SVGElement#colorGradient} + * function. + * + * @private + * @function Highcharts.SVGRenderer#getRadialAttr + * + * @param {Array} radialReference + * + * @param {Highcharts.SVGAttributes} gradAttr + * + * @return {Highcharts.SVGAttributes} + */ + getRadialAttr: function (radialReference, gradAttr) { + return { + cx: (radialReference[0] - radialReference[2] / 2) + + gradAttr.cx * radialReference[2], + cy: (radialReference[1] - radialReference[2] / 2) + + gradAttr.cy * radialReference[2], + r: gradAttr.r * radialReference[2] + }; + }, + /** + * Truncate the text node contents to a given length. Used when the css + * width is set. If the `textOverflow` is `ellipsis`, the text is truncated + * character by character to the given length. If not, the text is + * word-wrapped line by line. + * + * @private + * @function Highcharts.SVGRenderer#truncate + * + * @param {Highcharts.SVGElement} wrapper + * + * @param {Highcharts.HTMLDOMElement} tspan + * + * @param {string|undefined} text + * + * @param {Array|undefined} words + * + * @param {number} startAt + * + * @param {number} width + * + * @param {Function} getString + * + * @return {boolean} + * True if tspan is too long. + */ + truncate: function (wrapper, tspan, text, words, startAt, width, getString) { + var renderer = this, rotation = wrapper.rotation, str, + // Word wrap can not be truncated to shorter than one word, ellipsis + // text can be completely blank. + minIndex = words ? 1 : 0, maxIndex = (text || words).length, currentIndex = maxIndex, + // Cache the lengths to avoid checking the same twice + lengths = [], updateTSpan = function (s) { + if (tspan.firstChild) { + tspan.removeChild(tspan.firstChild); + } + if (s) { + tspan.appendChild(doc.createTextNode(s)); + } + }, getSubStringLength = function (charEnd, concatenatedEnd) { + // charEnd is useed when finding the character-by-character + // break for ellipsis, concatenatedEnd is used for word-by-word + // break for word wrapping. + var end = concatenatedEnd || charEnd; + if (typeof lengths[end] === 'undefined') { + // Modern browsers + if (tspan.getSubStringLength) { + // Fails with DOM exception on unit-tests/legend/members + // of unknown reason. Desired width is 0, text content + // is "5" and end is 1. + try { + lengths[end] = startAt + + tspan.getSubStringLength(0, words ? end + 1 : end); + } + catch (e) { + ''; + } + // Legacy + } + else if (renderer.getSpanWidth) { // #9058 jsdom + updateTSpan(getString(text || words, charEnd)); + lengths[end] = startAt + + renderer.getSpanWidth(wrapper, tspan); + } + } + return lengths[end]; + }, actualWidth, truncated; + wrapper.rotation = 0; // discard rotation when computing box + actualWidth = getSubStringLength(tspan.textContent.length); + truncated = startAt + actualWidth > width; + if (truncated) { + // Do a binary search for the index where to truncate the text + while (minIndex <= maxIndex) { + currentIndex = Math.ceil((minIndex + maxIndex) / 2); + // When checking words for word-wrap, we need to build the + // string and measure the subStringLength at the concatenated + // word length. + if (words) { + str = getString(words, currentIndex); + } + actualWidth = getSubStringLength(currentIndex, str && str.length - 1); + if (minIndex === maxIndex) { + // Complete + minIndex = maxIndex + 1; + } + else if (actualWidth > width) { + // Too large. Set max index to current. + maxIndex = currentIndex - 1; + } + else { + // Within width. Set min index to current. + minIndex = currentIndex; + } + } + // If max index was 0 it means the shortest possible text was also + // too large. For ellipsis that means only the ellipsis, while for + // word wrap it means the whole first word. + if (maxIndex === 0) { + // Remove ellipsis + updateTSpan(''); + // If the new text length is one less than the original, we don't + // need the ellipsis + } + else if (!(text && maxIndex === text.length - 1)) { + updateTSpan(str || getString(text || words, currentIndex)); + } + } + // When doing line wrapping, prepare for the next line by removing the + // items from this line. + if (words) { + words.splice(0, currentIndex); + } + wrapper.actualWidth = actualWidth; + wrapper.rotation = rotation; // Apply rotation again. + return truncated; + }, + /** + * A collection of characters mapped to HTML entities. When `useHTML` on an + * element is true, these entities will be rendered correctly by HTML. In + * the SVG pseudo-HTML, they need to be unescaped back to simple characters, + * so for example `<` will render as `<`. + * + * @example + * // Add support for unescaping quotes + * Highcharts.SVGRenderer.prototype.escapes['"'] = '"'; + * + * @name Highcharts.SVGRenderer#escapes + * @type {Highcharts.Dictionary} + */ + escapes: { + '&': '&', + '<': '<', + '>': '>', + "'": ''', + '"': '"' + }, + /** + * Parse a simple HTML string into SVG tspans. Called internally when text + * is set on an SVGElement. The function supports a subset of HTML tags, CSS + * text features like `width`, `text-overflow`, `white-space`, and also + * attributes like `href` and `style`. + * + * @private + * @function Highcharts.SVGRenderer#buildText + * + * @param {Highcharts.SVGElement} wrapper + * The parent SVGElement. + * + * @return {void} + */ + buildText: function (wrapper) { + var textNode = wrapper.element, renderer = this, forExport = renderer.forExport, textStr = pick(wrapper.textStr, '').toString(), hasMarkup = textStr.indexOf('<') !== -1, lines, childNodes = textNode.childNodes, truncated, parentX = attr(textNode, 'x'), textStyles = wrapper.styles, width = wrapper.textWidth, textLineHeight = textStyles && textStyles.lineHeight, textOutline = textStyles && textStyles.textOutline, ellipsis = textStyles && textStyles.textOverflow === 'ellipsis', noWrap = textStyles && textStyles.whiteSpace === 'nowrap', fontSize = textStyles && textStyles.fontSize, textCache, isSubsequentLine, i = childNodes.length, tempParent = width && !wrapper.added && this.box, getLineHeight = function (tspan) { + var fontSizeStyle; + if (!renderer.styledMode) { + fontSizeStyle = + /(px|em)$/.test(tspan && tspan.style.fontSize) ? + tspan.style.fontSize : + (fontSize || renderer.style.fontSize || 12); + } + return textLineHeight ? + pInt(textLineHeight) : + renderer.fontMetrics(fontSizeStyle, + // Get the computed size from parent if not explicit + (tspan.getAttribute('style') ? tspan : textNode)).h; + }, unescapeEntities = function (inputStr, except) { + objectEach(renderer.escapes, function (value, key) { + if (!except || except.indexOf(value) === -1) { + inputStr = inputStr.toString().replace(new RegExp(value, 'g'), key); + } + }); + return inputStr; + }, parseAttribute = function (s, attr) { + var start, delimiter; + start = s.indexOf('<'); + s = s.substring(start, s.indexOf('>') - start); + start = s.indexOf(attr + '='); + if (start !== -1) { + start = start + attr.length + 1; + delimiter = s.charAt(start); + if (delimiter === '"' || delimiter === "'") { // eslint-disable-line quotes + s = s.substring(start + 1); + return s.substring(0, s.indexOf(delimiter)); + } + } + }; + var regexMatchBreaks = //g; + // The buildText code is quite heavy, so if we're not changing something + // that affects the text, skip it (#6113). + textCache = [ + textStr, + ellipsis, + noWrap, + textLineHeight, + textOutline, + fontSize, + width + ].join(','); + if (textCache === wrapper.textCache) { + return; + } + wrapper.textCache = textCache; + // Remove old text + while (i--) { + textNode.removeChild(childNodes[i]); + } + // Skip tspans, add text directly to text node. The forceTSpan is a hook + // used in text outline hack. + if (!hasMarkup && + !textOutline && + !ellipsis && + !width && + (textStr.indexOf(' ') === -1 || + (noWrap && !regexMatchBreaks.test(textStr)))) { + textNode.appendChild(doc.createTextNode(unescapeEntities(textStr))); + // Complex strings, add more logic + } + else { + if (tempParent) { + // attach it to the DOM to read offset width + tempParent.appendChild(textNode); + } + if (hasMarkup) { + lines = renderer.styledMode ? (textStr + .replace(/<(b|strong)>/g, '') + .replace(/<(i|em)>/g, '')) : (textStr + .replace(/<(b|strong)>/g, '') + .replace(/<(i|em)>/g, '')); + lines = lines + .replace(//g, '') + .split(regexMatchBreaks); + } + else { + lines = [textStr]; + } + // Trim empty lines (#5261) + lines = lines.filter(function (line) { + return line !== ''; + }); + // build the lines + lines.forEach(function (line, lineNo) { + var spans, spanNo = 0, lineLength = 0; + line = line + // Trim to prevent useless/costly process on the spaces + // (#5258) + .replace(/^\s+|\s+$/g, '') + .replace(//g, '|||'); + spans = line.split('|||'); + spans.forEach(function buildTextSpans(span) { + if (span !== '' || spans.length === 1) { + var attributes = {}, tspan = doc.createElementNS(renderer.SVG_NS, 'tspan'), classAttribute, styleAttribute, // #390 + hrefAttribute; + classAttribute = parseAttribute(span, 'class'); + if (classAttribute) { + attr(tspan, 'class', classAttribute); + } + styleAttribute = parseAttribute(span, 'style'); + if (styleAttribute) { + styleAttribute = styleAttribute.replace(/(;| |^)color([ :])/, '$1fill$2'); + attr(tspan, 'style', styleAttribute); + } + // Not for export - #1529 + hrefAttribute = parseAttribute(span, 'href'); + if (hrefAttribute && !forExport) { + attr(tspan, 'onclick', 'location.href=\"' + hrefAttribute + '\"'); + attr(tspan, 'class', 'highcharts-anchor'); + if (!renderer.styledMode) { + css(tspan, { cursor: 'pointer' }); + } + } + // Strip away unsupported HTML tags (#7126) + span = unescapeEntities(span.replace(/<[a-zA-Z\/](.|\n)*?>/g, '') || ' '); + // Nested tags aren't supported, and cause crash in + // Safari (#1596) + if (span !== ' ') { + // add the text node + tspan.appendChild(doc.createTextNode(span)); + // First span in a line, align it to the left + if (!spanNo) { + if (lineNo && parentX !== null) { + attributes.x = parentX; + } + } + else { + attributes.dx = 0; // #16 + } + // add attributes + attr(tspan, attributes); + // Append it + textNode.appendChild(tspan); + // first span on subsequent line, add the line + // height + if (!spanNo && isSubsequentLine) { + // allow getting the right offset height in + // exporting in IE + if (!svg && forExport) { + css(tspan, { display: 'block' }); + } + // Set the line height based on the font size of + // either the text element or the tspan element + attr(tspan, 'dy', getLineHeight(tspan)); + } + // Check width and apply soft breaks or ellipsis + if (width) { + var words = span.replace(/([^\^])-/g, '$1- ').split(' '), // #1273 + hasWhiteSpace = !noWrap && (spans.length > 1 || + lineNo || + words.length > 1), wrapLineNo = 0, dy = getLineHeight(tspan); + if (ellipsis) { + truncated = renderer.truncate(wrapper, tspan, span, void 0, 0, + // Target width + Math.max(0, + // Substract the font face to make + // room for the ellipsis itself + width - parseInt(fontSize || 12, 10)), + // Build the text to test for + function (text, currentIndex) { + return text.substring(0, currentIndex) + '\u2026'; + }); + } + else if (hasWhiteSpace) { + while (words.length) { + // For subsequent lines, create tspans + // with the same style attributes as the + // parent text node. + if (words.length && + !noWrap && + wrapLineNo > 0) { + tspan = doc.createElementNS(SVG_NS, 'tspan'); + attr(tspan, { + dy: dy, + x: parentX + }); + if (styleAttribute) { // #390 + attr(tspan, 'style', styleAttribute); + } + // Start by appending the full + // remaining text + tspan.appendChild(doc.createTextNode(words.join(' ') + .replace(/- /g, '-'))); + textNode.appendChild(tspan); + } + // For each line, truncate the remaining + // words into the line length. + renderer.truncate(wrapper, tspan, null, words, wrapLineNo === 0 ? lineLength : 0, width, + // Build the text to test for + function (text, currentIndex) { + return words + .slice(0, currentIndex) + .join(' ') + .replace(/- /g, '-'); + }); + lineLength = wrapper.actualWidth; + wrapLineNo++; + } + } + } + spanNo++; + } + } + }); + // To avoid beginning lines that doesn't add to the textNode + // (#6144) + isSubsequentLine = (isSubsequentLine || + textNode.childNodes.length); + }); + if (ellipsis && truncated) { + wrapper.attr('title', unescapeEntities(wrapper.textStr, ['<', '>']) // #7179 + ); + } + if (tempParent) { + tempParent.removeChild(textNode); + } + // Apply the text outline + if (textOutline && wrapper.applyTextOutline) { + wrapper.applyTextOutline(textOutline); + } + } + }, + /** + * Returns white for dark colors and black for bright colors. + * + * @function Highcharts.SVGRenderer#getContrast + * + * @param {Highcharts.ColorString} rgba + * The color to get the contrast for. + * + * @return {Highcharts.ColorString} + * The contrast color, either `#000000` or `#FFFFFF`. + */ + getContrast: function (rgba) { + rgba = color(rgba).rgba; + // The threshold may be discussed. Here's a proposal for adding + // different weight to the color channels (#6216) + rgba[0] *= 1; // red + rgba[1] *= 1.2; // green + rgba[2] *= 0.5; // blue + return rgba[0] + rgba[1] + rgba[2] > + 1.8 * 255 ? + '#000000' : + '#FFFFFF'; + }, + /** + * Create a button with preset states. + * + * @function Highcharts.SVGRenderer#button + * + * @param {string} text + * The text or HTML to draw. + * + * @param {number} x + * The x position of the button's left side. + * + * @param {number} y + * The y position of the button's top side. + * + * @param {Highcharts.EventCallbackFunction} callback + * The function to execute on button click or touch. + * + * @param {Highcharts.SVGAttributes} [normalState] + * SVG attributes for the normal state. + * + * @param {Highcharts.SVGAttributes} [hoverState] + * SVG attributes for the hover state. + * + * @param {Highcharts.SVGAttributes} [pressedState] + * SVG attributes for the pressed state. + * + * @param {Highcharts.SVGAttributes} [disabledState] + * SVG attributes for the disabled state. + * + * @param {Highcharts.SymbolKeyValue} [shape=rect] + * The shape type. + * + * @param {boolean} [useHTML=false] + * Wether to use HTML to render the label. + * + * @return {Highcharts.SVGElement} + * The button element. + */ + button: function (text, x, y, callback, normalState, hoverState, pressedState, disabledState, shape, useHTML) { + var label = this.label(text, x, y, shape, void 0, void 0, useHTML, void 0, 'button'), curState = 0, styledMode = this.styledMode; + // Default, non-stylable attributes + label.attr(merge({ padding: 8, r: 2 }, normalState)); + if (!styledMode) { + // Presentational + var normalStyle, hoverStyle, pressedStyle, disabledStyle; + // Normal state - prepare the attributes + normalState = merge({ + fill: '#f7f7f7', + stroke: '#cccccc', + 'stroke-width': 1, + style: { + color: '#333333', + cursor: 'pointer', + fontWeight: 'normal' + } + }, normalState); + normalStyle = normalState.style; + delete normalState.style; + // Hover state + hoverState = merge(normalState, { + fill: '#e6e6e6' + }, hoverState); + hoverStyle = hoverState.style; + delete hoverState.style; + // Pressed state + pressedState = merge(normalState, { + fill: '#e6ebf5', + style: { + color: '#000000', + fontWeight: 'bold' + } + }, pressedState); + pressedStyle = pressedState.style; + delete pressedState.style; + // Disabled state + disabledState = merge(normalState, { + style: { + color: '#cccccc' + } + }, disabledState); + disabledStyle = disabledState.style; + delete disabledState.style; + } + // Add the events. IE9 and IE10 need mouseover and mouseout to funciton + // (#667). + addEvent(label.element, isMS ? 'mouseover' : 'mouseenter', function () { + if (curState !== 3) { + label.setState(1); + } + }); + addEvent(label.element, isMS ? 'mouseout' : 'mouseleave', function () { + if (curState !== 3) { + label.setState(curState); + } + }); + label.setState = function (state) { + // Hover state is temporary, don't record it + if (state !== 1) { + label.state = curState = state; + } + // Update visuals + label + .removeClass(/highcharts-button-(normal|hover|pressed|disabled)/) + .addClass('highcharts-button-' + + ['normal', 'hover', 'pressed', 'disabled'][state || 0]); + if (!styledMode) { + label + .attr([ + normalState, + hoverState, + pressedState, + disabledState + ][state || 0]) + .css([ + normalStyle, + hoverStyle, + pressedStyle, + disabledStyle + ][state || 0]); + } + }; + // Presentational attributes + if (!styledMode) { + label + .attr(normalState) + .css(extend({ cursor: 'default' }, normalStyle)); + } + return label + .on('click', function (e) { + if (curState !== 3) { + callback.call(label, e); + } + }); + }, + /** + * Make a straight line crisper by not spilling out to neighbour pixels. + * + * @function Highcharts.SVGRenderer#crispLine + * + * @param {Highcharts.SVGPathArray} points + * The original points on the format `[['M', 0, 0], ['L', 100, 0]]`. + * + * @param {number} width + * The width of the line. + * + * @param {string} roundingFunction + * The rounding function name on the `Math` object, can be one of + * `round`, `floor` or `ceil`. + * + * @return {Highcharts.SVGPathArray} + * The original points array, but modified to render crisply. + */ + crispLine: function (points, width, roundingFunction) { + if (roundingFunction === void 0) { roundingFunction = 'round'; } + var start = points[0]; + var end = points[1]; + // Normalize to a crisp line + if (start[1] === end[1]) { + // Substract due to #1129. Now bottom and left axis gridlines behave + // the same. + start[1] = end[1] = + Math[roundingFunction](start[1]) - (width % 2 / 2); + } + if (start[2] === end[2]) { + start[2] = end[2] = + Math[roundingFunction](start[2]) + (width % 2 / 2); + } + return points; + }, + /** + * Draw a path, wraps the SVG `path` element. + * + * @sample highcharts/members/renderer-path-on-chart/ + * Draw a path in a chart + * @sample highcharts/members/renderer-path/ + * Draw a path independent from a chart + * + * @example + * var path = renderer.path(['M', 10, 10, 'L', 30, 30, 'z']) + * .attr({ stroke: '#ff00ff' }) + * .add(); + * + * @function Highcharts.SVGRenderer#path + * + * @param {Highcharts.SVGPathArray} [path] + * An SVG path definition in array form. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + * + */ /** + * Draw a path, wraps the SVG `path` element. + * + * @function Highcharts.SVGRenderer#path + * + * @param {Highcharts.SVGAttributes} [attribs] + * The initial attributes. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ + path: function (path) { + var attribs = (this.styledMode ? {} : { + fill: 'none' + }); + if (isArray(path)) { + attribs.d = path; + } + else if (isObject(path)) { // attributes + extend(attribs, path); + } + return this.createElement('path').attr(attribs); + }, + /** + * Draw a circle, wraps the SVG `circle` element. + * + * @sample highcharts/members/renderer-circle/ + * Drawing a circle + * + * @function Highcharts.SVGRenderer#circle + * + * @param {number} [x] + * The center x position. + * + * @param {number} [y] + * The center y position. + * + * @param {number} [r] + * The radius. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ /** + * Draw a circle, wraps the SVG `circle` element. + * + * @function Highcharts.SVGRenderer#circle + * + * @param {Highcharts.SVGAttributes} [attribs] + * The initial attributes. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ + circle: function (x, y, r) { + var attribs = (isObject(x) ? + x : + typeof x === 'undefined' ? {} : { x: x, y: y, r: r }), wrapper = this.createElement('circle'); + // Setting x or y translates to cx and cy + wrapper.xSetter = wrapper.ySetter = function (value, key, element) { + element.setAttribute('c' + key, value); + }; + return wrapper.attr(attribs); + }, + /** + * Draw and return an arc. + * + * @sample highcharts/members/renderer-arc/ + * Drawing an arc + * + * @function Highcharts.SVGRenderer#arc + * + * @param {number} [x=0] + * Center X position. + * + * @param {number} [y=0] + * Center Y position. + * + * @param {number} [r=0] + * The outer radius' of the arc. + * + * @param {number} [innerR=0] + * Inner radius like used in donut charts. + * + * @param {number} [start=0] + * The starting angle of the arc in radians, where 0 is to the right + * and `-Math.PI/2` is up. + * + * @param {number} [end=0] + * The ending angle of the arc in radians, where 0 is to the right + * and `-Math.PI/2` is up. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ /** + * Draw and return an arc. Overloaded function that takes arguments object. + * + * @function Highcharts.SVGRenderer#arc + * + * @param {Highcharts.SVGAttributes} attribs + * Initial SVG attributes. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ + arc: function (x, y, r, innerR, start, end) { + var arc, options; + if (isObject(x)) { + options = x; + y = options.y; + r = options.r; + innerR = options.innerR; + start = options.start; + end = options.end; + x = options.x; + } + else { + options = { + innerR: innerR, + start: start, + end: end + }; + } + // Arcs are defined as symbols for the ability to set + // attributes in attr and animate + arc = this.symbol('arc', x, y, r, r, options); + arc.r = r; // #959 + return arc; + }, + /** + * Draw and return a rectangle. + * + * @function Highcharts.SVGRenderer#rect + * + * @param {number} [x] + * Left position. + * + * @param {number} [y] + * Top position. + * + * @param {number} [width] + * Width of the rectangle. + * + * @param {number} [height] + * Height of the rectangle. + * + * @param {number} [r] + * Border corner radius. + * + * @param {number} [strokeWidth] + * A stroke width can be supplied to allow crisp drawing. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ /** + * Draw and return a rectangle. + * + * @sample highcharts/members/renderer-rect-on-chart/ + * Draw a rectangle in a chart + * @sample highcharts/members/renderer-rect/ + * Draw a rectangle independent from a chart + * + * @function Highcharts.SVGRenderer#rect + * + * @param {Highcharts.SVGAttributes} [attributes] + * General SVG attributes for the rectangle. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ + rect: function (x, y, width, height, r, strokeWidth) { + r = isObject(x) ? x.r : r; + var wrapper = this.createElement('rect'), attribs = isObject(x) ? + x : + typeof x === 'undefined' ? + {} : + { + x: x, + y: y, + width: Math.max(width, 0), + height: Math.max(height, 0) + }; + if (!this.styledMode) { + if (typeof strokeWidth !== 'undefined') { + attribs.strokeWidth = strokeWidth; + attribs = wrapper.crisp(attribs); + } + attribs.fill = 'none'; + } + if (r) { + attribs.r = r; + } + wrapper.rSetter = function (value, key, element) { + wrapper.r = value; + attr(element, { + rx: value, + ry: value + }); + }; + wrapper.rGetter = function () { + return wrapper.r; + }; + return wrapper.attr(attribs); + }, + /** + * Resize the {@link SVGRenderer#box} and re-align all aligned child + * elements. + * + * @sample highcharts/members/renderer-g/ + * Show and hide grouped objects + * + * @function Highcharts.SVGRenderer#setSize + * + * @param {number} width + * The new pixel width. + * + * @param {number} height + * The new pixel height. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animate=true] + * Whether and how to animate. + * + * @return {void} + */ + setSize: function (width, height, animate) { + var renderer = this, alignedObjects = renderer.alignedObjects, i = alignedObjects.length; + renderer.width = width; + renderer.height = height; + renderer.boxWrapper.animate({ + width: width, + height: height + }, { + step: function () { + this.attr({ + viewBox: '0 0 ' + this.attr('width') + ' ' + + this.attr('height') + }); + }, + duration: pick(animate, true) ? void 0 : 0 + }); + while (i--) { + alignedObjects[i].align(); + } + }, + /** + * Create and return an svg group element. Child + * {@link Highcharts.SVGElement} objects are added to the group by using the + * group as the first parameter in {@link Highcharts.SVGElement#add|add()}. + * + * @function Highcharts.SVGRenderer#g + * + * @param {string} [name] + * The group will be given a class name of `highcharts-{name}`. This + * can be used for styling and scripting. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ + g: function (name) { + var elem = this.createElement('g'); + return name ? + elem.attr({ 'class': 'highcharts-' + name }) : + elem; + }, + /** + * Display an image. + * + * @sample highcharts/members/renderer-image-on-chart/ + * Add an image in a chart + * @sample highcharts/members/renderer-image/ + * Add an image independent of a chart + * + * @function Highcharts.SVGRenderer#image + * + * @param {string} src + * The image source. + * + * @param {number} [x] + * The X position. + * + * @param {number} [y] + * The Y position. + * + * @param {number} [width] + * The image width. If omitted, it defaults to the image file width. + * + * @param {number} [height] + * The image height. If omitted it defaults to the image file + * height. + * + * @param {Function} [onload] + * Event handler for image load. + * + * @return {Highcharts.SVGElement} + * The generated wrapper element. + */ + image: function (src, x, y, width, height, onload) { + var attribs = { preserveAspectRatio: 'none' }, elemWrapper, dummy, setSVGImageSource = function (el, src) { + // Set the href in the xlink namespace + if (el.setAttributeNS) { + el.setAttributeNS('http://www.w3.org/1999/xlink', 'href', src); + } + else { + // could be exporting in IE + // using href throws "not supported" in ie7 and under, + // requries regex shim to fix later + el.setAttribute('hc-svg-href', src); + } + }, onDummyLoad = function (e) { + setSVGImageSource(elemWrapper.element, src); + onload.call(elemWrapper, e); + }; + // optional properties + if (arguments.length > 1) { + extend(attribs, { + x: x, + y: y, + width: width, + height: height + }); + } + elemWrapper = this.createElement('image').attr(attribs); + // Add load event if supplied + if (onload) { + // We have to use a dummy HTML image since IE support for SVG image + // load events is very buggy. First set a transparent src, wait for + // dummy to load, and then add the real src to the SVG image. + setSVGImageSource(elemWrapper.element, 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==' /* eslint-disable-line */); + dummy = new win.Image(); + addEvent(dummy, 'load', onDummyLoad); + dummy.src = src; + if (dummy.complete) { + onDummyLoad({}); + } + } + else { + setSVGImageSource(elemWrapper.element, src); + } + return elemWrapper; + }, + /** + * Draw a symbol out of pre-defined shape paths from + * {@link SVGRenderer#symbols}. + * It is used in Highcharts for point makers, which cake a `symbol` option, + * and label and button backgrounds like in the tooltip and stock flags. + * + * @function Highcharts.SVGRenderer#symbol + * + * @param {string} symbol + * The symbol name. + * + * @param {number} [x] + * The X coordinate for the top left position. + * + * @param {number} [y] + * The Y coordinate for the top left position. + * + * @param {number} [width] + * The pixel width. + * + * @param {number} [height] + * The pixel height. + * + * @param {Highcharts.SymbolOptionsObject} [options] + * Additional options, depending on the actual symbol drawn. + * + * @return {Highcharts.SVGElement} + */ + symbol: function (symbol, x, y, width, height, options) { + var ren = this, obj, imageRegex = /^url\((.*?)\)$/, isImage = imageRegex.test(symbol), sym = (!isImage && (this.symbols[symbol] ? symbol : 'circle')), + // get the symbol definition function + symbolFn = (sym && this.symbols[sym]), path, imageSrc, centerImage; + if (symbolFn) { + // Check if there's a path defined for this symbol + if (typeof x === 'number') { + path = symbolFn.call(this.symbols, Math.round(x || 0), Math.round(y || 0), width, height, options); + } + obj = this.path(path); + if (!ren.styledMode) { + obj.attr('fill', 'none'); + } + // expando properties for use in animate and attr + extend(obj, { + symbolName: sym, + x: x, + y: y, + width: width, + height: height + }); + if (options) { + extend(obj, options); + } + // Image symbols + } + else if (isImage) { + imageSrc = symbol.match(imageRegex)[1]; + // Create the image synchronously, add attribs async + obj = this.image(imageSrc); + // The image width is not always the same as the symbol width. The + // image may be centered within the symbol, as is the case when + // image shapes are used as label backgrounds, for example in flags. + obj.imgwidth = pick(symbolSizes[imageSrc] && symbolSizes[imageSrc].width, options && options.width); + obj.imgheight = pick(symbolSizes[imageSrc] && symbolSizes[imageSrc].height, options && options.height); + /** + * Set the size and position + */ + centerImage = function () { + obj.attr({ + width: obj.width, + height: obj.height + }); + }; + /** + * Width and height setters that take both the image's physical size + * and the label size into consideration, and translates the image + * to center within the label. + */ + ['width', 'height'].forEach(function (key) { + obj[key + 'Setter'] = function (value, key) { + var attribs = {}, imgSize = this['img' + key], trans = key === 'width' ? 'translateX' : 'translateY'; + this[key] = value; + if (defined(imgSize)) { + // Scale and center the image within its container. + // The name `backgroundSize` is taken from the CSS spec, + // but the value `within` is made up. Other possible + // values in the spec, `cover` and `contain`, can be + // implemented if needed. + if (options && + options.backgroundSize === 'within' && + this.width && + this.height) { + imgSize = Math.round(imgSize * Math.min(this.width / this.imgwidth, this.height / this.imgheight)); + } + if (this.element) { + this.element.setAttribute(key, imgSize); + } + if (!this.alignByTranslate) { + attribs[trans] = ((this[key] || 0) - imgSize) / 2; + this.attr(attribs); + } + } + }; + }); + if (defined(x)) { + obj.attr({ + x: x, + y: y + }); + } + obj.isImg = true; + if (defined(obj.imgwidth) && defined(obj.imgheight)) { + centerImage(); + } + else { + // Initialize image to be 0 size so export will still function + // if there's no cached sizes. + obj.attr({ width: 0, height: 0 }); + // Create a dummy JavaScript image to get the width and height. + createElement('img', { + onload: function () { + var chart = charts[ren.chartIndex]; + // Special case for SVGs on IE11, the width is not + // accessible until the image is part of the DOM + // (#2854). + if (this.width === 0) { + css(this, { + position: 'absolute', + top: '-999em' + }); + doc.body.appendChild(this); + } + // Center the image + symbolSizes[imageSrc] = { + width: this.width, + height: this.height + }; + obj.imgwidth = this.width; + obj.imgheight = this.height; + if (obj.element) { + centerImage(); + } + // Clean up after #2854 workaround. + if (this.parentNode) { + this.parentNode.removeChild(this); + } + // Fire the load event when all external images are + // loaded + ren.imgCount--; + if (!ren.imgCount && chart && !chart.hasLoaded) { + chart.onload(); + } + }, + src: imageSrc + }); + this.imgCount++; + } + } + return obj; + }, + /** + * An extendable collection of functions for defining symbol paths. + * + * @name Highcharts.SVGRenderer#symbols + * @type {Highcharts.SymbolDictionary} + */ + symbols: { + circle: function (x, y, w, h) { + // Return a full arc + return this.arc(x + w / 2, y + h / 2, w / 2, h / 2, { + start: Math.PI * 0.5, + end: Math.PI * 2.5, + open: false + }); + }, + square: function (x, y, w, h) { + return [ + ['M', x, y], + ['L', x + w, y], + ['L', x + w, y + h], + ['L', x, y + h], + ['Z'] + ]; + }, + triangle: function (x, y, w, h) { + return [ + ['M', x + w / 2, y], + ['L', x + w, y + h], + ['L', x, y + h], + ['Z'] + ]; + }, + 'triangle-down': function (x, y, w, h) { + return [ + ['M', x, y], + ['L', x + w, y], + ['L', x + w / 2, y + h], + ['Z'] + ]; + }, + diamond: function (x, y, w, h) { + return [ + ['M', x + w / 2, y], + ['L', x + w, y + h / 2], + ['L', x + w / 2, y + h], + ['L', x, y + h / 2], + ['Z'] + ]; + }, + arc: function (x, y, w, h, options) { + var start = options.start, rx = options.r || w, ry = options.r || h || w, proximity = 0.001, fullCircle = Math.abs(options.end - options.start - 2 * Math.PI) < + proximity, + // Substract a small number to prevent cos and sin of start and + // end from becoming equal on 360 arcs (related: #1561) + end = options.end - proximity, innerRadius = options.innerR, open = pick(options.open, fullCircle), cosStart = Math.cos(start), sinStart = Math.sin(start), cosEnd = Math.cos(end), sinEnd = Math.sin(end), + // Proximity takes care of rounding errors around PI (#6971) + longArc = pick(options.longArc, options.end - start - Math.PI < proximity ? 0 : 1), arc; + arc = [ + [ + 'M', + x + rx * cosStart, + y + ry * sinStart + ], + [ + 'A', + rx, + ry, + 0, + longArc, + pick(options.clockwise, 1), + x + rx * cosEnd, + y + ry * sinEnd + ] + ]; + if (defined(innerRadius)) { + arc.push(open ? + [ + 'M', + x + innerRadius * cosEnd, + y + innerRadius * sinEnd + ] : [ + 'L', + x + innerRadius * cosEnd, + y + innerRadius * sinEnd + ], [ + 'A', + innerRadius, + innerRadius, + 0, + longArc, + // Clockwise - opposite to the outer arc clockwise + defined(options.clockwise) ? 1 - options.clockwise : 0, + x + innerRadius * cosStart, + y + innerRadius * sinStart + ]); + } + if (!open) { + arc.push(['Z']); + } + return arc; + }, + /** + * Callout shape used for default tooltips, also used for rounded + * rectangles in VML + */ + callout: function (x, y, w, h, options) { + var arrowLength = 6, halfDistance = 6, r = Math.min((options && options.r) || 0, w, h), safeDistance = r + halfDistance, anchorX = options && options.anchorX, anchorY = options && options.anchorY, path; + path = [ + ['M', x + r, y], + ['L', x + w - r, y], + ['C', x + w, y, x + w, y, x + w, y + r], + ['L', x + w, y + h - r], + ['C', x + w, y + h, x + w, y + h, x + w - r, y + h], + ['L', x + r, y + h], + ['C', x, y + h, x, y + h, x, y + h - r], + ['L', x, y + r], + ['C', x, y, x, y, x + r, y] // top-left corner + ]; + // Anchor on right side + if (anchorX && anchorX > w) { + // Chevron + if (anchorY > y + safeDistance && + anchorY < y + h - safeDistance) { + path.splice(3, 1, ['L', x + w, anchorY - halfDistance], ['L', x + w + arrowLength, anchorY], ['L', x + w, anchorY + halfDistance], ['L', x + w, y + h - r]); + // Simple connector + } + else { + path.splice(3, 1, ['L', x + w, h / 2], ['L', anchorX, anchorY], ['L', x + w, h / 2], ['L', x + w, y + h - r]); + } + // Anchor on left side + } + else if (anchorX && anchorX < 0) { + // Chevron + if (anchorY > y + safeDistance && + anchorY < y + h - safeDistance) { + path.splice(7, 1, ['L', x, anchorY + halfDistance], ['L', x - arrowLength, anchorY], ['L', x, anchorY - halfDistance], ['L', x, y + r]); + // Simple connector + } + else { + path.splice(7, 1, ['L', x, h / 2], ['L', anchorX, anchorY], ['L', x, h / 2], ['L', x, y + r]); + } + } + else if ( // replace bottom + anchorY && + anchorY > h && + anchorX > x + safeDistance && + anchorX < x + w - safeDistance) { + path.splice(5, 1, ['L', anchorX + halfDistance, y + h], ['L', anchorX, y + h + arrowLength], ['L', anchorX - halfDistance, y + h], ['L', x + r, y + h]); + } + else if ( // replace top + anchorY && + anchorY < 0 && + anchorX > x + safeDistance && + anchorX < x + w - safeDistance) { + path.splice(1, 1, ['L', anchorX - halfDistance, y], ['L', anchorX, y - arrowLength], ['L', anchorX + halfDistance, y], ['L', w - r, y]); + } + return path; + } + }, + /** + * Define a clipping rectangle. The clipping rectangle is later applied + * to {@link SVGElement} objects through the {@link SVGElement#clip} + * function. + * + * @example + * var circle = renderer.circle(100, 100, 100) + * .attr({ fill: 'red' }) + * .add(); + * var clipRect = renderer.clipRect(100, 100, 100, 100); + * + * // Leave only the lower right quarter visible + * circle.clip(clipRect); + * + * @function Highcharts.SVGRenderer#clipRect + * + * @param {number} [x] + * + * @param {number} [y] + * + * @param {number} [width] + * + * @param {number} [height] + * + * @return {Highcharts.ClipRectElement} + * A clipping rectangle. + */ + clipRect: function (x, y, width, height) { + var wrapper, + // Add a hyphen at the end to avoid confusion in testing indexes + // -1 and -10, -11 etc (#6550) + id = uniqueKey() + '-', clipPath = this.createElement('clipPath').attr({ + id: id + }).add(this.defs); + wrapper = this.rect(x, y, width, height, 0).add(clipPath); + wrapper.id = id; + wrapper.clipPath = clipPath; + wrapper.count = 0; + return wrapper; + }, + /** + * Draw text. The text can contain a subset of HTML, like spans and anchors + * and some basic text styling of these. For more advanced features like + * border and background, use {@link Highcharts.SVGRenderer#label} instead. + * To update the text after render, run `text.attr({ text: 'New text' })`. + * + * @sample highcharts/members/renderer-text-on-chart/ + * Annotate the chart freely + * @sample highcharts/members/renderer-on-chart/ + * Annotate with a border and in response to the data + * @sample highcharts/members/renderer-text/ + * Formatted text + * + * @function Highcharts.SVGRenderer#text + * + * @param {string} [str] + * The text of (subset) HTML to draw. + * + * @param {number} [x] + * The x position of the text's lower left corner. + * + * @param {number} [y] + * The y position of the text's lower left corner. + * + * @param {boolean} [useHTML=false] + * Use HTML to render the text. + * + * @return {Highcharts.SVGElement} + * The text object. + */ + text: function (str, x, y, useHTML) { + // declare variables + var renderer = this, wrapper, attribs = {}; + if (useHTML && (renderer.allowHTML || !renderer.forExport)) { + return renderer.html(str, x, y); + } + attribs.x = Math.round(x || 0); // X always needed for line-wrap logic + if (y) { + attribs.y = Math.round(y); + } + if (defined(str)) { + attribs.text = str; + } + wrapper = renderer.createElement('text') + .attr(attribs); + if (!useHTML) { + wrapper.xSetter = function (value, key, element) { + var tspans = element.getElementsByTagName('tspan'), tspan, parentVal = element.getAttribute(key), i; + for (i = 0; i < tspans.length; i++) { + tspan = tspans[i]; + // If the x values are equal, the tspan represents a + // linebreak + if (tspan.getAttribute(key) === parentVal) { + tspan.setAttribute(key, value); + } + } + element.setAttribute(key, value); + }; + } + return wrapper; + }, + /** + * Utility to return the baseline offset and total line height from the font + * size. + * + * @function Highcharts.SVGRenderer#fontMetrics + * + * @param {number|string} [fontSize] + * The current font size to inspect. If not given, the font size + * will be found from the DOM element. + * + * @param {Highcharts.SVGElement|Highcharts.SVGDOMElement} [elem] + * The element to inspect for a current font size. + * + * @return {Highcharts.FontMetricsObject} + * The font metrics. + */ + fontMetrics: function (fontSize, elem) { + var lineHeight, baseline; + if ((this.styledMode || !/px/.test(fontSize)) && + win.getComputedStyle // old IE doesn't support it + ) { + fontSize = elem && SVGElement.prototype.getStyle.call(elem, 'font-size'); + } + else { + fontSize = fontSize || + // When the elem is a DOM element (#5932) + (elem && elem.style && elem.style.fontSize) || + // Fall back on the renderer style default + (this.style && this.style.fontSize); + } + // Handle different units + if (/px/.test(fontSize)) { + fontSize = pInt(fontSize); + } + else { + fontSize = 12; + } + // Empirical values found by comparing font size and bounding box + // height. Applies to the default font family. + // https://jsfiddle.net/highcharts/7xvn7/ + lineHeight = fontSize < 24 ? fontSize + 3 : Math.round(fontSize * 1.2); + baseline = Math.round(lineHeight * 0.8); + return { + h: lineHeight, + b: baseline, + f: fontSize + }; + }, + /** + * Correct X and Y positioning of a label for rotation (#1764). + * + * @private + * @function Highcharts.SVGRenderer#rotCorr + * + * @param {number} baseline + * + * @param {number} rotation + * + * @param {boolean} [alterY] + * + * @param {Highcharts.PositionObject} + */ + rotCorr: function (baseline, rotation, alterY) { + var y = baseline; + if (rotation && alterY) { + y = Math.max(y * Math.cos(rotation * deg2rad), 4); + } + return { + x: (-baseline / 3) * Math.sin(rotation * deg2rad), + y: y + }; + }, + /** + * Compatibility function to convert the legacy one-dimensional path array + * into an array of segments. + * + * It is used in maps to parse the `path` option, and in SVGRenderer.dSetter + * to support legacy paths from demos. + * + * @param path @private + * @function Highcharts.SVGRenderer#pathToSegments + * + * @param {Array} + * + * @return {Highcharts.SVGPathArray} + */ + pathToSegments: function (path) { + var ret = []; + var segment = []; + var commandLength = { + A: 8, + C: 7, + H: 2, + L: 3, + M: 3, + Q: 5, + S: 5, + T: 3, + V: 2 + }; + // Short, non-typesafe parsing of the one-dimensional array. It splits + // the path on any string. This is not type checked against the tuple + // types, but is shorter, and doesn't require specific checks for any + // command type in SVG. + for (var i = 0; i < path.length; i++) { + // Command skipped, repeat previous or insert L/l for M/m + if (isString(segment[0]) && + isNumber(path[i]) && + segment.length === commandLength[(segment[0].toUpperCase())]) { + path.splice(i, 0, segment[0].replace('M', 'L').replace('m', 'l')); + } + // Split on string + if (typeof path[i] === 'string') { + if (segment.length) { + ret.push(segment.slice(0)); + } + segment.length = 0; + } + segment.push(path[i]); + } + ret.push(segment.slice(0)); + return ret; + /* + // Fully type-safe version where each tuple type is checked. The + // downside is filesize and a lack of flexibility for unsupported + // commands + const ret: Highcharts.SVGPathArray = [], + commands = { + A: 7, + C: 6, + H: 1, + L: 2, + M: 2, + Q: 4, + S: 4, + T: 2, + V: 1, + Z: 0 + }; + + let i = 0, + lastI = 0, + lastCommand; + + while (i < path.length) { + const item = path[i]; + + let command; + + if (typeof item === 'string') { + command = item; + i += 1; + } else { + command = lastCommand || 'M'; + } + + // Upper case + const commandUC = command.toUpperCase(); + + if (commandUC in commands) { + + // No numeric parameters + if (command === 'Z' || command === 'z') { + ret.push([command]); + + // One numeric parameter + } else { + const val0 = path[i]; + if (typeof val0 === 'number') { + + // Horizontal line to + if (command === 'H' || command === 'h') { + ret.push([command, val0]); + i += 1; + + // Vertical line to + } else if (command === 'V' || command === 'v') { + ret.push([command, val0]); + i += 1; + + // Two numeric parameters + } else { + const val1 = path[i + 1]; + if (typeof val1 === 'number') { + // lineTo + if (command === 'L' || command === 'l') { + ret.push([command, val0, val1]); + i += 2; + + // moveTo + } else if (command === 'M' || command === 'm') { + ret.push([command, val0, val1]); + i += 2; + + // Smooth quadratic bezier + } else if (command === 'T' || command === 't') { + ret.push([command, val0, val1]); + i += 2; + + // Four numeric parameters + } else { + const val2 = path[i + 2], + val3 = path[i + 3]; + if ( + typeof val2 === 'number' && + typeof val3 === 'number' + ) { + // Quadratic bezier to + if ( + command === 'Q' || + command === 'q' + ) { + ret.push([ + command, + val0, + val1, + val2, + val3 + ]); + i += 4; + + // Smooth cubic bezier to + } else if ( + command === 'S' || + command === 's' + ) { + ret.push([ + command, + val0, + val1, + val2, + val3 + ]); + i += 4; + + // Six numeric parameters + } else { + const val4 = path[i + 4], + val5 = path[i + 5]; + + if ( + typeof val4 === 'number' && + typeof val5 === 'number' + ) { + // Curve to + if ( + command === 'C' || + command === 'c' + ) { + ret.push([ + command, + val0, + val1, + val2, + val3, + val4, + val5 + ]); + i += 6; + + // Seven numeric parameters + } else { + const val6 = path[i + 6]; + + // Arc to + if ( + typeof val6 === + 'number' && + ( + command === 'A' || + command === 'a' + ) + ) { + ret.push([ + command, + val0, + val1, + val2, + val3, + val4, + val5, + val6 + ]); + i += 7; + + } + + } + } + } + } + } + } + + } + } + } + } + + // An unmarked command following a moveTo is a lineTo + lastCommand = command === 'M' ? 'L' : command; + + if (i === lastI) { + break; + } + lastI = i; + } + return ret; + */ + }, + /** + * Draw a label, which is an extended text element with support for border + * and background. Highcharts creates a `g` element with a text and a `path` + * or `rect` inside, to make it behave somewhat like a HTML div. Border and + * background are set through `stroke`, `stroke-width` and `fill` attributes + * using the {@link Highcharts.SVGElement#attr|attr} method. To update the + * text after render, run `label.attr({ text: 'New text' })`. + * + * @sample highcharts/members/renderer-label-on-chart/ + * A label on the chart + * + * @function Highcharts.SVGRenderer#label + * + * @param {string} str + * The initial text string or (subset) HTML to render. + * + * @param {number} x + * The x position of the label's left side. + * + * @param {number} [y] + * The y position of the label's top side or baseline, depending on + * the `baseline` parameter. + * + * @param {string} [shape='rect'] + * The shape of the label's border/background, if any. Defaults to + * `rect`. Other possible values are `callout` or other shapes + * defined in {@link Highcharts.SVGRenderer#symbols}. + * + * @param {number} [anchorX] + * In case the `shape` has a pointer, like a flag, this is the + * coordinates it should be pinned to. + * + * @param {number} [anchorY] + * In case the `shape` has a pointer, like a flag, this is the + * coordinates it should be pinned to. + * + * @param {boolean} [useHTML=false] + * Wether to use HTML to render the label. + * + * @param {boolean} [baseline=false] + * Whether to position the label relative to the text baseline, + * like {@link Highcharts.SVGRenderer#text|renderer.text}, or to the + * upper border of the rectangle. + * + * @param {string} [className] + * Class name for the group. + * + * @return {Highcharts.SVGElement} + * The generated label. + */ + label: function (str, x, y, shape, anchorX, anchorY, useHTML, baseline, className) { + var renderer = this, styledMode = renderer.styledMode, wrapper = renderer.g((className !== 'button' && 'label')), text = wrapper.text = renderer.text('', 0, 0, useHTML) + .attr({ + zIndex: 1 + }), box, emptyBBox = { width: 0, height: 0, x: 0, y: 0 }, bBox = emptyBBox, alignFactor = 0, padding = 3, paddingLeft = 0, width, height, wrapperX, wrapperY, textAlign, deferredAttr = {}, strokeWidth, baselineOffset, hasBGImage = /^url\((.*?)\)$/.test(shape), needsBox = styledMode || hasBGImage, getCrispAdjust = function () { + return styledMode ? + box.strokeWidth() % 2 / 2 : + (strokeWidth ? parseInt(strokeWidth, 10) : 0) % 2 / 2; + }, updateBoxSize, updateTextPadding, boxAttr; + if (className) { + wrapper.addClass('highcharts-' + className); + } + /* This function runs after the label is added to the DOM (when the + bounding box is available), and after the text of the label is + updated to detect the new bounding box and reflect it in the border + box. */ + updateBoxSize = function () { + var style = text.element.style, crispAdjust, attribs = {}; + // #12165 error when width is null (auto) + // #12163 when fontweight: bold, recalculate bBox withot cache + // #3295 && 3514 box failure when string equals 0 + bBox = ((!isNumber(width) || !isNumber(height) || textAlign) && + defined(text.textStr)) ? + text.getBBox() : emptyBBox; + wrapper.width = ((width || bBox.width || 0) + + 2 * padding + + paddingLeft); + wrapper.height = (height || bBox.height || 0) + 2 * padding; + // Update the label-scoped y offset. Math.min because of inline + // style (#9400) + baselineOffset = padding + Math.min(renderer + .fontMetrics(style && style.fontSize, text).b, + // When the height is 0, there is no bBox, so go with the font + // metrics. Highmaps CSS demos. + bBox.height || Infinity); + if (needsBox) { + // Create the border box if it is not already present + if (!box) { + // Symbol definition exists (#5324) + wrapper.box = box = + renderer.symbols[shape] || hasBGImage ? + renderer.symbol(shape) : + renderer.rect(); + box.addClass(// Don't use label className for buttons + (className === 'button' ? '' : 'highcharts-label-box') + + (className ? ' highcharts-' + className + '-box' : '')); + box.add(wrapper); + crispAdjust = getCrispAdjust(); + attribs.x = crispAdjust; + attribs.y = (baseline ? -baselineOffset : 0) + crispAdjust; + } + // Apply the box attributes + attribs.width = Math.round(wrapper.width); + attribs.height = Math.round(wrapper.height); + box.attr(extend(attribs, deferredAttr)); + deferredAttr = {}; + } + }; + /* + * This function runs after setting text or padding, but only if padding + * is changed. + */ + updateTextPadding = function () { + var textX = paddingLeft + padding, textY; + // determin y based on the baseline + textY = baseline ? 0 : baselineOffset; + // compensate for alignment + if (defined(width) && + bBox && + (textAlign === 'center' || textAlign === 'right')) { + textX += { center: 0.5, right: 1 }[textAlign] * + (width - bBox.width); + } + // update if anything changed + if (textX !== text.x || textY !== text.y) { + text.attr('x', textX); + // #8159 - prevent misplaced data labels in treemap + // (useHTML: true) + if (text.hasBoxWidthChanged) { + bBox = text.getBBox(true); + updateBoxSize(); + } + if (typeof textY !== 'undefined') { + text.attr('y', textY); + } + } + // record current values + text.x = textX; + text.y = textY; + }; + /* + * Set a box attribute, or defer it if the box is not yet created + */ + boxAttr = function (key, value) { + if (box) { + box.attr(key, value); + } + else { + deferredAttr[key] = value; + } + }; + /* + * After the text element is added, get the desired size of the border + * box and add it before the text in the DOM. + */ + wrapper.onAdd = function () { + text.add(wrapper); + wrapper.attr({ + // Alignment is available now (#3295, 0 not rendered if given + // as a value) + text: (str || str === 0) ? str : '', + x: x, + y: y + }); + if (box && defined(anchorX)) { + wrapper.attr({ + anchorX: anchorX, + anchorY: anchorY + }); + } + }; + /* + * Add specific attribute setters. + */ + // only change local variables + wrapper.widthSetter = function (value) { + // width:auto => null + width = isNumber(value) ? value : null; + }; + wrapper.heightSetter = function (value) { + height = value; + }; + wrapper['text-alignSetter'] = function (value) { + textAlign = value; + }; + wrapper.paddingSetter = function (value) { + if (defined(value) && value !== padding) { + padding = wrapper.padding = value; + updateTextPadding(); + } + }; + wrapper.paddingLeftSetter = function (value) { + if (defined(value) && value !== paddingLeft) { + paddingLeft = value; + updateTextPadding(); + } + }; + // change local variable and prevent setting attribute on the group + wrapper.alignSetter = function (value) { + value = { + left: 0, + center: 0.5, + right: 1 + }[value]; + if (value !== alignFactor) { + alignFactor = value; + // Bounding box exists, means we're dynamically changing + if (bBox) { + wrapper.attr({ x: wrapperX }); // #5134 + } + } + }; + // apply these to the box and the text alike + wrapper.textSetter = function (value) { + if (typeof value !== 'undefined') { + // Must use .attr to ensure transforms are done (#10009) + text.attr({ + text: value + }); + } + updateBoxSize(); + updateTextPadding(); + }; + // apply these to the box but not to the text + wrapper['stroke-widthSetter'] = function (value, key) { + if (value) { + needsBox = true; + } + strokeWidth = this['stroke-width'] = value; + boxAttr(key, value); + }; + if (styledMode) { + wrapper.rSetter = function (value, key) { + boxAttr(key, value); + }; + } + else { + wrapper.strokeSetter = + wrapper.fillSetter = + wrapper.rSetter = function (value, key) { + if (key !== 'r') { + if (key === 'fill' && value) { + needsBox = true; + } + // for animation getter (#6776) + wrapper[key] = value; + } + boxAttr(key, value); + }; + } + wrapper.anchorXSetter = function (value, key) { + anchorX = wrapper.anchorX = value; + boxAttr(key, Math.round(value) - getCrispAdjust() - wrapperX); + }; + wrapper.anchorYSetter = function (value, key) { + anchorY = wrapper.anchorY = value; + boxAttr(key, value - wrapperY); + }; + // rename attributes + wrapper.xSetter = function (value) { + wrapper.x = value; // for animation getter + if (alignFactor) { + value -= alignFactor * ((width || bBox.width) + 2 * padding); + // Force animation even when setting to the same value (#7898) + wrapper['forceAnimate:x'] = true; + } + wrapperX = Math.round(value); + wrapper.attr('translateX', wrapperX); + }; + wrapper.ySetter = function (value) { + wrapperY = wrapper.y = Math.round(value); + wrapper.attr('translateY', wrapperY); + }; + wrapper.isLabel = true; + // Redirect certain methods to either the box or the text + var baseCss = wrapper.css; + var wrapperExtension = { + /** + * Pick up some properties and apply them to the text instead of the + * wrapper. + */ + css: function (styles) { + if (styles) { + var textStyles = {}, isWidth, isFontStyle; + // Create a copy to avoid altering the original object + // (#537) + styles = merge(styles); + wrapper.textProps.forEach(function (prop) { + if (typeof styles[prop] !== 'undefined') { + textStyles[prop] = styles[prop]; + delete styles[prop]; + } + }); + text.css(textStyles); + isWidth = 'width' in textStyles; + isFontStyle = 'fontSize' in textStyles || + 'fontWeight' in textStyles; + // Update existing text, box (#9400, #12163) + if (isWidth || isFontStyle) { + updateBoxSize(); + // Keep updated (#9400, #12163) + if (isFontStyle) { + updateTextPadding(); + } + } + } + return baseCss.call(wrapper, styles); + }, + /* + * Return the bounding box of the box, not the group. + */ + getBBox: function () { + return { + width: bBox.width + 2 * padding, + height: bBox.height + 2 * padding, + x: bBox.x - padding, + y: bBox.y - padding + }; + }, + /** + * Destroy and release memory. + */ + destroy: function () { + // Added by button implementation + removeEvent(wrapper.element, 'mouseenter'); + removeEvent(wrapper.element, 'mouseleave'); + if (text) { + text.destroy(); + } + if (box) { + box = box.destroy(); + } + // Call base implementation to destroy the rest + SVGElement.prototype.destroy.call(wrapper); + // Release local pointers (#1298) + wrapper = + renderer = + text = + updateBoxSize = + updateTextPadding = + boxAttr = null; + } + }; + // Event handling. In case of useHTML, we need to make sure that events + // are captured on the span as well, and that mouseenter/mouseleave + // between the SVG group and the HTML span are not treated as real + // enter/leave events. #13310. + wrapper.on = function (eventType, handler) { + var span = text && text.element.tagName === 'SPAN' ? text : void 0; + var selectiveHandler; + if (span) { + selectiveHandler = function (e) { + if ((eventType === 'mouseenter' || + eventType === 'mouseleave') && + e.relatedTarget instanceof Element && + (wrapper.element.contains(e.relatedTarget) || + span.element.contains(e.relatedTarget))) { + return; + } + handler.call(wrapper.element, e); + }; + span.on(eventType, selectiveHandler); + } + SVGElement.prototype.on.call(wrapper, eventType, selectiveHandler || handler); + return wrapper; + }; + if (!styledMode) { + /** + * Apply the shadow to the box. + * + * @ignore + * @function Highcharts.SVGElement#shadow + * + * @return {Highcharts.SVGElement} + */ + wrapperExtension.shadow = function (b) { + if (b) { + updateBoxSize(); + if (box) { + box.shadow(b); + } + } + return wrapper; + }; + } + return extend(wrapper, wrapperExtension); + } + }); // end SVGRenderer + // general renderer + H.Renderer = SVGRenderer; + + }); + _registerModule(_modules, 'parts/Html.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var attr = U.attr, createElement = U.createElement, css = U.css, defined = U.defined, extend = U.extend, pick = U.pick, pInt = U.pInt; + var isFirefox = H.isFirefox, isMS = H.isMS, isWebKit = H.isWebKit, SVGElement = H.SVGElement, SVGRenderer = H.SVGRenderer, win = H.win; + /* eslint-disable valid-jsdoc */ + // Extend SvgElement for useHTML option. + extend(SVGElement.prototype, /** @lends SVGElement.prototype */ { + /** + * Apply CSS to HTML elements. This is used in text within SVG rendering and + * by the VML renderer + * + * @private + * @function Highcharts.SVGElement#htmlCss + * + * @param {Highcharts.CSSObject} styles + * + * @return {Highcharts.SVGElement} + */ + htmlCss: function (styles) { + var wrapper = this, element = wrapper.element, + // When setting or unsetting the width style, we need to update + // transform (#8809) + isSettingWidth = (element.tagName === 'SPAN' && + styles && + 'width' in styles), textWidth = pick(isSettingWidth && styles.width, void 0), doTransform; + if (isSettingWidth) { + delete styles.width; + wrapper.textWidth = textWidth; + doTransform = true; + } + if (styles && styles.textOverflow === 'ellipsis') { + styles.whiteSpace = 'nowrap'; + styles.overflow = 'hidden'; + } + wrapper.styles = extend(wrapper.styles, styles); + css(wrapper.element, styles); + // Now that all styles are applied, to the transform + if (doTransform) { + wrapper.htmlUpdateTransform(); + } + return wrapper; + }, + /** + * VML and useHTML method for calculating the bounding box based on offsets. + * + * @private + * @function Highcharts.SVGElement#htmlGetBBox + * + * @param {boolean} refresh + * Whether to force a fresh value from the DOM or to use the cached + * value. + * + * @return {Highcharts.BBoxObject} + * A hash containing values for x, y, width and height. + */ + htmlGetBBox: function () { + var wrapper = this, element = wrapper.element; + return { + x: element.offsetLeft, + y: element.offsetTop, + width: element.offsetWidth, + height: element.offsetHeight + }; + }, + /** + * VML override private method to update elements based on internal + * properties based on SVG transform. + * + * @private + * @function Highcharts.SVGElement#htmlUpdateTransform + * @return {void} + */ + htmlUpdateTransform: function () { + // aligning non added elements is expensive + if (!this.added) { + this.alignOnAdd = true; + return; + } + var wrapper = this, renderer = wrapper.renderer, elem = wrapper.element, translateX = wrapper.translateX || 0, translateY = wrapper.translateY || 0, x = wrapper.x || 0, y = wrapper.y || 0, align = wrapper.textAlign || 'left', alignCorrection = { + left: 0, center: 0.5, right: 1 + }[align], styles = wrapper.styles, whiteSpace = styles && styles.whiteSpace; + /** + * @private + * @return {number} + */ + function getTextPxLength() { + // Reset multiline/ellipsis in order to read width (#4928, + // #5417) + css(elem, { + width: '', + whiteSpace: whiteSpace || 'nowrap' + }); + return elem.offsetWidth; + } + // apply translate + css(elem, { + marginLeft: translateX, + marginTop: translateY + }); + if (!renderer.styledMode && wrapper.shadows) { // used in labels/tooltip + wrapper.shadows.forEach(function (shadow) { + css(shadow, { + marginLeft: translateX + 1, + marginTop: translateY + 1 + }); + }); + } + // apply inversion + if (wrapper.inverted) { // wrapper is a group + [].forEach.call(elem.childNodes, function (child) { + renderer.invertChild(child, elem); + }); + } + if (elem.tagName === 'SPAN') { + var rotation = wrapper.rotation, baseline, textWidth = wrapper.textWidth && pInt(wrapper.textWidth), currentTextTransform = [ + rotation, + align, + elem.innerHTML, + wrapper.textWidth, + wrapper.textAlign + ].join(','); + // Update textWidth. Use the memoized textPxLength if possible, to + // avoid the getTextPxLength function using elem.offsetWidth. + // Calling offsetWidth affects rendering time as it forces layout + // (#7656). + if (textWidth !== wrapper.oldTextWidth && + ((textWidth > wrapper.oldTextWidth) || + (wrapper.textPxLength || getTextPxLength()) > textWidth) && ( + // Only set the width if the text is able to word-wrap, or + // text-overflow is ellipsis (#9537) + /[ \-]/.test(elem.textContent || elem.innerText) || + elem.style.textOverflow === 'ellipsis')) { // #983, #1254 + css(elem, { + width: textWidth + 'px', + display: 'block', + whiteSpace: whiteSpace || 'normal' // #3331 + }); + wrapper.oldTextWidth = textWidth; + wrapper.hasBoxWidthChanged = true; // #8159 + } + else { + wrapper.hasBoxWidthChanged = false; // #8159 + } + // Do the calculations and DOM access only if properties changed + if (currentTextTransform !== wrapper.cTT) { + baseline = renderer.fontMetrics(elem.style.fontSize, elem).b; + // Renderer specific handling of span rotation, but only if we + // have something to update. + if (defined(rotation) && + ((rotation !== (wrapper.oldRotation || 0)) || + (align !== wrapper.oldAlign))) { + wrapper.setSpanRotation(rotation, alignCorrection, baseline); + } + wrapper.getSpanCorrection( + // Avoid elem.offsetWidth if we can, it affects rendering + // time heavily (#7656) + ((!defined(rotation) && wrapper.textPxLength) || // #7920 + elem.offsetWidth), baseline, alignCorrection, rotation, align); + } + // apply position with correction + css(elem, { + left: (x + (wrapper.xCorr || 0)) + 'px', + top: (y + (wrapper.yCorr || 0)) + 'px' + }); + // record current text transform + wrapper.cTT = currentTextTransform; + wrapper.oldRotation = rotation; + wrapper.oldAlign = align; + } + }, + /** + * Set the rotation of an individual HTML span. + * + * @private + * @function Highcharts.SVGElement#setSpanRotation + * @param {number} rotation + * @param {number} alignCorrection + * @param {number} baseline + * @return {void} + */ + setSpanRotation: function (rotation, alignCorrection, baseline) { + var rotationStyle = {}, cssTransformKey = this.renderer.getTransformKey(); + rotationStyle[cssTransformKey] = rotationStyle.transform = + 'rotate(' + rotation + 'deg)'; + rotationStyle[cssTransformKey + (isFirefox ? 'Origin' : '-origin')] = + rotationStyle.transformOrigin = + (alignCorrection * 100) + '% ' + baseline + 'px'; + css(this.element, rotationStyle); + }, + /** + * Get the correction in X and Y positioning as the element is rotated. + * + * @private + * @function Highcharts.SVGElement#getSpanCorrection + * @param {number} width + * @param {number} baseline + * @param {number} alignCorrection + * @return {void} + */ + getSpanCorrection: function (width, baseline, alignCorrection) { + this.xCorr = -width * alignCorrection; + this.yCorr = -baseline; + } + }); + // Extend SvgRenderer for useHTML option. + extend(SVGRenderer.prototype, /** @lends SVGRenderer.prototype */ { + /** + * @private + * @function Highcharts.SVGRenderer#getTransformKey + * + * @return {string} + */ + getTransformKey: function () { + return isMS && !/Edge/.test(win.navigator.userAgent) ? + '-ms-transform' : + isWebKit ? + '-webkit-transform' : + isFirefox ? + 'MozTransform' : + win.opera ? + '-o-transform' : + ''; + }, + /** + * Create HTML text node. This is used by the VML renderer as well as the + * SVG renderer through the useHTML option. + * + * @private + * @function Highcharts.SVGRenderer#html + * + * @param {string} str + * The text of (subset) HTML to draw. + * + * @param {number} x + * The x position of the text's lower left corner. + * + * @param {number} y + * The y position of the text's lower left corner. + * + * @return {Highcharts.HTMLDOMElement} + */ + html: function (str, x, y) { + var wrapper = this.createElement('span'), element = wrapper.element, renderer = wrapper.renderer, isSVG = renderer.isSVG, addSetters = function (gWrapper, style) { + // These properties are set as attributes on the SVG group, and + // as identical CSS properties on the div. (#3542) + ['opacity', 'visibility'].forEach(function (prop) { + gWrapper[prop + 'Setter'] = function (value, key, elem) { + var styleObject = gWrapper.div ? + gWrapper.div.style : + style; + SVGElement.prototype[prop + 'Setter'] + .call(this, value, key, elem); + if (styleObject) { + styleObject[key] = value; + } + }; + }); + gWrapper.addedSetters = true; + }; + // Text setter + wrapper.textSetter = function (value) { + if (value !== element.innerHTML) { + delete this.bBox; + delete this.oldTextWidth; + } + this.textStr = value; + element.innerHTML = pick(value, ''); + wrapper.doTransform = true; + }; + // Add setters for the element itself (#4938) + if (isSVG) { // #4938, only for HTML within SVG + addSetters(wrapper, wrapper.element.style); + } + // Various setters which rely on update transform + wrapper.xSetter = + wrapper.ySetter = + wrapper.alignSetter = + wrapper.rotationSetter = + function (value, key) { + if (key === 'align') { + // Do not overwrite the SVGElement.align method. Same as VML. + key = 'textAlign'; + } + wrapper[key] = value; + wrapper.doTransform = true; + }; + // Runs at the end of .attr() + wrapper.afterSetters = function () { + // Update transform. Do this outside the loop to prevent redundant + // updating for batch setting of attributes. + if (this.doTransform) { + this.htmlUpdateTransform(); + this.doTransform = false; + } + }; + // Set the default attributes + wrapper + .attr({ + text: str, + x: Math.round(x), + y: Math.round(y) + }) + .css({ + position: 'absolute' + }); + if (!renderer.styledMode) { + wrapper.css({ + fontFamily: this.style.fontFamily, + fontSize: this.style.fontSize + }); + } + // Keep the whiteSpace style outside the wrapper.styles collection + element.style.whiteSpace = 'nowrap'; + // Use the HTML specific .css method + wrapper.css = wrapper.htmlCss; + // This is specific for HTML within SVG + if (isSVG) { + wrapper.add = function (svgGroupWrapper) { + var htmlGroup, container = renderer.box.parentNode, parentGroup, parents = []; + this.parentGroup = svgGroupWrapper; + // Create a mock group to hold the HTML elements + if (svgGroupWrapper) { + htmlGroup = svgGroupWrapper.div; + if (!htmlGroup) { + // Read the parent chain into an array and read from top + // down + parentGroup = svgGroupWrapper; + while (parentGroup) { + parents.push(parentGroup); + // Move up to the next parent group + parentGroup = parentGroup.parentGroup; + } + // Ensure dynamically updating position when any parent + // is translated + parents.reverse().forEach(function (parentGroup) { + var htmlGroupStyle, cls = attr(parentGroup.element, 'class'); + /** + * Common translate setter for X and Y on the HTML + * group. Reverted the fix for #6957 du to + * positioning problems and offline export (#7254, + * #7280, #7529) + * @private + * @param {*} value + * @param {string} key + * @return {void} + */ + function translateSetter(value, key) { + parentGroup[key] = value; + if (key === 'translateX') { + htmlGroupStyle.left = value + 'px'; + } + else { + htmlGroupStyle.top = value + 'px'; + } + parentGroup.doTransform = true; + } + // Create a HTML div and append it to the parent div + // to emulate the SVG group structure + htmlGroup = + parentGroup.div = + parentGroup.div || createElement('div', cls ? { className: cls } : void 0, { + position: 'absolute', + left: (parentGroup.translateX || 0) + 'px', + top: (parentGroup.translateY || 0) + 'px', + display: parentGroup.display, + opacity: parentGroup.opacity, + pointerEvents: (parentGroup.styles && + parentGroup.styles.pointerEvents) // #5595 + // the top group is appended to container + }, htmlGroup || container); + // Shortcut + htmlGroupStyle = htmlGroup.style; + // Set listeners to update the HTML div's position + // whenever the SVG group position is changed. + extend(parentGroup, { + // (#7287) Pass htmlGroup to use + // the related group + classSetter: (function (htmlGroup) { + return function (value) { + this.element.setAttribute('class', value); + htmlGroup.className = value; + }; + }(htmlGroup)), + on: function () { + if (parents[0].div) { // #6418 + wrapper.on.apply({ element: parents[0].div }, arguments); + } + return parentGroup; + }, + translateXSetter: translateSetter, + translateYSetter: translateSetter + }); + if (!parentGroup.addedSetters) { + addSetters(parentGroup); + } + }); + } + } + else { + htmlGroup = container; + } + htmlGroup.appendChild(element); + // Shared with VML: + wrapper.added = true; + if (wrapper.alignOnAdd) { + wrapper.htmlUpdateTransform(); + } + return wrapper; + }; + } + return wrapper; + } + }); + + }); + _registerModule(_modules, 'parts/Tick.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Optional parameters for the tick. + * @private + * @interface Highcharts.TickParametersObject + */ /** + * Set category for the tick. + * @name Highcharts.TickParametersObject#category + * @type {string|undefined} + */ /** + * @name Highcharts.TickParametersObject#options + * @type {Highcharts.Dictionary|undefined} + */ /** + * Set tickmarkOffset for the tick. + * @name Highcharts.TickParametersObject#tickmarkOffset + * @type {number|undefined} + */ + var clamp = U.clamp, correctFloat = U.correctFloat, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, extend = U.extend, fireEvent = U.fireEvent, isNumber = U.isNumber, merge = U.merge, objectEach = U.objectEach, pick = U.pick; + var deg2rad = H.deg2rad; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The Tick class. + * + * @class + * @name Highcharts.Tick + * + * @param {Highcharts.Axis} axis + * The axis of the tick. + * + * @param {number} pos + * The position of the tick on the axis in terms of axis values. + * + * @param {string} [type] + * The type of tick, either 'minor' or an empty string + * + * @param {boolean} [noLabel=false] + * Whether to disable the label or not. Defaults to false. + * + * @param {object} [parameters] + * Optional parameters for the tick. + */ + var Tick = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Tick(axis, pos, type, noLabel, parameters) { + this.isNew = true; + this.isNewLabel = true; + /** + * The related axis of the tick. + * @name Highcharts.Tick#axis + * @type {Highcharts.Axis} + */ + this.axis = axis; + /** + * The logical position of the tick on the axis in terms of axis values. + * @name Highcharts.Tick#pos + * @type {number} + */ + this.pos = pos; + /** + * The tick type, which can be `"minor"`, or an empty string. + * @name Highcharts.Tick#type + * @type {string} + */ + this.type = type || ''; + this.parameters = parameters || {}; + /** + * The mark offset of the tick on the axis. Usually `undefined`, numeric + * for grid axes. + * @name Highcharts.Tick#tickmarkOffset + * @type {number|undefined} + */ + this.tickmarkOffset = this.parameters.tickmarkOffset; + this.options = this.parameters.options; + fireEvent(this, 'init'); + if (!type && !noLabel) { + this.addLabel(); + } + } + /* * + * + * Functions + * + * */ + /** + * Write the tick label. + * + * @private + * @function Highcharts.Tick#addLabel + * @return {void} + */ + Tick.prototype.addLabel = function () { + var tick = this, axis = tick.axis, options = axis.options, chart = axis.chart, categories = axis.categories, log = axis.logarithmic, names = axis.names, pos = tick.pos, labelOptions = pick(tick.options && tick.options.labels, options.labels), str, tickPositions = axis.tickPositions, isFirst = pos === tickPositions[0], isLast = pos === tickPositions[tickPositions.length - 1], value = this.parameters.category || (categories ? + pick(categories[pos], names[pos], pos) : + pos), label = tick.label, animateLabels = (!labelOptions.step || labelOptions.step === 1) && + axis.tickInterval === 1, tickPositionInfo = tickPositions.info, dateTimeLabelFormat, dateTimeLabelFormats, i, list; + // Set the datetime label format. If a higher rank is set for this + // position, use that. If not, use the general format. + if (axis.dateTime && tickPositionInfo) { + dateTimeLabelFormats = chart.time.resolveDTLFormat(options.dateTimeLabelFormats[(!options.grid && + tickPositionInfo.higherRanks[pos]) || + tickPositionInfo.unitName]); + dateTimeLabelFormat = dateTimeLabelFormats.main; + } + // set properties for access in render method + /** + * True if the tick is the first one on the axis. + * @name Highcharts.Tick#isFirst + * @readonly + * @type {boolean|undefined} + */ + tick.isFirst = isFirst; + /** + * True if the tick is the last one on the axis. + * @name Highcharts.Tick#isLast + * @readonly + * @type {boolean|undefined} + */ + tick.isLast = isLast; + // Get the string + tick.formatCtx = { + axis: axis, + chart: chart, + isFirst: isFirst, + isLast: isLast, + dateTimeLabelFormat: dateTimeLabelFormat, + tickPositionInfo: tickPositionInfo, + value: log ? correctFloat(log.lin2log(value)) : value, + pos: pos + }; + str = axis.labelFormatter.call(tick.formatCtx, this.formatCtx); + // Set up conditional formatting based on the format list if existing. + list = dateTimeLabelFormats && dateTimeLabelFormats.list; + if (list) { + tick.shortenLabel = function () { + for (i = 0; i < list.length; i++) { + label.attr({ + text: axis.labelFormatter.call(extend(tick.formatCtx, { dateTimeLabelFormat: list[i] })) + }); + if (label.getBBox().width < + axis.getSlotWidth(tick) - 2 * + pick(labelOptions.padding, 5)) { + return; + } + } + label.attr({ + text: '' + }); + }; + } + // Call only after first render + if (animateLabels && axis._addedPlotLB && axis.isXAxis) { + tick.moveLabel(str, labelOptions); + } + // First call + if (!defined(label) && !tick.movedLabel) { + /** + * The rendered text label of the tick. + * @name Highcharts.Tick#label + * @type {Highcharts.SVGElement|undefined} + */ + tick.label = label = tick.createLabel({ x: 0, y: 0 }, str, labelOptions); + // Base value to detect change for new calls to getBBox + tick.rotation = 0; + // update + } + else if (label && label.textStr !== str && !animateLabels) { + // When resetting text, also reset the width if dynamically set + // (#8809) + if (label.textWidth && + !(labelOptions.style && labelOptions.style.width) && + !label.styles.width) { + label.css({ width: null }); + } + label.attr({ text: str }); + label.textPxLength = label.getBBox().width; + } + }; + /** + * Render and return the label of the tick. + * + * @private + * @function Highcharts.Tick#createLabel + * @param {Highcharts.PositionObject} xy + * @param {string} str + * @param {Highcharts.XAxisLabelsOptions} labelOptions + * @return {Highcharts.SVGElement|undefined} + */ + Tick.prototype.createLabel = function (xy, str, labelOptions) { + var axis = this.axis, chart = axis.chart, label = defined(str) && labelOptions.enabled ? + chart.renderer + .text(str, xy.x, xy.y, labelOptions.useHTML) + .add(axis.labelGroup) : + null; + // Un-rotated length + if (label) { + // Without position absolute, IE export sometimes is wrong + if (!chart.styledMode) { + label.css(merge(labelOptions.style)); + } + label.textPxLength = label.getBBox().width; + } + return label; + }; + /** + * Destructor for the tick prototype + * + * @private + * @function Highcharts.Tick#destroy + * @return {void} + */ + Tick.prototype.destroy = function () { + destroyObjectProperties(this, this.axis); + }; + /** + * Gets the x and y positions for ticks in terms of pixels. + * + * @private + * @function Highcharts.Tick#getPosition + * + * @param {boolean} horiz + * Whether the tick is on an horizontal axis or not. + * + * @param {number} tickPos + * Position of the tick. + * + * @param {number} tickmarkOffset + * Tickmark offset for all ticks. + * + * @param {boolean} [old] + * Whether the axis has changed or not. + * + * @return {Highcharts.PositionObject} + * The tick position. + * + * @fires Highcharts.Tick#event:afterGetPosition + */ + Tick.prototype.getPosition = function (horiz, tickPos, tickmarkOffset, old) { + var axis = this.axis, chart = axis.chart, cHeight = (old && chart.oldChartHeight) || chart.chartHeight, pos; + pos = { + x: horiz ? + correctFloat(axis.translate(tickPos + tickmarkOffset, null, null, old) + + axis.transB) : + (axis.left + + axis.offset + + (axis.opposite ? + (((old && chart.oldChartWidth) || + chart.chartWidth) - + axis.right - + axis.left) : + 0)), + y: horiz ? + (cHeight - + axis.bottom + + axis.offset - + (axis.opposite ? axis.height : 0)) : + correctFloat(cHeight - + axis.translate(tickPos + tickmarkOffset, null, null, old) - + axis.transB) + }; + // Chrome workaround for #10516 + pos.y = clamp(pos.y, -1e5, 1e5); + fireEvent(this, 'afterGetPosition', { pos: pos }); + return pos; + }; + /** + * Get the x, y position of the tick label + * + * @private + * @return {Highcharts.PositionObject} + */ + Tick.prototype.getLabelPosition = function (x, y, label, horiz, labelOptions, tickmarkOffset, index, step) { + var axis = this.axis, transA = axis.transA, reversed = ( // #7911 + axis.isLinked && axis.linkedParent ? + axis.linkedParent.reversed : + axis.reversed), staggerLines = axis.staggerLines, rotCorr = axis.tickRotCorr || { x: 0, y: 0 }, yOffset = labelOptions.y, + // Adjust for label alignment if we use reserveSpace: true (#5286) + labelOffsetCorrection = (!horiz && !axis.reserveSpaceDefault ? + -axis.labelOffset * (axis.labelAlign === 'center' ? 0.5 : 1) : + 0), line, pos = {}; + if (!defined(yOffset)) { + if (axis.side === 0) { + yOffset = label.rotation ? -8 : -label.getBBox().height; + } + else if (axis.side === 2) { + yOffset = rotCorr.y + 8; + } + else { + // #3140, #3140 + yOffset = Math.cos(label.rotation * deg2rad) * + (rotCorr.y - label.getBBox(false, 0).height / 2); + } + } + x = x + + labelOptions.x + + labelOffsetCorrection + + rotCorr.x - + (tickmarkOffset && horiz ? + tickmarkOffset * transA * (reversed ? -1 : 1) : + 0); + y = y + yOffset - (tickmarkOffset && !horiz ? + tickmarkOffset * transA * (reversed ? 1 : -1) : 0); + // Correct for staggered labels + if (staggerLines) { + line = (index / (step || 1) % staggerLines); + if (axis.opposite) { + line = staggerLines - line - 1; + } + y += line * (axis.labelOffset / staggerLines); + } + pos.x = x; + pos.y = Math.round(y); + fireEvent(this, 'afterGetLabelPosition', { pos: pos, tickmarkOffset: tickmarkOffset, index: index }); + return pos; + }; + /** + * Get the offset height or width of the label + * + * @private + * @function Highcharts.Tick#getLabelSize + * @return {number} + */ + Tick.prototype.getLabelSize = function () { + return this.label ? + this.label.getBBox()[this.axis.horiz ? 'height' : 'width'] : + 0; + }; + /** + * Extendible method to return the path of the marker + * + * @private + * + */ + Tick.prototype.getMarkPath = function (x, y, tickLength, tickWidth, horiz, renderer) { + return renderer.crispLine([[ + 'M', + x, + y + ], [ + 'L', + x + (horiz ? 0 : -tickLength), + y + (horiz ? tickLength : 0) + ]], tickWidth); + }; + /** + * Handle the label overflow by adjusting the labels to the left and right + * edge, or hide them if they collide into the neighbour label. + * + * @private + * @function Highcharts.Tick#handleOverflow + * @param {Highcharts.PositionObject} xy + * @return {void} + */ + Tick.prototype.handleOverflow = function (xy) { + var tick = this, axis = this.axis, labelOptions = axis.options.labels, pxPos = xy.x, chartWidth = axis.chart.chartWidth, spacing = axis.chart.spacing, leftBound = pick(axis.labelLeft, Math.min(axis.pos, spacing[3])), rightBound = pick(axis.labelRight, Math.max(!axis.isRadial ? axis.pos + axis.len : 0, chartWidth - spacing[1])), label = this.label, rotation = this.rotation, factor = { + left: 0, + center: 0.5, + right: 1 + }[axis.labelAlign || label.attr('align')], labelWidth = label.getBBox().width, slotWidth = axis.getSlotWidth(tick), modifiedSlotWidth = slotWidth, xCorrection = factor, goRight = 1, leftPos, rightPos, textWidth, css = {}; + // Check if the label overshoots the chart spacing box. If it does, move + // it. If it now overshoots the slotWidth, add ellipsis. + if (!rotation && + pick(labelOptions.overflow, 'justify') === 'justify') { + leftPos = pxPos - factor * labelWidth; + rightPos = pxPos + (1 - factor) * labelWidth; + if (leftPos < leftBound) { + modifiedSlotWidth = + xy.x + modifiedSlotWidth * (1 - factor) - leftBound; + } + else if (rightPos > rightBound) { + modifiedSlotWidth = + rightBound - xy.x + modifiedSlotWidth * factor; + goRight = -1; + } + modifiedSlotWidth = Math.min(slotWidth, modifiedSlotWidth); // #4177 + if (modifiedSlotWidth < slotWidth && axis.labelAlign === 'center') { + xy.x += (goRight * + (slotWidth - + modifiedSlotWidth - + xCorrection * (slotWidth - Math.min(labelWidth, modifiedSlotWidth)))); + } + // If the label width exceeds the available space, set a text width + // to be picked up below. Also, if a width has been set before, we + // need to set a new one because the reported labelWidth will be + // limited by the box (#3938). + if (labelWidth > modifiedSlotWidth || + (axis.autoRotation && (label.styles || {}).width)) { + textWidth = modifiedSlotWidth; + } + // Add ellipsis to prevent rotated labels to be clipped against the edge + // of the chart + } + else if (rotation < 0 && + pxPos - factor * labelWidth < leftBound) { + textWidth = Math.round(pxPos / Math.cos(rotation * deg2rad) - leftBound); + } + else if (rotation > 0 && + pxPos + factor * labelWidth > rightBound) { + textWidth = Math.round((chartWidth - pxPos) / + Math.cos(rotation * deg2rad)); + } + if (textWidth) { + if (tick.shortenLabel) { + tick.shortenLabel(); + } + else { + css.width = Math.floor(textWidth) + 'px'; + if (!(labelOptions.style || {}).textOverflow) { + css.textOverflow = 'ellipsis'; + } + label.css(css); + } + } + }; + /** + * Try to replace the label if the same one already exists. + * + * @private + * @function Highcharts.Tick#moveLabel + * @param {string} str + * @param {Highcharts.XAxisLabelsOptions} labelOptions + * + * @return {void} + */ + Tick.prototype.moveLabel = function (str, labelOptions) { + var tick = this, label = tick.label, moved = false, xAxis = tick.axis, chart = xAxis.chart, labelPos, reversed = xAxis.reversed, inverted = chart.inverted, xPos, yPos; + if (label && label.textStr === str) { + tick.movedLabel = label; + moved = true; + delete tick.label; + } + else { // Find a label with the same string + objectEach(xAxis.ticks, function (currentTick) { + if (!moved && + !currentTick.isNew && + currentTick !== tick && + currentTick.label && + currentTick.label.textStr === str) { + tick.movedLabel = currentTick.label; + moved = true; + currentTick.labelPos = tick.movedLabel.xy; + delete currentTick.label; + } + }); + } + // Create new label if the actual one is moved + if (!moved && (tick.labelPos || label)) { + labelPos = tick.labelPos || label.xy; + xPos = inverted ? + labelPos.x : (reversed ? 0 : xAxis.width + xAxis.left); + yPos = inverted ? + (reversed ? (xAxis.width + xAxis.left) : 0) : labelPos.y; + tick.movedLabel = tick.createLabel({ x: xPos, y: yPos }, str, labelOptions); + if (tick.movedLabel) { + tick.movedLabel.attr({ opacity: 0 }); + } + } + }; + /** + * Put everything in place + * + * @private + * @param {number} index + * @param {boolean} [old] + * Use old coordinates to prepare an animation into new position + * @param {number} [opacity] + * @return {voids} + */ + Tick.prototype.render = function (index, old, opacity) { + var tick = this, axis = tick.axis, horiz = axis.horiz, pos = tick.pos, tickmarkOffset = pick(tick.tickmarkOffset, axis.tickmarkOffset), xy = tick.getPosition(horiz, pos, tickmarkOffset, old), x = xy.x, y = xy.y, reverseCrisp = ((horiz && x === axis.pos + axis.len) || + (!horiz && y === axis.pos)) ? -1 : 1; // #1480, #1687 + opacity = pick(opacity, 1); + this.isActive = true; + // Create the grid line + this.renderGridLine(old, opacity, reverseCrisp); + // create the tick mark + this.renderMark(xy, opacity, reverseCrisp); + // the label is created on init - now move it into place + this.renderLabel(xy, old, opacity, index); + tick.isNew = false; + fireEvent(this, 'afterRender'); + }; + /** + * Renders the gridLine. + * + * @private + * @param {boolean} old Whether or not the tick is old + * @param {number} opacity The opacity of the grid line + * @param {number} reverseCrisp Modifier for avoiding overlapping 1 or -1 + * @return {void} + */ + Tick.prototype.renderGridLine = function (old, opacity, reverseCrisp) { + var tick = this, axis = tick.axis, options = axis.options, gridLine = tick.gridLine, gridLinePath, attribs = {}, pos = tick.pos, type = tick.type, tickmarkOffset = pick(tick.tickmarkOffset, axis.tickmarkOffset), renderer = axis.chart.renderer, gridPrefix = type ? type + 'Grid' : 'grid', gridLineWidth = options[gridPrefix + 'LineWidth'], gridLineColor = options[gridPrefix + 'LineColor'], dashStyle = options[gridPrefix + 'LineDashStyle']; + if (!gridLine) { + if (!axis.chart.styledMode) { + attribs.stroke = gridLineColor; + attribs['stroke-width'] = gridLineWidth; + if (dashStyle) { + attribs.dashstyle = dashStyle; + } + } + if (!type) { + attribs.zIndex = 1; + } + if (old) { + opacity = 0; + } + /** + * The rendered grid line of the tick. + * @name Highcharts.Tick#gridLine + * @type {Highcharts.SVGElement|undefined} + */ + tick.gridLine = gridLine = renderer.path() + .attr(attribs) + .addClass('highcharts-' + (type ? type + '-' : '') + 'grid-line') + .add(axis.gridGroup); + } + if (gridLine) { + gridLinePath = axis.getPlotLinePath({ + value: pos + tickmarkOffset, + lineWidth: gridLine.strokeWidth() * reverseCrisp, + force: 'pass', + old: old + }); + // If the parameter 'old' is set, the current call will be followed + // by another call, therefore do not do any animations this time + if (gridLinePath) { + gridLine[old || tick.isNew ? 'attr' : 'animate']({ + d: gridLinePath, + opacity: opacity + }); + } + } + }; + /** + * Renders the tick mark. + * + * @private + * @param {Highcharts.PositionObject} xy The position vector of the mark + * @param {number} opacity The opacity of the mark + * @param {number} reverseCrisp Modifier for avoiding overlapping 1 or -1 + * @return {void} + */ + Tick.prototype.renderMark = function (xy, opacity, reverseCrisp) { + var tick = this, axis = tick.axis, options = axis.options, renderer = axis.chart.renderer, type = tick.type, tickPrefix = type ? type + 'Tick' : 'tick', tickSize = axis.tickSize(tickPrefix), mark = tick.mark, isNewMark = !mark, x = xy.x, y = xy.y, tickWidth = pick(options[tickPrefix + 'Width'], !type && axis.isXAxis ? 1 : 0), // X axis defaults to 1 + tickColor = options[tickPrefix + 'Color']; + if (tickSize) { + // negate the length + if (axis.opposite) { + tickSize[0] = -tickSize[0]; + } + // First time, create it + if (isNewMark) { + /** + * The rendered mark of the tick. + * @name Highcharts.Tick#mark + * @type {Highcharts.SVGElement|undefined} + */ + tick.mark = mark = renderer.path() + .addClass('highcharts-' + (type ? type + '-' : '') + 'tick') + .add(axis.axisGroup); + if (!axis.chart.styledMode) { + mark.attr({ + stroke: tickColor, + 'stroke-width': tickWidth + }); + } + } + mark[isNewMark ? 'attr' : 'animate']({ + d: tick.getMarkPath(x, y, tickSize[0], mark.strokeWidth() * reverseCrisp, axis.horiz, renderer), + opacity: opacity + }); + } + }; + /** + * Renders the tick label. + * Note: The label should already be created in init(), so it should only + * have to be moved into place. + * + * @private + * @param {Highcharts.PositionObject} xy The position vector of the label + * @param {boolean} old Whether or not the tick is old + * @param {number} opacity The opacity of the label + * @param {number} index The index of the tick + * @return {void} + */ + Tick.prototype.renderLabel = function (xy, old, opacity, index) { + var tick = this, axis = tick.axis, horiz = axis.horiz, options = axis.options, label = tick.label, labelOptions = options.labels, step = labelOptions.step, tickmarkOffset = pick(tick.tickmarkOffset, axis.tickmarkOffset), show = true, x = xy.x, y = xy.y; + if (label && isNumber(x)) { + label.xy = xy = tick.getLabelPosition(x, y, label, horiz, labelOptions, tickmarkOffset, index, step); + // Apply show first and show last. If the tick is both first and + // last, it is a single centered tick, in which case we show the + // label anyway (#2100). + if ((tick.isFirst && + !tick.isLast && + !pick(options.showFirstLabel, 1)) || + (tick.isLast && + !tick.isFirst && + !pick(options.showLastLabel, 1))) { + show = false; + // Handle label overflow and show or hide accordingly + } + else if (horiz && + !labelOptions.step && + !labelOptions.rotation && + !old && + opacity !== 0) { + tick.handleOverflow(xy); + } + // apply step + if (step && index % step) { + // show those indices dividable by step + show = false; + } + // Set the new position, and show or hide + if (show && isNumber(xy.y)) { + xy.opacity = opacity; + label[tick.isNewLabel ? 'attr' : 'animate'](xy); + tick.isNewLabel = false; + } + else { + label.attr('y', -9999); // #1338 + tick.isNewLabel = true; + } + } + }; + /** + * Replace labels with the moved ones to perform animation. Additionally + * destroy unused labels. + * + * @private + * @function Highcharts.Tick#replaceMovedLabel + * @return {void} + */ + Tick.prototype.replaceMovedLabel = function () { + var tick = this, label = tick.label, axis = tick.axis, reversed = axis.reversed, chart = tick.axis.chart, inverted = chart.inverted, x, y; + // Animate and destroy + if (label && !tick.isNew) { + x = inverted ? label.xy.x : (reversed ? axis.left : axis.width + axis.left); + y = inverted ? + (reversed ? axis.width + axis.top : axis.top) : + label.xy.y; + label.animate({ x: x, y: y, opacity: 0 }, void 0, label.destroy); + delete tick.label; + } + axis.isDirty = true; + tick.label = tick.movedLabel; + delete tick.movedLabel; + }; + return Tick; + }()); + H.Tick = Tick; + + return H.Tick; + }); + _registerModule(_modules, 'parts/Time.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (Highcharts, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Normalized interval. + * + * @interface Highcharts.TimeNormalizedObject + */ /** + * The count. + * + * @name Highcharts.TimeNormalizedObject#count + * @type {number} + */ /** + * The interval in axis values (ms). + * + * @name Highcharts.TimeNormalizedObject#unitRange + * @type {number} + */ + /** + * Function of an additional date format specifier. + * + * @callback Highcharts.TimeFormatCallbackFunction + * + * @param {number} timestamp + * The time to format. + * + * @return {string} + * The formatted portion of the date. + */ + /** + * Additonal time tick information. + * + * @interface Highcharts.TimeTicksInfoObject + * @extends Highcharts.TimeNormalizedObject + */ /** + * @name Highcharts.TimeTicksInfoObject#higherRanks + * @type {Array} + */ /** + * @name Highcharts.TimeTicksInfoObject#totalRange + * @type {number} + */ + /** + * Time ticks. + * + * @interface Highcharts.AxisTickPositionsArray + * @extends global.Array + */ /** + * @name Highcharts.AxisTickPositionsArray#info + * @type {Highcharts.TimeTicksInfoObject|undefined} + */ + /** + * A callback to return the time zone offset for a given datetime. It + * takes the timestamp in terms of milliseconds since January 1 1970, + * and returns the timezone offset in minutes. This provides a hook + * for drawing time based charts in specific time zones using their + * local DST crossover dates, with the help of external libraries. + * + * @callback Highcharts.TimezoneOffsetCallbackFunction + * + * @param {number} timestamp + * Timestamp in terms of milliseconds since January 1 1970. + * + * @return {number} + * Timezone offset in minutes. + */ + var defined = U.defined, error = U.error, extend = U.extend, isObject = U.isObject, merge = U.merge, objectEach = U.objectEach, pad = U.pad, pick = U.pick, splat = U.splat, timeUnits = U.timeUnits; + var H = Highcharts, win = H.win; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The Time class. Time settings are applied in general for each page using + * `Highcharts.setOptions`, or individually for each Chart item through the + * [time](https://api.highcharts.com/highcharts/time) options set. + * + * The Time object is available from {@link Highcharts.Chart#time}, + * which refers to `Highcharts.time` if no individual time settings are + * applied. + * + * @example + * // Apply time settings globally + * Highcharts.setOptions({ + * time: { + * timezone: 'Europe/London' + * } + * }); + * + * // Apply time settings by instance + * var chart = Highcharts.chart('container', { + * time: { + * timezone: 'America/New_York' + * }, + * series: [{ + * data: [1, 4, 3, 5] + * }] + * }); + * + * // Use the Time object + * console.log( + * 'Current time in New York', + * chart.time.dateFormat('%Y-%m-%d %H:%M:%S', Date.now()) + * ); + * + * @since 6.0.5 + * + * @class + * @name Highcharts.Time + * + * @param {Highcharts.TimeOptions} options + * Time options as defined in [chart.options.time](/highcharts/time). + */ + var Time = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Time(options) { + /* * + * + * Properties + * + * */ + this.options = {}; + this.useUTC = false; + this.variableTimezone = false; + this.Date = win.Date; + /** + * Get the time zone offset based on the current timezone information as + * set in the global options. + * + * @function Highcharts.Time#getTimezoneOffset + * + * @param {number} timestamp + * The JavaScript timestamp to inspect. + * + * @return {number} + * The timezone offset in minutes compared to UTC. + */ + this.getTimezoneOffset = this.timezoneOffsetFunction(); + this.update(options); + } + /* * + * + * Functions + * + * */ + /** + * Time units used in `Time.get` and `Time.set` + * + * @typedef {"Date"|"Day"|"FullYear"|"Hours"|"Milliseconds"|"Minutes"|"Month"|"Seconds"} Highcharts.TimeUnitValue + */ + /** + * Get the value of a date object in given units, and subject to the Time + * object's current timezone settings. This function corresponds directly to + * JavaScripts `Date.getXXX / Date.getUTCXXX`, so instead of calling + * `date.getHours()` or `date.getUTCHours()` we will call + * `time.get('Hours')`. + * + * @function Highcharts.Time#get + * + * @param {Highcharts.TimeUnitValue} unit + * @param {Date} date + * + * @return {number} + * The given time unit + */ + Time.prototype.get = function (unit, date) { + if (this.variableTimezone || this.timezoneOffset) { + var realMs = date.getTime(); + var ms = realMs - this.getTimezoneOffset(date); + date.setTime(ms); // Temporary adjust to timezone + var ret = date['getUTC' + unit](); + date.setTime(realMs); // Reset + return ret; + } + // UTC time with no timezone handling + if (this.useUTC) { + return date['getUTC' + unit](); + } + // Else, local time + return date['get' + unit](); + }; + /** + * Set the value of a date object in given units, and subject to the Time + * object's current timezone settings. This function corresponds directly to + * JavaScripts `Date.setXXX / Date.setUTCXXX`, so instead of calling + * `date.setHours(0)` or `date.setUTCHours(0)` we will call + * `time.set('Hours', 0)`. + * + * @function Highcharts.Time#set + * + * @param {Highcharts.TimeUnitValue} unit + * @param {Date} date + * @param {number} value + * + * @return {number} + * The epoch milliseconds of the updated date + */ + Time.prototype.set = function (unit, date, value) { + // UTC time with timezone handling + if (this.variableTimezone || this.timezoneOffset) { + // For lower order time units, just set it directly using UTC + // time + if (unit === 'Milliseconds' || + unit === 'Seconds' || + unit === 'Minutes') { + return date['setUTC' + unit](value); + } + // Higher order time units need to take the time zone into + // account + // Adjust by timezone + var offset = this.getTimezoneOffset(date); + var ms = date.getTime() - offset; + date.setTime(ms); + date['setUTC' + unit](value); + var newOffset = this.getTimezoneOffset(date); + ms = date.getTime() + newOffset; + return date.setTime(ms); + } + // UTC time with no timezone handling + if (this.useUTC) { + return date['setUTC' + unit](value); + } + // Else, local time + return date['set' + unit](value); + }; + /** + * Update the Time object with current options. It is called internally on + * initializing Highcharts, after running `Highcharts.setOptions` and on + * `Chart.update`. + * + * @private + * @function Highcharts.Time#update + * + * @param {Highcharts.TimeOptions} options + * + * @return {void} + */ + Time.prototype.update = function (options) { + var useUTC = pick(options && options.useUTC, true), time = this; + this.options = options = merge(true, this.options || {}, options); + // Allow using a different Date class + this.Date = options.Date || win.Date || Date; + this.useUTC = useUTC; + this.timezoneOffset = (useUTC && options.timezoneOffset); + this.getTimezoneOffset = this.timezoneOffsetFunction(); + /* + * The time object has options allowing for variable time zones, meaning + * the axis ticks or series data needs to consider this. + */ + this.variableTimezone = !!(!useUTC || + options.getTimezoneOffset || + options.timezone); + }; + /** + * Make a time and returns milliseconds. Interprets the inputs as UTC time, + * local time or a specific timezone time depending on the current time + * settings. + * + * @function Highcharts.Time#makeTime + * + * @param {number} year + * The year + * + * @param {number} month + * The month. Zero-based, so January is 0. + * + * @param {number} [date=1] + * The day of the month + * + * @param {number} [hours=0] + * The hour of the day, 0-23. + * + * @param {number} [minutes=0] + * The minutes + * + * @param {number} [seconds=0] + * The seconds + * + * @return {number} + * The time in milliseconds since January 1st 1970. + */ + Time.prototype.makeTime = function (year, month, date, hours, minutes, seconds) { + var d, offset, newOffset; + if (this.useUTC) { + d = this.Date.UTC.apply(0, arguments); + offset = this.getTimezoneOffset(d); + d += offset; + newOffset = this.getTimezoneOffset(d); + if (offset !== newOffset) { + d += newOffset - offset; + // A special case for transitioning from summer time to winter time. + // When the clock is set back, the same time is repeated twice, i.e. + // 02:30 am is repeated since the clock is set back from 3 am to + // 2 am. We need to make the same time as local Date does. + } + else if (offset - 36e5 === this.getTimezoneOffset(d - 36e5) && + !H.isSafari) { + d -= 36e5; + } + } + else { + d = new this.Date(year, month, pick(date, 1), pick(hours, 0), pick(minutes, 0), pick(seconds, 0)).getTime(); + } + return d; + }; + /** + * Sets the getTimezoneOffset function. If the `timezone` option is set, a + * default getTimezoneOffset function with that timezone is returned. If + * a `getTimezoneOffset` option is defined, it is returned. If neither are + * specified, the function using the `timezoneOffset` option or 0 offset is + * returned. + * + * @private + * @function Highcharts.Time#timezoneOffsetFunction + * + * @return {Function} + * A getTimezoneOffset function + */ + Time.prototype.timezoneOffsetFunction = function () { + var time = this, options = this.options, moment = win.moment; + if (!this.useUTC) { + return function (timestamp) { + return new Date(timestamp.toString()).getTimezoneOffset() * 60000; + }; + } + if (options.timezone) { + if (!moment) { + // getTimezoneOffset-function stays undefined because it depends + // on Moment.js + error(25); + } + else { + return function (timestamp) { + return -moment.tz(timestamp, options.timezone).utcOffset() * 60000; + }; + } + } + // If not timezone is set, look for the getTimezoneOffset callback + if (this.useUTC && options.getTimezoneOffset) { + return function (timestamp) { + return options.getTimezoneOffset(timestamp.valueOf()) * 60000; + }; + } + // Last, use the `timezoneOffset` option if set + return function () { + return (time.timezoneOffset || 0) * 60000; + }; + }; + /** + * Formats a JavaScript date timestamp (milliseconds since Jan 1st 1970) + * into a human readable date string. The available format keys are listed + * below. Additional formats can be given in the + * {@link Highcharts.dateFormats} hook. + * + * Supported format keys: + * - `%a`: Short weekday, like 'Mon' + * - `%A`: Long weekday, like 'Monday' + * - `%d`: Two digit day of the month, 01 to 31 + * - `%e`: Day of the month, 1 through 31 + * - `%w`: Day of the week, 0 through 6 + * - `%b`: Short month, like 'Jan' + * - `%B`: Long month, like 'January' + * - `%m`: Two digit month number, 01 through 12 + * - `%y`: Two digits year, like 09 for 2009 + * - `%Y`: Four digits year, like 2009 + * - `%H`: Two digits hours in 24h format, 00 through 23 + * - `%k`: Hours in 24h format, 0 through 23 + * - `%I`: Two digits hours in 12h format, 00 through 11 + * - `%l`: Hours in 12h format, 1 through 12 + * - `%M`: Two digits minutes, 00 through 59 + * - `%p`: Upper case AM or PM + * - `%P`: Lower case AM or PM + * - `%S`: Two digits seconds, 00 through 59 + * - `%L`: Milliseconds (naming from Ruby) + * + * @example + * const time = new Highcharts.Time(); + * const s = time.dateFormat('%Y-%m-%d %H:%M:%S', Date.UTC(2020, 0, 1)); + * console.log(s); // => 2020-01-01 00:00:00 + * + * @function Highcharts.Time#dateFormat + * + * @param {string} format + * The desired format where various time representations are + * prefixed with %. + * + * @param {number} timestamp + * The JavaScript timestamp. + * + * @param {boolean} [capitalize=false] + * Upper case first letter in the return. + * + * @return {string} + * The formatted date. + */ + Time.prototype.dateFormat = function (format, timestamp, capitalize) { + var _a; + if (!defined(timestamp) || isNaN(timestamp)) { + return ((_a = H.defaultOptions.lang) === null || _a === void 0 ? void 0 : _a.invalidDate) || ''; + } + format = pick(format, '%Y-%m-%d %H:%M:%S'); + var time = this, date = new this.Date(timestamp), + // get the basic time values + hours = this.get('Hours', date), day = this.get('Day', date), dayOfMonth = this.get('Date', date), month = this.get('Month', date), fullYear = this.get('FullYear', date), lang = H.defaultOptions.lang, langWeekdays = lang === null || lang === void 0 ? void 0 : lang.weekdays, shortWeekdays = lang === null || lang === void 0 ? void 0 : lang.shortWeekdays, + // List all format keys. Custom formats can be added from the + // outside. + replacements = extend({ + // Day + // Short weekday, like 'Mon' + a: shortWeekdays ? + shortWeekdays[day] : + langWeekdays[day].substr(0, 3), + // Long weekday, like 'Monday' + A: langWeekdays[day], + // Two digit day of the month, 01 to 31 + d: pad(dayOfMonth), + // Day of the month, 1 through 31 + e: pad(dayOfMonth, 2, ' '), + // Day of the week, 0 through 6 + w: day, + // Week (none implemented) + // 'W': weekNumber(), + // Month + // Short month, like 'Jan' + b: lang.shortMonths[month], + // Long month, like 'January' + B: lang.months[month], + // Two digit month number, 01 through 12 + m: pad(month + 1), + // Month number, 1 through 12 (#8150) + o: month + 1, + // Year + // Two digits year, like 09 for 2009 + y: fullYear.toString().substr(2, 2), + // Four digits year, like 2009 + Y: fullYear, + // Time + // Two digits hours in 24h format, 00 through 23 + H: pad(hours), + // Hours in 24h format, 0 through 23 + k: hours, + // Two digits hours in 12h format, 00 through 11 + I: pad((hours % 12) || 12), + // Hours in 12h format, 1 through 12 + l: (hours % 12) || 12, + // Two digits minutes, 00 through 59 + M: pad(this.get('Minutes', date)), + // Upper case AM or PM + p: hours < 12 ? 'AM' : 'PM', + // Lower case AM or PM + P: hours < 12 ? 'am' : 'pm', + // Two digits seconds, 00 through 59 + S: pad(date.getSeconds()), + // Milliseconds (naming from Ruby) + L: pad(Math.floor(timestamp % 1000), 3) + }, H.dateFormats); + // Do the replaces + objectEach(replacements, function (val, key) { + // Regex would do it in one line, but this is faster + while (format.indexOf('%' + key) !== -1) { + format = format.replace('%' + key, typeof val === 'function' ? val.call(time, timestamp) : val); + } + }); + // Optionally capitalize the string and return + return capitalize ? + (format.substr(0, 1).toUpperCase() + + format.substr(1)) : + format; + }; + /** + * Resolve legacy formats of dateTimeLabelFormats (strings and arrays) into + * an object. + * @private + * @param {string|Array|Highcharts.Dictionary} f - General format description + * @return {Highcharts.Dictionary} - The object definition + */ + Time.prototype.resolveDTLFormat = function (f) { + if (!isObject(f, true)) { // check for string or array + f = splat(f); + return { + main: f[0], + from: f[1], + to: f[2] + }; + } + return f; + }; + /** + * Return an array with time positions distributed on round time values + * right and right after min and max. Used in datetime axes as well as for + * grouping data on a datetime axis. + * + * @function Highcharts.Time#getTimeTicks + * + * @param {Highcharts.TimeNormalizedObject} normalizedInterval + * The interval in axis values (ms) and the count + * + * @param {number} [min] + * The minimum in axis values + * + * @param {number} [max] + * The maximum in axis values + * + * @param {number} [startOfWeek=1] + * + * @return {Highcharts.AxisTickPositionsArray} + */ + Time.prototype.getTimeTicks = function (normalizedInterval, min, max, startOfWeek) { + var time = this, Date = time.Date, tickPositions = [], i, higherRanks = {}, minYear, // used in months and years as a basis for Date.UTC() + // When crossing DST, use the max. Resolves #6278. + minDate = new Date(min), interval = normalizedInterval.unitRange, count = normalizedInterval.count || 1, variableDayLength, minDay; + startOfWeek = pick(startOfWeek, 1); + if (defined(min)) { // #1300 + time.set('Milliseconds', minDate, interval >= timeUnits.second ? + 0 : // #3935 + count * Math.floor(time.get('Milliseconds', minDate) / count)); // #3652, #3654 + if (interval >= timeUnits.second) { // second + time.set('Seconds', minDate, interval >= timeUnits.minute ? + 0 : // #3935 + count * Math.floor(time.get('Seconds', minDate) / count)); + } + if (interval >= timeUnits.minute) { // minute + time.set('Minutes', minDate, interval >= timeUnits.hour ? + 0 : + count * Math.floor(time.get('Minutes', minDate) / count)); + } + if (interval >= timeUnits.hour) { // hour + time.set('Hours', minDate, interval >= timeUnits.day ? + 0 : + count * Math.floor(time.get('Hours', minDate) / count)); + } + if (interval >= timeUnits.day) { // day + time.set('Date', minDate, interval >= timeUnits.month ? + 1 : + Math.max(1, count * Math.floor(time.get('Date', minDate) / count))); + } + if (interval >= timeUnits.month) { // month + time.set('Month', minDate, interval >= timeUnits.year ? 0 : + count * Math.floor(time.get('Month', minDate) / count)); + minYear = time.get('FullYear', minDate); + } + if (interval >= timeUnits.year) { // year + minYear -= minYear % count; + time.set('FullYear', minDate, minYear); + } + // week is a special case that runs outside the hierarchy + if (interval === timeUnits.week) { + // get start of current week, independent of count + minDay = time.get('Day', minDate); + time.set('Date', minDate, (time.get('Date', minDate) - + minDay + startOfWeek + + // We don't want to skip days that are before + // startOfWeek (#7051) + (minDay < startOfWeek ? -7 : 0))); + } + // Get basics for variable time spans + minYear = time.get('FullYear', minDate); + var minMonth = time.get('Month', minDate), minDateDate = time.get('Date', minDate), minHours = time.get('Hours', minDate); + // Redefine min to the floored/rounded minimum time (#7432) + min = minDate.getTime(); + // Handle local timezone offset + if (time.variableTimezone) { + // Detect whether we need to take the DST crossover into + // consideration. If we're crossing over DST, the day length may + // be 23h or 25h and we need to compute the exact clock time for + // each tick instead of just adding hours. This comes at a cost, + // so first we find out if it is needed (#4951). + variableDayLength = ( + // Long range, assume we're crossing over. + max - min > 4 * timeUnits.month || + // Short range, check if min and max are in different time + // zones. + time.getTimezoneOffset(min) !== + time.getTimezoneOffset(max)); + } + // Iterate and add tick positions at appropriate values + var t = minDate.getTime(); + i = 1; + while (t < max) { + tickPositions.push(t); + // if the interval is years, use Date.UTC to increase years + if (interval === timeUnits.year) { + t = time.makeTime(minYear + i * count, 0); + // if the interval is months, use Date.UTC to increase months + } + else if (interval === timeUnits.month) { + t = time.makeTime(minYear, minMonth + i * count); + // if we're using global time, the interval is not fixed as it + // jumps one hour at the DST crossover + } + else if (variableDayLength && + (interval === timeUnits.day || interval === timeUnits.week)) { + t = time.makeTime(minYear, minMonth, minDateDate + + i * count * (interval === timeUnits.day ? 1 : 7)); + } + else if (variableDayLength && + interval === timeUnits.hour && + count > 1) { + // make sure higher ranks are preserved across DST (#6797, + // #7621) + t = time.makeTime(minYear, minMonth, minDateDate, minHours + i * count); + // else, the interval is fixed and we use simple addition + } + else { + t += interval * count; + } + i++; + } + // push the last time + tickPositions.push(t); + // Handle higher ranks. Mark new days if the time is on midnight + // (#950, #1649, #1760, #3349). Use a reasonable dropout threshold + // to prevent looping over dense data grouping (#6156). + if (interval <= timeUnits.hour && tickPositions.length < 10000) { + tickPositions.forEach(function (t) { + if ( + // Speed optimization, no need to run dateFormat unless + // we're on a full or half hour + t % 1800000 === 0 && + // Check for local or global midnight + time.dateFormat('%H%M%S%L', t) === '000000000') { + higherRanks[t] = 'day'; + } + }); + } + } + // record information on the chosen unit - for dynamic label formatter + tickPositions.info = extend(normalizedInterval, { + higherRanks: higherRanks, + totalRange: interval * count + }); + return tickPositions; + }; + /* * + * + * Static Properties + * + * */ + /** + * Time options that can apply globally or to individual charts. These + * settings affect how `datetime` axes are laid out, how tooltips are + * formatted, how series + * [pointIntervalUnit](#plotOptions.series.pointIntervalUnit) works and how + * the Highstock range selector handles time. + * + * The common use case is that all charts in the same Highcharts object + * share the same time settings, in which case the global settings are set + * using `setOptions`. + * + * ```js + * // Apply time settings globally + * Highcharts.setOptions({ + * time: { + * timezone: 'Europe/London' + * } + * }); + * // Apply time settings by instance + * var chart = Highcharts.chart('container', { + * time: { + * timezone: 'America/New_York' + * }, + * series: [{ + * data: [1, 4, 3, 5] + * }] + * }); + * + * // Use the Time object + * console.log( + * 'Current time in New York', + * chart.time.dateFormat('%Y-%m-%d %H:%M:%S', Date.now()) + * ); + * ``` + * + * Since v6.0.5, the time options were moved from the `global` obect to the + * `time` object, and time options can be set on each individual chart. + * + * @sample {highcharts|highstock} + * highcharts/time/timezone/ + * Set the timezone globally + * @sample {highcharts} + * highcharts/time/individual/ + * Set the timezone per chart instance + * @sample {highstock} + * stock/time/individual/ + * Set the timezone per chart instance + * + * @since 6.0.5 + * @optionparent time + */ + Time.defaultOptions = { + /** + * A custom `Date` class for advanced date handling. For example, + * [JDate](https://github.com/tahajahangir/jdate) can be hooked in to + * handle Jalali dates. + * + * @type {*} + * @since 4.0.4 + * @product highcharts highstock gantt + */ + Date: void 0, + /** + * A callback to return the time zone offset for a given datetime. It + * takes the timestamp in terms of milliseconds since January 1 1970, + * and returns the timezone offset in minutes. This provides a hook + * for drawing time based charts in specific time zones using their + * local DST crossover dates, with the help of external libraries. + * + * @see [global.timezoneOffset](#global.timezoneOffset) + * + * @sample {highcharts|highstock} highcharts/time/gettimezoneoffset/ + * Use moment.js to draw Oslo time regardless of browser locale + * + * @type {Highcharts.TimezoneOffsetCallbackFunction} + * @since 4.1.0 + * @product highcharts highstock gantt + */ + getTimezoneOffset: void 0, + /** + * Requires [moment.js](https://momentjs.com/). If the timezone option + * is specified, it creates a default + * [getTimezoneOffset](#time.getTimezoneOffset) function that looks + * up the specified timezone in moment.js. If moment.js is not included, + * this throws a Highcharts error in the console, but does not crash the + * chart. + * + * @see [getTimezoneOffset](#time.getTimezoneOffset) + * + * @sample {highcharts|highstock} highcharts/time/timezone/ + * Europe/Oslo + * + * @type {string} + * @since 5.0.7 + * @product highcharts highstock gantt + */ + timezone: void 0, + /** + * The timezone offset in minutes. Positive values are west, negative + * values are east of UTC, as in the ECMAScript + * [getTimezoneOffset](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset) + * method. Use this to display UTC based data in a predefined time zone. + * + * @see [time.getTimezoneOffset](#time.getTimezoneOffset) + * + * @sample {highcharts|highstock} highcharts/time/timezoneoffset/ + * Timezone offset + * + * @since 3.0.8 + * @product highcharts highstock gantt + */ + timezoneOffset: 0, + /** + * Whether to use UTC time for axis scaling, tickmark placement and + * time display in `Highcharts.dateFormat`. Advantages of using UTC + * is that the time displays equally regardless of the user agent's + * time zone settings. Local time can be used when the data is loaded + * in real time or when correct Daylight Saving Time transitions are + * required. + * + * @sample {highcharts} highcharts/time/useutc-true/ + * True by default + * @sample {highcharts} highcharts/time/useutc-false/ + * False + */ + useUTC: true + }; + return Time; + }()); + H.Time = Time; + + return H.Time; + }); + _registerModule(_modules, 'parts/Options.js', [_modules['parts/Globals.js'], _modules['parts/Time.js'], _modules['parts/Color.js'], _modules['parts/Utilities.js']], function (H, Time, Color, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * @typedef {"plotBox"|"spacingBox"} Highcharts.ButtonRelativeToValue + */ + /** + * Gets fired when a series is added to the chart after load time, using the + * `addSeries` method. Returning `false` prevents the series from being added. + * + * @callback Highcharts.ChartAddSeriesCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart on which the event occured. + * + * @param {Highcharts.ChartAddSeriesEventObject} event + * The event that occured. + * + * @return {void} + */ + /** + * Contains common event information. Through the `options` property you can + * access the series options that were passed to the `addSeries` method. + * + * @interface Highcharts.ChartAddSeriesEventObject + */ /** + * The series options that were passed to the `addSeries` method. + * @name Highcharts.ChartAddSeriesEventObject#options + * @type {Highcharts.SeriesOptionsType} + */ /** + * Prevents the default behaviour of the event. + * @name Highcharts.ChartAddSeriesEventObject#preventDefault + * @type {Function} + */ /** + * The event target. + * @name Highcharts.ChartAddSeriesEventObject#target + * @type {Highcharts.Chart} + */ /** + * The event type. + * @name Highcharts.ChartAddSeriesEventObject#type + * @type {"addSeries"} + */ + /** + * Gets fired when clicking on the plot background. + * + * @callback Highcharts.ChartClickCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart on which the event occured. + * + * @param {Highcharts.PointerEventObject} event + * The event that occured. + * + * @return {void} + */ + /** + * Contains an axes of the clicked spot. + * + * @interface Highcharts.ChartClickEventAxisObject + */ /** + * Axis at the clicked spot. + * @name Highcharts.ChartClickEventAxisObject#axis + * @type {Highcharts.Axis} + */ /** + * Axis value at the clicked spot. + * @name Highcharts.ChartClickEventAxisObject#value + * @type {number} + */ + /** + * Contains information about the clicked spot on the chart. Remember the unit + * of a datetime axis is milliseconds since 1970-01-01 00:00:00. + * + * @interface Highcharts.ChartClickEventObject + * @extends Highcharts.PointerEventObject + */ /** + * Information about the x-axis on the clicked spot. + * @name Highcharts.ChartClickEventObject#xAxis + * @type {Array} + */ /** + * Information about the y-axis on the clicked spot. + * @name Highcharts.ChartClickEventObject#yAxis + * @type {Array} + */ /** + * Information about the z-axis on the clicked spot. + * @name Highcharts.ChartClickEventObject#zAxis + * @type {Array|undefined} + */ + /** + * Gets fired when the chart is finished loading. + * + * @callback Highcharts.ChartLoadCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart on which the event occured. + * + * @param {global.Event} event + * The event that occured. + * + * @return {void} + */ + /** + * Fires when the chart is redrawn, either after a call to `chart.redraw()` or + * after an axis, series or point is modified with the `redraw` option set to + * `true`. + * + * @callback Highcharts.ChartRedrawCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart on which the event occured. + * + * @param {global.Event} event + * The event that occured. + * + * @return {void} + */ + /** + * Gets fired after initial load of the chart (directly after the `load` event), + * and after each redraw (directly after the `redraw` event). + * + * @callback Highcharts.ChartRenderCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart on which the event occured. + * + * @param {global.Event} event + * The event that occured. + * + * @return {void} + */ + /** + * Gets fired when an area of the chart has been selected. The default action + * for the selection event is to zoom the chart to the selected area. It can be + * prevented by calling `event.preventDefault()` or return false. + * + * @callback Highcharts.ChartSelectionCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart on which the event occured. + * + * @param {global.ChartSelectionContextObject} event + * Event informations + * + * @return {boolean|undefined} + * Return false to prevent the default action, usually zoom. + */ + /** + * The primary axes are `xAxis[0]` and `yAxis[0]`. Remember the unit of a + * datetime axis is milliseconds since 1970-01-01 00:00:00. + * + * @interface Highcharts.ChartSelectionContextObject + * @extends global.Event + */ /** + * Arrays containing the axes of each dimension and each axis' min and max + * values. + * @name Highcharts.ChartSelectionContextObject#xAxis + * @type {Array} + */ /** + * Arrays containing the axes of each dimension and each axis' min and max + * values. + * @name Highcharts.ChartSelectionContextObject#yAxis + * @type {Array} + */ + /** + * Axis context of the selection. + * + * @interface Highcharts.ChartSelectionAxisContextObject + */ /** + * The selected Axis. + * @name Highcharts.ChartSelectionAxisContextObject#axis + * @type {Highcharts.Axis} + */ /** + * The maximum axis value, either automatic or set manually. + * @name Highcharts.ChartSelectionAxisContextObject#max + * @type {number} + */ /** + * The minimum axis value, either automatic or set manually. + * @name Highcharts.ChartSelectionAxisContextObject#min + * @type {number} + */ + var color = Color.parse; + var merge = U.merge; + var isTouchDevice = H.isTouchDevice, svg = H.svg; + /* ************************************************************************** * + * Handle the options * + * ************************************************************************** */ + /** + * Global default settings. + * + * @name Highcharts.defaultOptions + * @type {Highcharts.Options} + */ /** + * @optionparent + */ + H.defaultOptions = { + /** + * An array containing the default colors for the chart's series. When + * all colors are used, new colors are pulled from the start again. + * + * Default colors can also be set on a series or series.type basis, + * see [column.colors](#plotOptions.column.colors), + * [pie.colors](#plotOptions.pie.colors). + * + * In styled mode, the colors option doesn't exist. Instead, colors + * are defined in CSS and applied either through series or point class + * names, or through the [chart.colorCount](#chart.colorCount) option. + * + * + * ### Legacy + * + * In Highcharts 3.x, the default colors were: + * ```js + * colors: ['#2f7ed8', '#0d233a', '#8bbc21', '#910000', '#1aadce', + * '#492970', '#f28f43', '#77a1e5', '#c42525', '#a6c96a'] + * ``` + * + * In Highcharts 2.x, the default colors were: + * ```js + * colors: ['#4572A7', '#AA4643', '#89A54E', '#80699B', '#3D96AE', + * '#DB843D', '#92A8CD', '#A47D7C', '#B5CA92'] + * ``` + * + * @sample {highcharts} highcharts/chart/colors/ + * Assign a global color theme + * + * @type {Array} + * @default ["#7cb5ec", "#434348", "#90ed7d", "#f7a35c", "#8085e9", + * "#f15c80", "#e4d354", "#2b908f", "#f45b5b", "#91e8e1"] + */ + colors: '#7cb5ec #434348 #90ed7d #f7a35c #8085e9 #f15c80 #e4d354 #2b908f #f45b5b #91e8e1'.split(' '), + /** + * Styled mode only. Configuration object for adding SVG definitions for + * reusable elements. See [gradients, shadows and + * patterns](https://www.highcharts.com/docs/chart-design-and-style/gradients-shadows-and-patterns) + * for more information and code examples. + * + * @type {*} + * @since 5.0.0 + * @apioption defs + */ + /** + * @ignore-option + */ + symbols: ['circle', 'diamond', 'square', 'triangle', 'triangle-down'], + /** + * The language object is global and it can't be set on each chart + * initialization. Instead, use `Highcharts.setOptions` to set it before any + * chart is initialized. + * + * ```js + * Highcharts.setOptions({ + * lang: { + * months: [ + * 'Janvier', 'Février', 'Mars', 'Avril', + * 'Mai', 'Juin', 'Juillet', 'Août', + * 'Septembre', 'Octobre', 'Novembre', 'Décembre' + * ], + * weekdays: [ + * 'Dimanche', 'Lundi', 'Mardi', 'Mercredi', + * 'Jeudi', 'Vendredi', 'Samedi' + * ] + * } + * }); + * ``` + */ + lang: { + /** + * The loading text that appears when the chart is set into the loading + * state following a call to `chart.showLoading`. + */ + loading: 'Loading...', + /** + * An array containing the months names. Corresponds to the `%B` format + * in `Highcharts.dateFormat()`. + * + * @type {Array} + * @default ["January", "February", "March", "April", "May", "June", + * "July", "August", "September", "October", "November", + * "December"] + */ + months: [ + 'January', 'February', 'March', 'April', 'May', 'June', 'July', + 'August', 'September', 'October', 'November', 'December' + ], + /** + * An array containing the months names in abbreviated form. Corresponds + * to the `%b` format in `Highcharts.dateFormat()`. + * + * @type {Array} + * @default ["Jan", "Feb", "Mar", "Apr", "May", "Jun", + * "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] + */ + shortMonths: [ + 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', + 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' + ], + /** + * An array containing the weekday names. + * + * @type {Array} + * @default ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", + * "Friday", "Saturday"] + */ + weekdays: [ + 'Sunday', 'Monday', 'Tuesday', 'Wednesday', + 'Thursday', 'Friday', 'Saturday' + ], + /** + * Short week days, starting Sunday. If not specified, Highcharts uses + * the first three letters of the `lang.weekdays` option. + * + * @sample highcharts/lang/shortweekdays/ + * Finnish two-letter abbreviations + * + * @type {Array} + * @since 4.2.4 + * @apioption lang.shortWeekdays + */ + /** + * What to show in a date field for invalid dates. Defaults to an empty + * string. + * + * @type {string} + * @since 4.1.8 + * @product highcharts highstock + * @apioption lang.invalidDate + */ + /** + * The title appearing on hovering the zoom in button. The text itself + * defaults to "+" and can be changed in the button options. + * + * @type {string} + * @default Zoom in + * @product highmaps + * @apioption lang.zoomIn + */ + /** + * The title appearing on hovering the zoom out button. The text itself + * defaults to "-" and can be changed in the button options. + * + * @type {string} + * @default Zoom out + * @product highmaps + * @apioption lang.zoomOut + */ + /** + * The default decimal point used in the `Highcharts.numberFormat` + * method unless otherwise specified in the function arguments. + * + * @since 1.2.2 + */ + decimalPoint: '.', + /** + * [Metric prefixes](https://en.wikipedia.org/wiki/Metric_prefix) used + * to shorten high numbers in axis labels. Replacing any of the + * positions with `null` causes the full number to be written. Setting + * `numericSymbols` to `null` disables shortening altogether. + * + * @sample {highcharts} highcharts/lang/numericsymbols/ + * Replacing the symbols with text + * @sample {highstock} highcharts/lang/numericsymbols/ + * Replacing the symbols with text + * + * @type {Array} + * @default ["k", "M", "G", "T", "P", "E"] + * @since 2.3.0 + */ + numericSymbols: ['k', 'M', 'G', 'T', 'P', 'E'], + /** + * The magnitude of [numericSymbols](#lang.numericSymbol) replacements. + * Use 10000 for Japanese, Korean and various Chinese locales, which + * use symbols for 10^4, 10^8 and 10^12. + * + * @sample highcharts/lang/numericsymbolmagnitude/ + * 10000 magnitude for Japanese + * + * @type {number} + * @default 1000 + * @since 5.0.3 + * @apioption lang.numericSymbolMagnitude + */ + /** + * The text for the label appearing when a chart is zoomed. + * + * @since 1.2.4 + */ + resetZoom: 'Reset zoom', + /** + * The tooltip title for the label appearing when a chart is zoomed. + * + * @since 1.2.4 + */ + resetZoomTitle: 'Reset zoom level 1:1', + /** + * The default thousands separator used in the `Highcharts.numberFormat` + * method unless otherwise specified in the function arguments. Defaults + * to a single space character, which is recommended in + * [ISO 31-0](https://en.wikipedia.org/wiki/ISO_31-0#Numbers) and works + * across Anglo-American and continental European languages. + * + * @default \u0020 + * @since 1.2.2 + */ + thousandsSep: ' ' + }, + /** + * Global options that don't apply to each chart. These options, like + * the `lang` options, must be set using the `Highcharts.setOptions` + * method. + * + * ```js + * Highcharts.setOptions({ + * global: { + * useUTC: false + * } + * }); + * ``` + */ + /** + * _Canvg rendering for Android 2.x is removed as of Highcharts 5.0\. + * Use the [libURL](#exporting.libURL) option to configure exporting._ + * + * The URL to the additional file to lazy load for Android 2.x devices. + * These devices don't support SVG, so we download a helper file that + * contains [canvg](https://github.com/canvg/canvg), its dependency + * rbcolor, and our own CanVG Renderer class. To avoid hotlinking to + * our site, you can install canvas-tools.js on your own server and + * change this option accordingly. + * + * @deprecated + * + * @type {string} + * @default https://code.highcharts.com/{version}/modules/canvas-tools.js + * @product highcharts highmaps + * @apioption global.canvasToolsURL + */ + /** + * This option is deprecated since v6.0.5. Instead, use + * [time.useUTC](#time.useUTC) that supports individual time settings + * per chart. + * + * @deprecated + * + * @type {boolean} + * @apioption global.useUTC + */ + /** + * This option is deprecated since v6.0.5. Instead, use + * [time.Date](#time.Date) that supports individual time settings + * per chart. + * + * @deprecated + * + * @type {Function} + * @product highcharts highstock + * @apioption global.Date + */ + /** + * This option is deprecated since v6.0.5. Instead, use + * [time.getTimezoneOffset](#time.getTimezoneOffset) that supports + * individual time settings per chart. + * + * @deprecated + * + * @type {Function} + * @product highcharts highstock + * @apioption global.getTimezoneOffset + */ + /** + * This option is deprecated since v6.0.5. Instead, use + * [time.timezone](#time.timezone) that supports individual time + * settings per chart. + * + * @deprecated + * + * @type {string} + * @product highcharts highstock + * @apioption global.timezone + */ + /** + * This option is deprecated since v6.0.5. Instead, use + * [time.timezoneOffset](#time.timezoneOffset) that supports individual + * time settings per chart. + * + * @deprecated + * + * @type {number} + * @product highcharts highstock + * @apioption global.timezoneOffset + */ + global: {}, + time: Time.defaultOptions, + /** + * General options for the chart. + */ + chart: { + /** + * Default `mapData` for all series. If set to a string, it functions + * as an index into the `Highcharts.maps` array. Otherwise it is + * interpreted as map data. + * + * @see [mapData](#series.map.mapData) + * + * @sample maps/demo/geojson + * Loading geoJSON data + * @sample maps/chart/topojson + * Loading topoJSON converted to geoJSON + * + * @type {string|Array<*>} + * @since 5.0.0 + * @product highmaps + * @apioption chart.map + */ + /** + * Set lat/lon transformation definitions for the chart. If not defined, + * these are extracted from the map data. + * + * @type {*} + * @since 5.0.0 + * @product highmaps + * @apioption chart.mapTransforms + */ + /** + * When using multiple axis, the ticks of two or more opposite axes + * will automatically be aligned by adding ticks to the axis or axes + * with the least ticks, as if `tickAmount` were specified. + * + * This can be prevented by setting `alignTicks` to false. If the grid + * lines look messy, it's a good idea to hide them for the secondary + * axis by setting `gridLineWidth` to 0. + * + * If `startOnTick` or `endOnTick` in an Axis options are set to false, + * then the `alignTicks ` will be disabled for the Axis. + * + * Disabled for logarithmic axes. + * + * @sample {highcharts} highcharts/chart/alignticks-true/ + * True by default + * @sample {highcharts} highcharts/chart/alignticks-false/ + * False + * @sample {highstock} stock/chart/alignticks-true/ + * True by default + * @sample {highstock} stock/chart/alignticks-false/ + * False + * + * @type {boolean} + * @default true + * @product highcharts highstock gantt + * @apioption chart.alignTicks + */ + /** + * Set the overall animation for all chart updating. Animation can be + * disabled throughout the chart by setting it to false here. It can + * be overridden for each individual API method as a function parameter. + * The only animation not affected by this option is the initial series + * animation, see [plotOptions.series.animation]( + * #plotOptions.series.animation). + * + * The animation can either be set as a boolean or a configuration + * object. If `true`, it will use the 'swing' jQuery easing and a + * duration of 500 ms. If used as a configuration object, the following + * properties are supported: + * + * - **duration**: The duration of the animation in milliseconds. + * + * - **easing**: A string reference to an easing function set on the + * `Math` object. See + * [the easing demo](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-animation-easing/). + * + * When zooming on a series with less than 100 points, the chart redraw + * will be done with animation, but in case of more data points, it is + * necessary to set this option to ensure animation on zoom. + * + * @sample {highcharts} highcharts/chart/animation-none/ + * Updating with no animation + * @sample {highcharts} highcharts/chart/animation-duration/ + * With a longer duration + * @sample {highcharts} highcharts/chart/animation-easing/ + * With a jQuery UI easing + * @sample {highmaps} maps/chart/animation-none/ + * Updating with no animation + * @sample {highmaps} maps/chart/animation-duration/ + * With a longer duration + * + * @type {boolean|Highcharts.AnimationOptionsObject} + * @default undefined + * @apioption chart.animation + */ + /** + * A CSS class name to apply to the charts container `div`, allowing + * unique CSS styling for each chart. + * + * @type {string} + * @apioption chart.className + */ + /** + * Event listeners for the chart. + * + * @apioption chart.events + */ + /** + * Fires when a series is added to the chart after load time, using the + * `addSeries` method. One parameter, `event`, is passed to the + * function, containing common event information. Through + * `event.options` you can access the series options that were passed to + * the `addSeries` method. Returning false prevents the series from + * being added. + * + * @sample {highcharts} highcharts/chart/events-addseries/ + * Alert on add series + * @sample {highstock} stock/chart/events-addseries/ + * Alert on add series + * + * @type {Highcharts.ChartAddSeriesCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Chart + * @apioption chart.events.addSeries + */ + /** + * Fires when clicking on the plot background. One parameter, `event`, + * is passed to the function, containing common event information. + * + * Information on the clicked spot can be found through `event.xAxis` + * and `event.yAxis`, which are arrays containing the axes of each + * dimension and each axis' value at the clicked spot. The primary axes + * are `event.xAxis[0]` and `event.yAxis[0]`. Remember the unit of a + * datetime axis is milliseconds since 1970-01-01 00:00:00. + * + * ```js + * click: function(e) { + * console.log( + * Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', e.xAxis[0].value), + * e.yAxis[0].value + * ) + * } + * ``` + * + * @sample {highcharts} highcharts/chart/events-click/ + * Alert coordinates on click + * @sample {highcharts} highcharts/chart/events-container/ + * Alternatively, attach event to container + * @sample {highstock} stock/chart/events-click/ + * Alert coordinates on click + * @sample {highstock} highcharts/chart/events-container/ + * Alternatively, attach event to container + * @sample {highmaps} maps/chart/events-click/ + * Record coordinates on click + * @sample {highmaps} highcharts/chart/events-container/ + * Alternatively, attach event to container + * + * @type {Highcharts.ChartClickCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Chart + * @apioption chart.events.click + */ + /** + * Fires when the chart is finished loading. Since v4.2.2, it also waits + * for images to be loaded, for example from point markers. One + * parameter, `event`, is passed to the function, containing common + * event information. + * + * There is also a second parameter to the chart constructor where a + * callback function can be passed to be executed on chart.load. + * + * @sample {highcharts} highcharts/chart/events-load/ + * Alert on chart load + * @sample {highstock} stock/chart/events-load/ + * Alert on chart load + * @sample {highmaps} maps/chart/events-load/ + * Add series on chart load + * + * @type {Highcharts.ChartLoadCallbackFunction} + * @context Highcharts.Chart + * @apioption chart.events.load + */ + /** + * Fires when the chart is redrawn, either after a call to + * `chart.redraw()` or after an axis, series or point is modified with + * the `redraw` option set to `true`. One parameter, `event`, is passed + * to the function, containing common event information. + * + * @sample {highcharts} highcharts/chart/events-redraw/ + * Alert on chart redraw + * @sample {highstock} stock/chart/events-redraw/ + * Alert on chart redraw when adding a series or moving the + * zoomed range + * @sample {highmaps} maps/chart/events-redraw/ + * Set subtitle on chart redraw + * + * @type {Highcharts.ChartRedrawCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Chart + * @apioption chart.events.redraw + */ + /** + * Fires after initial load of the chart (directly after the `load` + * event), and after each redraw (directly after the `redraw` event). + * + * @type {Highcharts.ChartRenderCallbackFunction} + * @since 5.0.7 + * @context Highcharts.Chart + * @apioption chart.events.render + */ + /** + * Fires when an area of the chart has been selected. Selection is + * enabled by setting the chart's zoomType. One parameter, `event`, is + * passed to the function, containing common event information. The + * default action for the selection event is to zoom the chart to the + * selected area. It can be prevented by calling + * `event.preventDefault()` or return false. + * + * Information on the selected area can be found through `event.xAxis` + * and `event.yAxis`, which are arrays containing the axes of each + * dimension and each axis' min and max values. The primary axes are + * `event.xAxis[0]` and `event.yAxis[0]`. Remember the unit of a + * datetime axis is milliseconds since 1970-01-01 00:00:00. + * + * ```js + * selection: function(event) { + * // log the min and max of the primary, datetime x-axis + * console.log( + * Highcharts.dateFormat( + * '%Y-%m-%d %H:%M:%S', + * event.xAxis[0].min + * ), + * Highcharts.dateFormat( + * '%Y-%m-%d %H:%M:%S', + * event.xAxis[0].max + * ) + * ); + * // log the min and max of the y axis + * console.log(event.yAxis[0].min, event.yAxis[0].max); + * } + * ``` + * + * @sample {highcharts} highcharts/chart/events-selection/ + * Report on selection and reset + * @sample {highcharts} highcharts/chart/events-selection-points/ + * Select a range of points through a drag selection + * @sample {highstock} stock/chart/events-selection/ + * Report on selection and reset + * @sample {highstock} highcharts/chart/events-selection-points/ + * Select a range of points through a drag selection + * (Highcharts) + * + * @type {Highcharts.ChartSelectionCallbackFunction} + * @apioption chart.events.selection + */ + /** + * The margin between the outer edge of the chart and the plot area. + * The numbers in the array designate top, right, bottom and left + * respectively. Use the options `marginTop`, `marginRight`, + * `marginBottom` and `marginLeft` for shorthand setting of one option. + * + * By default there is no margin. The actual space is dynamically + * calculated from the offset of axis labels, axis title, title, + * subtitle and legend in addition to the `spacingTop`, `spacingRight`, + * `spacingBottom` and `spacingLeft` options. + * + * @sample {highcharts} highcharts/chart/margins-zero/ + * Zero margins + * @sample {highstock} stock/chart/margin-zero/ + * Zero margins + * + * @type {number|Array} + * @apioption chart.margin + */ + /** + * The margin between the bottom outer edge of the chart and the plot + * area. Use this to set a fixed pixel value for the margin as opposed + * to the default dynamic margin. See also `spacingBottom`. + * + * @sample {highcharts} highcharts/chart/marginbottom/ + * 100px bottom margin + * @sample {highstock} stock/chart/marginbottom/ + * 100px bottom margin + * @sample {highmaps} maps/chart/margin/ + * 100px margins + * + * @type {number} + * @since 2.0 + * @apioption chart.marginBottom + */ + /** + * The margin between the left outer edge of the chart and the plot + * area. Use this to set a fixed pixel value for the margin as opposed + * to the default dynamic margin. See also `spacingLeft`. + * + * @sample {highcharts} highcharts/chart/marginleft/ + * 150px left margin + * @sample {highstock} stock/chart/marginleft/ + * 150px left margin + * @sample {highmaps} maps/chart/margin/ + * 100px margins + * + * @type {number} + * @since 2.0 + * @apioption chart.marginLeft + */ + /** + * The margin between the right outer edge of the chart and the plot + * area. Use this to set a fixed pixel value for the margin as opposed + * to the default dynamic margin. See also `spacingRight`. + * + * @sample {highcharts} highcharts/chart/marginright/ + * 100px right margin + * @sample {highstock} stock/chart/marginright/ + * 100px right margin + * @sample {highmaps} maps/chart/margin/ + * 100px margins + * + * @type {number} + * @since 2.0 + * @apioption chart.marginRight + */ + /** + * The margin between the top outer edge of the chart and the plot area. + * Use this to set a fixed pixel value for the margin as opposed to + * the default dynamic margin. See also `spacingTop`. + * + * @sample {highcharts} highcharts/chart/margintop/ 100px top margin + * @sample {highstock} stock/chart/margintop/ + * 100px top margin + * @sample {highmaps} maps/chart/margin/ + * 100px margins + * + * @type {number} + * @since 2.0 + * @apioption chart.marginTop + */ + /** + * Callback function to override the default function that formats all + * the numbers in the chart. Returns a string with the formatted number. + * + * @sample highcharts/members/highcharts-numberformat + * Arabic digits in Highcharts + * @type {Highcharts.NumberFormatterCallbackFunction} + * @since 8.0.0 + * @apioption chart.numberFormatter + */ + /** + * Allows setting a key to switch between zooming and panning. Can be + * one of `alt`, `ctrl`, `meta` (the command key on Mac and Windows + * key on Windows) or `shift`. The keys are mapped directly to the key + * properties of the click event argument (`event.altKey`, + * `event.ctrlKey`, `event.metaKey` and `event.shiftKey`). + * + * @type {string} + * @since 4.0.3 + * @product highcharts gantt + * @validvalue ["alt", "ctrl", "meta", "shift"] + * @apioption chart.panKey + */ + /** + * Allow panning in a chart. Best used with [panKey](#chart.panKey) + * to combine zooming and panning. + * + * On touch devices, when the [tooltip.followTouchMove]( + * #tooltip.followTouchMove) option is `true` (default), panning + * requires two fingers. To allow panning with one finger, set + * `followTouchMove` to `false`. + * + * @sample {highcharts} highcharts/chart/pankey/ Zooming and panning + * @sample {highstock} stock/chart/panning/ Zooming and xy panning + * + * @product highcharts highstock gantt + * @apioption chart.panning + */ + /** + * Enable or disable chart panning. + * + * @type {boolean} + * @default {highcharts} false + * @default {highstock} true + * @apioption chart.panning.enabled + */ + /** + * Decides in what dimensions the user can pan the chart. Can be + * one of `x`, `y`, or `xy`. + * + * @sample {highcharts} highcharts/chart/panning-type + * Zooming and xy panning + * + * @type {string} + * @validvalue ["x", "y", "xy"] + * @default x + * @apioption chart.panning.type + */ + /** + * Equivalent to [zoomType](#chart.zoomType), but for multitouch + * gestures only. By default, the `pinchType` is the same as the + * `zoomType` setting. However, pinching can be enabled separately in + * some cases, for example in stock charts where a mouse drag pans the + * chart, while pinching is enabled. When [tooltip.followTouchMove]( + * #tooltip.followTouchMove) is true, pinchType only applies to + * two-finger touches. + * + * @type {string} + * @default {highcharts} undefined + * @default {highstock} x + * @since 3.0 + * @product highcharts highstock gantt + * @validvalue ["x", "y", "xy"] + * @apioption chart.pinchType + */ + /** + * Whether to apply styled mode. When in styled mode, no presentational + * attributes or CSS are applied to the chart SVG. Instead, CSS rules + * are required to style the chart. The default style sheet is + * available from `https://code.highcharts.com/css/highcharts.css`. + * + * @type {boolean} + * @default false + * @since 7.0 + * @apioption chart.styledMode + */ + styledMode: false, + /** + * The corner radius of the outer chart border. + * + * @sample {highcharts} highcharts/chart/borderradius/ + * 20px radius + * @sample {highstock} stock/chart/border/ + * 10px radius + * @sample {highmaps} maps/chart/border/ + * Border options + * + */ + borderRadius: 0, + /** + * In styled mode, this sets how many colors the class names + * should rotate between. With ten colors, series (or points) are + * given class names like `highcharts-color-0`, `highcharts-color-0` + * [...] `highcharts-color-9`. The equivalent in non-styled mode + * is to set colors using the [colors](#colors) setting. + * + * @since 5.0.0 + */ + colorCount: 10, + /** + * Alias of `type`. + * + * @sample {highcharts} highcharts/chart/defaultseriestype/ + * Bar + * + * @deprecated + * + * @product highcharts + */ + defaultSeriesType: 'line', + /** + * If true, the axes will scale to the remaining visible series once + * one series is hidden. If false, hiding and showing a series will + * not affect the axes or the other series. For stacks, once one series + * within the stack is hidden, the rest of the stack will close in + * around it even if the axis is not affected. + * + * @sample {highcharts} highcharts/chart/ignorehiddenseries-true/ + * True by default + * @sample {highcharts} highcharts/chart/ignorehiddenseries-false/ + * False + * @sample {highcharts} highcharts/chart/ignorehiddenseries-true-stacked/ + * True with stack + * @sample {highstock} stock/chart/ignorehiddenseries-true/ + * True by default + * @sample {highstock} stock/chart/ignorehiddenseries-false/ + * False + * + * @since 1.2.0 + * @product highcharts highstock gantt + */ + ignoreHiddenSeries: true, + /** + * Whether to invert the axes so that the x axis is vertical and y axis + * is horizontal. When `true`, the x axis is [reversed](#xAxis.reversed) + * by default. + * + * @productdesc {highcharts} + * If a bar series is present in the chart, it will be inverted + * automatically. Inverting the chart doesn't have an effect if there + * are no cartesian series in the chart, or if the chart is + * [polar](#chart.polar). + * + * @sample {highcharts} highcharts/chart/inverted/ + * Inverted line + * @sample {highstock} stock/navigator/inverted/ + * Inverted stock chart + * + * @type {boolean} + * @default false + * @product highcharts highstock gantt + * @apioption chart.inverted + */ + /** + * The distance between the outer edge of the chart and the content, + * like title or legend, or axis title and labels if present. The + * numbers in the array designate top, right, bottom and left + * respectively. Use the options spacingTop, spacingRight, spacingBottom + * and spacingLeft options for shorthand setting of one option. + * + * @type {Array} + * @see [chart.margin](#chart.margin) + * @default [10, 10, 15, 10] + * @since 3.0.6 + */ + spacing: [10, 10, 15, 10], + /** + * The button that appears after a selection zoom, allowing the user + * to reset zoom. + */ + resetZoomButton: { + /** + * What frame the button placement should be related to. Can be + * either `plotBox` or `spacingBox`. + * + * @sample {highcharts} highcharts/chart/resetzoombutton-relativeto/ + * Relative to the chart + * @sample {highstock} highcharts/chart/resetzoombutton-relativeto/ + * Relative to the chart + * + * @type {Highcharts.ButtonRelativeToValue} + * @default plot + * @since 2.2 + * @apioption chart.resetZoomButton.relativeTo + */ + /** + * A collection of attributes for the button. The object takes SVG + * attributes like `fill`, `stroke`, `stroke-width` or `r`, the + * border radius. The theme also supports `style`, a collection of + * CSS properties for the text. Equivalent attributes for the hover + * state are given in `theme.states.hover`. + * + * @sample {highcharts} highcharts/chart/resetzoombutton-theme/ + * Theming the button + * @sample {highstock} highcharts/chart/resetzoombutton-theme/ + * Theming the button + * + * @type {Highcharts.SVGAttributes} + * @since 2.2 + */ + theme: { + /** @internal */ + zIndex: 6 + }, + /** + * The position of the button. + * + * @sample {highcharts} highcharts/chart/resetzoombutton-position/ + * Above the plot area + * @sample {highstock} highcharts/chart/resetzoombutton-position/ + * Above the plot area + * @sample {highmaps} highcharts/chart/resetzoombutton-position/ + * Above the plot area + * + * @type {Highcharts.AlignObject} + * @since 2.2 + */ + position: { + /** + * The horizontal alignment of the button. + */ + align: 'right', + /** + * The horizontal offset of the button. + */ + x: -10, + /** + * The vertical alignment of the button. + * + * @type {Highcharts.VerticalAlignValue} + * @default top + * @apioption chart.resetZoomButton.position.verticalAlign + */ + /** + * The vertical offset of the button. + */ + y: 10 + } + }, + /** + * The pixel width of the plot area border. + * + * @sample {highcharts} highcharts/chart/plotborderwidth/ + * 1px border + * @sample {highstock} stock/chart/plotborder/ + * 2px border + * @sample {highmaps} maps/chart/plotborder/ + * Plot border options + * + * @type {number} + * @default 0 + * @apioption chart.plotBorderWidth + */ + /** + * Whether to apply a drop shadow to the plot area. Requires that + * plotBackgroundColor be set. The shadow can be an object configuration + * containing `color`, `offsetX`, `offsetY`, `opacity` and `width`. + * + * @sample {highcharts} highcharts/chart/plotshadow/ + * Plot shadow + * @sample {highstock} stock/chart/plotshadow/ + * Plot shadow + * @sample {highmaps} maps/chart/plotborder/ + * Plot border options + * + * @type {boolean|Highcharts.CSSObject} + * @default false + * @apioption chart.plotShadow + */ + /** + * When true, cartesian charts like line, spline, area and column are + * transformed into the polar coordinate system. This produces _polar + * charts_, also known as _radar charts_. + * + * @sample {highcharts} highcharts/demo/polar/ + * Polar chart + * @sample {highcharts} highcharts/demo/polar-wind-rose/ + * Wind rose, stacked polar column chart + * @sample {highcharts} highcharts/demo/polar-spider/ + * Spider web chart + * @sample {highcharts} highcharts/parallel-coordinates/polar/ + * Star plot, multivariate data in a polar chart + * + * @type {boolean} + * @default false + * @since 2.3.0 + * @product highcharts + * @requires highcharts-more + * @apioption chart.polar + */ + /** + * Whether to reflow the chart to fit the width of the container div + * on resizing the window. + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * True by default + * @sample {highcharts} highcharts/chart/reflow-false/ + * False + * @sample {highstock} stock/chart/reflow-true/ + * True by default + * @sample {highstock} stock/chart/reflow-false/ + * False + * @sample {highmaps} maps/chart/reflow-true/ + * True by default + * @sample {highmaps} maps/chart/reflow-false/ + * False + * + * @type {boolean} + * @default true + * @since 2.1 + * @apioption chart.reflow + */ + /** + * The HTML element where the chart will be rendered. If it is a string, + * the element by that id is used. The HTML element can also be passed + * by direct reference, or as the first argument of the chart + * constructor, in which case the option is not needed. + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * String + * @sample {highcharts} highcharts/chart/renderto-object/ + * Object reference + * @sample {highcharts} highcharts/chart/renderto-jquery/ + * Object reference through jQuery + * @sample {highstock} stock/chart/renderto-string/ + * String + * @sample {highstock} stock/chart/renderto-object/ + * Object reference + * @sample {highstock} stock/chart/renderto-jquery/ + * Object reference through jQuery + * + * @type {string|Highcharts.HTMLDOMElement} + * @apioption chart.renderTo + */ + /** + * The background color of the marker square when selecting (zooming + * in on) an area of the chart. + * + * @see In styled mode, the selection marker fill is set with the + * `.highcharts-selection-marker` class. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default rgba(51,92,173,0.25) + * @since 2.1.7 + * @apioption chart.selectionMarkerFill + */ + /** + * Whether to apply a drop shadow to the outer chart area. Requires + * that backgroundColor be set. The shadow can be an object + * configuration containing `color`, `offsetX`, `offsetY`, `opacity` and + * `width`. + * + * @sample {highcharts} highcharts/chart/shadow/ + * Shadow + * @sample {highstock} stock/chart/shadow/ + * Shadow + * @sample {highmaps} maps/chart/border/ + * Chart border and shadow + * + * @type {boolean|Highcharts.CSSObject} + * @default false + * @apioption chart.shadow + */ + /** + * Whether to show the axes initially. This only applies to empty charts + * where series are added dynamically, as axes are automatically added + * to cartesian series. + * + * @sample {highcharts} highcharts/chart/showaxes-false/ + * False by default + * @sample {highcharts} highcharts/chart/showaxes-true/ + * True + * + * @type {boolean} + * @since 1.2.5 + * @product highcharts gantt + * @apioption chart.showAxes + */ + /** + * The space between the bottom edge of the chart and the content (plot + * area, axis title and labels, title, subtitle or legend in top + * position). + * + * @sample {highcharts} highcharts/chart/spacingbottom/ + * Spacing bottom set to 100 + * @sample {highstock} stock/chart/spacingbottom/ + * Spacing bottom set to 100 + * @sample {highmaps} maps/chart/spacing/ + * Spacing 100 all around + * + * @type {number} + * @default 15 + * @since 2.1 + * @apioption chart.spacingBottom + */ + /** + * The space between the left edge of the chart and the content (plot + * area, axis title and labels, title, subtitle or legend in top + * position). + * + * @sample {highcharts} highcharts/chart/spacingleft/ + * Spacing left set to 100 + * @sample {highstock} stock/chart/spacingleft/ + * Spacing left set to 100 + * @sample {highmaps} maps/chart/spacing/ + * Spacing 100 all around + * + * @type {number} + * @default 10 + * @since 2.1 + * @apioption chart.spacingLeft + */ + /** + * The space between the right edge of the chart and the content (plot + * area, axis title and labels, title, subtitle or legend in top + * position). + * + * @sample {highcharts} highcharts/chart/spacingright-100/ + * Spacing set to 100 + * @sample {highcharts} highcharts/chart/spacingright-legend/ + * Legend in right position with default spacing + * @sample {highstock} stock/chart/spacingright/ + * Spacing set to 100 + * @sample {highmaps} maps/chart/spacing/ + * Spacing 100 all around + * + * @type {number} + * @default 10 + * @since 2.1 + * @apioption chart.spacingRight + */ + /** + * The space between the top edge of the chart and the content (plot + * area, axis title and labels, title, subtitle or legend in top + * position). + * + * @sample {highcharts} highcharts/chart/spacingtop-100/ + * A top spacing of 100 + * @sample {highcharts} highcharts/chart/spacingtop-10/ + * Floating chart title makes the plot area align to the default + * spacingTop of 10. + * @sample {highstock} stock/chart/spacingtop/ + * A top spacing of 100 + * @sample {highmaps} maps/chart/spacing/ + * Spacing 100 all around + * + * @type {number} + * @default 10 + * @since 2.1 + * @apioption chart.spacingTop + */ + /** + * Additional CSS styles to apply inline to the container `div`. Note + * that since the default font styles are applied in the renderer, it + * is ignorant of the individual chart options and must be set globally. + * + * @see In styled mode, general chart styles can be set with the + * `.highcharts-root` class. + * @sample {highcharts} highcharts/chart/style-serif-font/ + * Using a serif type font + * @sample {highcharts} highcharts/css/em/ + * Styled mode with relative font sizes + * @sample {highstock} stock/chart/style/ + * Using a serif type font + * @sample {highmaps} maps/chart/style-serif-font/ + * Using a serif type font + * + * @type {Highcharts.CSSObject} + * @default {"fontFamily": "\"Lucida Grande\", \"Lucida Sans Unicode\", Verdana, Arial, Helvetica, sans-serif","fontSize":"12px"} + * @apioption chart.style + */ + /** + * The default series type for the chart. Can be any of the chart types + * listed under [plotOptions](#plotOptions) and [series](#series) or can + * be a series provided by an additional module. + * + * In TypeScript this option has no effect in sense of typing and + * instead the `type` option must always be set in the series. + * + * @sample {highcharts} highcharts/chart/type-bar/ + * Bar + * @sample {highstock} stock/chart/type/ + * Areaspline + * @sample {highmaps} maps/chart/type-mapline/ + * Mapline + * + * @type {string} + * @default {highcharts} line + * @default {highstock} line + * @default {highmaps} map + * @since 2.1.0 + * @apioption chart.type + */ + /** + * Decides in what dimensions the user can zoom by dragging the mouse. + * Can be one of `x`, `y` or `xy`. + * + * @see [panKey](#chart.panKey) + * + * @sample {highcharts} highcharts/chart/zoomtype-none/ + * None by default + * @sample {highcharts} highcharts/chart/zoomtype-x/ + * X + * @sample {highcharts} highcharts/chart/zoomtype-y/ + * Y + * @sample {highcharts} highcharts/chart/zoomtype-xy/ + * Xy + * @sample {highstock} stock/demo/basic-line/ + * None by default + * @sample {highstock} stock/chart/zoomtype-x/ + * X + * @sample {highstock} stock/chart/zoomtype-y/ + * Y + * @sample {highstock} stock/chart/zoomtype-xy/ + * Xy + * + * @type {string} + * @product highcharts highstock gantt + * @validvalue ["x", "y", "xy"] + * @apioption chart.zoomType + */ + /** + * An explicit width for the chart. By default (when `null`) the width + * is calculated from the offset width of the containing element. + * + * @sample {highcharts} highcharts/chart/width/ + * 800px wide + * @sample {highstock} stock/chart/width/ + * 800px wide + * @sample {highmaps} maps/chart/size/ + * Chart with explicit size + * + * @type {null|number|string} + */ + width: null, + /** + * An explicit height for the chart. If a _number_, the height is + * given in pixels. If given a _percentage string_ (for example + * `'56%'`), the height is given as the percentage of the actual chart + * width. This allows for preserving the aspect ratio across responsive + * sizes. + * + * By default (when `null`) the height is calculated from the offset + * height of the containing element, or 400 pixels if the containing + * element's height is 0. + * + * @sample {highcharts} highcharts/chart/height/ + * 500px height + * @sample {highstock} stock/chart/height/ + * 300px height + * @sample {highmaps} maps/chart/size/ + * Chart with explicit size + * @sample highcharts/chart/height-percent/ + * Highcharts with percentage height + * + * @type {null|number|string} + */ + height: null, + /** + * The color of the outer chart border. + * + * @see In styled mode, the stroke is set with the + * `.highcharts-background` class. + * + * @sample {highcharts} highcharts/chart/bordercolor/ + * Brown border + * @sample {highstock} stock/chart/border/ + * Brown border + * @sample {highmaps} maps/chart/border/ + * Border options + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + borderColor: '#335cad', + /** + * The pixel width of the outer chart border. + * + * @see In styled mode, the stroke is set with the + * `.highcharts-background` class. + * + * @sample {highcharts} highcharts/chart/borderwidth/ + * 5px border + * @sample {highstock} stock/chart/border/ + * 2px border + * @sample {highmaps} maps/chart/border/ + * Border options + * + * @type {number} + * @default 0 + * @apioption chart.borderWidth + */ + /** + * The background color or gradient for the outer chart area. + * + * @see In styled mode, the background is set with the + * `.highcharts-background` class. + * + * @sample {highcharts} highcharts/chart/backgroundcolor-color/ + * Color + * @sample {highcharts} highcharts/chart/backgroundcolor-gradient/ + * Gradient + * @sample {highstock} stock/chart/backgroundcolor-color/ + * Color + * @sample {highstock} stock/chart/backgroundcolor-gradient/ + * Gradient + * @sample {highmaps} maps/chart/backgroundcolor-color/ + * Color + * @sample {highmaps} maps/chart/backgroundcolor-gradient/ + * Gradient + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + backgroundColor: '#ffffff', + /** + * The background color or gradient for the plot area. + * + * @see In styled mode, the plot background is set with the + * `.highcharts-plot-background` class. + * + * @sample {highcharts} highcharts/chart/plotbackgroundcolor-color/ + * Color + * @sample {highcharts} highcharts/chart/plotbackgroundcolor-gradient/ + * Gradient + * @sample {highstock} stock/chart/plotbackgroundcolor-color/ + * Color + * @sample {highstock} stock/chart/plotbackgroundcolor-gradient/ + * Gradient + * @sample {highmaps} maps/chart/plotbackgroundcolor-color/ + * Color + * @sample {highmaps} maps/chart/plotbackgroundcolor-gradient/ + * Gradient + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption chart.plotBackgroundColor + */ + /** + * The URL for an image to use as the plot background. To set an image + * as the background for the entire chart, set a CSS background image + * to the container element. Note that for the image to be applied to + * exported charts, its URL needs to be accessible by the export server. + * + * @see In styled mode, a plot background image can be set with the + * `.highcharts-plot-background` class and a [custom pattern]( + * https://www.highcharts.com/docs/chart-design-and-style/ + * gradients-shadows-and-patterns). + * + * @sample {highcharts} highcharts/chart/plotbackgroundimage/ + * Skies + * @sample {highstock} stock/chart/plotbackgroundimage/ + * Skies + * + * @type {string} + * @apioption chart.plotBackgroundImage + */ + /** + * The color of the inner chart or plot area border. + * + * @see In styled mode, a plot border stroke can be set with the + * `.highcharts-plot-border` class. + * + * @sample {highcharts} highcharts/chart/plotbordercolor/ + * Blue border + * @sample {highstock} stock/chart/plotborder/ + * Blue border + * @sample {highmaps} maps/chart/plotborder/ + * Plot border options + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + plotBorderColor: '#cccccc' + }, + /** + * The chart's main title. + * + * @sample {highmaps} maps/title/title/ + * Title options demonstrated + */ + title: { + /** + * When the title is floating, the plot area will not move to make space + * for it. + * + * @sample {highcharts} highcharts/chart/zoomtype-none/ + * False by default + * @sample {highcharts} highcharts/title/floating/ + * True - title on top of the plot area + * @sample {highstock} stock/chart/title-floating/ + * True - title on top of the plot area + * + * @type {boolean} + * @default false + * @since 2.1 + * @apioption title.floating + */ + /** + * CSS styles for the title. Use this for font styling, but use `align`, + * `x` and `y` for text alignment. + * + * In styled mode, the title style is given in the `.highcharts-title` + * class. + * + * @sample {highcharts} highcharts/title/style/ + * Custom color and weight + * @sample {highstock} stock/chart/title-style/ + * Custom color and weight + * @sample highcharts/css/titles/ + * Styled mode + * + * @type {Highcharts.CSSObject} + * @default {highcharts|highmaps} { "color": "#333333", "fontSize": "18px" } + * @default {highstock} { "color": "#333333", "fontSize": "16px" } + * @apioption title.style + */ + /** + * Whether to + * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the text. + * + * @type {boolean} + * @default false + * @apioption title.useHTML + */ + /** + * The vertical alignment of the title. Can be one of `"top"`, + * `"middle"` and `"bottom"`. When a value is given, the title behaves + * as if [floating](#title.floating) were `true`. + * + * @sample {highcharts} highcharts/title/verticalalign/ + * Chart title in bottom right corner + * @sample {highstock} stock/chart/title-verticalalign/ + * Chart title in bottom right corner + * + * @type {Highcharts.VerticalAlignValue} + * @since 2.1 + * @apioption title.verticalAlign + */ + /** + * The x position of the title relative to the alignment within + * `chart.spacingLeft` and `chart.spacingRight`. + * + * @sample {highcharts} highcharts/title/align/ + * Aligned to the plot area (x = 70px = margin left - spacing + * left) + * @sample {highstock} stock/chart/title-align/ + * Aligned to the plot area (x = 50px = margin left - spacing + * left) + * + * @type {number} + * @default 0 + * @since 2.0 + * @apioption title.x + */ + /** + * The y position of the title relative to the alignment within + * [chart.spacingTop](#chart.spacingTop) and [chart.spacingBottom]( + * #chart.spacingBottom). By default it depends on the font size. + * + * @sample {highcharts} highcharts/title/y/ + * Title inside the plot area + * @sample {highstock} stock/chart/title-verticalalign/ + * Chart title in bottom right corner + * + * @type {number} + * @since 2.0 + * @apioption title.y + */ + /** + * The title of the chart. To disable the title, set the `text` to + * `undefined`. + * + * @sample {highcharts} highcharts/title/text/ + * Custom title + * @sample {highstock} stock/chart/title-text/ + * Custom title + * + * @default {highcharts|highmaps} Chart title + * @default {highstock} undefined + */ + text: 'Chart title', + /** + * The horizontal alignment of the title. Can be one of "left", "center" + * and "right". + * + * @sample {highcharts} highcharts/title/align/ + * Aligned to the plot area (x = 70px = margin left - spacing + * left) + * @sample {highstock} stock/chart/title-align/ + * Aligned to the plot area (x = 50px = margin left - spacing + * left) + * + * @type {Highcharts.AlignValue} + * @since 2.0 + */ + align: 'center', + /** + * The margin between the title and the plot area, or if a subtitle + * is present, the margin between the subtitle and the plot area. + * + * @sample {highcharts} highcharts/title/margin-50/ + * A chart title margin of 50 + * @sample {highcharts} highcharts/title/margin-subtitle/ + * The same margin applied with a subtitle + * @sample {highstock} stock/chart/title-margin/ + * A chart title margin of 50 + * + * @since 2.1 + */ + margin: 15, + /** + * Adjustment made to the title width, normally to reserve space for + * the exporting burger menu. + * + * @sample highcharts/title/widthadjust/ + * Wider menu, greater padding + * + * @since 4.2.5 + */ + widthAdjust: -44 + }, + /** + * The chart's subtitle. This can be used both to display a subtitle below + * the main title, and to display random text anywhere in the chart. The + * subtitle can be updated after chart initialization through the + * `Chart.setTitle` method. + * + * @sample {highmaps} maps/title/subtitle/ + * Subtitle options demonstrated + */ + subtitle: { + /** + * When the subtitle is floating, the plot area will not move to make + * space for it. + * + * @sample {highcharts} highcharts/subtitle/floating/ + * Floating title and subtitle + * @sample {highstock} stock/chart/subtitle-footnote + * Footnote floating at bottom right of plot area + * + * @type {boolean} + * @default false + * @since 2.1 + * @apioption subtitle.floating + */ + /** + * CSS styles for the title. + * + * In styled mode, the subtitle style is given in the + * `.highcharts-subtitle` class. + * + * @sample {highcharts} highcharts/subtitle/style/ + * Custom color and weight + * @sample {highcharts} highcharts/css/titles/ + * Styled mode + * @sample {highstock} stock/chart/subtitle-style + * Custom color and weight + * @sample {highstock} highcharts/css/titles/ + * Styled mode + * @sample {highmaps} highcharts/css/titles/ + * Styled mode + * + * @type {Highcharts.CSSObject} + * @default {"color": "#666666"} + * @apioption subtitle.style + */ + /** + * Whether to + * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the text. + * + * @type {boolean} + * @default false + * @apioption subtitle.useHTML + */ + /** + * The vertical alignment of the title. Can be one of `"top"`, + * `"middle"` and `"bottom"`. When middle, the subtitle behaves as + * floating. + * + * @sample {highcharts} highcharts/subtitle/verticalalign/ + * Footnote at the bottom right of plot area + * @sample {highstock} stock/chart/subtitle-footnote + * Footnote at the bottom right of plot area + * + * @type {Highcharts.VerticalAlignValue} + * @since 2.1 + * @apioption subtitle.verticalAlign + */ + /** + * The x position of the subtitle relative to the alignment within + * `chart.spacingLeft` and `chart.spacingRight`. + * + * @sample {highcharts} highcharts/subtitle/align/ + * Footnote at right of plot area + * @sample {highstock} stock/chart/subtitle-footnote + * Footnote at the bottom right of plot area + * + * @type {number} + * @default 0 + * @since 2.0 + * @apioption subtitle.x + */ + /** + * The y position of the subtitle relative to the alignment within + * `chart.spacingTop` and `chart.spacingBottom`. By default the subtitle + * is laid out below the title unless the title is floating. + * + * @sample {highcharts} highcharts/subtitle/verticalalign/ + * Footnote at the bottom right of plot area + * @sample {highstock} stock/chart/subtitle-footnote + * Footnote at the bottom right of plot area + * + * @type {number} + * @since 2.0 + * @apioption subtitle.y + */ + /** + * The subtitle of the chart. + * + * @sample {highcharts|highstock} highcharts/subtitle/text/ + * Custom subtitle + * @sample {highcharts|highstock} highcharts/subtitle/text-formatted/ + * Formatted and linked text. + */ + text: '', + /** + * The horizontal alignment of the subtitle. Can be one of "left", + * "center" and "right". + * + * @sample {highcharts} highcharts/subtitle/align/ + * Footnote at right of plot area + * @sample {highstock} stock/chart/subtitle-footnote + * Footnote at bottom right of plot area + * + * @type {Highcharts.AlignValue} + * @since 2.0 + */ + align: 'center', + /** + * Adjustment made to the subtitle width, normally to reserve space + * for the exporting burger menu. + * + * @see [title.widthAdjust](#title.widthAdjust) + * + * @sample highcharts/title/widthadjust/ + * Wider menu, greater padding + * + * @since 4.2.5 + */ + widthAdjust: -44 + }, + /** + * The chart's caption, which will render below the chart and will be part + * of exported charts. The caption can be updated after chart initialization + * through the `Chart.update` or `Chart.caption.update` methods. + * + * @sample highcharts/caption/text/ + * A chart with a caption + * @since 7.2.0 + */ + caption: { + /** + * When the caption is floating, the plot area will not move to make + * space for it. + * + * @type {boolean} + * @default false + * @apioption caption.floating + */ + /** + * The margin between the caption and the plot area. + */ + margin: 15, + /** + * CSS styles for the caption. + * + * In styled mode, the caption style is given in the + * `.highcharts-caption` class. + * + * @sample {highcharts} highcharts/css/titles/ + * Styled mode + * + * @type {Highcharts.CSSObject} + * @default {"color": "#666666"} + * @apioption caption.style + */ + /** + * Whether to + * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the text. + * + * @type {boolean} + * @default false + * @apioption caption.useHTML + */ + /** + * The x position of the caption relative to the alignment within + * `chart.spacingLeft` and `chart.spacingRight`. + * + * @type {number} + * @default 0 + * @apioption caption.x + */ + /** + * The y position of the caption relative to the alignment within + * `chart.spacingTop` and `chart.spacingBottom`. + * + * @type {number} + * @apioption caption.y + */ + /** + * The caption text of the chart. + * + * @sample {highcharts} highcharts/caption/text/ + * Custom caption + */ + text: '', + /** + * The horizontal alignment of the caption. Can be one of "left", + * "center" and "right". + * + * @type {Highcharts.AlignValue} + */ + align: 'left', + /** + * The vertical alignment of the caption. Can be one of `"top"`, + * `"middle"` and `"bottom"`. When middle, the caption behaves as + * floating. + * + * @type {Highcharts.VerticalAlignValue} + */ + verticalAlign: 'bottom' + }, + /** + * The plotOptions is a wrapper object for config objects for each series + * type. The config objects for each series can also be overridden for + * each series item as given in the series array. + * + * Configuration options for the series are given in three levels. Options + * for all series in a chart are given in the [plotOptions.series]( + * #plotOptions.series) object. Then options for all series of a specific + * type are given in the plotOptions of that type, for example + * `plotOptions.line`. Next, options for one single series are given in + * [the series array](#series). + */ + plotOptions: {}, + /** + * HTML labels that can be positioned anywhere in the chart area. + * + * This option is deprecated since v7.1.2. Instead, use + * [annotations](#annotations) that support labels. + * + * @deprecated + * @product highcharts highstock + */ + labels: { + /** + * An HTML label that can be positioned anywhere in the chart area. + * + * @deprecated + * @type {Array<*>} + * @apioption labels.items + */ + /** + * Inner HTML or text for the label. + * + * @deprecated + * @type {string} + * @apioption labels.items.html + */ + /** + * CSS styles for each label. To position the label, use left and top + * like this: + * ```js + * style: { + * left: '100px', + * top: '100px' + * } + * ``` + * + * @deprecated + * @type {Highcharts.CSSObject} + * @apioption labels.items.style + */ + /** + * Shared CSS styles for all labels. + * + * @deprecated + * @type {Highcharts.CSSObject} + * @default {"color": "#333333", "position": "absolute"} + */ + style: { + /** + * @ignore-option + */ + position: 'absolute', + /** + * @ignore-option + */ + color: '#333333' + } + }, + /** + * The legend is a box containing a symbol and name for each series + * item or point item in the chart. Each series (or points in case + * of pie charts) is represented by a symbol and its name in the legend. + * + * It is possible to override the symbol creator function and create + * [custom legend symbols](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/studies/legend-custom-symbol/). + * + * @productdesc {highmaps} + * A Highmaps legend by default contains one legend item per series, but if + * a `colorAxis` is defined, the axis will be displayed in the legend. + * Either as a gradient, or as multiple legend items for `dataClasses`. + */ + legend: { + /** + * The background color of the legend. + * + * @see In styled mode, the legend background fill can be applied with + * the `.highcharts-legend-box` class. + * + * @sample {highcharts} highcharts/legend/backgroundcolor/ + * Yellowish background + * @sample {highstock} stock/legend/align/ + * Various legend options + * @sample {highmaps} maps/legend/border-background/ + * Border and background options + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption legend.backgroundColor + */ + /** + * The width of the drawn border around the legend. + * + * @see In styled mode, the legend border stroke width can be applied + * with the `.highcharts-legend-box` class. + * + * @sample {highcharts} highcharts/legend/borderwidth/ + * 2px border width + * @sample {highstock} stock/legend/align/ + * Various legend options + * @sample {highmaps} maps/legend/border-background/ + * Border and background options + * + * @type {number} + * @default 0 + * @apioption legend.borderWidth + */ + /** + * Enable or disable the legend. There is also a series-specific option, + * [showInLegend](#plotOptions.series.showInLegend), that can hide the + * series from the legend. In some series types this is `false` by + * default, so it must set to `true` in order to show the legend for the + * series. + * + * @sample {highcharts} highcharts/legend/enabled-false/ Legend disabled + * @sample {highstock} stock/legend/align/ Various legend options + * @sample {highmaps} maps/legend/enabled-false/ Legend disabled + * + * @default {highstock} false + * @default {highmaps} true + * @default {gantt} false + */ + enabled: true, + /** + * The horizontal alignment of the legend box within the chart area. + * Valid values are `left`, `center` and `right`. + * + * In the case that the legend is aligned in a corner position, the + * `layout` option will determine whether to place it above/below + * or on the side of the plot area. + * + * @sample {highcharts} highcharts/legend/align/ + * Legend at the right of the chart + * @sample {highstock} stock/legend/align/ + * Various legend options + * @sample {highmaps} maps/legend/alignment/ + * Legend alignment + * + * @type {Highcharts.AlignValue} + * @since 2.0 + */ + align: 'center', + /** + * If the [layout](legend.layout) is `horizontal` and the legend items + * span over two lines or more, whether to align the items into vertical + * columns. Setting this to `false` makes room for more items, but will + * look more messy. + * + * @since 6.1.0 + */ + alignColumns: true, + /** + * When the legend is floating, the plot area ignores it and is allowed + * to be placed below it. + * + * @sample {highcharts} highcharts/legend/floating-false/ + * False by default + * @sample {highcharts} highcharts/legend/floating-true/ + * True + * @sample {highmaps} maps/legend/alignment/ + * Floating legend + * + * @type {boolean} + * @default false + * @since 2.1 + * @apioption legend.floating + */ + /** + * The layout of the legend items. Can be one of `horizontal` or + * `vertical` or `proximate`. When `proximate`, the legend items will be + * placed as close as possible to the graphs they're representing, + * except in inverted charts or when the legend position doesn't allow + * it. + * + * @sample {highcharts} highcharts/legend/layout-horizontal/ + * Horizontal by default + * @sample {highcharts} highcharts/legend/layout-vertical/ + * Vertical + * @sample highcharts/legend/layout-proximate + * Labels proximate to the data + * @sample {highstock} stock/legend/layout-horizontal/ + * Horizontal by default + * @sample {highmaps} maps/legend/padding-itemmargin/ + * Vertical with data classes + * @sample {highmaps} maps/legend/layout-vertical/ + * Vertical with color axis gradient + * + * @validvalue ["horizontal", "vertical", "proximate"] + */ + layout: 'horizontal', + /** + * In a legend with horizontal layout, the itemDistance defines the + * pixel distance between each item. + * + * @sample {highcharts} highcharts/legend/layout-horizontal/ + * 50px item distance + * @sample {highstock} highcharts/legend/layout-horizontal/ + * 50px item distance + * + * @type {number} + * @default {highcharts} 20 + * @default {highstock} 20 + * @default {highmaps} 8 + * @since 3.0.3 + * @apioption legend.itemDistance + */ + /** + * The pixel bottom margin for each legend item. + * + * @sample {highcharts|highstock} highcharts/legend/padding-itemmargin/ + * Padding and item margins demonstrated + * @sample {highmaps} maps/legend/padding-itemmargin/ + * Padding and item margins demonstrated + * + * @type {number} + * @default 0 + * @since 2.2.0 + * @apioption legend.itemMarginBottom + */ + /** + * The pixel top margin for each legend item. + * + * @sample {highcharts|highstock} highcharts/legend/padding-itemmargin/ + * Padding and item margins demonstrated + * @sample {highmaps} maps/legend/padding-itemmargin/ + * Padding and item margins demonstrated + * + * @type {number} + * @default 0 + * @since 2.2.0 + * @apioption legend.itemMarginTop + */ + /** + * The width for each legend item. By default the items are laid out + * successively. In a [horizontal layout](legend.layout), if the items + * are laid out across two rows or more, they will be vertically aligned + * depending on the [legend.alignColumns](legend.alignColumns) option. + * + * @sample {highcharts} highcharts/legend/itemwidth-default/ + * Undefined by default + * @sample {highcharts} highcharts/legend/itemwidth-80/ + * 80 for aligned legend items + * + * @type {number} + * @since 2.0 + * @apioption legend.itemWidth + */ + /** + * A [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) + * for each legend label. Available variables relates to properties on + * the series, or the point in case of pies. + * + * @type {string} + * @default {name} + * @since 1.3 + * @apioption legend.labelFormat + */ + /* eslint-disable valid-jsdoc */ + /** + * Callback function to format each of the series' labels. The `this` + * keyword refers to the series object, or the point object in case of + * pie charts. By default the series or point name is printed. + * + * @productdesc {highmaps} + * In Highmaps the context can also be a data class in case of a + * `colorAxis`. + * + * @sample {highcharts} highcharts/legend/labelformatter/ + * Add text + * @sample {highmaps} maps/legend/labelformatter/ + * Data classes with label formatter + * + * @type {Highcharts.FormatterCallbackFunction} + */ + labelFormatter: function () { + /** eslint-enable valid-jsdoc */ + return this.name; + }, + /** + * Line height for the legend items. Deprecated as of 2.1\. Instead, + * the line height for each item can be set using + * `itemStyle.lineHeight`, and the padding between items using + * `itemMarginTop` and `itemMarginBottom`. + * + * @sample {highcharts} highcharts/legend/lineheight/ + * Setting padding + * + * @deprecated + * + * @type {number} + * @default 16 + * @since 2.0 + * @product highcharts gantt + * @apioption legend.lineHeight + */ + /** + * If the plot area sized is calculated automatically and the legend is + * not floating, the legend margin is the space between the legend and + * the axis labels or plot area. + * + * @sample {highcharts} highcharts/legend/margin-default/ + * 12 pixels by default + * @sample {highcharts} highcharts/legend/margin-30/ + * 30 pixels + * + * @type {number} + * @default 12 + * @since 2.1 + * @apioption legend.margin + */ + /** + * Maximum pixel height for the legend. When the maximum height is + * extended, navigation will show. + * + * @type {number} + * @since 2.3.0 + * @apioption legend.maxHeight + */ + /** + * The color of the drawn border around the legend. + * + * @see In styled mode, the legend border stroke can be applied with the + * `.highcharts-legend-box` class. + * + * @sample {highcharts} highcharts/legend/bordercolor/ + * Brown border + * @sample {highstock} stock/legend/align/ + * Various legend options + * @sample {highmaps} maps/legend/border-background/ + * Border and background options + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + borderColor: '#999999', + /** + * The border corner radius of the legend. + * + * @sample {highcharts} highcharts/legend/borderradius-default/ + * Square by default + * @sample {highcharts} highcharts/legend/borderradius-round/ + * 5px rounded + * @sample {highmaps} maps/legend/border-background/ + * Border and background options + */ + borderRadius: 0, + /** + * Options for the paging or navigation appearing when the legend is + * overflown. Navigation works well on screen, but not in static + * exported images. One way of working around that is to + * [increase the chart height in + * export](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/legend/navigation-enabled-false/). + */ + navigation: { + /** + * How to animate the pages when navigating up or down. A value of + * `true` applies the default navigation given in the + * `chart.animation` option. Additional options can be given as an + * object containing values for easing and duration. + * + * @sample {highcharts} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * @sample {highstock} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * + * @type {boolean|Highcharts.AnimationOptionsObject} + * @default true + * @since 2.2.4 + * @apioption legend.navigation.animation + */ + /** + * The pixel size of the up and down arrows in the legend paging + * navigation. + * + * @sample {highcharts} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * @sample {highstock} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * + * @type {number} + * @default 12 + * @since 2.2.4 + * @apioption legend.navigation.arrowSize + */ + /** + * Whether to enable the legend navigation. In most cases, disabling + * the navigation results in an unwanted overflow. + * + * See also the [adapt chart to legend]( + * https://www.highcharts.com/products/plugin-registry/single/8/Adapt-Chart-To-Legend) + * plugin for a solution to extend the chart height to make room for + * the legend, optionally in exported charts only. + * + * @type {boolean} + * @default true + * @since 4.2.4 + * @apioption legend.navigation.enabled + */ + /** + * Text styles for the legend page navigation. + * + * @see In styled mode, the navigation items are styled with the + * `.highcharts-legend-navigation` class. + * + * @sample {highcharts} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * @sample {highstock} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * + * @type {Highcharts.CSSObject} + * @since 2.2.4 + * @apioption legend.navigation.style + */ + /** + * The color for the active up or down arrow in the legend page + * navigation. + * + * @see In styled mode, the active arrow be styled with the + * `.highcharts-legend-nav-active` class. + * + * @sample {highcharts} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * @sample {highstock} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.2.4 + */ + activeColor: '#003399', + /** + * The color of the inactive up or down arrow in the legend page + * navigation. . + * + * @see In styled mode, the inactive arrow be styled with the + * `.highcharts-legend-nav-inactive` class. + * + * @sample {highcharts} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * @sample {highstock} highcharts/legend/navigation/ + * Legend page navigation demonstrated + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.2.4 + */ + inactiveColor: '#cccccc' + }, + /** + * The inner padding of the legend box. + * + * @sample {highcharts|highstock} highcharts/legend/padding-itemmargin/ + * Padding and item margins demonstrated + * @sample {highmaps} maps/legend/padding-itemmargin/ + * Padding and item margins demonstrated + * + * @type {number} + * @default 8 + * @since 2.2.0 + * @apioption legend.padding + */ + /** + * Whether to reverse the order of the legend items compared to the + * order of the series or points as defined in the configuration object. + * + * @see [yAxis.reversedStacks](#yAxis.reversedStacks), + * [series.legendIndex](#series.legendIndex) + * + * @sample {highcharts} highcharts/legend/reversed/ + * Stacked bar with reversed legend + * + * @type {boolean} + * @default false + * @since 1.2.5 + * @apioption legend.reversed + */ + /** + * Whether to show the symbol on the right side of the text rather than + * the left side. This is common in Arabic and Hebraic. + * + * @sample {highcharts} highcharts/legend/rtl/ + * Symbol to the right + * + * @type {boolean} + * @default false + * @since 2.2 + * @apioption legend.rtl + */ + /** + * CSS styles for the legend area. In the 1.x versions the position + * of the legend area was determined by CSS. In 2.x, the position is + * determined by properties like `align`, `verticalAlign`, `x` and `y`, + * but the styles are still parsed for backwards compatibility. + * + * @deprecated + * + * @type {Highcharts.CSSObject} + * @product highcharts highstock + * @apioption legend.style + */ + /** + * CSS styles for each legend item. Only a subset of CSS is supported, + * notably those options related to text. The default `textOverflow` + * property makes long texts truncate. Set it to `undefined` to wrap + * text instead. A `width` property can be added to control the text + * width. + * + * @see In styled mode, the legend items can be styled with the + * `.highcharts-legend-item` class. + * + * @sample {highcharts} highcharts/legend/itemstyle/ + * Bold black text + * @sample {highmaps} maps/legend/itemstyle/ + * Item text styles + * + * @type {Highcharts.CSSObject} + * @default {"color": "#333333", "cursor": "pointer", "fontSize": "12px", "fontWeight": "bold", "textOverflow": "ellipsis"} + */ + itemStyle: { + /** + * @ignore + */ + color: '#333333', + /** + * @ignore + */ + cursor: 'pointer', + /** + * @ignore + */ + fontSize: '12px', + /** + * @ignore + */ + fontWeight: 'bold', + /** + * @ignore + */ + textOverflow: 'ellipsis' + }, + /** + * CSS styles for each legend item in hover mode. Only a subset of + * CSS is supported, notably those options related to text. Properties + * are inherited from `style` unless overridden here. + * + * @see In styled mode, the hovered legend items can be styled with + * the `.highcharts-legend-item:hover` pesudo-class. + * + * @sample {highcharts} highcharts/legend/itemhoverstyle/ + * Red on hover + * @sample {highmaps} maps/legend/itemstyle/ + * Item text styles + * + * @type {Highcharts.CSSObject} + * @default {"color": "#000000"} + */ + itemHoverStyle: { + /** + * @ignore + */ + color: '#000000' + }, + /** + * CSS styles for each legend item when the corresponding series or + * point is hidden. Only a subset of CSS is supported, notably those + * options related to text. Properties are inherited from `style` + * unless overridden here. + * + * @see In styled mode, the hidden legend items can be styled with + * the `.highcharts-legend-item-hidden` class. + * + * @sample {highcharts} highcharts/legend/itemhiddenstyle/ + * Darker gray color + * + * @type {Highcharts.CSSObject} + * @default {"color": "#cccccc"} + */ + itemHiddenStyle: { + /** + * @ignore + */ + color: '#cccccc' + }, + /** + * Whether to apply a drop shadow to the legend. A `backgroundColor` + * also needs to be applied for this to take effect. The shadow can be + * an object configuration containing `color`, `offsetX`, `offsetY`, + * `opacity` and `width`. + * + * @sample {highcharts} highcharts/legend/shadow/ + * White background and drop shadow + * @sample {highstock} stock/legend/align/ + * Various legend options + * @sample {highmaps} maps/legend/border-background/ + * Border and background options + * + * @type {boolean|Highcharts.CSSObject} + */ + shadow: false, + /** + * Default styling for the checkbox next to a legend item when + * `showCheckbox` is true. + * + * @type {Highcharts.CSSObject} + * @default {"width": "13px", "height": "13px", "position":"absolute"} + */ + itemCheckboxStyle: { + /** + * @ignore + */ + position: 'absolute', + /** + * @ignore + */ + width: '13px', + /** + * @ignore + */ + height: '13px' + }, + // itemWidth: undefined, + /** + * When this is true, the legend symbol width will be the same as + * the symbol height, which in turn defaults to the font size of the + * legend items. + * + * @since 5.0.0 + */ + squareSymbol: true, + /** + * The pixel height of the symbol for series types that use a rectangle + * in the legend. Defaults to the font size of legend items. + * + * @productdesc {highmaps} + * In Highmaps, when the symbol is the gradient of a vertical color + * axis, the height defaults to 200. + * + * @sample {highmaps} maps/legend/layout-vertical-sized/ + * Sized vertical gradient + * @sample {highmaps} maps/legend/padding-itemmargin/ + * No distance between data classes + * + * @type {number} + * @since 3.0.8 + * @apioption legend.symbolHeight + */ + /** + * The border radius of the symbol for series types that use a rectangle + * in the legend. Defaults to half the `symbolHeight`. + * + * @sample {highcharts} highcharts/legend/symbolradius/ + * Round symbols + * @sample {highstock} highcharts/legend/symbolradius/ + * Round symbols + * @sample {highmaps} highcharts/legend/symbolradius/ + * Round symbols + * + * @type {number} + * @since 3.0.8 + * @apioption legend.symbolRadius + */ + /** + * The pixel width of the legend item symbol. When the `squareSymbol` + * option is set, this defaults to the `symbolHeight`, otherwise 16. + * + * @productdesc {highmaps} + * In Highmaps, when the symbol is the gradient of a horizontal color + * axis, the width defaults to 200. + * + * @sample {highcharts} highcharts/legend/symbolwidth/ + * Greater symbol width and padding + * @sample {highmaps} maps/legend/padding-itemmargin/ + * Padding and item margins demonstrated + * @sample {highmaps} maps/legend/layout-vertical-sized/ + * Sized vertical gradient + * + * @type {number} + * @apioption legend.symbolWidth + */ + /** + * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the legend item texts. + * + * Prior to 4.1.7, when using HTML, [legend.navigation]( + * #legend.navigation) was disabled. + * + * @type {boolean} + * @default false + * @apioption legend.useHTML + */ + /** + * The width of the legend box. If a number is set, it translates to + * pixels. Since v7.0.2 it allows setting a percent string of the full + * chart width, for example `40%`. + * + * Defaults to the full chart width from legends below or above the + * chart, half the chart width for legends to the left and right. + * + * @sample {highcharts} highcharts/legend/width/ + * Aligned to the plot area + * @sample {highcharts} highcharts/legend/width-percent/ + * A percent of the chart width + * + * @type {number|string} + * @since 2.0 + * @apioption legend.width + */ + /** + * The pixel padding between the legend item symbol and the legend + * item text. + * + * @sample {highcharts} highcharts/legend/symbolpadding/ + * Greater symbol width and padding + */ + symbolPadding: 5, + /** + * The vertical alignment of the legend box. Can be one of `top`, + * `middle` or `bottom`. Vertical position can be further determined + * by the `y` option. + * + * In the case that the legend is aligned in a corner position, the + * `layout` option will determine whether to place it above/below + * or on the side of the plot area. + * + * When the [layout](#legend.layout) option is `proximate`, the + * `verticalAlign` option doesn't apply. + * + * @sample {highcharts} highcharts/legend/verticalalign/ + * Legend 100px from the top of the chart + * @sample {highstock} stock/legend/align/ + * Various legend options + * @sample {highmaps} maps/legend/alignment/ + * Legend alignment + * + * @type {Highcharts.VerticalAlignValue} + * @since 2.0 + */ + verticalAlign: 'bottom', + // width: undefined, + /** + * The x offset of the legend relative to its horizontal alignment + * `align` within chart.spacingLeft and chart.spacingRight. Negative + * x moves it to the left, positive x moves it to the right. + * + * @sample {highcharts} highcharts/legend/width/ + * Aligned to the plot area + * + * @since 2.0 + */ + x: 0, + /** + * The vertical offset of the legend relative to it's vertical alignment + * `verticalAlign` within chart.spacingTop and chart.spacingBottom. + * Negative y moves it up, positive y moves it down. + * + * @sample {highcharts} highcharts/legend/verticalalign/ + * Legend 100px from the top of the chart + * @sample {highstock} stock/legend/align/ + * Various legend options + * @sample {highmaps} maps/legend/alignment/ + * Legend alignment + * + * @since 2.0 + */ + y: 0, + /** + * A title to be added on top of the legend. + * + * @sample {highcharts} highcharts/legend/title/ + * Legend title + * @sample {highmaps} maps/legend/alignment/ + * Legend with title + * + * @since 3.0 + */ + title: { + /** + * A text or HTML string for the title. + * + * @type {string} + * @since 3.0 + * @apioption legend.title.text + */ + /** + * Generic CSS styles for the legend title. + * + * @see In styled mode, the legend title is styled with the + * `.highcharts-legend-title` class. + * + * @type {Highcharts.CSSObject} + * @default {"fontWeight": "bold"} + * @since 3.0 + */ + style: { + /** + * @ignore + */ + fontWeight: 'bold' + } + } + }, + /** + * The loading options control the appearance of the loading screen + * that covers the plot area on chart operations. This screen only + * appears after an explicit call to `chart.showLoading()`. It is a + * utility for developers to communicate to the end user that something + * is going on, for example while retrieving new data via an XHR connection. + * The "Loading..." text itself is not part of this configuration + * object, but part of the `lang` object. + */ + loading: { + /** + * The duration in milliseconds of the fade out effect. + * + * @sample highcharts/loading/hideduration/ + * Fade in and out over a second + * + * @type {number} + * @default 100 + * @since 1.2.0 + * @apioption loading.hideDuration + */ + /** + * The duration in milliseconds of the fade in effect. + * + * @sample highcharts/loading/hideduration/ + * Fade in and out over a second + * + * @type {number} + * @default 100 + * @since 1.2.0 + * @apioption loading.showDuration + */ + /** + * CSS styles for the loading label `span`. + * + * @see In styled mode, the loading label is styled with the + * `.highcharts-loading-inner` class. + * + * @sample {highcharts|highmaps} highcharts/loading/labelstyle/ + * Vertically centered + * @sample {highstock} stock/loading/general/ + * Label styles + * + * @type {Highcharts.CSSObject} + * @default {"fontWeight": "bold", "position": "relative", "top": "45%"} + * @since 1.2.0 + */ + labelStyle: { + /** + * @ignore + */ + fontWeight: 'bold', + /** + * @ignore + */ + position: 'relative', + /** + * @ignore + */ + top: '45%' + }, + /** + * CSS styles for the loading screen that covers the plot area. + * + * In styled mode, the loading label is styled with the + * `.highcharts-loading` class. + * + * @sample {highcharts|highmaps} highcharts/loading/style/ + * Gray plot area, white text + * @sample {highstock} stock/loading/general/ + * Gray plot area, white text + * + * @type {Highcharts.CSSObject} + * @default {"position": "absolute", "backgroundColor": "#ffffff", "opacity": 0.5, "textAlign": "center"} + * @since 1.2.0 + */ + style: { + /** + * @ignore + */ + position: 'absolute', + /** + * @ignore + */ + backgroundColor: '#ffffff', + /** + * @ignore + */ + opacity: 0.5, + /** + * @ignore + */ + textAlign: 'center' + } + }, + /** + * Options for the tooltip that appears when the user hovers over a + * series or point. + * + * @declare Highcharts.TooltipOptions + */ + tooltip: { + /** + * The color of the tooltip border. When `undefined`, the border takes + * the color of the corresponding series or point. + * + * @sample {highcharts} highcharts/tooltip/bordercolor-default/ + * Follow series by default + * @sample {highcharts} highcharts/tooltip/bordercolor-black/ + * Black border + * @sample {highstock} stock/tooltip/general/ + * Styled tooltip + * @sample {highmaps} maps/tooltip/background-border/ + * Background and border demo + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption tooltip.borderColor + */ + /** + * A CSS class name to apply to the tooltip's container div, + * allowing unique CSS styling for each chart. + * + * @type {string} + * @apioption tooltip.className + */ + /** + * Since 4.1, the crosshair definitions are moved to the Axis object + * in order for a better separation from the tooltip. See + * [xAxis.crosshair](#xAxis.crosshair). + * + * @sample {highcharts} highcharts/tooltip/crosshairs-x/ + * Enable a crosshair for the x value + * + * @deprecated + * + * @type {*} + * @default true + * @apioption tooltip.crosshairs + */ + /** + * Distance from point to tooltip in pixels. + * + * @type {number} + * @default 16 + * @apioption tooltip.distance + */ + /** + * Whether the tooltip should follow the mouse as it moves across + * columns, pie slices and other point types with an extent. + * By default it behaves this way for pie, polygon, map, sankey + * and wordcloud series by override in the `plotOptions` + * for those series types. + * + * For touch moves to behave the same way, [followTouchMove]( + * #tooltip.followTouchMove) must be `true` also. + * + * @type {boolean} + * @default {highcharts} false + * @default {highstock} false + * @default {highmaps} true + * @since 3.0 + * @apioption tooltip.followPointer + */ + /** + * Whether the tooltip should update as the finger moves on a touch + * device. If this is `true` and [chart.panning](#chart.panning) is + * set,`followTouchMove` will take over one-finger touches, so the user + * needs to use two fingers for zooming and panning. + * + * Note the difference to [followPointer](#tooltip.followPointer) that + * only defines the _position_ of the tooltip. If `followPointer` is + * false in for example a column series, the tooltip will show above or + * below the column, but as `followTouchMove` is true, the tooltip will + * jump from column to column as the user swipes across the plot area. + * + * @type {boolean} + * @default {highcharts} true + * @default {highstock} true + * @default {highmaps} false + * @since 3.0.1 + * @apioption tooltip.followTouchMove + */ + /** + * Callback function to format the text of the tooltip from scratch. In + * case of single or [shared](#tooltip.shared) tooltips, a string should + * be returned. In case of [split](#tooltip.split) tooltips, it should + * return an array where the first item is the header, and subsequent + * items are mapped to the points. Return `false` to disable tooltip for + * a specific point on series. + * + * A subset of HTML is supported. Unless `useHTML` is true, the HTML of + * the tooltip is parsed and converted to SVG, therefore this isn't a + * complete HTML renderer. The following HTML tags are supported: `b`, + * `br`, `em`, `i`, `span`, `strong`. Spans can be styled with a `style` + * attribute, but only text-related CSS, that is shared with SVG, is + * handled. + * + * The available data in the formatter differ a bit depending on whether + * the tooltip is shared or split, or belongs to a single point. In a + * shared/split tooltip, all properties except `x`, which is common for + * all points, are kept in an array, `this.points`. + * + * Available data are: + * + * - **this.percentage (not shared) /** + * **this.points[i].percentage (shared)**: + * Stacked series and pies only. The point's percentage of the total. + * + * - **this.point (not shared) / this.points[i].point (shared)**: + * The point object. The point name, if defined, is available through + * `this.point.name`. + * + * - **this.points**: + * In a shared tooltip, this is an array containing all other + * properties for each point. + * + * - **this.series (not shared) / this.points[i].series (shared)**: + * The series object. The series name is available through + * `this.series.name`. + * + * - **this.total (not shared) / this.points[i].total (shared)**: + * Stacked series only. The total value at this point's x value. + * + * - **this.x**: + * The x value. This property is the same regardless of the tooltip + * being shared or not. + * + * - **this.y (not shared) / this.points[i].y (shared)**: + * The y value. + * + * @sample {highcharts} highcharts/tooltip/formatter-simple/ + * Simple string formatting + * @sample {highcharts} highcharts/tooltip/formatter-shared/ + * Formatting with shared tooltip + * @sample {highcharts|highstock} highcharts/tooltip/formatter-split/ + * Formatting with split tooltip + * @sample highcharts/tooltip/formatter-conditional-default/ + * Extending default formatter + * @sample {highstock} stock/tooltip/formatter/ + * Formatting with shared tooltip + * @sample {highmaps} maps/tooltip/formatter/ + * String formatting + * + * @type {Highcharts.TooltipFormatterCallbackFunction} + * @apioption tooltip.formatter + */ + /** + * Callback function to format the text of the tooltip for + * visible null points. + * Works analogously to [formatter](#tooltip.formatter). + * + * @sample highcharts/plotoptions/series-nullformat + * Format data label and tooltip for null point. + * + * @type {Highcharts.TooltipFormatterCallbackFunction} + * @apioption tooltip.nullFormatter + */ + /** + * The number of milliseconds to wait until the tooltip is hidden when + * mouse out from a point or chart. + * + * @type {number} + * @default 500 + * @since 3.0 + * @apioption tooltip.hideDelay + */ + /** + * Whether to allow the tooltip to render outside the chart's SVG + * element box. By default (`false`), the tooltip is rendered within the + * chart's SVG element, which results in the tooltip being aligned + * inside the chart area. For small charts, this may result in clipping + * or overlapping. When `true`, a separate SVG element is created and + * overlaid on the page, allowing the tooltip to be aligned inside the + * page itself. + * + * Defaults to `true` if `chart.scrollablePlotArea` is activated, + * otherwise `false`. + * + * @sample highcharts/tooltip/outside + * Small charts with tooltips outside + * + * @type {boolean|undefined} + * @default undefined + * @since 6.1.1 + * @apioption tooltip.outside + */ + /** + * A callback function for formatting the HTML output for a single point + * in the tooltip. Like the `pointFormat` string, but with more + * flexibility. + * + * @type {Highcharts.FormatterCallbackFunction} + * @since 4.1.0 + * @context Highcharts.Point + * @apioption tooltip.pointFormatter + */ + /** + * A callback function to place the tooltip in a default position. The + * callback receives three parameters: `labelWidth`, `labelHeight` and + * `point`, where point contains values for `plotX` and `plotY` telling + * where the reference point is in the plot area. Add `chart.plotLeft` + * and `chart.plotTop` to get the full coordinates. + * + * Since v7, when [tooltip.split](#tooltip.split) option is enabled, + * positioner is called for each of the boxes separately, including + * xAxis header. xAxis header is not a point, instead `point` argument + * contains info: + * `{ plotX: Number, plotY: Number, isHeader: Boolean }` + * + * + * The return should be an object containing x and y values, for example + * `{ x: 100, y: 100 }`. + * + * @sample {highcharts} highcharts/tooltip/positioner/ + * A fixed tooltip position + * @sample {highstock} stock/tooltip/positioner/ + * A fixed tooltip position on top of the chart + * @sample {highmaps} maps/tooltip/positioner/ + * A fixed tooltip position + * @sample {highstock} stock/tooltip/split-positioner/ + * Split tooltip with fixed positions + * @sample {highstock} stock/tooltip/positioner-scrollable-plotarea/ + * Scrollable plot area combined with tooltip positioner + * + * @type {Highcharts.TooltipPositionerCallbackFunction} + * @since 2.2.4 + * @apioption tooltip.positioner + */ + /** + * The name of a symbol to use for the border around the tooltip. Can + * be one of: `"callout"`, `"circle"`, or `"square"`. When + * [tooltip.split](#tooltip.split) + * option is enabled, shape is applied to all boxes except header, which + * is controlled by + * [tooltip.headerShape](#tooltip.headerShape). + * + * Custom callbacks for symbol path generation can also be added to + * `Highcharts.SVGRenderer.prototype.symbols` the same way as for + * [series.marker.symbol](plotOptions.line.marker.symbol). + * + * @type {Highcharts.TooltipShapeValue} + * @default callout + * @since 4.0 + * @apioption tooltip.shape + */ + /** + * The name of a symbol to use for the border around the tooltip + * header. Applies only when [tooltip.split](#tooltip.split) is + * enabled. + * + * Custom callbacks for symbol path generation can also be added to + * `Highcharts.SVGRenderer.prototype.symbols` the same way as for + * [series.marker.symbol](plotOptions.line.marker.symbol). + * + * @see [tooltip.shape](#tooltip.shape) + * + * @sample {highstock} stock/tooltip/split-positioner/ + * Different shapes for header and split boxes + * + * @type {Highcharts.TooltipShapeValue} + * @default callout + * @validvalue ["callout", "square"] + * @since 7.0 + * @apioption tooltip.headerShape + */ + /** + * When the tooltip is shared, the entire plot area will capture mouse + * movement or touch events. Tooltip texts for series types with ordered + * data (not pie, scatter, flags etc) will be shown in a single bubble. + * This is recommended for single series charts and for tablet/mobile + * optimized charts. + * + * See also [tooltip.split](#tooltip.split), that is better suited for + * charts with many series, especially line-type series. The + * `tooltip.split` option takes precedence over `tooltip.shared`. + * + * @sample {highcharts} highcharts/tooltip/shared-false/ + * False by default + * @sample {highcharts} highcharts/tooltip/shared-true/ + * True + * @sample {highcharts} highcharts/tooltip/shared-x-crosshair/ + * True with x axis crosshair + * @sample {highcharts} highcharts/tooltip/shared-true-mixed-types/ + * True with mixed series types + * + * @type {boolean} + * @default false + * @since 2.1 + * @product highcharts highstock + * @apioption tooltip.shared + */ + /** + * Split the tooltip into one label per series, with the header close + * to the axis. This is recommended over [shared](#tooltip.shared) + * tooltips for charts with multiple line series, generally making them + * easier to read. This option takes precedence over `tooltip.shared`. + * + * @productdesc {highstock} In Highstock, tooltips are split by default + * since v6.0.0. Stock charts typically contain multi-dimension points + * and multiple panes, making split tooltips the preferred layout over + * the previous `shared` tooltip. + * + * @sample highcharts/tooltip/split/ + * Split tooltip + * @sample {highcharts|highstock} highcharts/tooltip/formatter-split/ + * Split tooltip and custom formatter callback + * + * @type {boolean} + * @default {highcharts} false + * @default {highstock} true + * @since 5.0.0 + * @product highcharts highstock + * @apioption tooltip.split + */ + /** + * Prevents the tooltip from switching or closing, when touched or + * pointed. + * + * @sample highcharts/tooltip/stickoncontact/ + * Tooltip sticks on pointer contact + * + * @type {boolean} + * @since 8.0.1 + * @apioption tooltip.stickOnContact + */ + /** + * Use HTML to render the contents of the tooltip instead of SVG. Using + * HTML allows advanced formatting like tables and images in the + * tooltip. It is also recommended for rtl languages as it works around + * rtl bugs in early Firefox. + * + * @sample {highcharts|highstock} highcharts/tooltip/footerformat/ + * A table for value alignment + * @sample {highcharts|highstock} highcharts/tooltip/fullhtml/ + * Full HTML tooltip + * @sample {highmaps} maps/tooltip/usehtml/ + * Pure HTML tooltip + * + * @type {boolean} + * @default false + * @since 2.2 + * @apioption tooltip.useHTML + */ + /** + * How many decimals to show in each series' y value. This is + * overridable in each series' tooltip options object. The default is to + * preserve all decimals. + * + * @sample {highcharts|highstock} highcharts/tooltip/valuedecimals/ + * Set decimals, prefix and suffix for the value + * @sample {highmaps} maps/tooltip/valuedecimals/ + * Set decimals, prefix and suffix for the value + * + * @type {number} + * @since 2.2 + * @apioption tooltip.valueDecimals + */ + /** + * A string to prepend to each series' y value. Overridable in each + * series' tooltip options object. + * + * @sample {highcharts|highstock} highcharts/tooltip/valuedecimals/ + * Set decimals, prefix and suffix for the value + * @sample {highmaps} maps/tooltip/valuedecimals/ + * Set decimals, prefix and suffix for the value + * + * @type {string} + * @since 2.2 + * @apioption tooltip.valuePrefix + */ + /** + * A string to append to each series' y value. Overridable in each + * series' tooltip options object. + * + * @sample {highcharts|highstock} highcharts/tooltip/valuedecimals/ + * Set decimals, prefix and suffix for the value + * @sample {highmaps} maps/tooltip/valuedecimals/ + * Set decimals, prefix and suffix for the value + * + * @type {string} + * @since 2.2 + * @apioption tooltip.valueSuffix + */ + /** + * The format for the date in the tooltip header if the X axis is a + * datetime axis. The default is a best guess based on the smallest + * distance between points in the chart. + * + * @sample {highcharts} highcharts/tooltip/xdateformat/ + * A different format + * + * @type {string} + * @product highcharts highstock gantt + * @apioption tooltip.xDateFormat + */ + /** + * How many decimals to show for the `point.change` value when the + * `series.compare` option is set. This is overridable in each series' + * tooltip options object. The default is to preserve all decimals. + * + * @type {number} + * @since 1.0.1 + * @product highstock + * @apioption tooltip.changeDecimals + */ + /** + * Enable or disable the tooltip. + * + * @sample {highcharts} highcharts/tooltip/enabled/ + * Disabled + * @sample {highcharts} highcharts/plotoptions/series-point-events-mouseover/ + * Disable tooltip and show values on chart instead + */ + enabled: true, + /** + * Enable or disable animation of the tooltip. + * + * @type {boolean} + * @default true + * @since 2.3.0 + */ + animation: svg, + /** + * The radius of the rounded border corners. + * + * @sample {highcharts} highcharts/tooltip/bordercolor-default/ + * 5px by default + * @sample {highcharts} highcharts/tooltip/borderradius-0/ + * Square borders + * @sample {highmaps} maps/tooltip/background-border/ + * Background and border demo + */ + borderRadius: 3, + /** + * For series on a datetime axes, the date format in the tooltip's + * header will by default be guessed based on the closest data points. + * This member gives the default string representations used for + * each unit. For an overview of the replacement codes, see + * [dateFormat](/class-reference/Highcharts#dateFormat). + * + * @see [xAxis.dateTimeLabelFormats](#xAxis.dateTimeLabelFormats) + * + * @type {Highcharts.Dictionary} + * @product highcharts highstock gantt + */ + dateTimeLabelFormats: { + /** @internal */ + millisecond: '%A, %b %e, %H:%M:%S.%L', + /** @internal */ + second: '%A, %b %e, %H:%M:%S', + /** @internal */ + minute: '%A, %b %e, %H:%M', + /** @internal */ + hour: '%A, %b %e, %H:%M', + /** @internal */ + day: '%A, %b %e, %Y', + /** @internal */ + week: 'Week from %A, %b %e, %Y', + /** @internal */ + month: '%B %Y', + /** @internal */ + year: '%Y' + }, + /** + * A string to append to the tooltip format. + * + * @sample {highcharts} highcharts/tooltip/footerformat/ + * A table for value alignment + * @sample {highmaps} maps/tooltip/format/ + * Format demo + * + * @since 2.2 + */ + footerFormat: '', + /** + * Padding inside the tooltip, in pixels. + * + * @since 5.0.0 + */ + padding: 8, + /** + * Proximity snap for graphs or single points. It defaults to 10 for + * mouse-powered devices and 25 for touch devices. + * + * Note that in most cases the whole plot area captures the mouse + * movement, and in these cases `tooltip.snap` doesn't make sense. This + * applies when [stickyTracking](#plotOptions.series.stickyTracking) + * is `true` (default) and when the tooltip is [shared](#tooltip.shared) + * or [split](#tooltip.split). + * + * @sample {highcharts} highcharts/tooltip/bordercolor-default/ + * 10 px by default + * @sample {highcharts} highcharts/tooltip/snap-50/ + * 50 px on graph + * + * @type {number} + * @default 10/25 + * @since 1.2.0 + * @product highcharts highstock + */ + snap: isTouchDevice ? 25 : 10, + /** + * The HTML of the tooltip header line. Variables are enclosed by + * curly brackets. Available variables are `point.key`, `series.name`, + * `series.color` and other members from the `point` and `series` + * objects. The `point.key` variable contains the category name, x + * value or datetime string depending on the type of axis. For datetime + * axes, the `point.key` date format can be set using + * `tooltip.xDateFormat`. + * + * @sample {highcharts} highcharts/tooltip/footerformat/ + * An HTML table in the tooltip + * @sample {highstock} highcharts/tooltip/footerformat/ + * An HTML table in the tooltip + * @sample {highmaps} maps/tooltip/format/ + * Format demo + * + * @type {string} + * @apioption tooltip.headerFormat + */ + headerFormat: '{point.key}
', + /** + * The HTML of the null point's line in the tooltip. Works analogously + * to [pointFormat](#tooltip.pointFormat). + * + * @sample {highcharts} highcharts/plotoptions/series-nullformat + * Format data label and tooltip for null point. + * + * @type {string} + * @apioption tooltip.nullFormat + */ + /** + * The HTML of the point's line in the tooltip. Variables are enclosed + * by curly brackets. Available variables are point.x, point.y, series. + * name and series.color and other properties on the same form. + * Furthermore, `point.y` can be extended by the `tooltip.valuePrefix` + * and `tooltip.valueSuffix` variables. This can also be overridden for + * each series, which makes it a good hook for displaying units. + * + * In styled mode, the dot is colored by a class name rather + * than the point color. + * + * @sample {highcharts} highcharts/tooltip/pointformat/ + * A different point format with value suffix + * @sample {highmaps} maps/tooltip/format/ + * Format demo + * + * @type {string} + * @since 2.2 + * @apioption tooltip.pointFormat + */ + pointFormat: '\u25CF {series.name}: {point.y}
', + /** + * The background color or gradient for the tooltip. + * + * In styled mode, the stroke width is set in the + * `.highcharts-tooltip-box` class. + * + * @sample {highcharts} highcharts/tooltip/backgroundcolor-solid/ + * Yellowish background + * @sample {highcharts} highcharts/tooltip/backgroundcolor-gradient/ + * Gradient + * @sample {highcharts} highcharts/css/tooltip-border-background/ + * Tooltip in styled mode + * @sample {highstock} stock/tooltip/general/ + * Custom tooltip + * @sample {highstock} highcharts/css/tooltip-border-background/ + * Tooltip in styled mode + * @sample {highmaps} maps/tooltip/background-border/ + * Background and border demo + * @sample {highmaps} highcharts/css/tooltip-border-background/ + * Tooltip in styled mode + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + backgroundColor: color('#f7f7f7') + .setOpacity(0.85).get(), + /** + * The pixel width of the tooltip border. + * + * In styled mode, the stroke width is set in the + * `.highcharts-tooltip-box` class. + * + * @sample {highcharts} highcharts/tooltip/bordercolor-default/ + * 2px by default + * @sample {highcharts} highcharts/tooltip/borderwidth/ + * No border (shadow only) + * @sample {highcharts} highcharts/css/tooltip-border-background/ + * Tooltip in styled mode + * @sample {highstock} stock/tooltip/general/ + * Custom tooltip + * @sample {highstock} highcharts/css/tooltip-border-background/ + * Tooltip in styled mode + * @sample {highmaps} maps/tooltip/background-border/ + * Background and border demo + * @sample {highmaps} highcharts/css/tooltip-border-background/ + * Tooltip in styled mode + */ + borderWidth: 1, + /** + * Whether to apply a drop shadow to the tooltip. + * + * @sample {highcharts} highcharts/tooltip/bordercolor-default/ + * True by default + * @sample {highcharts} highcharts/tooltip/shadow/ + * False + * @sample {highmaps} maps/tooltip/positioner/ + * Fixed tooltip position, border and shadow disabled + * + * @type {boolean|Highcharts.ShadowOptionsObject} + */ + shadow: true, + /** + * CSS styles for the tooltip. The tooltip can also be styled through + * the CSS class `.highcharts-tooltip`. + * + * Note that the default `pointerEvents` style makes the tooltip ignore + * mouse events, so in order to use clickable tooltips, this value must + * be set to `auto`. + * + * @sample {highcharts} highcharts/tooltip/style/ + * Greater padding, bold text + * + * @type {Highcharts.CSSObject} + */ + style: { + /** @internal */ + color: '#333333', + /** @internal */ + cursor: 'default', + /** @internal */ + fontSize: '12px', + /** @internal */ + whiteSpace: 'nowrap' + } + }, + /** + * Highchart by default puts a credits label in the lower right corner + * of the chart. This can be changed using these options. + */ + credits: { + /** + * Credits for map source to be concatenated with conventional credit + * text. By default this is a format string that collects copyright + * information from the map if available. + * + * @see [mapTextFull](#credits.mapTextFull) + * @see [text](#credits.text) + * + * @type {string} + * @default \u00a9
{geojson.copyrightShort} + * @since 4.2.2 + * @product highmaps + * @apioption credits.mapText + */ + /** + * Detailed credits for map source to be displayed on hover of credits + * text. By default this is a format string that collects copyright + * information from the map if available. + * + * @see [mapText](#credits.mapText) + * @see [text](#credits.text) + * + * @type {string} + * @default {geojson.copyright} + * @since 4.2.2 + * @product highmaps + * @apioption credits.mapTextFull + */ + /** + * Whether to show the credits text. + * + * @sample {highcharts} highcharts/credits/enabled-false/ + * Credits disabled + * @sample {highstock} stock/credits/enabled/ + * Credits disabled + * @sample {highmaps} maps/credits/enabled-false/ + * Credits disabled + */ + enabled: true, + /** + * The URL for the credits label. + * + * @sample {highcharts} highcharts/credits/href/ + * Custom URL and text + * @sample {highmaps} maps/credits/customized/ + * Custom URL and text + */ + href: 'https://www.highcharts.com?credits', + /** + * Position configuration for the credits label. + * + * @sample {highcharts} highcharts/credits/position-left/ + * Left aligned + * @sample {highcharts} highcharts/credits/position-left/ + * Left aligned + * @sample {highmaps} maps/credits/customized/ + * Left aligned + * @sample {highmaps} maps/credits/customized/ + * Left aligned + * + * @type {Highcharts.AlignObject} + * @since 2.1 + */ + position: { + /** @internal */ + align: 'right', + /** @internal */ + x: -10, + /** @internal */ + verticalAlign: 'bottom', + /** @internal */ + y: -5 + }, + /** + * CSS styles for the credits label. + * + * @see In styled mode, credits styles can be set with the + * `.highcharts-credits` class. + * + * @type {Highcharts.CSSObject} + */ + style: { + /** @internal */ + cursor: 'pointer', + /** @internal */ + color: '#999999', + /** @internal */ + fontSize: '9px' + }, + /** + * The text for the credits label. + * + * @productdesc {highmaps} + * If a map is loaded as GeoJSON, the text defaults to + * `Highcharts @ {map-credits}`. Otherwise, it defaults to + * `Highcharts.com`. + * + * @sample {highcharts} highcharts/credits/href/ + * Custom URL and text + * @sample {highmaps} maps/credits/customized/ + * Custom URL and text + */ + text: 'Highcharts.com' + } + }; + /** + * Merge the default options with custom options and return the new options + * structure. Commonly used for defining reusable templates. + * + * @sample highcharts/global/useutc-false Setting a global option + * @sample highcharts/members/setoptions Applying a global theme + * + * @function Highcharts.setOptions + * + * @param {Highcharts.Options} options + * The new custom chart options. + * + * @return {Highcharts.Options} + * Updated options. + */ + H.setOptions = function (options) { + // Copy in the default options + H.defaultOptions = merge(true, H.defaultOptions, options); + // Update the time object + if (options.time || options.global) { + H.time.update(merge(H.defaultOptions.global, H.defaultOptions.time, options.global, options.time)); + } + return H.defaultOptions; + }; + /** + * Get the updated default options. Until 3.0.7, merely exposing defaultOptions + * for outside modules wasn't enough because the setOptions method created a new + * object. + * + * @function Highcharts.getOptions + * + * @return {Highcharts.Options} + */ + H.getOptions = function () { + return H.defaultOptions; + }; + // Series defaults + H.defaultPlotOptions = H.defaultOptions.plotOptions; + /** + * Global `Time` object with default options. Since v6.0.5, time settings can be + * applied individually for each chart. If no individual settings apply, this + * `Time` object is shared by all instances. + * + * @name Highcharts.time + * @type {Highcharts.Time} + */ + H.time = new Time(merge(H.defaultOptions.global, H.defaultOptions.time)); + /** + * Formats a JavaScript date timestamp (milliseconds since Jan 1st 1970) into a + * human readable date string. The format is a subset of the formats for PHP's + * [strftime](https://www.php.net/manual/en/function.strftime.php) function. + * Additional formats can be given in the {@link Highcharts.dateFormats} hook. + * + * Since v6.0.5, all internal dates are formatted through the + * {@link Highcharts.Chart#time} instance to respect chart-level time settings. + * The `Highcharts.dateFormat` function only reflects global time settings set + * with `setOptions`. + * + * Supported format keys: + * - `%a`: Short weekday, like 'Mon' + * - `%A`: Long weekday, like 'Monday' + * - `%d`: Two digit day of the month, 01 to 31 + * - `%e`: Day of the month, 1 through 31 + * - `%w`: Day of the week, 0 through 6 + * - `%b`: Short month, like 'Jan' + * - `%B`: Long month, like 'January' + * - `%m`: Two digit month number, 01 through 12 + * - `%y`: Two digits year, like 09 for 2009 + * - `%Y`: Four digits year, like 2009 + * - `%H`: Two digits hours in 24h format, 00 through 23 + * - `%k`: Hours in 24h format, 0 through 23 + * - `%I`: Two digits hours in 12h format, 00 through 11 + * - `%l`: Hours in 12h format, 1 through 12 + * - `%M`: Two digits minutes, 00 through 59 + * - `%p`: Upper case AM or PM + * - `%P`: Lower case AM or PM + * - `%S`: Two digits seconds, 00 through 59 + * - `%L`: Milliseconds (naming from Ruby) + * + * @function Highcharts.dateFormat + * + * @param {string} format + * The desired format where various time representations are prefixed + * with `%`. + * + * @param {number} timestamp + * The JavaScript timestamp. + * + * @param {boolean} [capitalize=false] + * Upper case first letter in the return. + * + * @return {string} + * The formatted date. + */ + H.dateFormat = function (format, timestamp, capitalize) { + return H.time.dateFormat(format, timestamp, capitalize); + }; + /* eslint-disable spaced-comment */ + + ''; + + }); + _registerModule(_modules, 'parts/Axis.js', [_modules['parts/Color.js'], _modules['parts/Globals.js'], _modules['parts/Tick.js'], _modules['parts/Utilities.js']], function (Color, H, Tick, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, animObject = U.animObject, arrayMax = U.arrayMax, arrayMin = U.arrayMin, clamp = U.clamp, correctFloat = U.correctFloat, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, error = U.error, extend = U.extend, fireEvent = U.fireEvent, format = U.format, getMagnitude = U.getMagnitude, isArray = U.isArray, isFunction = U.isFunction, isNumber = U.isNumber, isString = U.isString, merge = U.merge, normalizeTickInterval = U.normalizeTickInterval, objectEach = U.objectEach, pick = U.pick, relativeLength = U.relativeLength, removeEvent = U.removeEvent, splat = U.splat, syncTimeout = U.syncTimeout; + /** + * Options for the path on the Axis to be calculated. + * @interface Highcharts.AxisPlotLinePathOptionsObject + */ /** + * Axis value. + * @name Highcharts.AxisPlotLinePathOptionsObject#value + * @type {number|undefined} + */ /** + * Line width used for calculation crisp line coordinates. Defaults to 1. + * @name Highcharts.AxisPlotLinePathOptionsObject#lineWidth + * @type {number|undefined} + */ /** + * If `false`, the function will return null when it falls outside the axis + * bounds. If `true`, the function will return a path aligned to the plot area + * sides if it falls outside. If `pass`, it will return a path outside. + * @name Highcharts.AxisPlotLinePathOptionsObject#force + * @type {string|boolean|undefined} + */ /** + * Used in Highstock. When `true`, plot paths (crosshair, plotLines, gridLines) + * will be rendered on all axes when defined on the first axis. + * @name Highcharts.AxisPlotLinePathOptionsObject#acrossPanes + * @type {boolean|undefined} + */ /** + * Use old coordinates (for resizing and rescaling). + * If not set, defaults to `false`. + * @name Highcharts.AxisPlotLinePathOptionsObject#old + * @type {boolean|undefined} + */ /** + * If given, return the plot line path of a pixel position on the axis. + * @name Highcharts.AxisPlotLinePathOptionsObject#translatedValue + * @type {number|undefined} + */ /** + * Used in Polar axes. Reverse the positions for concatenation of polygonal + * plot bands + * @name Highcharts.AxisPlotLinePathOptionsObject#reverse + * @type {boolean|undefined} + */ + /** + * Options for crosshairs on axes. + * + * @product highstock + * + * @typedef {Highcharts.XAxisCrosshairOptions|Highcharts.YAxisCrosshairOptions} Highcharts.AxisCrosshairOptions + */ + /** + * @typedef {"navigator"|"pan"|"rangeSelectorButton"|"rangeSelectorInput"|"scrollbar"|"traverseUpButton"|"zoom"} Highcharts.AxisExtremesTriggerValue + */ + /** + * @callback Highcharts.AxisEventCallbackFunction + * + * @param {Highcharts.Axis} this + */ + /** + * @interface Highcharts.AxisLabelsFormatterContextObject + */ /** + * @name Highcharts.AxisLabelsFormatterContextObject#axis + * @type {Highcharts.Axis} + */ /** + * @name Highcharts.AxisLabelsFormatterContextObject#chart + * @type {Highcharts.Chart} + */ /** + * @name Highcharts.AxisLabelsFormatterContextObject#isFirst + * @type {boolean} + */ /** + * @name Highcharts.AxisLabelsFormatterContextObject#isLast + * @type {boolean} + */ /** + * @name Highcharts.AxisLabelsFormatterContextObject#pos + * @type {number} + */ /** + * @name Highcharts.AxisLabelsFormatterContextObject#value + * @type {number} + */ + /** + * Options for axes. + * + * @typedef {Highcharts.XAxisOptions|Highcharts.YAxisOptions|Highcharts.ZAxisOptions} Highcharts.AxisOptions + */ + /** + * @callback Highcharts.AxisPointBreakEventCallbackFunction + * + * @param {Highcharts.Axis} this + * + * @param {Highcharts.AxisPointBreakEventObject} evt + */ + /** + * @interface Highcharts.AxisPointBreakEventObject + */ /** + * @name Highcharts.AxisPointBreakEventObject#brk + * @type {Highcharts.Dictionary} + */ /** + * @name Highcharts.AxisPointBreakEventObject#point + * @type {Highcharts.Point} + */ /** + * @name Highcharts.AxisPointBreakEventObject#preventDefault + * @type {Function} + */ /** + * @name Highcharts.AxisPointBreakEventObject#target + * @type {Highcharts.SVGElement} + */ /** + * @name Highcharts.AxisPointBreakEventObject#type + * @type {"pointBreak"|"pointInBreak"} + */ + /** + * @callback Highcharts.AxisSetExtremesEventCallbackFunction + * + * @param {Highcharts.Axis} this + * + * @param {Highcharts.AxisSetExtremesEventObject} evt + */ + /** + * @interface Highcharts.AxisSetExtremesEventObject + * @extends Highcharts.ExtremesObject + */ /** + * @name Highcharts.AxisSetExtremesEventObject#preventDefault + * @type {Function} + */ /** + * @name Highcharts.AxisSetExtremesEventObject#target + * @type {Highcharts.SVGElement} + */ /** + * @name Highcharts.AxisSetExtremesEventObject#trigger + * @type {Highcharts.AxisExtremesTriggerValue|string} + */ /** + * @name Highcharts.AxisSetExtremesEventObject#type + * @type {"setExtremes"} + */ + /** + * @callback Highcharts.AxisTickPositionerCallbackFunction + * + * @param {Highcharts.Axis} this + * + * @return {Array} + */ + /** + * @interface Highcharts.AxisTickPositionsArray + * @augments Array + */ + /** + * @typedef {"high"|"low"|"middle"} Highcharts.AxisTitleAlignValue + */ + /** + * @typedef {Highcharts.XAxisTitleOptions|Highcharts.YAxisTitleOptions|Highcharts.ZAxisTitleOptions} Highcharts.AxisTitleOptions + */ + /** + * @typedef {"linear"|"logarithmic"|"datetime"|"category"|"treegrid"} Highcharts.AxisTypeValue + */ + /** + * The returned object literal from the {@link Highcharts.Axis#getExtremes} + * function. + * + * @interface Highcharts.ExtremesObject + */ /** + * The maximum value of the axis' associated series. + * @name Highcharts.ExtremesObject#dataMax + * @type {number} + */ /** + * The minimum value of the axis' associated series. + * @name Highcharts.ExtremesObject#dataMin + * @type {number} + */ /** + * The maximum axis value, either automatic or set manually. If the `max` option + * is not set, `maxPadding` is 0 and `endOnTick` is false, this value will be + * the same as `dataMax`. + * @name Highcharts.ExtremesObject#max + * @type {number} + */ /** + * The minimum axis value, either automatic or set manually. If the `min` option + * is not set, `minPadding` is 0 and `startOnTick` is false, this value will be + * the same as `dataMin`. + * @name Highcharts.ExtremesObject#min + * @type {number} + */ /** + * The user defined maximum, either from the `max` option or from a zoom or + * `setExtremes` action. + * @name Highcharts.ExtremesObject#userMax + * @type {number} + */ /** + * The user defined minimum, either from the `min` option or from a zoom or + * `setExtremes` action. + * @name Highcharts.ExtremesObject#userMin + * @type {number} + */ + /** + * Formatter function for the text of a crosshair label. + * + * @callback Highcharts.XAxisCrosshairLabelFormatterCallbackFunction + * + * @param {Highcharts.Axis} this + * Axis context + * + * @param {number} value + * Y value of the data point + * + * @return {string} + */ + var defaultOptions = H.defaultOptions, deg2rad = H.deg2rad; + /** + * Create a new axis object. Called internally when instanciating a new chart or + * adding axes by {@link Highcharts.Chart#addAxis}. + * + * A chart can have from 0 axes (pie chart) to multiples. In a normal, single + * series cartesian chart, there is one X axis and one Y axis. + * + * The X axis or axes are referenced by {@link Highcharts.Chart.xAxis}, which is + * an array of Axis objects. If there is only one axis, it can be referenced + * through `chart.xAxis[0]`, and multiple axes have increasing indices. The same + * pattern goes for Y axes. + * + * If you need to get the axes from a series object, use the `series.xAxis` and + * `series.yAxis` properties. These are not arrays, as one series can only be + * associated to one X and one Y axis. + * + * A third way to reference the axis programmatically is by `id`. Add an `id` in + * the axis configuration options, and get the axis by + * {@link Highcharts.Chart#get}. + * + * Configuration options for the axes are given in options.xAxis and + * options.yAxis. + * + * @class + * @name Highcharts.Axis + * + * @param {Highcharts.Chart} chart + * The Chart instance to apply the axis on. + * + * @param {Highcharts.AxisOptions} userOptions + * Axis options. + */ + var Axis = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Axis(chart, userOptions) { + this.alternateBands = void 0; + this.bottom = void 0; + this.categories = void 0; + this.chart = void 0; + this.closestPointRange = void 0; + this.coll = void 0; + this.hasNames = void 0; + this.hasVisibleSeries = void 0; + this.height = void 0; + this.isLinked = void 0; + this.labelEdge = void 0; // @todo + this.labelFormatter = void 0; + this.left = void 0; + this.len = void 0; + this.max = void 0; + this.maxLabelLength = void 0; + this.min = void 0; + this.minorTickInterval = void 0; + this.minorTicks = void 0; + this.minPixelPadding = void 0; + this.names = void 0; + this.offset = void 0; + this.oldMax = void 0; + this.oldMin = void 0; + this.options = void 0; + this.overlap = void 0; + this.paddedTicks = void 0; + this.plotLinesAndBands = void 0; + this.plotLinesAndBandsGroups = void 0; + this.pointRange = void 0; + this.pointRangePadding = void 0; + this.pos = void 0; + this.positiveValuesOnly = void 0; + this.right = void 0; + this.series = void 0; + this.side = void 0; + this.tickAmount = void 0; + this.tickInterval = void 0; + this.tickmarkOffset = void 0; + this.tickPositions = void 0; + this.tickRotCorr = void 0; + this.ticks = void 0; + this.top = void 0; + this.transA = void 0; + this.transB = void 0; + this.translationSlope = void 0; + this.userOptions = void 0; + this.visible = void 0; + this.width = void 0; + this.zoomEnabled = void 0; + this.init(chart, userOptions); + } + /* * + * + * Functions + * + * */ + /** + * Overrideable function to initialize the axis. + * + * @see {@link Axis} + * + * @function Highcharts.Axis#init + * + * @param {Highcharts.Chart} chart + * The Chart instance to apply the axis on. + * + * @param {Highcharts.AxisOptions} userOptions + * Axis options. + * + * @fires Highcharts.Axis#event:afterInit + * @fires Highcharts.Axis#event:init + */ + Axis.prototype.init = function (chart, userOptions) { + var isXAxis = userOptions.isX, axis = this; + /** + * The Chart that the axis belongs to. + * + * @name Highcharts.Axis#chart + * @type {Highcharts.Chart} + */ + axis.chart = chart; + /** + * Whether the axis is horizontal. + * + * @name Highcharts.Axis#horiz + * @type {boolean|undefined} + */ + axis.horiz = chart.inverted && !axis.isZAxis ? !isXAxis : isXAxis; + /** + * Whether the axis is the x-axis. + * + * @name Highcharts.Axis#isXAxis + * @type {boolean|undefined} + */ + axis.isXAxis = isXAxis; + /** + * The collection where the axis belongs, for example `xAxis`, `yAxis` + * or `colorAxis`. Corresponds to properties on Chart, for example + * {@link Chart.xAxis}. + * + * @name Highcharts.Axis#coll + * @type {string} + */ + axis.coll = axis.coll || (isXAxis ? 'xAxis' : 'yAxis'); + fireEvent(this, 'init', { userOptions: userOptions }); + axis.opposite = userOptions.opposite; // needed in setOptions + /** + * The side on which the axis is rendered. 0 is top, 1 is right, 2 + * is bottom and 3 is left. + * + * @name Highcharts.Axis#side + * @type {number} + */ + axis.side = userOptions.side || (axis.horiz ? + (axis.opposite ? 0 : 2) : // top : bottom + (axis.opposite ? 1 : 3)); // right : left + /** + * Current options for the axis after merge of defaults and user's + * options. + * + * @name Highcharts.Axis#options + * @type {Highcharts.AxisOptions} + */ + axis.setOptions(userOptions); + var options = this.options, type = options.type; + axis.labelFormatter = (options.labels.formatter || + // can be overwritten by dynamic format + axis.defaultLabelFormatter); + /** + * User's options for this axis without defaults. + * + * @name Highcharts.Axis#userOptions + * @type {Highcharts.AxisOptions} + */ + axis.userOptions = userOptions; + axis.minPixelPadding = 0; + /** + * Whether the axis is reversed. Based on the `axis.reversed`, + * option, but inverted charts have reversed xAxis by default. + * + * @name Highcharts.Axis#reversed + * @type {boolean} + */ + axis.reversed = options.reversed; + axis.visible = options.visible !== false; + axis.zoomEnabled = options.zoomEnabled !== false; + // Initial categories + axis.hasNames = + type === 'category' || options.categories === true; + /** + * If categories are present for the axis, names are used instead of + * numbers for that axis. + * + * Since Highcharts 3.0, categories can also be extracted by giving each + * point a name and setting axis type to `category`. However, if you + * have multiple series, best practice remains defining the `categories` + * array. + * + * @see [xAxis.categories](/highcharts/xAxis.categories) + * + * @name Highcharts.Axis#categories + * @type {Array} + * @readonly + */ + axis.categories = options.categories || axis.hasNames; + if (!axis.names) { // Preserve on update (#3830) + axis.names = []; + axis.names.keys = {}; + } + // Placeholder for plotlines and plotbands groups + axis.plotLinesAndBandsGroups = {}; + // Shorthand types + axis.positiveValuesOnly = !!(axis.logarithmic && !options.allowNegativeLog); + // Flag, if axis is linked to another axis + axis.isLinked = defined(options.linkedTo); + /** + * List of major ticks mapped by postition on axis. + * + * @see {@link Highcharts.Tick} + * + * @name Highcharts.Axis#ticks + * @type {Highcharts.Dictionary} + */ + axis.ticks = {}; + axis.labelEdge = []; + /** + * List of minor ticks mapped by position on the axis. + * + * @see {@link Highcharts.Tick} + * + * @name Highcharts.Axis#minorTicks + * @type {Highcharts.Dictionary} + */ + axis.minorTicks = {}; + // List of plotLines/Bands + axis.plotLinesAndBands = []; + // Alternate bands + axis.alternateBands = {}; + // Axis metrics + axis.len = 0; + axis.minRange = axis.userMinRange = options.minRange || options.maxZoom; + axis.range = options.range; + axis.offset = options.offset || 0; + /** + * The maximum value of the axis. In a logarithmic axis, this is the + * logarithm of the real value, and the real value can be obtained from + * {@link Axis#getExtremes}. + * + * @name Highcharts.Axis#max + * @type {number|null} + */ + axis.max = null; + /** + * The minimum value of the axis. In a logarithmic axis, this is the + * logarithm of the real value, and the real value can be obtained from + * {@link Axis#getExtremes}. + * + * @name Highcharts.Axis#min + * @type {number|null} + */ + axis.min = null; + /** + * The processed crosshair options. + * + * @name Highcharts.Axis#crosshair + * @type {boolean|Highcharts.AxisCrosshairOptions} + */ + axis.crosshair = pick(options.crosshair, splat(chart.options.tooltip.crosshairs)[isXAxis ? 0 : 1], false); + var events = axis.options.events; + // Register. Don't add it again on Axis.update(). + if (chart.axes.indexOf(axis) === -1) { // + if (isXAxis) { // #2713 + chart.axes.splice(chart.xAxis.length, 0, axis); + } + else { + chart.axes.push(axis); + } + chart[axis.coll].push(axis); + } + /** + * All series associated to the axis. + * + * @name Highcharts.Axis#series + * @type {Array} + */ + axis.series = axis.series || []; // populated by Series + // Reversed axis + if (chart.inverted && + !axis.isZAxis && + isXAxis && + typeof axis.reversed === 'undefined') { + axis.reversed = true; + } + axis.labelRotation = axis.options.labels.rotation; + // register event listeners + objectEach(events, function (event, eventType) { + if (isFunction(event)) { + addEvent(axis, eventType, event); + } + }); + fireEvent(this, 'afterInit'); + }; + /** + * Merge and set options. + * + * @private + * @function Highcharts.Axis#setOptions + * + * @param {Highcharts.AxisOptions} userOptions + * Axis options. + * + * @fires Highcharts.Axis#event:afterSetOptions + */ + Axis.prototype.setOptions = function (userOptions) { + this.options = merge(Axis.defaultOptions, (this.coll === 'yAxis') && Axis.defaultYAxisOptions, [ + Axis.defaultTopAxisOptions, + Axis.defaultRightAxisOptions, + Axis.defaultBottomAxisOptions, + Axis.defaultLeftAxisOptions + ][this.side], merge( + // if set in setOptions (#1053): + defaultOptions[this.coll], userOptions)); + fireEvent(this, 'afterSetOptions', { userOptions: userOptions }); + }; + /** + * The default label formatter. The context is a special config object for + * the label. In apps, use the + * [labels.formatter](https://api.highcharts.com/highcharts/xAxis.labels.formatter) + * instead, except when a modification is needed. + * + * @function Highcharts.Axis#defaultLabelFormatter + * + * @param {Highcharts.AxisLabelsFormatterContextObject} this + * Formatter context of axis label. + * + * @return {string} + * The formatted label content. + */ + Axis.prototype.defaultLabelFormatter = function () { + var axis = this.axis, value = this.value, time = axis.chart.time, categories = axis.categories, dateTimeLabelFormat = this.dateTimeLabelFormat, lang = defaultOptions.lang, numericSymbols = lang.numericSymbols, numSymMagnitude = lang.numericSymbolMagnitude || 1000, i = numericSymbols && numericSymbols.length, multi, ret, formatOption = axis.options.labels.format, + // make sure the same symbol is added for all labels on a linear + // axis + numericSymbolDetector = axis.logarithmic ? + Math.abs(value) : + axis.tickInterval; + var chart = this.chart; + var numberFormatter = chart.numberFormatter; + if (formatOption) { + ret = format(formatOption, this, chart); + } + else if (categories) { + ret = value; + } + else if (dateTimeLabelFormat) { // datetime axis + ret = time.dateFormat(dateTimeLabelFormat, value); + } + else if (i && numericSymbolDetector >= 1000) { + // Decide whether we should add a numeric symbol like k (thousands) + // or M (millions). If we are to enable this in tooltip or other + // places as well, we can move this logic to the numberFormatter and + // enable it by a parameter. + while (i-- && typeof ret === 'undefined') { + multi = Math.pow(numSymMagnitude, i + 1); + if ( + // Only accept a numeric symbol when the distance is more + // than a full unit. So for example if the symbol is k, we + // don't accept numbers like 0.5k. + numericSymbolDetector >= multi && + // Accept one decimal before the symbol. Accepts 0.5k but + // not 0.25k. How does this work with the previous? + (value * 10) % multi === 0 && + numericSymbols[i] !== null && + value !== 0) { // #5480 + ret = numberFormatter(value / multi, -1) + + numericSymbols[i]; + } + } + } + if (typeof ret === 'undefined') { + if (Math.abs(value) >= 10000) { // add thousands separators + ret = numberFormatter(value, -1); + } + else { // small numbers + ret = numberFormatter(value, -1, void 0, ''); // #2466 + } + } + return ret; + }; + /** + * Get the minimum and maximum for the series of each axis. The function + * analyzes the axis series and updates `this.dataMin` and `this.dataMax`. + * + * @private + * @function Highcharts.Axis#getSeriesExtremes + * + * @fires Highcharts.Axis#event:afterGetSeriesExtremes + * @fires Highcharts.Axis#event:getSeriesExtremes + */ + Axis.prototype.getSeriesExtremes = function () { + var axis = this, chart = axis.chart, xExtremes; + fireEvent(this, 'getSeriesExtremes', null, function () { + axis.hasVisibleSeries = false; + // Reset properties in case we're redrawing (#3353) + axis.dataMin = axis.dataMax = axis.threshold = null; + axis.softThreshold = !axis.isXAxis; + if (axis.stacking) { + axis.stacking.buildStacks(); + } + // loop through this axis' series + axis.series.forEach(function (series) { + if (series.visible || + !chart.options.chart.ignoreHiddenSeries) { + var seriesOptions = series.options, xData, threshold = seriesOptions.threshold, seriesDataMin, seriesDataMax; + axis.hasVisibleSeries = true; + // Validate threshold in logarithmic axes + if (axis.positiveValuesOnly && threshold <= 0) { + threshold = null; + } + // Get dataMin and dataMax for X axes + if (axis.isXAxis) { + xData = series.xData; + if (xData.length) { + xExtremes = series.getXExtremes(xData); + // If xData contains values which is not numbers, + // then filter them out. To prevent performance hit, + // we only do this after we have already found + // seriesDataMin because in most cases all data is + // valid. #5234. + seriesDataMin = xExtremes.min; + seriesDataMax = xExtremes.max; + if (!isNumber(seriesDataMin) && + // #5010: + !(seriesDataMin instanceof Date)) { + xData = xData.filter(isNumber); + xExtremes = series.getXExtremes(xData); + // Do it again with valid data + seriesDataMin = xExtremes.min; + seriesDataMax = xExtremes.max; + } + if (xData.length) { + axis.dataMin = Math.min(pick(axis.dataMin, seriesDataMin), seriesDataMin); + axis.dataMax = Math.max(pick(axis.dataMax, seriesDataMax), seriesDataMax); + } + } + // Get dataMin and dataMax for Y axes, as well as handle + // stacking and processed data + } + else { + // Get this particular series extremes + var dataExtremes = series.applyExtremes(); + // Get the dataMin and dataMax so far. If percentage is + // used, the min and max are always 0 and 100. If + // seriesDataMin and seriesDataMax is null, then series + // doesn't have active y data, we continue with nulls + if (isNumber(dataExtremes.dataMin)) { + seriesDataMin = dataExtremes.dataMin; + axis.dataMin = Math.min(pick(axis.dataMin, seriesDataMin), seriesDataMin); + } + if (isNumber(dataExtremes.dataMax)) { + seriesDataMax = dataExtremes.dataMax; + axis.dataMax = Math.max(pick(axis.dataMax, seriesDataMax), seriesDataMax); + } + // Adjust to threshold + if (defined(threshold)) { + axis.threshold = threshold; + } + // If any series has a hard threshold, it takes + // precedence + if (!seriesOptions.softThreshold || + axis.positiveValuesOnly) { + axis.softThreshold = false; + } + } + } + }); + }); + fireEvent(this, 'afterGetSeriesExtremes'); + }; + /** + * Translate from axis value to pixel position on the chart, or back. Use + * the `toPixels` and `toValue` functions in applications. + * + * @private + * @function Highcharts.Axis#translate + * + * @param {number} val + * TO-DO: parameter description + * + * @param {boolean|null} [backwards] + * TO-DO: parameter description + * + * @param {boolean|null} [cvsCoord] + * TO-DO: parameter description + * + * @param {boolean|null} [old] + * TO-DO: parameter description + * + * @param {boolean} [handleLog] + * TO-DO: parameter description + * + * @param {number} [pointPlacement] + * TO-DO: parameter description + * + * @return {number|undefined} + */ + Axis.prototype.translate = function (val, backwards, cvsCoord, old, handleLog, pointPlacement) { + var axis = this.linkedParent || this, // #1417 + sign = 1, cvsOffset = 0, localA = old ? axis.oldTransA : axis.transA, localMin = old ? axis.oldMin : axis.min, returnValue = 0, minPixelPadding = axis.minPixelPadding, doPostTranslate = (axis.isOrdinal || + axis.brokenAxis && axis.brokenAxis.hasBreaks || + (axis.logarithmic && handleLog)) && axis.lin2val; + if (!localA) { + localA = axis.transA; + } + // In vertical axes, the canvas coordinates start from 0 at the top like + // in SVG. + if (cvsCoord) { + sign *= -1; // canvas coordinates inverts the value + cvsOffset = axis.len; + } + // Handle reversed axis + if (axis.reversed) { + sign *= -1; + cvsOffset -= sign * (axis.sector || axis.len); + } + // From pixels to value + if (backwards) { // reverse translation + val = val * sign + cvsOffset; + val -= minPixelPadding; + // from chart pixel to value: + returnValue = val / localA + localMin; + if (doPostTranslate) { // log and ordinal axes + returnValue = axis.lin2val(returnValue); + } + // From value to pixels + } + else { + if (doPostTranslate) { // log and ordinal axes + val = axis.val2lin(val); + } + returnValue = isNumber(localMin) ? + (sign * (val - localMin) * localA + + cvsOffset + + (sign * minPixelPadding) + + (isNumber(pointPlacement) ? + localA * pointPlacement : + 0)) : + void 0; + } + return returnValue; + }; + /** + * Translate a value in terms of axis units into pixels within the chart. + * + * @function Highcharts.Axis#toPixels + * + * @param {number} value + * A value in terms of axis units. + * + * @param {boolean} paneCoordinates + * Whether to return the pixel coordinate relative to the chart or just the + * axis/pane itself. + * + * @return {number} + * Pixel position of the value on the chart or axis. + */ + Axis.prototype.toPixels = function (value, paneCoordinates) { + return this.translate(value, false, !this.horiz, null, true) + + (paneCoordinates ? 0 : this.pos); + }; + /** + * Translate a pixel position along the axis to a value in terms of axis + * units. + * + * @function Highcharts.Axis#toValue + * + * @param {number} pixel + * The pixel value coordinate. + * + * @param {boolean} [paneCoordinates=false] + * Whether the input pixel is relative to the chart or just the axis/pane + * itself. + * + * @return {number} + * The axis value. + */ + Axis.prototype.toValue = function (pixel, paneCoordinates) { + return this.translate(pixel - (paneCoordinates ? 0 : this.pos), true, !this.horiz, null, true); + }; + /** + * Create the path for a plot line that goes from the given value on + * this axis, across the plot to the opposite side. Also used internally for + * grid lines and crosshairs. + * + * @function Highcharts.Axis#getPlotLinePath + * + * @param {Highcharts.AxisPlotLinePathOptionsObject} options + * Options for the path. + * + * @return {Highcharts.SVGPathArray|null} + * The SVG path definition for the plot line. + */ + Axis.prototype.getPlotLinePath = function (options) { + var axis = this, chart = axis.chart, axisLeft = axis.left, axisTop = axis.top, old = options.old, value = options.value, translatedValue = options.translatedValue, lineWidth = options.lineWidth, force = options.force, x1, y1, x2, y2, cHeight = (old && chart.oldChartHeight) || chart.chartHeight, cWidth = (old && chart.oldChartWidth) || chart.chartWidth, skip, transB = axis.transB, evt; + // eslint-disable-next-line valid-jsdoc + /** + * Check if x is between a and b. If not, either move to a/b + * or skip, depending on the force parameter. + * @private + */ + function between(x, a, b) { + if (force !== 'pass' && x < a || x > b) { + if (force) { + x = clamp(x, a, b); + } + else { + skip = true; + } + } + return x; + } + evt = { + value: value, + lineWidth: lineWidth, + old: old, + force: force, + acrossPanes: options.acrossPanes, + translatedValue: translatedValue + }; + fireEvent(this, 'getPlotLinePath', evt, function (e) { + translatedValue = pick(translatedValue, axis.translate(value, null, null, old)); + // Keep the translated value within sane bounds, and avoid Infinity + // to fail the isNumber test (#7709). + translatedValue = clamp(translatedValue, -1e5, 1e5); + x1 = x2 = Math.round(translatedValue + transB); + y1 = y2 = Math.round(cHeight - translatedValue - transB); + if (!isNumber(translatedValue)) { // no min or max + skip = true; + force = false; // #7175, don't force it when path is invalid + } + else if (axis.horiz) { + y1 = axisTop; + y2 = cHeight - axis.bottom; + x1 = x2 = between(x1, axisLeft, axisLeft + axis.width); + } + else { + x1 = axisLeft; + x2 = cWidth - axis.right; + y1 = y2 = between(y1, axisTop, axisTop + axis.height); + } + e.path = skip && !force ? + null : + chart.renderer.crispLine([['M', x1, y1], ['L', x2, y2]], lineWidth || 1); + }); + return evt.path; + }; + /** + * Internal function to et the tick positions of a linear axis to round + * values like whole tens or every five. + * + * @function Highcharts.Axis#getLinearTickPositions + * + * @param {number} tickInterval + * The normalized tick interval. + * + * @param {number} min + * Axis minimum. + * + * @param {number} max + * Axis maximum. + * + * @return {Array} + * An array of axis values where ticks should be placed. + */ + Axis.prototype.getLinearTickPositions = function (tickInterval, min, max) { + var pos, lastPos, roundedMin = correctFloat(Math.floor(min / tickInterval) * tickInterval), roundedMax = correctFloat(Math.ceil(max / tickInterval) * tickInterval), tickPositions = [], precision; + // When the precision is higher than what we filter out in + // correctFloat, skip it (#6183). + if (correctFloat(roundedMin + tickInterval) === roundedMin) { + precision = 20; + } + // For single points, add a tick regardless of the relative position + // (#2662, #6274) + if (this.single) { + return [min]; + } + // Populate the intermediate values + pos = roundedMin; + while (pos <= roundedMax) { + // Place the tick on the rounded value + tickPositions.push(pos); + // Always add the raw tickInterval, not the corrected one. + pos = correctFloat(pos + tickInterval, precision); + // If the interval is not big enough in the current min - max range + // to actually increase the loop variable, we need to break out to + // prevent endless loop. Issue #619 + if (pos === lastPos) { + break; + } + // Record the last value + lastPos = pos; + } + return tickPositions; + }; + /** + * Resolve the new minorTicks/minorTickInterval options into the legacy + * loosely typed minorTickInterval option. + * + * @function Highcharts.Axis#getMinorTickInterval + * + * @return {number|"auto"|null} + */ + Axis.prototype.getMinorTickInterval = function () { + var options = this.options; + if (options.minorTicks === true) { + return pick(options.minorTickInterval, 'auto'); + } + if (options.minorTicks === false) { + return null; + } + return options.minorTickInterval; + }; + /** + * Internal function to return the minor tick positions. For logarithmic + * axes, the same logic as for major ticks is reused. + * + * @function Highcharts.Axis#getMinorTickPositions + * + * @return {Array} + * An array of axis values where ticks should be placed. + */ + Axis.prototype.getMinorTickPositions = function () { + var axis = this, options = axis.options, tickPositions = axis.tickPositions, minorTickInterval = axis.minorTickInterval, minorTickPositions = [], pos, pointRangePadding = axis.pointRangePadding || 0, min = axis.min - pointRangePadding, // #1498 + max = axis.max + pointRangePadding, // #1498 + range = max - min; + // If minor ticks get too dense, they are hard to read, and may cause + // long running script. So we don't draw them. + if (range && range / minorTickInterval < axis.len / 3) { // #3875 + var logarithmic_1 = axis.logarithmic; + if (logarithmic_1) { + // For each interval in the major ticks, compute the minor ticks + // separately. + this.paddedTicks.forEach(function (_pos, i, paddedTicks) { + if (i) { + minorTickPositions.push.apply(minorTickPositions, logarithmic_1.getLogTickPositions(minorTickInterval, paddedTicks[i - 1], paddedTicks[i], true)); + } + }); + } + else if (axis.dateTime && + this.getMinorTickInterval() === 'auto') { // #1314 + minorTickPositions = minorTickPositions.concat(axis.getTimeTicks(axis.dateTime.normalizeTimeTickInterval(minorTickInterval), min, max, options.startOfWeek)); + } + else { + for (pos = min + (tickPositions[0] - min) % minorTickInterval; pos <= max; pos += minorTickInterval) { + // Very, very, tight grid lines (#5771) + if (pos === minorTickPositions[0]) { + break; + } + minorTickPositions.push(pos); + } + } + } + if (minorTickPositions.length !== 0) { + axis.trimTicks(minorTickPositions); // #3652 #3743 #1498 #6330 + } + return minorTickPositions; + }; + /** + * Adjust the min and max for the minimum range. Keep in mind that the + * series data is not yet processed, so we don't have information on data + * cropping and grouping, or updated `axis.pointRange` or + * `series.pointRange`. The data can't be processed until we have finally + * established min and max. + * + * @private + * @function Highcharts.Axis#adjustForMinRange + */ + Axis.prototype.adjustForMinRange = function () { + var axis = this, options = axis.options, min = axis.min, max = axis.max, log = axis.logarithmic, zoomOffset, spaceAvailable, closestDataRange, i, distance, xData, loopLength, minArgs, maxArgs, minRange; + // Set the automatic minimum range based on the closest point distance + if (axis.isXAxis && + typeof axis.minRange === 'undefined' && + !log) { + if (defined(options.min) || defined(options.max)) { + axis.minRange = null; // don't do this again + } + else { + // Find the closest distance between raw data points, as opposed + // to closestPointRange that applies to processed points + // (cropped and grouped) + axis.series.forEach(function (series) { + xData = series.xData; + loopLength = series.xIncrement ? 1 : xData.length - 1; + for (i = loopLength; i > 0; i--) { + distance = xData[i] - xData[i - 1]; + if (typeof closestDataRange === 'undefined' || + distance < closestDataRange) { + closestDataRange = distance; + } + } + }); + axis.minRange = Math.min(closestDataRange * 5, axis.dataMax - axis.dataMin); + } + } + // if minRange is exceeded, adjust + if (max - min < axis.minRange) { + spaceAvailable = + axis.dataMax - axis.dataMin >= + axis.minRange; + minRange = axis.minRange; + zoomOffset = (minRange - max + min) / 2; + // if min and max options have been set, don't go beyond it + minArgs = [ + min - zoomOffset, + pick(options.min, min - zoomOffset) + ]; + // If space is available, stay within the data range + if (spaceAvailable) { + minArgs[2] = axis.logarithmic ? + axis.logarithmic.log2lin(axis.dataMin) : + axis.dataMin; + } + min = arrayMax(minArgs); + maxArgs = [ + min + minRange, + pick(options.max, min + minRange) + ]; + // If space is availabe, stay within the data range + if (spaceAvailable) { + maxArgs[2] = log ? + log.log2lin(axis.dataMax) : + axis.dataMax; + } + max = arrayMin(maxArgs); + // now if the max is adjusted, adjust the min back + if (max - min < minRange) { + minArgs[0] = max - minRange; + minArgs[1] = pick(options.min, max - minRange); + min = arrayMax(minArgs); + } + } + // Record modified extremes + axis.min = min; + axis.max = max; + }; + // eslint-disable-next-line valid-jsdoc + /** + * Find the closestPointRange across all series. + * + * @private + * @function Highcharts.Axis#getClosest + */ + Axis.prototype.getClosest = function () { + var ret; + if (this.categories) { + ret = 1; + } + else { + this.series.forEach(function (series) { + var seriesClosest = series.closestPointRange, visible = series.visible || + !series.chart.options.chart.ignoreHiddenSeries; + if (!series.noSharedTooltip && + defined(seriesClosest) && + visible) { + ret = defined(ret) ? + Math.min(ret, seriesClosest) : + seriesClosest; + } + }); + } + return ret; + }; + /** + * When a point name is given and no x, search for the name in the existing + * categories, or if categories aren't provided, search names or create a + * new category (#2522). + * @private + * @function Highcharts.Axis#nameToX + * + * @param {Highcharts.Point} point + * The point to inspect. + * + * @return {number} + * The X value that the point is given. + */ + Axis.prototype.nameToX = function (point) { + var explicitCategories = isArray(this.categories), names = explicitCategories ? this.categories : this.names, nameX = point.options.x, x; + point.series.requireSorting = false; + if (!defined(nameX)) { + nameX = this.options.uniqueNames === false ? + point.series.autoIncrement() : + (explicitCategories ? + names.indexOf(point.name) : + pick(names.keys[point.name], -1)); + } + if (nameX === -1) { // Not found in currenct categories + if (!explicitCategories) { + x = names.length; + } + } + else { + x = nameX; + } + // Write the last point's name to the names array + if (typeof x !== 'undefined') { + this.names[x] = point.name; + // Backwards mapping is much faster than array searching (#7725) + this.names.keys[point.name] = x; + } + return x; + }; + /** + * When changes have been done to series data, update the axis.names. + * + * @private + * @function Highcharts.Axis#updateNames + */ + Axis.prototype.updateNames = function () { + var axis = this, names = this.names, i = names.length; + if (i > 0) { + Object.keys(names.keys).forEach(function (key) { + delete (names.keys)[key]; + }); + names.length = 0; + this.minRange = this.userMinRange; // Reset + (this.series || []).forEach(function (series) { + // Reset incrementer (#5928) + series.xIncrement = null; + // When adding a series, points are not yet generated + if (!series.points || series.isDirtyData) { + // When we're updating the series with data that is longer + // than it was, and cropThreshold is passed, we need to make + // sure that the axis.max is increased _before_ running the + // premature processData. Otherwise this early iteration of + // processData will crop the points to axis.max, and the + // names array will be too short (#5857). + axis.max = Math.max(axis.max, series.xData.length - 1); + series.processData(); + series.generatePoints(); + } + series.data.forEach(function (point, i) { + var x; + if (point && + point.options && + typeof point.name !== 'undefined' // #9562 + ) { + x = axis.nameToX(point); + if (typeof x !== 'undefined' && x !== point.x) { + point.x = x; + series.xData[i] = x; + } + } + }); + }); + } + }; + /** + * Update translation information. + * + * @private + * @function Highcharts.Axis#setAxisTranslation + * + * @param {boolean} [saveOld] + * TO-DO: parameter description + * + * @fires Highcharts.Axis#event:afterSetAxisTranslation + */ + Axis.prototype.setAxisTranslation = function (saveOld) { + var axis = this, range = axis.max - axis.min, pointRange = axis.axisPointRange || 0, closestPointRange, minPointOffset = 0, pointRangePadding = 0, linkedParent = axis.linkedParent, ordinalCorrection, hasCategories = !!axis.categories, transA = axis.transA, isXAxis = axis.isXAxis; + // Adjust translation for padding. Y axis with categories need to go + // through the same (#1784). + if (isXAxis || hasCategories || pointRange) { + // Get the closest points + closestPointRange = axis.getClosest(); + if (linkedParent) { + minPointOffset = linkedParent.minPointOffset; + pointRangePadding = linkedParent.pointRangePadding; + } + else { + axis.series.forEach(function (series) { + var seriesPointRange = hasCategories ? + 1 : + (isXAxis ? + pick(series.options.pointRange, closestPointRange, 0) : + (axis.axisPointRange || 0)), // #2806 + pointPlacement = series.options.pointPlacement; + pointRange = Math.max(pointRange, seriesPointRange); + if (!axis.single || hasCategories) { + // TODO: series should internally set x- and y- + // pointPlacement to simplify this logic. + var isPointPlacementAxis = series.is('xrange') ? !isXAxis : isXAxis; + // minPointOffset is the value padding to the left of + // the axis in order to make room for points with a + // pointRange, typically columns. When the + // pointPlacement option is 'between' or 'on', this + // padding does not apply. + minPointOffset = Math.max(minPointOffset, isPointPlacementAxis && isString(pointPlacement) ? + 0 : + seriesPointRange / 2); + // Determine the total padding needed to the length of + // the axis to make room for the pointRange. If the + // series' pointPlacement is 'on', no padding is added. + pointRangePadding = Math.max(pointRangePadding, isPointPlacementAxis && pointPlacement === 'on' ? + 0 : + seriesPointRange); + } + }); + } + // Record minPointOffset and pointRangePadding + ordinalCorrection = axis.ordinal && axis.ordinal.slope && closestPointRange ? + axis.ordinal.slope / closestPointRange : + 1; // #988, #1853 + axis.minPointOffset = minPointOffset = + minPointOffset * ordinalCorrection; + axis.pointRangePadding = + pointRangePadding = pointRangePadding * ordinalCorrection; + // pointRange means the width reserved for each point, like in a + // column chart + axis.pointRange = Math.min(pointRange, axis.single && hasCategories ? 1 : range); + // closestPointRange means the closest distance between points. In + // columns it is mostly equal to pointRange, but in lines pointRange + // is 0 while closestPointRange is some other value + if (isXAxis) { + axis.closestPointRange = closestPointRange; + } + } + // Secondary values + if (saveOld) { + axis.oldTransA = transA; + } + axis.translationSlope = axis.transA = transA = + axis.staticScale || + axis.len / ((range + pointRangePadding) || 1); + // Translation addend + axis.transB = axis.horiz ? axis.left : axis.bottom; + axis.minPixelPadding = transA * minPointOffset; + fireEvent(this, 'afterSetAxisTranslation'); + }; + /** + * @private + * @function Highcharts.Axis#minFromRange + * + * @return {number} + */ + Axis.prototype.minFromRange = function () { + var axis = this; + return axis.max - axis.range; + }; + /** + * Set the tick positions to round values and optionally extend the extremes + * to the nearest tick. + * + * @private + * @function Highcharts.Axis#setTickInterval + * + * @param {boolean} secondPass + * TO-DO: parameter description + * + * @fires Highcharts.Axis#event:foundExtremes + */ + Axis.prototype.setTickInterval = function (secondPass) { + var axis = this, chart = axis.chart, log = axis.logarithmic, options = axis.options, isXAxis = axis.isXAxis, isLinked = axis.isLinked, maxPadding = options.maxPadding, minPadding = options.minPadding, length, linkedParentExtremes, tickIntervalOption = options.tickInterval, minTickInterval, tickPixelIntervalOption = options.tickPixelInterval, categories = axis.categories, threshold = isNumber(axis.threshold) ? axis.threshold : null, softThreshold = axis.softThreshold, thresholdMin, thresholdMax, hardMin, hardMax; + if (!axis.dateTime && !categories && !isLinked) { + this.getTickAmount(); + } + // Min or max set either by zooming/setExtremes or initial options + hardMin = pick(axis.userMin, options.min); + hardMax = pick(axis.userMax, options.max); + // Linked axis gets the extremes from the parent axis + if (isLinked) { + axis.linkedParent = chart[axis.coll][options.linkedTo]; + linkedParentExtremes = axis.linkedParent.getExtremes(); + axis.min = pick(linkedParentExtremes.min, linkedParentExtremes.dataMin); + axis.max = pick(linkedParentExtremes.max, linkedParentExtremes.dataMax); + if (options.type !== axis.linkedParent.options.type) { + // Can't link axes of different type + error(11, 1, chart); + } + // Initial min and max from the extreme data values + } + else { + // Adjust to hard threshold + if (!softThreshold && defined(threshold)) { + if (axis.dataMin >= threshold) { + thresholdMin = threshold; + minPadding = 0; + } + else if (axis.dataMax <= threshold) { + thresholdMax = threshold; + maxPadding = 0; + } + } + axis.min = pick(hardMin, thresholdMin, axis.dataMin); + axis.max = pick(hardMax, thresholdMax, axis.dataMax); + } + if (log) { + if (axis.positiveValuesOnly && + !secondPass && + Math.min(axis.min, pick(axis.dataMin, axis.min)) <= 0) { // #978 + // Can't plot negative values on log axis + error(10, 1, chart); + } + // The correctFloat cures #934, float errors on full tens. But it + // was too aggressive for #4360 because of conversion back to lin, + // therefore use precision 15. + axis.min = correctFloat(log.log2lin(axis.min), 16); + axis.max = correctFloat(log.log2lin(axis.max), 16); + } + // handle zoomed range + if (axis.range && defined(axis.max)) { + // #618, #6773: + axis.userMin = axis.min = hardMin = + Math.max(axis.dataMin, axis.minFromRange()); + axis.userMax = hardMax = axis.max; + axis.range = null; // don't use it when running setExtremes + } + // Hook for Highstock Scroller. Consider combining with beforePadding. + fireEvent(axis, 'foundExtremes'); + // Hook for adjusting this.min and this.max. Used by bubble series. + if (axis.beforePadding) { + axis.beforePadding(); + } + // adjust min and max for the minimum range + axis.adjustForMinRange(); + // Pad the values to get clear of the chart's edges. To avoid + // tickInterval taking the padding into account, we do this after + // computing tick interval (#1337). + if (!categories && + !axis.axisPointRange && + !(axis.stacking && axis.stacking.usePercentage) && + !isLinked && + defined(axis.min) && + defined(axis.max)) { + length = axis.max - axis.min; + if (length) { + if (!defined(hardMin) && minPadding) { + axis.min -= length * minPadding; + } + if (!defined(hardMax) && maxPadding) { + axis.max += length * maxPadding; + } + } + } + // Handle options for floor, ceiling, softMin and softMax (#6359) + if (!isNumber(axis.userMin)) { + if (isNumber(options.softMin) && options.softMin < axis.min) { + axis.min = hardMin = options.softMin; // #6894 + } + if (isNumber(options.floor)) { + axis.min = Math.max(axis.min, options.floor); + } + } + if (!isNumber(axis.userMax)) { + if (isNumber(options.softMax) && options.softMax > axis.max) { + axis.max = hardMax = options.softMax; // #6894 + } + if (isNumber(options.ceiling)) { + axis.max = Math.min(axis.max, options.ceiling); + } + } + // When the threshold is soft, adjust the extreme value only if the data + // extreme and the padded extreme land on either side of the threshold. + // For example, a series of [0, 1, 2, 3] would make the yAxis add a tick + // for -1 because of the default minPadding and startOnTick options. + // This is prevented by the softThreshold option. + if (softThreshold && defined(axis.dataMin)) { + threshold = threshold || 0; + if (!defined(hardMin) && + axis.min < threshold && + axis.dataMin >= threshold) { + axis.min = axis.options.minRange ? + Math.min(threshold, axis.max - + axis.minRange) : + threshold; + } + else if (!defined(hardMax) && + axis.max > threshold && + axis.dataMax <= threshold) { + axis.max = axis.options.minRange ? + Math.max(threshold, axis.min + + axis.minRange) : + threshold; + } + } + // get tickInterval + if (axis.min === axis.max || + typeof axis.min === 'undefined' || + typeof axis.max === 'undefined') { + axis.tickInterval = 1; + } + else if (isLinked && + !tickIntervalOption && + tickPixelIntervalOption === + axis.linkedParent.options.tickPixelInterval) { + axis.tickInterval = tickIntervalOption = + axis.linkedParent.tickInterval; + } + else { + axis.tickInterval = pick(tickIntervalOption, this.tickAmount ? + ((axis.max - axis.min) / + Math.max(this.tickAmount - 1, 1)) : + void 0, + // For categoried axis, 1 is default, for linear axis use + // tickPix + categories ? + 1 : + // don't let it be more than the data range + (axis.max - axis.min) * + tickPixelIntervalOption / + Math.max(axis.len, tickPixelIntervalOption)); + } + // Now we're finished detecting min and max, crop and group series data. + // This is in turn needed in order to find tick positions in ordinal + // axes. + if (isXAxis && !secondPass) { + axis.series.forEach(function (series) { + series.processData(axis.min !== axis.oldMin || axis.max !== axis.oldMax); + }); + } + // set the translation factor used in translate function + axis.setAxisTranslation(true); + // hook for ordinal axes and radial axes + if (axis.beforeSetTickPositions) { + axis.beforeSetTickPositions(); + } + // hook for extensions, used in Highstock ordinal axes + if (axis.ordinal) { + axis.tickInterval = axis.ordinal.postProcessTickInterval(axis.tickInterval); + } + // In column-like charts, don't cramp in more ticks than there are + // points (#1943, #4184) + if (axis.pointRange && !tickIntervalOption) { + axis.tickInterval = Math.max(axis.pointRange, axis.tickInterval); + } + // Before normalizing the tick interval, handle minimum tick interval. + // This applies only if tickInterval is not defined. + minTickInterval = pick(options.minTickInterval, (axis.dateTime && axis.closestPointRange)); + if (!tickIntervalOption && axis.tickInterval < minTickInterval) { + axis.tickInterval = minTickInterval; + } + // for linear axes, get magnitude and normalize the interval + if (!axis.dateTime && !axis.logarithmic && !tickIntervalOption) { + axis.tickInterval = normalizeTickInterval(axis.tickInterval, void 0, getMagnitude(axis.tickInterval), pick(options.allowDecimals, + // If the tick interval is greather than 0.5, avoid + // decimals, as linear axes are often used to render + // discrete values. #3363. If a tick amount is set, allow + // decimals by default, as it increases the chances for a + // good fit. + axis.tickInterval < 0.5 || this.tickAmount !== void 0), !!this.tickAmount); + } + // Prevent ticks from getting so close that we can't draw the labels + if (!this.tickAmount) { + axis.tickInterval = axis.unsquish(); + } + this.setTickPositions(); + }; + /** + * Now we have computed the normalized tickInterval, get the tick positions + * + * @function Highcharts.Axis#setTickPositions + * + * @fires Highcharts.Axis#event:afterSetTickPositions + */ + Axis.prototype.setTickPositions = function () { + var axis = this, options = this.options, tickPositions, tickPositionsOption = options.tickPositions, minorTickIntervalOption = this.getMinorTickInterval(), tickPositioner = options.tickPositioner, hasVerticalPanning = this.hasVerticalPanning(), isColorAxis = this.coll === 'colorAxis', startOnTick = (isColorAxis || !hasVerticalPanning) && options.startOnTick, endOnTick = (isColorAxis || !hasVerticalPanning) && options.endOnTick; + // Set the tickmarkOffset + this.tickmarkOffset = (this.categories && + options.tickmarkPlacement === 'between' && + this.tickInterval === 1) ? 0.5 : 0; // #3202 + // get minorTickInterval + this.minorTickInterval = + minorTickIntervalOption === 'auto' && + this.tickInterval ? + this.tickInterval / 5 : + minorTickIntervalOption; + // When there is only one point, or all points have the same value on + // this axis, then min and max are equal and tickPositions.length is 0 + // or 1. In this case, add some padding in order to center the point, + // but leave it with one tick. #1337. + this.single = + this.min === this.max && + defined(this.min) && + !this.tickAmount && + ( + // Data is on integer (#6563) + parseInt(this.min, 10) === this.min || + // Between integers and decimals are not allowed (#6274) + options.allowDecimals !== false); + /** + * Contains the current positions that are laid out on the axis. The + * positions are numbers in terms of axis values. In a category axis + * they are integers, in a datetime axis they are also integers, but + * designating milliseconds. + * + * This property is read only - for modifying the tick positions, use + * the `tickPositioner` callback or [axis.tickPositions( + * https://api.highcharts.com/highcharts/xAxis.tickPositions) option + * instead. + * + * @name Highcharts.Axis#tickPositions + * @type {Highcharts.AxisTickPositionsArray|undefined} + */ + this.tickPositions = + // Find the tick positions. Work on a copy (#1565) + tickPositions = + (tickPositionsOption && tickPositionsOption.slice()); + if (!tickPositions) { + // Too many ticks (#6405). Create a friendly warning and provide two + // ticks so at least we can show the data series. + if ((!axis.ordinal || !axis.ordinal.positions) && + ((this.max - this.min) / + this.tickInterval > + Math.max(2 * this.len, 200))) { + tickPositions = [this.min, this.max]; + error(19, false, this.chart); + } + else if (axis.dateTime) { + tickPositions = axis.getTimeTicks(axis.dateTime.normalizeTimeTickInterval(this.tickInterval, options.units), this.min, this.max, options.startOfWeek, axis.ordinal && axis.ordinal.positions, this.closestPointRange, true); + } + else if (axis.logarithmic) { + tickPositions = axis.logarithmic.getLogTickPositions(this.tickInterval, this.min, this.max); + } + else { + tickPositions = this.getLinearTickPositions(this.tickInterval, this.min, this.max); + } + // Too dense ticks, keep only the first and last (#4477) + if (tickPositions.length > this.len) { + tickPositions = [tickPositions[0], tickPositions.pop()]; + // Reduce doubled value (#7339) + if (tickPositions[0] === tickPositions[1]) { + tickPositions.length = 1; + } + } + this.tickPositions = tickPositions; + // Run the tick positioner callback, that allows modifying auto tick + // positions. + if (tickPositioner) { + tickPositioner = tickPositioner.apply(axis, [this.min, this.max]); + if (tickPositioner) { + this.tickPositions = tickPositions = tickPositioner; + } + } + } + // Reset min/max or remove extremes based on start/end on tick + this.paddedTicks = tickPositions.slice(0); // Used for logarithmic minor + this.trimTicks(tickPositions, startOnTick, endOnTick); + if (!this.isLinked) { + // Substract half a unit (#2619, #2846, #2515, #3390), + // but not in case of multiple ticks (#6897) + if (this.single && + tickPositions.length < 2 && + !this.categories && + !this.series.some(function (s) { + return (s.is('heatmap') && s.options.pointPlacement === 'between'); + })) { + this.min -= 0.5; + this.max += 0.5; + } + if (!tickPositionsOption && !tickPositioner) { + this.adjustTickAmount(); + } + } + fireEvent(this, 'afterSetTickPositions'); + }; + /** + * Handle startOnTick and endOnTick by either adapting to padding min/max or + * rounded min/max. Also handle single data points. + * + * @private + * @function Highcharts.Axis#trimTicks + * + * @param {Array} tickPositions + * TO-DO: parameter description + * + * @param {boolean} [startOnTick] + * TO-DO: parameter description + * + * @param {boolean} [endOnTick] + * TO-DO: parameter description + */ + Axis.prototype.trimTicks = function (tickPositions, startOnTick, endOnTick) { + var roundedMin = tickPositions[0], roundedMax = tickPositions[tickPositions.length - 1], minPointOffset = (!this.isOrdinal && this.minPointOffset) || 0; // (#12716) + fireEvent(this, 'trimTicks'); + if (!this.isLinked) { + if (startOnTick && roundedMin !== -Infinity) { // #6502 + this.min = roundedMin; + } + else { + while (this.min - minPointOffset > tickPositions[0]) { + tickPositions.shift(); + } + } + if (endOnTick) { + this.max = roundedMax; + } + else { + while (this.max + minPointOffset < + tickPositions[tickPositions.length - 1]) { + tickPositions.pop(); + } + } + // If no tick are left, set one tick in the middle (#3195) + if (tickPositions.length === 0 && + defined(roundedMin) && + !this.options.tickPositions) { + tickPositions.push((roundedMax + roundedMin) / 2); + } + } + }; + /** + * Check if there are multiple axes in the same pane. + * + * @private + * @function Highcharts.Axis#alignToOthers + * + * @return {boolean|undefined} + * True if there are other axes. + */ + Axis.prototype.alignToOthers = function () { + var axis = this, others = // Whether there is another axis to pair with this one + {}, hasOther, options = axis.options; + if ( + // Only if alignTicks is true + this.chart.options.chart.alignTicks !== false && + options.alignTicks !== false && + // Disabled when startOnTick or endOnTick are false (#7604) + options.startOnTick !== false && + options.endOnTick !== false && + // Don't try to align ticks on a log axis, they are not evenly + // spaced (#6021) + !axis.logarithmic) { + this.chart[this.coll].forEach(function (axis) { + var otherOptions = axis.options, horiz = axis.horiz, key = [ + horiz ? otherOptions.left : otherOptions.top, + otherOptions.width, + otherOptions.height, + otherOptions.pane + ].join(','); + if (axis.series.length) { // #4442 + if (others[key]) { + hasOther = true; // #4201 + } + else { + others[key] = 1; + } + } + }); + } + return hasOther; + }; + /** + * Find the max ticks of either the x and y axis collection, and record it + * in `this.tickAmount`. + * + * @private + * @function Highcharts.Axis#getTickAmount + */ + Axis.prototype.getTickAmount = function () { + var axis = this, options = this.options, tickAmount = options.tickAmount, tickPixelInterval = options.tickPixelInterval; + if (!defined(options.tickInterval) && + !tickAmount && this.len < tickPixelInterval && + !this.isRadial && + !axis.logarithmic && + options.startOnTick && + options.endOnTick) { + tickAmount = 2; + } + if (!tickAmount && this.alignToOthers()) { + // Add 1 because 4 tick intervals require 5 ticks (including first + // and last) + tickAmount = Math.ceil(this.len / tickPixelInterval) + 1; + } + // For tick amounts of 2 and 3, compute five ticks and remove the + // intermediate ones. This prevents the axis from adding ticks that are + // too far away from the data extremes. + if (tickAmount < 4) { + this.finalTickAmt = tickAmount; + tickAmount = 5; + } + this.tickAmount = tickAmount; + }; + /** + * When using multiple axes, adjust the number of ticks to match the highest + * number of ticks in that group. + * + * @private + * @function Highcharts.Axis#adjustTickAmount + */ + Axis.prototype.adjustTickAmount = function () { + var axis = this, axisOptions = axis.options, tickInterval = axis.tickInterval, tickPositions = axis.tickPositions, tickAmount = axis.tickAmount, finalTickAmt = axis.finalTickAmt, currentTickAmount = tickPositions && tickPositions.length, threshold = pick(axis.threshold, axis.softThreshold ? 0 : null), min, len, i; + if (axis.hasData()) { + if (currentTickAmount < tickAmount) { + min = axis.min; + while (tickPositions.length < tickAmount) { + // Extend evenly for both sides unless we're on the + // threshold (#3965) + if (tickPositions.length % 2 || + min === threshold) { + // to the end + tickPositions.push(correctFloat(tickPositions[tickPositions.length - 1] + + tickInterval)); + } + else { + // to the start + tickPositions.unshift(correctFloat(tickPositions[0] - tickInterval)); + } + } + axis.transA *= (currentTickAmount - 1) / (tickAmount - 1); + // Do not crop when ticks are not extremes (#9841) + axis.min = axisOptions.startOnTick ? + tickPositions[0] : + Math.min(axis.min, tickPositions[0]); + axis.max = axisOptions.endOnTick ? + tickPositions[tickPositions.length - 1] : + Math.max(axis.max, tickPositions[tickPositions.length - 1]); + // We have too many ticks, run second pass to try to reduce ticks + } + else if (currentTickAmount > tickAmount) { + axis.tickInterval *= 2; + axis.setTickPositions(); + } + // The finalTickAmt property is set in getTickAmount + if (defined(finalTickAmt)) { + i = len = tickPositions.length; + while (i--) { + if ( + // Remove every other tick + (finalTickAmt === 3 && i % 2 === 1) || + // Remove all but first and last + (finalTickAmt <= 2 && i > 0 && i < len - 1)) { + tickPositions.splice(i, 1); + } + } + axis.finalTickAmt = void 0; + } + } + }; + /** + * Set the scale based on data min and max, user set min and max or options. + * + * @private + * @function Highcharts.Axis#setScale + * + * @fires Highcharts.Axis#event:afterSetScale + */ + Axis.prototype.setScale = function () { + var axis = this, isDirtyAxisLength, isDirtyData = false, isXAxisDirty = false; + axis.series.forEach(function (series) { + var _a; + isDirtyData = isDirtyData || series.isDirtyData || series.isDirty; + // When x axis is dirty, we need new data extremes for y as + // well: + isXAxisDirty = isXAxisDirty || ((_a = series.xAxis) === null || _a === void 0 ? void 0 : _a.isDirty) || false; + }); + axis.oldMin = axis.min; + axis.oldMax = axis.max; + axis.oldAxisLength = axis.len; + // set the new axisLength + axis.setAxisSize(); + isDirtyAxisLength = axis.len !== axis.oldAxisLength; + // do we really need to go through all this? + if (isDirtyAxisLength || + isDirtyData || + isXAxisDirty || + axis.isLinked || + axis.forceRedraw || + axis.userMin !== axis.oldUserMin || + axis.userMax !== axis.oldUserMax || + axis.alignToOthers()) { + if (axis.stacking) { + axis.stacking.resetStacks(); + } + axis.forceRedraw = false; + // get data extremes if needed + axis.getSeriesExtremes(); + // get fixed positions based on tickInterval + axis.setTickInterval(); + // record old values to decide whether a rescale is necessary later + // on (#540) + axis.oldUserMin = axis.userMin; + axis.oldUserMax = axis.userMax; + // Mark as dirty if it is not already set to dirty and extremes have + // changed. #595. + if (!axis.isDirty) { + axis.isDirty = + isDirtyAxisLength || + axis.min !== axis.oldMin || + axis.max !== axis.oldMax; + } + } + else if (axis.stacking) { + axis.stacking.cleanStacks(); + } + // Recalculate panning state object, when the data + // has changed. It is required when vertical panning is enabled. + if (isDirtyData && axis.panningState) { + axis.panningState.isDirty = true; + } + fireEvent(this, 'afterSetScale'); + }; + /** + * Set the minimum and maximum of the axes after render time. If the + * `startOnTick` and `endOnTick` options are true, the minimum and maximum + * values are rounded off to the nearest tick. To prevent this, these + * options can be set to false before calling setExtremes. Also, setExtremes + * will not allow a range lower than the `minRange` option, which by default + * is the range of five points. + * + * @sample highcharts/members/axis-setextremes/ + * Set extremes from a button + * @sample highcharts/members/axis-setextremes-datetime/ + * Set extremes on a datetime axis + * @sample highcharts/members/axis-setextremes-off-ticks/ + * Set extremes off ticks + * @sample stock/members/axis-setextremes/ + * Set extremes in Highstock + * @sample maps/members/axis-setextremes/ + * Set extremes in Highmaps + * + * @function Highcharts.Axis#setExtremes + * + * @param {number} [newMin] + * The new minimum value. + * + * @param {number} [newMax] + * The new maximum value. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call to + * {@link Highcharts.Chart#redraw} + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=true] + * Enable or modify animations. + * + * @param {*} [eventArguments] + * Arguments to be accessed in event handler. + * + * @fires Highcharts.Axis#event:setExtremes + */ + Axis.prototype.setExtremes = function (newMin, newMax, redraw, animation, eventArguments) { + var axis = this, chart = axis.chart; + redraw = pick(redraw, true); // defaults to true + axis.series.forEach(function (serie) { + delete serie.kdTree; + }); + // Extend the arguments with min and max + eventArguments = extend(eventArguments, { + min: newMin, + max: newMax + }); + // Fire the event + fireEvent(axis, 'setExtremes', eventArguments, function () { + axis.userMin = newMin; + axis.userMax = newMax; + axis.eventArgs = eventArguments; + if (redraw) { + chart.redraw(animation); + } + }); + }; + /** + * Overridable method for zooming chart. Pulled out in a separate method to + * allow overriding in stock charts. + * @private + * @function Highcharts.Axis#zoom + * + * @param {number} newMin + * TO-DO: parameter description + * + * @param {number} newMax + * TO-DO: parameter description + * + * @return {boolean} + */ + Axis.prototype.zoom = function (newMin, newMax) { + var axis = this, dataMin = this.dataMin, dataMax = this.dataMax, options = this.options, min = Math.min(dataMin, pick(options.min, dataMin)), max = Math.max(dataMax, pick(options.max, dataMax)), evt = { + newMin: newMin, + newMax: newMax + }; + fireEvent(this, 'zoom', evt, function (e) { + // Use e.newMin and e.newMax - event handlers may have altered them + var newMin = e.newMin, newMax = e.newMax; + if (newMin !== axis.min || newMax !== axis.max) { // #5790 + // Prevent pinch zooming out of range. Check for defined is for + // #1946. #1734. + if (!axis.allowZoomOutside) { + // #6014, sometimes newMax will be smaller than min (or + // newMin will be larger than max). + if (defined(dataMin)) { + if (newMin < min) { + newMin = min; + } + if (newMin > max) { + newMin = max; + } + } + if (defined(dataMax)) { + if (newMax < min) { + newMax = min; + } + if (newMax > max) { + newMax = max; + } + } + } + // In full view, displaying the reset zoom button is not + // required + axis.displayBtn = (typeof newMin !== 'undefined' || + typeof newMax !== 'undefined'); + // Do it + axis.setExtremes(newMin, newMax, false, void 0, { trigger: 'zoom' }); + } + e.zoomed = true; + }); + return evt.zoomed; + }; + /** + * Update the axis metrics. + * + * @private + * @function Highcharts.Axis#setAxisSize + */ + Axis.prototype.setAxisSize = function () { + var chart = this.chart, options = this.options, + // [top, right, bottom, left] + offsets = options.offsets || [0, 0, 0, 0], horiz = this.horiz, + // Check for percentage based input values. Rounding fixes problems + // with column overflow and plot line filtering (#4898, #4899) + width = this.width = Math.round(relativeLength(pick(options.width, chart.plotWidth - offsets[3] + offsets[1]), chart.plotWidth)), height = this.height = Math.round(relativeLength(pick(options.height, chart.plotHeight - offsets[0] + offsets[2]), chart.plotHeight)), top = this.top = Math.round(relativeLength(pick(options.top, chart.plotTop + offsets[0]), chart.plotHeight, chart.plotTop)), left = this.left = Math.round(relativeLength(pick(options.left, chart.plotLeft + offsets[3]), chart.plotWidth, chart.plotLeft)); + // Expose basic values to use in Series object and navigator + this.bottom = chart.chartHeight - height - top; + this.right = chart.chartWidth - width - left; + // Direction agnostic properties + this.len = Math.max(horiz ? width : height, 0); // Math.max fixes #905 + this.pos = horiz ? left : top; // distance from SVG origin + }; + /** + * Get the current extremes for the axis. + * + * @sample highcharts/members/axis-getextremes/ + * Report extremes by click on a button + * @sample maps/members/axis-getextremes/ + * Get extremes in Highmaps + * + * @function Highcharts.Axis#getExtremes + * + * @return {Highcharts.ExtremesObject} + * An object containing extremes information. + */ + Axis.prototype.getExtremes = function () { + var axis = this; + var log = axis.logarithmic; + return { + min: log ? + correctFloat(log.lin2log(axis.min)) : + axis.min, + max: log ? + correctFloat(log.lin2log(axis.max)) : + axis.max, + dataMin: axis.dataMin, + dataMax: axis.dataMax, + userMin: axis.userMin, + userMax: axis.userMax + }; + }; + /** + * Get the zero plane either based on zero or on the min or max value. + * Used in bar and area plots. + * + * @function Highcharts.Axis#getThreshold + * + * @param {number} threshold + * The threshold in axis values. + * + * @return {number|undefined} + * The translated threshold position in terms of pixels, and corrected to + * stay within the axis bounds. + */ + Axis.prototype.getThreshold = function (threshold) { + var axis = this, log = axis.logarithmic, realMin = log ? log.lin2log(axis.min) : axis.min, realMax = log ? log.lin2log(axis.max) : axis.max; + if (threshold === null || threshold === -Infinity) { + threshold = realMin; + } + else if (threshold === Infinity) { + threshold = realMax; + } + else if (realMin > threshold) { + threshold = realMin; + } + else if (realMax < threshold) { + threshold = realMax; + } + return axis.translate(threshold, 0, 1, 0, 1); + }; + /** + * Compute auto alignment for the axis label based on which side the axis is + * on and the given rotation for the label. + * + * @private + * @function Highcharts.Axis#autoLabelAlign + * + * @param {number} rotation + * The rotation in degrees as set by either the `rotation` or `autoRotation` + * options. + * + * @return {Highcharts.AlignValue} + * Can be `"center"`, `"left"` or `"right"`. + */ + Axis.prototype.autoLabelAlign = function (rotation) { + var angle = (pick(rotation, 0) - (this.side * 90) + 720) % 360, evt = { align: 'center' }; + fireEvent(this, 'autoLabelAlign', evt, function (e) { + if (angle > 15 && angle < 165) { + e.align = 'right'; + } + else if (angle > 195 && angle < 345) { + e.align = 'left'; + } + }); + return evt.align; + }; + /** + * Get the tick length and width for the axis based on axis options. + * @private + * @function Highcharts.Axis#tickSize + * + * @param {string} [prefix] + * 'tick' or 'minorTick' + * + * @return {Array|undefined} + * An array of tickLength and tickWidth + */ + Axis.prototype.tickSize = function (prefix) { + var options = this.options, tickLength = options[prefix === 'tick' ? 'tickLength' : 'minorTickLength'], tickWidth = pick(options[prefix === 'tick' ? 'tickWidth' : 'minorTickWidth'], + // Default to 1 on linear and datetime X axes + prefix === 'tick' && this.isXAxis && !this.categories ? 1 : 0), e, tickSize; + if (tickWidth && tickLength) { + // Negate the length + if (options[prefix + 'Position'] === 'inside') { + tickLength = -tickLength; + } + tickSize = [tickLength, tickWidth]; + } + e = { tickSize: tickSize }; + fireEvent(this, 'afterTickSize', e); + return e.tickSize; + }; + /** + * Return the size of the labels. + * + * @private + * @function Highcharts.Axis#labelMetrics + * + * @return {Highcharts.FontMetricsObject} + */ + Axis.prototype.labelMetrics = function () { + var index = this.tickPositions && this.tickPositions[0] || 0; + return this.chart.renderer.fontMetrics(this.options.labels.style && + this.options.labels.style.fontSize, this.ticks[index] && this.ticks[index].label); + }; + /** + * Prevent the ticks from getting so close we can't draw the labels. On a + * horizontal axis, this is handled by rotating the labels, removing ticks + * and adding ellipsis. On a vertical axis remove ticks and add ellipsis. + * + * @private + * @function Highcharts.Axis#unsquish + * + * @return {number} + */ + Axis.prototype.unsquish = function () { + var labelOptions = this.options.labels, horiz = this.horiz, tickInterval = this.tickInterval, newTickInterval = tickInterval, slotSize = this.len / (((this.categories ? 1 : 0) + + this.max - + this.min) / + tickInterval), rotation, rotationOption = labelOptions.rotation, labelMetrics = this.labelMetrics(), step, bestScore = Number.MAX_VALUE, autoRotation, range = this.max - this.min, + // Return the multiple of tickInterval that is needed to avoid + // collision + getStep = function (spaceNeeded) { + var step = spaceNeeded / (slotSize || 1); + step = step > 1 ? Math.ceil(step) : 1; + // Guard for very small or negative angles (#9835) + if (step * tickInterval > range && + spaceNeeded !== Infinity && + slotSize !== Infinity && + range) { + step = Math.ceil(range / tickInterval); + } + return correctFloat(step * tickInterval); + }; + if (horiz) { + autoRotation = !labelOptions.staggerLines && + !labelOptions.step && + ( // #3971 + defined(rotationOption) ? + [rotationOption] : + slotSize < pick(labelOptions.autoRotationLimit, 80) && labelOptions.autoRotation); + if (autoRotation) { + // Loop over the given autoRotation options, and determine + // which gives the best score. The best score is that with + // the lowest number of steps and a rotation closest + // to horizontal. + autoRotation.forEach(function (rot) { + var score; + if (rot === rotationOption || + (rot && rot >= -90 && rot <= 90)) { // #3891 + step = getStep(Math.abs(labelMetrics.h / Math.sin(deg2rad * rot))); + score = step + Math.abs(rot / 360); + if (score < bestScore) { + bestScore = score; + rotation = rot; + newTickInterval = step; + } + } + }); + } + } + else if (!labelOptions.step) { // #4411 + newTickInterval = getStep(labelMetrics.h); + } + this.autoRotation = autoRotation; + this.labelRotation = pick(rotation, rotationOption); + return newTickInterval; + }; + /** + * Get the general slot width for labels/categories on this axis. This may + * change between the pre-render (from Axis.getOffset) and the final tick + * rendering and placement. + * + * @private + * @function Highcharts.Axis#getSlotWidth + * + * @param {Highcharts.Tick} [tick] Optionally, calculate the slot width + * basing on tick label. It is used in highcharts-3d module, where the slots + * has different widths depending on perspective angles. + * + * @return {number} + * The pixel width allocated to each axis label. + */ + Axis.prototype.getSlotWidth = function (tick) { + var _a; + // #5086, #1580, #1931 + var chart = this.chart, horiz = this.horiz, labelOptions = this.options.labels, slotCount = Math.max(this.tickPositions.length - (this.categories ? 0 : 1), 1), marginLeft = chart.margin[3]; + // Used by grid axis + if (tick && isNumber(tick.slotWidth)) { // #13221, can be 0 + return tick.slotWidth; + } + if (horiz && + labelOptions && + (labelOptions.step || 0) < 2) { + if (labelOptions.rotation) { // #4415 + return 0; + } + return ((this.staggerLines || 1) * this.len) / slotCount; + } + if (!horiz) { + // #7028 + var cssWidth = (_a = labelOptions === null || labelOptions === void 0 ? void 0 : labelOptions.style) === null || _a === void 0 ? void 0 : _a.width; + if (cssWidth !== void 0) { + return parseInt(cssWidth, 10); + } + if (marginLeft) { + return marginLeft - chart.spacing[3]; + } + } + // Last resort, a fraction of the available size + return chart.chartWidth * 0.33; + }; + /** + * Render the axis labels and determine whether ellipsis or rotation need to + * be applied. + * + * @private + * @function Highcharts.Axis#renderUnsquish + */ + Axis.prototype.renderUnsquish = function () { + var chart = this.chart, renderer = chart.renderer, tickPositions = this.tickPositions, ticks = this.ticks, labelOptions = this.options.labels, labelStyleOptions = (labelOptions && labelOptions.style || {}), horiz = this.horiz, slotWidth = this.getSlotWidth(), innerWidth = Math.max(1, Math.round(slotWidth - 2 * (labelOptions.padding || 5))), attr = {}, labelMetrics = this.labelMetrics(), textOverflowOption = (labelOptions.style && + labelOptions.style.textOverflow), commonWidth, commonTextOverflow, maxLabelLength = 0, label, i, pos; + // Set rotation option unless it is "auto", like in gauges + if (!isString(labelOptions.rotation)) { + // #4443: + attr.rotation = labelOptions.rotation || 0; + } + // Get the longest label length + tickPositions.forEach(function (tick) { + tick = ticks[tick]; + // Replace label - sorting animation + if (tick.movedLabel) { + tick.replaceMovedLabel(); + } + if (tick && + tick.label && + tick.label.textPxLength > maxLabelLength) { + maxLabelLength = tick.label.textPxLength; + } + }); + this.maxLabelLength = maxLabelLength; + // Handle auto rotation on horizontal axis + if (this.autoRotation) { + // Apply rotation only if the label is too wide for the slot, and + // the label is wider than its height. + if (maxLabelLength > innerWidth && + maxLabelLength > labelMetrics.h) { + attr.rotation = this.labelRotation; + } + else { + this.labelRotation = 0; + } + // Handle word-wrap or ellipsis on vertical axis + } + else if (slotWidth) { + // For word-wrap or ellipsis + commonWidth = innerWidth; + if (!textOverflowOption) { + commonTextOverflow = 'clip'; + // On vertical axis, only allow word wrap if there is room + // for more lines. + i = tickPositions.length; + while (!horiz && i--) { + pos = tickPositions[i]; + label = ticks[pos].label; + if (label) { + // Reset ellipsis in order to get the correct + // bounding box (#4070) + if (label.styles && + label.styles.textOverflow === 'ellipsis') { + label.css({ textOverflow: 'clip' }); + // Set the correct width in order to read + // the bounding box height (#4678, #5034) + } + else if (label.textPxLength > slotWidth) { + label.css({ width: slotWidth + 'px' }); + } + if (label.getBBox().height > (this.len / tickPositions.length - + (labelMetrics.h - labelMetrics.f))) { + label.specificTextOverflow = 'ellipsis'; + } + } + } + } + } + // Add ellipsis if the label length is significantly longer than ideal + if (attr.rotation) { + commonWidth = (maxLabelLength > chart.chartHeight * 0.5 ? + chart.chartHeight * 0.33 : + maxLabelLength); + if (!textOverflowOption) { + commonTextOverflow = 'ellipsis'; + } + } + // Set the explicit or automatic label alignment + this.labelAlign = labelOptions.align || + this.autoLabelAlign(this.labelRotation); + if (this.labelAlign) { + attr.align = this.labelAlign; + } + // Apply general and specific CSS + tickPositions.forEach(function (pos) { + var tick = ticks[pos], label = tick && tick.label, widthOption = labelStyleOptions.width, css = {}; + if (label) { + // This needs to go before the CSS in old IE (#4502) + label.attr(attr); + if (tick.shortenLabel) { + tick.shortenLabel(); + } + else if (commonWidth && + !widthOption && + // Setting width in this case messes with the bounding box + // (#7975) + labelStyleOptions.whiteSpace !== 'nowrap' && + ( + // Speed optimizing, #7656 + commonWidth < label.textPxLength || + // Resetting CSS, #4928 + label.element.tagName === 'SPAN')) { + css.width = commonWidth + 'px'; + if (!textOverflowOption) { + css.textOverflow = (label.specificTextOverflow || + commonTextOverflow); + } + label.css(css); + // Reset previously shortened label (#8210) + } + else if (label.styles && + label.styles.width && + !css.width && + !widthOption) { + label.css({ width: null }); + } + delete label.specificTextOverflow; + tick.rotation = attr.rotation; + } + }, this); + // Note: Why is this not part of getLabelPosition? + this.tickRotCorr = renderer.rotCorr(labelMetrics.b, this.labelRotation || 0, this.side !== 0); + }; + /** + * Return true if the axis has associated data. + * + * @function Highcharts.Axis#hasData + * + * @return {boolean} + * True if the axis has associated visible series and those series have + * either valid data points or explicit `min` and `max` settings. + */ + Axis.prototype.hasData = function () { + return this.series.some(function (s) { + return s.hasData(); + }) || + (this.options.showEmpty && + defined(this.min) && + defined(this.max)); + }; + /** + * Adds the title defined in axis.options.title. + * + * @function Highcharts.Axis#addTitle + * + * @param {boolean} [display] + * Whether or not to display the title. + */ + Axis.prototype.addTitle = function (display) { + var axis = this, renderer = axis.chart.renderer, horiz = axis.horiz, opposite = axis.opposite, options = axis.options, axisTitleOptions = options.title, textAlign, styledMode = axis.chart.styledMode; + if (!axis.axisTitle) { + textAlign = axisTitleOptions.textAlign; + if (!textAlign) { + textAlign = (horiz ? { + low: 'left', + middle: 'center', + high: 'right' + } : { + low: opposite ? 'right' : 'left', + middle: 'center', + high: opposite ? 'left' : 'right' + })[axisTitleOptions.align]; + } + axis.axisTitle = renderer + .text(axisTitleOptions.text, 0, 0, axisTitleOptions.useHTML) + .attr({ + zIndex: 7, + rotation: axisTitleOptions.rotation || 0, + align: textAlign + }) + .addClass('highcharts-axis-title'); + // #7814, don't mutate style option + if (!styledMode) { + axis.axisTitle.css(merge(axisTitleOptions.style)); + } + axis.axisTitle.add(axis.axisGroup); + axis.axisTitle.isNew = true; + } + // Max width defaults to the length of the axis + if (!styledMode && + !axisTitleOptions.style.width && + !axis.isRadial) { + axis.axisTitle.css({ + width: axis.len + 'px' + }); + } + // hide or show the title depending on whether showEmpty is set + axis.axisTitle[display ? 'show' : 'hide'](display); + }; + /** + * Generates a tick for initial positioning. + * + * @private + * @function Highcharts.Axis#generateTick + * + * @param {number} pos + * The tick position in axis values. + * + * @param {number} [i] + * The index of the tick in {@link Axis.tickPositions}. + */ + Axis.prototype.generateTick = function (pos) { + var axis = this; + var ticks = axis.ticks; + if (!ticks[pos]) { + ticks[pos] = new Tick(axis, pos); + } + else { + ticks[pos].addLabel(); // update labels depending on tick interval + } + }; + /** + * Render the tick labels to a preliminary position to get their sizes + * + * @private + * @function Highcharts.Axis#getOffset + * + * @fires Highcharts.Axis#event:afterGetOffset + */ + Axis.prototype.getOffset = function () { + var axis = this, chart = axis.chart, renderer = chart.renderer, options = axis.options, tickPositions = axis.tickPositions, ticks = axis.ticks, horiz = axis.horiz, side = axis.side, invertedSide = chart.inverted && + !axis.isZAxis ? [1, 0, 3, 2][side] : side, hasData, showAxis, titleOffset = 0, titleOffsetOption, titleMargin = 0, axisTitleOptions = options.title, labelOptions = options.labels, labelOffset = 0, // reset + labelOffsetPadded, axisOffset = chart.axisOffset, clipOffset = chart.clipOffset, clip, directionFactor = [-1, 1, 1, -1][side], className = options.className, axisParent = axis.axisParent, // Used in color axis + lineHeightCorrection; + // For reuse in Axis.render + hasData = axis.hasData(); + axis.showAxis = showAxis = hasData || pick(options.showEmpty, true); + // Set/reset staggerLines + axis.staggerLines = axis.horiz && labelOptions.staggerLines; + // Create the axisGroup and gridGroup elements on first iteration + if (!axis.axisGroup) { + axis.gridGroup = renderer.g('grid') + .attr({ zIndex: options.gridZIndex || 1 }) + .addClass('highcharts-' + this.coll.toLowerCase() + '-grid ' + + (className || '')) + .add(axisParent); + axis.axisGroup = renderer.g('axis') + .attr({ zIndex: options.zIndex || 2 }) + .addClass('highcharts-' + this.coll.toLowerCase() + ' ' + + (className || '')) + .add(axisParent); + axis.labelGroup = renderer.g('axis-labels') + .attr({ zIndex: labelOptions.zIndex || 7 }) + .addClass('highcharts-' + axis.coll.toLowerCase() + '-labels ' + + (className || '')) + .add(axisParent); + } + if (hasData || axis.isLinked) { + // Generate ticks + tickPositions.forEach(function (pos, i) { + // i is not used here, but may be used in overrides + axis.generateTick(pos, i); + }); + axis.renderUnsquish(); + // Left side must be align: right and right side must + // have align: left for labels + axis.reserveSpaceDefault = (side === 0 || + side === 2 || + { 1: 'left', 3: 'right' }[side] === axis.labelAlign); + if (pick(labelOptions.reserveSpace, axis.labelAlign === 'center' ? true : null, axis.reserveSpaceDefault)) { + tickPositions.forEach(function (pos) { + // get the highest offset + labelOffset = Math.max(ticks[pos].getLabelSize(), labelOffset); + }); + } + if (axis.staggerLines) { + labelOffset *= axis.staggerLines; + } + axis.labelOffset = labelOffset * (axis.opposite ? -1 : 1); + } + else { // doesn't have data + objectEach(ticks, function (tick, n) { + tick.destroy(); + delete ticks[n]; + }); + } + if (axisTitleOptions && + axisTitleOptions.text && + axisTitleOptions.enabled !== false) { + axis.addTitle(showAxis); + if (showAxis && axisTitleOptions.reserveSpace !== false) { + axis.titleOffset = titleOffset = + axis.axisTitle.getBBox()[horiz ? 'height' : 'width']; + titleOffsetOption = axisTitleOptions.offset; + titleMargin = defined(titleOffsetOption) ? + 0 : + pick(axisTitleOptions.margin, horiz ? 5 : 10); + } + } + // Render the axis line + axis.renderLine(); + // handle automatic or user set offset + axis.offset = directionFactor * pick(options.offset, axisOffset[side] ? axisOffset[side] + (options.margin || 0) : 0); + axis.tickRotCorr = axis.tickRotCorr || { x: 0, y: 0 }; // polar + if (side === 0) { + lineHeightCorrection = -axis.labelMetrics().h; + } + else if (side === 2) { + lineHeightCorrection = axis.tickRotCorr.y; + } + else { + lineHeightCorrection = 0; + } + // Find the padded label offset + labelOffsetPadded = Math.abs(labelOffset) + titleMargin; + if (labelOffset) { + labelOffsetPadded -= lineHeightCorrection; + labelOffsetPadded += directionFactor * (horiz ? + pick(labelOptions.y, axis.tickRotCorr.y + directionFactor * 8) : + labelOptions.x); + } + axis.axisTitleMargin = pick(titleOffsetOption, labelOffsetPadded); + if (axis.getMaxLabelDimensions) { + axis.maxLabelDimensions = axis.getMaxLabelDimensions(ticks, tickPositions); + } + // Due to GridAxis.tickSize, tickSize should be calculated after ticks + // has rendered. + var tickSize = this.tickSize('tick'); + axisOffset[side] = Math.max(axisOffset[side], axis.axisTitleMargin + titleOffset + + directionFactor * axis.offset, labelOffsetPadded, // #3027 + tickPositions && tickPositions.length && tickSize ? + tickSize[0] + directionFactor * axis.offset : + 0 // #4866 + ); + // Decide the clipping needed to keep the graph inside + // the plot area and axis lines + clip = options.offset ? + 0 : + // #4308, #4371: + Math.floor(axis.axisLine.strokeWidth() / 2) * 2; + clipOffset[invertedSide] = + Math.max(clipOffset[invertedSide], clip); + fireEvent(this, 'afterGetOffset'); + }; + /** + * Internal function to get the path for the axis line. Extended for polar + * charts. + * + * @function Highcharts.Axis#getLinePath + * + * @param {number} lineWidth + * The line width in pixels. + * + * @return {Highcharts.SVGPathArray} + * The SVG path definition in array form. + */ + Axis.prototype.getLinePath = function (lineWidth) { + var chart = this.chart, opposite = this.opposite, offset = this.offset, horiz = this.horiz, lineLeft = this.left + (opposite ? this.width : 0) + offset, lineTop = chart.chartHeight - this.bottom - + (opposite ? this.height : 0) + offset; + if (opposite) { + lineWidth *= -1; // crispify the other way - #1480, #1687 + } + return chart.renderer + .crispLine([ + [ + 'M', + horiz ? + this.left : + lineLeft, + horiz ? + lineTop : + this.top + ], + [ + 'L', + horiz ? + chart.chartWidth - this.right : + lineLeft, + horiz ? + lineTop : + chart.chartHeight - this.bottom + ] + ], lineWidth); + }; + /** + * Render the axis line. Called internally when rendering and redrawing the + * axis. + * + * @function Highcharts.Axis#renderLine + */ + Axis.prototype.renderLine = function () { + if (!this.axisLine) { + this.axisLine = this.chart.renderer.path() + .addClass('highcharts-axis-line') + .add(this.axisGroup); + if (!this.chart.styledMode) { + this.axisLine.attr({ + stroke: this.options.lineColor, + 'stroke-width': this.options.lineWidth, + zIndex: 7 + }); + } + } + }; + /** + * Position the axis title. + * + * @private + * @function Highcharts.Axis#getTitlePosition + * + * @return {Highcharts.PositionObject} + * X and Y positions for the title. + */ + Axis.prototype.getTitlePosition = function () { + // compute anchor points for each of the title align options + var horiz = this.horiz, axisLeft = this.left, axisTop = this.top, axisLength = this.len, axisTitleOptions = this.options.title, margin = horiz ? axisLeft : axisTop, opposite = this.opposite, offset = this.offset, xOption = axisTitleOptions.x || 0, yOption = axisTitleOptions.y || 0, axisTitle = this.axisTitle, fontMetrics = this.chart.renderer.fontMetrics(axisTitleOptions.style && + axisTitleOptions.style.fontSize, axisTitle), + // The part of a multiline text that is below the baseline of the + // first line. Subtract 1 to preserve pixel-perfectness from the + // old behaviour (v5.0.12), where only one line was allowed. + textHeightOvershoot = Math.max(axisTitle.getBBox(null, 0).height - fontMetrics.h - 1, 0), + // the position in the length direction of the axis + alongAxis = { + low: margin + (horiz ? 0 : axisLength), + middle: margin + axisLength / 2, + high: margin + (horiz ? axisLength : 0) + }[axisTitleOptions.align], + // the position in the perpendicular direction of the axis + offAxis = (horiz ? axisTop + this.height : axisLeft) + + (horiz ? 1 : -1) * // horizontal axis reverses the margin + (opposite ? -1 : 1) * // so does opposite axes + this.axisTitleMargin + + [ + -textHeightOvershoot, + textHeightOvershoot, + fontMetrics.f, + -textHeightOvershoot // left + ][this.side], titlePosition = { + x: horiz ? + alongAxis + xOption : + offAxis + (opposite ? this.width : 0) + offset + xOption, + y: horiz ? + offAxis + yOption - (opposite ? this.height : 0) + offset : + alongAxis + yOption + }; + fireEvent(this, 'afterGetTitlePosition', { titlePosition: titlePosition }); + return titlePosition; + }; + /** + * Render a minor tick into the given position. If a minor tick already + * exists in this position, move it. + * + * @function Highcharts.Axis#renderMinorTick + * + * @param {number} pos + * The position in axis values. + */ + Axis.prototype.renderMinorTick = function (pos) { + var axis = this; + var slideInTicks = axis.chart.hasRendered && isNumber(axis.oldMin); + var minorTicks = axis.minorTicks; + if (!minorTicks[pos]) { + minorTicks[pos] = new Tick(axis, pos, 'minor'); + } + // Render new ticks in old position + if (slideInTicks && minorTicks[pos].isNew) { + minorTicks[pos].render(null, true); + } + minorTicks[pos].render(null, false, 1); + }; + /** + * Render a major tick into the given position. If a tick already exists + * in this position, move it. + * + * @function Highcharts.Axis#renderTick + * + * @param {number} pos + * The position in axis values. + * + * @param {number} i + * The tick index. + */ + Axis.prototype.renderTick = function (pos, i) { + var axis = this; + var isLinked = axis.isLinked; + var ticks = axis.ticks; + var slideInTicks = axis.chart.hasRendered && isNumber(axis.oldMin); + // Linked axes need an extra check to find out if + if (!isLinked || + (pos >= axis.min && pos <= axis.max)) { + if (!ticks[pos]) { + ticks[pos] = new Tick(axis, pos); + } + // NOTE this seems like overkill. Could be handled in tick.render by + // setting old position in attr, then set new position in animate. + // render new ticks in old position + if (slideInTicks && ticks[pos].isNew) { + // Start with negative opacity so that it is visible from + // halfway into the animation + ticks[pos].render(i, true, -1); + } + ticks[pos].render(i); + } + }; + /** + * Render the axis. + * + * @private + * @function Highcharts.Axis#render + * + * @fires Highcharts.Axis#event:afterRender + */ + Axis.prototype.render = function () { + var axis = this, chart = axis.chart, log = axis.logarithmic, renderer = chart.renderer, options = axis.options, isLinked = axis.isLinked, tickPositions = axis.tickPositions, axisTitle = axis.axisTitle, ticks = axis.ticks, minorTicks = axis.minorTicks, alternateBands = axis.alternateBands, stackLabelOptions = options.stackLabels, alternateGridColor = options.alternateGridColor, tickmarkOffset = axis.tickmarkOffset, axisLine = axis.axisLine, showAxis = axis.showAxis, animation = animObject(renderer.globalAnimation), from, to; + // Reset + axis.labelEdge.length = 0; + axis.overlap = false; + // Mark all elements inActive before we go over and mark the active ones + [ticks, minorTicks, alternateBands].forEach(function (coll) { + objectEach(coll, function (tick) { + tick.isActive = false; + }); + }); + // If the series has data draw the ticks. Else only the line and title + if (axis.hasData() || isLinked) { + // minor ticks + if (axis.minorTickInterval && !axis.categories) { + axis.getMinorTickPositions().forEach(function (pos) { + axis.renderMinorTick(pos); + }); + } + // Major ticks. Pull out the first item and render it last so that + // we can get the position of the neighbour label. #808. + if (tickPositions.length) { // #1300 + tickPositions.forEach(function (pos, i) { + axis.renderTick(pos, i); + }); + // In a categorized axis, the tick marks are displayed + // between labels. So we need to add a tick mark and + // grid line at the left edge of the X axis. + if (tickmarkOffset && (axis.min === 0 || axis.single)) { + if (!ticks[-1]) { + ticks[-1] = new Tick(axis, -1, null, true); + } + ticks[-1].render(-1); + } + } + // alternate grid color + if (alternateGridColor) { + tickPositions.forEach(function (pos, i) { + to = typeof tickPositions[i + 1] !== 'undefined' ? + tickPositions[i + 1] + tickmarkOffset : + axis.max - tickmarkOffset; + if (i % 2 === 0 && + pos < axis.max && + to <= axis.max + (chart.polar ? + -tickmarkOffset : + tickmarkOffset)) { // #2248, #4660 + if (!alternateBands[pos]) { + // Should be imported from PlotLineOrBand.js, but + // the dependency cycle with axis is a problem + alternateBands[pos] = new H.PlotLineOrBand(axis); + } + from = pos + tickmarkOffset; // #949 + alternateBands[pos].options = { + from: log ? log.lin2log(from) : from, + to: log ? log.lin2log(to) : to, + color: alternateGridColor + }; + alternateBands[pos].render(); + alternateBands[pos].isActive = true; + } + }); + } + // custom plot lines and bands + if (!axis._addedPlotLB) { // only first time + (options.plotLines || []) + .concat(options.plotBands || []) + .forEach(function (plotLineOptions) { + axis.addPlotBandOrLine(plotLineOptions); + }); + axis._addedPlotLB = true; + } + } // end if hasData + // Remove inactive ticks + [ticks, minorTicks, alternateBands].forEach(function (coll) { + var i, forDestruction = [], delay = animation.duration, destroyInactiveItems = function () { + i = forDestruction.length; + while (i--) { + // When resizing rapidly, the same items + // may be destroyed in different timeouts, + // or the may be reactivated + if (coll[forDestruction[i]] && + !coll[forDestruction[i]].isActive) { + coll[forDestruction[i]].destroy(); + delete coll[forDestruction[i]]; + } + } + }; + objectEach(coll, function (tick, pos) { + if (!tick.isActive) { + // Render to zero opacity + tick.render(pos, false, 0); + tick.isActive = false; + forDestruction.push(pos); + } + }); + // When the objects are finished fading out, destroy them + syncTimeout(destroyInactiveItems, coll === alternateBands || + !chart.hasRendered || + !delay ? + 0 : + delay); + }); + // Set the axis line path + if (axisLine) { + axisLine[axisLine.isPlaced ? 'animate' : 'attr']({ + d: this.getLinePath(axisLine.strokeWidth()) + }); + axisLine.isPlaced = true; + // Show or hide the line depending on options.showEmpty + axisLine[showAxis ? 'show' : 'hide'](showAxis); + } + if (axisTitle && showAxis) { + var titleXy = axis.getTitlePosition(); + if (isNumber(titleXy.y)) { + axisTitle[axisTitle.isNew ? 'attr' : 'animate'](titleXy); + axisTitle.isNew = false; + } + else { + axisTitle.attr('y', -9999); + axisTitle.isNew = true; + } + } + // Stacked totals: + if (stackLabelOptions && stackLabelOptions.enabled && axis.stacking) { + axis.stacking.renderStackTotals(); + } + // End stacked totals + axis.isDirty = false; + fireEvent(this, 'afterRender'); + }; + /** + * Redraw the axis to reflect changes in the data or axis extremes. Called + * internally from Highcharts.Chart#redraw. + * + * @private + * @function Highcharts.Axis#redraw + */ + Axis.prototype.redraw = function () { + if (this.visible) { + // render the axis + this.render(); + // move plot lines and bands + this.plotLinesAndBands.forEach(function (plotLine) { + plotLine.render(); + }); + } + // mark associated series as dirty and ready for redraw + this.series.forEach(function (series) { + series.isDirty = true; + }); + }; + /** + * Returns an array of axis properties, that should be untouched during + * reinitialization. + * + * @private + * @function Highcharts.Axis#getKeepProps + * + * @return {Array} + */ + Axis.prototype.getKeepProps = function () { + return (this.keepProps || Axis.keepProps); + }; + /** + * Destroys an Axis instance. See {@link Axis#remove} for the API endpoint + * to fully remove the axis. + * + * @private + * @function Highcharts.Axis#destroy + * + * @param {boolean} [keepEvents] + * Whether to preserve events, used internally in Axis.update. + */ + Axis.prototype.destroy = function (keepEvents) { + var axis = this, plotLinesAndBands = axis.plotLinesAndBands, plotGroup, i; + fireEvent(this, 'destroy', { keepEvents: keepEvents }); + // Remove the events + if (!keepEvents) { + removeEvent(axis); + } + // Destroy collections + [axis.ticks, axis.minorTicks, axis.alternateBands].forEach(function (coll) { + destroyObjectProperties(coll); + }); + if (plotLinesAndBands) { + i = plotLinesAndBands.length; + while (i--) { // #1975 + plotLinesAndBands[i].destroy(); + } + } + // Destroy elements + ['axisLine', 'axisTitle', 'axisGroup', + 'gridGroup', 'labelGroup', 'cross', 'scrollbar'].forEach(function (prop) { + if (axis[prop]) { + axis[prop] = axis[prop].destroy(); + } + }); + // Destroy each generated group for plotlines and plotbands + for (plotGroup in axis.plotLinesAndBandsGroups) { // eslint-disable-line guard-for-in + axis.plotLinesAndBandsGroups[plotGroup] = + axis.plotLinesAndBandsGroups[plotGroup].destroy(); + } + // Delete all properties and fall back to the prototype. + objectEach(axis, function (val, key) { + if (axis.getKeepProps().indexOf(key) === -1) { + delete axis[key]; + } + }); + }; + /** + * Internal function to draw a crosshair. + * + * @function Highcharts.Axis#drawCrosshair + * + * @param {Highcharts.PointerEventObject} [e] + * The event arguments from the modified pointer event, extended with + * `chartX` and `chartY` + * + * @param {Highcharts.Point} [point] + * The Point object if the crosshair snaps to points. + * + * @fires Highcharts.Axis#event:afterDrawCrosshair + * @fires Highcharts.Axis#event:drawCrosshair + */ + Axis.prototype.drawCrosshair = function (e, point) { + var path, options = this.crosshair, snap = pick(options.snap, true), pos, categorized, graphic = this.cross, crossOptions, chart = this.chart; + fireEvent(this, 'drawCrosshair', { e: e, point: point }); + // Use last available event when updating non-snapped crosshairs without + // mouse interaction (#5287) + if (!e) { + e = this.cross && this.cross.e; + } + if ( + // Disabled in options + !this.crosshair || + // Snap + ((defined(point) || !snap) === false)) { + this.hideCrosshair(); + } + else { + // Get the path + if (!snap) { + pos = e && + (this.horiz ? + e.chartX - this.pos : + this.len - e.chartY + this.pos); + } + else if (defined(point)) { + // #3834 + pos = pick(this.coll !== 'colorAxis' ? + point.crosshairPos : // 3D axis extension + null, this.isXAxis ? + point.plotX : + this.len - point.plotY); + } + if (defined(pos)) { + crossOptions = { + // value, only used on radial + value: point && (this.isXAxis ? + point.x : + pick(point.stackY, point.y)), + translatedValue: pos + }; + if (chart.polar) { + // Additional information required for crosshairs in + // polar chart + extend(crossOptions, { + isCrosshair: true, + chartX: e && e.chartX, + chartY: e && e.chartY, + point: point + }); + } + path = this.getPlotLinePath(crossOptions) || + null; // #3189 + } + if (!defined(path)) { + this.hideCrosshair(); + return; + } + categorized = this.categories && !this.isRadial; + // Draw the cross + if (!graphic) { + this.cross = graphic = chart.renderer + .path() + .addClass('highcharts-crosshair highcharts-crosshair-' + + (categorized ? 'category ' : 'thin ') + + options.className) + .attr({ + zIndex: pick(options.zIndex, 2) + }) + .add(); + // Presentational attributes + if (!chart.styledMode) { + graphic.attr({ + stroke: options.color || + (categorized ? + Color + .parse('#ccd6eb') + .setOpacity(0.25) + .get() : + '#cccccc'), + 'stroke-width': pick(options.width, 1) + }).css({ + 'pointer-events': 'none' + }); + if (options.dashStyle) { + graphic.attr({ + dashstyle: options.dashStyle + }); + } + } + } + graphic.show().attr({ + d: path + }); + if (categorized && !options.width) { + graphic.attr({ + 'stroke-width': this.transA + }); + } + this.cross.e = e; + } + fireEvent(this, 'afterDrawCrosshair', { e: e, point: point }); + }; + /** + * Hide the crosshair if visible. + * + * @function Highcharts.Axis#hideCrosshair + */ + Axis.prototype.hideCrosshair = function () { + if (this.cross) { + this.cross.hide(); + } + fireEvent(this, 'afterHideCrosshair'); + }; + /** + * Check whether the chart has vertical panning ('y' or 'xy' type). + * + * @private + * @function Highcharts.Axis#hasVerticalPanning + * @return {boolean} + * + */ + Axis.prototype.hasVerticalPanning = function () { + var _a, _b; + return /y/.test(((_b = (_a = this.chart.options.chart) === null || _a === void 0 ? void 0 : _a.panning) === null || _b === void 0 ? void 0 : _b.type) || ''); + }; + /* * + * + * Static Properties + * + * */ + /** + * The X axis or category axis. Normally this is the horizontal axis, + * though if the chart is inverted this is the vertical axis. In case of + * multiple axes, the xAxis node is an array of configuration objects. + * + * See the [Axis class](/class-reference/Highcharts.Axis) for programmatic + * access to the axis. + * + * @productdesc {highmaps} + * In Highmaps, the axis is hidden, but it is used behind the scenes to + * control features like zooming and panning. Zooming is in effect the same + * as setting the extremes of one of the exes. + * + * @type {*|Array<*>} + * @optionparent xAxis + * + * @private + */ + Axis.defaultOptions = { + /** + * When using multiple axis, the ticks of two or more opposite axes + * will automatically be aligned by adding ticks to the axis or axes + * with the least ticks, as if `tickAmount` were specified. + * + * This can be prevented by setting `alignTicks` to false. If the grid + * lines look messy, it's a good idea to hide them for the secondary + * axis by setting `gridLineWidth` to 0. + * + * If `startOnTick` or `endOnTick` in an Axis options are set to false, + * then the `alignTicks ` will be disabled for the Axis. + * + * Disabled for logarithmic axes. + * + * @type {boolean} + * @default true + * @product highcharts highstock gantt + * @apioption xAxis.alignTicks + */ + /** + * Whether to allow decimals in this axis' ticks. When counting + * integers, like persons or hits on a web page, decimals should + * be avoided in the labels. + * + * @see [minTickInterval](#xAxis.minTickInterval) + * + * @sample {highcharts|highstock} highcharts/yaxis/allowdecimals-true/ + * True by default + * @sample {highcharts|highstock} highcharts/yaxis/allowdecimals-false/ + * False + * + * @type {boolean} + * @default true + * @since 2.0 + * @apioption xAxis.allowDecimals + */ + /** + * When using an alternate grid color, a band is painted across the + * plot area between every other grid line. + * + * @sample {highcharts} highcharts/yaxis/alternategridcolor/ + * Alternate grid color on the Y axis + * @sample {highstock} stock/xaxis/alternategridcolor/ + * Alternate grid color on the Y axis + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption xAxis.alternateGridColor + */ + /** + * An array defining breaks in the axis, the sections defined will be + * left out and all the points shifted closer to each other. + * + * @productdesc {highcharts} + * Requires that the broken-axis.js module is loaded. + * + * @sample {highcharts} highcharts/axisbreak/break-simple/ + * Simple break + * @sample {highcharts|highstock} highcharts/axisbreak/break-visualized/ + * Advanced with callback + * @sample {highstock} stock/demo/intraday-breaks/ + * Break on nights and weekends + * + * @type {Array<*>} + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption xAxis.breaks + */ + /** + * A number indicating how much space should be left between the start + * and the end of the break. The break size is given in axis units, + * so for instance on a `datetime` axis, a break size of 3600000 would + * indicate the equivalent of an hour. + * + * @type {number} + * @default 0 + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption xAxis.breaks.breakSize + */ + /** + * The point where the break starts. + * + * @type {number} + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption xAxis.breaks.from + */ + /** + * Defines an interval after which the break appears again. By default + * the breaks do not repeat. + * + * @type {number} + * @default 0 + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption xAxis.breaks.repeat + */ + /** + * The point where the break ends. + * + * @type {number} + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption xAxis.breaks.to + */ + /** + * If categories are present for the xAxis, names are used instead of + * numbers for that axis. + * + * Since Highcharts 3.0, categories can also + * be extracted by giving each point a [name](#series.data) and setting + * axis [type](#xAxis.type) to `category`. However, if you have multiple + * series, best practice remains defining the `categories` array. + * + * Example: `categories: ['Apples', 'Bananas', 'Oranges']` + * + * @sample {highcharts} highcharts/demo/line-labels/ + * With + * @sample {highcharts} highcharts/xaxis/categories/ + * Without + * + * @type {Array} + * @product highcharts gantt + * @apioption xAxis.categories + */ + /** + * The highest allowed value for automatically computed axis extremes. + * + * @see [floor](#xAxis.floor) + * + * @sample {highcharts|highstock} highcharts/yaxis/floor-ceiling/ + * Floor and ceiling + * + * @type {number} + * @since 4.0 + * @product highcharts highstock gantt + * @apioption xAxis.ceiling + */ + /** + * A class name that opens for styling the axis by CSS, especially in + * Highcharts styled mode. The class name is applied to group elements + * for the grid, axis elements and labels. + * + * @sample {highcharts|highstock|highmaps} highcharts/css/axis/ + * Multiple axes with separate styling + * + * @type {string} + * @since 5.0.0 + * @apioption xAxis.className + */ + /** + * Configure a crosshair that follows either the mouse pointer or the + * hovered point. + * + * In styled mode, the crosshairs are styled in the + * `.highcharts-crosshair`, `.highcharts-crosshair-thin` or + * `.highcharts-xaxis-category` classes. + * + * @productdesc {highstock} + * In Highstock, by default, the crosshair is enabled on the X axis and + * disabled on the Y axis. + * + * @sample {highcharts} highcharts/xaxis/crosshair-both/ + * Crosshair on both axes + * @sample {highstock} stock/xaxis/crosshairs-xy/ + * Crosshair on both axes + * @sample {highmaps} highcharts/xaxis/crosshair-both/ + * Crosshair on both axes + * + * @declare Highcharts.AxisCrosshairOptions + * @type {boolean|*} + * @default false + * @since 4.1 + * @apioption xAxis.crosshair + */ + /** + * A class name for the crosshair, especially as a hook for styling. + * + * @type {string} + * @since 5.0.0 + * @apioption xAxis.crosshair.className + */ + /** + * The color of the crosshair. Defaults to `#cccccc` for numeric and + * datetime axes, and `rgba(204,214,235,0.25)` for category axes, where + * the crosshair by default highlights the whole category. + * + * @sample {highcharts|highstock|highmaps} highcharts/xaxis/crosshair-customized/ + * Customized crosshairs + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #cccccc + * @since 4.1 + * @apioption xAxis.crosshair.color + */ + /** + * The dash style for the crosshair. See + * [plotOptions.series.dashStyle](#plotOptions.series.dashStyle) + * for possible values. + * + * @sample {highcharts|highmaps} highcharts/xaxis/crosshair-dotted/ + * Dotted crosshair + * @sample {highstock} stock/xaxis/crosshair-dashed/ + * Dashed X axis crosshair + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 4.1 + * @apioption xAxis.crosshair.dashStyle + */ + /** + * A label on the axis next to the crosshair. + * + * In styled mode, the label is styled with the + * `.highcharts-crosshair-label` class. + * + * @sample {highstock} stock/xaxis/crosshair-label/ + * Crosshair labels + * @sample {highstock} highcharts/css/crosshair-label/ + * Style mode + * + * @declare Highcharts.AxisCrosshairLabelOptions + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label + */ + /** + * Alignment of the label compared to the axis. Defaults to `"left"` for + * right-side axes, `"right"` for left-side axes and `"center"` for + * horizontal axes. + * + * @type {Highcharts.AlignValue} + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.align + */ + /** + * The background color for the label. Defaults to the related series + * color, or `#666666` if that is not available. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.backgroundColor + */ + /** + * The border color for the crosshair label + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.borderColor + */ + /** + * The border corner radius of the crosshair label. + * + * @type {number} + * @default 3 + * @since 2.1.10 + * @product highstock + * @apioption xAxis.crosshair.label.borderRadius + */ + /** + * The border width for the crosshair label. + * + * @type {number} + * @default 0 + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.borderWidth + */ + /** + * Flag to enable crosshair's label. + * + * @sample {highstock} stock/xaxis/crosshairs-xy/ + * Enabled label for yAxis' crosshair + * + * @type {boolean} + * @default false + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.enabled + */ + /** + * A format string for the crosshair label. Defaults to `{value}` for + * numeric axes and `{value:%b %d, %Y}` for datetime axes. + * + * @type {string} + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.format + */ + /** + * Formatter function for the label text. + * + * @type {Highcharts.XAxisCrosshairLabelFormatterCallbackFunction} + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.formatter + */ + /** + * Padding inside the crosshair label. + * + * @type {number} + * @default 8 + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.padding + */ + /** + * The shape to use for the label box. + * + * @type {string} + * @default callout + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.shape + */ + /** + * Text styles for the crosshair label. + * + * @type {Highcharts.CSSObject} + * @default {"color": "white", "fontWeight": "normal", "fontSize": "11px", "textAlign": "center"} + * @since 2.1 + * @product highstock + * @apioption xAxis.crosshair.label.style + */ + /** + * Whether the crosshair should snap to the point or follow the pointer + * independent of points. + * + * @sample {highcharts|highstock} highcharts/xaxis/crosshair-snap-false/ + * True by default + * @sample {highmaps} maps/demo/latlon-advanced/ + * Snap is false + * + * @type {boolean} + * @default true + * @since 4.1 + * @apioption xAxis.crosshair.snap + */ + /** + * The pixel width of the crosshair. Defaults to 1 for numeric or + * datetime axes, and for one category width for category axes. + * + * @sample {highcharts} highcharts/xaxis/crosshair-customized/ + * Customized crosshairs + * @sample {highstock} highcharts/xaxis/crosshair-customized/ + * Customized crosshairs + * @sample {highmaps} highcharts/xaxis/crosshair-customized/ + * Customized crosshairs + * + * @type {number} + * @default 1 + * @since 4.1 + * @apioption xAxis.crosshair.width + */ + /** + * The Z index of the crosshair. Higher Z indices allow drawing the + * crosshair on top of the series or behind the grid lines. + * + * @type {number} + * @default 2 + * @since 4.1 + * @apioption xAxis.crosshair.zIndex + */ + /** + * Whether to zoom axis. If `chart.zoomType` is set, the option allows + * to disable zooming on an individual axis. + * + * @sample {highcharts} highcharts/xaxis/zoomenabled/ + * Zoom enabled is false + * + * + * @type {boolean} + * @default enabled + * @apioption xAxis.zoomEnabled + */ + /** + * For a datetime axis, the scale will automatically adjust to the + * appropriate unit. This member gives the default string + * representations used for each unit. For intermediate values, + * different units may be used, for example the `day` unit can be used + * on midnight and `hour` unit be used for intermediate values on the + * same axis. For an overview of the replacement codes, see + * [dateFormat](/class-reference/Highcharts#dateFormat). + * + * Defaults to: + * ```js + * { + * millisecond: '%H:%M:%S.%L', + * second: '%H:%M:%S', + * minute: '%H:%M', + * hour: '%H:%M', + * day: '%e. %b', + * week: '%e. %b', + * month: '%b \'%y', + * year: '%Y' + * } + * ``` + * + * @sample {highcharts} highcharts/xaxis/datetimelabelformats/ + * Different day format on X axis + * @sample {highstock} stock/xaxis/datetimelabelformats/ + * More information in x axis labels + * + * @declare Highcharts.AxisDateTimeLabelFormatsOptions + * @product highcharts highstock gantt + */ + dateTimeLabelFormats: { + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + millisecond: { + main: '%H:%M:%S.%L', + range: false + }, + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + second: { + main: '%H:%M:%S', + range: false + }, + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + minute: { + main: '%H:%M', + range: false + }, + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + hour: { + main: '%H:%M', + range: false + }, + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + day: { + main: '%e. %b' + }, + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + week: { + main: '%e. %b' + }, + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + month: { + main: '%b \'%y' + }, + /** + * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject + * @type {string|*} + */ + year: { + main: '%Y' + } + }, + /** + * Whether to force the axis to end on a tick. Use this option with + * the `maxPadding` option to control the axis end. + * + * @productdesc {highstock} + * In Highstock, `endOnTick` is always `false` when the navigator + * is enabled, to prevent jumpy scrolling. + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * True by default + * @sample {highcharts} highcharts/yaxis/endontick/ + * False + * @sample {highstock} stock/demo/basic-line/ + * True by default + * @sample {highstock} stock/xaxis/endontick/ + * False + * + * @since 1.2.0 + */ + endOnTick: false, + /** + * Event handlers for the axis. + * + * @type {*} + * @apioption xAxis.events + */ + /** + * An event fired after the breaks have rendered. + * + * @see [breaks](#xAxis.breaks) + * + * @sample {highcharts} highcharts/axisbreak/break-event/ + * AfterBreak Event + * + * @type {Highcharts.AxisEventCallbackFunction} + * @since 4.1.0 + * @product highcharts gantt + * @apioption xAxis.events.afterBreaks + */ + /** + * As opposed to the `setExtremes` event, this event fires after the + * final min and max values are computed and corrected for `minRange`. + * + * Fires when the minimum and maximum is set for the axis, either by + * calling the `.setExtremes()` method or by selecting an area in the + * chart. One parameter, `event`, is passed to the function, containing + * common event information. + * + * The new user set minimum and maximum values can be found by + * `event.min` and `event.max`. These reflect the axis minimum and + * maximum in axis values. The actual data extremes are found in + * `event.dataMin` and `event.dataMax`. + * + * @type {Highcharts.AxisSetExtremesEventCallbackFunction} + * @since 2.3 + * @context Highcharts.Axis + * @apioption xAxis.events.afterSetExtremes + */ + /** + * An event fired when a break from this axis occurs on a point. + * + * @see [breaks](#xAxis.breaks) + * + * @sample {highcharts} highcharts/axisbreak/break-visualized/ + * Visualization of a Break + * + * @type {Highcharts.AxisPointBreakEventCallbackFunction} + * @since 4.1.0 + * @product highcharts gantt + * @context Highcharts.Axis + * @apioption xAxis.events.pointBreak + */ + /** + * An event fired when a point falls inside a break from this axis. + * + * @type {Highcharts.AxisPointBreakEventCallbackFunction} + * @product highcharts highstock gantt + * @context Highcharts.Axis + * @apioption xAxis.events.pointInBreak + */ + /** + * Fires when the minimum and maximum is set for the axis, either by + * calling the `.setExtremes()` method or by selecting an area in the + * chart. One parameter, `event`, is passed to the function, + * containing common event information. + * + * The new user set minimum and maximum values can be found by + * `event.min` and `event.max`. These reflect the axis minimum and + * maximum in data values. When an axis is zoomed all the way out from + * the "Reset zoom" button, `event.min` and `event.max` are null, and + * the new extremes are set based on `this.dataMin` and `this.dataMax`. + * + * @sample {highstock} stock/xaxis/events-setextremes/ + * Log new extremes on x axis + * + * @type {Highcharts.AxisSetExtremesEventCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Axis + * @apioption xAxis.events.setExtremes + */ + /** + * The lowest allowed value for automatically computed axis extremes. + * + * @see [ceiling](#yAxis.ceiling) + * + * @sample {highcharts} highcharts/yaxis/floor-ceiling/ + * Floor and ceiling + * @sample {highstock} stock/demo/lazy-loading/ + * Prevent negative stock price on Y axis + * + * @type {number} + * @since 4.0 + * @product highcharts highstock gantt + * @apioption xAxis.floor + */ + /** + * The dash or dot style of the grid lines. For possible values, see + * [this demonstration](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/). + * + * @sample {highcharts} highcharts/yaxis/gridlinedashstyle/ + * Long dashes + * @sample {highstock} stock/xaxis/gridlinedashstyle/ + * Long dashes + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 1.2 + * @apioption xAxis.gridLineDashStyle + */ + /** + * The Z index of the grid lines. + * + * @sample {highcharts|highstock} highcharts/xaxis/gridzindex/ + * A Z index of 4 renders the grid above the graph + * + * @type {number} + * @default 1 + * @product highcharts highstock gantt + * @apioption xAxis.gridZIndex + */ + /** + * An id for the axis. This can be used after render time to get + * a pointer to the axis object through `chart.get()`. + * + * @sample {highcharts} highcharts/xaxis/id/ + * Get the object + * @sample {highstock} stock/xaxis/id/ + * Get the object + * + * @type {string} + * @since 1.2.0 + * @apioption xAxis.id + */ + /** + * The axis labels show the number or category for each tick. + * + * Since v8.0.0: Labels are animated in categorized x-axis with + * updating data if `tickInterval` and `step` is set to 1. + * + * @productdesc {highmaps} + * X and Y axis labels are by default disabled in Highmaps, but the + * functionality is inherited from Highcharts and used on `colorAxis`, + * and can be enabled on X and Y axes too. + */ + labels: { + /** + * What part of the string the given position is anchored to. + * If `left`, the left side of the string is at the axis position. + * Can be one of `"left"`, `"center"` or `"right"`. Defaults to + * an intelligent guess based on which side of the chart the axis + * is on and the rotation of the label. + * + * @see [reserveSpace](#xAxis.labels.reserveSpace) + * + * @sample {highcharts} highcharts/xaxis/labels-align-left/ + * Left + * @sample {highcharts} highcharts/xaxis/labels-align-right/ + * Right + * @sample {highcharts} highcharts/xaxis/labels-reservespace-true/ + * Left-aligned labels on a vertical category axis + * + * @type {Highcharts.AlignValue} + * @apioption xAxis.labels.align + */ + /** + * For horizontal axes, the allowed degrees of label rotation + * to prevent overlapping labels. If there is enough space, + * labels are not rotated. As the chart gets narrower, it + * will start rotating the labels -45 degrees, then remove + * every second label and try again with rotations 0 and -45 etc. + * Set it to `false` to disable rotation, which will + * cause the labels to word-wrap if possible. + * + * @sample {highcharts|highstock} highcharts/xaxis/labels-autorotation-default/ + * Default auto rotation of 0 or -45 + * @sample {highcharts|highstock} highcharts/xaxis/labels-autorotation-0-90/ + * Custom graded auto rotation + * + * @type {Array|false} + * @default [-45] + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption xAxis.labels.autoRotation + */ + /** + * When each category width is more than this many pixels, we don't + * apply auto rotation. Instead, we lay out the axis label with word + * wrap. A lower limit makes sense when the label contains multiple + * short words that don't extend the available horizontal space for + * each label. + * + * @sample {highcharts} highcharts/xaxis/labels-autorotationlimit/ + * Lower limit + * + * @type {number} + * @default 80 + * @since 4.1.5 + * @product highcharts gantt + * @apioption xAxis.labels.autoRotationLimit + */ + /** + * Polar charts only. The label's pixel distance from the perimeter + * of the plot area. + * + * @type {number} + * @default 15 + * @product highcharts gantt + * @apioption xAxis.labels.distance + */ + /** + * Enable or disable the axis labels. + * + * @sample {highcharts} highcharts/xaxis/labels-enabled/ + * X axis labels disabled + * @sample {highstock} stock/xaxis/labels-enabled/ + * X axis labels disabled + * + * @default {highcharts|highstock|gantt} true + * @default {highmaps} false + */ + enabled: true, + /** + * A [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) + * for the axis label. + * + * @sample {highcharts|highstock} highcharts/yaxis/labels-format/ + * Add units to Y axis label + * + * @type {string} + * @default {value} + * @since 3.0 + * @apioption xAxis.labels.format + */ + /** + * Callback JavaScript function to format the label. The value + * is given by `this.value`. Additional properties for `this` are + * `axis`, `chart`, `isFirst` and `isLast`. The value of the default + * label formatter can be retrieved by calling + * `this.axis.defaultLabelFormatter.call(this)` within the function. + * + * Defaults to: + * ```js + * function() { + * return this.value; + * } + * ``` + * + * @sample {highcharts} highcharts/xaxis/labels-formatter-linked/ + * Linked category names + * @sample {highcharts} highcharts/xaxis/labels-formatter-extended/ + * Modified numeric labels + * @sample {highstock} stock/xaxis/labels-formatter/ + * Added units on Y axis + * + * @type {Highcharts.FormatterCallbackFunction} + * @apioption xAxis.labels.formatter + */ + /** + * The number of pixels to indent the labels per level in a treegrid + * axis. + * + * @sample gantt/treegrid-axis/demo + * Indentation 10px by default. + * @sample gantt/treegrid-axis/indentation-0px + * Indentation set to 0px. + * + * @product gantt + */ + indentation: 10, + /** + * Horizontal axis only. When `staggerLines` is not set, + * `maxStaggerLines` defines how many lines the axis is allowed to + * add to automatically avoid overlapping X labels. Set to `1` to + * disable overlap detection. + * + * @deprecated + * @type {number} + * @default 5 + * @since 1.3.3 + * @apioption xAxis.labels.maxStaggerLines + */ + /** + * How to handle overflowing labels on horizontal axis. If set to + * `"allow"`, it will not be aligned at all. By default it + * `"justify"` labels inside the chart area. If there is room to + * move it, it will be aligned to the edge, else it will be removed. + * + * @type {string} + * @default justify + * @since 2.2.5 + * @validvalue ["allow", "justify"] + * @apioption xAxis.labels.overflow + */ + /** + * The pixel padding for axis labels, to ensure white space between + * them. + * + * @type {number} + * @default 5 + * @product highcharts gantt + * @apioption xAxis.labels.padding + */ + /** + * Whether to reserve space for the labels. By default, space is + * reserved for the labels in these cases: + * + * * On all horizontal axes. + * * On vertical axes if `label.align` is `right` on a left-side + * axis or `left` on a right-side axis. + * * On vertical axes if `label.align` is `center`. + * + * This can be turned off when for example the labels are rendered + * inside the plot area instead of outside. + * + * @see [labels.align](#xAxis.labels.align) + * + * @sample {highcharts} highcharts/xaxis/labels-reservespace/ + * No reserved space, labels inside plot + * @sample {highcharts} highcharts/xaxis/labels-reservespace-true/ + * Left-aligned labels on a vertical category axis + * + * @type {boolean} + * @since 4.1.10 + * @product highcharts gantt + * @apioption xAxis.labels.reserveSpace + */ + /** + * Rotation of the labels in degrees. + * + * @sample {highcharts} highcharts/xaxis/labels-rotation/ + * X axis labels rotated 90° + * + * @type {number} + * @default 0 + * @apioption xAxis.labels.rotation + */ + /** + * Horizontal axes only. The number of lines to spread the labels + * over to make room or tighter labels. + * + * @sample {highcharts} highcharts/xaxis/labels-staggerlines/ + * Show labels over two lines + * @sample {highstock} stock/xaxis/labels-staggerlines/ + * Show labels over two lines + * + * @type {number} + * @since 2.1 + * @apioption xAxis.labels.staggerLines + */ + /** + * To show only every _n_'th label on the axis, set the step to _n_. + * Setting the step to 2 shows every other label. + * + * By default, the step is calculated automatically to avoid + * overlap. To prevent this, set it to 1\. This usually only + * happens on a category axis, and is often a sign that you have + * chosen the wrong axis type. + * + * Read more at + * [Axis docs](https://www.highcharts.com/docs/chart-concepts/axes) + * => What axis should I use? + * + * @sample {highcharts} highcharts/xaxis/labels-step/ + * Showing only every other axis label on a categorized + * x-axis + * @sample {highcharts} highcharts/xaxis/labels-step-auto/ + * Auto steps on a category axis + * + * @type {number} + * @since 2.1 + * @apioption xAxis.labels.step + */ + /** + * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the labels. + * + * @type {boolean} + * @default false + * @apioption xAxis.labels.useHTML + */ + /** + * The x position offset of the label relative to the tick position + * on the axis. + * + * @sample {highcharts} highcharts/xaxis/labels-x/ + * Y axis labels placed on grid lines + */ + x: 0, + /** + * The y position offset of the label relative to the tick position + * on the axis. The default makes it adapt to the font size on + * bottom axis. + * + * @sample {highcharts} highcharts/xaxis/labels-x/ + * Y axis labels placed on grid lines + * + * @type {number} + * @apioption xAxis.labels.y + */ + /** + * The Z index for the axis labels. + * + * @type {number} + * @default 7 + * @apioption xAxis.labels.zIndex + */ + /** + * CSS styles for the label. Use `whiteSpace: 'nowrap'` to prevent + * wrapping of category labels. Use `textOverflow: 'none'` to + * prevent ellipsis (dots). + * + * In styled mode, the labels are styled with the + * `.highcharts-axis-labels` class. + * + * @sample {highcharts} highcharts/xaxis/labels-style/ + * Red X axis labels + * + * @type {Highcharts.CSSObject} + */ + style: { + /** @internal */ + color: '#666666', + /** @internal */ + cursor: 'default', + /** @internal */ + fontSize: '11px' + } + }, + /** + * The left position as the horizontal axis. If it's a number, it is + * interpreted as pixel position relative to the chart. + * + * Since Highcharts v5.0.13: If it's a percentage string, it is + * interpreted as percentages of the plot width, offset from plot area + * left. + * + * @type {number|string} + * @product highcharts highstock + * @apioption xAxis.left + */ + /** + * The top position as the vertical axis. If it's a number, it is + * interpreted as pixel position relative to the chart. + * + * Since Highcharts 2: If it's a percentage string, it is interpreted + * as percentages of the plot height, offset from plot area top. + * + * @type {number|string} + * @product highcharts highstock + * @apioption xAxis.top + */ + /** + * Index of another axis that this axis is linked to. When an axis is + * linked to a master axis, it will take the same extremes as + * the master, but as assigned by min or max or by setExtremes. + * It can be used to show additional info, or to ease reading the + * chart by duplicating the scales. + * + * @sample {highcharts} highcharts/xaxis/linkedto/ + * Different string formats of the same date + * @sample {highcharts} highcharts/yaxis/linkedto/ + * Y values on both sides + * + * @type {number} + * @since 2.0.2 + * @product highcharts highstock gantt + * @apioption xAxis.linkedTo + */ + /** + * The maximum value of the axis. If `null`, the max value is + * automatically calculated. + * + * If the [endOnTick](#yAxis.endOnTick) option is true, the `max` value + * might be rounded up. + * + * If a [tickAmount](#yAxis.tickAmount) is set, the axis may be extended + * beyond the set max in order to reach the given number of ticks. The + * same may happen in a chart with multiple axes, determined by [chart. + * alignTicks](#chart), where a `tickAmount` is applied internally. + * + * @sample {highcharts} highcharts/yaxis/max-200/ + * Y axis max of 200 + * @sample {highcharts} highcharts/yaxis/max-logarithmic/ + * Y axis max on logarithmic axis + * @sample {highstock} stock/xaxis/min-max/ + * Fixed min and max on X axis + * @sample {highmaps} maps/axis/min-max/ + * Pre-zoomed to a specific area + * + * @type {number|null} + * @apioption xAxis.max + */ + /** + * Padding of the max value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. This is useful + * when you don't want the highest data value to appear on the edge + * of the plot area. When the axis' `max` option is set or a max extreme + * is set using `axis.setExtremes()`, the maxPadding will be ignored. + * + * @sample {highcharts} highcharts/yaxis/maxpadding/ + * Max padding of 0.25 on y axis + * @sample {highstock} stock/xaxis/minpadding-maxpadding/ + * Greater min- and maxPadding + * @sample {highmaps} maps/chart/plotbackgroundcolor-gradient/ + * Add some padding + * + * @default {highcharts} 0.01 + * @default {highstock|highmaps} 0 + * @since 1.2.0 + */ + maxPadding: 0.01, + /** + * Deprecated. Use `minRange` instead. + * + * @deprecated + * @type {number} + * @product highcharts highstock + * @apioption xAxis.maxZoom + */ + /** + * The minimum value of the axis. If `null` the min value is + * automatically calculated. + * + * If the [startOnTick](#yAxis.startOnTick) option is true (default), + * the `min` value might be rounded down. + * + * The automatically calculated minimum value is also affected by + * [floor](#yAxis.floor), [softMin](#yAxis.softMin), + * [minPadding](#yAxis.minPadding), [minRange](#yAxis.minRange) + * as well as [series.threshold](#plotOptions.series.threshold) + * and [series.softThreshold](#plotOptions.series.softThreshold). + * + * @sample {highcharts} highcharts/yaxis/min-startontick-false/ + * -50 with startOnTick to false + * @sample {highcharts} highcharts/yaxis/min-startontick-true/ + * -50 with startOnTick true by default + * @sample {highstock} stock/xaxis/min-max/ + * Set min and max on X axis + * @sample {highmaps} maps/axis/min-max/ + * Pre-zoomed to a specific area + * + * @type {number|null} + * @apioption xAxis.min + */ + /** + * The dash or dot style of the minor grid lines. For possible values, + * see [this demonstration](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/). + * + * @sample {highcharts} highcharts/yaxis/minorgridlinedashstyle/ + * Long dashes on minor grid lines + * @sample {highstock} stock/xaxis/minorgridlinedashstyle/ + * Long dashes on minor grid lines + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 1.2 + * @apioption xAxis.minorGridLineDashStyle + */ + /** + * Specific tick interval in axis units for the minor ticks. On a linear + * axis, if `"auto"`, the minor tick interval is calculated as a fifth + * of the tickInterval. If `null` or `undefined`, minor ticks are not + * shown. + * + * On logarithmic axes, the unit is the power of the value. For example, + * setting the minorTickInterval to 1 puts one tick on each of 0.1, 1, + * 10, 100 etc. Setting the minorTickInterval to 0.1 produces 9 ticks + * between 1 and 10, 10 and 100 etc. + * + * If user settings dictate minor ticks to become too dense, they don't + * make sense, and will be ignored to prevent performance problems. + * + * @sample {highcharts} highcharts/yaxis/minortickinterval-null/ + * Null by default + * @sample {highcharts} highcharts/yaxis/minortickinterval-5/ + * 5 units + * @sample {highcharts} highcharts/yaxis/minortickinterval-log-auto/ + * "auto" + * @sample {highcharts} highcharts/yaxis/minortickinterval-log/ + * 0.1 + * @sample {highstock} stock/demo/basic-line/ + * Null by default + * @sample {highstock} stock/xaxis/minortickinterval-auto/ + * "auto" + * + * @type {number|string|null} + * @apioption xAxis.minorTickInterval + */ + /** + * The pixel length of the minor tick marks. + * + * @sample {highcharts} highcharts/yaxis/minorticklength/ + * 10px on Y axis + * @sample {highstock} stock/xaxis/minorticks/ + * 10px on Y axis + */ + minorTickLength: 2, + /** + * The position of the minor tick marks relative to the axis line. + * Can be one of `inside` and `outside`. + * + * @sample {highcharts} highcharts/yaxis/minortickposition-outside/ + * Outside by default + * @sample {highcharts} highcharts/yaxis/minortickposition-inside/ + * Inside + * @sample {highstock} stock/xaxis/minorticks/ + * Inside + * + * @validvalue ["inside", "outside"] + */ + minorTickPosition: 'outside', + /** + * Enable or disable minor ticks. Unless + * [minorTickInterval](#xAxis.minorTickInterval) is set, the tick + * interval is calculated as a fifth of the `tickInterval`. + * + * On a logarithmic axis, minor ticks are laid out based on a best + * guess, attempting to enter approximately 5 minor ticks between + * each major tick. + * + * Prior to v6.0.0, ticks were unabled in auto layout by setting + * `minorTickInterval` to `"auto"`. + * + * @productdesc {highcharts} + * On axes using [categories](#xAxis.categories), minor ticks are not + * supported. + * + * @sample {highcharts} highcharts/yaxis/minorticks-true/ + * Enabled on linear Y axis + * + * @type {boolean} + * @default false + * @since 6.0.0 + * @apioption xAxis.minorTicks + */ + /** + * The pixel width of the minor tick mark. + * + * @sample {highcharts} highcharts/yaxis/minortickwidth/ + * 3px width + * @sample {highstock} stock/xaxis/minorticks/ + * 1px width + * + * @type {number} + * @default 0 + * @apioption xAxis.minorTickWidth + */ + /** + * Padding of the min value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. This is useful + * when you don't want the lowest data value to appear on the edge + * of the plot area. When the axis' `min` option is set or a min extreme + * is set using `axis.setExtremes()`, the minPadding will be ignored. + * + * @sample {highcharts} highcharts/yaxis/minpadding/ + * Min padding of 0.2 + * @sample {highstock} stock/xaxis/minpadding-maxpadding/ + * Greater min- and maxPadding + * @sample {highmaps} maps/chart/plotbackgroundcolor-gradient/ + * Add some padding + * + * @default {highcharts} 0.01 + * @default {highstock|highmaps} 0 + * @since 1.2.0 + * @product highcharts highstock gantt + */ + minPadding: 0.01, + /** + * The minimum range to display on this axis. The entire axis will not + * be allowed to span over a smaller interval than this. For example, + * for a datetime axis the main unit is milliseconds. If minRange is + * set to 3600000, you can't zoom in more than to one hour. + * + * The default minRange for the x axis is five times the smallest + * interval between any of the data points. + * + * On a logarithmic axis, the unit for the minimum range is the power. + * So a minRange of 1 means that the axis can be zoomed to 10-100, + * 100-1000, 1000-10000 etc. + * + * Note that the `minPadding`, `maxPadding`, `startOnTick` and + * `endOnTick` settings also affect how the extremes of the axis + * are computed. + * + * @sample {highcharts} highcharts/xaxis/minrange/ + * Minimum range of 5 + * @sample {highstock} stock/xaxis/minrange/ + * Max zoom of 6 months overrides user selections + * @sample {highmaps} maps/axis/minrange/ + * Minimum range of 1000 + * + * @type {number} + * @apioption xAxis.minRange + */ + /** + * The minimum tick interval allowed in axis values. For example on + * zooming in on an axis with daily data, this can be used to prevent + * the axis from showing hours. Defaults to the closest distance between + * two points on the axis. + * + * @type {number} + * @since 2.3.0 + * @apioption xAxis.minTickInterval + */ + /** + * The distance in pixels from the plot area to the axis line. + * A positive offset moves the axis with it's line, labels and ticks + * away from the plot area. This is typically used when two or more + * axes are displayed on the same side of the plot. With multiple + * axes the offset is dynamically adjusted to avoid collision, this + * can be overridden by setting offset explicitly. + * + * @sample {highcharts} highcharts/yaxis/offset/ + * Y axis offset of 70 + * @sample {highcharts} highcharts/yaxis/offset-centered/ + * Axes positioned in the center of the plot + * @sample {highstock} stock/xaxis/offset/ + * Y axis offset by 70 px + * + * @type {number} + * @default 0 + * @apioption xAxis.offset + */ + /** + * Whether to display the axis on the opposite side of the normal. The + * normal is on the left side for vertical axes and bottom for + * horizontal, so the opposite sides will be right and top respectively. + * This is typically used with dual or multiple axes. + * + * @sample {highcharts} highcharts/yaxis/opposite/ + * Secondary Y axis opposite + * @sample {highstock} stock/xaxis/opposite/ + * Y axis on left side + * + * @type {boolean} + * @default false + * @apioption xAxis.opposite + */ + /** + * In an ordinal axis, the points are equally spaced in the chart + * regardless of the actual time or x distance between them. This means + * that missing data periods (e.g. nights or weekends for a stock chart) + * will not take up space in the chart. + * Having `ordinal: false` will show any gaps created by the `gapSize` + * setting proportionate to their duration. + * + * In stock charts the X axis is ordinal by default, unless + * the boost module is used and at least one of the series' data length + * exceeds the [boostThreshold](#series.line.boostThreshold). + * + * @sample {highstock} stock/xaxis/ordinal-true/ + * True by default + * @sample {highstock} stock/xaxis/ordinal-false/ + * False + * + * @type {boolean} + * @default true + * @since 1.1 + * @product highstock + * @apioption xAxis.ordinal + */ + /** + * Additional range on the right side of the xAxis. Works similar to + * `xAxis.maxPadding`, but value is set in milliseconds. Can be set for + * both main `xAxis` and the navigator's `xAxis`. + * + * @sample {highstock} stock/xaxis/overscroll/ + * One minute overscroll with live data + * + * @type {number} + * @default 0 + * @since 6.0.0 + * @product highstock + * @apioption xAxis.overscroll + */ + /** + * Refers to the index in the [panes](#panes) array. Used for circular + * gauges and polar charts. When the option is not set then first pane + * will be used. + * + * @sample highcharts/demo/gauge-vu-meter + * Two gauges with different center + * + * @type {number} + * @product highcharts + * @apioption xAxis.pane + */ + /** + * The zoomed range to display when only defining one or none of `min` + * or `max`. For example, to show the latest month, a range of one month + * can be set. + * + * @sample {highstock} stock/xaxis/range/ + * Setting a zoomed range when the rangeSelector is disabled + * + * @type {number} + * @product highstock + * @apioption xAxis.range + */ + /** + * Whether to reverse the axis so that the highest number is closest + * to the origin. If the chart is inverted, the x axis is reversed by + * default. + * + * @sample {highcharts} highcharts/yaxis/reversed/ + * Reversed Y axis + * @sample {highstock} stock/xaxis/reversed/ + * Reversed Y axis + * + * @type {boolean} + * @default false + * @apioption xAxis.reversed + */ + // reversed: false, + /** + * This option determines how stacks should be ordered within a group. + * For example reversed xAxis also reverses stacks, so first series + * comes last in a group. To keep order like for non-reversed xAxis + * enable this option. + * + * @sample {highcharts} highcharts/xaxis/reversedstacks/ + * Reversed stacks comparison + * @sample {highstock} highcharts/xaxis/reversedstacks/ + * Reversed stacks comparison + * + * @type {boolean} + * @default false + * @since 6.1.1 + * @product highcharts highstock + * @apioption xAxis.reversedStacks + */ + /** + * An optional scrollbar to display on the X axis in response to + * limiting the minimum and maximum of the axis values. + * + * In styled mode, all the presentational options for the scrollbar are + * replaced by the classes `.highcharts-scrollbar-thumb`, + * `.highcharts-scrollbar-arrow`, `.highcharts-scrollbar-button`, + * `.highcharts-scrollbar-rifles` and `.highcharts-scrollbar-track`. + * + * @sample {highstock} stock/yaxis/heatmap-scrollbars/ + * Heatmap with both scrollbars + * + * @extends scrollbar + * @since 4.2.6 + * @product highstock + * @apioption xAxis.scrollbar + */ + /** + * Whether to show the axis line and title when the axis has no data. + * + * @sample {highcharts} highcharts/yaxis/showempty/ + * When clicking the legend to hide series, one axis preserves + * line and title, the other doesn't + * @sample {highstock} highcharts/yaxis/showempty/ + * When clicking the legend to hide series, one axis preserves + * line and title, the other doesn't + * + * @since 1.1 + */ + showEmpty: true, + /** + * Whether to show the first tick label. + * + * @sample {highcharts} highcharts/xaxis/showfirstlabel-false/ + * Set to false on X axis + * @sample {highstock} stock/xaxis/showfirstlabel/ + * Labels below plot lines on Y axis + * + * @type {boolean} + * @default true + * @apioption xAxis.showFirstLabel + */ + /** + * Whether to show the last tick label. Defaults to `true` on cartesian + * charts, and `false` on polar charts. + * + * @sample {highcharts} highcharts/xaxis/showlastlabel-true/ + * Set to true on X axis + * @sample {highstock} stock/xaxis/showfirstlabel/ + * Labels below plot lines on Y axis + * + * @type {boolean} + * @default true + * @product highcharts highstock gantt + * @apioption xAxis.showLastLabel + */ + /** + * A soft maximum for the axis. If the series data maximum is less than + * this, the axis will stay at this maximum, but if the series data + * maximum is higher, the axis will flex to show all data. + * + * @sample highcharts/yaxis/softmin-softmax/ + * Soft min and max + * + * @type {number} + * @since 5.0.1 + * @product highcharts highstock gantt + * @apioption xAxis.softMax + */ + /** + * A soft minimum for the axis. If the series data minimum is greater + * than this, the axis will stay at this minimum, but if the series + * data minimum is lower, the axis will flex to show all data. + * + * @sample highcharts/yaxis/softmin-softmax/ + * Soft min and max + * + * @type {number} + * @since 5.0.1 + * @product highcharts highstock gantt + * @apioption xAxis.softMin + */ + /** + * For datetime axes, this decides where to put the tick between weeks. + * 0 = Sunday, 1 = Monday. + * + * @sample {highcharts} highcharts/xaxis/startofweek-monday/ + * Monday by default + * @sample {highcharts} highcharts/xaxis/startofweek-sunday/ + * Sunday + * @sample {highstock} stock/xaxis/startofweek-1 + * Monday by default + * @sample {highstock} stock/xaxis/startofweek-0 + * Sunday + * + * @product highcharts highstock gantt + */ + startOfWeek: 1, + /** + * Whether to force the axis to start on a tick. Use this option with + * the `minPadding` option to control the axis start. + * + * @productdesc {highstock} + * In Highstock, `startOnTick` is always `false` when the navigator + * is enabled, to prevent jumpy scrolling. + * + * @sample {highcharts} highcharts/xaxis/startontick-false/ + * False by default + * @sample {highcharts} highcharts/xaxis/startontick-true/ + * True + * + * @since 1.2.0 + */ + startOnTick: false, + /** + * The amount of ticks to draw on the axis. This opens up for aligning + * the ticks of multiple charts or panes within a chart. This option + * overrides the `tickPixelInterval` option. + * + * This option only has an effect on linear axes. Datetime, logarithmic + * or category axes are not affected. + * + * @sample {highcharts} highcharts/yaxis/tickamount/ + * 8 ticks on Y axis + * @sample {highstock} highcharts/yaxis/tickamount/ + * 8 ticks on Y axis + * + * @type {number} + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption xAxis.tickAmount + */ + /** + * The interval of the tick marks in axis units. When `undefined`, the + * tick interval is computed to approximately follow the + * [tickPixelInterval](#xAxis.tickPixelInterval) on linear and datetime + * axes. On categorized axes, a `undefined` tickInterval will default to + * 1, one category. Note that datetime axes are based on milliseconds, + * so for example an interval of one day is expressed as + * `24 * 3600 * 1000`. + * + * On logarithmic axes, the tickInterval is based on powers, so a + * tickInterval of 1 means one tick on each of 0.1, 1, 10, 100 etc. A + * tickInterval of 2 means a tick of 0.1, 10, 1000 etc. A tickInterval + * of 0.2 puts a tick on 0.1, 0.2, 0.4, 0.6, 0.8, 1, 2, 4, 6, 8, 10, 20, + * 40 etc. + * + * + * If the tickInterval is too dense for labels to be drawn, Highcharts + * may remove ticks. + * + * If the chart has multiple axes, the [alignTicks](#chart.alignTicks) + * option may interfere with the `tickInterval` setting. + * + * @see [tickPixelInterval](#xAxis.tickPixelInterval) + * @see [tickPositions](#xAxis.tickPositions) + * @see [tickPositioner](#xAxis.tickPositioner) + * + * @sample {highcharts} highcharts/xaxis/tickinterval-5/ + * Tick interval of 5 on a linear axis + * @sample {highstock} stock/xaxis/tickinterval/ + * Tick interval of 0.01 on Y axis + * + * @type {number} + * @apioption xAxis.tickInterval + */ + /** + * The pixel length of the main tick marks. + * + * @sample {highcharts} highcharts/xaxis/ticklength/ + * 20 px tick length on the X axis + * @sample {highstock} stock/xaxis/ticks/ + * Formatted ticks on X axis + */ + tickLength: 10, + /** + * If tickInterval is `null` this option sets the approximate pixel + * interval of the tick marks. Not applicable to categorized axis. + * + * The tick interval is also influenced by the [minTickInterval]( + * #xAxis.minTickInterval) option, that, by default prevents ticks from + * being denser than the data points. + * + * @see [tickInterval](#xAxis.tickInterval) + * @see [tickPositioner](#xAxis.tickPositioner) + * @see [tickPositions](#xAxis.tickPositions) + * + * @sample {highcharts} highcharts/xaxis/tickpixelinterval-50/ + * 50 px on X axis + * @sample {highstock} stock/xaxis/tickpixelinterval/ + * 200 px on X axis + */ + tickPixelInterval: 100, + /** + * For categorized axes only. If `on` the tick mark is placed in the + * center of the category, if `between` the tick mark is placed between + * categories. The default is `between` if the `tickInterval` is 1, else + * `on`. + * + * @sample {highcharts} highcharts/xaxis/tickmarkplacement-between/ + * "between" by default + * @sample {highcharts} highcharts/xaxis/tickmarkplacement-on/ + * "on" + * + * @product highcharts gantt + * @validvalue ["on", "between"] + */ + tickmarkPlacement: 'between', + /** + * The position of the major tick marks relative to the axis line. + * Can be one of `inside` and `outside`. + * + * @sample {highcharts} highcharts/xaxis/tickposition-outside/ + * "outside" by default + * @sample {highcharts} highcharts/xaxis/tickposition-inside/ + * "inside" + * @sample {highstock} stock/xaxis/ticks/ + * Formatted ticks on X axis + * + * @validvalue ["inside", "outside"] + */ + tickPosition: 'outside', + /** + * A callback function returning array defining where the ticks are + * laid out on the axis. This overrides the default behaviour of + * [tickPixelInterval](#xAxis.tickPixelInterval) and [tickInterval]( + * #xAxis.tickInterval). The automatic tick positions are accessible + * through `this.tickPositions` and can be modified by the callback. + * + * @see [tickPositions](#xAxis.tickPositions) + * + * @sample {highcharts} highcharts/xaxis/tickpositions-tickpositioner/ + * Demo of tickPositions and tickPositioner + * @sample {highstock} highcharts/xaxis/tickpositions-tickpositioner/ + * Demo of tickPositions and tickPositioner + * + * @type {Highcharts.AxisTickPositionerCallbackFunction} + * @apioption xAxis.tickPositioner + */ + /** + * An array defining where the ticks are laid out on the axis. This + * overrides the default behaviour of [tickPixelInterval]( + * #xAxis.tickPixelInterval) and [tickInterval](#xAxis.tickInterval). + * + * @see [tickPositioner](#xAxis.tickPositioner) + * + * @sample {highcharts} highcharts/xaxis/tickpositions-tickpositioner/ + * Demo of tickPositions and tickPositioner + * @sample {highstock} highcharts/xaxis/tickpositions-tickpositioner/ + * Demo of tickPositions and tickPositioner + * + * @type {Array} + * @apioption xAxis.tickPositions + */ + /** + * The pixel width of the major tick marks. Defaults to 0 on category + * axes, otherwise 1. + * + * In styled mode, the stroke width is given in the `.highcharts-tick` + * class, but in order for the element to be generated on category axes, + * the option must be explicitly set to 1. + * + * @sample {highcharts} highcharts/xaxis/tickwidth/ + * 10 px width + * @sample {highcharts} highcharts/css/axis-grid/ + * Styled mode + * @sample {highstock} stock/xaxis/ticks/ + * Formatted ticks on X axis + * @sample {highstock} highcharts/css/axis-grid/ + * Styled mode + * + * @type {undefined|number} + * @default {highstock} 1 + * @default {highmaps} 0 + * @apioption xAxis.tickWidth + */ + /** + * The axis title, showing next to the axis line. + * + * @productdesc {highmaps} + * In Highmaps, the axis is hidden by default, but adding an axis title + * is still possible. X axis and Y axis titles will appear at the bottom + * and left by default. + */ + title: { + /** + * Deprecated. Set the `text` to `null` to disable the title. + * + * @deprecated + * @type {boolean} + * @product highcharts + * @apioption xAxis.title.enabled + */ + /** + * The pixel distance between the axis labels or line and the title. + * Defaults to 0 for horizontal axes, 10 for vertical + * + * @sample {highcharts} highcharts/xaxis/title-margin/ + * Y axis title margin of 60 + * + * @type {number} + * @apioption xAxis.title.margin + */ + /** + * The distance of the axis title from the axis line. By default, + * this distance is computed from the offset width of the labels, + * the labels' distance from the axis and the title's margin. + * However when the offset option is set, it overrides all this. + * + * @sample {highcharts} highcharts/yaxis/title-offset/ + * Place the axis title on top of the axis + * @sample {highstock} highcharts/yaxis/title-offset/ + * Place the axis title on top of the Y axis + * + * @type {number} + * @since 2.2.0 + * @apioption xAxis.title.offset + */ + /** + * Whether to reserve space for the title when laying out the axis. + * + * @type {boolean} + * @default true + * @since 5.0.11 + * @product highcharts highstock gantt + * @apioption xAxis.title.reserveSpace + */ + /** + * The rotation of the text in degrees. 0 is horizontal, 270 is + * vertical reading from bottom to top. + * + * @sample {highcharts} highcharts/yaxis/title-offset/ + * Horizontal + * + * @type {number} + * @default 0 + * @apioption xAxis.title.rotation + */ + /** + * The actual text of the axis title. It can contain basic HTML tags + * like `b`, `i` and `span` with style. + * + * @sample {highcharts} highcharts/xaxis/title-text/ + * Custom HTML + * @sample {highstock} stock/xaxis/title-text/ + * Titles for both axes + * + * @type {string|null} + * @apioption xAxis.title.text + */ + /** + * Alignment of the text, can be `"left"`, `"right"` or `"center"`. + * Default alignment depends on the + * [title.align](xAxis.title.align): + * + * Horizontal axes: + * - for `align` = `"low"`, `textAlign` is set to `left` + * - for `align` = `"middle"`, `textAlign` is set to `center` + * - for `align` = `"high"`, `textAlign` is set to `right` + * + * Vertical axes: + * - for `align` = `"low"` and `opposite` = `true`, `textAlign` is + * set to `right` + * - for `align` = `"low"` and `opposite` = `false`, `textAlign` is + * set to `left` + * - for `align` = `"middle"`, `textAlign` is set to `center` + * - for `align` = `"high"` and `opposite` = `true` `textAlign` is + * set to `left` + * - for `align` = `"high"` and `opposite` = `false` `textAlign` is + * set to `right` + * + * @type {Highcharts.AlignValue} + * @apioption xAxis.title.textAlign + */ + /** + * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the axis title. + * + * @type {boolean} + * @default false + * @product highcharts highstock gantt + * @apioption xAxis.title.useHTML + */ + /** + * Horizontal pixel offset of the title position. + * + * @type {number} + * @default 0 + * @since 4.1.6 + * @product highcharts highstock gantt + * @apioption xAxis.title.x + */ + /** + * Vertical pixel offset of the title position. + * + * @type {number} + * @product highcharts highstock gantt + * @apioption xAxis.title.y + */ + /** + * Alignment of the title relative to the axis values. Possible + * values are "low", "middle" or "high". + * + * @sample {highcharts} highcharts/xaxis/title-align-low/ + * "low" + * @sample {highcharts} highcharts/xaxis/title-align-center/ + * "middle" by default + * @sample {highcharts} highcharts/xaxis/title-align-high/ + * "high" + * @sample {highcharts} highcharts/yaxis/title-offset/ + * Place the Y axis title on top of the axis + * @sample {highstock} stock/xaxis/title-align/ + * Aligned to "high" value + * + * @type {Highcharts.AxisTitleAlignValue} + */ + align: 'middle', + /** + * CSS styles for the title. If the title text is longer than the + * axis length, it will wrap to multiple lines by default. This can + * be customized by setting `textOverflow: 'ellipsis'`, by + * setting a specific `width` or by setting `whiteSpace: 'nowrap'`. + * + * In styled mode, the stroke width is given in the + * `.highcharts-axis-title` class. + * + * @sample {highcharts} highcharts/xaxis/title-style/ + * Red + * @sample {highcharts} highcharts/css/axis/ + * Styled mode + * + * @type {Highcharts.CSSObject} + */ + style: { + /** @internal */ + color: '#666666' + } + }, + /** + * The type of axis. Can be one of `linear`, `logarithmic`, `datetime` + * or `category`. In a datetime axis, the numbers are given in + * milliseconds, and tick marks are placed on appropriate values like + * full hours or days. In a category axis, the + * [point names](#series.line.data.name) of the chart's series are used + * for categories, if not a [categories](#xAxis.categories) array is + * defined. + * + * @sample {highcharts} highcharts/xaxis/type-linear/ + * Linear + * @sample {highcharts} highcharts/yaxis/type-log/ + * Logarithmic + * @sample {highcharts} highcharts/yaxis/type-log-minorgrid/ + * Logarithmic with minor grid lines + * @sample {highcharts} highcharts/xaxis/type-log-both/ + * Logarithmic on two axes + * @sample {highcharts} highcharts/yaxis/type-log-negative/ + * Logarithmic with extension to emulate negative values + * + * @type {Highcharts.AxisTypeValue} + * @product highcharts gantt + */ + type: 'linear', + /** + * If there are multiple axes on the same side of the chart, the pixel + * margin between the axes. Defaults to 0 on vertical axes, 15 on + * horizontal axes. + * + * @type {number} + * @since 7.0.3 + * @apioption xAxis.margin + */ + /** + * Applies only when the axis `type` is `category`. When `uniqueNames` + * is true, points are placed on the X axis according to their names. + * If the same point name is repeated in the same or another series, + * the point is placed on the same X position as other points of the + * same name. When `uniqueNames` is false, the points are laid out in + * increasing X positions regardless of their names, and the X axis + * category will take the name of the last point in each position. + * + * @sample {highcharts} highcharts/xaxis/uniquenames-true/ + * True by default + * @sample {highcharts} highcharts/xaxis/uniquenames-false/ + * False + * + * @type {boolean} + * @default true + * @since 4.2.7 + * @product highcharts gantt + * @apioption xAxis.uniqueNames + */ + /** + * Datetime axis only. An array determining what time intervals the + * ticks are allowed to fall on. Each array item is an array where the + * first value is the time unit and the second value another array of + * allowed multiples. + * + * Defaults to: + * ```js + * units: [[ + * 'millisecond', // unit name + * [1, 2, 5, 10, 20, 25, 50, 100, 200, 500] // allowed multiples + * ], [ + * 'second', + * [1, 2, 5, 10, 15, 30] + * ], [ + * 'minute', + * [1, 2, 5, 10, 15, 30] + * ], [ + * 'hour', + * [1, 2, 3, 4, 6, 8, 12] + * ], [ + * 'day', + * [1] + * ], [ + * 'week', + * [1] + * ], [ + * 'month', + * [1, 3, 6] + * ], [ + * 'year', + * null + * ]] + * ``` + * + * @type {Array|null)>>} + * @product highcharts highstock gantt + * @apioption xAxis.units + */ + /** + * Whether axis, including axis title, line, ticks and labels, should + * be visible. + * + * @type {boolean} + * @default true + * @since 4.1.9 + * @product highcharts highstock gantt + * @apioption xAxis.visible + */ + /** + * Color of the minor, secondary grid lines. + * + * In styled mode, the stroke width is given in the + * `.highcharts-minor-grid-line` class. + * + * @sample {highcharts} highcharts/yaxis/minorgridlinecolor/ + * Bright grey lines from Y axis + * @sample {highcharts|highstock} highcharts/css/axis-grid/ + * Styled mode + * @sample {highstock} stock/xaxis/minorgridlinecolor/ + * Bright grey lines from Y axis + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #f2f2f2 + */ + minorGridLineColor: '#f2f2f2', + /** + * Width of the minor, secondary grid lines. + * + * In styled mode, the stroke width is given in the + * `.highcharts-grid-line` class. + * + * @sample {highcharts} highcharts/yaxis/minorgridlinewidth/ + * 2px lines from Y axis + * @sample {highcharts|highstock} highcharts/css/axis-grid/ + * Styled mode + * @sample {highstock} stock/xaxis/minorgridlinewidth/ + * 2px lines from Y axis + */ + minorGridLineWidth: 1, + /** + * Color for the minor tick marks. + * + * @sample {highcharts} highcharts/yaxis/minortickcolor/ + * Black tick marks on Y axis + * @sample {highstock} stock/xaxis/minorticks/ + * Black tick marks on Y axis + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #999999 + */ + minorTickColor: '#999999', + /** + * The color of the line marking the axis itself. + * + * In styled mode, the line stroke is given in the + * `.highcharts-axis-line` or `.highcharts-xaxis-line` class. + * + * @productdesc {highmaps} + * In Highmaps, the axis line is hidden by default, because the axis is + * not visible by default. + * + * @sample {highcharts} highcharts/yaxis/linecolor/ + * A red line on Y axis + * @sample {highcharts|highstock} highcharts/css/axis/ + * Axes in styled mode + * @sample {highstock} stock/xaxis/linecolor/ + * A red line on X axis + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #ccd6eb + */ + lineColor: '#ccd6eb', + /** + * The width of the line marking the axis itself. + * + * In styled mode, the stroke width is given in the + * `.highcharts-axis-line` or `.highcharts-xaxis-line` class. + * + * @sample {highcharts} highcharts/yaxis/linecolor/ + * A 1px line on Y axis + * @sample {highcharts|highstock} highcharts/css/axis/ + * Axes in styled mode + * @sample {highstock} stock/xaxis/linewidth/ + * A 2px line on X axis + * + * @default {highcharts|highstock} 1 + * @default {highmaps} 0 + */ + lineWidth: 1, + /** + * Color of the grid lines extending the ticks across the plot area. + * + * In styled mode, the stroke is given in the `.highcharts-grid-line` + * class. + * + * @productdesc {highmaps} + * In Highmaps, the grid lines are hidden by default. + * + * @sample {highcharts} highcharts/yaxis/gridlinecolor/ + * Green lines + * @sample {highcharts|highstock} highcharts/css/axis-grid/ + * Styled mode + * @sample {highstock} stock/xaxis/gridlinecolor/ + * Green lines + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #e6e6e6 + */ + gridLineColor: '#e6e6e6', + // gridLineDashStyle: 'solid', + /** + * The width of the grid lines extending the ticks across the plot area. + * + * In styled mode, the stroke width is given in the + * `.highcharts-grid-line` class. + * + * @sample {highcharts} highcharts/yaxis/gridlinewidth/ + * 2px lines + * @sample {highcharts|highstock} highcharts/css/axis-grid/ + * Styled mode + * @sample {highstock} stock/xaxis/gridlinewidth/ + * 2px lines + * + * @type {number} + * @default 0 + * @apioption xAxis.gridLineWidth + */ + // gridLineWidth: 0, + /** + * The height as the vertical axis. If it's a number, it is + * interpreted as pixels. + * + * Since Highcharts 2: If it's a percentage string, it is interpreted + * as percentages of the total plot height. + * + * @type {number|string} + * @product highcharts highstock + * @apioption xAxis.height + */ + /** + * The width as the horizontal axis. If it's a number, it is interpreted + * as pixels. + * + * Since Highcharts v5.0.13: If it's a percentage string, it is + * interpreted as percentages of the total plot width. + * + * @type {number|string} + * @product highcharts highstock + * @apioption xAxis.width + */ + /** + * Color for the main tick marks. + * + * In styled mode, the stroke is given in the `.highcharts-tick` + * class. + * + * @sample {highcharts} highcharts/xaxis/tickcolor/ + * Red ticks on X axis + * @sample {highcharts|highstock} highcharts/css/axis-grid/ + * Styled mode + * @sample {highstock} stock/xaxis/ticks/ + * Formatted ticks on X axis + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #ccd6eb + */ + tickColor: '#ccd6eb' + // tickWidth: 1 + }; + /** + * The Y axis or value axis. Normally this is the vertical axis, + * though if the chart is inverted this is the horizontal axis. + * In case of multiple axes, the yAxis node is an array of + * configuration objects. + * + * See [the Axis object](/class-reference/Highcharts.Axis) for programmatic + * access to the axis. + * + * @type {*|Array<*>} + * @extends xAxis + * @excluding currentDateIndicator,ordinal,overscroll + * @optionparent yAxis + * + * @private + */ + Axis.defaultYAxisOptions = { + /** + * The type of axis. Can be one of `linear`, `logarithmic`, `datetime`, + * `category` or `treegrid`. Defaults to `treegrid` for Gantt charts, + * `linear` for other chart types. + * + * In a datetime axis, the numbers are given in milliseconds, and tick + * marks are placed on appropriate values, like full hours or days. In a + * category or treegrid axis, the [point names](#series.line.data.name) + * of the chart's series are used for categories, if a + * [categories](#xAxis.categories) array is not defined. + * + * @sample {highcharts} highcharts/yaxis/type-log-minorgrid/ + * Logarithmic with minor grid lines + * @sample {highcharts} highcharts/yaxis/type-log-negative/ + * Logarithmic with extension to emulate negative values + * @sample {gantt} gantt/treegrid-axis/demo + * Treegrid axis + * + * @type {Highcharts.AxisTypeValue} + * @default {highcharts} linear + * @default {gantt} treegrid + * @product highcharts gantt + * @apioption yAxis.type + */ + /** + * The height of the Y axis. If it's a number, it is interpreted as + * pixels. + * + * Since Highcharts 2: If it's a percentage string, it is interpreted as + * percentages of the total plot height. + * + * @see [yAxis.top](#yAxis.top) + * + * @sample {highstock} stock/demo/candlestick-and-volume/ + * Percentage height panes + * + * @type {number|string} + * @product highcharts highstock + * @apioption yAxis.height + */ + /** + * Solid gauge only. Unless [stops](#yAxis.stops) are set, the color + * to represent the maximum value of the Y axis. + * + * @sample {highcharts} highcharts/yaxis/mincolor-maxcolor/ + * Min and max colors + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #003399 + * @since 4.0 + * @product highcharts + * @apioption yAxis.maxColor + */ + /** + * Solid gauge only. Unless [stops](#yAxis.stops) are set, the color + * to represent the minimum value of the Y axis. + * + * @sample {highcharts} highcharts/yaxis/mincolor-maxcolor/ + * Min and max color + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #e6ebf5 + * @since 4.0 + * @product highcharts + * @apioption yAxis.minColor + */ + /** + * Whether to reverse the axis so that the highest number is closest + * to the origin. + * + * @sample {highcharts} highcharts/yaxis/reversed/ + * Reversed Y axis + * @sample {highstock} stock/xaxis/reversed/ + * Reversed Y axis + * + * @type {boolean} + * @default {highcharts} false + * @default {highstock} false + * @default {highmaps} true + * @default {gantt} true + * @apioption yAxis.reversed + */ + /** + * If `true`, the first series in a stack will be drawn on top in a + * positive, non-reversed Y axis. If `false`, the first series is in + * the base of the stack. + * + * @sample {highcharts} highcharts/yaxis/reversedstacks-false/ + * Non-reversed stacks + * @sample {highstock} highcharts/yaxis/reversedstacks-false/ + * Non-reversed stacks + * + * @type {boolean} + * @default true + * @since 3.0.10 + * @product highcharts highstock + * @apioption yAxis.reversedStacks + */ + /** + * Solid gauge series only. Color stops for the solid gauge. Use this + * in cases where a linear gradient between a `minColor` and `maxColor` + * is not sufficient. The stops is an array of tuples, where the first + * item is a float between 0 and 1 assigning the relative position in + * the gradient, and the second item is the color. + * + * For solid gauges, the Y axis also inherits the concept of + * [data classes](https://api.highcharts.com/highmaps#colorAxis.dataClasses) + * from the Highmaps color axis. + * + * @see [minColor](#yAxis.minColor) + * @see [maxColor](#yAxis.maxColor) + * + * @sample {highcharts} highcharts/demo/gauge-solid/ + * True by default + * + * @type {Array} + * @since 4.0 + * @product highcharts + * @apioption yAxis.stops + */ + /** + * The pixel width of the major tick marks. + * + * @sample {highcharts} highcharts/xaxis/tickwidth/ 10 px width + * @sample {highstock} stock/xaxis/ticks/ Formatted ticks on X axis + * + * @type {number} + * @default 0 + * @product highcharts highstock gantt + * @apioption yAxis.tickWidth + */ + /** + * Angular gauges and solid gauges only. + * The label's pixel distance from the perimeter of the plot area. + * + * Since v7.1.2: If it's a percentage string, it is interpreted the + * same as [series.radius](#plotOptions.gauge.radius), so label can be + * aligned under the gauge's shape. + * + * @sample {highcharts} highcharts/yaxis/labels-distance/ + * Labels centered under the arc + * + * @type {number|string} + * @default -25 + * @product highcharts + * @apioption yAxis.labels.distance + */ + /** + * The y position offset of the label relative to the tick position + * on the axis. + * + * @sample {highcharts} highcharts/xaxis/labels-x/ + * Y axis labels placed on grid lines + * + * @type {number} + * @default {highcharts} 3 + * @default {highstock} -2 + * @default {highmaps} 3 + * @apioption yAxis.labels.y + */ + /** + * Whether to force the axis to end on a tick. Use this option with + * the `maxPadding` option to control the axis end. + * + * This option is always disabled, when panning type is + * either `y` or `xy`. + * + * @see [type](#chart.panning.type) + * + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * True by default + * @sample {highcharts} highcharts/yaxis/endontick/ + * False + * @sample {highstock} stock/demo/basic-line/ + * True by default + * @sample {highstock} stock/xaxis/endontick/ + * False for Y axis + * + * @since 1.2.0 + */ + endOnTick: true, + /** + * Padding of the max value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. This is useful + * when you don't want the highest data value to appear on the edge + * of the plot area. When the axis' `max` option is set or a max extreme + * is set using `axis.setExtremes()`, the maxPadding will be ignored. + * + * Also the `softThreshold` option takes precedence over `maxPadding`, + * so if the data is tangent to the threshold, `maxPadding` may not + * apply unless `softThreshold` is set to false. + * + * @sample {highcharts} highcharts/yaxis/maxpadding-02/ + * Max padding of 0.2 + * @sample {highstock} stock/xaxis/minpadding-maxpadding/ + * Greater min- and maxPadding + * + * @since 1.2.0 + * @product highcharts highstock gantt + */ + maxPadding: 0.05, + /** + * Padding of the min value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. This is useful + * when you don't want the lowest data value to appear on the edge + * of the plot area. When the axis' `min` option is set or a max extreme + * is set using `axis.setExtremes()`, the maxPadding will be ignored. + * + * Also the `softThreshold` option takes precedence over `minPadding`, + * so if the data is tangent to the threshold, `minPadding` may not + * apply unless `softThreshold` is set to false. + * + * @sample {highcharts} highcharts/yaxis/minpadding/ + * Min padding of 0.2 + * @sample {highstock} stock/xaxis/minpadding-maxpadding/ + * Greater min- and maxPadding + * + * @since 1.2.0 + * @product highcharts highstock gantt + */ + minPadding: 0.05, + /** + * @productdesc {highstock} + * In Highstock 1.x, the Y axis was placed on the left side by default. + * + * @sample {highcharts} highcharts/yaxis/opposite/ + * Secondary Y axis opposite + * @sample {highstock} stock/xaxis/opposite/ + * Y axis on left side + * + * @type {boolean} + * @default {highstock} true + * @default {highcharts} false + * @product highstock highcharts gantt + * @apioption yAxis.opposite + */ + /** + * @see [tickInterval](#xAxis.tickInterval) + * @see [tickPositioner](#xAxis.tickPositioner) + * @see [tickPositions](#xAxis.tickPositions) + */ + tickPixelInterval: 72, + showLastLabel: true, + /** + * @extends xAxis.labels + */ + labels: { + /** + * What part of the string the given position is anchored to. Can + * be one of `"left"`, `"center"` or `"right"`. The exact position + * also depends on the `labels.x` setting. + * + * Angular gauges and solid gauges defaults to `"center"`. + * Solid gauges with two labels have additional option `"auto"` + * for automatic horizontal and vertical alignment. + * + * @see [yAxis.labels.distance](#yAxis.labels.distance) + * + * @sample {highcharts} highcharts/yaxis/labels-align-left/ + * Left + * @sample {highcharts} highcharts/series-solidgauge/labels-auto-aligned/ + * Solid gauge labels auto aligned + * + * @type {Highcharts.AlignValue} + * @default {highcharts|highmaps} right + * @default {highstock} left + * @apioption yAxis.labels.align + */ + /** + * The x position offset of the label relative to the tick position + * on the axis. Defaults to -15 for left axis, 15 for right axis. + * + * @sample {highcharts} highcharts/xaxis/labels-x/ + * Y axis labels placed on grid lines + */ + x: -8 + }, + /** + * @productdesc {highmaps} + * In Highmaps, the axis line is hidden by default, because the axis is + * not visible by default. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption yAxis.lineColor + */ + /** + * @sample {highcharts} highcharts/yaxis/max-200/ + * Y axis max of 200 + * @sample {highcharts} highcharts/yaxis/max-logarithmic/ + * Y axis max on logarithmic axis + * @sample {highstock} stock/yaxis/min-max/ + * Fixed min and max on Y axis + * @sample {highmaps} maps/axis/min-max/ + * Pre-zoomed to a specific area + * + * @apioption yAxis.max + */ + /** + * @sample {highcharts} highcharts/yaxis/min-startontick-false/ + * -50 with startOnTick to false + * @sample {highcharts} highcharts/yaxis/min-startontick-true/ + * -50 with startOnTick true by default + * @sample {highstock} stock/yaxis/min-max/ + * Fixed min and max on Y axis + * @sample {highmaps} maps/axis/min-max/ + * Pre-zoomed to a specific area + * + * @apioption yAxis.min + */ + /** + * An optional scrollbar to display on the Y axis in response to + * limiting the minimum an maximum of the axis values. + * + * In styled mode, all the presentational options for the scrollbar + * are replaced by the classes `.highcharts-scrollbar-thumb`, + * `.highcharts-scrollbar-arrow`, `.highcharts-scrollbar-button`, + * `.highcharts-scrollbar-rifles` and `.highcharts-scrollbar-track`. + * + * @sample {highstock} stock/yaxis/scrollbar/ + * Scrollbar on the Y axis + * + * @extends scrollbar + * @since 4.2.6 + * @product highstock + * @excluding height + * @apioption yAxis.scrollbar + */ + /** + * Enable the scrollbar on the Y axis. + * + * @sample {highstock} stock/yaxis/scrollbar/ + * Enabled on Y axis + * + * @type {boolean} + * @default false + * @since 4.2.6 + * @product highstock + * @apioption yAxis.scrollbar.enabled + */ + /** + * Pixel margin between the scrollbar and the axis elements. + * + * @type {number} + * @default 10 + * @since 4.2.6 + * @product highstock + * @apioption yAxis.scrollbar.margin + */ + /** + * Whether to show the scrollbar when it is fully zoomed out at max + * range. Setting it to `false` on the Y axis makes the scrollbar stay + * hidden until the user zooms in, like common in browsers. + * + * @type {boolean} + * @default true + * @since 4.2.6 + * @product highstock + * @apioption yAxis.scrollbar.showFull + */ + /** + * The width of a vertical scrollbar or height of a horizontal + * scrollbar. Defaults to 20 on touch devices. + * + * @type {number} + * @default 14 + * @since 4.2.6 + * @product highstock + * @apioption yAxis.scrollbar.size + */ + /** + * Z index of the scrollbar elements. + * + * @type {number} + * @default 3 + * @since 4.2.6 + * @product highstock + * @apioption yAxis.scrollbar.zIndex + */ + /** + * A soft maximum for the axis. If the series data maximum is less + * than this, the axis will stay at this maximum, but if the series + * data maximum is higher, the axis will flex to show all data. + * + * **Note**: The [series.softThreshold]( + * #plotOptions.series.softThreshold) option takes precedence over this + * option. + * + * @sample highcharts/yaxis/softmin-softmax/ + * Soft min and max + * + * @type {number} + * @since 5.0.1 + * @product highcharts highstock gantt + * @apioption yAxis.softMax + */ + /** + * A soft minimum for the axis. If the series data minimum is greater + * than this, the axis will stay at this minimum, but if the series + * data minimum is lower, the axis will flex to show all data. + * + * **Note**: The [series.softThreshold]( + * #plotOptions.series.softThreshold) option takes precedence over this + * option. + * + * @sample highcharts/yaxis/softmin-softmax/ + * Soft min and max + * + * @type {number} + * @since 5.0.1 + * @product highcharts highstock gantt + * @apioption yAxis.softMin + */ + /** + * Defines the horizontal alignment of the stack total label. Can be one + * of `"left"`, `"center"` or `"right"`. The default value is calculated + * at runtime and depends on orientation and whether the stack is + * positive or negative. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-align-left/ + * Aligned to the left + * @sample {highcharts} highcharts/yaxis/stacklabels-align-center/ + * Aligned in center + * @sample {highcharts} highcharts/yaxis/stacklabels-align-right/ + * Aligned to the right + * + * @type {Highcharts.AlignValue} + * @since 2.1.5 + * @product highcharts + * @apioption yAxis.stackLabels.align + */ + /** + * A format string for the data label. Available variables are the same + * as for `formatter`. + * + * @type {string} + * @default {total} + * @since 3.0.2 + * @product highcharts highstock + * @apioption yAxis.stackLabels.format + */ + /** + * Rotation of the labels in degrees. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-rotation/ + * Labels rotated 45° + * + * @type {number} + * @default 0 + * @since 2.1.5 + * @product highcharts + * @apioption yAxis.stackLabels.rotation + */ + /** + * The text alignment for the label. While `align` determines where the + * texts anchor point is placed with regards to the stack, `textAlign` + * determines how the text is aligned against its anchor point. Possible + * values are `"left"`, `"center"` and `"right"`. The default value is + * calculated at runtime and depends on orientation and whether the + * stack is positive or negative. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-textalign-left/ + * Label in center position but text-aligned left + * + * @type {Highcharts.AlignValue} + * @since 2.1.5 + * @product highcharts + * @apioption yAxis.stackLabels.textAlign + */ + /** + * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the labels. + * + * @type {boolean} + * @default false + * @since 3.0 + * @product highcharts highstock + * @apioption yAxis.stackLabels.useHTML + */ + /** + * Defines the vertical alignment of the stack total label. Can be one + * of `"top"`, `"middle"` or `"bottom"`. The default value is calculated + * at runtime and depends on orientation and whether the stack is + * positive or negative. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-verticalalign-top/ + * Vertically aligned top + * @sample {highcharts} highcharts/yaxis/stacklabels-verticalalign-middle/ + * Vertically aligned middle + * @sample {highcharts} highcharts/yaxis/stacklabels-verticalalign-bottom/ + * Vertically aligned bottom + * + * @type {Highcharts.VerticalAlignValue} + * @since 2.1.5 + * @product highcharts + * @apioption yAxis.stackLabels.verticalAlign + */ + /** + * The x position offset of the label relative to the left of the + * stacked bar. The default value is calculated at runtime and depends + * on orientation and whether the stack is positive or negative. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-x/ + * Stack total labels with x offset + * + * @type {number} + * @since 2.1.5 + * @product highcharts + * @apioption yAxis.stackLabels.x + */ + /** + * The y position offset of the label relative to the tick position + * on the axis. The default value is calculated at runtime and depends + * on orientation and whether the stack is positive or negative. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-y/ + * Stack total labels with y offset + * + * @type {number} + * @since 2.1.5 + * @product highcharts + * @apioption yAxis.stackLabels.y + */ + /** + * Whether to force the axis to start on a tick. Use this option with + * the `maxPadding` option to control the axis start. + * + * This option is always disabled, when panning type is + * either `y` or `xy`. + * + * @see [type](#chart.panning.type) + * + * @sample {highcharts} highcharts/xaxis/startontick-false/ + * False by default + * @sample {highcharts} highcharts/xaxis/startontick-true/ + * True + * @sample {highstock} stock/xaxis/endontick/ + * False for Y axis + * + * @since 1.2.0 + * @product highcharts highstock gantt + */ + startOnTick: true, + title: { + /** + * The pixel distance between the axis labels and the title. + * Positive values are outside the axis line, negative are inside. + * + * @sample {highcharts} highcharts/xaxis/title-margin/ + * Y axis title margin of 60 + * + * @type {number} + * @default 40 + * @apioption yAxis.title.margin + */ + /** + * The rotation of the text in degrees. 0 is horizontal, 270 is + * vertical reading from bottom to top. + * + * @sample {highcharts} highcharts/yaxis/title-offset/ + * Horizontal + */ + rotation: 270, + /** + * The actual text of the axis title. Horizontal texts can contain + * HTML, but rotated texts are painted using vector techniques and + * must be clean text. The Y axis title is disabled by setting the + * `text` option to `undefined`. + * + * @sample {highcharts} highcharts/xaxis/title-text/ + * Custom HTML + * + * @type {string|null} + * @default {highcharts} Values + * @default {highstock} undefined + * @product highcharts highstock gantt + */ + text: 'Values' + }, + /** + * The top position of the Y axis. If it's a number, it is interpreted + * as pixel position relative to the chart. + * + * Since Highcharts 2: If it's a percentage string, it is interpreted as + * percentages of the plot height, offset from plot area top. + * + * @see [yAxis.height](#yAxis.height) + * + * @sample {highstock} stock/demo/candlestick-and-volume/ + * Percentage height panes + * + * @type {number|string} + * @product highcharts highstock + * @apioption yAxis.top + */ + /** + * The stack labels show the total value for each bar in a stacked + * column or bar chart. The label will be placed on top of positive + * columns and below negative columns. In case of an inverted column + * chart or a bar chart the label is placed to the right of positive + * bars and to the left of negative bars. + * + * @product highcharts + */ + stackLabels: { + /** + * Allow the stack labels to overlap. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-allowoverlap-false/ + * Default false + * + * @since 5.0.13 + * @product highcharts + */ + allowOverlap: false, + /** + * The background color or gradient for the stack label. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-box/ + * Stack labels box options + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 8.1.0 + * @apioption yAxis.stackLabels.backgroundColor + */ + /** + * The border color for the stack label. Defaults to `undefined`. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-box/ + * Stack labels box options + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 8.1.0 + * @apioption yAxis.stackLabels.borderColor + */ + /** + * The border radius in pixels for the stack label. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-box/ + * Stack labels box options + * @type {number} + * @default 0 + * @since 8.1.0 + * @apioption yAxis.stackLabels.borderRadius + */ + /** + * The border width in pixels for the stack label. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-box/ + * Stack labels box options + * @type {number} + * @default 0 + * @since 8.1.0 + * @apioption yAxis.stackLabels.borderWidth + */ + /** + * Enable or disable the stack total labels. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-enabled/ + * Enabled stack total labels + * @sample {highcharts} highcharts/yaxis/stacklabels-enabled-waterfall/ + * Enabled stack labels in waterfall chart + * + * @since 2.1.5 + * @product highcharts + */ + enabled: false, + /** + * Whether to hide stack labels that are outside the plot area. + * By default, the stack label is moved + * inside the plot area according to the + * [overflow](/highcharts/#yAxis/stackLabels/overflow) + * option. + * + * @type {boolean} + * @since 7.1.3 + */ + crop: true, + /** + * How to handle stack total labels that flow outside the plot area. + * The default is set to `"justify"`, + * which aligns them inside the plot area. + * For columns and bars, this means it will be moved inside the bar. + * To display stack labels outside the plot area, + * set `crop` to `false` and `overflow` to `"allow"`. + * + * @sample highcharts/yaxis/stacklabels-overflow/ + * Stack labels flows outside the plot area. + * + * @type {Highcharts.DataLabelsOverflowValue} + * @since 7.1.3 + */ + overflow: 'justify', + /* eslint-disable valid-jsdoc */ + /** + * Callback JavaScript function to format the label. The value is + * given by `this.total`. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-formatter/ + * Added units to stack total value + * + * @type {Highcharts.FormatterCallbackFunction} + * @since 2.1.5 + * @product highcharts + */ + formatter: function () { + var numberFormatter = this.axis.chart.numberFormatter; + /* eslint-enable valid-jsdoc */ + return numberFormatter(this.total, -1); + }, + /** + * CSS styles for the label. + * + * In styled mode, the styles are set in the + * `.highcharts-stack-label` class. + * + * @sample {highcharts} highcharts/yaxis/stacklabels-style/ + * Red stack total labels + * + * @type {Highcharts.CSSObject} + * @since 2.1.5 + * @product highcharts + */ + style: { + /** @internal */ + color: '#000000', + /** @internal */ + fontSize: '11px', + /** @internal */ + fontWeight: 'bold', + /** @internal */ + textOutline: '1px contrast' + } + }, + gridLineWidth: 1, + lineWidth: 0 + // tickWidth: 0 + }; + /** + * The Z axis or depth axis for 3D plots. + * + * See the [Axis class](/class-reference/Highcharts.Axis) for programmatic + * access to the axis. + * + * @sample {highcharts} highcharts/3d/scatter-zaxis-categories/ + * Z-Axis with Categories + * @sample {highcharts} highcharts/3d/scatter-zaxis-grid/ + * Z-Axis with styling + * + * @type {*|Array<*>} + * @extends xAxis + * @since 5.0.0 + * @product highcharts + * @excluding breaks, crosshair, height, left, lineColor, lineWidth, + * nameToX, showEmpty, top, width + * @apioption zAxis + * + * @private + */ + // This variable extends the defaultOptions for left axes. + Axis.defaultLeftAxisOptions = { + labels: { + x: -15 + }, + title: { + rotation: 270 + } + }; + // This variable extends the defaultOptions for right axes. + Axis.defaultRightAxisOptions = { + labels: { + x: 15 + }, + title: { + rotation: 90 + } + }; + // This variable extends the defaultOptions for bottom axes. + Axis.defaultBottomAxisOptions = { + labels: { + autoRotation: [-45], + x: 0 + // overflow: undefined, + // staggerLines: null + }, + margin: 15, + title: { + rotation: 0 + } + }; + // This variable extends the defaultOptions for top axes. + Axis.defaultTopAxisOptions = { + labels: { + autoRotation: [-45], + x: 0 + // overflow: undefined + // staggerLines: null + }, + margin: 15, + title: { + rotation: 0 + } + }; + // Properties to survive after destroy, needed for Axis.update (#4317, + // #5773, #5881). + Axis.keepProps = ['extKey', 'hcEvents', 'names', 'series', 'userMax', 'userMin']; + return Axis; + }()); + H.Axis = Axis; + + return H.Axis; + }); + _registerModule(_modules, 'parts/DateTimeAxis.js', [_modules['parts/Axis.js'], _modules['parts/Utilities.js']], function (Axis, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, getMagnitude = U.getMagnitude, normalizeTickInterval = U.normalizeTickInterval, timeUnits = U.timeUnits; + /* eslint-disable valid-jsdoc */ + var DateTimeAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function DateTimeAxisAdditions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Get a normalized tick interval for dates. Returns a configuration object + * with unit range (interval), count and name. Used to prepare data for + * `getTimeTicks`. Previously this logic was part of getTimeTicks, but as + * `getTimeTicks` now runs of segments in stock charts, the normalizing + * logic was extracted in order to prevent it for running over again for + * each segment having the same interval. #662, #697. + * @private + */ + /** + * Get a normalized tick interval for dates. Returns a configuration object + * with unit range (interval), count and name. Used to prepare data for + * `getTimeTicks`. Previously this logic was part of getTimeTicks, but as + * `getTimeTicks` now runs of segments in stock charts, the normalizing + * logic was extracted in order to prevent it for running over again for + * each segment having the same interval. #662, #697. + * @private + */ + DateTimeAxisAdditions.prototype.normalizeTimeTickInterval = function (tickInterval, unitsOption) { + var units = unitsOption || [[ + 'millisecond', + [1, 2, 5, 10, 20, 25, 50, 100, 200, 500] // allowed multiples + ], [ + 'second', + [1, 2, 5, 10, 15, 30] + ], [ + 'minute', + [1, 2, 5, 10, 15, 30] + ], [ + 'hour', + [1, 2, 3, 4, 6, 8, 12] + ], [ + 'day', + [1, 2] + ], [ + 'week', + [1, 2] + ], [ + 'month', + [1, 2, 3, 4, 6] + ], [ + 'year', + null + ]], unit = units[units.length - 1], // default unit is years + interval = timeUnits[unit[0]], multiples = unit[1], count, i; + // loop through the units to find the one that best fits the + // tickInterval + for (i = 0; i < units.length; i++) { + unit = units[i]; + interval = timeUnits[unit[0]]; + multiples = unit[1]; + if (units[i + 1]) { + // lessThan is in the middle between the highest multiple and + // the next unit. + var lessThan = (interval * + multiples[multiples.length - 1] + + timeUnits[units[i + 1][0]]) / 2; + // break and keep the current unit + if (tickInterval <= lessThan) { + break; + } + } + } + // prevent 2.5 years intervals, though 25, 250 etc. are allowed + if (interval === timeUnits.year && tickInterval < 5 * interval) { + multiples = [1, 2, 5]; + } + // get the count + count = normalizeTickInterval(tickInterval / interval, multiples, unit[0] === 'year' ? // #1913, #2360 + Math.max(getMagnitude(tickInterval / interval), 1) : + 1); + return { + unitRange: interval, + count: count, + unitName: unit[0] + }; + }; + return DateTimeAxisAdditions; + }()); + /** + * Date and time support for axes. + * + * @private + * @class + */ + var DateTimeAxis = /** @class */ (function () { + function DateTimeAxis() { + } + /* * + * + * Static Functions + * + * */ + /** + * Extends axis class with date and time support. + * @private + */ + DateTimeAxis.compose = function (AxisClass) { + AxisClass.keepProps.push('dateTime'); + var axisProto = AxisClass.prototype; + /** + * Set the tick positions to a time unit that makes sense, for example + * on the first of each month or on every Monday. Return an array with + * the time positions. Used in datetime axes as well as for grouping + * data on a datetime axis. + * + * @private + * @function Highcharts.Axis#getTimeTicks + * + * @param {Highcharts.TimeNormalizeObject} normalizedInterval + * The interval in axis values (ms) and thecount. + * + * @param {number} min + * The minimum in axis values. + * + * @param {number} max + * The maximum in axis values. + * + * @param {number} startOfWeek + * + * @return {Highcharts.AxisTickPositionsArray} + */ + axisProto.getTimeTicks = function () { + return this.chart.time.getTimeTicks.apply(this.chart.time, arguments); + }; + /* eslint-disable no-invalid-this */ + addEvent(AxisClass, 'init', function (e) { + var axis = this; + var options = e.userOptions; + if (options.type !== 'datetime') { + axis.dateTime = void 0; + return; + } + if (!axis.dateTime) { + axis.dateTime = new DateTimeAxisAdditions(axis); + } + }); + /* eslint-enable no-invalid-this */ + }; + /* * + * + * Static Properties + * + * */ + DateTimeAxis.AdditionsClass = DateTimeAxisAdditions; + return DateTimeAxis; + }()); + DateTimeAxis.compose(Axis); + + return DateTimeAxis; + }); + _registerModule(_modules, 'parts/LogarithmicAxis.js', [_modules['parts/Axis.js'], _modules['parts/Utilities.js']], function (Axis, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, getMagnitude = U.getMagnitude, normalizeTickInterval = U.normalizeTickInterval, pick = U.pick; + /* eslint-disable valid-jsdoc */ + /** + * Provides logarithmic support for axes. + * + * @private + * @class + */ + var LogarithmicAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function LogarithmicAxisAdditions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Set the tick positions of a logarithmic axis. + */ + LogarithmicAxisAdditions.prototype.getLogTickPositions = function (interval, min, max, minor) { + var log = this; + var axis = log.axis; + var axisLength = axis.len; + var options = axis.options; + // Since we use this method for both major and minor ticks, + // use a local variable and return the result + var positions = []; + // Reset + if (!minor) { + log.minorAutoInterval = void 0; + } + // First case: All ticks fall on whole logarithms: 1, 10, 100 etc. + if (interval >= 0.5) { + interval = Math.round(interval); + positions = axis.getLinearTickPositions(interval, min, max); + // Second case: We need intermediary ticks. For example + // 1, 2, 4, 6, 8, 10, 20, 40 etc. + } + else if (interval >= 0.08) { + var roundedMin = Math.floor(min), intermediate, i, j, len, pos, lastPos, break2; + if (interval > 0.3) { + intermediate = [1, 2, 4]; + // 0.2 equals five minor ticks per 1, 10, 100 etc + } + else if (interval > 0.15) { + intermediate = [1, 2, 4, 6, 8]; + } + else { // 0.1 equals ten minor ticks per 1, 10, 100 etc + intermediate = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + } + for (i = roundedMin; i < max + 1 && !break2; i++) { + len = intermediate.length; + for (j = 0; j < len && !break2; j++) { + pos = log.log2lin(log.lin2log(i) * intermediate[j]); + // #1670, lastPos is #3113 + if (pos > min && + (!minor || lastPos <= max) && + typeof lastPos !== 'undefined') { + positions.push(lastPos); + } + if (lastPos > max) { + break2 = true; + } + lastPos = pos; + } + } + // Third case: We are so deep in between whole logarithmic values that + // we might as well handle the tick positions like a linear axis. For + // example 1.01, 1.02, 1.03, 1.04. + } + else { + var realMin = log.lin2log(min), realMax = log.lin2log(max), tickIntervalOption = minor ? + axis.getMinorTickInterval() : + options.tickInterval, filteredTickIntervalOption = tickIntervalOption === 'auto' ? + null : + tickIntervalOption, tickPixelIntervalOption = options.tickPixelInterval / (minor ? 5 : 1), totalPixelLength = minor ? + axisLength / axis.tickPositions.length : + axisLength; + interval = pick(filteredTickIntervalOption, log.minorAutoInterval, (realMax - realMin) * + tickPixelIntervalOption / (totalPixelLength || 1)); + interval = normalizeTickInterval(interval, void 0, getMagnitude(interval)); + positions = axis.getLinearTickPositions(interval, realMin, realMax).map(log.log2lin); + if (!minor) { + log.minorAutoInterval = interval / 5; + } + } + // Set the axis-level tickInterval variable + if (!minor) { + axis.tickInterval = interval; + } + return positions; + }; + LogarithmicAxisAdditions.prototype.lin2log = function (num) { + return Math.pow(10, num); + }; + LogarithmicAxisAdditions.prototype.log2lin = function (num) { + return Math.log(num) / Math.LN10; + }; + return LogarithmicAxisAdditions; + }()); + var LogarithmicAxis = /** @class */ (function () { + function LogarithmicAxis() { + } + /** + * Provides logarithmic support for axes. + * + * @private + */ + LogarithmicAxis.compose = function (AxisClass) { + AxisClass.keepProps.push('logarithmic'); + // HC <= 8 backwards compatibility, allow wrapping + // Axis.prototype.lin2log and log2lin + // @todo Remove this in next major + var axisProto = AxisClass.prototype; + var logAxisProto = LogarithmicAxisAdditions.prototype; + axisProto.log2lin = logAxisProto.log2lin; + axisProto.lin2log = logAxisProto.lin2log; + /* eslint-disable no-invalid-this */ + addEvent(AxisClass, 'init', function (e) { + var axis = this; + var options = e.userOptions; + var logarithmic = axis.logarithmic; + if (options.type !== 'logarithmic') { + axis.logarithmic = void 0; + } + else { + if (!logarithmic) { + logarithmic = axis.logarithmic = new LogarithmicAxisAdditions(axis); + } + // HC <= 8 backwards compatibility, allow wrapping + // Axis.prototype.lin2log and log2lin + // @todo Remove this in next major + if (axis.log2lin !== logarithmic.log2lin) { + logarithmic.log2lin = axis.log2lin.bind(axis); + } + if (axis.lin2log !== logarithmic.lin2log) { + logarithmic.lin2log = axis.lin2log.bind(axis); + } + } + }); + addEvent(AxisClass, 'afterInit', function () { + var axis = this; + var log = axis.logarithmic; + // extend logarithmic axis + if (log) { + axis.lin2val = function (num) { + return log.lin2log(num); + }; + axis.val2lin = function (num) { + return log.log2lin(num); + }; + } + }); + }; + return LogarithmicAxis; + }()); + LogarithmicAxis.compose(Axis); // @todo move to factory functions + + return LogarithmicAxis; + }); + _registerModule(_modules, 'parts/PlotLineOrBand.js', [_modules['parts/Globals.js'], _modules['parts/Axis.js'], _modules['parts/Utilities.js']], function (H, Axis, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Options for plot bands on axes. + * + * @typedef {Highcharts.XAxisPlotBandsOptions|Highcharts.YAxisPlotBandsOptions|Highcharts.ZAxisPlotBandsOptions} Highcharts.AxisPlotBandsOptions + */ + /** + * Options for plot band labels on axes. + * + * @typedef {Highcharts.XAxisPlotBandsLabelOptions|Highcharts.YAxisPlotBandsLabelOptions|Highcharts.ZAxisPlotBandsLabelOptions} Highcharts.AxisPlotBandsLabelOptions + */ + /** + * Options for plot lines on axes. + * + * @typedef {Highcharts.XAxisPlotLinesOptions|Highcharts.YAxisPlotLinesOptions|Highcharts.ZAxisPlotLinesOptions} Highcharts.AxisPlotLinesOptions + */ + /** + * Options for plot line labels on axes. + * + * @typedef {Highcharts.XAxisPlotLinesLabelOptions|Highcharts.YAxisPlotLinesLabelOptions|Highcharts.ZAxisPlotLinesLabelOptions} Highcharts.AxisPlotLinesLabelOptions + */ + var arrayMax = U.arrayMax, arrayMin = U.arrayMin, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, erase = U.erase, extend = U.extend, fireEvent = U.fireEvent, merge = U.merge, objectEach = U.objectEach, pick = U.pick; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The object wrapper for plot lines and plot bands + * + * @class + * @name Highcharts.PlotLineOrBand + * + * @param {Highcharts.Axis} axis + * + * @param {Highcharts.AxisPlotLinesOptions|Highcharts.AxisPlotBandsOptions} [options] + */ + var PlotLineOrBand = /** @class */ (function () { + function PlotLineOrBand(axis, options) { + this.axis = axis; + if (options) { + this.options = options; + this.id = options.id; + } + } + /** + * Render the plot line or plot band. If it is already existing, + * move it. + * + * @private + * @function Highcharts.PlotLineOrBand#render + * @return {Highcharts.PlotLineOrBand|undefined} + */ + PlotLineOrBand.prototype.render = function () { + H.fireEvent(this, 'render'); + var plotLine = this, axis = plotLine.axis, horiz = axis.horiz, log = axis.logarithmic, options = plotLine.options, optionsLabel = options.label, label = plotLine.label, to = options.to, from = options.from, value = options.value, isBand = defined(from) && defined(to), isLine = defined(value), svgElem = plotLine.svgElem, isNew = !svgElem, path = [], color = options.color, zIndex = pick(options.zIndex, 0), events = options.events, attribs = { + 'class': 'highcharts-plot-' + (isBand ? 'band ' : 'line ') + + (options.className || '') + }, groupAttribs = {}, renderer = axis.chart.renderer, groupName = isBand ? 'bands' : 'lines', group; + // logarithmic conversion + if (log) { + from = log.log2lin(from); + to = log.log2lin(to); + value = log.log2lin(value); + } + // Set the presentational attributes + if (!axis.chart.styledMode) { + if (isLine) { + attribs.stroke = color || '#999999'; + attribs['stroke-width'] = pick(options.width, 1); + if (options.dashStyle) { + attribs.dashstyle = + options.dashStyle; + } + } + else if (isBand) { // plot band + attribs.fill = color || '#e6ebf5'; + if (options.borderWidth) { + attribs.stroke = options.borderColor; + attribs['stroke-width'] = options.borderWidth; + } + } + } + // Grouping and zIndex + groupAttribs.zIndex = zIndex; + groupName += '-' + zIndex; + group = axis.plotLinesAndBandsGroups[groupName]; + if (!group) { + axis.plotLinesAndBandsGroups[groupName] = group = + renderer.g('plot-' + groupName) + .attr(groupAttribs).add(); + } + // Create the path + if (isNew) { + /** + * SVG element of the plot line or band. + * + * @name Highcharts.PlotLineOrBand#svgElement + * @type {Highcharts.SVGElement} + */ + plotLine.svgElem = svgElem = renderer + .path() + .attr(attribs) + .add(group); + } + // Set the path or return + if (isLine) { + path = axis.getPlotLinePath({ + value: value, + lineWidth: svgElem.strokeWidth(), + acrossPanes: options.acrossPanes + }); + } + else if (isBand) { // plot band + path = axis.getPlotBandPath(from, to, options); + } + else { + return; + } + // common for lines and bands + if ((isNew || !svgElem.d) && path && path.length) { + svgElem.attr({ d: path }); + // events + if (events) { + objectEach(events, function (event, eventType) { + svgElem.on(eventType, function (e) { + events[eventType].apply(plotLine, [e]); + }); + }); + } + } + else if (svgElem) { + if (path) { + svgElem.show(true); + svgElem.animate({ d: path }); + } + else if (svgElem.d) { + svgElem.hide(); + if (label) { + plotLine.label = label = label.destroy(); + } + } + } + // the plot band/line label + if (optionsLabel && + (defined(optionsLabel.text) || defined(optionsLabel.formatter)) && + path && + path.length && + axis.width > 0 && + axis.height > 0 && + !path.isFlat) { + // apply defaults + optionsLabel = merge({ + align: horiz && isBand && 'center', + x: horiz ? !isBand && 4 : 10, + verticalAlign: !horiz && isBand && 'middle', + y: horiz ? isBand ? 16 : 10 : isBand ? 6 : -4, + rotation: horiz && !isBand && 90 + }, optionsLabel); + this.renderLabel(optionsLabel, path, isBand, zIndex); + } + else if (label) { // move out of sight + label.hide(); + } + // chainable + return plotLine; + }; + /** + * Render and align label for plot line or band. + * + * @private + * @function Highcharts.PlotLineOrBand#renderLabel + * @param {Highcharts.AxisPlotLinesLabelOptions|Highcharts.AxisPlotBandsLabelOptions} optionsLabel + * @param {Highcharts.SVGPathArray} path + * @param {boolean} [isBand] + * @param {number} [zIndex] + * @return {void} + */ + PlotLineOrBand.prototype.renderLabel = function (optionsLabel, path, isBand, zIndex) { + var plotLine = this, label = plotLine.label, renderer = plotLine.axis.chart.renderer, attribs, xBounds, yBounds, x, y, labelText; + // add the SVG element + if (!label) { + attribs = { + align: optionsLabel.textAlign || optionsLabel.align, + rotation: optionsLabel.rotation, + 'class': 'highcharts-plot-' + (isBand ? 'band' : 'line') + + '-label ' + (optionsLabel.className || '') + }; + attribs.zIndex = zIndex; + labelText = this.getLabelText(optionsLabel); + /** + * SVG element of the label. + * + * @name Highcharts.PlotLineOrBand#label + * @type {Highcharts.SVGElement} + */ + plotLine.label = label = renderer + .text(labelText, 0, 0, optionsLabel.useHTML) + .attr(attribs) + .add(); + if (!this.axis.chart.styledMode) { + label.css(optionsLabel.style); + } + } + // get the bounding box and align the label + // #3000 changed to better handle choice between plotband or plotline + xBounds = path.xBounds || + [path[0][1], path[1][1], (isBand ? path[2][1] : path[0][1])]; + yBounds = path.yBounds || + [path[0][2], path[1][2], (isBand ? path[2][2] : path[0][2])]; + x = arrayMin(xBounds); + y = arrayMin(yBounds); + label.align(optionsLabel, false, { + x: x, + y: y, + width: arrayMax(xBounds) - x, + height: arrayMax(yBounds) - y + }); + label.show(true); + }; + /** + * Get label's text content. + * + * @private + * @function Highcharts.PlotLineOrBand#getLabelText + * @param {Highcharts.AxisPlotLinesLabelOptions|Highcharts.AxisPlotBandsLabelOptions} optionsLabel + * @return {string} + */ + PlotLineOrBand.prototype.getLabelText = function (optionsLabel) { + return defined(optionsLabel.formatter) ? + optionsLabel.formatter + .call(this) : + optionsLabel.text; + }; + /** + * Remove the plot line or band. + * + * @function Highcharts.PlotLineOrBand#destroy + * @return {void} + */ + PlotLineOrBand.prototype.destroy = function () { + // remove it from the lookup + erase(this.axis.plotLinesAndBands, this); + delete this.axis; + destroyObjectProperties(this); + }; + return PlotLineOrBand; + }()); + /* eslint-enable no-invalid-this, valid-jsdoc */ + // Object with members for extending the Axis prototype + extend(Axis.prototype, /** @lends Highcharts.Axis.prototype */ { + /** + * An array of colored bands stretching across the plot area marking an + * interval on the axis. + * + * In styled mode, the plot bands are styled by the `.highcharts-plot-band` + * class in addition to the `className` option. + * + * @productdesc {highcharts} + * In a gauge, a plot band on the Y axis (value axis) will stretch along the + * perimeter of the gauge. + * + * @type {Array<*>} + * @product highcharts highstock gantt + * @apioption xAxis.plotBands + */ + /** + * Flag to decide if plotBand should be rendered across all panes. + * + * @since 7.1.2 + * @product highstock + * @type {boolean} + * @default true + * @apioption xAxis.plotBands.acrossPanes + */ + /** + * Border color for the plot band. Also requires `borderWidth` to be set. + * + * @type {Highcharts.ColorString} + * @apioption xAxis.plotBands.borderColor + */ + /** + * Border width for the plot band. Also requires `borderColor` to be set. + * + * @type {number} + * @default 0 + * @apioption xAxis.plotBands.borderWidth + */ + /** + * A custom class name, in addition to the default `highcharts-plot-band`, + * to apply to each individual band. + * + * @type {string} + * @since 5.0.0 + * @apioption xAxis.plotBands.className + */ + /** + * The color of the plot band. + * + * @sample {highcharts} highcharts/xaxis/plotbands-color/ + * Color band + * @sample {highstock} stock/xaxis/plotbands/ + * Plot band on Y axis + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #e6ebf5 + * @apioption xAxis.plotBands.color + */ + /** + * An object defining mouse events for the plot band. Supported properties + * are `click`, `mouseover`, `mouseout`, `mousemove`. + * + * @sample {highcharts} highcharts/xaxis/plotbands-events/ + * Mouse events demonstrated + * + * @since 1.2 + * @apioption xAxis.plotBands.events + */ + /** + * Click event on a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotBands.events.click + */ + /** + * Mouse move event on a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotBands.events.mousemove + */ + /** + * Mouse out event on the corner of a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotBands.events.mouseout + */ + /** + * Mouse over event on a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotBands.events.mouseover + */ + /** + * The start position of the plot band in axis units. + * + * @sample {highcharts} highcharts/xaxis/plotbands-color/ + * Datetime axis + * @sample {highcharts} highcharts/xaxis/plotbands-from/ + * Categorized axis + * @sample {highstock} stock/xaxis/plotbands/ + * Plot band on Y axis + * + * @type {number} + * @apioption xAxis.plotBands.from + */ + /** + * An id used for identifying the plot band in Axis.removePlotBand. + * + * @sample {highcharts} highcharts/xaxis/plotbands-id/ + * Remove plot band by id + * @sample {highstock} highcharts/xaxis/plotbands-id/ + * Remove plot band by id + * + * @type {string} + * @apioption xAxis.plotBands.id + */ + /** + * The end position of the plot band in axis units. + * + * @sample {highcharts} highcharts/xaxis/plotbands-color/ + * Datetime axis + * @sample {highcharts} highcharts/xaxis/plotbands-from/ + * Categorized axis + * @sample {highstock} stock/xaxis/plotbands/ + * Plot band on Y axis + * + * @type {number} + * @apioption xAxis.plotBands.to + */ + /** + * The z index of the plot band within the chart, relative to other + * elements. Using the same z index as another element may give + * unpredictable results, as the last rendered element will be on top. + * Values from 0 to 20 make sense. + * + * @sample {highcharts} highcharts/xaxis/plotbands-color/ + * Behind plot lines by default + * @sample {highcharts} highcharts/xaxis/plotbands-zindex/ + * Above plot lines + * @sample {highcharts} highcharts/xaxis/plotbands-zindex-above-series/ + * Above plot lines and series + * + * @type {number} + * @since 1.2 + * @apioption xAxis.plotBands.zIndex + */ + /** + * Text labels for the plot bands + * + * @product highcharts highstock gantt + * @apioption xAxis.plotBands.label + */ + /** + * Horizontal alignment of the label. Can be one of "left", "center" or + * "right". + * + * @sample {highcharts} highcharts/xaxis/plotbands-label-align/ + * Aligned to the right + * @sample {highstock} stock/xaxis/plotbands-label/ + * Plot band with labels + * + * @type {Highcharts.AlignValue} + * @default center + * @since 2.1 + * @apioption xAxis.plotBands.label.align + */ + /** + * Rotation of the text label in degrees . + * + * @sample {highcharts} highcharts/xaxis/plotbands-label-rotation/ + * Vertical text + * + * @type {number} + * @default 0 + * @since 2.1 + * @apioption xAxis.plotBands.label.rotation + */ + /** + * CSS styles for the text label. + * + * In styled mode, the labels are styled by the + * `.highcharts-plot-band-label` class. + * + * @sample {highcharts} highcharts/xaxis/plotbands-label-style/ + * Blue and bold label + * + * @type {Highcharts.CSSObject} + * @since 2.1 + * @apioption xAxis.plotBands.label.style + */ + /** + * The string text itself. A subset of HTML is supported. + * + * @type {string} + * @since 2.1 + * @apioption xAxis.plotBands.label.text + */ + /** + * The text alignment for the label. While `align` determines where the + * texts anchor point is placed within the plot band, `textAlign` determines + * how the text is aligned against its anchor point. Possible values are + * "left", "center" and "right". Defaults to the same as the `align` option. + * + * @sample {highcharts} highcharts/xaxis/plotbands-label-rotation/ + * Vertical text in center position but text-aligned left + * + * @type {Highcharts.AlignValue} + * @since 2.1 + * @apioption xAxis.plotBands.label.textAlign + */ + /** + * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the labels. + * + * @type {boolean} + * @default false + * @since 3.0.3 + * @apioption xAxis.plotBands.label.useHTML + */ + /** + * Vertical alignment of the label relative to the plot band. Can be one of + * "top", "middle" or "bottom". + * + * @sample {highcharts} highcharts/xaxis/plotbands-label-verticalalign/ + * Vertically centered label + * @sample {highstock} stock/xaxis/plotbands-label/ + * Plot band with labels + * + * @type {Highcharts.VerticalAlignValue} + * @default top + * @since 2.1 + * @apioption xAxis.plotBands.label.verticalAlign + */ + /** + * Horizontal position relative the alignment. Default varies by + * orientation. + * + * @sample {highcharts} highcharts/xaxis/plotbands-label-align/ + * Aligned 10px from the right edge + * @sample {highstock} stock/xaxis/plotbands-label/ + * Plot band with labels + * + * @type {number} + * @since 2.1 + * @apioption xAxis.plotBands.label.x + */ + /** + * Vertical position of the text baseline relative to the alignment. Default + * varies by orientation. + * + * @sample {highcharts} highcharts/xaxis/plotbands-label-y/ + * Label on x axis + * @sample {highstock} stock/xaxis/plotbands-label/ + * Plot band with labels + * + * @type {number} + * @since 2.1 + * @apioption xAxis.plotBands.label.y + */ + /** + * An array of lines stretching across the plot area, marking a specific + * value on one of the axes. + * + * In styled mode, the plot lines are styled by the + * `.highcharts-plot-line` class in addition to the `className` option. + * + * @type {Array<*>} + * @product highcharts highstock gantt + * @sample {highcharts} highcharts/xaxis/plotlines-color/ + * Basic plot line + * @sample {highcharts} highcharts/series-solidgauge/labels-auto-aligned/ + * Solid gauge plot line + * @apioption xAxis.plotLines + */ + /** + * Flag to decide if plotLine should be rendered across all panes. + * + * @sample {highstock} stock/xaxis/plotlines-acrosspanes/ + * Plot lines on different panes + * + * @since 7.1.2 + * @product highstock + * @type {boolean} + * @default true + * @apioption xAxis.plotLines.acrossPanes + */ + /** + * A custom class name, in addition to the default `highcharts-plot-line`, + * to apply to each individual line. + * + * @type {string} + * @since 5.0.0 + * @apioption xAxis.plotLines.className + */ + /** + * The color of the line. + * + * @sample {highcharts} highcharts/xaxis/plotlines-color/ + * A red line from X axis + * @sample {highstock} stock/xaxis/plotlines/ + * Plot line on Y axis + * + * @type {Highcharts.ColorString} + * @default #999999 + * @apioption xAxis.plotLines.color + */ + /** + * The dashing or dot style for the plot line. For possible values see + * [this overview](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/). + * + * @sample {highcharts} highcharts/xaxis/plotlines-dashstyle/ + * Dash and dot pattern + * @sample {highstock} stock/xaxis/plotlines/ + * Plot line on Y axis + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 1.2 + * @apioption xAxis.plotLines.dashStyle + */ + /** + * An object defining mouse events for the plot line. Supported + * properties are `click`, `mouseover`, `mouseout`, `mousemove`. + * + * @sample {highcharts} highcharts/xaxis/plotlines-events/ + * Mouse events demonstrated + * + * @since 1.2 + * @apioption xAxis.plotLines.events + */ + /** + * Click event on a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotLines.events.click + */ + /** + * Mouse move event on a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotLines.events.mousemove + */ + /** + * Mouse out event on the corner of a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotLines.events.mouseout + */ + /** + * Mouse over event on a plot band. + * + * @type {Highcharts.EventCallbackFunction} + * @apioption xAxis.plotLines.events.mouseover + */ + /** + * An id used for identifying the plot line in Axis.removePlotLine. + * + * @sample {highcharts} highcharts/xaxis/plotlines-id/ + * Remove plot line by id + * + * @type {string} + * @apioption xAxis.plotLines.id + */ + /** + * The position of the line in axis units. + * + * @sample {highcharts} highcharts/xaxis/plotlines-color/ + * Between two categories on X axis + * @sample {highstock} stock/xaxis/plotlines/ + * Plot line on Y axis + * + * @type {number} + * @apioption xAxis.plotLines.value + */ + /** + * The width or thickness of the plot line. + * + * @sample {highcharts} highcharts/xaxis/plotlines-color/ + * 2px wide line from X axis + * @sample {highstock} stock/xaxis/plotlines/ + * Plot line on Y axis + * + * @type {number} + * @default 2 + * @apioption xAxis.plotLines.width + */ + /** + * The z index of the plot line within the chart. + * + * @sample {highcharts} highcharts/xaxis/plotlines-zindex-behind/ + * Behind plot lines by default + * @sample {highcharts} highcharts/xaxis/plotlines-zindex-above/ + * Above plot lines + * @sample {highcharts} highcharts/xaxis/plotlines-zindex-above-all/ + * Above plot lines and series + * + * @type {number} + * @since 1.2 + * @apioption xAxis.plotLines.zIndex + */ + /** + * Text labels for the plot bands + * + * @apioption xAxis.plotLines.label + */ + /** + * Horizontal alignment of the label. Can be one of "left", "center" or + * "right". + * + * @sample {highcharts} highcharts/xaxis/plotlines-label-align-right/ + * Aligned to the right + * @sample {highstock} stock/xaxis/plotlines/ + * Plot line on Y axis + * + * @type {Highcharts.AlignValue} + * @default left + * @since 2.1 + * @apioption xAxis.plotLines.label.align + */ + /** + * Callback JavaScript function to format the label. Useful properties like + * the value of plot line or the range of plot band (`from` & `to` + * properties) can be found in `this.options` object. + * + * @sample {highcharts} highcharts/xaxis/plotlines-plotbands-label-formatter + * Label formatters for plot line and plot band. + * @type {Highcharts.FormatterCallbackFunction} + * @apioption xAxis.plotLines.label.formatter + */ + /** + * Rotation of the text label in degrees. Defaults to 0 for horizontal plot + * lines and 90 for vertical lines. + * + * @sample {highcharts} highcharts/xaxis/plotlines-label-verticalalign-middle/ + * Slanted text + * + * @type {number} + * @since 2.1 + * @apioption xAxis.plotLines.label.rotation + */ + /** + * CSS styles for the text label. + * + * In styled mode, the labels are styled by the + * `.highcharts-plot-line-label` class. + * + * @sample {highcharts} highcharts/xaxis/plotlines-label-style/ + * Blue and bold label + * + * @type {Highcharts.CSSObject} + * @since 2.1 + * @apioption xAxis.plotLines.label.style + */ + /** + * The text itself. A subset of HTML is supported. + * + * @type {string} + * @since 2.1 + * @apioption xAxis.plotLines.label.text + */ + /** + * The text alignment for the label. While `align` determines where the + * texts anchor point is placed within the plot band, `textAlign` determines + * how the text is aligned against its anchor point. Possible values are + * "left", "center" and "right". Defaults to the same as the `align` option. + * + * @sample {highcharts} highcharts/xaxis/plotlines-label-textalign/ + * Text label in bottom position + * + * @type {Highcharts.AlignValue} + * @since 2.1 + * @apioption xAxis.plotLines.label.textAlign + */ + /** + * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the labels. + * + * @type {boolean} + * @default false + * @since 3.0.3 + * @apioption xAxis.plotLines.label.useHTML + */ + /** + * Vertical alignment of the label relative to the plot line. Can be + * one of "top", "middle" or "bottom". + * + * @sample {highcharts} highcharts/xaxis/plotlines-label-verticalalign-middle/ + * Vertically centered label + * + * @type {Highcharts.VerticalAlignValue} + * @default {highcharts} top + * @default {highstock} top + * @since 2.1 + * @apioption xAxis.plotLines.label.verticalAlign + */ + /** + * Horizontal position relative the alignment. Default varies by + * orientation. + * + * @sample {highcharts} highcharts/xaxis/plotlines-label-align-right/ + * Aligned 10px from the right edge + * @sample {highstock} stock/xaxis/plotlines/ + * Plot line on Y axis + * + * @type {number} + * @since 2.1 + * @apioption xAxis.plotLines.label.x + */ + /** + * Vertical position of the text baseline relative to the alignment. Default + * varies by orientation. + * + * @sample {highcharts} highcharts/xaxis/plotlines-label-y/ + * Label below the plot line + * @sample {highstock} stock/xaxis/plotlines/ + * Plot line on Y axis + * + * @type {number} + * @since 2.1 + * @apioption xAxis.plotLines.label.y + */ + /** + * + * @type {Array<*>} + * @extends xAxis.plotBands + * @apioption yAxis.plotBands + */ + /** + * In a gauge chart, this option determines the inner radius of the + * plot band that stretches along the perimeter. It can be given as + * a percentage string, like `"100%"`, or as a pixel number, like `100`. + * By default, the inner radius is controlled by the [thickness]( + * #yAxis.plotBands.thickness) option. + * + * @sample {highcharts} highcharts/xaxis/plotbands-gauge + * Gauge plot band + * + * @type {number|string} + * @since 2.3 + * @product highcharts + * @apioption yAxis.plotBands.innerRadius + */ + /** + * In a gauge chart, this option determines the outer radius of the + * plot band that stretches along the perimeter. It can be given as + * a percentage string, like `"100%"`, or as a pixel number, like `100`. + * + * @sample {highcharts} highcharts/xaxis/plotbands-gauge + * Gauge plot band + * + * @type {number|string} + * @default 100% + * @since 2.3 + * @product highcharts + * @apioption yAxis.plotBands.outerRadius + */ + /** + * In a gauge chart, this option sets the width of the plot band + * stretching along the perimeter. It can be given as a percentage + * string, like `"10%"`, or as a pixel number, like `10`. The default + * value 10 is the same as the default [tickLength](#yAxis.tickLength), + * thus making the plot band act as a background for the tick markers. + * + * @sample {highcharts} highcharts/xaxis/plotbands-gauge + * Gauge plot band + * + * @type {number|string} + * @default 10 + * @since 2.3 + * @product highcharts + * @apioption yAxis.plotBands.thickness + */ + /** + * @type {Array<*>} + * @extends xAxis.plotLines + * @apioption yAxis.plotLines + */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Internal function to create the SVG path definition for a plot band. + * + * @function Highcharts.Axis#getPlotBandPath + * + * @param {number} from + * The axis value to start from. + * + * @param {number} to + * The axis value to end on. + * + * @return {Highcharts.SVGPathArray} + * The SVG path definition in array form. + */ + getPlotBandPath: function (from, to) { + var toPath = this.getPlotLinePath({ + value: to, + force: true, + acrossPanes: this.options.acrossPanes + }), path = this.getPlotLinePath({ + value: from, + force: true, + acrossPanes: this.options.acrossPanes + }), result = [], i, + // #4964 check if chart is inverted or plotband is on yAxis + horiz = this.horiz, plus = 1, isFlat, outside = (from < this.min && to < this.min) || + (from > this.max && to > this.max); + if (path && toPath) { + // Flat paths don't need labels (#3836) + if (outside) { + isFlat = path.toString() === toPath.toString(); + plus = 0; + } + // Go over each subpath - for panes in Highstock + for (i = 0; i < path.length; i += 2) { + var pathStart = path[i], pathEnd = path[i + 1], toPathStart = toPath[i], toPathEnd = toPath[i + 1]; + // Type checking all affected path segments. Consider something + // smarter. + if ((pathStart[0] === 'M' || pathStart[0] === 'L') && + (pathEnd[0] === 'M' || pathEnd[0] === 'L') && + (toPathStart[0] === 'M' || toPathStart[0] === 'L') && + (toPathEnd[0] === 'M' || toPathEnd[0] === 'L')) { + // Add 1 pixel when coordinates are the same + if (horiz && toPathStart[1] === pathStart[1]) { + toPathStart[1] += plus; + toPathEnd[1] += plus; + } + else if (!horiz && toPathStart[2] === pathStart[2]) { + toPathStart[2] += plus; + toPathEnd[2] += plus; + } + result.push(['M', pathStart[1], pathStart[2]], ['L', pathEnd[1], pathEnd[2]], ['L', toPathEnd[1], toPathEnd[2]], ['L', toPathStart[1], toPathStart[2]], ['Z']); + } + result.isFlat = isFlat; + } + } + else { // outside the axis area + path = null; + } + return result; + }, + /** + * Add a plot band after render time. + * + * @sample highcharts/members/axis-addplotband/ + * Toggle the plot band from a button + * + * @function Highcharts.Axis#addPlotBand + * + * @param {Highcharts.AxisPlotBandsOptions} options + * A configuration object for the plot band, as defined in + * [xAxis.plotBands](https://api.highcharts.com/highcharts/xAxis.plotBands). + * + * @return {Highcharts.PlotLineOrBand|undefined} + * The added plot band. + */ + addPlotBand: function (options) { + return this.addPlotBandOrLine(options, 'plotBands'); + }, + /** + * Add a plot line after render time. + * + * @sample highcharts/members/axis-addplotline/ + * Toggle the plot line from a button + * + * @function Highcharts.Axis#addPlotLine + * + * @param {Highcharts.AxisPlotLinesOptions} options + * A configuration object for the plot line, as defined in + * [xAxis.plotLines](https://api.highcharts.com/highcharts/xAxis.plotLines). + * + * @return {Highcharts.PlotLineOrBand|undefined} + * The added plot line. + */ + addPlotLine: function (options) { + return this.addPlotBandOrLine(options, 'plotLines'); + }, + /** + * Add a plot band or plot line after render time. Called from addPlotBand + * and addPlotLine internally. + * + * @private + * @function Highcharts.Axis#addPlotBandOrLine + * + * @param {Highcharts.AxisPlotBandsOptions|Highcharts.AxisPlotLinesOptions} options + * The plotBand or plotLine configuration object. + * + * @param {"plotBands"|"plotLines"} [coll] + * + * @return {Highcharts.PlotLineOrBand|undefined} + */ + addPlotBandOrLine: function (options, coll) { + var obj = new PlotLineOrBand(this, options).render(), userOptions = this.userOptions; + if (obj) { // #2189 + // Add it to the user options for exporting and Axis.update + if (coll) { + // Workaround Microsoft/TypeScript issue #32693 + var updatedOptions = (userOptions[coll] || []); + updatedOptions.push(options); + userOptions[coll] = updatedOptions; + } + this.plotLinesAndBands.push(obj); + } + return obj; + }, + /** + * Remove a plot band or plot line from the chart by id. Called internally + * from `removePlotBand` and `removePlotLine`. + * + * @private + * @function Highcharts.Axis#removePlotBandOrLine + * @param {string} id + * @return {void} + */ + removePlotBandOrLine: function (id) { + var plotLinesAndBands = this.plotLinesAndBands, options = this.options, userOptions = this.userOptions, i = plotLinesAndBands.length; + while (i--) { + if (plotLinesAndBands[i].id === id) { + plotLinesAndBands[i].destroy(); + } + } + ([ + options.plotLines || [], + userOptions.plotLines || [], + options.plotBands || [], + userOptions.plotBands || [] + ]).forEach(function (arr) { + i = arr.length; + while (i--) { + if ((arr[i] || {}).id === id) { + erase(arr, arr[i]); + } + } + }); + }, + /** + * Remove a plot band by its id. + * + * @sample highcharts/members/axis-removeplotband/ + * Remove plot band by id + * @sample highcharts/members/axis-addplotband/ + * Toggle the plot band from a button + * + * @function Highcharts.Axis#removePlotBand + * + * @param {string} id + * The plot band's `id` as given in the original configuration + * object or in the `addPlotBand` option. + * + * @return {void} + */ + removePlotBand: function (id) { + this.removePlotBandOrLine(id); + }, + /** + * Remove a plot line by its id. + * + * @sample highcharts/xaxis/plotlines-id/ + * Remove plot line by id + * @sample highcharts/members/axis-addplotline/ + * Toggle the plot line from a button + * + * @function Highcharts.Axis#removePlotLine + * + * @param {string} id + * The plot line's `id` as given in the original configuration + * object or in the `addPlotLine` option. + */ + removePlotLine: function (id) { + this.removePlotBandOrLine(id); + } + }); + H.PlotLineOrBand = PlotLineOrBand; + + return H.PlotLineOrBand; + }); + _registerModule(_modules, 'parts/Tooltip.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var clamp = U.clamp, css = U.css, defined = U.defined, discardElement = U.discardElement, extend = U.extend, fireEvent = U.fireEvent, format = U.format, isNumber = U.isNumber, isString = U.isString, merge = U.merge, offset = U.offset, pick = U.pick, splat = U.splat, syncTimeout = U.syncTimeout, timeUnits = U.timeUnits; + /** + * Callback function to format the text of the tooltip from scratch. + * + * In case of single or shared tooltips, a string should be be returned. In case + * of splitted tooltips, it should return an array where the first item is the + * header, and subsequent items are mapped to the points. Return `false` to + * disable tooltip for a specific point on series. + * + * @callback Highcharts.TooltipFormatterCallbackFunction + * + * @param {Highcharts.TooltipFormatterContextObject} this + * Context to format + * + * @param {Highcharts.Tooltip} tooltip + * The tooltip instance + * + * @return {false|string|Array<(string|null|undefined)>|null|undefined} + * Formatted text or false + */ + /** + * @interface Highcharts.TooltipFormatterContextObject + */ /** + * @name Highcharts.TooltipFormatterContextObject#color + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ /** + * @name Highcharts.TooltipFormatterContextObject#colorIndex + * @type {number|undefined} + */ /** + * @name Highcharts.TooltipFormatterContextObject#key + * @type {number} + */ /** + * @name Highcharts.TooltipFormatterContextObject#percentage + * @type {number|undefined} + */ /** + * @name Highcharts.TooltipFormatterContextObject#point + * @type {Highcharts.Point} + */ /** + * @name Highcharts.TooltipFormatterContextObject#points + * @type {Array|undefined} + */ /** + * @name Highcharts.TooltipFormatterContextObject#series + * @type {Highcharts.Series} + */ /** + * @name Highcharts.TooltipFormatterContextObject#total + * @type {number|undefined} + */ /** + * @name Highcharts.TooltipFormatterContextObject#x + * @type {number} + */ /** + * @name Highcharts.TooltipFormatterContextObject#y + * @type {number} + */ + /** + * A callback function to place the tooltip in a specific position. + * + * @callback Highcharts.TooltipPositionerCallbackFunction + * + * @param {number} labelWidth + * Width of the tooltip. + * + * @param {number} labelHeight + * Height of the tooltip. + * + * @param {Highcharts.Point} point + * Point information for positioning a tooltip. + * + * @return {Highcharts.PositionObject} + * New position for the tooltip. + */ + /** + * Point information for positioning a tooltip. + * + * @interface Highcharts.TooltipPositionerPointObject + */ /** + * If `tooltip.split` option is enabled and positioner is called for each of the + * boxes separately, this property indicates the call on the xAxis header, which + * is not a point itself. + * @name Highcharts.TooltipPositionerPointObject#isHeader + * @type {boolean} + */ /** + * @name Highcharts.TooltipPositionerPointObject#negative + * @type {boolean} + */ /** + * The reference point relative to the plot area. Add chart.plotLeft to get the + * full coordinates. + * @name Highcharts.TooltipPositionerPointObject#plotX + * @type {number} + */ /** + * The reference point relative to the plot area. Add chart.plotTop to get the + * full coordinates. + * @name Highcharts.TooltipPositionerPointObject#plotY + * @type {number} + */ + /** + * @typedef {"callout"|"circle"|"square"} Highcharts.TooltipShapeValue + */ + ''; // separates doclets above from variables below + var doc = H.doc; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Tooltip of a chart. + * + * @class + * @name Highcharts.Tooltip + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @param {Highcharts.TooltipOptions} options + * Tooltip options. + */ + var Tooltip = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Tooltip(chart, options) { + this.crosshairs = []; + this.distance = 0; + this.isHidden = true; + this.isSticky = false; + this.now = {}; + this.options = {}; + this.outside = false; + this.chart = chart; + this.init(chart, options); + } + /* * + * + * Functions + * + * */ + /** + * In styled mode, apply the default filter for the tooltip drop-shadow. It + * needs to have an id specific to the chart, otherwise there will be issues + * when one tooltip adopts the filter of a different chart, specifically one + * where the container is hidden. + * + * @private + * @function Highcharts.Tooltip#applyFilter + */ + Tooltip.prototype.applyFilter = function () { + var chart = this.chart; + chart.renderer.definition({ + tagName: 'filter', + id: 'drop-shadow-' + chart.index, + opacity: 0.5, + children: [{ + tagName: 'feGaussianBlur', + 'in': 'SourceAlpha', + stdDeviation: 1 + }, { + tagName: 'feOffset', + dx: 1, + dy: 1 + }, { + tagName: 'feComponentTransfer', + children: [{ + tagName: 'feFuncA', + type: 'linear', + slope: 0.3 + }] + }, { + tagName: 'feMerge', + children: [{ + tagName: 'feMergeNode' + }, { + tagName: 'feMergeNode', + 'in': 'SourceGraphic' + }] + }] + }); + chart.renderer.definition({ + tagName: 'style', + textContent: '.highcharts-tooltip-' + chart.index + '{' + + 'filter:url(#drop-shadow-' + chart.index + ')' + + '}' + }); + }; + /** + * Build the body (lines) of the tooltip by iterating over the items and + * returning one entry for each item, abstracting this functionality allows + * to easily overwrite and extend it. + * + * @private + * @function Highcharts.Tooltip#bodyFormatter + * @param {Array<(Highcharts.Point|Highcharts.Series)>} items + * @return {Array} + */ + Tooltip.prototype.bodyFormatter = function (items) { + return items.map(function (item) { + var tooltipOptions = item.series.tooltipOptions; + return (tooltipOptions[(item.point.formatPrefix || 'point') + 'Formatter'] || + item.point.tooltipFormatter).call(item.point, tooltipOptions[(item.point.formatPrefix || 'point') + 'Format'] || ''); + }); + }; + /** + * Destroy the single tooltips in a split tooltip. + * If the tooltip is active then it is not destroyed, unless forced to. + * + * @private + * @function Highcharts.Tooltip#cleanSplit + * + * @param {boolean} [force] + * Force destroy all tooltips. + */ + Tooltip.prototype.cleanSplit = function (force) { + this.chart.series.forEach(function (series) { + var tt = series && series.tt; + if (tt) { + if (!tt.isActive || force) { + series.tt = tt.destroy(); + } + else { + tt.isActive = false; + } + } + }); + }; + /** + * In case no user defined formatter is given, this will be used. Note that + * the context here is an object holding point, series, x, y etc. + * + * @function Highcharts.Tooltip#defaultFormatter + * + * @param {Highcharts.Tooltip} tooltip + * + * @return {Array} + */ + Tooltip.prototype.defaultFormatter = function (tooltip) { + var items = this.points || splat(this), s; + // Build the header + s = [tooltip.tooltipFooterHeaderFormatter(items[0])]; + // build the values + s = s.concat(tooltip.bodyFormatter(items)); + // footer + s.push(tooltip.tooltipFooterHeaderFormatter(items[0], true)); + return s; + }; + /** + * Removes and destroys the tooltip and its elements. + * + * @function Highcharts.Tooltip#destroy + */ + Tooltip.prototype.destroy = function () { + // Destroy and clear local variables + if (this.label) { + this.label = this.label.destroy(); + } + if (this.split && this.tt) { + this.cleanSplit(this.chart, true); + this.tt = this.tt.destroy(); + } + if (this.renderer) { + this.renderer = this.renderer.destroy(); + discardElement(this.container); + } + U.clearTimeout(this.hideTimer); + U.clearTimeout(this.tooltipTimeout); + }; + /** + * Extendable method to get the anchor position of the tooltip + * from a point or set of points + * + * @private + * @function Highcharts.Tooltip#getAnchor + * + * @param {Highcharts.Point|Array} points + * + * @param {Highcharts.PointerEventObject} [mouseEvent] + * + * @return {Array} + */ + Tooltip.prototype.getAnchor = function (points, mouseEvent) { + var ret, chart = this.chart, pointer = chart.pointer, inverted = chart.inverted, plotTop = chart.plotTop, plotLeft = chart.plotLeft, plotX = 0, plotY = 0, yAxis, xAxis; + points = splat(points); + // When tooltip follows mouse, relate the position to the mouse + if (this.followPointer && mouseEvent) { + if (typeof mouseEvent.chartX === 'undefined') { + mouseEvent = pointer.normalize(mouseEvent); + } + ret = [ + mouseEvent.chartX - plotLeft, + mouseEvent.chartY - plotTop + ]; + // Some series types use a specificly calculated tooltip position for + // each point + } + else if (points[0].tooltipPos) { + ret = points[0].tooltipPos; + // When shared, use the average position + } + else { + points.forEach(function (point) { + yAxis = point.series.yAxis; + xAxis = point.series.xAxis; + plotX += point.plotX + + (!inverted && xAxis ? xAxis.left - plotLeft : 0); + plotY += (point.plotLow ? + (point.plotLow + point.plotHigh) / 2 : + point.plotY) + (!inverted && yAxis ? yAxis.top - plotTop : 0); // #1151 + }); + plotX /= points.length; + plotY /= points.length; + ret = [ + inverted ? chart.plotWidth - plotY : plotX, + this.shared && !inverted && points.length > 1 && mouseEvent ? + // place shared tooltip next to the mouse (#424) + mouseEvent.chartY - plotTop : + inverted ? chart.plotHeight - plotX : plotY + ]; + } + return ret.map(Math.round); + }; + /** + * Get the optimal date format for a point, based on a range. + * + * @private + * @function Highcharts.Tooltip#getDateFormat + * + * @param {number} range + * The time range + * + * @param {number} date + * The date of the point in question + * + * @param {number} startOfWeek + * An integer representing the first day of the week, where 0 is + * Sunday. + * + * @param {Highcharts.Dictionary} dateTimeLabelFormats + * A map of time units to formats. + * + * @return {string} + * The optimal date format for a point. + */ + Tooltip.prototype.getDateFormat = function (range, date, startOfWeek, dateTimeLabelFormats) { + var time = this.chart.time, dateStr = time.dateFormat('%m-%d %H:%M:%S.%L', date), format, n, blank = '01-01 00:00:00.000', strpos = { + millisecond: 15, + second: 12, + minute: 9, + hour: 6, + day: 3 + }, lastN = 'millisecond'; // for sub-millisecond data, #4223 + for (n in timeUnits) { // eslint-disable-line guard-for-in + // If the range is exactly one week and we're looking at a + // Sunday/Monday, go for the week format + if (range === timeUnits.week && + +time.dateFormat('%w', date) === startOfWeek && + dateStr.substr(6) === blank.substr(6)) { + n = 'week'; + break; + } + // The first format that is too great for the range + if (timeUnits[n] > range) { + n = lastN; + break; + } + // If the point is placed every day at 23:59, we need to show + // the minutes as well. #2637. + if (strpos[n] && + dateStr.substr(strpos[n]) !== blank.substr(strpos[n])) { + break; + } + // Weeks are outside the hierarchy, only apply them on + // Mondays/Sundays like in the first condition + if (n !== 'week') { + lastN = n; + } + } + if (n) { + format = time.resolveDTLFormat(dateTimeLabelFormats[n]).main; + } + return format; + }; + /** + * Creates the Tooltip label element if it does not exist, then returns it. + * + * @function Highcharts.Tooltip#getLabel + * @return {Highcharts.SVGElement} + */ + Tooltip.prototype.getLabel = function () { + var _a, _b; + var tooltip = this, renderer = this.chart.renderer, styledMode = this.chart.styledMode, options = this.options, className = ('tooltip' + (defined(options.className) ? + ' ' + options.className : + '')), pointerEvents = (((_a = options.style) === null || _a === void 0 ? void 0 : _a.pointerEvents) || + (!this.followPointer && options.stickOnContact ? 'auto' : 'none')), container, set, onMouseEnter = function () { + tooltip.inContact = true; + }, onMouseLeave = function () { + var series = tooltip.chart.hoverSeries; + tooltip.inContact = false; + if (series && + series.onMouseOut) { + series.onMouseOut(); + } + }; + if (!this.label) { + if (this.outside) { + /** + * Reference to the tooltip's container, when + * [Highcharts.Tooltip#outside] is set to true, otherwise + * it's undefined. + * + * @name Highcharts.Tooltip#container + * @type {Highcharts.HTMLDOMElement|undefined} + */ + this.container = container = H.doc.createElement('div'); + container.className = 'highcharts-tooltip-container'; + css(container, { + position: 'absolute', + top: '1px', + pointerEvents: pointerEvents, + zIndex: 3 + }); + H.doc.body.appendChild(container); + /** + * Reference to the tooltip's renderer, when + * [Highcharts.Tooltip#outside] is set to true, otherwise + * it's undefined. + * + * @name Highcharts.Tooltip#renderer + * @type {Highcharts.SVGRenderer|undefined} + */ + this.renderer = renderer = new H.Renderer(container, 0, 0, (_b = this.chart.options.chart) === null || _b === void 0 ? void 0 : _b.style, void 0, void 0, renderer.styledMode); + } + // Create the label + if (this.split) { + this.label = renderer.g(className); + } + else { + this.label = renderer + .label('', 0, 0, options.shape || 'callout', null, null, options.useHTML, null, className) + .attr({ + padding: options.padding, + r: options.borderRadius + }); + if (!styledMode) { + this.label + .attr({ + fill: options.backgroundColor, + 'stroke-width': options.borderWidth + }) + // #2301, #2657 + .css(options.style) + .css({ pointerEvents: pointerEvents }) + .shadow(options.shadow); + } + } + if (styledMode) { + // Apply the drop-shadow filter + this.applyFilter(); + this.label.addClass('highcharts-tooltip-' + this.chart.index); + } + // Split tooltip use updateTooltipContainer to position the tooltip + // container. + if (tooltip.outside && !tooltip.split) { + set = { + x: this.label.xSetter, + y: this.label.ySetter + }; + this.label.xSetter = function (value, key) { + set[key].call(this.label, tooltip.distance); + container.style.left = value + 'px'; + }; + this.label.ySetter = function (value, key) { + set[key].call(this.label, tooltip.distance); + container.style.top = value + 'px'; + }; + } + this.label + .on('mouseenter', onMouseEnter) + .on('mouseleave', onMouseLeave) + .attr({ zIndex: 8 }) + .add(); + } + return this.label; + }; + /** + * Place the tooltip in a chart without spilling over + * and not covering the point it self. + * + * @private + * @function Highcharts.Tooltip#getPosition + * + * @param {number} boxWidth + * + * @param {number} boxHeight + * + * @param {Highcharts.Point} point + * + * @return {Highcharts.PositionObject} + */ + Tooltip.prototype.getPosition = function (boxWidth, boxHeight, point) { + var chart = this.chart, distance = this.distance, ret = {}, + // Don't use h if chart isn't inverted (#7242) ??? + h = (chart.inverted && point.h) || 0, // #4117 ??? + swapped, outside = this.outside, outerWidth = outside ? + // substract distance to prevent scrollbars + doc.documentElement.clientWidth - 2 * distance : + chart.chartWidth, outerHeight = outside ? + Math.max(doc.body.scrollHeight, doc.documentElement.scrollHeight, doc.body.offsetHeight, doc.documentElement.offsetHeight, doc.documentElement.clientHeight) : + chart.chartHeight, chartPosition = chart.pointer.getChartPosition(), containerScaling = chart.containerScaling, scaleX = function (val) { return ( // eslint-disable-line no-confusing-arrow + containerScaling ? val * containerScaling.scaleX : val); }, scaleY = function (val) { return ( // eslint-disable-line no-confusing-arrow + containerScaling ? val * containerScaling.scaleY : val); }, + // Build parameter arrays for firstDimension()/secondDimension() + buildDimensionArray = function (dim) { + var isX = dim === 'x'; + return [ + dim, + isX ? outerWidth : outerHeight, + isX ? boxWidth : boxHeight + ].concat(outside ? [ + // If we are using tooltip.outside, we need to scale the + // position to match scaling of the container in case there + // is a transform/zoom on the container. #11329 + isX ? scaleX(boxWidth) : scaleY(boxHeight), + isX ? chartPosition.left - distance + + scaleX(point.plotX + chart.plotLeft) : + chartPosition.top - distance + + scaleY(point.plotY + chart.plotTop), + 0, + isX ? outerWidth : outerHeight + ] : [ + // Not outside, no scaling is needed + isX ? boxWidth : boxHeight, + isX ? point.plotX + chart.plotLeft : + point.plotY + chart.plotTop, + isX ? chart.plotLeft : chart.plotTop, + isX ? chart.plotLeft + chart.plotWidth : + chart.plotTop + chart.plotHeight + ]); + }, first = buildDimensionArray('y'), second = buildDimensionArray('x'), + // The far side is right or bottom + preferFarSide = !this.followPointer && pick(point.ttBelow, !chart.inverted === !!point.negative), // #4984 + /* + * Handle the preferred dimension. When the preferred dimension is + * tooltip on top or bottom of the point, it will look for space + * there. + * + * @private + */ + firstDimension = function (dim, outerSize, innerSize, scaledInnerSize, // #11329 + point, min, max) { + var scaledDist = dim === 'y' ? + scaleY(distance) : scaleX(distance), scaleDiff = (innerSize - scaledInnerSize) / 2, roomLeft = scaledInnerSize < point - distance, roomRight = point + distance + scaledInnerSize < outerSize, alignedLeft = point - scaledDist - innerSize + scaleDiff, alignedRight = point + scaledDist - scaleDiff; + if (preferFarSide && roomRight) { + ret[dim] = alignedRight; + } + else if (!preferFarSide && roomLeft) { + ret[dim] = alignedLeft; + } + else if (roomLeft) { + ret[dim] = Math.min(max - scaledInnerSize, alignedLeft - h < 0 ? alignedLeft : alignedLeft - h); + } + else if (roomRight) { + ret[dim] = Math.max(min, alignedRight + h + innerSize > outerSize ? + alignedRight : + alignedRight + h); + } + else { + return false; + } + }, + /* + * Handle the secondary dimension. If the preferred dimension is + * tooltip on top or bottom of the point, the second dimension is to + * align the tooltip above the point, trying to align center but + * allowing left or right align within the chart box. + * + * @private + */ + secondDimension = function (dim, outerSize, innerSize, scaledInnerSize, // #11329 + point) { + var retVal; + // Too close to the edge, return false and swap dimensions + if (point < distance || point > outerSize - distance) { + retVal = false; + // Align left/top + } + else if (point < innerSize / 2) { + ret[dim] = 1; + // Align right/bottom + } + else if (point > outerSize - scaledInnerSize / 2) { + ret[dim] = outerSize - scaledInnerSize - 2; + // Align center + } + else { + ret[dim] = point - innerSize / 2; + } + return retVal; + }, + /* + * Swap the dimensions + */ + swap = function (count) { + var temp = first; + first = second; + second = temp; + swapped = count; + }, run = function () { + if (firstDimension.apply(0, first) !== false) { + if (secondDimension.apply(0, second) === false && + !swapped) { + swap(true); + run(); + } + } + else if (!swapped) { + swap(true); + run(); + } + else { + ret.x = ret.y = 0; + } + }; + // Under these conditions, prefer the tooltip on the side of the point + if (chart.inverted || this.len > 1) { + swap(); + } + run(); + return ret; + }; + /** + * Get the best X date format based on the closest point range on the axis. + * + * @private + * @function Highcharts.Tooltip#getXDateFormat + * + * @param {Highcharts.Point} point + * + * @param {Highcharts.TooltipOptions} options + * + * @param {Highcharts.Axis} xAxis + * + * @return {string} + */ + Tooltip.prototype.getXDateFormat = function (point, options, xAxis) { + var xDateFormat, dateTimeLabelFormats = options.dateTimeLabelFormats, closestPointRange = xAxis && xAxis.closestPointRange; + if (closestPointRange) { + xDateFormat = this.getDateFormat(closestPointRange, point.x, xAxis.options.startOfWeek, dateTimeLabelFormats); + } + else { + xDateFormat = dateTimeLabelFormats.day; + } + return xDateFormat || dateTimeLabelFormats.year; // #2546, 2581 + }; + /** + * Hides the tooltip with a fade out animation. + * + * @function Highcharts.Tooltip#hide + * + * @param {number} [delay] + * The fade out in milliseconds. If no value is provided the value + * of the tooltip.hideDelay option is used. A value of 0 disables + * the fade out animation. + */ + Tooltip.prototype.hide = function (delay) { + var tooltip = this; + // disallow duplicate timers (#1728, #1766) + U.clearTimeout(this.hideTimer); + delay = pick(delay, this.options.hideDelay, 500); + if (!this.isHidden) { + this.hideTimer = syncTimeout(function () { + // If there is a delay, do fadeOut with the default duration. If + // the hideDelay is 0, we assume no animation is wanted, so we + // pass 0 duration. #12994. + tooltip.getLabel().fadeOut(delay ? void 0 : delay); + tooltip.isHidden = true; + }, delay); + } + }; + /** + * @private + * @function Highcharts.Tooltip#init + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @param {Highcharts.TooltipOptions} options + * Tooltip options. + */ + Tooltip.prototype.init = function (chart, options) { + /** + * Chart of the tooltip. + * + * @readonly + * @name Highcharts.Tooltip#chart + * @type {Highcharts.Chart} + */ + this.chart = chart; + /** + * Used tooltip options. + * + * @readonly + * @name Highcharts.Tooltip#options + * @type {Highcharts.TooltipOptions} + */ + this.options = options; + /** + * List of crosshairs. + * + * @private + * @readonly + * @name Highcharts.Tooltip#crosshairs + * @type {Array} + */ + this.crosshairs = []; + /** + * Current values of x and y when animating. + * + * @private + * @readonly + * @name Highcharts.Tooltip#now + * @type {Highcharts.PositionObject} + */ + this.now = { x: 0, y: 0 }; + /** + * Tooltips are initially hidden. + * + * @private + * @readonly + * @name Highcharts.Tooltip#isHidden + * @type {boolean} + */ + this.isHidden = true; + /** + * True, if the tooltip is split into one label per series, with the + * header close to the axis. + * + * @readonly + * @name Highcharts.Tooltip#split + * @type {boolean|undefined} + */ + this.split = options.split && !chart.inverted && !chart.polar; + /** + * When the tooltip is shared, the entire plot area will capture mouse + * movement or touch events. + * + * @readonly + * @name Highcharts.Tooltip#shared + * @type {boolean|undefined} + */ + this.shared = options.shared || this.split; + /** + * Whether to allow the tooltip to render outside the chart's SVG + * element box. By default (false), the tooltip is rendered within the + * chart's SVG element, which results in the tooltip being aligned + * inside the chart area. + * + * @readonly + * @name Highcharts.Tooltip#outside + * @type {boolean} + * + * @todo + * Split tooltip does not support outside in the first iteration. Should + * not be too complicated to implement. + */ + this.outside = pick(options.outside, Boolean(chart.scrollablePixelsX || chart.scrollablePixelsY)); + }; + /** + * Returns true, if the pointer is in contact with the tooltip tracker. + */ + Tooltip.prototype.isStickyOnContact = function () { + return !!(!this.followPointer && + this.options.stickOnContact && + this.inContact); + }; + /** + * Moves the tooltip with a soft animation to a new position. + * + * @private + * @function Highcharts.Tooltip#move + * + * @param {number} x + * + * @param {number} y + * + * @param {number} anchorX + * + * @param {number} anchorY + */ + Tooltip.prototype.move = function (x, y, anchorX, anchorY) { + var tooltip = this, now = tooltip.now, animate = tooltip.options.animation !== false && + !tooltip.isHidden && + // When we get close to the target position, abort animation and + // land on the right place (#3056) + (Math.abs(x - now.x) > 1 || Math.abs(y - now.y) > 1), skipAnchor = tooltip.followPointer || tooltip.len > 1; + // Get intermediate values for animation + extend(now, { + x: animate ? (2 * now.x + x) / 3 : x, + y: animate ? (now.y + y) / 2 : y, + anchorX: skipAnchor ? + void 0 : + animate ? (2 * now.anchorX + anchorX) / 3 : anchorX, + anchorY: skipAnchor ? + void 0 : + animate ? (now.anchorY + anchorY) / 2 : anchorY + }); + // Move to the intermediate value + tooltip.getLabel().attr(now); + tooltip.drawTracker(); + // Run on next tick of the mouse tracker + if (animate) { + // Never allow two timeouts + U.clearTimeout(this.tooltipTimeout); + // Set the fixed interval ticking for the smooth tooltip + this.tooltipTimeout = setTimeout(function () { + // The interval function may still be running during destroy, + // so check that the chart is really there before calling. + if (tooltip) { + tooltip.move(x, y, anchorX, anchorY); + } + }, 32); + } + }; + /** + * Refresh the tooltip's text and position. + * + * @function Highcharts.Tooltip#refresh + * + * @param {Highcharts.Point|Array} pointOrPoints + * Either a point or an array of points. + * + * @param {Highcharts.PointerEventObject} [mouseEvent] + * Mouse event, that is responsible for the refresh and should be + * used for the tooltip update. + */ + Tooltip.prototype.refresh = function (pointOrPoints, mouseEvent) { + var tooltip = this, chart = this.chart, options = tooltip.options, x, y, point = pointOrPoints, anchor, textConfig = {}, text, pointConfig = [], formatter = options.formatter || tooltip.defaultFormatter, shared = tooltip.shared, currentSeries, styledMode = chart.styledMode; + if (!options.enabled) { + return; + } + U.clearTimeout(this.hideTimer); + // get the reference point coordinates (pie charts use tooltipPos) + tooltip.followPointer = splat(point)[0].series.tooltipOptions + .followPointer; + anchor = tooltip.getAnchor(point, mouseEvent); + x = anchor[0]; + y = anchor[1]; + // shared tooltip, array is sent over + if (shared && + !(point.series && + point.series.noSharedTooltip)) { + chart.pointer.applyInactiveState(point); + // Now set hover state for the choosen ones: + point.forEach(function (item) { + item.setState('hover'); + pointConfig.push(item.getLabelConfig()); + }); + textConfig = { + x: point[0].category, + y: point[0].y + }; + textConfig.points = pointConfig; + point = point[0]; + // single point tooltip + } + else { + textConfig = point.getLabelConfig(); + } + this.len = pointConfig.length; // #6128 + text = formatter.call(textConfig, tooltip); + // register the current series + currentSeries = point.series; + this.distance = pick(currentSeries.tooltipOptions.distance, 16); + // update the inner HTML + if (text === false) { + this.hide(); + } + else { + // update text + if (tooltip.split) { + this.renderSplit(text, splat(pointOrPoints)); + } + else { + var label = tooltip.getLabel(); + // Prevent the tooltip from flowing over the chart box (#6659) + if (!options.style.width || styledMode) { + label.css({ + width: this.chart.spacingBox.width + 'px' + }); + } + label.attr({ + text: text && text.join ? + text.join('') : + text + }); + // Set the stroke color of the box to reflect the point + label.removeClass(/highcharts-color-[\d]+/g) + .addClass('highcharts-color-' + + pick(point.colorIndex, currentSeries.colorIndex)); + if (!styledMode) { + label.attr({ + stroke: (options.borderColor || + point.color || + currentSeries.color || + '#666666') + }); + } + tooltip.updatePosition({ + plotX: x, + plotY: y, + negative: point.negative, + ttBelow: point.ttBelow, + h: anchor[2] || 0 + }); + } + // show it + if (tooltip.isHidden && tooltip.label) { + tooltip.label.attr({ + opacity: 1 + }).show(); + } + tooltip.isHidden = false; + } + fireEvent(this, 'refresh'); + }; + /** + * Render the split tooltip. Loops over each point's text and adds + * a label next to the point, then uses the distribute function to + * find best non-overlapping positions. + * + * @private + * @function Highcharts.Tooltip#renderSplit + * + * @param {string|Array<(boolean|string)>} labels + * + * @param {Array} points + */ + Tooltip.prototype.renderSplit = function (labels, points) { + var tooltip = this; + var chart = tooltip.chart, _a = tooltip.chart, chartWidth = _a.chartWidth, chartHeight = _a.chartHeight, plotHeight = _a.plotHeight, plotLeft = _a.plotLeft, plotTop = _a.plotTop, pointer = _a.pointer, ren = _a.renderer, _b = _a.scrollablePixelsY, scrollablePixelsY = _b === void 0 ? 0 : _b, _c = _a.scrollingContainer, _d = _c === void 0 ? { scrollLeft: 0, scrollTop: 0 } : _c, scrollLeft = _d.scrollLeft, scrollTop = _d.scrollTop, styledMode = _a.styledMode, distance = tooltip.distance, options = tooltip.options, positioner = tooltip.options.positioner; + // The area which the tooltip should be limited to. Limit to scrollable + // plot area if enabled, otherwise limit to the chart container. + var bounds = { + left: scrollLeft, + right: scrollLeft + chartWidth, + top: scrollTop, + bottom: scrollTop + chartHeight + }; + var tooltipLabel = tooltip.getLabel(); + var headerTop = Boolean(chart.xAxis[0] && chart.xAxis[0].opposite); + var distributionBoxTop = plotTop + scrollTop; + var headerHeight = 0; + var adjustedPlotHeight = plotHeight - scrollablePixelsY; + /** + * Calculates the anchor position for the partial tooltip + * + * @private + * @param {Highcharts.Point} point The point related to the tooltip + * @return {object} Returns an object with anchorX and anchorY + */ + function getAnchor(point) { + var isHeader = point.isHeader, _a = point.plotX, plotX = _a === void 0 ? 0 : _a, _b = point.plotY, plotY = _b === void 0 ? 0 : _b, series = point.series; + var anchorX; + var anchorY; + if (isHeader) { + // Set anchorX to plotX + anchorX = plotLeft + plotX; + // Set anchorY to center of visible plot area. + anchorY = plotTop + plotHeight / 2; + } + else { + var xAxis = series.xAxis, yAxis = series.yAxis; + // Set anchorX to plotX. Limit to within xAxis. + anchorX = xAxis.pos + clamp(plotX, -distance, xAxis.len + distance); + // Set anchorY, limit to the scrollable plot area + if (yAxis.pos + plotY >= scrollTop + plotTop && + yAxis.pos + plotY <= scrollTop + plotTop + plotHeight - scrollablePixelsY) { + anchorY = yAxis.pos + plotY; + } + } + // Limit values to plot area + anchorX = clamp(anchorX, bounds.left - distance, bounds.right + distance); + return { anchorX: anchorX, anchorY: anchorY }; + } + /** + * Calculates the position of the partial tooltip + * + * @private + * @param {number} anchorX The partial tooltip anchor x position + * @param {number} anchorY The partial tooltip anchor y position + * @param {boolean} isHeader Whether the partial tooltip is a header + * @param {number} boxWidth Width of the partial tooltip + * @return {Highcharts.PositionObject} Returns the partial tooltip x and + * y position + */ + function defaultPositioner(anchorX, anchorY, isHeader, boxWidth, alignedLeft) { + if (alignedLeft === void 0) { alignedLeft = true; } + var y; + var x; + if (isHeader) { + y = headerTop ? 0 : adjustedPlotHeight; + x = clamp(anchorX - (boxWidth / 2), bounds.left, bounds.right - boxWidth); + } + else { + y = anchorY - distributionBoxTop; + x = alignedLeft ? + anchorX - boxWidth - distance : + anchorX + distance; + x = clamp(x, alignedLeft ? x : bounds.left, bounds.right); + } + // NOTE: y is relative to distributionBoxTop + return { x: x, y: y }; + } + /** + * Updates the attributes and styling of the partial tooltip. Creates a + * new partial tooltip if it does not exists. + * + * @private + * @param {Highcharts.SVGElement|undefined} partialTooltip + * The partial tooltip to update + * @param {Highcharts.Point} point + * The point related to the partial tooltip + * @param {boolean|string} str The text for the partial tooltip + * @return {Highcharts.SVGElement} Returns the updated partial tooltip + */ + function updatePartialTooltip(partialTooltip, point, str) { + var tt = partialTooltip; + var isHeader = point.isHeader, series = point.series; + var colorClass = 'highcharts-color-' + pick(point.colorIndex, series.colorIndex, 'none'); + if (!tt) { + var attribs = { + padding: options.padding, + r: options.borderRadius + }; + if (!styledMode) { + attribs.fill = options.backgroundColor; + attribs['stroke-width'] = options.borderWidth; + } + tt = ren + .label('', 0, 0, (options[isHeader ? 'headerShape' : 'shape']) || + 'callout', void 0, void 0, options.useHTML) + .addClass((isHeader ? 'highcharts-tooltip-header ' : '') + + 'highcharts-tooltip-box ' + + colorClass) + .attr(attribs) + .add(tooltipLabel); + } + tt.isActive = true; + tt.attr({ + text: str + }); + if (!styledMode) { + tt.css(options.style) + .shadow(options.shadow) + .attr({ + stroke: (options.borderColor || + point.color || + series.color || + '#333333') + }); + } + return tt; + } + // Graceful degradation for legacy formatters + if (isString(labels)) { + labels = [false, labels]; + } + // Create the individual labels for header and points, ignore footer + var boxes = labels.slice(0, points.length + 1).reduce(function (boxes, str, i) { + if (str !== false && str !== '') { + var point = points[i - 1] || { + // Item 0 is the header. Instead of this, we could also + // use the crosshair label + isHeader: true, + plotX: points[0].plotX, + plotY: plotHeight, + series: {} + }; + var isHeader = point.isHeader; + // Store the tooltip label referance on the series + var owner = isHeader ? tooltip : point.series; + var tt = owner.tt = updatePartialTooltip(owner.tt, point, str); + // Get X position now, so we can move all to the other side in + // case of overflow + var bBox = tt.getBBox(); + var boxWidth = bBox.width + tt.strokeWidth(); + if (isHeader) { + headerHeight = bBox.height; + adjustedPlotHeight += headerHeight; + if (headerTop) { + distributionBoxTop -= headerHeight; + } + } + var _a = getAnchor(point), anchorX = _a.anchorX, anchorY = _a.anchorY; + if (typeof anchorY === 'number') { + var size = bBox.height + 1; + var boxPosition = positioner ? positioner.call(tooltip, boxWidth, size, point) : defaultPositioner(anchorX, anchorY, isHeader, boxWidth); + boxes.push({ + // 0-align to the top, 1-align to the bottom + align: positioner ? 0 : void 0, + anchorX: anchorX, + anchorY: anchorY, + boxWidth: boxWidth, + point: point, + rank: pick(boxPosition.rank, isHeader ? 1 : 0), + size: size, + target: boxPosition.y, + tt: tt, + x: boxPosition.x + }); + } + else { + // Hide tooltips which anchorY is outside the visible plot + // area + tt.isActive = false; + } + } + return boxes; + }, []); + // If overflow left then align all labels to the right + if (!positioner && boxes.some(function (box) { return box.x < bounds.left; })) { + boxes = boxes.map(function (box) { + var _a = defaultPositioner(box.anchorX, box.anchorY, box.point.isHeader, box.boxWidth, false), x = _a.x, y = _a.y; + return extend(box, { + target: y, + x: x + }); + }); + } + // Clean previous run (for missing points) + tooltip.cleanSplit(); + // Distribute and put in place + H.distribute(boxes, adjustedPlotHeight); + boxes.forEach(function (box) { + var anchorX = box.anchorX, anchorY = box.anchorY, pos = box.pos, x = box.x; + // Put the label in place + box.tt.attr({ + visibility: typeof pos === 'undefined' ? 'hidden' : 'inherit', + x: x, + /* NOTE: y should equal pos to be consistent with !split + * tooltip, but is currently relative to plotTop. Is left as is + * to avoid breaking change. Remove distributionBoxTop to make + * it consistent. + */ + y: pos + distributionBoxTop, + anchorX: anchorX, + anchorY: anchorY + }); + }); + /* If we have a seperate tooltip container, then update the necessary + * container properties. + * Test that tooltip has its own container and renderer before executing + * the operation. + */ + var container = tooltip.container, outside = tooltip.outside, renderer = tooltip.renderer; + if (outside && container && renderer) { + // Set container size to fit the tooltip + var _e = tooltipLabel.getBBox(), width = _e.width, height = _e.height, x = _e.x, y = _e.y; + renderer.setSize(width + x, height + y, false); + // Position the tooltip container to the chart container + var chartPosition = pointer.getChartPosition(); + container.style.left = chartPosition.left + 'px'; + container.style.top = chartPosition.top + 'px'; + } + }; + /** + * If the `stickOnContact` option is active, this will add a tracker shape. + * + * @private + * @function Highcharts.Tooltip#drawTracker + */ + Tooltip.prototype.drawTracker = function () { + var tooltip = this; + if (tooltip.followPointer || + !tooltip.options.stickOnContact) { + if (tooltip.tracker) { + tooltip.tracker.destroy(); + } + return; + } + var chart = tooltip.chart; + var label = tooltip.label; + var point = chart.hoverPoint; + if (!label || !point) { + return; + } + var box = { + x: 0, + y: 0, + width: 0, + height: 0 + }; + // Combine anchor and tooltip + var anchorPos = this.getAnchor(point); + var labelBBox = label.getBBox(); + anchorPos[0] += chart.plotLeft - label.translateX; + anchorPos[1] += chart.plotTop - label.translateY; + // When the mouse pointer is between the anchor point and the label, + // the label should stick. + box.x = Math.min(0, anchorPos[0]); + box.y = Math.min(0, anchorPos[1]); + box.width = (anchorPos[0] < 0 ? + Math.max(Math.abs(anchorPos[0]), (labelBBox.width - anchorPos[0])) : + Math.max(Math.abs(anchorPos[0]), labelBBox.width)); + box.height = (anchorPos[1] < 0 ? + Math.max(Math.abs(anchorPos[1]), (labelBBox.height - Math.abs(anchorPos[1]))) : + Math.max(Math.abs(anchorPos[1]), labelBBox.height)); + if (tooltip.tracker) { + tooltip.tracker.attr(box); + } + else { + tooltip.tracker = label.renderer + .rect(box) + .addClass('highcharts-tracker') + .add(label); + if (!chart.styledMode) { + tooltip.tracker.attr({ + fill: 'rgba(0,0,0,0)' + }); + } + } + }; + /** + * @private + */ + Tooltip.prototype.styledModeFormat = function (formatString) { + return formatString + .replace('style="font-size: 10px"', 'class="highcharts-header"') + .replace(/style="color:{(point|series)\.color}"/g, 'class="highcharts-color-{$1.colorIndex}"'); + }; + /** + * Format the footer/header of the tooltip + * #3397: abstraction to enable formatting of footer and header + * + * @private + * @function Highcharts.Tooltip#tooltipFooterHeaderFormatter + * @param {Highcharts.PointLabelObject} labelConfig + * @param {boolean} [isFooter] + * @return {string} + */ + Tooltip.prototype.tooltipFooterHeaderFormatter = function (labelConfig, isFooter) { + var footOrHead = isFooter ? 'footer' : 'header', series = labelConfig.series, tooltipOptions = series.tooltipOptions, xDateFormat = tooltipOptions.xDateFormat, xAxis = series.xAxis, isDateTime = (xAxis && + xAxis.options.type === 'datetime' && + isNumber(labelConfig.key)), formatString = tooltipOptions[footOrHead + 'Format'], e = { + isFooter: isFooter, + labelConfig: labelConfig + }; + fireEvent(this, 'headerFormatter', e, function (e) { + // Guess the best date format based on the closest point distance + // (#568, #3418) + if (isDateTime && !xDateFormat) { + xDateFormat = this.getXDateFormat(labelConfig, tooltipOptions, xAxis); + } + // Insert the footer date format if any + if (isDateTime && xDateFormat) { + ((labelConfig.point && labelConfig.point.tooltipDateKeys) || + ['key']).forEach(function (key) { + formatString = formatString.replace('{point.' + key + '}', '{point.' + key + ':' + xDateFormat + '}'); + }); + } + // Replace default header style with class name + if (series.chart.styledMode) { + formatString = this.styledModeFormat(formatString); + } + e.text = format(formatString, { + point: labelConfig, + series: series + }, this.chart); + }); + return e.text; + }; + /** + * Updates the tooltip with the provided tooltip options. + * + * @function Highcharts.Tooltip#update + * + * @param {Highcharts.TooltipOptions} options + * The tooltip options to update. + */ + Tooltip.prototype.update = function (options) { + this.destroy(); + // Update user options (#6218) + merge(true, this.chart.options.tooltip.userOptions, options); + this.init(this.chart, merge(true, this.options, options)); + }; + /** + * Find the new position and perform the move + * + * @private + * @function Highcharts.Tooltip#updatePosition + * + * @param {Highcharts.Point} point + */ + Tooltip.prototype.updatePosition = function (point) { + var chart = this.chart, pointer = chart.pointer, label = this.getLabel(), pos, anchorX = point.plotX + chart.plotLeft, anchorY = point.plotY + chart.plotTop, pad; + // Needed for outside: true (#11688) + var chartPosition = pointer.getChartPosition(); + pos = (this.options.positioner || this.getPosition).call(this, label.width, label.height, point); + // Set the renderer size dynamically to prevent document size to change + if (this.outside) { + pad = (this.options.borderWidth || 0) + 2 * this.distance; + this.renderer.setSize(label.width + pad, label.height + pad, false); + // Anchor and tooltip container need scaling if chart container has + // scale transform/css zoom. #11329. + var containerScaling = chart.containerScaling; + if (containerScaling) { + css(this.container, { + transform: "scale(" + containerScaling.scaleX + ", " + containerScaling.scaleY + ")" + }); + anchorX *= containerScaling.scaleX; + anchorY *= containerScaling.scaleY; + } + anchorX += chartPosition.left - pos.x; + anchorY += chartPosition.top - pos.y; + } + // do the move + this.move(Math.round(pos.x), Math.round(pos.y || 0), // can be undefined (#3977) + anchorX, anchorY); + }; + return Tooltip; + }()); + H.Tooltip = Tooltip; + + return H.Tooltip; + }); + _registerModule(_modules, 'parts/Pointer.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['parts/Tooltip.js'], _modules['parts/Color.js']], function (Highcharts, U, Tooltip, Color) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * One position in relation to an axis. + * + * @interface Highcharts.PointerAxisCoordinateObject + */ /** + * Related axis. + * + * @name Highcharts.PointerAxisCoordinateObject#axis + * @type {Highcharts.Axis} + */ /** + * Axis value. + * + * @name Highcharts.PointerAxisCoordinateObject#value + * @type {number} + */ + /** + * Positions in terms of axis values. + * + * @interface Highcharts.PointerAxisCoordinatesObject + */ /** + * Positions on the x-axis. + * @name Highcharts.PointerAxisCoordinatesObject#xAxis + * @type {Array} + */ /** + * Positions on the y-axis. + * @name Highcharts.PointerAxisCoordinatesObject#yAxis + * @type {Array} + */ + /** + * Pointer coordinates. + * + * @interface Highcharts.PointerCoordinatesObject + */ /** + * @name Highcharts.PointerCoordinatesObject#chartX + * @type {number} + */ /** + * @name Highcharts.PointerCoordinatesObject#chartY + * @type {number} + */ + /** + * A native browser mouse or touch event, extended with position information + * relative to the {@link Chart.container}. + * + * @interface Highcharts.PointerEventObject + * @extends global.PointerEvent + */ /** + * The X coordinate of the pointer interaction relative to the chart. + * + * @name Highcharts.PointerEventObject#chartX + * @type {number} + */ /** + * The Y coordinate of the pointer interaction relative to the chart. + * + * @name Highcharts.PointerEventObject#chartY + * @type {number} + */ + /** + * Axis-specific data of a selection. + * + * @interface Highcharts.SelectDataObject + */ /** + * @name Highcharts.SelectDataObject#axis + * @type {Highcharts.Axis} + */ /** + * @name Highcharts.SelectDataObject#max + * @type {number} + */ /** + * @name Highcharts.SelectDataObject#min + * @type {number} + */ + /** + * Object for select events. + * + * @interface Highcharts.SelectEventObject + */ /** + * @name Highcharts.SelectEventObject#originalEvent + * @type {global.Event} + */ /** + * @name Highcharts.SelectEventObject#xAxis + * @type {Array} + */ /** + * @name Highcharts.SelectEventObject#yAxis + * @type {Array} + */ + var addEvent = U.addEvent, attr = U.attr, css = U.css, defined = U.defined, extend = U.extend, find = U.find, fireEvent = U.fireEvent, isNumber = U.isNumber, isObject = U.isObject, objectEach = U.objectEach, offset = U.offset, pick = U.pick, splat = U.splat; + var color = Color.parse; + var H = Highcharts, charts = H.charts, noop = H.noop; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The mouse and touch tracker object. Each {@link Chart} item has one + * assosiated Pointer item that can be accessed from the {@link Chart.pointer} + * property. + * + * @class + * @name Highcharts.Pointer + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @param {Highcharts.Options} options + * The root options object. The pointer uses options from the chart and + * tooltip structures. + */ + var Pointer = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Pointer(chart, options) { + this.lastValidTouch = {}; + this.pinchDown = []; + this.runChartClick = false; + this.chart = chart; + this.hasDragged = false; + this.options = options; + this.unbindContainerMouseLeave = function () { }; + this.init(chart, options); + } + /* * + * + * Functions + * + * */ + /** + * Set inactive state to all series that are not currently hovered, + * or, if `inactiveOtherPoints` is set to true, set inactive state to + * all points within that series. + * + * @function Highcharts.Pointer#applyInactiveState + * + * @private + * + * @param {Array} points + * Currently hovered points + * + */ + Pointer.prototype.applyInactiveState = function (points) { + var activeSeries = [], series; + // Get all active series from the hovered points + (points || []).forEach(function (item) { + series = item.series; + // Include itself + activeSeries.push(series); + // Include parent series + if (series.linkedParent) { + activeSeries.push(series.linkedParent); + } + // Include all child series + if (series.linkedSeries) { + activeSeries = activeSeries.concat(series.linkedSeries); + } + // Include navigator series + if (series.navigatorSeries) { + activeSeries.push(series.navigatorSeries); + } + }); + // Now loop over all series, filtering out active series + this.chart.series.forEach(function (inactiveSeries) { + if (activeSeries.indexOf(inactiveSeries) === -1) { + // Inactive series + inactiveSeries.setState('inactive', true); + } + else if (inactiveSeries.options.inactiveOtherPoints) { + // Active series, but other points should be inactivated + inactiveSeries.setAllPointsToState('inactive'); + } + }); + }; + /** + * Destroys the Pointer object and disconnects DOM events. + * + * @function Highcharts.Pointer#destroy + * + * @return {void} + */ + Pointer.prototype.destroy = function () { + var pointer = this; + if (typeof pointer.unDocMouseMove !== 'undefined') { + pointer.unDocMouseMove(); + } + this.unbindContainerMouseLeave(); + if (!H.chartCount) { + if (H.unbindDocumentMouseUp) { + H.unbindDocumentMouseUp = H.unbindDocumentMouseUp(); + } + if (H.unbindDocumentTouchEnd) { + H.unbindDocumentTouchEnd = H.unbindDocumentTouchEnd(); + } + } + // memory and CPU leak + clearInterval(pointer.tooltipTimeout); + objectEach(pointer, function (val, prop) { + pointer[prop] = null; + }); + }; + /** + * Perform a drag operation in response to a mousemove event while the mouse + * is down. + * + * @private + * @function Highcharts.Pointer#drag + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + Pointer.prototype.drag = function (e) { + var chart = this.chart, chartOptions = chart.options.chart, chartX = e.chartX, chartY = e.chartY, zoomHor = this.zoomHor, zoomVert = this.zoomVert, plotLeft = chart.plotLeft, plotTop = chart.plotTop, plotWidth = chart.plotWidth, plotHeight = chart.plotHeight, clickedInside, size, selectionMarker = this.selectionMarker, mouseDownX = (this.mouseDownX || 0), mouseDownY = (this.mouseDownY || 0), panningEnabled = isObject(chartOptions.panning) ? + chartOptions.panning && chartOptions.panning.enabled : + chartOptions.panning, panKey = (chartOptions.panKey && e[chartOptions.panKey + 'Key']); + // If the device supports both touch and mouse (like IE11), and we are + // touch-dragging inside the plot area, don't handle the mouse event. + // #4339. + if (selectionMarker && selectionMarker.touch) { + return; + } + // If the mouse is outside the plot area, adjust to cooordinates + // inside to prevent the selection marker from going outside + if (chartX < plotLeft) { + chartX = plotLeft; + } + else if (chartX > plotLeft + plotWidth) { + chartX = plotLeft + plotWidth; + } + if (chartY < plotTop) { + chartY = plotTop; + } + else if (chartY > plotTop + plotHeight) { + chartY = plotTop + plotHeight; + } + // determine if the mouse has moved more than 10px + this.hasDragged = Math.sqrt(Math.pow(mouseDownX - chartX, 2) + + Math.pow(mouseDownY - chartY, 2)); + if (this.hasDragged > 10) { + clickedInside = chart.isInsidePlot(mouseDownX - plotLeft, mouseDownY - plotTop); + // make a selection + if (chart.hasCartesianSeries && + (this.zoomX || this.zoomY) && + clickedInside && + !panKey) { + if (!selectionMarker) { + this.selectionMarker = selectionMarker = + chart.renderer.rect(plotLeft, plotTop, zoomHor ? 1 : plotWidth, zoomVert ? 1 : plotHeight, 0) + .attr({ + 'class': 'highcharts-selection-marker', + zIndex: 7 + }) + .add(); + if (!chart.styledMode) { + selectionMarker.attr({ + fill: (chartOptions.selectionMarkerFill || + color('#335cad') + .setOpacity(0.25).get()) + }); + } + } + } + // adjust the width of the selection marker + if (selectionMarker && zoomHor) { + size = chartX - mouseDownX; + selectionMarker.attr({ + width: Math.abs(size), + x: (size > 0 ? 0 : size) + mouseDownX + }); + } + // adjust the height of the selection marker + if (selectionMarker && zoomVert) { + size = chartY - mouseDownY; + selectionMarker.attr({ + height: Math.abs(size), + y: (size > 0 ? 0 : size) + mouseDownY + }); + } + // panning + if (clickedInside && + !selectionMarker && + panningEnabled) { + chart.pan(e, chartOptions.panning); + } + } + }; + /** + * Start a drag operation. + * + * @private + * @function Highcharts.Pointer#dragStart + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + Pointer.prototype.dragStart = function (e) { + var chart = this.chart; + // Record the start position + chart.mouseIsDown = e.type; + chart.cancelClick = false; + chart.mouseDownX = this.mouseDownX = e.chartX; + chart.mouseDownY = this.mouseDownY = e.chartY; + }; + /** + * On mouse up or touch end across the entire document, drop the selection. + * + * @private + * @function Highcharts.Pointer#drop + * + * @param {global.Event} e + */ + Pointer.prototype.drop = function (e) { + var pointer = this, chart = this.chart, hasPinched = this.hasPinched; + if (this.selectionMarker) { + var selectionData = { + originalEvent: e, + xAxis: [], + yAxis: [] + }, selectionBox = this.selectionMarker, selectionLeft = selectionBox.attr ? + selectionBox.attr('x') : + selectionBox.x, selectionTop = selectionBox.attr ? + selectionBox.attr('y') : + selectionBox.y, selectionWidth = selectionBox.attr ? + selectionBox.attr('width') : + selectionBox.width, selectionHeight = selectionBox.attr ? + selectionBox.attr('height') : + selectionBox.height, runZoom; + // a selection has been made + if (this.hasDragged || hasPinched) { + // record each axis' min and max + chart.axes.forEach(function (axis) { + if (axis.zoomEnabled && + defined(axis.min) && + (hasPinched || + pointer[{ + xAxis: 'zoomX', + yAxis: 'zoomY' + }[axis.coll]])) { // #859, #3569 + var horiz = axis.horiz, minPixelPadding = e.type === 'touchend' ? + axis.minPixelPadding : + 0, // #1207, #3075 + selectionMin = axis.toValue((horiz ? selectionLeft : selectionTop) + + minPixelPadding), selectionMax = axis.toValue((horiz ? + selectionLeft + selectionWidth : + selectionTop + selectionHeight) - minPixelPadding); + selectionData[axis.coll].push({ + axis: axis, + // Min/max for reversed axes + min: Math.min(selectionMin, selectionMax), + max: Math.max(selectionMin, selectionMax) + }); + runZoom = true; + } + }); + if (runZoom) { + fireEvent(chart, 'selection', selectionData, function (args) { + chart.zoom(extend(args, hasPinched ? + { animation: false } : + null)); + }); + } + } + if (isNumber(chart.index)) { + this.selectionMarker = this.selectionMarker.destroy(); + } + // Reset scaling preview + if (hasPinched) { + this.scaleGroups(); + } + } + // Reset all. Check isNumber because it may be destroyed on mouse up + // (#877) + if (chart && isNumber(chart.index)) { + css(chart.container, { cursor: chart._cursor }); + chart.cancelClick = this.hasDragged > 10; // #370 + chart.mouseIsDown = this.hasDragged = this.hasPinched = false; + this.pinchDown = []; + } + }; + /** + * Finds the closest point to a set of coordinates, using the k-d-tree + * algorithm. + * + * @function Highcharts.Pointer#findNearestKDPoints + * + * @param {Array} series + * All the series to search in. + * + * @param {boolean|undefined} shared + * Whether it is a shared tooltip or not. + * + * @param {Highcharts.PointerEventObject} e + * The pointer event object, containing chart coordinates of the + * pointer. + * + * @return {Highcharts.Point|undefined} + * The point closest to given coordinates. + */ + Pointer.prototype.findNearestKDPoint = function (series, shared, e) { + var chart = this.chart; + var hoverPoint = chart.hoverPoint; + var tooltip = chart.tooltip; + if (hoverPoint && + tooltip && + tooltip.isStickyOnContact()) { + return hoverPoint; + } + var closest; + /** @private */ + function sort(p1, p2) { + var isCloserX = p1.distX - p2.distX, isCloser = p1.dist - p2.dist, isAbove = (p2.series.group && p2.series.group.zIndex) - + (p1.series.group && p1.series.group.zIndex), result; + // We have two points which are not in the same place on xAxis + // and shared tooltip: + if (isCloserX !== 0 && shared) { // #5721 + result = isCloserX; + // Points are not exactly in the same place on x/yAxis: + } + else if (isCloser !== 0) { + result = isCloser; + // The same xAxis and yAxis position, sort by z-index: + } + else if (isAbove !== 0) { + result = isAbove; + // The same zIndex, sort by array index: + } + else { + result = + p1.series.index > p2.series.index ? + -1 : + 1; + } + return result; + } + series.forEach(function (s) { + var noSharedTooltip = s.noSharedTooltip && shared, compareX = (!noSharedTooltip && + s.options.findNearestPointBy.indexOf('y') < 0), point = s.searchPoint(e, compareX); + if ( // Check that we actually found a point on the series. + isObject(point, true) && + // Use the new point if it is closer. + (!isObject(closest, true) || + (sort(closest, point) > 0))) { + closest = point; + } + }); + return closest; + }; + /** + * @private + * @function Highcharts.Pointer#getChartCoordinatesFromPoint + * @param {Highcharts.Point} point + * @param {boolean} [inverted] + * @return {Highcharts.PointerCoordinatesObject|undefined} + */ + Pointer.prototype.getChartCoordinatesFromPoint = function (point, inverted) { + var series = point.series, xAxis = series.xAxis, yAxis = series.yAxis, plotX = pick(point.clientX, point.plotX), shapeArgs = point.shapeArgs; + if (xAxis && yAxis) { + return inverted ? { + chartX: xAxis.len + xAxis.pos - plotX, + chartY: yAxis.len + yAxis.pos - point.plotY + } : { + chartX: plotX + xAxis.pos, + chartY: point.plotY + yAxis.pos + }; + } + if (shapeArgs && shapeArgs.x && shapeArgs.y) { + // E.g. pies do not have axes + return { + chartX: shapeArgs.x, + chartY: shapeArgs.y + }; + } + }; + /** + * Return the cached chartPosition if it is available on the Pointer, + * otherwise find it. Running offset is quite expensive, so it should be + * avoided when we know the chart hasn't moved. + * + * @function Highcharts.Pointer#getChartPosition + * + * @return {Highcharts.OffsetObject} + * The offset of the chart container within the page + */ + Pointer.prototype.getChartPosition = function () { + return (this.chartPosition || + (this.chartPosition = offset(this.chart.container))); + }; + /** + * Get the click position in terms of axis values. + * + * @function Highcharts.Pointer#getCoordinates + * + * @param {Highcharts.PointerEventObject} e + * Pointer event, extended with `chartX` and `chartY` properties. + * + * @return {Highcharts.PointerAxisCoordinatesObject} + */ + Pointer.prototype.getCoordinates = function (e) { + var coordinates = { + xAxis: [], + yAxis: [] + }; + this.chart.axes.forEach(function (axis) { + coordinates[axis.isXAxis ? 'xAxis' : 'yAxis'].push({ + axis: axis, + value: axis.toValue(e[axis.horiz ? 'chartX' : 'chartY']) + }); + }); + return coordinates; + }; + /** + * Calculates what is the current hovered point/points and series. + * + * @private + * @function Highcharts.Pointer#getHoverData + * + * @param {Highcharts.Point|undefined} existingHoverPoint + * The point currrently beeing hovered. + * + * @param {Highcharts.Series|undefined} existingHoverSeries + * The series currently beeing hovered. + * + * @param {Array} series + * All the series in the chart. + * + * @param {boolean} isDirectTouch + * Is the pointer directly hovering the point. + * + * @param {boolean|undefined} shared + * Whether it is a shared tooltip or not. + * + * @param {Highcharts.PointerEventObject} [e] + * The triggering event, containing chart coordinates of the pointer. + * + * @return {object} + * Object containing resulting hover data: hoverPoint, hoverSeries, + * and hoverPoints. + */ + Pointer.prototype.getHoverData = function (existingHoverPoint, existingHoverSeries, series, isDirectTouch, shared, e) { + var hoverPoint, hoverPoints = [], hoverSeries = existingHoverSeries, useExisting = !!(isDirectTouch && existingHoverPoint), notSticky = hoverSeries && !hoverSeries.stickyTracking, + // Which series to look in for the hover point + searchSeries, + // Parameters needed for beforeGetHoverData event. + eventArgs = { + chartX: e ? e.chartX : void 0, + chartY: e ? e.chartY : void 0, + shared: shared + }, filter = function (s) { + return (s.visible && + !(!shared && s.directTouch) && // #3821 + pick(s.options.enableMouseTracking, true)); + }; + // Find chart.hoverPane and update filter method in polar. + fireEvent(this, 'beforeGetHoverData', eventArgs); + searchSeries = notSticky ? + // Only search on hovered series if it has stickyTracking false + [hoverSeries] : + // Filter what series to look in. + series.filter(function (s) { + return eventArgs.filter ? eventArgs.filter(s) : filter(s) && + s.stickyTracking; + }); + // Use existing hovered point or find the one closest to coordinates. + hoverPoint = useExisting || !e ? + existingHoverPoint : + this.findNearestKDPoint(searchSeries, shared, e); + // Assign hover series + hoverSeries = hoverPoint && hoverPoint.series; + // If we have a hoverPoint, assign hoverPoints. + if (hoverPoint) { + // When tooltip is shared, it displays more than one point + if (shared && !hoverSeries.noSharedTooltip) { + searchSeries = series.filter(function (s) { + return eventArgs.filter ? + eventArgs.filter(s) : filter(s) && !s.noSharedTooltip; + }); + // Get all points with the same x value as the hoverPoint + searchSeries.forEach(function (s) { + var point = find(s.points, function (p) { + return p.x === hoverPoint.x && !p.isNull; + }); + if (isObject(point)) { + /* + * Boost returns a minimal point. Convert it to a usable + * point for tooltip and states. + */ + if (s.chart.isBoosting) { + point = s.getPoint(point); + } + hoverPoints.push(point); + } + }); + } + else { + hoverPoints.push(hoverPoint); + } + } + // Check whether the hoverPoint is inside pane we are hovering over. + eventArgs = { hoverPoint: hoverPoint }; + fireEvent(this, 'afterGetHoverData', eventArgs); + return { + hoverPoint: eventArgs.hoverPoint, + hoverSeries: hoverSeries, + hoverPoints: hoverPoints + }; + }; + /** + * @private + * @function Highcharts.Pointer#getPointFromEvent + * + * @param {global.Event} e + * + * @return {Highcharts.Point|undefined} + */ + Pointer.prototype.getPointFromEvent = function (e) { + var target = e.target, point; + while (target && !point) { + point = target.point; + target = target.parentNode; + } + return point; + }; + /** + * @private + * @function Highcharts.Pointer#onTrackerMouseOut + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + Pointer.prototype.onTrackerMouseOut = function (e) { + var chart = this.chart; + var relatedTarget = e.relatedTarget || e.toElement; + var series = chart.hoverSeries; + this.isDirectTouch = false; + if (series && + relatedTarget && + !series.stickyTracking && + !this.inClass(relatedTarget, 'highcharts-tooltip') && + (!this.inClass(relatedTarget, 'highcharts-series-' + series.index) || // #2499, #4465, #5553 + !this.inClass(relatedTarget, 'highcharts-tracker'))) { + series.onMouseOut(); + } + }; + /** + * Utility to detect whether an element has, or has a parent with, a + * specificclass name. Used on detection of tracker objects and on deciding + * whether hovering the tooltip should cause the active series to mouse out. + * + * @function Highcharts.Pointer#inClass + * + * @param {Highcharts.SVGDOMElement|Highcharts.HTMLDOMElement} element + * The element to investigate. + * + * @param {string} className + * The class name to look for. + * + * @return {boolean|undefined} + * True if either the element or one of its parents has the given + * class name. + */ + Pointer.prototype.inClass = function (element, className) { + var elemClassName; + while (element) { + elemClassName = attr(element, 'class'); + if (elemClassName) { + if (elemClassName.indexOf(className) !== -1) { + return true; + } + if (elemClassName.indexOf('highcharts-container') !== -1) { + return false; + } + } + element = element.parentNode; + } + }; + /** + * Initialize the Pointer. + * + * @private + * @function Highcharts.Pointer#init + * + * @param {Highcharts.Chart} chart + * The Chart instance. + * + * @param {Highcharts.Options} options + * The root options object. The pointer uses options from the chart + * and tooltip structures. + * + * @return {void} + */ + Pointer.prototype.init = function (chart, options) { + // Store references + this.options = options; + this.chart = chart; + // Do we need to handle click on a touch device? + this.runChartClick = + options.chart.events && + !!options.chart.events.click; + this.pinchDown = []; + this.lastValidTouch = {}; + if (Tooltip) { + /** + * Tooltip object for points of series. + * + * @name Highcharts.Chart#tooltip + * @type {Highcharts.Tooltip} + */ + chart.tooltip = new Tooltip(chart, options.tooltip); + this.followTouchMove = pick(options.tooltip.followTouchMove, true); + } + this.setDOMEvents(); + }; + /** + * Takes a browser event object and extends it with custom Highcharts + * properties `chartX` and `chartY` in order to work on the internal + * coordinate system. + * + * @function Highcharts.Pointer#normalize + * + * @param {global.MouseEvent|global.PointerEvent|global.TouchEvent} e + * Event object in standard browsers. + * + * @param {Highcharts.OffsetObject} [chartPosition] + * Additional chart offset. + * + * @return {Highcharts.PointerEventObject} + * A browser event with extended properties `chartX` and `chartY`. + */ + Pointer.prototype.normalize = function (e, chartPosition) { + var touches = e.touches; + // iOS (#2757) + var ePos = (touches ? + touches.length ? + touches.item(0) : + touches.changedTouches[0] : + e); + // Get mouse position + if (!chartPosition) { + chartPosition = this.getChartPosition(); + } + var chartX = ePos.pageX - chartPosition.left, chartY = ePos.pageY - chartPosition.top; + // #11329 - when there is scaling on a parent element, we need to take + // this into account + var containerScaling = this.chart.containerScaling; + if (containerScaling) { + chartX /= containerScaling.scaleX; + chartY /= containerScaling.scaleY; + } + return extend(e, { + chartX: Math.round(chartX), + chartY: Math.round(chartY) + }); + }; + /** + * @private + * @function Highcharts.Pointer#onContainerClick + * + * @param {global.MouseEvent} e + * + * @return {void} + */ + Pointer.prototype.onContainerClick = function (e) { + var chart = this.chart; + var hoverPoint = chart.hoverPoint; + var pEvt = this.normalize(e); + var plotLeft = chart.plotLeft; + var plotTop = chart.plotTop; + if (!chart.cancelClick) { + // On tracker click, fire the series and point events. #783, #1583 + if (hoverPoint && + this.inClass(pEvt.target, 'highcharts-tracker')) { + // the series click event + fireEvent(hoverPoint.series, 'click', extend(pEvt, { + point: hoverPoint + })); + // the point click event + if (chart.hoverPoint) { // it may be destroyed (#1844) + hoverPoint.firePointEvent('click', pEvt); + } + // When clicking outside a tracker, fire a chart event + } + else { + extend(pEvt, this.getCoordinates(pEvt)); + // fire a click event in the chart + if (chart.isInsidePlot((pEvt.chartX - plotLeft), (pEvt.chartY - plotTop))) { + fireEvent(chart, 'click', pEvt); + } + } + } + }; + /** + * @private + * @function Highcharts.Pointer#onContainerMouseDown + * + * @param {global.MouseEvent} e + */ + Pointer.prototype.onContainerMouseDown = function (e) { + // Normalize before the 'if' for the legacy IE (#7850) + e = this.normalize(e); + // #11635, Firefox does not reliable fire move event after click scroll + if (H.isFirefox && + e.button !== 0) { + this.onContainerMouseMove(e); + } + // #11635, limiting to primary button (incl. IE 8 support) + if (typeof e.button === 'undefined' || + ((e.buttons || e.button) & 1) === 1) { + this.zoomOption(e); + this.dragStart(e); + } + }; + /** + * When mouse leaves the container, hide the tooltip. + * + * @private + * @function Highcharts.Pointer#onContainerMouseLeave + * + * @param {global.MouseEvent} e + * + * @return {void} + */ + Pointer.prototype.onContainerMouseLeave = function (e) { + var chart = charts[pick(H.hoverChartIndex, -1)]; + var tooltip = this.chart.tooltip; + e = this.normalize(e); + // #4886, MS Touch end fires mouseleave but with no related target + if (chart && + (e.relatedTarget || e.toElement)) { + chart.pointer.reset(); + // Also reset the chart position, used in #149 fix + chart.pointer.chartPosition = void 0; + } + if ( // #11635, Firefox wheel scroll does not fire out events consistently + tooltip && + !tooltip.isHidden) { + this.reset(); + } + }; + /** + * The mousemove, touchmove and touchstart event handler + * + * @private + * @function Highcharts.Pointer#onContainerMouseMove + * + * @param {global.MouseEvent} e + * + * @return {void} + */ + Pointer.prototype.onContainerMouseMove = function (e) { + var chart = this.chart; + var pEvt = this.normalize(e); + this.setHoverChartIndex(); + // In IE8 we apparently need this returnValue set to false in order to + // avoid text being selected. But in Chrome, e.returnValue is prevented, + // plus we don't need to run e.preventDefault to prevent selected text + // in modern browsers. So we set it conditionally. Remove it when IE8 is + // no longer needed. #2251, #3224. + if (!pEvt.preventDefault) { + pEvt.returnValue = false; + } + if (chart.mouseIsDown === 'mousedown') { + this.drag(pEvt); + } + // Show the tooltip and run mouse over events (#977) + if (!chart.openMenu && + (this.inClass(pEvt.target, 'highcharts-tracker') || + chart.isInsidePlot((pEvt.chartX - chart.plotLeft), (pEvt.chartY - chart.plotTop)))) { + this.runPointActions(pEvt); + } + }; + /** + * @private + * @function Highcharts.Pointer#onDocumentTouchEnd + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + Pointer.prototype.onDocumentTouchEnd = function (e) { + if (charts[H.hoverChartIndex]) { + charts[H.hoverChartIndex].pointer.drop(e); + } + }; + /** + * @private + * @function Highcharts.Pointer#onContainerTouchMove + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + Pointer.prototype.onContainerTouchMove = function (e) { + this.touch(e); + }; + /** + * @private + * @function Highcharts.Pointer#onContainerTouchStart + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + Pointer.prototype.onContainerTouchStart = function (e) { + this.zoomOption(e); + this.touch(e, true); + }; + /** + * Special handler for mouse move that will hide the tooltip when the mouse + * leaves the plotarea. Issue #149 workaround. The mouseleave event does not + * always fire. + * + * @private + * @function Highcharts.Pointer#onDocumentMouseMove + * + * @param {global.MouseEvent} e + * + * @return {void} + */ + Pointer.prototype.onDocumentMouseMove = function (e) { + var chart = this.chart; + var chartPosition = this.chartPosition; + var pEvt = this.normalize(e, chartPosition); + var tooltip = chart.tooltip; + // If we're outside, hide the tooltip + if (chartPosition && + (!tooltip || + !tooltip.isStickyOnContact()) && + !chart.isInsidePlot(pEvt.chartX - chart.plotLeft, pEvt.chartY - chart.plotTop) && + !this.inClass(pEvt.target, 'highcharts-tracker')) { + this.reset(); + } + }; + /** + * @private + * @function Highcharts.Pointer#onDocumentMouseUp + * + * @param {global.MouseEvent} e + * + * @return {void} + */ + Pointer.prototype.onDocumentMouseUp = function (e) { + var chart = charts[pick(H.hoverChartIndex, -1)]; + if (chart) { + chart.pointer.drop(e); + } + }; + /** + * Handle touch events with two touches + * + * @private + * @function Highcharts.Pointer#pinch + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + Pointer.prototype.pinch = function (e) { + var self = this, chart = self.chart, pinchDown = self.pinchDown, touches = (e.touches || []), touchesLength = touches.length, lastValidTouch = self.lastValidTouch, hasZoom = self.hasZoom, selectionMarker = self.selectionMarker, transform = {}, fireClickEvent = touchesLength === 1 && ((self.inClass(e.target, 'highcharts-tracker') && + chart.runTrackerClick) || + self.runChartClick), clip = {}; + // Don't initiate panning until the user has pinched. This prevents us + // from blocking page scrolling as users scroll down a long page + // (#4210). + if (touchesLength > 1) { + self.initiated = true; + } + // On touch devices, only proceed to trigger click if a handler is + // defined + if (hasZoom && self.initiated && !fireClickEvent) { + e.preventDefault(); + } + // Normalize each touch + [].map.call(touches, function (e) { + return self.normalize(e); + }); + // Register the touch start position + if (e.type === 'touchstart') { + [].forEach.call(touches, function (e, i) { + pinchDown[i] = { chartX: e.chartX, chartY: e.chartY }; + }); + lastValidTouch.x = [pinchDown[0].chartX, pinchDown[1] && + pinchDown[1].chartX]; + lastValidTouch.y = [pinchDown[0].chartY, pinchDown[1] && + pinchDown[1].chartY]; + // Identify the data bounds in pixels + chart.axes.forEach(function (axis) { + if (axis.zoomEnabled) { + var bounds = chart.bounds[axis.horiz ? 'h' : 'v'], minPixelPadding = axis.minPixelPadding, min = axis.toPixels(Math.min(pick(axis.options.min, axis.dataMin), axis.dataMin)), max = axis.toPixels(Math.max(pick(axis.options.max, axis.dataMax), axis.dataMax)), absMin = Math.min(min, max), absMax = Math.max(min, max); + // Store the bounds for use in the touchmove handler + bounds.min = Math.min(axis.pos, absMin - minPixelPadding); + bounds.max = Math.max(axis.pos + axis.len, absMax + minPixelPadding); + } + }); + self.res = true; // reset on next move + // Optionally move the tooltip on touchmove + } + else if (self.followTouchMove && touchesLength === 1) { + this.runPointActions(self.normalize(e)); + // Event type is touchmove, handle panning and pinching + } + else if (pinchDown.length) { // can be 0 when releasing, if touchend + // fires first + // Set the marker + if (!selectionMarker) { + self.selectionMarker = selectionMarker = extend({ + destroy: noop, + touch: true + }, chart.plotBox); + } + self.pinchTranslate(pinchDown, touches, transform, selectionMarker, clip, lastValidTouch); + self.hasPinched = hasZoom; + // Scale and translate the groups to provide visual feedback during + // pinching + self.scaleGroups(transform, clip); + if (self.res) { + self.res = false; + this.reset(false, 0); + } + } + }; + /** + * Run translation operations + * + * @private + * @function Highcharts.Pointer#pinchTranslate + * + * @param {Array<*>} pinchDown + * + * @param {Array} touches + * + * @param {*} transform + * + * @param {*} selectionMarker + * + * @param {*} clip + * + * @param {*} lastValidTouch + * + * @return {void} + */ + Pointer.prototype.pinchTranslate = function (pinchDown, touches, transform, selectionMarker, clip, lastValidTouch) { + if (this.zoomHor) { + this.pinchTranslateDirection(true, pinchDown, touches, transform, selectionMarker, clip, lastValidTouch); + } + if (this.zoomVert) { + this.pinchTranslateDirection(false, pinchDown, touches, transform, selectionMarker, clip, lastValidTouch); + } + }; + /** + * Run translation operations for each direction (horizontal and vertical) + * independently. + * + * @private + * @function Highcharts.Pointer#pinchTranslateDirection + * + * @param {boolean} horiz + * + * @param {Array<*>} pinchDown + * + * @param {Array} touches + * + * @param {*} transform + * + * @param {*} selectionMarker + * + * @param {*} clip + * + * @param {*} lastValidTouch + * + * @param {number|undefined} [forcedScale=1] + * + * @return {void} + */ + Pointer.prototype.pinchTranslateDirection = function (horiz, pinchDown, touches, transform, selectionMarker, clip, lastValidTouch, forcedScale) { + var chart = this.chart, xy = horiz ? 'x' : 'y', XY = horiz ? 'X' : 'Y', sChartXY = ('chart' + XY), wh = horiz ? 'width' : 'height', plotLeftTop = chart['plot' + (horiz ? 'Left' : 'Top')], selectionWH, selectionXY, clipXY, scale = forcedScale || 1, inverted = chart.inverted, bounds = chart.bounds[horiz ? 'h' : 'v'], singleTouch = pinchDown.length === 1, touch0Start = pinchDown[0][sChartXY], touch0Now = touches[0][sChartXY], touch1Start = !singleTouch && pinchDown[1][sChartXY], touch1Now = !singleTouch && touches[1][sChartXY], outOfBounds, transformScale, scaleKey, setScale = function () { + // Don't zoom if fingers are too close on this axis + if (typeof touch1Now === 'number' && + Math.abs(touch0Start - touch1Start) > 20) { + scale = forcedScale || + Math.abs(touch0Now - touch1Now) / + Math.abs(touch0Start - touch1Start); + } + clipXY = ((plotLeftTop - touch0Now) / scale) + touch0Start; + selectionWH = chart['plot' + (horiz ? 'Width' : 'Height')] / scale; + }; + // Set the scale, first pass + setScale(); + // The clip position (x or y) is altered if out of bounds, the selection + // position is not + selectionXY = clipXY; + // Out of bounds + if (selectionXY < bounds.min) { + selectionXY = bounds.min; + outOfBounds = true; + } + else if (selectionXY + selectionWH > bounds.max) { + selectionXY = bounds.max - selectionWH; + outOfBounds = true; + } + // Is the chart dragged off its bounds, determined by dataMin and + // dataMax? + if (outOfBounds) { + // Modify the touchNow position in order to create an elastic drag + // movement. This indicates to the user that the chart is responsive + // but can't be dragged further. + touch0Now -= 0.8 * (touch0Now - lastValidTouch[xy][0]); + if (typeof touch1Now === 'number') { + touch1Now -= 0.8 * (touch1Now - lastValidTouch[xy][1]); + } + // Set the scale, second pass to adapt to the modified touchNow + // positions + setScale(); + } + else { + lastValidTouch[xy] = [touch0Now, touch1Now]; + } + // Set geometry for clipping, selection and transformation + if (!inverted) { + clip[xy] = clipXY - plotLeftTop; + clip[wh] = selectionWH; + } + scaleKey = inverted ? (horiz ? 'scaleY' : 'scaleX') : 'scale' + XY; + transformScale = inverted ? 1 / scale : scale; + selectionMarker[wh] = selectionWH; + selectionMarker[xy] = selectionXY; + transform[scaleKey] = scale; + transform['translate' + XY] = (transformScale * plotLeftTop) + + (touch0Now - (transformScale * touch0Start)); + }; + /** + * Reset the tracking by hiding the tooltip, the hover series state and the + * hover point + * + * @function Highcharts.Pointer#reset + * + * @param {boolean} [allowMove] + * Instead of destroying the tooltip altogether, allow moving it if + * possible. + * + * @param {number} [delay] + * + * @return {void} + */ + Pointer.prototype.reset = function (allowMove, delay) { + var pointer = this, chart = pointer.chart, hoverSeries = chart.hoverSeries, hoverPoint = chart.hoverPoint, hoverPoints = chart.hoverPoints, tooltip = chart.tooltip, tooltipPoints = tooltip && tooltip.shared ? + hoverPoints : + hoverPoint; + // Check if the points have moved outside the plot area (#1003, #4736, + // #5101) + if (allowMove && tooltipPoints) { + splat(tooltipPoints).forEach(function (point) { + if (point.series.isCartesian && + typeof point.plotX === 'undefined') { + allowMove = false; + } + }); + } + // Just move the tooltip, #349 + if (allowMove) { + if (tooltip && tooltipPoints && splat(tooltipPoints).length) { + tooltip.refresh(tooltipPoints); + if (tooltip.shared && hoverPoints) { // #8284 + hoverPoints.forEach(function (point) { + point.setState(point.state, true); + if (point.series.isCartesian) { + if (point.series.xAxis.crosshair) { + point.series.xAxis + .drawCrosshair(null, point); + } + if (point.series.yAxis.crosshair) { + point.series.yAxis + .drawCrosshair(null, point); + } + } + }); + } + else if (hoverPoint) { // #2500 + hoverPoint.setState(hoverPoint.state, true); + chart.axes.forEach(function (axis) { + if (axis.crosshair && + hoverPoint.series[axis.coll] === axis) { + axis.drawCrosshair(null, hoverPoint); + } + }); + } + } + // Full reset + } + else { + if (hoverPoint) { + hoverPoint.onMouseOut(); + } + if (hoverPoints) { + hoverPoints.forEach(function (point) { + point.setState(); + }); + } + if (hoverSeries) { + hoverSeries.onMouseOut(); + } + if (tooltip) { + tooltip.hide(delay); + } + if (pointer.unDocMouseMove) { + pointer.unDocMouseMove = pointer.unDocMouseMove(); + } + // Remove crosshairs + chart.axes.forEach(function (axis) { + axis.hideCrosshair(); + }); + pointer.hoverX = chart.hoverPoints = chart.hoverPoint = null; + } + }; + /** + * With line type charts with a single tracker, get the point closest to the + * mouse. Run Point.onMouseOver and display tooltip for the point or points. + * + * @private + * @function Highcharts.Pointer#runPointActions + * + * @param {global.Event} e + * + * @param {Highcharts.PointerEventObject} [p] + * + * @return {void} + * + * @fires Highcharts.Point#event:mouseOut + * @fires Highcharts.Point#event:mouseOver + */ + Pointer.prototype.runPointActions = function (e, p) { + var pointer = this, chart = pointer.chart, series = chart.series, tooltip = (chart.tooltip && chart.tooltip.options.enabled ? + chart.tooltip : + void 0), shared = (tooltip ? + tooltip.shared : + false), hoverPoint = p || chart.hoverPoint, hoverSeries = hoverPoint && hoverPoint.series || chart.hoverSeries, + // onMouseOver or already hovering a series with directTouch + isDirectTouch = (!e || e.type !== 'touchmove') && (!!p || ((hoverSeries && hoverSeries.directTouch) && + pointer.isDirectTouch)), hoverData = this.getHoverData(hoverPoint, hoverSeries, series, isDirectTouch, shared, e), useSharedTooltip, followPointer, anchor, points; + // Update variables from hoverData. + hoverPoint = hoverData.hoverPoint; + points = hoverData.hoverPoints; + hoverSeries = hoverData.hoverSeries; + followPointer = hoverSeries && hoverSeries.tooltipOptions.followPointer; + useSharedTooltip = (shared && + hoverSeries && + !hoverSeries.noSharedTooltip); + // Refresh tooltip for kdpoint if new hover point or tooltip was hidden + // #3926, #4200 + if (hoverPoint && + // !(hoverSeries && hoverSeries.directTouch) && + (hoverPoint !== chart.hoverPoint || (tooltip && tooltip.isHidden))) { + (chart.hoverPoints || []).forEach(function (p) { + if (points.indexOf(p) === -1) { + p.setState(); + } + }); + // Set normal state to previous series + if (chart.hoverSeries !== hoverSeries) { + hoverSeries.onMouseOver(); + } + pointer.applyInactiveState(points); + // Do mouseover on all points (#3919, #3985, #4410, #5622) + (points || []).forEach(function (p) { + p.setState('hover'); + }); + // If tracking is on series in stead of on each point, + // fire mouseOver on hover point. // #4448 + if (chart.hoverPoint) { + chart.hoverPoint.firePointEvent('mouseOut'); + } + // Hover point may have been destroyed in the event handlers (#7127) + if (!hoverPoint.series) { + return; + } + hoverPoint.firePointEvent('mouseOver'); + /** + * Contains all hovered points. + * + * @name Highcharts.Chart#hoverPoints + * @type {Array|null} + */ + chart.hoverPoints = points; + /** + * Contains the original hovered point. + * + * @name Highcharts.Chart#hoverPoint + * @type {Highcharts.Point|null} + */ + chart.hoverPoint = hoverPoint; + // Draw tooltip if necessary + if (tooltip) { + tooltip.refresh(useSharedTooltip ? points : hoverPoint, e); + } + // Update positions (regardless of kdpoint or hoverPoint) + } + else if (followPointer && tooltip && !tooltip.isHidden) { + anchor = tooltip.getAnchor([{}], e); + tooltip.updatePosition({ plotX: anchor[0], plotY: anchor[1] }); + } + // Start the event listener to pick up the tooltip and crosshairs + if (!pointer.unDocMouseMove) { + pointer.unDocMouseMove = addEvent(chart.container.ownerDocument, 'mousemove', function (e) { + var chart = charts[H.hoverChartIndex]; + if (chart) { + chart.pointer.onDocumentMouseMove(e); + } + }); + } + // Issues related to crosshair #4927, #5269 #5066, #5658 + chart.axes.forEach(function drawAxisCrosshair(axis) { + var snap = pick((axis.crosshair || {}).snap, true); + var point; + if (snap) { + point = chart.hoverPoint; // #13002 + if (!point || point.series[axis.coll] !== axis) { + point = find(points, function (p) { + return p.series[axis.coll] === axis; + }); + } + } + // Axis has snapping crosshairs, and one of the hover points belongs + // to axis. Always call drawCrosshair when it is not snap. + if (point || !snap) { + axis.drawCrosshair(e, point); + // Axis has snapping crosshairs, but no hover point belongs to axis + } + else { + axis.hideCrosshair(); + } + }); + }; + /** + * Scale series groups to a certain scale and translation. + * + * @private + * @function Highcharts.Pointer#scaleGroups + * + * @param {Highcharts.SeriesPlotBoxObject} [attribs] + * + * @param {boolean} [clip] + * + * @return {void} + */ + Pointer.prototype.scaleGroups = function (attribs, clip) { + var chart = this.chart, seriesAttribs; + // Scale each series + chart.series.forEach(function (series) { + seriesAttribs = attribs || series.getPlotBox(); // #1701 + if (series.xAxis && series.xAxis.zoomEnabled && series.group) { + series.group.attr(seriesAttribs); + if (series.markerGroup) { + series.markerGroup.attr(seriesAttribs); + series.markerGroup.clip(clip ? chart.clipRect : null); + } + if (series.dataLabelsGroup) { + series.dataLabelsGroup.attr(seriesAttribs); + } + } + }); + // Clip + chart.clipRect.attr(clip || chart.clipBox); + }; + /** + * Set the JS DOM events on the container and document. This method should + * contain a one-to-one assignment between methods and their handlers. Any + * advanced logic should be moved to the handler reflecting the event's + * name. + * + * @private + * @function Highcharts.Pointer#setDOMEvents + * + * @return {void} + */ + Pointer.prototype.setDOMEvents = function () { + var container = this.chart.container, ownerDoc = container.ownerDocument; + container.onmousedown = this.onContainerMouseDown.bind(this); + container.onmousemove = this.onContainerMouseMove.bind(this); + container.onclick = this.onContainerClick.bind(this); + this.unbindContainerMouseLeave = addEvent(container, 'mouseleave', this.onContainerMouseLeave.bind(this)); + if (!H.unbindDocumentMouseUp) { + H.unbindDocumentMouseUp = addEvent(ownerDoc, 'mouseup', this.onDocumentMouseUp.bind(this)); + } + if (H.hasTouch) { + addEvent(container, 'touchstart', this.onContainerTouchStart.bind(this)); + addEvent(container, 'touchmove', this.onContainerTouchMove.bind(this)); + if (!H.unbindDocumentTouchEnd) { + H.unbindDocumentTouchEnd = addEvent(ownerDoc, 'touchend', this.onDocumentTouchEnd.bind(this)); + } + } + }; + /** + * Sets the index of the hovered chart and leaves the previous hovered + * chart, to reset states like tooltip. + * + * @private + * @function Highcharts.Pointer#setHoverChartIndex + */ + Pointer.prototype.setHoverChartIndex = function () { + var chart = this.chart; + var hoverChart = H.charts[pick(H.hoverChartIndex, -1)]; + if (hoverChart && + hoverChart !== chart) { + hoverChart.pointer.onContainerMouseLeave({ relatedTarget: true }); + } + if (!hoverChart || + !hoverChart.mouseIsDown) { + H.hoverChartIndex = chart.index; + } + }; + /** + * General touch handler shared by touchstart and touchmove. + * + * @private + * @function Highcharts.Pointer#touch + * + * @param {Highcharts.PointerEventObject} e + * + * @param {boolean} [start] + * + * @return {void} + */ + Pointer.prototype.touch = function (e, start) { + var chart = this.chart, hasMoved, pinchDown, isInside; + this.setHoverChartIndex(); + if (e.touches.length === 1) { + e = this.normalize(e); + isInside = chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop); + if (isInside && !chart.openMenu) { + // Run mouse events and display tooltip etc + if (start) { + this.runPointActions(e); + } + // Android fires touchmove events after the touchstart even if + // the finger hasn't moved, or moved only a pixel or two. In iOS + // however, the touchmove doesn't fire unless the finger moves + // more than ~4px. So we emulate this behaviour in Android by + // checking how much it moved, and cancelling on small + // distances. #3450. + if (e.type === 'touchmove') { + pinchDown = this.pinchDown; + hasMoved = pinchDown[0] ? Math.sqrt(// #5266 + Math.pow(pinchDown[0].chartX - e.chartX, 2) + + Math.pow(pinchDown[0].chartY - e.chartY, 2)) >= 4 : false; + } + if (pick(hasMoved, true)) { + this.pinch(e); + } + } + else if (start) { + // Hide the tooltip on touching outside the plot area (#1203) + this.reset(); + } + } + else if (e.touches.length === 2) { + this.pinch(e); + } + }; + /** + * Resolve the zoomType option, this is reset on all touch start and mouse + * down events. + * + * @private + * @function Highcharts.Pointer#zoomOption + * + * @param {global.Event} e + * Event object. + * + * @param {void} + */ + Pointer.prototype.zoomOption = function (e) { + var chart = this.chart, options = chart.options.chart, zoomType = options.zoomType || '', inverted = chart.inverted, zoomX, zoomY; + // Look for the pinchType option + if (/touch/.test(e.type)) { + zoomType = pick(options.pinchType, zoomType); + } + this.zoomX = zoomX = /x/.test(zoomType); + this.zoomY = zoomY = /y/.test(zoomType); + this.zoomHor = (zoomX && !inverted) || (zoomY && inverted); + this.zoomVert = (zoomY && !inverted) || (zoomX && inverted); + this.hasZoom = zoomX || zoomY; + }; + return Pointer; + }()); + H.Pointer = Pointer; + + return H.Pointer; + }); + _registerModule(_modules, 'parts/MSPointer.js', [_modules['parts/Globals.js'], _modules['parts/Pointer.js'], _modules['parts/Utilities.js']], function (H, Pointer, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; + })(); + /* globals MSPointerEvent, PointerEvent */ + var addEvent = U.addEvent, css = U.css, objectEach = U.objectEach, removeEvent = U.removeEvent; + var charts = H.charts, doc = H.doc, noop = H.noop, win = H.win; + // The touches object keeps track of the points being touched at all times + var touches = {}; + var hasPointerEvent = !!win.PointerEvent; + /* eslint-disable valid-jsdoc */ + /** @private */ + function getWebkitTouches() { + var fake = []; + fake.item = function (i) { + return this[i]; + }; + objectEach(touches, function (touch) { + fake.push({ + pageX: touch.pageX, + pageY: touch.pageY, + target: touch.target + }); + }); + return fake; + } + /** @private */ + function translateMSPointer(e, method, wktype, func) { + var p; + if ((e.pointerType === 'touch' || + e.pointerType === e.MSPOINTER_TYPE_TOUCH) && charts[H.hoverChartIndex]) { + func(e); + p = charts[H.hoverChartIndex].pointer; + p[method]({ + type: wktype, + target: e.currentTarget, + preventDefault: noop, + touches: getWebkitTouches() + }); + } + } + /** @private */ + var MSPointer = /** @class */ (function (_super) { + __extends(MSPointer, _super); + function MSPointer() { + return _super !== null && _super.apply(this, arguments) || this; + } + /* * + * + * Functions + * + * */ + /** + * Add or remove the MS Pointer specific events + * + * @private + * @function Highcharts.Pointer#batchMSEvents + * + * @param {Function} fn + * + * @return {void} + */ + MSPointer.prototype.batchMSEvents = function (fn) { + fn(this.chart.container, hasPointerEvent ? 'pointerdown' : 'MSPointerDown', this.onContainerPointerDown); + fn(this.chart.container, hasPointerEvent ? 'pointermove' : 'MSPointerMove', this.onContainerPointerMove); + fn(doc, hasPointerEvent ? 'pointerup' : 'MSPointerUp', this.onDocumentPointerUp); + }; + // Destroy MS events also + MSPointer.prototype.destroy = function () { + this.batchMSEvents(removeEvent); + _super.prototype.destroy.call(this); + }; + // Disable default IE actions for pinch and such on chart element + MSPointer.prototype.init = function (chart, options) { + _super.prototype.init.call(this, chart, options); + if (this.hasZoom) { // #4014 + css(chart.container, { + '-ms-touch-action': 'none', + 'touch-action': 'none' + }); + } + }; + /** + * @private + * @function Highcharts.Pointer#onContainerPointerDown + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + MSPointer.prototype.onContainerPointerDown = function (e) { + translateMSPointer(e, 'onContainerTouchStart', 'touchstart', function (e) { + touches[e.pointerId] = { + pageX: e.pageX, + pageY: e.pageY, + target: e.currentTarget + }; + }); + }; + /** + * @private + * @function Highcharts.Pointer#onContainerPointerMove + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + MSPointer.prototype.onContainerPointerMove = function (e) { + translateMSPointer(e, 'onContainerTouchMove', 'touchmove', function (e) { + touches[e.pointerId] = ({ pageX: e.pageX, pageY: e.pageY }); + if (!touches[e.pointerId].target) { + touches[e.pointerId].target = e.currentTarget; + } + }); + }; + /** + * @private + * @function Highcharts.Pointer#onDocumentPointerUp + * + * @param {Highcharts.PointerEventObject} e + * + * @return {void} + */ + MSPointer.prototype.onDocumentPointerUp = function (e) { + translateMSPointer(e, 'onDocumentTouchEnd', 'touchend', function (e) { + delete touches[e.pointerId]; + }); + }; + // Add IE specific touch events to chart + MSPointer.prototype.setDOMEvents = function () { + _super.prototype.setDOMEvents.call(this); + if (this.hasZoom || this.followTouchMove) { + this.batchMSEvents(addEvent); + } + }; + return MSPointer; + }(Pointer)); + + return MSPointer; + }); + _registerModule(_modules, 'parts/Legend.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Gets fired when the legend item belonging to a point is clicked. The default + * action is to toggle the visibility of the point. This can be prevented by + * returning `false` or calling `event.preventDefault()`. + * + * @callback Highcharts.PointLegendItemClickCallbackFunction + * + * @param {Highcharts.Point} this + * The point on which the event occured. + * + * @param {Highcharts.PointLegendItemClickEventObject} event + * The event that occured. + */ + /** + * Information about the legend click event. + * + * @interface Highcharts.PointLegendItemClickEventObject + */ /** + * Related browser event. + * @name Highcharts.PointLegendItemClickEventObject#browserEvent + * @type {Highcharts.PointerEvent} + */ /** + * Prevent the default action of toggle the visibility of the point. + * @name Highcharts.PointLegendItemClickEventObject#preventDefault + * @type {Function} + */ /** + * Related point. + * @name Highcharts.PointLegendItemClickEventObject#target + * @type {Highcharts.Point} + */ /** + * Event type. + * @name Highcharts.PointLegendItemClickEventObject#type + * @type {"legendItemClick"} + */ + /** + * Gets fired when the legend item belonging to a series is clicked. The default + * action is to toggle the visibility of the series. This can be prevented by + * returning `false` or calling `event.preventDefault()`. + * + * @callback Highcharts.SeriesLegendItemClickCallbackFunction + * + * @param {Highcharts.Series} this + * The series where the event occured. + * + * @param {Highcharts.SeriesLegendItemClickEventObject} event + * The event that occured. + */ + /** + * Information about the legend click event. + * + * @interface Highcharts.SeriesLegendItemClickEventObject + */ /** + * Related browser event. + * @name Highcharts.SeriesLegendItemClickEventObject#browserEvent + * @type {Highcharts.PointerEvent} + */ /** + * Prevent the default action of toggle the visibility of the series. + * @name Highcharts.SeriesLegendItemClickEventObject#preventDefault + * @type {Function} + */ /** + * Related series. + * @name Highcharts.SeriesLegendItemClickEventObject#target + * @type {Highcharts.Series} + */ /** + * Event type. + * @name Highcharts.SeriesLegendItemClickEventObject#type + * @type {"legendItemClick"} + */ + var addEvent = U.addEvent, animObject = U.animObject, css = U.css, defined = U.defined, discardElement = U.discardElement, find = U.find, fireEvent = U.fireEvent, format = U.format, isNumber = U.isNumber, merge = U.merge, pick = U.pick, relativeLength = U.relativeLength, setAnimation = U.setAnimation, stableSort = U.stableSort, syncTimeout = U.syncTimeout, wrap = U.wrap; + var isFirefox = H.isFirefox, marginNames = H.marginNames, win = H.win; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The overview of the chart's series. The legend object is instanciated + * internally in the chart constructor, and is available from the `chart.legend` + * property. Each chart has only one legend. + * + * @class + * @name Highcharts.Legend + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @param {Highcharts.LegendOptions} options + * Legend options. + */ + var Legend = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Legend(chart, options) { + /* * + * + * Properties + * + * */ + this.allItems = []; + this.box = void 0; + this.contentGroup = void 0; + this.display = false; + this.group = void 0; + this.initialItemY = 0; + this.itemHeight = 0; + this.itemMarginBottom = 0; + this.itemMarginTop = 0; + this.itemX = 0; + this.itemY = 0; + this.lastItemY = 0; + this.lastLineHeight = 0; + this.legendHeight = 0; + this.legendWidth = 0; + this.maxItemWidth = 0; + this.maxLegendWidth = 0; + this.offsetWidth = 0; + this.options = {}; + this.padding = 0; + this.pages = []; + this.proximate = false; + this.scrollGroup = void 0; + this.symbolHeight = 0; + this.symbolWidth = 0; + this.titleHeight = 0; + this.totalItemWidth = 0; + this.widthOption = 0; + this.chart = chart; + this.init(chart, options); + } + /* * + * + * Functions + * + * */ + /** + * Initialize the legend. + * + * @private + * @function Highcharts.Legend#init + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @param {Highcharts.LegendOptions} options + * Legend options. + */ + Legend.prototype.init = function (chart, options) { + /** + * Chart of this legend. + * + * @readonly + * @name Highcharts.Legend#chart + * @type {Highcharts.Chart} + */ + this.chart = chart; + this.setOptions(options); + if (options.enabled) { + // Render it + this.render(); + // move checkboxes + addEvent(this.chart, 'endResize', function () { + this.legend.positionCheckboxes(); + }); + if (this.proximate) { + this.unchartrender = addEvent(this.chart, 'render', function () { + this.legend.proximatePositions(); + this.legend.positionItems(); + }); + } + else if (this.unchartrender) { + this.unchartrender(); + } + } + }; + /** + * @private + * @function Highcharts.Legend#setOptions + * @param {Highcharts.LegendOptions} options + */ + Legend.prototype.setOptions = function (options) { + var padding = pick(options.padding, 8); + /** + * Legend options. + * + * @readonly + * @name Highcharts.Legend#options + * @type {Highcharts.LegendOptions} + */ + this.options = options; + if (!this.chart.styledMode) { + this.itemStyle = options.itemStyle; + this.itemHiddenStyle = merge(this.itemStyle, options.itemHiddenStyle); + } + this.itemMarginTop = options.itemMarginTop || 0; + this.itemMarginBottom = options.itemMarginBottom || 0; + this.padding = padding; + this.initialItemY = padding - 5; // 5 is pixels above the text + this.symbolWidth = pick(options.symbolWidth, 16); + this.pages = []; + this.proximate = options.layout === 'proximate' && !this.chart.inverted; + this.baseline = void 0; // #12705: baseline has to be reset on every update + }; + /** + * Update the legend with new options. Equivalent to running `chart.update` + * with a legend configuration option. + * + * @sample highcharts/legend/legend-update/ + * Legend update + * + * @function Highcharts.Legend#update + * + * @param {Highcharts.LegendOptions} options + * Legend options. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the axis is altered. If doing more + * operations on the chart, it is a good idea to set redraw to false and + * call {@link Chart#redraw} after. Whether to redraw the chart. + * + * @fires Highcharts.Legends#event:afterUpdate + */ + Legend.prototype.update = function (options, redraw) { + var chart = this.chart; + this.setOptions(merge(true, this.options, options)); + this.destroy(); + chart.isDirtyLegend = chart.isDirtyBox = true; + if (pick(redraw, true)) { + chart.redraw(); + } + fireEvent(this, 'afterUpdate'); + }; + /** + * Set the colors for the legend item. + * + * @private + * @function Highcharts.Legend#colorizeItem + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + * A Series or Point instance + * @param {boolean} [visible=false] + * Dimmed or colored + * + * @todo + * Make events official: Fires the event `afterColorizeItem`. + */ + Legend.prototype.colorizeItem = function (item, visible) { + item.legendGroup[visible ? 'removeClass' : 'addClass']('highcharts-legend-item-hidden'); + if (!this.chart.styledMode) { + var legend = this, options = legend.options, legendItem = item.legendItem, legendLine = item.legendLine, legendSymbol = item.legendSymbol, hiddenColor = legend.itemHiddenStyle.color, textColor = visible ? + options.itemStyle.color : + hiddenColor, symbolColor = visible ? + (item.color || hiddenColor) : + hiddenColor, markerOptions = item.options && item.options.marker, symbolAttr = { fill: symbolColor }; + if (legendItem) { + legendItem.css({ + fill: textColor, + color: textColor // #1553, oldIE + }); + } + if (legendLine) { + legendLine.attr({ stroke: symbolColor }); + } + if (legendSymbol) { + // Apply marker options + if (markerOptions && legendSymbol.isMarker) { // #585 + symbolAttr = item.pointAttribs(); + if (!visible) { + // #6769 + symbolAttr.stroke = symbolAttr.fill = hiddenColor; + } + } + legendSymbol.attr(symbolAttr); + } + } + fireEvent(this, 'afterColorizeItem', { item: item, visible: visible }); + }; + /** + * @private + * @function Highcharts.Legend#positionItems + */ + Legend.prototype.positionItems = function () { + // Now that the legend width and height are established, put the items + // in the final position + this.allItems.forEach(this.positionItem, this); + if (!this.chart.isResizing) { + this.positionCheckboxes(); + } + }; + /** + * Position the legend item. + * + * @private + * @function Highcharts.Legend#positionItem + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + * The item to position + */ + Legend.prototype.positionItem = function (item) { + var legend = this, options = legend.options, symbolPadding = options.symbolPadding, ltr = !options.rtl, legendItemPos = item._legendItemPos, itemX = legendItemPos[0], itemY = legendItemPos[1], checkbox = item.checkbox, legendGroup = item.legendGroup; + if (legendGroup && legendGroup.element) { + legendGroup[defined(legendGroup.translateY) ? 'animate' : 'attr']({ + translateX: ltr ? + itemX : + legend.legendWidth - itemX - 2 * symbolPadding - 4, + translateY: itemY + }); + } + if (checkbox) { + checkbox.x = itemX; + checkbox.y = itemY; + } + }; + /** + * Destroy a single legend item, used internally on removing series items. + * + * @private + * @function Highcharts.Legend#destroyItem + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + * The item to remove + */ + Legend.prototype.destroyItem = function (item) { + var checkbox = item.checkbox; + // destroy SVG elements + ['legendItem', 'legendLine', 'legendSymbol', 'legendGroup'].forEach(function (key) { + if (item[key]) { + item[key] = item[key].destroy(); + } + }); + if (checkbox) { + discardElement(item.checkbox); + } + }; + /** + * Destroy the legend. Used internally. To reflow objects, `chart.redraw` + * must be called after destruction. + * + * @private + * @function Highcharts.Legend#destroy + */ + Legend.prototype.destroy = function () { + /** + * @private + * @param {string} key + * @return {void} + */ + function destroyItems(key) { + if (this[key]) { + this[key] = this[key].destroy(); + } + } + // Destroy items + this.getAllItems().forEach(function (item) { + ['legendItem', 'legendGroup'].forEach(destroyItems, item); + }); + // Destroy legend elements + [ + 'clipRect', + 'up', + 'down', + 'pager', + 'nav', + 'box', + 'title', + 'group' + ].forEach(destroyItems, this); + this.display = null; // Reset in .render on update. + }; + /** + * Position the checkboxes after the width is determined. + * + * @private + * @function Highcharts.Legend#positionCheckboxes + */ + Legend.prototype.positionCheckboxes = function () { + var alignAttr = this.group && this.group.alignAttr, translateY, clipHeight = this.clipHeight || this.legendHeight, titleHeight = this.titleHeight; + if (alignAttr) { + translateY = alignAttr.translateY; + this.allItems.forEach(function (item) { + var checkbox = item.checkbox, top; + if (checkbox) { + top = translateY + titleHeight + checkbox.y + + (this.scrollOffset || 0) + 3; + css(checkbox, { + left: (alignAttr.translateX + item.checkboxOffset + + checkbox.x - 20) + 'px', + top: top + 'px', + display: this.proximate || (top > translateY - 6 && + top < translateY + clipHeight - 6) ? + '' : + 'none' + }); + } + }, this); + } + }; + /** + * Render the legend title on top of the legend. + * + * @private + * @function Highcharts.Legend#renderTitle + */ + Legend.prototype.renderTitle = function () { + var options = this.options, padding = this.padding, titleOptions = options.title, titleHeight = 0, bBox; + if (titleOptions.text) { + if (!this.title) { + /** + * SVG element of the legend title. + * + * @readonly + * @name Highcharts.Legend#title + * @type {Highcharts.SVGElement} + */ + this.title = this.chart.renderer.label(titleOptions.text, padding - 3, padding - 4, null, null, null, options.useHTML, null, 'legend-title') + .attr({ zIndex: 1 }); + if (!this.chart.styledMode) { + this.title.css(titleOptions.style); + } + this.title.add(this.group); + } + // Set the max title width (#7253) + if (!titleOptions.width) { + this.title.css({ + width: this.maxLegendWidth + 'px' + }); + } + bBox = this.title.getBBox(); + titleHeight = bBox.height; + this.offsetWidth = bBox.width; // #1717 + this.contentGroup.attr({ translateY: titleHeight }); + } + this.titleHeight = titleHeight; + }; + /** + * Set the legend item text. + * + * @function Highcharts.Legend#setText + * @param {Highcharts.Point|Highcharts.Series} item + * The item for which to update the text in the legend. + */ + Legend.prototype.setText = function (item) { + var options = this.options; + item.legendItem.attr({ + text: options.labelFormat ? + format(options.labelFormat, item, this.chart) : + options.labelFormatter.call(item) + }); + }; + /** + * Render a single specific legend item. Called internally from the `render` + * function. + * + * @private + * @function Highcharts.Legend#renderItem + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + * The item to render. + */ + Legend.prototype.renderItem = function (item) { + var legend = this, chart = legend.chart, renderer = chart.renderer, options = legend.options, horizontal = options.layout === 'horizontal', symbolWidth = legend.symbolWidth, symbolPadding = options.symbolPadding, itemStyle = legend.itemStyle, itemHiddenStyle = legend.itemHiddenStyle, itemDistance = horizontal ? pick(options.itemDistance, 20) : 0, ltr = !options.rtl, bBox, li = item.legendItem, isSeries = !item.series, series = !isSeries && item.series.drawLegendSymbol ? + item.series : + item, seriesOptions = series.options, showCheckbox = legend.createCheckboxForItem && + seriesOptions && + seriesOptions.showCheckbox, + // full width minus text width + itemExtraWidth = symbolWidth + symbolPadding + + itemDistance + (showCheckbox ? 20 : 0), useHTML = options.useHTML, itemClassName = item.options.className; + if (!li) { // generate it once, later move it + // Generate the group box, a group to hold the symbol and text. Text + // is to be appended in Legend class. + item.legendGroup = renderer + .g('legend-item') + .addClass('highcharts-' + series.type + '-series ' + + 'highcharts-color-' + item.colorIndex + + (itemClassName ? ' ' + itemClassName : '') + + (isSeries ? + ' highcharts-series-' + item.index : + '')) + .attr({ zIndex: 1 }) + .add(legend.scrollGroup); + // Generate the list item text and add it to the group + item.legendItem = li = renderer.text('', ltr ? + symbolWidth + symbolPadding : + -symbolPadding, legend.baseline || 0, useHTML); + if (!chart.styledMode) { + // merge to prevent modifying original (#1021) + li.css(merge(item.visible ? + itemStyle : + itemHiddenStyle)); + } + li + .attr({ + align: ltr ? 'left' : 'right', + zIndex: 2 + }) + .add(item.legendGroup); + // Get the baseline for the first item - the font size is equal for + // all + if (!legend.baseline) { + legend.fontMetrics = renderer.fontMetrics(chart.styledMode ? 12 : itemStyle.fontSize, li); + legend.baseline = + legend.fontMetrics.f + 3 + legend.itemMarginTop; + li.attr('y', legend.baseline); + } + // Draw the legend symbol inside the group box + legend.symbolHeight = + options.symbolHeight || legend.fontMetrics.f; + series.drawLegendSymbol(legend, item); + if (legend.setItemEvents) { + legend.setItemEvents(item, li, useHTML); + } + } + // Add the HTML checkbox on top + if (showCheckbox && !item.checkbox && legend.createCheckboxForItem) { + legend.createCheckboxForItem(item); + } + // Colorize the items + legend.colorizeItem(item, item.visible); + // Take care of max width and text overflow (#6659) + if (chart.styledMode || !itemStyle.width) { + li.css({ + width: ((options.itemWidth || + legend.widthOption || + chart.spacingBox.width) - itemExtraWidth) + 'px' + }); + } + // Always update the text + legend.setText(item); + // calculate the positions for the next line + bBox = li.getBBox(); + item.itemWidth = item.checkboxOffset = + options.itemWidth || + item.legendItemWidth || + bBox.width + itemExtraWidth; + legend.maxItemWidth = Math.max(legend.maxItemWidth, item.itemWidth); + legend.totalItemWidth += item.itemWidth; + legend.itemHeight = item.itemHeight = Math.round(item.legendItemHeight || bBox.height || legend.symbolHeight); + }; + /** + * Get the position of the item in the layout. We now know the + * maxItemWidth from the previous loop. + * + * @private + * @function Highcharts.Legend#layoutItem + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + */ + Legend.prototype.layoutItem = function (item) { + var options = this.options, padding = this.padding, horizontal = options.layout === 'horizontal', itemHeight = item.itemHeight, itemMarginBottom = this.itemMarginBottom, itemMarginTop = this.itemMarginTop, itemDistance = horizontal ? pick(options.itemDistance, 20) : 0, maxLegendWidth = this.maxLegendWidth, itemWidth = (options.alignColumns && + this.totalItemWidth > maxLegendWidth) ? + this.maxItemWidth : + item.itemWidth; + // If the item exceeds the width, start a new line + if (horizontal && + this.itemX - padding + itemWidth > maxLegendWidth) { + this.itemX = padding; + if (this.lastLineHeight) { // Not for the first line (#10167) + this.itemY += (itemMarginTop + + this.lastLineHeight + + itemMarginBottom); + } + this.lastLineHeight = 0; // reset for next line (#915, #3976) + } + // Set the edge positions + this.lastItemY = itemMarginTop + this.itemY + itemMarginBottom; + this.lastLineHeight = Math.max(// #915 + itemHeight, this.lastLineHeight); + // cache the position of the newly generated or reordered items + item._legendItemPos = [this.itemX, this.itemY]; + // advance + if (horizontal) { + this.itemX += itemWidth; + } + else { + this.itemY += + itemMarginTop + itemHeight + itemMarginBottom; + this.lastLineHeight = itemHeight; + } + // the width of the widest item + this.offsetWidth = this.widthOption || Math.max((horizontal ? this.itemX - padding - (item.checkbox ? + // decrease by itemDistance only when no checkbox #4853 + 0 : + itemDistance) : itemWidth) + padding, this.offsetWidth); + }; + /** + * Get all items, which is one item per series for most series and one + * item per point for pie series and its derivatives. Fires the event + * `afterGetAllItems`. + * + * @private + * @function Highcharts.Legend#getAllItems + * @return {Array<(Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series)>} + * The current items in the legend. + * @fires Highcharts.Legend#event:afterGetAllItems + */ + Legend.prototype.getAllItems = function () { + var allItems = []; + this.chart.series.forEach(function (series) { + var seriesOptions = series && series.options; + // Handle showInLegend. If the series is linked to another series, + // defaults to false. + if (series && pick(seriesOptions.showInLegend, !defined(seriesOptions.linkedTo) ? void 0 : false, true)) { + // Use points or series for the legend item depending on + // legendType + allItems = allItems.concat(series.legendItems || + (seriesOptions.legendType === 'point' ? + series.data : + series)); + } + }); + fireEvent(this, 'afterGetAllItems', { allItems: allItems }); + return allItems; + }; + /** + * Get a short, three letter string reflecting the alignment and layout. + * + * @private + * @function Highcharts.Legend#getAlignment + * @return {string} + * The alignment, empty string if floating + */ + Legend.prototype.getAlignment = function () { + var options = this.options; + // Use the first letter of each alignment option in order to detect + // the side. (#4189 - use charAt(x) notation instead of [x] for IE7) + if (this.proximate) { + return options.align.charAt(0) + 'tv'; + } + return options.floating ? '' : (options.align.charAt(0) + + options.verticalAlign.charAt(0) + + options.layout.charAt(0)); + }; + /** + * Adjust the chart margins by reserving space for the legend on only one + * side of the chart. If the position is set to a corner, top or bottom is + * reserved for horizontal legends and left or right for vertical ones. + * + * @private + * @function Highcharts.Legend#adjustMargins + * @param {Array} margin + * @param {Array} spacing + */ + Legend.prototype.adjustMargins = function (margin, spacing) { + var chart = this.chart, options = this.options, alignment = this.getAlignment(); + if (alignment) { + ([ + /(lth|ct|rth)/, + /(rtv|rm|rbv)/, + /(rbh|cb|lbh)/, + /(lbv|lm|ltv)/ + ]).forEach(function (alignments, side) { + if (alignments.test(alignment) && !defined(margin[side])) { + // Now we have detected on which side of the chart we should + // reserve space for the legend + chart[marginNames[side]] = Math.max(chart[marginNames[side]], (chart.legend[(side + 1) % 2 ? 'legendHeight' : 'legendWidth'] + + [1, -1, -1, 1][side] * options[(side % 2) ? 'x' : 'y'] + + pick(options.margin, 12) + + spacing[side] + + (chart.titleOffset[side] || 0))); + } + }); + } + }; + /** + * @private + * @function Highcharts.Legend#proximatePositions + */ + Legend.prototype.proximatePositions = function () { + var chart = this.chart, boxes = [], alignLeft = this.options.align === 'left'; + this.allItems.forEach(function (item) { + var lastPoint, height, useFirstPoint = alignLeft, target, top; + if (item.yAxis && item.points) { + if (item.xAxis.options.reversed) { + useFirstPoint = !useFirstPoint; + } + lastPoint = find(useFirstPoint ? + item.points : + item.points.slice(0).reverse(), function (item) { + return isNumber(item.plotY); + }); + height = this.itemMarginTop + + item.legendItem.getBBox().height + + this.itemMarginBottom; + top = item.yAxis.top - chart.plotTop; + if (item.visible) { + target = lastPoint ? + lastPoint.plotY : + item.yAxis.height; + target += top - 0.3 * height; + } + else { + target = top + item.yAxis.height; + } + boxes.push({ + target: target, + size: height, + item: item + }); + } + }, this); + H.distribute(boxes, chart.plotHeight); + boxes.forEach(function (box) { + box.item._legendItemPos[1] = + chart.plotTop - chart.spacing[0] + box.pos; + }); + }; + /** + * Render the legend. This method can be called both before and after + * `chart.render`. If called after, it will only rearrange items instead + * of creating new ones. Called internally on initial render and after + * redraws. + * + * @private + * @function Highcharts.Legend#render + */ + Legend.prototype.render = function () { + var legend = this, chart = legend.chart, renderer = chart.renderer, legendGroup = legend.group, allItems, display, legendWidth, legendHeight, box = legend.box, options = legend.options, padding = legend.padding, allowedWidth; + legend.itemX = padding; + legend.itemY = legend.initialItemY; + legend.offsetWidth = 0; + legend.lastItemY = 0; + legend.widthOption = relativeLength(options.width, chart.spacingBox.width - padding); + // Compute how wide the legend is allowed to be + allowedWidth = + chart.spacingBox.width - 2 * padding - options.x; + if (['rm', 'lm'].indexOf(legend.getAlignment().substring(0, 2)) > -1) { + allowedWidth /= 2; + } + legend.maxLegendWidth = legend.widthOption || allowedWidth; + if (!legendGroup) { + /** + * SVG group of the legend. + * + * @readonly + * @name Highcharts.Legend#group + * @type {Highcharts.SVGElement} + */ + legend.group = legendGroup = renderer.g('legend') + .attr({ zIndex: 7 }) + .add(); + legend.contentGroup = renderer.g() + .attr({ zIndex: 1 }) // above background + .add(legendGroup); + legend.scrollGroup = renderer.g() + .add(legend.contentGroup); + } + legend.renderTitle(); + // add each series or point + allItems = legend.getAllItems(); + // sort by legendIndex + stableSort(allItems, function (a, b) { + return ((a.options && a.options.legendIndex) || 0) - + ((b.options && b.options.legendIndex) || 0); + }); + // reversed legend + if (options.reversed) { + allItems.reverse(); + } + /** + * All items for the legend, which is an array of series for most series + * and an array of points for pie series and its derivatives. + * + * @readonly + * @name Highcharts.Legend#allItems + * @type {Array<(Highcharts.Point|Highcharts.Series)>} + */ + legend.allItems = allItems; + legend.display = display = !!allItems.length; + // Render the items. First we run a loop to set the text and properties + // and read all the bounding boxes. The next loop computes the item + // positions based on the bounding boxes. + legend.lastLineHeight = 0; + legend.maxItemWidth = 0; + legend.totalItemWidth = 0; + legend.itemHeight = 0; + allItems.forEach(legend.renderItem, legend); + allItems.forEach(legend.layoutItem, legend); + // Get the box + legendWidth = (legend.widthOption || legend.offsetWidth) + padding; + legendHeight = legend.lastItemY + legend.lastLineHeight + + legend.titleHeight; + legendHeight = legend.handleOverflow(legendHeight); + legendHeight += padding; + // Draw the border and/or background + if (!box) { + /** + * SVG element of the legend box. + * + * @readonly + * @name Highcharts.Legend#box + * @type {Highcharts.SVGElement} + */ + legend.box = box = renderer.rect() + .addClass('highcharts-legend-box') + .attr({ + r: options.borderRadius + }) + .add(legendGroup); + box.isNew = true; + } + // Presentational + if (!chart.styledMode) { + box + .attr({ + stroke: options.borderColor, + 'stroke-width': options.borderWidth || 0, + fill: options.backgroundColor || 'none' + }) + .shadow(options.shadow); + } + if (legendWidth > 0 && legendHeight > 0) { + box[box.isNew ? 'attr' : 'animate'](box.crisp.call({}, { + x: 0, + y: 0, + width: legendWidth, + height: legendHeight + }, box.strokeWidth())); + box.isNew = false; + } + // hide the border if no items + box[display ? 'show' : 'hide'](); + // Open for responsiveness + if (chart.styledMode && legendGroup.getStyle('display') === 'none') { + legendWidth = legendHeight = 0; + } + legend.legendWidth = legendWidth; + legend.legendHeight = legendHeight; + if (display) { + legend.align(); + } + if (!this.proximate) { + this.positionItems(); + } + fireEvent(this, 'afterRender'); + }; + /** + * Align the legend to chart's box. + * + * @private + * @function Highcharts.align + * @param {Highcharts.BBoxObject} alignTo + * @return {void} + */ + Legend.prototype.align = function (alignTo) { + if (alignTo === void 0) { alignTo = this.chart.spacingBox; } + var chart = this.chart, options = this.options; + // If aligning to the top and the layout is horizontal, adjust for + // the title (#7428) + var y = alignTo.y; + if (/(lth|ct|rth)/.test(this.getAlignment()) && + chart.titleOffset[0] > 0) { + y += chart.titleOffset[0]; + } + else if (/(lbh|cb|rbh)/.test(this.getAlignment()) && + chart.titleOffset[2] > 0) { + y -= chart.titleOffset[2]; + } + if (y !== alignTo.y) { + alignTo = merge(alignTo, { y: y }); + } + this.group.align(merge(options, { + width: this.legendWidth, + height: this.legendHeight, + verticalAlign: this.proximate ? 'top' : options.verticalAlign + }), true, alignTo); + }; + /** + * Set up the overflow handling by adding navigation with up and down arrows + * below the legend. + * + * @private + * @function Highcharts.Legend#handleOverflow + * @param {number} legendHeight + * @return {number} + */ + Legend.prototype.handleOverflow = function (legendHeight) { + var legend = this, chart = this.chart, renderer = chart.renderer, options = this.options, optionsY = options.y, alignTop = options.verticalAlign === 'top', padding = this.padding, spaceHeight = (chart.spacingBox.height + + (alignTop ? -optionsY : optionsY) - padding), maxHeight = options.maxHeight, clipHeight, clipRect = this.clipRect, navOptions = options.navigation, animation = pick(navOptions.animation, true), arrowSize = navOptions.arrowSize || 12, nav = this.nav, pages = this.pages, lastY, allItems = this.allItems, clipToHeight = function (height) { + if (typeof height === 'number') { + clipRect.attr({ + height: height + }); + } + else if (clipRect) { // Reset (#5912) + legend.clipRect = clipRect.destroy(); + legend.contentGroup.clip(); + } + // useHTML + if (legend.contentGroup.div) { + legend.contentGroup.div.style.clip = height ? + 'rect(' + padding + 'px,9999px,' + + (padding + height) + 'px,0)' : + 'auto'; + } + }, addTracker = function (key) { + legend[key] = renderer + .circle(0, 0, arrowSize * 1.3) + .translate(arrowSize / 2, arrowSize / 2) + .add(nav); + if (!chart.styledMode) { + legend[key].attr('fill', 'rgba(0,0,0,0.0001)'); + } + return legend[key]; + }; + // Adjust the height + if (options.layout === 'horizontal' && + options.verticalAlign !== 'middle' && + !options.floating) { + spaceHeight /= 2; + } + if (maxHeight) { + spaceHeight = Math.min(spaceHeight, maxHeight); + } + // Reset the legend height and adjust the clipping rectangle + pages.length = 0; + if (legendHeight > spaceHeight && + navOptions.enabled !== false) { + this.clipHeight = clipHeight = + Math.max(spaceHeight - 20 - this.titleHeight - padding, 0); + this.currentPage = pick(this.currentPage, 1); + this.fullHeight = legendHeight; + // Fill pages with Y positions so that the top of each a legend item + // defines the scroll top for each page (#2098) + allItems.forEach(function (item, i) { + var y = item._legendItemPos[1], h = Math.round(item.legendItem.getBBox().height), len = pages.length; + if (!len || (y - pages[len - 1] > clipHeight && + (lastY || y) !== pages[len - 1])) { + pages.push(lastY || y); + len++; + } + // Keep track of which page each item is on + item.pageIx = len - 1; + if (lastY) { + allItems[i - 1].pageIx = len - 1; + } + if (i === allItems.length - 1 && + y + h - pages[len - 1] > clipHeight && + y !== lastY // #2617 + ) { + pages.push(y); + item.pageIx = len; + } + if (y !== lastY) { + lastY = y; + } + }); + // Only apply clipping if needed. Clipping causes blurred legend in + // PDF export (#1787) + if (!clipRect) { + clipRect = legend.clipRect = + renderer.clipRect(0, padding, 9999, 0); + legend.contentGroup.clip(clipRect); + } + clipToHeight(clipHeight); + // Add navigation elements + if (!nav) { + this.nav = nav = renderer.g() + .attr({ zIndex: 1 }) + .add(this.group); + this.up = renderer + .symbol('triangle', 0, 0, arrowSize, arrowSize) + .add(nav); + addTracker('upTracker') + .on('click', function () { + legend.scroll(-1, animation); + }); + this.pager = renderer.text('', 15, 10) + .addClass('highcharts-legend-navigation'); + if (!chart.styledMode) { + this.pager.css(navOptions.style); + } + this.pager.add(nav); + this.down = renderer + .symbol('triangle-down', 0, 0, arrowSize, arrowSize) + .add(nav); + addTracker('downTracker') + .on('click', function () { + legend.scroll(1, animation); + }); + } + // Set initial position + legend.scroll(0); + legendHeight = spaceHeight; + // Reset + } + else if (nav) { + clipToHeight(); + this.nav = nav.destroy(); // #6322 + this.scrollGroup.attr({ + translateY: 1 + }); + this.clipHeight = 0; // #1379 + } + return legendHeight; + }; + /** + * Scroll the legend by a number of pages. + * + * @private + * @function Highcharts.Legend#scroll + * + * @param {number} scrollBy + * The number of pages to scroll. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * Whether and how to apply animation. + * + * @return {void} + */ + Legend.prototype.scroll = function (scrollBy, animation) { + var _this = this; + var chart = this.chart, pages = this.pages, pageCount = pages.length, currentPage = this.currentPage + scrollBy, clipHeight = this.clipHeight, navOptions = this.options.navigation, pager = this.pager, padding = this.padding; + // When resizing while looking at the last page + if (currentPage > pageCount) { + currentPage = pageCount; + } + if (currentPage > 0) { + if (typeof animation !== 'undefined') { + setAnimation(animation, chart); + } + this.nav.attr({ + translateX: padding, + translateY: clipHeight + this.padding + 7 + this.titleHeight, + visibility: 'visible' + }); + [this.up, this.upTracker].forEach(function (elem) { + elem.attr({ + 'class': currentPage === 1 ? + 'highcharts-legend-nav-inactive' : + 'highcharts-legend-nav-active' + }); + }); + pager.attr({ + text: currentPage + '/' + pageCount + }); + [this.down, this.downTracker].forEach(function (elem) { + elem.attr({ + // adjust to text width + x: 18 + this.pager.getBBox().width, + 'class': currentPage === pageCount ? + 'highcharts-legend-nav-inactive' : + 'highcharts-legend-nav-active' + }); + }, this); + if (!chart.styledMode) { + this.up + .attr({ + fill: currentPage === 1 ? + navOptions.inactiveColor : + navOptions.activeColor + }); + this.upTracker + .css({ + cursor: currentPage === 1 ? 'default' : 'pointer' + }); + this.down + .attr({ + fill: currentPage === pageCount ? + navOptions.inactiveColor : + navOptions.activeColor + }); + this.downTracker + .css({ + cursor: currentPage === pageCount ? + 'default' : + 'pointer' + }); + } + this.scrollOffset = -pages[currentPage - 1] + this.initialItemY; + this.scrollGroup.animate({ + translateY: this.scrollOffset + }); + this.currentPage = currentPage; + this.positionCheckboxes(); + // Fire event after scroll animation is complete + var animOptions = animObject(pick(animation, chart.renderer.globalAnimation, true)); + syncTimeout(function () { + fireEvent(_this, 'afterScroll', { currentPage: currentPage }); + }, animOptions.duration || 0); + } + }; + return Legend; + }()); + // Workaround for #2030, horizontal legend items not displaying in IE11 Preview, + // and for #2580, a similar drawing flaw in Firefox 26. + // Explore if there's a general cause for this. The problem may be related + // to nested group elements, as the legend item texts are within 4 group + // elements. + if (/Trident\/7\.0/.test(win.navigator && win.navigator.userAgent) || + isFirefox) { + wrap(Legend.prototype, 'positionItem', function (proceed, item) { + var legend = this, + // If chart destroyed in sync, this is undefined (#2030) + runPositionItem = function () { + if (item._legendItemPos) { + proceed.call(legend, item); + } + }; + // Do it now, for export and to get checkbox placement + runPositionItem(); + // Do it after to work around the core issue + if (!legend.bubbleLegend) { + setTimeout(runPositionItem); + } + }); + } + H.Legend = Legend; + + return H.Legend; + }); + _registerModule(_modules, 'parts/Chart.js', [_modules['parts/Globals.js'], _modules['parts/Legend.js'], _modules['parts/MSPointer.js'], _modules['parts/Pointer.js'], _modules['parts/Time.js'], _modules['parts/Utilities.js']], function (H, Legend, MSPointer, Pointer, Time, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Callback for chart constructors. + * + * @callback Highcharts.ChartCallbackFunction + * + * @param {Highcharts.Chart} chart + * Created chart. + */ + /** + * Format a number and return a string based on input settings. + * + * @callback Highcharts.NumberFormatterCallbackFunction + * + * @param {number} number + * The input number to format. + * + * @param {number} decimals + * The amount of decimals. A value of -1 preserves the amount in the + * input number. + * + * @param {string} [decimalPoint] + * The decimal point, defaults to the one given in the lang options, or + * a dot. + * + * @param {string} [thousandsSep] + * The thousands separator, defaults to the one given in the lang + * options, or a space character. + * + * @return {string} The formatted number. + */ + /** + * The chart title. The title has an `update` method that allows modifying the + * options directly or indirectly via `chart.update`. + * + * @interface Highcharts.TitleObject + * @extends Highcharts.SVGElement + */ /** + * Modify options for the title. + * + * @function Highcharts.TitleObject#update + * + * @param {Highcharts.TitleOptions} titleOptions + * Options to modify. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the title is altered. If doing more + * operations on the chart, it is a good idea to set redraw to false and + * call {@link Chart#redraw} after. + */ + /** + * The chart subtitle. The subtitle has an `update` method that + * allows modifying the options directly or indirectly via + * `chart.update`. + * + * @interface Highcharts.SubtitleObject + * @extends Highcharts.SVGElement + */ /** + * Modify options for the subtitle. + * + * @function Highcharts.SubtitleObject#update + * + * @param {Highcharts.SubtitleOptions} subtitleOptions + * Options to modify. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the subtitle is altered. If doing + * more operations on the chart, it is a good idea to set redraw to false + * and call {@link Chart#redraw} after. + */ + /** + * The chart caption. The caption has an `update` method that + * allows modifying the options directly or indirectly via + * `chart.update`. + * + * @interface Highcharts.CaptionObject + * @extends Highcharts.SVGElement + */ /** + * Modify options for the caption. + * + * @function Highcharts.CaptionObject#update + * + * @param {Highcharts.CaptionOptions} captionOptions + * Options to modify. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the caption is altered. If doing + * more operations on the chart, it is a good idea to set redraw to false + * and call {@link Chart#redraw} after. + */ + var addEvent = U.addEvent, animate = U.animate, animObject = U.animObject, attr = U.attr, createElement = U.createElement, css = U.css, defined = U.defined, discardElement = U.discardElement, erase = U.erase, error = U.error, extend = U.extend, find = U.find, fireEvent = U.fireEvent, getStyle = U.getStyle, isArray = U.isArray, isFunction = U.isFunction, isNumber = U.isNumber, isObject = U.isObject, isString = U.isString, merge = U.merge, numberFormat = U.numberFormat, objectEach = U.objectEach, pick = U.pick, pInt = U.pInt, relativeLength = U.relativeLength, removeEvent = U.removeEvent, setAnimation = U.setAnimation, splat = U.splat, syncTimeout = U.syncTimeout, uniqueKey = U.uniqueKey; + var doc = H.doc, Axis = H.Axis, // @todo add as requirement + defaultOptions = H.defaultOptions, charts = H.charts, marginNames = H.marginNames, seriesTypes = H.seriesTypes, win = H.win; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The Chart class. The recommended constructor is {@link Highcharts#chart}. + * + * @example + * var chart = Highcharts.chart('container', { + * title: { + * text: 'My chart' + * }, + * series: [{ + * data: [1, 3, 2, 4] + * }] + * }) + * + * @class + * @name Highcharts.Chart + * + * @param {string|Highcharts.HTMLDOMElement} [renderTo] + * The DOM element to render to, or its id. + * + * @param {Highcharts.Options} options + * The chart options structure. + * + * @param {Highcharts.ChartCallbackFunction} [callback] + * Function to run when the chart has loaded and and all external images + * are loaded. Defining a + * [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load) + * handler is equivalent. + */ + var Chart = H.Chart = function () { + this.getArgs.apply(this, arguments); + }; + /** + * Factory function for basic charts. + * + * @example + * // Render a chart in to div#container + * var chart = Highcharts.chart('container', { + * title: { + * text: 'My chart' + * }, + * series: [{ + * data: [1, 3, 2, 4] + * }] + * }); + * + * @function Highcharts.chart + * + * @param {string|Highcharts.HTMLDOMElement} [renderTo] + * The DOM element to render to, or its id. + * + * @param {Highcharts.Options} options + * The chart options structure. + * + * @param {Highcharts.ChartCallbackFunction} [callback] + * Function to run when the chart has loaded and and all external images + * are loaded. Defining a + * [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load) + * handler is equivalent. + * + * @return {Highcharts.Chart} + * Returns the Chart object. + */ + H.chart = function (a, b, c) { + return new Chart(a, b, c); + }; + extend(Chart.prototype, /** @lends Highcharts.Chart.prototype */ { + // Hook for adding callbacks in modules + callbacks: [], + /** + * Handle the arguments passed to the constructor. + * + * @private + * @function Highcharts.Chart#getArgs + * + * @param {...Array<*>} arguments + * All arguments for the constructor. + * + * @return {Array<*>} + * Passed arguments without renderTo. + * + * @fires Highcharts.Chart#event:init + * @fires Highcharts.Chart#event:afterInit + */ + getArgs: function () { + var args = [].slice.call(arguments); + // Remove the optional first argument, renderTo, and + // set it on this. + if (isString(args[0]) || args[0].nodeName) { + this.renderTo = args.shift(); + } + this.init(args[0], args[1]); + }, + /** + * Overridable function that initializes the chart. The constructor's + * arguments are passed on directly. + * + * @function Highcharts.Chart#init + * + * @param {Highcharts.Options} userOptions + * Custom options. + * + * @param {Function} [callback] + * Function to run when the chart has loaded and and all external + * images are loaded. + * + * @return {void} + * + * @fires Highcharts.Chart#event:init + * @fires Highcharts.Chart#event:afterInit + */ + init: function (userOptions, callback) { + // Handle regular options + var options, + // skip merging data points to increase performance + seriesOptions = userOptions.series, userPlotOptions = userOptions.plotOptions || {}; + // Fire the event with a default function + fireEvent(this, 'init', { args: arguments }, function () { + userOptions.series = null; + options = merge(defaultOptions, userOptions); // do the merge + var optionsChart = options.chart || {}; + // Override (by copy of user options) or clear tooltip options + // in chart.options.plotOptions (#6218) + objectEach(options.plotOptions, function (typeOptions, type) { + if (isObject(typeOptions)) { // #8766 + typeOptions.tooltip = (userPlotOptions[type] && // override by copy: + merge(userPlotOptions[type].tooltip)) || void 0; // or clear + } + }); + // User options have higher priority than default options + // (#6218). In case of exporting: path is changed + options.tooltip.userOptions = (userOptions.chart && + userOptions.chart.forExport && + userOptions.tooltip.userOptions) || userOptions.tooltip; + // set back the series data + options.series = userOptions.series = seriesOptions; + /** + * The original options given to the constructor or a chart factory + * like {@link Highcharts.chart} and {@link Highcharts.stockChart}. + * + * @name Highcharts.Chart#userOptions + * @type {Highcharts.Options} + */ + this.userOptions = userOptions; + var chartEvents = optionsChart.events; + this.margin = []; + this.spacing = []; + // Pixel data bounds for touch zoom + this.bounds = { h: {}, v: {} }; + // An array of functions that returns labels that should be + // considered for anti-collision + this.labelCollectors = []; + this.callback = callback; + this.isResizing = 0; + /** + * The options structure for the chart after merging + * {@link #defaultOptions} and {@link #userOptions}. It contains + * members for the sub elements like series, legend, tooltip etc. + * + * @name Highcharts.Chart#options + * @type {Highcharts.Options} + */ + this.options = options; + /** + * All the axes in the chart. + * + * @see Highcharts.Chart.xAxis + * @see Highcharts.Chart.yAxis + * + * @name Highcharts.Chart#axes + * @type {Array} + */ + this.axes = []; + /** + * All the current series in the chart. + * + * @name Highcharts.Chart#series + * @type {Array} + */ + this.series = []; + /** + * The `Time` object associated with the chart. Since v6.0.5, + * time settings can be applied individually for each chart. If + * no individual settings apply, the `Time` object is shared by + * all instances. + * + * @name Highcharts.Chart#time + * @type {Highcharts.Time} + */ + this.time = + userOptions.time && Object.keys(userOptions.time).length ? + new Time(userOptions.time) : + H.time; + /** + * Callback function to override the default function that formats + * all the numbers in the chart. Returns a string with the formatted + * number. + * + * @name Highcharts.Chart#numberFormatter + * @type {Highcharts.NumberFormatterCallbackFunction} + */ + this.numberFormatter = optionsChart.numberFormatter || numberFormat; + /** + * Whether the chart is in styled mode, meaning all presentatinoal + * attributes are avoided. + * + * @name Highcharts.Chart#styledMode + * @type {boolean} + */ + this.styledMode = optionsChart.styledMode; + this.hasCartesianSeries = optionsChart.showAxes; + var chart = this; + /** + * Index position of the chart in the {@link Highcharts#charts} + * property. + * + * @name Highcharts.Chart#index + * @type {number} + * @readonly + */ + chart.index = charts.length; // Add the chart to the global lookup + charts.push(chart); + H.chartCount++; + // Chart event handlers + if (chartEvents) { + objectEach(chartEvents, function (event, eventType) { + if (isFunction(event)) { + addEvent(chart, eventType, event); + } + }); + } + /** + * A collection of the X axes in the chart. + * + * @name Highcharts.Chart#xAxis + * @type {Array} + */ + chart.xAxis = []; + /** + * A collection of the Y axes in the chart. + * + * @name Highcharts.Chart#yAxis + * @type {Array} + * + * @todo + * Make events official: Fire the event `afterInit`. + */ + chart.yAxis = []; + chart.pointCount = chart.colorCounter = chart.symbolCounter = 0; + // Fire after init but before first render, before axes and series + // have been initialized. + fireEvent(chart, 'afterInit'); + chart.firstRender(); + }); + }, + /** + * Internal function to unitialize an individual series. + * + * @private + * @function Highcharts.Chart#initSeries + * + * @param {Highcharts.SeriesOptions} options + * + * @return {Highcharts.Series} + */ + initSeries: function (options) { + var chart = this, optionsChart = chart.options.chart, type = (options.type || + optionsChart.type || + optionsChart.defaultSeriesType), series, Constr = seriesTypes[type]; + // No such series type + if (!Constr) { + error(17, true, chart, { missingModuleFor: type }); + } + series = new Constr(); + series.init(this, options); + return series; + }, + /** + * Internal function to set data for all series with enabled sorting. + * + * @private + * @function Highcharts.Chart#setSeriesData + * + * @param {Highcharts.SeriesOptions} options + * + * @return {void} + */ + setSeriesData: function () { + this.getSeriesOrderByLinks().forEach(function (series) { + // We need to set data for series with sorting after series init + if (!series.points && !series.data && series.enabledDataSorting) { + series.setData(series.options.data, false); + } + }); + }, + /** + * Sort and return chart series in order depending on the number of linked + * series. + * + * @private + * @function Highcharts.Series#getSeriesOrderByLinks + * + * @return {Array} + */ + getSeriesOrderByLinks: function () { + return this.series.concat().sort(function (a, b) { + if (a.linkedSeries.length || b.linkedSeries.length) { + return b.linkedSeries.length - a.linkedSeries.length; + } + return 0; + }); + }, + /** + * Order all series above a given index. When series are added and ordered + * by configuration, only the last series is handled (#248, #1123, #2456, + * #6112). This function is called on series initialization and destroy. + * + * @private + * @function Highcharts.Series#orderSeries + * @param {number} [fromIndex] + * If this is given, only the series above this index are handled. + * @return {void} + */ + orderSeries: function (fromIndex) { + var series = this.series, i = fromIndex || 0; + for (; i < series.length; i++) { + if (series[i]) { + /** + * Contains the series' index in the `Chart.series` array. + * + * @name Highcharts.Series#index + * @type {number} + * @readonly + */ + series[i].index = i; + series[i].name = series[i].getName(); + } + } + }, + /** + * Check whether a given point is within the plot area. + * + * @function Highcharts.Chart#isInsidePlot + * + * @param {number} plotX + * Pixel x relative to the plot area. + * + * @param {number} plotY + * Pixel y relative to the plot area. + * + * @param {boolean} [inverted] + * Whether the chart is inverted. + * + * @return {boolean} + * Returns true if the given point is inside the plot area. + */ + isInsidePlot: function (plotX, plotY, inverted) { + var x = inverted ? plotY : plotX, y = inverted ? plotX : plotY, e = { + x: x, + y: y, + isInsidePlot: x >= 0 && + x <= this.plotWidth && + y >= 0 && + y <= this.plotHeight + }; + fireEvent(this, 'afterIsInsidePlot', e); + return e.isInsidePlot; + }, + /** + * Redraw the chart after changes have been done to the data, axis extremes + * chart size or chart elements. All methods for updating axes, series or + * points have a parameter for redrawing the chart. This is `true` by + * default. But in many cases you want to do more than one operation on the + * chart before redrawing, for example add a number of points. In those + * cases it is a waste of resources to redraw the chart for each new point + * added. So you add the points and call `chart.redraw()` after. + * + * @function Highcharts.Chart#redraw + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * If or how to apply animation to the redraw. + * + * @return {void} + * + * @fires Highcharts.Chart#event:afterSetExtremes + * @fires Highcharts.Chart#event:beforeRedraw + * @fires Highcharts.Chart#event:predraw + * @fires Highcharts.Chart#event:redraw + * @fires Highcharts.Chart#event:render + * @fires Highcharts.Chart#event:updatedData + */ + redraw: function (animation) { + fireEvent(this, 'beforeRedraw'); + var chart = this, axes = chart.axes, series = chart.series, pointer = chart.pointer, legend = chart.legend, legendUserOptions = chart.userOptions.legend, redrawLegend = chart.isDirtyLegend, hasStackedSeries, hasDirtyStacks, hasCartesianSeries = chart.hasCartesianSeries, isDirtyBox = chart.isDirtyBox, i, serie, renderer = chart.renderer, isHiddenChart = renderer.isHidden(), afterRedraw = []; + // Handle responsive rules, not only on resize (#6130) + if (chart.setResponsive) { + chart.setResponsive(false); + } + // Set the global animation. When chart.hasRendered is not true, the + // redraw call comes from a responsive rule and animation should not + // occur. + setAnimation(chart.hasRendered ? animation : false, chart); + if (isHiddenChart) { + chart.temporaryDisplay(); + } + // Adjust title layout (reflow multiline text) + chart.layOutTitles(); + // link stacked series + i = series.length; + while (i--) { + serie = series[i]; + if (serie.options.stacking) { + hasStackedSeries = true; + if (serie.isDirty) { + hasDirtyStacks = true; + break; + } + } + } + if (hasDirtyStacks) { // mark others as dirty + i = series.length; + while (i--) { + serie = series[i]; + if (serie.options.stacking) { + serie.isDirty = true; + } + } + } + // Handle updated data in the series + series.forEach(function (serie) { + if (serie.isDirty) { + if (serie.options.legendType === 'point') { + if (serie.updateTotals) { + serie.updateTotals(); + } + redrawLegend = true; + } + else if (legendUserOptions && + (legendUserOptions.labelFormatter || + legendUserOptions.labelFormat)) { + redrawLegend = true; // #2165 + } + } + if (serie.isDirtyData) { + fireEvent(serie, 'updatedData'); + } + }); + // handle added or removed series + if (redrawLegend && legend && legend.options.enabled) { + // draw legend graphics + legend.render(); + chart.isDirtyLegend = false; + } + // reset stacks + if (hasStackedSeries) { + chart.getStacks(); + } + if (hasCartesianSeries) { + // set axes scales + axes.forEach(function (axis) { + axis.updateNames(); + axis.setScale(); + }); + } + chart.getMargins(); // #3098 + if (hasCartesianSeries) { + // If one axis is dirty, all axes must be redrawn (#792, #2169) + axes.forEach(function (axis) { + if (axis.isDirty) { + isDirtyBox = true; + } + }); + // redraw axes + axes.forEach(function (axis) { + // Fire 'afterSetExtremes' only if extremes are set + var key = axis.min + ',' + axis.max; + if (axis.extKey !== key) { // #821, #4452 + axis.extKey = key; + // prevent a recursive call to chart.redraw() (#1119) + afterRedraw.push(function () { + fireEvent(axis, 'afterSetExtremes', extend(axis.eventArgs, axis.getExtremes())); // #747, #751 + delete axis.eventArgs; + }); + } + if (isDirtyBox || hasStackedSeries) { + axis.redraw(); + } + }); + } + // the plot areas size has changed + if (isDirtyBox) { + chart.drawChartBox(); + } + // Fire an event before redrawing series, used by the boost module to + // clear previous series renderings. + fireEvent(chart, 'predraw'); + // redraw affected series + series.forEach(function (serie) { + if ((isDirtyBox || serie.isDirty) && serie.visible) { + serie.redraw(); + } + // Set it here, otherwise we will have unlimited 'updatedData' calls + // for a hidden series after setData(). Fixes #6012 + serie.isDirtyData = false; + }); + // move tooltip or reset + if (pointer) { + pointer.reset(true); + } + // redraw if canvas + renderer.draw(); + // Fire the events + fireEvent(chart, 'redraw'); + fireEvent(chart, 'render'); + if (isHiddenChart) { + chart.temporaryDisplay(true); + } + // Fire callbacks that are put on hold until after the redraw + afterRedraw.forEach(function (callback) { + callback.call(); + }); + }, + /** + * Get an axis, series or point object by `id` as given in the configuration + * options. Returns `undefined` if no item is found. + * + * @sample highcharts/plotoptions/series-id/ + * Get series by id + * + * @function Highcharts.Chart#get + * + * @param {string} id + * The id as given in the configuration options. + * + * @return {Highcharts.Axis|Highcharts.Series|Highcharts.Point|undefined} + * The retrieved item. + */ + get: function (id) { + var ret, series = this.series, i; + /** + * @private + * @param {Highcharts.Axis|Highcharts.Series} item + * @return {boolean} + */ + function itemById(item) { + return (item.id === id || + (item.options && item.options.id === id)); + } + ret = + // Search axes + find(this.axes, itemById) || + // Search series + find(this.series, itemById); + // Search points + for (i = 0; !ret && i < series.length; i++) { + ret = find(series[i].points || [], itemById); + } + return ret; + }, + /** + * Create the Axis instances based on the config options. + * + * @private + * @function Highcharts.Chart#getAxes + * + * @return {void} + * + * @fires Highcharts.Chart#event:afterGetAxes + * @fires Highcharts.Chart#event:getAxes + */ + getAxes: function () { + var chart = this, options = this.options, xAxisOptions = options.xAxis = splat(options.xAxis || {}), yAxisOptions = options.yAxis = splat(options.yAxis || {}), optionsArray; + fireEvent(this, 'getAxes'); + // make sure the options are arrays and add some members + xAxisOptions.forEach(function (axis, i) { + axis.index = i; + axis.isX = true; + }); + yAxisOptions.forEach(function (axis, i) { + axis.index = i; + }); + // concatenate all axis options into one array + optionsArray = xAxisOptions.concat(yAxisOptions); + optionsArray.forEach(function (axisOptions) { + new Axis(chart, axisOptions); // eslint-disable-line no-new + }); + fireEvent(this, 'afterGetAxes'); + }, + /** + * Returns an array of all currently selected points in the chart. Points + * can be selected by clicking or programmatically by the + * {@link Highcharts.Point#select} + * function. + * + * @sample highcharts/plotoptions/series-allowpointselect-line/ + * Get selected points + * + * @function Highcharts.Chart#getSelectedPoints + * + * @return {Array} + * The currently selected points. + */ + getSelectedPoints: function () { + var points = []; + this.series.forEach(function (serie) { + // For one-to-one points inspect series.data in order to retrieve + // points outside the visible range (#6445). For grouped data, + // inspect the generated series.points. + points = points.concat(serie.getPointsCollection().filter(function (point) { + return pick(point.selectedStaging, point.selected); + })); + }); + return points; + }, + /** + * Returns an array of all currently selected series in the chart. Series + * can be selected either programmatically by the + * {@link Highcharts.Series#select} + * function or by checking the checkbox next to the legend item if + * [series.showCheckBox](https://api.highcharts.com/highcharts/plotOptions.series.showCheckbox) + * is true. + * + * @sample highcharts/members/chart-getselectedseries/ + * Get selected series + * + * @function Highcharts.Chart#getSelectedSeries + * + * @return {Array} + * The currently selected series. + */ + getSelectedSeries: function () { + return this.series.filter(function (serie) { + return serie.selected; + }); + }, + /** + * Set a new title or subtitle for the chart. + * + * @sample highcharts/members/chart-settitle/ + * Set title text and styles + * + * @function Highcharts.Chart#setTitle + * + * @param {Highcharts.TitleOptions} [titleOptions] + * New title options. The title text itself is set by the + * `titleOptions.text` property. + * + * @param {Highcharts.SubtitleOptions} [subtitleOptions] + * New subtitle options. The subtitle text itself is set by the + * `subtitleOptions.text` property. + * + * @param {boolean} [redraw] + * Whether to redraw the chart or wait for a later call to + * `chart.redraw()`. + * + * @return {void} + */ + setTitle: function (titleOptions, subtitleOptions, redraw) { + this.applyDescription('title', titleOptions); + this.applyDescription('subtitle', subtitleOptions); + // The initial call also adds the caption. On update, chart.update will + // relay to Chart.setCaption. + this.applyDescription('caption', void 0); + this.layOutTitles(redraw); + }, + /** + * Apply a title, subtitle or caption for the chart + * + * @private + * @function Highcharts.Chart#applyDescription + * + * @param name {string} + * Either title, subtitle or caption + * @param {Highcharts.TitleOptions|Highcharts.SubtitleOptions|Highcharts.CaptionOptions|undefined} explicitOptions + * The options to set, will be merged with default options. + * + * @return {void} + */ + applyDescription: function (name, explicitOptions) { + var chart = this; + // Default style + var style = name === 'title' ? { + color: '#333333', + fontSize: this.options.isStock ? '16px' : '18px' // #2944 + } : { + color: '#666666' + }; + // Merge default options with explicit options + var options = this.options[name] = merge( + // Default styles + (!this.styledMode && { style: style }), this.options[name], explicitOptions); + var elem = this[name]; + if (elem && explicitOptions) { + this[name] = elem = elem.destroy(); // remove old + } + if (options && !elem) { + elem = this.renderer.text(options.text, 0, 0, options.useHTML) + .attr({ + align: options.align, + 'class': 'highcharts-' + name, + zIndex: options.zIndex || 4 + }) + .add(); + // Update methods, shortcut to Chart.setTitle, Chart.setSubtitle and + // Chart.setCaption + elem.update = function (updateOptions) { + var fn = { + title: 'setTitle', + subtitle: 'setSubtitle', + caption: 'setCaption' + }[name]; + chart[fn](updateOptions); + }; + // Presentational + if (!this.styledMode) { + elem.css(options.style); + } + /** + * The chart title. The title has an `update` method that allows + * modifying the options directly or indirectly via + * `chart.update`. + * + * @sample highcharts/members/title-update/ + * Updating titles + * + * @name Highcharts.Chart#title + * @type {Highcharts.TitleObject} + */ + /** + * The chart subtitle. The subtitle has an `update` method that + * allows modifying the options directly or indirectly via + * `chart.update`. + * + * @name Highcharts.Chart#subtitle + * @type {Highcharts.SubtitleObject} + */ + this[name] = elem; + } + }, + /** + * Internal function to lay out the chart title, subtitle and caption, and + * cache the full offset height for use in `getMargins`. The result is + * stored in `this.titleOffset`. + * + * @private + * @function Highcharts.Chart#layOutTitles + * + * @param {boolean} [redraw=true] + * + * @return {void} + * + * @fires Highcharts.Chart#event:afterLayOutTitles + */ + layOutTitles: function (redraw) { + var titleOffset = [0, 0, 0], requiresDirtyBox, renderer = this.renderer, spacingBox = this.spacingBox; + // Lay out the title and the subtitle respectively + ['title', 'subtitle', 'caption'].forEach(function (key) { + var title = this[key], titleOptions = this.options[key], verticalAlign = titleOptions.verticalAlign || 'top', offset = key === 'title' ? -3 : + // Floating subtitle (#6574) + verticalAlign === 'top' ? titleOffset[0] + 2 : 0, titleSize, height; + if (title) { + if (!this.styledMode) { + titleSize = titleOptions.style.fontSize; + } + titleSize = renderer.fontMetrics(titleSize, title).b; + title + .css({ + width: (titleOptions.width || + spacingBox.width + (titleOptions.widthAdjust || 0)) + 'px' + }); + // Skip the cache for HTML (#3481, #11666) + height = Math.round(title.getBBox(titleOptions.useHTML).height); + title.align(extend({ + y: verticalAlign === 'bottom' ? + titleSize : + offset + titleSize, + height: height + }, titleOptions), false, 'spacingBox'); + if (!titleOptions.floating) { + if (verticalAlign === 'top') { + titleOffset[0] = Math.ceil(titleOffset[0] + + height); + } + else if (verticalAlign === 'bottom') { + titleOffset[2] = Math.ceil(titleOffset[2] + + height); + } + } + } + }, this); + // Handle title.margin and caption.margin + if (titleOffset[0] && + (this.options.title.verticalAlign || 'top') === 'top') { + titleOffset[0] += this.options.title.margin; + } + if (titleOffset[2] && + this.options.caption.verticalAlign === 'bottom') { + titleOffset[2] += this.options.caption.margin; + } + requiresDirtyBox = (!this.titleOffset || + this.titleOffset.join(',') !== titleOffset.join(',')); + // Used in getMargins + this.titleOffset = titleOffset; + fireEvent(this, 'afterLayOutTitles'); + if (!this.isDirtyBox && requiresDirtyBox) { + this.isDirtyBox = this.isDirtyLegend = requiresDirtyBox; + // Redraw if necessary (#2719, #2744) + if (this.hasRendered && pick(redraw, true) && this.isDirtyBox) { + this.redraw(); + } + } + }, + /** + * Internal function to get the chart width and height according to options + * and container size. Sets {@link Chart.chartWidth} and + * {@link Chart.chartHeight}. + * + * @private + * @function Highcharts.Chart#getChartSize + * + * @return {void} + */ + getChartSize: function () { + var chart = this, optionsChart = chart.options.chart, widthOption = optionsChart.width, heightOption = optionsChart.height, renderTo = chart.renderTo; + // Get inner width and height + if (!defined(widthOption)) { + chart.containerWidth = getStyle(renderTo, 'width'); + } + if (!defined(heightOption)) { + chart.containerHeight = getStyle(renderTo, 'height'); + } + /** + * The current pixel width of the chart. + * + * @name Highcharts.Chart#chartWidth + * @type {number} + */ + chart.chartWidth = Math.max(// #1393 + 0, widthOption || chart.containerWidth || 600 // #1460 + ); + /** + * The current pixel height of the chart. + * + * @name Highcharts.Chart#chartHeight + * @type {number} + */ + chart.chartHeight = Math.max(0, relativeLength(heightOption, chart.chartWidth) || + (chart.containerHeight > 1 ? + chart.containerHeight : + 400)); + }, + /** + * If the renderTo element has no offsetWidth, most likely one or more of + * its parents are hidden. Loop up the DOM tree to temporarily display the + * parents, then save the original display properties, and when the true + * size is retrieved, reset them. Used on first render and on redraws. + * + * @private + * @function Highcharts.Chart#temporaryDisplay + * + * @param {boolean} [revert] + * Revert to the saved original styles. + * + * @return {void} + */ + temporaryDisplay: function (revert) { + var node = this.renderTo, tempStyle; + if (!revert) { + while (node && node.style) { + // When rendering to a detached node, it needs to be temporarily + // attached in order to read styling and bounding boxes (#5783, + // #7024). + if (!doc.body.contains(node) && !node.parentNode) { + node.hcOrigDetached = true; + doc.body.appendChild(node); + } + if (getStyle(node, 'display', false) === 'none' || + node.hcOricDetached) { + node.hcOrigStyle = { + display: node.style.display, + height: node.style.height, + overflow: node.style.overflow + }; + tempStyle = { + display: 'block', + overflow: 'hidden' + }; + if (node !== this.renderTo) { + tempStyle.height = 0; + } + css(node, tempStyle); + // If it still doesn't have an offset width after setting + // display to block, it probably has an !important priority + // #2631, 6803 + if (!node.offsetWidth) { + node.style.setProperty('display', 'block', 'important'); + } + } + node = node.parentNode; + if (node === doc.body) { + break; + } + } + } + else { + while (node && node.style) { + if (node.hcOrigStyle) { + css(node, node.hcOrigStyle); + delete node.hcOrigStyle; + } + if (node.hcOrigDetached) { + doc.body.removeChild(node); + node.hcOrigDetached = false; + } + node = node.parentNode; + } + } + }, + /** + * Set the {@link Chart.container|chart container's} class name, in + * addition to `highcharts-container`. + * + * @function Highcharts.Chart#setClassName + * + * @param {string} [className] + * + * @return {void} + */ + setClassName: function (className) { + this.container.className = 'highcharts-container ' + (className || ''); + }, + /** + * Get the containing element, determine the size and create the inner + * container div to hold the chart. + * + * @private + * @function Highcharts.Chart#afterGetContainer + * + * @return {void} + * + * @fires Highcharts.Chart#event:afterGetContainer + */ + getContainer: function () { + var chart = this, container, options = chart.options, optionsChart = options.chart, chartWidth, chartHeight, renderTo = chart.renderTo, indexAttrName = 'data-highcharts-chart', oldChartIndex, Ren, containerId = uniqueKey(), containerStyle, key; + if (!renderTo) { + chart.renderTo = renderTo = + optionsChart.renderTo; + } + if (isString(renderTo)) { + chart.renderTo = renderTo = + doc.getElementById(renderTo); + } + // Display an error if the renderTo is wrong + if (!renderTo) { + error(13, true, chart); + } + // If the container already holds a chart, destroy it. The check for + // hasRendered is there because web pages that are saved to disk from + // the browser, will preserve the data-highcharts-chart attribute and + // the SVG contents, but not an interactive chart. So in this case, + // charts[oldChartIndex] will point to the wrong chart if any (#2609). + oldChartIndex = pInt(attr(renderTo, indexAttrName)); + if (isNumber(oldChartIndex) && + charts[oldChartIndex] && + charts[oldChartIndex].hasRendered) { + charts[oldChartIndex].destroy(); + } + // Make a reference to the chart from the div + attr(renderTo, indexAttrName, chart.index); + // remove previous chart + renderTo.innerHTML = ''; + // If the container doesn't have an offsetWidth, it has or is a child of + // a node that has display:none. We need to temporarily move it out to a + // visible state to determine the size, else the legend and tooltips + // won't render properly. The skipClone option is used in sparklines as + // a micro optimization, saving about 1-2 ms each chart. + if (!optionsChart.skipClone && !renderTo.offsetWidth) { + chart.temporaryDisplay(); + } + // get the width and height + chart.getChartSize(); + chartWidth = chart.chartWidth; + chartHeight = chart.chartHeight; + // Allow table cells and flex-boxes to shrink without the chart blocking + // them out (#6427) + css(renderTo, { overflow: 'hidden' }); + // Create the inner container + if (!chart.styledMode) { + containerStyle = extend({ + position: 'relative', + // needed for context menu (avoidscrollbars) and content + // overflow in IE + overflow: 'hidden', + width: chartWidth + 'px', + height: chartHeight + 'px', + textAlign: 'left', + lineHeight: 'normal', + zIndex: 0, + '-webkit-tap-highlight-color': 'rgba(0,0,0,0)' + }, optionsChart.style); + } + /** + * The containing HTML element of the chart. The container is + * dynamically inserted into the element given as the `renderTo` + * parameter in the {@link Highcharts#chart} constructor. + * + * @name Highcharts.Chart#container + * @type {Highcharts.HTMLDOMElement} + */ + container = createElement('div', { + id: containerId + }, containerStyle, renderTo); + chart.container = container; + // cache the cursor (#1650) + chart._cursor = container.style.cursor; + // Initialize the renderer + Ren = H[optionsChart.renderer] || H.Renderer; + /** + * The renderer instance of the chart. Each chart instance has only one + * associated renderer. + * + * @name Highcharts.Chart#renderer + * @type {Highcharts.SVGRenderer} + */ + chart.renderer = new Ren(container, chartWidth, chartHeight, null, optionsChart.forExport, options.exporting && options.exporting.allowHTML, chart.styledMode); + // Set the initial animation from the options + setAnimation(void 0, chart); + chart.setClassName(optionsChart.className); + if (!chart.styledMode) { + chart.renderer.setStyle(optionsChart.style); + } + else { + // Initialize definitions + for (key in options.defs) { // eslint-disable-line guard-for-in + this.renderer.definition(options.defs[key]); + } + } + // Add a reference to the charts index + chart.renderer.chartIndex = chart.index; + fireEvent(this, 'afterGetContainer'); + }, + /** + * Calculate margins by rendering axis labels in a preliminary position. + * Title, subtitle and legend have already been rendered at this stage, but + * will be moved into their final positions. + * + * @private + * @function Highcharts.Chart#getMargins + * @param {boolean} skipAxes + * @return {void} + * @fires Highcharts.Chart#event:getMargins + */ + getMargins: function (skipAxes) { + var _a = this, spacing = _a.spacing, margin = _a.margin, titleOffset = _a.titleOffset; + this.resetMargins(); + // Adjust for title and subtitle + if (titleOffset[0] && !defined(margin[0])) { + this.plotTop = Math.max(this.plotTop, titleOffset[0] + spacing[0]); + } + if (titleOffset[2] && !defined(margin[2])) { + this.marginBottom = Math.max(this.marginBottom, titleOffset[2] + spacing[2]); + } + // Adjust for legend + if (this.legend && this.legend.display) { + this.legend.adjustMargins(margin, spacing); + } + fireEvent(this, 'getMargins'); + if (!skipAxes) { + this.getAxisMargins(); + } + }, + /** + * @private + * @function Highcharts.Chart#getAxisMargins + * @return {void} + */ + getAxisMargins: function () { + var chart = this, + // [top, right, bottom, left] + axisOffset = chart.axisOffset = [0, 0, 0, 0], colorAxis = chart.colorAxis, margin = chart.margin, getOffset = function (axes) { + axes.forEach(function (axis) { + if (axis.visible) { + axis.getOffset(); + } + }); + }; + // pre-render axes to get labels offset width + if (chart.hasCartesianSeries) { + getOffset(chart.axes); + } + else if (colorAxis && colorAxis.length) { + getOffset(colorAxis); + } + // Add the axis offsets + marginNames.forEach(function (m, side) { + if (!defined(margin[side])) { + chart[m] += axisOffset[side]; + } + }); + chart.setChartSize(); + }, + /** + * Reflows the chart to its container. By default, the chart reflows + * automatically to its container following a `window.resize` event, as per + * the [chart.reflow](https://api.highcharts.com/highcharts/chart.reflow) + * option. However, there are no reliable events for div resize, so if the + * container is resized without a window resize event, this must be called + * explicitly. + * + * @sample highcharts/members/chart-reflow/ + * Resize div and reflow + * @sample highcharts/chart/events-container/ + * Pop up and reflow + * + * @function Highcharts.Chart#reflow + * + * @param {global.Event} [e] + * Event arguments. Used primarily when the function is called + * internally as a response to window resize. + */ + reflow: function (e) { + var chart = this, optionsChart = chart.options.chart, renderTo = chart.renderTo, hasUserSize = (defined(optionsChart.width) && + defined(optionsChart.height)), width = optionsChart.width || getStyle(renderTo, 'width'), height = optionsChart.height || getStyle(renderTo, 'height'), target = e ? e.target : win; + // Width and height checks for display:none. Target is doc in IE8 and + // Opera, win in Firefox, Chrome and IE9. + if (!hasUserSize && + !chart.isPrinting && + width && + height && + (target === win || target === doc)) { + if (width !== chart.containerWidth || + height !== chart.containerHeight) { + U.clearTimeout(chart.reflowTimeout); + // When called from window.resize, e is set, else it's called + // directly (#2224) + chart.reflowTimeout = syncTimeout(function () { + // Set size, it may have been destroyed in the meantime + // (#1257) + if (chart.container) { + chart.setSize(void 0, void 0, false); + } + }, e ? 100 : 0); + } + chart.containerWidth = width; + chart.containerHeight = height; + } + }, + /** + * Toggle the event handlers necessary for auto resizing, depending on the + * `chart.reflow` option. + * + * @private + * @function Highcharts.Chart#setReflow + * @param {boolean} [reflow] + * @return {void} + */ + setReflow: function (reflow) { + var chart = this; + if (reflow !== false && !this.unbindReflow) { + this.unbindReflow = addEvent(win, 'resize', function (e) { + // a removed event listener still runs in Edge and IE if the + // listener was removed while the event runs, so check if the + // chart is not destroyed (#11609) + if (chart.options) { + chart.reflow(e); + } + }); + addEvent(this, 'destroy', this.unbindReflow); + } + else if (reflow === false && this.unbindReflow) { + // Unbind and unset + this.unbindReflow = this.unbindReflow(); + } + // The following will add listeners to re-fit the chart before and after + // printing (#2284). However it only works in WebKit. Should have worked + // in Firefox, but not supported in IE. + /* + if (win.matchMedia) { + win.matchMedia('print').addListener(function reflow() { + chart.reflow(); + }); + } + //*/ + }, + /** + * Resize the chart to a given width and height. In order to set the width + * only, the height argument may be skipped. To set the height only, pass + * `undefined` for the width. + * + * @sample highcharts/members/chart-setsize-button/ + * Test resizing from buttons + * @sample highcharts/members/chart-setsize-jquery-resizable/ + * Add a jQuery UI resizable + * @sample stock/members/chart-setsize/ + * Highstock with UI resizable + * + * @function Highcharts.Chart#setSize + * + * @param {number|null} [width] + * The new pixel width of the chart. Since v4.2.6, the argument can + * be `undefined` in order to preserve the current value (when + * setting height only), or `null` to adapt to the width of the + * containing element. + * + * @param {number|null} [height] + * The new pixel height of the chart. Since v4.2.6, the argument can + * be `undefined` in order to preserve the current value, or `null` + * in order to adapt to the height of the containing element. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=true] + * Whether and how to apply animation. + * + * @return {void} + * + * @fires Highcharts.Chart#event:endResize + * @fires Highcharts.Chart#event:resize + */ + setSize: function (width, height, animation) { + var chart = this, renderer = chart.renderer, globalAnimation; + // Handle the isResizing counter + chart.isResizing += 1; + // set the animation for the current process + setAnimation(animation, chart); + globalAnimation = renderer.globalAnimation; + chart.oldChartHeight = chart.chartHeight; + chart.oldChartWidth = chart.chartWidth; + if (typeof width !== 'undefined') { + chart.options.chart.width = width; + } + if (typeof height !== 'undefined') { + chart.options.chart.height = height; + } + chart.getChartSize(); + // Resize the container with the global animation applied if enabled + // (#2503) + if (!chart.styledMode) { + (globalAnimation ? animate : css)(chart.container, { + width: chart.chartWidth + 'px', + height: chart.chartHeight + 'px' + }, globalAnimation); + } + chart.setChartSize(true); + renderer.setSize(chart.chartWidth, chart.chartHeight, globalAnimation); + // handle axes + chart.axes.forEach(function (axis) { + axis.isDirty = true; + axis.setScale(); + }); + chart.isDirtyLegend = true; // force legend redraw + chart.isDirtyBox = true; // force redraw of plot and chart border + chart.layOutTitles(); // #2857 + chart.getMargins(); + chart.redraw(globalAnimation); + chart.oldChartHeight = null; + fireEvent(chart, 'resize'); + // Fire endResize and set isResizing back. If animation is disabled, + // fire without delay + syncTimeout(function () { + if (chart) { + fireEvent(chart, 'endResize', null, function () { + chart.isResizing -= 1; + }); + } + }, animObject(globalAnimation).duration || 0); + }, + /** + * Set the public chart properties. This is done before and after the + * pre-render to determine margin sizes. + * + * @private + * @function Highcharts.Chart#setChartSize + * + * @param {boolean} skipAxes + * + * @return {void} + * + * @fires Highcharts.Chart#event:afterSetChartSize + */ + setChartSize: function (skipAxes) { + var chart = this, inverted = chart.inverted, renderer = chart.renderer, chartWidth = chart.chartWidth, chartHeight = chart.chartHeight, optionsChart = chart.options.chart, spacing = chart.spacing, clipOffset = chart.clipOffset, clipX, clipY, plotLeft, plotTop, plotWidth, plotHeight, plotBorderWidth; + /** + * The current left position of the plot area in pixels. + * + * @name Highcharts.Chart#plotLeft + * @type {number} + */ + chart.plotLeft = plotLeft = Math.round(chart.plotLeft); + /** + * The current top position of the plot area in pixels. + * + * @name Highcharts.Chart#plotTop + * @type {number} + */ + chart.plotTop = plotTop = Math.round(chart.plotTop); + /** + * The current width of the plot area in pixels. + * + * @name Highcharts.Chart#plotWidth + * @type {number} + */ + chart.plotWidth = plotWidth = Math.max(0, Math.round(chartWidth - plotLeft - chart.marginRight)); + /** + * The current height of the plot area in pixels. + * + * @name Highcharts.Chart#plotHeight + * @type {number} + */ + chart.plotHeight = plotHeight = Math.max(0, Math.round(chartHeight - plotTop - chart.marginBottom)); + chart.plotSizeX = inverted ? plotHeight : plotWidth; + chart.plotSizeY = inverted ? plotWidth : plotHeight; + chart.plotBorderWidth = optionsChart.plotBorderWidth || 0; + // Set boxes used for alignment + chart.spacingBox = renderer.spacingBox = { + x: spacing[3], + y: spacing[0], + width: chartWidth - spacing[3] - spacing[1], + height: chartHeight - spacing[0] - spacing[2] + }; + chart.plotBox = renderer.plotBox = { + x: plotLeft, + y: plotTop, + width: plotWidth, + height: plotHeight + }; + plotBorderWidth = 2 * Math.floor(chart.plotBorderWidth / 2); + clipX = Math.ceil(Math.max(plotBorderWidth, clipOffset[3]) / 2); + clipY = Math.ceil(Math.max(plotBorderWidth, clipOffset[0]) / 2); + chart.clipBox = { + x: clipX, + y: clipY, + width: Math.floor(chart.plotSizeX - + Math.max(plotBorderWidth, clipOffset[1]) / 2 - + clipX), + height: Math.max(0, Math.floor(chart.plotSizeY - + Math.max(plotBorderWidth, clipOffset[2]) / 2 - + clipY)) + }; + if (!skipAxes) { + chart.axes.forEach(function (axis) { + axis.setAxisSize(); + axis.setAxisTranslation(); + }); + } + fireEvent(chart, 'afterSetChartSize', { skipAxes: skipAxes }); + }, + /** + * Initial margins before auto size margins are applied. + * + * @private + * @function Highcharts.Chart#resetMargins + * @return {void} + */ + resetMargins: function () { + fireEvent(this, 'resetMargins'); + var chart = this, chartOptions = chart.options.chart; + // Create margin and spacing array + ['margin', 'spacing'].forEach(function splashArrays(target) { + var value = chartOptions[target], values = isObject(value) ? value : [value, value, value, value]; + [ + 'Top', + 'Right', + 'Bottom', + 'Left' + ].forEach(function (sideName, side) { + chart[target][side] = pick(chartOptions[target + sideName], values[side]); + }); + }); + // Set margin names like chart.plotTop, chart.plotLeft, + // chart.marginRight, chart.marginBottom. + marginNames.forEach(function (m, side) { + chart[m] = pick(chart.margin[side], chart.spacing[side]); + }); + chart.axisOffset = [0, 0, 0, 0]; // top, right, bottom, left + chart.clipOffset = [0, 0, 0, 0]; + }, + /** + * Internal function to draw or redraw the borders and backgrounds for chart + * and plot area. + * + * @private + * @function Highcharts.Chart#drawChartBox + * @return {void} + * @fires Highcharts.Chart#event:afterDrawChartBox + */ + drawChartBox: function () { + var chart = this, optionsChart = chart.options.chart, renderer = chart.renderer, chartWidth = chart.chartWidth, chartHeight = chart.chartHeight, chartBackground = chart.chartBackground, plotBackground = chart.plotBackground, plotBorder = chart.plotBorder, chartBorderWidth, styledMode = chart.styledMode, plotBGImage = chart.plotBGImage, chartBackgroundColor = optionsChart.backgroundColor, plotBackgroundColor = optionsChart.plotBackgroundColor, plotBackgroundImage = optionsChart.plotBackgroundImage, mgn, bgAttr, plotLeft = chart.plotLeft, plotTop = chart.plotTop, plotWidth = chart.plotWidth, plotHeight = chart.plotHeight, plotBox = chart.plotBox, clipRect = chart.clipRect, clipBox = chart.clipBox, verb = 'animate'; + // Chart area + if (!chartBackground) { + chart.chartBackground = chartBackground = renderer.rect() + .addClass('highcharts-background') + .add(); + verb = 'attr'; + } + if (!styledMode) { + // Presentational + chartBorderWidth = optionsChart.borderWidth || 0; + mgn = chartBorderWidth + (optionsChart.shadow ? 8 : 0); + bgAttr = { + fill: chartBackgroundColor || 'none' + }; + if (chartBorderWidth || chartBackground['stroke-width']) { // #980 + bgAttr.stroke = optionsChart.borderColor; + bgAttr['stroke-width'] = chartBorderWidth; + } + chartBackground + .attr(bgAttr) + .shadow(optionsChart.shadow); + } + else { + chartBorderWidth = mgn = chartBackground.strokeWidth(); + } + chartBackground[verb]({ + x: mgn / 2, + y: mgn / 2, + width: chartWidth - mgn - chartBorderWidth % 2, + height: chartHeight - mgn - chartBorderWidth % 2, + r: optionsChart.borderRadius + }); + // Plot background + verb = 'animate'; + if (!plotBackground) { + verb = 'attr'; + chart.plotBackground = plotBackground = renderer.rect() + .addClass('highcharts-plot-background') + .add(); + } + plotBackground[verb](plotBox); + if (!styledMode) { + // Presentational attributes for the background + plotBackground + .attr({ + fill: plotBackgroundColor || 'none' + }) + .shadow(optionsChart.plotShadow); + // Create the background image + if (plotBackgroundImage) { + if (!plotBGImage) { + chart.plotBGImage = renderer.image(plotBackgroundImage, plotLeft, plotTop, plotWidth, plotHeight).add(); + } + else { + if (plotBackgroundImage !== plotBGImage.attr('href')) { + plotBGImage.attr('href', plotBackgroundImage); + } + plotBGImage.animate(plotBox); + } + } + } + // Plot clip + if (!clipRect) { + chart.clipRect = renderer.clipRect(clipBox); + } + else { + clipRect.animate({ + width: clipBox.width, + height: clipBox.height + }); + } + // Plot area border + verb = 'animate'; + if (!plotBorder) { + verb = 'attr'; + chart.plotBorder = plotBorder = renderer.rect() + .addClass('highcharts-plot-border') + .attr({ + zIndex: 1 // Above the grid + }) + .add(); + } + if (!styledMode) { + // Presentational + plotBorder.attr({ + stroke: optionsChart.plotBorderColor, + 'stroke-width': optionsChart.plotBorderWidth || 0, + fill: 'none' + }); + } + plotBorder[verb](plotBorder.crisp({ + x: plotLeft, + y: plotTop, + width: plotWidth, + height: plotHeight + }, -plotBorder.strokeWidth())); // #3282 plotBorder should be negative; + // reset + chart.isDirtyBox = false; + fireEvent(this, 'afterDrawChartBox'); + }, + /** + * Detect whether a certain chart property is needed based on inspecting its + * options and series. This mainly applies to the chart.inverted property, + * and in extensions to the chart.angular and chart.polar properties. + * + * @private + * @function Highcharts.Chart#propFromSeries + * @return {void} + */ + propFromSeries: function () { + var chart = this, optionsChart = chart.options.chart, klass, seriesOptions = chart.options.series, i, value; + /** + * The flag is set to `true` if a series of the chart is inverted. + * + * @name Highcharts.Chart#inverted + * @type {boolean|undefined} + */ + ['inverted', 'angular', 'polar'].forEach(function (key) { + // The default series type's class + klass = seriesTypes[(optionsChart.type || + optionsChart.defaultSeriesType)]; + // Get the value from available chart-wide properties + value = + // It is set in the options: + optionsChart[key] || + // The default series class: + (klass && klass.prototype[key]); + // requires it + // 4. Check if any the chart's series require it + i = seriesOptions && seriesOptions.length; + while (!value && i--) { + klass = seriesTypes[seriesOptions[i].type]; + if (klass && klass.prototype[key]) { + value = true; + } + } + // Set the chart property + chart[key] = value; + }); + }, + /** + * Internal function to link two or more series together, based on the + * `linkedTo` option. This is done from `Chart.render`, and after + * `Chart.addSeries` and `Series.remove`. + * + * @private + * @function Highcharts.Chart#linkSeries + * @return {void} + * @fires Highcharts.Chart#event:afterLinkSeries + */ + linkSeries: function () { + var chart = this, chartSeries = chart.series; + // Reset links + chartSeries.forEach(function (series) { + series.linkedSeries.length = 0; + }); + // Apply new links + chartSeries.forEach(function (series) { + var linkedTo = series.options.linkedTo; + if (isString(linkedTo)) { + if (linkedTo === ':previous') { + linkedTo = chart.series[series.index - 1]; + } + else { + linkedTo = chart.get(linkedTo); + } + // #3341 avoid mutual linking + if (linkedTo && linkedTo.linkedParent !== series) { + linkedTo.linkedSeries.push(series); + series.linkedParent = linkedTo; + if (linkedTo.enabledDataSorting) { + series.setDataSortingOptions(); + } + series.visible = pick(series.options.visible, linkedTo.options.visible, series.visible); // #3879 + } + } + }); + fireEvent(this, 'afterLinkSeries'); + }, + /** + * Render series for the chart. + * + * @private + * @function Highcharts.Chart#renderSeries + * @return {void} + */ + renderSeries: function () { + this.series.forEach(function (serie) { + serie.translate(); + serie.render(); + }); + }, + /** + * Render labels for the chart. + * + * @private + * @function Highcharts.Chart#renderLabels + * @return {void} + */ + renderLabels: function () { + var chart = this, labels = chart.options.labels; + if (labels.items) { + labels.items.forEach(function (label) { + var style = extend(labels.style, label.style), x = pInt(style.left) + chart.plotLeft, y = pInt(style.top) + chart.plotTop + 12; + // delete to prevent rewriting in IE + delete style.left; + delete style.top; + chart.renderer.text(label.html, x, y) + .attr({ zIndex: 2 }) + .css(style) + .add(); + }); + } + }, + /** + * Render all graphics for the chart. Runs internally on initialization. + * + * @private + * @function Highcharts.Chart#render + * @return {void} + */ + render: function () { + var chart = this, axes = chart.axes, colorAxis = chart.colorAxis, renderer = chart.renderer, options = chart.options, correction = 0, // correction for X axis labels + tempWidth, tempHeight, redoHorizontal, redoVertical, renderAxes = function (axes) { + axes.forEach(function (axis) { + if (axis.visible) { + axis.render(); + } + }); + }; + // Title + chart.setTitle(); + /** + * The overview of the chart's series. + * + * @name Highcharts.Chart#legend + * @type {Highcharts.Legend} + */ + chart.legend = new Legend(chart, options.legend); + // Get stacks + if (chart.getStacks) { + chart.getStacks(); + } + // Get chart margins + chart.getMargins(true); + chart.setChartSize(); + // Record preliminary dimensions for later comparison + tempWidth = chart.plotWidth; + axes.some(function (axis) { + if (axis.horiz && + axis.visible && + axis.options.labels.enabled && + axis.series.length) { + // 21 is the most common correction for X axis labels + correction = 21; + return true; + } + }); + // use Math.max to prevent negative plotHeight + chart.plotHeight = Math.max(chart.plotHeight - correction, 0); + tempHeight = chart.plotHeight; + // Get margins by pre-rendering axes + axes.forEach(function (axis) { + axis.setScale(); + }); + chart.getAxisMargins(); + // If the plot area size has changed significantly, calculate tick + // positions again + redoHorizontal = tempWidth / chart.plotWidth > 1.1; + // Height is more sensitive, use lower threshold + redoVertical = tempHeight / chart.plotHeight > 1.05; + if (redoHorizontal || redoVertical) { + axes.forEach(function (axis) { + if ((axis.horiz && redoHorizontal) || + (!axis.horiz && redoVertical)) { + // update to reflect the new margins + axis.setTickInterval(true); + } + }); + chart.getMargins(); // second pass to check for new labels + } + // Draw the borders and backgrounds + chart.drawChartBox(); + // Axes + if (chart.hasCartesianSeries) { + renderAxes(axes); + } + else if (colorAxis && colorAxis.length) { + renderAxes(colorAxis); + } + // The series + if (!chart.seriesGroup) { + chart.seriesGroup = renderer.g('series-group') + .attr({ zIndex: 3 }) + .add(); + } + chart.renderSeries(); + // Labels + chart.renderLabels(); + // Credits + chart.addCredits(); + // Handle responsiveness + if (chart.setResponsive) { + chart.setResponsive(); + } + // Handle scaling + chart.updateContainerScaling(); + // Set flag + chart.hasRendered = true; + }, + /** + * Set a new credits label for the chart. + * + * @sample highcharts/credits/credits-update/ + * Add and update credits + * + * @function Highcharts.Chart#addCredits + * + * @param {Highcharts.CreditsOptions} credits + * A configuration object for the new credits. + * + * @return {void} + */ + addCredits: function (credits) { + var chart = this; + credits = merge(true, this.options.credits, credits); + if (credits.enabled && !this.credits) { + /** + * The chart's credits label. The label has an `update` method that + * allows setting new options as per the + * [credits options set](https://api.highcharts.com/highcharts/credits). + * + * @name Highcharts.Chart#credits + * @type {Highcharts.SVGElement} + */ + this.credits = this.renderer.text(credits.text + (this.mapCredits || ''), 0, 0) + .addClass('highcharts-credits') + .on('click', function () { + if (credits.href) { + win.location.href = credits.href; + } + }) + .attr({ + align: credits.position.align, + zIndex: 8 + }); + if (!chart.styledMode) { + this.credits.css(credits.style); + } + this.credits + .add() + .align(credits.position); + // Dynamically update + this.credits.update = function (options) { + chart.credits = chart.credits.destroy(); + chart.addCredits(options); + }; + } + }, + /** + * Handle scaling, #11329 - when there is scaling/transform on the container + * or on a parent element, we need to take this into account. We calculate + * the scaling once here and it is picked up where we need to use it + * (Pointer, Tooltip). + * + * @private + * @function Highcharts.Chart#updateContainerScaling + * @return {void} + */ + updateContainerScaling: function () { + var container = this.container; + if (container.offsetWidth && + container.offsetHeight && + container.getBoundingClientRect) { + var bb = container.getBoundingClientRect(), scaleX = bb.width / container.offsetWidth, scaleY = bb.height / container.offsetHeight; + if (scaleX !== 1 || scaleY !== 1) { + this.containerScaling = { scaleX: scaleX, scaleY: scaleY }; + } + else { + delete this.containerScaling; + } + } + }, + /** + * Remove the chart and purge memory. This method is called internally + * before adding a second chart into the same container, as well as on + * window unload to prevent leaks. + * + * @sample highcharts/members/chart-destroy/ + * Destroy the chart from a button + * @sample stock/members/chart-destroy/ + * Destroy with Highstock + * + * @function Highcharts.Chart#destroy + * + * @return {void} + * + * @fires Highcharts.Chart#event:destroy + */ + destroy: function () { + var chart = this, axes = chart.axes, series = chart.series, container = chart.container, i, parentNode = container && container.parentNode; + // fire the chart.destoy event + fireEvent(chart, 'destroy'); + // Delete the chart from charts lookup array + if (chart.renderer.forExport) { + erase(charts, chart); // #6569 + } + else { + charts[chart.index] = void 0; + } + H.chartCount--; + chart.renderTo.removeAttribute('data-highcharts-chart'); + // remove events + removeEvent(chart); + // ==== Destroy collections: + // Destroy axes + i = axes.length; + while (i--) { + axes[i] = axes[i].destroy(); + } + // Destroy scroller & scroller series before destroying base series + if (this.scroller && this.scroller.destroy) { + this.scroller.destroy(); + } + // Destroy each series + i = series.length; + while (i--) { + series[i] = series[i].destroy(); + } + // ==== Destroy chart properties: + [ + 'title', 'subtitle', 'chartBackground', 'plotBackground', + 'plotBGImage', 'plotBorder', 'seriesGroup', 'clipRect', 'credits', + 'pointer', 'rangeSelector', 'legend', 'resetZoomButton', 'tooltip', + 'renderer' + ].forEach(function (name) { + var prop = chart[name]; + if (prop && prop.destroy) { + chart[name] = prop.destroy(); + } + }); + // Remove container and all SVG, check container as it can break in IE + // when destroyed before finished loading + if (container) { + container.innerHTML = ''; + removeEvent(container); + if (parentNode) { + discardElement(container); + } + } + // clean it all up + objectEach(chart, function (val, key) { + delete chart[key]; + }); + }, + /** + * Prepare for first rendering after all data are loaded. + * + * @private + * @function Highcharts.Chart#firstRender + * @return {void} + * + * @fires Highcharts.Chart#event:beforeRender + */ + firstRender: function () { + var chart = this, options = chart.options; + // Hook for oldIE to check whether the chart is ready to render + if (chart.isReadyToRender && !chart.isReadyToRender()) { + return; + } + // Create the container + chart.getContainer(); + chart.resetMargins(); + chart.setChartSize(); + // Set the common chart properties (mainly invert) from the given series + chart.propFromSeries(); + // get axes + chart.getAxes(); + // Initialize the series + (isArray(options.series) ? options.series : []).forEach( + // #9680 + function (serieOptions) { + chart.initSeries(serieOptions); + }); + chart.linkSeries(); + chart.setSeriesData(); + // Run an event after axes and series are initialized, but before + // render. At this stage, the series data is indexed and cached in the + // xData and yData arrays, so we can access those before rendering. Used + // in Highstock. + fireEvent(chart, 'beforeRender'); + // depends on inverted and on margins being set + if (Pointer) { + if (!H.hasTouch && (win.PointerEvent || win.MSPointerEvent)) { + chart.pointer = new MSPointer(chart, options); + } + else { + /** + * The Pointer that keeps track of mouse and touch interaction. + * + * @memberof Highcharts.Chart + * @name pointer + * @type {Highcharts.Pointer} + * @instance + */ + chart.pointer = new Pointer(chart, options); + } + } + chart.render(); + // Fire the load event if there are no external images + if (!chart.renderer.imgCount && !chart.hasLoaded) { + chart.onload(); + } + // If the chart was rendered outside the top container, put it back in + // (#3679) + chart.temporaryDisplay(true); + }, + /** + * Internal function that runs on chart load, async if any images are loaded + * in the chart. Runs the callbacks and triggers the `load` and `render` + * events. + * + * @private + * @function Highcharts.Chart#onload + * @return {void} + * @fires Highcharts.Chart#event:load + * @fires Highcharts.Chart#event:render + */ + onload: function () { + // Run callbacks, first the ones registered by modules, then user's one + this.callbacks.concat([this.callback]).forEach(function (fn) { + // Chart destroyed in its own callback (#3600) + if (fn && typeof this.index !== 'undefined') { + fn.apply(this, [this]); + } + }, this); + fireEvent(this, 'load'); + fireEvent(this, 'render'); + // Set up auto resize, check for not destroyed (#6068) + if (defined(this.index)) { + this.setReflow(this.options.chart.reflow); + } + // Don't run again + this.hasLoaded = true; + } + }); // end Chart + + }); + _registerModule(_modules, 'parts/ScrollablePlotArea.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * Highcharts feature to make the Y axis stay fixed when scrolling the chart + * horizontally on mobile devices. Supports left and right side axes. + */ + /* + WIP on vertical scrollable plot area (#9378). To do: + - Bottom axis positioning + - Test with Gantt + - Look for size optimizing the code + - API and demos + */ + var addEvent = U.addEvent, createElement = U.createElement, pick = U.pick, stop = U.stop; + var Chart = H.Chart; + /** + * Options for a scrollable plot area. This feature provides a minimum size for + * the plot area of the chart. If the size gets smaller than this, typically + * on mobile devices, a native browser scrollbar is presented. This scrollbar + * provides smooth scrolling for the contents of the plot area, whereas the + * title, legend and unaffected axes are fixed. + * + * Since v7.1.2, a scrollable plot area can be defined for either horizontal or + * vertical scrolling, depending on whether the `minWidth` or `minHeight` + * option is set. + * + * @sample highcharts/chart/scrollable-plotarea + * Scrollable plot area + * @sample highcharts/chart/scrollable-plotarea-vertical + * Vertically scrollable plot area + * @sample {gantt} highcharts/chart/scrollable-plotarea-vertical + * Gantt chart with vertically scrollable plot area + * + * @since 6.1.0 + * @product highcharts gantt + * @apioption chart.scrollablePlotArea + */ + /** + * The minimum height for the plot area. If it gets smaller than this, the plot + * area will become scrollable. + * + * @type {number} + * @apioption chart.scrollablePlotArea.minHeight + */ + /** + * The minimum width for the plot area. If it gets smaller than this, the plot + * area will become scrollable. + * + * @type {number} + * @apioption chart.scrollablePlotArea.minWidth + */ + /** + * The initial scrolling position of the scrollable plot area. Ranges from 0 to + * 1, where 0 aligns the plot area to the left and 1 aligns it to the right. + * Typically we would use 1 if the chart has right aligned Y axes. + * + * @type {number} + * @apioption chart.scrollablePlotArea.scrollPositionX + */ + /** + * The initial scrolling position of the scrollable plot area. Ranges from 0 to + * 1, where 0 aligns the plot area to the top and 1 aligns it to the bottom. + * + * @type {number} + * @apioption chart.scrollablePlotArea.scrollPositionY + */ + /** + * The opacity of mask applied on one of the sides of the plot + * area. + * + * @sample {highcharts} highcharts/chart/scrollable-plotarea-opacity + * Disabled opacity for the mask + * + * @type {number} + * @default 0.85 + * @since 7.1.1 + * @apioption chart.scrollablePlotArea.opacity + */ + ''; // detach API doclets + /* eslint-disable no-invalid-this, valid-jsdoc */ + addEvent(Chart, 'afterSetChartSize', function (e) { + var scrollablePlotArea = this.options.chart.scrollablePlotArea, scrollableMinWidth = scrollablePlotArea && scrollablePlotArea.minWidth, scrollableMinHeight = scrollablePlotArea && scrollablePlotArea.minHeight, scrollablePixelsX, scrollablePixelsY, corrections; + if (!this.renderer.forExport) { + // The amount of pixels to scroll, the difference between chart + // width and scrollable width + if (scrollableMinWidth) { + this.scrollablePixelsX = scrollablePixelsX = Math.max(0, scrollableMinWidth - this.chartWidth); + if (scrollablePixelsX) { + this.plotWidth += scrollablePixelsX; + if (this.inverted) { + this.clipBox.height += scrollablePixelsX; + this.plotBox.height += scrollablePixelsX; + } + else { + this.clipBox.width += scrollablePixelsX; + this.plotBox.width += scrollablePixelsX; + } + corrections = { + // Corrections for right side + 1: { name: 'right', value: scrollablePixelsX } + }; + } + // Currently we can only do either X or Y + } + else if (scrollableMinHeight) { + this.scrollablePixelsY = scrollablePixelsY = Math.max(0, scrollableMinHeight - this.chartHeight); + if (scrollablePixelsY) { + this.plotHeight += scrollablePixelsY; + if (this.inverted) { + this.clipBox.width += scrollablePixelsY; + this.plotBox.width += scrollablePixelsY; + } + else { + this.clipBox.height += scrollablePixelsY; + this.plotBox.height += scrollablePixelsY; + } + corrections = { + 2: { name: 'bottom', value: scrollablePixelsY } + }; + } + } + if (corrections && !e.skipAxes) { + this.axes.forEach(function (axis) { + // For right and bottom axes, only fix the plot line length + if (corrections[axis.side]) { + // Get the plot lines right in getPlotLinePath, + // temporarily set it to the adjusted plot width. + axis.getPlotLinePath = function () { + var marginName = corrections[axis.side].name, correctionValue = corrections[axis.side].value, + // axis.right or axis.bottom + margin = this[marginName], path; + // Temporarily adjust + this[marginName] = margin - correctionValue; + path = H.Axis.prototype.getPlotLinePath.apply(this, arguments); + // Reset + this[marginName] = margin; + return path; + }; + } + else { + // Apply the corrected plotWidth + axis.setAxisSize(); + axis.setAxisTranslation(); + } + }); + } + } + }); + addEvent(Chart, 'render', function () { + if (this.scrollablePixelsX || this.scrollablePixelsY) { + if (this.setUpScrolling) { + this.setUpScrolling(); + } + this.applyFixed(); + } + else if (this.fixedDiv) { // Has been in scrollable mode + this.applyFixed(); + } + }); + /** + * @private + * @function Highcharts.Chart#setUpScrolling + * @return {void} + */ + Chart.prototype.setUpScrolling = function () { + var _this = this; + var attribs = { + WebkitOverflowScrolling: 'touch', + overflowX: 'hidden', + overflowY: 'hidden' + }; + if (this.scrollablePixelsX) { + attribs.overflowX = 'auto'; + } + if (this.scrollablePixelsY) { + attribs.overflowY = 'auto'; + } + // Add the necessary divs to provide scrolling + this.scrollingContainer = createElement('div', { + 'className': 'highcharts-scrolling' + }, attribs, this.renderTo); + // On scroll, reset the chart position because it applies to the scrolled + // container + addEvent(this.scrollingContainer, 'scroll', function () { + if (_this.pointer) { + delete _this.pointer.chartPosition; + } + }); + this.innerContainer = createElement('div', { + 'className': 'highcharts-inner-container' + }, null, this.scrollingContainer); + // Now move the container inside + this.innerContainer.appendChild(this.container); + // Don't run again + this.setUpScrolling = null; + }; + /** + * These elements are moved over to the fixed renderer and stay fixed when the + * user scrolls the chart + * @private + */ + Chart.prototype.moveFixedElements = function () { + var container = this.container, fixedRenderer = this.fixedRenderer, fixedSelectors = [ + '.highcharts-contextbutton', + '.highcharts-credits', + '.highcharts-legend', + '.highcharts-legend-checkbox', + '.highcharts-navigator-series', + '.highcharts-navigator-xaxis', + '.highcharts-navigator-yaxis', + '.highcharts-navigator', + '.highcharts-reset-zoom', + '.highcharts-scrollbar', + '.highcharts-subtitle', + '.highcharts-title' + ], axisClass; + if (this.scrollablePixelsX && !this.inverted) { + axisClass = '.highcharts-yaxis'; + } + else if (this.scrollablePixelsX && this.inverted) { + axisClass = '.highcharts-xaxis'; + } + else if (this.scrollablePixelsY && !this.inverted) { + axisClass = '.highcharts-xaxis'; + } + else if (this.scrollablePixelsY && this.inverted) { + axisClass = '.highcharts-yaxis'; + } + fixedSelectors.push(axisClass, axisClass + '-labels'); + fixedSelectors.forEach(function (className) { + [].forEach.call(container.querySelectorAll(className), function (elem) { + (elem.namespaceURI === fixedRenderer.SVG_NS ? + fixedRenderer.box : + fixedRenderer.box.parentNode).appendChild(elem); + elem.style.pointerEvents = 'auto'; + }); + }); + }; + /** + * @private + * @function Highcharts.Chart#applyFixed + * @return {void} + */ + Chart.prototype.applyFixed = function () { + var _a; + var fixedRenderer, scrollableWidth, scrollableHeight, firstTime = !this.fixedDiv, scrollableOptions = this.options.chart.scrollablePlotArea; + // First render + if (firstTime) { + this.fixedDiv = createElement('div', { + className: 'highcharts-fixed' + }, { + position: 'absolute', + overflow: 'hidden', + pointerEvents: 'none', + zIndex: 2 + }, null, true); + this.renderTo.insertBefore(this.fixedDiv, this.renderTo.firstChild); + this.renderTo.style.overflow = 'visible'; + this.fixedRenderer = fixedRenderer = new H.Renderer(this.fixedDiv, this.chartWidth, this.chartHeight, (_a = this.options.chart) === null || _a === void 0 ? void 0 : _a.style); + // Mask + this.scrollableMask = fixedRenderer + .path() + .attr({ + fill: this.options.chart.backgroundColor || '#fff', + 'fill-opacity': pick(scrollableOptions.opacity, 0.85), + zIndex: -1 + }) + .addClass('highcharts-scrollable-mask') + .add(); + this.moveFixedElements(); + addEvent(this, 'afterShowResetZoom', this.moveFixedElements); + addEvent(this, 'afterLayOutTitles', this.moveFixedElements); + } + else { + // Set the size of the fixed renderer to the visible width + this.fixedRenderer.setSize(this.chartWidth, this.chartHeight); + } + // Increase the size of the scrollable renderer and background + scrollableWidth = this.chartWidth + (this.scrollablePixelsX || 0); + scrollableHeight = this.chartHeight + (this.scrollablePixelsY || 0); + stop(this.container); + this.container.style.width = scrollableWidth + 'px'; + this.container.style.height = scrollableHeight + 'px'; + this.renderer.boxWrapper.attr({ + width: scrollableWidth, + height: scrollableHeight, + viewBox: [0, 0, scrollableWidth, scrollableHeight].join(' ') + }); + this.chartBackground.attr({ + width: scrollableWidth, + height: scrollableHeight + }); + this.scrollingContainer.style.height = this.chartHeight + 'px'; + // Set scroll position + if (firstTime) { + if (scrollableOptions.scrollPositionX) { + this.scrollingContainer.scrollLeft = + this.scrollablePixelsX * + scrollableOptions.scrollPositionX; + } + if (scrollableOptions.scrollPositionY) { + this.scrollingContainer.scrollTop = + this.scrollablePixelsY * + scrollableOptions.scrollPositionY; + } + } + // Mask behind the left and right side + var axisOffset = this.axisOffset, maskTop = this.plotTop - axisOffset[0] - 1, maskLeft = this.plotLeft - axisOffset[3] - 1, maskBottom = this.plotTop + this.plotHeight + axisOffset[2] + 1, maskRight = this.plotLeft + this.plotWidth + axisOffset[1] + 1, maskPlotRight = this.plotLeft + this.plotWidth - + (this.scrollablePixelsX || 0), maskPlotBottom = this.plotTop + this.plotHeight - + (this.scrollablePixelsY || 0), d; + if (this.scrollablePixelsX) { + d = [ + // Left side + ['M', 0, maskTop], + ['L', this.plotLeft - 1, maskTop], + ['L', this.plotLeft - 1, maskBottom], + ['L', 0, maskBottom], + ['Z'], + // Right side + ['M', maskPlotRight, maskTop], + ['L', this.chartWidth, maskTop], + ['L', this.chartWidth, maskBottom], + ['L', maskPlotRight, maskBottom], + ['Z'] + ]; + } + else if (this.scrollablePixelsY) { + d = [ + // Top side + ['M', maskLeft, 0], + ['L', maskLeft, this.plotTop - 1], + ['L', maskRight, this.plotTop - 1], + ['L', maskRight, 0], + ['Z'], + // Bottom side + ['M', maskLeft, maskPlotBottom], + ['L', maskLeft, this.chartHeight], + ['L', maskRight, this.chartHeight], + ['L', maskRight, maskPlotBottom], + ['Z'] + ]; + } + else { + d = [['M', 0, 0]]; + } + if (this.redrawTrigger !== 'adjustHeight') { + this.scrollableMask.attr({ d: d }); + } + }; + + }); + _registerModule(_modules, 'parts/StackingAxis.js', [_modules['parts/Utilities.js']], function (U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, destroyObjectProperties = U.destroyObjectProperties, fireEvent = U.fireEvent, objectEach = U.objectEach, pick = U.pick; + /* eslint-disable valid-jsdoc */ + /** + * Adds stacking support to axes. + * @private + * @class + */ + var StackingAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function StackingAxisAdditions(axis) { + this.oldStacks = {}; + this.stacks = {}; + this.stacksTouched = 0; + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Build the stacks from top down + * @private + */ + StackingAxisAdditions.prototype.buildStacks = function () { + var stacking = this; + var axis = stacking.axis; + var axisSeries = axis.series; + var reversedStacks = pick(axis.options.reversedStacks, true); + var len = axisSeries.length; + var actualSeries, i; + if (!axis.isXAxis) { + stacking.usePercentage = false; + i = len; + while (i--) { + actualSeries = axisSeries[reversedStacks ? i : len - i - 1]; + actualSeries.setStackedPoints(); + } + // Loop up again to compute percent and stream stack + for (i = 0; i < len; i++) { + axisSeries[i].modifyStacks(); + } + fireEvent(axis, 'afterBuildStacks'); + } + }; + /** + * @private + */ + StackingAxisAdditions.prototype.cleanStacks = function () { + var stacking = this; + var axis = stacking.axis; + var stacks; + if (!axis.isXAxis) { + if (stacking.oldStacks) { + stacks = stacking.stacks = stacking.oldStacks; + } + // reset stacks + objectEach(stacks, function (type) { + objectEach(type, function (stack) { + stack.cumulative = stack.total; + }); + }); + } + }; + /** + * Set all the stacks to initial states and destroy unused ones. + * @private + */ + StackingAxisAdditions.prototype.resetStacks = function () { + var stacking = this; + var axis = stacking.axis; + var stacks = stacking.stacks; + if (!axis.isXAxis) { + objectEach(stacks, function (type) { + objectEach(type, function (stack, key) { + // Clean up memory after point deletion (#1044, #4320) + if (stack.touched < stacking.stacksTouched) { + stack.destroy(); + delete type[key]; + // Reset stacks + } + else { + stack.total = null; + stack.cumulative = null; + } + }); + }); + } + }; + /** + * @private + */ + StackingAxisAdditions.prototype.renderStackTotals = function () { + var stacking = this; + var axis = stacking.axis; + var chart = axis.chart; + var renderer = chart.renderer; + var stacks = stacking.stacks; + var stackTotalGroup = stacking.stackTotalGroup = (stacking.stackTotalGroup || + renderer + .g('stack-labels') + .attr({ + visibility: 'visible', + zIndex: 6 + }) + .add()); + // plotLeft/Top will change when y axis gets wider so we need to + // translate the stackTotalGroup at every render call. See bug #506 + // and #516 + stackTotalGroup.translate(chart.plotLeft, chart.plotTop); + // Render each stack total + objectEach(stacks, function (type) { + objectEach(type, function (stack) { + stack.render(stackTotalGroup); + }); + }); + }; + return StackingAxisAdditions; + }()); + /** + * Axis with stacking support. + * @private + * @class + */ + var StackingAxis = /** @class */ (function () { + function StackingAxis() { + } + /* * + * + * Static Functions + * + * */ + /** + * Extends axis with stacking support. + * @private + */ + StackingAxis.compose = function (AxisClass) { + var axisProto = AxisClass.prototype; + addEvent(AxisClass, 'init', StackingAxis.onInit); + addEvent(AxisClass, 'destroy', StackingAxis.onDestroy); + }; + /** + * @private + */ + StackingAxis.onDestroy = function () { + var stacking = this.stacking; + if (!stacking) { + return; + } + var stacks = stacking.stacks; + // Destroy each stack total + objectEach(stacks, function (stack, stackKey) { + destroyObjectProperties(stack); + stacks[stackKey] = null; + }); + if (stacking && + stacking.stackTotalGroup) { + stacking.stackTotalGroup.destroy(); + } + }; + /** + * @private + */ + StackingAxis.onInit = function () { + var axis = this; + if (!axis.stacking) { + axis.stacking = new StackingAxisAdditions(axis); + } + }; + return StackingAxis; + }()); + + return StackingAxis; + }); + _registerModule(_modules, 'mixins/legend-symbol.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var merge = U.merge, pick = U.pick; + /* eslint-disable valid-jsdoc */ + /** + * Legend symbol mixin. + * + * @private + * @mixin Highcharts.LegendSymbolMixin + */ + H.LegendSymbolMixin = { + /** + * Get the series' symbol in the legend + * + * @private + * @function Highcharts.LegendSymbolMixin.drawRectangle + * + * @param {Highcharts.Legend} legend + * The legend object + * + * @param {Highcharts.Point|Highcharts.Series} item + * The series (this) or point + */ + drawRectangle: function (legend, item) { + var options = legend.options, symbolHeight = legend.symbolHeight, square = options.squareSymbol, symbolWidth = square ? symbolHeight : legend.symbolWidth; + item.legendSymbol = this.chart.renderer.rect(square ? (legend.symbolWidth - symbolHeight) / 2 : 0, legend.baseline - symbolHeight + 1, // #3988 + symbolWidth, symbolHeight, pick(legend.options.symbolRadius, symbolHeight / 2)) + .addClass('highcharts-point') + .attr({ + zIndex: 3 + }).add(item.legendGroup); + }, + /** + * Get the series' symbol in the legend. This method should be overridable + * to create custom symbols through + * Highcharts.seriesTypes[type].prototype.drawLegendSymbols. + * + * @private + * @function Highcharts.LegendSymbolMixin.drawLineMarker + * + * @param {Highcharts.Legend} legend + * The legend object. + */ + drawLineMarker: function (legend) { + var options = this.options, markerOptions = options.marker, radius, legendSymbol, symbolWidth = legend.symbolWidth, symbolHeight = legend.symbolHeight, generalRadius = symbolHeight / 2, renderer = this.chart.renderer, legendItemGroup = this.legendGroup, verticalCenter = legend.baseline - + Math.round(legend.fontMetrics.b * 0.3), attr = {}; + // Draw the line + if (!this.chart.styledMode) { + attr = { + 'stroke-width': options.lineWidth || 0 + }; + if (options.dashStyle) { + attr.dashstyle = options.dashStyle; + } + } + this.legendLine = renderer + .path([ + 'M', + 0, + verticalCenter, + 'L', + symbolWidth, + verticalCenter + ]) + .addClass('highcharts-graph') + .attr(attr) + .add(legendItemGroup); + // Draw the marker + if (markerOptions && markerOptions.enabled !== false && symbolWidth) { + // Do not allow the marker to be larger than the symbolHeight + radius = Math.min(pick(markerOptions.radius, generalRadius), generalRadius); + // Restrict symbol markers size + if (this.symbol.indexOf('url') === 0) { + markerOptions = merge(markerOptions, { + width: symbolHeight, + height: symbolHeight + }); + radius = 0; + } + this.legendSymbol = legendSymbol = renderer.symbol(this.symbol, (symbolWidth / 2) - radius, verticalCenter - radius, 2 * radius, 2 * radius, markerOptions) + .addClass('highcharts-point') + .add(legendItemGroup); + legendSymbol.isMarker = true; + } + } + }; + + return H.LegendSymbolMixin; + }); + _registerModule(_modules, 'parts/Point.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (Highcharts, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Function callback when a series point is clicked. Return false to cancel the + * action. + * + * @callback Highcharts.PointClickCallbackFunction + * + * @param {Highcharts.Point} this + * The point where the event occured. + * + * @param {Highcharts.PointClickEventObject} event + * Event arguments. + */ + /** + * Common information for a click event on a series point. + * + * @interface Highcharts.PointClickEventObject + * @extends Highcharts.PointerEventObject + */ /** + * Clicked point. + * @name Highcharts.PointClickEventObject#point + * @type {Highcharts.Point} + */ + /** + * Configuration hash for the data label and tooltip formatters. + * + * @interface Highcharts.PointLabelObject + */ /** + * The point's current color. + * @name Highcharts.PointLabelObject#color + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined} + */ /** + * The point's current color index, used in styled mode instead of `color`. The + * color index is inserted in class names used for styling. + * @name Highcharts.PointLabelObject#colorIndex + * @type {number} + */ /** + * The name of the related point. + * @name Highcharts.PointLabelObject#key + * @type {string|undefined} + */ /** + * The percentage for related points in a stacked series or pies. + * @name Highcharts.PointLabelObject#percentage + * @type {number} + */ /** + * The related point. The point name, if defined, is available through + * `this.point.name`. + * @name Highcharts.PointLabelObject#point + * @type {Highcharts.Point} + */ /** + * The related series. The series name is available through `this.series.name`. + * @name Highcharts.PointLabelObject#series + * @type {Highcharts.Series} + */ /** + * The total of values in either a stack for stacked series, or a pie in a pie + * series. + * @name Highcharts.PointLabelObject#total + * @type {number|undefined} + */ /** + * For categorized axes this property holds the category name for the point. For + * other axes it holds the X value. + * @name Highcharts.PointLabelObject#x + * @type {number|string|undefined} + */ /** + * The y value of the point. + * @name Highcharts.PointLabelObject#y + * @type {number|undefined} + */ + /** + * Gets fired when the mouse leaves the area close to the point. + * + * @callback Highcharts.PointMouseOutCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {global.PointerEvent} event + * Event that occured. + */ + /** + * Gets fired when the mouse enters the area close to the point. + * + * @callback Highcharts.PointMouseOverCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {global.Event} event + * Event that occured. + */ + /** + * The generic point options for all series. + * + * In TypeScript you have to extend `PointOptionsObject` with an additional + * declaration to allow custom data options: + * + * ``` + * declare interface PointOptionsObject { + * customProperty: string; + * } + * ``` + * + * @interface Highcharts.PointOptionsObject + */ + /** + * Possible option types for a data point. + * + * @typedef {number|string|Array<(number|string)>|Highcharts.PointOptionsObject|null} Highcharts.PointOptionsType + */ + /** + * Gets fired when the point is removed using the `.remove()` method. + * + * @callback Highcharts.PointRemoveCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {global.Event} event + * Event that occured. + */ + /** + * Possible key values for the point state options. + * + * @typedef {"hover"|"inactive"|"normal"|"select"} Highcharts.PointStateValue + */ + /** + * Gets fired when the point is updated programmatically through the `.update()` + * method. + * + * @callback Highcharts.PointUpdateCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {Highcharts.PointUpdateEventObject} event + * Event that occured. + */ + /** + * Information about the update event. + * + * @interface Highcharts.PointUpdateEventObject + * @extends global.Event + */ /** + * Options data of the update event. + * @name Highcharts.PointUpdateEventObject#options + * @type {Highcharts.PointOptionsType} + */ + ''; // detach doclet above + var animObject = U.animObject, defined = U.defined, erase = U.erase, extend = U.extend, fireEvent = U.fireEvent, format = U.format, getNestedProperty = U.getNestedProperty, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, syncTimeout = U.syncTimeout, pick = U.pick, removeEvent = U.removeEvent, uniqueKey = U.uniqueKey; + var H = Highcharts; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The Point object. The point objects are generated from the `series.data` + * configuration objects or raw numbers. They can be accessed from the + * `Series.points` array. Other ways to instantiate points are through {@link + * Highcharts.Series#addPoint} or {@link Highcharts.Series#setData}. + * + * @class + * @name Highcharts.Point + */ + var Point = /** @class */ (function () { + function Point() { + /* * + * + * Properties + * + * */ + /** + * For categorized axes this property holds the category name for the + * point. For other axes it holds the X value. + * + * @name Highcharts.Point#category + * @type {string} + */ + this.category = void 0; + /** + * The point's current color index, used in styled mode instead of + * `color`. The color index is inserted in class names used for styling. + * + * @name Highcharts.Point#colorIndex + * @type {number} + */ + this.colorIndex = void 0; + this.formatPrefix = 'point'; + this.id = void 0; + this.isNull = false; + /** + * The name of the point. The name can be given as the first position of the + * point configuration array, or as a `name` property in the configuration: + * + * @example + * // Array config + * data: [ + * ['John', 1], + * ['Jane', 2] + * ] + * + * // Object config + * data: [{ + * name: 'John', + * y: 1 + * }, { + * name: 'Jane', + * y: 2 + * }] + * + * @name Highcharts.Point#name + * @type {string} + */ + this.name = void 0; + /** + * The point's options as applied in the initial configuration, or + * extended through `Point.update`. + * + * In TypeScript you have to extend `PointOptionsObject` via an + * additional interface to allow custom data options: + * + * ``` + * declare interface PointOptionsObject { + * customProperty: string; + * } + * ``` + * + * @name Highcharts.Point#options + * @type {Highcharts.PointOptionsObject} + */ + this.options = void 0; + /** + * The percentage for points in a stacked series or pies. + * + * @name Highcharts.Point#percentage + * @type {number|undefined} + */ + this.percentage = void 0; + this.selected = false; + /** + * The series object associated with the point. + * + * @name Highcharts.Point#series + * @type {Highcharts.Series} + */ + this.series = void 0; + /** + * The total of values in either a stack for stacked series, or a pie in a + * pie series. + * + * @name Highcharts.Point#total + * @type {number|undefined} + */ + this.total = void 0; + /** + * For certain series types, like pie charts, where individual points can + * be shown or hidden. + * + * @name Highcharts.Point#visible + * @type {boolean} + * @default true + */ + this.visible = true; + this.x = void 0; + } + /* * + * + * Functions + * + * */ + /** + * Animate SVG elements associated with the point. + * + * @private + * @function Highcharts.Point#animateBeforeDestroy + * @return {void} + */ + Point.prototype.animateBeforeDestroy = function () { + var point = this, animateParams = { x: point.startXPos, opacity: 0 }, isDataLabel, graphicalProps = point.getGraphicalProps(); + graphicalProps.singular.forEach(function (prop) { + isDataLabel = prop === 'dataLabel'; + point[prop] = point[prop].animate(isDataLabel ? { + x: point[prop].startXPos, + y: point[prop].startYPos, + opacity: 0 + } : animateParams); + }); + graphicalProps.plural.forEach(function (plural) { + point[plural].forEach(function (item) { + if (item.element) { + item.animate(extend({ x: point.startXPos }, (item.startYPos ? { + x: item.startXPos, + y: item.startYPos + } : {}))); + } + }); + }); + }; + /** + * Apply the options containing the x and y data and possible some extra + * properties. Called on point init or from point.update. + * + * @private + * @function Highcharts.Point#applyOptions + * + * @param {Highcharts.PointOptionsType} options + * The point options as defined in series.data. + * + * @param {number} [x] + * Optionally, the x value. + * + * @return {Highcharts.Point} + * The Point instance. + */ + Point.prototype.applyOptions = function (options, x) { + var point = this, series = point.series, pointValKey = series.options.pointValKey || series.pointValKey; + options = Point.prototype.optionsToObject.call(this, options); + // copy options directly to point + extend(point, options); + point.options = point.options ? extend(point.options, options) : options; + // Since options are copied into the Point instance, some accidental + // options must be shielded (#5681) + if (options.group) { + delete point.group; + } + if (options.dataLabels) { + delete point.dataLabels; + } + /** + * The y value of the point. + * @name Highcharts.Point#y + * @type {number|undefined} + */ + // For higher dimension series types. For instance, for ranges, point.y + // is mapped to point.low. + if (pointValKey) { + point.y = Point.prototype.getNestedProperty.call(point, pointValKey); + } + point.isNull = pick(point.isValid && !point.isValid(), point.x === null || !isNumber(point.y)); // #3571, check for NaN + point.formatPrefix = point.isNull ? 'null' : 'point'; // #9233, #10874 + // The point is initially selected by options (#5777) + if (point.selected) { + point.state = 'select'; + } + /** + * The x value of the point. + * @name Highcharts.Point#x + * @type {number} + */ + // If no x is set by now, get auto incremented value. All points must + // have an x value, however the y value can be null to create a gap in + // the series + if ('name' in point && + typeof x === 'undefined' && + series.xAxis && + series.xAxis.hasNames) { + point.x = series.xAxis.nameToX(point); + } + if (typeof point.x === 'undefined' && series) { + if (typeof x === 'undefined') { + point.x = series.autoIncrement(point); + } + else { + point.x = x; + } + } + return point; + }; + /** + * Destroy a point to clear memory. Its reference still stays in + * `series.data`. + * + * @private + * @function Highcharts.Point#destroy + * @return {void} + */ + Point.prototype.destroy = function () { + var point = this, series = point.series, chart = series.chart, dataSorting = series.options.dataSorting, hoverPoints = chart.hoverPoints, globalAnimation = point.series.chart.renderer.globalAnimation, animation = animObject(globalAnimation), prop; + /** + * Allow to call after animation. + * @private + */ + function destroyPoint() { + // Remove all events and elements + if (point.graphic || point.dataLabel || point.dataLabels) { + removeEvent(point); + point.destroyElements(); + } + for (prop in point) { // eslint-disable-line guard-for-in + point[prop] = null; + } + } + if (point.legendItem) { // pies have legend items + chart.legend.destroyItem(point); + } + if (hoverPoints) { + point.setState(); + erase(hoverPoints, point); + if (!hoverPoints.length) { + chart.hoverPoints = null; + } + } + if (point === chart.hoverPoint) { + point.onMouseOut(); + } + // Remove properties after animation + if (!dataSorting || !dataSorting.enabled) { + destroyPoint(); + } + else { + this.animateBeforeDestroy(); + syncTimeout(destroyPoint, animation.duration); + } + chart.pointCount--; + }; + /** + * Destroy SVG elements associated with the point. + * + * @private + * @function Highcharts.Point#destroyElements + * @param {Highcharts.Dictionary} [kinds] + * @return {void} + */ + Point.prototype.destroyElements = function (kinds) { + var point = this, props = point.getGraphicalProps(kinds); + props.singular.forEach(function (prop) { + point[prop] = point[prop].destroy(); + }); + props.plural.forEach(function (plural) { + point[plural].forEach(function (item) { + if (item.element) { + item.destroy(); + } + }); + delete point[plural]; + }); + }; + /** + * Fire an event on the Point object. + * + * @private + * @function Highcharts.Point#firePointEvent + * + * @param {string} eventType + * Type of the event. + * + * @param {Highcharts.Dictionary|Event} [eventArgs] + * Additional event arguments. + * + * @param {Highcharts.EventCallbackFunction|Function} [defaultFunction] + * Default event handler. + * + * @fires Highcharts.Point#event:* + */ + Point.prototype.firePointEvent = function (eventType, eventArgs, defaultFunction) { + var point = this, series = this.series, seriesOptions = series.options; + // load event handlers on demand to save time on mouseover/out + if (seriesOptions.point.events[eventType] || + (point.options && + point.options.events && + point.options.events[eventType])) { + point.importEvents(); + } + // add default handler if in selection mode + if (eventType === 'click' && seriesOptions.allowPointSelect) { + defaultFunction = function (event) { + // Control key is for Windows, meta (= Cmd key) for Mac, Shift + // for Opera. + if (point.select) { // #2911 + point.select(null, event.ctrlKey || event.metaKey || event.shiftKey); + } + }; + } + fireEvent(point, eventType, eventArgs, defaultFunction); + }; + /** + * Get the CSS class names for individual points. Used internally where the + * returned value is set on every point. + * + * @function Highcharts.Point#getClassName + * + * @return {string} + * The class names. + */ + Point.prototype.getClassName = function () { + var point = this; + return 'highcharts-point' + + (point.selected ? ' highcharts-point-select' : '') + + (point.negative ? ' highcharts-negative' : '') + + (point.isNull ? ' highcharts-null-point' : '') + + (typeof point.colorIndex !== 'undefined' ? + ' highcharts-color-' + point.colorIndex : '') + + (point.options.className ? ' ' + point.options.className : '') + + (point.zone && point.zone.className ? ' ' + + point.zone.className.replace('highcharts-negative', '') : ''); + }; + /** + * Get props of all existing graphical point elements. + * + * @private + * @function Highcharts.Point#getGraphicalProps + * @param {Highcharts.Dictionary} [kinds] + * @return {Highcharts.PointGraphicalProps} + */ + Point.prototype.getGraphicalProps = function (kinds) { + var point = this, props = [], prop, i, graphicalProps = { singular: [], plural: [] }; + kinds = kinds || { graphic: 1, dataLabel: 1 }; + if (kinds.graphic) { + props.push('graphic', 'shadowGroup'); + } + if (kinds.dataLabel) { + props.push('dataLabel', 'dataLabelUpper', 'connector'); + } + i = props.length; + while (i--) { + prop = props[i]; + if (point[prop]) { + graphicalProps.singular.push(prop); + } + } + ['dataLabel', 'connector'].forEach(function (prop) { + var plural = prop + 's'; + if (kinds[prop] && point[plural]) { + graphicalProps.plural.push(plural); + } + }); + return graphicalProps; + }; + /** + * Return the configuration hash needed for the data label and tooltip + * formatters. + * + * @function Highcharts.Point#getLabelConfig + * + * @return {Highcharts.PointLabelObject} + * Abstract object used in formatters and formats. + */ + Point.prototype.getLabelConfig = function () { + return { + x: this.category, + y: this.y, + color: this.color, + colorIndex: this.colorIndex, + key: this.name || this.category, + series: this.series, + point: this, + percentage: this.percentage, + total: this.total || this.stackTotal + }; + }; + /** + * Returns the value of the point property for a given value. + * @private + */ + Point.prototype.getNestedProperty = function (key) { + if (!key) { + return; + } + if (key.indexOf('custom.') === 0) { + return getNestedProperty(key, this.options); + } + return this[key]; + }; + /** + * In a series with `zones`, return the zone that the point belongs to. + * + * @function Highcharts.Point#getZone + * + * @return {Highcharts.SeriesZonesOptionsObject} + * The zone item. + */ + Point.prototype.getZone = function () { + var series = this.series, zones = series.zones, zoneAxis = series.zoneAxis || 'y', i = 0, zone; + zone = zones[i]; + while (this[zoneAxis] >= zone.value) { + zone = zones[++i]; + } + // For resetting or reusing the point (#8100) + if (!this.nonZonedColor) { + this.nonZonedColor = this.color; + } + if (zone && zone.color && !this.options.color) { + this.color = zone.color; + } + else { + this.color = this.nonZonedColor; + } + return zone; + }; + /** + * Utility to check if point has new shape type. Used in column series and + * all others that are based on column series. + * + * @return boolean|undefined + */ + Point.prototype.hasNewShapeType = function () { + var point = this; + var oldShapeType = point.graphic && + (point.graphic.symbolName || point.graphic.element.nodeName); + return oldShapeType !== this.shapeType; + }; + /** + * Initialize the point. Called internally based on the `series.data` + * option. + * + * @function Highcharts.Point#init + * + * @param {Highcharts.Series} series + * The series object containing this point. + * + * @param {Highcharts.PointOptionsType} options + * The data in either number, array or object format. + * + * @param {number} [x] + * Optionally, the X value of the point. + * + * @return {Highcharts.Point} + * The Point instance. + * + * @fires Highcharts.Point#event:afterInit + */ + Point.prototype.init = function (series, options, x) { + this.series = series; + this.applyOptions(options, x); + // Add a unique ID to the point if none is assigned + this.id = defined(this.id) ? this.id : uniqueKey(); + this.resolveColor(); + series.chart.pointCount++; + fireEvent(this, 'afterInit'); + return this; + }; + /** + * Transform number or array configs into objects. Also called for object + * configs. Used internally to unify the different configuration formats for + * points. For example, a simple number `10` in a line series will be + * transformed to `{ y: 10 }`, and an array config like `[1, 10]` in a + * scatter series will be transformed to `{ x: 1, y: 10 }`. + * + * @function Highcharts.Point#optionsToObject + * + * @param {Highcharts.PointOptionsType} options + * The input option. + * + * @return {Highcharts.Dictionary<*>} + * Transformed options. + */ + Point.prototype.optionsToObject = function (options) { + var ret = {}, series = this.series, keys = series.options.keys, pointArrayMap = keys || series.pointArrayMap || ['y'], valueCount = pointArrayMap.length, firstItemType, i = 0, j = 0; + if (isNumber(options) || options === null) { + ret[pointArrayMap[0]] = options; + } + else if (isArray(options)) { + // with leading x value + if (!keys && options.length > valueCount) { + firstItemType = typeof options[0]; + if (firstItemType === 'string') { + ret.name = options[0]; + } + else if (firstItemType === 'number') { + ret.x = options[0]; + } + i++; + } + while (j < valueCount) { + // Skip undefined positions for keys + if (!keys || typeof options[i] !== 'undefined') { + if (pointArrayMap[j].indexOf('.') > 0) { + // Handle nested keys, e.g. ['color.pattern.image'] + // Avoid function call unless necessary. + Point.prototype.setNestedProperty(ret, options[i], pointArrayMap[j]); + } + else { + ret[pointArrayMap[j]] = options[i]; + } + } + i++; + j++; + } + } + else if (typeof options === 'object') { + ret = options; + // This is the fastest way to detect if there are individual point + // dataLabels that need to be considered in drawDataLabels. These + // can only occur in object configs. + if (options.dataLabels) { + series._hasPointLabels = true; + } + // Same approach as above for markers + if (options.marker) { + series._hasPointMarkers = true; + } + } + return ret; + }; + /** + * @private + * @function Highcharts.Point#resolveColor + * @return {void} + */ + Point.prototype.resolveColor = function () { + var series = this.series, colors, optionsChart = series.chart.options.chart, colorCount = optionsChart.colorCount, styledMode = series.chart.styledMode, colorIndex; + // remove points nonZonedColor for later recalculation + delete this.nonZonedColor; + /** + * The point's current color. + * + * @name Highcharts.Point#color + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined} + */ + if (!styledMode && !this.options.color) { + this.color = series.color; // #3445 + } + if (series.options.colorByPoint) { + if (!styledMode) { + colors = series.options.colors || series.chart.options.colors; + this.color = this.color || colors[series.colorCounter]; + colorCount = colors.length; + } + colorIndex = series.colorCounter; + series.colorCounter++; + // loop back to zero + if (series.colorCounter === colorCount) { + series.colorCounter = 0; + } + } + else { + colorIndex = series.colorIndex; + } + this.colorIndex = pick(this.colorIndex, colorIndex); + }; + /** + * Set a value in an object, on the property defined by key. The key + * supports nested properties using dot notation. The function modifies the + * input object and does not make a copy. + * + * @function Highcharts.Point#setNestedProperty + * + * @param {T} object + * The object to set the value on. + * + * @param {*} value + * The value to set. + * + * @param {string} key + * Key to the property to set. + * + * @return {T} + * The modified object. + */ + Point.prototype.setNestedProperty = function (object, value, key) { + var nestedKeys = key.split('.'); + nestedKeys.reduce(function (result, key, i, arr) { + var isLastKey = arr.length - 1 === i; + result[key] = (isLastKey ? + value : + isObject(result[key], true) ? + result[key] : + {}); + return result[key]; + }, object); + return object; + }; + /** + * Extendable method for formatting each point's tooltip line. + * + * @function Highcharts.Point#tooltipFormatter + * + * @param {string} pointFormat + * The point format. + * + * @return {string} + * A string to be concatenated in to the common tooltip text. + */ + Point.prototype.tooltipFormatter = function (pointFormat) { + // Insert options for valueDecimals, valuePrefix, and valueSuffix + var series = this.series, seriesTooltipOptions = series.tooltipOptions, valueDecimals = pick(seriesTooltipOptions.valueDecimals, ''), valuePrefix = seriesTooltipOptions.valuePrefix || '', valueSuffix = seriesTooltipOptions.valueSuffix || ''; + // Replace default point style with class name + if (series.chart.styledMode) { + pointFormat = + series.chart.tooltip.styledModeFormat(pointFormat); + } + // Loop over the point array map and replace unformatted values with + // sprintf formatting markup + (series.pointArrayMap || ['y']).forEach(function (key) { + key = '{point.' + key; // without the closing bracket + if (valuePrefix || valueSuffix) { + pointFormat = pointFormat.replace(RegExp(key + '}', 'g'), valuePrefix + key + '}' + valueSuffix); + } + pointFormat = pointFormat.replace(RegExp(key + '}', 'g'), key + ':,.' + valueDecimals + 'f}'); + }); + return format(pointFormat, { + point: this, + series: this.series + }, series.chart); + }; + return Point; + }()); + H.Point = Point; + + return H.Point; + }); + _registerModule(_modules, 'parts/Series.js', [_modules['mixins/legend-symbol.js'], _modules['parts/Globals.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js']], function (LegendSymbolMixin, H, Point, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * This is a placeholder type of the possible series options for + * [Highcharts](../highcharts/series), [Highstock](../highstock/series), + * [Highmaps](../highmaps/series), and [Gantt](../gantt/series). + * + * In TypeScript is this dynamically generated to reference all possible types + * of series options. + * + * @ignore-declaration + * @typedef {Highcharts.SeriesOptions|Highcharts.Dictionary<*>} Highcharts.SeriesOptionsType + */ + /** + * Options for `dataSorting`. + * + * @interface Highcharts.DataSortingOptionsObject + * @since 8.0.0 + */ /** + * Enable or disable data sorting for the series. + * @name Highcharts.DataSortingOptionsObject#enabled + * @type {boolean|undefined} + */ /** + * Whether to allow matching points by name in an update. + * @name Highcharts.DataSortingOptionsObject#matchByName + * @type {boolean|undefined} + */ /** + * Determines what data value should be used to sort by. + * @name Highcharts.DataSortingOptionsObject#sortKey + * @type {string|undefined} + */ + /** + * Function callback when a series has been animated. + * + * @callback Highcharts.SeriesAfterAnimateCallbackFunction + * + * @param {Highcharts.Series} this + * The series where the event occured. + * + * @param {Highcharts.SeriesAfterAnimateEventObject} event + * Event arguments. + */ + /** + * Event information regarding completed animation of a series. + * + * @interface Highcharts.SeriesAfterAnimateEventObject + */ /** + * Animated series. + * @name Highcharts.SeriesAfterAnimateEventObject#target + * @type {Highcharts.Series} + */ /** + * Event type. + * @name Highcharts.SeriesAfterAnimateEventObject#type + * @type {"afterAnimate"} + */ + /** + * Function callback when the checkbox next to the series' name in the legend is + * clicked. + * + * @callback Highcharts.SeriesCheckboxClickCallbackFunction + * + * @param {Highcharts.Series} this + * The series where the event occured. + * + * @param {Highcharts.SeriesCheckboxClickEventObject} event + * Event arguments. + */ + /** + * Event information regarding check of a series box. + * + * @interface Highcharts.SeriesCheckboxClickEventObject + */ /** + * Whether the box has been checked. + * @name Highcharts.SeriesCheckboxClickEventObject#checked + * @type {boolean} + */ /** + * Related series. + * @name Highcharts.SeriesCheckboxClickEventObject#item + * @type {Highcharts.Series} + */ /** + * Related series. + * @name Highcharts.SeriesCheckboxClickEventObject#target + * @type {Highcharts.Series} + */ /** + * Event type. + * @name Highcharts.SeriesCheckboxClickEventObject#type + * @type {"checkboxClick"} + */ + /** + * Function callback when a series is clicked. Return false to cancel toogle + * actions. + * + * @callback Highcharts.SeriesClickCallbackFunction + * + * @param {Highcharts.Series} this + * The series where the event occured. + * + * @param {Highcharts.SeriesClickEventObject} event + * Event arguments. + */ + /** + * Common information for a click event on a series. + * + * @interface Highcharts.SeriesClickEventObject + * @extends global.Event + */ /** + * Nearest point on the graph. + * @name Highcharts.SeriesClickEventObject#point + * @type {Highcharts.Point} + */ + /** + * Gets fired when the series is hidden after chart generation time, either by + * clicking the legend item or by calling `.hide()`. + * + * @callback Highcharts.SeriesHideCallbackFunction + * + * @param {Highcharts.Series} this + * The series where the event occured. + * + * @param {global.Event} event + * The event that occured. + */ + /** + * The SVG value used for the `stroke-linecap` and `stroke-linejoin` of a line + * graph. + * + * @typedef {"butt"|"round"|"square"|string} Highcharts.SeriesLinecapValue + */ + /** + * Gets fired when the legend item belonging to the series is clicked. The + * default action is to toggle the visibility of the series. This can be + * prevented by returning `false` or calling `event.preventDefault()`. + * + * @callback Highcharts.SeriesLegendItemClickCallbackFunction + * + * @param {Highcharts.Series} this + * The series where the event occured. + * + * @param {Highcharts.SeriesLegendItemClickEventObject} event + * The event that occured. + */ + /** + * Information about the event. + * + * @interface Highcharts.SeriesLegendItemClickEventObject + */ /** + * Related browser event. + * @name Highcharts.SeriesLegendItemClickEventObject#browserEvent + * @type {global.PointerEvent} + */ /** + * Prevent the default action of toggle the visibility of the series. + * @name Highcharts.SeriesLegendItemClickEventObject#preventDefault + * @type {Function} + */ /** + * Related series. + * @name Highcharts.SeriesCheckboxClickEventObject#target + * @type {Highcharts.Series} + */ /** + * Event type. + * @name Highcharts.SeriesCheckboxClickEventObject#type + * @type {"checkboxClick"} + */ + /** + * Gets fired when the mouse leaves the graph. + * + * @callback Highcharts.SeriesMouseOutCallbackFunction + * + * @param {Highcharts.Series} this + * Series where the event occured. + * + * @param {global.PointerEvent} event + * Event that occured. + */ + /** + * Gets fired when the mouse enters the graph. + * + * @callback Highcharts.SeriesMouseOverCallbackFunction + * + * @param {Highcharts.Series} this + * Series where the event occured. + * + * @param {global.PointerEvent} event + * Event that occured. + */ + /** + * Translation and scale for the plot area of a series. + * + * @interface Highcharts.SeriesPlotBoxObject + */ /** + * @name Highcharts.SeriesPlotBoxObject#scaleX + * @type {number} + */ /** + * @name Highcharts.SeriesPlotBoxObject#scaleY + * @type {number} + */ /** + * @name Highcharts.SeriesPlotBoxObject#translateX + * @type {number} + */ /** + * @name Highcharts.SeriesPlotBoxObject#translateY + * @type {number} + */ + /** + * Gets fired when the series is shown after chart generation time, either by + * clicking the legend item or by calling `.show()`. + * + * @callback Highcharts.SeriesShowCallbackFunction + * + * @param {Highcharts.Series} this + * Series where the event occured. + * + * @param {global.Event} event + * Event that occured. + */ + /** + * Possible key values for the series state options. + * + * @typedef {"hover"|"inactive"|"normal"|"select"} Highcharts.SeriesStateValue + */ + ''; // detach doclets above + var addEvent = U.addEvent, animObject = U.animObject, arrayMax = U.arrayMax, arrayMin = U.arrayMin, clamp = U.clamp, correctFloat = U.correctFloat, defined = U.defined, erase = U.erase, error = U.error, extend = U.extend, find = U.find, fireEvent = U.fireEvent, getNestedProperty = U.getNestedProperty, isArray = U.isArray, isFunction = U.isFunction, isNumber = U.isNumber, isString = U.isString, merge = U.merge, objectEach = U.objectEach, pick = U.pick, removeEvent = U.removeEvent, seriesType = U.seriesType, splat = U.splat, syncTimeout = U.syncTimeout; + var defaultOptions = H.defaultOptions, defaultPlotOptions = H.defaultPlotOptions, seriesTypes = H.seriesTypes, SVGElement = H.SVGElement, win = H.win; + /** + * This is the base series prototype that all other series types inherit from. + * A new series is initialized either through the + * [series](https://api.highcharts.com/highcharts/series) + * option structure, or after the chart is initialized, through + * {@link Highcharts.Chart#addSeries}. + * + * The object can be accessed in a number of ways. All series and point event + * handlers give a reference to the `series` object. The chart object has a + * {@link Highcharts.Chart#series|series} property that is a collection of all + * the chart's series. The point objects and axis objects also have the same + * reference. + * + * Another way to reference the series programmatically is by `id`. Add an id + * in the series configuration options, and get the series object by + * {@link Highcharts.Chart#get}. + * + * Configuration options for the series are given in three levels. Options for + * all series in a chart are given in the + * [plotOptions.series](https://api.highcharts.com/highcharts/plotOptions.series) + * object. Then options for all series of a specific type + * are given in the plotOptions of that type, for example `plotOptions.line`. + * Next, options for one single series are given in the series array, or as + * arguments to `chart.addSeries`. + * + * The data in the series is stored in various arrays. + * + * - First, `series.options.data` contains all the original config options for + * each point whether added by options or methods like `series.addPoint`. + * + * - Next, `series.data` contains those values converted to points, but in case + * the series data length exceeds the `cropThreshold`, or if the data is + * grouped, `series.data` doesn't contain all the points. It only contains the + * points that have been created on demand. + * + * - Then there's `series.points` that contains all currently visible point + * objects. In case of cropping, the cropped-away points are not part of this + * array. The `series.points` array starts at `series.cropStart` compared to + * `series.data` and `series.options.data`. If however the series data is + * grouped, these can't be correlated one to one. + * + * - `series.xData` and `series.processedXData` contain clean x values, + * equivalent to `series.data` and `series.points`. + * + * - `series.yData` and `series.processedYData` contain clean y values, + * equivalent to `series.data` and `series.points`. + * + * @class + * @name Highcharts.Series + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @param {Highcharts.SeriesOptionsType|object} options + * The series options. + */ /** + * The line series is the base type and is therefor the series base prototype. + * + * @private + * @class + * @name Highcharts.seriesTypes.line + * + * @augments Highcharts.Series + */ + H.Series = seriesType('line', + /** + * Series options for specific data and the data itself. In TypeScript you + * have to cast the series options to specific series types, to get all + * possible options for a series. + * + * @example + * // TypeScript example + * Highcharts.chart('container', { + * series: [{ + * color: '#06C', + * data: [[0, 1], [2, 3]] + * } as Highcharts.SeriesLineOptions ] + * }); + * + * @type {Array<*>} + * @apioption series + */ + /** + * An id for the series. This can be used after render time to get a pointer + * to the series object through `chart.get()`. + * + * @sample {highcharts} highcharts/plotoptions/series-id/ + * Get series by id + * + * @type {string} + * @since 1.2.0 + * @apioption series.id + */ + /** + * The index of the series in the chart, affecting the internal index in the + * `chart.series` array, the visible Z index as well as the order in the + * legend. + * + * @type {number} + * @since 2.3.0 + * @apioption series.index + */ + /** + * The sequential index of the series in the legend. + * + * @see [legend.reversed](#legend.reversed), + * [yAxis.reversedStacks](#yAxis.reversedStacks) + * + * @sample {highcharts|highstock} highcharts/series/legendindex/ + * Legend in opposite order + * + * @type {number} + * @apioption series.legendIndex + */ + /** + * The name of the series as shown in the legend, tooltip etc. + * + * @sample {highcharts} highcharts/series/name/ + * Series name + * @sample {highmaps} maps/demo/category-map/ + * Series name + * + * @type {string} + * @apioption series.name + */ + /** + * This option allows grouping series in a stacked chart. The stack option + * can be a string or anything else, as long as the grouped series' stack + * options match each other after conversion into a string. + * + * @sample {highcharts} highcharts/series/stack/ + * Stacked and grouped columns + * + * @type {number|string} + * @since 2.1 + * @product highcharts highstock + * @apioption series.stack + */ + /** + * The type of series, for example `line` or `column`. By default, the + * series type is inherited from [chart.type](#chart.type), so unless the + * chart is a combination of series types, there is no need to set it on the + * series level. + * + * @sample {highcharts} highcharts/series/type/ + * Line and column in the same chart + * @sample highcharts/series/type-dynamic/ + * Dynamic types with button selector + * @sample {highmaps} maps/demo/mapline-mappoint/ + * Multiple types in the same map + * + * @type {string} + * @apioption series.type + */ + /** + * When using dual or multiple x axes, this number defines which xAxis the + * particular series is connected to. It refers to either the + * {@link #xAxis.id|axis id} + * or the index of the axis in the xAxis array, with 0 being the first. + * + * @type {number|string} + * @default 0 + * @product highcharts highstock + * @apioption series.xAxis + */ + /** + * When using dual or multiple y axes, this number defines which yAxis the + * particular series is connected to. It refers to either the + * {@link #yAxis.id|axis id} + * or the index of the axis in the yAxis array, with 0 being the first. + * + * @sample {highcharts} highcharts/series/yaxis/ + * Apply the column series to the secondary Y axis + * + * @type {number|string} + * @default 0 + * @product highcharts highstock + * @apioption series.yAxis + */ + /** + * Define the visual z index of the series. + * + * @sample {highcharts} highcharts/plotoptions/series-zindex-default/ + * With no z index, the series defined last are on top + * @sample {highcharts} highcharts/plotoptions/series-zindex/ + * With a z index, the series with the highest z index is on top + * @sample {highstock} highcharts/plotoptions/series-zindex-default/ + * With no z index, the series defined last are on top + * @sample {highstock} highcharts/plotoptions/series-zindex/ + * With a z index, the series with the highest z index is on top + * + * @type {number} + * @product highcharts highstock + * @apioption series.zIndex + */ + null, + /** + * General options for all series types. + * + * @optionparent plotOptions.series + */ + { + /** + * The SVG value used for the `stroke-linecap` and `stroke-linejoin` + * of a line graph. Round means that lines are rounded in the ends and + * bends. + * + * @type {Highcharts.SeriesLinecapValue} + * @default round + * @since 3.0.7 + * @apioption plotOptions.line.linecap + */ + /** + * Pixel width of the graph line. + * + * @see In styled mode, the line stroke-width can be set with the + * `.highcharts-graph` class name. + * + * @sample {highcharts} highcharts/plotoptions/series-linewidth-general/ + * On all series + * @sample {highcharts} highcharts/plotoptions/series-linewidth-specific/ + * On one single series + * + * @product highcharts highstock + * + * @private + */ + lineWidth: 2, + /** + * For some series, there is a limit that shuts down initial animation + * by default when the total number of points in the chart is too high. + * For example, for a column chart and its derivatives, animation does + * not run if there is more than 250 points totally. To disable this + * cap, set `animationLimit` to `Infinity`. + * + * @type {number} + * @apioption plotOptions.series.animationLimit + */ + /** + * Allow this series' points to be selected by clicking on the graphic + * (columns, point markers, pie slices, map areas etc). + * + * The selected points can be handled by point select and unselect + * events, or collectively by the [getSelectedPoints + * ](/class-reference/Highcharts.Chart#getSelectedPoints) function. + * + * And alternative way of selecting points is through dragging. + * + * @sample {highcharts} highcharts/plotoptions/series-allowpointselect-line/ + * Line + * @sample {highcharts} highcharts/plotoptions/series-allowpointselect-column/ + * Column + * @sample {highcharts} highcharts/plotoptions/series-allowpointselect-pie/ + * Pie + * @sample {highcharts} highcharts/chart/events-selection-points/ + * Select a range of points through a drag selection + * @sample {highmaps} maps/plotoptions/series-allowpointselect/ + * Map area + * @sample {highmaps} maps/plotoptions/mapbubble-allowpointselect/ + * Map bubble + * + * @since 1.2.0 + * + * @private + */ + allowPointSelect: false, + /** + * When true, each point or column edge is rounded to its nearest pixel + * in order to render sharp on screen. In some cases, when there are a + * lot of densely packed columns, this leads to visible difference + * in column widths or distance between columns. In these cases, + * setting `crisp` to `false` may look better, even though each column + * is rendered blurry. + * + * @sample {highcharts} highcharts/plotoptions/column-crisp-false/ + * Crisp is false + * + * @since 5.0.10 + * @product highcharts highstock gantt + * + * @private + */ + crisp: true, + /** + * If true, a checkbox is displayed next to the legend item to allow + * selecting the series. The state of the checkbox is determined by + * the `selected` option. + * + * @productdesc {highmaps} + * Note that if a `colorAxis` is defined, the color axis is represented + * in the legend, not the series. + * + * @sample {highcharts} highcharts/plotoptions/series-showcheckbox-true/ + * Show select box + * + * @since 1.2.0 + * + * @private + */ + showCheckbox: false, + /** + * Enable or disable the initial animation when a series is displayed. + * The animation can also be set as a configuration object. Please + * note that this option only applies to the initial animation of the + * series itself. For other animations, see [chart.animation]( + * #chart.animation) and the animation parameter under the API methods. + * The following properties are supported: + * + * - `duration`: The duration of the animation in milliseconds. + * + * - `easing`: Can be a string reference to an easing function set on + * the `Math` object or a function. See the _Custom easing function_ + * demo below. + * + * Due to poor performance, animation is disabled in old IE browsers + * for several chart types. + * + * @sample {highcharts} highcharts/plotoptions/series-animation-disabled/ + * Animation disabled + * @sample {highcharts} highcharts/plotoptions/series-animation-slower/ + * Slower animation + * @sample {highcharts} highcharts/plotoptions/series-animation-easing/ + * Custom easing function + * @sample {highstock} stock/plotoptions/animation-slower/ + * Slower animation + * @sample {highstock} stock/plotoptions/animation-easing/ + * Custom easing function + * @sample {highmaps} maps/plotoptions/series-animation-true/ + * Animation enabled on map series + * @sample {highmaps} maps/plotoptions/mapbubble-animation-false/ + * Disabled on mapbubble series + * + * @type {boolean|Highcharts.AnimationOptionsObject} + * @default {highcharts} true + * @default {highstock} true + * @default {highmaps} false + * + * @private + */ + animation: { + /** @internal */ + duration: 1000 + }, + /** + * An additional class name to apply to the series' graphical elements. + * This option does not replace default class names of the graphical + * element. + * + * @type {string} + * @since 5.0.0 + * @apioption plotOptions.series.className + */ + /** + * Disable this option to allow series rendering in the whole plotting + * area. + * + * **Note:** Clipping should be always enabled when + * [chart.zoomType](#chart.zoomType) is set + * + * @sample {highcharts} highcharts/plotoptions/series-clip/ + * Disabled clipping + * + * @default true + * @type {boolean} + * @since 3.0.0 + * @apioption plotOptions.series.clip + */ + /** + * The main color of the series. In line type series it applies to the + * line and the point markers unless otherwise specified. In bar type + * series it applies to the bars unless a color is specified per point. + * The default value is pulled from the `options.colors` array. + * + * In styled mode, the color can be defined by the + * [colorIndex](#plotOptions.series.colorIndex) option. Also, the series + * color can be set with the `.highcharts-series`, + * `.highcharts-color-{n}`, `.highcharts-{type}-series` or + * `.highcharts-series-{n}` class, or individual classes given by the + * `className` option. + * + * @productdesc {highmaps} + * In maps, the series color is rarely used, as most choropleth maps use + * the color to denote the value of each point. The series color can + * however be used in a map with multiple series holding categorized + * data. + * + * @sample {highcharts} highcharts/plotoptions/series-color-general/ + * General plot option + * @sample {highcharts} highcharts/plotoptions/series-color-specific/ + * One specific series + * @sample {highcharts} highcharts/plotoptions/series-color-area/ + * Area color + * @sample {highcharts} highcharts/series/infographic/ + * Pattern fill + * @sample {highmaps} maps/demo/category-map/ + * Category map by multiple series + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.series.color + */ + /** + * Styled mode only. A specific color index to use for the series, so + * its graphic representations are given the class name + * `highcharts-color-{n}`. + * + * @type {number} + * @since 5.0.0 + * @apioption plotOptions.series.colorIndex + */ + /** + * Whether to connect a graph line across null points, or render a gap + * between the two points on either side of the null. + * + * @sample {highcharts} highcharts/plotoptions/series-connectnulls-false/ + * False by default + * @sample {highcharts} highcharts/plotoptions/series-connectnulls-true/ + * True + * + * @type {boolean} + * @default false + * @product highcharts highstock + * @apioption plotOptions.series.connectNulls + */ + /** + * You can set the cursor to "pointer" if you have click events attached + * to the series, to signal to the user that the points and lines can + * be clicked. + * + * In styled mode, the series cursor can be set with the same classes + * as listed under [series.color](#plotOptions.series.color). + * + * @sample {highcharts} highcharts/plotoptions/series-cursor-line/ + * On line graph + * @sample {highcharts} highcharts/plotoptions/series-cursor-column/ + * On columns + * @sample {highcharts} highcharts/plotoptions/series-cursor-scatter/ + * On scatter markers + * @sample {highstock} stock/plotoptions/cursor/ + * Pointer on a line graph + * @sample {highmaps} maps/plotoptions/series-allowpointselect/ + * Map area + * @sample {highmaps} maps/plotoptions/mapbubble-allowpointselect/ + * Map bubble + * + * @type {string|Highcharts.CursorValue} + * @apioption plotOptions.series.cursor + */ + /** + * A reserved subspace to store options and values for customized + * functionality. Here you can add additional data for your own event + * callbacks and formatter callbacks. + * + * @sample {highcharts} highcharts/point/custom/ + * Point and series with custom data + * + * @type {Highcharts.Dictionary<*>} + * @apioption plotOptions.series.custom + */ + /** + * Name of the dash style to use for the graph, or for some series types + * the outline of each shape. + * + * In styled mode, the + * [stroke dash-array](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/css/series-dashstyle/) + * can be set with the same classes as listed under + * [series.color](#plotOptions.series.color). + * + * @sample {highcharts} highcharts/plotoptions/series-dashstyle-all/ + * Possible values demonstrated + * @sample {highcharts} highcharts/plotoptions/series-dashstyle/ + * Chart suitable for printing in black and white + * @sample {highstock} highcharts/plotoptions/series-dashstyle-all/ + * Possible values demonstrated + * @sample {highmaps} highcharts/plotoptions/series-dashstyle-all/ + * Possible values demonstrated + * @sample {highmaps} maps/plotoptions/series-dashstyle/ + * Dotted borders on a map + * + * @type {Highcharts.DashStyleValue} + * @default Solid + * @since 2.1 + * @apioption plotOptions.series.dashStyle + */ + /** + * A description of the series to add to the screen reader information + * about the series. + * + * @type {string} + * @since 5.0.0 + * @requires modules/accessibility + * @apioption plotOptions.series.description + */ + /** + * Options for the series data sorting. + * + * @type {Highcharts.DataSortingOptionsObject} + * @since 8.0.0 + * @product highcharts highstock + * @apioption plotOptions.series.dataSorting + */ + /** + * Enable or disable data sorting for the series. Use [xAxis.reversed]( + * #xAxis.reversed) to change the sorting order. + * + * @sample {highcharts} highcharts/datasorting/animation/ + * Data sorting in scatter-3d + * @sample {highcharts} highcharts/datasorting/labels-animation/ + * Axis labels animation + * @sample {highcharts} highcharts/datasorting/dependent-sorting/ + * Dependent series sorting + * @sample {highcharts} highcharts/datasorting/independent-sorting/ + * Independent series sorting + * + * @type {boolean} + * @since 8.0.0 + * @apioption plotOptions.series.dataSorting.enabled + */ + /** + * Whether to allow matching points by name in an update. If this option + * is disabled, points will be matched by order. + * + * @sample {highcharts} highcharts/datasorting/match-by-name/ + * Enabled match by name + * + * @type {boolean} + * @since 8.0.0 + * @apioption plotOptions.series.dataSorting.matchByName + */ + /** + * Determines what data value should be used to sort by. + * + * @sample {highcharts} highcharts/datasorting/sort-key/ + * Sort key as `z` value + * + * @type {string} + * @since 8.0.0 + * @default y + * @apioption plotOptions.series.dataSorting.sortKey + */ + /** + * Enable or disable the mouse tracking for a specific series. This + * includes point tooltips and click events on graphs and points. For + * large datasets it improves performance. + * + * @sample {highcharts} highcharts/plotoptions/series-enablemousetracking-false/ + * No mouse tracking + * @sample {highmaps} maps/plotoptions/series-enablemousetracking-false/ + * No mouse tracking + * + * @type {boolean} + * @default true + * @apioption plotOptions.series.enableMouseTracking + */ + /** + * Whether to use the Y extremes of the total chart width or only the + * zoomed area when zooming in on parts of the X axis. By default, the + * Y axis adjusts to the min and max of the visible data. Cartesian + * series only. + * + * @type {boolean} + * @default false + * @since 4.1.6 + * @product highcharts highstock gantt + * @apioption plotOptions.series.getExtremesFromAll + */ + /** + * An array specifying which option maps to which key in the data point + * array. This makes it convenient to work with unstructured data arrays + * from different sources. + * + * @see [series.data](#series.line.data) + * + * @sample {highcharts|highstock} highcharts/series/data-keys/ + * An extended data array with keys + * @sample {highcharts|highstock} highcharts/series/data-nested-keys/ + * Nested keys used to access object properties + * + * @type {Array} + * @since 4.1.6 + * @apioption plotOptions.series.keys + */ + /** + * The line cap used for line ends and line joins on the graph. + * + * @type {Highcharts.SeriesLinecapValue} + * @default round + * @product highcharts highstock + * @apioption plotOptions.series.linecap + */ + /** + * The [id](#series.id) of another series to link to. Additionally, + * the value can be ":previous" to link to the previous series. When + * two series are linked, only the first one appears in the legend. + * Toggling the visibility of this also toggles the linked series. + * + * If master series uses data sorting and linked series does not have + * its own sorting definition, the linked series will be sorted in the + * same order as the master one. + * + * @sample {highcharts|highstock} highcharts/demo/arearange-line/ + * Linked series + * + * @type {string} + * @since 3.0 + * @product highcharts highstock gantt + * @apioption plotOptions.series.linkedTo + */ + /** + * Options for the corresponding navigator series if `showInNavigator` + * is `true` for this series. Available options are the same as any + * series, documented at [plotOptions](#plotOptions.series) and + * [series](#series). + * + * These options are merged with options in [navigator.series]( + * #navigator.series), and will take precedence if the same option is + * defined both places. + * + * @see [navigator.series](#navigator.series) + * + * @type {Highcharts.PlotSeriesOptions} + * @since 5.0.0 + * @product highstock + * @apioption plotOptions.series.navigatorOptions + */ + /** + * The color for the parts of the graph or points that are below the + * [threshold](#plotOptions.series.threshold). Note that `zones` takes + * precedence over the negative color. Using `negativeColor` is + * equivalent to applying a zone with value of 0. + * + * @see In styled mode, a negative color is applied by setting this option + * to `true` combined with the `.highcharts-negative` class name. + * + * @sample {highcharts} highcharts/plotoptions/series-negative-color/ + * Spline, area and column + * @sample {highcharts} highcharts/plotoptions/arearange-negativecolor/ + * Arearange + * @sample {highcharts} highcharts/css/series-negative-color/ + * Styled mode + * @sample {highstock} highcharts/plotoptions/series-negative-color/ + * Spline, area and column + * @sample {highstock} highcharts/plotoptions/arearange-negativecolor/ + * Arearange + * @sample {highmaps} highcharts/plotoptions/series-negative-color/ + * Spline, area and column + * @sample {highmaps} highcharts/plotoptions/arearange-negativecolor/ + * Arearange + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 3.0 + * @apioption plotOptions.series.negativeColor + */ + /** + * Same as + * [accessibility.pointDescriptionFormatter](#accessibility.pointDescriptionFormatter), + * but for an individual series. Overrides the chart wide configuration. + * + * @type {Function} + * @since 5.0.12 + * @apioption plotOptions.series.pointDescriptionFormatter + */ + /** + * If no x values are given for the points in a series, `pointInterval` + * defines the interval of the x values. For example, if a series + * contains one value every decade starting from year 0, set + * `pointInterval` to `10`. In true `datetime` axes, the `pointInterval` + * is set in milliseconds. + * + * It can be also be combined with `pointIntervalUnit` to draw irregular + * time intervals. + * + * Please note that this options applies to the _series data_, not the + * interval of the axis ticks, which is independent. + * + * @sample {highcharts} highcharts/plotoptions/series-pointstart-datetime/ + * Datetime X axis + * @sample {highstock} stock/plotoptions/pointinterval-pointstart/ + * Using pointStart and pointInterval + * + * @type {number} + * @default 1 + * @product highcharts highstock gantt + * @apioption plotOptions.series.pointInterval + */ + /** + * On datetime series, this allows for setting the + * [pointInterval](#plotOptions.series.pointInterval) to irregular time + * units, `day`, `month` and `year`. A day is usually the same as 24 + * hours, but `pointIntervalUnit` also takes the DST crossover into + * consideration when dealing with local time. Combine this option with + * `pointInterval` to draw weeks, quarters, 6 months, 10 years etc. + * + * Please note that this options applies to the _series data_, not the + * interval of the axis ticks, which is independent. + * + * @sample {highcharts} highcharts/plotoptions/series-pointintervalunit/ + * One point a month + * @sample {highstock} highcharts/plotoptions/series-pointintervalunit/ + * One point a month + * + * @type {string} + * @since 4.1.0 + * @product highcharts highstock gantt + * @validvalue ["day", "month", "year"] + * @apioption plotOptions.series.pointIntervalUnit + */ + /** + * Possible values: `"on"`, `"between"`, `number`. + * + * In a column chart, when pointPlacement is `"on"`, the point will not + * create any padding of the X axis. In a polar column chart this means + * that the first column points directly north. If the pointPlacement is + * `"between"`, the columns will be laid out between ticks. This is + * useful for example for visualising an amount between two points in + * time or in a certain sector of a polar chart. + * + * Since Highcharts 3.0.2, the point placement can also be numeric, + * where 0 is on the axis value, -0.5 is between this value and the + * previous, and 0.5 is between this value and the next. Unlike the + * textual options, numeric point placement options won't affect axis + * padding. + * + * Note that pointPlacement needs a [pointRange]( + * #plotOptions.series.pointRange) to work. For column series this is + * computed, but for line-type series it needs to be set. + * + * For the `xrange` series type and gantt charts, if the Y axis is a + * category axis, the `pointPlacement` applies to the Y axis rather than + * the (typically datetime) X axis. + * + * Defaults to `undefined` in cartesian charts, `"between"` in polar + * charts. + * + * @see [xAxis.tickmarkPlacement](#xAxis.tickmarkPlacement) + * + * @sample {highcharts|highstock} highcharts/plotoptions/series-pointplacement-between/ + * Between in a column chart + * @sample {highcharts|highstock} highcharts/plotoptions/series-pointplacement-numeric/ + * Numeric placement for custom layout + * @sample {highcharts|highstock} maps/plotoptions/heatmap-pointplacement/ + * Placement in heatmap + * + * @type {string|number} + * @since 2.3.0 + * @product highcharts highstock gantt + * @apioption plotOptions.series.pointPlacement + */ + /** + * If no x values are given for the points in a series, pointStart + * defines on what value to start. For example, if a series contains one + * yearly value starting from 1945, set pointStart to 1945. + * + * @sample {highcharts} highcharts/plotoptions/series-pointstart-linear/ + * Linear + * @sample {highcharts} highcharts/plotoptions/series-pointstart-datetime/ + * Datetime + * @sample {highstock} stock/plotoptions/pointinterval-pointstart/ + * Using pointStart and pointInterval + * + * @type {number} + * @default 0 + * @product highcharts highstock gantt + * @apioption plotOptions.series.pointStart + */ + /** + * Whether to select the series initially. If `showCheckbox` is true, + * the checkbox next to the series name in the legend will be checked + * for a selected series. + * + * @sample {highcharts} highcharts/plotoptions/series-selected/ + * One out of two series selected + * + * @type {boolean} + * @default false + * @since 1.2.0 + * @apioption plotOptions.series.selected + */ + /** + * Whether to apply a drop shadow to the graph line. Since 2.3 the + * shadow can be an object configuration containing `color`, `offsetX`, + * `offsetY`, `opacity` and `width`. + * + * @sample {highcharts} highcharts/plotoptions/series-shadow/ + * Shadow enabled + * + * @type {boolean|Highcharts.ShadowOptionsObject} + * @default false + * @apioption plotOptions.series.shadow + */ + /** + * Whether to display this particular series or series type in the + * legend. Standalone series are shown in legend by default, and linked + * series are not. Since v7.2.0 it is possible to show series that use + * colorAxis by setting this option to `true`. + * + * @sample {highcharts} highcharts/plotoptions/series-showinlegend/ + * One series in the legend, one hidden + * + * @type {boolean} + * @apioption plotOptions.series.showInLegend + */ + /** + * Whether or not to show the series in the navigator. Takes precedence + * over [navigator.baseSeries](#navigator.baseSeries) if defined. + * + * @type {boolean} + * @since 5.0.0 + * @product highstock + * @apioption plotOptions.series.showInNavigator + */ + /** + * If set to `true`, the accessibility module will skip past the points + * in this series for keyboard navigation. + * + * @type {boolean} + * @since 5.0.12 + * @apioption plotOptions.series.skipKeyboardNavigation + */ + /** + * Whether to stack the values of each series on top of each other. + * Possible values are `undefined` to disable, `"normal"` to stack by + * value or `"percent"`. When stacking is enabled, data must be sorted + * in ascending X order. A special stacking option is with the + * streamgraph series type, where the stacking option is set to + * `"stream"`. The second one is `"overlap"`, which only applies to + * waterfall series. + * + * @see [yAxis.reversedStacks](#yAxis.reversedStacks) + * + * @sample {highcharts} highcharts/plotoptions/series-stacking-line/ + * Line + * @sample {highcharts} highcharts/plotoptions/series-stacking-column/ + * Column + * @sample {highcharts} highcharts/plotoptions/series-stacking-bar/ + * Bar + * @sample {highcharts} highcharts/plotoptions/series-stacking-area/ + * Area + * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-line/ + * Line + * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-column/ + * Column + * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-bar/ + * Bar + * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-area/ + * Area + * @sample {highcharts} highcharts/plotoptions/series-waterfall-with-normal-stacking + * Waterfall with normal stacking + * @sample {highcharts} highcharts/plotoptions/series-waterfall-with-overlap-stacking + * Waterfall with overlap stacking + * @sample {highstock} stock/plotoptions/stacking/ + * Area + * + * @type {string} + * @product highcharts highstock + * @validvalue ["normal", "overlap", "percent", "stream"] + * @apioption plotOptions.series.stacking + */ + /** + * Whether to apply steps to the line. Possible values are `left`, + * `center` and `right`. + * + * @sample {highcharts} highcharts/plotoptions/line-step/ + * Different step line options + * @sample {highcharts} highcharts/plotoptions/area-step/ + * Stepped, stacked area + * @sample {highstock} stock/plotoptions/line-step/ + * Step line + * + * @type {string} + * @since 1.2.5 + * @product highcharts highstock + * @validvalue ["left", "center", "right"] + * @apioption plotOptions.series.step + */ + /** + * The threshold, also called zero level or base level. For line type + * series this is only used in conjunction with + * [negativeColor](#plotOptions.series.negativeColor). + * + * @see [softThreshold](#plotOptions.series.softThreshold). + * + * @type {number} + * @default 0 + * @since 3.0 + * @product highcharts highstock + * @apioption plotOptions.series.threshold + */ + /** + * Set the initial visibility of the series. + * + * @sample {highcharts} highcharts/plotoptions/series-visible/ + * Two series, one hidden and one visible + * @sample {highstock} stock/plotoptions/series-visibility/ + * Hidden series + * + * @type {boolean} + * @default true + * @apioption plotOptions.series.visible + */ + /** + * Defines the Axis on which the zones are applied. + * + * @see [zones](#plotOptions.series.zones) + * + * @sample {highcharts} highcharts/series/color-zones-zoneaxis-x/ + * Zones on the X-Axis + * @sample {highstock} highcharts/series/color-zones-zoneaxis-x/ + * Zones on the X-Axis + * + * @type {string} + * @default y + * @since 4.1.0 + * @product highcharts highstock + * @apioption plotOptions.series.zoneAxis + */ + /** + * General event handlers for the series items. These event hooks can + * also be attached to the series at run time using the + * `Highcharts.addEvent` function. + * + * @declare Highcharts.SeriesEventsOptionsObject + * + * @private + */ + events: {}, + /** + * Fires after the series has finished its initial animation, or in case + * animation is disabled, immediately as the series is displayed. + * + * @sample {highcharts} highcharts/plotoptions/series-events-afteranimate/ + * Show label after animate + * @sample {highstock} highcharts/plotoptions/series-events-afteranimate/ + * Show label after animate + * + * @type {Highcharts.SeriesAfterAnimateCallbackFunction} + * @since 4.0 + * @product highcharts highstock gantt + * @context Highcharts.Series + * @apioption plotOptions.series.events.afterAnimate + */ + /** + * Fires when the checkbox next to the series' name in the legend is + * clicked. One parameter, `event`, is passed to the function. The state + * of the checkbox is found by `event.checked`. The checked item is + * found by `event.item`. Return `false` to prevent the default action + * which is to toggle the select state of the series. + * + * @sample {highcharts} highcharts/plotoptions/series-events-checkboxclick/ + * Alert checkbox status + * + * @type {Highcharts.SeriesCheckboxClickCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Series + * @apioption plotOptions.series.events.checkboxClick + */ + /** + * Fires when the series is clicked. One parameter, `event`, is passed + * to the function, containing common event information. Additionally, + * `event.point` holds a pointer to the nearest point on the graph. + * + * @sample {highcharts} highcharts/plotoptions/series-events-click/ + * Alert click info + * @sample {highstock} stock/plotoptions/series-events-click/ + * Alert click info + * @sample {highmaps} maps/plotoptions/series-events-click/ + * Display click info in subtitle + * + * @type {Highcharts.SeriesClickCallbackFunction} + * @context Highcharts.Series + * @apioption plotOptions.series.events.click + */ + /** + * Fires when the series is hidden after chart generation time, either + * by clicking the legend item or by calling `.hide()`. + * + * @sample {highcharts} highcharts/plotoptions/series-events-hide/ + * Alert when the series is hidden by clicking the legend item + * + * @type {Highcharts.SeriesHideCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Series + * @apioption plotOptions.series.events.hide + */ + /** + * Fires when the legend item belonging to the series is clicked. One + * parameter, `event`, is passed to the function. The default action + * is to toggle the visibility of the series. This can be prevented + * by returning `false` or calling `event.preventDefault()`. + * + * @sample {highcharts} highcharts/plotoptions/series-events-legenditemclick/ + * Confirm hiding and showing + * + * @type {Highcharts.SeriesLegendItemClickCallbackFunction} + * @context Highcharts.Series + * @apioption plotOptions.series.events.legendItemClick + */ + /** + * Fires when the mouse leaves the graph. One parameter, `event`, is + * passed to the function, containing common event information. If the + * [stickyTracking](#plotOptions.series) option is true, `mouseOut` + * doesn't happen before the mouse enters another graph or leaves the + * plot area. + * + * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-sticky/ + * With sticky tracking by default + * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-no-sticky/ + * Without sticky tracking + * + * @type {Highcharts.SeriesMouseOutCallbackFunction} + * @context Highcharts.Series + * @apioption plotOptions.series.events.mouseOut + */ + /** + * Fires when the mouse enters the graph. One parameter, `event`, is + * passed to the function, containing common event information. + * + * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-sticky/ + * With sticky tracking by default + * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-no-sticky/ + * Without sticky tracking + * + * @type {Highcharts.SeriesMouseOverCallbackFunction} + * @context Highcharts.Series + * @apioption plotOptions.series.events.mouseOver + */ + /** + * Fires when the series is shown after chart generation time, either + * by clicking the legend item or by calling `.show()`. + * + * @sample {highcharts} highcharts/plotoptions/series-events-show/ + * Alert when the series is shown by clicking the legend item. + * + * @type {Highcharts.SeriesShowCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Series + * @apioption plotOptions.series.events.show + */ + /** + * Options for the point markers of line-like series. Properties like + * `fillColor`, `lineColor` and `lineWidth` define the visual appearance + * of the markers. Other series types, like column series, don't have + * markers, but have visual options on the series level instead. + * + * In styled mode, the markers can be styled with the + * `.highcharts-point`, `.highcharts-point-hover` and + * `.highcharts-point-select` class names. + * + * @declare Highcharts.PointMarkerOptionsObject + * + * @private + */ + marker: { + /** + * Enable or disable the point marker. If `undefined`, the markers + * are hidden when the data is dense, and shown for more widespread + * data points. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-enabled/ + * Disabled markers + * @sample {highcharts} highcharts/plotoptions/series-marker-enabled-false/ + * Disabled in normal state but enabled on hover + * @sample {highstock} stock/plotoptions/series-marker/ + * Enabled markers + * + * @type {boolean} + * @default {highcharts} undefined + * @default {highstock} false + * @apioption plotOptions.series.marker.enabled + */ + /** + * The threshold for how dense the point markers should be before + * they are hidden, given that `enabled` is not defined. The number + * indicates the horizontal distance between the two closest points + * in the series, as multiples of the `marker.radius`. In other + * words, the default value of 2 means points are hidden if + * overlapping horizontally. + * + * @sample highcharts/plotoptions/series-marker-enabledthreshold + * A higher threshold + * + * @since 6.0.5 + */ + enabledThreshold: 2, + /** + * The fill color of the point marker. When `undefined`, the series' + * or point's color is used. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-fillcolor/ + * White fill + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.series.marker.fillColor + */ + /** + * Image markers only. Set the image width explicitly. When using + * this option, a `width` must also be set. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-width-height/ + * Fixed width and height + * @sample {highstock} highcharts/plotoptions/series-marker-width-height/ + * Fixed width and height + * + * @type {number} + * @since 4.0.4 + * @apioption plotOptions.series.marker.height + */ + /** + * The color of the point marker's outline. When `undefined`, the + * series' or point's color is used. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-fillcolor/ + * Inherit from series color (undefined) + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + lineColor: '#ffffff', + /** + * The width of the point marker's outline. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-fillcolor/ + * 2px blue marker + */ + lineWidth: 0, + /** + * The radius of the point marker. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-radius/ + * Bigger markers + * + * @default {highstock} 2 + */ + radius: 4, + /** + * A predefined shape or symbol for the marker. When undefined, the + * symbol is pulled from options.symbols. Other possible values are + * `'circle'`, `'square'`,`'diamond'`, `'triangle'` and + * `'triangle-down'`. + * + * Additionally, the URL to a graphic can be given on this form: + * `'url(graphic.png)'`. Note that for the image to be applied to + * exported charts, its URL needs to be accessible by the export + * server. + * + * Custom callbacks for symbol path generation can also be added to + * `Highcharts.SVGRenderer.prototype.symbols`. The callback is then + * used by its method name, as shown in the demo. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-symbol/ + * Predefined, graphic and custom markers + * @sample {highstock} highcharts/plotoptions/series-marker-symbol/ + * Predefined, graphic and custom markers + * + * @type {string} + * @apioption plotOptions.series.marker.symbol + */ + /** + * Image markers only. Set the image width explicitly. When using + * this option, a `height` must also be set. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-width-height/ + * Fixed width and height + * @sample {highstock} highcharts/plotoptions/series-marker-width-height/ + * Fixed width and height + * + * @type {number} + * @since 4.0.4 + * @apioption plotOptions.series.marker.width + */ + /** + * States for a single point marker. + * + * @declare Highcharts.PointStatesOptionsObject + */ + states: { + /** + * The normal state of a single point marker. Currently only + * used for setting animation when returning to normal state + * from hover. + * + * @declare Highcharts.PointStatesNormalOptionsObject + */ + normal: { + /** + * Animation when returning to normal state after hovering. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + */ + animation: true + }, + /** + * The hover state for a single point marker. + * + * @declare Highcharts.PointStatesHoverOptionsObject + */ + hover: { + /** + * Animation when hovering over the marker. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + */ + animation: { + /** @internal */ + duration: 50 + }, + /** + * Enable or disable the point marker. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-enabled/ + * Disabled hover state + */ + enabled: true, + /** + * The fill color of the marker in hover state. When + * `undefined`, the series' or point's fillColor for normal + * state is used. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.series.marker.states.hover.fillColor + */ + /** + * The color of the point marker's outline. When + * `undefined`, the series' or point's lineColor for normal + * state is used. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-linecolor/ + * White fill color, black line color + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.series.marker.states.hover.lineColor + */ + /** + * The width of the point marker's outline. When + * `undefined`, the series' or point's lineWidth for normal + * state is used. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-linewidth/ + * 3px line width + * + * @type {number} + * @apioption plotOptions.series.marker.states.hover.lineWidth + */ + /** + * The radius of the point marker. In hover state, it + * defaults to the normal state's radius + 2 as per the + * [radiusPlus](#plotOptions.series.marker.states.hover.radiusPlus) + * option. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-radius/ + * 10px radius + * + * @type {number} + * @apioption plotOptions.series.marker.states.hover.radius + */ + /** + * The number of pixels to increase the radius of the + * hovered point. + * + * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidthplus/ + * 5 pixels greater radius on hover + * @sample {highstock} highcharts/plotoptions/series-states-hover-linewidthplus/ + * 5 pixels greater radius on hover + * + * @since 4.0.3 + */ + radiusPlus: 2, + /** + * The additional line width for a hovered point. + * + * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidthplus/ + * 2 pixels wider on hover + * @sample {highstock} highcharts/plotoptions/series-states-hover-linewidthplus/ + * 2 pixels wider on hover + * + * @since 4.0.3 + */ + lineWidthPlus: 1 + }, + /** + * The appearance of the point marker when selected. In order to + * allow a point to be selected, set the + * `series.allowPointSelect` option to true. + * + * @declare Highcharts.PointStatesSelectOptionsObject + */ + select: { + /** + * Enable or disable visible feedback for selection. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-enabled/ + * Disabled select state + * + * @type {boolean} + * @default true + * @apioption plotOptions.series.marker.states.select.enabled + */ + /** + * The radius of the point marker. In hover state, it + * defaults to the normal state's radius + 2. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-radius/ + * 10px radius for selected points + * + * @type {number} + * @apioption plotOptions.series.marker.states.select.radius + */ + /** + * The fill color of the point marker. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-fillcolor/ + * Solid red discs for selected points + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + fillColor: '#cccccc', + /** + * The color of the point marker's outline. When + * `undefined`, the series' or point's color is used. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-linecolor/ + * Red line color for selected points + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + lineColor: '#000000', + /** + * The width of the point marker's outline. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-linewidth/ + * 3px line width for selected points + */ + lineWidth: 2 + } + } + }, + /** + * Properties for each single point. + * + * @declare Highcharts.PlotSeriesPointOptions + * + * @private + */ + point: { + /** + * Fires when a point is clicked. One parameter, `event`, is passed + * to the function, containing common event information. + * + * If the `series.allowPointSelect` option is true, the default + * action for the point's click event is to toggle the point's + * select state. Returning `false` cancels this action. + * + * @sample {highcharts} highcharts/plotoptions/series-point-events-click/ + * Click marker to alert values + * @sample {highcharts} highcharts/plotoptions/series-point-events-click-column/ + * Click column + * @sample {highcharts} highcharts/plotoptions/series-point-events-click-url/ + * Go to URL + * @sample {highmaps} maps/plotoptions/series-point-events-click/ + * Click marker to display values + * @sample {highmaps} maps/plotoptions/series-point-events-click-url/ + * Go to URL + * + * @type {Highcharts.PointClickCallbackFunction} + * @context Highcharts.Point + * @apioption plotOptions.series.point.events.click + */ + /** + * Fires when the mouse leaves the area close to the point. One + * parameter, `event`, is passed to the function, containing common + * event information. + * + * @sample {highcharts} highcharts/plotoptions/series-point-events-mouseover/ + * Show values in the chart's corner on mouse over + * + * @type {Highcharts.PointMouseOutCallbackFunction} + * @context Highcharts.Point + * @apioption plotOptions.series.point.events.mouseOut + */ + /** + * Fires when the mouse enters the area close to the point. One + * parameter, `event`, is passed to the function, containing common + * event information. + * + * @sample {highcharts} highcharts/plotoptions/series-point-events-mouseover/ + * Show values in the chart's corner on mouse over + * + * @type {Highcharts.PointMouseOverCallbackFunction} + * @context Highcharts.Point + * @apioption plotOptions.series.point.events.mouseOver + */ + /** + * Fires when the point is removed using the `.remove()` method. One + * parameter, `event`, is passed to the function. Returning `false` + * cancels the operation. + * + * @sample {highcharts} highcharts/plotoptions/series-point-events-remove/ + * Remove point and confirm + * + * @type {Highcharts.PointRemoveCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Point + * @apioption plotOptions.series.point.events.remove + */ + /** + * Fires when the point is selected either programmatically or + * following a click on the point. One parameter, `event`, is passed + * to the function. Returning `false` cancels the operation. + * + * @sample {highcharts} highcharts/plotoptions/series-point-events-select/ + * Report the last selected point + * @sample {highmaps} maps/plotoptions/series-allowpointselect/ + * Report select and unselect + * + * @type {Highcharts.PointSelectCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Point + * @apioption plotOptions.series.point.events.select + */ + /** + * Fires when the point is unselected either programmatically or + * following a click on the point. One parameter, `event`, is passed + * to the function. + * Returning `false` cancels the operation. + * + * @sample {highcharts} highcharts/plotoptions/series-point-events-unselect/ + * Report the last unselected point + * @sample {highmaps} maps/plotoptions/series-allowpointselect/ + * Report select and unselect + * + * @type {Highcharts.PointUnselectCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Point + * @apioption plotOptions.series.point.events.unselect + */ + /** + * Fires when the point is updated programmatically through the + * `.update()` method. One parameter, `event`, is passed to the + * function. The new point options can be accessed through + * `event.options`. Returning `false` cancels the operation. + * + * @sample {highcharts} highcharts/plotoptions/series-point-events-update/ + * Confirm point updating + * + * @type {Highcharts.PointUpdateCallbackFunction} + * @since 1.2.0 + * @context Highcharts.Point + * @apioption plotOptions.series.point.events.update + */ + /** + * Events for each single point. + * + * @declare Highcharts.PointEventsOptionsObject + */ + events: {} + }, + /** + * Options for the series data labels, appearing next to each data + * point. + * + * Since v6.2.0, multiple data labels can be applied to each single + * point by defining them as an array of configs. + * + * In styled mode, the data labels can be styled with the + * `.highcharts-data-label-box` and `.highcharts-data-label` class names + * ([see example](https://www.highcharts.com/samples/highcharts/css/series-datalabels)). + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-enabled + * Data labels enabled + * @sample {highcharts} highcharts/plotoptions/series-datalabels-multiple + * Multiple data labels on a bar series + * @sample {highcharts} highcharts/css/series-datalabels + * Style mode example + * + * @type {*|Array<*>} + * @product highcharts highstock highmaps gantt + * + * @private + */ + dataLabels: { + /** + * The alignment of the data label compared to the point. If + * `right`, the right side of the label should be touching the + * point. For points with an extent, like columns, the alignments + * also dictates how to align it inside the box, as given with the + * [inside](#plotOptions.column.dataLabels.inside) + * option. Can be one of `left`, `center` or `right`. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-align-left/ + * Left aligned + * @sample {highcharts} highcharts/plotoptions/bar-datalabels-align-inside-bar/ + * Data labels inside the bar + * + * @type {Highcharts.AlignValue|null} + */ + align: 'center', + /** + * Whether to allow data labels to overlap. To make the labels less + * sensitive for overlapping, the + * [dataLabels.padding](#plotOptions.series.dataLabels.padding) + * can be set to 0. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-allowoverlap-false/ + * Don't allow overlap + * + * @type {boolean} + * @default false + * @since 4.1.0 + * @apioption plotOptions.series.dataLabels.allowOverlap + */ + /** + * The background color or gradient for the data label. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/ + * Data labels box options + * @sample {highmaps} maps/plotoptions/series-datalabels-box/ + * Data labels box options + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.2.1 + * @apioption plotOptions.series.dataLabels.backgroundColor + */ + /** + * The border color for the data label. Defaults to `undefined`. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/ + * Data labels box options + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.2.1 + * @apioption plotOptions.series.dataLabels.borderColor + */ + /** + * The border radius in pixels for the data label. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/ + * Data labels box options + * @sample {highmaps} maps/plotoptions/series-datalabels-box/ + * Data labels box options + * + * @type {number} + * @default 0 + * @since 2.2.1 + * @apioption plotOptions.series.dataLabels.borderRadius + */ + /** + * The border width in pixels for the data label. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/ + * Data labels box options + * + * @type {number} + * @default 0 + * @since 2.2.1 + * @apioption plotOptions.series.dataLabels.borderWidth + */ + /** + * A class name for the data label. Particularly in styled mode, + * this can be used to give each series' or point's data label + * unique styling. In addition to this option, a default color class + * name is added so that we can give the labels a contrast text + * shadow. + * + * @sample {highcharts} highcharts/css/data-label-contrast/ + * Contrast text shadow + * @sample {highcharts} highcharts/css/series-datalabels/ + * Styling by CSS + * + * @type {string} + * @since 5.0.0 + * @apioption plotOptions.series.dataLabels.className + */ + /** + * The text color for the data labels. Defaults to `undefined`. For + * certain series types, like column or map, the data labels can be + * drawn inside the points. In this case the data label will be + * drawn with maximum contrast by default. Additionally, it will be + * given a `text-outline` style with the opposite color, to further + * increase the contrast. This can be overridden by setting the + * `text-outline` style to `none` in the `dataLabels.style` option. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-color/ + * Red data labels + * @sample {highmaps} maps/demo/color-axis/ + * White data labels + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.series.dataLabels.color + */ + /** + * Whether to hide data labels that are outside the plot area. By + * default, the data label is moved inside the plot area according + * to the + * [overflow](#plotOptions.series.dataLabels.overflow) + * option. + * + * @type {boolean} + * @default true + * @since 2.3.3 + * @apioption plotOptions.series.dataLabels.crop + */ + /** + * Whether to defer displaying the data labels until the initial + * series animation has finished. + * + * @type {boolean} + * @default true + * @since 4.0.0 + * @product highcharts highstock gantt + * @apioption plotOptions.series.dataLabels.defer + */ + /** + * Enable or disable the data labels. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-enabled/ + * Data labels enabled + * @sample {highmaps} maps/demo/color-axis/ + * Data labels enabled + * + * @type {boolean} + * @default false + * @apioption plotOptions.series.dataLabels.enabled + */ + /** + * A declarative filter to control of which data labels to display. + * The declarative filter is designed for use when callback + * functions are not available, like when the chart options require + * a pure JSON structure or for use with graphical editors. For + * programmatic control, use the `formatter` instead, and return + * `undefined` to disable a single data label. + * + * @example + * filter: { + * property: 'percentage', + * operator: '>', + * value: 4 + * } + * + * @sample {highcharts} highcharts/demo/pie-monochrome + * Data labels filtered by percentage + * + * @declare Highcharts.DataLabelsFilterOptionsObject + * @since 6.0.3 + * @apioption plotOptions.series.dataLabels.filter + */ + /** + * The operator to compare by. Can be one of `>`, `<`, `>=`, `<=`, + * `==`, and `===`. + * + * @type {string} + * @validvalue [">", "<", ">=", "<=", "==", "==="] + * @apioption plotOptions.series.dataLabels.filter.operator + */ + /** + * The point property to filter by. Point options are passed + * directly to properties, additionally there are `y` value, + * `percentage` and others listed under {@link Highcharts.Point} + * members. + * + * @type {string} + * @apioption plotOptions.series.dataLabels.filter.property + */ + /** + * The value to compare against. + * + * @type {number} + * @apioption plotOptions.series.dataLabels.filter.value + */ + /** + * A + * [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) + * for the data label. Available variables are the same as for + * `formatter`. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-format/ + * Add a unit + * @sample {highmaps} maps/plotoptions/series-datalabels-format/ + * Formatted value in the data label + * + * @type {string} + * @default y + * @default point.value + * @since 3.0 + * @apioption plotOptions.series.dataLabels.format + */ + // eslint-disable-next-line valid-jsdoc + /** + * Callback JavaScript function to format the data label. Note that + * if a `format` is defined, the format takes precedence and the + * formatter is ignored. + * + * @sample {highmaps} maps/plotoptions/series-datalabels-format/ + * Formatted value + * + * @type {Highcharts.DataLabelsFormatterCallbackFunction} + */ + formatter: function () { + var numberFormatter = this.series.chart.numberFormatter; + return typeof this.y !== 'number' ? '' : numberFormatter(this.y, -1); + }, + /** + * For points with an extent, like columns or map areas, whether to + * align the data label inside the box or to the actual value point. + * Defaults to `false` in most cases, `true` in stacked columns. + * + * @type {boolean} + * @since 3.0 + * @apioption plotOptions.series.dataLabels.inside + */ + /** + * Format for points with the value of null. Works analogously to + * [format](#plotOptions.series.dataLabels.format). `nullFormat` can + * be applied only to series which support displaying null points. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-format/ + * Format data label and tooltip for null point. + * + * @type {boolean|string} + * @since 7.1.0 + * @apioption plotOptions.series.dataLabels.nullFormat + */ + /** + * Callback JavaScript function that defines formatting for points + * with the value of null. Works analogously to + * [formatter](#plotOptions.series.dataLabels.formatter). + * `nullPointFormatter` can be applied only to series which support + * displaying null points. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-format/ + * Format data label and tooltip for null point. + * + * @type {Highcharts.DataLabelsFormatterCallbackFunction} + * @since 7.1.0 + * @apioption plotOptions.series.dataLabels.nullFormatter + */ + /** + * How to handle data labels that flow outside the plot area. The + * default is `"justify"`, which aligns them inside the plot area. + * For columns and bars, this means it will be moved inside the bar. + * To display data labels outside the plot area, set `crop` to + * `false` and `overflow` to `"allow"`. + * + * @type {Highcharts.DataLabelsOverflowValue} + * @default justify + * @since 3.0.6 + * @apioption plotOptions.series.dataLabels.overflow + */ + /** + * When either the `borderWidth` or the `backgroundColor` is set, + * this is the padding within the box. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/ + * Data labels box options + * @sample {highmaps} maps/plotoptions/series-datalabels-box/ + * Data labels box options + * + * @since 2.2.1 + */ + padding: 5, + /** + * Aligns data labels relative to points. If `center` alignment is + * not possible, it defaults to `right`. + * + * @type {Highcharts.AlignValue} + * @default center + * @apioption plotOptions.series.dataLabels.position + */ + /** + * Text rotation in degrees. Note that due to a more complex + * structure, backgrounds, borders and padding will be lost on a + * rotated data label. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-rotation/ + * Vertical labels + * + * @type {number} + * @default 0 + * @apioption plotOptions.series.dataLabels.rotation + */ + /** + * The shadow of the box. Works best with `borderWidth` or + * `backgroundColor`. Since 2.3 the shadow can be an object + * configuration containing `color`, `offsetX`, `offsetY`, `opacity` + * and `width`. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/ + * Data labels box options + * + * @type {boolean|Highcharts.ShadowOptionsObject} + * @default false + * @since 2.2.1 + * @apioption plotOptions.series.dataLabels.shadow + */ + /** + * The name of a symbol to use for the border around the label. + * Symbols are predefined functions on the Renderer object. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-shape/ + * A callout for annotations + * + * @type {string} + * @default square + * @since 4.1.2 + * @apioption plotOptions.series.dataLabels.shape + */ + /** + * Styles for the label. The default `color` setting is + * `"contrast"`, which is a pseudo color that Highcharts picks up + * and applies the maximum contrast to the underlying point item, + * for example the bar in a bar chart. + * + * The `textOutline` is a pseudo property that applies an outline of + * the given width with the given color, which by default is the + * maximum contrast to the text. So a bright text color will result + * in a black text outline for maximum readability on a mixed + * background. In some cases, especially with grayscale text, the + * text outline doesn't work well, in which cases it can be disabled + * by setting it to `"none"`. When `useHTML` is true, the + * `textOutline` will not be picked up. In this, case, the same + * effect can be acheived through the `text-shadow` CSS property. + * + * For some series types, where each point has an extent, like for + * example tree maps, the data label may overflow the point. There + * are two strategies for handling overflow. By default, the text + * will wrap to multiple lines. The other strategy is to set + * `style.textOverflow` to `ellipsis`, which will keep the text on + * one line plus it will break inside long words. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-style/ + * Bold labels + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow/ + * Long labels truncated with an ellipsis in a pie + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow-wrap/ + * Long labels are wrapped in a pie + * @sample {highmaps} maps/demo/color-axis/ + * Bold labels + * + * @type {Highcharts.CSSObject} + * @since 4.1.0 + * @apioption plotOptions.series.dataLabels.style + */ + style: { + /** @internal */ + fontSize: '11px', + /** @internal */ + fontWeight: 'bold', + /** @internal */ + color: 'contrast', + /** @internal */ + textOutline: '1px contrast' + }, + /** + * Options for a label text which should follow marker's shape. + * Border and background are disabled for a label that follows a + * path. + * + * **Note:** Only SVG-based renderer supports this option. Setting + * `useHTML` to true will disable this option. + * + * @declare Highcharts.DataLabelsTextPathOptionsObject + * @since 7.1.0 + * @apioption plotOptions.series.dataLabels.textPath + */ + /** + * Presentation attributes for the text path. + * + * @type {Highcharts.SVGAttributes} + * @since 7.1.0 + * @apioption plotOptions.series.dataLabels.textPath.attributes + */ + /** + * Enable or disable `textPath` option for link's or marker's data + * labels. + * + * @type {boolean} + * @since 7.1.0 + * @apioption plotOptions.series.dataLabels.textPath.enabled + */ + /** + * Whether to + * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the labels. + * + * @type {boolean} + * @default false + * @apioption plotOptions.series.dataLabels.useHTML + */ + /** + * The vertical alignment of a data label. Can be one of `top`, + * `middle` or `bottom`. The default value depends on the data, for + * instance in a column chart, the label is above positive values + * and below negative values. + * + * @type {Highcharts.VerticalAlignValue|null} + * @since 2.3.3 + */ + verticalAlign: 'bottom', + /** + * The x position offset of the label relative to the point in + * pixels. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-rotation/ + * Vertical and positioned + * @sample {highcharts} highcharts/plotoptions/bar-datalabels-align-inside-bar/ + * Data labels inside the bar + */ + x: 0, + /** + * The Z index of the data labels. The default Z index puts it above + * the series. Use a Z index of 2 to display it behind the series. + * + * @type {number} + * @default 6 + * @since 2.3.5 + * @apioption plotOptions.series.dataLabels.z + */ + /** + * The y position offset of the label relative to the point in + * pixels. + * + * @sample {highcharts} highcharts/plotoptions/series-datalabels-rotation/ + * Vertical and positioned + */ + y: 0 + }, + /** + * When the series contains less points than the crop threshold, all + * points are drawn, even if the points fall outside the visible plot + * area at the current zoom. The advantage of drawing all points + * (including markers and columns), is that animation is performed on + * updates. On the other hand, when the series contains more points than + * the crop threshold, the series data is cropped to only contain points + * that fall within the plot area. The advantage of cropping away + * invisible points is to increase performance on large series. + * + * @since 2.2 + * @product highcharts highstock + * + * @private + */ + cropThreshold: 300, + /** + * Opacity of a series parts: line, fill (e.g. area) and dataLabels. + * + * @see [states.inactive.opacity](#plotOptions.series.states.inactive.opacity) + * + * @since 7.1.0 + * + * @private + */ + opacity: 1, + /** + * The width of each point on the x axis. For example in a column chart + * with one value each day, the pointRange would be 1 day (= 24 * 3600 + * * 1000 milliseconds). This is normally computed automatically, but + * this option can be used to override the automatic value. + * + * @product highstock + * + * @private + */ + pointRange: 0, + /** + * When this is true, the series will not cause the Y axis to cross + * the zero plane (or [threshold](#plotOptions.series.threshold) option) + * unless the data actually crosses the plane. + * + * For example, if `softThreshold` is `false`, a series of 0, 1, 2, + * 3 will make the Y axis show negative values according to the + * `minPadding` option. If `softThreshold` is `true`, the Y axis starts + * at 0. + * + * @since 4.1.9 + * @product highcharts highstock + * + * @private + */ + softThreshold: true, + /** + * @declare Highcharts.SeriesStatesOptionsObject + * + * @private + */ + states: { + /** + * The normal state of a series, or for point items in column, pie + * and similar series. Currently only used for setting animation + * when returning to normal state from hover. + * + * @declare Highcharts.SeriesStatesNormalOptionsObject + */ + normal: { + /** + * Animation when returning to normal state after hovering. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + */ + animation: true + }, + /** + * Options for the hovered series. These settings override the + * normal state options when a series is moused over or touched. + * + * @declare Highcharts.SeriesStatesHoverOptionsObject + */ + hover: { + /** + * Enable separate styles for the hovered series to visualize + * that the user hovers either the series itself or the legend. + * + * @sample {highcharts} highcharts/plotoptions/series-states-hover-enabled/ + * Line + * @sample {highcharts} highcharts/plotoptions/series-states-hover-enabled-column/ + * Column + * @sample {highcharts} highcharts/plotoptions/series-states-hover-enabled-pie/ + * Pie + * + * @type {boolean} + * @default true + * @since 1.2 + * @apioption plotOptions.series.states.hover.enabled + */ + /** + * Animation setting for hovering the graph in line-type series. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + * @since 5.0.8 + * @product highcharts highstock + */ + animation: { + /** + * The duration of the hover animation in milliseconds. By + * default the hover state animates quickly in, and slowly + * back to normal. + * + * @internal + */ + duration: 50 + }, + /** + * Pixel width of the graph line. By default this property is + * undefined, and the `lineWidthPlus` property dictates how much + * to increase the linewidth from normal state. + * + * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidth/ + * 5px line on hover + * + * @type {number} + * @product highcharts highstock + * @apioption plotOptions.series.states.hover.lineWidth + */ + /** + * The additional line width for the graph of a hovered series. + * + * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidthplus/ + * 5 pixels wider + * @sample {highstock} highcharts/plotoptions/series-states-hover-linewidthplus/ + * 5 pixels wider + * + * @since 4.0.3 + * @product highcharts highstock + */ + lineWidthPlus: 1, + /** + * In Highcharts 1.0, the appearance of all markers belonging + * to the hovered series. For settings on the hover state of the + * individual point, see + * [marker.states.hover](#plotOptions.series.marker.states.hover). + * + * @deprecated + * + * @extends plotOptions.series.marker + * @excluding states + * @product highcharts highstock + */ + marker: { + // lineWidth: base + 1, + // radius: base + 1 + }, + /** + * Options for the halo appearing around the hovered point in + * line-type series as well as outside the hovered slice in pie + * charts. By default the halo is filled by the current point or + * series color with an opacity of 0.25\. The halo can be + * disabled by setting the `halo` option to `null`. + * + * In styled mode, the halo is styled with the + * `.highcharts-halo` class, with colors inherited from + * `.highcharts-color-{n}`. + * + * @sample {highcharts} highcharts/plotoptions/halo/ + * Halo options + * @sample {highstock} highcharts/plotoptions/halo/ + * Halo options + * + * @declare Highcharts.SeriesStatesHoverHaloOptionsObject + * @type {null|*} + * @since 4.0 + * @product highcharts highstock + */ + halo: { + /** + * A collection of SVG attributes to override the appearance + * of the halo, for example `fill`, `stroke` and + * `stroke-width`. + * + * @type {Highcharts.SVGAttributes} + * @since 4.0 + * @product highcharts highstock + * @apioption plotOptions.series.states.hover.halo.attributes + */ + /** + * The pixel size of the halo. For point markers this is the + * radius of the halo. For pie slices it is the width of the + * halo outside the slice. For bubbles it defaults to 5 and + * is the width of the halo outside the bubble. + * + * @since 4.0 + * @product highcharts highstock + */ + size: 10, + /** + * Opacity for the halo unless a specific fill is overridden + * using the `attributes` setting. Note that Highcharts is + * only able to apply opacity to colors of hex or rgb(a) + * formats. + * + * @since 4.0 + * @product highcharts highstock + */ + opacity: 0.25 + } + }, + /** + * Specific options for point in selected states, after being + * selected by + * [allowPointSelect](#plotOptions.series.allowPointSelect) + * or programmatically. + * + * @sample maps/plotoptions/series-allowpointselect/ + * Allow point select demo + * + * @declare Highcharts.SeriesStatesSelectOptionsObject + * @extends plotOptions.series.states.hover + * @excluding brightness + */ + select: { + animation: { + /** @internal */ + duration: 0 + } + }, + /** + * The opposite state of a hover for series. + * + * @sample highcharts/plotoptions/series-states-inactive-disabled + * Disabled inactive state + * + * @declare Highcharts.SeriesStatesInactiveOptionsObject + */ + inactive: { + /** + * Enable or disable the inactive state for a series + * + * @sample highcharts/plotoptions/series-states-inactive-disabled + * Disabled inactive state + * + * @type {boolean} + * @default true + * @apioption plotOptions.series.states.inactive.enabled + */ + /** + * The animation for entering the inactive state. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + */ + animation: { + /** @internal */ + duration: 50 + }, + /** + * Opacity of series elements (dataLabels, line, area). + * + * @type {number} + */ + opacity: 0.2 + } + }, + /** + * Sticky tracking of mouse events. When true, the `mouseOut` event on a + * series isn't triggered until the mouse moves over another series, or + * out of the plot area. When false, the `mouseOut` event on a series is + * triggered when the mouse leaves the area around the series' graph or + * markers. This also implies the tooltip when not shared. When + * `stickyTracking` is false and `tooltip.shared` is false, the tooltip + * will be hidden when moving the mouse between series. Defaults to true + * for line and area type series, but to false for columns, pies etc. + * + * **Note:** The boost module will force this option because of + * technical limitations. + * + * @sample {highcharts} highcharts/plotoptions/series-stickytracking-true/ + * True by default + * @sample {highcharts} highcharts/plotoptions/series-stickytracking-false/ + * False + * + * @default {highcharts} true + * @default {highstock} true + * @default {highmaps} false + * @since 2.0 + * + * @private + */ + stickyTracking: true, + /** + * A configuration object for the tooltip rendering of each single + * series. Properties are inherited from [tooltip](#tooltip), but only + * the following properties can be defined on a series level. + * + * @declare Highcharts.SeriesTooltipOptionsObject + * @since 2.3 + * @extends tooltip + * @excluding animation, backgroundColor, borderColor, borderRadius, + * borderWidth, className, crosshairs, enabled, formatter, + * headerShape, hideDelay, outside, padding, positioner, + * shadow, shape, shared, snap, split, style, useHTML + * @apioption plotOptions.series.tooltip + */ + /** + * When a series contains a data array that is longer than this, only + * one dimensional arrays of numbers, or two dimensional arrays with + * x and y values are allowed. Also, only the first point is tested, + * and the rest are assumed to be the same format. This saves expensive + * data checking and indexing in long series. Set it to `0` disable. + * + * Note: + * In boost mode turbo threshold is forced. Only array of numbers or + * two dimensional arrays are allowed. + * + * @since 2.2 + * @product highcharts highstock gantt + * + * @private + */ + turboThreshold: 1000, + /** + * An array defining zones within a series. Zones can be applied to the + * X axis, Y axis or Z axis for bubbles, according to the `zoneAxis` + * option. The zone definitions have to be in ascending order regarding + * to the value. + * + * In styled mode, the color zones are styled with the + * `.highcharts-zone-{n}` class, or custom classed from the `className` + * option + * ([view live demo](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/css/color-zones/)). + * + * @see [zoneAxis](#plotOptions.series.zoneAxis) + * + * @sample {highcharts} highcharts/series/color-zones-simple/ + * Color zones + * @sample {highstock} highcharts/series/color-zones-simple/ + * Color zones + * + * @declare Highcharts.SeriesZonesOptionsObject + * @type {Array<*>} + * @since 4.1.0 + * @product highcharts highstock + * @apioption plotOptions.series.zones + */ + /** + * Styled mode only. A custom class name for the zone. + * + * @sample highcharts/css/color-zones/ + * Zones styled by class name + * + * @type {string} + * @since 5.0.0 + * @apioption plotOptions.series.zones.className + */ + /** + * Defines the color of the series. + * + * @see [series color](#plotOptions.series.color) + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 4.1.0 + * @product highcharts highstock + * @apioption plotOptions.series.zones.color + */ + /** + * A name for the dash style to use for the graph. + * + * @see [plotOptions.series.dashStyle](#plotOptions.series.dashStyle) + * + * @sample {highcharts|highstock} highcharts/series/color-zones-dashstyle-dot/ + * Dashed line indicates prognosis + * + * @type {Highcharts.DashStyleValue} + * @since 4.1.0 + * @product highcharts highstock + * @apioption plotOptions.series.zones.dashStyle + */ + /** + * Defines the fill color for the series (in area type series) + * + * @see [fillColor](#plotOptions.area.fillColor) + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 4.1.0 + * @product highcharts highstock + * @apioption plotOptions.series.zones.fillColor + */ + /** + * The value up to where the zone extends, if undefined the zones + * stretches to the last value in the series. + * + * @type {number} + * @since 4.1.0 + * @product highcharts highstock + * @apioption plotOptions.series.zones.value + */ + /** + * When using dual or multiple color axes, this number defines which + * colorAxis the particular series is connected to. It refers to + * either the + * {@link #colorAxis.id|axis id} + * or the index of the axis in the colorAxis array, with 0 being the + * first. Set this option to false to prevent a series from connecting + * to the default color axis. + * + * Since v7.2.0 the option can also be an axis id or an axis index + * instead of a boolean flag. + * + * @sample highcharts/coloraxis/coloraxis-with-pie/ + * Color axis with pie series + * @sample highcharts/coloraxis/multiple-coloraxis/ + * Multiple color axis + * + * @type {number|string|boolean} + * @default 0 + * @product highcharts highstock highmaps + * @apioption plotOptions.series.colorAxis + */ + /** + * Determines what data value should be used to calculate point color + * if `colorAxis` is used. Requires to set `min` and `max` if some + * custom point property is used or if approximation for data grouping + * is set to `'sum'`. + * + * @sample highcharts/coloraxis/custom-color-key/ + * Custom color key + * @sample highcharts/coloraxis/changed-default-color-key/ + * Changed default color key + * + * @type {string} + * @default y + * @since 7.2.0 + * @product highcharts highstock highmaps + * @apioption plotOptions.series.colorKey + */ + /** + * Determines whether the series should look for the nearest point + * in both dimensions or just the x-dimension when hovering the series. + * Defaults to `'xy'` for scatter series and `'x'` for most other + * series. If the data has duplicate x-values, it is recommended to + * set this to `'xy'` to allow hovering over all points. + * + * Applies only to series types using nearest neighbor search (not + * direct hover) for tooltip. + * + * @sample {highcharts} highcharts/series/findnearestpointby/ + * Different hover behaviors + * @sample {highstock} highcharts/series/findnearestpointby/ + * Different hover behaviors + * @sample {highmaps} highcharts/series/findnearestpointby/ + * Different hover behaviors + * + * @since 5.0.10 + * @validvalue ["x", "xy"] + * + * @private + */ + findNearestPointBy: 'x' + }, + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** @lends Highcharts.Series.prototype */ + { + axisTypes: ['xAxis', 'yAxis'], + coll: 'series', + colorCounter: 0, + cropShoulder: 1, + directTouch: false, + eventsToUnbind: [], + isCartesian: true, + // each point's x and y values are stored in this.xData and this.yData + parallelArrays: ['x', 'y'], + pointClass: Point, + requireSorting: true, + sorted: true, + init: function (chart, options) { + fireEvent(this, 'init', { options: options }); + var series = this, events, chartSeries = chart.series, lastSeries; + // A lookup over those events that are added by _options_ (not + // programmatically). These are updated through Series.update() + // (#10861). + this.eventOptions = this.eventOptions || {}; + /** + * Read only. The chart that the series belongs to. + * + * @name Highcharts.Series#chart + * @type {Highcharts.Chart} + */ + series.chart = chart; + /** + * Read only. The series' type, like "line", "area", "column" etc. + * The type in the series options anc can be altered using + * {@link Series#update}. + * + * @name Highcharts.Series#type + * @type {string} + */ + /** + * Read only. The series' current options. To update, use + * {@link Series#update}. + * + * @name Highcharts.Series#options + * @type {Highcharts.SeriesOptionsType} + */ + series.options = options = series.setOptions(options); + series.linkedSeries = []; + // bind the axes + series.bindAxes(); + // set some variables + extend(series, { + /** + * The series name as given in the options. Defaults to + * "Series {n}". + * + * @name Highcharts.Series#name + * @type {string} + */ + name: options.name, + state: '', + /** + * Read only. The series' visibility state as set by {@link + * Series#show}, {@link Series#hide}, or in the initial + * configuration. + * + * @name Highcharts.Series#visible + * @type {boolean} + */ + visible: options.visible !== false, + /** + * Read only. The series' selected state as set by {@link + * Highcharts.Series#select}. + * + * @name Highcharts.Series#selected + * @type {boolean} + */ + selected: options.selected === true // false by default + }); + // Register event listeners + events = options.events; + objectEach(events, function (event, eventType) { + if (isFunction(event)) { + // If event does not exist, or is changed by Series.update + if (series.eventOptions[eventType] !== event) { + // Remove existing if set by option + if (isFunction(series.eventOptions[eventType])) { + removeEvent(series, eventType, series.eventOptions[eventType]); + } + series.eventOptions[eventType] = event; + addEvent(series, eventType, event); + } + } + }); + if ((events && events.click) || + (options.point && + options.point.events && + options.point.events.click) || + options.allowPointSelect) { + chart.runTrackerClick = true; + } + series.getColor(); + series.getSymbol(); + // Initialize the parallel data arrays + series.parallelArrays.forEach(function (key) { + if (!series[key + 'Data']) { + series[key + 'Data'] = []; + } + }); + // Mark cartesian + if (series.isCartesian) { + chart.hasCartesianSeries = true; + } + // Get the index and register the series in the chart. The index is + // one more than the current latest series index (#5960). + if (chartSeries.length) { + lastSeries = chartSeries[chartSeries.length - 1]; + } + series._i = pick(lastSeries && lastSeries._i, -1) + 1; + // Insert the series and re-order all series above the insertion + // point. + chart.orderSeries(this.insert(chartSeries)); + // Set options for series with sorting and set data later. + if (options.dataSorting && options.dataSorting.enabled) { + series.setDataSortingOptions(); + } + else if (!series.points && !series.data) { + series.setData(options.data, false); + } + fireEvent(this, 'afterInit'); + }, + /** + * Check whether the series item is itself or inherits from a certain + * series type. + * + * @function Highcharts.Series#is + * @param {string} type The type of series to check for, can be either + * featured or custom series types. For example `column`, `pie`, + * `ohlc` etc. + * + * @return {boolean} + * True if this item is or inherits from the given type. + */ + is: function (type) { + return seriesTypes[type] && this instanceof seriesTypes[type]; + }, + /** + * Insert the series in a collection with other series, either the chart + * series or yAxis series, in the correct order according to the index + * option. Used internally when adding series. + * + * @private + * @function Highcharts.Series#insert + * @param {Array} collection + * A collection of series, like `chart.series` or `xAxis.series`. + * @return {number} + * The index of the series in the collection. + */ + insert: function (collection) { + var indexOption = this.options.index, i; + // Insert by index option + if (isNumber(indexOption)) { + i = collection.length; + while (i--) { + // Loop down until the interted element has higher index + if (indexOption >= + pick(collection[i].options.index, collection[i]._i)) { + collection.splice(i + 1, 0, this); + break; + } + } + if (i === -1) { + collection.unshift(this); + } + i = i + 1; + // Or just push it to the end + } + else { + collection.push(this); + } + return pick(i, collection.length - 1); + }, + /** + * Set the xAxis and yAxis properties of cartesian series, and register + * the series in the `axis.series` array. + * + * @private + * @function Highcharts.Series#bindAxes + * @return {void} + * @exception 18 + */ + bindAxes: function () { + var series = this, seriesOptions = series.options, chart = series.chart, axisOptions; + fireEvent(this, 'bindAxes', null, function () { + // repeat for xAxis and yAxis + (series.axisTypes || []).forEach(function (AXIS) { + // loop through the chart's axis objects + chart[AXIS].forEach(function (axis) { + axisOptions = axis.options; + // apply if the series xAxis or yAxis option mathches + // the number of the axis, or if undefined, use the + // first axis + if (seriesOptions[AXIS] === + axisOptions.index || + (typeof seriesOptions[AXIS] !== + 'undefined' && + seriesOptions[AXIS] === axisOptions.id) || + (typeof seriesOptions[AXIS] === + 'undefined' && + axisOptions.index === 0)) { + // register this series in the axis.series lookup + series.insert(axis.series); + // set this series.xAxis or series.yAxis reference + /** + * Read only. The unique xAxis object associated + * with the series. + * + * @name Highcharts.Series#xAxis + * @type {Highcharts.Axis} + */ + /** + * Read only. The unique yAxis object associated + * with the series. + * + * @name Highcharts.Series#yAxis + * @type {Highcharts.Axis} + */ + series[AXIS] = axis; + // mark dirty for redraw + axis.isDirty = true; + } + }); + // The series needs an X and an Y axis + if (!series[AXIS] && + series.optionalAxis !== AXIS) { + error(18, true, chart); + } + }); + }); + fireEvent(this, 'afterBindAxes'); + }, + /** + * For simple series types like line and column, the data values are + * held in arrays like xData and yData for quick lookup to find extremes + * and more. For multidimensional series like bubble and map, this can + * be extended with arrays like zData and valueData by adding to the + * `series.parallelArrays` array. + * + * @private + * @function Highcharts.Series#updateParallelArrays + * @param {Highcharts.Point} point + * @param {number|string} i + * @return {void} + */ + updateParallelArrays: function (point, i) { + var series = point.series, args = arguments, fn = isNumber(i) ? + // Insert the value in the given position + function (key) { + var val = key === 'y' && series.toYData ? + series.toYData(point) : + point[key]; + series[key + 'Data'][i] = val; + } : + // Apply the method specified in i with the following + // arguments as arguments + function (key) { + Array.prototype[i].apply(series[key + 'Data'], Array.prototype.slice.call(args, 2)); + }; + series.parallelArrays.forEach(fn); + }, + /** + * Define hasData functions for series. These return true if there + * are data points on this series within the plot area. + * + * @private + * @function Highcharts.Series#hasData + * @return {boolean} + */ + hasData: function () { + return ((this.visible && + typeof this.dataMax !== 'undefined' && + typeof this.dataMin !== 'undefined') || ( // #3703 + this.visible && + this.yData && + this.yData.length > 0) // #9758 + ); + }, + /** + * Return an auto incremented x value based on the pointStart and + * pointInterval options. This is only used if an x value is not given + * for the point that calls autoIncrement. + * + * @private + * @function Highcharts.Series#autoIncrement + * @return {number} + */ + autoIncrement: function () { + var options = this.options, xIncrement = this.xIncrement, date, pointInterval, pointIntervalUnit = options.pointIntervalUnit, time = this.chart.time; + xIncrement = pick(xIncrement, options.pointStart, 0); + this.pointInterval = pointInterval = pick(this.pointInterval, options.pointInterval, 1); + // Added code for pointInterval strings + if (pointIntervalUnit) { + date = new time.Date(xIncrement); + if (pointIntervalUnit === 'day') { + time.set('Date', date, time.get('Date', date) + pointInterval); + } + else if (pointIntervalUnit === 'month') { + time.set('Month', date, time.get('Month', date) + pointInterval); + } + else if (pointIntervalUnit === 'year') { + time.set('FullYear', date, time.get('FullYear', date) + pointInterval); + } + pointInterval = date.getTime() - xIncrement; + } + this.xIncrement = xIncrement + pointInterval; + return xIncrement; + }, + /** + * Internal function to set properties for series if data sorting is + * enabled. + * + * @private + * @function Highcharts.Series#setDataSortingOptions + * @return {void} + */ + setDataSortingOptions: function () { + var options = this.options; + extend(this, { + requireSorting: false, + sorted: false, + enabledDataSorting: true, + allowDG: false + }); + // To allow unsorted data for column series. + if (!defined(options.pointRange)) { + options.pointRange = 1; + } + }, + /** + * Set the series options by merging from the options tree. Called + * internally on initializing and updating series. This function will + * not redraw the series. For API usage, use {@link Series#update}. + * @private + * @function Highcharts.Series#setOptions + * @param {Highcharts.SeriesOptionsType} itemOptions + * The series options. + * @return {Highcharts.SeriesOptionsType} + * @fires Highcharts.Series#event:afterSetOptions + */ + setOptions: function (itemOptions) { + var chart = this.chart, chartOptions = chart.options, plotOptions = chartOptions.plotOptions, userOptions = chart.userOptions || {}, seriesUserOptions = merge(itemOptions), options, zones, zone, styledMode = chart.styledMode, e = { + plotOptions: plotOptions, + userOptions: seriesUserOptions + }; + fireEvent(this, 'setOptions', e); + // These may be modified by the event + var typeOptions = e.plotOptions[this.type], userPlotOptions = (userOptions.plotOptions || {}); + // use copy to prevent undetected changes (#9762) + this.userOptions = e.userOptions; + options = merge(typeOptions, plotOptions.series, + // #3881, chart instance plotOptions[type] should trump + // plotOptions.series + userOptions.plotOptions && + userOptions.plotOptions[this.type], seriesUserOptions); + // The tooltip options are merged between global and series specific + // options. Importance order asscendingly: + // globals: (1)tooltip, (2)plotOptions.series, + // (3)plotOptions[this.type] + // init userOptions with possible later updates: 4-6 like 1-3 and + // (7)this series options + this.tooltipOptions = merge(defaultOptions.tooltip, // 1 + defaultOptions.plotOptions.series && + defaultOptions.plotOptions.series.tooltip, // 2 + defaultOptions.plotOptions[this.type].tooltip, // 3 + chartOptions.tooltip.userOptions, // 4 + plotOptions.series && + plotOptions.series.tooltip, // 5 + plotOptions[this.type].tooltip, // 6 + seriesUserOptions.tooltip // 7 + ); + // When shared tooltip, stickyTracking is true by default, + // unless user says otherwise. + this.stickyTracking = pick(seriesUserOptions.stickyTracking, userPlotOptions[this.type] && + userPlotOptions[this.type].stickyTracking, userPlotOptions.series && userPlotOptions.series.stickyTracking, (this.tooltipOptions.shared && !this.noSharedTooltip ? + true : + options.stickyTracking)); + // Delete marker object if not allowed (#1125) + if (typeOptions.marker === null) { + delete options.marker; + } + // Handle color zones + this.zoneAxis = options.zoneAxis; + zones = this.zones = (options.zones || []).slice(); + if ((options.negativeColor || options.negativeFillColor) && + !options.zones) { + zone = { + value: options[this.zoneAxis + 'Threshold'] || + options.threshold || + 0, + className: 'highcharts-negative' + }; + if (!styledMode) { + zone.color = options.negativeColor; + zone.fillColor = options.negativeFillColor; + } + zones.push(zone); + } + if (zones.length) { // Push one extra zone for the rest + if (defined(zones[zones.length - 1].value)) { + zones.push(styledMode ? {} : { + color: this.color, + fillColor: this.fillColor + }); + } + } + fireEvent(this, 'afterSetOptions', { options: options }); + return options; + }, + /** + * Return series name in "Series {Number}" format or the one defined by + * a user. This method can be simply overridden as series name format + * can vary (e.g. technical indicators). + * + * @function Highcharts.Series#getName + * @return {string} + * The series name. + */ + getName: function () { + // #4119 + return pick(this.options.name, 'Series ' + (this.index + 1)); + }, + /** + * @private + * @function Highcharts.Series#getCyclic + * @param {string} prop + * @param {*} [value] + * @param {Highcharts.Dictionary} [defaults] + * @return {void} + */ + getCyclic: function (prop, value, defaults) { + var i, chart = this.chart, userOptions = this.userOptions, indexName = prop + 'Index', counterName = prop + 'Counter', len = defaults ? defaults.length : pick(chart.options.chart[prop + 'Count'], chart[prop + 'Count']), setting; + if (!value) { + // Pick up either the colorIndex option, or the _colorIndex + // after Series.update() + setting = pick(userOptions[indexName], userOptions['_' + indexName]); + if (defined(setting)) { // after Series.update() + i = setting; + } + else { + // #6138 + if (!chart.series.length) { + chart[counterName] = 0; + } + userOptions['_' + indexName] = i = + chart[counterName] % len; + chart[counterName] += 1; + } + if (defaults) { + value = defaults[i]; + } + } + // Set the colorIndex + if (typeof i !== 'undefined') { + this[indexName] = i; + } + this[prop] = value; + }, + /** + * Get the series' color based on either the options or pulled from + * global options. + * + * @private + * @function Highcharts.Series#getColor + * @return {void} + */ + getColor: function () { + if (this.chart.styledMode) { + this.getCyclic('color'); + } + else if (this.options.colorByPoint) { + // #4359, selected slice got series.color even when colorByPoint + // was set. + this.options.color = null; + } + else { + this.getCyclic('color', this.options.color || + defaultPlotOptions[this.type].color, this.chart.options.colors); + } + }, + /** + * Get all points' instances created for this series. + * + * @private + * @function Highcharts.Series#getPointsCollection + * @return {Array} + */ + getPointsCollection: function () { + return (this.hasGroupedData ? this.points : this.data) || []; + }, + /** + * Get the series' symbol based on either the options or pulled from + * global options. + * + * @private + * @function Highcharts.Series#getSymbol + * @return {void} + */ + getSymbol: function () { + var seriesMarkerOption = this.options.marker; + this.getCyclic('symbol', seriesMarkerOption.symbol, this.chart.options.symbols); + }, + /** + * Finds the index of an existing point that matches the given point + * options. + * + * @private + * @function Highcharts.Series#findPointIndex + * @param {Highcharts.PointOptionsObject} optionsObject + * The options of the point. + * @param {number} fromIndex + * The index to start searching from, used for optimizing + * series with required sorting. + * @returns {number|undefined} + * Returns the index of a matching point, or undefined if no + * match is found. + */ + findPointIndex: function (optionsObject, fromIndex) { + var id = optionsObject.id, x = optionsObject.x, oldData = this.points, matchingPoint, matchedById, pointIndex, matchKey, dataSorting = this.options.dataSorting; + if (id) { + matchingPoint = this.chart.get(id); + } + else if (this.linkedParent || this.enabledDataSorting) { + matchKey = (dataSorting && dataSorting.matchByName) ? + 'name' : 'index'; + matchingPoint = find(oldData, function (oldPoint) { + return !oldPoint.touched && oldPoint[matchKey] === + optionsObject[matchKey]; + }); + // Add unmatched point as a new point + if (!matchingPoint) { + return void 0; + } + } + if (matchingPoint) { + pointIndex = matchingPoint && matchingPoint.index; + if (typeof pointIndex !== 'undefined') { + matchedById = true; + } + } + // Search for the same X in the existing data set + if (typeof pointIndex === 'undefined' && isNumber(x)) { + pointIndex = this.xData.indexOf(x, fromIndex); + } + // Reduce pointIndex if data is cropped + if (pointIndex !== -1 && + typeof pointIndex !== 'undefined' && + this.cropped) { + pointIndex = (pointIndex >= this.cropStart) ? + pointIndex - this.cropStart : pointIndex; + } + if (!matchedById && + oldData[pointIndex] && oldData[pointIndex].touched) { + pointIndex = void 0; + } + return pointIndex; + }, + /** + * @private + * @borrows LegendSymbolMixin.drawLineMarker as Highcharts.Series#drawLegendSymbol + */ + drawLegendSymbol: LegendSymbolMixin.drawLineMarker, + /** + * Internal function called from setData. If the point count is the same + * as is was, or if there are overlapping X values, just run + * Point.update which is cheaper, allows animation, and keeps references + * to points. This also allows adding or removing points if the X-es + * don't match. + * + * @private + * @function Highcharts.Series#updateData + * + * @param {Array} data + * + * @return {boolean} + */ + updateData: function (data, animation) { + var options = this.options, dataSorting = options.dataSorting, oldData = this.points, pointsToAdd = [], hasUpdatedByKey, i, point, lastIndex, requireSorting = this.requireSorting, equalLength = data.length === oldData.length, succeeded = true; + this.xIncrement = null; + // Iterate the new data + data.forEach(function (pointOptions, i) { + var id, x, pointIndex, optionsObject = (defined(pointOptions) && + this.pointClass.prototype.optionsToObject.call({ series: this }, pointOptions)) || {}; + // Get the x of the new data point + x = optionsObject.x; + id = optionsObject.id; + if (id || isNumber(x)) { + pointIndex = this.findPointIndex(optionsObject, lastIndex); + // Matching X not found + // or used already due to ununique x values (#8995), + // add point (but later) + if (pointIndex === -1 || + typeof pointIndex === 'undefined') { + pointsToAdd.push(pointOptions); + // Matching X found, update + } + else if (oldData[pointIndex] && + pointOptions !== options.data[pointIndex]) { + oldData[pointIndex].update(pointOptions, false, null, false); + // Mark it touched, below we will remove all points that + // are not touched. + oldData[pointIndex].touched = true; + // Speed optimize by only searching after last known + // index. Performs ~20% bettor on large data sets. + if (requireSorting) { + lastIndex = pointIndex + 1; + } + // Point exists, no changes, don't remove it + } + else if (oldData[pointIndex]) { + oldData[pointIndex].touched = true; + } + // If the length is equal and some of the nodes had a + // match in the same position, we don't want to remove + // non-matches. + if (!equalLength || + i !== pointIndex || + (dataSorting && dataSorting.enabled) || + this.hasDerivedData) { + hasUpdatedByKey = true; + } + } + else { + // Gather all points that are not matched + pointsToAdd.push(pointOptions); + } + }, this); + // Remove points that don't exist in the updated data set + if (hasUpdatedByKey) { + i = oldData.length; + while (i--) { + point = oldData[i]; + if (point && !point.touched && point.remove) { + point.remove(false, animation); + } + } + // If we did not find keys (ids or x-values), and the length is the + // same, update one-to-one + } + else if (equalLength && (!dataSorting || !dataSorting.enabled)) { + data.forEach(function (point, i) { + // .update doesn't exist on a linked, hidden series (#3709) + // (#10187) + if (oldData[i].update && point !== oldData[i].y) { + oldData[i].update(point, false, null, false); + } + }); + // Don't add new points since those configs are used above + pointsToAdd.length = 0; + // Did not succeed in updating data + } + else { + succeeded = false; + } + oldData.forEach(function (point) { + if (point) { + point.touched = false; + } + }); + if (!succeeded) { + return false; + } + // Add new points + pointsToAdd.forEach(function (point) { + this.addPoint(point, false, null, null, false); + }, this); + if (this.xIncrement === null && + this.xData && + this.xData.length) { + this.xIncrement = arrayMax(this.xData); + this.autoIncrement(); + } + return true; + }, + /** + * Apply a new set of data to the series and optionally redraw it. The + * new data array is passed by reference (except in case of + * `updatePoints`), and may later be mutated when updating the chart + * data. + * + * Note the difference in behaviour when setting the same amount of + * points, or a different amount of points, as handled by the + * `updatePoints` parameter. + * + * @sample highcharts/members/series-setdata/ + * Set new data from a button + * @sample highcharts/members/series-setdata-pie/ + * Set data in a pie + * @sample stock/members/series-setdata/ + * Set new data in Highstock + * @sample maps/members/series-setdata/ + * Set new data in Highmaps + * + * @function Highcharts.Series#setData + * + * @param {Array} data + * Takes an array of data in the same format as described under + * `series.{type}.data` for the given series type, for example a + * line series would take data in the form described under + * [series.line.data](https://api.highcharts.com/highcharts/series.line.data). + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the series is altered. If + * doing more operations on the chart, it is a good idea to set + * redraw to false and call {@link Chart#redraw} after. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * When the updated data is the same length as the existing data, + * points will be updated by default, and animation visualizes + * how the points are changed. Set false to disable animation, or + * a configuration object to set duration or easing. + * + * @param {boolean} [updatePoints=true] + * When this is true, points will be updated instead of replaced + * whenever possible. This occurs a) when the updated data is the + * same length as the existing data, b) when points are matched + * by their id's, or c) when points can be matched by X values. + * This allows updating with animation and performs better. In + * this case, the original array is not passed by reference. Set + * `false` to prevent. + * + * @return {void} + */ + setData: function (data, redraw, animation, updatePoints) { + var series = this, oldData = series.points, oldDataLength = (oldData && oldData.length) || 0, dataLength, options = series.options, chart = series.chart, dataSorting = options.dataSorting, firstPoint = null, xAxis = series.xAxis, i, turboThreshold = options.turboThreshold, pt, xData = this.xData, yData = this.yData, pointArrayMap = series.pointArrayMap, valueCount = pointArrayMap && pointArrayMap.length, keys = options.keys, indexOfX = 0, indexOfY = 1, updatedData; + data = data || []; + dataLength = data.length; + redraw = pick(redraw, true); + if (dataSorting && dataSorting.enabled) { + data = this.sortData(data); + } + // First try to run Point.update which is cheaper, allows animation, + // and keeps references to points. + if (updatePoints !== false && + dataLength && + oldDataLength && + !series.cropped && + !series.hasGroupedData && + series.visible && + // Soft updating has no benefit in boost, and causes JS error + // (#8355) + !series.isSeriesBoosting) { + updatedData = this.updateData(data, animation); + } + if (!updatedData) { + // Reset properties + series.xIncrement = null; + series.colorCounter = 0; // for series with colorByPoint (#1547) + // Update parallel arrays + this.parallelArrays.forEach(function (key) { + series[key + 'Data'].length = 0; + }); + // In turbo mode, only one- or twodimensional arrays of numbers + // are allowed. The first value is tested, and we assume that + // all the rest are defined the same way. Although the 'for' + // loops are similar, they are repeated inside each if-else + // conditional for max performance. + if (turboThreshold && dataLength > turboThreshold) { + firstPoint = series.getFirstValidPoint(data); + if (isNumber(firstPoint)) { // assume all points are numbers + for (i = 0; i < dataLength; i++) { + xData[i] = this.autoIncrement(); + yData[i] = data[i]; + } + // Assume all points are arrays when first point is + } + else if (isArray(firstPoint)) { + if (valueCount) { // [x, low, high] or [x, o, h, l, c] + for (i = 0; i < dataLength; i++) { + pt = data[i]; + xData[i] = pt[0]; + yData[i] = + pt.slice(1, valueCount + 1); + } + } + else { // [x, y] + if (keys) { + indexOfX = keys.indexOf('x'); + indexOfY = keys.indexOf('y'); + indexOfX = indexOfX >= 0 ? indexOfX : 0; + indexOfY = indexOfY >= 0 ? indexOfY : 1; + } + for (i = 0; i < dataLength; i++) { + pt = data[i]; + xData[i] = pt[indexOfX]; + yData[i] = pt[indexOfY]; + } + } + } + else { + // Highcharts expects configs to be numbers or arrays in + // turbo mode + error(12, false, chart); + } + } + else { + for (i = 0; i < dataLength; i++) { + // stray commas in oldIE: + if (typeof data[i] !== 'undefined') { + pt = { series: series }; + series.pointClass.prototype.applyOptions.apply(pt, [data[i]]); + series.updateParallelArrays(pt, i); + } + } + } + // Forgetting to cast strings to numbers is a common caveat when + // handling CSV or JSON + if (yData && isString(yData[0])) { + error(14, true, chart); + } + series.data = []; + series.options.data = series.userOptions.data = data; + // destroy old points + i = oldDataLength; + while (i--) { + if (oldData[i] && oldData[i].destroy) { + oldData[i].destroy(); + } + } + // reset minRange (#878) + if (xAxis) { + xAxis.minRange = xAxis.userMinRange; + } + // redraw + series.isDirty = chart.isDirtyBox = true; + series.isDirtyData = !!oldData; + animation = false; + } + // Typically for pie series, points need to be processed and + // generated prior to rendering the legend + if (options.legendType === 'point') { + this.processData(); + this.generatePoints(); + } + if (redraw) { + chart.redraw(animation); + } + }, + /** + * Internal function to sort series data + * + * @private + * @function Highcharts.Series#sortData + * @param {Array} data + * Force data grouping. + * @return {Array} + */ + sortData: function (data) { + var series = this, options = series.options, dataSorting = options.dataSorting, sortKey = dataSorting.sortKey || 'y', sortedData, getPointOptionsObject = function (series, pointOptions) { + return (defined(pointOptions) && + series.pointClass.prototype.optionsToObject.call({ + series: series + }, pointOptions)) || {}; + }; + data.forEach(function (pointOptions, i) { + data[i] = getPointOptionsObject(series, pointOptions); + data[i].index = i; + }, this); + // Sorting + sortedData = data.concat().sort(function (a, b) { + var aValue = getNestedProperty(sortKey, a); + var bValue = getNestedProperty(sortKey, b); + return bValue < aValue ? -1 : bValue > aValue ? 1 : 0; + }); + // Set x value depending on the position in the array + sortedData.forEach(function (point, i) { + point.x = i; + }, this); + // Set the same x for linked series points if they don't have their + // own sorting + if (series.linkedSeries) { + series.linkedSeries.forEach(function (linkedSeries) { + var options = linkedSeries.options, seriesData = options.data; + if ((!options.dataSorting || + !options.dataSorting.enabled) && + seriesData) { + seriesData.forEach(function (pointOptions, i) { + seriesData[i] = getPointOptionsObject(linkedSeries, pointOptions); + if (data[i]) { + seriesData[i].x = data[i].x; + seriesData[i].index = i; + } + }); + linkedSeries.setData(seriesData, false); + } + }); + } + return data; + }, + /** + * Internal function to process the data by cropping away unused data + * points if the series is longer than the crop threshold. This saves + * computing time for large series. + * + * @private + * @function Highcharts.Series#getProcessedData + * @param {boolean} [forceExtremesFromAll] + * Force getting extremes of a total series data range. + * @return {Highcharts.SeriesProcessedDataObject} + */ + getProcessedData: function (forceExtremesFromAll) { + var series = this, + // copied during slice operation: + processedXData = series.xData, processedYData = series.yData, dataLength = processedXData.length, croppedData, cropStart = 0, cropped, distance, closestPointRange, xAxis = series.xAxis, i, // loop variable + options = series.options, cropThreshold = options.cropThreshold, getExtremesFromAll = forceExtremesFromAll || + series.getExtremesFromAll || + options.getExtremesFromAll, // #4599 + isCartesian = series.isCartesian, xExtremes, val2lin = xAxis && xAxis.val2lin, isLog = !!(xAxis && xAxis.logarithmic), throwOnUnsorted = series.requireSorting, min, max; + if (xAxis) { + // corrected for log axis (#3053) + xExtremes = xAxis.getExtremes(); + min = xExtremes.min; + max = xExtremes.max; + } + // optionally filter out points outside the plot area + if (isCartesian && + series.sorted && + !getExtremesFromAll && + (!cropThreshold || + dataLength > cropThreshold || + series.forceCrop)) { + // it's outside current extremes + if (processedXData[dataLength - 1] < min || + processedXData[0] > max) { + processedXData = []; + processedYData = []; + // only crop if it's actually spilling out + } + else if (series.yData && (processedXData[0] < min || + processedXData[dataLength - 1] > max)) { + croppedData = this.cropData(series.xData, series.yData, min, max); + processedXData = croppedData.xData; + processedYData = croppedData.yData; + cropStart = croppedData.start; + cropped = true; + } + } + // Find the closest distance between processed points + i = processedXData.length || 1; + while (--i) { + distance = (isLog ? + (val2lin(processedXData[i]) - + val2lin(processedXData[i - 1])) : + (processedXData[i] - + processedXData[i - 1])); + if (distance > 0 && + (typeof closestPointRange === 'undefined' || + distance < closestPointRange)) { + closestPointRange = distance; + // Unsorted data is not supported by the line tooltip, as well + // as data grouping and navigation in Stock charts (#725) and + // width calculation of columns (#1900) + } + else if (distance < 0 && throwOnUnsorted) { + error(15, false, series.chart); + throwOnUnsorted = false; // Only once + } + } + return { + xData: processedXData, + yData: processedYData, + cropped: cropped, + cropStart: cropStart, + closestPointRange: closestPointRange + }; + }, + /** + * Internal function to apply processed data. + * In Highstock, this function is extended to provide data grouping. + * + * @private + * @function Highcharts.Series#processData + * @param {boolean} [force] + * Force data grouping. + * @return {boolean|undefined} + */ + processData: function (force) { + var series = this, xAxis = series.xAxis, processedData; + // If the series data or axes haven't changed, don't go through + // this. Return false to pass the message on to override methods + // like in data grouping. + if (series.isCartesian && + !series.isDirty && + !xAxis.isDirty && + !series.yAxis.isDirty && + !force) { + return false; + } + processedData = series.getProcessedData(); + // Record the properties + series.cropped = processedData.cropped; // undefined or true + series.cropStart = processedData.cropStart; + series.processedXData = processedData.xData; + series.processedYData = processedData.yData; + series.closestPointRange = + series.basePointRange = processedData.closestPointRange; + }, + /** + * Iterate over xData and crop values between min and max. Returns + * object containing crop start/end cropped xData with corresponding + * part of yData, dataMin and dataMax within the cropped range. + * + * @private + * @function Highcharts.Series#cropData + * @param {Array} xData + * @param {Array} yData + * @param {number} min + * @param {number} max + * @param {number} [cropShoulder] + * @return {Highcharts.SeriesCropDataObject} + */ + cropData: function (xData, yData, min, max, cropShoulder) { + var dataLength = xData.length, cropStart = 0, cropEnd = dataLength, i, j; + // line-type series need one point outside + cropShoulder = pick(cropShoulder, this.cropShoulder); + // iterate up to find slice start + for (i = 0; i < dataLength; i++) { + if (xData[i] >= min) { + cropStart = Math.max(0, i - cropShoulder); + break; + } + } + // proceed to find slice end + for (j = i; j < dataLength; j++) { + if (xData[j] > max) { + cropEnd = j + cropShoulder; + break; + } + } + return { + xData: xData.slice(cropStart, cropEnd), + yData: yData.slice(cropStart, cropEnd), + start: cropStart, + end: cropEnd + }; + }, + /** + * Generate the data point after the data has been processed by cropping + * away unused points and optionally grouped in Highcharts Stock. + * + * @private + * @function Highcharts.Series#generatePoints + * @return {void} + */ + generatePoints: function () { + var series = this, options = series.options, dataOptions = options.data, data = series.data, dataLength, processedXData = series.processedXData, processedYData = series.processedYData, PointClass = series.pointClass, processedDataLength = processedXData.length, cropStart = series.cropStart || 0, cursor, hasGroupedData = series.hasGroupedData, keys = options.keys, point, points = [], i; + if (!data && !hasGroupedData) { + var arr = []; + arr.length = dataOptions.length; + data = series.data = arr; + } + if (keys && hasGroupedData) { + // grouped data has already applied keys (#6590) + series.options.keys = false; + } + for (i = 0; i < processedDataLength; i++) { + cursor = cropStart + i; + if (!hasGroupedData) { + point = data[cursor]; + // #970: + if (!point && + typeof dataOptions[cursor] !== 'undefined') { + data[cursor] = point = (new PointClass()).init(series, dataOptions[cursor], processedXData[i]); + } + } + else { + // splat the y data in case of ohlc data array + point = (new PointClass()).init(series, [processedXData[i]].concat(splat(processedYData[i]))); + /** + * Highstock only. If a point object is created by data + * grouping, it doesn't reflect actual points in the raw + * data. In this case, the `dataGroup` property holds + * information that points back to the raw data. + * + * - `dataGroup.start` is the index of the first raw data + * point in the group. + * + * - `dataGroup.length` is the amount of points in the + * group. + * + * @product highstock + * + * @name Highcharts.Point#dataGroup + * @type {Highcharts.DataGroupingInfoObject|undefined} + */ + point.dataGroup = series.groupMap[i]; + if (point.dataGroup.options) { + point.options = point.dataGroup.options; + extend(point, point.dataGroup.options); + // Collision of props and options (#9770) + delete point.dataLabels; + } + } + if (point) { // #6279 + /** + * Contains the point's index in the `Series.points` array. + * + * @name Highcharts.Point#index + * @type {number} + * @readonly + */ + point.index = cursor; // For faster access in Point.update + points[i] = point; + } + } + // restore keys options (#6590) + series.options.keys = keys; + // Hide cropped-away points - this only runs when the number of + // points is above cropThreshold, or when swithching view from + // non-grouped data to grouped data (#637) + if (data && + (processedDataLength !== (dataLength = data.length) || + hasGroupedData)) { + for (i = 0; i < dataLength; i++) { + // when has grouped data, clear all points + if (i === cropStart && !hasGroupedData) { + i += processedDataLength; + } + if (data[i]) { + data[i].destroyElements(); + data[i].plotX = void 0; // #1003 + } + } + } + /** + * Read only. An array containing those values converted to points. + * In case the series data length exceeds the `cropThreshold`, or if + * the data is grouped, `series.data` doesn't contain all the + * points. Also, in case a series is hidden, the `data` array may be + * empty. To access raw values, `series.options.data` will always be + * up to date. `Series.data` only contains the points that have been + * created on demand. To modify the data, use + * {@link Highcharts.Series#setData} or + * {@link Highcharts.Point#update}. + * + * @see Series.points + * + * @name Highcharts.Series#data + * @type {Array} + */ + series.data = data; + /** + * An array containing all currently visible point objects. In case + * of cropping, the cropped-away points are not part of this array. + * The `series.points` array starts at `series.cropStart` compared + * to `series.data` and `series.options.data`. If however the series + * data is grouped, these can't be correlated one to one. To modify + * the data, use {@link Highcharts.Series#setData} or + * {@link Highcharts.Point#update}. + * + * @name Highcharts.Series#points + * @type {Array} + */ + series.points = points; + fireEvent(this, 'afterGeneratePoints'); + }, + /** + * Get current X extremes for the visible data. + * + * @private + * @function Highcharts.Series#getXExtremes + * + * @param {Array} xData + * The data to inspect. Defaults to the current data within the + * visible range. + * @return {Highcharts.RangeObject} + */ + getXExtremes: function (xData) { + return { + min: arrayMin(xData), + max: arrayMax(xData) + }; + }, + /** + * Calculate Y extremes for the visible data. The result is returned + * as an object with `dataMin` and `dataMax` properties. + * + * @private + * @function Highcharts.Series#getExtremes + * @param {Array} [yData] + * The data to inspect. Defaults to the current data within the + * visible range. + * @param {boolean} [forceExtremesFromAll] + * Force getting extremes of a total series data range. + * @return {Highcharts.DataExtremesObject} + */ + getExtremes: function (yData, forceExtremesFromAll) { + var xAxis = this.xAxis, yAxis = this.yAxis, xData = this.processedXData || this.xData, yDataLength, activeYData = [], activeCounter = 0, + // #2117, need to compensate for log X axis + xExtremes, xMin = 0, xMax = 0, validValue, withinRange, + // Handle X outside the viewed area. This does not work with + // non-sorted data like scatter (#7639). + shoulder = this.requireSorting ? this.cropShoulder : 0, positiveValuesOnly = yAxis ? yAxis.positiveValuesOnly : false, x, y, i, j; + yData = yData || this.stackedYData || this.processedYData || []; + yDataLength = yData.length; + if (xAxis) { + xExtremes = xAxis.getExtremes(); + xMin = xExtremes.min; + xMax = xExtremes.max; + } + for (i = 0; i < yDataLength; i++) { + x = xData[i]; + y = yData[i]; + // For points within the visible range, including the first + // point outside the visible range (#7061), consider y extremes. + validValue = ((isNumber(y) || isArray(y)) && + ((y.length || y > 0) || !positiveValuesOnly)); + withinRange = (forceExtremesFromAll || + this.getExtremesFromAll || + this.options.getExtremesFromAll || + this.cropped || + !xAxis || // for colorAxis support + ((xData[i + shoulder] || x) >= xMin && + (xData[i - shoulder] || x) <= xMax)); + if (validValue && withinRange) { + j = y.length; + if (j) { // array, like ohlc or range data + while (j--) { + if (isNumber(y[j])) { // #7380, #11513 + activeYData[activeCounter++] = y[j]; + } + } + } + else { + activeYData[activeCounter++] = y; + } + } + } + var dataExtremes = { + dataMin: arrayMin(activeYData), + dataMax: arrayMax(activeYData) + }; + fireEvent(this, 'afterGetExtremes', { dataExtremes: dataExtremes }); + return dataExtremes; + }, + /** + * Set the current data extremes as `dataMin` and `dataMax` on the + * Series item. Use this only when the series properties should be + * updated. + * + * @private + * @function Highcharts.Series#applyExtremes + * @return {void} + */ + applyExtremes: function () { + var dataExtremes = this.getExtremes(); + /** + * Contains the minimum value of the series' data point. + * @name Highcharts.Series#dataMin + * @type {number} + * @readonly + */ + this.dataMin = dataExtremes.dataMin; + /* * + * Contains the maximum value of the series' data point. + * @name Highcharts.Series#dataMax + * @type {number} + * @readonly + */ + this.dataMax = dataExtremes.dataMax; + return dataExtremes; + }, + /** + * Find and return the first non null point in the data + * + * @private + * @function Highcharts.Series.getFirstValidPoint + * @param {Array} data + * Array of options for points + * + * @return {Highcharts.PointOptionsType} + */ + getFirstValidPoint: function (data) { + var firstPoint = null, dataLength = data.length, i = 0; + while (firstPoint === null && i < dataLength) { + firstPoint = data[i]; + i++; + } + return firstPoint; + }, + /** + * Translate data points from raw data values to chart specific + * positioning data needed later in the `drawPoints` and `drawGraph` + * functions. This function can be overridden in plugins and custom + * series type implementations. + * + * @function Highcharts.Series#translate + * @return {void} + * @fires Highcharts.Series#events:translate + */ + translate: function () { + if (!this.processedXData) { // hidden series + this.processData(); + } + this.generatePoints(); + var series = this, options = series.options, stacking = options.stacking, xAxis = series.xAxis, categories = xAxis.categories, enabledDataSorting = series.enabledDataSorting, yAxis = series.yAxis, points = series.points, dataLength = points.length, hasModifyValue = !!series.modifyValue, i, pointPlacement = series.pointPlacementToXValue(), // #7860 + dynamicallyPlaced = Boolean(pointPlacement), threshold = options.threshold, stackThreshold = options.startFromThreshold ? threshold : 0, plotX, lastPlotX, stackIndicator, zoneAxis = this.zoneAxis || 'y', closestPointRangePx = Number.MAX_VALUE; + /** + * Plotted coordinates need to be within a limited range. Drawing + * too far outside the viewport causes various rendering issues + * (#3201, #3923, #7555). + * @private + */ + function limitedRange(val) { + return clamp(val, -1e5, 1e5); + } + // Translate each point + for (i = 0; i < dataLength; i++) { + var point = points[i], xValue = point.x, yValue = point.y, yBottom = point.low, stack = stacking && yAxis.stacking && yAxis.stacking.stacks[(series.negStacks && + yValue < + (stackThreshold ? 0 : threshold) ? + '-' : + '') + series.stackKey], pointStack, stackValues; + // Discard disallowed y values for log axes (#3434) + if (yAxis.positiveValuesOnly && + yValue !== null && + yValue <= 0) { + point.isNull = true; + } + // Get the plotX translation + point.plotX = plotX = correctFloat(// #5236 + limitedRange(xAxis.translate(// #3923 + xValue, 0, 0, 0, 1, pointPlacement, this.type === 'flags')) // #3923 + ); + // Calculate the bottom y value for stacked series + if (stacking && + series.visible && + stack && + stack[xValue]) { + stackIndicator = series.getStackIndicator(stackIndicator, xValue, series.index); + if (!point.isNull) { + pointStack = stack[xValue]; + stackValues = + pointStack.points[stackIndicator.key]; + } + } + if (isArray(stackValues)) { + yBottom = stackValues[0]; + yValue = stackValues[1]; + if (yBottom === stackThreshold && + stackIndicator.key === + stack[xValue].base) { + yBottom = pick((isNumber(threshold) && threshold), yAxis.min); + } + // #1200, #1232 + if (yAxis.positiveValuesOnly && yBottom <= 0) { + yBottom = null; + } + point.total = point.stackTotal = pointStack.total; + point.percentage = + pointStack.total && + (point.y / pointStack.total * 100); + point.stackY = yValue; + // Place the stack label + // in case of variwide series (where widths of points are + // different in most cases), stack labels are positioned + // wrongly, so the call of the setOffset is omited here and + // labels are correctly positioned later, at the end of the + // variwide's translate function (#10962) + if (!series.irregularWidths) { + pointStack.setOffset(series.pointXOffset || 0, series.barW || 0); + } + } + // Set translated yBottom or remove it + point.yBottom = defined(yBottom) ? + limitedRange(yAxis.translate(yBottom, 0, 1, 0, 1)) : + null; + // general hook, used for Highstock compare mode + if (hasModifyValue) { + yValue = series.modifyValue(yValue, point); + } + // Set the the plotY value, reset it for redraws + // #3201 + point.plotY = ((typeof yValue === 'number' && yValue !== Infinity) ? + limitedRange(yAxis.translate(yValue, 0, 1, 0, 1)) : + void 0); + point.isInside = this.isPointInside(point); + // Set client related positions for mouse tracking + point.clientX = dynamicallyPlaced ? + correctFloat(xAxis.translate(xValue, 0, 0, 0, 1, pointPlacement)) : + plotX; // #1514, #5383, #5518 + // Negative points. For bubble charts, this means negative z + // values (#9728) + point.negative = point[zoneAxis] < (options[zoneAxis + 'Threshold'] || + threshold || + 0); + // some API data + point.category = (categories && + typeof categories[point.x] !== 'undefined' ? + categories[point.x] : + point.x); + // Determine auto enabling of markers (#3635, #5099) + if (!point.isNull && point.visible !== false) { + if (typeof lastPlotX !== 'undefined') { + closestPointRangePx = Math.min(closestPointRangePx, Math.abs(plotX - lastPlotX)); + } + lastPlotX = plotX; + } + // Find point zone + point.zone = (this.zones.length && point.getZone()); + // Animate new points with data sorting + if (!point.graphic && series.group && enabledDataSorting) { + point.isNew = true; + } + } + series.closestPointRangePx = closestPointRangePx; + fireEvent(this, 'afterTranslate'); + }, + /** + * Return the series points with null points filtered out. + * + * @function Highcharts.Series#getValidPoints + * + * @param {Array} [points] + * The points to inspect, defaults to {@link Series.points}. + * + * @param {boolean} [insideOnly=false] + * Whether to inspect only the points that are inside the visible + * view. + * + * @param {boolean} [allowNull=false] + * Whether to allow null points to pass as valid points. + * + * @return {Array} + * The valid points. + */ + getValidPoints: function (points, insideOnly, allowNull) { + var chart = this.chart; + // #3916, #5029, #5085 + return (points || this.points || []).filter(function isValidPoint(point) { + if (insideOnly && !chart.isInsidePlot(point.plotX, point.plotY, chart.inverted)) { + return false; + } + return point.visible !== false && + (allowNull || !point.isNull); + }); + }, + /** + * Get the clipping for the series. Could be called for a series to + * initiate animating the clip or to set the final clip (only width + * and x). + * + * @private + * @function Highcharts.Series#getClip + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * Initialize the animation. + * @param {boolean} [finalBox] + * Final size for the clip - end state for the animation. + * @return {Highcharts.Dictionary} + */ + getClipBox: function (animation, finalBox) { + var series = this, options = series.options, chart = series.chart, inverted = chart.inverted, xAxis = series.xAxis, yAxis = xAxis && series.yAxis, clipBox; + if (animation && options.clip === false && yAxis) { + // support for not clipped series animation (#10450) + clipBox = inverted ? { + y: -chart.chartWidth + yAxis.len + yAxis.pos, + height: chart.chartWidth, + width: chart.chartHeight, + x: -chart.chartHeight + xAxis.len + xAxis.pos + } : { + y: -yAxis.pos, + height: chart.chartHeight, + width: chart.chartWidth, + x: -xAxis.pos + }; + // x and width will be changed later when setting for animation + // initial state in Series.setClip + } + else { + clipBox = series.clipBox || chart.clipBox; + if (finalBox) { + clipBox.width = chart.plotSizeX; + clipBox.x = 0; + } + } + return !finalBox ? clipBox : { + width: clipBox.width, + x: clipBox.x + }; + }, + /** + * Set the clipping for the series. For animated series it is called + * twice, first to initiate animating the clip then the second time + * without the animation to set the final clip. + * + * @private + * @function Highcharts.Series#setClip + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * @return {void} + */ + setClip: function (animation) { + var chart = this.chart, options = this.options, renderer = chart.renderer, inverted = chart.inverted, seriesClipBox = this.clipBox, clipBox = this.getClipBox(animation), sharedClipKey = this.sharedClipKey || + [ + '_sharedClip', + animation && animation.duration, + animation && animation.easing, + clipBox.height, + options.xAxis, + options.yAxis + ].join(','), // #4526 + clipRect = chart[sharedClipKey], markerClipRect = chart[sharedClipKey + 'm']; + if (animation) { + clipBox.width = 0; + if (inverted) { + clipBox.x = chart.plotHeight + + (options.clip !== false ? 0 : chart.plotTop); + } + } + // If a clipping rectangle with the same properties is currently + // present in the chart, use that. + if (!clipRect) { + // When animation is set, prepare the initial positions + if (animation) { + chart[sharedClipKey + 'm'] = markerClipRect = + renderer.clipRect( + // include the width of the first marker + inverted ? chart.plotSizeX + 99 : -99, inverted ? -chart.plotLeft : -chart.plotTop, 99, inverted ? chart.chartWidth : chart.chartHeight); + } + chart[sharedClipKey] = clipRect = renderer.clipRect(clipBox); + // Create hashmap for series indexes + clipRect.count = { length: 0 }; + // When the series is rendered again before starting animating, in + // compliance to a responsive rule + } + else if (!chart.hasLoaded) { + clipRect.attr(clipBox); + } + if (animation) { + if (!clipRect.count[this.index]) { + clipRect.count[this.index] = true; + clipRect.count.length += 1; + } + } + if (options.clip !== false || animation) { + this.group.clip(animation || seriesClipBox ? clipRect : chart.clipRect); + this.markerGroup.clip(markerClipRect); + this.sharedClipKey = sharedClipKey; + } + // Remove the shared clipping rectangle when all series are shown + if (!animation) { + if (clipRect.count[this.index]) { + delete clipRect.count[this.index]; + clipRect.count.length -= 1; + } + if (clipRect.count.length === 0 && + sharedClipKey && + chart[sharedClipKey]) { + if (!seriesClipBox) { + chart[sharedClipKey] = + chart[sharedClipKey].destroy(); + } + if (chart[sharedClipKey + 'm']) { + chart[sharedClipKey + 'm'] = + chart[sharedClipKey + 'm'].destroy(); + } + } + } + }, + /** + * Animate in the series. Called internally twice. First with the `init` + * parameter set to true, which sets up the initial state of the + * animation. Then when ready, it is called with the `init` parameter + * undefined, in order to perform the actual animation. After the + * second run, the function is removed. + * + * @function Highcharts.Series#animate + * + * @param {boolean} [init] + * Initialize the animation. + * + * @return {void} + */ + animate: function (init) { + var series = this, chart = series.chart, animation = animObject(series.options.animation), clipRect, sharedClipKey, finalBox; + // Initialize the animation. Set up the clipping rectangle. + if (!chart.hasRendered) { + if (init) { + series.setClip(animation); + // Run the animation + } + else { + sharedClipKey = this.sharedClipKey; + clipRect = chart[sharedClipKey]; + finalBox = series.getClipBox(animation, true); + if (clipRect) { + clipRect.animate(finalBox, animation); + } + if (chart[sharedClipKey + 'm']) { + chart[sharedClipKey + 'm'].animate({ + width: finalBox.width + 99, + x: finalBox.x - (chart.inverted ? 0 : 99) + }, animation); + } + } + } + }, + /** + * This runs after animation to land on the final plot clipping. + * + * @private + * @function Highcharts.Series#afterAnimate + * @return {void} + * @fires Highcharts.Series#event:afterAnimate + */ + afterAnimate: function () { + this.setClip(); + fireEvent(this, 'afterAnimate'); + this.finishedAnimating = true; + }, + /** + * Draw the markers for line-like series types, and columns or other + * graphical representation for {@link Point} objects for other series + * types. The resulting element is typically stored as + * {@link Point.graphic}, and is created on the first call and updated + * and moved on subsequent calls. + * + * @function Highcharts.Series#drawPoints + */ + drawPoints: function () { + var series = this, points = series.points, chart = series.chart, i, point, graphic, verb, options = series.options, seriesMarkerOptions = options.marker, pointMarkerOptions, hasPointMarker, markerGroup = (series[series.specialGroup] || + series.markerGroup), xAxis = series.xAxis, markerAttribs, globallyEnabled = pick(seriesMarkerOptions.enabled, !xAxis || xAxis.isRadial ? true : null, + // Use larger or equal as radius is null in bubbles (#6321) + series.closestPointRangePx >= (seriesMarkerOptions.enabledThreshold * + seriesMarkerOptions.radius)); + if (seriesMarkerOptions.enabled !== false || + series._hasPointMarkers) { + for (i = 0; i < points.length; i++) { + point = points[i]; + graphic = point.graphic; + verb = graphic ? 'animate' : 'attr'; + pointMarkerOptions = point.marker || {}; + hasPointMarker = !!point.marker; + var shouldDrawMarker = ((globallyEnabled && + typeof pointMarkerOptions.enabled === 'undefined') || pointMarkerOptions.enabled) && !point.isNull && point.visible !== false; + // only draw the point if y is defined + if (shouldDrawMarker) { + // Shortcuts + var symbol = pick(pointMarkerOptions.symbol, series.symbol); + markerAttribs = series.markerAttribs(point, (point.selected && 'select')); + // Set starting position for point sliding animation. + if (series.enabledDataSorting) { + point.startXPos = xAxis.reversed ? + -markerAttribs.width : + xAxis.width; + } + var isInside = point.isInside !== false; + if (graphic) { // update + // Since the marker group isn't clipped, each + // individual marker must be toggled + graphic[isInside ? 'show' : 'hide'](isInside) + .animate(markerAttribs); + } + else if (isInside && + (markerAttribs.width > 0 || point.hasImage)) { + /** + * The graphic representation of the point. + * Typically this is a simple shape, like a `rect` + * for column charts or `path` for line markers, but + * for some complex series types like boxplot or 3D + * charts, the graphic may be a `g` element + * containing other shapes. The graphic is generated + * the first time {@link Series#drawPoints} runs, + * and updated and moved on subsequent runs. + * + * @name Point#graphic + * @type {SVGElement} + */ + point.graphic = graphic = chart.renderer + .symbol(symbol, markerAttribs.x, markerAttribs.y, markerAttribs.width, markerAttribs.height, hasPointMarker ? + pointMarkerOptions : + seriesMarkerOptions) + .add(markerGroup); + // Sliding animation for new points + if (series.enabledDataSorting && + chart.hasRendered) { + graphic.attr({ + x: point.startXPos + }); + verb = 'animate'; + } + } + if (graphic && verb === 'animate') { // update + // Since the marker group isn't clipped, each + // individual marker must be toggled + graphic[isInside ? 'show' : 'hide'](isInside) + .animate(markerAttribs); + } + // Presentational attributes + if (graphic && !chart.styledMode) { + graphic[verb](series.pointAttribs(point, (point.selected && 'select'))); + } + if (graphic) { + graphic.addClass(point.getClassName(), true); + } + } + else if (graphic) { + point.graphic = graphic.destroy(); // #1269 + } + } + } + }, + /** + * Get non-presentational attributes for a point. Used internally for + * both styled mode and classic. Can be overridden for different series + * types. + * + * @see Series#pointAttribs + * + * @function Highcharts.Series#markerAttribs + * + * @param {Highcharts.Point} point + * The Point to inspect. + * + * @param {string} [state] + * The state, can be either `hover`, `select` or undefined. + * + * @return {Highcharts.SVGAttributes} + * A hash containing those attributes that are not settable from + * CSS. + */ + markerAttribs: function (point, state) { + var seriesOptions = this.options, seriesMarkerOptions = seriesOptions.marker, seriesStateOptions, pointMarkerOptions = point.marker || {}, symbol = (pointMarkerOptions.symbol || + seriesMarkerOptions.symbol), pointStateOptions, radius = pick(pointMarkerOptions.radius, seriesMarkerOptions.radius), attribs; + // Handle hover and select states + if (state) { + seriesStateOptions = seriesMarkerOptions.states[state]; + pointStateOptions = pointMarkerOptions.states && + pointMarkerOptions.states[state]; + radius = pick(pointStateOptions && pointStateOptions.radius, seriesStateOptions && seriesStateOptions.radius, radius + (seriesStateOptions && seriesStateOptions.radiusPlus || + 0)); + } + point.hasImage = symbol && symbol.indexOf('url') === 0; + if (point.hasImage) { + radius = 0; // and subsequently width and height is not set + } + attribs = { + // Math.floor for #1843: + x: seriesOptions.crisp ? + Math.floor(point.plotX) - radius : + point.plotX - radius, + y: point.plotY - radius + }; + if (radius) { + attribs.width = attribs.height = 2 * radius; + } + return attribs; + }, + /** + * Internal function to get presentational attributes for each point. + * Unlike {@link Series#markerAttribs}, this function should return + * those attributes that can also be set in CSS. In styled mode, + * `pointAttribs` won't be called. + * + * @private + * @function Highcharts.Series#pointAttribs + * + * @param {Highcharts.Point} [point] + * The point instance to inspect. + * + * @param {string} [state] + * The point state, can be either `hover`, `select` or 'normal'. + * If undefined, normal state is assumed. + * + * @return {Highcharts.SVGAttributes} + * The presentational attributes to be set on the point. + */ + pointAttribs: function (point, state) { + var seriesMarkerOptions = this.options.marker, seriesStateOptions, pointOptions = point && point.options, pointMarkerOptions = ((pointOptions && pointOptions.marker) || {}), pointStateOptions, color = this.color, pointColorOption = pointOptions && pointOptions.color, pointColor = point && point.color, strokeWidth = pick(pointMarkerOptions.lineWidth, seriesMarkerOptions.lineWidth), zoneColor = point && point.zone && point.zone.color, fill, stroke, opacity = 1; + color = (pointColorOption || + zoneColor || + pointColor || + color); + fill = (pointMarkerOptions.fillColor || + seriesMarkerOptions.fillColor || + color); + stroke = (pointMarkerOptions.lineColor || + seriesMarkerOptions.lineColor || + color); + // Handle hover and select states + state = state || 'normal'; + if (state) { + seriesStateOptions = seriesMarkerOptions.states[state]; + pointStateOptions = (pointMarkerOptions.states && + pointMarkerOptions.states[state]) || {}; + strokeWidth = pick(pointStateOptions.lineWidth, seriesStateOptions.lineWidth, strokeWidth + pick(pointStateOptions.lineWidthPlus, seriesStateOptions.lineWidthPlus, 0)); + fill = (pointStateOptions.fillColor || + seriesStateOptions.fillColor || + fill); + stroke = (pointStateOptions.lineColor || + seriesStateOptions.lineColor || + stroke); + opacity = pick(pointStateOptions.opacity, seriesStateOptions.opacity, opacity); + } + return { + 'stroke': stroke, + 'stroke-width': strokeWidth, + 'fill': fill, + 'opacity': opacity + }; + }, + /** + * Clear DOM objects and free up memory. + * + * @private + * @function Highcharts.Series#destroy + * @param {boolean} [keepEventsForUpdate] + * @return {void} + * @fires Highcharts.Series#event:destroy + */ + destroy: function (keepEventsForUpdate) { + var series = this, chart = series.chart, issue134 = /AppleWebKit\/533/.test(win.navigator.userAgent), destroy, i, data = series.data || [], point, axis; + // add event hook + fireEvent(series, 'destroy'); + // remove events + this.removeEvents(keepEventsForUpdate); + // erase from axes + (series.axisTypes || []).forEach(function (AXIS) { + axis = series[AXIS]; + if (axis && axis.series) { + erase(axis.series, series); + axis.isDirty = axis.forceRedraw = true; + } + }); + // remove legend items + if (series.legendItem) { + series.chart.legend.destroyItem(series); + } + // destroy all points with their elements + i = data.length; + while (i--) { + point = data[i]; + if (point && point.destroy) { + point.destroy(); + } + } + series.points = null; + // Clear the animation timeout if we are destroying the series + // during initial animation + U.clearTimeout(series.animationTimeout); + // Destroy all SVGElements associated to the series + objectEach(series, function (val, prop) { + // Survive provides a hook for not destroying + if (val instanceof SVGElement && !val.survive) { + // issue 134 workaround + destroy = issue134 && prop === 'group' ? + 'hide' : + 'destroy'; + val[destroy](); + } + }); + // remove from hoverSeries + if (chart.hoverSeries === series) { + chart.hoverSeries = null; + } + erase(chart.series, series); + chart.orderSeries(); + // clear all members + objectEach(series, function (val, prop) { + if (!keepEventsForUpdate || prop !== 'hcEvents') { + delete series[prop]; + } + }); + }, + /** + * Get the graph path. + * + * @private + * @function Highcharts.Series#getGraphPath + * @param {Array} points + * @param {boolean} [nullsAsZeroes] + * @param {boolean} [connectCliffs] + * @return {Highcharts.SVGPathArray} + */ + getGraphPath: function (points, nullsAsZeroes, connectCliffs) { + var series = this, options = series.options, step = options.step, reversed, graphPath = [], xMap = [], gap; + points = points || series.points; + // Bottom of a stack is reversed + reversed = points.reversed; + if (reversed) { + points.reverse(); + } + // Reverse the steps (#5004) + step = { + right: 1, + center: 2 + }[step] || (step && 3); + if (step && reversed) { + step = 4 - step; + } + // Remove invalid points, especially in spline (#5015) + points = this.getValidPoints(points, false, !(options.connectNulls && !nullsAsZeroes && !connectCliffs)); + // Build the line + points.forEach(function (point, i) { + var plotX = point.plotX, plotY = point.plotY, lastPoint = points[i - 1], + // the path to this point from the previous + pathToPoint; + if ((point.leftCliff || (lastPoint && lastPoint.rightCliff)) && + !connectCliffs) { + gap = true; // ... and continue + } + // Line series, nullsAsZeroes is not handled + if (point.isNull && !defined(nullsAsZeroes) && i > 0) { + gap = !options.connectNulls; + // Area series, nullsAsZeroes is set + } + else if (point.isNull && !nullsAsZeroes) { + gap = true; + } + else { + if (i === 0 || gap) { + pathToPoint = [[ + 'M', + point.plotX, + point.plotY + ]]; + // Generate the spline as defined in the SplineSeries object + } + else if (series.getPointSpline) { + pathToPoint = [series.getPointSpline(points, point, i)]; + } + else if (step) { + if (step === 1) { // right + pathToPoint = [[ + 'L', + lastPoint.plotX, + plotY + ]]; + } + else if (step === 2) { // center + pathToPoint = [[ + 'L', + (lastPoint.plotX + plotX) / 2, + lastPoint.plotY + ], [ + 'L', + (lastPoint.plotX + plotX) / 2, + plotY + ]]; + } + else { + pathToPoint = [[ + 'L', + plotX, + lastPoint.plotY + ]]; + } + pathToPoint.push([ + 'L', + plotX, + plotY + ]); + } + else { + // normal line to next point + pathToPoint = [[ + 'L', + plotX, + plotY + ]]; + } + // Prepare for animation. When step is enabled, there are + // two path nodes for each x value. + xMap.push(point.x); + if (step) { + xMap.push(point.x); + if (step === 2) { // step = center (#8073) + xMap.push(point.x); + } + } + graphPath.push.apply(graphPath, pathToPoint); + gap = false; + } + }); + graphPath.xMap = xMap; + series.graphPath = graphPath; + return graphPath; + }, + /** + * Draw the graph. Called internally when rendering line-like series + * types. The first time it generates the `series.graph` item and + * optionally other series-wide items like `series.area` for area + * charts. On subsequent calls these items are updated with new + * positions and attributes. + * + * @function Highcharts.Series#drawGraph + * + * @return {void} + */ + drawGraph: function () { + var series = this, options = this.options, graphPath = (this.gappedPath || this.getGraphPath).call(this), styledMode = this.chart.styledMode, props = [[ + 'graph', + 'highcharts-graph' + ]]; + // Presentational properties + if (!styledMode) { + props[0].push((options.lineColor || + this.color || + '#cccccc' // when colorByPoint = true + ), options.dashStyle); + } + props = series.getZonesGraphs(props); + // Draw the graph + props.forEach(function (prop, i) { + var graphKey = prop[0], graph = series[graphKey], verb = graph ? 'animate' : 'attr', attribs; + if (graph) { + graph.endX = series.preventGraphAnimation ? + null : + graphPath.xMap; + graph.animate({ d: graphPath }); + } + else if (graphPath.length) { // #1487 + /** + * SVG element of area-based charts. Can be used for styling + * purposes. If zones are configured, this element will be + * hidden and replaced by multiple zone areas, accessible + * via `series['zone-area-x']` (where x is a number, + * starting with 0). + * + * @name Highcharts.Series#area + * @type {Highcharts.SVGElement|undefined} + */ + /** + * SVG element of line-based charts. Can be used for styling + * purposes. If zones are configured, this element will be + * hidden and replaced by multiple zone lines, accessible + * via `series['zone-graph-x']` (where x is a number, + * starting with 0). + * + * @name Highcharts.Series#graph + * @type {Highcharts.SVGElement|undefined} + */ + series[graphKey] = graph = series.chart.renderer + .path(graphPath) + .addClass(prop[1]) + .attr({ zIndex: 1 }) // #1069 + .add(series.group); + } + if (graph && !styledMode) { + attribs = { + 'stroke': prop[2], + 'stroke-width': options.lineWidth, + // Polygon series use filled graph + 'fill': (series.fillGraph && series.color) || 'none' + }; + if (prop[3]) { + attribs.dashstyle = prop[3]; + } + else if (options.linecap !== 'square') { + attribs['stroke-linecap'] = + attribs['stroke-linejoin'] = 'round'; + } + graph[verb](attribs) + // Add shadow to normal series (0) or to first + // zone (1) #3932 + .shadow((i < 2) && options.shadow); + } + // Helpers for animation + if (graph) { + graph.startX = graphPath.xMap; + graph.isArea = graphPath.isArea; // For arearange animation + } + }); + }, + /** + * Get zones properties for building graphs. Extendable by series with + * multiple lines within one series. + * + * @private + * @function Highcharts.Series#getZonesGraphs + * + * @param {Array>} props + * + * @return {Array>} + */ + getZonesGraphs: function (props) { + // Add the zone properties if any + this.zones.forEach(function (zone, i) { + var propset = [ + 'zone-graph-' + i, + 'highcharts-graph highcharts-zone-graph-' + i + ' ' + + (zone.className || '') + ]; + if (!this.chart.styledMode) { + propset.push((zone.color || this.color), (zone.dashStyle || this.options.dashStyle)); + } + props.push(propset); + }, this); + return props; + }, + /** + * Clip the graphs into zones for colors and styling. + * + * @private + * @function Highcharts.Series#applyZones + * @return {void} + */ + applyZones: function () { + var series = this, chart = this.chart, renderer = chart.renderer, zones = this.zones, translatedFrom, translatedTo, clips = (this.clips || []), clipAttr, graph = this.graph, area = this.area, chartSizeMax = Math.max(chart.chartWidth, chart.chartHeight), axis = this[(this.zoneAxis || 'y') + 'Axis'], extremes, reversed, inverted = chart.inverted, horiz, pxRange, pxPosMin, pxPosMax, ignoreZones = false, zoneArea, zoneGraph; + if (zones.length && + (graph || area) && + axis && + typeof axis.min !== 'undefined') { + reversed = axis.reversed; + horiz = axis.horiz; + // The use of the Color Threshold assumes there are no gaps + // so it is safe to hide the original graph and area + // unless it is not waterfall series, then use showLine property + // to set lines between columns to be visible (#7862) + if (graph && !this.showLine) { + graph.hide(); + } + if (area) { + area.hide(); + } + // Create the clips + extremes = axis.getExtremes(); + zones.forEach(function (threshold, i) { + translatedFrom = reversed ? + (horiz ? chart.plotWidth : 0) : + (horiz ? 0 : (axis.toPixels(extremes.min) || 0)); + translatedFrom = clamp(pick(translatedTo, translatedFrom), 0, chartSizeMax); + translatedTo = clamp(Math.round(axis.toPixels(pick(threshold.value, extremes.max), true) || 0), 0, chartSizeMax); + if (ignoreZones) { + translatedFrom = translatedTo = + axis.toPixels(extremes.max); + } + pxRange = Math.abs(translatedFrom - translatedTo); + pxPosMin = Math.min(translatedFrom, translatedTo); + pxPosMax = Math.max(translatedFrom, translatedTo); + if (axis.isXAxis) { + clipAttr = { + x: inverted ? pxPosMax : pxPosMin, + y: 0, + width: pxRange, + height: chartSizeMax + }; + if (!horiz) { + clipAttr.x = chart.plotHeight - clipAttr.x; + } + } + else { + clipAttr = { + x: 0, + y: inverted ? pxPosMax : pxPosMin, + width: chartSizeMax, + height: pxRange + }; + if (horiz) { + clipAttr.y = chart.plotWidth - clipAttr.y; + } + } + // VML SUPPPORT + if (inverted && renderer.isVML) { + if (axis.isXAxis) { + clipAttr = { + x: 0, + y: reversed ? pxPosMin : pxPosMax, + height: clipAttr.width, + width: chart.chartWidth + }; + } + else { + clipAttr = { + x: (clipAttr.y - + chart.plotLeft - + chart.spacingBox.x), + y: 0, + width: clipAttr.height, + height: chart.chartHeight + }; + } + } + // END OF VML SUPPORT + if (clips[i]) { + clips[i].animate(clipAttr); + } + else { + clips[i] = renderer.clipRect(clipAttr); + } + // when no data, graph zone is not applied and after setData + // clip was ignored. As a result, it should be applied each + // time. + zoneArea = series['zone-area-' + i]; + zoneGraph = series['zone-graph-' + i]; + if (graph && zoneGraph) { + zoneGraph.clip(clips[i]); + } + if (area && zoneArea) { + zoneArea.clip(clips[i]); + } + // if this zone extends out of the axis, ignore the others + ignoreZones = threshold.value > extremes.max; + // Clear translatedTo for indicators + if (series.resetZones && translatedTo === 0) { + translatedTo = void 0; + } + }); + this.clips = clips; + } + else if (series.visible) { + // If zones were removed, restore graph and area + if (graph) { + graph.show(true); + } + if (area) { + area.show(true); + } + } + }, + /** + * Initialize and perform group inversion on series.group and + * series.markerGroup. + * + * @private + * @function Highcharts.Series#invertGroups + * @param {boolean} [inverted] + * @return {void} + */ + invertGroups: function (inverted) { + var series = this, chart = series.chart; + /** + * @private + */ + function setInvert() { + ['group', 'markerGroup'].forEach(function (groupName) { + if (series[groupName]) { + // VML/HTML needs explicit attributes for flipping + if (chart.renderer.isVML) { + series[groupName].attr({ + width: series.yAxis.len, + height: series.xAxis.len + }); + } + series[groupName].width = series.yAxis.len; + series[groupName].height = series.xAxis.len; + // If inverted polar, don't invert series group + series[groupName].invert(series.isRadialSeries ? false : inverted); + } + }); + } + // Pie, go away (#1736) + if (!series.xAxis) { + return; + } + // A fixed size is needed for inversion to work + series.eventsToUnbind.push(addEvent(chart, 'resize', setInvert)); + // Do it now + setInvert(); + // On subsequent render and redraw, just do setInvert without + // setting up events again + series.invertGroups = setInvert; + }, + /** + * General abstraction for creating plot groups like series.group, + * series.dataLabelsGroup and series.markerGroup. On subsequent calls, + * the group will only be adjusted to the updated plot size. + * + * @private + * @function Highcharts.Series#plotGroup + * @param {string} prop + * @param {string} name + * @param {string} visibility + * @param {number} [zIndex] + * @param {Highcharts.SVGElement} [parent] + * @return {Highcharts.SVGElement} + */ + plotGroup: function (prop, name, visibility, zIndex, parent) { + var group = this[prop], isNew = !group; + // Generate it on first call + if (isNew) { + this[prop] = group = this.chart.renderer + .g() + .attr({ + zIndex: zIndex || 0.1 // IE8 and pointer logic use this + }) + .add(parent); + } + // Add the class names, and replace existing ones as response to + // Series.update (#6660) + group.addClass(('highcharts-' + name + + ' highcharts-series-' + this.index + + ' highcharts-' + this.type + '-series ' + + (defined(this.colorIndex) ? + 'highcharts-color-' + this.colorIndex + ' ' : + '') + + (this.options.className || '') + + (group.hasClass('highcharts-tracker') ? + ' highcharts-tracker' : + '')), true); + // Place it on first and subsequent (redraw) calls + group.attr({ visibility: visibility })[isNew ? 'attr' : 'animate'](this.getPlotBox()); + return group; + }, + /** + * Get the translation and scale for the plot area of this series. + * + * @function Highcharts.Series#getPlotBox + * + * @return {Highcharts.SeriesPlotBoxObject} + */ + getPlotBox: function () { + var chart = this.chart, xAxis = this.xAxis, yAxis = this.yAxis; + // Swap axes for inverted (#2339) + if (chart.inverted) { + xAxis = yAxis; + yAxis = this.xAxis; + } + return { + translateX: xAxis ? xAxis.left : chart.plotLeft, + translateY: yAxis ? yAxis.top : chart.plotTop, + scaleX: 1, + scaleY: 1 + }; + }, + /** + * Removes the event handlers attached previously with addEvents. + * + * @private + * @function Highcharts.Series#removeEvents + * @param {boolean} [keepEventsForUpdate] + * @return {void} + */ + removeEvents: function (keepEventsForUpdate) { + var series = this; + if (!keepEventsForUpdate) { + // remove all events + removeEvent(series); + } + else if (series.eventsToUnbind.length) { + // remove only internal events for proper update + // #12355 - solves problem with multiple destroy events + series.eventsToUnbind.forEach(function (unbind) { + unbind(); + }); + series.eventsToUnbind.length = 0; + } + }, + /** + * Render the graph and markers. Called internally when first rendering + * and later when redrawing the chart. This function can be extended in + * plugins, but normally shouldn't be called directly. + * + * @function Highcharts.Series#render + * + * @return {void} + * + * @fires Highcharts.Series#event:afterRender + */ + render: function () { + var series = this, chart = series.chart, group, options = series.options, + // Animation doesn't work in IE8 quirks when the group div is + // hidden, and looks bad in other oldIE + animDuration = (!series.finishedAnimating && + chart.renderer.isSVG && + animObject(options.animation).duration), visibility = series.visible ? 'inherit' : 'hidden', // #2597 + zIndex = options.zIndex, hasRendered = series.hasRendered, chartSeriesGroup = chart.seriesGroup, inverted = chart.inverted; + fireEvent(this, 'render'); + // the group + group = series.plotGroup('group', 'series', visibility, zIndex, chartSeriesGroup); + series.markerGroup = series.plotGroup('markerGroup', 'markers', visibility, zIndex, chartSeriesGroup); + // initiate the animation + if (animDuration && series.animate) { + series.animate(true); + } + // SVGRenderer needs to know this before drawing elements (#1089, + // #1795) + group.inverted = series.isCartesian || series.invertable ? + inverted : false; + // Draw the graph if any + if (series.drawGraph) { + series.drawGraph(); + series.applyZones(); + } + // Draw the points + if (series.visible) { + series.drawPoints(); + } + /* series.points.forEach(function (point) { + if (point.redraw) { + point.redraw(); + } + }); */ + // Draw the data labels + if (series.drawDataLabels) { + series.drawDataLabels(); + } + // In pie charts, slices are added to the DOM, but actual rendering + // is postponed until labels reserved their space + if (series.redrawPoints) { + series.redrawPoints(); + } + // draw the mouse tracking area + if (series.drawTracker && + series.options.enableMouseTracking !== false) { + series.drawTracker(); + } + // Handle inverted series and tracker groups + series.invertGroups(inverted); + // Initial clipping, must be defined after inverting groups for VML. + // Applies to columns etc. (#3839). + if (options.clip !== false && + !series.sharedClipKey && + !hasRendered) { + group.clip(chart.clipRect); + } + // Run the animation + if (animDuration && series.animate) { + series.animate(); + } + // Call the afterAnimate function on animation complete (but don't + // overwrite the animation.complete option which should be available + // to the user). + if (!hasRendered) { + series.animationTimeout = syncTimeout(function () { + series.afterAnimate(); + }, animDuration || 0); + } + // Means data is in accordance with what you see + series.isDirty = false; + // (See #322) series.isDirty = series.isDirtyData = false; // means + // data is in accordance with what you see + series.hasRendered = true; + fireEvent(series, 'afterRender'); + }, + /** + * Redraw the series. This function is called internally from + * `chart.redraw` and normally shouldn't be called directly. + * + * @private + * @function Highcharts.Series#redraw + * @return {void} + */ + redraw: function () { + var series = this, chart = series.chart, + // cache it here as it is set to false in render, but used after + wasDirty = series.isDirty || series.isDirtyData, group = series.group, xAxis = series.xAxis, yAxis = series.yAxis; + // reposition on resize + if (group) { + if (chart.inverted) { + group.attr({ + width: chart.plotWidth, + height: chart.plotHeight + }); + } + group.animate({ + translateX: pick(xAxis && xAxis.left, chart.plotLeft), + translateY: pick(yAxis && yAxis.top, chart.plotTop) + }); + } + series.translate(); + series.render(); + if (wasDirty) { // #3868, #3945 + delete this.kdTree; + } + }, + kdAxisArray: ['clientX', 'plotY'], + /** + * @private + * @function Highcharts.Series#searchPoint + * @param {Highcharts.PointerEventObject} e + * @param {boolean} [compareX] + * @return {Highcharts.Point} + */ + searchPoint: function (e, compareX) { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, inverted = series.chart.inverted; + return this.searchKDTree({ + clientX: inverted ? + xAxis.len - e.chartY + xAxis.pos : + e.chartX - xAxis.pos, + plotY: inverted ? + yAxis.len - e.chartX + yAxis.pos : + e.chartY - yAxis.pos + }, compareX, e); + }, + /** + * Build the k-d-tree that is used by mouse and touch interaction to get + * the closest point. Line-like series typically have a one-dimensional + * tree where points are searched along the X axis, while scatter-like + * series typically search in two dimensions, X and Y. + * + * @private + * @function Highcharts.Series#buildKDTree + * @param {Highcharts.PointerEventObject} [e] + * @return {void} + */ + buildKDTree: function (e) { + // Prevent multiple k-d-trees from being built simultaneously + // (#6235) + this.buildingKdTree = true; + var series = this, dimensions = series.options.findNearestPointBy + .indexOf('y') > -1 ? 2 : 1; + /** + * Internal function + * @private + */ + function _kdtree(points, depth, dimensions) { + var axis, median, length = points && points.length; + if (length) { + // alternate between the axis + axis = series.kdAxisArray[depth % dimensions]; + // sort point array + points.sort(function (a, b) { + return a[axis] - b[axis]; + }); + median = Math.floor(length / 2); + // build and return nod + return { + point: points[median], + left: _kdtree(points.slice(0, median), depth + 1, dimensions), + right: _kdtree(points.slice(median + 1), depth + 1, dimensions) + }; + } + } + /** + * Start the recursive build process with a clone of the points + * array and null points filtered out. (#3873) + * @private + */ + function startRecursive() { + series.kdTree = _kdtree(series.getValidPoints(null, + // For line-type series restrict to plot area, but + // column-type series not (#3916, #4511) + !series.directTouch), dimensions, dimensions); + series.buildingKdTree = false; + } + delete series.kdTree; + // For testing tooltips, don't build async. Also if touchstart, we + // may be dealing with click events on mobile, so don't delay + // (#6817). + syncTimeout(startRecursive, series.options.kdNow || (e && e.type === 'touchstart') ? 0 : 1); + }, + /** + * @private + * @function Highcharts.Series#searchKDTree + * @param {Highcharts.KDPointSearchObject} point + * @param {boolean} [compareX] + * @param {Highcharts.PointerEventObject} [e] + * @return {Highcharts.Point|undefined} + */ + searchKDTree: function (point, compareX, e) { + var series = this, kdX = this.kdAxisArray[0], kdY = this.kdAxisArray[1], kdComparer = compareX ? 'distX' : 'dist', kdDimensions = series.options.findNearestPointBy + .indexOf('y') > -1 ? 2 : 1; + /** + * Set the one and two dimensional distance on the point object. + * @private + */ + function setDistance(p1, p2) { + var x = (defined(p1[kdX]) && + defined(p2[kdX])) ? + Math.pow(p1[kdX] - p2[kdX], 2) : + null, y = (defined(p1[kdY]) && + defined(p2[kdY])) ? + Math.pow(p1[kdY] - p2[kdY], 2) : + null, r = (x || 0) + (y || 0); + p2.dist = defined(r) ? Math.sqrt(r) : Number.MAX_VALUE; + p2.distX = defined(x) ? Math.sqrt(x) : Number.MAX_VALUE; + } + /** + * @private + */ + function _search(search, tree, depth, dimensions) { + var point = tree.point, axis = series.kdAxisArray[depth % dimensions], tdist, sideA, sideB, ret = point, nPoint1, nPoint2; + setDistance(search, point); + // Pick side based on distance to splitting point + tdist = search[axis] - point[axis]; + sideA = tdist < 0 ? 'left' : 'right'; + sideB = tdist < 0 ? 'right' : 'left'; + // End of tree + if (tree[sideA]) { + nPoint1 = _search(search, tree[sideA], depth + 1, dimensions); + ret = (nPoint1[kdComparer] < + ret[kdComparer] ? + nPoint1 : + point); + } + if (tree[sideB]) { + // compare distance to current best to splitting point to + // decide wether to check side B or not + if (Math.sqrt(tdist * tdist) < ret[kdComparer]) { + nPoint2 = _search(search, tree[sideB], depth + 1, dimensions); + ret = (nPoint2[kdComparer] < + ret[kdComparer] ? + nPoint2 : + ret); + } + } + return ret; + } + if (!this.kdTree && !this.buildingKdTree) { + this.buildKDTree(e); + } + if (this.kdTree) { + return _search(point, this.kdTree, kdDimensions, kdDimensions); + } + }, + /** + * @private + * @function Highcharts.Series#pointPlacementToXValue + * @return {number} + */ + pointPlacementToXValue: function () { + var _a = this, _b = _a.options, pointPlacement = _b.pointPlacement, pointRange = _b.pointRange, axis = _a.xAxis; + var factor = pointPlacement; + // Point placement is relative to each series pointRange (#5889) + if (factor === 'between') { + factor = axis.reversed ? -0.5 : 0.5; // #11955 + } + return isNumber(factor) ? + factor * pick(pointRange, axis.pointRange) : + 0; + }, + /** + * @private + * @function Highcharts.Series#isPointInside + * @param {Highcharts.Point} point + * @return {boolean} + */ + isPointInside: function (point) { + var isInside = typeof point.plotY !== 'undefined' && + typeof point.plotX !== 'undefined' && + point.plotY >= 0 && + point.plotY <= this.yAxis.len && // #3519 + point.plotX >= 0 && + point.plotX <= this.xAxis.len; + return isInside; + } + }); // end Series prototype + /** + * A line series displays information as a series of data points connected by + * straight line segments. + * + * @sample {highcharts} highcharts/demo/line-basic/ + * Line chart + * @sample {highstock} stock/demo/basic-line/ + * Line chart + * + * @extends plotOptions.series + * @product highcharts highstock + * @apioption plotOptions.line + */ + /** + * The SVG value used for the `stroke-linecap` and `stroke-linejoin` + * of a line graph. Round means that lines are rounded in the ends and + * bends. + * + * @type {Highcharts.SeriesLinecapValue} + * @default round + * @since 3.0.7 + * @apioption plotOptions.line.linecap + */ + /** + * A `line` series. If the [type](#series.line.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.line + * @excluding dataParser,dataURL + * @product highcharts highstock + * @apioption series.line + */ + /** + * An array of data points for the series. For the `line` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 1], + * [1, 2], + * [2, 8] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.line.turboThreshold), + * this option is not available. + * ```js + * data: [{ + * x: 1, + * y: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * **Note:** In TypeScript you have to extend `PointOptionsObject` with an + * additional declaration to allow custom data types: + * ```ts + * declare module `highcharts` { + * interface PointOptionsObject { + * custom: Record; + * } + * } + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @declare Highcharts.PointOptionsObject + * @type {Array|null|*>} + * @apioption series.line.data + */ + /** + * An additional, individual class name for the data point's graphic + * representation. + * + * @type {string} + * @since 5.0.0 + * @product highcharts gantt + * @apioption series.line.data.className + */ + /** + * Individual color for the point. By default the color is pulled from + * the global `colors` array. + * + * In styled mode, the `color` option doesn't take effect. Instead, use + * `colorIndex`. + * + * @sample {highcharts} highcharts/point/color/ + * Mark the highest point + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock gantt + * @apioption series.line.data.color + */ + /** + * A specific color index to use for the point, so its graphic representations + * are given the class name `highcharts-color-{n}`. In styled mode this will + * change the color of the graphic. In non-styled mode, the color by is set by + * the `fill` attribute, so the change in class name won't have a visual effect + * by default. + * + * @type {number} + * @since 5.0.0 + * @product highcharts gantt + * @apioption series.line.data.colorIndex + */ + /** + * A reserved subspace to store options and values for customized functionality. + * Here you can add additional data for your own event callbacks and formatter + * callbacks. + * + * @sample {highcharts} highcharts/point/custom/ + * Point and series with custom data + * + * @type {Highcharts.Dictionary<*>} + * @apioption series.line.data.custom + */ + /** + * Individual data label for each point. The options are the same as + * the ones for [plotOptions.series.dataLabels]( + * #plotOptions.series.dataLabels). + * + * @sample highcharts/point/datalabels/ + * Show a label for the last value + * + * @declare Highcharts.DataLabelsOptions + * @extends plotOptions.line.dataLabels + * @product highcharts highstock gantt + * @apioption series.line.data.dataLabels + */ + /** + * A description of the point to add to the screen reader information + * about the point. + * + * @type {string} + * @since 5.0.0 + * @requires modules/accessibility + * @apioption series.line.data.description + */ + /** + * An id for the point. This can be used after render time to get a + * pointer to the point object through `chart.get()`. + * + * @sample {highcharts} highcharts/point/id/ + * Remove an id'd point + * + * @type {string} + * @since 1.2.0 + * @product highcharts highstock gantt + * @apioption series.line.data.id + */ + /** + * The rank for this point's data label in case of collision. If two + * data labels are about to overlap, only the one with the highest `labelrank` + * will be drawn. + * + * @type {number} + * @apioption series.line.data.labelrank + */ + /** + * The name of the point as shown in the legend, tooltip, dataLabels, etc. + * + * @see [xAxis.uniqueNames](#xAxis.uniqueNames) + * + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Point names + * + * @type {string} + * @apioption series.line.data.name + */ + /** + * Whether the data point is selected initially. + * + * @type {boolean} + * @default false + * @product highcharts highstock gantt + * @apioption series.line.data.selected + */ + /** + * The x value of the point. For datetime axes, the X value is the timestamp + * in milliseconds since 1970. + * + * @type {number} + * @product highcharts highstock + * @apioption series.line.data.x + */ + /** + * The y value of the point. + * + * @type {number|null} + * @product highcharts highstock + * @apioption series.line.data.y + */ + /** + * The individual point events. + * + * @extends plotOptions.series.point.events + * @product highcharts highstock gantt + * @apioption series.line.data.events + */ + /** + * Options for the point markers of line-like series. + * + * @declare Highcharts.PointMarkerOptionsObject + * @extends plotOptions.series.marker + * @product highcharts highstock + * @apioption series.line.data.marker + */ + ''; // include precedent doclets in transpilat + + }); + _registerModule(_modules, 'parts/Stacking.js', [_modules['parts/Axis.js'], _modules['parts/Globals.js'], _modules['parts/StackingAxis.js'], _modules['parts/Utilities.js']], function (Axis, H, StackingAxis, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var correctFloat = U.correctFloat, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, format = U.format, pick = U.pick; + /** + * Stack of data points + * + * @product highcharts + * + * @interface Highcharts.StackItemObject + */ /** + * Alignment settings + * @name Highcharts.StackItemObject#alignOptions + * @type {Highcharts.AlignObject} + */ /** + * Related axis + * @name Highcharts.StackItemObject#axis + * @type {Highcharts.Axis} + */ /** + * Cumulative value of the stacked data points + * @name Highcharts.StackItemObject#cumulative + * @type {number} + */ /** + * True if on the negative side + * @name Highcharts.StackItemObject#isNegative + * @type {boolean} + */ /** + * Related SVG element + * @name Highcharts.StackItemObject#label + * @type {Highcharts.SVGElement} + */ /** + * Related stack options + * @name Highcharts.StackItemObject#options + * @type {Highcharts.YAxisStackLabelsOptions} + */ /** + * Total value of the stacked data points + * @name Highcharts.StackItemObject#total + * @type {number} + */ /** + * Shared x value of the stack + * @name Highcharts.StackItemObject#x + * @type {number} + */ + ''; // detached doclets above + var Chart = H.Chart, Series = H.Series; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The class for stacks. Each stack, on a specific X value and either negative + * or positive, has its own stack item. + * + * @private + * @class + * @name Highcharts.StackItem + * @param {Highcharts.Axis} axis + * @param {Highcharts.YAxisStackLabelsOptions} options + * @param {boolean} isNegative + * @param {number} x + * @param {Highcharts.OptionsStackingValue} [stackOption] + */ + var StackItem = /** @class */ (function () { + function StackItem(axis, options, isNegative, x, stackOption) { + var inverted = axis.chart.inverted; + this.axis = axis; + // Tells if the stack is negative + this.isNegative = isNegative; + // Save the options to be able to style the label + this.options = options = options || {}; + // Save the x value to be able to position the label later + this.x = x; + // Initialize total value + this.total = null; + // This will keep each points' extremes stored by series.index and point + // index + this.points = {}; + // Save the stack option on the series configuration object, + // and whether to treat it as percent + this.stack = stackOption; + this.leftCliff = 0; + this.rightCliff = 0; + // The align options and text align varies on whether the stack is + // negative and if the chart is inverted or not. + // First test the user supplied value, then use the dynamic. + this.alignOptions = { + align: options.align || + (inverted ? (isNegative ? 'left' : 'right') : 'center'), + verticalAlign: options.verticalAlign || + (inverted ? 'middle' : (isNegative ? 'bottom' : 'top')), + y: options.y, + x: options.x + }; + this.textAlign = options.textAlign || + (inverted ? (isNegative ? 'right' : 'left') : 'center'); + } + /** + * @private + * @function Highcharts.StackItem#destroy + */ + StackItem.prototype.destroy = function () { + destroyObjectProperties(this, this.axis); + }; + /** + * Renders the stack total label and adds it to the stack label group. + * + * @private + * @function Highcharts.StackItem#render + * @param {Highcharts.SVGElement} group + */ + StackItem.prototype.render = function (group) { + var chart = this.axis.chart, options = this.options, formatOption = options.format, attr = {}, str = formatOption ? // format the text in the label + format(formatOption, this, chart) : + options.formatter.call(this); + // Change the text to reflect the new total and set visibility to hidden + // in case the serie is hidden + if (this.label) { + this.label.attr({ text: str, visibility: 'hidden' }); + } + else { + // Create new label + this.label = chart.renderer + .label(str, null, null, options.shape, null, null, options.useHTML, false, 'stack-labels'); + attr = { + r: options.borderRadius || 0, + text: str, + rotation: options.rotation, + padding: pick(options.padding, 5), + visibility: 'hidden' // hidden until setOffset is called + }; + if (!chart.styledMode) { + attr.fill = options.backgroundColor; + attr.stroke = options.borderColor; + attr['stroke-width'] = options.borderWidth; + this.label.css(options.style); + } + this.label.attr(attr); + if (!this.label.added) { + this.label.add(group); // add to the labels-group + } + } + // Rank it higher than data labels (#8742) + this.label.labelrank = chart.plotHeight; + }; + /** + * Sets the offset that the stack has from the x value and repositions the + * label. + * + * @private + * @function Highcarts.StackItem#setOffset + * @param {number} xOffset + * @param {number} xWidth + * @param {number} [boxBottom] + * @param {number} [boxTop] + * @param {number} [defaultX] + */ + StackItem.prototype.setOffset = function (xOffset, xWidth, boxBottom, boxTop, defaultX) { + var stackItem = this, axis = stackItem.axis, chart = axis.chart, + // stack value translated mapped to chart coordinates + y = axis.translate(axis.stacking.usePercentage ? + 100 : + (boxTop ? + boxTop : + stackItem.total), 0, 0, 0, 1), yZero = axis.translate(boxBottom ? boxBottom : 0), // stack origin + // stack height: + h = defined(y) && Math.abs(y - yZero), + // x position: + x = pick(defaultX, chart.xAxis[0].translate(stackItem.x)) + + xOffset, stackBox = defined(y) && stackItem.getStackBox(chart, stackItem, x, y, xWidth, h, axis), label = stackItem.label, isNegative = stackItem.isNegative, isJustify = pick(stackItem.options.overflow, 'justify') === 'justify', textAlign = stackItem.textAlign, visible; + if (label && stackBox) { + var bBox = label.getBBox(), padding = label.padding, boxOffsetX, boxOffsetY; + if (textAlign === 'left') { + boxOffsetX = chart.inverted ? -padding : padding; + } + else if (textAlign === 'right') { + boxOffsetX = bBox.width; + } + else { + if (chart.inverted && textAlign === 'center') { + boxOffsetX = bBox.width / 2; + } + else { + boxOffsetX = chart.inverted ? + (isNegative ? bBox.width + padding : -padding) : bBox.width / 2; + } + } + boxOffsetY = chart.inverted ? + bBox.height / 2 : (isNegative ? -padding : bBox.height); + // Reset alignOptions property after justify #12337 + stackItem.alignOptions.x = pick(stackItem.options.x, 0); + stackItem.alignOptions.y = pick(stackItem.options.y, 0); + // Set the stackBox position + stackBox.x -= boxOffsetX; + stackBox.y -= boxOffsetY; + // Align the label to the box + label.align(stackItem.alignOptions, null, stackBox); + // Check if label is inside the plotArea #12294 + if (chart.isInsidePlot(label.alignAttr.x + boxOffsetX - stackItem.alignOptions.x, label.alignAttr.y + boxOffsetY - stackItem.alignOptions.y)) { + label.show(); + } + else { + // Move label away to avoid the overlapping issues + label.alignAttr.y = -9999; + isJustify = false; + } + if (isJustify) { + // Justify stackLabel into the stackBox + Series.prototype.justifyDataLabel.call(this.axis, label, stackItem.alignOptions, label.alignAttr, bBox, stackBox); + } + label.attr({ + x: label.alignAttr.x, + y: label.alignAttr.y + }); + if (pick(!isJustify && stackItem.options.crop, true)) { + visible = chart.isInsidePlot(label.x - padding + label.width, label.y) && + chart.isInsidePlot(label.x + padding, label.y); + if (!visible) { + label.hide(); + } + } + } + }; + /** + * @private + * @function Highcharts.StackItem#getStackBox + * + * @param {Highcharts.Chart} chart + * + * @param {Highcharts.StackItem} stackItem + * + * @param {number} x + * + * @param {number} y + * + * @param {number} xWidth + * + * @param {number} h + * + * @param {Highcharts.Axis} axis + * + * @return {Highcharts.BBoxObject} + */ + StackItem.prototype.getStackBox = function (chart, stackItem, x, y, xWidth, h, axis) { + var reversed = stackItem.axis.reversed, inverted = chart.inverted, axisPos = axis.height + axis.pos - + (inverted ? chart.plotLeft : chart.plotTop), neg = (stackItem.isNegative && !reversed) || + (!stackItem.isNegative && reversed); // #4056 + return { + x: inverted ? (neg ? y - axis.right : y - h + axis.pos - chart.plotLeft) : + x + chart.xAxis[0].transB - chart.plotLeft, + y: inverted ? + axis.height - x - xWidth : + (neg ? + (axisPos - y - h) : + axisPos - y), + width: inverted ? h : xWidth, + height: inverted ? xWidth : h + }; + }; + return StackItem; + }()); + /** + * Generate stacks for each series and calculate stacks total values + * + * @private + * @function Highcharts.Chart#getStacks + * @return {void} + */ + Chart.prototype.getStacks = function () { + var chart = this, inverted = chart.inverted; + // reset stacks for each yAxis + chart.yAxis.forEach(function (axis) { + if (axis.stacking && axis.stacking.stacks && axis.hasVisibleSeries) { + axis.stacking.oldStacks = axis.stacking.stacks; + } + }); + chart.series.forEach(function (series) { + var xAxisOptions = series.xAxis && series.xAxis.options || {}; + if (series.options.stacking && + (series.visible === true || + chart.options.chart.ignoreHiddenSeries === false)) { + series.stackKey = [ + series.type, + pick(series.options.stack, ''), + inverted ? xAxisOptions.top : xAxisOptions.left, + inverted ? xAxisOptions.height : xAxisOptions.width + ].join(','); + } + }); + }; + // Stacking methods defined on the Axis prototype + StackingAxis.compose(Axis); + // Stacking methods defnied for Series prototype + /** + * Adds series' points value to corresponding stack + * + * @private + * @function Highcharts.Series#setStackedPoints + */ + Series.prototype.setStackedPoints = function () { + if (!this.options.stacking || + (this.visible !== true && + this.chart.options.chart.ignoreHiddenSeries !== false)) { + return; + } + var series = this, xData = series.processedXData, yData = series.processedYData, stackedYData = [], yDataLength = yData.length, seriesOptions = series.options, threshold = seriesOptions.threshold, stackThreshold = pick(seriesOptions.startFromThreshold && threshold, 0), stackOption = seriesOptions.stack, stacking = seriesOptions.stacking, stackKey = series.stackKey, negKey = '-' + stackKey, negStacks = series.negStacks, yAxis = series.yAxis, stacks = yAxis.stacking.stacks, oldStacks = yAxis.stacking.oldStacks, stackIndicator, isNegative, stack, other, key, pointKey, i, x, y; + yAxis.stacking.stacksTouched += 1; + // loop over the non-null y values and read them into a local array + for (i = 0; i < yDataLength; i++) { + x = xData[i]; + y = yData[i]; + stackIndicator = series.getStackIndicator(stackIndicator, x, series.index); + pointKey = stackIndicator.key; + // Read stacked values into a stack based on the x value, + // the sign of y and the stack key. Stacking is also handled for null + // values (#739) + isNegative = negStacks && y < (stackThreshold ? 0 : threshold); + key = isNegative ? negKey : stackKey; + // Create empty object for this stack if it doesn't exist yet + if (!stacks[key]) { + stacks[key] = + {}; + } + // Initialize StackItem for this x + if (!stacks[key][x]) { + if (oldStacks[key] && + oldStacks[key][x]) { + stacks[key][x] = oldStacks[key][x]; + stacks[key][x].total = null; + } + else { + stacks[key][x] = new StackItem(yAxis, yAxis.options.stackLabels, isNegative, x, stackOption); + } + } + // If the StackItem doesn't exist, create it first + stack = stacks[key][x]; + if (y !== null) { + stack.points[pointKey] = stack.points[series.index] = + [pick(stack.cumulative, stackThreshold)]; + // Record the base of the stack + if (!defined(stack.cumulative)) { + stack.base = pointKey; + } + stack.touched = yAxis.stacking.stacksTouched; + // In area charts, if there are multiple points on the same X value, + // let the area fill the full span of those points + if (stackIndicator.index > 0 && series.singleStacks === false) { + stack.points[pointKey][0] = + stack.points[series.index + ',' + x + ',0'][0]; + } + // When updating to null, reset the point stack (#7493) + } + else { + stack.points[pointKey] = stack.points[series.index] = + null; + } + // Add value to the stack total + if (stacking === 'percent') { + // Percent stacked column, totals are the same for the positive and + // negative stacks + other = isNegative ? stackKey : negKey; + if (negStacks && stacks[other] && stacks[other][x]) { + other = stacks[other][x]; + stack.total = other.total = + Math.max(other.total, stack.total) + + Math.abs(y) || + 0; + // Percent stacked areas + } + else { + stack.total = + correctFloat(stack.total + (Math.abs(y) || 0)); + } + } + else { + stack.total = correctFloat(stack.total + (y || 0)); + } + stack.cumulative = + pick(stack.cumulative, stackThreshold) + (y || 0); + if (y !== null) { + stack.points[pointKey].push(stack.cumulative); + stackedYData[i] = stack.cumulative; + } + } + if (stacking === 'percent') { + yAxis.stacking.usePercentage = true; + } + this.stackedYData = stackedYData; // To be used in getExtremes + // Reset old stacks + yAxis.stacking.oldStacks = {}; + }; + /** + * Iterate over all stacks and compute the absolute values to percent + * + * @private + * @function Highcharts.Series#modifyStacks + */ + Series.prototype.modifyStacks = function () { + var series = this, yAxis = series.yAxis, stackKey = series.stackKey, stacks = yAxis.stacking.stacks, processedXData = series.processedXData, stackIndicator, stacking = series.options.stacking; + if (series[stacking + 'Stacker']) { // Modifier function exists + [stackKey, '-' + stackKey].forEach(function (key) { + var i = processedXData.length, x, stack, pointExtremes; + while (i--) { + x = processedXData[i]; + stackIndicator = series.getStackIndicator(stackIndicator, x, series.index, key); + stack = stacks[key] && stacks[key][x]; + pointExtremes = + stack && stack.points[stackIndicator.key]; + if (pointExtremes) { + series[stacking + 'Stacker'](pointExtremes, stack, i); + } + } + }); + } + }; + /** + * Modifier function for percent stacks. Blows up the stack to 100%. + * + * @private + * @function Highcharts.Series#percentStacker + * @param {Array} pointExtremes + * @param {Highcharts.StackItem} stack + * @param {number} i + */ + Series.prototype.percentStacker = function (pointExtremes, stack, i) { + var totalFactor = stack.total ? 100 / stack.total : 0; + // Y bottom value + pointExtremes[0] = correctFloat(pointExtremes[0] * totalFactor); + // Y value + pointExtremes[1] = correctFloat(pointExtremes[1] * totalFactor); + this.stackedYData[i] = pointExtremes[1]; + }; + /** + * Get stack indicator, according to it's x-value, to determine points with the + * same x-value + * + * @private + * @function Highcharts.Series#getStackIndicator + * @param {Highcharts.StackItemIndicatorObject|undefined} stackIndicator + * @param {number} x + * @param {number} index + * @param {string} [key] + * @return {Highcharts.StackItemIndicatorObject} + */ + Series.prototype.getStackIndicator = function (stackIndicator, x, index, key) { + // Update stack indicator, when: + // first point in a stack || x changed || stack type (negative vs positive) + // changed: + if (!defined(stackIndicator) || + stackIndicator.x !== x || + (key && stackIndicator.key !== key)) { + stackIndicator = { + x: x, + index: 0, + key: key + }; + } + else { + (stackIndicator).index++; + } + stackIndicator.key = + [index, x, stackIndicator.index].join(','); + return stackIndicator; + }; + H.StackItem = StackItem; + + return H.StackItem; + }); + _registerModule(_modules, 'parts/Dynamics.js', [_modules['parts/Globals.js'], _modules['parts/Point.js'], _modules['parts/Time.js'], _modules['parts/Utilities.js']], function (H, Point, Time, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, animate = U.animate, createElement = U.createElement, css = U.css, defined = U.defined, erase = U.erase, error = U.error, extend = U.extend, fireEvent = U.fireEvent, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, isString = U.isString, merge = U.merge, objectEach = U.objectEach, pick = U.pick, relativeLength = U.relativeLength, setAnimation = U.setAnimation, splat = U.splat; + var Axis = H.Axis, Chart = H.Chart, Series = H.Series, seriesTypes = H.seriesTypes; + /* eslint-disable valid-jsdoc */ + /** + * Remove settings that have not changed, to avoid unnecessary rendering or + * computing (#9197). + * @private + */ + H.cleanRecursively = function (newer, older) { + var result = {}; + objectEach(newer, function (val, key) { + var ob; + // Dive into objects (except DOM nodes) + if (isObject(newer[key], true) && + !newer.nodeType && // #10044 + older[key]) { + ob = H.cleanRecursively(newer[key], older[key]); + if (Object.keys(ob).length) { + result[key] = ob; + } + // Arrays, primitives and DOM nodes are copied directly + } + else if (isObject(newer[key]) || + newer[key] !== older[key]) { + result[key] = newer[key]; + } + }); + return result; + }; + // Extend the Chart prototype for dynamic methods + extend(Chart.prototype, /** @lends Highcharts.Chart.prototype */ { + /** + * Add a series to the chart after render time. Note that this method should + * never be used when adding data synchronously at chart render time, as it + * adds expense to the calculations and rendering. When adding data at the + * same time as the chart is initialized, add the series as a configuration + * option instead. With multiple axes, the `offset` is dynamically adjusted. + * + * @sample highcharts/members/chart-addseries/ + * Add a series from a button + * @sample stock/members/chart-addseries/ + * Add a series in Highstock + * + * @function Highcharts.Chart#addSeries + * + * @param {Highcharts.SeriesOptionsType} options + * The config options for the series. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after adding. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * Whether to apply animation, and optionally animation + * configuration. + * + * @return {Highcharts.Series} + * The newly created series object. + * + * @fires Highcharts.Chart#event:addSeries + * @fires Highcharts.Chart#event:afterAddSeries + */ + addSeries: function (options, redraw, animation) { + var series, chart = this; + if (options) { // <- not necessary + redraw = pick(redraw, true); // defaults to true + fireEvent(chart, 'addSeries', { options: options }, function () { + series = chart.initSeries(options); + chart.isDirtyLegend = true; + chart.linkSeries(); + if (series.enabledDataSorting) { + // We need to call `setData` after `linkSeries` + series.setData(options.data, false); + } + fireEvent(chart, 'afterAddSeries', { series: series }); + if (redraw) { + chart.redraw(animation); + } + }); + } + return series; + }, + /** + * Add an axis to the chart after render time. Note that this method should + * never be used when adding data synchronously at chart render time, as it + * adds expense to the calculations and rendering. When adding data at the + * same time as the chart is initialized, add the axis as a configuration + * option instead. + * + * @sample highcharts/members/chart-addaxis/ + * Add and remove axes + * + * @function Highcharts.Chart#addAxis + * + * @param {Highcharts.AxisOptions} options + * The axis options. + * + * @param {boolean} [isX=false] + * Whether it is an X axis or a value axis. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after adding. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=true] + * Whether and how to apply animation in the redraw. + * + * @return {Highcharts.Axis} + * The newly generated Axis object. + */ + addAxis: function (options, isX, redraw, animation) { + return this.createAxis(isX ? 'xAxis' : 'yAxis', { axis: options, redraw: redraw, animation: animation }); + }, + /** + * Add a color axis to the chart after render time. Note that this method + * should never be used when adding data synchronously at chart render time, + * as it adds expense to the calculations and rendering. When adding data at + * the same time as the chart is initialized, add the axis as a + * configuration option instead. + * + * @sample highcharts/members/chart-addaxis/ + * Add and remove axes + * + * @function Highcharts.Chart#addColorAxis + * + * @param {Highcharts.ColorAxisOptions} options + * The axis options. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after adding. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=true] + * Whether and how to apply animation in the redraw. + * + * @return {Highcharts.ColorAxis} + * The newly generated Axis object. + */ + addColorAxis: function (options, redraw, animation) { + return this.createAxis('colorAxis', { axis: options, redraw: redraw, animation: animation }); + }, + /** + * Factory for creating different axis types. + * + * @private + * @function Highcharts.Chart#createAxis + * + * @param {string} type + * An axis type. + * + * @param {...Array<*>} arguments + * All arguments for the constructor. + * + * @return {Highcharts.Axis | Highcharts.ColorAxis} + * The newly generated Axis object. + */ + createAxis: function (type, options) { + var chartOptions = this.options, isColorAxis = type === 'colorAxis', axisOptions = options.axis, redraw = options.redraw, animation = options.animation, userOptions = merge(axisOptions, { + index: this[type].length, + isX: type === 'xAxis' + }), axis; + if (isColorAxis) { + axis = new H.ColorAxis(this, userOptions); + } + else { + axis = new Axis(this, userOptions); + } + // Push the new axis options to the chart options + chartOptions[type] = splat(chartOptions[type] || {}); + chartOptions[type].push(userOptions); + if (isColorAxis) { + this.isDirtyLegend = true; + // Clear before 'bindAxes' (#11924) + this.axes.forEach(function (axis) { + axis.series = []; + }); + this.series.forEach(function (series) { + series.bindAxes(); + series.isDirtyData = true; + }); + } + if (pick(redraw, true)) { + this.redraw(animation); + } + return axis; + }, + /** + * Dim the chart and show a loading text or symbol. Options for the loading + * screen are defined in {@link + * https://api.highcharts.com/highcharts/loading|the loading options}. + * + * @sample highcharts/members/chart-hideloading/ + * Show and hide loading from a button + * @sample highcharts/members/chart-showloading/ + * Apply different text labels + * @sample stock/members/chart-show-hide-loading/ + * Toggle loading in Highstock + * + * @function Highcharts.Chart#showLoading + * + * @param {string} [str] + * An optional text to show in the loading label instead of the + * default one. The default text is set in + * [lang.loading](https://api.highcharts.com/highcharts/lang.loading). + * + * @return {void} + */ + showLoading: function (str) { + var chart = this, options = chart.options, loadingDiv = chart.loadingDiv, loadingOptions = options.loading, setLoadingSize = function () { + if (loadingDiv) { + css(loadingDiv, { + left: chart.plotLeft + 'px', + top: chart.plotTop + 'px', + width: chart.plotWidth + 'px', + height: chart.plotHeight + 'px' + }); + } + }; + // create the layer at the first call + if (!loadingDiv) { + chart.loadingDiv = loadingDiv = createElement('div', { + className: 'highcharts-loading highcharts-loading-hidden' + }, null, chart.container); + chart.loadingSpan = createElement('span', { className: 'highcharts-loading-inner' }, null, loadingDiv); + addEvent(chart, 'redraw', setLoadingSize); // #1080 + } + loadingDiv.className = 'highcharts-loading'; + // Update text + chart.loadingSpan.innerHTML = + pick(str, options.lang.loading, ''); + if (!chart.styledMode) { + // Update visuals + css(loadingDiv, extend(loadingOptions.style, { + zIndex: 10 + })); + css(chart.loadingSpan, loadingOptions.labelStyle); + // Show it + if (!chart.loadingShown) { + css(loadingDiv, { + opacity: 0, + display: '' + }); + animate(loadingDiv, { + opacity: loadingOptions.style.opacity || 0.5 + }, { + duration: loadingOptions.showDuration || 0 + }); + } + } + chart.loadingShown = true; + setLoadingSize(); + }, + /** + * Hide the loading layer. + * + * @see Highcharts.Chart#showLoading + * + * @sample highcharts/members/chart-hideloading/ + * Show and hide loading from a button + * @sample stock/members/chart-show-hide-loading/ + * Toggle loading in Highstock + * + * @function Highcharts.Chart#hideLoading + * + * @return {void} + */ + hideLoading: function () { + var options = this.options, loadingDiv = this.loadingDiv; + if (loadingDiv) { + loadingDiv.className = + 'highcharts-loading highcharts-loading-hidden'; + if (!this.styledMode) { + animate(loadingDiv, { + opacity: 0 + }, { + duration: options.loading.hideDuration || 100, + complete: function () { + css(loadingDiv, { display: 'none' }); + } + }); + } + } + this.loadingShown = false; + }, + /** + * These properties cause isDirtyBox to be set to true when updating. Can be + * extended from plugins. + */ + propsRequireDirtyBox: [ + 'backgroundColor', + 'borderColor', + 'borderWidth', + 'borderRadius', + 'plotBackgroundColor', + 'plotBackgroundImage', + 'plotBorderColor', + 'plotBorderWidth', + 'plotShadow', + 'shadow' + ], + /** + * These properties require a full reflow of chart elements, best + * implemented through running `Chart.setSize` internally (#8190). + * @type {Array} + */ + propsRequireReflow: [ + 'margin', + 'marginTop', + 'marginRight', + 'marginBottom', + 'marginLeft', + 'spacing', + 'spacingTop', + 'spacingRight', + 'spacingBottom', + 'spacingLeft' + ], + /** + * These properties cause all series to be updated when updating. Can be + * extended from plugins. + */ + propsRequireUpdateSeries: [ + 'chart.inverted', + 'chart.polar', + 'chart.ignoreHiddenSeries', + 'chart.type', + 'colors', + 'plotOptions', + 'time', + 'tooltip' + ], + /** + * These collections (arrays) implement update() methods with support for + * one-to-one option. + */ + collectionsWithUpdate: [ + 'xAxis', + 'yAxis', + 'zAxis', + 'series' + ], + /** + * A generic function to update any element of the chart. Elements can be + * enabled and disabled, moved, re-styled, re-formatted etc. + * + * A special case is configuration objects that take arrays, for example + * [xAxis](https://api.highcharts.com/highcharts/xAxis), + * [yAxis](https://api.highcharts.com/highcharts/yAxis) or + * [series](https://api.highcharts.com/highcharts/series). For these + * collections, an `id` option is used to map the new option set to an + * existing object. If an existing object of the same id is not found, the + * corresponding item is updated. So for example, running `chart.update` + * with a series item without an id, will cause the existing chart's series + * with the same index in the series array to be updated. When the + * `oneToOne` parameter is true, `chart.update` will also take care of + * adding and removing items from the collection. Read more under the + * parameter description below. + * + * Note that when changing series data, `chart.update` may mutate the passed + * data options. + * + * See also the + * [responsive option set](https://api.highcharts.com/highcharts/responsive). + * Switching between `responsive.rules` basically runs `chart.update` under + * the hood. + * + * @sample highcharts/members/chart-update/ + * Update chart geometry + * + * @function Highcharts.Chart#update + * + * @param {Highcharts.Options} options + * A configuration object for the new chart options. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart. + * + * @param {boolean} [oneToOne=false] + * When `true`, the `series`, `xAxis`, `yAxis` and `annotations` + * collections will be updated one to one, and items will be either + * added or removed to match the new updated options. For example, + * if the chart has two series and we call `chart.update` with a + * configuration containing three series, one will be added. If we + * call `chart.update` with one series, one will be removed. Setting + * an empty `series` array will remove all series, but leaving out + * the`series` property will leave all series untouched. If the + * series have id's, the new series options will be matched by id, + * and the remaining ones removed. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=true] + * Whether to apply animation, and optionally animation + * configuration. + * + * @return {void} + * + * @fires Highcharts.Chart#event:update + * @fires Highcharts.Chart#event:afterUpdate + */ + update: function (options, redraw, oneToOne, animation) { + var chart = this, adders = { + credits: 'addCredits', + title: 'setTitle', + subtitle: 'setSubtitle', + caption: 'setCaption' + }, optionsChart, updateAllAxes, updateAllSeries, newWidth, newHeight, runSetSize, isResponsiveOptions = options.isResponsiveOptions, itemsForRemoval = []; + fireEvent(chart, 'update', { options: options }); + // If there are responsive rules in action, undo the responsive rules + // before we apply the updated options and replay the responsive rules + // on top from the chart.redraw function (#9617). + if (!isResponsiveOptions) { + chart.setResponsive(false, true); + } + options = H.cleanRecursively(options, chart.options); + merge(true, chart.userOptions, options); + // If the top-level chart option is present, some special updates are + // required + optionsChart = options.chart; + if (optionsChart) { + merge(true, chart.options.chart, optionsChart); + // Setter function + if ('className' in optionsChart) { + chart.setClassName(optionsChart.className); + } + if ('reflow' in optionsChart) { + chart.setReflow(optionsChart.reflow); + } + if ('inverted' in optionsChart || + 'polar' in optionsChart || + 'type' in optionsChart) { + // Parse options.chart.inverted and options.chart.polar together + // with the available series. + chart.propFromSeries(); + updateAllAxes = true; + } + if ('alignTicks' in optionsChart) { // #6452 + updateAllAxes = true; + } + objectEach(optionsChart, function (val, key) { + if (chart.propsRequireUpdateSeries.indexOf('chart.' + key) !== + -1) { + updateAllSeries = true; + } + // Only dirty box + if (chart.propsRequireDirtyBox.indexOf(key) !== -1) { + chart.isDirtyBox = true; + } + // Chart setSize + if (!isResponsiveOptions && + chart.propsRequireReflow.indexOf(key) !== -1) { + runSetSize = true; + } + }); + if (!chart.styledMode && 'style' in optionsChart) { + chart.renderer.setStyle(optionsChart.style); + } + } + // Moved up, because tooltip needs updated plotOptions (#6218) + if (!chart.styledMode && options.colors) { + this.options.colors = options.colors; + } + if (options.plotOptions) { + merge(true, this.options.plotOptions, options.plotOptions); + } + // Maintaining legacy global time. If the chart is instanciated first + // with global time, then updated with time options, we need to create a + // new Time instance to avoid mutating the global time (#10536). + if (options.time && this.time === H.time) { + this.time = new Time(options.time); + } + // Some option stuctures correspond one-to-one to chart objects that + // have update methods, for example + // options.credits => chart.credits + // options.legend => chart.legend + // options.title => chart.title + // options.tooltip => chart.tooltip + // options.subtitle => chart.subtitle + // options.mapNavigation => chart.mapNavigation + // options.navigator => chart.navigator + // options.scrollbar => chart.scrollbar + objectEach(options, function (val, key) { + if (chart[key] && + typeof chart[key].update === 'function') { + chart[key].update(val, false); + // If a one-to-one object does not exist, look for an adder function + } + else if (typeof chart[adders[key]] === 'function') { + chart[adders[key]](val); + } + if (key !== 'chart' && + chart.propsRequireUpdateSeries.indexOf(key) !== -1) { + updateAllSeries = true; + } + }); + // Setters for collections. For axes and series, each item is referred + // by an id. If the id is not found, it defaults to the corresponding + // item in the collection, so setting one series without an id, will + // update the first series in the chart. Setting two series without + // an id will update the first and the second respectively (#6019) + // chart.update and responsive. + this.collectionsWithUpdate.forEach(function (coll) { + var indexMap; + if (options[coll]) { + // In stock charts, the navigator series are also part of the + // chart.series array, but those series should not be handled + // here (#8196). + if (coll === 'series') { + indexMap = []; + chart[coll].forEach(function (s, i) { + if (!s.options.isInternal) { + indexMap.push(pick(s.options.index, i)); + } + }); + } + splat(options[coll]).forEach(function (newOptions, i) { + var item = (defined(newOptions.id) && + chart.get(newOptions.id)) || chart[coll][indexMap ? indexMap[i] : i]; + if (item && item.coll === coll) { + item.update(newOptions, false); + if (oneToOne) { + item.touched = true; + } + } + // If oneToOne and no matching item is found, add one + if (!item && oneToOne && chart.collectionsWithInit[coll]) { + chart.collectionsWithInit[coll][0].apply(chart, + // [newOptions, ...extraArguments, redraw=false] + [ + newOptions + ].concat( + // Not all initializers require extra args + chart.collectionsWithInit[coll][1] || []).concat([ + false + ])).touched = true; + } + }); + // Add items for removal + if (oneToOne) { + chart[coll].forEach(function (item) { + if (!item.touched && !item.options.isInternal) { + itemsForRemoval.push(item); + } + else { + delete item.touched; + } + }); + } + } + }); + itemsForRemoval.forEach(function (item) { + if (item.remove) { + item.remove(false); + } + }); + if (updateAllAxes) { + chart.axes.forEach(function (axis) { + axis.update({}, false); + }); + } + // Certain options require the whole series structure to be thrown away + // and rebuilt + if (updateAllSeries) { + chart.getSeriesOrderByLinks().forEach(function (series) { + // Avoid removed navigator series + if (series.chart) { + series.update({}, false); + } + }, this); + } + // For loading, just update the options, do not redraw + if (options.loading) { + merge(true, chart.options.loading, options.loading); + } + // Update size. Redraw is forced. + newWidth = optionsChart && optionsChart.width; + newHeight = optionsChart && optionsChart.height; + if (isString(newHeight)) { + newHeight = relativeLength(newHeight, newWidth || chart.chartWidth); + } + if ( + // In this case, run chart.setSize with newWidth and newHeight which + // are undefined, only for reflowing chart elements because margin + // or spacing has been set (#8190) + runSetSize || + // In this case, the size is actually set + (isNumber(newWidth) && newWidth !== chart.chartWidth) || + (isNumber(newHeight) && newHeight !== chart.chartHeight)) { + chart.setSize(newWidth, newHeight, animation); + } + else if (pick(redraw, true)) { + chart.redraw(animation); + } + fireEvent(chart, 'afterUpdate', { + options: options, + redraw: redraw, + animation: animation + }); + }, + /** + * Shortcut to set the subtitle options. This can also be done from {@link + * Chart#update} or {@link Chart#setTitle}. + * + * @function Highcharts.Chart#setSubtitle + * + * @param {Highcharts.SubtitleOptions} options + * New subtitle options. The subtitle text itself is set by the + * `options.text` property. + * + * @return {void} + */ + setSubtitle: function (options, redraw) { + this.applyDescription('subtitle', options); + this.layOutTitles(redraw); + }, + /** + * Set the caption options. This can also be done from {@link + * Chart#update}. + * + * @function Highcharts.Chart#setCaption + * + * @param {Highcharts.CaptionOptions} options + * New caption options. The caption text itself is set by the + * `options.text` property. + * + * @return {void} + */ + setCaption: function (options, redraw) { + this.applyDescription('caption', options); + this.layOutTitles(redraw); + } + }); + /** + * These collections (arrays) implement `Chart.addSomethig` method used in + * chart.update() to create new object in the collection. Equivalent for + * deleting is resolved by simple `Somethig.remove()`. + * + * Note: We need to define these references after initializers are bound to + * chart's prototype. + */ + Chart.prototype.collectionsWithInit = { + // collectionName: [ initializingMethod, [extraArguments] ] + xAxis: [Chart.prototype.addAxis, [true]], + yAxis: [Chart.prototype.addAxis, [false]], + series: [Chart.prototype.addSeries] + }; + // extend the Point prototype for dynamic methods + extend(Point.prototype, /** @lends Highcharts.Point.prototype */ { + /** + * Update point with new options (typically x/y data) and optionally redraw + * the series. + * + * @sample highcharts/members/point-update-column/ + * Update column value + * @sample highcharts/members/point-update-pie/ + * Update pie slice + * @sample maps/members/point-update/ + * Update map area value in Highmaps + * + * @function Highcharts.Point#update + * + * @param {Highcharts.PointOptionsType} options + * The point options. Point options are handled as described under + * the `series.type.data` item for each series type. For example + * for a line series, if options is a single number, the point will + * be given that number as the marin y value. If it is an array, it + * will be interpreted as x and y values respectively. If it is an + * object, advanced options are applied. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the point is updated. If doing + * more operations on the chart, it is best practice to set + * `redraw` to false and call `chart.redraw()` after. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=true] + * Whether to apply animation, and optionally animation + * configuration. + * + * @return {void} + * + * @fires Highcharts.Point#event:update + */ + update: function (options, redraw, animation, runEvent) { + var point = this, series = point.series, graphic = point.graphic, i, chart = series.chart, seriesOptions = series.options; + redraw = pick(redraw, true); + /** + * @private + */ + function update() { + point.applyOptions(options); + // Update visuals, #4146 + // Handle dummy graphic elements for a11y, #12718 + var hasDummyGraphic = graphic && point.hasDummyGraphic; + var shouldDestroyGraphic = point.y === null ? !hasDummyGraphic : hasDummyGraphic; + if (graphic && shouldDestroyGraphic) { + point.graphic = graphic.destroy(); + delete point.hasDummyGraphic; + } + if (isObject(options, true)) { + // Destroy so we can get new elements + if (graphic && graphic.element) { + // "null" is also a valid symbol + if (options && + options.marker && + typeof options.marker.symbol !== 'undefined') { + point.graphic = graphic.destroy(); + } + } + if (options && options.dataLabels && point.dataLabel) { + point.dataLabel = point.dataLabel.destroy(); // #2468 + } + if (point.connector) { + point.connector = point.connector.destroy(); // #7243 + } + } + // record changes in the parallel arrays + i = point.index; + series.updateParallelArrays(point, i); + // Record the options to options.data. If the old or the new config + // is an object, use point options, otherwise use raw options + // (#4701, #4916). + seriesOptions.data[i] = (isObject(seriesOptions.data[i], true) || + isObject(options, true)) ? + point.options : + pick(options, seriesOptions.data[i]); + // redraw + series.isDirty = series.isDirtyData = true; + if (!series.fixedBox && series.hasCartesianSeries) { // #1906, #2320 + chart.isDirtyBox = true; + } + if (seriesOptions.legendType === 'point') { // #1831, #1885 + chart.isDirtyLegend = true; + } + if (redraw) { + chart.redraw(animation); + } + } + // Fire the event with a default handler of doing the update + if (runEvent === false) { // When called from setData + update(); + } + else { + point.firePointEvent('update', { options: options }, update); + } + }, + /** + * Remove a point and optionally redraw the series and if necessary the axes + * + * @sample highcharts/plotoptions/series-point-events-remove/ + * Remove point and confirm + * @sample highcharts/members/point-remove/ + * Remove pie slice + * @sample maps/members/point-remove/ + * Remove selected points in Highmaps + * + * @function Highcharts.Point#remove + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call. When + * doing more operations on the chart, for example running + * `point.remove()` in a loop, it is best practice to set `redraw` + * to false and call `chart.redraw()` after. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=false] + * Whether to apply animation, and optionally animation + * configuration. + * + * @return {void} + */ + remove: function (redraw, animation) { + this.series.removePoint(this.series.data.indexOf(this), redraw, animation); + } + }); + // Extend the series prototype for dynamic methods + extend(Series.prototype, /** @lends Series.prototype */ { + /** + * Add a point to the series after render time. The point can be added at + * the end, or by giving it an X value, to the start or in the middle of the + * series. + * + * @sample highcharts/members/series-addpoint-append/ + * Append point + * @sample highcharts/members/series-addpoint-append-and-shift/ + * Append and shift + * @sample highcharts/members/series-addpoint-x-and-y/ + * Both X and Y values given + * @sample highcharts/members/series-addpoint-pie/ + * Append pie slice + * @sample stock/members/series-addpoint/ + * Append 100 points in Highstock + * @sample stock/members/series-addpoint-shift/ + * Append and shift in Highstock + * @sample maps/members/series-addpoint/ + * Add a point in Highmaps + * + * @function Highcharts.Series#addPoint + * + * @param {Highcharts.PointOptionsType} options + * The point options. If options is a single number, a point with + * that y value is appended to the series. If it is an array, it will + * be interpreted as x and y values respectively. If it is an + * object, advanced options as outlined under `series.data` are + * applied. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the point is added. When adding + * more than one point, it is highly recommended that the redraw + * option be set to false, and instead {@link Chart#redraw} is + * explicitly called after the adding of points is finished. + * Otherwise, the chart will redraw after adding each point. + * + * @param {boolean} [shift=false] + * If true, a point is shifted off the start of the series as one is + * appended to the end. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * Whether to apply animation, and optionally animation + * configuration. + * + * @param {boolean} [withEvent=true] + * Used internally, whether to fire the series `addPoint` event. + * + * @return {void} + * + * @fires Highcharts.Series#event:addPoint + */ + addPoint: function (options, redraw, shift, animation, withEvent) { + var series = this, seriesOptions = series.options, data = series.data, chart = series.chart, xAxis = series.xAxis, names = xAxis && xAxis.hasNames && xAxis.names, dataOptions = seriesOptions.data, point, xData = series.xData, isInTheMiddle, i, x; + // Optional redraw, defaults to true + redraw = pick(redraw, true); + // Get options and push the point to xData, yData and series.options. In + // series.generatePoints the Point instance will be created on demand + // and pushed to the series.data array. + point = { series: series }; + series.pointClass.prototype.applyOptions.apply(point, [options]); + x = point.x; + // Get the insertion point + i = xData.length; + if (series.requireSorting && x < xData[i - 1]) { + isInTheMiddle = true; + while (i && xData[i - 1] > x) { + i--; + } + } + // Insert undefined item + series.updateParallelArrays(point, 'splice', i, 0, 0); + // Update it + series.updateParallelArrays(point, i); + if (names && point.name) { + names[x] = point.name; + } + dataOptions.splice(i, 0, options); + if (isInTheMiddle) { + series.data.splice(i, 0, null); + series.processData(); + } + // Generate points to be added to the legend (#1329) + if (seriesOptions.legendType === 'point') { + series.generatePoints(); + } + // Shift the first point off the parallel arrays + if (shift) { + if (data[0] && data[0].remove) { + data[0].remove(false); + } + else { + data.shift(); + series.updateParallelArrays(point, 'shift'); + dataOptions.shift(); + } + } + // Fire event + if (withEvent !== false) { + fireEvent(series, 'addPoint', { point: point }); + } + // redraw + series.isDirty = true; + series.isDirtyData = true; + if (redraw) { + chart.redraw(animation); // Animation is set anyway on redraw, #5665 + } + }, + /** + * Remove a point from the series. Unlike the + * {@link Highcharts.Point#remove} method, this can also be done on a point + * that is not instanciated because it is outside the view or subject to + * Highstock data grouping. + * + * @sample highcharts/members/series-removepoint/ + * Remove cropped point + * + * @function Highcharts.Series#removePoint + * + * @param {number} i + * The index of the point in the {@link Highcharts.Series.data|data} + * array. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the point is added. When + * removing more than one point, it is highly recommended that the + * `redraw` option be set to `false`, and instead {@link + * Highcharts.Chart#redraw} is explicitly called after the adding of + * points is finished. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * Whether and optionally how the series should be animated. + * + * @return {void} + * + * @fires Highcharts.Point#event:remove + */ + removePoint: function (i, redraw, animation) { + var series = this, data = series.data, point = data[i], points = series.points, chart = series.chart, remove = function () { + if (points && points.length === data.length) { // #4935 + points.splice(i, 1); + } + data.splice(i, 1); + series.options.data.splice(i, 1); + series.updateParallelArrays(point || { series: series }, 'splice', i, 1); + if (point) { + point.destroy(); + } + // redraw + series.isDirty = true; + series.isDirtyData = true; + if (redraw) { + chart.redraw(); + } + }; + setAnimation(animation, chart); + redraw = pick(redraw, true); + // Fire the event with a default handler of removing the point + if (point) { + point.firePointEvent('remove', null, remove); + } + else { + remove(); + } + }, + /** + * Remove a series and optionally redraw the chart. + * + * @sample highcharts/members/series-remove/ + * Remove first series from a button + * + * @function Highcharts.Series#remove + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call to + * {@link Highcharts.Chart#redraw}. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * Whether to apply animation, and optionally animation + * configuration. + * + * @param {boolean} [withEvent=true] + * Used internally, whether to fire the series `remove` event. + * + * @return {void} + * + * @fires Highcharts.Series#event:remove + */ + remove: function (redraw, animation, withEvent, keepEvents) { + var series = this, chart = series.chart; + /** + * @private + */ + function remove() { + // Destroy elements + series.destroy(keepEvents); + series.remove = null; // Prevent from doing again (#9097) + // Redraw + chart.isDirtyLegend = chart.isDirtyBox = true; + chart.linkSeries(); + if (pick(redraw, true)) { + chart.redraw(animation); + } + } + // Fire the event with a default handler of removing the point + if (withEvent !== false) { + fireEvent(series, 'remove', null, remove); + } + else { + remove(); + } + }, + /** + * Update the series with a new set of options. For a clean and precise + * handling of new options, all methods and elements from the series are + * removed, and it is initialized from scratch. Therefore, this method is + * more performance expensive than some other utility methods like {@link + * Series#setData} or {@link Series#setVisible}. + * + * Note that `Series.update` may mutate the passed `data` options. + * + * @sample highcharts/members/series-update/ + * Updating series options + * @sample maps/members/series-update/ + * Update series options in Highmaps + * + * @function Highcharts.Series#update + * + * @param {Highcharts.SeriesOptionsType} options + * New options that will be merged with the series' existing options. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the series is altered. If doing + * more operations on the chart, it is a good idea to set redraw to + * false and call {@link Chart#redraw} after. + * + * @return {void} + * + * @fires Highcharts.Series#event:update + * @fires Highcharts.Series#event:afterUpdate + */ + update: function (options, redraw) { + options = H.cleanRecursively(options, this.userOptions); + fireEvent(this, 'update', { options: options }); + var series = this, chart = series.chart, + // must use user options when changing type because series.options + // is merged in with type specific plotOptions + oldOptions = series.userOptions, seriesOptions, initialType = series.initialType || series.type, newType = (options.type || + oldOptions.type || + chart.options.chart.type), keepPoints = !( + // Indicators, histograms etc recalculate the data. It should be + // possible to omit this. + this.hasDerivedData || + // Changes to data grouping requires new points in new groups + options.dataGrouping || + // New type requires new point classes + (newType && newType !== this.type) || + // New options affecting how the data points are built + typeof options.pointStart !== 'undefined' || + options.pointInterval || + options.pointIntervalUnit || + options.keys), initialSeriesProto = seriesTypes[initialType].prototype, n, groups = [ + 'group', + 'markerGroup', + 'dataLabelsGroup', + 'transformGroup' + ], preserve = [ + 'eventOptions', + 'navigatorSeries', + 'baseSeries' + ], + // Animation must be enabled when calling update before the initial + // animation has first run. This happens when calling update + // directly after chart initialization, or when applying responsive + // rules (#6912). + animation = series.finishedAnimating && { animation: false }, kinds = {}; + if (keepPoints) { + preserve.push('data', 'isDirtyData', 'points', 'processedXData', 'processedYData', 'xIncrement', '_hasPointMarkers', '_hasPointLabels', + // Map specific, consider moving it to series-specific preserve- + // properties (#10617) + 'mapMap', 'mapData', 'minY', 'maxY', 'minX', 'maxX'); + if (options.visible !== false) { + preserve.push('area', 'graph'); + } + series.parallelArrays.forEach(function (key) { + preserve.push(key + 'Data'); + }); + if (options.data) { + // setData uses dataSorting options so we need to update them + // earlier + if (options.dataSorting) { + extend(series.options.dataSorting, options.dataSorting); + } + this.setData(options.data, false); + } + } + // Do the merge, with some forced options + options = merge(oldOptions, animation, { + // When oldOptions.index is null it should't be cleared. + // Otherwise navigator series will have wrong indexes (#10193). + index: typeof oldOptions.index === 'undefined' ? + series.index : oldOptions.index, + pointStart: pick( + // when updating from blank (#7933) + oldOptions.pointStart, + // when updating after addPoint + series.xData[0]) + }, (!keepPoints && { data: series.options.data }), options); + // Merge does not merge arrays, but replaces them. Since points were + // updated, `series.options.data` has correct merged options, use it: + if (keepPoints && options.data) { + options.data = series.options.data; + } + // Make sure preserved properties are not destroyed (#3094) + preserve = groups.concat(preserve); + preserve.forEach(function (prop) { + preserve[prop] = series[prop]; + delete series[prop]; + }); + // Destroy the series and delete all properties. Reinsert all + // methods and properties from the new type prototype (#2270, + // #3719). + series.remove(false, null, false, true); + for (n in initialSeriesProto) { // eslint-disable-line guard-for-in + series[n] = void 0; + } + if (seriesTypes[newType || initialType]) { + extend(series, seriesTypes[newType || initialType].prototype); + } + else { + error(17, true, chart, { missingModuleFor: (newType || initialType) }); + } + // Re-register groups (#3094) and other preserved properties + preserve.forEach(function (prop) { + series[prop] = preserve[prop]; + }); + series.init(chart, options); + // Remove particular elements of the points. Check `series.options` + // because we need to consider the options being set on plotOptions as + // well. + if (keepPoints && this.points) { + seriesOptions = series.options; + // What kind of elements to destroy + if (seriesOptions.visible === false) { + kinds.graphic = 1; + kinds.dataLabel = 1; + } + else if (!series._hasPointLabels) { + var marker = seriesOptions.marker, dataLabels = seriesOptions.dataLabels; + if (marker && (marker.enabled === false || + 'symbol' in marker // #10870 + )) { + kinds.graphic = 1; + } + if (dataLabels && + dataLabels.enabled === false) { + kinds.dataLabel = 1; + } + } + this.points.forEach(function (point) { + if (point && point.series) { + point.resolveColor(); + // Destroy elements in order to recreate based on updated + // series options. + if (Object.keys(kinds).length) { + point.destroyElements(kinds); + } + if (seriesOptions.showInLegend === false && + point.legendItem) { + chart.legend.destroyItem(point); + } + } + }, this); + } + // Update the Z index of groups (#3380, #7397) + if (options.zIndex !== oldOptions.zIndex) { + groups.forEach(function (groupName) { + if (series[groupName]) { + series[groupName].attr({ + zIndex: options.zIndex + }); + } + }); + } + series.initialType = initialType; + chart.linkSeries(); // Links are lost in series.remove (#3028) + fireEvent(this, 'afterUpdate'); + if (pick(redraw, true)) { + chart.redraw(keepPoints ? void 0 : false); + } + }, + /** + * Used from within series.update + * + * @private + * @function Highcharts.Series#setName + * + * @param {string} name + * + * @return {void} + */ + setName: function (name) { + this.name = this.options.name = this.userOptions.name = name; + this.chart.isDirtyLegend = true; + } + }); + // Extend the Axis.prototype for dynamic methods + extend(Axis.prototype, /** @lends Highcharts.Axis.prototype */ { + /** + * Update an axis object with a new set of options. The options are merged + * with the existing options, so only new or altered options need to be + * specified. + * + * @sample highcharts/members/axis-update/ + * Axis update demo + * + * @function Highcharts.Axis#update + * + * @param {Highcharts.AxisOptions} options + * The new options that will be merged in with existing options on + * the axis. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the axis is altered. If doing + * more operations on the chart, it is a good idea to set redraw to + * false and call {@link Chart#redraw} after. + * + * @return {void} + */ + update: function (options, redraw) { + var chart = this.chart, newEvents = ((options && options.events) || {}); + options = merge(this.userOptions, options); + // Color Axis is not an array, + // This change is applied in the ColorAxis wrapper + if (chart.options[this.coll].indexOf) { + // Don't use this.options.index, + // StockChart has Axes in navigator too + chart.options[this.coll][chart.options[this.coll].indexOf(this.userOptions)] = options; + } + // Remove old events, if no new exist (#8161) + objectEach(chart.options[this.coll].events, function (fn, ev) { + if (typeof newEvents[ev] === 'undefined') { + newEvents[ev] = void 0; + } + }); + this.destroy(true); + this.init(chart, extend(options, { events: newEvents })); + chart.isDirtyBox = true; + if (pick(redraw, true)) { + chart.redraw(); + } + }, + /** + * Remove the axis from the chart. + * + * @sample highcharts/members/chart-addaxis/ + * Add and remove axes + * + * @function Highcharts.Axis#remove + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart following the remove. + * + * @return {void} + */ + remove: function (redraw) { + var chart = this.chart, key = this.coll, // xAxis or yAxis + axisSeries = this.series, i = axisSeries.length; + // Remove associated series (#2687) + while (i--) { + if (axisSeries[i]) { + axisSeries[i].remove(false); + } + } + // Remove the axis + erase(chart.axes, this); + erase(chart[key], this); + if (isArray(chart.options[key])) { + chart.options[key].splice(this.options.index, 1); + } + else { // color axis, #6488 + delete chart.options[key]; + } + chart[key].forEach(function (axis, i) { + // Re-index, #1706, #8075 + axis.options.index = axis.userOptions.index = i; + }); + this.destroy(); + chart.isDirtyBox = true; + if (pick(redraw, true)) { + chart.redraw(); + } + }, + /** + * Update the axis title by options after render time. + * + * @sample highcharts/members/axis-settitle/ + * Set a new Y axis title + * + * @function Highcharts.Axis#setTitle + * + * @param {Highcharts.AxisTitleOptions} titleOptions + * The additional title options. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after setting the title. + * + * @return {void} + */ + setTitle: function (titleOptions, redraw) { + this.update({ title: titleOptions }, redraw); + }, + /** + * Set new axis categories and optionally redraw. + * + * @sample highcharts/members/axis-setcategories/ + * Set categories by click on a button + * + * @function Highcharts.Axis#setCategories + * + * @param {Array} categories + * The new categories. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart. + * + * @return {void} + */ + setCategories: function (categories, redraw) { + this.update({ categories: categories }, redraw); + } + }); + + }); + _registerModule(_modules, 'parts/AreaSeries.js', [_modules['parts/Globals.js'], _modules['parts/Color.js'], _modules['mixins/legend-symbol.js'], _modules['parts/Utilities.js']], function (H, Color, LegendSymbolMixin, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var color = Color.parse; + var objectEach = U.objectEach, pick = U.pick, seriesType = U.seriesType; + var Series = H.Series; + /** + * Area series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.area + * + * @augments Highcharts.Series + */ + seriesType('area', 'line', + /** + * The area series type. + * + * @sample {highcharts} highcharts/demo/area-basic/ + * Area chart + * @sample {highstock} stock/demo/area/ + * Area chart + * + * @extends plotOptions.line + * @excluding useOhlcData + * @product highcharts highstock + * @optionparent plotOptions.area + */ + { + /** + * Fill color or gradient for the area. When `null`, the series' `color` + * is used with the series' `fillOpacity`. + * + * In styled mode, the fill color can be set with the `.highcharts-area` + * class name. + * + * @sample {highcharts} highcharts/plotoptions/area-fillcolor-default/ + * Null by default + * @sample {highcharts} highcharts/plotoptions/area-fillcolor-gradient/ + * Gradient + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock + * @apioption plotOptions.area.fillColor + */ + /** + * Fill opacity for the area. When you set an explicit `fillColor`, + * the `fillOpacity` is not applied. Instead, you should define the + * opacity in the `fillColor` with an rgba color definition. The + * `fillOpacity` setting, also the default setting, overrides the alpha + * component of the `color` setting. + * + * In styled mode, the fill opacity can be set with the + * `.highcharts-area` class name. + * + * @sample {highcharts} highcharts/plotoptions/area-fillopacity/ + * Automatic fill color and fill opacity of 0.1 + * + * @type {number} + * @default {highcharts} 0.75 + * @default {highstock} 0.75 + * @product highcharts highstock + * @apioption plotOptions.area.fillOpacity + */ + /** + * A separate color for the graph line. By default the line takes the + * `color` of the series, but the lineColor setting allows setting a + * separate color for the line without altering the `fillColor`. + * + * In styled mode, the line stroke can be set with the + * `.highcharts-graph` class name. + * + * @sample {highcharts} highcharts/plotoptions/area-linecolor/ + * Dark gray line + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock + * @apioption plotOptions.area.lineColor + */ + /** + * A separate color for the negative part of the area. + * + * In styled mode, a negative color is set with the + * `.highcharts-negative` class name. + * + * @see [negativeColor](#plotOptions.area.negativeColor) + * + * @sample {highcharts} highcharts/css/series-negative-color/ + * Negative color in styled mode + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 3.0 + * @product highcharts + * @apioption plotOptions.area.negativeFillColor + */ + /** + * Whether the whole area or just the line should respond to mouseover + * tooltips and other mouse or touch events. + * + * @sample {highcharts|highstock} highcharts/plotoptions/area-trackbyarea/ + * Display the tooltip when the area is hovered + * + * @type {boolean} + * @default false + * @since 1.1.6 + * @product highcharts highstock + * @apioption plotOptions.area.trackByArea + */ + /** + * When this is true, the series will not cause the Y axis to cross + * the zero plane (or [threshold](#plotOptions.series.threshold) option) + * unless the data actually crosses the plane. + * + * For example, if `softThreshold` is `false`, a series of 0, 1, 2, + * 3 will make the Y axis show negative values according to the + * `minPadding` option. If `softThreshold` is `true`, the Y axis starts + * at 0. + * + * @since 4.1.9 + * @product highcharts highstock + */ + softThreshold: false, + /** + * The Y axis value to serve as the base for the area, for + * distinguishing between values above and below a threshold. The area + * between the graph and the threshold is filled. + * + * * If a number is given, the Y axis will scale to the threshold. + * * If `null`, the scaling behaves like a line series with fill between + * the graph and the Y axis minimum. + * * If `Infinity` or `-Infinity`, the area between the graph and the + * corresponing Y axis extreme is filled (since v6.1.0). + * + * @sample {highcharts} highcharts/plotoptions/area-threshold/ + * A threshold of 100 + * @sample {highcharts} highcharts/plotoptions/area-threshold-infinity/ + * A threshold of Infinity + * + * @type {number|null} + * @since 2.0 + * @product highcharts highstock + */ + threshold: 0 + }, + /* eslint-disable valid-jsdoc */ + /** + * @lends seriesTypes.area.prototype + */ + { + singleStacks: false, + /** + * Return an array of stacked points, where null and missing points are + * replaced by dummy points in order for gaps to be drawn correctly in + * stacks. + * @private + */ + getStackPoints: function (points) { + var series = this, segment = [], keys = [], xAxis = this.xAxis, yAxis = this.yAxis, stack = yAxis.stacking.stacks[this.stackKey], pointMap = {}, seriesIndex = series.index, yAxisSeries = yAxis.series, seriesLength = yAxisSeries.length, visibleSeries, upOrDown = pick(yAxis.options.reversedStacks, true) ? 1 : -1, i; + points = points || this.points; + if (this.options.stacking) { + for (i = 0; i < points.length; i++) { + // Reset after point update (#7326) + points[i].leftNull = points[i].rightNull = void 0; + // Create a map where we can quickly look up the points by + // their X values. + pointMap[points[i].x] = points[i]; + } + // Sort the keys (#1651) + objectEach(stack, function (stackX, x) { + // nulled after switching between + // grouping and not (#1651, #2336) + if (stackX.total !== null) { + keys.push(x); + } + }); + keys.sort(function (a, b) { + return a - b; + }); + visibleSeries = yAxisSeries.map(function (s) { + return s.visible; + }); + keys.forEach(function (x, idx) { + var y = 0, stackPoint, stackedValues; + if (pointMap[x] && !pointMap[x].isNull) { + segment.push(pointMap[x]); + // Find left and right cliff. -1 goes left, 1 goes + // right. + [-1, 1].forEach(function (direction) { + var nullName = direction === 1 ? + 'rightNull' : + 'leftNull', cliffName = direction === 1 ? + 'rightCliff' : + 'leftCliff', cliff = 0, otherStack = stack[keys[idx + direction]]; + // If there is a stack next to this one, + // to the left or to the right... + if (otherStack) { + i = seriesIndex; + // Can go either up or down, + // depending on reversedStacks + while (i >= 0 && i < seriesLength) { + stackPoint = otherStack.points[i]; + if (!stackPoint) { + // If the next point in this series + // is missing, mark the point + // with point.leftNull or + // point.rightNull = true. + if (i === seriesIndex) { + pointMap[x][nullName] = + true; + // If there are missing points in + // the next stack in any of the + // series below this one, we need + // to substract the missing values + // and add a hiatus to the left or + // right. + } + else if (visibleSeries[i]) { + stackedValues = + stack[x].points[i]; + if (stackedValues) { + cliff -= + stackedValues[1] - + stackedValues[0]; + } + } + } + // When reversedStacks is true, loop up, + // else loop down + i += upOrDown; + } + } + pointMap[x][cliffName] = cliff; + }); + // There is no point for this X value in this series, so we + // insert a dummy point in order for the areas to be drawn + // correctly. + } + else { + // Loop down the stack to find the series below this + // one that has a value (#1991) + i = seriesIndex; + while (i >= 0 && i < seriesLength) { + stackPoint = stack[x].points[i]; + if (stackPoint) { + y = stackPoint[1]; + break; + } + // When reversedStacks is true, loop up, else loop + // down + i += upOrDown; + } + y = yAxis.translate(// #6272 + y, 0, 1, 0, 1); + segment.push({ + isNull: true, + plotX: xAxis.translate(// #6272 + x, 0, 0, 0, 1), + x: x, + plotY: y, + yBottom: y + }); + } + }); + } + return segment; + }, + /** + * @private + */ + getGraphPath: function (points) { + var getGraphPath = Series.prototype.getGraphPath, graphPath, options = this.options, stacking = options.stacking, yAxis = this.yAxis, topPath, bottomPath, bottomPoints = [], graphPoints = [], seriesIndex = this.index, i, areaPath, plotX, stacks = yAxis.stacking.stacks[this.stackKey], threshold = options.threshold, translatedThreshold = Math.round(// #10909 + yAxis.getThreshold(options.threshold)), isNull, yBottom, connectNulls = pick(// #10574 + options.connectNulls, stacking === 'percent'), + // To display null points in underlying stacked series, this + // series graph must be broken, and the area also fall down to + // fill the gap left by the null point. #2069 + addDummyPoints = function (i, otherI, side) { + var point = points[i], stackedValues = stacking && + stacks[point.x].points[seriesIndex], nullVal = point[side + 'Null'] || 0, cliffVal = point[side + 'Cliff'] || 0, top, bottom, isNull = true; + if (cliffVal || nullVal) { + top = (nullVal ? + stackedValues[0] : + stackedValues[1]) + cliffVal; + bottom = stackedValues[0] + cliffVal; + isNull = !!nullVal; + } + else if (!stacking && + points[otherI] && + points[otherI].isNull) { + top = bottom = threshold; + } + // Add to the top and bottom line of the area + if (typeof top !== 'undefined') { + graphPoints.push({ + plotX: plotX, + plotY: top === null ? + translatedThreshold : + yAxis.getThreshold(top), + isNull: isNull, + isCliff: true + }); + bottomPoints.push({ + plotX: plotX, + plotY: bottom === null ? + translatedThreshold : + yAxis.getThreshold(bottom), + doCurve: false // #1041, gaps in areaspline areas + }); + } + }; + // Find what points to use + points = points || this.points; + // Fill in missing points + if (stacking) { + points = this.getStackPoints(points); + } + for (i = 0; i < points.length; i++) { + // Reset after series.update of stacking property (#12033) + if (!stacking) { + points[i].leftCliff = points[i].rightCliff = + points[i].leftNull = points[i].rightNull = void 0; + } + isNull = points[i].isNull; + plotX = pick(points[i].rectPlotX, points[i].plotX); + yBottom = pick(points[i].yBottom, translatedThreshold); + if (!isNull || connectNulls) { + if (!connectNulls) { + addDummyPoints(i, i - 1, 'left'); + } + // Skip null point when stacking is false and connectNulls + // true + if (!(isNull && !stacking && connectNulls)) { + graphPoints.push(points[i]); + bottomPoints.push({ + x: i, + plotX: plotX, + plotY: yBottom + }); + } + if (!connectNulls) { + addDummyPoints(i, i + 1, 'right'); + } + } + } + topPath = getGraphPath.call(this, graphPoints, true, true); + bottomPoints.reversed = true; + bottomPath = getGraphPath.call(this, bottomPoints, true, true); + var firstBottomPoint = bottomPath[0]; + if (firstBottomPoint && firstBottomPoint[0] === 'M') { + bottomPath[0] = ['L', firstBottomPoint[1], firstBottomPoint[2]]; + } + areaPath = topPath.concat(bottomPath); + // TODO: don't set leftCliff and rightCliff when connectNulls? + graphPath = getGraphPath + .call(this, graphPoints, false, connectNulls); + areaPath.xMap = topPath.xMap; + this.areaPath = areaPath; + return graphPath; + }, + /** + * Draw the graph and the underlying area. This method calls the Series + * base function and adds the area. The areaPath is calculated in the + * getSegmentPath method called from Series.prototype.drawGraph. + * @private + */ + drawGraph: function () { + // Define or reset areaPath + this.areaPath = []; + // Call the base method + Series.prototype.drawGraph.apply(this); + // Define local variables + var series = this, areaPath = this.areaPath, options = this.options, zones = this.zones, props = [[ + 'area', + 'highcharts-area', + this.color, + options.fillColor + ]]; // area name, main color, fill color + zones.forEach(function (zone, i) { + props.push([ + 'zone-area-' + i, + 'highcharts-area highcharts-zone-area-' + i + ' ' + + zone.className, + zone.color || series.color, + zone.fillColor || options.fillColor + ]); + }); + props.forEach(function (prop) { + var areaKey = prop[0], area = series[areaKey], verb = area ? 'animate' : 'attr', attribs = {}; + // Create or update the area + if (area) { // update + area.endX = series.preventGraphAnimation ? + null : + areaPath.xMap; + area.animate({ d: areaPath }); + } + else { // create + attribs.zIndex = 0; // #1069 + area = series[areaKey] = series.chart.renderer + .path(areaPath) + .addClass(prop[1]) + .add(series.group); + area.isArea = true; + } + if (!series.chart.styledMode) { + attribs.fill = pick(prop[3], color(prop[2]) + .setOpacity(pick(options.fillOpacity, 0.75)) + .get()); + } + area[verb](attribs); + area.startX = areaPath.xMap; + area.shiftUnit = options.step ? 2 : 1; + }); + }, + drawLegendSymbol: LegendSymbolMixin.drawRectangle + }); + /* eslint-enable valid-jsdoc */ + /** + * A `area` series. If the [type](#series.area.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.area + * @excluding dataParser, dataURL, useOhlcData + * @product highcharts highstock + * @apioption series.area + */ + /** + * An array of data points for the series. For the `area` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` * and `pointInterval` given in the series options. If the + * axis has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 9], + * [1, 7], + * [2, 6] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.area.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @product highcharts highstock + * @apioption series.area.data + */ + ''; // adds doclets above to transpilat + + }); + _registerModule(_modules, 'parts/SplineSeries.js', [_modules['parts/Utilities.js']], function (U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var pick = U.pick, seriesType = U.seriesType; + /** + * Spline series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.spline + * + * @augments Highcarts.Series + */ + seriesType('spline', 'line', + /** + * A spline series is a special type of line series, where the segments + * between the data points are smoothed. + * + * @sample {highcharts} highcharts/demo/spline-irregular-time/ + * Spline chart + * @sample {highstock} stock/demo/spline/ + * Spline chart + * + * @extends plotOptions.series + * @excluding step + * @product highcharts highstock + * @optionparent plotOptions.spline + */ + {}, + /** + * @lends seriesTypes.spline.prototype + */ + { + /* eslint-disable valid-jsdoc */ + /** + * Get the spline segment from a given point's previous neighbour to the + * given point. + * + * @private + * @function Highcharts.seriesTypes.spline#getPointSpline + * + * @param {Array} + * + * @param {Highcharts.Point} point + * + * @param {number} i + * + * @return {Highcharts.SVGPathArray} + */ + getPointSpline: function (points, point, i) { + var + // 1 means control points midway between points, 2 means 1/3 + // from the point, 3 is 1/4 etc + smoothing = 1.5, denom = smoothing + 1, plotX = point.plotX || 0, plotY = point.plotY || 0, lastPoint = points[i - 1], nextPoint = points[i + 1], leftContX, leftContY, rightContX, rightContY, ret; + /** + * @private + */ + function doCurve(otherPoint) { + return otherPoint && + !otherPoint.isNull && + otherPoint.doCurve !== false && + // #6387, area splines next to null: + !point.isCliff; + } + // Find control points + if (doCurve(lastPoint) && doCurve(nextPoint)) { + var lastX = lastPoint.plotX || 0, lastY = lastPoint.plotY || 0, nextX = nextPoint.plotX || 0, nextY = nextPoint.plotY || 0, correction = 0; + leftContX = (smoothing * plotX + lastX) / denom; + leftContY = (smoothing * plotY + lastY) / denom; + rightContX = (smoothing * plotX + nextX) / denom; + rightContY = (smoothing * plotY + nextY) / denom; + // Have the two control points make a straight line through main + // point + if (rightContX !== leftContX) { // #5016, division by zero + correction = (((rightContY - leftContY) * + (rightContX - plotX)) / + (rightContX - leftContX) + plotY - rightContY); + } + leftContY += correction; + rightContY += correction; + // to prevent false extremes, check that control points are + // between neighbouring points' y values + if (leftContY > lastY && leftContY > plotY) { + leftContY = Math.max(lastY, plotY); + // mirror of left control point + rightContY = 2 * plotY - leftContY; + } + else if (leftContY < lastY && leftContY < plotY) { + leftContY = Math.min(lastY, plotY); + rightContY = 2 * plotY - leftContY; + } + if (rightContY > nextY && rightContY > plotY) { + rightContY = Math.max(nextY, plotY); + leftContY = 2 * plotY - rightContY; + } + else if (rightContY < nextY && rightContY < plotY) { + rightContY = Math.min(nextY, plotY); + leftContY = 2 * plotY - rightContY; + } + // record for drawing in next point + point.rightContX = rightContX; + point.rightContY = rightContY; + } + // Visualize control points for debugging + /* + if (leftContX) { + this.chart.renderer.circle( + leftContX + this.chart.plotLeft, + leftContY + this.chart.plotTop, + 2 + ) + .attr({ + stroke: 'red', + 'stroke-width': 2, + fill: 'none', + zIndex: 9 + }) + .add(); + this.chart.renderer.path(['M', leftContX + this.chart.plotLeft, + leftContY + this.chart.plotTop, + 'L', plotX + this.chart.plotLeft, plotY + this.chart.plotTop]) + .attr({ + stroke: 'red', + 'stroke-width': 2, + zIndex: 9 + }) + .add(); + } + if (rightContX) { + this.chart.renderer.circle( + rightContX + this.chart.plotLeft, + rightContY + this.chart.plotTop, + 2 + ) + .attr({ + stroke: 'green', + 'stroke-width': 2, + fill: 'none', + zIndex: 9 + }) + .add(); + this.chart.renderer.path(['M', rightContX + this.chart.plotLeft, + rightContY + this.chart.plotTop, + 'L', plotX + this.chart.plotLeft, plotY + this.chart.plotTop]) + .attr({ + stroke: 'green', + 'stroke-width': 2, + zIndex: 9 + }) + .add(); + } + // */ + ret = [ + 'C', + pick(lastPoint.rightContX, lastPoint.plotX, 0), + pick(lastPoint.rightContY, lastPoint.plotY, 0), + pick(leftContX, plotX, 0), + pick(leftContY, plotY, 0), + plotX, + plotY + ]; + // reset for updating series later + lastPoint.rightContX = lastPoint.rightContY = void 0; + return ret; + } + /* eslint-enable valid-jsdoc */ + }); + /** + * A `spline` series. If the [type](#series.spline.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.spline + * @excluding dataParser, dataURL, step + * @product highcharts highstock + * @apioption series.spline + */ + /** + * An array of data points for the series. For the `spline` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 9], + * [1, 2], + * [2, 8] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.spline.turboThreshold), + * this option is not available. + * ```js + * data: [{ + * x: 1, + * y: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 0, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @product highcharts highstock + * @apioption series.spline.data + */ + ''; // adds doclets above intro transpilat + + }); + _registerModule(_modules, 'parts/AreaSplineSeries.js', [_modules['parts/Globals.js'], _modules['mixins/legend-symbol.js'], _modules['parts/Utilities.js']], function (H, LegendSymbolMixin, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var seriesType = U.seriesType; + var areaProto = H.seriesTypes.area.prototype, defaultPlotOptions = H.defaultPlotOptions; + /** + * AreaSpline series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.areaspline + * + * @augments Highcharts.Series + */ + seriesType('areaspline', 'spline', + /** + * The area spline series is an area series where the graph between the + * points is smoothed into a spline. + * + * @sample {highcharts} highcharts/demo/areaspline/ + * Area spline chart + * @sample {highstock} stock/demo/areaspline/ + * Area spline chart + * + * @extends plotOptions.area + * @excluding step + * @product highcharts highstock + * @apioption plotOptions.areaspline + */ + defaultPlotOptions.area, { + getStackPoints: areaProto.getStackPoints, + getGraphPath: areaProto.getGraphPath, + drawGraph: areaProto.drawGraph, + drawLegendSymbol: LegendSymbolMixin.drawRectangle + }); + /** + * A `areaspline` series. If the [type](#series.areaspline.type) option + * is not specified, it is inherited from [chart.type](#chart.type). + * + * + * @extends series,plotOptions.areaspline + * @excluding dataParser, dataURL, step + * @product highcharts highstock + * @apioption series.areaspline + */ + /** + * An array of data points for the series. For the `areaspline` series + * type, points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 10], + * [1, 9], + * [2, 3] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.areaspline.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 4, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 4, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @product highcharts highstock + * @apioption series.areaspline.data + */ + ''; // adds doclets above into transpilat + + }); + _registerModule(_modules, 'parts/ColumnSeries.js', [_modules['parts/Globals.js'], _modules['parts/Color.js'], _modules['mixins/legend-symbol.js'], _modules['parts/Utilities.js']], function (H, Color, LegendSymbolMixin, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Adjusted width and x offset of the columns for grouping. + * + * @private + * @interface Highcharts.ColumnMetricsObject + */ /** + * Width of the columns. + * @name Highcharts.ColumnMetricsObject#width + * @type {number} + */ /** + * Offset of the columns. + * @name Highcharts.ColumnMetricsObject#offset + * @type {number} + */ + ''; // detach doclets above + var color = Color.parse; + var animObject = U.animObject, clamp = U.clamp, defined = U.defined, extend = U.extend, isNumber = U.isNumber, merge = U.merge, pick = U.pick, seriesType = U.seriesType; + var noop = H.noop, Series = H.Series, svg = H.svg; + /** + * The column series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.column + * + * @augments Highcharts.Series + */ + seriesType('column', 'line', + /** + * Column series display one column per value along an X axis. + * + * @sample {highcharts} highcharts/demo/column-basic/ + * Column chart + * @sample {highstock} stock/demo/column/ + * Column chart + * + * @extends plotOptions.line + * @excluding connectEnds, connectNulls, gapSize, gapUnit, linecap, + * lineWidth, marker, step, useOhlcData + * @product highcharts highstock + * @optionparent plotOptions.column + */ + { + /** + * The corner radius of the border surrounding each column or bar. + * + * @sample {highcharts} highcharts/plotoptions/column-borderradius/ + * Rounded columns + * + * @product highcharts highstock gantt + * + * @private + */ + borderRadius: 0, + /** + * When using automatic point colors pulled from the global + * [colors](colors) or series-specific + * [plotOptions.column.colors](series.colors) collections, this option + * determines whether the chart should receive one color per series or + * one color per point. + * + * In styled mode, the `colors` or `series.colors` arrays are not + * supported, and instead this option gives the points individual color + * class names on the form `highcharts-color-{n}`. + * + * @see [series colors](#plotOptions.column.colors) + * + * @sample {highcharts} highcharts/plotoptions/column-colorbypoint-false/ + * False by default + * @sample {highcharts} highcharts/plotoptions/column-colorbypoint-true/ + * True + * + * @type {boolean} + * @default false + * @since 2.0 + * @product highcharts highstock gantt + * @apioption plotOptions.column.colorByPoint + */ + /** + * A series specific or series type specific color set to apply instead + * of the global [colors](#colors) when [colorByPoint]( + * #plotOptions.column.colorByPoint) is true. + * + * @type {Array} + * @since 3.0 + * @product highcharts highstock gantt + * @apioption plotOptions.column.colors + */ + /** + * Padding between each value groups, in x axis units. + * + * @sample {highcharts} highcharts/plotoptions/column-grouppadding-default/ + * 0.2 by default + * @sample {highcharts} highcharts/plotoptions/column-grouppadding-none/ + * No group padding - all columns are evenly spaced + * + * @product highcharts highstock gantt + * + * @private + */ + groupPadding: 0.2, + /** + * Whether to group non-stacked columns or to let them render + * independent of each other. Non-grouped columns will be laid out + * individually and overlap each other. + * + * @sample {highcharts} highcharts/plotoptions/column-grouping-false/ + * Grouping disabled + * @sample {highstock} highcharts/plotoptions/column-grouping-false/ + * Grouping disabled + * + * @type {boolean} + * @default true + * @since 2.3.0 + * @product highcharts highstock gantt + * @apioption plotOptions.column.grouping + */ + /** + * @ignore-option + * @private + */ + marker: null, + /** + * The maximum allowed pixel width for a column, translated to the + * height of a bar in a bar chart. This prevents the columns from + * becoming too wide when there is a small number of points in the + * chart. + * + * @see [pointWidth](#plotOptions.column.pointWidth) + * + * @sample {highcharts} highcharts/plotoptions/column-maxpointwidth-20/ + * Limited to 50 + * @sample {highstock} highcharts/plotoptions/column-maxpointwidth-20/ + * Limited to 50 + * + * @type {number} + * @since 4.1.8 + * @product highcharts highstock gantt + * @apioption plotOptions.column.maxPointWidth + */ + /** + * Padding between each column or bar, in x axis units. + * + * @sample {highcharts} highcharts/plotoptions/column-pointpadding-default/ + * 0.1 by default + * @sample {highcharts} highcharts/plotoptions/column-pointpadding-025/ + * 0.25 + * @sample {highcharts} highcharts/plotoptions/column-pointpadding-none/ + * 0 for tightly packed columns + * + * @product highcharts highstock gantt + * + * @private + */ + pointPadding: 0.1, + /** + * A pixel value specifying a fixed width for each column or bar. When + * `null`, the width is calculated from the `pointPadding` and + * `groupPadding`. + * + * @see [maxPointWidth](#plotOptions.column.maxPointWidth) + * + * @sample {highcharts} highcharts/plotoptions/column-pointwidth-20/ + * 20px wide columns regardless of chart width or the amount of + * data points + * + * @type {number} + * @since 1.2.5 + * @product highcharts highstock gantt + * @apioption plotOptions.column.pointWidth + */ + /** + * A pixel value specifying a fixed width for the column or bar. + * Overrides pointWidth on the series. + * + * @see [series.pointWidth](#plotOptions.column.pointWidth) + * + * @type {number} + * @default undefined + * @since 7.0.0 + * @product highcharts highstock gantt + * @apioption series.column.data.pointWidth + */ + /** + * The minimal height for a column or width for a bar. By default, + * 0 values are not shown. To visualize a 0 (or close to zero) point, + * set the minimal point length to a pixel value like 3\. In stacked + * column charts, minPointLength might not be respected for tightly + * packed values. + * + * @sample {highcharts} highcharts/plotoptions/column-minpointlength/ + * Zero base value + * @sample {highcharts} highcharts/plotoptions/column-minpointlength-pos-and-neg/ + * Positive and negative close to zero values + * + * @product highcharts highstock gantt + * + * @private + */ + minPointLength: 0, + /** + * When the series contains less points than the crop threshold, all + * points are drawn, event if the points fall outside the visible plot + * area at the current zoom. The advantage of drawing all points + * (including markers and columns), is that animation is performed on + * updates. On the other hand, when the series contains more points than + * the crop threshold, the series data is cropped to only contain points + * that fall within the plot area. The advantage of cropping away + * invisible points is to increase performance on large series. + * + * @product highcharts highstock gantt + * + * @private + */ + cropThreshold: 50, + /** + * The X axis range that each point is valid for. This determines the + * width of the column. On a categorized axis, the range will be 1 + * by default (one category unit). On linear and datetime axes, the + * range will be computed as the distance between the two closest data + * points. + * + * The default `null` means it is computed automatically, but this + * option can be used to override the automatic value. + * + * This option is set by default to 1 if data sorting is enabled. + * + * @sample {highcharts} highcharts/plotoptions/column-pointrange/ + * Set the point range to one day on a data set with one week + * between the points + * + * @type {number|null} + * @since 2.3 + * @product highcharts highstock gantt + * + * @private + */ + pointRange: null, + states: { + /** + * Options for the hovered point. These settings override the normal + * state options when a point is moused over or touched. + * + * @extends plotOptions.series.states.hover + * @excluding halo, lineWidth, lineWidthPlus, marker + * @product highcharts highstock gantt + */ + hover: { + /** @ignore-option */ + halo: false, + /** + * A specific border color for the hovered point. Defaults to + * inherit the normal state border color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts gantt + * @apioption plotOptions.column.states.hover.borderColor + */ + /** + * A specific color for the hovered point. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts gantt + * @apioption plotOptions.column.states.hover.color + */ + /** + * How much to brighten the point on interaction. Requires the + * main color to be defined in hex or rgb(a) format. + * + * In styled mode, the hover brightening is by default replaced + * with a fill-opacity set in the `.highcharts-point:hover` + * rule. + * + * @sample {highcharts} highcharts/plotoptions/column-states-hover-brightness/ + * Brighten by 0.5 + * + * @product highcharts highstock gantt + */ + brightness: 0.1 + }, + /** + * Options for the selected point. These settings override the + * normal state options when a point is selected. + * + * @extends plotOptions.series.states.select + * @excluding halo, lineWidth, lineWidthPlus, marker + * @product highcharts highstock gantt + */ + select: { + /** + * A specific color for the selected point. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #cccccc + * @product highcharts highstock gantt + */ + color: '#cccccc', + /** + * A specific border color for the selected point. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #000000 + * @product highcharts highstock gantt + */ + borderColor: '#000000' + } + }, + dataLabels: { + align: null, + verticalAlign: null, + y: null + }, + /** + * When this is true, the series will not cause the Y axis to cross + * the zero plane (or [threshold](#plotOptions.series.threshold) option) + * unless the data actually crosses the plane. + * + * For example, if `softThreshold` is `false`, a series of 0, 1, 2, + * 3 will make the Y axis show negative values according to the + * `minPadding` option. If `softThreshold` is `true`, the Y axis starts + * at 0. + * + * @since 4.1.9 + * @product highcharts highstock + * + * @private + */ + softThreshold: false, + // false doesn't work well: https://jsfiddle.net/highcharts/hz8fopan/14/ + /** + * @ignore-option + * @private + */ + startFromThreshold: true, + stickyTracking: false, + tooltip: { + distance: 6 + }, + /** + * The Y axis value to serve as the base for the columns, for + * distinguishing between values above and below a threshold. If `null`, + * the columns extend from the padding Y axis minimum. + * + * @type {number|null} + * @since 2.0 + * @product highcharts + * + * @private + */ + threshold: 0, + /** + * The width of the border surrounding each column or bar. Defaults to + * `1` when there is room for a border, but to `0` when the columns are + * so dense that a border would cover the next column. + * + * In styled mode, the stroke width can be set with the + * `.highcharts-point` rule. + * + * @sample {highcharts} highcharts/plotoptions/column-borderwidth/ + * 2px black border + * + * @type {number} + * @default undefined + * @product highcharts highstock gantt + * @apioption plotOptions.column.borderWidth + */ + /** + * The color of the border surrounding each column or bar. + * + * In styled mode, the border stroke can be set with the + * `.highcharts-point` rule. + * + * @sample {highcharts} highcharts/plotoptions/column-bordercolor/ + * Dark gray border + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #ffffff + * @product highcharts highstock gantt + * + * @private + */ + borderColor: '#ffffff' + }, + /** + * @lends seriesTypes.column.prototype + */ + { + cropShoulder: 0, + // When tooltip is not shared, this series (and derivatives) requires + // direct touch/hover. KD-tree does not apply. + directTouch: true, + trackerGroups: ['group', 'dataLabelsGroup'], + // use separate negative stacks, unlike area stacks where a negative + // point is substracted from previous (#1910) + negStacks: true, + /* eslint-disable valid-jsdoc */ + /** + * Initialize the series. Extends the basic Series.init method by + * marking other series of the same type as dirty. + * + * @private + * @function Highcharts.seriesTypes.column#init + * @return {void} + */ + init: function () { + Series.prototype.init.apply(this, arguments); + var series = this, chart = series.chart; + // if the series is added dynamically, force redraw of other + // series affected by a new column + if (chart.hasRendered) { + chart.series.forEach(function (otherSeries) { + if (otherSeries.type === series.type) { + otherSeries.isDirty = true; + } + }); + } + }, + /** + * Return the width and x offset of the columns adjusted for grouping, + * groupPadding, pointPadding, pointWidth etc. + * + * @private + * @function Highcharts.seriesTypes.column#getColumnMetrics + * @return {Highcharts.ColumnMetricsObject} + */ + getColumnMetrics: function () { + var series = this, options = series.options, xAxis = series.xAxis, yAxis = series.yAxis, reversedStacks = xAxis.options.reversedStacks, + // Keep backward compatibility: reversed xAxis had reversed + // stacks + reverseStacks = (xAxis.reversed && !reversedStacks) || + (!xAxis.reversed && reversedStacks), stackKey, stackGroups = {}, columnCount = 0; + // Get the total number of column type series. This is called on + // every series. Consider moving this logic to a chart.orderStacks() + // function and call it on init, addSeries and removeSeries + if (options.grouping === false) { + columnCount = 1; + } + else { + series.chart.series.forEach(function (otherSeries) { + var otherYAxis = otherSeries.yAxis, otherOptions = otherSeries.options, columnIndex; + if (otherSeries.type === series.type && + (otherSeries.visible || + !series.chart.options.chart + .ignoreHiddenSeries) && + yAxis.len === otherYAxis.len && + yAxis.pos === otherYAxis.pos) { // #642, #2086 + if (otherOptions.stacking) { + stackKey = otherSeries.stackKey; + if (typeof stackGroups[stackKey] === + 'undefined') { + stackGroups[stackKey] = columnCount++; + } + columnIndex = stackGroups[stackKey]; + } + else if (otherOptions.grouping !== false) { // #1162 + columnIndex = columnCount++; + } + otherSeries.columnIndex = columnIndex; + } + }); + } + var categoryWidth = Math.min(Math.abs(xAxis.transA) * ((xAxis.ordinal && xAxis.ordinal.slope) || + options.pointRange || + xAxis.closestPointRange || + xAxis.tickInterval || + 1), // #2610 + xAxis.len // #1535 + ), groupPadding = categoryWidth * options.groupPadding, groupWidth = categoryWidth - 2 * groupPadding, pointOffsetWidth = groupWidth / (columnCount || 1), pointWidth = Math.min(options.maxPointWidth || xAxis.len, pick(options.pointWidth, pointOffsetWidth * (1 - 2 * options.pointPadding))), pointPadding = (pointOffsetWidth - pointWidth) / 2, + // #1251, #3737 + colIndex = (series.columnIndex || 0) + (reverseStacks ? 1 : 0), pointXOffset = pointPadding + + (groupPadding + + colIndex * pointOffsetWidth - + (categoryWidth / 2)) * (reverseStacks ? -1 : 1); + // Save it for reading in linked series (Error bars particularly) + series.columnMetrics = { + width: pointWidth, + offset: pointXOffset + }; + return series.columnMetrics; + }, + /** + * Make the columns crisp. The edges are rounded to the nearest full + * pixel. + * + * @private + * @function Highcharts.seriesTypes.column#crispCol + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @return {Highcharts.BBoxObject} + */ + crispCol: function (x, y, w, h) { + var chart = this.chart, borderWidth = this.borderWidth, xCrisp = -(borderWidth % 2 ? 0.5 : 0), yCrisp = borderWidth % 2 ? 0.5 : 1, right, bottom, fromTop; + if (chart.inverted && chart.renderer.isVML) { + yCrisp += 1; + } + // Horizontal. We need to first compute the exact right edge, then + // round it and compute the width from there. + if (this.options.crisp) { + right = Math.round(x + w) + xCrisp; + x = Math.round(x) + xCrisp; + w = right - x; + } + // Vertical + bottom = Math.round(y + h) + yCrisp; + fromTop = Math.abs(y) <= 0.5 && bottom > 0.5; // #4504, #4656 + y = Math.round(y) + yCrisp; + h = bottom - y; + // Top edges are exceptions + if (fromTop && h) { // #5146 + y -= 1; + h += 1; + } + return { + x: x, + y: y, + width: w, + height: h + }; + }, + /** + * Translate each point to the plot area coordinate system and find + * shape positions + * + * @private + * @function Highcharts.seriesTypes.column#translate + */ + translate: function () { + var series = this, chart = series.chart, options = series.options, dense = series.dense = + series.closestPointRange * series.xAxis.transA < 2, borderWidth = series.borderWidth = pick(options.borderWidth, dense ? 0 : 1 // #3635 + ), xAxis = series.xAxis, yAxis = series.yAxis, threshold = options.threshold, translatedThreshold = series.translatedThreshold = + yAxis.getThreshold(threshold), minPointLength = pick(options.minPointLength, 5), metrics = series.getColumnMetrics(), seriesPointWidth = metrics.width, + // postprocessed for border width + seriesBarW = series.barW = + Math.max(seriesPointWidth, 1 + 2 * borderWidth), seriesXOffset = series.pointXOffset = metrics.offset, dataMin = series.dataMin, dataMax = series.dataMax; + if (chart.inverted) { + translatedThreshold -= 0.5; // #3355 + } + // When the pointPadding is 0, we want the columns to be packed + // tightly, so we allow individual columns to have individual sizes. + // When pointPadding is greater, we strive for equal-width columns + // (#2694). + if (options.pointPadding) { + seriesBarW = Math.ceil(seriesBarW); + } + Series.prototype.translate.apply(series); + // Record the new values + series.points.forEach(function (point) { + var yBottom = pick(point.yBottom, translatedThreshold), safeDistance = 999 + Math.abs(yBottom), pointWidth = seriesPointWidth, plotX = point.plotX, + // Don't draw too far outside plot area (#1303, #2241, + // #4264) + plotY = clamp(point.plotY, -safeDistance, yAxis.len + safeDistance), barX = point.plotX + seriesXOffset, barW = seriesBarW, barY = Math.min(plotY, yBottom), up, barH = Math.max(plotY, yBottom) - barY; + // Handle options.minPointLength + if (minPointLength && Math.abs(barH) < minPointLength) { + barH = minPointLength; + up = (!yAxis.reversed && !point.negative) || + (yAxis.reversed && point.negative); + // Reverse zeros if there's no positive value in the series + // in visible range (#7046) + if (isNumber(threshold) && + isNumber(dataMax) && + point.y === threshold && + dataMax <= threshold && + // and if there's room for it (#7311) + (yAxis.min || 0) < threshold && + // if all points are the same value (i.e zero) not draw + // as negative points (#10646) + dataMin !== dataMax) { + up = !up; + } + // If stacked... + barY = (Math.abs(barY - translatedThreshold) > minPointLength ? + // ...keep position + yBottom - minPointLength : + // #1485, #4051 + translatedThreshold - + (up ? minPointLength : 0)); + } + // Handle point.options.pointWidth + // @todo Handle grouping/stacking too. Calculate offset properly + if (defined(point.options.pointWidth)) { + pointWidth = barW = + Math.ceil(point.options.pointWidth); + barX -= Math.round((pointWidth - seriesPointWidth) / 2); + } + // Cache for access in polar + point.barX = barX; + point.pointWidth = pointWidth; + // Fix the tooltip on center of grouped columns (#1216, #424, + // #3648) + point.tooltipPos = chart.inverted ? + [ + yAxis.len + yAxis.pos - chart.plotLeft - plotY, + xAxis.len + xAxis.pos - chart.plotTop - (plotX || 0) - seriesXOffset - barW / 2, + barH + ] : + [barX + barW / 2, plotY + yAxis.pos - + chart.plotTop, barH]; + // Register shape type and arguments to be used in drawPoints + // Allow shapeType defined on pointClass level + point.shapeType = + series.pointClass.prototype.shapeType || 'rect'; + point.shapeArgs = series.crispCol.apply(series, point.isNull ? + // #3169, drilldown from null must have a position to work + // from #6585, dataLabel should be placed on xAxis, not + // floating in the middle of the chart + [barX, translatedThreshold, barW, 0] : + [barX, barY, barW, barH]); + }); + }, + getSymbol: noop, + /** + * Use a solid rectangle like the area series types + * + * @private + * @function Highcharts.seriesTypes.column#drawLegendSymbol + * + * @param {Highcharts.Legend} legend + * The legend object + * + * @param {Highcharts.Series|Highcharts.Point} item + * The series (this) or point + */ + drawLegendSymbol: LegendSymbolMixin.drawRectangle, + /** + * Columns have no graph + * + * @private + * @function Highcharts.seriesTypes.column#drawGraph + */ + drawGraph: function () { + this.group[this.dense ? 'addClass' : 'removeClass']('highcharts-dense-data'); + }, + /** + * Get presentational attributes + * + * @private + * @function Highcharts.seriesTypes.column#pointAttribs + * + * @param {Highcharts.ColumnPoint} point + * + * @param {string} state + * + * @return {Highcharts.SVGAttributes} + */ + pointAttribs: function (point, state) { + var options = this.options, stateOptions, ret, p2o = this.pointAttrToOptions || {}, strokeOption = p2o.stroke || 'borderColor', strokeWidthOption = p2o['stroke-width'] || 'borderWidth', fill = (point && point.color) || this.color, + // set to fill when borderColor null: + stroke = ((point && point[strokeOption]) || + options[strokeOption] || + this.color || + fill), strokeWidth = (point && point[strokeWidthOption]) || + options[strokeWidthOption] || + this[strokeWidthOption] || 0, dashstyle = (point && point.options.dashStyle) || options.dashStyle, opacity = pick(point && point.opacity, options.opacity, 1), zone, brightness; + // Handle zone colors + if (point && this.zones.length) { + zone = point.getZone(); + // When zones are present, don't use point.color (#4267). + // Changed order (#6527), added support for colorAxis (#10670) + fill = (point.options.color || + (zone && (zone.color || point.nonZonedColor)) || + this.color); + if (zone) { + stroke = zone.borderColor || stroke; + dashstyle = zone.dashStyle || dashstyle; + strokeWidth = zone.borderWidth || strokeWidth; + } + } + // Select or hover states + if (state && point) { + stateOptions = merge(options.states[state], + // #6401 + point.options.states && + point.options.states[state] || + {}); + brightness = stateOptions.brightness; + fill = + stateOptions.color || (typeof brightness !== 'undefined' && + color(fill) + .brighten(stateOptions.brightness) + .get()) || fill; + stroke = stateOptions[strokeOption] || stroke; + strokeWidth = + stateOptions[strokeWidthOption] || strokeWidth; + dashstyle = stateOptions.dashStyle || dashstyle; + opacity = pick(stateOptions.opacity, opacity); + } + ret = { + fill: fill, + stroke: stroke, + 'stroke-width': strokeWidth, + opacity: opacity + }; + if (dashstyle) { + ret.dashstyle = dashstyle; + } + return ret; + }, + /** + * Draw the columns. For bars, the series.group is rotated, so the same + * coordinates apply for columns and bars. This method is inherited by + * scatter series. + * + * @private + * @function Highcharts.seriesTypes.column#drawPoints + */ + drawPoints: function () { + var series = this, chart = this.chart, options = series.options, renderer = chart.renderer, animationLimit = options.animationLimit || 250, shapeArgs; + // draw the columns + series.points.forEach(function (point) { + var plotY = point.plotY, graphic = point.graphic, hasGraphic = !!graphic, verb = graphic && chart.pointCount < animationLimit ? + 'animate' : 'attr'; + if (isNumber(plotY) && point.y !== null) { + shapeArgs = point.shapeArgs; + // When updating a series between 2d and 3d or cartesian and + // polar, the shape type changes. + if (graphic && point.hasNewShapeType()) { + graphic = graphic.destroy(); + } + // Set starting position for point sliding animation. + if (series.enabledDataSorting) { + point.startXPos = series.xAxis.reversed ? + -(shapeArgs ? shapeArgs.width : 0) : + series.xAxis.width; + } + if (!graphic) { + point.graphic = graphic = + renderer[point.shapeType](shapeArgs) + .add(point.group || series.group); + if (graphic && + series.enabledDataSorting && + chart.hasRendered && + chart.pointCount < animationLimit) { + graphic.attr({ + x: point.startXPos + }); + hasGraphic = true; + verb = 'animate'; + } + } + if (graphic && hasGraphic) { // update + graphic[verb](merge(shapeArgs)); + } + // Border radius is not stylable (#6900) + if (options.borderRadius) { + graphic[verb]({ + r: options.borderRadius + }); + } + // Presentational + if (!chart.styledMode) { + graphic[verb](series.pointAttribs(point, (point.selected && 'select'))) + .shadow(point.allowShadow !== false && options.shadow, null, options.stacking && !options.borderRadius); + } + graphic.addClass(point.getClassName(), true); + } + else if (graphic) { + point.graphic = graphic.destroy(); // #1269 + } + }); + }, + /** + * Animate the column heights one by one from zero. + * + * @private + * @function Highcharts.seriesTypes.column#animate + * + * @param {boolean} init + * Whether to initialize the animation or run it + */ + animate: function (init) { + var series = this, yAxis = this.yAxis, options = series.options, inverted = this.chart.inverted, attr = {}, translateProp = inverted ? 'translateX' : 'translateY', translateStart, translatedThreshold; + if (init) { + attr.scaleY = 0.001; + translatedThreshold = clamp(yAxis.toPixels(options.threshold), yAxis.pos, yAxis.pos + yAxis.len); + if (inverted) { + attr.translateX = translatedThreshold - yAxis.len; + } + else { + attr.translateY = translatedThreshold; + } + // apply finnal clipping (used in Highstock) (#7083) + // animation is done by scaleY, so cliping is for panes + if (series.clipBox) { + series.setClip(); + } + series.group.attr(attr); + } + else { // run the animation + translateStart = series.group.attr(translateProp); + series.group.animate({ scaleY: 1 }, extend(animObject(series.options.animation), { + // Do the scale synchronously to ensure smooth + // updating (#5030, #7228) + step: function (val, fx) { + if (series.group) { + attr[translateProp] = translateStart + + fx.pos * (yAxis.pos - translateStart); + series.group.attr(attr); + } + } + })); + } + }, + /** + * Remove this series from the chart + * + * @private + * @function Highcharts.seriesTypes.column#remove + */ + remove: function () { + var series = this, chart = series.chart; + // column and bar series affects other series of the same type + // as they are either stacked or grouped + if (chart.hasRendered) { + chart.series.forEach(function (otherSeries) { + if (otherSeries.type === series.type) { + otherSeries.isDirty = true; + } + }); + } + Series.prototype.remove.apply(series, arguments); + } + }); + /* eslint-enable valid-jsdoc */ + /** + * A `column` series. If the [type](#series.column.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.column + * @excluding connectNulls, dataParser, dataURL, gapSize, gapUnit, linecap, + * lineWidth, marker, connectEnds, step + * @product highcharts highstock + * @apioption series.column + */ + /** + * An array of data points for the series. For the `column` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 6], + * [1, 2], + * [2, 6] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.column.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @excluding marker + * @product highcharts highstock + * @apioption series.column.data + */ + /** + * The color of the border surrounding the column or bar. + * + * In styled mode, the border stroke can be set with the `.highcharts-point` + * rule. + * + * @sample {highcharts} highcharts/plotoptions/column-bordercolor/ + * Dark gray border + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock + * @apioption series.column.data.borderColor + */ + /** + * The width of the border surrounding the column or bar. + * + * In styled mode, the stroke width can be set with the `.highcharts-point` + * rule. + * + * @sample {highcharts} highcharts/plotoptions/column-borderwidth/ + * 2px black border + * + * @type {number} + * @product highcharts highstock + * @apioption series.column.data.borderWidth + */ + /** + * A name for the dash style to use for the column or bar. Overrides + * dashStyle on the series. + * + * In styled mode, the stroke dash-array can be set with the same classes as + * listed under [data.color](#series.column.data.color). + * + * @see [series.pointWidth](#plotOptions.column.dashStyle) + * + * @type {Highcharts.DashStyleValue} + * @apioption series.column.data.dashStyle + */ + /** + * A pixel value specifying a fixed width for the column or bar. Overrides + * pointWidth on the series. + * + * @see [series.pointWidth](#plotOptions.column.pointWidth) + * + * @type {number} + * @apioption series.column.data.pointWidth + */ + /** + * @excluding halo, lineWidth, lineWidthPlus, marker + * @product highcharts highstock + * @apioption series.column.states.hover + */ + /** + * @excluding halo, lineWidth, lineWidthPlus, marker + * @product highcharts highstock + * @apioption series.column.states.select + */ + ''; // includes above doclets in transpilat + + }); + _registerModule(_modules, 'parts/BarSeries.js', [_modules['parts/Utilities.js']], function (U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var seriesType = U.seriesType; + /** + * Bar series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.bar + * + * @augments Highcharts.Series + */ + seriesType('bar', 'column', + /** + * A bar series is a special type of column series where the columns are + * horizontal. + * + * @sample highcharts/demo/bar-basic/ + * Bar chart + * + * @extends plotOptions.column + * @product highcharts + * @apioption plotOptions.bar + */ + /** + * @ignore + */ + null, { + inverted: true + }); + /** + * A `bar` series. If the [type](#series.bar.type) option is not specified, + * it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.bar + * @excluding connectNulls, dashStyle, dataParser, dataURL, gapSize, gapUnit, + * linecap, lineWidth, marker, connectEnds, step + * @product highcharts + * @apioption series.bar + */ + /** + * An array of data points for the series. For the `bar` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 5], + * [1, 10], + * [2, 3] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.bar.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 1, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 10, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.column.data + * @product highcharts + * @apioption series.bar.data + */ + /** + * @excluding halo,lineWidth,lineWidthPlus,marker + * @product highcharts highstock + * @apioption series.bar.states.hover + */ + /** + * @excluding halo,lineWidth,lineWidthPlus,marker + * @product highcharts highstock + * @apioption series.bar.states.select + */ + ''; // gets doclets above into transpilat + + }); + _registerModule(_modules, 'parts/ScatterSeries.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, seriesType = U.seriesType; + var Series = H.Series; + /** + * Scatter series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.scatter + * + * @augments Highcharts.Series + */ + seriesType('scatter', 'line', + /** + * A scatter plot uses cartesian coordinates to display values for two + * variables for a set of data. + * + * @sample {highcharts} highcharts/demo/scatter/ + * Scatter plot + * + * @extends plotOptions.line + * @excluding pointPlacement, shadow, useOhlcData + * @product highcharts highstock + * @optionparent plotOptions.scatter + */ + { + /** + * The width of the line connecting the data points. + * + * @sample {highcharts} highcharts/plotoptions/scatter-linewidth-none/ + * 0 by default + * @sample {highcharts} highcharts/plotoptions/scatter-linewidth-1/ + * 1px + * + * @product highcharts highstock + */ + lineWidth: 0, + findNearestPointBy: 'xy', + /** + * Apply a jitter effect for the rendered markers. When plotting + * discrete values, a little random noise may help telling the points + * apart. The jitter setting applies a random displacement of up to `n` + * axis units in either direction. So for example on a horizontal X + * axis, setting the `jitter.x` to 0.24 will render the point in a + * random position between 0.24 units to the left and 0.24 units to the + * right of the true axis position. On a category axis, setting it to + * 0.5 will fill up the bin and make the data appear continuous. + * + * When rendered on top of a box plot or a column series, a jitter value + * of 0.24 will correspond to the underlying series' default + * [groupPadding]( + * https://api.highcharts.com/highcharts/plotOptions.column.groupPadding) + * and [pointPadding]( + * https://api.highcharts.com/highcharts/plotOptions.column.pointPadding) + * settings. + * + * @sample {highcharts} highcharts/series-scatter/jitter + * Jitter on a scatter plot + * + * @sample {highcharts} highcharts/series-scatter/jitter-boxplot + * Jittered scatter plot on top of a box plot + * + * @product highcharts highstock + * @since 7.0.2 + */ + jitter: { + /** + * The maximal X offset for the random jitter effect. + */ + x: 0, + /** + * The maximal Y offset for the random jitter effect. + */ + y: 0 + }, + marker: { + enabled: true // Overrides auto-enabling in line series (#3647) + }, + /** + * Sticky tracking of mouse events. When true, the `mouseOut` event + * on a series isn't triggered until the mouse moves over another + * series, or out of the plot area. When false, the `mouseOut` event on + * a series is triggered when the mouse leaves the area around the + * series' graph or markers. This also implies the tooltip. When + * `stickyTracking` is false and `tooltip.shared` is false, the tooltip + * will be hidden when moving the mouse between series. + * + * @type {boolean} + * @default false + * @product highcharts highstock + * @apioption plotOptions.scatter.stickyTracking + */ + /** + * A configuration object for the tooltip rendering of each single + * series. Properties are inherited from [tooltip](#tooltip). + * Overridable properties are `headerFormat`, `pointFormat`, + * `yDecimals`, `xDateFormat`, `yPrefix` and `ySuffix`. Unlike other + * series, in a scatter plot the series.name by default shows in the + * headerFormat and point.x and point.y in the pointFormat. + * + * @product highcharts highstock + */ + tooltip: { + headerFormat: '\u25CF ' + + ' {series.name}
', + pointFormat: 'x: {point.x}
y: {point.y}
' + } + // Prototype members + }, { + sorted: false, + requireSorting: false, + noSharedTooltip: true, + trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'], + takeOrdinalPosition: false, + /* eslint-disable valid-jsdoc */ + /** + * @private + * @function Highcharts.seriesTypes.scatter#drawGraph + */ + drawGraph: function () { + if (this.options.lineWidth) { + Series.prototype.drawGraph.call(this); + } + }, + // Optionally add the jitter effect + applyJitter: function () { + var series = this, jitter = this.options.jitter, len = this.points.length; + /** + * Return a repeatable, pseudo-random number based on an integer + * seed. + * @private + */ + function unrandom(seed) { + var rand = Math.sin(seed) * 10000; + return rand - Math.floor(rand); + } + if (jitter) { + this.points.forEach(function (point, i) { + ['x', 'y'].forEach(function (dim, j) { + var axis, plotProp = 'plot' + dim.toUpperCase(), min, max, translatedJitter; + if (jitter[dim] && !point.isNull) { + axis = series[dim + 'Axis']; + translatedJitter = + jitter[dim] * axis.transA; + if (axis && !axis.isLog) { + // Identify the outer bounds of the jitter range + min = Math.max(0, point[plotProp] - translatedJitter); + max = Math.min(axis.len, point[plotProp] + translatedJitter); + // Find a random position within this range + point[plotProp] = min + + (max - min) * unrandom(i + j * len); + // Update clientX for the tooltip k-d-tree + if (dim === 'x') { + point.clientX = point.plotX; + } + } + } + }); + }); + } + } + /* eslint-enable valid-jsdoc */ + }); + /* eslint-disable no-invalid-this */ + addEvent(Series, 'afterTranslate', function () { + if (this.applyJitter) { + this.applyJitter(); + } + }); + /* eslint-enable no-invalid-this */ + /** + * A `scatter` series. If the [type](#series.scatter.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.scatter + * @excluding dataParser, dataURL, useOhlcData + * @product highcharts highstock + * @apioption series.scatter + */ + /** + * An array of data points for the series. For the `scatter` series + * type, points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 0], + * [1, 8], + * [2, 9] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.scatter.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 2, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 4, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @product highcharts highstock + * @apioption series.scatter.data + */ + ''; // adds doclets above to transpilat + + }); + _registerModule(_modules, 'mixins/centered-series.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * @private + * @interface Highcharts.RadianAngles + */ /** + * @name Highcharts.RadianAngles#end + * @type {number} + */ /** + * @name Highcharts.RadianAngles#start + * @type {number} + */ + var isNumber = U.isNumber, pick = U.pick, relativeLength = U.relativeLength; + var deg2rad = H.deg2rad; + /* eslint-disable valid-jsdoc */ + /** + * @private + * @mixin Highcharts.CenteredSeriesMixin + */ + H.CenteredSeriesMixin = { + /** + * Get the center of the pie based on the size and center options relative + * to the plot area. Borrowed by the polar and gauge series types. + * + * @private + * @function Highcharts.CenteredSeriesMixin.getCenter + * + * @return {Array} + */ + getCenter: function () { + var options = this.options, chart = this.chart, slicingRoom = 2 * (options.slicedOffset || 0), handleSlicingRoom, plotWidth = chart.plotWidth - 2 * slicingRoom, plotHeight = chart.plotHeight - 2 * slicingRoom, centerOption = options.center, smallestSize = Math.min(plotWidth, plotHeight), size = options.size, innerSize = options.innerSize || 0, positions, i, value; + if (typeof size === 'string') { + size = parseFloat(size); + } + if (typeof innerSize === 'string') { + innerSize = parseFloat(innerSize); + } + positions = [ + pick(centerOption[0], '50%'), + pick(centerOption[1], '50%'), + // Prevent from negative values + pick(size && size < 0 ? void 0 : options.size, '100%'), + pick(innerSize && innerSize < 0 ? void 0 : options.innerSize || 0, '0%') + ]; + // No need for inner size in angular (gauges) series + if (chart.angular) { + positions[3] = 0; + } + for (i = 0; i < 4; ++i) { + value = positions[i]; + handleSlicingRoom = i < 2 || (i === 2 && /%$/.test(value)); + // i == 0: centerX, relative to width + // i == 1: centerY, relative to height + // i == 2: size, relative to smallestSize + // i == 3: innerSize, relative to size + positions[i] = relativeLength(value, [plotWidth, plotHeight, smallestSize, positions[2]][i]) + (handleSlicingRoom ? slicingRoom : 0); + } + // innerSize cannot be larger than size (#3632) + if (positions[3] > positions[2]) { + positions[3] = positions[2]; + } + return positions; + }, + /** + * getStartAndEndRadians - Calculates start and end angles in radians. + * Used in series types such as pie and sunburst. + * + * @private + * @function Highcharts.CenteredSeriesMixin.getStartAndEndRadians + * + * @param {number} [start] + * Start angle in degrees. + * + * @param {number} [end] + * Start angle in degrees. + * + * @return {Highcharts.RadianAngles} + * Returns an object containing start and end angles as radians. + */ + getStartAndEndRadians: function (start, end) { + var startAngle = isNumber(start) ? start : 0, // must be a number + endAngle = ((isNumber(end) && // must be a number + end > startAngle && // must be larger than the start angle + // difference must be less than 360 degrees + (end - startAngle) < 360) ? + end : + startAngle + 360), correction = -90; + return { + start: deg2rad * (startAngle + correction), + end: deg2rad * (endAngle + correction) + }; + } + }; + + }); + _registerModule(_modules, 'parts/PieSeries.js', [_modules['parts/Globals.js'], _modules['mixins/legend-symbol.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js']], function (H, LegendSymbolMixin, Point, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, clamp = U.clamp, defined = U.defined, fireEvent = U.fireEvent, isNumber = U.isNumber, merge = U.merge, pick = U.pick, relativeLength = U.relativeLength, seriesType = U.seriesType, setAnimation = U.setAnimation; + var CenteredSeriesMixin = H.CenteredSeriesMixin, getStartAndEndRadians = CenteredSeriesMixin.getStartAndEndRadians, noop = H.noop, Series = H.Series, seriesTypes = H.seriesTypes; + /** + * Pie series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.pie + * + * @augments Highcharts.Series + */ + seriesType('pie', 'line', + /** + * A pie chart is a circular graphic which is divided into slices to + * illustrate numerical proportion. + * + * @sample highcharts/demo/pie-basic/ + * Pie chart + * + * @extends plotOptions.line + * @excluding animationLimit, boostThreshold, connectEnds, connectNulls, + * cropThreshold, dashStyle, dataSorting, dragDrop, + * findNearestPointBy, getExtremesFromAll, label, lineWidth, + * marker, negativeColor, pointInterval, pointIntervalUnit, + * pointPlacement, pointStart, softThreshold, stacking, step, + * threshold, turboThreshold, zoneAxis, zones, dataSorting + * @product highcharts + * @optionparent plotOptions.pie + */ + { + /** + * @excluding legendItemClick + * @apioption plotOptions.pie.events + */ + /** + * Fires when the checkbox next to the point name in the legend is + * clicked. One parameter, event, is passed to the function. The state + * of the checkbox is found by event.checked. The checked item is found + * by event.item. Return false to prevent the default action which is to + * toggle the select state of the series. + * + * @sample {highcharts} highcharts/plotoptions/series-events-checkboxclick/ + * Alert checkbox status + * + * @type {Function} + * @since 1.2.0 + * @product highcharts + * @context Highcharts.Point + * @apioption plotOptions.pie.events.checkboxClick + */ + /** + * Fires when the legend item belonging to the pie point (slice) is + * clicked. The `this` keyword refers to the point itself. One + * parameter, `event`, is passed to the function, containing common + * event information. The default action is to toggle the visibility of + * the point. This can be prevented by calling `event.preventDefault()`. + * + * @sample {highcharts} highcharts/plotoptions/pie-point-events-legenditemclick/ + * Confirm toggle visibility + * + * @type {Highcharts.PointLegendItemClickCallbackFunction} + * @since 1.2.0 + * @product highcharts + * @apioption plotOptions.pie.point.events.legendItemClick + */ + /** + * The center of the pie chart relative to the plot area. Can be + * percentages or pixel values. The default behaviour (as of 3.0) is to + * center the pie so that all slices and data labels are within the plot + * area. As a consequence, the pie may actually jump around in a chart + * with dynamic values, as the data labels move. In that case, the + * center should be explicitly set, for example to `["50%", "50%"]`. + * + * @sample {highcharts} highcharts/plotoptions/pie-center/ + * Centered at 100, 100 + * + * @type {Array<(number|string|null),(number|string|null)>} + * @default [null, null] + * @product highcharts + * + * @private + */ + center: [null, null], + /** + * The color of the pie series. A pie series is represented as an empty + * circle if the total sum of its values is 0. Use this property to + * define the color of its border. + * + * In styled mode, the color can be defined by the + * [colorIndex](#plotOptions.series.colorIndex) option. Also, the series + * color can be set with the `.highcharts-series`, + * `.highcharts-color-{n}`, `.highcharts-{type}-series` or + * `.highcharts-series-{n}` class, or individual classes given by the + * `className` option. + * + * @sample {highcharts} highcharts/plotoptions/pie-emptyseries/ + * Empty pie series + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #cccccc + * @apioption plotOptions.pie.color + */ + /** + * @product highcharts + * + * @private + */ + clip: false, + /** + * @ignore-option + * + * @private + */ + colorByPoint: true, + /** + * A series specific or series type specific color set to use instead + * of the global [colors](#colors). + * + * @sample {highcharts} highcharts/demo/pie-monochrome/ + * Set default colors for all pies + * + * @type {Array} + * @since 3.0 + * @product highcharts + * @apioption plotOptions.pie.colors + */ + /** + * @declare Highcharts.SeriesPieDataLabelsOptionsObject + * @extends plotOptions.series.dataLabels + * @excluding align, allowOverlap, inside, staggerLines, step + * @private + */ + dataLabels: { + /** + * Alignment method for data labels. Possible values are: + * + * - `toPlotEdges`: Each label touches the nearest vertical edge of + * the plot area. + * + * - `connectors`: Connectors have the same x position and the + * widest label of each half (left & right) touches the nearest + * vertical edge of the plot area. + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-alignto-connectors/ + * alignTo: connectors + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-alignto-plotedges/ + * alignTo: plotEdges + * + * @type {string} + * @since 7.0.0 + * @product highcharts + * @apioption plotOptions.pie.dataLabels.alignTo + */ + allowOverlap: true, + /** + * The color of the line connecting the data label to the pie slice. + * The default color is the same as the point's color. + * + * In styled mode, the connector stroke is given in the + * `.highcharts-data-label-connector` class. + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorcolor/ + * Blue connectors + * @sample {highcharts} highcharts/css/pie-point/ + * Styled connectors + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.1 + * @product highcharts + * @apioption plotOptions.pie.dataLabels.connectorColor + */ + /** + * The distance from the data label to the connector. Note that + * data labels also have a default `padding`, so in order for the + * connector to touch the text, the `padding` must also be 0. + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorpadding/ + * No padding + * + * @since 2.1 + * @product highcharts + */ + connectorPadding: 5, + /** + * Specifies the method that is used to generate the connector path. + * Highcharts provides 3 built-in connector shapes: `'fixedOffset'` + * (default), `'straight'` and `'crookedLine'`. Using + * `'crookedLine'` has the most sense (in most of the cases) when + * `'alignTo'` is set. + * + * Users can provide their own method by passing a function instead + * of a String. 3 arguments are passed to the callback: + * + * - Object that holds the information about the coordinates of the + * label (`x` & `y` properties) and how the label is located in + * relation to the pie (`alignment` property). `alignment` can by + * one of the following: + * `'left'` (pie on the left side of the data label), + * `'right'` (pie on the right side of the data label) or + * `'center'` (data label overlaps the pie). + * + * - Object that holds the information about the position of the + * connector. Its `touchingSliceAt` porperty tells the position + * of the place where the connector touches the slice. + * + * - Data label options + * + * The function has to return an SVG path definition in array form + * (see the example). + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorshape-string/ + * connectorShape is a String + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorshape-function/ + * connectorShape is a function + * + * @type {string|Function} + * @since 7.0.0 + * @product highcharts + */ + connectorShape: 'fixedOffset', + /** + * The width of the line connecting the data label to the pie slice. + * + * In styled mode, the connector stroke width is given in the + * `.highcharts-data-label-connector` class. + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorwidth-disabled/ + * Disable the connector + * @sample {highcharts} highcharts/css/pie-point/ + * Styled connectors + * + * @type {number} + * @default 1 + * @since 2.1 + * @product highcharts + * @apioption plotOptions.pie.dataLabels.connectorWidth + */ + /** + * Works only if `connectorShape` is `'crookedLine'`. It defines how + * far from the vertical plot edge the coonnector path should be + * crooked. + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-crookdistance/ + * crookDistance set to 90% + * + * @since 7.0.0 + * @product highcharts + */ + crookDistance: '70%', + /** + * The distance of the data label from the pie's edge. Negative + * numbers put the data label on top of the pie slices. Can also be + * defined as a percentage of pie's radius. Connectors are only + * shown for data labels outside the pie. + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-distance/ + * Data labels on top of the pie + * + * @type {number|string} + * @since 2.1 + * @product highcharts + */ + distance: 30, + enabled: true, + formatter: function () { + return this.point.isNull ? void 0 : this.point.name; + }, + /** + * Whether to render the connector as a soft arc or a line with + * sharp break. Works only if `connectorShape` equals to + * `fixedOffset`. + * + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-softconnector-true/ + * Soft + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-softconnector-false/ + * Non soft + * + * @since 2.1.7 + * @product highcharts + */ + softConnector: true, + /** + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow + * Long labels truncated with an ellipsis + * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow-wrap + * Long labels are wrapped + * + * @type {Highcharts.CSSObject} + * @apioption plotOptions.pie.dataLabels.style + */ + x: 0 + }, + /** + * If the total sum of the pie's values is 0, the series is represented + * as an empty circle . The `fillColor` option defines the color of that + * circle. Use [pie.borderWidth](#plotOptions.pie.borderWidth) to set + * the border thickness. + * + * @sample {highcharts} highcharts/plotoptions/pie-emptyseries/ + * Empty pie series + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @private + */ + fillColor: void 0, + /** + * The end angle of the pie in degrees where 0 is top and 90 is right. + * Defaults to `startAngle` plus 360. + * + * @sample {highcharts} highcharts/demo/pie-semi-circle/ + * Semi-circle donut + * + * @type {number} + * @since 1.3.6 + * @product highcharts + * @apioption plotOptions.pie.endAngle + */ + /** + * Equivalent to [chart.ignoreHiddenSeries](#chart.ignoreHiddenSeries), + * this option tells whether the series shall be redrawn as if the + * hidden point were `null`. + * + * The default value changed from `false` to `true` with Highcharts + * 3.0. + * + * @sample {highcharts} highcharts/plotoptions/pie-ignorehiddenpoint/ + * True, the hiddden point is ignored + * + * @since 2.3.0 + * @product highcharts + * + * @private + */ + ignoreHiddenPoint: true, + /** + * @ignore-option + * + * @private + */ + inactiveOtherPoints: true, + /** + * The size of the inner diameter for the pie. A size greater than 0 + * renders a donut chart. Can be a percentage or pixel value. + * Percentages are relative to the pie size. Pixel values are given as + * integers. + * + * + * Note: in Highcharts < 4.1.2, the percentage was relative to the plot + * area, not the pie size. + * + * @sample {highcharts} highcharts/plotoptions/pie-innersize-80px/ + * 80px inner size + * @sample {highcharts} highcharts/plotoptions/pie-innersize-50percent/ + * 50% of the plot area + * @sample {highcharts} highcharts/demo/3d-pie-donut/ + * 3D donut + * + * @type {number|string} + * @default 0 + * @since 2.0 + * @product highcharts + * @apioption plotOptions.pie.innerSize + */ + /** + * @ignore-option + * + * @private + */ + legendType: 'point', + /** + * @ignore-option + * + * @private + */ + marker: null, + /** + * The minimum size for a pie in response to auto margins. The pie will + * try to shrink to make room for data labels in side the plot area, + * but only to this size. + * + * @type {number|string} + * @default 80 + * @since 3.0 + * @product highcharts + * @apioption plotOptions.pie.minSize + */ + /** + * The diameter of the pie relative to the plot area. Can be a + * percentage or pixel value. Pixel values are given as integers. The + * default behaviour (as of 3.0) is to scale to the plot area and give + * room for data labels within the plot area. + * [slicedOffset](#plotOptions.pie.slicedOffset) is also included in the + * default size calculation. As a consequence, the size of the pie may + * vary when points are updated and data labels more around. In that + * case it is best to set a fixed value, for example `"75%"`. + * + * @sample {highcharts} highcharts/plotoptions/pie-size/ + * Smaller pie + * + * @type {number|string|null} + * @product highcharts + * + * @private + */ + size: null, + /** + * Whether to display this particular series or series type in the + * legend. Since 2.1, pies are not shown in the legend by default. + * + * @sample {highcharts} highcharts/plotoptions/series-showinlegend/ + * One series in the legend, one hidden + * + * @product highcharts + * + * @private + */ + showInLegend: false, + /** + * If a point is sliced, moved out from the center, how many pixels + * should it be moved?. + * + * @sample {highcharts} highcharts/plotoptions/pie-slicedoffset-20/ + * 20px offset + * + * @product highcharts + * + * @private + */ + slicedOffset: 10, + /** + * The start angle of the pie slices in degrees where 0 is top and 90 + * right. + * + * @sample {highcharts} highcharts/plotoptions/pie-startangle-90/ + * Start from right + * + * @type {number} + * @default 0 + * @since 2.3.4 + * @product highcharts + * @apioption plotOptions.pie.startAngle + */ + /** + * Sticky tracking of mouse events. When true, the `mouseOut` event + * on a series isn't triggered until the mouse moves over another + * series, or out of the plot area. When false, the `mouseOut` event on + * a series is triggered when the mouse leaves the area around the + * series' graph or markers. This also implies the tooltip. When + * `stickyTracking` is false and `tooltip.shared` is false, the tooltip + * will be hidden when moving the mouse between series. + * + * @product highcharts + * + * @private + */ + stickyTracking: false, + tooltip: { + followPointer: true + }, + /** + * The color of the border surrounding each slice. When `null`, the + * border takes the same color as the slice fill. This can be used + * together with a `borderWidth` to fill drawing gaps created by + * antialiazing artefacts in borderless pies. + * + * In styled mode, the border stroke is given in the `.highcharts-point` + * class. + * + * @sample {highcharts} highcharts/plotoptions/pie-bordercolor-black/ + * Black border + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #ffffff + * @product highcharts + * + * @private + */ + borderColor: '#ffffff', + /** + * The width of the border surrounding each slice. + * + * When setting the border width to 0, there may be small gaps between + * the slices due to SVG antialiasing artefacts. To work around this, + * keep the border width at 0.5 or 1, but set the `borderColor` to + * `null` instead. + * + * In styled mode, the border stroke width is given in the + * `.highcharts-point` class. + * + * @sample {highcharts} highcharts/plotoptions/pie-borderwidth/ + * 3px border + * + * @product highcharts + * + * @private + */ + borderWidth: 1, + /** + * @ignore-options + * @private + */ + lineWidth: void 0, + states: { + /** + * @extends plotOptions.series.states.hover + * @excluding marker, lineWidth, lineWidthPlus + * @product highcharts + */ + hover: { + /** + * How much to brighten the point on interaction. Requires the + * main color to be defined in hex or rgb(a) format. + * + * In styled mode, the hover brightness is by default replaced + * by a fill-opacity given in the `.highcharts-point-hover` + * class. + * + * @sample {highcharts} highcharts/plotoptions/pie-states-hover-brightness/ + * Brightened by 0.5 + * + * @product highcharts + */ + brightness: 0.1 + } + } + }, + /* eslint-disable valid-jsdoc */ + /** + * @lends seriesTypes.pie.prototype + */ + { + isCartesian: false, + requireSorting: false, + directTouch: true, + noSharedTooltip: true, + trackerGroups: ['group', 'dataLabelsGroup'], + axisTypes: [], + pointAttribs: seriesTypes.column.prototype.pointAttribs, + /** + * Animate the pies in + * + * @private + * @function Highcharts.seriesTypes.pie#animate + * + * @param {boolean} [init=false] + */ + animate: function (init) { + var series = this, points = series.points, startAngleRad = series.startAngleRad; + if (!init) { + points.forEach(function (point) { + var graphic = point.graphic, args = point.shapeArgs; + if (graphic && args) { + // start values + graphic.attr({ + // animate from inner radius (#779) + r: pick(point.startR, (series.center && series.center[3] / 2)), + start: startAngleRad, + end: startAngleRad + }); + // animate + graphic.animate({ + r: args.r, + start: args.start, + end: args.end + }, series.options.animation); + } + }); + } + }, + // Define hasData function for non-cartesian series. + // Returns true if the series has points at all. + hasData: function () { + return !!this.processedXData.length; // != 0 + }, + /** + * Recompute total chart sum and update percentages of points. + * + * @private + * @function Highcharts.seriesTypes.pie#updateTotals + * @return {void} + */ + updateTotals: function () { + var i, total = 0, points = this.points, len = points.length, point, ignoreHiddenPoint = this.options.ignoreHiddenPoint; + // Get the total sum + for (i = 0; i < len; i++) { + point = points[i]; + total += (ignoreHiddenPoint && !point.visible) ? + 0 : + point.isNull ? + 0 : + point.y; + } + this.total = total; + // Set each point's properties + for (i = 0; i < len; i++) { + point = points[i]; + point.percentage = + (total > 0 && (point.visible || !ignoreHiddenPoint)) ? + point.y / total * 100 : + 0; + point.total = total; + } + }, + /** + * Extend the generatePoints method by adding total and percentage + * properties to each point + * + * @private + * @function Highcharts.seriesTypes.pie#generatePoints + * @return {void} + */ + generatePoints: function () { + Series.prototype.generatePoints.call(this); + this.updateTotals(); + }, + /** + * Utility for getting the x value from a given y, used for + * anticollision logic in data labels. Added point for using specific + * points' label distance. + * @private + */ + getX: function (y, left, point) { + var center = this.center, + // Variable pie has individual radius + radius = this.radii ? + this.radii[point.index] : + center[2] / 2, angle, x; + angle = Math.asin(clamp((y - center[1]) / (radius + point.labelDistance), -1, 1)); + x = center[0] + + (left ? -1 : 1) * + (Math.cos(angle) * (radius + point.labelDistance)) + + (point.labelDistance > 0 ? + (left ? -1 : 1) * this.options.dataLabels.padding : + 0); + return x; + }, + /** + * Do translation for pie slices + * + * @private + * @function Highcharts.seriesTypes.pie#translate + * @param {Array} [positions] + * @return {void} + */ + translate: function (positions) { + this.generatePoints(); + var series = this, cumulative = 0, precision = 1000, // issue #172 + options = series.options, slicedOffset = options.slicedOffset, connectorOffset = slicedOffset + (options.borderWidth || 0), finalConnectorOffset, start, end, angle, radians = getStartAndEndRadians(options.startAngle, options.endAngle), startAngleRad = series.startAngleRad = radians.start, endAngleRad = series.endAngleRad = radians.end, circ = endAngleRad - startAngleRad, // 2 * Math.PI, + points = series.points, + // the x component of the radius vector for a given point + radiusX, radiusY, labelDistance = options.dataLabels.distance, ignoreHiddenPoint = options.ignoreHiddenPoint, i, len = points.length, point; + // Get positions - either an integer or a percentage string must be + // given. If positions are passed as a parameter, we're in a + // recursive loop for adjusting space for data labels. + if (!positions) { + series.center = positions = series.getCenter(); + } + // Calculate the geometry for each point + for (i = 0; i < len; i++) { + point = points[i]; + // set start and end angle + start = startAngleRad + (cumulative * circ); + if (!ignoreHiddenPoint || point.visible) { + cumulative += point.percentage / 100; + } + end = startAngleRad + (cumulative * circ); + // set the shape + point.shapeType = 'arc'; + point.shapeArgs = { + x: positions[0], + y: positions[1], + r: positions[2] / 2, + innerR: positions[3] / 2, + start: Math.round(start * precision) / precision, + end: Math.round(end * precision) / precision + }; + // Used for distance calculation for specific point. + point.labelDistance = pick((point.options.dataLabels && + point.options.dataLabels.distance), labelDistance); + // Compute point.labelDistance if it's defined as percentage + // of slice radius (#8854) + point.labelDistance = relativeLength(point.labelDistance, point.shapeArgs.r); + // Saved for later dataLabels distance calculation. + series.maxLabelDistance = Math.max(series.maxLabelDistance || 0, point.labelDistance); + // The angle must stay within -90 and 270 (#2645) + angle = (end + start) / 2; + if (angle > 1.5 * Math.PI) { + angle -= 2 * Math.PI; + } + else if (angle < -Math.PI / 2) { + angle += 2 * Math.PI; + } + // Center for the sliced out slice + point.slicedTranslation = { + translateX: Math.round(Math.cos(angle) * slicedOffset), + translateY: Math.round(Math.sin(angle) * slicedOffset) + }; + // set the anchor point for tooltips + radiusX = Math.cos(angle) * positions[2] / 2; + radiusY = Math.sin(angle) * positions[2] / 2; + point.tooltipPos = [ + positions[0] + radiusX * 0.7, + positions[1] + radiusY * 0.7 + ]; + point.half = angle < -Math.PI / 2 || angle > Math.PI / 2 ? + 1 : + 0; + point.angle = angle; + // Set the anchor point for data labels. Use point.labelDistance + // instead of labelDistance // #1174 + // finalConnectorOffset - not override connectorOffset value. + finalConnectorOffset = Math.min(connectorOffset, point.labelDistance / 5); // #1678 + point.labelPosition = { + natural: { + // initial position of the data label - it's utilized for + // finding the final position for the label + x: positions[0] + radiusX + Math.cos(angle) * + point.labelDistance, + y: positions[1] + radiusY + Math.sin(angle) * + point.labelDistance + }, + 'final': { + // used for generating connector path - + // initialized later in drawDataLabels function + // x: undefined, + // y: undefined + }, + // left - pie on the left side of the data label + // right - pie on the right side of the data label + // center - data label overlaps the pie + alignment: point.labelDistance < 0 ? + 'center' : point.half ? 'right' : 'left', + connectorPosition: { + breakAt: { + x: positions[0] + radiusX + Math.cos(angle) * + finalConnectorOffset, + y: positions[1] + radiusY + Math.sin(angle) * + finalConnectorOffset + }, + touchingSliceAt: { + x: positions[0] + radiusX, + y: positions[1] + radiusY + } + } + }; + } + fireEvent(series, 'afterTranslate'); + }, + /** + * Called internally to draw auxiliary graph in pie-like series in + * situtation when the default graph is not sufficient enough to present + * the data well. Auxiliary graph is saved in the same object as + * regular graph. + * + * @private + * @function Highcharts.seriesTypes.pie#drawEmpty + */ + drawEmpty: function () { + var centerX, centerY, options = this.options; + // Draw auxiliary graph if there're no visible points. + if (this.total === 0) { + centerX = this.center[0]; + centerY = this.center[1]; + if (!this.graph) { // Auxiliary graph doesn't exist yet. + this.graph = this.chart.renderer.circle(centerX, centerY, 0) + .addClass('highcharts-graph') + .add(this.group); + } + this.graph.animate({ + 'stroke-width': options.borderWidth, + cx: centerX, + cy: centerY, + r: this.center[2] / 2, + fill: options.fillColor || 'none', + stroke: options.color || + '#cccccc' + }, this.options.animation); + } + else if (this.graph) { // Destroy the graph object. + this.graph = this.graph.destroy(); + } + }, + /** + * Draw the data points + * + * @private + * @function Highcharts.seriesTypes.pie#drawPoints + * @return {void} + */ + redrawPoints: function () { + var series = this, chart = series.chart, renderer = chart.renderer, groupTranslation, graphic, pointAttr, shapeArgs, shadow = series.options.shadow; + this.drawEmpty(); + if (shadow && !series.shadowGroup && !chart.styledMode) { + series.shadowGroup = renderer.g('shadow') + .attr({ zIndex: -1 }) + .add(series.group); + } + // draw the slices + series.points.forEach(function (point) { + var animateTo = {}; + graphic = point.graphic; + if (!point.isNull && graphic) { + shapeArgs = point.shapeArgs; + // If the point is sliced, use special translation, else use + // plot area translation + groupTranslation = point.getTranslate(); + if (!chart.styledMode) { + // Put the shadow behind all points + var shadowGroup = point.shadowGroup; + if (shadow && !shadowGroup) { + shadowGroup = point.shadowGroup = renderer + .g('shadow') + .add(series.shadowGroup); + } + if (shadowGroup) { + shadowGroup.attr(groupTranslation); + } + pointAttr = series.pointAttribs(point, (point.selected && 'select')); + } + // Draw the slice + if (!point.delayedRendering) { + graphic + .setRadialReference(series.center); + if (!chart.styledMode) { + merge(true, animateTo, pointAttr); + } + merge(true, animateTo, shapeArgs, groupTranslation); + graphic.animate(animateTo); + } + else { + graphic + .setRadialReference(series.center) + .attr(shapeArgs) + .attr(groupTranslation); + if (!chart.styledMode) { + graphic + .attr(pointAttr) + .attr({ 'stroke-linejoin': 'round' }) + .shadow(shadow, shadowGroup); + } + point.delayedRendering = false; + } + graphic.attr({ + visibility: point.visible ? 'inherit' : 'hidden' + }); + graphic.addClass(point.getClassName()); + } + else if (graphic) { + point.graphic = graphic.destroy(); + } + }); + }, + /** + * Slices in pie chart are initialized in DOM, but it's shapes and + * animations are normally run in `drawPoints()`. + * @private + */ + drawPoints: function () { + var renderer = this.chart.renderer; + this.points.forEach(function (point) { + // When updating a series between 2d and 3d or cartesian and + // polar, the shape type changes. + if (point.graphic && point.hasNewShapeType()) { + point.graphic = point.graphic.destroy(); + } + if (!point.graphic) { + point.graphic = renderer[point.shapeType](point.shapeArgs) + .add(point.series.group); + point.delayedRendering = true; + } + }); + }, + /** + * @private + * @deprecated + * @function Highcharts.seriesTypes.pie#searchPoint + */ + searchPoint: noop, + /** + * Utility for sorting data labels + * + * @private + * @function Highcharts.seriesTypes.pie#sortByAngle + * @param {Array} points + * @param {number} sign + * @return {void} + */ + sortByAngle: function (points, sign) { + points.sort(function (a, b) { + return ((typeof a.angle !== 'undefined') && + (b.angle - a.angle) * sign); + }); + }, + /** + * Use a simple symbol from LegendSymbolMixin. + * + * @private + * @borrows Highcharts.LegendSymbolMixin.drawRectangle as Highcharts.seriesTypes.pie#drawLegendSymbol + */ + drawLegendSymbol: LegendSymbolMixin.drawRectangle, + /** + * Use the getCenter method from drawLegendSymbol. + * + * @private + * @borrows Highcharts.CenteredSeriesMixin.getCenter as Highcharts.seriesTypes.pie#getCenter + */ + getCenter: CenteredSeriesMixin.getCenter, + /** + * Pies don't have point marker symbols. + * + * @deprecated + * @private + * @function Highcharts.seriesTypes.pie#getSymbol + */ + getSymbol: noop, + /** + * @private + * @type {null} + */ + drawGraph: null + }, + /** + * @lends seriesTypes.pie.prototype.pointClass.prototype + */ + { + /** + * Initialize the pie slice + * + * @private + * @function Highcharts.seriesTypes.pie#pointClass#init + * @return {Highcharts.Point} + */ + init: function () { + Point.prototype.init.apply(this, arguments); + var point = this, toggleSlice; + point.name = pick(point.name, 'Slice'); + // add event listener for select + toggleSlice = function (e) { + point.slice(e.type === 'select'); + }; + addEvent(point, 'select', toggleSlice); + addEvent(point, 'unselect', toggleSlice); + return point; + }, + /** + * Negative points are not valid (#1530, #3623, #5322) + * + * @private + * @function Highcharts.seriesTypes.pie#pointClass#isValid + * @return {boolean} + */ + isValid: function () { + return isNumber(this.y) && this.y >= 0; + }, + /** + * Toggle the visibility of the pie slice + * + * @private + * @function Highcharts.seriesTypes.pie#pointClass#setVisible + * @param {boolean} vis + * Whether to show the slice or not. If undefined, the visibility + * is toggled. + * @param {boolean} [redraw=false] + * @return {void} + */ + setVisible: function (vis, redraw) { + var point = this, series = point.series, chart = series.chart, ignoreHiddenPoint = series.options.ignoreHiddenPoint; + redraw = pick(redraw, ignoreHiddenPoint); + if (vis !== point.visible) { + // If called without an argument, toggle visibility + point.visible = point.options.visible = vis = + typeof vis === 'undefined' ? !point.visible : vis; + // update userOptions.data + series.options.data[series.data.indexOf(point)] = + point.options; + // Show and hide associated elements. This is performed + // regardless of redraw or not, because chart.redraw only + // handles full series. + ['graphic', 'dataLabel', 'connector', 'shadowGroup'].forEach(function (key) { + if (point[key]) { + point[key][vis ? 'show' : 'hide'](true); + } + }); + if (point.legendItem) { + chart.legend.colorizeItem(point, vis); + } + // #4170, hide halo after hiding point + if (!vis && point.state === 'hover') { + point.setState(''); + } + // Handle ignore hidden slices + if (ignoreHiddenPoint) { + series.isDirty = true; + } + if (redraw) { + chart.redraw(); + } + } + }, + /** + * Set or toggle whether the slice is cut out from the pie + * + * @private + * @function Highcharts.seriesTypes.pie#pointClass#slice + * @param {boolean} sliced + * When undefined, the slice state is toggled. + * @param {boolean} redraw + * Whether to redraw the chart. True by default. + * @param {boolean|Highcharts.AnimationOptionsObject} + * Animation options. + * @return {void} + */ + slice: function (sliced, redraw, animation) { + var point = this, series = point.series, chart = series.chart; + setAnimation(animation, chart); + // redraw is true by default + redraw = pick(redraw, true); + /** + * Pie series only. Whether to display a slice offset from the + * center. + * @name Highcharts.Point#sliced + * @type {boolean|undefined} + */ + // if called without an argument, toggle + point.sliced = point.options.sliced = sliced = + defined(sliced) ? sliced : !point.sliced; + // update userOptions.data + series.options.data[series.data.indexOf(point)] = + point.options; + if (point.graphic) { + point.graphic.animate(this.getTranslate()); + } + if (point.shadowGroup) { + point.shadowGroup.animate(this.getTranslate()); + } + }, + /** + * @private + * @function Highcharts.seriesTypes.pie#pointClass#getTranslate + * @return {Highcharts.TranslationAttributes} + */ + getTranslate: function () { + return this.sliced ? this.slicedTranslation : { + translateX: 0, + translateY: 0 + }; + }, + /** + * @private + * @function Highcharts.seriesTypes.pie#pointClass#haloPath + * @param {number} size + * @return {Highcharts.SVGPathArray} + */ + haloPath: function (size) { + var shapeArgs = this.shapeArgs; + return this.sliced || !this.visible ? + [] : + this.series.chart.renderer.symbols.arc(shapeArgs.x, shapeArgs.y, shapeArgs.r + size, shapeArgs.r + size, { + // Substract 1px to ensure the background is not bleeding + // through between the halo and the slice (#7495). + innerR: shapeArgs.r - 1, + start: shapeArgs.start, + end: shapeArgs.end + }); + }, + connectorShapes: { + // only one available before v7.0.0 + fixedOffset: function (labelPosition, connectorPosition, options) { + var breakAt = connectorPosition.breakAt, touchingSliceAt = connectorPosition.touchingSliceAt, lineSegment = options.softConnector ? [ + 'C', + // 1st control point (of the curve) + labelPosition.x + + // 5 gives the connector a little horizontal bend + (labelPosition.alignment === 'left' ? -5 : 5), + labelPosition.y, + 2 * breakAt.x - touchingSliceAt.x, + 2 * breakAt.y - touchingSliceAt.y, + breakAt.x, + breakAt.y // + ] : [ + 'L', + breakAt.x, + breakAt.y + ]; + // assemble the path + return ([ + ['M', labelPosition.x, labelPosition.y], + lineSegment, + ['L', touchingSliceAt.x, touchingSliceAt.y] + ]); + }, + straight: function (labelPosition, connectorPosition) { + var touchingSliceAt = connectorPosition.touchingSliceAt; + // direct line to the slice + return [ + ['M', labelPosition.x, labelPosition.y], + ['L', touchingSliceAt.x, touchingSliceAt.y] + ]; + }, + crookedLine: function (labelPosition, connectorPosition, options) { + var touchingSliceAt = connectorPosition.touchingSliceAt, series = this.series, pieCenterX = series.center[0], plotWidth = series.chart.plotWidth, plotLeft = series.chart.plotLeft, alignment = labelPosition.alignment, radius = this.shapeArgs.r, crookDistance = relativeLength(// % to fraction + options.crookDistance, 1), crookX = alignment === 'left' ? + pieCenterX + radius + (plotWidth + plotLeft - + pieCenterX - radius) * (1 - crookDistance) : + plotLeft + (pieCenterX - radius) * crookDistance, segmentWithCrook = [ + 'L', + crookX, + labelPosition.y + ], useCrook = true; + // crookedLine formula doesn't make sense if the path overlaps + // the label - use straight line instead in that case + if (alignment === 'left' ? + (crookX > labelPosition.x || crookX < touchingSliceAt.x) : + (crookX < labelPosition.x || crookX > touchingSliceAt.x)) { + useCrook = false; + } + // assemble the path + var path = [ + ['M', labelPosition.x, labelPosition.y] + ]; + if (useCrook) { + path.push(segmentWithCrook); + } + path.push(['L', touchingSliceAt.x, touchingSliceAt.y]); + return path; + } + }, + /** + * Extendable method for getting the path of the connector between the + * data label and the pie slice. + */ + getConnectorPath: function () { + var labelPosition = this.labelPosition, options = this.series.options.dataLabels, connectorShape = options.connectorShape, predefinedShapes = this.connectorShapes; + // find out whether to use the predefined shape + if (predefinedShapes[connectorShape]) { + connectorShape = predefinedShapes[connectorShape]; + } + return connectorShape.call(this, { + // pass simplified label position object for user's convenience + x: labelPosition.final.x, + y: labelPosition.final.y, + alignment: labelPosition.alignment + }, labelPosition.connectorPosition, options); + } + } + /* eslint-enable valid-jsdoc */ + ); + /** + * A `pie` series. If the [type](#series.pie.type) option is not specified, + * it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.pie + * @excluding dataParser, dataURL, stack, xAxis, yAxis, dataSorting, step + * @product highcharts + * @apioption series.pie + */ + /** + * An array of data points for the series. For the `pie` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.pie.turboThreshold), + * this option is not available. + * ```js + * data: [{ + * y: 1, + * name: "Point2", + * color: "#00FF00" + * }, { + * y: 7, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @excluding marker, x + * @product highcharts + * @apioption series.pie.data + */ + /** + * @type {Highcharts.SeriesPieDataLabelsOptionsObject} + * @product highcharts + * @apioption series.pie.data.dataLabels + */ + /** + * The sequential index of the data point in the legend. + * + * @type {number} + * @product highcharts + * @apioption series.pie.data.legendIndex + */ + /** + * Whether to display a slice offset from the center. + * + * @sample {highcharts} highcharts/point/sliced/ + * One sliced point + * + * @type {boolean} + * @product highcharts + * @apioption series.pie.data.sliced + */ + /** + * @excluding legendItemClick + * @product highcharts + * @apioption series.pie.events + */ + ''; // placeholder for transpiled doclets above + + }); + _registerModule(_modules, 'parts/DataLabels.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Callback JavaScript function to format the data label as a string. Note that + * if a `format` is defined, the format takes precedence and the formatter is + * ignored. + * + * @callback Highcharts.DataLabelsFormatterCallbackFunction + * + * @param {Highcharts.PointLabelObject} this + * Data label context to format + * + * @param {Highcharts.DataLabelsOptions} options + * [API options](/highcharts/plotOptions.series.dataLabels) of the data label + * + * @return {number|string|null|undefined} + * Formatted data label text + */ + /** + * Values for handling data labels that flow outside the plot area. + * + * @typedef {"allow"|"justify"} Highcharts.DataLabelsOverflowValue + */ + var animObject = U.animObject, arrayMax = U.arrayMax, clamp = U.clamp, defined = U.defined, extend = U.extend, fireEvent = U.fireEvent, format = U.format, isArray = U.isArray, merge = U.merge, objectEach = U.objectEach, pick = U.pick, relativeLength = U.relativeLength, splat = U.splat, stableSort = U.stableSort; + var noop = H.noop, Series = H.Series, seriesTypes = H.seriesTypes; + /* eslint-disable valid-jsdoc */ + /** + * General distribution algorithm for distributing labels of differing size + * along a confined length in two dimensions. The algorithm takes an array of + * objects containing a size, a target and a rank. It will place the labels as + * close as possible to their targets, skipping the lowest ranked labels if + * necessary. + * + * @private + * @function Highcharts.distribute + * @param {Highcharts.DataLabelsBoxArray} boxes + * @param {number} len + * @param {number} [maxDistance] + * @return {void} + */ + H.distribute = function (boxes, len, maxDistance) { + var i, overlapping = true, origBoxes = boxes, // Original array will be altered with added .pos + restBoxes = [], // The outranked overshoot + box, target, total = 0, reducedLen = origBoxes.reducedLen || len; + /** + * @private + */ + function sortByTarget(a, b) { + return a.target - b.target; + } + // If the total size exceeds the len, remove those boxes with the lowest + // rank + i = boxes.length; + while (i--) { + total += boxes[i].size; + } + // Sort by rank, then slice away overshoot + if (total > reducedLen) { + stableSort(boxes, function (a, b) { + return (b.rank || 0) - (a.rank || 0); + }); + i = 0; + total = 0; + while (total <= reducedLen) { + total += boxes[i].size; + i++; + } + restBoxes = boxes.splice(i - 1, boxes.length); + } + // Order by target + stableSort(boxes, sortByTarget); + // So far we have been mutating the original array. Now + // create a copy with target arrays + boxes = boxes.map(function (box) { + return { + size: box.size, + targets: [box.target], + align: pick(box.align, 0.5) + }; + }); + while (overlapping) { + // Initial positions: target centered in box + i = boxes.length; + while (i--) { + box = boxes[i]; + // Composite box, average of targets + target = (Math.min.apply(0, box.targets) + + Math.max.apply(0, box.targets)) / 2; + box.pos = clamp(target - box.size * box.align, 0, len - box.size); + } + // Detect overlap and join boxes + i = boxes.length; + overlapping = false; + while (i--) { + // Overlap + if (i > 0 && + boxes[i - 1].pos + boxes[i - 1].size > + boxes[i].pos) { + // Add this size to the previous box + boxes[i - 1].size += boxes[i].size; + boxes[i - 1].targets = boxes[i - 1] + .targets + .concat(boxes[i].targets); + boxes[i - 1].align = 0.5; + // Overlapping right, push left + if (boxes[i - 1].pos + boxes[i - 1].size > len) { + boxes[i - 1].pos = len - boxes[i - 1].size; + } + boxes.splice(i, 1); // Remove this item + overlapping = true; + } + } + } + // Add the rest (hidden boxes) + origBoxes.push.apply(origBoxes, restBoxes); + // Now the composite boxes are placed, we need to put the original boxes + // within them + i = 0; + boxes.some(function (box) { + var posInCompositeBox = 0; + if (box.targets.some(function () { + origBoxes[i].pos = box.pos + posInCompositeBox; + // If the distance between the position and the target exceeds + // maxDistance, abort the loop and decrease the length in increments + // of 10% to recursively reduce the number of visible boxes by + // rank. Once all boxes are within the maxDistance, we're good. + if (typeof maxDistance !== 'undefined' && + Math.abs(origBoxes[i].pos - origBoxes[i].target) > maxDistance) { + // Reset the positions that are already set + origBoxes.slice(0, i + 1).forEach(function (box) { + delete box.pos; + }); + // Try with a smaller length + origBoxes.reducedLen = + (origBoxes.reducedLen || len) - (len * 0.1); + // Recurse + if (origBoxes.reducedLen > len * 0.1) { + H.distribute(origBoxes, len, maxDistance); + } + // Exceeded maxDistance => abort + return true; + } + posInCompositeBox += origBoxes[i].size; + i++; + })) { + // Exceeded maxDistance => abort + return true; + } + }); + // Add the rest (hidden) boxes and sort by target + stableSort(origBoxes, sortByTarget); + }; + /** + * Draw the data labels + * + * @private + * @function Highcharts.Series#drawDataLabels + * @return {void} + * @fires Highcharts.Series#event:afterDrawDataLabels + */ + Series.prototype.drawDataLabels = function () { + var series = this, chart = series.chart, seriesOptions = series.options, seriesDlOptions = seriesOptions.dataLabels, points = series.points, pointOptions, hasRendered = series.hasRendered || 0, dataLabelsGroup, seriesAnimDuration = animObject(seriesOptions.animation).duration, fadeInDuration = Math.min(seriesAnimDuration, 200), defer = !chart.renderer.forExport && pick(seriesDlOptions.defer, fadeInDuration > 0), renderer = chart.renderer; + /** + * Handle the dataLabels.filter option. + * @private + */ + function applyFilter(point, options) { + var filter = options.filter, op, prop, val; + if (filter) { + op = filter.operator; + prop = point[filter.property]; + val = filter.value; + if ((op === '>' && prop > val) || + (op === '<' && prop < val) || + (op === '>=' && prop >= val) || + (op === '<=' && prop <= val) || + (op === '==' && prop == val) || // eslint-disable-line eqeqeq + (op === '===' && prop === val)) { + return true; + } + return false; + } + return true; + } + /** + * Merge two objects that can be arrays. If one of them is an array, the + * other is merged into each element. If both are arrays, each element is + * merged by index. If neither are arrays, we use normal merge. + * @private + */ + function mergeArrays(one, two) { + var res = [], i; + if (isArray(one) && !isArray(two)) { + res = one.map(function (el) { + return merge(el, two); + }); + } + else if (isArray(two) && !isArray(one)) { + res = two.map(function (el) { + return merge(one, el); + }); + } + else if (!isArray(one) && !isArray(two)) { + res = merge(one, two); + } + else { + i = Math.max(one.length, two.length); + while (i--) { + res[i] = merge(one[i], two[i]); + } + } + return res; + } + // Merge in plotOptions.dataLabels for series + seriesDlOptions = mergeArrays(mergeArrays(chart.options.plotOptions && + chart.options.plotOptions.series && + chart.options.plotOptions.series.dataLabels, chart.options.plotOptions && + chart.options.plotOptions[series.type] && + chart.options.plotOptions[series.type].dataLabels), seriesDlOptions); + fireEvent(this, 'drawDataLabels'); + if (isArray(seriesDlOptions) || + seriesDlOptions.enabled || + series._hasPointLabels) { + // Create a separate group for the data labels to avoid rotation + dataLabelsGroup = series.plotGroup('dataLabelsGroup', 'data-labels', defer && !hasRendered ? 'hidden' : 'inherit', // #5133, #10220 + seriesDlOptions.zIndex || 6); + if (defer) { + dataLabelsGroup.attr({ opacity: +hasRendered }); // #3300 + if (!hasRendered) { + setTimeout(function () { + var group = series.dataLabelsGroup; + if (group) { + if (series.visible) { // #2597, #3023, #3024 + dataLabelsGroup.show(true); + } + group[seriesOptions.animation ? 'animate' : 'attr']({ opacity: 1 }, { duration: fadeInDuration }); + } + }, seriesAnimDuration - fadeInDuration); + } + } + // Make the labels for each point + points.forEach(function (point) { + // Merge in series options for the point. + // @note dataLabelAttribs (like pointAttribs) would eradicate + // the need for dlOptions, and simplify the section below. + pointOptions = splat(mergeArrays(seriesDlOptions, point.dlOptions || // dlOptions is used in treemaps + (point.options && point.options.dataLabels))); + // Handle each individual data label for this point + pointOptions.forEach(function (labelOptions, i) { + // Options for one datalabel + var labelEnabled = (labelOptions.enabled && + // #2282, #4641, #7112, #10049 + (!point.isNull || point.dataLabelOnNull) && + applyFilter(point, labelOptions)), labelConfig, formatString, labelText, style, rotation, attr, dataLabel = point.dataLabels ? point.dataLabels[i] : + point.dataLabel, connector = point.connectors ? point.connectors[i] : + point.connector, labelDistance = pick(labelOptions.distance, point.labelDistance), isNew = !dataLabel; + if (labelEnabled) { + // Create individual options structure that can be extended + // without affecting others + labelConfig = point.getLabelConfig(); + formatString = pick(labelOptions[point.formatPrefix + 'Format'], labelOptions.format); + labelText = defined(formatString) ? + format(formatString, labelConfig, chart) : + (labelOptions[point.formatPrefix + 'Formatter'] || + labelOptions.formatter).call(labelConfig, labelOptions); + style = labelOptions.style; + rotation = labelOptions.rotation; + if (!chart.styledMode) { + // Determine the color + style.color = pick(labelOptions.color, style.color, series.color, '#000000'); + // Get automated contrast color + if (style.color === 'contrast') { + point.contrastColor = renderer.getContrast((point.color || series.color)); + style.color = (!defined(labelDistance) && + labelOptions.inside) || + labelDistance < 0 || + !!seriesOptions.stacking ? + point.contrastColor : + '#000000'; + } + else { + delete point.contrastColor; + } + if (seriesOptions.cursor) { + style.cursor = seriesOptions.cursor; + } + } + attr = { + r: labelOptions.borderRadius || 0, + rotation: rotation, + padding: labelOptions.padding, + zIndex: 1 + }; + if (!chart.styledMode) { + attr.fill = labelOptions.backgroundColor; + attr.stroke = labelOptions.borderColor; + attr['stroke-width'] = labelOptions.borderWidth; + } + // Remove unused attributes (#947) + objectEach(attr, function (val, name) { + if (typeof val === 'undefined') { + delete attr[name]; + } + }); + } + // If the point is outside the plot area, destroy it. #678, #820 + if (dataLabel && (!labelEnabled || !defined(labelText))) { + point.dataLabel = + point.dataLabel && point.dataLabel.destroy(); + if (point.dataLabels) { + // Remove point.dataLabels if this was the last one + if (point.dataLabels.length === 1) { + delete point.dataLabels; + } + else { + delete point.dataLabels[i]; + } + } + if (!i) { + delete point.dataLabel; + } + if (connector) { + point.connector = point.connector.destroy(); + if (point.connectors) { + // Remove point.connectors if this was the last one + if (point.connectors.length === 1) { + delete point.connectors; + } + else { + delete point.connectors[i]; + } + } + } + // Individual labels are disabled if the are explicitly disabled + // in the point options, or if they fall outside the plot area. + } + else if (labelEnabled && defined(labelText)) { + if (!dataLabel) { + // Create new label element + point.dataLabels = point.dataLabels || []; + dataLabel = point.dataLabels[i] = rotation ? + // Labels don't rotate, use text element + renderer.text(labelText, 0, -9999, labelOptions.useHTML) + .addClass('highcharts-data-label') : + // We can use label + renderer.label(labelText, 0, -9999, labelOptions.shape, null, null, labelOptions.useHTML, null, 'data-label'); + // Store for backwards compatibility + if (!i) { + point.dataLabel = dataLabel; + } + dataLabel.addClass(' highcharts-data-label-color-' + point.colorIndex + + ' ' + (labelOptions.className || '') + + ( // #3398 + labelOptions.useHTML ? + ' highcharts-tracker' : + '')); + } + else { + // Use old element and just update text + attr.text = labelText; + } + // Store data label options for later access + dataLabel.options = labelOptions; + dataLabel.attr(attr); + if (!chart.styledMode) { + // Styles must be applied before add in order to read + // text bounding box + dataLabel.css(style).shadow(labelOptions.shadow); + } + if (!dataLabel.added) { + dataLabel.add(dataLabelsGroup); + } + if (labelOptions.textPath && !labelOptions.useHTML) { + dataLabel.setTextPath((point.getDataLabelPath && + point.getDataLabelPath(dataLabel)) || point.graphic, labelOptions.textPath); + if (point.dataLabelPath && + !labelOptions.textPath.enabled) { + // clean the DOM + point.dataLabelPath = point.dataLabelPath.destroy(); + } + } + // Now the data label is created and placed at 0,0, so we + // need to align it + series.alignDataLabel(point, dataLabel, labelOptions, null, isNew); + } + }); + }); + } + fireEvent(this, 'afterDrawDataLabels'); + }; + /** + * Align each individual data label. + * + * @private + * @function Highcharts.Series#alignDataLabel + * @param {Highcharts.Point} point + * @param {Highcharts.SVGElement} dataLabel + * @param {Highcharts.DataLabelsOptions} options + * @param {Highcharts.BBoxObject} alignTo + * @param {boolean} [isNew] + * @return {void} + */ + Series.prototype.alignDataLabel = function (point, dataLabel, options, alignTo, isNew) { + var series = this, chart = this.chart, inverted = this.isCartesian && chart.inverted, enabledDataSorting = this.enabledDataSorting, plotX = pick(point.dlBox && point.dlBox.centerX, point.plotX, -9999), plotY = pick(point.plotY, -9999), bBox = dataLabel.getBBox(), baseline, rotation = options.rotation, normRotation, negRotation, align = options.align, rotCorr, // rotation correction + isInsidePlot = chart.isInsidePlot(plotX, Math.round(plotY), inverted), + // Math.round for rounding errors (#2683), alignTo to allow column + // labels (#2700) + alignAttr, // the final position; + justify = pick(options.overflow, (enabledDataSorting ? 'none' : 'justify')) === 'justify', visible = this.visible && + point.visible !== false && + (point.series.forceDL || + (enabledDataSorting && !justify) || + isInsidePlot || + ( + // If the data label is inside the align box, it is enough + // that parts of the align box is inside the plot area + // (#12370) + options.inside && alignTo && chart.isInsidePlot(plotX, inverted ? + alignTo.x + 1 : + alignTo.y + alignTo.height - 1, inverted))), setStartPos = function (alignOptions) { + if (enabledDataSorting && series.xAxis && !justify) { + series.setDataLabelStartPos(point, dataLabel, isNew, isInsidePlot, alignOptions); + } + }; + if (visible) { + baseline = chart.renderer.fontMetrics(chart.styledMode ? void 0 : options.style.fontSize, dataLabel).b; + // The alignment box is a singular point + alignTo = extend({ + x: inverted ? this.yAxis.len - plotY : plotX, + y: Math.round(inverted ? this.xAxis.len - plotX : plotY), + width: 0, + height: 0 + }, alignTo); + // Add the text size for alignment calculation + extend(options, { + width: bBox.width, + height: bBox.height + }); + // Allow a hook for changing alignment in the last moment, then do the + // alignment + if (rotation) { + justify = false; // Not supported for rotated text + rotCorr = chart.renderer.rotCorr(baseline, rotation); // #3723 + alignAttr = { + x: (alignTo.x + + options.x + + alignTo.width / 2 + + rotCorr.x), + y: (alignTo.y + + options.y + + { top: 0, middle: 0.5, bottom: 1 }[options.verticalAlign] * + alignTo.height) + }; + setStartPos(alignAttr); // data sorting + dataLabel[isNew ? 'attr' : 'animate'](alignAttr) + .attr({ + align: align + }); + // Compensate for the rotated label sticking out on the sides + normRotation = (rotation + 720) % 360; + negRotation = normRotation > 180 && normRotation < 360; + if (align === 'left') { + alignAttr.y -= negRotation ? bBox.height : 0; + } + else if (align === 'center') { + alignAttr.x -= bBox.width / 2; + alignAttr.y -= bBox.height / 2; + } + else if (align === 'right') { + alignAttr.x -= bBox.width; + alignAttr.y -= negRotation ? 0 : bBox.height; + } + dataLabel.placed = true; + dataLabel.alignAttr = alignAttr; + } + else { + setStartPos(alignTo); // data sorting + dataLabel.align(options, null, alignTo); + alignAttr = dataLabel.alignAttr; + } + // Handle justify or crop + if (justify && alignTo.height >= 0) { // #8830 + this.justifyDataLabel(dataLabel, options, alignAttr, bBox, alignTo, isNew); + // Now check that the data label is within the plot area + } + else if (pick(options.crop, true)) { + visible = + chart.isInsidePlot(alignAttr.x, alignAttr.y) && + chart.isInsidePlot(alignAttr.x + bBox.width, alignAttr.y + bBox.height); + } + // When we're using a shape, make it possible with a connector or an + // arrow pointing to thie point + if (options.shape && !rotation) { + dataLabel[isNew ? 'attr' : 'animate']({ + anchorX: inverted ? + chart.plotWidth - point.plotY : + point.plotX, + anchorY: inverted ? + chart.plotHeight - point.plotX : + point.plotY + }); + } + } + // To use alignAttr property in hideOverlappingLabels + if (isNew && enabledDataSorting) { + dataLabel.placed = false; + } + // Show or hide based on the final aligned position + if (!visible && (!enabledDataSorting || justify)) { + dataLabel.hide(true); + dataLabel.placed = false; // don't animate back in + } + }; + /** + * Set starting position for data label sorting animation. + * + * @private + * @function Highcharts.Series#setDataLabelStartPos + * @param {Highcharts.SVGElement} dataLabel + * @param {Highcharts.ColumnPoint} point + * @param {boolean | undefined} [isNew] + * @param {boolean} [isInside] + * @param {Highcharts.AlignObject} [alignOptions] + * + * @return {void} + */ + Series.prototype.setDataLabelStartPos = function (point, dataLabel, isNew, isInside, alignOptions) { + var chart = this.chart, inverted = chart.inverted, xAxis = this.xAxis, reversed = xAxis.reversed, labelCenter = inverted ? dataLabel.height / 2 : dataLabel.width / 2, pointWidth = point.pointWidth, halfWidth = pointWidth ? pointWidth / 2 : 0, startXPos, startYPos; + startXPos = inverted ? + alignOptions.x : + (reversed ? + -labelCenter - halfWidth : + xAxis.width - labelCenter + halfWidth); + startYPos = inverted ? + (reversed ? + this.yAxis.height - labelCenter + halfWidth : + -labelCenter - halfWidth) : alignOptions.y; + dataLabel.startXPos = startXPos; + dataLabel.startYPos = startYPos; + // We need to handle visibility in case of sorting point outside plot area + if (!isInside) { + dataLabel + .attr({ opacity: 1 }) + .animate({ opacity: 0 }, void 0, dataLabel.hide); + } + else if (dataLabel.visibility === 'hidden') { + dataLabel.show(); + dataLabel + .attr({ opacity: 0 }) + .animate({ opacity: 1 }); + } + // Save start position on first render, but do not change position + if (!chart.hasRendered) { + return; + } + // Set start position + if (isNew) { + dataLabel.attr({ x: dataLabel.startXPos, y: dataLabel.startYPos }); + } + dataLabel.placed = true; + }; + /** + * If data labels fall partly outside the plot area, align them back in, in a + * way that doesn't hide the point. + * + * @private + * @function Highcharts.Series#justifyDataLabel + * @param {Highcharts.SVGElement} dataLabel + * @param {Highcharts.DataLabelsOptions} options + * @param {Highcharts.SVGAttributes} alignAttr + * @param {Highcharts.BBoxObject} bBox + * @param {Highcharts.BBoxObject} [alignTo] + * @param {boolean} [isNew] + * @return {boolean|undefined} + */ + Series.prototype.justifyDataLabel = function (dataLabel, options, alignAttr, bBox, alignTo, isNew) { + var chart = this.chart, align = options.align, verticalAlign = options.verticalAlign, off, justified, padding = dataLabel.box ? 0 : (dataLabel.padding || 0); + // Off left + off = alignAttr.x + padding; + if (off < 0) { + if (align === 'right') { + options.align = 'left'; + options.inside = true; + } + else { + options.x = -off; + } + justified = true; + } + // Off right + off = alignAttr.x + bBox.width - padding; + if (off > chart.plotWidth) { + if (align === 'left') { + options.align = 'right'; + options.inside = true; + } + else { + options.x = chart.plotWidth - off; + } + justified = true; + } + // Off top + off = alignAttr.y + padding; + if (off < 0) { + if (verticalAlign === 'bottom') { + options.verticalAlign = 'top'; + options.inside = true; + } + else { + options.y = -off; + } + justified = true; + } + // Off bottom + off = alignAttr.y + bBox.height - padding; + if (off > chart.plotHeight) { + if (verticalAlign === 'top') { + options.verticalAlign = 'bottom'; + options.inside = true; + } + else { + options.y = chart.plotHeight - off; + } + justified = true; + } + if (justified) { + dataLabel.placed = !isNew; + dataLabel.align(options, null, alignTo); + } + return justified; + }; + if (seriesTypes.pie) { + seriesTypes.pie.prototype.dataLabelPositioners = { + // Based on the value computed in Highcharts' distribute algorithm. + radialDistributionY: function (point) { + return point.top + point.distributeBox.pos; + }, + // get the x - use the natural x position for labels near the + // top and bottom, to prevent the top and botton slice + // connectors from touching each other on either side + // Based on the value computed in Highcharts' distribute algorithm. + radialDistributionX: function (series, point, y, naturalY) { + return series.getX(y < point.top + 2 || y > point.bottom - 2 ? + naturalY : + y, point.half, point); + }, + // dataLabels.distance determines the x position of the label + justify: function (point, radius, seriesCenter) { + return seriesCenter[0] + (point.half ? -1 : 1) * + (radius + point.labelDistance); + }, + // Left edges of the left-half labels touch the left edge of the plot + // area. Right edges of the right-half labels touch the right edge of + // the plot area. + alignToPlotEdges: function (dataLabel, half, plotWidth, plotLeft) { + var dataLabelWidth = dataLabel.getBBox().width; + return half ? dataLabelWidth + plotLeft : + plotWidth - dataLabelWidth - plotLeft; + }, + // Connectors of each side end in the same x position. Labels are + // aligned to them. Left edge of the widest left-half label touches the + // left edge of the plot area. Right edge of the widest right-half label + // touches the right edge of the plot area. + alignToConnectors: function (points, half, plotWidth, plotLeft) { + var maxDataLabelWidth = 0, dataLabelWidth; + // find widest data label + points.forEach(function (point) { + dataLabelWidth = point.dataLabel.getBBox().width; + if (dataLabelWidth > maxDataLabelWidth) { + maxDataLabelWidth = dataLabelWidth; + } + }); + return half ? maxDataLabelWidth + plotLeft : + plotWidth - maxDataLabelWidth - plotLeft; + } + }; + /** + * Override the base drawDataLabels method by pie specific functionality + * + * @private + * @function Highcharts.seriesTypes.pie#drawDataLabels + * @return {void} + */ + seriesTypes.pie.prototype.drawDataLabels = function () { + var series = this, data = series.data, point, chart = series.chart, options = series.options.dataLabels || {}, connectorPadding = options.connectorPadding, connectorWidth, plotWidth = chart.plotWidth, plotHeight = chart.plotHeight, plotLeft = chart.plotLeft, maxWidth = Math.round(chart.chartWidth / 3), connector, seriesCenter = series.center, radius = seriesCenter[2] / 2, centerY = seriesCenter[1], dataLabel, dataLabelWidth, + // labelPos, + labelPosition, labelHeight, + // divide the points into right and left halves for anti collision + halves = [ + [], + [] // left + ], x, y, visibility, j, overflow = [0, 0, 0, 0], // top, right, bottom, left + dataLabelPositioners = series.dataLabelPositioners, pointDataLabelsOptions; + // get out if not enabled + if (!series.visible || + (!options.enabled && + !series._hasPointLabels)) { + return; + } + // Reset all labels that have been shortened + data.forEach(function (point) { + if (point.dataLabel && point.visible && point.dataLabel.shortened) { + point.dataLabel + .attr({ + width: 'auto' + }).css({ + width: 'auto', + textOverflow: 'clip' + }); + point.dataLabel.shortened = false; + } + }); + // run parent method + Series.prototype.drawDataLabels.apply(series); + data.forEach(function (point) { + if (point.dataLabel) { + if (point.visible) { // #407, #2510 + // Arrange points for detection collision + halves[point.half].push(point); + // Reset positions (#4905) + point.dataLabel._pos = null; + // Avoid long labels squeezing the pie size too far down + if (!defined(options.style.width) && + !defined(point.options.dataLabels && + point.options.dataLabels.style && + point.options.dataLabels.style.width)) { + if (point.dataLabel.getBBox().width > maxWidth) { + point.dataLabel.css({ + // Use a fraction of the maxWidth to avoid + // wrapping close to the end of the string. + width: Math.round(maxWidth * 0.7) + 'px' + }); + point.dataLabel.shortened = true; + } + } + } + else { + point.dataLabel = point.dataLabel.destroy(); + // Workaround to make pies destroy multiple datalabels + // correctly. This logic needs rewriting to support multiple + // datalabels fully. + if (point.dataLabels && point.dataLabels.length === 1) { + delete point.dataLabels; + } + } + } + }); + /* Loop over the points in each half, starting from the top and bottom + * of the pie to detect overlapping labels. + */ + halves.forEach(function (points, i) { + var top, bottom, length = points.length, positions = [], naturalY, sideOverflow, size, distributionLength; + if (!length) { + return; + } + // Sort by angle + series.sortByAngle(points, i - 0.5); + // Only do anti-collision when we have dataLabels outside the pie + // and have connectors. (#856) + if (series.maxLabelDistance > 0) { + top = Math.max(0, centerY - radius - series.maxLabelDistance); + bottom = Math.min(centerY + radius + series.maxLabelDistance, chart.plotHeight); + points.forEach(function (point) { + // check if specific points' label is outside the pie + if (point.labelDistance > 0 && point.dataLabel) { + // point.top depends on point.labelDistance value + // Used for calculation of y value in getX method + point.top = Math.max(0, centerY - radius - point.labelDistance); + point.bottom = Math.min(centerY + radius + point.labelDistance, chart.plotHeight); + size = point.dataLabel.getBBox().height || 21; + // point.positionsIndex is needed for getting index of + // parameter related to specific point inside positions + // array - not every point is in positions array. + point.distributeBox = { + target: point.labelPosition.natural.y - + point.top + size / 2, + size: size, + rank: point.y + }; + positions.push(point.distributeBox); + } + }); + distributionLength = bottom + size - top; + H.distribute(positions, distributionLength, distributionLength / 5); + } + // Now the used slots are sorted, fill them up sequentially + for (j = 0; j < length; j++) { + point = points[j]; + // labelPos = point.labelPos; + labelPosition = point.labelPosition; + dataLabel = point.dataLabel; + visibility = point.visible === false ? 'hidden' : 'inherit'; + naturalY = labelPosition.natural.y; + y = naturalY; + if (positions && defined(point.distributeBox)) { + if (typeof point.distributeBox.pos === 'undefined') { + visibility = 'hidden'; + } + else { + labelHeight = point.distributeBox.size; + // Find label's y position + y = dataLabelPositioners + .radialDistributionY(point); + } + } + // It is needed to delete point.positionIndex for + // dynamically added points etc. + delete point.positionIndex; // @todo unused + // Find label's x position + // justify is undocumented in the API - preserve support for it + if (options.justify) { + x = dataLabelPositioners.justify(point, radius, seriesCenter); + } + else { + switch (options.alignTo) { + case 'connectors': + x = dataLabelPositioners.alignToConnectors(points, i, plotWidth, plotLeft); + break; + case 'plotEdges': + x = dataLabelPositioners.alignToPlotEdges(dataLabel, i, plotWidth, plotLeft); + break; + default: + x = dataLabelPositioners.radialDistributionX(series, point, y, naturalY); + } + } + // Record the placement and visibility + dataLabel._attr = { + visibility: visibility, + align: labelPosition.alignment + }; + pointDataLabelsOptions = point.options.dataLabels || {}; + dataLabel._pos = { + x: (x + + pick(pointDataLabelsOptions.x, options.x) + // (#12985) + ({ + left: connectorPadding, + right: -connectorPadding + }[labelPosition.alignment] || 0)), + // 10 is for the baseline (label vs text) + y: (y + + pick(pointDataLabelsOptions.y, options.y) - // (#12985) + 10) + }; + // labelPos.x = x; + // labelPos.y = y; + labelPosition.final.x = x; + labelPosition.final.y = y; + // Detect overflowing data labels + if (pick(options.crop, true)) { + dataLabelWidth = dataLabel.getBBox().width; + sideOverflow = null; + // Overflow left + if (x - dataLabelWidth < connectorPadding && + i === 1 // left half + ) { + sideOverflow = Math.round(dataLabelWidth - x + connectorPadding); + overflow[3] = Math.max(sideOverflow, overflow[3]); + // Overflow right + } + else if (x + dataLabelWidth > plotWidth - connectorPadding && + i === 0 // right half + ) { + sideOverflow = Math.round(x + dataLabelWidth - plotWidth + connectorPadding); + overflow[1] = Math.max(sideOverflow, overflow[1]); + } + // Overflow top + if (y - labelHeight / 2 < 0) { + overflow[0] = Math.max(Math.round(-y + labelHeight / 2), overflow[0]); + // Overflow left + } + else if (y + labelHeight / 2 > plotHeight) { + overflow[2] = Math.max(Math.round(y + labelHeight / 2 - plotHeight), overflow[2]); + } + dataLabel.sideOverflow = sideOverflow; + } + } // for each point + }); // for each half + // Do not apply the final placement and draw the connectors until we + // have verified that labels are not spilling over. + if (arrayMax(overflow) === 0 || + this.verifyDataLabelOverflow(overflow)) { + // Place the labels in the final position + this.placeDataLabels(); + this.points.forEach(function (point) { + // #8864: every connector can have individual options + pointDataLabelsOptions = + merge(options, point.options.dataLabels); + connectorWidth = + pick(pointDataLabelsOptions.connectorWidth, 1); + // Draw the connector + if (connectorWidth) { + var isNew; + connector = point.connector; + dataLabel = point.dataLabel; + if (dataLabel && + dataLabel._pos && + point.visible && + point.labelDistance > 0) { + visibility = dataLabel._attr.visibility; + isNew = !connector; + if (isNew) { + point.connector = connector = chart.renderer + .path() + .addClass('highcharts-data-label-connector ' + + ' highcharts-color-' + point.colorIndex + + (point.className ? + ' ' + point.className : + '')) + .add(series.dataLabelsGroup); + if (!chart.styledMode) { + connector.attr({ + 'stroke-width': connectorWidth, + 'stroke': (pointDataLabelsOptions.connectorColor || + point.color || + '#666666') + }); + } + } + connector[isNew ? 'attr' : 'animate']({ + d: point.getConnectorPath() + }); + connector.attr('visibility', visibility); + } + else if (connector) { + point.connector = connector.destroy(); + } + } + }); + } + }; + /** + * Extendable method for getting the path of the connector between the data + * label and the pie slice. + * + * @private + * @function Highcharts.seriesTypes.pie#connectorPath + * + * @param {*} labelPos + * + * @return {Highcharts.SVGPathArray} + */ + // TODO: depracated - remove it + /* + seriesTypes.pie.prototype.connectorPath = function (labelPos) { + var x = labelPos.x, + y = labelPos.y; + return pick(this.options.dataLabels.softConnector, true) ? [ + 'M', + // end of the string at the label + x + (labelPos[6] === 'left' ? 5 : -5), y, + 'C', + x, y, // first break, next to the label + 2 * labelPos[2] - labelPos[4], 2 * labelPos[3] - labelPos[5], + labelPos[2], labelPos[3], // second break + 'L', + labelPos[4], labelPos[5] // base + ] : [ + 'M', + // end of the string at the label + x + (labelPos[6] === 'left' ? 5 : -5), y, + 'L', + labelPos[2], labelPos[3], // second break + 'L', + labelPos[4], labelPos[5] // base + ]; + }; + */ + /** + * Perform the final placement of the data labels after we have verified + * that they fall within the plot area. + * + * @private + * @function Highcharts.seriesTypes.pie#placeDataLabels + * @return {void} + */ + seriesTypes.pie.prototype.placeDataLabels = function () { + this.points.forEach(function (point) { + var dataLabel = point.dataLabel, _pos; + if (dataLabel && point.visible) { + _pos = dataLabel._pos; + if (_pos) { + // Shorten data labels with ellipsis if they still overflow + // after the pie has reached minSize (#223). + if (dataLabel.sideOverflow) { + dataLabel._attr.width = + Math.max(dataLabel.getBBox().width - + dataLabel.sideOverflow, 0); + dataLabel.css({ + width: dataLabel._attr.width + 'px', + textOverflow: ((this.options.dataLabels.style || {}) + .textOverflow || + 'ellipsis') + }); + dataLabel.shortened = true; + } + dataLabel.attr(dataLabel._attr); + dataLabel[dataLabel.moved ? 'animate' : 'attr'](_pos); + dataLabel.moved = true; + } + else if (dataLabel) { + dataLabel.attr({ y: -9999 }); + } + } + // Clear for update + delete point.distributeBox; + }, this); + }; + seriesTypes.pie.prototype.alignDataLabel = noop; + /** + * Verify whether the data labels are allowed to draw, or we should run more + * translation and data label positioning to keep them inside the plot area. + * Returns true when data labels are ready to draw. + * + * @private + * @function Highcharts.seriesTypes.pie#verifyDataLabelOverflow + * @param {Array} overflow + * @return {boolean} + */ + seriesTypes.pie.prototype.verifyDataLabelOverflow = function (overflow) { + var center = this.center, options = this.options, centerOption = options.center, minSize = options.minSize || 80, newSize = minSize, + // If a size is set, return true and don't try to shrink the pie + // to fit the labels. + ret = options.size !== null; + if (!ret) { + // Handle horizontal size and center + if (centerOption[0] !== null) { // Fixed center + newSize = Math.max(center[2] - + Math.max(overflow[1], overflow[3]), minSize); + } + else { // Auto center + newSize = Math.max( + // horizontal overflow + center[2] - overflow[1] - overflow[3], minSize); + // horizontal center + center[0] += (overflow[3] - overflow[1]) / 2; + } + // Handle vertical size and center + if (centerOption[1] !== null) { // Fixed center + newSize = clamp(newSize, minSize, center[2] - Math.max(overflow[0], overflow[2])); + } + else { // Auto center + newSize = clamp(newSize, minSize, + // vertical overflow + center[2] - overflow[0] - overflow[2]); + // vertical center + center[1] += (overflow[0] - overflow[2]) / 2; + } + // If the size must be decreased, we need to run translate and + // drawDataLabels again + if (newSize < center[2]) { + center[2] = newSize; + center[3] = Math.min(// #3632 + relativeLength(options.innerSize || 0, newSize), newSize); + this.translate(center); + if (this.drawDataLabels) { + this.drawDataLabels(); + } + // Else, return true to indicate that the pie and its labels is + // within the plot area + } + else { + ret = true; + } + } + return ret; + }; + } + if (seriesTypes.column) { + /** + * Override the basic data label alignment by adjusting for the position of + * the column. + * + * @private + * @function Highcharts.seriesTypes.column#alignDataLabel + * @param {Highcharts.Point} point + * @param {Highcharts.SVGElement} dataLabel + * @param {Highcharts.DataLabelsOptions} options + * @param {Highcharts.BBoxObject} alignTo + * @param {boolean} [isNew] + * @return {void} + */ + seriesTypes.column.prototype.alignDataLabel = function (point, dataLabel, options, alignTo, isNew) { + var inverted = this.chart.inverted, series = point.series, + // data label box for alignment + dlBox = point.dlBox || point.shapeArgs, below = pick(point.below, // range series + point.plotY > + pick(this.translatedThreshold, series.yAxis.len)), + // draw it inside the box? + inside = pick(options.inside, !!this.options.stacking), overshoot; + // Align to the column itself, or the top of it + if (dlBox) { // Area range uses this method but not alignTo + alignTo = merge(dlBox); + if (alignTo.y < 0) { + alignTo.height += alignTo.y; + alignTo.y = 0; + } + // If parts of the box overshoots outside the plot area, modify the + // box to center the label inside + overshoot = alignTo.y + alignTo.height - series.yAxis.len; + if (overshoot > 0 && overshoot < alignTo.height) { + alignTo.height -= overshoot; + } + if (inverted) { + alignTo = { + x: series.yAxis.len - alignTo.y - alignTo.height, + y: series.xAxis.len - alignTo.x - alignTo.width, + width: alignTo.height, + height: alignTo.width + }; + } + // Compute the alignment box + if (!inside) { + if (inverted) { + alignTo.x += below ? 0 : alignTo.width; + alignTo.width = 0; + } + else { + alignTo.y += below ? alignTo.height : 0; + alignTo.height = 0; + } + } + } + // When alignment is undefined (typically columns and bars), display the + // individual point below or above the point depending on the threshold + options.align = pick(options.align, !inverted || inside ? 'center' : below ? 'right' : 'left'); + options.verticalAlign = pick(options.verticalAlign, inverted || inside ? 'middle' : below ? 'top' : 'bottom'); + // Call the parent method + Series.prototype.alignDataLabel.call(this, point, dataLabel, options, alignTo, isNew); + // If label was justified and we have contrast, set it: + if (options.inside && point.contrastColor) { + dataLabel.css({ + color: point.contrastColor + }); + } + }; + } + + }); + _registerModule(_modules, 'modules/overlapping-datalabels.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * Highcharts module to hide overlapping data labels. + * This module is included in Highcharts. + * + * (c) 2009-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, fireEvent = U.fireEvent, isArray = U.isArray, objectEach = U.objectEach, pick = U.pick; + var Chart = H.Chart; + /* eslint-disable no-invalid-this */ + // Collect potensial overlapping data labels. Stack labels probably don't need + // to be considered because they are usually accompanied by data labels that lie + // inside the columns. + addEvent(Chart, 'render', function collectAndHide() { + var labels = []; + // Consider external label collectors + (this.labelCollectors || []).forEach(function (collector) { + labels = labels.concat(collector()); + }); + (this.yAxis || []).forEach(function (yAxis) { + if (yAxis.stacking && + yAxis.options.stackLabels && + !yAxis.options.stackLabels.allowOverlap) { + objectEach(yAxis.stacking.stacks, function (stack) { + objectEach(stack, function (stackItem) { + labels.push(stackItem.label); + }); + }); + } + }); + (this.series || []).forEach(function (series) { + var dlOptions = series.options.dataLabels; + if (series.visible && + !(dlOptions.enabled === false && !series._hasPointLabels)) { // #3866 + (series.nodes || series.points).forEach(function (point) { + if (point.visible) { + var dataLabels = (isArray(point.dataLabels) ? + point.dataLabels : + (point.dataLabel ? [point.dataLabel] : [])); + dataLabels.forEach(function (label) { + var options = label.options; + label.labelrank = pick(options.labelrank, point.labelrank, point.shapeArgs && point.shapeArgs.height); // #4118 + if (!options.allowOverlap) { + labels.push(label); + } + }); + } + }); + } + }); + this.hideOverlappingLabels(labels); + }); + /** + * Hide overlapping labels. Labels are moved and faded in and out on zoom to + * provide a smooth visual imression. + * + * @private + * @function Highcharts.Chart#hideOverlappingLabels + * @param {Array} labels + * Rendered data labels + * @return {void} + * @requires modules/overlapping-datalabels + */ + Chart.prototype.hideOverlappingLabels = function (labels) { + var chart = this, len = labels.length, ren = chart.renderer, label, i, j, label1, label2, box1, box2, isLabelAffected = false, isIntersectRect = function (box1, box2) { + return !(box2.x > box1.x + box1.width || + box2.x + box2.width < box1.x || + box2.y > box1.y + box1.height || + box2.y + box2.height < box1.y); + }, + // Get the box with its position inside the chart, as opposed to getBBox + // that only reports the position relative to the parent. + getAbsoluteBox = function (label) { + var pos, parent, bBox, + // Substract the padding if no background or border (#4333) + padding = label.box ? 0 : (label.padding || 0), lineHeightCorrection = 0, xOffset = 0, boxWidth, alignValue; + if (label && + (!label.alignAttr || label.placed)) { + pos = label.alignAttr || { + x: label.attr('x'), + y: label.attr('y') + }; + parent = label.parentGroup; + // Get width and height if pure text nodes (stack labels) + if (!label.width) { + bBox = label.getBBox(); + label.width = bBox.width; + label.height = bBox.height; + // Labels positions are computed from top left corner, so + // we need to substract the text height from text nodes too. + lineHeightCorrection = ren + .fontMetrics(null, label.element).h; + } + boxWidth = label.width - 2 * padding; + alignValue = { + left: '0', + center: '0.5', + right: '1' + }[label.alignValue]; + if (alignValue) { + xOffset = +alignValue * boxWidth; + } + else if (Math.round(label.x) !== label.translateX) { + xOffset = label.x - label.translateX; + } + return { + x: pos.x + (parent.translateX || 0) + padding - xOffset, + y: pos.y + (parent.translateY || 0) + padding - + lineHeightCorrection, + width: label.width - 2 * padding, + height: label.height - 2 * padding + }; + } + }; + for (i = 0; i < len; i++) { + label = labels[i]; + if (label) { + // Mark with initial opacity + label.oldOpacity = label.opacity; + label.newOpacity = 1; + label.absoluteBox = getAbsoluteBox(label); + } + } + // Prevent a situation in a gradually rising slope, that each label will + // hide the previous one because the previous one always has lower rank. + labels.sort(function (a, b) { + return (b.labelrank || 0) - (a.labelrank || 0); + }); + // Detect overlapping labels + for (i = 0; i < len; i++) { + label1 = labels[i]; + box1 = label1 && label1.absoluteBox; + for (j = i + 1; j < len; ++j) { + label2 = labels[j]; + box2 = label2 && label2.absoluteBox; + if (box1 && + box2 && + label1 !== label2 && // #6465, polar chart with connectEnds + label1.newOpacity !== 0 && + label2.newOpacity !== 0) { + if (isIntersectRect(box1, box2)) { + (label1.labelrank < label2.labelrank ? label1 : label2) + .newOpacity = 0; + } + } + } + } + // Hide or show + labels.forEach(function (label) { + var complete, newOpacity; + if (label) { + newOpacity = label.newOpacity; + if (label.oldOpacity !== newOpacity) { + // Make sure the label is completely hidden to avoid catching + // clicks (#4362) + if (label.alignAttr && label.placed) { // data labels + label[newOpacity ? 'removeClass' : 'addClass']('highcharts-data-label-hidden'); + complete = function () { + if (!chart.styledMode) { + label.css({ pointerEvents: newOpacity ? 'auto' : 'none' }); + } + label.visibility = newOpacity ? 'inherit' : 'hidden'; + label.placed = !!newOpacity; + }; + isLabelAffected = true; + // Animate or set the opacity + label.alignAttr.opacity = newOpacity; + label[label.isOld ? 'animate' : 'attr'](label.alignAttr, null, complete); + fireEvent(chart, 'afterHideOverlappingLabel'); + } + else { // other labels, tick labels + label.attr({ + opacity: newOpacity + }); + } + } + label.isOld = true; + } + }); + if (isLabelAffected) { + fireEvent(chart, 'afterHideAllOverlappingLabels'); + } + }; + + }); + _registerModule(_modules, 'parts/Interaction.js', [_modules['parts/Globals.js'], _modules['parts/Legend.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js']], function (H, Legend, Point, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * @interface Highcharts.PointEventsOptionsObject + */ /** + * Fires when the point is selected either programmatically or following a click + * on the point. One parameter, `event`, is passed to the function. Returning + * `false` cancels the operation. + * @name Highcharts.PointEventsOptionsObject#select + * @type {Highcharts.PointSelectCallbackFunction|undefined} + */ /** + * Fires when the point is unselected either programmatically or following a + * click on the point. One parameter, `event`, is passed to the function. + * Returning `false` cancels the operation. + * @name Highcharts.PointEventsOptionsObject#unselect + * @type {Highcharts.PointUnselectCallbackFunction|undefined} + */ + /** + * Information about the select/unselect event. + * + * @interface Highcharts.PointInteractionEventObject + * @extends global.Event + */ /** + * @name Highcharts.PointInteractionEventObject#accumulate + * @type {boolean} + */ + /** + * Gets fired when the point is selected either programmatically or following a + * click on the point. + * + * @callback Highcharts.PointSelectCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {Highcharts.PointInteractionEventObject} event + * Event that occured. + */ + /** + * Fires when the point is unselected either programmatically or following a + * click on the point. + * + * @callback Highcharts.PointUnselectCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {Highcharts.PointInteractionEventObject} event + * Event that occured. + */ + var addEvent = U.addEvent, createElement = U.createElement, css = U.css, defined = U.defined, extend = U.extend, fireEvent = U.fireEvent, isArray = U.isArray, isFunction = U.isFunction, isNumber = U.isNumber, isObject = U.isObject, merge = U.merge, objectEach = U.objectEach, pick = U.pick; + var Chart = H.Chart, defaultOptions = H.defaultOptions, defaultPlotOptions = H.defaultPlotOptions, hasTouch = H.hasTouch, Series = H.Series, seriesTypes = H.seriesTypes, svg = H.svg, TrackerMixin; + /* eslint-disable valid-jsdoc */ + /** + * TrackerMixin for points and graphs. + * + * @private + * @mixin Highcharts.TrackerMixin + */ + TrackerMixin = H.TrackerMixin = { + /** + * Draw the tracker for a point. + * + * @private + * @function Highcharts.TrackerMixin.drawTrackerPoint + * @param {Highcharts.Series} this + * @fires Highcharts.Series#event:afterDrawTracker + */ + drawTrackerPoint: function () { + var series = this, chart = series.chart, pointer = chart.pointer, onMouseOver = function (e) { + var point = pointer.getPointFromEvent(e); + // undefined on graph in scatterchart + if (typeof point !== 'undefined') { + pointer.isDirectTouch = true; + point.onMouseOver(e); + } + }, dataLabels; + // Add reference to the point + series.points.forEach(function (point) { + dataLabels = (isArray(point.dataLabels) ? + point.dataLabels : + (point.dataLabel ? [point.dataLabel] : [])); + if (point.graphic) { + point.graphic.element.point = point; + } + dataLabels.forEach(function (dataLabel) { + if (dataLabel.div) { + dataLabel.div.point = point; + } + else { + dataLabel.element.point = point; + } + }); + }); + // Add the event listeners, we need to do this only once + if (!series._hasTracking) { + series.trackerGroups.forEach(function (key) { + if (series[key]) { + // we don't always have dataLabelsGroup + series[key] + .addClass('highcharts-tracker') + .on('mouseover', onMouseOver) + .on('mouseout', function (e) { + pointer.onTrackerMouseOut(e); + }); + if (hasTouch) { + series[key].on('touchstart', onMouseOver); + } + if (!chart.styledMode && series.options.cursor) { + series[key] + .css(css) + .css({ cursor: series.options.cursor }); + } + } + }); + series._hasTracking = true; + } + fireEvent(this, 'afterDrawTracker'); + }, + /** + * Draw the tracker object that sits above all data labels and markers to + * track mouse events on the graph or points. For the line type charts + * the tracker uses the same graphPath, but with a greater stroke width + * for better control. + * + * @private + * @function Highcharts.TrackerMixin.drawTrackerGraph + * @param {Highcharts.Series} this + * @fires Highcharts.Series#event:afterDrawTracker + */ + drawTrackerGraph: function () { + var series = this, options = series.options, trackByArea = options.trackByArea, trackerPath = [].concat(trackByArea ? + series.areaPath : + series.graphPath), + // trackerPathLength = trackerPath.length, + chart = series.chart, pointer = chart.pointer, renderer = chart.renderer, snap = chart.options.tooltip.snap, tracker = series.tracker, i, onMouseOver = function (e) { + if (chart.hoverSeries !== series) { + series.onMouseOver(); + } + }, + /* + * Empirical lowest possible opacities for TRACKER_FILL for an + * element to stay invisible but clickable + * IE6: 0.002 + * IE7: 0.002 + * IE8: 0.002 + * IE9: 0.00000000001 (unlimited) + * IE10: 0.0001 (exporting only) + * FF: 0.00000000001 (unlimited) + * Chrome: 0.000001 + * Safari: 0.000001 + * Opera: 0.00000000001 (unlimited) + */ + TRACKER_FILL = 'rgba(192,192,192,' + (svg ? 0.0001 : 0.002) + ')'; + // Draw the tracker + if (tracker) { + tracker.attr({ d: trackerPath }); + } + else if (series.graph) { // create + series.tracker = renderer.path(trackerPath) + .attr({ + visibility: series.visible ? 'visible' : 'hidden', + zIndex: 2 + }) + .addClass(trackByArea ? + 'highcharts-tracker-area' : + 'highcharts-tracker-line') + .add(series.group); + if (!chart.styledMode) { + series.tracker.attr({ + 'stroke-linecap': 'round', + 'stroke-linejoin': 'round', + stroke: TRACKER_FILL, + fill: trackByArea ? TRACKER_FILL : 'none', + 'stroke-width': series.graph.strokeWidth() + + (trackByArea ? 0 : 2 * snap) + }); + } + // The tracker is added to the series group, which is clipped, but + // is covered by the marker group. So the marker group also needs to + // capture events. + [series.tracker, series.markerGroup].forEach(function (tracker) { + tracker.addClass('highcharts-tracker') + .on('mouseover', onMouseOver) + .on('mouseout', function (e) { + pointer.onTrackerMouseOut(e); + }); + if (options.cursor && !chart.styledMode) { + tracker.css({ cursor: options.cursor }); + } + if (hasTouch) { + tracker.on('touchstart', onMouseOver); + } + }); + } + fireEvent(this, 'afterDrawTracker'); + } + }; + /* End TrackerMixin */ + // Add tracking event listener to the series group, so the point graphics + // themselves act as trackers + if (seriesTypes.column) { + /** + * @private + * @borrows Highcharts.TrackerMixin.drawTrackerPoint as Highcharts.seriesTypes.column#drawTracker + */ + seriesTypes.column.prototype.drawTracker = TrackerMixin.drawTrackerPoint; + } + if (seriesTypes.pie) { + /** + * @private + * @borrows Highcharts.TrackerMixin.drawTrackerPoint as Highcharts.seriesTypes.pie#drawTracker + */ + seriesTypes.pie.prototype.drawTracker = TrackerMixin.drawTrackerPoint; + } + if (seriesTypes.scatter) { + /** + * @private + * @borrows Highcharts.TrackerMixin.drawTrackerPoint as Highcharts.seriesTypes.scatter#drawTracker + */ + seriesTypes.scatter.prototype.drawTracker = TrackerMixin.drawTrackerPoint; + } + // Extend Legend for item events. + extend(Legend.prototype, { + /** + * @private + * @function Highcharts.Legend#setItemEvents + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + * @param {Highcharts.SVGElement} legendItem + * @param {boolean} [useHTML=false] + * @fires Highcharts.Point#event:legendItemClick + * @fires Highcharts.Series#event:legendItemClick + */ + setItemEvents: function (item, legendItem, useHTML) { + var legend = this, boxWrapper = legend.chart.renderer.boxWrapper, isPoint = item instanceof Point, activeClass = 'highcharts-legend-' + + (isPoint ? 'point' : 'series') + '-active', styledMode = legend.chart.styledMode, + // When `useHTML`, the symbol is rendered in other group, so + // we need to apply events listeners to both places + legendItems = useHTML ? + [legendItem, item.legendSymbol] : + [item.legendGroup]; + // Set the events on the item group, or in case of useHTML, the item + // itself (#1249) + legendItems.forEach(function (element) { + if (element) { + element + .on('mouseover', function () { + if (item.visible) { + legend.allItems.forEach(function (inactiveItem) { + if (item !== inactiveItem) { + inactiveItem.setState('inactive', !isPoint); + } + }); + } + item.setState('hover'); + // A CSS class to dim or hide other than the hovered + // series. + // Works only if hovered series is visible (#10071). + if (item.visible) { + boxWrapper.addClass(activeClass); + } + if (!styledMode) { + legendItem.css(legend.options.itemHoverStyle); + } + }) + .on('mouseout', function () { + if (!legend.chart.styledMode) { + legendItem.css(merge(item.visible ? + legend.itemStyle : + legend.itemHiddenStyle)); + } + legend.allItems.forEach(function (inactiveItem) { + if (item !== inactiveItem) { + inactiveItem.setState('', !isPoint); + } + }); + // A CSS class to dim or hide other than the hovered + // series. + boxWrapper.removeClass(activeClass); + item.setState(); + }) + .on('click', function (event) { + var strLegendItemClick = 'legendItemClick', fnLegendItemClick = function () { + if (item.setVisible) { + item.setVisible(); + } + // Reset inactive state + legend.allItems.forEach(function (inactiveItem) { + if (item !== inactiveItem) { + inactiveItem.setState(item.visible ? 'inactive' : '', !isPoint); + } + }); + }; + // A CSS class to dim or hide other than the hovered + // series. Event handling in iOS causes the activeClass + // to be added prior to click in some cases (#7418). + boxWrapper.removeClass(activeClass); + // Pass over the click/touch event. #4. + event = { + browserEvent: event + }; + // click the name or symbol + if (item.firePointEvent) { // point + item.firePointEvent(strLegendItemClick, event, fnLegendItemClick); + } + else { + fireEvent(item, strLegendItemClick, event, fnLegendItemClick); + } + }); + } + }); + }, + /** + * @private + * @function Highcharts.Legend#createCheckboxForItem + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + * @fires Highcharts.Series#event:checkboxClick + */ + createCheckboxForItem: function (item) { + var legend = this; + item.checkbox = createElement('input', { + type: 'checkbox', + className: 'highcharts-legend-checkbox', + checked: item.selected, + defaultChecked: item.selected // required by IE7 + }, legend.options.itemCheckboxStyle, legend.chart.container); + addEvent(item.checkbox, 'click', function (event) { + var target = event.target; + fireEvent(item.series || item, 'checkboxClick', { + checked: target.checked, + item: item + }, function () { + item.select(); + }); + }); + } + }); + // Extend the Chart object with interaction + extend(Chart.prototype, /** @lends Chart.prototype */ { + /** + * Display the zoom button, so users can reset zoom to the default view + * settings. + * + * @function Highcharts.Chart#showResetZoom + * + * @fires Highcharts.Chart#event:afterShowResetZoom + * @fires Highcharts.Chart#event:beforeShowResetZoom + */ + showResetZoom: function () { + var chart = this, lang = defaultOptions.lang, btnOptions = chart.options.chart.resetZoomButton, theme = btnOptions.theme, states = theme.states, alignTo = (btnOptions.relativeTo === 'chart' || + btnOptions.relativeTo === 'spaceBox' ? + null : + 'plotBox'); + /** + * @private + */ + function zoomOut() { + chart.zoomOut(); + } + fireEvent(this, 'beforeShowResetZoom', null, function () { + chart.resetZoomButton = chart.renderer + .button(lang.resetZoom, null, null, zoomOut, theme, states && states.hover) + .attr({ + align: btnOptions.position.align, + title: lang.resetZoomTitle + }) + .addClass('highcharts-reset-zoom') + .add() + .align(btnOptions.position, false, alignTo); + }); + fireEvent(this, 'afterShowResetZoom'); + }, + /** + * Zoom the chart out after a user has zoomed in. See also + * [Axis.setExtremes](/class-reference/Highcharts.Axis#setExtremes). + * + * @function Highcharts.Chart#zoomOut + * + * @fires Highcharts.Chart#event:selection + */ + zoomOut: function () { + fireEvent(this, 'selection', { resetSelection: true }, this.zoom); + }, + /** + * Zoom into a given portion of the chart given by axis coordinates. + * + * @private + * @function Highcharts.Chart#zoom + * @param {Highcharts.SelectEventObject} event + */ + zoom: function (event) { + var chart = this, hasZoomed, pointer = chart.pointer, displayButton = false, mouseDownPos = chart.inverted ? pointer.mouseDownX : pointer.mouseDownY, resetZoomButton; + // If zoom is called with no arguments, reset the axes + if (!event || event.resetSelection) { + chart.axes.forEach(function (axis) { + hasZoomed = axis.zoom(); + }); + pointer.initiated = false; // #6804 + } + else { // else, zoom in on all axes + event.xAxis.concat(event.yAxis).forEach(function (axisData) { + var axis = axisData.axis, axisStartPos = chart.inverted ? axis.left : axis.top, axisEndPos = chart.inverted ? + axisStartPos + axis.width : axisStartPos + axis.height, isXAxis = axis.isXAxis, isWithinPane = false; + // Check if zoomed area is within the pane (#1289). + // In case of multiple panes only one pane should be zoomed. + if ((!isXAxis && + mouseDownPos >= axisStartPos && + mouseDownPos <= axisEndPos) || + isXAxis || + !defined(mouseDownPos)) { + isWithinPane = true; + } + // don't zoom more than minRange + if (pointer[isXAxis ? 'zoomX' : 'zoomY'] && isWithinPane) { + hasZoomed = axis.zoom(axisData.min, axisData.max); + if (axis.displayBtn) { + displayButton = true; + } + } + }); + } + // Show or hide the Reset zoom button + resetZoomButton = chart.resetZoomButton; + if (displayButton && !resetZoomButton) { + chart.showResetZoom(); + } + else if (!displayButton && isObject(resetZoomButton)) { + chart.resetZoomButton = resetZoomButton.destroy(); + } + // Redraw + if (hasZoomed) { + chart.redraw(pick(chart.options.chart.animation, event && event.animation, chart.pointCount < 100)); + } + }, + /** + * Pan the chart by dragging the mouse across the pane. This function is + * called on mouse move, and the distance to pan is computed from chartX + * compared to the first chartX position in the dragging operation. + * + * @private + * @function Highcharts.Chart#pan + * @param {Highcharts.PointerEventObject} e + * @param {string} panning + */ + pan: function (e, panning) { + var chart = this, hoverPoints = chart.hoverPoints, panningOptions, chartOptions = chart.options.chart, hasMapNavigation = chart.options.mapNavigation && + chart.options.mapNavigation.enabled, doRedraw, type; + if (typeof panning === 'object') { + panningOptions = panning; + } + else { + panningOptions = { + enabled: panning, + type: 'x' + }; + } + if (chartOptions && chartOptions.panning) { + chartOptions.panning = panningOptions; + } + type = panningOptions.type; + fireEvent(this, 'pan', { originalEvent: e }, function () { + // remove active points for shared tooltip + if (hoverPoints) { + hoverPoints.forEach(function (point) { + point.setState(); + }); + } + // panning axis mapping + var xy = [1]; // x + if (type === 'xy') { + xy = [1, 0]; + } + else if (type === 'y') { + xy = [0]; + } + xy.forEach(function (isX) { + var axis = chart[isX ? 'xAxis' : 'yAxis'][0], axisOpt = axis.options, horiz = axis.horiz, mousePos = e[horiz ? 'chartX' : 'chartY'], mouseDown = horiz ? 'mouseDownX' : 'mouseDownY', startPos = chart[mouseDown], halfPointRange = (axis.pointRange || 0) / 2, pointRangeDirection = (axis.reversed && !chart.inverted) || + (!axis.reversed && chart.inverted) ? + -1 : + 1, extremes = axis.getExtremes(), panMin = axis.toValue(startPos - mousePos, true) + + halfPointRange * pointRangeDirection, panMax = axis.toValue(startPos + axis.len - mousePos, true) - + halfPointRange * pointRangeDirection, flipped = panMax < panMin, newMin = flipped ? panMax : panMin, newMax = flipped ? panMin : panMax, hasVerticalPanning = axis.hasVerticalPanning(), paddedMin, paddedMax, spill, panningState = axis.panningState; + // General calculations of panning state. + // This is related to using vertical panning. (#11315). + axis.series.forEach(function (series) { + if (hasVerticalPanning && + !isX && (!panningState || panningState.isDirty)) { + var processedData = series.getProcessedData(true), dataExtremes = series.getExtremes(processedData.yData, true); + if (!panningState) { + panningState = { + startMin: Number.MAX_VALUE, + startMax: -Number.MAX_VALUE + }; + } + if (isNumber(dataExtremes.dataMin) && + isNumber(dataExtremes.dataMax)) { + panningState.startMin = Math.min(dataExtremes.dataMin, panningState.startMin); + panningState.startMax = Math.max(dataExtremes.dataMax, panningState.startMax); + } + } + }); + paddedMin = Math.min(H.pick(panningState === null || panningState === void 0 ? void 0 : panningState.startMin, extremes.dataMin), halfPointRange ? + extremes.min : + axis.toValue(axis.toPixels(extremes.min) - + axis.minPixelPadding)); + paddedMax = Math.max(H.pick(panningState === null || panningState === void 0 ? void 0 : panningState.startMax, extremes.dataMax), halfPointRange ? + extremes.max : + axis.toValue(axis.toPixels(extremes.max) + + axis.minPixelPadding)); + axis.panningState = panningState; + // It is not necessary to calculate extremes on ordinal axis, + // because the are already calculated, so we don't want to + // override them. + if (!axisOpt.ordinal) { + // If the new range spills over, either to the min or max, + // adjust the new range. + spill = paddedMin - newMin; + if (spill > 0) { + newMax += spill; + newMin = paddedMin; + } + spill = newMax - paddedMax; + if (spill > 0) { + newMax = paddedMax; + newMin -= spill; + } + // Set new extremes if they are actually new + if (axis.series.length && + newMin !== extremes.min && + newMax !== extremes.max && + isX ? true : (panningState && + newMin >= paddedMin && + newMax <= paddedMax)) { + axis.setExtremes(newMin, newMax, false, false, { trigger: 'pan' }); + if (!chart.resetZoomButton && + !hasMapNavigation && + type.match('y')) { + chart.showResetZoom(); + axis.displayBtn = false; + } + doRedraw = true; + } + // set new reference for next run: + chart[mouseDown] = mousePos; + } + }); + if (doRedraw) { + chart.redraw(false); + } + css(chart.container, { cursor: 'move' }); + }); + } + }); + // Extend the Point object with interaction + extend(Point.prototype, /** @lends Highcharts.Point.prototype */ { + /** + * Toggle the selection status of a point. + * + * @see Highcharts.Chart#getSelectedPoints + * + * @sample highcharts/members/point-select/ + * Select a point from a button + * @sample highcharts/chart/events-selection-points/ + * Select a range of points through a drag selection + * @sample maps/series/data-id/ + * Select a point in Highmaps + * + * @function Highcharts.Point#select + * + * @param {boolean} [selected] + * When `true`, the point is selected. When `false`, the point is + * unselected. When `null` or `undefined`, the selection state is toggled. + * + * @param {boolean} [accumulate=false] + * When `true`, the selection is added to other selected points. + * When `false`, other selected points are deselected. Internally in + * Highcharts, when + * [allowPointSelect](https://api.highcharts.com/highcharts/plotOptions.series.allowPointSelect) + * is `true`, selected points are accumulated on Control, Shift or Cmd + * clicking the point. + * + * @fires Highcharts.Point#event:select + * @fires Highcharts.Point#event:unselect + */ + select: function (selected, accumulate) { + var point = this, series = point.series, chart = series.chart; + selected = pick(selected, !point.selected); + this.selectedStaging = selected; + // fire the event with the default handler + point.firePointEvent(selected ? 'select' : 'unselect', { accumulate: accumulate }, function () { + /** + * Whether the point is selected or not. + * + * @see Point#select + * @see Chart#getSelectedPoints + * + * @name Highcharts.Point#selected + * @type {boolean} + */ + point.selected = point.options.selected = selected; + series.options.data[series.data.indexOf(point)] = + point.options; + point.setState(selected && 'select'); + // unselect all other points unless Ctrl or Cmd + click + if (!accumulate) { + chart.getSelectedPoints().forEach(function (loopPoint) { + var loopSeries = loopPoint.series; + if (loopPoint.selected && loopPoint !== point) { + loopPoint.selected = loopPoint.options.selected = + false; + loopSeries.options.data[loopSeries.data.indexOf(loopPoint)] = loopPoint.options; + // Programatically selecting a point should restore + // normal state, but when click happened on other + // point, set inactive state to match other points + loopPoint.setState(chart.hoverPoints && + loopSeries.options.inactiveOtherPoints ? + 'inactive' : ''); + loopPoint.firePointEvent('unselect'); + } + }); + } + }); + delete this.selectedStaging; + }, + /** + * Runs on mouse over the point. Called internally from mouse and touch + * events. + * + * @function Highcharts.Point#onMouseOver + * + * @param {Highcharts.PointerEventObject} [e] + * The event arguments. + */ + onMouseOver: function (e) { + var point = this, series = point.series, chart = series.chart, pointer = chart.pointer; + e = e ? + pointer.normalize(e) : + // In cases where onMouseOver is called directly without an event + pointer.getChartCoordinatesFromPoint(point, chart.inverted); + pointer.runPointActions(e, point); + }, + /** + * Runs on mouse out from the point. Called internally from mouse and touch + * events. + * + * @function Highcharts.Point#onMouseOut + * @fires Highcharts.Point#event:mouseOut + */ + onMouseOut: function () { + var point = this, chart = point.series.chart; + point.firePointEvent('mouseOut'); + if (!point.series.options.inactiveOtherPoints) { + (chart.hoverPoints || []).forEach(function (p) { + p.setState(); + }); + } + chart.hoverPoints = chart.hoverPoint = null; + }, + /** + * Import events from the series' and point's options. Only do it on + * demand, to save processing time on hovering. + * + * @private + * @function Highcharts.Point#importEvents + */ + importEvents: function () { + if (!this.hasImportedEvents) { + var point = this, options = merge(point.series.options.point, point.options), events = options.events; + point.events = events; + objectEach(events, function (event, eventType) { + if (isFunction(event)) { + addEvent(point, eventType, event); + } + }); + this.hasImportedEvents = true; + } + }, + /** + * Set the point's state. + * + * @function Highcharts.Point#setState + * + * @param {Highcharts.PointStateValue|""} [state] + * The new state, can be one of `'hover'`, `'select'`, `'inactive'`, + * or `''` (an empty string), `'normal'` or `undefined` to set to + * normal state. + * @param {boolean} [move] + * State for animation. + * + * @fires Highcharts.Point#event:afterSetState + */ + setState: function (state, move) { + var point = this, series = point.series, previousState = point.state, stateOptions = (series.options.states[state || 'normal'] || + {}), markerOptions = (defaultPlotOptions[series.type].marker && + series.options.marker), normalDisabled = (markerOptions && markerOptions.enabled === false), markerStateOptions = ((markerOptions && + markerOptions.states && + markerOptions.states[state || 'normal']) || {}), stateDisabled = markerStateOptions.enabled === false, stateMarkerGraphic = series.stateMarkerGraphic, pointMarker = point.marker || {}, chart = series.chart, halo = series.halo, haloOptions, markerAttribs, pointAttribs, pointAttribsAnimation, hasMarkers = (markerOptions && series.markerAttribs), newSymbol; + state = state || ''; // empty string + if ( + // already has this state + (state === point.state && !move) || + // selected points don't respond to hover + (point.selected && state !== 'select') || + // series' state options is disabled + (stateOptions.enabled === false) || + // general point marker's state options is disabled + (state && (stateDisabled || + (normalDisabled && + markerStateOptions.enabled === false))) || + // individual point marker's state options is disabled + (state && + pointMarker.states && + pointMarker.states[state] && + pointMarker.states[state].enabled === false) // #1610 + ) { + return; + } + point.state = state; + if (hasMarkers) { + markerAttribs = series.markerAttribs(point, state); + } + // Apply hover styles to the existing point + if (point.graphic) { + if (previousState) { + point.graphic.removeClass('highcharts-point-' + previousState); + } + if (state) { + point.graphic.addClass('highcharts-point-' + state); + } + if (!chart.styledMode) { + pointAttribs = series.pointAttribs(point, state); + pointAttribsAnimation = pick(chart.options.chart.animation, stateOptions.animation); + // Some inactive points (e.g. slices in pie) should apply + // oppacity also for it's labels + if (series.options.inactiveOtherPoints && pointAttribs.opacity) { + (point.dataLabels || []).forEach(function (label) { + if (label) { + label.animate({ + opacity: pointAttribs.opacity + }, pointAttribsAnimation); + } + }); + if (point.connector) { + point.connector.animate({ + opacity: pointAttribs.opacity + }, pointAttribsAnimation); + } + } + point.graphic.animate(pointAttribs, pointAttribsAnimation); + } + if (markerAttribs) { + point.graphic.animate(markerAttribs, pick( + // Turn off globally: + chart.options.chart.animation, markerStateOptions.animation, markerOptions.animation)); + } + // Zooming in from a range with no markers to a range with markers + if (stateMarkerGraphic) { + stateMarkerGraphic.hide(); + } + } + else { + // if a graphic is not applied to each point in the normal state, + // create a shared graphic for the hover state + if (state && markerStateOptions) { + newSymbol = pointMarker.symbol || series.symbol; + // If the point has another symbol than the previous one, throw + // away the state marker graphic and force a new one (#1459) + if (stateMarkerGraphic && + stateMarkerGraphic.currentSymbol !== newSymbol) { + stateMarkerGraphic = stateMarkerGraphic.destroy(); + } + // Add a new state marker graphic + if (markerAttribs) { + if (!stateMarkerGraphic) { + if (newSymbol) { + series.stateMarkerGraphic = stateMarkerGraphic = + chart.renderer + .symbol(newSymbol, markerAttribs.x, markerAttribs.y, markerAttribs.width, markerAttribs.height) + .add(series.markerGroup); + stateMarkerGraphic.currentSymbol = newSymbol; + } + // Move the existing graphic + } + else { + stateMarkerGraphic[move ? 'animate' : 'attr']({ + x: markerAttribs.x, + y: markerAttribs.y + }); + } + } + if (!chart.styledMode && stateMarkerGraphic) { + stateMarkerGraphic.attr(series.pointAttribs(point, state)); + } + } + if (stateMarkerGraphic) { + stateMarkerGraphic[state && point.isInside ? 'show' : 'hide'](); // #2450 + stateMarkerGraphic.element.point = point; // #4310 + } + } + // Show me your halo + haloOptions = stateOptions.halo; + var markerGraphic = (point.graphic || stateMarkerGraphic); + var markerVisibility = (markerGraphic && markerGraphic.visibility || 'inherit'); + if (haloOptions && + haloOptions.size && + markerGraphic && + markerVisibility !== 'hidden' && + !point.isCluster) { + if (!halo) { + series.halo = halo = chart.renderer.path() + // #5818, #5903, #6705 + .add(markerGraphic.parentGroup); + } + halo.show()[move ? 'animate' : 'attr']({ + d: point.haloPath(haloOptions.size) + }); + halo.attr({ + 'class': 'highcharts-halo highcharts-color-' + + pick(point.colorIndex, series.colorIndex) + + (point.className ? ' ' + point.className : ''), + 'visibility': markerVisibility, + 'zIndex': -1 // #4929, #8276 + }); + halo.point = point; // #6055 + if (!chart.styledMode) { + halo.attr(extend({ + 'fill': point.color || series.color, + 'fill-opacity': haloOptions.opacity + }, haloOptions.attributes)); + } + } + else if (halo && halo.point && halo.point.haloPath) { + // Animate back to 0 on the current halo point (#6055) + halo.animate({ d: halo.point.haloPath(0) }, null, + // Hide after unhovering. The `complete` callback runs in the + // halo's context (#7681). + halo.hide); + } + fireEvent(point, 'afterSetState'); + }, + /** + * Get the path definition for the halo, which is usually a shadow-like + * circle around the currently hovered point. + * + * @function Highcharts.Point#haloPath + * + * @param {number} size + * The radius of the circular halo. + * + * @return {Highcharts.SVGPathArray} + * The path definition. + */ + haloPath: function (size) { + var series = this.series, chart = series.chart; + return chart.renderer.symbols.circle(Math.floor(this.plotX) - size, this.plotY - size, size * 2, size * 2); + } + }); + // Extend the Series object with interaction + extend(Series.prototype, /** @lends Highcharts.Series.prototype */ { + /** + * Runs on mouse over the series graphical items. + * + * @function Highcharts.Series#onMouseOver + * @fires Highcharts.Series#event:mouseOver + */ + onMouseOver: function () { + var series = this, chart = series.chart, hoverSeries = chart.hoverSeries, pointer = chart.pointer; + pointer.setHoverChartIndex(); + // set normal state to previous series + if (hoverSeries && hoverSeries !== series) { + hoverSeries.onMouseOut(); + } + // trigger the event, but to save processing time, + // only if defined + if (series.options.events.mouseOver) { + fireEvent(series, 'mouseOver'); + } + // hover this + series.setState('hover'); + /** + * Contains the original hovered series. + * + * @name Highcharts.Chart#hoverSeries + * @type {Highcharts.Series|null} + */ + chart.hoverSeries = series; + }, + /** + * Runs on mouse out of the series graphical items. + * + * @function Highcharts.Series#onMouseOut + * + * @fires Highcharts.Series#event:mouseOut + */ + onMouseOut: function () { + // trigger the event only if listeners exist + var series = this, options = series.options, chart = series.chart, tooltip = chart.tooltip, hoverPoint = chart.hoverPoint; + // #182, set to null before the mouseOut event fires + chart.hoverSeries = null; + // trigger mouse out on the point, which must be in this series + if (hoverPoint) { + hoverPoint.onMouseOut(); + } + // fire the mouse out event + if (series && options.events.mouseOut) { + fireEvent(series, 'mouseOut'); + } + // hide the tooltip + if (tooltip && + !series.stickyTracking && + (!tooltip.shared || series.noSharedTooltip)) { + tooltip.hide(); + } + // Reset all inactive states + chart.series.forEach(function (s) { + s.setState('', true); + }); + }, + /** + * Set the state of the series. Called internally on mouse interaction + * operations, but it can also be called directly to visually + * highlight a series. + * + * @function Highcharts.Series#setState + * + * @param {Highcharts.SeriesStateValue|""} [state] + * The new state, can be either `'hover'`, `'inactive'`, `'select'`, + * or `''` (an empty string), `'normal'` or `undefined` to set to + * normal state. + * @param {boolean} [inherit] + * Determines if state should be inherited by points too. + */ + setState: function (state, inherit) { + var series = this, options = series.options, graph = series.graph, inactiveOtherPoints = options.inactiveOtherPoints, stateOptions = options.states, lineWidth = options.lineWidth, opacity = options.opacity, + // By default a quick animation to hover/inactive, + // slower to un-hover + stateAnimation = pick((stateOptions[state || 'normal'] && + stateOptions[state || 'normal'].animation), series.chart.options.chart.animation), attribs, i = 0; + state = state || ''; + if (series.state !== state) { + // Toggle class names + [ + series.group, + series.markerGroup, + series.dataLabelsGroup + ].forEach(function (group) { + if (group) { + // Old state + if (series.state) { + group.removeClass('highcharts-series-' + series.state); + } + // New state + if (state) { + group.addClass('highcharts-series-' + state); + } + } + }); + series.state = state; + if (!series.chart.styledMode) { + if (stateOptions[state] && + stateOptions[state].enabled === false) { + return; + } + if (state) { + lineWidth = (stateOptions[state].lineWidth || + lineWidth + (stateOptions[state].lineWidthPlus || 0)); // #4035 + opacity = pick(stateOptions[state].opacity, opacity); + } + if (graph && !graph.dashstyle) { + attribs = { + 'stroke-width': lineWidth + }; + // Animate the graph stroke-width. + graph.animate(attribs, stateAnimation); + while (series['zone-graph-' + i]) { + series['zone-graph-' + i].attr(attribs); + i = i + 1; + } + } + // For some types (pie, networkgraph, sankey) opacity is + // resolved on a point level + if (!inactiveOtherPoints) { + [ + series.group, + series.markerGroup, + series.dataLabelsGroup, + series.labelBySeries + ].forEach(function (group) { + if (group) { + group.animate({ + opacity: opacity + }, stateAnimation); + } + }); + } + } + } + // Don't loop over points on a series that doesn't apply inactive state + // to siblings markers (e.g. line, column) + if (inherit && inactiveOtherPoints && series.points) { + series.setAllPointsToState(state); + } + }, + /** + * Set the state for all points in the series. + * + * @function Highcharts.Series#setAllPointsToState + * + * @private + * + * @param {string} [state] + * Can be either `hover` or undefined to set to normal state. + */ + setAllPointsToState: function (state) { + this.points.forEach(function (point) { + if (point.setState) { + point.setState(state); + } + }); + }, + /** + * Show or hide the series. + * + * @function Highcharts.Series#setVisible + * + * @param {boolean} [visible] + * True to show the series, false to hide. If undefined, the visibility is + * toggled. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart after the series is altered. If doing more + * operations on the chart, it is a good idea to set redraw to false and + * call {@link Chart#redraw|chart.redraw()} after. + * + * @fires Highcharts.Series#event:hide + * @fires Highcharts.Series#event:show + */ + setVisible: function (vis, redraw) { + var series = this, chart = series.chart, legendItem = series.legendItem, showOrHide, ignoreHiddenSeries = chart.options.chart.ignoreHiddenSeries, oldVisibility = series.visible; + // if called without an argument, toggle visibility + series.visible = + vis = + series.options.visible = + series.userOptions.visible = + typeof vis === 'undefined' ? !oldVisibility : vis; // #5618 + showOrHide = vis ? 'show' : 'hide'; + // show or hide elements + [ + 'group', + 'dataLabelsGroup', + 'markerGroup', + 'tracker', + 'tt' + ].forEach(function (key) { + if (series[key]) { + series[key][showOrHide](); + } + }); + // hide tooltip (#1361) + if (chart.hoverSeries === series || + (chart.hoverPoint && chart.hoverPoint.series) === series) { + series.onMouseOut(); + } + if (legendItem) { + chart.legend.colorizeItem(series, vis); + } + // rescale or adapt to resized chart + series.isDirty = true; + // in a stack, all other series are affected + if (series.options.stacking) { + chart.series.forEach(function (otherSeries) { + if (otherSeries.options.stacking && otherSeries.visible) { + otherSeries.isDirty = true; + } + }); + } + // show or hide linked series + series.linkedSeries.forEach(function (otherSeries) { + otherSeries.setVisible(vis, false); + }); + if (ignoreHiddenSeries) { + chart.isDirtyBox = true; + } + fireEvent(series, showOrHide); + if (redraw !== false) { + chart.redraw(); + } + }, + /** + * Show the series if hidden. + * + * @sample highcharts/members/series-hide/ + * Toggle visibility from a button + * + * @function Highcharts.Series#show + * @fires Highcharts.Series#event:show + */ + show: function () { + this.setVisible(true); + }, + /** + * Hide the series if visible. If the + * [chart.ignoreHiddenSeries](https://api.highcharts.com/highcharts/chart.ignoreHiddenSeries) + * option is true, the chart is redrawn without this series. + * + * @sample highcharts/members/series-hide/ + * Toggle visibility from a button + * + * @function Highcharts.Series#hide + * @fires Highcharts.Series#event:hide + */ + hide: function () { + this.setVisible(false); + }, + /** + * Select or unselect the series. This means its + * {@link Highcharts.Series.selected|selected} + * property is set, the checkbox in the legend is toggled and when selected, + * the series is returned by the {@link Highcharts.Chart#getSelectedSeries} + * function. + * + * @sample highcharts/members/series-select/ + * Select a series from a button + * + * @function Highcharts.Series#select + * + * @param {boolean} [selected] + * True to select the series, false to unselect. If undefined, the selection + * state is toggled. + * + * @fires Highcharts.Series#event:select + * @fires Highcharts.Series#event:unselect + */ + select: function (selected) { + var series = this; + series.selected = + selected = + this.options.selected = (typeof selected === 'undefined' ? + !series.selected : + selected); + if (series.checkbox) { + series.checkbox.checked = selected; + } + fireEvent(series, selected ? 'select' : 'unselect'); + }, + /** + * @private + * @borrows Highcharts.TrackerMixin.drawTrackerGraph as Highcharts.Series#drawTracker + */ + drawTracker: TrackerMixin.drawTrackerGraph + }); + + }); + _registerModule(_modules, 'parts/Responsive.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * A callback function to gain complete control on when the responsive rule + * applies. + * + * @callback Highcharts.ResponsiveCallbackFunction + * + * @param {Highcharts.Chart} this + * Chart context. + * + * @return {boolean} + * Return `true` if it applies. + */ + var find = U.find, isArray = U.isArray, isObject = U.isObject, merge = U.merge, objectEach = U.objectEach, pick = U.pick, splat = U.splat, uniqueKey = U.uniqueKey; + var Chart = H.Chart; + /** + * Allows setting a set of rules to apply for different screen or chart + * sizes. Each rule specifies additional chart options. + * + * @sample {highstock} stock/demo/responsive/ + * Stock chart + * @sample highcharts/responsive/axis/ + * Axis + * @sample highcharts/responsive/legend/ + * Legend + * @sample highcharts/responsive/classname/ + * Class name + * + * @since 5.0.0 + * @apioption responsive + */ + /** + * A set of rules for responsive settings. The rules are executed from + * the top down. + * + * @sample {highcharts} highcharts/responsive/axis/ + * Axis changes + * @sample {highstock} highcharts/responsive/axis/ + * Axis changes + * @sample {highmaps} highcharts/responsive/axis/ + * Axis changes + * + * @type {Array<*>} + * @since 5.0.0 + * @apioption responsive.rules + */ + /** + * A full set of chart options to apply as overrides to the general + * chart options. The chart options are applied when the given rule + * is active. + * + * A special case is configuration objects that take arrays, for example + * [xAxis](#xAxis), [yAxis](#yAxis) or [series](#series). For these + * collections, an `id` option is used to map the new option set to + * an existing object. If an existing object of the same id is not found, + * the item of the same indexupdated. So for example, setting `chartOptions` + * with two series items without an `id`, will cause the existing chart's + * two series to be updated with respective options. + * + * @sample {highstock} stock/demo/responsive/ + * Stock chart + * @sample highcharts/responsive/axis/ + * Axis + * @sample highcharts/responsive/legend/ + * Legend + * @sample highcharts/responsive/classname/ + * Class name + * + * @type {Highcharts.Options} + * @since 5.0.0 + * @apioption responsive.rules.chartOptions + */ + /** + * Under which conditions the rule applies. + * + * @since 5.0.0 + * @apioption responsive.rules.condition + */ + /** + * A callback function to gain complete control on when the responsive + * rule applies. Return `true` if it applies. This opens for checking + * against other metrics than the chart size, for example the document + * size or other elements. + * + * @type {Highcharts.ResponsiveCallbackFunction} + * @since 5.0.0 + * @context Highcharts.Chart + * @apioption responsive.rules.condition.callback + */ + /** + * The responsive rule applies if the chart height is less than this. + * + * @type {number} + * @since 5.0.0 + * @apioption responsive.rules.condition.maxHeight + */ + /** + * The responsive rule applies if the chart width is less than this. + * + * @sample highcharts/responsive/axis/ + * Max width is 500 + * + * @type {number} + * @since 5.0.0 + * @apioption responsive.rules.condition.maxWidth + */ + /** + * The responsive rule applies if the chart height is greater than this. + * + * @type {number} + * @default 0 + * @since 5.0.0 + * @apioption responsive.rules.condition.minHeight + */ + /** + * The responsive rule applies if the chart width is greater than this. + * + * @type {number} + * @default 0 + * @since 5.0.0 + * @apioption responsive.rules.condition.minWidth + */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Update the chart based on the current chart/document size and options for + * responsiveness. + * + * @private + * @function Highcharts.Chart#setResponsive + * @param {boolean} [redraw=true] + * @param {boolean} [reset=false] + * Reset by un-applying all rules. Chart.update resets all rules before + * applying updated options. + * @return {void} + */ + Chart.prototype.setResponsive = function (redraw, reset) { + var options = this.options.responsive, ruleIds = [], currentResponsive = this.currentResponsive, currentRuleIds, undoOptions; + if (!reset && options && options.rules) { + options.rules.forEach(function (rule) { + if (typeof rule._id === 'undefined') { + rule._id = uniqueKey(); + } + this.matchResponsiveRule(rule, ruleIds /* , redraw */); + }, this); + } + // Merge matching rules + var mergedOptions = merge.apply(0, ruleIds.map(function (ruleId) { + return find(options.rules, function (rule) { + return rule._id === ruleId; + }).chartOptions; + })); + mergedOptions.isResponsiveOptions = true; + // Stringified key for the rules that currently apply. + ruleIds = (ruleIds.toString() || void 0); + currentRuleIds = currentResponsive && currentResponsive.ruleIds; + // Changes in what rules apply + if (ruleIds !== currentRuleIds) { + // Undo previous rules. Before we apply a new set of rules, we need to + // roll back completely to base options (#6291). + if (currentResponsive) { + this.update(currentResponsive.undoOptions, redraw, true); + } + if (ruleIds) { + // Get undo-options for matching rules + undoOptions = this.currentOptions(mergedOptions); + undoOptions.isResponsiveOptions = true; + this.currentResponsive = { + ruleIds: ruleIds, + mergedOptions: mergedOptions, + undoOptions: undoOptions + }; + this.update(mergedOptions, redraw, true); + } + else { + this.currentResponsive = void 0; + } + } + }; + /** + * Handle a single responsiveness rule. + * + * @private + * @function Highcharts.Chart#matchResponsiveRule + * @param {Highcharts.ResponsiveRulesOptions} rule + * @param {Array} matches + * @return {void} + */ + Chart.prototype.matchResponsiveRule = function (rule, matches) { + var condition = rule.condition, fn = condition.callback || function () { + return (this.chartWidth <= pick(condition.maxWidth, Number.MAX_VALUE) && + this.chartHeight <= + pick(condition.maxHeight, Number.MAX_VALUE) && + this.chartWidth >= pick(condition.minWidth, 0) && + this.chartHeight >= pick(condition.minHeight, 0)); + }; + if (fn.call(this)) { + matches.push(rule._id); + } + }; + /** + * Get the current values for a given set of options. Used before we update + * the chart with a new responsiveness rule. + * TODO: Restore axis options (by id?) + * + * @private + * @function Highcharts.Chart#currentOptions + * @param {Highcharts.Options} options + * @return {Highcharts.Options} + */ + Chart.prototype.currentOptions = function (options) { + var chart = this, ret = {}; + /** + * Recurse over a set of options and its current values, + * and store the current values in the ret object. + */ + function getCurrent(options, curr, ret, depth) { + var i; + objectEach(options, function (val, key) { + if (!depth && + chart.collectionsWithUpdate.indexOf(key) > -1) { + val = splat(val); + ret[key] = []; + // Iterate over collections like series, xAxis or yAxis and map + // the items by index. + for (i = 0; i < val.length; i++) { + if (curr[key][i]) { // Item exists in current data (#6347) + ret[key][i] = {}; + getCurrent(val[i], curr[key][i], ret[key][i], depth + 1); + } + } + } + else if (isObject(val)) { + ret[key] = isArray(val) ? [] : {}; + getCurrent(val, curr[key] || {}, ret[key], depth + 1); + } + else if (typeof curr[key] === 'undefined') { // #10286 + ret[key] = null; + } + else { + ret[key] = curr[key]; + } + }); + } + getCurrent(options, this.options, ret, 0); + return ret; + }; + + }); + _registerModule(_modules, 'masters/highcharts.src.js', [_modules['parts/Globals.js']], function (Highcharts) { + + + return Highcharts; + }); + _modules['masters/highcharts.src.js']._modules = _modules; + return _modules['masters/highcharts.src.js']; +})); \ No newline at end of file diff --git a/librerias/gantt/code/lib/canvg.js b/librerias/gantt/code/lib/canvg.js new file mode 100644 index 0000000..df619d0 --- /dev/null +++ b/librerias/gantt/code/lib/canvg.js @@ -0,0 +1,130 @@ +/* + + canvg.js - Javascript SVG parser and renderer on Canvas + MIT Licensed + Gabe Lerner (gabelerner@gmail.com) + http://code.google.com/p/canvg/ + + Requires: rgbcolor.js - http://www.phpied.com/rgb-color-parser-in-javascript/ +*/ +(function(x,y){"undefined"!==typeof define&&define.amd?define("canvgModule",["rgbcolor","stackblur"],y):"undefined"!==typeof module&&module.exports&&(module.exports=y(require("rgbcolor"),require("stackblur")));x.canvg=y(x.RGBColor,x.stackBlur)})("undefined"!==typeof window?window:this,function(x,y){function A(h){var a=[0,0,0],l=function(c,b){var e=h.match(c);null!=e&&(a[b]+=e.length,h=h.replace(c," "))};h=h.replace(/:not\(([^\)]*)\)/g," $1 ");h=h.replace(/{[^]*/gm," ");l(B,1);l(C,0);l(D,1);l(E, +2);l(F,1);l(G,1);h=h.replace(/[\*\s\+>~]/g," ");h=h.replace(/[#\.]/g," ");l(H,2);return a.join("")}function I(h){var a={opts:h,FRAMERATE:30,MAX_VIRTUAL_PIXELS:3E4,log:function(a){}};1==a.opts.log&&"undefined"!=typeof console&&(a.log=function(a){console.log(a)});a.init=function(c){var b=0;a.UniqueId=function(){b++;return"canvg"+b};a.Definitions={};a.Styles={};a.StylesSpecificity={};a.Animations=[];a.Images=[];a.ctx=c;a.ViewPort=new function(){this.viewPorts=[];this.Clear=function(){this.viewPorts= +[]};this.SetCurrent=function(a,b){this.viewPorts.push({width:a,height:b})};this.RemoveCurrent=function(){this.viewPorts.pop()};this.Current=function(){return this.viewPorts[this.viewPorts.length-1]};this.width=function(){return this.Current().width};this.height=function(){return this.Current().height};this.ComputeSize=function(a){return null!=a&&"number"==typeof a?a:"x"==a?this.width():"y"==a?this.height():Math.sqrt(Math.pow(this.width(),2)+Math.pow(this.height(),2))/Math.sqrt(2)}}};a.init();a.ImagesLoaded= +function(){for(var c=0;c]*>/,"");b=new ActiveXObject("Microsoft.XMLDOM");b.async="false";b.loadXML(a);return b};a.Property=function(a,b){this.name=a;this.value=b};a.Property.prototype.getValue=function(){return this.value};a.Property.prototype.hasValue=function(){return null!=this.value&&""!==this.value}; +a.Property.prototype.numValue=function(){if(!this.hasValue())return 0;var a=parseFloat(this.value);(this.value+"").match(/%$/)&&(a/=100);return a};a.Property.prototype.valueOrDefault=function(a){return this.hasValue()?this.value:a};a.Property.prototype.numValueOrDefault=function(a){return this.hasValue()?this.numValue():a};a.Property.prototype.addOpacity=function(c){var b=this.value;if(null!=c.value&&""!=c.value&&"string"==typeof this.value){var e=new x(this.value);e.ok&&(b="rgba("+e.r+", "+e.g+", "+ +e.b+", "+c.numValue()+")")}return new a.Property(this.name,b)};a.Property.prototype.getDefinition=function(){var c=this.value.match(/#([^\)'"]+)/);c&&(c=c[1]);c||(c=this.value);return a.Definitions[c]};a.Property.prototype.isUrlDefinition=function(){return 0==this.value.indexOf("url(")};a.Property.prototype.getFillStyleDefinition=function(c,b){var e=this.getDefinition();if(null!=e&&e.createGradient)return e.createGradient(a.ctx,c,b);if(null!=e&&e.createPattern){if(e.getHrefAttribute().hasValue()){var d= +e.attribute("patternTransform"),e=e.getHrefAttribute().getDefinition();d.hasValue()&&(e.attribute("patternTransform",!0).value=d.value)}return e.createPattern(a.ctx,c)}return null};a.Property.prototype.getDPI=function(a){return 96};a.Property.prototype.getEM=function(c){var b=12,e=new a.Property("fontSize",a.Font.Parse(a.ctx.font).fontSize);e.hasValue()&&(b=e.toPixels(c));return b};a.Property.prototype.getUnits=function(){return(this.value+"").replace(/[0-9\.\-]/g,"")};a.Property.prototype.toPixels= +function(c,b){if(!this.hasValue())return 0;var e=this.value+"";if(e.match(/em$/))return this.numValue()*this.getEM(c);if(e.match(/ex$/))return this.numValue()*this.getEM(c)/2;if(e.match(/px$/))return this.numValue();if(e.match(/pt$/))return this.numValue()*this.getDPI(c)*(1/72);if(e.match(/pc$/))return 15*this.numValue();if(e.match(/cm$/))return this.numValue()*this.getDPI(c)/2.54;if(e.match(/mm$/))return this.numValue()*this.getDPI(c)/25.4;if(e.match(/in$/))return this.numValue()*this.getDPI(c); +if(e.match(/%$/))return this.numValue()*a.ViewPort.ComputeSize(c);e=this.numValue();return b&&1>e?e*a.ViewPort.ComputeSize(c):e};a.Property.prototype.toMilliseconds=function(){if(!this.hasValue())return 0;var a=this.value+"";if(a.match(/s$/))return 1E3*this.numValue();a.match(/ms$/);return this.numValue()};a.Property.prototype.toRadians=function(){if(!this.hasValue())return 0;var a=this.value+"";return a.match(/deg$/)?this.numValue()*(Math.PI/180):a.match(/grad$/)?this.numValue()*(Math.PI/200):a.match(/rad$/)? +this.numValue():this.numValue()*(Math.PI/180)};var l={baseline:"alphabetic","before-edge":"top","text-before-edge":"top",middle:"middle",central:"middle","after-edge":"bottom","text-after-edge":"bottom",ideographic:"ideographic",alphabetic:"alphabetic",hanging:"hanging",mathematical:"alphabetic"};a.Property.prototype.toTextBaseline=function(){return this.hasValue()?l[this.value]:null};a.Font=new function(){this.Styles="normal|italic|oblique|inherit";this.Variants="normal|small-caps|inherit";this.Weights= +"normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900|inherit";this.CreateFont=function(b,e,d,c,f,g){g=null!=g?this.Parse(g):this.CreateFont("","","","","",a.ctx.font);return{fontFamily:f||g.fontFamily,fontSize:c||g.fontSize,fontStyle:b||g.fontStyle,fontWeight:d||g.fontWeight,fontVariant:e||g.fontVariant,toString:function(){return[this.fontStyle,this.fontVariant,this.fontWeight,this.fontSize,this.fontFamily].join(" ")}}};var c=this;this.Parse=function(b){var e={};b=a.trim(a.compressSpaces(b|| +"")).split(" ");for(var d=!1,k=!1,f=!1,g=!1,m="",n=0;nthis.x2&&(this.x2=a)}if(null!=b){if(isNaN(this.y1)||isNaN(this.y2))this.y2=this.y1=b;bthis.y2&&(this.y2=b)}};this.addX=function(a){this.addPoint(a, +null)};this.addY=function(a){this.addPoint(null,a)};this.addBoundingBox=function(a){this.addPoint(a.x1,a.y1);this.addPoint(a.x2,a.y2)};this.addQuadraticCurve=function(a,b,e,d,c,r){e=a+2/3*(e-a);d=b+2/3*(d-b);this.addBezierCurve(a,b,e,e+1/3*(c-a),d,d+1/3*(r-b),c,r)};this.addBezierCurve=function(a,b,e,d,c,r,u,p){var t=[a,b],h=[e,d],q=[c,r],l=[u,p];this.addPoint(t[0],t[1]);this.addPoint(l[0],l[1]);for(i=0;1>=i;i++)a=function(a){return Math.pow(1-a,3)*t[i]+3*Math.pow(1-a,2)*a*h[i]+3*(1-a)*Math.pow(a, +2)*q[i]+Math.pow(a,3)*l[i]},b=6*t[i]-12*h[i]+6*q[i],e=-3*t[i]+9*h[i]-9*q[i]+3*l[i],d=3*h[i]-3*t[i],0==e?0!=b&&(b=-d/b,0b&&(0==i&&this.addX(a(b)),1==i&&this.addY(a(b)))):(d=Math.pow(b,2)-4*d*e,0>d||(c=(-b+Math.sqrt(d))/(2*e),0c&&(0==i&&this.addX(a(c)),1==i&&this.addY(a(c))),b=(-b-Math.sqrt(d))/(2*e),0b&&(0==i&&this.addX(a(b)),1==i&&this.addY(a(b)))))};this.isPointInBox=function(a,b){return this.x1<=a&&a<=this.x2&&this.y1<=b&&b<=this.y2};this.addPoint(a,b);this.addPoint(e,d)};a.Transform= +function(c){var b=this;this.Type={};this.Type.translate=function(b){this.p=a.CreatePoint(b);this.apply=function(a){a.translate(this.p.x||0,this.p.y||0)};this.unapply=function(a){a.translate(-1*this.p.x||0,-1*this.p.y||0)};this.applyToPoint=function(a){a.applyTransform([1,0,0,1,this.p.x||0,this.p.y||0])}};this.Type.rotate=function(b){b=a.ToNumberArray(b);this.angle=new a.Property("angle",b[0]);this.cx=b[1]||0;this.cy=b[2]||0;this.apply=function(a){a.translate(this.cx,this.cy);a.rotate(this.angle.toRadians()); +a.translate(-this.cx,-this.cy)};this.unapply=function(a){a.translate(this.cx,this.cy);a.rotate(-1*this.angle.toRadians());a.translate(-this.cx,-this.cy)};this.applyToPoint=function(a){var b=this.angle.toRadians();a.applyTransform([1,0,0,1,this.p.x||0,this.p.y||0]);a.applyTransform([Math.cos(b),Math.sin(b),-Math.sin(b),Math.cos(b),0,0]);a.applyTransform([1,0,0,1,-this.p.x||0,-this.p.y||0])}};this.Type.scale=function(b){this.p=a.CreatePoint(b);this.apply=function(a){a.scale(this.p.x||1,this.p.y||this.p.x|| +1)};this.unapply=function(a){a.scale(1/this.p.x||1,1/this.p.y||this.p.x||1)};this.applyToPoint=function(a){a.applyTransform([this.p.x||0,0,0,this.p.y||0,0,0])}};this.Type.matrix=function(b){this.m=a.ToNumberArray(b);this.apply=function(a){a.transform(this.m[0],this.m[1],this.m[2],this.m[3],this.m[4],this.m[5])};this.unapply=function(a){var b=this.m[0],e=this.m[2],d=this.m[4],c=this.m[1],f=this.m[3],k=this.m[5],h=1/(b*(1*f-0*k)-e*(1*c-0*k)+d*(0*c-0*f));a.transform(h*(1*f-0*k),h*(0*k-1*c),h*(0*d-1* +e),h*(1*b-0*d),h*(e*k-d*f),h*(d*c-b*k))};this.applyToPoint=function(a){a.applyTransform(this.m)}};this.Type.SkewBase=function(e){this.base=b.Type.matrix;this.base(e);this.angle=new a.Property("angle",e)};this.Type.SkewBase.prototype=new this.Type.matrix;this.Type.skewX=function(a){this.base=b.Type.SkewBase;this.base(a);this.m=[1,0,Math.tan(this.angle.toRadians()),1,0,0]};this.Type.skewX.prototype=new this.Type.SkewBase;this.Type.skewY=function(a){this.base=b.Type.SkewBase;this.base(a);this.m=[1,Math.tan(this.angle.toRadians()), +0,1,0,0]};this.Type.skewY.prototype=new this.Type.SkewBase;this.transforms=[];this.apply=function(a){for(var b=0;br&&(this.styles[k]=e[k],this.stylesSpecificity[k]=d)}}};if(null!=c&&1==c.nodeType){for(var b=0;bb;b++)c=c.replace(/([MmZzLlHhVvCcSsQqTtAa])([^\s])/gm,"$1 $2");c=c.replace(/([^\s])([MmZzLlHhVvCcSsQqTtAa])/gm,"$1 $2");c=c.replace(/([0-9])([+\-])/gm,"$1 $2");for(b=0;2>b;b++)c=c.replace(/(\.[0-9]*)(\.)/gm,"$1 $2");c=c.replace(/([Aa](\s+[0-9]+){3})\s+([01])\s*([01])/gm,"$1 $3 $4 ");c=a.compressSpaces(c);c=a.trim(c);this.PathParser=new function(b){this.tokens=b.split(" "); +this.reset=function(){this.i=-1;this.previousCommand=this.command="";this.start=new a.Point(0,0);this.control=new a.Point(0,0);this.current=new a.Point(0,0);this.points=[];this.angles=[]};this.isEnd=function(){return this.i>=this.tokens.length-1};this.isCommandOrEnd=function(){return this.isEnd()?!0:null!=this.tokens[this.i+1].match(/^[A-Za-z]$/)};this.isRelativeCommand=function(){switch(this.command){case "m":case "l":case "h":case "v":case "c":case "s":case "q":case "t":case "a":case "z":return!0}return!1}; +this.getToken=function(){this.i++;return this.tokens[this.i]};this.getScalar=function(){return parseFloat(this.getToken())};this.nextCommand=function(){this.previousCommand=this.command;this.command=this.getToken()};this.getPoint=function(){var b=new a.Point(this.getScalar(),this.getScalar());return this.makeAbsolute(b)};this.getAsControlPoint=function(){var a=this.getPoint();return this.control=a};this.getAsCurrentPoint=function(){var a=this.getPoint();return this.current=a};this.getReflectedControlPoint= +function(){return"c"!=this.previousCommand.toLowerCase()&&"s"!=this.previousCommand.toLowerCase()&&"q"!=this.previousCommand.toLowerCase()&&"t"!=this.previousCommand.toLowerCase()?this.current:new a.Point(2*this.current.x-this.control.x,2*this.current.y-this.control.y)};this.makeAbsolute=function(a){this.isRelativeCommand()&&(a.x+=this.current.x,a.y+=this.current.y);return a};this.addMarker=function(a,b,e){null!=e&&0=w(v,q)&&(l=Math.PI);1<=w(v,q)&&(l=0);v=1-n?1:-1;q=p+l/2*v;x=new a.Point(m.x+ +r*Math.cos(q),m.y+h*Math.sin(q));d.addMarkerAngle(x,q-v*Math.PI/2);d.addMarkerAngle(f,q-v*Math.PI);c.addPoint(f.x,f.y);null!=b&&(w=r>h?r:h,f=r>h?1:r/h,r=r>h?h/r:1,b.translate(m.x,m.y),b.rotate(g),b.scale(f,r),b.arc(0,0,w,p,p+l,1-n),b.scale(1/f,1/r),b.rotate(-g),b.translate(-m.x,-m.y))}break;case "Z":case "z":null!=b&&b.closePath(),d.current=d.start}return c};this.getMarkers=function(){for(var a=this.PathParser.getMarkerPoints(),b=this.PathParser.getMarkerAngles(),c=[],f=0;f=c;c++)for(var m=-1;1>=m;m++)d.save(),f.attributes.x=new a.Property("x",c*g.width),f.attributes.y=new a.Property("y",m*g.height),f.render(d),d.restore();return b.createPattern(g,"repeat")}};a.Element.pattern.prototype= +new a.Element.ElementBase;a.Element.marker=function(c){this.base=a.Element.ElementBase;this.base(c);this.baseRender=this.render;this.render=function(b,e,d){b.translate(e.x,e.y);"auto"==this.attribute("orient").valueOrDefault("auto")&&b.rotate(d);"strokeWidth"==this.attribute("markerUnits").valueOrDefault("strokeWidth")&&b.scale(b.lineWidth,b.lineWidth);b.save();var c=new a.Element.svg;c.attributes.viewBox=new a.Property("viewBox",this.attribute("viewBox").value);c.attributes.refX=new a.Property("refX", +this.attribute("refX").value);c.attributes.refY=new a.Property("refY",this.attribute("refY").value);c.attributes.width=new a.Property("width",this.attribute("markerWidth").value);c.attributes.height=new a.Property("height",this.attribute("markerHeight").value);c.attributes.fill=new a.Property("fill",this.attribute("fill").valueOrDefault("black"));c.attributes.stroke=new a.Property("stroke",this.attribute("stroke").valueOrDefault("none"));c.children=this.children;c.render(b);b.restore();"strokeWidth"== +this.attribute("markerUnits").valueOrDefault("strokeWidth")&&b.scale(1/b.lineWidth,1/b.lineWidth);"auto"==this.attribute("orient").valueOrDefault("auto")&&b.rotate(-d);b.translate(-e.x,-e.y)}};a.Element.marker.prototype=new a.Element.ElementBase;a.Element.defs=function(c){this.base=a.Element.ElementBase;this.base(c);this.render=function(a){}};a.Element.defs.prototype=new a.Element.ElementBase;a.Element.GradientBase=function(c){this.base=a.Element.ElementBase;this.base(c);this.stops=[];for(c=0;cthis.offset&&(this.offset=0);1this.maxDuration){if("indefinite"==this.attribute("repeatCount").value||"indefinite"==this.attribute("repeatDur").value)this.duration=0;else if("freeze"==this.attribute("fill").valueOrDefault("remove")&&!this.frozen)this.frozen=!0,this.parent.animationFrozen=!0,this.parent.animationFrozenValue= +this.getProperty().value;else if("remove"==this.attribute("fill").valueOrDefault("remove")&&!this.removed)return this.removed=!0,this.getProperty().value=this.parent.animationFrozen?this.parent.animationFrozenValue:this.initialValue,!0;return!1}this.duration+=a;a=!1;this.begind&&m.attribute("x").hasValue())break;f+=m.measureTextRecursive(a)}return-1*("end"==k?f:f/2)}return 0};this.renderChild=function(a,c,d){var k=c.children[d];k.attribute("x").hasValue()?(k.x=k.attribute("x").toPixels("x")+c.getAnchorDelta(a,c,d),k.attribute("dx").hasValue()&&(k.x+=k.attribute("dx").toPixels("x"))):(k.attribute("dx").hasValue()&&(c.x+=k.attribute("dx").toPixels("x")),k.x=c.x);c.x=k.x+k.measureText(a);k.attribute("y").hasValue()?(k.y=k.attribute("y").toPixels("y"),k.attribute("dy").hasValue()&& +(k.y+=k.attribute("dy").toPixels("y"))):(k.attribute("dy").hasValue()&&(c.y+=k.attribute("dy").toPixels("y")),k.y=c.y);c.y=k.y;k.render(a);for(d=0;dc?b-255:b)}this.base=a.Element.ElementBase;this.base(c);var e=a.ToNumberArray(this.attribute("values").value);switch(this.attribute("type").valueOrDefault("matrix")){case "saturate":c=e[0];e=[.213+.787*c,.715-.715*c,.072-.072*c,0,0,.213-.213*c,.715+.285*c,.072-.072*c,0,0,.213-.213*c,.715-.715*c,.072+.928*c,0,0,0,0,0,1,0,0,0,0,0,1];break;case "hueRotate":var d=e[0]*Math.PI/180;c=function(a,b,c){return a+ +Math.cos(d)*b+Math.sin(d)*c};e=[c(.213,.787,-.213),c(.715,-.715,-.715),c(.072,-.072,.928),0,0,c(.213,-.213,.143),c(.715,.285,.14),c(.072,-.072,-.283),0,0,c(.213,-.213,-.787),c(.715,-.715,.715),c(.072,.928,.072),0,0,0,0,0,1,0,0,0,0,0,1];break;case "luminanceToAlpha":e=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,.2125,.7154,.0721,0,0,0,0,0,0,1]}this.apply=function(a,c,d,e,h){var l=a.getImageData(0,0,e,h);for(d=0;d~\.\[:]+)/g,D=/(\.[^\s\+>~\.\[:]+)/g,E=/(::[^\s\+>~\.\[:]+|:first-line|:first-letter|:before|:after)/gi,F=/(:[\w-]+\([^\)]*\))/gi,G=/(:[^\s\+>~\.\[:]+)/g,H=/([^\s\+>~\.\[:]+)/g;"undefined"!=typeof CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.drawSvg=function(h,a,l,c,b){z(this.canvas,h,{ignoreMouse:!0,ignoreAnimation:!0,ignoreDimensions:!0, +ignoreClear:!0,offsetX:a,offsetY:l,scaleWidth:c,scaleHeight:b})});return z}); diff --git a/librerias/gantt/code/lib/canvg.src.js b/librerias/gantt/code/lib/canvg.src.js new file mode 100644 index 0000000..985af18 --- /dev/null +++ b/librerias/gantt/code/lib/canvg.src.js @@ -0,0 +1,3073 @@ +/** @preserve + * canvg.js - Javascript SVG parser and renderer on Canvas + * MIT Licensed + * Gabe Lerner (gabelerner@gmail.com) + * http://code.google.com/p/canvg/ + * + * Requires: rgbcolor.js - http://www.phpied.com/rgb-color-parser-in-javascript/ + */ + (function ( global, factory ) { + + 'use strict'; + + // export as AMD... + if ( typeof define !== 'undefined' && define.amd ) { + define('canvgModule', [ 'rgbcolor', 'stackblur' ], factory ); + } + + // ...or as browserify + else if ( typeof module !== 'undefined' && module.exports ) { + module.exports = factory( require( 'rgbcolor' ), require( 'stackblur' ) ); + } + + global.canvg = factory( global.RGBColor, global.stackBlur ); + +}( typeof window !== 'undefined' ? window : this, function ( RGBColor, stackBlur ) { + + // canvg(target, s) + // empty parameters: replace all 'svg' elements on page with 'canvas' elements + // target: canvas element or the id of a canvas element + // s: svg string, url to svg file, or xml document + // opts: optional hash of options + // ignoreMouse: true => ignore mouse events + // ignoreAnimation: true => ignore animations + // ignoreDimensions: true => does not try to resize canvas + // ignoreClear: true => does not clear canvas + // offsetX: int => draws at a x offset + // offsetY: int => draws at a y offset + // scaleWidth: int => scales horizontally to width + // scaleHeight: int => scales vertically to height + // renderCallback: function => will call the function after the first render is completed + // forceRedraw: function => will call the function on every frame, if it returns true, will redraw + var canvg = function (target, s, opts) { + // no parameters + if (target == null && s == null && opts == null) { + var svgTags = document.querySelectorAll('svg'); + for (var i=0; i~\.\[:]+)/g; + var classRegex = /(\.[^\s\+>~\.\[:]+)/g; + var pseudoElementRegex = /(::[^\s\+>~\.\[:]+|:first-line|:first-letter|:before|:after)/gi; + var pseudoClassWithBracketsRegex = /(:[\w-]+\([^\)]*\))/gi; + var pseudoClassRegex = /(:[^\s\+>~\.\[:]+)/g; + var elementRegex = /([^\s\+>~\.\[:]+)/g; + function getSelectorSpecificity(selector) { + var typeCount = [0, 0, 0]; + var findMatch = function(regex, type) { + var matches = selector.match(regex); + if (matches == null) { + return; + } + typeCount[type] += matches.length; + selector = selector.replace(regex, ' '); + }; + + selector = selector.replace(/:not\(([^\)]*)\)/g, ' $1 '); + selector = selector.replace(/{[^]*/gm, ' '); + findMatch(attributeRegex, 1); + findMatch(idRegex, 0); + findMatch(classRegex, 1); + findMatch(pseudoElementRegex, 2); + findMatch(pseudoClassWithBracketsRegex, 1); + findMatch(pseudoClassRegex, 1); + selector = selector.replace(/[\*\s\+>~]/g, ' '); + selector = selector.replace(/[#\.]/g, ' '); + findMatch(elementRegex, 2); + return typeCount.join(''); + } + + function build(opts) { + var svg = { opts: opts }; + + svg.FRAMERATE = 30; + svg.MAX_VIRTUAL_PIXELS = 30000; + + svg.log = function(msg) {}; + if (svg.opts['log'] == true && typeof(console) != 'undefined') { + svg.log = function(msg) { console.log(msg); }; + }; + + // globals + svg.init = function(ctx) { + var uniqueId = 0; + svg.UniqueId = function () { uniqueId++; return 'canvg' + uniqueId; }; + svg.Definitions = {}; + svg.Styles = {}; + svg.StylesSpecificity = {}; + svg.Animations = []; + svg.Images = []; + svg.ctx = ctx; + svg.ViewPort = new (function () { + this.viewPorts = []; + this.Clear = function() { this.viewPorts = []; } + this.SetCurrent = function(width, height) { this.viewPorts.push({ width: width, height: height }); } + this.RemoveCurrent = function() { this.viewPorts.pop(); } + this.Current = function() { return this.viewPorts[this.viewPorts.length - 1]; } + this.width = function() { return this.Current().width; } + this.height = function() { return this.Current().height; } + this.ComputeSize = function(d) { + if (d != null && typeof(d) == 'number') return d; + if (d == 'x') return this.width(); + if (d == 'y') return this.height(); + return Math.sqrt(Math.pow(this.width(), 2) + Math.pow(this.height(), 2)) / Math.sqrt(2); + } + }); + } + svg.init(); + + // images loaded + svg.ImagesLoaded = function() { + for (var i=0; i]*>/, ''); + var xmlDoc = new ActiveXObject('Microsoft.XMLDOM'); + xmlDoc.async = 'false'; + xmlDoc.loadXML(xml); + return xmlDoc; + } + } + + svg.Property = function(name, value) { + this.name = name; + this.value = value; + } + svg.Property.prototype.getValue = function() { + return this.value; + } + + svg.Property.prototype.hasValue = function() { + return (this.value != null && this.value !== ''); + } + + // return the numerical value of the property + svg.Property.prototype.numValue = function() { + if (!this.hasValue()) return 0; + + var n = parseFloat(this.value); + if ((this.value + '').match(/%$/)) { + n = n / 100.0; + } + return n; + } + + svg.Property.prototype.valueOrDefault = function(def) { + if (this.hasValue()) return this.value; + return def; + } + + svg.Property.prototype.numValueOrDefault = function(def) { + if (this.hasValue()) return this.numValue(); + return def; + } + + // color extensions + // augment the current color value with the opacity + svg.Property.prototype.addOpacity = function(opacityProp) { + var newValue = this.value; + if (opacityProp.value != null && opacityProp.value != '' && typeof(this.value)=='string') { // can only add opacity to colors, not patterns + var color = new RGBColor(this.value); + if (color.ok) { + newValue = 'rgba(' + color.r + ', ' + color.g + ', ' + color.b + ', ' + opacityProp.numValue() + ')'; + } + } + return new svg.Property(this.name, newValue); + } + + // definition extensions + // get the definition from the definitions table + svg.Property.prototype.getDefinition = function() { + var name = this.value.match(/#([^\)'"]+)/); + if (name) { name = name[1]; } + if (!name) { name = this.value; } + return svg.Definitions[name]; + } + + svg.Property.prototype.isUrlDefinition = function() { + return this.value.indexOf('url(') == 0 + } + + svg.Property.prototype.getFillStyleDefinition = function(e, opacityProp) { + var def = this.getDefinition(); + + // gradient + if (def != null && def.createGradient) { + return def.createGradient(svg.ctx, e, opacityProp); + } + + // pattern + if (def != null && def.createPattern) { + if (def.getHrefAttribute().hasValue()) { + var pt = def.attribute('patternTransform'); + def = def.getHrefAttribute().getDefinition(); + if (pt.hasValue()) { def.attribute('patternTransform', true).value = pt.value; } + } + return def.createPattern(svg.ctx, e); + } + + return null; + } + + // length extensions + svg.Property.prototype.getDPI = function(viewPort) { + return 96.0; // TODO: compute? + } + + svg.Property.prototype.getEM = function(viewPort) { + var em = 12; + + var fontSize = new svg.Property('fontSize', svg.Font.Parse(svg.ctx.font).fontSize); + if (fontSize.hasValue()) em = fontSize.toPixels(viewPort); + + return em; + } + + svg.Property.prototype.getUnits = function() { + var s = this.value+''; + return s.replace(/[0-9\.\-]/g,''); + } + + // get the length as pixels + svg.Property.prototype.toPixels = function(viewPort, processPercent) { + if (!this.hasValue()) return 0; + var s = this.value+''; + if (s.match(/em$/)) return this.numValue() * this.getEM(viewPort); + if (s.match(/ex$/)) return this.numValue() * this.getEM(viewPort) / 2.0; + if (s.match(/px$/)) return this.numValue(); + if (s.match(/pt$/)) return this.numValue() * this.getDPI(viewPort) * (1.0 / 72.0); + if (s.match(/pc$/)) return this.numValue() * 15; + if (s.match(/cm$/)) return this.numValue() * this.getDPI(viewPort) / 2.54; + if (s.match(/mm$/)) return this.numValue() * this.getDPI(viewPort) / 25.4; + if (s.match(/in$/)) return this.numValue() * this.getDPI(viewPort); + if (s.match(/%$/)) return this.numValue() * svg.ViewPort.ComputeSize(viewPort); + var n = this.numValue(); + if (processPercent && n < 1.0) return n * svg.ViewPort.ComputeSize(viewPort); + return n; + } + + // time extensions + // get the time as milliseconds + svg.Property.prototype.toMilliseconds = function() { + if (!this.hasValue()) return 0; + var s = this.value+''; + if (s.match(/s$/)) return this.numValue() * 1000; + if (s.match(/ms$/)) return this.numValue(); + return this.numValue(); + } + + // angle extensions + // get the angle as radians + svg.Property.prototype.toRadians = function() { + if (!this.hasValue()) return 0; + var s = this.value+''; + if (s.match(/deg$/)) return this.numValue() * (Math.PI / 180.0); + if (s.match(/grad$/)) return this.numValue() * (Math.PI / 200.0); + if (s.match(/rad$/)) return this.numValue(); + return this.numValue() * (Math.PI / 180.0); + } + + // text extensions + // get the text baseline + var textBaselineMapping = { + 'baseline': 'alphabetic', + 'before-edge': 'top', + 'text-before-edge': 'top', + 'middle': 'middle', + 'central': 'middle', + 'after-edge': 'bottom', + 'text-after-edge': 'bottom', + 'ideographic': 'ideographic', + 'alphabetic': 'alphabetic', + 'hanging': 'hanging', + 'mathematical': 'alphabetic' + }; + svg.Property.prototype.toTextBaseline = function () { + if (!this.hasValue()) return null; + return textBaselineMapping[this.value]; + } + + // fonts + svg.Font = new (function() { + this.Styles = 'normal|italic|oblique|inherit'; + this.Variants = 'normal|small-caps|inherit'; + this.Weights = 'normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900|inherit'; + + this.CreateFont = function(fontStyle, fontVariant, fontWeight, fontSize, fontFamily, inherit) { + var f = inherit != null ? this.Parse(inherit) : this.CreateFont('', '', '', '', '', svg.ctx.font); + return { + fontFamily: fontFamily || f.fontFamily, + fontSize: fontSize || f.fontSize, + fontStyle: fontStyle || f.fontStyle, + fontWeight: fontWeight || f.fontWeight, + fontVariant: fontVariant || f.fontVariant, + toString: function () { return [this.fontStyle, this.fontVariant, this.fontWeight, this.fontSize, this.fontFamily].join(' ') } + } + } + + var that = this; + this.Parse = function(s) { + var f = {}; + var d = svg.trim(svg.compressSpaces(s || '')).split(' '); + var set = { fontSize: false, fontStyle: false, fontWeight: false, fontVariant: false } + var ff = ''; + for (var i=0; i this.x2) this.x2 = x; + } + + if (y != null) { + if (isNaN(this.y1) || isNaN(this.y2)) { + this.y1 = y; + this.y2 = y; + } + if (y < this.y1) this.y1 = y; + if (y > this.y2) this.y2 = y; + } + } + this.addX = function(x) { this.addPoint(x, null); } + this.addY = function(y) { this.addPoint(null, y); } + + this.addBoundingBox = function(bb) { + this.addPoint(bb.x1, bb.y1); + this.addPoint(bb.x2, bb.y2); + } + + this.addQuadraticCurve = function(p0x, p0y, p1x, p1y, p2x, p2y) { + var cp1x = p0x + 2/3 * (p1x - p0x); // CP1 = QP0 + 2/3 *(QP1-QP0) + var cp1y = p0y + 2/3 * (p1y - p0y); // CP1 = QP0 + 2/3 *(QP1-QP0) + var cp2x = cp1x + 1/3 * (p2x - p0x); // CP2 = CP1 + 1/3 *(QP2-QP0) + var cp2y = cp1y + 1/3 * (p2y - p0y); // CP2 = CP1 + 1/3 *(QP2-QP0) + this.addBezierCurve(p0x, p0y, cp1x, cp2x, cp1y, cp2y, p2x, p2y); + } + + this.addBezierCurve = function(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y) { + // from http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html + var p0 = [p0x, p0y], p1 = [p1x, p1y], p2 = [p2x, p2y], p3 = [p3x, p3y]; + this.addPoint(p0[0], p0[1]); + this.addPoint(p3[0], p3[1]); + + for (i=0; i<=1; i++) { + var f = function(t) { + return Math.pow(1-t, 3) * p0[i] + + 3 * Math.pow(1-t, 2) * t * p1[i] + + 3 * (1-t) * Math.pow(t, 2) * p2[i] + + Math.pow(t, 3) * p3[i]; + } + + var b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i]; + var a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i]; + var c = 3 * p1[i] - 3 * p0[i]; + + if (a == 0) { + if (b == 0) continue; + var t = -c / b; + if (0 < t && t < 1) { + if (i == 0) this.addX(f(t)); + if (i == 1) this.addY(f(t)); + } + continue; + } + + var b2ac = Math.pow(b, 2) - 4 * c * a; + if (b2ac < 0) continue; + var t1 = (-b + Math.sqrt(b2ac)) / (2 * a); + if (0 < t1 && t1 < 1) { + if (i == 0) this.addX(f(t1)); + if (i == 1) this.addY(f(t1)); + } + var t2 = (-b - Math.sqrt(b2ac)) / (2 * a); + if (0 < t2 && t2 < 1) { + if (i == 0) this.addX(f(t2)); + if (i == 1) this.addY(f(t2)); + } + } + } + + this.isPointInBox = function(x, y) { + return (this.x1 <= x && x <= this.x2 && this.y1 <= y && y <= this.y2); + } + + this.addPoint(x1, y1); + this.addPoint(x2, y2); + } + + // transforms + svg.Transform = function(v) { + var that = this; + this.Type = {} + + // translate + this.Type.translate = function(s) { + this.p = svg.CreatePoint(s); + this.apply = function(ctx) { + ctx.translate(this.p.x || 0.0, this.p.y || 0.0); + } + this.unapply = function(ctx) { + ctx.translate(-1.0 * this.p.x || 0.0, -1.0 * this.p.y || 0.0); + } + this.applyToPoint = function(p) { + p.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]); + } + } + + // rotate + this.Type.rotate = function(s) { + var a = svg.ToNumberArray(s); + this.angle = new svg.Property('angle', a[0]); + this.cx = a[1] || 0; + this.cy = a[2] || 0; + this.apply = function(ctx) { + ctx.translate(this.cx, this.cy); + ctx.rotate(this.angle.toRadians()); + ctx.translate(-this.cx, -this.cy); + } + this.unapply = function(ctx) { + ctx.translate(this.cx, this.cy); + ctx.rotate(-1.0 * this.angle.toRadians()); + ctx.translate(-this.cx, -this.cy); + } + this.applyToPoint = function(p) { + var a = this.angle.toRadians(); + p.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]); + p.applyTransform([Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), 0, 0]); + p.applyTransform([1, 0, 0, 1, -this.p.x || 0.0, -this.p.y || 0.0]); + } + } + + this.Type.scale = function(s) { + this.p = svg.CreatePoint(s); + this.apply = function(ctx) { + ctx.scale(this.p.x || 1.0, this.p.y || this.p.x || 1.0); + } + this.unapply = function(ctx) { + ctx.scale(1.0 / this.p.x || 1.0, 1.0 / this.p.y || this.p.x || 1.0); + } + this.applyToPoint = function(p) { + p.applyTransform([this.p.x || 0.0, 0, 0, this.p.y || 0.0, 0, 0]); + } + } + + this.Type.matrix = function(s) { + this.m = svg.ToNumberArray(s); + this.apply = function(ctx) { + ctx.transform(this.m[0], this.m[1], this.m[2], this.m[3], this.m[4], this.m[5]); + } + this.unapply = function(ctx) { + var a = this.m[0]; + var b = this.m[2]; + var c = this.m[4]; + var d = this.m[1]; + var e = this.m[3]; + var f = this.m[5]; + var g = 0.0; + var h = 0.0; + var i = 1.0; + var det = 1 / (a*(e*i-f*h)-b*(d*i-f*g)+c*(d*h-e*g)); + ctx.transform( + det*(e*i-f*h), + det*(f*g-d*i), + det*(c*h-b*i), + det*(a*i-c*g), + det*(b*f-c*e), + det*(c*d-a*f) + ); + } + this.applyToPoint = function(p) { + p.applyTransform(this.m); + } + } + + this.Type.SkewBase = function(s) { + this.base = that.Type.matrix; + this.base(s); + this.angle = new svg.Property('angle', s); + } + this.Type.SkewBase.prototype = new this.Type.matrix; + + this.Type.skewX = function(s) { + this.base = that.Type.SkewBase; + this.base(s); + this.m = [1, 0, Math.tan(this.angle.toRadians()), 1, 0, 0]; + } + this.Type.skewX.prototype = new this.Type.SkewBase; + + this.Type.skewY = function(s) { + this.base = that.Type.SkewBase; + this.base(s); + this.m = [1, Math.tan(this.angle.toRadians()), 0, 1, 0, 0]; + } + this.Type.skewY.prototype = new this.Type.SkewBase; + + this.transforms = []; + + this.apply = function(ctx) { + for (var i=0; i=0; i--) { + this.transforms[i].unapply(ctx); + } + } + + this.applyToPoint = function(p) { + for (var i=0; i existingSpecificity) { + this.styles[name] = styles[name]; + this.stylesSpecificity[name] = specificity; + } + } + } + } + } + }; + + if (node != null && node.nodeType == 1) { //ELEMENT_NODE + // add attributes + for (var i=0; i= this.tokens.length - 1; + } + + this.isCommandOrEnd = function() { + if (this.isEnd()) return true; + return this.tokens[this.i + 1].match(/^[A-Za-z]$/) != null; + } + + this.isRelativeCommand = function() { + switch(this.command) + { + case 'm': + case 'l': + case 'h': + case 'v': + case 'c': + case 's': + case 'q': + case 't': + case 'a': + case 'z': + return true; + break; + } + return false; + } + + this.getToken = function() { + this.i++; + return this.tokens[this.i]; + } + + this.getScalar = function() { + return parseFloat(this.getToken()); + } + + this.nextCommand = function() { + this.previousCommand = this.command; + this.command = this.getToken(); + } + + this.getPoint = function() { + var p = new svg.Point(this.getScalar(), this.getScalar()); + return this.makeAbsolute(p); + } + + this.getAsControlPoint = function() { + var p = this.getPoint(); + this.control = p; + return p; + } + + this.getAsCurrentPoint = function() { + var p = this.getPoint(); + this.current = p; + return p; + } + + this.getReflectedControlPoint = function() { + if (this.previousCommand.toLowerCase() != 'c' && + this.previousCommand.toLowerCase() != 's' && + this.previousCommand.toLowerCase() != 'q' && + this.previousCommand.toLowerCase() != 't' ){ + return this.current; + } + + // reflect point + var p = new svg.Point(2 * this.current.x - this.control.x, 2 * this.current.y - this.control.y); + return p; + } + + this.makeAbsolute = function(p) { + if (this.isRelativeCommand()) { + p.x += this.current.x; + p.y += this.current.y; + } + return p; + } + + this.addMarker = function(p, from, priorTo) { + // if the last angle isn't filled in because we didn't have this point yet ... + if (priorTo != null && this.angles.length > 0 && this.angles[this.angles.length-1] == null) { + this.angles[this.angles.length-1] = this.points[this.points.length-1].angleTo(priorTo); + } + this.addMarkerAngle(p, from == null ? null : from.angleTo(p)); + } + + this.addMarkerAngle = function(p, a) { + this.points.push(p); + this.angles.push(a); + } + + this.getMarkerPoints = function() { return this.points; } + this.getMarkerAngles = function() { + for (var i=0; i 1) { + rx *= Math.sqrt(l); + ry *= Math.sqrt(l); + } + // cx', cy' + var s = (largeArcFlag == sweepFlag ? -1 : 1) * Math.sqrt( + ((Math.pow(rx,2)*Math.pow(ry,2))-(Math.pow(rx,2)*Math.pow(currp.y,2))-(Math.pow(ry,2)*Math.pow(currp.x,2))) / + (Math.pow(rx,2)*Math.pow(currp.y,2)+Math.pow(ry,2)*Math.pow(currp.x,2)) + ); + if (isNaN(s)) s = 0; + var cpp = new svg.Point(s * rx * currp.y / ry, s * -ry * currp.x / rx); + // cx, cy + var centp = new svg.Point( + (curr.x + cp.x) / 2.0 + Math.cos(xAxisRotation) * cpp.x - Math.sin(xAxisRotation) * cpp.y, + (curr.y + cp.y) / 2.0 + Math.sin(xAxisRotation) * cpp.x + Math.cos(xAxisRotation) * cpp.y + ); + // vector magnitude + var m = function(v) { return Math.sqrt(Math.pow(v[0],2) + Math.pow(v[1],2)); } + // ratio between two vectors + var r = function(u, v) { return (u[0]*v[0]+u[1]*v[1]) / (m(u)*m(v)) } + // angle between two vectors + var a = function(u, v) { return (u[0]*v[1] < u[1]*v[0] ? -1 : 1) * Math.acos(r(u,v)); } + // initial angle + var a1 = a([1,0], [(currp.x-cpp.x)/rx,(currp.y-cpp.y)/ry]); + // angle delta + var u = [(currp.x-cpp.x)/rx,(currp.y-cpp.y)/ry]; + var v = [(-currp.x-cpp.x)/rx,(-currp.y-cpp.y)/ry]; + var ad = a(u, v); + if (r(u,v) <= -1) ad = Math.PI; + if (r(u,v) >= 1) ad = 0; + + // for markers + var dir = 1 - sweepFlag ? 1.0 : -1.0; + var ah = a1 + dir * (ad / 2.0); + var halfWay = new svg.Point( + centp.x + rx * Math.cos(ah), + centp.y + ry * Math.sin(ah) + ); + pp.addMarkerAngle(halfWay, ah - dir * Math.PI / 2); + pp.addMarkerAngle(cp, ah - dir * Math.PI); + + bb.addPoint(cp.x, cp.y); // TODO: this is too naive, make it better + if (ctx != null) { + var r = rx > ry ? rx : ry; + var sx = rx > ry ? 1 : rx / ry; + var sy = rx > ry ? ry / rx : 1; + + ctx.translate(centp.x, centp.y); + ctx.rotate(xAxisRotation); + ctx.scale(sx, sy); + ctx.arc(0, 0, r, a1, a1 + ad, 1 - sweepFlag); + ctx.scale(1/sx, 1/sy); + ctx.rotate(-xAxisRotation); + ctx.translate(-centp.x, -centp.y); + } + } + break; + case 'Z': + case 'z': + if (ctx != null) ctx.closePath(); + pp.current = pp.start; + } + } + + return bb; + } + + this.getMarkers = function() { + var points = this.PathParser.getMarkerPoints(); + var angles = this.PathParser.getMarkerAngles(); + + var markers = []; + for (var i=0; i 1) this.offset = 1; + + var stopColor = this.style('stop-color', true); + if (stopColor.value === '') stopColor.value = '#000'; + if (this.style('stop-opacity').hasValue()) stopColor = stopColor.addOpacity(this.style('stop-opacity')); + this.color = stopColor.value; + } + svg.Element.stop.prototype = new svg.Element.ElementBase; + + // animation base element + svg.Element.AnimateBase = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + + svg.Animations.push(this); + + this.duration = 0.0; + this.begin = this.attribute('begin').toMilliseconds(); + this.maxDuration = this.begin + this.attribute('dur').toMilliseconds(); + + this.getProperty = function() { + var attributeType = this.attribute('attributeType').value; + var attributeName = this.attribute('attributeName').value; + + if (attributeType == 'CSS') { + return this.parent.style(attributeName, true); + } + return this.parent.attribute(attributeName, true); + }; + + this.initialValue = null; + this.initialUnits = ''; + this.removed = false; + + this.calcValue = function() { + // OVERRIDE ME! + return ''; + } + + this.update = function(delta) { + // set initial value + if (this.initialValue == null) { + this.initialValue = this.getProperty().value; + this.initialUnits = this.getProperty().getUnits(); + } + + // if we're past the end time + if (this.duration > this.maxDuration) { + // loop for indefinitely repeating animations + if (this.attribute('repeatCount').value == 'indefinite' + || this.attribute('repeatDur').value == 'indefinite') { + this.duration = 0.0 + } + else if (this.attribute('fill').valueOrDefault('remove') == 'freeze' && !this.frozen) { + this.frozen = true; + this.parent.animationFrozen = true; + this.parent.animationFrozenValue = this.getProperty().value; + } + else if (this.attribute('fill').valueOrDefault('remove') == 'remove' && !this.removed) { + this.removed = true; + this.getProperty().value = this.parent.animationFrozen ? this.parent.animationFrozenValue : this.initialValue; + return true; + } + return false; + } + this.duration = this.duration + delta; + + // if we're past the begin time + var updated = false; + if (this.begin < this.duration) { + var newValue = this.calcValue(); // tween + + if (this.attribute('type').hasValue()) { + // for transform, etc. + var type = this.attribute('type').value; + newValue = type + '(' + newValue + ')'; + } + + this.getProperty().value = newValue; + updated = true; + } + + return updated; + } + + this.from = this.attribute('from'); + this.to = this.attribute('to'); + this.values = this.attribute('values'); + if (this.values.hasValue()) this.values.value = this.values.value.split(';'); + + // fraction of duration we've covered + this.progress = function() { + var ret = { progress: (this.duration - this.begin) / (this.maxDuration - this.begin) }; + if (this.values.hasValue()) { + var p = ret.progress * (this.values.value.length - 1); + var lb = Math.floor(p), ub = Math.ceil(p); + ret.from = new svg.Property('from', parseFloat(this.values.value[lb])); + ret.to = new svg.Property('to', parseFloat(this.values.value[ub])); + ret.progress = (p - lb) / (ub - lb); + } + else { + ret.from = this.from; + ret.to = this.to; + } + return ret; + } + } + svg.Element.AnimateBase.prototype = new svg.Element.ElementBase; + + // animate element + svg.Element.animate = function(node) { + this.base = svg.Element.AnimateBase; + this.base(node); + + this.calcValue = function() { + var p = this.progress(); + + // tween value linearly + var newValue = p.from.numValue() + (p.to.numValue() - p.from.numValue()) * p.progress; + return newValue + this.initialUnits; + }; + } + svg.Element.animate.prototype = new svg.Element.AnimateBase; + + // animate color element + svg.Element.animateColor = function(node) { + this.base = svg.Element.AnimateBase; + this.base(node); + + this.calcValue = function() { + var p = this.progress(); + var from = new RGBColor(p.from.value); + var to = new RGBColor(p.to.value); + + if (from.ok && to.ok) { + // tween color linearly + var r = from.r + (to.r - from.r) * p.progress; + var g = from.g + (to.g - from.g) * p.progress; + var b = from.b + (to.b - from.b) * p.progress; + return 'rgb('+parseInt(r,10)+','+parseInt(g,10)+','+parseInt(b,10)+')'; + } + return this.attribute('from').value; + }; + } + svg.Element.animateColor.prototype = new svg.Element.AnimateBase; + + // animate transform element + svg.Element.animateTransform = function(node) { + this.base = svg.Element.AnimateBase; + this.base(node); + + this.calcValue = function() { + var p = this.progress(); + + // tween value linearly + var from = svg.ToNumberArray(p.from.value); + var to = svg.ToNumberArray(p.to.value); + var newValue = ''; + for (var i=0; i startI && child.attribute('x').hasValue()) break; // new group + width += child.measureTextRecursive(ctx); + } + return -1 * (textAnchor == 'end' ? width : width / 2.0); + } + return 0; + } + + this.renderChild = function(ctx, parent, i) { + var child = parent.children[i]; + if (child.attribute('x').hasValue()) { + child.x = child.attribute('x').toPixels('x') + parent.getAnchorDelta(ctx, parent, i); + if (child.attribute('dx').hasValue()) child.x += child.attribute('dx').toPixels('x'); + } + else { + if (child.attribute('dx').hasValue()) parent.x += child.attribute('dx').toPixels('x'); + child.x = parent.x; + } + parent.x = child.x + child.measureText(ctx); + + if (child.attribute('y').hasValue()) { + child.y = child.attribute('y').toPixels('y'); + if (child.attribute('dy').hasValue()) child.y += child.attribute('dy').toPixels('y'); + } + else { + if (child.attribute('dy').hasValue()) parent.y += child.attribute('dy').toPixels('y'); + child.y = parent.y; + } + parent.y = child.y; + + child.render(ctx); + + for (var i=0; i0 && text[i-1]!=' ' && i0 && text[i-1]!=' ' && (i == text.length-1 || text[i+1]==' ')) arabicForm = 'initial'; + if (typeof(font.glyphs[c]) != 'undefined') { + glyph = font.glyphs[c][arabicForm]; + if (glyph == null && font.glyphs[c].type == 'glyph') glyph = font.glyphs[c]; + } + } + else { + glyph = font.glyphs[c]; + } + if (glyph == null) glyph = font.missingGlyph; + return glyph; + } + + this.renderChildren = function(ctx) { + var customFont = this.parent.style('font-family').getDefinition(); + if (customFont != null) { + var fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize); + var fontStyle = this.parent.style('font-style').valueOrDefault(svg.Font.Parse(svg.ctx.font).fontStyle); + var text = this.getText(); + if (customFont.isRTL) text = text.split("").reverse().join(""); + + var dx = svg.ToNumberArray(this.parent.attribute('dx').value); + for (var i=0; i 0) { return ''; } + return this.text; + } + } + svg.Element.tspan.prototype = new svg.Element.TextElementBase; + + // tref + svg.Element.tref = function(node) { + this.base = svg.Element.TextElementBase; + this.base(node); + + this.getText = function() { + var element = this.getHrefAttribute().getDefinition(); + if (element != null) return element.children[0].getText(); + } + } + svg.Element.tref.prototype = new svg.Element.TextElementBase; + + // a element + svg.Element.a = function(node) { + this.base = svg.Element.TextElementBase; + this.base(node); + + this.hasText = node.childNodes.length > 0; + for (var i=0; i 0) { + // render as temporary group + var g = new svg.Element.g(); + g.children = this.children; + g.parent = this; + g.render(ctx); + } + } + + this.onclick = function() { + window.open(this.getHrefAttribute().value); + } + + this.onmousemove = function() { + svg.ctx.canvas.style.cursor = 'pointer'; + } + } + svg.Element.a.prototype = new svg.Element.TextElementBase; + + // image element + svg.Element.image = function(node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + + var href = this.getHrefAttribute().value; + if (href == '') { return; } + var isSvg = href.match(/\.svg$/) + + svg.Images.push(this); + this.loaded = false; + if (!isSvg) { + this.img = document.createElement('img'); + if (svg.opts['useCORS'] == true) { this.img.crossOrigin = 'Anonymous'; } + var self = this; + this.img.onload = function() { self.loaded = true; } + this.img.onerror = function() { svg.log('ERROR: image "' + href + '" not found'); self.loaded = true; } + this.img.src = href; + } + else { + this.img = svg.ajax(href); + this.loaded = true; + } + + this.renderChildren = function(ctx) { + var x = this.attribute('x').toPixels('x'); + var y = this.attribute('y').toPixels('y'); + + var width = this.attribute('width').toPixels('x'); + var height = this.attribute('height').toPixels('y'); + if (width == 0 || height == 0) return; + + ctx.save(); + if (isSvg) { + ctx.drawSvg(this.img, x, y, width, height); + } + else { + ctx.translate(x, y); + svg.AspectRatio(ctx, + this.attribute('preserveAspectRatio').value, + width, + this.img.width, + height, + this.img.height, + 0, + 0); + ctx.drawImage(this.img, 0, 0); + } + ctx.restore(); + } + + this.getBoundingBox = function() { + var x = this.attribute('x').toPixels('x'); + var y = this.attribute('y').toPixels('y'); + var width = this.attribute('width').toPixels('x'); + var height = this.attribute('height').toPixels('y'); + return new svg.BoundingBox(x, y, x + width, y + height); + } + } + svg.Element.image.prototype = new svg.Element.RenderedElementBase; + + // group element + svg.Element.g = function(node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + + this.getBoundingBox = function() { + var bb = new svg.BoundingBox(); + for (var i=0; i 0) { + var urlStart = srcs[s].indexOf('url'); + var urlEnd = srcs[s].indexOf(')', urlStart); + var url = srcs[s].substr(urlStart + 5, urlEnd - urlStart - 6); + var doc = svg.parseXml(svg.ajax(url)); + var fonts = doc.getElementsByTagName('font'); + for (var f=0; f, https://github.com/HackbrettXXX + * 2010-2016 James Hall , https://github.com/MrRio/jsPDF + * 2010 Aaron Spike, https://github.com/acspike + * 2012 Willow Systems Corporation, willow-systems.com + * 2012 Pablo Hess, https://github.com/pablohess + * 2012 Florian Jenett, https://github.com/fjenett + * 2013 Warren Weckesser, https://github.com/warrenweckesser + * 2013 Youssef Beddad, https://github.com/lifof + * 2013 Lee Driscoll, https://github.com/lsdriscoll + * 2013 Stefan Slonevskiy, https://github.com/stefslon + * 2013 Jeremy Morel, https://github.com/jmorel + * 2013 Christoph Hartmann, https://github.com/chris-rock + * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria + * 2014 James Makes, https://github.com/dollaruw + * 2014 Diego Casorran, https://github.com/diegocr + * 2014 Steven Spungin, https://github.com/Flamenco + * 2014 Kenneth Glassey, https://github.com/Gavvers + * + * Licensed under the MIT License + * + * Contributor(s): + * siefkenj, ahwolf, rickygu, Midnith, saintclair, eaparango, + * kim3er, mfo, alnorth, Flamenco + */!function(t){if("object"!=typeof t.console){t.console={};for(var e,n,r=t.console,i=function(){},o=["memory"],s="assert,clear,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn".split(",");e=o.pop();)r[e]||(r[e]={});for(;n=s.pop();)r[n]||(r[n]=i)}var a,c,u,h,l="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";void 0===t.btoa&&(t.btoa=function(t){var e,n,r,i,o,s=0,a=0,c="",u=[];if(!t)return t;for(;e=(o=t.charCodeAt(s++)<<16|t.charCodeAt(s++)<<8|t.charCodeAt(s++))>>18&63,n=o>>12&63,r=o>>6&63,i=63&o,u[a++]=l.charAt(e)+l.charAt(n)+l.charAt(r)+l.charAt(i),s>16&255,n=s>>8&255,r=255&s,u[c++]=64==i?String.fromCharCode(e):64==o?String.fromCharCode(e,n):String.fromCharCode(e,n,r),a>>0,r=new Array(n),i=1>>0,i=0;i>16&255,r=c>>8&255,i=255&c}if(void 0===r||void 0===o&&n===r&&r===i)if("string"==typeof n)e=n+" "+s[0];else switch(t.precision){case 2:e=ct(n/255)+" "+s[0];break;case 3:default:e=ut(n/255)+" "+s[0]}else if(void 0===o||"object"===re(o)){if("string"==typeof n)e=[n,r,i,s[1]].join(" ");else switch(t.precision){case 2:e=[ct(n/255),ct(r/255),ct(i/255),s[1]].join(" ");break;default:case 3:e=[ut(n/255),ut(r/255),ut(i/255),s[1]].join(" ")}o&&0===o.a&&(e=["255","255","255",s[1]].join(" "))}else if("string"==typeof n)e=[n,r,i,o,s[2]].join(" ");else switch(t.precision){case 2:e=[ct(n),ct(r),ct(i),ct(o),s[2]].join(" ");break;case 3:default:e=[ut(n),ut(r),ut(i),ut(o),s[2]].join(" ")}return e},X=function(t){var e=function(t){return("0"+parseInt(t)).slice(-2)},n=t.getTimezoneOffset(),r=n<0?"+":"-",i=Math.floor(Math.abs(n/60)),o=Math.abs(n%60),s=[r,e(i),"'",e(o),"'"].join("");return["D:",t.getFullYear(),e(t.getMonth()+1),e(t.getDate()),e(t.getHours()),e(t.getMinutes()),e(t.getSeconds()),s].join("")},J=function(t){var e;return void 0===re(t)&&(t=new Date),e="object"===re(t)&&"[object Date]"===Object.prototype.toString.call(t)?X(t):/^D:(20[0-2][0-9]|203[0-7]|19[7-9][0-9])(0[0-9]|1[0-2])([0-2][0-9]|3[0-1])(0[0-9]|1[0-9]|2[0-3])(0[0-9]|[1-5][0-9])(0[0-9]|[1-5][0-9])(\+0[0-9]|\+1[0-4]|\-0[0-9]|\-1[0-1])\'(0[0-9]|[1-5][0-9])\'?$/.test(t)?t:X(new Date),p=e},st=function(t){var e=p;return"jsDate"===t&&(e=function(t){var e=parseInt(t.substr(2,4),10),n=parseInt(t.substr(6,2),10)-1,r=parseInt(t.substr(8,2),10),i=parseInt(t.substr(10,2),10),o=parseInt(t.substr(12,2),10),s=parseInt(t.substr(14,2),10);parseInt(t.substr(16,2),10),parseInt(t.substr(20,2),10);return new Date(e,n,r,i,o,s,0)}(p)),e},at=function(t){return t=t||"12345678901234567890123456789012".split("").map(function(){return"ABCDEF0123456789".charAt(Math.floor(16*Math.random()))}).join(""),b=t},ct=function(t){return t.toFixed(2)},ut=function(t){return t.toFixed(3)},ht=function(t){return t.toFixed(16).replace(/0+$/,"")},lt=function(t){return it===G?t*m:it===rt?t:void 0},ft=function(t){return lt((e=t,it===G?w-e:it===rt?e:void 0));var e},pt=function(t){var e="00"+t;return e.substr(e.length-2)},dt=function(t){if(it!==rt)throw new Error(t+" is only available in 'advanced' API mode. You need to call advancedAPI() first.")},gt=function(t){t="string"==typeof t?t:t.toString(),S?T[s].push(t):(z+=t.length+1,D.push(t))},mt=function(){return _[++x]=z,gt(x+" 0 obj"),x},yt=function(t){gt("stream"),gt(t),gt("endstream")},wt=function(t){t.objectNumber=mt(),gt("<<"),gt("/Type /XObject"),gt("/Subtype /Form"),gt("/BBox ["+[ht(t.x),ht(t.y),ht(t.x+t.width),ht(t.y+t.height)].join(" ")+"]"),gt("/Matrix ["+t.matrix.toString()+"]");var e=t.pages[1].join("\n");gt("/Length "+e.length),gt(">>"),yt(e),gt("endobj")},vt=function(t,e){e||(e=21);var n=mt(),r=function(t,e){var n,r=[],i=1/(e-1);for(n=0;n<1;n+=i)r.push(n);if(r.push(1),0!=t[0].offset){var o={offset:0,color:t[0].color};t.unshift(o)}if(1!=t[t.length-1].offset){var s={offset:1,color:t[t.length-1].color};t.push(s)}for(var a="",c=0,u=0;ut[c+1].offset;)c++;var h=t[c].offset,l=(n-h)/(t[c+1].offset-h),f=t[c].color,p=t[c+1].color;a+=pt(Math.round((1-l)*f[0]+l*p[0]).toString(16))+pt(Math.round((1-l)*f[1]+l*p[1]).toString(16))+pt(Math.round((1-l)*f[2]+l*p[2]).toString(16))}return a.trim()}(t.colors,e);gt("<< /FunctionType 0"),gt("/Domain [0.0 1.0]"),gt("/Size ["+e+"]"),gt("/BitsPerSample 8"),gt("/Range [0.0 1.0 0.0 1.0 0.0 1.0]"),gt("/Decode [0.0 1.0 0.0 1.0 0.0 1.0]"),gt("/Length "+r.length),gt("/Filter /ASCIIHexDecode"),gt(">>"),yt(r),gt("endobj"),t.objectNumber=mt(),gt("<< /ShadingType "+t.type),gt("/ColorSpace /DeviceRGB");var i="/Coords ["+ht(parseFloat(t.coords[0]))+" "+ht(parseFloat(t.coords[1]))+" ";2===t.type?i+=ht(parseFloat(t.coords[2]))+" "+ht(parseFloat(t.coords[3])):i+=ht(parseFloat(t.coords[2]))+" "+ht(parseFloat(t.coords[3]))+" "+ht(parseFloat(t.coords[4]))+" "+ht(parseFloat(t.coords[5])),gt(i+="]"),t.matrix&>("/Matrix ["+t.matrix.toString()+"]"),gt("/Function "+n+" 0 R"),gt("/Extend [true true]"),gt(">>"),gt("endobj")},bt=function(t){for(var e in t.objectNumber=mt(),gt("<<"),t)switch(e){case"opacity":gt("/ca "+ct(t[e]));break;case"stroke-opacity":gt("/CA "+ct(t[e]))}gt(">>"),gt("endobj")},xt=function(){for(var t in gt("/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]"),gt("/Font <<"),nt)nt.hasOwnProperty(t)&>("/"+t+" "+nt[t].objectNumber+" 0 R");gt(">>"),gt("/Shading <<"),function(){for(var t in C)C.hasOwnProperty(t)&&C[t]instanceof W.ShadingPattern&&0<=C[t].objectNumber&>("/"+t+" "+C[t].objectNumber+" 0 R");ot.publish("putShadingPatternDict")}(),gt(">>"),gt("/Pattern <<"),function(){for(var t in C)C.hasOwnProperty(t)&&C[t]instanceof W.TilingPattern&&0<=C[t].objectNumber&>("/"+t+" "+C[t].objectNumber+" 0 R");ot.publish("putTilingPatternDict")}(),gt(">>"),gt("/ExtGState <<"),function(){var t;for(t in P)P.hasOwnProperty(t)&&0<=P[t].objectNumber&>("/"+t+" "+P[t].objectNumber+" 0 R");ot.publish("putGStateDict")}(),gt(">>"),gt("/XObject <<"),function(){for(var t in M)M.hasOwnProperty(t)&&0<=M[t].objectNumber&>("/"+t+" "+M[t].objectNumber+" 0 R");ot.publish("putXobjectDict")}(),gt(">>")},St=function(){!function(){for(var t in nt)nt.hasOwnProperty(t)&&(e=nt[t],ot.publish("putFont",{font:e,out:gt,newObject:mt,putStream:yt}),!0!==e.isAlreadyPutted&&(e.objectNumber=mt(),gt("<<"),gt("/Type /Font"),gt("/BaseFont /"+e.postScriptName),gt("/Subtype /Type1"),"string"==typeof e.encoding&>("/Encoding /"+e.encoding),gt("/FirstChar 32"),gt("/LastChar 255"),gt(">>"),gt("endobj")));var e}(),function(){var t;for(t in P)P.hasOwnProperty(t)&&bt(P[t])}(),function(){for(var t in M)M.hasOwnProperty(t)&&wt(M[t])}(),function(){var t,e,n;for(t in C)C.hasOwnProperty(t)&&(C[t]instanceof W.ShadingPattern?vt(C[t]):C[t]instanceof W.TilingPattern&&(e=C[t],n=mt(),gt("<<"),xt(),gt(">>"),gt("endobj"),e.objectNumber=mt(),gt("<< /Type /Pattern"),gt("/PatternType 1"),gt("/PaintType 1"),gt("/TilingType 1"),gt("/BBox ["+e.boundingBox.map(ht).join(" ")+"]"),gt("/XStep "+ht(e.xStep)),gt("/YStep "+ht(e.yStep)),gt("/Length "+e.stream.length),gt("/Resources "+n+" 0 R"),e.matrix&>("/Matrix ["+e.matrix.toString()+"]"),gt(">>"),yt(e.stream),gt("endobj")))}(),ot.publish("putResources"),_[2]=z,gt("2 0 obj"),gt("<<"),xt(),gt(">>"),gt("endobj"),ot.publish("postPutResources")},_t=function(t,e,n){k.hasOwnProperty(e)||(k[e]={}),k[e][n]=t},kt=function(t,e,n,r,i){i=i||!1;var o="F"+(Object.keys(nt).length+1).toString(10),s={id:o,postScriptName:t,fontName:e,fontStyle:n,encoding:r,isStandardFont:i,metadata:{}};return ot.publish("addFont",{font:s,instance:this}),void 0!==o&&(nt[o]=s,_t(o,e,n)),o},At=function(t,e){return new Ct(t.a*e.a+t.b*e.c,t.a*e.b+t.b*e.d,t.c*e.a+t.d*e.c,t.c*e.b+t.d*e.d,t.e*e.a+t.f*e.c+e.e,t.e*e.b+t.f*e.d+e.f)},Ct=function(t,e,n,r,i,o){this.a=t,this.b=e,this.c=n,this.d=r,this.e=i,this.f=o};Ct.prototype={toString:function(){return[ht(this.a),ht(this.b),ht(this.c),ht(this.d),ht(this.e),ht(this.f)].join(" ")},inversed:function(){var t=this.a,e=this.b,n=this.c,r=this.d,i=this.e,o=this.f,s=1/(t*r-e*n),a=r*s,c=-e*s,u=-n*s,h=t*s;return new Ct(a,c,u,h,-a*i-u*o,-c*i-h*o)}};var It=new Ct(1,0,0,1,0,0),Pt=function(){this.page=j,this.currentPage=s,this.pages=T.slice(0),this.pagedim=B.slice(0),this.pagesContext=O.slice(0),this.x=a,this.y=c,this.matrix=u,this.width=y,this.height=w,this.id="",this.objectNumber=-1};Pt.prototype={restore:function(){j=this.page,s=this.currentPage,O=this.pagesContext,B=this.pagedim,T=this.pages,a=this.x,c=this.y,u=this.matrix,y=this.width,w=this.height}};var Ft,qt=function(t,e,n,r,i){L.push(new Pt),j=s=0,T=[],a=t,c=e,u=i,Bt(n,r)},jt=function(t,e){if(!I[t]){var n=(e instanceof W.ShadingPattern?"Sh":"P")+(Object.keys(C).length+1).toString(10);e.id=n,I[t]=n,C[n]=e,ot.publish("addPattern",e)}},Tt=function(t,e){if(!t||!F[t]){var n=!1;for(var r in P)if(P.hasOwnProperty(r)&&P[r].equals(e)){n=!0;break}if(n)e=P[r];else{var i="GS"+(Object.keys(P).length+1).toString(10);(P[i]=e).id=i}return t&&(F[t]=e.id),ot.publish("addGState",e),e}},Ot=function(t,e){return function(t,e){var n,r,i,o,s,a,c,u,h;if(i=(e=e||{}).sourceEncoding||"Unicode",s=e.outputEncoding,(e.autoencode||s)&&nt[K].metadata&&nt[K].metadata[i]&&nt[K].metadata[i].encoding&&(o=nt[K].metadata[i].encoding,!s&&nt[K].encoding&&(s=nt[K].encoding),!s&&o.codePages&&(s=o.codePages[0]),"string"==typeof s&&(s=o[s]),s)){for(c=!1,a=[],n=0,r=t.length;n>8&&(c=!0);t=a.join("")}for(n=t.length;void 0===c&&0!==n;)t.charCodeAt(n-1)>>8&&(c=!0),n--;if(!c)return t;for(a=e.noBOM?[]:[254,255],n=0,r=t.length;n>8)>>8)throw new Error("Character at position "+n+" of string '"+t+"' exceeds 16bits. Cannot be encoded into UCS-2 BE");a.push(h),a.push(u-(h<<8))}return String.fromCharCode.apply(void 0,a)}(t,e).replace(/\\/g,"\\\\").replace(/\(/g,"\\(").replace(/\)/g,"\\)")},Bt=function(t,e){S=!0,T[++j]=[],B[j]={width:Number(t)||y,height:Number(e)||w},O[j]={},Et(j)},Dt=function(t,e){var n="string"==typeof e&&e.toLowerCase();if("string"==typeof t){var r=t.toLowerCase();te.hasOwnProperty(r)&&(t=te[r][0]/m,e=te[r][1]/m)}if(Array.isArray(t)&&(e=t[1],t=t[0]),n){switch(n.substr(0,1)){case"l":t>"),gt("endobj"),e=T[t].join("\n"),it===rt&&(e+="\nQ"),mt(),v){for(n=[],r=e.length;r--;)n[r]=e.charCodeAt(r);o=s.from(e),e=(i=new Deflater(6)).append(new Uint8Array(n)),u=e,h=i.flush(),l=void 0,(l=new Uint8Array(u.byteLength+h.byteLength)).set(new Uint8Array(u),0),l.set(new Uint8Array(h),u.byteLength),e=l,(n=new Uint8Array(e.byteLength+6)).set(new Uint8Array([120,156])),n.set(e,2),n.set(new Uint8Array([255&o,o>>8&255,o>>16&255,o>>24&255]),e.byteLength+2);for(var p=[],d=0;65535*d>")}else gt("<>");yt(e),gt("endobj")}_[1]=z,gt("1 0 obj"),gt("<>"),gt("endobj"),ot.publish("postPutPages")}(),function(){ot.publish("putAdditionalObjects");for(var t=0;t>"),gt("endobj"),mt(),gt("<<"),function(){switch(gt("/Type /Catalog"),gt("/Pages 1 0 R"),l||(l="fullwidth"),l){case"fullwidth":gt("/OpenAction [3 0 R /FitH null]");break;case"fullheight":gt("/OpenAction [3 0 R /FitV null]");break;case"fullpage":gt("/OpenAction [3 0 R /Fit]");break;case"original":gt("/OpenAction [3 0 R /XYZ null null 1]");break;default:var t=""+l;"%"===t.substr(t.length-1)&&(l=parseInt(l)/100),"number"==typeof l&>("/OpenAction [3 0 R /XYZ null null "+ct(l)+"]")}switch(f||(f="continuous"),f){case"continuous":gt("/PageLayout /OneColumn");break;case"single":gt("/PageLayout /SinglePage");break;case"two":case"twoleft":gt("/PageLayout /TwoColumnLeft");break;case"tworight":gt("/PageLayout /TwoColumnRight")}h&>("/PageMode /"+h),ot.publish("putCatalog")}(),gt(">>"),gt("endobj");var t,e=z,n="0000000000";for(gt("xref"),gt("0 "+(x+1)),gt(n+" 65535 f "),t=1;t<=x;t++){var r=_[t];gt("function"==typeof r?(n+_[t]()).slice(-10)+" 00000 n ":(n+_[t]).slice(-10)+" 00000 n ")}return gt("trailer"),gt("<<"),gt("/Size "+(x+1)),gt("/Root "+x+" 0 R"),gt("/Info "+(x-1)+" 0 R"),gt("/ID [ <"+b+"> <"+b+"> ]"),gt(">>"),gt("startxref"),gt(""+e),gt("%%EOF"),S=!0,D.join("\n")},zt=function(t){var e=it===G?"S":"n";return"D"===t?e="S":"F"===t?e="f":"FD"===t||"DF"===t?e="B":"f"!==t&&"f*"!==t&&"B"!==t&&"B*"!==t||(e=t),e},Mt=function(t,e,n){null===t||it===rt&&void 0===t||(t=zt(t),e?(n||(n={matrix:It}),n instanceof Ct&&(n={matrix:n}),n.key=e,n||(n=It),Nt(n,t)):gt(t))},Nt=function(t,e){var n=I[t.key],r=C[n];if(r instanceof W.ShadingPattern)gt("q"),gt(Lt(e)),r.gState&&W.setGState(r.gState),gt(t.matrix.toString()+" cm"),gt("/"+n+" sh"),gt("Q");else if(r instanceof W.TilingPattern){var i=new Ct(1,0,0,-1,0,w);t.matrix&&(i=At(t.matrix||It,i),n=r.createClone(t.key,t.boundingBox,t.xStep,t.yStep,i).id),gt("q"),gt("/Pattern cs"),gt("/"+n+" scn"),r.gState&&W.setGState(r.gState),gt(e),gt("Q")}},Lt=function(t){switch(t){case"f":case"F":return"W n";case"f*":return"W* n";case"B":return"W S";case"B*":return"W* S";case"S":return"W S";case"n":return"W n"}},Ht=function(){for(var t=Ut(),e=t.length,n=new ArrayBuffer(e),r=new Uint8Array(n);e--;)r[e]=t.charCodeAt(e);return n},Wt=function(){return new Blob([Ht()],{type:"application/pdf"})},Gt=((Ft=function(t,e){"string"==typeof e?e={filename:e}:(e=e||{}).filename=e.filename||"generated.pdf";var n="dataur"===(""+t).substr(0,6)?"data:application/pdf;filename="+e.filename+";base64,"+btoa(Ut()):0;switch(t){case void 0:return Ut();case"save":if("object"===("undefined"==typeof navigator?"undefined":re(navigator))&&navigator.getUserMedia&&(void 0===Zt.URL||void 0===Zt.URL.createObjectURL))return W.output("dataurlnewwindow");ie(Wt(),e.filename),"function"==typeof ie.unload&&Zt.setTimeout&&setTimeout(ie.unload,911);break;case"arraybuffer":return Ht();case"blob":return Wt();case"bloburi":case"bloburl":return Zt.URL&&Zt.URL.createObjectURL(Wt())||void 0;case"datauristring":case"dataurlstring":return n;case"dataurlnewwindow":var r='',i=Zt.open();if(null!==i&&i.document.write(r),i||"undefined"==typeof safari)return i;case"datauri":case"dataurl":return Zt.document.location.href=n;default:throw new Error('Output type "'+t+'" is not supported.')}}).foo=function(){try{return Ft.apply(this,arguments)}catch(t){var e=t.stack||"";~e.indexOf(" at ")&&(e=e.split(" at ")[1]);var n="Error in function "+e.split("\n")[0].split("<")[0]+": "+t.message;if(!Zt.console)throw new Error(n);Zt.console.error(n,t),Zt.alert&&alert(n)}},(Ft.foo.bar=Ft).foo),Vt=function(t){return!0===Array.isArray(V)&&-1":")"),Y=0):"[object Array]"===Object.prototype.toString.call(v[H])&&(W=v[H][1]*T,G=-v[H][2],V=(o?"<":"(")+v[H][0]+(o?">":")"),Y=1),void 0!==E&&void 0!==E[H]&&(X=E[H]+" Tw\n"),1===Y&&0=o.length-1;if(x&&!S){y+=" ";continue}if(x||S){if(S)g=b;else if(t.multiline&&a<(h+2)*(w+2)+2)continue t}else{if(!t.multiline)continue t;if(a<(h+2)*(w+2)+2)continue t;g=b}for(var _="",k=d;k<=g;k++)_+=o[k]+" ";switch(_=" "==_.substr(_.length-1)?_.substr(0,_.length-1):_,m=A(_,s+"px",i).width,t.Q){case 2:f=c-m-2;break;case 1:f=(c-m)/2;break;case 0:default:f=2}e+=f.toFixed(2)+" "+p.toFixed(2)+" Td\n",e+="("+_+") Tj\n",e+=-f.toFixed(2)+" 0 Td\n",p=-(s+2),m=0,d=g+1,w++,y=""}else;break}return r.text=e,r.fontSize=s,r},A=function(t,e,n){n=n||"helvetica";var r=h.internal.getFont(n),i=h.getStringUnitWidth(t,{font:r,fontSize:parseFloat(e),charSpace:0})*parseFloat(e);return{height:h.getStringUnitWidth("3",{font:r,fontSize:parseFloat(e),charSpace:0})*parseFloat(e)*1.5,width:i}},p={fields:[],xForms:[],acroFormDictionaryRoot:null,printedOut:!1,internal:null,isInitialized:!1},d=function(){var t=h.internal.acroformPlugin.acroFormDictionaryRoot.Fields;for(var e in t)if(t.hasOwnProperty(e)){var n=t[e];n.hasAnnotation&&m.call(h,n)}},g=function(t){h.internal.acroformPlugin.printedOut&&(h.internal.acroformPlugin.printedOut=!1,h.internal.acroformPlugin.acroFormDictionaryRoot=null),h.internal.acroformPlugin.acroFormDictionaryRoot||x.call(h),h.internal.acroformPlugin.acroFormDictionaryRoot.Fields.push(t)},m=function(t){var e={type:"reference",object:t};h.annotationPlugin.annotations[h.internal.getPageInfo(t.page).pageNumber].push(e)},y=function(){void 0!==h.internal.acroformPlugin.acroFormDictionaryRoot?h.internal.write("/AcroForm "+h.internal.acroformPlugin.acroFormDictionaryRoot.objId+" 0 R"):console.log("Root missing...")},w=function(){h.internal.events.unsubscribe(h.internal.acroformPlugin.acroFormDictionaryRoot._eventID),delete h.internal.acroformPlugin.acroFormDictionaryRoot._eventID,h.internal.acroformPlugin.printedOut=!0},v=function(t){var e=!t;t||(h.internal.newObjectDeferredBegin(h.internal.acroformPlugin.acroFormDictionaryRoot.objId),h.internal.out(h.internal.acroformPlugin.acroFormDictionaryRoot.getString()));t=t||h.internal.acroformPlugin.acroFormDictionaryRoot.Kids;for(var n in t)if(t.hasOwnProperty(n)){var r=t[n],i=r.Rect;r.Rect&&(r.Rect=l.call(this,r.Rect)),h.internal.newObjectDeferredBegin(r.objId);var o=r.objId+" 0 obj\n<<\n";if("object"===re(r)&&"function"==typeof r.getContent&&(o+=r.getContent()),r.Rect=i,r.hasAppearanceStream&&!r.appearanceStreamContent){var s=f.call(this,r);o+="/AP << /N "+s+" >>\n",h.internal.acroformPlugin.xForms.push(s)}if(r.appearanceStreamContent){for(var a in o+="/AP << ",r.appearanceStreamContent)if(r.appearanceStreamContent.hasOwnProperty(a)){var c=r.appearanceStreamContent[a];if(o+="/"+a+" ",o+="<< ",1<=Object.keys(c).length||Array.isArray(c))for(var n in c){var u;if(c.hasOwnProperty(n))"function"==typeof(u=c[n])&&(u=u.call(this,r)),o+="/"+n+" "+u+" ",0<=h.internal.acroformPlugin.xForms.indexOf(u)||h.internal.acroformPlugin.xForms.push(u)}else"function"==typeof(u=c)&&(u=u.call(this,r)),o+="/"+n+" "+u+" \n",0<=h.internal.acroformPlugin.xForms.indexOf(u)||h.internal.acroformPlugin.xForms.push(u);o+=" >>\n"}o+=">>\n"}o+=">>\nendobj\n",h.internal.out(o)}e&&b.call(this,h.internal.acroformPlugin.xForms)},b=function(t){for(var e in t)if(t.hasOwnProperty(e)){var n=e,r=t[e];h.internal.newObjectDeferredBegin(r&&r.objId);var i="";"object"===re(r)&&"function"==typeof r.getString&&(i=r.getString()),h.internal.out(i),delete t[n]}},x=function(){if(void 0!==this.internal&&(void 0===this.internal.acroformPlugin||!1===this.internal.acroformPlugin.isInitialized)){if(h=this,P.FieldNum=0,this.internal.acroformPlugin=JSON.parse(JSON.stringify(p)),this.internal.acroformPlugin.acroFormDictionaryRoot)throw new Error("Exception while creating AcroformDictionary");e=h.internal.scaleFactor,s=h.internal.pageSize.getHeight(),h.internal.acroformPlugin.acroFormDictionaryRoot=new I,h.internal.acroformPlugin.acroFormDictionaryRoot._eventID=h.internal.events.subscribe("postPutResources",w),h.internal.events.subscribe("buildDocument",d),h.internal.events.subscribe("putCatalog",y),h.internal.events.subscribe("postPutPages",v),h.internal.acroformPlugin.isInitialized=!0}},S=function(t){if(Array.isArray(t)){var e=" [";for(var n in t){if(t.hasOwnProperty(n))e+=t[n].toString(),e+=n>\n",this.stream&&(t+="stream\n",t+=this.stream,t+="\nendstream\n"),t+="endobj\n"},k.prototype.getContent=function(){var t="";return t+=function(t){var e="",n=Object.keys(t).filter(function(t){return"content"!=t&&"appearanceStreamContent"!=t&&"_"!=t.substring(0,1)});for(var r in n)if(n.hasOwnProperty(r)){var i=n[r],o=t[i];o&&(Array.isArray(o)?e+="/"+i+" "+S(o)+"\n":e+=o instanceof k?"/"+i+" "+o.objId+" 0 R\n":"/"+i+" "+o+"\n")}return e}(this)};var C=function(){var e;k.call(this),this.Type="/XObject",this.Subtype="/Form",this.FormType=1,this.BBox,this.Matrix,this.Resources="2 0 R",this.PieceInfo,Object.defineProperty(this,"Length",{enumerable:!0,get:function(){return void 0!==e?e.length:0}}),Object.defineProperty(this,"stream",{enumerable:!1,set:function(t){e=t.trim()},get:function(){return e||null}})};r(C,k);var I=function(){k.call(this);var t=[];Object.defineProperty(this,"Kids",{enumerable:!1,configurable:!0,get:function(){return 0>"},YesPushDown:function(t){var e=c(t),n=[],r=h.internal.getFont("zapfdingbats","normal").id;t.Q=1;var i=u(t,"3","ZapfDingbats",50);return n.push("0.749023 g"),n.push("0 0 "+M.internal.getWidth(t).toFixed(2)+" "+M.internal.getHeight(t).toFixed(2)+" re"),n.push("f"),n.push("BMC"),n.push("q"),n.push("0 0 1 rg"),n.push("/"+r+" "+i.fontSize.toFixed(2)+" Tf 0 g"),n.push("BT"),n.push(i.text),n.push("ET"),n.push("Q"),n.push("EMC"),e.stream=n.join("\n"),e},YesNormal:function(t){var e=c(t),n=h.internal.getFont("zapfdingbats","normal").id,r=[];t.Q=1;var i=M.internal.getHeight(t),o=M.internal.getWidth(t),s=u(t,"3","ZapfDingbats",.9*i);return r.push("1 g"),r.push("0 0 "+o.toFixed(2)+" "+i.toFixed(2)+" re"),r.push("f"),r.push("q"),r.push("0 0 1 rg"),r.push("0 0 "+(o-1).toFixed(2)+" "+(i-1).toFixed(2)+" re"),r.push("W"),r.push("n"),r.push("0 g"),r.push("BT"),r.push("/"+n+" "+s.fontSize.toFixed(2)+" Tf 0 g"),r.push(s.text),r.push("ET"),r.push("Q"),e.stream=r.join("\n"),e},OffPushDown:function(t){var e=c(t),n=[];return n.push("0.749023 g"),n.push("0 0 "+M.internal.getWidth(t).toFixed(2)+" "+M.internal.getHeight(t).toFixed(2)+" re"),n.push("f"),e.stream=n.join("\n"),e}},RadioButton:{Circle:{createAppearanceStream:function(t){var e={D:{Off:M.RadioButton.Circle.OffPushDown},N:{}};return e.N[t]=M.RadioButton.Circle.YesNormal,e.D[t]=M.RadioButton.Circle.YesPushDown,e},createMK:function(){return"<< /CA (l)>>"},YesNormal:function(t){var e=c(t),n=[],r=M.internal.getWidth(t)<=M.internal.getHeight(t)?M.internal.getWidth(t)/4:M.internal.getHeight(t)/4;r*=.9;var i=M.internal.Bezier_C;return n.push("q"),n.push("1 0 0 1 "+M.internal.getWidth(t)/2+" "+M.internal.getHeight(t)/2+" cm"),n.push(r+" 0 m"),n.push(r+" "+r*i+" "+r*i+" "+r+" 0 "+r+" c"),n.push("-"+r*i+" "+r+" -"+r+" "+r*i+" -"+r+" 0 c"),n.push("-"+r+" -"+r*i+" -"+r*i+" -"+r+" 0 -"+r+" c"),n.push(r*i+" -"+r+" "+r+" -"+r*i+" "+r+" 0 c"),n.push("f"),n.push("Q"),e.stream=n.join("\n"),e},YesPushDown:function(t){var e=c(t),n=[],r=M.internal.getWidth(t)<=M.internal.getHeight(t)?M.internal.getWidth(t)/4:M.internal.getHeight(t)/4,i=2*(r*=.9),o=i*M.internal.Bezier_C,s=r*M.internal.Bezier_C;return n.push("0.749023 g"),n.push("q"),n.push("1 0 0 1 "+(M.internal.getWidth(t)/2).toFixed(2)+" "+(M.internal.getHeight(t)/2).toFixed(2)+" cm"),n.push(i+" 0 m"),n.push(i+" "+o+" "+o+" "+i+" 0 "+i+" c"),n.push("-"+o+" "+i+" -"+i+" "+o+" -"+i+" 0 c"),n.push("-"+i+" -"+o+" -"+o+" -"+i+" 0 -"+i+" c"),n.push(o+" -"+i+" "+i+" -"+o+" "+i+" 0 c"),n.push("f"),n.push("Q"),n.push("0 g"),n.push("q"),n.push("1 0 0 1 "+(M.internal.getWidth(t)/2).toFixed(2)+" "+(M.internal.getHeight(t)/2).toFixed(2)+" cm"),n.push(r+" 0 m"),n.push(r+" "+s+" "+s+" "+r+" 0 "+r+" c"),n.push("-"+s+" "+r+" -"+r+" "+s+" -"+r+" 0 c"),n.push("-"+r+" -"+s+" -"+s+" -"+r+" 0 -"+r+" c"),n.push(s+" -"+r+" "+r+" -"+s+" "+r+" 0 c"),n.push("f"),n.push("Q"),e.stream=n.join("\n"),e},OffPushDown:function(t){var e=c(t),n=[],r=M.internal.getWidth(t)<=M.internal.getHeight(t)?M.internal.getWidth(t)/4:M.internal.getHeight(t)/4,i=2*(r*=.9),o=i*M.internal.Bezier_C;return n.push("0.749023 g"),n.push("q"),n.push("1 0 0 1 "+(M.internal.getWidth(t)/2).toFixed(2)+" "+(M.internal.getHeight(t)/2).toFixed(2)+" cm"),n.push(i+" 0 m"),n.push(i+" "+o+" "+o+" "+i+" 0 "+i+" c"),n.push("-"+o+" "+i+" -"+i+" "+o+" -"+i+" 0 c"),n.push("-"+i+" -"+o+" -"+o+" -"+i+" 0 -"+i+" c"),n.push(o+" -"+i+" "+i+" -"+o+" "+i+" 0 c"),n.push("f"),n.push("Q"),e.stream=n.join("\n"),e}},Cross:{createAppearanceStream:function(t){var e={D:{Off:M.RadioButton.Cross.OffPushDown},N:{}};return e.N[t]=M.RadioButton.Cross.YesNormal,e.D[t]=M.RadioButton.Cross.YesPushDown,e},createMK:function(){return"<< /CA (8)>>"},YesNormal:function(t){var e=c(t),n=[],r=M.internal.calculateCross(t);return n.push("q"),n.push("1 1 "+(M.internal.getWidth(t)-2).toFixed(2)+" "+(M.internal.getHeight(t)-2).toFixed(2)+" re"),n.push("W"),n.push("n"),n.push(r.x1.x.toFixed(2)+" "+r.x1.y.toFixed(2)+" m"),n.push(r.x2.x.toFixed(2)+" "+r.x2.y.toFixed(2)+" l"),n.push(r.x4.x.toFixed(2)+" "+r.x4.y.toFixed(2)+" m"),n.push(r.x3.x.toFixed(2)+" "+r.x3.y.toFixed(2)+" l"),n.push("s"),n.push("Q"),e.stream=n.join("\n"),e},YesPushDown:function(t){var e=c(t),n=M.internal.calculateCross(t),r=[];return r.push("0.749023 g"),r.push("0 0 "+M.internal.getWidth(t).toFixed(2)+" "+M.internal.getHeight(t).toFixed(2)+" re"),r.push("f"),r.push("q"),r.push("1 1 "+(M.internal.getWidth(t)-2).toFixed(2)+" "+(M.internal.getHeight(t)-2).toFixed(2)+" re"),r.push("W"),r.push("n"),r.push(n.x1.x.toFixed(2)+" "+n.x1.y.toFixed(2)+" m"),r.push(n.x2.x.toFixed(2)+" "+n.x2.y.toFixed(2)+" l"),r.push(n.x4.x.toFixed(2)+" "+n.x4.y.toFixed(2)+" m"),r.push(n.x3.x.toFixed(2)+" "+n.x3.y.toFixed(2)+" l"),r.push("s"),r.push("Q"),e.stream=r.join("\n"),e},OffPushDown:function(t){var e=c(t),n=[];return n.push("0.749023 g"),n.push("0 0 "+M.internal.getWidth(t).toFixed(2)+" "+M.internal.getHeight(t).toFixed(2)+" re"),n.push("f"),e.stream=n.join("\n"),e}}},createDefaultAppearanceStream:function(t){return"/F1 0 Tf 0 g"}};M.internal={Bezier_C:.551915024494,calculateCross:function(t){var e,n,r=M.internal.getWidth(t),i=M.internal.getHeight(t),o=(n=i)<(e=r)?n:e;return{x1:{x:(r-o)/2,y:(i-o)/2+o},x2:{x:(r-o)/2+o,y:(i-o)/2},x3:{x:(r-o)/2,y:(i-o)/2},x4:{x:(r-o)/2+o,y:(i-o)/2+o}}}},M.internal.getWidth=function(t){var e=0;return"object"===re(t)&&(e=a(t.Rect[2])),e},M.internal.getHeight=function(t){var e=0;return"object"===re(t)&&(e=a(t.Rect[3])),e},n.addField=function(t){return x.call(this),t instanceof U?this.addTextField.call(this,t):t instanceof F?this.addChoiceField.call(this,t):t instanceof O?this.addButton.call(this,t):t instanceof E?g.call(this,t):t&&g.call(this,t),t.page=h.internal.getCurrentPageInfo().pageNumber,this},n.addButton=function(t){x.call(this);var e=t||new P;e.FT="/Btn",e.Ff=o(e.Ff,t,h.internal.getPDFVersion()),g.call(this,e)},n.addTextField=function(t){x.call(this);var e=t||new P;e.FT="/Tx",e.Ff=o(e.Ff,t,h.internal.getPDFVersion()),g.call(this,e)},n.addChoiceField=function(t){x.call(this);var e=t||new P;e.FT="/Ch",e.Ff=o(e.Ff,t,h.internal.getPDFVersion()),g.call(this,e)},"object"==re(t)&&(t.ChoiceField=F,t.ListBox=q,t.ComboBox=j,t.EditBox=T,t.Button=O,t.PushButton=B,t.RadioButton=D,t.CheckBox=R,t.TextField=U,t.PasswordField=z,t.AcroForm={Appearance:M}),n.AcroFormChoiceField=F,n.AcroFormListBox=q,n.AcroFormComboBox=j,n.AcroFormEditBox=T,n.AcroFormButton=O,n.AcroFormPushButton=B,n.AcroFormRadioButton=D,n.AcroFormCheckBox=R,n.AcroFormTextField=U,n.AcroFormPasswordField=z,n.AcroFormAppearance=M,n.AcroForm={ChoiceField:F,ListBox:q,ComboBox:j,EditBox:T,Button:O,PushButton:B,RadioButton:D,CheckBox:R,TextField:U,PasswordField:z,Appearance:M}}(rt.API,"undefined"!=typeof window&&window||"undefined"!=typeof global&&global), +/** @license + * jsPDF addImage plugin + * Copyright (c) 2012 Jason Siefken, https://github.com/siefkenj/ + * 2013 Chris Dowling, https://github.com/gingerchris + * 2013 Trinh Ho, https://github.com/ineedfat + * 2013 Edwin Alejandro Perez, https://github.com/eaparango + * 2013 Norah Smith, https://github.com/burnburnrocket + * 2014 Diego Casorran, https://github.com/diegocr + * 2014 James Robb, https://github.com/jamesbrobb + * + * + */ +function(b){var x="addImage_",c={PNG:[[137,80,78,71]],TIFF:[[77,77,0,42],[73,73,42,0]],JPEG:[[255,216,255,224,void 0,void 0,74,70,73,70,0],[255,216,255,225,void 0,void 0,69,120,105,102,0,0]],JPEG2000:[[0,0,0,12,106,80,32,32]],GIF87a:[[71,73,70,56,55,97]],GIF89a:[[71,73,70,56,57,97]],BMP:[[66,77],[66,65],[67,73],[67,80],[73,67],[80,84]]};b.getImageFileTypeByImageData=function(t,e){var n,r;e=e||"UNKNOWN";var i,o,s,a="UNKNOWN";for(s in b.isArrayBufferView(t)&&(t=b.arrayBufferToBinaryString(t)),c)for(i=c[s],n=0;n>"),"trns"in e&&e.trns.constructor==Array){for(var o="",s=0,a=e.trns.length;s>"),i(e.data),r("endobj"),"smask"in e){var c="/Predictor "+e.p+" /Colors 1 /BitsPerComponent "+e.bpc+" /Columns "+e.w,u={w:e.w,h:e.h,cs:"DeviceGray",bpc:e.bpc,dp:c,data:e.smask};"f"in e&&(u.f=e.f),t.call(this,u)}e.cs===this.color_spaces.INDEXED&&(this.internal.newObject(),r("<< /Length "+e.pal.length+">>"),i(this.arrayBufferToBinaryString(new Uint8Array(e.pal))),r("endobj"))},S=function(){var t=this.internal.collections[x+"images"];for(var e in t)n.call(this,t[e])},_=function(){var t,e=this.internal.collections[x+"images"],n=this.internal.write;for(var r in e)n("/I"+(t=e[r]).i,t.n,"0","R")},k=function(t){return"function"==typeof b["process"+t.toUpperCase()]},A=function(t){return"object"===re(t)&&1===t.nodeType},C=function(t,e){if("IMG"===t.nodeName&&t.hasAttribute("src")){var n=""+t.getAttribute("src");if(0===n.indexOf("data:image/"))return unescape(n);!e&&/\.png(?:[?#].*)?$/i.test(n)&&(e="png")}if("CANVAS"===t.nodeName)var r=t;else{(r=document.createElement("canvas")).width=t.clientWidth||t.width,r.height=t.clientHeight||t.height;var i=r.getContext("2d");if(!i)throw"addImage requires canvas to be supported by browser.";i.drawImage(t,0,0,r.width,r.height)}return r.toDataURL("png"==(""+e).toLowerCase()?"image/png":"image/jpeg")},I=function(t,e){var n;if(e)for(var r in e)if(t===e[r].alias){n=e[r];break}return n};b.color_spaces={DEVICE_RGB:"DeviceRGB",DEVICE_GRAY:"DeviceGray",DEVICE_CMYK:"DeviceCMYK",CAL_GREY:"CalGray",CAL_RGB:"CalRGB",LAB:"Lab",ICC_BASED:"ICCBased",INDEXED:"Indexed",PATTERN:"Pattern",SEPARATION:"Separation",DEVICE_N:"DeviceN"},b.decode={DCT_DECODE:"DCTDecode",FLATE_DECODE:"FlateDecode",LZW_DECODE:"LZWDecode",JPX_DECODE:"JPXDecode",JBIG2_DECODE:"JBIG2Decode",ASCII85_DECODE:"ASCII85Decode",ASCII_HEX_DECODE:"ASCIIHexDecode",RUN_LENGTH_DECODE:"RunLengthDecode",CCITT_FAX_DECODE:"CCITTFaxDecode"},b.image_compression={NONE:"NONE",FAST:"FAST",MEDIUM:"MEDIUM",SLOW:"SLOW"},b.sHashCode=function(t){return t=t||"",Array.prototype.reduce&&t.split("").reduce(function(t,e){return(t=(t<<5)-t+e.charCodeAt(0))&t},0)},b.isString=function(t){return"string"==typeof t},b.validateStringAsBase64=function(t){var e=!0;return(t=t||"").length%4!=0&&(e=!1),!1===/[A-Za-z0-9\/]+/.test(t.substr(0,t.length-2))&&(e=!1),!1===/[A-Za-z0-9\/][A-Za-z0-9+\/]|[A-Za-z0-9+\/]=|==/.test(t.substr(-2))&&(e=!1),e},b.extractInfoFromBase64DataURI=function(t){return/^data:([\w]+?\/([\w]+?));\S*;*base64,(.+)$/g.exec(t)},b.supportsArrayBuffer=function(){return"undefined"!=typeof ArrayBuffer&&"undefined"!=typeof Uint8Array},b.isArrayBuffer=function(t){return!!this.supportsArrayBuffer()&&t instanceof ArrayBuffer},b.isArrayBufferView=function(t){return!!this.supportsArrayBuffer()&&("undefined"!=typeof Uint32Array&&(t instanceof Int8Array||t instanceof Uint8Array||"undefined"!=typeof Uint8ClampedArray&&t instanceof Uint8ClampedArray||t instanceof Int16Array||t instanceof Uint16Array||t instanceof Int32Array||t instanceof Uint32Array||t instanceof Float32Array||t instanceof Float64Array))},b.binaryStringToUint8Array=function(t){for(var e=t.length,n=new Uint8Array(e),r=0;r>18]+r[(258048&e)>>12]+r[(4032&e)>>6]+r[63&e];return 1==s?n+=r[(252&(e=i[a]))>>2]+r[(3&e)<<4]+"==":2==s&&(n+=r[(64512&(e=i[a]<<8|i[a+1]))>>10]+r[(1008&e)>>4]+r[(15&e)<<2]+"="),n},b.createImageInfo=function(t,e,n,r,i,o,s,a,c,u,h,l,f){var p={alias:a,w:e,h:n,cs:r,bpc:i,i:s,data:t};return o&&(p.f=o),c&&(p.dp=c),u&&(p.trns=u),h&&(p.pal=h),l&&(p.smask=l),f&&(p.p=f),p},b.addImage=function(t,e,n,r,i,o,s,a,c){var u="";if("string"!=typeof e){var h=o;o=i,i=r,r=n,n=e,e=h}if("object"===re(t)&&!A(t)&&"imageData"in t){var l=t;t=l.imageData,e=l.format||e,n=l.x||n||0,r=l.y||r||0,i=l.w||i,o=l.h||o,s=l.alias||s,a=l.compression||a,c=l.rotation||l.angle||c}if("string"==typeof t&&(t=unescape(t)),isNaN(n)||isNaN(r))throw console.error("jsPDF.addImage: Invalid coordinates",arguments),new Error("Invalid coordinates passed to jsPDF.addImage");var f,p,d,g,m,y,w,v=function(){var t=this.internal.collections[x+"images"];return t||(this.internal.collections[x+"images"]=t={},this.internal.events.subscribe("putResources",S),this.internal.events.subscribe("putXobjectDict",_)),t}.call(this);if(!(f=I(t,v))&&(A(t)&&(t=C(t,e)),(null==(w=s)||0===w.length)&&(s="string"==typeof(y=t)&&b.sHashCode(y)),!(f=I(s,v)))){if(this.isString(t)&&(""!==(u=this.convertStringToImageData(t))?t=u:void 0!==(u=this.loadImageFile(t))&&(t=u)),e=this.getImageFileTypeByImageData(t,e),!k(e))throw new Error("addImage does not support files of type '"+e+"', please ensure that a plugin for '"+e+"' support is added.");if(this.supportsArrayBuffer()&&(t instanceof Uint8Array||(p=t,t=this.binaryStringToUint8Array(t))),!(f=this["process"+e.toUpperCase()](t,(m=0,(g=v)&&(m=Object.keys?Object.keys(g).length:function(t){var e=0;for(var n in t)t.hasOwnProperty(n)&&e++;return e}(g)),m),s,((d=a)&&"string"==typeof d&&(d=d.toUpperCase()),d in b.image_compression?d:b.image_compression.NONE),p)))throw new Error("An unkwown error occurred whilst processing the image")}return function(t,e,n,r,i,o,s,a){var c=function(t,e,n){return t||e||(e=t=-96),t<0&&(t=-1*n.w*72/t/this.internal.scaleFactor),e<0&&(e=-1*n.h*72/e/this.internal.scaleFactor),0===t&&(t=e*n.w/n.h),0===e&&(e=t*n.h/n.w),[t,e]}.call(this,n,r,i),u=this.internal.getCoordinateString,h=this.internal.getVerticalCoordinateString;if(n=c[0],r=c[1],s[o]=i,a){a*=Math.PI/180;var l=Math.cos(a),f=Math.sin(a),p=function(t){return t.toFixed(4)},d=[p(l),p(f),p(-1*f),p(l),0,0,"cm"]}this.internal.write("q"),a?(this.internal.write([1,"0","0",1,u(t),h(e+r),"cm"].join(" ")),this.internal.write(d.join(" ")),this.internal.write([u(n),"0","0",u(r),"0","0","cm"].join(" "))):this.internal.write([u(n),"0","0",u(r),u(t),h(e+r),"cm"].join(" ")),this.isAdvancedAPI()&&this.internal.write([1,0,0,-1,0,0,"cm"].join(" ")),this.internal.write("/I"+i.i+" Do"),this.internal.write("Q")}.call(this,n,r,i,o,f,f.i,v,c),this},b.convertStringToImageData=function(t){var e,n="";this.isString(t)&&(null!==(e=this.extractInfoFromBase64DataURI(t))?b.validateStringAsBase64(e[3])&&(n=atob(e[3])):b.validateStringAsBase64(t)&&(n=atob(t)));return n};var u=function(t,e){return t.subarray(e,e+5)};b.processJPEG=function(t,e,n,r,i,o){var s,a=this.decode.DCT_DECODE;if(!this.isString(t)&&!this.isArrayBuffer(t)&&!this.isArrayBufferView(t))return null;if(this.isString(t)&&(s=function(t){var e;if(255===!t.charCodeAt(0)||216===!t.charCodeAt(1)||255===!t.charCodeAt(2)||224===!t.charCodeAt(3)||!t.charCodeAt(6)==="J".charCodeAt(0)||!t.charCodeAt(7)==="F".charCodeAt(0)||!t.charCodeAt(8)==="I".charCodeAt(0)||!t.charCodeAt(9)==="F".charCodeAt(0)||0===!t.charCodeAt(10))throw new Error("getJpegSize requires a binary string jpeg file");for(var n=256*t.charCodeAt(4)+t.charCodeAt(5),r=4,i=t.length;r>",u.content=m;var f=u.objId+" 0 R";m="<>";else if(c.options.pageNumber)switch(m="<>",this.internal.write(m))}}this.internal.write("]")}}]),n.createAnnotation=function(t){switch(t.type){case"link":this.link(t.bounds.x,t.bounds.y,t.bounds.w,t.bounds.h,t);break;case"text":case"freetext":this.annotationPlugin.annotations[this.internal.getCurrentPageInfo().pageNumber].push(t)}},n.link=function(t,e,n,r,i){this.annotationPlugin.annotations[this.internal.getCurrentPageInfo().pageNumber].push({x:t,y:e,w:n,h:r,options:i,type:"link"})},n.textWithLink=function(t,e,n,r){var i=this.getTextWidth(t),o=this.internal.getLineHeight()/this.internal.scaleFactor;return this.text(t,e,n),n+=.2*o,this.link(e,n-o,i,o,r),i},n.getTextWidth=function(t){var e=this.internal.getFontSize();return this.getStringUnitWidth(t)*e/this.internal.scaleFactor},n.getLineHeight=function(){return this.internal.getLineHeight()}, +/** + * @license + * Copyright (c) 2017 Aras Abbasi + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ +function(t){var s=Object.keys({ar:"Arabic (Standard)","ar-DZ":"Arabic (Algeria)","ar-BH":"Arabic (Bahrain)","ar-EG":"Arabic (Egypt)","ar-IQ":"Arabic (Iraq)","ar-JO":"Arabic (Jordan)","ar-KW":"Arabic (Kuwait)","ar-LB":"Arabic (Lebanon)","ar-LY":"Arabic (Libya)","ar-MA":"Arabic (Morocco)","ar-OM":"Arabic (Oman)","ar-QA":"Arabic (Qatar)","ar-SA":"Arabic (Saudi Arabia)","ar-SY":"Arabic (Syria)","ar-TN":"Arabic (Tunisia)","ar-AE":"Arabic (U.A.E.)","ar-YE":"Arabic (Yemen)",fa:"Persian","fa-IR":"Persian/Iran",ur:"Urdu"}),l={1569:[65152],1570:[65153,65154,65153,65154],1571:[65155,65156,65155,65156],1572:[65157,65158],1573:[65159,65160,65159,65160],1574:[65161,65162,65163,65164],1575:[65165,65166,65165,65166],1576:[65167,65168,65169,65170],1577:[65171,65172],1578:[65173,65174,65175,65176],1579:[65177,65178,65179,65180],1580:[65181,65182,65183,65184],1581:[65185,65186,65187,65188],1582:[65189,65190,65191,65192],1583:[65193,65194,65193],1584:[65195,65196,65195],1585:[65197,65198,65197],1586:[65199,65200,65199],1587:[65201,65202,65203,65204],1588:[65205,65206,65207,65208],1589:[65209,65210,65211,65212],1590:[65213,65214,65215,65216],1591:[65217,65218,65219,65220],1592:[65221,65222,65223,65224],1593:[65225,65226,65227,65228],1594:[65229,65230,65231,65232],1601:[65233,65234,65235,65236],1602:[65237,65238,65239,65240],1603:[65241,65242,65243,65244],1604:[65245,65246,65247,65248],1605:[65249,65250,65251,65252],1606:[65253,65254,65255,65256],1607:[65257,65258,65259,65260],1608:[65261,65262,65261],1609:[65263,65264,64488,64489],1610:[65265,65266,65267,65268],1649:[64336,64337],1655:[64477],1657:[64358,64359,64360,64361],1658:[64350,64351,64352,64353],1659:[64338,64339,64340,64341],1662:[64342,64343,64344,64345],1663:[64354,64355,64356,64357],1664:[64346,64347,64348,64349],1667:[64374,64375,64376,64377],1668:[64370,64371,64372,64373],1670:[64378,64379,64380,64381],1671:[64382,64383,64384,64385],1672:[64392,64393],1676:[64388,64389],1677:[64386,64387],1678:[64390,64391],1681:[64396,64397],1688:[64394,64395,64394],1700:[64362,64363,64364,64365],1702:[64366,64367,64368,64369],1705:[64398,64399,64400,64401],1709:[64467,64468,64469,64470],1711:[64402,64403,64404,64405],1713:[64410,64411,64412,64413],1715:[64406,64407,64408,64409],1722:[64414,64415],1723:[64416,64417,64418,64419],1726:[64426,64427,64428,64429],1728:[64420,64421],1729:[64422,64423,64424,64425],1733:[64480,64481],1734:[64473,64474],1735:[64471,64472],1736:[64475,64476],1737:[64482,64483],1739:[64478,64479],1740:[64508,64509,64510,64511],1744:[64484,64485,64486,64487],1746:[64430,64431],1747:[64432,64433]},f={1570:[65269,65270,65269,65270],1571:[65271,65272,65271,65272],1573:[65273,65274,65273,65274],1575:[65275,65276,65275,65276]},p={1570:[65153,65154,65153,65154],1571:[65155,65156,65155,65156],1573:[65159,65160,65159,65160],1575:[65165,65166,65165,65166]},d={1612:64606,1613:64607,1614:64608,1615:64609,1616:64610},e=[1570,1571,1573,1575],n=[1569,1570,1571,1572,1573,1575,1577,1583,1584,1585,1586,1608,1688],o=0,a=1,c=2,u=3;function g(t){return void 0!==t&&void 0!==l[t.charCodeAt(0)]}function h(t){return void 0!==t&&0<=n.indexOf(t.charCodeAt(0))}function m(t){return void 0!==t&&0<=e.indexOf(t.charCodeAt(0))}function y(t){return g(t)&&2<=l[t.charCodeAt(0)].length}function w(t,e,n,r){return g(t)?(r=r||{},l=Object.assign(l,r),!y(t)||!g(e)&&!g(n)||!g(n)&&h(e)||h(t)&&!g(e)||h(t)&&m(e)||h(t)&&h(e)?(l=Object.assign(l,p),o):g(i=t)&&4==l[i.charCodeAt(0)].length&&g(e)&&!h(e)&&g(n)&&y(n)?(l=Object.assign(l,p),u):h(t)||!g(n)?(l=Object.assign(l,p),a):(l=Object.assign(l,p),c)):-1;var i}var v=t.processArabic=function(t,e){t=t||"",e=e||!1;var n,r,i,o="",s=0,a=0,c="",u="",h="";for(s=0;s>"),this.internal.out("endobj")}),this.internal.events.subscribe("putCatalog",function(){this.internal.out("/OpenAction "+e+" 0 R")})}return this},( +/** + * @license + * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ +r=rt.API).events.push(["initialized",function(){this.canvas.pdf=this}]),r.canvas={getContext:function(t){return(this.pdf.context2d._canvas=this).pdf.context2d},childNodes:[],style:{},autoContext2dResizeX:!0,autoContext2dResizeY:!0},Object.defineProperty(r.canvas,"width",{get:function(){return this._width},set:function(t){this._width=t,this.autoContext2dResizeX&&(this.getContext("2d").pageWrapX=t+1)}}),Object.defineProperty(r.canvas,"height",{get:function(){return this._height},set:function(t){this._height=t,this.autoContext2dResizeY&&(this.getContext("2d").pageWrapY=t+1)}}), +/** + * @license + * ==================================================================== + * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com + * 2013 Eduardo Menezes de Morais, eduardo.morais@usp.br + * 2013 Lee Driscoll, https://github.com/lsdriscoll + * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria + * 2014 James Hall, james@parall.ax + * 2014 Diego Casorran, https://github.com/diegocr + * + * + * ==================================================================== + */ +C=rt.API,I={x:void 0,y:void 0,w:void 0,h:void 0,ln:void 0},P=1,p=function(t,e,n,r,i){I={x:t,y:e,w:n,h:r,ln:i}},d=function(){return I},F={left:0,top:0,bottom:0},C.setHeaderFunction=function(t){c=t},C.getTextDimensions=function(t,e){var n=this.table_font_size||this.internal.getFontSize(),r=(this.internal.getFont().fontStyle,(e=e||{}).scaleFactor||this.internal.scaleFactor),i=0,o=0,s=0;if("string"==typeof t)0!=(i=this.getStringUnitWidth(t)*n)&&(o=1);else if("[object Array]"===Object.prototype.toString.call(t)){for(var a=0;a=this.internal.pageSize.getHeight()-u.bottom&&(this.cellAddPage(),c=!0,this.printHeaders&&this.tableHeaderRow&&this.printHeaderRow(o,!0)),e=d().y+d().h,c&&(e=23)}if(void 0!==i[0])if(this.printingHeaderRow?this.rect(t,e,n,r,"FD"):this.rect(t,e,n,r),"right"===s){i instanceof Array||(i=[i]);for(var h=0;h=this.pageBreaks[r]){e++,0===this.lastBreak&&n++;var i=this.pageBreaks[r]-this.lastBreak;this.lastBreak=this.pageBreaks[r],n+=Math.floor(i/this.pageWrapY)}if(0===this.lastBreak)n+=Math.floor(t/this.pageWrapY)+1;return n+e}return this.pdf.internal.getCurrentPageInfo().pageNumber},_gotoPage:function(t){},drawImage:function(t,e,n,r,i,o,s,a,c){void 0!==o&&(e=o,n=s,r=a,i=c),e=this._wrapX(e),n=this._wrapY(n);var u,h=this._matrix_map_rect(this.ctx._transform,{x:e,y:n,w:r,h:i}),l=(this._matrix_map_rect(this.ctx._transform,{x:o,y:s,w:a,h:c}),/data:image\/(\w+).*/i.exec(t));u=null!=l?l[1]:"png",this.pdf.addImage(t,u,h.x,h.y,h.w,h.h)},_matrix_multiply:function(t,e){var n=e[0],r=e[1],i=e[2],o=e[3],s=e[4],a=e[5],c=n*t[0]+r*t[2],u=i*t[0]+o*t[2],h=s*t[0]+a*t[2]+t[4];return r=n*t[1]+r*t[3],o=i*t[1]+o*t[3],a=s*t[1]+a*t[3]+t[5],[n=c,r,i=u,o,s=h,a]},_matrix_rotation:function(t){return Math.atan2(t[2],t[0])},_matrix_decompose:function(t){var e=t[0],n=t[1],r=t[2],i=t[3],o=Math.sqrt(e*e+n*n),s=(e/=o)*r+(n/=o)*i;r-=e*s,i-=n*s;var a=Math.sqrt(r*r+i*i);return s/=a,e*(i/=a)>"),this.internal.out("endobj"),l=this.internal.newObject(),this.internal.out("<<"),this.internal.out("/S /JavaScript"),this.internal.out("/JS ("+f+")"),this.internal.out(">>"),this.internal.out("endobj")}),this.internal.events.subscribe("putCatalog",function(){void 0!==h&&void 0!==l&&this.internal.out("/Names <>")}),this},( +/** + * @license + * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ +g=rt.API).events.push(["postPutResources",function(){var t=this,e=/^(\d+) 0 obj$/;if(0> endobj")}var l=t.internal.newObject();for(t.internal.write("<< /Names [ "),r=0;r>","endobj"),t.internal.newObject(),t.internal.write("<< /Dests "+l+" 0 R"),t.internal.write(">>","endobj")}}]),g.events.push(["putCatalog",function(){0> \r\nendobj\r\n"},o.outline.count_r=function(t,e){for(var n=0;n>>24&255,f[l++]=a>>>16&255,f[l++]=a>>>8&255,f[l++]=255&a,q.arrayBufferToBinaryString(f)},m=function(t,e){var n=Math.LOG2E*Math.log(32768)-8<<4|8,r=n<<8;return r|=Math.min(3,(e-1&255)>>1)<<6,r|=0,[n,255&(r+=31-r%31)]},y=function(t,e){for(var n,r=1,i=0,o=t.length,s=0;0>>0},v=function(t,e,n,r){for(var i,o,s,a=t.length/e,c=new Uint8Array(t.length+a),u=O(),h=0;h>>1)&255;return o},k=function(t,e,n){var r,i,o,s,a=[],c=0,u=t.length;for(a[0]=4;c>>d&255,d+=o.bits;y[v]=x>>>d&255}if(16===o.bits){g=(C=new Uint32Array(o.decodePixels().buffer)).length,m=new Uint8Array(g*(32/o.pixelBitlength)*o.colors),y=new Uint8Array(g*(32/o.pixelBitlength));for(var x,S=1>>0&255,S&&(m[b++]=x>>>16&255,x=C[v++],m[b++]=x>>>0&255),y[_++]=x>>>16&255;p=8}r!==q.image_compression.NONE&&j()?(t=T(m,o.width*o.colors,o.colors,r),h=T(y,o.width,1,r)):(t=m,h=y,f=null)}if(3===o.colorType&&(l=this.color_spaces.INDEXED,u=o.palette,o.transparency.indexed)){var k=o.transparency.indexed,A=0;for(v=0,g=k.length;vr&&(i.push(t.slice(c,o)),a=0,c=o),a+=e[o],o++;return c!==o&&i.push(t.slice(c,o)),i},H=function(t,e,n){n||(n={});var r,i,o,s,a,c,u=[],h=[u],l=n.textIndent||0,f=0,p=0,d=t.split(" "),g=z.apply(this,[" ",n])[0];if(c=-1===n.lineIndent?d[0].length+2:n.lineIndent||0){var m=Array(c).join(" "),y=[];d.map(function(t){1<(t=t.split(/\s*\n/)).length?y=y.concat(t.map(function(t,e){return(e&&t.length?"\n":"")+t})):y.push(t[0])}),d=y,c=N.apply(this,[m,n])}for(o=0,s=d.length;o>")}),this.internal.viewerpreferences.isSubscribed=!0),this.internal.viewerpreferences.configuration=n,this}, +/** ==================================================================== + * jsPDF XMP metadata plugin + * Copyright (c) 2016 Jussi Utunen, u-jussi@suomi24.fi + * + * + * ==================================================================== + */ +Q=rt.API,tt=$=Z="",Q.addMetadata=function(t,e){return $=e||"http://jspdf.default.namespaceuri/",Z=t,this.internal.events.subscribe("postPutResources",function(){if(Z){var t='',e=unescape(encodeURIComponent('')),n=unescape(encodeURIComponent(t)),r=unescape(encodeURIComponent(Z)),i=unescape(encodeURIComponent("")),o=unescape(encodeURIComponent("")),s=n.length+r.length+i.length+e.length+o.length;tt=this.internal.newObject(),this.internal.write("<< /Type /Metadata /Subtype /XML /Length "+s+" >>"),this.internal.write("stream"),this.internal.write(e+n+r+i+o),this.internal.write("endstream"),this.internal.write("endobj")}else tt=""}),this.internal.events.subscribe("putCatalog",function(){tt&&this.internal.write("/Metadata "+tt+" 0 R")}),this},function(p,t){var e=p.API;var m=e.pdfEscape16=function(t,e){for(var n,r=e.metadata.Unicode.widths,i=["","0","00","000","0000"],o=[""],s=0,a=t.length;s<"+i+">");return r.length&&(o+="\n"+r.length+" beginbfchar\n"+r.join("\n")+"\nendbfchar\n"),o+="endcmap\nCMapName currentdict /CMap defineresource pop\nend\nend"};e.events.push(["putFont",function(t){!function(t,e,n,r){if(t.metadata instanceof p.API.TTFFont&&"Identity-H"===t.encoding){for(var i=t.metadata.Unicode.widths,o=t.metadata.subset.encode(t.metadata.glyIdsUsed,1),s="",a=0;a>"),r(s),e("endobj");var u=n(),h=d(t.metadata.toUnicode);e("<<"),e("/Length "+h.length),e("/Length1 "+h.length),e(">>"),r(h),e("endobj");var l=n();e("<<"),e("/Type /FontDescriptor"),e("/FontName /"+t.fontName),e("/FontFile2 "+c+" 0 R"),e("/FontBBox "+p.API.PDFObject.convert(t.metadata.bbox)),e("/Flags "+t.metadata.flags),e("/StemV "+t.metadata.stemV),e("/ItalicAngle "+t.metadata.italicAngle),e("/Ascent "+t.metadata.ascender),e("/Descent "+t.metadata.decender),e("/CapHeight "+t.metadata.capHeight),e(">>"),e("endobj");var f=n();e("<<"),e("/Type /Font"),e("/BaseFont /"+t.fontName),e("/FontDescriptor "+l+" 0 R"),e("/W "+p.API.PDFObject.convert(i)),e("/CIDToGIDMap /Identity"),e("/DW 1000"),e("/Subtype /CIDFontType2"),e("/CIDSystemInfo"),e("<<"),e("/Supplement 0"),e("/Registry (Adobe)"),e("/Ordering ("+t.encoding+")"),e(">>"),e(">>"),e("endobj"),t.objectNumber=n(),e("<<"),e("/Type /Font"),e("/Subtype /Type0"),e("/ToUnicode "+u+" 0 R"),e("/BaseFont /"+t.fontName),e("/Encoding /"+t.encoding),e("/DescendantFonts ["+f+" 0 R]"),e(">>"),e("endobj"),t.isAlreadyPutted=!0}}(t.font,t.out,t.newObject,t.putStream)}]);e.events.push(["putFont",function(t){!function(t,e,n,r){if(t.metadata instanceof p.API.TTFFont&&"WinAnsiEncoding"===t.encoding){t.metadata.Unicode.widths;for(var i=t.metadata.rawData,o="",s=0;s>"),e("endobj"),t.objectNumber=n(),s=0;s>"),e("endobj"),t.isAlreadyPutted=!0}}(t.font,t.out,t.newObject,t.putStream)}]);var u=function(t){var e,n,r=t.text||"",i=t.x,o=t.y,s=t.options||{},a=t.mutex||{},c=a.pdfEscape,u=a.activeFontKey,h=a.fonts,l=(a.activeFontSize,""),f=0,p="",d=h[n=u].encoding;if("Identity-H"!==h[n].encoding)return{text:r,x:i,y:o,options:s,mutex:a};for(p=r,n=u,"[object Array]"===Object.prototype.toString.call(r)&&(p=r[0]),f=0;f>7,i=1<<(7&n)+1;x[t++];x[t++];var o=null;r&&(o=t,t+=3*i);var s=!0,a=[],c=0,u=null,h=0,l=null;for(this.width=S,this.height=e;s&&t>2&7,t++;break;case 254:for(;;){if(0===(k=x[t++]))break;t+=k}break;default:throw"Unknown graphic control label: 0x"+x[t-1].toString(16)}break;case 44:var p=x[t++]|x[t++]<<8,d=x[t++]|x[t++]<<8,g=x[t++]|x[t++]<<8,m=x[t++]|x[t++]<<8,y=x[t++],w=y>>6&1,v=o,b=!1;if(y>>7){b=!0;v=t,t+=3*(1<<(7&y)+1)}var _=t;for(t++;;){var k;if(0===(k=x[t++]))break;t+=k}a.push({x:p,y:d,width:g,height:m,has_local_palette:b,palette_offset:v,data_offset:_,data_length:t-_,transparent_index:u,interlaced:!!w,delay:c,disposal:h});break;case 59:s=!1;break;default:throw"Unknown gif block: 0x"+x[t-1].toString(16)}this.numFrames=function(){return a.length},this.loopCount=function(){return l},this.frameInfo=function(t){if(t<0||t>=a.length)throw"Frame index out of range.";return a[t]},this.decodeAndBlitFrameBGRA=function(t,e){var n=this.frameInfo(t),r=n.width*n.height,i=new Uint8Array(r);bt(x,n.data_offset,i,r);var o=n.palette_offset,s=n.transparent_index;null===s&&(s=256);var a=n.width,c=S-a,u=a,h=4*(n.y*S+n.x),l=4*((n.y+n.height)*S+n.x),f=h,p=4*c;!0===n.interlaced&&(p+=4*(a+c)*7);for(var d=8,g=0,m=i.length;g>=1)),y===s)f+=4;else{var w=x[o+3*y],v=x[o+3*y+1],b=x[o+3*y+2];e[f++]=b,e[f++]=v,e[f++]=w,e[f++]=255}--u}},this.decodeAndBlitFrameRGBA=function(t,e){var n=this.frameInfo(t),r=n.width*n.height,i=new Uint8Array(r);bt(x,n.data_offset,i,r);var o=n.palette_offset,s=n.transparent_index;null===s&&(s=256);var a=n.width,c=S-a,u=a,h=4*(n.y*S+n.x),l=4*((n.y+n.height)*S+n.x),f=h,p=4*c;!0===n.interlaced&&(p+=4*(a+c)*7);for(var d=8,g=0,m=i.length;g>=1)),y===s)f+=4;else{var w=x[o+3*y],v=x[o+3*y+1],b=x[o+3*y+2];e[f++]=w,e[f++]=v,e[f++]=b,e[f++]=255}--u}}}function bt(t,e,n,r){for(var i=t[e++],o=1<>=c,h-=c,m!==o){if(m===s)break;for(var y=m>8,++w;var b=v;if(r>=8;null!==g&&a<4096&&(d[a++]=g<<8|b,u+1<=a&&c<12&&(++c,u=u<<1|1)),g=m}else a=s+1,u=(1<<(c=i+1))-1,g=null}return f!==r&&console.log("Warning, gif stream shorter than expected."),n}"undefined"!=typeof module&&module.exports?module.exports.saveAs=ie:"undefined"!=typeof define&&null!==define&&null!==define.amd&&define("FileSaver.js",function(){return ie}),rt.API.adler32cs=(ut="function"==typeof ArrayBuffer&&"function"==typeof Uint8Array,ht=ut?function(t){return t instanceof ArrayBuffer||!1}:function(){return!1},lt=function(t){return unescape(encodeURIComponent(t))},ft=65521,pt=function(t,e){for(var n=65535&t,r=t>>>16,i=0,o=e.length;i>>0},dt=function(t,e){for(var n=65535&t,r=t>>>16,i=0,o=e.length;i>>0},mt=(gt={}).Adler32=(((ct=(at=function(t){if(!(this instanceof at))throw new TypeError("Constructor cannot called be as a function.");if(!isFinite(t=null==t?1:+t))throw new Error("First arguments needs to be a finite number.");this.checksum=t>>>0}).prototype={}).constructor=at).from=((it=function(t){if(!(this instanceof at))throw new TypeError("Constructor cannot called be as a function.");if(null==t)throw new Error("First argument needs to be a string.");this.checksum=pt(1,t.toString())}).prototype=ct,it),at.fromUtf8=((ot=function(t){if(!(this instanceof at))throw new TypeError("Constructor cannot called be as a function.");if(null==t)throw new Error("First argument needs to be a string.");var e=lt(t.toString());this.checksum=pt(1,e)}).prototype=ct,ot),ut&&(at.fromBuffer=((st=function(t){if(!(this instanceof at))throw new TypeError("Constructor cannot called be as a function.");if(!ht(t))throw new Error("First argument needs to be ArrayBuffer.");var e=new Uint8Array(t);return this.checksum=dt(1,e)}).prototype=ct,st)),ct.update=function(t){if(null==t)throw new Error("First argument needs to be a string.");return t=t.toString(),this.checksum=pt(this.checksum,t)},ct.updateUtf8=function(t){if(null==t)throw new Error("First argument needs to be a string.");var e=lt(t.toString());return this.checksum=pt(this.checksum,e)},ut&&(ct.updateBuffer=function(t){if(!ht(t))throw new Error("First argument needs to be ArrayBuffer.");var e=new Uint8Array(t);return this.checksum=dt(this.checksum,e)}),ct.clone=function(){return new mt(this.checksum)},at),gt.from=function(t){if(null==t)throw new Error("First argument needs to be a string.");return pt(1,t.toString())},gt.fromUtf8=function(t){if(null==t)throw new Error("First argument needs to be a string.");var e=lt(t.toString());return pt(1,e)},ut&&(gt.fromBuffer=function(t){if(!ht(t))throw new Error("First argument need to be ArrayBuffer.");var e=new Uint8Array(t);return dt(1,e)}),gt), +/* + Copyright (c) 2008, Adobe Systems Incorporated + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Adobe Systems Incorporated nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + Copyright (c) 2013 Gildas Lormeau. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, + INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +function(t){var d=15,g=573,e=[0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,0,0,16,17,18,18,19,19,20,20,20,20,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29];function lt(){var p=this;function c(t,e){for(var n=0;n|=1&t,t>>>=1,n<<=1,0<--e;);return n>>>1}p.build_tree=function(t){var e,n,r,i=p.dyn_tree,o=p.stat_desc.static_tree,s=p.stat_desc.elems,a=-1;for(t.heap_len=0,t.heap_max=g,e=0;ep.max_code||(t.bl_count[i]++,o=0,h<=n&&(o=u[n-h]),s=a[2*n],t.opt_len+=s*(i+o),c&&(t.static_len+=s*(c[2*n+1]+o)));if(0!==f){do{for(i=l-1;0===t.bl_count[i];)i--;t.bl_count[i]--,t.bl_count[i+1]+=2,t.bl_count[l]--,f-=2}while(0p.max_code||(a[2*r+1]!=i&&(t.opt_len+=(i-a[2*r+1])*a[2*r],a[2*r+1]=i),n--)}}(t),function(t,e,n){var r,i,o,s=[],a=0;for(r=1;r<=d;r++)s[r]=a=a+n[r-1]<<1;for(i=0;i<=e;i++)0!==(o=t[2*i+1])&&(t[2*i]=c(s[o]++,o))}(i,p.max_code,t.bl_count)}}function ft(t,e,n,r,i){var o=this;o.static_tree=t,o.extra_bits=e,o.extra_base=n,o.elems=r,o.max_length=i}lt._length_code=[0,1,2,3,4,5,6,7,8,8,9,9,10,10,11,11,12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28],lt.base_length=[0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224,0],lt.base_dist=[0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576],lt.d_code=function(t){return t<256?e[t]:e[256+(t>>>7)]},lt.extra_lbits=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],lt.extra_dbits=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],lt.extra_blbits=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],lt.bl_order=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],ft.static_ltree=[12,8,140,8,76,8,204,8,44,8,172,8,108,8,236,8,28,8,156,8,92,8,220,8,60,8,188,8,124,8,252,8,2,8,130,8,66,8,194,8,34,8,162,8,98,8,226,8,18,8,146,8,82,8,210,8,50,8,178,8,114,8,242,8,10,8,138,8,74,8,202,8,42,8,170,8,106,8,234,8,26,8,154,8,90,8,218,8,58,8,186,8,122,8,250,8,6,8,134,8,70,8,198,8,38,8,166,8,102,8,230,8,22,8,150,8,86,8,214,8,54,8,182,8,118,8,246,8,14,8,142,8,78,8,206,8,46,8,174,8,110,8,238,8,30,8,158,8,94,8,222,8,62,8,190,8,126,8,254,8,1,8,129,8,65,8,193,8,33,8,161,8,97,8,225,8,17,8,145,8,81,8,209,8,49,8,177,8,113,8,241,8,9,8,137,8,73,8,201,8,41,8,169,8,105,8,233,8,25,8,153,8,89,8,217,8,57,8,185,8,121,8,249,8,5,8,133,8,69,8,197,8,37,8,165,8,101,8,229,8,21,8,149,8,85,8,213,8,53,8,181,8,117,8,245,8,13,8,141,8,77,8,205,8,45,8,173,8,109,8,237,8,29,8,157,8,93,8,221,8,61,8,189,8,125,8,253,8,19,9,275,9,147,9,403,9,83,9,339,9,211,9,467,9,51,9,307,9,179,9,435,9,115,9,371,9,243,9,499,9,11,9,267,9,139,9,395,9,75,9,331,9,203,9,459,9,43,9,299,9,171,9,427,9,107,9,363,9,235,9,491,9,27,9,283,9,155,9,411,9,91,9,347,9,219,9,475,9,59,9,315,9,187,9,443,9,123,9,379,9,251,9,507,9,7,9,263,9,135,9,391,9,71,9,327,9,199,9,455,9,39,9,295,9,167,9,423,9,103,9,359,9,231,9,487,9,23,9,279,9,151,9,407,9,87,9,343,9,215,9,471,9,55,9,311,9,183,9,439,9,119,9,375,9,247,9,503,9,15,9,271,9,143,9,399,9,79,9,335,9,207,9,463,9,47,9,303,9,175,9,431,9,111,9,367,9,239,9,495,9,31,9,287,9,159,9,415,9,95,9,351,9,223,9,479,9,63,9,319,9,191,9,447,9,127,9,383,9,255,9,511,9,0,7,64,7,32,7,96,7,16,7,80,7,48,7,112,7,8,7,72,7,40,7,104,7,24,7,88,7,56,7,120,7,4,7,68,7,36,7,100,7,20,7,84,7,52,7,116,7,3,8,131,8,67,8,195,8,35,8,163,8,99,8,227,8],ft.static_dtree=[0,5,16,5,8,5,24,5,4,5,20,5,12,5,28,5,2,5,18,5,10,5,26,5,6,5,22,5,14,5,30,5,1,5,17,5,9,5,25,5,5,5,21,5,13,5,29,5,3,5,19,5,11,5,27,5,7,5,23,5],ft.static_l_desc=new ft(ft.static_ltree,lt.extra_lbits,257,286,d),ft.static_d_desc=new ft(ft.static_dtree,lt.extra_dbits,0,30,d),ft.static_bl_desc=new ft(null,lt.extra_blbits,0,19,7);function n(t,e,n,r,i){var o=this;o.good_length=t,o.max_lazy=e,o.nice_length=n,o.max_chain=r,o.func=i}var pt=[new n(0,0,0,0,0),new n(4,4,8,4,1),new n(4,5,16,8,1),new n(4,6,32,32,1),new n(4,4,16,16,2),new n(8,16,32,32,2),new n(8,16,128,128,2),new n(8,32,128,256,2),new n(32,128,258,1024,2),new n(32,258,258,4096,2)],dt=["need dictionary","stream end","","","stream error","data error","","buffer error","",""],gt=262;function mt(t,e,n,r){var i=t[2*e],o=t[2*n];return i>>8&255)}function $(t,e){var n,r=e;16-r>>16-W,W+=r-16):(H|=t<>>=8,W-=8)}function rt(t,e){var n,r,i;if(G.pending_buf[N+2*M]=t>>>8&255,G.pending_buf[N+2*M+1]=255&t,G.pending_buf[U+M]=255&e,M++,0===t?a[2*e]++:(o++,t--,a[2*(lt._length_code[e]+256+1)]++,E[2*lt.d_code(t)]++),0==(8191&M)&&2>>=3,o>>3,(i=G.static_len+3+7>>>3)<=r&&(r=i)):r=i=e+5,e+4<=r&&-1!=t?st(t,e,n):i==r?($(2+(n?1:0),3),it(ft.static_ltree,ft.static_dtree)):($(4+(n?1:0),3),function(t,e,n){var r;for($(t-257,5),$(e-1,5),$(n-4,4),r=0;r>=2),Ps&&0!=--r);return o<=P?o:P}function ht(t){return t.total_in=t.total_out=0,t.msg=null,G.pending=0,G.pending_out=0,u=113,l=0,V.dyn_tree=a,V.stat_desc=ft.static_l_desc,Y.dyn_tree=E,Y.stat_desc=ft.static_d_desc,X.dyn_tree=R,X.stat_desc=ft.static_bl_desc,W=H=0,L=8,J(),function(){var t;for(i=2*f,t=y[v-1]=0;t>1)&&(i=3),r|=i<<6,0!==C&&(r|=32),u=113,Q((a=r+=31-r%31)>>8&255),Q(255&a)),0!==G.pending){if(c.flush_pending(),0===c.avail_out)return l=-1,0}else if(0===c.avail_in&&e<=o&&4!=e)return c.msg=dt[7],-5;if(666==u&&0!==c.avail_in)return t.msg=dt[7],-5;if(0!==c.avail_in||0!==P||0!=e&&666!=u){switch(s=-1,pt[T].func){case 0:s=function(t){var e,n=65535;for(h-5t.avail_out&&(e=t.avail_out),0!==e&&(t.next_out.set(t.dstate.pending_buf.subarray(t.dstate.pending_out,t.dstate.pending_out+e),t.next_out_index),t.next_out_index+=e,t.dstate.pending_out+=e,t.total_out+=e,t.avail_out-=e,t.dstate.pending-=e,0===t.dstate.pending&&(t.dstate.pending_out=0))}};var o=t.zip||t;o.Deflater=o._jzlib_Deflater=function(t){var a=new i,c=new Uint8Array(512),e=t?t.level:-1;void 0===e&&(e=-1),a.deflateInit(e),a.next_out=c,this.append=function(t,e){var n,r=[],i=0,o=0,s=0;if(t.length){a.next_in_index=0,a.next_in=t,a.avail_in=t.length;do{if(a.next_out_index=0,a.avail_out=512,0!=a.deflate(0))throw new Error("deflating: "+a.msg);a.next_out_index&&(512==a.next_out_index?r.push(new Uint8Array(c)):r.push(new Uint8Array(c.subarray(0,a.next_out_index)))),s+=a.next_out_index,e&&0 "+a.toRGB()+" -> "+a.toHex());s.appendChild(c),s.appendChild(u),o.appendChild(s)}catch(t){}return o}},function(t){var n="+".charCodeAt(0),r="/".charCodeAt(0),i="0".charCodeAt(0),o="a".charCodeAt(0),s="A".charCodeAt(0),a="-".charCodeAt(0),c="_".charCodeAt(0),h=function(t){var e=t.charCodeAt(0);return e===n||e===a?62:e===r||e===c?63:e>16),u((65280&i)>>8),u(255&i);return 2===o?u(255&(i=h(t.charAt(e))<<2|h(t.charAt(e+1))>>4)):1===o&&(u((i=h(t.charAt(e))<<10|h(t.charAt(e+1))<<4|h(t.charAt(e+2))>>2)>>8&255),u(255&i)),s}(n),e,r)},i.prototype.parse=function(){return this.directory=new e(this.contents),this.head=new p(this),this.name=new b(this),this.cmap=new y(this),this.toUnicode=new Map,this.hhea=new g(this),this.maxp=new x(this),this.hmtx=new S(this),this.post=new w(this),this.os2=new m(this),this.loca=new I(this),this.glyf=new k(this),this.ascender=this.os2.exists&&this.os2.ascender||this.hhea.ascender,this.decender=this.os2.exists&&this.os2.decender||this.hhea.decender,this.lineGap=this.os2.exists&&this.os2.lineGap||this.hhea.lineGap,this.bbox=[this.head.xMin,this.head.yMin,this.head.xMax,this.head.yMax]},i.prototype.registerTTF=function(){var i,t,e,n,r;if(this.scaleFactor=1e3/this.head.unitsPerEm,this.bbox=function(){var t,e,n,r;for(r=[],t=0,e=(n=this.bbox).length;t>16)&&(t=-(1+(65535^t))),this.italicAngle=+(t+"."+e)):this.italicAngle=0,this.ascender=Math.round(this.ascender*this.scaleFactor),this.decender=Math.round(this.decender*this.scaleFactor),this.lineGap=Math.round(this.lineGap*this.scaleFactor),this.capHeight=this.os2.exists&&this.os2.capHeight||this.ascender,this.xHeight=this.os2.exists&&this.os2.xHeight||0,this.familyClass=(this.os2.exists&&this.os2.familyClass||0)>>8,this.isSerif=1===(r=this.familyClass)||2===r||3===r||4===r||5===r||7===r,this.isScript=10===this.familyClass,this.flags=0,this.post.isFixedPitch&&(this.flags|=1),this.isSerif&&(this.flags|=2),this.isScript&&(this.flags|=8),0!==this.italicAngle&&(this.flags|=64),this.flags|=32,!this.cmap.unicode)throw new Error("No unicode cmap for font")},i.prototype.characterToGlyph=function(t){var e;return(null!=(e=this.cmap.unicode)?e.codeMap[t]:void 0)||0},i.prototype.widthOfGlyph=function(t){var e;return e=1e3/this.head.unitsPerEm,this.hmtx.forGlyph(t).advance*e},i.prototype.widthOfString=function(t,e,n){var r,i,o,s,a;for(i=s=o=0,a=(t=""+t).length;0<=a?s>>24&255),this.writeByte(t>>16&255),this.writeByte(t>>8&255),this.writeByte(255&t)},t.prototype.readInt32=function(){var t;return 2147483648<=(t=this.readUInt32())?t-4294967296:t},t.prototype.writeInt32=function(t){return t<0&&(t+=4294967296),this.writeUInt32(t)},t.prototype.readUInt16=function(){return this.readByte()<<8|this.readByte()},t.prototype.writeUInt16=function(t){return this.writeByte(t>>8&255),this.writeByte(255&t)},t.prototype.readInt16=function(){var t;return 32768<=(t=this.readUInt16())?t-65536:t},t.prototype.writeInt16=function(t){return t<0&&(t+=65536),this.writeUInt16(t)},t.prototype.readString=function(t){var e,n,r;for(n=[],e=r=0;0<=t?r>24&255),this.writeByte(e>>16&255),this.writeByte(e>>8&255),this.writeByte(255&e),this.writeByte(n>>24&255),this.writeByte(n>>16&255),this.writeByte(n>>8&255),this.writeByte(255&n)},t.prototype.readInt=function(){return this.readInt32()},t.prototype.writeInt=function(t){return this.writeInt32(t)},t.prototype.read=function(t){var e,n;for(e=[],n=0;0<=t?n>8,c[4*u+1]=(16711680&n[u])>>16,c[4*u]=(4278190080&n[u])>>24;return c},e}(),P=function(){function t(t){this.font=t,this.subset={},this.unicodes={},this.next=33}return t.prototype.generateCmap=function(){var t,e,n,r,i;for(e in r=this.font.cmap.tables[0].codeMap,t={},i=this.subset)n=i[e],t[e]=r[n];return t},t.prototype.glyphsFor=function(t){var e,n,r,i,o,s,a;for(r={},o=0,s=t.length;o>"),e.join("\n")},s}()}(rt), +/* + # PNG.js + # Copyright (c) 2011 Devon Govett + # MIT LICENSE + # + # + */ +yt="undefined"!=typeof self&&self||"undefined"!=typeof window&&window||"undefined"!=typeof global&&global||Function('return typeof this === "object" && this.content')()||Function("return this")(),wt=function(){var u,n,r;function i(t){var e,n,r,i,o,s,a,c,u,h,l,f,p,d;for(this.data=t,this.pos=8,this.palette=[],this.imgData=[],this.transparency={},this.animation=null,this.text={},s=null;;){switch(e=this.readUInt32(),u=function(){var t,e;for(e=[],t=0;t<4;++t)e.push(String.fromCharCode(this.data[this.pos++]));return e}.call(this).join("")){case"IHDR":this.width=this.readUInt32(),this.height=this.readUInt32(),this.bits=this.data[this.pos++],this.colorType=this.data[this.pos++],this.compressionMethod=this.data[this.pos++],this.filterMethod=this.data[this.pos++],this.interlaceMethod=this.data[this.pos++];break;case"acTL":this.animation={numFrames:this.readUInt32(),numPlays:this.readUInt32()||1/0,frames:[]};break;case"PLTE":this.palette=this.read(e);break;case"fcTL":s&&this.animation.frames.push(s),this.pos+=4,s={width:this.readUInt32(),height:this.readUInt32(),xOffset:this.readUInt32(),yOffset:this.readUInt32()},o=this.readUInt16(),i=this.readUInt16()||100,s.delay=1e3*o/i,s.disposeOp=this.data[this.pos++],s.blendOp=this.data[this.pos++],s.data=[];break;case"IDAT":case"fdAT":for("fdAT"===u&&(this.pos+=4,e-=4),t=(null!=s?s.data:void 0)||this.imgData,f=0;0<=e?fr)throw new Error("More transparent colors than palette size");if(0<(h=r-this.transparency.indexed.length))for(p=0;0<=h?pthis.data.length)throw new Error("Incomplete or corrupt PNG file")}}i.load=function(t,e,n){var r;return"function"==typeof e&&(n=e),(r=new XMLHttpRequest).open("GET",t,!0),r.responseType="arraybuffer",r.onload=function(){var t;return t=new i(new Uint8Array(r.response||r.mozResponseArrayBuffer)),"function"==typeof(null!=e?e.getContext:void 0)&&t.render(e),"function"==typeof n?n(t):void 0},r.send(null)},i.prototype.read=function(t){var e,n;for(n=[],e=0;0<=t?e + * Chris G Jones + * Shaon Barman + * Vivien Nicolas <21@vingtetun.org> + * Justin D'Arcangelo + * Yury Delendik + * + * + */ +var xt=function(){function t(){this.pos=0,this.bufferLength=0,this.eof=!1,this.buffer=null}return t.prototype={ensureBuffer:function(t){var e=this.buffer,n=e?e.byteLength:0;if(t>t,this.codeSize=n-=t,this.bytesPos=o,e},t.prototype.getCode=function(t){for(var e=t[0],n=t[1],r=this.codeSize,i=this.codeBuf,o=this.bytes,s=this.bytesPos;r>16,h=65535&c;return(0==r||r>u,this.codeSize=r-u,this.bytesPos=s,h},t.prototype.generateHuffmanTable=function(t){for(var e=t.length,n=0,r=0;rn&&(n=t[r]);for(var i=1<>=1;for(r=h;r>=1)){var n,r;if(1==e)n=T,r=O;else if(2==e){for(var i=this.getBits(5)+257,o=this.getBits(5)+1,s=this.getBits(4)+4,a=Array(F.length),c=0;c>16;0>16)&&(y=this.getBits(y));var w=(65535&m)+y;d<=g+h&&(d=(C=this.ensureBuffer(g+h)).length);for(var v=0;v> 18 & 0x3f; + h2 = bits >> 12 & 0x3f; + h3 = bits >> 6 & 0x3f; + h4 = bits & 0x3f; // use hexets to index into b64, and append result to encoded string + + tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); + } while (i < data.length); + + enc = tmp_arr.join(""); + var r = data.length % 3; + return (r ? enc.slice(0, r - 3) : enc) + "===".slice(r || 3); + }; + } + + if (typeof global.atob === "undefined") { + global.atob = function (data) { + // discuss at: http://phpjs.org/functions/base64_decode/ + // original by: Tyler Akins (http://rumkin.com) + // improved by: Thunder.m + // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // input by: Aman Gupta + // input by: Brett Zamir (http://brett-zamir.me) + // bugfixed by: Onno Marsman + // bugfixed by: Pellentesque Malesuada + // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA=='); + // returns 1: 'Kevin van Zonneveld' + var o1, + o2, + o3, + h1, + h2, + h3, + h4, + bits, + i = 0, + ac = 0, + dec = "", + tmp_arr = []; + + if (!data) { + return data; + } + + data += ""; + + do { + // unpack four hexets into three octets using index points in b64 + h1 = b64.indexOf(data.charAt(i++)); + h2 = b64.indexOf(data.charAt(i++)); + h3 = b64.indexOf(data.charAt(i++)); + h4 = b64.indexOf(data.charAt(i++)); + bits = h1 << 18 | h2 << 12 | h3 << 6 | h4; + o1 = bits >> 16 & 0xff; + o2 = bits >> 8 & 0xff; + o3 = bits & 0xff; + + if (h3 == 64) { + tmp_arr[ac++] = String.fromCharCode(o1); + } else if (h4 == 64) { + tmp_arr[ac++] = String.fromCharCode(o1, o2); + } else { + tmp_arr[ac++] = String.fromCharCode(o1, o2, o3); + } + } while (i < data.length); + + dec = tmp_arr.join(""); + return dec; + }; + } + + if (!Array.prototype.map) { + Array.prototype.map = function (fun + /*, thisArg */ + ) { + if (this === void 0 || this === null || typeof fun !== "function") throw new TypeError(); + var t = Object(this), + len = t.length >>> 0, + res = new Array(len); + var thisArg = arguments.length > 1 ? arguments[1] : void 0; + + for (var i = 0; i < len; i++) { + // NOTE: Absolute correctness would demand Object.defineProperty + // be used. But this method is fairly new, and failure is + // possible only if Object.prototype or Array.prototype + // has a property |i| (very unlikely), so use a less-correct + // but more portable alternative. + if (i in t) res[i] = fun.call(thisArg, t[i], i, t); + } + + return res; + }; + } + + if (!Array.isArray) { + Array.isArray = function (arg) { + return Object.prototype.toString.call(arg) === "[object Array]"; + }; + } + + if (!Array.prototype.forEach) { + Array.prototype.forEach = function (fun, thisArg) { + + if (this === void 0 || this === null || typeof fun !== "function") throw new TypeError(); + var t = Object(this), + len = t.length >>> 0; + + for (var i = 0; i < len; i++) { + if (i in t) fun.call(thisArg, t[i], i, t); + } + }; + } + + if (!Object.keys) { + Object.keys = function () { + + var hasOwnProperty = Object.prototype.hasOwnProperty, + hasDontEnumBug = !{ + toString: null + }.propertyIsEnumerable("toString"), + dontEnums = ["toString", "toLocaleString", "valueOf", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "constructor"], + dontEnumsLength = dontEnums.length; + return function (obj) { + if (typeof obj !== "object" && (typeof obj !== "function" || obj === null)) { + throw new TypeError(); + } + + var result = [], + prop, + i; + + for (prop in obj) { + if (hasOwnProperty.call(obj, prop)) { + result.push(prop); + } + } + + if (hasDontEnumBug) { + for (i = 0; i < dontEnumsLength; i++) { + if (hasOwnProperty.call(obj, dontEnums[i])) { + result.push(dontEnums[i]); + } + } + } + + return result; + }; + }(); + } + + if (typeof Object.assign != "function") { + Object.assign = function (target) { + + if (target == null) { + throw new TypeError("Cannot convert undefined or null to object"); + } + + target = Object(target); + + for (var index = 1; index < arguments.length; index++) { + var source = arguments[index]; + + if (source != null) { + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + } + + return target; + }; + } + + if (!String.prototype.trim) { + String.prototype.trim = function () { + return this.replace(/^\s+|\s+$/g, ""); + }; + } + + if (!String.prototype.trimLeft) { + String.prototype.trimLeft = function () { + return this.replace(/^\s+/g, ""); + }; + } + + if (!String.prototype.trimRight) { + String.prototype.trimRight = function () { + return this.replace(/\s+$/g, ""); + }; + } + })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function("return this")()); // `self` is undefined in Firefox for Android content script context + // while `this` is nsIContentFrameMessageManager + // with an attribute `content` that corresponds to the window + + (function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : factory(); + })(window, function () { + /** + * @this {Promise} + */ + + function finallyConstructor(callback) { + var constructor = this.constructor; + return this.then(function (value) { + return constructor.resolve(callback()).then(function () { + return value; + }); + }, function (reason) { + return constructor.resolve(callback()).then(function () { + return constructor.reject(reason); + }); + }); + } // Store setTimeout reference so promise-polyfill will be unaffected by + // other code modifying setTimeout (like sinon.useFakeTimers()) + + + var setTimeoutFunc = setTimeout; + + function noop() {} // Polyfill for Function.prototype.bind + + + function bind(fn, thisArg) { + return function () { + fn.apply(thisArg, arguments); + }; + } + /** + * @constructor + * @param {Function} fn + */ + + + function Promise(fn) { + if (!(this instanceof Promise)) throw new TypeError('Promises must be constructed via new'); + if (typeof fn !== 'function') throw new TypeError('not a function'); + /** @type {!number} */ + + this._state = 0; + /** @type {!boolean} */ + + this._handled = false; + /** @type {Promise|undefined} */ + + this._value = undefined; + /** @type {!Array} */ + + this._deferreds = []; + doResolve(fn, this); + } + + function handle(self, deferred) { + while (self._state === 3) { + self = self._value; + } + + if (self._state === 0) { + self._deferreds.push(deferred); + + return; + } + + self._handled = true; + + Promise._immediateFn(function () { + var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; + + if (cb === null) { + (self._state === 1 ? resolve : reject)(deferred.promise, self._value); + return; + } + + var ret; + + try { + ret = cb(self._value); + } catch (e) { + reject(deferred.promise, e); + return; + } + + resolve(deferred.promise, ret); + }); + } + + function resolve(self, newValue) { + try { + // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure + if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.'); + + if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) { + var then = newValue.then; + + if (newValue instanceof Promise) { + self._state = 3; + self._value = newValue; + finale(self); + return; + } else if (typeof then === 'function') { + doResolve(bind(then, newValue), self); + return; + } + } + + self._state = 1; + self._value = newValue; + finale(self); + } catch (e) { + reject(self, e); + } + } + + function reject(self, newValue) { + self._state = 2; + self._value = newValue; + finale(self); + } + + function finale(self) { + if (self._state === 2 && self._deferreds.length === 0) { + Promise._immediateFn(function () { + if (!self._handled) { + Promise._unhandledRejectionFn(self._value); + } + }); + } + + for (var i = 0, len = self._deferreds.length; i < len; i++) { + handle(self, self._deferreds[i]); + } + + self._deferreds = null; + } + /** + * @constructor + */ + + + function Handler(onFulfilled, onRejected, promise) { + this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; + this.onRejected = typeof onRejected === 'function' ? onRejected : null; + this.promise = promise; + } + /** + * Take a potentially misbehaving resolver function and make sure + * onFulfilled and onRejected are only called once. + * + * Makes no guarantees about asynchrony. + */ + + + function doResolve(fn, self) { + var done = false; + + try { + fn(function (value) { + if (done) return; + done = true; + resolve(self, value); + }, function (reason) { + if (done) return; + done = true; + reject(self, reason); + }); + } catch (ex) { + if (done) return; + done = true; + reject(self, ex); + } + } + + Promise.prototype['catch'] = function (onRejected) { + return this.then(null, onRejected); + }; + + Promise.prototype.then = function (onFulfilled, onRejected) { + // @ts-ignore + var prom = new this.constructor(noop); + handle(this, new Handler(onFulfilled, onRejected, prom)); + return prom; + }; + + Promise.prototype['finally'] = finallyConstructor; + + Promise.all = function (arr) { + return new Promise(function (resolve, reject) { + if (!arr || typeof arr.length === 'undefined') throw new TypeError('Promise.all accepts an array'); + var args = Array.prototype.slice.call(arr); + if (args.length === 0) return resolve([]); + var remaining = args.length; + + function res(i, val) { + try { + if (val && (typeof val === 'object' || typeof val === 'function')) { + var then = val.then; + + if (typeof then === 'function') { + then.call(val, function (val) { + res(i, val); + }, reject); + return; + } + } + + args[i] = val; + + if (--remaining === 0) { + resolve(args); + } + } catch (ex) { + reject(ex); + } + } + + for (var i = 0; i < args.length; i++) { + res(i, args[i]); + } + }); + }; + + Promise.resolve = function (value) { + if (value && typeof value === 'object' && value.constructor === Promise) { + return value; + } + + return new Promise(function (resolve) { + resolve(value); + }); + }; + + Promise.reject = function (value) { + return new Promise(function (resolve, reject) { + reject(value); + }); + }; + + Promise.race = function (values) { + return new Promise(function (resolve, reject) { + for (var i = 0, len = values.length; i < len; i++) { + values[i].then(resolve, reject); + } + }); + }; // Use polyfill for setImmediate for performance gains + + + Promise._immediateFn = typeof setImmediate === 'function' && function (fn) { + setImmediate(fn); + } || function (fn) { + setTimeoutFunc(fn, 0); + }; + + Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) { + if (typeof console !== 'undefined' && console) { + console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console + } + }; + /** @suppress {undefinedVars} */ + + + var globalNS = function () { + // the only reliable means to get the global object is + // `Function('return this')()` + // However, this causes CSP violations in Chrome apps. + if (typeof self !== 'undefined') { + return self; + } + + if (typeof window !== 'undefined') { + return window; + } + + if (typeof global !== 'undefined') { + return global; + } + + throw new Error('unable to locate global object'); + }(); + + if (!('Promise' in globalNS)) { + globalNS['Promise'] = Promise; + } else if (!globalNS.Promise.prototype['finally']) { + globalNS.Promise.prototype['finally'] = finallyConstructor; + } + }); + + function _typeof(obj) { + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + _typeof = function (obj) { + return typeof obj; + }; + } else { + _typeof = function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + + return _typeof(obj); + } + + /** @license + * jsPDF - PDF Document creation from JavaScript + * Version 2.0.0 Built on 2019-01-22T15:32:38.220Z + * CommitID 0110a2202b + * + * Copyright (c) 2015-2018 yWorks GmbH, http://www.yworks.com + * 2015-2018 Lukas Holländer , https://github.com/HackbrettXXX + * 2010-2016 James Hall , https://github.com/MrRio/jsPDF + * 2010 Aaron Spike, https://github.com/acspike + * 2012 Willow Systems Corporation, willow-systems.com + * 2012 Pablo Hess, https://github.com/pablohess + * 2012 Florian Jenett, https://github.com/fjenett + * 2013 Warren Weckesser, https://github.com/warrenweckesser + * 2013 Youssef Beddad, https://github.com/lifof + * 2013 Lee Driscoll, https://github.com/lsdriscoll + * 2013 Stefan Slonevskiy, https://github.com/stefslon + * 2013 Jeremy Morel, https://github.com/jmorel + * 2013 Christoph Hartmann, https://github.com/chris-rock + * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria + * 2014 James Makes, https://github.com/dollaruw + * 2014 Diego Casorran, https://github.com/diegocr + * 2014 Steven Spungin, https://github.com/Flamenco + * 2014 Kenneth Glassey, https://github.com/Gavvers + * + * Licensed under the MIT License + * + * Contributor(s): + * siefkenj, ahwolf, rickygu, Midnith, saintclair, eaparango, + * kim3er, mfo, alnorth, Flamenco + */ + + /** + * Creates new jsPDF document object instance. + * @name jsPDF + * @class + * @param orientation {string/Object} Orientation of the first page. Possible values are "portrait" or "landscape" (or shortcuts "p" (Default), "l")
+ * Can also be an options object. + * @param unit {string} Measurement unit to be used when coordinates are specified.
+ * Possible values are "pt" (points), "mm" (Default), "cm", "in" or "px". + * @param format {string/Array} The format of the first page. Can be
  • a0 - a10
  • b0 - b10
  • c0 - c10
  • c0 - c10
  • dl
  • letter
  • government-letter
  • legal
  • junior-legal
  • ledger
  • tabloid
  • credit-card

+ * Default is "a4". If you want to use your own format just pass instead of one of the above predefined formats the size as an number-array , e.g. [595.28, 841.89] + * @returns {jsPDF} jsPDF-instance + * @description + * If the first parameter (orientation) is an object, it will be interpreted as an object of named parameters + * ``` + * { + * orientation: 'p', + * unit: 'mm', + * format: 'a4', + * hotfixes: [] // an array of hotfix strings to enable + * } + * ``` + */ + var jsPDF = function (global) { + + var pdfVersion = "1.3", + pageFormats = { + // Size in pt of various paper formats + a0: [2383.94, 3370.39], + a1: [1683.78, 2383.94], + a2: [1190.55, 1683.78], + a3: [841.89, 1190.55], + a4: [595.28, 841.89], + a5: [419.53, 595.28], + a6: [297.64, 419.53], + a7: [209.76, 297.64], + a8: [147.4, 209.76], + a9: [104.88, 147.4], + a10: [73.7, 104.88], + b0: [2834.65, 4008.19], + b1: [2004.09, 2834.65], + b2: [1417.32, 2004.09], + b3: [1000.63, 1417.32], + b4: [708.66, 1000.63], + b5: [498.9, 708.66], + b6: [354.33, 498.9], + b7: [249.45, 354.33], + b8: [175.75, 249.45], + b9: [124.72, 175.75], + b10: [87.87, 124.72], + c0: [2599.37, 3676.54], + c1: [1836.85, 2599.37], + c2: [1298.27, 1836.85], + c3: [918.43, 1298.27], + c4: [649.13, 918.43], + c5: [459.21, 649.13], + c6: [323.15, 459.21], + c7: [229.61, 323.15], + c8: [161.57, 229.61], + c9: [113.39, 161.57], + c10: [79.37, 113.39], + dl: [311.81, 623.62], + letter: [612, 792], + "government-letter": [576, 756], + legal: [612, 1008], + "junior-legal": [576, 360], + ledger: [1224, 792], + tabloid: [792, 1224], + "credit-card": [153, 243] + }; + /** + * jsPDF's Internal PubSub Implementation. + * Backward compatible rewritten on 2014 by + * Diego Casorran, https://github.com/diegocr + * + * @class + * @name PubSub + * @ignore + */ + + function PubSub(context) { + var topics = {}; + + this.subscribe = function (topic, callback, once) { + if (typeof callback !== "function") { + return false; + } + + if (!topics.hasOwnProperty(topic)) { + topics[topic] = {}; + } + + var id = Math.random().toString(35); + topics[topic][id] = [callback, !!once]; + return id; + }; + + this.unsubscribe = function (token) { + for (var topic in topics) { + if (topics[topic][token]) { + delete topics[topic][token]; + return true; + } + } + + return false; + }; + + this.publish = function (topic) { + if (topics.hasOwnProperty(topic)) { + var args = Array.prototype.slice.call(arguments, 1), + idr = []; + + for (var id in topics[topic]) { + var sub = topics[topic][id]; + + try { + sub[0].apply(context, args); + } catch (ex) { + if (global.console) { + console.error("jsPDF PubSub Error", ex.message, ex); + } + } + + if (sub[1]) idr.push(id); + } + + if (idr.length) idr.forEach(this.unsubscribe); + } + }; + } + /** + * @constructor + * @private + */ + + + function jsPDF(orientation, unit, format, compressPdf) { + var options = {}; + + if (_typeof(orientation) === "object") { + options = orientation; + orientation = options.orientation; + unit = options.unit || unit; + format = options.format || format; + compressPdf = options.compress || options.compressPdf || compressPdf; + } // Default options + + + unit = unit || "mm"; + format = format || "a4"; + orientation = ("" + (orientation || "P")).toLowerCase(); + + var format_as_string = ("" + format).toLowerCase(), + compress = !!compressPdf && typeof Uint8Array === "function", + textColor = options.textColor || "0 g", + drawColor = options.drawColor || "0 G", + activeFontSize = options.fontSize || 16, + activeCharSpace = options.charSpace || 0, + R2L = options.R2L || false, + lineHeightProportion = options.lineHeight || 1.15, + lineWidth = options.lineWidth || 0.200025, + // 2mm + fileId = "00000000000000000000000000000000", + objectNumber = 2, + // 'n' Current object number + outToPages = !1, + // switches where out() prints. outToPages true = push to pages obj. outToPages false = doc builder content + offsets = [], + // List of offsets. Activated and reset by buildDocument(). Pupulated by various calls buildDocument makes. + fonts = {}, + // collection of font objects, where key is fontKey - a dynamically created label for a given font. + fontmap = {}, + // mapping structure fontName > fontStyle > font key - performance layer. See addFont() + activeFontKey, + // will be string representing the KEY of the font as combination of fontName + fontStyle + fontStateStack = [], + // + patterns = {}, + // collection of pattern objects + patternMap = {}, + // see fonts + gStates = {}, + // collection of graphic state objects + gStatesMap = {}, + // see fonts + activeGState = null, + k, + // Scale factor + tmp, + page = 0, + currentPage, + pages = [], + pagesContext = [], + // same index as pages and pagedim + pagedim = [], + content = [], + additionalObjects = [], + lineCapID = 0, + lineJoinID = 0, + content_length = 0, + renderTargets = {}, + renderTargetMap = {}, + renderTargetStack = [], + pageX, + pageY, + pageMatrix, + // only used for FormObjects + pageWidth, + pageHeight, + pageMode, + zoomMode, + layoutMode, + creationDate, + documentProperties = { + title: "", + subject: "", + author: "", + keywords: "", + creator: "" + }, + API = {}, + ApiMode = { + COMPAT: "compat", + ADVANCED: "advanced" + }, + apiMode = ApiMode.COMPAT, + events = new PubSub(API), + hotfixes = options.hotfixes || [], + ///////////////////// + // Private functions + ///////////////////// + generateColorString = function generateColorString(options) { + var color; + var ch1 = options.ch1; + var ch2 = options.ch2; + var ch3 = options.ch3; + var ch4 = options.ch4; + var precision = options.precision; + var letterArray = options.pdfColorType === "draw" ? ["G", "RG", "K"] : ["g", "rg", "k"]; + + if (typeof ch1 === "string" && ch1.charAt(0) !== "#") { + var rgbColor = new RGBColor(ch1); + + if (rgbColor.ok) { + ch1 = rgbColor.toHex(); + } + } //convert short rgb to long form + + + if (typeof ch1 === "string" && /^#[0-9A-Fa-f]{3}$/.test(ch1)) { + ch1 = "#" + ch1[1] + ch1[1] + ch1[2] + ch1[2] + ch1[3] + ch1[3]; + } + + if (typeof ch1 === "string" && /^#[0-9A-Fa-f]{6}$/.test(ch1)) { + var hex = parseInt(ch1.substr(1), 16); + ch1 = hex >> 16 & 255; + ch2 = hex >> 8 & 255; + ch3 = hex & 255; + } + + if (typeof ch2 === "undefined" || typeof ch4 === "undefined" && ch1 === ch2 && ch2 === ch3) { + // Gray color space. + if (typeof ch1 === "string") { + color = ch1 + " " + letterArray[0]; + } else { + switch (options.precision) { + case 2: + color = f2(ch1 / 255) + " " + letterArray[0]; + break; + + case 3: + default: + color = f3(ch1 / 255) + " " + letterArray[0]; + } + } + } else if (typeof ch4 === "undefined" || _typeof(ch4) === "object") { + // assume RGB + if (typeof ch1 === "string") { + color = [ch1, ch2, ch3, letterArray[1]].join(" "); + } else { + switch (options.precision) { + case 2: + color = [f2(ch1 / 255), f2(ch2 / 255), f2(ch3 / 255), letterArray[1]].join(" "); + break; + + default: + case 3: + color = [f3(ch1 / 255), f3(ch2 / 255), f3(ch3 / 255), letterArray[1]].join(" "); + } + } // assume RGBA + + + if (ch4 && ch4.a === 0) { + //TODO Implement transparency. + //WORKAROUND use white for now + color = ["255", "255", "255", letterArray[1]].join(" "); + } + } else { + // assume CMYK + if (typeof ch1 === "string") { + color = [ch1, ch2, ch3, ch4, letterArray[2]].join(" "); + } else { + switch (options.precision) { + case 2: + color = [f2(ch1), f2(ch2), f2(ch3), f2(ch4), letterArray[2]].join(" "); + break; + + case 3: + default: + color = [f3(ch1), f3(ch2), f3(ch3), f3(ch4), letterArray[2]].join(" "); + } + } + } + + return color; + }, + convertDateToPDFDate = function convertDateToPDFDate(parmDate) { + var padd2 = function padd2(number) { + return ("0" + parseInt(number)).slice(-2); + }; + + var result = ""; + var tzoffset = parmDate.getTimezoneOffset(), + tzsign = tzoffset < 0 ? "+" : "-", + tzhour = Math.floor(Math.abs(tzoffset / 60)), + tzmin = Math.abs(tzoffset % 60), + timeZoneString = [tzsign, padd2(tzhour), "'", padd2(tzmin), "'"].join(""); + result = ["D:", parmDate.getFullYear(), padd2(parmDate.getMonth() + 1), padd2(parmDate.getDate()), padd2(parmDate.getHours()), padd2(parmDate.getMinutes()), padd2(parmDate.getSeconds()), timeZoneString].join(""); + return result; + }, + convertPDFDateToDate = function convertPDFDateToDate(parmPDFDate) { + var year = parseInt(parmPDFDate.substr(2, 4), 10); + var month = parseInt(parmPDFDate.substr(6, 2), 10) - 1; + var date = parseInt(parmPDFDate.substr(8, 2), 10); + var hour = parseInt(parmPDFDate.substr(10, 2), 10); + var minutes = parseInt(parmPDFDate.substr(12, 2), 10); + var seconds = parseInt(parmPDFDate.substr(14, 2), 10); + var timeZoneHour = parseInt(parmPDFDate.substr(16, 2), 10); + var timeZoneMinutes = parseInt(parmPDFDate.substr(20, 2), 10); + var resultingDate = new Date(year, month, date, hour, minutes, seconds, 0); + return resultingDate; + }, + setCreationDate = function setCreationDate(date) { + var tmpCreationDateString; + var regexPDFCreationDate = /^D:(20[0-2][0-9]|203[0-7]|19[7-9][0-9])(0[0-9]|1[0-2])([0-2][0-9]|3[0-1])(0[0-9]|1[0-9]|2[0-3])(0[0-9]|[1-5][0-9])(0[0-9]|[1-5][0-9])(\+0[0-9]|\+1[0-4]|\-0[0-9]|\-1[0-1])\'(0[0-9]|[1-5][0-9])\'?$/; + + if (_typeof(date) === undefined) { + date = new Date(); + } + + if (_typeof(date) === "object" && Object.prototype.toString.call(date) === "[object Date]") { + tmpCreationDateString = convertDateToPDFDate(date); + } else if (regexPDFCreationDate.test(date)) { + tmpCreationDateString = date; + } else { + tmpCreationDateString = convertDateToPDFDate(new Date()); + } + + creationDate = tmpCreationDateString; + return creationDate; + }, + getCreationDate = function getCreationDate(type) { + var result = creationDate; + + if (type === "jsDate") { + result = convertPDFDateToDate(creationDate); + } + + return result; + }, + setFileId = function setFileId(value) { + value = value || "12345678901234567890123456789012".split("").map(function () { + return "ABCDEF0123456789".charAt(Math.floor(Math.random() * 16)); + }).join(""); + fileId = value; + return fileId; + }, + getFileId = function getFileId() { + return fileId; + }, + f2 = function f2(number) { + return number.toFixed(2); // Ie, %.2f + }, + f3 = function f3(number) { + return number.toFixed(3); // Ie, %.3f + }, + // high precision float + hpf = function hpf(number) { + return number.toFixed(16).replace(/0+$/, ""); + }, + scaleByK = function scaleByK(coordinate) { + if (apiMode === ApiMode.COMPAT) { + return coordinate * k; + } else if (apiMode === ApiMode.ADVANCED) { + return coordinate; + } + }, + transformY = function transformY(y) { + if (apiMode === ApiMode.COMPAT) { + return pageHeight - y; + } else if (apiMode === ApiMode.ADVANCED) { + return y; + } + }, + transformScaleY = function transformScaleY(y) { + return scaleByK(transformY(y)); + }, + padd2Hex = function padd2Hex(hexString) { + var s = "00" + hexString; + return s.substr(s.length - 2); + }, + advancedApiModeTrap = function advancedApiModeTrap(methodName) { + if (apiMode !== ApiMode.ADVANCED) { + throw new Error(methodName + " is only available in 'advanced' API mode. " + "You need to call advancedAPI() first."); + } + }, + out = function out(string) { + string = typeof string === "string" ? string : string.toString(); + + if (outToPages) { + /* set by beginPage */ + pages[currentPage].push(string); + } else { + // +1 for '\n' that will be used to join 'content' + content_length += string.length + 1; + content.push(string); + } + }, + newObject = function newObject() { + // Begin a new object + objectNumber++; + offsets[objectNumber] = content_length; + out(objectNumber + " 0 obj"); + return objectNumber; + }, + // Does not output the object until after the pages have been output. + // Returns an object containing the objectId and content. + // All pages have been added so the object ID can be estimated to start right after. + // This does not modify the current objectNumber; It must be updated after the newObjects are output. + newAdditionalObject = function newAdditionalObject() { + var objId = pages.length * 2 + 1; + objId += additionalObjects.length; + var obj = { + objId: objId, + content: "" + }; + additionalObjects.push(obj); + return obj; + }, + // Does not output the object. The caller must call newObjectDeferredBegin(oid) before outputing any data + newObjectDeferred = function newObjectDeferred() { + objectNumber++; + + offsets[objectNumber] = function () { + return content_length; + }; + + return objectNumber; + }, + newObjectDeferredBegin = function newObjectDeferredBegin(oid) { + offsets[oid] = content_length; + }, + putStream = function putStream(str) { + out("stream"); + out(str); + out("endstream"); + }, + appendBuffer = function appendBuffer(buffer1, buffer2) { + var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength); + tmp.set(new Uint8Array(buffer1), 0); + tmp.set(new Uint8Array(buffer2), buffer1.byteLength); + return tmp; + }, + putPages = function putPages() { + var n, + p, + arr, + i, + deflater, + adler32, + adler32cs, + wPt, + hPt, + pageObjectNumbers = []; + adler32cs = global.adler32cs || jsPDF.API.adler32cs; + + if (compress && typeof adler32cs === "undefined") { + compress = false; + } // outToPages = false as set in endDocument(). out() writes to content. + + + for (n = 1; n <= page; n++) { + pageObjectNumbers.push(newObject()); + wPt = (pageWidth = pagedim[n].width) * k; + hPt = (pageHeight = pagedim[n].height) * k; + out("<>"); + out("endobj"); // Page content + + p = pages[n].join("\n"); + + if (apiMode === ApiMode.ADVANCED) { + // if the user forgot to switch back to COMPAT mode, we must balance the graphics stack again + p += "\nQ"; + } + + newObject(); + + if (compress) { + arr = []; + i = p.length; + + while (i--) { + arr[i] = p.charCodeAt(i); + } + + adler32 = adler32cs.from(p); + deflater = new Deflater(6); + p = deflater.append(new Uint8Array(arr)); + p = appendBuffer(p, deflater.flush()); + arr = new Uint8Array(p.byteLength + 6); + arr.set(new Uint8Array([120, 156])); + arr.set(p, 2); + arr.set(new Uint8Array([adler32 & 0xff, adler32 >> 8 & 0xff, adler32 >> 16 & 0xff, adler32 >> 24 & 0xff]), p.byteLength + 2); + var strings = [], + chunkSize = 0xffff; // There is a maximum stack size. We cannot call String.fromCharCode with as many arguments as we want + + for (var j = 0; j * chunkSize < arr.length; j++) { + strings.push(String.fromCharCode.apply(null, arr.subarray(j * chunkSize, (j + 1) * chunkSize))); + } + + p = strings.join(''); + out("<>"); + } else { + out("<>"); + } + + putStream(p); + out("endobj"); + } + + offsets[1] = content_length; + out("1 0 obj"); + out("<>"); + out("endobj"); + events.publish("postPutPages"); + }, + putFont = function putFont(font) { + events.publish("putFont", { + font: font, + out: out, + newObject: newObject, + putStream: putStream + }); + + if (font.isAlreadyPutted !== true) { + font.objectNumber = newObject(); + out("<<"); + out("/Type /Font"); + out("/BaseFont /" + font.postScriptName); + out("/Subtype /Type1"); + + if (typeof font.encoding === "string") { + out("/Encoding /" + font.encoding); + } + + out("/FirstChar 32"); + out("/LastChar 255"); + out(">>"); + out("endobj"); + } + }, + putFonts = function putFonts() { + for (var fontKey in fonts) { + if (fonts.hasOwnProperty(fontKey)) { + putFont(fonts[fontKey]); + } + } + }, + putXObject = function putXObject(xObject) { + xObject.objectNumber = newObject(); + out("<<"); + out("/Type /XObject"); + out("/Subtype /Form"); + out("/BBox [" + [hpf(xObject.x), hpf(xObject.y), hpf(xObject.x + xObject.width), hpf(xObject.y + xObject.height)].join(" ") + "]"); + out("/Matrix [" + xObject.matrix.toString() + "]"); // TODO: /Resources + + var p = xObject.pages[1].join("\n"); + out("/Length " + p.length); + out(">>"); + putStream(p); + out("endobj"); + }, + putXObjects = function putXObjects() { + for (var xObjectKey in renderTargets) { + if (renderTargets.hasOwnProperty(xObjectKey)) { + putXObject(renderTargets[xObjectKey]); + } + } + }, + interpolateAndEncodeRGBStream = function interpolateAndEncodeRGBStream(colors, numberSamples) { + var tValues = []; + var t; + var dT = 1.0 / (numberSamples - 1); + + for (t = 0.0; t < 1.0; t += dT) { + tValues.push(t); + } + + tValues.push(1.0); // add first and last control point if not present + + if (colors[0].offset != 0.0) { + var c0 = { + offset: 0.0, + color: colors[0].color + }; + colors.unshift(c0); + } + + if (colors[colors.length - 1].offset != 1.0) { + var c1 = { + offset: 1.0, + color: colors[colors.length - 1].color + }; + colors.push(c1); + } + + var out = ""; + var index = 0; + + for (var i = 0; i < tValues.length; i++) { + t = tValues[i]; + + while (t > colors[index + 1].offset) { + index++; + } + + var a = colors[index].offset; + var b = colors[index + 1].offset; + var d = (t - a) / (b - a); + var aColor = colors[index].color; + var bColor = colors[index + 1].color; + out += padd2Hex(Math.round((1 - d) * aColor[0] + d * bColor[0]).toString(16)) + padd2Hex(Math.round((1 - d) * aColor[1] + d * bColor[1]).toString(16)) + padd2Hex(Math.round((1 - d) * aColor[2] + d * bColor[2]).toString(16)); + } + + return out.trim(); + }, + putShadingPattern = function putShadingPattern(pattern, numberSamples) { + /* + Axial patterns shade between the two points specified in coords, radial patterns between the inner + and outer circle. + The user can specify an array (colors) that maps t-Values in [0, 1] to RGB colors. These are now + interpolated to equidistant samples and written to pdf as a sample (type 0) function. + */ + // The number of color samples that should be used to describe the shading. + // The higher, the more accurate the gradient will be. + numberSamples || (numberSamples = 21); + var funcObjectNumber = newObject(); + var stream = interpolateAndEncodeRGBStream(pattern.colors, numberSamples); + out("<< /FunctionType 0"); + out("/Domain [0.0 1.0]"); + out("/Size [" + numberSamples + "]"); + out("/BitsPerSample 8"); + out("/Range [0.0 1.0 0.0 1.0 0.0 1.0]"); + out("/Decode [0.0 1.0 0.0 1.0 0.0 1.0]"); + out("/Length " + stream.length); // The stream is Hex encoded + + out("/Filter /ASCIIHexDecode"); + out(">>"); + putStream(stream); + out("endobj"); + pattern.objectNumber = newObject(); + out("<< /ShadingType " + pattern.type); + out("/ColorSpace /DeviceRGB"); + var coords = "/Coords [" + hpf(parseFloat(pattern.coords[0])) + " " + // x1 + hpf(parseFloat(pattern.coords[1])) + " "; // y1 + + if (pattern.type === 2) { + // axial + coords += hpf(parseFloat(pattern.coords[2])) + " " + // x2 + hpf(parseFloat(pattern.coords[3])); // y2 + } else { + // radial + coords += hpf(parseFloat(pattern.coords[2])) + " " + // r1 + hpf(parseFloat(pattern.coords[3])) + " " + // x2 + hpf(parseFloat(pattern.coords[4])) + " " + // y2 + hpf(parseFloat(pattern.coords[5])); // r2 + } + + coords += "]"; + out(coords); + + if (pattern.matrix) { + out("/Matrix [" + pattern.matrix.toString() + "]"); + } + + out("/Function " + funcObjectNumber + " 0 R"); + out("/Extend [true true]"); + out(">>"); + out("endobj"); + }, + putTilingPattern = function putTilingPattern(pattern) { + var resourcesObjectNumber = newObject(); + out("<<"); + putResourceDictionary(); + out(">>"); + out("endobj"); + pattern.objectNumber = newObject(); + out("<< /Type /Pattern"); + out("/PatternType 1"); // tiling pattern + + out("/PaintType 1"); // colored tiling pattern + + out("/TilingType 1"); // constant spacing + + out("/BBox [" + pattern.boundingBox.map(hpf).join(" ") + "]"); + out("/XStep " + hpf(pattern.xStep)); + out("/YStep " + hpf(pattern.yStep)); + out("/Length " + pattern.stream.length); + out("/Resources " + resourcesObjectNumber + " 0 R"); // TODO: resources + + pattern.matrix && out("/Matrix [" + pattern.matrix.toString() + "]"); + out(">>"); + putStream(pattern.stream); + out("endobj"); + }, + putPatterns = function putPatterns() { + var patternKey; + + for (patternKey in patterns) { + if (patterns.hasOwnProperty(patternKey)) { + if (patterns[patternKey] instanceof API.ShadingPattern) { + putShadingPattern(patterns[patternKey]); + } else if (patterns[patternKey] instanceof API.TilingPattern) { + putTilingPattern(patterns[patternKey]); + } + } + } + }, + putGState = function putGState(gState) { + gState.objectNumber = newObject(); + out("<<"); + + for (var p in gState) { + switch (p) { + case "opacity": + out("/ca " + f2(gState[p])); + break; + + case "stroke-opacity": + out("/CA " + f2(gState[p])); + break; + } + } + + out(">>"); + out("endobj"); + }, + putGStates = function putGStates() { + var gStateKey; + + for (gStateKey in gStates) { + if (gStates.hasOwnProperty(gStateKey)) { + putGState(gStates[gStateKey]); + } + } + }, + putXobjectDict = function putXobjectDict() { + for (var xObjectKey in renderTargets) { + if (renderTargets.hasOwnProperty(xObjectKey) && renderTargets[xObjectKey].objectNumber >= 0) { + out("/" + xObjectKey + " " + renderTargets[xObjectKey].objectNumber + " 0 R"); + } + } + + events.publish("putXobjectDict"); + }, + putShadingPatternDict = function putShadingPatternDict() { + for (var patternKey in patterns) { + if (patterns.hasOwnProperty(patternKey) && patterns[patternKey] instanceof API.ShadingPattern && patterns[patternKey].objectNumber >= 0) { + out("/" + patternKey + " " + patterns[patternKey].objectNumber + " 0 R"); + } + } + + events.publish("putShadingPatternDict"); + }, + putTilingPatternDict = function putTilingPatternDict() { + for (var patternKey in patterns) { + if (patterns.hasOwnProperty(patternKey) && patterns[patternKey] instanceof API.TilingPattern && patterns[patternKey].objectNumber >= 0) { + out("/" + patternKey + " " + patterns[patternKey].objectNumber + " 0 R"); + } + } + + events.publish("putTilingPatternDict"); + }, + putGStatesDict = function putGStatesDict() { + var gStateKey; + + for (gStateKey in gStates) { + if (gStates.hasOwnProperty(gStateKey) && gStates[gStateKey].objectNumber >= 0) { + out("/" + gStateKey + " " + gStates[gStateKey].objectNumber + " 0 R"); + } + } + + events.publish("putGStateDict"); + }, + putResourceDictionary = function putResourceDictionary() { + out("/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]"); + out("/Font <<"); // Do this for each font, the '1' bit is the index of the font + + for (var fontKey in fonts) { + if (fonts.hasOwnProperty(fontKey)) { + out("/" + fontKey + " " + fonts[fontKey].objectNumber + " 0 R"); + } + } + + out(">>"); + out("/Shading <<"); + putShadingPatternDict(); + out(">>"); + out("/Pattern <<"); + putTilingPatternDict(); + out(">>"); + out("/ExtGState <<"); + putGStatesDict(); + out(">>"); + out("/XObject <<"); + putXobjectDict(); + out(">>"); + }, + putResources = function putResources() { + putFonts(); + putGStates(); + putXObjects(); + putPatterns(); + events.publish("putResources"); // Resource dictionary + + offsets[2] = content_length; + out("2 0 obj"); + out("<<"); + putResourceDictionary(); + out(">>"); + out("endobj"); + events.publish("postPutResources"); + }, + putAdditionalObjects = function putAdditionalObjects() { + events.publish("putAdditionalObjects"); + + for (var i = 0; i < additionalObjects.length; i++) { + var obj = additionalObjects[i]; + offsets[obj.objId] = content_length; + out(obj.objId + " 0 obj"); + out(obj.content); + out("endobj"); + } + + objectNumber += additionalObjects.length; + events.publish("postPutAdditionalObjects"); + }, + addToFontDictionary = function addToFontDictionary(fontKey, fontName, fontStyle) { + // this is mapping structure for quick font key lookup. + // returns the KEY of the font (ex: "F1") for a given + // pair of font name and type (ex: "Arial". "Italic") + if (!fontmap.hasOwnProperty(fontName)) { + fontmap[fontName] = {}; + } + + fontmap[fontName][fontStyle] = fontKey; + }, + addFont = function addFont(postScriptName, fontName, fontStyle, encoding, isStandardFont) { + isStandardFont = isStandardFont || false; + var fontKey = "F" + (Object.keys(fonts).length + 1).toString(10), + // This is FontObject + font = { + id: fontKey, + postScriptName: postScriptName, + fontName: fontName, + fontStyle: fontStyle, + encoding: encoding, + isStandardFont: isStandardFont, + metadata: {} + }; + var instance = this; + events.publish("addFont", { + font: font, + instance: instance + }); + + if (fontKey !== undefined) { + fonts[fontKey] = font; + addToFontDictionary(fontKey, fontName, fontStyle); + } + + return fontKey; + }, + addFonts = function addFonts() { + var HELVETICA = "helvetica", + TIMES = "times", + COURIER = "courier", + NORMAL = "normal", + BOLD = "bold", + ITALIC = "italic", + BOLD_ITALIC = "bolditalic", + ZAPF = "zapfdingbats", + SYMBOL = "symbol", + standardFonts = [["Helvetica", HELVETICA, NORMAL, "WinAnsiEncoding"], ["Helvetica-Bold", HELVETICA, BOLD, "WinAnsiEncoding"], ["Helvetica-Oblique", HELVETICA, ITALIC, "WinAnsiEncoding"], ["Helvetica-BoldOblique", HELVETICA, BOLD_ITALIC, "WinAnsiEncoding"], ["Courier", COURIER, NORMAL, "WinAnsiEncoding"], ["Courier-Bold", COURIER, BOLD, "WinAnsiEncoding"], ["Courier-Oblique", COURIER, ITALIC, "WinAnsiEncoding"], ["Courier-BoldOblique", COURIER, BOLD_ITALIC, "WinAnsiEncoding"], ["Times-Roman", TIMES, NORMAL, "WinAnsiEncoding"], ["Times-Bold", TIMES, BOLD, "WinAnsiEncoding"], ["Times-Italic", TIMES, ITALIC, "WinAnsiEncoding"], ["Times-BoldItalic", TIMES, BOLD_ITALIC, "WinAnsiEncoding"], ["ZapfDingbats", ZAPF, NORMAL, null], ["Symbol", SYMBOL, NORMAL, null]]; + + for (var i = 0, l = standardFonts.length; i < l; i++) { + var fontKey = addFont(standardFonts[i][0], standardFonts[i][1], standardFonts[i][2], standardFonts[i][3], true); // adding aliases for standard fonts, this time matching the capitalization + + var parts = standardFonts[i][0].split("-"); + addToFontDictionary(fontKey, parts[0], parts[1] || ""); + } + + events.publish("addFonts", { + fonts: fonts, + dictionary: fontmap + }); + }, + matrixMult = function matrixMult(m1, m2) { + return new Matrix(m1.a * m2.a + m1.b * m2.c, m1.a * m2.b + m1.b * m2.d, m1.c * m2.a + m1.d * m2.c, m1.c * m2.b + m1.d * m2.d, m1.e * m2.a + m1.f * m2.c + m2.e, m1.e * m2.b + m1.f * m2.d + m2.f); + }, + Matrix = function Matrix(a, b, c, d, e, f) { + this.a = a; + this.b = b; + this.c = c; + this.d = d; + this.e = e; + this.f = f; + }; + + Matrix.prototype = { + toString: function toString() { + return [hpf(this.a), hpf(this.b), hpf(this.c), hpf(this.d), hpf(this.e), hpf(this.f)].join(" "); + }, + inversed: function inversed() { + var a = this.a, + b = this.b, + c = this.c, + d = this.d, + e = this.e, + f = this.f; + var quot = 1 / (a * d - b * c); + var aInv = d * quot; + var bInv = -b * quot; + var cInv = -c * quot; + var dInv = a * quot; + var eInv = -aInv * e - cInv * f; + var fInv = -bInv * e - dInv * f; + return new Matrix(aInv, bInv, cInv, dInv, eInv, fInv); + } + }; + + var unitMatrix = new Matrix(1, 0, 0, 1, 0, 0), + // Used (1) to save the current stream state to the XObjects stack and (2) to save completed form + // objects in the xObjects map. + RenderTarget = function RenderTarget() { + this.page = page; + this.currentPage = currentPage; + this.pages = pages.slice(0); + this.pagedim = pagedim.slice(0); + this.pagesContext = pagesContext.slice(0); + this.x = pageX; + this.y = pageY; + this.matrix = pageMatrix; + this.width = pageWidth; + this.height = pageHeight; + this.id = ""; // set by endFormObject() + + this.objectNumber = -1; // will be set by putXObject() + }; + + RenderTarget.prototype = { + restore: function restore() { + page = this.page; + currentPage = this.currentPage; + pagesContext = this.pagesContext; + pagedim = this.pagedim; + pages = this.pages; + pageX = this.x; + pageY = this.y; + pageMatrix = this.matrix; + pageWidth = this.width; + pageHeight = this.height; + } + }; + + var beginNewRenderTarget = function beginNewRenderTarget(x, y, width, height, matrix) { + // save current state + renderTargetStack.push(new RenderTarget()); // clear pages + + page = currentPage = 0; + pages = []; + pageX = x; + pageY = y; + pageMatrix = matrix; + beginPage(width, height); + }, + endFormObject = function endFormObject(key) { + // only add it if it is not already present (the keys provided by the user must be unique!) + if (renderTargetMap[key]) return; // save the created xObject + + var newXObject = new RenderTarget(); + var xObjectId = "Xo" + (Object.keys(renderTargets).length + 1).toString(10); + newXObject.id = xObjectId; + renderTargetMap[key] = xObjectId; + renderTargets[xObjectId] = newXObject; + events.publish("addFormObject", newXObject); // restore state from stack + + renderTargetStack.pop().restore(); + }, + + /** + * Adds a new pattern for later use. + * @param {String} key The key by it can be referenced later. The keys must be unique! + * @param {API.Pattern} pattern The pattern + */ + addPattern = function addPattern(key, pattern) { + // only add it if it is not already present (the keys provided by the user must be unique!) + if (patternMap[key]) return; + var prefix = pattern instanceof API.ShadingPattern ? "Sh" : "P"; + var patternKey = prefix + (Object.keys(patterns).length + 1).toString(10); + pattern.id = patternKey; + patternMap[key] = patternKey; + patterns[patternKey] = pattern; + events.publish("addPattern", pattern); + }, + + /** + * Adds a new Graphics State. Duplicates are automatically eliminated. + * @param {String} key Might also be null, if no later reference to this gState is needed + * @param {Object} gState The gState object + */ + addGState = function addGState(key, gState) { + // only add it if it is not already present (the keys provided by the user must be unique!) + if (key && gStatesMap[key]) return; + var duplicate = false; + + for (var s in gStates) { + if (gStates.hasOwnProperty(s)) { + if (gStates[s].equals(gState)) { + duplicate = true; + break; + } + } + } + + if (duplicate) { + gState = gStates[s]; + } else { + var gStateKey = "GS" + (Object.keys(gStates).length + 1).toString(10); + gStates[gStateKey] = gState; + gState.id = gStateKey; + } // several user keys may point to the same GState object + + + key && (gStatesMap[key] = gState.id); + events.publish("addGState", gState); + return gState; + }, + SAFE = function __safeCall(fn) { + fn.foo = function __safeCallWrapper() { + try { + return fn.apply(this, arguments); + } catch (e) { + var stack = e.stack || ""; + if (~stack.indexOf(" at ")) stack = stack.split(" at ")[1]; + var m = "Error in function " + stack.split("\n")[0].split("<")[0] + ": " + e.message; + + if (global.console) { + global.console.error(m, e); + if (global.alert) alert(m); + } else { + throw new Error(m); + } + } + }; + + fn.foo.bar = fn; + return fn.foo; + }, + to8bitStream = function to8bitStream(text, flags) { + /** + * PDF 1.3 spec: + * "For text strings encoded in Unicode, the first two bytes must be 254 followed by + * 255, representing the Unicode byte order marker, U+FEFF. (This sequence conflicts + * with the PDFDocEncoding character sequence thorn ydieresis, which is unlikely + * to be a meaningful beginning of a word or phrase.) The remainder of the + * string consists of Unicode character codes, according to the UTF-16 encoding + * specified in the Unicode standard, version 2.0. Commonly used Unicode values + * are represented as 2 bytes per character, with the high-order byte appearing first + * in the string." + * + * In other words, if there are chars in a string with char code above 255, we + * recode the string to UCS2 BE - string doubles in length and BOM is prepended. + * + * HOWEVER! + * Actual *content* (body) text (as opposed to strings used in document properties etc) + * does NOT expect BOM. There, it is treated as a literal GID (Glyph ID) + * + * Because of Adobe's focus on "you subset your fonts!" you are not supposed to have + * a font that maps directly Unicode (UCS2 / UTF16BE) code to font GID, but you could + * fudge it with "Identity-H" encoding and custom CIDtoGID map that mimics Unicode + * code page. There, however, all characters in the stream are treated as GIDs, + * including BOM, which is the reason we need to skip BOM in content text (i.e. that + * that is tied to a font). + * + * To signal this "special" PDFEscape / to8bitStream handling mode, + * API.text() function sets (unless you overwrite it with manual values + * given to API.text(.., flags) ) + * flags.autoencode = true + * flags.noBOM = true + * + * =================================================================================== + * `flags` properties relied upon: + * .sourceEncoding = string with encoding label. + * "Unicode" by default. = encoding of the incoming text. + * pass some non-existing encoding name + * (ex: 'Do not touch my strings! I know what I am doing.') + * to make encoding code skip the encoding step. + * .outputEncoding = Either valid PDF encoding name + * (must be supported by jsPDF font metrics, otherwise no encoding) + * or a JS object, where key = sourceCharCode, value = outputCharCode + * missing keys will be treated as: sourceCharCode === outputCharCode + * .noBOM + * See comment higher above for explanation for why this is important + * .autoencode + * See comment higher above for explanation for why this is important + */ + var i, l, sourceEncoding, encodingBlock, outputEncoding, newtext, isUnicode, ch, bch; + flags = flags || {}; + sourceEncoding = flags.sourceEncoding || "Unicode"; + outputEncoding = flags.outputEncoding; // This 'encoding' section relies on font metrics format + // attached to font objects by, among others, + // "Willow Systems' standard_font_metrics plugin" + // see jspdf.plugin.standard_font_metrics.js for format + // of the font.metadata.encoding Object. + // It should be something like + // .encoding = {'codePages':['WinANSI....'], 'WinANSI...':{code:code, ...}} + // .widths = {0:width, code:width, ..., 'fof':divisor} + // .kerning = {code:{previous_char_code:shift, ..., 'fof':-divisor},...} + + if ((flags.autoencode || outputEncoding) && fonts[activeFontKey].metadata && fonts[activeFontKey].metadata[sourceEncoding] && fonts[activeFontKey].metadata[sourceEncoding].encoding) { + encodingBlock = fonts[activeFontKey].metadata[sourceEncoding].encoding; // each font has default encoding. Some have it clearly defined. + + if (!outputEncoding && fonts[activeFontKey].encoding) { + outputEncoding = fonts[activeFontKey].encoding; + } // Hmmm, the above did not work? Let's try again, in different place. + + + if (!outputEncoding && encodingBlock.codePages) { + outputEncoding = encodingBlock.codePages[0]; // let's say, first one is the default + } + + if (typeof outputEncoding === "string") { + outputEncoding = encodingBlock[outputEncoding]; + } // we want output encoding to be a JS Object, where + // key = sourceEncoding's character code and + // value = outputEncoding's character code. + + + if (outputEncoding) { + isUnicode = false; + newtext = []; + + for (i = 0, l = text.length; i < l; i++) { + ch = outputEncoding[text.charCodeAt(i)]; + + if (ch) { + newtext.push(String.fromCharCode(ch)); + } else { + newtext.push(text[i]); + } // since we are looping over chars anyway, might as well + // check for residual unicodeness + + + if (newtext[i].charCodeAt(0) >> 8) { + /* more than 255 */ + isUnicode = true; + } + } + + text = newtext.join(""); + } + } + + i = text.length; // isUnicode may be set to false above. Hence the triple-equal to undefined + + while (isUnicode === undefined && i !== 0) { + if (text.charCodeAt(i - 1) >> 8) { + /* more than 255 */ + isUnicode = true; + } + + i--; + } + + if (!isUnicode) { + return text; + } + + newtext = flags.noBOM ? [] : [254, 255]; + + for (i = 0, l = text.length; i < l; i++) { + ch = text.charCodeAt(i); + bch = ch >> 8; // divide by 256 + + if (bch >> 8) { + /* something left after dividing by 256 second time */ + throw new Error("Character at position " + i + " of string '" + text + "' exceeds 16bits. Cannot be encoded into UCS-2 BE"); + } + + newtext.push(bch); + newtext.push(ch - (bch << 8)); + } + + return String.fromCharCode.apply(undefined, newtext); + }, + pdfEscape = function pdfEscape(text, flags) { + /** + * Replace '/', '(', and ')' with pdf-safe versions + * + * Doing to8bitStream does NOT make this PDF display unicode text. For that + * we also need to reference a unicode font and embed it - royal pain in the rear. + * + * There is still a benefit to to8bitStream - PDF simply cannot handle 16bit chars, + * which JavaScript Strings are happy to provide. So, while we still cannot display + * 2-byte characters property, at least CONDITIONALLY converting (entire string containing) + * 16bit chars to (USC-2-BE) 2-bytes per char + BOM streams we ensure that entire PDF + * is still parseable. + * This will allow immediate support for unicode in document properties strings. + */ + return to8bitStream(text, flags).replace(/\\/g, "\\\\").replace(/\(/g, "\\(").replace(/\)/g, "\\)"); + }, + putInfo = function putInfo() { + out("/Producer (jsPDF " + jsPDF.version + ")"); + + for (var key in documentProperties) { + if (documentProperties.hasOwnProperty(key) && documentProperties[key]) { + out("/" + key.substr(0, 1).toUpperCase() + key.substr(1) + " (" + pdfEscape(documentProperties[key]) + ")"); + } + } + + out("/CreationDate (" + creationDate + ")"); + }, + putCatalog = function putCatalog() { + out("/Type /Catalog"); + out("/Pages 1 0 R"); // PDF13ref Section 7.2.1 + + if (!zoomMode) zoomMode = "fullwidth"; + + switch (zoomMode) { + case "fullwidth": + out("/OpenAction [3 0 R /FitH null]"); + break; + + case "fullheight": + out("/OpenAction [3 0 R /FitV null]"); + break; + + case "fullpage": + out("/OpenAction [3 0 R /Fit]"); + break; + + case "original": + out("/OpenAction [3 0 R /XYZ null null 1]"); + break; + + default: + var pcn = "" + zoomMode; + if (pcn.substr(pcn.length - 1) === "%") zoomMode = parseInt(zoomMode) / 100; + + if (typeof zoomMode === "number") { + out("/OpenAction [3 0 R /XYZ null null " + f2(zoomMode) + "]"); + } + + } + + if (!layoutMode) layoutMode = "continuous"; + + switch (layoutMode) { + case "continuous": + out("/PageLayout /OneColumn"); + break; + + case "single": + out("/PageLayout /SinglePage"); + break; + + case "two": + case "twoleft": + out("/PageLayout /TwoColumnLeft"); + break; + + case "tworight": + out("/PageLayout /TwoColumnRight"); + break; + } + + if (pageMode) { + /** + * A name object specifying how the document should be displayed when opened: + * UseNone : Neither document outline nor thumbnail images visible -- DEFAULT + * UseOutlines : Document outline visible + * UseThumbs : Thumbnail images visible + * FullScreen : Full-screen mode, with no menu bar, window controls, or any other window visible + */ + out("/PageMode /" + pageMode); + } + + events.publish("putCatalog"); + }, + putTrailer = function putTrailer() { + out("/Size " + (objectNumber + 1)); + out("/Root " + objectNumber + " 0 R"); + out("/Info " + (objectNumber - 1) + " 0 R"); + out("/ID [ <" + fileId + "> <" + fileId + "> ]"); + }, + beginPage = function beginPage(width, height) { + outToPages = true; + pages[++page] = []; + pagedim[page] = { + width: Number(width) || pageWidth, + height: Number(height) || pageHeight + }; + pagesContext[page] = {}; + + _setPage(page); + }, + _addPage = function _addPage(width, height) { + // Dimensions are stored as user units and converted to points on output + var orientation = typeof height === "string" && height.toLowerCase(); + + if (typeof width === "string") { + var format = width.toLowerCase(); + + if (pageFormats.hasOwnProperty(format)) { + width = pageFormats[format][0] / k; + height = pageFormats[format][1] / k; + } + } + + if (Array.isArray(width)) { + height = width[1]; + width = width[0]; + } + + if (orientation) { + switch (orientation.substr(0, 1)) { + case "l": + if (height > width) orientation = "s"; + break; + + case "p": + if (width > height) orientation = "s"; + break; + } + + if (orientation === "s") { + tmp = width; + width = height; + height = tmp; + } + } + + beginPage(width, height); // Set line width + + out(hpf(lineWidth * k) + " w"); // Set draw color + + out(drawColor); // resurrecting non-default line caps, joins + + if (lineCapID !== 0) { + out(lineCapID + " J"); + } + + if (lineJoinID !== 0) { + out(lineJoinID + " j"); + } + + events.publish("addPage", { + pageNumber: page + }); + }, + _deletePage = function _deletePage(n) { + if (n > 0 && n <= page) { + pages.splice(n, 1); + pagedim.splice(n, 1); + page--; + + if (currentPage > page) { + currentPage = page; + } + + this.setPage(currentPage); + } + }, + _setPage = function _setPage(n) { + if (n > 0 && n <= page) { + currentPage = n; + pageWidth = pagedim[n].width; + pageHeight = pagedim[n].height; + } + }, + + /** + * Returns a document-specific font key - a label assigned to a + * font name + font type combination at the time the font was added + * to the font inventory. + * + * Font key is used as label for the desired font for a block of text + * to be added to the PDF document stream. + * @private + * @function + * @param {String} fontName can be undefined on "falthy" to indicate "use current" + * @param {String} fontStyle can be undefined on "falthy" to indicate "use current" + * @returns {String} Font key. + */ + _getFont = function getFont(fontName, fontStyle, options) { + var key = undefined, + fontNameLowerCase; + options = options || {}; + fontName = fontName !== undefined ? fontName : fonts[activeFontKey].fontName; + fontStyle = fontStyle !== undefined ? fontStyle : fonts[activeFontKey].fontStyle; + fontNameLowerCase = fontName.toLowerCase(); + + if (fontmap[fontNameLowerCase] !== undefined && fontmap[fontNameLowerCase][fontStyle] !== undefined) { + key = fontmap[fontNameLowerCase][fontStyle]; + } else if (fontmap[fontName] !== undefined && fontmap[fontName][fontStyle] !== undefined) { + key = fontmap[fontName][fontStyle]; + } else { + if (options.disableWarning === false) { + console.warn("Unable to look up font label for font '" + fontName + "', '" + fontStyle + "'. Refer to getFontList() for available fonts."); + } + } + + if (!key && !options.noFallback) { + key = fontmap["times"][fontStyle]; + + if (key == null) { + key = fontmap["times"]["normal"]; + } + } + + return key; + }, + buildDocument = function buildDocument() { + outToPages = false; // switches out() to content + + objectNumber = 2; + content_length = 0; + content = []; + offsets = []; + additionalObjects = []; // Added for AcroForm + + events.publish("buildDocument"); // putHeader() + + out("%PDF-" + pdfVersion); + out("%\xBA\xDF\xAC\xE0"); + putPages(); // Must happen after putPages + // Modifies current object Id + + putAdditionalObjects(); + putResources(); // Info + + newObject(); + out("<<"); + putInfo(); + out(">>"); + out("endobj"); // Catalog + + newObject(); + out("<<"); + putCatalog(); + out(">>"); + out("endobj"); // Cross-ref + + var o = content_length, + i, + p = "0000000000"; + out("xref"); + out("0 " + (objectNumber + 1)); + out(p + " 65535 f "); + + for (i = 1; i <= objectNumber; i++) { + var offset = offsets[i]; + + if (typeof offset === "function") { + out((p + offsets[i]()).slice(-10) + " 00000 n "); + } else { + out((p + offsets[i]).slice(-10) + " 00000 n "); + } + } // Trailer + + + out("trailer"); + out("<<"); + putTrailer(); + out(">>"); + out("startxref"); + out("" + o); + out("%%EOF"); + outToPages = true; + return content.join("\n"); + }, + getStyle = function getStyle(style) { + // see path-painting operators in PDF spec + // The default in MrRio's implementation is "S" (stroke), whereas the default in the yWorks implementation + // was "n" (none). Although this has nothing to do with transforms, we should use the API switch here. + var op = apiMode === ApiMode.COMPAT ? "S" : "n"; + + if (style === "D") { + op = "S"; // stroke + } else if (style === "F") { + op = "f"; // fill + } else if (style === "FD" || style === "DF") { + op = "B"; // both + } else if (style === "f" || style === "f*" || style === "B" || style === "B*") { + /* + Allow direct use of these PDF path-painting operators: + - f fill using nonzero winding number rule + - f* fill using even-odd rule + - B fill then stroke with fill using non-zero winding number rule + - B* fill then stroke with fill using even-odd rule + */ + op = style; + } + + return op; + }, + // puts the style for the previously drawn path. If a patternKey is provided, the pattern is used to fill + // the path. Use patternMatrix to transform the pattern to rhe right location. + putStyle = function putStyle(style, patternKey, patternData) { + if (style === null || apiMode === ApiMode.ADVANCED && style === undefined) { + return; + } + + style = getStyle(style); // stroking / filling / both the path + + if (!patternKey) { + out(style); + return; + } + + if (!patternData) { + patternData = { + matrix: unitMatrix + }; + } + + if (patternData instanceof Matrix) { + patternData = { + matrix: patternData + }; + } + + patternData.key = patternKey; + patternData || (patternData = unitMatrix); + fillWithPattern(patternData, style); + }, + fillWithPattern = function fillWithPattern(patternData, style) { + var patternId = patternMap[patternData.key]; + var pattern = patterns[patternId]; + + if (pattern instanceof API.ShadingPattern) { + out("q"); + out(clipRuleFromStyle(style)); + + if (pattern.gState) { + API.setGState(pattern.gState); + } + + out(patternData.matrix.toString() + " cm"); + out("/" + patternId + " sh"); + out("Q"); + } else if (pattern instanceof API.TilingPattern) { + // pdf draws patterns starting at the bottom left corner and they are not affected by the global transformation, + // so we must flip them + var matrix = new Matrix(1, 0, 0, -1, 0, pageHeight); + + if (patternData.matrix) { + matrix = matrixMult(patternData.matrix || unitMatrix, matrix); // we cannot apply a matrix to the pattern on use so we must abuse the pattern matrix and create new instances + // for each use + + patternId = pattern.createClone(patternData.key, patternData.boundingBox, patternData.xStep, patternData.yStep, matrix).id; + } + + out("q"); + out("/Pattern cs"); + out("/" + patternId + " scn"); + + if (pattern.gState) { + API.setGState(pattern.gState); + } + + out(style); + out("Q"); + } + }, + clipRuleFromStyle = function clipRuleFromStyle(style) { + switch (style) { + case "f": + case "F": + return "W n"; + + case "f*": + return "W* n"; + + case "B": + return "W S"; + + case "B*": + return "W* S"; + // these two are for compatibility reasons (in the past, calling any primitive method with a shading pattern + // and "n"/"S" as style would still fill/fill and stroke the path) + + case "S": + return "W S"; + + case "n": + return "W n"; + } + }, + getArrayBuffer = function getArrayBuffer() { + var data = buildDocument(), + len = data.length, + ab = new ArrayBuffer(len), + u8 = new Uint8Array(ab); + + while (len--) { + u8[len] = data.charCodeAt(len); + } + + return ab; + }, + getBlob = function getBlob() { + return new Blob([getArrayBuffer()], { + type: "application/pdf" + }); + }, + _output = SAFE(function (type, options) { + if (typeof options === "string") { + options = { + filename: options + }; + } else { + options = options || {}; + options.filename = options.filename || "generated.pdf"; + } + + var datauri = ("" + type).substr(0, 6) === "dataur" ? "data:application/pdf;filename=" + options.filename + ";base64," + btoa(buildDocument()) : 0; + + switch (type) { + case undefined: + return buildDocument(); + + case "save": + if ((typeof navigator === "undefined" ? "undefined" : _typeof(navigator)) === "object" && navigator.getUserMedia) { + if (global.URL === undefined || global.URL.createObjectURL === undefined) { + return API.output("dataurlnewwindow"); + } + } + + saveAs(getBlob(), options.filename); + + if (typeof saveAs.unload === "function") { + if (global.setTimeout) { + setTimeout(saveAs.unload, 911); + } + } + + break; + + case "arraybuffer": + return getArrayBuffer(); + + case "blob": + return getBlob(); + + case "bloburi": + case "bloburl": + // User is responsible of calling revokeObjectURL + return global.URL && global.URL.createObjectURL(getBlob()) || void 0; + + case "datauristring": + case "dataurlstring": + return datauri; + + case "dataurlnewwindow": + var htmlForNewWindow = "" + "" + "" + '' + ""; + var nW = global.open(); + + if (nW !== null) { + nW.document.write(htmlForNewWindow); + } + + if (nW || typeof safari === "undefined") return nW; + + /* pass through */ + + case "datauri": + case "dataurl": + return global.document.location.href = datauri; + + default: + throw new Error('Output type "' + type + '" is not supported.'); + } // @TODO: Add different output options + + }), + + /** + * Used to see if a supplied hotfix was requested when the pdf instance was created. + * @param {string} hotfixName - The name of the hotfix to check. + * @returns {boolean} + */ + hasHotfix = function hasHotfix(hotfixName) { + return Array.isArray(hotfixes) === true && hotfixes.indexOf(hotfixName) > -1; + }; + + switch (unit) { + case "pt": + k = 1; + break; + + case "mm": + k = 72 / 25.4000508; + break; + + case "cm": + k = 72 / 2.54000508; + break; + + case "in": + k = 72; + break; + + case "px": + if (hasHotfix("px_scaling") == true) { + k = 72 / 96; + } else { + k = 96 / 72; + } + + break; + + case "pc": + k = 12; + break; + + case "em": + k = 12; + break; + + case "ex": + k = 6; + break; + + default: + throw "Invalid unit: " + unit; + } + + setCreationDate(); + setFileId(); //--------------------------------------- + // Public API + + /** + * Object exposing internal API to plugins + * @public + * @ignore + */ + + API.internal = { + pdfEscape: pdfEscape, + getStyle: getStyle, + + /** + * Returns {FontObject} describing a particular font. + * @public + * @function + * @param {String} fontName (Optional) Font's family name + * @param {String} fontStyle (Optional) Font's style variation name (Example:"Italic") + * @returns {FontObject} + */ + getFont: function getFont() { + return fonts[_getFont.apply(API, arguments)]; + }, + getFontSize: function getFontSize() { + return activeFontSize; + }, + getCharSpace: function getCharSpace() { + return activeCharSpace; + }, + getTextColor: function getTextColor() { + var colorEncoded = textColor.split(" "); + + if (colorEncoded.length === 2 && colorEncoded[1] === "g") { + // convert grayscale value to rgb so that it can be converted to hex for consistency + var floatVal = parseFloat(colorEncoded[0]); + colorEncoded = [floatVal, floatVal, floatVal, "r"]; + } + + var colorAsHex = "#"; + + for (var i = 0; i < 3; i++) { + colorAsHex += ("0" + Math.floor(parseFloat(colorEncoded[i]) * 255).toString(16)).slice(-2); + } + + return colorAsHex; + }, + getLineHeight: function getLineHeight() { + return activeFontSize * lineHeightProportion; + }, + write: function write(string1 + /*, string2, string3, etc */ + ) { + out(arguments.length === 1 ? string1 : Array.prototype.join.call(arguments, " ")); + }, + getCoordinateString: function getCoordinateString(value) { + return hpf(scaleByK(value)); + }, + getVerticalCoordinateString: function getVerticalCoordinateString(value) { + return hpf(transformScaleY(value)); + }, + collections: {}, + newObject: newObject, + newAdditionalObject: newAdditionalObject, + newObjectDeferred: newObjectDeferred, + newObjectDeferredBegin: newObjectDeferredBegin, + putStream: putStream, + events: events, + // ratio that you use in multiplication of a given "size" number to arrive to 'point' + // units of measurement. + // scaleFactor is set at initialization of the document and calculated against the stated + // default measurement units for the document. + // If default is "mm", k is the number that will turn number in 'mm' into 'points' number. + // through multiplication. + scaleFactor: k, + pageSize: { + getWidth: function getWidth() { + return pageWidth; + }, + getHeight: function getHeight() { + return pageHeight; + } + }, + output: function output(type, options) { + return _output(type, options); + }, + getNumberOfPages: function getNumberOfPages() { + return pages.length - 1; + }, + pages: pages, + out: out, + f2: f2, + getPageInfo: function getPageInfo(pageNumberOneBased) { + var objId = (pageNumberOneBased - 1) * 2 + 3; + return { + objId: objId, + pageNumber: pageNumberOneBased, + pageContext: pagesContext[pageNumberOneBased] + }; + }, + getCurrentPageInfo: function getCurrentPageInfo() { + var objId = (currentPage - 1) * 2 + 3; + return { + objId: objId, + pageNumber: currentPage, + pageContext: pagesContext[currentPage] + }; + }, + getPDFVersion: function getPDFVersion() { + return pdfVersion; + }, + hasHotfix: hasHotfix //Expose the hasHotfix check so plugins can also check them. + + }; + + function advancedAPI() { + // prepend global change of basis matrix + // (Now, instead of converting every coordinate to the pdf coordinate system, we apply a matrix + // that does this job for us (however, texts, images and similar objects must be drawn bottom up)) + this.saveGraphicsState(); + out(new Matrix(k, 0, 0, -k, 0, pageHeight * k).toString() + " cm"); + this.setFontSize(this.getFontSize() / k); + apiMode = ApiMode.ADVANCED; + } + + function compatAPI() { + this.restoreGraphicsState(); + apiMode = ApiMode.COMPAT; + } + /** + * @callback ApiSwitchBody + * @param {jsPDF} pdf + */ + + /** + * For compatibility reasons jsPDF offers two API modes which differ in the way they convert between the the usual + * screen coordinates and the PDF coordinate system. + * - "compat": Offers full compatibility across all plugins but does not allow arbitrary transforms + * - "advanced": Allows arbitrary transforms and more advanced features like pattern fills. Some plugins might + * not support this mode, though. + * Initial mode is "compat". + * + * You can either provide a callback to the body argument, which means that jsPDF will automatically switch back to + * the original API mode afterwards; or you can omit the callback and switch back manually using {@link compatAPI}. + * + * Note, that the calls to {@link saveGraphicsState} and {@link restoreGraphicsState} need to be balanced within the + * callback or between calls of this method and its counterpart {@link compatAPI}. Calls to {@link beginFormObject} + * or {@link beginTilingPattern} need to be closed by their counterparts before switching back to "compat" API mode. + * + * @param {ApiSwitchBody=} body When provided, this callback will be called after the API mode has been switched. + * The API mode will be switched back automatically afterwards. + * @returns {jsPDF} + * @methodOf jsPDF# + * @name advancedAPI + */ + + + API.advancedAPI = function (body) { + var doSwitch = apiMode === ApiMode.COMPAT; + + if (doSwitch) { + advancedAPI.call(this); + } + + if (typeof body !== "function") { + return this; + } + + body(this); + + if (doSwitch) { + compatAPI.call(this); + } + + return this; + }; + /** + * Switches to "compat" API mode. See {@link advancedAPI} for more details. + * + * @param {ApiSwitchBody=} body When provided, this callback will be called after the API mode has been switched. + * The API mode will be switched back automatically afterwards. + * @return {jsPDF} + * @methodOf jsPDF# + * @name compatApi + */ + + + API.compatAPI = function (body) { + var doSwitch = apiMode === ApiMode.ADVANCED; + + if (doSwitch) { + compatAPI.call(this); + } + + if (typeof body !== "function") { + return this; + } + + body(this); + + if (doSwitch) { + advancedAPI.call(this); + } + + return this; + }; + /** + * @return {boolean} True iff the current API mode is "advanced". See {@link advancedAPI}. + * @methodOf jsPDF# + * @name isAdvancedAPI + */ + + + API.isAdvancedAPI = function () { + return apiMode === ApiMode.ADVANCED; + }; + /** + * Inserts a debug comment into the pdf. + * @param {String} text + * @returns {jsPDF} + * @methodOf jsPDF# + * @name comment + */ + + + API.comment = function (text) { + out("#" + text); + return this; + }; + /** + * An object representing a pdf graphics state. + * @param parameters A parameter object that contains all properties this graphics state wants to set. + * Supported are: opacity, stroke-opacity + * @constructor + */ + + + API.GState = function (parameters) { + var supported = "opacity,stroke-opacity".split(","); + + for (var p in parameters) { + if (parameters.hasOwnProperty(p) && supported.indexOf(p) >= 0) { + this[p] = parameters[p]; + } + } + + this.id = ""; // set by addGState() + + this.objectNumber = -1; // will be set by putGState() + }; + + API.GState.prototype.equals = function equals(other) { + var ignore = "id,objectNumber,equals"; + if (!other || _typeof(other) !== _typeof(this)) return false; + var count = 0; + + for (var p in this) { + if (ignore.indexOf(p) >= 0) continue; + if (this.hasOwnProperty(p) && !other.hasOwnProperty(p)) return false; + if (this[p] !== other[p]) return false; + count++; + } + + for (var p in other) { + if (other.hasOwnProperty(p) && ignore.indexOf(p) < 0) count--; + } + + return count === 0; + }; + /** + * Adds a new {@link GState} for later use. See {@link setGState}. + * @param {String} key + * @param {GState} gState + * @function + * @instance + * @returns {jsPDF} + * + * @methodOf jsPDF# + * @name addPage + */ + + + API.addGState = function (key, gState) { + addGState(key, gState); + return this; + }; + /** + * Adds (and transfers the focus to) new page to the PDF document. + * @param {String/Array} format The format of the new page. Can be
  • a0 - a10
  • b0 - b10
  • c0 - c10
  • c0 - c10
  • dl
  • letter
  • government-letter
  • legal
  • junior-legal
  • ledger
  • tabloid
  • credit-card

+ * Default is "a4". If you want to use your own format just pass instead of one of the above predefined formats the size as an number-array , e.g. [595.28, 841.89] + * @param {string} orientation Orientation of the new page. Possible values are "portrait" or "landscape" (or shortcuts "p" (Default), "l") + * @function + * @instance + * @returns {jsPDF} + * + * @memberOf jsPDF + * @name addPage + */ + + + API.addPage = function (format, orientation) { + _addPage.apply(this, arguments); + + return this; + }; + /** + * Adds (and transfers the focus to) new page to the PDF document. + * @function + * @instance + * @returns {jsPDF} + * + * @memberOf jsPDF + * @name setPage + * @param {number} page Switch the active page to the page number specified + * @example + * doc = jsPDF() + * doc.addPage() + * doc.addPage() + * doc.text('I am on page 3', 10, 10) + * doc.setPage(1) + * doc.text('I am on page 1', 10, 10) + */ + + + API.setPage = function (page) { + _setPage.apply(this, arguments); + + return this; + }; + /** + * @name insertPage + * @memberOf jsPDF + * + * @function + * @instance + * @param {Object} beforePage + * @returns {jsPDF} + */ + + + API.insertPage = function (beforePage) { + this.addPage(); + this.movePage(currentPage, beforePage); + return this; + }; + /** + * @name movePage + * @memberOf jsPDF + * @function + * @instance + * @param {Object} targetPage + * @param {Object} beforePage + * @returns {jsPDF} + */ + + + API.movePage = function (targetPage, beforePage) { + var tmpPagesContext, tmpPagedim, tmpPages, i; + + if (targetPage > beforePage) { + tmpPages = pages[targetPage]; + tmpPagedim = pagedim[targetPage]; + tmpPagesContext = pagesContext[targetPage]; + + for (i = targetPage; i > beforePage; i--) { + pages[i] = pages[i - 1]; + pagedim[i] = pagedim[i - 1]; + pagesContext[i] = pagesContext[i - 1]; + } + + pages[beforePage] = tmpPages; + pagedim[beforePage] = tmpPagedim; + pagesContext[beforePage] = tmpPagesContext; + this.setPage(beforePage); + } else if (targetPage < beforePage) { + tmpPages = pages[targetPage]; + tmpPagedim = pagedim[targetPage]; + tmpPagesContext = pagesContext[targetPage]; + + for (i = targetPage; i < beforePage; i++) { + pages[i] = pages[i + 1]; + pagedim[i] = pagedim[i + 1]; + pagesContext[i] = pagesContext[i + 1]; + } + + pages[beforePage] = tmpPages; + pagedim[beforePage] = tmpPagedim; + pagesContext[beforePage] = tmpPagesContext; + this.setPage(beforePage); + } + + return this; + }; + /** + * @name deletePage + * @memberOf jsPDF + * @function + * @instance + * @returns {jsPDF} + */ + + + API.deletePage = function () { + _deletePage.apply(this, arguments); + + return this; + }; + /** + * @name setCreationDate + * @memberOf jsPDF + * @function + * @instance + * @param {Object} date + * @returns {jsPDF} + */ + + + API.setCreationDate = function (date) { + setCreationDate(date); + return this; + }; + /** + * @name getCreationDate + * @memberOf jsPDF + * @function + * @instance + * @param {Object} type + * @returns {Object} + */ + + + API.getCreationDate = function (type) { + return getCreationDate(type); + }; + /** + * @name setFileId + * @memberOf jsPDF + * @function + * @instance + * @param {string} value GUID + * @returns {jsPDF} + */ + + + API.setFileId = function (value) { + setFileId(value); + return this; + }; + /** + * @name getFileId + * @memberOf jsPDF + * @function + * @instance + * + * @returns {string} GUID + */ + + + API.getFileId = function () { + return getFileId(); + }; + /** + * Set the display mode options of the page like zoom and layout. + * + * @param {integer|String} zoom You can pass an integer or percentage as + * a string. 2 will scale the document up 2x, '200%' will scale up by the + * same amount. You can also set it to 'fullwidth', 'fullheight', + * 'fullpage', or 'original'. + * + * Only certain PDF readers support this, such as Adobe Acrobat + * + * @param {string} layout Layout mode can be: 'continuous' - this is the + * default continuous scroll. 'single' - the single page mode only shows one + * page at a time. 'twoleft' - two column left mode, first page starts on + * the left, and 'tworight' - pages are laid out in two columns, with the + * first page on the right. This would be used for books. + * @param {string} pmode 'UseOutlines' - it shows the + * outline of the document on the left. 'UseThumbs' - shows thumbnails along + * the left. 'FullScreen' - prompts the user to enter fullscreen mode. + * + * @returns {jsPDF} + * @function + * @instance + * @name setDisplayMode + * @methodOf jsPDF# + */ + + + API.setDisplayMode = function (zoom, layout, pmode) { + zoomMode = zoom; + layoutMode = layout; + pageMode = pmode; + var validPageModes = [undefined, null, "UseNone", "UseOutlines", "UseThumbs", "FullScreen"]; + + if (validPageModes.indexOf(pmode) == -1) { + throw new Error('Page mode must be one of UseNone, UseOutlines, UseThumbs, or FullScreen. "' + pmode + '" is not recognized.'); + } + + return this; + }; + /** + * Saves the current graphics state ("pushes it on the stack"). It can be restored by {@link restoreGraphicsState} + * later. Here, the general pdf graphics state is meant, also including the current transformation matrix, + * fill and stroke colors etc. + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name saveGraphicsState + */ + + + API.saveGraphicsState = function () { + out("q"); // as we cannot set font key and size independently we must keep track of both + + fontStateStack.push({ + key: activeFontKey, + size: activeFontSize, + color: textColor + }); + return this; + }; + /** + * Restores a previously saved graphics state saved by {@link saveGraphicsState} ("pops the stack"). + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name restoreGraphicsState + */ + + + API.restoreGraphicsState = function () { + out("Q"); // restore previous font state + + var fontState = fontStateStack.pop(); + activeFontKey = fontState.key; + activeFontSize = fontState.size; + textColor = fontState.color; + activeGState = null; + return this; + }; + /** + * Appends this matrix to the left of all previously applied matrices. + * + * Only available in "advanced" API mode. + * + * @param {Matrix} matrix + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setCurrentTransformationMatrix + */ + + + API.setCurrentTransformationMatrix = function (matrix) { + advancedApiModeTrap("setCurrentTransformationMatrix()"); + out(matrix.toString() + " cm"); + return this; + }; + /** + * Starts a new pdf form object, which means that all conseequent draw calls target a new independent object + * until {@link endFormObject} is called. The created object can be referenced and drawn later using + * {@link doFormObject}. Nested form objects are possible. + * x, y, width, height set the bounding box that is used to clip the content. + * + * Only available in "advanced" API mode. + * + * @param {number} x + * @param {number} y + * @param {number} width + * @param {number} height + * @param {Matrix} matrix The matrix that will be applied to convert the form objects coordinate system to + * the parent's. + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name beginFormObject + */ + + + API.beginFormObject = function (x, y, width, height, matrix) { + advancedApiModeTrap("beginFormObject()"); // The user can set the output target to a new form object. Nested form objects are possible. + // Currently, they use the resource dictionary of the surrounding stream. This should be changed, as + // the PDF-Spec states: + // "In PDF 1.2 and later versions, form XObjects may be independent of the content streams in which + // they appear, and this is strongly recommended although not requiredIn PDF 1.2 and later versions, + // form XObjects may be independent of the content streams in which they appear, and this is strongly + // recommended although not required" + + beginNewRenderTarget(x, y, width, height, matrix); + return this; + }; + /** + * Completes and saves the form object. Only available in "advanced" API mode. + * @param {String} key The key by which this form object can be referenced. + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name endFormObject + */ + + + API.endFormObject = function (key) { + advancedApiModeTrap("endFormObject()"); + endFormObject(key); + return this; + }; + /** + * Draws the specified form object by referencing to the respective pdf XObject created with + * {@link API.beginFormObject} and {@link endFormObject}. + * The location is determined by matrix. + * + * Only available in "advanced" API mode. + * + * @param {String} key The key to the form object. + * @param {Matrix} matrix The matrix applied before drawing the form object. + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name doFormObject + */ + + + API.doFormObject = function (key, matrix) { + advancedApiModeTrap("doFormObject()"); + var xObject = renderTargets[renderTargetMap[key]]; + out("q"); + out(matrix.toString() + " cm"); + out("/" + xObject.id + " Do"); + out("Q"); + return this; + }; + /** + * Returns the form object specified by key. + * @param key {String} + * @returns {{x: number, y: number, width: number, height: number, matrix: Matrix}} + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name getFormObject + */ + + + API.getFormObject = function (key) { + var xObject = renderTargets[renderTargetMap[key]]; + return { + x: xObject.x, + y: xObject.y, + width: xObject.width, + height: xObject.height, + matrix: xObject.matrix + }; + }; + /** + * A matrix object for 2D homogenous transformations: + * | a b 0 | + * | c d 0 | + * | e f 1 | + * pdf multiplies matrices righthand: v' = v x m1 x m2 x ... + * @param {number} a + * @param {number} b + * @param {number} c + * @param {number} d + * @param {number} e + * @param {number} f + * @constructor + */ + + + API.Matrix = Matrix; + /** + * Multiplies two matrices. (see {@link Matrix}) + * @param {Matrix} m1 + * @param {Matrix} m2 + * @methodOf jsPDF# + * @name matrixMult + */ + + API.matrixMult = matrixMult; + /** + * The unit matrix (equivalent to new Matrix(1, 0, 0, 1, 0, 0)). + * @type {Matrix} + * @fieldOf jsPDF# + * @name unitMatrix + */ + + API.unitMatrix = unitMatrix; + + var Pattern = function Pattern(gState, matrix) { + this.gState = gState; + this.matrix = matrix; + this.id = ""; // set by addPattern() + + this.objectNumber = -1; // will be set by putPattern() + }; + /** + * A pattern describing a shading pattern. + * + * Only available in "advanced" API mode. + * + * @param {String} type One of "axial" or "radial" + * @param {Array} coords Either [x1, y1, x2, y2] for "axial" type describing the two interpolation points + * or [x1, y1, r, x2, y2, r2] for "radial" describing inner and the outer circle. + * @param {Array} colors An array of objects with the fields "offset" and "color". "offset" describes + * the offset in parameter space [0, 1]. "color" is an array of length 3 describing RGB values in [0, 255]. + * @param {GState=} gState An additional graphics state that gets applied to the pattern (optional). + * @param {Matrix=} matrix A matrix that describes the transformation between the pattern coordinate system + * and the use coordinate system (optional). + * @constructor + * @extends API.Pattern + */ + + + API.ShadingPattern = function (type, coords, colors, gState, matrix) { + advancedApiModeTrap("ShadingPattern"); // see putPattern() for information how they are realized + + this.type = type === "axial" ? 2 : 3; + this.coords = coords; + this.colors = colors; + Pattern.call(this, gState, matrix); + }; + /** + * A PDF Tiling pattern. + * + * Only available in "advanced" API mode. + * + * @param {Array.} boundingBox The bounding box at which one pattern cell gets clipped. + * @param {Number} xStep Horizontal spacing between pattern cells. + * @param {Number} yStep Vertical spacing between pattern cells. + * @param {API.GState=} gState An additional graphics state that gets applied to the pattern (optional). + * @param {Matrix=} matrix A matrix that describes the transformation between the pattern coordinate system + * and the use coordinate system (optional). + * @constructor + * @extends API.Pattern + */ + + + API.TilingPattern = function (boundingBox, xStep, yStep, gState, matrix) { + advancedApiModeTrap("TilingPattern"); + this.boundingBox = boundingBox; + this.xStep = xStep; + this.yStep = yStep; + this.stream = ""; // set by endTilingPattern(); + + this.cloneIndex = 0; + Pattern.call(this, gState, matrix); + }; + + API.TilingPattern.prototype = { + createClone: function createClone(patternKey, boundingBox, xStep, yStep, matrix) { + var clone = new API.TilingPattern(boundingBox || this.boundingBox, xStep || this.xStep, yStep || this.yStep, this.gState, matrix || this.matrix); + clone.stream = this.stream; + var key = patternKey + "$$" + this.cloneIndex++ + "$$"; + addPattern(key, clone); + return clone; + } + }; + /** + * Adds a new {@link API.ShadingPattern} for later use. Only available in "advanced" API mode. + * @param {String} key + * @param {Pattern} pattern + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name addPattern + */ + + API.addShadingPattern = function (key, pattern) { + advancedApiModeTrap("addShadingPattern()"); + addPattern(key, pattern); + return this; + }; + /** + * Begins a new tiling pattern. All subsequent render calls are drawn to this pattern until {@link API.endTilingPattern} + * gets called. Only available in "advanced" API mode. + * @param {API.Pattern} pattern + * @methodOf jsPDF# + * @name beginTilingPattern + */ + + + API.beginTilingPattern = function (pattern) { + advancedApiModeTrap("beginTilingPattern()"); + beginNewRenderTarget(pattern.boundingBox[0], pattern.boundingBox[1], pattern.boundingBox[2] - pattern.boundingBox[0], pattern.boundingBox[3] - pattern.boundingBox[1], pattern.matrix); + }; + /** + * Ends a tiling pattern and sets the render target to the one active before {@link API.beginTilingPattern} has been called. + * + * Only available in "advanced" API mode. + * + * @param {string} key A unique key that is used to reference this pattern at later use. + * @param {API.Pattern} pattern The pattern to end. + * @methodOf jsPDF# + * @name endTilingPattern + */ + + + API.endTilingPattern = function (key, pattern) { + advancedApiModeTrap("endTilingPattern()"); // retrieve the stream + + pattern.stream = pages[currentPage].join("\n"); + addPattern(key, pattern); + events.publish("endTilingPattern", pattern); // restore state from stack + + renderTargetStack.pop().restore(); + }; + /** + * Adds text to page. Supports adding multiline text when 'text' argument is an Array of Strings. + * + * @function + * @param {String|Array} text String or array of strings to be added to the page. Each line is shifted one line down + * per font, spacing settings declared before this call. + * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Object} options Collection of settings signalling how the text must be encoded. Defaults are sane. If you + * think you want to pass some flags, you likely can read the source. + * @param {number|Matrix} transform If transform is a number the text will be rotated by this value around the + * anchor set by x and y. + * + * If it is a Matrix, this matrix gets directly applied to the text, which allows shearing + * effects etc.; the x and y offsets are then applied AFTER the coordinate system has been established by this + * matrix. This means passing a rotation matrix that is equivalent to some rotation angle will in general yield a + * DIFFERENT result. A matrix is only allowed in "advanced" API mode. + * + * @param align {string} + * @returns {jsPDF} + * @methodOf jsPDF# + * @name text + */ + + + API.text = function (text, x, y, options, transform) { + /** + * Inserts something like this into PDF + * BT + * /F1 16 Tf % Font name + size + * 16 TL % How many units down for next line in multiline text + * 0 g % color + * 28.35 813.54 Td % position + * (line one) Tj + * T* (line two) Tj + * T* (line three) Tj + * ET + */ + if (transform !== undefined && transform instanceof Matrix) { + advancedApiModeTrap("The transform parameter of text() with a Matrix value"); + } + + var xtra = ""; + var isHex = false; + var lineHeight = lineHeightProportion; + var scope = this; + + function ESC(s) { + s = s.split("\t").join(Array(options.TabLen || 9).join(" ")); + return pdfEscape(s, flags); + } + + function transformTextToSpecialArray(text) { + //we don't want to destroy original text array, so cloning it + var sa = text.concat(); + var da = []; + var len = sa.length; + var curDa; //we do array.join('text that must not be PDFescaped") + //thus, pdfEscape each component separately + + while (len--) { + curDa = sa.shift(); + + if (typeof curDa === "string") { + da.push(curDa); + } else { + if (Object.prototype.toString.call(text) === "[object Array]" && curDa.length === 1) { + da.push(curDa[0]); + } else { + da.push([curDa[0], curDa[1], curDa[2]]); + } + } + } + + return da; + } + + function processTextByFunction(text, processingFunction) { + var result; + + if (typeof text === "string") { + result = processingFunction(text)[0]; + } else if (Object.prototype.toString.call(text) === "[object Array]") { + //we don't want to destroy original text array, so cloning it + var sa = text.concat(); + var da = []; + var len = sa.length; + var curDa; + var tmpResult; //we do array.join('text that must not be PDFescaped") + //thus, pdfEscape each component separately + + while (len--) { + curDa = sa.shift(); + + if (typeof curDa === "string") { + da.push(processingFunction(curDa)[0]); + } else if (Object.prototype.toString.call(curDa) === "[object Array]" && curDa[0] === "string") { + tmpResult = processingFunction(curDa[0], curDa[1], curDa[2]); + da.push([tmpResult[0], tmpResult[1], tmpResult[2]]); + } + } + + result = da; + } + + return result; + } //backwardsCompatibility + + + var tmp; // Pre-August-2012 the order of arguments was function(x, y, text, flags) + // in effort to make all calls have similar signature like + // function(data, coordinates... , miscellaneous) + // this method had its args flipped. + // code below allows backward compatibility with old arg order. + + if (typeof text === "number") { + tmp = y; + y = x; + x = text; + text = tmp; + } + + var flags = arguments[3]; + var angle = arguments[4]; + var align = arguments[5]; + + if (_typeof(flags) !== "object" || flags === null) { + if (typeof angle === "string") { + align = angle; + angle = null; + } + + if (typeof flags === "string") { + align = flags; + flags = null; + } + + if (typeof flags === "number") { + angle = flags; + flags = null; + } + + options = { + flags: flags, + angle: angle, + align: align + }; + } //Check if text is of type String + + + var textIsOfTypeString = false; + var tmpTextIsOfTypeString = true; + + if (typeof text === "string") { + textIsOfTypeString = true; + } else if (Object.prototype.toString.call(text) === "[object Array]") { + //we don't want to destroy original text array, so cloning it + var sa = text.concat(); + var da = []; + var len = sa.length; + var curDa; //we do array.join('text that must not be PDFescaped") + //thus, pdfEscape each component separately + + while (len--) { + curDa = sa.shift(); + + if (typeof curDa !== "string" || Object.prototype.toString.call(curDa) === "[object Array]" && typeof curDa[0] !== "string") { + tmpTextIsOfTypeString = false; + } + } + + textIsOfTypeString = tmpTextIsOfTypeString; + } + + if (textIsOfTypeString === false) { + throw new Error('Type of text must be string or Array. "' + text + '" is not recognized.'); + } //Escaping + + + var activeFontEncoding = fonts[activeFontKey].encoding; + + if (activeFontEncoding === "WinAnsiEncoding" || activeFontEncoding === "StandardEncoding") { + text = processTextByFunction(text, function (text, posX, posY) { + return [ESC(text), posX, posY]; + }); + } //If there are any newlines in text, we assume + //the user wanted to print multiple lines, so break the + //text up into an array. If the text is already an array, + //we assume the user knows what they are doing. + //Convert text into an array anyway to simplify + //later code. + + + if (typeof text === "string") { + if (text.match(/[\r?\n]/)) { + text = text.split(/\r\n|\r|\n/g); + } else { + text = [text]; + } + } //multiline + + + var maxWidth = options.maxWidth || 0; + + if (maxWidth > 0) { + if (typeof text === "string") { + text = scope.splitTextToSize(text, maxWidth); + } else if (Object.prototype.toString.call(text) === "[object Array]") { + text = scope.splitTextToSize(text.join(" "), maxWidth); + } + } //creating Payload-Object to make text byRef + + + var payload = { + text: text, + x: x, + y: y, + options: options, + mutex: { + pdfEscape: pdfEscape, + activeFontKey: activeFontKey, + fonts: fonts, + activeFontSize: activeFontSize + } + }; + events.publish("preProcessText", payload); + text = payload.text; + options = payload.options; //angle + + var angle = options.angle; + var transformationMatrix = null; + + if (angle && typeof angle === "number") { + angle *= Math.PI / 180; + + if (apiMode === ApiMode.ADVANCED) { + angle = -angle; + } + + var c = Math.cos(angle), + s = Math.sin(angle); + transformationMatrix = new Matrix(c, s, -s, c, 0, 0); + } else if (angle && angle instanceof Matrix) { + transformationMatrix = angle; + } //charSpace + + + var charSpace = options.charSpace; + + if (charSpace !== undefined) { + xtra += charSpace + " Tc\n"; + } //lang + + + var lang = options.lang; + var tmpRenderingMode = -1; + var parmRenderingMode = options.renderingMode || options.stroke; + var pageContext = scope.internal.getCurrentPageInfo().pageContext; + + switch (parmRenderingMode) { + case 0: + case false: + case "fill": + tmpRenderingMode = 0; + break; + + case 1: + case true: + case "stroke": + tmpRenderingMode = 1; + break; + + case 2: + case "fillThenStroke": + tmpRenderingMode = 2; + break; + + case 3: + case "invisible": + tmpRenderingMode = 3; + break; + + case 4: + case "fillAndAddForClipping": + tmpRenderingMode = 4; + break; + + case 5: + case "strokeAndAddPathForClipping": + tmpRenderingMode = 5; + break; + + case 6: + case "fillThenStrokeAndAddToPathForClipping": + tmpRenderingMode = 6; + break; + + case 7: + case "addToPathForClipping": + tmpRenderingMode = 7; + break; + } + + var usedRenderingMode = pageContext.usedRenderingMode || -1; //if the coder wrote it explicitly to use a specific + //renderingMode, then use it + + if (tmpRenderingMode !== -1) { + xtra += tmpRenderingMode + " Tr\n"; //otherwise check if we used the rendering Mode already + //if so then set the rendering Mode... + } else if (usedRenderingMode !== -1) { + xtra += "0 Tr\n"; + } + + if (tmpRenderingMode !== -1) { + pageContext.usedRenderingMode = tmpRenderingMode; + } //align + + + var align = options.align || "left"; + var leading = activeFontSize * lineHeight; + var pageWidth = scope.internal.pageSize.getWidth(); + var k = scope.internal.scaleFactor; + var activeFont = fonts[activeFontKey]; + var charSpace = options.charSpace || activeCharSpace; + var maxWidth = options.maxWidth || 0; + var lineWidths; + var flags = {}; + var wordSpacingPerLine = []; + + if (Object.prototype.toString.call(text) === "[object Array]") { + var da = transformTextToSpecialArray(text); + var newY; + var maxLineLength; + var lineWidths; + + if (align !== "left") { + lineWidths = da.map(function (v) { + return scope.getStringUnitWidth(v, { + font: activeFont, + charSpace: charSpace, + fontSize: activeFontSize + }) * activeFontSize / k; + }); + } + + var maxLineLength = Math.max.apply(Math, lineWidths); //The first line uses the "main" Td setting, + //and the subsequent lines are offset by the + //previous line's x coordinate. + + var prevWidth = 0; + var delta; + var newX; + var xOffset = 0; + + if (align === "right") { + xOffset = -lineWidths[0]; + text = []; + + for (var i = 0, len = da.length; i < len; i++) { + delta = maxLineLength - lineWidths[i]; + + if (i === 0) { + newX = 0; + newY = 0; + } else { + newX = prevWidth - lineWidths[i]; + newY = leading; + } + + text.push([da[i], newX, newY]); + prevWidth = lineWidths[i]; + } + } else if (align === "center") { + xOffset = -lineWidths[0] / 2; + text = []; + + for (var i = 0, len = da.length; i < len; i++) { + delta = (maxLineLength - lineWidths[i]) / 2; + + if (i === 0) { + newX = 0; + newY = 0; + } else { + newX = (prevWidth - lineWidths[i]) / 2; + newY = leading; + } + + text.push([da[i], newX, newY]); + prevWidth = lineWidths[i]; + } + } else if (align === "left") { + text = []; + + for (var i = 0, len = da.length; i < len; i++) { + text.push(da[i]); + } + } else if (align === "justify") { + text = []; + var maxWidth = maxWidth !== 0 ? maxWidth : pageWidth; + + for (var i = 0, len = da.length; i < len; i++) { + newX = 0; + newY = i === 0 ? 0 : leading; + + if (i < len - 1) { + wordSpacingPerLine.push((maxWidth - lineWidths[i]) / (da[i].split(" ").length - 1)); + } + + text.push([da[i], newX, newY]); + } + } else { + throw new Error('Unrecognized alignment option, use "left", "center", "right" or "justify".'); + } + } //R2L + + + var doReversing = typeof options.R2L === "boolean" ? options.R2L : R2L; + + if (doReversing === true) { + text = processTextByFunction(text, function (text, posX, posY) { + return [text.split("").reverse().join(""), posX, posY]; + }); + } //creating Payload-Object to make text byRef + + + var payload = { + text: text, + x: x, + y: y, + options: options, + mutex: { + pdfEscape: pdfEscape, + activeFontKey: activeFontKey, + fonts: fonts, + activeFontSize: activeFontSize + } + }; + events.publish("postProcessText", payload); + text = payload.text; + isHex = payload.mutex.isHex; + var da = transformTextToSpecialArray(text); + text = []; + var variant = 0; + var len = da.length; + var posX; + var posY; + var content; + var wordSpacing = ""; + + for (var i = 0; i < len; i++) { + wordSpacing = ""; + + if (Object.prototype.toString.call(da[i]) !== "[object Array]") { + content = (isHex ? "<" : "(") + da[i] + (isHex ? ">" : ")"); + variant = 0; + } else if (Object.prototype.toString.call(da[i]) === "[object Array]") { + posX = da[i][1] * k; // x offset must always be scaled! + // y offset/leading must NOT be scaled by k as it is dependent of the font size, which is always given + // in plain pt + + posY = -da[i][2]; + content = (isHex ? "<" : "(") + da[i][0] + (isHex ? ">" : ")"); + variant = 1; + } + + if (wordSpacingPerLine !== undefined && wordSpacingPerLine[i] !== undefined) { + wordSpacing = wordSpacingPerLine[i] + " Tw\n"; + } + + if (variant === 1 && i > 0) { + text.push(wordSpacing + hpf(posX) + " " + hpf(posY) + " " + " Td\n" + content); + } else { + text.push(wordSpacing + content); + } + } + + if (variant === 0) { + text = text.join(" Tj\nT* "); + } else { + text = text.join(" Tj\n"); + } + + if (apiMode === ApiMode.ADVANCED && transformationMatrix === null) { + transformationMatrix = unitMatrix; + } + + if (transformationMatrix !== null) { + // It is kind of more intuitive to apply a plain rotation around the text anchor set by x and y + // but when the user supplies an arbitrary transformation matrix, the x and y offsets should be applied + // in the coordinate system established by this matrix + if (typeof angle === "number") { + transformationMatrix = matrixMult(transformationMatrix, new Matrix(1, 0, 0, 1, scaleByK(x), transformScaleY(y))); + } else { + transformationMatrix = matrixMult(new Matrix(1, 0, 0, 1, scaleByK(x), transformScaleY(y)), transformationMatrix); + } + + transformationMatrix = matrixMult( // xOffset must always be scaled! + new Matrix(1, 0, 0, 1, xOffset * k, 0), transformationMatrix); + + if (apiMode === ApiMode.ADVANCED) { + transformationMatrix = matrixMult(new Matrix(1, 0, 0, -1, 0, 0), transformationMatrix); + } + + text = transformationMatrix.toString() + " Tm\n" + text; + } else { + text = hpf(scaleByK(x + xOffset)) + " " + hpf(transformScaleY(y)) + " " + " Td\n" + text; + } + + text += " Tj\n"; + var result = "BT\n/" + activeFontKey + " " + activeFontSize + " Tf\n" + // font face, style, size + (activeFontSize * lineHeight).toFixed(2) + " TL\n" + // line spacing + textColor + "\n"; + result += xtra; + result += text; + result += "ET"; + out(result); + return scope; + }; + /** + * Letter spacing method to print text with gaps + * + * @function + * @instance + * @param {String|Array} text String to be added to the page. + * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {number} spacing Spacing (in units declared at inception) + * @returns {jsPDF} + * @methodOf jsPDF# + * @name lstext + * @deprecated We'll be removing this function. It doesn't take character width into account. + */ + + + API.lstext = function (text, x, y, spacing) { + console.warn("jsPDF.lstext is deprecated"); + + for (var i = 0, len = text.length; i < len; i++, x += spacing) { + this.text(text[i], x, y); + } + + return this; + }; + /** + * Draws a line from (x1, y1) to (x2, y2). No extra call to {@link API.stroke} is needed. + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @return {jsPDF} + * @methodOf jsPDF# + * @name line + */ + + + API.line = function (x1, y1, x2, y2) { + if (apiMode === ApiMode.COMPAT) { + return this.lines([[x2 - x1, y2 - y1]], x1, y1, [1, 1], "D"); + } else { + return this.lines([[x2 - x1, y2 - y1]], x1, y1, [1, 1]).stroke(); + } + }; + /** + * Begin a new subpath by moving the current point to coordinates (x, y). The PDF "m" operator. + * @param {number} x + * @param {number} y + * @methodOf jsPDF# + * @name moveTo + */ + + + API.moveTo = function (x, y) { + out(hpf(scaleByK(x)) + " " + hpf(transformScaleY(y)) + " m"); + }; + /** + * Append a straight line segment from the current point to the point (x, y). The PDF "l" operator. + * @param {number} x + * @param {number} y + * @methodOf jsPDF# + * @name lineTo + */ + + + API.lineTo = function (x, y) { + out(hpf(scaleByK(x)) + " " + hpf(transformScaleY(y)) + " l"); + }; + /** + * Append a cubic Bézier curve to the current path. The curve shall extend from the current point to the point + * (x3, y3), using (x1, y1) and (x2, y2) as Bézier control points. The new current point shall be (x3, x3). + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @param {number} x3 + * @param {number} y3 + * @methodOf jsPDF# + * @name curveTo + */ + + + API.curveTo = function (x1, y1, x2, y2, x3, y3) { + out([hpf(scaleByK(x1)), hpf(transformScaleY(y1)), hpf(scaleByK(x2)), hpf(transformScaleY(y2)), hpf(scaleByK(x3)), hpf(transformScaleY(y3)), "c"].join(" ")); + }; // PDF supports these path painting and clip path operators: + // + // S - stroke + // s - close/stroke + // f (F) - fill non-zero + // f* - fill evenodd + // B - fill stroke nonzero + // B* - fill stroke evenodd + // b - close fill stroke nonzero + // b* - close fill stroke evenodd + // n - nothing (consume path) + // W - clip nonzero + // W* - clip evenodd + // + // In order to keep the API small, we omit the close-and-fill/stroke operators and provide a separate close() + // method. + + /** + * Close the current path. The PDF "h" operator. + * @return jsPDF + * @methodOf jsPDF# + * @name close + */ + + + API.close = function () { + out("h"); + return this; + }; + /** + * Stroke the path. The PDF "S" operator. + * @return jsPDF + * @methodOf jsPDF# + * @name stroke + */ + + + API.stroke = function () { + out("S"); + return this; + }; + /** + * @typedef {Object} PatternData + * @property {string} key The key of the pattern + * @property {Matrix} matrix The matrix that gets applied to the pattern right before drawing. + * @property {number[]|undefined} boundingBox Only relevant for tiling patterns. The bounding box at which one + * pattern cell gets clipped + * @property {number|undefined} xStep Only relevant for tiling patterns. Horizontal spacing between pattern cells + * @property {number|undefined} yStep Only relevant for tiling patterns. Vertical spacing between pattern cells + */ + + /** + * Fill the current path using the nonzero winding number rule. If a pattern is provided, the path will be filled + * with this pattern, otherwise with the current fill color. Equivalent to the PDF "f" operator. + * @param {PatternData=} pattern If provided the path will be filled with this pattern + * @return jsPDF + * @methodOf jsPDF# + * @name fill + */ + + + API.fill = function (pattern) { + fillWithOptionalPattern("f", pattern); + return this; + }; + /** + * Fill the current path using the even-odd rule. The PDF f* operator. + * @see API.fill + * @param {PatternData=} pattern Optional pattern + * @return jsPDF + * @methodOf jsPDF# + * @name fillEvenOdd + */ + + + API.fillEvenOdd = function (pattern) { + fillWithOptionalPattern("f*", pattern); + return this; + }; + /** + * Fill using the nonzero winding number rule and then stroke the current Path. The PDF "B" operator. + * @see API.fill + * @param {PatternData=} pattern Optional pattern + * @return jsPDF + * @methodOf jsPDF# + * @name fillStroke + */ + + + API.fillStroke = function (pattern) { + fillWithOptionalPattern("B", pattern); + return this; + }; + /** + * Fill using the even-odd rule and then stroke the current Path. The PDF "B" operator. + * @see API.fill + * @param {PatternData=} pattern Optional pattern + * @return jsPDF + * @methodOf jsPDF# + * @name fillStrokeEvenOdd + */ + + + API.fillStrokeEvenOdd = function (pattern) { + fillWithOptionalPattern("B*", pattern); + return this; + }; + + function fillWithOptionalPattern(style, pattern) { + if (_typeof(pattern) === "object") { + fillWithPattern(pattern, style); + } else { + out(style); + } + } + /** + * Modify the current clip path by intersecting it with the current path using the nonzero winding number rule. Note + * that this will NOT consume the current path. In order to only use this path for clipping call + * {@link API.discardPath} afterwards. + * + * When in "compat" API mode this method has a historical bug and will always stroke the path as well, use + * {@link API.clip_fixed} instead. + * @return jsPDF + * @methodOf jsPDF# + * @name clip + */ + + + API.clip = function () { + if (apiMode === ApiMode.COMPAT) { + // By patrick-roberts, github.com/MrRio/jsPDF/issues/328 + // Call .clip() after calling .rect() with a style argument of null + out("W"); // clip + + out("S"); // stroke path; necessary for clip to work + } else { + out("W"); + } + + return this; + }; + /** + * Modify the current clip path by intersecting it with the current path using the even-odd rule. Note + * that this will NOT consume the current path. In order to only use this path for clipping call + * {@link API.discardPath} afterwards. + * + * @return jsPDF + * @methodOf jsPDF# + * @name clipEvenOdd + */ + + + API.clipEvenOdd = function () { + out("W*"); + return this; + }; + /** + * Consumes the current path without any effect. Mainly used in combination with {@link clip} or + * {@link clipEvenOdd}. The PDF "n" operator. + * @return {jsPDF} + * @methodOf jsPDF# + * @name discardPath + */ + + + API.discardPath = function () { + out("n"); + return this; + }; + /** + * This fixes the previous function clip(). Perhaps the 'stroke path' hack was due to the missing 'n' instruction? + * We introduce the fixed version so as to not break API. + * @param fillRule + * @deprecated Don't use this method when in "advanced" API mode. + * @methodOf jsPDF# + * @name clip_fixed + */ + + + API.clip_fixed = function (fillRule) { + // Call .clip() after calling drawing ops with a style argument of null + // W is the PDF clipping op + if ("evenodd" === fillRule) { + out("W*"); + } else { + out("W"); + } // End the path object without filling or stroking it. + // This operator is a path-painting no-op, used primarily for the side effect of changing the current clipping path + // (see Section 4.4.3, “Clipping Path Operators”) + + + out("n"); + }; + /** + * @typedef {Object} PatternData + * {Matrix|undefined} matrix + * {Number|undefined} xStep + * {Number|undefined} yStep + * {Array.|undefined} boundingBox + */ + + /** + * Adds series of curves (straight lines or cubic bezier curves) to canvas, starting at `x`, `y` coordinates. + * All data points in `lines` are relative to last line origin. + * `x`, `y` become x1,y1 for first line / curve in the set. + * For lines you only need to specify [x2, y2] - (ending point) vector against x1, y1 starting point. + * For bezier curves you need to specify [x2,y2,x3,y3,x4,y4] - vectors to control points 1, 2, ending point. All vectors are against the start of the curve - x1,y1. + * + * @example .lines([[2,2],[-2,2],[1,1,2,2,3,3],[2,1]], 212,110, 10) // line, line, bezier curve, line + * @param {Array} lines Array of *vector* shifts as pairs (lines) or sextets (cubic bezier curves). + * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Number} scale (Defaults to [1.0,1.0]) x,y Scaling factor for all vectors. Elements can be any floating number Sub-one makes drawing smaller. Over-one grows the drawing. Negative flips the direction. + * @param {String=} style A string specifying the painting style or null. Valid styles include: + * 'S' [default] - stroke, + * 'F' - fill, + * and 'DF' (or 'FD') - fill then stroke. + * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple + * method calls. The last drawing method call used to define the shape should not have a null style argument. + * + * In "advanced" API mode this parameter is deprecated. + * @param {Boolean=} closed If true, the path is closed with a straight line from the end of the last curve to the starting point. + * @param {String=} patternKey The pattern key for the pattern that should be used to fill the path. Deprecated! + * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that + * will modify the pattern on use. Deprecated! + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name lines + */ + + + API.lines = function (lines, x, y, scale, style, closed, patternKey, patternData) { + var scalex, scaley, i, l, leg, x2, y2, x3, y3, x4, y4; // Pre-August-2012 the order of arguments was function(x, y, lines, scale, style) + // in effort to make all calls have similar signature like + // function(content, coordinateX, coordinateY , miscellaneous) + // this method had its args flipped. + // code below allows backward compatibility with old arg order. + + if (typeof lines === "number") { + var tmp = y; + y = x; + x = lines; + lines = tmp; + } + + scale = scale || [1, 1]; // starting point + + this.moveTo(x, y); + scalex = scale[0]; + scaley = scale[1]; + l = lines.length; //, x2, y2 // bezier only. In page default measurement "units", *after* scaling + //, x3, y3 // bezier only. In page default measurement "units", *after* scaling + // ending point for all, lines and bezier. . In page default measurement "units", *after* scaling + + x4 = x; // last / ending point = starting point for first item. + + y4 = y; // last / ending point = starting point for first item. + + for (i = 0; i < l; i++) { + leg = lines[i]; + + if (leg.length === 2) { + // simple line + x4 = leg[0] * scalex + x4; // here last x4 was prior ending point + + y4 = leg[1] * scaley + y4; // here last y4 was prior ending point + + this.lineTo(x4, y4); + } else { + // bezier curve + x2 = leg[0] * scalex + x4; // here last x4 is prior ending point + + y2 = leg[1] * scaley + y4; // here last y4 is prior ending point + + x3 = leg[2] * scalex + x4; // here last x4 is prior ending point + + y3 = leg[3] * scaley + y4; // here last y4 is prior ending point + + x4 = leg[4] * scalex + x4; // here last x4 was prior ending point + + y4 = leg[5] * scaley + y4; // here last y4 was prior ending point + + this.curveTo(x2, y2, x3, y3, x4, y4); + } + } + + if (closed) { + this.close(); + } + + putStyle(style, patternKey, patternData); + return this; + }; + /** + * Similar to {@link API.lines} but all coordinates are interpreted as absolute coordinates instead of relative. + * @param {Array} lines An array of {op: operator, c: coordinates} object, where op is one of "m" (move to), "l" (line to) + * "c" (cubic bezier curve) and "h" (close (sub)path)). c is an array of coordinates. "m" and "l" expect two, "c" + * six and "h" an empty array (or undefined). + * @param {String=} style The style. Deprecated! + * @param {String=} patternKey The pattern key for the pattern that should be used to fill the path. Deprecated! + * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that + * will modify the pattern on use. Deprecated! + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name path + */ + + + API.path = function (lines, style, patternKey, patternData) { + for (var i = 0; i < lines.length; i++) { + var leg = lines[i]; + var coords = leg.c; + + switch (leg.op) { + case "m": + this.moveTo(coords[0], coords[1]); + break; + + case "l": + this.lineTo(coords[0], coords[1]); + break; + + case "c": + this.curveTo.apply(this, coords); + break; + + case "h": + this.close(); + break; + } + } + + putStyle(style, patternKey, patternData); + return this; + }; + /** + * Adds a rectangle to PDF + * + * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Number} w Width (in units declared at inception of PDF document) + * @param {Number} h Height (in units declared at inception of PDF document) + * @param {String=} style A string specifying the painting style or null. Valid styles include: + * 'S' [default] - stroke, + * 'F' - fill, + * and 'DF' (or 'FD') - fill then stroke. + * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple + * method calls. The last drawing method call used to define the shape should not have a null style argument. + * + * In "advanced" API mode this parameter is deprecated. + * @param {String=} patternKey The pattern key for the pattern that should be used to fill the primitive. Deprecated! + * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that + * will modify the pattern on use. Deprecated! + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name rect + */ + + + API.rect = function (x, y, w, h, style, patternKey, patternData) { + if (apiMode === ApiMode.COMPAT) { + h = -h; + } + + out([hpf(scaleByK(x)), hpf(transformScaleY(y)), hpf(scaleByK(w)), hpf(scaleByK(h)), "re"].join(" ")); + putStyle(style, patternKey, patternData); + return this; + }; + /** + * Adds a triangle to PDF + * + * @param {Number} x1 Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y1 Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Number} x2 Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y2 Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Number} x3 Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y3 Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {String=} style A string specifying the painting style or null. Valid styles include: + * 'S' [default] - stroke, + * 'F' - fill, + * and 'DF' (or 'FD') - fill then stroke. + * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple + * method calls. The last drawing method call used to define the shape should not have a null style argument. + * + * In "advanced" API mode this parameter is deprecated. + * @param {String=} patternKey The pattern key for the pattern that should be used to fill the primitive. Deprecated! + * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that + * will modify the pattern on use. Deprecated! + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name triangle + */ + + + API.triangle = function (x1, y1, x2, y2, x3, y3, style, patternKey, patternData) { + this.lines([[x2 - x1, y2 - y1], // vector to point 2 + [x3 - x2, y3 - y2], // vector to point 3 + [x1 - x3, y1 - y3] // closing vector back to point 1 + ], x1, y1, // start of path + [1, 1], style, true, patternKey, patternData); + return this; + }; + /** + * Adds a rectangle with rounded corners to PDF + * + * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Number} w Width (in units declared at inception of PDF document) + * @param {Number} h Height (in units declared at inception of PDF document) + * @param {Number} rx Radius along x axis (in units declared at inception of PDF document) + * @param {Number} ry Radius along y axis (in units declared at inception of PDF document) + * @param {String=} style A string specifying the painting style or null. Valid styles include: + * 'S' [default] - stroke, + * 'F' - fill, + * and 'DF' (or 'FD') - fill then stroke. + * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple + * method calls. The last drawing method call used to define the shape should not have a null style argument. + * + * In "advanced" API mode this parameter is deprecated. + * @param {String=} patternKey The pattern key for the pattern that should be used to fill the primitive. Deprecated! + * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that + * will modify the pattern on use. Deprecated! + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name roundedRect + */ + + + API.roundedRect = function (x, y, w, h, rx, ry, style, patternKey, patternData) { + var MyArc = 4 / 3 * (Math.SQRT2 - 1); + rx = Math.min(rx, w * 0.5); + ry = Math.min(ry, h * 0.5); + this.lines([[w - 2 * rx, 0], [rx * MyArc, 0, rx, ry - ry * MyArc, rx, ry], [0, h - 2 * ry], [0, ry * MyArc, -(rx * MyArc), ry, -rx, ry], [-w + 2 * rx, 0], [-(rx * MyArc), 0, -rx, -(ry * MyArc), -rx, -ry], [0, -h + 2 * ry], [0, -(ry * MyArc), rx * MyArc, -ry, rx, -ry]], x + rx, y, // start of path + [1, 1], style, true, patternKey, patternData); + return this; + }; + /** + * Adds an ellipse to PDF + * + * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Number} rx Radius along x axis (in units declared at inception of PDF document) + * @param {Number} ry Radius along y axis (in units declared at inception of PDF document) + * @param {String=} style A string specifying the painting style or null. Valid styles include: + * 'S' [default] - stroke, + * 'F' - fill, + * and 'DF' (or 'FD') - fill then stroke. + * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple + * method calls. The last drawing method call used to define the shape should not have a null style argument. + * + * In "advanced" API mode this parameter is deprecated. + * @param {String=} patternKey The pattern key for the pattern that should be used to fill the primitive. Deprecated! + * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that + * will modify the pattern on use. Deprecated! + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name ellipse + */ + + + API.ellipse = function (x, y, rx, ry, style, patternKey, patternData) { + var lx = 4 / 3 * (Math.SQRT2 - 1) * rx, + ly = 4 / 3 * (Math.SQRT2 - 1) * ry; + this.moveTo(x + rx, y); + this.curveTo(x + rx, y - ly, x + lx, y - ry, x, y - ry); + this.curveTo(x - lx, y - ry, x - rx, y - ly, x - rx, y); + this.curveTo(x - rx, y + ly, x - lx, y + ry, x, y + ry); + this.curveTo(x + lx, y + ry, x + rx, y + ly, x + rx, y); + putStyle(style, patternKey, patternData); + return this; + }; + /** + * Adds an circle to PDF + * + * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Number} r Radius (in units declared at inception of PDF document) + * @param {String=} style A string specifying the painting style or null. Valid styles include: + * 'S' [default] - stroke, + * 'F' - fill, + * and 'DF' (or 'FD') - fill then stroke. + * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple + * method calls. The last drawing method call used to define the shape should not have a null style argument. + * + * In "advanced" API mode this parameter is deprecated. + * @param {String=} patternKey The pattern key for the pattern that should be used to fill the primitive. Deprecated! + * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that + * will modify the pattern on use. Deprecated! + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name circle + */ + + + API.circle = function (x, y, r, style, patternKey, patternData) { + return this.ellipse(x, y, r, r, style, patternKey, patternData); + }; + /** + * Adds a properties to the PDF document + * + * @param {Object} properties A property_name-to-property_value object structure. + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setProperties + */ + + + API.setProperties = function (properties) { + // copying only those properties we can render. + for (var property in documentProperties) { + if (documentProperties.hasOwnProperty(property) && properties[property]) { + documentProperties[property] = properties[property]; + } + } + + return this; + }; + /** + * Sets font size for upcoming text elements. + * + * @param {number} size Font size in points. + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setFontSize + */ + + + API.setFontSize = function (size) { + // convert font size into current unit system + if (apiMode === ApiMode.ADVANCED) { + activeFontSize = size / k; + } else { + activeFontSize = size; + } + + out("/" + activeFontKey + " " + activeFontSize + " Tf"); + return this; + }; + /** + * @return {number} + * @methodOf jsPDF# + * @name getFontSize + */ + + + API.getFontSize = function () { + if (apiMode === ApiMode.COMPAT) { + return activeFontSize; + } else { + return activeFontSize * k; + } + }; + /** + * Sets text font face, variant for upcoming text elements. + * See output of jsPDF.getFontList() for possible font names, styles. + * + * @param {string} fontName Font name or family. Example: "times" + * @param {string} fontStyle Font style or variant. Example: "italic" + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setFont + */ + + + API.setFont = function (fontName, fontStyle) { + activeFontKey = _getFont(fontName, fontStyle); // if font is not found, the above line blows up and we never go further + + out("/" + activeFontKey + " " + activeFontSize + " Tf"); + return this; + }; + /** + * Switches font style or variant for upcoming text elements, + * while keeping the font face or family same. + * See output of jsPDF.getFontList() for possible font names, styles. + * + * @param {string} style Font style or variant. Example: "italic" + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setFontStyle + */ + + + API.setFontStyle = API.setFontType = function (style) { + activeFontKey = _getFont(undefined, style); // if font is not found, the above line blows up and we never go further + + out("/" + activeFontKey + " " + activeFontSize + " Tf"); + return this; + }; + /** + * Returns an object - a tree of fontName to fontStyle relationships available to + * active PDF document. + * + * @public + * @function + * @instance + * @returns {Object} Like {'times':['normal', 'italic', ... ], 'arial':['normal', 'bold', ... ], ... } + * @methodOf jsPDF# + * @name getFontList + */ + + + API.getFontList = function () { + // TODO: iterate over fonts array or return copy of fontmap instead in case more are ever added. + var list = {}, + fontName, + fontStyle, + tmp; + + for (fontName in fontmap) { + if (fontmap.hasOwnProperty(fontName)) { + list[fontName] = tmp = []; + + for (fontStyle in fontmap[fontName]) { + if (fontmap[fontName].hasOwnProperty(fontStyle)) { + tmp.push(fontStyle); + } + } + } + } + + return list; + }; + /** + * Add a custom font to the current instance. + * + * @param {String} postScriptName name of the Font. Example: "Menlo-Regular" + * @param {String} fontName of font-family from @font-face definition. Example: "Menlo Regular" + * @param {String} fontStyle style. Example: "normal" + * @function + * @instance + * @methodOf jsPDF + * @name addFont + */ + + + API.addFont = function (postScriptName, fontName, fontStyle, encoding) { + encoding = encoding || "Identity-H"; + addFont.call(this, postScriptName, fontName, fontStyle, encoding); + }; + /** + * Sets line width for upcoming lines. + * + * @param {number} width Line width (in units declared at inception of PDF document) + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setLineWidth + */ + + + API.setLineWidth = function (width) { + out(scaleByK(width).toFixed(2) + " w"); + return this; + }; + /** + * Sets the stroke color for upcoming elements. + * + * Depending on the number of arguments given, Gray, RGB, or CMYK + * color space is implied. + * + * When only ch1 is given, "Gray" color space is implied and it + * must be a value in the range from 0.00 (solid black) to to 1.00 (white) + * if values are communicated as String types, or in range from 0 (black) + * to 255 (white) if communicated as Number type. + * The RGB-like 0-255 range is provided for backward compatibility. + * + * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each + * value must be in the range from 0.00 (minimum intensity) to to 1.00 + * (max intensity) if values are communicated as String types, or + * from 0 (min intensity) to to 255 (max intensity) if values are communicated + * as Number types. + * The RGB-like 0-255 range is provided for backward compatibility. + * + * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each + * value must be a in the range from 0.00 (0% concentration) to to + * 1.00 (100% concentration) + * + * Because JavaScript treats fixed point numbers badly (rounds to + * floating point nearest to binary representation) it is highly advised to + * communicate the fractional numbers as String types, not JavaScript Number type. + * + * @param {Number|String} ch1 Color channel value or {string} ch1 color value in hexadecimal, example: '#FFFFFF' + * @param {Number|String} ch2 Color channel value + * @param {Number|String} ch3 Color channel value + * @param {Number|String} ch4 Color channel value + * + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setDrawColor + */ + + + API.setDrawColor = function (ch1, ch2, ch3, ch4) { + var options = { + ch1: ch1, + ch2: ch2, + ch3: ch3, + ch4: ch4, + pdfColorType: "draw", + precision: 2 + }; + out(generateColorString(options)); + return this; + }; + /** + * Sets the fill color for upcoming elements. + * + * Depending on the number of arguments given, Gray, RGB, or CMYK + * color space is implied. + * + * When only ch1 is given, "Gray" color space is implied and it + * must be a value in the range from 0.00 (solid black) to to 1.00 (white) + * if values are communicated as String types, or in range from 0 (black) + * to 255 (white) if communicated as Number type. + * The RGB-like 0-255 range is provided for backward compatibility. + * + * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each + * value must be in the range from 0.00 (minimum intensity) to to 1.00 + * (max intensity) if values are communicated as String types, or + * from 0 (min intensity) to to 255 (max intensity) if values are communicated + * as Number types. + * The RGB-like 0-255 range is provided for backward compatibility. + * + * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each + * value must be a in the range from 0.00 (0% concentration) to to + * 1.00 (100% concentration) + * + * Because JavaScript treats fixed point numbers badly (rounds to + * floating point nearest to binary representation) it is highly advised to + * communicate the fractional numbers as String types, not JavaScript Number type. + * + * @param {Number|String} ch1 Color channel value or {string} ch1 color value in hexadecimal, example: '#FFFFFF' + * @param {Number|String} ch2 Color channel value + * @param {Number|String} ch3 Color channel value + * @param {Number|String} ch4 Color channel value + * + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setFillColor + */ + + + API.setFillColor = function (ch1, ch2, ch3, ch4) { + var options = { + ch1: ch1, + ch2: ch2, + ch3: ch3, + ch4: ch4, + pdfColorType: "fill", + precision: 2 + }; + out(generateColorString(options)); + return this; + }; + /** + * Sets the text color for upcoming elements. + * + * Depending on the number of arguments given, Gray, RGB, or CMYK + * color space is implied. + * + * When only ch1 is given, "Gray" color space is implied and it + * must be a value in the range from 0.00 (solid black) to to 1.00 (white) + * if values are communicated as String types, or in range from 0 (black) + * to 255 (white) if communicated as Number type. + * The RGB-like 0-255 range is provided for backward compatibility. + * + * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each + * value must be in the range from 0.00 (minimum intensity) to to 1.00 + * (max intensity) if values are communicated as String types, or + * from 0 (min intensity) to to 255 (max intensity) if values are communicated + * as Number types. + * The RGB-like 0-255 range is provided for backward compatibility. + * + * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each + * value must be a in the range from 0.00 (0% concentration) to to + * 1.00 (100% concentration) + * + * Because JavaScript treats fixed point numbers badly (rounds to + * floating point nearest to binary representation) it is highly advised to + * communicate the fractional numbers as String types, not JavaScript Number type. + * + * @param {Number|String} ch1 Color channel value or {string} ch1 color value in hexadecimal, example: '#FFFFFF' + * @param {Number|String} ch2 Color channel value + * @param {Number|String} ch3 Color channel value + * @param {Number|String} ch4 Color channel value + * + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setTextColor + */ + + + API.setTextColor = function (ch1, ch2, ch3, ch4) { + var options = { + ch1: ch1, + ch2: ch2, + ch3: ch3, + ch4: ch4, + pdfColorType: "text", + precision: 3 + }; + textColor = generateColorString(options); + return this; + }; + /** + * Initializes the default character set that the user wants to be global.. + * + * @param {number} charSpace + * @function + * @instance + * @returns {jsPDF} jsPDF-instance + * @methodOf jsPDF + * @name setCharSpace + */ + + + API.setCharSpace = function (charSpace) { + if (apiMode === ApiMode.COMPAT) { + activeCharSpace = charSpace; + } else if (apiMode === ApiMode.ADVANCED) { + activeCharSpace = charSpace / k; + } + + return this; + }; + /** + * Initializes the default character set that the user wants to be global.. + * + * @param {boolean} boolean + * @function + * @instance + * @returns {jsPDF} jsPDF-instance + * @methodOf jsPDF + * @name setR2L + */ + + + API.setR2L = function (boolean) { + R2L = boolean; + return this; + }; + /** + * Sets a either previously added {@link GState} (via {@link addGState}) or a new {@link GState}. + * @param {String|GState} gState If type is string, a previously added GState is used, if type is GState + * it will be added before use. + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setGState + */ + + + API.setGState = function (gState) { + if (typeof gState === "string") { + gState = gStates[gStatesMap[gState]]; + } else { + gState = addGState(null, gState); + } + + if (!gState.equals(activeGState)) { + out("/" + gState.id + " gs"); + activeGState = gState; + } + }; + /** + * Is an Object providing a mapping from human-readable to + * integer flag values designating the varieties of line cap + * and join styles. + * + * @fieldOf jsPDF# + * @name CapJoinStyles + */ + + + API.CapJoinStyles = { + 0: 0, + butt: 0, + but: 0, + miter: 0, + 1: 1, + round: 1, + rounded: 1, + circle: 1, + 2: 2, + projecting: 2, + project: 2, + square: 2, + bevel: 2 + }; + /** + * Sets the line cap styles + * See {jsPDF.CapJoinStyles} for variants + * + * @param {String|Number} style A string or number identifying the type of line cap + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setLineCap + */ + + API.setLineCap = function (style) { + var id = this.CapJoinStyles[style]; + + if (id === undefined) { + throw new Error("Line cap style of '" + style + "' is not recognized. See or extend .CapJoinStyles property for valid styles"); + } + + lineCapID = id; + out(id + " J"); + return this; + }; + /** + * Sets the line join styles + * See {jsPDF.CapJoinStyles} for variants + * + * @param {String|Number} style A string or number identifying the type of line join + * @function + * @instance + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setLineJoin + */ + + + API.setLineJoin = function (style) { + var id = this.CapJoinStyles[style]; + + if (id === undefined) { + throw new Error("Line join style of '" + style + "' is not recognized. See or extend .CapJoinStyles property for valid styles"); + } + + lineJoinID = id; + out(id + " j"); + return this; + }; + /** + * Sets the miter limit. + * @param {number} miterLimit + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setMiterLimit + */ + + + API.setLineMiterLimit = function (miterLimit) { + out(hpf(miterLimit) + " M"); + return this; + }; + /** + * Sets the line dash pattern. + * @param {Array} array An array containing 0-2 numbers. The first number sets the length of the + * dashes, the second number the length of the gaps. If the second number is missing, the gaps are considered + * to be as long as the dashes. An empty array means solid, unbroken lines. + * @param phase The phase lines start with. + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setLineDashPattern + */ + + + API.setLineDashPattern = function (array, phase) { + out(["[" + (array[0] !== undefined ? array[0] : ""), (array[1] !== undefined ? array[1] : "") + "]", phase, "d"].join(" ")); + return this; + }; + /** + * Generates the PDF document. + * + * If `type` argument is undefined, output is raw body of resulting PDF returned as a string. + * + * @param {string} type A string identifying one of the possible output types. + * @param {Object} options An object providing some additional signalling to PDF generator. + * + * @function + * @instance + * @returns {jsPDF} + * @memberOf jsPDF + * @name output + */ + + + API.output = _output; + /** + * Saves as PDF document. An alias of jsPDF.output('save', 'filename.pdf') + * + * @memberOf jsPDF + * @name save + * @function + * @instance + * @param {string} filename The filename including extension. + * @returns {jsPDF} jsPDF-instance + */ + + API.save = function (filename) { + API.output("save", filename); + }; // applying plugins (more methods) ON TOP of built-in API. + // this is intentional as we allow plugins to override + // built-ins + + + for (var plugin in jsPDF.API) { + if (jsPDF.API.hasOwnProperty(plugin)) { + if (plugin === "events" && jsPDF.API.events.length) { + (function (events, newEvents) { + // jsPDF.API.events is a JS Array of Arrays + // where each Array is a pair of event name, handler + // Events were added by plugins to the jsPDF instantiator. + // These are always added to the new instance and some ran + // during instantiation. + var eventname, handler_and_args, i; + + for (i = newEvents.length - 1; i !== -1; i--) { + // subscribe takes 3 args: 'topic', function, runonce_flag + // if undefined, runonce is false. + // users can attach callback directly, + // or they can attach an array with [callback, runonce_flag] + // that's what the "apply" magic is for below. + eventname = newEvents[i][0]; + handler_and_args = newEvents[i][1]; + events.subscribe.apply(events, [eventname].concat(typeof handler_and_args === "function" ? [handler_and_args] : handler_and_args)); + } + })(events, jsPDF.API.events); + } else { + API[plugin] = jsPDF.API[plugin]; + } + } + } ////////////////////////////////////////////////////// + // continuing initialization of jsPDF Document object + ////////////////////////////////////////////////////// + // Add the first page automatically + + + addFonts(); + activeFontKey = "F1"; + + _addPage(format, orientation); + + events.publish("initialized"); + return API; + } + /** + * jsPDF.API is a STATIC property of jsPDF class. + * jsPDF.API is an object you can add methods and properties to. + * The methods / properties you add will show up in new jsPDF objects. + * + * One property is prepopulated. It is the 'events' Object. Plugin authors can add topics, + * callbacks to this object. These will be reassigned to all new instances of jsPDF. + * + * @static + * @public + * @memberOf jsPDF + * @name API + * + * @example + * jsPDF.API.mymethod = function(){ + * // 'this' will be ref to internal API object. see jsPDF source + * // , so you can refer to built-in methods like so: + * // this.line(....) + * // this.text(....) + * } + * var pdfdoc = new jsPDF() + * pdfdoc.mymethod() // <- !!!!!! + */ + + + jsPDF.API = { + events: [] + }; + /** + * The version of jsPDF + * @name version + * @type {string} + * @memberOf jsPDF + */ + + jsPDF.version = "0.0.0"; + + if (typeof define === "function" && define.amd) { + define(function () { + return jsPDF; + }); + } else if (typeof module !== "undefined" && module.exports) { + module.exports = jsPDF; + module.exports.jsPDF = jsPDF; + } else { + global.jsPDF = jsPDF; + } + + return jsPDF; + }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function("return this")()); // `self` is undefined in Firefox for Android content script context + // while `this` is nsIContentFrameMessageManager + // with an attribute `content` that corresponds to the window + + /** + * @license + * Copyright (c) 2016 Alexander Weidt, + * https://github.com/BiggA94 + * + * Licensed under the MIT License. http://opensource.org/licenses/mit-license + */ + + /** + * jsPDF AcroForm Plugin + * + * @name AcroForm + * @module + */ + (function (jsPDFAPI, globalObj) { + + var scope; + var pageHeight; + var scaleFactor = 1; + + var inherit = function inherit(child, parent) { + + child.prototype = Object.create(parent.prototype); + child.prototype.constructor = child; + }; + + var scale = function scale(x) { + return x * (scaleFactor / 1); // 1 = (96 / 72) + }; + + var createFormXObject = function createFormXObject(formObject) { + var xobj = new AcroFormXObject(); + var height = AcroFormAppearance.internal.getHeight(formObject) || 0; + var width = AcroFormAppearance.internal.getWidth(formObject) || 0; + xobj.BBox = [0, 0, width.toFixed(2), height.toFixed(2)]; + return xobj; + }; + + var setBitPosition = function setBitPosition(variable, position, value) { + variable = variable || 0; + value = value || 1; + var bitMask = 1; + bitMask = bitMask << position - 1; + + if (value == 1) { + // Set the Bit to 1 + var variable = variable | bitMask; + } else { + // Set the Bit to 0 + var variable = variable & ~bitMask; + } + + return variable; + }; + /** + * Calculating the Ff entry: + * + * The Ff entry contains flags, that have to be set bitwise In the Following + * the number in the Comment is the BitPosition + */ + + + var calculateFlagsOnOptions = function calculateFlagsOnOptions(flags, opts, PDFVersion) { + var PDFVersion = PDFVersion || 1.3; + var flags = flags || 0; // 1, readOnly + + if (opts.readOnly == true) { + flags = setBitPosition(flags, 1); + } // 2, required + + + if (opts.required == true) { + flags = setBitPosition(flags, 2); + } // 4, noExport + + + if (opts.noExport == true) { + flags = setBitPosition(flags, 3); + } // 13, multiline + + + if (opts.multiline == true) { + flags = setBitPosition(flags, 13); + } // 14, Password + + + if (opts.password) { + flags = setBitPosition(flags, 14); + } // 15, NoToggleToOff (Radio buttons only + + + if (opts.noToggleToOff) { + flags = setBitPosition(flags, 15); + } // 16, Radio + + + if (opts.radio) { + flags = setBitPosition(flags, 16); + } // 17, Pushbutton + + + if (opts.pushbutton) { + flags = setBitPosition(flags, 17); + } // 18, Combo (If not set, the choiceField is a listBox!!) + + + if (opts.combo) { + flags = setBitPosition(flags, 18); + } // 19, Edit + + + if (opts.edit) { + flags = setBitPosition(flags, 19); + } // 20, Sort + + + if (opts.sort) { + flags = setBitPosition(flags, 20); + } // 21, FileSelect, PDF 1.4... + + + if (opts.fileSelect && PDFVersion >= 1.4) { + flags = setBitPosition(flags, 21); + } // 22, MultiSelect (PDF 1.4) + + + if (opts.multiSelect && PDFVersion >= 1.4) { + flags = setBitPosition(flags, 22); + } // 23, DoNotSpellCheck (PDF 1.4) + + + if (opts.doNotSpellCheck && PDFVersion >= 1.4) { + flags = setBitPosition(flags, 23); + } // 24, DoNotScroll (PDF 1.4) + + + if (opts.doNotScroll == true && PDFVersion >= 1.4) { + flags = setBitPosition(flags, 24); + } // 25, RichText (PDF 1.4) + + + if (opts.richText && PDFVersion >= 1.4) { + flags = setBitPosition(flags, 25); + } + + return flags; + }; + + var calculateCoordinates = function calculateCoordinates(args) { + var x = args[0]; + var y = args[1]; + var w = args[2]; + var h = args[3]; + var coordinates = {}; + + if (Array.isArray(x)) { + x[0] = scale(x[0]); + x[1] = scale(x[1]); + x[2] = scale(x[2]); + x[3] = scale(x[3]); + } else { + x = scale(x); + y = scale(y); + w = scale(w); + h = scale(h); + } + + coordinates.lowerLeft_X = x || 0; + coordinates.lowerLeft_Y = scale(pageHeight) - y - h || 0; + coordinates.upperRight_X = x + w || 0; + coordinates.upperRight_Y = scale(pageHeight) - y || 0; + return [coordinates.lowerLeft_X.toFixed(2), coordinates.lowerLeft_Y.toFixed(2), coordinates.upperRight_X.toFixed(2), coordinates.upperRight_Y.toFixed(2)]; + }; + + var calculateAppearanceStream = function calculateAppearanceStream(formObject) { + if (formObject.appearanceStreamContent) { + // If appearanceStream is already set, use it + return formObject.appearanceStreamContent; + } + + if (!formObject.V && !formObject.DV) { + return; + } // else calculate it + + + var stream = []; + var text = formObject.V || formObject.DV; + var calcRes = calculateX(formObject, text); + stream.push("/Tx BMC"); + stream.push("q"); + stream.push("/F1 " + calcRes.fontSize.toFixed(2) + " Tf"); + stream.push("1 0 0 1 0 0 Tm"); // Text Matrix + + stream.push("BT"); // Begin Text + + stream.push(calcRes.text); + stream.push("ET"); // End Text + + stream.push("Q"); + stream.push("EMC"); + var appearanceStreamContent = new createFormXObject(formObject); + appearanceStreamContent.stream = stream.join("\n"); + return appearanceStreamContent; + }; + + var calculateX = function calculateX(formObject, text, font, maxFontSize) { + var maxFontSize = maxFontSize || 12; + var font = font || "helvetica"; + var returnValue = { + text: "", + fontSize: "" + }; // Remove Brackets + + text = text.substr(0, 1) == "(" ? text.substr(1) : text; + text = text.substr(text.length - 1) == ")" ? text.substr(0, text.length - 1) : text; // split into array of words + + var textSplit = text.split(" "); + var fontSize = maxFontSize; // The Starting fontSize (The Maximum) + + var lineSpacing = 2; + var borderPadding = 2; + var height = AcroFormAppearance.internal.getHeight(formObject) || 0; + height = height < 0 ? -height : height; + var width = AcroFormAppearance.internal.getWidth(formObject) || 0; + width = width < 0 ? -width : width; + + var isSmallerThanWidth = function isSmallerThanWidth(i, lastLine, fontSize) { + if (i + 1 < textSplit.length) { + var tmp = lastLine + " " + textSplit[i + 1]; + var TextWidth = calculateFontSpace(tmp, fontSize + "px", font).width; + var FieldWidth = width - 2 * borderPadding; + return TextWidth <= FieldWidth; + } else { + return false; + } + }; + + fontSize++; + + FontSize: while (true) { + var text = ""; + fontSize--; + var textHeight = calculateFontSpace("3", fontSize + "px", font).height; + var startY = formObject.multiline ? height - fontSize : (height - textHeight) / 2; + startY += lineSpacing; + var startX = -borderPadding; + var lastY = startY; + var firstWordInLine = 0, + lastWordInLine = 0; + var lastLength = 0; + + if (fontSize <= 0) { + // In case, the Text doesn't fit at all + fontSize = 12; + text = "(...) Tj\n"; + text += "% Width of Text: " + calculateFontSpace(text, "1px").width + ", FieldWidth:" + width + "\n"; + break; + } + + lastLength = calculateFontSpace(textSplit[0] + " ", fontSize + "px", font).width; + var lastLine = ""; + var lineCount = 0; + + Line: for (var i in textSplit) { + if (textSplit.hasOwnProperty(i)) { + lastLine += textSplit[i] + " "; // Remove last blank + + lastLine = lastLine.substr(lastLine.length - 1) == " " ? lastLine.substr(0, lastLine.length - 1) : lastLine; + var key = parseInt(i); + lastLength = calculateFontSpace(lastLine + " ", fontSize + "px", font).width; + var nextLineIsSmaller = isSmallerThanWidth(key, lastLine, fontSize); + var isLastWord = i >= textSplit.length - 1; + + if (nextLineIsSmaller && !isLastWord) { + lastLine += " "; + continue; // Line + } else if (!nextLineIsSmaller && !isLastWord) { + if (!formObject.multiline) { + continue FontSize; + } else { + if ((textHeight + lineSpacing) * (lineCount + 2) + lineSpacing > height) { + // If the Text is higher than the + // FieldObject + continue FontSize; + } + + lastWordInLine = key; // go on + } + } else if (isLastWord) { + lastWordInLine = key; + } else { + if (formObject.multiline && (textHeight + lineSpacing) * (lineCount + 2) + lineSpacing > height) { + // If the Text is higher than the FieldObject + continue FontSize; + } + } + + var line = ""; + + for (var x = firstWordInLine; x <= lastWordInLine; x++) { + line += textSplit[x] + " "; + } // Remove last blank + + + line = line.substr(line.length - 1) == " " ? line.substr(0, line.length - 1) : line; // lastLength -= blankSpace.width; + + lastLength = calculateFontSpace(line, fontSize + "px", font).width; // Calculate startX + + switch (formObject.Q) { + case 2: + // Right justified + startX = width - lastLength - borderPadding; + break; + + case 1: + // Q = 1 := Text-Alignment: Center + startX = (width - lastLength) / 2; + break; + + case 0: + default: + startX = borderPadding; + break; + } + + text += startX.toFixed(2) + " " + lastY.toFixed(2) + " Td\n"; + text += "(" + line + ") Tj\n"; // reset X in PDF + + text += -startX.toFixed(2) + " 0 Td\n"; // After a Line, adjust y position + + lastY = -(fontSize + lineSpacing); + + lastLength = 0; + firstWordInLine = lastWordInLine + 1; + lineCount++; + lastLine = ""; + continue Line; + } + } + + break; + } + + returnValue.text = text; + returnValue.fontSize = fontSize; + return returnValue; + }; + /** + * Small workaround for calculating the TextMetric approximately. + * + * @param text + * @param fontsize + * @returns {TextMetrics} (Has Height and Width) + */ + + + var calculateFontSpace = function calculateFontSpace(text, fontSize, fontType) { + fontType = fontType || "helvetica"; + var font = scope.internal.getFont(fontType); + var width = scope.getStringUnitWidth(text, { + font: font, + fontSize: parseFloat(fontSize), + charSpace: 0 + }) * parseFloat(fontSize); + var height = scope.getStringUnitWidth("3", { + font: font, + fontSize: parseFloat(fontSize), + charSpace: 0 + }) * parseFloat(fontSize) * 1.5; + var result = { + height: height, + width: width + }; + return result; + }; + + var acroformPluginTemplate = { + fields: [], + xForms: [], + + /** + * acroFormDictionaryRoot contains information about the AcroForm + * Dictionary 0: The Event-Token, the AcroFormDictionaryCallback has + * 1: The Object ID of the Root + */ + acroFormDictionaryRoot: null, + + /** + * After the PDF gets evaluated, the reference to the root has to be + * reset, this indicates, whether the root has already been printed + * out + */ + printedOut: false, + internal: null, + isInitialized: false + }; + + var annotReferenceCallback = function annotReferenceCallback() { + var fields = scope.internal.acroformPlugin.acroFormDictionaryRoot.Fields; + + for (var i in fields) { + if (fields.hasOwnProperty(i)) { + var formObject = fields[i]; // add Annot Reference! + + if (formObject.hasAnnotation) { + // If theres an Annotation Widget in the Form Object, put the + // Reference in the /Annot array + createAnnotationReference.call(scope, formObject); + } + } + } + }; + + var putForm = function putForm(formObject) { + if (scope.internal.acroformPlugin.printedOut) { + scope.internal.acroformPlugin.printedOut = false; + scope.internal.acroformPlugin.acroFormDictionaryRoot = null; + } + + if (!scope.internal.acroformPlugin.acroFormDictionaryRoot) { + initializeAcroForm.call(scope); + } + + scope.internal.acroformPlugin.acroFormDictionaryRoot.Fields.push(formObject); + }; + /** + * Create the Reference to the widgetAnnotation, so that it gets referenced + * in the Annot[] int the+ (Requires the Annotation Plugin) + */ + + + var createAnnotationReference = function createAnnotationReference(object) { + var options = { + type: "reference", + object: object + }; + scope.annotationPlugin.annotations[scope.internal.getPageInfo(object.page).pageNumber].push(options); + }; // Callbacks + + + var putCatalogCallback = function putCatalogCallback() { + // Put reference to AcroForm to DocumentCatalog + if (typeof scope.internal.acroformPlugin.acroFormDictionaryRoot != "undefined") { + // for safety, shouldn't normally be the case + scope.internal.write("/AcroForm " + scope.internal.acroformPlugin.acroFormDictionaryRoot.objId + " " + 0 + " R"); + } else { + console.log("Root missing..."); + } + }; + /** + * Adds /Acroform X 0 R to Document Catalog, and creates the AcroForm + * Dictionary + */ + + + var AcroFormDictionaryCallback = function AcroFormDictionaryCallback() { + // Remove event + scope.internal.events.unsubscribe(scope.internal.acroformPlugin.acroFormDictionaryRoot._eventID); + delete scope.internal.acroformPlugin.acroFormDictionaryRoot._eventID; + scope.internal.acroformPlugin.printedOut = true; + }; + /** + * Creates the single Fields and writes them into the Document + * + * If fieldArray is set, use the fields that are inside it instead of the + * fields from the AcroRoot (for the FormXObjects...) + */ + + + var createFieldCallback = function createFieldCallback(fieldArray) { + var standardFields = !fieldArray; + + if (!fieldArray) { + // in case there is no fieldArray specified, we want to print out + // the Fields of the AcroForm + // Print out Root + scope.internal.newObjectDeferredBegin(scope.internal.acroformPlugin.acroFormDictionaryRoot.objId); + scope.internal.out(scope.internal.acroformPlugin.acroFormDictionaryRoot.getString()); + } + + var fieldArray = fieldArray || scope.internal.acroformPlugin.acroFormDictionaryRoot.Kids; + + for (var i in fieldArray) { + if (fieldArray.hasOwnProperty(i)) { + var form = fieldArray[i]; + var oldRect = form.Rect; + + if (form.Rect) { + form.Rect = calculateCoordinates.call(this, form.Rect); + } // Start Writing the Object + + + scope.internal.newObjectDeferredBegin(form.objId); + var content = form.objId + " 0 obj\n<<\n"; + + if (_typeof(form) === "object" && typeof form.getContent === "function") { + content += form.getContent(); + } + + form.Rect = oldRect; + + if (form.hasAppearanceStream && !form.appearanceStreamContent) { + // Calculate Appearance + var appearance = calculateAppearanceStream.call(this, form); + content += "/AP << /N " + appearance + " >>\n"; + scope.internal.acroformPlugin.xForms.push(appearance); + } // Assume AppearanceStreamContent is a Array with N,R,D (at least + // one of them!) + + + if (form.appearanceStreamContent) { + content += "/AP << "; // Iterate over N,R and D + + for (var k in form.appearanceStreamContent) { + if (form.appearanceStreamContent.hasOwnProperty(k)) { + var value = form.appearanceStreamContent[k]; + content += "/" + k + " "; + content += "<< "; + + if (Object.keys(value).length >= 1 || Array.isArray(value)) { + // appearanceStream is an Array or Object! + for (var i in value) { + if (value.hasOwnProperty(i)) { + var obj = value[i]; + + if (typeof obj === "function") { + // if Function is referenced, call it in order + // to get the FormXObject + obj = obj.call(this, form); + } + + content += "/" + i + " " + obj + " "; // In case the XForm is already used, e.g. OffState + // of CheckBoxes, don't add it + + if (!(scope.internal.acroformPlugin.xForms.indexOf(obj) >= 0)) scope.internal.acroformPlugin.xForms.push(obj); + } + } + } else { + var obj = value; + + if (typeof obj === "function") { + // if Function is referenced, call it in order to + // get the FormXObject + obj = obj.call(this, form); + } + + content += "/" + i + " " + obj + " \n"; + if (!(scope.internal.acroformPlugin.xForms.indexOf(obj) >= 0)) scope.internal.acroformPlugin.xForms.push(obj); + } + + content += " >>\n"; + } + } // appearance stream is a normal Object.. + + + content += ">>\n"; + } + + content += ">>\nendobj\n"; + scope.internal.out(content); + } + } + + if (standardFields) { + createXFormObjectCallback.call(this, scope.internal.acroformPlugin.xForms); + } + }; + + var createXFormObjectCallback = function createXFormObjectCallback(fieldArray) { + for (var i in fieldArray) { + if (fieldArray.hasOwnProperty(i)) { + var key = i; + var form = fieldArray[i]; // Start Writing the Object + + scope.internal.newObjectDeferredBegin(form && form.objId); + var content = ""; + + if (_typeof(form) === "object" && typeof form.getString === "function") { + content = form.getString(); + } + + scope.internal.out(content); + delete fieldArray[key]; + } + } + }; + + var initializeAcroForm = function initializeAcroForm() { + if (this.internal !== undefined && (this.internal.acroformPlugin === undefined || this.internal.acroformPlugin.isInitialized === false)) { + scope = this; + AcroFormField.FieldNum = 0; + this.internal.acroformPlugin = JSON.parse(JSON.stringify(acroformPluginTemplate)); + + if (this.internal.acroformPlugin.acroFormDictionaryRoot) { + // return; + throw new Error("Exception while creating AcroformDictionary"); + } + + scaleFactor = scope.internal.scaleFactor; + pageHeight = scope.internal.pageSize.getHeight(); // The Object Number of the AcroForm Dictionary + + scope.internal.acroformPlugin.acroFormDictionaryRoot = new AcroFormDictionary(); // add Callback for creating the AcroForm Dictionary + + scope.internal.acroformPlugin.acroFormDictionaryRoot._eventID = scope.internal.events.subscribe("postPutResources", AcroFormDictionaryCallback); + scope.internal.events.subscribe("buildDocument", annotReferenceCallback); // buildDocument + // Register event, that is triggered when the DocumentCatalog is + // written, in order to add /AcroForm + + scope.internal.events.subscribe("putCatalog", putCatalogCallback); // Register event, that creates all Fields + + scope.internal.events.subscribe("postPutPages", createFieldCallback); + scope.internal.acroformPlugin.isInitialized = true; + } + }; + + var arrayToPdfArray = function arrayToPdfArray(array) { + if (Array.isArray(array)) { + var content = " ["; + + for (var i in array) { + if (array.hasOwnProperty(i)) { + var element = array[i].toString(); + content += element; + content += i < array.length - 1 ? " " : ""; + } + } + + content += "]"; + return content; + } + }; + + var toPdfString = function toPdfString(string) { + string = string || ""; // put Bracket at the Beginning of the String + + if (string.indexOf("(") !== 0) { + string = "(" + string; + } + + if (string.substring(string.length - 1) != ")") { + string += ")"; + } + + return string; + }; // ########################## + // Classes + // ########################## + + + var AcroFormPDFObject = function AcroFormPDFObject() { + // The Object ID in the PDF Object Model + // todo + var _objId; + + Object.defineProperty(this, "objId", { + get: function get() { + if (!_objId) { + _objId = scope.internal.newObjectDeferred(); + } + + if (!_objId) { + console.log("Couldn't create Object ID"); + } + + return _objId; + }, + configurable: false + }); + }; + + AcroFormPDFObject.prototype.toString = function () { + return this.objId + " 0 R"; + }; + + AcroFormPDFObject.prototype.getString = function () { + var res = this.objId + " 0 obj\n<<"; + var content = this.getContent(); + res += content + ">>\n"; + + if (this.stream) { + res += "stream\n"; + res += this.stream; + res += "\nendstream\n"; + } + + res += "endobj\n"; + return res; + }; + + AcroFormPDFObject.prototype.getContent = function () { + /** + * Prints out all enumerable Variables from the Object + * + * @param fieldObject + * @returns {string} + */ + var createContentFromFieldObject = function createContentFromFieldObject(fieldObject) { + var content = ""; + var keys = Object.keys(fieldObject).filter(function (key) { + return key != "content" && key != "appearanceStreamContent" && key.substring(0, 1) != "_"; + }); + + for (var i in keys) { + if (keys.hasOwnProperty(i)) { + var key = keys[i]; + var value = fieldObject[key]; + /* + * if (key == 'Rect' && value) { value = + * AcroForm.internal.calculateCoordinates.call(jsPDF.API.acroformPlugin.internal, + * value); } + */ + + if (value) { + if (Array.isArray(value)) { + content += "/" + key + " " + arrayToPdfArray(value) + "\n"; + } else if (value instanceof AcroFormPDFObject) { + // In case it is a reference to another PDFObject, + // take the referennce number + content += "/" + key + " " + value.objId + " 0 R" + "\n"; + } else { + content += "/" + key + " " + value + "\n"; + } + } + } + } + + return content; + }; + + var object = ""; + object += createContentFromFieldObject(this); + return object; + }; + + var AcroFormXObject = function AcroFormXObject() { + AcroFormPDFObject.call(this); + this.Type = "/XObject"; + this.Subtype = "/Form"; + this.FormType = 1; + this.BBox; + this.Matrix; + this.Resources = "2 0 R"; + this.PieceInfo; + + var _stream; + + Object.defineProperty(this, "Length", { + enumerable: true, + get: function get() { + return _stream !== undefined ? _stream.length : 0; + } + }); + Object.defineProperty(this, "stream", { + enumerable: false, + set: function set(val) { + _stream = val.trim(); + }, + get: function get() { + if (_stream) { + return _stream; + } else { + return null; + } + } + }); + }; + + inherit(AcroFormXObject, AcroFormPDFObject); // ##### The Objects, the User can Create: + + var AcroFormDictionary = function AcroFormDictionary() { + AcroFormPDFObject.call(this); + var _Kids = []; + Object.defineProperty(this, "Kids", { + enumerable: false, + configurable: true, + get: function get() { + if (_Kids.length > 0) { + return _Kids; + } else { + return; + } + } + }); + Object.defineProperty(this, "Fields", { + enumerable: true, + configurable: true, + get: function get() { + return _Kids; + } + }); // Default Appearance + + this.DA; + }; + + inherit(AcroFormDictionary, AcroFormPDFObject); // The Field Object contains the Variables, that every Field needs + // Rectangle for Appearance: lower_left_X, lower_left_Y, width, height + + var AcroFormField = function AcroFormField() { + + AcroFormPDFObject.call(this); + var _Rect = null; + Object.defineProperty(this, "Rect", { + enumerable: true, + configurable: false, + get: function get() { + if (!_Rect) { + return; + } + + var tmp = _Rect; // var calculatedRes = + // AcroForm.internal.calculateCoordinates(_Rect); // do + // later! + + return tmp; + }, + set: function set(val) { + _Rect = val; + } + }); + var _FT = ""; + Object.defineProperty(this, "FT", { + enumerable: true, + set: function set(val) { + _FT = val; + }, + get: function get() { + return _FT; + } + }); + var _F = 4; + Object.defineProperty(this, "F", { + enumerable: true, + set: function set(val) { + _F = val; + }, + get: function get() { + return _F; + } + }); + /** + * The Partial name of the Field Object. It has to be unique. + */ + + var _T = null; + Object.defineProperty(this, "T", { + enumerable: true, + configurable: false, + set: function set(val) { + _T = val; + }, + get: function get() { + if (!_T || _T.length < 1) { + if (this instanceof AcroFormChildClass) { + // In case of a Child from a Radio´Group, you don't + // need a FieldName!!! + return; + } + + return "(FieldObject" + AcroFormField.FieldNum++ + ")"; + } + + if (_T.substring(0, 1) == "(" && _T.substring(_T.length - 1)) { + return _T; + } + + return "(" + _T + ")"; + } + }); + var _DA = null; // Defines the default appearance (Needed for variable Text) + + Object.defineProperty(this, "DA", { + enumerable: true, + get: function get() { + if (!_DA) { + return; + } + + return "(" + _DA + ")"; + }, + set: function set(val) { + _DA = val; + } + }); + var _DV = null; // Defines the default value + + Object.defineProperty(this, "DV", { + enumerable: true, + configurable: true, + get: function get() { + if (!_DV) { + return; + } + + return _DV; + }, + set: function set(val) { + _DV = val; + } + }); + var _V = null; // Defines the default value + + Object.defineProperty(this, "V", { + enumerable: true, + configurable: true, + get: function get() { + if (!_V) { + return; + } + + return _V; + }, + set: function set(val) { + _V = val; + } + }); // this.Type = "/Annot"; + // this.Subtype = "/Widget"; + + Object.defineProperty(this, "Type", { + enumerable: true, + get: function get() { + return this.hasAnnotation ? "/Annot" : null; + } + }); + Object.defineProperty(this, "Subtype", { + enumerable: true, + get: function get() { + return this.hasAnnotation ? "/Widget" : null; + } + }); + /** + * + * @type {Array} + */ + + this.BG; + Object.defineProperty(this, "hasAnnotation", { + enumerable: false, + get: function get() { + if (this.Rect || this.BC || this.BG) { + return true; + } + + return false; + } + }); + Object.defineProperty(this, "hasAppearanceStream", { + enumerable: false, + configurable: true, + writable: true + }); + Object.defineProperty(this, "page", { + enumerable: false, + configurable: true, + writable: true + }); + }; + + inherit(AcroFormField, AcroFormPDFObject); + + var AcroFormChoiceField = function AcroFormChoiceField() { + AcroFormField.call(this); // Field Type = Choice Field + + this.FT = "/Ch"; // options + + this.Opt = []; + this.V = "()"; // Top Index + + this.TI = 0; + /** + * Defines, whether the + * + * @type {boolean} + */ + + var _combo = false; + Object.defineProperty(this, "combo", { + enumerable: false, + get: function get() { + return _combo; + }, + set: function set(val) { + _combo = val; + } + }); + /** + * Defines, whether the Choice Field is an Edit Field. An Edit Field + * is automatically an Combo Field. + */ + + Object.defineProperty(this, "edit", { + enumerable: true, + set: function set(val) { + if (val == true) { + this._edit = true; // ComboBox has to be true + + this.combo = true; + } else { + this._edit = false; + } + }, + get: function get() { + if (!this._edit) { + return false; + } + + return this._edit; + }, + configurable: false + }); + this.hasAppearanceStream = true; + }; + + inherit(AcroFormChoiceField, AcroFormField); + + var AcroFormListBox = function AcroFormListBox() { + AcroFormChoiceField.call(this); + this.combo = false; + }; + + inherit(AcroFormListBox, AcroFormChoiceField); + + var AcroFormComboBox = function AcroFormComboBox() { + AcroFormListBox.call(this); + this.combo = true; + }; + + inherit(AcroFormComboBox, AcroFormListBox); + + var AcroFormEditBox = function AcroFormEditBox() { + AcroFormComboBox.call(this); + this.edit = true; + }; + + inherit(AcroFormEditBox, AcroFormComboBox); + + var AcroFormButton = function AcroFormButton() { + AcroFormField.call(this); + this.FT = "/Btn"; // this.hasAnnotation = true; + }; + + inherit(AcroFormButton, AcroFormField); + + var AcroFormPushButton = function AcroFormPushButton() { + AcroFormButton.call(this); + var _pushbutton = true; + Object.defineProperty(this, "pushbutton", { + enumerable: false, + get: function get() { + return _pushbutton; + }, + set: function set(val) { + _pushbutton = val; + } + }); + }; + + inherit(AcroFormPushButton, AcroFormButton); + + var AcroFormRadioButton = function AcroFormRadioButton() { + AcroFormButton.call(this); + var _radio = true; + Object.defineProperty(this, "radio", { + enumerable: false, + get: function get() { + return _radio; + }, + set: function set(val) { + _radio = val; + } + }); + var _Kids = []; + Object.defineProperty(this, "Kids", { + enumerable: true, + get: function get() { + if (_Kids.length > 0) { + return _Kids; + } + } + }); + Object.defineProperty(this, "__Kids", { + get: function get() { + return _Kids; + } + }); + + var _noToggleToOff; + + Object.defineProperty(this, "noToggleToOff", { + enumerable: false, + get: function get() { + return _noToggleToOff; + }, + set: function set(val) { + _noToggleToOff = val; + } + }); // this.hasAnnotation = false; + }; + + inherit(AcroFormRadioButton, AcroFormButton); + /* + * The Child classs of a RadioButton (the radioGroup) -> The single + * Buttons + */ + + var AcroFormChildClass = function AcroFormChildClass(parent, name) { + AcroFormField.call(this); + this.Parent = parent; // todo: set AppearanceType as variable that can be set from the + // outside... + + this._AppearanceType = AcroFormAppearance.RadioButton.Circle; // The Default appearanceType is the Circle + + this.appearanceStreamContent = this._AppearanceType.createAppearanceStream(name); // Set Print in the Annot Flag + + this.F = setBitPosition(this.F, 3, 1); // Set AppearanceCharacteristicsDictionary with default appearance + // if field is not interacting with user + + this.MK = this._AppearanceType.createMK(); // (8) -> Cross, (1)-> Circle, ()-> nothing + // Default Appearance is Off + + this.AS = "/Off"; // + name; + + this._Name = name; + }; + + inherit(AcroFormChildClass, AcroFormField); + + AcroFormRadioButton.prototype.setAppearance = function (appearance) { + if (!("createAppearanceStream" in appearance && "createMK" in appearance)) { + console.log("Couldn't assign Appearance to RadioButton. Appearance was Invalid!"); + return; + } + + for (var i in this.__Kids) { + if (this.__Kids.hasOwnProperty(i)) { + var child = this.__Kids[i]; + child.appearanceStreamContent = appearance.createAppearanceStream(child._Name); + child.MK = appearance.createMK(); + } + } + }; + + AcroFormRadioButton.prototype.createOption = function (name) { + var parent = this; + var kidCount = this.__Kids.length; // Create new Child for RadioGroup + + var child = new AcroFormChildClass(parent, name); // Add to Parent + + this.__Kids.push(child); + + jsPDFAPI.addField(child); + return child; + }; + /** + * @name AcroFormCheckBox + * + * @memberOf AcroForm + * @function + */ + + + var AcroFormCheckBox = function AcroFormCheckBox() { + AcroFormButton.call(this); + this.appearanceStreamContent = AcroFormAppearance.CheckBox.createAppearanceStream(); + this.MK = AcroFormAppearance.CheckBox.createMK(); + this.AS = "/On"; + this.V = "/On"; + }; + + inherit(AcroFormCheckBox, AcroFormButton); + + var AcroFormTextField = function AcroFormTextField() { + AcroFormField.call(this); + this.DA = AcroFormAppearance.createDefaultAppearanceStream(); + this.F = 4; + + var _V; + + Object.defineProperty(this, "V", { + get: function get() { + if (_V) { + return toPdfString(_V); + } else { + return _V; + } + }, + enumerable: true, + set: function set(val) { + _V = val; + } + }); + + var _DV; + + Object.defineProperty(this, "DV", { + get: function get() { + if (_DV) { + return toPdfString(_DV); + } else { + return _DV; + } + }, + enumerable: true, + set: function set(val) { + _DV = val; + } + }); + var _multiline = false; + Object.defineProperty(this, "multiline", { + enumerable: false, + get: function get() { + return _multiline; + }, + set: function set(val) { + _multiline = val; + } + }); + /** + * For PDF 1.4 + * + * @type {boolean} + */ + + var _fileSelect = false; + Object.defineProperty(this, "fileSelect", { + enumerable: false, + get: function get() { + return _fileSelect; + }, + set: function set(val) { + _fileSelect = val; + } + }); + /** + * For PDF 1.4 + * + * @type {boolean} + */ + + var _doNotSpellCheck = false; + Object.defineProperty(this, "doNotSpellCheck", { + enumerable: false, + get: function get() { + return _doNotSpellCheck; + }, + set: function set(val) { + _doNotSpellCheck = val; + } + }); + /** + * For PDF 1.4 + * + * @type {boolean} + */ + + var _doNotScroll = false; + Object.defineProperty(this, "doNotScroll", { + enumerable: false, + get: function get() { + return _doNotScroll; + }, + set: function set(val) { + _doNotScroll = val; + } + }); + var _MaxLen = false; + Object.defineProperty(this, "MaxLen", { + enumerable: true, + get: function get() { + return _MaxLen; + }, + set: function set(val) { + _MaxLen = val; + } + }); + Object.defineProperty(this, "hasAppearanceStream", { + enumerable: false, + get: function get() { + return this.V || this.DV; + } + }); + }; + + inherit(AcroFormTextField, AcroFormField); + + var AcroFormPasswordField = function AcroFormPasswordField() { + AcroFormTextField.call(this); + var _password = true; + Object.defineProperty(this, "password", { + enumerable: false, + get: function get() { + return _password; + }, + set: function set(val) { + _password = val; + } + }); + }; + + inherit(AcroFormPasswordField, AcroFormTextField); // Contains Methods for creating standard appearances + + var AcroFormAppearance = { + CheckBox: { + createAppearanceStream: function createAppearanceStream() { + var appearance = { + N: { + On: AcroFormAppearance.CheckBox.YesNormal + }, + D: { + On: AcroFormAppearance.CheckBox.YesPushDown, + Off: AcroFormAppearance.CheckBox.OffPushDown + } + }; + return appearance; + }, + + /** + * If any other icons are needed, the number between the + * brackets can be changed + * + * @returns {string} + */ + createMK: function createMK() { + return "<< /CA (3)>>"; + }, + + /** + * Returns the standard On Appearance for a CheckBox + * + * @returns {AcroFormXObject} + */ + YesPushDown: function YesPushDown(formObject) { + var xobj = createFormXObject(formObject); + var stream = []; + var zapfDingbatsId = scope.internal.getFont("zapfdingbats", "normal").id; + formObject.Q = 1; // set text-alignment as centered + + var calcRes = calculateX(formObject, "3", "ZapfDingbats", 50); + stream.push("0.749023 g"); + stream.push("0 0 " + AcroFormAppearance.internal.getWidth(formObject).toFixed(2) + " " + AcroFormAppearance.internal.getHeight(formObject).toFixed(2) + " re"); + stream.push("f"); + stream.push("BMC"); + stream.push("q"); + stream.push("0 0 1 rg"); + stream.push("/" + zapfDingbatsId + " " + calcRes.fontSize.toFixed(2) + " Tf 0 g"); + stream.push("BT"); + stream.push(calcRes.text); + stream.push("ET"); + stream.push("Q"); + stream.push("EMC"); + xobj.stream = stream.join("\n"); + return xobj; + }, + YesNormal: function YesNormal(formObject) { + var xobj = createFormXObject(formObject); + var zapfDingbatsId = scope.internal.getFont("zapfdingbats", "normal").id; + var stream = []; + formObject.Q = 1; // set text-alignment as centered + + var height = AcroFormAppearance.internal.getHeight(formObject); + var width = AcroFormAppearance.internal.getWidth(formObject); + var calcRes = calculateX(formObject, "3", "ZapfDingbats", height * 0.9); + stream.push("1 g"); + stream.push("0 0 " + width.toFixed(2) + " " + height.toFixed(2) + " re"); + stream.push("f"); + stream.push("q"); + stream.push("0 0 1 rg"); + stream.push("0 0 " + (width - 1).toFixed(2) + " " + (height - 1).toFixed(2) + " re"); + stream.push("W"); + stream.push("n"); + stream.push("0 g"); + stream.push("BT"); + stream.push("/" + zapfDingbatsId + " " + calcRes.fontSize.toFixed(2) + " Tf 0 g"); + stream.push(calcRes.text); + stream.push("ET"); + stream.push("Q"); + xobj.stream = stream.join("\n"); + return xobj; + }, + + /** + * Returns the standard Off Appearance for a CheckBox + * + * @returns {AcroFormXObject} + */ + OffPushDown: function OffPushDown(formObject) { + var xobj = createFormXObject(formObject); + var stream = []; + stream.push("0.749023 g"); + stream.push("0 0 " + AcroFormAppearance.internal.getWidth(formObject).toFixed(2) + " " + AcroFormAppearance.internal.getHeight(formObject).toFixed(2) + " re"); + stream.push("f"); + xobj.stream = stream.join("\n"); + return xobj; + } + }, + RadioButton: { + Circle: { + createAppearanceStream: function createAppearanceStream(name) { + var appearanceStreamContent = { + D: { + Off: AcroFormAppearance.RadioButton.Circle.OffPushDown + }, + N: {} + }; + appearanceStreamContent.N[name] = AcroFormAppearance.RadioButton.Circle.YesNormal; + appearanceStreamContent.D[name] = AcroFormAppearance.RadioButton.Circle.YesPushDown; + return appearanceStreamContent; + }, + createMK: function createMK() { + return "<< /CA (l)>>"; + }, + YesNormal: function YesNormal(formObject) { + var xobj = createFormXObject(formObject); + var stream = []; // Make the Radius of the Circle relative to min(height, + // width) of formObject + + var DotRadius = AcroFormAppearance.internal.getWidth(formObject) <= AcroFormAppearance.internal.getHeight(formObject) ? AcroFormAppearance.internal.getWidth(formObject) / 4 : AcroFormAppearance.internal.getHeight(formObject) / 4; // The Borderpadding... + + DotRadius *= 0.9; + var c = AcroFormAppearance.internal.Bezier_C; + /* + * The Following is a Circle created with Bezier-Curves. + */ + + stream.push("q"); + stream.push("1 0 0 1 " + AcroFormAppearance.internal.getWidth(formObject) / 2 + " " + AcroFormAppearance.internal.getHeight(formObject) / 2 + " cm"); + stream.push(DotRadius + " 0 m"); + stream.push(DotRadius + " " + DotRadius * c + " " + DotRadius * c + " " + DotRadius + " 0 " + DotRadius + " c"); + stream.push("-" + DotRadius * c + " " + DotRadius + " -" + DotRadius + " " + DotRadius * c + " -" + DotRadius + " 0 c"); + stream.push("-" + DotRadius + " -" + DotRadius * c + " -" + DotRadius * c + " -" + DotRadius + " 0 -" + DotRadius + " c"); + stream.push(DotRadius * c + " -" + DotRadius + " " + DotRadius + " -" + DotRadius * c + " " + DotRadius + " 0 c"); + stream.push("f"); + stream.push("Q"); + xobj.stream = stream.join("\n"); + return xobj; + }, + YesPushDown: function YesPushDown(formObject) { + var xobj = createFormXObject(formObject); + var stream = []; + var DotRadius = AcroFormAppearance.internal.getWidth(formObject) <= AcroFormAppearance.internal.getHeight(formObject) ? AcroFormAppearance.internal.getWidth(formObject) / 4 : AcroFormAppearance.internal.getHeight(formObject) / 4; // The Borderpadding... + + DotRadius *= 0.9; // Save results for later use; no need to waste + // processor ticks on doing math + + var k = DotRadius * 2; // var c = AcroFormAppearance.internal.Bezier_C; + + var kc = k * AcroFormAppearance.internal.Bezier_C; + var dc = DotRadius * AcroFormAppearance.internal.Bezier_C; + stream.push("0.749023 g"); + stream.push("q"); + stream.push("1 0 0 1 " + (AcroFormAppearance.internal.getWidth(formObject) / 2).toFixed(2) + " " + (AcroFormAppearance.internal.getHeight(formObject) / 2).toFixed(2) + " cm"); + stream.push(k + " 0 m"); + stream.push(k + " " + kc + " " + kc + " " + k + " 0 " + k + " c"); + stream.push("-" + kc + " " + k + " -" + k + " " + kc + " -" + k + " 0 c"); + stream.push("-" + k + " -" + kc + " -" + kc + " -" + k + " 0 -" + k + " c"); + stream.push(kc + " -" + k + " " + k + " -" + kc + " " + k + " 0 c"); + stream.push("f"); + stream.push("Q"); + stream.push("0 g"); + stream.push("q"); + stream.push("1 0 0 1 " + (AcroFormAppearance.internal.getWidth(formObject) / 2).toFixed(2) + " " + (AcroFormAppearance.internal.getHeight(formObject) / 2).toFixed(2) + " cm"); + stream.push(DotRadius + " 0 m"); + stream.push("" + DotRadius + " " + dc + " " + dc + " " + DotRadius + " 0 " + DotRadius + " c"); + stream.push("-" + dc + " " + DotRadius + " -" + DotRadius + " " + dc + " -" + DotRadius + " 0 c"); + stream.push("-" + DotRadius + " -" + dc + " -" + dc + " -" + DotRadius + " 0 -" + DotRadius + " c"); + stream.push(dc + " -" + DotRadius + " " + DotRadius + " -" + dc + " " + DotRadius + " 0 c"); + stream.push("f"); + stream.push("Q"); + xobj.stream = stream.join("\n"); + return xobj; + }, + OffPushDown: function OffPushDown(formObject) { + var xobj = createFormXObject(formObject); + var stream = []; + var DotRadius = AcroFormAppearance.internal.getWidth(formObject) <= AcroFormAppearance.internal.getHeight(formObject) ? AcroFormAppearance.internal.getWidth(formObject) / 4 : AcroFormAppearance.internal.getHeight(formObject) / 4; // The Borderpadding... + + DotRadius *= 0.9; // Save results for later use; no need to waste + // processor ticks on doing math + + var k = DotRadius * 2; // var c = AcroFormAppearance.internal.Bezier_C; + + var kc = k * AcroFormAppearance.internal.Bezier_C; + stream.push("0.749023 g"); + stream.push("q"); + stream.push("1 0 0 1 " + (AcroFormAppearance.internal.getWidth(formObject) / 2).toFixed(2) + " " + (AcroFormAppearance.internal.getHeight(formObject) / 2).toFixed(2) + " cm"); + stream.push(k + " 0 m"); + stream.push(k + " " + kc + " " + kc + " " + k + " 0 " + k + " c"); + stream.push("-" + kc + " " + k + " -" + k + " " + kc + " -" + k + " 0 c"); + stream.push("-" + k + " -" + kc + " -" + kc + " -" + k + " 0 -" + k + " c"); + stream.push(kc + " -" + k + " " + k + " -" + kc + " " + k + " 0 c"); + stream.push("f"); + stream.push("Q"); + xobj.stream = stream.join("\n"); + return xobj; + } + }, + Cross: { + /** + * Creates the Actual AppearanceDictionary-References + * + * @param {string} name + * @returns {Object} + * @ignore + */ + createAppearanceStream: function createAppearanceStream(name) { + var appearanceStreamContent = { + D: { + Off: AcroFormAppearance.RadioButton.Cross.OffPushDown + }, + N: {} + }; + appearanceStreamContent.N[name] = AcroFormAppearance.RadioButton.Cross.YesNormal; + appearanceStreamContent.D[name] = AcroFormAppearance.RadioButton.Cross.YesPushDown; + return appearanceStreamContent; + }, + createMK: function createMK() { + return "<< /CA (8)>>"; + }, + YesNormal: function YesNormal(formObject) { + var xobj = createFormXObject(formObject); + var stream = []; + var cross = AcroFormAppearance.internal.calculateCross(formObject); + stream.push("q"); + stream.push("1 1 " + (AcroFormAppearance.internal.getWidth(formObject) - 2).toFixed(2) + " " + (AcroFormAppearance.internal.getHeight(formObject) - 2).toFixed(2) + " re"); + stream.push("W"); + stream.push("n"); + stream.push(cross.x1.x.toFixed(2) + " " + cross.x1.y.toFixed(2) + " m"); + stream.push(cross.x2.x.toFixed(2) + " " + cross.x2.y.toFixed(2) + " l"); + stream.push(cross.x4.x.toFixed(2) + " " + cross.x4.y.toFixed(2) + " m"); + stream.push(cross.x3.x.toFixed(2) + " " + cross.x3.y.toFixed(2) + " l"); + stream.push("s"); + stream.push("Q"); + xobj.stream = stream.join("\n"); + return xobj; + }, + YesPushDown: function YesPushDown(formObject) { + var xobj = createFormXObject(formObject); + var cross = AcroFormAppearance.internal.calculateCross(formObject); + var stream = []; + stream.push("0.749023 g"); + stream.push("0 0 " + AcroFormAppearance.internal.getWidth(formObject).toFixed(2) + " " + AcroFormAppearance.internal.getHeight(formObject).toFixed(2) + " re"); + stream.push("f"); + stream.push("q"); + stream.push("1 1 " + (AcroFormAppearance.internal.getWidth(formObject) - 2).toFixed(2) + " " + (AcroFormAppearance.internal.getHeight(formObject) - 2).toFixed(2) + " re"); + stream.push("W"); + stream.push("n"); + stream.push(cross.x1.x.toFixed(2) + " " + cross.x1.y.toFixed(2) + " m"); + stream.push(cross.x2.x.toFixed(2) + " " + cross.x2.y.toFixed(2) + " l"); + stream.push(cross.x4.x.toFixed(2) + " " + cross.x4.y.toFixed(2) + " m"); + stream.push(cross.x3.x.toFixed(2) + " " + cross.x3.y.toFixed(2) + " l"); + stream.push("s"); + stream.push("Q"); + xobj.stream = stream.join("\n"); + return xobj; + }, + OffPushDown: function OffPushDown(formObject) { + var xobj = createFormXObject(formObject); + var stream = []; + stream.push("0.749023 g"); + stream.push("0 0 " + AcroFormAppearance.internal.getWidth(formObject).toFixed(2) + " " + AcroFormAppearance.internal.getHeight(formObject).toFixed(2) + " re"); + stream.push("f"); + xobj.stream = stream.join("\n"); + return xobj; + } + } + }, + + /** + * Returns the standard Appearance + * + * @returns {AcroFormXObject} + */ + createDefaultAppearanceStream: function createDefaultAppearanceStream(formObject) { + // Set Helvetica to Standard Font (size: auto) + // Color: Black + return "/F1 0 Tf 0 g"; + } + }; + AcroFormAppearance.internal = { + Bezier_C: 0.551915024494, + calculateCross: function calculateCross(formObject) { + var min = function min(x, y) { + return x > y ? y : x; + }; + + var width = AcroFormAppearance.internal.getWidth(formObject); + var height = AcroFormAppearance.internal.getHeight(formObject); + var a = min(width, height); + + var cross = { + x1: { + // upperLeft + x: (width - a) / 2, + y: (height - a) / 2 + a // height - borderPadding + + }, + x2: { + // lowerRight + x: (width - a) / 2 + a, + y: (height - a) / 2 // borderPadding + + }, + x3: { + // lowerLeft + x: (width - a) / 2, + y: (height - a) / 2 // borderPadding + + }, + x4: { + // upperRight + x: (width - a) / 2 + a, + y: (height - a) / 2 + a // height - borderPadding + + } + }; + return cross; + } + }; + + AcroFormAppearance.internal.getWidth = function (formObject) { + var result = 0; + + if (_typeof(formObject) === "object") { + result = scale(formObject.Rect[2]); // (formObject.Rect[2] - + // formObject.Rect[0]) || 0; + } + + return result; + }; + + AcroFormAppearance.internal.getHeight = function (formObject) { + var result = 0; + + if (_typeof(formObject) === "object") { + result = scale(formObject.Rect[3]); // (formObject.Rect[1] - + // formObject.Rect[3]) || 0; + } + + return result; + }; // Public: + + /** + * Add an AcroForm-Field to the {jsPDF}-instance + * + * @memberOf AcroForm + * @name addField + * @param {Object} fieldObject + * @returns {jsPDF} + */ + + + jsPDFAPI.addField = function (fieldObject) { + initializeAcroForm.call(this); // var opt = parseOptions(fieldObject); + + if (fieldObject instanceof AcroFormTextField) { + this.addTextField.call(this, fieldObject); + } else if (fieldObject instanceof AcroFormChoiceField) { + this.addChoiceField.call(this, fieldObject); + } else if (fieldObject instanceof AcroFormButton) { + this.addButton.call(this, fieldObject); + } else if (fieldObject instanceof AcroFormChildClass) { + putForm.call(this, fieldObject); + } else if (fieldObject) { + // try to put.. + putForm.call(this, fieldObject); + } + + fieldObject.page = scope.internal.getCurrentPageInfo().pageNumber; + return this; + }; + /** + * @name addButton + * @param {AcroFormButton} + * @memberOf AcroForm + */ + + + jsPDFAPI.addButton = function (opts) { + initializeAcroForm.call(this); + var options = opts || new AcroFormField(); + options.FT = "/Btn"; + options.Ff = calculateFlagsOnOptions(options.Ff, opts, scope.internal.getPDFVersion()); + putForm.call(this, options); + }; + + jsPDFAPI.addTextField = function (opts) { + initializeAcroForm.call(this); + var options = opts || new AcroFormField(); + options.FT = "/Tx"; + options.Ff = calculateFlagsOnOptions(options.Ff, opts, scope.internal.getPDFVersion()); // Add field + + putForm.call(this, options); + }; + + jsPDFAPI.addChoiceField = function (opts) { + initializeAcroForm.call(this); + var options = opts || new AcroFormField(); + options.FT = "/Ch"; + options.Ff = calculateFlagsOnOptions(options.Ff, opts, scope.internal.getPDFVersion()); // options.hasAnnotation = true; + // Add field + + putForm.call(this, options); + }; + + if (_typeof(globalObj) == "object") { + globalObj["ChoiceField"] = AcroFormChoiceField; + globalObj["ListBox"] = AcroFormListBox; + globalObj["ComboBox"] = AcroFormComboBox; + globalObj["EditBox"] = AcroFormEditBox; + globalObj["Button"] = AcroFormButton; + globalObj["PushButton"] = AcroFormPushButton; + globalObj["RadioButton"] = AcroFormRadioButton; + globalObj["CheckBox"] = AcroFormCheckBox; + globalObj["TextField"] = AcroFormTextField; + globalObj["PasswordField"] = AcroFormPasswordField; // backwardsCompatibility + + globalObj["AcroForm"] = { + Appearance: AcroFormAppearance + }; + } + + jsPDFAPI.AcroFormChoiceField = AcroFormChoiceField; + jsPDFAPI.AcroFormListBox = AcroFormListBox; + jsPDFAPI.AcroFormComboBox = AcroFormComboBox; + jsPDFAPI.AcroFormEditBox = AcroFormEditBox; + jsPDFAPI.AcroFormButton = AcroFormButton; + jsPDFAPI.AcroFormPushButton = AcroFormPushButton; + jsPDFAPI.AcroFormRadioButton = AcroFormRadioButton; + jsPDFAPI.AcroFormCheckBox = AcroFormCheckBox; + jsPDFAPI.AcroFormTextField = AcroFormTextField; + jsPDFAPI.AcroFormPasswordField = AcroFormPasswordField; + jsPDFAPI.AcroFormAppearance = AcroFormAppearance; + jsPDFAPI.AcroForm = { + ChoiceField: AcroFormChoiceField, + ListBox: AcroFormListBox, + ComboBox: AcroFormComboBox, + EditBox: AcroFormEditBox, + Button: AcroFormButton, + PushButton: AcroFormPushButton, + RadioButton: AcroFormRadioButton, + CheckBox: AcroFormCheckBox, + TextField: AcroFormTextField, + PasswordField: AcroFormPasswordField, + Appearance: AcroFormAppearance + }; + })(jsPDF.API, typeof window !== "undefined" && window || typeof global !== "undefined" && global); + + /** @license + * jsPDF addImage plugin + * Copyright (c) 2012 Jason Siefken, https://github.com/siefkenj/ + * 2013 Chris Dowling, https://github.com/gingerchris + * 2013 Trinh Ho, https://github.com/ineedfat + * 2013 Edwin Alejandro Perez, https://github.com/eaparango + * 2013 Norah Smith, https://github.com/burnburnrocket + * 2014 Diego Casorran, https://github.com/diegocr + * 2014 James Robb, https://github.com/jamesbrobb + * + * + */ + + /** + * @name addImage + * @module + */ + (function (jsPDFAPI) { + + var namespace = "addImage_"; + var imageFileTypeHeaders = { + PNG: [[0x89, 0x50, 0x4e, 0x47]], + TIFF: [[0x4d, 0x4d, 0x00, 0x2a], //Motorola + [0x49, 0x49, 0x2a, 0x00] //Intel + ], + JPEG: [[0xff, 0xd8, 0xff, 0xe0, undefined, undefined, 0x4a, 0x46, 0x49, 0x46, 0x00], //JFIF + [0xff, 0xd8, 0xff, 0xe1, undefined, undefined, 0x45, 0x78, 0x69, 0x66, 0x00, 0x00] //Exif + ], + JPEG2000: [[0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20]], + GIF87a: [[0x47, 0x49, 0x46, 0x38, 0x37, 0x61]], + GIF89a: [[0x47, 0x49, 0x46, 0x38, 0x39, 0x61]], + BMP: [[0x42, 0x4d], //BM - Windows 3.1x, 95, NT, ... etc. + [0x42, 0x41], //BA - OS/2 struct bitmap array + [0x43, 0x49], //CI - OS/2 struct color icon + [0x43, 0x50], //CP - OS/2 const color pointer + [0x49, 0x43], //IC - OS/2 struct icon + [0x50, 0x54] //PT - OS/2 pointer + ] + }; + /** + * Recognize filetype of Image by magic-bytes + * + * https://en.wikipedia.org/wiki/List_of_file_signatures + * + * @name getImageFileTypeByImageData + * @public + * @function + * @param {string|arraybuffer} imageData imageData as base64 encoded DataUrl or arraybuffer + * @param {string} format format of file if filetype-recognition fails, e.g. 'JPEG' + * + * @returns {string} filetype of Image + */ + + jsPDFAPI.getImageFileTypeByImageData = function (imageData, fallbackFormat) { + fallbackFormat = fallbackFormat || "UNKNOWN"; + var i; + var j; + var result = "UNKNOWN"; + var headerSchemata; + var compareResult; + var fileType; + + if (jsPDFAPI.isArrayBufferView(imageData)) { + imageData = jsPDFAPI.arrayBufferToBinaryString(imageData); + } + + for (fileType in imageFileTypeHeaders) { + headerSchemata = imageFileTypeHeaders[fileType]; + + for (i = 0; i < headerSchemata.length; i += 1) { + compareResult = true; + + for (j = 0; j < headerSchemata[i].length; j += 1) { + if (headerSchemata[i][j] === undefined) { + continue; + } + + if (headerSchemata[i][j] !== imageData.charCodeAt(j)) { + compareResult = false; + break; + } + } + + if (compareResult === true) { + result = fileType; + break; + } + } + } + + if (result === "UNKNOWN" && fallbackFormat !== "UNKNOWN") { + console.warn('FileType of Image not recognized. Processing image as "' + fallbackFormat + '".'); + result = fallbackFormat; + } + + return result; + }; // Image functionality ported from pdf.js + + + var putImage = function putImage(img) { + var objectNumber = this.internal.newObject(), + out = this.internal.write, + putStream = this.internal.putStream; + img["n"] = objectNumber; + out("<>"); + } + + if ("trns" in img && img["trns"].constructor == Array) { + var trns = "", + i = 0, + len = img["trns"].length; + + for (; i < len; i++) { + trns += img["trns"][i] + " " + img["trns"][i] + " "; + } + + out("/Mask [" + trns + "]"); + } + + if ("smask" in img) { + out("/SMask " + (objectNumber + 1) + " 0 R"); + } + + out("/Length " + img["data"].length + ">>"); + putStream(img["data"]); + out("endobj"); // Soft mask + + if ("smask" in img) { + var dp = "/Predictor " + img["p"] + " /Colors 1 /BitsPerComponent " + img["bpc"] + " /Columns " + img["w"]; + var smask = { + w: img["w"], + h: img["h"], + cs: "DeviceGray", + bpc: img["bpc"], + dp: dp, + data: img["smask"] + }; + if ("f" in img) smask.f = img["f"]; + putImage.call(this, smask); + } //Palette + + + if (img["cs"] === this.color_spaces.INDEXED) { + this.internal.newObject(); //out('<< /Filter / ' + img['f'] +' /Length ' + img['pal'].length + '>>'); + //putStream(zlib.compress(img['pal'])); + + out("<< /Length " + img["pal"].length + ">>"); + putStream(this.arrayBufferToBinaryString(new Uint8Array(img["pal"]))); + out("endobj"); + } + }, + putResourcesCallback = function putResourcesCallback() { + var images = this.internal.collections[namespace + "images"]; + + for (var i in images) { + putImage.call(this, images[i]); + } + }, + putXObjectsDictCallback = function putXObjectsDictCallback() { + var images = this.internal.collections[namespace + "images"], + out = this.internal.write, + image; + + for (var i in images) { + image = images[i]; + out("/I" + image["i"], image["n"], "0", "R"); + } + }, + checkCompressValue = function checkCompressValue(value) { + if (value && typeof value === "string") value = value.toUpperCase(); + return value in jsPDFAPI.image_compression ? value : jsPDFAPI.image_compression.NONE; + }, + getImages = function getImages() { + var images = this.internal.collections[namespace + "images"]; //first run, so initialise stuff + + if (!images) { + this.internal.collections[namespace + "images"] = images = {}; + this.internal.events.subscribe("putResources", putResourcesCallback); + this.internal.events.subscribe("putXobjectDict", putXObjectsDictCallback); + } + + return images; + }, + getImageIndex = function getImageIndex(images) { + var imageIndex = 0; + + if (images) { + // this is NOT the first time this method is ran on this instance of jsPDF object. + imageIndex = Object.keys ? Object.keys(images).length : function (o) { + var i = 0; + + for (var e in o) { + if (o.hasOwnProperty(e)) { + i++; + } + } + + return i; + }(images); + } + + return imageIndex; + }, + notDefined = function notDefined(value) { + return typeof value === "undefined" || value === null || value.length === 0; + }, + generateAliasFromData = function generateAliasFromData(data) { + return typeof data === "string" && jsPDFAPI.sHashCode(data); + }, + isImageTypeSupported = function isImageTypeSupported(type) { + return typeof jsPDFAPI["process" + type.toUpperCase()] === "function"; + }, + isDOMElement = function isDOMElement(object) { + return _typeof(object) === "object" && object.nodeType === 1; + }, + createDataURIFromElement = function createDataURIFromElement(element, format) { + //if element is an image which uses data url definition, just return the dataurl + if (element.nodeName === "IMG" && element.hasAttribute("src")) { + var src = "" + element.getAttribute("src"); + if (src.indexOf("data:image/") === 0) return unescape(src); // only if the user doesn't care about a format + + if (!format && /\.png(?:[?#].*)?$/i.test(src)) format = "png"; + } + + if (element.nodeName === "CANVAS") { + var canvas = element; + } else { + var canvas = document.createElement("canvas"); + canvas.width = element.clientWidth || element.width; + canvas.height = element.clientHeight || element.height; + var ctx = canvas.getContext("2d"); + + if (!ctx) { + throw "addImage requires canvas to be supported by browser."; + } + + ctx.drawImage(element, 0, 0, canvas.width, canvas.height); + } + + return canvas.toDataURL(("" + format).toLowerCase() == "png" ? "image/png" : "image/jpeg"); + }, + checkImagesForAlias = function checkImagesForAlias(alias, images) { + var cached_info; + + if (images) { + for (var e in images) { + if (alias === images[e].alias) { + cached_info = images[e]; + break; + } + } + } + + return cached_info; + }, + determineWidthAndHeight = function determineWidthAndHeight(w, h, info) { + if (!w && !h) { + w = -96; + h = -96; + } + + if (w < 0) { + w = -1 * info["w"] * 72 / w / this.internal.scaleFactor; + } + + if (h < 0) { + h = -1 * info["h"] * 72 / h / this.internal.scaleFactor; + } + + if (w === 0) { + w = h * info["w"] / info["h"]; + } + + if (h === 0) { + h = w * info["h"] / info["w"]; + } + + return [w, h]; + }, + writeImageToPDF = function writeImageToPDF(x, y, w, h, info, index, images, rotation) { + var dims = determineWidthAndHeight.call(this, w, h, info), + coord = this.internal.getCoordinateString, + vcoord = this.internal.getVerticalCoordinateString; + w = dims[0]; + h = dims[1]; + images[index] = info; + + if (rotation) { + rotation *= Math.PI / 180; + var c = Math.cos(rotation); + var s = Math.sin(rotation); //like in pdf Reference do it 4 digits instead of 2 + + var f4 = function f4(number) { + return number.toFixed(4); + }; + + var rotationTransformationMatrix = [f4(c), f4(s), f4(s * -1), f4(c), 0, 0, "cm"]; + } + + this.internal.write("q"); //Save graphics state + + if (rotation) { + this.internal.write([1, "0", "0", 1, coord(x), vcoord(y + h), "cm"].join(" ")); //Translate + + this.internal.write(rotationTransformationMatrix.join(" ")); //Rotate + + this.internal.write([coord(w), "0", "0", coord(h), "0", "0", "cm"].join(" ")); //Scale + } else { + this.internal.write([coord(w), "0", "0", coord(h), coord(x), vcoord(y + h), "cm"].join(" ")); //Translate and Scale + } + + if (this.isAdvancedAPI()) { + // draw image bottom up when in "advanced" API mode + this.internal.write([1, 0, 0, -1, 0, 0, "cm"].join(" ")); + } + + this.internal.write("/I" + info["i"] + " Do"); //Paint Image + + this.internal.write("Q"); //Restore graphics state + }; + /** + * COLOR SPACES + */ + + + jsPDFAPI.color_spaces = { + DEVICE_RGB: "DeviceRGB", + DEVICE_GRAY: "DeviceGray", + DEVICE_CMYK: "DeviceCMYK", + CAL_GREY: "CalGray", + CAL_RGB: "CalRGB", + LAB: "Lab", + ICC_BASED: "ICCBased", + INDEXED: "Indexed", + PATTERN: "Pattern", + SEPARATION: "Separation", + DEVICE_N: "DeviceN" + }; + /** + * DECODE METHODS + */ + + jsPDFAPI.decode = { + DCT_DECODE: "DCTDecode", + FLATE_DECODE: "FlateDecode", + LZW_DECODE: "LZWDecode", + JPX_DECODE: "JPXDecode", + JBIG2_DECODE: "JBIG2Decode", + ASCII85_DECODE: "ASCII85Decode", + ASCII_HEX_DECODE: "ASCIIHexDecode", + RUN_LENGTH_DECODE: "RunLengthDecode", + CCITT_FAX_DECODE: "CCITTFaxDecode" + }; + /** + * IMAGE COMPRESSION TYPES + */ + + jsPDFAPI.image_compression = { + NONE: "NONE", + FAST: "FAST", + MEDIUM: "MEDIUM", + SLOW: "SLOW" + }; + /** + * @name sHashCode + * @function + * @param {string} str + * @returns {string} + */ + + jsPDFAPI.sHashCode = function (str) { + str = str || ""; + return Array.prototype.reduce && str.split("").reduce(function (a, b) { + a = (a << 5) - a + b.charCodeAt(0); + return a & a; + }, 0); + }; + /** + * @name isString + * @function + * @param {any} object + * @returns {boolean} + */ + + + jsPDFAPI.isString = function (object) { + return typeof object === "string"; + }; + /** + * Validates if given String is a valid Base64-String + * + * @name validateStringAsBase64 + * @public + * @function + * @param {String} possible Base64-String + * + * @returns {boolean} + */ + + + jsPDFAPI.validateStringAsBase64 = function (possibleBase64String) { + possibleBase64String = possibleBase64String || ""; + var result = true; + + if (possibleBase64String.length % 4 !== 0) { + result = false; + } + + if (/[A-Za-z0-9\/]+/.test(possibleBase64String.substr(0, possibleBase64String.length - 2)) === false) { + result = false; + } + + if (/[A-Za-z0-9\/][A-Za-z0-9+\/]|[A-Za-z0-9+\/]=|==/.test(possibleBase64String.substr(-2)) === false) { + result = false; + } + + return result; + }; + /** + * Strips out and returns info from a valid base64 data URI + * + * @name extractInfoFromBase64DataURI + * @function + * @param {string} dataUrl a valid data URI of format 'data:[][;base64],' + * @returns {Array}an Array containing the following + * [0] the complete data URI + * [1] + * [2] format - the second part of the mime-type i.e 'png' in 'image/png' + * [4] + */ + + + jsPDFAPI.extractInfoFromBase64DataURI = function (dataURI) { + return /^data:([\w]+?\/([\w]+?));\S*;*base64,(.+)$/g.exec(dataURI); + }; + /** + * Check to see if ArrayBuffer is supported + * + * @name supportsArrayBuffer + * @function + * @returns {boolean} + */ + + + jsPDFAPI.supportsArrayBuffer = function () { + return typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined"; + }; + /** + * Tests supplied object to determine if ArrayBuffer + * + * @name isArrayBuffer + * @function + * @param {Object} object an Object + * + * @returns {boolean} + */ + + + jsPDFAPI.isArrayBuffer = function (object) { + if (!this.supportsArrayBuffer()) return false; + return object instanceof ArrayBuffer; + }; + /** + * Tests supplied object to determine if it implements the ArrayBufferView (TypedArray) interface + * + * @name isArrayBufferView + * @function + * @param {Object} object an Object + * @returns {boolean} + */ + + + jsPDFAPI.isArrayBufferView = function (object) { + if (!this.supportsArrayBuffer()) return false; + if (typeof Uint32Array === "undefined") return false; + return object instanceof Int8Array || object instanceof Uint8Array || typeof Uint8ClampedArray !== "undefined" && object instanceof Uint8ClampedArray || object instanceof Int16Array || object instanceof Uint16Array || object instanceof Int32Array || object instanceof Uint32Array || object instanceof Float32Array || object instanceof Float64Array; + }; + /** + * Convert the Buffer to a Binary String + * + * @name binaryStringToUint8Array + * @public + * @function + * @param {ArrayBuffer} BinaryString with ImageData + * + * @returns {Uint8Array} + */ + + + jsPDFAPI.binaryStringToUint8Array = function (binary_string) { + /* + * not sure how efficient this will be will bigger files. Is there a native method? + */ + var len = binary_string.length; + var bytes = new Uint8Array(len); + + for (var i = 0; i < len; i++) { + bytes[i] = binary_string.charCodeAt(i); + } + + return bytes; + }; + /** + * Convert the Buffer to a Binary String + * + * @name arrayBufferToBinaryString + * @public + * @function + * @param {ArrayBuffer} ArrayBuffer with ImageData + * + * @returns {String} + */ + + + jsPDFAPI.arrayBufferToBinaryString = function (buffer) { + if (typeof atob === "function") { + return atob(this.arrayBufferToBase64(buffer)); + } + + if (typeof TextDecoder === "function") { + var decoder = new TextDecoder("ascii"); // test if the encoding is supported + + if (decoder.encoding === "ascii") { + return decoder.decode(buffer); + } + } //Fallback-solution + + + var data = this.isArrayBuffer(buffer) ? buffer : new Uint8Array(buffer); + var chunkSizeForSlice = 0x5000; + var binary_string = ""; + var slicesCount = Math.ceil(data.byteLength / chunkSizeForSlice); + + for (var i = 0; i < slicesCount; i++) { + binary_string += String.fromCharCode.apply(null, data.slice(i * chunkSizeForSlice, i * chunkSizeForSlice + chunkSizeForSlice)); + } + + return binary_string; + }; + /** + * Converts an ArrayBuffer directly to base64 + * + * Taken from http://jsperf.com/encoding-xhr-image-data/31 + * + * Need to test if this is a better solution for larger files + * + * @name arrayBufferToBase64 + * @param {arraybuffer} arrayBuffer + * @public + * @function + * + * @returns {string} + */ + + + jsPDFAPI.arrayBufferToBase64 = function (arrayBuffer) { + var base64 = ""; + var encodings = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var bytes = new Uint8Array(arrayBuffer); + var byteLength = bytes.byteLength; + var byteRemainder = byteLength % 3; + var mainLength = byteLength - byteRemainder; + var a, b, c, d; + var chunk; // Main loop deals with bytes in chunks of 3 + + for (var i = 0; i < mainLength; i = i + 3) { + // Combine the three bytes into a single integer + chunk = bytes[i] << 16 | bytes[i + 1] << 8 | bytes[i + 2]; // Use bitmasks to extract 6-bit segments from the triplet + + a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18 + + b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12 + + c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6 + + d = chunk & 63; // 63 = 2^6 - 1 + // Convert the raw binary segments to the appropriate ASCII encoding + + base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]; + } // Deal with the remaining bytes and padding + + + if (byteRemainder == 1) { + chunk = bytes[mainLength]; + a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2 + // Set the 4 least significant bits to zero + + b = (chunk & 3) << 4; // 3 = 2^2 - 1 + + base64 += encodings[a] + encodings[b] + "=="; + } else if (byteRemainder == 2) { + chunk = bytes[mainLength] << 8 | bytes[mainLength + 1]; + a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10 + + b = (chunk & 1008) >> 4; // 1008 = (2^6 - 1) << 4 + // Set the 2 least significant bits to zero + + c = (chunk & 15) << 2; // 15 = 2^4 - 1 + + base64 += encodings[a] + encodings[b] + encodings[c] + "="; + } + + return base64; + }; + /** + * + * @name createImageInfo + * @param {Object} data + * @param {number} wd width + * @param {number} ht height + * @param {Object} cs colorSpace + * @param {number} bpc bits per channel + * @param {any} f + * @param {number} imageIndex + * @param {string} alias + * @param {any} dp + * @param {any} trns + * @param {any} pal + * @param {any} smask + * @param {any} p + * @public + * @function + * + * @returns {Object} + */ + + + jsPDFAPI.createImageInfo = function (data, wd, ht, cs, bpc, f, imageIndex, alias, dp, trns, pal, smask, p) { + var info = { + alias: alias, + w: wd, + h: ht, + cs: cs, + bpc: bpc, + i: imageIndex, + data: data // n: objectNumber will be added by putImage code + + }; + if (f) info.f = f; + if (dp) info.dp = dp; + if (trns) info.trns = trns; + if (pal) info.pal = pal; + if (smask) info.smask = smask; + if (p) info.p = p; // predictor parameter for PNG compression + + return info; + }; + /** + * Adds an Image to the PDF. + * + * @name addImage + * @public + * @function + * @param {string/Image-Element/Canvas-Element/Uint8Array} imageData imageData as base64 encoded DataUrl or Image-HTMLElement or Canvas-HTMLElement + * @param {string} format format of file if filetype-recognition fails, e.g. 'JPEG' + * @param {number} x x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {number} y y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {number} width width of the image (in units declared at inception of PDF document) + * @param {number} height height of the Image (in units declared at inception of PDF document) + * @param {string} alias alias of the image (if used multiple times) + * @param {string} compression compression of the generated JPEG, can have the values 'NONE', 'FAST', 'MEDIUM' and 'SLOW' + * @param {number} rotation rotation of the image in degrees (0-359) + * + * @returns jsPDF + */ + + + jsPDFAPI.addImage = function (imageData, format, x, y, w, h, alias, compression, rotation) { + + var tmpImageData = ""; + + if (typeof format !== "string") { + var tmp = h; + h = w; + w = y; + y = x; + x = format; + format = tmp; + } + + if (_typeof(imageData) === "object" && !isDOMElement(imageData) && "imageData" in imageData) { + var options = imageData; + imageData = options.imageData; + format = options.format || format; + x = options.x || x || 0; + y = options.y || y || 0; + w = options.w || w; + h = options.h || h; + alias = options.alias || alias; + compression = options.compression || compression; + rotation = options.rotation || options.angle || rotation; + } + + if (typeof imageData === "string") { + imageData = unescape(imageData); + } + + if (isNaN(x) || isNaN(y)) { + console.error("jsPDF.addImage: Invalid coordinates", arguments); + throw new Error("Invalid coordinates passed to jsPDF.addImage"); + } + + var images = getImages.call(this), + info; + + if (!(info = checkImagesForAlias(imageData, images))) { + var dataAsBinaryString; + if (isDOMElement(imageData)) imageData = createDataURIFromElement(imageData, format); + if (notDefined(alias)) alias = generateAliasFromData(imageData); + + if (!(info = checkImagesForAlias(alias, images))) { + if (this.isString(imageData)) { + tmpImageData = this.convertStringToImageData(imageData); + + if (tmpImageData !== "") { + imageData = tmpImageData; + } else { + tmpImageData = this.loadImageFile(imageData); + + if (tmpImageData !== undefined) { + imageData = tmpImageData; + } + } + } + + format = this.getImageFileTypeByImageData(imageData, format); + if (!isImageTypeSupported(format)) throw new Error("addImage does not support files of type '" + format + "', please ensure that a plugin for '" + format + "' support is added."); + /** + * need to test if it's more efficient to convert all binary strings + * to TypedArray - or should we just leave and process as string? + */ + + if (this.supportsArrayBuffer()) { + // no need to convert if imageData is already uint8array + if (!(imageData instanceof Uint8Array)) { + dataAsBinaryString = imageData; + imageData = this.binaryStringToUint8Array(imageData); + } + } + + info = this["process" + format.toUpperCase()](imageData, getImageIndex(images), alias, checkCompressValue(compression), dataAsBinaryString); + if (!info) throw new Error("An unkwown error occurred whilst processing the image"); + } + } + + writeImageToPDF.call(this, x, y, w, h, info, info.i, images, rotation); + return this; + }; + /** + * @name convertStringToImageData + * @function + * @param {string} stringData + * @returns {string} binary data + */ + + + jsPDFAPI.convertStringToImageData = function (stringData) { + var base64Info; + var imageData = ""; + + if (this.isString(stringData)) { + var base64Info = this.extractInfoFromBase64DataURI(stringData); + + if (base64Info !== null) { + if (jsPDFAPI.validateStringAsBase64(base64Info[3])) { + imageData = atob(base64Info[3]); //convert to binary string + } + } else if (jsPDFAPI.validateStringAsBase64(stringData)) { + imageData = atob(stringData); + } + } + + return imageData; + }; + /** + * JPEG SUPPORT + **/ + //takes a string imgData containing the raw bytes of + //a jpeg image and returns [width, height] + //Algorithm from: http://www.64lines.com/jpeg-width-height + + + var getJpegSize = function getJpegSize(imgData) { + + var width, height, numcomponents; // Verify we have a valid jpeg header 0xff,0xd8,0xff,0xe0,?,?,'J','F','I','F',0x00 + + if (!imgData.charCodeAt(0) === 0xff || !imgData.charCodeAt(1) === 0xd8 || !imgData.charCodeAt(2) === 0xff || !imgData.charCodeAt(3) === 0xe0 || !imgData.charCodeAt(6) === "J".charCodeAt(0) || !imgData.charCodeAt(7) === "F".charCodeAt(0) || !imgData.charCodeAt(8) === "I".charCodeAt(0) || !imgData.charCodeAt(9) === "F".charCodeAt(0) || !imgData.charCodeAt(10) === 0x00) { + throw new Error("getJpegSize requires a binary string jpeg file"); + } + + var blockLength = imgData.charCodeAt(4) * 256 + imgData.charCodeAt(5); + var i = 4, + len = imgData.length; + + while (i < len) { + i += blockLength; + + if (imgData.charCodeAt(i) !== 0xff) { + throw new Error("getJpegSize could not find the size of the image"); + } + + if (imgData.charCodeAt(i + 1) === 0xc0 || //(SOF) Huffman - Baseline DCT + imgData.charCodeAt(i + 1) === 0xc1 || //(SOF) Huffman - Extended sequential DCT + imgData.charCodeAt(i + 1) === 0xc2 || // Progressive DCT (SOF2) + imgData.charCodeAt(i + 1) === 0xc3 || // Spatial (sequential) lossless (SOF3) + imgData.charCodeAt(i + 1) === 0xc4 || // Differential sequential DCT (SOF5) + imgData.charCodeAt(i + 1) === 0xc5 || // Differential progressive DCT (SOF6) + imgData.charCodeAt(i + 1) === 0xc6 || // Differential spatial (SOF7) + imgData.charCodeAt(i + 1) === 0xc7) { + height = imgData.charCodeAt(i + 5) * 256 + imgData.charCodeAt(i + 6); + width = imgData.charCodeAt(i + 7) * 256 + imgData.charCodeAt(i + 8); + numcomponents = imgData.charCodeAt(i + 9); + return [width, height, numcomponents]; + } else { + i += 2; + blockLength = imgData.charCodeAt(i) * 256 + imgData.charCodeAt(i + 1); + } + } + }, + getJpegSizeFromBytes = function getJpegSizeFromBytes(data) { + var hdr = data[0] << 8 | data[1]; + if (hdr !== 0xffd8) throw new Error("Supplied data is not a JPEG"); + var len = data.length, + block = (data[4] << 8) + data[5], + pos = 4, + bytes, + width, + height, + numcomponents; + + while (pos < len) { + pos += block; + bytes = readBytes(data, pos); + block = (bytes[2] << 8) + bytes[3]; + + if ((bytes[1] === 0xc0 || bytes[1] === 0xc2) && bytes[0] === 0xff && block > 7) { + bytes = readBytes(data, pos + 5); + width = (bytes[2] << 8) + bytes[3]; + height = (bytes[0] << 8) + bytes[1]; + numcomponents = bytes[4]; + return { + width: width, + height: height, + numcomponents: numcomponents + }; + } + + pos += 2; + } + + throw new Error("getJpegSizeFromBytes could not find the size of the image"); + }, + readBytes = function readBytes(data, offset) { + return data.subarray(offset, offset + 5); + }; + /** + * @ignore + */ + + + jsPDFAPI.processJPEG = function (data, index, alias, compression, dataAsBinaryString, colorSpace) { + + var filter = this.decode.DCT_DECODE, + bpc = 8, + dims; + + if (!this.isString(data) && !this.isArrayBuffer(data) && !this.isArrayBufferView(data)) { + return null; + } + + if (this.isString(data)) { + dims = getJpegSize(data); + } + + if (this.isArrayBuffer(data)) { + data = new Uint8Array(data); + } + + if (this.isArrayBufferView(data)) { + dims = getJpegSizeFromBytes(data); // if we already have a stored binary string rep use that + + data = dataAsBinaryString || this.arrayBufferToBinaryString(data); + } + + if (colorSpace === undefined) { + switch (dims.numcomponents) { + case 1: + colorSpace = this.color_spaces.DEVICE_GRAY; + break; + + case 4: + colorSpace = this.color_spaces.DEVICE_CMYK; + break; + + default: + case 3: + colorSpace = this.color_spaces.DEVICE_RGB; + break; + } + } + + return this.createImageInfo(data, dims.width, dims.height, colorSpace, bpc, filter, index, alias); + }; + /** + * @ignore + */ + + + jsPDFAPI.processJPG = function () + /*data, index, alias, compression, dataAsBinaryString*/ + { + return this.processJPEG.apply(this, arguments); + }; + /** + * @name loadImageFile + * @function + * @param {string} path + * @param {boolean} sync + * @param {function} callback + */ + + + jsPDFAPI.loadImageFile = function (path, sync, callback) { + sync = sync || true; + + callback = callback || function () {}; + + var isNode = Object.prototype.toString.call(typeof process !== "undefined" ? process : 0) === "[object process]"; + + var xhrMethod = function xhrMethod(url, sync, callback) { + var req = new XMLHttpRequest(); + var byteArray = []; + var i = 0; + + var sanitizeUnicode = function sanitizeUnicode(data) { + var dataLength = data.length; + var StringFromCharCode = String.fromCharCode; //Transform Unicode to ASCII + + for (i = 0; i < dataLength; i += 1) { + byteArray.push(StringFromCharCode(data.charCodeAt(i) & 0xff)); + } + + return byteArray.join(""); + }; + + req.open("GET", url, !sync); // XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com] + + req.overrideMimeType("text/plain; charset=x-user-defined"); + + if (sync === false) { + req.onload = function () { + return sanitizeUnicode(this.responseText); + }; + } + + req.send(null); + + if (req.status !== 200) { + console.warn('Unable to load file "' + url + '"'); + return; + } + + if (sync) { + return sanitizeUnicode(req.responseText); + } + }; //we have a browser and probably no CORS-Problem + + + if ((typeof window === "undefined" ? "undefined" : _typeof(window)) !== undefined && (typeof location === "undefined" ? "undefined" : _typeof(location)) === "object" && location.protocol.substr(0, 4) === "http") { + return xhrMethod(path, sync, callback); + } + }; + /** + * @name getImageProperties + * @function + * @param {Object} imageData + * @returns {Object} + */ + + + jsPDFAPI.getImageProperties = function (imageData) { + var info; + var tmpImageData = ""; + var format; + + if (isDOMElement(imageData)) { + imageData = createDataURIFromElement(imageData); + } + + if (this.isString(imageData)) { + tmpImageData = this.convertStringToImageData(imageData); + + if (tmpImageData !== "") { + imageData = tmpImageData; + } else { + tmpImageData = this.loadImageFile(imageData); + + if (tmpImageData !== undefined) { + imageData = tmpImageData; + } + } + } + + format = this.getImageFileTypeByImageData(imageData); + if (!isImageTypeSupported(format)) throw new Error("addImage does not support files of type '" + format + "', please ensure that a plugin for '" + format + "' support is added."); + /** + * need to test if it's more efficient to convert all binary strings + * to TypedArray - or should we just leave and process as string? + */ + + if (this.supportsArrayBuffer()) { + // no need to convert if imageData is already uint8array + if (!(imageData instanceof Uint8Array)) { + imageData = this.binaryStringToUint8Array(imageData); + } + } + + info = this["process" + format.toUpperCase()](imageData); + + if (!info) { + throw new Error("An unkwown error occurred whilst processing the image"); + } + + return { + fileType: format, + width: info.w, + height: info.h, + colorSpace: info.cs, + compressionMode: info.f, + bitsPerComponent: info.bpc + }; + }; + })(jsPDF.API); + + /** + * @license + * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * jsPDF Annotations PlugIn + * + * There are many types of annotations in a PDF document. Annotations are placed + * on a page at a particular location. They are not 'attached' to an object. + *
+ * This plugin current supports
+ *
  • Goto Page (set pageNumber and top in options) + *
  • Goto Name (set name and top in options) + *
  • Goto URL (set url in options) + *

    + * The destination magnification factor can also be specified when goto is a page number or a named destination. (see documentation below) + * (set magFactor in options). XYZ is the default. + *

    + *

    + * Links, Text, Popup, and FreeText are supported. + *

    + *

    + * Options In PDF spec Not Implemented Yet + *

  • link border + *
  • named target + *
  • page coordinates + *
  • destination page scaling and layout + *
  • actions other than URL and GotoPage + *
  • background / hover actions + *

    + * @name annotations + * @module + */ + + /* + Destination Magnification Factors + See PDF 1.3 Page 386 for meanings and options + + [supported] + XYZ (options; left top zoom) + Fit (no options) + FitH (options: top) + FitV (options: left) + + [not supported] + FitR + FitB + FitBH + FitBV + */ + (function (jsPDFAPI) { + + var annotationPlugin = { + /** + * An array of arrays, indexed by pageNumber. + */ + annotations: [], + f2: function f2(number) { + return number.toFixed(2); + }, + notEmpty: function notEmpty(obj) { + if (typeof obj != "undefined") { + if (obj != "") { + return true; + } + } + } + }; + jsPDF.API.annotationPlugin = annotationPlugin; + jsPDF.API.events.push(["addPage", function (info) { + this.annotationPlugin.annotations[info.pageNumber] = []; + }]); + jsPDFAPI.events.push(["putPage", function (info) { + //TODO store annotations in pageContext so reorder/remove will not affect them. + var pageAnnos = this.annotationPlugin.annotations[info.pageNumber]; + var found = false; + + for (var a = 0; a < pageAnnos.length && !found; a++) { + var anno = pageAnnos[a]; + + switch (anno.type) { + case "link": + if (annotationPlugin.notEmpty(anno.options.url) || annotationPlugin.notEmpty(anno.options.pageNumber)) { + found = true; + break; + } + + case "reference": + case "text": + case "freetext": + found = true; + break; + } + } + + if (found == false) { + return; + } + + this.internal.write("/Annots ["); + var f2 = this.annotationPlugin.f2; + var k = this.internal.scaleFactor; + var pageHeight = this.internal.pageSize.getHeight(); + var pageInfo = this.internal.getPageInfo(info.pageNumber); + + for (var a = 0; a < pageAnnos.length; a++) { + var anno = pageAnnos[a]; + + switch (anno.type) { + case "reference": + // References to Widget Anotations (for AcroForm Fields) + this.internal.write(" " + anno.object.objId + " 0 R "); + break; + + case "text": + // Create a an object for both the text and the popup + var objText = this.internal.newAdditionalObject(); + var objPopup = this.internal.newAdditionalObject(); + var title = anno.title || "Note"; + var rect = "/Rect [" + f2(anno.bounds.x * k) + " " + f2(pageHeight - (anno.bounds.y + anno.bounds.h) * k) + " " + f2((anno.bounds.x + anno.bounds.w) * k) + " " + f2((pageHeight - anno.bounds.y) * k) + "] "; + line = "<>"; + objText.content = line; + var parent = objText.objId + " 0 R"; + var popoff = 30; + var rect = "/Rect [" + f2((anno.bounds.x + popoff) * k) + " " + f2(pageHeight - (anno.bounds.y + anno.bounds.h) * k) + " " + f2((anno.bounds.x + anno.bounds.w + popoff) * k) + " " + f2((pageHeight - anno.bounds.y) * k) + "] "; //var rect2 = "/Rect [" + f2(anno.bounds.x * k) + " " + f2((pageHeight - anno.bounds.y) * k) + " " + f2(anno.bounds.x + anno.bounds.w * k) + " " + f2(pageHeight - (anno.bounds.y + anno.bounds.h) * k) + "] "; + + line = "<>"; + } else if (anno.options.pageNumber) { + // first page is 0 + var info = this.internal.getPageInfo(anno.options.pageNumber); + line = "< pageNumber or url [required] + *

    If pageNumber is specified, top and zoom may also be specified

    + * @name link + * @function + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @param {Object} options + */ + + + jsPDFAPI.link = function (x, y, w, h, options) { + + this.annotationPlugin.annotations[this.internal.getCurrentPageInfo().pageNumber].push({ + x: x, + y: y, + w: w, + h: h, + options: options, + type: "link" + }); + }; + /** + * Currently only supports single line text. + * Returns the width of the text/link + * + * @name textWithLink + * @function + * @param {string} text + * @param {number} x + * @param {number} y + * @param {Object} options + * @returns {number} width the width of the text/link + */ + + + jsPDFAPI.textWithLink = function (text, x, y, options) { + + var width = this.getTextWidth(text); + var height = this.internal.getLineHeight() / this.internal.scaleFactor; + this.text(text, x, y); //TODO We really need the text baseline height to do this correctly. + // Or ability to draw text on top, bottom, center, or baseline. + + y += height * 0.2; + this.link(x, y - height, width, height, options); + return width; + }; //TODO move into external library + + /** + * @name getTextWidth + * @function + * @param {string} text + * @returns {number} txtWidth + */ + + + jsPDFAPI.getTextWidth = function (text) { + + var fontSize = this.internal.getFontSize(); + var txtWidth = this.getStringUnitWidth(text) * fontSize / this.internal.scaleFactor; + return txtWidth; + }; //TODO move into external library + + /** + * @name getLineHeight + * @function + * @returns {number} lineHeight + */ + + + jsPDFAPI.getLineHeight = function () { + return this.internal.getLineHeight(); + }; + + return this; + })(jsPDF.API); + + /** + * @license + * Copyright (c) 2017 Aras Abbasi + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * jsPDF arabic parser PlugIn + * + * @name arabic + * @module + */ + (function (jsPDFAPI) { + + var arLangCodes = { + ar: "Arabic (Standard)", + "ar-DZ": "Arabic (Algeria)", + "ar-BH": "Arabic (Bahrain)", + "ar-EG": "Arabic (Egypt)", + "ar-IQ": "Arabic (Iraq)", + "ar-JO": "Arabic (Jordan)", + "ar-KW": "Arabic (Kuwait)", + "ar-LB": "Arabic (Lebanon)", + "ar-LY": "Arabic (Libya)", + "ar-MA": "Arabic (Morocco)", + "ar-OM": "Arabic (Oman)", + "ar-QA": "Arabic (Qatar)", + "ar-SA": "Arabic (Saudi Arabia)", + "ar-SY": "Arabic (Syria)", + "ar-TN": "Arabic (Tunisia)", + "ar-AE": "Arabic (U.A.E.)", + "ar-YE": "Arabic (Yemen)", + fa: "Persian", + "fa-IR": "Persian/Iran", + ur: "Urdu" + }; + var arLangCodesKeys = Object.keys(arLangCodes); + /** + * Arabic shape substitutions: char code => (isolated, final, initial, medial). + */ + + var arabicSubst = { + 1569: [65152], + 1570: [65153, 65154, 65153, 65154], + 1571: [65155, 65156, 65155, 65156], + 1572: [65157, 65158], + 1573: [65159, 65160, 65159, 65160], + 1574: [65161, 65162, 65163, 65164], + 1575: [65165, 65166, 65165, 65166], + 1576: [65167, 65168, 65169, 65170], + 1577: [65171, 65172], + 1578: [65173, 65174, 65175, 65176], + 1579: [65177, 65178, 65179, 65180], + 1580: [65181, 65182, 65183, 65184], + 1581: [65185, 65186, 65187, 65188], + 1582: [65189, 65190, 65191, 65192], + 1583: [65193, 65194, 65193], + 1584: [65195, 65196, 65195], + 1585: [65197, 65198, 65197], + 1586: [65199, 65200, 65199], + 1587: [65201, 65202, 65203, 65204], + 1588: [65205, 65206, 65207, 65208], + 1589: [65209, 65210, 65211, 65212], + 1590: [65213, 65214, 65215, 65216], + 1591: [65217, 65218, 65219, 65220], + 1592: [65221, 65222, 65223, 65224], + 1593: [65225, 65226, 65227, 65228], + 1594: [65229, 65230, 65231, 65232], + 1601: [65233, 65234, 65235, 65236], + 1602: [65237, 65238, 65239, 65240], + 1603: [65241, 65242, 65243, 65244], + 1604: [65245, 65246, 65247, 65248], + 1605: [65249, 65250, 65251, 65252], + 1606: [65253, 65254, 65255, 65256], + 1607: [65257, 65258, 65259, 65260], + 1608: [65261, 65262, 65261], + 1609: [65263, 65264, 64488, 64489], + 1610: [65265, 65266, 65267, 65268], + 1649: [64336, 64337], + 1655: [64477], + 1657: [64358, 64359, 64360, 64361], + 1658: [64350, 64351, 64352, 64353], + 1659: [64338, 64339, 64340, 64341], + 1662: [64342, 64343, 64344, 64345], + 1663: [64354, 64355, 64356, 64357], + 1664: [64346, 64347, 64348, 64349], + 1667: [64374, 64375, 64376, 64377], + 1668: [64370, 64371, 64372, 64373], + 1670: [64378, 64379, 64380, 64381], + 1671: [64382, 64383, 64384, 64385], + 1672: [64392, 64393], + 1676: [64388, 64389], + 1677: [64386, 64387], + 1678: [64390, 64391], + 1681: [64396, 64397], + 1688: [64394, 64395, 64394], + 1700: [64362, 64363, 64364, 64365], + 1702: [64366, 64367, 64368, 64369], + 1705: [64398, 64399, 64400, 64401], + 1709: [64467, 64468, 64469, 64470], + 1711: [64402, 64403, 64404, 64405], + 1713: [64410, 64411, 64412, 64413], + 1715: [64406, 64407, 64408, 64409], + 1722: [64414, 64415], + 1723: [64416, 64417, 64418, 64419], + 1726: [64426, 64427, 64428, 64429], + 1728: [64420, 64421], + 1729: [64422, 64423, 64424, 64425], + 1733: [64480, 64481], + 1734: [64473, 64474], + 1735: [64471, 64472], + 1736: [64475, 64476], + 1737: [64482, 64483], + 1739: [64478, 64479], + 1740: [64508, 64509, 64510, 64511], + 1744: [64484, 64485, 64486, 64487], + 1746: [64430, 64431], + 1747: [64432, 64433] + }; + var arabiclaasubst = { + 1570: [65269, 65270, 65269, 65270], + 1571: [65271, 65272, 65271, 65272], + 1573: [65273, 65274, 65273, 65274], + 1575: [65275, 65276, 65275, 65276] + }; + var arabicorigsubst = { + 1570: [65153, 65154, 65153, 65154], + 1571: [65155, 65156, 65155, 65156], + 1573: [65159, 65160, 65159, 65160], + 1575: [65165, 65166, 65165, 65166] + }; + var arabic_diacritics = { + 1612: 64606, + // Shadda + Dammatan + 1613: 64607, + // Shadda + Kasratan + 1614: 64608, + // Shadda + Fatha + 1615: 64609, + // Shadda + Damma + 1616: 64610 // Shadda + Kasra + + }; + var alfletter = [1570, 1571, 1573, 1575]; + var endedletter = [1569, 1570, 1571, 1572, 1573, 1575, 1577, 1583, 1584, 1585, 1586, 1608, 1688]; + var isolatedForm = 0; + var finalForm = 1; + var initialForm = 2; + var medialForm = 3; //private + + function isArabicLetter(letter) { + return letter !== undefined && arabicSubst[letter.charCodeAt(0)] !== undefined; + } + + function isArabicEndLetter(letter) { + return letter !== undefined && endedletter.indexOf(letter.charCodeAt(0)) >= 0; + } + + function isArabicAlfLetter(letter) { + return letter !== undefined && alfletter.indexOf(letter.charCodeAt(0)) >= 0; + } + + function arabicLetterHasFinalForm(letter) { + return isArabicLetter(letter) && arabicSubst[letter.charCodeAt(0)].length >= 2; + } + + function arabicLetterHasMedialForm(letter) { + return isArabicLetter(letter) && arabicSubst[letter.charCodeAt(0)].length == 4; + } + + function isArabicDiacritic(letter) { + return letter !== undefined && arabic_diacritics[letter.charCodeAt(0)] !== undefined; + } + + function getCorrectForm(currentChar, beforeChar, nextChar, arabicSubstition) { + + if (!isArabicLetter(currentChar)) { + return -1; + } + + arabicSubstition = arabicSubstition || {}; + arabicSubst = Object.assign(arabicSubst, arabicSubstition); + + if (!arabicLetterHasFinalForm(currentChar) || !isArabicLetter(beforeChar) && !isArabicLetter(nextChar) || !isArabicLetter(nextChar) && isArabicEndLetter(beforeChar) || isArabicEndLetter(currentChar) && !isArabicLetter(beforeChar) || isArabicEndLetter(currentChar) && isArabicAlfLetter(beforeChar) || isArabicEndLetter(currentChar) && isArabicEndLetter(beforeChar)) { + arabicSubst = Object.assign(arabicSubst, arabicorigsubst); + return isolatedForm; + } + + if (arabicLetterHasMedialForm(currentChar) && isArabicLetter(beforeChar) && !isArabicEndLetter(beforeChar) && isArabicLetter(nextChar) && arabicLetterHasFinalForm(nextChar)) { + arabicSubst = Object.assign(arabicSubst, arabicorigsubst); + return medialForm; + } + + if (isArabicEndLetter(currentChar) || !isArabicLetter(nextChar)) { + arabicSubst = Object.assign(arabicSubst, arabicorigsubst); + return finalForm; + } + + arabicSubst = Object.assign(arabicSubst, arabicorigsubst); + return initialForm; + } + + var commonSubstition = function commonSubstition(character) { + var replacementTable = { + "(": ")", + ")": "(" + }; + return replacementTable[character] || character; + }; + /** + * @name processArabic + * @function + * @param {string} text + * @param {boolean} reverse + * @returns {string} + */ + + + var processArabic = jsPDFAPI.processArabic = function (text, reverse) { + text = text || ""; + reverse = reverse || false; + var result = ""; + var i = 0; + var position = 0; + var currentLetter = ""; + var prevLetter = ""; + var nextLetter = ""; + var resultingLetter; + var localPrevLetter; + var localCurrentLetter; + var localNextLetter; + + for (i = 0; i < text.length; i += 1) { + currentLetter = text[i]; + prevLetter = text[i - 1]; + nextLetter = text[i + 1]; + + if (!isArabicLetter(currentLetter)) { + result += reverse ? commonSubstition(currentLetter) : currentLetter; + } else { + if (prevLetter !== undefined && prevLetter.charCodeAt(0) === 1604 && isArabicAlfLetter(currentLetter)) { + localPrevLetter = text[i - 2]; + localCurrentLetter = currentLetter; + localNextLetter = text[i + 1]; + position = getCorrectForm(localCurrentLetter, localPrevLetter, localNextLetter, arabiclaasubst); + resultingLetter = String.fromCharCode(arabiclaasubst[currentLetter.charCodeAt(0)][position]); + result = result.substr(0, result.length - 1) + resultingLetter; + } else if (prevLetter !== undefined && prevLetter.charCodeAt(0) === 1617 && isArabicDiacritic(currentLetter)) { + localPrevLetter = text[i - 2]; + localCurrentLetter = currentLetter; + localNextLetter = text[i + 1]; + position = getCorrectForm(localCurrentLetter, localPrevLetter, localNextLetter, arabicorigsubst); + resultingLetter = String.fromCharCode(arabic_diacritics[currentLetter.charCodeAt(0)][position]); + result = result.substr(0, result.length - 1) + resultingLetter; + } else { + position = getCorrectForm(currentLetter, prevLetter, nextLetter, arabicorigsubst); + result += String.fromCharCode(arabicSubst[currentLetter.charCodeAt(0)][position]); + } + } + } + + return reverse ? result.split("").reverse().join("") : result; + }; + + var arabicParserFunction = function arabicParserFunction(args) { + var text = args.text; + var x = args.x; + var y = args.y; + var options = args.options || {}; + var mutex = args.mutex || {}; + var lang = options.lang; + var tmpText = []; + + if (arLangCodesKeys.indexOf(lang) >= 0) { + if (Object.prototype.toString.call(text) === "[object Array]") { + var i = 0; + tmpText = []; + + for (i = 0; i < text.length; i += 1) { + if (Object.prototype.toString.call(text[i]) === "[object Array]") { + tmpText.push([processArabic(text[i][0], true), text[i][1], text[i][2]]); + } else { + tmpText.push([processArabic(text[i], true)]); + } + } + + args.text = tmpText; + } else { + args.text = processArabic(text, true); + } //force charSpace if not given. + + + if (options.charSpace === undefined) { + args.options.charSpace = 0; + } //if R2L is true, set it false. + + + if (options.R2L === true) { + args.options.R2L = false; + } + } + }; + + jsPDFAPI.events.push(["preProcessText", arabicParserFunction]); + })(jsPDF.API); + + /** @license + * jsPDF Autoprint Plugin + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * @name autoprint + * @module + */ + (function (jsPDFAPI) { + /** + * Makes the PDF automatically print. This works in Chrome, Firefox, Acrobat + * Reader. + * + * @name autoPrint + * @function + * @param {Object} options (optional) Set the attribute variant to 'non-conform' (default) or 'javascript' to activate different methods of automatic printing when opening in a PDF-viewer . + * @returns {jsPDF} + * @example + * var doc = new jsPDF(); + * doc.text(10, 10, 'This is a test'); + * doc.autoPrint({variant: 'non-conform'}); + * doc.save('autoprint.pdf'); + */ + + jsPDFAPI.autoPrint = function (options) { + + var refAutoPrintTag; + options = options || {}; + options.variant = options.variant || "non-conform"; + + switch (options.variant) { + case "javascript": + //https://github.com/Rob--W/pdf.js/commit/c676ecb5a0f54677b9f3340c3ef2cf42225453bb + this.addJS("print({});"); + break; + + case "non-conform": + default: + this.internal.events.subscribe("postPutResources", function () { + refAutoPrintTag = this.internal.newObject(); + this.internal.out("<<"); + this.internal.out("/S /Named"); + this.internal.out("/Type /Action"); + this.internal.out("/N /Print"); + this.internal.out(">>"); + this.internal.out("endobj"); + }); + this.internal.events.subscribe("putCatalog", function () { + this.internal.out("/OpenAction " + refAutoPrintTag + " 0 R"); + }); + break; + } + + return this; + }; + })(jsPDF.API); + + /** + * @license + * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * jsPDF Canvas PlugIn + * This plugin mimics the HTML5 Canvas + * + * The goal is to provide a way for current canvas users to print directly to a PDF. + * @name canvas + * @module + */ + (function (jsPDFAPI) { + + jsPDFAPI.events.push(["initialized", function () { + this.canvas.pdf = this; + }]); + /** + * @name canvas + * @static + * @type {Object} + */ + + jsPDFAPI.canvas = { + /** + * @name getContext + * @function + * @param {string} the context type + */ + getContext: function getContext(name) { + this.pdf.context2d._canvas = this; + return this.pdf.context2d; + }, + childNodes: [], + style: {}, + autoContext2dResizeX: true, + autoContext2dResizeY: true + }; + /** + * Width of the canvas + * + * @name width + * @property {number} width + */ + + Object.defineProperty(jsPDFAPI.canvas, "width", { + get: function get() { + return this._width; + }, + set: function set(value) { + this._width = value; + + if (this.autoContext2dResizeX) { + this.getContext("2d").pageWrapX = value + 1; + } + } + }); + /** + * Height of the canvas + * + * @name height + * @property {number} height + */ + + Object.defineProperty(jsPDFAPI.canvas, "height", { + get: function get() { + return this._height; + }, + set: function set(value) { + this._height = value; + + if (this.autoContext2dResizeY) { + this.getContext("2d").pageWrapY = value + 1; + } + } + }); + return this; + })(jsPDF.API); + + /** + * @license + * ==================================================================== + * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com + * 2013 Eduardo Menezes de Morais, eduardo.morais@usp.br + * 2013 Lee Driscoll, https://github.com/lsdriscoll + * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria + * 2014 James Hall, james@parall.ax + * 2014 Diego Casorran, https://github.com/diegocr + * + * + * ==================================================================== + */ + + /** + * @name cell + * @module + */ + (function (jsPDFAPI) { + /*jslint browser:true */ + + /*global document: false, jsPDF */ + + var padding = 3, + margin = 13, + headerFunction, + lastCellPos = { + x: undefined, + y: undefined, + w: undefined, + h: undefined, + ln: undefined + }, + pages = 1, + setLastCellPosition = function setLastCellPosition(x, y, w, h, ln) { + lastCellPos = { + x: x, + y: y, + w: w, + h: h, + ln: ln + }; + }, + getLastCellPosition = function getLastCellPosition() { + return lastCellPos; + }, + NO_MARGINS = { + left: 0, + top: 0, + bottom: 0 + }; + /** + * @name setHeaderFunction + * @function + * @param {function} func + */ + + + jsPDFAPI.setHeaderFunction = function (func) { + headerFunction = func; + }; + /** + * @name getTextDimensions + * @function + * @param {string} txt + * @returns {Object} dimensions + */ + + + jsPDFAPI.getTextDimensions = function (text, options) { + var fontSize = this.table_font_size || this.internal.getFontSize(); + var fontStyle = this.internal.getFont().fontStyle; + options = options || {}; + var scaleFactor = options.scaleFactor || this.internal.scaleFactor; + var width = 0; + var amountOfLines = 0; + var height = 0; + var tempWidth = 0; + + if (typeof text === "string") { + width = this.getStringUnitWidth(text) * fontSize; + + if (width !== 0) { + amountOfLines = 1; + } + } else if (Object.prototype.toString.call(text) === "[object Array]") { + for (var i = 0; i < text.length; i++) { + tempWidth = this.getStringUnitWidth(text[i]) * fontSize; + + if (width < tempWidth) { + width = tempWidth; + } + } + + if (width !== 0) { + amountOfLines = text.length; + } + } else { + console.error("getTextDimensions expects text-parameter to be of type String or an Array of Strings."); + } + + width = width / scaleFactor; + height = amountOfLines * fontSize * 1.15 / scaleFactor; + return { + w: width, + h: height + }; + }; + /** + * @name cellAddPage + * @function + */ + + + jsPDFAPI.cellAddPage = function () { + var margins = this.margins || NO_MARGINS; + this.addPage(); + setLastCellPosition(margins.left, margins.top, undefined, undefined); //setLastCellPosition(undefined, undefined, undefined, undefined, undefined); + + pages += 1; + }; + /** + * @name cellInitialize + * @function + */ + + + jsPDFAPI.cellInitialize = function () { + lastCellPos = { + x: undefined, + y: undefined, + w: undefined, + h: undefined, + ln: undefined + }; + pages = 1; + }; + /** + * @name cell + * @function + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @param {string} txt + * @param {number} ln lineNumber + * @param {string} align + * @return {jsPDF} jsPDF-instance + */ + + + jsPDFAPI.cell = function (x, y, w, h, txt, ln, align) { + var curCell = getLastCellPosition(); + var pgAdded = false; // If this is not the first cell, we must change its position + + if (curCell.ln !== undefined) { + if (curCell.ln === ln) { + //Same line + x = curCell.x + curCell.w; + y = curCell.y; + } else { + //New line + var margins = this.margins || NO_MARGINS; + + if (curCell.y + curCell.h + h + margin >= this.internal.pageSize.getHeight() - margins.bottom) { + this.cellAddPage(); + pgAdded = true; + + if (this.printHeaders && this.tableHeaderRow) { + this.printHeaderRow(ln, true); + } + } //We ignore the passed y: the lines may have different heights + + + y = getLastCellPosition().y + getLastCellPosition().h; + if (pgAdded) y = margin + 10; + } + } + + if (txt[0] !== undefined) { + if (this.printingHeaderRow) { + this.rect(x, y, w, h, "FD"); + } else { + this.rect(x, y, w, h); + } + + if (align === "right") { + if (!(txt instanceof Array)) { + txt = [txt]; + } + + for (var i = 0; i < txt.length; i++) { + var currentLine = txt[i]; + var textSize = this.getStringUnitWidth(currentLine) * this.internal.getFontSize(); + this.text(currentLine, x + w - textSize - padding, y + this.internal.getLineHeight() * (i + 1)); + } + } else { + this.text(txt, x + padding, y + this.internal.getLineHeight()); + } + } + + setLastCellPosition(x, y, w, h, ln); + return this; + }; + /** + * Return the maximum value from an array + * + * @name arrayMax + * @function + * @param {Array} array + * @param comparisonFn + * @returns {number} + */ + + + jsPDFAPI.arrayMax = function (array, comparisonFn) { + var max = array[0], + i, + ln, + item; + + for (i = 0, ln = array.length; i < ln; i += 1) { + item = array[i]; + + if (comparisonFn) { + if (comparisonFn(max, item) === -1) { + max = item; + } + } else { + if (item > max) { + max = item; + } + } + } + + return max; + }; + /** + * Create a table from a set of data. + * @name table + * @function + * @param {Integer} [x] : left-position for top-left corner of table + * @param {Integer} [y] top-position for top-left corner of table + * @param {Object[]} [data] As array of objects containing key-value pairs corresponding to a row of data. + * @param {String[]} [headers] Omit or null to auto-generate headers at a performance cost + * @param {Object} [config.printHeaders] True to print column headers at the top of every page + * @param {Object} [config.autoSize] True to dynamically set the column widths to match the widest cell value + * @param {Object} [config.margins] margin values for left, top, bottom, and width + * @param {Object} [config.fontSize] Integer fontSize to use (optional) + * @returns {jsPDF} jsPDF-instance + */ + + + jsPDFAPI.table = function (x, y, data, headers, config) { + if (!data) { + throw "No data for PDF table"; + } + + var headerNames = [], + headerPrompts = [], + header, + i, + ln, + cln, + columnMatrix = {}, + columnWidths = {}, + columnData, + column, + columnMinWidths = [], + j, + tableHeaderConfigs = [], + model, + jln, + func, + //set up defaults. If a value is provided in config, defaults will be overwritten: + autoSize = false, + printHeaders = true, + fontSize = 12, + margins = NO_MARGINS; + margins.width = this.internal.pageSize.getWidth(); + + if (config) { + //override config defaults if the user has specified non-default behavior: + if (config.autoSize === true) { + autoSize = true; + } + + if (config.printHeaders === false) { + printHeaders = false; + } + + if (config.fontSize) { + fontSize = config.fontSize; + } + + if (config.css && typeof config.css["font-size"] !== "undefined") { + fontSize = config.css["font-size"] * 16; + } + + if (config.margins) { + margins = config.margins; + } + } + /** + * @property {Number} lnMod + * Keep track of the current line number modifier used when creating cells + */ + + + this.lnMod = 0; + lastCellPos = { + x: undefined, + y: undefined, + w: undefined, + h: undefined, + ln: undefined + }, pages = 1; + this.printHeaders = printHeaders; + this.margins = margins; + this.setFontSize(fontSize); + this.table_font_size = fontSize; // Set header values + + if (headers === undefined || headers === null) { + // No headers defined so we derive from data + headerNames = Object.keys(data[0]); + } else if (headers[0] && typeof headers[0] !== "string") { + var px2pt = 0.264583 * 72 / 25.4; // Split header configs into names and prompts + + for (i = 0, ln = headers.length; i < ln; i += 1) { + header = headers[i]; + headerNames.push(header.name); + headerPrompts.push(header.prompt); + columnWidths[header.name] = header.width * px2pt; + } + } else { + headerNames = headers; + } + + if (autoSize) { + // Create a matrix of columns e.g., {column_title: [row1_Record, row2_Record]} + func = function func(rec) { + return rec[header]; + }; + + for (i = 0, ln = headerNames.length; i < ln; i += 1) { + header = headerNames[i]; + columnMatrix[header] = data.map(func); // get header width + + columnMinWidths.push(this.getTextDimensions(headerPrompts[i] || header, { + scaleFactor: 1 + }).w); + column = columnMatrix[header]; // get cell widths + + for (j = 0, cln = column.length; j < cln; j += 1) { + columnData = column[j]; + columnMinWidths.push(this.getTextDimensions(columnData, { + scaleFactor: 1 + }).w); + } // get final column width + + + columnWidths[header] = jsPDFAPI.arrayMax(columnMinWidths); //have to reset + + columnMinWidths = []; + } + } // -- Construct the table + + + if (printHeaders) { + var lineHeight = this.calculateLineHeight(headerNames, columnWidths, headerPrompts.length ? headerPrompts : headerNames); // Construct the header row + + for (i = 0, ln = headerNames.length; i < ln; i += 1) { + header = headerNames[i]; + tableHeaderConfigs.push([x, y, columnWidths[header], lineHeight, String(headerPrompts.length ? headerPrompts[i] : header)]); + } // Store the table header config + + + this.setTableHeaderRow(tableHeaderConfigs); // Print the header for the start of the table + + this.printHeaderRow(1, false); + } // Construct the data rows + + + for (i = 0, ln = data.length; i < ln; i += 1) { + var lineHeight; + model = data[i]; + lineHeight = this.calculateLineHeight(headerNames, columnWidths, model); + + for (j = 0, jln = headerNames.length; j < jln; j += 1) { + header = headerNames[j]; + this.cell(x, y, columnWidths[header], lineHeight, model[header], i + 2, header.align); + } + } + + this.lastCellPos = lastCellPos; + this.table_x = x; + this.table_y = y; + return this; + }; + /** + * Calculate the height for containing the highest column + * + * @name calculateLineHeight + * @function + * @param {String[]} headerNames is the header, used as keys to the data + * @param {Integer[]} columnWidths is size of each column + * @param {Object[]} model is the line of data we want to calculate the height of + * @returns {number} lineHeight + */ + + + jsPDFAPI.calculateLineHeight = function (headerNames, columnWidths, model) { + var header, + lineHeight = 0; + + for (var j = 0; j < headerNames.length; j++) { + header = headerNames[j]; + model[header] = this.splitTextToSize(String(model[header]), columnWidths[header] - padding); + var h = this.internal.getLineHeight() * model[header].length + padding; + if (h > lineHeight) lineHeight = h; + } + + return lineHeight; + }; + /** + * Store the config for outputting a table header + * + * @name setTableHeaderRow + * @function + * @param {Object[]} config + * An array of cell configs that would define a header row: Each config matches the config used by jsPDFAPI.cell + * except the ln parameter is excluded + */ + + + jsPDFAPI.setTableHeaderRow = function (config) { + this.tableHeaderRow = config; + }; + /** + * Output the store header row + * + * @name printHeaderRow + * @function + * @param {number} lineNumber The line number to output the header at + * @param {boolean} new_page + */ + + + jsPDFAPI.printHeaderRow = function (lineNumber, new_page) { + if (!this.tableHeaderRow) { + throw "Property tableHeaderRow does not exist."; + } + + var tableHeaderCell, tmpArray, i, ln; + this.printingHeaderRow = true; + + if (headerFunction !== undefined) { + var position = headerFunction(this, pages); + setLastCellPosition(position[0], position[1], position[2], position[3], -1); + } + + this.setFontStyle("bold"); + var tempHeaderConf = []; + + for (i = 0, ln = this.tableHeaderRow.length; i < ln; i += 1) { + this.setFillColor(200, 200, 200); + tableHeaderCell = this.tableHeaderRow[i]; + + if (new_page) { + this.margins.top = margin; + tableHeaderCell[1] = this.margins && this.margins.top || 0; + tempHeaderConf.push(tableHeaderCell); + } + + tmpArray = [].concat(tableHeaderCell); + this.cell.apply(this, tmpArray.concat(lineNumber)); + } + + if (tempHeaderConf.length > 0) { + this.setTableHeaderRow(tempHeaderConf); + } + + this.setFontStyle("normal"); + this.printingHeaderRow = false; + }; + })(jsPDF.API); + + /** + * jsPDF Context2D PlugIn Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv + * + * Licensed under the MIT License. http://opensource.org/licenses/mit-license + */ + + /** + * TODO implement stroke opacity (refactor from fill() method ) + * TODO transform angle and radii parameters + */ + + /** + * This plugin mimics the HTML5 Canvas's context2d. + * + * The goal is to provide a way for current canvas implementations to print directly to a PDF. + * + * @name context2d + * @module + */ + (function (jsPDFAPI, globalObj) { + + jsPDFAPI.events.push(["initialized", function () { + this.context2d.pdf = this; + this.context2d.internal.pdf = this; + this.context2d.ctx = new context(); + this.context2d.ctxStack = []; + this.context2d.path = []; + }]); + jsPDFAPI.context2d = { + /** + * @name pageWrapXEnabled + * @type {boolean} + * @default false + */ + pageWrapXEnabled: false, + + /** + * @name pageWrapYEnabled + * @type {boolean} + * @default false + */ + pageWrapYEnabled: false, + + /** + * @name pageWrapX + * @type {number} + * @default 9999999 + */ + pageWrapX: 9999999, + + /** + * @name pageWrapY + * @type {number} + * @default 9999999 + */ + pageWrapY: 9999999, + + /** + * @name ctx + * @type {Object} + */ + ctx: new context(), + + /** + * @name f2 + * @type {function} + * @ignore + */ + f2: function f2(number) { + return number.toFixed(2); + }, + + /** + * Fills the current drawing (path) + * + * @name fill + * @function + * @description The fill() method fills the current drawing (path). The default color is black. + */ + fill: function fill() { + //evenodd or nonzero (default) + var rule = "fill"; + + this._drawPaths(rule, false); + }, + + /** + * Actually draws the path you have defined + * + * @name stroke + * @function + * @description The stroke() method actually draws the path you have defined with all those moveTo() and lineTo() methods. The default color is black. + */ + stroke: function stroke() { + var rule = "stroke"; + + this._drawPaths(rule, false); + }, + + /** + * Begins a path, or resets the current + * + * @name beginPath + * @function + * @description The beginPath() method begins a path, or resets the current path. + */ + beginPath: function beginPath() { + this._resetPath(); + + this._beginPath(); + }, + + /** + * Moves the path to the specified point in the canvas, without creating a line + * + * @name moveTo + * @function + * @param x {Number} The x-coordinate of where to move the path to + * @param y {Number} The y-coordinate of where to move the path to + */ + moveTo: function moveTo(x, y) { + x = this._wrapX(x); + y = this._wrapY(y); + + var xpt = this._matrix_map_point(this.ctx._transform, [x, y]); + + x = xpt[0]; + y = xpt[1]; + var obj = { + type: "mt", + x: x, + y: y + }; + this.path.push(obj); + }, + + /** + * Creates a path from the current point back to the starting point + * + * @name closePath + * @function + * @description The closePath() method creates a path from the current point back to the starting point. + */ + closePath: function closePath() { + this._closePath(); + + var obj = { + type: "close" + }; + this.path.push(obj); + }, + + /** + * Adds a new point and creates a line to that point from the last specified point in the canvas + * + * @name lineTo + * @function + * @param x The x-coordinate of where to create the line to + * @param y The y-coordinate of where to create the line to + * @description The lineTo() method adds a new point and creates a line TO that point FROM the last specified point in the canvas (this method does not draw the line). + */ + lineTo: function lineTo(x, y) { + x = this._wrapX(x); + y = this._wrapY(y); + + var xpt = this._matrix_map_point(this.ctx._transform, [x, y]); + + x = xpt[0]; + y = xpt[1]; + var obj = { + type: "lt", + x: x, + y: y + }; + this.path.push(obj); + }, + + /** + * Clips a region of any shape and size from the original canvas + * + * @name clip + * @function + * @description The clip() method clips a region of any shape and size from the original canvas. + */ + clip: function clip() { + this._drawPaths(null, true); + }, + + /** + * Creates a cubic Bézier curve + * + * @name quadraticCurveTo + * @function + * @param cpx {Number} The x-coordinate of the Bézier control point + * @param cpy {Number} The y-coordinate of the Bézier control point + * @param x {Number} The x-coordinate of the ending point + * @param y {Number} The y-coordinate of the ending point + * @description The quadraticCurveTo() method adds a point to the current path by using the specified control points that represent a quadratic Bézier curve.

    A quadratic Bézier curve requires two points. The first point is a control point that is used in the quadratic Bézier calculation and the second point is the ending point for the curve. The starting point for the curve is the last point in the current path. If a path does not exist, use the beginPath() and moveTo() methods to define a starting point. + */ + quadraticCurveTo: function quadraticCurveTo(cpx, cpy, x, y) { + var x1 = this._wrapX(cpx); + + var y1 = this._wrapY(cpy); + + x = this._wrapX(x); + y = this._wrapY(y); + var xpt; + xpt = this._matrix_map_point(this.ctx._transform, [x, y]); + x = xpt[0]; + y = xpt[1]; + xpt = this._matrix_map_point(this.ctx._transform, [x1, y1]); + x1 = xpt[0]; + y1 = xpt[1]; + var obj = { + type: "qct", + x1: x1, + y1: y1, + x: x, + y: y + }; + this.path.push(obj); + }, + + /** + * Creates a cubic Bézier curve + * + * @name bezierCurveTo + * @function + * @param cp1x {Number} The x-coordinate of the first Bézier control point + * @param cp1y {Number} The y-coordinate of the first Bézier control point + * @param cp2x {Number} The x-coordinate of the second Bézier control point + * @param cp2y {Number} The y-coordinate of the second Bézier control point + * @param x {Number} The x-coordinate of the ending point + * @param y {Number} The y-coordinate of the ending point + * @description The bezierCurveTo() method adds a point to the current path by using the specified control points that represent a cubic Bézier curve.

    A cubic bezier curve requires three points. The first two points are control points that are used in the cubic Bézier calculation and the last point is the ending point for the curve. The starting point for the curve is the last point in the current path. If a path does not exist, use the beginPath() and moveTo() methods to define a starting point. + */ + bezierCurveTo: function bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) { + var x1 = this._wrapX(cp1x); + + var y1 = this._wrapY(cp1y); + + var x2 = this._wrapX(cp2x); + + var y2 = this._wrapY(cp2y); + + x = this._wrapX(x); + y = this._wrapY(y); + var xpt; + xpt = this._matrix_map_point(this.ctx._transform, [x, y]); + x = xpt[0]; + y = xpt[1]; + xpt = this._matrix_map_point(this.ctx._transform, [x1, y1]); + x1 = xpt[0]; + y1 = xpt[1]; + xpt = this._matrix_map_point(this.ctx._transform, [x2, y2]); + x2 = xpt[0]; + y2 = xpt[1]; + var obj = { + type: "bct", + x1: x1, + y1: y1, + x2: x2, + y2: y2, + x: x, + y: y + }; + this.path.push(obj); + }, + + /** + * Creates an arc/curve (used to create circles, or parts of circles) + * + * @name arc + * @function + * @param x {Number} The x-coordinate of the center of the circle + * @param y {Number} The y-coordinate of the center of the circle + * @param radius {Number} The radius of the circle + * @param startAngle {Number} The starting angle, in radians (0 is at the 3 o'clock position of the arc's circle) + * @param endAngle {Number} The ending angle, in radians + * @param counterclockwise {Boolean} Optional. Specifies whether the drawing should be counterclockwise or clockwise. False is default, and indicates clockwise, while true indicates counter-clockwise. + * @description The arc() method creates an arc/curve (used to create circles, or parts of circles). + */ + arc: function arc(x, y, radius, startAngle, endAngle, counterclockwise) { + x = this._wrapX(x); + y = this._wrapY(y); + counterclockwise = counterclockwise || false; + + if (!this._matrix_is_identity(this.ctx._transform)) { + var xpt = this._matrix_map_point(this.ctx._transform, [x, y]); + + x = xpt[0]; + y = xpt[1]; + + var x_radPt0 = this._matrix_map_point(this.ctx._transform, [0, 0]); + + var x_radPt = this._matrix_map_point(this.ctx._transform, [0, radius]); + + radius = Math.sqrt(Math.pow(x_radPt[0] - x_radPt0[0], 2) + Math.pow(x_radPt[1] - x_radPt0[1], 2)); + } + + var obj = { + type: "arc", + x: x, + y: y, + radius: radius, + startAngle: startAngle, + endAngle: endAngle, + counterclockwise: counterclockwise + }; + this.path.push(obj); + }, + + /** + * Creates an arc/curve between two tangents + * + * @name arcTo + * @function + * @param x1 {Number} The x-coordinate of the first tangent + * @param y1 {Number} The y-coordinate of the first tangent + * @param x2 {Number} The x-coordinate of the second tangent + * @param y2 {Number} The y-coordinate of the second tangent + * @param radius The radius of the + * @description The arcTo() method creates an arc/curve between two tangents on the canvas. + */ + arcTo: function arcTo(x1, y1, x2, y2, radius) {//TODO needs to be implemented + }, + //Rectangles + + /** + * Creates a rectangle + * + * @name rect + * @function + * @param x {Number} The x-coordinate of the upper-left corner of the rectangle + * @param y {Number} The y-coordinate of the upper-left corner of the rectangle + * @param w {Number} The width of the rectangle, in pixels + * @param h {Number} The height of the rectangle, in pixels + * @description The rect() method creates a rectangle. + */ + rect: function rect(x, y, w, h) { + this.moveTo(x, y); + this.lineTo(x + w, y); + this.lineTo(x + w, y + h); + this.lineTo(x, y + h); + this.lineTo(x, y); + this.lineTo(x + w, y); + this.lineTo(x, y); + }, + + /** + * Draws a "filled" rectangle + * + * @name fillRect + * @function + * @param x {Number} The x-coordinate of the upper-left corner of the rectangle + * @param y {Number} The y-coordinate of the upper-left corner of the rectangle + * @param w {Number} The width of the rectangle, in pixels + * @param h {Number} The height of the rectangle, in pixels + * @description The fillRect() method draws a "filled" rectangle. The default color of the fill is black. + */ + fillRect: function fillRect(x, y, w, h) { + if (this._isFillTransparent()) { + return; + } + + x = this._wrapX(x); + y = this._wrapY(y); + + var xpt1 = this._matrix_map_point(this.ctx._transform, [x, y]); + + var xpt2 = this._matrix_map_point(this.ctx._transform, [x + w, y]); + + var xpt3 = this._matrix_map_point(this.ctx._transform, [x + w, y + h]); + + var xpt4 = this._matrix_map_point(this.ctx._transform, [x, y + h]); + + this.pdf.internal.out("q"); + this.pdf.setLineCap("butt"); + this.pdf.setLineJoin("miter"); + var lines = []; + lines.push([xpt2[0] - xpt1[0], xpt2[1] - xpt1[1]]); + lines.push([xpt3[0] - xpt2[0], xpt3[1] - xpt2[1]]); + lines.push([xpt4[0] - xpt3[0], xpt4[1] - xpt3[1]]); + lines.push([xpt1[0] - xpt4[0], xpt1[1] - xpt4[1]]); + lines.push([xpt2[0] - xpt1[0], xpt2[1] - xpt1[1]]); + lines.push([xpt1[0] - xpt2[0], xpt1[1] - xpt2[1]]); + this.pdf.lines(lines, xpt1[0], xpt1[1], null, "F"); + this.pdf.internal.out("Q"); + }, + + /** + * Draws a rectangle (no fill) + * + * @name strokeRect + * @function + * @param x {Number} The x-coordinate of the upper-left corner of the rectangle + * @param y {Number} The y-coordinate of the upper-left corner of the rectangle + * @param w {Number} The width of the rectangle, in pixels + * @param h {Number} The height of the rectangle, in pixels + * @description The strokeRect() method draws a rectangle (no fill). The default color of the stroke is black. + */ + strokeRect: function strokeRect(x, y, w, h) { + if (this._isStrokeTransparent()) { + return; + } + + x = this._wrapX(x); + y = this._wrapY(y); + + var xpt1 = this._matrix_map_point(this.ctx._transform, [x, y]); + + var xpt2 = this._matrix_map_point(this.ctx._transform, [x + w, y]); + + var xpt3 = this._matrix_map_point(this.ctx._transform, [x + w, y + h]); + + var xpt4 = this._matrix_map_point(this.ctx._transform, [x, y + h]); + + var lines = []; + lines.push([xpt2[0] - xpt1[0], xpt2[1] - xpt1[1]]); + lines.push([xpt3[0] - xpt2[0], xpt3[1] - xpt2[1]]); + lines.push([xpt4[0] - xpt3[0], xpt4[1] - xpt3[1]]); + lines.push([xpt1[0] - xpt4[0], xpt1[1] - xpt4[1]]); + lines.push([xpt2[0] - xpt1[0], xpt2[1] - xpt1[1]]); + lines.push([xpt1[0] - xpt2[0], xpt1[1] - xpt2[1]]); + this.pdf.lines(lines, xpt1[0], xpt1[1], null, "S"); + }, + + /** + * Clears the specified pixels within a given rectangle + * + * @name clearRect + * @function + * @param x {Number} The x-coordinate of the upper-left corner of the rectangle + * @param y {Number} The y-coordinate of the upper-left corner of the rectangle + * @param w {Number} The width of the rectangle to clear, in pixels + * @param h {Number} The height of the rectangle to clear, in pixels + * @description We cannot clear PDF commands that were already written to PDF, so we use white instead.
    + * As a special case, read a special flag (ignoreClearRect) and do nothing if it is set. + * This results in all calls to clearRect() to do nothing, and keep the canvas transparent. + * This flag is stored in the save/restore context and is managed the same way as other drawing states. + * + */ + clearRect: function clearRect(x, y, w, h) { + if (this.ctx.ignoreClearRect) { + return; + } + + this.save(); + + this._setFillStyle("#ffffff"); + + this.fillRect(x, y, w, h); + this.restore(); + }, + //Other + + /** + * Saves the state of the current context + * + * @name save + * @function + */ + save: function save() { + this.pdf.internal.out("q"); + this.ctx._fontSize = this.pdf.internal.getFontSize(); + var ctx = new context(); + ctx.copy(this.ctx); + this.ctxStack.push(this.ctx); + this.ctx = ctx; + }, + + /** + * Returns previously saved path state and attributes + * + * @name restore + * @function + */ + restore: function restore() { + this.pdf.internal.out("Q"); + + if (this.ctxStack.length !== 0) { + this.ctx = this.ctxStack.pop(); + + this._setFillStyle(this.ctx.fillStyle); + + this._setStrokeStyle(this.ctx.strokeStyle); + + this._setFont(this.ctx.font); + + this.pdf.setFontSize(this.ctx._fontSize); + + this._setLineCap(this.ctx.lineCap); + + this._setLineWidth(this.ctx.lineWidth); + + this._setLineJoin(this.ctx.lineJoin); + } + }, + // some stubs + + /** + * @name createEvent + * @function + */ + createEvent: function createEvent() { + console.log("createEvent not implemented (yet)"); + }, + + /** + * @name toDataURL + * @function + */ + toDataURL: function toDataURL() { + console.log("toDataUrl not implemented (yet)"); + }, + //helper functions + _beginPath: function _beginPath() { + this.path.push({ + type: "begin" + }); + }, + _closePath: function _closePath() { + var pathBegin = { + x: 0, + y: 0 + }; + var i = 0; + var len = this.path.length; + + for (i = this.path.length - 1; i !== -1; i--) { + if (this.path[i].type === "begin") { + if (_typeof(this.path[i + 1]) === "object" && typeof this.path[i + 1].x === "number") { + pathBegin = { + x: this.path[i + 1].x, + y: this.path[i + 1].y + }; + var obj = { + type: "lt", + x: pathBegin.x, + y: pathBegin.y + }; + this.path.push(obj); + break; + } + } + } //TODO Repeat second move to get lineJoins correct, maybe only when lineJoin active in _drawPaths + + + if (_typeof(this.path[i + 2]) === "object" && typeof this.path[i + 2].x === "number") { + this.path.push(JSON.parse(JSON.stringify(this.path[i + 2]))); + } + }, + _resetPath: function _resetPath() { + this.path = []; + }, + + /** + * Get the decimal values of r, g, b and a + * + * @name _getRGBA + * @function + * @private + * @ignore + */ + _getRGBA: function _getRGBA(style) { + var r, g, b, a; + + if (style.isCanvasGradient === true) { + style = style.getColor(); + } + + var rgbColor = new RGBColor(style); + + if (!style) { + return { + r: 0, + g: 0, + b: 0, + a: 0, + style: style + }; + } + + if (this.internal.rxTransparent.test(style)) { + r = 0; + g = 0; + b = 0; + a = 0; + } else { + var m = this.internal.rxRgb.exec(style); + + if (m != null) { + r = parseInt(m[1]); + g = parseInt(m[2]); + b = parseInt(m[3]); + a = 1; + } else { + m = this.internal.rxRgba.exec(style); + + if (m != null) { + r = parseInt(m[1]); + g = parseInt(m[2]); + b = parseInt(m[3]); + a = parseFloat(m[4]); + } else { + a = 1; + + if (style.charAt(0) != "#") { + if (rgbColor.ok) { + style = rgbColor.toHex(); + } else { + style = "#000000"; + } + } + + if (style.length === 4) { + r = style.substring(1, 2); + r += r; + g = style.substring(2, 3); + g += g; + b = style.substring(3, 4); + b += b; + } else { + r = style.substring(1, 3); + g = style.substring(3, 5); + b = style.substring(5, 7); + } + + r = parseInt(r, 16); + g = parseInt(g, 16); + b = parseInt(b, 16); + } + } + } + + return { + r: r, + g: g, + b: b, + a: a, + style: style + }; + }, + + /** + * @name _isFilllTransparent + * @function + * @private + * @ignore + * @returns {Boolean} + */ + _isFillTransparent: function _isFillTransparent() { + return this.ctx._isFillTransparent || this.globalAlpha == 0; + }, + + /** + * @name _isStrokeTransparent + * @function + * @private + * @ignore + * @returns {Boolean} + */ + _isStrokeTransparent: function _isStrokeTransparent() { + return this.ctx._isStrokeTransparent || this.globalAlpha == 0; + }, + + /** + * Sets the color, gradient, or pattern used to fill the drawing + * + * @name _setFillStyle + * @function + * @private + * @ignore + */ + _setFillStyle: function _setFillStyle(style) { + var rgba; + rgba = this._getRGBA(style); + this.ctx.fillStyle = style; + this.ctx._isFillTransparent = rgba.a === 0; + this.ctx._fillOpacity = rgba.a; + this.pdf.setFillColor(rgba.r, rgba.g, rgba.b, { + a: rgba.a + }); + this.pdf.setTextColor(rgba.r, rgba.g, rgba.b, { + a: rgba.a + }); + }, + + /** + * Sets the color, gradient, or pattern used for strokes + * + * @name _setStrokeStyle + * @function + * @private + * @ignore + */ + _setStrokeStyle: function _setStrokeStyle(style) { + var rgba = this._getRGBA(style); + + this.ctx.strokeStyle = rgba.style; + this.ctx._isStrokeTransparent = rgba.a === 0; + this.ctx._strokeOpacity = rgba.a; //TODO jsPDF to handle rgba + + if (rgba.a === 0) { + this.pdf.setDrawColor(255, 255, 255); + } else if (rgba.a === 1) { + this.pdf.setDrawColor(rgba.r, rgba.g, rgba.b); + } else { + //this.pdf.setDrawColor(rgba.r, rgba.g, rgba.b, {a: rgba.a}); + this.pdf.setDrawColor(rgba.r, rgba.g, rgba.b); + } + }, + + /** + * Sets font properties for text content + * + * @name _setFont + * @function + * @param {String} The font property uses the same syntax as the CSS font property. + * @private + * @ignore + */ + _setFont: function _setFont(font) { + this.ctx.font = font; + var rx, m; //source: https://stackoverflow.com/a/10136041 + + rx = /^\s*(?=(?:(?:[-a-z]+\s*){0,2}(italic|oblique))?)(?=(?:(?:[-a-z]+\s*){0,2}(small-caps))?)(?=(?:(?:[-a-z]+\s*){0,2}(bold(?:er)?|lighter|[1-9]00))?)(?:(?:normal|\1|\2|\3)\s*){0,3}((?:xx?-)?(?:small|large)|medium|smaller|larger|[.\d]+(?:\%|in|[cem]m|ex|p[ctx]))(?:\s*\/\s*(normal|[.\d]+(?:\%|in|[cem]m|ex|p[ctx])))?\s*([-,\"\'\sa-z]+?)\s*$/i; + m = rx.exec(font); + + if (m != null) { + var fontStyle = m[1]; + var fontVariant = m[2]; + var fontWeight = m[3]; + var fontSize = m[4]; + var fontSizeUnit = m[5]; + var fontFamily = m[6]; + } else { + return; + } + + if ("px" === fontSizeUnit) { + fontSize = Math.floor(parseFloat(fontSize)); // fontSize = fontSize * 1.25; + } else if ("em" === fontSizeUnit) { + fontSize = Math.floor(parseFloat(fontSize) * this.pdf.getFontSize()); + } else { + fontSize = Math.floor(parseFloat(fontSize)); + } + + this.pdf.setFontSize(fontSize); + var style = ""; + + if (fontWeight === "bold" || parseInt(fontWeight, 10) >= 700 || fontStyle === "bold") { + style = "bold"; + } + + if (fontStyle === "italic") { + style += "italic"; + } + + if (style.length === 0) { + style = "normal"; + } + + var jsPdfFontName = ""; + var parts = fontFamily.toLowerCase().replace(/"|'/g, "").split(/\s*,\s*/); + var fallbackFonts = { + arial: "Helvetica", + verdana: "Helvetica", + helvetica: "Helvetica", + "sans-serif": "Helvetica", + fixed: "Courier", + monospace: "Courier", + terminal: "Courier", + courier: "Courier", + times: "Times", + cursive: "Times", + fantasy: "Times", + serif: "Times" + }; + + for (var i = 0; i < parts.length; i++) { + if (this.pdf.internal.getFont(parts[i], style, { + noFallback: true, + disableWarning: true + }) !== undefined) { + jsPdfFontName = parts[i]; + break; + } else if (style === "bolditalic" && this.pdf.internal.getFont(parts[i], "bold", { + noFallback: true, + disableWarning: true + }) !== undefined) { + jsPdfFontName = parts[i]; + style = "bold"; + } else if (this.pdf.internal.getFont(parts[i], "normal", { + noFallback: true, + disableWarning: true + }) !== undefined) { + jsPdfFontName = parts[i]; + style = "normal"; + break; + } + } + + if (jsPdfFontName === "") { + for (var i = 0; i < parts.length; i++) { + if (fallbackFonts[parts[i]]) { + jsPdfFontName = fallbackFonts[parts[i]]; + break; + } + } + } + + jsPdfFontName = jsPdfFontName === "" ? "Times" : jsPdfFontName; + this.pdf.setFont(jsPdfFontName, style); + }, + + /** + * @name _setTextBaseline + * @function + * @private + * @ignore + */ + _setTextBaseline: function _setTextBaseline(baseline) { + this.ctx.textBaseline = baseline; + }, + + /** + * @name _getTextBaseline + * @function + * @private + * @ignore + * @returns {Number} + */ + _getTextBaseline: function _getTextBaseline() { + return this.ctx.textBaseline; + }, + + /** + * @name _setTextAlign + * @function + * @private + * @ignore + */ + _setTextAlign: function _setTextAlign(canvasAlign) { + switch (canvasAlign) { + case "right": + case "end": + this.ctx.textAlign = "right"; + break; + + case "center": + this.ctx.textAlign = "center"; + break; + + case "left": + case "start": + default: + this.ctx.textAlign = "left"; + break; + } + }, + + /** + * @name _getTextAlign + * @function + * @private + * @ignore + * @returns {String} + */ + _getTextAlign: function _getTextAlign() { + return this.ctx.textAlign; + }, + + /** + * Draws "filled" text on the canvas + * + * @name fillText + * @function + * @param text {String} Specifies the text that will be written on the canvas + * @param x {Number} The x coordinate where to start painting the text (relative to the canvas) + * @param y {Number} The y coordinate where to start painting the text (relative to the canvas) + * @param maxWidth {Number} Optional. The maximum allowed width of the text, in pixels + * @description The fillText() method draws filled text on the canvas. The default color of the text is black. + */ + fillText: function fillText(text, x, y, maxWidth) { + if (this._isFillTransparent()) { + return; + } + + x = this._wrapX(x); + y = this._wrapY(y); + + var xpt = this._matrix_map_point(this.ctx._transform, [x, y]); + + x = xpt[0]; + y = xpt[1]; + + var rads = this._matrix_rotation(this.ctx._transform); + + var degs = rads * 57.2958; // We only use X axis as scale hint + + var scale = 1; + + try { + scale = this._matrix_decompose(this._getTransform()).scale[0]; + } catch (e) { + console.warn(e); + } // In some cases the transform was very small (5.715760606202283e-17). Most likely a canvg rounding error. + + + if (scale < 0.01) { + this.pdf.text(text, x, this._getBaseline(y), { + angle: degs, + align: this.textAlign + }); + } else { + var oldSize = this.pdf.internal.getFontSize(); + this.pdf.setFontSize(oldSize * scale); + this.pdf.text(text, x, this._getBaseline(y), { + angle: degs, + align: this.textAlign + }); + this.pdf.setFontSize(oldSize); + } + }, + + /** + * Draws text on the canvas (no fill) + * + * @name strokeText + * @function + * @param text {String} Specifies the text that will be written on the canvas + * @param x {Number} The x coordinate where to start painting the text (relative to the canvas) + * @param y {Number} The y coordinate where to start painting the text (relative to the canvas) + * @param maxWidth {Number} Optional. The maximum allowed width of the text, in pixels + * @description The strokeText() method draws text (with no fill) on the canvas. The default color of the text is black. + */ + strokeText: function strokeText(text, x, y, maxWidth) { + if (this._isStrokeTransparent()) { + return; + } + + x = this._wrapX(x); + y = this._wrapY(y); + + var xpt = this._matrix_map_point(this.ctx._transform, [x, y]); + + x = xpt[0]; + y = xpt[1]; + + var rads = this._matrix_rotation(this.ctx._transform); + + var degs = rads * 57.2958; + var scale = 1; // We only use the X axis as scale hint + + try { + scale = this._matrix_decompose(this._getTransform()).scale[0]; + } catch (e) { + console.warn(e); + } + + if (scale < 0.01) { + this.pdf.text(text, x, this._getBaseline(y), { + angle: degs, + align: this.textAlign, + renderingMode: "stroke" + }); + } else { + var oldSize = this.pdf.internal.getFontSize(); + this.pdf.setFontSize(oldSize * scale); + this.pdf.text(text, x, this._getBaseline(y), { + angle: degs, + align: this.textAlign, + renderingMode: "stroke" + }); + this.pdf.setFontSize(oldSize); + } + }, + + /** + * Returns an object that contains the width of the specified text + * + * @name measureText + * @function + * @param text {String} The text to be measured + * @description The measureText() method returns an object that contains the width of the specified text, in pixels. + * @returns {Number} + */ + measureText: function measureText(text) { + var pdf = this.pdf; + return { + getWidth: function getWidth() { + var fontSize = pdf.internal.getFontSize(); + var txtWidth = pdf.getStringUnitWidth(text) * fontSize / pdf.internal.scaleFactor; // Convert points to pixels + //TODO Use scaleFactor? + + txtWidth *= 1.3333; + return txtWidth; + }, + + get width() { + return this.getWidth(text); + } + + }; + }, + //Line Styles + + /** + * + * @name _setLineWidth + * @function + * @private + * @ignore + */ + _setLineWidth: function _setLineWidth(width) { + this.ctx.lineWidth = width; + this.pdf.setLineWidth(width); + }, + + /** + * @name _setLineCap + * @function + * @private + * @ignore + */ + _setLineCap: function _setLineCap(style) { + this.ctx.lineCap = style; + this.pdf.setLineCap(style); + }, + + /** + * + * @name _setLineJoin + * @function + * @private + * @ignore + */ + _setLineJoin: function _setLineJoin(style) { + this.ctx.lineJoin = style; + this.pdf.setLineJoin(style); + }, + + /** + * + * @name _getLineJoin + * @function + * @private + * @ignore + */ + _getLineJoin: function _getLineJoin() { + return this.ctx.lineJoin; + }, + + /** + * + * @name _wrapX + * @function + * @private + * @ignore + */ + _wrapX: function _wrapX(x) { + if (this.pageWrapXEnabled) { + return x % this.pageWrapX; + } else { + return x; + } + }, + + /** + * @name _wrapY + * @function + * @private + * @ignore + */ + _wrapY: function _wrapY(y) { + if (this.pageWrapYEnabled) { + this._gotoPage(this._page(y)); + + return (y - this.lastBreak) % this.pageWrapY; + } else { + return y; + } + }, + //Transformations + + /** + * Scales the current drawing bigger or smaller + * + * @name scale + * @function + * @param scalewidth {Number} Scales the width of the current drawing (1=100%, 0.5=50%, 2=200%, etc.) + * @param scaleheight {Number} Scales the height of the current drawing (1=100%, 0.5=50%, 2=200%, etc.) + * @description The scale() method scales the current drawing, bigger or smaller. + */ + scale: function scale(scalewidth, scaleheight) { + var matrix = [scalewidth, 0.0, 0.0, scaleheight, 0.0, 0.0]; + this.ctx._transform = this._matrix_multiply(this.ctx._transform, matrix); + }, + + /** + * Rotates the current drawing + * + * @name rotate + * @function + * @param angle {Number} The rotation angle, in radians. + * @description To calculate from degrees to radians: degrees*Math.PI/180.
    + * Example: to rotate 5 degrees, specify the following: 5*Math.PI/180 + */ + rotate: function rotate(angle) { + var matrix = [Math.cos(angle), Math.sin(angle), -Math.sin(angle), Math.cos(angle), 0.0, 0.0]; + this.ctx._transform = this._matrix_multiply(this.ctx._transform, matrix); + }, + + /** + * Remaps the (0,0) position on the canvas + * + * @name translate + * @function + * @param x {Number} The value to add to horizontal (x) coordinates + * @param y {Number} The value to add to vertical (y) coordinates + * @description The translate() method remaps the (0,0) position on the canvas. + */ + translate: function translate(x, y) { + var matrix = [1.0, 0.0, 0.0, 1.0, x, y]; + this.ctx._transform = this._matrix_multiply(this.ctx._transform, matrix); + }, + + /** + * Replaces the current transformation matrix for the drawing + * + * @name transform + * @function + * @param a {Number} Horizontal scaling + * @param b {Number} Horizontal skewing + * @param c {Number} Vertical skewing + * @param d {Number} Vertical scaling + * @param e {Number} Horizontal moving + * @param f {Number} Vertical moving + * @description Each object on the canvas has a current transformation matrix.

    The transform() method replaces the current transformation matrix. It multiplies the current transformation matrix with the matrix described by:



    a c e

    b d f

    0 0 1

    In other words, the transform() method lets you scale, rotate, move, and skew the current context. + */ + transform: function transform(a, b, c, d, e, f) { + this.ctx._transform = this._matrix_multiply(this.ctx._transform, [a, b, c, d, e, f]); + }, + + /** + * Resets the current transform to the identity matrix. Then runs transform() + * + * @name setTransform + * @function + * @param a {Number} Horizontal scaling + * @param b {Number} Horizontal skewing + * @param c {Number} Vertical skewing + * @param d {Number} Vertical scaling + * @param e {Number} Horizontal moving + * @param f {Number} Vertical moving + * @description Each object on the canvas has a current transformation matrix.

    The setTransform() method resets the current transform to the identity matrix, and then runs transform() with the same arguments.

    In other words, the setTransform() method lets you scale, rotate, move, and skew the current context. + */ + setTransform: function setTransform(a, b, c, d, e, f) { + this.ctx._transform = [a, b, c, d, e, f]; + }, + + /** + * @name _getTransform + * @function + * @private + * @ignore + */ + _getTransform: function _getTransform() { + return this.ctx._transform; + }, + lastBreak: 0, + // Y Position of page breaks. + pageBreaks: [], + + /** + * Should only be used if pageWrapYEnabled is true + * + * @name _page + * @function + * @private + * @ignore + * @returns One-based Page Number + */ + _page: function _page(y) { + if (this.pageWrapYEnabled) { + this.lastBreak = 0; + var manualBreaks = 0; + var autoBreaks = 0; + + for (var i = 0; i < this.pageBreaks.length; i++) { + if (y >= this.pageBreaks[i]) { + manualBreaks++; + + if (this.lastBreak === 0) { + autoBreaks++; + } + + var spaceBetweenLastBreak = this.pageBreaks[i] - this.lastBreak; + this.lastBreak = this.pageBreaks[i]; + var pagesSinceLastBreak = Math.floor(spaceBetweenLastBreak / this.pageWrapY); + autoBreaks += pagesSinceLastBreak; + } + } + + if (this.lastBreak === 0) { + var pagesSinceLastBreak = Math.floor(y / this.pageWrapY) + 1; + autoBreaks += pagesSinceLastBreak; + } + + return autoBreaks + manualBreaks; + } else { + return this.pdf.internal.getCurrentPageInfo().pageNumber; + } + }, + _gotoPage: function _gotoPage(pageOneBased) {// This is a stub to be overriden if needed + }, + + /** + * Draws an image, canvas, or video onto the canvas + * + * @function + * @param img {} Specifies the image, canvas, or video element to use + * @param sx {Number} Optional. The x coordinate where to start clipping + * @param sy {Number} Optional. The y coordinate where to start clipping + * @param swidth {Number} Optional. The width of the clipped image + * @param sheight {Number} Optional. The height of the clipped image + * @param x {Number} The x coordinate where to place the image on the canvas + * @param y {Number} The y coordinate where to place the image on the canvas + * @param width {Number} Optional. The width of the image to use (stretch or reduce the image) + * @param height {Number} Optional. The height of the image to use (stretch or reduce the image) + * + */ + drawImage: function drawImage(img, x, y, w, h, x2, y2, w2, h2) { + if (x2 !== undefined) { + x = x2; + y = y2; + w = w2; + h = h2; + } + + x = this._wrapX(x); + y = this._wrapY(y); + + var xRect = this._matrix_map_rect(this.ctx._transform, { + x: x, + y: y, + w: w, + h: h + }); + + var xRect2 = this._matrix_map_rect(this.ctx._transform, { + x: x2, + y: y2, + w: w2, + h: h2 + }); // TODO implement source clipping and image scaling + + + var format; + var rx = /data:image\/(\w+).*/i; + var m = rx.exec(img); + + if (m != null) { + format = m[1]; + } else { + // format = "jpeg"; + format = "png"; + } + + this.pdf.addImage(img, format, xRect.x, xRect.y, xRect.w, xRect.h); + }, + + /** + * Multiply the first matrix by the second + * + * @name matrix_multiply + * @function + * @param m1 + * @param m2 + * @returns {Array} + * @private + * @ignore + */ + _matrix_multiply: function _matrix_multiply(m2, m1) { + var sx = m1[0]; + var shy = m1[1]; + var shx = m1[2]; + var sy = m1[3]; + var tx = m1[4]; + var ty = m1[5]; + var t0 = sx * m2[0] + shy * m2[2]; + var t2 = shx * m2[0] + sy * m2[2]; + var t4 = tx * m2[0] + ty * m2[2] + m2[4]; + shy = sx * m2[1] + shy * m2[3]; + sy = shx * m2[1] + sy * m2[3]; + ty = tx * m2[1] + ty * m2[3] + m2[5]; + sx = t0; + shx = t2; + tx = t4; + return [sx, shy, shx, sy, tx, ty]; + }, + + /** + * @name _matrix_rotation + * @function + * @private + * @ignore + */ + _matrix_rotation: function _matrix_rotation(m) { + return Math.atan2(m[2], m[0]); + }, + + /** + * @name _matrix_decompose + * @function + * @private + * @ignore + */ + _matrix_decompose: function _matrix_decompose(matrix) { + var a = matrix[0]; + var b = matrix[1]; + var c = matrix[2]; + var d = matrix[3]; + var scaleX = Math.sqrt(a * a + b * b); + a /= scaleX; + b /= scaleX; + var shear = a * c + b * d; + c -= a * shear; + d -= b * shear; + var scaleY = Math.sqrt(c * c + d * d); + c /= scaleY; + d /= scaleY; + shear /= scaleY; + + if (a * d < b * c) { + a = -a; + b = -b; + shear = -shear; + scaleX = -scaleX; + } + + return { + scale: [scaleX, 0, 0, scaleY, 0, 0], + translate: [1, 0, 0, 1, matrix[4], matrix[5]], + rotate: [a, b, -b, a, 0, 0], + skew: [1, 0, shear, 1, 0, 0] + }; + }, + + /** + * @name _matrix_map_point + * @function + * @private + * @ignore + */ + _matrix_map_point: function _matrix_map_point(m1, pt) { + var sx = m1[0]; + var shy = m1[1]; + var shx = m1[2]; + var sy = m1[3]; + var tx = m1[4]; + var ty = m1[5]; + var px = pt[0]; + var py = pt[1]; + var x = px * sx + py * shx + tx; + var y = px * shy + py * sy + ty; + return [x, y]; + }, + + /** + * @name _matrix_map_point_obj + * @function + * @private + * @ignore + */ + _matrix_map_point_obj: function _matrix_map_point_obj(m1, pt) { + var xpt = this._matrix_map_point(m1, [pt.x, pt.y]); + + return { + x: xpt[0], + y: xpt[1] + }; + }, + + /** + * @name _matrix_map_rect + * @function + * @private + * @ignore + */ + _matrix_map_rect: function _matrix_map_rect(m1, rect) { + var p1 = this._matrix_map_point(m1, [rect.x, rect.y]); + + var p2 = this._matrix_map_point(m1, [rect.x + rect.w, rect.y + rect.h]); + + return { + x: p1[0], + y: p1[1], + w: p2[0] - p1[0], + h: p2[1] - p1[1] + }; + }, + + /** + * @name _matrix_is_identity + * @function + * @private + * @ignore + */ + _matrix_is_identity: function _matrix_is_identity(m1) { + if (m1[0] != 1) { + return false; + } + + if (m1[1] != 0) { + return false; + } + + if (m1[2] != 0) { + return false; + } + + if (m1[3] != 1) { + return false; + } + + if (m1[4] != 0) { + return false; + } + + if (m1[5] != 0) { + return false; + } + + return true; + }, + + /** + * Processes the paths + * + * @function + * @param rule {String} + * @param isClip {Boolean} + * @private + * @ignore + */ + _drawPaths: function _drawPaths(rule, isClip) { + var isStroke = rule === "stroke"; + var isFill = !isStroke; + + if (isStroke && !isClip && this._isStrokeTransparent()) { + return; + } + + if (isFill && !isClip && this._isFillTransparent()) { + return; + } + + var v2Support = typeof this.pdf.internal.newObject2 === "function"; + var lines; + + if (globalObj.outIntercept) { + lines = globalObj.outIntercept.type === "group" ? globalObj.outIntercept.stream : globalObj.outIntercept; + } else { + lines = this.internal.getCurrentPage(); + } + + var moves = []; + var outInterceptOld = globalObj.outIntercept; + /* + if (v2Support) { + // Blend and Mask + switch (this.ctx.globalCompositeOperation) { + case 'normal': + case 'source-over': + break; + case 'destination-in': + case 'destination-out': + //TODO this need to be added to the current group or page + // define a mask stream + var obj = this.pdf.internal.newStreamObject(); // define a mask state + var obj2 = this.pdf.internal.newObject2(); + obj2.push('<>'); // /S /Luminosity will need to define color space + obj2.push('>>'); // add mask to page resources + var gsName = 'MASK' + obj2.objId; + this.pdf.internal.addGraphicsState(gsName, obj2.objId); + var instruction = '/' + gsName + ' gs'; // add mask to page, group, or stream + lines.splice(0, 0, 'q'); + lines.splice(1, 0, instruction); + lines.push('Q'); + globalObj.outIntercept = obj; + break; + default: + var dictionaryEntry = '/' + this.pdf.internal.blendModeMap[this.ctx.globalCompositeOperation.toUpperCase()]; + if (dictionaryEntry) { + this.pdf.internal.out(dictionaryEntry + ' gs'); + } + break; + } + } + */ + + var alpha = this.ctx.globalAlpha; + + if (this.ctx._fillOpacity < 1) { + // TODO combine this with global opacity + alpha = this.ctx._fillOpacity; + } //TODO check for an opacity graphics state that was already created + //TODO do not set opacity if current value is already active + + /* + if (v2Support) { + var objOpac = this.pdf.internal.newObject2(); + objOpac.push('<>'); + var gsName = 'GS_O_' + objOpac.objId; + this.pdf.internal.addGraphicsState(gsName, objOpac.objId); + this.pdf.internal.out('/' + gsName + ' gs'); + } + */ + + + var xPath = this.path; + + for (var i = 0; i < xPath.length; i++) { + var pt = xPath[i]; + + switch (pt.type) { + case "begin": + moves.push({ + begin: true + }); + break; + + case "close": + moves.push({ + close: true + }); + break; + + case "mt": + moves.push({ + start: pt, + deltas: [], + abs: [] + }); + break; + + case "lt": + var delta = [pt.x - xPath[i - 1].x, pt.y - xPath[i - 1].y]; + var iii = moves.length; + + if (iii > 0) { + for (iii; iii > 0; iii--) { + if (moves[iii - 1].close !== true && moves[iii - 1].begin !== true) { + moves[iii - 1].deltas.push(delta); + moves[iii - 1].abs.push(pt); + break; + } + } + } + + break; + + case "bct": + var delta = [pt.x1 - xPath[i - 1].x, pt.y1 - xPath[i - 1].y, pt.x2 - xPath[i - 1].x, pt.y2 - xPath[i - 1].y, pt.x - xPath[i - 1].x, pt.y - xPath[i - 1].y]; + moves[moves.length - 1].deltas.push(delta); + break; + + case "qct": + // convert to bezier + var x1 = xPath[i - 1].x + 2.0 / 3.0 * (pt.x1 - xPath[i - 1].x); + var y1 = xPath[i - 1].y + 2.0 / 3.0 * (pt.y1 - xPath[i - 1].y); + var x2 = pt.x + 2.0 / 3.0 * (pt.x1 - pt.x); + var y2 = pt.y + 2.0 / 3.0 * (pt.y1 - pt.y); + var x3 = pt.x; + var y3 = pt.y; + var delta = [x1 - xPath[i - 1].x, y1 - xPath[i - 1].y, x2 - xPath[i - 1].x, y2 - xPath[i - 1].y, x3 - xPath[i - 1].x, y3 - xPath[i - 1].y]; + moves[moves.length - 1].deltas.push(delta); + break; + + case "arc": + moves.push({ + deltas: [], + abs: [] + }); + moves[moves.length - 1].arc = true; + + if (Array.isArray(moves[moves.length - 1].abs)) { + moves[moves.length - 1].abs.push(pt); + } + + break; + } + } + + var style; + + if (!isClip) { + if (isStroke) { + style = "S"; + } else { + style = "f"; + } + } else { + style = null; + } + + for (var i = 0; i < moves.length; i++) { + if (moves[i].begin) ; + + if (moves[i].arc) { + if (moves[i].start) { + this.internal.move2(this, moves[i].start.x, moves[i].start.y); + } + + var arcs = moves[i].abs; + + for (var ii = 0; ii < arcs.length; ii++) { + var arc = arcs[ii]; //TODO lines deltas were getting in here + + if (typeof arc.startAngle !== "undefined") { + var start = arc.startAngle * 360 / (2 * Math.PI); + var end = arc.endAngle * 360 / (2 * Math.PI); + var x = arc.x; + var y = arc.y; + this.internal.arc2(this, x, y, arc.radius, start, end, arc.counterclockwise, style, isClip); + } else { + this.internal.line2(c2d, arc.x, arc.y); + } + } + } + + if (!moves[i].arc) { + if (moves[i].close !== true && moves[i].begin !== true) { + var x = moves[i].start.x; + var y = moves[i].start.y; + this.pdf.lines(moves[i].deltas, x, y, null, null); + } + } + + if (moves[i].close) ; + } + + if (style) { + this.pdf.internal.out(style); + } + + if (isClip) { + this.pdf.clip(); + } + + globalObj.outIntercept = outInterceptOld; // if (this.ctx._clip_path.length > 0) { + // lines.push('Q'); + // } + }, + + /* + _pushMask: function () { + var v2Support = typeof this.pdf.internal.newObject2 === 'function'; + if (!v2Support) { + console.log('jsPDF v2 not enabled') + return; + } + // define a mask stream + var obj = this.pdf.internal.newStreamObject(); + // define a mask state + var obj2 = this.pdf.internal.newObject2(); + obj2.push('<>'); // /S /Luminosity will need to define color space + obj2.push('>>'); + // add mask to page resources + var gsName = 'MASK' + obj2.objId; + this.pdf.internal.addGraphicsState(gsName, obj2.objId); + var instruction = '/' + gsName + ' gs'; + this.pdf.internal.out(instruction); + }, + */ + _getBaseline: function _getBaseline(y) { + var height = parseInt(this.pdf.internal.getFontSize() / this.pdf.internal.scaleFactor); // TODO Get descent from font descriptor + + var descent = height * 0.25; + + switch (this.ctx.textBaseline) { + case "bottom": + return y - descent; + + case "top": + return y + height; + + case "hanging": + return y + height - descent; + + case "middle": + return y + height / 2 - descent; + + case "ideographic": + // TODO not implemented + return y; + + case "alphabetic": + default: + return y; + } + }, + createLinearGradient: function createLinearGradient() { + var canvasGradient = function canvasGradient() {}; + + canvasGradient.colorStops = []; + + canvasGradient.addColorStop = function (offset, color) { + this.colorStops.push([offset, color]); + }; + + canvasGradient.getColor = function () { + if (this.colorStops.length === 0) { + return "#000000"; + } + + return this.colorStops[0][1]; + }; + + canvasGradient.isCanvasGradient = true; + return canvasGradient; + }, + createPattern: function createPattern() { + return this.createLinearGradient(); + }, + createRadialGradient: function createRadialGradient() { + return this.createLinearGradient(); + } + }; + var c2d = jsPDFAPI.context2d; + /** + * Sets or returns the color, gradient, or pattern used to fill the drawing + * + * @name fillStyle + * @default #000000 + * @property {(color|gradient|pattern)} value The color of the drawing. Default value is #000000
    + * A gradient object (linear or radial) used to fill the drawing (not supported by context2d)
    + * A pattern object to use to fill the drawing (not supported by context2d) + */ + + Object.defineProperty(c2d, "fillStyle", { + set: function set(value) { + this._setFillStyle(value); + }, + get: function get() { + return this.ctx.fillStyle; + } + }); + /** + * Sets or returns the color, gradient, or pattern used for strokes + * + * @name strokeStyle + * @default #000000 + * @property {color} color A CSS color value that indicates the stroke color of the drawing. Default value is #000000 (not supported by context2d) + * @property {gradient} gradient A gradient object (linear or radial) used to create a gradient stroke (not supported by context2d) + * @property {pattern} pattern A pattern object used to create a pattern stroke (not supported by context2d) + */ + + Object.defineProperty(c2d, "strokeStyle", { + set: function set(value) { + this._setStrokeStyle(value); + }, + get: function get() { + return this.ctx.strokeStyle; + } + }); //Line Styles + + /** + * Sets or returns the style of the end caps for a line + * + * @name lineCap + * @default butt + * @property {(butt|round|square)} lineCap butt A flat edge is added to each end of the line
    + * round A rounded end cap is added to each end of the line
    + * square A square end cap is added to each end of the line
    + */ + + Object.defineProperty(c2d, "lineCap", { + set: function set(val) { + this._setLineCap(val); + }, + get: function get() { + return this.ctx.lineCap; + } + }); + /** + * Sets or returns the current line width + * + * @name lineWidth + * @default 1 + * @property {number} lineWidth The current line width, in pixels + */ + + Object.defineProperty(c2d, "lineWidth", { + set: function set(value) { + this._setLineWidth(value); + }, + get: function get() { + return this.ctx.lineWidth; + } + }); + /** + * Sets or returns the type of corner created, when two lines meet + */ + + Object.defineProperty(c2d, "lineJoin", { + set: function set(val) { + this._setLineJoin(val); + }, + get: function get() { + return this.ctx.lineJoin; + } + }); + /** + * Sets or returns the maximum miter length + */ + + Object.defineProperty(c2d, "miterLimit", { + set: function set(val) { + this.ctx.miterLimit = val; + }, + get: function get() { + return this.ctx.miterLimit; + } + }); + Object.defineProperty(c2d, "textBaseline", { + set: function set(value) { + this._setTextBaseline(value); + }, + get: function get() { + return this._getTextBaseline(); + } + }); + Object.defineProperty(c2d, "textAlign", { + set: function set(value) { + this._setTextAlign(value); + }, + get: function get() { + return this._getTextAlign(); + } + }); + Object.defineProperty(c2d, "font", { + set: function set(value) { + this._setFont(value); + }, + get: function get() { + return this.ctx.font; + } + }); + Object.defineProperty(c2d, "globalCompositeOperation", { + set: function set(value) { + this.ctx.globalCompositeOperation = value; + }, + get: function get() { + return this.ctx.globalCompositeOperation; + } + }); + Object.defineProperty(c2d, "globalAlpha", { + set: function set(value) { + this.ctx.globalAlpha = value; + }, + get: function get() { + return this.ctx.globalAlpha; + } + }); + Object.defineProperty(c2d, "canvas", { + get: function get() { + return { + parentNode: false, + style: false + }; + } + }); // Not HTML API + + Object.defineProperty(c2d, "ignoreClearRect", { + set: function set(value) { + this.ctx.ignoreClearRect = value; + }, + get: function get() { + return this.ctx.ignoreClearRect; + } + }); // End Not HTML API + + c2d.internal = {}; + c2d.internal.rxRgb = /rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/; + c2d.internal.rxRgba = /rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d\.]+)\s*\)/; + c2d.internal.rxTransparent = /transparent|rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*0+\s*\)/; // http://hansmuller-flex.blogspot.com/2011/10/more-about-approximating-circular-arcs.html + + c2d.internal.arc = function (c2d, xc, yc, r, a1, a2, counterclockwise, style) { + var k = this.pdf.internal.scaleFactor; + var pageHeight = this.pdf.internal.pageSize.getHeight(); + var f2 = this.pdf.internal.f2; + var a1r = a1 * (Math.PI / 180); + var a2r = a2 * (Math.PI / 180); + var curves = this.createArc(r, a1r, a2r, counterclockwise); + + for (var i = 0; i < curves.length; i++) { + var curve = curves[i]; + + if (i === 0) { + this.pdf.internal.out([f2((curve.x1 + xc) * k), f2((pageHeight - (curve.y1 + yc)) * k), "m", f2((curve.x2 + xc) * k), f2((pageHeight - (curve.y2 + yc)) * k), f2((curve.x3 + xc) * k), f2((pageHeight - (curve.y3 + yc)) * k), f2((curve.x4 + xc) * k), f2((pageHeight - (curve.y4 + yc)) * k), "c"].join(" ")); + } else { + this.pdf.internal.out([f2((curve.x2 + xc) * k), f2((pageHeight - (curve.y2 + yc)) * k), f2((curve.x3 + xc) * k), f2((pageHeight - (curve.y3 + yc)) * k), f2((curve.x4 + xc) * k), f2((pageHeight - (curve.y4 + yc)) * k), "c"].join(" ")); + } //c2d._lastPoint = {x: curve.x1 + xc, y: curve.y1 + yc}; + + + c2d._lastPoint = { + x: xc, + y: yc + }; // f2((curve.x1 + xc) * k), f2((pageHeight - (curve.y1 + yc)) * k), 'm', f2((curve.x2 + xc) * k), f2((pageHeight - (curve.y2 + yc)) * k), f2((curve.x3 + xc) * k), f2((pageHeight - (curve.y3 + yc)) * k), f2((curve.x4 + xc) * k), f2((pageHeight - (curve.y4 + yc)) * k), 'c' + } + + if (style !== null) { + this.pdf.internal.out(this.pdf.internal.getStyle(style)); + } + }; + /** + * + * @param x Edge point X + * @param y Edge point Y + * @param r Radius + * @param a1 start angle + * @param a2 end angle + * @param counterclockwise + * @param style + * @param isClip + */ + + + c2d.internal.arc2 = function (c2d, x, y, r, a1, a2, counterclockwise, style, isClip) { + // we need to convert from cartesian to polar here methinks. + var centerX = x; // + r; + + var centerY = y; + + if (!isClip) { + this.arc(c2d, centerX, centerY, r, a1, a2, counterclockwise, style); + } else { + this.arc(c2d, centerX, centerY, r, a1, a2, counterclockwise, null); + this.pdf.clip(); + } + }; + + c2d.internal.move2 = function (c2d, x, y) { + var k = this.pdf.internal.scaleFactor; + var pageHeight = this.pdf.internal.pageSize.getHeight(); + var f2 = this.pdf.internal.f2; + this.pdf.internal.out([f2(x * k), f2((pageHeight - y) * k), "m"].join(" ")); + c2d._lastPoint = { + x: x, + y: y + }; + }; + + c2d.internal.line2 = function (c2d, dx, dy) { + var k = this.pdf.internal.scaleFactor; + var pageHeight = this.pdf.internal.pageSize.getHeight(); + var f2 = this.pdf.internal.f2; //var pt = {x: c2d._lastPoint.x + dx, y: c2d._lastPoint.y + dy}; + + var pt = { + x: dx, + y: dy + }; + this.pdf.internal.out([f2(pt.x * k), f2((pageHeight - pt.y) * k), "l"].join(" ")); //this.pdf.internal.out('f'); + + c2d._lastPoint = pt; + }; + /** + * Return a array of objects that represent bezier curves which approximate the circular arc centered at the origin, from startAngle to endAngle (radians) with the specified radius. + * + * Each bezier curve is an object with four points, where x1,y1 and x4,y4 are the arc's end points and x2,y2 and x3,y3 are the cubic bezier's control points. + */ + + + c2d.internal.createArc = function (radius, startAngle, endAngle, anticlockwise) { + var EPSILON = 0.00001; // Roughly 1/1000th of a degree, see below + // normalize startAngle, endAngle to [-2PI, 2PI] + + var twoPI = Math.PI * 2; + var startAngleN = startAngle; + + if (startAngleN < twoPI || startAngleN > twoPI) { + startAngleN = startAngleN % twoPI; + } + + var endAngleN = endAngle; + + if (endAngleN < twoPI || endAngleN > twoPI) { + endAngleN = endAngleN % twoPI; + } // Compute the sequence of arc curves, up to PI/2 at a time. + // Total arc angle is less than 2PI. + + + var curves = []; + var piOverTwo = Math.PI / 2.0; //var sgn = (startAngle < endAngle) ? +1 : -1; // clockwise or counterclockwise + + var sgn = anticlockwise ? -1 : +1; + var a1 = startAngle; + + for (var totalAngle = Math.min(twoPI, Math.abs(endAngleN - startAngleN)); totalAngle > EPSILON;) { + var a2 = a1 + sgn * Math.min(totalAngle, piOverTwo); + curves.push(this.createSmallArc(radius, a1, a2)); + totalAngle -= Math.abs(a2 - a1); + a1 = a2; + } + + return curves; + }; + + c2d.internal.getCurrentPage = function () { + return this.pdf.internal.pages[this.pdf.internal.getCurrentPageInfo().pageNumber]; + }; + /** + * Cubic bezier approximation of a circular arc centered at the origin, from (radians) a1 to a2, where a2-a1 < pi/2. The arc's radius is r. + * + * Returns an object with four points, where x1,y1 and x4,y4 are the arc's end points and x2,y2 and x3,y3 are the cubic bezier's control points. + * + * This algorithm is based on the approach described in: A. Riškus, "Approximation of a Cubic Bezier Curve by Circular Arcs and Vice Versa," Information Technology and Control, 35(4), 2006 pp. 371-378. + */ + + + c2d.internal.createSmallArc = function (r, a1, a2) { + // Compute all four points for an arc that subtends the same total angle + // but is centered on the X-axis + var a = (a2 - a1) / 2.0; + var x4 = r * Math.cos(a); + var y4 = r * Math.sin(a); + var x1 = x4; + var y1 = -y4; + var q1 = x1 * x1 + y1 * y1; + var q2 = q1 + x1 * x4 + y1 * y4; + var k2 = 4 / 3 * (Math.sqrt(2 * q1 * q2) - q2) / (x1 * y4 - y1 * x4); + var x2 = x1 - k2 * y1; + var y2 = y1 + k2 * x1; + var x3 = x2; + var y3 = -y2; // Find the arc points' actual locations by computing x1,y1 and x4,y4 + // and rotating the control points by a + a1 + + var ar = a + a1; + var cos_ar = Math.cos(ar); + var sin_ar = Math.sin(ar); + return { + x1: r * Math.cos(a1), + y1: r * Math.sin(a1), + x2: x2 * cos_ar - y2 * sin_ar, + y2: x2 * sin_ar + y2 * cos_ar, + x3: x3 * cos_ar - y3 * sin_ar, + y3: x3 * sin_ar + y3 * cos_ar, + x4: r * Math.cos(a2), + y4: r * Math.sin(a2) + }; + }; + /** + * + * @function + * @constructor + */ + + + function context() { + this._isStrokeTransparent = false; + this._strokeOpacity = 1; + this.strokeStyle = "#000000"; + this.fillStyle = "#000000"; + this._isFillTransparent = false; + this._fillOpacity = 1; + this.font = "12pt times"; + this.textBaseline = "alphabetic"; // top,bottom,middle,ideographic,alphabetic,hanging + + this.textAlign = "left"; + this.lineWidth = 1; + this.lineJoin = "miter"; // round, bevel, miter + + this.lineCap = "butt"; // butt, round, square + + this._transform = [1, 0, 0, 1, 0, 0]; // sx, shy, shx, sy, tx, ty + + this.globalCompositeOperation = "normal"; + this.globalAlpha = 1.0; + this._clip_path = []; + this.currentPoint = { + x: 0, + y: 0 + }; // TODO miter limit //default 10 + // Not HTML API + + this.ignoreClearRect = false; + + this.copy = function (ctx) { + this._isStrokeTransparent = ctx._isStrokeTransparent; + this._strokeOpacity = ctx._strokeOpacity; + this.strokeStyle = ctx.strokeStyle; + this._isFillTransparent = ctx._isFillTransparent; + this._fillOpacity = ctx._fillOpacity; + this.fillStyle = ctx.fillStyle; + this.font = ctx.font; + this.lineWidth = ctx.lineWidth; + this.lineJoin = ctx.lineJoin; + this.lineCap = ctx.lineCap; + this.textBaseline = ctx.textBaseline; + this.textAlign = ctx.textAlign; + this._fontSize = ctx._fontSize; + this._transform = ctx._transform.slice(0); + this.globalCompositeOperation = ctx.globalCompositeOperation; + this.globalAlpha = ctx.globalAlpha; + this._clip_path = ctx._clip_path.slice(0); //TODO deep copy? + + this.currentPoint = ctx.currentPoint; // Not HTML API + + this.ignoreClearRect = ctx.ignoreClearRect; + }; + } + + return this; + })(jsPDF.API, typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function("return this")()); + + /** + * Copyright (c) 2018 Erik Koopmans + * Released under the MIT License. + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * jsPDF html PlugIn + * + * @name html + * @module + */ + (function (jsPDFAPI, global) { + /** + * Determine the type of a variable/object. + * + * @private + * @ignore + */ + + var objType = function objType(obj) { + var type = _typeof(obj); + + if (type === "undefined") return "undefined";else if (type === "string" || obj instanceof String) return "string";else if (type === "number" || obj instanceof Number) return "number";else if (type === "function" || obj instanceof Function) return "function";else if (!!obj && obj.constructor === Array) return "array";else if (obj && obj.nodeType === 1) return "element";else if (type === "object") return "object";else return "unknown"; + }; + /** + * Create an HTML element with optional className, innerHTML, and style. + * + * @private + * @ignore + */ + + + var createElement = function createElement(tagName, opt) { + var el = document.createElement(tagName); + if (opt.className) el.className = opt.className; + + if (opt.innerHTML) { + el.innerHTML = opt.innerHTML; + var scripts = el.getElementsByTagName("script"); + + for (var i = scripts.length; i-- > 0; null) { + scripts[i].parentNode.removeChild(scripts[i]); + } + } + + for (var key in opt.style) { + el.style[key] = opt.style[key]; + } + + return el; + }; + /** + * Deep-clone a node and preserve contents/properties. + * + * @private + * @ignore + */ + + + var cloneNode = function cloneNode(node, javascriptEnabled) { + // Recursively clone the node. + var clone = node.nodeType === 3 ? document.createTextNode(node.nodeValue) : node.cloneNode(false); + + for (var child = node.firstChild; child; child = child.nextSibling) { + if (javascriptEnabled === true || child.nodeType !== 1 || child.nodeName !== "SCRIPT") { + clone.appendChild(cloneNode(child, javascriptEnabled)); + } + } + + if (node.nodeType === 1) { + // Preserve contents/properties of special nodes. + if (node.nodeName === "CANVAS") { + clone.width = node.width; + clone.height = node.height; + clone.getContext("2d").drawImage(node, 0, 0); + } else if (node.nodeName === "TEXTAREA" || node.nodeName === "SELECT") { + clone.value = node.value; + } // Preserve the node's scroll position when it loads. + + + clone.addEventListener("load", function () { + clone.scrollTop = node.scrollTop; + clone.scrollLeft = node.scrollLeft; + }, true); + } // Return the cloned node. + + + return clone; + }; + /* ----- CONSTRUCTOR ----- */ + + + var Worker = function Worker(opt) { + // Create the root parent for the proto chain, and the starting Worker. + var root = Object.assign(Worker.convert(Promise.resolve()), JSON.parse(JSON.stringify(Worker.template))); + var self = Worker.convert(Promise.resolve(), root); // Set progress, optional settings, and return. + + self = self.setProgress(1, Worker, 1, [Worker]); + self = self.set(opt); + return self; + }; // Boilerplate for subclassing Promise. + + + Worker.prototype = Object.create(Promise.prototype); + Worker.prototype.constructor = Worker; // Converts/casts promises into Workers. + + Worker.convert = function convert(promise, inherit) { + // Uses prototypal inheritance to receive changes made to ancestors' properties. + promise.__proto__ = inherit || Worker.prototype; + return promise; + }; + + Worker.template = { + prop: { + src: null, + container: null, + overlay: null, + canvas: null, + img: null, + pdf: null, + pageSize: null, + callback: function callback() {} + }, + progress: { + val: 0, + state: null, + n: 0, + stack: [] + }, + opt: { + filename: "file.pdf", + margin: [0, 0, 0, 0], + enableLinks: true, + html2canvas: {}, + jsPDF: {} + } + }; + /* ----- FROM / TO ----- */ + + Worker.prototype.from = function from(src, type) { + function getType(src) { + switch (objType(src)) { + case "string": + return "string"; + + case "element": + return src.nodeName.toLowerCase === "canvas" ? "canvas" : "element"; + + default: + return "unknown"; + } + } + + return this.then(function from_main() { + type = type || getType(src); + + switch (type) { + case "string": + return this.set({ + src: createElement("div", { + innerHTML: src + }) + }); + + case "element": + return this.set({ + src: src + }); + + case "canvas": + return this.set({ + canvas: src + }); + + case "img": + return this.set({ + img: src + }); + + default: + return this.error("Unknown source type."); + } + }); + }; + + Worker.prototype.to = function to(target) { + // Route the 'to' request to the appropriate method. + switch (target) { + case "container": + return this.toContainer(); + + case "canvas": + return this.toCanvas(); + + case "img": + return this.toImg(); + + case "pdf": + return this.toPdf(); + + default: + return this.error("Invalid target."); + } + }; + + Worker.prototype.toContainer = function toContainer() { + // Set up function prerequisites. + var prereqs = [function checkSrc() { + return this.prop.src || this.error("Cannot duplicate - no source HTML."); + }, function checkPageSize() { + return this.prop.pageSize || this.setPageSize(); + }]; + return this.thenList(prereqs).then(function toContainer_main() { + // Define the CSS styles for the container and its overlay parent. + var overlayCSS = { + position: "fixed", + overflow: "hidden", + zIndex: 1000, + left: "-100000px", + right: 0, + bottom: 0, + top: 0 + }; + var containerCSS = { + position: "relative", + display: "inline-block", + width: Math.max(this.prop.src.clientWidth, this.prop.src.scrollWidth, this.prop.src.offsetWidth) + "px", + left: 0, + right: 0, + top: 0, + margin: "auto", + backgroundColor: "white" + }; // Set the overlay to hidden (could be changed in the future to provide a print preview). + + var source = cloneNode(this.prop.src, this.opt.html2canvas.javascriptEnabled); + + if (source.tagName === "BODY") { + containerCSS.height = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight) + "px"; + } + + this.prop.overlay = createElement("div", { + className: "html2pdf__overlay", + style: overlayCSS + }); + this.prop.container = createElement("div", { + className: "html2pdf__container", + style: containerCSS + }); + this.prop.container.appendChild(source); + this.prop.container.firstChild.appendChild(createElement("div", { + style: { + clear: "both", + border: "0 none transparent", + margin: 0, + padding: 0, + height: 0 + } + })); + this.prop.container.style.float = "none"; + this.prop.overlay.appendChild(this.prop.container); + document.body.appendChild(this.prop.overlay); + this.prop.container.firstChild.style.position = "relative"; + this.prop.container.height = Math.max(this.prop.container.firstChild.clientHeight, this.prop.container.firstChild.scrollHeight, this.prop.container.firstChild.offsetHeight) + "px"; + }); + }; + + Worker.prototype.toCanvas = function toCanvas() { + // Set up function prerequisites. + var prereqs = [function checkContainer() { + return document.body.contains(this.prop.container) || this.toContainer(); + }]; // Fulfill prereqs then create the canvas. + + return this.thenList(prereqs).then(function toCanvas_main() { + // Handle old-fashioned 'onrendered' argument. + var options = Object.assign({}, this.opt.html2canvas); + delete options.onrendered; + + if (!this.isHtml2CanvasLoaded()) { + return; + } + + return html2canvas(this.prop.container, options); + }).then(function toCanvas_post(canvas) { + // Handle old-fashioned 'onrendered' argument. + var onRendered = this.opt.html2canvas.onrendered || function () {}; + + onRendered(canvas); + this.prop.canvas = canvas; + document.body.removeChild(this.prop.overlay); + }); + }; + + Worker.prototype.toContext2d = function toContext2d() { + // Set up function prerequisites. + var prereqs = [function checkContainer() { + return document.body.contains(this.prop.container) || this.toContainer(); + }]; // Fulfill prereqs then create the canvas. + + return this.thenList(prereqs).then(function toContext2d_main() { + // Handle old-fashioned 'onrendered' argument. + var pdf = this.opt.jsPDF; + var options = Object.assign({ + async: true, + allowTaint: true, + backgroundColor: "#ffffff", + imageTimeout: 15000, + logging: true, + proxy: null, + removeContainer: true, + foreignObjectRendering: false, + useCORS: false + }, this.opt.html2canvas); + delete options.onrendered; + options.windowHeight = options.windowHeight || 0; + options.windowHeight = options.windowHeight == 0 ? Math.max(this.prop.container.clientHeight, this.prop.container.scrollHeight, this.prop.container.offsetHeight) : options.windowHeight; + + if (!this.isHtml2CanvasLoaded()) { + return; + } + + return html2canvas(this.prop.container, options); + }).then(function toContext2d_post(canvas) { + // Handle old-fashioned 'onrendered' argument. + var onRendered = this.opt.html2canvas.onrendered || function () {}; + + onRendered(canvas); + this.prop.canvas = canvas; + document.body.removeChild(this.prop.overlay); + }); + }; + + Worker.prototype.toImg = function toImg() { + // Set up function prerequisites. + var prereqs = [function checkCanvas() { + return this.prop.canvas || this.toCanvas(); + }]; // Fulfill prereqs then create the image. + + return this.thenList(prereqs).then(function toImg_main() { + var imgData = this.prop.canvas.toDataURL("image/" + this.opt.image.type, this.opt.image.quality); + this.prop.img = document.createElement("img"); + this.prop.img.src = imgData; + }); + }; + + Worker.prototype.toPdf = function toPdf() { + // Set up function prerequisites. + var prereqs = [function checkContext2d() { + return this.toContext2d(); + } //function checkCanvas() { return this.prop.canvas || this.toCanvas(); } + ]; // Fulfill prereqs then create the image. + + return this.thenList(prereqs).then(function toPdf_main() { + // Create local copies of frequently used properties. + this.prop.pdf = this.prop.pdf || this.opt.jsPDF; + }); + }; + /* ----- OUTPUT / SAVE ----- */ + + + Worker.prototype.output = function output(type, options, src) { + // Redirect requests to the correct function (outputPdf / outputImg). + src = src || "pdf"; + + if (src.toLowerCase() === "img" || src.toLowerCase() === "image") { + return this.outputImg(type, options); + } else { + return this.outputPdf(type, options); + } + }; + + Worker.prototype.outputPdf = function outputPdf(type, options) { + // Set up function prerequisites. + var prereqs = [function checkPdf() { + return this.prop.pdf || this.toPdf(); + }]; // Fulfill prereqs then perform the appropriate output. + + return this.thenList(prereqs).then(function outputPdf_main() { + /* Currently implemented output types: + * https://rawgit.com/MrRio/jsPDF/master/docs/jspdf.js.html#line992 + * save(options), arraybuffer, blob, bloburi/bloburl, + * datauristring/dataurlstring, dataurlnewwindow, datauri/dataurl + */ + return this.prop.pdf.output(type, options); + }); + }; + + Worker.prototype.outputImg = function outputImg(type, options) { + // Set up function prerequisites. + var prereqs = [function checkImg() { + return this.prop.img || this.toImg(); + }]; // Fulfill prereqs then perform the appropriate output. + + return this.thenList(prereqs).then(function outputImg_main() { + switch (type) { + case undefined: + case "img": + return this.prop.img; + + case "datauristring": + case "dataurlstring": + return this.prop.img.src; + + case "datauri": + case "dataurl": + return document.location.href = this.prop.img.src; + + default: + throw 'Image output type "' + type + '" is not supported.'; + } + }); + }; + + Worker.prototype.isHtml2CanvasLoaded = function () { + var result = typeof global.html2canvas !== "undefined"; + + if (!result) { + console.error("html2canvas not loaded."); + } + + return result; + }; + + Worker.prototype.save = function save(filename) { + // Set up function prerequisites. + var prereqs = [function checkPdf() { + return this.prop.pdf || this.toPdf(); + }]; + + if (!this.isHtml2CanvasLoaded()) { + return; + } // Fulfill prereqs, update the filename (if provided), and save the PDF. + + + return this.thenList(prereqs).set(filename ? { + filename: filename + } : null).then(function save_main() { + this.prop.pdf.save(this.opt.filename); + }); + }; + + Worker.prototype.doCallback = function doCallback(filename) { + // Set up function prerequisites. + var prereqs = [function checkPdf() { + return this.prop.pdf || this.toPdf(); + }]; + + if (!this.isHtml2CanvasLoaded()) { + return; + } // Fulfill prereqs, update the filename (if provided), and save the PDF. + + + return this.thenList(prereqs).then(function doCallback_main() { + this.prop.callback(this.prop.pdf); + }); + }; + /* ----- SET / GET ----- */ + + + Worker.prototype.set = function set(opt) { + // TODO: Implement ordered pairs? + // Silently ignore invalid or empty input. + if (objType(opt) !== "object") { + return this; + } // Build an array of setter functions to queue. + + + var fns = Object.keys(opt || {}).map(function (key) { + if (key in Worker.template.prop) { + // Set pre-defined properties. + return function set_prop() { + this.prop[key] = opt[key]; + }; + } else { + switch (key) { + case "margin": + return this.setMargin.bind(this, opt.margin); + + case "jsPDF": + return function set_jsPDF() { + this.opt.jsPDF = opt.jsPDF; + return this.setPageSize(); + }; + + case "pageSize": + return this.setPageSize.bind(this, opt.pageSize); + + default: + // Set any other properties in opt. + return function set_opt() { + this.opt[key] = opt[key]; + }; + } + } + }, this); // Set properties within the promise chain. + + return this.then(function set_main() { + return this.thenList(fns); + }); + }; + + Worker.prototype.get = function get(key, cbk) { + return this.then(function get_main() { + // Fetch the requested property, either as a predefined prop or in opt. + var val = key in Worker.template.prop ? this.prop[key] : this.opt[key]; + return cbk ? cbk(val) : val; + }); + }; + + Worker.prototype.setMargin = function setMargin(margin) { + return this.then(function setMargin_main() { + // Parse the margin property. + switch (objType(margin)) { + case "number": + margin = [margin, margin, margin, margin]; + + case "array": + if (margin.length === 2) { + margin = [margin[0], margin[1], margin[0], margin[1]]; + } + + if (margin.length === 4) { + break; + } + + default: + return this.error("Invalid margin array."); + } // Set the margin property, then update pageSize. + + + this.opt.margin = margin; + }).then(this.setPageSize); + }; + + Worker.prototype.setPageSize = function setPageSize(pageSize) { + function toPx(val, k) { + return Math.floor(val * k / 72 * 96); + } + + return this.then(function setPageSize_main() { + // Retrieve page-size based on jsPDF settings, if not explicitly provided. + pageSize = pageSize || jsPDF.getPageSize(this.opt.jsPDF); // Add 'inner' field if not present. + + if (!pageSize.hasOwnProperty("inner")) { + pageSize.inner = { + width: pageSize.width - this.opt.margin[1] - this.opt.margin[3], + height: pageSize.height - this.opt.margin[0] - this.opt.margin[2] + }; + pageSize.inner.px = { + width: toPx(pageSize.inner.width, pageSize.k), + height: toPx(pageSize.inner.height, pageSize.k) + }; + pageSize.inner.ratio = pageSize.inner.height / pageSize.inner.width; + } // Attach pageSize to this. + + + this.prop.pageSize = pageSize; + }); + }; + + Worker.prototype.setProgress = function setProgress(val, state, n, stack) { + // Immediately update all progress values. + if (val != null) this.progress.val = val; + if (state != null) this.progress.state = state; + if (n != null) this.progress.n = n; + if (stack != null) this.progress.stack = stack; + this.progress.ratio = this.progress.val / this.progress.state; // Return this for command chaining. + + return this; + }; + + Worker.prototype.updateProgress = function updateProgress(val, state, n, stack) { + // Immediately update all progress values, using setProgress. + return this.setProgress(val ? this.progress.val + val : null, state ? state : null, n ? this.progress.n + n : null, stack ? this.progress.stack.concat(stack) : null); + }; + /* ----- PROMISE MAPPING ----- */ + + + Worker.prototype.then = function then(onFulfilled, onRejected) { + // Wrap `this` for encapsulation. + var self = this; + return this.thenCore(onFulfilled, onRejected, function then_main(onFulfilled, onRejected) { + // Update progress while queuing, calling, and resolving `then`. + self.updateProgress(null, null, 1, [onFulfilled]); + return Promise.prototype.then.call(this, function then_pre(val) { + self.updateProgress(null, onFulfilled); + return val; + }).then(onFulfilled, onRejected).then(function then_post(val) { + self.updateProgress(1); + return val; + }); + }); + }; + + Worker.prototype.thenCore = function thenCore(onFulfilled, onRejected, thenBase) { + // Handle optional thenBase parameter. + thenBase = thenBase || Promise.prototype.then; // Wrap `this` for encapsulation and bind it to the promise handlers. + + var self = this; + + if (onFulfilled) { + onFulfilled = onFulfilled.bind(self); + } + + if (onRejected) { + onRejected = onRejected.bind(self); + } // Cast self into a Promise to avoid polyfills recursively defining `then`. + + + var isNative = Promise.toString().indexOf("[native code]") !== -1 && Promise.name === "Promise"; + var selfPromise = isNative ? self : Worker.convert(Object.assign({}, self), Promise.prototype); // Return the promise, after casting it into a Worker and preserving props. + + var returnVal = thenBase.call(selfPromise, onFulfilled, onRejected); + return Worker.convert(returnVal, self.__proto__); + }; + + Worker.prototype.thenExternal = function thenExternal(onFulfilled, onRejected) { + // Call `then` and return a standard promise (exits the Worker chain). + return Promise.prototype.then.call(this, onFulfilled, onRejected); + }; + + Worker.prototype.thenList = function thenList(fns) { + // Queue a series of promise 'factories' into the promise chain. + var self = this; + fns.forEach(function thenList_forEach(fn) { + self = self.thenCore(fn); + }); + return self; + }; + + Worker.prototype["catch"] = function (onRejected) { + // Bind `this` to the promise handler, call `catch`, and return a Worker. + if (onRejected) { + onRejected = onRejected.bind(this); + } + + var returnVal = Promise.prototype["catch"].call(this, onRejected); + return Worker.convert(returnVal, this); + }; + + Worker.prototype.catchExternal = function catchExternal(onRejected) { + // Call `catch` and return a standard promise (exits the Worker chain). + return Promise.prototype["catch"].call(this, onRejected); + }; + + Worker.prototype.error = function error(msg) { + // Throw the error in the Promise chain. + return this.then(function error_main() { + throw new Error(msg); + }); + }; + /* ----- ALIASES ----- */ + + + Worker.prototype.using = Worker.prototype.set; + Worker.prototype.saveAs = Worker.prototype.save; + Worker.prototype.export = Worker.prototype.output; + Worker.prototype.run = Worker.prototype.then; // Get dimensions of a PDF page, as determined by jsPDF. + + jsPDF.getPageSize = function (orientation, unit, format) { + // Decode options object + if (_typeof(orientation) === "object") { + var options = orientation; + orientation = options.orientation; + unit = options.unit || unit; + format = options.format || format; + } // Default options + + + unit = unit || "mm"; + format = format || "a4"; + orientation = ("" + (orientation || "P")).toLowerCase(); + var format_as_string = ("" + format).toLowerCase(); // Size in pt of various paper formats + + var pageFormats = { + a0: [2383.94, 3370.39], + a1: [1683.78, 2383.94], + a2: [1190.55, 1683.78], + a3: [841.89, 1190.55], + a4: [595.28, 841.89], + a5: [419.53, 595.28], + a6: [297.64, 419.53], + a7: [209.76, 297.64], + a8: [147.4, 209.76], + a9: [104.88, 147.4], + a10: [73.7, 104.88], + b0: [2834.65, 4008.19], + b1: [2004.09, 2834.65], + b2: [1417.32, 2004.09], + b3: [1000.63, 1417.32], + b4: [708.66, 1000.63], + b5: [498.9, 708.66], + b6: [354.33, 498.9], + b7: [249.45, 354.33], + b8: [175.75, 249.45], + b9: [124.72, 175.75], + b10: [87.87, 124.72], + c0: [2599.37, 3676.54], + c1: [1836.85, 2599.37], + c2: [1298.27, 1836.85], + c3: [918.43, 1298.27], + c4: [649.13, 918.43], + c5: [459.21, 649.13], + c6: [323.15, 459.21], + c7: [229.61, 323.15], + c8: [161.57, 229.61], + c9: [113.39, 161.57], + c10: [79.37, 113.39], + dl: [311.81, 623.62], + letter: [612, 792], + "government-letter": [576, 756], + legal: [612, 1008], + "junior-legal": [576, 360], + ledger: [1224, 792], + tabloid: [792, 1224], + "credit-card": [153, 243] + }; // Unit conversion + + switch (unit) { + case "pt": + var k = 1; + break; + + case "mm": + var k = 72 / 25.4; + break; + + case "cm": + var k = 72 / 2.54; + break; + + case "in": + var k = 72; + break; + + case "px": + var k = 72 / 96; + break; + + case "pc": + var k = 12; + break; + + case "em": + var k = 12; + break; + + case "ex": + var k = 6; + break; + + default: + throw "Invalid unit: " + unit; + } // Dimensions are stored as user units and converted to points on output + + + if (pageFormats.hasOwnProperty(format_as_string)) { + var pageHeight = pageFormats[format_as_string][1] / k; + var pageWidth = pageFormats[format_as_string][0] / k; + } else { + try { + var pageHeight = format[1]; + var pageWidth = format[0]; + } catch (err) { + throw new Error("Invalid format: " + format); + } + } // Handle page orientation + + + if (orientation === "p" || orientation === "portrait") { + orientation = "p"; + + if (pageWidth > pageHeight) { + var tmp = pageWidth; + pageWidth = pageHeight; + pageHeight = tmp; + } + } else if (orientation === "l" || orientation === "landscape") { + orientation = "l"; + + if (pageHeight > pageWidth) { + var tmp = pageWidth; + pageWidth = pageHeight; + pageHeight = tmp; + } + } else { + throw "Invalid orientation: " + orientation; + } // Return information (k is the unit conversion ratio from pts) + + + var info = { + width: pageWidth, + height: pageHeight, + unit: unit, + k: k + }; + return info; + }; + /** + * Generate a PDF from an HTML element or string using. + * + * @name html + * @function + * @param {Element|string} source The source element or HTML string. + * @param {Object=} options An object of optional settings. + * @description The Plugin needs html2canvas from niklasvh + */ + + + jsPDFAPI.html = function (src, options) { + + options = options || {}; + + options.callback = options.callback || function () {}; + + options.html2canvas = options.html2canvas || {}; + options.html2canvas.canvas = options.html2canvas.canvas || this.canvas; + options.jsPDF = options.jsPDF || this; // Create a new worker with the given options. + + var pdf = options.jsPDF; + pdf.annotations = { + _nameMap: [], + createAnnotation: function createAnnotation(href, bounds) { + var x = pdf.context2d._wrapX(bounds.left); + + var y = pdf.context2d._wrapY(bounds.top); + + var page = pdf.context2d._page(bounds.top); + + var options; + var index = href.indexOf("#"); + + if (index >= 0) { + options = { + name: href.substring(index + 1) + }; + } else { + options = { + url: href + }; + } + + pdf.link(x, y, bounds.right - bounds.left, bounds.bottom - bounds.top, options); + }, + setName: function setName(name, bounds) { + var x = pdf.context2d._wrapX(bounds.left); + + var y = pdf.context2d._wrapY(bounds.top); + + var page = pdf.context2d._page(bounds.top); + + this._nameMap[name] = { + page: page, + x: x, + y: y + }; + } + }; + + pdf.context2d._pageBreakAt = function (y) { + this.pageBreaks.push(y); + }; + + pdf.context2d._gotoPage = function (pageOneBased) { + while (pdf.internal.getNumberOfPages() < pageOneBased) { + pdf.addPage(); + } + + pdf.setPage(pageOneBased); + }; + + pdf.context2d.pageWrapYEnabled = true; + pdf.context2d.pageWrapY = pdf.internal.pageSize.getHeight() / pdf.internal.scaleFactor + 1; + pdf.canvas.autoContext2dResizeY = false; + var worker = new Worker(options); + + if (!options.worker) { + // If worker is not set to true, perform the traditional 'simple' operation. + return worker.from(src).doCallback(); + } else { + // Otherwise, return the worker for new Promise-based operation. + return worker; + } + + return this; + }; + })(jsPDF.API, typeof window !== "undefined" && window || typeof global !== "undefined" && global); + + /** + * @license + * ==================================================================== + * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com + * + * + * ==================================================================== + */ + + /*global jsPDF */ + + /** + * jsPDF JavaScript plugin + * + * @name javascript + * @module + */ + (function (jsPDFAPI) { + + var jsNamesObj, jsJsObj, text; + /** + * @name addJS + * @function + * @param {string} javascript The javascript to be embedded into the PDF-file. + * @returns {jsPDF} + */ + + jsPDFAPI.addJS = function (javascript) { + text = javascript; + this.internal.events.subscribe("postPutResources", function (javascript) { + jsNamesObj = this.internal.newObject(); + this.internal.out("<<"); + this.internal.out("/Names [(EmbeddedJS) " + (jsNamesObj + 1) + " 0 R]"); + this.internal.out(">>"); + this.internal.out("endobj"); + jsJsObj = this.internal.newObject(); + this.internal.out("<<"); + this.internal.out("/S /JavaScript"); + this.internal.out("/JS (" + text + ")"); + this.internal.out(">>"); + this.internal.out("endobj"); + }); + this.internal.events.subscribe("putCatalog", function () { + if (jsNamesObj !== undefined && jsJsObj !== undefined) { + this.internal.out("/Names <>"); + } + }); + return this; + }; + })(jsPDF.API); + + /** + * @license + * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * jsPDF Outline PlugIn + * + * Generates a PDF Outline + * @name outline + * @module + */ + (function (jsPDFAPI) { + + jsPDFAPI.events.push(["postPutResources", function () { + var pdf = this; + var rx = /^(\d+) 0 obj$/; // Write action goto objects for each page + // this.outline.destsGoto = []; + // for (var i = 0; i < totalPages; i++) { + // var id = pdf.internal.newObject(); + // this.outline.destsGoto.push(id); + // pdf.internal.write("<> endobj"); + // } + // + // for (var i = 0; i < dests.length; i++) { + // pdf.internal.write("(page_" + (i + 1) + ")" + dests[i] + " 0 + // R"); + // } + // + + if (this.outline.root.children.length > 0) { + var lines = pdf.outline.render().split(/\r\n/); + + for (var i = 0; i < lines.length; i++) { + var line = lines[i]; + var m = rx.exec(line); + + if (m != null) { + var oid = m[1]; + pdf.internal.newObjectDeferredBegin(oid); + } + + pdf.internal.write(line); + } + } // This code will write named destination for each page reference + // (page_1, etc) + + + if (this.outline.createNamedDestinations) { + var totalPages = this.internal.pages.length; // WARNING: this assumes jsPDF starts on page 3 and pageIDs + // follow 5, 7, 9, etc + // Write destination objects for each page + + var dests = []; + + for (var i = 0; i < totalPages; i++) { + var id = pdf.internal.newObject(); + dests.push(id); + var info = pdf.internal.getPageInfo(i + 1); + pdf.internal.write("<< /D[" + info.objId + " 0 R /XYZ null null null]>> endobj"); + } // assign a name for each destination + + + var names2Oid = pdf.internal.newObject(); + pdf.internal.write("<< /Names [ "); + + for (var i = 0; i < dests.length; i++) { + pdf.internal.write("(page_" + (i + 1) + ")" + dests[i] + " 0 R"); + } + + pdf.internal.write(" ] >>", "endobj"); // var kids = pdf.internal.newObject(); + // pdf.internal.write('<< /Kids [ ' + names2Oid + ' 0 R'); + // pdf.internal.write(' ] >>', 'endobj'); + + var namesOid = pdf.internal.newObject(); + pdf.internal.write("<< /Dests " + names2Oid + " 0 R"); + pdf.internal.write(">>", "endobj"); + } + }]); + jsPDFAPI.events.push(["putCatalog", function () { + var pdf = this; + + if (pdf.outline.root.children.length > 0) { + pdf.internal.write("/Outlines", this.outline.makeRef(this.outline.root)); + + if (this.outline.createNamedDestinations) { + pdf.internal.write("/Names " + namesOid + " 0 R"); + } // Open with Bookmarks showing + // pdf.internal.write("/PageMode /UseOutlines"); + + } + }]); + jsPDFAPI.events.push(["initialized", function () { + var pdf = this; + pdf.outline = { + createNamedDestinations: false, + root: { + children: [] + } + }; + /** + * Options: pageNumber + */ + + pdf.outline.add = function (parent, title, options) { + var item = { + title: title, + options: options, + children: [] + }; + + if (parent == null) { + parent = this.root; + } + + parent.children.push(item); + return item; + }; + + pdf.outline.render = function () { + this.ctx = {}; + this.ctx.val = ""; + this.ctx.pdf = pdf; + this.genIds_r(this.root); + this.renderRoot(this.root); + this.renderItems(this.root); + return this.ctx.val; + }; + + pdf.outline.genIds_r = function (node) { + node.id = pdf.internal.newObjectDeferred(); + + for (var i = 0; i < node.children.length; i++) { + this.genIds_r(node.children[i]); + } + }; + + pdf.outline.renderRoot = function (node) { + this.objStart(node); + this.line("/Type /Outlines"); + + if (node.children.length > 0) { + this.line("/First " + this.makeRef(node.children[0])); + this.line("/Last " + this.makeRef(node.children[node.children.length - 1])); + } + + this.line("/Count " + this.count_r({ + count: 0 + }, node)); + this.objEnd(); + }; + + pdf.outline.renderItems = function (node) { + for (var i = 0; i < node.children.length; i++) { + var item = node.children[i]; + this.objStart(item); + this.line("/Title " + this.makeString(item.title)); + this.line("/Parent " + this.makeRef(node)); + + if (i > 0) { + this.line("/Prev " + this.makeRef(node.children[i - 1])); + } + + if (i < node.children.length - 1) { + this.line("/Next " + this.makeRef(node.children[i + 1])); + } + + if (item.children.length > 0) { + this.line("/First " + this.makeRef(item.children[0])); + this.line("/Last " + this.makeRef(item.children[item.children.length - 1])); + } + + var count = this.count = this.count_r({ + count: 0 + }, item); + + if (count > 0) { + this.line("/Count " + count); + } + + if (item.options) { + if (item.options.pageNumber) { + // Explicit Destination + //WARNING this assumes page ids are 3,5,7, etc. + var info = pdf.internal.getPageInfo(item.options.pageNumber); + this.line("/Dest " + "[" + info.objId + " 0 R /XYZ 0 " + this.ctx.pdf.internal.pageSize.getHeight() * this.ctx.pdf.internal.scaleFactor + " 0]"); // this line does not work on all clients (pageNumber instead of page ref) + //this.line('/Dest ' + '[' + (item.options.pageNumber - 1) + ' /XYZ 0 ' + this.ctx.pdf.internal.pageSize.getHeight() + ' 0]'); + // Named Destination + // this.line('/Dest (page_' + (item.options.pageNumber) + ')'); + // Action Destination + // var id = pdf.internal.newObject(); + // pdf.internal.write('<> endobj'); + // this.line('/A ' + id + ' 0 R' ); + } + } + + this.objEnd(); + } + + for (var i = 0; i < node.children.length; i++) { + var item = node.children[i]; + this.renderItems(item); + } + }; + + pdf.outline.line = function (text) { + this.ctx.val += text + "\r\n"; + }; + + pdf.outline.makeRef = function (node) { + return node.id + " 0 R"; + }; + + pdf.outline.makeString = function (val) { + return "(" + pdf.internal.pdfEscape(val) + ")"; + }; + + pdf.outline.objStart = function (node) { + this.ctx.val += "\r\n" + node.id + " 0 obj" + "\r\n<<\r\n"; + }; + + pdf.outline.objEnd = function (node) { + this.ctx.val += ">> \r\n" + "endobj" + "\r\n"; + }; + + pdf.outline.count_r = function (ctx, node) { + for (var i = 0; i < node.children.length; i++) { + ctx.count++; + this.count_r(ctx, node.children[i]); + } + + return ctx.count; + }; + }]); + return this; + })(jsPDF.API); + + /** + * @license + * + * Copyright (c) 2014 James Robb, https://github.com/jamesbrobb + * + * + * ==================================================================== + */ + + /** + * jsPDF PNG PlugIn + * @name png_support + * @module + */ + (function (jsPDFAPI) { + /* + * @see http://www.w3.org/TR/PNG-Chunks.html + * + Color Allowed Interpretation + Type Bit Depths + 0 1,2,4,8,16 Each pixel is a grayscale sample. + 2 8,16 Each pixel is an R,G,B triple. + 3 1,2,4,8 Each pixel is a palette index; + a PLTE chunk must appear. + 4 8,16 Each pixel is a grayscale sample, + followed by an alpha sample. + 6 8,16 Each pixel is an R,G,B triple, + followed by an alpha sample. + */ + + /* + * PNG filter method types + * + * @see http://www.w3.org/TR/PNG-Filters.html + * @see http://www.libpng.org/pub/png/book/chapter09.html + * + * This is what the value 'Predictor' in decode params relates to + * + * 15 is "optimal prediction", which means the prediction algorithm can change from line to line. + * In that case, you actually have to read the first byte off each line for the prediction algorthim (which should be 0-4, corresponding to PDF 10-14) and select the appropriate unprediction algorithm based on that byte. + * + 0 None + 1 Sub + 2 Up + 3 Average + 4 Paeth + */ + + var doesNotHavePngJS = function doesNotHavePngJS() { + return typeof PNG !== "function" || typeof FlateStream !== "function"; + }, + canCompress = function canCompress(value) { + return value !== jsPDFAPI.image_compression.NONE && hasCompressionJS(); + }, + hasCompressionJS = function hasCompressionJS() { + var inst = typeof Deflater === "function"; + if (!inst) throw new Error("requires deflate.js for compression"); + return inst; + }, + compressBytes = function compressBytes(bytes, lineLength, colorsPerPixel, compression) { + var level = 5, + filter_method = filterUp; + + switch (compression) { + case jsPDFAPI.image_compression.FAST: + level = 3; + filter_method = filterSub; + break; + + case jsPDFAPI.image_compression.MEDIUM: + level = 6; + filter_method = filterAverage; + break; + + case jsPDFAPI.image_compression.SLOW: + level = 9; + filter_method = filterPaeth; //uses to sum to choose best filter for each line + + break; + } + + bytes = applyPngFilterMethod(bytes, lineLength, colorsPerPixel, filter_method); + var header = new Uint8Array(createZlibHeader(level)); + var checksum = adler32(bytes); + var deflate = new Deflater(level); + var a = deflate.append(bytes); + var cBytes = deflate.flush(); + var len = header.length + a.length + cBytes.length; + var cmpd = new Uint8Array(len + 4); + cmpd.set(header); + cmpd.set(a, header.length); + cmpd.set(cBytes, header.length + a.length); + cmpd[len++] = checksum >>> 24 & 0xff; + cmpd[len++] = checksum >>> 16 & 0xff; + cmpd[len++] = checksum >>> 8 & 0xff; + cmpd[len++] = checksum & 0xff; + return jsPDFAPI.arrayBufferToBinaryString(cmpd); + }, + createZlibHeader = function createZlibHeader(bytes, level) { + /* + * @see http://www.ietf.org/rfc/rfc1950.txt for zlib header + */ + var cm = 8; + var cinfo = Math.LOG2E * Math.log(0x8000) - 8; + var cmf = cinfo << 4 | cm; + var hdr = cmf << 8; + var flevel = Math.min(3, (level - 1 & 0xff) >> 1); + hdr |= flevel << 6; + hdr |= 0; //FDICT + + hdr += 31 - hdr % 31; + return [cmf, hdr & 0xff & 0xff]; + }, + adler32 = function adler32(array, param) { + var adler = 1; + var s1 = adler & 0xffff, + s2 = adler >>> 16 & 0xffff; + var len = array.length; + var tlen; + var i = 0; + + while (len > 0) { + tlen = len > param ? param : len; + len -= tlen; + + do { + s1 += array[i++]; + s2 += s1; + } while (--tlen); + + s1 %= 65521; + s2 %= 65521; + } + + return (s2 << 16 | s1) >>> 0; + }, + applyPngFilterMethod = function applyPngFilterMethod(bytes, lineLength, colorsPerPixel, filter_method) { + var lines = bytes.length / lineLength, + result = new Uint8Array(bytes.length + lines), + filter_methods = getFilterMethods(), + i = 0, + line, + prevLine, + offset; + + for (; i < lines; i++) { + offset = i * lineLength; + line = bytes.subarray(offset, offset + lineLength); + + if (filter_method) { + result.set(filter_method(line, colorsPerPixel, prevLine), offset + i); + } else { + var j = 0, + len = filter_methods.length, + results = []; + + for (; j < len; j++) { + results[j] = filter_methods[j](line, colorsPerPixel, prevLine); + } + + var ind = getIndexOfSmallestSum(results.concat()); + result.set(results[ind], offset + i); + } + + prevLine = line; + } + + return result; + }, + filterNone = function filterNone(line, colorsPerPixel, prevLine) { + /*var result = new Uint8Array(line.length + 1); + result[0] = 0; + result.set(line, 1);*/ + var result = Array.apply([], line); + result.unshift(0); + return result; + }, + filterSub = function filterSub(line, colorsPerPixel, prevLine) { + var result = [], + i = 0, + len = line.length, + left; + result[0] = 1; + + for (; i < len; i++) { + left = line[i - colorsPerPixel] || 0; + result[i + 1] = line[i] - left + 0x0100 & 0xff; + } + + return result; + }, + filterUp = function filterUp(line, colorsPerPixel, prevLine) { + var result = [], + i = 0, + len = line.length, + up; + result[0] = 2; + + for (; i < len; i++) { + up = prevLine && prevLine[i] || 0; + result[i + 1] = line[i] - up + 0x0100 & 0xff; + } + + return result; + }, + filterAverage = function filterAverage(line, colorsPerPixel, prevLine) { + var result = [], + i = 0, + len = line.length, + left, + up; + result[0] = 3; + + for (; i < len; i++) { + left = line[i - colorsPerPixel] || 0; + up = prevLine && prevLine[i] || 0; + result[i + 1] = line[i] + 0x0100 - (left + up >>> 1) & 0xff; + } + + return result; + }, + filterPaeth = function filterPaeth(line, colorsPerPixel, prevLine) { + var result = [], + i = 0, + len = line.length, + left, + up, + upLeft, + paeth; + result[0] = 4; + + for (; i < len; i++) { + left = line[i - colorsPerPixel] || 0; + up = prevLine && prevLine[i] || 0; + upLeft = prevLine && prevLine[i - colorsPerPixel] || 0; + paeth = paethPredictor(left, up, upLeft); + result[i + 1] = line[i] - paeth + 0x0100 & 0xff; + } + + return result; + }, + paethPredictor = function paethPredictor(left, up, upLeft) { + var p = left + up - upLeft, + pLeft = Math.abs(p - left), + pUp = Math.abs(p - up), + pUpLeft = Math.abs(p - upLeft); + return pLeft <= pUp && pLeft <= pUpLeft ? left : pUp <= pUpLeft ? up : upLeft; + }, + getFilterMethods = function getFilterMethods() { + return [filterNone, filterSub, filterUp, filterAverage, filterPaeth]; + }, + getIndexOfSmallestSum = function getIndexOfSmallestSum(arrays) { + var i = 0, + len = arrays.length, + sum, + min, + ind; + + while (i < len) { + sum = absSum(arrays[i].slice(1)); + + if (sum < min || !min) { + min = sum; + ind = i; + } + + i++; + } + + return ind; + }, + absSum = function absSum(array) { + var i = 0, + len = array.length, + sum = 0; + + while (i < len) { + sum += Math.abs(array[i++]); + } + + return sum; + }, + getPredictorFromCompression = function getPredictorFromCompression(compression) { + var predictor; + + switch (compression) { + case jsPDFAPI.image_compression.FAST: + predictor = 11; + break; + + case jsPDFAPI.image_compression.MEDIUM: + predictor = 13; + break; + + case jsPDFAPI.image_compression.SLOW: + predictor = 14; + break; + + default: + predictor = 12; + break; + } + + return predictor; + }; + /** + * + * @name processPNG + * @function + * @ignore + */ + + + jsPDFAPI.processPNG = function (imageData, imageIndex, alias, compression, dataAsBinaryString) { + + var colorSpace = this.color_spaces.DEVICE_RGB, + decode = this.decode.FLATE_DECODE, + bpc = 8, + img, + dp, + trns, + colors, + pal, + smask; + /* if(this.isString(imageData)) { + }*/ + + if (this.isArrayBuffer(imageData)) imageData = new Uint8Array(imageData); + + if (this.isArrayBufferView(imageData)) { + if (doesNotHavePngJS()) throw new Error("PNG support requires png.js and zlib.js"); + img = new PNG(imageData); + imageData = img.imgData; + bpc = img.bits; + colorSpace = img.colorSpace; + colors = img.colors; //logImg(img); + + /* + * colorType 6 - Each pixel is an R,G,B triple, followed by an alpha sample. + * + * colorType 4 - Each pixel is a grayscale sample, followed by an alpha sample. + * + * Extract alpha to create two separate images, using the alpha as a sMask + */ + + if ([4, 6].indexOf(img.colorType) !== -1) { + /* + * processes 8 bit RGBA and grayscale + alpha images + */ + if (img.bits === 8) { + var pixels = img.pixelBitlength == 32 ? new Uint32Array(img.decodePixels().buffer) : img.pixelBitlength == 16 ? new Uint16Array(img.decodePixels().buffer) : new Uint8Array(img.decodePixels().buffer), + len = pixels.length, + imgData = new Uint8Array(len * img.colors), + alphaData = new Uint8Array(len), + pDiff = img.pixelBitlength - img.bits, + i = 0, + n = 0, + pixel, + pbl; + + for (; i < len; i++) { + pixel = pixels[i]; + pbl = 0; + + while (pbl < pDiff) { + imgData[n++] = pixel >>> pbl & 0xff; + pbl = pbl + img.bits; + } + + alphaData[i] = pixel >>> pbl & 0xff; + } + } + /* + * processes 16 bit RGBA and grayscale + alpha images + */ + + + if (img.bits === 16) { + var pixels = new Uint32Array(img.decodePixels().buffer), + len = pixels.length, + imgData = new Uint8Array(len * (32 / img.pixelBitlength) * img.colors), + alphaData = new Uint8Array(len * (32 / img.pixelBitlength)), + hasColors = img.colors > 1, + i = 0, + n = 0, + a = 0, + pixel; + + while (i < len) { + pixel = pixels[i++]; + imgData[n++] = pixel >>> 0 & 0xff; + + if (hasColors) { + imgData[n++] = pixel >>> 16 & 0xff; + pixel = pixels[i++]; + imgData[n++] = pixel >>> 0 & 0xff; + } + + alphaData[a++] = pixel >>> 16 & 0xff; + } + + bpc = 8; + } + + if (canCompress(compression)) { + imageData = compressBytes(imgData, img.width * img.colors, img.colors, compression); + smask = compressBytes(alphaData, img.width, 1, compression); + } else { + imageData = imgData; + smask = alphaData; + decode = null; + } + } + /* + * Indexed png. Each pixel is a palette index. + */ + + + if (img.colorType === 3) { + colorSpace = this.color_spaces.INDEXED; + pal = img.palette; + + if (img.transparency.indexed) { + var trans = img.transparency.indexed; + var total = 0, + i = 0, + len = trans.length; + + for (; i < len; ++i) { + total += trans[i]; + } + + total = total / 255; + /* + * a single color is specified as 100% transparent (0), + * so we set trns to use a /Mask with that index + */ + + if (total === len - 1 && trans.indexOf(0) !== -1) { + trns = [trans.indexOf(0)]; + /* + * there's more than one colour within the palette that specifies + * a transparency value less than 255, so we unroll the pixels to create an image sMask + */ + } else if (total !== len) { + var pixels = img.decodePixels(), + alphaData = new Uint8Array(pixels.length), + i = 0, + len = pixels.length; + + for (; i < len; i++) { + alphaData[i] = trans[pixels[i]]; + } + + smask = compressBytes(alphaData, img.width, 1); + } + } + } + + var predictor = getPredictorFromCompression(compression); + if (decode === this.decode.FLATE_DECODE) dp = "/Predictor " + predictor + " /Colors " + colors + " /BitsPerComponent " + bpc + " /Columns " + img.width; //remove 'Predictor' as it applies to the type of png filter applied to its IDAT - we only apply with compression + else dp = "/Colors " + colors + " /BitsPerComponent " + bpc + " /Columns " + img.width; + if (this.isArrayBuffer(imageData) || this.isArrayBufferView(imageData)) imageData = this.arrayBufferToBinaryString(imageData); + if (smask && this.isArrayBuffer(smask) || this.isArrayBufferView(smask)) smask = this.arrayBufferToBinaryString(smask); + return this.createImageInfo(imageData, img.width, img.height, colorSpace, bpc, decode, imageIndex, alias, dp, trns, pal, smask, predictor); + } + + throw new Error("Unsupported PNG image data, try using JPEG instead."); + }; + })(jsPDF.API); + + /** + * @license + * Copyright (c) 2017 Aras Abbasi + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * jsPDF gif Support PlugIn + * + * @name gif_support + * @module + */ + (function (jsPDFAPI) { + + jsPDFAPI.processGIF89A = function (imageData, imageIndex, alias, compression, dataAsBinaryString) { + var reader = new GifReader(imageData); + var width = reader.width, + height = reader.height; + var qu = 100; + var pixels = []; + reader.decodeAndBlitFrameRGBA(0, pixels); + var rawImageData = { + data: pixels, + width: width, + height: height + }; + var encoder = new JPEGEncoder(qu); + var data = encoder.encode(rawImageData, qu); + return jsPDFAPI.processJPEG.call(this, data, imageIndex, alias, compression); + }; + + jsPDFAPI.processGIF87A = jsPDFAPI.processGIF89A; + })(jsPDF.API); + + /** + * Copyright (c) 2018 Aras Abbasi + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * jsPDF bmp Support PlugIn + * @name bmp_support + * @module + */ + (function (jsPDFAPI) { + + jsPDFAPI.processBMP = function (imageData, imageIndex, alias, compression, dataAsBinaryString) { + var reader = new BmpDecoder(imageData, false); + var width = reader.width, + height = reader.height; + var qu = 100; + var pixels = reader.getData(); + var rawImageData = { + data: pixels, + width: width, + height: height + }; + var encoder = new JPEGEncoder(qu); + var data = encoder.encode(rawImageData, qu); + return jsPDFAPI.processJPEG.call(this, data, imageIndex, alias, compression); + }; + })(jsPDF.API); + + /** + * @license + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * jsPDF setLanguage Plugin + * + * @name setLanguage + * @module + */ + (function (jsPDFAPI) { + /** + * Add Language Tag to the generated PDF + * + * @name setLanguage + * @function + * @param {string} langCode The Language code as ISO-639-1 (e.g. 'en') or as country language code (e.g. 'en-GB'). + * @returns {jsPDF} + * @example + * var doc = new jsPDF() + * doc.text(10, 10, 'This is a test') + * doc.setLanguage("en-US") + * doc.save('english.pdf') + */ + + jsPDFAPI.setLanguage = function (langCode) { + + var langCodes = { + af: "Afrikaans", + sq: "Albanian", + ar: "Arabic (Standard)", + "ar-DZ": "Arabic (Algeria)", + "ar-BH": "Arabic (Bahrain)", + "ar-EG": "Arabic (Egypt)", + "ar-IQ": "Arabic (Iraq)", + "ar-JO": "Arabic (Jordan)", + "ar-KW": "Arabic (Kuwait)", + "ar-LB": "Arabic (Lebanon)", + "ar-LY": "Arabic (Libya)", + "ar-MA": "Arabic (Morocco)", + "ar-OM": "Arabic (Oman)", + "ar-QA": "Arabic (Qatar)", + "ar-SA": "Arabic (Saudi Arabia)", + "ar-SY": "Arabic (Syria)", + "ar-TN": "Arabic (Tunisia)", + "ar-AE": "Arabic (U.A.E.)", + "ar-YE": "Arabic (Yemen)", + an: "Aragonese", + hy: "Armenian", + as: "Assamese", + ast: "Asturian", + az: "Azerbaijani", + eu: "Basque", + be: "Belarusian", + bn: "Bengali", + bs: "Bosnian", + br: "Breton", + bg: "Bulgarian", + my: "Burmese", + ca: "Catalan", + ch: "Chamorro", + ce: "Chechen", + zh: "Chinese", + "zh-HK": "Chinese (Hong Kong)", + "zh-CN": "Chinese (PRC)", + "zh-SG": "Chinese (Singapore)", + "zh-TW": "Chinese (Taiwan)", + cv: "Chuvash", + co: "Corsican", + cr: "Cree", + hr: "Croatian", + cs: "Czech", + da: "Danish", + nl: "Dutch (Standard)", + "nl-BE": "Dutch (Belgian)", + en: "English", + "en-AU": "English (Australia)", + "en-BZ": "English (Belize)", + "en-CA": "English (Canada)", + "en-IE": "English (Ireland)", + "en-JM": "English (Jamaica)", + "en-NZ": "English (New Zealand)", + "en-PH": "English (Philippines)", + "en-ZA": "English (South Africa)", + "en-TT": "English (Trinidad & Tobago)", + "en-GB": "English (United Kingdom)", + "en-US": "English (United States)", + "en-ZW": "English (Zimbabwe)", + eo: "Esperanto", + et: "Estonian", + fo: "Faeroese", + fj: "Fijian", + fi: "Finnish", + fr: "French (Standard)", + "fr-BE": "French (Belgium)", + "fr-CA": "French (Canada)", + "fr-FR": "French (France)", + "fr-LU": "French (Luxembourg)", + "fr-MC": "French (Monaco)", + "fr-CH": "French (Switzerland)", + fy: "Frisian", + fur: "Friulian", + gd: "Gaelic (Scots)", + "gd-IE": "Gaelic (Irish)", + gl: "Galacian", + ka: "Georgian", + de: "German (Standard)", + "de-AT": "German (Austria)", + "de-DE": "German (Germany)", + "de-LI": "German (Liechtenstein)", + "de-LU": "German (Luxembourg)", + "de-CH": "German (Switzerland)", + el: "Greek", + gu: "Gujurati", + ht: "Haitian", + he: "Hebrew", + hi: "Hindi", + hu: "Hungarian", + is: "Icelandic", + id: "Indonesian", + iu: "Inuktitut", + ga: "Irish", + it: "Italian (Standard)", + "it-CH": "Italian (Switzerland)", + ja: "Japanese", + kn: "Kannada", + ks: "Kashmiri", + kk: "Kazakh", + km: "Khmer", + ky: "Kirghiz", + tlh: "Klingon", + ko: "Korean", + "ko-KP": "Korean (North Korea)", + "ko-KR": "Korean (South Korea)", + la: "Latin", + lv: "Latvian", + lt: "Lithuanian", + lb: "Luxembourgish", + mk: "FYRO Macedonian", + ms: "Malay", + ml: "Malayalam", + mt: "Maltese", + mi: "Maori", + mr: "Marathi", + mo: "Moldavian", + nv: "Navajo", + ng: "Ndonga", + ne: "Nepali", + no: "Norwegian", + nb: "Norwegian (Bokmal)", + nn: "Norwegian (Nynorsk)", + oc: "Occitan", + or: "Oriya", + om: "Oromo", + fa: "Persian", + "fa-IR": "Persian/Iran", + pl: "Polish", + pt: "Portuguese", + "pt-BR": "Portuguese (Brazil)", + pa: "Punjabi", + "pa-IN": "Punjabi (India)", + "pa-PK": "Punjabi (Pakistan)", + qu: "Quechua", + rm: "Rhaeto-Romanic", + ro: "Romanian", + "ro-MO": "Romanian (Moldavia)", + ru: "Russian", + "ru-MO": "Russian (Moldavia)", + sz: "Sami (Lappish)", + sg: "Sango", + sa: "Sanskrit", + sc: "Sardinian", + sd: "Sindhi", + si: "Singhalese", + sr: "Serbian", + sk: "Slovak", + sl: "Slovenian", + so: "Somani", + sb: "Sorbian", + es: "Spanish", + "es-AR": "Spanish (Argentina)", + "es-BO": "Spanish (Bolivia)", + "es-CL": "Spanish (Chile)", + "es-CO": "Spanish (Colombia)", + "es-CR": "Spanish (Costa Rica)", + "es-DO": "Spanish (Dominican Republic)", + "es-EC": "Spanish (Ecuador)", + "es-SV": "Spanish (El Salvador)", + "es-GT": "Spanish (Guatemala)", + "es-HN": "Spanish (Honduras)", + "es-MX": "Spanish (Mexico)", + "es-NI": "Spanish (Nicaragua)", + "es-PA": "Spanish (Panama)", + "es-PY": "Spanish (Paraguay)", + "es-PE": "Spanish (Peru)", + "es-PR": "Spanish (Puerto Rico)", + "es-ES": "Spanish (Spain)", + "es-UY": "Spanish (Uruguay)", + "es-VE": "Spanish (Venezuela)", + sx: "Sutu", + sw: "Swahili", + sv: "Swedish", + "sv-FI": "Swedish (Finland)", + "sv-SV": "Swedish (Sweden)", + ta: "Tamil", + tt: "Tatar", + te: "Teluga", + th: "Thai", + tig: "Tigre", + ts: "Tsonga", + tn: "Tswana", + tr: "Turkish", + tk: "Turkmen", + uk: "Ukrainian", + hsb: "Upper Sorbian", + ur: "Urdu", + ve: "Venda", + vi: "Vietnamese", + vo: "Volapuk", + wa: "Walloon", + cy: "Welsh", + xh: "Xhosa", + ji: "Yiddish", + zu: "Zulu" + }; + + if (this.internal.languageSettings === undefined) { + this.internal.languageSettings = {}; + this.internal.languageSettings.isSubscribed = false; + } + + if (langCodes[langCode] !== undefined) { + this.internal.languageSettings.languageCode = langCode; + + if (this.internal.languageSettings.isSubscribed === false) { + this.internal.events.subscribe("putCatalog", function () { + this.internal.write("/Lang (" + this.internal.languageSettings.languageCode + ")"); + }); + this.internal.languageSettings.isSubscribed = true; + } + } + + return this; + }; + })(jsPDF.API); + + /** @license + * MIT license. + * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com + * 2014 Diego Casorran, https://github.com/diegocr + * + * + * ==================================================================== + */ + + /** + * jsPDF split_text_to_size plugin + * + * @name split_text_to_size + * @module + */ + (function (API) { + /** + * Returns an array of length matching length of the 'word' string, with each + * cell occupied by the width of the char in that position. + * + * @name getCharWidthsArray + * @function + * @param {string} text + * @param {Object} options + * @returns {Array} + */ + + var getCharWidthsArray = API.getCharWidthsArray = function (text, options) { + options = options || {}; + var activeFont = options.font || this.internal.getFont(); + var fontSize = options.fontSize || this.internal.getFontSize(); + var charSpace = options.charSpace || this.internal.getCharSpace(); + var widths = options.widths ? options.widths : activeFont.metadata.Unicode.widths; + var widthsFractionOf = widths.fof ? widths.fof : 1; + var kerning = options.kerning ? options.kerning : activeFont.metadata.Unicode.kerning; + var kerningFractionOf = kerning.fof ? kerning.fof : 1; + var i; + var l; + var char_code; + var prior_char_code = 0; //for kerning + + var default_char_width = widths[0] || widthsFractionOf; + var output = []; + + for (i = 0, l = text.length; i < l; i++) { + char_code = text.charCodeAt(i); + + if (typeof activeFont.metadata.widthOfString === "function") { + output.push((activeFont.metadata.widthOfGlyph(activeFont.metadata.characterToGlyph(char_code)) + charSpace * (1000 / fontSize) || 0) / 1000); + } else { + output.push((widths[char_code] || default_char_width) / widthsFractionOf + (kerning[char_code] && kerning[char_code][prior_char_code] || 0) / kerningFractionOf); + } + + prior_char_code = char_code; + } + + return output; + }; + /** + * Calculate the sum of a number-array + * + * @name getArraySum + * @public + * @function + * @param {Array} array Array of numbers + * @returns {number} + */ + + + var getArraySum = API.getArraySum = function (array) { + var i = array.length, + output = 0; + + while (i) { + i--; + output += array[i]; + } + + return output; + }; + /** + * Returns a widths of string in a given font, if the font size is set as 1 point. + * + * In other words, this is "proportional" value. For 1 unit of font size, the length + * of the string will be that much. + * + * Multiply by font size to get actual width in *points* + * Then divide by 72 to get inches or divide by (72/25.6) to get 'mm' etc. + * + * @name getStringUnitWidth + * @public + * @function + * @param {string} text + * @param {string} options + * @returns {number} result + */ + + + var getStringUnitWidth = API.getStringUnitWidth = function (text, options) { + options = options || {}; + var fontSize = options.fontSize || this.internal.getFontSize(); + var font = options.font || this.internal.getFont(); + var charSpace = options.charSpace || this.internal.getCharSpace(); + var result = 0; + + if (typeof font.metadata.widthOfString === "function") { + result = font.metadata.widthOfString(text, fontSize, charSpace) / fontSize; + } else { + result = getArraySum(getCharWidthsArray.apply(this, arguments)); + } + + return result; + }; + /** + returns array of lines + */ + + + var splitLongWord = function splitLongWord(word, widths_array, firstLineMaxLen, maxLen) { + var answer = []; // 1st, chop off the piece that can fit on the hanging line. + + var i = 0, + l = word.length, + workingLen = 0; + + while (i !== l && workingLen + widths_array[i] < firstLineMaxLen) { + workingLen += widths_array[i]; + i++; + } // this is first line. + + + answer.push(word.slice(0, i)); // 2nd. Split the rest into maxLen pieces. + + var startOfLine = i; + workingLen = 0; + + while (i !== l) { + if (workingLen + widths_array[i] > maxLen) { + answer.push(word.slice(startOfLine, i)); + workingLen = 0; + startOfLine = i; + } + + workingLen += widths_array[i]; + i++; + } + + if (startOfLine !== i) { + answer.push(word.slice(startOfLine, i)); + } + + return answer; + }; // Note, all sizing inputs for this function must be in "font measurement units" + // By default, for PDF, it's "point". + + + var splitParagraphIntoLines = function splitParagraphIntoLines(text, maxlen, options) { + // at this time works only on Western scripts, ones with space char + // separating the words. Feel free to expand. + if (!options) { + options = {}; + } + + var line = [], + lines = [line], + line_length = options.textIndent || 0, + separator_length = 0, + current_word_length = 0, + word, + widths_array, + words = text.split(" "), + spaceCharWidth = getCharWidthsArray.apply(this, [" ", options])[0], + i, + l, + tmp, + lineIndent; + + if (options.lineIndent === -1) { + lineIndent = words[0].length + 2; + } else { + lineIndent = options.lineIndent || 0; + } + + if (lineIndent) { + var pad = Array(lineIndent).join(" "), + wrds = []; + words.map(function (wrd) { + wrd = wrd.split(/\s*\n/); + + if (wrd.length > 1) { + wrds = wrds.concat(wrd.map(function (wrd, idx) { + return (idx && wrd.length ? "\n" : "") + wrd; + })); + } else { + wrds.push(wrd[0]); + } + }); + words = wrds; + lineIndent = getStringUnitWidth.apply(this, [pad, options]); + } + + for (i = 0, l = words.length; i < l; i++) { + var force = 0; + word = words[i]; + + if (lineIndent && word[0] == "\n") { + word = word.substr(1); + force = 1; + } + + widths_array = getCharWidthsArray.apply(this, [word, options]); + current_word_length = getArraySum(widths_array); + + if (line_length + separator_length + current_word_length > maxlen || force) { + if (current_word_length > maxlen) { + // this happens when you have space-less long URLs for example. + // we just chop these to size. We do NOT insert hiphens + tmp = splitLongWord.apply(this, [word, widths_array, maxlen - (line_length + separator_length), maxlen]); // first line we add to existing line object + + line.push(tmp.shift()); // it's ok to have extra space indicator there + // last line we make into new line object + + line = [tmp.pop()]; // lines in the middle we apped to lines object as whole lines + + while (tmp.length) { + lines.push([tmp.shift()]); // single fragment occupies whole line + } + + current_word_length = getArraySum(widths_array.slice(word.length - (line[0] ? line[0].length : 0))); + } else { + // just put it on a new line + line = [word]; + } // now we attach new line to lines + + + lines.push(line); + line_length = current_word_length + lineIndent; + separator_length = spaceCharWidth; + } else { + line.push(word); + line_length += separator_length + current_word_length; + separator_length = spaceCharWidth; + } + } + + if (lineIndent) { + var postProcess = function postProcess(ln, idx) { + return (idx ? pad : "") + ln.join(" "); + }; + } else { + var postProcess = function postProcess(ln) { + return ln.join(" "); + }; + } + + return lines.map(postProcess); + }; + /** + * Splits a given string into an array of strings. Uses 'size' value + * (in measurement units declared as default for the jsPDF instance) + * and the font's "widths" and "Kerning" tables, where available, to + * determine display length of a given string for a given font. + * + * We use character's 100% of unit size (height) as width when Width + * table or other default width is not available. + * + * @name splitTextToSize + * @public + * @function + * @param {string} text Unencoded, regular JavaScript (Unicode, UTF-16 / UCS-2) string. + * @param {number} size Nominal number, measured in units default to this instance of jsPDF. + * @param {Object} options Optional flags needed for chopper to do the right thing. + * @returns {Array} array Array with strings chopped to size. + */ + + + API.splitTextToSize = function (text, maxlen, options) { + + options = options || {}; + + var fsize = options.fontSize || this.internal.getFontSize(), + newOptions = function (options) { + var widths = { + 0: 1 + }, + kerning = {}; + + if (!options.widths || !options.kerning) { + var f = this.internal.getFont(options.fontName, options.fontStyle), + encoding = "Unicode"; // NOT UTF8, NOT UTF16BE/LE, NOT UCS2BE/LE + // Actual JavaScript-native String's 16bit char codes used. + // no multi-byte logic here + + if (f.metadata[encoding]) { + return { + widths: f.metadata[encoding].widths || widths, + kerning: f.metadata[encoding].kerning || kerning + }; + } else { + return { + font: f.metadata, + fontSize: this.internal.getFontSize(), + charSpace: this.internal.getCharSpace() + }; + } + } else { + return { + widths: options.widths, + kerning: options.kerning + }; + } // then use default values + + + return { + widths: widths, + kerning: kerning + }; + }.call(this, options); // first we split on end-of-line chars + + + var paragraphs; + + if (Array.isArray(text)) { + paragraphs = text; + } else { + paragraphs = text.split(/\r?\n/); + } // now we convert size (max length of line) into "font size units" + // at present time, the "font size unit" is always 'point' + // 'proportional' means, "in proportion to font size" + + + var fontUnit_maxLen = 1.0 * this.internal.scaleFactor * maxlen / fsize; // at this time, fsize is always in "points" regardless of the default measurement unit of the doc. + // this may change in the future? + // until then, proportional_maxlen is likely to be in 'points' + // If first line is to be indented (shorter or longer) than maxLen + // we indicate that by using CSS-style "text-indent" option. + // here it's in font units too (which is likely 'points') + // it can be negative (which makes the first line longer than maxLen) + + newOptions.textIndent = options.textIndent ? options.textIndent * 1.0 * this.internal.scaleFactor / fsize : 0; + newOptions.lineIndent = options.lineIndent; + var i, + l, + output = []; + + for (i = 0, l = paragraphs.length; i < l; i++) { + output = output.concat(splitParagraphIntoLines.apply(this, [paragraphs[i], fontUnit_maxLen, newOptions])); + } + + return output; + }; + })(jsPDF.API); + + /** @license + jsPDF standard_fonts_metrics plugin + * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com + * MIT license. + * + * ==================================================================== + */ + + /** + * This file adds the standard font metrics to jsPDF. + * + * Font metrics data is reprocessed derivative of contents of + * "Font Metrics for PDF Core 14 Fonts" package, which exhibits the following copyright and license: + * + * Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved. + * + * This file and the 14 PostScript(R) AFM files it accompanies may be used, + * copied, and distributed for any purpose and without charge, with or without + * modification, provided that all copyright notices are retained; that the AFM + * files are not distributed without this file; that all modifications to this + * file or any of the AFM files are prominently noted in the modified file(s); + * and that this paragraph is not modified. Adobe Systems has no responsibility + * or obligation to support the use of the AFM files. + * + * @name standard_fonts_metrics + * @module + */ + (function (API) { + /* + # reference (Python) versions of 'compress' and 'uncompress' + # only 'uncompress' function is featured lower as JavaScript + # if you want to unit test "roundtrip", just transcribe the reference + # 'compress' function from Python into JavaScript + def compress(data): + keys = '0123456789abcdef' + values = 'klmnopqrstuvwxyz' + mapping = dict(zip(keys, values)) + vals = [] + for key in data.keys(): + value = data[key] + try: + keystring = hex(key)[2:] + keystring = keystring[:-1] + mapping[keystring[-1:]] + except: + keystring = key.join(["'","'"]) + #print('Keystring is %s' % keystring) + try: + if value < 0: + valuestring = hex(value)[3:] + numberprefix = '-' + else: + valuestring = hex(value)[2:] + numberprefix = '' + valuestring = numberprefix + valuestring[:-1] + mapping[valuestring[-1:]] + except: + if type(value) == dict: + valuestring = compress(value) + else: + raise Exception("Don't know what to do with value type %s" % type(value)) + vals.append(keystring+valuestring) + + return '{' + ''.join(vals) + '}' + def uncompress(data): + decoded = '0123456789abcdef' + encoded = 'klmnopqrstuvwxyz' + mapping = dict(zip(encoded, decoded)) + sign = +1 + stringmode = False + stringparts = [] + output = {} + activeobject = output + parentchain = [] + keyparts = '' + valueparts = '' + key = None + ending = set(encoded) + i = 1 + l = len(data) - 1 # stripping starting, ending {} + while i != l: # stripping {} + # -, {, }, ' are special. + ch = data[i] + i += 1 + if ch == "'": + if stringmode: + # end of string mode + stringmode = False + key = ''.join(stringparts) + else: + # start of string mode + stringmode = True + stringparts = [] + elif stringmode == True: + #print("Adding %s to stringpart" % ch) + stringparts.append(ch) + elif ch == '{': + # start of object + parentchain.append( [activeobject, key] ) + activeobject = {} + key = None + #DEBUG = True + elif ch == '}': + # end of object + parent, key = parentchain.pop() + parent[key] = activeobject + key = None + activeobject = parent + #DEBUG = False + elif ch == '-': + sign = -1 + else: + # must be number + if key == None: + #debug("In Key. It is '%s', ch is '%s'" % (keyparts, ch)) + if ch in ending: + #debug("End of key") + keyparts += mapping[ch] + key = int(keyparts, 16) * sign + sign = +1 + keyparts = '' + else: + keyparts += ch + else: + #debug("In value. It is '%s', ch is '%s'" % (valueparts, ch)) + if ch in ending: + #debug("End of value") + valueparts += mapping[ch] + activeobject[key] = int(valueparts, 16) * sign + sign = +1 + key = None + valueparts = '' + else: + valueparts += ch + #debug(activeobject) + return output + */ + + /** + Uncompresses data compressed into custom, base16-like format. + @public + @function + @param + @returns {Type} + */ + + var uncompress = function uncompress(data) { + var decoded = "0123456789abcdef", + encoded = "klmnopqrstuvwxyz", + mapping = {}; + + for (var i = 0; i < encoded.length; i++) { + mapping[encoded[i]] = decoded[i]; + } + + var undef, + output = {}, + sign = 1, + stringparts, + // undef. will be [] in string mode + activeobject = output, + parentchain = [], + parent_key_pair, + keyparts = "", + valueparts = "", + key, + // undef. will be Truthy when Key is resolved. + datalen = data.length - 1, + // stripping ending } + ch; + i = 1; // stripping starting { + + while (i != datalen) { + // - { } ' are special. + ch = data[i]; + i += 1; + + if (ch == "'") { + if (stringparts) { + // end of string mode + key = stringparts.join(""); + stringparts = undef; + } else { + // start of string mode + stringparts = []; + } + } else if (stringparts) { + stringparts.push(ch); + } else if (ch == "{") { + // start of object + parentchain.push([activeobject, key]); + activeobject = {}; + key = undef; + } else if (ch == "}") { + // end of object + parent_key_pair = parentchain.pop(); + parent_key_pair[0][parent_key_pair[1]] = activeobject; + key = undef; + activeobject = parent_key_pair[0]; + } else if (ch == "-") { + sign = -1; + } else { + // must be number + if (key === undef) { + if (mapping.hasOwnProperty(ch)) { + keyparts += mapping[ch]; + key = parseInt(keyparts, 16) * sign; + sign = +1; + keyparts = ""; + } else { + keyparts += ch; + } + } else { + if (mapping.hasOwnProperty(ch)) { + valueparts += mapping[ch]; + activeobject[key] = parseInt(valueparts, 16) * sign; + sign = +1; + key = undef; + valueparts = ""; + } else { + valueparts += ch; + } + } + } + } // end while + + + return output; + }; // encoding = 'Unicode' + // NOT UTF8, NOT UTF16BE/LE, NOT UCS2BE/LE. NO clever BOM behavior + // Actual 16bit char codes used. + // no multi-byte logic here + // Unicode characters to WinAnsiEncoding: + // {402: 131, 8211: 150, 8212: 151, 8216: 145, 8217: 146, 8218: 130, 8220: 147, 8221: 148, 8222: 132, 8224: 134, 8225: 135, 8226: 149, 8230: 133, 8364: 128, 8240:137, 8249: 139, 8250: 155, 710: 136, 8482: 153, 338: 140, 339: 156, 732: 152, 352: 138, 353: 154, 376: 159, 381: 142, 382: 158} + // as you can see, all Unicode chars are outside of 0-255 range. No char code conflicts. + // this means that you can give Win cp1252 encoded strings to jsPDF for rendering directly + // as well as give strings with some (supported by these fonts) Unicode characters and + // these will be mapped to win cp1252 + // for example, you can send char code (cp1252) 0x80 or (unicode) 0x20AC, getting "Euro" glyph displayed in both cases. + + + var encodingBlock = { + codePages: ["WinAnsiEncoding"], + WinAnsiEncoding: uncompress("{19m8n201n9q201o9r201s9l201t9m201u8m201w9n201x9o201y8o202k8q202l8r202m9p202q8p20aw8k203k8t203t8v203u9v2cq8s212m9t15m8w15n9w2dw9s16k8u16l9u17s9z17x8y17y9y}") + }, + encodings = { + Unicode: { + Courier: encodingBlock, + "Courier-Bold": encodingBlock, + "Courier-BoldOblique": encodingBlock, + "Courier-Oblique": encodingBlock, + Helvetica: encodingBlock, + "Helvetica-Bold": encodingBlock, + "Helvetica-BoldOblique": encodingBlock, + "Helvetica-Oblique": encodingBlock, + "Times-Roman": encodingBlock, + "Times-Bold": encodingBlock, + "Times-BoldItalic": encodingBlock, + "Times-Italic": encodingBlock // , 'Symbol' + // , 'ZapfDingbats' + + } + }, + fontMetrics = { + Unicode: { + // all sizing numbers are n/fontMetricsFractionOf = one font size unit + // this means that if fontMetricsFractionOf = 1000, and letter A's width is 476, it's + // width is 476/1000 or 47.6% of its height (regardless of font size) + // At this time this value applies to "widths" and "kerning" numbers. + // char code 0 represents "default" (average) width - use it for chars missing in this table. + // key 'fof' represents the "fontMetricsFractionOf" value + "Courier-Oblique": uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"), + "Times-BoldItalic": uncompress("{'widths'{k3o2q4ycx2r201n3m201o6o201s2l201t2l201u2l201w3m201x3m201y3m2k1t2l2r202m2n2n3m2o3m2p5n202q6o2r1w2s2l2t2l2u3m2v3t2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v2l3w3t3x3t3y3t3z3m4k5n4l4m4m4m4n4m4o4s4p4m4q4m4r4s4s4y4t2r4u3m4v4m4w3x4x5t4y4s4z4s5k3x5l4s5m4m5n3r5o3x5p4s5q4m5r5t5s4m5t3x5u3x5v2l5w1w5x2l5y3t5z3m6k2l6l3m6m3m6n2w6o3m6p2w6q2l6r3m6s3r6t1w6u1w6v3m6w1w6x4y6y3r6z3m7k3m7l3m7m2r7n2r7o1w7p3r7q2w7r4m7s3m7t2w7u2r7v2n7w1q7x2n7y3t202l3mcl4mal2ram3man3mao3map3mar3mas2lat4uau1uav3maw3way4uaz2lbk2sbl3t'fof'6obo2lbp3tbq3mbr1tbs2lbu1ybv3mbz3mck4m202k3mcm4mcn4mco4mcp4mcq5ycr4mcs4mct4mcu4mcv4mcw2r2m3rcy2rcz2rdl4sdm4sdn4sdo4sdp4sdq4sds4sdt4sdu4sdv4sdw4sdz3mek3mel3mem3men3meo3mep3meq4ser2wes2wet2weu2wev2wew1wex1wey1wez1wfl3rfm3mfn3mfo3mfp3mfq3mfr3tfs3mft3rfu3rfv3rfw3rfz2w203k6o212m6o2dw2l2cq2l3t3m3u2l17s3x19m3m}'kerning'{cl{4qu5kt5qt5rs17ss5ts}201s{201ss}201t{cks4lscmscnscoscpscls2wu2yu201ts}201x{2wu2yu}2k{201ts}2w{4qx5kx5ou5qx5rs17su5tu}2x{17su5tu5ou}2y{4qx5kx5ou5qx5rs17ss5ts}'fof'-6ofn{17sw5tw5ou5qw5rs}7t{cksclscmscnscoscps4ls}3u{17su5tu5os5qs}3v{17su5tu5os5qs}7p{17su5tu}ck{4qu5kt5qt5rs17ss5ts}4l{4qu5kt5qt5rs17ss5ts}cm{4qu5kt5qt5rs17ss5ts}cn{4qu5kt5qt5rs17ss5ts}co{4qu5kt5qt5rs17ss5ts}cp{4qu5kt5qt5rs17ss5ts}6l{4qu5ou5qw5rt17su5tu}5q{ckuclucmucnucoucpu4lu}5r{ckuclucmucnucoucpu4lu}7q{cksclscmscnscoscps4ls}6p{4qu5ou5qw5rt17sw5tw}ek{4qu5ou5qw5rt17su5tu}el{4qu5ou5qw5rt17su5tu}em{4qu5ou5qw5rt17su5tu}en{4qu5ou5qw5rt17su5tu}eo{4qu5ou5qw5rt17su5tu}ep{4qu5ou5qw5rt17su5tu}es{17ss5ts5qs4qu}et{4qu5ou5qw5rt17sw5tw}eu{4qu5ou5qw5rt17ss5ts}ev{17ss5ts5qs4qu}6z{17sw5tw5ou5qw5rs}fm{17sw5tw5ou5qw5rs}7n{201ts}fo{17sw5tw5ou5qw5rs}fp{17sw5tw5ou5qw5rs}fq{17sw5tw5ou5qw5rs}7r{cksclscmscnscoscps4ls}fs{17sw5tw5ou5qw5rs}ft{17su5tu}fu{17su5tu}fv{17su5tu}fw{17su5tu}fz{cksclscmscnscoscps4ls}}}"), + "Helvetica-Bold": uncompress("{'widths'{k3s2q4scx1w201n3r201o6o201s1w201t1w201u1w201w3m201x3m201y3m2k1w2l2l202m2n2n3r2o3r2p5t202q6o2r1s2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v2l3w3u3x3u3y3u3z3x4k6l4l4s4m4s4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3r4v4s4w3x4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v2l5w1w5x2l5y3u5z3r6k2l6l3r6m3x6n3r6o3x6p3r6q2l6r3x6s3x6t1w6u1w6v3r6w1w6x5t6y3x6z3x7k3x7l3x7m2r7n3r7o2l7p3x7q3r7r4y7s3r7t3r7u3m7v2r7w1w7x2r7y3u202l3rcl4sal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3xbq3rbr1wbs2lbu2obv3rbz3xck4s202k3rcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw1w2m2zcy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3res3ret3reu3rev3rew1wex1wey1wez1wfl3xfm3xfn3xfo3xfp3xfq3xfr3ufs3xft3xfu3xfv3xfw3xfz3r203k6o212m6o2dw2l2cq2l3t3r3u2l17s4m19m3r}'kerning'{cl{4qs5ku5ot5qs17sv5tv}201t{2ww4wy2yw}201w{2ks}201x{2ww4wy2yw}2k{201ts201xs}2w{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}2x{5ow5qs}2y{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}'fof'-6o7p{17su5tu5ot}ck{4qs5ku5ot5qs17sv5tv}4l{4qs5ku5ot5qs17sv5tv}cm{4qs5ku5ot5qs17sv5tv}cn{4qs5ku5ot5qs17sv5tv}co{4qs5ku5ot5qs17sv5tv}cp{4qs5ku5ot5qs17sv5tv}6l{17st5tt5os}17s{2kwclvcmvcnvcovcpv4lv4wwckv}5o{2kucltcmtcntcotcpt4lt4wtckt}5q{2ksclscmscnscoscps4ls4wvcks}5r{2ks4ws}5t{2kwclvcmvcnvcovcpv4lv4wwckv}eo{17st5tt5os}fu{17su5tu5ot}6p{17ss5ts}ek{17st5tt5os}el{17st5tt5os}em{17st5tt5os}en{17st5tt5os}6o{201ts}ep{17st5tt5os}es{17ss5ts}et{17ss5ts}eu{17ss5ts}ev{17ss5ts}6z{17su5tu5os5qt}fm{17su5tu5os5qt}fn{17su5tu5os5qt}fo{17su5tu5os5qt}fp{17su5tu5os5qt}fq{17su5tu5os5qt}fs{17su5tu5os5qt}ft{17su5tu5ot}7m{5os}fv{17su5tu5ot}fw{17su5tu5ot}}}"), + Courier: uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"), + "Courier-BoldOblique": uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"), + "Times-Bold": uncompress("{'widths'{k3q2q5ncx2r201n3m201o6o201s2l201t2l201u2l201w3m201x3m201y3m2k1t2l2l202m2n2n3m2o3m2p6o202q6o2r1w2s2l2t2l2u3m2v3t2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v2l3w3t3x3t3y3t3z3m4k5x4l4s4m4m4n4s4o4s4p4m4q3x4r4y4s4y4t2r4u3m4v4y4w4m4x5y4y4s4z4y5k3x5l4y5m4s5n3r5o4m5p4s5q4s5r6o5s4s5t4s5u4m5v2l5w1w5x2l5y3u5z3m6k2l6l3m6m3r6n2w6o3r6p2w6q2l6r3m6s3r6t1w6u2l6v3r6w1w6x5n6y3r6z3m7k3r7l3r7m2w7n2r7o2l7p3r7q3m7r4s7s3m7t3m7u2w7v2r7w1q7x2r7y3o202l3mcl4sal2lam3man3mao3map3mar3mas2lat4uau1yav3maw3tay4uaz2lbk2sbl3t'fof'6obo2lbp3rbr1tbs2lbu2lbv3mbz3mck4s202k3mcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw2r2m3rcy2rcz2rdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3rek3mel3mem3men3meo3mep3meq4ser2wes2wet2weu2wev2wew1wex1wey1wez1wfl3rfm3mfn3mfo3mfp3mfq3mfr3tfs3mft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3m3u2l17s4s19m3m}'kerning'{cl{4qt5ks5ot5qy5rw17sv5tv}201t{cks4lscmscnscoscpscls4wv}2k{201ts}2w{4qu5ku7mu5os5qx5ru17su5tu}2x{17su5tu5ou5qs}2y{4qv5kv7mu5ot5qz5ru17su5tu}'fof'-6o7t{cksclscmscnscoscps4ls}3u{17su5tu5os5qu}3v{17su5tu5os5qu}fu{17su5tu5ou5qu}7p{17su5tu5ou5qu}ck{4qt5ks5ot5qy5rw17sv5tv}4l{4qt5ks5ot5qy5rw17sv5tv}cm{4qt5ks5ot5qy5rw17sv5tv}cn{4qt5ks5ot5qy5rw17sv5tv}co{4qt5ks5ot5qy5rw17sv5tv}cp{4qt5ks5ot5qy5rw17sv5tv}6l{17st5tt5ou5qu}17s{ckuclucmucnucoucpu4lu4wu}5o{ckuclucmucnucoucpu4lu4wu}5q{ckzclzcmzcnzcozcpz4lz4wu}5r{ckxclxcmxcnxcoxcpx4lx4wu}5t{ckuclucmucnucoucpu4lu4wu}7q{ckuclucmucnucoucpu4lu}6p{17sw5tw5ou5qu}ek{17st5tt5qu}el{17st5tt5ou5qu}em{17st5tt5qu}en{17st5tt5qu}eo{17st5tt5qu}ep{17st5tt5ou5qu}es{17ss5ts5qu}et{17sw5tw5ou5qu}eu{17sw5tw5ou5qu}ev{17ss5ts5qu}6z{17sw5tw5ou5qu5rs}fm{17sw5tw5ou5qu5rs}fn{17sw5tw5ou5qu5rs}fo{17sw5tw5ou5qu5rs}fp{17sw5tw5ou5qu5rs}fq{17sw5tw5ou5qu5rs}7r{cktcltcmtcntcotcpt4lt5os}fs{17sw5tw5ou5qu5rs}ft{17su5tu5ou5qu}7m{5os}fv{17su5tu5ou5qu}fw{17su5tu5ou5qu}fz{cksclscmscnscoscps4ls}}}"), + Symbol: uncompress("{'widths'{k3uaw4r19m3m2k1t2l2l202m2y2n3m2p5n202q6o3k3m2s2l2t2l2v3r2w1t3m3m2y1t2z1wbk2sbl3r'fof'6o3n3m3o3m3p3m3q3m3r3m3s3m3t3m3u1w3v1w3w3r3x3r3y3r3z2wbp3t3l3m5v2l5x2l5z3m2q4yfr3r7v3k7w1o7x3k}'kerning'{'fof'-6o}}"), + Helvetica: uncompress("{'widths'{k3p2q4mcx1w201n3r201o6o201s1q201t1q201u1q201w2l201x2l201y2l2k1w2l1w202m2n2n3r2o3r2p5t202q6o2r1n2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v1w3w3u3x3u3y3u3z3r4k6p4l4m4m4m4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3m4v4m4w3r4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v1w5w1w5x1w5y2z5z3r6k2l6l3r6m3r6n3m6o3r6p3r6q1w6r3r6s3r6t1q6u1q6v3m6w1q6x5n6y3r6z3r7k3r7l3r7m2l7n3m7o1w7p3r7q3m7r4s7s3m7t3m7u3m7v2l7w1u7x2l7y3u202l3rcl4mal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3rbr1wbs2lbu2obv3rbz3xck4m202k3rcm4mcn4mco4mcp4mcq6ocr4scs4mct4mcu4mcv4mcw1w2m2ncy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3mes3ret3reu3rev3rew1wex1wey1wez1wfl3rfm3rfn3rfo3rfp3rfq3rfr3ufs3xft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3r3u1w17s4m19m3r}'kerning'{5q{4wv}cl{4qs5kw5ow5qs17sv5tv}201t{2wu4w1k2yu}201x{2wu4wy2yu}17s{2ktclucmucnu4otcpu4lu4wycoucku}2w{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}2x{17sy5ty5oy5qs}2y{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}'fof'-6o7p{17sv5tv5ow}ck{4qs5kw5ow5qs17sv5tv}4l{4qs5kw5ow5qs17sv5tv}cm{4qs5kw5ow5qs17sv5tv}cn{4qs5kw5ow5qs17sv5tv}co{4qs5kw5ow5qs17sv5tv}cp{4qs5kw5ow5qs17sv5tv}6l{17sy5ty5ow}do{17st5tt}4z{17st5tt}7s{fst}dm{17st5tt}dn{17st5tt}5o{ckwclwcmwcnwcowcpw4lw4wv}dp{17st5tt}dq{17st5tt}7t{5ow}ds{17st5tt}5t{2ktclucmucnu4otcpu4lu4wycoucku}fu{17sv5tv5ow}6p{17sy5ty5ow5qs}ek{17sy5ty5ow}el{17sy5ty5ow}em{17sy5ty5ow}en{5ty}eo{17sy5ty5ow}ep{17sy5ty5ow}es{17sy5ty5qs}et{17sy5ty5ow5qs}eu{17sy5ty5ow5qs}ev{17sy5ty5ow5qs}6z{17sy5ty5ow5qs}fm{17sy5ty5ow5qs}fn{17sy5ty5ow5qs}fo{17sy5ty5ow5qs}fp{17sy5ty5qs}fq{17sy5ty5ow5qs}7r{5ow}fs{17sy5ty5ow5qs}ft{17sv5tv5ow}7m{5ow}fv{17sv5tv5ow}fw{17sv5tv5ow}}}"), + "Helvetica-BoldOblique": uncompress("{'widths'{k3s2q4scx1w201n3r201o6o201s1w201t1w201u1w201w3m201x3m201y3m2k1w2l2l202m2n2n3r2o3r2p5t202q6o2r1s2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v2l3w3u3x3u3y3u3z3x4k6l4l4s4m4s4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3r4v4s4w3x4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v2l5w1w5x2l5y3u5z3r6k2l6l3r6m3x6n3r6o3x6p3r6q2l6r3x6s3x6t1w6u1w6v3r6w1w6x5t6y3x6z3x7k3x7l3x7m2r7n3r7o2l7p3x7q3r7r4y7s3r7t3r7u3m7v2r7w1w7x2r7y3u202l3rcl4sal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3xbq3rbr1wbs2lbu2obv3rbz3xck4s202k3rcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw1w2m2zcy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3res3ret3reu3rev3rew1wex1wey1wez1wfl3xfm3xfn3xfo3xfp3xfq3xfr3ufs3xft3xfu3xfv3xfw3xfz3r203k6o212m6o2dw2l2cq2l3t3r3u2l17s4m19m3r}'kerning'{cl{4qs5ku5ot5qs17sv5tv}201t{2ww4wy2yw}201w{2ks}201x{2ww4wy2yw}2k{201ts201xs}2w{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}2x{5ow5qs}2y{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}'fof'-6o7p{17su5tu5ot}ck{4qs5ku5ot5qs17sv5tv}4l{4qs5ku5ot5qs17sv5tv}cm{4qs5ku5ot5qs17sv5tv}cn{4qs5ku5ot5qs17sv5tv}co{4qs5ku5ot5qs17sv5tv}cp{4qs5ku5ot5qs17sv5tv}6l{17st5tt5os}17s{2kwclvcmvcnvcovcpv4lv4wwckv}5o{2kucltcmtcntcotcpt4lt4wtckt}5q{2ksclscmscnscoscps4ls4wvcks}5r{2ks4ws}5t{2kwclvcmvcnvcovcpv4lv4wwckv}eo{17st5tt5os}fu{17su5tu5ot}6p{17ss5ts}ek{17st5tt5os}el{17st5tt5os}em{17st5tt5os}en{17st5tt5os}6o{201ts}ep{17st5tt5os}es{17ss5ts}et{17ss5ts}eu{17ss5ts}ev{17ss5ts}6z{17su5tu5os5qt}fm{17su5tu5os5qt}fn{17su5tu5os5qt}fo{17su5tu5os5qt}fp{17su5tu5os5qt}fq{17su5tu5os5qt}fs{17su5tu5os5qt}ft{17su5tu5ot}7m{5os}fv{17su5tu5ot}fw{17su5tu5ot}}}"), + ZapfDingbats: uncompress("{'widths'{k4u2k1w'fof'6o}'kerning'{'fof'-6o}}"), + "Courier-Bold": uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"), + "Times-Italic": uncompress("{'widths'{k3n2q4ycx2l201n3m201o5t201s2l201t2l201u2l201w3r201x3r201y3r2k1t2l2l202m2n2n3m2o3m2p5n202q5t2r1p2s2l2t2l2u3m2v4n2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v2l3w4n3x4n3y4n3z3m4k5w4l3x4m3x4n4m4o4s4p3x4q3x4r4s4s4s4t2l4u2w4v4m4w3r4x5n4y4m4z4s5k3x5l4s5m3x5n3m5o3r5p4s5q3x5r5n5s3x5t3r5u3r5v2r5w1w5x2r5y2u5z3m6k2l6l3m6m3m6n2w6o3m6p2w6q1w6r3m6s3m6t1w6u1w6v2w6w1w6x4s6y3m6z3m7k3m7l3m7m2r7n2r7o1w7p3m7q2w7r4m7s2w7t2w7u2r7v2s7w1v7x2s7y3q202l3mcl3xal2ram3man3mao3map3mar3mas2lat4wau1vav3maw4nay4waz2lbk2sbl4n'fof'6obo2lbp3mbq3obr1tbs2lbu1zbv3mbz3mck3x202k3mcm3xcn3xco3xcp3xcq5tcr4mcs3xct3xcu3xcv3xcw2l2m2ucy2lcz2ldl4mdm4sdn4sdo4sdp4sdq4sds4sdt4sdu4sdv4sdw4sdz3mek3mel3mem3men3meo3mep3meq4mer2wes2wet2weu2wev2wew1wex1wey1wez1wfl3mfm3mfn3mfo3mfp3mfq3mfr4nfs3mft3mfu3mfv3mfw3mfz2w203k6o212m6m2dw2l2cq2l3t3m3u2l17s3r19m3m}'kerning'{cl{5kt4qw}201s{201sw}201t{201tw2wy2yy6q-t}201x{2wy2yy}2k{201tw}2w{7qs4qy7rs5ky7mw5os5qx5ru17su5tu}2x{17ss5ts5os}2y{7qs4qy7rs5ky7mw5os5qx5ru17su5tu}'fof'-6o6t{17ss5ts5qs}7t{5os}3v{5qs}7p{17su5tu5qs}ck{5kt4qw}4l{5kt4qw}cm{5kt4qw}cn{5kt4qw}co{5kt4qw}cp{5kt4qw}6l{4qs5ks5ou5qw5ru17su5tu}17s{2ks}5q{ckvclvcmvcnvcovcpv4lv}5r{ckuclucmucnucoucpu4lu}5t{2ks}6p{4qs5ks5ou5qw5ru17su5tu}ek{4qs5ks5ou5qw5ru17su5tu}el{4qs5ks5ou5qw5ru17su5tu}em{4qs5ks5ou5qw5ru17su5tu}en{4qs5ks5ou5qw5ru17su5tu}eo{4qs5ks5ou5qw5ru17su5tu}ep{4qs5ks5ou5qw5ru17su5tu}es{5ks5qs4qs}et{4qs5ks5ou5qw5ru17su5tu}eu{4qs5ks5qw5ru17su5tu}ev{5ks5qs4qs}ex{17ss5ts5qs}6z{4qv5ks5ou5qw5ru17su5tu}fm{4qv5ks5ou5qw5ru17su5tu}fn{4qv5ks5ou5qw5ru17su5tu}fo{4qv5ks5ou5qw5ru17su5tu}fp{4qv5ks5ou5qw5ru17su5tu}fq{4qv5ks5ou5qw5ru17su5tu}7r{5os}fs{4qv5ks5ou5qw5ru17su5tu}ft{17su5tu5qs}fu{17su5tu5qs}fv{17su5tu5qs}fw{17su5tu5qs}}}"), + "Times-Roman": uncompress("{'widths'{k3n2q4ycx2l201n3m201o6o201s2l201t2l201u2l201w2w201x2w201y2w2k1t2l2l202m2n2n3m2o3m2p5n202q6o2r1m2s2l2t2l2u3m2v3s2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v1w3w3s3x3s3y3s3z2w4k5w4l4s4m4m4n4m4o4s4p3x4q3r4r4s4s4s4t2l4u2r4v4s4w3x4x5t4y4s4z4s5k3r5l4s5m4m5n3r5o3x5p4s5q4s5r5y5s4s5t4s5u3x5v2l5w1w5x2l5y2z5z3m6k2l6l2w6m3m6n2w6o3m6p2w6q2l6r3m6s3m6t1w6u1w6v3m6w1w6x4y6y3m6z3m7k3m7l3m7m2l7n2r7o1w7p3m7q3m7r4s7s3m7t3m7u2w7v3k7w1o7x3k7y3q202l3mcl4sal2lam3man3mao3map3mar3mas2lat4wau1vav3maw3say4waz2lbk2sbl3s'fof'6obo2lbp3mbq2xbr1tbs2lbu1zbv3mbz2wck4s202k3mcm4scn4sco4scp4scq5tcr4mcs3xct3xcu3xcv3xcw2l2m2tcy2lcz2ldl4sdm4sdn4sdo4sdp4sdq4sds4sdt4sdu4sdv4sdw4sdz3mek2wel2wem2wen2weo2wep2weq4mer2wes2wet2weu2wev2wew1wex1wey1wez1wfl3mfm3mfn3mfo3mfp3mfq3mfr3sfs3mft3mfu3mfv3mfw3mfz3m203k6o212m6m2dw2l2cq2l3t3m3u1w17s4s19m3m}'kerning'{cl{4qs5ku17sw5ou5qy5rw201ss5tw201ws}201s{201ss}201t{ckw4lwcmwcnwcowcpwclw4wu201ts}2k{201ts}2w{4qs5kw5os5qx5ru17sx5tx}2x{17sw5tw5ou5qu}2y{4qs5kw5os5qx5ru17sx5tx}'fof'-6o7t{ckuclucmucnucoucpu4lu5os5rs}3u{17su5tu5qs}3v{17su5tu5qs}7p{17sw5tw5qs}ck{4qs5ku17sw5ou5qy5rw201ss5tw201ws}4l{4qs5ku17sw5ou5qy5rw201ss5tw201ws}cm{4qs5ku17sw5ou5qy5rw201ss5tw201ws}cn{4qs5ku17sw5ou5qy5rw201ss5tw201ws}co{4qs5ku17sw5ou5qy5rw201ss5tw201ws}cp{4qs5ku17sw5ou5qy5rw201ss5tw201ws}6l{17su5tu5os5qw5rs}17s{2ktclvcmvcnvcovcpv4lv4wuckv}5o{ckwclwcmwcnwcowcpw4lw4wu}5q{ckyclycmycnycoycpy4ly4wu5ms}5r{cktcltcmtcntcotcpt4lt4ws}5t{2ktclvcmvcnvcovcpv4lv4wuckv}7q{cksclscmscnscoscps4ls}6p{17su5tu5qw5rs}ek{5qs5rs}el{17su5tu5os5qw5rs}em{17su5tu5os5qs5rs}en{17su5qs5rs}eo{5qs5rs}ep{17su5tu5os5qw5rs}es{5qs}et{17su5tu5qw5rs}eu{17su5tu5qs5rs}ev{5qs}6z{17sv5tv5os5qx5rs}fm{5os5qt5rs}fn{17sv5tv5os5qx5rs}fo{17sv5tv5os5qx5rs}fp{5os5qt5rs}fq{5os5qt5rs}7r{ckuclucmucnucoucpu4lu5os}fs{17sv5tv5os5qx5rs}ft{17ss5ts5qs}fu{17sw5tw5qs}fv{17sw5tw5qs}fw{17ss5ts5qs}fz{ckuclucmucnucoucpu4lu5os5rs}}}"), + "Helvetica-Oblique": uncompress("{'widths'{k3p2q4mcx1w201n3r201o6o201s1q201t1q201u1q201w2l201x2l201y2l2k1w2l1w202m2n2n3r2o3r2p5t202q6o2r1n2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v1w3w3u3x3u3y3u3z3r4k6p4l4m4m4m4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3m4v4m4w3r4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v1w5w1w5x1w5y2z5z3r6k2l6l3r6m3r6n3m6o3r6p3r6q1w6r3r6s3r6t1q6u1q6v3m6w1q6x5n6y3r6z3r7k3r7l3r7m2l7n3m7o1w7p3r7q3m7r4s7s3m7t3m7u3m7v2l7w1u7x2l7y3u202l3rcl4mal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3rbr1wbs2lbu2obv3rbz3xck4m202k3rcm4mcn4mco4mcp4mcq6ocr4scs4mct4mcu4mcv4mcw1w2m2ncy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3mes3ret3reu3rev3rew1wex1wey1wez1wfl3rfm3rfn3rfo3rfp3rfq3rfr3ufs3xft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3r3u1w17s4m19m3r}'kerning'{5q{4wv}cl{4qs5kw5ow5qs17sv5tv}201t{2wu4w1k2yu}201x{2wu4wy2yu}17s{2ktclucmucnu4otcpu4lu4wycoucku}2w{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}2x{17sy5ty5oy5qs}2y{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}'fof'-6o7p{17sv5tv5ow}ck{4qs5kw5ow5qs17sv5tv}4l{4qs5kw5ow5qs17sv5tv}cm{4qs5kw5ow5qs17sv5tv}cn{4qs5kw5ow5qs17sv5tv}co{4qs5kw5ow5qs17sv5tv}cp{4qs5kw5ow5qs17sv5tv}6l{17sy5ty5ow}do{17st5tt}4z{17st5tt}7s{fst}dm{17st5tt}dn{17st5tt}5o{ckwclwcmwcnwcowcpw4lw4wv}dp{17st5tt}dq{17st5tt}7t{5ow}ds{17st5tt}5t{2ktclucmucnu4otcpu4lu4wycoucku}fu{17sv5tv5ow}6p{17sy5ty5ow5qs}ek{17sy5ty5ow}el{17sy5ty5ow}em{17sy5ty5ow}en{5ty}eo{17sy5ty5ow}ep{17sy5ty5ow}es{17sy5ty5qs}et{17sy5ty5ow5qs}eu{17sy5ty5ow5qs}ev{17sy5ty5ow5qs}6z{17sy5ty5ow5qs}fm{17sy5ty5ow5qs}fn{17sy5ty5ow5qs}fo{17sy5ty5ow5qs}fp{17sy5ty5qs}fq{17sy5ty5ow5qs}7r{5ow}fs{17sy5ty5ow5qs}ft{17sv5tv5ow}7m{5ow}fv{17sv5tv5ow}fw{17sv5tv5ow}}}") + } + }; + /* + This event handler is fired when a new jsPDF object is initialized + This event handler appends metrics data to standard fonts within + that jsPDF instance. The metrics are mapped over Unicode character + codes, NOT CIDs or other codes matching the StandardEncoding table of the + standard PDF fonts. + Future: + Also included is the encoding maping table, converting Unicode (UCS-2, UTF-16) + char codes to StandardEncoding character codes. The encoding table is to be used + somewhere around "pdfEscape" call. + */ + + API.events.push(["addFont", function (data) { + var font = data.font; + var metrics, + unicode_section, + encoding = "Unicode", + encodingBlock; + metrics = fontMetrics[encoding][font.postScriptName]; + + if (metrics) { + if (font.metadata[encoding]) { + unicode_section = font.metadata[encoding]; + } else { + unicode_section = font.metadata[encoding] = {}; + } + + unicode_section.widths = metrics.widths; + unicode_section.kerning = metrics.kerning; + } + + encodingBlock = encodings[encoding][font.postScriptName]; + + if (encodingBlock) { + if (font.metadata[encoding]) { + unicode_section = font.metadata[encoding]; + } else { + unicode_section = font.metadata[encoding] = {}; + } + + unicode_section.encoding = encodingBlock; + + if (encodingBlock.codePages && encodingBlock.codePages.length) { + font.encoding = encodingBlock.codePages[0]; + } + } + }]); // end of adding event handler + })(jsPDF.API); + + /** + * @license + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * @name ttfsupport + * @module + */ + (function (jsPDF, global) { + + jsPDF.API.events.push(["addFont", function (data) { + var font = data.font; + var instance = data.instance; + + if (typeof instance !== "undefined" && instance.existsFileInVFS(font.postScriptName)) { + var file = instance.getFileFromVFS(font.postScriptName); + + if (typeof file !== "string") { + throw new Error("Font is not stored as string-data in vFS, import fonts or remove declaration doc.addFont('" + font.postScriptName + "')."); + } + + font.metadata = jsPDF.API.TTFFont.open(font.postScriptName, font.fontName, file, font.encoding); + font.metadata.Unicode = font.metadata.Unicode || { + encoding: {}, + kerning: {}, + widths: [] + }; + font.metadata.glyIdsUsed = [0]; + } else if (font.isStandardFont === false) { + throw new Error("Font does not exist in vFS, import fonts or remove declaration doc.addFont('" + font.postScriptName + "')."); + } + }]); // end of adding event handler + })(jsPDF, typeof self !== "undefined" && self || typeof global !== "undefined" && global || typeof window !== "undefined" && window || Function("return this")()); + + /** @license + * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com + * + * + * ==================================================================== + */ + + /** + * jsPDF SVG plugin + * + * @name svg + * @module + */ + (function (jsPDFAPI) { + /** + * Parses SVG XML and converts only some of the SVG elements into + * PDF elements. + * + * Supports: + * paths + * + * @name addSvg + * @public + * @function + * @param {string} SVG-Data as Text + * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {number} width of SVG (in units declared at inception of PDF document) + * @param {number} height of SVG (in units declared at inception of PDF document) + * @returns {Object} jsPDF-instance + */ + + jsPDFAPI.addSvg = function (svgtext, x, y, w, h) { + // 'this' is _jsPDF object returned when jsPDF is inited (new jsPDF()) + var undef; + + if (x === undef || y === undef) { + throw new Error("addSVG needs values for 'x' and 'y'"); + } + + function InjectCSS(cssbody, document) { + var styletag = document.createElement("style"); + styletag.type = "text/css"; + + if (styletag.styleSheet) { + // ie + styletag.styleSheet.cssText = cssbody; + } else { + // others + styletag.appendChild(document.createTextNode(cssbody)); + } + + document.getElementsByTagName("head")[0].appendChild(styletag); + } + + function createWorkerNode(document) { + var frameID = "childframe", + // Date.now().toString() + '_' + (Math.random() * 100).toString() + frame = document.createElement("iframe"); + InjectCSS(".jsPDF_sillysvg_iframe {display:none;position:absolute;}", document); + frame.name = frameID; + frame.setAttribute("width", 0); + frame.setAttribute("height", 0); + frame.setAttribute("frameborder", "0"); + frame.setAttribute("scrolling", "no"); + frame.setAttribute("seamless", "seamless"); + frame.setAttribute("class", "jsPDF_sillysvg_iframe"); + document.body.appendChild(frame); + return frame; + } + + function attachSVGToWorkerNode(svgtext, frame) { + var framedoc = (frame.contentWindow || frame.contentDocument).document; + framedoc.write(svgtext); + framedoc.close(); + return framedoc.getElementsByTagName("svg")[0]; + } + + function convertPathToPDFLinesArgs(path) { + // - starting coordinate pair + // - array of arrays of vector shifts (2-len for line, 6 len for bezier) + // - scale array [horizontal, vertical] ratios + // - style (stroke, fill, both) + + var x = parseFloat(path[1]), + y = parseFloat(path[2]), + vectors = [], + position = 3, + len = path.length; + + while (position < len) { + if (path[position] === "c") { + vectors.push([parseFloat(path[position + 1]), parseFloat(path[position + 2]), parseFloat(path[position + 3]), parseFloat(path[position + 4]), parseFloat(path[position + 5]), parseFloat(path[position + 6])]); + position += 7; + } else if (path[position] === "l") { + vectors.push([parseFloat(path[position + 1]), parseFloat(path[position + 2])]); + position += 3; + } else { + position += 1; + } + } + + return [x, y, vectors]; + } + + var workernode = createWorkerNode(document), + svgnode = attachSVGToWorkerNode(svgtext, workernode), + scale = [1, 1], + svgw = parseFloat(svgnode.getAttribute("width")), + svgh = parseFloat(svgnode.getAttribute("height")); + + if (svgw && svgh) { + // setting both w and h makes image stretch to size. + // this may distort the image, but fits your demanded size + if (w && h) { + scale = [w / svgw, h / svgh]; + } // if only one is set, that value is set as max and SVG + // is scaled proportionately. + else if (w) { + scale = [w / svgw, w / svgw]; + } else if (h) { + scale = [h / svgh, h / svgh]; + } + } + + var i, + l, + tmp, + linesargs, + items = svgnode.childNodes; + + for (i = 0, l = items.length; i < l; i++) { + tmp = items[i]; + + if (tmp.tagName && tmp.tagName.toUpperCase() === "PATH") { + linesargs = convertPathToPDFLinesArgs(tmp.getAttribute("d").split(" ")); // path start x coordinate + + linesargs[0] = linesargs[0] * scale[0] + x; // where x is upper left X of image + // path start y coordinate + + linesargs[1] = linesargs[1] * scale[1] + y; // where y is upper left Y of image + // the rest of lines are vectors. these will adjust with scale value auto. + + this.lines.call(this, linesargs[2], // lines + linesargs[0], // starting x + linesargs[1], // starting y + scale); + } + } // clean up + // workernode.parentNode.removeChild(workernode) + + + return this; + }; //fallback + + + jsPDFAPI.addSVG = jsPDFAPI.addSvg; + /** + * Parses SVG XML and saves it as image into the PDF. + * + * Depends on canvas-element and canvg + * + * @name addSvgAsImage + * @public + * @function + * @param {string} SVG-Data as Text + * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {number} width of SVG-Image (in units declared at inception of PDF document) + * @param {number} height of SVG-Image (in units declared at inception of PDF document) + * @param {string} alias of SVG-Image (if used multiple times) + * @param {string} compression of the generated JPEG, can have the values 'NONE', 'FAST', 'MEDIUM' and 'SLOW' + * @param {number} rotation of the image in degrees (0-359) + * + * @returns jsPDF jsPDF-instance + */ + + jsPDFAPI.addSvgAsImage = function (svg, x, y, w, h, alias, compression, rotation) { + if (isNaN(x) || isNaN(y)) { + console.error("jsPDF.addSvgAsImage: Invalid coordinates", arguments); + throw new Error("Invalid coordinates passed to jsPDF.addSvgAsImage"); + } + + if (isNaN(w) || isNaN(h)) { + console.error("jsPDF.addSvgAsImage: Invalid measurements", arguments); + throw new Error("Invalid measurements (width and/or height) passed to jsPDF.addSvgAsImage"); + } + + var canvas = document.createElement("canvas"); + canvas.width = w; + canvas.height = h; + var ctx = canvas.getContext("2d"); + ctx.fillStyle = "#fff"; /// set white fill style + + ctx.fillRect(0, 0, canvas.width, canvas.height); //load a svg snippet in the canvas with id = 'drawingArea' + + canvg(canvas, svg, { + ignoreMouse: true, + ignoreAnimation: true, + ignoreDimensions: true, + ignoreClear: true + }); + this.addImage(canvas.toDataURL("image/jpeg", 1.0), x, y, w, h, compression, rotation); + return this; + }; + })(jsPDF.API); + + /** + * @license + * ==================================================================== + * Copyright (c) 2013 Eduardo Menezes de Morais, eduardo.morais@usp.br + * + * + * ==================================================================== + */ + + /** + * jsPDF total_pages plugin + * @name total_pages + * @module + */ + (function (jsPDFAPI) { + /** + * @name putTotalPages + * @function + * @param {string} pageExpression Regular Expression + * @returns {jsPDF} jsPDF-instance + */ + + jsPDFAPI.putTotalPages = function (pageExpression) { + + var replaceExpression = new RegExp(pageExpression, "g"); + + for (var n = 1; n <= this.internal.getNumberOfPages(); n++) { + for (var i = 0; i < this.internal.pages[n].length; i++) { + this.internal.pages[n][i] = this.internal.pages[n][i].replace(replaceExpression, this.internal.getNumberOfPages()); + } + } + + return this; + }; + })(jsPDF.API); + + /** + * jsPDF viewerPreferences Plugin + * @author Aras Abbasi (github.com/arasabbasi) + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * Adds the ability to set ViewerPreferences and by thus + * controlling the way the document is to be presented on the + * screen or in print. + * @name viewerpreferences + * @module + */ + (function (jsPDFAPI) { + /** + * Set the ViewerPreferences of the generated PDF + * + * @name viewerPreferences + * @function + * @public + * @param {Object} options Array with the ViewerPreferences
    + * Example: doc.viewerPreferences({"FitWindow":true});
    + *
    + * You can set following preferences:
    + *
    + * HideToolbar (boolean)
    + * Default value: false
    + *
    + * HideMenubar (boolean)
    + * Default value: false.
    + *
    + * HideWindowUI (boolean)
    + * Default value: false.
    + *
    + * FitWindow (boolean)
    + * Default value: false.
    + *
    + * CenterWindow (boolean)
    + * Default value: false
    + *
    + * DisplayDocTitle (boolean)
    + * Default value: false.
    + *
    + * NonFullScreenPageMode (string)
    + * Possible values: UseNone, UseOutlines, UseThumbs, UseOC
    + * Default value: UseNone
    + *
    + * Direction (string)
    + * Possible values: L2R, R2L
    + * Default value: L2R.
    + *
    + * ViewArea (string)
    + * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox
    + * Default value: CropBox.
    + *
    + * ViewClip (string)
    + * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox
    + * Default value: CropBox
    + *
    + * PrintArea (string)
    + * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox
    + * Default value: CropBox
    + *
    + * PrintClip (string)
    + * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox
    + * Default value: CropBox.
    + *
    + * PrintScaling (string)
    + * Possible values: AppDefault, None
    + * Default value: AppDefault.
    + *
    + * Duplex (string)
    + * Possible values: Simplex, DuplexFlipLongEdge, DuplexFlipShortEdge + * Default value: none
    + *
    + * PickTrayByPDFSize (boolean)
    + * Default value: false
    + *
    + * PrintPageRange (Array)
    + * Example: [[1,5], [7,9]]
    + * Default value: as defined by PDF viewer application
    + *
    + * NumCopies (Number)
    + * Possible values: 1, 2, 3, 4, 5
    + * Default value: 1
    + *
    + * For more information see the PDF Reference, sixth edition on Page 577 + * @param {boolean} doReset True to reset the settings + * @function + * @returns jsPDF jsPDF-instance + * @example + * var doc = new jsPDF() + * doc.text('This is a test', 10, 10) + * doc.viewerPreferences({'FitWindow': true}, true) + * doc.save("viewerPreferences.pdf") + * + * // Example printing 10 copies, using cropbox, and hiding UI. + * doc.viewerPreferences({ + * 'HideWindowUI': true, + * 'PrintArea': 'CropBox', + * 'NumCopies': 10 + * }) + */ + + jsPDFAPI.viewerPreferences = function (options, doReset) { + options = options || {}; + doReset = doReset || false; + var configuration; + var configurationTemplate = { + HideToolbar: { + defaultValue: false, + value: false, + type: "boolean", + explicitSet: false, + valueSet: [true, false], + pdfVersion: 1.3 + }, + HideMenubar: { + defaultValue: false, + value: false, + type: "boolean", + explicitSet: false, + valueSet: [true, false], + pdfVersion: 1.3 + }, + HideWindowUI: { + defaultValue: false, + value: false, + type: "boolean", + explicitSet: false, + valueSet: [true, false], + pdfVersion: 1.3 + }, + FitWindow: { + defaultValue: false, + value: false, + type: "boolean", + explicitSet: false, + valueSet: [true, false], + pdfVersion: 1.3 + }, + CenterWindow: { + defaultValue: false, + value: false, + type: "boolean", + explicitSet: false, + valueSet: [true, false], + pdfVersion: 1.3 + }, + DisplayDocTitle: { + defaultValue: false, + value: false, + type: "boolean", + explicitSet: false, + valueSet: [true, false], + pdfVersion: 1.4 + }, + NonFullScreenPageMode: { + defaultValue: "UseNone", + value: "UseNone", + type: "name", + explicitSet: false, + valueSet: ["UseNone", "UseOutlines", "UseThumbs", "UseOC"], + pdfVersion: 1.3 + }, + Direction: { + defaultValue: "L2R", + value: "L2R", + type: "name", + explicitSet: false, + valueSet: ["L2R", "R2L"], + pdfVersion: 1.3 + }, + ViewArea: { + defaultValue: "CropBox", + value: "CropBox", + type: "name", + explicitSet: false, + valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"], + pdfVersion: 1.4 + }, + ViewClip: { + defaultValue: "CropBox", + value: "CropBox", + type: "name", + explicitSet: false, + valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"], + pdfVersion: 1.4 + }, + PrintArea: { + defaultValue: "CropBox", + value: "CropBox", + type: "name", + explicitSet: false, + valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"], + pdfVersion: 1.4 + }, + PrintClip: { + defaultValue: "CropBox", + value: "CropBox", + type: "name", + explicitSet: false, + valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"], + pdfVersion: 1.4 + }, + PrintScaling: { + defaultValue: "AppDefault", + value: "AppDefault", + type: "name", + explicitSet: false, + valueSet: ["AppDefault", "None"], + pdfVersion: 1.6 + }, + Duplex: { + defaultValue: "", + value: "none", + type: "name", + explicitSet: false, + valueSet: ["Simplex", "DuplexFlipShortEdge", "DuplexFlipLongEdge", "none"], + pdfVersion: 1.7 + }, + PickTrayByPDFSize: { + defaultValue: false, + value: false, + type: "boolean", + explicitSet: false, + valueSet: [true, false], + pdfVersion: 1.7 + }, + PrintPageRange: { + defaultValue: "", + value: "", + type: "array", + explicitSet: false, + valueSet: null, + pdfVersion: 1.7 + }, + NumCopies: { + defaultValue: 1, + value: 1, + type: "integer", + explicitSet: false, + valueSet: null, + pdfVersion: 1.7 + } + }; + var configurationKeys = Object.keys(configurationTemplate); + var rangeArray = []; + var i = 0; + var j = 0; + var k = 0; + var isValid = true; + var method; + var value; + + function arrayContainsElement(array, element) { + var iterator; + var result = false; + + for (iterator = 0; iterator < array.length; iterator += 1) { + if (array[iterator] === element) { + result = true; + } + } + + return result; + } + + if (this.internal.viewerpreferences === undefined) { + this.internal.viewerpreferences = {}; + this.internal.viewerpreferences.configuration = JSON.parse(JSON.stringify(configurationTemplate)); + this.internal.viewerpreferences.isSubscribed = false; + } + + configuration = this.internal.viewerpreferences.configuration; + + if (options === "reset" || doReset === true) { + var len = configurationKeys.length; + + for (k = 0; k < len; k += 1) { + configuration[configurationKeys[k]].value = configuration[configurationKeys[k]].defaultValue; + configuration[configurationKeys[k]].explicitSet = false; + } + } + + if (_typeof(options) === "object") { + for (method in options) { + value = options[method]; + + if (arrayContainsElement(configurationKeys, method) && value !== undefined) { + if (configuration[method].type === "boolean" && typeof value === "boolean") { + configuration[method].value = value; + } else if (configuration[method].type === "name" && arrayContainsElement(configuration[method].valueSet, value)) { + configuration[method].value = value; + } else if (configuration[method].type === "integer" && Number.isInteger(value)) { + configuration[method].value = value; + } else if (configuration[method].type === "array") { + for (i = 0; i < value.length; i += 1) { + isValid = true; + + if (value[i].length === 1 && typeof value[i][0] === "number") { + rangeArray.push(String(value[i])); + } else if (value[i].length > 1) { + for (j = 0; j < value[i].length; j += 1) { + if (typeof value[i][j] !== "number") { + isValid = false; + } + } + + if (isValid === true) { + rangeArray.push(String(value[i].join("-"))); + } + } + } + + configuration[method].value = String(rangeArray); + } else { + configuration[method].value = configuration[method].defaultValue; + } + + configuration[method].explicitSet = true; + } + } + } + + if (this.internal.viewerpreferences.isSubscribed === false) { + this.internal.events.subscribe("putCatalog", function () { + var pdfDict = []; + var vPref; + + for (vPref in configuration) { + if (configuration[vPref].explicitSet === true) { + if (configuration[vPref].type === "name") { + pdfDict.push("/" + vPref + " /" + configuration[vPref].value); + } else { + pdfDict.push("/" + vPref + " " + configuration[vPref].value); + } + } + } + + if (pdfDict.length !== 0) { + this.internal.write("/ViewerPreferences\n<<\n" + pdfDict.join("\n") + "\n>>"); + } + }); + this.internal.viewerpreferences.isSubscribed = true; + } + + this.internal.viewerpreferences.configuration = configuration; + return this; + }; + })(jsPDF.API); + + /** ==================================================================== + * jsPDF XMP metadata plugin + * Copyright (c) 2016 Jussi Utunen, u-jussi@suomi24.fi + * + * + * ==================================================================== + */ + + /*global jsPDF */ + + /** + * @name xmp_metadata + * @module + */ + (function (jsPDFAPI) { + + var xmpmetadata = ""; + var xmpnamespaceuri = ""; + var metadata_object_number = ""; + /** + * Adds XMP formatted metadata to PDF + * + * @name addMetadata + * @function + * @param {String} metadata The actual metadata to be added. The metadata shall be stored as XMP simple value. Note that if the metadata string contains XML markup characters "<", ">" or "&", those characters should be written using XML entities. + * @param {String} namespaceuri Sets the namespace URI for the metadata. Last character should be slash or hash. + * @returns {jsPDF} jsPDF-instance + */ + + jsPDFAPI.addMetadata = function (metadata, namespaceuri) { + xmpnamespaceuri = namespaceuri || "http://jspdf.default.namespaceuri/"; //The namespace URI for an XMP name shall not be empty + + xmpmetadata = metadata; + this.internal.events.subscribe("postPutResources", function () { + if (!xmpmetadata) { + metadata_object_number = ""; + } else { + var xmpmeta_beginning = ''; + var rdf_beginning = ''; + var rdf_ending = ""; + var xmpmeta_ending = ""; + var utf8_xmpmeta_beginning = unescape(encodeURIComponent(xmpmeta_beginning)); + var utf8_rdf_beginning = unescape(encodeURIComponent(rdf_beginning)); + var utf8_metadata = unescape(encodeURIComponent(xmpmetadata)); + var utf8_rdf_ending = unescape(encodeURIComponent(rdf_ending)); + var utf8_xmpmeta_ending = unescape(encodeURIComponent(xmpmeta_ending)); + var total_len = utf8_rdf_beginning.length + utf8_metadata.length + utf8_rdf_ending.length + utf8_xmpmeta_beginning.length + utf8_xmpmeta_ending.length; + metadata_object_number = this.internal.newObject(); + this.internal.write("<< /Type /Metadata /Subtype /XML /Length " + total_len + " >>"); + this.internal.write("stream"); + this.internal.write(utf8_xmpmeta_beginning + utf8_rdf_beginning + utf8_metadata + utf8_rdf_ending + utf8_xmpmeta_ending); + this.internal.write("endstream"); + this.internal.write("endobj"); + } + }); + this.internal.events.subscribe("putCatalog", function () { + if (metadata_object_number) { + this.internal.write("/Metadata " + metadata_object_number + " 0 R"); + } + }); + return this; + }; + })(jsPDF.API); + + /** + * @name utf8 + * @module + */ + (function (jsPDF, global) { + + var jsPDFAPI = jsPDF.API; + /**************************************************/ + + /* function : toHex */ + + /* comment : Replace str with a hex string. */ + + /**************************************************/ + + function toHex(str) { + var hex = ""; + + for (var i = 0; i < str.length; i++) { + hex += "" + str.charCodeAt(i).toString(16); + } + + return hex; + } + /***************************************************************************************************/ + + /* function : pdfEscape16 */ + + /* comment : The character id of a 2-byte string is converted to a hexadecimal number by obtaining */ + + /* the corresponding glyph id and width, and then adding padding to the string. */ + + /***************************************************************************************************/ + + + var pdfEscape16 = jsPDFAPI.pdfEscape16 = function (text, font) { + var widths = font.metadata.Unicode.widths; + var padz = ["", "0", "00", "000", "0000"]; + var ar = [""]; + + for (var i = 0, l = text.length, t; i < l; ++i) { + t = font.metadata.characterToGlyph(text.charCodeAt(i)); + font.metadata.glyIdsUsed.push(t); + font.metadata.toUnicode[t] = text.charCodeAt(i); + + if (widths.indexOf(t) == -1) { + widths.push(t); + widths.push([parseInt(font.metadata.widthOfGlyph(t), 10)]); + } + + if (t == "0") { + //Spaces are not allowed in cmap. + return ar.join(""); + } else { + t = t.toString(16); + ar.push(padz[4 - t.length], t); + } + } + + return ar.join(""); + }; + + var toUnicodeCmap = function toUnicodeCmap(map) { + var code, codes, range, unicode, unicodeMap, _i, _len; + + unicodeMap = "/CIDInit /ProcSet findresource begin\n12 dict begin\nbegincmap\n/CIDSystemInfo <<\n /Registry (Adobe)\n /Ordering (UCS)\n /Supplement 0\n>> def\n/CMapName /Adobe-Identity-UCS def\n/CMapType 2 def\n1 begincodespacerange\n<0000>\nendcodespacerange"; + codes = Object.keys(map).sort(function (a, b) { + return a - b; + }); + range = []; + + for (_i = 0, _len = codes.length; _i < _len; _i++) { + code = codes[_i]; + + if (range.length >= 100) { + unicodeMap += "\n" + range.length + " beginbfchar\n" + range.join("\n") + "\nendbfchar"; + range = []; + } + + unicode = ("0000" + map[code].toString(16)).slice(-4); + code = ("0000" + (+code).toString(16)).slice(-4); + range.push("<" + code + "><" + unicode + ">"); + } + + if (range.length) { + unicodeMap += "\n" + range.length + " beginbfchar\n" + range.join("\n") + "\nendbfchar\n"; + } + + unicodeMap += "endcmap\nCMapName currentdict /CMap defineresource pop\nend\nend"; + return unicodeMap; + }; + + var identityHFunction = function identityHFunction(font, out, newObject, putStream) { + if (font.metadata instanceof jsPDF.API.TTFFont && font.encoding === "Identity-H") { + //Tag with Identity-H + var widths = font.metadata.Unicode.widths; + var data = font.metadata.subset.encode(font.metadata.glyIdsUsed, 1); + var pdfOutput = data; + var pdfOutput2 = ""; + + for (var i = 0; i < pdfOutput.length; i++) { + pdfOutput2 += String.fromCharCode(pdfOutput[i]); + } + + var fontTable = newObject(); + out("<<"); + out("/Length " + pdfOutput2.length); + out("/Length1 " + pdfOutput2.length); + out(">>"); + putStream(pdfOutput2); + out("endobj"); + var cmap = newObject(); + var cmapData = toUnicodeCmap(font.metadata.toUnicode); + out("<<"); + out("/Length " + cmapData.length); + out("/Length1 " + cmapData.length); + out(">>"); + putStream(cmapData); + out("endobj"); + var fontDescriptor = newObject(); + out("<<"); + out("/Type /FontDescriptor"); + out("/FontName /" + font.fontName); + out("/FontFile2 " + fontTable + " 0 R"); + out("/FontBBox " + jsPDF.API.PDFObject.convert(font.metadata.bbox)); + out("/Flags " + font.metadata.flags); + out("/StemV " + font.metadata.stemV); + out("/ItalicAngle " + font.metadata.italicAngle); + out("/Ascent " + font.metadata.ascender); + out("/Descent " + font.metadata.decender); + out("/CapHeight " + font.metadata.capHeight); + out(">>"); + out("endobj"); + var DescendantFont = newObject(); + out("<<"); + out("/Type /Font"); + out("/BaseFont /" + font.fontName); + out("/FontDescriptor " + fontDescriptor + " 0 R"); + out("/W " + jsPDF.API.PDFObject.convert(widths)); + out("/CIDToGIDMap /Identity"); + out("/DW 1000"); + out("/Subtype /CIDFontType2"); + out("/CIDSystemInfo"); + out("<<"); + out("/Supplement 0"); + out("/Registry (Adobe)"); + out("/Ordering (" + font.encoding + ")"); + out(">>"); + out(">>"); + out("endobj"); + font.objectNumber = newObject(); + out("<<"); + out("/Type /Font"); + out("/Subtype /Type0"); + out("/ToUnicode " + cmap + " 0 R"); + out("/BaseFont /" + font.fontName); + out("/Encoding /" + font.encoding); + out("/DescendantFonts [" + DescendantFont + " 0 R]"); + out(">>"); + out("endobj"); + font.isAlreadyPutted = true; + } + }; + + jsPDFAPI.events.push(["putFont", function (args) { + identityHFunction(args.font, args.out, args.newObject, args.putStream); + }]); + + var winAnsiEncodingFunction = function winAnsiEncodingFunction(font, out, newObject, putStream) { + if (font.metadata instanceof jsPDF.API.TTFFont && font.encoding === "WinAnsiEncoding") { + //Tag with WinAnsi encoding + var widths = font.metadata.Unicode.widths; + var data = font.metadata.rawData; + var pdfOutput = data; + var pdfOutput2 = ""; + + for (var i = 0; i < pdfOutput.length; i++) { + pdfOutput2 += String.fromCharCode(pdfOutput[i]); + } + + var fontTable = newObject(); + putStream({ + data: pdfOutput2, + addLength1: true + }); + out("endobj"); + var cmap = newObject(); + var cmapData = toUnicodeCmap(font.metadata.toUnicode); + putStream({ + data: cmapData, + addLength1: true + }); + out("endobj"); + var fontDescriptor = newObject(); + out("<<"); + out("/Descent " + font.metadata.decender); + out("/CapHeight " + font.metadata.capHeight); + out("/StemV " + font.metadata.stemV); + out("/Type /FontDescriptor"); + out("/FontFile2 " + fontTable + " 0 R"); + out("/Flags 96"); + out("/FontBBox " + jsPDF.API.PDFObject.convert(font.metadata.bbox)); + out("/FontName /" + font.fontName); + out("/ItalicAngle " + font.metadata.italicAngle); + out("/Ascent " + font.metadata.ascender); + out(">>"); + out("endobj"); + font.objectNumber = newObject(); + + for (var i = 0; i < font.metadata.hmtx.widths.length; i++) { + font.metadata.hmtx.widths[i] = parseInt(font.metadata.hmtx.widths[i] * (1000 / font.metadata.head.unitsPerEm)); //Change the width of Em units to Point units. + } + + out("<>"); + out("endobj"); + font.isAlreadyPutted = true; + } + }; + + jsPDFAPI.events.push(["putFont", function (args) { + winAnsiEncodingFunction(args.font, args.out, args.newObject, args.putStream); + }]); + + var utf8TextFunction = function utf8TextFunction(args) { + var text = args.text || ""; + var x = args.x; + var y = args.y; + var options = args.options || {}; + var mutex = args.mutex || {}; + var pdfEscape = mutex.pdfEscape; + var activeFontKey = mutex.activeFontKey; + var fonts = mutex.fonts; + var key, + fontSize = mutex.activeFontSize; + var str = "", + s = 0, + cmapConfirm; + var strText = ""; + var key = activeFontKey; + var encoding = fonts[key].encoding; + + if (fonts[key].encoding !== "Identity-H") { + return { + text: text, + x: x, + y: y, + options: options, + mutex: mutex + }; + } + strText = text; + key = activeFontKey; + + if (Object.prototype.toString.call(text) === "[object Array]") { + strText = text[0]; + } + + for (s = 0; s < strText.length; s += 1) { + if (fonts[key].metadata.hasOwnProperty("cmap")) { + cmapConfirm = fonts[key].metadata.cmap.unicode.codeMap[strText[s].charCodeAt(0)]; + /* + if (Object.prototype.toString.call(text) === '[object Array]') { + var i = 0; + // for (i = 0; i < text.length; i += 1) { + if (Object.prototype.toString.call(text[s]) === '[object Array]') { + cmapConfirm = fonts[key].metadata.cmap.unicode.codeMap[strText[s][0].charCodeAt(0)]; //Make sure the cmap has the corresponding glyph id + } else { + + } + //} + + } else { + cmapConfirm = fonts[key].metadata.cmap.unicode.codeMap[strText[s].charCodeAt(0)]; //Make sure the cmap has the corresponding glyph id + }*/ + } + + if (!cmapConfirm) { + if (strText[s].charCodeAt(0) < 256 && fonts[key].metadata.hasOwnProperty("Unicode")) { + str += strText[s]; + } else { + str += ""; + } + } else { + str += strText[s]; + } + } + + var result = ""; + + if (parseInt(key.slice(1)) < 14 || encoding === "WinAnsiEncoding") { + //For the default 13 font + result = toHex(pdfEscape(str, key)); + } else if (encoding === "Identity-H") { + result = pdfEscape16(str, fonts[key]); + } + + mutex.isHex = true; + return { + text: result, + x: x, + y: y, + options: options, + mutex: mutex + }; + }; + + var utf8EscapeFunction = function utf8EscapeFunction(parms) { + var text = parms.text || "", + x = parms.x, + y = parms.y, + options = parms.options, + mutex = parms.mutex; + var lang = options.lang; + var tmpText = []; + var args = { + text: text, + x: x, + y: y, + options: options, + mutex: mutex + }; + + if (Object.prototype.toString.call(text) === "[object Array]") { + var i = 0; + + for (i = 0; i < text.length; i += 1) { + if (Object.prototype.toString.call(text[i]) === "[object Array]") { + if (text[i].length === 3) { + tmpText.push([utf8TextFunction(Object.assign({}, args, { + text: text[i][0] + })).text, text[i][1], text[i][2]]); + } else { + tmpText.push(utf8TextFunction(Object.assign({}, args, { + text: text[i] + })).text); + } + } else { + tmpText.push(utf8TextFunction(Object.assign({}, args, { + text: text[i] + })).text); + } + } + + parms.text = tmpText; + } else { + parms.text = utf8TextFunction(Object.assign({}, args, { + text: text + })).text; + } + }; + + jsPDFAPI.events.push(["postProcessText", utf8EscapeFunction]); + })(jsPDF, typeof self !== "undefined" && self || typeof global !== "undefined" && global || typeof window !== "undefined" && window || Function("return this")()); + + /** + * jsPDF virtual FileSystem functionality + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + + /** + * Use the vFS to handle files + * + * @name vFS + * @module + */ + (function (jsPDFAPI) { + + var vFS = {}; + /** + * Check if the file exists in the vFS + * + * @name existsFileInVFS + * @function + * @param {string} Possible filename in the vFS. + * @returns {boolean} + * @example + * doc.existsFileInVFS("someFile.txt"); + */ + + jsPDFAPI.existsFileInVFS = function (filename) { + return vFS.hasOwnProperty(filename); + }; + /** + * Add a file to the vFS + * + * @name addFileToVFS + * @function + * @param {string} filename The name of the file which should be added. + * @param {string} filecontent The content of the file. + * @returns {jsPDF} + * @example + * doc.addFileToVFS("someFile.txt", "BADFACE1"); + */ + + + jsPDFAPI.addFileToVFS = function (filename, filecontent) { + vFS[filename] = filecontent; + return this; + }; + /** + * Get the file from the vFS + * + * @name getFileFromVFS + * @function + * @returns {string} The name of the file which gets requested. + * @example + * doc.getFileFromVFS("someFile.txt"); + */ + + + jsPDFAPI.getFileFromVFS = function (filename) { + if (vFS.hasOwnProperty(filename)) { + return vFS[filename]; + } + + return null; + }; + })(jsPDF.API); + + /* Blob.js + * A Blob implementation. + * 2014-07-24 + * + * By Eli Grey, http://eligrey.com + * By Devin Samarin, https://github.com/dsamarin + * License: X11/MIT + * See https://github.com/eligrey/Blob.js/blob/master/LICENSE.md + */ + + /*global self, unescape */ + + /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, + plusplus: true */ + + /*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */ + (function (view) { + + view.URL = view.URL || view.webkitURL; + + if (view.Blob && view.URL) { + try { + new Blob(); + return; + } catch (e) {} + } // Internally we use a BlobBuilder implementation to base Blob off of + // in order to support older browsers that only have BlobBuilder + + + var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || function (view) { + var get_class = function (object) { + return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1]; + }, + FakeBlobBuilder = function BlobBuilder() { + this.data = []; + }, + FakeBlob = function Blob(data, type, encoding) { + this.data = data; + this.size = data.length; + this.type = type; + this.encoding = encoding; + }, + FBB_proto = FakeBlobBuilder.prototype, + FB_proto = FakeBlob.prototype, + FileReaderSync = view.FileReaderSync, + FileException = function (type) { + this.code = this[this.name = type]; + }, + file_ex_codes = ("NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR " + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR").split(" "), + file_ex_code = file_ex_codes.length, + real_URL = view.URL || view.webkitURL || view, + real_create_object_URL = real_URL.createObjectURL, + real_revoke_object_URL = real_URL.revokeObjectURL, + URL = real_URL, + btoa = view.btoa, + atob = view.atob, + ArrayBuffer = view.ArrayBuffer, + Uint8Array = view.Uint8Array, + origin = /^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/; + + FakeBlob.fake = FB_proto.fake = true; + + while (file_ex_code--) { + FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1; + } // Polyfill URL + + + if (!real_URL.createObjectURL) { + URL = view.URL = function (uri) { + var uri_info = document.createElementNS("http://www.w3.org/1999/xhtml", "a"), + uri_origin; + uri_info.href = uri; + + if (!("origin" in uri_info)) { + if (uri_info.protocol.toLowerCase() === "data:") { + uri_info.origin = null; + } else { + uri_origin = uri.match(origin); + uri_info.origin = uri_origin && uri_origin[1]; + } + } + + return uri_info; + }; + } + + URL.createObjectURL = function (blob) { + var type = blob.type, + data_URI_header; + + if (type === null) { + type = "application/octet-stream"; + } + + if (blob instanceof FakeBlob) { + data_URI_header = "data:" + type; + + if (blob.encoding === "base64") { + return data_URI_header + ";base64," + blob.data; + } else if (blob.encoding === "URI") { + return data_URI_header + "," + decodeURIComponent(blob.data); + } + + if (btoa) { + return data_URI_header + ";base64," + btoa(blob.data); + } else { + return data_URI_header + "," + encodeURIComponent(blob.data); + } + } else if (real_create_object_URL) { + return real_create_object_URL.call(real_URL, blob); + } + }; + + URL.revokeObjectURL = function (object_URL) { + if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) { + real_revoke_object_URL.call(real_URL, object_URL); + } + }; + + FBB_proto.append = function (data + /*, endings*/ + ) { + var bb = this.data; // decode data to a binary string + + if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) { + var str = "", + buf = new Uint8Array(data), + i = 0, + buf_len = buf.length; + + for (; i < buf_len; i++) { + str += String.fromCharCode(buf[i]); + } + + bb.push(str); + } else if (get_class(data) === "Blob" || get_class(data) === "File") { + if (FileReaderSync) { + var fr = new FileReaderSync(); + bb.push(fr.readAsBinaryString(data)); + } else { + // async FileReader won't work as BlobBuilder is sync + throw new FileException("NOT_READABLE_ERR"); + } + } else if (data instanceof FakeBlob) { + if (data.encoding === "base64" && atob) { + bb.push(atob(data.data)); + } else if (data.encoding === "URI") { + bb.push(decodeURIComponent(data.data)); + } else if (data.encoding === "raw") { + bb.push(data.data); + } + } else { + if (typeof data !== "string") { + data += ""; // convert unsupported types to strings + } // decode UTF-16 to binary string + + + bb.push(unescape(encodeURIComponent(data))); + } + }; + + FBB_proto.getBlob = function (type) { + if (!arguments.length) { + type = null; + } + + return new FakeBlob(this.data.join(""), type, "raw"); + }; + + FBB_proto.toString = function () { + return "[object BlobBuilder]"; + }; + + FB_proto.slice = function (start, end, type) { + var args = arguments.length; + + if (args < 3) { + type = null; + } + + return new FakeBlob(this.data.slice(start, args > 1 ? end : this.data.length), type, this.encoding); + }; + + FB_proto.toString = function () { + return "[object Blob]"; + }; + + FB_proto.close = function () { + this.size = 0; + delete this.data; + }; + + return FakeBlobBuilder; + }(view); + + view.Blob = function (blobParts, options) { + var type = options ? options.type || "" : ""; + var builder = new BlobBuilder(); + + if (blobParts) { + for (var i = 0, len = blobParts.length; i < len; i++) { + if (Uint8Array && blobParts[i] instanceof Uint8Array) { + builder.append(blobParts[i].buffer); + } else { + builder.append(blobParts[i]); + } + } + } + + var blob = builder.getBlob(type); + + if (!blob.slice && blob.webkitSlice) { + blob.slice = blob.webkitSlice; + } + + return blob; + }; + + var getPrototypeOf = Object.getPrototypeOf || function (object) { + return object.__proto__; + }; + + view.Blob.prototype = getPrototypeOf(new view.Blob()); + })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || window.content || window); + + /* FileSaver.js + * A saveAs() FileSaver implementation. + * 1.3.2 + * 2016-06-16 18:25:19 + * + * By Eli Grey, http://eligrey.com + * License: MIT + * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md + */ + + /*global self */ + + /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */ + + /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ + var saveAs = saveAs || function (view) { + + if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) { + return; + } + + var doc = view.document // only get URL when necessary in case Blob.js hasn't overridden it yet + , + get_URL = function () { + return view.URL || view.webkitURL || view; + }, + save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a"), + can_use_save_link = "download" in save_link, + click = function (node) { + var event = new MouseEvent("click"); + node.dispatchEvent(event); + }, + is_safari = /constructor/i.test(view.HTMLElement) || view.safari, + is_chrome_ios = /CriOS\/[\d]+/.test(navigator.userAgent), + throw_outside = function (ex) { + (view.setImmediate || view.setTimeout)(function () { + throw ex; + }, 0); + }, + force_saveable_type = "application/octet-stream" // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to + , + arbitrary_revoke_timeout = 1000 * 40 // in ms + , + revoke = function (file) { + var revoker = function () { + if (typeof file === "string") { + // file is an object URL + get_URL().revokeObjectURL(file); + } else { + // file is a File + file.remove(); + } + }; + + setTimeout(revoker, arbitrary_revoke_timeout); + }, + dispatch = function (filesaver, event_types, event) { + event_types = [].concat(event_types); + var i = event_types.length; + + while (i--) { + var listener = filesaver["on" + event_types[i]]; + + if (typeof listener === "function") { + try { + listener.call(filesaver, event || filesaver); + } catch (ex) { + throw_outside(ex); + } + } + } + }, + auto_bom = function (blob) { + // prepend BOM for UTF-8 XML and text/* types (including HTML) + // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF + if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) { + return new Blob([String.fromCharCode(0xFEFF), blob], { + type: blob.type + }); + } + + return blob; + }, + FileSaver = function (blob, name, no_auto_bom) { + if (!no_auto_bom) { + blob = auto_bom(blob); + } // First try a.download, then web filesystem, then object URLs + + + var filesaver = this, + type = blob.type, + force = type === force_saveable_type, + object_url, + dispatch_all = function () { + dispatch(filesaver, "writestart progress write writeend".split(" ")); + } // on any filesys errors revert to saving with object URLs + , + fs_error = function () { + if ((is_chrome_ios || force && is_safari) && view.FileReader) { + // Safari doesn't allow downloading of blob urls + var reader = new FileReader(); + + reader.onloadend = function () { + var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;'); + var popup = view.open(url, '_blank'); + if (!popup) view.location.href = url; + url = undefined; // release reference before dispatching + + filesaver.readyState = filesaver.DONE; + dispatch_all(); + }; + + reader.readAsDataURL(blob); + filesaver.readyState = filesaver.INIT; + return; + } // don't create more object URLs than needed + + + if (!object_url) { + object_url = get_URL().createObjectURL(blob); + } + + if (force) { + view.location.href = object_url; + } else { + var opened = view.open(object_url, "_blank"); + + if (!opened) { + // Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html + view.location.href = object_url; + } + } + + filesaver.readyState = filesaver.DONE; + dispatch_all(); + revoke(object_url); + }; + + filesaver.readyState = filesaver.INIT; + + if (can_use_save_link) { + object_url = get_URL().createObjectURL(blob); + setTimeout(function () { + save_link.href = object_url; + save_link.download = name; + click(save_link); + dispatch_all(); + revoke(object_url); + filesaver.readyState = filesaver.DONE; + }); + return; + } + + fs_error(); + }, + FS_proto = FileSaver.prototype, + saveAs = function (blob, name, no_auto_bom) { + return new FileSaver(blob, name || blob.name || "download", no_auto_bom); + }; // IE 10+ (native saveAs) + + + if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) { + return function (blob, name, no_auto_bom) { + name = name || blob.name || "download"; + + if (!no_auto_bom) { + blob = auto_bom(blob); + } + + return navigator.msSaveOrOpenBlob(blob, name); + }; + } + + FS_proto.abort = function () {}; + + FS_proto.readyState = FS_proto.INIT = 0; + FS_proto.WRITING = 1; + FS_proto.DONE = 2; + FS_proto.error = FS_proto.onwritestart = FS_proto.onprogress = FS_proto.onwrite = FS_proto.onabort = FS_proto.onerror = FS_proto.onwriteend = null; + return saveAs; + }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || window.content); // `self` is undefined in Firefox for Android content script context + // while `this` is nsIContentFrameMessageManager + // with an attribute `content` that corresponds to the window + + + if (typeof module !== "undefined" && module.exports) { + module.exports.saveAs = saveAs; + } else if (typeof define !== "undefined" && define !== null && define.amd !== null) { + define("FileSaver.js", function () { + return saveAs; + }); + } + + // (c) Dean McNamee , 2013. + // + // https://github.com/deanm/omggif + // + // + // + // omggif is a JavaScript implementation of a GIF 89a encoder and decoder, + // including animation and compression. It does not rely on any specific + // underlying system, so should run in the browser, Node, or Plask. + function GifWriter(buf, width, height, gopts) { + var p = 0; + var gopts = gopts === undefined ? {} : gopts; + var loop_count = gopts.loop === undefined ? null : gopts.loop; + var global_palette = gopts.palette === undefined ? null : gopts.palette; + if (width <= 0 || height <= 0 || width > 65535 || height > 65535) throw "Width/Height invalid."; + + function check_palette_and_num_colors(palette) { + var num_colors = palette.length; + if (num_colors < 2 || num_colors > 256 || num_colors & num_colors - 1) throw "Invalid code/color length, must be power of 2 and 2 .. 256."; + return num_colors; + } // - Header. + + + buf[p++] = 0x47; + buf[p++] = 0x49; + buf[p++] = 0x46; // GIF + + buf[p++] = 0x38; + buf[p++] = 0x39; + buf[p++] = 0x61; // 89a + // Handling of Global Color Table (palette) and background index. + + var gp_num_colors_pow2 = 0; + var background = 0; + + if (global_palette !== null) { + var gp_num_colors = check_palette_and_num_colors(global_palette); + + while (gp_num_colors >>= 1) ++gp_num_colors_pow2; + + gp_num_colors = 1 << gp_num_colors_pow2; + --gp_num_colors_pow2; + + if (gopts.background !== undefined) { + background = gopts.background; + if (background >= gp_num_colors) throw "Background index out of range."; // The GIF spec states that a background index of 0 should be ignored, so + // this is probably a mistake and you really want to set it to another + // slot in the palette. But actually in the end most browsers, etc end + // up ignoring this almost completely (including for dispose background). + + if (background === 0) throw "Background index explicitly passed as 0."; + } + } // - Logical Screen Descriptor. + // NOTE(deanm): w/h apparently ignored by implementations, but set anyway. + + + buf[p++] = width & 0xff; + buf[p++] = width >> 8 & 0xff; + buf[p++] = height & 0xff; + buf[p++] = height >> 8 & 0xff; // NOTE: Indicates 0-bpp original color resolution (unused?). + + buf[p++] = (global_palette !== null ? 0x80 : 0) | // Global Color Table Flag. + gp_num_colors_pow2; // NOTE: No sort flag (unused?). + + buf[p++] = background; // Background Color Index. + + buf[p++] = 0; // Pixel aspect ratio (unused?). + // - Global Color Table + + if (global_palette !== null) { + for (var i = 0, il = global_palette.length; i < il; ++i) { + var rgb = global_palette[i]; + buf[p++] = rgb >> 16 & 0xff; + buf[p++] = rgb >> 8 & 0xff; + buf[p++] = rgb & 0xff; + } + } + + if (loop_count !== null) { + // Netscape block for looping. + if (loop_count < 0 || loop_count > 65535) throw "Loop count invalid."; // Extension code, label, and length. + + buf[p++] = 0x21; + buf[p++] = 0xff; + buf[p++] = 0x0b; // NETSCAPE2.0 + + buf[p++] = 0x4e; + buf[p++] = 0x45; + buf[p++] = 0x54; + buf[p++] = 0x53; + buf[p++] = 0x43; + buf[p++] = 0x41; + buf[p++] = 0x50; + buf[p++] = 0x45; + buf[p++] = 0x32; + buf[p++] = 0x2e; + buf[p++] = 0x30; // Sub-block + + buf[p++] = 0x03; + buf[p++] = 0x01; + buf[p++] = loop_count & 0xff; + buf[p++] = loop_count >> 8 & 0xff; + buf[p++] = 0x00; // Terminator. + } + + var ended = false; + + this.addFrame = function (x, y, w, h, indexed_pixels, opts) { + if (ended === true) { + --p; + ended = false; + } // Un-end. + + + opts = opts === undefined ? {} : opts; // TODO(deanm): Bounds check x, y. Do they need to be within the virtual + // canvas width/height, I imagine? + + if (x < 0 || y < 0 || x > 65535 || y > 65535) throw "x/y invalid."; + if (w <= 0 || h <= 0 || w > 65535 || h > 65535) throw "Width/Height invalid."; + if (indexed_pixels.length < w * h) throw "Not enough pixels for the frame size."; + var using_local_palette = true; + var palette = opts.palette; + + if (palette === undefined || palette === null) { + using_local_palette = false; + palette = global_palette; + } + + if (palette === undefined || palette === null) throw "Must supply either a local or global palette."; + var num_colors = check_palette_and_num_colors(palette); // Compute the min_code_size (power of 2), destroying num_colors. + + var min_code_size = 0; + + while (num_colors >>= 1) ++min_code_size; + + num_colors = 1 << min_code_size; // Now we can easily get it back. + + var delay = opts.delay === undefined ? 0 : opts.delay; // From the spec: + // 0 - No disposal specified. The decoder is + // not required to take any action. + // 1 - Do not dispose. The graphic is to be left + // in place. + // 2 - Restore to background color. The area used by the + // graphic must be restored to the background color. + // 3 - Restore to previous. The decoder is required to + // restore the area overwritten by the graphic with + // what was there prior to rendering the graphic. + // 4-7 - To be defined. + // NOTE(deanm): Dispose background doesn't really work, apparently most + // browsers ignore the background palette index and clear to transparency. + + var disposal = opts.disposal === undefined ? 0 : opts.disposal; + if (disposal < 0 || disposal > 3) // 4-7 is reserved. + throw "Disposal out of range."; + var use_transparency = false; + var transparent_index = 0; + + if (opts.transparent !== undefined && opts.transparent !== null) { + use_transparency = true; + transparent_index = opts.transparent; + if (transparent_index < 0 || transparent_index >= num_colors) throw "Transparent color index."; + } + + if (disposal !== 0 || use_transparency || delay !== 0) { + // - Graphics Control Extension + buf[p++] = 0x21; + buf[p++] = 0xf9; // Extension / Label. + + buf[p++] = 4; // Byte size. + + buf[p++] = disposal << 2 | (use_transparency === true ? 1 : 0); + buf[p++] = delay & 0xff; + buf[p++] = delay >> 8 & 0xff; + buf[p++] = transparent_index; // Transparent color index. + + buf[p++] = 0; // Block Terminator. + } // - Image Descriptor + + + buf[p++] = 0x2c; // Image Seperator. + + buf[p++] = x & 0xff; + buf[p++] = x >> 8 & 0xff; // Left. + + buf[p++] = y & 0xff; + buf[p++] = y >> 8 & 0xff; // Top. + + buf[p++] = w & 0xff; + buf[p++] = w >> 8 & 0xff; + buf[p++] = h & 0xff; + buf[p++] = h >> 8 & 0xff; // NOTE: No sort flag (unused?). + // TODO(deanm): Support interlace. + + buf[p++] = using_local_palette === true ? 0x80 | min_code_size - 1 : 0; // - Local Color Table + + if (using_local_palette === true) { + for (var i = 0, il = palette.length; i < il; ++i) { + var rgb = palette[i]; + buf[p++] = rgb >> 16 & 0xff; + buf[p++] = rgb >> 8 & 0xff; + buf[p++] = rgb & 0xff; + } + } + + p = GifWriterOutputLZWCodeStream(buf, p, min_code_size < 2 ? 2 : min_code_size, indexed_pixels); + }; + + this.end = function () { + if (ended === false) { + buf[p++] = 0x3b; // Trailer. + + ended = true; + } + + return p; + }; + } // Main compression routine, palette indexes -> LZW code stream. + // |index_stream| must have at least one entry. + + + function GifWriterOutputLZWCodeStream(buf, p, min_code_size, index_stream) { + buf[p++] = min_code_size; + var cur_subblock = p++; // Pointing at the length field. + + var clear_code = 1 << min_code_size; + var code_mask = clear_code - 1; + var eoi_code = clear_code + 1; + var next_code = eoi_code + 1; + var cur_code_size = min_code_size + 1; // Number of bits per code. + + var cur_shift = 0; // We have at most 12-bit codes, so we should have to hold a max of 19 + // bits here (and then we would write out). + + var cur = 0; + + function emit_bytes_to_buffer(bit_block_size) { + while (cur_shift >= bit_block_size) { + buf[p++] = cur & 0xff; + cur >>= 8; + cur_shift -= 8; + + if (p === cur_subblock + 256) { + // Finished a subblock. + buf[cur_subblock] = 255; + cur_subblock = p++; + } + } + } + + function emit_code(c) { + cur |= c << cur_shift; + cur_shift += cur_code_size; + emit_bytes_to_buffer(8); + } // I am not an expert on the topic, and I don't want to write a thesis. + // However, it is good to outline here the basic algorithm and the few data + // structures and optimizations here that make this implementation fast. + // The basic idea behind LZW is to build a table of previously seen runs + // addressed by a short id (herein called output code). All data is + // referenced by a code, which represents one or more values from the + // original input stream. All input bytes can be referenced as the same + // value as an output code. So if you didn't want any compression, you + // could more or less just output the original bytes as codes (there are + // some details to this, but it is the idea). In order to achieve + // compression, values greater then the input range (codes can be up to + // 12-bit while input only 8-bit) represent a sequence of previously seen + // inputs. The decompressor is able to build the same mapping while + // decoding, so there is always a shared common knowledge between the + // encoding and decoder, which is also important for "timing" aspects like + // how to handle variable bit width code encoding. + // + // One obvious but very important consequence of the table system is there + // is always a unique id (at most 12-bits) to map the runs. 'A' might be + // 4, then 'AA' might be 10, 'AAA' 11, 'AAAA' 12, etc. This relationship + // can be used for an effecient lookup strategy for the code mapping. We + // need to know if a run has been seen before, and be able to map that run + // to the output code. Since we start with known unique ids (input bytes), + // and then from those build more unique ids (table entries), we can + // continue this chain (almost like a linked list) to always have small + // integer values that represent the current byte chains in the encoder. + // This means instead of tracking the input bytes (AAAABCD) to know our + // current state, we can track the table entry for AAAABC (it is guaranteed + // to exist by the nature of the algorithm) and the next character D. + // Therefor the tuple of (table_entry, byte) is guaranteed to also be + // unique. This allows us to create a simple lookup key for mapping input + // sequences to codes (table indices) without having to store or search + // any of the code sequences. So if 'AAAA' has a table entry of 12, the + // tuple of ('AAAA', K) for any input byte K will be unique, and can be our + // key. This leads to a integer value at most 20-bits, which can always + // fit in an SMI value and be used as a fast sparse array / object key. + // Output code for the current contents of the index buffer. + + + var ib_code = index_stream[0] & code_mask; // Load first input index. + + var code_table = {}; // Key'd on our 20-bit "tuple". + + emit_code(clear_code); // Spec says first code should be a clear code. + // First index already loaded, process the rest of the stream. + + for (var i = 1, il = index_stream.length; i < il; ++i) { + var k = index_stream[i] & code_mask; + var cur_key = ib_code << 8 | k; // (prev, k) unique tuple. + + var cur_code = code_table[cur_key]; // buffer + k. + // Check if we have to create a new code table entry. + + if (cur_code === undefined) { + // We don't have buffer + k. + // Emit index buffer (without k). + // This is an inline version of emit_code, because this is the core + // writing routine of the compressor (and V8 cannot inline emit_code + // because it is a closure here in a different context). Additionally + // we can call emit_byte_to_buffer less often, because we can have + // 30-bits (from our 31-bit signed SMI), and we know our codes will only + // be 12-bits, so can safely have 18-bits there without overflow. + // emit_code(ib_code); + cur |= ib_code << cur_shift; + cur_shift += cur_code_size; + + while (cur_shift >= 8) { + buf[p++] = cur & 0xff; + cur >>= 8; + cur_shift -= 8; + + if (p === cur_subblock + 256) { + // Finished a subblock. + buf[cur_subblock] = 255; + cur_subblock = p++; + } + } + + if (next_code === 4096) { + // Table full, need a clear. + emit_code(clear_code); + next_code = eoi_code + 1; + cur_code_size = min_code_size + 1; + code_table = {}; + } else { + // Table not full, insert a new entry. + // Increase our variable bit code sizes if necessary. This is a bit + // tricky as it is based on "timing" between the encoding and + // decoder. From the encoders perspective this should happen after + // we've already emitted the index buffer and are about to create the + // first table entry that would overflow our current code bit size. + if (next_code >= 1 << cur_code_size) ++cur_code_size; + code_table[cur_key] = next_code++; // Insert into code table. + } + + ib_code = k; // Index buffer to single input k. + } else { + ib_code = cur_code; // Index buffer to sequence in code table. + } + } + + emit_code(ib_code); // There will still be something in the index buffer. + + emit_code(eoi_code); // End Of Information. + // Flush / finalize the sub-blocks stream to the buffer. + + emit_bytes_to_buffer(1); // Finish the sub-blocks, writing out any unfinished lengths and + // terminating with a sub-block of length 0. If we have already started + // but not yet used a sub-block it can just become the terminator. + + if (cur_subblock + 1 === p) { + // Started but unused. + buf[cur_subblock] = 0; + } else { + // Started and used, write length and additional terminator block. + buf[cur_subblock] = p - cur_subblock - 1; + buf[p++] = 0; + } + + return p; + } + + function GifReader(buf) { + var p = 0; // - Header (GIF87a or GIF89a). + + if (buf[p++] !== 0x47 || buf[p++] !== 0x49 || buf[p++] !== 0x46 || buf[p++] !== 0x38 || (buf[p++] + 1 & 0xfd) !== 0x38 || buf[p++] !== 0x61) { + throw "Invalid GIF 87a/89a header."; + } // - Logical Screen Descriptor. + + + var width = buf[p++] | buf[p++] << 8; + var height = buf[p++] | buf[p++] << 8; + var pf0 = buf[p++]; // . + + var global_palette_flag = pf0 >> 7; + var num_global_colors_pow2 = pf0 & 0x7; + var num_global_colors = 1 << num_global_colors_pow2 + 1; + var background = buf[p++]; + buf[p++]; // Pixel aspect ratio (unused?). + + var global_palette_offset = null; + + if (global_palette_flag) { + global_palette_offset = p; + p += num_global_colors * 3; // Seek past palette. + } + + var no_eof = true; + var frames = []; + var delay = 0; + var transparent_index = null; + var disposal = 0; // 0 - No disposal specified. + + var loop_count = null; + this.width = width; + this.height = height; + + while (no_eof && p < buf.length) { + switch (buf[p++]) { + case 0x21: + // Graphics Control Extension Block + switch (buf[p++]) { + case 0xff: + // Application specific block + // Try if it's a Netscape block (with animation loop counter). + if (buf[p] !== 0x0b || // 21 FF already read, check block size. + // NETSCAPE2.0 + buf[p + 1] == 0x4e && buf[p + 2] == 0x45 && buf[p + 3] == 0x54 && buf[p + 4] == 0x53 && buf[p + 5] == 0x43 && buf[p + 6] == 0x41 && buf[p + 7] == 0x50 && buf[p + 8] == 0x45 && buf[p + 9] == 0x32 && buf[p + 10] == 0x2e && buf[p + 11] == 0x30 && // Sub-block + buf[p + 12] == 0x03 && buf[p + 13] == 0x01 && buf[p + 16] == 0) { + p += 14; + loop_count = buf[p++] | buf[p++] << 8; + p++; // Skip terminator. + } else { + // We don't know what it is, just try to get past it. + p += 12; + + while (true) { + // Seek through subblocks. + var block_size = buf[p++]; + if (block_size === 0) break; + p += block_size; + } + } + + break; + + case 0xf9: + // Graphics Control Extension + if (buf[p++] !== 0x4 || buf[p + 4] !== 0) throw "Invalid graphics extension block."; + var pf1 = buf[p++]; + delay = buf[p++] | buf[p++] << 8; + transparent_index = buf[p++]; + if ((pf1 & 1) === 0) transparent_index = null; + disposal = pf1 >> 2 & 0x7; + p++; // Skip terminator. + + break; + + case 0xfe: + // Comment Extension. + while (true) { + // Seek through subblocks. + var block_size = buf[p++]; + if (block_size === 0) break; // console.log(buf.slice(p, p+block_size).toString('ascii')); + + p += block_size; + } + + break; + + default: + throw "Unknown graphic control label: 0x" + buf[p - 1].toString(16); + } + + break; + + case 0x2c: + // Image Descriptor. + var x = buf[p++] | buf[p++] << 8; + var y = buf[p++] | buf[p++] << 8; + var w = buf[p++] | buf[p++] << 8; + var h = buf[p++] | buf[p++] << 8; + var pf2 = buf[p++]; + var local_palette_flag = pf2 >> 7; + var interlace_flag = pf2 >> 6 & 1; + var num_local_colors_pow2 = pf2 & 0x7; + var num_local_colors = 1 << num_local_colors_pow2 + 1; + var palette_offset = global_palette_offset; + var has_local_palette = false; + + if (local_palette_flag) { + var has_local_palette = true; + palette_offset = p; // Override with local palette. + + p += num_local_colors * 3; // Seek past palette. + } + + var data_offset = p; + p++; // codesize + + while (true) { + var block_size = buf[p++]; + if (block_size === 0) break; + p += block_size; + } + + frames.push({ + x: x, + y: y, + width: w, + height: h, + has_local_palette: has_local_palette, + palette_offset: palette_offset, + data_offset: data_offset, + data_length: p - data_offset, + transparent_index: transparent_index, + interlaced: !!interlace_flag, + delay: delay, + disposal: disposal + }); + break; + + case 0x3b: + // Trailer Marker (end of file). + no_eof = false; + break; + + default: + throw "Unknown gif block: 0x" + buf[p - 1].toString(16); + break; + } + } + + this.numFrames = function () { + return frames.length; + }; + + this.loopCount = function () { + return loop_count; + }; + + this.frameInfo = function (frame_num) { + if (frame_num < 0 || frame_num >= frames.length) throw "Frame index out of range."; + return frames[frame_num]; + }; + + this.decodeAndBlitFrameBGRA = function (frame_num, pixels) { + var frame = this.frameInfo(frame_num); + var num_pixels = frame.width * frame.height; + var index_stream = new Uint8Array(num_pixels); // At most 8-bit indices. + + GifReaderLZWOutputIndexStream(buf, frame.data_offset, index_stream, num_pixels); + var palette_offset = frame.palette_offset; // NOTE(deanm): It seems to be much faster to compare index to 256 than + // to === null. Not sure why, but CompareStub_EQ_STRICT shows up high in + // the profile, not sure if it's related to using a Uint8Array. + + var trans = frame.transparent_index; + if (trans === null) trans = 256; // We are possibly just blitting to a portion of the entire frame. + // That is a subrect within the framerect, so the additional pixels + // must be skipped over after we finished a scanline. + + var framewidth = frame.width; + var framestride = width - framewidth; + var xleft = framewidth; // Number of subrect pixels left in scanline. + // Output indicies of the top left and bottom right corners of the subrect. + + var opbeg = (frame.y * width + frame.x) * 4; + var opend = ((frame.y + frame.height) * width + frame.x) * 4; + var op = opbeg; + var scanstride = framestride * 4; // Use scanstride to skip past the rows when interlacing. This is skipping + // 7 rows for the first two passes, then 3 then 1. + + if (frame.interlaced === true) { + scanstride += (framewidth + framestride) * 4 * 7; // Pass 1. + } + + var interlaceskip = 8; // Tracking the row interval in the current pass. + + for (var i = 0, il = index_stream.length; i < il; ++i) { + var index = index_stream[i]; + + if (xleft === 0) { + // Beginning of new scan line + op += scanstride; + xleft = framewidth; + + if (op >= opend) { + // Catch the wrap to switch passes when interlacing. + scanstride = framestride + (framewidth + framestride) * 4 * (interlaceskip - 1); // interlaceskip / 2 * 4 is interlaceskip << 1. + + op = opbeg + (framewidth + framestride) * (interlaceskip << 1); + interlaceskip >>= 1; + } + } + + if (index === trans) { + op += 4; + } else { + var r = buf[palette_offset + index * 3]; + var g = buf[palette_offset + index * 3 + 1]; + var b = buf[palette_offset + index * 3 + 2]; + pixels[op++] = b; + pixels[op++] = g; + pixels[op++] = r; + pixels[op++] = 255; + } + + --xleft; + } + }; // I will go to copy and paste hell one day... + + + this.decodeAndBlitFrameRGBA = function (frame_num, pixels) { + var frame = this.frameInfo(frame_num); + var num_pixels = frame.width * frame.height; + var index_stream = new Uint8Array(num_pixels); // At most 8-bit indices. + + GifReaderLZWOutputIndexStream(buf, frame.data_offset, index_stream, num_pixels); + var palette_offset = frame.palette_offset; // NOTE(deanm): It seems to be much faster to compare index to 256 than + // to === null. Not sure why, but CompareStub_EQ_STRICT shows up high in + // the profile, not sure if it's related to using a Uint8Array. + + var trans = frame.transparent_index; + if (trans === null) trans = 256; // We are possibly just blitting to a portion of the entire frame. + // That is a subrect within the framerect, so the additional pixels + // must be skipped over after we finished a scanline. + + var framewidth = frame.width; + var framestride = width - framewidth; + var xleft = framewidth; // Number of subrect pixels left in scanline. + // Output indicies of the top left and bottom right corners of the subrect. + + var opbeg = (frame.y * width + frame.x) * 4; + var opend = ((frame.y + frame.height) * width + frame.x) * 4; + var op = opbeg; + var scanstride = framestride * 4; // Use scanstride to skip past the rows when interlacing. This is skipping + // 7 rows for the first two passes, then 3 then 1. + + if (frame.interlaced === true) { + scanstride += (framewidth + framestride) * 4 * 7; // Pass 1. + } + + var interlaceskip = 8; // Tracking the row interval in the current pass. + + for (var i = 0, il = index_stream.length; i < il; ++i) { + var index = index_stream[i]; + + if (xleft === 0) { + // Beginning of new scan line + op += scanstride; + xleft = framewidth; + + if (op >= opend) { + // Catch the wrap to switch passes when interlacing. + scanstride = framestride + (framewidth + framestride) * 4 * (interlaceskip - 1); // interlaceskip / 2 * 4 is interlaceskip << 1. + + op = opbeg + (framewidth + framestride) * (interlaceskip << 1); + interlaceskip >>= 1; + } + } + + if (index === trans) { + op += 4; + } else { + var r = buf[palette_offset + index * 3]; + var g = buf[palette_offset + index * 3 + 1]; + var b = buf[palette_offset + index * 3 + 2]; + pixels[op++] = r; + pixels[op++] = g; + pixels[op++] = b; + pixels[op++] = 255; + } + + --xleft; + } + }; + } + + function GifReaderLZWOutputIndexStream(code_stream, p, output, output_length) { + var min_code_size = code_stream[p++]; + var clear_code = 1 << min_code_size; + var eoi_code = clear_code + 1; + var next_code = eoi_code + 1; + var cur_code_size = min_code_size + 1; // Number of bits per code. + // NOTE: This shares the same name as the encoder, but has a different + // meaning here. Here this masks each code coming from the code stream. + + var code_mask = (1 << cur_code_size) - 1; + var cur_shift = 0; + var cur = 0; + var op = 0; // Output pointer. + + var subblock_size = code_stream[p++]; // TODO(deanm): Would using a TypedArray be any faster? At least it would + // solve the fast mode / backing store uncertainty. + // var code_table = Array(4096); + + var code_table = new Int32Array(4096); // Can be signed, we only use 20 bits. + + var prev_code = null; // Track code-1. + + while (true) { + // Read up to two bytes, making sure we always 12-bits for max sized code. + while (cur_shift < 16) { + if (subblock_size === 0) break; // No more data to be read. + + cur |= code_stream[p++] << cur_shift; + cur_shift += 8; + + if (subblock_size === 1) { + // Never let it get to 0 to hold logic above. + subblock_size = code_stream[p++]; // Next subblock. + } else { + --subblock_size; + } + } // TODO(deanm): We should never really get here, we should have received + // and EOI. + + + if (cur_shift < cur_code_size) break; + var code = cur & code_mask; + cur >>= cur_code_size; + cur_shift -= cur_code_size; // TODO(deanm): Maybe should check that the first code was a clear code, + // at least this is what you're supposed to do. But actually our encoder + // now doesn't emit a clear code first anyway. + + if (code === clear_code) { + // We don't actually have to clear the table. This could be a good idea + // for greater error checking, but we don't really do any anyway. We + // will just track it with next_code and overwrite old entries. + next_code = eoi_code + 1; + cur_code_size = min_code_size + 1; + code_mask = (1 << cur_code_size) - 1; // Don't update prev_code ? + + prev_code = null; + continue; + } else if (code === eoi_code) { + break; + } // We have a similar situation as the decoder, where we want to store + // variable length entries (code table entries), but we want to do in a + // faster manner than an array of arrays. The code below stores sort of a + // linked list within the code table, and then "chases" through it to + // construct the dictionary entries. When a new entry is created, just the + // last byte is stored, and the rest (prefix) of the entry is only + // referenced by its table entry. Then the code chases through the + // prefixes until it reaches a single byte code. We have to chase twice, + // first to compute the length, and then to actually copy the data to the + // output (backwards, since we know the length). The alternative would be + // storing something in an intermediate stack, but that doesn't make any + // more sense. I implemented an approach where it also stored the length + // in the code table, although it's a bit tricky because you run out of + // bits (12 + 12 + 8), but I didn't measure much improvements (the table + // entries are generally not the long). Even when I created benchmarks for + // very long table entries the complexity did not seem worth it. + // The code table stores the prefix entry in 12 bits and then the suffix + // byte in 8 bits, so each entry is 20 bits. + + + var chase_code = code < next_code ? code : prev_code; // Chase what we will output, either {CODE} or {CODE-1}. + + var chase_length = 0; + var chase = chase_code; + + while (chase > clear_code) { + chase = code_table[chase] >> 8; + ++chase_length; + } + + var k = chase; + var op_end = op + chase_length + (chase_code !== code ? 1 : 0); + + if (op_end > output_length) { + console.log("Warning, gif stream longer than expected."); + return; + } // Already have the first byte from the chase, might as well write it fast. + + + output[op++] = k; + op += chase_length; + var b = op; // Track pointer, writing backwards. + + if (chase_code !== code) // The case of emitting {CODE-1} + k. + output[op++] = k; + chase = chase_code; + + while (chase_length--) { + chase = code_table[chase]; + output[--b] = chase & 0xff; // Write backwards. + + chase >>= 8; // Pull down to the prefix code. + } + + if (prev_code !== null && next_code < 4096) { + code_table[next_code++] = prev_code << 8 | k; // TODO(deanm): Figure out this clearing vs code growth logic better. I + // have an feeling that it should just happen somewhere else, for now it + // is awkward between when we grow past the max and then hit a clear code. + // For now just check if we hit the max 12-bits (then a clear code should + // follow, also of course encoded in 12-bits). + + if (next_code >= code_mask + 1 && cur_code_size < 12) { + ++cur_code_size; + code_mask = code_mask << 1 | 1; + } + } + + prev_code = code; + } + + if (op !== output_length) { + console.log("Warning, gif stream shorter than expected."); + } + + return output; + } + + try { + + + } catch (e) {} // CommonJS. + + /* + * Copyright (c) 2012 chick307 + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + (function (jsPDF, callback) { + jsPDF.API.adler32cs = callback(); + })(jsPDF, function () { + var _hasArrayBuffer = typeof ArrayBuffer === "function" && typeof Uint8Array === "function"; + + var _Buffer = null, + _isBuffer = function () { + if (!_hasArrayBuffer) return function _isBuffer() { + return false; + }; + + return function _isBuffer(value) { + return value instanceof ArrayBuffer || _Buffer !== null && value instanceof _Buffer; + }; + }(); + + var _utf8ToBinary = function () { + if (_Buffer !== null) { + return function _utf8ToBinary(utf8String) { + return new _Buffer(utf8String, "utf8").toString("binary"); + }; + } else { + return function _utf8ToBinary(utf8String) { + return unescape(encodeURIComponent(utf8String)); + }; + } + }(); + + var MOD = 65521; + + var _update = function _update(checksum, binaryString) { + var a = checksum & 0xffff, + b = checksum >>> 16; + + for (var i = 0, length = binaryString.length; i < length; i++) { + a = (a + (binaryString.charCodeAt(i) & 0xff)) % MOD; + b = (b + a) % MOD; + } + + return (b << 16 | a) >>> 0; + }; + + var _updateUint8Array = function _updateUint8Array(checksum, uint8Array) { + var a = checksum & 0xffff, + b = checksum >>> 16; + + for (var i = 0, length = uint8Array.length; i < length; i++) { + a = (a + uint8Array[i]) % MOD; + b = (b + a) % MOD; + } + + return (b << 16 | a) >>> 0; + }; + + var exports = {}; + + var Adler32 = exports.Adler32 = function () { + var ctor = function Adler32(checksum) { + if (!(this instanceof ctor)) { + throw new TypeError("Constructor cannot called be as a function."); + } + + if (!isFinite(checksum = checksum == null ? 1 : +checksum)) { + throw new Error("First arguments needs to be a finite number."); + } + + this.checksum = checksum >>> 0; + }; + + var proto = ctor.prototype = {}; + proto.constructor = ctor; + + ctor.from = function (from) { + from.prototype = proto; + return from; + }(function from(binaryString) { + if (!(this instanceof ctor)) { + throw new TypeError("Constructor cannot called be as a function."); + } + + if (binaryString == null) throw new Error("First argument needs to be a string."); + this.checksum = _update(1, binaryString.toString()); + }); + + ctor.fromUtf8 = function (fromUtf8) { + fromUtf8.prototype = proto; + return fromUtf8; + }(function fromUtf8(utf8String) { + if (!(this instanceof ctor)) { + throw new TypeError("Constructor cannot called be as a function."); + } + + if (utf8String == null) throw new Error("First argument needs to be a string."); + + var binaryString = _utf8ToBinary(utf8String.toString()); + + this.checksum = _update(1, binaryString); + }); + + if (_hasArrayBuffer) { + ctor.fromBuffer = function (fromBuffer) { + fromBuffer.prototype = proto; + return fromBuffer; + }(function fromBuffer(buffer) { + if (!(this instanceof ctor)) { + throw new TypeError("Constructor cannot called be as a function."); + } + + if (!_isBuffer(buffer)) throw new Error("First argument needs to be ArrayBuffer."); + var array = new Uint8Array(buffer); + return this.checksum = _updateUint8Array(1, array); + }); + } + + proto.update = function update(binaryString) { + if (binaryString == null) throw new Error("First argument needs to be a string."); + binaryString = binaryString.toString(); + return this.checksum = _update(this.checksum, binaryString); + }; + + proto.updateUtf8 = function updateUtf8(utf8String) { + if (utf8String == null) throw new Error("First argument needs to be a string."); + + var binaryString = _utf8ToBinary(utf8String.toString()); + + return this.checksum = _update(this.checksum, binaryString); + }; + + if (_hasArrayBuffer) { + proto.updateBuffer = function updateBuffer(buffer) { + if (!_isBuffer(buffer)) throw new Error("First argument needs to be ArrayBuffer."); + var array = new Uint8Array(buffer); + return this.checksum = _updateUint8Array(this.checksum, array); + }; + } + + proto.clone = function clone() { + return new Adler32(this.checksum); + }; + + return ctor; + }(); + + exports.from = function from(binaryString) { + if (binaryString == null) throw new Error("First argument needs to be a string."); + return _update(1, binaryString.toString()); + }; + + exports.fromUtf8 = function fromUtf8(utf8String) { + if (utf8String == null) throw new Error("First argument needs to be a string."); + + var binaryString = _utf8ToBinary(utf8String.toString()); + + return _update(1, binaryString); + }; + + if (_hasArrayBuffer) { + exports.fromBuffer = function fromBuffer(buffer) { + if (!_isBuffer(buffer)) throw new Error("First argument need to be ArrayBuffer."); + var array = new Uint8Array(buffer); + return _updateUint8Array(1, array); + }; + } + + return exports; + }); + + /* + Copyright (c) 2008, Adobe Systems Incorporated + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Adobe Systems Incorporated nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + /** + * @author shaozilee + * + * Bmp format decoder,support 1bit 4bit 8bit 24bit bmp + * + */ + + /* + Copyright (c) 2013 Gildas Lormeau. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, + INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + /* + * This program is based on JZlib 1.0.2 ymnk, JCraft,Inc. + * JZlib is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + (function (global) { + + var MAX_BITS = 15; + var D_CODES = 30; + var BL_CODES = 19; + var LENGTH_CODES = 29; + var LITERALS = 256; + var L_CODES = LITERALS + 1 + LENGTH_CODES; + var HEAP_SIZE = 2 * L_CODES + 1; + var END_BLOCK = 256; // Bit length codes must not exceed MAX_BL_BITS bits + + var MAX_BL_BITS = 7; // repeat previous bit length 3-6 times (2 bits of repeat count) + + var REP_3_6 = 16; // repeat a zero length 3-10 times (3 bits of repeat count) + + var REPZ_3_10 = 17; // repeat a zero length 11-138 times (7 bits of repeat count) + + var REPZ_11_138 = 18; // The lengths of the bit length codes are sent in order of decreasing + // probability, to avoid transmitting the lengths for unused bit + // length codes. + + var Buf_size = 8 * 2; // JZlib version : "1.0.2" + + var Z_DEFAULT_COMPRESSION = -1; // compression strategy + + var Z_FILTERED = 1; + var Z_HUFFMAN_ONLY = 2; + var Z_DEFAULT_STRATEGY = 0; + var Z_NO_FLUSH = 0; + var Z_PARTIAL_FLUSH = 1; + var Z_FULL_FLUSH = 3; + var Z_FINISH = 4; + var Z_OK = 0; + var Z_STREAM_END = 1; + var Z_NEED_DICT = 2; + var Z_STREAM_ERROR = -2; + var Z_DATA_ERROR = -3; + var Z_BUF_ERROR = -5; // Tree + // see definition of array dist_code below + + var _dist_code = [0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29]; + + function Tree() { + var that = this; // dyn_tree; // the dynamic tree + // max_code; // largest code with non zero frequency + // stat_desc; // the corresponding static tree + // Compute the optimal bit lengths for a tree and update the total bit + // length + // for the current block. + // IN assertion: the fields freq and dad are set, heap[heap_max] and + // above are the tree nodes sorted by increasing frequency. + // OUT assertions: the field len is set to the optimal bit length, the + // array bl_count contains the frequencies for each bit length. + // The length opt_len is updated; static_len is also updated if stree is + // not null. + + function gen_bitlen(s) { + var tree = that.dyn_tree; + var stree = that.stat_desc.static_tree; + var extra = that.stat_desc.extra_bits; + var base = that.stat_desc.extra_base; + var max_length = that.stat_desc.max_length; + var h; // heap index + + var n, m; // iterate over the tree elements + + var bits; // bit length + + var xbits; // extra bits + + var f; // frequency + + var overflow = 0; // number of elements with bit length too large + + for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0; // In a first pass, compute the optimal bit lengths (which may + // overflow in the case of the bit length tree). + + + tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap + + for (h = s.heap_max + 1; h < HEAP_SIZE; h++) { + n = s.heap[h]; + bits = tree[tree[n * 2 + 1] * 2 + 1] + 1; + + if (bits > max_length) { + bits = max_length; + overflow++; + } + + tree[n * 2 + 1] = bits; // We overwrite tree[n*2+1] which is no longer needed + + if (n > that.max_code) continue; // not a leaf node + + s.bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n - base]; + f = tree[n * 2]; + s.opt_len += f * (bits + xbits); + if (stree) s.static_len += f * (stree[n * 2 + 1] + xbits); + } + + if (overflow === 0) return; // This happens for example on obj2 and pic of the Calgary corpus + // Find the first bit length which could increase: + + do { + bits = max_length - 1; + + while (s.bl_count[bits] === 0) bits--; + + s.bl_count[bits]--; // move one leaf down the tree + + s.bl_count[bits + 1] += 2; // move one overflow item as its brother + + s.bl_count[max_length]--; // The brother of the overflow item also moves one step up, + // but this does not affect bl_count[max_length] + + overflow -= 2; + } while (overflow > 0); + + for (bits = max_length; bits !== 0; bits--) { + n = s.bl_count[bits]; + + while (n !== 0) { + m = s.heap[--h]; + if (m > that.max_code) continue; + + if (tree[m * 2 + 1] != bits) { + s.opt_len += (bits - tree[m * 2 + 1]) * tree[m * 2]; + tree[m * 2 + 1] = bits; + } + + n--; + } + } + } // Reverse the first len bits of a code, using straightforward code (a + // faster + // method would use a table) + // IN assertion: 1 <= len <= 15 + + + function bi_reverse(code, // the value to invert + len // its bit length + ) { + var res = 0; + + do { + res |= code & 1; + code >>>= 1; + res <<= 1; + } while (--len > 0); + + return res >>> 1; + } // Generate the codes for a given tree and bit counts (which need not be + // optimal). + // IN assertion: the array bl_count contains the bit length statistics for + // the given tree and the field len is set for all tree elements. + // OUT assertion: the field code is set for all tree elements of non + // zero code length. + + + function gen_codes(tree, // the tree to decorate + max_code, // largest code with non zero frequency + bl_count // number of codes at each bit length + ) { + var next_code = []; // next code value for each + // bit length + + var code = 0; // running code value + + var bits; // bit index + + var n; // code index + + var len; // The distribution counts are first used to generate the code values + // without bit reversal. + + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = code + bl_count[bits - 1] << 1; + } // Check that the bit counts in bl_count are consistent. The last code + // must be all ones. + // Assert (code + bl_count[MAX_BITS]-1 == (1<= 1; n--) s.pqdownheap(tree, n); // Construct the Huffman tree by repeatedly combining the least two + // frequent nodes. + + + node = elems; // next internal node of the tree + + do { + // n = node of least frequency + n = s.heap[1]; + s.heap[1] = s.heap[s.heap_len--]; + s.pqdownheap(tree, 1); + m = s.heap[1]; // m = node of next least frequency + + s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency + + s.heap[--s.heap_max] = m; // Create a new node father of n and m + + tree[node * 2] = tree[n * 2] + tree[m * 2]; + s.depth[node] = Math.max(s.depth[n], s.depth[m]) + 1; + tree[n * 2 + 1] = tree[m * 2 + 1] = node; // and insert the new node in the heap + + s.heap[1] = node++; + s.pqdownheap(tree, 1); + } while (s.heap_len >= 2); + + s.heap[--s.heap_max] = s.heap[1]; // At this point, the fields freq and dad are set. We can now + // generate the bit lengths. + + gen_bitlen(s); // The field len is now set, we can generate the bit codes + + gen_codes(tree, that.max_code, s.bl_count); + }; + } + + Tree._length_code = [0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28]; + Tree.base_length = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0]; + Tree.base_dist = [0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576]; // Mapping from a distance to a distance code. dist is the distance - 1 and + // must not have side effects. _dist_code[256] and _dist_code[257] are never + // used. + + Tree.d_code = function (dist) { + return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]; + }; // extra bits for each length code + + + Tree.extra_lbits = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0]; // extra bits for each distance code + + Tree.extra_dbits = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13]; // extra bits for each bit length code + + Tree.extra_blbits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7]; + Tree.bl_order = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; // StaticTree + + function StaticTree(static_tree, extra_bits, extra_base, elems, max_length) { + var that = this; + that.static_tree = static_tree; + that.extra_bits = extra_bits; + that.extra_base = extra_base; + that.elems = elems; + that.max_length = max_length; + } + + StaticTree.static_ltree = [12, 8, 140, 8, 76, 8, 204, 8, 44, 8, 172, 8, 108, 8, 236, 8, 28, 8, 156, 8, 92, 8, 220, 8, 60, 8, 188, 8, 124, 8, 252, 8, 2, 8, 130, 8, 66, 8, 194, 8, 34, 8, 162, 8, 98, 8, 226, 8, 18, 8, 146, 8, 82, 8, 210, 8, 50, 8, 178, 8, 114, 8, 242, 8, 10, 8, 138, 8, 74, 8, 202, 8, 42, 8, 170, 8, 106, 8, 234, 8, 26, 8, 154, 8, 90, 8, 218, 8, 58, 8, 186, 8, 122, 8, 250, 8, 6, 8, 134, 8, 70, 8, 198, 8, 38, 8, 166, 8, 102, 8, 230, 8, 22, 8, 150, 8, 86, 8, 214, 8, 54, 8, 182, 8, 118, 8, 246, 8, 14, 8, 142, 8, 78, 8, 206, 8, 46, 8, 174, 8, 110, 8, 238, 8, 30, 8, 158, 8, 94, 8, 222, 8, 62, 8, 190, 8, 126, 8, 254, 8, 1, 8, 129, 8, 65, 8, 193, 8, 33, 8, 161, 8, 97, 8, 225, 8, 17, 8, 145, 8, 81, 8, 209, 8, 49, 8, 177, 8, 113, 8, 241, 8, 9, 8, 137, 8, 73, 8, 201, 8, 41, 8, 169, 8, 105, 8, 233, 8, 25, 8, 153, 8, 89, 8, 217, 8, 57, 8, 185, 8, 121, 8, 249, 8, 5, 8, 133, 8, 69, 8, 197, 8, 37, 8, 165, 8, 101, 8, 229, 8, 21, 8, 149, 8, 85, 8, 213, 8, 53, 8, 181, 8, 117, 8, 245, 8, 13, 8, 141, 8, 77, 8, 205, 8, 45, 8, 173, 8, 109, 8, 237, 8, 29, 8, 157, 8, 93, 8, 221, 8, 61, 8, 189, 8, 125, 8, 253, 8, 19, 9, 275, 9, 147, 9, 403, 9, 83, 9, 339, 9, 211, 9, 467, 9, 51, 9, 307, 9, 179, 9, 435, 9, 115, 9, 371, 9, 243, 9, 499, 9, 11, 9, 267, 9, 139, 9, 395, 9, 75, 9, 331, 9, 203, 9, 459, 9, 43, 9, 299, 9, 171, 9, 427, 9, 107, 9, 363, 9, 235, 9, 491, 9, 27, 9, 283, 9, 155, 9, 411, 9, 91, 9, 347, 9, 219, 9, 475, 9, 59, 9, 315, 9, 187, 9, 443, 9, 123, 9, 379, 9, 251, 9, 507, 9, 7, 9, 263, 9, 135, 9, 391, 9, 71, 9, 327, 9, 199, 9, 455, 9, 39, 9, 295, 9, 167, 9, 423, 9, 103, 9, 359, 9, 231, 9, 487, 9, 23, 9, 279, 9, 151, 9, 407, 9, 87, 9, 343, 9, 215, 9, 471, 9, 55, 9, 311, 9, 183, 9, 439, 9, 119, 9, 375, 9, 247, 9, 503, 9, 15, 9, 271, 9, 143, 9, 399, 9, 79, 9, 335, 9, 207, 9, 463, 9, 47, 9, 303, 9, 175, 9, 431, 9, 111, 9, 367, 9, 239, 9, 495, 9, 31, 9, 287, 9, 159, 9, 415, 9, 95, 9, 351, 9, 223, 9, 479, 9, 63, 9, 319, 9, 191, 9, 447, 9, 127, 9, 383, 9, 255, 9, 511, 9, 0, 7, 64, 7, 32, 7, 96, 7, 16, 7, 80, 7, 48, 7, 112, 7, 8, 7, 72, 7, 40, 7, 104, 7, 24, 7, 88, 7, 56, 7, 120, 7, 4, 7, 68, 7, 36, 7, 100, 7, 20, 7, 84, 7, 52, 7, 116, 7, 3, 8, 131, 8, 67, 8, 195, 8, 35, 8, 163, 8, 99, 8, 227, 8]; + StaticTree.static_dtree = [0, 5, 16, 5, 8, 5, 24, 5, 4, 5, 20, 5, 12, 5, 28, 5, 2, 5, 18, 5, 10, 5, 26, 5, 6, 5, 22, 5, 14, 5, 30, 5, 1, 5, 17, 5, 9, 5, 25, 5, 5, 5, 21, 5, 13, 5, 29, 5, 3, 5, 19, 5, 11, 5, 27, 5, 7, 5, 23, 5]; + StaticTree.static_l_desc = new StaticTree(StaticTree.static_ltree, Tree.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS); + StaticTree.static_d_desc = new StaticTree(StaticTree.static_dtree, Tree.extra_dbits, 0, D_CODES, MAX_BITS); + StaticTree.static_bl_desc = new StaticTree(null, Tree.extra_blbits, 0, BL_CODES, MAX_BL_BITS); // Deflate + + var MAX_MEM_LEVEL = 9; + var DEF_MEM_LEVEL = 8; + + function Config(good_length, max_lazy, nice_length, max_chain, func) { + var that = this; + that.good_length = good_length; + that.max_lazy = max_lazy; + that.nice_length = nice_length; + that.max_chain = max_chain; + that.func = func; + } + + var STORED = 0; + var FAST = 1; + var SLOW = 2; + var config_table = [new Config(0, 0, 0, 0, STORED), new Config(4, 4, 8, 4, FAST), new Config(4, 5, 16, 8, FAST), new Config(4, 6, 32, 32, FAST), new Config(4, 4, 16, 16, SLOW), new Config(8, 16, 32, 32, SLOW), new Config(8, 16, 128, 128, SLOW), new Config(8, 32, 128, 256, SLOW), new Config(32, 128, 258, 1024, SLOW), new Config(32, 258, 258, 4096, SLOW)]; + var z_errmsg = ["need dictionary", // Z_NEED_DICT + // 2 + "stream end", // Z_STREAM_END 1 + "", // Z_OK 0 + "", // Z_ERRNO (-1) + "stream error", // Z_STREAM_ERROR (-2) + "data error", // Z_DATA_ERROR (-3) + "", // Z_MEM_ERROR (-4) + "buffer error", // Z_BUF_ERROR (-5) + "", // Z_VERSION_ERROR (-6) + ""]; // block not completed, need more input or more output + + var NeedMore = 0; // block flush performed + + var BlockDone = 1; // finish started, need only more output at next deflate + + var FinishStarted = 2; // finish done, accept no more input or output + + var FinishDone = 3; // preset dictionary flag in zlib header + + var PRESET_DICT = 0x20; + var INIT_STATE = 42; + var BUSY_STATE = 113; + var FINISH_STATE = 666; // The deflate compression method + + var Z_DEFLATED = 8; + var STORED_BLOCK = 0; + var STATIC_TREES = 1; + var DYN_TREES = 2; + var MIN_MATCH = 3; + var MAX_MATCH = 258; + var MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1; + + function smaller(tree, n, m, depth) { + var tn2 = tree[n * 2]; + var tm2 = tree[m * 2]; + return tn2 < tm2 || tn2 == tm2 && depth[n] <= depth[m]; + } + + function Deflate() { + var that = this; + var strm; // pointer back to this zlib stream + + var status; // as the name implies + // pending_buf; // output still pending + + var pending_buf_size; // size of pending_buf + + var last_flush; // value of flush param for previous deflate call + + var w_size; // LZ77 window size (32K by default) + + var w_bits; // log2(w_size) (8..16) + + var w_mask; // w_size - 1 + + var window; // Sliding window. Input bytes are read into the second half of the window, + // and move to the first half later to keep a dictionary of at least wSize + // bytes. With this organization, matches are limited to a distance of + // wSize-MAX_MATCH bytes, but this ensures that IO is always + // performed with a length multiple of the block size. Also, it limits + // the window size to 64K, which is quite useful on MSDOS. + // To do: use the user input buffer as sliding window. + + var window_size; // Actual size of window: 2*wSize, except when the user input buffer + // is directly used as sliding window. + + var prev; // Link to older string with same hash index. To limit the size of this + // array to 64K, this link is maintained only for the last 32K strings. + // An index in this array is thus a window index modulo 32K. + + var head; // Heads of the hash chains or NIL. + + var ins_h; // hash index of string to be inserted + + var hash_size; // number of elements in hash table + + var hash_bits; // log2(hash_size) + + var hash_mask; // hash_size-1 + // Number of bits by which ins_h must be shifted at each input + // step. It must be such that after MIN_MATCH steps, the oldest + // byte no longer takes part in the hash key, that is: + // hash_shift * MIN_MATCH >= hash_bits + + var hash_shift; // Window position at the beginning of the current output block. Gets + // negative when the window is moved backwards. + + var block_start; + var match_length; // length of best match + + var prev_match; // previous match + + var match_available; // set if previous match exists + + var strstart; // start of string to insert + + var match_start; // start of matching string + + var lookahead; // number of valid bytes ahead in window + // Length of the best match at previous step. Matches not greater than this + // are discarded. This is used in the lazy match evaluation. + + var prev_length; // To speed up deflation, hash chains are never searched beyond this + // length. A higher limit improves compression ratio but degrades the speed. + + var max_chain_length; // Attempt to find a better match only when the current match is strictly + // smaller than this value. This mechanism is used only for compression + // levels >= 4. + + var max_lazy_match; // Insert new strings in the hash table only if the match length is not + // greater than this length. This saves time but degrades compression. + // max_insert_length is used only for compression levels <= 3. + + var level; // compression level (1..9) + + var strategy; // favor or force Huffman coding + // Use a faster search when the previous match is longer than this + + var good_match; // Stop searching when current match exceeds this + + var nice_match; + var dyn_ltree; // literal and length tree + + var dyn_dtree; // distance tree + + var bl_tree; // Huffman tree for bit lengths + + var l_desc = new Tree(); // desc for literal tree + + var d_desc = new Tree(); // desc for distance tree + + var bl_desc = new Tree(); // desc for bit length tree + // that.heap_len; // number of elements in the heap + // that.heap_max; // element of largest frequency + // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + // The same heap array is used to build all trees. + // Depth of each subtree used as tie breaker for trees of equal frequency + + that.depth = []; + var l_buf; // index for literals or lengths */ + // Size of match buffer for literals/lengths. There are 4 reasons for + // limiting lit_bufsize to 64K: + // - frequencies can be kept in 16 bit counters + // - if compression is not successful for the first block, all input + // data is still in the window so we can still emit a stored block even + // when input comes from standard input. (This can also be done for + // all blocks if lit_bufsize is not greater than 32K.) + // - if compression is not successful for a file smaller than 64K, we can + // even emit a stored file instead of a stored block (saving 5 bytes). + // This is applicable only for zip (not gzip or zlib). + // - creating new Huffman trees less frequently may not provide fast + // adaptation to changes in the input data statistics. (Take for + // example a binary file with poorly compressible code followed by + // a highly compressible string table.) Smaller buffer sizes give + // fast adaptation but have of course the overhead of transmitting + // trees more frequently. + // - I can't count above 4 + + var lit_bufsize; + var last_lit; // running index in l_buf + // Buffer for distances. To simplify the code, d_buf and l_buf have + // the same number of elements. To use different lengths, an extra flag + // array would be necessary. + + var d_buf; // index of pendig_buf + // that.opt_len; // bit length of current block with optimal trees + // that.static_len; // bit length of current block with static trees + + var matches; // number of string matches in current block + + var last_eob_len; // bit length of EOB code for last block + // Output buffer. bits are inserted starting at the bottom (least + // significant bits). + + var bi_buf; // Number of valid bits in bi_buf. All bits above the last valid bit + // are always zero. + + var bi_valid; // number of codes at each bit length for an optimal tree + + that.bl_count = []; // heap used to build the Huffman trees + + that.heap = []; + dyn_ltree = []; + dyn_dtree = []; + bl_tree = []; + + function lm_init() { + var i; + window_size = 2 * w_size; + head[hash_size - 1] = 0; + + for (i = 0; i < hash_size - 1; i++) { + head[i] = 0; + } // Set the default configuration parameters: + + + max_lazy_match = config_table[level].max_lazy; + good_match = config_table[level].good_length; + nice_match = config_table[level].nice_length; + max_chain_length = config_table[level].max_chain; + strstart = 0; + block_start = 0; + lookahead = 0; + match_length = prev_length = MIN_MATCH - 1; + match_available = 0; + ins_h = 0; + } + + function init_block() { + var i; // Initialize the trees. + + for (i = 0; i < L_CODES; i++) dyn_ltree[i * 2] = 0; + + for (i = 0; i < D_CODES; i++) dyn_dtree[i * 2] = 0; + + for (i = 0; i < BL_CODES; i++) bl_tree[i * 2] = 0; + + dyn_ltree[END_BLOCK * 2] = 1; + that.opt_len = that.static_len = 0; + last_lit = matches = 0; + } // Initialize the tree data structures for a new zlib stream. + + + function tr_init() { + l_desc.dyn_tree = dyn_ltree; + l_desc.stat_desc = StaticTree.static_l_desc; + d_desc.dyn_tree = dyn_dtree; + d_desc.stat_desc = StaticTree.static_d_desc; + bl_desc.dyn_tree = bl_tree; + bl_desc.stat_desc = StaticTree.static_bl_desc; + bi_buf = 0; + bi_valid = 0; + last_eob_len = 8; // enough lookahead for inflate + // Initialize the first block of the first file: + + init_block(); + } // Restore the heap property by moving down the tree starting at node k, + // exchanging a node with the smallest of its two sons if necessary, + // stopping + // when the heap property is re-established (each father smaller than its + // two sons). + + + that.pqdownheap = function (tree, // the tree to restore + k // node to move down + ) { + var heap = that.heap; + var v = heap[k]; + var j = k << 1; // left son of k + + while (j <= that.heap_len) { + // Set j to the smallest of the two sons: + if (j < that.heap_len && smaller(tree, heap[j + 1], heap[j], that.depth)) { + j++; + } // Exit if v is smaller than both sons + + + if (smaller(tree, v, heap[j], that.depth)) break; // Exchange v with the smallest son + + heap[k] = heap[j]; + k = j; // And continue down the tree, setting j to the left son of k + + j <<= 1; + } + + heap[k] = v; + }; // Scan a literal or distance tree to determine the frequencies of the codes + // in the bit length tree. + + + function scan_tree(tree, // the tree to be scanned + max_code // and its largest code of non zero frequency + ) { + var n; // iterates over all tree elements + + var prevlen = -1; // last emitted length + + var curlen; // length of current code + + var nextlen = tree[0 * 2 + 1]; // length of next code + + var count = 0; // repeat count of the current code + + var max_count = 7; // max repeat count + + var min_count = 4; // min repeat count + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + + tree[(max_code + 1) * 2 + 1] = 0xffff; // guard + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]; + + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + bl_tree[curlen * 2] += count; + } else if (curlen !== 0) { + if (curlen != prevlen) bl_tree[curlen * 2]++; + bl_tree[REP_3_6 * 2]++; + } else if (count <= 10) { + bl_tree[REPZ_3_10 * 2]++; + } else { + bl_tree[REPZ_11_138 * 2]++; + } + + count = 0; + prevlen = curlen; + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } else if (curlen == nextlen) { + max_count = 6; + min_count = 3; + } else { + max_count = 7; + min_count = 4; + } + } + } // Construct the Huffman tree for the bit lengths and return the index in + // bl_order of the last bit length code to send. + + + function build_bl_tree() { + var max_blindex; // index of last bit length code of non zero freq + // Determine the bit length frequencies for literal and distance trees + + scan_tree(dyn_ltree, l_desc.max_code); + scan_tree(dyn_dtree, d_desc.max_code); // Build the bit length tree: + + bl_desc.build_tree(that); // opt_len now includes the length of the tree representations, except + // the lengths of the bit lengths codes and the 5+5+4 bits for the + // counts. + // Determine the number of bit length codes to send. The pkzip format + // requires that at least 4 bit length codes be sent. (appnote.txt says + // 3 but the actual value used is 4.) + + for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) { + if (bl_tree[Tree.bl_order[max_blindex] * 2 + 1] !== 0) break; + } // Update opt_len to include the bit length tree and counts + + + that.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; + return max_blindex; + } // Output a byte on the stream. + // IN assertion: there is enough room in pending_buf. + + + function put_byte(p) { + that.pending_buf[that.pending++] = p; + } + + function put_short(w) { + put_byte(w & 0xff); + put_byte(w >>> 8 & 0xff); + } + + function putShortMSB(b) { + put_byte(b >> 8 & 0xff); + put_byte(b & 0xff & 0xff); + } + + function send_bits(value, length) { + var val, + len = length; + + if (bi_valid > Buf_size - len) { + val = value; // bi_buf |= (val << bi_valid); + + bi_buf |= val << bi_valid & 0xffff; + put_short(bi_buf); + bi_buf = val >>> Buf_size - bi_valid; + bi_valid += len - Buf_size; + } else { + // bi_buf |= (value) << bi_valid; + bi_buf |= value << bi_valid & 0xffff; + bi_valid += len; + } + } + + function send_code(c, tree) { + var c2 = c * 2; + send_bits(tree[c2] & 0xffff, tree[c2 + 1] & 0xffff); + } // Send a literal or distance tree in compressed form, using the codes in + // bl_tree. + + + function send_tree(tree, // the tree to be sent + max_code // and its largest code of non zero frequency + ) { + var n; // iterates over all tree elements + + var prevlen = -1; // last emitted length + + var curlen; // length of current code + + var nextlen = tree[0 * 2 + 1]; // length of next code + + var count = 0; // repeat count of the current code + + var max_count = 7; // max repeat count + + var min_count = 4; // min repeat count + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n + 1) * 2 + 1]; + + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { + send_code(curlen, bl_tree); + } while (--count !== 0); + } else if (curlen !== 0) { + if (curlen != prevlen) { + send_code(curlen, bl_tree); + count--; + } + + send_code(REP_3_6, bl_tree); + send_bits(count - 3, 2); + } else if (count <= 10) { + send_code(REPZ_3_10, bl_tree); + send_bits(count - 3, 3); + } else { + send_code(REPZ_11_138, bl_tree); + send_bits(count - 11, 7); + } + + count = 0; + prevlen = curlen; + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } else if (curlen == nextlen) { + max_count = 6; + min_count = 3; + } else { + max_count = 7; + min_count = 4; + } + } + } // Send the header for a block using dynamic Huffman trees: the counts, the + // lengths of the bit length codes, the literal tree and the distance tree. + // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + + + function send_all_trees(lcodes, dcodes, blcodes) { + var rank; // index in bl_order + + send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt + + send_bits(dcodes - 1, 5); + send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt + + for (rank = 0; rank < blcodes; rank++) { + send_bits(bl_tree[Tree.bl_order[rank] * 2 + 1], 3); + } + + send_tree(dyn_ltree, lcodes - 1); // literal tree + + send_tree(dyn_dtree, dcodes - 1); // distance tree + } // Flush the bit buffer, keeping at most 7 bits in it. + + + function bi_flush() { + if (bi_valid == 16) { + put_short(bi_buf); + bi_buf = 0; + bi_valid = 0; + } else if (bi_valid >= 8) { + put_byte(bi_buf & 0xff); + bi_buf >>>= 8; + bi_valid -= 8; + } + } // Send one empty static block to give enough lookahead for inflate. + // This takes 10 bits, of which 7 may remain in the bit buffer. + // The current inflate code requires 9 bits of lookahead. If the + // last two codes for the previous block (real code plus EOB) were coded + // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + // the last real code. In this case we send two empty static blocks instead + // of one. (There are no problems if the previous block is stored or fixed.) + // To simplify the code, we assume the worst case of last real code encoded + // on one bit only. + + + function _tr_align() { + send_bits(STATIC_TREES << 1, 3); + send_code(END_BLOCK, StaticTree.static_ltree); + bi_flush(); // Of the 10 bits for the empty block, we have already sent + // (10 - bi_valid) bits. The lookahead for the last real code (before + // the EOB of the previous block) was thus at least one plus the length + // of the EOB plus what we have just sent of the empty static block. + + if (1 + last_eob_len + 10 - bi_valid < 9) { + send_bits(STATIC_TREES << 1, 3); + send_code(END_BLOCK, StaticTree.static_ltree); + bi_flush(); + } + + last_eob_len = 7; + } // Save the match info and tally the frequency counts. Return true if + // the current block must be flushed. + + + function _tr_tally(dist, // distance of matched string + lc // match length-MIN_MATCH or unmatched char (if dist==0) + ) { + var out_length, in_length, dcode; + that.pending_buf[d_buf + last_lit * 2] = dist >>> 8 & 0xff; + that.pending_buf[d_buf + last_lit * 2 + 1] = dist & 0xff; + that.pending_buf[l_buf + last_lit] = lc & 0xff; + last_lit++; + + if (dist === 0) { + // lc is the unmatched char + dyn_ltree[lc * 2]++; + } else { + matches++; // Here, lc is the match length - MIN_MATCH + + dist--; // dist = match distance - 1 + + dyn_ltree[(Tree._length_code[lc] + LITERALS + 1) * 2]++; + dyn_dtree[Tree.d_code(dist) * 2]++; + } + + if ((last_lit & 0x1fff) === 0 && level > 2) { + // Compute an upper bound for the compressed length + out_length = last_lit * 8; + in_length = strstart - block_start; + + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += dyn_dtree[dcode * 2] * (5 + Tree.extra_dbits[dcode]); + } + + out_length >>>= 3; + if (matches < Math.floor(last_lit / 2) && out_length < Math.floor(in_length / 2)) return true; + } + + return last_lit == lit_bufsize - 1; // We avoid equality with lit_bufsize because of wraparound at 64K + // on 16 bit machines and because stored blocks are restricted to + // 64K-1 bytes. + } // Send the block data compressed using the given Huffman trees + + + function compress_block(ltree, dtree) { + var dist; // distance of matched string + + var lc; // match length or unmatched char (if dist === 0) + + var lx = 0; // running index in l_buf + + var code; // the code to send + + var extra; // number of extra bits to send + + if (last_lit !== 0) { + do { + dist = that.pending_buf[d_buf + lx * 2] << 8 & 0xff00 | that.pending_buf[d_buf + lx * 2 + 1] & 0xff; + lc = that.pending_buf[l_buf + lx] & 0xff; + lx++; + + if (dist === 0) { + send_code(lc, ltree); // send a literal byte + } else { + // Here, lc is the match length - MIN_MATCH + code = Tree._length_code[lc]; + send_code(code + LITERALS + 1, ltree); // send the length + // code + + extra = Tree.extra_lbits[code]; + + if (extra !== 0) { + lc -= Tree.base_length[code]; + send_bits(lc, extra); // send the extra length bits + } + + dist--; // dist is now the match distance - 1 + + code = Tree.d_code(dist); + send_code(code, dtree); // send the distance code + + extra = Tree.extra_dbits[code]; + + if (extra !== 0) { + dist -= Tree.base_dist[code]; + send_bits(dist, extra); // send the extra distance bits + } + } // literal or match pair ? + // Check that the overlay between pending_buf and d_buf+l_buf is + // ok: + + } while (lx < last_lit); + } + + send_code(END_BLOCK, ltree); + last_eob_len = ltree[END_BLOCK * 2 + 1]; + } // Flush the bit buffer and align the output on a byte boundary + + + function bi_windup() { + if (bi_valid > 8) { + put_short(bi_buf); + } else if (bi_valid > 0) { + put_byte(bi_buf & 0xff); + } + + bi_buf = 0; + bi_valid = 0; + } // Copy a stored block, storing first the length and its + // one's complement if requested. + + + function copy_block(buf, // the input data + len, // its length + header // true if block header must be written + ) { + bi_windup(); // align on byte boundary + + last_eob_len = 8; // enough lookahead for inflate + + if (header) { + put_short(len); + put_short(~len); + } + + that.pending_buf.set(window.subarray(buf, buf + len), that.pending); + that.pending += len; + } // Send a stored block + + + function _tr_stored_block(buf, // input block + stored_len, // length of input block + eof // true if this is the last block for a file + ) { + send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type + + copy_block(buf, stored_len, true); // with header + } // Determine the best encoding for the current block: dynamic trees, static + // trees or store, and output the encoded block to the zip file. + + + function _tr_flush_block(buf, // input block, or NULL if too old + stored_len, // length of input block + eof // true if this is the last block for a file + ) { + var opt_lenb, static_lenb; // opt_len and static_len in bytes + + var max_blindex = 0; // index of last bit length code of non zero freq + // Build the Huffman trees unless a stored block is forced + + if (level > 0) { + // Construct the literal and distance trees + l_desc.build_tree(that); + d_desc.build_tree(that); // At this point, opt_len and static_len are the total bit lengths + // of + // the compressed block data, excluding the tree representations. + // Build the bit length tree for the above two trees, and get the + // index + // in bl_order of the last bit length code to send. + + max_blindex = build_bl_tree(); // Determine the best encoding. Compute first the block length in + // bytes + + opt_lenb = that.opt_len + 3 + 7 >>> 3; + static_lenb = that.static_len + 3 + 7 >>> 3; + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + } else { + opt_lenb = static_lenb = stored_len + 5; // force a stored block + } + + if (stored_len + 4 <= opt_lenb && buf != -1) { + // 4: two words for the lengths + // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + // Otherwise we can't have processed more than WSIZE input bytes + // since + // the last block flush, because compression would have been + // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + // transform a block into a stored block. + _tr_stored_block(buf, stored_len, eof); + } else if (static_lenb == opt_lenb) { + send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3); + compress_block(StaticTree.static_ltree, StaticTree.static_dtree); + } else { + send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3); + send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1, max_blindex + 1); + compress_block(dyn_ltree, dyn_dtree); + } // The above check is made mod 2^32, for files larger than 512 MB + // and uLong implemented on 32 bits. + + + init_block(); + + if (eof) { + bi_windup(); + } + } + + function flush_block_only(eof) { + _tr_flush_block(block_start >= 0 ? block_start : -1, strstart - block_start, eof); + + block_start = strstart; + strm.flush_pending(); + } // Fill the window when the lookahead becomes insufficient. + // Updates strstart and lookahead. + // + // IN assertion: lookahead < MIN_LOOKAHEAD + // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + // At least one byte has been read, or avail_in === 0; reads are + // performed for at least two bytes (required for the zip translate_eol + // option -- not supported here). + + + function fill_window() { + var n, m; + var p; + var more; // Amount of free space at the end of the window. + + do { + more = window_size - lookahead - strstart; // Deal with !@#$% 64K limit: + + if (more === 0 && strstart === 0 && lookahead === 0) { + more = w_size; + } else if (more == -1) { + // Very unlikely, but possible on 16 bit machine if strstart == + // 0 + // and lookahead == 1 (input done one byte at time) + more--; // If the window is almost full and there is insufficient + // lookahead, + // move the upper half to the lower one to make room in the + // upper half. + } else if (strstart >= w_size + w_size - MIN_LOOKAHEAD) { + window.set(window.subarray(w_size, w_size + w_size), 0); + match_start -= w_size; + strstart -= w_size; // we now have strstart >= MAX_DIST + + block_start -= w_size; // Slide the hash table (could be avoided with 32 bit values + // at the expense of memory usage). We slide even when level == + // 0 + // to keep the hash table consistent if we switch back to level + // > 0 + // later. (Using level 0 permanently is not an optimal usage of + // zlib, so we don't care about this pathological case.) + + n = hash_size; + p = n; + + do { + m = head[--p] & 0xffff; + head[p] = m >= w_size ? m - w_size : 0; + } while (--n !== 0); + + n = w_size; + p = n; + + do { + m = prev[--p] & 0xffff; + prev[p] = m >= w_size ? m - w_size : 0; // If n is not on any hash chain, prev[n] is garbage but + // its value will never be used. + } while (--n !== 0); + + more += w_size; + } + + if (strm.avail_in === 0) return; // If there was no sliding: + // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + // more == window_size - lookahead - strstart + // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + // => more >= window_size - 2*WSIZE + 2 + // In the BIG_MEM or MMAP case (not yet supported), + // window_size == input_size + MIN_LOOKAHEAD && + // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + // Otherwise, window_size == 2*WSIZE so more >= 2. + // If there was sliding, more >= WSIZE. So in all cases, more >= 2. + + n = strm.read_buf(window, strstart + lookahead, more); + lookahead += n; // Initialize the hash value now that we have some input: + + if (lookahead >= MIN_MATCH) { + ins_h = window[strstart] & 0xff; + ins_h = (ins_h << hash_shift ^ window[strstart + 1] & 0xff) & hash_mask; + } // If the whole input has less than MIN_MATCH bytes, ins_h is + // garbage, + // but this is not important since only literal bytes will be + // emitted. + + } while (lookahead < MIN_LOOKAHEAD && strm.avail_in !== 0); + } // Copy without compression as much as possible from the input stream, + // return + // the current block state. + // This function does not insert new strings in the dictionary since + // uncompressible data is probably not useful. This function is used + // only for the level=0 compression option. + // NOTE: this function should be optimized to avoid extra copying from + // window to pending_buf. + + + function deflate_stored(flush) { + // Stored blocks are limited to 0xffff bytes, pending_buf is limited + // to pending_buf_size, and each stored block has a 5 byte header: + var max_block_size = 0xffff; + var max_start; + + if (max_block_size > pending_buf_size - 5) { + max_block_size = pending_buf_size - 5; + } // Copy as much as possible from input to output: + + + while (true) { + // Fill the window as much as possible: + if (lookahead <= 1) { + fill_window(); + if (lookahead === 0 && flush == Z_NO_FLUSH) return NeedMore; + if (lookahead === 0) break; // flush the current block + } + + strstart += lookahead; + lookahead = 0; // Emit a stored block if pending_buf will be full: + + max_start = block_start + max_block_size; + + if (strstart === 0 || strstart >= max_start) { + // strstart === 0 is possible when wraparound on 16-bit machine + lookahead = strstart - max_start; + strstart = max_start; + flush_block_only(false); + if (strm.avail_out === 0) return NeedMore; + } // Flush if we may have to slide, otherwise block_start may become + // negative and the data will be gone: + + + if (strstart - block_start >= w_size - MIN_LOOKAHEAD) { + flush_block_only(false); + if (strm.avail_out === 0) return NeedMore; + } + } + + flush_block_only(flush == Z_FINISH); + if (strm.avail_out === 0) return flush == Z_FINISH ? FinishStarted : NeedMore; + return flush == Z_FINISH ? FinishDone : BlockDone; + } + + function longest_match(cur_match) { + var chain_length = max_chain_length; // max hash chain length + + var scan = strstart; // current string + + var match; // matched string + + var len; // length of current match + + var best_len = prev_length; // best match length so far + + var limit = strstart > w_size - MIN_LOOKAHEAD ? strstart - (w_size - MIN_LOOKAHEAD) : 0; + var _nice_match = nice_match; // Stop when cur_match becomes <= limit. To simplify the code, + // we prevent matches with the string of window index 0. + + var wmask = w_mask; + var strend = strstart + MAX_MATCH; + var scan_end1 = window[scan + best_len - 1]; + var scan_end = window[scan + best_len]; // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of + // 16. + // It is easy to get rid of this optimization if necessary. + // Do not waste too much time if we already have a good match: + + if (prev_length >= good_match) { + chain_length >>= 2; + } // Do not look for matches beyond the end of the input. This is + // necessary + // to make deflate deterministic. + + + if (_nice_match > lookahead) _nice_match = lookahead; + + do { + match = cur_match; // Skip to next match if the match length cannot increase + // or if the match length is less than 2: + + if (window[match + best_len] != scan_end || window[match + best_len - 1] != scan_end1 || window[match] != window[scan] || window[++match] != window[scan + 1]) continue; // The check at best_len-1 can be removed because it will be made + // again later. (This heuristic is not always a win.) + // It is not necessary to compare scan[2] and match[2] since they + // are always equal when the other bytes match, given that + // the hash keys are equal and that HASH_BITS >= 8. + + scan += 2; + match++; // We check for insufficient lookahead only every 8th comparison; + // the 256th check will be made at strstart+258. + + do {} while (window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && scan < strend); + + len = MAX_MATCH - (strend - scan); + scan = strend - MAX_MATCH; + + if (len > best_len) { + match_start = cur_match; + best_len = len; + if (len >= _nice_match) break; + scan_end1 = window[scan + best_len - 1]; + scan_end = window[scan + best_len]; + } + } while ((cur_match = prev[cur_match & wmask] & 0xffff) > limit && --chain_length !== 0); + + if (best_len <= lookahead) return best_len; + return lookahead; + } // Compress as much as possible from the input stream, return the current + // block state. + // This function does not perform lazy evaluation of matches and inserts + // new strings in the dictionary only for unmatched strings or for short + // matches. It is used only for the fast compression options. + + + function deflate_fast(flush) { + // short hash_head = 0; // head of the hash chain + var hash_head = 0; // head of the hash chain + + var bflush; // set if current block must be flushed + + while (true) { + // Make sure that we always have enough lookahead, except + // at the end of the input file. We need MAX_MATCH bytes + // for the next match, plus MIN_MATCH bytes to insert the + // string following the next match. + if (lookahead < MIN_LOOKAHEAD) { + fill_window(); + + if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return NeedMore; + } + + if (lookahead === 0) break; // flush the current block + } // Insert the string window[strstart .. strstart+2] in the + // dictionary, and set hash_head to the head of the hash chain: + + + if (lookahead >= MIN_MATCH) { + ins_h = (ins_h << hash_shift ^ window[strstart + (MIN_MATCH - 1)] & 0xff) & hash_mask; // prev[strstart&w_mask]=hash_head=head[ins_h]; + + hash_head = head[ins_h] & 0xffff; + prev[strstart & w_mask] = head[ins_h]; + head[ins_h] = strstart; + } // Find the longest match, discarding those <= prev_length. + // At this point we have always match_length < MIN_MATCH + + + if (hash_head !== 0 && (strstart - hash_head & 0xffff) <= w_size - MIN_LOOKAHEAD) { + // To simplify the code, we prevent matches with the string + // of window index 0 (in particular we have to avoid a match + // of the string with itself at the start of the input file). + if (strategy != Z_HUFFMAN_ONLY) { + match_length = longest_match(hash_head); + } // longest_match() sets match_start + + } + + if (match_length >= MIN_MATCH) { + // check_match(strstart, match_start, match_length); + bflush = _tr_tally(strstart - match_start, match_length - MIN_MATCH); + lookahead -= match_length; // Insert new strings in the hash table only if the match length + // is not too large. This saves time but degrades compression. + + if (match_length <= max_lazy_match && lookahead >= MIN_MATCH) { + match_length--; // string at strstart already in hash table + + do { + strstart++; + ins_h = (ins_h << hash_shift ^ window[strstart + (MIN_MATCH - 1)] & 0xff) & hash_mask; // prev[strstart&w_mask]=hash_head=head[ins_h]; + + hash_head = head[ins_h] & 0xffff; + prev[strstart & w_mask] = head[ins_h]; + head[ins_h] = strstart; // strstart never exceeds WSIZE-MAX_MATCH, so there are + // always MIN_MATCH bytes ahead. + } while (--match_length !== 0); + + strstart++; + } else { + strstart += match_length; + match_length = 0; + ins_h = window[strstart] & 0xff; + ins_h = (ins_h << hash_shift ^ window[strstart + 1] & 0xff) & hash_mask; // If lookahead < MIN_MATCH, ins_h is garbage, but it does + // not + // matter since it will be recomputed at next deflate call. + } + } else { + // No match, output a literal byte + bflush = _tr_tally(0, window[strstart] & 0xff); + lookahead--; + strstart++; + } + + if (bflush) { + flush_block_only(false); + if (strm.avail_out === 0) return NeedMore; + } + } + + flush_block_only(flush == Z_FINISH); + + if (strm.avail_out === 0) { + if (flush == Z_FINISH) return FinishStarted;else return NeedMore; + } + + return flush == Z_FINISH ? FinishDone : BlockDone; + } // Same as above, but achieves better compression. We use a lazy + // evaluation for matches: a match is finally adopted only if there is + // no better match at the next window position. + + + function deflate_slow(flush) { + // short hash_head = 0; // head of hash chain + var hash_head = 0; // head of hash chain + + var bflush; // set if current block must be flushed + + var max_insert; // Process the input block. + + while (true) { + // Make sure that we always have enough lookahead, except + // at the end of the input file. We need MAX_MATCH bytes + // for the next match, plus MIN_MATCH bytes to insert the + // string following the next match. + if (lookahead < MIN_LOOKAHEAD) { + fill_window(); + + if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return NeedMore; + } + + if (lookahead === 0) break; // flush the current block + } // Insert the string window[strstart .. strstart+2] in the + // dictionary, and set hash_head to the head of the hash chain: + + + if (lookahead >= MIN_MATCH) { + ins_h = (ins_h << hash_shift ^ window[strstart + (MIN_MATCH - 1)] & 0xff) & hash_mask; // prev[strstart&w_mask]=hash_head=head[ins_h]; + + hash_head = head[ins_h] & 0xffff; + prev[strstart & w_mask] = head[ins_h]; + head[ins_h] = strstart; + } // Find the longest match, discarding those <= prev_length. + + + prev_length = match_length; + prev_match = match_start; + match_length = MIN_MATCH - 1; + + if (hash_head !== 0 && prev_length < max_lazy_match && (strstart - hash_head & 0xffff) <= w_size - MIN_LOOKAHEAD) { + // To simplify the code, we prevent matches with the string + // of window index 0 (in particular we have to avoid a match + // of the string with itself at the start of the input file). + if (strategy != Z_HUFFMAN_ONLY) { + match_length = longest_match(hash_head); + } // longest_match() sets match_start + + + if (match_length <= 5 && (strategy == Z_FILTERED || match_length == MIN_MATCH && strstart - match_start > 4096)) { + // If prev_match is also MIN_MATCH, match_start is garbage + // but we will ignore the current match anyway. + match_length = MIN_MATCH - 1; + } + } // If there was a match at the previous step and the current + // match is not better, output the previous match: + + + if (prev_length >= MIN_MATCH && match_length <= prev_length) { + max_insert = strstart + lookahead - MIN_MATCH; // Do not insert strings in hash table beyond this. + // check_match(strstart-1, prev_match, prev_length); + + bflush = _tr_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH); // Insert in hash table all strings up to the end of the match. + // strstart-1 and strstart are already inserted. If there is not + // enough lookahead, the last two strings are not inserted in + // the hash table. + + lookahead -= prev_length - 1; + prev_length -= 2; + + do { + if (++strstart <= max_insert) { + ins_h = (ins_h << hash_shift ^ window[strstart + (MIN_MATCH - 1)] & 0xff) & hash_mask; // prev[strstart&w_mask]=hash_head=head[ins_h]; + + hash_head = head[ins_h] & 0xffff; + prev[strstart & w_mask] = head[ins_h]; + head[ins_h] = strstart; + } + } while (--prev_length !== 0); + + match_available = 0; + match_length = MIN_MATCH - 1; + strstart++; + + if (bflush) { + flush_block_only(false); + if (strm.avail_out === 0) return NeedMore; + } + } else if (match_available !== 0) { + // If there was no match at the previous position, output a + // single literal. If there was a match but the current match + // is longer, truncate the previous match to a single literal. + bflush = _tr_tally(0, window[strstart - 1] & 0xff); + + if (bflush) { + flush_block_only(false); + } + + strstart++; + lookahead--; + if (strm.avail_out === 0) return NeedMore; + } else { + // There is no previous match to compare with, wait for + // the next step to decide. + match_available = 1; + strstart++; + lookahead--; + } + } + + if (match_available !== 0) { + bflush = _tr_tally(0, window[strstart - 1] & 0xff); + match_available = 0; + } + + flush_block_only(flush == Z_FINISH); + + if (strm.avail_out === 0) { + if (flush == Z_FINISH) return FinishStarted;else return NeedMore; + } + + return flush == Z_FINISH ? FinishDone : BlockDone; + } + + function deflateReset(strm) { + strm.total_in = strm.total_out = 0; + strm.msg = null; // + + that.pending = 0; + that.pending_out = 0; + status = BUSY_STATE; + last_flush = Z_NO_FLUSH; + tr_init(); + lm_init(); + return Z_OK; + } + + that.deflateInit = function (strm, _level, bits, _method, memLevel, _strategy) { + if (!_method) _method = Z_DEFLATED; + if (!memLevel) memLevel = DEF_MEM_LEVEL; + if (!_strategy) _strategy = Z_DEFAULT_STRATEGY; // byte[] my_version=ZLIB_VERSION; + // + // if (!version || version[0] != my_version[0] + // || stream_size != sizeof(z_stream)) { + // return Z_VERSION_ERROR; + // } + + strm.msg = null; + if (_level == Z_DEFAULT_COMPRESSION) _level = 6; + + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || _method != Z_DEFLATED || bits < 9 || bits > 15 || _level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + + strm.dstate = that; + w_bits = bits; + w_size = 1 << w_bits; + w_mask = w_size - 1; + hash_bits = memLevel + 7; + hash_size = 1 << hash_bits; + hash_mask = hash_size - 1; + hash_shift = Math.floor((hash_bits + MIN_MATCH - 1) / MIN_MATCH); + window = new Uint8Array(w_size * 2); + prev = []; + head = []; + lit_bufsize = 1 << memLevel + 6; // 16K elements by default + // We overlay pending_buf and d_buf+l_buf. This works since the average + // output size for (length,distance) codes is <= 24 bits. + + that.pending_buf = new Uint8Array(lit_bufsize * 4); + pending_buf_size = lit_bufsize * 4; + d_buf = Math.floor(lit_bufsize / 2); + l_buf = (1 + 2) * lit_bufsize; + level = _level; + strategy = _strategy; + return deflateReset(strm); + }; + + that.deflateEnd = function () { + if (status != INIT_STATE && status != BUSY_STATE && status != FINISH_STATE) { + return Z_STREAM_ERROR; + } // Deallocate in reverse order of allocations: + + + that.pending_buf = null; + head = null; + prev = null; + window = null; // free + + that.dstate = null; + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; + }; + + that.deflateParams = function (strm, _level, _strategy) { + var err = Z_OK; + + if (_level == Z_DEFAULT_COMPRESSION) { + _level = 6; + } + + if (_level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + + if (config_table[level].func != config_table[_level].func && strm.total_in !== 0) { + // Flush the last buffer: + err = strm.deflate(Z_PARTIAL_FLUSH); + } + + if (level != _level) { + level = _level; + max_lazy_match = config_table[level].max_lazy; + good_match = config_table[level].good_length; + nice_match = config_table[level].nice_length; + max_chain_length = config_table[level].max_chain; + } + + strategy = _strategy; + return err; + }; + + that.deflateSetDictionary = function (strm, dictionary, dictLength) { + var length = dictLength; + var n, + index = 0; + if (!dictionary || status != INIT_STATE) return Z_STREAM_ERROR; + if (length < MIN_MATCH) return Z_OK; + + if (length > w_size - MIN_LOOKAHEAD) { + length = w_size - MIN_LOOKAHEAD; + index = dictLength - length; // use the tail of the dictionary + } + + window.set(dictionary.subarray(index, index + length), 0); + strstart = length; + block_start = length; // Insert all strings in the hash table (except for the last two bytes). + // s->lookahead stays null, so s->ins_h will be recomputed at the next + // call of fill_window. + + ins_h = window[0] & 0xff; + ins_h = (ins_h << hash_shift ^ window[1] & 0xff) & hash_mask; + + for (n = 0; n <= length - MIN_MATCH; n++) { + ins_h = (ins_h << hash_shift ^ window[n + (MIN_MATCH - 1)] & 0xff) & hash_mask; + prev[n & w_mask] = head[ins_h]; + head[ins_h] = n; + } + + return Z_OK; + }; + + that.deflate = function (_strm, flush) { + var i, header, level_flags, old_flush, bstate; + + if (flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + + if (!_strm.next_out || !_strm.next_in && _strm.avail_in !== 0 || status == FINISH_STATE && flush != Z_FINISH) { + _strm.msg = z_errmsg[Z_NEED_DICT - Z_STREAM_ERROR]; + return Z_STREAM_ERROR; + } + + if (_strm.avail_out === 0) { + _strm.msg = z_errmsg[Z_NEED_DICT - Z_BUF_ERROR]; + return Z_BUF_ERROR; + } + + strm = _strm; // just in case + + old_flush = last_flush; + last_flush = flush; // Write the zlib header + + if (status == INIT_STATE) { + header = Z_DEFLATED + (w_bits - 8 << 4) << 8; + level_flags = (level - 1 & 0xff) >> 1; + if (level_flags > 3) level_flags = 3; + header |= level_flags << 6; + if (strstart !== 0) header |= PRESET_DICT; + header += 31 - header % 31; + status = BUSY_STATE; + putShortMSB(header); + } // Flush as much pending output as possible + + + if (that.pending !== 0) { + strm.flush_pending(); + + if (strm.avail_out === 0) { + // console.log(" avail_out==0"); + // Since avail_out is 0, deflate will be called again with + // more output space, but possibly with both pending and + // avail_in equal to zero. There won't be anything to do, + // but this is not an error situation so make sure we + // return OK instead of BUF_ERROR at next call of deflate: + last_flush = -1; + return Z_OK; + } // Make sure there is something to do and avoid duplicate + // consecutive + // flushes. For repeated and useless calls with Z_FINISH, we keep + // returning Z_STREAM_END instead of Z_BUFF_ERROR. + + } else if (strm.avail_in === 0 && flush <= old_flush && flush != Z_FINISH) { + strm.msg = z_errmsg[Z_NEED_DICT - Z_BUF_ERROR]; + return Z_BUF_ERROR; + } // User must not provide more input after the first FINISH: + + + if (status == FINISH_STATE && strm.avail_in !== 0) { + _strm.msg = z_errmsg[Z_NEED_DICT - Z_BUF_ERROR]; + return Z_BUF_ERROR; + } // Start a new block or continue the current one. + + + if (strm.avail_in !== 0 || lookahead !== 0 || flush != Z_NO_FLUSH && status != FINISH_STATE) { + bstate = -1; + + switch (config_table[level].func) { + case STORED: + bstate = deflate_stored(flush); + break; + + case FAST: + bstate = deflate_fast(flush); + break; + + case SLOW: + bstate = deflate_slow(flush); + break; + + default: + } + + if (bstate == FinishStarted || bstate == FinishDone) { + status = FINISH_STATE; + } + + if (bstate == NeedMore || bstate == FinishStarted) { + if (strm.avail_out === 0) { + last_flush = -1; // avoid BUF_ERROR next call, see above + } + + return Z_OK; // If flush != Z_NO_FLUSH && avail_out === 0, the next call + // of deflate should use the same flush parameter to make sure + // that the flush is complete. So we don't have to output an + // empty block here, this will be done at next call. This also + // ensures that for a very small output buffer, we emit at most + // one empty block. + } + + if (bstate == BlockDone) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(); + } else { + // FULL_FLUSH or SYNC_FLUSH + _tr_stored_block(0, 0, false); // For a full flush, this empty block will be recognized + // as a special marker by inflate_sync(). + + + if (flush == Z_FULL_FLUSH) { + // state.head[s.hash_size-1]=0; + for (i = 0; i < hash_size + /*-1*/ + ; i++) // forget history + head[i] = 0; + } + } + + strm.flush_pending(); + + if (strm.avail_out === 0) { + last_flush = -1; // avoid BUF_ERROR at next call, see above + + return Z_OK; + } + } + } + + if (flush != Z_FINISH) return Z_OK; + return Z_STREAM_END; + }; + } // ZStream + + + function ZStream() { + var that = this; + that.next_in_index = 0; + that.next_out_index = 0; // that.next_in; // next input byte + + that.avail_in = 0; // number of bytes available at next_in + + that.total_in = 0; // total nb of input bytes read so far + // that.next_out; // next output byte should be put there + + that.avail_out = 0; // remaining free space at next_out + + that.total_out = 0; // total nb of bytes output so far + // that.msg; + // that.dstate; + } + + ZStream.prototype = { + deflateInit: function (level, bits) { + var that = this; + that.dstate = new Deflate(); + if (!bits) bits = MAX_BITS; + return that.dstate.deflateInit(that, level, bits); + }, + deflate: function (flush) { + var that = this; + + if (!that.dstate) { + return Z_STREAM_ERROR; + } + + return that.dstate.deflate(that, flush); + }, + deflateEnd: function () { + var that = this; + if (!that.dstate) return Z_STREAM_ERROR; + var ret = that.dstate.deflateEnd(); + that.dstate = null; + return ret; + }, + deflateParams: function (level, strategy) { + var that = this; + if (!that.dstate) return Z_STREAM_ERROR; + return that.dstate.deflateParams(that, level, strategy); + }, + deflateSetDictionary: function (dictionary, dictLength) { + var that = this; + if (!that.dstate) return Z_STREAM_ERROR; + return that.dstate.deflateSetDictionary(that, dictionary, dictLength); + }, + // Read a new buffer from the current input stream, update the + // total number of bytes read. All deflate() input goes through + // this function so some applications may wish to modify it to avoid + // allocating a large strm->next_in buffer and copying from it. + // (See also flush_pending()). + read_buf: function (buf, start, size) { + var that = this; + var len = that.avail_in; + if (len > size) len = size; + if (len === 0) return 0; + that.avail_in -= len; + buf.set(that.next_in.subarray(that.next_in_index, that.next_in_index + len), start); + that.next_in_index += len; + that.total_in += len; + return len; + }, + // Flush as much pending output as possible. All deflate() output goes + // through this function so some applications may wish to modify it + // to avoid allocating a large strm->next_out buffer and copying into it. + // (See also read_buf()). + flush_pending: function () { + var that = this; + var len = that.dstate.pending; + if (len > that.avail_out) len = that.avail_out; + if (len === 0) return; // if (that.dstate.pending_buf.length <= that.dstate.pending_out || that.next_out.length <= that.next_out_index + // || that.dstate.pending_buf.length < (that.dstate.pending_out + len) || that.next_out.length < (that.next_out_index + + // len)) { + // console.log(that.dstate.pending_buf.length + ", " + that.dstate.pending_out + ", " + that.next_out.length + ", " + + // that.next_out_index + ", " + len); + // console.log("avail_out=" + that.avail_out); + // } + + that.next_out.set(that.dstate.pending_buf.subarray(that.dstate.pending_out, that.dstate.pending_out + len), that.next_out_index); + that.next_out_index += len; + that.dstate.pending_out += len; + that.total_out += len; + that.avail_out -= len; + that.dstate.pending -= len; + + if (that.dstate.pending === 0) { + that.dstate.pending_out = 0; + } + } + }; // Deflater + + function Deflater(options) { + var that = this; + var z = new ZStream(); + var bufsize = 512; + var flush = Z_NO_FLUSH; + var buf = new Uint8Array(bufsize); + var level = options ? options.level : Z_DEFAULT_COMPRESSION; + if (typeof level == "undefined") level = Z_DEFAULT_COMPRESSION; + z.deflateInit(level); + z.next_out = buf; + + that.append = function (data, onprogress) { + var err, + buffers = [], + lastIndex = 0, + bufferIndex = 0, + bufferSize = 0, + array; + if (!data.length) return; + z.next_in_index = 0; + z.next_in = data; + z.avail_in = data.length; + + do { + z.next_out_index = 0; + z.avail_out = bufsize; + err = z.deflate(flush); + if (err != Z_OK) throw new Error("deflating: " + z.msg); + if (z.next_out_index) if (z.next_out_index == bufsize) buffers.push(new Uint8Array(buf));else buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index))); + bufferSize += z.next_out_index; + + if (onprogress && z.next_in_index > 0 && z.next_in_index != lastIndex) { + onprogress(z.next_in_index); + lastIndex = z.next_in_index; + } + } while (z.avail_in > 0 || z.avail_out === 0); + + array = new Uint8Array(bufferSize); + buffers.forEach(function (chunk) { + array.set(chunk, bufferIndex); + bufferIndex += chunk.length; + }); + return array; + }; + + that.flush = function () { + var err, + buffers = [], + bufferIndex = 0, + bufferSize = 0, + array; + + do { + z.next_out_index = 0; + z.avail_out = bufsize; + err = z.deflate(Z_FINISH); + if (err != Z_STREAM_END && err != Z_OK) throw new Error("deflating: " + z.msg); + if (bufsize - z.avail_out > 0) buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index))); + bufferSize += z.next_out_index; + } while (z.avail_in > 0 || z.avail_out === 0); + + z.deflateEnd(); + array = new Uint8Array(bufferSize); + buffers.forEach(function (chunk) { + array.set(chunk, bufferIndex); + bufferIndex += chunk.length; + }); + return array; + }; + } // 'zip' may not be defined in z-worker and some tests + + + var env = global.zip || global; + env.Deflater = env._jzlib_Deflater = Deflater; + })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function("return this")()); // `self` is undefined in Firefox for Android content script context + // while `this` is nsIContentFrameMessageManager + // with an attribute `content` that corresponds to the window + + /** + * A class to parse color values + * @author Stoyan Stefanov + * @link http://www.phpied.com/rgb-color-parser-in-javascript/ + * @license Use it if you like it + */ + (function (global) { + + function RGBColor(color_string) { + this.ok = false; // strip any leading # + + if (color_string.charAt(0) == "#") { + // remove # if any + color_string = color_string.substr(1, 6); + } + + color_string = color_string.replace(/ /g, ""); + color_string = color_string.toLowerCase(); + var channels; // before getting into regexps, try simple matches + // and overwrite the input + + var simple_colors = { + aliceblue: "f0f8ff", + antiquewhite: "faebd7", + aqua: "00ffff", + aquamarine: "7fffd4", + azure: "f0ffff", + beige: "f5f5dc", + bisque: "ffe4c4", + black: "000000", + blanchedalmond: "ffebcd", + blue: "0000ff", + blueviolet: "8a2be2", + brown: "a52a2a", + burlywood: "deb887", + cadetblue: "5f9ea0", + chartreuse: "7fff00", + chocolate: "d2691e", + coral: "ff7f50", + cornflowerblue: "6495ed", + cornsilk: "fff8dc", + crimson: "dc143c", + cyan: "00ffff", + darkblue: "00008b", + darkcyan: "008b8b", + darkgoldenrod: "b8860b", + darkgray: "a9a9a9", + darkgreen: "006400", + darkkhaki: "bdb76b", + darkmagenta: "8b008b", + darkolivegreen: "556b2f", + darkorange: "ff8c00", + darkorchid: "9932cc", + darkred: "8b0000", + darksalmon: "e9967a", + darkseagreen: "8fbc8f", + darkslateblue: "483d8b", + darkslategray: "2f4f4f", + darkturquoise: "00ced1", + darkviolet: "9400d3", + deeppink: "ff1493", + deepskyblue: "00bfff", + dimgray: "696969", + dodgerblue: "1e90ff", + feldspar: "d19275", + firebrick: "b22222", + floralwhite: "fffaf0", + forestgreen: "228b22", + fuchsia: "ff00ff", + gainsboro: "dcdcdc", + ghostwhite: "f8f8ff", + gold: "ffd700", + goldenrod: "daa520", + gray: "808080", + green: "008000", + greenyellow: "adff2f", + honeydew: "f0fff0", + hotpink: "ff69b4", + indianred: "cd5c5c", + indigo: "4b0082", + ivory: "fffff0", + khaki: "f0e68c", + lavender: "e6e6fa", + lavenderblush: "fff0f5", + lawngreen: "7cfc00", + lemonchiffon: "fffacd", + lightblue: "add8e6", + lightcoral: "f08080", + lightcyan: "e0ffff", + lightgoldenrodyellow: "fafad2", + lightgrey: "d3d3d3", + lightgreen: "90ee90", + lightpink: "ffb6c1", + lightsalmon: "ffa07a", + lightseagreen: "20b2aa", + lightskyblue: "87cefa", + lightslateblue: "8470ff", + lightslategray: "778899", + lightsteelblue: "b0c4de", + lightyellow: "ffffe0", + lime: "00ff00", + limegreen: "32cd32", + linen: "faf0e6", + magenta: "ff00ff", + maroon: "800000", + mediumaquamarine: "66cdaa", + mediumblue: "0000cd", + mediumorchid: "ba55d3", + mediumpurple: "9370d8", + mediumseagreen: "3cb371", + mediumslateblue: "7b68ee", + mediumspringgreen: "00fa9a", + mediumturquoise: "48d1cc", + mediumvioletred: "c71585", + midnightblue: "191970", + mintcream: "f5fffa", + mistyrose: "ffe4e1", + moccasin: "ffe4b5", + navajowhite: "ffdead", + navy: "000080", + oldlace: "fdf5e6", + olive: "808000", + olivedrab: "6b8e23", + orange: "ffa500", + orangered: "ff4500", + orchid: "da70d6", + palegoldenrod: "eee8aa", + palegreen: "98fb98", + paleturquoise: "afeeee", + palevioletred: "d87093", + papayawhip: "ffefd5", + peachpuff: "ffdab9", + peru: "cd853f", + pink: "ffc0cb", + plum: "dda0dd", + powderblue: "b0e0e6", + purple: "800080", + red: "ff0000", + rosybrown: "bc8f8f", + royalblue: "4169e1", + saddlebrown: "8b4513", + salmon: "fa8072", + sandybrown: "f4a460", + seagreen: "2e8b57", + seashell: "fff5ee", + sienna: "a0522d", + silver: "c0c0c0", + skyblue: "87ceeb", + slateblue: "6a5acd", + slategray: "708090", + snow: "fffafa", + springgreen: "00ff7f", + steelblue: "4682b4", + tan: "d2b48c", + teal: "008080", + thistle: "d8bfd8", + tomato: "ff6347", + turquoise: "40e0d0", + violet: "ee82ee", + violetred: "d02090", + wheat: "f5deb3", + white: "ffffff", + whitesmoke: "f5f5f5", + yellow: "ffff00", + yellowgreen: "9acd32" + }; + + for (var key in simple_colors) { + if (color_string == key) { + color_string = simple_colors[key]; + } + } // emd of simple type-in colors + // array of color definition objects + + + var color_defs = [{ + re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, + example: ["rgb(123, 234, 45)", "rgb(255,234,245)"], + process: function (bits) { + return [parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3])]; + } + }, { + re: /^(\w{2})(\w{2})(\w{2})$/, + example: ["#00ff00", "336699"], + process: function (bits) { + return [parseInt(bits[1], 16), parseInt(bits[2], 16), parseInt(bits[3], 16)]; + } + }, { + re: /^(\w{1})(\w{1})(\w{1})$/, + example: ["#fb0", "f0f"], + process: function (bits) { + return [parseInt(bits[1] + bits[1], 16), parseInt(bits[2] + bits[2], 16), parseInt(bits[3] + bits[3], 16)]; + } + }]; // search through the definitions to find a match + + for (var i = 0; i < color_defs.length; i++) { + var re = color_defs[i].re; + var processor = color_defs[i].process; + var bits = re.exec(color_string); + + if (bits) { + channels = processor(bits); + this.r = channels[0]; + this.g = channels[1]; + this.b = channels[2]; + this.ok = true; + } + } // validate/cleanup values + + + this.r = this.r < 0 || isNaN(this.r) ? 0 : this.r > 255 ? 255 : this.r; + this.g = this.g < 0 || isNaN(this.g) ? 0 : this.g > 255 ? 255 : this.g; + this.b = this.b < 0 || isNaN(this.b) ? 0 : this.b > 255 ? 255 : this.b; // some getters + + this.toRGB = function () { + return "rgb(" + this.r + ", " + this.g + ", " + this.b + ")"; + }; + + this.toHex = function () { + var r = this.r.toString(16); + var g = this.g.toString(16); + var b = this.b.toString(16); + if (r.length == 1) r = "0" + r; + if (g.length == 1) g = "0" + g; + if (b.length == 1) b = "0" + b; + return "#" + r + g + b; + }; // help + + + this.getHelpXML = function () { + var examples = new Array(); // add regexps + + for (var i = 0; i < color_defs.length; i++) { + var example = color_defs[i].example; + + for (var j = 0; j < example.length; j++) { + examples[examples.length] = example[j]; + } + } // add type-in colors + + + for (var sc in simple_colors) { + examples[examples.length] = sc; + } + + var xml = document.createElement("ul"); + xml.setAttribute("id", "rgbcolor-examples"); + + for (var i = 0; i < examples.length; i++) { + try { + var list_item = document.createElement("li"); + var list_color = new RGBColor(examples[i]); + var example_div = document.createElement("div"); + example_div.style.cssText = "margin: 3px; " + "border: 1px solid black; " + "background:" + list_color.toHex() + "; " + "color:" + list_color.toHex(); + example_div.appendChild(document.createTextNode("test")); + var list_item_value = document.createTextNode(" " + examples[i] + " -> " + list_color.toRGB() + " -> " + list_color.toHex()); + list_item.appendChild(example_div); + list_item.appendChild(list_item_value); + xml.appendChild(list_item); + } catch (e) {} + } + + return xml; + }; + } + + global.RGBColor = RGBColor; + })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function("return this")()); // `self` is undefined in Firefox for Android content script context + // while `this` is nsIContentFrameMessageManager + // with an attribute `content` that corresponds to the window + + /************************************************ + * Title : custom font * + * Start Data : 2017. 01. 22. * + * Comment : TEXT API * + ************************************************/ + + /****************************** + * jsPDF extension API Design * + * ****************************/ + (function (jsPDF) { + + var PLUS = "+".charCodeAt(0); + var SLASH = "/".charCodeAt(0); + var NUMBER = "0".charCodeAt(0); + var LOWER = "a".charCodeAt(0); + var UPPER = "A".charCodeAt(0); + var PLUS_URL_SAFE = "-".charCodeAt(0); + var SLASH_URL_SAFE = "_".charCodeAt(0); + /*****************************************************************/ + + /* function : b64ToByteArray */ + + /* comment : Base64 encoded TTF file contents (b64) are decoded */ + + /* by Byte array and stored. */ + + /*****************************************************************/ + + var b64ToByteArray = function (b64) { + var i, j, l, tmp, placeHolders, arr; + + if (b64.length % 4 > 0) { + throw new Error("Invalid string. Length must be a multiple of 4"); + } // the number of equal signs (place holders) + // if there are two placeholders, than the two characters before it + // represent one byte + // if there is only one, then the three characters before it represent 2 bytes + // this is just a cheap hack to not do indexOf twice + + + var len = b64.length; + placeHolders = "=" === b64.charAt(len - 2) ? 2 : "=" === b64.charAt(len - 1) ? 1 : 0; // base64 is 4/3 + up to two characters of the original data + + arr = new Uint8Array(b64.length * 3 / 4 - placeHolders); // if there are placeholders, only get up to the last complete 4 chars + + l = placeHolders > 0 ? b64.length - 4 : b64.length; + var L = 0; + + function push(v) { + arr[L++] = v; + } + + for (i = 0, j = 0; i < l; i += 4, j += 3) { + tmp = decode(b64.charAt(i)) << 18 | decode(b64.charAt(i + 1)) << 12 | decode(b64.charAt(i + 2)) << 6 | decode(b64.charAt(i + 3)); + push((tmp & 0xff0000) >> 16); + push((tmp & 0xff00) >> 8); + push(tmp & 0xff); + } + + if (placeHolders === 2) { + tmp = decode(b64.charAt(i)) << 2 | decode(b64.charAt(i + 1)) >> 4; + push(tmp & 0xff); + } else if (placeHolders === 1) { + tmp = decode(b64.charAt(i)) << 10 | decode(b64.charAt(i + 1)) << 4 | decode(b64.charAt(i + 2)) >> 2; + push(tmp >> 8 & 0xff); + push(tmp & 0xff); + } + + return arr; + }; + /***************************************************************/ + + /* function : decode */ + + /* comment : Change the base64 encoded font's content to match */ + + /* the base64 index value. */ + + /***************************************************************/ + + + var decode = function (elt) { + var code = elt.charCodeAt(0); + if (code === PLUS || code === PLUS_URL_SAFE) return 62; // '+' + + if (code === SLASH || code === SLASH_URL_SAFE) return 63; // '/' + + if (code < NUMBER) return -1; //no match + + if (code < NUMBER + 10) return code - NUMBER + 26 + 26; + if (code < UPPER + 26) return code - UPPER; + if (code < LOWER + 26) return code - LOWER + 26; + }; + + jsPDF.API.TTFFont = function () { + /************************************************************************/ + + /* function : open */ + + /* comment : Decode the encoded ttf content and create a TTFFont object. */ + + /************************************************************************/ + TTFFont.open = function (filename, name, vfs, encoding) { + var contents; + + if (typeof vfs !== "string") { + throw new Error("Invalid argument supplied in TTFFont.open"); + } + + contents = b64ToByteArray(vfs); + return new TTFFont(contents, name, encoding); + }; + /***************************************************************/ + + /* function : TTFFont gernerator */ + + /* comment : Decode TTF contents are parsed, Data, */ + + /* Subset object is created, and registerTTF function is called.*/ + + /***************************************************************/ + + + function TTFFont(rawData, name, encoding) { + var data; + + this.rawData = rawData; + data = this.contents = new Data(rawData); + this.contents.pos = 4; + + if (data.readString(4) === "ttcf") { + if (!name) { + throw new Error("Must specify a font name for TTC files."); + } + throw new Error("Font " + name + " not found in TTC file."); + } else { + data.pos = 0; + this.parse(); + this.subset = new Subset(this); + this.registerTTF(); + } + } + /********************************************************/ + + /* function : parse */ + + /* comment : TTF Parses the file contents by each table.*/ + + /********************************************************/ + + + TTFFont.prototype.parse = function () { + this.directory = new Directory(this.contents); + this.head = new HeadTable(this); + this.name = new NameTable(this); + this.cmap = new CmapTable(this); + this.toUnicode = new Map(); + this.hhea = new HheaTable(this); + this.maxp = new MaxpTable(this); + this.hmtx = new HmtxTable(this); + this.post = new PostTable(this); + this.os2 = new OS2Table(this); + this.loca = new LocaTable(this); + this.glyf = new GlyfTable(this); + this.ascender = this.os2.exists && this.os2.ascender || this.hhea.ascender; + this.decender = this.os2.exists && this.os2.decender || this.hhea.decender; + this.lineGap = this.os2.exists && this.os2.lineGap || this.hhea.lineGap; + return this.bbox = [this.head.xMin, this.head.yMin, this.head.xMax, this.head.yMax]; + }; + /***************************************************************/ + + /* function : registerTTF */ + + /* comment : Get the value to assign pdf font descriptors. */ + + /***************************************************************/ + + + TTFFont.prototype.registerTTF = function () { + var e, hi, low, raw, _ref; + + this.scaleFactor = 1000.0 / this.head.unitsPerEm; + + this.bbox = function () { + var _i, _len, _ref, _results; + + _ref = this.bbox; + _results = []; + + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + e = _ref[_i]; + + _results.push(Math.round(e * this.scaleFactor)); + } + + return _results; + }.call(this); + + this.stemV = 0; + + if (this.post.exists) { + raw = this.post.italic_angle; + hi = raw >> 16; + low = raw & 0xff; + + if (hi & 0x8000 !== 0) { + hi = -((hi ^ 0xffff) + 1); + } + + this.italicAngle = +("" + hi + "." + low); + } else { + this.italicAngle = 0; + } + + this.ascender = Math.round(this.ascender * this.scaleFactor); + this.decender = Math.round(this.decender * this.scaleFactor); + this.lineGap = Math.round(this.lineGap * this.scaleFactor); + this.capHeight = this.os2.exists && this.os2.capHeight || this.ascender; + this.xHeight = this.os2.exists && this.os2.xHeight || 0; + this.familyClass = (this.os2.exists && this.os2.familyClass || 0) >> 8; + this.isSerif = (_ref = this.familyClass) === 1 || _ref === 2 || _ref === 3 || _ref === 4 || _ref === 5 || _ref === 7; + this.isScript = this.familyClass === 10; + this.flags = 0; + + if (this.post.isFixedPitch) { + this.flags |= 1 << 0; + } + + if (this.isSerif) { + this.flags |= 1 << 1; + } + + if (this.isScript) { + this.flags |= 1 << 3; + } + + if (this.italicAngle !== 0) { + this.flags |= 1 << 6; + } + + this.flags |= 1 << 5; + + if (!this.cmap.unicode) { + throw new Error("No unicode cmap for font"); + } + }; + + TTFFont.prototype.characterToGlyph = function (character) { + var _ref; + + return ((_ref = this.cmap.unicode) != null ? _ref.codeMap[character] : void 0) || 0; + }; + + TTFFont.prototype.widthOfGlyph = function (glyph) { + var scale; + scale = 1000.0 / this.head.unitsPerEm; + return this.hmtx.forGlyph(glyph).advance * scale; + }; + + TTFFont.prototype.widthOfString = function (string, size, charSpace) { + var charCode, i, scale, width, _i, _ref, charSpace; + + string = "" + string; + width = 0; + + for (i = _i = 0, _ref = string.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { + charCode = string.charCodeAt(i); + width += this.widthOfGlyph(this.characterToGlyph(charCode)) + charSpace * (1000 / size) || 0; + } + + scale = size / 1000; + return width * scale; + }; + + TTFFont.prototype.lineHeight = function (size, includeGap) { + var gap; + + if (includeGap == null) { + includeGap = false; + } + + gap = includeGap ? this.lineGap : 0; + return (this.ascender + gap - this.decender) / 1000 * size; + }; + + return TTFFont; + }(); + /************************************************************************************************/ + + /* function : Data */ + + /* comment : The ttf data decoded and stored in an array is read and written to the Data object.*/ + + /************************************************************************************************/ + + + var Data = function () { + function Data(data) { + this.data = data != null ? data : []; + this.pos = 0; + this.length = this.data.length; + } + + Data.prototype.readByte = function () { + return this.data[this.pos++]; + }; + + Data.prototype.writeByte = function (byte) { + return this.data[this.pos++] = byte; + }; + + Data.prototype.readUInt32 = function () { + var b1, b2, b3, b4; + b1 = this.readByte() * 0x1000000; + b2 = this.readByte() << 16; + b3 = this.readByte() << 8; + b4 = this.readByte(); + return b1 + b2 + b3 + b4; + }; + + Data.prototype.writeUInt32 = function (val) { + this.writeByte(val >>> 24 & 0xff); + this.writeByte(val >> 16 & 0xff); + this.writeByte(val >> 8 & 0xff); + return this.writeByte(val & 0xff); + }; + + Data.prototype.readInt32 = function () { + var int; + int = this.readUInt32(); + + if (int >= 0x80000000) { + return int - 0x100000000; + } else { + return int; + } + }; + + Data.prototype.writeInt32 = function (val) { + if (val < 0) { + val += 0x100000000; + } + + return this.writeUInt32(val); + }; + + Data.prototype.readUInt16 = function () { + var b1, b2; + b1 = this.readByte() << 8; + b2 = this.readByte(); + return b1 | b2; + }; + + Data.prototype.writeUInt16 = function (val) { + this.writeByte(val >> 8 & 0xff); + return this.writeByte(val & 0xff); + }; + + Data.prototype.readInt16 = function () { + var int; + int = this.readUInt16(); + + if (int >= 0x8000) { + return int - 0x10000; + } else { + return int; + } + }; + + Data.prototype.writeInt16 = function (val) { + if (val < 0) { + val += 0x10000; + } + + return this.writeUInt16(val); + }; + + Data.prototype.readString = function (length) { + var i, ret, _i; + + ret = []; + + for (i = _i = 0; 0 <= length ? _i < length : _i > length; i = 0 <= length ? ++_i : --_i) { + ret[i] = String.fromCharCode(this.readByte()); + } + + return ret.join(""); + }; + + Data.prototype.writeString = function (val) { + var i, _i, _ref, _results; + + _results = []; + + for (i = _i = 0, _ref = val.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { + _results.push(this.writeByte(val.charCodeAt(i))); + } + + return _results; + }; + /*Data.prototype.stringAt = function (pos, length) { + this.pos = pos; + return this.readString(length); + };*/ + + + Data.prototype.readShort = function () { + return this.readInt16(); + }; + + Data.prototype.writeShort = function (val) { + return this.writeInt16(val); + }; + + Data.prototype.readLongLong = function () { + var b1, b2, b3, b4, b5, b6, b7, b8; + b1 = this.readByte(); + b2 = this.readByte(); + b3 = this.readByte(); + b4 = this.readByte(); + b5 = this.readByte(); + b6 = this.readByte(); + b7 = this.readByte(); + b8 = this.readByte(); + + if (b1 & 0x80) { + return ((b1 ^ 0xff) * 0x100000000000000 + (b2 ^ 0xff) * 0x1000000000000 + (b3 ^ 0xff) * 0x10000000000 + (b4 ^ 0xff) * 0x100000000 + (b5 ^ 0xff) * 0x1000000 + (b6 ^ 0xff) * 0x10000 + (b7 ^ 0xff) * 0x100 + (b8 ^ 0xff) + 1) * -1; + } + + return b1 * 0x100000000000000 + b2 * 0x1000000000000 + b3 * 0x10000000000 + b4 * 0x100000000 + b5 * 0x1000000 + b6 * 0x10000 + b7 * 0x100 + b8; + }; + + Data.prototype.writeLongLong = function (val) { + var high, low; + high = Math.floor(val / 0x100000000); + low = val & 0xffffffff; + this.writeByte(high >> 24 & 0xff); + this.writeByte(high >> 16 & 0xff); + this.writeByte(high >> 8 & 0xff); + this.writeByte(high & 0xff); + this.writeByte(low >> 24 & 0xff); + this.writeByte(low >> 16 & 0xff); + this.writeByte(low >> 8 & 0xff); + return this.writeByte(low & 0xff); + }; + + Data.prototype.readInt = function () { + return this.readInt32(); + }; + + Data.prototype.writeInt = function (val) { + return this.writeInt32(val); + }; + /*Data.prototype.slice = function (start, end) { + return this.data.slice(start, end); + };*/ + + + Data.prototype.read = function (bytes) { + var buf, i, _i; + + buf = []; + + for (i = _i = 0; 0 <= bytes ? _i < bytes : _i > bytes; i = 0 <= bytes ? ++_i : --_i) { + buf.push(this.readByte()); + } + + return buf; + }; + + Data.prototype.write = function (bytes) { + var byte, _i, _len, _results; + + _results = []; + + for (_i = 0, _len = bytes.length; _i < _len; _i++) { + byte = bytes[_i]; + + _results.push(this.writeByte(byte)); + } + + return _results; + }; + + return Data; + }(); + + var Directory = function () { + var checksum; + /*****************************************************************************************************/ + + /* function : Directory generator */ + + /* comment : Initialize the offset, tag, length, and checksum for each table for the font to be used.*/ + + /*****************************************************************************************************/ + + function Directory(data) { + var entry, i, _i, _ref; + + this.scalarType = data.readInt(); + this.tableCount = data.readShort(); + this.searchRange = data.readShort(); + this.entrySelector = data.readShort(); + this.rangeShift = data.readShort(); + this.tables = {}; + + for (i = _i = 0, _ref = this.tableCount; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { + entry = { + tag: data.readString(4), + checksum: data.readInt(), + offset: data.readInt(), + length: data.readInt() + }; + this.tables[entry.tag] = entry; + } + } + /********************************************************************************************************/ + + /* function : encode */ + + /* comment : It encodes and stores the font table object and information used for the directory object. */ + + /********************************************************************************************************/ + + + Directory.prototype.encode = function (tables) { + var adjustment, directory, directoryLength, entrySelector, headOffset, log2, offset, rangeShift, searchRange, sum, table, tableCount, tableData, tag; + tableCount = Object.keys(tables).length; + log2 = Math.log(2); + searchRange = Math.floor(Math.log(tableCount) / log2) * 16; + entrySelector = Math.floor(searchRange / log2); + rangeShift = tableCount * 16 - searchRange; + directory = new Data(); + directory.writeInt(this.scalarType); + directory.writeShort(tableCount); + directory.writeShort(searchRange); + directory.writeShort(entrySelector); + directory.writeShort(rangeShift); + directoryLength = tableCount * 16; + offset = directory.pos + directoryLength; + headOffset = null; + tableData = []; + + for (tag in tables) { + table = tables[tag]; + directory.writeString(tag); + directory.writeInt(checksum(table)); + directory.writeInt(offset); + directory.writeInt(table.length); + tableData = tableData.concat(table); + + if (tag === "head") { + headOffset = offset; + } + + offset += table.length; + + while (offset % 4) { + tableData.push(0); + offset++; + } + } + + directory.write(tableData); + sum = checksum(directory.data); + adjustment = 0xb1b0afba - sum; + directory.pos = headOffset + 8; + directory.writeUInt32(adjustment); + return directory.data; + }; + /***************************************************************/ + + /* function : checksum */ + + /* comment : Duplicate the table for the tag. */ + + /***************************************************************/ + + + checksum = function (data) { + var i, sum, tmp, _i, _ref; + + data = __slice.call(data); + + while (data.length % 4) { + data.push(0); + } + + tmp = new Data(data); + sum = 0; + + for (i = _i = 0, _ref = data.length; _i < _ref; i = _i += 4) { + sum += tmp.readUInt32(); + } + + return sum & 0xffffffff; + }; + + return Directory; + }(); + + var Table, + __hasProp = {}.hasOwnProperty, + __extends = function (child, parent) { + for (var key in parent) { + if (__hasProp.call(parent, key)) child[key] = parent[key]; + } + + function ctor() { + this.constructor = child; + } + + ctor.prototype = parent.prototype; + child.prototype = new ctor(); + child.__super__ = parent.prototype; + return child; + }; + /***************************************************************/ + + /* function : Table */ + + /* comment : Save info for each table, and parse the table. */ + + /***************************************************************/ + + + Table = function () { + function Table(file) { + var info; + this.file = file; + info = this.file.directory.tables[this.tag]; + this.exists = !!info; + + if (info) { + this.offset = info.offset, this.length = info.length; + this.parse(this.file.contents); + } + } + + Table.prototype.parse = function () {}; + + Table.prototype.encode = function () {}; + + Table.prototype.raw = function () { + if (!this.exists) { + return null; + } + + this.file.contents.pos = this.offset; + return this.file.contents.read(this.length); + }; + + return Table; + }(); + + var HeadTable = function (_super) { + __extends(HeadTable, _super); + + function HeadTable() { + return HeadTable.__super__.constructor.apply(this, arguments); + } + + HeadTable.prototype.tag = "head"; + + HeadTable.prototype.parse = function (data) { + data.pos = this.offset; + this.version = data.readInt(); + this.revision = data.readInt(); + this.checkSumAdjustment = data.readInt(); + this.magicNumber = data.readInt(); + this.flags = data.readShort(); + this.unitsPerEm = data.readShort(); + this.created = data.readLongLong(); + this.modified = data.readLongLong(); + this.xMin = data.readShort(); + this.yMin = data.readShort(); + this.xMax = data.readShort(); + this.yMax = data.readShort(); + this.macStyle = data.readShort(); + this.lowestRecPPEM = data.readShort(); + this.fontDirectionHint = data.readShort(); + this.indexToLocFormat = data.readShort(); + return this.glyphDataFormat = data.readShort(); + }; + + HeadTable.prototype.encode = function (indexToLocFormat) { + var table; + table = new Data(); + table.writeInt(this.version); + table.writeInt(this.revision); + table.writeInt(this.checkSumAdjustment); + table.writeInt(this.magicNumber); + table.writeShort(this.flags); + table.writeShort(this.unitsPerEm); + table.writeLongLong(this.created); + table.writeLongLong(this.modified); + table.writeShort(this.xMin); + table.writeShort(this.yMin); + table.writeShort(this.xMax); + table.writeShort(this.yMax); + table.writeShort(this.macStyle); + table.writeShort(this.lowestRecPPEM); + table.writeShort(this.fontDirectionHint); + table.writeShort(indexToLocFormat); + table.writeShort(this.glyphDataFormat); + return table.data; + }; + + return HeadTable; + }(Table); + /************************************************************************************/ + + /* function : CmapEntry */ + + /* comment : Cmap Initializes and encodes object information (required by pdf spec).*/ + + /************************************************************************************/ + + + var CmapEntry = function () { + function CmapEntry(data, offset) { + var code, count, endCode, glyphId, glyphIds, i, idDelta, idRangeOffset, index, saveOffset, segCount, segCountX2, start, startCode, tail, _i, _j, _k, _len; + + this.platformID = data.readUInt16(); + this.encodingID = data.readShort(); + this.offset = offset + data.readInt(); + saveOffset = data.pos; + data.pos = this.offset; + this.format = data.readUInt16(); + this.length = data.readUInt16(); + this.language = data.readUInt16(); + this.isUnicode = this.platformID === 3 && this.encodingID === 1 && this.format === 4 || this.platformID === 0 && this.format === 4; + this.codeMap = {}; + + switch (this.format) { + case 0: + for (i = _i = 0; _i < 256; i = ++_i) { + this.codeMap[i] = data.readByte(); + } + + break; + + case 4: + segCountX2 = data.readUInt16(); + segCount = segCountX2 / 2; + data.pos += 6; + + endCode = function () { + var _j, _results; + + _results = []; + + for (i = _j = 0; 0 <= segCount ? _j < segCount : _j > segCount; i = 0 <= segCount ? ++_j : --_j) { + _results.push(data.readUInt16()); + } + + return _results; + }(); + + data.pos += 2; + + startCode = function () { + var _j, _results; + + _results = []; + + for (i = _j = 0; 0 <= segCount ? _j < segCount : _j > segCount; i = 0 <= segCount ? ++_j : --_j) { + _results.push(data.readUInt16()); + } + + return _results; + }(); + + idDelta = function () { + var _j, _results; + + _results = []; + + for (i = _j = 0; 0 <= segCount ? _j < segCount : _j > segCount; i = 0 <= segCount ? ++_j : --_j) { + _results.push(data.readUInt16()); + } + + return _results; + }(); + + idRangeOffset = function () { + var _j, _results; + + _results = []; + + for (i = _j = 0; 0 <= segCount ? _j < segCount : _j > segCount; i = 0 <= segCount ? ++_j : --_j) { + _results.push(data.readUInt16()); + } + + return _results; + }(); + + count = (this.length - data.pos + this.offset) / 2; + + glyphIds = function () { + var _j, _results; + + _results = []; + + for (i = _j = 0; 0 <= count ? _j < count : _j > count; i = 0 <= count ? ++_j : --_j) { + _results.push(data.readUInt16()); + } + + return _results; + }(); + + for (i = _j = 0, _len = endCode.length; _j < _len; i = ++_j) { + tail = endCode[i]; + start = startCode[i]; + + for (code = _k = start; start <= tail ? _k <= tail : _k >= tail; code = start <= tail ? ++_k : --_k) { + if (idRangeOffset[i] === 0) { + glyphId = code + idDelta[i]; + } else { + index = idRangeOffset[i] / 2 + (code - start) - (segCount - i); + glyphId = glyphIds[index] || 0; + + if (glyphId !== 0) { + glyphId += idDelta[i]; + } + } + + this.codeMap[code] = glyphId & 0xffff; + } + } + + } + + data.pos = saveOffset; + } + + CmapEntry.encode = function (charmap, encoding) { + var charMap, code, codeMap, codes, delta, deltas, diff, endCode, endCodes, entrySelector, glyphIDs, i, id, indexes, last, map, nextID, offset, old, rangeOffsets, rangeShift, result, searchRange, segCount, segCountX2, startCode, startCodes, startGlyph, subtable, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _len5, _len6, _len7, _m, _n, _name, _o, _p, _q; + + subtable = new Data(); + codes = Object.keys(charmap).sort(function (a, b) { + return a - b; + }); + + switch (encoding) { + case "macroman": + id = 0; + + indexes = function () { + var _i, _results; + + _results = []; + + for (i = _i = 0; _i < 256; i = ++_i) { + _results.push(0); + } + + return _results; + }(); + + map = { + 0: 0 + }; + codeMap = {}; + + for (_i = 0, _len = codes.length; _i < _len; _i++) { + code = codes[_i]; + + if (map[_name = charmap[code]] == null) { + map[_name] = ++id; + } + + codeMap[code] = { + old: charmap[code], + new: map[charmap[code]] + }; + indexes[code] = map[charmap[code]]; + } + + subtable.writeUInt16(1); + subtable.writeUInt16(0); + subtable.writeUInt32(12); + subtable.writeUInt16(0); + subtable.writeUInt16(262); + subtable.writeUInt16(0); + subtable.write(indexes); + return result = { + charMap: codeMap, + subtable: subtable.data, + maxGlyphID: id + 1 + }; + + case "unicode": + startCodes = []; + endCodes = []; + nextID = 0; + map = {}; + charMap = {}; + last = diff = null; + + for (_j = 0, _len1 = codes.length; _j < _len1; _j++) { + code = codes[_j]; + old = charmap[code]; + + if (map[old] == null) { + map[old] = ++nextID; + } + + charMap[code] = { + old: old, + new: map[old] + }; + delta = map[old] - code; + + if (last == null || delta !== diff) { + if (last) { + endCodes.push(last); + } + + startCodes.push(code); + diff = delta; + } + + last = code; + } + + if (last) { + endCodes.push(last); + } + + endCodes.push(0xffff); + startCodes.push(0xffff); + segCount = startCodes.length; + segCountX2 = segCount * 2; + searchRange = 2 * Math.pow(Math.log(segCount) / Math.LN2, 2); + entrySelector = Math.log(searchRange / 2) / Math.LN2; + rangeShift = 2 * segCount - searchRange; + deltas = []; + rangeOffsets = []; + glyphIDs = []; + + for (i = _k = 0, _len2 = startCodes.length; _k < _len2; i = ++_k) { + startCode = startCodes[i]; + endCode = endCodes[i]; + + if (startCode === 0xffff) { + deltas.push(0); + rangeOffsets.push(0); + break; + } + + startGlyph = charMap[startCode]["new"]; + + if (startCode - startGlyph >= 0x8000) { + deltas.push(0); + rangeOffsets.push(2 * (glyphIDs.length + segCount - i)); + + for (code = _l = startCode; startCode <= endCode ? _l <= endCode : _l >= endCode; code = startCode <= endCode ? ++_l : --_l) { + glyphIDs.push(charMap[code]["new"]); + } + } else { + deltas.push(startGlyph - startCode); + rangeOffsets.push(0); + } + } + + subtable.writeUInt16(3); + subtable.writeUInt16(1); + subtable.writeUInt32(12); + subtable.writeUInt16(4); + subtable.writeUInt16(16 + segCount * 8 + glyphIDs.length * 2); + subtable.writeUInt16(0); + subtable.writeUInt16(segCountX2); + subtable.writeUInt16(searchRange); + subtable.writeUInt16(entrySelector); + subtable.writeUInt16(rangeShift); + + for (_m = 0, _len3 = endCodes.length; _m < _len3; _m++) { + code = endCodes[_m]; + subtable.writeUInt16(code); + } + + subtable.writeUInt16(0); + + for (_n = 0, _len4 = startCodes.length; _n < _len4; _n++) { + code = startCodes[_n]; + subtable.writeUInt16(code); + } + + for (_o = 0, _len5 = deltas.length; _o < _len5; _o++) { + delta = deltas[_o]; + subtable.writeUInt16(delta); + } + + for (_p = 0, _len6 = rangeOffsets.length; _p < _len6; _p++) { + offset = rangeOffsets[_p]; + subtable.writeUInt16(offset); + } + + for (_q = 0, _len7 = glyphIDs.length; _q < _len7; _q++) { + id = glyphIDs[_q]; + subtable.writeUInt16(id); + } + + return result = { + charMap: charMap, + subtable: subtable.data, + maxGlyphID: nextID + 1 + }; + } + }; + + return CmapEntry; + }(); + + var CmapTable = function (_super) { + __extends(CmapTable, _super); + + function CmapTable() { + return CmapTable.__super__.constructor.apply(this, arguments); + } + + CmapTable.prototype.tag = "cmap"; + + CmapTable.prototype.parse = function (data) { + var entry, i, tableCount, _i; + + data.pos = this.offset; + this.version = data.readUInt16(); + tableCount = data.readUInt16(); + this.tables = []; + this.unicode = null; + + for (i = _i = 0; 0 <= tableCount ? _i < tableCount : _i > tableCount; i = 0 <= tableCount ? ++_i : --_i) { + entry = new CmapEntry(data, this.offset); + this.tables.push(entry); + + if (entry.isUnicode) { + if (this.unicode == null) { + this.unicode = entry; + } + } + } + + return true; + }; + /*************************************************************************/ + + /* function : encode */ + + /* comment : Encode the cmap table corresponding to the input character. */ + + /*************************************************************************/ + + + CmapTable.encode = function (charmap, encoding) { + var result, table; + + if (encoding == null) { + encoding = "macroman"; + } + + result = CmapEntry.encode(charmap, encoding); + table = new Data(); + table.writeUInt16(0); + table.writeUInt16(1); + result.table = table.data.concat(result.subtable); + return result; + }; + + return CmapTable; + }(Table); + + var HheaTable = function (_super) { + __extends(HheaTable, _super); + + function HheaTable() { + return HheaTable.__super__.constructor.apply(this, arguments); + } + + HheaTable.prototype.tag = "hhea"; + + HheaTable.prototype.parse = function (data) { + data.pos = this.offset; + this.version = data.readInt(); + this.ascender = data.readShort(); + this.decender = data.readShort(); + this.lineGap = data.readShort(); + this.advanceWidthMax = data.readShort(); + this.minLeftSideBearing = data.readShort(); + this.minRightSideBearing = data.readShort(); + this.xMaxExtent = data.readShort(); + this.caretSlopeRise = data.readShort(); + this.caretSlopeRun = data.readShort(); + this.caretOffset = data.readShort(); + data.pos += 4 * 2; + this.metricDataFormat = data.readShort(); + return this.numberOfMetrics = data.readUInt16(); + }; + /*HheaTable.prototype.encode = function (ids) { + var i, table, _i, _ref; + table = new Data; + table.writeInt(this.version); + table.writeShort(this.ascender); + table.writeShort(this.decender); + table.writeShort(this.lineGap); + table.writeShort(this.advanceWidthMax); + table.writeShort(this.minLeftSideBearing); + table.writeShort(this.minRightSideBearing); + table.writeShort(this.xMaxExtent); + table.writeShort(this.caretSlopeRise); + table.writeShort(this.caretSlopeRun); + table.writeShort(this.caretOffset); + for (i = _i = 0, _ref = 4 * 2; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { + table.writeByte(0); + } + table.writeShort(this.metricDataFormat); + table.writeUInt16(ids.length); + return table.data; + };*/ + + + return HheaTable; + }(Table); + + var OS2Table = function (_super) { + __extends(OS2Table, _super); + + function OS2Table() { + return OS2Table.__super__.constructor.apply(this, arguments); + } + + OS2Table.prototype.tag = "OS/2"; + + OS2Table.prototype.parse = function (data) { + var i; + data.pos = this.offset; + this.version = data.readUInt16(); + this.averageCharWidth = data.readShort(); + this.weightClass = data.readUInt16(); + this.widthClass = data.readUInt16(); + this.type = data.readShort(); + this.ySubscriptXSize = data.readShort(); + this.ySubscriptYSize = data.readShort(); + this.ySubscriptXOffset = data.readShort(); + this.ySubscriptYOffset = data.readShort(); + this.ySuperscriptXSize = data.readShort(); + this.ySuperscriptYSize = data.readShort(); + this.ySuperscriptXOffset = data.readShort(); + this.ySuperscriptYOffset = data.readShort(); + this.yStrikeoutSize = data.readShort(); + this.yStrikeoutPosition = data.readShort(); + this.familyClass = data.readShort(); + + this.panose = function () { + var _i, _results; + + _results = []; + + for (i = _i = 0; _i < 10; i = ++_i) { + _results.push(data.readByte()); + } + + return _results; + }(); + + this.charRange = function () { + var _i, _results; + + _results = []; + + for (i = _i = 0; _i < 4; i = ++_i) { + _results.push(data.readInt()); + } + + return _results; + }(); + + this.vendorID = data.readString(4); + this.selection = data.readShort(); + this.firstCharIndex = data.readShort(); + this.lastCharIndex = data.readShort(); + + if (this.version > 0) { + this.ascent = data.readShort(); + this.descent = data.readShort(); + this.lineGap = data.readShort(); + this.winAscent = data.readShort(); + this.winDescent = data.readShort(); + + this.codePageRange = function () { + var _i, _results; + + _results = []; + + for (i = _i = 0; _i < 2; i = ++_i) { + _results.push(data.readInt()); + } + + return _results; + }(); + + if (this.version > 1) { + this.xHeight = data.readShort(); + this.capHeight = data.readShort(); + this.defaultChar = data.readShort(); + this.breakChar = data.readShort(); + return this.maxContext = data.readShort(); + } + } + }; + /*OS2Table.prototype.encode = function () { + return this.raw(); + };*/ + + + return OS2Table; + }(Table); + + var PostTable = function (_super) { + + __extends(PostTable, _super); + + function PostTable() { + return PostTable.__super__.constructor.apply(this, arguments); + } + + PostTable.prototype.tag = "post"; + + PostTable.prototype.parse = function (data) { + var i, length, numberOfGlyphs, _i, _results; + + data.pos = this.offset; + this.format = data.readInt(); + this.italicAngle = data.readInt(); + this.underlinePosition = data.readShort(); + this.underlineThickness = data.readShort(); + this.isFixedPitch = data.readInt(); + this.minMemType42 = data.readInt(); + this.maxMemType42 = data.readInt(); + this.minMemType1 = data.readInt(); + this.maxMemType1 = data.readInt(); + + switch (this.format) { + case 0x00010000: + break; + + case 0x00020000: + numberOfGlyphs = data.readUInt16(); + this.glyphNameIndex = []; + + for (i = _i = 0; 0 <= numberOfGlyphs ? _i < numberOfGlyphs : _i > numberOfGlyphs; i = 0 <= numberOfGlyphs ? ++_i : --_i) { + this.glyphNameIndex.push(data.readUInt16()); + } + + this.names = []; + _results = []; + + while (data.pos < this.offset + this.length) { + length = data.readByte(); + + _results.push(this.names.push(data.readString(length))); + } + + return _results; + break; + + case 0x00025000: + numberOfGlyphs = data.readUInt16(); + return this.offsets = data.read(numberOfGlyphs); + + case 0x00030000: + break; + + case 0x00040000: + return this.map = function () { + var _j, _ref, _results1; + + _results1 = []; + + for (i = _j = 0, _ref = this.file.maxp.numGlyphs; 0 <= _ref ? _j < _ref : _j > _ref; i = 0 <= _ref ? ++_j : --_j) { + _results1.push(data.readUInt32()); + } + + return _results1; + }.call(this); + } + }; + return PostTable; + }(Table); + /*********************************************************************************************************/ + + /* function : NameEntry */ + + /* comment : Store copyright information, platformID, encodingID, and languageID in the NameEntry object.*/ + + /*********************************************************************************************************/ + + + var NameEntry = function () { + function NameEntry(raw, entry) { + this.raw = raw; + this.length = raw.length; + this.platformID = entry.platformID; + this.encodingID = entry.encodingID; + this.languageID = entry.languageID; + } + + return NameEntry; + }(); + + var NameTable = function (_super) { + + __extends(NameTable, _super); + + function NameTable() { + return NameTable.__super__.constructor.apply(this, arguments); + } + + NameTable.prototype.tag = "name"; + + NameTable.prototype.parse = function (data) { + var count, entries, entry, format, i, name, stringOffset, strings, text, _i, _j, _len, _name; + + data.pos = this.offset; + format = data.readShort(); + count = data.readShort(); + stringOffset = data.readShort(); + entries = []; + + for (i = _i = 0; 0 <= count ? _i < count : _i > count; i = 0 <= count ? ++_i : --_i) { + entries.push({ + platformID: data.readShort(), + encodingID: data.readShort(), + languageID: data.readShort(), + nameID: data.readShort(), + length: data.readShort(), + offset: this.offset + stringOffset + data.readShort() + }); + } + + strings = {}; + + for (i = _j = 0, _len = entries.length; _j < _len; i = ++_j) { + entry = entries[i]; + data.pos = entry.offset; + text = data.readString(entry.length); + name = new NameEntry(text, entry); + + if (strings[_name = entry.nameID] == null) { + strings[_name] = []; + } + + strings[entry.nameID].push(name); + } + + this.strings = strings; + this.copyright = strings[0]; + this.fontFamily = strings[1]; + this.fontSubfamily = strings[2]; + this.uniqueSubfamily = strings[3]; + this.fontName = strings[4]; + this.version = strings[5]; + + try { + this.postscriptName = strings[6][0].raw.replace(/[\x00-\x19\x80-\xff]/g, ""); + } catch (e) { + this.postscriptName = strings[4][0].raw.replace(/[\x00-\x19\x80-\xff]/g, ""); + } + + this.trademark = strings[7]; + this.manufacturer = strings[8]; + this.designer = strings[9]; + this.description = strings[10]; + this.vendorUrl = strings[11]; + this.designerUrl = strings[12]; + this.license = strings[13]; + this.licenseUrl = strings[14]; + this.preferredFamily = strings[15]; + this.preferredSubfamily = strings[17]; + this.compatibleFull = strings[18]; + return this.sampleText = strings[19]; + }; + /*NameTable.prototype.encode = function () { + var id, list, nameID, nameTable, postscriptName, strCount, strTable, string, strings, table, val, _i, _len, _ref; + strings = {}; + _ref = this.strings; + for (id in _ref) { + val = _ref[id]; + strings[id] = val; + } + postscriptName = new NameEntry("" + subsetTag + "+" + this.postscriptName, { + platformID: 1 + , encodingID: 0 + , languageID: 0 + }); + strings[6] = [postscriptName]; + subsetTag = successorOf(subsetTag); + strCount = 0; + for (id in strings) { + list = strings[id]; + if (list != null) { + strCount += list.length; + } + } + table = new Data; + strTable = new Data; + table.writeShort(0); + table.writeShort(strCount); + table.writeShort(6 + 12 * strCount); + for (nameID in strings) { + list = strings[nameID]; + if (list != null) { + for (_i = 0, _len = list.length; _i < _len; _i++) { + string = list[_i]; + table.writeShort(string.platformID); + table.writeShort(string.encodingID); + table.writeShort(string.languageID); + table.writeShort(nameID); + table.writeShort(string.length); + table.writeShort(strTable.pos); + strTable.writeString(string.raw); + } + } + } + return nameTable = { + postscriptName: postscriptName.raw + , table: table.data.concat(strTable.data) + }; + };*/ + + return NameTable; + }(Table); + + var MaxpTable = function (_super) { + __extends(MaxpTable, _super); + + function MaxpTable() { + return MaxpTable.__super__.constructor.apply(this, arguments); + } + + MaxpTable.prototype.tag = "maxp"; + + MaxpTable.prototype.parse = function (data) { + data.pos = this.offset; + this.version = data.readInt(); + this.numGlyphs = data.readUInt16(); + this.maxPoints = data.readUInt16(); + this.maxContours = data.readUInt16(); + this.maxCompositePoints = data.readUInt16(); + this.maxComponentContours = data.readUInt16(); + this.maxZones = data.readUInt16(); + this.maxTwilightPoints = data.readUInt16(); + this.maxStorage = data.readUInt16(); + this.maxFunctionDefs = data.readUInt16(); + this.maxInstructionDefs = data.readUInt16(); + this.maxStackElements = data.readUInt16(); + this.maxSizeOfInstructions = data.readUInt16(); + this.maxComponentElements = data.readUInt16(); + return this.maxComponentDepth = data.readUInt16(); + }; + /*MaxpTable.prototype.encode = function (ids) { + var table; + table = new Data; + table.writeInt(this.version); + table.writeUInt16(ids.length); + table.writeUInt16(this.maxPoints); + table.writeUInt16(this.maxContours); + table.writeUInt16(this.maxCompositePoints); + table.writeUInt16(this.maxComponentContours); + table.writeUInt16(this.maxZones); + table.writeUInt16(this.maxTwilightPoints); + table.writeUInt16(this.maxStorage); + table.writeUInt16(this.maxFunctionDefs); + table.writeUInt16(this.maxInstructionDefs); + table.writeUInt16(this.maxStackElements); + table.writeUInt16(this.maxSizeOfInstructions); + table.writeUInt16(this.maxComponentElements); + table.writeUInt16(this.maxComponentDepth); + return table.data; + };*/ + + + return MaxpTable; + }(Table); + + var HmtxTable = function (_super) { + __extends(HmtxTable, _super); + + function HmtxTable() { + return HmtxTable.__super__.constructor.apply(this, arguments); + } + + HmtxTable.prototype.tag = "hmtx"; + + HmtxTable.prototype.parse = function (data) { + var i, last, lsbCount, m, _i, _j, _ref, _results; + + data.pos = this.offset; + this.metrics = []; + + for (i = _i = 0, _ref = this.file.hhea.numberOfMetrics; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { + this.metrics.push({ + advance: data.readUInt16(), + lsb: data.readInt16() + }); + } + + lsbCount = this.file.maxp.numGlyphs - this.file.hhea.numberOfMetrics; + + this.leftSideBearings = function () { + var _j, _results; + + _results = []; + + for (i = _j = 0; 0 <= lsbCount ? _j < lsbCount : _j > lsbCount; i = 0 <= lsbCount ? ++_j : --_j) { + _results.push(data.readInt16()); + } + + return _results; + }(); + + this.widths = function () { + var _j, _len, _ref1, _results; + + _ref1 = this.metrics; + _results = []; + + for (_j = 0, _len = _ref1.length; _j < _len; _j++) { + m = _ref1[_j]; + + _results.push(m.advance); + } + + return _results; + }.call(this); + + last = this.widths[this.widths.length - 1]; + _results = []; + + for (i = _j = 0; 0 <= lsbCount ? _j < lsbCount : _j > lsbCount; i = 0 <= lsbCount ? ++_j : --_j) { + _results.push(this.widths.push(last)); + } + + return _results; + }; + /***************************************************************/ + + /* function : forGlyph */ + + /* comment : Returns the advance width and lsb for this glyph. */ + + /***************************************************************/ + + + HmtxTable.prototype.forGlyph = function (id) { + var metrics; + + if (id in this.metrics) { + return this.metrics[id]; + } + + return metrics = { + advance: this.metrics[this.metrics.length - 1].advance, + lsb: this.leftSideBearings[id - this.metrics.length] + }; + }; + /*HmtxTable.prototype.encode = function (mapping) { + var id, metric, table, _i, _len; + table = new Data; + for (_i = 0, _len = mapping.length; _i < _len; _i++) { + id = mapping[_i]; + metric = this.forGlyph(id); + table.writeUInt16(metric.advance); + table.writeUInt16(metric.lsb); + } + return table.data; + };*/ + + + return HmtxTable; + }(Table); + + var __slice = [].slice; + + var GlyfTable = function (_super) { + __extends(GlyfTable, _super); + + function GlyfTable() { + return GlyfTable.__super__.constructor.apply(this, arguments); + } + + GlyfTable.prototype.tag = "glyf"; + + GlyfTable.prototype.parse = function (data) { + return this.cache = {}; + }; + + GlyfTable.prototype.glyphFor = function (id) { + id = id; + var data, index, length, loca, numberOfContours, raw, xMax, xMin, yMax, yMin; + + if (id in this.cache) { + return this.cache[id]; + } + + loca = this.file.loca; + data = this.file.contents; + index = loca.indexOf(id); + length = loca.lengthOf(id); + + if (length === 0) { + return this.cache[id] = null; + } + + data.pos = this.offset + index; + raw = new Data(data.read(length)); + numberOfContours = raw.readShort(); + xMin = raw.readShort(); + yMin = raw.readShort(); + xMax = raw.readShort(); + yMax = raw.readShort(); + + if (numberOfContours === -1) { + this.cache[id] = new CompoundGlyph(raw, xMin, yMin, xMax, yMax); + } else { + this.cache[id] = new SimpleGlyph(raw, numberOfContours, xMin, yMin, xMax, yMax); + } + + return this.cache[id]; + }; + + GlyfTable.prototype.encode = function (glyphs, mapping, old2new) { + var glyph, id, offsets, table, _i, _len; + + table = []; + offsets = []; + + for (_i = 0, _len = mapping.length; _i < _len; _i++) { + id = mapping[_i]; + glyph = glyphs[id]; + offsets.push(table.length); + + if (glyph) { + table = table.concat(glyph.encode(old2new)); + } + } + + offsets.push(table.length); + return { + table: table, + offsets: offsets + }; + }; + + return GlyfTable; + }(Table); + + var SimpleGlyph = function () { + /**************************************************************************/ + + /* function : SimpleGlyph */ + + /* comment : Stores raw, xMin, yMin, xMax, and yMax values for this glyph.*/ + + /**************************************************************************/ + function SimpleGlyph(raw, numberOfContours, xMin, yMin, xMax, yMax) { + this.raw = raw; + this.numberOfContours = numberOfContours; + this.xMin = xMin; + this.yMin = yMin; + this.xMax = xMax; + this.yMax = yMax; + this.compound = false; + } + + SimpleGlyph.prototype.encode = function () { + return this.raw.data; + }; + + return SimpleGlyph; + }(); + + var CompoundGlyph = function () { + var ARG_1_AND_2_ARE_WORDS, MORE_COMPONENTS, WE_HAVE_AN_X_AND_Y_SCALE, WE_HAVE_A_SCALE, WE_HAVE_A_TWO_BY_TWO; + ARG_1_AND_2_ARE_WORDS = 0x0001; + WE_HAVE_A_SCALE = 0x0008; + MORE_COMPONENTS = 0x0020; + WE_HAVE_AN_X_AND_Y_SCALE = 0x0040; + WE_HAVE_A_TWO_BY_TWO = 0x0080; + /********************************************************************************************************************/ + + /* function : CompoundGlypg generator */ + + /* comment : It stores raw, xMin, yMin, xMax, yMax, glyph id, and glyph offset for the corresponding compound glyph.*/ + + /********************************************************************************************************************/ + + function CompoundGlyph(raw, xMin, yMin, xMax, yMax) { + var data, flags; + this.raw = raw; + this.xMin = xMin; + this.yMin = yMin; + this.xMax = xMax; + this.yMax = yMax; + this.compound = true; + this.glyphIDs = []; + this.glyphOffsets = []; + data = this.raw; + + while (true) { + flags = data.readShort(); + this.glyphOffsets.push(data.pos); + this.glyphIDs.push(data.readShort()); + + if (!(flags & MORE_COMPONENTS)) { + break; + } + + if (flags & ARG_1_AND_2_ARE_WORDS) { + data.pos += 4; + } else { + data.pos += 2; + } + + if (flags & WE_HAVE_A_TWO_BY_TWO) { + data.pos += 8; + } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) { + data.pos += 4; + } else if (flags & WE_HAVE_A_SCALE) { + data.pos += 2; + } + } + } + /****************************************************************************************************************/ + + /* function : CompoundGlypg encode */ + + /* comment : After creating a table for the characters you typed, you call directory.encode to encode the table.*/ + + /****************************************************************************************************************/ + + + CompoundGlyph.prototype.encode = function (mapping) { + var i, id, result, _i, _len, _ref; + + result = new Data(__slice.call(this.raw.data)); + _ref = this.glyphIDs; + + for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { + id = _ref[i]; + result.pos = this.glyphOffsets[i]; + } + + return result.data; + }; + + return CompoundGlyph; + }(); + + var LocaTable = function (_super) { + __extends(LocaTable, _super); + + function LocaTable() { + return LocaTable.__super__.constructor.apply(this, arguments); + } + + LocaTable.prototype.tag = "loca"; + + LocaTable.prototype.parse = function (data) { + var format, i; + data.pos = this.offset; + format = this.file.head.indexToLocFormat; + + if (format === 0) { + return this.offsets = function () { + var _i, _ref, _results; + + _results = []; + + for (i = _i = 0, _ref = this.length; _i < _ref; i = _i += 2) { + _results.push(data.readUInt16() * 2); + } + + return _results; + }.call(this); + } else { + return this.offsets = function () { + var _i, _ref, _results; + + _results = []; + + for (i = _i = 0, _ref = this.length; _i < _ref; i = _i += 4) { + _results.push(data.readUInt32()); + } + + return _results; + }.call(this); + } + }; + + LocaTable.prototype.indexOf = function (id) { + return this.offsets[id]; + }; + + LocaTable.prototype.lengthOf = function (id) { + return this.offsets[id + 1] - this.offsets[id]; + }; + + LocaTable.prototype.encode = function (offsets, activeGlyphs) { + var LocaTable = new Uint32Array(this.offsets.length); + var glyfPtr = 0; + var listGlyf = 0; + + for (var k = 0; k < LocaTable.length; ++k) { + LocaTable[k] = glyfPtr; + + if (listGlyf < activeGlyphs.length && activeGlyphs[listGlyf] == k) { + ++listGlyf; + LocaTable[k] = glyfPtr; + var start = this.offsets[k]; + var len = this.offsets[k + 1] - start; + + if (len > 0) { + glyfPtr += len; + } + } + } + + var newLocaTable = new Array(LocaTable.length * 4); + + for (var j = 0; j < LocaTable.length; ++j) { + newLocaTable[4 * j + 3] = LocaTable[j] & 0x000000ff; + newLocaTable[4 * j + 2] = (LocaTable[j] & 0x0000ff00) >> 8; + newLocaTable[4 * j + 1] = (LocaTable[j] & 0x00ff0000) >> 16; + newLocaTable[4 * j] = (LocaTable[j] & 0xff000000) >> 24; + } + + return newLocaTable; + }; + + return LocaTable; + }(Table); + /************************************************************************************/ + + /* function : invert */ + + /* comment : Change the object's (key: value) to create an object with (value: key).*/ + + /************************************************************************************/ + + + var invert = function (object) { + var key, ret, val; + ret = {}; + + for (key in object) { + val = object[key]; + ret[val] = key; + } + + return ret; + }; + /*var successorOf = function (input) { + var added, alphabet, carry, i, index, isUpperCase, last, length, next, result; + alphabet = 'abcdefghijklmnopqrstuvwxyz'; + length = alphabet.length; + result = input; + i = input.length; + while (i >= 0) { + last = input.charAt(--i); + if (isNaN(last)) { + index = alphabet.indexOf(last.toLowerCase()); + if (index === -1) { + next = last; + carry = true; + } + else { + next = alphabet.charAt((index + 1) % length); + isUpperCase = last === last.toUpperCase(); + if (isUpperCase) { + next = next.toUpperCase(); + } + carry = index + 1 >= length; + if (carry && i === 0) { + added = isUpperCase ? 'A' : 'a'; + result = added + next + result.slice(1); + break; + } + } + } + else { + next = +last + 1; + carry = next > 9; + if (carry) { + next = 0; + } + if (carry && i === 0) { + result = '1' + next + result.slice(1); + break; + } + } + result = result.slice(0, i) + next + result.slice(i + 1); + if (!carry) { + break; + } + } + return result; + };*/ + + + var Subset = function () { + function Subset(font) { + this.font = font; + this.subset = {}; + this.unicodes = {}; + this.next = 33; + } + /*Subset.prototype.use = function (character) { + var i, _i, _ref; + if (typeof character === 'string') { + for (i = _i = 0, _ref = character.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { + this.use(character.charCodeAt(i)); + } + return; + } + if (!this.unicodes[character]) { + this.subset[this.next] = character; + return this.unicodes[character] = this.next++; + } + };*/ + + /*Subset.prototype.encodeText = function (text) { + var char, i, string, _i, _ref; + string = ''; + for (i = _i = 0, _ref = text.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { + char = this.unicodes[text.charCodeAt(i)]; + string += String.fromCharCode(char); + } + return string; + };*/ + + /***************************************************************/ + + /* function : generateCmap */ + + /* comment : Returns the unicode cmap for this font. */ + + /***************************************************************/ + + + Subset.prototype.generateCmap = function () { + var mapping, roman, unicode, unicodeCmap, _ref; + + unicodeCmap = this.font.cmap.tables[0].codeMap; + mapping = {}; + _ref = this.subset; + + for (roman in _ref) { + unicode = _ref[roman]; + mapping[roman] = unicodeCmap[unicode]; + } + + return mapping; + }; + /*Subset.prototype.glyphIDs = function () { + var ret, roman, unicode, unicodeCmap, val, _ref; + unicodeCmap = this.font.cmap.tables[0].codeMap; + ret = [0]; + _ref = this.subset; + for (roman in _ref) { + unicode = _ref[roman]; + val = unicodeCmap[unicode]; + if ((val != null) && __indexOf.call(ret, val) < 0) { + ret.push(val); + } + } + return ret.sort(); + };*/ + + /******************************************************************/ + + /* function : glyphsFor */ + + /* comment : Returns simple glyph objects for the input character.*/ + + /******************************************************************/ + + + Subset.prototype.glyphsFor = function (glyphIDs) { + var additionalIDs, glyph, glyphs, id, _i, _len, _ref; + + glyphs = {}; + + for (_i = 0, _len = glyphIDs.length; _i < _len; _i++) { + id = glyphIDs[_i]; + glyphs[id] = this.font.glyf.glyphFor(id); + } + + additionalIDs = []; + + for (id in glyphs) { + glyph = glyphs[id]; + + if (glyph != null ? glyph.compound : void 0) { + additionalIDs.push.apply(additionalIDs, glyph.glyphIDs); + } + } + + if (additionalIDs.length > 0) { + _ref = this.glyphsFor(additionalIDs); + + for (id in _ref) { + glyph = _ref[id]; + glyphs[id] = glyph; + } + } + + return glyphs; + }; + /***************************************************************/ + + /* function : encode */ + + /* comment : Encode various tables for the characters you use. */ + + /***************************************************************/ + + + Subset.prototype.encode = function (glyID, indexToLocFormat) { + var cmap, code, glyf, glyphs, id, ids, loca, new2old, newIDs, nextGlyphID, old2new, oldID, oldIDs, tables, _ref; + + cmap = CmapTable.encode(this.generateCmap(), "unicode"); + glyphs = this.glyphsFor(glyID); + old2new = { + 0: 0 + }; + _ref = cmap.charMap; + + for (code in _ref) { + ids = _ref[code]; + old2new[ids.old] = ids["new"]; + } + + nextGlyphID = cmap.maxGlyphID; + + for (oldID in glyphs) { + if (!(oldID in old2new)) { + old2new[oldID] = nextGlyphID++; + } + } + + new2old = invert(old2new); + newIDs = Object.keys(new2old).sort(function (a, b) { + return a - b; + }); + + oldIDs = function () { + var _i, _len, _results; + + _results = []; + + for (_i = 0, _len = newIDs.length; _i < _len; _i++) { + id = newIDs[_i]; + + _results.push(new2old[id]); + } + + return _results; + }(); + + glyf = this.font.glyf.encode(glyphs, oldIDs, old2new); + loca = this.font.loca.encode(glyf.offsets, oldIDs); + tables = { + cmap: this.font.cmap.raw(), + glyf: glyf.table, + loca: loca, + hmtx: this.font.hmtx.raw(), + hhea: this.font.hhea.raw(), + maxp: this.font.maxp.raw(), + post: this.font.post.raw(), + name: this.font.name.raw(), + head: this.font.head.encode(indexToLocFormat) + }; + + if (this.font.os2.exists) { + tables["OS/2"] = this.font.os2.raw(); + } + + return this.font.directory.encode(tables); + }; + + return Subset; + }(); + + jsPDF.API.PDFObject = function () { + var pad; + + function PDFObject() {} + + pad = function (str, length) { + return (Array(length + 1).join("0") + str).slice(-length); + }; + /*****************************************************************************/ + + /* function : convert */ + + /* comment :Converts pdf tag's / FontBBox and array values in / W to strings */ + + /*****************************************************************************/ + + + PDFObject.convert = function (object) { + var e, items, key, out, val; + + if (Array.isArray(object)) { + items = function () { + var _i, _len, _results; + + _results = []; + + for (_i = 0, _len = object.length; _i < _len; _i++) { + e = object[_i]; + + _results.push(PDFObject.convert(e)); + } + + return _results; + }().join(" "); + + return "[" + items + "]"; + } else if (typeof object === "string") { + return "/" + object; + } else if (object != null ? object.isString : void 0) { + return "(" + object + ")"; + } else if (object instanceof Date) { + return "(D:" + pad(object.getUTCFullYear(), 4) + pad(object.getUTCMonth(), 2) + pad(object.getUTCDate(), 2) + pad(object.getUTCHours(), 2) + pad(object.getUTCMinutes(), 2) + pad(object.getUTCSeconds(), 2) + "Z)"; + } else if ({}.toString.call(object) === "[object Object]") { + out = ["<<"]; + + for (key in object) { + val = object[key]; + out.push("/" + key + " " + PDFObject.convert(val)); + } + + out.push(">>"); + return out.join("\n"); + } else { + return "" + object; + } + }; + + return PDFObject; + }(); + })(jsPDF); + + // Generated by CoffeeScript 1.4.0 + + /* + # PNG.js + # Copyright (c) 2011 Devon Govett + # MIT LICENSE + # + # + */ + (function (global) { + var PNG; + + PNG = function () { + var APNG_BLEND_OP_SOURCE, APNG_DISPOSE_OP_BACKGROUND, APNG_DISPOSE_OP_PREVIOUS, makeImage, scratchCanvas, scratchCtx; + + PNG.load = function (url, canvas, callback) { + var xhr; + + if (typeof canvas === "function") { + callback = canvas; + } + + xhr = new XMLHttpRequest(); + xhr.open("GET", url, true); + xhr.responseType = "arraybuffer"; + + xhr.onload = function () { + var data, png; + data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer); + png = new PNG(data); + + if (typeof (canvas != null ? canvas.getContext : void 0) === "function") { + png.render(canvas); + } + + return typeof callback === "function" ? callback(png) : void 0; + }; + + return xhr.send(null); + }; + APNG_DISPOSE_OP_BACKGROUND = 1; + APNG_DISPOSE_OP_PREVIOUS = 2; + APNG_BLEND_OP_SOURCE = 0; + + function PNG(data) { + var chunkSize, colors, palLen, delayDen, delayNum, frame, i, index, key, section, palShort, text, _i, _j, _ref; + + this.data = data; + this.pos = 8; + this.palette = []; + this.imgData = []; + this.transparency = {}; + this.animation = null; + this.text = {}; + frame = null; + + while (true) { + chunkSize = this.readUInt32(); + + section = function () { + var _i, _results; + + _results = []; + + for (i = _i = 0; _i < 4; i = ++_i) { + _results.push(String.fromCharCode(this.data[this.pos++])); + } + + return _results; + }.call(this).join(""); + + switch (section) { + case "IHDR": + this.width = this.readUInt32(); + this.height = this.readUInt32(); + this.bits = this.data[this.pos++]; + this.colorType = this.data[this.pos++]; + this.compressionMethod = this.data[this.pos++]; + this.filterMethod = this.data[this.pos++]; + this.interlaceMethod = this.data[this.pos++]; + break; + + case "acTL": + this.animation = { + numFrames: this.readUInt32(), + numPlays: this.readUInt32() || Infinity, + frames: [] + }; + break; + + case "PLTE": + this.palette = this.read(chunkSize); + break; + + case "fcTL": + if (frame) { + this.animation.frames.push(frame); + } + + this.pos += 4; + frame = { + width: this.readUInt32(), + height: this.readUInt32(), + xOffset: this.readUInt32(), + yOffset: this.readUInt32() + }; + delayNum = this.readUInt16(); + delayDen = this.readUInt16() || 100; + frame.delay = 1000 * delayNum / delayDen; + frame.disposeOp = this.data[this.pos++]; + frame.blendOp = this.data[this.pos++]; + frame.data = []; + break; + + case "IDAT": + case "fdAT": + if (section === "fdAT") { + this.pos += 4; + chunkSize -= 4; + } + + data = (frame != null ? frame.data : void 0) || this.imgData; + + for (i = _i = 0; 0 <= chunkSize ? _i < chunkSize : _i > chunkSize; i = 0 <= chunkSize ? ++_i : --_i) { + data.push(this.data[this.pos++]); + } + + break; + + case "tRNS": + this.transparency = {}; + + switch (this.colorType) { + case 3: + palLen = this.palette.length / 3; + this.transparency.indexed = this.read(chunkSize); + if (this.transparency.indexed.length > palLen) throw new Error("More transparent colors than palette size"); + /* + * According to the PNG spec trns should be increased to the same size as palette if shorter + */ + //palShort = 255 - this.transparency.indexed.length; + + palShort = palLen - this.transparency.indexed.length; + + if (palShort > 0) { + for (i = _j = 0; 0 <= palShort ? _j < palShort : _j > palShort; i = 0 <= palShort ? ++_j : --_j) { + this.transparency.indexed.push(255); + } + } + + break; + + case 0: + this.transparency.grayscale = this.read(chunkSize)[0]; + break; + + case 2: + this.transparency.rgb = this.read(chunkSize); + } + + break; + + case "tEXt": + text = this.read(chunkSize); + index = text.indexOf(0); + key = String.fromCharCode.apply(String, text.slice(0, index)); + this.text[key] = String.fromCharCode.apply(String, text.slice(index + 1)); + break; + + case "IEND": + if (frame) { + this.animation.frames.push(frame); + } + + this.colors = function () { + switch (this.colorType) { + case 0: + case 3: + case 4: + return 1; + + case 2: + case 6: + return 3; + } + }.call(this); + + this.hasAlphaChannel = (_ref = this.colorType) === 4 || _ref === 6; + colors = this.colors + (this.hasAlphaChannel ? 1 : 0); + this.pixelBitlength = this.bits * colors; + + this.colorSpace = function () { + switch (this.colors) { + case 1: + return "DeviceGray"; + + case 3: + return "DeviceRGB"; + } + }.call(this); + + this.imgData = new Uint8Array(this.imgData); + return; + + default: + this.pos += chunkSize; + } + + this.pos += 4; + + if (this.pos > this.data.length) { + throw new Error("Incomplete or corrupt PNG file"); + } + } + + return; + } + + PNG.prototype.read = function (bytes) { + var i, _i, _results; + + _results = []; + + for (i = _i = 0; 0 <= bytes ? _i < bytes : _i > bytes; i = 0 <= bytes ? ++_i : --_i) { + _results.push(this.data[this.pos++]); + } + + return _results; + }; + + PNG.prototype.readUInt32 = function () { + var b1, b2, b3, b4; + b1 = this.data[this.pos++] << 24; + b2 = this.data[this.pos++] << 16; + b3 = this.data[this.pos++] << 8; + b4 = this.data[this.pos++]; + return b1 | b2 | b3 | b4; + }; + + PNG.prototype.readUInt16 = function () { + var b1, b2; + b1 = this.data[this.pos++] << 8; + b2 = this.data[this.pos++]; + return b1 | b2; + }; + + PNG.prototype.decodePixels = function (data) { + var pixelBytes = this.pixelBitlength / 8; + var fullPixels = new Uint8Array(this.width * this.height * pixelBytes); + var pos = 0; + + var _this = this; + + if (data == null) { + data = this.imgData; + } + + if (data.length === 0) { + return new Uint8Array(0); + } + + data = new FlateStream(data); + data = data.getBytes(); + + function pass(x0, y0, dx, dy) { + var abyte, c, col, i, left, length, p, pa, paeth, pb, pc, pixels, row, scanlineLength, upper, upperLeft, _i, _j, _k, _l, _m; + + var w = Math.ceil((_this.width - x0) / dx), + h = Math.ceil((_this.height - y0) / dy); + var isFull = _this.width == w && _this.height == h; + scanlineLength = pixelBytes * w; + pixels = isFull ? fullPixels : new Uint8Array(scanlineLength * h); + length = data.length; + row = 0; + c = 0; + + while (row < h && pos < length) { + switch (data[pos++]) { + case 0: + for (i = _i = 0; _i < scanlineLength; i = _i += 1) { + pixels[c++] = data[pos++]; + } + + break; + + case 1: + for (i = _j = 0; _j < scanlineLength; i = _j += 1) { + abyte = data[pos++]; + left = i < pixelBytes ? 0 : pixels[c - pixelBytes]; + pixels[c++] = (abyte + left) % 256; + } + + break; + + case 2: + for (i = _k = 0; _k < scanlineLength; i = _k += 1) { + abyte = data[pos++]; + col = (i - i % pixelBytes) / pixelBytes; + upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + i % pixelBytes]; + pixels[c++] = (upper + abyte) % 256; + } + + break; + + case 3: + for (i = _l = 0; _l < scanlineLength; i = _l += 1) { + abyte = data[pos++]; + col = (i - i % pixelBytes) / pixelBytes; + left = i < pixelBytes ? 0 : pixels[c - pixelBytes]; + upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + i % pixelBytes]; + pixels[c++] = (abyte + Math.floor((left + upper) / 2)) % 256; + } + + break; + + case 4: + for (i = _m = 0; _m < scanlineLength; i = _m += 1) { + abyte = data[pos++]; + col = (i - i % pixelBytes) / pixelBytes; + left = i < pixelBytes ? 0 : pixels[c - pixelBytes]; + + if (row === 0) { + upper = upperLeft = 0; + } else { + upper = pixels[(row - 1) * scanlineLength + col * pixelBytes + i % pixelBytes]; + upperLeft = col && pixels[(row - 1) * scanlineLength + (col - 1) * pixelBytes + i % pixelBytes]; + } + + p = left + upper - upperLeft; + pa = Math.abs(p - left); + pb = Math.abs(p - upper); + pc = Math.abs(p - upperLeft); + + if (pa <= pb && pa <= pc) { + paeth = left; + } else if (pb <= pc) { + paeth = upper; + } else { + paeth = upperLeft; + } + + pixels[c++] = (abyte + paeth) % 256; + } + + break; + + default: + throw new Error("Invalid filter algorithm: " + data[pos - 1]); + } + + if (!isFull) { + var fullPos = ((y0 + row * dy) * _this.width + x0) * pixelBytes; + var partPos = row * scanlineLength; + + for (i = 0; i < w; i += 1) { + for (var j = 0; j < pixelBytes; j += 1) fullPixels[fullPos++] = pixels[partPos++]; + + fullPos += (dx - 1) * pixelBytes; + } + } + + row++; + } + } + + if (_this.interlaceMethod == 1) { + /* + 1 6 4 6 2 6 4 6 + 7 7 7 7 7 7 7 7 + 5 6 5 6 5 6 5 6 + 7 7 7 7 7 7 7 7 + 3 6 4 6 3 6 4 6 + 7 7 7 7 7 7 7 7 + 5 6 5 6 5 6 5 6 + 7 7 7 7 7 7 7 7 + */ + pass(0, 0, 8, 8); // 1 + + /* NOTE these seem to follow the pattern: + * pass(x, 0, 2*x, 2*x); + * pass(0, x, x, 2*x); + * with x being 4, 2, 1. + */ + + pass(4, 0, 8, 8); // 2 + + pass(0, 4, 4, 8); // 3 + + pass(2, 0, 4, 4); // 4 + + pass(0, 2, 2, 4); // 5 + + pass(1, 0, 2, 2); // 6 + + pass(0, 1, 1, 2); // 7 + } else { + pass(0, 0, 1, 1); + } + + return fullPixels; + }; + + PNG.prototype.decodePalette = function () { + var c, i, length, palette, pos, ret, transparency, _i, _ref, _ref1; + + palette = this.palette; + transparency = this.transparency.indexed || []; + ret = new Uint8Array((transparency.length || 0) + palette.length); + pos = 0; + length = palette.length; + c = 0; + + for (i = _i = 0, _ref = palette.length; _i < _ref; i = _i += 3) { + ret[pos++] = palette[i]; + ret[pos++] = palette[i + 1]; + ret[pos++] = palette[i + 2]; + ret[pos++] = (_ref1 = transparency[c++]) != null ? _ref1 : 255; + } + + return ret; + }; + + PNG.prototype.copyToImageData = function (imageData, pixels) { + var alpha, colors, data, i, input, j, k, length, palette, v, _ref; + + colors = this.colors; + palette = null; + alpha = this.hasAlphaChannel; + + if (this.palette.length) { + palette = (_ref = this._decodedPalette) != null ? _ref : this._decodedPalette = this.decodePalette(); + colors = 4; + alpha = true; + } + + data = imageData.data || imageData; + length = data.length; + input = palette || pixels; + i = j = 0; + + if (colors === 1) { + while (i < length) { + k = palette ? pixels[i / 4] * 4 : j; + v = input[k++]; + data[i++] = v; + data[i++] = v; + data[i++] = v; + data[i++] = alpha ? input[k++] : 255; + j = k; + } + } else { + while (i < length) { + k = palette ? pixels[i / 4] * 4 : j; + data[i++] = input[k++]; + data[i++] = input[k++]; + data[i++] = input[k++]; + data[i++] = alpha ? input[k++] : 255; + j = k; + } + } + }; + + PNG.prototype.decode = function () { + var ret; + ret = new Uint8Array(this.width * this.height * 4); + this.copyToImageData(ret, this.decodePixels()); + return ret; + }; + + try { + scratchCanvas = global.document.createElement("canvas"); + scratchCtx = scratchCanvas.getContext("2d"); + } catch (e) { + return -1; + } + + makeImage = function (imageData) { + var img; + scratchCtx.width = imageData.width; + scratchCtx.height = imageData.height; + scratchCtx.clearRect(0, 0, imageData.width, imageData.height); + scratchCtx.putImageData(imageData, 0, 0); + img = new Image(); + img.src = scratchCanvas.toDataURL(); + return img; + }; + + PNG.prototype.decodeFrames = function (ctx) { + var frame, i, imageData, pixels, _i, _len, _ref, _results; + + if (!this.animation) { + return; + } + + _ref = this.animation.frames; + _results = []; + + for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { + frame = _ref[i]; + imageData = ctx.createImageData(frame.width, frame.height); + pixels = this.decodePixels(new Uint8Array(frame.data)); + this.copyToImageData(imageData, pixels); + frame.imageData = imageData; + + _results.push(frame.image = makeImage(imageData)); + } + + return _results; + }; + + PNG.prototype.renderFrame = function (ctx, number) { + var frame, frames, prev; + frames = this.animation.frames; + frame = frames[number]; + prev = frames[number - 1]; + + if (number === 0) { + ctx.clearRect(0, 0, this.width, this.height); + } + + if ((prev != null ? prev.disposeOp : void 0) === APNG_DISPOSE_OP_BACKGROUND) { + ctx.clearRect(prev.xOffset, prev.yOffset, prev.width, prev.height); + } else if ((prev != null ? prev.disposeOp : void 0) === APNG_DISPOSE_OP_PREVIOUS) { + ctx.putImageData(prev.imageData, prev.xOffset, prev.yOffset); + } + + if (frame.blendOp === APNG_BLEND_OP_SOURCE) { + ctx.clearRect(frame.xOffset, frame.yOffset, frame.width, frame.height); + } + + return ctx.drawImage(frame.image, frame.xOffset, frame.yOffset); + }; + + PNG.prototype.animate = function (ctx) { + var doFrame, + frameNumber, + frames, + numFrames, + numPlays, + _ref, + _this = this; + + frameNumber = 0; + _ref = this.animation, numFrames = _ref.numFrames, frames = _ref.frames, numPlays = _ref.numPlays; + return (doFrame = function () { + var f, frame; + f = frameNumber++ % numFrames; + frame = frames[f]; + + _this.renderFrame(ctx, f); + + if (numFrames > 1 && frameNumber / numFrames < numPlays) { + return _this.animation._timeout = setTimeout(doFrame, frame.delay); + } + })(); + }; + + PNG.prototype.stopAnimation = function () { + var _ref; + + return clearTimeout((_ref = this.animation) != null ? _ref._timeout : void 0); + }; + + PNG.prototype.render = function (canvas) { + var ctx, data; + + if (canvas._png) { + canvas._png.stopAnimation(); + } + + canvas._png = this; + canvas.width = this.width; + canvas.height = this.height; + ctx = canvas.getContext("2d"); + + if (this.animation) { + this.decodeFrames(ctx); + return this.animate(ctx); + } else { + data = ctx.createImageData(this.width, this.height); + this.copyToImageData(data, this.decodePixels()); + return ctx.putImageData(data, 0, 0); + } + }; + + return PNG; + }(); + + global.PNG = PNG; + })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function("return this")()); // `self` is undefined in Firefox for Android content script context + // while `this` is nsIContentFrameMessageManager + // with an attribute `content` that corresponds to the window + + /* + * Extracted from pdf.js + * https://github.com/andreasgal/pdf.js + * + * Copyright (c) 2011 Mozilla Foundation + * + * Contributors: Andreas Gal + * Chris G Jones + * Shaon Barman + * Vivien Nicolas <21@vingtetun.org> + * Justin D'Arcangelo + * Yury Delendik + * + * + */ + var DecodeStream = function () { + function constructor() { + this.pos = 0; + this.bufferLength = 0; + this.eof = false; + this.buffer = null; + } + + constructor.prototype = { + ensureBuffer: function decodestream_ensureBuffer(requested) { + var buffer = this.buffer; + var current = buffer ? buffer.byteLength : 0; + if (requested < current) return buffer; + var size = 512; + + while (size < requested) size <<= 1; + + var buffer2 = new Uint8Array(size); + + for (var i = 0; i < current; ++i) buffer2[i] = buffer[i]; + + return this.buffer = buffer2; + }, + getByte: function decodestream_getByte() { + var pos = this.pos; + + while (this.bufferLength <= pos) { + if (this.eof) return null; + this.readBlock(); + } + + return this.buffer[this.pos++]; + }, + getBytes: function decodestream_getBytes(length) { + var pos = this.pos; + + if (length) { + this.ensureBuffer(pos + length); + var end = pos + length; + + while (!this.eof && this.bufferLength < end) this.readBlock(); + + var bufEnd = this.bufferLength; + if (end > bufEnd) end = bufEnd; + } else { + while (!this.eof) this.readBlock(); + + var end = this.bufferLength; + } + + this.pos = end; + return this.buffer.subarray(pos, end); + }, + lookChar: function decodestream_lookChar() { + var pos = this.pos; + + while (this.bufferLength <= pos) { + if (this.eof) return null; + this.readBlock(); + } + + return String.fromCharCode(this.buffer[this.pos]); + }, + getChar: function decodestream_getChar() { + var pos = this.pos; + + while (this.bufferLength <= pos) { + if (this.eof) return null; + this.readBlock(); + } + + return String.fromCharCode(this.buffer[this.pos++]); + }, + makeSubStream: function decodestream_makeSubstream(start, length, dict) { + var end = start + length; + + while (this.bufferLength <= end && !this.eof) this.readBlock(); + + return new Stream(this.buffer, start, length, dict); + }, + skip: function decodestream_skip(n) { + if (!n) n = 1; + this.pos += n; + }, + reset: function decodestream_reset() { + this.pos = 0; + } + }; + return constructor; + }(); + + var FlateStream = function () { + if (typeof Uint32Array === "undefined") { + return undefined; + } + + var codeLenCodeMap = new Uint32Array([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]); + var lengthDecode = new Uint32Array([0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a, 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f, 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073, 0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102]); + var distDecode = new Uint32Array([0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d, 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1, 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01, 0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001]); + var fixedLitCodeTab = [new Uint32Array([0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0, 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0, 0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80078, 0x80038, 0x900d0, 0x7010c, 0x80068, 0x80028, 0x900b0, 0x80008, 0x80088, 0x80048, 0x900f0, 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8, 0x7010a, 0x80064, 0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8, 0x70106, 0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8, 0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c, 0x900f8, 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c4, 0x70109, 0x80062, 0x80022, 0x900a4, 0x80002, 0x80082, 0x80042, 0x900e4, 0x70105, 0x8005a, 0x8001a, 0x90094, 0x70115, 0x8007a, 0x8003a, 0x900d4, 0x7010d, 0x8006a, 0x8002a, 0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4, 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc, 0x7010b, 0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec, 0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e, 0x900dc, 0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e, 0x8004e, 0x900fc, 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c2, 0x70108, 0x80061, 0x80021, 0x900a2, 0x80001, 0x80081, 0x80041, 0x900e2, 0x70104, 0x80059, 0x80019, 0x90092, 0x70114, 0x80079, 0x80039, 0x900d2, 0x7010c, 0x80069, 0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2, 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca, 0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045, 0x900ea, 0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d, 0x8003d, 0x900da, 0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d, 0x8008d, 0x8004d, 0x900fa, 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c6, 0x70109, 0x80063, 0x80023, 0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6, 0x70105, 0x8005b, 0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6, 0x7010d, 0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 0x900f6, 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900ce, 0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087, 0x80047, 0x900ee, 0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117, 0x8007f, 0x8003f, 0x900de, 0x7010f, 0x8006f, 0x8002f, 0x900be, 0x8000f, 0x8008f, 0x8004f, 0x900fe, 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c1, 0x70108, 0x80060, 0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1, 0x70104, 0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1, 0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048, 0x900f1, 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c9, 0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004, 0x80084, 0x80044, 0x900e9, 0x70106, 0x8005c, 0x8001c, 0x90099, 0x70116, 0x8007c, 0x8003c, 0x900d9, 0x7010e, 0x8006c, 0x8002c, 0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9, 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5, 0x70109, 0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5, 0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a, 0x900d5, 0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a, 0x8004a, 0x900f5, 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cd, 0x7010b, 0x80066, 0x80026, 0x900ad, 0x80006, 0x80086, 0x80046, 0x900ed, 0x70107, 0x8005e, 0x8001e, 0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd, 0x7010f, 0x8006e, 0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd, 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3, 0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041, 0x900e3, 0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079, 0x80039, 0x900d3, 0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009, 0x80089, 0x80049, 0x900f3, 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900cb, 0x7010a, 0x80065, 0x80025, 0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb, 0x70106, 0x8005d, 0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db, 0x7010e, 0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb, 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c7, 0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083, 0x80043, 0x900e7, 0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115, 0x8007b, 0x8003b, 0x900d7, 0x7010d, 0x8006b, 0x8002b, 0x900b7, 0x8000b, 0x8008b, 0x8004b, 0x900f7, 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf, 0x7010b, 0x80067, 0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef, 0x70107, 0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df, 0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f, 0x900ff]), 9]; + var fixedDistCodeTab = [new Uint32Array([0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c, 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000, 0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d, 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000]), 5]; + + function error(e) { + throw new Error(e); + } + + function constructor(bytes) { + //var bytes = stream.getBytes(); + var bytesPos = 0; + var cmf = bytes[bytesPos++]; + var flg = bytes[bytesPos++]; + if (cmf == -1 || flg == -1) error("Invalid header in flate stream"); + if ((cmf & 0x0f) != 0x08) error("Unknown compression method in flate stream"); + if (((cmf << 8) + flg) % 31 != 0) error("Bad FCHECK in flate stream"); + if (flg & 0x20) error("FDICT bit set in flate stream"); + this.bytes = bytes; + this.bytesPos = bytesPos; + this.codeSize = 0; + this.codeBuf = 0; + DecodeStream.call(this); + } + + constructor.prototype = Object.create(DecodeStream.prototype); + + constructor.prototype.getBits = function (bits) { + var codeSize = this.codeSize; + var codeBuf = this.codeBuf; + var bytes = this.bytes; + var bytesPos = this.bytesPos; + var b; + + while (codeSize < bits) { + if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad encoding in flate stream"); + codeBuf |= b << codeSize; + codeSize += 8; + } + + b = codeBuf & (1 << bits) - 1; + this.codeBuf = codeBuf >> bits; + this.codeSize = codeSize -= bits; + this.bytesPos = bytesPos; + return b; + }; + + constructor.prototype.getCode = function (table) { + var codes = table[0]; + var maxLen = table[1]; + var codeSize = this.codeSize; + var codeBuf = this.codeBuf; + var bytes = this.bytes; + var bytesPos = this.bytesPos; + + while (codeSize < maxLen) { + var b; + if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad encoding in flate stream"); + codeBuf |= b << codeSize; + codeSize += 8; + } + + var code = codes[codeBuf & (1 << maxLen) - 1]; + var codeLen = code >> 16; + var codeVal = code & 0xffff; + if (codeSize == 0 || codeSize < codeLen || codeLen == 0) error("Bad encoding in flate stream"); + this.codeBuf = codeBuf >> codeLen; + this.codeSize = codeSize - codeLen; + this.bytesPos = bytesPos; + return codeVal; + }; + + constructor.prototype.generateHuffmanTable = function (lengths) { + var n = lengths.length; // find max code length + + var maxLen = 0; + + for (var i = 0; i < n; ++i) { + if (lengths[i] > maxLen) maxLen = lengths[i]; + } // build the table + + + var size = 1 << maxLen; + var codes = new Uint32Array(size); + + for (var len = 1, code = 0, skip = 2; len <= maxLen; ++len, code <<= 1, skip <<= 1) { + for (var val = 0; val < n; ++val) { + if (lengths[val] == len) { + // bit-reverse the code + var code2 = 0; + var t = code; + + for (var i = 0; i < len; ++i) { + code2 = code2 << 1 | t & 1; + t >>= 1; + } // fill the table entries + + + for (var i = code2; i < size; i += skip) codes[i] = len << 16 | val; + + ++code; + } + } + } + + return [codes, maxLen]; + }; + + constructor.prototype.readBlock = function () { + function repeat(stream, array, len, offset, what) { + var repeat = stream.getBits(len) + offset; + + while (repeat-- > 0) array[i++] = what; + } // read block header + + + var hdr = this.getBits(3); + if (hdr & 1) this.eof = true; + hdr >>= 1; + + if (hdr == 0) { + // uncompressed block + var bytes = this.bytes; + var bytesPos = this.bytesPos; + var b; + if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad block header in flate stream"); + var blockLen = b; + if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad block header in flate stream"); + blockLen |= b << 8; + if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad block header in flate stream"); + var check = b; + if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad block header in flate stream"); + check |= b << 8; + if (check != (~blockLen & 0xffff)) error("Bad uncompressed block length in flate stream"); + this.codeBuf = 0; + this.codeSize = 0; + var bufferLength = this.bufferLength; + var buffer = this.ensureBuffer(bufferLength + blockLen); + var end = bufferLength + blockLen; + this.bufferLength = end; + + for (var n = bufferLength; n < end; ++n) { + if (typeof (b = bytes[bytesPos++]) == "undefined") { + this.eof = true; + break; + } + + buffer[n] = b; + } + + this.bytesPos = bytesPos; + return; + } + + var litCodeTable; + var distCodeTable; + + if (hdr == 1) { + // compressed block, fixed codes + litCodeTable = fixedLitCodeTab; + distCodeTable = fixedDistCodeTab; + } else if (hdr == 2) { + // compressed block, dynamic codes + var numLitCodes = this.getBits(5) + 257; + var numDistCodes = this.getBits(5) + 1; + var numCodeLenCodes = this.getBits(4) + 4; // build the code lengths code table + + var codeLenCodeLengths = Array(codeLenCodeMap.length); + var i = 0; + + while (i < numCodeLenCodes) codeLenCodeLengths[codeLenCodeMap[i++]] = this.getBits(3); + + var codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths); // build the literal and distance code tables + + var len = 0; + var i = 0; + var codes = numLitCodes + numDistCodes; + var codeLengths = new Array(codes); + + while (i < codes) { + var code = this.getCode(codeLenCodeTab); + + if (code == 16) { + repeat(this, codeLengths, 2, 3, len); + } else if (code == 17) { + repeat(this, codeLengths, 3, 3, len = 0); + } else if (code == 18) { + repeat(this, codeLengths, 7, 11, len = 0); + } else { + codeLengths[i++] = len = code; + } + } + + litCodeTable = this.generateHuffmanTable(codeLengths.slice(0, numLitCodes)); + distCodeTable = this.generateHuffmanTable(codeLengths.slice(numLitCodes, codes)); + } else { + error("Unknown block type in flate stream"); + } + + var buffer = this.buffer; + var limit = buffer ? buffer.length : 0; + var pos = this.bufferLength; + + while (true) { + var code1 = this.getCode(litCodeTable); + + if (code1 < 256) { + if (pos + 1 >= limit) { + buffer = this.ensureBuffer(pos + 1); + limit = buffer.length; + } + + buffer[pos++] = code1; + continue; + } + + if (code1 == 256) { + this.bufferLength = pos; + return; + } + + code1 -= 257; + code1 = lengthDecode[code1]; + var code2 = code1 >> 16; + if (code2 > 0) code2 = this.getBits(code2); + var len = (code1 & 0xffff) + code2; + code1 = this.getCode(distCodeTable); + code1 = distDecode[code1]; + code2 = code1 >> 16; + if (code2 > 0) code2 = this.getBits(code2); + var dist = (code1 & 0xffff) + code2; + + if (pos + len >= limit) { + buffer = this.ensureBuffer(pos + len); + limit = buffer.length; + } + + for (var k = 0; k < len; ++k, ++pos) buffer[pos] = buffer[pos - dist]; + } + }; + + return constructor; + }(); + + exports.default = jsPDF; + var _default2 = exports.default; + function rewire($stub) { + exports.default = $stub; + } + function restore() { + exports.default = _default2; + } + + exports.rewire = rewire; + exports.restore = restore; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/librerias/gantt/code/lib/rgbcolor.js b/librerias/gantt/code/lib/rgbcolor.js new file mode 100644 index 0000000..6ed15cb --- /dev/null +++ b/librerias/gantt/code/lib/rgbcolor.js @@ -0,0 +1,17 @@ +/* + + A class to parse color values + @author Stoyan Stefanov + @link http://www.phpied.com/rgb-color-parser-in-javascript/ + @license Use it if you like it +*/ +(function(f){function g(b){this.ok=!1;"#"==b.charAt(0)&&(b=b.substr(1,6));b=b.replace(/ /g,"");b=b.toLowerCase();var m={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"00ffff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000000",blanchedalmond:"ffebcd",blue:"0000ff",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"00ffff",darkblue:"00008b", +darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dodgerblue:"1e90ff",feldspar:"d19275",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"ff00ff", +gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgrey:"d3d3d3",lightgreen:"90ee90",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa", +lightslateblue:"8470ff",lightslategray:"778899",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"00ff00",limegreen:"32cd32",linen:"faf0e6",magenta:"ff00ff",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370d8",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080", +oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"d87093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",red:"ff0000",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd", +slategray:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",violetred:"d02090",wheat:"f5deb3",white:"ffffff",whitesmoke:"f5f5f5",yellow:"ffff00",yellowgreen:"9acd32"},e;for(e in m)b==e&&(b=m[e]);var h=[{re:/^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,example:["rgb(123, 234, 45)","rgb(255,234,245)"],process:function(a){return[parseInt(a[1]),parseInt(a[2]),parseInt(a[3])]}},{re:/^(\w{2})(\w{2})(\w{2})$/, +example:["#00ff00","336699"],process:function(a){return[parseInt(a[1],16),parseInt(a[2],16),parseInt(a[3],16)]}},{re:/^(\w{1})(\w{1})(\w{1})$/,example:["#fb0","f0f"],process:function(a){return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)]}}];for(e=0;ethis.r||isNaN(this.r)?0:255this.g||isNaN(this.g)?0: +255this.b||isNaN(this.b)?0:255 "+l.toRGB()+" -> "+l.toHex());f.appendChild(n);f.appendChild(k);d.appendChild(f)}catch(p){}return d}}"function"===typeof define&&define.amd?define(function(){return g}): +"undefined"!==typeof module&&module.exports?module.exports=g:f.RGBColor=g;return g})("undefined"!==typeof self&&self||"undefined"!==typeof window&&window||this); \ No newline at end of file diff --git a/librerias/gantt/code/lib/rgbcolor.src.js b/librerias/gantt/code/lib/rgbcolor.src.js new file mode 100644 index 0000000..b2195eb --- /dev/null +++ b/librerias/gantt/code/lib/rgbcolor.src.js @@ -0,0 +1,299 @@ +/** @preserve + * A class to parse color values + * @author Stoyan Stefanov + * @link http://www.phpied.com/rgb-color-parser-in-javascript/ + * @license Use it if you like it + */ +(function (global) { +function RGBColor(color_string) +{ + this.ok = false; + + // strip any leading # + if (color_string.charAt(0) == '#') { // remove # if any + color_string = color_string.substr(1,6); + } + + color_string = color_string.replace(/ /g,''); + color_string = color_string.toLowerCase(); + + // before getting into regexps, try simple matches + // and overwrite the input + var simple_colors = { + aliceblue: 'f0f8ff', + antiquewhite: 'faebd7', + aqua: '00ffff', + aquamarine: '7fffd4', + azure: 'f0ffff', + beige: 'f5f5dc', + bisque: 'ffe4c4', + black: '000000', + blanchedalmond: 'ffebcd', + blue: '0000ff', + blueviolet: '8a2be2', + brown: 'a52a2a', + burlywood: 'deb887', + cadetblue: '5f9ea0', + chartreuse: '7fff00', + chocolate: 'd2691e', + coral: 'ff7f50', + cornflowerblue: '6495ed', + cornsilk: 'fff8dc', + crimson: 'dc143c', + cyan: '00ffff', + darkblue: '00008b', + darkcyan: '008b8b', + darkgoldenrod: 'b8860b', + darkgray: 'a9a9a9', + darkgreen: '006400', + darkkhaki: 'bdb76b', + darkmagenta: '8b008b', + darkolivegreen: '556b2f', + darkorange: 'ff8c00', + darkorchid: '9932cc', + darkred: '8b0000', + darksalmon: 'e9967a', + darkseagreen: '8fbc8f', + darkslateblue: '483d8b', + darkslategray: '2f4f4f', + darkturquoise: '00ced1', + darkviolet: '9400d3', + deeppink: 'ff1493', + deepskyblue: '00bfff', + dimgray: '696969', + dodgerblue: '1e90ff', + feldspar: 'd19275', + firebrick: 'b22222', + floralwhite: 'fffaf0', + forestgreen: '228b22', + fuchsia: 'ff00ff', + gainsboro: 'dcdcdc', + ghostwhite: 'f8f8ff', + gold: 'ffd700', + goldenrod: 'daa520', + gray: '808080', + green: '008000', + greenyellow: 'adff2f', + honeydew: 'f0fff0', + hotpink: 'ff69b4', + indianred : 'cd5c5c', + indigo : '4b0082', + ivory: 'fffff0', + khaki: 'f0e68c', + lavender: 'e6e6fa', + lavenderblush: 'fff0f5', + lawngreen: '7cfc00', + lemonchiffon: 'fffacd', + lightblue: 'add8e6', + lightcoral: 'f08080', + lightcyan: 'e0ffff', + lightgoldenrodyellow: 'fafad2', + lightgrey: 'd3d3d3', + lightgreen: '90ee90', + lightpink: 'ffb6c1', + lightsalmon: 'ffa07a', + lightseagreen: '20b2aa', + lightskyblue: '87cefa', + lightslateblue: '8470ff', + lightslategray: '778899', + lightsteelblue: 'b0c4de', + lightyellow: 'ffffe0', + lime: '00ff00', + limegreen: '32cd32', + linen: 'faf0e6', + magenta: 'ff00ff', + maroon: '800000', + mediumaquamarine: '66cdaa', + mediumblue: '0000cd', + mediumorchid: 'ba55d3', + mediumpurple: '9370d8', + mediumseagreen: '3cb371', + mediumslateblue: '7b68ee', + mediumspringgreen: '00fa9a', + mediumturquoise: '48d1cc', + mediumvioletred: 'c71585', + midnightblue: '191970', + mintcream: 'f5fffa', + mistyrose: 'ffe4e1', + moccasin: 'ffe4b5', + navajowhite: 'ffdead', + navy: '000080', + oldlace: 'fdf5e6', + olive: '808000', + olivedrab: '6b8e23', + orange: 'ffa500', + orangered: 'ff4500', + orchid: 'da70d6', + palegoldenrod: 'eee8aa', + palegreen: '98fb98', + paleturquoise: 'afeeee', + palevioletred: 'd87093', + papayawhip: 'ffefd5', + peachpuff: 'ffdab9', + peru: 'cd853f', + pink: 'ffc0cb', + plum: 'dda0dd', + powderblue: 'b0e0e6', + purple: '800080', + red: 'ff0000', + rosybrown: 'bc8f8f', + royalblue: '4169e1', + saddlebrown: '8b4513', + salmon: 'fa8072', + sandybrown: 'f4a460', + seagreen: '2e8b57', + seashell: 'fff5ee', + sienna: 'a0522d', + silver: 'c0c0c0', + skyblue: '87ceeb', + slateblue: '6a5acd', + slategray: '708090', + snow: 'fffafa', + springgreen: '00ff7f', + steelblue: '4682b4', + tan: 'd2b48c', + teal: '008080', + thistle: 'd8bfd8', + tomato: 'ff6347', + turquoise: '40e0d0', + violet: 'ee82ee', + violetred: 'd02090', + wheat: 'f5deb3', + white: 'ffffff', + whitesmoke: 'f5f5f5', + yellow: 'ffff00', + yellowgreen: '9acd32' + }; + for (var key in simple_colors) { + if (color_string == key) { + color_string = simple_colors[key]; + } + } + // emd of simple type-in colors + + // array of color definition objects + var color_defs = [ + { + re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, + example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'], + process: function (bits){ + return [ + parseInt(bits[1]), + parseInt(bits[2]), + parseInt(bits[3]) + ]; + } + }, + { + re: /^(\w{2})(\w{2})(\w{2})$/, + example: ['#00ff00', '336699'], + process: function (bits){ + return [ + parseInt(bits[1], 16), + parseInt(bits[2], 16), + parseInt(bits[3], 16) + ]; + } + }, + { + re: /^(\w{1})(\w{1})(\w{1})$/, + example: ['#fb0', 'f0f'], + process: function (bits){ + return [ + parseInt(bits[1] + bits[1], 16), + parseInt(bits[2] + bits[2], 16), + parseInt(bits[3] + bits[3], 16) + ]; + } + } + ]; + + // search through the definitions to find a match + for (var i = 0; i < color_defs.length; i++) { + var re = color_defs[i].re; + var processor = color_defs[i].process; + var bits = re.exec(color_string); + if (bits) { + channels = processor(bits); + this.r = channels[0]; + this.g = channels[1]; + this.b = channels[2]; + this.ok = true; + } + + } + + // validate/cleanup values + this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r); + this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g); + this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b); + + // some getters + this.toRGB = function () { + return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')'; + } + this.toHex = function () { + var r = this.r.toString(16); + var g = this.g.toString(16); + var b = this.b.toString(16); + if (r.length == 1) r = '0' + r; + if (g.length == 1) g = '0' + g; + if (b.length == 1) b = '0' + b; + return '#' + r + g + b; + } + + // help + this.getHelpXML = function () { + + var examples = new Array(); + // add regexps + for (var i = 0; i < color_defs.length; i++) { + var example = color_defs[i].example; + for (var j = 0; j < example.length; j++) { + examples[examples.length] = example[j]; + } + } + // add type-in colors + for (var sc in simple_colors) { + examples[examples.length] = sc; + } + + var xml = document.createElement('ul'); + xml.setAttribute('id', 'rgbcolor-examples'); + for (var i = 0; i < examples.length; i++) { + try { + var list_item = document.createElement('li'); + var list_color = new RGBColor(examples[i]); + var example_div = document.createElement('div'); + example_div.style.cssText = + 'margin: 3px; ' + + 'border: 1px solid black; ' + + 'background:' + list_color.toHex() + '; ' + + 'color:' + list_color.toHex() + ; + example_div.appendChild(document.createTextNode('test')); + var list_item_value = document.createTextNode( + ' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex() + ); + list_item.appendChild(example_div); + list_item.appendChild(list_item_value); + xml.appendChild(list_item); + + } catch(e){} + } + return xml; + + } + +} +if (typeof define === "function" && define.amd) { + define(function () { + return RGBColor; + }); +} else if (typeof module !== "undefined" && module.exports) { + module.exports = RGBColor; +} else { + global.RGBColor = RGBColor; +} +return RGBColor; +})(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this); \ No newline at end of file diff --git a/librerias/gantt/code/lib/svg2pdf.js b/librerias/gantt/code/lib/svg2pdf.js new file mode 100644 index 0000000..53607af --- /dev/null +++ b/librerias/gantt/code/lib/svg2pdf.js @@ -0,0 +1,38 @@ +/** + * Modules in this bundle + * @license + * + * svg2pdf.js: + * license: MIT (http://opensource.org/licenses/MIT) + * author: yFiles for HTML Support Team + * homepage: https://github.com/yWorks/svg2pdf.js#readme + * version: 1.3.1 + * + * cssesc: + * license: MIT (http://opensource.org/licenses/MIT) + * author: Mathias Bynens + * homepage: https://mths.be/cssesc + * version: 2.0.0 + * + * font-family: + * license: MIT (http://opensource.org/licenses/MIT) + * author: Taro Hanamura + * homepage: https://github.com/hanamura/font-family + * version: 0.2.0 + * + * svgpath: + * license: MIT (http://opensource.org/licenses/MIT) + * homepage: https://github.com/fontello/svgpath#readme + * version: 2.2.1 + * + * This header is generated by licensify (https://github.com/twada/licensify) + */ +!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).svg2pdf=t()}}(function(){return function n(s,o,h){function c(e,t){if(!o[e]){if(!s[e]){var r="function"==typeof require&&require;if(!t&&r)return r(e,!0);if(u)return u(e,!0);var a=new Error("Cannot find module '"+e+"'");throw a.code="MODULE_NOT_FOUND",a}var i=o[e]={exports:{}};s[e][0].call(i.exports,function(t){return c(s[e][1][t]||t)},i,i.exports,n,s,o,h)}return o[e].exports}for(var u="function"==typeof require&&require,t=0;tMath.abs(c-n)?(c-i)/h:h/(c-n))/Math.PI,0<=this.ax?(this.rx=Math.sqrt(c),this.ry=Math.sqrt(u)):(this.ax+=90,this.rx=Math.sqrt(u),this.ry=Math.sqrt(c)),this},a.prototype.isDegenerate=function(){return this.rx=s[r]&&(t.result.push([e].concat(a.splice(0,s[r]))),s[r]););}function n(t){var e,r,a,i=t.max;if(t.segmentStart=t.index,function(t){switch(32|t){case 109:case 122:case 108:case 104:case 118:case 99:case 115:case 113:case 116:case 97:case 114:return!0}return!1}(t.path.charCodeAt(t.index)))if(r=s[t.path[t.index].toLowerCase()],t.index++,o(t),t.data=[],r){for(e=!1;;){for(a=r;0=t.max)break;if(!(48<=(n=t.path.charCodeAt(t.index))&&n<=57||43===n||45===n||46===n))break}}var n;u(t)}else u(t);else t.err="SvgPath: bad command "+t.path[t.index]+" (at pos "+t.index+")"}e.exports=function(t){var e=new i(t),r=e.max;for(o(e);e.index + * @link http://www.phpied.com/rgb-color-parser-in-javascript/ + * @license Use it if you like it + */ +!function(t){function f(t){this.ok=!1,"#"==t.charAt(0)&&(t=t.substr(1,6)),t=(t=t.replace(/ /g,"")).toLowerCase();var u={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"00ffff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000000",blanchedalmond:"ffebcd",blue:"0000ff",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"00ffff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dodgerblue:"1e90ff",feldspar:"d19275",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"ff00ff",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgrey:"d3d3d3",lightgreen:"90ee90",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslateblue:"8470ff",lightslategray:"778899",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"00ff00",limegreen:"32cd32",linen:"faf0e6",magenta:"ff00ff",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370d8",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"d87093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",red:"ff0000",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",violetred:"d02090",wheat:"f5deb3",white:"ffffff",whitesmoke:"f5f5f5",yellow:"ffff00",yellowgreen:"9acd32"};for(var e in u)t==e&&(t=u[e]);for(var l=[{re:/^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,example:["rgb(123, 234, 45)","rgb(255,234,245)"],process:function(t){return[parseInt(t[1]),parseInt(t[2]),parseInt(t[3])]}},{re:/^(\w{2})(\w{2})(\w{2})$/,example:["#00ff00","336699"],process:function(t){return[parseInt(t[1],16),parseInt(t[2],16),parseInt(t[3],16)]}},{re:/^(\w{1})(\w{1})(\w{1})$/,example:["#fb0","f0f"],process:function(t){return[parseInt(t[1]+t[1],16),parseInt(t[2]+t[2],16),parseInt(t[3]+t[3],16)]}}],r=0;r "+o.toRGB()+" -> "+o.toHex());s.appendChild(h),s.appendChild(c),n.appendChild(s)}catch(t){}return n}}void 0!==e&&e.exports?e.exports=f:t.RGBColor=f}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this)},{}],11:[function(r,p,t){!function(t){var rt,u,c,i,at,it=/url\(["']?#([^"']+)["']?\)/,nt=/^\s*data:(([^/,;]+\/[^/,;]+)(?:;([^,;=]+=[^,;=]+))?)?(?:;(base64))?,(.*\s*)$/i,h="http://www.w3.org/2000/svg",st=function(t){var e=t.getAttribute("d");u&&(e=u(e).unshort().unarc().abs().toString(),t.setAttribute("d",e));var r=t.pathSegList;if(r)return r;r=[];for(var a,i=/([a-df-zA-DF-Z])([^a-df-zA-DF-Z]*)/g;a=i.exec(e);){var n=kt(a[2]),s=a[1],o=0<="zZ".indexOf(s)?0:0<="hHvV".indexOf(s)?1:0<="mMlLtT".indexOf(s)?2:0<="sSqQ".indexOf(s)?4:0<="aA".indexOf(s)?7:0<="cC".indexOf(s)?6:-1,h=0;do{var c={pathSegTypeAsLetter:s};switch(s){case"h":case"H":c.x=n[h];break;case"v":case"V":c.y=n[h];break;case"c":case"C":c.x1=n[h+o-6],c.y1=n[h+o-5];case"s":case"S":c.x2=n[h+o-4],c.y2=n[h+o-3];case"t":case"T":case"l":case"L":case"m":case"M":c.x=n[h+o-2],c.y=n[h+o-1];break;case"q":case"Q":c.x1=n[h],c.y1=n[h+1],c.x=n[h+2],c.y=n[h+3];break;case"a":case"A":throw new Error("Cannot convert Arcs without SvgPath package")}r.push(c),"m"===s?s="l":"M"===s&&(s="L"),h+=o}while(h",o={};return function(t){var e=o[t];if(!e){var r=i(s,t,"16px","normal","normal"),a=n(s,t,"16px","normal","normal");e=Math.abs(r-a)<.1?i:n,o[t]=e}return e}}();function N(t,e){if(0===t.length)return 0;var r=e.fontFamily;return a(r)(t,e.fontFamily,e.fontSize+"px",e.fontStyle,e.fontWeight)}function q(t,e,r){this.texts=[],this.textNodes=[],this.textAnchor=t,this.originX=e,this.originY=r}function P(t,e){var r;return(r=t&&t.toString().match(/^([\-0-9.]+)em$/))?parseFloat(r[1])*e:(r=t&&t.toString().match(/^([\-0-9.]+)(px|)$/))?parseFloat(r[1]):0}q.prototype.add=function(t,e){this.texts.push(e),this.textNodes.push(t)},q.prototype.put=function(t,e){var r,a,i,n=[],s=[],o=[],h=this.originX,c=this.originY,u=h,l=h;for(r=0;r + * homepage: https://github.com/yWorks/svg2pdf.js#readme + * version: 1.3.1 + * + * cssesc: + * license: MIT (http://opensource.org/licenses/MIT) + * author: Mathias Bynens + * homepage: https://mths.be/cssesc + * version: 2.0.0 + * + * font-family: + * license: MIT (http://opensource.org/licenses/MIT) + * author: Taro Hanamura + * homepage: https://github.com/hanamura/font-family + * version: 0.2.0 + * + * svgpath: + * license: MIT (http://opensource.org/licenses/MIT) + * homepage: https://github.com/fontello/svgpath#readme + * version: 2.2.1 + * + * This header is generated by licensify (https://github.com/twada/licensify) + */ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.svg2pdf = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 1.0) { div = 1.0; } + if (div < -1.0) { div = -1.0; } + + return sign * Math.acos(div); +} + + +// Convert from endpoint to center parameterization, +// see http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes +// +// Return [cx, cy, theta1, delta_theta] +// +function get_arc_center(x1, y1, x2, y2, fa, fs, rx, ry, sin_phi, cos_phi) { + // Step 1. + // + // Moving an ellipse so origin will be the middlepoint between our two + // points. After that, rotate it to line up ellipse axes with coordinate + // axes. + // + var x1p = cos_phi*(x1-x2)/2 + sin_phi*(y1-y2)/2; + var y1p = -sin_phi*(x1-x2)/2 + cos_phi*(y1-y2)/2; + + var rx_sq = rx * rx; + var ry_sq = ry * ry; + var x1p_sq = x1p * x1p; + var y1p_sq = y1p * y1p; + + // Step 2. + // + // Compute coordinates of the centre of this ellipse (cx', cy') + // in the new coordinate system. + // + var radicant = (rx_sq * ry_sq) - (rx_sq * y1p_sq) - (ry_sq * x1p_sq); + + if (radicant < 0) { + // due to rounding errors it might be e.g. -1.3877787807814457e-17 + radicant = 0; + } + + radicant /= (rx_sq * y1p_sq) + (ry_sq * x1p_sq); + radicant = Math.sqrt(radicant) * (fa === fs ? -1 : 1); + + var cxp = radicant * rx/ry * y1p; + var cyp = radicant * -ry/rx * x1p; + + // Step 3. + // + // Transform back to get centre coordinates (cx, cy) in the original + // coordinate system. + // + var cx = cos_phi*cxp - sin_phi*cyp + (x1+x2)/2; + var cy = sin_phi*cxp + cos_phi*cyp + (y1+y2)/2; + + // Step 4. + // + // Compute angles (theta1, delta_theta). + // + var v1x = (x1p - cxp) / rx; + var v1y = (y1p - cyp) / ry; + var v2x = (-x1p - cxp) / rx; + var v2y = (-y1p - cyp) / ry; + + var theta1 = vector_angle(1, 0, v1x, v1y); + var delta_theta = vector_angle(v1x, v1y, v2x, v2y); + + if (fs === 0 && delta_theta > 0) { + delta_theta -= TAU; + } + if (fs === 1 && delta_theta < 0) { + delta_theta += TAU; + } + + return [ cx, cy, theta1, delta_theta ]; +} + +// +// Approximate one unit arc segment with bézier curves, +// see http://math.stackexchange.com/questions/873224 +// +function approximate_unit_arc(theta1, delta_theta) { + var alpha = 4/3 * Math.tan(delta_theta/4); + + var x1 = Math.cos(theta1); + var y1 = Math.sin(theta1); + var x2 = Math.cos(theta1 + delta_theta); + var y2 = Math.sin(theta1 + delta_theta); + + return [ x1, y1, x1 - y1*alpha, y1 + x1*alpha, x2 + y2*alpha, y2 - x2*alpha, x2, y2 ]; +} + +module.exports = function a2c(x1, y1, x2, y2, fa, fs, rx, ry, phi) { + var sin_phi = Math.sin(phi * TAU / 360); + var cos_phi = Math.cos(phi * TAU / 360); + + // Make sure radii are valid + // + var x1p = cos_phi*(x1-x2)/2 + sin_phi*(y1-y2)/2; + var y1p = -sin_phi*(x1-x2)/2 + cos_phi*(y1-y2)/2; + + if (x1p === 0 && y1p === 0) { + // we're asked to draw line to itself + return []; + } + + if (rx === 0 || ry === 0) { + // one of the radii is zero + return []; + } + + + // Compensate out-of-range radii + // + rx = Math.abs(rx); + ry = Math.abs(ry); + + var lambda = (x1p * x1p) / (rx * rx) + (y1p * y1p) / (ry * ry); + if (lambda > 1) { + rx *= Math.sqrt(lambda); + ry *= Math.sqrt(lambda); + } + + + // Get center parameters (cx, cy, theta1, delta_theta) + // + var cc = get_arc_center(x1, y1, x2, y2, fa, fs, rx, ry, sin_phi, cos_phi); + + var result = []; + var theta1 = cc[2]; + var delta_theta = cc[3]; + + // Split an arc to multiple segments, so each segment + // will be less than τ/4 (= 90°) + // + var segments = Math.max(Math.ceil(Math.abs(delta_theta) / (TAU / 4)), 1); + delta_theta /= segments; + + for (var i = 0; i < segments; i++) { + result.push(approximate_unit_arc(theta1, delta_theta)); + theta1 += delta_theta; + } + + // We have a bezier approximation of a unit circle, + // now need to transform back to the original ellipse + // + return result.map(function (curve) { + for (var i = 0; i < curve.length; i += 2) { + var x = curve[i + 0]; + var y = curve[i + 1]; + + // scale + x *= rx; + y *= ry; + + // rotate + var xp = cos_phi*x - sin_phi*y; + var yp = sin_phi*x + cos_phi*y; + + // translate + curve[i + 0] = xp + cc[0]; + curve[i + 1] = yp + cc[1]; + } + + return curve; + }); +}; + +},{}],3:[function(require,module,exports){ +'use strict'; + +/* eslint-disable space-infix-ops */ + +// The precision used to consider an ellipse as a circle +// +var epsilon = 0.0000000001; + +// To convert degree in radians +// +var torad = Math.PI / 180; + +// Class constructor : +// an ellipse centred at 0 with radii rx,ry and x - axis - angle ax. +// +function Ellipse(rx, ry, ax) { + if (!(this instanceof Ellipse)) { return new Ellipse(rx, ry, ax); } + this.rx = rx; + this.ry = ry; + this.ax = ax; +} + +// Apply a linear transform m to the ellipse +// m is an array representing a matrix : +// - - +// | m[0] m[2] | +// | m[1] m[3] | +// - - +// +Ellipse.prototype.transform = function (m) { + // We consider the current ellipse as image of the unit circle + // by first scale(rx,ry) and then rotate(ax) ... + // So we apply ma = m x rotate(ax) x scale(rx,ry) to the unit circle. + var c = Math.cos(this.ax * torad), s = Math.sin(this.ax * torad); + var ma = [ + this.rx * (m[0]*c + m[2]*s), + this.rx * (m[1]*c + m[3]*s), + this.ry * (-m[0]*s + m[2]*c), + this.ry * (-m[1]*s + m[3]*c) + ]; + + // ma * transpose(ma) = [ J L ] + // [ L K ] + // L is calculated later (if the image is not a circle) + var J = ma[0]*ma[0] + ma[2]*ma[2], + K = ma[1]*ma[1] + ma[3]*ma[3]; + + // the discriminant of the characteristic polynomial of ma * transpose(ma) + var D = ((ma[0]-ma[3])*(ma[0]-ma[3]) + (ma[2]+ma[1])*(ma[2]+ma[1])) * + ((ma[0]+ma[3])*(ma[0]+ma[3]) + (ma[2]-ma[1])*(ma[2]-ma[1])); + + // the "mean eigenvalue" + var JK = (J + K) / 2; + + // check if the image is (almost) a circle + if (D < epsilon * JK) { + // if it is + this.rx = this.ry = Math.sqrt(JK); + this.ax = 0; + return this; + } + + // if it is not a circle + var L = ma[0]*ma[1] + ma[2]*ma[3]; + + D = Math.sqrt(D); + + // {l1,l2} = the two eigen values of ma * transpose(ma) + var l1 = JK + D/2, + l2 = JK - D/2; + // the x - axis - rotation angle is the argument of the l1 - eigenvector + this.ax = (Math.abs(L) < epsilon && Math.abs(l1 - K) < epsilon) ? + 90 + : + Math.atan(Math.abs(L) > Math.abs(l1 - K) ? + (l1 - J) / L + : + L / (l1 - K) + ) * 180 / Math.PI; + + // if ax > 0 => rx = sqrt(l1), ry = sqrt(l2), else exchange axes and ax += 90 + if (this.ax >= 0) { + // if ax in [0,90] + this.rx = Math.sqrt(l1); + this.ry = Math.sqrt(l2); + } else { + // if ax in ]-90,0[ => exchange axes + this.ax += 90; + this.rx = Math.sqrt(l2); + this.ry = Math.sqrt(l1); + } + + return this; +}; + +// Check if the ellipse is (almost) degenerate, i.e. rx = 0 or ry = 0 +// +Ellipse.prototype.isDegenerate = function () { + return (this.rx < epsilon * this.ry || this.ry < epsilon * this.rx); +}; + +module.exports = Ellipse; + +},{}],4:[function(require,module,exports){ +'use strict'; + +// combine 2 matrixes +// m1, m2 - [a, b, c, d, e, g] +// +function combine(m1, m2) { + return [ + m1[0] * m2[0] + m1[2] * m2[1], + m1[1] * m2[0] + m1[3] * m2[1], + m1[0] * m2[2] + m1[2] * m2[3], + m1[1] * m2[2] + m1[3] * m2[3], + m1[0] * m2[4] + m1[2] * m2[5] + m1[4], + m1[1] * m2[4] + m1[3] * m2[5] + m1[5] + ]; +} + + +function Matrix() { + if (!(this instanceof Matrix)) { return new Matrix(); } + this.queue = []; // list of matrixes to apply + this.cache = null; // combined matrix cache +} + + +Matrix.prototype.matrix = function (m) { + if (m[0] === 1 && m[1] === 0 && m[2] === 0 && m[3] === 1 && m[4] === 0 && m[5] === 0) { + return this; + } + this.cache = null; + this.queue.push(m); + return this; +}; + + +Matrix.prototype.translate = function (tx, ty) { + if (tx !== 0 || ty !== 0) { + this.cache = null; + this.queue.push([ 1, 0, 0, 1, tx, ty ]); + } + return this; +}; + + +Matrix.prototype.scale = function (sx, sy) { + if (sx !== 1 || sy !== 1) { + this.cache = null; + this.queue.push([ sx, 0, 0, sy, 0, 0 ]); + } + return this; +}; + + +Matrix.prototype.rotate = function (angle, rx, ry) { + var rad, cos, sin; + + if (angle !== 0) { + this.translate(rx, ry); + + rad = angle * Math.PI / 180; + cos = Math.cos(rad); + sin = Math.sin(rad); + + this.queue.push([ cos, sin, -sin, cos, 0, 0 ]); + this.cache = null; + + this.translate(-rx, -ry); + } + return this; +}; + + +Matrix.prototype.skewX = function (angle) { + if (angle !== 0) { + this.cache = null; + this.queue.push([ 1, 0, Math.tan(angle * Math.PI / 180), 1, 0, 0 ]); + } + return this; +}; + + +Matrix.prototype.skewY = function (angle) { + if (angle !== 0) { + this.cache = null; + this.queue.push([ 1, Math.tan(angle * Math.PI / 180), 0, 1, 0, 0 ]); + } + return this; +}; + + +// Flatten queue +// +Matrix.prototype.toArray = function () { + if (this.cache) { + return this.cache; + } + + if (!this.queue.length) { + this.cache = [ 1, 0, 0, 1, 0, 0 ]; + return this.cache; + } + + this.cache = this.queue[0]; + + if (this.queue.length === 1) { + return this.cache; + } + + for (var i = 1; i < this.queue.length; i++) { + this.cache = combine(this.cache, this.queue[i]); + } + + return this.cache; +}; + + +// Apply list of matrixes to (x,y) point. +// If `isRelative` set, `translate` component of matrix will be skipped +// +Matrix.prototype.calc = function (x, y, isRelative) { + var m; + + // Don't change point on empty transforms queue + if (!this.queue.length) { return [ x, y ]; } + + // Calculate final matrix, if not exists + // + // NB. if you deside to apply transforms to point one-by-one, + // they should be taken in reverse order + + if (!this.cache) { + this.cache = this.toArray(); + } + + m = this.cache; + + // Apply matrix to point + return [ + x * m[0] + y * m[2] + (isRelative ? 0 : m[4]), + x * m[1] + y * m[3] + (isRelative ? 0 : m[5]) + ]; +}; + + +module.exports = Matrix; + +},{}],5:[function(require,module,exports){ +'use strict'; + + +var paramCounts = { a: 7, c: 6, h: 1, l: 2, m: 2, r: 4, q: 4, s: 4, t: 2, v: 1, z: 0 }; + +var SPECIAL_SPACES = [ + 0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, + 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF +]; + +function isSpace(ch) { + return (ch === 0x0A) || (ch === 0x0D) || (ch === 0x2028) || (ch === 0x2029) || // Line terminators + // White spaces + (ch === 0x20) || (ch === 0x09) || (ch === 0x0B) || (ch === 0x0C) || (ch === 0xA0) || + (ch >= 0x1680 && SPECIAL_SPACES.indexOf(ch) >= 0); +} + +function isCommand(code) { + /*eslint-disable no-bitwise*/ + switch (code | 0x20) { + case 0x6D/* m */: + case 0x7A/* z */: + case 0x6C/* l */: + case 0x68/* h */: + case 0x76/* v */: + case 0x63/* c */: + case 0x73/* s */: + case 0x71/* q */: + case 0x74/* t */: + case 0x61/* a */: + case 0x72/* r */: + return true; + } + return false; +} + +function isDigit(code) { + return (code >= 48 && code <= 57); // 0..9 +} + +function isDigitStart(code) { + return (code >= 48 && code <= 57) || /* 0..9 */ + code === 0x2B || /* + */ + code === 0x2D || /* - */ + code === 0x2E; /* . */ +} + + +function State(path) { + this.index = 0; + this.path = path; + this.max = path.length; + this.result = []; + this.param = 0.0; + this.err = ''; + this.segmentStart = 0; + this.data = []; +} + +function skipSpaces(state) { + while (state.index < state.max && isSpace(state.path.charCodeAt(state.index))) { + state.index++; + } +} + + +function scanParam(state) { + var start = state.index, + index = start, + max = state.max, + zeroFirst = false, + hasCeiling = false, + hasDecimal = false, + hasDot = false, + ch; + + if (index >= max) { + state.err = 'SvgPath: missed param (at pos ' + index + ')'; + return; + } + ch = state.path.charCodeAt(index); + + if (ch === 0x2B/* + */ || ch === 0x2D/* - */) { + index++; + ch = (index < max) ? state.path.charCodeAt(index) : 0; + } + + // This logic is shamelessly borrowed from Esprima + // https://github.com/ariya/esprimas + // + if (!isDigit(ch) && ch !== 0x2E/* . */) { + state.err = 'SvgPath: param should start with 0..9 or `.` (at pos ' + index + ')'; + return; + } + + if (ch !== 0x2E/* . */) { + zeroFirst = (ch === 0x30/* 0 */); + index++; + + ch = (index < max) ? state.path.charCodeAt(index) : 0; + + if (zeroFirst && index < max) { + // decimal number starts with '0' such as '09' is illegal. + if (ch && isDigit(ch)) { + state.err = 'SvgPath: numbers started with `0` such as `09` are ilegal (at pos ' + start + ')'; + return; + } + } + + while (index < max && isDigit(state.path.charCodeAt(index))) { + index++; + hasCeiling = true; + } + ch = (index < max) ? state.path.charCodeAt(index) : 0; + } + + if (ch === 0x2E/* . */) { + hasDot = true; + index++; + while (isDigit(state.path.charCodeAt(index))) { + index++; + hasDecimal = true; + } + ch = (index < max) ? state.path.charCodeAt(index) : 0; + } + + if (ch === 0x65/* e */ || ch === 0x45/* E */) { + if (hasDot && !hasCeiling && !hasDecimal) { + state.err = 'SvgPath: invalid float exponent (at pos ' + index + ')'; + return; + } + + index++; + + ch = (index < max) ? state.path.charCodeAt(index) : 0; + if (ch === 0x2B/* + */ || ch === 0x2D/* - */) { + index++; + } + if (index < max && isDigit(state.path.charCodeAt(index))) { + while (index < max && isDigit(state.path.charCodeAt(index))) { + index++; + } + } else { + state.err = 'SvgPath: invalid float exponent (at pos ' + index + ')'; + return; + } + } + + state.index = index; + state.param = parseFloat(state.path.slice(start, index)) + 0.0; +} + + +function finalizeSegment(state) { + var cmd, cmdLC; + + // Process duplicated commands (without comand name) + + // This logic is shamelessly borrowed from Raphael + // https://github.com/DmitryBaranovskiy/raphael/ + // + cmd = state.path[state.segmentStart]; + cmdLC = cmd.toLowerCase(); + + var params = state.data; + + if (cmdLC === 'm' && params.length > 2) { + state.result.push([ cmd, params[0], params[1] ]); + params = params.slice(2); + cmdLC = 'l'; + cmd = (cmd === 'm') ? 'l' : 'L'; + } + + if (cmdLC === 'r') { + state.result.push([ cmd ].concat(params)); + } else { + + while (params.length >= paramCounts[cmdLC]) { + state.result.push([ cmd ].concat(params.splice(0, paramCounts[cmdLC]))); + if (!paramCounts[cmdLC]) { + break; + } + } + } +} + + +function scanSegment(state) { + var max = state.max, + cmdCode, comma_found, need_params, i; + + state.segmentStart = state.index; + cmdCode = state.path.charCodeAt(state.index); + + if (!isCommand(cmdCode)) { + state.err = 'SvgPath: bad command ' + state.path[state.index] + ' (at pos ' + state.index + ')'; + return; + } + + need_params = paramCounts[state.path[state.index].toLowerCase()]; + + state.index++; + skipSpaces(state); + + state.data = []; + + if (!need_params) { + // Z + finalizeSegment(state); + return; + } + + comma_found = false; + + for (;;) { + for (i = need_params; i > 0; i--) { + scanParam(state); + if (state.err.length) { + return; + } + state.data.push(state.param); + + skipSpaces(state); + comma_found = false; + + if (state.index < max && state.path.charCodeAt(state.index) === 0x2C/* , */) { + state.index++; + skipSpaces(state); + comma_found = true; + } + } + + // after ',' param is mandatory + if (comma_found) { + continue; + } + + if (state.index >= state.max) { + break; + } + + // Stop on next segment + if (!isDigitStart(state.path.charCodeAt(state.index))) { + break; + } + } + + finalizeSegment(state); +} + + +/* Returns array of segments: + * + * [ + * [ command, coord1, coord2, ... ] + * ] + */ +module.exports = function pathParse(svgPath) { + var state = new State(svgPath); + var max = state.max; + + skipSpaces(state); + + while (state.index < max && !state.err.length) { + scanSegment(state); + } + + if (state.err.length) { + state.result = []; + + } else if (state.result.length) { + + if ('mM'.indexOf(state.result[0][0]) < 0) { + state.err = 'SvgPath: string should start with `M` or `m`'; + state.result = []; + } else { + state.result[0][0] = 'M'; + } + } + + return { + err: state.err, + segments: state.result + }; +}; + +},{}],6:[function(require,module,exports){ +// SVG Path transformations library +// +// Usage: +// +// SvgPath('...') +// .translate(-150, -100) +// .scale(0.5) +// .translate(-150, -100) +// .toFixed(1) +// .toString() +// + +'use strict'; + + +var pathParse = require('./path_parse'); +var transformParse = require('./transform_parse'); +var matrix = require('./matrix'); +var a2c = require('./a2c'); +var ellipse = require('./ellipse'); + + +// Class constructor +// +function SvgPath(path) { + if (!(this instanceof SvgPath)) { return new SvgPath(path); } + + var pstate = pathParse(path); + + // Array of path segments. + // Each segment is array [command, param1, param2, ...] + this.segments = pstate.segments; + + // Error message on parse error. + this.err = pstate.err; + + // Transforms stack for lazy evaluation + this.__stack = []; +} + + +SvgPath.prototype.__matrix = function (m) { + var self = this, i; + + // Quick leave for empty matrix + if (!m.queue.length) { return; } + + this.iterate(function (s, index, x, y) { + var p, result, name, isRelative; + + switch (s[0]) { + + // Process 'assymetric' commands separately + case 'v': + p = m.calc(0, s[1], true); + result = (p[0] === 0) ? [ 'v', p[1] ] : [ 'l', p[0], p[1] ]; + break; + + case 'V': + p = m.calc(x, s[1], false); + result = (p[0] === m.calc(x, y, false)[0]) ? [ 'V', p[1] ] : [ 'L', p[0], p[1] ]; + break; + + case 'h': + p = m.calc(s[1], 0, true); + result = (p[1] === 0) ? [ 'h', p[0] ] : [ 'l', p[0], p[1] ]; + break; + + case 'H': + p = m.calc(s[1], y, false); + result = (p[1] === m.calc(x, y, false)[1]) ? [ 'H', p[0] ] : [ 'L', p[0], p[1] ]; + break; + + case 'a': + case 'A': + // ARC is: ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] + + // Drop segment if arc is empty (end point === start point) + /*if ((s[0] === 'A' && s[6] === x && s[7] === y) || + (s[0] === 'a' && s[6] === 0 && s[7] === 0)) { + return []; + }*/ + + // Transform rx, ry and the x-axis-rotation + var ma = m.toArray(); + var e = ellipse(s[1], s[2], s[3]).transform(ma); + + // flip sweep-flag if matrix is not orientation-preserving + if (ma[0] * ma[3] - ma[1] * ma[2] < 0) { + s[5] = s[5] ? '0' : '1'; + } + + // Transform end point as usual (without translation for relative notation) + p = m.calc(s[6], s[7], s[0] === 'a'); + + // Empty arcs can be ignored by renderer, but should not be dropped + // to avoid collisions with `S A S` and so on. Replace with empty line. + if ((s[0] === 'A' && s[6] === x && s[7] === y) || + (s[0] === 'a' && s[6] === 0 && s[7] === 0)) { + result = [ s[0] === 'a' ? 'l' : 'L', p[0], p[1] ]; + break; + } + + // if the resulting ellipse is (almost) a segment ... + if (e.isDegenerate()) { + // replace the arc by a line + result = [ s[0] === 'a' ? 'l' : 'L', p[0], p[1] ]; + } else { + // if it is a real ellipse + // s[0], s[4] and s[5] are not modified + result = [ s[0], e.rx, e.ry, e.ax, s[4], s[5], p[0], p[1] ]; + } + + break; + + case 'm': + // Edge case. The very first `m` should be processed as absolute, if happens. + // Make sense for coord shift transforms. + isRelative = index > 0; + + p = m.calc(s[1], s[2], isRelative); + result = [ 'm', p[0], p[1] ]; + break; + + default: + name = s[0]; + result = [ name ]; + isRelative = (name.toLowerCase() === name); + + // Apply transformations to the segment + for (i = 1; i < s.length; i += 2) { + p = m.calc(s[i], s[i + 1], isRelative); + result.push(p[0], p[1]); + } + } + + self.segments[index] = result; + }, true); +}; + + +// Apply stacked commands +// +SvgPath.prototype.__evaluateStack = function () { + var m, i; + + if (!this.__stack.length) { return; } + + if (this.__stack.length === 1) { + this.__matrix(this.__stack[0]); + this.__stack = []; + return; + } + + m = matrix(); + i = this.__stack.length; + + while (--i >= 0) { + m.matrix(this.__stack[i].toArray()); + } + + this.__matrix(m); + this.__stack = []; +}; + + +// Convert processed SVG Path back to string +// +SvgPath.prototype.toString = function () { + var elements = [], skipCmd, cmd; + + this.__evaluateStack(); + + for (var i = 0; i < this.segments.length; i++) { + // remove repeating commands names + cmd = this.segments[i][0]; + skipCmd = i > 0 && cmd !== 'm' && cmd !== 'M' && cmd === this.segments[i - 1][0]; + elements = elements.concat(skipCmd ? this.segments[i].slice(1) : this.segments[i]); + } + + return elements.join(' ') + // Optimizations: remove spaces around commands & before `-` + // + // We could also remove leading zeros for `0.5`-like values, + // but their count is too small to spend time for. + .replace(/ ?([achlmqrstvz]) ?/gi, '$1') + .replace(/ \-/g, '-') + // workaround for FontForge SVG importing bug + .replace(/zm/g, 'z m'); +}; + + +// Translate path to (x [, y]) +// +SvgPath.prototype.translate = function (x, y) { + this.__stack.push(matrix().translate(x, y || 0)); + return this; +}; + + +// Scale path to (sx [, sy]) +// sy = sx if not defined +// +SvgPath.prototype.scale = function (sx, sy) { + this.__stack.push(matrix().scale(sx, (!sy && (sy !== 0)) ? sx : sy)); + return this; +}; + + +// Rotate path around point (sx [, sy]) +// sy = sx if not defined +// +SvgPath.prototype.rotate = function (angle, rx, ry) { + this.__stack.push(matrix().rotate(angle, rx || 0, ry || 0)); + return this; +}; + + +// Skew path along the X axis by `degrees` angle +// +SvgPath.prototype.skewX = function (degrees) { + this.__stack.push(matrix().skewX(degrees)); + return this; +}; + + +// Skew path along the Y axis by `degrees` angle +// +SvgPath.prototype.skewY = function (degrees) { + this.__stack.push(matrix().skewY(degrees)); + return this; +}; + + +// Apply matrix transform (array of 6 elements) +// +SvgPath.prototype.matrix = function (m) { + this.__stack.push(matrix().matrix(m)); + return this; +}; + + +// Transform path according to "transform" attr of SVG spec +// +SvgPath.prototype.transform = function (transformString) { + if (!transformString.trim()) { + return this; + } + this.__stack.push(transformParse(transformString)); + return this; +}; + + +// Round coords with given decimal precition. +// 0 by default (to integers) +// +SvgPath.prototype.round = function (d) { + var contourStartDeltaX = 0, contourStartDeltaY = 0, deltaX = 0, deltaY = 0, l; + + d = d || 0; + + this.__evaluateStack(); + + this.segments.forEach(function (s) { + var isRelative = (s[0].toLowerCase() === s[0]); + + switch (s[0]) { + case 'H': + case 'h': + if (isRelative) { s[1] += deltaX; } + deltaX = s[1] - s[1].toFixed(d); + s[1] = +s[1].toFixed(d); + return; + + case 'V': + case 'v': + if (isRelative) { s[1] += deltaY; } + deltaY = s[1] - s[1].toFixed(d); + s[1] = +s[1].toFixed(d); + return; + + case 'Z': + case 'z': + deltaX = contourStartDeltaX; + deltaY = contourStartDeltaY; + return; + + case 'M': + case 'm': + if (isRelative) { + s[1] += deltaX; + s[2] += deltaY; + } + + deltaX = s[1] - s[1].toFixed(d); + deltaY = s[2] - s[2].toFixed(d); + + contourStartDeltaX = deltaX; + contourStartDeltaY = deltaY; + + s[1] = +s[1].toFixed(d); + s[2] = +s[2].toFixed(d); + return; + + case 'A': + case 'a': + // [cmd, rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] + if (isRelative) { + s[6] += deltaX; + s[7] += deltaY; + } + + deltaX = s[6] - s[6].toFixed(d); + deltaY = s[7] - s[7].toFixed(d); + + s[1] = +s[1].toFixed(d); + s[2] = +s[2].toFixed(d); + s[3] = +s[3].toFixed(d + 2); // better precision for rotation + s[6] = +s[6].toFixed(d); + s[7] = +s[7].toFixed(d); + return; + + default: + // a c l q s t + l = s.length; + + if (isRelative) { + s[l - 2] += deltaX; + s[l - 1] += deltaY; + } + + deltaX = s[l - 2] - s[l - 2].toFixed(d); + deltaY = s[l - 1] - s[l - 1].toFixed(d); + + s.forEach(function (val, i) { + if (!i) { return; } + s[i] = +s[i].toFixed(d); + }); + return; + } + }); + + return this; +}; + + +// Apply iterator function to all segments. If function returns result, +// current segment will be replaced to array of returned segments. +// If empty array is returned, current regment will be deleted. +// +SvgPath.prototype.iterate = function (iterator, keepLazyStack) { + var segments = this.segments, + replacements = {}, + needReplace = false, + lastX = 0, + lastY = 0, + countourStartX = 0, + countourStartY = 0; + var i, j, newSegments; + + if (!keepLazyStack) { + this.__evaluateStack(); + } + + segments.forEach(function (s, index) { + + var res = iterator(s, index, lastX, lastY); + + if (Array.isArray(res)) { + replacements[index] = res; + needReplace = true; + } + + var isRelative = (s[0] === s[0].toLowerCase()); + + // calculate absolute X and Y + switch (s[0]) { + case 'm': + case 'M': + lastX = s[1] + (isRelative ? lastX : 0); + lastY = s[2] + (isRelative ? lastY : 0); + countourStartX = lastX; + countourStartY = lastY; + return; + + case 'h': + case 'H': + lastX = s[1] + (isRelative ? lastX : 0); + return; + + case 'v': + case 'V': + lastY = s[1] + (isRelative ? lastY : 0); + return; + + case 'z': + case 'Z': + // That make sence for multiple contours + lastX = countourStartX; + lastY = countourStartY; + return; + + default: + lastX = s[s.length - 2] + (isRelative ? lastX : 0); + lastY = s[s.length - 1] + (isRelative ? lastY : 0); + } + }); + + // Replace segments if iterator return results + + if (!needReplace) { return this; } + + newSegments = []; + + for (i = 0; i < segments.length; i++) { + if (typeof replacements[i] !== 'undefined') { + for (j = 0; j < replacements[i].length; j++) { + newSegments.push(replacements[i][j]); + } + } else { + newSegments.push(segments[i]); + } + } + + this.segments = newSegments; + + return this; +}; + + +// Converts segments from relative to absolute +// +SvgPath.prototype.abs = function () { + + this.iterate(function (s, index, x, y) { + var name = s[0], + nameUC = name.toUpperCase(), + i; + + // Skip absolute commands + if (name === nameUC) { return; } + + s[0] = nameUC; + + switch (name) { + case 'v': + // v has shifted coords parity + s[1] += y; + return; + + case 'a': + // ARC is: ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] + // touch x, y only + s[6] += x; + s[7] += y; + return; + + default: + for (i = 1; i < s.length; i++) { + s[i] += i % 2 ? x : y; // odd values are X, even - Y + } + } + }, true); + + return this; +}; + + +// Converts segments from absolute to relative +// +SvgPath.prototype.rel = function () { + + this.iterate(function (s, index, x, y) { + var name = s[0], + nameLC = name.toLowerCase(), + i; + + // Skip relative commands + if (name === nameLC) { return; } + + // Don't touch the first M to avoid potential confusions. + if (index === 0 && name === 'M') { return; } + + s[0] = nameLC; + + switch (name) { + case 'V': + // V has shifted coords parity + s[1] -= y; + return; + + case 'A': + // ARC is: ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] + // touch x, y only + s[6] -= x; + s[7] -= y; + return; + + default: + for (i = 1; i < s.length; i++) { + s[i] -= i % 2 ? x : y; // odd values are X, even - Y + } + } + }, true); + + return this; +}; + + +// Converts arcs to cubic bézier curves +// +SvgPath.prototype.unarc = function () { + this.iterate(function (s, index, x, y) { + var new_segments, nextX, nextY, result = [], name = s[0]; + + // Skip anything except arcs + if (name !== 'A' && name !== 'a') { return null; } + + if (name === 'a') { + // convert relative arc coordinates to absolute + nextX = x + s[6]; + nextY = y + s[7]; + } else { + nextX = s[6]; + nextY = s[7]; + } + + new_segments = a2c(x, y, nextX, nextY, s[4], s[5], s[1], s[2], s[3]); + + // Degenerated arcs can be ignored by renderer, but should not be dropped + // to avoid collisions with `S A S` and so on. Replace with empty line. + if (new_segments.length === 0) { + return [ [ s[0] === 'a' ? 'l' : 'L', s[6], s[7] ] ]; + } + + new_segments.forEach(function (s) { + result.push([ 'C', s[2], s[3], s[4], s[5], s[6], s[7] ]); + }); + + return result; + }); + + return this; +}; + + +// Converts smooth curves (with missed control point) to generic curves +// +SvgPath.prototype.unshort = function () { + var segments = this.segments; + var prevControlX, prevControlY, prevSegment; + var curControlX, curControlY; + + // TODO: add lazy evaluation flag when relative commands supported + + this.iterate(function (s, idx, x, y) { + var name = s[0], nameUC = name.toUpperCase(), isRelative; + + // First command MUST be M|m, it's safe to skip. + // Protect from access to [-1] for sure. + if (!idx) { return; } + + if (nameUC === 'T') { // quadratic curve + isRelative = (name === 't'); + + prevSegment = segments[idx - 1]; + + if (prevSegment[0] === 'Q') { + prevControlX = prevSegment[1] - x; + prevControlY = prevSegment[2] - y; + } else if (prevSegment[0] === 'q') { + prevControlX = prevSegment[1] - prevSegment[3]; + prevControlY = prevSegment[2] - prevSegment[4]; + } else { + prevControlX = 0; + prevControlY = 0; + } + + curControlX = -prevControlX; + curControlY = -prevControlY; + + if (!isRelative) { + curControlX += x; + curControlY += y; + } + + segments[idx] = [ + isRelative ? 'q' : 'Q', + curControlX, curControlY, + s[1], s[2] + ]; + + } else if (nameUC === 'S') { // cubic curve + isRelative = (name === 's'); + + prevSegment = segments[idx - 1]; + + if (prevSegment[0] === 'C') { + prevControlX = prevSegment[3] - x; + prevControlY = prevSegment[4] - y; + } else if (prevSegment[0] === 'c') { + prevControlX = prevSegment[3] - prevSegment[5]; + prevControlY = prevSegment[4] - prevSegment[6]; + } else { + prevControlX = 0; + prevControlY = 0; + } + + curControlX = -prevControlX; + curControlY = -prevControlY; + + if (!isRelative) { + curControlX += x; + curControlY += y; + } + + segments[idx] = [ + isRelative ? 'c' : 'C', + curControlX, curControlY, + s[1], s[2], s[3], s[4] + ]; + } + }); + + return this; +}; + + +module.exports = SvgPath; + +},{"./a2c":2,"./ellipse":3,"./matrix":4,"./path_parse":5,"./transform_parse":7}],7:[function(require,module,exports){ +'use strict'; + + +var Matrix = require('./matrix'); + +var operations = { + matrix: true, + scale: true, + rotate: true, + translate: true, + skewX: true, + skewY: true +}; + +var CMD_SPLIT_RE = /\s*(matrix|translate|scale|rotate|skewX|skewY)\s*\(\s*(.+?)\s*\)[\s,]*/; +var PARAMS_SPLIT_RE = /[\s,]+/; + + +module.exports = function transformParse(transformString) { + var matrix = new Matrix(); + var cmd, params; + + // Split value into ['', 'translate', '10 50', '', 'scale', '2', '', 'rotate', '-45', ''] + transformString.split(CMD_SPLIT_RE).forEach(function (item) { + + // Skip empty elements + if (!item.length) { return; } + + // remember operation + if (typeof operations[item] !== 'undefined') { + cmd = item; + return; + } + + // extract params & att operation to matrix + params = item.split(PARAMS_SPLIT_RE).map(function (i) { + return +i || 0; + }); + + // If params count is not correct - ignore command + switch (cmd) { + case 'matrix': + if (params.length === 6) { + matrix.matrix(params); + } + return; + + case 'scale': + if (params.length === 1) { + matrix.scale(params[0], params[0]); + } else if (params.length === 2) { + matrix.scale(params[0], params[1]); + } + return; + + case 'rotate': + if (params.length === 1) { + matrix.rotate(params[0], 0, 0); + } else if (params.length === 3) { + matrix.rotate(params[0], params[1], params[2]); + } + return; + + case 'translate': + if (params.length === 1) { + matrix.translate(params[0], 0); + } else if (params.length === 2) { + matrix.translate(params[0], params[1]); + } + return; + + case 'skewX': + if (params.length === 1) { + matrix.skewX(params[0]); + } + return; + + case 'skewY': + if (params.length === 1) { + matrix.skewY(params[0]); + } + return; + } + }); + + return matrix; +}; + +},{"./matrix":4}],8:[function(require,module,exports){ +/*! https://mths.be/cssesc v1.0.1 by @mathias */ +'use strict'; + +var object = {}; +var hasOwnProperty = object.hasOwnProperty; +var merge = function merge(options, defaults) { + if (!options) { + return defaults; + } + var result = {}; + for (var key in defaults) { + // `if (defaults.hasOwnProperty(key) { … }` is not needed here, since + // only recognized option names are used. + result[key] = hasOwnProperty.call(options, key) ? options[key] : defaults[key]; + } + return result; +}; + +var regexAnySingleEscape = /[ -,\.\/;-@\[-\^`\{-~]/; +var regexSingleEscape = /[ -,\.\/;-@\[\]\^`\{-~]/; +var regexAlwaysEscape = /['"\\]/; +var regexExcessiveSpaces = /(^|\\+)?(\\[A-F0-9]{1,6})\x20(?![a-fA-F0-9\x20])/g; + +// https://mathiasbynens.be/notes/css-escapes#css +var cssesc = function cssesc(string, options) { + options = merge(options, cssesc.options); + if (options.quotes != 'single' && options.quotes != 'double') { + options.quotes = 'single'; + } + var quote = options.quotes == 'double' ? '"' : '\''; + var isIdentifier = options.isIdentifier; + + var firstChar = string.charAt(0); + var output = ''; + var counter = 0; + var length = string.length; + while (counter < length) { + var character = string.charAt(counter++); + var codePoint = character.charCodeAt(); + var value = void 0; + // If it’s not a printable ASCII character… + if (codePoint < 0x20 || codePoint > 0x7E) { + if (codePoint >= 0xD800 && codePoint <= 0xDBFF && counter < length) { + // It’s a high surrogate, and there is a next character. + var extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { + // next character is low surrogate + codePoint = ((codePoint & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000; + } else { + // It’s an unmatched surrogate; only append this code unit, in case + // the next code unit is the high surrogate of a surrogate pair. + counter--; + } + } + value = '\\' + codePoint.toString(16).toUpperCase() + ' '; + } else { + if (options.escapeEverything) { + if (regexAnySingleEscape.test(character)) { + value = '\\' + character; + } else { + value = '\\' + codePoint.toString(16).toUpperCase() + ' '; + } + // Note: `:` could be escaped as `\:`, but that fails in IE < 8. + } else if (/[\t\n\f\r\x0B:]/.test(character)) { + if (!isIdentifier && character == ':') { + value = character; + } else { + value = '\\' + codePoint.toString(16).toUpperCase() + ' '; + } + } else if (character == '\\' || !isIdentifier && (character == '"' && quote == character || character == '\'' && quote == character) || isIdentifier && regexSingleEscape.test(character)) { + value = '\\' + character; + } else { + value = character; + } + } + output += value; + } + + if (isIdentifier) { + if (/^_/.test(output)) { + // Prevent IE6 from ignoring the rule altogether (in case this is for an + // identifier used as a selector) + output = '\\_' + output.slice(1); + } else if (/^-[-\d]/.test(output)) { + output = '\\-' + output.slice(1); + } else if (/\d/.test(firstChar)) { + output = '\\3' + firstChar + ' ' + output.slice(1); + } + } + + // Remove spaces after `\HEX` escapes that are not followed by a hex digit, + // since they’re redundant. Note that this is only possible if the escape + // sequence isn’t preceded by an odd number of backslashes. + output = output.replace(regexExcessiveSpaces, function ($0, $1, $2) { + if ($1 && $1.length % 2) { + // It’s not safe to remove the space, so don’t. + return $0; + } + // Strip the space. + return ($1 || '') + $2; + }); + + if (!isIdentifier && options.wrap) { + return quote + output + quote; + } + return output; +}; + +// Expose default options (so they can be overridden globally). +cssesc.options = { + 'escapeEverything': false, + 'isIdentifier': false, + 'quotes': 'single', + 'wrap': false +}; + +cssesc.version = '1.0.1'; + +module.exports = cssesc; + +},{}],9:[function(require,module,exports){ +// parse +// ===== + +// states +// ------ + +var PLAIN = 0; +var STRINGS = 1; +var ESCAPING = 2; +var IDENTIFIER = 3; +var SEPARATING = 4; + +// patterns +// -------- + +var identifierPattern = /[a-z0-9_-]/i; +var spacePattern = /[\s\t]/; + +// --- + +var parse = function(str) { + + // vars + // ---- + + var starting = true; + var state = PLAIN; + var buffer = ''; + var i = 0; + var quote; + var c; + + // result + // ------ + + var names = []; + + // parse + // ----- + + while (true) { + + c = str[i]; + + if (state === PLAIN) { + + if (!c && starting) { + + break; + + } else if (!c && !starting) { + + throw new Error('Parse error'); + + } else if (c === '"' || c === "'") { + + quote = c; + state = STRINGS; + starting = false; + + } else if (spacePattern.test(c)) { + } else if (identifierPattern.test(c)) { + + state = IDENTIFIER; + starting = false; + i--; + + } else { + + throw new Error('Parse error'); + + } + + } else if (state === STRINGS) { + + if (!c) { + + throw new Error('Parse Error'); + + } else if (c === "\\") { + + state = ESCAPING; + + } else if (c === quote) { + + names.push(buffer); + buffer = ''; + state = SEPARATING; + + } else { + + buffer += c; + + } + + } else if (state === ESCAPING) { + + if (c === quote || c === "\\") { + + buffer += c; + state = STRINGS; + + } else { + + throw new Error('Parse error'); + + } + + } else if (state === IDENTIFIER) { + + if (!c) { + + names.push(buffer); + break; + + } else if (identifierPattern.test(c)) { + + buffer += c; + + } else if (c === ',') { + + names.push(buffer); + buffer = ''; + state = PLAIN; + + } else if (spacePattern.test(c)) { + + names.push(buffer); + buffer = ''; + state = SEPARATING; + + } else { + + throw new Error('Parse error'); + + } + + } else if (state === SEPARATING) { + + if (!c) { + + break; + + } else if (c === ',') { + + state = PLAIN; + + } else if (spacePattern.test(c)) { + } else { + + throw new Error('Parse error'); + + } + + } + + i++; + + } + + // result + // ------ + + return names; + +}; + +// stringify +// ========= + +// pattern +// ------- + +var stringsPattern = /[^a-z0-9_-]/i; + +// --- + +var stringify = function(names, options) { + + // quote + // ----- + + var quote = options && options.quote || '"'; + if (quote !== '"' && quote !== "'") { + throw new Error('Quote must be `\'` or `"`'); + } + var quotePattern = new RegExp(quote, 'g'); + + // stringify + // --------- + + var safeNames = []; + + for (var i = 0; i < names.length; ++i) { + var name = names[i]; + + if (stringsPattern.test(name)) { + name = name + .replace(/\\/g, "\\\\") + .replace(quotePattern, "\\" + quote); + name = quote + name + quote; + } + safeNames.push(name); + } + + // result + // ------ + + return safeNames.join(', '); +}; + +// export +// ====== + +module.exports = { + parse: parse, + stringify: stringify, +}; + +},{}],10:[function(require,module,exports){ +/** + * A class to parse color values + * @author Stoyan Stefanov + * @link http://www.phpied.com/rgb-color-parser-in-javascript/ + * @license Use it if you like it + */ +(function (global) { +function RGBColor(color_string) +{ + this.ok = false; + + // strip any leading # + if (color_string.charAt(0) == '#') { // remove # if any + color_string = color_string.substr(1,6); + } + + color_string = color_string.replace(/ /g,''); + color_string = color_string.toLowerCase(); + + // before getting into regexps, try simple matches + // and overwrite the input + var simple_colors = { + aliceblue: 'f0f8ff', + antiquewhite: 'faebd7', + aqua: '00ffff', + aquamarine: '7fffd4', + azure: 'f0ffff', + beige: 'f5f5dc', + bisque: 'ffe4c4', + black: '000000', + blanchedalmond: 'ffebcd', + blue: '0000ff', + blueviolet: '8a2be2', + brown: 'a52a2a', + burlywood: 'deb887', + cadetblue: '5f9ea0', + chartreuse: '7fff00', + chocolate: 'd2691e', + coral: 'ff7f50', + cornflowerblue: '6495ed', + cornsilk: 'fff8dc', + crimson: 'dc143c', + cyan: '00ffff', + darkblue: '00008b', + darkcyan: '008b8b', + darkgoldenrod: 'b8860b', + darkgray: 'a9a9a9', + darkgreen: '006400', + darkkhaki: 'bdb76b', + darkmagenta: '8b008b', + darkolivegreen: '556b2f', + darkorange: 'ff8c00', + darkorchid: '9932cc', + darkred: '8b0000', + darksalmon: 'e9967a', + darkseagreen: '8fbc8f', + darkslateblue: '483d8b', + darkslategray: '2f4f4f', + darkturquoise: '00ced1', + darkviolet: '9400d3', + deeppink: 'ff1493', + deepskyblue: '00bfff', + dimgray: '696969', + dodgerblue: '1e90ff', + feldspar: 'd19275', + firebrick: 'b22222', + floralwhite: 'fffaf0', + forestgreen: '228b22', + fuchsia: 'ff00ff', + gainsboro: 'dcdcdc', + ghostwhite: 'f8f8ff', + gold: 'ffd700', + goldenrod: 'daa520', + gray: '808080', + green: '008000', + greenyellow: 'adff2f', + honeydew: 'f0fff0', + hotpink: 'ff69b4', + indianred : 'cd5c5c', + indigo : '4b0082', + ivory: 'fffff0', + khaki: 'f0e68c', + lavender: 'e6e6fa', + lavenderblush: 'fff0f5', + lawngreen: '7cfc00', + lemonchiffon: 'fffacd', + lightblue: 'add8e6', + lightcoral: 'f08080', + lightcyan: 'e0ffff', + lightgoldenrodyellow: 'fafad2', + lightgrey: 'd3d3d3', + lightgreen: '90ee90', + lightpink: 'ffb6c1', + lightsalmon: 'ffa07a', + lightseagreen: '20b2aa', + lightskyblue: '87cefa', + lightslateblue: '8470ff', + lightslategray: '778899', + lightsteelblue: 'b0c4de', + lightyellow: 'ffffe0', + lime: '00ff00', + limegreen: '32cd32', + linen: 'faf0e6', + magenta: 'ff00ff', + maroon: '800000', + mediumaquamarine: '66cdaa', + mediumblue: '0000cd', + mediumorchid: 'ba55d3', + mediumpurple: '9370d8', + mediumseagreen: '3cb371', + mediumslateblue: '7b68ee', + mediumspringgreen: '00fa9a', + mediumturquoise: '48d1cc', + mediumvioletred: 'c71585', + midnightblue: '191970', + mintcream: 'f5fffa', + mistyrose: 'ffe4e1', + moccasin: 'ffe4b5', + navajowhite: 'ffdead', + navy: '000080', + oldlace: 'fdf5e6', + olive: '808000', + olivedrab: '6b8e23', + orange: 'ffa500', + orangered: 'ff4500', + orchid: 'da70d6', + palegoldenrod: 'eee8aa', + palegreen: '98fb98', + paleturquoise: 'afeeee', + palevioletred: 'd87093', + papayawhip: 'ffefd5', + peachpuff: 'ffdab9', + peru: 'cd853f', + pink: 'ffc0cb', + plum: 'dda0dd', + powderblue: 'b0e0e6', + purple: '800080', + red: 'ff0000', + rosybrown: 'bc8f8f', + royalblue: '4169e1', + saddlebrown: '8b4513', + salmon: 'fa8072', + sandybrown: 'f4a460', + seagreen: '2e8b57', + seashell: 'fff5ee', + sienna: 'a0522d', + silver: 'c0c0c0', + skyblue: '87ceeb', + slateblue: '6a5acd', + slategray: '708090', + snow: 'fffafa', + springgreen: '00ff7f', + steelblue: '4682b4', + tan: 'd2b48c', + teal: '008080', + thistle: 'd8bfd8', + tomato: 'ff6347', + turquoise: '40e0d0', + violet: 'ee82ee', + violetred: 'd02090', + wheat: 'f5deb3', + white: 'ffffff', + whitesmoke: 'f5f5f5', + yellow: 'ffff00', + yellowgreen: '9acd32' + }; + for (var key in simple_colors) { + if (color_string == key) { + color_string = simple_colors[key]; + } + } + // emd of simple type-in colors + + // array of color definition objects + var color_defs = [ + { + re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, + example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'], + process: function (bits){ + return [ + parseInt(bits[1]), + parseInt(bits[2]), + parseInt(bits[3]) + ]; + } + }, + { + re: /^(\w{2})(\w{2})(\w{2})$/, + example: ['#00ff00', '336699'], + process: function (bits){ + return [ + parseInt(bits[1], 16), + parseInt(bits[2], 16), + parseInt(bits[3], 16) + ]; + } + }, + { + re: /^(\w{1})(\w{1})(\w{1})$/, + example: ['#fb0', 'f0f'], + process: function (bits){ + return [ + parseInt(bits[1] + bits[1], 16), + parseInt(bits[2] + bits[2], 16), + parseInt(bits[3] + bits[3], 16) + ]; + } + } + ]; + + // search through the definitions to find a match + for (var i = 0; i < color_defs.length; i++) { + var re = color_defs[i].re; + var processor = color_defs[i].process; + var bits = re.exec(color_string); + if (bits) { + var channels = processor(bits); + this.r = channels[0]; + this.g = channels[1]; + this.b = channels[2]; + this.ok = true; + } + + } + + // validate/cleanup values + this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r); + this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g); + this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b); + + // some getters + this.toRGB = function () { + return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')'; + } + this.toHex = function () { + var r = this.r.toString(16); + var g = this.g.toString(16); + var b = this.b.toString(16); + if (r.length == 1) r = '0' + r; + if (g.length == 1) g = '0' + g; + if (b.length == 1) b = '0' + b; + return '#' + r + g + b; + } + + // help + this.getHelpXML = function () { + + var examples = new Array(); + // add regexps + for (var i = 0; i < color_defs.length; i++) { + var example = color_defs[i].example; + for (var j = 0; j < example.length; j++) { + examples[examples.length] = example[j]; + } + } + // add type-in colors + for (var sc in simple_colors) { + examples[examples.length] = sc; + } + + var xml = document.createElement('ul'); + xml.setAttribute('id', 'rgbcolor-examples'); + for (var i = 0; i < examples.length; i++) { + try { + var list_item = document.createElement('li'); + var list_color = new RGBColor(examples[i]); + var example_div = document.createElement('div'); + example_div.style.cssText = + 'margin: 3px; ' + + 'border: 1px solid black; ' + + 'background:' + list_color.toHex() + '; ' + + 'color:' + list_color.toHex() + ; + example_div.appendChild(document.createTextNode('test')); + var list_item_value = document.createTextNode( + ' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex() + ); + list_item.appendChild(example_div); + list_item.appendChild(list_item_value); + xml.appendChild(list_item); + + } catch(e){} + } + return xml; + + } + +} +if (typeof define === "function" && define.amd) { + define(function () { + return RGBColor; + }); +} else if (typeof module !== "undefined" && module.exports) { + module.exports = RGBColor; +} else { + global.RGBColor = RGBColor; +} +return RGBColor; +})(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this); + +},{}],11:[function(require,module,exports){ +/* +The MIT License (MIT) + +Copyright (c) 2015-2017 yWorks GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/** + * Renders an svg element to a jsPDF document. + * For accurate results a DOM document is required (mainly used for text size measurement and image format conversion) + * @param element {HTMLElement} The svg element, which will be cloned, so the original stays unchanged. + * @param pdf {jsPDF} The jsPDF object. + * @param options {object} An object that may contain render options. Currently supported are: + * scale: The global factor by which everything is scaled. + * xOffset, yOffset: Offsets that are added to every coordinate AFTER scaling (They are not + * influenced by the scale attribute). + */ +(function (global) { + var RGBColor; + var SvgPath; + var FontFamily; + var cssEsc; + + var _pdf; // jsPDF pdf-document + + var cToQ = 2 / 3; // ratio to convert quadratic bezier curves to cubic ones + + var iriReference = /url\(["']?#([^"']+)["']?\)/; + + // groups: 1: mime-type (+ charset), 2: mime-type (w/o charset), 3: charset, 4: base64?, 5: body + var dataUrlRegex = /^\s*data:(([^/,;]+\/[^/,;]+)(?:;([^,;=]+=[^,;=]+))?)?(?:;(base64))?,(.*\s*)$/i; + + var svgNamespaceURI = "http://www.w3.org/2000/svg"; + + + // pathSegList is marked deprecated in chrome, so parse the d attribute manually if necessary + var getPathSegList = function (node) { + var d = node.getAttribute("d"); + + // Replace arcs before path segment list is handled + if (SvgPath) { + d = SvgPath(d).unshort().unarc().abs().toString(); + node.setAttribute('d', d); + } + + var pathSegList = node.pathSegList; + + if (pathSegList) { + return pathSegList; + } + + pathSegList = []; + + var regex = /([a-df-zA-DF-Z])([^a-df-zA-DF-Z]*)/g, + match; + while (match = regex.exec(d)) { + var coords = parseFloats(match[2]); + + var type = match[1]; + var length = "zZ".indexOf(type) >= 0 ? 0 : + "hHvV".indexOf(type) >= 0 ? 1 : + "mMlLtT".indexOf(type) >= 0 ? 2 : + "sSqQ".indexOf(type) >= 0 ? 4 : + "aA".indexOf(type) >= 0 ? 7 : + "cC".indexOf(type) >= 0 ? 6 : -1; + + var i = 0; + do { + var pathSeg = {pathSegTypeAsLetter: type}; + switch (type) { + case "h": + case "H": + pathSeg.x = coords[i]; + break; + + case "v": + case "V": + pathSeg.y = coords[i]; + break; + + case "c": + case "C": + pathSeg.x1 = coords[i + length - 6]; + pathSeg.y1 = coords[i + length - 5]; + case "s": + case "S": + pathSeg.x2 = coords[i + length - 4]; + pathSeg.y2 = coords[i + length - 3]; + case "t": + case "T": + case "l": + case "L": + case "m": + case "M": + pathSeg.x = coords[i + length - 2]; + pathSeg.y = coords[i + length - 1]; + break; + + case "q": + case "Q": + pathSeg.x1 = coords[i]; + pathSeg.y1 = coords[i + 1]; + pathSeg.x = coords[i + 2]; + pathSeg.y = coords[i + 3]; + break; + case "a": + case "A": + throw new Error("Cannot convert Arcs without SvgPath package"); + } + + pathSegList.push(pathSeg); + + // "If a moveto is followed by multiple pairs of coordinates, the subsequent pairs are treated as implicit + // lineto commands" + if (type === "m") { + type = "l"; + } else if (type === "M") { + type = "L"; + } + + i += length; + } while(i < coords.length); + } + + pathSegList.getItem = function (i) { + return this[i] + }; + pathSegList.numberOfItems = pathSegList.length; + + return pathSegList; + }; + + // returns an attribute of a node, either from the node directly or from css + var getAttribute = function (node, propertyNode, propertyCss) { + propertyCss = propertyCss || propertyNode; + return node.getAttribute(propertyNode) || node.style && node.style[propertyCss]; + }; + + /** + * @param {Element} node + * @param {string} tagsString + * @return {boolean} + */ + var nodeIs = function (node, tagsString) { + return tagsString.split(",").indexOf(node.tagName.toLowerCase()) >= 0; + }; + + var forEachChild = function (node, fn) { + // copy list of children, as the original might be modified + var children = []; + for (var i = 0; i < node.childNodes.length; i++) { + var childNode = node.childNodes[i]; + if (childNode.nodeName.charAt(0) !== "#") + children.push(childNode); + } + for (i = 0; i < children.length; i++) { + fn(i, children[i]); + } + }; + + var getAngle = function (from, to) { + return Math.atan2(to[1] - from[1], to[0] - from[0]); + }; + + function normalize(v) { + var length = Math.sqrt(v[0] * v[0] + v[1] * v[1]); + return [v[0] / length, v[1] / length]; + } + + function getDirectionVector(from, to) { + var v = [to[0] - from[0], to[1] - from[1]]; + return normalize(v); + } + + function addVectors(v1, v2) { + return [v1[0] + v2[0], v1[1] + v2[1]]; + } + + // mirrors p1 at p2 + var mirrorPoint = function (p1, p2) { + var dx = p2[0] - p1[0]; + var dy = p2[1] - p1[1]; + + return [p1[0] + 2 * dx, p1[1] + 2 * dy]; + }; + + // transforms a cubic bezier control point to a quadratic one: returns from + (2/3) * (to - from) + var toCubic = function (from, to) { + return [cToQ * (to[0] - from[0]) + from[0], cToQ * (to[1] - from[1]) + from[1]]; + }; + + // extracts a control point from a previous path segment (for t,T,s,S segments) + var getControlPointFromPrevious = function (i, from, list, prevX, prevY) { + var prev = list.getItem(i - 1); + var p2; + if (i > 0 && (prev.pathSegTypeAsLetter === "C" || prev.pathSegTypeAsLetter === "S")) { + p2 = mirrorPoint([prev.x2, prev.y2], from); + } else if (i > 0 && (prev.pathSegTypeAsLetter === "c" || prev.pathSegTypeAsLetter === "s")) { + p2 = mirrorPoint([prev.x2 + prevX, prev.y2 + prevY], from); + } else { + p2 = [from[0], from[1]]; + } + return p2; + }; + + /** + * @param {Element} rootSvg + * @constructor + * @property {Object.} renderedElements + * @property {Element} rootSvg + */ + function ReferencesHandler(rootSvg) { + this.renderedElements = {}; + this.rootSvg = rootSvg; + } + + /** + * @param {string} id + * @return {*} + */ + ReferencesHandler.prototype.getRendered = function (id) { + if (this.renderedElements.hasOwnProperty(id)) { + return this.renderedElements[id]; + } + + var node = this.rootSvg.querySelector("#" + cssEsc(id, {isIdentifier: true})); + + if (nodeIs(node, "lineargradient")) { + putGradient(node, "axial", [ + node.getAttribute("x1") || 0, + node.getAttribute("y1") || 0, + node.getAttribute("x2") || 1, + node.getAttribute("y2") || 0 + ]); + } else if (nodeIs(node, "radialgradient")) { + putGradient(node, "radial", [ + node.getAttribute("fx") || node.getAttribute("cx") || 0.5, + node.getAttribute("fy") || node.getAttribute("cy") || 0.5, + 0, + node.getAttribute("cx") || 0.5, + node.getAttribute("cy") || 0.5, + node.getAttribute("r") || 0.5 + ]); + } else if (nodeIs(node, "pattern")) { + pattern(node, this, AttributeState.default()) + } else if (nodeIs(node, "marker")) { + // the transformations directly at the node are written to the pdf form object transformation matrix + var tfMatrix = computeNodeTransform(node); + var bBox = getUntransformedBBox(node); + + _pdf.beginFormObject(bBox[0], bBox[1], bBox[2], bBox[3], tfMatrix); + renderChildren(node, _pdf.unitMatrix, this, false, false, AttributeState.default()); + _pdf.endFormObject(node.getAttribute("id")); + } else if (!nodeIs(node, "clippath")) { + // all other nodes will be rendered as PDF form object + renderNode(node, _pdf.unitMatrix, this, true, false, AttributeState.default()); + } + + this.renderedElements[id] = node; + return node; + }; + + var AttributeState = function () { + this.xmlSpace = null; + this.color = null; + this.fill = null; + this.fillOpacity = 1.0; + // this.fillRule = null; + this.fontFamily = null; + this.fontSize = 16; + this.fontStyle = null; + // this.fontVariant = null; + this.fontWeight = null; + this.opacity = 1.0; + this.stroke = null; + this.strokeDasharray = null; + this.strokeDashoffset = null; + this.strokeLinecap = null; + this.strokeLinejoin = null; + this.strokeMiterlimit = 4.0; + this.strokeOpacity = 1.0; + this.strokeWidth = 1.0; + // this.textAlign = null; + this.textAnchor = null; + this.visibility = null; + }; + + AttributeState.default = function () { + var attributeState = new AttributeState(); + + attributeState.xmlSpace = "default"; + attributeState.fill = new RGBColor("rgb(0, 0, 0)"); + attributeState.fillOpacity = 1.0; + // attributeState.fillRule = "nonzero"; + attributeState.fontFamily = "times"; + attributeState.fontSize = 16; + attributeState.fontStyle = "normal"; + // attributeState.fontVariant = "normal"; + attributeState.fontWeight = "normal"; + attributeState.opacity = 1.0; + attributeState.stroke = null; + attributeState.strokeDasharray = null; + attributeState.strokeDashoffset = null; + attributeState.strokeLinecap = "butt"; + attributeState.strokeLinejoin = "miter"; + attributeState.strokeMiterlimit = 4.0; + attributeState.strokeOpacity = 1.0; + attributeState.strokeWidth = 1.0; + // attributeState.textAlign = "start"; + attributeState.textAnchor = "start"; + attributeState.visibility = "visible"; + + return attributeState; + }; + + AttributeState.prototype.clone = function () { + var clone = new AttributeState(); + + clone.xmlSpace = this.xmlSpace; + clone.fill = this.fill; + clone.fillOpacity = this.fillOpacity; + // clone.fillRule = this.fillRule; + clone.fontFamily = this.fontFamily; + clone.fontSize = this.fontSize; + clone.fontStyle = this.fontStyle; + // clone.fontVariant = this.fontVariant; + clone.fontWeight = this.fontWeight; + clone.opacity = this.opacity; + clone.stroke = this.stroke; + clone.strokeDasharray = this.strokeDasharray; + clone.strokeDashoffset = this.strokeDashoffset; + clone.strokeLinecap = this.strokeLinecap; + clone.strokeLinejoin = this.strokeLinejoin; + clone.strokeMiterlimit = this.strokeMiterlimit; + clone.strokeOpacity = this.strokeOpacity; + clone.strokeWidth = this.strokeWidth; + // clone.textAlign = this.textAlign; + clone.textAnchor = this.textAnchor; + clone.visibility = this.visibility; + + return clone; + }; + + /** + * @constructor + * @property {Marker[]} markers + */ + function MarkerList() { + this.markers = []; + } + + /** + * @param {Marker} marker + */ + MarkerList.prototype.addMarker = function addMarker(marker) { + this.markers.push(marker); + }; + + MarkerList.prototype.draw = function (tfMatrix, refsHandler, attributeState) { + for (var i = 0; i < this.markers.length; i++) { + var marker = this.markers[i]; + + var tf; + var angle = marker.angle, anchor = marker.anchor; + var cos = Math.cos(angle); + var sin = Math.sin(angle); + // position at and rotate around anchor + tf = new _pdf.Matrix(cos, sin, -sin, cos, anchor[0], anchor[1]); + // scale with stroke-width + tf = _pdf.matrixMult(new _pdf.Matrix(attributeState.strokeWidth, 0, 0, attributeState.strokeWidth, 0, 0), tf); + + tf = _pdf.matrixMult(tf, tfMatrix); + + // as the marker is already scaled by the current line width we must not apply the line width twice! + _pdf.saveGraphicsState(); + _pdf.setLineWidth(1.0); + refsHandler.getRendered(marker.id); + _pdf.doFormObject(marker.id, tf); + _pdf.restoreGraphicsState(); + } + }; + + /** + * @param {string} id + * @param {[number,number]} anchor + * @param {number} angle + */ + function Marker(id, anchor, angle) { + this.id = id; + this.anchor = anchor; + this.angle = angle; + } + + function removeNewlines(str) { + return str.replace(/[\n\r]/g, ""); + } + + function replaceTabsBySpace(str) { + return str.replace(/[\t]/g, " "); + } + + function consolidateSpaces(str) { + return str.replace(/ +/g, " "); + } + + function trimLeft(str) { + return str.replace(/^\s+/,""); + } + + function trimRight(str) { + return str.replace(/\s+$/,""); + } + + function computeViewBoxTransform(node, viewBox, eX, eY, eWidth, eHeight) { + var vbX = viewBox[0]; + var vbY = viewBox[1]; + var vbWidth = viewBox[2]; + var vbHeight = viewBox[3]; + + var scaleX = eWidth / vbWidth; + var scaleY = eHeight / vbHeight; + + var align, meetOrSlice; + var preserveAspectRatio = node.getAttribute("preserveAspectRatio"); + if (preserveAspectRatio) { + var alignAndMeetOrSlice = preserveAspectRatio.split(" "); + if (alignAndMeetOrSlice[0] === "defer") { + alignAndMeetOrSlice = alignAndMeetOrSlice.slice(1); + } + + align = alignAndMeetOrSlice[0]; + meetOrSlice = alignAndMeetOrSlice[1] || "meet"; + } else { + align = "xMidYMid"; + meetOrSlice = "meet" + } + + if (align !== "none") { + if (meetOrSlice === "meet") { + // uniform scaling with min scale + scaleX = scaleY = Math.min(scaleX, scaleY); + } else if (meetOrSlice === "slice") { + // uniform scaling with max scale + scaleX = scaleY = Math.max(scaleX, scaleY); + } + } + + var translateX = eX - (vbX * scaleX); + var translateY = eY - (vbY * scaleY); + + if (align.indexOf("xMid") >= 0) { + translateX += (eWidth - vbWidth * scaleX) / 2; + } else if (align.indexOf("xMax") >= 0) { + translateX += eWidth - vbWidth * scaleX; + } + + if (align.indexOf("yMid") >= 0) { + translateY += (eHeight - vbHeight * scaleY) / 2; + } else if (align.indexOf("yMax") >= 0) { + translateY += (eHeight - vbHeight * scaleY); + } + + var translate = new _pdf.Matrix(1, 0, 0, 1, translateX, translateY); + var scale = new _pdf.Matrix(scaleX, 0, 0, scaleY, 0, 0); + + return _pdf.matrixMult(scale, translate); + } + + // computes the transform directly applied at the node (such as viewbox scaling and the "transform" atrribute) + // x,y,cx,cy,r,... are omitted + var computeNodeTransform = function (node) { + var viewBox, x, y; + var nodeTransform = _pdf.unitMatrix; + if (nodeIs(node, "svg,g")) { + x = parseFloat(node.getAttribute("x")) || 0; + y = parseFloat(node.getAttribute("y")) || 0; + + viewBox = node.getAttribute("viewBox"); + if (viewBox) { + var box = parseFloats(viewBox); + var width = parseFloat(node.getAttribute("width")) || box[2]; + var height = parseFloat(node.getAttribute("height")) || box[3]; + nodeTransform = computeViewBoxTransform(node, box, x, y, width, height) + } else { + nodeTransform = new _pdf.Matrix(1, 0, 0, 1, x, y); + } + } else if (nodeIs(node, "marker")) { + x = parseFloat(node.getAttribute("refX")) || 0; + y = parseFloat(node.getAttribute("refY")) || 0; + + viewBox = node.getAttribute("viewBox"); + if (viewBox) { + var bounds = parseFloats(viewBox); + bounds[0] = bounds[1] = 0; // for some reason vbX anc vbY seem to be ignored for markers + nodeTransform = computeViewBoxTransform(node, + bounds, + 0, + 0, + parseFloat(node.getAttribute("markerWidth")) || 3, + parseFloat(node.getAttribute("markerHeight")) || 3 + ); + nodeTransform = _pdf.matrixMult(new _pdf.Matrix(1, 0, 0, 1, -x, -y), nodeTransform); + } else { + nodeTransform = new _pdf.Matrix(1, 0, 0, 1, -x, -y); + } + } + + var transformString = node.getAttribute("transform"); + if (!transformString) + return nodeTransform; + else + return _pdf.matrixMult(nodeTransform, parseTransform(transformString)); + }; + + // parses the "points" string used by polygons and returns an array of points + var parsePointsString = function (string) { + var floats = parseFloats(string); + var result = []; + for (var i = 0; i < floats.length - 1; i += 2) { + var x = floats[i]; + var y = floats[i + 1]; + result.push([x, y]); + } + return result; + }; + + // parses the "transform" string + var parseTransform = function (transformString) { + if (!transformString) + return _pdf.unitMatrix; + + var mRegex = /^\s*matrix\(([^\)]+)\)\s*/, + tRegex = /^\s*translate\(([^\)]+)\)\s*/, + rRegex = /^\s*rotate\(([^\)]+)\)\s*/, + sRegex = /^\s*scale\(([^\)]+)\)\s*/, + sXRegex = /^\s*skewX\(([^\)]+)\)\s*/, + sYRegex = /^\s*skewY\(([^\)]+)\)\s*/; + + var resultMatrix = _pdf.unitMatrix, m; + + while (transformString.length > 0) { + var match = mRegex.exec(transformString); + if (match) { + m = parseFloats(match[1]); + resultMatrix = _pdf.matrixMult(new _pdf.Matrix(m[0], m[1], m[2], m[3], m[4], m[5]), resultMatrix); + transformString = transformString.substr(match[0].length); + } + match = rRegex.exec(transformString); + if (match) { + m = parseFloats(match[1]); + var a = Math.PI * m[0] / 180; + resultMatrix = _pdf.matrixMult(new _pdf.Matrix(Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), 0, 0), resultMatrix); + if (m[1] && m[2]) { + var t1 = new _pdf.Matrix(1, 0, 0, 1, m[1], m[2]); + var t2 = new _pdf.Matrix(1, 0, 0, 1, -m[1], -m[2]); + resultMatrix = _pdf.matrixMult(t2, _pdf.matrixMult(resultMatrix, t1)); + } + transformString = transformString.substr(match[0].length); + } + match = tRegex.exec(transformString); + if (match) { + m = parseFloats(match[1]); + resultMatrix = _pdf.matrixMult(new _pdf.Matrix(1, 0, 0, 1, m[0], m[1] || 0), resultMatrix); + transformString = transformString.substr(match[0].length); + } + match = sRegex.exec(transformString); + if (match) { + m = parseFloats(match[1]); + if (!m[1]) + m[1] = m[0]; + resultMatrix = _pdf.matrixMult(new _pdf.Matrix(m[0], 0, 0, m[1], 0, 0), resultMatrix); + transformString = transformString.substr(match[0].length); + } + match = sXRegex.exec(transformString); + if (match) { + m = parseFloat(match[1]); + resultMatrix = _pdf.matrixMult(new _pdf.Matrix(1, 0, Math.tan(m), 1, 0, 0), resultMatrix); + transformString = transformString.substr(match[0].length); + } + match = sYRegex.exec(transformString); + if (match) { + m = parseFloat(match[1]); + resultMatrix = _pdf.matrixMult(new _pdf.Matrix(1, Math.tan(m), 0, 1, 0, 0), resultMatrix); + transformString = transformString.substr(match[0].length); + } + } + return resultMatrix; + }; + + // parses a comma, sign and/or whitespace separated string of floats and returns the single floats in an array + var parseFloats = function (str) { + var floats = [], match, + regex = /[+-]?(?:(?:\d+\.?\d*)|(?:\d*\.?\d+))(?:[eE][+-]?\d+)?/g; + while(match = regex.exec(str)) { + floats.push(parseFloat(match[0])); + } + return floats; + }; + + // extends RGBColor by rgba colors as RGBColor is not capable of it + var parseColor = function (colorString) { + if (colorString === "transparent") { + var transparent = new RGBColor("rgb(0,0,0)"); + transparent.a = 0; + return transparent + } + + var match = /\s*rgba\(((?:[^,\)]*,){3}[^,\)]*)\)\s*/.exec(colorString); + if (match) { + var floats = parseFloats(match[1]); + var color = new RGBColor("rgb(" + floats.slice(0,3).join(",") + ")"); + color.a = floats[3]; + return color; + } else { + return new RGBColor(colorString); + } + }; + + // multiplies a vector with a matrix: vec' = vec * matrix + var multVecMatrix = function (vec, matrix) { + var x = vec[0]; + var y = vec[1]; + return [ + matrix.a * x + matrix.c * y + matrix.e, + matrix.b * x + matrix.d * y + matrix.f + ]; + }; + + // returns the untransformed bounding box [x, y, width, height] of an svg element (quite expensive for path and polygon objects, as + // the whole points/d-string has to be processed) + var getUntransformedBBox = function (node) { + if (getAttribute(node, "display") === "none") { + return [0, 0, 0, 0]; + } + + var i, minX, minY, maxX, maxY, viewBox, vb, boundingBox; + var pf = parseFloat; + + if (nodeIs(node, "polygon,polyline")) { + var points = parsePointsString(node.getAttribute("points")); + minX = Number.POSITIVE_INFINITY; + minY = Number.POSITIVE_INFINITY; + maxX = Number.NEGATIVE_INFINITY; + maxY = Number.NEGATIVE_INFINITY; + for (i = 0; i < points.length; i++) { + var point = points[i]; + minX = Math.min(minX, point[0]); + maxX = Math.max(maxX, point[0]); + minY = Math.min(minY, point[1]); + maxY = Math.max(maxY, point[1]); + } + boundingBox = [ + minX, + minY, + maxX - minX, + maxY - minY + ]; + } else if (nodeIs(node, "path")) { + var list = getPathSegList(node); + minX = Number.POSITIVE_INFINITY; + minY = Number.POSITIVE_INFINITY; + maxX = Number.NEGATIVE_INFINITY; + maxY = Number.NEGATIVE_INFINITY; + var x = 0, y = 0; + var prevX, prevY, newX, newY; + var p2, p3, to; + for (i = 0; i < list.numberOfItems; i++) { + var seg = list.getItem(i); + var cmd = seg.pathSegTypeAsLetter; + switch (cmd) { + case "H": + newX = seg.x; + newY = y; + break; + case "h": + newX = seg.x + x; + newY = y; + break; + case "V": + newX = x; + newY = seg.y; + break; + case "v": + newX = x; + newY = seg.y + y; + break; + case "C": + p2 = [seg.x1, seg.y1]; + p3 = [seg.x2, seg.y2]; + to = [seg.x, seg.y]; + break; + case "c": + p2 = [seg.x1 + x, seg.y1 + y]; + p3 = [seg.x2 + x, seg.y2 + y]; + to = [seg.x + x, seg.y + y]; + break; + case "S": + p2 = getControlPointFromPrevious(i, [x, y], list, prevX, prevY); + p3 = [seg.x2, seg.y2]; + to = [seg.x, seg.y]; + break; + case "s": + p2 = getControlPointFromPrevious(i, [x, y], list, prevX, prevY); + p3 = [seg.x2 + x, seg.y2 + y]; + to = [seg.x + x, seg.y + y]; + break; + case "Q": + pf = [seg.x1, seg.y1]; + p2 = toCubic([x, y], pf); + p3 = toCubic([seg.x, seg.y], pf); + to = [seg.x, seg.y]; + break; + case "q": + pf = [seg.x1 + x, seg.y1 + y]; + p2 = toCubic([x, y], pf); + p3 = toCubic([x + seg.x, y + seg.y], pf); + to = [seg.x + x, seg.y + y]; + break; + case "T": + p2 = getControlPointFromPrevious(i, [x, y], list, prevX, prevY); + p2 = toCubic([x, y], pf); + p3 = toCubic([seg.x, seg.y], pf); + to = [seg.x, seg.y]; + break; + case "t": + pf = getControlPointFromPrevious(i, [x, y], list, prevX, prevY); + p2 = toCubic([x, y], pf); + p3 = toCubic([x + seg.x, y + seg.y], pf); + to = [seg.x + x, seg.y + y]; + break; + // TODO: A,a + } + if ("sScCqQtT".indexOf(cmd) >= 0) { + prevX = x; + prevY = y; + } + if ("MLCSQT".indexOf(cmd) >= 0) { + x = seg.x; + y = seg.y; + } else if ("mlcsqt".indexOf(cmd) >= 0) { + x = seg.x + x; + y = seg.y + y; + } else if ("zZ".indexOf(cmd) < 0) { + x = newX; + y = newY; + } + if ("CSQTcsqt".indexOf(cmd) >= 0) { + minX = Math.min(minX, x, p2[0], p3[0], to[0]); + maxX = Math.max(maxX, x, p2[0], p3[0], to[0]); + minY = Math.min(minY, y, p2[1], p3[1], to[1]); + maxY = Math.max(maxY, y, p2[1], p3[1], to[1]); + } else { + minX = Math.min(minX, x); + maxX = Math.max(maxX, x); + minY = Math.min(minY, y); + maxY = Math.max(maxY, y); + } + } + boundingBox = [ + minX, + minY, + maxX - minX, + maxY - minY + ]; + } else if (nodeIs(node, "svg")) { + viewBox = node.getAttribute("viewBox"); + if (viewBox) { + vb = parseFloats(viewBox); + } + return [ + pf(node.getAttribute("x")) || (vb && vb[0]) || 0, + pf(node.getAttribute("y")) || (vb && vb[1]) || 0, + pf(node.getAttribute("width")) || (vb && vb[2]) || 0, + pf(node.getAttribute("height")) || (vb && vb[3]) || 0 + ]; + } else if (nodeIs(node, "g,clippath")) { + boundingBox = [0, 0, 0, 0]; + forEachChild(node, function (i, node) { + var nodeBox = getUntransformedBBox(node); + boundingBox = [ + Math.min(boundingBox[0], nodeBox[0]), + Math.min(boundingBox[1], nodeBox[1]), + Math.max(boundingBox[0] + boundingBox[2], nodeBox[0] + nodeBox[2]) - Math.min(boundingBox[0], nodeBox[0]), + Math.max(boundingBox[1] + boundingBox[3], nodeBox[1] + nodeBox[3]) - Math.min(boundingBox[1], nodeBox[1]) + ]; + }); + } else if (nodeIs(node, "marker")) { + viewBox = node.getAttribute("viewBox"); + if (viewBox) { + vb = parseFloats(viewBox); + } + return [ + (vb && vb[0]) || 0, + (vb && vb[1]) || 0, + (vb && vb[2]) || pf(node.getAttribute("marker-width")) || 0, + (vb && vb[3]) || pf(node.getAttribute("marker-height")) || 0 + ]; + } else if (nodeIs(node, "pattern")) { + return [ + pf(node.getAttribute("x")) || 0, + pf(node.getAttribute("y")) || 0, + pf(node.getAttribute("width")) || 0, + pf(node.getAttribute("height")) || 0 + ] + } else { + // TODO: check if there are other possible coordinate attributes + var x1 = pf(node.getAttribute("x1")) || pf(node.getAttribute("x")) || pf((node.getAttribute("cx")) - pf(node.getAttribute("r"))) || 0; + var x2 = pf(node.getAttribute("x2")) || (x1 + pf(node.getAttribute("width"))) || (pf(node.getAttribute("cx")) + pf(node.getAttribute("r"))) || 0; + var y1 = pf(node.getAttribute("y1")) || pf(node.getAttribute("y")) || (pf(node.getAttribute("cy")) - pf(node.getAttribute("r"))) || 0; + var y2 = pf(node.getAttribute("y2")) || (y1 + pf(node.getAttribute("height"))) || (pf(node.getAttribute("cy")) + pf(node.getAttribute("r"))) || 0; + boundingBox = [ + Math.min(x1, x2), + Math.min(y1, y2), + Math.max(x1, x2) - Math.min(x1, x2), + Math.max(y1, y2) - Math.min(y1, y2) + ]; + } + + if (!nodeIs(node, "marker,svg,g")) { + // add line-width + var lineWidth = getAttribute(node, "stroke-width") || 1; + var miterLimit = getAttribute(node, "stroke-miterlimit"); + // miterLength / lineWidth = 1 / sin(phi / 2) + miterLimit && (lineWidth *= 0.5 / (Math.sin(Math.PI / 12))); + return [ + boundingBox[0] - lineWidth, + boundingBox[1] - lineWidth, + boundingBox[2] + 2 * lineWidth, + boundingBox[3] + 2 * lineWidth + ]; + } + + return boundingBox; + }; + + // transforms a bounding box and returns a new rect that contains it + var transformBBox = function (box, matrix) { + var bl = multVecMatrix([box[0], box[1]], matrix); + var br = multVecMatrix([box[0] + box[2], box[1]], matrix); + var tl = multVecMatrix([box[0], box[1] + box[3]], matrix); + var tr = multVecMatrix([box[0] + box[2], box[1] + box[3]], matrix); + + var bottom = Math.min(bl[1], br[1], tl[1], tr[1]); + var left = Math.min(bl[0], br[0], tl[0], tr[0]); + var top = Math.max(bl[1], br[1], tl[1], tr[1]); + var right = Math.max(bl[0], br[0], tl[0], tr[0]); + + return [ + left, + bottom, + right - left, + top - bottom + ] + }; + + // draws a polygon + var polygon = function (node, refsHandler, attributeState, closed) { + if (!node.hasAttribute("points") || node.getAttribute("points") === "") { + return; + } + + var points = parsePointsString(node.getAttribute("points")); + var lines = [{op: "m", c: points[0]}]; + var i, angle; + for (i = 1; i < points.length; i++) { + lines.push({op: "l", c: points[i]}); + } + + if (closed) { + lines.push({op: "h"}); + } + + _pdf.path(lines); + + var markerEnd = node.getAttribute("marker-end"), + markerStart = node.getAttribute("marker-start"), + markerMid = node.getAttribute("marker-mid"); + + if (markerStart || markerMid || markerEnd) { + var length = lines.length; + var markers = new MarkerList(); + if (markerStart) { + markerStart = iriReference.exec(markerStart)[1]; + angle = addVectors(getDirectionVector(lines[0].c, lines[1].c), getDirectionVector(lines[length - 2].c, lines[0].c)); + markers.addMarker(new Marker(markerStart, lines[0].c, Math.atan2(angle[1], angle[0]))); + } + + if (markerMid) { + markerMid = iriReference.exec(markerMid)[1]; + var prevAngle = getDirectionVector(lines[0].c, lines[1].c), curAngle; + for (i = 1; i < lines.length - 2; i++) { + curAngle = getDirectionVector(lines[i].c, lines[i + 1].c); + angle = addVectors(prevAngle, curAngle); + markers.addMarker(new Marker(markerMid, lines[i].c, Math.atan2(angle[1], angle[0]))); + prevAngle = curAngle; + } + + curAngle = getDirectionVector(lines[length - 2].c, lines[0].c); + angle = addVectors(prevAngle, curAngle); + markers.addMarker(new Marker(markerMid, lines[length - 2].c, Math.atan2(angle[1], angle[0]))); + } + + if (markerEnd) { + markerEnd = iriReference.exec(markerEnd)[1]; + angle = addVectors(getDirectionVector(lines[0].c, lines[1].c), getDirectionVector(lines[length - 2].c, lines[0].c)); + markers.addMarker(new Marker(markerEnd, lines[0].c, Math.atan2(angle[1], angle[0]))); + } + + markers.draw(_pdf.unitMatrix, refsHandler, attributeState); + } + }; + + // draws an image + var image = function (node) { + var width = parseFloat(node.getAttribute("width")), + height = parseFloat(node.getAttribute("height")), + x = parseFloat(node.getAttribute("x") || 0), + y = parseFloat(node.getAttribute("y") || 0); + + + var imageUrl = node.getAttribute("xlink:href") || node.getAttribute("href"); + + var dataUrl = imageUrl.match(dataUrlRegex); + if (dataUrl && dataUrl[2] === "image/svg+xml") { + var svgText = dataUrl[5]; + if (dataUrl[4] === "base64") { + svgText = atob(svgText); + } else { + svgText = decodeURIComponent(svgText); + } + + var parser = new DOMParser(); + var svgElement = parser.parseFromString(svgText, "image/svg+xml").firstElementChild; + + // unless preserveAspectRatio starts with "defer", the preserveAspectRatio attribute of the svg is ignored + var preserveAspectRatio = node.getAttribute("preserveAspectRatio"); + if (!preserveAspectRatio + || preserveAspectRatio.indexOf("defer") < 0 + || !svgElement.getAttribute("preserveAspectRatio")) { + svgElement.setAttribute("preserveAspectRatio", preserveAspectRatio); + } + + svgElement.setAttribute("x", String(x)); + svgElement.setAttribute("y", String(y)); + svgElement.setAttribute("width", String(width)); + svgElement.setAttribute("height", String(height)); + + renderNode(svgElement, _pdf.unitMatrix, {}, false, false, AttributeState.default()); + return; + } + + try { + _pdf.addImage( + imageUrl, + "", // will be ignored anyways if imageUrl is a data url + x, + y, + width, + height + ); + } catch (e) { + (typeof console === "object" + && console.warn + && console.warn('svg2pdfjs: Images with external resource link are not supported! ("' + imageUrl + '")')); + } + }; + + // draws a path + var path = function (node, tfMatrix, refsHandler, withinClipPath, attributeState) { + var list = getPathSegList(node); + var markerEnd = node.getAttribute("marker-end"), + markerStart = node.getAttribute("marker-start"), + markerMid = node.getAttribute("marker-mid"); + + markerEnd && (markerEnd = iriReference.exec(markerEnd)[1]); + markerStart && (markerStart = iriReference.exec(markerStart)[1]); + markerMid && (markerMid = iriReference.exec(markerMid)[1]); + + var getLinesFromPath = function () { + var x = 0, y = 0; + var x0 = x, y0 = y; + var prevX, prevY, newX, newY; + var to, p, p2, p3; + var lines = []; + var markers = new MarkerList(); + var op; + var prevAngle = [0, 0], curAngle; + + for (var i = 0; i < list.numberOfItems; i++) { + var seg = list.getItem(i); + var cmd = seg.pathSegTypeAsLetter; + switch (cmd) { + case "M": + x0 = x; + y0 = y; + to = [seg.x, seg.y]; + op = "m"; + break; + case "m": + x0 = x; + y0 = y; + to = [seg.x + x, seg.y + y]; + op = "m"; + break; + case "L": + to = [seg.x, seg.y]; + op = "l"; + break; + case "l": + to = [seg.x + x, seg.y + y]; + op = "l"; + break; + case "H": + to = [seg.x, y]; + op = "l"; + newX = seg.x; + newY = y; + break; + case "h": + to = [seg.x + x, y]; + op = "l"; + newX = seg.x + x; + newY = y; + break; + case "V": + to = [x, seg.y]; + op = "l"; + newX = x; + newY = seg.y; + break; + case "v": + to = [x, seg.y + y]; + op = "l"; + newX = x; + newY = seg.y + y; + break; + case "C": + p2 = [seg.x1, seg.y1]; + p3 = [seg.x2, seg.y2]; + to = [seg.x, seg.y]; + break; + case "c": + p2 = [seg.x1 + x, seg.y1 + y]; + p3 = [seg.x2 + x, seg.y2 + y]; + to = [seg.x + x, seg.y + y]; + break; + case "S": + p2 = getControlPointFromPrevious(i, [x, y], list, prevX, prevY); + p3 = [seg.x2, seg.y2]; + to = [seg.x, seg.y]; + break; + case "s": + p2 = getControlPointFromPrevious(i, [x, y], list, prevX, prevY); + p3 = [seg.x2 + x, seg.y2 + y]; + to = [seg.x + x, seg.y + y]; + break; + case "Q": + p = [seg.x1, seg.y1]; + p2 = toCubic([x, y], p); + p3 = toCubic([seg.x, seg.y], p); + to = [seg.x, seg.y]; + break; + case "q": + p = [seg.x1 + x, seg.y1 + y]; + p2 = toCubic([x, y], p); + p3 = toCubic([x + seg.x, y + seg.y], p); + to = [seg.x + x, seg.y + y]; + break; + case "T": + p = getControlPointFromPrevious(i, [x, y], list, prevX, prevY); + p2 = toCubic([x, y], p); + p3 = toCubic([seg.x, seg.y], p); + to = [seg.x, seg.y]; + break; + case "t": + p = getControlPointFromPrevious(i, [x, y], list, prevX, prevY); + p2 = toCubic([x, y], p); + p3 = toCubic([x + seg.x, y + seg.y], p); + to = [seg.x + x, seg.y + y]; + break; + // TODO: A,a + case "Z": + case "z": + x = x0; + y = y0; + lines.push({op: "h"}); + break; + } + + var hasStartMarker = markerStart + && (i === 1 + || ("mM".indexOf(cmd) < 0 && "mM".indexOf(list.getItem(i - 1).pathSegTypeAsLetter) >= 0)); + var hasEndMarker = markerEnd + && (i === list.numberOfItems - 1 + || ("mM".indexOf(cmd) < 0 && "mM".indexOf(list.getItem(i + 1).pathSegTypeAsLetter) >= 0)); + var hasMidMarker = markerMid + && i > 0 + && !(i === 1 && "mM".indexOf(list.getItem(i - 1).pathSegTypeAsLetter) >= 0); + + if ("sScCqQtT".indexOf(cmd) >= 0) { + hasStartMarker && markers.addMarker(new Marker(markerStart, [x, y], getAngle([x, y], p2))); + hasEndMarker && markers.addMarker(new Marker(markerEnd, to, getAngle(p3, to))); + if (hasMidMarker) { + curAngle = getDirectionVector([x, y], p2); + curAngle = "mM".indexOf(list.getItem(i - 1).pathSegTypeAsLetter) >= 0 ? + curAngle : normalize(addVectors(prevAngle, curAngle)); + markers.addMarker(new Marker(markerMid, [x, y], Math.atan2(curAngle[1], curAngle[0]))); + } + + prevAngle = getDirectionVector(p3, to); + + prevX = x; + prevY = y; + + if (withinClipPath) { + p2 = multVecMatrix(p2, tfMatrix); + p3 = multVecMatrix(p3, tfMatrix); + to = multVecMatrix(to, tfMatrix); + } + + lines.push({ + op: "c", c: [ + p2[0], p2[1], + p3[0], p3[1], + to[0], to[1] + ] + }); + } else if ("lLhHvVmM".indexOf(cmd) >= 0) { + curAngle = getDirectionVector([x, y], to); + hasStartMarker && markers.addMarker(new Marker(markerStart, [x, y], Math.atan2(curAngle[1], curAngle[0]))); + hasEndMarker && markers.addMarker(new Marker(markerEnd, to, Math.atan2(curAngle[1], curAngle[0]))); + if (hasMidMarker) { + var angle = "mM".indexOf(cmd) >= 0 ? + prevAngle : "mM".indexOf(list.getItem(i - 1).pathSegTypeAsLetter) >= 0 ? + curAngle : normalize(addVectors(prevAngle, curAngle)); + markers.addMarker(new Marker(markerMid, [x, y], Math.atan2(angle[1], angle[0]))); + } + prevAngle = curAngle; + + if (withinClipPath) { + to = multVecMatrix(to, tfMatrix); + } + + lines.push({op: op, c: to}); + } + + if ("MLCSQT".indexOf(cmd) >= 0) { + x = seg.x; + y = seg.y; + } else if ("mlcsqt".indexOf(cmd) >= 0) { + x = seg.x + x; + y = seg.y + y; + } else if ("zZ".indexOf(cmd) < 0) { + x = newX; + y = newY; + } + } + + return {lines: lines, markers: markers}; + }; + var lines = getLinesFromPath(); + + if (lines.lines.length > 0) { + _pdf.path(lines.lines); + } + + if (markerEnd || markerStart || markerMid) { + lines.markers.draw(_pdf.unitMatrix, refsHandler, attributeState); + } + }; + + // draws the element referenced by a use node, makes use of pdf's XObjects/FormObjects so nodes are only written once + // to the pdf document. This highly reduces the file size and computation time. + var use = function (node, tfMatrix, refsHandler) { + var url = (node.getAttribute("href") || node.getAttribute("xlink:href")); + // just in case someone has the idea to use empty use-tags, wtf??? + if (!url) + return; + + // get the size of the referenced form object (to apply the correct scaling) + var id = url.substring(1); + refsHandler.getRendered(id); + var formObject = _pdf.getFormObject(id); + + // scale and position it right + var x = node.getAttribute("x") || 0; + var y = node.getAttribute("y") || 0; + var width = node.getAttribute("width") || formObject.width; + var height = node.getAttribute("height") || formObject.height; + var t = new _pdf.Matrix(width / formObject.width || 0, 0, 0, height / formObject.height || 0, x, y); + t = _pdf.matrixMult(t, tfMatrix); + _pdf.doFormObject(id, t); + }; + + // draws a line + var line = function (node, refsHandler, attributeState) { + var p1 = [parseFloat(node.getAttribute('x1') || 0), parseFloat(node.getAttribute('y1') || 0)]; + var p2 = [parseFloat(node.getAttribute('x2') || 0), parseFloat(node.getAttribute('y2') || 0)]; + + if (attributeState.stroke !== null){ + _pdf.line(p1[0], p1[1], p2[0], p2[1]); + } + + var markerStart = node.getAttribute("marker-start"), + markerEnd = node.getAttribute("marker-end"); + + if (markerStart || markerEnd) { + var markers = new MarkerList(); + var angle = getAngle(p1, p2); + if (markerStart) { + markers.addMarker(new Marker(iriReference.exec(markerStart)[1], p1, angle)); + } + if (markerEnd) { + markers.addMarker(new Marker(iriReference.exec(markerEnd)[1], p2, angle)); + } + markers.draw(_pdf.unitMatrix, refsHandler, attributeState); + } + }; + + // draws a rect + var rect = function (node) { + _pdf.roundedRect( + parseFloat(node.getAttribute('x')) || 0, + parseFloat(node.getAttribute('y')) || 0, + parseFloat(node.getAttribute('width')), + parseFloat(node.getAttribute('height')), + parseFloat(node.getAttribute('rx')) || 0, + parseFloat(node.getAttribute('ry')) || 0 + ); + }; + + // draws an ellipse + var ellipse = function (node) { + _pdf.ellipse( + parseFloat(node.getAttribute('cx')) || 0, + parseFloat(node.getAttribute('cy')) || 0, + parseFloat(node.getAttribute('rx')), + parseFloat(node.getAttribute('ry')) + ); + }; + + // draws a circle + var circle = function (node) { + var radius = parseFloat(node.getAttribute('r')) || 0; + _pdf.ellipse( + parseFloat(node.getAttribute('cx')) || 0, + parseFloat(node.getAttribute('cy')) || 0, + radius, + radius + ); + }; + + // applies text transformations to a text node + var transformText = function (node, text) { + var textTransform = getAttribute(node, "text-transform"); + switch (textTransform) { + case "uppercase": return text.toUpperCase(); + case "lowercase": return text.toLowerCase(); + default: return text; + // TODO: capitalize, full-width + } + }; + + /** + * Canvas text measuring is a lot faster than svg measuring. However, it is inaccurate for some fonts. So test each + * font once and decide if canvas is accurate enough. + * @param {string} text + * @param {string} fontFamily + * @returns {function(string, string, string, string, string)} + */ + var getMeasureFunction = (function getMeasureFunction() { + /** + * @param {string} text + * @param {string} fontFamily + * @param {string} fontSize + * @param {string} fontStyle + * @param {string} fontWeight + */ + function canvasTextMeasure(text, fontFamily, fontSize, fontStyle, fontWeight) { + var canvas = document.createElement("canvas"); + var context = canvas.getContext("2d"); + + context.font = [fontStyle, fontWeight, fontSize, fontFamily].join(" "); + return context.measureText(text).width; + } + + /** + * @param {string} text + * @param {string} fontFamily + * @param {string} fontSize + * @param {string} fontStyle + * @param {string} fontWeight + */ + function svgTextMeasure(text, fontFamily, fontSize, fontStyle, fontWeight) { + var textNode = document.createElementNS(svgNamespaceURI, "text"); + textNode.setAttribute("font-family", fontFamily); + textNode.setAttribute("font-size", fontSize); + textNode.setAttribute("font-style", fontStyle); + textNode.setAttribute("font-weight", fontWeight); + textNode.setAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:space", "preserve"); + textNode.appendChild(document.createTextNode(text)); + + var svg = document.createElementNS(svgNamespaceURI, "svg"); + svg.appendChild(textNode); + svg.setAttribute("visibility", "hidden"); + document.body.appendChild(svg); + + var width = textNode.getBBox().width; + + document.body.removeChild(svg); + + return width; + } + + var testString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789!\"$%&/()=?'\\+*-_.:,;^}][{#~|<>"; + var epsilon = 0.1; + var measureMethods = {}; + + return function getMeasureFunction(fontFamily) { + var method = measureMethods[fontFamily]; + if (!method) { + var fontSize = "16px"; + var fontStyle = "normal"; + var fontWeight = "normal"; + var canvasWidth = canvasTextMeasure(testString, fontFamily, fontSize, fontStyle, fontWeight); + var svgWidth = svgTextMeasure(testString, fontFamily, fontSize, fontStyle, fontWeight); + + method = Math.abs(canvasWidth - svgWidth) < epsilon ? canvasTextMeasure : svgTextMeasure; + + measureMethods[fontFamily] = method; + } + + return method; + } + })(); + + /** + * @param {string} text + * @param {AttributeState} attributeState + * @returns {number} + */ + function measureTextWidth(text, attributeState) { + if (text.length === 0) { + return 0; + } + + var fontFamily = attributeState.fontFamily; + var measure = getMeasureFunction(fontFamily); + + return measure(text, attributeState.fontFamily, attributeState.fontSize + "px", attributeState.fontStyle, attributeState.fontWeight); + } + + /** + * @param {string} text + * @param {AttributeState} attributeState + * @returns {number} + */ + function getTextOffset(text, attributeState) { + var textAnchor = attributeState.textAnchor; + if (textAnchor === "start") { + return 0; + } + + var width = measureTextWidth(text, attributeState); + + var xOffset = 0; + switch (textAnchor) { + case "end": + xOffset = width; + break; + case "middle": + xOffset = width / 2; + break; + } + + return xOffset; + } + + /** + * @param {string} textAnchor + * @param {number} originX + * @param {number} originY + * @constructor + */ + function TextChunk(textAnchor, originX, originY) { + this.texts = []; + this.textNodes = []; + this.textAnchor = textAnchor; + this.originX = originX; + this.originY = originY; + } + + /** + * @param {SVGElement} tSpan + * @param {string} text + */ + TextChunk.prototype.add = function(tSpan, text) { + this.texts.push(text); + this.textNodes.push(tSpan); + }; + /** + * Outputs the chunk to pdf. + * @param {jsPDF.Matrix} transform + * @param {AttributeState} attributeState + * @returns {[number, number]} The last current text position. + */ + TextChunk.prototype.put = function (transform, attributeState) { + var i, textNode; + + var xs = [], ys = [], attributeStates = []; + var currentTextX = this.originX, currentTextY = this.originY; + var minX = currentTextX, maxX = currentTextX; + for (i = 0; i < this.textNodes.length; i++) { + textNode = this.textNodes[i]; + + var x = currentTextX; + var y = currentTextY; + + if (textNode.nodeName === "#text") { + textNodeAttributeState = attributeState + } else { + var textNodeAttributeState = attributeState.clone(); + var tSpanColor = getAttribute(textNode, "fill"); + setTextProperties(textNode, tSpanColor && new RGBColor(tSpanColor), textNodeAttributeState); + + var tSpanDx = textNode.getAttribute("dx"); + if (tSpanDx !== null) { + x += toPixels(tSpanDx, textNodeAttributeState.fontSize); + } + + var tSpanDy = textNode.getAttribute("dy"); + if (tSpanDy !== null) { + y += toPixels(tSpanDy, textNodeAttributeState.fontSize); + } + } + + attributeStates[i] = textNodeAttributeState; + + xs[i] = x; + ys[i] = y; + + currentTextX = x + measureTextWidth(this.texts[i], textNodeAttributeState); + + currentTextY = y; + + minX = Math.min(minX, x); + maxX = Math.max(maxX, currentTextX); + } + + var textOffset; + switch (this.textAnchor) { + case "start": textOffset = 0; break; + case "middle": textOffset = (maxX - minX) / 2; break; + case "end": textOffset = maxX - minX; break; + } + + for (i = 0; i < this.textNodes.length; i++) { + textNode = this.textNodes[i]; + + if (textNode.nodeName !== "#text") { + var tSpanVisibility = getAttribute(textNode, "visibility") || attributeState.visibility; + if (tSpanVisibility === "hidden") { + continue; + } + } + + _pdf.saveGraphicsState(); + putTextProperties(attributeStates[i], attributeState); + + _pdf.text(xs[i] - textOffset, ys[i], this.texts[i], void 0, transform); + + _pdf.restoreGraphicsState(); + } + + return [currentTextX, currentTextY]; + }; + + /** + * Convert em, px and bare number attributes to pixel values + * @param {string} value + * @param {number} pdfFontSize + */ + function toPixels(value, pdfFontSize) { + var match; + + // em + match = value && value.toString().match(/^([\-0-9.]+)em$/); + if (match) { + return parseFloat(match[1]) * pdfFontSize; + } + + // pixels + match = value && value.toString().match(/^([\-0-9.]+)(px|)$/); + if (match) { + return parseFloat(match[1]); + } + return 0; + } + + + function transformXmlSpace(trimmedText, attributeState) { + trimmedText = removeNewlines(trimmedText); + trimmedText = replaceTabsBySpace(trimmedText); + + if (attributeState.xmlSpace === "default") { + trimmedText = trimmedText.trim(); + trimmedText = consolidateSpaces(trimmedText); + } + + return trimmedText; + } + + /** + * Draws a text element and its tspan children. + * @param {SVGElement} node + * @param {jsPDF.Matrix} tfMatrix + * @param {boolean} hasFillColor + * @param {RGBColor} fillRGB + * @param {AttributeState} attributeState + */ + var text = function (node, tfMatrix, hasFillColor, fillRGB, attributeState) { + _pdf.saveGraphicsState(); + + var dx, dy, xOffset = 0; + + var pdfFontSize = _pdf.getFontSize(); + var textX = toPixels(node.getAttribute('x'), pdfFontSize); + var textY = toPixels(node.getAttribute('y'), pdfFontSize); + + dx = toPixels(node.getAttribute("dx"), pdfFontSize); + dy = toPixels(node.getAttribute("dy"), pdfFontSize); + + var visibility = attributeState.visibility; + // when there are no tspans draw the text directly + var tSpanCount = node.childElementCount; + if (tSpanCount === 0) { + var trimmedText = transformXmlSpace(node.textContent, attributeState); + var transformedText = transformText(node, trimmedText); + xOffset = getTextOffset(transformedText, attributeState); + + if (visibility === "visible") { + _pdf.text( + textX + dx - xOffset, + textY + dy, + transformedText, + void 0, + tfMatrix + ); + } + } else { + // otherwise loop over tspans and position each relative to the previous one + var currentTextSegment = new TextChunk(attributeState.textAnchor, textX + dx, textY + dy); + + for (var i = 0; i < node.childNodes.length; i++) { + var textNode = node.childNodes[i]; + if (!textNode.textContent) { + continue; + } + + var xmlSpace = attributeState.xmlSpace; + + if (textNode.nodeName === "#text") { + + } else if (nodeIs(textNode, "tspan")) { + var tSpan = textNode; + + var lastPositions; + + var tSpanAbsX = tSpan.getAttribute("x"); + if (tSpanAbsX !== null) { + var x = toPixels(tSpanAbsX, pdfFontSize); + + lastPositions = currentTextSegment.put(tfMatrix, attributeState); + currentTextSegment = new TextChunk(tSpan.getAttribute("text-anchor") || attributeState.textAnchor, x, lastPositions[1]); + } + + var tSpanAbsY = tSpan.getAttribute("y"); + if (tSpanAbsY !== null) { + var y = toPixels(tSpanAbsY, pdfFontSize); + + lastPositions = currentTextSegment.put(tfMatrix, attributeState); + currentTextSegment = new TextChunk(tSpan.getAttribute("text-anchor") || attributeState.textAnchor, lastPositions[0], y); + } + + var tSpanXmlSpace = tSpan.getAttribute("xml:space"); + if (tSpanXmlSpace) { + xmlSpace = tSpanXmlSpace; + } + } + + trimmedText = textNode.textContent; + trimmedText = removeNewlines(trimmedText); + trimmedText = replaceTabsBySpace(trimmedText); + + if (xmlSpace === "default") { + if (i === 0) { + trimmedText = trimLeft(trimmedText); + } + if (i === tSpanCount - 1) { + trimmedText = trimRight(trimmedText); + } + + trimmedText = consolidateSpaces(trimmedText); + } + + transformedText = transformText(node, trimmedText); + currentTextSegment.add(textNode, transformedText); + } + + currentTextSegment.put(tfMatrix, attributeState); + } + + _pdf.restoreGraphicsState(); + }; + + // renders all children of a node + var renderChildren = function (node, tfMatrix, refsHandler, withinDefs, withinClipPath, attributeState) { + forEachChild(node, function (i, node) { + renderNode(node, tfMatrix, refsHandler, withinDefs, withinClipPath, attributeState); + }); + }; + + // adds a gradient to defs and the pdf document for later use, type is either "axial" or "radial" + // opacity is only supported rudimentary by averaging over all stops + // transforms are applied on use + var putGradient = function (node, type, coords) { + var colors = []; + var opacitySum = 0; + var hasOpacity = false; + var gState; + forEachChild(node, function (i, element) { + // since opacity gradients are hard to realize, average the opacity over the control points + if (element.tagName.toLowerCase() === "stop") { + var color = new RGBColor(getAttribute(element, "stop-color")); + colors.push({ + offset: parseFloat(element.getAttribute("offset")), + color: [color.r, color.g, color.b] + }); + var opacity = getAttribute(element, "stop-opacity"); + if (opacity && opacity != 1) { + opacitySum += parseFloat(opacity); + hasOpacity = true; + } + } + }); + + if (hasOpacity) { + gState = new _pdf.GState({opacity: opacitySum / colors.length}); + } + + var pattern = new _pdf.ShadingPattern(type, coords, colors, gState); + var id = node.getAttribute("id"); + _pdf.addShadingPattern(id, pattern); + }; + + var pattern = function (node, refsHandler, attributeState) { + var id = node.getAttribute("id"); + + // the transformations directly at the node are written to the pattern transformation matrix + var bBox = getUntransformedBBox(node); + var pattern = new _pdf.TilingPattern([bBox[0], bBox[1], bBox[0] + bBox[2], bBox[1] + bBox[3]], bBox[2], bBox[3], + null, _pdf.unitMatrix /* this parameter is ignored !*/); + + _pdf.beginTilingPattern(pattern); + // continue without transformation + renderChildren(node, _pdf.unitMatrix, refsHandler, false, false, attributeState); + _pdf.endTilingPattern(id, pattern); + }; + + var fontAliases = { + "sans-serif": "helvetica", + "verdana": "helvetica", + "arial": "helvetica", + + "fixed": "courier", + "monospace": "courier", + "terminal": "courier", + + "serif": "times", + "cursive": "times", + "fantasy": "times" + }; + + /** + * @param {AttributeState} attributeState + * @param {string[]} fontFamilies + * @return {string} + */ + function findFirstAvailableFontFamily(attributeState, fontFamilies) { + var fontType = ""; + if (attributeState.fontWeight === "bold") { + fontType = "bold"; + } + if (attributeState.fontStyle === "italic") { + fontType += "italic"; + } + if (fontType === "") { + fontType = "normal"; + } + + var availableFonts = _pdf.getFontList(); + var firstAvailable = ""; + var fontIsAvailable = fontFamilies.some(function (font) { + var availableStyles = availableFonts[font]; + if (availableStyles && availableStyles.indexOf(fontType) >= 0) { + firstAvailable = font; + return true; + } + + font = font.toLowerCase(); + if (fontAliases.hasOwnProperty(font)) { + firstAvailable = font; + return true; + } + + return false; + }); + + if (!fontIsAvailable) { + firstAvailable = "times"; + } + + return firstAvailable; + } + + function setTextProperties(node, fillRGB, attributeState) { + if (fillRGB && fillRGB.ok) { + attributeState.fill = fillRGB; + } + + var fontWeight = getAttribute(node, "font-weight"); + if (fontWeight) { + attributeState.fontWeight = fontWeight; + } + + var fontStyle = getAttribute(node, "font-style"); + if (fontStyle) { + attributeState.fontStyle = fontStyle; + } + + var fontFamily = getAttribute(node, "font-family"); + if (fontFamily) { + var fontFamilies = FontFamily.parse(fontFamily); + attributeState.fontFamily = findFirstAvailableFontFamily(attributeState, fontFamilies); + } + + var fontSize = getAttribute(node, "font-size"); + if (fontSize) { + attributeState.fontSize = parseFloat(fontSize); + } + + var textAnchor = getAttribute(node, "text-anchor"); + if (textAnchor) { + attributeState.textAnchor = textAnchor; + } + } + + /** + * @param {AttributeState} attributeState + * @param {AttributeState} parentAttributeState + */ + function putTextProperties(attributeState, parentAttributeState) { + if (attributeState.fontFamily !== parentAttributeState.fontFamily) { + if (fontAliases.hasOwnProperty(attributeState.fontFamily)) { + _pdf.setFont(fontAliases[attributeState.fontFamily]); + } else { + _pdf.setFont(attributeState.fontFamily); + } + } + + if (attributeState.fill !== parentAttributeState.fill && attributeState.fill.ok) { + var fillRGB = attributeState.fill; + _pdf.setTextColor(fillRGB.r, fillRGB.g, fillRGB.b); + } + + if (attributeState.fontWeight !== parentAttributeState.fontWeight + || attributeState.fontStyle !== parentAttributeState.fontStyle) { + var fontType = ""; + if (attributeState.fontWeight === "bold") { + fontType = "bold"; + } + if (attributeState.fontStyle === "italic") { + fontType += "italic"; + } + + if (fontType === "") { + fontType = "normal"; + } + + _pdf.setFontType(fontType); + } + + if (attributeState.fontSize !== parentAttributeState.fontSize) { + _pdf.setFontSize(attributeState.fontSize); + } + } + + + /** + * Renders a svg node. + * @param node The svg element + * @param contextTransform The current transformation matrix + * @param refsHandler The handler that will render references on demand + * @param withinDefs True iff we are top-level within a defs node, so the target can be switched to an pdf form object + * @param {boolean} withinClipPath + * @param {AttributeState} attributeState Keeps track of parent attributes that are inherited automatically + */ + var renderNode = function (node, contextTransform, refsHandler, withinDefs, withinClipPath, attributeState) { + var parentAttributeState = attributeState; + attributeState = attributeState.clone(); + + if (nodeIs(node, "defs,clippath,pattern,lineargradient,radialgradient,marker")) { + // we will only render them on demand + return; + } + + if (getAttribute(node, "display") === "none") { + return; + } + + var visibility = attributeState.visibility = getAttribute(node, "visibility") || attributeState.visibility; + if (visibility === "hidden" && !nodeIs(node, "svg,g,marker,a,pattern,defs,text")) { + return; + } + + var tfMatrix, + hasFillColor = false, + fillRGB = null, + fill = "inherit", + stroke = "inherit", + patternOrGradient = undefined, + bBox; + + // + // Decide about the render target and set the correct transformation + // + + // if we are within a defs node, start a new pdf form object and draw this node and all children on that instead + // of the top-level page + var targetIsFormObject = withinDefs && !nodeIs(node, "lineargradient,radialgradient,pattern,clippath"); + if (targetIsFormObject) { + + // the transformations directly at the node are written to the pdf form object transformation matrix + tfMatrix = computeNodeTransform(node); + bBox = getUntransformedBBox(node); + + _pdf.beginFormObject(bBox[0], bBox[1], bBox[2], bBox[3], tfMatrix); + + // continue without transformation and set withinDefs to false to prevent child nodes from starting new form objects + tfMatrix = _pdf.unitMatrix; + withinDefs = false; + + } else { + tfMatrix = _pdf.matrixMult(computeNodeTransform(node), contextTransform); + + if (!withinClipPath) { + _pdf.saveGraphicsState(); + } + } + + var hasClipPath = node.hasAttribute("clip-path") && node.getAttribute("clip-path") !== "none"; + if (hasClipPath) { + var clipPathId = iriReference.exec(node.getAttribute("clip-path")); + var clipPathNode = refsHandler.getRendered(clipPathId[1]); + + var clipPathMatrix = tfMatrix; + if (clipPathNode.hasAttribute("clipPathUnits") + && clipPathNode.getAttribute("clipPathUnits").toLowerCase() === "objectboundingbox") { + bBox = getUntransformedBBox(node); + clipPathMatrix = _pdf.matrixMult(new _pdf.Matrix(bBox[2], 0, 0, bBox[3], bBox[0], bBox[1]), clipPathMatrix); + } + + // here, browsers show different results for a "transform" attribute on the clipPath element itself: + // IE/Edge considers it, Chrome and Firefox ignore it. However, the specification lists "transform" as a valid + // attribute for clipPath elements, although not explicitly explaining its behavior. This implementation follows + // IE/Edge and considers the "transform" attribute as additional transformation within the coordinate system + // established by the "clipPathUnits" attribute. + clipPathMatrix = _pdf.matrixMult(computeNodeTransform(clipPathNode), clipPathMatrix); + + _pdf.saveGraphicsState(); + _pdf.setCurrentTransformationMatrix(clipPathMatrix); + + renderChildren(clipPathNode, _pdf.unitMatrix, refsHandler, false, true, attributeState); + _pdf.clip().discardPath(); + + // as we cannot use restoreGraphicsState() to reset the transform (this would reset the clipping path, as well), + // we must append the inverse instead + _pdf.setCurrentTransformationMatrix(clipPathMatrix.inversed()); + } + + // + // extract fill and stroke mode + // + + // fill mode + if (nodeIs(node, "g,path,rect,text,ellipse,line,circle,polygon,polyline")) { + function setDefaultColor() { + fillRGB = new RGBColor("rgb(0, 0, 0)"); + hasFillColor = true; + fill = true; + } + + var fillColor = getAttribute(node, "fill"); + if (fillColor) { + var url = iriReference.exec(fillColor); + if (url) { + // probably a gradient or pattern (or something unsupported) + var fillUrl = url[1]; + var fillNode = refsHandler.getRendered(fillUrl); + if (fillNode && nodeIs(fillNode, "lineargradient,radialgradient")) { + + // matrix to convert between gradient space and user space + // for "userSpaceOnUse" this is the current transformation: tfMatrix + // for "objectBoundingBox" or default, the gradient gets scaled and transformed to the bounding box + var gradientUnitsMatrix; + if (!fillNode.hasAttribute("gradientUnits") + || fillNode.getAttribute("gradientUnits").toLowerCase() === "objectboundingbox") { + bBox || (bBox = getUntransformedBBox(node)); + gradientUnitsMatrix = new _pdf.Matrix(bBox[2], 0, 0, bBox[3], bBox[0], bBox[1]); + } else { + gradientUnitsMatrix = _pdf.unitMatrix; + } + + // matrix that is applied to the gradient before any other transformations + var gradientTransform = parseTransform(fillNode.getAttribute("gradientTransform")); + + patternOrGradient = { + key: fillUrl, + matrix: _pdf.matrixMult(gradientTransform, gradientUnitsMatrix) + }; + + fill = true; + } else if (fillNode && nodeIs(fillNode, "pattern")) { + var fillBBox, y, width, height, x; + patternOrGradient = { key: fillUrl }; + + var patternUnitsMatrix = _pdf.unitMatrix; + if (!fillNode.hasAttribute("patternUnits") + || fillNode.getAttribute("patternUnits").toLowerCase() === "objectboundingbox") { + bBox || (bBox = getUntransformedBBox(node)); + patternUnitsMatrix = new _pdf.Matrix(1, 0, 0, 1, bBox[0], bBox[1]); + + // TODO: slightly inaccurate (rounding errors? line width bBoxes?) + fillBBox = getUntransformedBBox(fillNode); + x = fillBBox[0] * bBox[0]; + y = fillBBox[1] * bBox[1]; + width = fillBBox[2] * bBox[2]; + height = fillBBox[3] * bBox[3]; + patternOrGradient.boundingBox = [x, y, x + width, y + height]; + patternOrGradient.xStep = width; + patternOrGradient.yStep = height; + } + + var patternContentUnitsMatrix = _pdf.unitMatrix; + if (fillNode.hasAttribute("patternContentUnits") + && fillNode.getAttribute("patternContentUnits").toLowerCase() === "objectboundingbox") { + bBox || (bBox = getUntransformedBBox(node)); + patternContentUnitsMatrix = new _pdf.Matrix(bBox[2], 0, 0, bBox[3], 0, 0); + + fillBBox = patternOrGradient.boundingBox || getUntransformedBBox(fillNode); + x = fillBBox[0] / bBox[0]; + y = fillBBox[1] / bBox[1]; + width = fillBBox[2] / bBox[2]; + height = fillBBox[3] / bBox[3]; + patternOrGradient.boundingBox = [x, y, x + width, y + height]; + patternOrGradient.xStep = width; + patternOrGradient.yStep = height; + } + + var patternTransformMatrix = _pdf.unitMatrix; + if (fillNode.hasAttribute("patternTransform")) { + patternTransformMatrix = parseTransform(fillNode.getAttribute("patternTransform")); + } + + var matrix = patternContentUnitsMatrix; + matrix = _pdf.matrixMult(matrix, patternUnitsMatrix); + matrix = _pdf.matrixMult(matrix, patternTransformMatrix); + matrix = _pdf.matrixMult(matrix, tfMatrix); + + patternOrGradient.matrix = matrix; + + fill = true; + } else { + // unsupported fill argument -> fill black + setDefaultColor(); + } + } else { + // plain color + fillRGB = parseColor(fillColor); + if (fillRGB.ok) { + hasFillColor = true; + fill = true; + } else { + fill = false; + } + } + } + + // opacity is realized via a pdf graphics state + var fillOpacity = 1.0, strokeOpacity = 1.0; + var nodeFillOpacity = getAttribute(node, "fill-opacity"); + if (nodeFillOpacity) { + fillOpacity *= parseFloat(nodeFillOpacity); + } + if (fillRGB && typeof fillRGB.a === "number") { + fillOpacity *= fillRGB.a; + } + + var nodeStrokeOpacity = getAttribute(node, "stroke-opacity"); + if (nodeStrokeOpacity) { + strokeOpacity *= parseFloat(nodeStrokeOpacity); + } + if (strokeRGB && typeof strokeRGB.a === "number") { + strokeOpacity *= strokeRGB.a; + } + + var nodeOpacity = getAttribute(node, "opacity"); + if (nodeOpacity) { + var opacity = parseFloat(nodeOpacity); + strokeOpacity *= opacity; + fillOpacity *= opacity; + } + + var hasFillOpacity = fillOpacity < 1.0; + var hasStrokeOpacity = strokeOpacity < 1.0; + if (hasFillOpacity || hasStrokeOpacity) { + var gState = {}; + hasFillOpacity && (gState["opacity"] = fillOpacity); + hasStrokeOpacity && (gState["stroke-opacity"] = strokeOpacity); + _pdf.setGState(new _pdf.GState(gState)); + } + + } + + if (nodeIs(node, "g,path,rect,ellipse,line,circle,polygon,polyline")) { + // text has no fill color, so don't apply it until here + if (hasFillColor) { + attributeState.fill = fillRGB; + _pdf.setFillColor(fillRGB.r, fillRGB.g, fillRGB.b); + } + + // stroke mode + var strokeColor = getAttribute(node, "stroke"); + if (strokeColor) { + var strokeWidth = getAttribute(node, "stroke-width"); + if (strokeWidth !== void 0 && strokeWidth !== "") { + strokeWidth = Math.abs(parseFloat(strokeWidth)); + attributeState.strokeWidth = strokeWidth; + _pdf.setLineWidth(strokeWidth); + } else { + // needed for inherited zero width strokes + strokeWidth = attributeState.strokeWidth + } + var strokeRGB = new RGBColor(strokeColor); + if (strokeRGB.ok) { + attributeState.stroke = strokeRGB; + _pdf.setDrawColor(strokeRGB.r, strokeRGB.g, strokeRGB.b); + + // pdf spec states: "A line width of 0 denotes the thinnest line that can be rendered at device resolution: + // 1 device pixel wide". SVG, however, does not draw zero width lines. + stroke = strokeWidth !== 0; + } + var lineCap = getAttribute(node, "stroke-linecap"); + if (lineCap) { + _pdf.setLineCap(attributeState.strokeLinecap = lineCap); + } + var lineJoin = getAttribute(node, "stroke-linejoin"); + if (lineJoin) { + _pdf.setLineJoin(attributeState.strokeLinejoin = lineJoin); + } + var dashArray = getAttribute(node, "stroke-dasharray"); + if (dashArray) { + dashArray = parseFloats(dashArray); + var dashOffset = parseInt(getAttribute(node, "stroke-dashoffset")) || 0; + attributeState.strokeDasharray = dashArray; + attributeState.strokeDashoffset = dashOffset; + _pdf.setLineDashPattern(dashArray, dashOffset); + } + var miterLimit = getAttribute(node, "stroke-miterlimit"); + if (miterLimit !== void 0 && miterLimit !== "") { + _pdf.setLineMiterLimit(attributeState.strokeMiterlimit = parseFloat(miterLimit)); + } + } + } + + // inherit fill and stroke mode if not specified at this node + if (fill === "inherit") { + fill = attributeState.fill !== null; + } + if (stroke === "inherit") { + stroke = attributeState.stroke !== null; + } + + var xmlSpace = node.getAttribute("xml:space"); + if (xmlSpace) { + attributeState.xmlSpace = xmlSpace; + } + + setTextProperties(node, fillRGB, attributeState); + putTextProperties(attributeState, parentAttributeState); + + // do the actual drawing + switch (node.tagName.toLowerCase()) { + case 'svg': + case 'g': + case 'a': + renderChildren(node, tfMatrix, refsHandler, withinDefs, false, attributeState); + break; + + case 'use': + use(node, tfMatrix, refsHandler); + break; + + case 'line': + if (!withinClipPath) { + _pdf.setCurrentTransformationMatrix(tfMatrix); + line(node, refsHandler, attributeState); + } + break; + + case 'rect': + if (!withinClipPath) { + _pdf.setCurrentTransformationMatrix(tfMatrix); + } + rect(node); + break; + + case 'ellipse': + if (!withinClipPath) { + _pdf.setCurrentTransformationMatrix(tfMatrix); + } + ellipse(node); + break; + + case 'circle': + if (!withinClipPath) { + _pdf.setCurrentTransformationMatrix(tfMatrix); + } + circle(node); + break; + case 'text': + text(node, tfMatrix, hasFillColor, fillRGB, attributeState); + break; + + case 'path': + if (!withinClipPath) { + _pdf.setCurrentTransformationMatrix(tfMatrix); + } + path(node, tfMatrix, refsHandler, withinClipPath, attributeState); + break; + + case 'polygon': + case 'polyline': + if (!withinClipPath) { + _pdf.setCurrentTransformationMatrix(tfMatrix); + } + polygon(node, refsHandler, attributeState, node.tagName.toLowerCase() === "polygon"); + break; + + case 'image': + _pdf.setCurrentTransformationMatrix(tfMatrix); + image(node); + break; + } + + if (nodeIs(node, "path,rect,ellipse,circle,polygon,polyline") && !withinClipPath) { + if (fill && stroke) { + _pdf.fillStroke(patternOrGradient); + } else if (fill) { + _pdf.fill(patternOrGradient); + } else if (stroke) { + _pdf.stroke(); + } else { + _pdf.discardPath(); + } + } + + // close either the formObject or the graphics context + if (targetIsFormObject) { + _pdf.endFormObject(node.getAttribute("id")); + } else if (!withinClipPath) { + _pdf.restoreGraphicsState(); + } + + if (hasClipPath) { + _pdf.restoreGraphicsState(); + } + }; + + // the actual svgToPdf function (see above) + var svg2pdf = function (element, pdf, options) { + _pdf = pdf; + + var k = options.scale || 1.0, + xOffset = options.xOffset || 0.0, + yOffset = options.yOffset || 0.0; + + + _pdf.advancedAPI(function () { + + // set offsets and scale everything by k + _pdf.saveGraphicsState(); + _pdf.setCurrentTransformationMatrix(new _pdf.Matrix(k, 0, 0, k, xOffset, yOffset)); + + // set default values that differ from pdf defaults + var attributeState = AttributeState.default(); + _pdf.setLineWidth(attributeState.strokeWidth); + var fill = attributeState.fill; + _pdf.setFillColor(fill.r, fill.g, fill.b); + _pdf.setFont(attributeState.fontFamily); + _pdf.setFontSize(attributeState.fontSize); + + + var refsHandler = new ReferencesHandler(element); + renderNode(element.cloneNode(true), _pdf.unitMatrix, refsHandler, false, false, attributeState); + + _pdf.restoreGraphicsState(); + + }); + + return _pdf; + }; + + if (typeof define === "function" && define.amd) { + define(["./rgbcolor", "SvgPath", "font-family", "cssesc"], function (rgbcolor, svgpath, fontFamily, cssesc) { + RGBColor = rgbcolor; + SvgPath = svgpath; + FontFamily = fontFamily; + cssEsc = cssesc; + return svg2pdf; + }); + } else if (typeof module !== "undefined" && module.exports) { + RGBColor = require("./rgbcolor.js"); + SvgPath = require("SvgPath"); + FontFamily = require("font-family"); + cssEsc = require("cssesc"); + module.exports = svg2pdf; + } else { + SvgPath = global.SvgPath; + RGBColor = global.RGBColor; + FontFamily = global.FontFamily; + cssEsc = global.cssesc; + global.svg2pdf = svg2pdf; + // for compatibility reasons + global.svgElementToPdf = svg2pdf; + } + return svg2pdf; +}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this)); + +},{"./rgbcolor.js":10,"SvgPath":1,"cssesc":8,"font-family":9}]},{},[11])(11) +}); +//# sourceMappingURL=svg2pdf.js.map diff --git a/librerias/gantt/code/modules/accessibility.js b/librerias/gantt/code/modules/accessibility.js new file mode 100644 index 0000000..e11d404 --- /dev/null +++ b/librerias/gantt/code/modules/accessibility.js @@ -0,0 +1,178 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Accessibility module + + (c) 2010-2019 Highsoft AS + Author: Oystein Moseng + + License: www.highcharts.com/license +*/ +(function(v){"object"===typeof module&&module.exports?(v["default"]=v,module.exports=v):"function"===typeof define&&define.amd?define("highcharts/modules/accessibility",["highcharts"],function(r){v(r);v.Highcharts=r;return v}):v("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(v){function r(a,f,q,l){a.hasOwnProperty(f)||(a[f]=l.apply(null,q))}var a=v?v._modules:{};r(a,"modules/accessibility/utils/htmlUtilities.js",[a["parts/Utilities.js"],a["parts/Globals.js"]],function(a,f){function h(a){return a.replace(/&/g, +"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")}var l=a.merge,n=f.win,e=n.document;return{addClass:function(a,e){a.classList?a.classList.add(e):0>a.className.indexOf(e)&&(a.className+=e)},escapeStringForHTML:h,getElement:function(a){return e.getElementById(a)},getFakeMouseEvent:function(a){if("function"===typeof n.MouseEvent)return new n.MouseEvent(a);if(e.createEvent){var t=e.createEvent("MouseEvent");if(t.initMouseEvent)return t.initMouseEvent(a, +!0,!0,n,"click"===a?1:0,0,0,0,0,!1,!1,!1,!1,0,null),t}return{type:a}},removeElement:function(a){a&&a.parentNode&&a.parentNode.removeChild(a)},reverseChildNodes:function(a){for(var e=a.childNodes.length;e--;)a.appendChild(a.childNodes[e])},setElAttrs:function(a,e){Object.keys(e).forEach(function(k){var d=e[k];null===d?a.removeAttribute(k):(d=h(""+d),a.setAttribute(k,d))})},stripHTMLTagsFromString:function(a){return"string"===typeof a?a.replace(/<\/?[^>]+(>|$)/g,""):a},visuallyHideElement:function(a){l(!0, +a.style,{position:"absolute",width:"1px",height:"1px",overflow:"hidden",whiteSpace:"nowrap",clip:"rect(1px, 1px, 1px, 1px)",marginTop:"-3px","-ms-filter":"progid:DXImageTransform.Microsoft.Alpha(Opacity=1)",filter:"alpha(opacity=1)",opacity:"0.01"})}}});r(a,"modules/accessibility/utils/chartUtilities.js",[a["modules/accessibility/utils/htmlUtilities.js"],a["parts/Utilities.js"]],function(a,f){function h(a){if(a.points&&a.points.length&&a.points[0].graphic)return a.points[0].graphic.element}function l(a){var d= +h(a);return d&&d.parentNode||a.graph&&a.graph.element||a.group&&a.group.element}function n(a,d){d.setAttribute("aria-hidden",!1);d!==a.renderTo&&d.parentNode&&(Array.prototype.forEach.call(d.parentNode.childNodes,function(c){c.hasAttribute("aria-hidden")||c.setAttribute("aria-hidden",!0)}),n(a,d.parentNode))}var e=a.stripHTMLTagsFromString,t=f.defined,p=f.find;return{getChartTitle:function(a){return e(a.options.title.text||a.langFormat("accessibility.defaultChartTitle",{chart:a}))},getAxisDescription:function(a){return e(a&& +(a.userOptions&&a.userOptions.accessibility&&a.userOptions.accessibility.description||a.axisTitle&&a.axisTitle.textStr||a.options.id||a.categories&&"categories"||a.dateTime&&"Time"||"values"))},getPointFromXY:function(a,d,c){for(var b=a.length,g;b--;)if(g=p(a[b].points||[],function(b){return b.x===d&&b.y===c}))return g},getSeriesFirstPointElement:h,getSeriesFromName:function(a,d){return d?(a.series||[]).filter(function(c){return c.name===d}):a.series},getSeriesA11yElement:l,unhideChartElementFromAT:n, +hideSeriesFromAT:function(a){(a=l(a))&&a.setAttribute("aria-hidden",!0)},scrollToPoint:function(a){var d=a.series.xAxis,c=a.series.yAxis,b=(null===d||void 0===d?0:d.scrollbar)?d:c;if((d=null===b||void 0===b?void 0:b.scrollbar)&&t(d.to)&&t(d.from)){c=d.to-d.from;if(t(b.dataMin)&&t(b.dataMax)){var g=b.toPixels(b.dataMin),m=b.toPixels(b.dataMax);a=(b.toPixels(a["xAxis"===b.coll?"x":"y"]||0)-g)/(m-g)}else a=0;d.updatePosition(a-c/2,a+c/2);v.fireEvent(d,"changed",{from:d.from,to:d.to,trigger:"scrollbar", +DOMEvent:null})}}}});r(a,"modules/accessibility/KeyboardNavigationHandler.js",[a["parts/Utilities.js"]],function(a){function h(a,h){this.chart=a;this.keyCodeMap=h.keyCodeMap||[];this.validate=h.validate;this.init=h.init;this.terminate=h.terminate;this.response={success:1,prev:2,next:3,noHandler:4,fail:5}}var q=a.find;h.prototype={run:function(a){var h=a.which||a.keyCode,e=this.response.noHandler,t=q(this.keyCodeMap,function(a){return-1a||g!==c-1;d.a11yProxyElement&&(d.a11yProxyElement.style.visibility=g?"hidden":"visible")})},onChartRender:function(){this.legendProxyButtonClicked?delete this.legendProxyButtonClicked:this.updateProxies()},updateProxies:function(){c(this.legendProxyGroup);var b=this.chart,a=b.legend&&b.legend.allItems,d=b.options.legend.accessibility|| +{};!a||!a.length||b.colorAxis&&b.colorAxis.length||!1===d.enabled||(this.addLegendProxyGroup(),this.proxyLegendItems(),this.updateLegendItemProxyVisibility())},addLegendProxyGroup:function(){var b=this.chart.options.accessibility,c=this.chart.langFormat("accessibility.legend.legendLabel",{});this.legendProxyGroup=this.addProxyGroup({"aria-label":c,role:"all"===b.landmarkVerbosity?"region":null})},proxyLegendItems:function(){var b=this;(this.chart.legend&&this.chart.legend.allItems||[]).forEach(function(c){c.legendItem&& +c.legendItem.element&&b.proxyLegendItem(c)})},proxyLegendItem:function(b){var c=this,a=this.chart.langFormat("accessibility.legend.legendItem",{chart:this.chart,itemName:d(b.name)});b.a11yProxyElement=this.createProxyButton(b.legendItem,this.legendProxyGroup,{tabindex:-1,"aria-pressed":!b.visible,"aria-label":a},b.legendGroup.div?b.legendItem:b.legendGroup,function(){c.legendProxyButtonClicked=!0})},getKeyboardNavigation:function(){var b=this.keyCodes,c=this;return new n(this.chart,{keyCodeMap:[[[b.left, +b.right,b.up,b.down],function(b){return c.onKbdArrowKey(this,b)}],[[b.enter,b.space],function(){return c.onKbdClick(this)}]],validate:function(){return c.shouldHaveLegendNavigation()},init:function(b){return c.onKbdNavigationInit(b)}})},onKbdArrowKey:function(b,c){var a=this.keyCodes,d=b.response,g=this.chart,e=g.options.accessibility,u=g.legend.allItems.length;c=c===a.left||c===a.up?-1:1;return g.highlightLegendItem(this.highlightedLegendItemIx+c)?(this.highlightedLegendItemIx+=c,d.success):1=e&&b||0<=e&&!b||5>x||k(w))&&x"+c+"
  • ":""})}var t=a.inArray,p=f.escapeStringForHTML,k=f.stripHTMLTagsFromString;return{getAnnotationsInfoHTML:function(a){var c=a.annotations;return c&&c.length?"
      "+e(a).join(" ")+"
    ":""},getAnnotationLabelDescription:n,getAnnotationListItems:e,getPointAnnotationTexts:function(a){var c=h(a.series.chart).filter(function(b){return-1c&&b.graphic&&b.graphic.element)})||null:null}function h(b){var c=b.chart.options.accessibility.series.pointDescriptionEnabledThreshold; +return!!(!1!==c&&b.points&&b.points.length>=c)}function p(b){var c=b.options.accessibility||{};return!h(b)&&!c.exposeAsGroupOnly}function k(b){var c=b.chart.options.accessibility.keyboardNavigation.seriesNavigation;return!(!b.points||!(b.points.length"," "),d=b.id&&0>b.id.indexOf("highcharts-"),m="x, "+b.x;return b.name||c||a||(d?b.id:m)}function x(b,c,a){var g=c||"",m=a||"";return b.series.pointArrayMap.reduce(function(c,a){c+=c.length?", ":"";var e=d(b,y(b[a],b.options[a]));return c+(a+": "+g+e+m)},"")}function A(b){var c= +b.series,a=c.chart.options.accessibility.point||{},g=c.tooltipOptions||{},m=a.valuePrefix||g.valuePrefix||"";a=a.valueSuffix||g.valueSuffix||"";g=d(b,b["undefined"!==typeof b.value?"value":"y"]);return b.isNull?c.chart.langFormat("accessibility.series.nullPointValue",{point:b}):c.pointArrayMap?x(b,m,a):m+g+a}function B(b){var c=b.series,a=c.chart,d=a.options.accessibility.point.valueDescriptionFormat,g=(c=y(c.xAxis&&c.xAxis.options.accessibility&&c.xAxis.options.accessibility.enabled,!a.angular))? +m(b):"";b={point:b,index:F(b.index)?b.index+1:"",xDescription:g,value:A(b),separator:c?", ":""};return E(d,b,a)}function u(b){var c=b.series,a=c.chart,d=B(b),g=b.options&&b.options.accessibility&&b.options.accessibility.description;g=g?" "+g:"";c=1b&&dc.dataMax&&(a=c.dataMax,d=a-g);this.setExtremes(d,a)};a=function(){}; +a.prototype=new q;h(a.prototype,{init:function(){var b=this,c=this.chart;["afterShowResetZoom","afterDrilldown","drillupall"].forEach(function(a){b.addEvent(c,a,function(){b.updateProxyOverlays()})})},onChartUpdate:function(){var b=this.chart,c=this;b.mapNavButtons&&b.mapNavButtons.forEach(function(a,d){k(b,a.element);c.setMapNavButtonAttrs(a.element,"accessibility.zoom.mapZoom"+(d?"Out":"In"))})},setMapNavButtonAttrs:function(b,c){var a=this.chart;c=a.langFormat(c,{chart:a});d(b,{tabindex:-1,role:"button", +"aria-label":c})},onChartRender:function(){this.updateProxyOverlays()},updateProxyOverlays:function(){var b=this.chart;c(this.drillUpProxyGroup);c(this.resetZoomProxyGroup);b.resetZoomButton&&this.recreateProxyButtonAndGroup(b.resetZoomButton,"resetZoomProxyButton","resetZoomProxyGroup",b.langFormat("accessibility.zoom.resetZoomButton",{chart:b}));b.drillUpButton&&this.recreateProxyButtonAndGroup(b.drillUpButton,"drillUpProxyButton","drillUpProxyGroup",b.langFormat("accessibility.drillUpButton",{chart:b, +buttonText:b.getDrilldownBackText()}))},recreateProxyButtonAndGroup:function(b,a,d,e){c(this[d]);this[d]=this.addProxyGroup();this[a]=this.createProxyButton(b,this[d],{"aria-label":e,tabindex:-1})},getMapZoomNavigation:function(){var b=this.keyCodes,c=this.chart,a=this;return new l(c,{keyCodeMap:[[[b.up,b.down,b.left,b.right],function(b){return a.onMapKbdArrow(this,b)}],[[b.tab],function(b,c){return a.onMapKbdTab(this,c)}],[[b.space,b.enter],function(){return a.onMapKbdClick(this)}]],validate:function(){return!!(c.mapZoom&& +c.mapNavButtons&&c.mapNavButtons.length)},init:function(b){return a.onMapNavInit(b)}})},onMapKbdArrow:function(b,c){var a=this.keyCodes;this.chart[c===a.up||c===a.down?"yAxis":"xAxis"][0].panStep(c===a.left||c===a.up?-1:1);return b.response.success},onMapKbdTab:function(b,c){var a=this.chart;b=b.response;var d=(c=c.shiftKey)&&!this.focusedMapNavButtonIx||!c&&this.focusedMapNavButtonIx;a.mapNavButtons[this.focusedMapNavButtonIx].setState(0);if(d)return a.mapZoom(),b[c?"prev":"next"];this.focusedMapNavButtonIx+= +c?-1:1;c=a.mapNavButtons[this.focusedMapNavButtonIx];a.setFocusToElement(c.box,c.element);c.setState(2);return b.success},onMapKbdClick:function(b){this.fakeClickEvent(this.chart.mapNavButtons[this.focusedMapNavButtonIx].element);return b.response.success},onMapNavInit:function(b){var c=this.chart,a=c.mapNavButtons[0],d=c.mapNavButtons[1];a=0b)return a[0").replace(/</(h[1-7]|p|div|ul|ol|li|a|button)>/g,"").replace(/<(div|a|button) id="([a-zA-Z\-0-9#]*?)">/g,'<$1 id="$2">')}var k=a.win.document,d=f.extend,c=f.format,b=f.pick,g=n.getAnnotationsInfoHTML,m=e.unhideChartElementFromAT,r=e.getChartTitle,A=e.getAxisDescription,B=t.addClass,u=t.setElAttrs,z=t.escapeStringForHTML,v=t.stripHTMLTagsFromString,C=t.getElement,E=t.visuallyHideElement; +a.Chart.prototype.getTypeDescription=function(b){var a=b[0],c=this.series&&this.series[0]||{};c={numSeries:this.series.length,numPoints:c.points&&c.points.length,chart:this,mapTitle:c.mapTitle};if(!a)return this.langFormat("accessibility.chartTypes.emptyChart",c);if("map"===a)return c.mapTitle?this.langFormat("accessibility.chartTypes.mapTypeDescription",c):this.langFormat("accessibility.chartTypes.unknownMap",c);if(1this.series.length?"Single":"Multiple";return(this.langFormat("accessibility.chartTypes."+b+d,c)||this.langFormat("accessibility.chartTypes.default"+d,c))+(a?" "+a:"")};f=function(){};f.prototype=new q;d(f.prototype,{init:function(){var b=this.chart,a=this;this.initRegionsDefinitions();this.addEvent(b,"afterGetTable",function(b){a.onDataTableCreated(b)});this.addEvent(b,"afterViewData",function(b){a.dataTableDiv= +b;setTimeout(function(){a.focusDataTable()},300)});this.announcer=new l(b,"assertive")},initRegionsDefinitions:function(){var b=this;this.screenReaderSections={before:{element:null,buildContent:function(a){var c=a.options.accessibility.screenReaderSection.beforeChartFormatter;return c?c(a):b.defaultBeforeChartFormatter(a)},insertIntoDOM:function(b,a){a.renderTo.insertBefore(b,a.renderTo.firstChild)},afterInserted:function(){"undefined"!==typeof b.sonifyButtonId&&b.initSonifyButton(b.sonifyButtonId); +"undefined"!==typeof b.dataTableButtonId&&b.initDataTableButton(b.dataTableButtonId)}},after:{element:null,buildContent:function(a){var c=a.options.accessibility.screenReaderSection.afterChartFormatter;return c?c(a):b.defaultAfterChartFormatter()},insertIntoDOM:function(b,a){a.renderTo.insertBefore(b,a.container.nextSibling)}}}},onChartRender:function(){var b=this;this.linkedDescriptionElement=this.getLinkedDescriptionElement();this.setLinkedDescriptionAttrs();Object.keys(this.screenReaderSections).forEach(function(a){b.updateScreenReaderSection(a)})}, +getLinkedDescriptionElement:function(){var b=this.chart.options.accessibility.linkedDescription;if(b){if("string"!==typeof b)return b;b=c(b,this.chart);b=k.querySelectorAll(b);if(1===b.length)return b[0]}},setLinkedDescriptionAttrs:function(){var b=this.linkedDescriptionElement;b&&(b.setAttribute("aria-hidden","true"),B(b,"highcharts-linked-description"))},updateScreenReaderSection:function(b){var a=this.chart,c=this.screenReaderSections[b],d=c.buildContent(a),g=c.element=c.element||this.createElement("div"), +e=g.firstChild||this.createElement("div");this.setScreenReaderSectionAttribs(g,b);e.innerHTML=d;g.appendChild(e);c.insertIntoDOM(g,a);E(e);m(a,e);c.afterInserted&&c.afterInserted()},setScreenReaderSectionAttribs:function(b,a){var c=this.chart,d=c.langFormat("accessibility.screenReaderSection."+a+"RegionLabel",{chart:c});u(b,{id:"highcharts-screen-reader-region-"+a+"-"+c.index,"aria-label":d});b.style.position="relative";"all"===c.options.accessibility.landmarkVerbosity&&d&&b.setAttribute("role","region")}, +defaultBeforeChartFormatter:function(){var b,c=this.chart,d=c.options.accessibility.screenReaderSection.beforeChartFormat,e=this.getAxesDescription(),f=c.sonify&&(null===(b=c.options.sonification)||void 0===b?void 0:b.enabled);b="highcharts-a11y-sonify-data-btn-"+c.index;var m="hc-linkto-highcharts-data-table-"+c.index,p=g(c),k=c.langFormat("accessibility.screenReaderSection.annotations.heading",{chart:c});e={chartTitle:r(c),typeDescription:this.getTypeDescriptionText(),chartSubtitle:this.getSubtitleText(), +chartLongdesc:this.getLongdescText(),xAxisDescription:e.xAxis,yAxisDescription:e.yAxis,playAsSoundButton:f?this.getSonifyButtonText(b):"",viewTableButton:c.getCSV?this.getDataTableButtonText(m):"",annotationsTitle:p?k:"",annotationsList:p};c=a.i18nFormat(d,e,c);this.dataTableButtonId=m;this.sonifyButtonId=b;return h(z(c)).replace(/<(\w+)[^>]*?>\s*<\/\1>/g,"")},defaultAfterChartFormatter:function(){var b=this.chart,c=b.options.accessibility.screenReaderSection.afterChartFormat,d={endOfChartMarker:this.getEndOfChartMarkerText()}; +b=a.i18nFormat(c,d,b);return h(z(b)).replace(/<(\w+)[^>]*?>\s*<\/\1>/g,"")},getLinkedDescription:function(){var b=this.linkedDescriptionElement;return v(b&&b.innerHTML||"")},getLongdescText:function(){var b=this.chart.options,a=b.caption;a=a&&a.text;var c=this.getLinkedDescription();return b.accessibility.description||c||a||""},getTypeDescriptionText:function(){var b=this.chart;return b.types?b.options.accessibility.typeDescription||b.getTypeDescription(b.types):""},getDataTableButtonText:function(b){var a= +this.chart;a=a.langFormat("accessibility.table.viewAsDataTableButtonText",{chart:a,chartTitle:r(a)});return''+a+""},getSonifyButtonText:function(b){var a,c=this.chart;if(!1===(null===(a=c.options.sonification)||void 0===a?void 0:a.enabled))return"";a=c.langFormat("accessibility.sonification.playAsSoundButtonText",{chart:c,chartTitle:r(c)});return'"},getSubtitleText:function(){var b=this.chart.options.subtitle;return v(b&&b.text||"")},getEndOfChartMarkerText:function(){var b= +this.chart,a=b.langFormat("accessibility.screenReaderSection.endOfChartMarker",{chart:b});return'
    '+a+"
    "},onDataTableCreated:function(b){var a=this.chart;a.options.accessibility.enabled&&(this.viewDataTableButton&&this.viewDataTableButton.setAttribute("aria-expanded","true"),b.html=b.html.replace("a.types.indexOf("map"),g=!!a.hasCartesianSeries,e=c("xAxis",!a.angular&&g&&d);c=c("yAxis",g&&d);d={};e&&(d.xAxis=this.getAxisDescriptionText("xAxis"));c&&(d.yAxis=this.getAxisDescriptionText("yAxis"));return d},getAxisDescriptionText:function(b){var a=this,c=this.chart,d=c[b];return c.langFormat("accessibility.axis."+ +b+"Description"+(1{chartTitle}
    {typeDescription}
    {chartSubtitle}
    {chartLongdesc}
    {playAsSoundButton}
    {viewTableButton}
    {xAxisDescription}
    {yAxisDescription}
    {annotationsTitle}{annotationsList}
    ",afterChartFormat:"{endOfChartMarker}",axisRangeDateFormat:"%Y-%m-%d %H:%M:%S"},series:{describeSingleSeries:!1, +pointDescriptionEnabledThreshold:200},point:{valueDescriptionFormat:"{index}. {xDescription}{separator}{value}."},landmarkVerbosity:"all",linkedDescription:'*[data-highcharts-chart="{index}"] + .highcharts-description',keyboardNavigation:{enabled:!0,focusBorder:{enabled:!0,hideBrowserFocusOutline:!0,style:{color:"#335cad",lineWidth:2,borderRadius:3},margin:2},order:["series","zoom","rangeSelector","legend","chartMenu"],wrapAround:!0,seriesNavigation:{skipNullPoints:!0,pointNavigationEnabledThreshold:!1}}, +announceNewData:{enabled:!1,minAnnounceInterval:5E3,interruptUser:!1}},legend:{accessibility:{enabled:!0,keyboardNavigation:{enabled:!0}}},exporting:{accessibility:{enabled:!0}}}});r(a,"modules/accessibility/options/langOptions.js",[],function(){return{accessibility:{defaultChartTitle:"Chart",chartContainerLabel:"{title}. Highcharts interactive chart.",svgContainerLabel:"Interactive chart",drillUpButton:"{buttonText}",credits:"Chart credits: {creditsStr}",thousandsSep:",",svgContainerTitle:"",graphicContainerLabel:"", +screenReaderSection:{beforeRegionLabel:"Chart screen reader information.",afterRegionLabel:"",annotations:{heading:"Chart annotations summary",descriptionSinglePoint:"{annotationText}. Related to {annotationPoint}",descriptionMultiplePoints:"{annotationText}. Related to {annotationPoint}{ Also related to, #each(additionalAnnotationPoints)}",descriptionNoPoints:"{annotationText}"},endOfChartMarker:"End of interactive chart."},sonification:{playAsSoundButtonText:"Play as sound, {chartTitle}",playAsSoundClickAnnouncement:"Play"}, +legend:{legendLabel:"Toggle series visibility",legendItem:"Toggle visibility of {itemName}"},zoom:{mapZoomIn:"Zoom chart",mapZoomOut:"Zoom out chart",resetZoomButton:"Reset zoom"},rangeSelector:{minInputLabel:"Select start date.",maxInputLabel:"Select end date.",buttonText:"Select range {buttonText}"},table:{viewAsDataTableButtonText:"View as data table, {chartTitle}",tableSummary:"Table representation of chart."},announceNewData:{newDataAnnounce:"Updated data for chart {chartTitle}",newSeriesAnnounceSingle:"New data series: {seriesDesc}", +newPointAnnounceSingle:"New data point: {pointDesc}",newSeriesAnnounceMultiple:"New data series in chart {chartTitle}: {seriesDesc}",newPointAnnounceMultiple:"New data point in chart {chartTitle}: {pointDesc}"},seriesTypeDescriptions:{boxplot:"Box plot charts are typically used to display groups of statistical data. Each data point in the chart can have up to 5 values: minimum, lower quartile, median, upper quartile, and maximum.",arearange:"Arearange charts are line charts displaying a range between a lower and higher value for each point.", +areasplinerange:"These charts are line charts displaying a range between a lower and higher value for each point.",bubble:"Bubble charts are scatter charts where each data point also has a size value.",columnrange:"Columnrange charts are column charts displaying a range between a lower and higher value for each point.",errorbar:"Errorbar series are used to display the variability of the data.",funnel:"Funnel charts are used to display reduction of data in stages.",pyramid:"Pyramid charts consist of a single pyramid with item heights corresponding to each point value.", +waterfall:"A waterfall chart is a column chart where each column contributes towards a total end value."},chartTypes:{emptyChart:"Empty chart",mapTypeDescription:"Map of {mapTitle} with {numSeries} data series.",unknownMap:"Map of unspecified region with {numSeries} data series.",combinationChart:"Combination chart with {numSeries} data series.",defaultSingle:"Chart with {numPoints} data {#plural(numPoints, points, point)}.",defaultMultiple:"Chart with {numSeries} data series.",splineSingle:"Line chart with {numPoints} data {#plural(numPoints, points, point)}.", +splineMultiple:"Line chart with {numSeries} lines.",lineSingle:"Line chart with {numPoints} data {#plural(numPoints, points, point)}.",lineMultiple:"Line chart with {numSeries} lines.",columnSingle:"Bar chart with {numPoints} {#plural(numPoints, bars, bar)}.",columnMultiple:"Bar chart with {numSeries} data series.",barSingle:"Bar chart with {numPoints} {#plural(numPoints, bars, bar)}.",barMultiple:"Bar chart with {numSeries} data series.",pieSingle:"Pie chart with {numPoints} {#plural(numPoints, slices, slice)}.", +pieMultiple:"Pie chart with {numSeries} pies.",scatterSingle:"Scatter chart with {numPoints} {#plural(numPoints, points, point)}.",scatterMultiple:"Scatter chart with {numSeries} data series.",boxplotSingle:"Boxplot with {numPoints} {#plural(numPoints, boxes, box)}.",boxplotMultiple:"Boxplot with {numSeries} data series.",bubbleSingle:"Bubble chart with {numPoints} {#plural(numPoints, bubbles, bubble)}.",bubbleMultiple:"Bubble chart with {numSeries} data series."},axis:{xAxisDescriptionSingular:"The chart has 1 X axis displaying {names[0]}. {ranges[0]}", +xAxisDescriptionPlural:"The chart has {numAxes} X axes displaying {#each(names, -1) }and {names[-1]}.",yAxisDescriptionSingular:"The chart has 1 Y axis displaying {names[0]}. {ranges[0]}",yAxisDescriptionPlural:"The chart has {numAxes} Y axes displaying {#each(names, -1) }and {names[-1]}.",timeRangeDays:"Range: {range} days.",timeRangeHours:"Range: {range} hours.",timeRangeMinutes:"Range: {range} minutes.",timeRangeSeconds:"Range: {range} seconds.",rangeFromTo:"Range: {rangeFrom} to {rangeTo}.",rangeCategories:"Range: {numCategories} categories."}, +exporting:{chartMenuLabel:"Chart menu",menuButtonLabel:"View chart menu",exportRegionLabel:"Chart menu"},series:{summary:{"default":"{name}, series {ix} of {numSeries} with {numPoints} data {#plural(numPoints, points, point)}.",defaultCombination:"{name}, series {ix} of {numSeries} with {numPoints} data {#plural(numPoints, points, point)}.",line:"{name}, line {ix} of {numSeries} with {numPoints} data {#plural(numPoints, points, point)}.",lineCombination:"{name}, series {ix} of {numSeries}. Line with {numPoints} data {#plural(numPoints, points, point)}.", +spline:"{name}, line {ix} of {numSeries} with {numPoints} data {#plural(numPoints, points, point)}.",splineCombination:"{name}, series {ix} of {numSeries}. Line with {numPoints} data {#plural(numPoints, points, point)}.",column:"{name}, bar series {ix} of {numSeries} with {numPoints} {#plural(numPoints, bars, bar)}.",columnCombination:"{name}, series {ix} of {numSeries}. Bar series with {numPoints} {#plural(numPoints, bars, bar)}.",bar:"{name}, bar series {ix} of {numSeries} with {numPoints} {#plural(numPoints, bars, bar)}.", +barCombination:"{name}, series {ix} of {numSeries}. Bar series with {numPoints} {#plural(numPoints, bars, bar)}.",pie:"{name}, pie {ix} of {numSeries} with {numPoints} {#plural(numPoints, slices, slice)}.",pieCombination:"{name}, series {ix} of {numSeries}. Pie with {numPoints} {#plural(numPoints, slices, slice)}.",scatter:"{name}, scatter plot {ix} of {numSeries} with {numPoints} {#plural(numPoints, points, point)}.",scatterCombination:"{name}, series {ix} of {numSeries}, scatter plot with {numPoints} {#plural(numPoints, points, point)}.", +boxplot:"{name}, boxplot {ix} of {numSeries} with {numPoints} {#plural(numPoints, boxes, box)}.",boxplotCombination:"{name}, series {ix} of {numSeries}. Boxplot with {numPoints} {#plural(numPoints, boxes, box)}.",bubble:"{name}, bubble series {ix} of {numSeries} with {numPoints} {#plural(numPoints, bubbles, bubble)}.",bubbleCombination:"{name}, series {ix} of {numSeries}. Bubble series with {numPoints} {#plural(numPoints, bubbles, bubble)}.",map:"{name}, map {ix} of {numSeries} with {numPoints} {#plural(numPoints, areas, area)}.", +mapCombination:"{name}, series {ix} of {numSeries}. Map with {numPoints} {#plural(numPoints, areas, area)}.",mapline:"{name}, line {ix} of {numSeries} with {numPoints} data {#plural(numPoints, points, point)}.",maplineCombination:"{name}, series {ix} of {numSeries}. Line with {numPoints} data {#plural(numPoints, points, point)}.",mapbubble:"{name}, bubble series {ix} of {numSeries} with {numPoints} {#plural(numPoints, bubbles, bubble)}.",mapbubbleCombination:"{name}, series {ix} of {numSeries}. Bubble series with {numPoints} {#plural(numPoints, bubbles, bubble)}."}, +description:"{description}",xAxisDescription:"X axis, {name}",yAxisDescription:"Y axis, {name}",nullPointValue:"No value",pointAnnotationsDescription:"{Annotation: #each(annotations). }"}}}});r(a,"modules/accessibility/options/deprecatedOptions.js",[a["parts/Utilities.js"]],function(a){function f(a,c,b){p("Highcharts: Deprecated option "+c+" used. This will be removed from future versions of Highcharts. Use "+b+" instead.",!1,a)}function h(a,c,b){for(var d,e=0;ee?f.length+e:Math.min(e,f.length),d=0;da?(b=f[f.length+a],"undefined"===typeof b&&(b=f[0])):(b=f[a],"undefined"===typeof b&&(b=f[f.length-1]))),"undefined"!==typeof b?b:""):"{"+a+"}"}var l=f.format,n=f.pick;a.i18nFormat=function(a,f,p){var e=function(a,b){a=a.slice(b||0);var c=a.indexOf("{"),d=a.indexOf("}");if(-1c)return{statement:a.substring(c+1,d),begin:b+c+1,end:b+d}},d=[],c=0;do{var b=e(a,c);var g=a.substring(c,b&&b.begin-1);g.length&&d.push({value:g,type:"constant"}); +b&&d.push({value:b.statement,type:"statement"});c=b?b.end+1:c+1}while(b);d.forEach(function(a){"statement"===a.type&&(a.value=h(a.value,f))});return l(d.reduce(function(a,b){return a+b.value},""),f,p)};a.Chart.prototype.langFormat=function(e,f){e=e.split(".");for(var h=this.options.lang,k=0;k/g, '>') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(/\//g, '/'); + } + /** + * Get an element by ID + * @param {string} id + * @private + * @return {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement|null} + */ + function getElement(id) { + return doc.getElementById(id); + } + /** + * Get a fake mouse event of a given type + * @param {string} type + * @private + * @return {global.MouseEvent} + */ + function getFakeMouseEvent(type) { + if (typeof win.MouseEvent === 'function') { + return new win.MouseEvent(type); + } + // No MouseEvent support, try using initMouseEvent + if (doc.createEvent) { + var evt = doc.createEvent('MouseEvent'); + if (evt.initMouseEvent) { + evt.initMouseEvent(type, true, // Bubble + true, // Cancel + win, // View + type === 'click' ? 1 : 0, // Detail + // Coords + 0, 0, 0, 0, + // Pressed keys + false, false, false, false, 0, // button + null // related target + ); + return evt; + } + } + return { type: type }; + } + /** + * Remove an element from the DOM. + * @private + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} [element] + * @return {void} + */ + function removeElement(element) { + if (element && element.parentNode) { + element.parentNode.removeChild(element); + } + } + /** + * Utility function. Reverses child nodes of a DOM element. + * @private + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} node + * @return {void} + */ + function reverseChildNodes(node) { + var i = node.childNodes.length; + while (i--) { + node.appendChild(node.childNodes[i]); + } + } + /** + * Set attributes on element. Set to null to remove attribute. + * @private + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} el + * @param {Highcharts.HTMLAttributes|Highcharts.SVGAttributes} attrs + * @return {void} + */ + function setElAttrs(el, attrs) { + Object.keys(attrs).forEach(function (attr) { + var val = attrs[attr]; + if (val === null) { + el.removeAttribute(attr); + } + else { + var cleanedVal = escapeStringForHTML('' + val); + el.setAttribute(attr, cleanedVal); + } + }); + } + /** + * Used for aria-label attributes, painting on a canvas will fail if the + * text contains tags. + * @private + * @param {string} str + * @return {string} + */ + function stripHTMLTagsFromString(str) { + return typeof str === 'string' ? + str.replace(/<\/?[^>]+(>|$)/g, '') : str; + } + /** + * Utility function for hiding an element visually, but still keeping it + * available to screen reader users. + * @private + * @param {Highcharts.HTMLDOMElement} element + * @return {void} + */ + function visuallyHideElement(element) { + var hiddenStyle = { + position: 'absolute', + width: '1px', + height: '1px', + overflow: 'hidden', + whiteSpace: 'nowrap', + clip: 'rect(1px, 1px, 1px, 1px)', + marginTop: '-3px', + '-ms-filter': 'progid:DXImageTransform.Microsoft.Alpha(Opacity=1)', + filter: 'alpha(opacity=1)', + opacity: '0.01' + }; + merge(true, element.style, hiddenStyle); + } + var HTMLUtilities = { + addClass: addClass, + escapeStringForHTML: escapeStringForHTML, + getElement: getElement, + getFakeMouseEvent: getFakeMouseEvent, + removeElement: removeElement, + reverseChildNodes: reverseChildNodes, + setElAttrs: setElAttrs, + stripHTMLTagsFromString: stripHTMLTagsFromString, + visuallyHideElement: visuallyHideElement + }; + + return HTMLUtilities; + }); + _registerModule(_modules, 'modules/accessibility/utils/chartUtilities.js', [_modules['modules/accessibility/utils/htmlUtilities.js'], _modules['parts/Utilities.js']], function (HTMLUtilities, U) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Utils for dealing with charts. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var stripHTMLTags = HTMLUtilities.stripHTMLTagsFromString; + var defined = U.defined, find = U.find; + /* eslint-disable valid-jsdoc */ + /** + * @return {string} + */ + function getChartTitle(chart) { + return stripHTMLTags(chart.options.title.text || + chart.langFormat('accessibility.defaultChartTitle', { chart: chart })); + } + /** + * @param {Highcharts.Axis} axis + * @return {string} + */ + function getAxisDescription(axis) { + return stripHTMLTags(axis && (axis.userOptions && axis.userOptions.accessibility && + axis.userOptions.accessibility.description || + axis.axisTitle && axis.axisTitle.textStr || + axis.options.id || + axis.categories && 'categories' || + axis.dateTime && 'Time' || + 'values')); + } + /** + * Get the DOM element for the first point in the series. + * @private + * @param {Highcharts.Series} series + * The series to get element for. + * @return {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement|undefined} + * The DOM element for the point. + */ + function getSeriesFirstPointElement(series) { + if (series.points && + series.points.length && + series.points[0].graphic) { + return series.points[0].graphic.element; + } + } + /** + * Get the DOM element for the series that we put accessibility info on. + * @private + * @param {Highcharts.Series} series + * The series to get element for. + * @return {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement|undefined} + * The DOM element for the series + */ + function getSeriesA11yElement(series) { + var firstPointEl = getSeriesFirstPointElement(series); + return (firstPointEl && + firstPointEl.parentNode || series.graph && + series.graph.element || series.group && + series.group.element); // Could be tracker series depending on series type + } + /** + * Remove aria-hidden from element. Also unhides parents of the element, and + * hides siblings that are not explicitly unhidden. + * @private + * @param {Highcharts.Chart} chart + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} element + * @return {void} + */ + function unhideChartElementFromAT(chart, element) { + element.setAttribute('aria-hidden', false); + if (element === chart.renderTo || !element.parentNode) { + return; + } + // Hide siblings unless their hidden state is already explicitly set + Array.prototype.forEach.call(element.parentNode.childNodes, function (node) { + if (!node.hasAttribute('aria-hidden')) { + node.setAttribute('aria-hidden', true); + } + }); + // Repeat for parent + unhideChartElementFromAT(chart, element.parentNode); + } + /** + * Hide series from screen readers. + * @private + * @param {Highcharts.Series} series + * The series to hide + * @return {void} + */ + function hideSeriesFromAT(series) { + var seriesEl = getSeriesA11yElement(series); + if (seriesEl) { + seriesEl.setAttribute('aria-hidden', true); + } + } + /** + * Get series objects by series name. + * @private + * @param {Highcharts.Chart} chart + * @param {string} name + * @return {Array} + */ + function getSeriesFromName(chart, name) { + if (!name) { + return chart.series; + } + return (chart.series || []).filter(function (s) { + return s.name === name; + }); + } + /** + * Get point in a series from x/y values. + * @private + * @param {Array} series + * @param {number} x + * @param {number} y + * @return {Highcharts.Point|undefined} + */ + function getPointFromXY(series, x, y) { + var i = series.length, res; + while (i--) { + res = find(series[i].points || [], function (p) { + return p.x === x && p.y === y; + }); + if (res) { + return res; + } + } + } + /** + * Get relative position of point on an x/y axis from 0 to 1. + * @private + * @param {Highcharts.Axis} axis + * @param {Highcharts.Point} point + * @return {number} + */ + function getRelativePointAxisPosition(axis, point) { + if (!defined(axis.dataMin) || !defined(axis.dataMax)) { + return 0; + } + var axisStart = axis.toPixels(axis.dataMin); + var axisEnd = axis.toPixels(axis.dataMax); + // We have to use pixel position because of axis breaks, log axis etc. + var positionProp = axis.coll === 'xAxis' ? 'x' : 'y'; + var pointPos = axis.toPixels(point[positionProp] || 0); + return (pointPos - axisStart) / (axisEnd - axisStart); + } + /** + * Get relative position of point on an x/y axis from 0 to 1. + * @private + * @param {Highcharts.Point} point + */ + function scrollToPoint(point) { + var xAxis = point.series.xAxis; + var yAxis = point.series.yAxis; + var axis = (xAxis === null || xAxis === void 0 ? void 0 : xAxis.scrollbar) ? xAxis : yAxis; + var scrollbar = axis === null || axis === void 0 ? void 0 : axis.scrollbar; + if (scrollbar && defined(scrollbar.to) && defined(scrollbar.from)) { + var range = scrollbar.to - scrollbar.from; + var pos = getRelativePointAxisPosition(axis, point); + scrollbar.updatePosition(pos - range / 2, pos + range / 2); + Highcharts.fireEvent(scrollbar, 'changed', { + from: scrollbar.from, + to: scrollbar.to, + trigger: 'scrollbar', + DOMEvent: null + }); + } + } + var ChartUtilities = { + getChartTitle: getChartTitle, + getAxisDescription: getAxisDescription, + getPointFromXY: getPointFromXY, + getSeriesFirstPointElement: getSeriesFirstPointElement, + getSeriesFromName: getSeriesFromName, + getSeriesA11yElement: getSeriesA11yElement, + unhideChartElementFromAT: unhideChartElementFromAT, + hideSeriesFromAT: hideSeriesFromAT, + scrollToPoint: scrollToPoint + }; + + return ChartUtilities; + }); + _registerModule(_modules, 'modules/accessibility/KeyboardNavigationHandler.js', [_modules['parts/Utilities.js']], function (U) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Keyboard navigation handler base class definition + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var find = U.find; + /** + * Options for the keyboard navigation handler. + * + * @interface Highcharts.KeyboardNavigationHandlerOptionsObject + */ /** + * An array containing pairs of an array of keycodes, mapped to a handler + * function. When the keycode is received, the handler is called with the + * keycode as parameter. + * @name Highcharts.KeyboardNavigationHandlerOptionsObject#keyCodeMap + * @type {Array, Function>>} + */ /** + * Function to run on initialization of module. + * @name Highcharts.KeyboardNavigationHandlerOptionsObject#init + * @type {Function} + */ /** + * Function to run before moving to next/prev module. Receives moving direction + * as parameter: +1 for next, -1 for previous. + * @name Highcharts.KeyboardNavigationHandlerOptionsObject#terminate + * @type {Function|undefined} + */ /** + * Function to run to validate module. Should return false if module should not + * run, true otherwise. Receives chart as parameter. + * @name Highcharts.KeyboardNavigationHandlerOptionsObject#validate + * @type {Function|undefined} + */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Define a keyboard navigation handler for use with a + * Highcharts.AccessibilityComponent instance. This functions as an abstraction + * layer for keyboard navigation, and defines a map of keyCodes to handler + * functions. + * + * @requires module:modules/accessibility + * + * @sample highcharts/accessibility/custom-component + * Custom accessibility component + * + * @class + * @name Highcharts.KeyboardNavigationHandler + * + * @param {Highcharts.Chart} chart + * The chart this module should act on. + * + * @param {Highcharts.KeyboardNavigationHandlerOptionsObject} options + * Options for the keyboard navigation handler. + */ + function KeyboardNavigationHandler(chart, options) { + this.chart = chart; + this.keyCodeMap = options.keyCodeMap || []; + this.validate = options.validate; + this.init = options.init; + this.terminate = options.terminate; + // Response enum + this.response = { + success: 1, + prev: 2, + next: 3, + noHandler: 4, + fail: 5 // Handler failed + }; + } + KeyboardNavigationHandler.prototype = { + /** + * Find handler function(s) for key code in the keyCodeMap and run it. + * + * @function KeyboardNavigationHandler#run + * @param {global.KeyboardEvent} e + * @return {number} Returns a response code indicating whether the run was + * a success/fail/unhandled, or if we should move to next/prev module. + */ + run: function (e) { + var keyCode = e.which || e.keyCode, response = this.response.noHandler, handlerCodeSet = find(this.keyCodeMap, function (codeSet) { + return codeSet[0].indexOf(keyCode) > -1; + }); + if (handlerCodeSet) { + response = handlerCodeSet[1].call(this, keyCode, e); + } + else if (keyCode === 9) { + // Default tab handler, move to next/prev module + response = this.response[e.shiftKey ? 'prev' : 'next']; + } + return response; + } + }; + + return KeyboardNavigationHandler; + }); + _registerModule(_modules, 'modules/accessibility/utils/EventProvider.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Class that can keep track of events added, and clean them up on destroy. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, extend = U.extend; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * @private + * @class + */ + var EventProvider = function () { + this.eventRemovers = []; + }; + extend(EventProvider.prototype, { + /** + * Add an event to an element and keep track of it for later removal. + * Same args as Highcharts.addEvent. + * @private + * @return {Function} + */ + addEvent: function () { + var remover = addEvent.apply(H, arguments); + this.eventRemovers.push(remover); + return remover; + }, + /** + * Remove all added events. + * @private + * @return {void} + */ + removeAddedEvents: function () { + this.eventRemovers.forEach(function (remover) { + remover(); + }); + this.eventRemovers = []; + } + }); + + return EventProvider; + }); + _registerModule(_modules, 'modules/accessibility/utils/DOMElementProvider.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/utils/htmlUtilities.js']], function (H, U, HTMLUtilities) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Class that can keep track of elements added to DOM and clean them up on + * destroy. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var doc = H.win.document; + var extend = U.extend; + var removeElement = HTMLUtilities.removeElement; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * @private + * @class + */ + var DOMElementProvider = function () { + this.elements = []; + }; + extend(DOMElementProvider.prototype, { + /** + * Create an element and keep track of it for later removal. + * Same args as document.createElement + * @private + */ + createElement: function () { + var el = doc.createElement.apply(doc, arguments); + this.elements.push(el); + return el; + }, + /** + * Destroy all created elements, removing them from the DOM. + * @private + */ + destroyCreatedElements: function () { + this.elements.forEach(function (element) { + removeElement(element); + }); + this.elements = []; + } + }); + + return DOMElementProvider; + }); + _registerModule(_modules, 'modules/accessibility/AccessibilityComponent.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/utils/htmlUtilities.js'], _modules['modules/accessibility/utils/chartUtilities.js'], _modules['modules/accessibility/utils/EventProvider.js'], _modules['modules/accessibility/utils/DOMElementProvider.js']], function (H, U, HTMLUtilities, ChartUtilities, EventProvider, DOMElementProvider) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Accessibility component class definition + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var win = H.win, doc = win.document; + var extend = U.extend, fireEvent = U.fireEvent, merge = U.merge; + var removeElement = HTMLUtilities.removeElement, getFakeMouseEvent = HTMLUtilities.getFakeMouseEvent; + var unhideChartElementFromAT = ChartUtilities.unhideChartElementFromAT; + /* eslint-disable valid-jsdoc */ + /** @lends Highcharts.AccessibilityComponent */ + var functionsToOverrideByDerivedClasses = { + /** + * Called on component initialization. + */ + init: function () { }, + /** + * Get keyboard navigation handler for this component. + * @return {Highcharts.KeyboardNavigationHandler} + */ + getKeyboardNavigation: function () { }, + /** + * Called on updates to the chart, including options changes. + * Note that this is also called on first render of chart. + */ + onChartUpdate: function () { }, + /** + * Called on every chart render. + */ + onChartRender: function () { }, + /** + * Called when accessibility is disabled or chart is destroyed. + */ + destroy: function () { } + }; + /** + * The AccessibilityComponent base class, representing a part of the chart that + * has accessibility logic connected to it. This class can be inherited from to + * create a custom accessibility component for a chart. + * + * Components should take care to destroy added elements and unregister event + * handlers on destroy. This is handled automatically if using this.addEvent and + * this.createElement. + * + * @sample highcharts/accessibility/custom-component + * Custom accessibility component + * + * @requires module:modules/accessibility + * @class + * @name Highcharts.AccessibilityComponent + */ + function AccessibilityComponent() { } + /** + * @lends Highcharts.AccessibilityComponent + */ + AccessibilityComponent.prototype = { + /** + * Initialize the class + * @private + * @param {Highcharts.Chart} chart + * Chart object + */ + initBase: function (chart) { + this.chart = chart; + this.eventProvider = new EventProvider(); + this.domElementProvider = new DOMElementProvider(); + // Key code enum for common keys + this.keyCodes = { + left: 37, + right: 39, + up: 38, + down: 40, + enter: 13, + space: 32, + esc: 27, + tab: 9 + }; + }, + /** + * Add an event to an element and keep track of it for later removal. + * See EventProvider for details. + * @private + */ + addEvent: function () { + return this.eventProvider.addEvent + .apply(this.eventProvider, arguments); + }, + /** + * Create an element and keep track of it for later removal. + * See DOMElementProvider for details. + * @private + */ + createElement: function () { + return this.domElementProvider.createElement.apply(this.domElementProvider, arguments); + }, + /** + * Fire an event on an element that is either wrapped by Highcharts, + * or a DOM element + * @private + * @param {Highcharts.HTMLElement|Highcharts.HTMLDOMElement| + * Highcharts.SVGDOMElement|Highcharts.SVGElement} el + * @param {Event} eventObject + */ + fireEventOnWrappedOrUnwrappedElement: function (el, eventObject) { + var type = eventObject.type; + if (doc.createEvent && (el.dispatchEvent || el.fireEvent)) { + if (el.dispatchEvent) { + el.dispatchEvent(eventObject); + } + else { + el.fireEvent(type, eventObject); + } + } + else { + fireEvent(el, type, eventObject); + } + }, + /** + * Utility function to attempt to fake a click event on an element. + * @private + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} element + */ + fakeClickEvent: function (element) { + if (element) { + var fakeEventObject = getFakeMouseEvent('click'); + this.fireEventOnWrappedOrUnwrappedElement(element, fakeEventObject); + } + }, + /** + * Add a new proxy group to the proxy container. Creates the proxy container + * if it does not exist. + * @private + * @param {Highcharts.HTMLAttributes} [attrs] + * The attributes to set on the new group div. + * @return {Highcharts.HTMLDOMElement} + * The new proxy group element. + */ + addProxyGroup: function (attrs) { + this.createOrUpdateProxyContainer(); + var groupDiv = this.createElement('div'); + Object.keys(attrs || {}).forEach(function (prop) { + if (attrs[prop] !== null) { + groupDiv.setAttribute(prop, attrs[prop]); + } + }); + this.chart.a11yProxyContainer.appendChild(groupDiv); + return groupDiv; + }, + /** + * Creates and updates DOM position of proxy container + * @private + */ + createOrUpdateProxyContainer: function () { + var chart = this.chart, rendererSVGEl = chart.renderer.box; + chart.a11yProxyContainer = chart.a11yProxyContainer || + this.createProxyContainerElement(); + if (rendererSVGEl.nextSibling !== chart.a11yProxyContainer) { + chart.container.insertBefore(chart.a11yProxyContainer, rendererSVGEl.nextSibling); + } + }, + /** + * @private + * @return {Highcharts.HTMLDOMElement} element + */ + createProxyContainerElement: function () { + var pc = doc.createElement('div'); + pc.className = 'highcharts-a11y-proxy-container'; + return pc; + }, + /** + * Create an invisible proxy HTML button in the same position as an SVG + * element + * @private + * @param {Highcharts.SVGElement} svgElement + * The wrapped svg el to proxy. + * @param {Highcharts.HTMLDOMElement} parentGroup + * The proxy group element in the proxy container to add this button to. + * @param {Highcharts.SVGAttributes} [attributes] + * Additional attributes to set. + * @param {Highcharts.SVGElement} [posElement] + * Element to use for positioning instead of svgElement. + * @param {Function} [preClickEvent] + * Function to call before click event fires. + * + * @return {Highcharts.HTMLDOMElement} The proxy button. + */ + createProxyButton: function (svgElement, parentGroup, attributes, posElement, preClickEvent) { + var svgEl = svgElement.element, proxy = this.createElement('button'), attrs = merge({ + 'aria-label': svgEl.getAttribute('aria-label') + }, attributes), bBox = this.getElementPosition(posElement || svgElement); + Object.keys(attrs).forEach(function (prop) { + if (attrs[prop] !== null) { + proxy.setAttribute(prop, attrs[prop]); + } + }); + proxy.className = 'highcharts-a11y-proxy-button'; + if (preClickEvent) { + this.addEvent(proxy, 'click', preClickEvent); + } + this.setProxyButtonStyle(proxy, bBox); + this.proxyMouseEventsForButton(svgEl, proxy); + // Add to chart div and unhide from screen readers + parentGroup.appendChild(proxy); + if (!attrs['aria-hidden']) { + unhideChartElementFromAT(this.chart, proxy); + } + return proxy; + }, + /** + * Get the position relative to chart container for a wrapped SVG element. + * @private + * @param {Highcharts.SVGElement} element + * The element to calculate position for. + * @return {Highcharts.BBoxObject} + * Object with x and y props for the position. + */ + getElementPosition: function (element) { + var el = element.element, div = this.chart.renderTo; + if (div && el && el.getBoundingClientRect) { + var rectEl = el.getBoundingClientRect(), rectDiv = div.getBoundingClientRect(); + return { + x: rectEl.left - rectDiv.left, + y: rectEl.top - rectDiv.top, + width: rectEl.right - rectEl.left, + height: rectEl.bottom - rectEl.top + }; + } + return { x: 0, y: 0, width: 1, height: 1 }; + }, + /** + * @private + * @param {Highcharts.HTMLElement} button + * @param {Highcharts.BBoxObject} bBox + */ + setProxyButtonStyle: function (button, bBox) { + merge(true, button.style, { + 'border-width': 0, + 'background-color': 'transparent', + cursor: 'pointer', + outline: 'none', + opacity: 0.001, + filter: 'alpha(opacity=1)', + '-ms-filter': 'progid:DXImageTransform.Microsoft.Alpha(Opacity=1)', + zIndex: 999, + overflow: 'hidden', + padding: 0, + margin: 0, + display: 'block', + position: 'absolute', + width: (bBox.width || 1) + 'px', + height: (bBox.height || 1) + 'px', + left: (bBox.x || 0) + 'px', + top: (bBox.y || 0) + 'px' + }); + }, + /** + * @private + * @param {Highcharts.HTMLElement|Highcharts.HTMLDOMElement| + * Highcharts.SVGDOMElement|Highcharts.SVGElement} source + * @param {Highcharts.HTMLElement} button + */ + proxyMouseEventsForButton: function (source, button) { + var component = this; + [ + 'click', 'touchstart', 'touchend', 'touchcancel', 'touchmove', + 'mouseover', 'mouseenter', 'mouseleave', 'mouseout' + ].forEach(function (evtType) { + component.addEvent(button, evtType, function (e) { + var clonedEvent = component.cloneMouseEvent(e); + if (source) { + component.fireEventOnWrappedOrUnwrappedElement(source, clonedEvent); + } + e.stopPropagation(); + e.preventDefault(); + }); + }); + }, + /** + * Utility function to clone a mouse event for re-dispatching. + * @private + * @param {global.MouseEvent} e The event to clone. + * @return {global.MouseEvent} The cloned event + */ + cloneMouseEvent: function (e) { + if (typeof win.MouseEvent === 'function') { + return new win.MouseEvent(e.type, e); + } + // No MouseEvent support, try using initMouseEvent + if (doc.createEvent) { + var evt = doc.createEvent('MouseEvent'); + if (evt.initMouseEvent) { + evt.initMouseEvent(e.type, e.bubbles, // #10561, #12161 + e.cancelable, e.view || win, e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget); + return evt; + } + } + return getFakeMouseEvent(e.type); + }, + /** + * Remove traces of the component. + * @private + */ + destroyBase: function () { + removeElement(this.chart.a11yProxyContainer); + this.domElementProvider.destroyCreatedElements(); + this.eventProvider.removeAddedEvents(); + } + }; + extend(AccessibilityComponent.prototype, functionsToOverrideByDerivedClasses); + + return AccessibilityComponent; + }); + _registerModule(_modules, 'modules/accessibility/KeyboardNavigation.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/utils/htmlUtilities.js'], _modules['modules/accessibility/utils/EventProvider.js']], function (H, U, HTMLUtilities, EventProvider) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Main keyboard navigation handling. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var win = H.win, doc = win.document; + var addEvent = U.addEvent, fireEvent = U.fireEvent; + var getElement = HTMLUtilities.getElement; + /* eslint-disable valid-jsdoc */ + // Add event listener to document to detect ESC key press and dismiss + // hover/popup content. + addEvent(doc, 'keydown', function (e) { + var keycode = e.which || e.keyCode; + var esc = 27; + if (keycode === esc && H.charts) { + H.charts.forEach(function (chart) { + if (chart && chart.dismissPopupContent) { + chart.dismissPopupContent(); + } + }); + } + }); + /** + * Dismiss popup content in chart, including export menu and tooltip. + */ + H.Chart.prototype.dismissPopupContent = function () { + var chart = this; + fireEvent(this, 'dismissPopupContent', {}, function () { + if (chart.tooltip) { + chart.tooltip.hide(0); + } + chart.hideExportMenu(); + }); + }; + /** + * The KeyboardNavigation class, containing the overall keyboard navigation + * logic for the chart. + * + * @requires module:modules/accessibility + * + * @private + * @class + * @param {Highcharts.Chart} chart + * Chart object + * @param {object} components + * Map of component names to AccessibilityComponent objects. + * @name Highcharts.KeyboardNavigation + */ + function KeyboardNavigation(chart, components) { + this.init(chart, components); + } + KeyboardNavigation.prototype = { + /** + * Initialize the class + * @private + * @param {Highcharts.Chart} chart + * Chart object + * @param {object} components + * Map of component names to AccessibilityComponent objects. + */ + init: function (chart, components) { + var _this = this; + var ep = this.eventProvider = new EventProvider(); + this.chart = chart; + this.components = components; + this.modules = []; + this.currentModuleIx = 0; + ep.addEvent(chart.renderTo, 'keydown', function (e) { return _this.onKeydown(e); }); + ep.addEvent(chart.container, 'focus', function (e) { return _this.onFocus(e); }); + ep.addEvent(doc, 'mouseup', function () { return _this.onMouseUp(); }); + ep.addEvent(chart.renderTo, 'mousedown', function () { + _this.isClickingChart = true; + }); + ep.addEvent(chart.renderTo, 'mouseover', function () { + _this.pointerIsOverChart = true; + }); + ep.addEvent(chart.renderTo, 'mouseout', function () { + _this.pointerIsOverChart = false; + }); + // Run an update to get all modules + this.update(); + // Init first module + if (this.modules.length) { + this.modules[0].init(1); + } + }, + /** + * Update the modules for the keyboard navigation. + * @param {Array} [order] + * Array specifying the tab order of the components. + */ + update: function (order) { + var a11yOptions = this.chart.options.accessibility, keyboardOptions = a11yOptions && a11yOptions.keyboardNavigation, components = this.components; + this.updateContainerTabindex(); + if (keyboardOptions && + keyboardOptions.enabled && + order && + order.length) { + // We (still) have keyboard navigation. Update module list + this.modules = order.reduce(function (modules, componentName) { + var navModules = components[componentName].getKeyboardNavigation(); + return modules.concat(navModules); + }, []); + this.updateExitAnchor(); + } + else { + this.modules = []; + this.currentModuleIx = 0; + this.removeExitAnchor(); + } + }, + /** + * Function to run on container focus + * @private + * @param {global.FocusEvent} e Browser focus event. + */ + onFocus: function (e) { + var _a; + var chart = this.chart; + var focusComesFromChart = (e.relatedTarget && + chart.container.contains(e.relatedTarget)); + // Init keyboard nav if tabbing into chart + if (!this.isClickingChart && !focusComesFromChart) { + (_a = this.modules[0]) === null || _a === void 0 ? void 0 : _a.init(1); + } + }, + /** + * Reset chart navigation state if we click outside the chart and it's + * not already reset. + * @private + */ + onMouseUp: function () { + delete this.isClickingChart; + if (!this.keyboardReset && !this.pointerIsOverChart) { + var chart = this.chart, curMod = this.modules && + this.modules[this.currentModuleIx || 0]; + if (curMod && curMod.terminate) { + curMod.terminate(); + } + if (chart.focusElement) { + chart.focusElement.removeFocusBorder(); + } + this.currentModuleIx = 0; + this.keyboardReset = true; + } + }, + /** + * Function to run on keydown + * @private + * @param {global.KeyboardEvent} ev Browser keydown event. + */ + onKeydown: function (ev) { + var e = ev || win.event, preventDefault, curNavModule = this.modules && this.modules.length && + this.modules[this.currentModuleIx]; + // Used for resetting nav state when clicking outside chart + this.keyboardReset = false; + // If there is a nav module for the current index, run it. + // Otherwise, we are outside of the chart in some direction. + if (curNavModule) { + var response = curNavModule.run(e); + if (response === curNavModule.response.success) { + preventDefault = true; + } + else if (response === curNavModule.response.prev) { + preventDefault = this.prev(); + } + else if (response === curNavModule.response.next) { + preventDefault = this.next(); + } + if (preventDefault) { + e.preventDefault(); + e.stopPropagation(); + } + } + }, + /** + * Go to previous module. + * @private + */ + prev: function () { + return this.move(-1); + }, + /** + * Go to next module. + * @private + */ + next: function () { + return this.move(1); + }, + /** + * Move to prev/next module. + * @private + * @param {number} direction + * Direction to move. +1 for next, -1 for prev. + * @return {boolean} + * True if there was a valid module in direction. + */ + move: function (direction) { + var curModule = this.modules && this.modules[this.currentModuleIx]; + if (curModule && curModule.terminate) { + curModule.terminate(direction); + } + // Remove existing focus border if any + if (this.chart.focusElement) { + this.chart.focusElement.removeFocusBorder(); + } + this.currentModuleIx += direction; + var newModule = this.modules && this.modules[this.currentModuleIx]; + if (newModule) { + if (newModule.validate && !newModule.validate()) { + return this.move(direction); // Invalid module, recurse + } + if (newModule.init) { + newModule.init(direction); // Valid module, init it + return true; + } + } + // No module + this.currentModuleIx = 0; // Reset counter + // Set focus to chart or exit anchor depending on direction + if (direction > 0) { + this.exiting = true; + this.exitAnchor.focus(); + } + else { + this.chart.container.focus(); + } + return false; + }, + /** + * We use an exit anchor to move focus out of chart whenever we want, by + * setting focus to this div and not preventing the default tab action. We + * also use this when users come back into the chart by tabbing back, in + * order to navigate from the end of the chart. + * @private + */ + updateExitAnchor: function () { + var endMarkerId = 'highcharts-end-of-chart-marker-' + this.chart.index, endMarker = getElement(endMarkerId); + this.removeExitAnchor(); + if (endMarker) { + this.makeElementAnExitAnchor(endMarker); + this.exitAnchor = endMarker; + } + else { + this.createExitAnchor(); + } + }, + /** + * Chart container should have tabindex if navigation is enabled. + * @private + */ + updateContainerTabindex: function () { + var a11yOptions = this.chart.options.accessibility, keyboardOptions = a11yOptions && a11yOptions.keyboardNavigation, shouldHaveTabindex = !(keyboardOptions && keyboardOptions.enabled === false), container = this.chart.container, curTabindex = container.getAttribute('tabIndex'); + if (shouldHaveTabindex && !curTabindex) { + container.setAttribute('tabindex', '0'); + } + else if (!shouldHaveTabindex && curTabindex === '0') { + container.removeAttribute('tabindex'); + } + }, + /** + * @private + */ + makeElementAnExitAnchor: function (el) { + el.setAttribute('class', 'highcharts-exit-anchor'); + el.setAttribute('tabindex', '0'); + el.setAttribute('aria-hidden', false); + // Handle focus + this.addExitAnchorEventsToEl(el); + }, + /** + * Add new exit anchor to the chart. + * + * @private + */ + createExitAnchor: function () { + var chart = this.chart, exitAnchor = this.exitAnchor = doc.createElement('div'); + chart.renderTo.appendChild(exitAnchor); + this.makeElementAnExitAnchor(exitAnchor); + }, + /** + * @private + */ + removeExitAnchor: function () { + if (this.exitAnchor && this.exitAnchor.parentNode) { + this.exitAnchor.parentNode + .removeChild(this.exitAnchor); + delete this.exitAnchor; + } + }, + /** + * @private + */ + addExitAnchorEventsToEl: function (element) { + var chart = this.chart, keyboardNavigation = this; + this.eventProvider.addEvent(element, 'focus', function (ev) { + var e = ev || win.event, curModule, focusComesFromChart = (e.relatedTarget && + chart.container.contains(e.relatedTarget)), comingInBackwards = !(focusComesFromChart || keyboardNavigation.exiting); + if (comingInBackwards) { + chart.renderTo.focus(); + e.preventDefault(); + // Move to last valid keyboard nav module + // Note the we don't run it, just set the index + if (keyboardNavigation.modules && + keyboardNavigation.modules.length) { + keyboardNavigation.currentModuleIx = + keyboardNavigation.modules.length - 1; + curModule = keyboardNavigation.modules[keyboardNavigation.currentModuleIx]; + // Validate the module + if (curModule && + curModule.validate && !curModule.validate()) { + // Invalid. Try moving backwards to find next valid. + keyboardNavigation.prev(); + } + else if (curModule) { + // We have a valid module, init it + curModule.init(-1); + } + } + } + else { + // Don't skip the next focus, we only skip once. + keyboardNavigation.exiting = false; + } + }); + }, + /** + * Remove all traces of keyboard navigation. + * @private + */ + destroy: function () { + this.removeExitAnchor(); + this.eventProvider.removeAddedEvents(); + if (this.chart.container.getAttribute('tabindex') === '0') { + this.chart.container.removeAttribute('tabindex'); + } + } + }; + + return KeyboardNavigation; + }); + _registerModule(_modules, 'modules/accessibility/components/LegendComponent.js', [_modules['parts/Globals.js'], _modules['parts/Legend.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/AccessibilityComponent.js'], _modules['modules/accessibility/KeyboardNavigationHandler.js'], _modules['modules/accessibility/utils/htmlUtilities.js']], function (H, Legend, U, AccessibilityComponent, KeyboardNavigationHandler, HTMLUtilities) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Accessibility component for chart legend. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, extend = U.extend, fireEvent = U.fireEvent; + var stripHTMLTags = HTMLUtilities.stripHTMLTagsFromString, removeElement = HTMLUtilities.removeElement; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * @private + */ + function scrollLegendToItem(legend, itemIx) { + var itemPage = legend.allItems[itemIx].pageIx, curPage = legend.currentPage; + if (typeof itemPage !== 'undefined' && itemPage + 1 !== curPage) { + legend.scroll(1 + itemPage - curPage); + } + } + /** + * @private + */ + function shouldDoLegendA11y(chart) { + var items = chart.legend && chart.legend.allItems, legendA11yOptions = (chart.options.legend.accessibility || {}); + return !!(items && items.length && + !(chart.colorAxis && chart.colorAxis.length) && + legendA11yOptions.enabled !== false); + } + /** + * Highlight legend item by index. + * + * @private + * @function Highcharts.Chart#highlightLegendItem + * + * @param {number} ix + * + * @return {boolean} + */ + H.Chart.prototype.highlightLegendItem = function (ix) { + var items = this.legend.allItems, oldIx = this.highlightedLegendItemIx; + if (items[ix]) { + if (items[oldIx]) { + fireEvent(items[oldIx].legendGroup.element, 'mouseout'); + } + scrollLegendToItem(this.legend, ix); + this.setFocusToElement(items[ix].legendItem, items[ix].a11yProxyElement); + fireEvent(items[ix].legendGroup.element, 'mouseover'); + return true; + } + return false; + }; + // Keep track of pressed state for legend items + addEvent(Legend, 'afterColorizeItem', function (e) { + var chart = this.chart, a11yOptions = chart.options.accessibility, legendItem = e.item; + if (a11yOptions.enabled && legendItem && legendItem.a11yProxyElement) { + legendItem.a11yProxyElement.setAttribute('aria-pressed', e.visible ? 'false' : 'true'); + } + }); + /** + * The LegendComponent class + * + * @private + * @class + * @name Highcharts.LegendComponent + */ + var LegendComponent = function () { }; + LegendComponent.prototype = new AccessibilityComponent(); + extend(LegendComponent.prototype, /** @lends Highcharts.LegendComponent */ { + /** + * Init the component + * @private + */ + init: function () { + var component = this; + this.addEvent(Legend, 'afterScroll', function () { + if (this.chart === component.chart) { + component.updateProxies(); + } + }); + }, + /** + * @private + */ + updateLegendItemProxyVisibility: function () { + var legend = this.chart.legend, items = legend.allItems || [], curPage = legend.currentPage || 1, clipHeight = legend.clipHeight || 0; + items.forEach(function (item) { + var itemPage = item.pageIx || 0, y = item._legendItemPos ? item._legendItemPos[1] : 0, h = item.legendItem ? Math.round(item.legendItem.getBBox().height) : 0, hide = y + h - legend.pages[itemPage] > clipHeight || itemPage !== curPage - 1; + if (item.a11yProxyElement) { + item.a11yProxyElement.style.visibility = hide ? + 'hidden' : 'visible'; + } + }); + }, + /** + * The legend needs updates on every render, in order to update positioning + * of the proxy overlays. + */ + onChartRender: function () { + var component = this; + // Ignore render after proxy clicked. No need to destroy it, and + // destroying also kills focus. + if (this.legendProxyButtonClicked) { + delete component.legendProxyButtonClicked; + return; + } + this.updateProxies(); + }, + /** + * @private + */ + updateProxies: function () { + removeElement(this.legendProxyGroup); + if (shouldDoLegendA11y(this.chart)) { + this.addLegendProxyGroup(); + this.proxyLegendItems(); + this.updateLegendItemProxyVisibility(); + } + }, + /** + * @private + */ + addLegendProxyGroup: function () { + var a11yOptions = this.chart.options.accessibility, groupLabel = this.chart.langFormat('accessibility.legend.legendLabel', {}), groupRole = a11yOptions.landmarkVerbosity === 'all' ? + 'region' : null; + this.legendProxyGroup = this.addProxyGroup({ + 'aria-label': groupLabel, + 'role': groupRole + }); + }, + /** + * @private + */ + proxyLegendItems: function () { + var component = this, items = (this.chart.legend && + this.chart.legend.allItems || []); + items.forEach(function (item) { + if (item.legendItem && item.legendItem.element) { + component.proxyLegendItem(item); + } + }); + }, + /** + * @private + * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item + */ + proxyLegendItem: function (item) { + var component = this, itemLabel = this.chart.langFormat('accessibility.legend.legendItem', { + chart: this.chart, + itemName: stripHTMLTags(item.name) + }), attribs = { + tabindex: -1, + 'aria-pressed': !item.visible, + 'aria-label': itemLabel + }, + // Keep track of when we should ignore next render + preClickEvent = function () { + component.legendProxyButtonClicked = true; + }, + // Considers useHTML + proxyPositioningElement = item.legendGroup.div ? + item.legendItem : item.legendGroup; + item.a11yProxyElement = this.createProxyButton(item.legendItem, this.legendProxyGroup, attribs, proxyPositioningElement, preClickEvent); + }, + /** + * Get keyboard navigation handler for this component. + * @return {Highcharts.KeyboardNavigationHandler} + */ + getKeyboardNavigation: function () { + var keys = this.keyCodes, component = this, chart = this.chart; + return new KeyboardNavigationHandler(chart, { + keyCodeMap: [ + [ + [keys.left, keys.right, keys.up, keys.down], + function (keyCode) { + return component.onKbdArrowKey(this, keyCode); + } + ], + [ + [keys.enter, keys.space], + function () { + return component.onKbdClick(this); + } + ] + ], + validate: function () { + return component.shouldHaveLegendNavigation(); + }, + init: function (direction) { + return component.onKbdNavigationInit(direction); + } + }); + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler + * @param {number} keyCode + * @return {number} + * Response code + */ + onKbdArrowKey: function (keyboardNavigationHandler, keyCode) { + var keys = this.keyCodes, response = keyboardNavigationHandler.response, chart = this.chart, a11yOptions = chart.options.accessibility, numItems = chart.legend.allItems.length, direction = (keyCode === keys.left || keyCode === keys.up) ? -1 : 1; + var res = chart.highlightLegendItem(this.highlightedLegendItemIx + direction); + if (res) { + this.highlightedLegendItemIx += direction; + return response.success; + } + if (numItems > 1 && + a11yOptions.keyboardNavigation.wrapAround) { + keyboardNavigationHandler.init(direction); + return response.success; + } + // No wrap, move + return response[direction > 0 ? 'next' : 'prev']; + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler + * @return {number} + * Response code + */ + onKbdClick: function (keyboardNavigationHandler) { + var legendItem = this.chart.legend.allItems[this.highlightedLegendItemIx]; + if (legendItem && legendItem.a11yProxyElement) { + fireEvent(legendItem.a11yProxyElement, 'click'); + } + return keyboardNavigationHandler.response.success; + }, + /** + * @private + * @return {boolean|undefined} + */ + shouldHaveLegendNavigation: function () { + var chart = this.chart, legendOptions = chart.options.legend || {}, hasLegend = chart.legend && chart.legend.allItems, hasColorAxis = chart.colorAxis && chart.colorAxis.length, legendA11yOptions = (legendOptions.accessibility || {}); + return !!(hasLegend && + chart.legend.display && + !hasColorAxis && + legendA11yOptions.enabled && + legendA11yOptions.keyboardNavigation && + legendA11yOptions.keyboardNavigation.enabled); + }, + /** + * @private + * @param {number} direction + */ + onKbdNavigationInit: function (direction) { + var chart = this.chart, lastIx = chart.legend.allItems.length - 1, ixToHighlight = direction > 0 ? 0 : lastIx; + chart.highlightLegendItem(ixToHighlight); + this.highlightedLegendItemIx = ixToHighlight; + } + }); + + return LegendComponent; + }); + _registerModule(_modules, 'modules/accessibility/components/MenuComponent.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/AccessibilityComponent.js'], _modules['modules/accessibility/KeyboardNavigationHandler.js'], _modules['modules/accessibility/utils/chartUtilities.js'], _modules['modules/accessibility/utils/htmlUtilities.js']], function (H, U, AccessibilityComponent, KeyboardNavigationHandler, ChartUtilities, HTMLUtilities) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Accessibility component for exporting menu. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend; + var unhideChartElementFromAT = ChartUtilities.unhideChartElementFromAT; + var removeElement = HTMLUtilities.removeElement, getFakeMouseEvent = HTMLUtilities.getFakeMouseEvent; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Get the wrapped export button element of a chart. + * + * @private + * @param {Highcharts.Chart} chart + * @returns {Highcharts.SVGElement} + */ + function getExportMenuButtonElement(chart) { + return chart.exportSVGElements && chart.exportSVGElements[0]; + } + /** + * Show the export menu and focus the first item (if exists). + * + * @private + * @function Highcharts.Chart#showExportMenu + */ + H.Chart.prototype.showExportMenu = function () { + var exportButton = getExportMenuButtonElement(this); + if (exportButton) { + var el = exportButton.element; + if (el.onclick) { + el.onclick(getFakeMouseEvent('click')); + } + } + }; + /** + * @private + * @function Highcharts.Chart#hideExportMenu + */ + H.Chart.prototype.hideExportMenu = function () { + var chart = this, exportList = chart.exportDivElements; + if (exportList && chart.exportContextMenu) { + // Reset hover states etc. + exportList.forEach(function (el) { + if (el.className === 'highcharts-menu-item' && el.onmouseout) { + el.onmouseout(getFakeMouseEvent('mouseout')); + } + }); + chart.highlightedExportItemIx = 0; + // Hide the menu div + chart.exportContextMenu.hideMenu(); + // Make sure the chart has focus and can capture keyboard events + chart.container.focus(); + } + }; + /** + * Highlight export menu item by index. + * + * @private + * @function Highcharts.Chart#highlightExportItem + * + * @param {number} ix + * + * @return {boolean} + */ + H.Chart.prototype.highlightExportItem = function (ix) { + var listItem = this.exportDivElements && this.exportDivElements[ix], curHighlighted = this.exportDivElements && + this.exportDivElements[this.highlightedExportItemIx], hasSVGFocusSupport; + if (listItem && + listItem.tagName === 'LI' && + !(listItem.children && listItem.children.length)) { + // Test if we have focus support for SVG elements + hasSVGFocusSupport = !!(this.renderTo.getElementsByTagName('g')[0] || {}).focus; + // Only focus if we can set focus back to the elements after + // destroying the menu (#7422) + if (listItem.focus && hasSVGFocusSupport) { + listItem.focus(); + } + if (curHighlighted && curHighlighted.onmouseout) { + curHighlighted.onmouseout(getFakeMouseEvent('mouseout')); + } + if (listItem.onmouseover) { + listItem.onmouseover(getFakeMouseEvent('mouseover')); + } + this.highlightedExportItemIx = ix; + return true; + } + return false; + }; + /** + * Try to highlight the last valid export menu item. + * + * @private + * @function Highcharts.Chart#highlightLastExportItem + * @return {boolean} + */ + H.Chart.prototype.highlightLastExportItem = function () { + var chart = this, i; + if (chart.exportDivElements) { + i = chart.exportDivElements.length; + while (i--) { + if (chart.highlightExportItem(i)) { + return true; + } + } + } + return false; + }; + /** + * @private + * @param {Highcharts.Chart} chart + */ + function exportingShouldHaveA11y(chart) { + var exportingOpts = chart.options.exporting, exportButton = getExportMenuButtonElement(chart); + return !!(exportingOpts && + exportingOpts.enabled !== false && + exportingOpts.accessibility && + exportingOpts.accessibility.enabled && + exportButton && + exportButton.element); + } + /** + * The MenuComponent class + * + * @private + * @class + * @name Highcharts.MenuComponent + */ + var MenuComponent = function () { }; + MenuComponent.prototype = new AccessibilityComponent(); + extend(MenuComponent.prototype, /** @lends Highcharts.MenuComponent */ { + /** + * Init the component + */ + init: function () { + var chart = this.chart, component = this; + this.addEvent(chart, 'exportMenuShown', function () { + component.onMenuShown(); + }); + this.addEvent(chart, 'exportMenuHidden', function () { + component.onMenuHidden(); + }); + }, + /** + * @private + */ + onMenuHidden: function () { + var menu = this.chart.exportContextMenu; + if (menu) { + menu.setAttribute('aria-hidden', 'true'); + } + this.isExportMenuShown = false; + this.setExportButtonExpandedState('false'); + }, + /** + * @private + */ + onMenuShown: function () { + var chart = this.chart, menu = chart.exportContextMenu; + if (menu) { + this.addAccessibleContextMenuAttribs(); + unhideChartElementFromAT(chart, menu); + } + this.isExportMenuShown = true; + this.setExportButtonExpandedState('true'); + }, + /** + * @private + * @param {string} stateStr + */ + setExportButtonExpandedState: function (stateStr) { + var button = this.exportButtonProxy; + if (button) { + button.setAttribute('aria-expanded', stateStr); + } + }, + /** + * Called on each render of the chart. We need to update positioning of the + * proxy overlay. + */ + onChartRender: function () { + var chart = this.chart, a11yOptions = chart.options.accessibility; + // Always start with a clean slate + removeElement(this.exportProxyGroup); + // Set screen reader properties on export menu + if (exportingShouldHaveA11y(chart)) { + // Proxy button and group + this.exportProxyGroup = this.addProxyGroup( + // Wrap in a region div if verbosity is high + a11yOptions.landmarkVerbosity === 'all' ? { + 'aria-label': chart.langFormat('accessibility.exporting.exportRegionLabel', { chart: chart }), + 'role': 'region' + } : {}); + var button = getExportMenuButtonElement(this.chart); + this.exportButtonProxy = this.createProxyButton(button, this.exportProxyGroup, { + 'aria-label': chart.langFormat('accessibility.exporting.menuButtonLabel', { chart: chart }), + 'aria-expanded': 'false' + }); + } + }, + /** + * @private + */ + addAccessibleContextMenuAttribs: function () { + var chart = this.chart, exportList = chart.exportDivElements; + if (exportList && exportList.length) { + // Set tabindex on the menu items to allow focusing by script + // Set role to give screen readers a chance to pick up the contents + exportList.forEach(function (item) { + if (item.tagName === 'LI' && + !(item.children && item.children.length)) { + item.setAttribute('tabindex', -1); + } + else { + item.setAttribute('aria-hidden', 'true'); + } + }); + // Set accessibility properties on parent div + var parentDiv = exportList[0].parentNode; + parentDiv.removeAttribute('aria-hidden'); + parentDiv.setAttribute('aria-label', chart.langFormat('accessibility.exporting.chartMenuLabel', { chart: chart })); + } + }, + /** + * Get keyboard navigation handler for this component. + * @return {Highcharts.KeyboardNavigationHandler} + */ + getKeyboardNavigation: function () { + var keys = this.keyCodes, chart = this.chart, component = this; + return new KeyboardNavigationHandler(chart, { + keyCodeMap: [ + // Arrow prev handler + [ + [keys.left, keys.up], + function () { + return component.onKbdPrevious(this); + } + ], + // Arrow next handler + [ + [keys.right, keys.down], + function () { + return component.onKbdNext(this); + } + ], + // Click handler + [ + [keys.enter, keys.space], + function () { + return component.onKbdClick(this); + } + ], + // ESC handler + [ + [keys.esc], + function () { + return this.response.prev; + } + ] + ], + // Only run exporting navigation if exporting support exists and is + // enabled on chart + validate: function () { + return chart.exportChart && + chart.options.exporting.enabled !== false && + chart.options.exporting.accessibility.enabled !== + false; + }, + // Focus export menu button + init: function () { + var exportBtn = component.exportButtonProxy, exportGroup = chart.exportingGroup; + if (exportGroup && exportBtn) { + chart.setFocusToElement(exportGroup, exportBtn); + } + }, + // Hide the menu + terminate: function () { + chart.hideExportMenu(); + } + }); + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler + * @return {number} + * Response code + */ + onKbdPrevious: function (keyboardNavigationHandler) { + var chart = this.chart, a11yOptions = chart.options.accessibility, response = keyboardNavigationHandler.response, i = chart.highlightedExportItemIx || 0; + // Try to highlight prev item in list. Highlighting e.g. + // separators will fail. + while (i--) { + if (chart.highlightExportItem(i)) { + return response.success; + } + } + // We failed, so wrap around or move to prev module + if (a11yOptions.keyboardNavigation.wrapAround) { + chart.highlightLastExportItem(); + return response.success; + } + return response.prev; + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler + * @return {number} + * Response code + */ + onKbdNext: function (keyboardNavigationHandler) { + var chart = this.chart, a11yOptions = chart.options.accessibility, response = keyboardNavigationHandler.response, i = (chart.highlightedExportItemIx || 0) + 1; + // Try to highlight next item in list. Highlighting e.g. + // separators will fail. + for (; i < chart.exportDivElements.length; ++i) { + if (chart.highlightExportItem(i)) { + return response.success; + } + } + // We failed, so wrap around or move to next module + if (a11yOptions.keyboardNavigation.wrapAround) { + chart.highlightExportItem(0); + return response.success; + } + return response.next; + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler + * @return {number} + * Response code + */ + onKbdClick: function (keyboardNavigationHandler) { + var chart = this.chart, curHighlightedItem = chart.exportDivElements[chart.highlightedExportItemIx], exportButtonElement = getExportMenuButtonElement(chart).element; + if (this.isExportMenuShown) { + this.fakeClickEvent(curHighlightedItem); + } + else { + this.fakeClickEvent(exportButtonElement); + chart.highlightExportItem(0); + } + return keyboardNavigationHandler.response.success; + } + }); + + return MenuComponent; + }); + _registerModule(_modules, 'modules/accessibility/components/SeriesComponent/SeriesKeyboardNavigation.js', [_modules['parts/Globals.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/KeyboardNavigationHandler.js'], _modules['modules/accessibility/utils/EventProvider.js'], _modules['modules/accessibility/utils/chartUtilities.js']], function (H, Point, U, KeyboardNavigationHandler, EventProvider, ChartUtilities) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Handle keyboard navigation for series. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend, defined = U.defined; + var getPointFromXY = ChartUtilities.getPointFromXY, getSeriesFromName = ChartUtilities.getSeriesFromName, scrollToPoint = ChartUtilities.scrollToPoint; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /* + * Set for which series types it makes sense to move to the closest point with + * up/down arrows, and which series types should just move to next series. + */ + H.Series.prototype.keyboardMoveVertical = true; + ['column', 'pie'].forEach(function (type) { + if (H.seriesTypes[type]) { + H.seriesTypes[type].prototype.keyboardMoveVertical = false; + } + }); + /** + * Get the index of a point in a series. This is needed when using e.g. data + * grouping. + * + * @private + * @function getPointIndex + * + * @param {Highcharts.AccessibilityPoint} point + * The point to find index of. + * + * @return {number|undefined} + * The index in the series.points array of the point. + */ + function getPointIndex(point) { + var index = point.index, points = point.series.points, i = points.length; + if (points[index] !== point) { + while (i--) { + if (points[i] === point) { + return i; + } + } + } + else { + return index; + } + } + /** + * Determine if series navigation should be skipped + * + * @private + * @function isSkipSeries + * + * @param {Highcharts.Series} series + * + * @return {boolean|number|undefined} + */ + function isSkipSeries(series) { + var a11yOptions = series.chart.options.accessibility, seriesNavOptions = a11yOptions.keyboardNavigation.seriesNavigation, seriesA11yOptions = series.options.accessibility || {}, seriesKbdNavOptions = seriesA11yOptions.keyboardNavigation; + return seriesKbdNavOptions && seriesKbdNavOptions.enabled === false || + seriesA11yOptions.enabled === false || + series.options.enableMouseTracking === false || // #8440 + !series.visible || + // Skip all points in a series where pointNavigationEnabledThreshold is + // reached + (seriesNavOptions.pointNavigationEnabledThreshold && + seriesNavOptions.pointNavigationEnabledThreshold <= + series.points.length); + } + /** + * Determine if navigation for a point should be skipped + * + * @private + * @function isSkipPoint + * + * @param {Highcharts.Point} point + * + * @return {boolean|number|undefined} + */ + function isSkipPoint(point) { + var a11yOptions = point.series.chart.options.accessibility; + return point.isNull && + a11yOptions.keyboardNavigation.seriesNavigation.skipNullPoints || + point.visible === false || + isSkipSeries(point.series); + } + /** + * Get the point in a series that is closest (in pixel distance) to a reference + * point. Optionally supply weight factors for x and y directions. + * + * @private + * @function getClosestPoint + * + * @param {Highcharts.Point} point + * @param {Highcharts.Series} series + * @param {number} [xWeight] + * @param {number} [yWeight] + * + * @return {Highcharts.Point|undefined} + */ + function getClosestPoint(point, series, xWeight, yWeight) { + var minDistance = Infinity, dPoint, minIx, distance, i = series.points.length, hasUndefinedPosition = function (point) { + return !(defined(point.plotX) && defined(point.plotY)); + }; + if (hasUndefinedPosition(point)) { + return; + } + while (i--) { + dPoint = series.points[i]; + if (hasUndefinedPosition(dPoint)) { + continue; + } + distance = (point.plotX - dPoint.plotX) * + (point.plotX - dPoint.plotX) * + (xWeight || 1) + + (point.plotY - dPoint.plotY) * + (point.plotY - dPoint.plotY) * + (yWeight || 1); + if (distance < minDistance) { + minDistance = distance; + minIx = i; + } + } + return defined(minIx) ? series.points[minIx] : void 0; + } + /** + * Highlights a point (show tooltip and display hover state). + * + * @private + * @function Highcharts.Point#highlight + * + * @return {Highcharts.Point} + * This highlighted point. + */ + Point.prototype.highlight = function () { + var chart = this.series.chart; + if (!this.isNull) { + this.onMouseOver(); // Show the hover marker and tooltip + } + else { + if (chart.tooltip) { + chart.tooltip.hide(0); + } + // Don't call blur on the element, as it messes up the chart div's focus + } + scrollToPoint(this); + // We focus only after calling onMouseOver because the state change can + // change z-index and mess up the element. + if (this.graphic) { + chart.setFocusToElement(this.graphic); + } + chart.highlightedPoint = this; + return this; + }; + /** + * Function to highlight next/previous point in chart. + * + * @private + * @function Highcharts.Chart#highlightAdjacentPoint + * + * @param {boolean} next + * Flag for the direction. + * + * @return {Highcharts.Point|boolean} + * Returns highlighted point on success, false on failure (no adjacent + * point to highlight in chosen direction). + */ + H.Chart.prototype.highlightAdjacentPoint = function (next) { + var chart = this, series = chart.series, curPoint = chart.highlightedPoint, curPointIndex = curPoint && getPointIndex(curPoint) || 0, curPoints = (curPoint && curPoint.series.points), lastSeries = chart.series && chart.series[chart.series.length - 1], lastPoint = lastSeries && lastSeries.points && + lastSeries.points[lastSeries.points.length - 1], newSeries, newPoint; + // If no points, return false + if (!series[0] || !series[0].points) { + return false; + } + if (!curPoint) { + // No point is highlighted yet. Try first/last point depending on move + // direction + newPoint = next ? series[0].points[0] : lastPoint; + } + else { + // We have a highlighted point. + // Grab next/prev point & series + newSeries = series[curPoint.series.index + (next ? 1 : -1)]; + newPoint = curPoints[curPointIndex + (next ? 1 : -1)]; + if (!newPoint && newSeries) { + // Done with this series, try next one + newPoint = newSeries.points[next ? 0 : newSeries.points.length - 1]; + } + // If there is no adjacent point, we return false + if (!newPoint) { + return false; + } + } + // Recursively skip points + if (isSkipPoint(newPoint)) { + // If we skip this whole series, move to the end of the series before we + // recurse, just to optimize + newSeries = newPoint.series; + if (isSkipSeries(newSeries)) { + chart.highlightedPoint = next ? + newSeries.points[newSeries.points.length - 1] : + newSeries.points[0]; + } + else { + // Otherwise, just move one point + chart.highlightedPoint = newPoint; + } + // Retry + return chart.highlightAdjacentPoint(next); + } + // There is an adjacent point, highlight it + return newPoint.highlight(); + }; + /** + * Highlight first valid point in a series. Returns the point if successfully + * highlighted, otherwise false. If there is a highlighted point in the series, + * use that as starting point. + * + * @private + * @function Highcharts.Series#highlightFirstValidPoint + * + * @return {boolean|Highcharts.Point} + */ + H.Series.prototype.highlightFirstValidPoint = function () { + var curPoint = this.chart.highlightedPoint, start = (curPoint && curPoint.series) === this ? + getPointIndex(curPoint) : + 0, points = this.points, len = points.length; + if (points && len) { + for (var i = start; i < len; ++i) { + if (!isSkipPoint(points[i])) { + return points[i].highlight(); + } + } + for (var j = start; j >= 0; --j) { + if (!isSkipPoint(points[j])) { + return points[j].highlight(); + } + } + } + return false; + }; + /** + * Highlight next/previous series in chart. Returns false if no adjacent series + * in the direction, otherwise returns new highlighted point. + * + * @private + * @function Highcharts.Chart#highlightAdjacentSeries + * + * @param {boolean} down + * + * @return {Highcharts.Point|boolean} + */ + H.Chart.prototype.highlightAdjacentSeries = function (down) { + var chart = this, newSeries, newPoint, adjacentNewPoint, curPoint = chart.highlightedPoint, lastSeries = chart.series && chart.series[chart.series.length - 1], lastPoint = lastSeries && lastSeries.points && + lastSeries.points[lastSeries.points.length - 1]; + // If no point is highlighted, highlight the first/last point + if (!chart.highlightedPoint) { + newSeries = down ? (chart.series && chart.series[0]) : lastSeries; + newPoint = down ? + (newSeries && newSeries.points && newSeries.points[0]) : lastPoint; + return newPoint ? newPoint.highlight() : false; + } + newSeries = chart.series[curPoint.series.index + (down ? -1 : 1)]; + if (!newSeries) { + return false; + } + // We have a new series in this direction, find the right point + // Weigh xDistance as counting much higher than Y distance + newPoint = getClosestPoint(curPoint, newSeries, 4); + if (!newPoint) { + return false; + } + // New series and point exists, but we might want to skip it + if (isSkipSeries(newSeries)) { + // Skip the series + newPoint.highlight(); + adjacentNewPoint = chart.highlightAdjacentSeries(down); // Try recurse + if (!adjacentNewPoint) { + // Recurse failed + curPoint.highlight(); + return false; + } + // Recurse succeeded + return adjacentNewPoint; + } + // Highlight the new point or any first valid point back or forwards from it + newPoint.highlight(); + return newPoint.series.highlightFirstValidPoint(); + }; + /** + * Highlight the closest point vertically. + * + * @private + * @function Highcharts.Chart#highlightAdjacentPointVertical + * + * @param {boolean} down + * + * @return {Highcharts.Point|boolean} + */ + H.Chart.prototype.highlightAdjacentPointVertical = function (down) { + var curPoint = this.highlightedPoint, minDistance = Infinity, bestPoint; + if (!defined(curPoint.plotX) || !defined(curPoint.plotY)) { + return false; + } + this.series.forEach(function (series) { + if (isSkipSeries(series)) { + return; + } + series.points.forEach(function (point) { + if (!defined(point.plotY) || !defined(point.plotX) || + point === curPoint) { + return; + } + var yDistance = point.plotY - curPoint.plotY, width = Math.abs(point.plotX - curPoint.plotX), distance = Math.abs(yDistance) * Math.abs(yDistance) + + width * width * 4; // Weigh horizontal distance highly + // Reverse distance number if axis is reversed + if (series.yAxis && series.yAxis.reversed) { + yDistance *= -1; + } + if (yDistance <= 0 && down || yDistance >= 0 && !down || // Chk dir + distance < 5 || // Points in same spot => infinite loop + isSkipPoint(point)) { + return; + } + if (distance < minDistance) { + minDistance = distance; + bestPoint = point; + } + }); + }); + return bestPoint ? bestPoint.highlight() : false; + }; + /** + * @private + * @param {Highcharts.Chart} chart + * @return {Highcharts.Point|boolean} + */ + function highlightFirstValidPointInChart(chart) { + var res = false; + delete chart.highlightedPoint; + res = chart.series.reduce(function (acc, cur) { + return acc || cur.highlightFirstValidPoint(); + }, false); + return res; + } + /** + * @private + * @param {Highcharts.Chart} chart + * @return {Highcharts.Point|boolean} + */ + function highlightLastValidPointInChart(chart) { + var numSeries = chart.series.length, i = numSeries, res = false; + while (i--) { + chart.highlightedPoint = chart.series[i].points[chart.series[i].points.length - 1]; + // Highlight first valid point in the series will also + // look backwards. It always starts from currently + // highlighted point. + res = chart.series[i].highlightFirstValidPoint(); + if (res) { + break; + } + } + return res; + } + /** + * @private + * @param {Highcharts.Chart} chart + */ + function updateChartFocusAfterDrilling(chart) { + highlightFirstValidPointInChart(chart); + if (chart.focusElement) { + chart.focusElement.removeFocusBorder(); + } + } + /** + * @private + * @class + * @name Highcharts.SeriesKeyboardNavigation + */ + function SeriesKeyboardNavigation(chart, keyCodes) { + this.keyCodes = keyCodes; + this.chart = chart; + } + extend(SeriesKeyboardNavigation.prototype, /** @lends Highcharts.SeriesKeyboardNavigation */ { + /** + * Init the keyboard navigation + */ + init: function () { + var keyboardNavigation = this, chart = this.chart, e = this.eventProvider = new EventProvider(); + e.addEvent(H.Series, 'destroy', function () { + return keyboardNavigation.onSeriesDestroy(this); + }); + e.addEvent(chart, 'afterDrilldown', function () { + updateChartFocusAfterDrilling(this); + }); + e.addEvent(chart, 'drilldown', function (e) { + var point = e.point, series = point.series; + keyboardNavigation.lastDrilledDownPoint = { + x: point.x, + y: point.y, + seriesName: series ? series.name : '' + }; + }); + e.addEvent(chart, 'drillupall', function () { + setTimeout(function () { + keyboardNavigation.onDrillupAll(); + }, 10); + }); + }, + onDrillupAll: function () { + // After drillup we want to find the point that was drilled down to and + // highlight it. + var last = this.lastDrilledDownPoint, chart = this.chart, series = last && getSeriesFromName(chart, last.seriesName), point; + if (last && series && defined(last.x) && defined(last.y)) { + point = getPointFromXY(series, last.x, last.y); + } + // Container focus can be lost on drillup due to deleted elements. + if (chart.container) { + chart.container.focus(); + } + if (point && point.highlight) { + point.highlight(); + } + if (chart.focusElement) { + chart.focusElement.removeFocusBorder(); + } + }, + /** + * @return {Highcharts.KeyboardNavigationHandler} + */ + getKeyboardNavigationHandler: function () { + var keyboardNavigation = this, keys = this.keyCodes, chart = this.chart, inverted = chart.inverted; + return new KeyboardNavigationHandler(chart, { + keyCodeMap: [ + [inverted ? [keys.up, keys.down] : [keys.left, keys.right], + function (keyCode) { + return keyboardNavigation.onKbdSideways(this, keyCode); + }], + [inverted ? [keys.left, keys.right] : [keys.up, keys.down], + function (keyCode) { + return keyboardNavigation.onKbdVertical(this, keyCode); + }], + [[keys.enter, keys.space], + function () { + if (chart.highlightedPoint) { + chart.highlightedPoint.firePointEvent('click'); + } + return this.response.success; + }] + ], + init: function (dir) { + return keyboardNavigation.onHandlerInit(this, dir); + }, + terminate: function () { + return keyboardNavigation.onHandlerTerminate(); + } + }); + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} handler + * @param {number} keyCode + * @return {number} + * response + */ + onKbdSideways: function (handler, keyCode) { + var keys = this.keyCodes, isNext = keyCode === keys.right || keyCode === keys.down; + return this.attemptHighlightAdjacentPoint(handler, isNext); + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} handler + * @param {number} keyCode + * @return {number} + * response + */ + onKbdVertical: function (handler, keyCode) { + var chart = this.chart, keys = this.keyCodes, isNext = keyCode === keys.down || keyCode === keys.right, navOptions = chart.options.accessibility.keyboardNavigation + .seriesNavigation; + // Handle serialized mode, act like left/right + if (navOptions.mode && navOptions.mode === 'serialize') { + return this.attemptHighlightAdjacentPoint(handler, isNext); + } + // Normal mode, move between series + var highlightMethod = (chart.highlightedPoint && + chart.highlightedPoint.series.keyboardMoveVertical) ? + 'highlightAdjacentPointVertical' : + 'highlightAdjacentSeries'; + chart[highlightMethod](isNext); + return handler.response.success; + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} handler + * @param {number} initDirection + * @return {number} + * response + */ + onHandlerInit: function (handler, initDirection) { + var chart = this.chart; + if (initDirection > 0) { + highlightFirstValidPointInChart(chart); + } + else { + highlightLastValidPointInChart(chart); + } + return handler.response.success; + }, + /** + * @private + */ + onHandlerTerminate: function () { + var _a, _b; + var chart = this.chart; + var curPoint = chart.highlightedPoint; + (_a = chart.tooltip) === null || _a === void 0 ? void 0 : _a.hide(0); + (_b = curPoint === null || curPoint === void 0 ? void 0 : curPoint.onMouseOut) === null || _b === void 0 ? void 0 : _b.call(curPoint); + delete chart.highlightedPoint; + }, + /** + * Function that attempts to highlight next/prev point. Handles wrap around. + * @private + * @param {Highcharts.KeyboardNavigationHandler} handler + * @param {boolean} directionIsNext + * @return {number} + * response + */ + attemptHighlightAdjacentPoint: function (handler, directionIsNext) { + var chart = this.chart, wrapAround = chart.options.accessibility.keyboardNavigation + .wrapAround, highlightSuccessful = chart.highlightAdjacentPoint(directionIsNext); + if (!highlightSuccessful) { + if (wrapAround) { + return handler.init(directionIsNext ? 1 : -1); + } + return handler.response[directionIsNext ? 'next' : 'prev']; + } + return handler.response.success; + }, + /** + * @private + */ + onSeriesDestroy: function (series) { + var chart = this.chart, currentHighlightedPointDestroyed = chart.highlightedPoint && + chart.highlightedPoint.series === series; + if (currentHighlightedPointDestroyed) { + delete chart.highlightedPoint; + if (chart.focusElement) { + chart.focusElement.removeFocusBorder(); + } + } + }, + /** + * @private + */ + destroy: function () { + this.eventProvider.removeAddedEvents(); + } + }); + + return SeriesKeyboardNavigation; + }); + _registerModule(_modules, 'modules/accessibility/components/AnnotationsA11y.js', [_modules['parts/Utilities.js'], _modules['modules/accessibility/utils/htmlUtilities.js']], function (U, HTMLUtilities) { + /* * + * + * (c) 2009-2019 Øystein Moseng + * + * Annotations accessibility code. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var inArray = U.inArray; + var escapeStringForHTML = HTMLUtilities.escapeStringForHTML, stripHTMLTagsFromString = HTMLUtilities.stripHTMLTagsFromString; + /** + * Get list of all annotation labels in the chart. + * + * @private + * @param {Highcharts.Chart} chart The chart to get annotation info on. + * @return {Array} The labels, or empty array if none. + */ + function getChartAnnotationLabels(chart) { + var annotations = chart.annotations || []; + return annotations.reduce(function (acc, cur) { + var _a; + if (((_a = cur.options) === null || _a === void 0 ? void 0 : _a.visible) !== false) { + acc = acc.concat(cur.labels); + } + return acc; + }, []); + } + /** + * Get the text of an annotation label. + * + * @private + * @param {object} label The annotation label object + * @return {string} The text in the label. + */ + function getLabelText(label) { + var _a, _b, _c, _d; + var a11yDesc = (_b = (_a = label.options) === null || _a === void 0 ? void 0 : _a.accessibility) === null || _b === void 0 ? void 0 : _b.description; + return a11yDesc ? a11yDesc : ((_d = (_c = label.graphic) === null || _c === void 0 ? void 0 : _c.text) === null || _d === void 0 ? void 0 : _d.textStr) || ''; + } + /** + * Describe an annotation label. + * + * @private + * @param {object} label The annotation label object to describe + * @return {string} The description for the label. + */ + function getAnnotationLabelDescription(label) { + var _a, _b; + var a11yDesc = (_b = (_a = label.options) === null || _a === void 0 ? void 0 : _a.accessibility) === null || _b === void 0 ? void 0 : _b.description; + if (a11yDesc) { + return a11yDesc; + } + var chart = label.chart; + var labelText = getLabelText(label); + var points = label.points; + var getAriaLabel = function (point) { var _a, _b; return ((_b = (_a = point === null || point === void 0 ? void 0 : point.graphic) === null || _a === void 0 ? void 0 : _a.element) === null || _b === void 0 ? void 0 : _b.getAttribute('aria-label')) || ''; }; + var getValueDesc = function (point) { + var _a; + var valDesc = ((_a = point === null || point === void 0 ? void 0 : point.accessibility) === null || _a === void 0 ? void 0 : _a.valueDescription) || getAriaLabel(point); + var seriesName = (point === null || point === void 0 ? void 0 : point.series.name) || ''; + return (seriesName ? seriesName + ', ' : '') + 'data point ' + valDesc; + }; + var pointValueDescriptions = points + .filter(function (p) { return !!p.graphic; }) // Filter out mock points + .map(getValueDesc) + .filter(function (desc) { return !!desc; }); // Filter out points we can't describe + var numPoints = pointValueDescriptions.length; + var pointsSelector = numPoints > 1 ? 'MultiplePoints' : numPoints ? 'SinglePoint' : 'NoPoints'; + var langFormatStr = 'accessibility.screenReaderSection.annotations.description' + pointsSelector; + var context = { + annotationText: labelText, + numPoints: numPoints, + annotationPoint: pointValueDescriptions[0], + additionalAnnotationPoints: pointValueDescriptions.slice(1) + }; + return chart.langFormat(langFormatStr, context); + } + /** + * Return array of HTML strings for each annotation label in the chart. + * + * @private + * @param {Highcharts.Chart} chart The chart to get annotation info on. + * @return {Array} Array of strings with HTML content for each annotation label. + */ + function getAnnotationListItems(chart) { + var labels = getChartAnnotationLabels(chart); + return labels.map(function (label) { + var desc = escapeStringForHTML(stripHTMLTagsFromString(getAnnotationLabelDescription(label))); + return desc ? "
  • " + desc + "
  • " : ''; + }); + } + /** + * Return the annotation info for a chart as string. + * + * @private + * @param {Highcharts.Chart} chart The chart to get annotation info on. + * @return {string} String with HTML content or empty string if no annotations. + */ + function getAnnotationsInfoHTML(chart) { + var annotations = chart.annotations; + if (!(annotations && annotations.length)) { + return ''; + } + var annotationItems = getAnnotationListItems(chart); + return "
      " + annotationItems.join(' ') + "
    "; + } + /** + * Return the texts for the annotation(s) connected to a point, or empty array + * if none. + * + * @private + * @param {Highcharts.Point} point The data point to get the annotation info from. + * @return {Array} Annotation texts + */ + function getPointAnnotationTexts(point) { + var labels = getChartAnnotationLabels(point.series.chart); + var pointLabels = labels + .filter(function (label) { return inArray(point, label.points) > -1; }); + if (!pointLabels.length) { + return []; + } + return pointLabels.map(function (label) { return "" + getLabelText(label); }); + } + var AnnotationsA11y = { + getAnnotationsInfoHTML: getAnnotationsInfoHTML, + getAnnotationLabelDescription: getAnnotationLabelDescription, + getAnnotationListItems: getAnnotationListItems, + getPointAnnotationTexts: getPointAnnotationTexts + }; + + return AnnotationsA11y; + }); + _registerModule(_modules, 'modules/accessibility/components/SeriesComponent/SeriesDescriber.js', [_modules['parts/Utilities.js'], _modules['modules/accessibility/components/AnnotationsA11y.js'], _modules['modules/accessibility/utils/htmlUtilities.js'], _modules['modules/accessibility/utils/chartUtilities.js'], _modules['parts/Tooltip.js']], function (U, AnnotationsA11y, HTMLUtilities, ChartUtilities, Tooltip) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Place desriptions on a series and its points. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var find = U.find, format = U.format, isNumber = U.isNumber, numberFormat = U.numberFormat, pick = U.pick, defined = U.defined; + var getPointAnnotationTexts = AnnotationsA11y.getPointAnnotationTexts; + var escapeStringForHTML = HTMLUtilities.escapeStringForHTML, reverseChildNodes = HTMLUtilities.reverseChildNodes, stripHTMLTags = HTMLUtilities.stripHTMLTagsFromString; + var getAxisDescription = ChartUtilities.getAxisDescription, getSeriesFirstPointElement = ChartUtilities.getSeriesFirstPointElement, getSeriesA11yElement = ChartUtilities.getSeriesA11yElement, unhideChartElementFromAT = ChartUtilities.unhideChartElementFromAT; + /* eslint-disable valid-jsdoc */ + /** + * @private + */ + function findFirstPointWithGraphic(point) { + var sourcePointIndex = point.index; + if (!point.series || !point.series.data || !defined(sourcePointIndex)) { + return null; + } + return find(point.series.data, function (p) { + return !!(p && + typeof p.index !== 'undefined' && + p.index > sourcePointIndex && + p.graphic && + p.graphic.element); + }) || null; + } + /** + * @private + */ + function shouldAddDummyPoint(point) { + // Note: Sunburst series use isNull for hidden points on drilldown. + // Ignore these. + var isSunburst = point.series && point.series.is('sunburst'), isNull = point.isNull; + return isNull && !isSunburst; + } + /** + * @private + */ + function makeDummyElement(point, pos) { + var renderer = point.series.chart.renderer, dummy = renderer.rect(pos.x, pos.y, 1, 1); + dummy.attr({ + 'class': 'highcharts-a11y-dummy-point', + fill: 'none', + opacity: 0, + 'fill-opacity': 0, + 'stroke-opacity': 0 + }); + return dummy; + } + /** + * @private + * @param {Highcharts.Point} point + * @return {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement|undefined} + */ + function addDummyPointElement(point) { + var series = point.series, firstPointWithGraphic = findFirstPointWithGraphic(point), firstGraphic = firstPointWithGraphic && firstPointWithGraphic.graphic, parentGroup = firstGraphic ? + firstGraphic.parentGroup : + series.graph || series.group, dummyPos = firstPointWithGraphic ? { + x: pick(point.plotX, firstPointWithGraphic.plotX, 0), + y: pick(point.plotY, firstPointWithGraphic.plotY, 0) + } : { + x: pick(point.plotX, 0), + y: pick(point.plotY, 0) + }, dummyElement = makeDummyElement(point, dummyPos); + if (parentGroup && parentGroup.element) { + point.graphic = dummyElement; + point.hasDummyGraphic = true; + dummyElement.add(parentGroup); + // Move to correct pos in DOM + parentGroup.element.insertBefore(dummyElement.element, firstGraphic ? firstGraphic.element : null); + return dummyElement.element; + } + } + /** + * @private + * @param {Highcharts.Series} series + * @return {boolean} + */ + function hasMorePointsThanDescriptionThreshold(series) { + var chartA11yOptions = series.chart.options.accessibility, threshold = (chartA11yOptions.series.pointDescriptionEnabledThreshold); + return !!(threshold !== false && + series.points && + series.points.length >= threshold); + } + /** + * @private + * @param {Highcharts.Series} series + * @return {boolean} + */ + function shouldSetScreenReaderPropsOnPoints(series) { + var seriesA11yOptions = series.options.accessibility || {}; + return !hasMorePointsThanDescriptionThreshold(series) && + !seriesA11yOptions.exposeAsGroupOnly; + } + /** + * @private + * @param {Highcharts.Series} series + * @return {boolean} + */ + function shouldSetKeyboardNavPropsOnPoints(series) { + var chartA11yOptions = series.chart.options.accessibility, seriesNavOptions = chartA11yOptions.keyboardNavigation.seriesNavigation; + return !!(series.points && (series.points.length < + seriesNavOptions.pointNavigationEnabledThreshold || + seriesNavOptions.pointNavigationEnabledThreshold === false)); + } + /** + * @private + * @param {Highcharts.Series} series + * @return {boolean} + */ + function shouldDescribeSeriesElement(series) { + var chart = series.chart, chartOptions = chart.options.chart || {}, chartHas3d = chartOptions.options3d && chartOptions.options3d.enabled, hasMultipleSeries = chart.series.length > 1, describeSingleSeriesOption = chart.options.accessibility.series.describeSingleSeries, exposeAsGroupOnlyOption = (series.options.accessibility || {}).exposeAsGroupOnly, noDescribe3D = chartHas3d && hasMultipleSeries; + return !noDescribe3D && (hasMultipleSeries || describeSingleSeriesOption || + exposeAsGroupOnlyOption || hasMorePointsThanDescriptionThreshold(series)); + } + /** + * @private + * @param {Highcharts.Point} point + * @param {number} value + * @return {string} + */ + function pointNumberToString(point, value) { + var chart = point.series.chart, a11yPointOptions = chart.options.accessibility.point || {}, tooltipOptions = point.series.tooltipOptions || {}, lang = chart.options.lang; + if (isNumber(value)) { + return numberFormat(value, a11yPointOptions.valueDecimals || + tooltipOptions.valueDecimals || + -1, lang.decimalPoint, lang.accessibility.thousandsSep || lang.thousandsSep); + } + return value; + } + /** + * @private + * @param {Highcharts.Series} series + * @return {string} + */ + function getSeriesDescriptionText(series) { + var seriesA11yOptions = series.options.accessibility || {}, descOpt = seriesA11yOptions.description; + return descOpt && series.chart.langFormat('accessibility.series.description', { + description: descOpt, + series: series + }) || ''; + } + /** + * @private + * @param {Highcharts.series} series + * @param {string} axisCollection + * @return {string} + */ + function getSeriesAxisDescriptionText(series, axisCollection) { + var axis = series[axisCollection]; + return series.chart.langFormat('accessibility.series.' + axisCollection + 'Description', { + name: getAxisDescription(axis), + series: series + }); + } + /** + * Get accessible time description for a point on a datetime axis. + * + * @private + * @function Highcharts.Point#getTimeDescription + * @param {Highcharts.Point} point + * @return {string|undefined} + * The description as string. + */ + function getPointA11yTimeDescription(point) { + var series = point.series, chart = series.chart, a11yOptions = chart.options.accessibility.point || {}, hasDateXAxis = series.xAxis && series.xAxis.dateTime; + if (hasDateXAxis) { + var tooltipDateFormat = Tooltip.prototype.getXDateFormat.call({ + getDateFormat: Tooltip.prototype.getDateFormat, + chart: chart + }, point, chart.options.tooltip, series.xAxis), dateFormat = a11yOptions.dateFormatter && + a11yOptions.dateFormatter(point) || + a11yOptions.dateFormat || + tooltipDateFormat; + return chart.time.dateFormat(dateFormat, point.x, void 0); + } + } + /** + * @private + * @param {Highcharts.Point} point + * @return {string} + */ + function getPointXDescription(point) { + var timeDesc = getPointA11yTimeDescription(point), xAxis = point.series.xAxis || {}, pointCategory = xAxis.categories && defined(point.category) && + ('' + point.category).replace('
    ', ' '), canUseId = point.id && point.id.indexOf('highcharts-') < 0, fallback = 'x, ' + point.x; + return point.name || timeDesc || pointCategory || + (canUseId ? point.id : fallback); + } + /** + * @private + * @param {Highcharts.Point} point + * @param {string} prefix + * @param {string} suffix + * @return {string} + */ + function getPointArrayMapValueDescription(point, prefix, suffix) { + var pre = prefix || '', suf = suffix || '', keyToValStr = function (key) { + var num = pointNumberToString(point, pick(point[key], point.options[key])); + return key + ': ' + pre + num + suf; + }, pointArrayMap = point.series.pointArrayMap; + return pointArrayMap.reduce(function (desc, key) { + return desc + (desc.length ? ', ' : '') + keyToValStr(key); + }, ''); + } + /** + * @private + * @param {Highcharts.Point} point + * @return {string} + */ + function getPointValue(point) { + var series = point.series, a11yPointOpts = series.chart.options.accessibility.point || {}, tooltipOptions = series.tooltipOptions || {}, valuePrefix = a11yPointOpts.valuePrefix || + tooltipOptions.valuePrefix || '', valueSuffix = a11yPointOpts.valueSuffix || + tooltipOptions.valueSuffix || '', fallbackKey = (typeof point.value !== + 'undefined' ? + 'value' : 'y'), fallbackDesc = pointNumberToString(point, point[fallbackKey]); + if (point.isNull) { + return series.chart.langFormat('accessibility.series.nullPointValue', { + point: point + }); + } + if (series.pointArrayMap) { + return getPointArrayMapValueDescription(point, valuePrefix, valueSuffix); + } + return valuePrefix + fallbackDesc + valueSuffix; + } + /** + * Return the description for the annotation(s) connected to a point, or empty + * string if none. + * + * @private + * @param {Highcharts.Point} point The data point to get the annotation info from. + * @return {string} Annotation description + */ + function getPointAnnotationDescription(point) { + var chart = point.series.chart; + var langKey = 'accessibility.series.pointAnnotationsDescription'; + var annotations = getPointAnnotationTexts(point); + var context = { point: point, annotations: annotations }; + return annotations.length ? chart.langFormat(langKey, context) : ''; + } + /** + * Return string with information about point. + * @private + * @return {string} + */ + function getPointValueDescription(point) { + var series = point.series, chart = series.chart, pointValueDescriptionFormat = chart.options.accessibility + .point.valueDescriptionFormat, showXDescription = pick(series.xAxis && + series.xAxis.options.accessibility && + series.xAxis.options.accessibility.enabled, !chart.angular), xDesc = showXDescription ? getPointXDescription(point) : '', context = { + point: point, + index: defined(point.index) ? (point.index + 1) : '', + xDescription: xDesc, + value: getPointValue(point), + separator: showXDescription ? ', ' : '' + }; + return format(pointValueDescriptionFormat, context, chart); + } + /** + * Return string with information about point. + * @private + * @return {string} + */ + function defaultPointDescriptionFormatter(point) { + var series = point.series, chart = series.chart, valText = getPointValueDescription(point), description = point.options && point.options.accessibility && + point.options.accessibility.description, userDescText = description ? ' ' + description : '', seriesNameText = chart.series.length > 1 && series.name ? + ' ' + series.name + '.' : '', annotationsDesc = getPointAnnotationDescription(point), pointAnnotationsText = annotationsDesc ? ' ' + annotationsDesc : ''; + point.accessibility = point.accessibility || {}; + point.accessibility.valueDescription = valText; + return valText + userDescText + seriesNameText + pointAnnotationsText; + } + /** + * Set a11y props on a point element + * @private + * @param {Highcharts.Point} point + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} pointElement + */ + function setPointScreenReaderAttribs(point, pointElement) { + var series = point.series, a11yPointOptions = series.chart.options.accessibility.point || {}, seriesA11yOptions = series.options.accessibility || {}, label = escapeStringForHTML(stripHTMLTags(seriesA11yOptions.pointDescriptionFormatter && + seriesA11yOptions.pointDescriptionFormatter(point) || + a11yPointOptions.descriptionFormatter && + a11yPointOptions.descriptionFormatter(point) || + defaultPointDescriptionFormatter(point))); + pointElement.setAttribute('role', 'img'); + pointElement.setAttribute('aria-label', label); + } + /** + * Add accessible info to individual point elements of a series + * @private + * @param {Highcharts.Series} series + */ + function describePointsInSeries(series) { + var setScreenReaderProps = shouldSetScreenReaderPropsOnPoints(series), setKeyboardProps = shouldSetKeyboardNavPropsOnPoints(series); + if (setScreenReaderProps || setKeyboardProps) { + series.points.forEach(function (point) { + var pointEl = point.graphic && point.graphic.element || + shouldAddDummyPoint(point) && addDummyPointElement(point); + if (pointEl) { + // We always set tabindex, as long as we are setting props. + // When setting tabindex, also remove default outline to + // avoid ugly border on click. + pointEl.setAttribute('tabindex', '-1'); + pointEl.style.outline = '0'; + if (setScreenReaderProps) { + setPointScreenReaderAttribs(point, pointEl); + } + else { + pointEl.setAttribute('aria-hidden', true); + } + } + }); + } + } + /** + * Return string with information about series. + * @private + * @return {string} + */ + function defaultSeriesDescriptionFormatter(series) { + var chart = series.chart, chartTypes = chart.types || [], description = getSeriesDescriptionText(series), shouldDescribeAxis = function (coll) { + return chart[coll] && chart[coll].length > 1 && series[coll]; + }, xAxisInfo = getSeriesAxisDescriptionText(series, 'xAxis'), yAxisInfo = getSeriesAxisDescriptionText(series, 'yAxis'), summaryContext = { + name: series.name || '', + ix: series.index + 1, + numSeries: chart.series && chart.series.length, + numPoints: series.points && series.points.length, + series: series + }, combinationSuffix = chartTypes.length > 1 ? 'Combination' : '', summary = chart.langFormat('accessibility.series.summary.' + series.type + combinationSuffix, summaryContext) || chart.langFormat('accessibility.series.summary.default' + combinationSuffix, summaryContext); + return summary + (description ? ' ' + description : '') + (shouldDescribeAxis('yAxis') ? ' ' + yAxisInfo : '') + (shouldDescribeAxis('xAxis') ? ' ' + xAxisInfo : ''); + } + /** + * Set a11y props on a series element + * @private + * @param {Highcharts.Series} series + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} seriesElement + */ + function describeSeriesElement(series, seriesElement) { + var seriesA11yOptions = series.options.accessibility || {}, a11yOptions = series.chart.options.accessibility, landmarkVerbosity = a11yOptions.landmarkVerbosity; + // Handle role attribute + if (seriesA11yOptions.exposeAsGroupOnly) { + seriesElement.setAttribute('role', 'img'); + } + else if (landmarkVerbosity === 'all') { + seriesElement.setAttribute('role', 'region'); + } /* else do not add role */ + seriesElement.setAttribute('tabindex', '-1'); + seriesElement.style.outline = '0'; // Don't show browser outline on click, despite tabindex + seriesElement.setAttribute('aria-label', escapeStringForHTML(stripHTMLTags(a11yOptions.series.descriptionFormatter && + a11yOptions.series.descriptionFormatter(series) || + defaultSeriesDescriptionFormatter(series)))); + } + /** + * Put accessible info on series and points of a series. + * @param {Highcharts.Series} series The series to add info on. + */ + function describeSeries(series) { + var chart = series.chart, firstPointEl = getSeriesFirstPointElement(series), seriesEl = getSeriesA11yElement(series), is3d = chart.is3d && chart.is3d(); + if (seriesEl) { + // For some series types the order of elements do not match the + // order of points in series. In that case we have to reverse them + // in order for AT to read them out in an understandable order. + // Due to z-index issues we can not do this for 3D charts. + if (seriesEl.lastChild === firstPointEl && !is3d) { + reverseChildNodes(seriesEl); + } + describePointsInSeries(series); + unhideChartElementFromAT(chart, seriesEl); + if (shouldDescribeSeriesElement(series)) { + describeSeriesElement(series, seriesEl); + } + else { + seriesEl.setAttribute('aria-label', ''); + } + } + } + var SeriesDescriber = { + describeSeries: describeSeries, + defaultPointDescriptionFormatter: defaultPointDescriptionFormatter, + defaultSeriesDescriptionFormatter: defaultSeriesDescriptionFormatter, + getPointA11yTimeDescription: getPointA11yTimeDescription, + getPointXDescription: getPointXDescription, + getPointValue: getPointValue, + getPointValueDescription: getPointValueDescription + }; + + return SeriesDescriber; + }); + _registerModule(_modules, 'modules/accessibility/utils/Announcer.js', [_modules['parts/Globals.js'], _modules['modules/accessibility/utils/DOMElementProvider.js'], _modules['modules/accessibility/utils/htmlUtilities.js']], function (H, DOMElementProvider, HTMLUtilities) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Create announcer to speak messages to screen readers and other AT. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var visuallyHideElement = HTMLUtilities.visuallyHideElement; + var Announcer = /** @class */ (function () { + function Announcer(chart, type) { + this.chart = chart; + this.domElementProvider = new DOMElementProvider(); + this.announceRegion = this.addAnnounceRegion(type); + } + Announcer.prototype.destroy = function () { + this.domElementProvider.destroyCreatedElements(); + }; + Announcer.prototype.announce = function (message) { + var _this = this; + this.announceRegion.innerHTML = message; + // Delete contents after a little while to avoid user finding the live + // region in the DOM. + if (this.clearAnnouncementRegionTimer) { + clearTimeout(this.clearAnnouncementRegionTimer); + } + this.clearAnnouncementRegionTimer = setTimeout(function () { + _this.announceRegion.innerHTML = ''; + delete _this.clearAnnouncementRegionTimer; + }, 1000); + }; + Announcer.prototype.addAnnounceRegion = function (type) { + var chartContainer = this.chart.renderTo; + var div = this.domElementProvider.createElement('div'); + div.setAttribute('aria-hidden', false); + div.setAttribute('aria-live', type); + visuallyHideElement(div); + chartContainer.insertBefore(div, chartContainer.firstChild); + return div; + }; + return Announcer; + }()); + H.Announcer = Announcer; + + return Announcer; + }); + _registerModule(_modules, 'modules/accessibility/components/SeriesComponent/NewDataAnnouncer.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/utils/chartUtilities.js'], _modules['modules/accessibility/components/SeriesComponent/SeriesDescriber.js'], _modules['modules/accessibility/utils/Announcer.js'], _modules['modules/accessibility/utils/EventProvider.js']], function (H, U, ChartUtilities, SeriesDescriber, Announcer, EventProvider) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Handle announcing new data for a chart. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend, defined = U.defined; + var getChartTitle = ChartUtilities.getChartTitle; + var defaultPointDescriptionFormatter = SeriesDescriber + .defaultPointDescriptionFormatter, defaultSeriesDescriptionFormatter = SeriesDescriber + .defaultSeriesDescriptionFormatter; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * @private + */ + function chartHasAnnounceEnabled(chart) { + return !!chart.options.accessibility.announceNewData.enabled; + } + /** + * @private + */ + function findPointInDataArray(point) { + var candidates = point.series.data.filter(function (candidate) { + return point.x === candidate.x && point.y === candidate.y; + }); + return candidates.length === 1 ? candidates[0] : point; + } + /** + * Get array of unique series from two arrays + * @private + */ + function getUniqueSeries(arrayA, arrayB) { + var uniqueSeries = (arrayA || []).concat(arrayB || []) + .reduce(function (acc, cur) { + acc[cur.name + cur.index] = cur; + return acc; + }, {}); + return Object.keys(uniqueSeries).map(function (ix) { + return uniqueSeries[ix]; + }); + } + /** + * @private + * @class + */ + var NewDataAnnouncer = function (chart) { + this.chart = chart; + }; + extend(NewDataAnnouncer.prototype, { + /** + * Initialize the new data announcer. + * @private + */ + init: function () { + var chart = this.chart; + var announceOptions = chart.options.accessibility.announceNewData; + var announceType = announceOptions.interruptUser ? 'assertive' : 'polite'; + this.lastAnnouncementTime = 0; + this.dirty = { + allSeries: {} + }; + this.eventProvider = new EventProvider(); + this.announcer = new Announcer(chart, announceType); + this.addEventListeners(); + }, + /** + * Remove traces of announcer. + * @private + */ + destroy: function () { + this.eventProvider.removeAddedEvents(); + this.announcer.destroy(); + }, + /** + * Add event listeners for the announcer + * @private + */ + addEventListeners: function () { + var announcer = this, chart = this.chart, e = this.eventProvider; + e.addEvent(chart, 'afterDrilldown', function () { + announcer.lastAnnouncementTime = 0; + }); + e.addEvent(H.Series, 'updatedData', function () { + announcer.onSeriesUpdatedData(this); + }); + e.addEvent(chart, 'afterAddSeries', function (e) { + announcer.onSeriesAdded(e.series); + }); + e.addEvent(H.Series, 'addPoint', function (e) { + announcer.onPointAdded(e.point); + }); + e.addEvent(chart, 'redraw', function () { + announcer.announceDirtyData(); + }); + }, + /** + * On new data in the series, make sure we add it to the dirty list. + * @private + * @param {Highcharts.Series} series + */ + onSeriesUpdatedData: function (series) { + var chart = this.chart; + if (series.chart === chart && chartHasAnnounceEnabled(chart)) { + this.dirty.hasDirty = true; + this.dirty.allSeries[series.name + series.index] = series; + } + }, + /** + * On new data series added, update dirty list. + * @private + * @param {Highcharts.Series} series + */ + onSeriesAdded: function (series) { + if (chartHasAnnounceEnabled(this.chart)) { + this.dirty.hasDirty = true; + this.dirty.allSeries[series.name + series.index] = series; + // Add it to newSeries storage unless we already have one + this.dirty.newSeries = defined(this.dirty.newSeries) ? + void 0 : series; + } + }, + /** + * On new point added, update dirty list. + * @private + * @param {Highcharts.Point} point + */ + onPointAdded: function (point) { + var chart = point.series.chart; + if (this.chart === chart && chartHasAnnounceEnabled(chart)) { + // Add it to newPoint storage unless we already have one + this.dirty.newPoint = defined(this.dirty.newPoint) ? + void 0 : point; + } + }, + /** + * Gather what we know and announce the data to user. + * @private + */ + announceDirtyData: function () { + var chart = this.chart, announcer = this; + if (chart.options.accessibility.announceNewData && + this.dirty.hasDirty) { + var newPoint = this.dirty.newPoint; + // If we have a single new point, see if we can find it in the + // data array. Otherwise we can only pass through options to + // the description builder, and it is a bit sparse in info. + if (newPoint) { + newPoint = findPointInDataArray(newPoint); + } + this.queueAnnouncement(Object.keys(this.dirty.allSeries).map(function (ix) { + return announcer.dirty.allSeries[ix]; + }), this.dirty.newSeries, newPoint); + // Reset + this.dirty = { + allSeries: {} + }; + } + }, + /** + * Announce to user that there is new data. + * @private + * @param {Array} dirtySeries + * Array of series with new data. + * @param {Highcharts.Series} [newSeries] + * If a single new series was added, a reference to this series. + * @param {Highcharts.Point} [newPoint] + * If a single point was added, a reference to this point. + */ + queueAnnouncement: function (dirtySeries, newSeries, newPoint) { + var _this = this; + var chart = this.chart; + var annOptions = chart.options.accessibility.announceNewData; + if (annOptions.enabled) { + var now = +new Date(); + var dTime = now - this.lastAnnouncementTime; + var time = Math.max(0, annOptions.minAnnounceInterval - dTime); + // Add series from previously queued announcement. + var allSeries = getUniqueSeries(this.queuedAnnouncement && this.queuedAnnouncement.series, dirtySeries); + // Build message and announce + var message = this.buildAnnouncementMessage(allSeries, newSeries, newPoint); + if (message) { + // Is there already one queued? + if (this.queuedAnnouncement) { + clearTimeout(this.queuedAnnouncementTimer); + } + // Build the announcement + this.queuedAnnouncement = { + time: now, + message: message, + series: allSeries + }; + // Queue the announcement + this.queuedAnnouncementTimer = setTimeout(function () { + if (_this && _this.announcer) { + _this.lastAnnouncementTime = +new Date(); + _this.announcer.announce(_this.queuedAnnouncement.message); + delete _this.queuedAnnouncement; + delete _this.queuedAnnouncementTimer; + } + }, time); + } + } + }, + /** + * Get announcement message for new data. + * @private + * @param {Array} dirtySeries + * Array of series with new data. + * @param {Highcharts.Series} [newSeries] + * If a single new series was added, a reference to this series. + * @param {Highcharts.Point} [newPoint] + * If a single point was added, a reference to this point. + * + * @return {string|null} + * The announcement message to give to user. + */ + buildAnnouncementMessage: function (dirtySeries, newSeries, newPoint) { + var chart = this.chart, annOptions = chart.options.accessibility.announceNewData; + // User supplied formatter? + if (annOptions.announcementFormatter) { + var formatterRes = annOptions.announcementFormatter(dirtySeries, newSeries, newPoint); + if (formatterRes !== false) { + return formatterRes.length ? formatterRes : null; + } + } + // Default formatter - use lang options + var multiple = H.charts && H.charts.length > 1 ? 'Multiple' : 'Single', langKey = newSeries ? 'newSeriesAnnounce' + multiple : + newPoint ? 'newPointAnnounce' + multiple : 'newDataAnnounce', chartTitle = getChartTitle(chart); + return chart.langFormat('accessibility.announceNewData.' + langKey, { + chartTitle: chartTitle, + seriesDesc: newSeries ? + defaultSeriesDescriptionFormatter(newSeries) : + null, + pointDesc: newPoint ? + defaultPointDescriptionFormatter(newPoint) : + null, + point: newPoint, + series: newSeries + }); + } + }); + + return NewDataAnnouncer; + }); + _registerModule(_modules, 'modules/accessibility/components/SeriesComponent/forcedMarkers.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Handle forcing series markers. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, merge = U.merge; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * @private + */ + function isWithinDescriptionThreshold(series) { + var a11yOptions = series.chart.options.accessibility; + return series.points.length < + a11yOptions.series.pointDescriptionEnabledThreshold || + a11yOptions.series.pointDescriptionEnabledThreshold === false; + } + /** + * @private + */ + function isWithinNavigationThreshold(series) { + var navOptions = series.chart.options.accessibility + .keyboardNavigation.seriesNavigation; + return series.points.length < + navOptions.pointNavigationEnabledThreshold || + navOptions.pointNavigationEnabledThreshold === false; + } + /** + * @private + */ + function shouldForceMarkers(series) { + var chartA11yEnabled = series.chart.options.accessibility.enabled, seriesA11yEnabled = (series.options.accessibility && + series.options.accessibility.enabled) !== false, withinDescriptionThreshold = isWithinDescriptionThreshold(series), withinNavigationThreshold = isWithinNavigationThreshold(series); + return chartA11yEnabled && seriesA11yEnabled && + (withinDescriptionThreshold || withinNavigationThreshold); + } + /** + * @private + */ + function unforceMarkerOptions(series) { + var resetMarkerOptions = series.resetA11yMarkerOptions; + merge(true, series.options, { + marker: { + enabled: resetMarkerOptions.enabled, + states: { + normal: { + opacity: resetMarkerOptions.states && + resetMarkerOptions.states.normal && + resetMarkerOptions.states.normal.opacity + } + } + } + }); + } + /** + * @private + */ + function forceZeroOpacityMarkerOptions(options) { + merge(true, options, { + marker: { + enabled: true, + states: { + normal: { + opacity: 0 + } + } + } + }); + } + /** + * @private + */ + function getPointMarkerOpacity(pointOptions) { + return pointOptions.marker.states && + pointOptions.marker.states.normal && + pointOptions.marker.states.normal.opacity || 1; + } + /** + * @private + */ + function forceDisplayPointMarker(pointOptions) { + merge(true, pointOptions.marker, { + states: { + normal: { + opacity: getPointMarkerOpacity(pointOptions) + } + } + }); + } + /** + * @private + */ + function handleForcePointMarkers(points) { + var i = points.length; + while (i--) { + var pointOptions = points[i].options; + if (pointOptions.marker) { + if (pointOptions.marker.enabled) { + forceDisplayPointMarker(pointOptions); + } + else { + forceZeroOpacityMarkerOptions(pointOptions); + } + } + } + } + /** + * @private + */ + function addForceMarkersEvents() { + /** + * Keep track of forcing markers. + * @private + */ + addEvent(H.Series, 'render', function () { + var series = this, options = series.options; + if (shouldForceMarkers(series)) { + if (options.marker && options.marker.enabled === false) { + series.a11yMarkersForced = true; + forceZeroOpacityMarkerOptions(series.options); + } + if (series._hasPointMarkers && series.points && series.points.length) { + handleForcePointMarkers(series.points); + } + } + else if (series.a11yMarkersForced && series.resetMarkerOptions) { + delete series.a11yMarkersForced; + unforceMarkerOptions(series); + } + }); + /** + * Keep track of options to reset markers to if no longer forced. + * @private + */ + addEvent(H.Series, 'afterSetOptions', function (e) { + this.resetA11yMarkerOptions = merge(e.options.marker || {}, this.userOptions.marker || {}); + }); + } + + return addForceMarkersEvents; + }); + _registerModule(_modules, 'modules/accessibility/components/SeriesComponent/SeriesComponent.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/AccessibilityComponent.js'], _modules['modules/accessibility/components/SeriesComponent/SeriesKeyboardNavigation.js'], _modules['modules/accessibility/components/SeriesComponent/NewDataAnnouncer.js'], _modules['modules/accessibility/components/SeriesComponent/forcedMarkers.js'], _modules['modules/accessibility/utils/chartUtilities.js'], _modules['modules/accessibility/components/SeriesComponent/SeriesDescriber.js'], _modules['parts/Tooltip.js']], function (H, U, AccessibilityComponent, SeriesKeyboardNavigation, NewDataAnnouncer, addForceMarkersEvents, ChartUtilities, SeriesDescriber, Tooltip) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Accessibility component for series and points. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend; + var hideSeriesFromAT = ChartUtilities.hideSeriesFromAT; + var describeSeries = SeriesDescriber.describeSeries; + // Expose functionality to users + H.SeriesAccessibilityDescriber = SeriesDescriber; + // Handle forcing markers + addForceMarkersEvents(); + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The SeriesComponent class + * + * @private + * @class + * @name Highcharts.SeriesComponent + */ + var SeriesComponent = function () { }; + SeriesComponent.prototype = new AccessibilityComponent(); + extend(SeriesComponent.prototype, /** @lends Highcharts.SeriesComponent */ { + /** + * Init the component. + */ + init: function () { + this.newDataAnnouncer = new NewDataAnnouncer(this.chart); + this.newDataAnnouncer.init(); + this.keyboardNavigation = new SeriesKeyboardNavigation(this.chart, this.keyCodes); + this.keyboardNavigation.init(); + this.hideTooltipFromATWhenShown(); + this.hideSeriesLabelsFromATWhenShown(); + }, + /** + * @private + */ + hideTooltipFromATWhenShown: function () { + var component = this; + this.addEvent(Tooltip, 'refresh', function () { + if (this.chart === component.chart && + this.label && + this.label.element) { + this.label.element.setAttribute('aria-hidden', true); + } + }); + }, + /** + * @private + */ + hideSeriesLabelsFromATWhenShown: function () { + this.addEvent(this.chart, 'afterDrawSeriesLabels', function () { + this.series.forEach(function (series) { + if (series.labelBySeries) { + series.labelBySeries.attr('aria-hidden', true); + } + }); + }); + }, + /** + * Called on chart render. It is necessary to do this for render in case + * markers change on zoom/pixel density. + */ + onChartRender: function () { + var chart = this.chart; + chart.series.forEach(function (series) { + var shouldDescribeSeries = (series.options.accessibility && + series.options.accessibility.enabled) !== false && + series.visible; + if (shouldDescribeSeries) { + describeSeries(series); + } + else { + hideSeriesFromAT(series); + } + }); + }, + /** + * Get keyboard navigation handler for this component. + * @return {Highcharts.KeyboardNavigationHandler} + */ + getKeyboardNavigation: function () { + return this.keyboardNavigation.getKeyboardNavigationHandler(); + }, + /** + * Remove traces + */ + destroy: function () { + this.newDataAnnouncer.destroy(); + this.keyboardNavigation.destroy(); + } + }); + + return SeriesComponent; + }); + _registerModule(_modules, 'modules/accessibility/components/ZoomComponent.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/AccessibilityComponent.js'], _modules['modules/accessibility/KeyboardNavigationHandler.js'], _modules['modules/accessibility/utils/chartUtilities.js'], _modules['modules/accessibility/utils/htmlUtilities.js']], function (H, U, AccessibilityComponent, KeyboardNavigationHandler, ChartUtilities, HTMLUtilities) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Accessibility component for chart zoom. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend, pick = U.pick; + var unhideChartElementFromAT = ChartUtilities.unhideChartElementFromAT; + var setElAttrs = HTMLUtilities.setElAttrs, removeElement = HTMLUtilities.removeElement; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * @private + */ + function chartHasMapZoom(chart) { + return !!(chart.mapZoom && + chart.mapNavButtons && + chart.mapNavButtons.length); + } + /** + * Pan along axis in a direction (1 or -1), optionally with a defined + * granularity (number of steps it takes to walk across current view) + * + * @private + * @function Highcharts.Axis#panStep + * + * @param {number} direction + * @param {number} [granularity] + */ + H.Axis.prototype.panStep = function (direction, granularity) { + var gran = granularity || 3, extremes = this.getExtremes(), step = (extremes.max - extremes.min) / gran * direction, newMax = extremes.max + step, newMin = extremes.min + step, size = newMax - newMin; + if (direction < 0 && newMin < extremes.dataMin) { + newMin = extremes.dataMin; + newMax = newMin + size; + } + else if (direction > 0 && newMax > extremes.dataMax) { + newMax = extremes.dataMax; + newMin = newMax - size; + } + this.setExtremes(newMin, newMax); + }; + /** + * The ZoomComponent class + * + * @private + * @class + * @name Highcharts.ZoomComponent + */ + var ZoomComponent = function () { }; + ZoomComponent.prototype = new AccessibilityComponent(); + extend(ZoomComponent.prototype, /** @lends Highcharts.ZoomComponent */ { + /** + * Initialize the component + */ + init: function () { + var component = this, chart = this.chart; + [ + 'afterShowResetZoom', 'afterDrilldown', 'drillupall' + ].forEach(function (eventType) { + component.addEvent(chart, eventType, function () { + component.updateProxyOverlays(); + }); + }); + }, + /** + * Called when chart is updated + */ + onChartUpdate: function () { + var chart = this.chart, component = this; + // Make map zoom buttons accessible + if (chart.mapNavButtons) { + chart.mapNavButtons.forEach(function (button, i) { + unhideChartElementFromAT(chart, button.element); + component.setMapNavButtonAttrs(button.element, 'accessibility.zoom.mapZoom' + (i ? 'Out' : 'In')); + }); + } + }, + /** + * @private + * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} button + * @param {string} labelFormatKey + */ + setMapNavButtonAttrs: function (button, labelFormatKey) { + var chart = this.chart, label = chart.langFormat(labelFormatKey, { chart: chart }); + setElAttrs(button, { + tabindex: -1, + role: 'button', + 'aria-label': label + }); + }, + /** + * Update the proxy overlays on every new render to ensure positions are + * correct. + */ + onChartRender: function () { + this.updateProxyOverlays(); + }, + /** + * Update proxy overlays, recreating the buttons. + */ + updateProxyOverlays: function () { + var chart = this.chart; + // Always start with a clean slate + removeElement(this.drillUpProxyGroup); + removeElement(this.resetZoomProxyGroup); + if (chart.resetZoomButton) { + this.recreateProxyButtonAndGroup(chart.resetZoomButton, 'resetZoomProxyButton', 'resetZoomProxyGroup', chart.langFormat('accessibility.zoom.resetZoomButton', { chart: chart })); + } + if (chart.drillUpButton) { + this.recreateProxyButtonAndGroup(chart.drillUpButton, 'drillUpProxyButton', 'drillUpProxyGroup', chart.langFormat('accessibility.drillUpButton', { + chart: chart, + buttonText: chart.getDrilldownBackText() + })); + } + }, + /** + * @private + * @param {Highcharts.SVGElement} buttonEl + * @param {string} buttonProp + * @param {string} groupProp + * @param {string} label + */ + recreateProxyButtonAndGroup: function (buttonEl, buttonProp, groupProp, label) { + removeElement(this[groupProp]); + this[groupProp] = this.addProxyGroup(); + this[buttonProp] = this.createProxyButton(buttonEl, this[groupProp], { 'aria-label': label, tabindex: -1 }); + }, + /** + * Get keyboard navigation handler for map zoom. + * @private + * @return {Highcharts.KeyboardNavigationHandler} The module object + */ + getMapZoomNavigation: function () { + var keys = this.keyCodes, chart = this.chart, component = this; + return new KeyboardNavigationHandler(chart, { + keyCodeMap: [ + [ + [keys.up, keys.down, keys.left, keys.right], + function (keyCode) { + return component.onMapKbdArrow(this, keyCode); + } + ], + [ + [keys.tab], + function (_keyCode, e) { + return component.onMapKbdTab(this, e); + } + ], + [ + [keys.space, keys.enter], + function () { + return component.onMapKbdClick(this); + } + ] + ], + validate: function () { + return chartHasMapZoom(chart); + }, + init: function (direction) { + return component.onMapNavInit(direction); + } + }); + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler + * @param {number} keyCode + * @return {number} Response code + */ + onMapKbdArrow: function (keyboardNavigationHandler, keyCode) { + var keys = this.keyCodes, panAxis = (keyCode === keys.up || keyCode === keys.down) ? + 'yAxis' : 'xAxis', stepDirection = (keyCode === keys.left || keyCode === keys.up) ? + -1 : 1; + this.chart[panAxis][0].panStep(stepDirection); + return keyboardNavigationHandler.response.success; + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler + * @param {global.KeyboardEvent} event + * @return {number} Response code + */ + onMapKbdTab: function (keyboardNavigationHandler, event) { + var button, chart = this.chart, response = keyboardNavigationHandler.response, isBackwards = event.shiftKey, isMoveOutOfRange = isBackwards && !this.focusedMapNavButtonIx || + !isBackwards && this.focusedMapNavButtonIx; + // Deselect old + chart.mapNavButtons[this.focusedMapNavButtonIx].setState(0); + if (isMoveOutOfRange) { + chart.mapZoom(); // Reset zoom + return response[isBackwards ? 'prev' : 'next']; + } + // Select other button + this.focusedMapNavButtonIx += isBackwards ? -1 : 1; + button = chart.mapNavButtons[this.focusedMapNavButtonIx]; + chart.setFocusToElement(button.box, button.element); + button.setState(2); + return response.success; + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler + * @return {number} Response code + */ + onMapKbdClick: function (keyboardNavigationHandler) { + this.fakeClickEvent(this.chart.mapNavButtons[this.focusedMapNavButtonIx] + .element); + return keyboardNavigationHandler.response.success; + }, + /** + * @private + * @param {number} direction + */ + onMapNavInit: function (direction) { + var chart = this.chart, zoomIn = chart.mapNavButtons[0], zoomOut = chart.mapNavButtons[1], initialButton = direction > 0 ? zoomIn : zoomOut; + chart.setFocusToElement(initialButton.box, initialButton.element); + initialButton.setState(2); + this.focusedMapNavButtonIx = direction > 0 ? 0 : 1; + }, + /** + * Get keyboard navigation handler for a simple chart button. Provide the + * button reference for the chart, and a function to call on click. + * + * @private + * @param {string} buttonProp The property on chart referencing the button. + * @return {Highcharts.KeyboardNavigationHandler} The module object + */ + simpleButtonNavigation: function (buttonProp, proxyProp, onClick) { + var keys = this.keyCodes, component = this, chart = this.chart; + return new KeyboardNavigationHandler(chart, { + keyCodeMap: [ + [ + [keys.tab, keys.up, keys.down, keys.left, keys.right], + function (keyCode, e) { + var isBackwards = keyCode === keys.tab && e.shiftKey || + keyCode === keys.left || keyCode === keys.up; + // Arrow/tab => just move + return this.response[isBackwards ? 'prev' : 'next']; + } + ], + [ + [keys.space, keys.enter], + function () { + var res = onClick(this, chart); + return pick(res, this.response.success); + } + ] + ], + validate: function () { + var hasButton = (chart[buttonProp] && + chart[buttonProp].box && + component[proxyProp]); + return hasButton; + }, + init: function () { + chart.setFocusToElement(chart[buttonProp].box, component[proxyProp]); + } + }); + }, + /** + * Get keyboard navigation handlers for this component. + * @return {Array} + * List of module objects + */ + getKeyboardNavigation: function () { + return [ + this.simpleButtonNavigation('resetZoomButton', 'resetZoomProxyButton', function (_handler, chart) { + chart.zoomOut(); + }), + this.simpleButtonNavigation('drillUpButton', 'drillUpProxyButton', function (handler, chart) { + chart.drillUp(); + return handler.response.prev; + }), + this.getMapZoomNavigation() + ]; + } + }); + + return ZoomComponent; + }); + _registerModule(_modules, 'modules/accessibility/components/RangeSelectorComponent.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/AccessibilityComponent.js'], _modules['modules/accessibility/KeyboardNavigationHandler.js'], _modules['modules/accessibility/utils/chartUtilities.js'], _modules['modules/accessibility/utils/htmlUtilities.js']], function (H, U, AccessibilityComponent, KeyboardNavigationHandler, ChartUtilities, HTMLUtilities) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Accessibility component for the range selector. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend; + var unhideChartElementFromAT = ChartUtilities.unhideChartElementFromAT; + var setElAttrs = HTMLUtilities.setElAttrs; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * @private + */ + function shouldRunInputNavigation(chart) { + var inputVisible = (chart.rangeSelector && + chart.rangeSelector.inputGroup && + chart.rangeSelector.inputGroup.element + .getAttribute('visibility') !== 'hidden'); + return (inputVisible && + chart.options.rangeSelector.inputEnabled !== false && + chart.rangeSelector.minInput && + chart.rangeSelector.maxInput); + } + /** + * Highlight range selector button by index. + * + * @private + * @function Highcharts.Chart#highlightRangeSelectorButton + * + * @param {number} ix + * + * @return {boolean} + */ + H.Chart.prototype.highlightRangeSelectorButton = function (ix) { + var buttons = this.rangeSelector.buttons, curSelectedIx = this.highlightedRangeSelectorItemIx; + // Deselect old + if (typeof curSelectedIx !== 'undefined' && buttons[curSelectedIx]) { + buttons[curSelectedIx].setState(this.oldRangeSelectorItemState || 0); + } + // Select new + this.highlightedRangeSelectorItemIx = ix; + if (buttons[ix]) { + this.setFocusToElement(buttons[ix].box, buttons[ix].element); + this.oldRangeSelectorItemState = buttons[ix].state; + buttons[ix].setState(2); + return true; + } + return false; + }; + /** + * The RangeSelectorComponent class + * + * @private + * @class + * @name Highcharts.RangeSelectorComponent + */ + var RangeSelectorComponent = function () { }; + RangeSelectorComponent.prototype = new AccessibilityComponent(); + extend(RangeSelectorComponent.prototype, /** @lends Highcharts.RangeSelectorComponent */ { + /** + * Called on first render/updates to the chart, including options changes. + */ + onChartUpdate: function () { + var chart = this.chart, component = this, rangeSelector = chart.rangeSelector; + if (!rangeSelector) { + return; + } + if (rangeSelector.buttons && rangeSelector.buttons.length) { + rangeSelector.buttons.forEach(function (button) { + unhideChartElementFromAT(chart, button.element); + component.setRangeButtonAttrs(button); + }); + } + // Make sure input boxes are accessible and focusable + if (rangeSelector.maxInput && rangeSelector.minInput) { + ['minInput', 'maxInput'].forEach(function (key, i) { + var input = rangeSelector[key]; + if (input) { + unhideChartElementFromAT(chart, input); + component.setRangeInputAttrs(input, 'accessibility.rangeSelector.' + (i ? 'max' : 'min') + + 'InputLabel'); + } + }); + } + }, + /** + * @private + * @param {Highcharts.SVGElement} button + */ + setRangeButtonAttrs: function (button) { + var chart = this.chart, label = chart.langFormat('accessibility.rangeSelector.buttonText', { + chart: chart, + buttonText: button.text && button.text.textStr + }); + setElAttrs(button.element, { + tabindex: -1, + role: 'button', + 'aria-label': label + }); + }, + /** + * @private + */ + setRangeInputAttrs: function (input, langKey) { + var chart = this.chart; + setElAttrs(input, { + tabindex: -1, + role: 'textbox', + 'aria-label': chart.langFormat(langKey, { chart: chart }) + }); + }, + /** + * Get navigation for the range selector buttons. + * @private + * @return {Highcharts.KeyboardNavigationHandler} The module object. + */ + getRangeSelectorButtonNavigation: function () { + var chart = this.chart, keys = this.keyCodes, component = this; + return new KeyboardNavigationHandler(chart, { + keyCodeMap: [ + [ + [keys.left, keys.right, keys.up, keys.down], + function (keyCode) { + return component.onButtonNavKbdArrowKey(this, keyCode); + } + ], + [ + [keys.enter, keys.space], + function () { + return component.onButtonNavKbdClick(this); + } + ] + ], + validate: function () { + var hasRangeSelector = chart.rangeSelector && + chart.rangeSelector.buttons && + chart.rangeSelector.buttons.length; + return hasRangeSelector; + }, + init: function (direction) { + var lastButtonIx = (chart.rangeSelector.buttons.length - 1); + chart.highlightRangeSelectorButton(direction > 0 ? 0 : lastButtonIx); + } + }); + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler + * @param {number} keyCode + * @return {number} Response code + */ + onButtonNavKbdArrowKey: function (keyboardNavigationHandler, keyCode) { + var response = keyboardNavigationHandler.response, keys = this.keyCodes, chart = this.chart, wrapAround = chart.options.accessibility + .keyboardNavigation.wrapAround, direction = (keyCode === keys.left || keyCode === keys.up) ? -1 : 1, didHighlight = chart.highlightRangeSelectorButton(chart.highlightedRangeSelectorItemIx + direction); + if (!didHighlight) { + if (wrapAround) { + keyboardNavigationHandler.init(direction); + return response.success; + } + return response[direction > 0 ? 'next' : 'prev']; + } + return response.success; + }, + /** + * @private + */ + onButtonNavKbdClick: function (keyboardNavigationHandler) { + var response = keyboardNavigationHandler.response, chart = this.chart, wasDisabled = chart.oldRangeSelectorItemState === 3; + if (!wasDisabled) { + this.fakeClickEvent(chart.rangeSelector.buttons[chart.highlightedRangeSelectorItemIx].element); + } + return response.success; + }, + /** + * Get navigation for the range selector input boxes. + * @private + * @return {Highcharts.KeyboardNavigationHandler} + * The module object. + */ + getRangeSelectorInputNavigation: function () { + var chart = this.chart, keys = this.keyCodes, component = this; + return new KeyboardNavigationHandler(chart, { + keyCodeMap: [ + [ + [ + keys.tab, keys.up, keys.down + ], function (keyCode, e) { + var direction = (keyCode === keys.tab && e.shiftKey || + keyCode === keys.up) ? -1 : 1; + return component.onInputKbdMove(this, direction); + } + ] + ], + validate: function () { + return shouldRunInputNavigation(chart); + }, + init: function (direction) { + component.onInputNavInit(direction); + }, + terminate: function () { + component.onInputNavTerminate(); + } + }); + }, + /** + * @private + * @param {Highcharts.KeyboardNavigationHandler} keyboardNavigationHandler + * @param {number} direction + * @return {number} Response code + */ + onInputKbdMove: function (keyboardNavigationHandler, direction) { + var chart = this.chart, response = keyboardNavigationHandler.response, newIx = chart.highlightedInputRangeIx = + chart.highlightedInputRangeIx + direction, newIxOutOfRange = newIx > 1 || newIx < 0; + if (newIxOutOfRange) { + return response[direction > 0 ? 'next' : 'prev']; + } + chart.rangeSelector[newIx ? 'maxInput' : 'minInput'].focus(); + return response.success; + }, + /** + * @private + * @param {number} direction + */ + onInputNavInit: function (direction) { + var chart = this.chart, buttonIxToHighlight = direction > 0 ? 0 : 1; + chart.highlightedInputRangeIx = buttonIxToHighlight; + chart.rangeSelector[buttonIxToHighlight ? 'maxInput' : 'minInput'].focus(); + }, + /** + * @private + */ + onInputNavTerminate: function () { + var rangeSel = (this.chart.rangeSelector || {}); + if (rangeSel.maxInput) { + rangeSel.hideInput('max'); + } + if (rangeSel.minInput) { + rangeSel.hideInput('min'); + } + }, + /** + * Get keyboard navigation handlers for this component. + * @return {Array} + * List of module objects. + */ + getKeyboardNavigation: function () { + return [ + this.getRangeSelectorButtonNavigation(), + this.getRangeSelectorInputNavigation() + ]; + } + }); + + return RangeSelectorComponent; + }); + _registerModule(_modules, 'modules/accessibility/components/InfoRegionsComponent.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/AccessibilityComponent.js'], _modules['modules/accessibility/utils/Announcer.js'], _modules['modules/accessibility/components/AnnotationsA11y.js'], _modules['modules/accessibility/utils/chartUtilities.js'], _modules['modules/accessibility/utils/htmlUtilities.js']], function (H, U, AccessibilityComponent, Announcer, AnnotationsA11y, ChartUtilities, HTMLUtilities) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Accessibility component for chart info region and table. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var doc = H.win.document; + var extend = U.extend, format = U.format, pick = U.pick; + var getAnnotationsInfoHTML = AnnotationsA11y.getAnnotationsInfoHTML; + var unhideChartElementFromAT = ChartUtilities.unhideChartElementFromAT, getChartTitle = ChartUtilities.getChartTitle, getAxisDescription = ChartUtilities.getAxisDescription; + var addClass = HTMLUtilities.addClass, setElAttrs = HTMLUtilities.setElAttrs, escapeStringForHTML = HTMLUtilities.escapeStringForHTML, stripHTMLTagsFromString = HTMLUtilities.stripHTMLTagsFromString, getElement = HTMLUtilities.getElement, visuallyHideElement = HTMLUtilities.visuallyHideElement; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * @private + */ + function getTypeDescForMapChart(chart, formatContext) { + return formatContext.mapTitle ? + chart.langFormat('accessibility.chartTypes.mapTypeDescription', formatContext) : + chart.langFormat('accessibility.chartTypes.unknownMap', formatContext); + } + /** + * @private + */ + function getTypeDescForCombinationChart(chart, formatContext) { + return chart.langFormat('accessibility.chartTypes.combinationChart', formatContext); + } + /** + * @private + */ + function getTypeDescForEmptyChart(chart, formatContext) { + return chart.langFormat('accessibility.chartTypes.emptyChart', formatContext); + } + /** + * @private + */ + function buildTypeDescriptionFromSeries(chart, types, context) { + var firstType = types[0], typeExplaination = chart.langFormat('accessibility.seriesTypeDescriptions.' + firstType, context), multi = chart.series && chart.series.length < 2 ? 'Single' : 'Multiple'; + return (chart.langFormat('accessibility.chartTypes.' + firstType + multi, context) || + chart.langFormat('accessibility.chartTypes.default' + multi, context)) + (typeExplaination ? ' ' + typeExplaination : ''); + } + /** + * @private + */ + function getTableSummary(chart) { + return chart.langFormat('accessibility.table.tableSummary', { chart: chart }); + } + /** + * @private + */ + function stripEmptyHTMLTags(str) { + return str.replace(/<(\w+)[^>]*?>\s*<\/\1>/g, ''); + } + /** + * @private + */ + function enableSimpleHTML(str) { + return str + .replace(/<(h[1-7]|p|div|ul|ol|li)>/g, '<$1>') + .replace(/</(h[1-7]|p|div|ul|ol|li|a|button)>/g, '') + .replace(/<(div|a|button) id="([a-zA-Z\-0-9#]*?)">/g, '<$1 id="$2">'); + } + /** + * @private + */ + function stringToSimpleHTML(str) { + return stripEmptyHTMLTags(enableSimpleHTML(escapeStringForHTML(str))); + } + /** + * Return simplified explaination of chart type. Some types will not be familiar + * to most users, but in those cases we try to add an explaination of the type. + * + * @private + * @function Highcharts.Chart#getTypeDescription + * @param {Array} types The series types in this chart. + * @return {string} The text description of the chart type. + */ + H.Chart.prototype.getTypeDescription = function (types) { + var firstType = types[0], firstSeries = this.series && this.series[0] || {}, formatContext = { + numSeries: this.series.length, + numPoints: firstSeries.points && firstSeries.points.length, + chart: this, + mapTitle: firstSeries.mapTitle + }; + if (!firstType) { + return getTypeDescForEmptyChart(this, formatContext); + } + if (firstType === 'map') { + return getTypeDescForMapChart(this, formatContext); + } + if (this.types.length > 1) { + return getTypeDescForCombinationChart(this, formatContext); + } + return buildTypeDescriptionFromSeries(this, types, formatContext); + }; + /** + * The InfoRegionsComponent class + * + * @private + * @class + * @name Highcharts.InfoRegionsComponent + */ + var InfoRegionsComponent = function () { }; + InfoRegionsComponent.prototype = new AccessibilityComponent(); + extend(InfoRegionsComponent.prototype, /** @lends Highcharts.InfoRegionsComponent */ { + /** + * Init the component + * @private + */ + init: function () { + var chart = this.chart; + var component = this; + this.initRegionsDefinitions(); + this.addEvent(chart, 'afterGetTable', function (e) { + component.onDataTableCreated(e); + }); + this.addEvent(chart, 'afterViewData', function (tableDiv) { + component.dataTableDiv = tableDiv; + // Use small delay to give browsers & AT time to register new table + setTimeout(function () { + component.focusDataTable(); + }, 300); + }); + this.announcer = new Announcer(chart, 'assertive'); + }, + /** + * @private + */ + initRegionsDefinitions: function () { + var component = this; + this.screenReaderSections = { + before: { + element: null, + buildContent: function (chart) { + var formatter = chart.options.accessibility + .screenReaderSection.beforeChartFormatter; + return formatter ? formatter(chart) : + component.defaultBeforeChartFormatter(chart); + }, + insertIntoDOM: function (el, chart) { + chart.renderTo.insertBefore(el, chart.renderTo.firstChild); + }, + afterInserted: function () { + if (typeof component.sonifyButtonId !== 'undefined') { + component.initSonifyButton(component.sonifyButtonId); + } + if (typeof component.dataTableButtonId !== 'undefined') { + component.initDataTableButton(component.dataTableButtonId); + } + } + }, + after: { + element: null, + buildContent: function (chart) { + var formatter = chart.options.accessibility.screenReaderSection + .afterChartFormatter; + return formatter ? formatter(chart) : + component.defaultAfterChartFormatter(); + }, + insertIntoDOM: function (el, chart) { + chart.renderTo.insertBefore(el, chart.container.nextSibling); + } + } + }; + }, + /** + * Called on chart render. Have to update the sections on render, in order + * to get a11y info from series. + */ + onChartRender: function () { + var component = this; + this.linkedDescriptionElement = this.getLinkedDescriptionElement(); + this.setLinkedDescriptionAttrs(); + Object.keys(this.screenReaderSections).forEach(function (regionKey) { + component.updateScreenReaderSection(regionKey); + }); + }, + /** + * @private + */ + getLinkedDescriptionElement: function () { + var chartOptions = this.chart.options, linkedDescOption = chartOptions.accessibility.linkedDescription; + if (!linkedDescOption) { + return; + } + if (typeof linkedDescOption !== 'string') { + return linkedDescOption; + } + var query = format(linkedDescOption, this.chart), queryMatch = doc.querySelectorAll(query); + if (queryMatch.length === 1) { + return queryMatch[0]; + } + }, + /** + * @private + */ + setLinkedDescriptionAttrs: function () { + var el = this.linkedDescriptionElement; + if (el) { + el.setAttribute('aria-hidden', 'true'); + addClass(el, 'highcharts-linked-description'); + } + }, + /** + * @private + * @param {string} regionKey The name/key of the region to update + */ + updateScreenReaderSection: function (regionKey) { + var chart = this.chart, region = this.screenReaderSections[regionKey], content = region.buildContent(chart), sectionDiv = region.element = (region.element || this.createElement('div')), hiddenDiv = (sectionDiv.firstChild || this.createElement('div')); + this.setScreenReaderSectionAttribs(sectionDiv, regionKey); + hiddenDiv.innerHTML = content; + sectionDiv.appendChild(hiddenDiv); + region.insertIntoDOM(sectionDiv, chart); + visuallyHideElement(hiddenDiv); + unhideChartElementFromAT(chart, hiddenDiv); + if (region.afterInserted) { + region.afterInserted(); + } + }, + /** + * @private + * @param {Highcharts.HTMLDOMElement} sectionDiv The section element + * @param {string} regionKey Name/key of the region we are setting attrs for + */ + setScreenReaderSectionAttribs: function (sectionDiv, regionKey) { + var labelLangKey = ('accessibility.screenReaderSection.' + regionKey + 'RegionLabel'), chart = this.chart, labelText = chart.langFormat(labelLangKey, { chart: chart }), sectionId = 'highcharts-screen-reader-region-' + regionKey + '-' + + chart.index; + setElAttrs(sectionDiv, { + id: sectionId, + 'aria-label': labelText + }); + // Sections are wrapped to be positioned relatively to chart in case + // elements inside are tabbed to. + sectionDiv.style.position = 'relative'; + if (chart.options.accessibility.landmarkVerbosity === 'all' && + labelText) { + sectionDiv.setAttribute('role', 'region'); + } + }, + /** + * @private + * @return {string} + */ + defaultBeforeChartFormatter: function () { + var _a; + var chart = this.chart, format = chart.options.accessibility + .screenReaderSection.beforeChartFormat, axesDesc = this.getAxesDescription(), shouldHaveSonifyBtn = chart.sonify && ((_a = chart.options.sonification) === null || _a === void 0 ? void 0 : _a.enabled), sonifyButtonId = 'highcharts-a11y-sonify-data-btn-' + + chart.index, dataTableButtonId = 'hc-linkto-highcharts-data-table-' + + chart.index, annotationsList = getAnnotationsInfoHTML(chart), annotationsTitleStr = chart.langFormat('accessibility.screenReaderSection.annotations.heading', { chart: chart }), context = { + chartTitle: getChartTitle(chart), + typeDescription: this.getTypeDescriptionText(), + chartSubtitle: this.getSubtitleText(), + chartLongdesc: this.getLongdescText(), + xAxisDescription: axesDesc.xAxis, + yAxisDescription: axesDesc.yAxis, + playAsSoundButton: shouldHaveSonifyBtn ? + this.getSonifyButtonText(sonifyButtonId) : '', + viewTableButton: chart.getCSV ? + this.getDataTableButtonText(dataTableButtonId) : '', + annotationsTitle: annotationsList ? annotationsTitleStr : '', + annotationsList: annotationsList + }, formattedString = H.i18nFormat(format, context, chart); + this.dataTableButtonId = dataTableButtonId; + this.sonifyButtonId = sonifyButtonId; + return stringToSimpleHTML(formattedString); + }, + /** + * @private + * @return {string} + */ + defaultAfterChartFormatter: function () { + var chart = this.chart, format = chart.options.accessibility + .screenReaderSection.afterChartFormat, context = { + endOfChartMarker: this.getEndOfChartMarkerText() + }, formattedString = H.i18nFormat(format, context, chart); + return stringToSimpleHTML(formattedString); + }, + /** + * @private + * @return {string} + */ + getLinkedDescription: function () { + var el = this.linkedDescriptionElement, content = el && el.innerHTML || ''; + return stripHTMLTagsFromString(content); + }, + /** + * @private + * @return {string} + */ + getLongdescText: function () { + var chartOptions = this.chart.options, captionOptions = chartOptions.caption, captionText = captionOptions && captionOptions.text, linkedDescription = this.getLinkedDescription(); + return (chartOptions.accessibility.description || + linkedDescription || + captionText || + ''); + }, + /** + * @private + * @return {string} + */ + getTypeDescriptionText: function () { + var chart = this.chart; + return chart.types ? + chart.options.accessibility.typeDescription || + chart.getTypeDescription(chart.types) : ''; + }, + /** + * @private + * @param {string} buttonId + * @return {string} + */ + getDataTableButtonText: function (buttonId) { + var chart = this.chart, buttonText = chart.langFormat('accessibility.table.viewAsDataTableButtonText', { chart: chart, chartTitle: getChartTitle(chart) }); + return '' + buttonText + ''; + }, + /** + * @private + * @param {string} buttonId + * @return {string} + */ + getSonifyButtonText: function (buttonId) { + var _a; + var chart = this.chart; + if (((_a = chart.options.sonification) === null || _a === void 0 ? void 0 : _a.enabled) === false) { + return ''; + } + var buttonText = chart.langFormat('accessibility.sonification.playAsSoundButtonText', { chart: chart, chartTitle: getChartTitle(chart) }); + return ''; + }, + /** + * @private + * @return {string} + */ + getSubtitleText: function () { + var subtitle = (this.chart.options.subtitle); + return stripHTMLTagsFromString(subtitle && subtitle.text || ''); + }, + /** + * @private + * @return {string} + */ + getEndOfChartMarkerText: function () { + var chart = this.chart, markerText = chart.langFormat('accessibility.screenReaderSection.endOfChartMarker', { chart: chart }), id = 'highcharts-end-of-chart-marker-' + chart.index; + return '
    ' + markerText + '
    '; + }, + /** + * @private + * @param {Highcharts.Dictionary} e + */ + onDataTableCreated: function (e) { + var chart = this.chart; + if (chart.options.accessibility.enabled) { + if (this.viewDataTableButton) { + this.viewDataTableButton.setAttribute('aria-expanded', 'true'); + } + e.html = e.html.replace('
    } + */ + getAxesDescription: function () { + var chart = this.chart, shouldDescribeColl = function (collectionKey, defaultCondition) { + var axes = chart[collectionKey]; + return axes.length > 1 || axes[0] && + pick(axes[0].options.accessibility && + axes[0].options.accessibility.enabled, defaultCondition); + }, hasNoMap = !!chart.types && chart.types.indexOf('map') < 0, hasCartesian = !!chart.hasCartesianSeries, showXAxes = shouldDescribeColl('xAxis', !chart.angular && hasCartesian && hasNoMap), showYAxes = shouldDescribeColl('yAxis', hasCartesian && hasNoMap), desc = {}; + if (showXAxes) { + desc.xAxis = this.getAxisDescriptionText('xAxis'); + } + if (showYAxes) { + desc.yAxis = this.getAxisDescriptionText('yAxis'); + } + return desc; + }, + /** + * @private + * @param {string} collectionKey + * @return {string} + */ + getAxisDescriptionText: function (collectionKey) { + var component = this, chart = this.chart, axes = chart[collectionKey]; + return chart.langFormat('accessibility.axis.' + collectionKey + 'Description' + (axes.length > 1 ? 'Plural' : 'Singular'), { + chart: chart, + names: axes.map(function (axis) { + return getAxisDescription(axis); + }), + ranges: axes.map(function (axis) { + return component.getAxisRangeDescription(axis); + }), + numAxes: axes.length + }); + }, + /** + * Return string with text description of the axis range. + * @private + * @param {Highcharts.Axis} axis The axis to get range desc of. + * @return {string} A string with the range description for the axis. + */ + getAxisRangeDescription: function (axis) { + var axisOptions = axis.options || {}; + // Handle overridden range description + if (axisOptions.accessibility && + typeof axisOptions.accessibility.rangeDescription !== 'undefined') { + return axisOptions.accessibility.rangeDescription; + } + // Handle category axes + if (axis.categories) { + return this.getCategoryAxisRangeDesc(axis); + } + // Use time range, not from-to? + if (axis.dateTime && (axis.min === 0 || axis.dataMin === 0)) { + return this.getAxisTimeLengthDesc(axis); + } + // Just use from and to. + // We have the range and the unit to use, find the desc format + return this.getAxisFromToDescription(axis); + }, + /** + * @private + * @param {Highcharts.Axis} axis + * @return {string} + */ + getCategoryAxisRangeDesc: function (axis) { + var chart = this.chart; + if (axis.dataMax && axis.dataMin) { + return chart.langFormat('accessibility.axis.rangeCategories', { + chart: chart, + axis: axis, + numCategories: axis.dataMax - axis.dataMin + 1 + }); + } + return ''; + }, + /** + * @private + * @param {Highcharts.Axis} axis + * @return {string} + */ + getAxisTimeLengthDesc: function (axis) { + var chart = this.chart, range = {}, rangeUnit = 'Seconds'; + range.Seconds = ((axis.max || 0) - (axis.min || 0)) / 1000; + range.Minutes = range.Seconds / 60; + range.Hours = range.Minutes / 60; + range.Days = range.Hours / 24; + ['Minutes', 'Hours', 'Days'].forEach(function (unit) { + if (range[unit] > 2) { + rangeUnit = unit; + } + }); + var rangeValue = range[rangeUnit].toFixed(rangeUnit !== 'Seconds' && + rangeUnit !== 'Minutes' ? 1 : 0 // Use decimals for days/hours + ); + // We have the range and the unit to use, find the desc format + return chart.langFormat('accessibility.axis.timeRange' + rangeUnit, { + chart: chart, + axis: axis, + range: rangeValue.replace('.0', '') + }); + }, + /** + * @private + * @param {Highcharts.Axis} axis + * @return {string} + */ + getAxisFromToDescription: function (axis) { + var chart = this.chart, dateRangeFormat = chart.options.accessibility + .screenReaderSection.axisRangeDateFormat, format = function (axisKey) { + return axis.dateTime ? chart.time.dateFormat(dateRangeFormat, axis[axisKey]) : axis[axisKey]; + }; + return chart.langFormat('accessibility.axis.rangeFromTo', { + chart: chart, + axis: axis, + rangeFrom: format('min'), + rangeTo: format('max') + }); + }, + /** + * Remove component traces + */ + destroy: function () { + var _a; + (_a = this.announcer) === null || _a === void 0 ? void 0 : _a.destroy(); + } + }); + + return InfoRegionsComponent; + }); + _registerModule(_modules, 'modules/accessibility/components/ContainerComponent.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/accessibility/utils/htmlUtilities.js'], _modules['modules/accessibility/utils/chartUtilities.js'], _modules['modules/accessibility/AccessibilityComponent.js']], function (H, U, HTMLUtilities, ChartUtilities, AccessibilityComponent) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Accessibility component for chart container. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var doc = H.win.document; + var extend = U.extend; + var stripHTMLTags = HTMLUtilities.stripHTMLTagsFromString; + var unhideChartElementFromAT = ChartUtilities.unhideChartElementFromAT, getChartTitle = ChartUtilities.getChartTitle; + /* eslint-disable valid-jsdoc */ + /** + * The ContainerComponent class + * + * @private + * @class + * @name Highcharts.ContainerComponent + */ + var ContainerComponent = function () { }; + ContainerComponent.prototype = new AccessibilityComponent(); + extend(ContainerComponent.prototype, /** @lends Highcharts.ContainerComponent */ { + /** + * Called on first render/updates to the chart, including options changes. + */ + onChartUpdate: function () { + this.handleSVGTitleElement(); + this.setSVGContainerLabel(); + this.setGraphicContainerAttrs(); + this.setRenderToAttrs(); + this.makeCreditsAccessible(); + }, + /** + * @private + */ + handleSVGTitleElement: function () { + var chart = this.chart, titleId = 'highcharts-title-' + chart.index, titleContents = stripHTMLTags(chart.langFormat('accessibility.svgContainerTitle', { + chartTitle: getChartTitle(chart) + })); + if (titleContents.length) { + var titleElement = this.svgTitleElement = + this.svgTitleElement || doc.createElementNS('http://www.w3.org/2000/svg', 'title'); + titleElement.textContent = titleContents; + titleElement.id = titleId; + chart.renderTo.insertBefore(titleElement, chart.renderTo.firstChild); + } + }, + /** + * @private + */ + setSVGContainerLabel: function () { + var chart = this.chart, svgContainerLabel = stripHTMLTags(chart.langFormat('accessibility.svgContainerLabel', { + chartTitle: getChartTitle(chart) + })); + if (chart.renderer.box && svgContainerLabel.length) { + chart.renderer.box.setAttribute('aria-label', svgContainerLabel); + } + }, + /** + * @private + */ + setGraphicContainerAttrs: function () { + var chart = this.chart, label = chart.langFormat('accessibility.graphicContainerLabel', { + chartTitle: getChartTitle(chart) + }); + if (label.length) { + chart.container.setAttribute('aria-label', label); + } + }, + /** + * @private + */ + setRenderToAttrs: function () { + var chart = this.chart; + if (chart.options.accessibility.landmarkVerbosity !== 'disabled') { + chart.renderTo.setAttribute('role', 'region'); + } + else { + chart.renderTo.removeAttribute('role'); + } + chart.renderTo.setAttribute('aria-label', chart.langFormat('accessibility.chartContainerLabel', { + title: getChartTitle(chart), + chart: chart + })); + }, + /** + * @private + */ + makeCreditsAccessible: function () { + var chart = this.chart, credits = chart.credits; + if (credits) { + if (credits.textStr) { + credits.element.setAttribute('aria-label', stripHTMLTags(chart.langFormat('accessibility.credits', { creditsStr: credits.textStr }))); + } + unhideChartElementFromAT(chart, credits.element); + } + }, + /** + * Accessibility disabled/chart destroyed. + */ + destroy: function () { + this.chart.renderTo.setAttribute('aria-hidden', true); + } + }); + + return ContainerComponent; + }); + _registerModule(_modules, 'modules/accessibility/high-contrast-mode.js', [_modules['parts/Globals.js']], function (H) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Handling for Windows High Contrast Mode. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var isMS = H.isMS, win = H.win, doc = win.document; + var whcm = { + /** + * Detect WHCM in the browser. + * + * @function Highcharts#isHighContrastModeActive + * @private + * @return {boolean} Returns true if the browser is in High Contrast mode. + */ + isHighContrastModeActive: function () { + // Use media query on Edge, but not on IE + var isEdge = /(Edg)/.test(win.navigator.userAgent); + if (win.matchMedia && isEdge) { + return win.matchMedia('(-ms-high-contrast: active)').matches; + } + // Test BG image for IE + if (isMS && win.getComputedStyle) { + var testDiv = doc.createElement('div'); + testDiv.style.backgroundImage = 'url(#)'; + doc.body.appendChild(testDiv); + var bi = (testDiv.currentStyle || + win.getComputedStyle(testDiv)).backgroundImage; + doc.body.removeChild(testDiv); + return bi === 'none'; + } + // Not used for other browsers + return false; + }, + /** + * Force high contrast theme for the chart. The default theme is defined in + * a separate file. + * + * @function Highcharts#setHighContrastTheme + * @private + * @param {Highcharts.AccessibilityChart} chart The chart to set the theme of. + * @return {void} + */ + setHighContrastTheme: function (chart) { + // We might want to add additional functionality here in the future for + // storing the old state so that we can reset the theme if HC mode is + // disabled. For now, the user will have to reload the page. + chart.highContrastModeActive = true; + // Apply theme to chart + var theme = (chart.options.accessibility.highContrastTheme); + chart.update(theme, false); + // Force series colors (plotOptions is not enough) + chart.series.forEach(function (s) { + var plotOpts = theme.plotOptions[s.type] || {}; + s.update({ + color: plotOpts.color || 'windowText', + colors: [plotOpts.color || 'windowText'], + borderColor: plotOpts.borderColor || 'window' + }); + // Force point colors if existing + s.points.forEach(function (p) { + if (p.options && p.options.color) { + p.update({ + color: plotOpts.color || 'windowText', + borderColor: plotOpts.borderColor || 'window' + }, false); + } + }); + }); + // The redraw for each series and after is required for 3D pie + // (workaround) + chart.redraw(); + } + }; + + return whcm; + }); + _registerModule(_modules, 'modules/accessibility/high-contrast-theme.js', [], function () { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Default theme for Windows High Contrast Mode. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var theme = { + chart: { + backgroundColor: 'window' + }, + title: { + style: { + color: 'windowText' + } + }, + subtitle: { + style: { + color: 'windowText' + } + }, + colorAxis: { + minColor: 'windowText', + maxColor: 'windowText', + stops: [] + }, + colors: ['windowText'], + xAxis: { + gridLineColor: 'windowText', + labels: { + style: { + color: 'windowText' + } + }, + lineColor: 'windowText', + minorGridLineColor: 'windowText', + tickColor: 'windowText', + title: { + style: { + color: 'windowText' + } + } + }, + yAxis: { + gridLineColor: 'windowText', + labels: { + style: { + color: 'windowText' + } + }, + lineColor: 'windowText', + minorGridLineColor: 'windowText', + tickColor: 'windowText', + title: { + style: { + color: 'windowText' + } + } + }, + tooltip: { + backgroundColor: 'window', + borderColor: 'windowText', + style: { + color: 'windowText' + } + }, + plotOptions: { + series: { + lineColor: 'windowText', + fillColor: 'window', + borderColor: 'windowText', + edgeColor: 'windowText', + borderWidth: 1, + dataLabels: { + connectorColor: 'windowText', + color: 'windowText', + style: { + color: 'windowText', + textOutline: 'none' + } + }, + marker: { + lineColor: 'windowText', + fillColor: 'windowText' + } + }, + pie: { + color: 'window', + colors: ['window'], + borderColor: 'windowText', + borderWidth: 1 + }, + boxplot: { + fillColor: 'window' + }, + candlestick: { + lineColor: 'windowText', + fillColor: 'window' + }, + errorbar: { + fillColor: 'window' + } + }, + legend: { + backgroundColor: 'window', + itemStyle: { + color: 'windowText' + }, + itemHoverStyle: { + color: 'windowText' + }, + itemHiddenStyle: { + color: '#555' + }, + title: { + style: { + color: 'windowText' + } + } + }, + credits: { + style: { + color: 'windowText' + } + }, + labels: { + style: { + color: 'windowText' + } + }, + drilldown: { + activeAxisLabelStyle: { + color: 'windowText' + }, + activeDataLabelStyle: { + color: 'windowText' + } + }, + navigation: { + buttonOptions: { + symbolStroke: 'windowText', + theme: { + fill: 'window' + } + } + }, + rangeSelector: { + buttonTheme: { + fill: 'window', + stroke: 'windowText', + style: { + color: 'windowText' + }, + states: { + hover: { + fill: 'window', + stroke: 'windowText', + style: { + color: 'windowText' + } + }, + select: { + fill: '#444', + stroke: 'windowText', + style: { + color: 'windowText' + } + } + } + }, + inputBoxBorderColor: 'windowText', + inputStyle: { + backgroundColor: 'window', + color: 'windowText' + }, + labelStyle: { + color: 'windowText' + } + }, + navigator: { + handles: { + backgroundColor: 'window', + borderColor: 'windowText' + }, + outlineColor: 'windowText', + maskFill: 'transparent', + series: { + color: 'windowText', + lineColor: 'windowText' + }, + xAxis: { + gridLineColor: 'windowText' + } + }, + scrollbar: { + barBackgroundColor: '#444', + barBorderColor: 'windowText', + buttonArrowColor: 'windowText', + buttonBackgroundColor: 'window', + buttonBorderColor: 'windowText', + rifleColor: 'windowText', + trackBackgroundColor: 'window', + trackBorderColor: 'windowText' + } + }; + + return theme; + }); + _registerModule(_modules, 'modules/accessibility/options/options.js', [], function () { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Default options for accessibility. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Formatter callback for the accessibility announcement. + * + * @callback Highcharts.AccessibilityAnnouncementFormatter + * + * @param {Array} updatedSeries + * Array of all series that received updates. If an announcement is already + * queued, the series that received updates for that announcement are also + * included in this array. + * + * @param {Highcharts.Series} [addedSeries] + * This is provided if {@link Highcharts.Chart#addSeries} was called, and there + * is a new series. In that case, this argument is a reference to the new + * series. + * + * @param {Highcharts.Point} [addedPoint] + * This is provided if {@link Highcharts.Series#addPoint} was called, and there + * is a new point. In that case, this argument is a reference to the new point. + * + * @return {false|string} + * The function should return a string with the text to announce to the user. + * Return empty string to not announce anything. Return `false` to use the + * default announcement format. + */ + /** + * @interface Highcharts.PointAccessibilityOptionsObject + */ /** + * Provide a description of the data point, announced to screen readers. + * @name Highcharts.PointAccessibilityOptionsObject#description + * @type {string|undefined} + * @requires modules/accessibility + * @since 7.1.0 + */ + /* * + * @interface Highcharts.PointOptionsObject in parts/Point.ts + */ /** + * @name Highcharts.PointOptionsObject#accessibility + * @type {Highcharts.PointAccessibilityOptionsObject|undefined} + * @requires modules/accessibility + * @since 7.1.0 + */ + /** + * @callback Highcharts.ScreenReaderClickCallbackFunction + * + * @param {global.MouseEvent} evt + * Mouse click event + * + * @return {void} + */ + /** + * Creates a formatted string for the screen reader module. + * + * @callback Highcharts.ScreenReaderFormatterCallbackFunction + * + * @param {T} context + * Context to format + * + * @return {string} + * Formatted string for the screen reader module. + */ + var options = { + /** + * Options for configuring accessibility for the chart. Requires the + * [accessibility module](https://code.highcharts.com/modules/accessibility.js) + * to be loaded. For a description of the module and information + * on its features, see + * [Highcharts Accessibility](https://www.highcharts.com/docs/chart-concepts/accessibility). + * + * @since 5.0.0 + * @requires modules/accessibility + * @optionparent accessibility + */ + accessibility: { + /** + * Enable accessibility functionality for the chart. + * + * @since 5.0.0 + */ + enabled: true, + /** + * Accessibility options for the screen reader information sections + * added before and after the chart. + * + * @since 8.0.0 + */ + screenReaderSection: { + /** + * Function to run upon clicking the "View as Data Table" link in + * the screen reader region. + * + * By default Highcharts will insert and set focus to a data table + * representation of the chart. + * + * @type {Highcharts.ScreenReaderClickCallbackFunction} + * @since 8.0.0 + * @apioption accessibility.screenReaderSection.onViewDataTableClick + */ + /** + * Function to run upon clicking the "Play as sound" button in + * the screen reader region. + * + * By default Highcharts will call the `chart.sonify` function. + * + * @type {Highcharts.ScreenReaderClickCallbackFunction} + * @since 8.0.1 + * @apioption accessibility.screenReaderSection.onPlayAsSoundClick + */ + /** + * A formatter function to create the HTML contents of the hidden + * screen reader information region before the chart. Receives one + * argument, `chart`, referring to the chart object. Should return a + * string with the HTML content of the region. By default this + * returns an automatic description of the chart based on + * [beforeChartFormat](#accessibility.screenReaderSection.beforeChartFormat). + * + * @type {Highcharts.ScreenReaderFormatterCallbackFunction} + * @since 8.0.0 + * @apioption accessibility.screenReaderSection.beforeChartFormatter + */ + /** + * Format for the screen reader information region before the chart. + * Supported HTML tags are ``, `

    `, `

    `, ``, `
    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    `this.min`The mininimum value of the points in the selected + * range.
    `this.max`The maximum value of the points in the selected + * range.
    `this.average`The average value of the points in the selected + * range.
    `this.bins`The amount of the points in the selected range.
    + * + * @type {function} + * + */ + formatter: void 0 + } + }, + controlPointOptions: { + positioner: function (target) { + var cpIndex = this.index, chart = target.chart, options = target.options, typeOptions = options.typeOptions, selectType = typeOptions.selectType, controlPointOptions = options.controlPointOptions, inverted = chart.inverted, xAxis = chart.xAxis[typeOptions.xAxis], yAxis = chart.yAxis[typeOptions.yAxis], targetX = target.xAxisMax, targetY = target.yAxisMax, ext = target.calculations.getExtremes(target.xAxisMin, target.xAxisMax, target.yAxisMin, target.yAxisMax), x, y; + if (selectType === 'x') { + targetY = (ext.yAxisMax - ext.yAxisMin) / 2; + // first control point + if (cpIndex === 0) { + targetX = target.xAxisMin; + } + } + if (selectType === 'y') { + targetX = ext.xAxisMin + + ((ext.xAxisMax - ext.xAxisMin) / 2); + // first control point + if (cpIndex === 0) { + targetY = target.yAxisMin; + } + } + if (inverted) { + x = yAxis.toPixels(targetY); + y = xAxis.toPixels(targetX); + } + else { + x = xAxis.toPixels(targetX); + y = yAxis.toPixels(targetY); + } + return { + x: x - (controlPointOptions.width / 2), + y: y - (controlPointOptions.height / 2) + }; + }, + events: { + drag: function (e, target) { + var translation = this.mouseMoveToTranslation(e), selectType = target.options.typeOptions.selectType, index = this.index, x = selectType === 'y' ? 0 : translation.x, y = selectType === 'x' ? 0 : translation.y; + target.resize(x, y, index, selectType); + target.resizeX += x; + target.resizeY += y; + target.redraw(false, true); + } + } + } + }); + Annotation.types.measure = Measure; + + return Measure; + }); + _registerModule(_modules, 'mixins/navigation.js', [], function () { + /** + * + * (c) 2010-2018 Paweł Fus + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var chartNavigation = { + /** + * Initializes `chart.navigation` object which delegates `update()` methods + * to all other common classes (used in exporting and navigationBindings). + * + * @private + * @param {Highcharts.Chart} chart + * The chart instance. + * @return {void} + */ + initUpdate: function (chart) { + if (!chart.navigation) { + chart.navigation = { + updates: [], + update: function (options, redraw) { + this.updates.forEach(function (updateConfig) { + updateConfig.update.call(updateConfig.context, options, redraw); + }); + } + }; + } + }, + /** + * Registers an `update()` method in the `chart.navigation` object. + * + * @private + * @param {Highcharts.ChartNavigationUpdateFunction} update + * The `update()` method that will be called in `chart.update()`. + * @param {Highcharts.Chart} chart + * The chart instance. `update()` will use that as a context + * (`this`). + * @return {void} + */ + addUpdate: function (update, chart) { + if (!chart.navigation) { + this.initUpdate(chart); + } + chart.navigation.updates.push({ + update: update, + context: chart + }); + } + }; + + return chartNavigation; + }); + _registerModule(_modules, 'annotations/navigationBindings.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['mixins/navigation.js']], function (H, U, chartNavigationMixin) { + /* * + * + * (c) 2009-2017 Highsoft, Black Label + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * A config object for navigation bindings in annotations. + * + * @interface Highcharts.NavigationBindingsOptionsObject + */ /** + * ClassName of the element for a binding. + * @name Highcharts.NavigationBindingsOptionsObject#className + * @type {string|undefined} + */ /** + * Last event to be fired after last step event. + * @name Highcharts.NavigationBindingsOptionsObject#end + * @type {Function|undefined} + */ /** + * Initial event, fired on a button click. + * @name Highcharts.NavigationBindingsOptionsObject#init + * @type {Function|undefined} + */ /** + * Event fired on first click on a chart. + * @name Highcharts.NavigationBindingsOptionsObject#start + * @type {Function|undefined} + */ /** + * Last event to be fired after last step event. Array of step events to be + * called sequentially after each user click. + * @name Highcharts.NavigationBindingsOptionsObject#steps + * @type {Array|undefined} + */ + var addEvent = U.addEvent, attr = U.attr, extend = U.extend, format = U.format, fireEvent = U.fireEvent, isArray = U.isArray, isFunction = U.isFunction, isNumber = U.isNumber, isObject = U.isObject, merge = U.merge, objectEach = U.objectEach, pick = U.pick; + var doc = H.doc, win = H.win, PREFIX = 'highcharts-'; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * IE 9-11 polyfill for Element.closest(): + * @private + */ + function closestPolyfill(el, s) { + var ElementProto = win.Element.prototype, elementMatches = ElementProto.matches || + ElementProto.msMatchesSelector || + ElementProto.webkitMatchesSelector, ret = null; + if (ElementProto.closest) { + ret = ElementProto.closest.call(el, s); + } + else { + do { + if (elementMatches.call(el, s)) { + return el; + } + el = el.parentElement || el.parentNode; + } while (el !== null && el.nodeType === 1); + } + return ret; + } + /** + * @private + * @interface bindingsUtils + */ + var bindingsUtils = { + /** + * Update size of background (rect) in some annotations: Measure, Simple + * Rect. + * + * @private + * @function Highcharts.NavigationBindingsUtilsObject.updateRectSize + * + * @param {Highcharts.PointerEventObject} event + * Normalized browser event + * + * @param {Highcharts.Annotation} annotation + * Annotation to be updated + */ + updateRectSize: function (event, annotation) { + var chart = annotation.chart, options = annotation.options.typeOptions, coords = chart.pointer.getCoordinates(event), width = coords.xAxis[0].value - options.point.x, height = options.point.y - coords.yAxis[0].value; + annotation.update({ + typeOptions: { + background: { + width: chart.inverted ? height : width, + height: chart.inverted ? width : height + } + } + }); + }, + /** + * Get field type according to value + * + * @private + * @function Highcharts.NavigationBindingsUtilsObject.getFieldType + * + * @param {'boolean'|'number'|'string'} value + * Atomic type (one of: string, number, boolean) + * + * @return {'checkbox'|'number'|'text'} + * Field type (one of: text, number, checkbox) + */ + getFieldType: function (value) { + return { + 'string': 'text', + 'number': 'number', + 'boolean': 'checkbox' + }[typeof value]; + } + }; + /** + * @private + */ + var NavigationBindings = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function NavigationBindings(chart, options) { + this.boundClassNames = void 0; + this.selectedButton = void 0; + this.chart = chart; + this.options = options; + this.eventsToUnbind = []; + this.container = doc.getElementsByClassName(this.options.bindingsClassName || ''); + } + // Private properties added by bindings: + // Active (selected) annotation that is editted through popup/forms + // activeAnnotation: Annotation + // Holder for current step, used on mouse move to update bound object + // mouseMoveEvent: function () {} + // Next event in `step` array to be called on chart's click + // nextEvent: function () {} + // Index in the `step` array of the current event + // stepIndex: 0 + // Flag to determine if current binding has steps + // steps: true|false + // Bindings holder for all events + // selectedButton: {} + // Holder for user options, returned from `start` event, and passed on to + // `step`'s' and `end`. + // currentUserDetails: {} + /* * + * + * Functions + * + * */ + /** + * Initi all events conencted to NavigationBindings. + * + * @private + * @function Highcharts.NavigationBindings#initEvents + */ + NavigationBindings.prototype.initEvents = function () { + var navigation = this, chart = navigation.chart, bindingsContainer = navigation.container, options = navigation.options; + // Shorthand object for getting events for buttons: + navigation.boundClassNames = {}; + objectEach((options.bindings || {}), function (value) { + navigation.boundClassNames[value.className] = value; + }); + // Handle multiple containers with the same class names: + [].forEach.call(bindingsContainer, function (subContainer) { + navigation.eventsToUnbind.push(addEvent(subContainer, 'click', function (event) { + var bindings = navigation.getButtonEvents(subContainer, event); + if (bindings) { + navigation.bindingsButtonClick(bindings.button, bindings.events, event); + } + })); + }); + objectEach(options.events || {}, function (callback, eventName) { + if (isFunction(callback)) { + navigation.eventsToUnbind.push(addEvent(navigation, eventName, callback)); + } + }); + navigation.eventsToUnbind.push(addEvent(chart.container, 'click', function (e) { + if (!chart.cancelClick && + chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop)) { + navigation.bindingsChartClick(this, e); + } + })); + navigation.eventsToUnbind.push(addEvent(chart.container, 'mousemove', function (e) { + navigation.bindingsContainerMouseMove(this, e); + })); + }; + /** + * Common chart.update() delegation, shared between bindings and exporting. + * + * @private + * @function Highcharts.NavigationBindings#initUpdate + */ + NavigationBindings.prototype.initUpdate = function () { + var navigation = this; + chartNavigationMixin.addUpdate(function (options) { + navigation.update(options); + }, this.chart); + }; + /** + * Hook for click on a button, method selcts/unselects buttons, + * then calls `bindings.init` callback. + * + * @private + * @function Highcharts.NavigationBindings#bindingsButtonClick + * + * @param {Highcharts.HTMLDOMElement} [button] + * Clicked button + * + * @param {object} events + * Events passed down from bindings (`init`, `start`, `step`, `end`) + * + * @param {Highcharts.PointerEventObject} clickEvent + * Browser's click event + */ + NavigationBindings.prototype.bindingsButtonClick = function (button, events, clickEvent) { + var navigation = this, chart = navigation.chart; + if (navigation.selectedButtonElement) { + fireEvent(navigation, 'deselectButton', { button: navigation.selectedButtonElement }); + if (navigation.nextEvent) { + // Remove in-progress annotations adders: + if (navigation.currentUserDetails && + navigation.currentUserDetails.coll === 'annotations') { + chart.removeAnnotation(navigation.currentUserDetails); + } + navigation.mouseMoveEvent = navigation.nextEvent = false; + } + } + navigation.selectedButton = events; + navigation.selectedButtonElement = button; + fireEvent(navigation, 'selectButton', { button: button }); + // Call "init" event, for example to open modal window + if (events.init) { + events.init.call(navigation, button, clickEvent); + } + if (events.start || events.steps) { + chart.renderer.boxWrapper.addClass(PREFIX + 'draw-mode'); + } + }; + /** + * Hook for click on a chart, first click on a chart calls `start` event, + * then on all subsequent clicks iterate over `steps` array. + * When finished, calls `end` event. + * + * @private + * @function Highcharts.NavigationBindings#bindingsChartClick + * + * @param {Highcharts.Chart} chart + * Chart that click was performed on. + * + * @param {Highcharts.PointerEventObject} clickEvent + * Browser's click event. + */ + NavigationBindings.prototype.bindingsChartClick = function (chart, clickEvent) { + var navigation = this, chart = navigation.chart, selectedButton = navigation.selectedButton, svgContainer = chart.renderer.boxWrapper; + // Click outside popups, should close them and deselect the annotation + if (navigation.activeAnnotation && + !clickEvent.activeAnnotation && + // Element could be removed in the child action, e.g. button + clickEvent.target.parentNode && + // TO DO: Polyfill for IE11? + !closestPolyfill(clickEvent.target, '.' + PREFIX + 'popup')) { + fireEvent(navigation, 'closePopup'); + navigation.deselectAnnotation(); + } + if (!selectedButton || !selectedButton.start) { + return; + } + if (!navigation.nextEvent) { + // Call init method: + navigation.currentUserDetails = selectedButton.start.call(navigation, clickEvent); + // If steps exists (e.g. Annotations), bind them: + if (selectedButton.steps) { + navigation.stepIndex = 0; + navigation.steps = true; + navigation.mouseMoveEvent = navigation.nextEvent = + selectedButton.steps[navigation.stepIndex]; + } + else { + fireEvent(navigation, 'deselectButton', { button: navigation.selectedButtonElement }); + svgContainer.removeClass(PREFIX + 'draw-mode'); + navigation.steps = false; + navigation.selectedButton = null; + // First click is also the last one: + if (selectedButton.end) { + selectedButton.end.call(navigation, clickEvent, navigation.currentUserDetails); + } + } + } + else { + navigation.nextEvent(clickEvent, navigation.currentUserDetails); + if (navigation.steps) { + navigation.stepIndex++; + if (selectedButton.steps[navigation.stepIndex]) { + // If we have more steps, bind them one by one: + navigation.mouseMoveEvent = navigation.nextEvent = + selectedButton.steps[navigation.stepIndex]; + } + else { + fireEvent(navigation, 'deselectButton', { button: navigation.selectedButtonElement }); + svgContainer.removeClass(PREFIX + 'draw-mode'); + // That was the last step, call end(): + if (selectedButton.end) { + selectedButton.end.call(navigation, clickEvent, navigation.currentUserDetails); + } + navigation.nextEvent = false; + navigation.mouseMoveEvent = false; + navigation.selectedButton = null; + } + } + } + }; + /** + * Hook for mouse move on a chart's container. It calls current step. + * + * @private + * @function Highcharts.NavigationBindings#bindingsContainerMouseMove + * + * @param {Highcharts.HTMLDOMElement} container + * Chart's container. + * + * @param {global.Event} moveEvent + * Browser's move event. + */ + NavigationBindings.prototype.bindingsContainerMouseMove = function (_container, moveEvent) { + if (this.mouseMoveEvent) { + this.mouseMoveEvent(moveEvent, this.currentUserDetails); + } + }; + /** + * Translate fields (e.g. `params.period` or `marker.styles.color`) to + * Highcharts options object (e.g. `{ params: { period } }`). + * + * @private + * @function Highcharts.NavigationBindings#fieldsToOptions + * + * @param {Highcharts.Dictionary} fields + * Fields from popup form. + * + * @param {T} config + * Default config to be modified. + * + * @return {T} + * Modified config + */ + NavigationBindings.prototype.fieldsToOptions = function (fields, config) { + objectEach(fields, function (value, field) { + var parsedValue = parseFloat(value), path = field.split('.'), parent = config, pathLength = path.length - 1; + // If it's a number (not "format" options), parse it: + if (isNumber(parsedValue) && + !value.match(/px/g) && + !field.match(/format/g)) { + value = parsedValue; + } + // Remove empty strings or values like 0 + if (value !== '' && value !== 'undefined') { + path.forEach(function (name, index) { + var nextName = pick(path[index + 1], ''); + if (pathLength === index) { + // Last index, put value: + parent[name] = value; + } + else if (!parent[name]) { + // Create middle property: + parent[name] = nextName.match(/\d/g) ? [] : {}; + parent = parent[name]; + } + else { + // Jump into next property + parent = parent[name]; + } + }); + } + }); + return config; + }; + /** + * Shorthand method to deselect an annotation. + * + * @function Highcharts.NavigationBindings#deselectAnnotation + */ + NavigationBindings.prototype.deselectAnnotation = function () { + if (this.activeAnnotation) { + this.activeAnnotation.setControlPointsVisibility(false); + this.activeAnnotation = false; + } + }; + /** + * Generates API config for popup in the same format as options for + * Annotation object. + * + * @function Highcharts.NavigationBindings#annotationToFields + * + * @param {Highcharts.Annotation} annotation + * Annotations object + * + * @return {Highcharts.Dictionary} + * Annotation options to be displayed in popup box + */ + NavigationBindings.prototype.annotationToFields = function (annotation) { + var options = annotation.options, editables = NavigationBindings.annotationsEditable, nestedEditables = editables.nestedOptions, getFieldType = this.utils.getFieldType, type = pick(options.type, options.shapes && options.shapes[0] && + options.shapes[0].type, options.labels && options.labels[0] && + options.labels[0].itemType, 'label'), nonEditables = NavigationBindings.annotationsNonEditable[options.langKey] || [], visualOptions = { + langKey: options.langKey, + type: type + }; + /** + * Nested options traversing. Method goes down to the options and copies + * allowed options (with values) to new object, which is last parameter: + * "parent". + * + * @private + * + * @param {*} option + * Atomic type or object/array + * + * @param {string} key + * Option name, for example "visible" or "x", "y" + * + * @param {object} parentEditables + * Editables from NavigationBindings.annotationsEditable + * + * @param {object} parent + * Where new options will be assigned + */ + function traverse(option, key, parentEditables, parent) { + var nextParent; + if (parentEditables && + nonEditables.indexOf(key) === -1 && + ((parentEditables.indexOf && + parentEditables.indexOf(key)) >= 0 || + parentEditables[key] || // nested array + parentEditables === true // simple array + )) { + // Roots: + if (isArray(option)) { + parent[key] = []; + option.forEach(function (arrayOption, i) { + if (!isObject(arrayOption)) { + // Simple arrays, e.g. [String, Number, Boolean] + traverse(arrayOption, 0, nestedEditables[key], parent[key]); + } + else { + // Advanced arrays, e.g. [Object, Object] + parent[key][i] = {}; + objectEach(arrayOption, function (nestedOption, nestedKey) { + traverse(nestedOption, nestedKey, nestedEditables[key], parent[key][i]); + }); + } + }); + } + else if (isObject(option)) { + nextParent = {}; + if (isArray(parent)) { + parent.push(nextParent); + nextParent[key] = {}; + nextParent = nextParent[key]; + } + else { + parent[key] = nextParent; + } + objectEach(option, function (nestedOption, nestedKey) { + traverse(nestedOption, nestedKey, key === 0 ? parentEditables : nestedEditables[key], nextParent); + }); + } + else { + // Leaf: + if (key === 'format') { + parent[key] = [ + format(option, annotation.labels[0].points[0]).toString(), + 'text' + ]; + } + else if (isArray(parent)) { + parent.push([option, getFieldType(option)]); + } + else { + parent[key] = [option, getFieldType(option)]; + } + } + } + } + objectEach(options, function (option, key) { + if (key === 'typeOptions') { + visualOptions[key] = {}; + objectEach(options[key], function (typeOption, typeKey) { + traverse(typeOption, typeKey, nestedEditables, visualOptions[key], true); + }); + } + else { + traverse(option, key, editables[type], visualOptions); + } + }); + return visualOptions; + }; + /** + * Get all class names for all parents in the element. Iterates until finds + * main container. + * + * @function Highcharts.NavigationBindings#getClickedClassNames + * + * @param {Highcharts.HTMLDOMElement} + * Container that event is bound to. + * + * @param {global.Event} event + * Browser's event. + * + * @return {Array>} + * Array of class names with corresponding elements + */ + NavigationBindings.prototype.getClickedClassNames = function (container, event) { + var element = event.target, classNames = [], elemClassName; + while (element) { + elemClassName = attr(element, 'class'); + if (elemClassName) { + classNames = classNames.concat(elemClassName + .split(' ') + .map(function (name) { + return [ + name, + element + ]; + })); + } + element = element.parentNode; + if (element === container) { + return classNames; + } + } + return classNames; + }; + /** + * Get events bound to a button. It's a custom event delegation to find all + * events connected to the element. + * + * @private + * @function Highcharts.NavigationBindings#getButtonEvents + * + * @param {Highcharts.HTMLDOMElement} container + * Container that event is bound to. + * + * @param {global.Event} event + * Browser's event. + * + * @return {object} + * Object with events (init, start, steps, and end) + */ + NavigationBindings.prototype.getButtonEvents = function (container, event) { + var navigation = this, classNames = this.getClickedClassNames(container, event), bindings; + classNames.forEach(function (className) { + if (navigation.boundClassNames[className[0]] && !bindings) { + bindings = { + events: navigation.boundClassNames[className[0]], + button: className[1] + }; + } + }); + return bindings; + }; + /** + * Bindings are just events, so the whole update process is simply + * removing old events and adding new ones. + * + * @private + * @function Highcharts.NavigationBindings#update + */ + NavigationBindings.prototype.update = function (options) { + this.options = merge(true, this.options, options); + this.removeEvents(); + this.initEvents(); + }; + /** + * Remove all events created in the navigation. + * + * @private + * @function Highcharts.NavigationBindings#removeEvents + */ + NavigationBindings.prototype.removeEvents = function () { + this.eventsToUnbind.forEach(function (unbinder) { + unbinder(); + }); + }; + NavigationBindings.prototype.destroy = function () { + this.removeEvents(); + }; + /* * + * + * Static Properties + * + * */ + // Define which options from annotations should show up in edit box: + NavigationBindings.annotationsEditable = { + // `typeOptions` are always available + // Nested and shared options: + nestedOptions: { + labelOptions: ['style', 'format', 'backgroundColor'], + labels: ['style'], + label: ['style'], + style: ['fontSize', 'color'], + background: ['fill', 'strokeWidth', 'stroke'], + innerBackground: ['fill', 'strokeWidth', 'stroke'], + outerBackground: ['fill', 'strokeWidth', 'stroke'], + shapeOptions: ['fill', 'strokeWidth', 'stroke'], + shapes: ['fill', 'strokeWidth', 'stroke'], + line: ['strokeWidth', 'stroke'], + backgroundColors: [true], + connector: ['fill', 'strokeWidth', 'stroke'], + crosshairX: ['strokeWidth', 'stroke'], + crosshairY: ['strokeWidth', 'stroke'] + }, + // Simple shapes: + circle: ['shapes'], + verticalLine: [], + label: ['labelOptions'], + // Measure + measure: ['background', 'crosshairY', 'crosshairX'], + // Others: + fibonacci: [], + tunnel: ['background', 'line', 'height'], + pitchfork: ['innerBackground', 'outerBackground'], + rect: ['shapes'], + // Crooked lines, elliots, arrows etc: + crookedLine: [], + basicAnnotation: [] + }; + // Define non editable fields per annotation, for example Rectangle inherits + // options from Measure, but crosshairs are not available + NavigationBindings.annotationsNonEditable = { + rectangle: ['crosshairX', 'crosshairY', 'label'] + }; + return NavigationBindings; + }()); + /** + * General utils for bindings + * + * @private + * @name Highcharts.NavigationBindings.utils + * @type {bindingsUtils} + */ + NavigationBindings.prototype.utils = bindingsUtils; + H.Chart.prototype.initNavigationBindings = function () { + var chart = this, options = chart.options; + if (options && options.navigation && options.navigation.bindings) { + chart.navigationBindings = new NavigationBindings(chart, options.navigation); + chart.navigationBindings.initEvents(); + chart.navigationBindings.initUpdate(); + } + }; + addEvent(H.Chart, 'load', function () { + this.initNavigationBindings(); + }); + addEvent(H.Chart, 'destroy', function () { + if (this.navigationBindings) { + this.navigationBindings.destroy(); + } + }); + addEvent(NavigationBindings, 'deselectButton', function () { + this.selectedButtonElement = null; + }); + addEvent(H.Annotation, 'remove', function () { + if (this.chart.navigationBindings) { + this.chart.navigationBindings.deselectAnnotation(); + } + }); + /** + * Show edit-annotation form: + * @private + */ + function selectableAnnotation(annotationType) { + var originalClick = annotationType.prototype.defaultOptions.events && + annotationType.prototype.defaultOptions.events.click; + /** + * @private + */ + function selectAndshowPopup(event) { + var annotation = this, navigation = annotation.chart.navigationBindings, prevAnnotation = navigation.activeAnnotation; + if (originalClick) { + originalClick.click.call(annotation, event); + } + if (prevAnnotation !== annotation) { + // Select current: + navigation.deselectAnnotation(); + navigation.activeAnnotation = annotation; + annotation.setControlPointsVisibility(true); + fireEvent(navigation, 'showPopup', { + annotation: annotation, + formType: 'annotation-toolbar', + options: navigation.annotationToFields(annotation), + onSubmit: function (data) { + var config = {}, typeOptions; + if (data.actionType === 'remove') { + navigation.activeAnnotation = false; + navigation.chart.removeAnnotation(annotation); + } + else { + navigation.fieldsToOptions(data.fields, config); + navigation.deselectAnnotation(); + typeOptions = config.typeOptions; + if (annotation.options.type === 'measure') { + // Manually disable crooshars according to + // stroke width of the shape: + typeOptions.crosshairY.enabled = + typeOptions.crosshairY.strokeWidth !== 0; + typeOptions.crosshairX.enabled = + typeOptions.crosshairX.strokeWidth !== 0; + } + annotation.update(config); + } + } + }); + } + else { + // Deselect current: + navigation.deselectAnnotation(); + fireEvent(navigation, 'closePopup'); + } + // Let bubble event to chart.click: + event.activeAnnotation = true; + } + merge(true, annotationType.prototype.defaultOptions.events, { + click: selectAndshowPopup + }); + } + if (H.Annotation) { + // Basic shapes: + selectableAnnotation(H.Annotation); + // Advanced annotations: + objectEach(H.Annotation.types, function (annotationType) { + selectableAnnotation(annotationType); + }); + } + H.setOptions({ + /** + * @optionparent lang + */ + lang: { + /** + * Configure the Popup strings in the chart. Requires the + * `annotations.js` or `annotations-advanced.src.js` module to be + * loaded. + * + * @since 7.0.0 + * @product highcharts highstock + */ + navigation: { + /** + * Translations for all field names used in popup. + * + * @product highcharts highstock + */ + popup: { + simpleShapes: 'Simple shapes', + lines: 'Lines', + circle: 'Circle', + rectangle: 'Rectangle', + label: 'Label', + shapeOptions: 'Shape options', + typeOptions: 'Details', + fill: 'Fill', + format: 'Text', + strokeWidth: 'Line width', + stroke: 'Line color', + title: 'Title', + name: 'Name', + labelOptions: 'Label options', + labels: 'Labels', + backgroundColor: 'Background color', + backgroundColors: 'Background colors', + borderColor: 'Border color', + borderRadius: 'Border radius', + borderWidth: 'Border width', + style: 'Style', + padding: 'Padding', + fontSize: 'Font size', + color: 'Color', + height: 'Height', + shapes: 'Shape options' + } + } + }, + /** + * @optionparent navigation + * @product highcharts highstock + */ + navigation: { + /** + * A CSS class name where all bindings will be attached to. Multiple + * charts on the same page should have separate class names to prevent + * duplicating events. + * + * Default value of versions < 7.0.4 `highcharts-bindings-wrapper` + * + * @since 7.0.0 + * @type {string} + */ + bindingsClassName: 'highcharts-bindings-container', + /** + * Bindings definitions for custom HTML buttons. Each binding implements + * simple event-driven interface: + * + * - `className`: classname used to bind event to + * + * - `init`: initial event, fired on button click + * + * - `start`: fired on first click on a chart + * + * - `steps`: array of sequential events fired one after another on each + * of users clicks + * + * - `end`: last event to be called after last step event + * + * @type {Highcharts.Dictionary|*} + * @sample stock/stocktools/stocktools-thresholds + * Custom bindings in Highstock + * @since 7.0.0 + * @product highcharts highstock + */ + bindings: { + /** + * A circle annotation bindings. Includes `start` and one event in + * `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @default {"className": "highcharts-circle-annotation", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + circleAnnotation: { + /** @ignore-option */ + className: 'highcharts-circle-annotation', + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation; + return this.chart.addAnnotation(merge({ + langKey: 'circle', + type: 'basicAnnotation', + shapes: [{ + type: 'circle', + point: { + xAxis: 0, + yAxis: 0, + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, + r: 5 + }] + }, navigation + .annotationsOptions, navigation + .bindings + .circleAnnotation + .annotationsOptions)); + }, + /** @ignore-option */ + steps: [ + function (e, annotation) { + var point = annotation.options.shapes[0].point, x = this.chart.xAxis[0].toPixels(point.x), y = this.chart.yAxis[0].toPixels(point.y), inverted = this.chart.inverted, distance = Math.max(Math.sqrt(Math.pow(inverted ? y - e.chartX : x - e.chartX, 2) + + Math.pow(inverted ? x - e.chartY : y - e.chartY, 2)), 5); + annotation.update({ + shapes: [{ + r: distance + }] + }); + } + ] + }, + /** + * A rectangle annotation bindings. Includes `start` and one event + * in `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @default {"className": "highcharts-rectangle-annotation", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + rectangleAnnotation: { + /** @ignore-option */ + className: 'highcharts-rectangle-annotation', + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, x = coords.xAxis[0].value, y = coords.yAxis[0].value; + return this.chart.addAnnotation(merge({ + langKey: 'rectangle', + type: 'basicAnnotation', + shapes: [{ + type: 'path', + points: [{ + xAxis: 0, + yAxis: 0, + x: x, + y: y + }, { + xAxis: 0, + yAxis: 0, + x: x, + y: y + }, { + xAxis: 0, + yAxis: 0, + x: x, + y: y + }, { + xAxis: 0, + yAxis: 0, + x: x, + y: y + }] + }] + }, navigation + .annotationsOptions, navigation + .bindings + .rectangleAnnotation + .annotationsOptions)); + }, + /** @ignore-option */ + steps: [ + function (e, annotation) { + var points = annotation.options.shapes[0].points, coords = this.chart.pointer.getCoordinates(e), x = coords.xAxis[0].value, y = coords.yAxis[0].value; + // Top right point + points[1].x = x; + // Bottom right point (cursor position) + points[2].x = x; + points[2].y = y; + // Bottom left + points[3].y = y; + annotation.update({ + shapes: [{ + points: points + }] + }); + } + ] + }, + /** + * A label annotation bindings. Includes `start` event only. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @default {"className": "highcharts-label-annotation", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + labelAnnotation: { + /** @ignore-option */ + className: 'highcharts-label-annotation', + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation; + return this.chart.addAnnotation(merge({ + langKey: 'label', + type: 'basicAnnotation', + labelOptions: { + format: '{y:.2f}' + }, + labels: [{ + point: { + xAxis: 0, + yAxis: 0, + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, + overflow: 'none', + crop: true + }] + }, navigation + .annotationsOptions, navigation + .bindings + .labelAnnotation + .annotationsOptions)); + } + } + }, + /** + * Path where Highcharts will look for icons. Change this to use icons + * from a different server. + * + * @type {string} + * @default https://code.highcharts.com/8.1.0/gfx/stock-icons/ + * @since 7.1.3 + * @apioption navigation.iconsURL + */ + /** + * A `showPopup` event. Fired when selecting for example an annotation. + * + * @type {Function} + * @apioption navigation.events.showPopup + */ + /** + * A `closePopup` event. Fired when Popup should be hidden, for example + * when clicking on an annotation again. + * + * @type {Function} + * @apioption navigation.events.closePopup + */ + /** + * Event fired on a button click. + * + * @type {Function} + * @sample highcharts/annotations/gui/ + * Change icon in a dropddown on event + * @sample highcharts/annotations/gui-buttons/ + * Change button class on event + * @apioption navigation.events.selectButton + */ + /** + * Event fired when button state should change, for example after + * adding an annotation. + * + * @type {Function} + * @sample highcharts/annotations/gui/ + * Change icon in a dropddown on event + * @sample highcharts/annotations/gui-buttons/ + * Change button class on event + * @apioption navigation.events.deselectButton + */ + /** + * Events to communicate between Stock Tools and custom GUI. + * + * @since 7.0.0 + * @product highcharts highstock + * @optionparent navigation.events + */ + events: {}, + /** + * Additional options to be merged into all annotations. + * + * @sample stock/stocktools/navigation-annotation-options + * Set red color of all line annotations + * + * @type {Highcharts.AnnotationsOptions} + * @extends annotations + * @exclude crookedLine, elliottWave, fibonacci, infinityLine, + * measure, pitchfork, tunnel, verticalLine, basicAnnotation + * @apioption navigation.annotationsOptions + */ + annotationsOptions: {} + } + }); + + return NavigationBindings; + }); + _registerModule(_modules, 'annotations/popup.js', [_modules['parts/Globals.js'], _modules['annotations/navigationBindings.js'], _modules['parts/Utilities.js']], function (H, NavigationBindings, U) { + /* * + * + * Popup generator for Stock tools + * + * (c) 2009-2017 Sebastian Bochan + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, createElement = U.createElement, defined = U.defined, isArray = U.isArray, isObject = U.isObject, isString = U.isString, objectEach = U.objectEach, pick = U.pick, wrap = U.wrap; + var indexFilter = /\d/g, PREFIX = 'highcharts-', DIV = 'div', INPUT = 'input', LABEL = 'label', BUTTON = 'button', SELECT = 'select', OPTION = 'option', SPAN = 'span', UL = 'ul', LI = 'li', H3 = 'h3'; + /* eslint-disable no-invalid-this, valid-jsdoc */ + // onContainerMouseDown blocks internal popup events, due to e.preventDefault. + // Related issue #4606 + wrap(H.Pointer.prototype, 'onContainerMouseDown', function (proceed, e) { + var popupClass = e.target && e.target.className; + // elements is not in popup + if (!(isString(popupClass) && + popupClass.indexOf(PREFIX + 'popup-field') >= 0)) { + proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + } + }); + H.Popup = function (parentDiv, iconsURL) { + this.init(parentDiv, iconsURL); + }; + H.Popup.prototype = { + /** + * Initialize the popup. Create base div and add close button. + * @private + * @param {Highcharts.HTMLDOMElement} parentDiv + * Container where popup should be placed + * @param {string} iconsURL + * Icon URL + */ + init: function (parentDiv, iconsURL) { + // create popup div + this.container = createElement(DIV, { + className: PREFIX + 'popup' + }, null, parentDiv); + this.lang = this.getLangpack(); + this.iconsURL = iconsURL; + // add close button + this.addCloseBtn(); + }, + /** + * Create HTML element and attach click event (close popup). + * @private + */ + addCloseBtn: function () { + var _self = this, closeBtn; + // create close popup btn + closeBtn = createElement(DIV, { + className: PREFIX + 'popup-close' + }, null, this.container); + closeBtn.style['background-image'] = 'url(' + + this.iconsURL + 'close.svg)'; + ['click', 'touchstart'].forEach(function (eventName) { + addEvent(closeBtn, eventName, function () { + _self.closePopup(); + }); + }); + }, + /** + * Create two columns (divs) in HTML. + * @private + * @param {Highcharts.HTMLDOMElement} container + * Container of columns + * @return {Highcharts.Dictionary} + * Reference to two HTML columns (lhsCol, rhsCol) + */ + addColsContainer: function (container) { + var rhsCol, lhsCol; + // left column + lhsCol = createElement(DIV, { + className: PREFIX + 'popup-lhs-col' + }, null, container); + // right column + rhsCol = createElement(DIV, { + className: PREFIX + 'popup-rhs-col' + }, null, container); + // wrapper content + createElement(DIV, { + className: PREFIX + 'popup-rhs-col-wrapper' + }, null, rhsCol); + return { + lhsCol: lhsCol, + rhsCol: rhsCol + }; + }, + /** + * Create input with label. + * @private + * @param {string} option + * Chain of fields i.e params.styles.fontSize + * @param {string} type + * Indicator type + * @param {Highhcharts.HTMLDOMElement} + * Container where elements should be added + * @param {string} value + * Default value of input i.e period value is 14, extracted from + * defaultOptions (ADD mode) or series options (EDIT mode) + */ + addInput: function (option, type, parentDiv, value) { + var optionParamList = option.split('.'), optionName = optionParamList[optionParamList.length - 1], lang = this.lang, inputName = PREFIX + type + '-' + optionName; + if (!inputName.match(indexFilter)) { + // add label + createElement(LABEL, { + innerHTML: lang[optionName] || optionName, + htmlFor: inputName + }, null, parentDiv); + } + // add input + createElement(INPUT, { + name: inputName, + value: value[0], + type: value[1], + className: PREFIX + 'popup-field' + }, null, parentDiv).setAttribute(PREFIX + 'data-name', option); + }, + /** + * Create button. + * @private + * @param {Highcharts.HTMLDOMElement} parentDiv + * Container where elements should be added + * @param {string} label + * Text placed as button label + * @param {string} type + * add | edit | remove + * @param {Function} callback + * On click callback + * @param {Highcharts.HTMLDOMElement} fieldsDiv + * Container where inputs are generated + * @return {Highcharts.HTMLDOMElement} + * HTML button + */ + addButton: function (parentDiv, label, type, callback, fieldsDiv) { + var _self = this, closePopup = this.closePopup, getFields = this.getFields, button; + button = createElement(BUTTON, { + innerHTML: label + }, null, parentDiv); + ['click', 'touchstart'].forEach(function (eventName) { + addEvent(button, eventName, function () { + closePopup.call(_self); + return callback(getFields(fieldsDiv, type)); + }); + }); + return button; + }, + /** + * Get values from all inputs and create JSON. + * @private + * @param {Highcharts.HTMLDOMElement} - container where inputs are created + * @param {string} - add | edit | remove + * @return {Highcharts.PopupFieldsObject} - fields + */ + getFields: function (parentDiv, type) { + var inputList = parentDiv.querySelectorAll('input'), optionSeries = '#' + PREFIX + 'select-series > option:checked', optionVolume = '#' + PREFIX + 'select-volume > option:checked', linkedTo = parentDiv.querySelectorAll(optionSeries)[0], volumeTo = parentDiv.querySelectorAll(optionVolume)[0], seriesId, param, fieldsOutput; + fieldsOutput = { + actionType: type, + linkedTo: linkedTo && linkedTo.getAttribute('value'), + fields: {} + }; + [].forEach.call(inputList, function (input) { + param = input.getAttribute(PREFIX + 'data-name'); + seriesId = input.getAttribute(PREFIX + 'data-series-id'); + // params + if (seriesId) { + fieldsOutput.seriesId = input.value; + } + else if (param) { + fieldsOutput.fields[param] = input.value; + } + else { + // type like sma / ema + fieldsOutput.type = input.value; + } + }); + if (volumeTo) { + fieldsOutput.fields['params.volumeSeriesID'] = volumeTo.getAttribute('value'); + } + return fieldsOutput; + }, + /** + * Reset content of the current popup and show. + * @private + */ + showPopup: function () { + var popupDiv = this.container, toolbarClass = PREFIX + 'annotation-toolbar', popupCloseBtn = popupDiv + .querySelectorAll('.' + PREFIX + 'popup-close')[0]; + // reset content + popupDiv.innerHTML = ''; + // reset toolbar styles if exists + if (popupDiv.className.indexOf(toolbarClass) >= 0) { + popupDiv.classList.remove(toolbarClass); + // reset toolbar inline styles + popupDiv.removeAttribute('style'); + } + // add close button + popupDiv.appendChild(popupCloseBtn); + popupDiv.style.display = 'block'; + }, + /** + * Hide popup. + * @private + */ + closePopup: function () { + this.popup.container.style.display = 'none'; + }, + /** + * Create content and show popup. + * @private + * @param {string} - type of popup i.e indicators + * @param {Highcharts.Chart} - chart + * @param {Highcharts.AnnotationsOptions} - options + * @param {Function} - on click callback + */ + showForm: function (type, chart, options, callback) { + this.popup = chart.navigationBindings.popup; + // show blank popup + this.showPopup(); + // indicator form + if (type === 'indicators') { + this.indicators.addForm.call(this, chart, options, callback); + } + // annotation small toolbar + if (type === 'annotation-toolbar') { + this.annotations.addToolbar.call(this, chart, options, callback); + } + // annotation edit form + if (type === 'annotation-edit') { + this.annotations.addForm.call(this, chart, options, callback); + } + // flags form - add / edit + if (type === 'flag') { + this.annotations.addForm.call(this, chart, options, callback, true); + } + }, + /** + * Return lang definitions for popup. + * @private + * @return {Highcharts.Dictionary} - elements translations. + */ + getLangpack: function () { + return H.getOptions().lang.navigation.popup; + }, + annotations: { + /** + * Create annotation simple form. It contains two buttons + * (edit / remove) and text label. + * @private + * @param {Highcharts.Chart} - chart + * @param {Highcharts.AnnotationsOptions} - options + * @param {Function} - on click callback + */ + addToolbar: function (chart, options, callback) { + var _self = this, lang = this.lang, popupDiv = this.popup.container, showForm = this.showForm, toolbarClass = PREFIX + 'annotation-toolbar', button; + // set small size + if (popupDiv.className.indexOf(toolbarClass) === -1) { + popupDiv.className += ' ' + toolbarClass; + } + // set position + popupDiv.style.top = chart.plotTop + 10 + 'px'; + // create label + createElement(SPAN, { + innerHTML: pick( + // Advanced annotations: + lang[options.langKey] || options.langKey, + // Basic shapes: + options.shapes && options.shapes[0].type) + }, null, popupDiv); + // add buttons + button = this.addButton(popupDiv, lang.removeButton || 'remove', 'remove', callback, popupDiv); + button.className += ' ' + PREFIX + 'annotation-remove-button'; + button.style['background-image'] = 'url(' + + this.iconsURL + 'destroy.svg)'; + button = this.addButton(popupDiv, lang.editButton || 'edit', 'edit', function () { + showForm.call(_self, 'annotation-edit', chart, options, callback); + }, popupDiv); + button.className += ' ' + PREFIX + 'annotation-edit-button'; + button.style['background-image'] = 'url(' + + this.iconsURL + 'edit.svg)'; + }, + /** + * Create annotation simple form. + * It contains fields with param names. + * @private + * @param {Highcharts.Chart} chart + * Chart + * @param {Object} options + * Options + * @param {Function} callback + * On click callback + * @param {boolean} [isInit] + * If it is a form declared for init annotation + */ + addForm: function (chart, options, callback, isInit) { + var popupDiv = this.popup.container, lang = this.lang, bottomRow, lhsCol; + // create title of annotations + lhsCol = createElement('h2', { + innerHTML: lang[options.langKey] || options.langKey, + className: PREFIX + 'popup-main-title' + }, null, popupDiv); + // left column + lhsCol = createElement(DIV, { + className: PREFIX + 'popup-lhs-col ' + PREFIX + 'popup-lhs-full' + }, null, popupDiv); + bottomRow = createElement(DIV, { + className: PREFIX + 'popup-bottom-row' + }, null, popupDiv); + this.annotations.addFormFields.call(this, lhsCol, chart, '', options, [], true); + this.addButton(bottomRow, isInit ? + (lang.addButton || 'add') : + (lang.saveButton || 'save'), isInit ? 'add' : 'save', callback, popupDiv); + }, + /** + * Create annotation's form fields. + * @private + * @param {Highcharts.HTMLDOMElement} parentDiv + * Div where inputs are placed + * @param {Highcharts.Chart} chart + * Chart + * @param {string} parentNode + * Name of parent to create chain of names + * @param {Highcharts.AnnotationsOptions} options + * Options + * @param {Array} storage + * Array where all items are stored + * @param {boolean} [isRoot] + * Recursive flag for root + */ + addFormFields: function (parentDiv, chart, parentNode, options, storage, isRoot) { + var _self = this, addFormFields = this.annotations.addFormFields, addInput = this.addInput, lang = this.lang, parentFullName, titleName; + objectEach(options, function (value, option) { + // create name like params.styles.fontSize + parentFullName = parentNode !== '' ? + parentNode + '.' + option : option; + if (isObject(value)) { + if ( + // value is object of options + !isArray(value) || + // array of objects with params. i.e labels in Fibonacci + (isArray(value) && isObject(value[0]))) { + titleName = lang[option] || option; + if (!titleName.match(indexFilter)) { + storage.push([ + true, + titleName, + parentDiv + ]); + } + addFormFields.call(_self, parentDiv, chart, parentFullName, value, storage, false); + } + else { + storage.push([ + _self, + parentFullName, + 'annotation', + parentDiv, + value + ]); + } + } + }); + if (isRoot) { + storage = storage.sort(function (a) { + return a[1].match(/format/g) ? -1 : 1; + }); + storage.forEach(function (genInput) { + if (genInput[0] === true) { + createElement(SPAN, { + className: PREFIX + 'annotation-title', + innerHTML: genInput[1] + }, null, genInput[2]); + } + else { + addInput.apply(genInput[0], genInput.splice(1)); + } + }); + } + } + }, + indicators: { + /** + * Create indicator's form. It contains two tabs (ADD and EDIT) with + * content. + * @private + */ + addForm: function (chart, _options, callback) { + var tabsContainers, indicators = this.indicators, lang = this.lang, buttonParentDiv; + // add tabs + this.tabs.init.call(this, chart); + // get all tabs content divs + tabsContainers = this.popup.container + .querySelectorAll('.' + PREFIX + 'tab-item-content'); + // ADD tab + this.addColsContainer(tabsContainers[0]); + indicators.addIndicatorList.call(this, chart, tabsContainers[0], 'add'); + buttonParentDiv = tabsContainers[0] + .querySelectorAll('.' + PREFIX + 'popup-rhs-col')[0]; + this.addButton(buttonParentDiv, lang.addButton || 'add', 'add', callback, buttonParentDiv); + // EDIT tab + this.addColsContainer(tabsContainers[1]); + indicators.addIndicatorList.call(this, chart, tabsContainers[1], 'edit'); + buttonParentDiv = tabsContainers[1] + .querySelectorAll('.' + PREFIX + 'popup-rhs-col')[0]; + this.addButton(buttonParentDiv, lang.saveButton || 'save', 'edit', callback, buttonParentDiv); + this.addButton(buttonParentDiv, lang.removeButton || 'remove', 'remove', callback, buttonParentDiv); + }, + /** + * Create HTML list of all indicators (ADD mode) or added indicators + * (EDIT mode). + * @private + */ + addIndicatorList: function (chart, parentDiv, listType) { + var _self = this, lhsCol = parentDiv.querySelectorAll('.' + PREFIX + 'popup-lhs-col')[0], rhsCol = parentDiv.querySelectorAll('.' + PREFIX + 'popup-rhs-col')[0], isEdit = listType === 'edit', series = (isEdit ? + chart.series : // EDIT mode + chart.options.plotOptions // ADD mode + ), addFormFields = this.indicators.addFormFields, rhsColWrapper, indicatorList, item; + // create wrapper for list + indicatorList = createElement(UL, { + className: PREFIX + 'indicator-list' + }, null, lhsCol); + rhsColWrapper = rhsCol + .querySelectorAll('.' + PREFIX + 'popup-rhs-col-wrapper')[0]; + objectEach(series, function (serie, value) { + var seriesOptions = serie.options; + if (serie.params || + seriesOptions && seriesOptions.params) { + var indicatorNameType = _self.indicators.getNameType(serie, value), indicatorType = indicatorNameType.type; + item = createElement(LI, { + className: PREFIX + 'indicator-list', + innerHTML: indicatorNameType.name + }, null, indicatorList); + ['click', 'touchstart'].forEach(function (eventName) { + addEvent(item, eventName, function () { + addFormFields.call(_self, chart, isEdit ? serie : series[indicatorType], indicatorNameType.type, rhsColWrapper); + // add hidden input with series.id + if (isEdit && serie.options) { + createElement(INPUT, { + type: 'hidden', + name: PREFIX + 'id-' + indicatorType, + value: serie.options.id + }, null, rhsColWrapper) + .setAttribute(PREFIX + 'data-series-id', serie.options.id); + } + }); + }); + } + }); + // select first item from the list + if (indicatorList.childNodes.length > 0) { + indicatorList.childNodes[0].click(); + } + }, + /** + * Extract full name and type of requested indicator. + * @private + * @param {Highcharts.Series} series + * Series which name is needed. (EDIT mode - defaultOptions.series, ADD + * mode - indicator series). + * @param {string} - indicator type like: sma, ema, etc. + * @return {Object} - series name and type like: sma, ema, etc. + */ + getNameType: function (series, type) { + var options = series.options, seriesTypes = H.seriesTypes, + // add mode + seriesName = seriesTypes[type] && + seriesTypes[type].prototype.nameBase || type.toUpperCase(), seriesType = type; + // edit + if (options && options.type) { + seriesType = series.options.type; + seriesName = series.name; + } + return { + name: seriesName, + type: seriesType + }; + }, + /** + * List all series with unique ID. Its mandatory for indicators to set + * correct linking. + * @private + * @param {string} type + * Indicator type like: sma, ema, etc. + * @param {string} optionName + * Type of select i.e series or volume. + * @param {Highcharts.Chart} chart + * Chart + * @param {Highcharts.HTMLDOMElement} parentDiv + * Element where created HTML list is added + * @param {string} selectedOption + * optional param for default value in dropdown + */ + listAllSeries: function (type, optionName, chart, parentDiv, selectedOption) { + var selectName = PREFIX + optionName + '-type-' + type, lang = this.lang, selectBox, seriesOptions; + createElement(LABEL, { + innerHTML: lang[optionName] || optionName, + htmlFor: selectName + }, null, parentDiv); + // select type + selectBox = createElement(SELECT, { + name: selectName, + className: PREFIX + 'popup-field' + }, null, parentDiv); + selectBox.setAttribute('id', PREFIX + 'select-' + optionName); + // list all series which have id - mandatory for creating indicator + chart.series.forEach(function (serie) { + seriesOptions = serie.options; + if (!seriesOptions.params && + seriesOptions.id && + seriesOptions.id !== PREFIX + 'navigator-series') { + createElement(OPTION, { + innerHTML: seriesOptions.name || seriesOptions.id, + value: seriesOptions.id + }, null, selectBox); + } + }); + if (defined(selectedOption)) { + selectBox.value = selectedOption; + } + }, + /** + * Create typical inputs for chosen indicator. Fields are extracted from + * defaultOptions (ADD mode) or current indicator (ADD mode). Two extra + * fields are added: + * - hidden input - contains indicator type (required for callback) + * - select - list of series which can be linked with indicator + * @private + * @param {Highcharts.Chart} chart + * Chart + * @param {Highcharts.Series} series + * Indicator + * @param {string} seriesType + * Indicator type like: sma, ema, etc. + * @param {Highcharts.HTMLDOMElement} rhsColWrapper + * Element where created HTML list is added + */ + addFormFields: function (chart, series, seriesType, rhsColWrapper) { + var fields = series.params || series.options.params, getNameType = this.indicators.getNameType; + // reset current content + rhsColWrapper.innerHTML = ''; + // create title (indicator name in the right column) + createElement(H3, { + className: PREFIX + 'indicator-title', + innerHTML: getNameType(series, seriesType).name + }, null, rhsColWrapper); + // input type + createElement(INPUT, { + type: 'hidden', + name: PREFIX + 'type-' + seriesType, + value: seriesType + }, null, rhsColWrapper); + // list all series with id + this.indicators.listAllSeries.call(this, seriesType, 'series', chart, rhsColWrapper, series.linkedParent && fields.volumeSeriesID); + if (fields.volumeSeriesID) { + this.indicators.listAllSeries.call(this, seriesType, 'volume', chart, rhsColWrapper, series.linkedParent && series.linkedParent.options.id); + } + // add param fields + this.indicators.addParamInputs.call(this, chart, 'params', fields, seriesType, rhsColWrapper); + }, + /** + * Recurent function which lists all fields, from params object and + * create them as inputs. Each input has unique `data-name` attribute, + * which keeps chain of fields i.e params.styles.fontSize. + * @private + * @param {Highcharts.Chart} chart + * Chart + * @param {string} parentNode + * Name of parent to create chain of names + * @param {Highcharts.PopupFieldsDictionary} fields + * Params which are based for input create + * @param {string} type + * Indicator type like: sma, ema, etc. + * @param {Highcharts.HTMLDOMElement} parentDiv + * Element where created HTML list is added + */ + addParamInputs: function (chart, parentNode, fields, type, parentDiv) { + var _self = this, addParamInputs = this.indicators.addParamInputs, addInput = this.addInput, parentFullName; + objectEach(fields, function (value, fieldName) { + // create name like params.styles.fontSize + parentFullName = parentNode + '.' + fieldName; + if (isObject(value)) { + addParamInputs.call(_self, chart, parentFullName, value, type, parentDiv); + } + else if ( + // skip volume field which is created by addFormFields + parentFullName !== 'params.volumeSeriesID') { + addInput.call(_self, parentFullName, type, parentDiv, [value, 'text'] // all inputs are text type + ); + } + }); + }, + /** + * Get amount of indicators added to chart. + * @private + * @return {number} - Amount of indicators + */ + getAmount: function () { + var series = this.series, counter = 0; + objectEach(series, function (serie) { + var seriesOptions = serie.options; + if (serie.params || + seriesOptions && seriesOptions.params) { + counter++; + } + }); + return counter; + } + }, + tabs: { + /** + * Init tabs. Create tab menu items, tabs containers + * @private + * @param {Highcharts.Chart} chart + * Reference to current chart + */ + init: function (chart) { + var tabs = this.tabs, indicatorsCount = this.indicators.getAmount.call(chart), firstTab; // run by default + // create menu items + firstTab = tabs.addMenuItem.call(this, 'add'); + tabs.addMenuItem.call(this, 'edit', indicatorsCount); + // create tabs containers + tabs.addContentItem.call(this, 'add'); + tabs.addContentItem.call(this, 'edit'); + tabs.switchTabs.call(this, indicatorsCount); + // activate first tab + tabs.selectTab.call(this, firstTab, 0); + }, + /** + * Create tab menu item + * @private + * @param {string} tabName + * `add` or `edit` + * @param {number} [disableTab] + * Disable tab when 0 + * @return {Highcharts.HTMLDOMElement} + * Created HTML tab-menu element + */ + addMenuItem: function (tabName, disableTab) { + var popupDiv = this.popup.container, className = PREFIX + 'tab-item', lang = this.lang, menuItem; + if (disableTab === 0) { + className += ' ' + PREFIX + 'tab-disabled'; + } + // tab 1 + menuItem = createElement(SPAN, { + innerHTML: lang[tabName + 'Button'] || tabName, + className: className + }, null, popupDiv); + menuItem.setAttribute(PREFIX + 'data-tab-type', tabName); + return menuItem; + }, + /** + * Create tab content + * @private + * @return {HTMLDOMElement} - created HTML tab-content element + */ + addContentItem: function () { + var popupDiv = this.popup.container; + return createElement(DIV, { + className: PREFIX + 'tab-item-content' + }, null, popupDiv); + }, + /** + * Add click event to each tab + * @private + * @param {number} disableTab + * Disable tab when 0 + */ + switchTabs: function (disableTab) { + var _self = this, popupDiv = this.popup.container, tabs = popupDiv.querySelectorAll('.' + PREFIX + 'tab-item'), dataParam; + tabs.forEach(function (tab, i) { + dataParam = tab.getAttribute(PREFIX + 'data-tab-type'); + if (dataParam === 'edit' && disableTab === 0) { + return; + } + ['click', 'touchstart'].forEach(function (eventName) { + addEvent(tab, eventName, function () { + // reset class on other elements + _self.tabs.deselectAll.call(_self); + _self.tabs.selectTab.call(_self, this, i); + }); + }); + }); + }, + /** + * Set tab as visible + * @private + * @param {globals.Element} - current tab + * @param {number} - Index of tab in menu + */ + selectTab: function (tab, index) { + var allTabs = this.popup.container + .querySelectorAll('.' + PREFIX + 'tab-item-content'); + tab.className += ' ' + PREFIX + 'tab-item-active'; + allTabs[index].className += ' ' + PREFIX + 'tab-item-show'; + }, + /** + * Set all tabs as invisible. + * @private + */ + deselectAll: function () { + var popupDiv = this.popup.container, tabs = popupDiv + .querySelectorAll('.' + PREFIX + 'tab-item'), tabsContent = popupDiv + .querySelectorAll('.' + PREFIX + 'tab-item-content'), i; + for (i = 0; i < tabs.length; i++) { + tabs[i].classList.remove(PREFIX + 'tab-item-active'); + tabsContent[i].classList.remove(PREFIX + 'tab-item-show'); + } + } + } + }; + addEvent(NavigationBindings, 'showPopup', function (config) { + if (!this.popup) { + // Add popup to main container + this.popup = new H.Popup(this.chart.container, (this.chart.options.navigation.iconsURL || + (this.chart.options.stockTools && + this.chart.options.stockTools.gui.iconsURL) || + 'https://code.highcharts.com/8.1.0/gfx/stock-icons/')); + } + this.popup.showForm(config.formType, this.chart, config.options, config.onSubmit); + }); + addEvent(NavigationBindings, 'closePopup', function () { + if (this.popup) { + this.popup.closePopup(); + } + }); + + }); + _registerModule(_modules, 'masters/modules/annotations-advanced.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/annotations.js b/librerias/gantt/code/modules/annotations.js new file mode 100644 index 0000000..21d1ac1 --- /dev/null +++ b/librerias/gantt/code/modules/annotations.js @@ -0,0 +1,103 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Annotations module + + (c) 2009-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(c){"object"===typeof module&&module.exports?(c["default"]=c,module.exports=c):"function"===typeof define&&define.amd?define("highcharts/modules/annotations",["highcharts"],function(p){c(p);c.Highcharts=p;return c}):c("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(c){function p(c,a,m,t){c.hasOwnProperty(a)||(c[a]=t.apply(null,m))}c=c?c._modules:{};p(c,"annotations/eventEmitterMixin.js",[c["parts/Globals.js"],c["parts/Utilities.js"]],function(c,a){var k=a.addEvent,t=a.fireEvent, +f=a.inArray,d=a.objectEach,B=a.pick,r=a.removeEvent;return{addEvents:function(){var b=this,g=function(g){k(g,"mousedown",function(e){b.onMouseDown(e)})};g(this.graphic.element);(b.labels||[]).forEach(function(b){b.options.useHTML&&b.graphic.text&&g(b.graphic.text.element)});d(b.options.events,function(g,e){var h=function(h){"click"===e&&b.cancelClick||g.call(b,b.chart.pointer.normalize(h),b.target)};if(-1===f(e,b.nonDOMEvents||[]))b.graphic.on(e,h);else k(b,e,h)});if(b.options.draggable&&(k(b,"drag", +b.onDrag),!b.graphic.renderer.styledMode)){var a={cursor:{x:"ew-resize",y:"ns-resize",xy:"move"}[b.options.draggable]};b.graphic.css(a);(b.labels||[]).forEach(function(b){b.options.useHTML&&b.graphic.text&&b.graphic.text.css(a)})}b.isUpdating||t(b,"add")},removeDocEvents:function(){this.removeDrag&&(this.removeDrag=this.removeDrag());this.removeMouseUp&&(this.removeMouseUp=this.removeMouseUp())},onMouseDown:function(b){var g=this,d=g.chart.pointer;b.preventDefault&&b.preventDefault();if(2!==b.button){b= +d.normalize(b);var a=b.chartX;var e=b.chartY;g.cancelClick=!1;g.chart.hasDraggedAnnotation=!0;g.removeDrag=k(c.doc,"mousemove",function(b){g.hasDragged=!0;b=d.normalize(b);b.prevChartX=a;b.prevChartY=e;t(g,"drag",b);a=b.chartX;e=b.chartY});g.removeMouseUp=k(c.doc,"mouseup",function(b){g.cancelClick=g.hasDragged;g.hasDragged=!1;g.chart.hasDraggedAnnotation=!1;t(B(g.target,g),"afterUpdate");g.onMouseUp(b)})}},onMouseUp:function(b){var g=this.chart;b=this.target||this;var d=g.options.annotations;g=g.annotations.indexOf(b); +this.removeDocEvents();d[g]=b.options},onDrag:function(b){if(this.chart.isInsidePlot(b.chartX-this.chart.plotLeft,b.chartY-this.chart.plotTop)){var g=this.mouseMoveToTranslation(b);"x"===this.options.draggable&&(g.y=0);"y"===this.options.draggable&&(g.x=0);this.points.length?this.translate(g.x,g.y):(this.shapes.forEach(function(b){b.translate(g.x,g.y)}),this.labels.forEach(function(b){b.translate(g.x,g.y)}));this.redraw(!1)}},mouseMoveToRadians:function(b,g,d){var a=b.prevChartY-d,e=b.prevChartX- +g;d=b.chartY-d;b=b.chartX-g;this.chart.inverted&&(g=e,e=a,a=g,g=b,b=d,d=g);return Math.atan2(d,b)-Math.atan2(a,e)},mouseMoveToTranslation:function(b){var g=b.chartX-b.prevChartX;b=b.chartY-b.prevChartY;if(this.chart.inverted){var d=b;b=g;g=d}return{x:g,y:b}},mouseMoveToScale:function(b,g,d){g=(b.chartX-g||1)/(b.prevChartX-g||1);b=(b.chartY-d||1)/(b.prevChartY-d||1);this.chart.inverted&&(d=b,b=g,g=d);return{x:g,y:b}},destroy:function(){this.removeDocEvents();r(this);this.hcEvents=null}}});p(c,"annotations/ControlPoint.js", +[c["parts/Utilities.js"],c["annotations/eventEmitterMixin.js"]],function(c,a){var k=c.merge,t=c.pick;return function(){function f(d,f,c,b){this.addEvents=a.addEvents;this.graphic=void 0;this.mouseMoveToRadians=a.mouseMoveToRadians;this.mouseMoveToScale=a.mouseMoveToScale;this.mouseMoveToTranslation=a.mouseMoveToTranslation;this.onDrag=a.onDrag;this.onMouseDown=a.onMouseDown;this.onMouseUp=a.onMouseUp;this.removeDocEvents=a.removeDocEvents;this.nonDOMEvents=["drag"];this.chart=d;this.target=f;this.options= +c;this.index=t(c.index,b)}f.prototype.setVisibility=function(d){this.graphic.attr("visibility",d?"visible":"hidden");this.options.visible=d};f.prototype.render=function(){var d=this.chart,a=this.options;this.graphic=d.renderer.symbol(a.symbol,0,0,a.width,a.height).add(d.controlPointsGroup).css(a.style);this.setVisibility(a.visible);this.addEvents()};f.prototype.redraw=function(d){this.graphic[d?"animate":"attr"](this.options.positioner.call(this,this.target))};f.prototype.destroy=function(){a.destroy.call(this); +this.graphic&&(this.graphic=this.graphic.destroy());this.options=this.target=this.chart=null};f.prototype.update=function(d){var a=this.chart,f=this.target,b=this.index;d=k(!0,this.options,d);this.destroy();this.constructor(a,f,d,b);this.render(a.controlPointsGroup);this.redraw()};return f}()});p(c,"annotations/MockPoint.js",[c["parts/Globals.js"],c["parts/Utilities.js"]],function(c,a){var k=a.defined,t=a.fireEvent;return function(){function a(d,a,f){this.y=this.x=this.plotY=this.plotX=this.isInside= +void 0;this.mock=!0;this.series={visible:!0,chart:d,getPlotBox:c.Series.prototype.getPlotBox};this.target=a||null;this.options=f;this.applyOptions(this.getOptions())}a.fromPoint=function(d){return new a(d.series.chart,null,{x:d.x,y:d.y,xAxis:d.series.xAxis,yAxis:d.series.yAxis})};a.pointToPixels=function(d,a){var c=d.series,b=c.chart,g=d.plotX,f=d.plotY;b.inverted&&(d.mock?(g=d.plotY,f=d.plotX):(g=b.plotWidth-d.plotY,f=b.plotHeight-d.plotX));c&&!a&&(d=c.getPlotBox(),g+=d.translateX,f+=d.translateY); +return{x:g,y:f}};a.pointToOptions=function(d){return{x:d.x,y:d.y,xAxis:d.series.xAxis,yAxis:d.series.yAxis}};a.prototype.hasDynamicOptions=function(){return"function"===typeof this.options};a.prototype.getOptions=function(){return this.hasDynamicOptions()?this.options(this.target):this.options};a.prototype.applyOptions=function(d){this.command=d.command;this.setAxis(d,"x");this.setAxis(d,"y");this.refresh()};a.prototype.setAxis=function(d,a){a+="Axis";d=d[a];var f=this.series.chart;this.series[a]= +d instanceof c.Axis?d:k(d)?f[a][d]||f.get(d):null};a.prototype.toAnchor=function(){var a=[this.plotX,this.plotY,0,0];this.series.chart.inverted&&(a[0]=this.plotY,a[1]=this.plotX);return a};a.prototype.getLabelConfig=function(){return{x:this.x,y:this.y,point:this}};a.prototype.isInsidePlot=function(){var a=this.plotX,c=this.plotY,f=this.series.xAxis,b=this.series.yAxis,g={x:a,y:c,isInsidePlot:!0};f&&(g.isInsidePlot=k(a)&&0<=a&&a<=f.len);b&&(g.isInsidePlot=g.isInsidePlot&&k(c)&&0<=c&&c<=b.len);t(this.series.chart, +"afterIsInsidePlot",g);return g.isInsidePlot};a.prototype.refresh=function(){var a=this.series,c=a.xAxis;a=a.yAxis;var f=this.getOptions();c?(this.x=f.x,this.plotX=c.toPixels(f.x,!0)):(this.x=null,this.plotX=f.x);a?(this.y=f.y,this.plotY=a.toPixels(f.y,!0)):(this.y=null,this.plotY=f.y);this.isInside=this.isInsidePlot()};a.prototype.translate=function(a,f,c,b){this.hasDynamicOptions()||(this.plotX+=c,this.plotY+=b,this.refreshOptions())};a.prototype.scale=function(a,c,f,b){if(!this.hasDynamicOptions()){var g= +this.plotY*b;this.plotX=(1-f)*a+this.plotX*f;this.plotY=(1-b)*c+g;this.refreshOptions()}};a.prototype.rotate=function(a,f,c){if(!this.hasDynamicOptions()){var b=Math.cos(c);c=Math.sin(c);var g=this.plotX,d=this.plotY;g-=a;d-=f;this.plotX=g*b-d*c+a;this.plotY=g*c+d*b+f;this.refreshOptions()}};a.prototype.refreshOptions=function(){var a=this.series,c=a.xAxis;a=a.yAxis;this.x=this.options.x=c?this.options.x=c.toValue(this.plotX,!0):this.plotX;this.y=this.options.y=a?a.toValue(this.plotY,!0):this.plotY}; +return a}()});p(c,"annotations/controllable/controllableMixin.js",[c["parts/Utilities.js"],c["annotations/ControlPoint.js"],c["annotations/MockPoint.js"],c["parts/Tooltip.js"]],function(c,a,m,t){var f=c.isObject,d=c.isString,k=c.merge,r=c.splat;return{init:function(b,a,c){this.annotation=b;this.chart=b.chart;this.options=a;this.points=[];this.controlPoints=[];this.index=c;this.linkPoints();this.addControlPoints()},attr:function(){this.graphic.attr.apply(this.graphic,arguments)},getPointsOptions:function(){var b= +this.options;return b.points||b.point&&r(b.point)},attrsFromOptions:function(b){var a=this.constructor.attrsMap,c={},d,e=this.chart.styledMode;for(d in b){var h=a[d];!h||e&&-1!==["fill","stroke","stroke-width"].indexOf(h)||(c[h]=b[d])}return c},anchor:function(b){var a=b.series.getPlotBox();b=b.mock?b.toAnchor():t.prototype.getAnchor.call({chart:b.series.chart},b);b={x:b[0]+(this.options.x||0),y:b[1]+(this.options.y||0),height:b[2]||0,width:b[3]||0};return{relativePosition:b,absolutePosition:k(b, +{x:b.x+a.translateX,y:b.y+a.translateY})}},point:function(b,a){if(b&&b.series)return b;a&&null!==a.series||(f(b)?a=new m(this.chart,this,b):d(b)?a=this.chart.get(b)||null:"function"===typeof b&&(a=b.call(a,this),a=a.series?a:new m(this.chart,this,b)));return a},linkPoints:function(){var b=this.getPointsOptions(),a=this.points,c=b&&b.length||0,d;for(d=0;dd&&("right"===e?b.align="left":b.x=-d);d=c+n.width-l;d>a.plotWidth&&("left"===e?b.align="right": +b.x=a.plotWidth-d);d=u+l;0>d&&("bottom"===h?b.verticalAlign="top":b.y=-d);d=u+n.height-l;d>a.plotHeight&&("top"===h?b.verticalAlign="bottom":b.y=a.plotHeight-d);return b};p.attrsMap={backgroundColor:"fill",borderColor:"stroke",borderWidth:"stroke-width",zIndex:"zIndex",borderRadius:"r",padding:"padding"};b(!0,p.prototype,m,{translatePoint:function(a,b){m.translatePoint.call(this,a,b,0)},translate:function(a,b){var c=this.annotation.chart,e=this.annotation.userOptions,d=c.annotations.indexOf(this.annotation); +d=c.options.annotations[d];c.inverted&&(c=a,a=b,b=c);this.options.x+=a;this.options.y+=b;d[this.collection][this.index].x=this.options.x;d[this.collection][this.index].y=this.options.y;e[this.collection][this.index].x=this.options.x;e[this.collection][this.index].y=this.options.y},render:function(a){var b=this.options,c=this.attrsFromOptions(b),d=b.style;this.graphic=this.annotation.chart.renderer.label("",0,-9999,b.shape,null,null,b.useHTML,null,"annotation-label").attr(c).add(a);this.annotation.chart.styledMode|| +("contrast"===d.color&&(d.color=this.annotation.chart.renderer.getContrast(-1u&&(u=-d-u);ub+d?n.push(["L",a+h,b+d]):fa+c&&n.push(["L",a+c,b+d/2])}return n||[]};return p});p(c,"annotations/controllable/ControllableImage.js",[c["parts/Utilities.js"], +c["annotations/controllable/controllableMixin.js"],c["annotations/controllable/ControllableLabel.js"]],function(c,a,m){c=c.merge;var k=function(a,c,k){this.init(a,c,k);this.collection="shapes"};k.attrsMap={width:"width",height:"height",zIndex:"zIndex"};c(!0,k.prototype,a,{type:"image",translate:a.translateShape,render:function(c){var d=this.attrsFromOptions(this.options),f=this.options;this.graphic=this.annotation.chart.renderer.image(f.src,0,-9E9,f.width,f.height).attr(d).add(c);this.graphic.width= +f.width;this.graphic.height=f.height;a.render.call(this)},redraw:function(c){var d=this.anchor(this.points[0]);if(d=m.prototype.position.call(this,d))this.graphic[c?"animate":"attr"]({x:d.x,y:d.y});else this.graphic.attr({x:0,y:-9E9});this.graphic.placed=!!d;a.redraw.call(this,c)}});return k});p(c,"annotations/annotations.src.js",[c["parts/Globals.js"],c["parts/Utilities.js"],c["annotations/controllable/controllableMixin.js"],c["annotations/controllable/ControllableRect.js"],c["annotations/controllable/ControllableCircle.js"], +c["annotations/controllable/ControllablePath.js"],c["annotations/controllable/ControllableImage.js"],c["annotations/controllable/ControllableLabel.js"],c["annotations/eventEmitterMixin.js"],c["annotations/MockPoint.js"],c["annotations/ControlPoint.js"]],function(c,a,m,t,f,d,p,r,b,g,z){var k=a.addEvent,e=a.defined,h=a.destroyObjectProperties,l=a.erase,q=a.extend,y=a.find,v=a.fireEvent,n=a.merge,u=a.pick,C=a.splat;a=a.wrap;var A=c.Chart.prototype,w=c.Annotation=function(a,b){this.chart=a;this.points= +[];this.controlPoints=[];this.coll="annotations";this.labels=[];this.shapes=[];this.options=n(this.defaultOptions,b);this.userOptions=b;b=this.getLabelsAndShapesOptions(this.options,b);this.options.labels=b.labels;this.options.shapes=b.shapes;this.init(a,this.options)};n(!0,w.prototype,m,b,{nonDOMEvents:["add","afterUpdate","drag","remove"],defaultOptions:{visible:!0,draggable:"xy",labelOptions:{align:"center",allowOverlap:!1,backgroundColor:"rgba(0, 0, 0, 0.75)",borderColor:"black",borderRadius:3, +borderWidth:1,className:"",crop:!1,formatter:function(){return e(this.y)?this.y:"Annotation label"},overflow:"justify",padding:5,shadow:!1,shape:"callout",style:{fontSize:"11px",fontWeight:"normal",color:"contrast"},useHTML:!1,verticalAlign:"bottom",x:0,y:-16},shapeOptions:{stroke:"rgba(0, 0, 0, 0.75)",strokeWidth:1,fill:"rgba(0, 0, 0, 0.75)",r:0,snap:2},controlPointOptions:{symbol:"circle",width:10,height:10,style:{stroke:"black","stroke-width":2,fill:"white"},visible:!1,events:{}},events:{},zIndex:6}, +init:function(){this.linkPoints();this.addControlPoints();this.addShapes();this.addLabels();this.setLabelCollector()},getLabelsAndShapesOptions:function(a,b){var c={};["labels","shapes"].forEach(function(d){a[d]&&(c[d]=C(b[d]).map(function(b,c){return n(a[d][c],b)}))});return c},addShapes:function(){(this.options.shapes||[]).forEach(function(a,b){a=this.initShape(a,b);n(!0,this.options.shapes[b],a.options)},this)},addLabels:function(){(this.options.labels||[]).forEach(function(a,b){a=this.initLabel(a, +b);n(!0,this.options.labels[b],a.options)},this)},addClipPaths:function(){this.setClipAxes();this.clipXAxis&&this.clipYAxis&&(this.clipRect=this.chart.renderer.clipRect(this.getClipBox()))},setClipAxes:function(){var a=this.chart.xAxis,b=this.chart.yAxis,c=(this.options.labels||[]).concat(this.options.shapes||[]).reduce(function(c,d){return[a[d&&d.point&&d.point.xAxis]||c[0],b[d&&d.point&&d.point.yAxis]||c[1]]},[]);this.clipXAxis=c[0];this.clipYAxis=c[1]},getClipBox:function(){if(this.clipXAxis&& +this.clipYAxis)return{x:this.clipXAxis.left,y:this.clipYAxis.top,width:this.clipXAxis.width,height:this.clipYAxis.height}},setLabelCollector:function(){var a=this;a.labelCollector=function(){return a.labels.reduce(function(a,b){b.options.allowOverlap||a.push(b.graphic);return a},[])};a.chart.labelCollectors.push(a.labelCollector)},setOptions:function(a){this.options=n(this.defaultOptions,a)},redraw:function(a){this.linkPoints();this.graphic||this.render();this.clipRect&&this.clipRect.animate(this.getClipBox()); +this.redrawItems(this.shapes,a);this.redrawItems(this.labels,a);m.redraw.call(this,a)},redrawItems:function(a,b){for(var c=a.length;c--;)this.redrawItem(a[c],b)},renderItems:function(a){for(var b=a.length;b--;)this.renderItem(a[b])},render:function(){var a=this.chart.renderer;this.graphic=a.g("annotation").attr({zIndex:this.options.zIndex,visibility:this.options.visible?"visible":"hidden"}).add();this.shapesGroup=a.g("annotation-shapes").add(this.graphic).clip(this.chart.plotBoxClip);this.labelsGroup= +a.g("annotation-labels").attr({translateX:0,translateY:0}).add(this.graphic);this.addClipPaths();this.clipRect&&this.graphic.clip(this.clipRect);this.renderItems(this.shapes);this.renderItems(this.labels);this.addEvents();m.render.call(this)},setVisibility:function(a){var b=this.options;a=u(a,!b.visible);this.graphic.attr("visibility",a?"visible":"hidden");a||this.setControlPointsVisibility(!1);b.visible=a},setControlPointsVisibility:function(a){var b=function(b){b.setControlPointsVisibility(a)}; +m.setControlPointsVisibility.call(this,a);this.shapes.forEach(b);this.labels.forEach(b)},destroy:function(){var a=this.chart,c=function(a){a.destroy()};this.labels.forEach(c);this.shapes.forEach(c);this.clipYAxis=this.clipXAxis=null;l(a.labelCollectors,this.labelCollector);b.destroy.call(this);m.destroy.call(this);h(this,a)},remove:function(){return this.chart.removeAnnotation(this)},update:function(a,b){var c=this.chart,d=this.getLabelsAndShapesOptions(this.userOptions,a),e=c.annotations.indexOf(this); +a=n(!0,this.userOptions,a);a.labels=d.labels;a.shapes=d.shapes;this.destroy();this.constructor(c,a);c.options.annotations[e]=a;this.isUpdating=!0;u(b,!0)&&c.redraw();v(this,"afterUpdate");this.isUpdating=!1},initShape:function(a,b){a=n(this.options.shapeOptions,{controlPointOptions:this.options.controlPointOptions},a);b=new w.shapesMap[a.type](this,a,b);b.itemType="shape";this.shapes.push(b);return b},initLabel:function(a,b){a=n(this.options.labelOptions,{controlPointOptions:this.options.controlPointOptions}, +a);b=new r(this,a,b);b.itemType="label";this.labels.push(b);return b},redrawItem:function(a,b){a.linkPoints();a.shouldBeDrawn()?(a.graphic||this.renderItem(a),a.redraw(u(b,!0)&&a.graphic.placed),a.points.length&&this.adjustVisibility(a)):this.destroyItem(a)},adjustVisibility:function(a){var b=!1,c=a.graphic;a.points.forEach(function(a){!1!==a.series.visible&&!1!==a.visible&&(b=!0)});b?"hidden"===c.visibility&&c.show():c.hide()},destroyItem:function(a){l(this[a.itemType+"s"],a);a.destroy()},renderItem:function(a){a.render("label"=== +a.itemType?this.labelsGroup:this.shapesGroup)}});w.shapesMap={rect:t,circle:f,path:d,image:p};w.types={};w.MockPoint=g;w.ControlPoint=z;c.extendAnnotation=function(a,b,c,d){b=b||w;n(!0,a.prototype,b.prototype,c);a.prototype.defaultOptions=n(a.prototype.defaultOptions,d||{})};q(A,{initAnnotation:function(a){a=new (w.types[a.type]||w)(this,a);this.annotations.push(a);return a},addAnnotation:function(a,b){a=this.initAnnotation(a);this.options.annotations.push(a.options);u(b,!0)&&a.redraw();return a}, +removeAnnotation:function(a){var b=this.annotations,c="annotations"===a.coll?a:y(b,function(b){return b.options.id===a});c&&(v(c,"remove"),l(this.options.annotations,c.options),l(b,c),c.destroy())},drawAnnotations:function(){this.plotBoxClip.attr(this.plotBox);this.annotations.forEach(function(a){a.redraw()})}});A.collectionsWithUpdate.push("annotations");A.collectionsWithInit.annotations=[A.addAnnotation];A.callbacks.push(function(a){a.annotations=[];a.options.annotations||(a.options.annotations= +[]);a.plotBoxClip=this.renderer.clipRect(this.plotBox);a.controlPointsGroup=a.renderer.g("control-points").attr({zIndex:99}).clip(a.plotBoxClip).add();a.options.annotations.forEach(function(b,c){b=a.initAnnotation(b);a.options.annotations[c]=b.options});a.drawAnnotations();k(a,"redraw",a.drawAnnotations);k(a,"destroy",function(){a.plotBoxClip.destroy();a.controlPointsGroup.destroy()})});a(c.Pointer.prototype,"onContainerMouseDown",function(a){this.chart.hasDraggedAnnotation||a.apply(this,Array.prototype.slice.call(arguments, +1))})});p(c,"mixins/navigation.js",[],function(){return{initUpdate:function(c){c.navigation||(c.navigation={updates:[],update:function(a,c){this.updates.forEach(function(k){k.update.call(k.context,a,c)})}})},addUpdate:function(c,a){a.navigation||this.initUpdate(a);a.navigation.updates.push({update:c,context:a})}}});p(c,"annotations/navigationBindings.js",[c["parts/Globals.js"],c["parts/Utilities.js"],c["mixins/navigation.js"]],function(c,a,m){function k(a){var b=a.prototype.defaultOptions.events&& +a.prototype.defaultOptions.events.click;e(!0,a.prototype.defaultOptions.events,{click:function(a){var c=this,d=c.chart.navigationBindings,e=d.activeAnnotation;b&&b.click.call(c,a);e!==c?(d.deselectAnnotation(),d.activeAnnotation=c,c.setControlPointsVisibility(!0),r(d,"showPopup",{annotation:c,formType:"annotation-toolbar",options:d.annotationToFields(c),onSubmit:function(a){var b={};"remove"===a.actionType?(d.activeAnnotation=!1,d.chart.removeAnnotation(c)):(d.fieldsToOptions(a.fields,b),d.deselectAnnotation(), +a=b.typeOptions,"measure"===c.options.type&&(a.crosshairY.enabled=0!==a.crosshairY.strokeWidth,a.crosshairX.enabled=0!==a.crosshairX.strokeWidth),c.update(b))}})):(d.deselectAnnotation(),r(d,"closePopup"));a.activeAnnotation=!0}})}var f=a.addEvent,d=a.attr,p=a.format,r=a.fireEvent,b=a.isArray,g=a.isFunction,z=a.isNumber,x=a.isObject,e=a.merge,h=a.objectEach,l=a.pick,q=c.doc,y=c.win,v=function(){function a(a,b){this.selectedButton=this.boundClassNames=void 0;this.chart=a;this.options=b;this.eventsToUnbind= +[];this.container=q.getElementsByClassName(this.options.bindingsClassName||"")}a.prototype.initEvents=function(){var a=this,b=a.chart,c=a.container,d=a.options;a.boundClassNames={};h(d.bindings||{},function(b){a.boundClassNames[b.className]=b});[].forEach.call(c,function(b){a.eventsToUnbind.push(f(b,"click",function(c){var d=a.getButtonEvents(b,c);d&&a.bindingsButtonClick(d.button,d.events,c)}))});h(d.events||{},function(b,c){g(b)&&a.eventsToUnbind.push(f(a,c,b))});a.eventsToUnbind.push(f(b.container, +"click",function(c){!b.cancelClick&&b.isInsidePlot(c.chartX-b.plotLeft,c.chartY-b.plotTop)&&a.bindingsChartClick(this,c)}));a.eventsToUnbind.push(f(b.container,"mousemove",function(b){a.bindingsContainerMouseMove(this,b)}))};a.prototype.initUpdate=function(){var a=this;m.addUpdate(function(b){a.update(b)},this.chart)};a.prototype.bindingsButtonClick=function(a,b,c){var d=this.chart;this.selectedButtonElement&&(r(this,"deselectButton",{button:this.selectedButtonElement}),this.nextEvent&&(this.currentUserDetails&& +"annotations"===this.currentUserDetails.coll&&d.removeAnnotation(this.currentUserDetails),this.mouseMoveEvent=this.nextEvent=!1));this.selectedButton=b;this.selectedButtonElement=a;r(this,"selectButton",{button:a});b.init&&b.init.call(this,a,c);(b.start||b.steps)&&d.renderer.boxWrapper.addClass("highcharts-draw-mode")};a.prototype.bindingsChartClick=function(a,b){a=this.chart;var c=this.selectedButton;a=a.renderer.boxWrapper;var d;if(d=this.activeAnnotation&&!b.activeAnnotation&&b.target.parentNode){a:{d= +b.target;var e=y.Element.prototype,h=e.matches||e.msMatchesSelector||e.webkitMatchesSelector,f=null;if(e.closest)f=e.closest.call(d,".highcharts-popup");else{do{if(h.call(d,".highcharts-popup"))break a;d=d.parentElement||d.parentNode}while(null!==d&&1===d.nodeType)}d=f}d=!d}d&&(r(this,"closePopup"),this.deselectAnnotation());c&&c.start&&(this.nextEvent?(this.nextEvent(b,this.currentUserDetails),this.steps&&(this.stepIndex++,c.steps[this.stepIndex]?this.mouseMoveEvent=this.nextEvent=c.steps[this.stepIndex]: +(r(this,"deselectButton",{button:this.selectedButtonElement}),a.removeClass("highcharts-draw-mode"),c.end&&c.end.call(this,b,this.currentUserDetails),this.mouseMoveEvent=this.nextEvent=!1,this.selectedButton=null))):(this.currentUserDetails=c.start.call(this,b),c.steps?(this.stepIndex=0,this.steps=!0,this.mouseMoveEvent=this.nextEvent=c.steps[this.stepIndex]):(r(this,"deselectButton",{button:this.selectedButtonElement}),a.removeClass("highcharts-draw-mode"),this.steps=!1,this.selectedButton=null, +c.end&&c.end.call(this,b,this.currentUserDetails))))};a.prototype.bindingsContainerMouseMove=function(a,b){this.mouseMoveEvent&&this.mouseMoveEvent(b,this.currentUserDetails)};a.prototype.fieldsToOptions=function(a,b){h(a,function(a,c){var d=parseFloat(a),e=c.split("."),h=b,f=e.length-1;!z(d)||a.match(/px/g)||c.match(/format/g)||(a=d);""!==a&&"undefined"!==a&&e.forEach(function(b,c){var d=l(e[c+1],"");f===c?h[b]=a:(h[b]||(h[b]=d.match(/\d/g)?[]:{}),h=h[b])})});return b};a.prototype.deselectAnnotation= +function(){this.activeAnnotation&&(this.activeAnnotation.setControlPointsVisibility(!1),this.activeAnnotation=!1)};a.prototype.annotationToFields=function(c){function d(a,e,f,l){if(f&&-1===v.indexOf(e)&&(0<=(f.indexOf&&f.indexOf(e))||f[e]||!0===f))if(b(a))l[e]=[],a.forEach(function(a,b){x(a)?(l[e][b]={},h(a,function(a,c){d(a,c,n[e],l[e][b])})):d(a,0,n[e],l[e])});else if(x(a)){var u={};b(l)?(l.push(u),u[e]={},u=u[e]):l[e]=u;h(a,function(a,b){d(a,b,0===e?f:n[e],u)})}else"format"===e?l[e]=[p(a,c.labels[0].points[0]).toString(), +"text"]:b(l)?l.push([a,g(a)]):l[e]=[a,g(a)]}var e=c.options,f=a.annotationsEditable,n=f.nestedOptions,g=this.utils.getFieldType,u=l(e.type,e.shapes&&e.shapes[0]&&e.shapes[0].type,e.labels&&e.labels[0]&&e.labels[0].itemType,"label"),v=a.annotationsNonEditable[e.langKey]||[],q={langKey:e.langKey,type:u};h(e,function(a,b){"typeOptions"===b?(q[b]={},h(e[b],function(a,c){d(a,c,n,q[b],!0)})):d(a,b,f[u],q)});return q};a.prototype.getClickedClassNames=function(a,b){var c=b.target;b=[];for(var e;c&&((e=d(c, +"class"))&&(b=b.concat(e.split(" ").map(function(a){return[a,c]}))),c=c.parentNode,c!==a););return b};a.prototype.getButtonEvents=function(a,b){var c=this,d;this.getClickedClassNames(a,b).forEach(function(a){c.boundClassNames[a[0]]&&!d&&(d={events:c.boundClassNames[a[0]],button:a[1]})});return d};a.prototype.update=function(a){this.options=e(!0,this.options,a);this.removeEvents();this.initEvents()};a.prototype.removeEvents=function(){this.eventsToUnbind.forEach(function(a){a()})};a.prototype.destroy= +function(){this.removeEvents()};a.annotationsEditable={nestedOptions:{labelOptions:["style","format","backgroundColor"],labels:["style"],label:["style"],style:["fontSize","color"],background:["fill","strokeWidth","stroke"],innerBackground:["fill","strokeWidth","stroke"],outerBackground:["fill","strokeWidth","stroke"],shapeOptions:["fill","strokeWidth","stroke"],shapes:["fill","strokeWidth","stroke"],line:["strokeWidth","stroke"],backgroundColors:[!0],connector:["fill","strokeWidth","stroke"],crosshairX:["strokeWidth", +"stroke"],crosshairY:["strokeWidth","stroke"]},circle:["shapes"],verticalLine:[],label:["labelOptions"],measure:["background","crosshairY","crosshairX"],fibonacci:[],tunnel:["background","line","height"],pitchfork:["innerBackground","outerBackground"],rect:["shapes"],crookedLine:[],basicAnnotation:[]};a.annotationsNonEditable={rectangle:["crosshairX","crosshairY","label"]};return a}();v.prototype.utils={updateRectSize:function(a,b){var c=b.chart,d=b.options.typeOptions,e=c.pointer.getCoordinates(a); +a=e.xAxis[0].value-d.point.x;d=d.point.y-e.yAxis[0].value;b.update({typeOptions:{background:{width:c.inverted?d:a,height:c.inverted?a:d}}})},getFieldType:function(a){return{string:"text",number:"number","boolean":"checkbox"}[typeof a]}};c.Chart.prototype.initNavigationBindings=function(){var a=this.options;a&&a.navigation&&a.navigation.bindings&&(this.navigationBindings=new v(this,a.navigation),this.navigationBindings.initEvents(),this.navigationBindings.initUpdate())};f(c.Chart,"load",function(){this.initNavigationBindings()}); +f(c.Chart,"destroy",function(){this.navigationBindings&&this.navigationBindings.destroy()});f(v,"deselectButton",function(){this.selectedButtonElement=null});f(c.Annotation,"remove",function(){this.chart.navigationBindings&&this.chart.navigationBindings.deselectAnnotation()});c.Annotation&&(k(c.Annotation),h(c.Annotation.types,function(a){k(a)}));c.setOptions({lang:{navigation:{popup:{simpleShapes:"Simple shapes",lines:"Lines",circle:"Circle",rectangle:"Rectangle",label:"Label",shapeOptions:"Shape options", +typeOptions:"Details",fill:"Fill",format:"Text",strokeWidth:"Line width",stroke:"Line color",title:"Title",name:"Name",labelOptions:"Label options",labels:"Labels",backgroundColor:"Background color",backgroundColors:"Background colors",borderColor:"Border color",borderRadius:"Border radius",borderWidth:"Border width",style:"Style",padding:"Padding",fontSize:"Font size",color:"Color",height:"Height",shapes:"Shape options"}}},navigation:{bindingsClassName:"highcharts-bindings-container",bindings:{circleAnnotation:{className:"highcharts-circle-annotation", +start:function(a){a=this.chart.pointer.getCoordinates(a);var b=this.chart.options.navigation;return this.chart.addAnnotation(e({langKey:"circle",type:"basicAnnotation",shapes:[{type:"circle",point:{xAxis:0,yAxis:0,x:a.xAxis[0].value,y:a.yAxis[0].value},r:5}]},b.annotationsOptions,b.bindings.circleAnnotation.annotationsOptions))},steps:[function(a,b){var c=b.options.shapes[0].point,d=this.chart.xAxis[0].toPixels(c.x);c=this.chart.yAxis[0].toPixels(c.y);var e=this.chart.inverted;b.update({shapes:[{r:Math.max(Math.sqrt(Math.pow(e? +c-a.chartX:d-a.chartX,2)+Math.pow(e?d-a.chartY:c-a.chartY,2)),5)}]})}]},rectangleAnnotation:{className:"highcharts-rectangle-annotation",start:function(a){var b=this.chart.pointer.getCoordinates(a);a=this.chart.options.navigation;var c=b.xAxis[0].value;b=b.yAxis[0].value;return this.chart.addAnnotation(e({langKey:"rectangle",type:"basicAnnotation",shapes:[{type:"path",points:[{xAxis:0,yAxis:0,x:c,y:b},{xAxis:0,yAxis:0,x:c,y:b},{xAxis:0,yAxis:0,x:c,y:b},{xAxis:0,yAxis:0,x:c,y:b}]}]},a.annotationsOptions, +a.bindings.rectangleAnnotation.annotationsOptions))},steps:[function(a,b){var c=b.options.shapes[0].points,d=this.chart.pointer.getCoordinates(a);a=d.xAxis[0].value;d=d.yAxis[0].value;c[1].x=a;c[2].x=a;c[2].y=d;c[3].y=d;b.update({shapes:[{points:c}]})}]},labelAnnotation:{className:"highcharts-label-annotation",start:function(a){a=this.chart.pointer.getCoordinates(a);var b=this.chart.options.navigation;return this.chart.addAnnotation(e({langKey:"label",type:"basicAnnotation",labelOptions:{format:"{y:.2f}"}, +labels:[{point:{xAxis:0,yAxis:0,x:a.xAxis[0].value,y:a.yAxis[0].value},overflow:"none",crop:!0}]},b.annotationsOptions,b.bindings.labelAnnotation.annotationsOptions))}}},events:{},annotationsOptions:{}}});return v});p(c,"annotations/popup.js",[c["parts/Globals.js"],c["annotations/navigationBindings.js"],c["parts/Utilities.js"]],function(c,a,m){var k=m.addEvent,f=m.createElement,d=m.defined,p=m.isArray,r=m.isObject,b=m.isString,g=m.objectEach,z=m.pick;m=m.wrap;var x=/\d/g;m(c.Pointer.prototype,"onContainerMouseDown", +function(a,c){var d=c.target&&c.target.className;b(d)&&0<=d.indexOf("highcharts-popup-field")||a.apply(this,Array.prototype.slice.call(arguments,1))});c.Popup=function(a,b){this.init(a,b)};c.Popup.prototype={init:function(a,b){this.container=f("div",{className:"highcharts-popup"},null,a);this.lang=this.getLangpack();this.iconsURL=b;this.addCloseBtn()},addCloseBtn:function(){var a=this;var b=f("div",{className:"highcharts-popup-close"},null,this.container);b.style["background-image"]="url("+this.iconsURL+ +"close.svg)";["click","touchstart"].forEach(function(c){k(b,c,function(){a.closePopup()})})},addColsContainer:function(a){var b=f("div",{className:"highcharts-popup-lhs-col"},null,a);a=f("div",{className:"highcharts-popup-rhs-col"},null,a);f("div",{className:"highcharts-popup-rhs-col-wrapper"},null,a);return{lhsCol:b,rhsCol:a}},addInput:function(a,b,c,d){var e=a.split(".");e=e[e.length-1];var h=this.lang;b="highcharts-"+b+"-"+e;b.match(x)||f("label",{innerHTML:h[e]||e,htmlFor:b},null,c);f("input", +{name:b,value:d[0],type:d[1],className:"highcharts-popup-field"},null,c).setAttribute("highcharts-data-name",a)},addButton:function(a,b,c,d,g){var e=this,h=this.closePopup,l=this.getFields;var q=f("button",{innerHTML:b},null,a);["click","touchstart"].forEach(function(a){k(q,a,function(){h.call(e);return d(l(g,c))})});return q},getFields:function(a,b){var c=a.querySelectorAll("input"),d=a.querySelectorAll("#highcharts-select-series > option:checked")[0];a=a.querySelectorAll("#highcharts-select-volume > option:checked")[0]; +var e,f;var h={actionType:b,linkedTo:d&&d.getAttribute("value"),fields:{}};[].forEach.call(c,function(a){f=a.getAttribute("highcharts-data-name");(e=a.getAttribute("highcharts-data-series-id"))?h.seriesId=a.value:f?h.fields[f]=a.value:h.type=a.value});a&&(h.fields["params.volumeSeriesID"]=a.getAttribute("value"));return h},showPopup:function(){var a=this.container,b=a.querySelectorAll(".highcharts-popup-close")[0];a.innerHTML="";0<=a.className.indexOf("highcharts-annotation-toolbar")&&(a.classList.remove("highcharts-annotation-toolbar"), +a.removeAttribute("style"));a.appendChild(b);a.style.display="block"},closePopup:function(){this.popup.container.style.display="none"},showForm:function(a,b,c,d){this.popup=b.navigationBindings.popup;this.showPopup();"indicators"===a&&this.indicators.addForm.call(this,b,c,d);"annotation-toolbar"===a&&this.annotations.addToolbar.call(this,b,c,d);"annotation-edit"===a&&this.annotations.addForm.call(this,b,c,d);"flag"===a&&this.annotations.addForm.call(this,b,c,d,!0)},getLangpack:function(){return c.getOptions().lang.navigation.popup}, +annotations:{addToolbar:function(a,b,c){var d=this,e=this.lang,h=this.popup.container,g=this.showForm;-1===h.className.indexOf("highcharts-annotation-toolbar")&&(h.className+=" highcharts-annotation-toolbar");h.style.top=a.plotTop+10+"px";f("span",{innerHTML:z(e[b.langKey]||b.langKey,b.shapes&&b.shapes[0].type)},null,h);var l=this.addButton(h,e.removeButton||"remove","remove",c,h);l.className+=" highcharts-annotation-remove-button";l.style["background-image"]="url("+this.iconsURL+"destroy.svg)";l= +this.addButton(h,e.editButton||"edit","edit",function(){g.call(d,"annotation-edit",a,b,c)},h);l.className+=" highcharts-annotation-edit-button";l.style["background-image"]="url("+this.iconsURL+"edit.svg)"},addForm:function(a,b,c,d){var e=this.popup.container,h=this.lang;f("h2",{innerHTML:h[b.langKey]||b.langKey,className:"highcharts-popup-main-title"},null,e);var g=f("div",{className:"highcharts-popup-lhs-col highcharts-popup-lhs-full"},null,e);var l=f("div",{className:"highcharts-popup-bottom-row"}, +null,e);this.annotations.addFormFields.call(this,g,a,"",b,[],!0);this.addButton(l,d?h.addButton||"add":h.saveButton||"save",d?"add":"save",c,e)},addFormFields:function(a,b,c,d,k,v){var e=this,h=this.annotations.addFormFields,l=this.addInput,q=this.lang,m,y;g(d,function(d,f){m=""!==c?c+"."+f:f;r(d)&&(!p(d)||p(d)&&r(d[0])?(y=q[f]||f,y.match(x)||k.push([!0,y,a]),h.call(e,a,b,m,d,k,!1)):k.push([e,m,"annotation",a,d]))});v&&(k=k.sort(function(a){return a[1].match(/format/g)?-1:1}),k.forEach(function(a){!0=== +a[0]?f("span",{className:"highcharts-annotation-title",innerHTML:a[1]},null,a[2]):l.apply(a[0],a.splice(1))}))}},indicators:{addForm:function(a,b,c){var d=this.indicators,e=this.lang;this.tabs.init.call(this,a);b=this.popup.container.querySelectorAll(".highcharts-tab-item-content");this.addColsContainer(b[0]);d.addIndicatorList.call(this,a,b[0],"add");var f=b[0].querySelectorAll(".highcharts-popup-rhs-col")[0];this.addButton(f,e.addButton||"add","add",c,f);this.addColsContainer(b[1]);d.addIndicatorList.call(this, +a,b[1],"edit");f=b[1].querySelectorAll(".highcharts-popup-rhs-col")[0];this.addButton(f,e.saveButton||"save","edit",c,f);this.addButton(f,e.removeButton||"remove","remove",c,f)},addIndicatorList:function(a,b,c){var d=this,e=b.querySelectorAll(".highcharts-popup-lhs-col")[0];b=b.querySelectorAll(".highcharts-popup-rhs-col")[0];var h="edit"===c,l=h?a.series:a.options.plotOptions,m=this.indicators.addFormFields,p;var r=f("ul",{className:"highcharts-indicator-list"},null,e);var t=b.querySelectorAll(".highcharts-popup-rhs-col-wrapper")[0]; +g(l,function(b,c){var e=b.options;if(b.params||e&&e.params){var g=d.indicators.getNameType(b,c),q=g.type;p=f("li",{className:"highcharts-indicator-list",innerHTML:g.name},null,r);["click","touchstart"].forEach(function(c){k(p,c,function(){m.call(d,a,h?b:l[q],g.type,t);h&&b.options&&f("input",{type:"hidden",name:"highcharts-id-"+q,value:b.options.id},null,t).setAttribute("highcharts-data-series-id",b.options.id)})})}});0} + */ + this.nonDOMEvents = ['drag']; + this.chart = chart; + this.target = target; + this.options = options; + this.index = pick(options.index, index); + } + /** + * Set the visibility of the control point. + * + * @function Highcharts.AnnotationControlPoint#setVisibility + * + * @param {boolean} visible + * Visibility of the control point. + * + * @return {void} + */ + ControlPoint.prototype.setVisibility = function (visible) { + this.graphic.attr('visibility', visible ? 'visible' : 'hidden'); + this.options.visible = visible; + }; + /** + * Render the control point. + * @private + */ + ControlPoint.prototype.render = function () { + var chart = this.chart, options = this.options; + this.graphic = chart.renderer + .symbol(options.symbol, 0, 0, options.width, options.height) + .add(chart.controlPointsGroup) + .css(options.style); + this.setVisibility(options.visible); + // npm test -- --tests "highcharts/annotations-advanced/*" + this.addEvents(); + }; + /** + * Redraw the control point. + * @private + * @param {boolean} [animation] + */ + ControlPoint.prototype.redraw = function (animation) { + this.graphic[animation ? 'animate' : 'attr'](this.options.positioner.call(this, this.target)); + }; + /** + * Destroy the control point. + * @private + */ + ControlPoint.prototype.destroy = function () { + eventEmitterMixin.destroy.call(this); + if (this.graphic) { + this.graphic = this.graphic.destroy(); + } + this.chart = null; + this.target = null; + this.options = null; + }; + /** + * Update the control point. + * + * @function Highcharts.AnnotationControlPoint#update + * + * @param {Partial} userOptions + * New options for the control point. + * + * @return {void} + */ + ControlPoint.prototype.update = function (userOptions) { + var chart = this.chart, target = this.target, index = this.index, options = merge(true, this.options, userOptions); + this.destroy(); + this.constructor(chart, target, options, index); + this.render(chart.controlPointsGroup); + this.redraw(); + }; + return ControlPoint; + }()); + + return ControlPoint; + }); + _registerModule(_modules, 'annotations/MockPoint.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * @private + * @interface Highcharts.AnnotationMockLabelOptionsObject + */ /** + * Point instance of the point. + * @name Highcharts.AnnotationMockLabelOptionsObject#point + * @type {Highcharts.AnnotationMockPoint} + */ /** + * X value translated to x axis scale. + * @name Highcharts.AnnotationMockLabelOptionsObject#x + * @type {number|null} + */ /** + * Y value translated to y axis scale. + * @name Highcharts.AnnotationMockLabelOptionsObject#y + * @type {number|null} + */ + /** + * A mock series instance imitating a real series from a real point. + * @private + * @interface Highcharts.AnnotationMockSeries + */ /** + * Whether a series is visible. + * @name Highcharts.AnnotationMockSeries#visible + * @type {boolean} + */ /** + * A chart instance. + * @name Highcharts.AnnotationMockSeries#chart + * @type {Highcharts.Chart} + */ /** + * @name Highcharts.AnnotationMockSeries#getPlotBox + * @type {Function} + */ + /** + * Indicates if this is a mock point for an annotation. + * @name Highcharts.Point#mock + * @type {boolean|undefined} + */ + var defined = U.defined, extend = U.extend, fireEvent = U.fireEvent; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * A trimmed point object which imitates {@link Highchart.Point} class. It is + * created when there is a need of pointing to some chart's position using axis + * values or pixel values + * + * @requires modules/annotations + * + * @private + * @class + * @name Highcharts.AnnotationMockPoint + * + * @hideconstructor + * + * @param {Highcharts.Chart} chart + * The chart instance. + * + * @param {Highcharts.AnnotationControllable|null} target + * The related controllable. + * + * @param {Highcharts.AnnotationMockPointOptionsObject|Function} options + * The options object. + */ + var MockPoint = /** @class */ (function () { + function MockPoint(chart, target, options) { + this.isInside = void 0; + this.plotX = void 0; + this.plotY = void 0; + this.x = void 0; + this.y = void 0; + /* * + * + * Functions + * + * */ + /** + * A flag indicating that a point is not the real one. + * + * @type {boolean} + * @default true + */ + this.mock = true; + /** + * A mock series instance imitating a real series from a real point. + * + * @name Annotation.AnnotationMockPoint#series + * @type {Highcharts.AnnotationMockSeries} + */ + this.series = { + visible: true, + chart: chart, + getPlotBox: H.Series.prototype.getPlotBox + }; + /** + * @name Annotation.AnnotationMockPoint#target + * @type {Highcharts.AnnotationControllable|null} + */ + this.target = target || null; + /** + * Options for the mock point. + * + * @name Annotation.AnnotationMockPoint#options + * @type {Highcharts.AnnotationsMockPointOptionsObject} + */ + this.options = options; + /** + * If an xAxis is set it represents the point's value in terms of the + * xAxis. + * + * @name Annotation.AnnotationMockPoint#x + * @type {number|undefined} + */ + /** + * If an yAxis is set it represents the point's value in terms of the + * yAxis. + * + * @name Annotation.AnnotationMockPoint#y + * @type {number|undefined} + */ + /** + * It represents the point's pixel x coordinate relative to its plot + * box. + * + * @name Annotation.AnnotationMockPoint#plotX + * @type {number|undefined} + */ + /** + * It represents the point's pixel y position relative to its plot box. + * + * @name Annotation.AnnotationMockPoint#plotY + * @type {number|undefined} + */ + /** + * Whether the point is inside the plot box. + * + * @name Annotation.AnnotationMockPoint#isInside + * @type {boolean|undefined} + */ + this.applyOptions(this.getOptions()); + } + /** + * Create a mock point from a real Highcharts point. + * + * @private + * @static + * + * @param {Highcharts.Point} point + * + * @return {Highcharts.AnnotationMockPoint} + * A mock point instance. + */ + MockPoint.fromPoint = function (point) { + return new MockPoint(point.series.chart, null, { + x: point.x, + y: point.y, + xAxis: point.series.xAxis, + yAxis: point.series.yAxis + }); + }; + /** + * Get the pixel position from the point like object. + * + * @private + * @static + * + * @param {Highcharts.AnnotationPointType} point + * + * @param {boolean} [paneCoordinates] + * whether the pixel position should be relative + * + * @return {Highcharts.PositionObject} pixel position + */ + MockPoint.pointToPixels = function (point, paneCoordinates) { + var series = point.series, chart = series.chart, x = point.plotX, y = point.plotY, plotBox; + if (chart.inverted) { + if (point.mock) { + x = point.plotY; + y = point.plotX; + } + else { + x = chart.plotWidth - point.plotY; + y = chart.plotHeight - point.plotX; + } + } + if (series && !paneCoordinates) { + plotBox = series.getPlotBox(); + x += plotBox.translateX; + y += plotBox.translateY; + } + return { + x: x, + y: y + }; + }; + /** + * Get fresh mock point options from the point like object. + * + * @private + * @static + * + * @param {Highcharts.AnnotationPointType} point + * + * @return {Highcharts.AnnotationMockPointOptionsObject} + * A mock point's options. + */ + MockPoint.pointToOptions = function (point) { + return { + x: point.x, + y: point.y, + xAxis: point.series.xAxis, + yAxis: point.series.yAxis + }; + }; + /** + * Check if the point has dynamic options. + * @private + * @return {boolean} + * A positive flag if the point has dynamic options. + */ + MockPoint.prototype.hasDynamicOptions = function () { + return typeof this.options === 'function'; + }; + /** + * Get the point's options. + * @private + * @return {Highcharts.AnnotationMockPointOptionsObject} + * The mock point's options. + */ + MockPoint.prototype.getOptions = function () { + return this.hasDynamicOptions() ? + this.options(this.target) : + this.options; + }; + /** + * Apply options for the point. + * @private + * @param {Highcharts.AnnotationMockPointOptionsObject} options + */ + MockPoint.prototype.applyOptions = function (options) { + this.command = options.command; + this.setAxis(options, 'x'); + this.setAxis(options, 'y'); + this.refresh(); + }; + /** + * Set x or y axis. + * @private + * @param {Highcharts.AnnotationMockPointOptionsObject} options + * @param {string} xOrY + * 'x' or 'y' string literal + */ + MockPoint.prototype.setAxis = function (options, xOrY) { + var axisName = (xOrY + 'Axis'), axisOptions = options[axisName], chart = this.series.chart; + this.series[axisName] = + axisOptions instanceof H.Axis ? + axisOptions : + defined(axisOptions) ? + (chart[axisName][axisOptions] || + chart.get(axisOptions)) : + null; + }; + /** + * Transform the mock point to an anchor (relative position on the chart). + * @private + * @return {Array} + * A quadruple of numbers which denotes x, y, width and height of the box + **/ + MockPoint.prototype.toAnchor = function () { + var anchor = [this.plotX, this.plotY, 0, 0]; + if (this.series.chart.inverted) { + anchor[0] = this.plotY; + anchor[1] = this.plotX; + } + return anchor; + }; + /** + * Returns a label config object - the same as + * Highcharts.Point.prototype.getLabelConfig + * @private + * @return {Annotation.MockPoint.LabelConfig} the point's label config + */ + MockPoint.prototype.getLabelConfig = function () { + return { + x: this.x, + y: this.y, + point: this + }; + }; + /** + * Check if the point is inside its pane. + * @private + * @return {boolean} A flag indicating whether the point is inside the pane. + */ + MockPoint.prototype.isInsidePlot = function () { + var plotX = this.plotX, plotY = this.plotY, xAxis = this.series.xAxis, yAxis = this.series.yAxis, e = { + x: plotX, + y: plotY, + isInsidePlot: true + }; + if (xAxis) { + e.isInsidePlot = defined(plotX) && plotX >= 0 && plotX <= xAxis.len; + } + if (yAxis) { + e.isInsidePlot = + e.isInsidePlot && + defined(plotY) && + plotY >= 0 && plotY <= yAxis.len; + } + fireEvent(this.series.chart, 'afterIsInsidePlot', e); + return e.isInsidePlot; + }; + /** + * Refresh point values and coordinates based on its options. + * @private + */ + MockPoint.prototype.refresh = function () { + var series = this.series, xAxis = series.xAxis, yAxis = series.yAxis, options = this.getOptions(); + if (xAxis) { + this.x = options.x; + this.plotX = xAxis.toPixels(options.x, true); + } + else { + this.x = null; + this.plotX = options.x; + } + if (yAxis) { + this.y = options.y; + this.plotY = yAxis.toPixels(options.y, true); + } + else { + this.y = null; + this.plotY = options.y; + } + this.isInside = this.isInsidePlot(); + }; + /** + * Translate the point. + * + * @private + * + * @param {number|undefined} cx + * Origin x transformation. + * + * @param {number|undefined} cy + * Origin y transformation. + * + * @param {number} dx + * Translation for x coordinate. + * + * @param {number} dy + * Translation for y coordinate. + **/ + MockPoint.prototype.translate = function (_cx, _cy, dx, dy) { + if (!this.hasDynamicOptions()) { + this.plotX += dx; + this.plotY += dy; + this.refreshOptions(); + } + }; + /** + * Scale the point. + * + * @private + * + * @param {number} cx + * Origin x transformation. + * + * @param {number} cy + * Origin y transformation. + * + * @param {number} sx + * Scale factor x. + * + * @param {number} sy + * Scale factor y. + */ + MockPoint.prototype.scale = function (cx, cy, sx, sy) { + if (!this.hasDynamicOptions()) { + var x = this.plotX * sx, y = this.plotY * sy, tx = (1 - sx) * cx, ty = (1 - sy) * cy; + this.plotX = tx + x; + this.plotY = ty + y; + this.refreshOptions(); + } + }; + /** + * Rotate the point. + * @private + * @param {number} cx origin x rotation + * @param {number} cy origin y rotation + * @param {number} radians + */ + MockPoint.prototype.rotate = function (cx, cy, radians) { + if (!this.hasDynamicOptions()) { + var cos = Math.cos(radians), sin = Math.sin(radians), x = this.plotX, y = this.plotY, tx, ty; + x -= cx; + y -= cy; + tx = x * cos - y * sin; + ty = x * sin + y * cos; + this.plotX = tx + cx; + this.plotY = ty + cy; + this.refreshOptions(); + } + }; + /** + * Refresh point options based on its plot coordinates. + * @private + */ + MockPoint.prototype.refreshOptions = function () { + var series = this.series, xAxis = series.xAxis, yAxis = series.yAxis; + this.x = this.options.x = xAxis ? + this.options.x = xAxis.toValue(this.plotX, true) : + this.plotX; + this.y = this.options.y = yAxis ? + yAxis.toValue(this.plotY, true) : + this.plotY; + }; + return MockPoint; + }()); + + return MockPoint; + }); + _registerModule(_modules, 'annotations/controllable/controllableMixin.js', [_modules['parts/Utilities.js'], _modules['annotations/ControlPoint.js'], _modules['annotations/MockPoint.js'], _modules['parts/Tooltip.js']], function (U, ControlPoint, MockPoint, Tooltip) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * An object which denots a controllable's anchor positions - relative and + * absolute. + * + * @private + * @interface Highcharts.AnnotationAnchorObject + */ /** + * Relative to the plot area position + * @name Highcharts.AnnotationAnchorObject#relativePosition + * @type {Highcharts.BBoxObject} + */ /** + * Absolute position + * @name Highcharts.AnnotationAnchorObject#absolutePosition + * @type {Highcharts.BBoxObject} + */ + /** + * @interface Highcharts.AnnotationControllable + */ /** + * @name Highcharts.AnnotationControllable#annotation + * @type {Highcharts.Annotation} + */ /** + * @name Highcharts.AnnotationControllable#chart + * @type {Highcharts.Chart} + */ /** + * @name Highcharts.AnnotationControllable#collection + * @type {string} + */ /** + * @private + * @name Highcharts.AnnotationControllable#controlPoints + * @type {Array} + */ /** + * @name Highcharts.AnnotationControllable#points + * @type {Array} + */ + var isObject = U.isObject, isString = U.isString, merge = U.merge, splat = U.splat; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * It provides methods for handling points, control points + * and points transformations. + * + * @private + * @mixin + * @name Highcharts.AnnotationControllableMixin + */ + var controllableMixin = { + /** + * Init the controllable + */ + init: function (annotation, options, index) { + this.annotation = annotation; + this.chart = annotation.chart; + this.options = options; + this.points = []; + this.controlPoints = []; + this.index = index; + this.linkPoints(); + this.addControlPoints(); + }, + /** + * Redirect attr usage on the controllable graphic element. + */ + attr: function () { + this.graphic.attr.apply(this.graphic, arguments); + }, + /** + * Get the controllable's points options. + * + * @return {Array} + * An array of points' options. + */ + getPointsOptions: function () { + var options = this.options; + return (options.points || (options.point && splat(options.point))); + }, + /** + * Utility function for mapping item's options + * to element's attribute + * + * @param {Highcharts.AnnotationsLabelsOptions|Highcharts.AnnotationsShapesOptions} options + * + * @return {Highcharts.SVGAttributes} + * Mapped options. + */ + attrsFromOptions: function (options) { + var map = this.constructor.attrsMap, attrs = {}, key, mappedKey, styledMode = this.chart.styledMode; + for (key in options) { // eslint-disable-line guard-for-in + mappedKey = map[key]; + if (mappedKey && + (!styledMode || + ['fill', 'stroke', 'stroke-width'] + .indexOf(mappedKey) === -1)) { + attrs[mappedKey] = options[key]; + } + } + return attrs; + }, + /** + * Returns object which denotes anchor position - relative and absolute. + * + * @param {Highcharts.AnnotationPointType} point + * A point like object. + * + * @return {Highcharts.AnnotationAnchorObject} a controllable anchor + */ + anchor: function (point) { + var plotBox = point.series.getPlotBox(), box = point.mock ? + point.toAnchor() : + Tooltip.prototype.getAnchor.call({ + chart: point.series.chart + }, point), anchor = { + x: box[0] + (this.options.x || 0), + y: box[1] + (this.options.y || 0), + height: box[2] || 0, + width: box[3] || 0 + }; + return { + relativePosition: anchor, + absolutePosition: merge(anchor, { + x: anchor.x + plotBox.translateX, + y: anchor.y + plotBox.translateY + }) + }; + }, + /** + * Map point's options to a point-like object. + * + * @param {string|Function|Highcharts.AnnotationMockPointOptionsObject|Highcharts.AnnotationPointType} pointOptions + * Point's options. + * + * @param {Highcharts.AnnotationPointType} point + * A point-like instance. + * + * @return {Highcharts.AnnotationPointType|null} + * if the point is found/set returns this point, otherwise null + */ + point: function (pointOptions, point) { + if (pointOptions && pointOptions.series) { + return pointOptions; + } + if (!point || point.series === null) { + if (isObject(pointOptions)) { + point = new MockPoint(this.chart, this, pointOptions); + } + else if (isString(pointOptions)) { + point = this.chart.get(pointOptions) || null; + } + else if (typeof pointOptions === 'function') { + var pointConfig = pointOptions.call(point, this); + point = pointConfig.series ? + pointConfig : + new MockPoint(this.chart, this, pointOptions); + } + } + return point; + }, + /** + * Find point-like objects based on points options. + * + * @return {Array} an array of point-like objects + */ + linkPoints: function () { + var pointsOptions = this.getPointsOptions(), points = this.points, len = (pointsOptions && pointsOptions.length) || 0, i, point; + for (i = 0; i < len; i++) { + point = this.point(pointsOptions[i], points[i]); + if (!point) { + points.length = 0; + return; + } + if (point.mock) { + point.refresh(); + } + points[i] = point; + } + return points; + }, + /** + * Add control points to a controllable. + */ + addControlPoints: function () { + var controlPointsOptions = this.options.controlPoints; + (controlPointsOptions || []).forEach(function (controlPointOptions, i) { + var options = merge(this.options.controlPointOptions, controlPointOptions); + if (!options.index) { + options.index = i; + } + controlPointsOptions[i] = options; + this.controlPoints.push(new ControlPoint(this.chart, this, options)); + }, this); + }, + /** + * Check if a controllable should be rendered/redrawn. + * + * @return {boolean} + * Whether a controllable should be drawn. + */ + shouldBeDrawn: function () { + return Boolean(this.points.length); + }, + /** + * Render a controllable. + */ + render: function (_parentGroup) { + this.controlPoints.forEach(function (controlPoint) { + controlPoint.render(); + }); + }, + /** + * Redraw a controllable. + * + * @param {boolean} [animation] + */ + redraw: function (animation) { + this.controlPoints.forEach(function (controlPoint) { + controlPoint.redraw(animation); + }); + }, + /** + * Transform a controllable with a specific transformation. + * + * @param {string} transformation a transformation name + * @param {number|null} cx origin x transformation + * @param {number|null} cy origin y transformation + * @param {number} p1 param for the transformation + * @param {number} [p2] param for the transformation + */ + transform: function (transformation, cx, cy, p1, p2) { + if (this.chart.inverted) { + var temp = cx; + cx = cy; + cy = temp; + } + this.points.forEach(function (point, i) { + this.transformPoint(transformation, cx, cy, p1, p2, i); + }, this); + }, + /** + * Transform a point with a specific transformation + * If a transformed point is a real point it is replaced with + * the mock point. + * + * @param {string} transformation a transformation name + * @param {number|null} cx origin x transformation + * @param {number|null} cy origin y transformation + * @param {number} p1 param for the transformation + * @param {number|undefined} p2 param for the transformation + * @param {number} i index of the point + */ + transformPoint: function (transformation, cx, cy, p1, p2, i) { + var point = this.points[i]; + if (!point.mock) { + point = this.points[i] = MockPoint.fromPoint(point); + } + point[transformation](cx, cy, p1, p2); + }, + /** + * Translate a controllable. + * + * @param {number} dx translation for x coordinate + * @param {number} dy translation for y coordinate + **/ + translate: function (dx, dy) { + this.transform('translate', null, null, dx, dy); + }, + /** + * Translate a specific point within a controllable. + * + * @param {number} dx translation for x coordinate + * @param {number} dy translation for y coordinate + * @param {number} i index of the point + **/ + translatePoint: function (dx, dy, i) { + this.transformPoint('translate', null, null, dx, dy, i); + }, + /** + * Translate shape within controllable item. + * Replaces `controllable.translate` method. + * + * @param {number} dx translation for x coordinate + * @param {number} dy translation for y coordinate + */ + translateShape: function (dx, dy) { + var chart = this.annotation.chart, + // Annotation.options + shapeOptions = this.annotation.userOptions, + // Chart.options.annotations + annotationIndex = chart.annotations.indexOf(this.annotation), chartOptions = chart.options.annotations[annotationIndex]; + this.translatePoint(dx, dy, 0); + // Options stored in: + // - chart (for exporting) + // - current config (for redraws) + chartOptions[this.collection][this.index].point = this.options.point; + shapeOptions[this.collection][this.index].point = this.options.point; + }, + /** + * Rotate a controllable. + * + * @param {number} cx origin x rotation + * @param {number} cy origin y rotation + * @param {number} radians + **/ + rotate: function (cx, cy, radians) { + this.transform('rotate', cx, cy, radians); + }, + /** + * Scale a controllable. + * + * @param {number} cx origin x rotation + * @param {number} cy origin y rotation + * @param {number} sx scale factor x + * @param {number} sy scale factor y + */ + scale: function (cx, cy, sx, sy) { + this.transform('scale', cx, cy, sx, sy); + }, + /** + * Set control points' visibility. + * + * @param {boolean} visible + */ + setControlPointsVisibility: function (visible) { + this.controlPoints.forEach(function (controlPoint) { + controlPoint.setVisibility(visible); + }); + }, + /** + * Destroy a controllable. + */ + destroy: function () { + if (this.graphic) { + this.graphic = this.graphic.destroy(); + } + if (this.tracker) { + this.tracker = this.tracker.destroy(); + } + this.controlPoints.forEach(function (controlPoint) { + controlPoint.destroy(); + }); + this.chart = null; + this.points = null; + this.controlPoints = null; + this.options = null; + if (this.annotation) { + this.annotation = null; + } + }, + /** + * Update a controllable. + * + * @param {Object} newOptions + */ + update: function (newOptions) { + var annotation = this.annotation, options = merge(true, this.options, newOptions), parentGroup = this.graphic.parentGroup; + this.destroy(); + this.constructor(annotation, options); + this.render(parentGroup); + this.redraw(); + } + }; + + return controllableMixin; + }); + _registerModule(_modules, 'annotations/controllable/markerMixin.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, defined = U.defined, merge = U.merge, objectEach = U.objectEach, uniqueKey = U.uniqueKey; + /** + * Options for configuring markers for annotations. + * + * An example of the arrow marker: + *
    +         * {
    +         *   arrow: {
    +         *     id: 'arrow',
    +         *     tagName: 'marker',
    +         *     refY: 5,
    +         *     refX: 5,
    +         *     markerWidth: 10,
    +         *     markerHeight: 10,
    +         *     children: [{
    +         *       tagName: 'path',
    +         *       attrs: {
    +         *         d: 'M 0 0 L 10 5 L 0 10 Z',
    +         *         strokeWidth: 0
    +         *       }
    +         *     }]
    +         *   }
    +         * }
    +         * 
    + * + * @sample highcharts/annotations/custom-markers/ + * Define a custom marker for annotations + * + * @sample highcharts/css/annotations-markers/ + * Define markers in a styled mode + * + * @type {Highcharts.Dictionary} + * @since 6.0.0 + * @optionparent defs + */ + var defaultMarkers = { + /** + * @type {Highcharts.SVGDefinitionObject} + */ + arrow: { + tagName: 'marker', + render: false, + id: 'arrow', + refY: 5, + refX: 9, + markerWidth: 10, + markerHeight: 10, + /** + * @type {Array} + */ + children: [{ + tagName: 'path', + d: 'M 0 0 L 10 5 L 0 10 Z', + strokeWidth: 0 + }] + }, + /** + * @type {Highcharts.SVGDefinitionObject} + */ + 'reverse-arrow': { + tagName: 'marker', + render: false, + id: 'reverse-arrow', + refY: 5, + refX: 1, + markerWidth: 10, + markerHeight: 10, + children: [{ + tagName: 'path', + // reverse triangle (used as an arrow) + d: 'M 0 5 L 10 0 L 10 10 Z', + strokeWidth: 0 + }] + } + }; + H.SVGRenderer.prototype.addMarker = function (id, markerOptions) { + var options = { id: id }; + var attrs = { + stroke: markerOptions.color || 'none', + fill: markerOptions.color || 'rgba(0, 0, 0, 0.75)' + }; + options.children = markerOptions.children.map(function (child) { + return merge(attrs, child); + }); + var marker = this.definition(merge(true, { + markerWidth: 20, + markerHeight: 20, + refX: 0, + refY: 0, + orient: 'auto' + }, markerOptions, options)); + marker.id = id; + return marker; + }; + /* eslint-disable no-invalid-this, valid-jsdoc */ + var createMarkerSetter = function (markerType) { + return function (value) { + this.attr(markerType, 'url(#' + value + ')'); + }; + }; + /** + * @private + * @mixin + * @name Highcharts.AnnotaitonMarkerMixin + */ + var markerMixin = { + markerEndSetter: createMarkerSetter('marker-end'), + markerStartSetter: createMarkerSetter('marker-start'), + /** + * Set markers. + * @private + * @param {Highcharts.AnnotationControllablePath} item + */ + setItemMarkers: function (item) { + var itemOptions = item.options, chart = item.chart, defs = chart.options.defs, fill = itemOptions.fill, color = defined(fill) && fill !== 'none' ? + fill : + itemOptions.stroke, setMarker = function (markerType) { + var markerId = itemOptions[markerType], def, predefinedMarker, key, marker; + if (markerId) { + for (key in defs) { // eslint-disable-line guard-for-in + def = defs[key]; + if (markerId === def.id && + def.tagName === 'marker') { + predefinedMarker = def; + break; + } + } + if (predefinedMarker) { + marker = item[markerType] = chart.renderer + .addMarker((itemOptions.id || uniqueKey()) + '-' + + predefinedMarker.id, merge(predefinedMarker, { color: color })); + item.attr(markerType, marker.attr('id')); + } + } + }; + ['markerStart', 'markerEnd'].forEach(setMarker); + } + }; + addEvent(H.Chart, 'afterGetContainer', function () { + this.options.defs = merge(defaultMarkers, this.options.defs || {}); + objectEach(this.options.defs, function (def) { + if (def.tagName === 'marker' && def.render !== false) { + this.renderer.addMarker(def.id, def); + } + }, this); + }); + + return markerMixin; + }); + _registerModule(_modules, 'annotations/controllable/ControllablePath.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['annotations/controllable/controllableMixin.js'], _modules['annotations/controllable/markerMixin.js']], function (H, U, controllableMixin, markerMixin) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend, merge = U.merge; + // See TRACKER_FILL in highcharts.src.js + var TRACKER_FILL = 'rgba(192,192,192,' + (H.svg ? 0.0001 : 0.002) + ')'; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * A controllable path class. + * + * @requires modules/annotations + * + * @private + * @class + * @name Highcharts.AnnotationControllablePath + * + * @param {Highcharts.Annotation} + * Related annotation. + * + * @param {Highcharts.AnnotationsShapeOptions} options + * A path's options object. + * + * @param {number} index + * Index of the path. + **/ + var ControllablePath = function (annotation, options, index) { + this.init(annotation, options, index); + this.collection = 'shapes'; + }; + /** + * A map object which allows to map options attributes to element attributes + * + * @name Highcharts.AnnotationControllablePath.attrsMap + * @type {Highcharts.Dictionary} + */ + ControllablePath.attrsMap = { + dashStyle: 'dashstyle', + strokeWidth: 'stroke-width', + stroke: 'stroke', + fill: 'fill', + zIndex: 'zIndex' + }; + merge(true, ControllablePath.prototype, controllableMixin, /** @lends Highcharts.AnnotationControllablePath# */ { + /** + * @type 'path' + */ + type: 'path', + setMarkers: markerMixin.setItemMarkers, + /** + * Map the controllable path to 'd' path attribute. + * + * @return {Highcharts.SVGPathArray|null} + * A path's d attribute. + */ + toD: function () { + var dOption = this.options.d; + if (dOption) { + return typeof dOption === 'function' ? + dOption.call(this) : + dOption; + } + var points = this.points, len = points.length, showPath = len, point = points[0], position = showPath && this.anchor(point).absolutePosition, pointIndex = 0, command, d = []; + if (position) { + d.push(['M', position.x, position.y]); + while (++pointIndex < len && showPath) { + point = points[pointIndex]; + command = point.command || 'L'; + position = this.anchor(point).absolutePosition; + if (command === 'M') { + d.push([command, position.x, position.y]); + } + else if (command === 'L') { + d.push([command, position.x, position.y]); + } + else if (command === 'Z') { + d.push([command]); + } + showPath = point.series.visible; + } + } + return showPath ? + this.chart.renderer.crispLine(d, this.graphic.strokeWidth()) : + null; + }, + shouldBeDrawn: function () { + return (controllableMixin.shouldBeDrawn.call(this) || Boolean(this.options.d)); + }, + render: function (parent) { + var options = this.options, attrs = this.attrsFromOptions(options); + this.graphic = this.annotation.chart.renderer + .path([['M', 0, 0]]) + .attr(attrs) + .add(parent); + if (options.className) { + this.graphic.addClass(options.className); + } + this.tracker = this.annotation.chart.renderer + .path([['M', 0, 0]]) + .addClass('highcharts-tracker-line') + .attr({ + zIndex: 2 + }) + .add(parent); + if (!this.annotation.chart.styledMode) { + this.tracker.attr({ + 'stroke-linejoin': 'round', + stroke: TRACKER_FILL, + fill: TRACKER_FILL, + 'stroke-width': this.graphic.strokeWidth() + + options.snap * 2 + }); + } + controllableMixin.render.call(this); + extend(this.graphic, { + markerStartSetter: markerMixin.markerStartSetter, + markerEndSetter: markerMixin.markerEndSetter + }); + this.setMarkers(this); + }, + redraw: function (animation) { + var d = this.toD(), action = animation ? 'animate' : 'attr'; + if (d) { + this.graphic[action]({ d: d }); + this.tracker[action]({ d: d }); + } + else { + this.graphic.attr({ d: 'M 0 ' + -9e9 }); + this.tracker.attr({ d: 'M 0 ' + -9e9 }); + } + this.graphic.placed = this.tracker.placed = Boolean(d); + controllableMixin.redraw.call(this, animation); + } + }); + + return ControllablePath; + }); + _registerModule(_modules, 'annotations/controllable/ControllableRect.js', [_modules['parts/Utilities.js'], _modules['annotations/controllable/controllableMixin.js'], _modules['annotations/controllable/ControllablePath.js']], function (U, controllableMixin, ControllablePath) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var merge = U.merge; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * A controllable rect class. + * + * @requires modules/annotations + * + * @private + * @class + * @name Highcharts.AnnotationControllableRect + * + * @param {Highcharts.Annotation} annotation + * An annotation instance. + * + * @param {Highcharts.AnnotationsShapeOptions} options + * A rect's options. + * + * @param {number} index + * Index of the rectangle + */ + var ControllableRect = function (annotation, options, index) { + this.init(annotation, options, index); + this.collection = 'shapes'; + }; + /** + * @typedef {Annotation.ControllablePath.AttrsMap} + * Annotation.ControllableRect.AttrsMap + * @property {string} width=width + * @property {string} height=height + */ + /** + * A map object which allows to map options attributes to element attributes + * + * @type {Annotation.ControllableRect.AttrsMap} + */ + ControllableRect.attrsMap = merge(ControllablePath.attrsMap, { + width: 'width', + height: 'height' + }); + merge(true, ControllableRect.prototype, controllableMixin, /** @lends Annotation.ControllableRect# */ { + /** + * @type 'rect' + */ + type: 'rect', + translate: controllableMixin.translateShape, + render: function (parent) { + var attrs = this.attrsFromOptions(this.options); + this.graphic = this.annotation.chart.renderer + .rect(0, -9e9, 0, 0) + .attr(attrs) + .add(parent); + controllableMixin.render.call(this); + }, + redraw: function (animation) { + var position = this.anchor(this.points[0]).absolutePosition; + if (position) { + this.graphic[animation ? 'animate' : 'attr']({ + x: position.x, + y: position.y, + width: this.options.width, + height: this.options.height + }); + } + else { + this.attr({ + x: 0, + y: -9e9 + }); + } + this.graphic.placed = Boolean(position); + controllableMixin.redraw.call(this, animation); + } + }); + + return ControllableRect; + }); + _registerModule(_modules, 'annotations/controllable/ControllableCircle.js', [_modules['parts/Utilities.js'], _modules['annotations/controllable/controllableMixin.js'], _modules['annotations/controllable/ControllablePath.js']], function (U, controllableMixin, ControllablePath) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var merge = U.merge; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * A controllable circle class. + * + * @requires modules/annotations + * + * @private + * @constructor + * @name Highcharts.AnnotationControllableCircle + * + * @param {Highcharts.Annotation} annotation an annotation instance + * @param {Highcharts.AnnotationsShapeOptions} options a shape's options + * @param {number} index of the circle + **/ + var ControllableCircle = function (annotation, options, index) { + this.init(annotation, options, index); + this.collection = 'shapes'; + }; + /** + * A map object which allows to map options attributes to element attributes. + * + * @name Highcharts.AnnotationControllableCircle.attrsMap + * @type {Highcharts.Dictionary} + */ + ControllableCircle.attrsMap = merge(ControllablePath.attrsMap, { + r: 'r' + }); + merge(true, ControllableCircle.prototype, controllableMixin, /** @lends Highcharts.AnnotationControllableCircle# */ { + /** + * @type 'circle' + */ + type: 'circle', + translate: controllableMixin.translateShape, + render: function (parent) { + var attrs = this.attrsFromOptions(this.options); + this.graphic = this.annotation.chart.renderer + .circle(0, -9e9, 0) + .attr(attrs) + .add(parent); + controllableMixin.render.call(this); + }, + redraw: function (animation) { + var position = this.anchor(this.points[0]).absolutePosition; + if (position) { + this.graphic[animation ? 'animate' : 'attr']({ + x: position.x, + y: position.y, + r: this.options.r + }); + } + else { + this.graphic.attr({ + x: 0, + y: -9e9 + }); + } + this.graphic.placed = Boolean(position); + controllableMixin.redraw.call(this, animation); + }, + /** + * Set the radius. + * + * @param {number} r a radius to be set + */ + setRadius: function (r) { + this.options.r = r; + } + }); + + return ControllableCircle; + }); + _registerModule(_modules, 'annotations/controllable/ControllableLabel.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['annotations/controllable/controllableMixin.js'], _modules['annotations/MockPoint.js'], _modules['parts/Tooltip.js']], function (H, U, controllableMixin, MockPoint, Tooltip) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend, format = U.format, isNumber = U.isNumber, merge = U.merge, pick = U.pick; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * A controllable label class. + * + * @requires modules/annotations + * + * @private + * @class + * @name Highcharts.AnnotationControllableLabel + * + * @param {Highcharts.Annotation} annotation + * An annotation instance. + * @param {Highcharts.AnnotationsLabelOptions} options + * A label's options. + * @param {number} index + * Index of the label. + */ + var ControllableLabel = function (annotation, options, index) { + this.init(annotation, options, index); + this.collection = 'labels'; + }; + /** + * Shapes which do not have background - the object is used for proper + * setting of the contrast color. + * + * @type {Array} + */ + ControllableLabel.shapesWithoutBackground = ['connector']; + /** + * Returns new aligned position based alignment options and box to align to. + * It is almost a one-to-one copy from SVGElement.prototype.align + * except it does not use and mutate an element + * + * @param {Highcharts.AnnotationAlignObject} alignOptions + * + * @param {Highcharts.BBoxObject} box + * + * @return {Highcharts.PositionObject} + * Aligned position. + */ + ControllableLabel.alignedPosition = function (alignOptions, box) { + var align = alignOptions.align, vAlign = alignOptions.verticalAlign, x = (box.x || 0) + (alignOptions.x || 0), y = (box.y || 0) + (alignOptions.y || 0), alignFactor, vAlignFactor; + if (align === 'right') { + alignFactor = 1; + } + else if (align === 'center') { + alignFactor = 2; + } + if (alignFactor) { + x += (box.width - (alignOptions.width || 0)) / alignFactor; + } + if (vAlign === 'bottom') { + vAlignFactor = 1; + } + else if (vAlign === 'middle') { + vAlignFactor = 2; + } + if (vAlignFactor) { + y += (box.height - (alignOptions.height || 0)) / vAlignFactor; + } + return { + x: Math.round(x), + y: Math.round(y) + }; + }; + /** + * Returns new alignment options for a label if the label is outside the + * plot area. It is almost a one-to-one copy from + * Series.prototype.justifyDataLabel except it does not mutate the label and + * it works with absolute instead of relative position. + */ + ControllableLabel.justifiedOptions = function (chart, label, alignOptions, alignAttr) { + var align = alignOptions.align, verticalAlign = alignOptions.verticalAlign, padding = label.box ? 0 : (label.padding || 0), bBox = label.getBBox(), off, + // + options = { + align: align, + verticalAlign: verticalAlign, + x: alignOptions.x, + y: alignOptions.y, + width: label.width, + height: label.height + }, + // + x = alignAttr.x - chart.plotLeft, y = alignAttr.y - chart.plotTop; + // Off left + off = x + padding; + if (off < 0) { + if (align === 'right') { + options.align = 'left'; + } + else { + options.x = -off; + } + } + // Off right + off = x + bBox.width - padding; + if (off > chart.plotWidth) { + if (align === 'left') { + options.align = 'right'; + } + else { + options.x = chart.plotWidth - off; + } + } + // Off top + off = y + padding; + if (off < 0) { + if (verticalAlign === 'bottom') { + options.verticalAlign = 'top'; + } + else { + options.y = -off; + } + } + // Off bottom + off = y + bBox.height - padding; + if (off > chart.plotHeight) { + if (verticalAlign === 'top') { + options.verticalAlign = 'bottom'; + } + else { + options.y = chart.plotHeight - off; + } + } + return options; + }; + /** + * A map object which allows to map options attributes to element attributes + * + * @type {Highcharts.Dictionary} + */ + ControllableLabel.attrsMap = { + backgroundColor: 'fill', + borderColor: 'stroke', + borderWidth: 'stroke-width', + zIndex: 'zIndex', + borderRadius: 'r', + padding: 'padding' + }; + merge(true, ControllableLabel.prototype, controllableMixin, + /** @lends Annotation.ControllableLabel# */ { + /** + * Translate the point of the label by deltaX and deltaY translations. + * The point is the label's anchor. + * + * @param {number} dx translation for x coordinate + * @param {number} dy translation for y coordinate + **/ + translatePoint: function (dx, dy) { + controllableMixin.translatePoint.call(this, dx, dy, 0); + }, + /** + * Translate x and y position relative to the label's anchor. + * + * @param {number} dx translation for x coordinate + * @param {number} dy translation for y coordinate + **/ + translate: function (dx, dy) { + var chart = this.annotation.chart, + // Annotation.options + labelOptions = this.annotation.userOptions, + // Chart.options.annotations + annotationIndex = chart.annotations.indexOf(this.annotation), chartAnnotations = chart.options.annotations, chartOptions = chartAnnotations[annotationIndex], temp; + if (chart.inverted) { + temp = dx; + dx = dy; + dy = temp; + } + // Local options: + this.options.x += dx; + this.options.y += dy; + // Options stored in chart: + chartOptions[this.collection][this.index].x = this.options.x; + chartOptions[this.collection][this.index].y = this.options.y; + labelOptions[this.collection][this.index].x = this.options.x; + labelOptions[this.collection][this.index].y = this.options.y; + }, + render: function (parent) { + var options = this.options, attrs = this.attrsFromOptions(options), style = options.style; + this.graphic = this.annotation.chart.renderer + .label('', 0, -9999, // #10055 + options.shape, null, null, options.useHTML, null, 'annotation-label') + .attr(attrs) + .add(parent); + if (!this.annotation.chart.styledMode) { + if (style.color === 'contrast') { + style.color = this.annotation.chart.renderer.getContrast(ControllableLabel.shapesWithoutBackground.indexOf(options.shape) > -1 ? '#FFFFFF' : options.backgroundColor); + } + this.graphic + .css(options.style) + .shadow(options.shadow); + } + if (options.className) { + this.graphic.addClass(options.className); + } + this.graphic.labelrank = options.labelrank; + controllableMixin.render.call(this); + }, + redraw: function (animation) { + var options = this.options, text = this.text || options.format || options.text, label = this.graphic, point = this.points[0], show = false, anchor, attrs; + label.attr({ + text: text ? + format(text, point.getLabelConfig(), this.annotation.chart) : + options.formatter.call(point, this) + }); + anchor = this.anchor(point); + attrs = this.position(anchor); + show = attrs; + if (show) { + label.alignAttr = attrs; + attrs.anchorX = anchor.absolutePosition.x; + attrs.anchorY = anchor.absolutePosition.y; + label[animation ? 'animate' : 'attr'](attrs); + } + else { + label.attr({ + x: 0, + y: -9999 // #10055 + }); + } + label.placed = Boolean(show); + controllableMixin.redraw.call(this, animation); + }, + /** + * All basic shapes don't support alignTo() method except label. + * For a controllable label, we need to subtract translation from + * options. + */ + anchor: function () { + var anchor = controllableMixin.anchor.apply(this, arguments), x = this.options.x || 0, y = this.options.y || 0; + anchor.absolutePosition.x -= x; + anchor.absolutePosition.y -= y; + anchor.relativePosition.x -= x; + anchor.relativePosition.y -= y; + return anchor; + }, + /** + * Returns the label position relative to its anchor. + * + * @param {Highcharts.AnnotationAnchorObject} anchor + * + * @return {Highcharts.PositionObject|null} + */ + position: function (anchor) { + var item = this.graphic, chart = this.annotation.chart, point = this.points[0], itemOptions = this.options, anchorAbsolutePosition = anchor.absolutePosition, anchorRelativePosition = anchor.relativePosition, itemPosition, alignTo, itemPosRelativeX, itemPosRelativeY, showItem = point.series.visible && + MockPoint.prototype.isInsidePlot.call(point); + if (showItem) { + if (itemOptions.distance) { + itemPosition = Tooltip.prototype.getPosition.call({ + chart: chart, + distance: pick(itemOptions.distance, 16) + }, item.width, item.height, { + plotX: anchorRelativePosition.x, + plotY: anchorRelativePosition.y, + negative: point.negative, + ttBelow: point.ttBelow, + h: (anchorRelativePosition.height || anchorRelativePosition.width) + }); + } + else if (itemOptions.positioner) { + itemPosition = itemOptions.positioner.call(this); + } + else { + alignTo = { + x: anchorAbsolutePosition.x, + y: anchorAbsolutePosition.y, + width: 0, + height: 0 + }; + itemPosition = ControllableLabel.alignedPosition(extend(itemOptions, { + width: item.width, + height: item.height + }), alignTo); + if (this.options.overflow === 'justify') { + itemPosition = ControllableLabel.alignedPosition(ControllableLabel.justifiedOptions(chart, item, itemOptions, itemPosition), alignTo); + } + } + if (itemOptions.crop) { + itemPosRelativeX = itemPosition.x - chart.plotLeft; + itemPosRelativeY = itemPosition.y - chart.plotTop; + showItem = + chart.isInsidePlot(itemPosRelativeX, itemPosRelativeY) && + chart.isInsidePlot(itemPosRelativeX + item.width, itemPosRelativeY + item.height); + } + } + return showItem ? itemPosition : null; + } + }); + /* ********************************************************************** */ + /** + * General symbol definition for labels with connector + * @private + */ + H.SVGRenderer.prototype.symbols.connector = function (x, y, w, h, options) { + var anchorX = options && options.anchorX, anchorY = options && options.anchorY, path, yOffset, lateral = w / 2; + if (isNumber(anchorX) && isNumber(anchorY)) { + path = [['M', anchorX, anchorY]]; + // Prefer 45 deg connectors + yOffset = y - anchorY; + if (yOffset < 0) { + yOffset = -h - yOffset; + } + if (yOffset < w) { + lateral = anchorX < x + (w / 2) ? yOffset : w - yOffset; + } + // Anchor below label + if (anchorY > y + h) { + path.push(['L', x + lateral, y + h]); + // Anchor above label + } + else if (anchorY < y) { + path.push(['L', x + lateral, y]); + // Anchor left of label + } + else if (anchorX < x) { + path.push(['L', x, y + h / 2]); + // Anchor right of label + } + else if (anchorX > x + w) { + path.push(['L', x + w, y + h / 2]); + } + } + return path || []; + }; + + return ControllableLabel; + }); + _registerModule(_modules, 'annotations/controllable/ControllableImage.js', [_modules['parts/Utilities.js'], _modules['annotations/controllable/controllableMixin.js'], _modules['annotations/controllable/ControllableLabel.js']], function (U, controllableMixin, ControllableLabel) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var merge = U.merge; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * A controllable image class. + * + * @requires modules/annotations + * + * @private + * @class + * @name Highcharts.AnnotationControllableImage + * + * @param {Highcharts.Annotation} annotation + * An annotation instance. + * + * @param {Highcharts.AnnotationsShapeOptions} options + * A controllable's options. + * + * @param {number} index + * Index of the image. + **/ + var ControllableImage = function (annotation, options, index) { + this.init(annotation, options, index); + this.collection = 'shapes'; + }; + /** + * A map object which allows to map options attributes to element attributes + * + * @name Highcharts.AnnotationControllableImage.attrsMap + * @type {Highcharts.Dictionary} + */ + ControllableImage.attrsMap = { + width: 'width', + height: 'height', + zIndex: 'zIndex' + }; + merge(true, ControllableImage.prototype, controllableMixin, /** @lends Annotation.ControllableImage# */ { + /** + * @type 'image' + */ + type: 'image', + translate: controllableMixin.translateShape, + render: function (parent) { + var attrs = this.attrsFromOptions(this.options), options = this.options; + this.graphic = this.annotation.chart.renderer + .image(options.src, 0, -9e9, options.width, options.height) + .attr(attrs) + .add(parent); + this.graphic.width = options.width; + this.graphic.height = options.height; + controllableMixin.render.call(this); + }, + redraw: function (animation) { + var anchor = this.anchor(this.points[0]), position = ControllableLabel.prototype.position.call(this, anchor); + if (position) { + this.graphic[animation ? 'animate' : 'attr']({ + x: position.x, + y: position.y + }); + } + else { + this.graphic.attr({ + x: 0, + y: -9e9 + }); + } + this.graphic.placed = Boolean(position); + controllableMixin.redraw.call(this, animation); + } + }); + + return ControllableImage; + }); + _registerModule(_modules, 'annotations/annotations.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['annotations/controllable/controllableMixin.js'], _modules['annotations/controllable/ControllableRect.js'], _modules['annotations/controllable/ControllableCircle.js'], _modules['annotations/controllable/ControllablePath.js'], _modules['annotations/controllable/ControllableImage.js'], _modules['annotations/controllable/ControllableLabel.js'], _modules['annotations/eventEmitterMixin.js'], _modules['annotations/MockPoint.js'], _modules['annotations/ControlPoint.js']], function (H, U, controllableMixin, ControllableRect, ControllableCircle, ControllablePath, ControllableImage, ControllableLabel, eventEmitterMixin, MockPoint, ControlPoint) { + /* * + * + * (c) 2009-2017 Highsoft, Black Label + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, erase = U.erase, extend = U.extend, find = U.find, fireEvent = U.fireEvent, merge = U.merge, pick = U.pick, splat = U.splat, wrap = U.wrap; + var chartProto = H.Chart.prototype; + /* ********************************************************************* + * + * ANNOTATION + * + ******************************************************************** */ + /** + * Possible directions for draggable annotations. An empty string (`''`) + * makes the annotation undraggable. + * + * @typedef {''|'x'|'xy'|'y'} Highcharts.AnnotationDraggableValue + */ + /** + * @private + * @typedef { + * Highcharts.AnnotationControllableCircle| + * Highcharts.AnnotationControllableImage| + * Highcharts.AnnotationControllablePath| + * Highcharts.AnnotationControllableRect + * } + * Highcharts.AnnotationShapeType + * @requires modules/annotations + */ + /** + * @private + * @typedef { + * Highcharts.AnnotationControllableLabel + * } + * Highcharts.AnnotationLabelType + * @requires modules/annotations + */ + /** + * A point-like object, a mock point or a point used in series. + * @private + * @typedef {Highcharts.AnnotationMockPoint|Highcharts.Point} Highcharts.AnnotationPointType + * @requires modules/annotations + */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * An annotation class which serves as a container for items like labels or + * shapes. Created items are positioned on the chart either by linking them to + * existing points or created mock points + * + * @class + * @name Highcharts.Annotation + * + * @param {Highcharts.Chart} chart a chart instance + * @param {Highcharts.AnnotationsOptions} userOptions the options object + */ + var Annotation = H.Annotation = function (chart, userOptions) { + var labelsAndShapes; + /** + * The chart that the annotation belongs to. + * + * @type {Highcharts.Chart} + */ + this.chart = chart; + /** + * The array of points which defines the annotation. + * + * @type {Array} + */ + this.points = []; + /** + * The array of control points. + * + * @private + * @name Highcharts.Annotation#controlPoints + * @type {Array} + */ + this.controlPoints = []; + this.coll = 'annotations'; + /** + * The array of labels which belong to the annotation. + * + * @private + * @name Highcharts.Annotation#labels + * @type {Array} + */ + this.labels = []; + /** + * The array of shapes which belong to the annotation. + * + * @private + * @name Highcharts.Annotation#shapes + * @type {Array} + */ + this.shapes = []; + /** + * The options for the annotations. + * + * @name Highcharts.Annotation#options + * @type {Highcharts.AnnotationsOptions} + */ + this.options = merge(this.defaultOptions, userOptions); + /** + * The user options for the annotations. + * + * @name Highcharts.Annotation#userOptions + * @type {Highcharts.AnnotationsOptions} + */ + this.userOptions = userOptions; + // Handle labels and shapes - those are arrays + // Merging does not work with arrays (stores reference) + labelsAndShapes = this.getLabelsAndShapesOptions(this.options, userOptions); + this.options.labels = labelsAndShapes.labels; + this.options.shapes = labelsAndShapes.shapes; + /** + * The callback that reports to the overlapping-labels module which + * labels it should account for. + * @private + * @name Highcharts.Annotation#labelCollector + * @type {Function} + */ + /** + * The group svg element. + * + * @name Highcharts.Annotation#group + * @type {Highcharts.SVGElement} + */ + /** + * The group svg element of the annotation's shapes. + * + * @name Highcharts.Annotation#shapesGroup + * @type {Highcharts.SVGElement} + */ + /** + * The group svg element of the annotation's labels. + * + * @name Highcharts.Annotation#labelsGroup + * @type {Highcharts.SVGElement} + */ + this.init(chart, this.options); + }; + merge(true, Annotation.prototype, controllableMixin, eventEmitterMixin, + /** @lends Highcharts.Annotation# */ + { + /** + * List of events for `annotation.options.events` that should not be + * added to `annotation.graphic` but to the `annotation`. + * + * @private + * @type {Array} + */ + nonDOMEvents: ['add', 'afterUpdate', 'drag', 'remove'], + /** + * A basic type of an annotation. It allows to add custom labels + * or shapes. The items can be tied to points, axis coordinates + * or chart pixel coordinates. + * + * @sample highcharts/annotations/basic/ + * Basic annotations + * @sample highcharts/demo/annotations/ + * Advanced annotations + * @sample highcharts/css/annotations + * Styled mode + * @sample highcharts/annotations-advanced/controllable + * Controllable items + * @sample {highstock} stock/annotations/fibonacci-retracements + * Custom annotation, Fibonacci retracement + * + * @type {Array<*>} + * @since 6.0.0 + * @requires modules/annotations + * @optionparent annotations + * + * @private + */ + defaultOptions: { + /** + * Sets an ID for an annotation. Can be user later when removing an + * annotation in [Chart#removeAnnotation(id)]( + * /class-reference/Highcharts.Chart#removeAnnotation) method. + * + * @type {number|string} + * @apioption annotations.id + */ + /** + * Whether the annotation is visible. + * + * @sample highcharts/annotations/visible/ + * Set annotation visibility + */ + visible: true, + /** + * Allow an annotation to be draggable by a user. Possible + * values are `'x'`, `'xy'`, `'y'` and `''` (disabled). + * + * @sample highcharts/annotations/draggable/ + * Annotations draggable: 'xy' + * + * @type {Highcharts.AnnotationDraggableValue} + */ + draggable: 'xy', + /** + * Options for annotation's labels. Each label inherits options + * from the labelOptions object. An option from the labelOptions + * can be overwritten by config for a specific label. + * + * @requires modules/annotations + */ + labelOptions: { + /** + * The alignment of the annotation's label. If right, + * the right side of the label should be touching the point. + * + * @sample highcharts/annotations/label-position/ + * Set labels position + * + * @type {Highcharts.AlignValue} + */ + align: 'center', + /** + * Whether to allow the annotation's labels to overlap. + * To make the labels less sensitive for overlapping, + * the can be set to 0. + * + * @sample highcharts/annotations/tooltip-like/ + * Hide overlapping labels + */ + allowOverlap: false, + /** + * The background color or gradient for the annotation's label. + * + * @sample highcharts/annotations/label-presentation/ + * Set labels graphic options + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + backgroundColor: 'rgba(0, 0, 0, 0.75)', + /** + * The border color for the annotation's label. + * + * @sample highcharts/annotations/label-presentation/ + * Set labels graphic options + * + * @type {Highcharts.ColorString} + */ + borderColor: 'black', + /** + * The border radius in pixels for the annotaiton's label. + * + * @sample highcharts/annotations/label-presentation/ + * Set labels graphic options + */ + borderRadius: 3, + /** + * The border width in pixels for the annotation's label + * + * @sample highcharts/annotations/label-presentation/ + * Set labels graphic options + */ + borderWidth: 1, + /** + * A class name for styling by CSS. + * + * @sample highcharts/css/annotations + * Styled mode annotations + * + * @since 6.0.5 + */ + className: '', + /** + * Whether to hide the annotation's label + * that is outside the plot area. + * + * @sample highcharts/annotations/label-crop-overflow/ + * Crop or justify labels + */ + crop: false, + /** + * The label's pixel distance from the point. + * + * @sample highcharts/annotations/label-position/ + * Set labels position + * + * @type {number} + * @apioption annotations.labelOptions.distance + */ + /** + * A + * [format](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) + * string for the data label. + * + * @see [plotOptions.series.dataLabels.format](plotOptions.series.dataLabels.format.html) + * + * @sample highcharts/annotations/label-text/ + * Set labels text + * + * @type {string} + * @apioption annotations.labelOptions.format + */ + /** + * Alias for the format option. + * + * @see [format](annotations.labelOptions.format.html) + * + * @sample highcharts/annotations/label-text/ + * Set labels text + * + * @type {string} + * @apioption annotations.labelOptions.text + */ + /** + * Callback JavaScript function to format the annotation's + * label. Note that if a `format` or `text` are defined, the + * format or text take precedence and the formatter is ignored. + * `This` refers to a point object. + * + * @sample highcharts/annotations/label-text/ + * Set labels text + * + * @type {Highcharts.FormatterCallbackFunction} + * @default function () { return defined(this.y) ? this.y : 'Annotation label'; } + */ + formatter: function () { + return defined(this.y) ? this.y : 'Annotation label'; + }, + /** + * How to handle the annotation's label that flow outside the + * plot area. The justify option aligns the label inside the + * plot area. + * + * @sample highcharts/annotations/label-crop-overflow/ + * Crop or justify labels + * + * @validvalue ["allow", "justify"] + */ + overflow: 'justify', + /** + * When either the borderWidth or the backgroundColor is set, + * this is the padding within the box. + * + * @sample highcharts/annotations/label-presentation/ + * Set labels graphic options + */ + padding: 5, + /** + * The shadow of the box. The shadow can be an object + * configuration containing `color`, `offsetX`, `offsetY`, + * `opacity` and `width`. + * + * @sample highcharts/annotations/label-presentation/ + * Set labels graphic options + * + * @type {boolean|Highcharts.ShadowOptionsObject} + */ + shadow: false, + /** + * The name of a symbol to use for the border around the label. + * Symbols are predefined functions on the Renderer object. + * + * @sample highcharts/annotations/shapes/ + * Available shapes for labels + */ + shape: 'callout', + /** + * Styles for the annotation's label. + * + * @see [plotOptions.series.dataLabels.style](plotOptions.series.dataLabels.style.html) + * + * @sample highcharts/annotations/label-presentation/ + * Set labels graphic options + * + * @type {Highcharts.CSSObject} + */ + style: { + /** @ignore */ + fontSize: '11px', + /** @ignore */ + fontWeight: 'normal', + /** @ignore */ + color: 'contrast' + }, + /** + * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) + * to render the annotation's label. + */ + useHTML: false, + /** + * The vertical alignment of the annotation's label. + * + * @sample highcharts/annotations/label-position/ + * Set labels position + * + * @type {Highcharts.VerticalAlignValue} + */ + verticalAlign: 'bottom', + /** + * The x position offset of the label relative to the point. + * Note that if a `distance` is defined, the distance takes + * precedence over `x` and `y` options. + * + * @sample highcharts/annotations/label-position/ + * Set labels position + */ + x: 0, + /** + * The y position offset of the label relative to the point. + * Note that if a `distance` is defined, the distance takes + * precedence over `x` and `y` options. + * + * @sample highcharts/annotations/label-position/ + * Set labels position + */ + y: -16 + }, + /** + * An array of labels for the annotation. For options that apply to + * multiple labels, they can be added to the + * [labelOptions](annotations.labelOptions.html). + * + * @type {Array<*>} + * @extends annotations.labelOptions + * @apioption annotations.labels + */ + /** + * This option defines the point to which the label will be + * connected. It can be either the point which exists in the + * series - it is referenced by the point's id - or a new point with + * defined x, y properties and optionally axes. + * + * @sample highcharts/annotations/mock-point/ + * Attach annotation to a mock point + * + * @declare Highcharts.AnnotationMockPointOptionsObject + * @type {string|*} + * @requires modules/annotations + * @apioption annotations.labels.point + */ + /** + * The x position of the point. Units can be either in axis + * or chart pixel coordinates. + * + * @type {number} + * @apioption annotations.labels.point.x + */ + /** + * The y position of the point. Units can be either in axis + * or chart pixel coordinates. + * + * @type {number} + * @apioption annotations.labels.point.y + */ + /** + * This number defines which xAxis the point is connected to. It + * refers to either the axis id or the index of the axis in the + * xAxis array. If the option is not configured or the axis is not + * found the point's x coordinate refers to the chart pixels. + * + * @type {number|string|null} + * @apioption annotations.labels.point.xAxis + */ + /** + * This number defines which yAxis the point is connected to. It + * refers to either the axis id or the index of the axis in the + * yAxis array. If the option is not configured or the axis is not + * found the point's y coordinate refers to the chart pixels. + * + * @type {number|string|null} + * @apioption annotations.labels.point.yAxis + */ + /** + * An array of shapes for the annotation. For options that apply to + * multiple shapes, then can be added to the + * [shapeOptions](annotations.shapeOptions.html). + * + * @type {Array<*>} + * @extends annotations.shapeOptions + * @apioption annotations.shapes + */ + /** + * This option defines the point to which the shape will be + * connected. It can be either the point which exists in the + * series - it is referenced by the point's id - or a new point with + * defined x, y properties and optionally axes. + * + * @declare Highcharts.AnnotationMockPointOptionsObject + * @type {string|Highcharts.AnnotationMockPointOptionsObject} + * @extends annotations.labels.point + * @apioption annotations.shapes.point + */ + /** + * An array of points for the shape. This option is available for + * shapes which can use multiple points such as path. A point can be + * either a point object or a point's id. + * + * @see [annotations.shapes.point](annotations.shapes.point.html) + * + * @declare Highcharts.AnnotationMockPointOptionsObject + * @type {Array} + * @extends annotations.labels.point + * @apioption annotations.shapes.points + */ + /** + * The URL for an image to use as the annotation shape. Note, + * type has to be set to `'image'`. + * + * @see [annotations.shapes.type](annotations.shapes.type) + * @sample highcharts/annotations/shape-src/ + * Define a marker image url for annotations + * + * @type {string} + * @apioption annotations.shapes.src + */ + /** + * Id of the marker which will be drawn at the final vertex of the + * path. Custom markers can be defined in defs property. + * + * @see [defs.markers](defs.markers.html) + * + * @sample highcharts/annotations/custom-markers/ + * Define a custom marker for annotations + * + * @type {string} + * @apioption annotations.shapes.markerEnd + */ + /** + * Id of the marker which will be drawn at the first vertex of the + * path. Custom markers can be defined in defs property. + * + * @see [defs.markers](defs.markers.html) + * + * @sample {highcharts} highcharts/annotations/custom-markers/ + * Define a custom marker for annotations + * + * @type {string} + * @apioption annotations.shapes.markerStart + */ + /** + * Options for annotation's shapes. Each shape inherits options from + * the shapeOptions object. An option from the shapeOptions can be + * overwritten by config for a specific shape. + * + * @requires modules/annotations + */ + shapeOptions: { + /** + * The width of the shape. + * + * @sample highcharts/annotations/shape/ + * Basic shape annotation + * + * @type {number} + * @apioption annotations.shapeOptions.width + **/ + /** + * The height of the shape. + * + * @sample highcharts/annotations/shape/ + * Basic shape annotation + * + * @type {number} + * @apioption annotations.shapeOptions.height + */ + /** + * The type of the shape, e.g. circle or rectangle. + * + * @sample highcharts/annotations/shape/ + * Basic shape annotation + * + * @type {string} + * @default 'rect' + * @apioption annotations.shapeOptions.type + */ + /** + * The URL for an image to use as the annotation shape. Note, + * type has to be set to `'image'`. + * + * @see [annotations.shapeOptions.type](annotations.shapeOptions.type) + * @sample highcharts/annotations/shape-src/ + * Define a marker image url for annotations + * + * @type {string} + * @apioption annotations.shapeOptions.src + */ + /** + * Name of the dash style to use for the shape's stroke. + * + * @sample {highcharts} highcharts/plotoptions/series-dashstyle-all/ + * Possible values demonstrated + * + * @type {Highcharts.DashStyleValue} + * @apioption annotations.shapeOptions.dashStyle + */ + /** + * The color of the shape's stroke. + * + * @sample highcharts/annotations/shape/ + * Basic shape annotation + * + * @type {Highcharts.ColorString} + */ + stroke: 'rgba(0, 0, 0, 0.75)', + /** + * The pixel stroke width of the shape. + * + * @sample highcharts/annotations/shape/ + * Basic shape annotation + */ + strokeWidth: 1, + /** + * The color of the shape's fill. + * + * @sample highcharts/annotations/shape/ + * Basic shape annotation + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + fill: 'rgba(0, 0, 0, 0.75)', + /** + * The radius of the shape. + * + * @sample highcharts/annotations/shape/ + * Basic shape annotation + */ + r: 0, + /** + * Defines additional snapping area around an annotation + * making this annotation to focus. Defined in pixels. + */ + snap: 2 + }, + /** + * Options for annotation's control points. Each control point + * inherits options from controlPointOptions object. + * Options from the controlPointOptions can be overwritten + * by options in a specific control point. + * + * @declare Highcharts.AnnotationControlPointOptionsObject + * @requires modules/annotations + * @apioption annotations.controlPointOptions + */ + controlPointOptions: { + /** + * @type {Highcharts.AnnotationControlPointPositionerFunction} + * @apioption annotations.controlPointOptions.positioner + */ + symbol: 'circle', + width: 10, + height: 10, + style: { + stroke: 'black', + 'stroke-width': 2, + fill: 'white' + }, + visible: false, + events: {} + }, + /** + * Event callback when annotation is added to the chart. + * + * @type {Highcharts.EventCallbackFunction} + * @since 7.1.0 + * @apioption annotations.events.add + */ + /** + * Event callback when annotation is updated (e.g. drag and + * droppped or resized by control points). + * + * @type {Highcharts.EventCallbackFunction} + * @since 7.1.0 + * @apioption annotations.events.afterUpdate + */ + /** + * Event callback when annotation is removed from the chart. + * + * @type {Highcharts.EventCallbackFunction} + * @since 7.1.0 + * @apioption annotations.events.remove + */ + /** + * Events available in annotations. + * + * @requires modules/annotations + */ + events: {}, + /** + * The Z index of the annotation. + */ + zIndex: 6 + }, + /** + * Initialize the annotation. + * @private + */ + init: function () { + this.linkPoints(); + this.addControlPoints(); + this.addShapes(); + this.addLabels(); + this.setLabelCollector(); + }, + getLabelsAndShapesOptions: function (baseOptions, newOptions) { + var mergedOptions = {}; + ['labels', 'shapes'].forEach(function (name) { + if (baseOptions[name]) { + mergedOptions[name] = splat(newOptions[name]).map(function (basicOptions, i) { + return merge(baseOptions[name][i], basicOptions); + }); + } + }); + return mergedOptions; + }, + addShapes: function () { + (this.options.shapes || []).forEach(function (shapeOptions, i) { + var shape = this.initShape(shapeOptions, i); + merge(true, this.options.shapes[i], shape.options); + }, this); + }, + addLabels: function () { + (this.options.labels || []).forEach(function (labelsOptions, i) { + var labels = this.initLabel(labelsOptions, i); + merge(true, this.options.labels[i], labels.options); + }, this); + }, + addClipPaths: function () { + this.setClipAxes(); + if (this.clipXAxis && this.clipYAxis) { + this.clipRect = this.chart.renderer.clipRect(this.getClipBox()); + } + }, + setClipAxes: function () { + var xAxes = this.chart.xAxis, yAxes = this.chart.yAxis, linkedAxes = (this.options.labels || []) + .concat(this.options.shapes || []) + .reduce(function (axes, labelOrShape) { + return [ + xAxes[labelOrShape && + labelOrShape.point && + labelOrShape.point.xAxis] || axes[0], + yAxes[labelOrShape && + labelOrShape.point && + labelOrShape.point.yAxis] || axes[1] + ]; + }, []); + this.clipXAxis = linkedAxes[0]; + this.clipYAxis = linkedAxes[1]; + }, + getClipBox: function () { + if (this.clipXAxis && this.clipYAxis) { + return { + x: this.clipXAxis.left, + y: this.clipYAxis.top, + width: this.clipXAxis.width, + height: this.clipYAxis.height + }; + } + }, + setLabelCollector: function () { + var annotation = this; + annotation.labelCollector = function () { + return annotation.labels.reduce(function (labels, label) { + if (!label.options.allowOverlap) { + labels.push(label.graphic); + } + return labels; + }, []); + }; + annotation.chart.labelCollectors.push(annotation.labelCollector); + }, + /** + * Set an annotation options. + * @private + * @param {Highcharts.AnnotationsOptions} - user options for an annotation + */ + setOptions: function (userOptions) { + this.options = merge(this.defaultOptions, userOptions); + }, + redraw: function (animation) { + this.linkPoints(); + if (!this.graphic) { + this.render(); + } + if (this.clipRect) { + this.clipRect.animate(this.getClipBox()); + } + this.redrawItems(this.shapes, animation); + this.redrawItems(this.labels, animation); + controllableMixin.redraw.call(this, animation); + }, + /** + * @private + * @param {Array} items + * @param {boolean} [animation] + */ + redrawItems: function (items, animation) { + var i = items.length; + // needs a backward loop + // labels/shapes array might be modified + // due to destruction of the item + while (i--) { + this.redrawItem(items[i], animation); + } + }, + /** + * @private + * @param {Array} items + */ + renderItems: function (items) { + var i = items.length; + while (i--) { + this.renderItem(items[i]); + } + }, + render: function () { + var renderer = this.chart.renderer; + this.graphic = renderer + .g('annotation') + .attr({ + zIndex: this.options.zIndex, + visibility: this.options.visible ? + 'visible' : + 'hidden' + }) + .add(); + this.shapesGroup = renderer + .g('annotation-shapes') + .add(this.graphic) + .clip(this.chart.plotBoxClip); + this.labelsGroup = renderer + .g('annotation-labels') + .attr({ + // hideOverlappingLabels requires translation + translateX: 0, + translateY: 0 + }) + .add(this.graphic); + this.addClipPaths(); + if (this.clipRect) { + this.graphic.clip(this.clipRect); + } + // Render shapes and labels before adding events (#13070). + this.renderItems(this.shapes); + this.renderItems(this.labels); + this.addEvents(); + controllableMixin.render.call(this); + }, + /** + * Set the annotation's visibility. + * @private + * @param {boolean} [visible] + * Whether to show or hide an annotation. If the param is omitted, the + * annotation's visibility is toggled. + */ + setVisibility: function (visible) { + var options = this.options, visibility = pick(visible, !options.visible); + this.graphic.attr('visibility', visibility ? 'visible' : 'hidden'); + if (!visibility) { + this.setControlPointsVisibility(false); + } + options.visible = visibility; + }, + setControlPointsVisibility: function (visible) { + var setItemControlPointsVisibility = function (item) { + item.setControlPointsVisibility(visible); + }; + controllableMixin.setControlPointsVisibility.call(this, visible); + this.shapes.forEach(setItemControlPointsVisibility); + this.labels.forEach(setItemControlPointsVisibility); + }, + /** + * Destroy the annotation. This function does not touch the chart + * that the annotation belongs to (all annotations are kept in + * the chart.annotations array) - it is recommended to use + * {@link Highcharts.Chart#removeAnnotation} instead. + * @private + */ + destroy: function () { + var chart = this.chart, destroyItem = function (item) { + item.destroy(); + }; + this.labels.forEach(destroyItem); + this.shapes.forEach(destroyItem); + this.clipXAxis = null; + this.clipYAxis = null; + erase(chart.labelCollectors, this.labelCollector); + eventEmitterMixin.destroy.call(this); + controllableMixin.destroy.call(this); + destroyObjectProperties(this, chart); + }, + /** + * See {@link Highcharts.Chart#removeAnnotation}. + * @private + */ + remove: function () { + // Let chart.update() remove annoations on demand + return this.chart.removeAnnotation(this); + }, + /** + * Updates an annotation. + * + * @function Highcharts.Annotation#update + * + * @param {Partial} userOptions + * New user options for the annotation. + * + * @return {void} + */ + update: function (userOptions, redraw) { + var chart = this.chart, labelsAndShapes = this.getLabelsAndShapesOptions(this.userOptions, userOptions), userOptionsIndex = chart.annotations.indexOf(this), options = merge(true, this.userOptions, userOptions); + options.labels = labelsAndShapes.labels; + options.shapes = labelsAndShapes.shapes; + this.destroy(); + this.constructor(chart, options); + // Update options in chart options, used in exporting (#9767): + chart.options.annotations[userOptionsIndex] = options; + this.isUpdating = true; + if (pick(redraw, true)) { + chart.redraw(); + } + fireEvent(this, 'afterUpdate'); + this.isUpdating = false; + }, + /* ************************************************************* + * ITEM SECTION + * Contains methods for handling a single item in an annotation + **************************************************************** */ + /** + * Initialisation of a single shape + * @private + * @param {Object} shapeOptions - a confg object for a single shape + */ + initShape: function (shapeOptions, index) { + var options = merge(this.options.shapeOptions, { + controlPointOptions: this.options.controlPointOptions + }, shapeOptions), shape = new Annotation.shapesMap[options.type](this, options, index); + shape.itemType = 'shape'; + this.shapes.push(shape); + return shape; + }, + /** + * Initialisation of a single label + * @private + */ + initLabel: function (labelOptions, index) { + var options = merge(this.options.labelOptions, { + controlPointOptions: this.options.controlPointOptions + }, labelOptions), label = new ControllableLabel(this, options, index); + label.itemType = 'label'; + this.labels.push(label); + return label; + }, + /** + * Redraw a single item. + * @private + * @param {Annotation.Label|Annotation.Shape} item + * @param {boolean} [animation] + */ + redrawItem: function (item, animation) { + item.linkPoints(); + if (!item.shouldBeDrawn()) { + this.destroyItem(item); + } + else { + if (!item.graphic) { + this.renderItem(item); + } + item.redraw(pick(animation, true) && item.graphic.placed); + if (item.points.length) { + this.adjustVisibility(item); + } + } + }, + /** + * Hide or show annotaiton attached to points. + * @private + * @param {Annotation.Label|Annotation.Shape} item + */ + adjustVisibility: function (item) { + var hasVisiblePoints = false, label = item.graphic; + item.points.forEach(function (point) { + if (point.series.visible !== false && + point.visible !== false) { + hasVisiblePoints = true; + } + }); + if (!hasVisiblePoints) { + label.hide(); + } + else if (label.visibility === 'hidden') { + label.show(); + } + }, + /** + * Destroy a single item. + * @private + * @param {Annotation.Label|Annotation.Shape} item + */ + destroyItem: function (item) { + // erase from shapes or labels array + erase(this[item.itemType + 's'], item); + item.destroy(); + }, + /** + * @private + */ + renderItem: function (item) { + item.render(item.itemType === 'label' ? + this.labelsGroup : + this.shapesGroup); + } + }); + /** + * An object uses for mapping between a shape type and a constructor. + * To add a new shape type extend this object with type name as a key + * and a constructor as its value. + */ + Annotation.shapesMap = { + 'rect': ControllableRect, + 'circle': ControllableCircle, + 'path': ControllablePath, + 'image': ControllableImage + }; + Annotation.types = {}; + Annotation.MockPoint = MockPoint; + Annotation.ControlPoint = ControlPoint; + H.extendAnnotation = function (Constructor, BaseConstructor, prototype, defaultOptions) { + BaseConstructor = BaseConstructor || Annotation; + merge(true, Constructor.prototype, BaseConstructor.prototype, prototype); + Constructor.prototype.defaultOptions = merge(Constructor.prototype.defaultOptions, defaultOptions || {}); + }; + /* ********************************************************************* + * + * EXTENDING CHART PROTOTYPE + * + ******************************************************************** */ + extend(chartProto, /** @lends Highcharts.Chart# */ { + initAnnotation: function (userOptions) { + var Constructor = Annotation.types[userOptions.type] || Annotation, annotation = new Constructor(this, userOptions); + this.annotations.push(annotation); + return annotation; + }, + /** + * Add an annotation to the chart after render time. + * + * @param {Highcharts.AnnotationsOptions} options + * The annotation options for the new, detailed annotation. + * @param {boolean} [redraw] + * + * @return {Highcharts.Annotation} - The newly generated annotation. + */ + addAnnotation: function (userOptions, redraw) { + var annotation = this.initAnnotation(userOptions); + this.options.annotations.push(annotation.options); + if (pick(redraw, true)) { + annotation.redraw(); + } + return annotation; + }, + /** + * Remove an annotation from the chart. + * + * @param {number|string|Highcharts.Annotation} idOrAnnotation + * The annotation's id or direct annotation object. + */ + removeAnnotation: function (idOrAnnotation) { + var annotations = this.annotations, annotation = idOrAnnotation.coll === 'annotations' ? + idOrAnnotation : + find(annotations, function (annotation) { + return annotation.options.id === idOrAnnotation; + }); + if (annotation) { + fireEvent(annotation, 'remove'); + erase(this.options.annotations, annotation.options); + erase(annotations, annotation); + annotation.destroy(); + } + }, + drawAnnotations: function () { + this.plotBoxClip.attr(this.plotBox); + this.annotations.forEach(function (annotation) { + annotation.redraw(); + }); + } + }); + // Let chart.update() update annotations + chartProto.collectionsWithUpdate.push('annotations'); + // Let chart.update() create annoations on demand + chartProto.collectionsWithInit.annotations = [chartProto.addAnnotation]; + chartProto.callbacks.push(function (chart) { + chart.annotations = []; + if (!chart.options.annotations) { + chart.options.annotations = []; + } + chart.plotBoxClip = this.renderer.clipRect(this.plotBox); + chart.controlPointsGroup = chart.renderer + .g('control-points') + .attr({ zIndex: 99 }) + .clip(chart.plotBoxClip) + .add(); + chart.options.annotations.forEach(function (annotationOptions, i) { + var annotation = chart.initAnnotation(annotationOptions); + chart.options.annotations[i] = annotation.options; + }); + chart.drawAnnotations(); + addEvent(chart, 'redraw', chart.drawAnnotations); + addEvent(chart, 'destroy', function () { + chart.plotBoxClip.destroy(); + chart.controlPointsGroup.destroy(); + }); + }); + wrap(H.Pointer.prototype, 'onContainerMouseDown', function (proceed) { + if (!this.chart.hasDraggedAnnotation) { + proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + } + }); + + }); + _registerModule(_modules, 'mixins/navigation.js', [], function () { + /** + * + * (c) 2010-2018 Paweł Fus + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var chartNavigation = { + /** + * Initializes `chart.navigation` object which delegates `update()` methods + * to all other common classes (used in exporting and navigationBindings). + * + * @private + * @param {Highcharts.Chart} chart + * The chart instance. + * @return {void} + */ + initUpdate: function (chart) { + if (!chart.navigation) { + chart.navigation = { + updates: [], + update: function (options, redraw) { + this.updates.forEach(function (updateConfig) { + updateConfig.update.call(updateConfig.context, options, redraw); + }); + } + }; + } + }, + /** + * Registers an `update()` method in the `chart.navigation` object. + * + * @private + * @param {Highcharts.ChartNavigationUpdateFunction} update + * The `update()` method that will be called in `chart.update()`. + * @param {Highcharts.Chart} chart + * The chart instance. `update()` will use that as a context + * (`this`). + * @return {void} + */ + addUpdate: function (update, chart) { + if (!chart.navigation) { + this.initUpdate(chart); + } + chart.navigation.updates.push({ + update: update, + context: chart + }); + } + }; + + return chartNavigation; + }); + _registerModule(_modules, 'annotations/navigationBindings.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['mixins/navigation.js']], function (H, U, chartNavigationMixin) { + /* * + * + * (c) 2009-2017 Highsoft, Black Label + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * A config object for navigation bindings in annotations. + * + * @interface Highcharts.NavigationBindingsOptionsObject + */ /** + * ClassName of the element for a binding. + * @name Highcharts.NavigationBindingsOptionsObject#className + * @type {string|undefined} + */ /** + * Last event to be fired after last step event. + * @name Highcharts.NavigationBindingsOptionsObject#end + * @type {Function|undefined} + */ /** + * Initial event, fired on a button click. + * @name Highcharts.NavigationBindingsOptionsObject#init + * @type {Function|undefined} + */ /** + * Event fired on first click on a chart. + * @name Highcharts.NavigationBindingsOptionsObject#start + * @type {Function|undefined} + */ /** + * Last event to be fired after last step event. Array of step events to be + * called sequentially after each user click. + * @name Highcharts.NavigationBindingsOptionsObject#steps + * @type {Array|undefined} + */ + var addEvent = U.addEvent, attr = U.attr, extend = U.extend, format = U.format, fireEvent = U.fireEvent, isArray = U.isArray, isFunction = U.isFunction, isNumber = U.isNumber, isObject = U.isObject, merge = U.merge, objectEach = U.objectEach, pick = U.pick; + var doc = H.doc, win = H.win, PREFIX = 'highcharts-'; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * IE 9-11 polyfill for Element.closest(): + * @private + */ + function closestPolyfill(el, s) { + var ElementProto = win.Element.prototype, elementMatches = ElementProto.matches || + ElementProto.msMatchesSelector || + ElementProto.webkitMatchesSelector, ret = null; + if (ElementProto.closest) { + ret = ElementProto.closest.call(el, s); + } + else { + do { + if (elementMatches.call(el, s)) { + return el; + } + el = el.parentElement || el.parentNode; + } while (el !== null && el.nodeType === 1); + } + return ret; + } + /** + * @private + * @interface bindingsUtils + */ + var bindingsUtils = { + /** + * Update size of background (rect) in some annotations: Measure, Simple + * Rect. + * + * @private + * @function Highcharts.NavigationBindingsUtilsObject.updateRectSize + * + * @param {Highcharts.PointerEventObject} event + * Normalized browser event + * + * @param {Highcharts.Annotation} annotation + * Annotation to be updated + */ + updateRectSize: function (event, annotation) { + var chart = annotation.chart, options = annotation.options.typeOptions, coords = chart.pointer.getCoordinates(event), width = coords.xAxis[0].value - options.point.x, height = options.point.y - coords.yAxis[0].value; + annotation.update({ + typeOptions: { + background: { + width: chart.inverted ? height : width, + height: chart.inverted ? width : height + } + } + }); + }, + /** + * Get field type according to value + * + * @private + * @function Highcharts.NavigationBindingsUtilsObject.getFieldType + * + * @param {'boolean'|'number'|'string'} value + * Atomic type (one of: string, number, boolean) + * + * @return {'checkbox'|'number'|'text'} + * Field type (one of: text, number, checkbox) + */ + getFieldType: function (value) { + return { + 'string': 'text', + 'number': 'number', + 'boolean': 'checkbox' + }[typeof value]; + } + }; + /** + * @private + */ + var NavigationBindings = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function NavigationBindings(chart, options) { + this.boundClassNames = void 0; + this.selectedButton = void 0; + this.chart = chart; + this.options = options; + this.eventsToUnbind = []; + this.container = doc.getElementsByClassName(this.options.bindingsClassName || ''); + } + // Private properties added by bindings: + // Active (selected) annotation that is editted through popup/forms + // activeAnnotation: Annotation + // Holder for current step, used on mouse move to update bound object + // mouseMoveEvent: function () {} + // Next event in `step` array to be called on chart's click + // nextEvent: function () {} + // Index in the `step` array of the current event + // stepIndex: 0 + // Flag to determine if current binding has steps + // steps: true|false + // Bindings holder for all events + // selectedButton: {} + // Holder for user options, returned from `start` event, and passed on to + // `step`'s' and `end`. + // currentUserDetails: {} + /* * + * + * Functions + * + * */ + /** + * Initi all events conencted to NavigationBindings. + * + * @private + * @function Highcharts.NavigationBindings#initEvents + */ + NavigationBindings.prototype.initEvents = function () { + var navigation = this, chart = navigation.chart, bindingsContainer = navigation.container, options = navigation.options; + // Shorthand object for getting events for buttons: + navigation.boundClassNames = {}; + objectEach((options.bindings || {}), function (value) { + navigation.boundClassNames[value.className] = value; + }); + // Handle multiple containers with the same class names: + [].forEach.call(bindingsContainer, function (subContainer) { + navigation.eventsToUnbind.push(addEvent(subContainer, 'click', function (event) { + var bindings = navigation.getButtonEvents(subContainer, event); + if (bindings) { + navigation.bindingsButtonClick(bindings.button, bindings.events, event); + } + })); + }); + objectEach(options.events || {}, function (callback, eventName) { + if (isFunction(callback)) { + navigation.eventsToUnbind.push(addEvent(navigation, eventName, callback)); + } + }); + navigation.eventsToUnbind.push(addEvent(chart.container, 'click', function (e) { + if (!chart.cancelClick && + chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop)) { + navigation.bindingsChartClick(this, e); + } + })); + navigation.eventsToUnbind.push(addEvent(chart.container, 'mousemove', function (e) { + navigation.bindingsContainerMouseMove(this, e); + })); + }; + /** + * Common chart.update() delegation, shared between bindings and exporting. + * + * @private + * @function Highcharts.NavigationBindings#initUpdate + */ + NavigationBindings.prototype.initUpdate = function () { + var navigation = this; + chartNavigationMixin.addUpdate(function (options) { + navigation.update(options); + }, this.chart); + }; + /** + * Hook for click on a button, method selcts/unselects buttons, + * then calls `bindings.init` callback. + * + * @private + * @function Highcharts.NavigationBindings#bindingsButtonClick + * + * @param {Highcharts.HTMLDOMElement} [button] + * Clicked button + * + * @param {object} events + * Events passed down from bindings (`init`, `start`, `step`, `end`) + * + * @param {Highcharts.PointerEventObject} clickEvent + * Browser's click event + */ + NavigationBindings.prototype.bindingsButtonClick = function (button, events, clickEvent) { + var navigation = this, chart = navigation.chart; + if (navigation.selectedButtonElement) { + fireEvent(navigation, 'deselectButton', { button: navigation.selectedButtonElement }); + if (navigation.nextEvent) { + // Remove in-progress annotations adders: + if (navigation.currentUserDetails && + navigation.currentUserDetails.coll === 'annotations') { + chart.removeAnnotation(navigation.currentUserDetails); + } + navigation.mouseMoveEvent = navigation.nextEvent = false; + } + } + navigation.selectedButton = events; + navigation.selectedButtonElement = button; + fireEvent(navigation, 'selectButton', { button: button }); + // Call "init" event, for example to open modal window + if (events.init) { + events.init.call(navigation, button, clickEvent); + } + if (events.start || events.steps) { + chart.renderer.boxWrapper.addClass(PREFIX + 'draw-mode'); + } + }; + /** + * Hook for click on a chart, first click on a chart calls `start` event, + * then on all subsequent clicks iterate over `steps` array. + * When finished, calls `end` event. + * + * @private + * @function Highcharts.NavigationBindings#bindingsChartClick + * + * @param {Highcharts.Chart} chart + * Chart that click was performed on. + * + * @param {Highcharts.PointerEventObject} clickEvent + * Browser's click event. + */ + NavigationBindings.prototype.bindingsChartClick = function (chart, clickEvent) { + var navigation = this, chart = navigation.chart, selectedButton = navigation.selectedButton, svgContainer = chart.renderer.boxWrapper; + // Click outside popups, should close them and deselect the annotation + if (navigation.activeAnnotation && + !clickEvent.activeAnnotation && + // Element could be removed in the child action, e.g. button + clickEvent.target.parentNode && + // TO DO: Polyfill for IE11? + !closestPolyfill(clickEvent.target, '.' + PREFIX + 'popup')) { + fireEvent(navigation, 'closePopup'); + navigation.deselectAnnotation(); + } + if (!selectedButton || !selectedButton.start) { + return; + } + if (!navigation.nextEvent) { + // Call init method: + navigation.currentUserDetails = selectedButton.start.call(navigation, clickEvent); + // If steps exists (e.g. Annotations), bind them: + if (selectedButton.steps) { + navigation.stepIndex = 0; + navigation.steps = true; + navigation.mouseMoveEvent = navigation.nextEvent = + selectedButton.steps[navigation.stepIndex]; + } + else { + fireEvent(navigation, 'deselectButton', { button: navigation.selectedButtonElement }); + svgContainer.removeClass(PREFIX + 'draw-mode'); + navigation.steps = false; + navigation.selectedButton = null; + // First click is also the last one: + if (selectedButton.end) { + selectedButton.end.call(navigation, clickEvent, navigation.currentUserDetails); + } + } + } + else { + navigation.nextEvent(clickEvent, navigation.currentUserDetails); + if (navigation.steps) { + navigation.stepIndex++; + if (selectedButton.steps[navigation.stepIndex]) { + // If we have more steps, bind them one by one: + navigation.mouseMoveEvent = navigation.nextEvent = + selectedButton.steps[navigation.stepIndex]; + } + else { + fireEvent(navigation, 'deselectButton', { button: navigation.selectedButtonElement }); + svgContainer.removeClass(PREFIX + 'draw-mode'); + // That was the last step, call end(): + if (selectedButton.end) { + selectedButton.end.call(navigation, clickEvent, navigation.currentUserDetails); + } + navigation.nextEvent = false; + navigation.mouseMoveEvent = false; + navigation.selectedButton = null; + } + } + } + }; + /** + * Hook for mouse move on a chart's container. It calls current step. + * + * @private + * @function Highcharts.NavigationBindings#bindingsContainerMouseMove + * + * @param {Highcharts.HTMLDOMElement} container + * Chart's container. + * + * @param {global.Event} moveEvent + * Browser's move event. + */ + NavigationBindings.prototype.bindingsContainerMouseMove = function (_container, moveEvent) { + if (this.mouseMoveEvent) { + this.mouseMoveEvent(moveEvent, this.currentUserDetails); + } + }; + /** + * Translate fields (e.g. `params.period` or `marker.styles.color`) to + * Highcharts options object (e.g. `{ params: { period } }`). + * + * @private + * @function Highcharts.NavigationBindings#fieldsToOptions + * + * @param {Highcharts.Dictionary} fields + * Fields from popup form. + * + * @param {T} config + * Default config to be modified. + * + * @return {T} + * Modified config + */ + NavigationBindings.prototype.fieldsToOptions = function (fields, config) { + objectEach(fields, function (value, field) { + var parsedValue = parseFloat(value), path = field.split('.'), parent = config, pathLength = path.length - 1; + // If it's a number (not "format" options), parse it: + if (isNumber(parsedValue) && + !value.match(/px/g) && + !field.match(/format/g)) { + value = parsedValue; + } + // Remove empty strings or values like 0 + if (value !== '' && value !== 'undefined') { + path.forEach(function (name, index) { + var nextName = pick(path[index + 1], ''); + if (pathLength === index) { + // Last index, put value: + parent[name] = value; + } + else if (!parent[name]) { + // Create middle property: + parent[name] = nextName.match(/\d/g) ? [] : {}; + parent = parent[name]; + } + else { + // Jump into next property + parent = parent[name]; + } + }); + } + }); + return config; + }; + /** + * Shorthand method to deselect an annotation. + * + * @function Highcharts.NavigationBindings#deselectAnnotation + */ + NavigationBindings.prototype.deselectAnnotation = function () { + if (this.activeAnnotation) { + this.activeAnnotation.setControlPointsVisibility(false); + this.activeAnnotation = false; + } + }; + /** + * Generates API config for popup in the same format as options for + * Annotation object. + * + * @function Highcharts.NavigationBindings#annotationToFields + * + * @param {Highcharts.Annotation} annotation + * Annotations object + * + * @return {Highcharts.Dictionary} + * Annotation options to be displayed in popup box + */ + NavigationBindings.prototype.annotationToFields = function (annotation) { + var options = annotation.options, editables = NavigationBindings.annotationsEditable, nestedEditables = editables.nestedOptions, getFieldType = this.utils.getFieldType, type = pick(options.type, options.shapes && options.shapes[0] && + options.shapes[0].type, options.labels && options.labels[0] && + options.labels[0].itemType, 'label'), nonEditables = NavigationBindings.annotationsNonEditable[options.langKey] || [], visualOptions = { + langKey: options.langKey, + type: type + }; + /** + * Nested options traversing. Method goes down to the options and copies + * allowed options (with values) to new object, which is last parameter: + * "parent". + * + * @private + * + * @param {*} option + * Atomic type or object/array + * + * @param {string} key + * Option name, for example "visible" or "x", "y" + * + * @param {object} parentEditables + * Editables from NavigationBindings.annotationsEditable + * + * @param {object} parent + * Where new options will be assigned + */ + function traverse(option, key, parentEditables, parent) { + var nextParent; + if (parentEditables && + nonEditables.indexOf(key) === -1 && + ((parentEditables.indexOf && + parentEditables.indexOf(key)) >= 0 || + parentEditables[key] || // nested array + parentEditables === true // simple array + )) { + // Roots: + if (isArray(option)) { + parent[key] = []; + option.forEach(function (arrayOption, i) { + if (!isObject(arrayOption)) { + // Simple arrays, e.g. [String, Number, Boolean] + traverse(arrayOption, 0, nestedEditables[key], parent[key]); + } + else { + // Advanced arrays, e.g. [Object, Object] + parent[key][i] = {}; + objectEach(arrayOption, function (nestedOption, nestedKey) { + traverse(nestedOption, nestedKey, nestedEditables[key], parent[key][i]); + }); + } + }); + } + else if (isObject(option)) { + nextParent = {}; + if (isArray(parent)) { + parent.push(nextParent); + nextParent[key] = {}; + nextParent = nextParent[key]; + } + else { + parent[key] = nextParent; + } + objectEach(option, function (nestedOption, nestedKey) { + traverse(nestedOption, nestedKey, key === 0 ? parentEditables : nestedEditables[key], nextParent); + }); + } + else { + // Leaf: + if (key === 'format') { + parent[key] = [ + format(option, annotation.labels[0].points[0]).toString(), + 'text' + ]; + } + else if (isArray(parent)) { + parent.push([option, getFieldType(option)]); + } + else { + parent[key] = [option, getFieldType(option)]; + } + } + } + } + objectEach(options, function (option, key) { + if (key === 'typeOptions') { + visualOptions[key] = {}; + objectEach(options[key], function (typeOption, typeKey) { + traverse(typeOption, typeKey, nestedEditables, visualOptions[key], true); + }); + } + else { + traverse(option, key, editables[type], visualOptions); + } + }); + return visualOptions; + }; + /** + * Get all class names for all parents in the element. Iterates until finds + * main container. + * + * @function Highcharts.NavigationBindings#getClickedClassNames + * + * @param {Highcharts.HTMLDOMElement} + * Container that event is bound to. + * + * @param {global.Event} event + * Browser's event. + * + * @return {Array>} + * Array of class names with corresponding elements + */ + NavigationBindings.prototype.getClickedClassNames = function (container, event) { + var element = event.target, classNames = [], elemClassName; + while (element) { + elemClassName = attr(element, 'class'); + if (elemClassName) { + classNames = classNames.concat(elemClassName + .split(' ') + .map(function (name) { + return [ + name, + element + ]; + })); + } + element = element.parentNode; + if (element === container) { + return classNames; + } + } + return classNames; + }; + /** + * Get events bound to a button. It's a custom event delegation to find all + * events connected to the element. + * + * @private + * @function Highcharts.NavigationBindings#getButtonEvents + * + * @param {Highcharts.HTMLDOMElement} container + * Container that event is bound to. + * + * @param {global.Event} event + * Browser's event. + * + * @return {object} + * Object with events (init, start, steps, and end) + */ + NavigationBindings.prototype.getButtonEvents = function (container, event) { + var navigation = this, classNames = this.getClickedClassNames(container, event), bindings; + classNames.forEach(function (className) { + if (navigation.boundClassNames[className[0]] && !bindings) { + bindings = { + events: navigation.boundClassNames[className[0]], + button: className[1] + }; + } + }); + return bindings; + }; + /** + * Bindings are just events, so the whole update process is simply + * removing old events and adding new ones. + * + * @private + * @function Highcharts.NavigationBindings#update + */ + NavigationBindings.prototype.update = function (options) { + this.options = merge(true, this.options, options); + this.removeEvents(); + this.initEvents(); + }; + /** + * Remove all events created in the navigation. + * + * @private + * @function Highcharts.NavigationBindings#removeEvents + */ + NavigationBindings.prototype.removeEvents = function () { + this.eventsToUnbind.forEach(function (unbinder) { + unbinder(); + }); + }; + NavigationBindings.prototype.destroy = function () { + this.removeEvents(); + }; + /* * + * + * Static Properties + * + * */ + // Define which options from annotations should show up in edit box: + NavigationBindings.annotationsEditable = { + // `typeOptions` are always available + // Nested and shared options: + nestedOptions: { + labelOptions: ['style', 'format', 'backgroundColor'], + labels: ['style'], + label: ['style'], + style: ['fontSize', 'color'], + background: ['fill', 'strokeWidth', 'stroke'], + innerBackground: ['fill', 'strokeWidth', 'stroke'], + outerBackground: ['fill', 'strokeWidth', 'stroke'], + shapeOptions: ['fill', 'strokeWidth', 'stroke'], + shapes: ['fill', 'strokeWidth', 'stroke'], + line: ['strokeWidth', 'stroke'], + backgroundColors: [true], + connector: ['fill', 'strokeWidth', 'stroke'], + crosshairX: ['strokeWidth', 'stroke'], + crosshairY: ['strokeWidth', 'stroke'] + }, + // Simple shapes: + circle: ['shapes'], + verticalLine: [], + label: ['labelOptions'], + // Measure + measure: ['background', 'crosshairY', 'crosshairX'], + // Others: + fibonacci: [], + tunnel: ['background', 'line', 'height'], + pitchfork: ['innerBackground', 'outerBackground'], + rect: ['shapes'], + // Crooked lines, elliots, arrows etc: + crookedLine: [], + basicAnnotation: [] + }; + // Define non editable fields per annotation, for example Rectangle inherits + // options from Measure, but crosshairs are not available + NavigationBindings.annotationsNonEditable = { + rectangle: ['crosshairX', 'crosshairY', 'label'] + }; + return NavigationBindings; + }()); + /** + * General utils for bindings + * + * @private + * @name Highcharts.NavigationBindings.utils + * @type {bindingsUtils} + */ + NavigationBindings.prototype.utils = bindingsUtils; + H.Chart.prototype.initNavigationBindings = function () { + var chart = this, options = chart.options; + if (options && options.navigation && options.navigation.bindings) { + chart.navigationBindings = new NavigationBindings(chart, options.navigation); + chart.navigationBindings.initEvents(); + chart.navigationBindings.initUpdate(); + } + }; + addEvent(H.Chart, 'load', function () { + this.initNavigationBindings(); + }); + addEvent(H.Chart, 'destroy', function () { + if (this.navigationBindings) { + this.navigationBindings.destroy(); + } + }); + addEvent(NavigationBindings, 'deselectButton', function () { + this.selectedButtonElement = null; + }); + addEvent(H.Annotation, 'remove', function () { + if (this.chart.navigationBindings) { + this.chart.navigationBindings.deselectAnnotation(); + } + }); + /** + * Show edit-annotation form: + * @private + */ + function selectableAnnotation(annotationType) { + var originalClick = annotationType.prototype.defaultOptions.events && + annotationType.prototype.defaultOptions.events.click; + /** + * @private + */ + function selectAndshowPopup(event) { + var annotation = this, navigation = annotation.chart.navigationBindings, prevAnnotation = navigation.activeAnnotation; + if (originalClick) { + originalClick.click.call(annotation, event); + } + if (prevAnnotation !== annotation) { + // Select current: + navigation.deselectAnnotation(); + navigation.activeAnnotation = annotation; + annotation.setControlPointsVisibility(true); + fireEvent(navigation, 'showPopup', { + annotation: annotation, + formType: 'annotation-toolbar', + options: navigation.annotationToFields(annotation), + onSubmit: function (data) { + var config = {}, typeOptions; + if (data.actionType === 'remove') { + navigation.activeAnnotation = false; + navigation.chart.removeAnnotation(annotation); + } + else { + navigation.fieldsToOptions(data.fields, config); + navigation.deselectAnnotation(); + typeOptions = config.typeOptions; + if (annotation.options.type === 'measure') { + // Manually disable crooshars according to + // stroke width of the shape: + typeOptions.crosshairY.enabled = + typeOptions.crosshairY.strokeWidth !== 0; + typeOptions.crosshairX.enabled = + typeOptions.crosshairX.strokeWidth !== 0; + } + annotation.update(config); + } + } + }); + } + else { + // Deselect current: + navigation.deselectAnnotation(); + fireEvent(navigation, 'closePopup'); + } + // Let bubble event to chart.click: + event.activeAnnotation = true; + } + merge(true, annotationType.prototype.defaultOptions.events, { + click: selectAndshowPopup + }); + } + if (H.Annotation) { + // Basic shapes: + selectableAnnotation(H.Annotation); + // Advanced annotations: + objectEach(H.Annotation.types, function (annotationType) { + selectableAnnotation(annotationType); + }); + } + H.setOptions({ + /** + * @optionparent lang + */ + lang: { + /** + * Configure the Popup strings in the chart. Requires the + * `annotations.js` or `annotations-advanced.src.js` module to be + * loaded. + * + * @since 7.0.0 + * @product highcharts highstock + */ + navigation: { + /** + * Translations for all field names used in popup. + * + * @product highcharts highstock + */ + popup: { + simpleShapes: 'Simple shapes', + lines: 'Lines', + circle: 'Circle', + rectangle: 'Rectangle', + label: 'Label', + shapeOptions: 'Shape options', + typeOptions: 'Details', + fill: 'Fill', + format: 'Text', + strokeWidth: 'Line width', + stroke: 'Line color', + title: 'Title', + name: 'Name', + labelOptions: 'Label options', + labels: 'Labels', + backgroundColor: 'Background color', + backgroundColors: 'Background colors', + borderColor: 'Border color', + borderRadius: 'Border radius', + borderWidth: 'Border width', + style: 'Style', + padding: 'Padding', + fontSize: 'Font size', + color: 'Color', + height: 'Height', + shapes: 'Shape options' + } + } + }, + /** + * @optionparent navigation + * @product highcharts highstock + */ + navigation: { + /** + * A CSS class name where all bindings will be attached to. Multiple + * charts on the same page should have separate class names to prevent + * duplicating events. + * + * Default value of versions < 7.0.4 `highcharts-bindings-wrapper` + * + * @since 7.0.0 + * @type {string} + */ + bindingsClassName: 'highcharts-bindings-container', + /** + * Bindings definitions for custom HTML buttons. Each binding implements + * simple event-driven interface: + * + * - `className`: classname used to bind event to + * + * - `init`: initial event, fired on button click + * + * - `start`: fired on first click on a chart + * + * - `steps`: array of sequential events fired one after another on each + * of users clicks + * + * - `end`: last event to be called after last step event + * + * @type {Highcharts.Dictionary|*} + * @sample stock/stocktools/stocktools-thresholds + * Custom bindings in Highstock + * @since 7.0.0 + * @product highcharts highstock + */ + bindings: { + /** + * A circle annotation bindings. Includes `start` and one event in + * `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @default {"className": "highcharts-circle-annotation", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + circleAnnotation: { + /** @ignore-option */ + className: 'highcharts-circle-annotation', + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation; + return this.chart.addAnnotation(merge({ + langKey: 'circle', + type: 'basicAnnotation', + shapes: [{ + type: 'circle', + point: { + xAxis: 0, + yAxis: 0, + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, + r: 5 + }] + }, navigation + .annotationsOptions, navigation + .bindings + .circleAnnotation + .annotationsOptions)); + }, + /** @ignore-option */ + steps: [ + function (e, annotation) { + var point = annotation.options.shapes[0].point, x = this.chart.xAxis[0].toPixels(point.x), y = this.chart.yAxis[0].toPixels(point.y), inverted = this.chart.inverted, distance = Math.max(Math.sqrt(Math.pow(inverted ? y - e.chartX : x - e.chartX, 2) + + Math.pow(inverted ? x - e.chartY : y - e.chartY, 2)), 5); + annotation.update({ + shapes: [{ + r: distance + }] + }); + } + ] + }, + /** + * A rectangle annotation bindings. Includes `start` and one event + * in `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @default {"className": "highcharts-rectangle-annotation", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + rectangleAnnotation: { + /** @ignore-option */ + className: 'highcharts-rectangle-annotation', + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, x = coords.xAxis[0].value, y = coords.yAxis[0].value; + return this.chart.addAnnotation(merge({ + langKey: 'rectangle', + type: 'basicAnnotation', + shapes: [{ + type: 'path', + points: [{ + xAxis: 0, + yAxis: 0, + x: x, + y: y + }, { + xAxis: 0, + yAxis: 0, + x: x, + y: y + }, { + xAxis: 0, + yAxis: 0, + x: x, + y: y + }, { + xAxis: 0, + yAxis: 0, + x: x, + y: y + }] + }] + }, navigation + .annotationsOptions, navigation + .bindings + .rectangleAnnotation + .annotationsOptions)); + }, + /** @ignore-option */ + steps: [ + function (e, annotation) { + var points = annotation.options.shapes[0].points, coords = this.chart.pointer.getCoordinates(e), x = coords.xAxis[0].value, y = coords.yAxis[0].value; + // Top right point + points[1].x = x; + // Bottom right point (cursor position) + points[2].x = x; + points[2].y = y; + // Bottom left + points[3].y = y; + annotation.update({ + shapes: [{ + points: points + }] + }); + } + ] + }, + /** + * A label annotation bindings. Includes `start` event only. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @default {"className": "highcharts-label-annotation", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + labelAnnotation: { + /** @ignore-option */ + className: 'highcharts-label-annotation', + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation; + return this.chart.addAnnotation(merge({ + langKey: 'label', + type: 'basicAnnotation', + labelOptions: { + format: '{y:.2f}' + }, + labels: [{ + point: { + xAxis: 0, + yAxis: 0, + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, + overflow: 'none', + crop: true + }] + }, navigation + .annotationsOptions, navigation + .bindings + .labelAnnotation + .annotationsOptions)); + } + } + }, + /** + * Path where Highcharts will look for icons. Change this to use icons + * from a different server. + * + * @type {string} + * @default https://code.highcharts.com/8.1.0/gfx/stock-icons/ + * @since 7.1.3 + * @apioption navigation.iconsURL + */ + /** + * A `showPopup` event. Fired when selecting for example an annotation. + * + * @type {Function} + * @apioption navigation.events.showPopup + */ + /** + * A `closePopup` event. Fired when Popup should be hidden, for example + * when clicking on an annotation again. + * + * @type {Function} + * @apioption navigation.events.closePopup + */ + /** + * Event fired on a button click. + * + * @type {Function} + * @sample highcharts/annotations/gui/ + * Change icon in a dropddown on event + * @sample highcharts/annotations/gui-buttons/ + * Change button class on event + * @apioption navigation.events.selectButton + */ + /** + * Event fired when button state should change, for example after + * adding an annotation. + * + * @type {Function} + * @sample highcharts/annotations/gui/ + * Change icon in a dropddown on event + * @sample highcharts/annotations/gui-buttons/ + * Change button class on event + * @apioption navigation.events.deselectButton + */ + /** + * Events to communicate between Stock Tools and custom GUI. + * + * @since 7.0.0 + * @product highcharts highstock + * @optionparent navigation.events + */ + events: {}, + /** + * Additional options to be merged into all annotations. + * + * @sample stock/stocktools/navigation-annotation-options + * Set red color of all line annotations + * + * @type {Highcharts.AnnotationsOptions} + * @extends annotations + * @exclude crookedLine, elliottWave, fibonacci, infinityLine, + * measure, pitchfork, tunnel, verticalLine, basicAnnotation + * @apioption navigation.annotationsOptions + */ + annotationsOptions: {} + } + }); + + return NavigationBindings; + }); + _registerModule(_modules, 'annotations/popup.js', [_modules['parts/Globals.js'], _modules['annotations/navigationBindings.js'], _modules['parts/Utilities.js']], function (H, NavigationBindings, U) { + /* * + * + * Popup generator for Stock tools + * + * (c) 2009-2017 Sebastian Bochan + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, createElement = U.createElement, defined = U.defined, isArray = U.isArray, isObject = U.isObject, isString = U.isString, objectEach = U.objectEach, pick = U.pick, wrap = U.wrap; + var indexFilter = /\d/g, PREFIX = 'highcharts-', DIV = 'div', INPUT = 'input', LABEL = 'label', BUTTON = 'button', SELECT = 'select', OPTION = 'option', SPAN = 'span', UL = 'ul', LI = 'li', H3 = 'h3'; + /* eslint-disable no-invalid-this, valid-jsdoc */ + // onContainerMouseDown blocks internal popup events, due to e.preventDefault. + // Related issue #4606 + wrap(H.Pointer.prototype, 'onContainerMouseDown', function (proceed, e) { + var popupClass = e.target && e.target.className; + // elements is not in popup + if (!(isString(popupClass) && + popupClass.indexOf(PREFIX + 'popup-field') >= 0)) { + proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + } + }); + H.Popup = function (parentDiv, iconsURL) { + this.init(parentDiv, iconsURL); + }; + H.Popup.prototype = { + /** + * Initialize the popup. Create base div and add close button. + * @private + * @param {Highcharts.HTMLDOMElement} parentDiv + * Container where popup should be placed + * @param {string} iconsURL + * Icon URL + */ + init: function (parentDiv, iconsURL) { + // create popup div + this.container = createElement(DIV, { + className: PREFIX + 'popup' + }, null, parentDiv); + this.lang = this.getLangpack(); + this.iconsURL = iconsURL; + // add close button + this.addCloseBtn(); + }, + /** + * Create HTML element and attach click event (close popup). + * @private + */ + addCloseBtn: function () { + var _self = this, closeBtn; + // create close popup btn + closeBtn = createElement(DIV, { + className: PREFIX + 'popup-close' + }, null, this.container); + closeBtn.style['background-image'] = 'url(' + + this.iconsURL + 'close.svg)'; + ['click', 'touchstart'].forEach(function (eventName) { + addEvent(closeBtn, eventName, function () { + _self.closePopup(); + }); + }); + }, + /** + * Create two columns (divs) in HTML. + * @private + * @param {Highcharts.HTMLDOMElement} container + * Container of columns + * @return {Highcharts.Dictionary} + * Reference to two HTML columns (lhsCol, rhsCol) + */ + addColsContainer: function (container) { + var rhsCol, lhsCol; + // left column + lhsCol = createElement(DIV, { + className: PREFIX + 'popup-lhs-col' + }, null, container); + // right column + rhsCol = createElement(DIV, { + className: PREFIX + 'popup-rhs-col' + }, null, container); + // wrapper content + createElement(DIV, { + className: PREFIX + 'popup-rhs-col-wrapper' + }, null, rhsCol); + return { + lhsCol: lhsCol, + rhsCol: rhsCol + }; + }, + /** + * Create input with label. + * @private + * @param {string} option + * Chain of fields i.e params.styles.fontSize + * @param {string} type + * Indicator type + * @param {Highhcharts.HTMLDOMElement} + * Container where elements should be added + * @param {string} value + * Default value of input i.e period value is 14, extracted from + * defaultOptions (ADD mode) or series options (EDIT mode) + */ + addInput: function (option, type, parentDiv, value) { + var optionParamList = option.split('.'), optionName = optionParamList[optionParamList.length - 1], lang = this.lang, inputName = PREFIX + type + '-' + optionName; + if (!inputName.match(indexFilter)) { + // add label + createElement(LABEL, { + innerHTML: lang[optionName] || optionName, + htmlFor: inputName + }, null, parentDiv); + } + // add input + createElement(INPUT, { + name: inputName, + value: value[0], + type: value[1], + className: PREFIX + 'popup-field' + }, null, parentDiv).setAttribute(PREFIX + 'data-name', option); + }, + /** + * Create button. + * @private + * @param {Highcharts.HTMLDOMElement} parentDiv + * Container where elements should be added + * @param {string} label + * Text placed as button label + * @param {string} type + * add | edit | remove + * @param {Function} callback + * On click callback + * @param {Highcharts.HTMLDOMElement} fieldsDiv + * Container where inputs are generated + * @return {Highcharts.HTMLDOMElement} + * HTML button + */ + addButton: function (parentDiv, label, type, callback, fieldsDiv) { + var _self = this, closePopup = this.closePopup, getFields = this.getFields, button; + button = createElement(BUTTON, { + innerHTML: label + }, null, parentDiv); + ['click', 'touchstart'].forEach(function (eventName) { + addEvent(button, eventName, function () { + closePopup.call(_self); + return callback(getFields(fieldsDiv, type)); + }); + }); + return button; + }, + /** + * Get values from all inputs and create JSON. + * @private + * @param {Highcharts.HTMLDOMElement} - container where inputs are created + * @param {string} - add | edit | remove + * @return {Highcharts.PopupFieldsObject} - fields + */ + getFields: function (parentDiv, type) { + var inputList = parentDiv.querySelectorAll('input'), optionSeries = '#' + PREFIX + 'select-series > option:checked', optionVolume = '#' + PREFIX + 'select-volume > option:checked', linkedTo = parentDiv.querySelectorAll(optionSeries)[0], volumeTo = parentDiv.querySelectorAll(optionVolume)[0], seriesId, param, fieldsOutput; + fieldsOutput = { + actionType: type, + linkedTo: linkedTo && linkedTo.getAttribute('value'), + fields: {} + }; + [].forEach.call(inputList, function (input) { + param = input.getAttribute(PREFIX + 'data-name'); + seriesId = input.getAttribute(PREFIX + 'data-series-id'); + // params + if (seriesId) { + fieldsOutput.seriesId = input.value; + } + else if (param) { + fieldsOutput.fields[param] = input.value; + } + else { + // type like sma / ema + fieldsOutput.type = input.value; + } + }); + if (volumeTo) { + fieldsOutput.fields['params.volumeSeriesID'] = volumeTo.getAttribute('value'); + } + return fieldsOutput; + }, + /** + * Reset content of the current popup and show. + * @private + */ + showPopup: function () { + var popupDiv = this.container, toolbarClass = PREFIX + 'annotation-toolbar', popupCloseBtn = popupDiv + .querySelectorAll('.' + PREFIX + 'popup-close')[0]; + // reset content + popupDiv.innerHTML = ''; + // reset toolbar styles if exists + if (popupDiv.className.indexOf(toolbarClass) >= 0) { + popupDiv.classList.remove(toolbarClass); + // reset toolbar inline styles + popupDiv.removeAttribute('style'); + } + // add close button + popupDiv.appendChild(popupCloseBtn); + popupDiv.style.display = 'block'; + }, + /** + * Hide popup. + * @private + */ + closePopup: function () { + this.popup.container.style.display = 'none'; + }, + /** + * Create content and show popup. + * @private + * @param {string} - type of popup i.e indicators + * @param {Highcharts.Chart} - chart + * @param {Highcharts.AnnotationsOptions} - options + * @param {Function} - on click callback + */ + showForm: function (type, chart, options, callback) { + this.popup = chart.navigationBindings.popup; + // show blank popup + this.showPopup(); + // indicator form + if (type === 'indicators') { + this.indicators.addForm.call(this, chart, options, callback); + } + // annotation small toolbar + if (type === 'annotation-toolbar') { + this.annotations.addToolbar.call(this, chart, options, callback); + } + // annotation edit form + if (type === 'annotation-edit') { + this.annotations.addForm.call(this, chart, options, callback); + } + // flags form - add / edit + if (type === 'flag') { + this.annotations.addForm.call(this, chart, options, callback, true); + } + }, + /** + * Return lang definitions for popup. + * @private + * @return {Highcharts.Dictionary} - elements translations. + */ + getLangpack: function () { + return H.getOptions().lang.navigation.popup; + }, + annotations: { + /** + * Create annotation simple form. It contains two buttons + * (edit / remove) and text label. + * @private + * @param {Highcharts.Chart} - chart + * @param {Highcharts.AnnotationsOptions} - options + * @param {Function} - on click callback + */ + addToolbar: function (chart, options, callback) { + var _self = this, lang = this.lang, popupDiv = this.popup.container, showForm = this.showForm, toolbarClass = PREFIX + 'annotation-toolbar', button; + // set small size + if (popupDiv.className.indexOf(toolbarClass) === -1) { + popupDiv.className += ' ' + toolbarClass; + } + // set position + popupDiv.style.top = chart.plotTop + 10 + 'px'; + // create label + createElement(SPAN, { + innerHTML: pick( + // Advanced annotations: + lang[options.langKey] || options.langKey, + // Basic shapes: + options.shapes && options.shapes[0].type) + }, null, popupDiv); + // add buttons + button = this.addButton(popupDiv, lang.removeButton || 'remove', 'remove', callback, popupDiv); + button.className += ' ' + PREFIX + 'annotation-remove-button'; + button.style['background-image'] = 'url(' + + this.iconsURL + 'destroy.svg)'; + button = this.addButton(popupDiv, lang.editButton || 'edit', 'edit', function () { + showForm.call(_self, 'annotation-edit', chart, options, callback); + }, popupDiv); + button.className += ' ' + PREFIX + 'annotation-edit-button'; + button.style['background-image'] = 'url(' + + this.iconsURL + 'edit.svg)'; + }, + /** + * Create annotation simple form. + * It contains fields with param names. + * @private + * @param {Highcharts.Chart} chart + * Chart + * @param {Object} options + * Options + * @param {Function} callback + * On click callback + * @param {boolean} [isInit] + * If it is a form declared for init annotation + */ + addForm: function (chart, options, callback, isInit) { + var popupDiv = this.popup.container, lang = this.lang, bottomRow, lhsCol; + // create title of annotations + lhsCol = createElement('h2', { + innerHTML: lang[options.langKey] || options.langKey, + className: PREFIX + 'popup-main-title' + }, null, popupDiv); + // left column + lhsCol = createElement(DIV, { + className: PREFIX + 'popup-lhs-col ' + PREFIX + 'popup-lhs-full' + }, null, popupDiv); + bottomRow = createElement(DIV, { + className: PREFIX + 'popup-bottom-row' + }, null, popupDiv); + this.annotations.addFormFields.call(this, lhsCol, chart, '', options, [], true); + this.addButton(bottomRow, isInit ? + (lang.addButton || 'add') : + (lang.saveButton || 'save'), isInit ? 'add' : 'save', callback, popupDiv); + }, + /** + * Create annotation's form fields. + * @private + * @param {Highcharts.HTMLDOMElement} parentDiv + * Div where inputs are placed + * @param {Highcharts.Chart} chart + * Chart + * @param {string} parentNode + * Name of parent to create chain of names + * @param {Highcharts.AnnotationsOptions} options + * Options + * @param {Array} storage + * Array where all items are stored + * @param {boolean} [isRoot] + * Recursive flag for root + */ + addFormFields: function (parentDiv, chart, parentNode, options, storage, isRoot) { + var _self = this, addFormFields = this.annotations.addFormFields, addInput = this.addInput, lang = this.lang, parentFullName, titleName; + objectEach(options, function (value, option) { + // create name like params.styles.fontSize + parentFullName = parentNode !== '' ? + parentNode + '.' + option : option; + if (isObject(value)) { + if ( + // value is object of options + !isArray(value) || + // array of objects with params. i.e labels in Fibonacci + (isArray(value) && isObject(value[0]))) { + titleName = lang[option] || option; + if (!titleName.match(indexFilter)) { + storage.push([ + true, + titleName, + parentDiv + ]); + } + addFormFields.call(_self, parentDiv, chart, parentFullName, value, storage, false); + } + else { + storage.push([ + _self, + parentFullName, + 'annotation', + parentDiv, + value + ]); + } + } + }); + if (isRoot) { + storage = storage.sort(function (a) { + return a[1].match(/format/g) ? -1 : 1; + }); + storage.forEach(function (genInput) { + if (genInput[0] === true) { + createElement(SPAN, { + className: PREFIX + 'annotation-title', + innerHTML: genInput[1] + }, null, genInput[2]); + } + else { + addInput.apply(genInput[0], genInput.splice(1)); + } + }); + } + } + }, + indicators: { + /** + * Create indicator's form. It contains two tabs (ADD and EDIT) with + * content. + * @private + */ + addForm: function (chart, _options, callback) { + var tabsContainers, indicators = this.indicators, lang = this.lang, buttonParentDiv; + // add tabs + this.tabs.init.call(this, chart); + // get all tabs content divs + tabsContainers = this.popup.container + .querySelectorAll('.' + PREFIX + 'tab-item-content'); + // ADD tab + this.addColsContainer(tabsContainers[0]); + indicators.addIndicatorList.call(this, chart, tabsContainers[0], 'add'); + buttonParentDiv = tabsContainers[0] + .querySelectorAll('.' + PREFIX + 'popup-rhs-col')[0]; + this.addButton(buttonParentDiv, lang.addButton || 'add', 'add', callback, buttonParentDiv); + // EDIT tab + this.addColsContainer(tabsContainers[1]); + indicators.addIndicatorList.call(this, chart, tabsContainers[1], 'edit'); + buttonParentDiv = tabsContainers[1] + .querySelectorAll('.' + PREFIX + 'popup-rhs-col')[0]; + this.addButton(buttonParentDiv, lang.saveButton || 'save', 'edit', callback, buttonParentDiv); + this.addButton(buttonParentDiv, lang.removeButton || 'remove', 'remove', callback, buttonParentDiv); + }, + /** + * Create HTML list of all indicators (ADD mode) or added indicators + * (EDIT mode). + * @private + */ + addIndicatorList: function (chart, parentDiv, listType) { + var _self = this, lhsCol = parentDiv.querySelectorAll('.' + PREFIX + 'popup-lhs-col')[0], rhsCol = parentDiv.querySelectorAll('.' + PREFIX + 'popup-rhs-col')[0], isEdit = listType === 'edit', series = (isEdit ? + chart.series : // EDIT mode + chart.options.plotOptions // ADD mode + ), addFormFields = this.indicators.addFormFields, rhsColWrapper, indicatorList, item; + // create wrapper for list + indicatorList = createElement(UL, { + className: PREFIX + 'indicator-list' + }, null, lhsCol); + rhsColWrapper = rhsCol + .querySelectorAll('.' + PREFIX + 'popup-rhs-col-wrapper')[0]; + objectEach(series, function (serie, value) { + var seriesOptions = serie.options; + if (serie.params || + seriesOptions && seriesOptions.params) { + var indicatorNameType = _self.indicators.getNameType(serie, value), indicatorType = indicatorNameType.type; + item = createElement(LI, { + className: PREFIX + 'indicator-list', + innerHTML: indicatorNameType.name + }, null, indicatorList); + ['click', 'touchstart'].forEach(function (eventName) { + addEvent(item, eventName, function () { + addFormFields.call(_self, chart, isEdit ? serie : series[indicatorType], indicatorNameType.type, rhsColWrapper); + // add hidden input with series.id + if (isEdit && serie.options) { + createElement(INPUT, { + type: 'hidden', + name: PREFIX + 'id-' + indicatorType, + value: serie.options.id + }, null, rhsColWrapper) + .setAttribute(PREFIX + 'data-series-id', serie.options.id); + } + }); + }); + } + }); + // select first item from the list + if (indicatorList.childNodes.length > 0) { + indicatorList.childNodes[0].click(); + } + }, + /** + * Extract full name and type of requested indicator. + * @private + * @param {Highcharts.Series} series + * Series which name is needed. (EDIT mode - defaultOptions.series, ADD + * mode - indicator series). + * @param {string} - indicator type like: sma, ema, etc. + * @return {Object} - series name and type like: sma, ema, etc. + */ + getNameType: function (series, type) { + var options = series.options, seriesTypes = H.seriesTypes, + // add mode + seriesName = seriesTypes[type] && + seriesTypes[type].prototype.nameBase || type.toUpperCase(), seriesType = type; + // edit + if (options && options.type) { + seriesType = series.options.type; + seriesName = series.name; + } + return { + name: seriesName, + type: seriesType + }; + }, + /** + * List all series with unique ID. Its mandatory for indicators to set + * correct linking. + * @private + * @param {string} type + * Indicator type like: sma, ema, etc. + * @param {string} optionName + * Type of select i.e series or volume. + * @param {Highcharts.Chart} chart + * Chart + * @param {Highcharts.HTMLDOMElement} parentDiv + * Element where created HTML list is added + * @param {string} selectedOption + * optional param for default value in dropdown + */ + listAllSeries: function (type, optionName, chart, parentDiv, selectedOption) { + var selectName = PREFIX + optionName + '-type-' + type, lang = this.lang, selectBox, seriesOptions; + createElement(LABEL, { + innerHTML: lang[optionName] || optionName, + htmlFor: selectName + }, null, parentDiv); + // select type + selectBox = createElement(SELECT, { + name: selectName, + className: PREFIX + 'popup-field' + }, null, parentDiv); + selectBox.setAttribute('id', PREFIX + 'select-' + optionName); + // list all series which have id - mandatory for creating indicator + chart.series.forEach(function (serie) { + seriesOptions = serie.options; + if (!seriesOptions.params && + seriesOptions.id && + seriesOptions.id !== PREFIX + 'navigator-series') { + createElement(OPTION, { + innerHTML: seriesOptions.name || seriesOptions.id, + value: seriesOptions.id + }, null, selectBox); + } + }); + if (defined(selectedOption)) { + selectBox.value = selectedOption; + } + }, + /** + * Create typical inputs for chosen indicator. Fields are extracted from + * defaultOptions (ADD mode) or current indicator (ADD mode). Two extra + * fields are added: + * - hidden input - contains indicator type (required for callback) + * - select - list of series which can be linked with indicator + * @private + * @param {Highcharts.Chart} chart + * Chart + * @param {Highcharts.Series} series + * Indicator + * @param {string} seriesType + * Indicator type like: sma, ema, etc. + * @param {Highcharts.HTMLDOMElement} rhsColWrapper + * Element where created HTML list is added + */ + addFormFields: function (chart, series, seriesType, rhsColWrapper) { + var fields = series.params || series.options.params, getNameType = this.indicators.getNameType; + // reset current content + rhsColWrapper.innerHTML = ''; + // create title (indicator name in the right column) + createElement(H3, { + className: PREFIX + 'indicator-title', + innerHTML: getNameType(series, seriesType).name + }, null, rhsColWrapper); + // input type + createElement(INPUT, { + type: 'hidden', + name: PREFIX + 'type-' + seriesType, + value: seriesType + }, null, rhsColWrapper); + // list all series with id + this.indicators.listAllSeries.call(this, seriesType, 'series', chart, rhsColWrapper, series.linkedParent && fields.volumeSeriesID); + if (fields.volumeSeriesID) { + this.indicators.listAllSeries.call(this, seriesType, 'volume', chart, rhsColWrapper, series.linkedParent && series.linkedParent.options.id); + } + // add param fields + this.indicators.addParamInputs.call(this, chart, 'params', fields, seriesType, rhsColWrapper); + }, + /** + * Recurent function which lists all fields, from params object and + * create them as inputs. Each input has unique `data-name` attribute, + * which keeps chain of fields i.e params.styles.fontSize. + * @private + * @param {Highcharts.Chart} chart + * Chart + * @param {string} parentNode + * Name of parent to create chain of names + * @param {Highcharts.PopupFieldsDictionary} fields + * Params which are based for input create + * @param {string} type + * Indicator type like: sma, ema, etc. + * @param {Highcharts.HTMLDOMElement} parentDiv + * Element where created HTML list is added + */ + addParamInputs: function (chart, parentNode, fields, type, parentDiv) { + var _self = this, addParamInputs = this.indicators.addParamInputs, addInput = this.addInput, parentFullName; + objectEach(fields, function (value, fieldName) { + // create name like params.styles.fontSize + parentFullName = parentNode + '.' + fieldName; + if (isObject(value)) { + addParamInputs.call(_self, chart, parentFullName, value, type, parentDiv); + } + else if ( + // skip volume field which is created by addFormFields + parentFullName !== 'params.volumeSeriesID') { + addInput.call(_self, parentFullName, type, parentDiv, [value, 'text'] // all inputs are text type + ); + } + }); + }, + /** + * Get amount of indicators added to chart. + * @private + * @return {number} - Amount of indicators + */ + getAmount: function () { + var series = this.series, counter = 0; + objectEach(series, function (serie) { + var seriesOptions = serie.options; + if (serie.params || + seriesOptions && seriesOptions.params) { + counter++; + } + }); + return counter; + } + }, + tabs: { + /** + * Init tabs. Create tab menu items, tabs containers + * @private + * @param {Highcharts.Chart} chart + * Reference to current chart + */ + init: function (chart) { + var tabs = this.tabs, indicatorsCount = this.indicators.getAmount.call(chart), firstTab; // run by default + // create menu items + firstTab = tabs.addMenuItem.call(this, 'add'); + tabs.addMenuItem.call(this, 'edit', indicatorsCount); + // create tabs containers + tabs.addContentItem.call(this, 'add'); + tabs.addContentItem.call(this, 'edit'); + tabs.switchTabs.call(this, indicatorsCount); + // activate first tab + tabs.selectTab.call(this, firstTab, 0); + }, + /** + * Create tab menu item + * @private + * @param {string} tabName + * `add` or `edit` + * @param {number} [disableTab] + * Disable tab when 0 + * @return {Highcharts.HTMLDOMElement} + * Created HTML tab-menu element + */ + addMenuItem: function (tabName, disableTab) { + var popupDiv = this.popup.container, className = PREFIX + 'tab-item', lang = this.lang, menuItem; + if (disableTab === 0) { + className += ' ' + PREFIX + 'tab-disabled'; + } + // tab 1 + menuItem = createElement(SPAN, { + innerHTML: lang[tabName + 'Button'] || tabName, + className: className + }, null, popupDiv); + menuItem.setAttribute(PREFIX + 'data-tab-type', tabName); + return menuItem; + }, + /** + * Create tab content + * @private + * @return {HTMLDOMElement} - created HTML tab-content element + */ + addContentItem: function () { + var popupDiv = this.popup.container; + return createElement(DIV, { + className: PREFIX + 'tab-item-content' + }, null, popupDiv); + }, + /** + * Add click event to each tab + * @private + * @param {number} disableTab + * Disable tab when 0 + */ + switchTabs: function (disableTab) { + var _self = this, popupDiv = this.popup.container, tabs = popupDiv.querySelectorAll('.' + PREFIX + 'tab-item'), dataParam; + tabs.forEach(function (tab, i) { + dataParam = tab.getAttribute(PREFIX + 'data-tab-type'); + if (dataParam === 'edit' && disableTab === 0) { + return; + } + ['click', 'touchstart'].forEach(function (eventName) { + addEvent(tab, eventName, function () { + // reset class on other elements + _self.tabs.deselectAll.call(_self); + _self.tabs.selectTab.call(_self, this, i); + }); + }); + }); + }, + /** + * Set tab as visible + * @private + * @param {globals.Element} - current tab + * @param {number} - Index of tab in menu + */ + selectTab: function (tab, index) { + var allTabs = this.popup.container + .querySelectorAll('.' + PREFIX + 'tab-item-content'); + tab.className += ' ' + PREFIX + 'tab-item-active'; + allTabs[index].className += ' ' + PREFIX + 'tab-item-show'; + }, + /** + * Set all tabs as invisible. + * @private + */ + deselectAll: function () { + var popupDiv = this.popup.container, tabs = popupDiv + .querySelectorAll('.' + PREFIX + 'tab-item'), tabsContent = popupDiv + .querySelectorAll('.' + PREFIX + 'tab-item-content'), i; + for (i = 0; i < tabs.length; i++) { + tabs[i].classList.remove(PREFIX + 'tab-item-active'); + tabsContent[i].classList.remove(PREFIX + 'tab-item-show'); + } + } + } + }; + addEvent(NavigationBindings, 'showPopup', function (config) { + if (!this.popup) { + // Add popup to main container + this.popup = new H.Popup(this.chart.container, (this.chart.options.navigation.iconsURL || + (this.chart.options.stockTools && + this.chart.options.stockTools.gui.iconsURL) || + 'https://code.highcharts.com/8.1.0/gfx/stock-icons/')); + } + this.popup.showForm(config.formType, this.chart, config.options, config.onSubmit); + }); + addEvent(NavigationBindings, 'closePopup', function () { + if (this.popup) { + this.popup.closePopup(); + } + }); + + }); + _registerModule(_modules, 'masters/modules/annotations.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/arrow-symbols.js b/librerias/gantt/code/modules/arrow-symbols.js new file mode 100644 index 0000000..f39cf4a --- /dev/null +++ b/librerias/gantt/code/modules/arrow-symbols.js @@ -0,0 +1,13 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Arrow Symbols + + (c) 2017-2019 Lars A. V. Cabrera + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/arrow-symbols",["highcharts"],function(f){a(f);a.Highcharts=f;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function f(a,e,b,c){a.hasOwnProperty(e)||(a[e]=c.apply(null,b))}a=a?a._modules:{};f(a,"parts-gantt/ArrowSymbols.js",[a["parts/Globals.js"]],function(a){a.SVGRenderer.prototype.symbols.arrow=function(a,b,c,d){return[["M", +a,b+d/2],["L",a+c,b],["L",a,b+d/2],["L",a+c,b+d]]};a.SVGRenderer.prototype.symbols["arrow-half"]=function(e,b,c,d){return a.SVGRenderer.prototype.symbols.arrow(e,b,c/2,d)};a.SVGRenderer.prototype.symbols["triangle-left"]=function(a,b,c,d){return[["M",a+c,b],["L",a,b+d/2],["L",a+c,b+d],["Z"]]};a.SVGRenderer.prototype.symbols["arrow-filled"]=a.SVGRenderer.prototype.symbols["triangle-left"];a.SVGRenderer.prototype.symbols["triangle-left-half"]=function(e,b,c,d){return a.SVGRenderer.prototype.symbols["triangle-left"](e, +b,c/2,d)};a.SVGRenderer.prototype.symbols["arrow-filled-half"]=a.SVGRenderer.prototype.symbols["triangle-left-half"]});f(a,"masters/modules/arrow-symbols.src.js",[],function(){})}); +//# sourceMappingURL=arrow-symbols.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/arrow-symbols.js.map b/librerias/gantt/code/modules/arrow-symbols.js.map new file mode 100644 index 0000000..49c9427 --- /dev/null +++ b/librerias/gantt/code/modules/arrow-symbols.js.map @@ -0,0 +1 @@ +{"version":3,"file":"arrow-symbols.js.map","lineCount":12,"mappings":"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","sources":["arrow-symbols.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","SVGRenderer","prototype","symbols","arrow","H.SVGRenderer.prototype.symbols.arrow","x","y","w","h"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/arrow-symbols.src.js b/librerias/gantt/code/modules/arrow-symbols.src.js new file mode 100644 index 0000000..93d2f38 --- /dev/null +++ b/librerias/gantt/code/modules/arrow-symbols.src.js @@ -0,0 +1,230 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * Arrow Symbols + * + * (c) 2017-2019 Lars A. V. Cabrera + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/arrow-symbols', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'parts-gantt/ArrowSymbols.js', [_modules['parts/Globals.js']], function (H) { + /* * + * + * (c) 2017 Highsoft AS + * Authors: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Creates an arrow symbol. Like a triangle, except not filled. + * ``` + * o + * o + * o + * o + * o + * o + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols.arrow = function (x, y, w, h) { + return [ + ['M', x, y + h / 2], + ['L', x + w, y], + ['L', x, y + h / 2], + ['L', x + w, y + h] + ]; + }; + /** + * Creates a half-width arrow symbol. Like a triangle, except not filled. + * ``` + * o + * o + * o + * o + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols['arrow-half'] = function (x, y, w, h) { + return H.SVGRenderer.prototype.symbols.arrow(x, y, w / 2, h); + }; + /** + * Creates a left-oriented triangle. + * ``` + * o + * ooooooo + * ooooooooooooo + * ooooooo + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the triangle + * + * @param {number} y + * y position of the triangle + * + * @param {number} w + * width of the triangle + * + * @param {number} h + * height of the triangle + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols['triangle-left'] = function (x, y, w, h) { + return [ + ['M', x + w, y], + ['L', x, y + h / 2], + ['L', x + w, y + h], + ['Z'] + ]; + }; + /** + * Alias function for triangle-left. + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols['arrow-filled'] = + H.SVGRenderer.prototype.symbols['triangle-left']; + /** + * Creates a half-width, left-oriented triangle. + * ``` + * o + * oooo + * ooooooo + * oooo + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the triangle + * + * @param {number} y + * y position of the triangle + * + * @param {number} w + * width of the triangle + * + * @param {number} h + * height of the triangle + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols['triangle-left-half'] = function (x, y, w, h) { + return H.SVGRenderer.prototype.symbols['triangle-left'](x, y, w / 2, h); + }; + /** + * Alias function for triangle-left-half. + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols['arrow-filled-half'] = + H.SVGRenderer.prototype.symbols['triangle-left-half']; + + }); + _registerModule(_modules, 'masters/modules/arrow-symbols.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/boost-canvas.js b/librerias/gantt/code/modules/boost-canvas.js new file mode 100644 index 0000000..424d2e9 --- /dev/null +++ b/librerias/gantt/code/modules/boost-canvas.js @@ -0,0 +1,25 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Boost module + + (c) 2010-2019 Highsoft AS + Author: Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/boost-canvas",["highcharts"],function(m){b(m);b.Highcharts=m;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function m(b,m,q,y){b.hasOwnProperty(m)||(b[m]=y.apply(null,q))}b=b?b._modules:{};m(b,"modules/boost-canvas.src.js",[b["parts/Globals.js"],b["parts/Color.js"],b["parts/Utilities.js"]],function(b,m,q){var y=m.parse, +z=q.addEvent,w=q.extend,ba=q.fireEvent,ca=q.isNumber,da=q.merge,ea=q.pick,r=q.wrap,A=b.win.document,fa=function(){},B=b.Series,k=b.seriesTypes,L;b.initCanvasBoost=function(){b.seriesTypes.heatmap&&r(b.seriesTypes.heatmap.prototype,"drawPoints",function(){var a=this.chart,c=this.getContext(),e=this.chart.inverted,b=this.xAxis,d=this.yAxis;c?(this.points.forEach(function(f){var g=f.plotY;"undefined"===typeof g||isNaN(g)||null===f.y||(g=f.shapeArgs,f=a.styledMode?f.series.colorAttribs(f):f.series.pointAttribs(f), +c.fillStyle=f.fill,e?c.fillRect(d.len-g.y+b.left,b.len-g.x+d.top,-g.height,-g.width):c.fillRect(g.x+b.left,g.y+d.top,g.width,g.height))}),this.canvasToSVG()):this.chart.showLoading("Your browser doesn't support HTML5 canvas,
    please use a modern browser")});w(B.prototype,{getContext:function(){var a=this.chart,c=a.chartWidth,e=a.chartHeight,b=a.seriesGroup||this.group,d=this,m=function(a,d,e,c,b,f,g){a.call(this,e,d,c,b,f,g)};a.isChartSeriesBoosting()&&(d=a,b=a.seriesGroup);var g=d.ctx;d.canvas|| +(d.canvas=A.createElement("canvas"),d.renderTarget=a.renderer.image("",0,0,c,e).addClass("highcharts-boost-canvas").add(b),d.ctx=g=d.canvas.getContext("2d"),a.inverted&&["moveTo","lineTo","rect","arc"].forEach(function(a){r(g,a,m)}),d.boostCopy=function(){d.renderTarget.attr({href:d.canvas.toDataURL("image/png")})},d.boostClear=function(){g.clearRect(0,0,d.canvas.width,d.canvas.height);d===this&&d.renderTarget.attr({href:""})},d.boostClipRect=a.renderer.clipRect(),d.renderTarget.clip(d.boostClipRect)); +d.canvas.width!==c&&(d.canvas.width=c);d.canvas.height!==e&&(d.canvas.height=e);d.renderTarget.attr({x:0,y:0,width:c,height:e,style:"pointer-events: none",href:""});d.boostClipRect.attr(a.getBoostClipRect(d));return g},canvasToSVG:function(){this.chart.isChartSeriesBoosting()?this.boostClear&&this.boostClear():(this.boostCopy||this.chart.boostCopy)&&(this.boostCopy||this.chart.boostCopy)()},cvsLineTo:function(a,c,e){a.lineTo(c,e)},renderCanvas:function(){var a=this,c=a.options,e=a.chart,f=this.xAxis, +d=this.yAxis,k=(e.options.boost||{}).timeRendering||!1,g=0,r=a.processedXData,A=a.processedYData,M=c.data,l=f.getExtremes(),C=l.min,D=l.max;l=d.getExtremes();var B=l.min,ha=l.max,N={},E,ia=!!a.sampling,F=c.marker&&c.marker.radius,O=this.cvsDrawPoint,G=c.lineWidth?this.cvsLineTo:void 0,P=F&&1>=F?this.cvsMarkerSquare:this.cvsMarkerCircle,ja=this.cvsStrokeBatch||1E3,ka=!1!==c.enableMouseTracking,Q;l=c.threshold;var u=d.getThreshold(l),R=ca(l),S=u,la=this.fill,T=a.pointArrayMap&&"low,high"===a.pointArrayMap.join(","), +U=!!c.stacking,V=a.cropStart||0;l=e.options.loading;var ma=a.requireSorting,W,na=c.connectNulls,X=!r,H,I,v,x,J,t=U?a.data:r||M,oa=a.fillOpacity?(new m(a.color)).setOpacity(ea(c.fillOpacity,.75)).get():a.color,Y=function(){la?(n.fillStyle=oa,n.fill()):(n.strokeStyle=a.color,n.lineWidth=c.lineWidth,n.stroke())},Z=function(d,c,b,f){0===g&&(n.beginPath(),G&&(n.lineJoin="round"));e.scroller&&"highcharts-navigator-series"===a.options.className?(c+=e.scroller.top,b&&(b+=e.scroller.top)):c+=e.plotTop;d+= +e.plotLeft;W?n.moveTo(d,c):O?O(n,d,c,b,Q):G?G(n,d,c):P&&P.call(a,n,d,c,F,f);g+=1;g===ja&&(Y(),g=0);Q={clientX:d,plotY:c,yBottom:b}},pa="x"===c.findNearestPointBy,aa=this.xData||this.options.xData||this.processedXData||!1,K=function(a,c,b){J=pa?a:a+","+c;ka&&!N[J]&&(N[J]=!0,e.inverted&&(a=f.len-a,c=d.len-c),qa.push({x:aa?aa[V+b]:!1,clientX:a,plotX:a,plotY:c,i:V+b}))};this.renderTarget&&this.renderTarget.attr({href:""});(this.points||this.graph)&&this.destroyGraphics();a.plotGroup("group","series", +a.visible?"visible":"hidden",c.zIndex,e.seriesGroup);a.markerGroup=a.group;z(a,"destroy",function(){a.markerGroup=null});var qa=this.points=[];var n=this.getContext();a.buildKDTree=fa;this.boostClear&&this.boostClear();this.visible&&(99999=C&&k<=D&&(g=!0);l&&l>=C&&l<=D&&(m=!0);if(T){X&&(h=c.slice(1,3));var r=h[0];h=h[1]}else U&&(p=c.x,h=c.stackY,r=h-c.y);c=null===h;ma||(q=h>=B&&h<=ha);if(!c&&(p>=C&&p<=D&&q||g||m))if(p=Math.round(f.toPixels(p,!0)),ia){if("undefined"===typeof v||p===E){T||(r=h);if("undefined"=== +typeof x||h>I)I=h,x=b;if("undefined"===typeof v||r' + + 'please use a modern browser'); + // Uncomment this to provide low-level (slow) support in oldIE. + // It will cause script errors on charts with more than a few + // thousand points. + // arguments[0].call(this); + } + }); + } + extend(Series.prototype, { + /** + * Create a hidden canvas to draw the graph on. The contents is later + * copied over to an SVG image element. + * + * @private + * @function Highcharts.Series#getContext + */ + getContext: function () { + var chart = this.chart, width = chart.chartWidth, height = chart.chartHeight, targetGroup = chart.seriesGroup || this.group, target = this, ctx, swapXY = function (proceed, x, y, a, b, c, d) { + proceed.call(this, y, x, a, b, c, d); + }; + if (chart.isChartSeriesBoosting()) { + target = chart; + targetGroup = chart.seriesGroup; + } + ctx = target.ctx; + if (!target.canvas) { + target.canvas = doc.createElement('canvas'); + target.renderTarget = chart.renderer + .image('', 0, 0, width, height) + .addClass('highcharts-boost-canvas') + .add(targetGroup); + target.ctx = ctx = target.canvas.getContext('2d'); + if (chart.inverted) { + ['moveTo', 'lineTo', 'rect', 'arc'].forEach(function (fn) { + wrap(ctx, fn, swapXY); + }); + } + target.boostCopy = function () { + target.renderTarget.attr({ + href: target.canvas.toDataURL('image/png') + }); + }; + target.boostClear = function () { + ctx.clearRect(0, 0, target.canvas.width, target.canvas.height); + if (target === this) { + target.renderTarget.attr({ href: '' }); + } + }; + target.boostClipRect = chart.renderer.clipRect(); + target.renderTarget.clip(target.boostClipRect); + } + else if (!(target instanceof H.Chart)) { + // ctx.clearRect(0, 0, width, height); + } + if (target.canvas.width !== width) { + target.canvas.width = width; + } + if (target.canvas.height !== height) { + target.canvas.height = height; + } + target.renderTarget.attr({ + x: 0, + y: 0, + width: width, + height: height, + style: 'pointer-events: none', + href: '' + }); + target.boostClipRect.attr(chart.getBoostClipRect(target)); + return ctx; + }, + /** + * Draw the canvas image inside an SVG image + * + * @private + * @function Highcharts.Series#canvasToSVG + */ + canvasToSVG: function () { + if (!this.chart.isChartSeriesBoosting()) { + if (this.boostCopy || this.chart.boostCopy) { + (this.boostCopy || this.chart.boostCopy)(); + } + } + else { + if (this.boostClear) { + this.boostClear(); + } + } + }, + cvsLineTo: function (ctx, clientX, plotY) { + ctx.lineTo(clientX, plotY); + }, + renderCanvas: function () { + var series = this, options = series.options, chart = series.chart, xAxis = this.xAxis, yAxis = this.yAxis, activeBoostSettings = chart.options.boost || {}, boostSettings = { + timeRendering: activeBoostSettings.timeRendering || false, + timeSeriesProcessing: activeBoostSettings.timeSeriesProcessing || false, + timeSetup: activeBoostSettings.timeSetup || false + }, ctx, c = 0, xData = series.processedXData, yData = series.processedYData, rawData = options.data, xExtremes = xAxis.getExtremes(), xMin = xExtremes.min, xMax = xExtremes.max, yExtremes = yAxis.getExtremes(), yMin = yExtremes.min, yMax = yExtremes.max, pointTaken = {}, lastClientX, sampling = !!series.sampling, points, r = options.marker && options.marker.radius, cvsDrawPoint = this.cvsDrawPoint, cvsLineTo = options.lineWidth ? this.cvsLineTo : void 0, cvsMarker = (r && r <= 1 ? + this.cvsMarkerSquare : + this.cvsMarkerCircle), strokeBatch = this.cvsStrokeBatch || 1000, enableMouseTracking = options.enableMouseTracking !== false, lastPoint, threshold = options.threshold, yBottom = yAxis.getThreshold(threshold), hasThreshold = isNumber(threshold), translatedThreshold = yBottom, doFill = this.fill, isRange = (series.pointArrayMap && + series.pointArrayMap.join(',') === 'low,high'), isStacked = !!options.stacking, cropStart = series.cropStart || 0, loadingOptions = chart.options.loading, requireSorting = series.requireSorting, wasNull, connectNulls = options.connectNulls, useRaw = !xData, minVal, maxVal, minI, maxI, index, sdata = (isStacked ? + series.data : + (xData || rawData)), fillColor = (series.fillOpacity ? + new Color(series.color).setOpacity(pick(options.fillOpacity, 0.75)).get() : + series.color), + // + stroke = function () { + if (doFill) { + ctx.fillStyle = fillColor; + ctx.fill(); + } + else { + ctx.strokeStyle = series.color; + ctx.lineWidth = options.lineWidth; + ctx.stroke(); + } + }, + // + drawPoint = function (clientX, plotY, yBottom, i) { + if (c === 0) { + ctx.beginPath(); + if (cvsLineTo) { + ctx.lineJoin = 'round'; + } + } + if (chart.scroller && + series.options.className === + 'highcharts-navigator-series') { + plotY += chart.scroller.top; + if (yBottom) { + yBottom += chart.scroller.top; + } + } + else { + plotY += chart.plotTop; + } + clientX += chart.plotLeft; + if (wasNull) { + ctx.moveTo(clientX, plotY); + } + else { + if (cvsDrawPoint) { + cvsDrawPoint(ctx, clientX, plotY, yBottom, lastPoint); + } + else if (cvsLineTo) { + cvsLineTo(ctx, clientX, plotY); + } + else if (cvsMarker) { + cvsMarker.call(series, ctx, clientX, plotY, r, i); + } + } + // We need to stroke the line for every 1000 pixels. It will + // crash the browser memory use if we stroke too + // infrequently. + c = c + 1; + if (c === strokeBatch) { + stroke(); + c = 0; + } + // Area charts need to keep track of the last point + lastPoint = { + clientX: clientX, + plotY: plotY, + yBottom: yBottom + }; + }, + // + compareX = options.findNearestPointBy === 'x', + // + xDataFull = (this.xData || + this.options.xData || + this.processedXData || + false), + // + addKDPoint = function (clientX, plotY, i) { + // Shaves off about 60ms compared to repeated concatenation + index = compareX ? clientX : clientX + ',' + plotY; + // The k-d tree requires series points. + // Reduce the amount of points, since the time to build the + // tree increases exponentially. + if (enableMouseTracking && !pointTaken[index]) { + pointTaken[index] = true; + if (chart.inverted) { + clientX = xAxis.len - clientX; + plotY = yAxis.len - plotY; + } + points.push({ + x: xDataFull ? + xDataFull[cropStart + i] : + false, + clientX: clientX, + plotX: clientX, + plotY: plotY, + i: cropStart + i + }); + } + }; + if (this.renderTarget) { + this.renderTarget.attr({ 'href': '' }); + } + // If we are zooming out from SVG mode, destroy the graphics + if (this.points || this.graph) { + this.destroyGraphics(); + } + // The group + series.plotGroup('group', 'series', series.visible ? 'visible' : 'hidden', options.zIndex, chart.seriesGroup); + series.markerGroup = series.group; + addEvent(series, 'destroy', function () { + // Prevent destroy twice + series.markerGroup = null; + }); + points = this.points = []; + ctx = this.getContext(); + series.buildKDTree = noop; // Do not start building while drawing + if (this.boostClear) { + this.boostClear(); + } + // if (this.canvas) { + // ctx.clearRect( + // 0, + // 0, + // this.canvas.width, + // this.canvas.height + // ); + // } + if (!this.visible) { + return; + } + // Display a loading indicator + if (rawData.length > 99999) { + chart.options.loading = merge(loadingOptions, { + labelStyle: { + backgroundColor: color('#ffffff').setOpacity(0.75).get(), + padding: '1em', + borderRadius: '0.5em' + }, + style: { + backgroundColor: 'none', + opacity: 1 + } + }); + U.clearTimeout(destroyLoadingDiv); + chart.showLoading('Drawing...'); + chart.options.loading = loadingOptions; // reset + } + if (boostSettings.timeRendering) { + console.time('canvas rendering'); // eslint-disable-line no-console + } + // Loop over the points + H.eachAsync(sdata, function (d, i) { + var x, y, clientX, plotY, isNull, low, isNextInside = false, isPrevInside = false, nx = false, px = false, chartDestroyed = typeof chart.index === 'undefined', isYInside = true; + if (!chartDestroyed) { + if (useRaw) { + x = d[0]; + y = d[1]; + if (sdata[i + 1]) { + nx = sdata[i + 1][0]; + } + if (sdata[i - 1]) { + px = sdata[i - 1][0]; + } + } + else { + x = d; + y = yData[i]; + if (sdata[i + 1]) { + nx = sdata[i + 1]; + } + if (sdata[i - 1]) { + px = sdata[i - 1]; + } + } + if (nx && nx >= xMin && nx <= xMax) { + isNextInside = true; + } + if (px && px >= xMin && px <= xMax) { + isPrevInside = true; + } + // Resolve low and high for range series + if (isRange) { + if (useRaw) { + y = d.slice(1, 3); + } + low = y[0]; + y = y[1]; + } + else if (isStacked) { + x = d.x; + y = d.stackY; + low = y - d.y; + } + isNull = y === null; + // Optimize for scatter zooming + if (!requireSorting) { + isYInside = y >= yMin && y <= yMax; + } + if (!isNull && + ((x >= xMin && x <= xMax && isYInside) || + (isNextInside || isPrevInside))) { + clientX = Math.round(xAxis.toPixels(x, true)); + if (sampling) { + if (typeof minI === 'undefined' || + clientX === lastClientX) { + if (!isRange) { + low = y; + } + if (typeof maxI === 'undefined' || y > maxVal) { + maxVal = y; + maxI = i; + } + if (typeof minI === 'undefined' || + low < minVal) { + minVal = low; + minI = i; + } + } + // Add points and reset + if (clientX !== lastClientX) { + // maxI also a number: + if (typeof minI !== 'undefined') { + plotY = yAxis.toPixels(maxVal, true); + yBottom = yAxis.toPixels(minVal, true); + drawPoint(clientX, hasThreshold ? + Math.min(plotY, translatedThreshold) : plotY, hasThreshold ? + Math.max(yBottom, translatedThreshold) : yBottom, i); + addKDPoint(clientX, plotY, maxI); + if (yBottom !== plotY) { + addKDPoint(clientX, yBottom, minI); + } + } + minI = maxI = void 0; + lastClientX = clientX; + } + } + else { + plotY = Math.round(yAxis.toPixels(y, true)); + drawPoint(clientX, plotY, yBottom, i); + addKDPoint(clientX, plotY, i); + } + } + wasNull = isNull && !connectNulls; + if (i % CHUNK_SIZE === 0) { + if (series.boostCopy || series.chart.boostCopy) { + (series.boostCopy || series.chart.boostCopy)(); + } + } + } + return !chartDestroyed; + }, function () { + var loadingDiv = chart.loadingDiv, loadingShown = chart.loadingShown; + stroke(); + // if (series.boostCopy || series.chart.boostCopy) { + // (series.boostCopy || series.chart.boostCopy)(); + // } + series.canvasToSVG(); + if (boostSettings.timeRendering) { + console.timeEnd('canvas rendering'); // eslint-disable-line no-console + } + fireEvent(series, 'renderedCanvas'); + // Do not use chart.hideLoading, as it runs JS animation and + // will be blocked by buildKDTree. CSS animation looks good, but + // then it must be deleted in timeout. If we add the module to + // core, change hideLoading so we can skip this block. + if (loadingShown) { + extend(loadingDiv.style, { + transition: 'opacity 250ms', + opacity: 0 + }); + chart.loadingShown = false; + destroyLoadingDiv = setTimeout(function () { + if (loadingDiv.parentNode) { // In exporting it is falsy + loadingDiv.parentNode.removeChild(loadingDiv); + } + chart.loadingDiv = chart.loadingSpan = null; + }, 250); + } + // Go back to prototype, ready to build + delete series.buildKDTree; + series.buildKDTree(); + // Don't do async on export, the exportChart, getSVGForExport and + // getSVG methods are not chained for it. + }, chart.renderer.forExport ? Number.MAX_VALUE : void 0); + } + }); + seriesTypes.scatter.prototype.cvsMarkerCircle = function (ctx, clientX, plotY, r) { + ctx.moveTo(clientX, plotY); + ctx.arc(clientX, plotY, r, 0, 2 * Math.PI, false); + }; + // Rect is twice as fast as arc, should be used for small markers + seriesTypes.scatter.prototype.cvsMarkerSquare = function (ctx, clientX, plotY, r) { + ctx.rect(clientX - r, plotY - r, r * 2, r * 2); + }; + seriesTypes.scatter.prototype.fill = true; + if (seriesTypes.bubble) { + seriesTypes.bubble.prototype.cvsMarkerCircle = function (ctx, clientX, plotY, r, i) { + ctx.moveTo(clientX, plotY); + ctx.arc(clientX, plotY, this.radii && this.radii[i], 0, 2 * Math.PI, false); + }; + seriesTypes.bubble.prototype.cvsStrokeBatch = 1; + } + extend(seriesTypes.area.prototype, { + cvsDrawPoint: function (ctx, clientX, plotY, yBottom, lastPoint) { + if (lastPoint && clientX !== lastPoint.clientX) { + ctx.moveTo(lastPoint.clientX, lastPoint.yBottom); + ctx.lineTo(lastPoint.clientX, lastPoint.plotY); + ctx.lineTo(clientX, plotY); + ctx.lineTo(clientX, yBottom); + } + }, + fill: true, + fillOpacity: true, + sampling: true + }); + extend(seriesTypes.column.prototype, { + cvsDrawPoint: function (ctx, clientX, plotY, yBottom) { + ctx.rect(clientX - 1, plotY, 1, yBottom - plotY); + }, + fill: true, + sampling: true + }); + H.Chart.prototype.callbacks.push(function (chart) { + /** + * @private + */ + function canvasToSVG() { + if (chart.boostCopy) { + chart.boostCopy(); + } + } + /** + * @private + */ + function clear() { + if (chart.renderTarget) { + chart.renderTarget.attr({ href: '' }); + } + if (chart.canvas) { + chart.canvas.getContext('2d').clearRect(0, 0, chart.canvas.width, chart.canvas.height); + } + } + addEvent(chart, 'predraw', clear); + addEvent(chart, 'render', canvasToSVG); + }); + }; + + }); + _registerModule(_modules, 'masters/modules/boost-canvas.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/boost.js b/librerias/gantt/code/modules/boost.js new file mode 100644 index 0000000..181f360 --- /dev/null +++ b/librerias/gantt/code/modules/boost.js @@ -0,0 +1,136 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Boost module + + (c) 2010-2019 Highsoft AS + Author: Torstein Honsi + + License: www.highcharts.com/license + + This is a Highcharts module that draws long data series on a canvas in order + to increase performance of the initial load time and tooltip responsiveness. + + Compatible with WebGL compatible browsers (not IE < 11). + + If this module is taken in as part of the core + - All the loading logic should be merged with core. Update styles in the + core. + - Most of the method wraps should probably be added directly in parent + methods. + + Notes for boost mode + - Area lines are not drawn + - Lines are not drawn on scatter charts + - Zones and negativeColor don't work + - Dash styles are not rendered on lines. + - Columns are always one pixel wide. Don't set the threshold too low. + - Disable animations + - Marker shapes are not supported: markers will always be circles, except + heatmap series, where markers are always rectangles. + + Optimizing tips for users + - Set extremes (min, max) explicitly on the axes in order for Highcharts to + avoid computing extremes. + - Set enableMouseTracking to false on the series to improve total rendering + time. + - The default threshold is set based on one series. If you have multiple, + dense series, the combined number of points drawn gets higher, and you may + want to set the threshold lower in order to use optimizations. + - If drawing large scatter charts, it's beneficial to set the marker radius + to a value less than 1. This is to add additional spacing to make the chart + more readable. + - If the value increments on both the X and Y axis aren't small, consider + setting useGPUTranslations to true on the boost settings object. If you do + this and the increments are small (e.g. datetime axis with small time + increments) it may cause rendering issues due to floating point rounding + errors, so your millage may vary. + + Settings + There are two ways of setting the boost threshold: + - Per series: boost based on number of points in individual series + - Per chart: boost based on the number of series + + To set the series boost threshold, set seriesBoostThreshold on the chart + object. + To set the series-specific threshold, set boostThreshold on the series + object. + + In addition, the following can be set in the boost object: + { + //Wether or not to use alpha blending + useAlpha: boolean - default: true + //Set to true to perform translations on the GPU. + //Much faster, but may cause rendering issues + //when using values far from 0 due to floating point + //rounding issues + useGPUTranslations: boolean - default: false + //Use pre-allocated buffers, much faster, + //but may cause rendering issues with some data sets + usePreallocated: boolean - default: false + } +*/ +(function(c){"object"===typeof module&&module.exports?(c["default"]=c,module.exports=c):"function"===typeof define&&define.amd?define("highcharts/modules/boost",["highcharts"],function(m){c(m);c.Highcharts=m;return c}):c("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(c){function m(c,E,f,C){c.hasOwnProperty(E)||(c[E]=C.apply(null,f))}c=c?c._modules:{};m(c,"modules/boost/boostables.js",[],function(){return"area arearange column columnrange bar line scatter heatmap bubble treemap".split(" ")}); +m(c,"modules/boost/boostable-map.js",[c["modules/boost/boostables.js"]],function(c){var k={};c.forEach(function(c){k[c]=1});return k});m(c,"modules/boost/wgl-shader.js",[c["parts/Utilities.js"]],function(c){var k=c.clamp,f=c.error,C=c.pick;return function(d){function c(){v.length&&f("[highcharts boost] shader error - "+v.join("\n"))}function w(b,a){var g=d.createShader("vertex"===a?d.VERTEX_SHADER:d.FRAGMENT_SHADER);d.shaderSource(g,b);d.compileShader(g);return d.getShaderParameter(g,d.COMPILE_STATUS)? +g:(v.push("when compiling "+a+" shader:\n"+d.getShaderInfoLog(g)),!1)}function r(){function g(a){return d.getUniformLocation(b,a)}var k=w("#version 100\n#define LN10 2.302585092994046\nprecision highp float;\nattribute vec4 aVertexPosition;\nattribute vec4 aColor;\nvarying highp vec2 position;\nvarying highp vec4 vColor;\nuniform mat4 uPMatrix;\nuniform float pSize;\nuniform float translatedThreshold;\nuniform bool hasThreshold;\nuniform bool skipTranslation;\nuniform float xAxisTrans;\nuniform float xAxisMin;\nuniform float xAxisMinPad;\nuniform float xAxisPointRange;\nuniform float xAxisLen;\nuniform bool xAxisPostTranslate;\nuniform float xAxisOrdinalSlope;\nuniform float xAxisOrdinalOffset;\nuniform float xAxisPos;\nuniform bool xAxisCVSCoord;\nuniform bool xAxisIsLog;\nuniform bool xAxisReversed;\nuniform float yAxisTrans;\nuniform float yAxisMin;\nuniform float yAxisMinPad;\nuniform float yAxisPointRange;\nuniform float yAxisLen;\nuniform bool yAxisPostTranslate;\nuniform float yAxisOrdinalSlope;\nuniform float yAxisOrdinalOffset;\nuniform float yAxisPos;\nuniform bool yAxisCVSCoord;\nuniform bool yAxisIsLog;\nuniform bool yAxisReversed;\nuniform bool isBubble;\nuniform bool bubbleSizeByArea;\nuniform float bubbleZMin;\nuniform float bubbleZMax;\nuniform float bubbleZThreshold;\nuniform float bubbleMinSize;\nuniform float bubbleMaxSize;\nuniform bool bubbleSizeAbs;\nuniform bool isInverted;\nfloat bubbleRadius(){\nfloat value = aVertexPosition.w;\nfloat zMax = bubbleZMax;\nfloat zMin = bubbleZMin;\nfloat radius = 0.0;\nfloat pos = 0.0;\nfloat zRange = zMax - zMin;\nif (bubbleSizeAbs){\nvalue = value - bubbleZThreshold;\nzMax = max(zMax - bubbleZThreshold, zMin - bubbleZThreshold);\nzMin = 0.0;\n}\nif (value < zMin){\nradius = bubbleZMin / 2.0 - 1.0;\n} else {\npos = zRange > 0.0 ? (value - zMin) / zRange : 0.5;\nif (bubbleSizeByArea && pos > 0.0){\npos = sqrt(pos);\n}\nradius = ceil(bubbleMinSize + pos * (bubbleMaxSize - bubbleMinSize)) / 2.0;\n}\nreturn radius * 2.0;\n}\nfloat translate(float val,\nfloat pointPlacement,\nfloat localA,\nfloat localMin,\nfloat minPixelPadding,\nfloat pointRange,\nfloat len,\nbool cvsCoord,\nbool isLog,\nbool reversed\n){\nfloat sign = 1.0;\nfloat cvsOffset = 0.0;\nif (cvsCoord) {\nsign *= -1.0;\ncvsOffset = len;\n}\nif (isLog) {\nval = log(val) / LN10;\n}\nif (reversed) {\nsign *= -1.0;\ncvsOffset -= sign * len;\n}\nreturn sign * (val - localMin) * localA + cvsOffset + \n(sign * minPixelPadding);\n}\nfloat xToPixels(float value) {\nif (skipTranslation){\nreturn value;// + xAxisPos;\n}\nreturn translate(value, 0.0, xAxisTrans, xAxisMin, xAxisMinPad, xAxisPointRange, xAxisLen, xAxisCVSCoord, xAxisIsLog, xAxisReversed);// + xAxisPos;\n}\nfloat yToPixels(float value, float checkTreshold) {\nfloat v;\nif (skipTranslation){\nv = value;// + yAxisPos;\n} else {\nv = translate(value, 0.0, yAxisTrans, yAxisMin, yAxisMinPad, yAxisPointRange, yAxisLen, yAxisCVSCoord, yAxisIsLog, yAxisReversed);// + yAxisPos;\nif (v > yAxisLen) {\nv = yAxisLen;\n}\n}\nif (checkTreshold > 0.0 && hasThreshold) {\nv = min(v, translatedThreshold);\n}\nreturn v;\n}\nvoid main(void) {\nif (isBubble){\ngl_PointSize = bubbleRadius();\n} else {\ngl_PointSize = pSize;\n}\nvColor = aColor;\nif (skipTranslation && isInverted) {\ngl_Position = uPMatrix * vec4(aVertexPosition.y + yAxisPos, aVertexPosition.x + xAxisPos, 0.0, 1.0);\n} else if (isInverted) {\ngl_Position = uPMatrix * vec4(yToPixels(aVertexPosition.y, aVertexPosition.z) + yAxisPos, xToPixels(aVertexPosition.x) + xAxisPos, 0.0, 1.0);\n} else {\ngl_Position = uPMatrix * vec4(xToPixels(aVertexPosition.x) + xAxisPos, yToPixels(aVertexPosition.y, aVertexPosition.z) + yAxisPos, 0.0, 1.0);\n}\n}", +"vertex"),e=w("precision highp float;\nuniform vec4 fillColor;\nvarying highp vec2 position;\nvarying highp vec4 vColor;\nuniform sampler2D uSampler;\nuniform bool isCircle;\nuniform bool hasColor;\nvoid main(void) {\nvec4 col = fillColor;\nvec4 tcol;\nif (hasColor) {\ncol = vColor;\n}\nif (isCircle) {\ntcol = texture2D(uSampler, gl_PointCoord.st);\ncol *= tcol;\nif (tcol.r < 0.0) {\ndiscard;\n} else {\ngl_FragColor = col;\n}\n} else {\ngl_FragColor = col;\n}\n}","fragment");if(!k||!e)return b=!1, +c(),!1;b=d.createProgram();d.attachShader(b,k);d.attachShader(b,e);d.linkProgram(b);if(!d.getProgramParameter(b,d.LINK_STATUS))return v.push(d.getProgramInfoLog(b)),c(),b=!1;d.useProgram(b);d.bindAttribLocation(b,0,"aVertexPosition");N=g("uPMatrix");p=g("pSize");n=g("fillColor");l=g("isBubble");D=g("bubbleSizeAbs");G=g("bubbleSizeByArea");M=g("uSampler");a=g("skipTranslation");t=g("isCircle");H=g("isInverted");return!0}function q(a,c){d&&b&&(a=h[a]=h[a]||d.getUniformLocation(b,a),d.uniform1f(a,c))} +var h={},b,N,p,n,l,D,G,a,t,H,v=[],M;return d&&!r()?!1:{psUniform:function(){return p},pUniform:function(){return N},fillColorUniform:function(){return n},setBubbleUniforms:function(a,c,e){var g=a.options,p=Number.MAX_VALUE,H=-Number.MAX_VALUE;d&&b&&"bubble"===a.type&&(p=C(g.zMin,k(c,!1===g.displayNegative?g.zThreshold:-Number.MAX_VALUE,p)),H=C(g.zMax,Math.max(H,e)),d.uniform1i(l,1),d.uniform1i(t,1),d.uniform1i(G,"width"!==a.options.sizeBy),d.uniform1i(D,a.options.sizeByAbsoluteValue),q("bubbleZMin", +p),q("bubbleZMax",H),q("bubbleZThreshold",a.options.zThreshold),q("bubbleMinSize",a.minPxSize),q("bubbleMaxSize",a.maxPxSize))},bind:function(){d&&b&&d.useProgram(b)},program:function(){return b},create:r,setUniform:q,setPMatrix:function(a){d&&b&&d.uniformMatrix4fv(N,!1,a)},setColor:function(a){d&&b&&d.uniform4f(n,a[0]/255,a[1]/255,a[2]/255,a[3])},setPointSize:function(a){d&&b&&d.uniform1f(p,a)},setSkipTranslation:function(g){d&&b&&d.uniform1i(a,!0===g?1:0)},setTexture:function(a){d&&b&&d.uniform1i(M, +a)},setDrawAsCircle:function(a){d&&b&&d.uniform1i(t,a?1:0)},reset:function(){d&&b&&(d.uniform1i(l,0),d.uniform1i(t,0))},setInverted:function(a){d&&b&&d.uniform1i(H,a)},destroy:function(){d&&b&&(d.deleteProgram(b),b=!1)}}}});m(c,"modules/boost/wgl-vbuffer.js",[],function(){return function(c,E,f){function k(){d&&(c.deleteBuffer(d),A=d=!1);q=0;w=f||2;h=[]}var d=!1,A=!1,w=f||2,r=!1,q=0,h;return{destroy:k,bind:function(){if(!d)return!1;c.vertexAttribPointer(A,w,c.FLOAT,!1,0,0)},data:h,build:function(b, +f,p){var n;h=b||[];if(!(h&&0!==h.length||r))return k(),!1;w=p||w;d&&c.deleteBuffer(d);r||(n=new Float32Array(h));d=c.createBuffer();c.bindBuffer(c.ARRAY_BUFFER,d);c.bufferData(c.ARRAY_BUFFER,r||n,c.STATIC_DRAW);A=c.getAttribLocation(E.program(),f);c.enableVertexAttribArray(A);return!0},render:function(b,k,p){var n=r?r.length:h.length;if(!d||!n)return!1;if(!b||b>n||0>b)b=0;if(!k||k>n)k=n;c.drawArrays(c[(p||"points").toUpperCase()],b/w,(k-b)/w);return!0},allocate:function(b){q=-1;r=new Float32Array(4* +b)},push:function(b,c,d,n){r&&(r[++q]=b,r[++q]=c,r[++q]=d,r[++q]=n)}}}});m(c,"modules/boost/wgl-renderer.js",[c["parts/Globals.js"],c["modules/boost/wgl-shader.js"],c["modules/boost/wgl-vbuffer.js"],c["parts/Color.js"],c["parts/Utilities.js"]],function(c,E,f,C,d){var k=C.parse,w=d.isNumber,r=d.isObject,q=d.merge,h=d.objectEach,b=d.pick,N=c.win.document;return function(d){function p(a){if(a.isSeriesBoosting){var b=!!a.options.stacking;var R=a.xData||a.options.xData||a.processedXData;b=(b?a.data:R|| +a.options.data).length;"treemap"===a.type?b*=12:"heatmap"===a.type?b*=6:U[a.type]&&(b*=2);return b}return 0}function l(){e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT)}function D(a,b){function c(a){a&&(b.colorData.push(a[0]),b.colorData.push(a[1]),b.colorData.push(a[2]),b.colorData.push(a[3]))}function e(a,b,e,g,d){c(d);z.usePreallocated?A.push(a,b,e?1:0,g||1):(O.push(a),O.push(b),O.push(e?1:0),O.push(g||1))}function g(){b.segments.length&&(b.segments[b.segments.length-1].to=O.length)}function d(){b.segments.length&& +b.segments[b.segments.length-1].from===O.length||(g(),b.segments.push({from:O.length}))}function p(a,b,g,d,y){c(y);e(a+g,b);c(y);e(a,b);c(y);e(a,b+d);c(y);e(a,b+d);c(y);e(a+g,b+d);c(y);e(a+g,b)}function t(a,c){z.useGPUTranslations||(b.skipTranslation=!0,a.x=m.toPixels(a.x,!0),a.y=q.toPixels(a.y,!0));c?O=[a.x,a.y,0,2].concat(O):e(a.x,a.y,0,2)}var R=a.pointArrayMap&&"low,high"===a.pointArrayMap.join(","),H=a.chart,y=a.options,n=!!y.stacking,w=y.data,l=a.xAxis.getExtremes(),v=l.min;l=l.max;var h=a.yAxis.getExtremes(), +M=h.min;h=h.max;var f=a.xData||y.xData||a.processedXData,G=a.yData||y.yData||a.processedYData,D=a.zData||y.zData||a.processedZData,q=a.yAxis,m=a.xAxis,E=a.chart.plotWidth,N=!f||0===f.length,K=y.connectNulls,u=a.points||!1,J=!1,L=!1,S;f=n?a.data:f||w;var P={x:Number.MAX_VALUE,y:0},Q={x:-Number.MAX_VALUE,y:0},Y=0,la=!1,I=-1,T=!1,W=!1,ba="undefined"===typeof H.index,ha=!1,ia=!1;var x=!1;var va=U[a.type],ja=!1,ra=!0,sa=!0,aa=y.zones||!1,X=!1,ta=y.threshold,ka=!1;if(!(y.boostData&&0b.node.levelDynamic)return 1;if(a.node.levelDynamicb.zMax&&(b.zMax=F[2]);F[2]b.zMax&&(b.zMax=D[I]),D[I]=v&&W<=l&&(ha=!0);T&&T>=v&&T<=l&&(ia=!0);if(R){N&&(B=F.slice(1,3));var ca= +B[0];B=B[1]}else n&&(u=F.x,B=F.stackY,ca=B-F.y);null!==M&&"undefined"!==typeof M&&null!==h&&"undefined"!==typeof h&&(ra=B>=M&&B<=h);u>l&&Q.xv&&(P.x=u,P.y=B);if(null!==B||!K)if(null!==B&&(ra||ha||ia)){if((W>=v||u>=v)&&(T<=l||u<=l)&&(ja=!0),ja||ha||ia){ka&&u-T>ka&&d();aa&&(x=X.rgba,aa.some(function(a,b){b=aa[b-1];if("undefined"!==typeof a.value&&B<=a.value){if(!b||B>=b.value)x=k(a.color).rgba;return!0}return!1}),x[0]/=255,x[1]/=255,x[2]/=255);if(!z.useGPUTranslations&&(b.skipTranslation= +!0,u=m.toPixels(u,!0),B=q.toPixels(B,!0),u>E&&"points"===b.drawMode))continue;if(va){F=ca;if(!1===ca||"undefined"===typeof ca)F=0>B?B:0;R||n||(F=Math.max(null===ta?M:ta,M));z.useGPUTranslations||(F=q.toPixels(F,!0));e(u,F,0,0,x)}b.hasMarkers&&ja&&!1!==J&&(a.closestPointRangePx=Math.min(a.closestPointRangePx,Math.abs(u-J)));!z.useGPUTranslations&&!z.usePreallocated&&J&&1>Math.abs(u-J)&&L&&1>Math.abs(B-L)?z.debug.showSkipSummary&&++Y:(y.step&&!sa&&e(u,L,0,2,x),e(u,B,0,"bubble"===a.type?ua||1:2,x),J= +u,L=B,la=!0,sa=!1)}}else d()}else d()}z.debug.showSkipSummary&&console.log("skipped points:",Y);la||!1===K||"line_strip"!==a.drawMode||(P.x-Number.MAX_VALUE&&t(Q))}g()}}function G(){K=[];Q.data=O=[];Y=[];A&&A.destroy()}function a(a){g&&(g.setUniform("xAxisTrans",a.transA),g.setUniform("xAxisMin",a.min),g.setUniform("xAxisMinPad",a.minPixelPadding),g.setUniform("xAxisPointRange",a.pointRange),g.setUniform("xAxisLen",a.len),g.setUniform("xAxisPos",a.pos),g.setUniform("xAxisCVSCoord", +!a.horiz),g.setUniform("xAxisIsLog",!!a.logarithmic),g.setUniform("xAxisReversed",!!a.reversed))}function t(a){g&&(g.setUniform("yAxisTrans",a.transA),g.setUniform("yAxisMin",a.min),g.setUniform("yAxisMinPad",a.minPixelPadding),g.setUniform("yAxisPointRange",a.pointRange),g.setUniform("yAxisLen",a.len),g.setUniform("yAxisPos",a.pos),g.setUniform("yAxisCVSCoord",!a.horiz),g.setUniform("yAxisIsLog",!!a.logarithmic),g.setUniform("yAxisReversed",!!a.reversed))}function H(a,b){g.setUniform("hasThreshold", +a);g.setUniform("translatedThreshold",b)}function v(p){if(p)m=p.chartWidth||800,J=p.chartHeight||400;else return!1;if(!(e&&m&&J&&g))return!1;z.debug.timeRendering&&console.time("gl rendering");e.canvas.width=m;e.canvas.height=J;g.bind();e.viewport(0,0,m,J);g.setPMatrix([2/m,0,0,0,0,-(2/J),0,0,0,0,-2,0,-1,1,-1,1]);12*((n.marker?n.marker.radius:10)||10));l=L[l&&l.symbol||c.series.symbol]||L.circle;if(!(0===c.segments.length||c.segmentslength&&c.segments[0].from===c.segments[0].to)){l.isReady&&(e.bindTexture(e.TEXTURE_2D,l.handle),g.setTexture(l.handle));p.styledMode?l=c.series.markerGroup&&c.series.markerGroup.getStyle("fill"): +(l=c.series.pointAttribs&&c.series.pointAttribs().fill||c.series.color,n.colorByPoint&&(l=c.series.chart.options.colors[d]));c.series.fillOpacity&&n.fillOpacity&&(l=(new C(l)).setOpacity(b(n.fillOpacity,1)).get());l=k(l).rgba;z.useAlpha||(l[3]=1);"lines"===c.drawMode&&z.useAlpha&&1>l[3]&&(l[3]/=10);"add"===n.boostBlending?(e.blendFunc(e.SRC_ALPHA,e.ONE),e.blendEquation(e.FUNC_ADD)):"mult"===n.boostBlending||"multiply"===n.boostBlending?e.blendFunc(e.DST_COLOR,e.ZERO):"darken"===n.boostBlending?(e.blendFunc(e.ONE, +e.ONE),e.blendEquation(e.FUNC_MIN)):e.blendFuncSeparate(e.SRC_ALPHA,e.ONE_MINUS_SRC_ALPHA,e.ONE,e.ONE_MINUS_SRC_ALPHA);g.reset();0=(a.options.boostThreshold||Number.MAX_VALUE)&&++c)}b.boostForceChartBoost=k&&(f===b.series.length&&0=D&&t<=N);if(null!==t&&h>=r&&h<=A&&f)if(a=k.toPixels(h,!0),ba){if("undefined"===typeof V||a===U){y||(c=t);if("undefined"===typeof Z||t>ea)ea=t,Z=b;if("undefined"===typeof V||c=(c.options.boostThreshold||Number.MAX_VALUE)}var c=this,d=this.options.data;p(this.chart)&&A[this.type]?(b(d)&&"heatmap"!==this.type&&"treemap"!==this.type&& +!this.options.stacking&&this.hasExtremes&&this.hasExtremes(!0)||(a.apply(this,Array.prototype.slice.call(arguments,1)),d=this.processedXData),(this.isSeriesBoosting=b(d))?(d=this.getFirstValidPoint(this.options.data),h(d)||q(d)||r(12,!1,this.chart),this.enterBoost()):this.exitBoost&&this.exitBoost()):a.apply(this,Array.prototype.slice.call(arguments,1))});k(l,"hide",function(){this.canvas&&this.renderTarget&&(this.ogl&&this.ogl.clear(),this.boostClear())});l.prototype.enterBoost=function(){this.alteredByBoost= +[];["allowDG","directTouch","stickyTracking"].forEach(function(a){this.alteredByBoost.push({prop:a,val:this[a],own:Object.hasOwnProperty.call(this,a)})},this);this.directTouch=this.allowDG=!1;this.stickyTracking=!0;this.labelBySeries&&(this.labelBySeries=this.labelBySeries.destroy())};l.prototype.exitBoost=function(){(this.alteredByBoost||[]).forEach(function(a){a.own?this[a.prop]=a.val:delete this[a.prop]},this);this.boostClear&&this.boostClear()};l.prototype.hasExtremes=function(a){var b=this.options, +c=this.xAxis&&this.xAxis.options,d=this.yAxis&&this.yAxis.options,f=this.colorAxis&&this.colorAxis.options;return b.data.length>(b.boostThreshold||Number.MAX_VALUE)&&h(d.min)&&h(d.max)&&(!a||h(c.min)&&h(c.max))&&(!f||h(f.min)&&h(f.max))};l.prototype.destroyGraphics=function(){var a=this,b=this.points,c,d;if(b)for(d=0;d 0.0 ? (value - zMin) / zRange : 0.5;', + 'if (bubbleSizeByArea && pos > 0.0){', + 'pos = sqrt(pos);', + '}', + 'radius = ceil(bubbleMinSize + pos * (bubbleMaxSize - bubbleMinSize)) / 2.0;', + '}', + 'return radius * 2.0;', + '}', + 'float translate(float val,', + 'float pointPlacement,', + 'float localA,', + 'float localMin,', + 'float minPixelPadding,', + 'float pointRange,', + 'float len,', + 'bool cvsCoord,', + 'bool isLog,', + 'bool reversed', + '){', + 'float sign = 1.0;', + 'float cvsOffset = 0.0;', + 'if (cvsCoord) {', + 'sign *= -1.0;', + 'cvsOffset = len;', + '}', + 'if (isLog) {', + 'val = log(val) / LN10;', + '}', + 'if (reversed) {', + 'sign *= -1.0;', + 'cvsOffset -= sign * len;', + '}', + 'return sign * (val - localMin) * localA + cvsOffset + ', + '(sign * minPixelPadding);', + '}', + 'float xToPixels(float value) {', + 'if (skipTranslation){', + 'return value;// + xAxisPos;', + '}', + 'return translate(value, 0.0, xAxisTrans, xAxisMin, xAxisMinPad, xAxisPointRange, xAxisLen, xAxisCVSCoord, xAxisIsLog, xAxisReversed);// + xAxisPos;', + '}', + 'float yToPixels(float value, float checkTreshold) {', + 'float v;', + 'if (skipTranslation){', + 'v = value;// + yAxisPos;', + '} else {', + 'v = translate(value, 0.0, yAxisTrans, yAxisMin, yAxisMinPad, yAxisPointRange, yAxisLen, yAxisCVSCoord, yAxisIsLog, yAxisReversed);// + yAxisPos;', + 'if (v > yAxisLen) {', + 'v = yAxisLen;', + '}', + '}', + 'if (checkTreshold > 0.0 && hasThreshold) {', + 'v = min(v, translatedThreshold);', + '}', + 'return v;', + '}', + 'void main(void) {', + 'if (isBubble){', + 'gl_PointSize = bubbleRadius();', + '} else {', + 'gl_PointSize = pSize;', + '}', + // 'gl_PointSize = 10.0;', + 'vColor = aColor;', + 'if (skipTranslation && isInverted) {', + // If we get translated values from JS, just swap them (x, y) + 'gl_Position = uPMatrix * vec4(aVertexPosition.y + yAxisPos, aVertexPosition.x + xAxisPos, 0.0, 1.0);', + '} else if (isInverted) {', + // But when calculating pixel positions directly, + // swap axes and values (x, y) + 'gl_Position = uPMatrix * vec4(yToPixels(aVertexPosition.y, aVertexPosition.z) + yAxisPos, xToPixels(aVertexPosition.x) + xAxisPos, 0.0, 1.0);', + '} else {', + 'gl_Position = uPMatrix * vec4(xToPixels(aVertexPosition.x) + xAxisPos, yToPixels(aVertexPosition.y, aVertexPosition.z) + yAxisPos, 0.0, 1.0);', + '}', + // 'gl_Position = uPMatrix * vec4(aVertexPosition.x, aVertexPosition.y, 0.0, 1.0);', + '}' + /* eslint-enable max-len, @typescript-eslint/indent */ + ].join('\n'), + // Fragment shader source + fragShade = [ + /* eslint-disable max-len, @typescript-eslint/indent */ + 'precision highp float;', + 'uniform vec4 fillColor;', + 'varying highp vec2 position;', + 'varying highp vec4 vColor;', + 'uniform sampler2D uSampler;', + 'uniform bool isCircle;', + 'uniform bool hasColor;', + // 'vec4 toColor(float value, vec2 point) {', + // 'return vec4(0.0, 0.0, 0.0, 0.0);', + // '}', + 'void main(void) {', + 'vec4 col = fillColor;', + 'vec4 tcol;', + 'if (hasColor) {', + 'col = vColor;', + '}', + 'if (isCircle) {', + 'tcol = texture2D(uSampler, gl_PointCoord.st);', + 'col *= tcol;', + 'if (tcol.r < 0.0) {', + 'discard;', + '} else {', + 'gl_FragColor = col;', + '}', + '} else {', + 'gl_FragColor = col;', + '}', + '}' + /* eslint-enable max-len, @typescript-eslint/indent */ + ].join('\n'), uLocations = {}, + // The shader program + shaderProgram, + // Uniform handle to the perspective matrix + pUniform, + // Uniform for point size + psUniform, + // Uniform for fill color + fillColorUniform, + // Uniform for isBubble + isBubbleUniform, + // Uniform for bubble abs sizing + bubbleSizeAbsUniform, bubbleSizeAreaUniform, + // Skip translation uniform + skipTranslationUniform, + // Set to 1 if circle + isCircleUniform, + // Uniform for invertion + isInverted, + // Error stack + errors = [], + // Texture uniform + uSamplerUniform; + /** + * Handle errors accumulated in errors stack + * @private + */ + function handleErrors() { + if (errors.length) { + error('[highcharts boost] shader error - ' + errors.join('\n')); + } + } + /** + * String to shader program + * @private + * @param {string} str - the program source + * @param {string} type - the program type: either `vertex` or `fragment` + * @returns {bool|shader} + */ + function stringToProgram(str, type) { + var t = type === 'vertex' ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER, shader = gl.createShader(t); + gl.shaderSource(shader, str); + gl.compileShader(shader); + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + errors.push('when compiling ' + + type + + ' shader:\n' + + gl.getShaderInfoLog(shader)); + return false; + } + return shader; + } + /** + * Create the shader. + * Loads the shader program statically defined above + * @private + */ + function createShader() { + var v = stringToProgram(vertShade, 'vertex'), f = stringToProgram(fragShade, 'fragment'); + if (!v || !f) { + shaderProgram = false; + handleErrors(); + return false; + } + /** + * @private + */ + function uloc(n) { + return gl.getUniformLocation(shaderProgram, n); + } + shaderProgram = gl.createProgram(); + gl.attachShader(shaderProgram, v); + gl.attachShader(shaderProgram, f); + gl.linkProgram(shaderProgram); + if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { + errors.push(gl.getProgramInfoLog(shaderProgram)); + handleErrors(); + shaderProgram = false; + return false; + } + gl.useProgram(shaderProgram); + gl.bindAttribLocation(shaderProgram, 0, 'aVertexPosition'); + pUniform = uloc('uPMatrix'); + psUniform = uloc('pSize'); + fillColorUniform = uloc('fillColor'); + isBubbleUniform = uloc('isBubble'); + bubbleSizeAbsUniform = uloc('bubbleSizeAbs'); + bubbleSizeAreaUniform = uloc('bubbleSizeByArea'); + uSamplerUniform = uloc('uSampler'); + skipTranslationUniform = uloc('skipTranslation'); + isCircleUniform = uloc('isCircle'); + isInverted = uloc('isInverted'); + return true; + } + /** + * Destroy the shader + * @private + */ + function destroy() { + if (gl && shaderProgram) { + gl.deleteProgram(shaderProgram); + shaderProgram = false; + } + } + /** + * Bind the shader. + * This makes the shader the active one until another one is bound, + * or until 0 is bound. + * @private + */ + function bind() { + if (gl && shaderProgram) { + gl.useProgram(shaderProgram); + } + } + /** + * Set a uniform value. + * This uses a hash map to cache uniform locations. + * @private + * @param name {string} - the name of the uniform to set + * @param val {float} - the value to set + */ + function setUniform(name, val) { + if (gl && shaderProgram) { + var u = uLocations[name] = (uLocations[name] || + gl.getUniformLocation(shaderProgram, name)); + gl.uniform1f(u, val); + } + } + /** + * Set the active texture + * @private + * @param texture - the texture + */ + function setTexture(texture) { + if (gl && shaderProgram) { + gl.uniform1i(uSamplerUniform, texture); + } + } + /** + * Set if inversion state + * @private + * @flag is the state + */ + function setInverted(flag) { + if (gl && shaderProgram) { + gl.uniform1i(isInverted, flag); + } + } + /** + * Enable/disable circle drawing + * @private + */ + function setDrawAsCircle(flag) { + if (gl && shaderProgram) { + gl.uniform1i(isCircleUniform, flag ? 1 : 0); + } + } + /** + * Flush + * @private + */ + function reset() { + if (gl && shaderProgram) { + gl.uniform1i(isBubbleUniform, 0); + gl.uniform1i(isCircleUniform, 0); + } + } + /** + * Set bubble uniforms + * @private + * @param series {Highcharts.Series} - the series to use + */ + function setBubbleUniforms(series, zCalcMin, zCalcMax) { + var seriesOptions = series.options, zMin = Number.MAX_VALUE, zMax = -Number.MAX_VALUE; + if (gl && shaderProgram && series.type === 'bubble') { + zMin = pick(seriesOptions.zMin, clamp(zCalcMin, seriesOptions.displayNegative === false ? + seriesOptions.zThreshold : -Number.MAX_VALUE, zMin)); + zMax = pick(seriesOptions.zMax, Math.max(zMax, zCalcMax)); + gl.uniform1i(isBubbleUniform, 1); + gl.uniform1i(isCircleUniform, 1); + gl.uniform1i(bubbleSizeAreaUniform, (series.options.sizeBy !== 'width')); + gl.uniform1i(bubbleSizeAbsUniform, series.options + .sizeByAbsoluteValue); + setUniform('bubbleZMin', zMin); + setUniform('bubbleZMax', zMax); + setUniform('bubbleZThreshold', series.options.zThreshold); + setUniform('bubbleMinSize', series.minPxSize); + setUniform('bubbleMaxSize', series.maxPxSize); + } + } + /** + * Set the Color uniform. + * @private + * @param color {Array} - an array with RGBA values + */ + function setColor(color) { + if (gl && shaderProgram) { + gl.uniform4f(fillColorUniform, color[0] / 255.0, color[1] / 255.0, color[2] / 255.0, color[3]); + } + } + /** + * Set skip translation + * @private + */ + function setSkipTranslation(flag) { + if (gl && shaderProgram) { + gl.uniform1i(skipTranslationUniform, flag === true ? 1 : 0); + } + } + /** + * Set the perspective matrix + * @private + * @param m {Matrix4x4} - the matrix + */ + function setPMatrix(m) { + if (gl && shaderProgram) { + gl.uniformMatrix4fv(pUniform, false, m); + } + } + /** + * Set the point size. + * @private + * @param p {float} - point size + */ + function setPointSize(p) { + if (gl && shaderProgram) { + gl.uniform1f(psUniform, p); + } + } + /** + * Get the shader program handle + * @private + * @return {GLInt} - the handle for the program + */ + function getProgram() { + return shaderProgram; + } + if (gl) { + if (!createShader()) { + return false; + } + } + return { + psUniform: function () { + return psUniform; + }, + pUniform: function () { + return pUniform; + }, + fillColorUniform: function () { + return fillColorUniform; + }, + setBubbleUniforms: setBubbleUniforms, + bind: bind, + program: getProgram, + create: createShader, + setUniform: setUniform, + setPMatrix: setPMatrix, + setColor: setColor, + setPointSize: setPointSize, + setSkipTranslation: setSkipTranslation, + setTexture: setTexture, + setDrawAsCircle: setDrawAsCircle, + reset: reset, + setInverted: setInverted, + destroy: destroy + }; + } + + return GLShader; + }); + _registerModule(_modules, 'modules/boost/wgl-vbuffer.js', [], function () { + /* * + * + * Copyright (c) 2019-2020 Highsoft AS + * + * Boost module: stripped-down renderer for higher performance + * + * License: highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /* eslint-disable valid-jsdoc */ + /** + * Vertex Buffer abstraction. + * A vertex buffer is a set of vertices which are passed to the GPU + * in a single call. + * + * @private + * @function GLVertexBuffer + * + * @param {WebGLContext} gl + * the context in which to create the buffer + * + * @param {GLShader} shader + * the shader to use + * + * @return {*} + */ + function GLVertexBuffer(gl, shader, dataComponents + /* , type */ + ) { + var buffer = false, vertAttribute = false, components = dataComponents || 2, preAllocated = false, iterator = 0, + // farray = false, + data; + // type = type || 'float'; + /** + * @private + */ + function destroy() { + if (buffer) { + gl.deleteBuffer(buffer); + buffer = false; + vertAttribute = false; + } + iterator = 0; + components = dataComponents || 2; + data = []; + } + /** + * Build the buffer + * @private + * @param dataIn {Array} - a 0 padded array of indices + * @param attrib {String} - the name of the Attribute to bind the buffer to + * @param dataComponents {Integer} - the number of components per. indice + */ + function build(dataIn, attrib, dataComponents) { + var farray; + data = dataIn || []; + if ((!data || data.length === 0) && !preAllocated) { + // console.error('trying to render empty vbuffer'); + destroy(); + return false; + } + components = dataComponents || components; + if (buffer) { + gl.deleteBuffer(buffer); + } + if (!preAllocated) { + farray = new Float32Array(data); + } + buffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, preAllocated || farray, gl.STATIC_DRAW); + // gl.bindAttribLocation(shader.program(), 0, 'aVertexPosition'); + vertAttribute = gl.getAttribLocation(shader.program(), attrib); + gl.enableVertexAttribArray(vertAttribute); + // Trigger cleanup + farray = false; + return true; + } + /** + * Bind the buffer + * @private + */ + function bind() { + if (!buffer) { + return false; + } + // gl.bindAttribLocation(shader.program(), 0, 'aVertexPosition'); + // gl.enableVertexAttribArray(vertAttribute); + // gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.vertexAttribPointer(vertAttribute, components, gl.FLOAT, false, 0, 0); + // gl.enableVertexAttribArray(vertAttribute); + } + /** + * Render the buffer + * @private + * @param from {Integer} - the start indice + * @param to {Integer} - the end indice + * @param drawMode {String} - the draw mode + */ + function render(from, to, drawMode) { + var length = preAllocated ? preAllocated.length : data.length; + if (!buffer) { + return false; + } + if (!length) { + return false; + } + if (!from || from > length || from < 0) { + from = 0; + } + if (!to || to > length) { + to = length; + } + drawMode = drawMode || 'points'; + gl.drawArrays(gl[drawMode.toUpperCase()], from / components, (to - from) / components); + return true; + } + /** + * @private + */ + function push(x, y, a, b) { + if (preAllocated) { // && iterator <= preAllocated.length - 4) { + preAllocated[++iterator] = x; + preAllocated[++iterator] = y; + preAllocated[++iterator] = a; + preAllocated[++iterator] = b; + } + } + /** + * Note about pre-allocated buffers: + * - This is slower for charts with many series + * @private + */ + function allocate(size) { + size *= 4; + iterator = -1; + preAllocated = new Float32Array(size); + } + // ///////////////////////////////////////////////////////////////////////// + return { + destroy: destroy, + bind: bind, + data: data, + build: build, + render: render, + allocate: allocate, + push: push + }; + } + + return GLVertexBuffer; + }); + _registerModule(_modules, 'modules/boost/wgl-renderer.js', [_modules['parts/Globals.js'], _modules['modules/boost/wgl-shader.js'], _modules['modules/boost/wgl-vbuffer.js'], _modules['parts/Color.js'], _modules['parts/Utilities.js']], function (H, GLShader, GLVertexBuffer, Color, U) { + /* * + * + * Copyright (c) 2019-2020 Highsoft AS + * + * Boost module: stripped-down renderer for higher performance + * + * License: highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var color = Color.parse; + var isNumber = U.isNumber, isObject = U.isObject, merge = U.merge, objectEach = U.objectEach, pick = U.pick; + var win = H.win, doc = win.document; + /* eslint-disable valid-jsdoc */ + /** + * Main renderer. Used to render series. + * + * Notes to self: + * - May be able to build a point map by rendering to a separate canvas and + * encoding values in the color data. + * - Need to figure out a way to transform the data quicker + * + * @private + * @function GLRenderer + * + * @param {Function} postRenderCallback + * + * @return {*} + */ + function GLRenderer(postRenderCallback) { + // // Shader + var shader = false, + // Vertex buffers - keyed on shader attribute name + vbuffer = false, + // Opengl context + gl = false, + // Width of our viewport in pixels + width = 0, + // Height of our viewport in pixels + height = 0, + // The data to render - array of coordinates + data = false, + // The marker data + markerData = false, + // Exports + exports = {}, + // Is it inited? + isInited = false, + // The series stack + series = [], + // Texture handles + textureHandles = {}, + // Things to draw as "rectangles" (i.e lines) + asBar = { + 'column': true, + 'columnrange': true, + 'bar': true, + 'area': true, + 'arearange': true + }, asCircle = { + 'scatter': true, + 'bubble': true + }, + // Render settings + settings = { + pointSize: 1, + lineWidth: 1, + fillColor: '#AA00AA', + useAlpha: true, + usePreallocated: false, + useGPUTranslations: false, + debug: { + timeRendering: false, + timeSeriesProcessing: false, + timeSetup: false, + timeBufferCopy: false, + timeKDTree: false, + showSkipSummary: false + } + }; + // ///////////////////////////////////////////////////////////////////////// + /** + * @private + */ + function setOptions(options) { + merge(true, settings, options); + } + /** + * @private + */ + function seriesPointCount(series) { + var isStacked, xData, s; + if (series.isSeriesBoosting) { + isStacked = !!series.options.stacking; + xData = (series.xData || + series.options.xData || + series.processedXData); + s = (isStacked ? series.data : (xData || series.options.data)) + .length; + if (series.type === 'treemap') { + s *= 12; + } + else if (series.type === 'heatmap') { + s *= 6; + } + else if (asBar[series.type]) { + s *= 2; + } + return s; + } + return 0; + } + /** + * Allocate a float buffer to fit all series + * @private + */ + function allocateBuffer(chart) { + var s = 0; + if (!settings.usePreallocated) { + return; + } + chart.series.forEach(function (series) { + if (series.isSeriesBoosting) { + s += seriesPointCount(series); + } + }); + vbuffer.allocate(s); + } + /** + * @private + */ + function allocateBufferForSingleSeries(series) { + var s = 0; + if (!settings.usePreallocated) { + return; + } + if (series.isSeriesBoosting) { + s = seriesPointCount(series); + } + vbuffer.allocate(s); + } + /** + * Returns an orthographic perspective matrix + * @private + * @param {number} width - the width of the viewport in pixels + * @param {number} height - the height of the viewport in pixels + */ + function orthoMatrix(width, height) { + var near = 0, far = 1; + return [ + 2 / width, 0, 0, 0, + 0, -(2 / height), 0, 0, + 0, 0, -2 / (far - near), 0, + -1, 1, -(far + near) / (far - near), 1 + ]; + } + /** + * Clear the depth and color buffer + * @private + */ + function clear() { + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + } + /** + * Get the WebGL context + * @private + * @returns {WebGLContext} - the context + */ + function getGL() { + return gl; + } + /** + * Push data for a single series + * This calculates additional vertices and transforms the data to be + * aligned correctly in memory + * @private + */ + function pushSeriesData(series, inst) { + var isRange = (series.pointArrayMap && + series.pointArrayMap.join(',') === 'low,high'), chart = series.chart, options = series.options, isStacked = !!options.stacking, rawData = options.data, xExtremes = series.xAxis.getExtremes(), xMin = xExtremes.min, xMax = xExtremes.max, yExtremes = series.yAxis.getExtremes(), yMin = yExtremes.min, yMax = yExtremes.max, xData = series.xData || options.xData || series.processedXData, yData = series.yData || options.yData || series.processedYData, zData = (series.zData || options.zData || + series.processedZData), yAxis = series.yAxis, xAxis = series.xAxis, + // plotHeight = series.chart.plotHeight, + plotWidth = series.chart.plotWidth, useRaw = !xData || xData.length === 0, + // threshold = options.threshold, + // yBottom = chart.yAxis[0].getThreshold(threshold), + // hasThreshold = isNumber(threshold), + // colorByPoint = series.options.colorByPoint, + // This is required for color by point, so make sure this is + // uncommented if enabling that + // colorIndex = 0, + // Required for color axis support + // caxis, + connectNulls = options.connectNulls, + // For some reason eslint/TypeScript don't pick up that this is + // actually used: --- bre1470: it is never read, just set + // maxVal: (number|undefined), // eslint-disable-line no-unused-vars + points = series.points || false, lastX = false, lastY = false, minVal, pcolor, scolor, sdata = isStacked ? series.data : (xData || rawData), closestLeft = { x: Number.MAX_VALUE, y: 0 }, closestRight = { x: -Number.MAX_VALUE, y: 0 }, + // + skipped = 0, hadPoints = false, + // + cullXThreshold = 1, cullYThreshold = 1, + // The following are used in the builder while loop + x, y, d, z, i = -1, px = false, nx = false, low, chartDestroyed = typeof chart.index === 'undefined', nextInside = false, prevInside = false, pcolor = false, drawAsBar = asBar[series.type], isXInside = false, isYInside = true, firstPoint = true, zones = options.zones || false, zoneDefColor = false, threshold = options.threshold, gapSize = false; + if (options.boostData && options.boostData.length > 0) { + return; + } + if (options.gapSize) { + gapSize = options.gapUnit !== 'value' ? + options.gapSize * series.closestPointRange : + options.gapSize; + } + if (zones) { + zones.some(function (zone) { + if (typeof zone.value === 'undefined') { + zoneDefColor = new Color(zone.color); + return true; + } + return false; + }); + if (!zoneDefColor) { + zoneDefColor = ((series.pointAttribs && series.pointAttribs().fill) || + series.color); + zoneDefColor = new Color(zoneDefColor); + } + } + if (chart.inverted) { + // plotHeight = series.chart.plotWidth; + plotWidth = series.chart.plotHeight; + } + series.closestPointRangePx = Number.MAX_VALUE; + /** + * Push color to color buffer - need to do this per vertex. + * @private + */ + function pushColor(color) { + if (color) { + inst.colorData.push(color[0]); + inst.colorData.push(color[1]); + inst.colorData.push(color[2]); + inst.colorData.push(color[3]); + } + } + /** + * Push a vertice to the data buffer. + * @private + */ + function vertice(x, y, checkTreshold, pointSize, color) { + pushColor(color); + if (settings.usePreallocated) { + vbuffer.push(x, y, checkTreshold ? 1 : 0, pointSize || 1); + } + else { + data.push(x); + data.push(y); + data.push(checkTreshold ? 1 : 0); + data.push(pointSize || 1); + } + } + /** + * @private + */ + function closeSegment() { + if (inst.segments.length) { + inst.segments[inst.segments.length - 1].to = data.length; + } + } + /** + * Create a new segment for the current set. + * @private + */ + function beginSegment() { + // Insert a segment on the series. + // A segment is just a start indice. + // When adding a segment, if one exists from before, it should + // set the previous segment's end + if (inst.segments.length && + inst.segments[inst.segments.length - 1].from === data.length) { + return; + } + closeSegment(); + inst.segments.push({ + from: data.length + }); + } + /** + * Push a rectangle to the data buffer. + * @private + */ + function pushRect(x, y, w, h, color) { + pushColor(color); + vertice(x + w, y); + pushColor(color); + vertice(x, y); + pushColor(color); + vertice(x, y + h); + pushColor(color); + vertice(x, y + h); + pushColor(color); + vertice(x + w, y + h); + pushColor(color); + vertice(x + w, y); + } + // Create the first segment + beginSegment(); + // Special case for point shapes + if (points && points.length > 0) { + // If we're doing points, we assume that the points are already + // translated, so we skip the shader translation. + inst.skipTranslation = true; + // Force triangle draw mode + inst.drawMode = 'triangles'; + // We don't have a z component in the shader, so we need to sort. + if (points[0].node && points[0].node.levelDynamic) { + points.sort(function (a, b) { + if (a.node) { + if (a.node.levelDynamic > + b.node.levelDynamic) { + return 1; + } + if (a.node.levelDynamic < + b.node.levelDynamic) { + return -1; + } + } + return 0; + }); + } + points.forEach(function (point) { + var plotY = point.plotY, shapeArgs, swidth, pointAttr; + if (typeof plotY !== 'undefined' && + !isNaN(plotY) && + point.y !== null) { + shapeArgs = point.shapeArgs; + pointAttr = chart.styledMode ? + point.series + .colorAttribs(point) : + pointAttr = point.series.pointAttribs(point); + swidth = pointAttr['stroke-width'] || 0; + // Handle point colors + pcolor = color(pointAttr.fill).rgba; + pcolor[0] /= 255.0; + pcolor[1] /= 255.0; + pcolor[2] /= 255.0; + // So there are two ways of doing this. Either we can + // create a rectangle of two triangles, or we can do a + // point and use point size. Latter is faster, but + // only supports squares. So we're doing triangles. + // We could also use one color per. vertice to get + // better color interpolation. + // If there's stroking, we do an additional rect + if (series.type === 'treemap') { + swidth = swidth || 1; + scolor = color(pointAttr.stroke).rgba; + scolor[0] /= 255.0; + scolor[1] /= 255.0; + scolor[2] /= 255.0; + pushRect(shapeArgs.x, shapeArgs.y, shapeArgs.width, shapeArgs.height, scolor); + swidth /= 2; + } + // } else { + // swidth = 0; + // } + // Fixes issues with inverted heatmaps (see #6981) + // The root cause is that the coordinate system is flipped. + // In other words, instead of [0,0] being top-left, it's + // bottom-right. This causes a vertical and horizontal flip + // in the resulting image, making it rotated 180 degrees. + if (series.type === 'heatmap' && chart.inverted) { + shapeArgs.x = xAxis.len - shapeArgs.x; + shapeArgs.y = yAxis.len - shapeArgs.y; + shapeArgs.width = -shapeArgs.width; + shapeArgs.height = -shapeArgs.height; + } + pushRect(shapeArgs.x + swidth, shapeArgs.y + swidth, shapeArgs.width - (swidth * 2), shapeArgs.height - (swidth * 2), pcolor); + } + }); + closeSegment(); + return; + } + // Extract color axis + // (chart.axes || []).forEach(function (a) { + // if (H.ColorAxis && a instanceof H.ColorAxis) { + // caxis = a; + // } + // }); + while (i < sdata.length - 1) { + d = sdata[++i]; + // px = x = y = z = nx = low = false; + // chartDestroyed = typeof chart.index === 'undefined'; + // nextInside = prevInside = pcolor = isXInside = isYInside = false; + // drawAsBar = asBar[series.type]; + if (chartDestroyed) { + break; + } + // Uncomment this to enable color by point. + // This currently left disabled as the charts look really ugly + // when enabled and there's a lot of points. + // Leaving in for the future (tm). + // if (colorByPoint) { + // colorIndex = ++colorIndex % + // series.chart.options.colors.length; + // pcolor = toRGBAFast(series.chart.options.colors[colorIndex]); + // pcolor[0] /= 255.0; + // pcolor[1] /= 255.0; + // pcolor[2] /= 255.0; + // } + // Handle the point.color option (#5999) + var pointOptions = rawData && rawData[i]; + if (!useRaw && isObject(pointOptions, true)) { + if (pointOptions.color) { + pcolor = color(pointOptions.color).rgba; + pcolor[0] /= 255.0; + pcolor[1] /= 255.0; + pcolor[2] /= 255.0; + } + } + if (useRaw) { + x = d[0]; + y = d[1]; + if (sdata[i + 1]) { + nx = sdata[i + 1][0]; + } + if (sdata[i - 1]) { + px = sdata[i - 1][0]; + } + if (d.length >= 3) { + z = d[2]; + if (d[2] > inst.zMax) { + inst.zMax = d[2]; + } + if (d[2] < inst.zMin) { + inst.zMin = d[2]; + } + } + } + else { + x = d; + y = yData[i]; + if (sdata[i + 1]) { + nx = sdata[i + 1]; + } + if (sdata[i - 1]) { + px = sdata[i - 1]; + } + if (zData && zData.length) { + z = zData[i]; + if (zData[i] > inst.zMax) { + inst.zMax = zData[i]; + } + if (zData[i] < inst.zMin) { + inst.zMin = zData[i]; + } + } + } + if (!connectNulls && (x === null || y === null)) { + beginSegment(); + continue; + } + if (nx && nx >= xMin && nx <= xMax) { + nextInside = true; + } + if (px && px >= xMin && px <= xMax) { + prevInside = true; + } + if (isRange) { + if (useRaw) { + y = d.slice(1, 3); + } + low = y[0]; + y = y[1]; + } + else if (isStacked) { + x = d.x; + y = d.stackY; + low = y - d.y; + } + if (yMin !== null && + typeof yMin !== 'undefined' && + yMax !== null && + typeof yMax !== 'undefined') { + isYInside = y >= yMin && y <= yMax; + } + if (x > xMax && closestRight.x < xMax) { + closestRight.x = x; + closestRight.y = y; + } + if (x < xMin && closestLeft.x > xMin) { + closestLeft.x = x; + closestLeft.y = y; + } + if (y === null && connectNulls) { + continue; + } + // Cull points outside the extremes + if (y === null || (!isYInside && !nextInside && !prevInside)) { + beginSegment(); + continue; + } + // The first point before and first after extremes should be + // rendered (#9962) + if ((nx >= xMin || x >= xMin) && + (px <= xMax || x <= xMax)) { + isXInside = true; + } + if (!isXInside && !nextInside && !prevInside) { + continue; + } + if (gapSize && x - px > gapSize) { + beginSegment(); + } + // Note: Boost requires that zones are sorted! + if (zones) { + pcolor = zoneDefColor.rgba; + zones.some(function (// eslint-disable-line no-loop-func + zone, i) { + var last = zones[i - 1]; + if (typeof zone.value !== 'undefined' && y <= zone.value) { + if (!last || y >= last.value) { + pcolor = color(zone.color).rgba; + } + return true; + } + return false; + }); + pcolor[0] /= 255.0; + pcolor[1] /= 255.0; + pcolor[2] /= 255.0; + } + // Skip translations - temporary floating point fix + if (!settings.useGPUTranslations) { + inst.skipTranslation = true; + x = xAxis.toPixels(x, true); + y = yAxis.toPixels(y, true); + // Make sure we're not drawing outside of the chart area. + // See #6594. Update: this is no longer required as far as I + // can tell. Leaving in for git blame in case there are edge + // cases I've not found. Having this in breaks #10246. + // if (y > plotHeight) { + // y = plotHeight; + // } + if (x > plotWidth) { + // If this is rendered as a point, just skip drawing it + // entirely, as we're not dependandt on lineTo'ing to it. + // See #8197 + if (inst.drawMode === 'points') { + continue; + } + // Having this here will clamp markers and make the angle + // of the last line wrong. See 9166. + // x = plotWidth; + } + } + if (drawAsBar) { + // maxVal = y; + minVal = low; + if (low === false || typeof low === 'undefined') { + if (y < 0) { + minVal = y; + } + else { + minVal = 0; + } + } + if (!isRange && !isStacked) { + minVal = Math.max(threshold === null ? yMin : threshold, // #5268 + yMin); // #8731 + } + if (!settings.useGPUTranslations) { + minVal = yAxis.toPixels(minVal, true); + } + // Need to add an extra point here + vertice(x, minVal, 0, 0, pcolor); + } + // No markers on out of bounds things. + // Out of bound things are shown if and only if the next + // or previous point is inside the rect. + if (inst.hasMarkers && isXInside) { + // x = Highcharts.correctFloat( + // Math.min(Math.max(-1e5, xAxis.translate( + // x, + // 0, + // 0, + // 0, + // 1, + // 0.5, + // false + // )), 1e5) + // ); + if (lastX !== false) { + series.closestPointRangePx = Math.min(series.closestPointRangePx, Math.abs(x - lastX)); + } + } + // If the last _drawn_ point is closer to this point than the + // threshold, skip it. Shaves off 20-100ms in processing. + if (!settings.useGPUTranslations && + !settings.usePreallocated && + (lastX && Math.abs(x - lastX) < cullXThreshold) && + (lastY && Math.abs(y - lastY) < cullYThreshold)) { + if (settings.debug.showSkipSummary) { + ++skipped; + } + continue; + } + // Do step line if enabled. + // Draws an additional point at the old Y at the new X. + // See #6976. + if (options.step && !firstPoint) { + vertice(x, lastY, 0, 2, pcolor); + } + vertice(x, y, 0, series.type === 'bubble' ? (z || 1) : 2, pcolor); + // Uncomment this to support color axis. + // if (caxis) { + // pcolor = color(caxis.toColor(y)).rgba; + // inst.colorData.push(color[0] / 255.0); + // inst.colorData.push(color[1] / 255.0); + // inst.colorData.push(color[2] / 255.0); + // inst.colorData.push(color[3]); + // } + lastX = x; + lastY = y; + hadPoints = true; + firstPoint = false; + } + if (settings.debug.showSkipSummary) { + console.log('skipped points:', skipped); // eslint-disable-line no-console + } + /** + * @private + */ + function pushSupplementPoint(point, atStart) { + if (!settings.useGPUTranslations) { + inst.skipTranslation = true; + point.x = xAxis.toPixels(point.x, true); + point.y = yAxis.toPixels(point.y, true); + } + // We should only do this for lines, and we should ignore markers + // since there's no point here that would have a marker. + if (atStart) { + data = [point.x, point.y, 0, 2].concat(data); + return; + } + vertice(point.x, point.y, 0, 2); + } + if (!hadPoints && + connectNulls !== false && + series.drawMode === 'line_strip') { + if (closestLeft.x < Number.MAX_VALUE) { + // We actually need to push this *before* the complete buffer. + pushSupplementPoint(closestLeft, true); + } + if (closestRight.x > -Number.MAX_VALUE) { + pushSupplementPoint(closestRight); + } + } + closeSegment(); + } + /** + * Push a series to the renderer + * If we render the series immediatly, we don't have to loop later + * @private + * @param s {Highchart.Series} - the series to push + */ + function pushSeries(s) { + if (series.length > 0) { + // series[series.length - 1].to = data.length; + if (series[series.length - 1].hasMarkers) { + series[series.length - 1].markerTo = markerData.length; + } + } + if (settings.debug.timeSeriesProcessing) { + console.time('building ' + s.type + ' series'); // eslint-disable-line no-console + } + series.push({ + segments: [], + // from: data.length, + markerFrom: markerData.length, + // Push RGBA values to this array to use per. point coloring. + // It should be 0-padded, so each component should be pushed in + // succession. + colorData: [], + series: s, + zMin: Number.MAX_VALUE, + zMax: -Number.MAX_VALUE, + hasMarkers: s.options.marker ? + s.options.marker.enabled !== false : + false, + showMarkers: true, + drawMode: { + 'area': 'lines', + 'arearange': 'lines', + 'areaspline': 'line_strip', + 'column': 'lines', + 'columnrange': 'lines', + 'bar': 'lines', + 'line': 'line_strip', + 'scatter': 'points', + 'heatmap': 'triangles', + 'treemap': 'triangles', + 'bubble': 'points' + }[s.type] || 'line_strip' + }); + // Add the series data to our buffer(s) + pushSeriesData(s, series[series.length - 1]); + if (settings.debug.timeSeriesProcessing) { + console.timeEnd('building ' + s.type + ' series'); // eslint-disable-line no-console + } + } + /** + * Flush the renderer. + * This removes pushed series and vertices. + * Should be called after clearing and before rendering + * @private + */ + function flush() { + series = []; + exports.data = data = []; + markerData = []; + if (vbuffer) { + vbuffer.destroy(); + } + } + /** + * Pass x-axis to shader + * @private + * @param axis {Highcharts.Axis} - the x-axis + */ + function setXAxis(axis) { + if (!shader) { + return; + } + shader.setUniform('xAxisTrans', axis.transA); + shader.setUniform('xAxisMin', axis.min); + shader.setUniform('xAxisMinPad', axis.minPixelPadding); + shader.setUniform('xAxisPointRange', axis.pointRange); + shader.setUniform('xAxisLen', axis.len); + shader.setUniform('xAxisPos', axis.pos); + shader.setUniform('xAxisCVSCoord', (!axis.horiz)); + shader.setUniform('xAxisIsLog', (!!axis.logarithmic)); + shader.setUniform('xAxisReversed', (!!axis.reversed)); + } + /** + * Pass y-axis to shader + * @private + * @param axis {Highcharts.Axis} - the y-axis + */ + function setYAxis(axis) { + if (!shader) { + return; + } + shader.setUniform('yAxisTrans', axis.transA); + shader.setUniform('yAxisMin', axis.min); + shader.setUniform('yAxisMinPad', axis.minPixelPadding); + shader.setUniform('yAxisPointRange', axis.pointRange); + shader.setUniform('yAxisLen', axis.len); + shader.setUniform('yAxisPos', axis.pos); + shader.setUniform('yAxisCVSCoord', (!axis.horiz)); + shader.setUniform('yAxisIsLog', (!!axis.logarithmic)); + shader.setUniform('yAxisReversed', (!!axis.reversed)); + } + /** + * Set the translation threshold + * @private + * @param has {boolean} - has threshold flag + * @param translation {Float} - the threshold + */ + function setThreshold(has, translation) { + shader.setUniform('hasThreshold', has); + shader.setUniform('translatedThreshold', translation); + } + /** + * Render the data + * This renders all pushed series. + * @private + */ + function render(chart) { + if (chart) { + if (!chart.chartHeight || !chart.chartWidth) { + // chart.setChartSize(); + } + width = chart.chartWidth || 800; + height = chart.chartHeight || 400; + } + else { + return false; + } + if (!gl || !width || !height || !shader) { + return false; + } + if (settings.debug.timeRendering) { + console.time('gl rendering'); // eslint-disable-line no-console + } + gl.canvas.width = width; + gl.canvas.height = height; + shader.bind(); + gl.viewport(0, 0, width, height); + shader.setPMatrix(orthoMatrix(width, height)); + if (settings.lineWidth > 1 && !H.isMS) { + gl.lineWidth(settings.lineWidth); + } + vbuffer.build(exports.data, 'aVertexPosition', 4); + vbuffer.bind(); + shader.setInverted(chart.inverted); + // Render the series + series.forEach(function (s, si) { + var options = s.series.options, shapeOptions = options.marker, sindex, lineWidth = (typeof options.lineWidth !== 'undefined' ? + options.lineWidth : + 1), threshold = options.threshold, hasThreshold = isNumber(threshold), yBottom = s.series.yAxis.getThreshold(threshold), translatedThreshold = yBottom, cbuffer, showMarkers = pick(options.marker ? options.marker.enabled : null, s.series.xAxis.isRadial ? true : null, s.series.closestPointRangePx > + 2 * ((options.marker ? + options.marker.radius : + 10) || 10)), fillColor, shapeTexture = textureHandles[(shapeOptions && shapeOptions.symbol) || + s.series.symbol] || textureHandles.circle, scolor = []; + if (s.segments.length === 0 || + (s.segmentslength && + s.segments[0].from === s.segments[0].to)) { + return; + } + if (shapeTexture.isReady) { + gl.bindTexture(gl.TEXTURE_2D, shapeTexture.handle); + shader.setTexture(shapeTexture.handle); + } + if (chart.styledMode) { + fillColor = (s.series.markerGroup && + s.series.markerGroup.getStyle('fill')); + } + else { + fillColor = + (s.series.pointAttribs && s.series.pointAttribs().fill) || + s.series.color; + if (options.colorByPoint) { + fillColor = s.series.chart.options.colors[si]; + } + } + if (s.series.fillOpacity && options.fillOpacity) { + fillColor = new Color(fillColor).setOpacity(pick(options.fillOpacity, 1.0)).get(); + } + scolor = color(fillColor).rgba; + if (!settings.useAlpha) { + scolor[3] = 1.0; + } + // This is very much temporary + if (s.drawMode === 'lines' && + settings.useAlpha && + scolor[3] < 1) { + scolor[3] /= 10; + } + // Blending + if (options.boostBlending === 'add') { + gl.blendFunc(gl.SRC_ALPHA, gl.ONE); + gl.blendEquation(gl.FUNC_ADD); + } + else if (options.boostBlending === 'mult' || + options.boostBlending === 'multiply') { + gl.blendFunc(gl.DST_COLOR, gl.ZERO); + } + else if (options.boostBlending === 'darken') { + gl.blendFunc(gl.ONE, gl.ONE); + gl.blendEquation(gl.FUNC_MIN); + } + else { + // gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + // gl.blendEquation(gl.FUNC_ADD); + gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + } + shader.reset(); + // If there are entries in the colorData buffer, build and bind it. + if (s.colorData.length > 0) { + shader.setUniform('hasColor', 1.0); + cbuffer = GLVertexBuffer(gl, shader); // eslint-disable-line new-cap + cbuffer.build(s.colorData, 'aColor', 4); + cbuffer.bind(); + } + // Set series specific uniforms + shader.setColor(scolor); + setXAxis(s.series.xAxis); + setYAxis(s.series.yAxis); + setThreshold(hasThreshold, translatedThreshold); + if (s.drawMode === 'points') { + if (options.marker && isNumber(options.marker.radius)) { + shader.setPointSize(options.marker.radius * 2.0); + } + else { + shader.setPointSize(1); + } + } + // If set to true, the toPixels translations in the shader + // is skipped, i.e it's assumed that the value is a pixel coord. + shader.setSkipTranslation(s.skipTranslation); + if (s.series.type === 'bubble') { + shader.setBubbleUniforms(s.series, s.zMin, s.zMax); + } + shader.setDrawAsCircle(asCircle[s.series.type] || false); + // Do the actual rendering + // If the line width is < 0, skip rendering of the lines. See #7833. + if (lineWidth > 0 || s.drawMode !== 'line_strip') { + for (sindex = 0; sindex < s.segments.length; sindex++) { + // if (s.segments[sindex].from < s.segments[sindex].to) { + vbuffer.render(s.segments[sindex].from, s.segments[sindex].to, s.drawMode); + // } + } + } + if (s.hasMarkers && showMarkers) { + if (options.marker && isNumber(options.marker.radius)) { + shader.setPointSize(options.marker.radius * 2.0); + } + else { + shader.setPointSize(10); + } + shader.setDrawAsCircle(true); + for (sindex = 0; sindex < s.segments.length; sindex++) { + // if (s.segments[sindex].from < s.segments[sindex].to) { + vbuffer.render(s.segments[sindex].from, s.segments[sindex].to, 'POINTS'); + // } + } + } + }); + if (settings.debug.timeRendering) { + console.timeEnd('gl rendering'); // eslint-disable-line no-console + } + if (postRenderCallback) { + postRenderCallback(); + } + flush(); + } + /** + * Render the data when ready + * @private + */ + function renderWhenReady(chart) { + clear(); + if (chart.renderer.forExport) { + return render(chart); + } + if (isInited) { + render(chart); + } + else { + setTimeout(function () { + renderWhenReady(chart); + }, 1); + } + } + /** + * Set the viewport size in pixels + * Creates an orthographic perspective matrix and applies it. + * @private + * @param w {Integer} - the width of the viewport + * @param h {Integer} - the height of the viewport + */ + function setSize(w, h) { + // Skip if there's no change, or if we have no valid shader + if ((width === w && height === h) || !shader) { + return; + } + width = w; + height = h; + shader.bind(); + shader.setPMatrix(orthoMatrix(width, height)); + } + /** + * Init OpenGL + * @private + * @param canvas {HTMLCanvas} - the canvas to render to + */ + function init(canvas, noFlush) { + var i = 0, contexts = [ + 'webgl', + 'experimental-webgl', + 'moz-webgl', + 'webkit-3d' + ]; + isInited = false; + if (!canvas) { + return false; + } + if (settings.debug.timeSetup) { + console.time('gl setup'); // eslint-disable-line no-console + } + for (; i < contexts.length; i++) { + gl = canvas.getContext(contexts[i], { + // premultipliedAlpha: false + }); + if (gl) { + break; + } + } + if (gl) { + if (!noFlush) { + flush(); + } + } + else { + return false; + } + gl.enable(gl.BLEND); + // gl.blendFunc(gl.SRC_ALPHA, gl.ONE); + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + gl.disable(gl.DEPTH_TEST); + // gl.depthMask(gl.FALSE); + gl.depthFunc(gl.LESS); + shader = GLShader(gl); // eslint-disable-line new-cap + if (!shader) { + // We need to abort, there's no shader context + return false; + } + vbuffer = GLVertexBuffer(gl, shader); // eslint-disable-line new-cap + /** + * @private + */ + function createTexture(name, fn) { + var props = { + isReady: false, + texture: doc.createElement('canvas'), + handle: gl.createTexture() + }, ctx = props.texture.getContext('2d'); + textureHandles[name] = props; + props.texture.width = 512; + props.texture.height = 512; + ctx.mozImageSmoothingEnabled = false; + ctx.webkitImageSmoothingEnabled = false; + ctx.msImageSmoothingEnabled = false; + ctx.imageSmoothingEnabled = false; + ctx.strokeStyle = 'rgba(255, 255, 255, 0)'; + ctx.fillStyle = '#FFF'; + fn(ctx); + try { + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, props.handle); + // gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, props.texture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + // gl.generateMipmap(gl.TEXTURE_2D); + gl.bindTexture(gl.TEXTURE_2D, null); + props.isReady = true; + } + catch (e) { + // silent error + } + } + // Circle shape + createTexture('circle', function (ctx) { + ctx.beginPath(); + ctx.arc(256, 256, 256, 0, 2 * Math.PI); + ctx.stroke(); + ctx.fill(); + }); + // Square shape + createTexture('square', function (ctx) { + ctx.fillRect(0, 0, 512, 512); + }); + // Diamond shape + createTexture('diamond', function (ctx) { + ctx.beginPath(); + ctx.moveTo(256, 0); + ctx.lineTo(512, 256); + ctx.lineTo(256, 512); + ctx.lineTo(0, 256); + ctx.lineTo(256, 0); + ctx.fill(); + }); + // Triangle shape + createTexture('triangle', function (ctx) { + ctx.beginPath(); + ctx.moveTo(0, 512); + ctx.lineTo(256, 0); + ctx.lineTo(512, 512); + ctx.lineTo(0, 512); + ctx.fill(); + }); + // Triangle shape (rotated) + createTexture('triangle-down', function (ctx) { + ctx.beginPath(); + ctx.moveTo(0, 0); + ctx.lineTo(256, 512); + ctx.lineTo(512, 0); + ctx.lineTo(0, 0); + ctx.fill(); + }); + isInited = true; + if (settings.debug.timeSetup) { + console.timeEnd('gl setup'); // eslint-disable-line no-console + } + return true; + } + /** + * Check if we have a valid OGL context + * @private + * @returns {Boolean} - true if the context is valid + */ + function valid() { + return gl !== false; + } + /** + * Check if the renderer has been initialized + * @private + * @returns {Boolean} - true if it has, false if not + */ + function inited() { + return isInited; + } + /** + * @private + */ + function destroy() { + flush(); + vbuffer.destroy(); + shader.destroy(); + if (gl) { + objectEach(textureHandles, function (key) { + if (textureHandles[key].handle) { + gl.deleteTexture(textureHandles[key].handle); + } + }); + gl.canvas.width = 1; + gl.canvas.height = 1; + } + } + // ///////////////////////////////////////////////////////////////////////// + exports = { + allocateBufferForSingleSeries: allocateBufferForSingleSeries, + pushSeries: pushSeries, + setSize: setSize, + inited: inited, + setThreshold: setThreshold, + init: init, + render: renderWhenReady, + settings: settings, + valid: valid, + clear: clear, + flush: flush, + setXAxis: setXAxis, + setYAxis: setYAxis, + data: data, + gl: getGL, + allocateBuffer: allocateBuffer, + destroy: destroy, + setOptions: setOptions + }; + return exports; + } + + return GLRenderer; + }); + _registerModule(_modules, 'modules/boost/boost-attach.js', [_modules['parts/Globals.js'], _modules['modules/boost/wgl-renderer.js'], _modules['parts/Utilities.js']], function (H, GLRenderer, U) { + /* * + * + * Copyright (c) 2019-2020 Highsoft AS + * + * Boost module: stripped-down renderer for higher performance + * + * License: highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var error = U.error; + var win = H.win, doc = win.document, mainCanvas = doc.createElement('canvas'); + /** + * Create a canvas + context and attach it to the target + * + * @private + * @function createAndAttachRenderer + * + * @param {Highcharts.Chart} chart + * the chart + * + * @param {Highcharts.Series} series + * the series + * + * @return {Highcharts.BoostGLRenderer} + * the canvas renderer + */ + function createAndAttachRenderer(chart, series) { + var width = chart.chartWidth, height = chart.chartHeight, target = chart, targetGroup = chart.seriesGroup || series.group, alpha = 1, foSupported = doc.implementation.hasFeature('www.http://w3.org/TR/SVG11/feature#Extensibility', '1.1'); + if (chart.isChartSeriesBoosting()) { + target = chart; + } + else { + target = series; + } + // Support for foreignObject is flimsy as best. + // IE does not support it, and Chrome has a bug which messes up + // the canvas draw order. + // As such, we force the Image fallback for now, but leaving the + // actual Canvas path in-place in case this changes in the future. + foSupported = false; + if (!target.renderTarget) { + target.canvas = mainCanvas; + // Fall back to image tag if foreignObject isn't supported, + // or if we're exporting. + if (chart.renderer.forExport || !foSupported) { + target.renderTarget = chart.renderer.image('', 0, 0, width, height) + .addClass('highcharts-boost-canvas') + .add(targetGroup); + target.boostClear = function () { + target.renderTarget.attr({ href: '' }); + }; + target.boostCopy = function () { + target.boostResizeTarget(); + target.renderTarget.attr({ + href: target.canvas.toDataURL('image/png') + }); + }; + } + else { + target.renderTargetFo = chart.renderer + .createElement('foreignObject') + .add(targetGroup); + target.renderTarget = doc.createElement('canvas'); + target.renderTargetCtx = + target.renderTarget.getContext('2d'); + target.renderTargetFo.element.appendChild(target.renderTarget); + target.boostClear = function () { + target.renderTarget.width = + target.canvas.width; + target.renderTarget.height = + target.canvas.height; + }; + target.boostCopy = function () { + target.renderTarget.width = + target.canvas.width; + target.renderTarget.height = + target.canvas.height; + target.renderTargetCtx + .drawImage(target.canvas, 0, 0); + }; + } + target.boostResizeTarget = function () { + width = chart.chartWidth; + height = chart.chartHeight; + (target.renderTargetFo || target.renderTarget) + .attr({ + x: 0, + y: 0, + width: width, + height: height + }) + .css({ + pointerEvents: 'none', + mixedBlendMode: 'normal', + opacity: alpha + }); + if (target instanceof H.Chart) { + target.markerGroup.translate(chart.plotLeft, chart.plotTop); + } + }; + target.boostClipRect = chart.renderer.clipRect(); + (target.renderTargetFo || target.renderTarget) + .clip(target.boostClipRect); + if (target instanceof H.Chart) { + target.markerGroup = target.renderer.g().add(targetGroup); + target.markerGroup.translate(series.xAxis.pos, series.yAxis.pos); + } + } + target.canvas.width = width; + target.canvas.height = height; + target.boostClipRect.attr(chart.getBoostClipRect(target)); + target.boostResizeTarget(); + target.boostClear(); + if (!target.ogl) { + target.ogl = GLRenderer(function () { + if (target.ogl.settings.debug.timeBufferCopy) { + console.time('buffer copy'); // eslint-disable-line no-console + } + target.boostCopy(); + if (target.ogl.settings.debug.timeBufferCopy) { + console.timeEnd('buffer copy'); // eslint-disable-line no-console + } + }); + if (!target.ogl.init(target.canvas)) { + // The OGL renderer couldn't be inited. + // This likely means a shader error as we wouldn't get to this point + // if there was no WebGL support. + error('[highcharts boost] - unable to init WebGL renderer'); + } + // target.ogl.clear(); + target.ogl.setOptions(chart.options.boost || {}); + if (target instanceof H.Chart) { + target.ogl.allocateBuffer(chart); + } + } + target.ogl.setSize(width, height); + return target.ogl; + } + + return createAndAttachRenderer; + }); + _registerModule(_modules, 'modules/boost/boost-utils.js', [_modules['parts/Globals.js'], _modules['modules/boost/boostable-map.js'], _modules['modules/boost/boost-attach.js'], _modules['parts/Utilities.js']], function (H, boostableMap, createAndAttachRenderer, U) { + /* * + * + * Copyright (c) 2019-2020 Highsoft AS + * + * Boost module: stripped-down renderer for higher performance + * + * License: highcharts.com/license + * + * This files contains generic utility functions used by the boost module. + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var pick = U.pick; + var win = H.win, doc = win.document; + // This should be a const. + var CHUNK_SIZE = 3000; + /** + * Tolerant max() function. + * + * @private + * @function patientMax + * + * @param {...Array>} args + * Max arguments + * + * @return {number} + * Max value + */ + function patientMax() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var r = -Number.MAX_VALUE; + args.forEach(function (t) { + if (typeof t !== 'undefined' && + t !== null && + typeof t.length !== 'undefined') { + // r = r < t.length ? t.length : r; + if (t.length > 0) { + r = t.length; + return true; + } + } + }); + return r; + } + /** + * Return true if ths boost.enabled option is true + * + * @private + * @function boostEnabled + * + * @param {Highcharts.Chart} chart + * The chart + * + * @return {boolean} + * True, if boost is enabled. + */ + function boostEnabled(chart) { + return pick((chart && + chart.options && + chart.options.boost && + chart.options.boost.enabled), true); + } + /** + * Returns true if we should force boosting the chart + * @private + * @function shouldForceChartSeriesBoosting + * + * @param {Highcharts.Chart} chart + * The chart to check for forcing on + * + * @return {boolean} + * True, if boosting should be forced. + */ + function shouldForceChartSeriesBoosting(chart) { + // If there are more than five series currently boosting, + // we should boost the whole chart to avoid running out of webgl contexts. + var sboostCount = 0, canBoostCount = 0, allowBoostForce = pick(chart.options.boost && chart.options.boost.allowForce, true), series; + if (typeof chart.boostForceChartBoost !== 'undefined') { + return chart.boostForceChartBoost; + } + if (chart.series.length > 1) { + for (var i = 0; i < chart.series.length; i++) { + series = chart.series[i]; + // Don't count series with boostThreshold set to 0 + // See #8950 + // Also don't count if the series is hidden. + // See #9046 + if (series.options.boostThreshold === 0 || + series.visible === false) { + continue; + } + // Don't count heatmap series as they are handled differently. + // In the future we should make the heatmap/treemap path compatible + // with forcing. See #9636. + if (series.type === 'heatmap') { + continue; + } + if (boostableMap[series.type]) { + ++canBoostCount; + } + if (patientMax(series.processedXData, series.options.data, + // series.xData, + series.points) >= (series.options.boostThreshold || Number.MAX_VALUE)) { + ++sboostCount; + } + } + } + chart.boostForceChartBoost = allowBoostForce && ((canBoostCount === chart.series.length && + sboostCount > 0) || + sboostCount > 5); + return chart.boostForceChartBoost; + } + /* eslint-disable valid-jsdoc */ + /** + * Performs the actual render if the renderer is + * attached to the series. + * @private + * @param renderer {OGLRenderer} - the renderer + * @param series {Highcharts.Series} - the series + */ + function renderIfNotSeriesBoosting(renderer, series, chart) { + if (renderer && + series.renderTarget && + series.canvas && + !(chart || series.chart).isChartSeriesBoosting()) { + renderer.render(chart || series.chart); + } + } + /** + * @private + */ + function allocateIfNotSeriesBoosting(renderer, series) { + if (renderer && + series.renderTarget && + series.canvas && + !series.chart.isChartSeriesBoosting()) { + renderer.allocateBufferForSingleSeries(series); + } + } + /** + * An "async" foreach loop. Uses a setTimeout to keep the loop from blocking the + * UI thread. + * + * @private + * + * @param arr {Array} - the array to loop through + * @param fn {Function} - the callback to call for each item + * @param finalFunc {Function} - the callback to call when done + * @param chunkSize {Number} - the number of iterations per timeout + * @param i {Number} - the current index + * @param noTimeout {Boolean} - set to true to skip timeouts + */ + function eachAsync(arr, fn, finalFunc, chunkSize, i, noTimeout) { + i = i || 0; + chunkSize = chunkSize || CHUNK_SIZE; + var threshold = i + chunkSize, proceed = true; + while (proceed && i < threshold && i < arr.length) { + proceed = fn(arr[i], i); + ++i; + } + if (proceed) { + if (i < arr.length) { + if (noTimeout) { + eachAsync(arr, fn, finalFunc, chunkSize, i, noTimeout); + } + else if (win.requestAnimationFrame) { + // If available, do requestAnimationFrame - shaves off a few ms + win.requestAnimationFrame(function () { + eachAsync(arr, fn, finalFunc, chunkSize, i); + }); + } + else { + setTimeout(function () { + eachAsync(arr, fn, finalFunc, chunkSize, i); + }); + } + } + else if (finalFunc) { + finalFunc(); + } + } + } + /** + * Returns true if the current browser supports webgl + * + * @private + * @function hasWebGLSupport + * + * @return {boolean} + */ + function hasWebGLSupport() { + var i = 0, canvas, contexts = ['webgl', 'experimental-webgl', 'moz-webgl', 'webkit-3d'], context = false; + if (typeof win.WebGLRenderingContext !== 'undefined') { + canvas = doc.createElement('canvas'); + for (; i < contexts.length; i++) { + try { + context = canvas.getContext(contexts[i]); + if (typeof context !== 'undefined' && context !== null) { + return true; + } + } + catch (e) { + // silent error + } + } + } + return false; + } + /* eslint-disable no-invalid-this */ + /** + * Used for treemap|heatmap.drawPoints + * + * @private + * @function pointDrawHandler + * + * @param {Function} proceed + * + * @return {*} + */ + function pointDrawHandler(proceed) { + var enabled = true, renderer; + if (this.chart.options && this.chart.options.boost) { + enabled = typeof this.chart.options.boost.enabled === 'undefined' ? + true : + this.chart.options.boost.enabled; + } + if (!enabled || !this.isSeriesBoosting) { + return proceed.call(this); + } + this.chart.isBoosting = true; + // Make sure we have a valid OGL context + renderer = createAndAttachRenderer(this.chart, this); + if (renderer) { + allocateIfNotSeriesBoosting(renderer, this); + renderer.pushSeries(this); + } + renderIfNotSeriesBoosting(renderer, this); + } + /* eslint-enable no-invalid-this, valid-jsdoc */ + var funs = { + patientMax: patientMax, + boostEnabled: boostEnabled, + shouldForceChartSeriesBoosting: shouldForceChartSeriesBoosting, + renderIfNotSeriesBoosting: renderIfNotSeriesBoosting, + allocateIfNotSeriesBoosting: allocateIfNotSeriesBoosting, + eachAsync: eachAsync, + hasWebGLSupport: hasWebGLSupport, + pointDrawHandler: pointDrawHandler + }; + // This needs to be fixed. + H.hasWebGLSupport = hasWebGLSupport; + + return funs; + }); + _registerModule(_modules, 'modules/boost/boost-init.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/boost/boost-utils.js'], _modules['modules/boost/boost-attach.js']], function (H, U, butils, createAndAttachRenderer) { + /* * + * + * Copyright (c) 2019-2020 Highsoft AS + * + * Boost module: stripped-down renderer for higher performance + * + * License: highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, extend = U.extend, fireEvent = U.fireEvent, wrap = U.wrap; + var Series = H.Series, seriesTypes = H.seriesTypes, noop = function () { }, eachAsync = butils.eachAsync, pointDrawHandler = butils.pointDrawHandler, allocateIfNotSeriesBoosting = butils.allocateIfNotSeriesBoosting, renderIfNotSeriesBoosting = butils.renderIfNotSeriesBoosting, shouldForceChartSeriesBoosting = butils.shouldForceChartSeriesBoosting, index; + /* eslint-disable valid-jsdoc */ + /** + * Initialize the boot module. + * + * @private + * @return {void} + */ + function init() { + extend(Series.prototype, { + /** + * @private + * @function Highcharts.Series#renderCanvas + */ + renderCanvas: function () { + var series = this, options = series.options || {}, renderer = false, chart = series.chart, xAxis = this.xAxis, yAxis = this.yAxis, xData = options.xData || series.processedXData, yData = options.yData || series.processedYData, rawData = options.data, xExtremes = xAxis.getExtremes(), xMin = xExtremes.min, xMax = xExtremes.max, yExtremes = yAxis.getExtremes(), yMin = yExtremes.min, yMax = yExtremes.max, pointTaken = {}, lastClientX, sampling = !!series.sampling, points, enableMouseTracking = options.enableMouseTracking !== false, threshold = options.threshold, yBottom = yAxis.getThreshold(threshold), isRange = series.pointArrayMap && + series.pointArrayMap.join(',') === 'low,high', isStacked = !!options.stacking, cropStart = series.cropStart || 0, requireSorting = series.requireSorting, useRaw = !xData, minVal, maxVal, minI, maxI, boostOptions, compareX = options.findNearestPointBy === 'x', xDataFull = (this.xData || + this.options.xData || + this.processedXData || + false), addKDPoint = function (clientX, plotY, i) { + // We need to do ceil on the clientX to make things + // snap to pixel values. The renderer will frequently + // draw stuff on "sub-pixels". + clientX = Math.ceil(clientX); + // Shaves off about 60ms compared to repeated concatenation + index = compareX ? clientX : clientX + ',' + plotY; + // The k-d tree requires series points. + // Reduce the amount of points, since the time to build the + // tree increases exponentially. + if (enableMouseTracking && !pointTaken[index]) { + pointTaken[index] = true; + if (chart.inverted) { + clientX = xAxis.len - clientX; + plotY = yAxis.len - plotY; + } + points.push({ + x: xDataFull ? xDataFull[cropStart + i] : false, + clientX: clientX, + plotX: clientX, + plotY: plotY, + i: cropStart + i + }); + } + }; + // Get or create the renderer + renderer = createAndAttachRenderer(chart, series); + chart.isBoosting = true; + boostOptions = renderer.settings; + if (!this.visible) { + return; + } + // If we are zooming out from SVG mode, destroy the graphics + if (this.points || this.graph) { + this.destroyGraphics(); + } + // If we're rendering per. series we should create the marker groups + // as usual. + if (!chart.isChartSeriesBoosting()) { + // If all series were boosting, but are not anymore + // restore private markerGroup + if (this.markerGroup === chart.markerGroup) { + this.markerGroup = void 0; + } + this.markerGroup = series.plotGroup('markerGroup', 'markers', true, 1, chart.seriesGroup); + } + else { + // If series has a private markeGroup, remove that + // and use common markerGroup + if (this.markerGroup && + this.markerGroup !== chart.markerGroup) { + this.markerGroup.destroy(); + } + // Use a single group for the markers + this.markerGroup = chart.markerGroup; + // When switching from chart boosting mode, destroy redundant + // series boosting targets + if (this.renderTarget) { + this.renderTarget = this.renderTarget.destroy(); + } + } + points = this.points = []; + // Do not start building while drawing + series.buildKDTree = noop; + if (renderer) { + allocateIfNotSeriesBoosting(renderer, this); + renderer.pushSeries(series); + // Perform the actual renderer if we're on series level + renderIfNotSeriesBoosting(renderer, this, chart); + } + /** + * This builds the KD-tree + * @private + */ + function processPoint(d, i) { + var x, y, clientX, plotY, isNull, low = false, chartDestroyed = typeof chart.index === 'undefined', isYInside = true; + if (!chartDestroyed) { + if (useRaw) { + x = d[0]; + y = d[1]; + } + else { + x = d; + y = yData[i]; + } + // Resolve low and high for range series + if (isRange) { + if (useRaw) { + y = d.slice(1, 3); + } + low = y[0]; + y = y[1]; + } + else if (isStacked) { + x = d.x; + y = d.stackY; + low = y - d.y; + } + isNull = y === null; + // Optimize for scatter zooming + if (!requireSorting) { + isYInside = y >= yMin && y <= yMax; + } + if (!isNull && x >= xMin && x <= xMax && isYInside) { + clientX = xAxis.toPixels(x, true); + if (sampling) { + if (typeof minI === 'undefined' || + clientX === lastClientX) { + if (!isRange) { + low = y; + } + if (typeof maxI === 'undefined' || + y > maxVal) { + maxVal = y; + maxI = i; + } + if (typeof minI === 'undefined' || + low < minVal) { + minVal = low; + minI = i; + } + } + // Add points and reset + if (clientX !== lastClientX) { + // maxI is number too: + if (typeof minI !== 'undefined') { + plotY = + yAxis.toPixels(maxVal, true); + yBottom = + yAxis.toPixels(minVal, true); + addKDPoint(clientX, plotY, maxI); + if (yBottom !== plotY) { + addKDPoint(clientX, yBottom, minI); + } + } + minI = maxI = void 0; + lastClientX = clientX; + } + } + else { + plotY = Math.ceil(yAxis.toPixels(y, true)); + addKDPoint(clientX, plotY, i); + } + } + } + return !chartDestroyed; + } + /** + * @private + */ + function doneProcessing() { + fireEvent(series, 'renderedCanvas'); + // Go back to prototype, ready to build + delete series.buildKDTree; + series.buildKDTree(); + if (boostOptions.debug.timeKDTree) { + console.timeEnd('kd tree building'); // eslint-disable-line no-console + } + } + // Loop over the points to build the k-d tree - skip this if + // exporting + if (!chart.renderer.forExport) { + if (boostOptions.debug.timeKDTree) { + console.time('kd tree building'); // eslint-disable-line no-console + } + eachAsync(isStacked ? series.data : (xData || rawData), processPoint, doneProcessing); + } + } + }); + /* + * We need to handle heatmaps separatly, since we can't perform the + * size/color calculations in the shader easily. + * + * This likely needs future optimization. + */ + ['heatmap', 'treemap'].forEach(function (t) { + if (seriesTypes[t]) { + wrap(seriesTypes[t].prototype, 'drawPoints', pointDrawHandler); + } + }); + /* eslint-disable no-invalid-this */ + if (seriesTypes.bubble) { + // By default, the bubble series does not use the KD-tree, so force it + // to. + delete seriesTypes.bubble.prototype.buildKDTree; + // seriesTypes.bubble.prototype.directTouch = false; + // Needed for markers to work correctly + wrap(seriesTypes.bubble.prototype, 'markerAttribs', function (proceed) { + if (this.isSeriesBoosting) { + return false; + } + return proceed.apply(this, [].slice.call(arguments, 1)); + }); + } + seriesTypes.scatter.prototype.fill = true; + extend(seriesTypes.area.prototype, { + fill: true, + fillOpacity: true, + sampling: true + }); + extend(seriesTypes.column.prototype, { + fill: true, + sampling: true + }); + // Take care of the canvas blitting + H.Chart.prototype.callbacks.push(function (chart) { + /** + * Convert chart-level canvas to image. + * @private + */ + function canvasToSVG() { + if (chart.ogl && chart.isChartSeriesBoosting()) { + chart.ogl.render(chart); + } + } + /** + * Clear chart-level canvas. + * @private + */ + function preRender() { + // Reset force state + chart.boostForceChartBoost = void 0; + chart.boostForceChartBoost = shouldForceChartSeriesBoosting(chart); + chart.isBoosting = false; + if (!chart.isChartSeriesBoosting() && chart.didBoost) { + chart.didBoost = false; + } + // Clear the canvas + if (chart.boostClear) { + chart.boostClear(); + } + if (chart.canvas && chart.ogl && chart.isChartSeriesBoosting()) { + chart.didBoost = true; + // Allocate + chart.ogl.allocateBuffer(chart); + } + // see #6518 + #6739 + if (chart.markerGroup && + chart.xAxis && + chart.xAxis.length > 0 && + chart.yAxis && + chart.yAxis.length > 0) { + chart.markerGroup.translate(chart.xAxis[0].pos, chart.yAxis[0].pos); + } + } + addEvent(chart, 'predraw', preRender); + addEvent(chart, 'render', canvasToSVG); + // addEvent(chart, 'zoom', function () { + // chart.boostForceChartBoost = + // shouldForceChartSeriesBoosting(chart); + // }); + }); + /* eslint-enable no-invalid-this */ + } + + return init; + }); + _registerModule(_modules, 'modules/boost/boost-overrides.js', [_modules['parts/Globals.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js'], _modules['modules/boost/boost-utils.js'], _modules['modules/boost/boostables.js'], _modules['modules/boost/boostable-map.js']], function (H, Point, U, butils, boostable, boostableMap) { + /* * + * + * Copyright (c) 2019-2020 Highsoft AS + * + * Boost module: stripped-down renderer for higher performance + * + * License: highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, error = U.error, isArray = U.isArray, isNumber = U.isNumber, pick = U.pick, wrap = U.wrap; + var boostEnabled = butils.boostEnabled, shouldForceChartSeriesBoosting = butils.shouldForceChartSeriesBoosting, Chart = H.Chart, Series = H.Series, seriesTypes = H.seriesTypes, plotOptions = H.getOptions().plotOptions; + /** + * Returns true if the chart is in series boost mode. + * + * @function Highcharts.Chart#isChartSeriesBoosting + * + * @param {Highcharts.Chart} chart + * the chart to check + * + * @return {boolean} + * true if the chart is in series boost mode + */ + Chart.prototype.isChartSeriesBoosting = function () { + var isSeriesBoosting, threshold = pick(this.options.boost && this.options.boost.seriesThreshold, 50); + isSeriesBoosting = threshold <= this.series.length || + shouldForceChartSeriesBoosting(this); + return isSeriesBoosting; + }; + /* eslint-disable valid-jsdoc */ + /** + * Get the clip rectangle for a target, either a series or the chart. For the + * chart, we need to consider the maximum extent of its Y axes, in case of + * Highstock panes and navigator. + * + * @private + * @function Highcharts.Chart#getBoostClipRect + * + * @param {Highcharts.Chart} target + * + * @return {Highcharts.BBoxObject} + */ + Chart.prototype.getBoostClipRect = function (target) { + var clipBox = { + x: this.plotLeft, + y: this.plotTop, + width: this.plotWidth, + height: this.plotHeight + }; + if (target === this) { + this.yAxis.forEach(function (yAxis) { + clipBox.y = Math.min(yAxis.pos, clipBox.y); + clipBox.height = Math.max(yAxis.pos - this.plotTop + yAxis.len, clipBox.height); + }, this); + } + return clipBox; + }; + /** + * Return a full Point object based on the index. + * The boost module uses stripped point objects for performance reasons. + * + * @function Highcharts.Series#getPoint + * + * @param {object|Highcharts.Point} boostPoint + * A stripped-down point object + * + * @return {Highcharts.Point} + * A Point object as per https://api.highcharts.com/highcharts#Point + */ + Series.prototype.getPoint = function (boostPoint) { + var point = boostPoint, xData = (this.xData || this.options.xData || this.processedXData || + false); + if (boostPoint && !(boostPoint instanceof this.pointClass)) { + point = (new this.pointClass()).init(// eslint-disable-line new-cap + this, this.options.data[boostPoint.i], xData ? xData[boostPoint.i] : void 0); + point.category = pick(this.xAxis.categories ? + this.xAxis.categories[point.x] : + point.x, // @todo simplify + point.x); + point.dist = boostPoint.dist; + point.distX = boostPoint.distX; + point.plotX = boostPoint.plotX; + point.plotY = boostPoint.plotY; + point.index = boostPoint.i; + point.isInside = this.isPointInside(boostPoint); + } + return point; + }; + /* eslint-disable no-invalid-this */ + // Return a point instance from the k-d-tree + wrap(Series.prototype, 'searchPoint', function (proceed) { + return this.getPoint(proceed.apply(this, [].slice.call(arguments, 1))); + }); + // For inverted series, we need to swap X-Y values before running base methods + wrap(Point.prototype, 'haloPath', function (proceed) { + var halo, point = this, series = point.series, chart = series.chart, plotX = point.plotX, plotY = point.plotY, inverted = chart.inverted; + if (series.isSeriesBoosting && inverted) { + point.plotX = series.yAxis.len - plotY; + point.plotY = series.xAxis.len - plotX; + } + halo = proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + if (series.isSeriesBoosting && inverted) { + point.plotX = plotX; + point.plotY = plotY; + } + return halo; + }); + wrap(Series.prototype, 'markerAttribs', function (proceed, point) { + var attribs, series = this, chart = series.chart, plotX = point.plotX, plotY = point.plotY, inverted = chart.inverted; + if (series.isSeriesBoosting && inverted) { + point.plotX = series.yAxis.len - plotY; + point.plotY = series.xAxis.len - plotX; + } + attribs = proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + if (series.isSeriesBoosting && inverted) { + point.plotX = plotX; + point.plotY = plotY; + } + return attribs; + }); + /* + * Extend series.destroy to also remove the fake k-d-tree points (#5137). + * Normally this is handled by Series.destroy that calls Point.destroy, + * but the fake search points are not registered like that. + */ + addEvent(Series, 'destroy', function () { + var series = this, chart = series.chart; + if (chart.markerGroup === series.markerGroup) { + series.markerGroup = null; + } + if (chart.hoverPoints) { + chart.hoverPoints = chart.hoverPoints.filter(function (point) { + return point.series === series; + }); + } + if (chart.hoverPoint && chart.hoverPoint.series === series) { + chart.hoverPoint = null; + } + }); + /* + * Do not compute extremes when min and max are set. + * If we use this in the core, we can add the hook + * to hasExtremes to the methods directly. + */ + wrap(Series.prototype, 'getExtremes', function (proceed) { + if (!this.isSeriesBoosting || (!this.hasExtremes || !this.hasExtremes())) { + return proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + } + return {}; + }); + /* + * Override a bunch of methods the same way. If the number of points is + * below the threshold, run the original method. If not, check for a + * canvas version or do nothing. + * + * Note that we're not overriding any of these for heatmaps. + */ + [ + 'translate', + 'generatePoints', + 'drawTracker', + 'drawPoints', + 'render' + ].forEach(function (method) { + /** + * @private + */ + function branch(proceed) { + var letItPass = this.options.stacking && + (method === 'translate' || method === 'generatePoints'); + if (!this.isSeriesBoosting || + letItPass || + !boostEnabled(this.chart) || + this.type === 'heatmap' || + this.type === 'treemap' || + !boostableMap[this.type] || + this.options.boostThreshold === 0) { + proceed.call(this); + // If a canvas version of the method exists, like renderCanvas(), run + } + else if (this[method + 'Canvas']) { + this[method + 'Canvas'](); + } + } + wrap(Series.prototype, method, branch); + // A special case for some types - their translate method is already wrapped + if (method === 'translate') { + [ + 'column', + 'bar', + 'arearange', + 'columnrange', + 'heatmap', + 'treemap' + ].forEach(function (type) { + if (seriesTypes[type]) { + wrap(seriesTypes[type].prototype, method, branch); + } + }); + } + }); + // If the series is a heatmap or treemap, or if the series is not boosting + // do the default behaviour. Otherwise, process if the series has no extremes. + wrap(Series.prototype, 'processData', function (proceed) { + var series = this, dataToMeasure = this.options.data, firstPoint; + /** + * Used twice in this function, first on this.options.data, the second + * time it runs the check again after processedXData is built. + * @private + * @todo Check what happens with data grouping + */ + function getSeriesBoosting(data) { + return series.chart.isChartSeriesBoosting() || ((data ? data.length : 0) >= + (series.options.boostThreshold || Number.MAX_VALUE)); + } + if (boostEnabled(this.chart) && boostableMap[this.type]) { + // If there are no extremes given in the options, we also need to + // process the data to read the data extremes. If this is a heatmap, do + // default behaviour. + if (!getSeriesBoosting(dataToMeasure) || // First pass with options.data + this.type === 'heatmap' || + this.type === 'treemap' || + this.options.stacking || // processedYData for the stack (#7481) + !this.hasExtremes || + !this.hasExtremes(true)) { + proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + dataToMeasure = this.processedXData; + } + // Set the isBoosting flag, second pass with processedXData to see if we + // have zoomed. + this.isSeriesBoosting = getSeriesBoosting(dataToMeasure); + // Enter or exit boost mode + if (this.isSeriesBoosting) { + // Force turbo-mode: + firstPoint = this.getFirstValidPoint(this.options.data); + if (!isNumber(firstPoint) && !isArray(firstPoint)) { + error(12, false, this.chart); + } + this.enterBoost(); + } + else if (this.exitBoost) { + this.exitBoost(); + } + // The series type is not boostable + } + else { + proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + } + }); + addEvent(Series, 'hide', function () { + if (this.canvas && this.renderTarget) { + if (this.ogl) { + this.ogl.clear(); + } + this.boostClear(); + } + }); + /** + * Enter boost mode and apply boost-specific properties. + * + * @function Highcharts.Series#enterBoost + */ + Series.prototype.enterBoost = function () { + this.alteredByBoost = []; + // Save the original values, including whether it was an own property or + // inherited from the prototype. + ['allowDG', 'directTouch', 'stickyTracking'].forEach(function (prop) { + this.alteredByBoost.push({ + prop: prop, + val: this[prop], + own: Object.hasOwnProperty.call(this, prop) + }); + }, this); + this.allowDG = false; + this.directTouch = false; + this.stickyTracking = true; + // Hide series label if any + if (this.labelBySeries) { + this.labelBySeries = this.labelBySeries.destroy(); + } + }; + /** + * Exit from boost mode and restore non-boost properties. + * + * @function Highcharts.Series#exitBoost + */ + Series.prototype.exitBoost = function () { + // Reset instance properties and/or delete instance properties and go back + // to prototype + (this.alteredByBoost || []).forEach(function (setting) { + if (setting.own) { + this[setting.prop] = setting.val; + } + else { + // Revert to prototype + delete this[setting.prop]; + } + }, this); + // Clear previous run + if (this.boostClear) { + this.boostClear(); + } + }; + /** + * @private + * @function Highcharts.Series#hasExtremes + * + * @param {boolean} checkX + * + * @return {boolean} + */ + Series.prototype.hasExtremes = function (checkX) { + var options = this.options, data = options.data, xAxis = this.xAxis && this.xAxis.options, yAxis = this.yAxis && this.yAxis.options, colorAxis = this.colorAxis && this.colorAxis.options; + return data.length > (options.boostThreshold || Number.MAX_VALUE) && + // Defined yAxis extremes + isNumber(yAxis.min) && + isNumber(yAxis.max) && + // Defined (and required) xAxis extremes + (!checkX || + (isNumber(xAxis.min) && isNumber(xAxis.max))) && + // Defined (e.g. heatmap) colorAxis extremes + (!colorAxis || + (isNumber(colorAxis.min) && isNumber(colorAxis.max))); + }; + /** + * If implemented in the core, parts of this can probably be + * shared with other similar methods in Highcharts. + * + * @function Highcharts.Series#destroyGraphics + */ + Series.prototype.destroyGraphics = function () { + var series = this, points = this.points, point, i; + if (points) { + for (i = 0; i < points.length; i = i + 1) { + point = points[i]; + if (point && point.destroyElements) { + point.destroyElements(); // #7557 + } + } + } + ['graph', 'area', 'tracker'].forEach(function (prop) { + if (series[prop]) { + series[prop] = series[prop].destroy(); + } + }); + }; + // Set default options + boostable.forEach(function (type) { + if (plotOptions[type]) { + plotOptions[type].boostThreshold = 5000; + plotOptions[type].boostData = []; + seriesTypes[type].prototype.fillOpacity = true; + } + }); + + }); + _registerModule(_modules, 'modules/boost/named-colors.js', [_modules['parts/Color.js']], function (Color) { + /* * + * + * Copyright (c) 2019-2020 Highsoft AS + * + * Boost module: stripped-down renderer for higher performance + * + * License: highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + // Register color names since GL can't render those directly. + // TODO: When supporting modern syntax, make this a const and a named export + var defaultHTMLColorMap = { + aliceblue: '#f0f8ff', + antiquewhite: '#faebd7', + aqua: '#00ffff', + aquamarine: '#7fffd4', + azure: '#f0ffff', + beige: '#f5f5dc', + bisque: '#ffe4c4', + black: '#000000', + blanchedalmond: '#ffebcd', + blue: '#0000ff', + blueviolet: '#8a2be2', + brown: '#a52a2a', + burlywood: '#deb887', + cadetblue: '#5f9ea0', + chartreuse: '#7fff00', + chocolate: '#d2691e', + coral: '#ff7f50', + cornflowerblue: '#6495ed', + cornsilk: '#fff8dc', + crimson: '#dc143c', + cyan: '#00ffff', + darkblue: '#00008b', + darkcyan: '#008b8b', + darkgoldenrod: '#b8860b', + darkgray: '#a9a9a9', + darkgreen: '#006400', + darkkhaki: '#bdb76b', + darkmagenta: '#8b008b', + darkolivegreen: '#556b2f', + darkorange: '#ff8c00', + darkorchid: '#9932cc', + darkred: '#8b0000', + darksalmon: '#e9967a', + darkseagreen: '#8fbc8f', + darkslateblue: '#483d8b', + darkslategray: '#2f4f4f', + darkturquoise: '#00ced1', + darkviolet: '#9400d3', + deeppink: '#ff1493', + deepskyblue: '#00bfff', + dimgray: '#696969', + dodgerblue: '#1e90ff', + feldspar: '#d19275', + firebrick: '#b22222', + floralwhite: '#fffaf0', + forestgreen: '#228b22', + fuchsia: '#ff00ff', + gainsboro: '#dcdcdc', + ghostwhite: '#f8f8ff', + gold: '#ffd700', + goldenrod: '#daa520', + gray: '#808080', + green: '#008000', + greenyellow: '#adff2f', + honeydew: '#f0fff0', + hotpink: '#ff69b4', + indianred: '#cd5c5c', + indigo: '#4b0082', + ivory: '#fffff0', + khaki: '#f0e68c', + lavender: '#e6e6fa', + lavenderblush: '#fff0f5', + lawngreen: '#7cfc00', + lemonchiffon: '#fffacd', + lightblue: '#add8e6', + lightcoral: '#f08080', + lightcyan: '#e0ffff', + lightgoldenrodyellow: '#fafad2', + lightgrey: '#d3d3d3', + lightgreen: '#90ee90', + lightpink: '#ffb6c1', + lightsalmon: '#ffa07a', + lightseagreen: '#20b2aa', + lightskyblue: '#87cefa', + lightslateblue: '#8470ff', + lightslategray: '#778899', + lightsteelblue: '#b0c4de', + lightyellow: '#ffffe0', + lime: '#00ff00', + limegreen: '#32cd32', + linen: '#faf0e6', + magenta: '#ff00ff', + maroon: '#800000', + mediumaquamarine: '#66cdaa', + mediumblue: '#0000cd', + mediumorchid: '#ba55d3', + mediumpurple: '#9370d8', + mediumseagreen: '#3cb371', + mediumslateblue: '#7b68ee', + mediumspringgreen: '#00fa9a', + mediumturquoise: '#48d1cc', + mediumvioletred: '#c71585', + midnightblue: '#191970', + mintcream: '#f5fffa', + mistyrose: '#ffe4e1', + moccasin: '#ffe4b5', + navajowhite: '#ffdead', + navy: '#000080', + oldlace: '#fdf5e6', + olive: '#808000', + olivedrab: '#6b8e23', + orange: '#ffa500', + orangered: '#ff4500', + orchid: '#da70d6', + palegoldenrod: '#eee8aa', + palegreen: '#98fb98', + paleturquoise: '#afeeee', + palevioletred: '#d87093', + papayawhip: '#ffefd5', + peachpuff: '#ffdab9', + peru: '#cd853f', + pink: '#ffc0cb', + plum: '#dda0dd', + powderblue: '#b0e0e6', + purple: '#800080', + red: '#ff0000', + rosybrown: '#bc8f8f', + royalblue: '#4169e1', + saddlebrown: '#8b4513', + salmon: '#fa8072', + sandybrown: '#f4a460', + seagreen: '#2e8b57', + seashell: '#fff5ee', + sienna: '#a0522d', + silver: '#c0c0c0', + skyblue: '#87ceeb', + slateblue: '#6a5acd', + slategray: '#708090', + snow: '#fffafa', + springgreen: '#00ff7f', + steelblue: '#4682b4', + tan: '#d2b48c', + teal: '#008080', + thistle: '#d8bfd8', + tomato: '#ff6347', + turquoise: '#40e0d0', + violet: '#ee82ee', + violetred: '#d02090', + wheat: '#f5deb3', + white: '#ffffff', + whitesmoke: '#f5f5f5', + yellow: '#ffff00', + yellowgreen: '#9acd32' + }; + Color.names = defaultHTMLColorMap; + + return defaultHTMLColorMap; + }); + _registerModule(_modules, 'modules/boost/boost.js', [_modules['parts/Globals.js'], _modules['modules/boost/boost-utils.js'], _modules['modules/boost/boost-init.js'], _modules['parts/Utilities.js']], function (H, butils, init, U) { + /* * + * + * Copyright (c) 2019-2020 Highsoft AS + * + * Boost module: stripped-down renderer for higher performance + * + * License: highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var error = U.error; + // These need to be fixed when we support named imports + var hasWebGLSupport = butils.hasWebGLSupport; + if (!hasWebGLSupport()) { + if (typeof H.initCanvasBoost !== 'undefined') { + // Fallback to canvas boost + H.initCanvasBoost(); + } + else { + error(26); + } + } + else { + // WebGL support is alright, and we're good to go. + init(); + } + + }); + _registerModule(_modules, 'masters/modules/boost.src.js', [], function () { + + + /* * + * Options for the Boost module. The Boost module allows certain series types + * to be rendered by WebGL instead of the default SVG. This allows hundreds of + * thousands of data points to be rendered in milliseconds. In addition to the + * WebGL rendering it saves time by skipping processing and inspection of the + * data wherever possible. This introduces some limitations to what features are + * available in boost mode. See [the docs]( + * https://www.highcharts.com/docs/advanced-chart-features/boost-module) for + * details. + * + * In addition to the global `boost` option, each series has a + * [boostThreshold](#plotOptions.series.boostThreshold) that defines when the + * boost should kick in. + * + * Requires the `modules/boost.js` module. + * + * @sample {highstock} highcharts/boost/line-series-heavy-stock + * Stock chart + * @sample {highstock} highcharts/boost/line-series-heavy-dynamic + * Dynamic stock chart + * @sample highcharts/boost/line + * Line chart + * @sample highcharts/boost/line-series-heavy + * Line chart with hundreds of series + * @sample highcharts/boost/scatter + * Scatter chart + * @sample highcharts/boost/area + * Area chart + * @sample highcharts/boost/arearange + * Area range chart + * @sample highcharts/boost/column + * Column chart + * @sample highcharts/boost/columnrange + * Column range chart + * @sample highcharts/boost/bubble + * Bubble chart + * @sample highcharts/boost/heatmap + * Heat map + * @sample highcharts/boost/treemap + * Tree map + * + * @product highcharts highstock + * @apioption boost + * */ + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/broken-axis.js b/librerias/gantt/code/modules/broken-axis.js new file mode 100644 index 0000000..ef38acd --- /dev/null +++ b/librerias/gantt/code/modules/broken-axis.js @@ -0,0 +1,19 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2009-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(c){"object"===typeof module&&module.exports?(c["default"]=c,module.exports=c):"function"===typeof define&&define.amd?define("highcharts/modules/broken-axis",["highcharts"],function(h){c(h);c.Highcharts=h;return c}):c("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(c){function h(c,v,m,h){c.hasOwnProperty(v)||(c[v]=h.apply(null,m))}c=c?c._modules:{};h(c,"modules/broken-axis.src.js",[c["parts/Axis.js"],c["parts/Globals.js"],c["parts/Utilities.js"],c["parts/Stacking.js"]],function(c, +h,m,A){var q=m.addEvent,v=m.find,x=m.fireEvent,B=m.isArray,y=m.isNumber,r=m.pick,z=h.Series,C=function(){function l(b){this.hasBreaks=!1;this.axis=b}l.isInBreak=function(b,e){var d=b.repeat||Infinity,a=b.from,f=b.to-b.from;e=e>=a?(e-a)%d:d-(a-e)%d;return b.inclusive?e<=f:e=b)break;else a.to=b)break;else if(l.isInBreak(f,b)){d-=b-f.from;break}}return d};l.prototype.findBreakAt=function(b,e){return v(e,function(d){return d.fromp;)n-=k;for(;nb.to||g>b.from&&hb.from&&hb.from&&h>b.to&&ha&&b>=this.basePointRange&&(a=b),g=void 0;d--;)g&&!1!==g.visible||(g=e[d+1]),b=e[d],!1!==g.visible&&!1!==b.visible&&(g.x- +b.x>a&&(g=(b.x+g.x)/2,e.splice(d+1,0,{isNull:!0,x:g}),c.stacking&&this.options.stacking&&(g=c.stacking.stacks[this.stackKey][g]=new A(c,c.options.stackLabels,!1,g,this.stack),g.total=0)),g=b);return this.getGraphPath(e)};q(b,"init",function(){this.brokenAxis||(this.brokenAxis=new C(this))});q(b,"afterInit",function(){"undefined"!==typeof this.brokenAxis&&this.brokenAxis.setBreaks(this.options.breaks,!1)});q(b,"afterSetTickPositions",function(){var a=this.brokenAxis;if(a&&a.hasBreaks){var b=this.tickPositions, +e=this.tickPositions.info,d=[],c;for(c=0;c= from ? + (val - from) % repeat : + repeat - ((from - val) % repeat)); + if (!brk.inclusive) { + ret = test < length && test !== 0; + } + else { + ret = test <= length; + } + return ret; + }; + /** + * @private + */ + BrokenAxisAdditions.lin2Val = function (val) { + var axis = this; + var brokenAxis = axis.brokenAxis; + var breakArray = brokenAxis && brokenAxis.breakArray; + if (!breakArray) { + return val; + } + var nval = val, brk, i; + for (i = 0; i < breakArray.length; i++) { + brk = breakArray[i]; + if (brk.from >= nval) { + break; + } + else if (brk.to < nval) { + nval += brk.len; + } + else if (BrokenAxisAdditions.isInBreak(brk, nval)) { + nval += brk.len; + } + } + return nval; + }; + /** + * @private + */ + BrokenAxisAdditions.val2Lin = function (val) { + var axis = this; + var brokenAxis = axis.brokenAxis; + var breakArray = brokenAxis && brokenAxis.breakArray; + if (!breakArray) { + return val; + } + var nval = val, brk, i; + for (i = 0; i < breakArray.length; i++) { + brk = breakArray[i]; + if (brk.to <= val) { + nval -= brk.len; + } + else if (brk.from >= val) { + break; + } + else if (BrokenAxisAdditions.isInBreak(brk, val)) { + nval -= (val - brk.from); + break; + } + } + return nval; + }; + /* * + * + * Functions + * + * */ + /** + * Returns the first break found where the x is larger then break.from and + * smaller then break.to. + * + * @param {number} x + * The number which should be within a break. + * + * @param {Array} breaks + * The array of breaks to search within. + * + * @return {Highcharts.XAxisBreaksOptions|undefined} + * Returns the first break found that matches, returns false if no break is + * found. + */ + BrokenAxisAdditions.prototype.findBreakAt = function (x, breaks) { + return find(breaks, function (b) { + return b.from < x && x < b.to; + }); + }; + /** + * @private + */ + BrokenAxisAdditions.prototype.isInAnyBreak = function (val, testKeep) { + var brokenAxis = this; + var axis = brokenAxis.axis; + var breaks = axis.options.breaks, i = breaks && breaks.length, inbrk, keep, ret; + if (i) { + while (i--) { + if (BrokenAxisAdditions.isInBreak(breaks[i], val)) { + inbrk = true; + if (!keep) { + keep = pick(breaks[i].showPoints, !axis.isXAxis); + } + } + } + if (inbrk && testKeep) { + ret = inbrk && !keep; + } + else { + ret = inbrk; + } + } + return ret; + }; + /** + * Dynamically set or unset breaks in an axis. This function in lighter than + * usin Axis.update, and it also preserves animation. + * + * @private + * @function Highcharts.Axis#setBreaks + * + * @param {Array} [breaks] + * The breaks to add. When `undefined` it removes existing breaks. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart immediately. + * + * @return {void} + */ + BrokenAxisAdditions.prototype.setBreaks = function (breaks, redraw) { + var brokenAxis = this; + var axis = brokenAxis.axis; + var hasBreaks = (isArray(breaks) && !!breaks.length); + axis.isDirty = brokenAxis.hasBreaks !== hasBreaks; + brokenAxis.hasBreaks = hasBreaks; + axis.options.breaks = axis.userOptions.breaks = breaks; + axis.forceRedraw = true; // Force recalculation in setScale + // Recalculate series related to the axis. + axis.series.forEach(function (series) { + series.isDirty = true; + }); + if (!hasBreaks && axis.val2lin === BrokenAxisAdditions.val2Lin) { + // Revert to prototype functions + delete axis.val2lin; + delete axis.lin2val; + } + if (hasBreaks) { + axis.userOptions.ordinal = false; + axis.lin2val = BrokenAxisAdditions.lin2Val; + axis.val2lin = BrokenAxisAdditions.val2Lin; + axis.setExtremes = function (newMin, newMax, redraw, animation, eventArguments) { + // If trying to set extremes inside a break, extend min to + // after, and max to before the break ( #3857 ) + if (brokenAxis.hasBreaks) { + var axisBreak, breaks = this.options.breaks; + while ((axisBreak = brokenAxis.findBreakAt(newMin, breaks))) { + newMin = axisBreak.to; + } + while ((axisBreak = brokenAxis.findBreakAt(newMax, breaks))) { + newMax = axisBreak.from; + } + // If both min and max is within the same break. + if (newMax < newMin) { + newMax = newMin; + } + } + Axis.prototype.setExtremes.call(this, newMin, newMax, redraw, animation, eventArguments); + }; + axis.setAxisTranslation = function (saveOld) { + Axis.prototype.setAxisTranslation.call(this, saveOld); + brokenAxis.unitLength = null; + if (brokenAxis.hasBreaks) { + var breaks = axis.options.breaks || [], + // Temporary one: + breakArrayT = [], breakArray = [], length = 0, inBrk, repeat, min = axis.userMin || axis.min, max = axis.userMax || axis.max, pointRangePadding = pick(axis.pointRangePadding, 0), start, i; + // Min & max check (#4247) + breaks.forEach(function (brk) { + repeat = brk.repeat || Infinity; + if (BrokenAxisAdditions.isInBreak(brk, min)) { + min += + (brk.to % repeat) - + (min % repeat); + } + if (BrokenAxisAdditions.isInBreak(brk, max)) { + max -= + (max % repeat) - + (brk.from % repeat); + } + }); + // Construct an array holding all breaks in the axis + breaks.forEach(function (brk) { + start = brk.from; + repeat = brk.repeat || Infinity; + while (start - repeat > min) { + start -= repeat; + } + while (start < min) { + start += repeat; + } + for (i = start; i < max; i += repeat) { + breakArrayT.push({ + value: i, + move: 'in' + }); + breakArrayT.push({ + value: i + (brk.to - brk.from), + move: 'out', + size: brk.breakSize + }); + } + }); + breakArrayT.sort(function (a, b) { + return ((a.value === b.value) ? + ((a.move === 'in' ? 0 : 1) - + (b.move === 'in' ? 0 : 1)) : + a.value - b.value); + }); + // Simplify the breaks + inBrk = 0; + start = min; + breakArrayT.forEach(function (brk) { + inBrk += (brk.move === 'in' ? 1 : -1); + if (inBrk === 1 && brk.move === 'in') { + start = brk.value; + } + if (inBrk === 0) { + breakArray.push({ + from: start, + to: brk.value, + len: brk.value - start - (brk.size || 0) + }); + length += brk.value - start - (brk.size || 0); + } + }); + /** + * HC <= 8 backwards compatibility, used by demo samples. + * @deprecated + * @private + * @requires modules/broken-axis + */ + axis.breakArray = brokenAxis.breakArray = breakArray; + // Used with staticScale, and below the actual axis length, + // when breaks are substracted. + brokenAxis.unitLength = max - min - length + pointRangePadding; + fireEvent(axis, 'afterBreaks'); + if (axis.staticScale) { + axis.transA = axis.staticScale; + } + else if (brokenAxis.unitLength) { + axis.transA *= + (max - axis.min + pointRangePadding) / + brokenAxis.unitLength; + } + if (pointRangePadding) { + axis.minPixelPadding = + axis.transA * axis.minPointOffset; + } + axis.min = min; + axis.max = max; + } + }; + } + if (pick(redraw, true)) { + axis.chart.redraw(); + } + }; + return BrokenAxisAdditions; + }()); + /** + * Axis with support of broken data rows. + * @private + * @class + */ + var BrokenAxis = /** @class */ (function () { + function BrokenAxis() { + } + /** + * Adds support for broken axes. + * @private + */ + BrokenAxis.compose = function (AxisClass, SeriesClass) { + AxisClass.keepProps.push('brokenAxis'); + var seriesProto = Series.prototype; + /** + * @private + */ + seriesProto.drawBreaks = function (axis, keys) { + var series = this, points = series.points, breaks, threshold, eventName, y; + if (axis && // #5950 + axis.brokenAxis && + axis.brokenAxis.hasBreaks) { + var brokenAxis_1 = axis.brokenAxis; + keys.forEach(function (key) { + breaks = brokenAxis_1 && brokenAxis_1.breakArray || []; + threshold = axis.isXAxis ? + axis.min : + pick(series.options.threshold, axis.min); + points.forEach(function (point) { + y = pick(point['stack' + key.toUpperCase()], point[key]); + breaks.forEach(function (brk) { + if (isNumber(threshold) && isNumber(y)) { + eventName = false; + if ((threshold < brk.from && y > brk.to) || + (threshold > brk.from && y < brk.from)) { + eventName = 'pointBreak'; + } + else if ((threshold < brk.from && y > brk.from && y < brk.to) || + (threshold > brk.from && y > brk.to && y < brk.from)) { + eventName = 'pointInBreak'; + } + if (eventName) { + fireEvent(axis, eventName, { point: point, brk: brk }); + } + } + }); + }); + }); + } + }; + /** + * Extend getGraphPath by identifying gaps in the data so that we can + * draw a gap in the line or area. This was moved from ordinal axis + * module to broken axis module as of #5045. + * + * @private + * @function Highcharts.Series#gappedPath + * + * @return {Highcharts.SVGPathArray} + * Gapped path + */ + seriesProto.gappedPath = function () { + var currentDataGrouping = this.currentDataGrouping, groupingSize = currentDataGrouping && currentDataGrouping.gapSize, gapSize = this.options.gapSize, points = this.points.slice(), i = points.length - 1, yAxis = this.yAxis, stack; + /** + * Defines when to display a gap in the graph, together with the + * [gapUnit](plotOptions.series.gapUnit) option. + * + * In case when `dataGrouping` is enabled, points can be grouped + * into a larger time span. This can make the grouped points to have + * a greater distance than the absolute value of `gapSize` property, + * which will result in disappearing graph completely. To prevent + * this situation the mentioned distance between grouped points is + * used instead of previously defined `gapSize`. + * + * In practice, this option is most often used to visualize gaps in + * time series. In a stock chart, intraday data is available for + * daytime hours, while gaps will appear in nights and weekends. + * + * @see [gapUnit](plotOptions.series.gapUnit) + * @see [xAxis.breaks](#xAxis.breaks) + * + * @sample {highstock} stock/plotoptions/series-gapsize/ + * Setting the gap size to 2 introduces gaps for weekends + * in daily datasets. + * + * @type {number} + * @default 0 + * @product highstock + * @requires modules/broken-axis + * @apioption plotOptions.series.gapSize + */ + /** + * Together with [gapSize](plotOptions.series.gapSize), this option + * defines where to draw gaps in the graph. + * + * When the `gapUnit` is `"relative"` (default), a gap size of 5 + * means that if the distance between two points is greater than + * 5 times that of the two closest points, the graph will be broken. + * + * When the `gapUnit` is `"value"`, the gap is based on absolute + * axis values, which on a datetime axis is milliseconds. This also + * applies to the navigator series that inherits gap options from + * the base series. + * + * @see [gapSize](plotOptions.series.gapSize) + * + * @type {string} + * @default relative + * @since 5.0.13 + * @product highstock + * @validvalue ["relative", "value"] + * @requires modules/broken-axis + * @apioption plotOptions.series.gapUnit + */ + if (gapSize && i > 0) { // #5008 + // Gap unit is relative + if (this.options.gapUnit !== 'value') { + gapSize *= this.basePointRange; + } + // Setting a new gapSize in case dataGrouping is enabled (#7686) + if (groupingSize && + groupingSize > gapSize && + // Except when DG is forced (e.g. from other series) + // and has lower granularity than actual points (#11351) + groupingSize >= this.basePointRange) { + gapSize = groupingSize; + } + // extension for ordinal breaks + var current = void 0, next = void 0; + while (i--) { + // Reassign next if it is not visible + if (!(next && next.visible !== false)) { + next = points[i + 1]; + } + current = points[i]; + // Skip iteration if one of the points is not visible + if (next.visible === false || current.visible === false) { + continue; + } + if (next.x - current.x > gapSize) { + var xRange = (current.x + next.x) / 2; + points.splice(// insert after this one + i + 1, 0, { + isNull: true, + x: xRange + }); + // For stacked chart generate empty stack items, #6546 + if (yAxis.stacking && this.options.stacking) { + stack = yAxis.stacking.stacks[this.stackKey][xRange] = + new StackItem(yAxis, yAxis.options + .stackLabels, false, xRange, this.stack); + stack.total = 0; + } + } + // Assign current to next for the upcoming iteration + next = current; + } + } + // Call base method + return this.getGraphPath(points); + }; + /* eslint-disable no-invalid-this */ + addEvent(AxisClass, 'init', function () { + var axis = this; + if (!axis.brokenAxis) { + axis.brokenAxis = new BrokenAxisAdditions(axis); + } + }); + addEvent(AxisClass, 'afterInit', function () { + if (typeof this.brokenAxis !== 'undefined') { + this.brokenAxis.setBreaks(this.options.breaks, false); + } + }); + addEvent(AxisClass, 'afterSetTickPositions', function () { + var axis = this; + var brokenAxis = axis.brokenAxis; + if (brokenAxis && + brokenAxis.hasBreaks) { + var tickPositions = this.tickPositions, info = this.tickPositions.info, newPositions = [], i; + for (i = 0; i < tickPositions.length; i++) { + if (!brokenAxis.isInAnyBreak(tickPositions[i])) { + newPositions.push(tickPositions[i]); + } + } + this.tickPositions = newPositions; + this.tickPositions.info = info; + } + }); + // Force Axis to be not-ordinal when breaks are defined + addEvent(AxisClass, 'afterSetOptions', function () { + if (this.brokenAxis && this.brokenAxis.hasBreaks) { + this.options.ordinal = false; + } + }); + addEvent(SeriesClass, 'afterGeneratePoints', function () { + var _a = this, isDirty = _a.isDirty, connectNulls = _a.options.connectNulls, points = _a.points, xAxis = _a.xAxis, yAxis = _a.yAxis; + // Set, or reset visibility of the points. Axis.setBreaks marks the + // series as isDirty + if (isDirty) { + var i = points.length; + while (i--) { + var point = points[i]; + // Respect nulls inside the break (#4275) + var nullGap = point.y === null && connectNulls === false; + var isPointInBreak = (!nullGap && ((xAxis && + xAxis.brokenAxis && + xAxis.brokenAxis.isInAnyBreak(point.x, true)) || (yAxis && + yAxis.brokenAxis && + yAxis.brokenAxis.isInAnyBreak(point.y, true)))); + // Set point.visible if in any break. + // If not in break, reset visible to original value. + point.visible = isPointInBreak ? + false : + point.options.visible !== false; + } + } + }); + addEvent(SeriesClass, 'afterRender', function drawPointsWrapped() { + this.drawBreaks(this.xAxis, ['x']); + this.drawBreaks(this.yAxis, pick(this.pointArrayMap, ['y'])); + }); + }; + return BrokenAxis; + }()); + BrokenAxis.compose(Axis, Series); // @todo remove automatism + + return BrokenAxis; + }); + _registerModule(_modules, 'masters/modules/broken-axis.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/bullet.js b/librerias/gantt/code/modules/bullet.js new file mode 100644 index 0000000..88470ab --- /dev/null +++ b/librerias/gantt/code/modules/bullet.js @@ -0,0 +1,15 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Bullet graph series type for Highcharts + + (c) 2010-2019 Kacper Madej + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/bullet",["highcharts"],function(d){a(d);a.Highcharts=d;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function d(a,b,n,d){a.hasOwnProperty(b)||(a[b]=d.apply(null,n))}a=a?a._modules:{};d(a,"modules/bullet.src.js",[a["parts/Globals.js"],a["parts/Utilities.js"]],function(a,b){var d=b.isNumber,r=b.merge,k=b.pick,t=b.relativeLength; +b=b.seriesType;var f=a.seriesTypes.column.prototype;b("bullet","column",{targetOptions:{width:"140%",height:3,borderWidth:0},tooltip:{pointFormat:'\u25cf {series.name}: {point.y}. Target: {point.target}
    '}},{pointArrayMap:["y","target"],parallelArrays:["x","y","target"],drawPoints:function(){var a=this,l=a.chart,b=a.options,n=b.animationLimit||250;f.drawPoints.apply(this);a.points.forEach(function(c){var p=c.options,e=c.targetGraphic,f=c.target, +m=c.y;if(d(f)&&null!==f){var g=r(b.targetOptions,p.targetOptions);var u=g.height;var h=c.shapeArgs;var q=t(g.width,h.width);var v=a.yAxis.translate(f,!1,!0,!1,!0)-g.height/2-.5;h=a.crispCol.apply({chart:l,borderWidth:g.borderWidth,options:{crisp:b.crisp}},[h.x+h.width/2-q/2,v,q,u]);e?(e[l.pointCount\u25CF' + + ' {series.name}: {point.y}. Target: {point.target}' + + '
    ' + } + }, { + pointArrayMap: ['y', 'target'], + parallelArrays: ['x', 'y', 'target'], + /* eslint-disable valid-jsdoc */ + /** + * Draws the targets. For inverted chart, the `series.group` is rotated, + * so the same coordinates apply. This method is based on column series + * drawPoints function. + * + * @ignore + * @function Highcharts.Series#drawPoints + */ + drawPoints: function () { + var series = this, chart = series.chart, options = series.options, animationLimit = options.animationLimit || 250; + columnProto.drawPoints.apply(this); + series.points.forEach(function (point) { + var pointOptions = point.options, shapeArgs, targetGraphic = point.targetGraphic, targetShapeArgs, targetVal = point.target, pointVal = point.y, width, height, targetOptions, y; + if (isNumber(targetVal) && targetVal !== null) { + targetOptions = merge(options.targetOptions, pointOptions.targetOptions); + height = targetOptions.height; + shapeArgs = point.shapeArgs; + width = relativeLength(targetOptions.width, shapeArgs.width); + y = series.yAxis.translate(targetVal, false, true, false, true) - targetOptions.height / 2 - 0.5; + targetShapeArgs = series.crispCol.apply({ + // Use fake series object to set borderWidth of target + chart: chart, + borderWidth: targetOptions.borderWidth, + options: { + crisp: options.crisp + } + }, [ + (shapeArgs.x + + shapeArgs.width / 2 - width / 2), + y, + width, + height + ]); + if (targetGraphic) { + // Update + targetGraphic[chart.pointCount < animationLimit ? + 'animate' : + 'attr'](targetShapeArgs); + // Add or remove tooltip reference + if (isNumber(pointVal) && pointVal !== null) { + targetGraphic.element.point = point; + } + else { + targetGraphic.element.point = void 0; + } + } + else { + point.targetGraphic = targetGraphic = chart.renderer + .rect() + .attr(targetShapeArgs) + .add(series.group); + } + // Presentational + if (!chart.styledMode) { + targetGraphic.attr({ + fill: pick(targetOptions.color, pointOptions.color, (series.zones.length && (point.getZone.call({ + series: series, + x: point.x, + y: targetVal, + options: {} + }).color || series.color)) || void 0, point.color, series.color), + stroke: pick(targetOptions.borderColor, point.borderColor, series.options.borderColor), + 'stroke-width': targetOptions.borderWidth + }); + } + // Add tooltip reference + if (isNumber(pointVal) && pointVal !== null) { + targetGraphic.element.point = point; + } + targetGraphic.addClass(point.getClassName() + + ' highcharts-bullet-target', true); + } + else if (targetGraphic) { + // #1269: + point.targetGraphic = targetGraphic.destroy(); + } + }); + }, + /** + * Includes target values to extend extremes from y values. + * + * @ignore + * @function Highcharts.Series#getExtremes + */ + getExtremes: function (yData) { + var series = this, targetData = series.targetData, yMax, yMin; + var dataExtremes = columnProto.getExtremes.call(this, yData); + if (targetData && targetData.length) { + var targetExtremes = columnProto.getExtremes.call(this, targetData); + if (isNumber(targetExtremes.dataMin)) { + dataExtremes.dataMin = Math.min(pick(dataExtremes.dataMin, Infinity), targetExtremes.dataMin); + } + if (isNumber(targetExtremes.dataMax)) { + dataExtremes.dataMax = Math.max(pick(dataExtremes.dataMax, -Infinity), targetExtremes.dataMax); + } + } + return dataExtremes; + } + /* eslint-enable valid-jsdoc */ + }, + /** @lends Highcharts.seriesTypes.ohlc.prototype.pointClass.prototype */ + { + // eslint-disable-next-line valid-jsdoc + /** + * Destroys target graphic. + * + * @private + * @function + */ + destroy: function () { + if (this.targetGraphic) { + this.targetGraphic = this.targetGraphic.destroy(); + } + columnProto.pointClass.prototype.destroy + .apply(this, arguments); + return; + } + }); + /** + * A `bullet` series. If the [type](#series.bullet.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.bullet + * @since 6.0.0 + * @product highcharts + * @excluding dataParser, dataURL, marker, dataSorting + * @requires modules/bullet + * @apioption series.bullet + */ + /** + * An array of data points for the series. For the `bullet` series type, + * points can be given in the following ways: + * + * 1. An array of arrays with 3 or 2 values. In this case, the values correspond + * to `x,y,target`. If the first value is a string, it is applied as the name + * of the point, and the `x` value is inferred. The `x` value can also be + * omitted, in which case the inner arrays should be of length 2\. Then the + * `x` value is automatically calculated, either starting at 0 and + * incremented by 1, or from `pointStart` and `pointInterval` given in the + * series options. + * ```js + * data: [ + * [0, 40, 75], + * [1, 50, 50], + * [2, 60, 40] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.bullet.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 0, + * y: 40, + * target: 75, + * name: "Point1", + * color: "#00FF00" + * }, { + * x: 1, + * y: 60, + * target: 40, + * name: "Point2", + * color: "#FF00FF" + * }] + * ``` + * + * @type {Array|Array<(number|string),number,number>|*>} + * @extends series.column.data + * @since 6.0.0 + * @product highcharts + * @apioption series.bullet.data + */ + /** + * The target value of a point. + * + * @type {number} + * @since 6.0.0 + * @product highcharts + * @apioption series.bullet.data.target + */ + /** + * Individual target options for each point. + * + * @extends plotOptions.bullet.targetOptions + * @product highcharts + * @apioption series.bullet.data.targetOptions + */ + /** + * @product highcharts + * @excluding halo, lineWidth, lineWidthPlus, marker + * @apioption series.bullet.states.hover + */ + /** + * @product highcharts + * @excluding halo, lineWidth, lineWidthPlus, marker + * @apioption series.bullet.states.select + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'masters/modules/bullet.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/coloraxis.js b/librerias/gantt/code/modules/coloraxis.js new file mode 100644 index 0000000..43d4361 --- /dev/null +++ b/librerias/gantt/code/modules/coloraxis.js @@ -0,0 +1,30 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + ColorAxis module + + (c) 2012-2019 Pawel Potaczek + + License: www.highcharts.com/license +*/ +(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/color-axis",["highcharts"],function(n){b(n);b.Highcharts=n;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function n(b,g,l,q){b.hasOwnProperty(g)||(b[g]=q.apply(null,l))}b=b?b._modules:{};n(b,"parts-map/ColorSeriesMixin.js",[b["parts/Globals.js"]],function(b){b.colorPointMixin={setVisible:function(b){var l=this,g=b? +"show":"hide";l.visible=l.options.visible=!!b;["graphic","dataLabel"].forEach(function(b){if(l[b])l[b][g]()})}};b.colorSeriesMixin={optionalAxis:"colorAxis",colorAxis:0,translateColors:function(){var b=this,l=this.options.nullColor,q=this.colorAxis,n=this.colorKey;(this.data.length?this.data:this.points).forEach(function(g){var k=g.getNestedProperty(n);if(k=g.options.color||(g.isNull||null===g.value?l:q&&"undefined"!==typeof k?q.toColor(k,g):g.color||b.color))g.color=k})}}});n(b,"parts-map/ColorAxis.js", +[b["parts/Axis.js"],b["parts/Color.js"],b["parts/Globals.js"],b["parts/Legend.js"],b["mixins/legend-symbol.js"],b["parts/Point.js"],b["parts/Utilities.js"]],function(b,g,l,n,z,A,k){var q=this&&this.__extends||function(){var b=function(d,a){b=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(a,f){a.__proto__=f}||function(a,f){for(var c in f)f.hasOwnProperty(c)&&(a[c]=f[c])};return b(d,a)};return function(d,a){function c(){this.constructor=d}b(d,a);d.prototype=null===a?Object.create(a): +(c.prototype=a.prototype,new c)}}(),t=g.parse;g=k.addEvent;var y=k.erase,w=k.extend,B=k.Fx,C=k.isNumber,x=k.merge,r=k.pick,D=k.splat;"";k=l.Chart;var u=l.Series,E=l.colorPointMixin,F=l.noop;w(u.prototype,l.colorSeriesMixin);w(A.prototype,E);k.prototype.collectionsWithUpdate.push("colorAxis");k.prototype.collectionsWithInit.colorAxis=[k.prototype.addColorAxis];var v=function(b){function d(a,c){var f=b.call(this,a,c)||this;f.beforePadding=!1;f.chart=void 0;f.coll="colorAxis";f.dataClasses=void 0;f.legendItem= +void 0;f.legendItems=void 0;f.name="";f.options=void 0;f.stops=void 0;f.visible=!0;f.init(a,c);return f}q(d,b);d.buildOptions=function(a,c,f){a=a.options.legend||{};var e=f.layout?"vertical"!==f.layout:"vertical"!==a.layout;return x(c,{side:e?2:1,reversed:!e},f,{opposite:!e,showEmpty:!1,title:null,visible:a.enabled&&(f?!1!==f.visible:!0)})};d.prototype.init=function(a,c){var f=d.buildOptions(a,d.defaultOptions,c);this.coll="colorAxis";b.prototype.init.call(this,a,f);c.dataClasses&&this.initDataClasses(c); +this.initStops();this.horiz=!f.opposite;this.zoomEnabled=!1};d.prototype.initDataClasses=function(a){var c=this.chart,f,e=0,b=c.options.chart.colorCount,d=this.options,h=a.dataClasses.length;this.dataClasses=f=[];this.legendItems=[];a.dataClasses.forEach(function(a,p){a=x(a);f.push(a);if(c.styledMode||!a.color)"category"===d.dataClassColor?(c.styledMode||(p=c.options.colors,b=p.length,a.color=p[e]),a.colorIndex=e,e++,e===b&&(e=0)):a.color=t(d.minColor).tweenTo(t(d.maxColor),2>h?.5:p/(h-1))})};d.prototype.hasData= +function(){return!!(this.tickPositions||[]).length};d.prototype.setTickPositions=function(){if(!this.dataClasses)return b.prototype.setTickPositions.call(this)};d.prototype.initStops=function(){this.stops=this.options.stops||[[0,this.options.minColor],[1,this.options.maxColor]];this.stops.forEach(function(a){a.color=t(a[1])})};d.prototype.setOptions=function(a){b.prototype.setOptions.call(this,a);this.options.crosshair=this.options.marker};d.prototype.setAxisSize=function(){var a=this.legendSymbol, +c=this.chart,f=c.options.legend||{},e,b;a?(this.left=f=a.attr("x"),this.top=e=a.attr("y"),this.width=b=a.attr("width"),this.height=a=a.attr("height"),this.right=c.chartWidth-f-b,this.bottom=c.chartHeight-e-a,this.len=this.horiz?b:a,this.pos=this.horiz?f:e):this.len=(this.horiz?f.symbolWidth:f.symbolHeight)||d.defaultLegendLength};d.prototype.normalizedValue=function(a){this.logarithmic&&(a=this.logarithmic.log2lin(a));return 1-(this.max-a)/(this.max-this.min||1)};d.prototype.toColor=function(a,c){var f= +this.dataClasses,e=this.stops,b;if(f)for(b=f.length;b--;){var d=f[b];var h=d.from;e=d.to;if(("undefined"===typeof h||a>=h)&&("undefined"===typeof e||a<=e)){var g=d.color;c&&(c.dataClass=b,c.colorIndex=d.colorIndex);break}}else{a=this.normalizedValue(a);for(b=e.length;b--&&!(a>e[b][0]););h=e[b]||e[b+1];e=e[b+1]||h;a=1-(e[0]-a)/(e[0]-h[0]||1);g=h.color.tweenTo(e.color,a)}return g};d.prototype.getOffset=function(){var a=this.legendGroup,c=this.chart.axisOffset[this.side];a&&(this.axisParent=a,b.prototype.getOffset.call(this), +this.added||(this.added=!0,this.labelLeft=0,this.labelRight=this.width),this.chart.axisOffset[this.side]=c)};d.prototype.setLegendColor=function(){var a=this.reversed,c=a?1:0;a=a?0:1;c=this.horiz?[c,0,a,0]:[0,a,0,c];this.legendColor={linearGradient:{x1:c[0],y1:c[1],x2:c[2],y2:c[3]},stops:this.stops}};d.prototype.drawLegendSymbol=function(a,c){var b=a.padding,e=a.options,p=this.horiz,g=r(e.symbolWidth,p?d.defaultLegendLength:12),h=r(e.symbolHeight,p?12:d.defaultLegendLength),m=r(e.labelPadding,p?16: +30);e=r(e.itemDistance,10);this.setLegendColor();c.legendSymbol=this.chart.renderer.rect(0,a.baseline-11,g,h).attr({zIndex:1}).add(c.legendGroup);this.legendItemWidth=g+b+(p?e:m);this.legendItemHeight=h+b+(p?m:0)};d.prototype.setState=function(a){this.series.forEach(function(c){c.setState(a)})};d.prototype.setVisible=function(){};d.prototype.getSeriesExtremes=function(){var a=this.series,c=a.length,b;this.dataMin=Infinity;for(this.dataMax=-Infinity;c--;){var e=a[c];var d=e.colorKey=r(e.options.colorKey, +e.colorKey,e.pointValKey,e.zoneAxis,"y");var g=e.pointArrayMap;var h=e[d+"Min"]&&e[d+"Max"];if(e[d+"Data"])var m=e[d+"Data"];else if(g){m=[];g=g.indexOf(d);var k=e.yData;if(0<=g&&k)for(b=0;bg+m&&(h=g+m+2);c.plotX=h;c.plotY=this.len-h;b.prototype.drawCrosshair.call(this,a,c);c.plotX=d;c.plotY=e;this.cross&&!this.cross.addedToColorAxis&&this.legendGroup&&(this.cross.addClass("highcharts-coloraxis-marker").add(this.legendGroup),this.cross.addedToColorAxis=!0,!this.chart.styledMode&& +this.crosshair&&this.cross.attr({fill:this.crosshair.color}))}};d.prototype.getPlotLinePath=function(a){var c=a.translatedValue;return C(c)?this.horiz?[["M",c-4,this.top-6],["L",c+4,this.top-6],["L",c,this.top],["Z"]]:[["M",this.left,c],["L",this.left-6,c+6],["L",this.left-6,c-6],["Z"]]:b.prototype.getPlotLinePath.call(this,a)};d.prototype.update=function(a,c){var f=this.chart,e=f.legend,g=d.buildOptions(f,{},a);this.series.forEach(function(a){a.isDirtyData=!0});(a.dataClasses&&e.allItems||this.dataClasses)&& +this.destroyItems();f.options[this.coll]=x(this.userOptions,g);b.prototype.update.call(this,g,c);this.legendItem&&(this.setLegendColor(),e.colorizeItem(this,!0))};d.prototype.destroyItems=function(){var a=this.chart;this.legendItem?a.legend.destroyItem(this):this.legendItems&&this.legendItems.forEach(function(c){a.legend.destroyItem(c)});a.isDirtyLegend=!0};d.prototype.remove=function(a){this.destroyItems();b.prototype.remove.call(this,a)};d.prototype.getDataClassLegendSymbols=function(){var a=this, +c=a.chart,b=a.legendItems,d=c.options.legend,g=d.valueDecimals,m=d.valueSuffix||"",h;b.length||a.dataClasses.forEach(function(d,e){var f=!0,k=d.from,l=d.to,n=c.numberFormatter;h="";"undefined"===typeof k?h="< ":"undefined"===typeof l&&(h="> ");"undefined"!==typeof k&&(h+=n(k,g)+m);"undefined"!==typeof k&&"undefined"!==typeof l&&(h+=" - ");"undefined"!==typeof l&&(h+=n(l,g)+m);b.push(w({chart:c,name:h,options:{},drawLegendSymbol:z.drawRectangle,visible:!0,setState:F,isDataClass:!0,setVisible:function(){f= +a.visible=!f;a.series.forEach(function(a){a.points.forEach(function(a){a.dataClass===e&&a.setVisible(f)})});c.legend.colorizeItem(this,f)}},d))});return b};d.defaultLegendLength=200;d.defaultOptions={lineWidth:0,minPadding:0,maxPadding:0,gridLineWidth:1,tickPixelInterval:72,startOnTick:!0,endOnTick:!0,offset:0,marker:{animation:{duration:50},width:.01,color:"#999999"},labels:{overflow:"justify",rotation:0},minColor:"#e6ebf5",maxColor:"#003399",tickLength:5,showInLegend:!0};d.keepProps=["legendGroup", +"legendItemHeight","legendItemWidth","legendItem","legendSymbol"];return d}(b);Array.prototype.push.apply(b.keepProps,v.keepProps);l.ColorAxis=v;["fill","stroke"].forEach(function(b){B.prototype[b+"Setter"]=function(){this.elem.attr(b,t(this.start).tweenTo(t(this.end),this.pos),null,!0)}});g(k,"afterGetAxes",function(){var b=this,d=b.options;this.colorAxis=[];d.colorAxis&&(d.colorAxis=D(d.colorAxis),d.colorAxis.forEach(function(a,c){a.index=c;new v(b,a)}))});g(u,"bindAxes",function(){var b=this.axisTypes; +b?-1===b.indexOf("colorAxis")&&b.push("colorAxis"):this.axisTypes=["colorAxis"]});g(n,"afterGetAllItems",function(b){var d=[],a,c;(this.chart.colorAxis||[]).forEach(function(c){(a=c.options)&&a.showInLegend&&(a.dataClasses&&a.visible?d=d.concat(c.getDataClassLegendSymbols()):a.visible&&d.push(c),c.series.forEach(function(c){if(!c.options.showInLegend||a.dataClasses)"point"===c.options.legendType?c.points.forEach(function(a){y(b.allItems,a)}):y(b.allItems,c)}))});for(c=d.length;c--;)b.allItems.unshift(d[c])}); +g(n,"afterColorizeItem",function(b){b.visible&&b.item.legendColor&&b.item.legendSymbol.attr({fill:b.item.legendColor})});g(n,"afterUpdate",function(){var b=this.chart.colorAxis;b&&b.forEach(function(b,a,c){b.update({},c)})});g(u,"afterTranslate",function(){(this.chart.colorAxis&&this.chart.colorAxis.length||this.colorAttribs)&&this.translateColors()});return v});n(b,"masters/modules/coloraxis.src.js",[],function(){})}); +//# sourceMappingURL=coloraxis.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/coloraxis.js.map b/librerias/gantt/code/modules/coloraxis.js.map new file mode 100644 index 0000000..d978497 --- /dev/null +++ b/librerias/gantt/code/modules/coloraxis.js.map @@ -0,0 +1 @@ +{"version":3,"file":"coloraxis.js.map","lineCount":29,"mappings":"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","sources":["coloraxis.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","colorPointMixin","setVisible","vis","point","method","visible","options","forEach","key","colorSeriesMixin","optionalAxis","colorAxis","translateColors","series","nullColor","colorKey","data","length","points","value","getNestedProperty","color","isNull","toColor","Axis","Color","Legend","LegendSymbolMixin","Point","U","__extends","extendStatics","d","b","Object","setPrototypeOf","__proto__","Array","p","__","constructor","prototype","create","parse","addEvent","erase","extend","Fx","isNumber","merge","pick","splat","Chart","Series","noop","collectionsWithUpdate","push","collectionsWithInit","addColorAxis","ColorAxis","_super","chart","userOptions","_this","call","beforePadding","coll","dataClasses","legendItem","legendItems","name","stops","init","buildOptions","ColorAxis.buildOptions","legend","horiz","layout","side","reversed","opposite","showEmpty","title","enabled","ColorAxis.prototype.init","defaultOptions","axis","initDataClasses","initStops","zoomEnabled","ColorAxis.prototype.initDataClasses","colorCounter","colorCount","len","dataClass","i","styledMode","dataClassColor","colors","colorIndex","minColor","tweenTo","maxColor","hasData","ColorAxis.prototype.hasData","tickPositions","setTickPositions","ColorAxis.prototype.setTickPositions","ColorAxis.prototype.initStops","stop","setOptions","ColorAxis.prototype.setOptions","crosshair","marker","setAxisSize","ColorAxis.prototype.setAxisSize","symbol","legendSymbol","legendOptions","y","width","left","x","attr","top","height","right","chartWidth","bottom","chartHeight","pos","symbolWidth","symbolHeight","defaultLegendLength","normalizedValue","ColorAxis.prototype.normalizedValue","logarithmic","log2lin","max","min","ColorAxis.prototype.toColor","from","to","getOffset","ColorAxis.prototype.getOffset","group","legendGroup","sideOffset","axisOffset","axisParent","added","labelLeft","labelRight","setLegendColor","ColorAxis.prototype.setLegendColor","one","zero","grad","legendColor","linearGradient","x1","y1","x2","y2","drawLegendSymbol","ColorAxis.prototype.drawLegendSymbol","item","padding","labelPadding","itemDistance","renderer","rect","baseline","zIndex","add","legendItemWidth","legendItemHeight","setState","ColorAxis.prototype.setState","state","ColorAxis.prototype.setVisible","getSeriesExtremes","ColorAxis.prototype.getSeriesExtremes","j","dataMin","Infinity","dataMax","cSeries","pointValKey","zoneAxis","pointArrayMap","calculatedExtremes","colorValArray","colorValIndex","indexOf","yData","minColorValue","maxColorValue","cExtremes","getExtremes","Math","applyExtremes","drawCrosshair","ColorAxis.prototype.drawCrosshair","e","plotX","plotY","axisPos","axisLen","crossPos","toPixels","cross","addedToColorAxis","addClass","fill","getPlotLinePath","ColorAxis.prototype.getPlotLinePath","translatedValue","update","ColorAxis.prototype.update","newOptions","redraw","updatedOptions","isDirtyData","allItems","destroyItems","colorizeItem","ColorAxis.prototype.destroyItems","destroyItem","isDirtyLegend","remove","ColorAxis.prototype.remove","getDataClassLegendSymbols","ColorAxis.prototype.getDataClassLegendSymbols","valueDecimals","valueSuffix","numberFormatter","drawRectangle","isDataClass","lineWidth","minPadding","maxPadding","gridLineWidth","tickPixelInterval","startOnTick","endOnTick","offset","animation","duration","labels","overflow","rotation","tickLength","showInLegend","keepProps","prop","elem","start","end","axisOptions","index","axisTypes","colorAxisItems","concat","legendType","unshift","colorAxes","colorAttribs"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/coloraxis.src.js b/librerias/gantt/code/modules/coloraxis.src.js new file mode 100644 index 0000000..20d89fa --- /dev/null +++ b/librerias/gantt/code/modules/coloraxis.src.js @@ -0,0 +1,1268 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * ColorAxis module + * + * (c) 2012-2019 Pawel Potaczek + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/color-axis', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'parts-map/ColorSeriesMixin.js', [_modules['parts/Globals.js']], function (H) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Mixin for maps and heatmaps + * + * @private + * @mixin Highcharts.colorPointMixin + */ + H.colorPointMixin = { + /* eslint-disable valid-jsdoc */ + /** + * Set the visibility of a single point + * @private + * @function Highcharts.colorPointMixin.setVisible + * @param {boolean} visible + * @return {void} + */ + setVisible: function (vis) { + var point = this, method = vis ? 'show' : 'hide'; + point.visible = point.options.visible = Boolean(vis); + // Show and hide associated elements + ['graphic', 'dataLabel'].forEach(function (key) { + if (point[key]) { + point[key][method](); + } + }); + } + /* eslint-enable valid-jsdoc */ + }; + /** + * @private + * @mixin Highcharts.colorSeriesMixin + */ + H.colorSeriesMixin = { + optionalAxis: 'colorAxis', + colorAxis: 0, + /* eslint-disable valid-jsdoc */ + /** + * In choropleth maps, the color is a result of the value, so this needs + * translation too + * @private + * @function Highcharts.colorSeriesMixin.translateColors + * @return {void} + */ + translateColors: function () { + var series = this, points = this.data.length ? this.data : this.points, nullColor = this.options.nullColor, colorAxis = this.colorAxis, colorKey = this.colorKey; + points.forEach(function (point) { + var value = point.getNestedProperty(colorKey), color; + color = point.options.color || + (point.isNull || point.value === null ? + nullColor : + (colorAxis && typeof value !== 'undefined') ? + colorAxis.toColor(value, point) : + point.color || series.color); + if (color) { + point.color = color; + } + }); + } + /* eslint-enable valid-jsdoc */ + }; + + }); + _registerModule(_modules, 'parts-map/ColorAxis.js', [_modules['parts/Axis.js'], _modules['parts/Color.js'], _modules['parts/Globals.js'], _modules['parts/Legend.js'], _modules['mixins/legend-symbol.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js']], function (Axis, Color, H, Legend, LegendSymbolMixin, Point, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; + })(); + var color = Color.parse; + var addEvent = U.addEvent, erase = U.erase, extend = U.extend, Fx = U.Fx, isNumber = U.isNumber, merge = U.merge, pick = U.pick, splat = U.splat; + /** + * Color axis types + * + * @typedef {"linear"|"logarithmic"} Highcharts.ColorAxisTypeValue + */ + ''; // detach doclet above + var Chart = H.Chart, Series = H.Series, colorPointMixin = H.colorPointMixin, colorSeriesMixin = H.colorSeriesMixin, noop = H.noop; + extend(Series.prototype, colorSeriesMixin); + extend(Point.prototype, colorPointMixin); + Chart.prototype.collectionsWithUpdate.push('colorAxis'); + Chart.prototype.collectionsWithInit.colorAxis = [Chart.prototype.addColorAxis]; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The ColorAxis object for inclusion in gradient legends. + * + * @class + * @name Highcharts.ColorAxis + * @augments Highcharts.Axis + * + * @param {Highcharts.Chart} chart + * The related chart of the color axis. + * + * @param {Highcharts.ColorAxisOptions} userOptions + * The color axis options for initialization. + */ + var ColorAxis = /** @class */ (function (_super) { + __extends(ColorAxis, _super); + /* * + * + * Constructors + * + * */ + /** + * @private + */ + function ColorAxis(chart, userOptions) { + var _this = _super.call(this, chart, userOptions) || this; + _this.beforePadding = false; // Prevents unnecessary padding with `hc-more` + _this.chart = void 0; + _this.coll = 'colorAxis'; + _this.dataClasses = void 0; + _this.legendItem = void 0; + _this.legendItems = void 0; + _this.name = ''; // Prevents 'undefined' in legend in IE8 + _this.options = void 0; + _this.stops = void 0; + _this.visible = true; + _this.init(chart, userOptions); + return _this; + } + /* * + * + * Static Functions + * + * */ + /** + * Build options to keep layout params on init and update. + * @private + */ + ColorAxis.buildOptions = function (chart, options, userOptions) { + var legend = chart.options.legend || {}, horiz = userOptions.layout ? + userOptions.layout !== 'vertical' : + legend.layout !== 'vertical'; + return merge(options, { + side: horiz ? 2 : 1, + reversed: !horiz + }, userOptions, { + opposite: !horiz, + showEmpty: false, + title: null, + visible: legend.enabled && + (userOptions ? userOptions.visible !== false : true) + }); + }; + /* * + * + * Functions + * + * */ + /** + * Initializes the color axis. + * + * @function Highcharts.ColorAxis#init + * + * @param {Highcharts.Chart} chart + * The related chart of the color axis. + * + * @param {Highcharts.ColorAxisOptions} userOptions + * The color axis options for initialization. + */ + ColorAxis.prototype.init = function (chart, userOptions) { + var axis = this; + var options = ColorAxis.buildOptions(// Build the options + chart, ColorAxis.defaultOptions, userOptions); + axis.coll = 'colorAxis'; + _super.prototype.init.call(this, chart, options); + // Base init() pushes it to the xAxis array, now pop it again + // chart[this.isXAxis ? 'xAxis' : 'yAxis'].pop(); + // Prepare data classes + if (userOptions.dataClasses) { + axis.initDataClasses(userOptions); + } + axis.initStops(); + // Override original axis properties + axis.horiz = !options.opposite; + axis.zoomEnabled = false; + }; + /** + * @private + */ + ColorAxis.prototype.initDataClasses = function (userOptions) { + var axis = this; + var chart = axis.chart, dataClasses, colorCounter = 0, colorCount = chart.options.chart.colorCount, options = axis.options, len = userOptions.dataClasses.length; + axis.dataClasses = dataClasses = []; + axis.legendItems = []; + userOptions.dataClasses.forEach(function (dataClass, i) { + var colors; + dataClass = merge(dataClass); + dataClasses.push(dataClass); + if (!chart.styledMode && dataClass.color) { + return; + } + if (options.dataClassColor === 'category') { + if (!chart.styledMode) { + colors = chart.options.colors; + colorCount = colors.length; + dataClass.color = colors[colorCounter]; + } + dataClass.colorIndex = colorCounter; + // increase and loop back to zero + colorCounter++; + if (colorCounter === colorCount) { + colorCounter = 0; + } + } + else { + dataClass.color = color(options.minColor).tweenTo(color(options.maxColor), len < 2 ? 0.5 : i / (len - 1) // #3219 + ); + } + }); + }; + /** + * Returns true if the series has points at all. + * + * @function Highcharts.ColorAxis#hasData + * + * @return {boolean} + * True, if the series has points, otherwise false. + */ + ColorAxis.prototype.hasData = function () { + return !!(this.tickPositions || []).length; + }; + /** + * Override so that ticks are not added in data class axes (#6914) + * @private + */ + ColorAxis.prototype.setTickPositions = function () { + if (!this.dataClasses) { + return _super.prototype.setTickPositions.call(this); + } + }; + /** + * @private + */ + ColorAxis.prototype.initStops = function () { + var axis = this; + axis.stops = axis.options.stops || [ + [0, axis.options.minColor], + [1, axis.options.maxColor] + ]; + axis.stops.forEach(function (stop) { + stop.color = color(stop[1]); + }); + }; + /** + * Extend the setOptions method to process extreme colors and color stops. + * @private + */ + ColorAxis.prototype.setOptions = function (userOptions) { + var axis = this; + _super.prototype.setOptions.call(this, userOptions); + axis.options.crosshair = axis.options.marker; + }; + /** + * @private + */ + ColorAxis.prototype.setAxisSize = function () { + var axis = this; + var symbol = axis.legendSymbol; + var chart = axis.chart; + var legendOptions = chart.options.legend || {}; + var x, y, width, height; + if (symbol) { + this.left = x = symbol.attr('x'); + this.top = y = symbol.attr('y'); + this.width = width = symbol.attr('width'); + this.height = height = symbol.attr('height'); + this.right = chart.chartWidth - x - width; + this.bottom = chart.chartHeight - y - height; + this.len = this.horiz ? width : height; + this.pos = this.horiz ? x : y; + } + else { + // Fake length for disabled legend to avoid tick issues + // and such (#5205) + this.len = (this.horiz ? + legendOptions.symbolWidth : + legendOptions.symbolHeight) || ColorAxis.defaultLegendLength; + } + }; + /** + * @private + */ + ColorAxis.prototype.normalizedValue = function (value) { + var axis = this; + if (axis.logarithmic) { + value = axis.logarithmic.log2lin(value); + } + return 1 - ((axis.max - value) / + ((axis.max - axis.min) || 1)); + }; + /** + * Translate from a value to a color. + * @private + */ + ColorAxis.prototype.toColor = function (value, point) { + var axis = this; + var dataClasses = axis.dataClasses; + var stops = axis.stops; + var pos, from, to, color, dataClass, i; + if (dataClasses) { + i = dataClasses.length; + while (i--) { + dataClass = dataClasses[i]; + from = dataClass.from; + to = dataClass.to; + if ((typeof from === 'undefined' || value >= from) && + (typeof to === 'undefined' || value <= to)) { + color = dataClass.color; + if (point) { + point.dataClass = i; + point.colorIndex = dataClass.colorIndex; + } + break; + } + } + } + else { + pos = axis.normalizedValue(value); + i = stops.length; + while (i--) { + if (pos > stops[i][0]) { + break; + } + } + from = stops[i] || stops[i + 1]; + to = stops[i + 1] || from; + // The position within the gradient + pos = 1 - (to[0] - pos) / ((to[0] - from[0]) || 1); + color = from.color.tweenTo(to.color, pos); + } + return color; + }; + /** + * Override the getOffset method to add the whole axis groups inside the + * legend. + * @private + */ + ColorAxis.prototype.getOffset = function () { + var axis = this; + var group = axis.legendGroup; + var sideOffset = axis.chart.axisOffset[axis.side]; + if (group) { + // Hook for the getOffset method to add groups to this parent + // group + axis.axisParent = group; + // Call the base + _super.prototype.getOffset.call(this); + // First time only + if (!axis.added) { + axis.added = true; + axis.labelLeft = 0; + axis.labelRight = axis.width; + } + // Reset it to avoid color axis reserving space + axis.chart.axisOffset[axis.side] = sideOffset; + } + }; + /** + * Create the color gradient. + * @private + */ + ColorAxis.prototype.setLegendColor = function () { + var axis = this; + var horiz = axis.horiz; + var reversed = axis.reversed; + var one = reversed ? 1 : 0; + var zero = reversed ? 0 : 1; + var grad = horiz ? [one, 0, zero, 0] : [0, zero, 0, one]; // #3190 + axis.legendColor = { + linearGradient: { + x1: grad[0], + y1: grad[1], + x2: grad[2], + y2: grad[3] + }, + stops: axis.stops + }; + }; + /** + * The color axis appears inside the legend and has its own legend symbol. + * @private + */ + ColorAxis.prototype.drawLegendSymbol = function (legend, item) { + var axis = this; + var padding = legend.padding; + var legendOptions = legend.options; + var horiz = axis.horiz; + var width = pick(legendOptions.symbolWidth, horiz ? ColorAxis.defaultLegendLength : 12); + var height = pick(legendOptions.symbolHeight, horiz ? 12 : ColorAxis.defaultLegendLength); + var labelPadding = pick(legendOptions.labelPadding, horiz ? 16 : 30); + var itemDistance = pick(legendOptions.itemDistance, 10); + this.setLegendColor(); + // Create the gradient + item.legendSymbol = this.chart.renderer.rect(0, legend.baseline - 11, width, height).attr({ + zIndex: 1 + }).add(item.legendGroup); + // Set how much space this legend item takes up + axis.legendItemWidth = width + padding + (horiz ? itemDistance : labelPadding); + axis.legendItemHeight = height + padding + (horiz ? labelPadding : 0); + }; + /** + * Fool the legend. + * @private + */ + ColorAxis.prototype.setState = function (state) { + this.series.forEach(function (series) { + series.setState(state); + }); + }; + /** + * @private + */ + ColorAxis.prototype.setVisible = function () { + }; + /** + * @private + */ + ColorAxis.prototype.getSeriesExtremes = function () { + var axis = this; + var series = axis.series; + var colorValArray, colorKey, colorValIndex, pointArrayMap, calculatedExtremes, cSeries, i = series.length, yData, j; + this.dataMin = Infinity; + this.dataMax = -Infinity; + while (i--) { // x, y, value, other + cSeries = series[i]; + colorKey = cSeries.colorKey = pick(cSeries.options.colorKey, cSeries.colorKey, cSeries.pointValKey, cSeries.zoneAxis, 'y'); + pointArrayMap = cSeries.pointArrayMap; + calculatedExtremes = cSeries[colorKey + 'Min'] && + cSeries[colorKey + 'Max']; + if (cSeries[colorKey + 'Data']) { + colorValArray = cSeries[colorKey + 'Data']; + } + else { + if (!pointArrayMap) { + colorValArray = cSeries.yData; + } + else { + colorValArray = []; + colorValIndex = pointArrayMap.indexOf(colorKey); + yData = cSeries.yData; + if (colorValIndex >= 0 && yData) { + for (j = 0; j < yData.length; j++) { + colorValArray.push(pick(yData[j][colorValIndex], yData[j])); + } + } + } + } + // If color key extremes are already calculated, use them. + if (calculatedExtremes) { + cSeries.minColorValue = cSeries[colorKey + 'Min']; + cSeries.maxColorValue = cSeries[colorKey + 'Max']; + } + else { + var cExtremes = Series.prototype.getExtremes.call(cSeries, colorValArray); + cSeries.minColorValue = cExtremes.dataMin; + cSeries.maxColorValue = cExtremes.dataMax; + } + if (typeof cSeries.minColorValue !== 'undefined') { + this.dataMin = + Math.min(this.dataMin, cSeries.minColorValue); + this.dataMax = + Math.max(this.dataMax, cSeries.maxColorValue); + } + if (!calculatedExtremes) { + Series.prototype.applyExtremes.call(cSeries); + } + } + }; + /** + * Internal function to draw a crosshair. + * + * @function Highcharts.ColorAxis#drawCrosshair + * + * @param {Highcharts.PointerEventObject} [e] + * The event arguments from the modified pointer event, extended with + * `chartX` and `chartY` + * + * @param {Highcharts.Point} [point] + * The Point object if the crosshair snaps to points. + * + * @fires Highcharts.ColorAxis#event:afterDrawCrosshair + * @fires Highcharts.ColorAxis#event:drawCrosshair + */ + ColorAxis.prototype.drawCrosshair = function (e, point) { + var axis = this; + var plotX = point && point.plotX; + var plotY = point && point.plotY; + var axisPos = axis.pos; + var axisLen = axis.len; + var crossPos; + if (point) { + crossPos = axis.toPixels(point.getNestedProperty(point.series.colorKey)); + if (crossPos < axisPos) { + crossPos = axisPos - 2; + } + else if (crossPos > axisPos + axisLen) { + crossPos = axisPos + axisLen + 2; + } + point.plotX = crossPos; + point.plotY = axis.len - crossPos; + _super.prototype.drawCrosshair.call(this, e, point); + point.plotX = plotX; + point.plotY = plotY; + if (axis.cross && + !axis.cross.addedToColorAxis && + axis.legendGroup) { + axis.cross + .addClass('highcharts-coloraxis-marker') + .add(axis.legendGroup); + axis.cross.addedToColorAxis = true; + if (!axis.chart.styledMode && + axis.crosshair) { + axis.cross.attr({ + fill: axis.crosshair.color + }); + } + } + } + }; + /** + * @private + */ + ColorAxis.prototype.getPlotLinePath = function (options) { + var axis = this; + var left = axis.left; + var pos = options.translatedValue; + var top = axis.top; + // crosshairs only + return isNumber(pos) ? // pos can be 0 (#3969) + (axis.horiz ? [ + ['M', pos - 4, this.top - 6], + ['L', pos + 4, this.top - 6], + ['L', pos, this.top], + ['Z'] + ] : [ + ['M', this.left, pos], + ['L', this.left - 6, pos + 6], + ['L', this.left - 6, pos - 6], + ['Z'] + ]) : + _super.prototype.getPlotLinePath.call(this, options); + }; + /** + * Updates a color axis instance with a new set of options. The options are + * merged with the existing options, so only new or altered options need to + * be specified. + * + * @function Highcharts.ColorAxis#update + * + * @param {Highcharts.ColorAxisOptions} newOptions + * The new options that will be merged in with existing options on the color + * axis. + * + * @param {boolean} [redraw] + * Whether to redraw the chart after the color axis is altered. If doing + * more operations on the chart, it is a good idea to set redraw to `false` + * and call {@link Highcharts.Chart#redraw} after. + */ + ColorAxis.prototype.update = function (newOptions, redraw) { + var axis = this; + var chart = axis.chart; + var legend = chart.legend; + var updatedOptions = ColorAxis.buildOptions(chart, {}, newOptions); + this.series.forEach(function (series) { + // Needed for Axis.update when choropleth colors change + series.isDirtyData = true; + }); + // When updating data classes, destroy old items and make sure new + // ones are created (#3207) + if (newOptions.dataClasses && legend.allItems || axis.dataClasses) { + axis.destroyItems(); + } + // Keep the options structure updated for export. Unlike xAxis and + // yAxis, the colorAxis is not an array. (#3207) + chart.options[axis.coll] = + merge(axis.userOptions, updatedOptions); + _super.prototype.update.call(this, updatedOptions, redraw); + if (axis.legendItem) { + axis.setLegendColor(); + legend.colorizeItem(this, true); + } + }; + /** + * Destroy color axis legend items. + * @private + */ + ColorAxis.prototype.destroyItems = function () { + var axis = this; + var chart = axis.chart; + if (axis.legendItem) { + chart.legend.destroyItem(axis); + } + else if (axis.legendItems) { + axis.legendItems.forEach(function (item) { + chart.legend.destroyItem(item); + }); + } + chart.isDirtyLegend = true; + }; + /** + * Removes the color axis and the related legend item. + * + * @function Highcharts.ColorAxis#remove + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart following the remove. + */ + ColorAxis.prototype.remove = function (redraw) { + this.destroyItems(); + _super.prototype.remove.call(this, redraw); + }; + /** + * Get the legend item symbols for data classes. + * @private + */ + ColorAxis.prototype.getDataClassLegendSymbols = function () { + var axis = this; + var chart = axis.chart; + var legendItems = axis.legendItems; + var legendOptions = chart.options.legend; + var valueDecimals = legendOptions.valueDecimals; + var valueSuffix = legendOptions.valueSuffix || ''; + var name; + if (!legendItems.length) { + axis.dataClasses.forEach(function (dataClass, i) { + var vis = true, from = dataClass.from, to = dataClass.to; + var numberFormatter = chart.numberFormatter; + // Assemble the default name. This can be overridden + // by legend.options.labelFormatter + name = ''; + if (typeof from === 'undefined') { + name = '< '; + } + else if (typeof to === 'undefined') { + name = '> '; + } + if (typeof from !== 'undefined') { + name += numberFormatter(from, valueDecimals) + valueSuffix; + } + if (typeof from !== 'undefined' && typeof to !== 'undefined') { + name += ' - '; + } + if (typeof to !== 'undefined') { + name += numberFormatter(to, valueDecimals) + valueSuffix; + } + // Add a mock object to the legend items + legendItems.push(extend({ + chart: chart, + name: name, + options: {}, + drawLegendSymbol: LegendSymbolMixin.drawRectangle, + visible: true, + setState: noop, + isDataClass: true, + setVisible: function () { + vis = axis.visible = !vis; + axis.series.forEach(function (series) { + series.points.forEach(function (point) { + if (point.dataClass === i) { + point.setVisible(vis); + } + }); + }); + chart.legend.colorizeItem(this, vis); + } + }, dataClass)); + }); + } + return legendItems; + }; + /* * + * + * Static Functions + * + * */ + ColorAxis.defaultLegendLength = 200; + /** + * A color axis for series. Visually, the color + * axis will appear as a gradient or as separate items inside the + * legend, depending on whether the axis is scalar or based on data + * classes. + * + * For supported color formats, see the + * [docs article about colors](https://www.highcharts.com/docs/chart-design-and-style/colors). + * + * A scalar color axis is represented by a gradient. The colors either + * range between the [minColor](#colorAxis.minColor) and the + * [maxColor](#colorAxis.maxColor), or for more fine grained control the + * colors can be defined in [stops](#colorAxis.stops). Often times, the + * color axis needs to be adjusted to get the right color spread for the + * data. In addition to stops, consider using a logarithmic + * [axis type](#colorAxis.type), or setting [min](#colorAxis.min) and + * [max](#colorAxis.max) to avoid the colors being determined by + * outliers. + * + * When [dataClasses](#colorAxis.dataClasses) are used, the ranges are + * subdivided into separate classes like categories based on their + * values. This can be used for ranges between two values, but also for + * a true category. However, when your data is categorized, it may be as + * convenient to add each category to a separate series. + * + * Color axis does not work with: `sankey`, `sunburst`, `dependencywheel`, + * `networkgraph`, `wordcloud`, `venn`, `gauge` and `solidgauge` series + * types. + * + * Since v7.2.0 `colorAxis` can also be an array of options objects. + * + * See [the Axis object](/class-reference/Highcharts.Axis) for + * programmatic access to the axis. + * + * @sample {highcharts} highcharts/coloraxis/custom-color-key + * Column chart with color axis + * @sample {highcharts} highcharts/coloraxis/horizontal-layout + * Horizontal layout + * @sample {highmaps} maps/coloraxis/dataclasscolor + * With data classes + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor + * Min color and max color + * + * @extends xAxis + * @excluding alignTicks, allowDecimals, alternateGridColor, breaks, + * categories, crosshair, dateTimeLabelFormats, height, left, + * lineWidth, linkedTo, maxZoom, minRange, minTickInterval, + * offset, opposite, pane, plotBands, plotLines, + * reversedStacks, showEmpty, title, top, width, zoomEnabled + * @product highcharts highstock highmaps + * @type {*|Array<*>} + * @optionparent colorAxis + * @ignore + */ + ColorAxis.defaultOptions = { + /** + * Whether to allow decimals on the color axis. + * @type {boolean} + * @default true + * @product highcharts highstock highmaps + * @apioption colorAxis.allowDecimals + */ + /** + * Determines how to set each data class' color if no individual + * color is set. The default value, `tween`, computes intermediate + * colors between `minColor` and `maxColor`. The other possible + * value, `category`, pulls colors from the global or chart specific + * [colors](#colors) array. + * + * @sample {highmaps} maps/coloraxis/dataclasscolor/ + * Category colors + * + * @type {string} + * @default tween + * @product highcharts highstock highmaps + * @validvalue ["tween", "category"] + * @apioption colorAxis.dataClassColor + */ + /** + * An array of data classes or ranges for the choropleth map. If + * none given, the color axis is scalar and values are distributed + * as a gradient between the minimum and maximum colors. + * + * @sample {highmaps} maps/demo/data-class-ranges/ + * Multiple ranges + * + * @sample {highmaps} maps/demo/data-class-two-ranges/ + * Two ranges + * + * @type {Array<*>} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses + */ + /** + * The layout of the color axis. Can be `'horizontal'` or `'vertical'`. + * If none given, the color axis has the same layout as the legend. + * + * @sample highcharts/coloraxis/horizontal-layout/ + * Horizontal color axis layout with vertical legend + * + * @type {string|undefined} + * @since 7.2.0 + * @product highcharts highstock highmaps + * @apioption colorAxis.layout + */ + /** + * The color of each data class. If not set, the color is pulled + * from the global or chart-specific [colors](#colors) array. In + * styled mode, this option is ignored. Instead, use colors defined + * in CSS. + * + * @sample {highmaps} maps/demo/data-class-two-ranges/ + * Explicit colors + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses.color + */ + /** + * The start of the value range that the data class represents, + * relating to the point value. + * + * The range of each `dataClass` is closed in both ends, but can be + * overridden by the next `dataClass`. + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses.from + */ + /** + * The name of the data class as it appears in the legend. + * If no name is given, it is automatically created based on the + * `from` and `to` values. For full programmatic control, + * [legend.labelFormatter](#legend.labelFormatter) can be used. + * In the formatter, `this.from` and `this.to` can be accessed. + * + * @sample {highmaps} maps/coloraxis/dataclasses-name/ + * Named data classes + * + * @sample {highmaps} maps/coloraxis/dataclasses-labelformatter/ + * Formatted data classes + * + * @type {string} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses.name + */ + /** + * The end of the value range that the data class represents, + * relating to the point value. + * + * The range of each `dataClass` is closed in both ends, but can be + * overridden by the next `dataClass`. + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses.to + */ + /** @ignore-option */ + lineWidth: 0, + /** + * Padding of the min value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. + * + * @product highcharts highstock highmaps + */ + minPadding: 0, + /** + * The maximum value of the axis in terms of map point values. If + * `null`, the max value is automatically calculated. If the + * `endOnTick` option is true, the max value might be rounded up. + * + * @sample {highmaps} maps/coloraxis/gridlines/ + * Explicit min and max to reduce the effect of outliers + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.max + */ + /** + * The minimum value of the axis in terms of map point values. If + * `null`, the min value is automatically calculated. If the + * `startOnTick` option is true, the min value might be rounded + * down. + * + * @sample {highmaps} maps/coloraxis/gridlines/ + * Explicit min and max to reduce the effect of outliers + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.min + */ + /** + * Padding of the max value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. + * + * @product highcharts highstock highmaps + */ + maxPadding: 0, + /** + * Color of the grid lines extending from the axis across the + * gradient. + * + * @sample {highmaps} maps/coloraxis/gridlines/ + * Grid lines demonstrated + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #e6e6e6 + * @product highcharts highstock highmaps + * @apioption colorAxis.gridLineColor + */ + /** + * The width of the grid lines extending from the axis across the + * gradient of a scalar color axis. + * + * @sample {highmaps} maps/coloraxis/gridlines/ + * Grid lines demonstrated + * + * @product highcharts highstock highmaps + */ + gridLineWidth: 1, + /** + * The interval of the tick marks in axis units. When `null`, the + * tick interval is computed to approximately follow the + * `tickPixelInterval`. + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.tickInterval + */ + /** + * If [tickInterval](#colorAxis.tickInterval) is `null` this option + * sets the approximate pixel interval of the tick marks. + * + * @product highcharts highstock highmaps + */ + tickPixelInterval: 72, + /** + * Whether to force the axis to start on a tick. Use this option + * with the `maxPadding` option to control the axis start. + * + * @product highcharts highstock highmaps + */ + startOnTick: true, + /** + * Whether to force the axis to end on a tick. Use this option with + * the [maxPadding](#colorAxis.maxPadding) option to control the + * axis end. + * + * @product highcharts highstock highmaps + */ + endOnTick: true, + /** @ignore */ + offset: 0, + /** + * The triangular marker on a scalar color axis that points to the + * value of the hovered area. To disable the marker, set + * `marker: null`. + * + * @sample {highmaps} maps/coloraxis/marker/ + * Black marker + * + * @declare Highcharts.PointMarkerOptionsObject + * @product highcharts highstock highmaps + */ + marker: { + /** + * Animation for the marker as it moves between values. Set to + * `false` to disable animation. Defaults to `{ duration: 50 }`. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + * @product highcharts highstock highmaps + */ + animation: { + /** @internal */ + duration: 50 + }, + /** @internal */ + width: 0.01, + /** + * The color of the marker. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock highmaps + */ + color: '#999999' + }, + /** + * The axis labels show the number for each tick. + * + * For more live examples on label options, see [xAxis.labels in the + * Highcharts API.](/highcharts#xAxis.labels) + * + * @extends xAxis.labels + * @product highcharts highstock highmaps + */ + labels: { + /** + * How to handle overflowing labels on horizontal color axis. If set + * to `"allow"`, it will not be aligned at all. By default it + * `"justify"` labels inside the chart area. If there is room to + * move it, it will be aligned to the edge, else it will be removed. + * + * @validvalue ["allow", "justify"] + * @product highcharts highstock highmaps + */ + overflow: 'justify', + rotation: 0 + }, + /** + * The color to represent the minimum of the color axis. Unless + * [dataClasses](#colorAxis.dataClasses) or + * [stops](#colorAxis.stops) are set, the gradient starts at this + * value. + * + * If dataClasses are set, the color is based on minColor and + * maxColor unless a color is set for each data class, or the + * [dataClassColor](#colorAxis.dataClassColor) is set. + * + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor/ + * Min and max colors on scalar (gradient) axis + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor-dataclasses/ + * On data classes + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock highmaps + */ + minColor: '#e6ebf5', + /** + * The color to represent the maximum of the color axis. Unless + * [dataClasses](#colorAxis.dataClasses) or + * [stops](#colorAxis.stops) are set, the gradient ends at this + * value. + * + * If dataClasses are set, the color is based on minColor and + * maxColor unless a color is set for each data class, or the + * [dataClassColor](#colorAxis.dataClassColor) is set. + * + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor/ + * Min and max colors on scalar (gradient) axis + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor-dataclasses/ + * On data classes + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock highmaps + */ + maxColor: '#003399', + /** + * Color stops for the gradient of a scalar color axis. Use this in + * cases where a linear gradient between a `minColor` and `maxColor` + * is not sufficient. The stops is an array of tuples, where the + * first item is a float between 0 and 1 assigning the relative + * position in the gradient, and the second item is the color. + * + * @sample {highmaps} maps/demo/heatmap/ + * Heatmap with three color stops + * + * @type {Array>} + * @product highcharts highstock highmaps + * @apioption colorAxis.stops + */ + /** + * The pixel length of the main tick marks on the color axis. + */ + tickLength: 5, + /** + * The type of interpolation to use for the color axis. Can be + * `linear` or `logarithmic`. + * + * @sample highcharts/coloraxis/logarithmic-with-emulate-negative-values/ + * Logarithmic color axis with extension to emulate negative + * values + * + * @type {Highcharts.ColorAxisTypeValue} + * @default linear + * @product highcharts highstock highmaps + * @apioption colorAxis.type + */ + /** + * Whether to reverse the axis so that the highest number is closest + * to the origin. Defaults to `false` in a horizontal legend and + * `true` in a vertical legend, where the smallest value starts on + * top. + * + * @type {boolean} + * @product highcharts highstock highmaps + * @apioption colorAxis.reversed + */ + /** + * @product highcharts highstock highmaps + * @excluding afterBreaks, pointBreak, pointInBreak + * @apioption colorAxis.events + */ + /** + * Fires when the legend item belonging to the colorAxis is clicked. + * One parameter, `event`, is passed to the function. + * + * @type {Function} + * @product highcharts highstock highmaps + * @apioption colorAxis.events.legendItemClick + */ + /** + * Whether to display the colorAxis in the legend. + * + * @sample highcharts/coloraxis/hidden-coloraxis-with-3d-chart/ + * Hidden color axis with 3d chart + * + * @see [heatmap.showInLegend](#series.heatmap.showInLegend) + * + * @since 4.2.7 + * @product highcharts highstock highmaps + */ + showInLegend: true + }; + /** + * @private + */ + ColorAxis.keepProps = [ + 'legendGroup', + 'legendItemHeight', + 'legendItemWidth', + 'legendItem', + 'legendSymbol' + ]; + return ColorAxis; + }(Axis)); + // Properties to preserve after destroy, for Axis.update (#5881, #6025). + Array.prototype.push.apply(Axis.keepProps, ColorAxis.keepProps); + H.ColorAxis = ColorAxis; + /** + * Handle animation of the color attributes directly + * + * @private + * @function Highcharts.Fx#fillSetter + */ /** + * Handle animation of the color attributes directly + * + * @private + * @function Highcharts.Fx#strokeSetter + */ + ['fill', 'stroke'].forEach(function (prop) { + Fx.prototype[prop + 'Setter'] = function () { + this.elem.attr(prop, color(this.start).tweenTo(color(this.end), this.pos), null, true); + }; + }); + // Extend the chart getAxes method to also get the color axis + addEvent(Chart, 'afterGetAxes', function () { + var chart = this, options = chart.options; + this.colorAxis = []; + if (options.colorAxis) { + options.colorAxis = splat(options.colorAxis); + options.colorAxis.forEach(function (axisOptions, i) { + axisOptions.index = i; + new ColorAxis(chart, axisOptions); // eslint-disable-line no-new + }); + } + }); + // Add colorAxis to series axisTypes + addEvent(Series, 'bindAxes', function () { + var axisTypes = this.axisTypes; + if (!axisTypes) { + this.axisTypes = ['colorAxis']; + } + else if (axisTypes.indexOf('colorAxis') === -1) { + axisTypes.push('colorAxis'); + } + }); + // Add the color axis. This also removes the axis' own series to prevent + // them from showing up individually. + addEvent(Legend, 'afterGetAllItems', function (e) { + var colorAxisItems = [], colorAxes = this.chart.colorAxis || [], options, i; + colorAxes.forEach(function (colorAxis) { + options = colorAxis.options; + if (options && options.showInLegend) { + // Data classes + if (options.dataClasses && options.visible) { + colorAxisItems = colorAxisItems.concat(colorAxis.getDataClassLegendSymbols()); + // Gradient legend + } + else if (options.visible) { + // Add this axis on top + colorAxisItems.push(colorAxis); + } + // If dataClasses are defined or showInLegend option is not set to + // true, do not add color axis' series to legend. + colorAxis.series.forEach(function (series) { + if (!series.options.showInLegend || options.dataClasses) { + if (series.options.legendType === 'point') { + series.points.forEach(function (point) { + erase(e.allItems, point); + }); + } + else { + erase(e.allItems, series); + } + } + }); + } + }); + i = colorAxisItems.length; + while (i--) { + e.allItems.unshift(colorAxisItems[i]); + } + }); + addEvent(Legend, 'afterColorizeItem', function (e) { + if (e.visible && e.item.legendColor) { + e.item.legendSymbol.attr({ + fill: e.item.legendColor + }); + } + }); + // Updates in the legend need to be reflected in the color axis (6888) + addEvent(Legend, 'afterUpdate', function () { + var colorAxes = this.chart.colorAxis; + if (colorAxes) { + colorAxes.forEach(function (colorAxis) { + colorAxis.update({}, arguments[2]); + }); + } + }); + // Calculate and set colors for points + addEvent(Series, 'afterTranslate', function () { + if (this.chart.colorAxis && + this.chart.colorAxis.length || + this.colorAttribs) { + this.translateColors(); + } + }); + + return ColorAxis; + }); + _registerModule(_modules, 'masters/modules/coloraxis.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/current-date-indicator.js b/librerias/gantt/code/modules/current-date-indicator.js new file mode 100644 index 0000000..95875b1 --- /dev/null +++ b/librerias/gantt/code/modules/current-date-indicator.js @@ -0,0 +1,13 @@ +/* + Highcharts Gantt JS v8.1.0 (2020-05-05) + + CurrentDateIndicator + + (c) 2010-2019 Lars A. V. Cabrera + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/current-date-indicator",["highcharts"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,c,b,d){a.hasOwnProperty(c)||(a[c]=d.apply(null,b))}a=a?a._modules:{};b(a,"parts-gantt/CurrentDateIndicator.js",[a["parts/Globals.js"],a["parts/Utilities.js"],a["parts/PlotLineOrBand.js"]], +function(a,c,b){var d=c.addEvent,e=c.merge;c=c.wrap;var f={currentDateIndicator:!0,color:"#ccd6eb",width:2,label:{format:"%a, %b %d %Y, %H:%M",formatter:function(b,g){return a.dateFormat(g,b)},rotation:0,style:{fontSize:"10px"}}};d(a.Axis,"afterSetOptions",function(){var a=this.options,b=a.currentDateIndicator;b&&(b="object"===typeof b?e(f,b):e(f),b.value=new Date,a.plotLines||(a.plotLines=[]),a.plotLines.push(b))});d(b,"render",function(){this.label&&this.label.attr({text:this.getLabelText(this.options.label)})}); +c(b.prototype,"getLabelText",function(a,b){var c=this.options;return c.currentDateIndicator&&c.label&&"function"===typeof c.label.formatter?(c.value=new Date,c.label.formatter.call(this,c.value,c.label.format)):a.call(this,b)})});b(a,"masters/modules/current-date-indicator.src.js",[],function(){})}); +//# sourceMappingURL=current-date-indicator.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/current-date-indicator.js.map b/librerias/gantt/code/modules/current-date-indicator.js.map new file mode 100644 index 0000000..929c0df --- /dev/null +++ b/librerias/gantt/code/modules/current-date-indicator.js.map @@ -0,0 +1 @@ +{"version":3,"file":"current-date-indicator.js.map","lineCount":12,"mappings":"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","sources":["current-date-indicator.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","U","PlotLineOrBand","addEvent","merge","wrap","defaultConfig","currentDateIndicator","color","width","label","format","formatter","value","dateFormat","rotation","style","fontSize","Axis","options","cdiOptions","Date","plotLines","push","attr","text","getLabelText","prototype","defaultMethod","defaultLabelOptions","call"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/current-date-indicator.src.js b/librerias/gantt/code/modules/current-date-indicator.src.js new file mode 100644 index 0000000..e6ee200 --- /dev/null +++ b/librerias/gantt/code/modules/current-date-indicator.src.js @@ -0,0 +1,131 @@ +/** + * @license Highcharts Gantt JS v8.1.0 (2020-05-05) + * + * CurrentDateIndicator + * + * (c) 2010-2019 Lars A. V. Cabrera + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/current-date-indicator', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'parts-gantt/CurrentDateIndicator.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['parts/PlotLineOrBand.js']], function (H, U, PlotLineOrBand) { + /* * + * + * (c) 2016-2020 Highsoft AS + * + * Author: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, merge = U.merge, wrap = U.wrap; + var Axis = H.Axis; + var defaultConfig = { + /** + * Show an indicator on the axis for the current date and time. Can be a + * boolean or a configuration object similar to + * [xAxis.plotLines](#xAxis.plotLines). + * + * @sample gantt/current-date-indicator/demo + * Current date indicator enabled + * @sample gantt/current-date-indicator/object-config + * Current date indicator with custom options + * + * @declare Highcharts.AxisCurrentDateIndicatorOptions + * @type {boolean|*} + * @default true + * @extends xAxis.plotLines + * @excluding value + * @product gantt + * @apioption xAxis.currentDateIndicator + */ + currentDateIndicator: true, + color: '#ccd6eb', + width: 2, + /** + * @declare Highcharts.AxisCurrentDateIndicatorLabelOptions + */ + label: { + /** + * Format of the label. This options is passed as the fist argument to + * [dateFormat](/class-reference/Highcharts#dateFormat) function. + * + * @type {string} + * @default '%a, %b %d %Y, %H:%M' + * @product gantt + * @apioption xAxis.currentDateIndicator.label.format + */ + format: '%a, %b %d %Y, %H:%M', + formatter: function (value, format) { + return H.dateFormat(format, value); + }, + rotation: 0, + /** + * @type {Highcharts.CSSObject} + */ + style: { + /** @internal */ + fontSize: '10px' + } + } + }; + /* eslint-disable no-invalid-this */ + addEvent(Axis, 'afterSetOptions', function () { + var options = this.options, cdiOptions = options.currentDateIndicator; + if (cdiOptions) { + cdiOptions = typeof cdiOptions === 'object' ? + merge(defaultConfig, cdiOptions) : merge(defaultConfig); + cdiOptions.value = new Date(); + if (!options.plotLines) { + options.plotLines = []; + } + options.plotLines.push(cdiOptions); + } + }); + addEvent(PlotLineOrBand, 'render', function () { + // If the label already exists, update its text + if (this.label) { + this.label.attr({ + text: this.getLabelText(this.options.label) + }); + } + }); + wrap(PlotLineOrBand.prototype, 'getLabelText', function (defaultMethod, defaultLabelOptions) { + var options = this.options; + if (options.currentDateIndicator && options.label && + typeof options.label.formatter === 'function') { + options.value = new Date(); + return options.label.formatter + .call(this, options.value, options.label.format); + } + return defaultMethod.call(this, defaultLabelOptions); + }); + + }); + _registerModule(_modules, 'masters/modules/current-date-indicator.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/cylinder.js b/librerias/gantt/code/modules/cylinder.js new file mode 100644 index 0000000..d14db58 --- /dev/null +++ b/librerias/gantt/code/modules/cylinder.js @@ -0,0 +1,17 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Highcharts cylinder module + + (c) 2010-2019 Kacper Madej + + License: www.highcharts.com/license +*/ +(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/cylinder",["highcharts","highcharts/highcharts-3d"],function(g){b(g);b.Highcharts=g;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function g(b,h,f,g){b.hasOwnProperty(h)||(b[h]=g.apply(null,f))}b=b?b._modules:{};g(b,"modules/cylinder.src.js",[b["parts/Globals.js"],b["parts/Color.js"],b["parts/Utilities.js"]],function(b, +g,f){var h=g.parse;g=f.merge;var r=f.pick,t=f.seriesType,u=b.charts,v=b.deg2rad,w=b.perspective;f=b.Renderer.prototype;var x=f.cuboidPath,k=function(a){return!a.some(function(a){return"C"===a[0]})};t("cylinder","column",{},{},{shapeType:"cylinder",hasNewShapeType:b.seriesTypes.column.prototype.pointClass.prototype.hasNewShapeType});b=g(f.elements3d.cuboid,{parts:["top","bottom","front","back"],pathType:"cylinder",fillSetter:function(a){this.singleSetterForParts("fill",null,{front:a,back:a,top:h(a).brighten(.1).get(), +bottom:h(a).brighten(-.1).get()});this.color=this.fill=a;return this}});f.elements3d.cylinder=b;f.cylinder=function(a){return this.element3d("cylinder",a)};f.cylinderPath=function(a){var c=u[this.chartIndex],d=x.call(this,a),e=!d.isTop,b=!d.isFront,f=this.getCylinderEnd(c,a);a=this.getCylinderEnd(c,a,!0);return{front:this.getCylinderFront(f,a),back:this.getCylinderBack(f,a),top:f,bottom:a,zIndexes:{top:e?3:0,bottom:e?0:3,front:b?2:1,back:b?1:2,group:d.zIndexes.group}}};f.getCylinderFront=function(a, +c){a=a.slice(0,3);if(k(c)){var d=c[0];"M"===d[0]&&(a.push(c[2]),a.push(c[1]),a.push(["L",d[1],d[2]]))}else{d=c[0];var e=c[1];c=c[2];"M"===d[0]&&"C"===e[0]&&"C"===c[0]&&(a.push(["L",c[5],c[6]]),a.push(["C",c[3],c[4],c[1],c[2],e[5],e[6]]),a.push(["C",e[3],e[4],e[1],e[2],d[1],d[2]]))}a.push(["Z"]);return a};f.getCylinderBack=function(a,c){var d=[];if(k(a)){var e=a[0],b=a[2];"M"===e[0]&&"L"===b[0]&&(d.push(["M",b[1],b[2]]),d.push(a[3]),d.push(["L",e[1],e[2]]))}else"C"===a[2][0]&&d.push(["M",a[2][5],a[2][6]]), +d.push(a[3],a[4]);k(c)?(e=c[0],"M"===e[0]&&(d.push(["L",e[1],e[2]]),d.push(c[3]),d.push(c[2]))):(a=c[2],e=c[3],c=c[4],"C"===a[0]&&"C"===e[0]&&"C"===c[0]&&(d.push(["L",c[5],c[6]]),d.push(["C",c[3],c[4],c[1],c[2],e[5],e[6]]),d.push(["C",e[3],e[4],e[1],e[2],a[5],a[6]])));d.push(["Z"]);return d};f.getCylinderEnd=function(a,c,d){var e=r(c.depth,c.width),b=Math.min(c.width,e)/2,f=v*(a.options.chart.options3d.beta-90+(c.alphaCorrection||0));d=c.y+(d?c.height:0);var g=.5519*b,h=c.width/2+c.x,k=e/2+c.z,l= +[{x:0,y:d,z:b},{x:g,y:d,z:b},{x:b,y:d,z:g},{x:b,y:d,z:0},{x:b,y:d,z:-g},{x:g,y:d,z:-b},{x:0,y:d,z:-b},{x:-g,y:d,z:-b},{x:-b,y:d,z:-g},{x:-b,y:d,z:0},{x:-b,y:d,z:g},{x:-g,y:d,z:b},{x:0,y:d,z:b}],p=Math.cos(f),q=Math.sin(f),m,n;l.forEach(function(a,b){m=a.x;n=a.z;l[b].x=m*p-n*q+h;l[b].z=n*p+m*q+k});a=w(l,a,!0);return 2.5>Math.abs(a[3].y-a[9].y)&&2.5>Math.abs(a[0].y-a[6].y)?this.toLinePath([a[0],a[3],a[6],a[9]],!0):this.getCurvedPath(a)};f.getCurvedPath=function(a){var b=[["M",a[0].x,a[0].y]],d=a.length- +2,e;for(e=1;e|null|*>} + * @extends series.column.data + * @product highcharts highstock + * @apioption series.cylinder.data + */ + // cylinder extends cuboid + cylinderMethods = merge(RendererProto.elements3d.cuboid, { + parts: ['top', 'bottom', 'front', 'back'], + pathType: 'cylinder', + fillSetter: function (fill) { + this.singleSetterForParts('fill', null, { + front: fill, + back: fill, + top: color(fill).brighten(0.1).get(), + bottom: color(fill).brighten(-0.1).get() + }); + // fill for animation getter (#6776) + this.color = this.fill = fill; + return this; + } + }); + RendererProto.elements3d.cylinder = cylinderMethods; + RendererProto.cylinder = function (shapeArgs) { + return this.element3d('cylinder', shapeArgs); + }; + // Generates paths and zIndexes. + RendererProto.cylinderPath = function (shapeArgs) { + var renderer = this, chart = charts[renderer.chartIndex], + // decide zIndexes of parts based on cubiod logic, for consistency. + cuboidData = cuboidPath.call(renderer, shapeArgs), isTopFirst = !cuboidData.isTop, isFronFirst = !cuboidData.isFront, top = renderer.getCylinderEnd(chart, shapeArgs), bottom = renderer.getCylinderEnd(chart, shapeArgs, true); + return { + front: renderer.getCylinderFront(top, bottom), + back: renderer.getCylinderBack(top, bottom), + top: top, + bottom: bottom, + zIndexes: { + top: isTopFirst ? 3 : 0, + bottom: isTopFirst ? 0 : 3, + front: isFronFirst ? 2 : 1, + back: isFronFirst ? 1 : 2, + group: cuboidData.zIndexes.group + } + }; + }; + // Returns cylinder Front path + RendererProto.getCylinderFront = function (topPath, bottomPath) { + var path = topPath.slice(0, 3); + if (isSimplified(bottomPath)) { + var move = bottomPath[0]; + if (move[0] === 'M') { + path.push(bottomPath[2]); + path.push(bottomPath[1]); + path.push(['L', move[1], move[2]]); + } + } + else { + var move = bottomPath[0], curve1 = bottomPath[1], curve2 = bottomPath[2]; + if (move[0] === 'M' && curve1[0] === 'C' && curve2[0] === 'C') { + path.push(['L', curve2[5], curve2[6]]); + path.push(['C', curve2[3], curve2[4], curve2[1], curve2[2], curve1[5], curve1[6]]); + path.push(['C', curve1[3], curve1[4], curve1[1], curve1[2], move[1], move[2]]); + } + } + path.push(['Z']); + return path; + }; + // Returns cylinder Back path + RendererProto.getCylinderBack = function (topPath, bottomPath) { + var path = []; + if (isSimplified(topPath)) { + var move = topPath[0], line2 = topPath[2]; + if (move[0] === 'M' && line2[0] === 'L') { + path.push(['M', line2[1], line2[2]]); + path.push(topPath[3]); + // End at start + path.push(['L', move[1], move[2]]); + } + } + else { + if (topPath[2][0] === 'C') { + path.push(['M', topPath[2][5], topPath[2][6]]); + } + path.push(topPath[3], topPath[4]); + } + if (isSimplified(bottomPath)) { + var move = bottomPath[0]; + if (move[0] === 'M') { + path.push(['L', move[1], move[2]]); + path.push(bottomPath[3]); + path.push(bottomPath[2]); + } + } + else { + var curve2 = bottomPath[2], curve3 = bottomPath[3], curve4 = bottomPath[4]; + if (curve2[0] === 'C' && curve3[0] === 'C' && curve4[0] === 'C') { + path.push(['L', curve4[5], curve4[6]]); + path.push(['C', curve4[3], curve4[4], curve4[1], curve4[2], curve3[5], curve3[6]]); + path.push(['C', curve3[3], curve3[4], curve3[1], curve3[2], curve2[5], curve2[6]]); + } + } + path.push(['Z']); + return path; + }; + // Retruns cylinder path for top or bottom + RendererProto.getCylinderEnd = function (chart, shapeArgs, isBottom) { + // A half of the smaller one out of width or depth (optional, because + // there's no depth for a funnel that reuses the code) + var depth = pick(shapeArgs.depth, shapeArgs.width), radius = Math.min(shapeArgs.width, depth) / 2, + // Approximated longest diameter + angleOffset = deg2rad * (chart.options.chart.options3d.beta - 90 + + (shapeArgs.alphaCorrection || 0)), + // Could be top or bottom of the cylinder + y = shapeArgs.y + (isBottom ? shapeArgs.height : 0), + // Use cubic Bezier curve to draw a cricle in x,z (y is constant). + // More math. at spencermortensen.com/articles/bezier-circle/ + c = 0.5519 * radius, centerX = shapeArgs.width / 2 + shapeArgs.x, centerZ = depth / 2 + shapeArgs.z, + // points could be generated in a loop, but readability will plummet + points = [{ + x: 0, + y: y, + z: radius + }, { + x: c, + y: y, + z: radius + }, { + x: radius, + y: y, + z: c + }, { + x: radius, + y: y, + z: 0 + }, { + x: radius, + y: y, + z: -c + }, { + x: c, + y: y, + z: -radius + }, { + x: 0, + y: y, + z: -radius + }, { + x: -c, + y: y, + z: -radius + }, { + x: -radius, + y: y, + z: -c + }, { + x: -radius, + y: y, + z: 0 + }, { + x: -radius, + y: y, + z: c + }, { + x: -c, + y: y, + z: radius + }, { + x: 0, + y: y, + z: radius + }], cosTheta = Math.cos(angleOffset), sinTheta = Math.sin(angleOffset), perspectivePoints, path, x, z; + // rotete to match chart's beta and translate to the shape center + points.forEach(function (point, i) { + x = point.x; + z = point.z; + // x′ = (x * cosθ − z * sinθ) + centerX + // z′ = (z * cosθ + x * sinθ) + centerZ + points[i].x = (x * cosTheta - z * sinTheta) + centerX; + points[i].z = (z * cosTheta + x * sinTheta) + centerZ; + }); + perspectivePoints = perspective(points, chart, true); + // check for sub-pixel curve issue, compare front and back edges + if (Math.abs(perspectivePoints[3].y - perspectivePoints[9].y) < 2.5 && + Math.abs(perspectivePoints[0].y - perspectivePoints[6].y) < 2.5) { + // use simplied shape + path = this.toLinePath([ + perspectivePoints[0], + perspectivePoints[3], + perspectivePoints[6], + perspectivePoints[9] + ], true); + } + else { + // or default curved path to imitate ellipse (2D circle) + path = this.getCurvedPath(perspectivePoints); + } + return path; + }; + // Returns curved path in format of: + // [ M, x, y, ...[C, cp1x, cp2y, cp2x, cp2y, epx, epy]*n_times ] + // (cp - control point, ep - end point) + RendererProto.getCurvedPath = function (points) { + var path = [['M', points[0].x, points[0].y]], limit = points.length - 2, i; + for (i = 1; i < limit; i += 3) { + path.push([ + 'C', + points[i].x, points[i].y, + points[i + 1].x, points[i + 1].y, + points[i + 2].x, points[i + 2].y + ]); + } + return path; + }; + + }); + _registerModule(_modules, 'masters/modules/cylinder.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/data.js b/librerias/gantt/code/modules/data.js new file mode 100644 index 0000000..c18c4f3 --- /dev/null +++ b/librerias/gantt/code/modules/data.js @@ -0,0 +1,41 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Data module + + (c) 2012-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(c){"object"===typeof module&&module.exports?(c["default"]=c,module.exports=c):"function"===typeof define&&define.amd?define("highcharts/modules/data",["highcharts"],function(t){c(t);c.Highcharts=t;return c}):c("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(c){function t(c,l,u,t){c.hasOwnProperty(l)||(c[l]=t.apply(null,u))}c=c?c._modules:{};t(c,"mixins/ajax.js",[c["parts/Globals.js"],c["parts/Utilities.js"]],function(c,l){var u=l.merge,t=l.objectEach;c.ajax=function(c){var h= +u(!0,{url:!1,type:"get",dataType:"json",success:!1,error:!1,data:!1,headers:{}},c);c={json:"application/json",xml:"application/xml",text:"text/plain",octet:"application/octet-stream"};var l=new XMLHttpRequest;if(!h.url)return!1;l.open(h.type.toUpperCase(),h.url,!0);h.headers["Content-Type"]||l.setRequestHeader("Content-Type",c[h.dataType]||c.text);t(h.headers,function(c,h){l.setRequestHeader(h,c)});l.onreadystatechange=function(){if(4===l.readyState){if(200===l.status){var c=l.responseText;if("json"=== +h.dataType)try{c=JSON.parse(c)}catch(z){h.error&&h.error(l,z);return}return h.success&&h.success(c)}h.error&&h.error(l,l.responseText)}};try{h.data=JSON.stringify(h.data)}catch(C){}l.send(h.data||!0)};c.getJSON=function(l,h){c.ajax({url:l,success:h,dataType:"json",headers:{"Content-Type":"text/plain"}})}});t(c,"modules/data.src.js",[c["parts/Globals.js"],c["parts/Utilities.js"],c["parts/Globals.js"],c["parts/Point.js"]],function(c,l,u,t){var E=l.addEvent,h=l.defined,F=l.extend,C=l.fireEvent,z=l.isNumber, +A=l.merge,G=l.objectEach,H=l.pick,I=l.splat;l=u.Chart;var J=u.win.document,K=function(){function f(a,b,e){this.options=this.rawColumns=this.firstRowAsNames=this.chartOptions=this.chart=void 0;this.dateFormats={"YYYY/mm/dd":{regex:/^([0-9]{4})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{1,2})$/,parser:function(a){return a?Date.UTC(+a[1],a[2]-1,+a[3]):NaN}},"dd/mm/YYYY":{regex:/^([0-9]{1,2})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{4})$/,parser:function(a){return a?Date.UTC(+a[3],a[2]-1,+a[1]):NaN},alternative:"mm/dd/YYYY"}, +"mm/dd/YYYY":{regex:/^([0-9]{1,2})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{4})$/,parser:function(a){return a?Date.UTC(+a[3],a[1]-1,+a[2]):NaN}},"dd/mm/YY":{regex:/^([0-9]{1,2})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{2})$/,parser:function(a){if(!a)return NaN;var b=+a[3];b=b>(new Date).getFullYear()-2E3?b+1900:b+2E3;return Date.UTC(b,a[2]-1,+a[1])},alternative:"mm/dd/YY"},"mm/dd/YY":{regex:/^([0-9]{1,2})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{2})$/,parser:function(a){return a?Date.UTC(+a[3]+2E3,a[1]-1,+a[2]):NaN}}}; +this.init(a,b,e)}f.prototype.init=function(a,b,e){var d=a.decimalPoint;b&&(this.chartOptions=b);e&&(this.chart=e);"."!==d&&","!==d&&(d=void 0);this.options=a;this.columns=a.columns||this.rowsToColumns(a.rows)||[];this.firstRowAsNames=H(a.firstRowAsNames,this.firstRowAsNames,!0);this.decimalRegex=d&&new RegExp("^(-?[0-9]+)"+d+"([0-9]+)$");this.rawColumns=[];if(this.columns.length){this.dataFound();var g=!0}this.hasURLOption(a)&&(clearTimeout(this.liveDataTimeout),g=!1);g||(g=this.fetchLiveData()); +g||(g=!!this.parseCSV().length);g||(g=!!this.parseTable().length);g||(g=this.parseGoogleSpreadsheet());!g&&a.afterComplete&&a.afterComplete()};f.prototype.hasURLOption=function(a){return!(!a||!(a.rowsURL||a.csvURL||a.columnsURL))};f.prototype.getColumnDistribution=function(){var a=this.chartOptions,b=this.options,e=[],d=function(a){return(u.seriesTypes[a||"line"].prototype.pointArrayMap||[0]).length},g=a&&a.chart&&a.chart.type,m=[],c=[],k=0;b=b&&b.seriesMapping||a&&a.series&&a.series.map(function(){return{x:0}})|| +[];var p;(a&&a.series||[]).forEach(function(a){m.push(d(a.type||g))});b.forEach(function(a){e.push(a.x||0)});0===e.length&&e.push(0);b.forEach(function(b){var e=new D,y=m[k]||d(g),q=(a&&a.series||[])[k]||{},f=u.seriesTypes[q.type||g||"line"].prototype.pointArrayMap,l=f||["y"];(h(b.x)||q.isCartesian||!f)&&e.addColumnReader(b.x,"x");G(b,function(a,b){"x"!==b&&e.addColumnReader(a,b)});for(p=0;p +B||B>l?(++B,k=""):(!isNaN(parseFloat(k))&&isFinite(k)?(k=parseFloat(k),m("number")):isNaN(Date.parse(k))?m("string"):(k=k.replace(/\//g,"-"),m("date")),h.lengthq[","]?";":",";m.decimalPoint||(m.decimalPoint=b>e?".":",",g.decimalRegex=new RegExp("^(-?[0-9]+)"+ +m.decimalPoint+"([0-9]+)$"));return d}function d(a,b){var d=[],e=0,c=!1,f=[],k=[],n;if(!b||b>a.length)b=a.length;for(;ep[n]?"YY":"YYYY":12=p[n]?(d[n]="dd",c=!0):d[n].length|| +(d[n]="mm")))}if(c){for(n=0;na)a=0;if(!f||f>=c.length)f=c.length-1;if(m.itemDelimiter)var x=m.itemDelimiter;else x=null,x=e(c);var v=0;for(r=a;r<=f;r++)"#"===c[r][0]?v++:b(c[r],r-a-v);m.columnTypes&&0!==m.columnTypes.length||!w.length||!w[0].length||"date"!==w[0][1]||m.dateFormat||(m.dateFormat=d(h[0]));this.dataFound()}return h}; +f.prototype.parseTable=function(){var a=this.options,b=a.table,e=this.columns||[],d=a.startRow||0,g=a.endRow||Number.MAX_VALUE,m=a.startColumn||0,c=a.endColumn||Number.MAX_VALUE;b&&("string"===typeof b&&(b=J.getElementById(b)),[].forEach.call(b.getElementsByTagName("tr"),function(a,b){b>=d&&b<=g&&[].forEach.call(a.children,function(a,g){var f=e[g-m],k=1;if(("TD"===a.tagName||"TH"===a.tagName)&&g>=m&&g<=c)for(e[g-m]||(e[g-m]=[]),e[g-m][b-d]=a.innerHTML;b-d>=k&&void 0===f[b-d-k];)f[b-d-k]=null,k++})}), +this.dataFound());return e};f.prototype.fetchLiveData=function(){function a(p){function l(k,l,q){function h(){m&&e.liveDataURL===k&&(b.liveDataTimeout=setTimeout(a,f))}if(!k||0!==k.indexOf("http"))return k&&d.error&&d.error("Invalid URL"),!1;p&&(clearTimeout(b.liveDataTimeout),e.liveDataURL=k);c.ajax({url:k,dataType:q||"json",success:function(a){e&&e.series&&l(a);h()},error:function(a,b){3>++g&&h();return d.error&&d.error(b,a)}});return!0}l(k.csvURL,function(a){e.update({data:{csv:a}})},"text")|| +l(k.rowsURL,function(a){e.update({data:{rows:a}})})||l(k.columnsURL,function(a){e.update({data:{columns:a}})})}var b=this,e=this.chart,d=this.options,g=0,m=d.enablePolling,f=1E3*(d.dataRefreshRate||2),k=A(d);if(!this.hasURLOption(d))return!1;1E3>f&&(f=1E3);delete d.csvURL;delete d.rowsURL;delete d.columnsURL;a(!0);return this.hasURLOption(d)};f.prototype.parseGoogleSpreadsheet=function(){function a(b){var g=["https://spreadsheets.google.com/feeds/cells",d,m,"public/values?alt=json"].join("/");c.ajax({url:g, +dataType:"json",success:function(d){b(d);e.enablePolling&&setTimeout(function(){a(b)},1E3*(e.dataRefreshRate||2))},error:function(a,b){return e.error&&e.error(b,a)}})}var b=this,e=this.options,d=e.googleSpreadsheetKey,g=this.chart,m=e.googleSpreadsheetWorksheet||1,f=e.startRow||0,k=e.endRow||Number.MAX_VALUE,p=e.startColumn||0,l=e.endColumn||Number.MAX_VALUE,h=1E3*(e.dataRefreshRate||2);4E3>h&&(h=4E3);d&&(delete e.googleSpreadsheetKey,a(function(a){var d=[];a=a.feed.entry;var e=(a||[]).length,m=0, +c;if(!a||0===a.length)return!1;for(c=0;c=p&&c<=l&&(d[c-p]=[]);for(c=0;c=p&&y<=l&&m>=f&&m<=k){var r=h.gs$cell||h.content;h=null;r.numericValue?h=0<=r.$t.indexOf("/")||0<=r.$t.indexOf("-")?r.$t:0a[g+1])):(t&&t.length&&(k=this.parseDate(q)),f&&z(k)&&"float"!== +u?(p[g]=q,a[g]=k,a.isDatetime=!0,"undefined"!==typeof a[g+1]&&(q=k>a[g+1],q!==h&&"undefined"!==typeof h&&(this.alternativeFormat?(this.dateFormat=this.alternativeFormat,g=a.length,this.alternativeFormat=this.dateFormats[this.dateFormat].alternative):a.unsorted=!0),h=q)):(a[g]=""===t?null:t,0!==g&&(a.isDatetime||a.isNumeric)&&(a.mixed=!0)))}f&&a.mixed&&(d[b]=e[b]);if(f&&h&&this.options.sort)for(b=0;b} + */ /** + * The data type expected. + * @name Highcharts.AjaxSettingsObject#dataType + * @type {"json"|"xml"|"text"|"octet"} + */ /** + * Function to call on error. + * @name Highcharts.AjaxSettingsObject#error + * @type {Function} + */ /** + * The headers; keyed on header name. + * @name Highcharts.AjaxSettingsObject#headers + * @type {Highcharts.Dictionary} + */ /** + * Function to call on success. + * @name Highcharts.AjaxSettingsObject#success + * @type {Function} + */ /** + * The verb to use. + * @name Highcharts.AjaxSettingsObject#type + * @type {"GET"|"POST"|"UPDATE"|"DELETE"} + */ /** + * The URL to call. + * @name Highcharts.AjaxSettingsObject#url + * @type {string} + */ + /** + * Perform an Ajax call. + * + * @function Highcharts.ajax + * + * @param {Partial} attr + * The Ajax settings to use. + * + * @return {false|undefined} + * Returns false, if error occured. + */ + H.ajax = function (attr) { + var options = merge(true, { + url: false, + type: 'get', + dataType: 'json', + success: false, + error: false, + data: false, + headers: {} + }, attr), headers = { + json: 'application/json', + xml: 'application/xml', + text: 'text/plain', + octet: 'application/octet-stream' + }, r = new XMLHttpRequest(); + /** + * @private + * @param {XMLHttpRequest} xhr - Internal request object. + * @param {string|Error} err - Occured error. + * @return {void} + */ + function handleError(xhr, err) { + if (options.error) { + options.error(xhr, err); + } + else { + // @todo Maybe emit a highcharts error event here + } + } + if (!options.url) { + return false; + } + r.open(options.type.toUpperCase(), options.url, true); + if (!options.headers['Content-Type']) { + r.setRequestHeader('Content-Type', headers[options.dataType] || headers.text); + } + objectEach(options.headers, function (val, key) { + r.setRequestHeader(key, val); + }); + // @todo lacking timeout handling + r.onreadystatechange = function () { + var res; + if (r.readyState === 4) { + if (r.status === 200) { + res = r.responseText; + if (options.dataType === 'json') { + try { + res = JSON.parse(res); + } + catch (e) { + return handleError(r, e); + } + } + return options.success && options.success(res); + } + handleError(r, r.responseText); + } + }; + try { + options.data = JSON.stringify(options.data); + } + catch (e) { + // empty + } + r.send(options.data || true); + }; + /** + * Get a JSON resource over XHR, also supporting CORS without preflight. + * + * @function Highcharts.getJSON + * @param {string} url + * The URL to load. + * @param {Function} success + * The success callback. For error handling, use the `Highcharts.ajax` + * function instead. + * @return {void} + */ + H.getJSON = function (url, success) { + H.ajax({ + url: url, + success: success, + dataType: 'json', + headers: { + // Override the Content-Type to avoid preflight problems with CORS + // in the Highcharts demos + 'Content-Type': 'text/plain' + } + }); + }; + + }); + _registerModule(_modules, 'modules/data.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['parts/Globals.js'], _modules['parts/Point.js']], function (Highcharts, U, H, Point) { + /* * + * + * Data module + * + * (c) 2012-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Callback function to modify the CSV before parsing it by the data module. + * + * @callback Highcharts.DataBeforeParseCallbackFunction + * + * @param {string} csv + * The CSV to modify. + * + * @return {string} + * The CSV to parse. + */ + /** + * Callback function that gets called after parsing data. + * + * @callback Highcharts.DataCompleteCallbackFunction + * + * @param {Highcharts.Options} chartOptions + * The chart options that were used. + */ + /** + * Callback function that returns the correspondig Date object to a match. + * + * @callback Highcharts.DataDateFormatCallbackFunction + * + * @param {Array} match + * + * @return {number} + */ + /** + * Structure for alternative date formats to parse. + * + * @interface Highcharts.DataDateFormatObject + */ /** + * @name Highcharts.DataDateFormatObject#alternative + * @type {string|undefined} + */ /** + * @name Highcharts.DataDateFormatObject#parser + * @type {Highcharts.DataDateFormatCallbackFunction} + */ /** + * @name Highcharts.DataDateFormatObject#regex + * @type {global.RegExp} + */ + /** + * Possible types for a data item in a column or row. + * + * @typedef {number|string|null} Highcharts.DataValueType + */ + /** + * Callback function to parse string representations of dates into + * JavaScript timestamps (milliseconds since 1.1.1970). + * + * @callback Highcharts.DataParseDateCallbackFunction + * + * @param {string} dateValue + * + * @return {number} + * Timestamp (milliseconds since 1.1.1970) as integer for Date class. + */ + /** + * Callback function to access the parsed columns, the two-dimentional + * input data array directly, before they are interpreted into series + * data and categories. + * + * @callback Highcharts.DataParsedCallbackFunction + * + * @param {Array>} columns + * The parsed columns by the data module. + * + * @return {boolean|undefined} + * Return `false` to stop completion, or call `this.complete()` to + * continue async. + */ + var addEvent = U.addEvent, defined = U.defined, extend = U.extend, fireEvent = U.fireEvent, isNumber = U.isNumber, merge = U.merge, objectEach = U.objectEach, pick = U.pick, splat = U.splat; + // Utilities + var Chart = H.Chart, win = H.win, doc = win.document; + /** + * The Data module provides a simplified interface for adding data to + * a chart from sources like CVS, HTML tables or grid views. See also + * the [tutorial article on the Data module]( + * https://www.highcharts.com/docs/working-with-data/data-module). + * + * It requires the `modules/data.js` file to be loaded. + * + * Please note that the default way of adding data in Highcharts, without + * the need of a module, is through the [series._type_.data](#series.line.data) + * option. + * + * @sample {highcharts} highcharts/demo/column-parsed/ + * HTML table + * @sample {highcharts} highcharts/data/csv/ + * CSV + * + * @since 4.0 + * @requires modules/data + * @apioption data + */ + /** + * A callback function to modify the CSV before parsing it. Return the modified + * string. + * + * @sample {highcharts} highcharts/demo/line-ajax/ + * Modify CSV before parse + * + * @type {Highcharts.DataBeforeParseCallbackFunction} + * @since 6.1 + * @apioption data.beforeParse + */ + /** + * A two-dimensional array representing the input data on tabular form. + * This input can be used when the data is already parsed, for example + * from a grid view component. Each cell can be a string or number. + * If not switchRowsAndColumns is set, the columns are interpreted as + * series. + * + * @see [data.rows](#data.rows) + * + * @sample {highcharts} highcharts/data/columns/ + * Columns + * + * @type {Array>} + * @since 4.0 + * @apioption data.columns + */ + /** + * The callback that is evaluated when the data is finished loading, + * optionally from an external source, and parsed. The first argument + * passed is a finished chart options object, containing the series. + * These options can be extended with additional options and passed + * directly to the chart constructor. + * + * @see [data.parsed](#data.parsed) + * + * @sample {highcharts} highcharts/data/complete/ + * Modify data on complete + * + * @type {Highcharts.DataCompleteCallbackFunction} + * @since 4.0 + * @apioption data.complete + */ + /** + * A comma delimited string to be parsed. Related options are [startRow]( + * #data.startRow), [endRow](#data.endRow), [startColumn](#data.startColumn) + * and [endColumn](#data.endColumn) to delimit what part of the table + * is used. The [lineDelimiter](#data.lineDelimiter) and [itemDelimiter]( + * #data.itemDelimiter) options define the CSV delimiter formats. + * + * The built-in CSV parser doesn't support all flavours of CSV, so in + * some cases it may be necessary to use an external CSV parser. See + * [this example](https://jsfiddle.net/highcharts/u59176h4/) of parsing + * CSV through the MIT licensed [Papa Parse](http://papaparse.com/) + * library. + * + * @sample {highcharts} highcharts/data/csv/ + * Data from CSV + * + * @type {string} + * @since 4.0 + * @apioption data.csv + */ + /** + * Which of the predefined date formats in Date.prototype.dateFormats + * to use to parse date values. Defaults to a best guess based on what + * format gives valid and ordered dates. Valid options include: `YYYY/mm/dd`, + * `dd/mm/YYYY`, `mm/dd/YYYY`, `dd/mm/YY`, `mm/dd/YY`. + * + * @see [data.parseDate](#data.parseDate) + * + * @sample {highcharts} highcharts/data/dateformat-auto/ + * Best guess date format + * + * @type {string} + * @since 4.0 + * @validvalue ["YYYY/mm/dd", "dd/mm/YYYY", "mm/dd/YYYY", "dd/mm/YYYY", + * "dd/mm/YY", "mm/dd/YY"] + * @apioption data.dateFormat + */ + /** + * The decimal point used for parsing numbers in the CSV. + * + * If both this and data.delimiter is set to `undefined`, the parser will + * attempt to deduce the decimal point automatically. + * + * @sample {highcharts} highcharts/data/delimiters/ + * Comma as decimal point + * + * @type {string} + * @default . + * @since 4.1.0 + * @apioption data.decimalPoint + */ + /** + * In tabular input data, the last column (indexed by 0) to use. Defaults + * to the last column containing data. + * + * @sample {highcharts} highcharts/data/start-end/ + * Limited data + * + * @type {number} + * @since 4.0 + * @apioption data.endColumn + */ + /** + * In tabular input data, the last row (indexed by 0) to use. Defaults + * to the last row containing data. + * + * @sample {highcharts} highcharts/data/start-end/ + * Limited data + * + * @type {number} + * @since 4.0.4 + * @apioption data.endRow + */ + /** + * Whether to use the first row in the data set as series names. + * + * @sample {highcharts} highcharts/data/start-end/ + * Don't get series names from the CSV + * @sample {highstock} highcharts/data/start-end/ + * Don't get series names from the CSV + * + * @type {boolean} + * @default true + * @since 4.1.0 + * @product highcharts highstock gantt + * @apioption data.firstRowAsNames + */ + /** + * The key for a Google Spreadsheet to load. See [general information + * on GS](https://developers.google.com/gdata/samples/spreadsheet_sample). + * + * @sample {highcharts} highcharts/data/google-spreadsheet/ + * Load a Google Spreadsheet + * + * @type {string} + * @since 4.0 + * @apioption data.googleSpreadsheetKey + */ + /** + * The Google Spreadsheet worksheet to use in combination with + * [googleSpreadsheetKey](#data.googleSpreadsheetKey). The available id's from + * your sheet can be read from `https://spreadsheets.google.com/feeds/worksheets/{key}/public/basic`. + * + * @sample {highcharts} highcharts/data/google-spreadsheet/ + * Load a Google Spreadsheet + * + * @type {string} + * @since 4.0 + * @apioption data.googleSpreadsheetWorksheet + */ + /** + * Item or cell delimiter for parsing CSV. Defaults to the tab character + * `\t` if a tab character is found in the CSV string, if not it defaults + * to `,`. + * + * If this is set to false or undefined, the parser will attempt to deduce + * the delimiter automatically. + * + * @sample {highcharts} highcharts/data/delimiters/ + * Delimiters + * + * @type {string} + * @since 4.0 + * @apioption data.itemDelimiter + */ + /** + * Line delimiter for parsing CSV. + * + * @sample {highcharts} highcharts/data/delimiters/ + * Delimiters + * + * @type {string} + * @default \n + * @since 4.0 + * @apioption data.lineDelimiter + */ + /** + * A callback function to access the parsed columns, the two-dimentional + * input data array directly, before they are interpreted into series + * data and categories. Return `false` to stop completion, or call + * `this.complete()` to continue async. + * + * @see [data.complete](#data.complete) + * + * @sample {highcharts} highcharts/data/parsed/ + * Modify data after parse + * + * @type {Highcharts.DataParsedCallbackFunction} + * @since 4.0 + * @apioption data.parsed + */ + /** + * A callback function to parse string representations of dates into + * JavaScript timestamps. Should return an integer timestamp on success. + * + * @see [dateFormat](#data.dateFormat) + * + * @type {Highcharts.DataParseDateCallbackFunction} + * @since 4.0 + * @apioption data.parseDate + */ + /** + * The same as the columns input option, but defining rows intead of + * columns. + * + * @see [data.columns](#data.columns) + * + * @sample {highcharts} highcharts/data/rows/ + * Data in rows + * + * @type {Array>} + * @since 4.0 + * @apioption data.rows + */ + /** + * An array containing dictionaries for each series. A dictionary exists of + * Point property names as the key and the CSV column index as the value. + * + * @sample {highcharts} highcharts/data/seriesmapping-label/ + * Label from data set + * + * @type {Array>} + * @since 4.0.4 + * @apioption data.seriesMapping + */ + /** + * In tabular input data, the first column (indexed by 0) to use. + * + * @sample {highcharts} highcharts/data/start-end/ + * Limited data + * + * @type {number} + * @default 0 + * @since 4.0 + * @apioption data.startColumn + */ + /** + * In tabular input data, the first row (indexed by 0) to use. + * + * @sample {highcharts} highcharts/data/start-end/ + * Limited data + * + * @type {number} + * @default 0 + * @since 4.0 + * @apioption data.startRow + */ + /** + * Switch rows and columns of the input data, so that `this.columns` + * effectively becomes the rows of the data set, and the rows are interpreted + * as series. + * + * @sample {highcharts} highcharts/data/switchrowsandcolumns/ + * Switch rows and columns + * + * @type {boolean} + * @default false + * @since 4.0 + * @apioption data.switchRowsAndColumns + */ + /** + * An HTML table or the id of such to be parsed as input data. Related + * options are `startRow`, `endRow`, `startColumn` and `endColumn` to + * delimit what part of the table is used. + * + * @sample {highcharts} highcharts/demo/column-parsed/ + * Parsed table + * + * @type {string|global.HTMLElement} + * @since 4.0 + * @apioption data.table + */ + /** + * An URL to a remote CSV dataset. Will be fetched when the chart is created + * using Ajax. + * + * @sample highcharts/data/livedata-columns + * Categorized bar chart with CSV and live polling + * @sample highcharts/data/livedata-csv + * Time based line chart with CSV and live polling + * + * @type {string} + * @apioption data.csvURL + */ + /** + * A URL to a remote JSON dataset, structured as a row array. + * Will be fetched when the chart is created using Ajax. + * + * @sample highcharts/data/livedata-rows + * Rows with live polling + * + * @type {string} + * @apioption data.rowsURL + */ + /** + * A URL to a remote JSON dataset, structured as a column array. + * Will be fetched when the chart is created using Ajax. + * + * @sample highcharts/data/livedata-columns + * Columns with live polling + * + * @type {string} + * @apioption data.columnsURL + */ + /** + * Sets the refresh rate for data polling when importing remote dataset by + * setting [data.csvURL](data.csvURL), [data.rowsURL](data.rowsURL), + * [data.columnsURL](data.columnsURL), or + * [data.googleSpreadsheetKey](data.googleSpreadsheetKey). + * + * Note that polling must be enabled by setting + * [data.enablePolling](data.enablePolling) to true. + * + * The value is the number of seconds between pollings. + * It cannot be set to less than 1 second. + * + * @sample highcharts/demo/live-data + * Live data with user set refresh rate + * + * @default 1 + * @type {number} + * @apioption data.dataRefreshRate + */ + /** + * Enables automatic refetching of remote datasets every _n_ seconds (defined by + * setting [data.dataRefreshRate](data.dataRefreshRate)). + * + * Only works when either [data.csvURL](data.csvURL), + * [data.rowsURL](data.rowsURL), [data.columnsURL](data.columnsURL), or + * [data.googleSpreadsheetKey](data.googleSpreadsheetKey). + * + * @sample highcharts/demo/live-data + * Live data + * @sample highcharts/data/livedata-columns + * Categorized bar chart with CSV and live polling + * + * @type {boolean} + * @default false + * @apioption data.enablePolling + */ + /* eslint-disable valid-jsdoc */ + /** + * The Data class + * + * @requires module:modules/data + * + * @class + * @name Highcharts.Data + * + * @param {Highcharts.DataOptions} dataOptions + * + * @param {Highcharts.Options} [chartOptions] + * + * @param {Highcharts.Chart} [chart] + */ + var Data = /** @class */ (function () { + function Data(dataOptions, chartOptions, chart) { + this.chart = void 0; + this.chartOptions = void 0; + this.firstRowAsNames = void 0; + this.rawColumns = void 0; + this.options = void 0; + /** + * A collection of available date formats, extendable from the outside to + * support custom date formats. + * + * @name Highcharts.Data#dateFormats + * @type {Highcharts.Dictionary} + */ + this.dateFormats = { + 'YYYY/mm/dd': { + regex: /^([0-9]{4})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{1,2})$/, + parser: function (match) { + return (match ? + Date.UTC(+match[1], match[2] - 1, +match[3]) : + NaN); + } + }, + 'dd/mm/YYYY': { + regex: /^([0-9]{1,2})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{4})$/, + parser: function (match) { + return (match ? + Date.UTC(+match[3], match[2] - 1, +match[1]) : + NaN); + }, + alternative: 'mm/dd/YYYY' // different format with the same regex + }, + 'mm/dd/YYYY': { + regex: /^([0-9]{1,2})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{4})$/, + parser: function (match) { + return (match ? + Date.UTC(+match[3], match[1] - 1, +match[2]) : + NaN); + } + }, + 'dd/mm/YY': { + regex: /^([0-9]{1,2})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{2})$/, + parser: function (match) { + if (!match) { + return NaN; + } + var year = +match[3], d = new Date(); + if (year > (d.getFullYear() - 2000)) { + year += 1900; + } + else { + year += 2000; + } + return Date.UTC(year, match[2] - 1, +match[1]); + }, + alternative: 'mm/dd/YY' // different format with the same regex + }, + 'mm/dd/YY': { + regex: /^([0-9]{1,2})[\-\/\.]([0-9]{1,2})[\-\/\.]([0-9]{2})$/, + parser: function (match) { + return (match ? + Date.UTC(+match[3] + 2000, match[1] - 1, +match[2]) : + NaN); + } + } + }; + this.init(dataOptions, chartOptions, chart); + } + /** + * Initialize the Data object with the given options + * + * @private + * @function Highcharts.Data#init + * @param {Highcharts.DataOptions} options + * @param {Highcharts.Options} [chartOptions] + * @param {Highcharts.Chart} [chart] + */ + Data.prototype.init = function (options, chartOptions, chart) { + var decimalPoint = options.decimalPoint, hasData; + if (chartOptions) { + this.chartOptions = chartOptions; + } + if (chart) { + this.chart = chart; + } + if (decimalPoint !== '.' && decimalPoint !== ',') { + decimalPoint = void 0; + } + this.options = options; + this.columns = (options.columns || + this.rowsToColumns(options.rows) || + []); + this.firstRowAsNames = pick(options.firstRowAsNames, this.firstRowAsNames, true); + this.decimalRegex = (decimalPoint && + new RegExp('^(-?[0-9]+)' + decimalPoint + '([0-9]+)$')); + // This is a two-dimensional array holding the raw, trimmed string + // values with the same organisation as the columns array. It makes it + // possible for example to revert from interpreted timestamps to + // string-based categories. + this.rawColumns = []; + // No need to parse or interpret anything + if (this.columns.length) { + this.dataFound(); + hasData = true; + } + if (this.hasURLOption(options)) { + clearTimeout(this.liveDataTimeout); + hasData = false; + } + if (!hasData) { + // Fetch live data + hasData = this.fetchLiveData(); + } + if (!hasData) { + // Parse a CSV string if options.csv is given. The parseCSV function + // returns a columns array, if it has no length, we have no data + hasData = Boolean(this.parseCSV().length); + } + if (!hasData) { + // Parse a HTML table if options.table is given + hasData = Boolean(this.parseTable().length); + } + if (!hasData) { + // Parse a Google Spreadsheet + hasData = this.parseGoogleSpreadsheet(); + } + if (!hasData && options.afterComplete) { + options.afterComplete(); + } + }; + Data.prototype.hasURLOption = function (options) { + return Boolean(options && + (options.rowsURL || options.csvURL || options.columnsURL)); + }; + /** + * Get the column distribution. For example, a line series takes a single + * column for Y values. A range series takes two columns for low and high + * values respectively, and an OHLC series takes four columns. + * + * @function Highcharts.Data#getColumnDistribution + */ + Data.prototype.getColumnDistribution = function () { + var chartOptions = this.chartOptions, options = this.options, xColumns = [], getValueCount = function (type) { + return (H.seriesTypes[type || 'line'].prototype + .pointArrayMap || + [0]).length; + }, getPointArrayMap = function (type) { + return H.seriesTypes[type || 'line'] + .prototype.pointArrayMap; + }, globalType = (chartOptions && + chartOptions.chart && + chartOptions.chart.type), individualCounts = [], seriesBuilders = [], seriesIndex = 0, + // If no series mapping is defined, check if the series array is + // defined with types. + seriesMapping = ((options && options.seriesMapping) || + (chartOptions && + chartOptions.series && + chartOptions.series.map(function () { + return { x: 0 }; + })) || + []), i; + ((chartOptions && chartOptions.series) || []).forEach(function (series) { + individualCounts.push(getValueCount(series.type || globalType)); + }); + // Collect the x-column indexes from seriesMapping + seriesMapping.forEach(function (mapping) { + xColumns.push(mapping.x || 0); + }); + // If there are no defined series with x-columns, use the first column + // as x column + if (xColumns.length === 0) { + xColumns.push(0); + } + // Loop all seriesMappings and constructs SeriesBuilders from + // the mapping options. + seriesMapping.forEach(function (mapping) { + var builder = new SeriesBuilder(), numberOfValueColumnsNeeded = individualCounts[seriesIndex] || + getValueCount(globalType), seriesArr = (chartOptions && chartOptions.series) || [], series = seriesArr[seriesIndex] || {}, defaultPointArrayMap = getPointArrayMap(series.type || globalType), pointArrayMap = defaultPointArrayMap || ['y']; + if ( + // User-defined x.mapping + defined(mapping.x) || + // All non cartesian don't need 'x' + series.isCartesian || + // Except pie series: + !defaultPointArrayMap) { + // Add an x reader from the x property or from an undefined + // column if the property is not set. It will then be auto + // populated later. + builder.addColumnReader(mapping.x, 'x'); + } + // Add all column mappings + objectEach(mapping, function (val, name) { + if (name !== 'x') { + builder.addColumnReader(val, name); + } + }); + // Add missing columns + for (i = 0; i < numberOfValueColumnsNeeded; i++) { + if (!builder.hasReader(pointArrayMap[i])) { + // Create and add a column reader for the next free column + // index + builder.addColumnReader(void 0, pointArrayMap[i]); + } + } + seriesBuilders.push(builder); + seriesIndex++; + }); + var globalPointArrayMap = getPointArrayMap(globalType); + if (typeof globalPointArrayMap === 'undefined') { + globalPointArrayMap = ['y']; + } + this.valueCount = { + global: getValueCount(globalType), + xColumns: xColumns, + individual: individualCounts, + seriesBuilders: seriesBuilders, + globalPointArrayMap: globalPointArrayMap + }; + }; + /** + * When the data is parsed into columns, either by CSV, table, GS or direct + * input, continue with other operations. + * + * @private + * @function Highcharts.Data#dataFound + */ + Data.prototype.dataFound = function () { + if (this.options.switchRowsAndColumns) { + this.columns = this.rowsToColumns(this.columns); + } + // Interpret the info about series and columns + this.getColumnDistribution(); + // Interpret the values into right types + this.parseTypes(); + // Handle columns if a handleColumns callback is given + if (this.parsed() !== false) { + // Complete if a complete callback is given + this.complete(); + } + }; + /** + * Parse a CSV input string + * + * @function Highcharts.Data#parseCSV + * + * @param {Highcharts.DataOptions} [inOptions] + * + * @return {Array>} + */ + Data.prototype.parseCSV = function (inOptions) { + var self = this, options = inOptions || this.options, csv = options.csv, columns, startRow = (typeof options.startRow !== 'undefined' && options.startRow ? + options.startRow : + 0), endRow = options.endRow || Number.MAX_VALUE, startColumn = (typeof options.startColumn !== 'undefined' && + options.startColumn) ? options.startColumn : 0, endColumn = options.endColumn || Number.MAX_VALUE, itemDelimiter, lines, rowIt = 0, + // activeRowNo = 0, + dataTypes = [], + // We count potential delimiters in the prepass, and use the + // result as the basis of half-intelligent guesses. + potDelimiters = { + ',': 0, + ';': 0, + '\t': 0 + }; + columns = this.columns = []; + /* + This implementation is quite verbose. It will be shortened once + it's stable and passes all the test. + + It's also not written with speed in mind, instead everything is + very seggregated, and there a several redundant loops. + This is to make it easier to stabilize the code initially. + + We do a pre-pass on the first 4 rows to make some intelligent + guesses on the set. Guessed delimiters are in this pass counted. + + Auto detecting delimiters + - If we meet a quoted string, the next symbol afterwards + (that's not \s, \t) is the delimiter + - If we meet a date, the next symbol afterwards is the delimiter + + Date formats + - If we meet a column with date formats, check all of them to + see if one of the potential months crossing 12. If it does, + we now know the format + + It would make things easier to guess the delimiter before + doing the actual parsing. + + General rules: + - Quoting is allowed, e.g: "Col 1",123,321 + - Quoting is optional, e.g.: Col1,123,321 + - Doubble quoting is escaping, e.g. "Col ""Hello world""",123 + - Spaces are considered part of the data: Col1 ,123 + - New line is always the row delimiter + - Potential column delimiters are , ; \t + - First row may optionally contain headers + - The last row may or may not have a row delimiter + - Comments are optionally supported, in which case the comment + must start at the first column, and the rest of the line will + be ignored + */ + /** + * Parse a single row. + * @private + */ + function parseRow(columnStr, rowNumber, noAdd, callbacks) { + var i = 0, c = '', cl = '', cn = '', token = '', actualColumn = 0, column = 0; + /** + * @private + */ + function read(j) { + c = columnStr[j]; + cl = columnStr[j - 1]; + cn = columnStr[j + 1]; + } + /** + * @private + */ + function pushType(type) { + if (dataTypes.length < column + 1) { + dataTypes.push([type]); + } + if (dataTypes[column][dataTypes[column].length - 1] !== type) { + dataTypes[column].push(type); + } + } + /** + * @private + */ + function push() { + if (startColumn > actualColumn || actualColumn > endColumn) { + // Skip this column, but increment the column count (#7272) + ++actualColumn; + token = ''; + return; + } + if (!isNaN(parseFloat(token)) && isFinite(token)) { + token = parseFloat(token); + pushType('number'); + } + else if (!isNaN(Date.parse(token))) { + token = token.replace(/\//g, '-'); + pushType('date'); + } + else { + pushType('string'); + } + if (columns.length < column + 1) { + columns.push([]); + } + if (!noAdd) { + // Don't push - if there's a varrying amount of columns + // for each row, pushing will skew everything down n slots + columns[column][rowNumber] = token; + } + token = ''; + ++column; + ++actualColumn; + } + if (!columnStr.trim().length) { + return; + } + if (columnStr.trim()[0] === '#') { + return; + } + for (; i < columnStr.length; i++) { + read(i); + // Quoted string + if (c === '#') { + // The rest of the row is a comment + push(); + return; + } + if (c === '"') { + read(++i); + while (i < columnStr.length) { + if (c === '"' && cl !== '"' && cn !== '"') { + break; + } + if (c !== '"' || (c === '"' && cl !== '"')) { + token += c; + } + read(++i); + } + // Perform "plugin" handling + } + else if (callbacks && callbacks[c]) { + if (callbacks[c](c, token)) { + push(); + } + // Delimiter - push current token + } + else if (c === itemDelimiter) { + push(); + // Actual column data + } + else { + token += c; + } + } + push(); + } + /** + * Attempt to guess the delimiter. We do a separate parse pass here + * because we need to count potential delimiters softly without making + * any assumptions. + * @private + */ + function guessDelimiter(lines) { + var points = 0, commas = 0, guessed = false; + lines.some(function (columnStr, i) { + var inStr = false, c, cn, cl, token = ''; + // We should be able to detect dateformats within 13 rows + if (i > 13) { + return true; + } + for (var j = 0; j < columnStr.length; j++) { + c = columnStr[j]; + cn = columnStr[j + 1]; + cl = columnStr[j - 1]; + if (c === '#') { + // Skip the rest of the line - it's a comment + return; + } + if (c === '"') { + if (inStr) { + if (cl !== '"' && cn !== '"') { + while (cn === ' ' && j < columnStr.length) { + cn = columnStr[++j]; + } + // After parsing a string, the next non-blank + // should be a delimiter if the CSV is properly + // formed. + if (typeof potDelimiters[cn] !== 'undefined') { + potDelimiters[cn]++; + } + inStr = false; + } + } + else { + inStr = true; + } + } + else if (typeof potDelimiters[c] !== 'undefined') { + token = token.trim(); + if (!isNaN(Date.parse(token))) { + potDelimiters[c]++; + } + else if (isNaN(token) || + !isFinite(token)) { + potDelimiters[c]++; + } + token = ''; + } + else { + token += c; + } + if (c === ',') { + commas++; + } + if (c === '.') { + points++; + } + } + }); + // Count the potential delimiters. + // This could be improved by checking if the number of delimiters + // equals the number of columns - 1 + if (potDelimiters[';'] > potDelimiters[',']) { + guessed = ';'; + } + else if (potDelimiters[','] > potDelimiters[';']) { + guessed = ','; + } + else { + // No good guess could be made.. + guessed = ','; + } + // Try to deduce the decimal point if it's not explicitly set. + // If both commas or points is > 0 there is likely an issue + if (!options.decimalPoint) { + if (points > commas) { + options.decimalPoint = '.'; + } + else { + options.decimalPoint = ','; + } + // Apply a new decimal regex based on the presumed decimal sep. + self.decimalRegex = new RegExp('^(-?[0-9]+)' + + options.decimalPoint + + '([0-9]+)$'); + } + return guessed; + } + /** + * Tries to guess the date format + * - Check if either month candidate exceeds 12 + * - Check if year is missing (use current year) + * - Check if a shortened year format is used (e.g. 1/1/99) + * - If no guess can be made, the user must be prompted + * data is the data to deduce a format based on + * @private + */ + function deduceDateFormat(data, limit) { + var format = 'YYYY/mm/dd', thing, guessedFormat = [], calculatedFormat, i = 0, madeDeduction = false, + // candidates = {}, + stable = [], max = [], j; + if (!limit || limit > data.length) { + limit = data.length; + } + for (; i < limit; i++) { + if (typeof data[i] !== 'undefined' && + data[i] && data[i].length) { + thing = data[i] + .trim() + .replace(/\//g, ' ') + .replace(/\-/g, ' ') + .replace(/\./g, ' ') + .split(' '); + guessedFormat = [ + '', + '', + '' + ]; + for (j = 0; j < thing.length; j++) { + if (j < guessedFormat.length) { + thing[j] = parseInt(thing[j], 10); + if (thing[j]) { + max[j] = (!max[j] || max[j] < thing[j]) ? + thing[j] : + max[j]; + if (typeof stable[j] !== 'undefined') { + if (stable[j] !== thing[j]) { + stable[j] = false; + } + } + else { + stable[j] = thing[j]; + } + if (thing[j] > 31) { + if (thing[j] < 100) { + guessedFormat[j] = 'YY'; + } + else { + guessedFormat[j] = 'YYYY'; + } + // madeDeduction = true; + } + else if (thing[j] > 12 && + thing[j] <= 31) { + guessedFormat[j] = 'dd'; + madeDeduction = true; + } + else if (!guessedFormat[j].length) { + guessedFormat[j] = 'mm'; + } + } + } + } + } + } + if (madeDeduction) { + // This handles a few edge cases with hard to guess dates + for (j = 0; j < stable.length; j++) { + if (stable[j] !== false) { + if (max[j] > 12 && + guessedFormat[j] !== 'YY' && + guessedFormat[j] !== 'YYYY') { + guessedFormat[j] = 'YY'; + } + } + else if (max[j] > 12 && guessedFormat[j] === 'mm') { + guessedFormat[j] = 'dd'; + } + } + // If the middle one is dd, and the last one is dd, + // the last should likely be year. + if (guessedFormat.length === 3 && + guessedFormat[1] === 'dd' && + guessedFormat[2] === 'dd') { + guessedFormat[2] = 'YY'; + } + calculatedFormat = guessedFormat.join('/'); + // If the caculated format is not valid, we need to present an + // error. + if (!(options.dateFormats || self.dateFormats)[calculatedFormat]) { + // This should emit an event instead + fireEvent('deduceDateFailed'); + return format; + } + return calculatedFormat; + } + return format; + } + /** + * @todo + * Figure out the best axis types for the data + * - If the first column is a number, we're good + * - If the first column is a date, set to date/time + * - If the first column is a string, set to categories + * @private + */ + function deduceAxisTypes() { + } + if (csv && options.beforeParse) { + csv = options.beforeParse.call(this, csv); + } + if (csv) { + lines = csv + .replace(/\r\n/g, '\n') // Unix + .replace(/\r/g, '\n') // Mac + .split(options.lineDelimiter || '\n'); + if (!startRow || startRow < 0) { + startRow = 0; + } + if (!endRow || endRow >= lines.length) { + endRow = lines.length - 1; + } + if (options.itemDelimiter) { + itemDelimiter = options.itemDelimiter; + } + else { + itemDelimiter = null; + itemDelimiter = guessDelimiter(lines); + } + var offset = 0; + for (rowIt = startRow; rowIt <= endRow; rowIt++) { + if (lines[rowIt][0] === '#') { + offset++; + } + else { + parseRow(lines[rowIt], rowIt - startRow - offset); + } + } + // //Make sure that there's header columns for everything + // columns.forEach(function (col) { + // }); + deduceAxisTypes(); + if ((!options.columnTypes || options.columnTypes.length === 0) && + dataTypes.length && + dataTypes[0].length && + dataTypes[0][1] === 'date' && + !options.dateFormat) { + options.dateFormat = deduceDateFormat(columns[0]); + } + // lines.forEach(function (line, rowNo) { + // var trimmed = self.trim(line), + // isComment = trimmed.indexOf('#') === 0, + // isBlank = trimmed === '', + // items; + // if ( + // rowNo >= startRow && + // rowNo <= endRow && + // !isComment && !isBlank + // ) { + // items = line.split(itemDelimiter); + // items.forEach(function (item, colNo) { + // if (colNo >= startColumn && colNo <= endColumn) { + // if (!columns[colNo - startColumn]) { + // columns[colNo - startColumn] = []; + // } + // columns[colNo - startColumn][activeRowNo] = item; + // } + // }); + // activeRowNo += 1; + // } + // }); + // + this.dataFound(); + } + return columns; + }; + /** + * Parse a HTML table + * + * @function Highcharts.Data#parseTable + * + * @return {Array>} + */ + Data.prototype.parseTable = function () { + var options = this.options, table = options.table, columns = this.columns || [], startRow = options.startRow || 0, endRow = options.endRow || Number.MAX_VALUE, startColumn = options.startColumn || 0, endColumn = options.endColumn || Number.MAX_VALUE; + if (table) { + if (typeof table === 'string') { + table = doc.getElementById(table); + } + [].forEach.call(table.getElementsByTagName('tr'), function (tr, rowNo) { + if (rowNo >= startRow && rowNo <= endRow) { + [].forEach.call(tr.children, function (item, colNo) { + var row = columns[colNo - startColumn]; + var i = 1; + if ((item.tagName === 'TD' || + item.tagName === 'TH') && + colNo >= startColumn && + colNo <= endColumn) { + if (!columns[colNo - startColumn]) { + columns[colNo - startColumn] = []; + } + columns[colNo - startColumn][rowNo - startRow] = item.innerHTML; + // Loop over all previous indices and make sure + // they are nulls, not undefined. + while (rowNo - startRow >= i && + row[rowNo - startRow - i] === void 0) { + row[rowNo - startRow - i] = null; + i++; + } + } + }); + } + }); + this.dataFound(); // continue + } + return columns; + }; + /** + * Fetch or refetch live data + * + * @function Highcharts.Data#fetchLiveData + * + * @return {boolean} + * The URLs that were tried can be found in the options + */ + Data.prototype.fetchLiveData = function () { + var data = this, chart = this.chart, options = this.options, maxRetries = 3, currentRetries = 0, pollingEnabled = options.enablePolling, updateIntervalMs = (options.dataRefreshRate || 2) * 1000, originalOptions = merge(options); + if (!this.hasURLOption(options)) { + return false; + } + // Do not allow polling more than once a second + if (updateIntervalMs < 1000) { + updateIntervalMs = 1000; + } + delete options.csvURL; + delete options.rowsURL; + delete options.columnsURL; + /** + * @private + */ + function performFetch(initialFetch) { + /** + * Helper function for doing the data fetch + polling. + * @private + */ + function request(url, done, tp) { + if (!url || url.indexOf('http') !== 0) { + if (url && options.error) { + options.error('Invalid URL'); + } + return false; + } + if (initialFetch) { + clearTimeout(data.liveDataTimeout); + chart.liveDataURL = url; + } + /** + * @private + */ + function poll() { + // Poll + if (pollingEnabled && chart.liveDataURL === url) { + // We need to stop doing this if the URL has changed + data.liveDataTimeout = + setTimeout(performFetch, updateIntervalMs); + } + } + Highcharts.ajax({ + url: url, + dataType: tp || 'json', + success: function (res) { + if (chart && chart.series) { + done(res); + } + poll(); + }, + error: function (xhr, text) { + if (++currentRetries < maxRetries) { + poll(); + } + return options.error && options.error(text, xhr); + } + }); + return true; + } + if (!request(originalOptions.csvURL, function (res) { + chart.update({ + data: { + csv: res + } + }); + }, 'text')) { + if (!request(originalOptions.rowsURL, function (res) { + chart.update({ + data: { + rows: res + } + }); + })) { + request(originalOptions.columnsURL, function (res) { + chart.update({ + data: { + columns: res + } + }); + }); + } + } + } + performFetch(true); + return this.hasURLOption(options); + }; + /** + * Parse a Google spreadsheet. + * + * @function Highcharts.Data#parseGoogleSpreadsheet + * + * @return {boolean} + * Always returns false, because it is an intermediate fetch. + */ + Data.prototype.parseGoogleSpreadsheet = function () { + var data = this, options = this.options, googleSpreadsheetKey = options.googleSpreadsheetKey, chart = this.chart, + // use sheet 1 as the default rather than od6 + // as the latter sometimes cause issues (it looks like it can + // be renamed in some cases, ref. a fogbugz case). + worksheet = options.googleSpreadsheetWorksheet || 1, startRow = options.startRow || 0, endRow = options.endRow || Number.MAX_VALUE, startColumn = options.startColumn || 0, endColumn = options.endColumn || Number.MAX_VALUE, refreshRate = (options.dataRefreshRate || 2) * 1000; + if (refreshRate < 4000) { + refreshRate = 4000; + } + /** + * Fetch the actual spreadsheet using XMLHttpRequest. + * @private + */ + function fetchSheet(fn) { + var url = [ + 'https://spreadsheets.google.com/feeds/cells', + googleSpreadsheetKey, + worksheet, + 'public/values?alt=json' + ].join('/'); + Highcharts.ajax({ + url: url, + dataType: 'json', + success: function (json) { + fn(json); + if (options.enablePolling) { + setTimeout(function () { + fetchSheet(fn); + }, (options.dataRefreshRate || 2) * 1000); + } + }, + error: function (xhr, text) { + return options.error && options.error(text, xhr); + } + }); + } + if (googleSpreadsheetKey) { + delete options.googleSpreadsheetKey; + fetchSheet(function (json) { + // Prepare the data from the spreadsheat + var columns = [], cells = json.feed.entry, cell, cellCount = (cells || []).length, colCount = 0, rowCount = 0, val, gr, gc, cellInner, i; + if (!cells || cells.length === 0) { + return false; + } + // First, find the total number of columns and rows that + // are actually filled with data + for (i = 0; i < cellCount; i++) { + cell = cells[i]; + colCount = Math.max(colCount, cell.gs$cell.col); + rowCount = Math.max(rowCount, cell.gs$cell.row); + } + // Set up arrays containing the column data + for (i = 0; i < colCount; i++) { + if (i >= startColumn && i <= endColumn) { + // Create new columns with the length of either + // end-start or rowCount + columns[i - startColumn] = []; + } + } + // Loop over the cells and assign the value to the right + // place in the column arrays + for (i = 0; i < cellCount; i++) { + cell = cells[i]; + gr = cell.gs$cell.row - 1; // rows start at 1 + gc = cell.gs$cell.col - 1; // columns start at 1 + // If both row and col falls inside start and end set the + // transposed cell value in the newly created columns + if (gc >= startColumn && gc <= endColumn && + gr >= startRow && gr <= endRow) { + cellInner = cell.gs$cell || cell.content; + val = null; + if (cellInner.numericValue) { + if (cellInner.$t.indexOf('/') >= 0 || + cellInner.$t.indexOf('-') >= 0) { + // This is a date - for future reference. + val = cellInner.$t; + } + else if (cellInner.$t.indexOf('%') > 0) { + // Percentage + val = parseFloat(cellInner.numericValue) * 100; + } + else { + val = parseFloat(cellInner.numericValue); + } + } + else if (cellInner.$t && cellInner.$t.length) { + val = cellInner.$t; + } + columns[gc - startColumn][gr - startRow] = val; + } + } + // Insert null for empty spreadsheet cells (#5298) + columns.forEach(function (column) { + for (i = 0; i < column.length; i++) { + if (typeof column[i] === 'undefined') { + column[i] = null; + } + } + }); + if (chart && chart.series) { + chart.update({ + data: { + columns: columns + } + }); + } + else { // #8245 + data.columns = columns; + data.dataFound(); + } + }); + } + // This is an intermediate fetch, so always return false. + return false; + }; + /** + * Trim a string from whitespaces. + * + * @function Highcharts.Data#trim + * + * @param {string} str + * String to trim + * + * @param {boolean} [inside=false] + * Remove all spaces between numbers. + * + * @return {string} + * Trimed string + */ + Data.prototype.trim = function (str, inside) { + if (typeof str === 'string') { + str = str.replace(/^\s+|\s+$/g, ''); + // Clear white space insdie the string, like thousands separators + if (inside && /^[0-9\s]+$/.test(str)) { + str = str.replace(/\s/g, ''); + } + if (this.decimalRegex) { + str = str.replace(this.decimalRegex, '$1.$2'); + } + } + return str; + }; + /** + * Parse numeric cells in to number types and date types in to true dates. + * + * @function Highcharts.Data#parseTypes + */ + Data.prototype.parseTypes = function () { + var columns = this.columns, col = columns.length; + while (col--) { + this.parseColumn(columns[col], col); + } + }; + /** + * Parse a single column. Set properties like .isDatetime and .isNumeric. + * + * @function Highcharts.Data#parseColumn + * + * @param {Array} column + * Column to parse + * + * @param {number} col + * Column index + */ + Data.prototype.parseColumn = function (column, col) { + var rawColumns = this.rawColumns, columns = this.columns, row = column.length, val, floatVal, trimVal, trimInsideVal, firstRowAsNames = this.firstRowAsNames, isXColumn = this.valueCount.xColumns.indexOf(col) !== -1, dateVal, backup = [], diff, chartOptions = this.chartOptions, descending, columnTypes = this.options.columnTypes || [], columnType = columnTypes[col], forceCategory = isXColumn && ((chartOptions && + chartOptions.xAxis && + splat(chartOptions.xAxis)[0].type === 'category') || columnType === 'string'); + if (!rawColumns[col]) { + rawColumns[col] = []; + } + while (row--) { + val = backup[row] || column[row]; + trimVal = this.trim(val); + trimInsideVal = this.trim(val, true); + floatVal = parseFloat(trimInsideVal); + // Set it the first time + if (typeof rawColumns[col][row] === 'undefined') { + rawColumns[col][row] = trimVal; + } + // Disable number or date parsing by setting the X axis type to + // category + if (forceCategory || (row === 0 && firstRowAsNames)) { + column[row] = '' + trimVal; + } + else if (+trimInsideVal === floatVal) { // is numeric + column[row] = floatVal; + // If the number is greater than milliseconds in a year, assume + // datetime + if (floatVal > 365 * 24 * 3600 * 1000 && + columnType !== 'float') { + column.isDatetime = true; + } + else { + column.isNumeric = true; + } + if (typeof column[row + 1] !== 'undefined') { + descending = floatVal > column[row + 1]; + } + // String, continue to determine if it is a date string or really a + // string + } + else { + if (trimVal && trimVal.length) { + dateVal = this.parseDate(val); + } + // Only allow parsing of dates if this column is an x-column + if (isXColumn && isNumber(dateVal) && columnType !== 'float') { + backup[row] = val; + column[row] = dateVal; + column.isDatetime = true; + // Check if the dates are uniformly descending or ascending. + // If they are not, chances are that they are a different + // time format, so check for alternative. + if (typeof column[row + 1] !== 'undefined') { + diff = dateVal > column[row + 1]; + if (diff !== descending && + typeof descending !== 'undefined') { + if (this.alternativeFormat) { + this.dateFormat = this.alternativeFormat; + row = column.length; + this.alternativeFormat = + this.dateFormats[this.dateFormat] + .alternative; + } + else { + column.unsorted = true; + } + } + descending = diff; + } + } + else { // string + column[row] = trimVal === '' ? null : trimVal; + if (row !== 0 && + (column.isDatetime || + column.isNumeric)) { + column.mixed = true; + } + } + } + } + // If strings are intermixed with numbers or dates in a parsed column, + // it is an indication that parsing went wrong or the data was not + // intended to display as numbers or dates and parsing is too + // aggressive. Fall back to categories. Demonstrated in the + // highcharts/demo/column-drilldown sample. + if (isXColumn && column.mixed) { + columns[col] = rawColumns[col]; + } + // If the 0 column is date or number and descending, reverse all + // columns. + if (isXColumn && descending && this.options.sort) { + for (col = 0; col < columns.length; col++) { + columns[col].reverse(); + if (firstRowAsNames) { + columns[col].unshift(columns[col].pop()); + } + } + } + }; + /** + * Parse a date and return it as a number. Overridable through + * `options.parseDate`. + * + * @function Highcharts.Data#parseDate + * + * @param {string} val + * + * @return {number} + */ + Data.prototype.parseDate = function (val) { + var parseDate = this.options.parseDate, ret, key, format, dateFormat = this.options.dateFormat || this.dateFormat, match; + if (parseDate) { + ret = parseDate(val); + } + else if (typeof val === 'string') { + // Auto-detect the date format the first time + if (!dateFormat) { + for (key in this.dateFormats) { // eslint-disable-line guard-for-in + format = this.dateFormats[key]; + match = val.match(format.regex); + if (match) { + this.dateFormat = dateFormat = key; + this.alternativeFormat = format.alternative; + ret = format.parser(match); + break; + } + } + // Next time, use the one previously found + } + else { + format = this.dateFormats[dateFormat]; + if (!format) { + // The selected format is invalid + format = this.dateFormats['YYYY/mm/dd']; + } + match = val.match(format.regex); + if (match) { + ret = format.parser(match); + } + } + // Fall back to Date.parse + if (!match) { + match = Date.parse(val); + // External tools like Date.js and MooTools extend Date object + // and returns a date. + if (typeof match === 'object' && + match !== null && + match.getTime) { + ret = (match.getTime() - + match.getTimezoneOffset() * + 60000); + // Timestamp + } + else if (isNumber(match)) { + ret = match - (new Date(match)).getTimezoneOffset() * 60000; + } + } + } + return ret; + }; + /** + * Reorganize rows into columns. + * + * @function Highcharts.Data#rowsToColumns + * + * @param {Array>} rows + * + * @return {Array>|undefined} + */ + Data.prototype.rowsToColumns = function (rows) { + var row, rowsLength, col, colsLength, columns; + if (rows) { + columns = []; + rowsLength = rows.length; + for (row = 0; row < rowsLength; row++) { + colsLength = rows[row].length; + for (col = 0; col < colsLength; col++) { + if (!columns[col]) { + columns[col] = []; + } + columns[col][row] = rows[row][col]; + } + } + } + return columns; + }; + /** + * Get the parsed data in a form that we can apply directly to the + * `series.data` config. Array positions can be mapped using the + * `series.keys` option. + * + * @example + * const data = Highcharts.data({ + * csv: document.getElementById('data').innerHTML + * }).getData(); + * + * @function Highcharts.Data#getData + * + * @return {Array>|undefined} Data rows + */ + Data.prototype.getData = function () { + if (this.columns) { + return this.rowsToColumns(this.columns).slice(1); + } + }; + /** + * A hook for working directly on the parsed columns + * + * @function Highcharts.Data#parsed + * + * @return {boolean|undefined} + */ + Data.prototype.parsed = function () { + if (this.options.parsed) { + return this.options.parsed.call(this, this.columns); + } + }; + /** + * @private + * @function Highcharts.Data#getFreeIndexes + */ + Data.prototype.getFreeIndexes = function (numberOfColumns, seriesBuilders) { + var s, i, freeIndexes = [], freeIndexValues = [], referencedIndexes; + // Add all columns as free + for (i = 0; i < numberOfColumns; i = i + 1) { + freeIndexes.push(true); + } + // Loop all defined builders and remove their referenced columns + for (s = 0; s < seriesBuilders.length; s = s + 1) { + referencedIndexes = seriesBuilders[s].getReferencedColumnIndexes(); + for (i = 0; i < referencedIndexes.length; i = i + 1) { + freeIndexes[referencedIndexes[i]] = false; + } + } + // Collect the values for the free indexes + for (i = 0; i < freeIndexes.length; i = i + 1) { + if (freeIndexes[i]) { + freeIndexValues.push(i); + } + } + return freeIndexValues; + }; + /** + * If a complete callback function is provided in the options, interpret the + * columns into a Highcharts options object. + * + * @function Highcharts.Data#complete + */ + Data.prototype.complete = function () { + var columns = this.columns, xColumns = [], type, options = this.options, series, data, i, j, r, seriesIndex, chartOptions, allSeriesBuilders = [], builder, freeIndexes, typeCol, index; + xColumns.length = columns.length; + if (options.complete || options.afterComplete) { + // Get the names and shift the top row + if (this.firstRowAsNames) { + for (i = 0; i < columns.length; i++) { + columns[i].name = columns[i].shift(); + } + } + // Use the next columns for series + series = []; + freeIndexes = this.getFreeIndexes(columns.length, this.valueCount.seriesBuilders); + // Populate defined series + for (seriesIndex = 0; seriesIndex < this.valueCount.seriesBuilders.length; seriesIndex++) { + builder = this.valueCount.seriesBuilders[seriesIndex]; + // If the builder can be populated with remaining columns, then + // add it to allBuilders + if (builder.populateColumns(freeIndexes)) { + allSeriesBuilders.push(builder); + } + } + // Populate dynamic series + while (freeIndexes.length > 0) { + builder = new SeriesBuilder(); + builder.addColumnReader(0, 'x'); + // Mark index as used (not free) + index = freeIndexes.indexOf(0); + if (index !== -1) { + freeIndexes.splice(index, 1); + } + for (i = 0; i < this.valueCount.global; i++) { + // Create and add a column reader for the next free column + // index + builder.addColumnReader(void 0, this.valueCount.globalPointArrayMap[i]); + } + // If the builder can be populated with remaining columns, then + // add it to allBuilders + if (builder.populateColumns(freeIndexes)) { + allSeriesBuilders.push(builder); + } + } + // Get the data-type from the first series x column + if (allSeriesBuilders.length > 0 && + allSeriesBuilders[0].readers.length > 0) { + typeCol = columns[allSeriesBuilders[0].readers[0].columnIndex]; + if (typeof typeCol !== 'undefined') { + if (typeCol.isDatetime) { + type = 'datetime'; + } + else if (!typeCol.isNumeric) { + type = 'category'; + } + } + } + // Axis type is category, then the "x" column should be called + // "name" + if (type === 'category') { + for (seriesIndex = 0; seriesIndex < allSeriesBuilders.length; seriesIndex++) { + builder = allSeriesBuilders[seriesIndex]; + for (r = 0; r < builder.readers.length; r++) { + if (builder.readers[r].configName === 'x') { + builder.readers[r].configName = 'name'; + } + } + } + } + // Read data for all builders + for (seriesIndex = 0; seriesIndex < allSeriesBuilders.length; seriesIndex++) { + builder = allSeriesBuilders[seriesIndex]; + // Iterate down the cells of each column and add data to the + // series + data = []; + for (j = 0; j < columns[0].length; j++) { + data[j] = builder.read(columns, j); + } + // Add the series + series[seriesIndex] = { + data: data + }; + if (builder.name) { + series[seriesIndex].name = builder.name; + } + if (type === 'category') { + series[seriesIndex].turboThreshold = 0; + } + } + // Do the callback + chartOptions = { + series: series + }; + if (type) { + chartOptions.xAxis = { + type: type + }; + if (type === 'category') { + chartOptions.xAxis.uniqueNames = false; + } + } + if (options.complete) { + options.complete(chartOptions); + } + // The afterComplete hook is used internally to avoid conflict with + // the externally available complete option. + if (options.afterComplete) { + options.afterComplete(chartOptions); + } + } + }; + /** + * Updates the chart with new data options. + * + * @function Highcharts.Data#update + * + * @param {Highcharts.DataOptions} options + * + * @param {boolean} [redraw=true] + */ + Data.prototype.update = function (options, redraw) { + var chart = this.chart; + if (options) { + // Set the complete handler + options.afterComplete = function (dataOptions) { + // Avoid setting axis options unless the type changes. Running + // Axis.update will cause the whole structure to be destroyed + // and rebuilt, and animation is lost. + if (dataOptions) { + if (dataOptions.xAxis && + chart.xAxis[0] && + dataOptions.xAxis.type === + chart.xAxis[0].options.type) { + delete dataOptions.xAxis; + } + // @todo looks not right: + chart.update(dataOptions, redraw, true); + } + }; + // Apply it + merge(true, chart.options.data, options); + this.init(chart.options.data); + } + }; + return Data; + }()); + // Register the Data prototype and data function on Highcharts + // Highcharts.Data = Data as any; + /** + * Creates a data object to parse data for a chart. + * + * @function Highcharts.data + * + * @param {Highcharts.DataOptions} dataOptions + * + * @param {Highcharts.Options} [chartOptions] + * + * @param {Highcharts.Chart} [chart] + * + * @return {Highcharts.Data} + */ + H.data = function (dataOptions, chartOptions, chart) { + return new H.Data(dataOptions, chartOptions, chart); + }; + // Extend Chart.init so that the Chart constructor accepts a new configuration + // option group, data. + addEvent(Chart, 'init', function (e) { + var chart = this, // eslint-disable-line no-invalid-this + userOptions = (e.args[0] || {}), callback = e.args[1]; + if (userOptions && userOptions.data && !chart.hasDataDef) { + chart.hasDataDef = true; + /** + * The data parser for this chart. + * + * @name Highcharts.Chart#data + * @type {Highcharts.Data|undefined} + */ + chart.data = new H.Data(extend(userOptions.data, { + afterComplete: function (dataOptions) { + var i, series; + // Merge series configs + if (Object.hasOwnProperty.call(userOptions, 'series')) { + if (typeof userOptions.series === 'object') { + i = Math.max(userOptions.series.length, dataOptions && dataOptions.series ? + dataOptions.series.length : + 0); + while (i--) { + series = userOptions.series[i] || {}; + userOptions.series[i] = merge(series, dataOptions && dataOptions.series ? + dataOptions.series[i] : + {}); + } + } + else { // Allow merging in dataOptions.series (#2856) + delete userOptions.series; + } + } + // Do the merge + userOptions = merge(dataOptions, userOptions); + // Run chart.init again + chart.init(userOptions, callback); + } + }), userOptions, chart); + e.preventDefault(); + } + }); + /** + * Creates a new SeriesBuilder. A SeriesBuilder consists of a number + * of ColumnReaders that reads columns and give them a name. + * Ex: A series builder can be constructed to read column 3 as 'x' and + * column 7 and 8 as 'y1' and 'y2'. + * The output would then be points/rows of the form {x: 11, y1: 22, y2: 33} + * + * The name of the builder is taken from the second column. In the above + * example it would be the column with index 7. + * + * @private + * @class + * @name SeriesBuilder + */ + var SeriesBuilder = /** @class */ (function () { + function SeriesBuilder() { + /* eslint-disable no-invalid-this */ + this.readers = []; + this.pointIsArray = true; + /* eslint-enable no-invalid-this */ + this.name = void 0; + } + /** + * Populates readers with column indexes. A reader can be added without + * a specific index and for those readers the index is taken sequentially + * from the free columns (this is handled by the ColumnCursor instance). + * + * @function SeriesBuilder#populateColumns + * + * @param {Array} freeIndexes + * + * @returns {boolean} + */ + SeriesBuilder.prototype.populateColumns = function (freeIndexes) { + var builder = this, enoughColumns = true; + // Loop each reader and give it an index if its missing. + // The freeIndexes.shift() will return undefined if there + // are no more columns. + builder.readers.forEach(function (reader) { + if (typeof reader.columnIndex === 'undefined') { + reader.columnIndex = freeIndexes.shift(); + } + }); + // Now, all readers should have columns mapped. If not + // then return false to signal that this series should + // not be added. + builder.readers.forEach(function (reader) { + if (typeof reader.columnIndex === 'undefined') { + enoughColumns = false; + } + }); + return enoughColumns; + }; + /** + * Reads a row from the dataset and returns a point or array depending + * on the names of the readers. + * + * @function SeriesBuilder#read + * + * @param {Array>} columns + * + * @param {number} rowIndex + * + * @returns {Array|Highcharts.Dictionary} + */ + SeriesBuilder.prototype.read = function (columns, rowIndex) { + var builder = this, pointIsArray = builder.pointIsArray, point = pointIsArray ? [] : {}, columnIndexes; + // Loop each reader and ask it to read its value. + // Then, build an array or point based on the readers names. + builder.readers.forEach(function (reader) { + var value = columns[reader.columnIndex][rowIndex]; + if (pointIsArray) { + point.push(value); + } + else { + if (reader.configName.indexOf('.') > 0) { + // Handle nested property names + Point.prototype.setNestedProperty(point, value, reader.configName); + } + else { + point[reader.configName] = value; + } + } + }); + // The name comes from the first column (excluding the x column) + if (typeof this.name === 'undefined' && builder.readers.length >= 2) { + columnIndexes = builder.getReferencedColumnIndexes(); + if (columnIndexes.length >= 2) { + // remove the first one (x col) + columnIndexes.shift(); + // Sort the remaining + columnIndexes.sort(function (a, b) { + return a - b; + }); + // Now use the lowest index as name column + this.name = columns[columnIndexes.shift()].name; + } + } + return point; + }; + /** + * Creates and adds ColumnReader from the given columnIndex and configName. + * ColumnIndex can be undefined and in that case the reader will be given + * an index when columns are populated. + * + * @function SeriesBuilder#addColumnReader + * + * @param {number} columnIndex + * + * @param {string} configName + */ + SeriesBuilder.prototype.addColumnReader = function (columnIndex, configName) { + this.readers.push({ + columnIndex: columnIndex, + configName: configName + }); + if (!(configName === 'x' || + configName === 'y' || + typeof configName === 'undefined')) { + this.pointIsArray = false; + } + }; + /** + * Returns an array of column indexes that the builder will use when + * reading data. + * + * @function SeriesBuilder#getReferencedColumnIndexes + * + * @returns {Array} + */ + SeriesBuilder.prototype.getReferencedColumnIndexes = function () { + var i, referencedColumnIndexes = [], columnReader; + for (i = 0; i < this.readers.length; i = i + 1) { + columnReader = this.readers[i]; + if (typeof columnReader.columnIndex !== 'undefined') { + referencedColumnIndexes.push(columnReader.columnIndex); + } + } + return referencedColumnIndexes; + }; + /** + * Returns true if the builder has a reader for the given configName. + * + * @function SeriesBuider#hasReader + * + * @param {string} configName + * + * @returns {boolean|undefined} + */ + SeriesBuilder.prototype.hasReader = function (configName) { + var i, columnReader; + for (i = 0; i < this.readers.length; i = i + 1) { + columnReader = this.readers[i]; + if (columnReader.configName === configName) { + return true; + } + } + // Else return undefined + }; + return SeriesBuilder; + }()); + H.Data = Data; + + return H.Data; + }); + _registerModule(_modules, 'masters/modules/data.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/datagrouping.js b/librerias/gantt/code/modules/datagrouping.js new file mode 100644 index 0000000..4155599 --- /dev/null +++ b/librerias/gantt/code/modules/datagrouping.js @@ -0,0 +1,26 @@ +/* + Highstock JS v8.1.0 (2020-05-05) + + Data grouping module + + (c) 2010-2019 Torstein Hnsi + + License: www.highcharts.com/license +*/ +(function(d){"object"===typeof module&&module.exports?(d["default"]=d,module.exports=d):"function"===typeof define&&define.amd?define("highcharts/modules/datagrouping",["highcharts"],function(g){d(g);d.Highcharts=g;return d}):d("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(d){function g(d,w,g,D){d.hasOwnProperty(w)||(d[w]=D.apply(null,g))}d=d?d._modules:{};g(d,"parts/DataGrouping.js",[d["parts/DateTimeAxis.js"],d["parts/Globals.js"],d["parts/Point.js"],d["parts/Tooltip.js"],d["parts/Utilities.js"]], +function(d,w,g,D,f){"";var y=f.addEvent,C=f.arrayMax,K=f.arrayMin,L=f.correctFloat,E=f.defined,M=f.error,N=f.extend,O=f.format,x=f.isNumber,F=f.merge,G=f.pick,B=w.Axis,P=w.defaultPlotOptions;f=w.Series;var u=w.approximations={sum:function(a){var c=a.length;if(!c&&a.hasNulls)var b=null;else if(c)for(b=0;c--;)b+=a[c];return b},average:function(a){var c=a.length;a=u.sum(a);x(a)&&c&&(a=L(a/c));return a},averages:function(){var a=[];[].forEach.call(arguments,function(c){a.push(u.average(c))});return"undefined"=== +typeof a[0]?void 0:a},open:function(a){return a.length?a[0]:a.hasNulls?null:void 0},high:function(a){return a.length?C(a):a.hasNulls?null:void 0},low:function(a){return a.length?K(a):a.hasNulls?null:void 0},close:function(a){return a.length?a[a.length-1]:a.hasNulls?null:void 0},ohlc:function(a,c,b,h){a=u.open(a);c=u.high(c);b=u.low(b);h=u.close(h);if(x(a)||x(c)||x(b)||x(h))return[a,c,b,h]},range:function(a,c){a=u.low(a);c=u.high(c);if(x(a)||x(c))return[a,c];if(null===a&&null===c)return null}},H=function(a, +c,b,h){var e=this,d=e.data,v=e.options&&e.options.data,A=[],n=[],f=[],p=a.length,q=!!c,r=[],k=e.pointArrayMap,g=k&&k.length,w=["x"].concat(k||["y"]),m=0,y=0,t;h="function"===typeof h?h:u[h]?u[h]:u[e.getDGApproximation&&e.getDGApproximation()||"average"];g?k.forEach(function(){r.push([])}):r.push([]);var B=g||1;for(t=0;t<=p&&!(a[t]>=b[0]);t++);for(t;t<=p;t++){for(;"undefined"!==typeof b[m+1]&&a[t]>=b[m+1]||t===p;){var l=b[m];e.dataGroupInfo={start:e.cropStart+y,length:r[0].length};var z=h.apply(e, +r);e.pointClass&&!E(e.dataGroupInfo.options)&&(e.dataGroupInfo.options=F(e.pointClass.prototype.optionsToObject.call({series:e},e.options.data[e.cropStart+y])),w.forEach(function(a){delete e.dataGroupInfo.options[a]}));"undefined"!==typeof z&&(A.push(l),n.push(z),f.push(e.dataGroupInfo));y=t;for(l=0;lthis.chart.plotSizeX/d||c&&f.forced)&&(e=!0);return e?d:0};B.prototype.setDataGrouping=function(a,c){var b;c=G(c,!0);a||(a={forced:!1,units:null});if(this instanceof B)for(b=this.series.length;b--;)this.series[b].update({dataGrouping:a},!1);else this.chart.options.series.forEach(function(b){b.dataGrouping=a},!1);this.ordinal&&(this.ordinal.slope= +void 0);c&&this.chart.redraw()};w.dataGrouping=I;"";return I});g(d,"masters/modules/datagrouping.src.js",[d["parts/DataGrouping.js"]],function(d){return d})}); +//# sourceMappingURL=datagrouping.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/datagrouping.js.map b/librerias/gantt/code/modules/datagrouping.js.map new file mode 100644 index 0000000..bfe4098 --- /dev/null +++ b/librerias/gantt/code/modules/datagrouping.js.map @@ -0,0 +1 @@ +{"version":3,"file":"datagrouping.js.map","lineCount":25,"mappings":"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","sources":["datagrouping.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","DateTimeAxis","H","Point","Tooltip","U","addEvent","arrayMax","arrayMin","correctFloat","defined","error","extend","format","isNumber","merge","pick","Axis","defaultPlotOptions","Series","approximations","sum","arr","len","length","hasNulls","ret","average","averages","forEach","call","arguments","push","open","high","low","close","ohlc","range","groupData","xData","yData","groupPositions","approximation","series","data","dataOptions","options","groupedXData","groupedYData","groupMap","dataLength","handleYData","values","pointArrayMap","pointArrayMapLength","extendedPointArrayMap","concat","pos","start","i","getDGApproximation","valuesLen","pointX","dataGroupInfo","cropStart","groupedY","approximationFn","pointClass","prototype","optionsToObject","key","j","index","point","applyOptions","val","pointY","dataGrouping","seriesProto","baseProcessData","processData","baseGeneratePoints","generatePoints","commonOptions","groupPixelWidth","dateTimeLabelFormats","millisecond","second","minute","hour","day","week","month","year","specificOptions","line","spline","area","areaspline","arearange","column","columnrange","candlestick","defaultDataGroupingUnits","seriesProto.getDGApproximation","is","seriesProto.processData","chart","dataGroupingOptions","groupingEnabled","allowDG","enabled","isStock","visible","ignoreHiddenSeries","hasGroupedData","lastDataGrouping","currentDataGrouping","revertRequireSorting","forceCrop","hasProcessed","requireSorting","skip","destroyGroupedData","processedXData","groupAll","processedYData","plotSizeX","xAxis","ordinal","getGroupPixelWidth","isDirty","points","extremes","getExtremes","xMin","min","xMax","max","groupIntervalFactor","getGroupIntervalFactor","interval","getTimeTicks","AdditionsClass","normalizeTimeTickInterval","units","Math","startOfWeek","closestPointRange","groupedData","gapSize","smoothed","info","segmentStarts","indexOf","totalRange","dataMin","croppedData","cropData","preventGraphAnimation","seriesProto.destroyGroupedData","destroy","seriesProto.generatePoints","dataGroup","e","time","labelConfig","tooltipOptions","xDateFormat","formatString","isFooter","type","labelFormats","unitName","count","xDateFormatEnd","tooltip","getXDateFormat","formattedKey","dateFormat","styledMode","styledModeFormat","text","preventDefault","plotOptions","defaultOptions","baseOptions","useCommonDataGrouping","userOptions","Axis.prototype.getGroupPixelWidth","doGrouping","dgOptions","forced","setDataGrouping","Axis.prototype.setDataGrouping","redraw","update","seriesOptions","axis","slope"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/datagrouping.src.js b/librerias/gantt/code/modules/datagrouping.src.js new file mode 100644 index 0000000..ef64be2 --- /dev/null +++ b/librerias/gantt/code/modules/datagrouping.src.js @@ -0,0 +1,925 @@ +/** + * @license Highstock JS v8.1.0 (2020-05-05) + * + * Data grouping module + * + * (c) 2010-2019 Torstein Hønsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/datagrouping', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'parts/DataGrouping.js', [_modules['parts/DateTimeAxis.js'], _modules['parts/Globals.js'], _modules['parts/Point.js'], _modules['parts/Tooltip.js'], _modules['parts/Utilities.js']], function (DateTimeAxis, H, Point, Tooltip, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * @typedef {"average"|"averages"|"open"|"high"|"low"|"close"|"sum"} Highcharts.DataGroupingApproximationValue + */ + /** + * @interface Highcharts.DataGroupingInfoObject + */ /** + * @name Highcharts.DataGroupingInfoObject#length + * @type {number} + */ /** + * @name Highcharts.DataGroupingInfoObject#options + * @type {Highcharts.SeriesOptionsType|undefined} + */ /** + * @name Highcharts.DataGroupingInfoObject#start + * @type {number} + */ + ''; // detach doclets above + var addEvent = U.addEvent, arrayMax = U.arrayMax, arrayMin = U.arrayMin, correctFloat = U.correctFloat, defined = U.defined, error = U.error, extend = U.extend, format = U.format, isNumber = U.isNumber, merge = U.merge, pick = U.pick; + var Axis = H.Axis, defaultPlotOptions = H.defaultPlotOptions, Series = H.Series; + /* ************************************************************************** * + * Start data grouping module * + * ************************************************************************** */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Define the available approximation types. The data grouping + * approximations takes an array or numbers as the first parameter. In case + * of ohlc, four arrays are sent in as four parameters. Each array consists + * only of numbers. In case null values belong to the group, the property + * .hasNulls will be set to true on the array. + * + * @product highstock + * + * @private + * @name Highcharts.approximations + * @type {Highcharts.Dictionary} + */ + var approximations = H.approximations = { + sum: function (arr) { + var len = arr.length, ret; + // 1. it consists of nulls exclusive + if (!len && arr.hasNulls) { + ret = null; + // 2. it has a length and real values + } + else if (len) { + ret = 0; + while (len--) { + ret += arr[len]; + } + } + // 3. it has zero length, so just return undefined + // => doNothing() + return ret; + }, + average: function (arr) { + var len = arr.length, ret = approximations.sum(arr); + // If we have a number, return it divided by the length. If not, + // return null or undefined based on what the sum method finds. + if (isNumber(ret) && len) { + ret = correctFloat(ret / len); + } + return ret; + }, + // The same as average, but for series with multiple values, like area + // ranges. + averages: function () { + var ret = []; + [].forEach.call(arguments, function (arr) { + ret.push(approximations.average(arr)); + }); + // Return undefined when first elem. is undefined and let + // sum method handle null (#7377) + return typeof ret[0] === 'undefined' ? void 0 : ret; + }, + open: function (arr) { + return arr.length ? arr[0] : (arr.hasNulls ? null : void 0); + }, + high: function (arr) { + return arr.length ? + arrayMax(arr) : + (arr.hasNulls ? null : void 0); + }, + low: function (arr) { + return arr.length ? + arrayMin(arr) : + (arr.hasNulls ? null : void 0); + }, + close: function (arr) { + return arr.length ? + arr[arr.length - 1] : + (arr.hasNulls ? null : void 0); + }, + // ohlc and range are special cases where a multidimensional array is + // input and an array is output + ohlc: function (open, high, low, close) { + open = approximations.open(open); + high = approximations.high(high); + low = approximations.low(low); + close = approximations.close(close); + if (isNumber(open) || + isNumber(high) || + isNumber(low) || + isNumber(close)) { + return [open, high, low, close]; + } + // else, return is undefined + }, + range: function (low, high) { + low = approximations.low(low); + high = approximations.high(high); + if (isNumber(low) || isNumber(high)) { + return [low, high]; + } + if (low === null && high === null) { + return null; + } + // else, return is undefined + } + }; + var groupData = function (xData, yData, groupPositions, approximation) { + var series = this, data = series.data, dataOptions = series.options && series.options.data, groupedXData = [], groupedYData = [], groupMap = [], dataLength = xData.length, pointX, pointY, groupedY, + // when grouping the fake extended axis for panning, + // we don't need to consider y + handleYData = !!yData, values = [], approximationFn, pointArrayMap = series.pointArrayMap, pointArrayMapLength = pointArrayMap && pointArrayMap.length, extendedPointArrayMap = ['x'].concat(pointArrayMap || ['y']), pos = 0, start = 0, valuesLen, i, j; + /** + * @private + */ + function getApproximation(approx) { + if (typeof approx === 'function') { + return approx; + } + if (approximations[approx]) { + return approximations[approx]; + } + return approximations[(series.getDGApproximation && series.getDGApproximation()) || + 'average']; + } + approximationFn = getApproximation(approximation); + // Calculate values array size from pointArrayMap length + if (pointArrayMapLength) { + pointArrayMap.forEach(function () { + values.push([]); + }); + } + else { + values.push([]); + } + valuesLen = pointArrayMapLength || 1; + // Start with the first point within the X axis range (#2696) + for (i = 0; i <= dataLength; i++) { + if (xData[i] >= groupPositions[0]) { + break; + } + } + for (i; i <= dataLength; i++) { + // when a new group is entered, summarize and initialize + // the previous group + while ((typeof groupPositions[pos + 1] !== 'undefined' && + xData[i] >= groupPositions[pos + 1]) || + i === dataLength) { // get the last group + // get group x and y + pointX = groupPositions[pos]; + series.dataGroupInfo = { + start: series.cropStart + start, + length: values[0].length + }; + groupedY = approximationFn.apply(series, values); + // By default, let options of the first grouped point be passed over + // to the grouped point. This allows preserving properties like + // `name` and `color` or custom properties. Implementers can + // override this from the approximation function, where they can + // write custom options to `this.dataGroupInfo.options`. + if (series.pointClass && !defined(series.dataGroupInfo.options)) { + // Convert numbers and arrays into objects + series.dataGroupInfo.options = merge(series.pointClass.prototype + .optionsToObject.call({ series: series }, series.options.data[series.cropStart + start])); + // Make sure the raw data (x, y, open, high etc) is not copied + // over and overwriting approximated data. + extendedPointArrayMap.forEach(function (key) { + delete series.dataGroupInfo.options[key]; + }); + } + // push the grouped data + if (typeof groupedY !== 'undefined') { + groupedXData.push(pointX); + groupedYData.push(groupedY); + groupMap.push(series.dataGroupInfo); + } + // reset the aggregate arrays + start = i; + for (j = 0; j < valuesLen; j++) { + values[j].length = 0; // faster than values[j] = [] + values[j].hasNulls = false; + } + // Advance on the group positions + pos += 1; + // don't loop beyond the last group + if (i === dataLength) { + break; + } + } + // break out + if (i === dataLength) { + break; + } + // for each raw data point, push it to an array that contains all values + // for this specific group + if (pointArrayMap) { + var index = series.cropStart + i, point = (data && data[index]) || + series.pointClass.prototype.applyOptions.apply({ + series: series + }, [dataOptions[index]]), val; + for (j = 0; j < pointArrayMapLength; j++) { + val = point[pointArrayMap[j]]; + if (isNumber(val)) { + values[j].push(val); + } + else if (val === null) { + values[j].hasNulls = true; + } + } + } + else { + pointY = handleYData ? yData[i] : null; + if (isNumber(pointY)) { + values[0].push(pointY); + } + else if (pointY === null) { + values[0].hasNulls = true; + } + } + } + return { + groupedXData: groupedXData, + groupedYData: groupedYData, + groupMap: groupMap + }; + }; + var dataGrouping = { + approximations: approximations, + groupData: groupData + }; + // ----------------------------------------------------------------------------- + // The following code applies to implementation of data grouping on a Series + var seriesProto = Series.prototype, baseProcessData = seriesProto.processData, baseGeneratePoints = seriesProto.generatePoints, + /** @ignore */ + commonOptions = { + // enabled: null, // (true for stock charts, false for basic), + // forced: undefined, + groupPixelWidth: 2, + // the first one is the point or start value, the second is the start + // value if we're dealing with range, the third one is the end value if + // dealing with a range + dateTimeLabelFormats: { + millisecond: [ + '%A, %b %e, %H:%M:%S.%L', + '%A, %b %e, %H:%M:%S.%L', + '-%H:%M:%S.%L' + ], + second: [ + '%A, %b %e, %H:%M:%S', + '%A, %b %e, %H:%M:%S', + '-%H:%M:%S' + ], + minute: [ + '%A, %b %e, %H:%M', + '%A, %b %e, %H:%M', + '-%H:%M' + ], + hour: [ + '%A, %b %e, %H:%M', + '%A, %b %e, %H:%M', + '-%H:%M' + ], + day: [ + '%A, %b %e, %Y', + '%A, %b %e', + '-%A, %b %e, %Y' + ], + week: [ + 'Week from %A, %b %e, %Y', + '%A, %b %e', + '-%A, %b %e, %Y' + ], + month: [ + '%B %Y', + '%B', + '-%B %Y' + ], + year: [ + '%Y', + '%Y', + '-%Y' + ] + } + // smoothed = false, // enable this for navigator series only + }, specificOptions = { + line: {}, + spline: {}, + area: {}, + areaspline: {}, + arearange: {}, + column: { + groupPixelWidth: 10 + }, + columnrange: { + groupPixelWidth: 10 + }, + candlestick: { + groupPixelWidth: 10 + }, + ohlc: { + groupPixelWidth: 5 + } + }, + // units are defined in a separate array to allow complete overriding in + // case of a user option + defaultDataGroupingUnits = H.defaultDataGroupingUnits = [ + [ + 'millisecond', + [1, 2, 5, 10, 20, 25, 50, 100, 200, 500] // allowed multiples + ], [ + 'second', + [1, 2, 5, 10, 15, 30] + ], [ + 'minute', + [1, 2, 5, 10, 15, 30] + ], [ + 'hour', + [1, 2, 3, 4, 6, 8, 12] + ], [ + 'day', + [1] + ], [ + 'week', + [1] + ], [ + 'month', + [1, 3, 6] + ], [ + 'year', + null + ] + ]; + // Set default approximations to the prototypes if present. Properties are + // inherited down. Can be overridden for individual series types. + seriesProto.getDGApproximation = function () { + if (this.is('arearange')) { + return 'range'; + } + if (this.is('ohlc')) { + return 'ohlc'; + } + if (this.is('column')) { + return 'sum'; + } + return 'average'; + }; + /** + * Takes parallel arrays of x and y data and groups the data into intervals + * defined by groupPositions, a collection of starting x values for each group. + * + * @private + * @function Highcharts.Series#groupData + * + * @param {Array} xData + * + * @param {Array|Array>} yData + * + * @param {boolean} groupPositions + * + * @param {string|Function} approximation + * + * @return {void} + */ + seriesProto.groupData = groupData; + // Extend the basic processData method, that crops the data to the current zoom + // range, with data grouping logic. + seriesProto.processData = function () { + var series = this, chart = series.chart, options = series.options, dataGroupingOptions = options.dataGrouping, groupingEnabled = series.allowDG !== false && dataGroupingOptions && + pick(dataGroupingOptions.enabled, chart.options.isStock), visible = (series.visible || !chart.options.chart.ignoreHiddenSeries), hasGroupedData, skip, lastDataGrouping = this.currentDataGrouping, currentDataGrouping, croppedData, revertRequireSorting = false; + // Run base method + series.forceCrop = groupingEnabled; // #334 + series.groupPixelWidth = null; // #2110 + series.hasProcessed = true; // #2692 + // Data needs to be sorted for dataGrouping + if (groupingEnabled && !series.requireSorting) { + series.requireSorting = revertRequireSorting = true; + } + // Skip if processData returns false or if grouping is disabled (in that + // order) + skip = (baseProcessData.apply(series, arguments) === false || + !groupingEnabled); + // Revert original requireSorting value if changed + if (revertRequireSorting) { + series.requireSorting = false; + } + if (!skip) { + series.destroyGroupedData(); + var i, processedXData = dataGroupingOptions.groupAll ? + series.xData : + series.processedXData, processedYData = dataGroupingOptions.groupAll ? + series.yData : + series.processedYData, plotSizeX = chart.plotSizeX, xAxis = series.xAxis, ordinal = xAxis.options.ordinal, groupPixelWidth = series.groupPixelWidth = + xAxis.getGroupPixelWidth && xAxis.getGroupPixelWidth(); + // Execute grouping if the amount of points is greater than the limit + // defined in groupPixelWidth + if (groupPixelWidth) { + hasGroupedData = true; + // Force recreation of point instances in series.translate, #5699 + series.isDirty = true; + series.points = null; // #6709 + var extremes = xAxis.getExtremes(), xMin = extremes.min, xMax = extremes.max, groupIntervalFactor = (ordinal && + xAxis.ordinal && + xAxis.ordinal.getGroupIntervalFactor(xMin, xMax, series)) || 1, interval = (groupPixelWidth * (xMax - xMin) / plotSizeX) * + groupIntervalFactor, groupPositions = xAxis.getTimeTicks(DateTimeAxis.AdditionsClass.prototype.normalizeTimeTickInterval(interval, dataGroupingOptions.units || + defaultDataGroupingUnits), + // Processed data may extend beyond axis (#4907) + Math.min(xMin, processedXData[0]), Math.max(xMax, processedXData[processedXData.length - 1]), xAxis.options.startOfWeek, processedXData, series.closestPointRange), groupedData = seriesProto.groupData.apply(series, [ + processedXData, + processedYData, + groupPositions, + dataGroupingOptions.approximation + ]), groupedXData = groupedData.groupedXData, groupedYData = groupedData.groupedYData, gapSize = 0; + // Prevent the smoothed data to spill out left and right, and make + // sure data is not shifted to the left + if (dataGroupingOptions.smoothed && groupedXData.length) { + i = groupedXData.length - 1; + groupedXData[i] = Math.min(groupedXData[i], xMax); + while (i-- && i > 0) { + groupedXData[i] += interval / 2; + } + groupedXData[0] = Math.max(groupedXData[0], xMin); + } + // Record what data grouping values were used + for (i = 1; i < groupPositions.length; i++) { + // The grouped gapSize needs to be the largest distance between + // the group to capture varying group sizes like months or DST + // crossing (#10000). Also check that the gap is not at the + // start of a segment. + if (!groupPositions.info.segmentStarts || + groupPositions.info.segmentStarts.indexOf(i) === -1) { + gapSize = Math.max(groupPositions[i] - groupPositions[i - 1], gapSize); + } + } + currentDataGrouping = groupPositions.info; + currentDataGrouping.gapSize = gapSize; + series.closestPointRange = groupPositions.info.totalRange; + series.groupMap = groupedData.groupMap; + // Make sure the X axis extends to show the first group (#2533) + // But only for visible series (#5493, #6393) + if (defined(groupedXData[0]) && + groupedXData[0] < xAxis.min && + visible) { + if ((!defined(xAxis.options.min) && + xAxis.min <= xAxis.dataMin) || + xAxis.min === xAxis.dataMin) { + xAxis.min = Math.min(groupedXData[0], xAxis.min); + } + xAxis.dataMin = Math.min(groupedXData[0], xAxis.dataMin); + } + // We calculated all group positions but we should render + // only the ones within the visible range + if (dataGroupingOptions.groupAll) { + croppedData = series.cropData(groupedXData, groupedYData, xAxis.min, xAxis.max, 1 // Ordinal xAxis will remove left-most points otherwise + ); + groupedXData = croppedData.xData; + groupedYData = croppedData.yData; + } + // Set series props + series.processedXData = groupedXData; + series.processedYData = groupedYData; + } + else { + series.groupMap = null; + } + series.hasGroupedData = hasGroupedData; + series.currentDataGrouping = currentDataGrouping; + series.preventGraphAnimation = + (lastDataGrouping && lastDataGrouping.totalRange) !== + (currentDataGrouping && currentDataGrouping.totalRange); + } + }; + // Destroy the grouped data points. #622, #740 + seriesProto.destroyGroupedData = function () { + // Clear previous groups + if (this.groupedData) { + this.groupedData.forEach(function (point, i) { + if (point) { + this.groupedData[i] = point.destroy ? + point.destroy() : null; + } + }, this); + // Clears all: + // - `this.groupedData` + // - `this.points` + // - `preserve` object in series.update() + this.groupedData.length = 0; + } + }; + // Override the generatePoints method by adding a reference to grouped data + seriesProto.generatePoints = function () { + baseGeneratePoints.apply(this); + // Record grouped data in order to let it be destroyed the next time + // processData runs + this.destroyGroupedData(); // #622 + this.groupedData = this.hasGroupedData ? this.points : null; + }; + // Override point prototype to throw a warning when trying to update grouped + // points. + addEvent(Point, 'update', function () { + if (this.dataGroup) { + error(24, false, this.series.chart); + return false; + } + }); + // Extend the original method, make the tooltip's header reflect the grouped + // range. + addEvent(Tooltip, 'headerFormatter', function (e) { + var tooltip = this, chart = this.chart, time = chart.time, labelConfig = e.labelConfig, series = labelConfig.series, options = series.options, tooltipOptions = series.tooltipOptions, dataGroupingOptions = options.dataGrouping, xDateFormat = tooltipOptions.xDateFormat, xDateFormatEnd, xAxis = series.xAxis, currentDataGrouping, dateTimeLabelFormats, labelFormats, formattedKey, formatString = tooltipOptions[(e.isFooter ? 'footer' : 'header') + 'Format']; + // apply only to grouped series + if (xAxis && + xAxis.options.type === 'datetime' && + dataGroupingOptions && + isNumber(labelConfig.key)) { + // set variables + currentDataGrouping = series.currentDataGrouping; + dateTimeLabelFormats = dataGroupingOptions.dateTimeLabelFormats || + // Fallback to commonOptions (#9693) + commonOptions.dateTimeLabelFormats; + // if we have grouped data, use the grouping information to get the + // right format + if (currentDataGrouping) { + labelFormats = + dateTimeLabelFormats[currentDataGrouping.unitName]; + if (currentDataGrouping.count === 1) { + xDateFormat = labelFormats[0]; + } + else { + xDateFormat = labelFormats[1]; + xDateFormatEnd = labelFormats[2]; + } + // if not grouped, and we don't have set the xDateFormat option, get the + // best fit, so if the least distance between points is one minute, show + // it, but if the least distance is one day, skip hours and minutes etc. + } + else if (!xDateFormat && dateTimeLabelFormats) { + xDateFormat = tooltip.getXDateFormat(labelConfig, tooltipOptions, xAxis); + } + // now format the key + formattedKey = time.dateFormat(xDateFormat, labelConfig.key); + if (xDateFormatEnd) { + formattedKey += time.dateFormat(xDateFormatEnd, labelConfig.key + currentDataGrouping.totalRange - 1); + } + // Replace default header style with class name + if (series.chart.styledMode) { + formatString = this.styledModeFormat(formatString); + } + // return the replaced format + e.text = format(formatString, { + point: extend(labelConfig.point, { key: formattedKey }), + series: series + }, chart); + e.preventDefault(); + } + }); + // Destroy grouped data on series destroy + addEvent(Series, 'destroy', seriesProto.destroyGroupedData); + // Handle default options for data grouping. This must be set at runtime because + // some series types are defined after this. + addEvent(Series, 'afterSetOptions', function (e) { + var options = e.options, type = this.type, plotOptions = this.chart.options.plotOptions, defaultOptions = defaultPlotOptions[type].dataGrouping, + // External series, for example technical indicators should also + // inherit commonOptions which are not available outside this module + baseOptions = this.useCommonDataGrouping && commonOptions; + if (specificOptions[type] || baseOptions) { // #1284 + if (!defaultOptions) { + defaultOptions = merge(commonOptions, specificOptions[type]); + } + options.dataGrouping = merge(baseOptions, defaultOptions, plotOptions.series && plotOptions.series.dataGrouping, // #1228 + // Set by the StockChart constructor: + plotOptions[type].dataGrouping, this.userOptions.dataGrouping); + } + }); + // When resetting the scale reset the hasProccessed flag to avoid taking + // previous data grouping of neighbour series into accound when determining + // group pixel width (#2692). + addEvent(Axis, 'afterSetScale', function () { + this.series.forEach(function (series) { + series.hasProcessed = false; + }); + }); + // Get the data grouping pixel width based on the greatest defined individual + // width of the axis' series, and if whether one of the axes need grouping. + Axis.prototype.getGroupPixelWidth = function () { + var series = this.series, len = series.length, i, groupPixelWidth = 0, doGrouping = false, dataLength, dgOptions; + // If multiple series are compared on the same x axis, give them the same + // group pixel width (#334) + i = len; + while (i--) { + dgOptions = series[i].options.dataGrouping; + if (dgOptions) { + groupPixelWidth = Math.max(groupPixelWidth, + // Fallback to commonOptions (#9693) + pick(dgOptions.groupPixelWidth, commonOptions.groupPixelWidth)); + } + } + // If one of the series needs grouping, apply it to all (#1634) + i = len; + while (i--) { + dgOptions = series[i].options.dataGrouping; + if (dgOptions && series[i].hasProcessed) { // #2692 + dataLength = (series[i].processedXData || series[i].data).length; + // Execute grouping if the amount of points is greater than the + // limit defined in groupPixelWidth + if (series[i].groupPixelWidth || + dataLength > + (this.chart.plotSizeX / groupPixelWidth) || + (dataLength && dgOptions.forced)) { + doGrouping = true; + } + } + } + return doGrouping ? groupPixelWidth : 0; + }; + /** + * Highstock only. Force data grouping on all the axis' series. + * + * @product highstock + * + * @function Highcharts.Axis#setDataGrouping + * + * @param {boolean|Highcharts.DataGroupingOptionsObject} [dataGrouping] + * A `dataGrouping` configuration. Use `false` to disable data grouping + * dynamically. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for a later call to + * {@link Chart#redraw}. + * + * @return {void} + */ + Axis.prototype.setDataGrouping = function (dataGrouping, redraw) { + var axis = this; + var i; + redraw = pick(redraw, true); + if (!dataGrouping) { + dataGrouping = { + forced: false, + units: null + }; + } + // Axis is instantiated, update all series + if (this instanceof Axis) { + i = this.series.length; + while (i--) { + this.series[i].update({ + dataGrouping: dataGrouping + }, false); + } + // Axis not yet instanciated, alter series options + } + else { + this.chart.options.series.forEach(function (seriesOptions) { + seriesOptions.dataGrouping = dataGrouping; + }, false); + } + // Clear ordinal slope, so we won't accidentaly use the old one (#7827) + if (axis.ordinal) { + axis.ordinal.slope = void 0; + } + if (redraw) { + this.chart.redraw(); + } + }; + H.dataGrouping = dataGrouping; + /* eslint-enable no-invalid-this, valid-jsdoc */ + /** + * Data grouping is the concept of sampling the data values into larger + * blocks in order to ease readability and increase performance of the + * JavaScript charts. Highstock by default applies data grouping when + * the points become closer than a certain pixel value, determined by + * the `groupPixelWidth` option. + * + * If data grouping is applied, the grouping information of grouped + * points can be read from the [Point.dataGroup]( + * /class-reference/Highcharts.Point#dataGroup). If point options other than + * the data itself are set, for example `name` or `color` or custom properties, + * the grouping logic doesn't know how to group it. In this case the options of + * the first point instance are copied over to the group point. This can be + * altered through a custom `approximation` callback function. + * + * @declare Highcharts.DataGroupingOptionsObject + * @product highstock + * @requires product:highstock + * @requires module:modules/datagrouping + * @apioption plotOptions.series.dataGrouping + */ + /** + * The method of approximation inside a group. When for example 30 days + * are grouped into one month, this determines what value should represent + * the group. Possible values are "average", "averages", "open", "high", + * "low", "close" and "sum". For OHLC and candlestick series the approximation + * is "ohlc" by default, which finds the open, high, low and close values + * within all the grouped data. For ranges, the approximation is "range", + * which finds the low and high values. For multi-dimensional data, + * like ranges and OHLC, "averages" will compute the average for each + * dimension. + * + * Custom aggregate methods can be added by assigning a callback function + * as the approximation. This function takes a numeric array as the + * argument and should return a single numeric value or `null`. Note + * that the numeric array will never contain null values, only true + * numbers. Instead, if null values are present in the raw data, the + * numeric array will have an `.hasNulls` property set to `true`. For + * single-value data sets the data is available in the first argument + * of the callback function. For OHLC data sets, all the open values + * are in the first argument, all high values in the second etc. + * + * Since v4.2.7, grouping meta data is available in the approximation + * callback from `this.dataGroupInfo`. It can be used to extract information + * from the raw data. + * + * Defaults to `average` for line-type series, `sum` for columns, `range` + * for range series and `ohlc` for OHLC and candlestick. + * + * @sample {highstock} stock/plotoptions/series-datagrouping-approximation + * Approximation callback with custom data + * + * @type {Highcharts.DataGroupingApproximationValue|Function} + * @apioption plotOptions.series.dataGrouping.approximation + */ + /** + * Datetime formats for the header of the tooltip in a stock chart. + * The format can vary within a chart depending on the currently selected + * time range and the current data grouping. + * + * The default formats are: + * ```js + * { + * millisecond: [ + * '%A, %b %e, %H:%M:%S.%L', '%A, %b %e, %H:%M:%S.%L', '-%H:%M:%S.%L' + * ], + * second: ['%A, %b %e, %H:%M:%S', '%A, %b %e, %H:%M:%S', '-%H:%M:%S'], + * minute: ['%A, %b %e, %H:%M', '%A, %b %e, %H:%M', '-%H:%M'], + * hour: ['%A, %b %e, %H:%M', '%A, %b %e, %H:%M', '-%H:%M'], + * day: ['%A, %b %e, %Y', '%A, %b %e', '-%A, %b %e, %Y'], + * week: ['Week from %A, %b %e, %Y', '%A, %b %e', '-%A, %b %e, %Y'], + * month: ['%B %Y', '%B', '-%B %Y'], + * year: ['%Y', '%Y', '-%Y'] + * } + * ``` + * + * For each of these array definitions, the first item is the format + * used when the active time span is one unit. For instance, if the + * current data applies to one week, the first item of the week array + * is used. The second and third items are used when the active time + * span is more than two units. For instance, if the current data applies + * to two weeks, the second and third item of the week array are used, + * and applied to the start and end date of the time span. + * + * @type {object} + * @apioption plotOptions.series.dataGrouping.dateTimeLabelFormats + */ + /** + * Enable or disable data grouping. + * + * @type {boolean} + * @default true + * @apioption plotOptions.series.dataGrouping.enabled + */ + /** + * When data grouping is forced, it runs no matter how small the intervals + * are. This can be handy for example when the sum should be calculated + * for values appearing at random times within each hour. + * + * @type {boolean} + * @default false + * @apioption plotOptions.series.dataGrouping.forced + */ + /** + * The approximate pixel width of each group. If for example a series + * with 30 points is displayed over a 600 pixel wide plot area, no grouping + * is performed. If however the series contains so many points that + * the spacing is less than the groupPixelWidth, Highcharts will try + * to group it into appropriate groups so that each is more or less + * two pixels wide. If multiple series with different group pixel widths + * are drawn on the same x axis, all series will take the greatest width. + * For example, line series have 2px default group width, while column + * series have 10px. If combined, both the line and the column will + * have 10px by default. + * + * @type {number} + * @default 2 + * @apioption plotOptions.series.dataGrouping.groupPixelWidth + */ + /** + * By default only points within the visible range are grouped. Enabling this + * option will force data grouping to calculate all grouped points for a given + * dataset. That option prevents for example a column series from calculating + * a grouped point partially. The effect is similar to + * [Series.getExtremesFromAll](#plotOptions.series.getExtremesFromAll) but does + * not affect yAxis extremes. + * + * @sample {highstock} stock/plotoptions/series-datagrouping-groupall/ + * Two series with the same data but different groupAll setting + * + * @type {boolean} + * @default false + * @since 6.1.0 + * @apioption plotOptions.series.dataGrouping.groupAll + */ + /** + * Normally, a group is indexed by the start of that group, so for example + * when 30 daily values are grouped into one month, that month's x value + * will be the 1st of the month. This apparently shifts the data to + * the left. When the smoothed option is true, this is compensated for. + * The data is shifted to the middle of the group, and min and max + * values are preserved. Internally, this is used in the Navigator series. + * + * @type {boolean} + * @default false + * @apioption plotOptions.series.dataGrouping.smoothed + */ + /** + * An array determining what time intervals the data is allowed to be + * grouped to. Each array item is an array where the first value is + * the time unit and the second value another array of allowed multiples. + * + * Defaults to: + * ```js + * units: [[ + * 'millisecond', // unit name + * [1, 2, 5, 10, 20, 25, 50, 100, 200, 500] // allowed multiples + * ], [ + * 'second', + * [1, 2, 5, 10, 15, 30] + * ], [ + * 'minute', + * [1, 2, 5, 10, 15, 30] + * ], [ + * 'hour', + * [1, 2, 3, 4, 6, 8, 12] + * ], [ + * 'day', + * [1] + * ], [ + * 'week', + * [1] + * ], [ + * 'month', + * [1, 3, 6] + * ], [ + * 'year', + * null + * ]] + * ``` + * + * @type {Array|null)>>} + * @apioption plotOptions.series.dataGrouping.units + */ + /** + * The approximate pixel width of each group. If for example a series + * with 30 points is displayed over a 600 pixel wide plot area, no grouping + * is performed. If however the series contains so many points that + * the spacing is less than the groupPixelWidth, Highcharts will try + * to group it into appropriate groups so that each is more or less + * two pixels wide. Defaults to `10`. + * + * @sample {highstock} stock/plotoptions/series-datagrouping-grouppixelwidth/ + * Two series with the same data density but different groupPixelWidth + * + * @type {number} + * @default 10 + * @apioption plotOptions.column.dataGrouping.groupPixelWidth + */ + ''; // required by JSDoc parsing + + return dataGrouping; + }); + _registerModule(_modules, 'masters/modules/datagrouping.src.js', [_modules['parts/DataGrouping.js']], function (dataGrouping) { + + + return dataGrouping; + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/debugger.js b/librerias/gantt/code/modules/debugger.js new file mode 100644 index 0000000..d123f39 --- /dev/null +++ b/librerias/gantt/code/modules/debugger.js @@ -0,0 +1,30 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Debugger module + + (c) 2012-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/debugger",["highcharts"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,c,b,f){a.hasOwnProperty(c)||(a[c]=f.apply(null,b))}a=a?a._modules:{};b(a,"error-messages.js",[a["parts/Globals.js"]],function(a){a.errorMessages={10:{title:"Can't plot zero or subzero values on a logarithmic axis", +text:'

    Can\'t plot zero or subzero values on a logarithmic axis

    This error occurs in the following situations:

    • If a zero or subzero data value is added to a logarithmic axis
    • If the minimum of a logarithimic axis is set to 0 or less
    • If the threshold is set to 0 or less

    Note: As of Highcharts 5.0.8 it\'s possible to bypass this error message by setting Axis.prototype.allowNegativeLog to true, and add custom conversion functions. View live demo. It is also possible to use a similar workaround for colorAxis. View live demo.

    ', +enduser:'

    Can\'t plot zero or subzero values on a logarithmic axis

    This error occurs in the following situations:

    • If a zero or subzero data value is added to a logarithmic axis
    • If the minimum of a logarithimic axis is set to 0 or less
    • If the threshold is set to 0 or less

    As of Highcharts 5.0.8 it\'s possible to bypass this error message by setting Axis.prototype.allowNegativeLog to true and add custom conversion functions. ">View Live Demo. It is also possible to use a similar workaround for colorAxis. View live demo.

    '}, +11:{title:"Can't link axes of different type",text:"

    Can't link axes of different type

    This error occurs when using the linkedTo option to link two axes of different types, for example a logarithmic axis to a linear axis. Highcharts can't link these because the calculation of ticks, extremes, padding etc. is different.

    "},12:{title:"Highcharts expects point configuration to be numbers or arrays in turbo mode",text:'

    Highcharts expects point configuration to be numbers or arrays in turbo mode

    This error occurs if the series.data option contains object configurations and the number of points exceeds the turboThreshold. It can be fixed by either setting turboThreshold to a higher value, or changing the point configurations to numbers or arrays.

    In boost mode, turbo mode is always on, which means only array of numbers or two dimensional arrays are allowed.

    See plotOptions.series.turboThreshold

    '}, +13:{title:"Rendering div not found",text:'

    Rendering div not found

    This error occurs if the chart.renderTo option is misconfigured so that Highcharts is unable to find the HTML element to render the chart in.

    If using a DOM ID when creating the chart, make sure a node with the same ID exists somewhere in the DOM.

    '},14:{title:"String value sent to series.data, expected Number",text:"

    String value sent to series.data, expected Number

    This happens if using a string as a data point, for example in a setup like this:

    series: [{\n    data: ["3", "5", "1", "6"]\n}]

    Highcharts expects numerical data values.

    The most common reason for this error this is that data is parsed from CSV or from a XML source, and the implementer forgot to run parseFloat on the parsed value.

    Note: For performance reasons internal type casting is not performed, and only the first value is checked (since 2.3).

    "}, +15:{title:"Highcharts expects data to be sorted",text:"

    Highcharts expects data to be sorted

    This happens when creating a line series or a stock chart where the data is not sorted in ascending X order.

    For performance reasons, Highcharts does not sort the data, instead it requires that the implementer pre-sorts the data.

    "},16:{title:"Highcharts already defined in the page",text:"

    Highcharts already defined in the page

    This error happens if the Highcharts namespace already exists when loading Highcharts or Highstock.

    This is caused by including Highcharts or Highstock more than once.

    Keep in mind that the Highcharts.Chart constructor and all features of Highcharts are included in Highstock, so if using the Chart and StockChart constructors in combination, only the highstock.js file is required.

    "}, +17:{title:"The requested series type does not exist",text:"

    The requested series type does not exist

    This error happens when setting chart.type or series.type to a series type that isn't defined in Highcharts. A typical reason may be that the module or extension where the series type is defined isn't included.

    For example in order to create an arearange series, the highcharts-more.js file must be loaded.

    "},18:{title:"The requested axis does not exist", +text:"

    The requested axis does not exist

    This error happens when setting a series' xAxis or yAxis property to point to an axis that does not exist.

    "},19:{title:"Too many ticks",text:"

    Too many ticks

    This error happens when applying too many ticks to an axis, specifically when adding more ticks than the axis pixel length.

    With default value this won't happen, but there are edge cases, for example when setting axis categories and xAxis.labels.step in combination with a long data range, when the axis is instructed to create a great number of ticks.

    "}, +20:{title:"Can't add object point configuration to a long data series",text:"

    Can't add object point configuration to a long data series

    In Highstock, when trying to add a point using the object literal configuration syntax, it will only work when the number of data points is below the series' turboThreshold. Instead of the object syntax, use the Array syntax.

    "},21:{title:"Can't find Proj4js library", +text:'

    Can\'t find Proj4js library

    Using latitude/longitude functionality in Highmaps requires the Proj4js library to be loaded.

    '},22:{title:"Map does not support latitude/longitude",text:'

    Map does not support latitude/longitude

    The loaded map does not support latitude/longitude functionality. This is only supported with maps from the official Highmaps map collection from version 1.1.0 onwards. If you are using a custom map, consider using the Proj4js library to convert between projections.

    '}, +23:{title:"Unsupported color format used for color interpolation",text:"

    Unsupported color format used for color interpolation

    Highcharts supports three color formats primarily: hex (#FFFFFF), rgb (rgba(255,255,255)) and rgba (rgba(255,255,255,1)). If any other format, like 3-digit colors (#FFF), named colors (white) or gradient structures are used in for example a heatmap, Highcharts will fail to interpolate and will instead use the end-color with no interpolation applied.

    We've chosen to preserve this limitation in order to keep the weight of the implementation at a minimum.

    "}, +24:{title:"Cannot run Point.update on a grouped point",text:"

    Cannot run Point.update on a grouped point

    Running Point.update in Highstock when a point is grouped by data grouping is not supported.

    This is not supported because when data grouping is enabled, there won't be any references to the raw points, which is required by the Point.update function.

    "},25:{title:"Can't find Moment.js library",text:'

    Can\'t find Moment.js library

    Using the global.timezone option requires the Moment.js library to be loaded.

    '}, +26:{title:"WebGL not supported, and no fallback module included",text:"

    WebGL not supported, and no fallback module included

    This happens when the browser doesn't support WebGL,and the canvas fallback module (boost-canvas.js) hasn't been included OR if the fallback module was includedafter the boost module.

    If a fallback is required, make sure to include boost-canvas.js, and that it's included before boost.js.

    Please note that the fallback module is not intended as a fully-featured one. Rather, it's a minimal implementation of the WebGL counterpart.

    "}, +27:{title:"This browser does not support SVG",text:"

    This browser does not support SVG

    This happens in old IE when the oldie.js module isn't loaded.

    If compatibility with IE versions 6, 7 and 8 is required, add the module after loading highcharts.js. In a website context, it's a good idea to load it in a conditional comment to avoid traffic overhead and dead code in modern browsers:

    <!--[if lt IE 9]>\n    <script src='https://code.highcharts.com/modules/oldie.js'></script>\n<![endif]-->
    "}, +28:{title:"Fallback to export server disabled",text:'

    Fallback to export server disabled

    This happens when the offline export module encounters a chart that it can\'t export successfully, and the fallback to the online export server is disabled. The offline exporting module will fail for certain browsers, and certain features (e.g. exporting.allowHTML ), depending on the type of image exporting to. For a compatibility overview, see Client Side Export.

    For very complex charts, it\'s possible that exporting fail in browsers that don\'t support Blob objects, due to data URL length limits. It\'s always recommended to define the exporting.error callback when disabling the fallback, so that details can be provided to the end-user if offline export isn\'t working for them.

    '}, +29:{title:"Browser does not support WebAudio",text:"

    Browser does not support WebAudio

    This happens when you attempt to use the sonification module on a chart in a browser or environment that does not support the WebAudio API. This API is supported on all modern browsers, including Microsoft Edge, Google Chrome and Mozilla Firefox.

    "},30:{title:"Invalid instrument",text:"

    Invalid instrument

    This happens when you try to use a sonification instrument that is not valid. If you are using a predefined instrument, make sure your spelling is correct.

    "}, +31:{title:"Non-unique point or node id",text:"

    Non-unique point or node id

    This error occurs when using the same id for two or more points or nodes.

    "},meta:{files:"errors/10/readme.md errors/10/enduser.md errors/11/readme.md errors/12/readme.md errors/13/readme.md errors/14/readme.md errors/15/readme.md errors/16/readme.md errors/17/readme.md errors/18/readme.md errors/19/readme.md errors/20/readme.md errors/21/readme.md errors/22/readme.md errors/23/readme.md errors/24/readme.md errors/25/readme.md errors/26/readme.md errors/27/readme.md errors/28/readme.md errors/29/readme.md errors/30/readme.md errors/31/readme.md".split(" ")}}}); +b(a,"modules/debugger.src.js",[a["parts/Globals.js"],a["parts/Utilities.js"]],function(a,b){var c=b.addEvent,f=b.isNumber;b=a.setOptions;b({chart:{displayErrors:!0}});c(a.Chart,"displayError",function(b){var d=b.code,e=this.options.chart;b=this.renderer;this.errorElements&&this.errorElements.forEach(function(a){a&&a.destroy()});if(e&&e.displayErrors&&b){this.errorElements=[];d=f(d)?"Highcharts error #"+d+": "+a.errorMessages[d].text:d;e=this.chartWidth;var c=this.chartHeight;d=d.replace(/

    (.*)<\/h1>/g, +'
    $1
    ').replace(/<\/p>/g,"


    ");this.errorElements[0]=b.rect(2,2,e-4,c-4).attr({"stroke-width":4,stroke:"#ff0000",zIndex:3}).add();this.errorElements[1]=b.label(d,0,0,"rect",void 0,void 0,void 0,void 0,"debugger").css({color:"#ffffff",width:e-16+"px",padding:0}).attr({fill:"rgba(255, 0, 0, 0.9)",width:e,padding:8,zIndex:10}).add();this.errorElements[1].attr({y:c-this.errorElements[1].getBBox().height})}});c(a.Chart,"beforeRedraw",function(){var a=this.errorElements; +a&&a.length&&a.forEach(function(a){a.destroy()});this.errorElements=null})});b(a,"masters/modules/debugger.src.js",[],function(){})}); +//# sourceMappingURL=debugger.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/debugger.js.map b/librerias/gantt/code/modules/debugger.js.map new file mode 100644 index 0000000..976af4e --- /dev/null +++ b/librerias/gantt/code/modules/debugger.js.map @@ -0,0 +1 @@ +{"version":3,"file":"debugger.js.map","lineCount":29,"mappings":"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","sources":["debugger.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","errorMessages","U","addEvent","isNumber","setOptions","chart","displayErrors","Chart","e","code","options","renderer","errorElements","forEach","el","destroy","msg","text","chartWidth","chartHeight","replace","rect","attr","stroke","zIndex","add","label","css","color","width","padding","fill","y","getBBox","height","length"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/debugger.src.js b/librerias/gantt/code/modules/debugger.src.js new file mode 100644 index 0000000..ed722c9 --- /dev/null +++ b/librerias/gantt/code/modules/debugger.src.js @@ -0,0 +1,256 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * Debugger module + * + * (c) 2012-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/debugger', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'error-messages.js', [_modules['parts/Globals.js']], function (H) { + /* eslint-disable */ + /* * + * Error information for the debugger module + * (c) 2010-2019 Torstein Honsi + * License: www.highcharts.com/license + */ + + // DO NOT EDIT! + // Automatically generated by ./tools/error-messages.js + // Sources can be found in ./errors/*/*.md + + + + H.errorMessages = { + "10": { + "title": "Can't plot zero or subzero values on a logarithmic axis", + "text": "

    Can't plot zero or subzero values on a logarithmic axis

    This error occurs in the following situations:

    • If a zero or subzero data value is added to a logarithmic axis
    • If the minimum of a logarithimic axis is set to 0 or less
    • If the threshold is set to 0 or less

    Note: As of Highcharts 5.0.8 it's possible to bypass this error message by setting Axis.prototype.allowNegativeLog to true, and add custom conversion functions. View live demo. It is also possible to use a similar workaround for colorAxis. View live demo.

    ", + "enduser": "

    Can't plot zero or subzero values on a logarithmic axis

    This error occurs in the following situations:

    • If a zero or subzero data value is added to a logarithmic axis
    • If the minimum of a logarithimic axis is set to 0 or less
    • If the threshold is set to 0 or less

    As of Highcharts 5.0.8 it's possible to bypass this error message by setting Axis.prototype.allowNegativeLog to true and add custom conversion functions. \">View Live Demo. It is also possible to use a similar workaround for colorAxis. View live demo.

    " + }, + "11": { + "title": "Can't link axes of different type", + "text": "

    Can't link axes of different type

    This error occurs when using the linkedTo option to link two axes of different types, for example a logarithmic axis to a linear axis. Highcharts can't link these because the calculation of ticks, extremes, padding etc. is different.

    " + }, + "12": { + "title": "Highcharts expects point configuration to be numbers or arrays in turbo mode", + "text": "

    Highcharts expects point configuration to be numbers or arrays in turbo mode

    This error occurs if the series.data option contains object configurations and the number of points exceeds the turboThreshold. It can be fixed by either setting turboThreshold to a higher value, or changing the point configurations to numbers or arrays.

    In boost mode, turbo mode is always on, which means only array of numbers or two dimensional arrays are allowed.

    See plotOptions.series.turboThreshold

    " + }, + "13": { + "title": "Rendering div not found", + "text": "

    Rendering div not found

    This error occurs if the chart.renderTo option is misconfigured so that Highcharts is unable to find the HTML element to render the chart in.

    If using a DOM ID when creating the chart, make sure a node with the same ID exists somewhere in the DOM.

    " + }, + "14": { + "title": "String value sent to series.data, expected Number", + "text": "

    String value sent to series.data, expected Number

    This happens if using a string as a data point, for example in a setup like this:

    series: [{\n    data: ["3", "5", "1", "6"]\n}]

    Highcharts expects numerical data values.

    The most common reason for this error this is that data is parsed from CSV or from a XML source, and the implementer forgot to run parseFloat on the parsed value.

    Note: For performance reasons internal type casting is not performed, and only the first value is checked (since 2.3).

    " + }, + "15": { + "title": "Highcharts expects data to be sorted", + "text": "

    Highcharts expects data to be sorted

    This happens when creating a line series or a stock chart where the data is not sorted in ascending X order.

    For performance reasons, Highcharts does not sort the data, instead it requires that the implementer pre-sorts the data.

    " + }, + "16": { + "title": "Highcharts already defined in the page", + "text": "

    Highcharts already defined in the page

    This error happens if the Highcharts namespace already exists when loading Highcharts or Highstock.

    This is caused by including Highcharts or Highstock more than once.

    Keep in mind that the Highcharts.Chart constructor and all features of Highcharts are included in Highstock, so if using the Chart and StockChart constructors in combination, only the highstock.js file is required.

    " + }, + "17": { + "title": "The requested series type does not exist", + "text": "

    The requested series type does not exist

    This error happens when setting chart.type or series.type to a series type that isn't defined in Highcharts. A typical reason may be that the module or extension where the series type is defined isn't included.

    For example in order to create an arearange series, the highcharts-more.js file must be loaded.

    " + }, + "18": { + "title": "The requested axis does not exist", + "text": "

    The requested axis does not exist

    This error happens when setting a series' xAxis or yAxis property to point to an axis that does not exist.

    " + }, + "19": { + "title": "Too many ticks", + "text": "

    Too many ticks

    This error happens when applying too many ticks to an axis, specifically when adding more ticks than the axis pixel length.

    With default value this won't happen, but there are edge cases, for example when setting axis categories and xAxis.labels.step in combination with a long data range, when the axis is instructed to create a great number of ticks.

    " + }, + "20": { + "title": "Can't add object point configuration to a long data series", + "text": "

    Can't add object point configuration to a long data series

    In Highstock, when trying to add a point using the object literal configuration syntax, it will only work when the number of data points is below the series' turboThreshold. Instead of the object syntax, use the Array syntax.

    " + }, + "21": { + "title": "Can't find Proj4js library", + "text": "

    Can't find Proj4js library

    Using latitude/longitude functionality in Highmaps requires the Proj4js library to be loaded.

    " + }, + "22": { + "title": "Map does not support latitude/longitude", + "text": "

    Map does not support latitude/longitude

    The loaded map does not support latitude/longitude functionality. This is only supported with maps from the official Highmaps map collection from version 1.1.0 onwards. If you are using a custom map, consider using the Proj4js library to convert between projections.

    " + }, + "23": { + "title": "Unsupported color format used for color interpolation", + "text": "

    Unsupported color format used for color interpolation

    Highcharts supports three color formats primarily: hex (#FFFFFF), rgb (rgba(255,255,255)) and rgba (rgba(255,255,255,1)). If any other format, like 3-digit colors (#FFF), named colors (white) or gradient structures are used in for example a heatmap, Highcharts will fail to interpolate and will instead use the end-color with no interpolation applied.

    We've chosen to preserve this limitation in order to keep the weight of the implementation at a minimum.

    " + }, + "24": { + "title": "Cannot run Point.update on a grouped point", + "text": "

    Cannot run Point.update on a grouped point

    Running Point.update in Highstock when a point is grouped by data grouping is not supported.

    This is not supported because when data grouping is enabled, there won't be any references to the raw points, which is required by the Point.update function.

    " + }, + "25": { + "title": "Can't find Moment.js library", + "text": "

    Can't find Moment.js library

    Using the global.timezone option requires the Moment.js library to be loaded.

    " + }, + "26": { + "title": "WebGL not supported, and no fallback module included", + "text": "

    WebGL not supported, and no fallback module included

    This happens when the browser doesn't support WebGL,and the canvas fallback module (boost-canvas.js) hasn't been included OR if the fallback module was includedafter the boost module.

    If a fallback is required, make sure to include boost-canvas.js, and that it's included before boost.js.

    Please note that the fallback module is not intended as a fully-featured one. Rather, it's a minimal implementation of the WebGL counterpart.

    " + }, + "27": { + "title": "This browser does not support SVG", + "text": "

    This browser does not support SVG

    This happens in old IE when the oldie.js module isn't loaded.

    If compatibility with IE versions 6, 7 and 8 is required, add the module after loading highcharts.js. In a website context, it's a good idea to load it in a conditional comment to avoid traffic overhead and dead code in modern browsers:

    <!--[if lt IE 9]>\n    <script src='https://code.highcharts.com/modules/oldie.js'></script>\n<![endif]-->
    " + }, + "28": { + "title": "Fallback to export server disabled", + "text": "

    Fallback to export server disabled

    This happens when the offline export module encounters a chart that it can't export successfully, and the fallback to the online export server is disabled. The offline exporting module will fail for certain browsers, and certain features (e.g. exporting.allowHTML ), depending on the type of image exporting to. For a compatibility overview, see Client Side Export.

    For very complex charts, it's possible that exporting fail in browsers that don't support Blob objects, due to data URL length limits. It's always recommended to define the exporting.error callback when disabling the fallback, so that details can be provided to the end-user if offline export isn't working for them.

    " + }, + "29": { + "title": "Browser does not support WebAudio", + "text": "

    Browser does not support WebAudio

    This happens when you attempt to use the sonification module on a chart in a browser or environment that does not support the WebAudio API. This API is supported on all modern browsers, including Microsoft Edge, Google Chrome and Mozilla Firefox.

    " + }, + "30": { + "title": "Invalid instrument", + "text": "

    Invalid instrument

    This happens when you try to use a sonification instrument that is not valid. If you are using a predefined instrument, make sure your spelling is correct.

    " + }, + "31": { + "title": "Non-unique point or node id", + "text": "

    Non-unique point or node id

    This error occurs when using the same id for two or more points or nodes.

    " + }, + "meta": { + "files": [ + "errors/10/readme.md", + "errors/10/enduser.md", + "errors/11/readme.md", + "errors/12/readme.md", + "errors/13/readme.md", + "errors/14/readme.md", + "errors/15/readme.md", + "errors/16/readme.md", + "errors/17/readme.md", + "errors/18/readme.md", + "errors/19/readme.md", + "errors/20/readme.md", + "errors/21/readme.md", + "errors/22/readme.md", + "errors/23/readme.md", + "errors/24/readme.md", + "errors/25/readme.md", + "errors/26/readme.md", + "errors/27/readme.md", + "errors/28/readme.md", + "errors/29/readme.md", + "errors/30/readme.md", + "errors/31/readme.md" + ] + } + }; + + }); + _registerModule(_modules, 'modules/debugger.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, isNumber = U.isNumber; + var setOptions = H.setOptions; + setOptions({ + /** + * @optionparent chart + */ + chart: { + /** + * Whether to display errors on the chart. When `false`, the errors will + * be shown only in the console. + * + * @sample highcharts/chart/display-errors/ + * Show errors on chart + * + * @since 7.0.0 + * @requires modules/debugger + */ + displayErrors: true + } + }); + /* eslint-disable no-invalid-this */ + addEvent(H.Chart, 'displayError', function (e) { + var chart = this, code = e.code, msg, options = chart.options.chart, renderer = chart.renderer, chartWidth, chartHeight; + if (chart.errorElements) { + (chart.errorElements).forEach(function (el) { + if (el) { + el.destroy(); + } + }); + } + if (options && options.displayErrors && renderer) { + chart.errorElements = []; + msg = isNumber(code) ? + ('Highcharts error #' + code + ': ' + + H.errorMessages[code].text) : + code; + chartWidth = chart.chartWidth; + chartHeight = chart.chartHeight; + // Format msg so SVGRenderer can handle it + msg = msg + .replace(/

    (.*)<\/h1>/g, '
    $1
    ') + .replace(/<\/p>/g, '


    '); + // Render red chart frame. + chart.errorElements[0] = renderer.rect(2, 2, chartWidth - 4, chartHeight - 4).attr({ + 'stroke-width': 4, + stroke: '#ff0000', + zIndex: 3 + }).add(); + // Render error message + chart.errorElements[1] = renderer.label(msg, 0, 0, 'rect', void 0, void 0, void 0, void 0, 'debugger').css({ + color: '#ffffff', + width: (chartWidth - 16) + 'px', + padding: 0 + }).attr({ + fill: 'rgba(255, 0, 0, 0.9)', + width: chartWidth, + padding: 8, + zIndex: 10 + }).add(); + chart.errorElements[1].attr({ + y: chartHeight - this.errorElements[1].getBBox().height + }); + } + }); + addEvent(H.Chart, 'beforeRedraw', function () { + var errorElements = this.errorElements; + if (errorElements && errorElements.length) { + errorElements.forEach(function (el) { + el.destroy(); + }); + } + this.errorElements = null; + }); + + }); + _registerModule(_modules, 'masters/modules/debugger.src.js', [], function () { + + + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/dependency-wheel.js b/librerias/gantt/code/modules/dependency-wheel.js new file mode 100644 index 0000000..fa4efb0 --- /dev/null +++ b/librerias/gantt/code/modules/dependency-wheel.js @@ -0,0 +1,17 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Dependency wheel module + + (c) 2010-2018 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/dependency-wheel",["highcharts","highcharts/modules/sankey"],function(d){a(d);a.Highcharts=d;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function d(a,f,d,l){a.hasOwnProperty(f)||(a[f]=l.apply(null,d))}a=a?a._modules:{};d(a,"modules/dependency-wheel.src.js",[a["parts/Globals.js"],a["parts/Utilities.js"]],function(a, +d){var f=d.animObject;d=d.seriesType;var l=a.seriesTypes.sankey.prototype;d("dependencywheel","sankey",{center:[null,null],curveFactor:.6,startAngle:0},{orderNodes:!1,getCenter:a.seriesTypes.pie.prototype.getCenter,createNodeColumns:function(){var a=[this.createNodeColumn()];this.nodes.forEach(function(c){c.column=0;a[0].push(c)});return a},getNodePadding:function(){return this.options.nodePadding/Math.PI},createNode:function(a){var c=l.createNode.call(this,a);c.index=this.nodes.length-1;c.getSum= +function(){return c.linksFrom.concat(c.linksTo).reduce(function(a,c){return a+c.weight},0)};c.offset=function(a){function h(a){return a.fromNode===c?a.toNode:a.fromNode}var p=0,b,g=c.linksFrom.concat(c.linksTo);g.sort(function(a,c){return h(a).index-h(c).index});for(b=0;bc.index){g=g.slice(0,b).reverse().concat(g.slice(b).reverse());var n=!0;break}n||g.reverse();for(b=0;bMath.PI&&(b=2*Math.PI-b);b*=k;bthis.angle||this.angle>Math.PI,f=d.start,b=d.end;this.dataLabelPath||(this.dataLabelPath=c.arc({open:!0}).add(a)); +this.dataLabelPath.attr({x:d.x,y:d.y,r:d.r+(this.dataLabel.options.distance||0),start:h?f:b,end:h?b:f,clockwise:+h});return this.dataLabelPath},isValid:function(){return!0}});""});d(a,"masters/modules/dependency-wheel.src.js",[],function(){})}); +//# sourceMappingURL=dependency-wheel.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/dependency-wheel.js.map b/librerias/gantt/code/modules/dependency-wheel.js.map new file mode 100644 index 0000000..d89ff3a --- /dev/null +++ b/librerias/gantt/code/modules/dependency-wheel.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dependency-wheel.js.map","lineCount":16,"mappings":"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","sources":["dependency-wheel.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","U","animObject","seriesType","base","seriesTypes","sankey","prototype","center","curveFactor","startAngle","orderNodes","getCenter","pie","createNodeColumns","columns","createNodeColumn","nodes","forEach","node","column","push","getNodePadding","options","nodePadding","Math","PI","createNode","id","call","index","length","getSum","node.getSum","linksFrom","concat","linksTo","reduce","acc","link","weight","offset","node.offset","point","otherNode","fromNode","toNode","i","links","sort","a","b","slice","reverse","sliced","translate","factor","chart","plotHeight","deg2rad","nodeColumns","sum","shapeArgs","centerX","centerY","r","innerR","nodeWidth","start","y","end","height","angle","shapeType","x","dlBox","cos","sin","width","linkBase","distance","corners","map","top","abs","cpX","cpY","d","animate","init","step","animation","duration","graphic","attr","opacity","setTimeout","points","isNode","setState","NodesMixin","setNodeState","getDataLabelPath","label","renderer","series","upperHalf","dataLabelPath","arc","open","add","dataLabel","clockwise","isValid"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/dependency-wheel.src.js b/librerias/gantt/code/modules/dependency-wheel.src.js new file mode 100644 index 0000000..d3e46fb --- /dev/null +++ b/librerias/gantt/code/modules/dependency-wheel.src.js @@ -0,0 +1,370 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * Dependency wheel module + * + * (c) 2010-2018 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/dependency-wheel', ['highcharts', 'highcharts/modules/sankey'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'modules/dependency-wheel.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * Dependency wheel module + * + * (c) 2018-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var animObject = U.animObject, seriesType = U.seriesType; + var base = H.seriesTypes.sankey.prototype; + /** + * @private + * @class + * @name Highcharts.seriesTypes.dependencywheel + * + * @augments Highcharts.seriesTypes.sankey + */ + seriesType('dependencywheel', 'sankey', + /** + * A dependency wheel chart is a type of flow diagram, where all nodes are + * laid out in a circle, and the flow between the are drawn as link bands. + * + * @sample highcharts/demo/dependency-wheel/ + * Dependency wheel + * + * @extends plotOptions.sankey + * @exclude dataSorting + * @since 7.1.0 + * @product highcharts + * @requires modules/dependencywheel + * @optionparent plotOptions.dependencywheel + */ + { + /** + * The center of the wheel relative to the plot area. Can be + * percentages or pixel values. The default behaviour is to + * center the wheel inside the plot area. + * + * @type {Array} + * @default [null, null] + * @product highcharts + */ + center: [null, null], + curveFactor: 0.6, + /** + * The start angle of the dependency wheel, in degrees where 0 is up. + */ + startAngle: 0 + }, { + orderNodes: false, + getCenter: H.seriesTypes.pie.prototype.getCenter, + /* eslint-disable valid-jsdoc */ + /** + * Dependency wheel has only one column, it runs along the perimeter. + * @private + */ + createNodeColumns: function () { + var columns = [this.createNodeColumn()]; + this.nodes.forEach(function (node) { + node.column = 0; + columns[0].push(node); + }); + return columns; + }, + /** + * Translate from vertical pixels to perimeter. + * @private + */ + getNodePadding: function () { + return this.options.nodePadding / Math.PI; + }, + createNode: function (id) { + var node = base.createNode.call(this, id); + node.index = this.nodes.length - 1; + /** + * Return the sum of incoming and outgoing links. + * @private + */ + node.getSum = function () { + return node.linksFrom + .concat(node.linksTo) + .reduce(function (acc, link) { + return acc + link.weight; + }, 0); + }; + /** + * Get the offset in weight values of a point/link. + * @private + */ + node.offset = function (point) { + var offset = 0, i, links = node.linksFrom.concat(node.linksTo), sliced; + /** + * @private + */ + function otherNode(link) { + if (link.fromNode === node) { + return link.toNode; + } + return link.fromNode; + } + // Sort and slice the links to avoid links going out of each + // node crossing each other. + links.sort(function (a, b) { + return otherNode(a).index - otherNode(b).index; + }); + for (i = 0; i < links.length; i++) { + if (otherNode(links[i]).index > node.index) { + links = links.slice(0, i).reverse().concat(links.slice(i).reverse()); + sliced = true; + break; + } + } + if (!sliced) { + links.reverse(); + } + for (i = 0; i < links.length; i++) { + if (links[i] === point) { + return offset; + } + offset += links[i].weight; + } + }; + return node; + }, + /** + * @private + * @todo Override the refactored sankey translateLink and translateNode + * functions instead of the whole translate function. + */ + translate: function () { + var options = this.options, factor = 2 * Math.PI / + (this.chart.plotHeight + this.getNodePadding()), center = this.getCenter(), startAngle = (options.startAngle - 90) * H.deg2rad; + base.translate.call(this); + this.nodeColumns[0].forEach(function (node) { + // Don't render the nodes if sum is 0 #12453 + if (node.sum) { + var shapeArgs = node.shapeArgs, centerX = center[0], centerY = center[1], r = center[2] / 2, innerR = r - options.nodeWidth, start = startAngle + factor * shapeArgs.y, end = startAngle + + factor * (shapeArgs.y + shapeArgs.height); + // Middle angle + node.angle = start + (end - start) / 2; + node.shapeType = 'arc'; + node.shapeArgs = { + x: centerX, + y: centerY, + r: r, + innerR: innerR, + start: start, + end: end + }; + node.dlBox = { + x: centerX + Math.cos((start + end) / 2) * (r + innerR) / 2, + y: centerY + Math.sin((start + end) / 2) * (r + innerR) / 2, + width: 1, + height: 1 + }; + // Draw the links from this node + node.linksFrom.forEach(function (point) { + if (point.linkBase) { + var distance; + var corners = point.linkBase.map(function (top, i) { + var angle = factor * top, x = Math.cos(startAngle + angle) * (innerR + 1), y = Math.sin(startAngle + angle) * (innerR + 1), curveFactor = options.curveFactor; + // The distance between the from and to node + // along the perimeter. This affect how curved + // the link is, so that links between neighbours + // don't extend too far towards the center. + distance = Math.abs(point.linkBase[3 - i] * factor - angle); + if (distance > Math.PI) { + distance = 2 * Math.PI - distance; + } + distance = distance * innerR; + if (distance < innerR) { + curveFactor *= (distance / innerR); + } + return { + x: centerX + x, + y: centerY + y, + cpX: centerX + (1 - curveFactor) * x, + cpY: centerY + (1 - curveFactor) * y + }; + }); + point.shapeArgs = { + d: [[ + 'M', + corners[0].x, corners[0].y + ], [ + 'A', + innerR, innerR, + 0, + 0, + 1, + corners[1].x, corners[1].y + ], [ + 'C', + corners[1].cpX, corners[1].cpY, + corners[2].cpX, corners[2].cpY, + corners[2].x, corners[2].y + ], [ + 'A', + innerR, innerR, + 0, + 0, + 1, + corners[3].x, corners[3].y + ], [ + 'C', + corners[3].cpX, corners[3].cpY, + corners[0].cpX, corners[0].cpY, + corners[0].x, corners[0].y + ]] + }; + } + }); + } + }); + }, + animate: function (init) { + if (!init) { + var duration = animObject(this.options.animation).duration, step = (duration / 2) / this.nodes.length; + this.nodes.forEach(function (point, i) { + var graphic = point.graphic; + if (graphic) { + graphic.attr({ opacity: 0 }); + setTimeout(function () { + graphic.animate({ opacity: 1 }, { duration: step }); + }, step * i); + } + }, this); + this.points.forEach(function (point) { + var graphic = point.graphic; + if (!point.isNode && graphic) { + graphic.attr({ opacity: 0 }) + .animate({ + opacity: 1 + }, this.options.animation); + } + }, this); + } + } + /* eslint-enable valid-jsdoc */ + }, + // Point class + { + setState: H.NodesMixin.setNodeState, + /* eslint-disable valid-jsdoc */ + /** + * Return a text path that the data label uses. + * @private + */ + getDataLabelPath: function (label) { + var renderer = this.series.chart.renderer, shapeArgs = this.shapeArgs, upperHalf = this.angle < 0 || this.angle > Math.PI, start = shapeArgs.start, end = shapeArgs.end; + if (!this.dataLabelPath) { + this.dataLabelPath = renderer + .arc({ open: true }) + // Add it inside the data label group so it gets destroyed + // with the label + .add(label); + } + this.dataLabelPath.attr({ + x: shapeArgs.x, + y: shapeArgs.y, + r: (shapeArgs.r + + (this.dataLabel.options.distance || 0)), + start: (upperHalf ? start : end), + end: (upperHalf ? end : start), + clockwise: +upperHalf + }); + return this.dataLabelPath; + }, + isValid: function () { + // No null points here + return true; + } + /* eslint-enable valid-jsdoc */ + }); + /** + * A `dependencywheel` series. If the [type](#series.dependencywheel.type) + * option is not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.dependencywheel + * @exclude dataSorting + * @product highcharts + * @requires modules/dependencywheel + * @apioption series.dependencywheel + */ + /** + * A collection of options for the individual nodes. The nodes in a dependency + * diagram are auto-generated instances of `Highcharts.Point`, but options can + * be applied here and linked by the `id`. + * + * @extends series.sankey.nodes + * @type {Array<*>} + * @product highcharts + * @excluding offset + * @apioption series.dependencywheel.nodes + */ + /** + * An array of data points for the series. For the `dependencywheel` series + * type, points can be given in the following way: + * + * An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of data + * points exceeds the series' [turboThreshold](#series.area.turboThreshold), + * this option is not available. + * + * ```js + * data: [{ + * from: 'Category1', + * to: 'Category2', + * weight: 2 + * }, { + * from: 'Category1', + * to: 'Category3', + * weight: 5 + * }] + * ``` + * + * @type {Array<*>} + * @extends series.sankey.data + * @product highcharts + * @excluding outgoing, dataLabels + * @apioption series.dependencywheel.data + */ + /** + * Individual data label for each node. The options are the same as + * the ones for [series.dependencywheel.dataLabels](#series.dependencywheel.dataLabels). + * + * @apioption series.dependencywheel.nodes.dataLabels + */ + ''; // adds doclets above to the transpiled file + + }); + _registerModule(_modules, 'masters/modules/dependency-wheel.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/dotplot.js b/librerias/gantt/code/modules/dotplot.js new file mode 100644 index 0000000..fe3ff0f --- /dev/null +++ b/librerias/gantt/code/modules/dotplot.js @@ -0,0 +1,14 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Dot plot series type for Highcharts + + (c) 2010-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/dotplot",["highcharts"],function(d){a(d);a.Highcharts=d;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function d(a,c,d,p){a.hasOwnProperty(c)||(a[c]=p.apply(null,d))}a=a?a._modules:{};d(a,"modules/dotplot.src.js",[a["parts/Globals.js"],a["parts/Utilities.js"]],function(a,c){var d=c.extend,p=c.objectEach,t=c.pick;c= +c.seriesType;c("dotplot","column",{itemPadding:.2,marker:{symbol:"circle",states:{hover:{},select:{}}}},{markerAttribs:void 0,drawPoints:function(){var a=this,c=a.chart.renderer,k=this.options.marker,l=this.yAxis.transA*a.options.itemPadding,m=this.borderWidth%2?.5:1;this.points.forEach(function(b){var e;var f=b.marker||{};var u=f.symbol||k.symbol,x=t(f.radius,k.radius),v="rect"!==u;b.graphics=e=b.graphics||{};var n=b.pointAttr?b.pointAttr[b.selected?"selected":""]||a.pointAttr[""]:a.pointAttribs(b, +b.selected&&"select");delete n.r;a.chart.styledMode&&(delete n.stroke,delete n["stroke-width"]);if(null!==b.y){b.graphic||(b.graphic=c.g("point").add(a.group));var h=b.y;var w=t(b.stackY,b.y);var q=Math.min(b.pointWidth,a.yAxis.transA-l);for(f=w;f>w-b.y;f--){var g=b.barX+(v?b.pointWidth/2-q/2:0);var r=a.yAxis.toPixels(f,!0)+l/2;a.options.crisp&&(g=Math.round(g)-m,r=Math.round(r)+m);g={x:g,y:r,width:Math.round(v?q:b.pointWidth),height:Math.round(q),r:x};e[h]?e[h].animate(g):e[h]=c.symbol(u).attr(d(g, +n)).add(b.graphic);e[h].isActive=!0;h--}}p(e,function(a,b){a.isActive?a.isActive=!1:(a.destroy(),delete a[b])})})}});a.SVGRenderer.prototype.symbols.rect=function(c,d,k,l,m){return a.SVGRenderer.prototype.symbols.callout(c,d,k,l,m)}});d(a,"masters/modules/dotplot.src.js",[],function(){})}); +//# sourceMappingURL=dotplot.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/dotplot.js.map b/librerias/gantt/code/modules/dotplot.js.map new file mode 100644 index 0000000..fe278b1 --- /dev/null +++ b/librerias/gantt/code/modules/dotplot.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dotplot.js.map","lineCount":13,"mappings":"A;;;;;;;;;AAUC,SAAS,CAACA,CAAD,CAAU,CACM,QAAtB,GAAI,MAAOC,OAAX,EAAkCA,MAAAC,QAAlC,EACIF,CAAA,CAAQ,SAAR,CACA,CADqBA,CACrB,CAAAC,MAAAC,QAAA,CAAiBF,CAFrB,EAG6B,UAAtB,GAAI,MAAOG,OAAX,EAAoCA,MAAAC,IAApC,CACHD,MAAA,CAAO,4BAAP,CAAqC,CAAC,YAAD,CAArC,CAAqD,QAAS,CAACE,CAAD,CAAa,CACvEL,CAAA,CAAQK,CAAR,CACAL,EAAAK,WAAA,CAAqBA,CACrB,OAAOL,EAHgE,CAA3E,CADG,CAOHA,CAAA,CAA8B,WAAtB,GAAA,MAAOK,WAAP,CAAoCA,UAApC,CAAiDC,IAAAA,EAAzD,CAXY,CAAnB,CAAA,CAaC,QAAS,CAACD,CAAD,CAAa,CAEpBE,QAASA,EAAe,CAACC,CAAD,CAAMC,CAAN,CAAYC,CAAZ,CAAkBC,CAAlB,CAAsB,CACrCH,CAAAI,eAAA,CAAmBH,CAAnB,CAAL,GACID,CAAA,CAAIC,CAAJ,CADJ,CACgBE,CAAAE,MAAA,CAAS,IAAT,CAAeH,CAAf,CADhB,CAD0C,CAD1CI,CAAAA,CAAWT,CAAA,CAAaA,CAAAS,SAAb,CAAmC,EAMlDP,EAAA,CAAgBO,CAAhB,CAA0B,wBAA1B,CAAoD,CAACA,CAAA,CAAS,kBAAT,CAAD,CAA+BA,CAAA,CAAS,oBAAT,CAA/B,CAApD,CAAoH,QAAS,CAACC,CAAD,CAAIC,CAAJ,CAAO,CAAA,IAmB5HC,EAASD,CAAAC,OAnBmH,CAmBzGC,EAAaF,CAAAE,WAnB4F,CAmB9EC,EAAOH,CAAAG,KAAQC,EAAAA;AAAaJ,CAAAI,WAQ9EA,EAAA,CAAW,SAAX,CAAsB,QAAtB,CAAgC,CAC5BC,YAAa,EADe,CAE5BC,OAAQ,CACJC,OAAQ,QADJ,CAEJC,OAAQ,CACJC,MAAO,EADH,CAEJC,OAAQ,EAFJ,CAFJ,CAFoB,CAAhC,CASG,CACCC,cAAe,IAAK,EADrB,CAECC,WAAYA,QAAS,EAAG,CAAA,IAChBC,EAAS,IADO,CACDC,EAAWD,CAAAE,MAAAD,SADV,CACiCE,EAAsB,IAAAC,QAAAX,OADvD,CAC4EY,EAAwB,IAAAC,MAAAC,OAAxBF,CAC5FL,CAAAI,QAAAZ,YAFgB,CAE4CgB,EAAlB,IAAAC,YAA0B,CAAc,CAAd,CAAkB,EAAlB,CAAwB,CAChG,KAAAC,OAAAC,QAAA,CAAoB,QAAS,CAACC,CAAD,CAAQ,CAAA,IACjBC,CAA4BC,KAAAA,EAAqBF,CAAAnB,OAArBqB,EAAqC,EADhD,KACoDpB,EAAUoB,CAAApB,OAAVA,EACjFS,CAAAT,OAF6B,CAEAqB,EAASzB,CAAA,CAAKwB,CAAAC,OAAL,CAAgCZ,CAAAY,OAAhC,CAFT,CAEkFC,EAAsB,MAAtBA,GAAWtB,CAC9HkB,EAAAC,SAAA,CAAiBA,CAAjB,CAA4BD,CAAAC,SAA5B,EAA8C,EAC9C,KAAAI,EAAYL,CAAAK,UAAA,CACPL,CAAAK,UAAA,CAAgBL,CAAAM,SAAA,CAAiB,UAAjB,CAA8B,EAA9C,CADO,EAEJlB,CAAAiB,UAAA,CAAiB,EAAjB,CAFI,CAGRjB,CAAAmB,aAAA,CAAoBP,CAApB;AAA2BA,CAAAM,SAA3B,EAA6C,QAA7C,CACJ,QAAOD,CAAAG,EACHpB,EAAAE,MAAAmB,WAAJ,GACI,OAAOJ,CAAAK,OACP,CAAA,OAAOL,CAAA,CAAU,cAAV,CAFX,CAIA,IAAgB,IAAhB,GAAIL,CAAAW,EAAJ,CAAsB,CACbX,CAAAY,QAAL,GACIZ,CAAAY,QADJ,CACoBvB,CAAAwB,EAAA,CAAW,OAAX,CAAAC,IAAA,CAAwB1B,CAAA2B,MAAxB,CADpB,CAGA,KAAAC,EAAQhB,CAAAW,EACR,KAAAM,EAAOvC,CAAA,CAAKsB,CAAAkB,OAAL,CAAmBlB,CAAAW,EAAnB,CACP,KAAAQ,EAAOC,IAAAC,IAAA,CAASrB,CAAAsB,WAAT,CAA2BlC,CAAAM,MAAAC,OAA3B,CAAiDF,CAAjD,CACP,KAAK8B,CAAL,CAAYN,CAAZ,CAAkBM,CAAlB,CAAyBN,CAAzB,CAAgCjB,CAAAW,EAAhC,CAAyCY,CAAA,EAAzC,CAAiD,CAC7C,IAAAC,EAAIxB,CAAAyB,KAAJD,EAAkBpB,CAAA,CACdJ,CAAAsB,WADc,CACK,CADL,CACSH,CADT,CACgB,CADhB,CAEd,CAFJK,CAGA,KAAAb,EAAIvB,CAAAM,MAAAgC,SAAA,CAAsBH,CAAtB,CAA4B,CAAA,CAA5B,CAAJZ,CACIlB,CADJkB,CAC4B,CACxBvB,EAAAI,QAAAI,MAAJ,GACI4B,CACA,CADIJ,IAAAO,MAAA,CAAWH,CAAX,CACJ,CADoB5B,CACpB,CAAAe,CAAA,CAAIS,IAAAO,MAAA,CAAWhB,CAAX,CAAJ,CAAoBf,CAFxB,CAIAgC,EAAA,CAAO,CACHJ,EAAGA,CADA,CAEHb,EAAGA,CAFA,CAGHkB,MAAOT,IAAAO,MAAA,CAAWvB,CAAA,CAAWe,CAAX,CAAkBnB,CAAAsB,WAA7B,CAHJ,CAIHQ,OAAQV,IAAAO,MAAA,CAAWR,CAAX,CAJL,CAKHX,EAAGL,CALA,CAOHF,EAAA,CAASe,CAAT,CAAJ,CACIf,CAAA,CAASe,CAAT,CAAAe,QAAA,CAAwBH,CAAxB,CADJ,CAII3B,CAAA,CAASe,CAAT,CAJJ,CAIsB3B,CAAAP,OAAA,CAAgBA,CAAhB,CAAA8C,KAAA,CACRpD,CAAA,CAAOoD,CAAP;AAAavB,CAAb,CADQ,CAAAS,IAAA,CAETd,CAAAY,QAFS,CAItBX,EAAA,CAASe,CAAT,CAAAgB,SAAA,CAA2B,CAAA,CAC3BhB,EAAA,EA1B6C,CAP/B,CAoCtBvC,CAAA,CAAWwB,CAAX,CAAqB,QAAS,CAACW,CAAD,CAAUqB,CAAV,CAAe,CACpCrB,CAAAoB,SAAL,CAKIpB,CAAAoB,SALJ,CAKuB,CAAA,CALvB,EACIpB,CAAAsB,QAAA,EACA,CAAA,OAAOtB,CAAA,CAAQqB,CAAR,CAFX,CADyC,CAA7C,CAjDiC,CAArC,CAHoB,CAFzB,CATH,CA2EA3D,EAAA6D,YAAAC,UAAAC,QAAAC,KAAA,CAAuCC,QAAS,CAACf,CAAD,CAAIb,CAAJ,CAAO6B,CAAP,CAAUC,CAAV,CAAajD,CAAb,CAAsB,CAClE,MAAOlB,EAAA6D,YAAAC,UAAAC,QAAAK,QAAA,CAAwClB,CAAxC,CAA2Cb,CAA3C,CAA8C6B,CAA9C,CAAiDC,CAAjD,CAAoDjD,CAApD,CAD2D,CAtG0D,CAApI,CA2GA1B,EAAA,CAAgBO,CAAhB,CAA0B,gCAA1B,CAA4D,EAA5D,CAAgE,QAAS,EAAG,EAA5E,CAlHoB,CAbvB;","sources":["dotplot.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","U","extend","objectEach","pick","seriesType","itemPadding","marker","symbol","states","hover","select","markerAttribs","drawPoints","series","renderer","chart","seriesMarkerOptions","options","itemPaddingTranslated","yAxis","transA","crisp","borderWidth","points","forEach","point","graphics","pointMarkerOptions","radius","isSquare","pointAttr","selected","pointAttribs","r","styledMode","stroke","y","graphic","g","add","group","itemY","yTop","stackY","size","Math","min","pointWidth","yPos","x","barX","toPixels","round","attr","width","height","animate","isActive","key","destroy","SVGRenderer","prototype","symbols","rect","H.SVGRenderer.prototype.symbols.rect","w","h","callout"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/dotplot.src.js b/librerias/gantt/code/modules/dotplot.src.js new file mode 100644 index 0000000..1542334 --- /dev/null +++ b/librerias/gantt/code/modules/dotplot.src.js @@ -0,0 +1,142 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * Dot plot series type for Highcharts + * + * (c) 2010-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/dotplot', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'modules/dotplot.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2009-2020 Torstein Honsi + * + * Dot plot series type for Highcharts + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * @private + * @todo + * - Check update, remove etc. + * - Custom icons like persons, carts etc. Either as images, font icons or + * Highcharts symbols. + */ + var extend = U.extend, objectEach = U.objectEach, pick = U.pick, seriesType = U.seriesType; + /** + * @private + * @class + * @name Highcharts.seriesTypes.dotplot + * + * @augments Highcharts.Series + */ + seriesType('dotplot', 'column', { + itemPadding: 0.2, + marker: { + symbol: 'circle', + states: { + hover: {}, + select: {} + } + } + }, { + markerAttribs: void 0, + drawPoints: function () { + var series = this, renderer = series.chart.renderer, seriesMarkerOptions = this.options.marker, itemPaddingTranslated = this.yAxis.transA * + series.options.itemPadding, borderWidth = this.borderWidth, crisp = borderWidth % 2 ? 0.5 : 1; + this.points.forEach(function (point) { + var yPos, attr, graphics, itemY, pointAttr, pointMarkerOptions = point.marker || {}, symbol = (pointMarkerOptions.symbol || + seriesMarkerOptions.symbol), radius = pick(pointMarkerOptions.radius, seriesMarkerOptions.radius), size, yTop, isSquare = symbol !== 'rect', x, y; + point.graphics = graphics = point.graphics || {}; + pointAttr = point.pointAttr ? + (point.pointAttr[point.selected ? 'selected' : ''] || + series.pointAttr['']) : + series.pointAttribs(point, point.selected && 'select'); + delete pointAttr.r; + if (series.chart.styledMode) { + delete pointAttr.stroke; + delete pointAttr['stroke-width']; + } + if (point.y !== null) { + if (!point.graphic) { + point.graphic = renderer.g('point').add(series.group); + } + itemY = point.y; + yTop = pick(point.stackY, point.y); + size = Math.min(point.pointWidth, series.yAxis.transA - itemPaddingTranslated); + for (yPos = yTop; yPos > yTop - point.y; yPos--) { + x = point.barX + (isSquare ? + point.pointWidth / 2 - size / 2 : + 0); + y = series.yAxis.toPixels(yPos, true) + + itemPaddingTranslated / 2; + if (series.options.crisp) { + x = Math.round(x) - crisp; + y = Math.round(y) + crisp; + } + attr = { + x: x, + y: y, + width: Math.round(isSquare ? size : point.pointWidth), + height: Math.round(size), + r: radius + }; + if (graphics[itemY]) { + graphics[itemY].animate(attr); + } + else { + graphics[itemY] = renderer.symbol(symbol) + .attr(extend(attr, pointAttr)) + .add(point.graphic); + } + graphics[itemY].isActive = true; + itemY--; + } + } + objectEach(graphics, function (graphic, key) { + if (!graphic.isActive) { + graphic.destroy(); + delete graphic[key]; + } + else { + graphic.isActive = false; + } + }); + }); + } + }); + H.SVGRenderer.prototype.symbols.rect = function (x, y, w, h, options) { + return H.SVGRenderer.prototype.symbols.callout(x, y, w, h, options); + }; + + }); + _registerModule(_modules, 'masters/modules/dotplot.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/drag-panes.js b/librerias/gantt/code/modules/drag-panes.js new file mode 100644 index 0000000..bcf3c57 --- /dev/null +++ b/librerias/gantt/code/modules/drag-panes.js @@ -0,0 +1,20 @@ +/* + Highstock JS v8.1.0 (2020-05-05) + + Drag-panes module + + (c) 2010-2019 Highsoft AS + Author: Kacper Madej + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/drag-panes",["highcharts","highcharts/modules/stock"],function(m){a(m);a.Highcharts=m;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function m(a,b,e,q){a.hasOwnProperty(b)||(a[b]=q.apply(null,e))}a=a?a._modules:{};m(a,"modules/drag-panes.src.js",[a["parts/Globals.js"],a["parts/Utilities.js"]],function(a,b){var e=b.addEvent, +q=b.clamp,m=b.isNumber,y=b.merge,z=b.objectEach,v=b.relativeLength;b=b.wrap;var A=a.hasTouch,l=a.Axis,w=a.Pointer,x=function(){function a(c){this.options=this.lastPos=this.controlLine=this.axis=void 0;this.init(c)}a.prototype.init=function(c,a){this.axis=c;this.options=c.options.resize;this.render();a||this.addMouseEvents()};a.prototype.render=function(){var c=this.axis,a=c.chart,d=this.options,b=d.x||0,e=d.y,h=q(c.top+c.height+e,a.plotTop,a.plotTop+a.plotHeight),k={};a.styledMode||(k={cursor:d.cursor, +stroke:d.lineColor,"stroke-width":d.lineWidth,dashstyle:d.lineDashStyle});this.lastPos=h-e;this.controlLine||(this.controlLine=a.renderer.path().addClass("highcharts-axis-resizer"));this.controlLine.add(c.axisGroup);d=a.styledMode?this.controlLine.strokeWidth():d.lineWidth;k.d=a.renderer.crispLine([["M",c.left+b,h],["L",c.left+c.width+b,h]],d);this.controlLine.attr(k)};a.prototype.addMouseEvents=function(){var c=this,a=c.controlLine.element,d=c.axis.chart.container,b=[],n,h,k;c.mouseMoveHandler=n= +function(a){c.onMouseMove(a)};c.mouseUpHandler=h=function(a){c.onMouseUp(a)};c.mouseDownHandler=k=function(a){c.onMouseDown(a)};b.push(e(d,"mousemove",n),e(d.ownerDocument,"mouseup",h),e(a,"mousedown",k));A&&b.push(e(d,"touchmove",n),e(d.ownerDocument,"touchend",h),e(a,"touchstart",k));c.eventsToUnbind=b};a.prototype.onMouseMove=function(a){a.touches&&0===a.touches[0].pageX||!this.grabbed||(this.hasDragged=!0,this.updateAxes(this.axis.chart.pointer.normalize(a).chartY-this.options.y))};a.prototype.onMouseUp= +function(a){this.hasDragged&&this.updateAxes(this.axis.chart.pointer.normalize(a).chartY-this.options.y);this.grabbed=this.hasDragged=this.axis.chart.activeResizer=null};a.prototype.onMouseDown=function(a){this.axis.chart.pointer.reset(!1,0);this.grabbed=this.axis.chart.activeResizer=!0};a.prototype.updateAxes=function(a){var c=this,d=c.axis.chart,b=c.options.controlledAxis,e=0===b.next.length?[d.yAxis.indexOf(c.axis)+1]:b.next;b=[c.axis].concat(b.prev);var n=[],k=!1,t=d.plotTop,p=d.plotHeight,l= +t+p;a=q(a,t,l);var u=a-c.lastPos;1>u*u||([b,e].forEach(function(b,e){b.forEach(function(b,g){var f=(b=m(b)?d.yAxis[b]:e||g?d.get(b):b)&&b.options;if(f&&"navigator-y-axis"!==f.id){g=b.top;var h=Math.round(v(f.minLength,p));var r=Math.round(v(f.maxLength,p));e?(u=a-c.lastPos,f=Math.round(q(b.len-u,h,r)),g=b.top+u,g+f>l&&(r=l-f-g,a+=r,g+=r),gl&&(f=p)),f===h&&(k=!0),n.push({axis:b,options:{top:100*(g-t)/p+"%",height:100*f/p+"%"}})):(f=Math.round(q(a-g,h,r)),f===r&&(k=!0),a=g+f,n.push({axis:b, +options:{height:100*f/p+"%"}}))}})}),k||(n.forEach(function(a){a.axis.update(a.options,!1)}),d.redraw(!1)))};a.prototype.destroy=function(){var a=this;delete a.axis.resizer;this.eventsToUnbind&&this.eventsToUnbind.forEach(function(a){a()});a.controlLine.destroy();z(a,function(b,c){a[c]=null})};a.resizerOptions={minLength:"10%",maxLength:"100%",resize:{controlledAxis:{next:[],prev:[]},enabled:!1,cursor:"ns-resize",lineColor:"#cccccc",lineDashStyle:"Solid",lineWidth:4,x:0,y:0}};return a}();l.keepProps.push("resizer"); +e(l,"afterRender",function(){var b=this.resizer,c=this.options.resize;c&&(c=!1!==c.enabled,b?c?b.init(this,!0):b.destroy():c&&(this.resizer=new a.AxisResizer(this)))});e(l,"destroy",function(a){!a.keepEvents&&this.resizer&&this.resizer.destroy()});b(w.prototype,"runPointActions",function(a){this.chart.activeResizer||a.apply(this,Array.prototype.slice.call(arguments,1))});b(w.prototype,"drag",function(a){this.chart.activeResizer||a.apply(this,Array.prototype.slice.call(arguments,1))});y(!0,l.defaultYAxisOptions, +x.resizerOptions);a.AxisResizer=x;return a.AxisResizer});m(a,"masters/modules/drag-panes.src.js",[],function(){})}); +//# sourceMappingURL=drag-panes.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/drag-panes.js.map b/librerias/gantt/code/modules/drag-panes.js.map new file mode 100644 index 0000000..f166772 --- /dev/null +++ b/librerias/gantt/code/modules/drag-panes.js.map @@ -0,0 +1 @@ +{"version":3,"file":"drag-panes.js.map","lineCount":19,"mappings":"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","sources":["drag-panes.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","U","addEvent","clamp","isNumber","merge","objectEach","relativeLength","wrap","hasTouch","Axis","Pointer","AxisResizer","axis","options","lastPos","controlLine","init","prototype","AxisResizer.prototype.init","update","resize","render","addMouseEvents","AxisResizer.prototype.render","resizer","chart","x","y","pos","top","height","plotTop","plotHeight","attr","styledMode","cursor","stroke","lineColor","lineWidth","dashstyle","lineDashStyle","renderer","addClass","add","axisGroup","strokeWidth","d","crispLine","left","width","AxisResizer.prototype.addMouseEvents","ctrlLineElem","element","container","eventsToUnbind","mouseMoveHandler","mouseUpHandler","mouseDownHandler","e","onMouseMove","onMouseUp","onMouseDown","push","ownerDocument","AxisResizer.prototype.onMouseMove","touches","pageX","grabbed","hasDragged","updateAxes","pointer","normalize","chartY","AxisResizer.prototype.onMouseUp","activeResizer","AxisResizer.prototype.onMouseDown","reset","AxisResizer.prototype.updateAxes","axes","controlledAxis","nextAxes","next","length","yAxis","indexOf","prevAxes","concat","prev","axesConfigs","stopDrag","plotBottom","yDelta","forEach","axesGroup","isNext","axisInfo","i","axisOptions","get","id","minLength","Math","round","maxLength","len","hDelta","config","redraw","destroy","AxisResizer.prototype.destroy","unbind","val","key","resizerOptions","enabled","keepProps","keepEvents","proceed","Array","slice","call","arguments","defaultYAxisOptions"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/drag-panes.src.js b/librerias/gantt/code/modules/drag-panes.src.js new file mode 100644 index 0000000..f6b06a6 --- /dev/null +++ b/librerias/gantt/code/modules/drag-panes.src.js @@ -0,0 +1,540 @@ +/** + * @license Highstock JS v8.1.0 (2020-05-05) + * + * Drag-panes module + * + * (c) 2010-2019 Highsoft AS + * Author: Kacper Madej + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/drag-panes', ['highcharts', 'highcharts/modules/stock'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'modules/drag-panes.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * Plugin for resizing axes / panes in a chart. + * + * (c) 2010-2017 Highsoft AS + * + * Author: Kacper Madej + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, clamp = U.clamp, isNumber = U.isNumber, merge = U.merge, objectEach = U.objectEach, relativeLength = U.relativeLength, wrap = U.wrap; + var hasTouch = H.hasTouch, Axis = H.Axis, Pointer = H.Pointer; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The AxisResizer class. + * + * @private + * @class + * @name Highcharts.AxisResizer + * + * @param {Highcharts.Axis} axis + * Main axis for the AxisResizer. + */ + var AxisResizer = /** @class */ (function () { + function AxisResizer(axis) { + /* eslint-enable no-invalid-this */ + this.axis = void 0; + this.controlLine = void 0; + this.lastPos = void 0; + this.options = void 0; + this.init(axis); + } + /** + * Initialize the AxisResizer object. + * + * @function Highcharts.AxisResizer#init + * + * @param {Highcharts.Axis} axis + * Main axis for the AxisResizer. + */ + AxisResizer.prototype.init = function (axis, update) { + this.axis = axis; + this.options = axis.options.resize; + this.render(); + if (!update) { + // Add mouse events. + this.addMouseEvents(); + } + }; + /** + * Render the AxisResizer + * + * @function Highcharts.AxisResizer#render + */ + AxisResizer.prototype.render = function () { + var resizer = this, axis = resizer.axis, chart = axis.chart, options = resizer.options, x = options.x || 0, y = options.y, + // Normalize control line position according to the plot area + pos = clamp(axis.top + axis.height + y, chart.plotTop, chart.plotTop + chart.plotHeight), attr = {}, lineWidth; + if (!chart.styledMode) { + attr = { + cursor: options.cursor, + stroke: options.lineColor, + 'stroke-width': options.lineWidth, + dashstyle: options.lineDashStyle + }; + } + // Register current position for future reference. + resizer.lastPos = pos - y; + if (!resizer.controlLine) { + resizer.controlLine = chart.renderer.path() + .addClass('highcharts-axis-resizer'); + } + // Add to axisGroup after axis update, because the group is recreated + // Do .add() before path is calculated because strokeWidth() needs it. + resizer.controlLine.add(axis.axisGroup); + lineWidth = chart.styledMode ? + resizer.controlLine.strokeWidth() : + options.lineWidth; + attr.d = chart.renderer.crispLine([ + ['M', axis.left + x, pos], + ['L', axis.left + axis.width + x, pos] + ], lineWidth); + resizer.controlLine.attr(attr); + }; + /** + * Set up the mouse and touch events for the control line. + * + * @function Highcharts.AxisResizer#addMouseEvents + */ + AxisResizer.prototype.addMouseEvents = function () { + var resizer = this, ctrlLineElem = resizer.controlLine.element, container = resizer.axis.chart.container, eventsToUnbind = [], mouseMoveHandler, mouseUpHandler, mouseDownHandler; + // Create mouse events' handlers. + // Make them as separate functions to enable wrapping them: + resizer.mouseMoveHandler = mouseMoveHandler = function (e) { + resizer.onMouseMove(e); + }; + resizer.mouseUpHandler = mouseUpHandler = function (e) { + resizer.onMouseUp(e); + }; + resizer.mouseDownHandler = mouseDownHandler = function (e) { + resizer.onMouseDown(e); + }; + // Add mouse move and mouseup events. These are bind to doc/container, + // because resizer.grabbed flag is stored in mousedown events. + eventsToUnbind.push(addEvent(container, 'mousemove', mouseMoveHandler), addEvent(container.ownerDocument, 'mouseup', mouseUpHandler), addEvent(ctrlLineElem, 'mousedown', mouseDownHandler)); + // Touch events. + if (hasTouch) { + eventsToUnbind.push(addEvent(container, 'touchmove', mouseMoveHandler), addEvent(container.ownerDocument, 'touchend', mouseUpHandler), addEvent(ctrlLineElem, 'touchstart', mouseDownHandler)); + } + resizer.eventsToUnbind = eventsToUnbind; + }; + /** + * Mouse move event based on x/y mouse position. + * + * @function Highcharts.AxisResizer#onMouseMove + * + * @param {Highcharts.PointerEventObject} e + * Mouse event. + */ + AxisResizer.prototype.onMouseMove = function (e) { + /* + * In iOS, a mousemove event with e.pageX === 0 is fired when holding + * the finger down in the center of the scrollbar. This should + * be ignored. Borrowed from Navigator. + */ + if (!e.touches || e.touches[0].pageX !== 0) { + // Drag the control line + if (this.grabbed) { + this.hasDragged = true; + this.updateAxes(this.axis.chart.pointer.normalize(e).chartY - + this.options.y); + } + } + }; + /** + * Mouse up event based on x/y mouse position. + * + * @function Highcharts.AxisResizer#onMouseUp + * + * @param {Highcharts.PointerEventObject} e + * Mouse event. + */ + AxisResizer.prototype.onMouseUp = function (e) { + if (this.hasDragged) { + this.updateAxes(this.axis.chart.pointer.normalize(e).chartY - + this.options.y); + } + // Restore runPointActions. + this.grabbed = this.hasDragged = this.axis.chart.activeResizer = + null; + }; + /** + * Mousedown on a control line. + * Will store necessary information for drag&drop. + * + * @function Highcharts.AxisResizer#onMouseDown + */ + AxisResizer.prototype.onMouseDown = function (e) { + // Clear all hover effects. + this.axis.chart.pointer.reset(false, 0); + // Disable runPointActions. + this.grabbed = this.axis.chart.activeResizer = true; + }; + /** + * Update all connected axes after a change of control line position + * + * @function Highcharts.AxisResizer#updateAxes + * + * @param {number} chartY + */ + AxisResizer.prototype.updateAxes = function (chartY) { + var resizer = this, chart = resizer.axis.chart, axes = resizer.options.controlledAxis, nextAxes = axes.next.length === 0 ? + [chart.yAxis.indexOf(resizer.axis) + 1] : axes.next, + // Main axis is included in the prev array by default + prevAxes = [resizer.axis].concat(axes.prev), + // prev and next configs + axesConfigs = [], stopDrag = false, plotTop = chart.plotTop, plotHeight = chart.plotHeight, plotBottom = plotTop + plotHeight, yDelta, calculatePercent = function (value) { + return value * 100 / plotHeight + '%'; + }, normalize = function (val, min, max) { + return Math.round(clamp(val, min, max)); + }; + // Normalize chartY to plot area limits + chartY = clamp(chartY, plotTop, plotBottom); + yDelta = chartY - resizer.lastPos; + // Update on changes of at least 1 pixel in the desired direction + if (yDelta * yDelta < 1) { + return; + } + // First gather info how axes should behave + [prevAxes, nextAxes].forEach(function (axesGroup, isNext) { + axesGroup.forEach(function (axisInfo, i) { + // Axes given as array index, axis object or axis id + var axis = isNumber(axisInfo) ? + // If it's a number - it's an index + chart.yAxis[axisInfo] : + ( + // If it's first elem. in first group + (!isNext && !i) ? + // then it's an Axis object + axisInfo : + // else it should be an id + chart.get(axisInfo)), axisOptions = axis && axis.options, optionsToUpdate = {}, hDelta = 0, height, top, minLength, maxLength; + // Skip if axis is not found + // or it is navigator's yAxis (#7732) + if (!axisOptions || + axisOptions.id === 'navigator-y-axis') { + return; + } + top = axis.top; + minLength = Math.round(relativeLength(axisOptions.minLength, plotHeight)); + maxLength = Math.round(relativeLength(axisOptions.maxLength, plotHeight)); + if (isNext) { + // Try to change height first. yDelta could had changed + yDelta = chartY - resizer.lastPos; + // Normalize height to option limits + height = normalize(axis.len - yDelta, minLength, maxLength); + // Adjust top, so the axis looks like shrinked from top + top = axis.top + yDelta; + // Check for plot area limits + if (top + height > plotBottom) { + hDelta = plotBottom - height - top; + chartY += hDelta; + top += hDelta; + } + // Fit to plot - when overflowing on top + if (top < plotTop) { + top = plotTop; + if (top + height > plotBottom) { + height = plotHeight; + } + } + // If next axis meets min length, stop dragging: + if (height === minLength) { + stopDrag = true; + } + axesConfigs.push({ + axis: axis, + options: { + top: calculatePercent(top - plotTop), + height: calculatePercent(height) + } + }); + } + else { + // Normalize height to option limits + height = normalize(chartY - top, minLength, maxLength); + // If prev axis meets max length, stop dragging: + if (height === maxLength) { + stopDrag = true; + } + // Check axis size limits + chartY = top + height; + axesConfigs.push({ + axis: axis, + options: { + height: calculatePercent(height) + } + }); + } + optionsToUpdate.height = height; + }); + }); + // If we hit the min/maxLength with dragging, don't do anything: + if (!stopDrag) { + // Now update axes: + axesConfigs.forEach(function (config) { + config.axis.update(config.options, false); + }); + chart.redraw(false); + } + }; + /** + * Destroy AxisResizer. Clear outside references, clear events, + * destroy elements, nullify properties. + * + * @function Highcharts.AxisResizer#destroy + */ + AxisResizer.prototype.destroy = function () { + var resizer = this, axis = resizer.axis; + // Clear resizer in axis + delete axis.resizer; + // Clear control line events + if (this.eventsToUnbind) { + this.eventsToUnbind.forEach(function (unbind) { + unbind(); + }); + } + // Destroy AxisResizer elements + resizer.controlLine.destroy(); + // Nullify properties + objectEach(resizer, function (val, key) { + resizer[key] = null; + }); + }; + // Default options for AxisResizer. + AxisResizer.resizerOptions = { + /** + * Minimal size of a resizable axis. Could be set as a percent + * of plot area or pixel size. + * + * @sample {highstock} stock/yaxis/resize-min-max-length + * minLength and maxLength + * + * @type {number|string} + * @product highstock + * @requires modules/drag-panes + * @apioption yAxis.minLength + */ + minLength: '10%', + /** + * Maximal size of a resizable axis. Could be set as a percent + * of plot area or pixel size. + * + * @sample {highstock} stock/yaxis/resize-min-max-length + * minLength and maxLength + * + * @type {number|string} + * @product highstock + * @requires modules/drag-panes + * @apioption yAxis.maxLength + */ + maxLength: '100%', + /** + * Options for axis resizing. It adds a thick line between panes which + * the user can drag in order to resize the panes. + * + * @sample {highstock} stock/demo/candlestick-and-volume + * Axis resizing enabled + * + * @product highstock + * @requires modules/drag-panes + * @optionparent yAxis.resize + */ + resize: { + /** + * Contains two arrays of axes that are controlled by control line + * of the axis. + * + * @requires modules/drag-panes + */ + controlledAxis: { + /** + * Array of axes that should move out of the way of resizing + * being done for the current axis. If not set, the next axis + * will be used. + * + * @sample {highstock} stock/yaxis/multiple-resizers + * Three panes with resizers + * @sample {highstock} stock/yaxis/resize-multiple-axes + * One resizer controlling multiple axes + * + * @type {Array} + * @default [] + * @requires modules/drag-panes + */ + next: [], + /** + * Array of axes that should move with the current axis + * while resizing. + * + * @sample {highstock} stock/yaxis/multiple-resizers + * Three panes with resizers + * @sample {highstock} stock/yaxis/resize-multiple-axes + * One resizer controlling multiple axes + * + * @type {Array} + * @default [] + * @requires modules/drag-panes + */ + prev: [] + }, + /** + * Enable or disable resize by drag for the axis. + * + * @sample {highstock} stock/demo/candlestick-and-volume + * Enabled resizer + * + * @requires modules/drag-panes + */ + enabled: false, + /** + * Cursor style for the control line. + * + * In styled mode use class `highcharts-axis-resizer` instead. + * + * @requires modules/drag-panes + */ + cursor: 'ns-resize', + /** + * Color of the control line. + * + * In styled mode use class `highcharts-axis-resizer` instead. + * + * @sample {highstock} stock/yaxis/styled-resizer + * Styled resizer + * + * @type {Highcharts.ColorString} + * @requires modules/drag-panes + */ + lineColor: '#cccccc', + /** + * Dash style of the control line. + * + * In styled mode use class `highcharts-axis-resizer` instead. + * + * @see For supported options check [dashStyle](#plotOptions.series.dashStyle) + * + * @sample {highstock} stock/yaxis/styled-resizer + * Styled resizer + * + * @requires modules/drag-panes + */ + lineDashStyle: 'Solid', + /** + * Width of the control line. + * + * In styled mode use class `highcharts-axis-resizer` instead. + * + * @sample {highstock} stock/yaxis/styled-resizer + * Styled resizer + * + * @requires modules/drag-panes + */ + lineWidth: 4, + /** + * Horizontal offset of the control line. + * + * @sample {highstock} stock/yaxis/styled-resizer + * Styled resizer + * + * @requires modules/drag-panes + */ + x: 0, + /** + * Vertical offset of the control line. + * + * @sample {highstock} stock/yaxis/styled-resizer + * Styled resizer + * + * @requires modules/drag-panes + */ + y: 0 + } + }; + return AxisResizer; + }()); + // Keep resizer reference on axis update + Axis.keepProps.push('resizer'); + /* eslint-disable no-invalid-this */ + // Add new AxisResizer, update or remove it + addEvent(Axis, 'afterRender', function () { + var axis = this, resizer = axis.resizer, resizerOptions = axis.options.resize, enabled; + if (resizerOptions) { + enabled = resizerOptions.enabled !== false; + if (resizer) { + // Resizer present and enabled + if (enabled) { + // Update options + resizer.init(axis, true); + // Resizer present, but disabled + } + else { + // Destroy the resizer + resizer.destroy(); + } + } + else { + // Resizer not present and enabled + if (enabled) { + // Add new resizer + axis.resizer = new H.AxisResizer(axis); + } + // Resizer not present and disabled, so do nothing + } + } + }); + // Clear resizer on axis remove. + addEvent(Axis, 'destroy', function (e) { + if (!e.keepEvents && this.resizer) { + this.resizer.destroy(); + } + }); + // Prevent any hover effects while dragging a control line of AxisResizer. + wrap(Pointer.prototype, 'runPointActions', function (proceed) { + if (!this.chart.activeResizer) { + proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + } + }); + // Prevent default drag action detection while dragging a control line of + // AxisResizer. (#7563) + wrap(Pointer.prototype, 'drag', function (proceed) { + if (!this.chart.activeResizer) { + proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + } + }); + merge(true, Axis.defaultYAxisOptions, AxisResizer.resizerOptions); + H.AxisResizer = AxisResizer; + + return H.AxisResizer; + }); + _registerModule(_modules, 'masters/modules/drag-panes.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/draggable-points.js b/librerias/gantt/code/modules/draggable-points.js new file mode 100644 index 0000000..8069bde --- /dev/null +++ b/librerias/gantt/code/modules/draggable-points.js @@ -0,0 +1,40 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2009-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(f){"object"===typeof module&&module.exports?(f["default"]=f,module.exports=f):"function"===typeof define&&define.amd?define("highcharts/modules/draggable-points",["highcharts"],function(t){f(t);f.Highcharts=t;return f}):f("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(f){function t(f,m,k,t){f.hasOwnProperty(m)||(f[m]=t.apply(null,k))}f=f?f._modules:{};t(f,"modules/draggable-points.src.js",[f["parts/Globals.js"],f["parts/Point.js"],f["parts/Utilities.js"]],function(f,m,k){function t(a){return{left:"right", +right:"left",top:"bottom",bottom:"top"}[a]}function K(a){var b=["draggableX","draggableY"],c;p(a.dragDropProps,function(a){a.optionName&&b.push(a.optionName)});for(c=b.length;c--;)if(a.options.dragDrop[b[c]])return!0}function L(a){var b=a.series?a.series.length:0;if(a.hasCartesianSeries&&!a.polar)for(;b--;)if(a.series[b].options.dragDrop&&K(a.series[b]))return!0}function M(a){var b=a.series,c=b.options.dragDrop||{};a=a.options&&a.options.dragDrop;var d,e;p(b.dragDropProps,function(a){"x"===a.axis&& +a.move?d=!0:"y"===a.axis&&a.move&&(e=!0)});return(c.draggableX&&d||c.draggableY&&e)&&!(a&&!1===a.draggableX&&!1===a.draggableY)&&b.yAxis&&b.xAxis}function x(a,b){return"undefined"===typeof a.chartX||"undefined"===typeof a.chartY?b.pointer.normalize(a):a}function y(a,b,c,d){var e=b.map(function(b){return u(a,b,c,d)});return function(){e.forEach(function(a){a()})}}function N(a,b,c){var d=b.dragDropData.origin;b=d.chartX;d=d.chartY;var e=a.chartX;a=a.chartY;return Math.sqrt((e-b)*(e-b)+(a-d)*(a-d))> +c}function O(a,b,c){var d={chartX:a.chartX,chartY:a.chartY,guideBox:c&&{x:c.attr("x"),y:c.attr("y"),width:c.attr("width"),height:c.attr("height")},points:{}};b.forEach(function(b){var c={};p(b.series.dragDropProps,function(d,e){d=b.series[d.axis+"Axis"];c[e]=b[e];c[e+"Offset"]=d.toPixels(b[e])-(d.horiz?a.chartX:a.chartY)});c.point=b;d.points[b.id]=c});return d}function P(a){var b=a.series,c=[],d=b.options.dragDrop.groupBy;b.isSeriesBoosting?b.options.data.forEach(function(a,d){c.push((new b.pointClass).init(b, +a));c[c.length-1].index=d}):c=b.points;return a.options[d]?c.filter(function(b){return b.options[d]===a.options[d]}):[a]}function D(a,b){var c=P(b),d=b.series,e=d.chart,q;w(d.options.dragDrop&&d.options.dragDrop.liveRedraw,!0)||(e.dragGuideBox=q=d.getGuideBox(c),e.setGuideBoxState("default",d.options.dragDrop.guideBox).add(d.group));e.dragDropData={origin:O(a,c,q),point:b,groupedPoints:c,isDragging:!0}}function Q(a,b){var c=a.point,d=r(c.series.options.dragDrop,c.options.dragDrop),e={},q=a.updateProp, +C={};p(c.series.dragDropProps,function(a,b){if(!q||q===b&&a.resize&&(!a.optionName||!1!==d[a.optionName]))if(q||a.move&&("x"===a.axis&&d.draggableX||"y"===a.axis&&d.draggableY))e[b]=a});(q?[c]:a.groupedPoints).forEach(function(c){C[c.id]={point:c,newValues:c.getDropValues(a.origin,b,e)}});return C}function E(a,b){var c=a.dragDropData.newPoints;b=!1===b?!1:r({duration:400},a.options.chart.animation);a.isDragDropAnimating=!0;p(c,function(a){a.point.update(a.newValues,!1)});a.redraw(b);setTimeout(function(){delete a.isDragDropAnimating; +a.hoverPoint&&!a.dragHandles&&a.hoverPoint.showDragHandles()},b.duration)}function F(a){var b=a.series&&a.series.chart,c=b&&b.dragDropData;!b||!b.dragHandles||c&&(c.isDragging&&c.draggedPastSensitivity||c.isHoveringHandle===a.id)||b.hideDragHandles()}function G(a){var b=0,c;for(c in a)Object.hasOwnProperty.call(a,c)&&b++;return b}function H(a){for(var b in a)if(Object.hasOwnProperty.call(a,b))return a[b]}function R(a,b){if(!b.zoomOrPanKeyPressed(a)){var c=b.dragDropData;var d=0;if(c&&c.isDragging){var e= +c.point;d=e.series.options.dragDrop;a.preventDefault();c.draggedPastSensitivity||(c.draggedPastSensitivity=N(a,b,w(e.options.dragDrop&&e.options.dragDrop.dragSensitivity,d&&d.dragSensitivity,2)));c.draggedPastSensitivity&&(c.newPoints=Q(c,a),b=c.newPoints,d=G(b),b=1===d?H(b):null,e.firePointEvent("drag",{origin:c.origin,newPoints:c.newPoints,newPoint:b&&b.newValues,newPointId:b&&b.point.id,numNewPoints:d,chartX:a.chartX,chartY:a.chartY},function(){var b=e.series,c=b.chart,d=c.dragDropData,f=r(b.options.dragDrop, +e.options.dragDrop),g=f.draggableX,l=f.draggableY;b=d.origin;var h=a.chartX-b.chartX,z=a.chartY-b.chartY,n=h;d=d.updateProp;c.inverted&&(h=-z,z=-n);if(w(f.liveRedraw,!0))E(c,!1),e.showDragHandles();else if(d){g=h;c=z;n=e.series;l=n.chart;d=l.dragDropData;f=n.dragDropProps[d.updateProp];var k=d.newPoints[e.id].newValues;var m="function"===typeof f.resizeSide?f.resizeSide(k,e):f.resizeSide;f.beforeResize&&f.beforeResize(l.dragGuideBox,k,e);l=l.dragGuideBox;n="x"===f.axis&&n.xAxis.reversed||"y"===f.axis&& +n.yAxis.reversed?t(m):m;g="x"===f.axis?g-(d.origin.prevdX||0):0;c="y"===f.axis?c-(d.origin.prevdY||0):0;switch(n){case "left":var p={x:l.attr("x")+g,width:Math.max(1,l.attr("width")-g)};break;case "right":p={width:Math.max(1,l.attr("width")+g)};break;case "top":p={y:l.attr("y")+c,height:Math.max(1,l.attr("height")-c)};break;case "bottom":p={height:Math.max(1,l.attr("height")+c)}}l.attr(p)}else c.dragGuideBox.translate(g?h:0,l?z:0);b.prevdX=h;b.prevdY=z}))}}}function B(a,b){var c=b.dragDropData;if(c&& +c.isDragging&&c.draggedPastSensitivity){var d=c.point,e=c.newPoints,q=G(e),f=1===q?H(e):null;b.dragHandles&&b.hideDragHandles();a.preventDefault();b.cancelClick=!0;d.firePointEvent("drop",{origin:c.origin,chartX:a.chartX,chartY:a.chartY,newPoints:e,numNewPoints:q,newPoint:f&&f.newValues,newPointId:f&&f.point.id},function(){E(b)})}delete b.dragDropData;b.dragGuideBox&&(b.dragGuideBox.destroy(),delete b.dragGuideBox)}function S(a){var b=a.container,c=f.doc;L(a)&&(y(b,["mousedown","touchstart"],function(b){b= +x(b,a);var c=a.hoverPoint,d=r(c&&c.series.options.dragDrop,c&&c.options.dragDrop),f=d.draggableX||!1;d=d.draggableY||!1;a.cancelClick=!1;!f&&!d||a.zoomOrPanKeyPressed(b)||a.hasDraggedAnnotation||(a.dragDropData&&a.dragDropData.isDragging?B(b,a):c&&M(c)&&(a.mouseIsDown=!1,D(b,c),c.firePointEvent("dragStart",b)))}),y(b,["mousemove","touchmove"],function(b){R(x(b,a),a)}),u(b,"mouseleave",function(b){B(x(b,a),a)}),a.unbindDragDropMouseUp=y(c,["mouseup","touchend"],function(b){B(x(b,a),a)}),a.hasAddedDragDropEvents= +!0,u(a,"destroy",function(){a.unbindDragDropMouseUp&&a.unbindDragDropMouseUp()}))}"";var u=k.addEvent,T=k.clamp,r=k.merge,p=k.objectEach,w=k.pick,g=f.seriesTypes;k=function(a){a=a.shapeArgs||a.graphic.getBBox();var b=a.r||0,c=a.height/2;return[["M",0,b],["L",0,c-5],["A",1,1,0,0,0,0,c+5],["A",1,1,0,0,0,0,c-5],["M",0,c+5],["L",0,a.height-b]]};var A=g.line.prototype.dragDropProps={x:{axis:"x",move:!0},y:{axis:"y",move:!0}};g.flags&&(g.flags.prototype.dragDropProps=A);var h=g.column.prototype.dragDropProps= +{x:{axis:"x",move:!0},y:{axis:"y",move:!1,resize:!0,beforeResize:function(a,b,c){var d=c.series.translatedThreshold,e=a.attr("y");b.y>=c.series.options.threshold?(b=a.attr("height"),a.attr({height:Math.max(0,Math.round(b+(d?d-(e+b):0)))})):a.attr({y:Math.round(e+(d?d-e:0))})},resizeSide:function(a,b){var c=b.series.chart.dragHandles;a=a.y>=(b.series.options.threshold||0)?"top":"bottom";b=t(a);c[b]&&(c[b].destroy(),delete c[b]);return a},handlePositioner:function(a){var b=a.shapeArgs||a.graphic.getBBox(); +return{x:b.x,y:a.y>=(a.series.options.threshold||0)?b.y:b.y+b.height}},handleFormatter:function(a){a=a.shapeArgs;var b=a.r||0,c=a.width/2;return["M",b,0,"L",c-5,0,"A",1,1,0,0,0,c+5,0,"A",1,1,0,0,0,c-5,0,"M",c+5,0,"L",a.width-b,0]}}};g.bullet&&(g.bullet.prototype.dragDropProps={x:h.x,y:h.y,target:{optionName:"draggableTarget",axis:"y",move:!0,resize:!0,resizeSide:"top",handlePositioner:function(a){var b=a.targetGraphic.getBBox();return{x:a.barX,y:b.y+b.height/2}},handleFormatter:h.y.handleFormatter}}); +g.columnrange&&(g.columnrange.prototype.dragDropProps={x:{axis:"x",move:!0},low:{optionName:"draggableLow",axis:"y",move:!0,resize:!0,resizeSide:"bottom",handlePositioner:function(a){a=a.shapeArgs||a.graphic.getBBox();return{x:a.x,y:a.y+a.height}},handleFormatter:h.y.handleFormatter,propValidate:function(a,b){return a<=b.high}},high:{optionName:"draggableHigh",axis:"y",move:!0,resize:!0,resizeSide:"top",handlePositioner:function(a){a=a.shapeArgs||a.graphic.getBBox();return{x:a.x,y:a.y}},handleFormatter:h.y.handleFormatter, +propValidate:function(a,b){return a>=b.low}}});g.boxplot&&(g.boxplot.prototype.dragDropProps={x:h.x,low:{optionName:"draggableLow",axis:"y",move:!0,resize:!0,resizeSide:"bottom",handlePositioner:function(a){return{x:a.shapeArgs.x,y:a.lowPlot}},handleFormatter:h.y.handleFormatter,propValidate:function(a,b){return a<=b.q1}},q1:{optionName:"draggableQ1",axis:"y",move:!0,resize:!0,resizeSide:"bottom",handlePositioner:function(a){return{x:a.shapeArgs.x,y:a.q1Plot}},handleFormatter:h.y.handleFormatter, +propValidate:function(a,b){return a<=b.median&&a>=b.low}},median:{axis:"y",move:!0},q3:{optionName:"draggableQ3",axis:"y",move:!0,resize:!0,resizeSide:"top",handlePositioner:function(a){return{x:a.shapeArgs.x,y:a.q3Plot}},handleFormatter:h.y.handleFormatter,propValidate:function(a,b){return a<=b.high&&a>=b.median}},high:{optionName:"draggableHigh",axis:"y",move:!0,resize:!0,resizeSide:"top",handlePositioner:function(a){return{x:a.shapeArgs.x,y:a.highPlot}},handleFormatter:h.y.handleFormatter,propValidate:function(a, +b){return a>=b.q3}}});g.ohlc&&(g.ohlc.prototype.dragDropProps={x:h.x,low:{optionName:"draggableLow",axis:"y",move:!0,resize:!0,resizeSide:"bottom",handlePositioner:function(a){return{x:a.shapeArgs.x,y:a.plotLow}},handleFormatter:h.y.handleFormatter,propValidate:function(a,b){return a<=b.open&&a<=b.close}},high:{optionName:"draggableHigh",axis:"y",move:!0,resize:!0,resizeSide:"top",handlePositioner:function(a){return{x:a.shapeArgs.x,y:a.plotHigh}},handleFormatter:h.y.handleFormatter,propValidate:function(a, +b){return a>=b.open&&a>=b.close}},open:{optionName:"draggableOpen",axis:"y",move:!0,resize:!0,resizeSide:function(a){return a.open>=a.close?"top":"bottom"},handlePositioner:function(a){return{x:a.shapeArgs.x,y:a.plotOpen}},handleFormatter:h.y.handleFormatter,propValidate:function(a,b){return a<=b.high&&a>=b.low}},close:{optionName:"draggableClose",axis:"y",move:!0,resize:!0,resizeSide:function(a){return a.open>=a.close?"bottom":"top"},handlePositioner:function(a){return{x:a.shapeArgs.x,y:a.plotClose}}, +handleFormatter:h.y.handleFormatter,propValidate:function(a,b){return a<=b.high&&a>=b.low}}});if(g.arearange){A=g.columnrange.prototype.dragDropProps;var I=function(a){a=a.graphic?a.graphic.getBBox().width/2+1:4;return[["M",0-a,0],["a",a,a,0,1,0,2*a,0],["a",a,a,0,1,0,-2*a,0]]};g.arearange.prototype.dragDropProps={x:A.x,low:{optionName:"draggableLow",axis:"y",move:!0,resize:!0,resizeSide:"bottom",handlePositioner:function(a){return(a=a.lowerGraphic&&a.lowerGraphic.getBBox())?{x:a.x+a.width/2,y:a.y+ +a.height/2}:{x:-999,y:-999}},handleFormatter:I,propValidate:A.low.propValidate},high:{optionName:"draggableHigh",axis:"y",move:!0,resize:!0,resizeSide:"top",handlePositioner:function(a){return(a=a.upperGraphic&&a.upperGraphic.getBBox())?{x:a.x+a.width/2,y:a.y+a.height/2}:{x:-999,y:-999}},handleFormatter:I,propValidate:A.high.propValidate}}}g.waterfall&&(g.waterfall.prototype.dragDropProps={x:h.x,y:r(h.y,{handleFormatter:function(a){return a.isSum||a.isIntermediateSum?null:h.y.handleFormatter(a)}})}); +if(g.xrange){var J=function(a,b){var c=a.series,d=c.xAxis,e=c.yAxis,f=c.chart.inverted;b=d.toPixels(a[b],!0);var g=e.toPixels(a.y,!0);a=c.columnMetrics?c.columnMetrics.offset:-a.shapeArgs.height/2;f&&(b=d.len-b,g=e.len-g);return{x:Math.round(b),y:Math.round(g+a)}};k=g.xrange.prototype.dragDropProps={y:{axis:"y",move:!0},x:{optionName:"draggableX1",axis:"x",move:!0,resize:!0,resizeSide:"left",handlePositioner:function(a){return J(a,"x")},handleFormatter:k,propValidate:function(a,b){return a<=b.x2}}, +x2:{optionName:"draggableX2",axis:"x",move:!0,resize:!0,resizeSide:"right",handlePositioner:function(a){return J(a,"x2")},handleFormatter:k,propValidate:function(a,b){return a>=b.x}}};g.gantt&&(g.gantt.prototype.dragDropProps={y:k.y,start:r(k.x,{optionName:"draggableStart",validateIndividualDrag:function(a){return!a.milestone}}),end:r(k.x2,{optionName:"draggableEnd",validateIndividualDrag:function(a){return!a.milestone}})})}"gauge pie sunburst wordcloud sankey histogram pareto vector windbarb treemap bellcurve sma map mapline".split(" ").forEach(function(a){g[a]&& +(g[a].prototype.dragDropProps=null)});var U={"default":{className:"highcharts-drag-box-default",lineWidth:1,lineColor:"#888",color:"rgba(0, 0, 0, 0.1)",cursor:"move",zIndex:900}},V={className:"highcharts-drag-handle",color:"#fff",lineColor:"rgba(0, 0, 0, 0.6)",lineWidth:1,zIndex:901};f.Chart.prototype.setGuideBoxState=function(a,b){var c=this.dragGuideBox;b=r(U,b);a=r(b["default"],b[a]);return c.attr({className:a.className,stroke:a.lineColor,strokeWidth:a.lineWidth,fill:a.color,cursor:a.cursor,zIndex:a.zIndex}).css({pointerEvents:"none"})}; +m.prototype.getDropValues=function(a,b,c){var d=this,e=d.series,f=r(e.options.dragDrop,d.options.dragDrop),g={},h=a.points[d.id],k;for(k in c)if(Object.hasOwnProperty.call(c,k)){if("undefined"!==typeof m){var m=!1;break}m=!0}p(c,function(a,c){var q=h[c],n=e[a.axis+"Axis"];n=n.toValue((n.horiz?b.chartX:b.chartY)+h[c+"Offset"]);var v=a.axis.toUpperCase(),k=e[v.toLowerCase()+"Axis"].categories?1:0;k=w(f["dragPrecision"+v],k);var l=w(f["dragMin"+v],-Infinity);v=w(f["dragMax"+v],Infinity);k&&(n=Math.round(n/ +k)*k);n=T(n,l,v);m&&a.propValidate&&!a.propValidate(n,d)||"undefined"===typeof q||(g[c]=n)});return g};f.Series.prototype.getGuideBox=function(a){var b=this.chart,c=Infinity,d=-Infinity,e=Infinity,f=-Infinity,g;a.forEach(function(a){(a=a.graphic&&a.graphic.getBBox()||a.shapeArgs)&&(a.width||a.height||a.x||a.y)&&(g=!0,c=Math.min(a.x,c),d=Math.max(a.x+a.width,d),e=Math.min(a.y,e),f=Math.max(a.y+a.height,f))});return g?b.renderer.rect(c,e,d-c,f-e):b.renderer.g()};m.prototype.showDragHandles=function(){var a= +this,b=a.series,c=b.chart,d=c.renderer,f=r(b.options.dragDrop,a.options.dragDrop);p(b.dragDropProps,function(e,g){var h=r(V,e.handleOptions,f.dragHandle),k={className:h.className,"stroke-width":h.lineWidth,fill:h.color,stroke:h.lineColor},m=h.pathFormatter||e.handleFormatter,l=e.handlePositioner;var p=e.validateIndividualDrag?e.validateIndividualDrag(a):!0;e.resize&&p&&e.resizeSide&&m&&(f["draggable"+e.axis.toUpperCase()]||f[e.optionName])&&!1!==f[e.optionName]&&(c.dragHandles||(c.dragHandles={group:d.g("drag-drop-handles").add(b.markerGroup|| +b.group)}),c.dragHandles.point=a.id,l=l(a),k.d=p=m(a),m="function"===typeof e.resizeSide?e.resizeSide(a.options,a):e.resizeSide,!p||0>l.x||0>l.y||(k.cursor=h.cursor||"x"===e.axis!==!!c.inverted?"ew-resize":"ns-resize",(e=c.dragHandles[m])||(e=c.dragHandles[m]=d.path().add(c.dragHandles.group)),e.translate(l.x,l.y).attr(k),y(e.element,["touchstart","mousedown"],function(b){b=x(b,c);var d=a.series.chart;d.zoomOrPanKeyPressed(b)||(d.mouseIsDown=!1,D(b,a),d.dragDropData.updateProp=b.updateProp=g,a.firePointEvent("dragStart", +b),b.stopPropagation(),b.preventDefault())}),u(c.dragHandles.group.element,"mouseover",function(){c.dragDropData=c.dragDropData||{};c.dragDropData.isHoveringHandle=a.id}),y(c.dragHandles.group.element,["touchend","mouseout"],function(){var b=a.series.chart;b.dragDropData&&a.id===b.dragDropData.isHoveringHandle&&delete b.dragDropData.isHoveringHandle;b.hoverPoint||F(a)})))})};f.Chart.prototype.hideDragHandles=function(){this.dragHandles&&(p(this.dragHandles,function(a,b){"group"!==b&&a.destroy&&a.destroy()}), +this.dragHandles.group&&this.dragHandles.group.destroy&&this.dragHandles.group.destroy(),delete this.dragHandles)};u(m,"mouseOver",function(){var a=this;setTimeout(function(){var b=a.series,c=b&&b.chart,d=c&&c.dragDropData,e=c&&c.is3d&&c.is3d();!c||d&&d.isDragging&&d.draggedPastSensitivity||c.isDragDropAnimating||!b.options.dragDrop||e||(c.dragHandles&&c.hideDragHandles(),a.showDragHandles())},12)});u(m,"mouseOut",function(){var a=this;setTimeout(function(){a.series&&F(a)},10)});u(m,"remove",function(){var a= +this.series.chart,b=a.dragHandles;b&&b.point===this.id&&a.hideDragHandles()});f.Chart.prototype.zoomOrPanKeyPressed=function(a){var b=this.userOptions.chart||{},c=b.panKey&&b.panKey+"Key";return a[b.zoomKey&&b.zoomKey+"Key"]||a[c]};u(f.Chart,"render",function(){this.hasAddedDragDropEvents||S(this)})});t(f,"masters/modules/draggable-points.src.js",[],function(){})}); +//# sourceMappingURL=draggable-points.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/draggable-points.js.map b/librerias/gantt/code/modules/draggable-points.js.map new file mode 100644 index 0000000..026d061 --- /dev/null +++ b/librerias/gantt/code/modules/draggable-points.js.map @@ -0,0 +1 @@ +{"version":3,"file":"draggable-points.js.map","lineCount":39,"mappings":"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","sources":["draggable-points.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","Point","U","flipResizeSide","side","left","right","top","bottom","isSeriesDraggable","series","props","i","objectEach","dragDropProps","val","optionName","push","length","options","dragDrop","isChartDraggable","chart","hasCartesianSeries","polar","isPointMovable","point","seriesDragDropOptions","pointDragDropOptions","hasMovableX","hasMovableY","p","axis","move","draggableX","draggableY","yAxis","xAxis","getNormalizedEvent","e","chartX","chartY","pointer","normalize","addEvents","el","types","removeFuncs","map","type","addEvent","forEach","hasDraggedPastSensitivity","sensitivity","orig","dragDropData","origin","oldX","oldY","newX","newY","Math","sqrt","distance","getPositionSnapshot","points","guideBox","res","x","attr","y","width","height","pointProps","key","toPixels","horiz","id","getGroupedPoints","groupKey","groupBy","isSeriesBoosting","data","pointOptions","init","pointClass","index","filter","comparePoint","initDragDrop","groupedPoints","pick","liveRedraw","dragGuideBox","getGuideBox","setGuideBoxState","add","group","isDragging","getNewPoints","newPos","merge","updateProps","resizeProp","updateProp","hashmap","resize","newValues","getDropValues","updatePoints","animate","newPoints","animOptions","duration","animation","isDragDropAnimating","newPoint","update","redraw","setTimeout","hoverPoint","dragHandles","showDragHandles","mouseOut","draggedPastSensitivity","isHoveringHandle","hideDragHandles","countProps","count","Object","call","getFirstProp","mouseMove","zoomOrPanKeyPressed","numNewPoints","seriesDragDropOpts","preventDefault","dragSensitivity","defaultDragSensitivity","firePointEvent","newPointId","dX","dY","oldDx","inverted","resizeSide","beforeResize","reversed","prevdX","prevdY","updateSide","resizeAttrs","rect","max","translate","mouseUp","cancelClick","destroy","addDragDropEvents","container","doc","dragPoint","dragDropOptions","hasDraggedAnnotation","mouseIsDown","unbindDragDropMouseUp","hasAddedDragDropEvents","clamp","seriesTypes","horizHandleFormatter","shapeArgs","graphic","getBBox","r","centerY","lineDragDropProps","line","prototype","flags","columnDragDropProps","column","pointVals","threshold","translatedThreshold","round","diff","flipSide","handlePositioner","bBox","handleFormatter","radius","centerX","bullet","target","targetGraphic","barX","columnrange","low","propValidate","high","boxplot","lowPlot","q1","q1Plot","median","q3","q3Plot","highPlot","ohlc","plotLow","open","close","plotHigh","plotOpen","plotClose","arearange","columnrangeDragDropProps","arearangeHandleFormatter","lowerGraphic","upperGraphic","waterfall","isSum","isIntermediateSum","xrange","xrangeHandlePositioner","xProp","offsetY","columnMetrics","offset","len","xrangeDragDropProps","x2","gantt","start","validateIndividualDrag","milestone","end","defaultGuideBoxOptions","className","lineWidth","lineColor","color","cursor","zIndex","defaultDragHandleOptions","Chart","H.Chart.prototype.setGuideBoxState","state","guideBoxOptions","stateOptions","stroke","strokeWidth","fill","css","pointerEvents","Point.prototype.getDropValues","result","pointOrigin","updateSingleProp","oldVal","toValue","toUpperCase","defaultPrecision","direction","toLowerCase","categories","precision","min","Infinity","newVal","Series","H.Series.prototype.getGuideBox","minX","maxX","minY","maxY","changed","renderer","g","Point.prototype.showDragHandles","handleOptions","dragHandle","handleAttrs","pathFormatter","positioner","validate","markerGroup","pos","d","handleSide","handle","element","stopPropagation","H.Chart.prototype.hideDragHandles","is3d","H.Chart.prototype.zoomOrPanKeyPressed","chartOptions","userOptions","panKey","zoomKey"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/draggable-points.src.js b/librerias/gantt/code/modules/draggable-points.src.js new file mode 100644 index 0000000..b849171 --- /dev/null +++ b/librerias/gantt/code/modules/draggable-points.src.js @@ -0,0 +1,2286 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * (c) 2009-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/draggable-points', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'modules/draggable-points.src.js', [_modules['parts/Globals.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js']], function (H, Point, U) { + /* * + * + * (c) 2009-2020 Highsoft AS + * + * Authors: Øystein Moseng, Torstein Hønsi, Jon A. Nygård + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Current drag and drop position. + * + * @interface Highcharts.DragDropPositionObject + */ /** + * Chart x position + * @name Highcharts.DragDropPositionObject#chartX + * @type {number} + */ /** + * Chart y position + * @name Highcharts.DragDropPositionObject#chartY + * @type {number} + */ /** + * Drag and drop guide box. + * @name Highcharts.DragDropPositionObject#guideBox + * @type {Highcharts.BBoxObject|undefined} + */ /** + * Updated point data. + * @name Highcharts.DragDropPositionObject#points + * @type {Highcharts.Dictionary>} + */ /** + * Delta of previous x position. + * @name Highcharts.DragDropPositionObject#prevdX + * @type {number|undefined} + */ /** + * Delta of previous y position. + * @name Highcharts.DragDropPositionObject#prevdY + * @type {number|undefined} + */ + /** + * Function callback to execute while series points are dragged. Return false to + * stop the default drag action. + * + * @callback Highcharts.PointDragCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {Highcharts.PointDragEventObject} event + * Event arguments. + */ + /** + * Contains information about a points new values. + * + * @interface Highcharts.PointDragDropObject + */ /** + * New values. + * @name Highcharts.PointDragDropObject#newValues + * @type {Highcharts.Dictionary} + */ /** + * Updated point. + * @name Highcharts.PointDragDropObject#point + * @type {Highcharts.Point} + */ + /** + * Contains common information for a drag event on series points. + * + * @interface Highcharts.PointDragEventObject + */ /** + * New point after drag if only a single one. + * @name Highcharts.PointDropEventObject#newPoint + * @type {Highcharts.PointDragDropObject|undefined} + */ /** + * New point id after drag if only a single one. + * @name Highcharts.PointDropEventObject#newPointId + * @type {string|undefined} + */ /** + * New points during drag. + * @name Highcharts.PointDragEventObject#newPoints + * @type {Highcharts.Dictionary} + */ /** + * Original data. + * @name Highcharts.PointDragEventObject#origin + * @type {Highcharts.DragDropPositionObject} + */ /** + * Prevent default drag action. + * @name Highcharts.PointDragEventObject#preventDefault + * @type {Function} + */ /** + * Target point that caused the event. + * @name Highcharts.PointDragEventObject#target + * @type {Highcharts.Point} + */ /** + * Event type. + * @name Highcharts.PointDragEventObject#type + * @type {"drag"} + */ + /** + * Function callback to execute when a series point is dragged. + * + * @callback Highcharts.PointDragStartCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {Highcharts.PointDragStartEventObject} event + * Event arguments. + */ + /** + * Contains common information for a drag event on series point. + * + * @interface Highcharts.PointDragStartEventObject + * @extends global.MouseEvent + */ /** + * Data property being dragged. + * @name Highcharts.PointDragStartEventObject#updateProp + * @type {string|undefined} + */ + /** + * Function callback to execute when series points are dropped. + * + * @callback Highcharts.PointDropCallbackFunction + * + * @param {Highcharts.Point} this + * Point where the event occured. + * + * @param {Highcharts.PointDropEventObject} event + * Event arguments. + */ + /** + * Contains common information for a drop event on series points. + * + * @interface Highcharts.PointDropEventObject + */ /** + * New point after drop if only a single one. + * @name Highcharts.PointDropEventObject#newPoint + * @type {Highcharts.PointDragDropObject|undefined} + */ /** + * New point id after drop if only a single one. + * @name Highcharts.PointDropEventObject#newPointId + * @type {string|undefined} + */ /** + * New points after drop. + * @name Highcharts.PointDropEventObject#newPoints + * @type {Highcharts.Dictionary} + */ /** + * Number of new points. + * @name Highcharts.PointDropEventObject#numNewPoints + * @type {number} + */ /** + * Original data. + * @name Highcharts.PointDropEventObject#origin + * @type {Highcharts.DragDropPositionObject} + */ /** + * Prevent default drop action. + * @name Highcharts.PointDropEventObject#preventDefault + * @type {Function} + */ /** + * Target point that caused the event. + * @name Highcharts.PointDropEventObject#target + * @type {Highcharts.Point} + */ /** + * Event type. + * @name Highcharts.PointDropEventObject#type + * @type {"drop"} + */ + ''; // detaches doclets above + var addEvent = U.addEvent, clamp = U.clamp, merge = U.merge, objectEach = U.objectEach, pick = U.pick; + var seriesTypes = H.seriesTypes; + /** + * Flip a side property, used with resizeRect. If input side is "left", return + * "right" etc. + * + * @private + * @function flipResizeSide + * + * @param {string} side + * Side prop to flip. Can be `left`, `right`, `top` or `bottom`. + * + * @return {"bottom"|"left"|"right"|"top"|undefined} + * The flipped side. + */ + function flipResizeSide(side) { + return { + left: 'right', + right: 'left', + top: 'bottom', + bottom: 'top' + }[side]; + } + /* @todo + Add drag/drop support to specific data props for different series types. + + The dragDrop.draggableX/Y user options on series enable/disable all of these per + irection unless they are specifically set in options using + dragDrop.{optionName}. If the prop does not specify an optionName here, it can + only be enabled/disabled by the user with draggableX/Y. + + Supported options for each prop: + optionName: User option in series.dragDrop that enables/disables + dragging this prop. + axis: Can be 'x' or 'y'. Whether this prop is linked to x or y axis. + move: Whether or not this prop should be updated when moving points. + resize: Whether or not to draw a drag handle and allow user to drag and + update this prop by itself. + beforeResize: Hook to perform tasks before a resize is made. Gets + the guide box, the new points values, and the point as args. + resizeSide: Which side of the guide box to resize when dragging the + handle. Can be "left", "right", "top", "bottom". Chart.inverted is + handled automatically. Can also be a function, taking the new point + values as parameter, as well as the point, and returning a string + with the side. + propValidate: Function that takes the prop value and the point as + arguments, and returns true if the prop value is valid, false if + not. It is used to prevent e.g. resizing "low" above "high". + handlePositioner: For resizeable props, return 0,0 in SVG plot coords of + where to place the dragHandle. Gets point as argument. Should return + object with x and y properties. + handleFormatter: For resizeable props, return the path of the drag + handle as an SVG path array. Gets the point as argument. The handle + is translated according to handlePositioner. + handleOptions: Options to merge with the default handle options. + + TODO: + - It makes sense to have support for resizing the size of bubbles and + e.g variwide columns. This requires us to support dragging along a + z-axis, somehow computing a relative value from old to new pixel + size. + - Moving maps could be useful, although we would have to compute new + point.path values in order to do it properly (using SVG translate + is easier, but won't update the data). + */ + // 90deg rotated column handle path, used in multiple series types + var horizHandleFormatter = function (point) { + var shapeArgs = point.shapeArgs || point.graphic.getBBox(), top = shapeArgs.r || 0, // Rounding of bar corners + bottom = shapeArgs.height - top, centerY = shapeArgs.height / 2; + return [ + // Top wick + ['M', 0, top], + ['L', 0, centerY - 5], + // Circle + ['A', 1, 1, 0, 0, 0, 0, centerY + 5], + ['A', 1, 1, 0, 0, 0, 0, centerY - 5], + // Bottom wick + ['M', 0, centerY + 5], + ['L', 0, bottom] + ]; + }; + // Line series - only draggableX/Y, no drag handles + var lineDragDropProps = seriesTypes.line.prototype.dragDropProps = { + x: { + axis: 'x', + move: true + }, + y: { + axis: 'y', + move: true + } + }; + // Flag series - same as line/scatter + if (seriesTypes.flags) { + seriesTypes.flags.prototype.dragDropProps = lineDragDropProps; + } + // Column series - x can be moved, y can only be resized. Note extra + // functionality for handling upside down columns (below threshold). + var columnDragDropProps = seriesTypes.column.prototype.dragDropProps = { + x: { + axis: 'x', + move: true + }, + y: { + axis: 'y', + move: false, + resize: true, + // Force guideBox start coordinates + beforeResize: function (guideBox, pointVals, point) { + // We need to ensure that guideBox always starts at threshold. + // We flip whether or not we update the top or bottom of the guide + // box at threshold, but if we drag the mouse fast, the top has not + // reached threshold before we cross over and update the bottom. + var threshold = point.series.translatedThreshold, y = guideBox.attr('y'), height, diff; + if (pointVals.y >= point.series.options.threshold || 0) { + // Above threshold - always set height to hit the threshold + height = guideBox.attr('height'); + diff = threshold ? + threshold - (y + height) : + 0; + guideBox.attr({ + height: Math.max(0, Math.round(height + diff)) + }); + } + else { + // Below - always set y to start at threshold + guideBox.attr({ + y: Math.round(y + (threshold ? threshold - y : 0)) + }); + } + }, + // Flip the side of the resize handle if column is below threshold. + // Make sure we remove the handle on the other side. + resizeSide: function (pointVals, point) { + var chart = point.series.chart, dragHandles = chart.dragHandles, side = pointVals.y >= (point.series.options.threshold || 0) ? + 'top' : 'bottom', flipSide = flipResizeSide(side); + // Force remove handle on other side + if (dragHandles[flipSide]) { + dragHandles[flipSide].destroy(); + delete dragHandles[flipSide]; + } + return side; + }, + // Position handle at bottom if column is below threshold + handlePositioner: function (point) { + var bBox = point.shapeArgs || point.graphic.getBBox(); + return { + x: bBox.x, + y: point.y >= (point.series.options.threshold || 0) ? + bBox.y : bBox.y + bBox.height + }; + }, + // Horizontal handle + handleFormatter: function (point) { + var shapeArgs = point.shapeArgs, radius = shapeArgs.r || 0, // Rounding of bar corners + centerX = shapeArgs.width / 2; + return [ + // Left wick + 'M', radius, 0, + 'L', centerX - 5, 0, + // Circle + 'A', 1, 1, 0, 0, 0, centerX + 5, 0, + 'A', 1, 1, 0, 0, 0, centerX - 5, 0, + // Right wick + 'M', centerX + 5, 0, + 'L', shapeArgs.width - radius, 0 + ]; + } + } + }; + // Bullet graph, x/y same as column, but also allow target to be dragged. + if (seriesTypes.bullet) { + seriesTypes.bullet.prototype.dragDropProps = { + x: columnDragDropProps.x, + y: columnDragDropProps.y, + /** + * Allow target value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.bullet.dragDrop.draggableTarget + */ + target: { + optionName: 'draggableTarget', + axis: 'y', + move: true, + resize: true, + resizeSide: 'top', + handlePositioner: function (point) { + var bBox = point.targetGraphic.getBBox(); + return { + x: point.barX, + y: bBox.y + bBox.height / 2 + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter + } + }; + } + // Columnrange series - move x, resize or move low/high + if (seriesTypes.columnrange) { + seriesTypes.columnrange.prototype.dragDropProps = { + x: { + axis: 'x', + move: true + }, + /** + * Allow low value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.columnrange.dragDrop.draggableLow + */ + low: { + optionName: 'draggableLow', + axis: 'y', + move: true, + resize: true, + resizeSide: 'bottom', + handlePositioner: function (point) { + var bBox = point.shapeArgs || point.graphic.getBBox(); + return { + x: bBox.x, + y: bBox.y + bBox.height + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter, + propValidate: function (val, point) { + return val <= point.high; + } + }, + /** + * Allow high value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.columnrange.dragDrop.draggableHigh + */ + high: { + optionName: 'draggableHigh', + axis: 'y', + move: true, + resize: true, + resizeSide: 'top', + handlePositioner: function (point) { + var bBox = point.shapeArgs || point.graphic.getBBox(); + return { + x: bBox.x, + y: bBox.y + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter, + propValidate: function (val, point) { + return val >= point.low; + } + } + }; + } + // Boxplot series - move x, resize or move low/q1/q3/high + if (seriesTypes.boxplot) { + seriesTypes.boxplot.prototype.dragDropProps = { + x: columnDragDropProps.x, + /** + * Allow low value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.boxplot.dragDrop.draggableLow + */ + low: { + optionName: 'draggableLow', + axis: 'y', + move: true, + resize: true, + resizeSide: 'bottom', + handlePositioner: function (point) { + return { + x: point.shapeArgs.x, + y: point.lowPlot + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter, + propValidate: function (val, point) { + return val <= point.q1; + } + }, + /** + * Allow Q1 value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.boxplot.dragDrop.draggableQ1 + */ + q1: { + optionName: 'draggableQ1', + axis: 'y', + move: true, + resize: true, + resizeSide: 'bottom', + handlePositioner: function (point) { + return { + x: point.shapeArgs.x, + y: point.q1Plot + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter, + propValidate: function (val, point) { + return val <= point.median && val >= point.low; + } + }, + median: { + // Median can not be dragged individually, just move the whole + // point for this. + axis: 'y', + move: true + }, + /** + * Allow Q3 value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.boxplot.dragDrop.draggableQ3 + */ + q3: { + optionName: 'draggableQ3', + axis: 'y', + move: true, + resize: true, + resizeSide: 'top', + handlePositioner: function (point) { + return { + x: point.shapeArgs.x, + y: point.q3Plot + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter, + propValidate: function (val, point) { + return val <= point.high && val >= point.median; + } + }, + /** + * Allow high value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.boxplot.dragDrop.draggableHigh + */ + high: { + optionName: 'draggableHigh', + axis: 'y', + move: true, + resize: true, + resizeSide: 'top', + handlePositioner: function (point) { + return { + x: point.shapeArgs.x, + y: point.highPlot + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter, + propValidate: function (val, point) { + return val >= point.q3; + } + } + }; + } + // OHLC series - move x, resize or move open/high/low/close + if (seriesTypes.ohlc) { + seriesTypes.ohlc.prototype.dragDropProps = { + x: columnDragDropProps.x, + /** + * Allow low value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.ohlc.dragDrop.draggableLow + */ + low: { + optionName: 'draggableLow', + axis: 'y', + move: true, + resize: true, + resizeSide: 'bottom', + handlePositioner: function (point) { + return { + x: point.shapeArgs.x, + y: point.plotLow + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter, + propValidate: function (val, point) { + return val <= point.open && val <= point.close; + } + }, + /** + * Allow high value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.ohlc.dragDrop.draggableHigh + */ + high: { + optionName: 'draggableHigh', + axis: 'y', + move: true, + resize: true, + resizeSide: 'top', + handlePositioner: function (point) { + return { + x: point.shapeArgs.x, + y: point.plotHigh + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter, + propValidate: function (val, point) { + return val >= point.open && val >= point.close; + } + }, + /** + * Allow open value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.ohlc.dragDrop.draggableOpen + */ + open: { + optionName: 'draggableOpen', + axis: 'y', + move: true, + resize: true, + resizeSide: function (point) { + return point.open >= point.close ? 'top' : 'bottom'; + }, + handlePositioner: function (point) { + return { + x: point.shapeArgs.x, + y: point.plotOpen + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter, + propValidate: function (val, point) { + return val <= point.high && val >= point.low; + } + }, + /** + * Allow close value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.ohlc.dragDrop.draggableClose + */ + close: { + optionName: 'draggableClose', + axis: 'y', + move: true, + resize: true, + resizeSide: function (point) { + return point.open >= point.close ? 'bottom' : 'top'; + }, + handlePositioner: function (point) { + return { + x: point.shapeArgs.x, + y: point.plotClose + }; + }, + handleFormatter: columnDragDropProps.y.handleFormatter, + propValidate: function (val, point) { + return val <= point.high && val >= point.low; + } + } + }; + } + // Arearange series - move x, resize or move low/high + if (seriesTypes.arearange) { + var columnrangeDragDropProps = seriesTypes.columnrange.prototype.dragDropProps, + // Use a circle covering the marker as drag handle + arearangeHandleFormatter = function (point) { + var radius = point.graphic ? + point.graphic.getBBox().width / 2 + 1 : + 4; + return [ + ['M', 0 - radius, 0], + ['a', radius, radius, 0, 1, 0, radius * 2, 0], + ['a', radius, radius, 0, 1, 0, radius * -2, 0] + ]; + }; + seriesTypes.arearange.prototype.dragDropProps = { + x: columnrangeDragDropProps.x, + /** + * Allow low value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.arearange.dragDrop.draggableLow + */ + low: { + optionName: 'draggableLow', + axis: 'y', + move: true, + resize: true, + resizeSide: 'bottom', + handlePositioner: function (point) { + var bBox = point.lowerGraphic && point.lowerGraphic.getBBox(); + return bBox ? { + x: bBox.x + bBox.width / 2, + y: bBox.y + bBox.height / 2 + } : { x: -999, y: -999 }; + }, + handleFormatter: arearangeHandleFormatter, + propValidate: columnrangeDragDropProps.low.propValidate + }, + /** + * Allow high value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.arearange.dragDrop.draggableHigh + */ + high: { + optionName: 'draggableHigh', + axis: 'y', + move: true, + resize: true, + resizeSide: 'top', + handlePositioner: function (point) { + var bBox = point.upperGraphic && point.upperGraphic.getBBox(); + return bBox ? { + x: bBox.x + bBox.width / 2, + y: bBox.y + bBox.height / 2 + } : { x: -999, y: -999 }; + }, + handleFormatter: arearangeHandleFormatter, + propValidate: columnrangeDragDropProps.high.propValidate + } + }; + } + // Waterfall - mostly as column, but don't show drag handles for sum points + if (seriesTypes.waterfall) { + seriesTypes.waterfall.prototype.dragDropProps = { + x: columnDragDropProps.x, + y: merge(columnDragDropProps.y, { + handleFormatter: function (point) { + return point.isSum || point.isIntermediateSum ? null : + columnDragDropProps.y.handleFormatter(point); + } + }) + }; + } + // Xrange - resize/move x/x2, and move y + if (seriesTypes.xrange) { + // Handle positioner logic is the same for x and x2 apart from the + // x value. shapeArgs does not take yAxis reversed etc into account, so we + // use axis.toPixels to handle positioning. + var xrangeHandlePositioner = function (point, xProp) { + var series = point.series, xAxis = series.xAxis, yAxis = series.yAxis, inverted = series.chart.inverted, + // Using toPixels handles axis.reversed, but doesn't take + // chart.inverted into account. + newX = xAxis.toPixels(point[xProp], true), newY = yAxis.toPixels(point.y, true), offsetY = series.columnMetrics ? series.columnMetrics.offset : + -point.shapeArgs.height / 2; + // Handle chart inverted + if (inverted) { + newX = xAxis.len - newX; + newY = yAxis.len - newY; + } + newY += offsetY; // (#12872) + return { + x: Math.round(newX), + y: Math.round(newY) + }; + }, xrangeDragDropProps = seriesTypes.xrange.prototype.dragDropProps = { + y: { + axis: 'y', + move: true + }, + /** + * Allow x value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.xrange.dragDrop.draggableX1 + */ + x: { + optionName: 'draggableX1', + axis: 'x', + move: true, + resize: true, + resizeSide: 'left', + handlePositioner: function (point) { + return xrangeHandlePositioner(point, 'x'); + }, + handleFormatter: horizHandleFormatter, + propValidate: function (val, point) { + return val <= point.x2; + } + }, + /** + * Allow x2 value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.xrange.dragDrop.draggableX2 + */ + x2: { + optionName: 'draggableX2', + axis: 'x', + move: true, + resize: true, + resizeSide: 'right', + handlePositioner: function (point) { + return xrangeHandlePositioner(point, 'x2'); + }, + handleFormatter: horizHandleFormatter, + propValidate: function (val, point) { + return val >= point.x; + } + } + }; + // Gantt - same as xrange, but with aliases + if (seriesTypes.gantt) { + seriesTypes.gantt.prototype.dragDropProps = { + y: xrangeDragDropProps.y, + /** + * Allow start value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.gantt.dragDrop.draggableStart + */ + start: merge(xrangeDragDropProps.x, { + optionName: 'draggableStart', + // Do not allow individual drag handles for milestones + validateIndividualDrag: function (point) { + return !point.milestone; + } + }), + /** + * Allow end value to be dragged individually. + * + * @type {boolean} + * @default true + * @requires modules/draggable-points + * @apioption plotOptions.gantt.dragDrop.draggableEnd + */ + end: merge(xrangeDragDropProps.x2, { + optionName: 'draggableEnd', + // Do not allow individual drag handles for milestones + validateIndividualDrag: function (point) { + return !point.milestone; + } + }) + }; + } + } + // Don't support certain series types + [ + 'gauge', + 'pie', + 'sunburst', + 'wordcloud', + 'sankey', + 'histogram', + 'pareto', + 'vector', + 'windbarb', + 'treemap', + 'bellcurve', + 'sma', + 'map', + 'mapline' + ].forEach( + /** + * @private + * @param {string} type + * Unsupported series type + * @return {void} + */ + function (type) { + if (seriesTypes[type]) { + seriesTypes[type].prototype.dragDropProps = null; + } + }); + /** + * The draggable-points module allows points to be moved around or modified in + * the chart. In addition to the options mentioned under the `dragDrop` API + * structure, the module fires three events, + * [point.dragStart](plotOptions.series.point.events.dragStart), + * [point.drag](plotOptions.series.point.events.drag) and + * [point.drop](plotOptions.series.point.events.drop). + * + * @sample highcharts/dragdrop/resize-column + * Draggable column and line series + * @sample highcharts/dragdrop/bar-series + * Draggable bar + * @sample highcharts/dragdrop/drag-bubble + * Draggable bubbles + * @sample highcharts/dragdrop/drag-xrange + * Draggable X range series + * + * @declare Highcharts.SeriesDragDropOptionsObject + * @since 6.2.0 + * @requires modules/draggable-points + * @apioption plotOptions.series.dragDrop + */ + /** + * The amount of pixels to drag the pointer before it counts as a drag + * operation. This prevents drag/drop to fire when just clicking or selecting + * points. + * + * @type {number} + * @default 2 + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.dragSensitivity + * + * @private + */ + var defaultDragSensitivity = 2; + /** + * Style options for the guide box. The guide box has one state by default, the + * `default` state. + * + * @type {Highcharts.Dictionary} + * @since 6.2.0 + * @optionparent plotOptions.series.dragDrop.guideBox + * + * @private + */ + var defaultGuideBoxOptions = { + /** + * Style options for the guide box default state. + * + * @declare Highcharts.DragDropGuideBoxOptionsObject + * @since 6.2.0 + */ + 'default': { + /** + * CSS class name of the guide box in this state. Defaults to + * `highcharts-drag-box-default`. + * + * @since 6.2.0 + */ + className: 'highcharts-drag-box-default', + /** + * Width of the line around the guide box. + * + * @since 6.2.0 + */ + lineWidth: 1, + /** + * Color of the border around the guide box. + * + * @type {Highcharts.ColorString} + * @since 6.2.0 + */ + lineColor: '#888', + /** + * Guide box fill color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 6.2.0 + */ + color: 'rgba(0, 0, 0, 0.1)', + /** + * Guide box cursor. + * + * @since 6.2.0 + */ + cursor: 'move', + /** + * Guide box zIndex. + * + * @since 6.2.0 + */ + zIndex: 900 + } + }; + /** + * Options for the drag handles. + * + * @declare Highcharts.DragDropHandleOptionsObject + * @since 6.2.0 + * @optionparent plotOptions.series.dragDrop.dragHandle + * + * @private + */ + var defaultDragHandleOptions = { + /** + * Function to define the SVG path to use for the drag handles. Takes the + * point as argument. Should return an SVG path in array format. The SVG + * path is automatically positioned on the point. + * + * @type {Function} + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.dragHandle.pathFormatter + */ + // pathFormatter: null, + /** + * The mouse cursor to use for the drag handles. By default this is + * intelligently switching between `ew-resize` and `ns-resize` depending on + * the direction the point is being dragged. + * + * @type {string} + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.dragHandle.cursor + */ + // cursor: null, + /** + * The class name of the drag handles. Defaults to `highcharts-drag-handle`. + * + * @since 6.2.0 + */ + className: 'highcharts-drag-handle', + /** + * The fill color of the drag handles. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 6.2.0 + */ + color: '#fff', + /** + * The line color of the drag handles. + * + * @type {Highcharts.ColorString} + * @since 6.2.0 + */ + lineColor: 'rgba(0, 0, 0, 0.6)', + /** + * The line width for the drag handles. + * + * @since 6.2.0 + */ + lineWidth: 1, + /** + * The z index for the drag handles. + * + * @since 6.2.0 + */ + zIndex: 901 + }; + /** + * Set the minimum X value the points can be moved to. + * + * @sample {gantt} gantt/dragdrop/drag-gantt + * Limit dragging + * @sample {highcharts} highcharts/dragdrop/drag-xrange + * Limit dragging + * + * @type {number} + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.dragMinX + */ + /** + * Set the maximum X value the points can be moved to. + * + * @sample {gantt} gantt/dragdrop/drag-gantt + * Limit dragging + * @sample {highcharts} highcharts/dragdrop/drag-xrange + * Limit dragging + * + * @type {number} + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.dragMaxX + */ + /** + * Set the minimum Y value the points can be moved to. + * + * @sample {gantt} gantt/dragdrop/drag-gantt + * Limit dragging + * @sample {highcharts} highcharts/dragdrop/drag-xrange + * Limit dragging + * + * @type {number} + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.dragMinY + */ + /** + * Set the maximum Y value the points can be moved to. + * + * @sample {gantt} gantt/dragdrop/drag-gantt + * Limit dragging + * @sample {highcharts} highcharts/dragdrop/drag-xrange + * Limit dragging + * + * @type {number} + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.dragMaxY + */ + /** + * The X precision value to drag to for this series. Set to 0 to disable. By + * default this is disabled, except for category axes, where the default is 1. + * + * @type {number} + * @default 0 + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.dragPrecisionX + */ + /** + * The Y precision value to drag to for this series. Set to 0 to disable. By + * default this is disabled, except for category axes, where the default is 1. + * + * @type {number} + * @default 0 + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.dragPrecisionY + */ + /** + * Enable dragging in the X dimension. + * + * @type {boolean} + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.draggableX + */ + /** + * Enable dragging in the Y dimension. Note that this is not supported for + * TreeGrid axes (the default axis type in Gantt charts). + * + * @type {boolean} + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.draggableY + */ + /** + * Group the points by a property. Points with the same property value will be + * grouped together when moving. + * + * @sample {gantt} gantt/dragdrop/drag-gantt + * Drag grouped points + * @sample {highcharts} highcharts/dragdrop/drag-xrange + * Drag grouped points + * + * @type {string} + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.groupBy + */ + /** + * Update points as they are dragged. If false, a guide box is drawn to + * illustrate the new point size. + * + * @sample {gantt} gantt/dragdrop/drag-gantt + * liveRedraw disabled + * @sample {highcharts} highcharts/dragdrop/drag-xrange + * liveRedraw disabled + * + * @type {boolean} + * @default true + * @since 6.2.0 + * @apioption plotOptions.series.dragDrop.liveRedraw + */ + /** + * Set a key to hold when dragging to zoom the chart. This is useful to avoid + * zooming while moving points. Should be set different than + * [chart.panKey](#chart.panKey). + * + * @type {string} + * @since 6.2.0 + * @validvalue ["alt", "ctrl", "meta", "shift"] + * @requires modules/draggable-points + * @apioption chart.zoomKey + */ + /** + * Callback that fires when starting to drag a point. The mouse event object is + * passed in as an argument. If a drag handle is used, `e.updateProp` is set to + * the data property being dragged. The `this` context is the point. See + * [drag and drop options](plotOptions.series.dragDrop). + * + * @sample {highcharts} highcharts/dragdrop/drag-xrange + * Drag events + * + * @type {Highcharts.PointDragStartCallbackFunction} + * @since 6.2.0 + * @requires modules/draggable-points + * @apioption plotOptions.series.point.events.dragStart + */ + /** + * Callback that fires while dragging a point. The mouse event is passed in as + * parameter. The original data can be accessed from `e.origin`, and the new + * point values can be accessed from `e.newPoints`. If there is only a single + * point being updated, it can be accessed from `e.newPoint` for simplicity, and + * its ID can be accessed from `e.newPointId`. The `this` context is the point + * being dragged. To stop the default drag action, return false. See + * [drag and drop options](plotOptions.series.dragDrop). + * + * @sample {highcharts} highcharts/dragdrop/drag-xrange + * Drag events + * + * @type {Highcharts.PointDragCallbackFunction} + * @since 6.2.0 + * @requires modules/draggable-points + * @apioption plotOptions.series.point.events.drag + */ + /** + * Callback that fires when the point is dropped. The parameters passed are the + * same as for [drag](#plotOptions.series.point.events.drag). To stop the + * default drop action, return false. See + * [drag and drop options](plotOptions.series.dragDrop). + * + * @sample {highcharts} highcharts/dragdrop/drag-xrange + * Drag events + * + * @type {Highcharts.PointDropCallbackFunction} + * @since 6.2.0 + * @requires modules/draggable-points + * @apioption plotOptions.series.point.events.drop + */ + /** + * Point specific options for the draggable-points module. Overrides options on + * `series.dragDrop`. + * + * @declare Highcharts.SeriesLineDataDragDropOptions + * @extends plotOptions.series.dragDrop + * @since 6.2.0 + * @requires modules/draggable-points + * @apioption series.line.data.dragDrop + */ + /** + * Utility function to test if a series is using drag/drop, looking at its + * options. + * + * @private + * @function isSeriesDraggable + * @param {Highcharts.Series} series + * The series to test. + * @return {boolean} + * True if the series is using drag/drop. + */ + function isSeriesDraggable(series) { + var props = ['draggableX', 'draggableY'], i; + // Add optionNames from dragDropProps to the array of props to check for + objectEach(series.dragDropProps, function (val) { + if (val.optionName) { + props.push(val.optionName); + } + }); + // Loop over all options we have that could enable dragDrop for this + // series. If any of them are truthy, this series is draggable. + i = props.length; + while (i--) { + if (series.options.dragDrop[props[i]]) { + return true; + } + } + } + /** + * Utility function to test if a chart should have drag/drop enabled, looking at + * its options. + * + * @private + * @function isChartDraggable + * @param {Highcharts.Chart} chart + * The chart to test. + * @return {boolean} + * True if the chart is drag/droppable. + */ + function isChartDraggable(chart) { + var i = chart.series ? chart.series.length : 0; + if (chart.hasCartesianSeries && !chart.polar) { + while (i--) { + if (chart.series[i].options.dragDrop && + isSeriesDraggable(chart.series[i])) { + return true; + } + } + } + } + /** + * Utility function to test if a point is movable (any of its props can be + * dragged by a move, not just individually). + * + * @private + * @function isPointMovable + * @param {Highcharts.Point} point + * The point to test. + * @return {boolean} + * True if the point is movable. + */ + function isPointMovable(point) { + var series = point.series, seriesDragDropOptions = series.options.dragDrop || {}, pointDragDropOptions = point.options && point.options.dragDrop, updateProps = series.dragDropProps, hasMovableX, hasMovableY; + objectEach(updateProps, function (p) { + if (p.axis === 'x' && p.move) { + hasMovableX = true; + } + else if (p.axis === 'y' && p.move) { + hasMovableY = true; + } + }); + // We can only move the point if draggableX/Y is set, even if all the + // individual prop options are set. + return ((seriesDragDropOptions.draggableX && hasMovableX || + seriesDragDropOptions.draggableY && hasMovableY) && + !(pointDragDropOptions && + pointDragDropOptions.draggableX === false && + pointDragDropOptions.draggableY === false) && + series.yAxis && + series.xAxis); + } + /** + * Take a mouse/touch event and return the event object with chartX/chartY. + * + * @private + * @function getNormalizedEvent + * @param {global.PointerEvent} e + * The event to normalize. + * @param {Highcharts.Chart} chart + * The related chart. + * @return {Highcharts.PointerEventLObject} + * The normalized event. + */ + function getNormalizedEvent(e, chart) { + return (typeof e.chartX === 'undefined' || + typeof e.chartY === 'undefined' ? + chart.pointer.normalize(e) : + e); + } + /** + * Add multiple event listeners with the same handler to the same element. + * + * @private + * @function addEvents + * @param {T} el + * The element or object to add listeners to. + * @param {Array} types + * Array with the event types this handler should apply to. + * @param {Function|Highcharts.EventCallbackFunction} fn + * The function callback to execute when the events are fired. + * @param {Highcharts.EventOptionsObject} [options] + * Event options: + * - `order`: The order the event handler should be called. This opens + * for having one handler be called before another, independent of in + * which order they were added. + * @return {Function} + * A callback function to remove the added events. + * @template T + */ + function addEvents(el, types, fn, options) { + var removeFuncs = types.map(function (type) { + return addEvent(el, type, fn, options); + }); + return function () { + removeFuncs.forEach(function (fn) { + fn(); + }); + }; + } + /** + * In mousemove events, check that we have dragged mouse further than the + * dragSensitivity before we call mouseMove handler. + * + * @private + * @function hasDraggedPastSensitivity + * + * @param {Highcharts.PointerEventObject} e + * Mouse move event to test. + * + * @param {Highcharts.Chart} chart + * Chart that has started dragging. + * + * @param {number} sensitivity + * Pixel sensitivity to test against. + * + * @return {boolean} + * True if the event is moved past sensitivity relative to the chart's + * drag origin. + */ + function hasDraggedPastSensitivity(e, chart, sensitivity) { + var orig = chart.dragDropData.origin, oldX = orig.chartX, oldY = orig.chartY, newX = e.chartX, newY = e.chartY, distance = Math.sqrt((newX - oldX) * (newX - oldX) + + (newY - oldY) * (newY - oldY)); + return distance > sensitivity; + } + /** + * Get a snapshot of points, mouse position, and guide box dimensions + * + * @private + * @function getPositionSnapshot + * + * @param {Highcharts.PointerEventObject} e + * Mouse event with mouse position to snapshot. + * + * @param {Array} points + * Points to take snapshot of. We store the value of the data properties + * defined in each series' dragDropProps. + * + * @param {Highcharts.SVGElement} [guideBox] + * The guide box to take snapshot of. + * + * @return {object} + * Snapshot object. Point properties are placed in a hashmap with IDs as + * keys. + */ + function getPositionSnapshot(e, points, guideBox) { + var res = { + chartX: e.chartX, + chartY: e.chartY, + guideBox: guideBox && { + x: guideBox.attr('x'), + y: guideBox.attr('y'), + width: guideBox.attr('width'), + height: guideBox.attr('height') + }, + points: {} + }; + // Loop over the points and add their props + points.forEach(function (point) { + var pointProps = {}; + // Add all of the props defined in the series' dragDropProps to the + // snapshot + objectEach(point.series.dragDropProps, function (val, key) { + var axis = point.series[val.axis + 'Axis']; + pointProps[key] = point[key]; + // Record how far cursor was from the point when drag started. + // This later will be used to calculate new value according to the + // current position of the cursor. + // e.g. `high` value is translated to `highOffset` + pointProps[key + 'Offset'] = + // e.g. yAxis.toPixels(point.high), xAxis.toPixels(point.end) + axis.toPixels(point[key]) - + (axis.horiz ? e.chartX : e.chartY); + }); + pointProps.point = point; // Store reference to point + res.points[point.id] = pointProps; + }); + return res; + } + /** + * Get a list of points that are grouped with this point. If only one point is + * in the group, that point is returned by itself in an array. + * + * @private + * @function getGroupedPoints + * @param {Highcharts.Point} point + * Point to find group from. + * @return {Array} + * Array of points in this group. + */ + function getGroupedPoints(point) { + var series = point.series, points = [], groupKey = series.options.dragDrop.groupBy; + if (series.isSeriesBoosting) { // #11156 + series.options.data.forEach(function (pointOptions, i) { + points.push((new series.pointClass()).init(// eslint-disable-line new-cap + series, pointOptions)); + points[points.length - 1].index = i; + }); + } + else { + points = series.points; + } + return point.options[groupKey] ? + // If we have a grouping option, filter the points by that + points.filter(function (comparePoint) { + return comparePoint.options[groupKey] === + point.options[groupKey]; + }) : + // Otherwise return the point by itself only + [point]; + } + /** + * Resize a rect element on one side. The element is modified. + * + * @private + * @function resizeRect + * @param {Highcharts.SVGElement} rect + * Rect element to resize. + * @param {string} updateSide + * Which side of the rect to update. Can be `left`, `right`, `top` or + * `bottom`. + * @param {Highcharts.PositionObject} update + * Object with x and y properties, detailing how much to resize each + * dimension. + * @return {void} + */ + function resizeRect(rect, updateSide, update) { + var resizeAttrs; + switch (updateSide) { + case 'left': + resizeAttrs = { + x: rect.attr('x') + update.x, + width: Math.max(1, rect.attr('width') - update.x) + }; + break; + case 'right': + resizeAttrs = { + width: Math.max(1, rect.attr('width') + update.x) + }; + break; + case 'top': + resizeAttrs = { + y: rect.attr('y') + update.y, + height: Math.max(1, rect.attr('height') - update.y) + }; + break; + case 'bottom': + resizeAttrs = { + height: Math.max(1, rect.attr('height') + update.y) + }; + break; + default: + } + rect.attr(resizeAttrs); + } + /** + * Prepare chart.dragDropData with origin info, and show the guide box. + * + * @private + * @function initDragDrop + * @param {Highcharts.PointerEventObject} e + * Mouse event with original mouse position. + * @param {Highcharts.Point} point + * The point the dragging started on. + * @return {void} + */ + function initDragDrop(e, point) { + var groupedPoints = getGroupedPoints(point), series = point.series, chart = series.chart, guideBox; + // If liveRedraw is disabled, show the guide box with the default state + if (!pick(series.options.dragDrop && series.options.dragDrop.liveRedraw, true)) { + chart.dragGuideBox = guideBox = series.getGuideBox(groupedPoints); + chart + .setGuideBoxState('default', series.options.dragDrop.guideBox) + .add(series.group); + } + // Store some data on the chart to pick up later + chart.dragDropData = { + origin: getPositionSnapshot(e, groupedPoints, guideBox), + point: point, + groupedPoints: groupedPoints, + isDragging: true + }; + } + /** + * Calculate new point options from points being dragged. + * + * @private + * @function getNewPoints + * + * @param {object} dragDropData + * A chart's dragDropData with drag/drop origin information, and info on + * which points are being dragged. + * + * @param {Highcharts.PointerEventObject} newPos + * Event with the new position of the mouse (chartX/Y properties). + * + * @return {Highchats.Dictionary} + * Hashmap with point.id mapped to an object with the original point + * reference, as well as the new data values. + */ + function getNewPoints(dragDropData, newPos) { + var point = dragDropData.point, series = point.series, options = merge(series.options.dragDrop, point.options.dragDrop), updateProps = {}, resizeProp = dragDropData.updateProp, hashmap = {}; + // Go through the data props that can be updated on this series and find out + // which ones we want to update. + objectEach(point.series.dragDropProps, function (val, key) { + // If we are resizing, skip if this key is not the correct one or it + // is not resizable. + if (resizeProp && (resizeProp !== key || + !val.resize || + val.optionName && options[val.optionName] === false)) { + return; + } + // If we are resizing, we now know it is good. If we are moving, check + // that moving along this axis is enabled, and the prop is movable. + // If this prop is enabled, add it to be updated. + if (resizeProp || (val.move && + (val.axis === 'x' && options.draggableX || + val.axis === 'y' && options.draggableY))) { + updateProps[key] = val; + } + }); + // Go through the points to be updated and get new options for each of them + ( + // If resizing).forEach(only update the point we are resizing + resizeProp ? + [point] : + dragDropData.groupedPoints).forEach(function (p) { + hashmap[p.id] = { + point: p, + newValues: p.getDropValues(dragDropData.origin, newPos, updateProps) + }; + }); + return hashmap; + } + /** + * Update the points in a chart from dragDropData.newPoints. + * + * @private + * @function updatePoints + * @param {Highcharts.Chart} chart + * A chart with dragDropData.newPoints. + * @param {boolean} [animate=true] + * Animate updating points? + * @return {void} + */ + function updatePoints(chart, animate) { + var newPoints = chart.dragDropData.newPoints, animOptions = animate === false ? false : merge({ + duration: 400 // 400 is the default in animate + }, chart.options.chart.animation); + chart.isDragDropAnimating = true; + // Update the points + objectEach(newPoints, function (newPoint) { + newPoint.point.update(newPoint.newValues, false); + }); + chart.redraw(animOptions); + // Clear the isAnimating flag after animation duration is complete. + // The complete handler for animation seems to have bugs at this time, so + // we have to use a timeout instead. + setTimeout(function () { + delete chart.isDragDropAnimating; + if (chart.hoverPoint && !chart.dragHandles) { + chart.hoverPoint.showDragHandles(); + } + }, animOptions.duration); + } + /** + * Resize the guide box according to point options and a difference in mouse + * positions. Handles reversed axes. + * + * @private + * @function resizeGuideBox + * @param {Highcharts.Point} point + * The point that is being resized. + * @param {number} dX + * Difference in X position. + * @param {number} dY + * Difference in Y position. + * @return {void} + */ + function resizeGuideBox(point, dX, dY) { + var series = point.series, chart = series.chart, dragDropData = chart.dragDropData, resizeSide, newPoint, resizeProp = series.dragDropProps[dragDropData.updateProp]; + // dragDropProp.resizeSide holds info on which side to resize. + newPoint = dragDropData.newPoints[point.id].newValues; + resizeSide = typeof resizeProp.resizeSide === 'function' ? + resizeProp.resizeSide(newPoint, point) : resizeProp.resizeSide; + // Call resize hook if it is defined + if (resizeProp.beforeResize) { + resizeProp.beforeResize(chart.dragGuideBox, newPoint, point); + } + // Do the resize + resizeRect(chart.dragGuideBox, resizeProp.axis === 'x' && series.xAxis.reversed || + resizeProp.axis === 'y' && series.yAxis.reversed ? + flipResizeSide(resizeSide) : resizeSide, { + x: resizeProp.axis === 'x' ? + dX - (dragDropData.origin.prevdX || 0) : 0, + y: resizeProp.axis === 'y' ? + dY - (dragDropData.origin.prevdY || 0) : 0 + }); + } + /** + * Default mouse move handler while dragging. Handles updating points or guide + * box. + * + * @private + * @function dragMove + * @param {Highcharts.PointerEventObject} e + * The mouse move event. + * @param {Highcharts.Point} point + * The point that is dragged. + * @return {void} + */ + function dragMove(e, point) { + var series = point.series, chart = series.chart, data = chart.dragDropData, options = merge(series.options.dragDrop, point.options.dragDrop), draggableX = options.draggableX, draggableY = options.draggableY, origin = data.origin, dX = e.chartX - origin.chartX, dY = e.chartY - origin.chartY, oldDx = dX, updateProp = data.updateProp; + // Handle inverted + if (chart.inverted) { + dX = -dY; + dY = -oldDx; + } + // If we have liveRedraw enabled, update the points immediately. Otherwise + // update the guideBox. + if (pick(options.liveRedraw, true)) { + updatePoints(chart, false); + // Update drag handles + point.showDragHandles(); + } + else { + // No live redraw, update guide box + if (updateProp) { + // We are resizing, so resize the guide box + resizeGuideBox(point, dX, dY); + } + else { + // We are moving, so move the guide box + chart.dragGuideBox.translate(draggableX ? dX : 0, draggableY ? dY : 0); + } + } + // Update stored previous dX/Y + origin.prevdX = dX; + origin.prevdY = dY; + } + /** + * Set the state of the guide box. + * + * @private + * @function Highcharts.Chart#setGuideBoxState + * @param {string} state + * The state to set the guide box to. + * @param {Highcharts.Dictionary} [options] + * Additional overall guideBox options to consider. + * @return {Highcharts.SVGElement} + * The modified guide box. + */ + H.Chart.prototype.setGuideBoxState = function (state, options) { + var guideBox = this.dragGuideBox, guideBoxOptions = merge(defaultGuideBoxOptions, options), stateOptions = merge(guideBoxOptions['default'], // eslint-disable-line dot-notation + guideBoxOptions[state]); + return guideBox + .attr({ + className: stateOptions.className, + stroke: stateOptions.lineColor, + strokeWidth: stateOptions.lineWidth, + fill: stateOptions.color, + cursor: stateOptions.cursor, + zIndex: stateOptions.zIndex + }) + // Use pointerEvents 'none' to avoid capturing the click event + .css({ pointerEvents: 'none' }); + }; + /** + * Get updated point values when dragging a point. + * + * @private + * @function Highcharts.Point#getDropValues + * + * @param {object} origin + * Mouse position (chartX/Y) and point props at current data values. + * Point props should be organized per point.id in a hashmap. + * + * @param {Highcharts.PointerEventObject} newPos + * New mouse position (chartX/Y). + * + * @param {Highcharts.Dictionary>>} updateProps + * Point props to modify. Map of prop objects where each key refers to + * the prop, and the value is an object with an axis property. Example: + * { + * x: { + * axis: 'x' + * }, + * x2: { + * axis: 'x' + * } + * } + * + * @return {Highcharts.Dictionary} + * An object with updated data values. + */ + Point.prototype.getDropValues = function (origin, newPos, updateProps) { + var point = this, series = point.series, options = merge(series.options.dragDrop, point.options.dragDrop), result = {}, updateSingleProp, pointOrigin = origin.points[point.id]; + // Find out if we only have one prop to update + for (var key in updateProps) { + if (Object.hasOwnProperty.call(updateProps, key)) { + if (typeof updateSingleProp !== 'undefined') { + updateSingleProp = false; + break; + } + updateSingleProp = true; + } + } + /** + * Utility function to apply precision and limit a value within the + * draggable range. + * @private + * @param {number} val + * Value to limit + * @param {string} direction + * Axis direction + * @return {number} + * Limited value + */ + var limitToRange = function (val, direction) { + var defaultPrecision = series[direction.toLowerCase() + 'Axis'] + .categories ? 1 : 0, precision = pick(options['dragPrecision' + direction], defaultPrecision), min = pick(options['dragMin' + direction], -Infinity), max = pick(options['dragMax' + direction], Infinity), res = val; + if (precision) { + res = Math.round(res / precision) * precision; + } + return clamp(res, min, max); + }; + // Assign new value to property. Adds dX/YValue to the old value, limiting + // it within min/max ranges. + objectEach(updateProps, function (val, key) { + var oldVal = pointOrigin[key], axis = series[val.axis + 'Axis'], newVal = limitToRange(axis.toValue((axis.horiz ? newPos.chartX : newPos.chartY) + + pointOrigin[key + 'Offset']), val.axis.toUpperCase()); + // If we are updating a single prop, and it has a validation function + // for the prop, run it. If it fails, don't update the value. + if (!(updateSingleProp && + val.propValidate && + !val.propValidate(newVal, point)) && + typeof oldVal !== 'undefined') { + result[key] = newVal; + } + }); + return result; + }; + /** + * Returns an SVGElement to use as the guide box for a set of points. + * + * @private + * @function Highcharts.Series#getGuideBox + * + * @param {Array} points + * The state to set the guide box to. + * + * @return {Highcharts.SVGElement} + * An SVG element for the guide box, not added to DOM. + */ + H.Series.prototype.getGuideBox = function (points) { + var chart = this.chart, minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity, changed; + // Find bounding box of all points + points.forEach(function (point) { + var bBox = point.graphic && point.graphic.getBBox() || point.shapeArgs; + if (bBox && (bBox.width || bBox.height || bBox.x || bBox.y)) { + changed = true; + minX = Math.min(bBox.x, minX); + maxX = Math.max(bBox.x + bBox.width, maxX); + minY = Math.min(bBox.y, minY); + maxY = Math.max(bBox.y + bBox.height, maxY); + } + }); + return changed ? chart.renderer.rect(minX, minY, maxX - minX, maxY - minY) : chart.renderer.g(); + }; + /** + * On point mouse out. Hide drag handles, depending on state. + * + * @private + * @function mouseOut + * @param {Highcharts.Point} point + * The point mousing out of. + * @return {void} + */ + function mouseOut(point) { + var chart = point.series && point.series.chart, dragDropData = chart && chart.dragDropData; + if (chart && + chart.dragHandles && + !(dragDropData && + (dragDropData.isDragging && + dragDropData.draggedPastSensitivity || + dragDropData.isHoveringHandle === point.id))) { + chart.hideDragHandles(); + } + } + /** + * Mouseout on resize handle. Handle states, and possibly run mouseOut on point. + * + * @private + * @function onResizeHandleMouseOut + * @param {Highcharts.Point} point + * The point mousing out of. + * @return {void} + */ + function onResizeHandleMouseOut(point) { + var chart = point.series.chart; + if (chart.dragDropData && + point.id === chart.dragDropData.isHoveringHandle) { + delete chart.dragDropData.isHoveringHandle; + } + if (!chart.hoverPoint) { + mouseOut(point); + } + } + /** + * Mousedown on resize handle. Init a drag if the conditions are right. + * + * @private + * @function onResizeHandleMouseDown + * @param {Highcharts.PointerEventObject} e + * The mousedown event. + * @param {Highcharts.Point} point + * The point mousing down on. + * @param {string} updateProp + * The data property this resize handle is attached to for this point. + * @return {void} + */ + function onResizeHandleMouseDown(e, point, updateProp) { + var chart = point.series.chart; + // Ignore if zoom/pan key is pressed + if (chart.zoomOrPanKeyPressed(e)) { + return; + } + // Prevent zooming + chart.mouseIsDown = false; + // We started a drag + initDragDrop(e, point); + chart.dragDropData.updateProp = + e.updateProp = updateProp; + point.firePointEvent('dragStart', e); + // Prevent default to avoid point click for dragging too + e.stopPropagation(); + e.preventDefault(); + } + /** + * Render drag handles on a point - depending on which handles are enabled - and + * attach events to them. + * + * @private + * @function Highcharts.Point#showDragHandles + * @return {void} + */ + Point.prototype.showDragHandles = function () { + var point = this, series = point.series, chart = series.chart, renderer = chart.renderer, options = merge(series.options.dragDrop, point.options.dragDrop); + // Go through each updateProp and see if we are supposed to create a handle + // for it. + objectEach(series.dragDropProps, function (val, key) { + var handleOptions = merge(defaultDragHandleOptions, val.handleOptions, options.dragHandle), handleAttrs = { + className: handleOptions.className, + 'stroke-width': handleOptions.lineWidth, + fill: handleOptions.color, + stroke: handleOptions.lineColor + }, pathFormatter = handleOptions.pathFormatter || val.handleFormatter, positioner = val.handlePositioner, pos, handle, handleSide, path, + // Run validation function on whether or not we allow individual + // updating of this prop. + validate = val.validateIndividualDrag ? + val.validateIndividualDrag(point) : true; + if (val.resize && + validate && + val.resizeSide && + pathFormatter && + (options['draggable' + val.axis.toUpperCase()] || + options[val.optionName]) && + options[val.optionName] !== false) { + // Create group if it doesn't exist + if (!chart.dragHandles) { + chart.dragHandles = { + group: renderer + .g('drag-drop-handles') + .add(series.markerGroup || series.group) + }; + } + // Store which point this is + chart.dragHandles.point = point.id; + // Find position and path of handle + pos = positioner(point); + handleAttrs.d = path = pathFormatter(point); + handleSide = typeof val.resizeSide === 'function' ? + val.resizeSide(point.options, point) : val.resizeSide; + if (!path || pos.x < 0 || pos.y < 0) { + return; + } + // If cursor is not set explicitly, use axis direction + handleAttrs.cursor = handleOptions.cursor || + (val.axis === 'x') !== !!chart.inverted ? + 'ew-resize' : 'ns-resize'; + // Create and add the handle element if it doesn't exist + handle = chart.dragHandles[handleSide]; + if (!handle) { + handle = chart.dragHandles[handleSide] = renderer + .path() + .add(chart.dragHandles.group); + } + // Move and update handle + handle.translate(pos.x, pos.y).attr(handleAttrs); + // Add events + addEvents(handle.element, ['touchstart', 'mousedown'], function (e) { + onResizeHandleMouseDown(getNormalizedEvent(e, chart), point, key); + }); + addEvent(chart.dragHandles.group.element, 'mouseover', function () { + chart.dragDropData = chart.dragDropData || {}; + chart.dragDropData.isHoveringHandle = point.id; + }); + addEvents(chart.dragHandles.group.element, ['touchend', 'mouseout'], function () { + onResizeHandleMouseOut(point); + }); + } + }); + }; + /** + * Remove the chart's drag handles if they exist. + * + * @private + * @function Highcharts.Chart#hideDragHandles + * @return {void} + */ + H.Chart.prototype.hideDragHandles = function () { + var chart = this; + if (chart.dragHandles) { + objectEach(chart.dragHandles, function (val, key) { + if (key !== 'group' && val.destroy) { + val.destroy(); + } + }); + if (chart.dragHandles.group && chart.dragHandles.group.destroy) { + chart.dragHandles.group.destroy(); + } + delete chart.dragHandles; + } + }; + /** + * Utility function to count the number of props in an object. + * + * @private + * @function countProps + * + * @param {object} obj + * The object to count. + * + * @return {number} + * Number of own properties on the object. + */ + function countProps(obj) { + var count = 0; + for (var p in obj) { + if (Object.hasOwnProperty.call(obj, p)) { + count++; + } + } + return count; + } + /** + * Utility function to get the value of the first prop of an object. (Note that + * the order of keys in an object is usually not guaranteed.) + * + * @private + * @function getFirstProp + * @param {Highcharts.Dictionary} obj + * The object to count. + * @return {T} + * Value of the first prop in the object. + * @template T + */ + function getFirstProp(obj) { + for (var p in obj) { + if (Object.hasOwnProperty.call(obj, p)) { + return obj[p]; + } + } + } + /** + * Mouseover on a point. Show drag handles if the conditions are right. + * + * @private + * @function mouseOver + * @param {Highcharts.Point} point + * The point mousing over. + * @return {void} + */ + function mouseOver(point) { + var series = point.series, chart = series && series.chart, dragDropData = chart && chart.dragDropData, is3d = chart && chart.is3d && chart.is3d(); + if (chart && + !(dragDropData && + dragDropData.isDragging && // Ignore if dragging a point + dragDropData.draggedPastSensitivity) && + !chart.isDragDropAnimating && // Ignore if animating + series.options.dragDrop && // No need to compute handles without this + !is3d // No 3D support + ) { + // Hide the handles if they exist on another point already + if (chart.dragHandles) { + chart.hideDragHandles(); + } + point.showDragHandles(); + } + } + /** + * On container mouse move. Handle drag sensitivity and fire drag event. + * + * @private + * @function mouseMove + * @param {Highcharts.PointerEventObject} e + * The mouse move event. + * @param {Highcharts.Chart} chart + * The chart we are moving across. + * @return {void} + */ + function mouseMove(e, chart) { + // Ignore if zoom/pan key is pressed + if (chart.zoomOrPanKeyPressed(e)) { + return; + } + var dragDropData = chart.dragDropData, point, seriesDragDropOpts, newPoints, numNewPoints = 0, newPoint; + if (dragDropData && dragDropData.isDragging) { + point = dragDropData.point; + seriesDragDropOpts = point.series.options.dragDrop; + // No tooltip for dragging + e.preventDefault(); + // Update sensitivity test if not passed yet + if (!dragDropData.draggedPastSensitivity) { + dragDropData.draggedPastSensitivity = hasDraggedPastSensitivity(e, chart, pick(point.options.dragDrop && + point.options.dragDrop.dragSensitivity, seriesDragDropOpts && + seriesDragDropOpts.dragSensitivity, defaultDragSensitivity)); + } + // If we have dragged past dragSensitivity, run the mousemove handler + // for dragging + if (dragDropData.draggedPastSensitivity) { + // Find the new point values from the moving + dragDropData.newPoints = getNewPoints(dragDropData, e); + // If we are only dragging one point, add it to the event + newPoints = dragDropData.newPoints; + numNewPoints = countProps(newPoints); + newPoint = numNewPoints === 1 ? + getFirstProp(newPoints) : + null; + // Run the handler + point.firePointEvent('drag', { + origin: dragDropData.origin, + newPoints: dragDropData.newPoints, + newPoint: newPoint && newPoint.newValues, + newPointId: newPoint && newPoint.point.id, + numNewPoints: numNewPoints, + chartX: e.chartX, + chartY: e.chartY + }, function () { + dragMove(e, point); + }); + } + } + } + /** + * On container mouse up. Fire drop event and reset state. + * + * @private + * @function mouseUp + * @param {Highcharts.PointerEventObject} e + * The mouse up event. + * @param {Highcharts.Chart} chart + * The chart we were dragging in. + * @return {void} + */ + function mouseUp(e, chart) { + var dragDropData = chart.dragDropData; + if (dragDropData && + dragDropData.isDragging && + dragDropData.draggedPastSensitivity) { + var point = dragDropData.point, newPoints = dragDropData.newPoints, numNewPoints = countProps(newPoints), newPoint = numNewPoints === 1 ? + getFirstProp(newPoints) : + null; + // Hide the drag handles + if (chart.dragHandles) { + chart.hideDragHandles(); + } + // Prevent default action + e.preventDefault(); + chart.cancelClick = true; + // Fire the event, with a default handler that updates the points + point.firePointEvent('drop', { + origin: dragDropData.origin, + chartX: e.chartX, + chartY: e.chartY, + newPoints: newPoints, + numNewPoints: numNewPoints, + newPoint: newPoint && newPoint.newValues, + newPointId: newPoint && newPoint.point.id + }, function () { + updatePoints(chart); + }); + } + // Reset + delete chart.dragDropData; + // Clean up the drag guide box if it exists. This is always added on + // drag start, even if user is overriding events. + if (chart.dragGuideBox) { + chart.dragGuideBox.destroy(); + delete chart.dragGuideBox; + } + } + /** + * On container mouse down. Init dragdrop if conditions are right. + * + * @private + * @function mouseDown + * @param {Highcharts.PointerEventObject} e + * The mouse down event. + * @param {Highcharts.Chart} chart + * The chart we are clicking. + * @return {void} + */ + function mouseDown(e, chart) { + var dragPoint = chart.hoverPoint, dragDropOptions = merge(dragPoint && dragPoint.series.options.dragDrop, dragPoint && dragPoint.options.dragDrop), draggableX = dragDropOptions.draggableX || false, draggableY = dragDropOptions.draggableY || false; + // Reset cancel click + chart.cancelClick = false; + // Ignore if: + if ( + // Option is disabled for the point + !(draggableX || draggableY) || + // Zoom/pan key is pressed + chart.zoomOrPanKeyPressed(e) || + // Dragging an annotation + chart.hasDraggedAnnotation) { + return; + } + // If we somehow get a mousedown event while we are dragging, cancel + if (chart.dragDropData && chart.dragDropData.isDragging) { + mouseUp(e, chart); + return; + } + // If this point is movable, start dragging it + if (dragPoint && isPointMovable(dragPoint)) { + chart.mouseIsDown = false; // Prevent zooming + initDragDrop(e, dragPoint); + dragPoint.firePointEvent('dragStart', e); + } + } + /* eslint-disable no-invalid-this */ + // Point hover event. We use a short timeout due to issues with coordinating + // point mouseover/out events on dragHandles and points. Particularly arearange + // series are finicky since the markers are not individual points. This logic + // should preferably be improved in the future. Notice that the mouseOut event + // below must have a shorter timeout to ensure event order. + addEvent(Point, 'mouseOver', function () { + var point = this; + setTimeout(function () { + mouseOver(point); + }, 12); + }); + // Point mouseleave event. See above function for explanation of the timeout. + addEvent(Point, 'mouseOut', function () { + var point = this; + setTimeout(function () { + if (point.series) { + mouseOut(point); + } + }, 10); + }); + // Hide drag handles on a point if it is removed + addEvent(Point, 'remove', function () { + var chart = this.series.chart, dragHandles = chart.dragHandles; + if (dragHandles && dragHandles.point === this.id) { + chart.hideDragHandles(); + } + }); + /** + * Check whether the zoomKey or panKey is pressed. + * + * @private + * @function Highcharts.Chart#zoomOrPanKeyPressed + * @param {global.Event} e + * A mouse event. + * @return {boolean} + * True if the zoom or pan keys are pressed. False otherwise. + */ + H.Chart.prototype.zoomOrPanKeyPressed = function (e) { + // Check whether the panKey and zoomKey are set in chart.userOptions + var chartOptions = this.userOptions.chart || {}, panKey = chartOptions.panKey && chartOptions.panKey + 'Key', zoomKey = chartOptions.zoomKey && chartOptions.zoomKey + 'Key'; + return (e[zoomKey] || e[panKey]); + }; + /** + * Add events to document and chart if the chart is draggable. + * + * @private + * @function addDragDropEvents + * @param {Highcharts.Chart} chart + * The chart to add events to. + * @return {void} + */ + function addDragDropEvents(chart) { + var container = chart.container, doc = H.doc; + // Only enable if we have a draggable chart + if (isChartDraggable(chart)) { + addEvents(container, ['mousedown', 'touchstart'], function (e) { + mouseDown(getNormalizedEvent(e, chart), chart); + }); + addEvents(container, ['mousemove', 'touchmove'], function (e) { + mouseMove(getNormalizedEvent(e, chart), chart); + }); + addEvent(container, 'mouseleave', function (e) { + mouseUp(getNormalizedEvent(e, chart), chart); + }); + chart.unbindDragDropMouseUp = addEvents(doc, ['mouseup', 'touchend'], function (e) { + mouseUp(getNormalizedEvent(e, chart), chart); + }); + // Add flag to avoid doing this again + chart.hasAddedDragDropEvents = true; + // Add cleanup to make sure we don't pollute document + addEvent(chart, 'destroy', function () { + if (chart.unbindDragDropMouseUp) { + chart.unbindDragDropMouseUp(); + } + }); + } + } + // Add event listener to Chart.render that checks whether or not we should add + // dragdrop. + addEvent(H.Chart, 'render', function () { + // If we don't have dragDrop events, see if we should add them + if (!this.hasAddedDragDropEvents) { + addDragDropEvents(this); + } + }); + + }); + _registerModule(_modules, 'masters/modules/draggable-points.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/drilldown.js b/librerias/gantt/code/modules/drilldown.js new file mode 100644 index 0000000..80743cc --- /dev/null +++ b/librerias/gantt/code/modules/drilldown.js @@ -0,0 +1,31 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Highcharts Drilldown module + + Author: Torstein Honsi + License: www.highcharts.com/license + +*/ +(function(c){"object"===typeof module&&module.exports?(c["default"]=c,module.exports=c):"function"===typeof define&&define.amd?define("highcharts/modules/drilldown",["highcharts"],function(m){c(m);c.Highcharts=m;return c}):c("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(c){function m(c,m,u,x){c.hasOwnProperty(m)||(c[m]=x.apply(null,u))}c=c?c._modules:{};m(c,"modules/drilldown.src.js",[c["parts/Globals.js"],c["parts/Color.js"],c["parts/Point.js"],c["parts/Tick.js"],c["parts/Utilities.js"]], +function(c,m,u,x,l){var n=l.addEvent,E=l.removeEvent,A=l.animObject,t=l.extend,y=l.fireEvent,F=l.format,v=l.merge,B=l.objectEach,w=l.pick,G=l.syncTimeout,H=c.noop;l=c.defaultOptions;var p=c.Chart,r=c.seriesTypes,C=r.pie;r=r.column;var D=1;t(l.lang,{drillUpText:"\u25c1 Back to {series.name}"});l.drilldown={activeAxisLabelStyle:{cursor:"pointer",color:"#003399",fontWeight:"bold",textDecoration:"underline"},activeDataLabelStyle:{cursor:"pointer",color:"#003399",fontWeight:"bold",textDecoration:"underline"}, +animation:{duration:500},drillUpButton:{position:{align:"right",x:-10,y:10}}};c.SVGRenderer.prototype.Element.prototype.fadeIn=function(a){this.attr({opacity:.1,visibility:"inherit"}).animate({opacity:w(this.newOpacity,1)},a||{duration:250})};p.prototype.addSeriesAsDrilldown=function(a,b){this.addSingleSeriesAsDrilldown(a,b);this.applyDrilldown()};p.prototype.addSingleSeriesAsDrilldown=function(a,b){var d=a.series,f=d.xAxis,e=d.yAxis,g=[],h=[],q;var k=this.styledMode?{colorIndex:w(a.colorIndex,d.colorIndex)}: +{color:a.color||d.color};this.drilldownLevels||(this.drilldownLevels=[]);var c=d.options._levelNumber||0;(q=this.drilldownLevels[this.drilldownLevels.length-1])&&q.levelNumber!==c&&(q=void 0);b=t(t({_ddSeriesId:D++},k),b);var l=d.points.indexOf(a);d.chart.series.forEach(function(a){a.xAxis!==f||a.isDrilling||(a.options._ddSeriesId=a.options._ddSeriesId||D++,a.options._colorIndex=a.userOptions._colorIndex,a.options._levelNumber=a.options._levelNumber||c,q?(g=q.levelSeries,h=q.levelSeriesOptions):(g.push(a), +a.purgedOptions=v({_ddSeriesId:a.options._ddSeriesId,_levelNumber:a.options._levelNumber,selected:a.options.selected},a.userOptions),h.push(a.purgedOptions)))});a=t({levelNumber:c,seriesOptions:d.options,seriesPurgedOptions:d.purgedOptions,levelSeriesOptions:h,levelSeries:g,shapeArgs:a.shapeArgs,bBox:a.graphic?a.graphic.getBBox():{},color:a.isNull?(new m(k.color)).setOpacity(0).get():k.color,lowerSeriesOptions:b,pointOptions:d.options.data[l],pointIndex:l,oldExtremes:{xMin:f&&f.userMin,xMax:f&&f.userMax, +yMin:e&&e.userMin,yMax:e&&e.userMax},resetZoomButton:this.resetZoomButton},k);this.drilldownLevels.push(a);f&&f.names&&(f.names.length=0);b=a.lowerSeries=this.addSeries(b,!1);b.options._levelNumber=c+1;f&&(f.oldPos=f.pos,f.userMin=f.userMax=null,e.userMin=e.userMax=null);d.type===b.type&&(b.animate=b.animateDrilldown||H,b.options.animation=!0)};p.prototype.applyDrilldown=function(){var a=this.drilldownLevels;if(a&&0|undefined} + */ /** + * Options for the new series. If the event is utilized for async drilldown, the + * seriesOptions are not added, but rather loaded async. + * @name Highcharts.DrilldownEventObject#seriesOptions + * @type {Highcharts.SeriesOptionsType|undefined} + */ /** + * The event target. + * @name Highcharts.DrilldownEventObject#target + * @type {Highcharts.Chart} + */ /** + * The event type. + * @name Highcharts.DrilldownEventObject#type + * @type {"drilldown"} + */ + /** + * This gets fired after all the series have been drilled up. This is especially + * usefull in a chart with multiple drilldown series. + * + * @callback Highcharts.DrillupAllCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart where the event occurs. + * + * @param {Highcharts.DrillupAllEventObject} e + * The final drillup event. + */ + /** + * The event arguments when all the series have been drilled up. + * + * @interface Highcharts.DrillupAllEventObject + */ /** + * Prevents the default behaviour of the event. + * @name Highcharts.DrillupAllEventObject#preventDefault + * @type {Function} + */ /** + * The event target. + * @name Highcharts.DrillupAllEventObject#target + * @type {Highcharts.Chart} + */ /** + * The event type. + * @name Highcharts.DrillupAllEventObject#type + * @type {"drillupall"} + */ + /** + * Gets fired when drilling up from a drilldown series. + * + * @callback Highcharts.DrillupCallbackFunction + * + * @param {Highcharts.Chart} this + * The chart where the event occurs. + * + * @param {Highcharts.DrillupEventObject} e + * The drillup event. + */ + /** + * The event arguments when drilling up from a drilldown series. + * + * @interface Highcharts.DrillupEventObject + */ /** + * Prevents the default behaviour of the event. + * @name Highcharts.DrillupEventObject#preventDefault + * @type {Function} + */ /** + * Options for the new series. + * @name Highcharts.DrillupEventObject#seriesOptions + * @type {Highcharts.SeriesOptionsType|undefined} + */ /** + * The event target. + * @name Highcharts.DrillupEventObject#target + * @type {Highcharts.Chart} + */ /** + * The event type. + * @name Highcharts.DrillupEventObject#type + * @type {"drillup"} + */ + var addEvent = U.addEvent, removeEvent = U.removeEvent, animObject = U.animObject, extend = U.extend, fireEvent = U.fireEvent, format = U.format, merge = U.merge, objectEach = U.objectEach, pick = U.pick, syncTimeout = U.syncTimeout; + var noop = H.noop, defaultOptions = H.defaultOptions, Chart = H.Chart, seriesTypes = H.seriesTypes, PieSeries = seriesTypes.pie, ColumnSeries = seriesTypes.column, ddSeriesId = 1; + // Add language + extend(defaultOptions.lang, + /** + * @optionparent lang + */ + { + /** + * The text for the button that appears when drilling down, linking back + * to the parent series. The parent series' name is inserted for + * `{series.name}`. + * + * @since 3.0.8 + * @product highcharts highmaps + * @requires modules/drilldown + * + * @private + */ + drillUpText: '◁ Back to {series.name}' + }); + /** + * Options for drill down, the concept of inspecting increasingly high + * resolution data through clicking on chart items like columns or pie slices. + * + * The drilldown feature requires the drilldown.js file to be loaded, + * found in the modules directory of the download package, or online at + * [code.highcharts.com/modules/drilldown.js + * ](https://code.highcharts.com/modules/drilldown.js). + * + * @product highcharts highmaps + * @requires modules/drilldown + * @optionparent drilldown + */ + defaultOptions.drilldown = { + /** + * When this option is false, clicking a single point will drill down + * all points in the same category, equivalent to clicking the X axis + * label. + * + * @sample {highcharts} highcharts/drilldown/allowpointdrilldown-false/ + * Don't allow point drilldown + * + * @type {boolean} + * @default true + * @since 4.1.7 + * @product highcharts + * @apioption drilldown.allowPointDrilldown + */ + /** + * An array of series configurations for the drill down. Each series + * configuration uses the same syntax as the [series](#series) option set. + * These drilldown series are hidden by default. The drilldown series is + * linked to the parent series' point by its `id`. + * + * @type {Array} + * @since 3.0.8 + * @product highcharts highmaps + * @apioption drilldown.series + */ + /** + * Additional styles to apply to the X axis label for a point that + * has drilldown data. By default it is underlined and blue to invite + * to interaction. + * + * In styled mode, active label styles can be set with the + * `.highcharts-drilldown-axis-label` class. + * + * @sample {highcharts} highcharts/drilldown/labels/ + * Label styles + * + * @type {Highcharts.CSSObject} + * @default { "cursor": "pointer", "color": "#003399", "fontWeight": "bold", "textDecoration": "underline" } + * @since 3.0.8 + * @product highcharts highmaps + */ + activeAxisLabelStyle: { + /** @ignore-option */ + cursor: 'pointer', + /** @ignore-option */ + color: '#003399', + /** @ignore-option */ + fontWeight: 'bold', + /** @ignore-option */ + textDecoration: 'underline' + }, + /** + * Additional styles to apply to the data label of a point that has + * drilldown data. By default it is underlined and blue to invite to + * interaction. + * + * In styled mode, active data label styles can be applied with the + * `.highcharts-drilldown-data-label` class. + * + * @sample {highcharts} highcharts/drilldown/labels/ + * Label styles + * + * @type {Highcharts.CSSObject} + * @default { "cursor": "pointer", "color": "#003399", "fontWeight": "bold", "textDecoration": "underline" } + * @since 3.0.8 + * @product highcharts highmaps + */ + activeDataLabelStyle: { + cursor: 'pointer', + color: '#003399', + fontWeight: 'bold', + textDecoration: 'underline' + }, + /** + * Set the animation for all drilldown animations. Animation of a drilldown + * occurs when drilling between a column point and a column series, + * or a pie slice and a full pie series. Drilldown can still be used + * between series and points of different types, but animation will + * not occur. + * + * The animation can either be set as a boolean or a configuration + * object. If `true`, it will use the 'swing' jQuery easing and a duration + * of 500 ms. If used as a configuration object, the following properties + * are supported: + * + * - `duration`: The duration of the animation in milliseconds. + * + * - `easing`: A string reference to an easing function set on the `Math` + * object. See + * [the easing demo](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-animation-easing/). + * + * @type {boolean|Highcharts.AnimationOptionsObject} + * @since 3.0.8 + * @product highcharts highmaps + */ + animation: { + /** @internal */ + duration: 500 + }, + /** + * Options for the drill up button that appears when drilling down on a + * series. The text for the button is defined in + * [lang.drillUpText](#lang.drillUpText). + * + * @sample {highcharts} highcharts/drilldown/drillupbutton/ + * Drill up button + * @sample {highmaps} highcharts/drilldown/drillupbutton/ + * Drill up button + * + * @since 3.0.8 + * @product highcharts highmaps + */ + drillUpButton: { + /** + * What box to align the button to. Can be either `plotBox` or + * `spacingBox`. + * + * @type {Highcharts.ButtonRelativeToValue} + * @default plotBox + * @since 3.0.8 + * @product highcharts highmaps + * @apioption drilldown.drillUpButton.relativeTo + */ + /** + * A collection of attributes for the button. The object takes SVG + * attributes like `fill`, `stroke`, `stroke-width` or `r`, the border + * radius. The theme also supports `style`, a collection of CSS + * properties for the text. Equivalent attributes for the hover state + * are given in `theme.states.hover`. + * + * In styled mode, drill-up button styles can be applied with the + * `.highcharts-drillup-button` class. + * + * @sample {highcharts} highcharts/drilldown/drillupbutton/ + * Button theming + * @sample {highmaps} highcharts/drilldown/drillupbutton/ + * Button theming + * + * @type {object} + * @since 3.0.8 + * @product highcharts highmaps + * @apioption drilldown.drillUpButton.theme + */ + /** + * Positioning options for the button within the `relativeTo` box. + * Available properties are `x`, `y`, `align` and `verticalAlign`. + * + * @type {Highcharts.AlignObject} + * @since 3.0.8 + * @product highcharts highmaps + */ + position: { + /** + * Vertical alignment of the button. + * + * @type {Highcharts.VerticalAlignValue} + * @default top + * @product highcharts highmaps + * @apioption drilldown.drillUpButton.position.verticalAlign + */ + /** + * Horizontal alignment. + * + * @type {Highcharts.AlignValue} + */ + align: 'right', + /** + * The X offset of the button. + */ + x: -10, + /** + * The Y offset of the button. + */ + y: 10 + } + } + }; + /** + * Fires when a drilldown point is clicked, before the new series is added. This + * event is also utilized for async drilldown, where the seriesOptions are not + * added by option, but rather loaded async. Note that when clicking a category + * label to trigger multiple series drilldown, one `drilldown` event is + * triggered per point in the category. + * + * Event arguments: + * + * - `category`: If a category label was clicked, which index. + * + * - `originalEvent`: The original browser event (usually click) that triggered + * the drilldown. + * + * - `point`: The originating point. + * + * - `points`: If a category label was clicked, this array holds all points + * corresponing to the category. + * + * - `seriesOptions`: Options for the new series. + * + * @sample {highcharts} highcharts/drilldown/async/ + * Async drilldown + * + * @type {Highcharts.DrilldownCallbackFunction} + * @since 3.0.8 + * @product highcharts highmaps + * @context Highcharts.Chart + * @requires modules/drilldown + * @apioption chart.events.drilldown + */ + /** + * Fires when drilling up from a drilldown series. + * + * @type {Highcharts.DrillupCallbackFunction} + * @since 3.0.8 + * @product highcharts highmaps + * @context Highcharts.Chart + * @requires modules/drilldown + * @apioption chart.events.drillup + */ + /** + * In a chart with multiple drilldown series, this event fires after all the + * series have been drilled up. + * + * @type {Highcharts.DrillupAllCallbackFunction} + * @since 4.2.4 + * @product highcharts highmaps + * @context Highcharts.Chart + * @requires modules/drilldown + * @apioption chart.events.drillupall + */ + /** + * The `id` of a series in the [drilldown.series](#drilldown.series) array to + * use for a drilldown for this point. + * + * @sample {highcharts} highcharts/drilldown/basic/ + * Basic drilldown + * + * @type {string} + * @since 3.0.8 + * @product highcharts + * @requires modules/drilldown + * @apioption series.line.data.drilldown + */ + /** + * A general fadeIn method. + * + * @requires module:modules/drilldown + * + * @function Highcharts.SVGElement#fadeIn + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * The animation options for the element fade. + */ + H.SVGRenderer.prototype.Element.prototype.fadeIn = function (animation) { + this + .attr({ + opacity: 0.1, + visibility: 'inherit' + }) + .animate({ + opacity: pick(this.newOpacity, 1) // newOpacity used in maps + }, animation || { + duration: 250 + }); + }; + /** + * Add a series to the chart as drilldown from a specific point in the parent + * series. This method is used for async drilldown, when clicking a point in a + * series should result in loading and displaying a more high-resolution series. + * When not async, the setup is simpler using the + * [drilldown.series](https://api.highcharts.com/highcharts/drilldown.series) + * options structure. + * + * @sample highcharts/drilldown/async/ + * Async drilldown + * + * @function Highcharts.Chart#addSeriesAsDrilldown + * + * @param {Highcharts.Point} point + * The point from which the drilldown will start. + * + * @param {Highcharts.SeriesOptionsType} options + * The series options for the new, detailed series. + */ + Chart.prototype.addSeriesAsDrilldown = function (point, options) { + this.addSingleSeriesAsDrilldown(point, options); + this.applyDrilldown(); + }; + Chart.prototype.addSingleSeriesAsDrilldown = function (point, ddOptions) { + var oldSeries = point.series, xAxis = oldSeries.xAxis, yAxis = oldSeries.yAxis, newSeries, pointIndex, levelSeries = [], levelSeriesOptions = [], level, levelNumber, last, colorProp; + colorProp = this.styledMode ? + { colorIndex: pick(point.colorIndex, oldSeries.colorIndex) } : + { color: point.color || oldSeries.color }; + if (!this.drilldownLevels) { + this.drilldownLevels = []; + } + levelNumber = oldSeries.options._levelNumber || 0; + // See if we can reuse the registered series from last run + last = this.drilldownLevels[this.drilldownLevels.length - 1]; + if (last && last.levelNumber !== levelNumber) { + last = void 0; + } + ddOptions = extend(extend({ + _ddSeriesId: ddSeriesId++ + }, colorProp), ddOptions); + pointIndex = oldSeries.points.indexOf(point); + // Record options for all current series + oldSeries.chart.series.forEach(function (series) { + if (series.xAxis === xAxis && !series.isDrilling) { + series.options._ddSeriesId = + series.options._ddSeriesId || ddSeriesId++; + series.options._colorIndex = series.userOptions._colorIndex; + series.options._levelNumber = + series.options._levelNumber || levelNumber; // #3182 + if (last) { + levelSeries = last.levelSeries; + levelSeriesOptions = last.levelSeriesOptions; + } + else { + levelSeries.push(series); + // (#10597) + series.purgedOptions = merge({ + _ddSeriesId: series.options._ddSeriesId, + _levelNumber: series.options._levelNumber, + selected: series.options.selected + }, series.userOptions); + levelSeriesOptions.push(series.purgedOptions); + } + } + }); + // Add a record of properties for each drilldown level + level = extend({ + levelNumber: levelNumber, + seriesOptions: oldSeries.options, + seriesPurgedOptions: oldSeries.purgedOptions, + levelSeriesOptions: levelSeriesOptions, + levelSeries: levelSeries, + shapeArgs: point.shapeArgs, + // no graphic in line series with markers disabled + bBox: point.graphic ? point.graphic.getBBox() : {}, + color: point.isNull ? + new Color(colorProp.color).setOpacity(0).get() : + colorProp.color, + lowerSeriesOptions: ddOptions, + pointOptions: oldSeries.options.data[pointIndex], + pointIndex: pointIndex, + oldExtremes: { + xMin: xAxis && xAxis.userMin, + xMax: xAxis && xAxis.userMax, + yMin: yAxis && yAxis.userMin, + yMax: yAxis && yAxis.userMax + }, + resetZoomButton: this.resetZoomButton + }, colorProp); + // Push it to the lookup array + this.drilldownLevels.push(level); + // Reset names to prevent extending (#6704) + if (xAxis && xAxis.names) { + xAxis.names.length = 0; + } + newSeries = level.lowerSeries = this.addSeries(ddOptions, false); + newSeries.options._levelNumber = levelNumber + 1; + if (xAxis) { + xAxis.oldPos = xAxis.pos; + xAxis.userMin = xAxis.userMax = null; + yAxis.userMin = yAxis.userMax = null; + } + // Run fancy cross-animation on supported and equal types + if (oldSeries.type === newSeries.type) { + newSeries.animate = newSeries.animateDrilldown || noop; + newSeries.options.animation = true; + } + }; + Chart.prototype.applyDrilldown = function () { + var drilldownLevels = this.drilldownLevels, levelToRemove; + if (drilldownLevels && drilldownLevels.length > 0) { // #3352, async loading + levelToRemove = drilldownLevels[drilldownLevels.length - 1].levelNumber; + this.drilldownLevels.forEach(function (level) { + if (level.levelNumber === levelToRemove) { + level.levelSeries.forEach(function (series) { + // Not removed, not added as part of a multi-series + // drilldown + if (series.options && + series.options._levelNumber === levelToRemove) { + series.remove(false); + } + }); + } + }); + } + // We have a reset zoom button. Hide it and detatch it from the chart. It + // is preserved to the layer config above. + if (this.resetZoomButton) { + this.resetZoomButton.hide(); + delete this.resetZoomButton; + } + this.pointer.reset(); + this.redraw(); + this.showDrillUpButton(); + fireEvent(this, 'afterDrilldown'); + }; + Chart.prototype.getDrilldownBackText = function () { + var drilldownLevels = this.drilldownLevels, lastLevel; + if (drilldownLevels && drilldownLevels.length > 0) { // #3352, async loading + lastLevel = drilldownLevels[drilldownLevels.length - 1]; + lastLevel.series = lastLevel.seriesOptions; + return format(this.options.lang.drillUpText, lastLevel); + } + }; + Chart.prototype.showDrillUpButton = function () { + var chart = this, backText = this.getDrilldownBackText(), buttonOptions = chart.options.drilldown.drillUpButton, attr, states; + if (!this.drillUpButton) { + attr = buttonOptions.theme; + states = attr && attr.states; + this.drillUpButton = this.renderer.button(backText, null, null, function () { + chart.drillUp(); + }, attr, states && states.hover, states && states.select) + .addClass('highcharts-drillup-button') + .attr({ + align: buttonOptions.position.align, + zIndex: 7 + }) + .add() + .align(buttonOptions.position, false, buttonOptions.relativeTo || 'plotBox'); + } + else { + this.drillUpButton.attr({ + text: backText + }) + .align(); + } + }; + /** + * When the chart is drilled down to a child series, calling `chart.drillUp()` + * will drill up to the parent series. + * + * @requires modules/drilldown + * + * @function Highcharts.Chart#drillUp + */ + Chart.prototype.drillUp = function () { + if (!this.drilldownLevels || this.drilldownLevels.length === 0) { + return; + } + var chart = this, drilldownLevels = chart.drilldownLevels, levelNumber = drilldownLevels[drilldownLevels.length - 1].levelNumber, i = drilldownLevels.length, chartSeries = chart.series, seriesI, level, oldSeries, newSeries, oldExtremes, addSeries = function (seriesOptions) { + var addedSeries; + chartSeries.forEach(function (series) { + if (series.options._ddSeriesId === seriesOptions._ddSeriesId) { + addedSeries = series; + } + }); + addedSeries = addedSeries || chart.addSeries(seriesOptions, false); + if (addedSeries.type === oldSeries.type && + addedSeries.animateDrillupTo) { + addedSeries.animate = addedSeries.animateDrillupTo; + } + if (seriesOptions === level.seriesPurgedOptions) { + newSeries = addedSeries; + } + }; + while (i--) { + level = drilldownLevels[i]; + if (level.levelNumber === levelNumber) { + drilldownLevels.pop(); + // Get the lower series by reference or id + oldSeries = level.lowerSeries; + if (!oldSeries.chart) { // #2786 + seriesI = chartSeries.length; // #2919 + while (seriesI--) { + if (chartSeries[seriesI].options.id === + level.lowerSeriesOptions.id && + chartSeries[seriesI].options._levelNumber === + levelNumber + 1) { // #3867 + oldSeries = chartSeries[seriesI]; + break; + } + } + } + oldSeries.xData = []; // Overcome problems with minRange (#2898) + level.levelSeriesOptions.forEach(addSeries); + fireEvent(chart, 'drillup', { + seriesOptions: level.seriesPurgedOptions || + level.seriesOptions + }); + if (newSeries.type === oldSeries.type) { + newSeries.drilldownLevel = level; + newSeries.options.animation = + chart.options.drilldown.animation; + if (oldSeries.animateDrillupFrom && oldSeries.chart) { // #2919 + oldSeries.animateDrillupFrom(level); + } + } + newSeries.options._levelNumber = levelNumber; + oldSeries.remove(false); + // Reset the zoom level of the upper series + if (newSeries.xAxis) { + oldExtremes = level.oldExtremes; + newSeries.xAxis.setExtremes(oldExtremes.xMin, oldExtremes.xMax, false); + newSeries.yAxis.setExtremes(oldExtremes.yMin, oldExtremes.yMax, false); + } + // We have a resetZoomButton tucked away for this level. Attatch + // it to the chart and show it. + if (level.resetZoomButton) { + chart.resetZoomButton = level.resetZoomButton; + chart.resetZoomButton.show(); + } + } + } + this.redraw(); + if (this.drilldownLevels.length === 0) { + this.drillUpButton = this.drillUpButton.destroy(); + } + else { + this.drillUpButton.attr({ + text: this.getDrilldownBackText() + }) + .align(); + } + this.ddDupes.length = []; // #3315 + // Fire a once-off event after all series have been drilled up (#5158) + fireEvent(chart, 'drillupall'); + }; + /* eslint-disable no-invalid-this */ + // Add update function to be called internally from Chart.update + // (#7600, #12855) + addEvent(Chart, 'afterInit', function () { + var chart = this; + chart.drilldown = { + update: function (options, redraw) { + merge(true, chart.options.drilldown, options); + if (pick(redraw, true)) { + chart.redraw(); + } + } + }; + }); + // Don't show the reset button if we already are displaying the drillUp button. + addEvent(Chart, 'beforeShowResetZoom', function () { + if (this.drillUpButton) { + return false; + } + }); + addEvent(Chart, 'render', function () { + (this.xAxis || []).forEach(function (axis) { + axis.ddPoints = {}; + axis.series.forEach(function (series) { + var i, xData = series.xData || [], points = series.points, p; + for (i = 0; i < xData.length; i++) { + p = series.options.data[i]; + // The `drilldown` property can only be set on an array or an + // object + if (typeof p !== 'number') { + // Convert array to object (#8008) + p = series.pointClass.prototype.optionsToObject + .call({ series: series }, p); + if (p.drilldown) { + if (!axis.ddPoints[xData[i]]) { + axis.ddPoints[xData[i]] = []; + } + axis.ddPoints[xData[i]].push(points ? points[i] : true); + } + } + } + }); + // Add drillability to ticks, and always keep it drillability updated + // (#3951) + objectEach(axis.ticks, Tick.prototype.drillable); + }); + }); + /** + * When drilling up, keep the upper series invisible until the lower series has + * moved into place. + * + * @private + * @function Highcharts.ColumnSeries#animateDrillupTo + * @param {boolean} [init=false] + * Whether to initialize animation + */ + ColumnSeries.prototype.animateDrillupTo = function (init) { + if (!init) { + var newSeries = this, level = newSeries.drilldownLevel; + // First hide all items before animating in again + this.points.forEach(function (point) { + var dataLabel = point.dataLabel; + if (point.graphic) { // #3407 + point.graphic.hide(); + } + if (dataLabel) { + // The data label is initially hidden, make sure it is not faded + // in (#6127) + dataLabel.hidden = dataLabel.attr('visibility') === 'hidden'; + if (!dataLabel.hidden) { + dataLabel.hide(); + if (point.connector) { + point.connector.hide(); + } + } + } + }); + // Do dummy animation on first point to get to complete + syncTimeout(function () { + if (newSeries.points) { // May be destroyed in the meantime, #3389 + newSeries.points.forEach(function (point, i) { + // Fade in other points + var verb = i === (level && level.pointIndex) ? 'show' : 'fadeIn', inherit = verb === 'show' ? true : void 0, dataLabel = point.dataLabel; + if (point.graphic) { // #3407 + point.graphic[verb](inherit); + } + if (dataLabel && !dataLabel.hidden) { // #6127 + dataLabel.fadeIn(); // #7384 + if (point.connector) { + point.connector.fadeIn(); + } + } + }); + } + }, Math.max(this.chart.options.drilldown.animation.duration - 50, 0)); + // Reset to prototype + delete this.animate; + } + }; + ColumnSeries.prototype.animateDrilldown = function (init) { + var series = this, chart = this.chart, drilldownLevels = chart.drilldownLevels, animateFrom, animationOptions = animObject(chart.options.drilldown.animation), xAxis = this.xAxis, styledMode = chart.styledMode; + if (!init) { + drilldownLevels.forEach(function (level) { + if (series.options._ddSeriesId === + level.lowerSeriesOptions._ddSeriesId) { + animateFrom = level.shapeArgs; + if (!styledMode) { + // Add the point colors to animate from + animateFrom.fill = level.color; + } + } + }); + animateFrom.x += pick(xAxis.oldPos, xAxis.pos) - xAxis.pos; + this.points.forEach(function (point) { + var animateTo = point.shapeArgs; + if (!styledMode) { + // Add the point colors to animate to + animateTo.fill = point.color; + } + if (point.graphic) { + point.graphic + .attr(animateFrom) + .animate(extend(point.shapeArgs, { fill: point.color || series.color }), animationOptions); + } + if (point.dataLabel) { + point.dataLabel.fadeIn(animationOptions); + } + }); + // Reset to prototype + delete this.animate; + } + }; + /** + * When drilling up, pull out the individual point graphics from the lower + * series and animate them into the origin point in the upper series. + * + * @private + * @function Highcharts.ColumnSeries#animateDrillupFrom + * @param {Highcharts.DrilldownLevelObject} level + * Level container + * @return {void} + */ + ColumnSeries.prototype.animateDrillupFrom = function (level) { + var animationOptions = animObject(this.chart.options.drilldown.animation), group = this.group, + // For 3d column series all columns are added to one group + // so we should not delete the whole group. #5297 + removeGroup = group !== this.chart.columnGroup, series = this; + // Cancel mouse events on the series group (#2787) + series.trackerGroups.forEach(function (key) { + if (series[key]) { // we don't always have dataLabelsGroup + series[key].on('mouseover'); + } + }); + if (removeGroup) { + delete this.group; + } + this.points.forEach(function (point) { + var graphic = point.graphic, animateTo = level.shapeArgs, complete = function () { + graphic.destroy(); + if (group && removeGroup) { + group = group.destroy(); + } + }; + if (graphic) { + delete point.graphic; + if (!series.chart.styledMode) { + animateTo.fill = level.color; + } + if (animationOptions.duration) { + graphic.animate(animateTo, merge(animationOptions, { complete: complete })); + } + else { + graphic.attr(animateTo); + complete(); + } + } + }); + }; + if (PieSeries) { + extend(PieSeries.prototype, { + animateDrillupTo: ColumnSeries.prototype.animateDrillupTo, + animateDrillupFrom: ColumnSeries.prototype.animateDrillupFrom, + animateDrilldown: function (init) { + var level = this.chart.drilldownLevels[this.chart.drilldownLevels.length - 1], animationOptions = this.chart.options.drilldown.animation, animateFrom = level.shapeArgs, start = animateFrom.start, angle = animateFrom.end - start, startAngle = angle / this.points.length, styledMode = this.chart.styledMode; + if (!init) { + this.points.forEach(function (point, i) { + var animateTo = point.shapeArgs; + if (!styledMode) { + animateFrom.fill = level.color; + animateTo.fill = point.color; + } + if (point.graphic) { + point.graphic + .attr(merge(animateFrom, { + start: start + i * startAngle, + end: start + (i + 1) * startAngle + }))[animationOptions ? 'animate' : 'attr'](animateTo, animationOptions); + } + }); + // Reset to prototype + delete this.animate; + } + } + }); + } + Point.prototype.doDrilldown = function (_holdRedraw, category, originalEvent) { + var series = this.series, chart = series.chart, drilldown = chart.options.drilldown, i = (drilldown.series || []).length, seriesOptions; + if (!chart.ddDupes) { + chart.ddDupes = []; + } + while (i-- && !seriesOptions) { + if (drilldown.series[i].id === this.drilldown && + chart.ddDupes.indexOf(this.drilldown) === -1) { + seriesOptions = drilldown.series[i]; + chart.ddDupes.push(this.drilldown); + } + } + // Fire the event. If seriesOptions is undefined, the implementer can check + // for seriesOptions, and call addSeriesAsDrilldown async if necessary. + fireEvent(chart, 'drilldown', { + point: this, + seriesOptions: seriesOptions, + category: category, + originalEvent: originalEvent, + points: (typeof category !== 'undefined' && + this.series.xAxis.getDDPoints(category).slice(0)) + }, function (e) { + var chart = e.point.series && e.point.series.chart, seriesOptions = e.seriesOptions; + if (chart && seriesOptions) { + if (_holdRedraw) { + chart.addSingleSeriesAsDrilldown(e.point, seriesOptions); + } + else { + chart.addSeriesAsDrilldown(e.point, seriesOptions); + } + } + }); + }; + /** + * Drill down to a given category. This is the same as clicking on an axis + * label. + * + * @private + * @function Highcharts.Axis#drilldownCategory + * @param {number} x + * Tick position + * @param {global.MouseEvent} e + * Click event + * @return {void} + */ + H.Axis.prototype.drilldownCategory = function (x, e) { + objectEach(this.getDDPoints(x), function (point) { + if (point && + point.series && + point.series.visible && + point.doDrilldown) { // #3197 + point.doDrilldown(true, x, e); + } + }); + this.chart.applyDrilldown(); + }; + /** + * Return drillable points for this specific X value. + * + * @private + * @function Highcharts.Axis#getDDPoints + * @param {number} x + * Tick position + * @return {Array<(boolean|Highcharts.Point)>|undefined} + * Drillable points + */ + H.Axis.prototype.getDDPoints = function (x) { + return this.ddPoints && this.ddPoints[x]; + }; + /** + * Make a tick label drillable, or remove drilling on update. + * + * @private + * @function Highcharts.Axis#drillable + * @return {void} + */ + Tick.prototype.drillable = function () { + var pos = this.pos, label = this.label, axis = this.axis, isDrillable = axis.coll === 'xAxis' && axis.getDDPoints, ddPointsX = isDrillable && axis.getDDPoints(pos), styledMode = axis.chart.styledMode; + if (isDrillable) { + if (label && ddPointsX && ddPointsX.length) { + label.drillable = true; + if (!label.basicStyles && !styledMode) { + label.basicStyles = merge(label.styles); + } + label.addClass('highcharts-drilldown-axis-label'); + // #12656 - avoid duplicate of attach event + if (label.removeOnDrillableClick) { + removeEvent(label.element, 'click'); + } + label.removeOnDrillableClick = addEvent(label.element, 'click', function (e) { + e.preventDefault(); + axis.drilldownCategory(pos, e); + }); + if (!styledMode) { + label.css(axis.chart.options.drilldown.activeAxisLabelStyle); + } + } + else if (label && label.drillable && label.removeOnDrillableClick) { + if (!styledMode) { + label.styles = {}; // reset for full overwrite of styles + label.css(label.basicStyles); + } + label.removeOnDrillableClick(); // #3806 + label.removeClass('highcharts-drilldown-axis-label'); + } + } + }; + // On initialization of each point, identify its label and make it clickable. + // Also, provide a list of points associated to that label. + addEvent(Point, 'afterInit', function () { + var point = this, series = point.series; + if (point.drilldown) { + // Add the click event to the point + addEvent(point, 'click', function (e) { + if (series.xAxis && + series.chart.options.drilldown.allowPointDrilldown === + false) { + // #5822, x changed + series.xAxis.drilldownCategory(point.x, e); + } + else { + point.doDrilldown(void 0, void 0, e); + } + }); + } + return point; + }); + addEvent(H.Series, 'afterDrawDataLabels', function () { + var css = this.chart.options.drilldown.activeDataLabelStyle, renderer = this.chart.renderer, styledMode = this.chart.styledMode; + this.points.forEach(function (point) { + var dataLabelsOptions = point.options.dataLabels, pointCSS = pick(point.dlOptions, dataLabelsOptions && dataLabelsOptions.style, {}); + if (point.drilldown && point.dataLabel) { + if (css.color === 'contrast' && !styledMode) { + pointCSS.color = renderer.getContrast(point.color || this.color); + } + if (dataLabelsOptions && dataLabelsOptions.color) { + pointCSS.color = dataLabelsOptions.color; + } + point.dataLabel + .addClass('highcharts-drilldown-data-label'); + if (!styledMode) { + point.dataLabel + .css(css) + .css(pointCSS); + } + } + }, this); + }); + var applyCursorCSS = function (element, cursor, addClass, styledMode) { + element[addClass ? 'addClass' : 'removeClass']('highcharts-drilldown-point'); + if (!styledMode) { + element.css({ cursor: cursor }); + } + }; + // Mark the trackers with a pointer + addEvent(H.Series, 'afterDrawTracker', function () { + var styledMode = this.chart.styledMode; + this.points.forEach(function (point) { + if (point.drilldown && point.graphic) { + applyCursorCSS(point.graphic, 'pointer', true, styledMode); + } + }); + }); + addEvent(Point, 'afterSetState', function () { + var styledMode = this.series.chart.styledMode; + if (this.drilldown && this.series.halo && this.state === 'hover') { + applyCursorCSS(this.series.halo, 'pointer', true, styledMode); + } + else if (this.series.halo) { + applyCursorCSS(this.series.halo, 'auto', false, styledMode); + } + }); + + }); + _registerModule(_modules, 'masters/modules/drilldown.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/dumbbell.js b/librerias/gantt/code/modules/dumbbell.js new file mode 100644 index 0000000..2248c14 --- /dev/null +++ b/librerias/gantt/code/modules/dumbbell.js @@ -0,0 +1,16 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2009-2019 Sebastian Bochan, Rafal Sebestjanski + + License: www.highcharts.com/license +*/ +(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/dumbbell",["highcharts"],function(f){b(f);b.Highcharts=f;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function f(b,c,f,r){b.hasOwnProperty(c)||(b[c]=r.apply(null,f))}b=b?b._modules:{};f(b,"modules/dumbbell.src.js",[b["parts/Globals.js"],b["parts/Utilities.js"]],function(b,c){var f=b.SVGRenderer,r=c.extend,h=c.pick; +c=c.seriesType;var p=b.seriesTypes,u=b.Series.prototype,l=p.arearange.prototype,t=p.column.prototype,m=l.pointClass.prototype;c("dumbbell","arearange",{trackByArea:!1,fillColor:"none",lineWidth:0,pointRange:1,connectorWidth:1,stickyTracking:!1,groupPadding:.2,crisp:!1,pointPadding:.1,lowColor:"#333333",states:{hover:{lineWidthPlus:0,connectorWidthPlus:1,halo:!1}}},{trackerGroups:["group","markerGroup","dataLabelsGroup"],drawTracker:b.TrackerMixin.drawTrackerPoint,drawGraph:b.noop,crispCol:t.crispCol, +getConnectorAttribs:function(a){var b=this.chart,e=a.options,g=this.options,d=this.xAxis,n=this.yAxis,c=h(e.connectorWidth,g.connectorWidth),l=h(e.connectorColor,g.connectorColor,e.color,a.zone?a.zone.color:void 0,a.color),p=h(g.states&&g.states.hover&&g.states.hover.connectorWidthPlus,1),m=h(e.dashStyle,g.dashStyle),q=h(a.plotLow,a.plotY),k=n.toPixels(g.threshold||0,!0);k=h(a.plotHigh,b.inverted?n.len-k:k);a.state&&(c+=p);0>q?q=0:q>=n.len&&(q=n.len);0>k?k=0:k>=n.len&&(k=n.len);if(0>a.plotX||a.plotX> +d.len)c=0;a.upperGraphic&&(d={y:a.y,zone:a.zone},a.y=a.high,a.zone=a.zone?a.getZone():void 0,l=h(e.connectorColor,g.connectorColor,e.color,a.zone?a.zone.color:void 0,a.color),r(a,d));a={d:f.prototype.crispLine([["M",a.plotX,q],["L",a.plotX,k]],c,"ceil")};b.styledMode||(a.stroke=l,a["stroke-width"]=c,m&&(a.dashstyle=m));return a},drawConnector:function(a){var b=h(this.options.animationLimit,250);b=a.connector&&this.chart.pointCount= yAxis.len) { + pointTop = yAxis.len; + } + if (pointBottom < 0) { + pointBottom = 0; + } + else if (pointBottom >= yAxis.len) { + pointBottom = yAxis.len; + } + if (point.plotX < 0 || point.plotX > xAxis.len) { + connectorWidth = 0; + } + // Connector should reflect upper marker's zone color + if (point.upperGraphic) { + origProps = { + y: point.y, + zone: point.zone + }; + point.y = point.high; + point.zone = point.zone ? point.getZone() : void 0; + connectorColor = pick(pointOptions.connectorColor, seriesOptions.connectorColor, pointOptions.color, point.zone ? point.zone.color : void 0, point.color); + extend(point, origProps); + } + attribs = { + d: SVGRenderer.prototype.crispLine([[ + 'M', + point.plotX, + pointTop + ], [ + 'L', + point.plotX, + pointBottom + ]], connectorWidth, 'ceil') + }; + if (!chart.styledMode) { + attribs.stroke = connectorColor; + attribs['stroke-width'] = connectorWidth; + if (dashStyle) { + attribs.dashstyle = dashStyle; + } + } + return attribs; + }, + /** + * Draw connector line that connects dumbbell point's low and high values. + * @private + * + * @param {Highcharts.Series} this The series of points. + * @param {Highcharts.Point} point The point to inspect. + * + * @return {void} + */ + drawConnector: function (point) { + var series = this, animationLimit = pick(series.options.animationLimit, 250), verb = point.connector && series.chart.pointCount < animationLimit ? + 'animate' : 'attr'; + if (!point.connector) { + point.connector = series.chart.renderer.path() + .addClass('highcharts-lollipop-stem') + .attr({ + zIndex: -1 + }) + .add(series.markerGroup); + } + point.connector[verb](this.getConnectorAttribs(point)); + }, + /** + * Return the width and x offset of the dumbbell adjusted for grouping, + * groupPadding, pointPadding, pointWidth etc. + * + * @private + * + * @function Highcharts.seriesTypes.column#getColumnMetrics + * + * @param {Highcharts.Series} this The series of points. + * + * @return {Highcharts.ColumnMetricsObject} metrics shapeArgs + * + */ + getColumnMetrics: function () { + var metrics = colProto.getColumnMetrics.apply(this, arguments); + metrics.offset += metrics.width / 2; + return metrics; + }, + translatePoint: areaRangeProto.translate, + setShapeArgs: columnRangeProto.translate, + /** + * Translate each point to the plot area coordinate system and find + * shape positions + * + * @private + * + * @function Highcharts.seriesTypes.dumbbell#translate + * + * @param {Highcharts.Series} this The series of points. + * + * @return {void} + */ + translate: function () { + // Calculate shapeargs + this.setShapeArgs.apply(this); + // Calculate point low / high values + this.translatePoint.apply(this, arguments); + // Correct x position + this.points.forEach(function (point) { + var shapeArgs = point.shapeArgs, pointWidth = point.pointWidth; + point.plotX = shapeArgs.x; + shapeArgs.x = point.plotX - pointWidth / 2; + point.tooltipPos = null; + }); + this.columnMetrics.offset -= this.columnMetrics.width / 2; + }, + seriesDrawPoints: areaRangeProto.drawPoints, + /** + * Extend the arearange series' drawPoints method by applying a connector + * and coloring markers. + * @private + * + * @function Highcharts.Series#drawPoints + * + * @param {Highcharts.Series} this The series of points. + * + * @return {void} + */ + drawPoints: function () { + var series = this, chart = series.chart, pointLength = series.points.length, seriesLowColor = series.lowColor = series.options.lowColor, i = 0, lowerGraphicColor, point, zoneColor; + this.seriesDrawPoints.apply(series, arguments); + // Draw connectors and color upper markers + while (i < pointLength) { + point = series.points[i]; + series.drawConnector(point); + if (point.upperGraphic) { + point.upperGraphic.element.point = point; + point.upperGraphic.addClass('highcharts-lollipop-high'); + } + point.connector.element.point = point; + if (point.lowerGraphic) { + zoneColor = point.zone && point.zone.color; + lowerGraphicColor = pick(point.options.lowColor, seriesLowColor, point.options.color, zoneColor, point.color, series.color); + if (!chart.styledMode) { + point.lowerGraphic.attr({ + fill: lowerGraphicColor + }); + } + point.lowerGraphic.addClass('highcharts-lollipop-low'); + } + i++; + } + }, + /** + * Get non-presentational attributes for a point. Used internally for + * both styled mode and classic. Set correct position in link with connector + * line. + * + * @see Series#pointAttribs + * + * @function Highcharts.Series#markerAttribs + * + * @param {Highcharts.Series} this The series of points. + * + * @return {Highcharts.SVGAttributes} + * A hash containing those attributes that are not settable from + * CSS. + */ + markerAttribs: function () { + var ret = areaRangeProto.markerAttribs.apply(this, arguments); + ret.x = Math.floor(ret.x); + ret.y = Math.floor(ret.y); + return ret; + }, + /** + * Get presentational attributes + * + * @private + * @function Highcharts.seriesTypes.column#pointAttribs + * + * @param {Highcharts.Series} this The series of points. + * @param {Highcharts.Point} point The point to inspect. + * @param {string} state current state of point (normal, hover, select) + * + * @return {Highcharts.SVGAttributes} pointAttribs SVGAttributes + */ + pointAttribs: function (point, state) { + var pointAttribs; + pointAttribs = seriesProto.pointAttribs.apply(this, arguments); + if (state === 'hover') { + delete pointAttribs.fill; + } + return pointAttribs; + } + }, { + // seriesTypes doesn't inherit from arearange point proto so put below + // methods rigidly. + destroyElements: areaRangePointProto.destroyElements, + isValid: areaRangePointProto.isValid, + pointSetState: areaRangePointProto.setState, + /** + * Set the point's state extended by have influence on the connector + * (between low and high value). + * + * @private + * @param {Highcharts.Point} this The point to inspect. + * + * @return {void} + */ + setState: function () { + var point = this, series = point.series, chart = series.chart, seriesLowColor = series.options.lowColor, seriesMarker = series.options.marker, pointOptions = point.options, pointLowColor = pointOptions.lowColor, zoneColor = point.zone && point.zone.color, lowerGraphicColor = pick(pointLowColor, seriesLowColor, pointOptions.color, zoneColor, point.color, series.color), verb = 'attr', upperGraphicColor, origProps; + this.pointSetState.apply(this, arguments); + if (!point.state) { + verb = 'animate'; + if (point.lowerGraphic && !chart.styledMode) { + point.lowerGraphic.attr({ + fill: lowerGraphicColor + }); + if (point.upperGraphic) { + origProps = { + y: point.y, + zone: point.zone + }; + point.y = point.high; + point.zone = point.zone ? point.getZone() : void 0; + upperGraphicColor = pick(point.marker ? point.marker.fillColor : void 0, seriesMarker ? seriesMarker.fillColor : void 0, pointOptions.color, point.zone ? point.zone.color : void 0, point.color); + point.upperGraphic.attr({ + fill: upperGraphicColor + }); + extend(point, origProps); + } + } + } + point.connector[verb](series.getConnectorAttribs(point)); + } + }); + /** + * The `dumbbell` series. If the [type](#series.dumbbell.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.dumbbell + * @product highcharts highstock + * @requires highcharts-more + * @requires modules/dumbbell + * @apioption series.dumbbell + */ + /** + * An array of data points for the series. For the `dumbbell` series + * type, points can be given in the following ways: + * + * 1. An array of arrays with 3 or 2 values. In this case, the values correspond + * to `x,low,high`. If the first value is a string, it is applied as the name + * of the point, and the `x` value is inferred. The `x` value can also be + * omitted, in which case the inner arrays should be of length 2\. Then the + * `x` value is automatically calculated, either starting at 0 and + * incremented by 1, or from `pointStart` and `pointInterval` given in the + * series options. + * ```js + * data: [ + * [0, 4, 2], + * [1, 2, 1], + * [2, 9, 10] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.dumbbell.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * low: 0, + * high: 4, + * name: "Point2", + * color: "#00FF00", + * lowColor: "#00FFFF", + * connectorWidth: 3, + * connectorColor: "#FF00FF" + * }, { + * x: 1, + * low: 5, + * high: 3, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|Array<(number|string),number,number>|*>} + * @extends series.arearange.data + * @product highcharts highstock + * @apioption series.dumbbell.data + */ + /** + * Color of the line that connects the dumbbell point's values. + * By default it is the series' color. + * + * @type {string} + * @since 8.0.0 + * @product highcharts highstock + * @apioption series.dumbbell.data.connectorColor + */ + /** + * Pixel width of the line that connects the dumbbell point's values. + * + * @type {number} + * @since 8.0.0 + * @default 1 + * @product highcharts highstock + * @apioption series.dumbbell.data.connectorWidth + */ + /** + * Color of the start markers in a dumbbell graph. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 8.0.0 + * @default #333333 + * @product highcharts highstock + * @apioption series.dumbbell.data.lowColor + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'masters/modules/dumbbell.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/export-data.js b/librerias/gantt/code/modules/export-data.js new file mode 100644 index 0000000..f44dbe2 --- /dev/null +++ b/librerias/gantt/code/modules/export-data.js @@ -0,0 +1,30 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Exporting module + + (c) 2010-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(c){"object"===typeof module&&module.exports?(c["default"]=c,module.exports=c):"function"===typeof define&&define.amd?define("highcharts/modules/export-data",["highcharts","highcharts/modules/exporting"],function(e){c(e);c.Highcharts=e;return c}):c("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(c){function e(b,a,c,g){b.hasOwnProperty(a)||(b[a]=g.apply(null,c))}c=c?c._modules:{};e(c,"mixins/ajax.js",[c["parts/Globals.js"],c["parts/Utilities.js"]],function(b,a){var c=a.merge, +g=a.objectEach;b.ajax=function(b){var a=c(!0,{url:!1,type:"get",dataType:"json",success:!1,error:!1,data:!1,headers:{}},b);b={json:"application/json",xml:"application/xml",text:"text/plain",octet:"application/octet-stream"};var d=new XMLHttpRequest;if(!a.url)return!1;d.open(a.type.toUpperCase(),a.url,!0);a.headers["Content-Type"]||d.setRequestHeader("Content-Type",b[a.dataType]||b.text);g(a.headers,function(a,b){d.setRequestHeader(b,a)});d.onreadystatechange=function(){if(4===d.readyState){if(200=== +d.status){var b=d.responseText;if("json"===a.dataType)try{b=JSON.parse(b)}catch(f){a.error&&a.error(d,f);return}return a.success&&a.success(b)}a.error&&a.error(d,d.responseText)}};try{a.data=JSON.stringify(a.data)}catch(C){}d.send(a.data||!0)};b.getJSON=function(a,c){b.ajax({url:a,success:c,dataType:"json",headers:{"Content-Type":"text/plain"}})}});e(c,"mixins/download-url.js",[c["parts/Globals.js"]],function(b){var a=b.win,c=a.navigator,g=a.document,e=a.URL||a.webkitURL||a,t=/Edge\/\d+/.test(c.userAgent); +b.dataURLtoBlob=function(b){if((b=b.match(/data:([^;]*)(;base64)?,([0-9A-Za-z+/]+)/))&&3c.userAgent.indexOf("Chrome"), +f=d.URL||d.webkitURL||d;try{if(c.msSaveOrOpenBlob&&d.MSBlobBuilder){var q=new d.MSBlobBuilder;q.append(a);return q.getBlob("image/svg+xml")}if(!n)return f.createObjectURL(new d.Blob(["\ufeff"+a],{type:b}))}catch(H){}}var e=a.defined,G=a.extend,t=a.pick,d=b.win,C=d.document,f=b.seriesTypes,l=b.downloadURL,y=b.fireEvent;b.setOptions({exporting:{csv:{columnHeaderFormatter:null,dateFormat:"%Y-%m-%d %H:%M:%S",decimalPoint:null,itemDelimiter:null,lineDelimiter:"\n"},showTable:!1,useMultiLevelHeaders:!0, +useRowspanHeaders:!0},lang:{downloadCSV:"Download CSV",downloadXLS:"Download XLS",exportData:{categoryHeader:"Category",categoryDatetimeHeader:"DateTime"},viewData:"View data table"}});b.addEvent(b.Chart,"render",function(){this.options&&this.options.exporting&&this.options.exporting.showTable&&!this.options.chart.forExport&&this.viewData()});b.Chart.prototype.setUpKeyToAxis=function(){f.arearange&&(f.arearange.prototype.keyToAxis={low:"y",high:"y"});f.gantt&&(f.gantt.prototype.keyToAxis={start:"x", +end:"x"})};b.Chart.prototype.getDataRows=function(a){var c=this.hasParallelCoordinates,d=this.time,f=this.options.exporting&&this.options.exporting.csv||{},n=this.xAxis,q={},l=[],D=[],A=[],r;var u=this.options.lang.exportData;var w=u.categoryHeader,m=u.categoryDatetimeHeader,E=function(k,c,d){if(f.columnHeaderFormatter){var h=f.columnHeaderFormatter(k,c,d);if(!1!==h)return h}return k?k instanceof b.Axis?k.options.title&&k.options.title.text||(k.dateTime?m:w):a?{columnTitle:1',c=this.options,d=a?(1.1).toLocaleString()[1]:".",g=t(c.exporting.useMultiLevelHeaders,!0);a=this.getDataRows(g);var f=0,e=g?a.shift():null,l=a.shift(),n=function(a,b,c,g){var h=t(g,"");b="text"+(b?" "+b:"");"number"===typeof h?(h=h.toString(),","===d&&(h= +h.replace(".",d)),b="number"):g||(b="empty");return"<"+a+(c?" "+c:"")+' class="'+b+'">'+h+""};!1!==c.exporting.tableCaption&&(b+=''+t(c.exporting.tableCaption,c.title.text?c.title.text.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/"):"Chart")+"");for(var r=0,u=a.length;rf&&(f=a[r].length);b+=function(a,b,d){var f="",h=0;d=d||b&& +b.length;var e,l=0;if(e=g&&a&&b){a:if(e=a.length,b.length===e){for(;e--;)if(a[e]!==b[e]){e=!1;break a}e=!0}else e=!1;e=!e}if(e){for(f+="";h"}return f+""}(e,l,Math.max(f,l.length));b+="";a.forEach(function(a){b+="";for(var c=0;c"});b+="";a={html:b};y(this,"afterGetTable",a);return a.html};b.Chart.prototype.downloadCSV=function(){var a=this.getCSV(!0);l(c(a,"text/csv")||"data:text/csv,\ufeff"+encodeURIComponent(a),this.getFilename()+".csv")};b.Chart.prototype.downloadXLS=function(){var a= +'\x3c!--[if gte mso 9]>Ark1td{border:none;font-family: Calibri, sans-serif;} .number{mso-number-format:"0.00";} .text{ mso-number-format:"@";}'+ +this.getTable(!0)+"";l(c(a,"application/vnd.ms-excel")||"data:application/vnd.ms-excel;base64,"+d.btoa(unescape(encodeURIComponent(a))),this.getFilename()+".xls")};b.Chart.prototype.viewData=function(){this.dataTableDiv||(this.dataTableDiv=C.createElement("div"),this.dataTableDiv.className="highcharts-data-table",this.renderTo.parentNode.insertBefore(this.dataTableDiv,this.renderTo.nextSibling));this.dataTableDiv.innerHTML=this.getTable();y(this,"afterViewData",this.dataTableDiv)};if(a= +b.getOptions().exporting)G(a.menuItemDefinitions,{downloadCSV:{textKey:"downloadCSV",onclick:function(){this.downloadCSV()}},downloadXLS:{textKey:"downloadXLS",onclick:function(){this.downloadXLS()}},viewData:{textKey:"viewData",onclick:function(){this.viewData()}}}),a.buttons&&a.buttons.contextButton.menuItems.push("separator","downloadCSV","downloadXLS","viewData");f.map&&(f.map.prototype.exportKey="name");f.mapbubble&&(f.mapbubble.prototype.exportKey="name");f.treemap&&(f.treemap.prototype.exportKey= +"name")});e(c,"masters/modules/export-data.src.js",[],function(){})}); +//# sourceMappingURL=export-data.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/export-data.js.map b/librerias/gantt/code/modules/export-data.js.map new file mode 100644 index 0000000..dd27eba --- /dev/null +++ b/librerias/gantt/code/modules/export-data.js.map @@ -0,0 +1 @@ +{"version":3,"file":"export-data.js.map","lineCount":29,"mappings":"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","sources":["export-data.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","U","merge","objectEach","ajax","H.ajax","attr","options","url","type","dataType","success","error","data","headers","json","xml","text","octet","r","XMLHttpRequest","open","toUpperCase","setRequestHeader","val","key","onreadystatechange","r.onreadystatechange","readyState","status","res","responseText","JSON","parse","e","stringify","send","getJSON","H.getJSON","win","nav","navigator","doc","document","domurl","URL","webkitURL","isEdgeBrowser","test","userAgent","dataURLtoBlob","Highcharts.dataURLtoBlob","dataURL","parts","match","length","atob","ArrayBuffer","Uint8Array","Blob","createObjectURL","binStr","buf","binary","i","charCodeAt","blob","downloadURL","Highcharts.downloadURL","filename","a","createElement","String","msSaveOrOpenBlob","Error","download","href","body","appendChild","click","removeChild","windowRef","location","getBlobFromContent","content","webKit","indexOf","MSBlobBuilder","append","getBlob","defined","extend","pick","seriesTypes","fireEvent","setOptions","exporting","csv","columnHeaderFormatter","dateFormat","decimalPoint","itemDelimiter","lineDelimiter","showTable","useMultiLevelHeaders","useRowspanHeaders","lang","downloadCSV","downloadXLS","exportData","categoryHeader","categoryDatetimeHeader","viewData","addEvent","Chart","chart","forExport","prototype","setUpKeyToAxis","Highcharts.Chart.prototype.setUpKeyToAxis","arearange","keyToAxis","low","high","gantt","start","end","getDataRows","Highcharts.Chart.prototype.getDataRows","multiLevelHeaders","hasParallelCoords","hasParallelCoordinates","time","csvOptions","xAxes","xAxis","rows","rowArr","topLevelColumnTitles","columnTitles","columnTitleObj","exportDataOptions","item","keyLength","s","Axis","title","dateTime","columnTitle","name","topLevelColumnTitle","getCategoryAndDateTimeMap","series","pointArrayMap","pIdx","categoryMap","dateTimeValueAxisMap","forEach","prop","axisName","axis","isNumber","categories","xAxisIndices","keys","valueCount","xTaken","requireSorting","xAxisIndex","categoryAndDatetimeMap","j","includeInDataExport","isInternal","visible","find","index","push","mockSeries","autoIncrement","eachData","point","pointClass","applyOptions","x","exportKey","hasNames","xValues","Object","call","dataRows","column","sort","b","xTitle","splice","row","category","Date","getTime","names","concat","getCSV","Highcharts.Chart.prototype.getCSV","useLocalDecimalPoint","toLocaleString","toString","replace","join","getTable","Highcharts.Chart.prototype.getTable","html","rowLength","topHeaders","shift","subHeaders","getCellHTMLFromValue","tag","classes","attrs","value","className","tableCaption","len","getTableHeaderHTML","topheaders","subheaders","cur","curColspan","row1","row2","next","rowspan","Math","max","Highcharts.Chart.prototype.downloadCSV","encodeURIComponent","getFilename","Highcharts.Chart.prototype.downloadXLS","template","uri","btoa","unescape","Highcharts.Chart.prototype.viewData","dataTableDiv","renderTo","parentNode","insertBefore","nextSibling","innerHTML","exportingOptions","getOptions","menuItemDefinitions","textKey","onclick","buttons","contextButton","menuItems","map","mapbubble","treemap"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/export-data.src.js b/librerias/gantt/code/modules/export-data.src.js new file mode 100644 index 0000000..b600557 --- /dev/null +++ b/librerias/gantt/code/modules/export-data.src.js @@ -0,0 +1,1095 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * Exporting module + * + * (c) 2010-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/export-data', ['highcharts', 'highcharts/modules/exporting'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'mixins/ajax.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2017 Christer Vasseng, Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var merge = U.merge, objectEach = U.objectEach; + /** + * @interface Highcharts.AjaxSettingsObject + */ /** + * The payload to send. + * + * @name Highcharts.AjaxSettingsObject#data + * @type {string|Highcharts.Dictionary} + */ /** + * The data type expected. + * @name Highcharts.AjaxSettingsObject#dataType + * @type {"json"|"xml"|"text"|"octet"} + */ /** + * Function to call on error. + * @name Highcharts.AjaxSettingsObject#error + * @type {Function} + */ /** + * The headers; keyed on header name. + * @name Highcharts.AjaxSettingsObject#headers + * @type {Highcharts.Dictionary} + */ /** + * Function to call on success. + * @name Highcharts.AjaxSettingsObject#success + * @type {Function} + */ /** + * The verb to use. + * @name Highcharts.AjaxSettingsObject#type + * @type {"GET"|"POST"|"UPDATE"|"DELETE"} + */ /** + * The URL to call. + * @name Highcharts.AjaxSettingsObject#url + * @type {string} + */ + /** + * Perform an Ajax call. + * + * @function Highcharts.ajax + * + * @param {Partial} attr + * The Ajax settings to use. + * + * @return {false|undefined} + * Returns false, if error occured. + */ + H.ajax = function (attr) { + var options = merge(true, { + url: false, + type: 'get', + dataType: 'json', + success: false, + error: false, + data: false, + headers: {} + }, attr), headers = { + json: 'application/json', + xml: 'application/xml', + text: 'text/plain', + octet: 'application/octet-stream' + }, r = new XMLHttpRequest(); + /** + * @private + * @param {XMLHttpRequest} xhr - Internal request object. + * @param {string|Error} err - Occured error. + * @return {void} + */ + function handleError(xhr, err) { + if (options.error) { + options.error(xhr, err); + } + else { + // @todo Maybe emit a highcharts error event here + } + } + if (!options.url) { + return false; + } + r.open(options.type.toUpperCase(), options.url, true); + if (!options.headers['Content-Type']) { + r.setRequestHeader('Content-Type', headers[options.dataType] || headers.text); + } + objectEach(options.headers, function (val, key) { + r.setRequestHeader(key, val); + }); + // @todo lacking timeout handling + r.onreadystatechange = function () { + var res; + if (r.readyState === 4) { + if (r.status === 200) { + res = r.responseText; + if (options.dataType === 'json') { + try { + res = JSON.parse(res); + } + catch (e) { + return handleError(r, e); + } + } + return options.success && options.success(res); + } + handleError(r, r.responseText); + } + }; + try { + options.data = JSON.stringify(options.data); + } + catch (e) { + // empty + } + r.send(options.data || true); + }; + /** + * Get a JSON resource over XHR, also supporting CORS without preflight. + * + * @function Highcharts.getJSON + * @param {string} url + * The URL to load. + * @param {Function} success + * The success callback. For error handling, use the `Highcharts.ajax` + * function instead. + * @return {void} + */ + H.getJSON = function (url, success) { + H.ajax({ + url: url, + success: success, + dataType: 'json', + headers: { + // Override the Content-Type to avoid preflight problems with CORS + // in the Highcharts demos + 'Content-Type': 'text/plain' + } + }); + }; + + }); + _registerModule(_modules, 'mixins/download-url.js', [_modules['parts/Globals.js']], function (Highcharts) { + /* * + * + * (c) 2015-2020 Oystein Moseng + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * Mixin for downloading content in the browser + * + * */ + var win = Highcharts.win, nav = win.navigator, doc = win.document, domurl = win.URL || win.webkitURL || win, isEdgeBrowser = /Edge\/\d+/.test(nav.userAgent); + /** + * Convert base64 dataURL to Blob if supported, otherwise returns undefined. + * @private + * @function Highcharts.dataURLtoBlob + * @param {string} dataURL + * URL to convert + * @return {string|undefined} + * Blob + */ + Highcharts.dataURLtoBlob = function (dataURL) { + var parts = dataURL.match(/data:([^;]*)(;base64)?,([0-9A-Za-z+/]+)/); + if (parts && + parts.length > 3 && + win.atob && + win.ArrayBuffer && + win.Uint8Array && + win.Blob && + domurl.createObjectURL) { + // Try to convert data URL to Blob + var binStr = win.atob(parts[3]), buf = new win.ArrayBuffer(binStr.length), binary = new win.Uint8Array(buf), blob; + for (var i = 0; i < binary.length; ++i) { + binary[i] = binStr.charCodeAt(i); + } + blob = new win.Blob([binary], { 'type': parts[1] }); + return domurl.createObjectURL(blob); + } + }; + /** + * Download a data URL in the browser. Can also take a blob as first param. + * + * @private + * @function Highcharts.downloadURL + * @param {string|global.URL} dataURL + * The dataURL/Blob to download + * @param {string} filename + * The name of the resulting file (w/extension) + * @return {void} + */ + Highcharts.downloadURL = function (dataURL, filename) { + var a = doc.createElement('a'), windowRef; + // IE specific blob implementation + // Don't use for normal dataURLs + if (typeof dataURL !== 'string' && + !(dataURL instanceof String) && + nav.msSaveOrOpenBlob) { + nav.msSaveOrOpenBlob(dataURL, filename); + return; + } + // Some browsers have limitations for data URL lengths. Try to convert to + // Blob or fall back. Edge always needs that blob. + if (isEdgeBrowser || dataURL.length > 2000000) { + dataURL = Highcharts.dataURLtoBlob(dataURL); + if (!dataURL) { + throw new Error('Failed to convert to blob'); + } + } + // Try HTML5 download attr if supported + if (typeof a.download !== 'undefined') { + a.href = dataURL; + a.download = filename; // HTML5 download attribute + doc.body.appendChild(a); + a.click(); + doc.body.removeChild(a); + } + else { + // No download attr, just opening data URI + try { + windowRef = win.open(dataURL, 'chart'); + if (typeof windowRef === 'undefined' || windowRef === null) { + throw new Error('Failed to open window'); + } + } + catch (e) { + // window.open failed, trying location.href + win.location.href = dataURL; + } + } + }; + + }); + _registerModule(_modules, 'modules/export-data.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (Highcharts, U) { + /* * + * + * Experimental data export module for Highcharts + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + // @todo + // - Set up systematic tests for all series types, paired with tests of the data + // module importing the same data. + /** + * Function callback to execute while data rows are processed for exporting. + * This allows the modification of data rows before processed into the final + * format. + * + * @callback Highcharts.ExportDataCallbackFunction + * @extends Highcharts.EventCallbackFunction + * + * @param {Highcharts.Chart} this + * Chart context where the event occured. + * + * @param {Highcharts.ExportDataEventObject} event + * Event object with data rows that can be modified. + */ + /** + * Contains information about the export data event. + * + * @interface Highcharts.ExportDataEventObject + */ /** + * Contains the data rows for the current export task and can be modified. + * @name Highcharts.ExportDataEventObject#dataRows + * @type {Array>} + */ + var defined = U.defined, extend = U.extend, isObject = U.isObject, pick = U.pick; + var win = Highcharts.win, doc = win.document, seriesTypes = Highcharts.seriesTypes, downloadURL = Highcharts.downloadURL, fireEvent = Highcharts.fireEvent; + // Can we add this to utils? Also used in screen-reader.js + /** + * HTML encode some characters vulnerable for XSS. + * @private + * @param {string} html The input string + * @return {string} The excaped string + */ + function htmlencode(html) { + return html + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(/\//g, '/'); + } + Highcharts.setOptions({ + /** + * Callback that fires while exporting data. This allows the modification of + * data rows before processed into the final format. + * + * @type {Highcharts.ExportDataCallbackFunction} + * @context Highcharts.Chart + * @requires modules/export-data + * @apioption chart.events.exportData + */ + /** + * When set to `false` will prevent the series data from being included in + * any form of data export. + * + * Since version 6.0.0 until 7.1.0 the option was existing undocumented + * as `includeInCSVExport`. + * + * @type {boolean} + * @since 7.1.0 + * @requires modules/export-data + * @apioption plotOptions.series.includeInDataExport + */ + /** + * @optionparent exporting + * @private + */ + exporting: { + /** + * Caption for the data table. Same as chart title by default. Set to + * `false` to disable. + * + * @sample highcharts/export-data/multilevel-table + * Multiple table headers + * + * @type {boolean|string} + * @since 6.0.4 + * @requires modules/export-data + * @apioption exporting.tableCaption + */ + /** + * Options for exporting data to CSV or ExCel, or displaying the data + * in a HTML table or a JavaScript structure. + * + * This module adds data export options to the export menu and provides + * functions like `Chart.getCSV`, `Chart.getTable`, `Chart.getDataRows` + * and `Chart.viewData`. + * + * The XLS converter is limited and only creates a HTML string that is + * passed for download, which works but creates a warning before + * opening. The workaround for this is to use a third party XLSX + * converter, as demonstrated in the sample below. + * + * @sample highcharts/export-data/categorized/ Categorized data + * @sample highcharts/export-data/stock-timeaxis/ Highstock time axis + * @sample highcharts/export-data/xlsx/ + * Using a third party XLSX converter + * + * @since 6.0.0 + * @requires modules/export-data + */ + csv: { + /** + * Formatter callback for the column headers. Parameters are: + * - `item` - The series or axis object) + * - `key` - The point key, for example y or z + * - `keyLength` - The amount of value keys for this item, for + * example a range series has the keys `low` and `high` so the + * key length is 2. + * + * If [useMultiLevelHeaders](#exporting.useMultiLevelHeaders) is + * true, columnHeaderFormatter by default returns an object with + * columnTitle and topLevelColumnTitle for each key. Columns with + * the same topLevelColumnTitle have their titles merged into a + * single cell with colspan for table/Excel export. + * + * If `useMultiLevelHeaders` is false, or for CSV export, it returns + * the series name, followed by the key if there is more than one + * key. + * + * For the axis it returns the axis title or "Category" or + * "DateTime" by default. + * + * Return `false` to use Highcharts' proposed header. + * + * @sample highcharts/export-data/multilevel-table + * Multiple table headers + * + * @type {Function|null} + */ + columnHeaderFormatter: null, + /** + * Which date format to use for exported dates on a datetime X axis. + * See `Highcharts.dateFormat`. + */ + dateFormat: '%Y-%m-%d %H:%M:%S', + /** + * Which decimal point to use for exported CSV. Defaults to the same + * as the browser locale, typically `.` (English) or `,` (German, + * French etc). + * + * @type {string|null} + * @since 6.0.4 + */ + decimalPoint: null, + /** + * The item delimiter in the exported data. Use `;` for direct + * exporting to Excel. Defaults to a best guess based on the browser + * locale. If the locale _decimal point_ is `,`, the `itemDelimiter` + * defaults to `;`, otherwise the `itemDelimiter` defaults to `,`. + * + * @type {string|null} + */ + itemDelimiter: null, + /** + * The line delimiter in the exported data, defaults to a newline. + */ + lineDelimiter: '\n' + }, + /** + * Show a HTML table below the chart with the chart's current data. + * + * @sample highcharts/export-data/showtable/ + * Show the table + * @sample highcharts/studies/exporting-table-html + * Experiment with putting the table inside the subtitle to + * allow exporting it. + * + * @since 6.0.0 + * @requires modules/export-data + */ + showTable: false, + /** + * Use multi level headers in data table. If [csv.columnHeaderFormatter + * ](#exporting.csv.columnHeaderFormatter) is defined, it has to return + * objects in order for multi level headers to work. + * + * @sample highcharts/export-data/multilevel-table + * Multiple table headers + * + * @since 6.0.4 + * @requires modules/export-data + */ + useMultiLevelHeaders: true, + /** + * If using multi level table headers, use rowspans for headers that + * have only one level. + * + * @sample highcharts/export-data/multilevel-table + * Multiple table headers + * + * @since 6.0.4 + * @requires modules/export-data + */ + useRowspanHeaders: true + }, + /** + * @optionparent lang + * + * @private + */ + lang: { + /** + * The text for the menu item. + * + * @since 6.0.0 + * @requires modules/export-data + */ + downloadCSV: 'Download CSV', + /** + * The text for the menu item. + * + * @since 6.0.0 + * @requires modules/export-data + */ + downloadXLS: 'Download XLS', + /** + * The text for exported table. + * + * @since 8.1.0 + * @requires modules/export-data + */ + exportData: { + /** + * The category column title. + */ + categoryHeader: 'Category', + /** + * The category column title when axis type set to "datetime". + */ + categoryDatetimeHeader: 'DateTime' + }, + /** + * The text for the menu item. + * + * @since 6.0.0 + * @requires modules/export-data + */ + viewData: 'View data table' + } + }); + /* eslint-disable no-invalid-this */ + // Add an event listener to handle the showTable option + Highcharts.addEvent(Highcharts.Chart, 'render', function () { + if (this.options && + this.options.exporting && + this.options.exporting.showTable && + !this.options.chart.forExport) { + this.viewData(); + } + }); + /* eslint-enable no-invalid-this */ + /** + * Set up key-to-axis bindings. This is used when the Y axis is datetime or + * categorized. For example in an arearange series, the low and high values + * should be formatted according to the Y axis type, and in order to link them + * we need this map. + * + * @private + * @function Highcharts.Chart#setUpKeyToAxis + */ + Highcharts.Chart.prototype.setUpKeyToAxis = function () { + if (seriesTypes.arearange) { + seriesTypes.arearange.prototype.keyToAxis = { + low: 'y', + high: 'y' + }; + } + if (seriesTypes.gantt) { + seriesTypes.gantt.prototype.keyToAxis = { + start: 'x', + end: 'x' + }; + } + }; + /** + * Export-data module required. Returns a two-dimensional array containing the + * current chart data. + * + * @function Highcharts.Chart#getDataRows + * + * @param {boolean} [multiLevelHeaders] + * Use multilevel headers for the rows by default. Adds an extra row with + * top level headers. If a custom columnHeaderFormatter is defined, this + * can override the behavior. + * + * @return {Array>} + * The current chart data + * + * @fires Highcharts.Chart#event:exportData + */ + Highcharts.Chart.prototype.getDataRows = function (multiLevelHeaders) { + var hasParallelCoords = this.hasParallelCoordinates, time = this.time, csvOptions = ((this.options.exporting && this.options.exporting.csv) || {}), xAxis, xAxes = this.xAxis, rows = {}, rowArr = [], dataRows, topLevelColumnTitles = [], columnTitles = [], columnTitleObj, i, x, xTitle, langOptions = this.options.lang, exportDataOptions = langOptions.exportData, categoryHeader = exportDataOptions.categoryHeader, categoryDatetimeHeader = exportDataOptions.categoryDatetimeHeader, + // Options + columnHeaderFormatter = function (item, key, keyLength) { + if (csvOptions.columnHeaderFormatter) { + var s = csvOptions.columnHeaderFormatter(item, key, keyLength); + if (s !== false) { + return s; + } + } + if (!item) { + return categoryHeader; + } + if (item instanceof Highcharts.Axis) { + return (item.options.title && item.options.title.text) || + (item.dateTime ? categoryDatetimeHeader : categoryHeader); + } + if (multiLevelHeaders) { + return { + columnTitle: keyLength > 1 ? + key : + item.name, + topLevelColumnTitle: item.name + }; + } + return item.name + (keyLength > 1 ? ' (' + key + ')' : ''); + }, + // Map the categories for value axes + getCategoryAndDateTimeMap = function (series, pointArrayMap, pIdx) { + var categoryMap = {}, dateTimeValueAxisMap = {}; + pointArrayMap.forEach(function (prop) { + var axisName = ((series.keyToAxis && series.keyToAxis[prop]) || + prop) + 'Axis', + // Points in parallel coordinates refers to all yAxis + // not only `series.yAxis` + axis = Highcharts.isNumber(pIdx) ? + series.chart[axisName][pIdx] : + series[axisName]; + categoryMap[prop] = (axis && axis.categories) || []; + dateTimeValueAxisMap[prop] = (axis && axis.dateTime); + }); + return { + categoryMap: categoryMap, + dateTimeValueAxisMap: dateTimeValueAxisMap + }; + }, xAxisIndices = []; + // Loop the series and index values + i = 0; + this.setUpKeyToAxis(); + this.series.forEach(function (series) { + var keys = series.options.keys, xAxis = series.xAxis, pointArrayMap = keys || series.pointArrayMap || ['y'], valueCount = pointArrayMap.length, xTaken = !series.requireSorting && {}, xAxisIndex = xAxes.indexOf(xAxis), categoryAndDatetimeMap = getCategoryAndDateTimeMap(series, pointArrayMap), mockSeries, j; + if (series.options.includeInDataExport !== false && + !series.options.isInternal && + series.visible !== false // #55 + ) { + // Build a lookup for X axis index and the position of the first + // series that belongs to that X axis. Includes -1 for non-axis + // series types like pies. + if (!Highcharts.find(xAxisIndices, function (index) { + return index[0] === xAxisIndex; + })) { + xAxisIndices.push([xAxisIndex, i]); + } + // Compute the column headers and top level headers, usually the + // same as series names + j = 0; + while (j < valueCount) { + columnTitleObj = columnHeaderFormatter(series, pointArrayMap[j], pointArrayMap.length); + columnTitles.push(columnTitleObj.columnTitle || columnTitleObj); + if (multiLevelHeaders) { + topLevelColumnTitles.push(columnTitleObj.topLevelColumnTitle || + columnTitleObj); + } + j++; + } + mockSeries = { + chart: series.chart, + autoIncrement: series.autoIncrement, + options: series.options, + pointArrayMap: series.pointArrayMap + }; + // Export directly from options.data because we need the uncropped + // data (#7913), and we need to support Boost (#7026). + series.options.data.forEach(function eachData(options, pIdx) { + var key, prop, val, name, point; + // In parallel coordinates chart, each data point is connected + // to a separate yAxis, conform this + if (hasParallelCoords) { + categoryAndDatetimeMap = getCategoryAndDateTimeMap(series, pointArrayMap, pIdx); + } + point = { series: mockSeries }; + series.pointClass.prototype.applyOptions.apply(point, [options]); + key = point.x; + name = series.data[pIdx] && series.data[pIdx].name; + j = 0; + // Pies, funnels, geo maps etc. use point name in X row + if (!xAxis || + series.exportKey === 'name' || + (!hasParallelCoords && xAxis && xAxis.hasNames)) { + key = name; + } + if (xTaken) { + if (xTaken[key]) { + key += '|' + pIdx; + } + xTaken[key] = true; + } + if (!rows[key]) { + // Generate the row + rows[key] = []; + // Contain the X values from one or more X axes + rows[key].xValues = []; + } + rows[key].x = point.x; + rows[key].name = name; + rows[key].xValues[xAxisIndex] = point.x; + while (j < valueCount) { + prop = pointArrayMap[j]; // y, z etc + val = point[prop]; + rows[key][i + j] = pick( + // Y axis category if present + categoryAndDatetimeMap.categoryMap[prop][val], + // datetime yAxis + categoryAndDatetimeMap.dateTimeValueAxisMap[prop] ? + time.dateFormat(csvOptions.dateFormat, val) : + null, + // linear/log yAxis + val); + j++; + } + }); + i = i + j; + } + }); + // Make a sortable array + for (x in rows) { + if (Object.hasOwnProperty.call(rows, x)) { + rowArr.push(rows[x]); + } + } + var xAxisIndex, column; + // Add computed column headers and top level headers to final row set + dataRows = multiLevelHeaders ? [topLevelColumnTitles, columnTitles] : + [columnTitles]; + i = xAxisIndices.length; + while (i--) { // Start from end to splice in + xAxisIndex = xAxisIndices[i][0]; + column = xAxisIndices[i][1]; + xAxis = xAxes[xAxisIndex]; + // Sort it by X values + rowArr.sort(function (// eslint-disable-line no-loop-func + a, b) { + return a.xValues[xAxisIndex] - b.xValues[xAxisIndex]; + }); + // Add header row + xTitle = columnHeaderFormatter(xAxis); + dataRows[0].splice(column, 0, xTitle); + if (multiLevelHeaders && dataRows[1]) { + // If using multi level headers, we just added top level header. + // Also add for sub level + dataRows[1].splice(column, 0, xTitle); + } + // Add the category column + rowArr.forEach(function (// eslint-disable-line no-loop-func + row) { + var category = row.name; + if (xAxis && !defined(category)) { + if (xAxis.dateTime) { + if (row.x instanceof Date) { + row.x = row.x.getTime(); + } + category = time.dateFormat(csvOptions.dateFormat, row.x); + } + else if (xAxis.categories) { + category = pick(xAxis.names[row.x], xAxis.categories[row.x], row.x); + } + else { + category = row.x; + } + } + // Add the X/date/category + row.splice(column, 0, category); + }); + } + dataRows = dataRows.concat(rowArr); + fireEvent(this, 'exportData', { dataRows: dataRows }); + return dataRows; + }; + /** + * Export-data module required. Returns the current chart data as a CSV string. + * + * @function Highcharts.Chart#getCSV + * + * @param {boolean} [useLocalDecimalPoint] + * Whether to use the local decimal point as detected from the browser. + * This makes it easier to export data to Excel in the same locale as the + * user is. + * + * @return {string} + * CSV representation of the data + */ + Highcharts.Chart.prototype.getCSV = function (useLocalDecimalPoint) { + var csv = '', rows = this.getDataRows(), csvOptions = this.options.exporting.csv, decimalPoint = pick(csvOptions.decimalPoint, csvOptions.itemDelimiter !== ',' && useLocalDecimalPoint ? + (1.1).toLocaleString()[1] : + '.'), + // use ';' for direct to Excel + itemDelimiter = pick(csvOptions.itemDelimiter, decimalPoint === ',' ? ';' : ','), + // '\n' isn't working with the js csv data extraction + lineDelimiter = csvOptions.lineDelimiter; + // Transform the rows to CSV + rows.forEach(function (row, i) { + var val = '', j = row.length; + while (j--) { + val = row[j]; + if (typeof val === 'string') { + val = '"' + val + '"'; + } + if (typeof val === 'number') { + if (decimalPoint !== '.') { + val = val.toString().replace('.', decimalPoint); + } + } + row[j] = val; + } + // Add the values + csv += row.join(itemDelimiter); + // Add the line delimiter + if (i < rows.length - 1) { + csv += lineDelimiter; + } + }); + return csv; + }; + /** + * Export-data module required. Build a HTML table with the chart's current + * data. + * + * @sample highcharts/export-data/viewdata/ + * View the data from the export menu + * + * @function Highcharts.Chart#getTable + * + * @param {boolean} [useLocalDecimalPoint] + * Whether to use the local decimal point as detected from the browser. + * This makes it easier to export data to Excel in the same locale as the + * user is. + * + * @return {string} + * HTML representation of the data. + * + * @fires Highcharts.Chart#event:afterGetTable + */ + Highcharts.Chart.prototype.getTable = function (useLocalDecimalPoint) { + var html = '', options = this.options, decimalPoint = useLocalDecimalPoint ? (1.1).toLocaleString()[1] : '.', useMultiLevelHeaders = pick(options.exporting.useMultiLevelHeaders, true), rows = this.getDataRows(useMultiLevelHeaders), rowLength = 0, topHeaders = useMultiLevelHeaders ? rows.shift() : null, subHeaders = rows.shift(), + // Compare two rows for equality + isRowEqual = function (row1, row2) { + var i = row1.length; + if (row2.length === i) { + while (i--) { + if (row1[i] !== row2[i]) { + return false; + } + } + } + else { + return false; + } + return true; + }, + // Get table cell HTML from value + getCellHTMLFromValue = function (tag, classes, attrs, value) { + var val = pick(value, ''), className = 'text' + (classes ? ' ' + classes : ''); + // Convert to string if number + if (typeof val === 'number') { + val = val.toString(); + if (decimalPoint === ',') { + val = val.replace('.', decimalPoint); + } + className = 'number'; + } + else if (!value) { + className = 'empty'; + } + return '<' + tag + (attrs ? ' ' + attrs : '') + + ' class="' + className + '">' + + val + ''; + }, + // Get table header markup from row data + getTableHeaderHTML = function (topheaders, subheaders, rowLength) { + var html = '', i = 0, len = rowLength || subheaders && subheaders.length, next, cur, curColspan = 0, rowspan; + // Clean up multiple table headers. Chart.getDataRows() returns two + // levels of headers when using multilevel, not merged. We need to + // merge identical headers, remove redundant headers, and keep it + // all marked up nicely. + if (useMultiLevelHeaders && + topheaders && + subheaders && + !isRowEqual(topheaders, subheaders)) { + html += ''; + for (; i < len; ++i) { + cur = topheaders[i]; + next = topheaders[i + 1]; + if (cur === next) { + ++curColspan; + } + else if (curColspan) { + // Ended colspan + // Add cur to HTML with colspan. + html += getCellHTMLFromValue('th', 'highcharts-table-topheading', 'scope="col" ' + + 'colspan="' + (curColspan + 1) + '"', cur); + curColspan = 0; + } + else { + // Cur is standalone. If it is same as sublevel, + // remove sublevel and add just toplevel. + if (cur === subheaders[i]) { + if (options.exporting.useRowspanHeaders) { + rowspan = 2; + delete subheaders[i]; + } + else { + rowspan = 1; + subheaders[i] = ''; + } + } + else { + rowspan = 1; + } + html += getCellHTMLFromValue('th', 'highcharts-table-topheading', 'scope="col"' + + (rowspan > 1 ? + ' valign="top" rowspan="' + rowspan + '"' : + ''), cur); + } + } + html += ''; + } + // Add the subheaders (the only headers if not using multilevels) + if (subheaders) { + html += ''; + for (i = 0, len = subheaders.length; i < len; ++i) { + if (typeof subheaders[i] !== 'undefined') { + html += getCellHTMLFromValue('th', null, 'scope="col"', subheaders[i]); + } + } + html += ''; + } + html += ''; + return html; + }; + // Add table caption + if (options.exporting.tableCaption !== false) { + html += ''; + } + // Find longest row + for (var i = 0, len = rows.length; i < len; ++i) { + if (rows[i].length > rowLength) { + rowLength = rows[i].length; + } + } + // Add header + html += getTableHeaderHTML(topHeaders, subHeaders, Math.max(rowLength, subHeaders.length)); + // Transform the rows to HTML + html += ''; + rows.forEach(function (row) { + html += ''; + for (var j = 0; j < rowLength; j++) { + // Make first column a header too. Especially important for + // category axes, but also might make sense for datetime? Should + // await user feedback on this. + html += getCellHTMLFromValue(j ? 'td' : 'th', null, j ? '' : 'scope="row"', row[j]); + } + html += ''; + }); + html += '
    ' + pick(options.exporting.tableCaption, (options.title.text ? + htmlencode(options.title.text) : + 'Chart')) + '
    '; + var e = { html: html }; + fireEvent(this, 'afterGetTable', e); + return e.html; + }; + /** + * Get a blob object from content, if blob is supported + * + * @private + * @param {string} content + * The content to create the blob from. + * @param {string} type + * The type of the content. + * @return {string|undefined} + * The blob object, or undefined if not supported. + */ + function getBlobFromContent(content, type) { + var nav = win.navigator, webKit = (nav.userAgent.indexOf('WebKit') > -1 && + nav.userAgent.indexOf('Chrome') < 0), domurl = win.URL || win.webkitURL || win; + try { + // MS specific + if (nav.msSaveOrOpenBlob && win.MSBlobBuilder) { + var blob = new win.MSBlobBuilder(); + blob.append(content); + return blob.getBlob('image/svg+xml'); + } + // Safari requires data URI since it doesn't allow navigation to blob + // URLs. + if (!webKit) { + return domurl.createObjectURL(new win.Blob(['\uFEFF' + content], // #7084 + { type: type })); + } + } + catch (e) { + // Ignore + } + } + /** + * Generates a data URL of CSV for local download in the browser. This is the + * default action for a click on the 'Download CSV' button. + * + * See {@link Highcharts.Chart#getCSV} to get the CSV data itself. + * + * @function Highcharts.Chart#downloadCSV + * + * @requires modules/exporting + */ + Highcharts.Chart.prototype.downloadCSV = function () { + var csv = this.getCSV(true); + downloadURL(getBlobFromContent(csv, 'text/csv') || + 'data:text/csv,\uFEFF' + encodeURIComponent(csv), this.getFilename() + '.csv'); + }; + /** + * Generates a data URL of an XLS document for local download in the browser. + * This is the default action for a click on the 'Download XLS' button. + * + * See {@link Highcharts.Chart#getTable} to get the table data itself. + * + * @function Highcharts.Chart#downloadXLS + * + * @requires modules/exporting + */ + Highcharts.Chart.prototype.downloadXLS = function () { + var uri = 'data:application/vnd.ms-excel;base64,', template = '' + + '' + + '' + + '' + + '' + + '' + + this.getTable(true) + + '', base64 = function (s) { + return win.btoa(unescape(encodeURIComponent(s))); // #50 + }; + downloadURL(getBlobFromContent(template, 'application/vnd.ms-excel') || + uri + base64(template), this.getFilename() + '.xls'); + }; + /** + * Export-data module required. View the data in a table below the chart. + * + * @function Highcharts.Chart#viewData + * + * @fires Highcharts.Chart#event:afterViewData + */ + Highcharts.Chart.prototype.viewData = function () { + if (!this.dataTableDiv) { + this.dataTableDiv = doc.createElement('div'); + this.dataTableDiv.className = 'highcharts-data-table'; + // Insert after the chart container + this.renderTo.parentNode.insertBefore(this.dataTableDiv, this.renderTo.nextSibling); + } + this.dataTableDiv.innerHTML = this.getTable(); + fireEvent(this, 'afterViewData', this.dataTableDiv); + }; + // Add "Download CSV" to the exporting menu. + var exportingOptions = Highcharts.getOptions().exporting; + if (exportingOptions) { + extend(exportingOptions.menuItemDefinitions, { + downloadCSV: { + textKey: 'downloadCSV', + onclick: function () { + this.downloadCSV(); + } + }, + downloadXLS: { + textKey: 'downloadXLS', + onclick: function () { + this.downloadXLS(); + } + }, + viewData: { + textKey: 'viewData', + onclick: function () { + this.viewData(); + } + } + }); + if (exportingOptions.buttons) { + exportingOptions.buttons.contextButton.menuItems.push('separator', 'downloadCSV', 'downloadXLS', 'viewData'); + } + } + // Series specific + if (seriesTypes.map) { + seriesTypes.map.prototype.exportKey = 'name'; + } + if (seriesTypes.mapbubble) { + seriesTypes.mapbubble.prototype.exportKey = 'name'; + } + if (seriesTypes.treemap) { + seriesTypes.treemap.prototype.exportKey = 'name'; + } + + }); + _registerModule(_modules, 'masters/modules/export-data.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/exporting.js b/librerias/gantt/code/modules/exporting.js new file mode 100644 index 0000000..106cbd9 --- /dev/null +++ b/librerias/gantt/code/modules/exporting.js @@ -0,0 +1,43 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Exporting module + + (c) 2010-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(g){"object"===typeof module&&module.exports?(g["default"]=g,module.exports=g):"function"===typeof define&&define.amd?define("highcharts/modules/exporting",["highcharts"],function(n){g(n);g.Highcharts=n;return g}):g("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(g){function n(e,f,g,l){e.hasOwnProperty(f)||(e[f]=l.apply(null,g))}g=g?g._modules:{};n(g,"modules/full-screen.src.js",[g["parts/Globals.js"],g["parts/Utilities.js"]],function(e,f){var g=f.addEvent;f=e.Chart;var l=function(){function e(k){this.chart= +k;this.isOpen=!1;k=k.renderTo;this.browserProps||("function"===typeof k.requestFullscreen?this.browserProps={fullscreenChange:"fullscreenchange",requestFullscreen:"requestFullscreen",exitFullscreen:"exitFullscreen"}:k.mozRequestFullScreen?this.browserProps={fullscreenChange:"mozfullscreenchange",requestFullscreen:"mozRequestFullScreen",exitFullscreen:"mozCancelFullScreen"}:k.webkitRequestFullScreen?this.browserProps={fullscreenChange:"webkitfullscreenchange",requestFullscreen:"webkitRequestFullScreen", +exitFullscreen:"webkitExitFullscreen"}:k.msRequestFullscreen&&(this.browserProps={fullscreenChange:"MSFullscreenChange",requestFullscreen:"msRequestFullscreen",exitFullscreen:"msExitFullscreen"}))}e.prototype.close=function(){var k=this.chart;if(this.isOpen&&this.browserProps&&k.container.ownerDocument instanceof Document)k.container.ownerDocument[this.browserProps.exitFullscreen]();this.unbindFullscreenEvent&&this.unbindFullscreenEvent();this.isOpen=!1;this.setButtonText()};e.prototype.open=function(){var k= +this,e=k.chart;if(k.browserProps){k.unbindFullscreenEvent=g(e.container.ownerDocument,k.browserProps.fullscreenChange,function(){k.isOpen?(k.isOpen=!1,k.close()):(k.isOpen=!0,k.setButtonText())});var f=e.renderTo[k.browserProps.requestFullscreen]();if(f)f["catch"](function(){alert("Full screen is not supported inside a frame.")});g(e,"destroy",k.unbindFullscreenEvent)}};e.prototype.setButtonText=function(){var e,f=this.chart,g=f.exportDivElements,l=f.options.exporting,q=null===(e=null===l||void 0=== +l?void 0:l.buttons)||void 0===e?void 0:e.contextButton.menuItems;e=f.options.lang;(null===l||void 0===l?0:l.menuItemDefinitions)&&(null===e||void 0===e?0:e.exitFullscreen)&&e.viewFullscreen&&q&&g&&g.length&&(g[q.indexOf("viewFullscreen")].innerHTML=this.isOpen?e.exitFullscreen:l.menuItemDefinitions.viewFullscreen.text||e.viewFullscreen)};e.prototype.toggle=function(){this.isOpen?this.close():this.open()};return e}();e.Fullscreen=l;g(f,"beforeRender",function(){this.fullscreen=new e.Fullscreen(this)}); +return e.Fullscreen});n(g,"mixins/navigation.js",[],function(){return{initUpdate:function(e){e.navigation||(e.navigation={updates:[],update:function(e,g){this.updates.forEach(function(f){f.update.call(f.context,e,g)})}})},addUpdate:function(e,f){f.navigation||this.initUpdate(f);f.navigation.updates.push({update:e,context:f})}}});n(g,"modules/exporting.src.js",[g["parts/Globals.js"],g["parts/Utilities.js"],g["mixins/navigation.js"]],function(e,f,g){var l=f.addEvent,q=f.css,k=f.createElement,n=f.discardElement, +w=f.extend,I=f.find,A=f.fireEvent,J=f.isObject,r=f.merge,E=f.objectEach,t=f.pick,K=f.removeEvent,L=f.uniqueKey,v=e.defaultOptions,x=e.doc,B=e.Chart,M=e.isTouchDevice,y=e.win,G=y.navigator.userAgent,F=e.SVGRenderer,H=e.Renderer.prototype.symbols,N=/Edge\/|Trident\/|MSIE /.test(G),O=/firefox/i.test(G);w(v.lang,{viewFullscreen:"View in full screen",exitFullscreen:"Exit from full screen",printChart:"Print chart",downloadPNG:"Download PNG image",downloadJPEG:"Download JPEG image",downloadPDF:"Download PDF document", +downloadSVG:"Download SVG vector image",contextButtonTitle:"Chart context menu"});v.navigation||(v.navigation={});r(!0,v.navigation,{buttonOptions:{theme:{},symbolSize:14,symbolX:12.5,symbolY:10.5,align:"right",buttonSpacing:3,height:22,verticalAlign:"top",width:24}});r(!0,v.navigation,{menuStyle:{border:"1px solid #999999",background:"#ffffff",padding:"5px 0"},menuItemStyle:{padding:"0.5em 1em",color:"#333333",background:"none",fontSize:M?"14px":"11px",transition:"background 250ms, color 250ms"}, +menuItemHoverStyle:{background:"#335cad",color:"#ffffff"},buttonOptions:{symbolFill:"#666666",symbolStroke:"#666666",symbolStrokeWidth:3,theme:{padding:5}}});v.exporting={type:"image/png",url:"https://export.highcharts.com/",printMaxWidth:780,scale:2,buttons:{contextButton:{className:"highcharts-contextbutton",menuClassName:"highcharts-contextmenu",symbol:"menu",titleKey:"contextButtonTitle",menuItems:"viewFullscreen printChart separator downloadPNG downloadJPEG downloadPDF downloadSVG".split(" ")}}, +menuItemDefinitions:{viewFullscreen:{textKey:"viewFullscreen",onclick:function(){this.fullscreen.toggle()}},printChart:{textKey:"printChart",onclick:function(){this.print()}},separator:{separator:!0},downloadPNG:{textKey:"downloadPNG",onclick:function(){this.exportChart()}},downloadJPEG:{textKey:"downloadJPEG",onclick:function(){this.exportChart({type:"image/jpeg"})}},downloadPDF:{textKey:"downloadPDF",onclick:function(){this.exportChart({type:"application/pdf"})}},downloadSVG:{textKey:"downloadSVG", +onclick:function(){this.exportChart({type:"image/svg+xml"})}}}};e.post=function(a,b,c){var d=k("form",r({method:"post",action:a,enctype:"multipart/form-data"},c),{display:"none"},x.body);E(b,function(a,b){k("input",{type:"hidden",name:b,value:a},null,d)});d.submit();n(d)};e.isSafari&&e.win.matchMedia("print").addListener(function(a){e.printingChart&&(a.matches?e.printingChart.beforePrint():e.printingChart.afterPrint())});w(B.prototype,{sanitizeSVG:function(a,b){var c=a.indexOf("")+6,d=a.substr(c); +a=a.substr(0,c);b&&b.exporting&&b.exporting.allowHTML&&d&&(d=''+d+"",a=a.replace("",d+""));a=a.replace(/zIndex="[^"]+"/g,"").replace(/symbolName="[^"]+"/g,"").replace(/jQuery[0-9]+="[^"]+"/g,"").replace(/url\(("|")(.*?)("|");?\)/g,"url($2)").replace(/url\([^#]+#/g,"url(#").replace(/]+(>|$)/g,"").replace(/[\s_]+/g,"-").replace(/[^a-z0-9\-]/g,"").replace(/^[\-]+/g,"").replace(/[\-]+/g,"-").substr(0,24).replace(/[\-]+$/g,""));if(!b||5>b.length)b="chart";return b},exportChart:function(a,b){b=this.getSVGForExport(a,b);a=r(this.options.exporting,a);e.post(a.url,{filename:a.filename?a.filename.replace(/\//g,"-"):this.getFilename(),type:a.type,width:a.width||0, +scale:a.scale,svg:b},a.formAttributes)},moveContainers:function(a){(this.fixedDiv?[this.fixedDiv,this.scrollingContainer]:[this.container]).forEach(function(b){a.appendChild(b)})},beforePrint:function(){var a=x.body,b=this.options.exporting.printMaxWidth,c={childNodes:a.childNodes,origDisplay:[],resetParams:void 0};this.isPrinting=!0;this.pointer.reset(null,0);A(this,"beforePrint");b&&this.chartWidth>b&&(c.resetParams=[this.options.chart.width,void 0,!1],this.setSize(b,void 0,!1));[].forEach.call(c.childNodes, +function(a,b){1===a.nodeType&&(c.origDisplay[b]=a.style.display,a.style.display="none")});this.moveContainers(a);this.printReverseInfo=c},afterPrint:function(){if(this.printReverseInfo){var a=this.printReverseInfo.childNodes,b=this.printReverseInfo.origDisplay,c=this.printReverseInfo.resetParams;this.moveContainers(this.renderTo);[].forEach.call(a,function(a,c){1===a.nodeType&&(a.style.display=b[c]||"")});this.isPrinting=!1;c&&this.setSize.apply(this,c);delete this.printReverseInfo;delete e.printingChart; +A(this,"afterPrint")}},print:function(){var a=this;a.isPrinting||(e.printingChart=a,e.isSafari||a.beforePrint(),setTimeout(function(){y.focus();y.print();e.isSafari||setTimeout(function(){a.afterPrint()},1E3)},1))},contextMenu:function(a,b,c,d,e,g,u){var h=this,D=h.options.navigation,r=h.chartWidth,z=h.chartHeight,p="cache-"+a,m=h[p],C=Math.max(e,g);if(!m){h.exportContextMenu=h[p]=m=k("div",{className:a},{position:"absolute",zIndex:1E3,padding:C+"px",pointerEvents:"auto"},h.fixedDiv||h.container); +var n=k("ul",{className:"highcharts-menu"},{listStyle:"none",margin:0,padding:0},m);h.styledMode||q(n,w({MozBoxShadow:"3px 3px 10px #888",WebkitBoxShadow:"3px 3px 10px #888",boxShadow:"3px 3px 10px #888"},D.menuStyle));m.hideMenu=function(){q(m,{display:"none"});u&&u.setState(0);h.openMenu=!1;q(h.renderTo,{overflow:"hidden"});f.clearTimeout(m.hideTimer);A(h,"exportMenuHidden")};h.exportEvents.push(l(m,"mouseleave",function(){m.hideTimer=y.setTimeout(m.hideMenu,500)}),l(m,"mouseenter",function(){f.clearTimeout(m.hideTimer)}), +l(x,"mouseup",function(b){h.pointer.inClass(b.target,a)||m.hideMenu()}),l(m,"click",function(){h.openMenu&&m.hideMenu()}));b.forEach(function(a){"string"===typeof a&&(a=h.options.exporting.menuItemDefinitions[a]);if(J(a,!0)){if(a.separator)var b=k("hr",null,null,n);else b=k("li",{className:"highcharts-menu-item",onclick:function(b){b&&b.stopPropagation();m.hideMenu();a.onclick&&a.onclick.apply(h,arguments)},innerHTML:a.text||h.options.lang[a.textKey]},null,n),h.styledMode||(b.onmouseover=function(){q(this, +D.menuItemHoverStyle)},b.onmouseout=function(){q(this,D.menuItemStyle)},q(b,w({cursor:"pointer"},D.menuItemStyle)));h.exportDivElements.push(b)}});h.exportDivElements.push(n,m);h.exportMenuWidth=m.offsetWidth;h.exportMenuHeight=m.offsetHeight}b={display:"block"};c+h.exportMenuWidth>r?b.right=r-c-e-C+"px":b.left=c-C+"px";d+g+h.exportMenuHeight>z&&"top"!==u.alignOptions.verticalAlign?b.bottom=z-d-C+"px":b.top=d+g-C+"px";q(m,b);q(h.renderTo,{overflow:""});h.openMenu=!0;A(h,"exportMenuShown")},addButton:function(a){var b= +this,c=b.renderer,d=r(b.options.navigation.buttonOptions,a),e=d.onclick,f=d.menuItems,g=d.symbolSize||12;b.btnCount||(b.btnCount=0);b.exportDivElements||(b.exportDivElements=[],b.exportSVGElements=[]);if(!1!==d.enabled){var h=d.theme,k=h.states,l=k&&k.hover;k=k&&k.select;var z;b.styledMode||(h.fill=t(h.fill,"#ffffff"),h.stroke=t(h.stroke,"none"));delete h.states;e?z=function(a){a&&a.stopPropagation();e.call(b,a)}:f&&(z=function(a){a&&a.stopPropagation();b.contextMenu(p.menuClassName,f,p.translateX, +p.translateY,p.width,p.height,p);p.setState(2)});d.text&&d.symbol?h.paddingLeft=t(h.paddingLeft,25):d.text||w(h,{width:d.width,height:d.height,padding:0});b.styledMode||(h["stroke-linecap"]="round",h.fill=t(h.fill,"#ffffff"),h.stroke=t(h.stroke,"none"));var p=c.button(d.text,0,0,z,h,l,k).addClass(a.className).attr({title:t(b.options.lang[d._titleKey||d.titleKey],"")});p.menuClassName=a.menuClassName||"highcharts-menu-"+b.btnCount++;if(d.symbol){var m=c.symbol(d.symbol,d.symbolX-g/2,d.symbolY-g/2, +g,g,{width:g,height:g}).addClass("highcharts-button-symbol").attr({zIndex:1}).add(p);b.styledMode||m.attr({stroke:d.symbolStroke,fill:d.symbolFill,"stroke-width":d.symbolStrokeWidth||1})}p.add(b.exportingGroup).align(w(d,{width:p.width,x:t(d.x,b.buttonOffset)}),!0,"spacingBox");b.buttonOffset+=(p.width+d.buttonSpacing)*("right"===d.align?-1:1);b.exportSVGElements.push(p,m)}},destroyExport:function(a){var b=a?a.target:this;a=b.exportSVGElements;var c=b.exportDivElements,d=b.exportEvents,e;a&&(a.forEach(function(a, +d){a&&(a.onclick=a.ontouchstart=null,e="cache-"+a.menuClassName,b[e]&&delete b[e],b.exportSVGElements[d]=a.destroy())}),a.length=0);b.exportingGroup&&(b.exportingGroup.destroy(),delete b.exportingGroup);c&&(c.forEach(function(a,d){f.clearTimeout(a.hideTimer);K(a,"mouseleave");b.exportDivElements[d]=a.onmouseout=a.onmouseover=a.ontouchstart=a.onclick=null;n(a)}),c.length=0);d&&(d.forEach(function(a){a()}),d.length=0)}});F.prototype.inlineToAttributes="fill stroke strokeLinecap strokeLinejoin strokeWidth textAnchor x y".split(" "); +F.prototype.inlineBlacklist=[/-/,/^(clipPath|cssText|d|height|width)$/,/^font$/,/[lL]ogical(Width|Height)$/,/perspective/,/TapHighlightColor/,/^transition/,/^length$/];F.prototype.unstyledElements=["clipPath","defs","desc"];B.prototype.inlineStyles=function(){function a(a){return a.replace(/([A-Z])/g,function(a,b){return"-"+b.toLowerCase()})}function b(c){function p(b,f){n=q=!1;if(g){for(t=g.length;t--&&!q;)q=g[t].test(f);n=!q}"transform"===f&&"none"===b&&(n=!0);for(t=e.length;t--&&!n;)n=e[t].test(f)|| +"function"===typeof b;n||w[f]===b&&"svg"!==c.nodeName||h[c.nodeName][f]===b||(-1!==d.indexOf(f)?c.setAttribute(a(f),b):m+=a(f)+":"+b+";")}var m="",n,q,t;if(1===c.nodeType&&-1===f.indexOf(c.nodeName)){var u=y.getComputedStyle(c,null);var w="svg"===c.nodeName?{}:y.getComputedStyle(c.parentNode,null);if(!h[c.nodeName]){k=l.getElementsByTagName("svg")[0];var v=l.createElementNS(c.namespaceURI,c.nodeName);k.appendChild(v);h[c.nodeName]=r(y.getComputedStyle(v,null));"text"===c.nodeName&&delete h.text.fill; +k.removeChild(v)}if(O||N)for(var x in u)p(u[x],x);else E(u,p);m&&(u=c.getAttribute("style"),c.setAttribute("style",(u?u+";":"")+m));"svg"===c.nodeName&&c.setAttribute("stroke-width","1px");"text"!==c.nodeName&&[].forEach.call(c.children||c.childNodes,b)}}var c=this.renderer,d=c.inlineToAttributes,e=c.inlineBlacklist,g=c.inlineWhitelist,f=c.unstyledElements,h={},k;c=x.createElement("iframe");q(c,{width:"1px",height:"1px",visibility:"hidden"});x.body.appendChild(c);var l=c.contentWindow.document;l.open(); +l.write('');l.close();b(this.container.querySelector("svg"));k.parentNode.removeChild(k)};H.menu=function(a,b,c,d){return[["M",a,b+2.5],["L",a+c,b+2.5],["M",a,b+d/2+.5],["L",a+c,b+d/2+.5],["M",a,b+d-1.5],["L",a+c,b+d-1.5]]};H.menuball=function(a,b,c,d){a=[];d=d/3-2;return a=a.concat(this.circle(c-d,b,d,d),this.circle(c-d,b+d+4,d,d),this.circle(c-d,b+2*(d+4),d,d))};B.prototype.renderExporting=function(){var a=this,b=a.options.exporting,c=b.buttons,d=a.isDirtyExporting|| +!a.exportSVGElements;a.buttonOffset=0;a.isDirtyExporting&&a.destroyExport();d&&!1!==b.enabled&&(a.exportEvents=[],a.exportingGroup=a.exportingGroup||a.renderer.g("exporting-group").attr({zIndex:3}).add(),E(c,function(b){a.addButton(b)}),a.isDirtyExporting=!1);l(a,"destroy",a.destroyExport)};l(B,"init",function(){var a=this;a.exporting={update:function(b,c){a.isDirtyExporting=!0;r(!0,a.options.exporting,b);t(c,!0)&&a.redraw()}};g.addUpdate(function(b,c){a.isDirtyExporting=!0;r(!0,a.options.navigation, +b);t(c,!0)&&a.redraw()},a)});B.prototype.callbacks.push(function(a){a.renderExporting();l(a,"redraw",a.renderExporting)})});n(g,"masters/modules/exporting.src.js",[],function(){})}); +//# sourceMappingURL=exporting.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/exporting.js.map b/librerias/gantt/code/modules/exporting.js.map new file mode 100644 index 0000000..3471cfe --- /dev/null +++ b/librerias/gantt/code/modules/exporting.js.map @@ -0,0 +1 @@ +{"version":3,"file":"exporting.js.map","lineCount":42,"mappings":"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","sources":["exporting.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","U","addEvent","Chart","Fullscreen","chart","isOpen","container","renderTo","browserProps","requestFullscreen","fullscreenChange","exitFullscreen","mozRequestFullScreen","webkitRequestFullScreen","msRequestFullscreen","prototype","close","Fullscreen.prototype.close","fullscreen","ownerDocument","Document","unbindFullscreenEvent","setButtonText","open","Fullscreen.prototype.open","promise","alert","Fullscreen.prototype.setButtonText","_a","exportDivElements","exportingOptions","options","exporting","menuItems","buttons","contextButton","lang","menuItemDefinitions","viewFullscreen","length","indexOf","innerHTML","text","toggle","Fullscreen.prototype.toggle","chartNavigation","initUpdate","navigation","updates","update","redraw","forEach","updateConfig","call","context","addUpdate","push","chartNavigationMixin","css","createElement","discardElement","extend","find","fireEvent","isObject","merge","objectEach","pick","removeEvent","uniqueKey","defaultOptions","doc","isTouchDevice","win","userAgent","navigator","SVGRenderer","symbols","Renderer","isMSBrowser","test","isFirefoxBrowser","printChart","downloadPNG","downloadJPEG","downloadPDF","downloadSVG","contextButtonTitle","buttonOptions","theme","symbolSize","symbolX","symbolY","align","buttonSpacing","height","verticalAlign","width","menuStyle","border","background","padding","menuItemStyle","color","fontSize","transition","menuItemHoverStyle","symbolFill","symbolStroke","symbolStrokeWidth","type","url","printMaxWidth","scale","className","menuClassName","symbol","titleKey","textKey","onclick","print","separator","exportChart","post","H.post","data","formAttributes","form","method","action","enctype","display","body","val","name","value","submit","isSafari","matchMedia","addListener","mqlEvent","printingChart","matches","beforePrint","afterPrint","sanitizeSVG","svg","split","html","substr","allowHTML","replace","ieSanitizeSVG","getChartHTML","styledMode","inlineStyles","getSVG","chartOptions","seriesOptions","plotOptions","userOptions","time","sandbox","position","top","chartWidth","chartHeight","cssWidth","style","cssHeight","sourceWidth","parseInt","isGantt","sourceHeight","animation","forExport","renderer","enabled","series","serie","enableMouseTracking","showCheckbox","visible","isInternal","axes","axis","internalKey","chartCopy","callback","coll","collOptions","axisCopy","copy","extremes","getExtremes","userMin","userMax","min","max","setExtremes","destroy","getSVGForExport","chartExportingOptions","borderRadius","getFilename","s","title","filename","toLowerCase","moveContainers","moveTo","fixedDiv","scrollingContainer","div","appendChild","printReverseInfo","childNodes","origDisplay","resetParams","isPrinting","pointer","reset","setSize","node","i","nodeType","setTimeout","focus","contextMenu","items","x","y","button","navOptions","cacheName","menu","menuPadding","Math","exportContextMenu","zIndex","pointerEvents","innerMenu","listStyle","margin","MozBoxShadow","WebkitBoxShadow","boxShadow","hideMenu","menu.hideMenu","setState","openMenu","overflow","clearTimeout","hideTimer","exportEvents","e","inClass","target","item","element","stopPropagation","arguments","onmouseover","element.onmouseover","onmouseout","element.onmouseout","cursor","exportMenuWidth","offsetWidth","exportMenuHeight","offsetHeight","right","left","alignOptions","bottom","addButton","btnOptions","btnCount","exportSVGElements","attr","states","hover","select","fill","stroke","translateX","translateY","paddingLeft","addClass","_titleKey","add","exportingGroup","buttonOffset","destroyExport","elem","ontouchstart","unbind","inlineToAttributes","inlineBlacklist","unstyledElements","Chart.prototype.inlineStyles","hyphenate","prop","a","b","recurse","filterStyles","blacklisted","whitelisted","whitelist","blacklist","parentStyles","nodeName","defaultStyles","setAttribute","cssText","styles","getComputedStyle","parentNode","dummySVG","iframeDoc","getElementsByTagName","dummy","createElementNS","namespaceURI","removeChild","p","styleAttr","getAttribute","children","inlineWhitelist","iframe","visibility","contentWindow","document","write","querySelector","symbols.menu","arr","menuball","symbols.menuball","h","concat","circle","renderExporting","Chart.prototype.renderExporting","isDirty","isDirtyExporting","g","callbacks"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/exporting.src.js b/librerias/gantt/code/modules/exporting.src.js new file mode 100644 index 0000000..2bbd5c0 --- /dev/null +++ b/librerias/gantt/code/modules/exporting.src.js @@ -0,0 +1,2290 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * Exporting module + * + * (c) 2010-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/exporting', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'modules/full-screen.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * (c) 2009-2020 Rafal Sebestjanski + * + * Full screen for Highcharts + * + * License: www.highcharts.com/license + */ + var addEvent = U.addEvent; + var Chart = H.Chart; + /** + * The module allows user to enable display chart in full screen mode. + * Used in StockTools too. + * Based on default solutions in browsers. + * + */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Handles displaying chart's container in the fullscreen mode. + * + * @class + * @name Highcharts.Fullscreen + * @hideconstructor + * @requires modules/full-screen + */ + var Fullscreen = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Fullscreen(chart) { + /** + * Chart managed by the fullscreen controller. + * @name Highcharts.Fullscreen#chart + * @type {Highcharts.Chart} + */ + this.chart = chart; + /** + * The flag is set to `true` when the chart is displayed in + * the fullscreen mode. + * + * @name Highcharts.Fullscreen#isOpen + * @type {boolean|undefined} + * @since 8.0.1 + */ + this.isOpen = false; + var container = chart.renderTo; + // Hold event and methods available only for a current browser. + if (!this.browserProps) { + if (typeof container.requestFullscreen === 'function') { + this.browserProps = { + fullscreenChange: 'fullscreenchange', + requestFullscreen: 'requestFullscreen', + exitFullscreen: 'exitFullscreen' + }; + } + else if (container.mozRequestFullScreen) { + this.browserProps = { + fullscreenChange: 'mozfullscreenchange', + requestFullscreen: 'mozRequestFullScreen', + exitFullscreen: 'mozCancelFullScreen' + }; + } + else if (container.webkitRequestFullScreen) { + this.browserProps = { + fullscreenChange: 'webkitfullscreenchange', + requestFullscreen: 'webkitRequestFullScreen', + exitFullscreen: 'webkitExitFullscreen' + }; + } + else if (container.msRequestFullscreen) { + this.browserProps = { + fullscreenChange: 'MSFullscreenChange', + requestFullscreen: 'msRequestFullscreen', + exitFullscreen: 'msExitFullscreen' + }; + } + } + } + /* * + * + * Functions + * + * */ + /** + * Stops displaying the chart in fullscreen mode. + * Exporting module required. + * + * @since 8.0.1 + * + * @function Highcharts.Fullscreen#close + * @return {void} + * @requires modules/full-screen + */ + Fullscreen.prototype.close = function () { + var fullscreen = this, chart = fullscreen.chart; + // Don't fire exitFullscreen() when user exited using 'Escape' button. + if (fullscreen.isOpen && + fullscreen.browserProps && + chart.container.ownerDocument instanceof Document) { + chart.container.ownerDocument[fullscreen.browserProps.exitFullscreen](); + } + // Unbind event as it's necessary only before exiting from fullscreen. + if (fullscreen.unbindFullscreenEvent) { + fullscreen.unbindFullscreenEvent(); + } + fullscreen.isOpen = false; + fullscreen.setButtonText(); + }; + /** + * Displays the chart in fullscreen mode. + * When fired customly by user before exporting context button is created, + * button's text will not be replaced - it's on the user side. + * Exporting module required. + * + * @since 8.0.1 + * + * @function Highcharts.Fullscreen#open + * @return {void} + * @requires modules/full-screen + */ + Fullscreen.prototype.open = function () { + var fullscreen = this, chart = fullscreen.chart; + // Handle exitFullscreen() method when user clicks 'Escape' button. + if (fullscreen.browserProps) { + fullscreen.unbindFullscreenEvent = addEvent(chart.container.ownerDocument, // chart's document + fullscreen.browserProps.fullscreenChange, function () { + // Handle lack of async of browser's fullScreenChange event. + if (fullscreen.isOpen) { + fullscreen.isOpen = false; + fullscreen.close(); + } + else { + fullscreen.isOpen = true; + fullscreen.setButtonText(); + } + }); + var promise = chart.renderTo[fullscreen.browserProps.requestFullscreen](); + if (promise) { + // No dot notation because of IE8 compatibility + promise['catch'](function () { + alert(// eslint-disable-line no-alert + 'Full screen is not supported inside a frame.'); + }); + } + addEvent(chart, 'destroy', fullscreen.unbindFullscreenEvent); + } + }; + /** + * Replaces the exporting context button's text when toogling the + * fullscreen mode. + * + * @private + * + * @since 8.0.1 + * + * @requires modules/full-screen + * @return {void} + */ + Fullscreen.prototype.setButtonText = function () { + var _a; + var chart = this.chart, exportDivElements = chart.exportDivElements, exportingOptions = chart.options.exporting, menuItems = (_a = exportingOptions === null || exportingOptions === void 0 ? void 0 : exportingOptions.buttons) === null || _a === void 0 ? void 0 : _a.contextButton.menuItems, lang = chart.options.lang; + if ((exportingOptions === null || exportingOptions === void 0 ? void 0 : exportingOptions.menuItemDefinitions) && (lang === null || lang === void 0 ? void 0 : lang.exitFullscreen) && + lang.viewFullscreen && + menuItems && + exportDivElements && + exportDivElements.length) { + exportDivElements[menuItems.indexOf('viewFullscreen')] + .innerHTML = !this.isOpen ? + (exportingOptions.menuItemDefinitions.viewFullscreen.text || + lang.viewFullscreen) : lang.exitFullscreen; + } + }; + /** + * Toggles displaying the chart in fullscreen mode. + * By default, when the exporting module is enabled, a context button with + * a drop down menu in the upper right corner accesses this function. + * Exporting module required. + * + * @since 8.0.1 + * + * @sample highcharts/members/chart-togglefullscreen/ + * Toggle fullscreen mode from a HTML button + * + * @function Highcharts.Fullscreen#toggle + * @requires modules/full-screen + */ + Fullscreen.prototype.toggle = function () { + var fullscreen = this; + if (!fullscreen.isOpen) { + fullscreen.open(); + } + else { + fullscreen.close(); + } + }; + return Fullscreen; + }()); + H.Fullscreen = Fullscreen; + // Initialize fullscreen + addEvent(Chart, 'beforeRender', function () { + /** + * @name Highcharts.Chart#fullscreen + * @type {Highcharts.Fullscreen} + * @requires modules/full-screen + */ + this.fullscreen = new H.Fullscreen(this); + }); + + return H.Fullscreen; + }); + _registerModule(_modules, 'mixins/navigation.js', [], function () { + /** + * + * (c) 2010-2018 Paweł Fus + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var chartNavigation = { + /** + * Initializes `chart.navigation` object which delegates `update()` methods + * to all other common classes (used in exporting and navigationBindings). + * + * @private + * @param {Highcharts.Chart} chart + * The chart instance. + * @return {void} + */ + initUpdate: function (chart) { + if (!chart.navigation) { + chart.navigation = { + updates: [], + update: function (options, redraw) { + this.updates.forEach(function (updateConfig) { + updateConfig.update.call(updateConfig.context, options, redraw); + }); + } + }; + } + }, + /** + * Registers an `update()` method in the `chart.navigation` object. + * + * @private + * @param {Highcharts.ChartNavigationUpdateFunction} update + * The `update()` method that will be called in `chart.update()`. + * @param {Highcharts.Chart} chart + * The chart instance. `update()` will use that as a context + * (`this`). + * @return {void} + */ + addUpdate: function (update, chart) { + if (!chart.navigation) { + this.initUpdate(chart); + } + chart.navigation.updates.push({ + update: update, + context: chart + }); + } + }; + + return chartNavigation; + }); + _registerModule(_modules, 'modules/exporting.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['mixins/navigation.js']], function (H, U, chartNavigationMixin) { + /* * + * + * Exporting module + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Gets fired after a chart is printed through the context menu item or the + * Chart.print method. + * + * @callback Highcharts.ExportingAfterPrintCallbackFunction + * + * @param {Highcharts.Chart} chart + * The chart on which the event occured. + * + * @param {global.Event} event + * The event that occured. + */ + /** + * Gets fired before a chart is printed through the context menu item or the + * Chart.print method. + * + * @callback Highcharts.ExportingBeforePrintCallbackFunction + * + * @param {Highcharts.Chart} chart + * The chart on which the event occured. + * + * @param {global.Event} event + * The event that occured. + */ + /** + * Function to call if the offline-exporting module fails to export a chart on + * the client side. + * + * @callback Highcharts.ExportingErrorCallbackFunction + * + * @param {Highcharts.ExportingOptions} options + * The exporting options. + * + * @param {global.Error} err + * The error from the module. + */ + /** + * Definition for a menu item in the context menu. + * + * @interface Highcharts.ExportingMenuObject + */ /** + * The text for the menu item. + * + * @name Highcharts.ExportingMenuObject#text + * @type {string|undefined} + */ /** + * If internationalization is required, the key to a language string. + * + * @name Highcharts.ExportingMenuObject#textKey + * @type {string|undefined} + */ /** + * The click handler for the menu item. + * + * @name Highcharts.ExportingMenuObject#onclick + * @type {Highcharts.EventCallbackFunction|undefined} + */ /** + * Indicates a separator line instead of an item. + * + * @name Highcharts.ExportingMenuObject#separator + * @type {boolean|undefined} + */ + /** + * Possible MIME types for exporting. + * + * @typedef {"image/png"|"image/jpeg"|"application/pdf"|"image/svg+xml"} Highcharts.ExportingMimeTypeValue + */ + var addEvent = U.addEvent, css = U.css, createElement = U.createElement, discardElement = U.discardElement, extend = U.extend, find = U.find, fireEvent = U.fireEvent, isObject = U.isObject, merge = U.merge, objectEach = U.objectEach, pick = U.pick, removeEvent = U.removeEvent, uniqueKey = U.uniqueKey; + // create shortcuts + var defaultOptions = H.defaultOptions, doc = H.doc, Chart = H.Chart, isTouchDevice = H.isTouchDevice, win = H.win, userAgent = win.navigator.userAgent, SVGRenderer = H.SVGRenderer, symbols = H.Renderer.prototype.symbols, isMSBrowser = /Edge\/|Trident\/|MSIE /.test(userAgent), isFirefoxBrowser = /firefox/i.test(userAgent); + // Add language + extend(defaultOptions.lang + /** + * @optionparent lang + */ + , { + /** + * Exporting module only. The text for the menu item to view the chart + * in full screen. + * + * @since 8.0.1 + * + * @private + */ + viewFullscreen: 'View in full screen', + /** + * Exporting module only. The text for the menu item to exit the chart + * from full screen. + * + * @since 8.0.1 + * + * @private + */ + exitFullscreen: 'Exit from full screen', + /** + * Exporting module only. The text for the menu item to print the chart. + * + * @since 3.0.1 + * @requires modules/exporting + * + * @private + */ + printChart: 'Print chart', + /** + * Exporting module only. The text for the PNG download menu item. + * + * @since 2.0 + * @requires modules/exporting + * + * @private + */ + downloadPNG: 'Download PNG image', + /** + * Exporting module only. The text for the JPEG download menu item. + * + * @since 2.0 + * @requires modules/exporting + * + * @private + */ + downloadJPEG: 'Download JPEG image', + /** + * Exporting module only. The text for the PDF download menu item. + * + * @since 2.0 + * @requires modules/exporting + * + * @private + */ + downloadPDF: 'Download PDF document', + /** + * Exporting module only. The text for the SVG download menu item. + * + * @since 2.0 + * @requires modules/exporting + * + * @private + */ + downloadSVG: 'Download SVG vector image', + /** + * Exporting module menu. The tooltip title for the context menu holding + * print and export menu items. + * + * @since 3.0 + * @requires modules/exporting + * + * @private + */ + contextButtonTitle: 'Chart context menu' + }); + if (!defaultOptions.navigation) { + // Buttons and menus are collected in a separate config option set called + // 'navigation'. This can be extended later to add control buttons like + // zoom and pan right click menus. + /** + * A collection of options for buttons and menus appearing in the exporting + * module. + * + * @requires modules/exporting + * @optionparent navigation + */ + defaultOptions.navigation = {}; + } + merge(true, defaultOptions.navigation, { + /** + * @optionparent navigation.buttonOptions + * + * @private + */ + buttonOptions: { + theme: {}, + /** + * Whether to enable buttons. + * + * @sample highcharts/navigation/buttonoptions-enabled/ + * Exporting module loaded but buttons disabled + * + * @type {boolean} + * @default true + * @since 2.0 + * @apioption navigation.buttonOptions.enabled + */ + /** + * The pixel size of the symbol on the button. + * + * @sample highcharts/navigation/buttonoptions-height/ + * Bigger buttons + * + * @since 2.0 + */ + symbolSize: 14, + /** + * The x position of the center of the symbol inside the button. + * + * @sample highcharts/navigation/buttonoptions-height/ + * Bigger buttons + * + * @since 2.0 + */ + symbolX: 12.5, + /** + * The y position of the center of the symbol inside the button. + * + * @sample highcharts/navigation/buttonoptions-height/ + * Bigger buttons + * + * @since 2.0 + */ + symbolY: 10.5, + /** + * Alignment for the buttons. + * + * @sample highcharts/navigation/buttonoptions-align/ + * Center aligned + * + * @type {Highcharts.AlignValue} + * @since 2.0 + */ + align: 'right', + /** + * The pixel spacing between buttons. + * + * @since 2.0 + */ + buttonSpacing: 3, + /** + * Pixel height of the buttons. + * + * @sample highcharts/navigation/buttonoptions-height/ + * Bigger buttons + * + * @since 2.0 + */ + height: 22, + /** + * A text string to add to the individual button. + * + * @sample highcharts/exporting/buttons-text/ + * Full text button + * @sample highcharts/exporting/buttons-text-symbol/ + * Combined symbol and text + * + * @type {string} + * @default null + * @since 3.0 + * @apioption navigation.buttonOptions.text + */ + /** + * The vertical offset of the button's position relative to its + * `verticalAlign`. + * + * @sample highcharts/navigation/buttonoptions-verticalalign/ + * Buttons at lower right + * + * @type {number} + * @default 0 + * @since 2.0 + * @apioption navigation.buttonOptions.y + */ + /** + * The vertical alignment of the buttons. Can be one of `"top"`, + * `"middle"` or `"bottom"`. + * + * @sample highcharts/navigation/buttonoptions-verticalalign/ + * Buttons at lower right + * + * @type {Highcharts.VerticalAlignValue} + * @since 2.0 + */ + verticalAlign: 'top', + /** + * The pixel width of the button. + * + * @sample highcharts/navigation/buttonoptions-height/ + * Bigger buttons + * + * @since 2.0 + */ + width: 24 + } + }); + // Presentational attributes + merge(true, defaultOptions.navigation + /** + * A collection of options for buttons and menus appearing in the exporting + * module. + * + * @optionparent navigation + */ + , { + /** + * CSS styles for the popup menu appearing by default when the export + * icon is clicked. This menu is rendered in HTML. + * + * @see In styled mode, the menu is styled with the `.highcharts-menu` + * class. + * + * @sample highcharts/navigation/menustyle/ + * Light gray menu background + * + * @type {Highcharts.CSSObject} + * @default {"border": "1px solid #999999", "background": "#ffffff", "padding": "5px 0"} + * @since 2.0 + * + * @private + */ + menuStyle: { + /** @ignore-option */ + border: '1px solid #999999', + /** @ignore-option */ + background: '#ffffff', + /** @ignore-option */ + padding: '5px 0' + }, + /** + * CSS styles for the individual items within the popup menu appearing + * by default when the export icon is clicked. The menu items are + * rendered in HTML. Font size defaults to `11px` on desktop and `14px` + * on touch devices. + * + * @see In styled mode, the menu items are styled with the + * `.highcharts-menu-item` class. + * + * @sample {highcharts} highcharts/navigation/menuitemstyle/ + * Add a grey stripe to the left + * + * @type {Highcharts.CSSObject} + * @default {"padding": "0.5em 1em", "color": "#333333", "background": "none", "fontSize": "11px/14px", "transition": "background 250ms, color 250ms"} + * @since 2.0 + * + * @private + */ + menuItemStyle: { + /** @ignore-option */ + padding: '0.5em 1em', + /** @ignore-option */ + color: '#333333', + /** @ignore-option */ + background: 'none', + /** @ignore-option */ + fontSize: isTouchDevice ? '14px' : '11px', + /** @ignore-option */ + transition: 'background 250ms, color 250ms' + }, + /** + * CSS styles for the hover state of the individual items within the + * popup menu appearing by default when the export icon is clicked. The + * menu items are rendered in HTML. + * + * @see In styled mode, the menu items are styled with the + * `.highcharts-menu-item` class. + * + * @sample highcharts/navigation/menuitemhoverstyle/ + * Bold text on hover + * + * @type {Highcharts.CSSObject} + * @default {"background": "#335cad", "color": "#ffffff"} + * @since 2.0 + * + * @private + */ + menuItemHoverStyle: { + /** @ignore-option */ + background: '#335cad', + /** @ignore-option */ + color: '#ffffff' + }, + /** + * A collection of options for buttons appearing in the exporting + * module. + * + * In styled mode, the buttons are styled with the + * `.highcharts-contextbutton` and `.highcharts-button-symbol` classes. + * + * @requires modules/exporting + * + * @private + */ + buttonOptions: { + /** + * Fill color for the symbol within the button. + * + * @sample highcharts/navigation/buttonoptions-symbolfill/ + * Blue symbol stroke for one of the buttons + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 2.0 + */ + symbolFill: '#666666', + /** + * The color of the symbol's stroke or line. + * + * @sample highcharts/navigation/buttonoptions-symbolstroke/ + * Blue symbol stroke + * + * @type {Highcharts.ColorString} + * @since 2.0 + */ + symbolStroke: '#666666', + /** + * The pixel stroke width of the symbol on the button. + * + * @sample highcharts/navigation/buttonoptions-height/ + * Bigger buttons + * + * @since 2.0 + */ + symbolStrokeWidth: 3, + /** + * A configuration object for the button theme. The object accepts + * SVG properties like `stroke-width`, `stroke` and `fill`. + * Tri-state button styles are supported by the `states.hover` and + * `states.select` objects. + * + * @sample highcharts/navigation/buttonoptions-theme/ + * Theming the buttons + * + * @requires modules/exporting + * + * @since 3.0 + */ + theme: { + /** + * The default fill exists only to capture hover events. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #ffffff + * @apioption navigation.buttonOptions.theme.fill + */ + /** + * Default stroke for the buttons. + * @type {Highcharts.ColorString} + * @default none + * @apioption navigation.buttonOptions.theme.stroke + */ + /** + * Padding for the button. + */ + padding: 5 + } + } + }); + // Add the export related options + /** + * Options for the exporting module. For an overview on the matter, see + * [the docs](https://www.highcharts.com/docs/export-module/export-module-overview). + * + * @requires modules/exporting + * @optionparent exporting + */ + defaultOptions.exporting = { + /** + * Experimental setting to allow HTML inside the chart (added through + * the `useHTML` options), directly in the exported image. This allows + * you to preserve complicated HTML structures like tables or bi-directional + * text in exported charts. + * + * Disclaimer: The HTML is rendered in a `foreignObject` tag in the + * generated SVG. The official export server is based on PhantomJS, + * which supports this, but other SVG clients, like Batik, does not + * support it. This also applies to downloaded SVG that you want to + * open in a desktop client. + * + * @type {boolean} + * @default false + * @since 4.1.8 + * @apioption exporting.allowHTML + */ + /** + * Additional chart options to be merged into the chart before exporting to + * an image format. This does not apply to printing the chart via the export + * menu. + * + * For example, a common use case is to add data labels to improve + * readability of the exported chart, or to add a printer-friendly color + * scheme to exported PDFs. + * + * @sample {highcharts} highcharts/exporting/chartoptions-data-labels/ + * Added data labels + * @sample {highstock} highcharts/exporting/chartoptions-data-labels/ + * Added data labels + * + * @type {Highcharts.Options} + * @apioption exporting.chartOptions + */ + /** + * Whether to enable the exporting module. Disabling the module will + * hide the context button, but API methods will still be available. + * + * @sample {highcharts} highcharts/exporting/enabled-false/ + * Exporting module is loaded but disabled + * @sample {highstock} highcharts/exporting/enabled-false/ + * Exporting module is loaded but disabled + * + * @type {boolean} + * @default true + * @since 2.0 + * @apioption exporting.enabled + */ + /** + * Function to call if the offline-exporting module fails to export + * a chart on the client side, and [fallbackToExportServer]( + * #exporting.fallbackToExportServer) is disabled. If left undefined, an + * exception is thrown instead. Receives two parameters, the exporting + * options, and the error from the module. + * + * @see [fallbackToExportServer](#exporting.fallbackToExportServer) + * + * @type {Highcharts.ExportingErrorCallbackFunction} + * @since 5.0.0 + * @requires modules/exporting + * @requires modules/offline-exporting + * @apioption exporting.error + */ + /** + * Whether or not to fall back to the export server if the offline-exporting + * module is unable to export the chart on the client side. This happens for + * certain browsers, and certain features (e.g. + * [allowHTML](#exporting.allowHTML)), depending on the image type exporting + * to. For very complex charts, it is possible that export can fail in + * browsers that don't support Blob objects, due to data URL length limits. + * It is recommended to define the [exporting.error](#exporting.error) + * handler if disabling fallback, in order to notify users in case export + * fails. + * + * @type {boolean} + * @default true + * @since 4.1.8 + * @requires modules/exporting + * @requires modules/offline-exporting + * @apioption exporting.fallbackToExportServer + */ + /** + * The filename, without extension, to use for the exported chart. + * + * @sample {highcharts} highcharts/exporting/filename/ + * Custom file name + * @sample {highstock} highcharts/exporting/filename/ + * Custom file name + * + * @type {string} + * @default chart + * @since 2.0 + * @apioption exporting.filename + */ + /** + * An object containing additional key value data for the POST form that + * sends the SVG to the export server. For example, a `target` can be set to + * make sure the generated image is received in another frame, or a custom + * `enctype` or `encoding` can be set. + * + * @type {Highcharts.HTMLAttributes} + * @since 3.0.8 + * @apioption exporting.formAttributes + */ + /** + * Path where Highcharts will look for export module dependencies to + * load on demand if they don't already exist on `window`. Should currently + * point to location of [CanVG](https://github.com/canvg/canvg) library, + * [RGBColor.js](https://github.com/canvg/canvg), + * [jsPDF](https://github.com/yWorks/jsPDF) and + * [svg2pdf.js](https://github.com/yWorks/svg2pdf.js), required for client + * side export in certain browsers. + * + * @type {string} + * @default https://code.highcharts.com/{version}/lib + * @since 5.0.0 + * @apioption exporting.libURL + */ + /** + * Analogous to [sourceWidth](#exporting.sourceWidth). + * + * @type {number} + * @since 3.0 + * @apioption exporting.sourceHeight + */ + /** + * The width of the original chart when exported, unless an explicit + * [chart.width](#chart.width) is set, or a pixel width is set on the + * container. The width exported raster image is then multiplied by + * [scale](#exporting.scale). + * + * @sample {highcharts} highcharts/exporting/sourcewidth/ + * Source size demo + * @sample {highstock} highcharts/exporting/sourcewidth/ + * Source size demo + * @sample {highmaps} maps/exporting/sourcewidth/ + * Source size demo + * + * @type {number} + * @since 3.0 + * @apioption exporting.sourceWidth + */ + /** + * The pixel width of charts exported to PNG or JPG. As of Highcharts + * 3.0, the default pixel width is a function of the [chart.width]( + * #chart.width) or [exporting.sourceWidth](#exporting.sourceWidth) and the + * [exporting.scale](#exporting.scale). + * + * @sample {highcharts} highcharts/exporting/width/ + * Export to 200px wide images + * @sample {highstock} highcharts/exporting/width/ + * Export to 200px wide images + * + * @type {number} + * @since 2.0 + * @apioption exporting.width + */ + /** + * Default MIME type for exporting if `chart.exportChart()` is called + * without specifying a `type` option. Possible values are `image/png`, + * `image/jpeg`, `application/pdf` and `image/svg+xml`. + * + * @type {Highcharts.ExportingMimeTypeValue} + * @since 2.0 + */ + type: 'image/png', + /** + * The URL for the server module converting the SVG string to an image + * format. By default this points to Highchart's free web service. + * + * @since 2.0 + */ + url: 'https://export.highcharts.com/', + /** + * When printing the chart from the menu item in the burger menu, if + * the on-screen chart exceeds this width, it is resized. After printing + * or cancelled, it is restored. The default width makes the chart + * fit into typical paper format. Note that this does not affect the + * chart when printing the web page as a whole. + * + * @since 4.2.5 + */ + printMaxWidth: 780, + /** + * Defines the scale or zoom factor for the exported image compared + * to the on-screen display. While for instance a 600px wide chart + * may look good on a website, it will look bad in print. The default + * scale of 2 makes this chart export to a 1200px PNG or JPG. + * + * @see [chart.width](#chart.width) + * @see [exporting.sourceWidth](#exporting.sourceWidth) + * + * @sample {highcharts} highcharts/exporting/scale/ + * Scale demonstrated + * @sample {highstock} highcharts/exporting/scale/ + * Scale demonstrated + * @sample {highmaps} maps/exporting/scale/ + * Scale demonstrated + * + * @since 3.0 + */ + scale: 2, + /** + * Options for the export related buttons, print and export. In addition + * to the default buttons listed here, custom buttons can be added. + * See [navigation.buttonOptions](#navigation.buttonOptions) for general + * options. + * + * @type {Highcharts.Dictionary<*>} + * @requires modules/exporting + */ + buttons: { + /** + * Options for the export button. + * + * In styled mode, export button styles can be applied with the + * `.highcharts-contextbutton` class. + * + * @declare Highcharts.ExportingButtonsOptionsObject + * @extends navigation.buttonOptions + * @requires modules/exporting + */ + contextButton: { + /** + * A click handler callback to use on the button directly instead of + * the popup menu. + * + * @sample highcharts/exporting/buttons-contextbutton-onclick/ + * Skip the menu and export the chart directly + * + * @type {Function} + * @since 2.0 + * @apioption exporting.buttons.contextButton.onclick + */ + /** + * See [navigation.buttonOptions.symbolFill]( + * #navigation.buttonOptions.symbolFill). + * + * @type {Highcharts.ColorString} + * @default #666666 + * @since 2.0 + * @apioption exporting.buttons.contextButton.symbolFill + */ + /** + * The horizontal position of the button relative to the `align` + * option. + * + * @type {number} + * @default -10 + * @since 2.0 + * @apioption exporting.buttons.contextButton.x + */ + /** + * The class name of the context button. + */ + className: 'highcharts-contextbutton', + /** + * The class name of the menu appearing from the button. + */ + menuClassName: 'highcharts-contextmenu', + /** + * The symbol for the button. Points to a definition function in + * the `Highcharts.Renderer.symbols` collection. The default + * `exportIcon` function is part of the exporting module. Possible + * values are "circle", "square", "diamond", "triangle", + * "triangle-down", "menu", "menuball" or custom shape. + * + * @sample highcharts/exporting/buttons-contextbutton-symbol/ + * Use a circle for symbol + * @sample highcharts/exporting/buttons-contextbutton-symbol-custom/ + * Custom shape as symbol + * + * @type {Highcharts.SymbolKeyValue|"exportIcon"|"menu"|"menuball"|string} + * @since 2.0 + */ + symbol: 'menu', + /** + * The key to a [lang](#lang) option setting that is used for the + * button's title tooltip. When the key is `contextButtonTitle`, it + * refers to [lang.contextButtonTitle](#lang.contextButtonTitle) + * that defaults to "Chart context menu". + * + * @since 6.1.4 + */ + titleKey: 'contextButtonTitle', + /** + * This option is deprecated, use + * [titleKey](#exporting.buttons.contextButton.titleKey) instead. + * + * @deprecated + * @type {string} + * @apioption exporting.buttons.contextButton._titleKey + */ + /** + * A collection of strings pointing to config options for the menu + * items. The config options are defined in the + * `menuItemDefinitions` option. + * + * By default, there is the "View in full screen" and "Print" menu + * items, plus one menu item for each of the available export types. + * + * @sample {highcharts} highcharts/exporting/menuitemdefinitions/ + * Menu item definitions + * @sample {highstock} highcharts/exporting/menuitemdefinitions/ + * Menu item definitions + * @sample {highmaps} highcharts/exporting/menuitemdefinitions/ + * Menu item definitions + * + * @type {Array} + * @default ["viewFullscreen", "printChart", "separator", "downloadPNG", "downloadJPEG", "downloadPDF", "downloadSVG"] + * @since 2.0 + */ + menuItems: [ + 'viewFullscreen', + 'printChart', + 'separator', + 'downloadPNG', + 'downloadJPEG', + 'downloadPDF', + 'downloadSVG' + ] + } + }, + /** + * An object consisting of definitions for the menu items in the context + * menu. Each key value pair has a `key` that is referenced in the + * [menuItems](#exporting.buttons.contextButton.menuItems) setting, + * and a `value`, which is an object with the following properties: + * + * - **onclick:** The click handler for the menu item + * + * - **text:** The text for the menu item + * + * - **textKey:** If internationalization is required, the key to a language + * string + * + * Custom text for the "exitFullScreen" can be set only in lang options + * (it is not a separate button). + * + * @sample {highcharts} highcharts/exporting/menuitemdefinitions/ + * Menu item definitions + * @sample {highstock} highcharts/exporting/menuitemdefinitions/ + * Menu item definitions + * @sample {highmaps} highcharts/exporting/menuitemdefinitions/ + * Menu item definitions + * + * + * @type {Highcharts.Dictionary} + * @default {"viewFullscreen": {}, "printChart": {}, "separator": {}, "downloadPNG": {}, "downloadJPEG": {}, "downloadPDF": {}, "downloadSVG": {}} + * @since 5.0.13 + */ + menuItemDefinitions: { + /** + * @ignore + */ + viewFullscreen: { + textKey: 'viewFullscreen', + onclick: function () { + this.fullscreen.toggle(); + } + }, + /** + * @ignore + */ + printChart: { + textKey: 'printChart', + onclick: function () { + this.print(); + } + }, + /** + * @ignore + */ + separator: { + separator: true + }, + /** + * @ignore + */ + downloadPNG: { + textKey: 'downloadPNG', + onclick: function () { + this.exportChart(); + } + }, + /** + * @ignore + */ + downloadJPEG: { + textKey: 'downloadJPEG', + onclick: function () { + this.exportChart({ + type: 'image/jpeg' + }); + } + }, + /** + * @ignore + */ + downloadPDF: { + textKey: 'downloadPDF', + onclick: function () { + this.exportChart({ + type: 'application/pdf' + }); + } + }, + /** + * @ignore + */ + downloadSVG: { + textKey: 'downloadSVG', + onclick: function () { + this.exportChart({ + type: 'image/svg+xml' + }); + } + } + } + }; + /** + * Fires after a chart is printed through the context menu item or the + * `Chart.print` method. + * + * @sample highcharts/chart/events-beforeprint-afterprint/ + * Rescale the chart to print + * + * @type {Highcharts.ExportingAfterPrintCallbackFunction} + * @since 4.1.0 + * @context Highcharts.Chart + * @requires modules/exporting + * @apioption chart.events.afterPrint + */ + /** + * Fires before a chart is printed through the context menu item or + * the `Chart.print` method. + * + * @sample highcharts/chart/events-beforeprint-afterprint/ + * Rescale the chart to print + * + * @type {Highcharts.ExportingBeforePrintCallbackFunction} + * @since 4.1.0 + * @context Highcharts.Chart + * @requires modules/exporting + * @apioption chart.events.beforePrint + */ + /** + * The post utility + * + * @private + * @function Highcharts.post + * @param {string} url + * Post URL + * @param {object} data + * Post data + * @param {Highcharts.Dictionary} [formAttributes] + * Additional attributes for the post request + * @return {void} + */ + H.post = function (url, data, formAttributes) { + // create the form + var form = createElement('form', merge({ + method: 'post', + action: url, + enctype: 'multipart/form-data' + }, formAttributes), { + display: 'none' + }, doc.body); + // add the data + objectEach(data, function (val, name) { + createElement('input', { + type: 'hidden', + name: name, + value: val + }, null, form); + }); + // submit + form.submit(); + // clean up + discardElement(form); + }; + if (H.isSafari) { + H.win.matchMedia('print').addListener(function (mqlEvent) { + if (!H.printingChart) { + return void 0; + } + if (mqlEvent.matches) { + H.printingChart.beforePrint(); + } + else { + H.printingChart.afterPrint(); + } + }); + } + extend(Chart.prototype, /** @lends Highcharts.Chart.prototype */ { + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Exporting module only. A collection of fixes on the produced SVG to + * account for expando properties, browser bugs, VML problems and other. + * Returns a cleaned SVG. + * + * @private + * @function Highcharts.Chart#sanitizeSVG + * @param {string} svg + * SVG code to sanitize + * @param {Highcharts.Options} options + * Chart options to apply + * @return {string} + * Sanitized SVG code + * @requires modules/exporting + */ + sanitizeSVG: function (svg, options) { + var split = svg.indexOf('') + 6, html = svg.substr(split); + // Remove any HTML added to the container after the SVG (#894, #9087) + svg = svg.substr(0, split); + // Move HTML into a foreignObject + if (options && options.exporting && options.exporting.allowHTML) { + if (html) { + html = '' + + '' + + html + + '' + + ''; + svg = svg.replace('', html + ''); + } + } + svg = svg + .replace(/zIndex="[^"]+"/g, '') + .replace(/symbolName="[^"]+"/g, '') + .replace(/jQuery[0-9]+="[^"]+"/g, '') + .replace(/url\(("|")(.*?)("|")\;?\)/g, 'url($2)') + .replace(/url\([^#]+#/g, 'url(#') + .replace(/]+(>|$)/g, '') // strip HTML tags + .replace(/[\s_]+/g, '-') + .replace(/[^a-z0-9\-]/g, '') // preserve only latin + .replace(/^[\-]+/g, '') // dashes in the start + .replace(/[\-]+/g, '-') // dashes in a row + .substr(0, 24) + .replace(/[\-]+$/g, ''); // dashes in the end; + } + if (!filename || filename.length < 5) { + filename = 'chart'; + } + return filename; + }, + /** + * Exporting module required. Submit an SVG version of the chart to a server + * along with some parameters for conversion. + * + * @sample highcharts/members/chart-exportchart/ + * Export with no options + * @sample highcharts/members/chart-exportchart-filename/ + * PDF type and custom filename + * @sample highcharts/members/chart-exportchart-custom-background/ + * Different chart background in export + * @sample stock/members/chart-exportchart/ + * Export with Highstock + * + * @function Highcharts.Chart#exportChart + * + * @param {Highcharts.ExportingOptions} exportingOptions + * Exporting options in addition to those defined in + * [exporting](https://api.highcharts.com/highcharts/exporting). + * + * @param {Highcharts.Options} chartOptions + * Additional chart options for the exported chart. For example a + * different background color can be added here, or `dataLabels` for + * export only. + * + * @return {void} + * + * @requires modules/exporting + */ + exportChart: function (exportingOptions, chartOptions) { + var svg = this.getSVGForExport(exportingOptions, chartOptions); + // merge the options + exportingOptions = merge(this.options.exporting, exportingOptions); + // do the post + H.post(exportingOptions.url, { + filename: exportingOptions.filename ? exportingOptions.filename.replace(/\//g, '-') : this.getFilename(), + type: exportingOptions.type, + // IE8 fails to post undefined correctly, so use 0 + width: exportingOptions.width || 0, + scale: exportingOptions.scale, + svg: svg + }, exportingOptions.formAttributes); + }, + /** + * Move the chart container(s) to another div. + * + * @function Highcharts#moveContainers + * + * @private + * + * @param {Highcharts.HTMLDOMElement} moveTo + * Move target + * @return {void} + */ + moveContainers: function (moveTo) { + var chart = this; + (chart.fixedDiv ? // When scrollablePlotArea is active (#9533) + [chart.fixedDiv, chart.scrollingContainer] : + [chart.container]).forEach(function (div) { + moveTo.appendChild(div); + }); + }, + /** + * Prepare chart and document before printing a chart. + * + * @function Highcharts#beforePrint + * + * @private + * + * @return {void} + * + * @fires Highcharts.Chart#event:beforePrint + */ + beforePrint: function () { + var chart = this, body = doc.body, printMaxWidth = chart.options.exporting.printMaxWidth, printReverseInfo = { + childNodes: body.childNodes, + origDisplay: [], + resetParams: void 0 + }; + var handleMaxWidth; + chart.isPrinting = true; + chart.pointer.reset(null, 0); + fireEvent(chart, 'beforePrint'); + // Handle printMaxWidth + handleMaxWidth = printMaxWidth && chart.chartWidth > printMaxWidth; + if (handleMaxWidth) { + printReverseInfo.resetParams = [ + chart.options.chart.width, + void 0, + false + ]; + chart.setSize(printMaxWidth, void 0, false); + } + // hide all body content + [].forEach.call(printReverseInfo.childNodes, function (node, i) { + if (node.nodeType === 1) { + printReverseInfo.origDisplay[i] = node.style.display; + node.style.display = 'none'; + } + }); + // pull out the chart + chart.moveContainers(body); + // Storage details for undo action after printing + chart.printReverseInfo = printReverseInfo; + }, + /** + * Clena up after printing a chart. + * + * @function Highcharts#afterPrint + * + * @private + * + * @param {Highcharts.Chart} chart + * Chart that was (or suppose to be) printed + * @return {void} + * + * @fires Highcharts.Chart#event:afterPrint + */ + afterPrint: function () { + var chart = this; + if (!chart.printReverseInfo) { + return void 0; + } + var childNodes = chart.printReverseInfo.childNodes, origDisplay = chart.printReverseInfo.origDisplay, resetParams = chart.printReverseInfo.resetParams; + // put the chart back in + chart.moveContainers(chart.renderTo); + // restore all body content + [].forEach.call(childNodes, function (node, i) { + if (node.nodeType === 1) { + node.style.display = (origDisplay[i] || ''); + } + }); + chart.isPrinting = false; + // Reset printMaxWidth + if (resetParams) { + chart.setSize.apply(chart, resetParams); + } + delete chart.printReverseInfo; + delete H.printingChart; + fireEvent(chart, 'afterPrint'); + }, + /** + * Exporting module required. Clears away other elements in the page and + * prints the chart as it is displayed. By default, when the exporting + * module is enabled, a context button with a drop down menu in the upper + * right corner accesses this function. + * + * @sample highcharts/members/chart-print/ + * Print from a HTML button + * + * @function Highcharts.Chart#print + * + * @return {void} + * + * @fires Highcharts.Chart#event:beforePrint + * @fires Highcharts.Chart#event:afterPrint + * + * @requires modules/exporting + */ + print: function () { + var chart = this; + if (chart.isPrinting) { // block the button while in printing mode + return; + } + H.printingChart = chart; + if (!H.isSafari) { + chart.beforePrint(); + } + // Give the browser time to draw WebGL content, an issue that randomly + // appears (at least) in Chrome ~67 on the Mac (#8708). + setTimeout(function () { + win.focus(); // #1510 + win.print(); + // allow the browser to prepare before reverting + if (!H.isSafari) { + setTimeout(function () { + chart.afterPrint(); + }, 1000); + } + }, 1); + }, + /** + * Display a popup menu for choosing the export type. + * + * @private + * @function Highcharts.Chart#contextMenu + * @param {string} className + * An identifier for the menu. + * @param {Array} items + * A collection with text and onclicks for the items. + * @param {number} x + * The x position of the opener button + * @param {number} y + * The y position of the opener button + * @param {number} width + * The width of the opener button + * @param {number} height + * The height of the opener button + * @return {void} + * @requires modules/exporting + */ + contextMenu: function (className, items, x, y, width, height, button) { + var chart = this, navOptions = chart.options.navigation, chartWidth = chart.chartWidth, chartHeight = chart.chartHeight, cacheName = 'cache-' + className, menu = chart[cacheName], menuPadding = Math.max(width, height), // for mouse leave detection + innerMenu, menuStyle; + // create the menu only the first time + if (!menu) { + // create a HTML element above the SVG + chart.exportContextMenu = chart[cacheName] = menu = + createElement('div', { + className: className + }, { + position: 'absolute', + zIndex: 1000, + padding: menuPadding + 'px', + pointerEvents: 'auto' + }, chart.fixedDiv || chart.container); + innerMenu = createElement('ul', { className: 'highcharts-menu' }, { + listStyle: 'none', + margin: 0, + padding: 0 + }, menu); + // Presentational CSS + if (!chart.styledMode) { + css(innerMenu, extend({ + MozBoxShadow: '3px 3px 10px #888', + WebkitBoxShadow: '3px 3px 10px #888', + boxShadow: '3px 3px 10px #888' + }, navOptions.menuStyle)); + } + // hide on mouse out + menu.hideMenu = function () { + css(menu, { display: 'none' }); + if (button) { + button.setState(0); + } + chart.openMenu = false; + css(chart.renderTo, { overflow: 'hidden' }); // #10361 + U.clearTimeout(menu.hideTimer); + fireEvent(chart, 'exportMenuHidden'); + }; + // Hide the menu some time after mouse leave (#1357) + chart.exportEvents.push(addEvent(menu, 'mouseleave', function () { + menu.hideTimer = win.setTimeout(menu.hideMenu, 500); + }), addEvent(menu, 'mouseenter', function () { + U.clearTimeout(menu.hideTimer); + }), + // Hide it on clicking or touching outside the menu (#2258, + // #2335, #2407) + addEvent(doc, 'mouseup', function (e) { + if (!chart.pointer.inClass(e.target, className)) { + menu.hideMenu(); + } + }), addEvent(menu, 'click', function () { + if (chart.openMenu) { + menu.hideMenu(); + } + })); + // create the items + items.forEach(function (item) { + if (typeof item === 'string') { + item = chart.options.exporting + .menuItemDefinitions[item]; + } + if (isObject(item, true)) { + var element; + if (item.separator) { + element = createElement('hr', null, null, innerMenu); + } + else { + element = createElement('li', { + className: 'highcharts-menu-item', + onclick: function (e) { + if (e) { // IE7 + e.stopPropagation(); + } + menu.hideMenu(); + if (item.onclick) { + item.onclick + .apply(chart, arguments); + } + }, + innerHTML: (item.text || + chart.options.lang[item.textKey]) + }, null, innerMenu); + if (!chart.styledMode) { + element.onmouseover = function () { + css(this, navOptions.menuItemHoverStyle); + }; + element.onmouseout = function () { + css(this, navOptions.menuItemStyle); + }; + css(element, extend({ + cursor: 'pointer' + }, navOptions.menuItemStyle)); + } + } + // Keep references to menu divs to be able to destroy them + chart.exportDivElements.push(element); + } + }); + // Keep references to menu and innerMenu div to be able to destroy + // them + chart.exportDivElements.push(innerMenu, menu); + chart.exportMenuWidth = menu.offsetWidth; + chart.exportMenuHeight = menu.offsetHeight; + } + menuStyle = { display: 'block' }; + // if outside right, right align it + if (x + chart.exportMenuWidth > chartWidth) { + menuStyle.right = (chartWidth - x - width - menuPadding) + 'px'; + } + else { + menuStyle.left = (x - menuPadding) + 'px'; + } + // if outside bottom, bottom align it + if (y + height + chart.exportMenuHeight > chartHeight && + button.alignOptions.verticalAlign !== 'top') { + menuStyle.bottom = (chartHeight - y - menuPadding) + 'px'; + } + else { + menuStyle.top = (y + height - menuPadding) + 'px'; + } + css(menu, menuStyle); + css(chart.renderTo, { overflow: '' }); // #10361 + chart.openMenu = true; + fireEvent(chart, 'exportMenuShown'); + }, + /** + * Add the export button to the chart, with options. + * + * @private + * @function Highcharts.Chart#addButton + * @param {Highcharts.NavigationButtonOptions} options + * @return {void} + * @requires modules/exporting + */ + addButton: function (options) { + var chart = this, renderer = chart.renderer, btnOptions = merge(chart.options.navigation.buttonOptions, options), onclick = btnOptions.onclick, menuItems = btnOptions.menuItems, symbol, button, symbolSize = btnOptions.symbolSize || 12; + if (!chart.btnCount) { + chart.btnCount = 0; + } + // Keeps references to the button elements + if (!chart.exportDivElements) { + chart.exportDivElements = []; + chart.exportSVGElements = []; + } + if (btnOptions.enabled === false) { + return; + } + var attr = btnOptions.theme, states = attr.states, hover = states && states.hover, select = states && states.select, callback; + if (!chart.styledMode) { + attr.fill = pick(attr.fill, '#ffffff'); + attr.stroke = pick(attr.stroke, 'none'); + } + delete attr.states; + if (onclick) { + callback = function (e) { + if (e) { + e.stopPropagation(); + } + onclick.call(chart, e); + }; + } + else if (menuItems) { + callback = function (e) { + // consistent with onclick call (#3495) + if (e) { + e.stopPropagation(); + } + chart.contextMenu(button.menuClassName, menuItems, button.translateX, button.translateY, button.width, button.height, button); + button.setState(2); + }; + } + if (btnOptions.text && btnOptions.symbol) { + attr.paddingLeft = pick(attr.paddingLeft, 25); + } + else if (!btnOptions.text) { + extend(attr, { + width: btnOptions.width, + height: btnOptions.height, + padding: 0 + }); + } + if (!chart.styledMode) { + attr['stroke-linecap'] = 'round'; + attr.fill = pick(attr.fill, '#ffffff'); + attr.stroke = pick(attr.stroke, 'none'); + } + button = renderer + .button(btnOptions.text, 0, 0, callback, attr, hover, select) + .addClass(options.className) + .attr({ + title: pick(chart.options.lang[btnOptions._titleKey || btnOptions.titleKey], '') + }); + button.menuClassName = (options.menuClassName || + 'highcharts-menu-' + chart.btnCount++); + if (btnOptions.symbol) { + symbol = renderer + .symbol(btnOptions.symbol, btnOptions.symbolX - (symbolSize / 2), btnOptions.symbolY - (symbolSize / 2), symbolSize, symbolSize + // If symbol is an image, scale it (#7957) + , { + width: symbolSize, + height: symbolSize + }) + .addClass('highcharts-button-symbol') + .attr({ + zIndex: 1 + }) + .add(button); + if (!chart.styledMode) { + symbol.attr({ + stroke: btnOptions.symbolStroke, + fill: btnOptions.symbolFill, + 'stroke-width': btnOptions.symbolStrokeWidth || 1 + }); + } + } + button + .add(chart.exportingGroup) + .align(extend(btnOptions, { + width: button.width, + x: pick(btnOptions.x, chart.buttonOffset) // #1654 + }), true, 'spacingBox'); + chart.buttonOffset += ((button.width + btnOptions.buttonSpacing) * + (btnOptions.align === 'right' ? -1 : 1)); + chart.exportSVGElements.push(button, symbol); + }, + /** + * Destroy the export buttons. + * @private + * @function Highcharts.Chart#destroyExport + * @param {global.Event} [e] + * @return {void} + * @requires modules/exporting + */ + destroyExport: function (e) { + var chart = e ? e.target : this, exportSVGElements = chart.exportSVGElements, exportDivElements = chart.exportDivElements, exportEvents = chart.exportEvents, cacheName; + // Destroy the extra buttons added + if (exportSVGElements) { + exportSVGElements.forEach(function (elem, i) { + // Destroy and null the svg elements + if (elem) { // #1822 + elem.onclick = elem.ontouchstart = null; + cacheName = 'cache-' + elem.menuClassName; + if (chart[cacheName]) { + delete chart[cacheName]; + } + chart.exportSVGElements[i] = elem.destroy(); + } + }); + exportSVGElements.length = 0; + } + // Destroy the exporting group + if (chart.exportingGroup) { + chart.exportingGroup.destroy(); + delete chart.exportingGroup; + } + // Destroy the divs for the menu + if (exportDivElements) { + exportDivElements.forEach(function (elem, i) { + // Remove the event handler + U.clearTimeout(elem.hideTimer); // #5427 + removeEvent(elem, 'mouseleave'); + // Remove inline events + chart.exportDivElements[i] = + elem.onmouseout = + elem.onmouseover = + elem.ontouchstart = + elem.onclick = null; + // Destroy the div by moving to garbage bin + discardElement(elem); + }); + exportDivElements.length = 0; + } + if (exportEvents) { + exportEvents.forEach(function (unbind) { + unbind(); + }); + exportEvents.length = 0; + } + } + /* eslint-enable no-invalid-this, valid-jsdoc */ + }); + // These ones are translated to attributes rather than styles + SVGRenderer.prototype.inlineToAttributes = [ + 'fill', + 'stroke', + 'strokeLinecap', + 'strokeLinejoin', + 'strokeWidth', + 'textAnchor', + 'x', + 'y' + ]; + // These CSS properties are not inlined. Remember camelCase. + SVGRenderer.prototype.inlineBlacklist = [ + /-/, + /^(clipPath|cssText|d|height|width)$/, + /^font$/, + /[lL]ogical(Width|Height)$/, + /perspective/, + /TapHighlightColor/, + /^transition/, + /^length$/ // #7700 + // /^text (border|color|cursor|height|webkitBorder)/ + ]; + SVGRenderer.prototype.unstyledElements = [ + 'clipPath', + 'defs', + 'desc' + ]; + /** + * Analyze inherited styles from stylesheets and add them inline + * + * @private + * @function Highcharts.Chart#inlineStyles + * @return {void} + * + * @todo: What are the border styles for text about? In general, text has a lot + * of properties. + * @todo: Make it work with IE9 and IE10. + * + * @requires modules/exporting + */ + Chart.prototype.inlineStyles = function () { + var renderer = this.renderer, inlineToAttributes = renderer.inlineToAttributes, blacklist = renderer.inlineBlacklist, whitelist = renderer.inlineWhitelist, // For IE + unstyledElements = renderer.unstyledElements, defaultStyles = {}, dummySVG, iframe, iframeDoc; + // Create an iframe where we read default styles without pollution from this + // body + iframe = doc.createElement('iframe'); + css(iframe, { + width: '1px', + height: '1px', + visibility: 'hidden' + }); + doc.body.appendChild(iframe); + iframeDoc = iframe.contentWindow.document; + iframeDoc.open(); + iframeDoc.write(''); + iframeDoc.close(); + /** + * Make hyphenated property names out of camelCase + * @private + * @param {string} prop + * Property name in camelCase + * @return {string} + * Hyphenated property name + */ + function hyphenate(prop) { + return prop.replace(/([A-Z])/g, function (a, b) { + return '-' + b.toLowerCase(); + }); + } + /** + * Call this on all elements and recurse to children + * @private + * @param {Highcharts.HTMLDOMElement} node + * Element child + * @return {void} + */ + function recurse(node) { + var styles, parentStyles, cssText = '', dummy, styleAttr, blacklisted, whitelisted, i; + /** + * Check computed styles and whether they are in the white/blacklist for + * styles or atttributes. + * @private + * @param {string} val + * Style value + * @param {string} prop + * Style property name + * @return {void} + */ + function filterStyles(val, prop) { + // Check against whitelist & blacklist + blacklisted = whitelisted = false; + if (whitelist) { + // Styled mode in IE has a whitelist instead. + // Exclude all props not in this list. + i = whitelist.length; + while (i-- && !whitelisted) { + whitelisted = whitelist[i].test(prop); + } + blacklisted = !whitelisted; + } + // Explicitly remove empty transforms + if (prop === 'transform' && val === 'none') { + blacklisted = true; + } + i = blacklist.length; + while (i-- && !blacklisted) { + blacklisted = (blacklist[i].test(prop) || + typeof val === 'function'); + } + if (!blacklisted) { + // If parent node has the same style, it gets inherited, no need + // to inline it. Top-level props should be diffed against parent + // (#7687). + if ((parentStyles[prop] !== val || node.nodeName === 'svg') && + defaultStyles[node.nodeName][prop] !== val) { + // Attributes + if (inlineToAttributes.indexOf(prop) !== -1) { + node.setAttribute(hyphenate(prop), val); + // Styles + } + else { + cssText += hyphenate(prop) + ':' + val + ';'; + } + } + } + } + if (node.nodeType === 1 && + unstyledElements.indexOf(node.nodeName) === -1) { + styles = win.getComputedStyle(node, null); + parentStyles = node.nodeName === 'svg' ? + {} : + win.getComputedStyle(node.parentNode, null); + // Get default styles from the browser so that we don't have to add + // these + if (!defaultStyles[node.nodeName]) { + /* + if (!dummySVG) { + dummySVG = doc.createElementNS(H.SVG_NS, 'svg'); + dummySVG.setAttribute('version', '1.1'); + doc.body.appendChild(dummySVG); + } + */ + dummySVG = iframeDoc.getElementsByTagName('svg')[0]; + dummy = iframeDoc.createElementNS(node.namespaceURI, node.nodeName); + dummySVG.appendChild(dummy); + // Copy, so we can remove the node + defaultStyles[node.nodeName] = merge(win.getComputedStyle(dummy, null)); + // Remove default fill, otherwise text disappears when exported + if (node.nodeName === 'text') { + delete defaultStyles.text.fill; + } + dummySVG.removeChild(dummy); + } + // Loop through all styles and add them inline if they are ok + if (isFirefoxBrowser || isMSBrowser) { + // Some browsers put lots of styles on the prototype + for (var p in styles) { // eslint-disable-line guard-for-in + filterStyles(styles[p], p); + } + } + else { + objectEach(styles, filterStyles); + } + // Apply styles + if (cssText) { + styleAttr = node.getAttribute('style'); + node.setAttribute('style', (styleAttr ? styleAttr + ';' : '') + cssText); + } + // Set default stroke width (needed at least for IE) + if (node.nodeName === 'svg') { + node.setAttribute('stroke-width', '1px'); + } + if (node.nodeName === 'text') { + return; + } + // Recurse + [].forEach.call(node.children || node.childNodes, recurse); + } + } + /** + * Remove the dummy objects used to get defaults + * @private + * @return {void} + */ + function tearDown() { + dummySVG.parentNode.removeChild(dummySVG); + } + recurse(this.container.querySelector('svg')); + tearDown(); + }; + symbols.menu = function (x, y, width, height) { + var arr = [ + ['M', x, y + 2.5], + ['L', x + width, y + 2.5], + ['M', x, y + height / 2 + 0.5], + ['L', x + width, y + height / 2 + 0.5], + ['M', x, y + height - 1.5], + ['L', x + width, y + height - 1.5] + ]; + return arr; + }; + symbols.menuball = function (x, y, width, height) { + var path = [], h = (height / 3) - 2; + path = path.concat(this.circle(width - h, y, h, h), this.circle(width - h, y + h + 4, h, h), this.circle(width - h, y + 2 * (h + 4), h, h)); + return path; + }; + /** + * Add the buttons on chart load + * @private + * @function Highcharts.Chart#renderExporting + * @return {void} + * @requires modules/exporting + */ + Chart.prototype.renderExporting = function () { + var chart = this, exportingOptions = chart.options.exporting, buttons = exportingOptions.buttons, isDirty = chart.isDirtyExporting || !chart.exportSVGElements; + chart.buttonOffset = 0; + if (chart.isDirtyExporting) { + chart.destroyExport(); + } + if (isDirty && exportingOptions.enabled !== false) { + chart.exportEvents = []; + chart.exportingGroup = chart.exportingGroup || + chart.renderer.g('exporting-group').attr({ + zIndex: 3 // #4955, // #8392 + }).add(); + objectEach(buttons, function (button) { + chart.addButton(button); + }); + chart.isDirtyExporting = false; + } + // Destroy the export elements at chart destroy + addEvent(chart, 'destroy', chart.destroyExport); + }; + /* eslint-disable no-invalid-this */ + // Add update methods to handle chart.update and chart.exporting.update and + // chart.navigation.update. These must be added to the chart instance rather + // than the Chart prototype in order to use the chart instance inside the update + // function. + addEvent(Chart, 'init', function () { + var chart = this; + /** + * @private + * @param {"exporting"|"navigation"} prop + * Property name in option root + * @param {Highcharts.ExportingOptions|Highcharts.NavigationOptions} options + * Options to update + * @param {boolean} [redraw=true] + * Whether to redraw + * @return {void} + */ + function update(prop, options, redraw) { + chart.isDirtyExporting = true; + merge(true, chart.options[prop], options); + if (pick(redraw, true)) { + chart.redraw(); + } + } + chart.exporting = { + update: function (options, redraw) { + update('exporting', options, redraw); + } + }; + // Register update() method for navigation. Can not be set the same way as + // for exporting, because navigation options are shared with bindings which + // has separate update() logic. + chartNavigationMixin.addUpdate(function (options, redraw) { + update('navigation', options, redraw); + }, chart); + }); + /* eslint-enable no-invalid-this */ + Chart.prototype.callbacks.push(function (chart) { + chart.renderExporting(); + addEvent(chart, 'redraw', chart.renderExporting); + // Uncomment this to see a button directly below the chart, for quick + // testing of export + /* + var button, viewImage, viewSource; + if (!chart.renderer.forExport) { + viewImage = function () { + var div = doc.createElement('div'); + div.innerHTML = chart.getSVGForExport(); + chart.renderTo.parentNode.appendChild(div); + }; + + viewSource = function () { + var pre = doc.createElement('pre'); + pre.innerHTML = chart.getSVGForExport() + .replace(//g, '>'); + chart.renderTo.parentNode.appendChild(pre); + }; + + viewImage(); + + // View SVG Image + button = doc.createElement('button'); + button.innerHTML = 'View SVG Image'; + chart.renderTo.parentNode.appendChild(button); + button.onclick = viewImage; + + // View SVG Source + button = doc.createElement('button'); + button.innerHTML = 'View SVG Source'; + chart.renderTo.parentNode.appendChild(button); + button.onclick = viewSource; + } + //*/ + }); + + }); + _registerModule(_modules, 'masters/modules/exporting.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/full-screen.js b/librerias/gantt/code/modules/full-screen.js new file mode 100644 index 0000000..2582776 --- /dev/null +++ b/librerias/gantt/code/modules/full-screen.js @@ -0,0 +1,17 @@ +/* + Highstock JS v8.1.0 (2020-05-05) + + Advanced Highstock tools + + (c) 2010-2019 Highsoft AS + Author: Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/full-screen",["highcharts"],function(c){a(c);a.Highcharts=c;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function c(a,g,c,f){a.hasOwnProperty(g)||(a[g]=f.apply(null,c))}a=a?a._modules:{};c(a,"modules/full-screen.src.js",[a["parts/Globals.js"],a["parts/Utilities.js"]],function(a,c){var d=c.addEvent;c=a.Chart;var f= +function(){function a(b){this.chart=b;this.isOpen=!1;b=b.renderTo;this.browserProps||("function"===typeof b.requestFullscreen?this.browserProps={fullscreenChange:"fullscreenchange",requestFullscreen:"requestFullscreen",exitFullscreen:"exitFullscreen"}:b.mozRequestFullScreen?this.browserProps={fullscreenChange:"mozfullscreenchange",requestFullscreen:"mozRequestFullScreen",exitFullscreen:"mozCancelFullScreen"}:b.webkitRequestFullScreen?this.browserProps={fullscreenChange:"webkitfullscreenchange",requestFullscreen:"webkitRequestFullScreen", +exitFullscreen:"webkitExitFullscreen"}:b.msRequestFullscreen&&(this.browserProps={fullscreenChange:"MSFullscreenChange",requestFullscreen:"msRequestFullscreen",exitFullscreen:"msExitFullscreen"}))}a.prototype.close=function(){var b=this.chart;if(this.isOpen&&this.browserProps&&b.container.ownerDocument instanceof Document)b.container.ownerDocument[this.browserProps.exitFullscreen]();this.unbindFullscreenEvent&&this.unbindFullscreenEvent();this.isOpen=!1;this.setButtonText()};a.prototype.open=function(){var b= +this,a=b.chart;if(b.browserProps){b.unbindFullscreenEvent=d(a.container.ownerDocument,b.browserProps.fullscreenChange,function(){b.isOpen?(b.isOpen=!1,b.close()):(b.isOpen=!0,b.setButtonText())});var c=a.renderTo[b.browserProps.requestFullscreen]();if(c)c["catch"](function(){alert("Full screen is not supported inside a frame.")});d(a,"destroy",b.unbindFullscreenEvent)}};a.prototype.setButtonText=function(){var a,c=this.chart,d=c.exportDivElements,e=c.options.exporting,f=null===(a=null===e||void 0=== +e?void 0:e.buttons)||void 0===a?void 0:a.contextButton.menuItems;a=c.options.lang;(null===e||void 0===e?0:e.menuItemDefinitions)&&(null===a||void 0===a?0:a.exitFullscreen)&&a.viewFullscreen&&f&&d&&d.length&&(d[f.indexOf("viewFullscreen")].innerHTML=this.isOpen?a.exitFullscreen:e.menuItemDefinitions.viewFullscreen.text||a.viewFullscreen)};a.prototype.toggle=function(){this.isOpen?this.close():this.open()};return a}();a.Fullscreen=f;d(c,"beforeRender",function(){this.fullscreen=new a.Fullscreen(this)}); +return a.Fullscreen});c(a,"masters/modules/full-screen.src.js",[],function(){})}); +//# sourceMappingURL=full-screen.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/full-screen.js.map b/librerias/gantt/code/modules/full-screen.js.map new file mode 100644 index 0000000..1883574 --- /dev/null +++ b/librerias/gantt/code/modules/full-screen.js.map @@ -0,0 +1 @@ +{"version":3,"file":"full-screen.js.map","lineCount":16,"mappings":"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","sources":["full-screen.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","U","addEvent","Chart","Fullscreen","chart","isOpen","container","renderTo","browserProps","requestFullscreen","fullscreenChange","exitFullscreen","mozRequestFullScreen","webkitRequestFullScreen","msRequestFullscreen","prototype","close","Fullscreen.prototype.close","fullscreen","ownerDocument","Document","unbindFullscreenEvent","setButtonText","open","Fullscreen.prototype.open","promise","alert","Fullscreen.prototype.setButtonText","_a","exportDivElements","exportingOptions","options","exporting","menuItems","buttons","contextButton","lang","menuItemDefinitions","viewFullscreen","length","indexOf","innerHTML","text","toggle","Fullscreen.prototype.toggle"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/full-screen.src.js b/librerias/gantt/code/modules/full-screen.src.js new file mode 100644 index 0000000..6a0bcf9 --- /dev/null +++ b/librerias/gantt/code/modules/full-screen.src.js @@ -0,0 +1,248 @@ +/** + * @license Highstock JS v8.1.0 (2020-05-05) + * + * Advanced Highstock tools + * + * (c) 2010-2019 Highsoft AS + * Author: Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/full-screen', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'modules/full-screen.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * (c) 2009-2020 Rafal Sebestjanski + * + * Full screen for Highcharts + * + * License: www.highcharts.com/license + */ + var addEvent = U.addEvent; + var Chart = H.Chart; + /** + * The module allows user to enable display chart in full screen mode. + * Used in StockTools too. + * Based on default solutions in browsers. + * + */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Handles displaying chart's container in the fullscreen mode. + * + * @class + * @name Highcharts.Fullscreen + * @hideconstructor + * @requires modules/full-screen + */ + var Fullscreen = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Fullscreen(chart) { + /** + * Chart managed by the fullscreen controller. + * @name Highcharts.Fullscreen#chart + * @type {Highcharts.Chart} + */ + this.chart = chart; + /** + * The flag is set to `true` when the chart is displayed in + * the fullscreen mode. + * + * @name Highcharts.Fullscreen#isOpen + * @type {boolean|undefined} + * @since 8.0.1 + */ + this.isOpen = false; + var container = chart.renderTo; + // Hold event and methods available only for a current browser. + if (!this.browserProps) { + if (typeof container.requestFullscreen === 'function') { + this.browserProps = { + fullscreenChange: 'fullscreenchange', + requestFullscreen: 'requestFullscreen', + exitFullscreen: 'exitFullscreen' + }; + } + else if (container.mozRequestFullScreen) { + this.browserProps = { + fullscreenChange: 'mozfullscreenchange', + requestFullscreen: 'mozRequestFullScreen', + exitFullscreen: 'mozCancelFullScreen' + }; + } + else if (container.webkitRequestFullScreen) { + this.browserProps = { + fullscreenChange: 'webkitfullscreenchange', + requestFullscreen: 'webkitRequestFullScreen', + exitFullscreen: 'webkitExitFullscreen' + }; + } + else if (container.msRequestFullscreen) { + this.browserProps = { + fullscreenChange: 'MSFullscreenChange', + requestFullscreen: 'msRequestFullscreen', + exitFullscreen: 'msExitFullscreen' + }; + } + } + } + /* * + * + * Functions + * + * */ + /** + * Stops displaying the chart in fullscreen mode. + * Exporting module required. + * + * @since 8.0.1 + * + * @function Highcharts.Fullscreen#close + * @return {void} + * @requires modules/full-screen + */ + Fullscreen.prototype.close = function () { + var fullscreen = this, chart = fullscreen.chart; + // Don't fire exitFullscreen() when user exited using 'Escape' button. + if (fullscreen.isOpen && + fullscreen.browserProps && + chart.container.ownerDocument instanceof Document) { + chart.container.ownerDocument[fullscreen.browserProps.exitFullscreen](); + } + // Unbind event as it's necessary only before exiting from fullscreen. + if (fullscreen.unbindFullscreenEvent) { + fullscreen.unbindFullscreenEvent(); + } + fullscreen.isOpen = false; + fullscreen.setButtonText(); + }; + /** + * Displays the chart in fullscreen mode. + * When fired customly by user before exporting context button is created, + * button's text will not be replaced - it's on the user side. + * Exporting module required. + * + * @since 8.0.1 + * + * @function Highcharts.Fullscreen#open + * @return {void} + * @requires modules/full-screen + */ + Fullscreen.prototype.open = function () { + var fullscreen = this, chart = fullscreen.chart; + // Handle exitFullscreen() method when user clicks 'Escape' button. + if (fullscreen.browserProps) { + fullscreen.unbindFullscreenEvent = addEvent(chart.container.ownerDocument, // chart's document + fullscreen.browserProps.fullscreenChange, function () { + // Handle lack of async of browser's fullScreenChange event. + if (fullscreen.isOpen) { + fullscreen.isOpen = false; + fullscreen.close(); + } + else { + fullscreen.isOpen = true; + fullscreen.setButtonText(); + } + }); + var promise = chart.renderTo[fullscreen.browserProps.requestFullscreen](); + if (promise) { + // No dot notation because of IE8 compatibility + promise['catch'](function () { + alert(// eslint-disable-line no-alert + 'Full screen is not supported inside a frame.'); + }); + } + addEvent(chart, 'destroy', fullscreen.unbindFullscreenEvent); + } + }; + /** + * Replaces the exporting context button's text when toogling the + * fullscreen mode. + * + * @private + * + * @since 8.0.1 + * + * @requires modules/full-screen + * @return {void} + */ + Fullscreen.prototype.setButtonText = function () { + var _a; + var chart = this.chart, exportDivElements = chart.exportDivElements, exportingOptions = chart.options.exporting, menuItems = (_a = exportingOptions === null || exportingOptions === void 0 ? void 0 : exportingOptions.buttons) === null || _a === void 0 ? void 0 : _a.contextButton.menuItems, lang = chart.options.lang; + if ((exportingOptions === null || exportingOptions === void 0 ? void 0 : exportingOptions.menuItemDefinitions) && (lang === null || lang === void 0 ? void 0 : lang.exitFullscreen) && + lang.viewFullscreen && + menuItems && + exportDivElements && + exportDivElements.length) { + exportDivElements[menuItems.indexOf('viewFullscreen')] + .innerHTML = !this.isOpen ? + (exportingOptions.menuItemDefinitions.viewFullscreen.text || + lang.viewFullscreen) : lang.exitFullscreen; + } + }; + /** + * Toggles displaying the chart in fullscreen mode. + * By default, when the exporting module is enabled, a context button with + * a drop down menu in the upper right corner accesses this function. + * Exporting module required. + * + * @since 8.0.1 + * + * @sample highcharts/members/chart-togglefullscreen/ + * Toggle fullscreen mode from a HTML button + * + * @function Highcharts.Fullscreen#toggle + * @requires modules/full-screen + */ + Fullscreen.prototype.toggle = function () { + var fullscreen = this; + if (!fullscreen.isOpen) { + fullscreen.open(); + } + else { + fullscreen.close(); + } + }; + return Fullscreen; + }()); + H.Fullscreen = Fullscreen; + // Initialize fullscreen + addEvent(Chart, 'beforeRender', function () { + /** + * @name Highcharts.Chart#fullscreen + * @type {Highcharts.Fullscreen} + * @requires modules/full-screen + */ + this.fullscreen = new H.Fullscreen(this); + }); + + return H.Fullscreen; + }); + _registerModule(_modules, 'masters/modules/full-screen.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/funnel.js b/librerias/gantt/code/modules/funnel.js new file mode 100644 index 0000000..8e0e968 --- /dev/null +++ b/librerias/gantt/code/modules/funnel.js @@ -0,0 +1,18 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Highcharts funnel module + + (c) 2010-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/funnel",["highcharts"],function(e){b(e);b.Highcharts=e;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function e(b,l,e,B){b.hasOwnProperty(l)||(b[l]=B.apply(null,e))}b=b?b._modules:{};e(b,"modules/funnel.src.js",[b["parts/Globals.js"],b["parts/Utilities.js"]],function(b,l){var e=l.isArray,B=l.pick;l=b.seriesType;var F= +b.seriesTypes,K=b.fireEvent,G=b.addEvent,I=b.noop;l("funnel","pie",{animation:!1,center:["50%","50%"],width:"90%",neckWidth:"30%",height:"100%",neckHeight:"25%",reversed:!1,size:!0,dataLabels:{connectorWidth:1,verticalAlign:"middle"},states:{select:{color:"#cccccc",borderColor:"#000000"}}},{animate:I,translate:function(){function a(b,a){return/%$/.test(b)?a*parseInt(b,10)/100:parseInt(b,10)}var b=0,d=this,g=d.chart,f=d.options,k=f.reversed,c=f.ignoreHiddenPoint,v=g.plotWidth;g=g.plotHeight;var e= +0,l=f.center,h=a(l[0],v),m=a(l[1],g),F=a(f.width,v),r,t=a(f.height,g),y=a(f.neckWidth,v),H=a(f.neckHeight,g),z=m-t/2+t-H;v=d.data;var C,D,G="left"===f.dataLabels.position?1:0,A,n,E,u,p,x,q;d.getWidthAt=function(b){var a=m-t/2;return b>z||t===H?y:y+(F-y)*(1-(b-a)/(t-H))};d.getX=function(b,a,c){return h+(a?-1:1)*(d.getWidthAt(k?2*m-b:b)/2+c.labelDistance)};d.center=[h,m,t];d.centerX=h;v.forEach(function(a){c&&!1===a.visible||(b+=a.y)});v.forEach(function(a){q=null;D=b?a.y/b:0;n=m-t/2+e*t;p=n+D*t;r= +d.getWidthAt(n);A=h-r/2;E=A+r;r=d.getWidthAt(p);u=h-r/2;x=u+r;n>z?(A=u=h-y/2,E=x=h+y/2):p>z&&(q=p,r=d.getWidthAt(z),u=h-r/2,x=u+r,p=z);k&&(n=2*m-n,p=2*m-p,null!==q&&(q=2*m-q));C=[["M",A,n],["L",E,n],["L",x,p]];null!==q&&C.push(["L",x,q],["L",u,q]);C.push(["L",u,p],["Z"]);a.shapeType="path";a.shapeArgs={d:C};a.percentage=100*D;a.plotX=h;a.plotY=(n+(q||p))/2;a.tooltipPos=[h,a.plotY];a.dlBox={x:u,y:n,topWidth:E-A,bottomWidth:x-u,height:Math.abs(B(q,p)-n),width:NaN};a.slice=I;a.half=G;c&&!1===a.visible|| +(e+=D)});K(d,"afterTranslate")},sortByAngle:function(a){a.sort(function(a,b){return a.plotY-b.plotY})},drawDataLabels:function(){var a=this.data,b=this.options.dataLabels.distance,d,g=a.length;for(this.center[2]-=2*b;g--;){var f=a[g];var k=(d=f.half)?1:-1;var c=f.plotY;f.labelDistance=B(f.options.dataLabels&&f.options.dataLabels.distance,b);this.maxLabelDistance=Math.max(f.labelDistance,this.maxLabelDistance||0);var e=this.getX(c,d,f);f.labelPosition={natural:{x:0,y:c},"final":{},alignment:d?"right": +"left",connectorPosition:{breakAt:{x:e+(f.labelDistance-5)*k,y:c},touchingSliceAt:{x:e+f.labelDistance*k,y:c}}}}F[this.options.dataLabels.inside?"column":"pie"].prototype.drawDataLabels.call(this)},alignDataLabel:function(a,e,d,g,f){var k=a.series;g=k.options.reversed;var c=a.dlBox||a.shapeArgs,l=d.align,w=d.verticalAlign,J=((k.options||{}).dataLabels||{}).inside,h=k.center[1];k=k.getWidthAt((g?2*h-a.plotY:a.plotY)-c.height/2+e.height);k="middle"===w?(c.topWidth-c.bottomWidth)/4:(k-c.bottomWidth)/ +2;h=c.y;var m=c.x;"middle"===w?h=c.y-c.height/2+e.height/2:"top"===w&&(h=c.y-c.height+e.height+d.padding);if("top"===w&&!g||"bottom"===w&&g||"middle"===w)"right"===l?m=c.x-d.padding+k:"left"===l&&(m=c.x+d.padding-k);g={x:m,y:g?h-c.height:h,width:c.bottomWidth,height:c.height};d.verticalAlign="bottom";J&&!a.visible||b.Series.prototype.alignDataLabel.call(this,a,e,d,g,f);J&&(!a.visible&&a.dataLabel&&(a.dataLabel.placed=!1),a.contrastColor&&e.css({color:a.contrastColor}))}});G(b.Chart,"afterHideAllOverlappingLabels", +function(){this.series.forEach(function(a){var b=a.options&&a.options.dataLabels;e(b)&&(b=b[0]);a.is("pie")&&a.placeDataLabels&&b&&!b.inside&&a.placeDataLabels()})});l("pyramid","funnel",{neckWidth:"0%",neckHeight:"0%",reversed:!0});""});e(b,"masters/modules/funnel.src.js",[],function(){})}); +//# sourceMappingURL=funnel.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/funnel.js.map b/librerias/gantt/code/modules/funnel.js.map new file mode 100644 index 0000000..898014b --- /dev/null +++ b/librerias/gantt/code/modules/funnel.js.map @@ -0,0 +1 @@ +{"version":3,"file":"funnel.js.map","lineCount":17,"mappings":"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","sources":["funnel.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","U","isArray","pick","seriesType","seriesTypes","fireEvent","addEvent","noop","animation","center","width","neckWidth","height","neckHeight","reversed","size","dataLabels","connectorWidth","verticalAlign","states","select","color","borderColor","animate","translate","getLength","length","relativeTo","test","parseInt","sum","series","chart","options","ignoreHiddenPoint","plotWidth","plotHeight","cumulative","centerX","centerY","tempWidth","neckY","data","fraction","half","position","x1","y1","x2","x3","y3","x4","y5","getWidthAt","series.getWidthAt","y","top","getX","series.getX","point","labelDistance","forEach","visible","push","shapeType","shapeArgs","d","percentage","plotX","plotY","tooltipPos","dlBox","x","topWidth","bottomWidth","Math","abs","NaN","slice","sortByAngle","points","sort","a","b","drawDataLabels","distance","leftSide","i","sign","maxLabelDistance","max","labelPosition","natural","alignment","connectorPosition","breakAt","touchingSliceAt","inside","prototype","call","alignDataLabel","dataLabel","alignTo","isNew","align","widthAtLabel","pointPlotY","offset","padding","Series","placed","contrastColor","css","Chart","dataLabelsOptions","is","placeDataLabels"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/funnel.src.js b/librerias/gantt/code/modules/funnel.src.js new file mode 100644 index 0000000..c3d8138 --- /dev/null +++ b/librerias/gantt/code/modules/funnel.src.js @@ -0,0 +1,578 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * Highcharts funnel module + * + * (c) 2010-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/funnel', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'modules/funnel.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (Highcharts, U) { + /* * + * + * Highcharts funnel module + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /* eslint indent: 0 */ + var isArray = U.isArray, pick = U.pick; + // create shortcuts + var seriesType = Highcharts.seriesType, seriesTypes = Highcharts.seriesTypes, fireEvent = Highcharts.fireEvent, addEvent = Highcharts.addEvent, noop = Highcharts.noop; + /** + * @private + * @class + * @name Highcharts.seriesTypes.funnel + * + * @augments Highcharts.Series + */ + seriesType('funnel', 'pie', + /** + * Funnel charts are a type of chart often used to visualize stages in a + * sales project, where the top are the initial stages with the most + * clients. It requires that the modules/funnel.js file is loaded. + * + * @sample highcharts/demo/funnel/ + * Funnel demo + * + * @extends plotOptions.pie + * @excluding innerSize,size,dataSorting + * @product highcharts + * @requires modules/funnel + * @optionparent plotOptions.funnel + */ + { + /** + * Initial animation is by default disabled for the funnel chart. + */ + animation: false, + /** + * The center of the series. By default, it is centered in the middle + * of the plot area, so it fills the plot area height. + * + * @type {Array} + * @default ["50%", "50%"] + * @since 3.0 + */ + center: ['50%', '50%'], + /** + * The width of the funnel compared to the width of the plot area, + * or the pixel width if it is a number. + * + * @type {number|string} + * @since 3.0 + */ + width: '90%', + /** + * The width of the neck, the lower part of the funnel. A number defines + * pixel width, a percentage string defines a percentage of the plot + * area width. + * + * @sample {highcharts} highcharts/demo/funnel/ + * Funnel demo + * + * @type {number|string} + * @since 3.0 + */ + neckWidth: '30%', + /** + * The height of the funnel or pyramid. If it is a number it defines + * the pixel height, if it is a percentage string it is the percentage + * of the plot area height. + * + * @sample {highcharts} highcharts/demo/funnel/ + * Funnel demo + * + * @type {number|string} + * @since 3.0 + */ + height: '100%', + /** + * The height of the neck, the lower part of the funnel. A number + * defines pixel width, a percentage string defines a percentage of the + * plot area height. + * + * @type {number|string} + */ + neckHeight: '25%', + /** + * A reversed funnel has the widest area down. A reversed funnel with + * no neck width and neck height is a pyramid. + * + * @since 3.0.10 + */ + reversed: false, + /** + * To avoid adapting the data label size in Pie.drawDataLabels. + * @ignore-option + */ + size: true, + dataLabels: { + connectorWidth: 1, + verticalAlign: 'middle' + }, + /** + * Options for the series states. + */ + states: { + /** + * @excluding halo, marker, lineWidth, lineWidthPlus + * @apioption plotOptions.funnel.states.hover + */ + /** + * Options for a selected funnel item. + * + * @excluding halo, marker, lineWidth, lineWidthPlus + */ + select: { + /** + * A specific color for the selected point. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + color: '#cccccc', + /** + * A specific border color for the selected point. + * + * @type {Highcharts.ColorString} + */ + borderColor: '#000000' + } + } + }, + // Properties + { + animate: noop, + // Overrides the pie translate method + translate: function () { + var sum = 0, series = this, chart = series.chart, options = series.options, reversed = options.reversed, ignoreHiddenPoint = options.ignoreHiddenPoint, plotWidth = chart.plotWidth, plotHeight = chart.plotHeight, cumulative = 0, // start at top + center = options.center, centerX = getLength(center[0], plotWidth), centerY = getLength(center[1], plotHeight), width = getLength(options.width, plotWidth), tempWidth, height = getLength(options.height, plotHeight), neckWidth = getLength(options.neckWidth, plotWidth), neckHeight = getLength(options.neckHeight, plotHeight), neckY = (centerY - height / 2) + height - neckHeight, data = series.data, path, fraction, half = (options.dataLabels.position === 'left' ? + 1 : + 0), x1, y1, x2, x3, y3, x4, y5; + /** + * Get positions - either an integer or a percentage string must be + * given. + * @private + * @param {number|string|undefined} length + * Length + * @param {number} relativeTo + * Relative factor + * @return {number} + * Relative position + */ + function getLength(length, relativeTo) { + return (/%$/).test(length) ? + relativeTo * parseInt(length, 10) / 100 : + parseInt(length, 10); + } + series.getWidthAt = function (y) { + var top = (centerY - height / 2); + return (y > neckY || height === neckHeight) ? + neckWidth : + neckWidth + (width - neckWidth) * + (1 - (y - top) / (height - neckHeight)); + }; + series.getX = function (y, half, point) { + return centerX + (half ? -1 : 1) * + ((series.getWidthAt(reversed ? 2 * centerY - y : y) / 2) + + point.labelDistance); + }; + // Expose + series.center = [centerX, centerY, height]; + series.centerX = centerX; + /* + Individual point coordinate naming: + + x1,y1 _________________ x2,y1 + \ / + \ / + \ / + \ / + \ / + x3,y3 _________ x4,y3 + + Additional for the base of the neck: + + | | + | | + | | + x3,y5 _________ x4,y5 + + */ + // get the total sum + data.forEach(function (point) { + if (!ignoreHiddenPoint || point.visible !== false) { + sum += point.y; + } + }); + data.forEach(function (point) { + // set start and end positions + y5 = null; + fraction = sum ? point.y / sum : 0; + y1 = centerY - height / 2 + cumulative * height; + y3 = y1 + fraction * height; + tempWidth = series.getWidthAt(y1); + x1 = centerX - tempWidth / 2; + x2 = x1 + tempWidth; + tempWidth = series.getWidthAt(y3); + x3 = centerX - tempWidth / 2; + x4 = x3 + tempWidth; + // the entire point is within the neck + if (y1 > neckY) { + x1 = x3 = centerX - neckWidth / 2; + x2 = x4 = centerX + neckWidth / 2; + // the base of the neck + } + else if (y3 > neckY) { + y5 = y3; + tempWidth = series.getWidthAt(neckY); + x3 = centerX - tempWidth / 2; + x4 = x3 + tempWidth; + y3 = neckY; + } + if (reversed) { + y1 = 2 * centerY - y1; + y3 = 2 * centerY - y3; + if (y5 !== null) { + y5 = 2 * centerY - y5; + } + } + // save the path + path = [ + ['M', x1, y1], + ['L', x2, y1], + ['L', x4, y3] + ]; + if (y5 !== null) { + path.push(['L', x4, y5], ['L', x3, y5]); + } + path.push(['L', x3, y3], ['Z']); + // prepare for using shared dr + point.shapeType = 'path'; + point.shapeArgs = { d: path }; + // for tooltips and data labels + point.percentage = fraction * 100; + point.plotX = centerX; + point.plotY = (y1 + (y5 || y3)) / 2; + // Placement of tooltips and data labels + point.tooltipPos = [ + centerX, + point.plotY + ]; + point.dlBox = { + x: x3, + y: y1, + topWidth: x2 - x1, + bottomWidth: x4 - x3, + height: Math.abs(pick(y5, y3) - y1), + width: NaN + }; + // Slice is a noop on funnel points + point.slice = noop; + // Mimicking pie data label placement logic + point.half = half; + if (!ignoreHiddenPoint || point.visible !== false) { + cumulative += fraction; + } + }); + fireEvent(series, 'afterTranslate'); + }, + // Funnel items don't have angles (#2289) + sortByAngle: function (points) { + points.sort(function (a, b) { + return a.plotY - b.plotY; + }); + }, + // Extend the pie data label method + drawDataLabels: function () { + var series = this, data = series.data, labelDistance = series.options.dataLabels.distance, leftSide, sign, point, i = data.length, x, y; + // In the original pie label anticollision logic, the slots are + // distributed from one labelDistance above to one labelDistance + // below the pie. In funnels we don't want this. + series.center[2] -= 2 * labelDistance; + // Set the label position array for each point. + while (i--) { + point = data[i]; + leftSide = point.half; + sign = leftSide ? 1 : -1; + y = point.plotY; + point.labelDistance = pick(point.options.dataLabels && + point.options.dataLabels.distance, labelDistance); + series.maxLabelDistance = Math.max(point.labelDistance, series.maxLabelDistance || 0); + x = series.getX(y, leftSide, point); + // set the anchor point for data labels + point.labelPosition = { + // initial position of the data label - it's utilized for + // finding the final position for the label + natural: { + x: 0, + y: y + }, + 'final': { + // used for generating connector path - + // initialized later in drawDataLabels function + // x: undefined, + // y: undefined + }, + // left - funnel on the left side of the data label + // right - funnel on the right side of the data label + alignment: leftSide ? 'right' : 'left', + connectorPosition: { + breakAt: { + x: x + (point.labelDistance - 5) * sign, + y: y + }, + touchingSliceAt: { + x: x + point.labelDistance * sign, + y: y + } + } + }; + } + seriesTypes[series.options.dataLabels.inside ? 'column' : 'pie'].prototype.drawDataLabels.call(this); + }, + alignDataLabel: function (point, dataLabel, options, alignTo, isNew) { + var series = point.series, reversed = series.options.reversed, dlBox = point.dlBox || point.shapeArgs, align = options.align, verticalAlign = options.verticalAlign, inside = ((series.options || {}).dataLabels || {}).inside, centerY = series.center[1], pointPlotY = (reversed ? + 2 * centerY - point.plotY : + point.plotY), widthAtLabel = series.getWidthAt(pointPlotY - dlBox.height / 2 + + dataLabel.height), offset = verticalAlign === 'middle' ? + (dlBox.topWidth - dlBox.bottomWidth) / 4 : + (widthAtLabel - dlBox.bottomWidth) / 2, y = dlBox.y, x = dlBox.x; + if (verticalAlign === 'middle') { + y = dlBox.y - dlBox.height / 2 + dataLabel.height / 2; + } + else if (verticalAlign === 'top') { + y = dlBox.y - dlBox.height + dataLabel.height + + options.padding; + } + if (verticalAlign === 'top' && !reversed || + verticalAlign === 'bottom' && reversed || + verticalAlign === 'middle') { + if (align === 'right') { + x = dlBox.x - options.padding + offset; + } + else if (align === 'left') { + x = dlBox.x + options.padding - offset; + } + } + alignTo = { + x: x, + y: reversed ? y - dlBox.height : y, + width: dlBox.bottomWidth, + height: dlBox.height + }; + options.verticalAlign = 'bottom'; + // Call the parent method + if (!inside || point.visible) { + Highcharts.Series.prototype.alignDataLabel.call(this, point, dataLabel, options, alignTo, isNew); + } + if (inside) { + if (!point.visible && point.dataLabel) { + // Avoid animation from top + point.dataLabel.placed = false; + } + // If label is inside and we have contrast, set it: + if (point.contrastColor) { + dataLabel.css({ + color: point.contrastColor + }); + } + } + } + }); + /* eslint-disable no-invalid-this */ + addEvent(Highcharts.Chart, 'afterHideAllOverlappingLabels', function () { + this.series.forEach(function (series) { + var dataLabelsOptions = series.options && series.options.dataLabels; + if (isArray(dataLabelsOptions)) { + dataLabelsOptions = dataLabelsOptions[0]; + } + if (series.is('pie') && + series.placeDataLabels && + dataLabelsOptions && + !dataLabelsOptions.inside) { + series.placeDataLabels(); + } + }); + }); + /** + * A `funnel` series. If the [type](#series.funnel.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.funnel + * @excluding dataParser, dataURL, stack, xAxis, yAxis, dataSorting + * @product highcharts + * @requires modules/funnel + * @apioption series.funnel + */ + /** + * An array of data points for the series. For the `funnel` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values + * will be interpreted as `y` options. Example: + * + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of data + * points exceeds the series' [turboThreshold](#series.funnel.turboThreshold), + * this option is not available. + * + * ```js + * data: [{ + * y: 3, + * name: "Point2", + * color: "#00FF00" + * }, { + * y: 1, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array} + * @extends series.pie.data + * @excluding sliced + * @product highcharts + * @apioption series.funnel.data + */ + /** + * Pyramid series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.pyramid + * + * @augments Highcharts.Series + */ + seriesType('pyramid', 'funnel', + /** + * A pyramid series is a special type of funnel, without neck and reversed + * by default. + * + * @sample highcharts/demo/pyramid/ + * Pyramid chart + * + * @extends plotOptions.funnel + * @product highcharts + * @requires modules/funnel + * @optionparent plotOptions.pyramid + */ + { + /** + * The pyramid neck width is zero by default, as opposed to the funnel, + * which shares the same layout logic. + * + * @since 3.0.10 + */ + neckWidth: '0%', + /** + * The pyramid neck width is zero by default, as opposed to the funnel, + * which shares the same layout logic. + * + * @since 3.0.10 + */ + neckHeight: '0%', + /** + * The pyramid is reversed by default, as opposed to the funnel, which + * shares the layout engine, and is not reversed. + * + * @since 3.0.10 + */ + reversed: true + }); + /** + * A `pyramid` series. If the [type](#series.pyramid.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.pyramid + * @excluding dataParser, dataURL, stack, xAxis, yAxis, dataSorting + * @product highcharts + * @requires modules/funnel + * @apioption series.pyramid + */ + /** + * An array of data points for the series. For the `pyramid` series + * type, points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.pyramid.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * y: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * y: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array} + * @extends series.pie.data + * @excluding sliced + * @product highcharts + * @apioption series.pyramid.data + */ + ''; // adds doclets above into transpiled file + + }); + _registerModule(_modules, 'masters/modules/funnel.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/funnel3d.js b/librerias/gantt/code/modules/funnel3d.js new file mode 100644 index 0000000..bd9c7c0 --- /dev/null +++ b/librerias/gantt/code/modules/funnel3d.js @@ -0,0 +1,26 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Highcharts funnel module + + (c) 2010-2019 Kacper Madej + + License: www.highcharts.com/license +*/ +(function(d){"object"===typeof module&&module.exports?(d["default"]=d,module.exports=d):"function"===typeof define&&define.amd?define("highcharts/modules/funnel3d",["highcharts","highcharts/highcharts-3d","highcharts/modules/cylinder"],function(t){d(t);d.Highcharts=t;return d}):d("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(d){function t(d,m,l,h){d.hasOwnProperty(m)||(d[m]=h.apply(null,l))}d=d?d._modules:{};t(d,"modules/funnel3d.src.js",[d["parts/Globals.js"],d["parts/Color.js"], +d["parts/Utilities.js"]],function(d,m,l){var h=m.parse,t=l.error,D=l.extend,k=l.merge,B=l.pick,v=l.relativeLength;l=l.seriesType;var H=d.charts,J=d.seriesTypes;m=d.Renderer.prototype;var K=m.cuboidPath;l("funnel3d","column",{center:["50%","50%"],width:"90%",neckWidth:"30%",height:"100%",neckHeight:"25%",reversed:!1,gradientForSides:!0,animation:!1,edgeWidth:0,colorByPoint:!0,showInLegend:!1,dataLabels:{align:"right",crop:!1,inside:!1,overflow:"allow"}},{bindAxes:function(){d.Series.prototype.bindAxes.apply(this, +arguments);D(this.xAxis.options,{gridLineWidth:0,lineWidth:0,title:null,tickPositions:[]});D(this.yAxis.options,{gridLineWidth:0,title:null,labels:{enabled:!1}})},translate3dShapes:d.noop,translate:function(){d.Series.prototype.translate.apply(this,arguments);var a=0,b=this.chart,c=this.options,g=c.reversed,u=c.ignoreHiddenPoint,e=b.plotWidth,E=b.plotHeight,f=0,I=c.center,w=v(I[0],e),r=v(I[1],E),l=v(c.width,e),p,k,n=v(c.height,E),m=v(c.neckWidth,e),t=v(c.neckHeight,E),h=r-n/2+n-t;e=this.data;var z, +F,x,A,G,C,q;this.getWidthAt=k=function(b){var a=r-n/2;return b>h||n===t?m:m+(l-m)*(1-(b-a)/(n-t))};this.center=[w,r,n];this.centerX=w;e.forEach(function(b){u&&!1===b.visible||(a+=b.y)});e.forEach(function(e){G=null;z=a?e.y/a:0;x=r-n/2+f*n;A=x+z*n;p=k(x);C=A-x;q={gradientForSides:B(e.options.gradientForSides,c.gradientForSides),x:w,y:x,height:C,width:p,z:1,top:{width:p}};p=k(A);q.bottom={fraction:z,width:p};x>=h?q.isCylinder=!0:A>h&&(G=A,p=k(h),A=h,q.bottom.width=p,q.middle={fraction:C?(h-x)/C:0,width:p}); +g&&(q.y=x=r+n/2-(f+z)*n,q.middle&&(q.middle.fraction=1-(C?q.middle.fraction:0)),p=q.width,q.width=q.bottom.width,q.bottom.width=p);e.shapeArgs=D(e.shapeArgs,q);e.percentage=100*z;e.plotX=w;e.plotY=g?r+n/2-(f+z/2)*n:(x+(G||A))/2;F=d.perspective([{x:w,y:e.plotY,z:g?-(l-k(e.plotY))/2:-k(e.plotY)/2}],b,!0)[0];e.tooltipPos=[F.x,F.y];e.dlBoxRaw={x:w,width:k(e.plotY),y:x,bottom:q.height,fullWidth:l};u&&!1===e.visible||(f+=z)})},alignDataLabel:function(a,b,c){var g=a.dlBoxRaw,u=this.chart.inverted,e=a.plotY> +B(this.translatedThreshold,this.yAxis.len),d=B(c.inside,!!this.options.stacking),f={x:g.x,y:g.y,height:0};c.align=B(c.align,!u||d?"center":e?"right":"left");c.verticalAlign=B(c.verticalAlign,u||d?"middle":e?"top":"bottom");"top"!==c.verticalAlign&&(f.y+=g.bottom/("bottom"===c.verticalAlign?1:2));f.width=this.getWidthAt(f.y);this.options.reversed&&(f.width=g.fullWidth-f.width);d?f.x-=f.width/2:"left"===c.align?(c.align="right",f.x-=1.5*f.width):"right"===c.align?(c.align="left",f.x+=f.width/2):f.x-= +f.width/2;a.dlBox=f;J.column.prototype.alignDataLabel.apply(this,arguments)}},{shapeType:"funnel3d",hasNewShapeType:d.seriesTypes.column.prototype.pointClass.prototype.hasNewShapeType});l=k(m.elements3d.cuboid,{parts:"top bottom frontUpper backUpper frontLower backLower rightUpper rightLower".split(" "),mainParts:["top","bottom"],sideGroups:["upperGroup","lowerGroup"],sideParts:{upperGroup:["frontUpper","backUpper","rightUpper"],lowerGroup:["frontLower","backLower","rightLower"]},pathType:"funnel3d", +opacitySetter:function(a){var b=this,c=b.parts,g=d.charts[b.renderer.chartIndex],u="group-opacity-"+a+"-"+g.index;b.parts=b.mainParts;b.singleSetterForParts("opacity",a);b.parts=c;g.renderer.filterId||(g.renderer.definition({tagName:"filter",id:u,children:[{tagName:"feComponentTransfer",children:[{tagName:"feFuncA",type:"table",tableValues:"0 "+a}]}]}),b.sideGroups.forEach(function(a){b[a].attr({filter:"url(#"+u+")"})}),b.renderer.styledMode&&(g.renderer.definition({tagName:"style",textContent:".highcharts-"+ +u+" {filter:url(#"+u+")}"}),b.sideGroups.forEach(function(b){b.addClass("highcharts-"+u)})));return b},fillSetter:function(a){var b=this,c=h(a),g=c.rgba[3],d={top:h(a).brighten(.1).get(),bottom:h(a).brighten(-.2).get()};1>g?(c.rgba[3]=1,c=c.get("rgb"),b.attr({opacity:g})):c=a;c.linearGradient||c.radialGradient||!b.gradientForSides||(c={linearGradient:{x1:0,x2:1,y1:1,y2:1},stops:[[0,h(a).brighten(-.2).get()],[.5,a],[1,h(a).brighten(-.2).get()]]});c.linearGradient?b.sideGroups.forEach(function(a){var e= +b[a].gradientBox,f=c.linearGradient,g=k(c,{linearGradient:{x1:e.x+f.x1*e.width,y1:e.y+f.y1*e.height,x2:e.x+f.x2*e.width,y2:e.y+f.y2*e.height}});b.sideParts[a].forEach(function(b){d[b]=g})}):(k(!0,d,{frontUpper:c,backUpper:c,rightUpper:c,frontLower:c,backLower:c,rightLower:c}),c.radialGradient&&b.sideGroups.forEach(function(a){var c=b[a].gradientBox,e=c.x+c.width/2,g=c.y+c.height/2,d=Math.min(c.width,c.height);b.sideParts[a].forEach(function(a){b[a].setRadialReference([e,g,d])})}));b.singleSetterForParts("fill", +null,d);b.color=b.fill=a;c.linearGradient&&[b.frontLower,b.frontUpper].forEach(function(a){(a=(a=a.element)&&b.renderer.gradients[a.gradient])&&"userSpaceOnUse"!==a.attr("gradientUnits")&&a.attr({gradientUnits:"userSpaceOnUse"})});return b},adjustForGradient:function(){var a=this,b;a.sideGroups.forEach(function(c){var g={x:Number.MAX_VALUE,y:Number.MAX_VALUE},d={x:-Number.MAX_VALUE,y:-Number.MAX_VALUE};a.sideParts[c].forEach(function(c){b=a[c].getBBox(!0);g={x:Math.min(g.x,b.x),y:Math.min(g.y,b.y)}; +d={x:Math.max(d.x,b.x+b.width),y:Math.max(d.y,b.y+b.height)}});a[c].gradientBox={x:g.x,width:d.x-g.x,y:g.y,height:d.y-g.y}})},zIndexSetter:function(){this.finishedOnAdd&&this.adjustForGradient();return this.renderer.Element.prototype.zIndexSetter.apply(this,arguments)},onAdd:function(){this.adjustForGradient();this.finishedOnAdd=!0}});m.elements3d.funnel3d=l;m.funnel3d=function(a){var b=this.element3d("funnel3d",a),c=this.styledMode,d={"stroke-width":1,stroke:"none"};b.upperGroup=this.g("funnel3d-upper-group").attr({zIndex:b.frontUpper.zIndex}).add(b); +[b.frontUpper,b.backUpper,b.rightUpper].forEach(function(a){c||a.attr(d);a.add(b.upperGroup)});b.lowerGroup=this.g("funnel3d-lower-group").attr({zIndex:b.frontLower.zIndex}).add(b);[b.frontLower,b.backLower,b.rightLower].forEach(function(a){c||a.attr(d);a.add(b.lowerGroup)});b.gradientForSides=a.gradientForSides;return b};m.funnel3dPath=function(a){this.getCylinderEnd||t("A required Highcharts module is missing: cylinder.js",!0,H[this.chartIndex]);var b=H[this.chartIndex],c=a.alphaCorrection=90-Math.abs(b.options.chart.options3d.alpha% +180-90),d=K.call(this,k(a,{depth:a.width,width:(a.width+a.bottom.width)/2})),l=d.isTop,e=!d.isFront,m=!!a.middle,f=this.getCylinderEnd(b,k(a,{x:a.x-a.width/2,z:a.z-a.width/2,alphaCorrection:c})),h=a.bottom.width,w=k(a,{width:h,x:a.x-h/2,z:a.z-h/2,alphaCorrection:c}),r=this.getCylinderEnd(b,w,!0),y=h,p=w,v=r,n=r;m&&(y=a.middle.width,p=k(a,{y:a.y+a.middle.fraction*a.height,width:y,x:a.x-y/2,z:a.z-y/2}),v=this.getCylinderEnd(b,p,!1),n=this.getCylinderEnd(b,p,!1));d={top:f,bottom:r,frontUpper:this.getCylinderFront(f, +v),zIndexes:{group:d.zIndexes.group,top:0!==l?0:3,bottom:1!==l?0:3,frontUpper:e?2:1,backUpper:e?1:2,rightUpper:e?2:1}};d.backUpper=this.getCylinderBack(f,v);f=1!==Math.min(y,a.width)/Math.max(y,a.width);d.rightUpper=this.getCylinderFront(this.getCylinderEnd(b,k(a,{x:a.x-a.width/2,z:a.z-a.width/2,alphaCorrection:f?-c:0}),!1),this.getCylinderEnd(b,k(p,{alphaCorrection:f?-c:0}),!m));m&&(f=1!==Math.min(y,h)/Math.max(y,h),k(!0,d,{frontLower:this.getCylinderFront(n,r),backLower:this.getCylinderBack(n,r), +rightLower:this.getCylinderFront(this.getCylinderEnd(b,k(w,{alphaCorrection:f?-c:0}),!0),this.getCylinderEnd(b,k(p,{alphaCorrection:f?-c:0}),!1)),zIndexes:{frontLower:e?2:1,backLower:e?1:2,rightLower:e?1:2}}));return d}});t(d,"masters/modules/funnel3d.src.js",[],function(){})}); +//# sourceMappingURL=funnel3d.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/funnel3d.js.map b/librerias/gantt/code/modules/funnel3d.js.map new file mode 100644 index 0000000..0b9ddff --- /dev/null +++ b/librerias/gantt/code/modules/funnel3d.js.map @@ -0,0 +1 @@ +{"version":3,"file":"funnel3d.js.map","lineCount":25,"mappings":"A;;;;;;;;;AAUC,SAAS,CAACA,CAAD,CAAU,CACM,QAAtB,GAAI,MAAOC,OAAX,EAAkCA,MAAAC,QAAlC,EACIF,CAAA,CAAQ,SAAR,CACA,CADqBA,CACrB,CAAAC,MAAAC,QAAA,CAAiBF,CAFrB,EAG6B,UAAtB,GAAI,MAAOG,OAAX,EAAoCA,MAAAC,IAApC,CACHD,MAAA,CAAO,6BAAP,CAAsC,CAAC,YAAD,CAAe,0BAAf,CAA2C,6BAA3C,CAAtC,CAAiH,QAAS,CAACE,CAAD,CAAa,CACnIL,CAAA,CAAQK,CAAR,CACAL,EAAAK,WAAA,CAAqBA,CACrB,OAAOL,EAH4H,CAAvI,CADG,CAOHA,CAAA,CAA8B,WAAtB,GAAA,MAAOK,WAAP,CAAoCA,UAApC,CAAiDC,IAAAA,EAAzD,CAXY,CAAnB,CAAA,CAaC,QAAS,CAACD,CAAD,CAAa,CAEpBE,QAASA,EAAe,CAACC,CAAD,CAAMC,CAAN,CAAYC,CAAZ,CAAkBC,CAAlB,CAAsB,CACrCH,CAAAI,eAAA,CAAmBH,CAAnB,CAAL,GACID,CAAA,CAAIC,CAAJ,CADJ,CACgBE,CAAAE,MAAA,CAAS,IAAT,CAAeH,CAAf,CADhB,CAD0C,CAD1CI,CAAAA,CAAWT,CAAA,CAAaA,CAAAS,SAAb,CAAmC,EAMlDP,EAAA,CAAgBO,CAAhB,CAA0B,yBAA1B,CAAqD,CAACA,CAAA,CAAS,kBAAT,CAAD,CAA+BA,CAAA,CAAS,gBAAT,CAA/B;AAA2DA,CAAA,CAAS,oBAAT,CAA3D,CAArD,CAAiJ,QAAS,CAACC,CAAD,CAAIC,CAAJ,CAAWC,CAAX,CAAc,CAcpK,IAAIC,EAAQF,CAAAG,MAAZ,CACIC,EAAQH,CAAAG,MADZ,CACqBC,EAASJ,CAAAI,OAD9B,CACwCC,EAAQL,CAAAK,MADhD,CACyDC,EAAON,CAAAM,KADhE,CACwEC,EAAiBP,CAAAO,eAAkBC,EAAAA,CAAaR,CAAAQ,WAf4C,KAgBhKC,EAASX,CAAAW,OAhBuJ,CAgB7IC,EAAcZ,CAAAY,YAErCC,EAAAA,CAAgBb,CAAAc,SAAAC,UAlBoJ,KAoBpKC,EAAaH,CAAAG,WAUbN,EAAA,CAAW,UAAX,CAAuB,QAAvB,CAsBA,CAEIO,OAAQ,CAAC,KAAD,CAAQ,KAAR,CAFZ,CAWIC,MAAO,KAXX,CAqBIC,UAAW,KArBf,CA+BIC,OAAQ,MA/BZ,CAyCIC,WAAY,KAzChB,CAgDIC,SAAU,CAAA,CAhDd,CAuDIC,iBAAkB,CAAA,CAvDtB,CAwDIC,UAAW,CAAA,CAxDf,CAyDIC,UAAW,CAzDf,CA0DIC,aAAc,CAAA,CA1DlB,CA2DIC,aAAc,CAAA,CA3DlB,CA4DIC,WAAY,CACRC,MAAO,OADC,CAERC,KAAM,CAAA,CAFE,CAGRC,OAAQ,CAAA,CAHA,CAIRC,SAAU,OAJF,CA5DhB,CAtBA,CAwFG,CAECC,SAAUA,QAAS,EAAG,CAClBjC,CAAAkC,OAAAnB,UAAAkB,SAAAnC,MAAA,CAAkC,IAAlC;AAAwCqC,SAAxC,CACA7B,EAAA,CAAO,IAAA8B,MAAAC,QAAP,CAA2B,CACvBC,cAAe,CADQ,CAEvBC,UAAW,CAFY,CAGvBC,MAAO,IAHgB,CAIvBC,cAAe,EAJQ,CAA3B,CAMAnC,EAAA,CAAO,IAAAoC,MAAAL,QAAP,CAA2B,CACvBC,cAAe,CADQ,CAEvBE,MAAO,IAFgB,CAGvBG,OAAQ,CACJC,QAAS,CAAA,CADL,CAHe,CAA3B,CARkB,CAFvB,CAkBCC,kBAAmB7C,CAAA8C,KAlBpB,CAmBCC,UAAWA,QAAS,EAAG,CACnB/C,CAAAkC,OAAAnB,UAAAgC,UAAAjD,MAAA,CAAmC,IAAnC,CAAyCqC,SAAzC,CADmB,KAEfa,EAAM,CAFS,CAESC,EAANC,IAAcD,MAFjB,CAE+BZ,EAA5Ba,IAAsCb,QAFzC,CAEyDf,EAAWe,CAAAf,SAFpE,CAEsF6B,EAAoBd,CAAAc,kBAF1G,CAEqIC,EAAYH,CAAAG,UAFjJ,CAEkKC,EAAaJ,CAAAI,WAF/K,CAEiMC,EAAa,CAF9M,CAGnBrC,EAASoB,CAAApB,OAHU,CAGMsC,EAAU9C,CAAA,CAAeQ,CAAA,CAAO,CAAP,CAAf,CAA0BmC,CAA1B,CAHhB,CAGsDI,EAAU/C,CAAA,CAAeQ,CAAA,CAAO,CAAP,CAAf,CAA0BoC,CAA1B,CAHhE,CAGuGnC,EAAQT,CAAA,CAAe4B,CAAAnB,MAAf,CAA8BkC,CAA9B,CAH/G,CAGyJK,CAHzJ,CAGoKC,CAHpK,CAGgLtC,EAASX,CAAA,CAAe4B,CAAAjB,OAAf,CAA+BiC,CAA/B,CAHzL,CAGqOlC,EAAYV,CAAA,CAAe4B,CAAAlB,UAAf,CAAkCiC,CAAlC,CAHjP,CAG+R/B,EAAaZ,CAAA,CAAe4B,CAAAhB,WAAf,CAAmCgC,CAAnC,CAH5S,CAG4VM,EAASH,CAATG,CAAmBvC,CAAnBuC,CAA4B,CAA5BA,CAAiCvC,CAAjCuC,CAA0CtC,CAAYuC,EAAAA,CAD/YV,IACsZU,KAHzZ,KAGsaC,CAHta;AAGgbC,CAHhb,CAKnBC,CALmB,CAKfC,CALe,CAKXC,CALW,CAOnBC,CAPmB,CAOhBC,CALmBjB,KAOtBQ,WAAA,CAAoBA,CAApB,CAAiCA,QAAS,CAACU,CAAD,CAAI,CAC1C,IAAIC,EAAOb,CAAPa,CAAiBjD,CAAjBiD,CAA0B,CAC9B,OAAQD,EAAD,CAAKT,CAAL,EAAcvC,CAAd,GAAyBC,CAAzB,CACHF,CADG,CAEHA,CAFG,EAEUD,CAFV,CAEkBC,CAFlB,GAGE,CAHF,EAGOiD,CAHP,CAGWC,CAHX,GAGmBjD,CAHnB,CAG4BC,CAH5B,EAFmC,CAPxB6B,KAetBjC,OAAA,CAAgB,CAACsC,CAAD,CAAUC,CAAV,CAAmBpC,CAAnB,CAfM8B,KAgBtBK,QAAA,CAAiBA,CAoBjBK,EAAAU,QAAA,CAAa,QAAS,CAACC,CAAD,CAAQ,CACrBpB,CAAL,EAA4C,CAAA,CAA5C,GAA0BoB,CAAAC,QAA1B,GACIxB,CADJ,EACWuB,CAAAH,EADX,CAD0B,CAA9B,CAKAR,EAAAU,QAAA,CAAa,QAAS,CAACC,CAAD,CAAQ,CAE1BN,CAAA,CAAK,IACLJ,EAAA,CAAWb,CAAA,CAAMuB,CAAAH,EAAN,CAAgBpB,CAAhB,CAAsB,CACjCe,EAAA,CAAKP,CAAL,CAAepC,CAAf,CAAwB,CAAxB,CAA4BkC,CAA5B,CAAyClC,CACzC4C,EAAA,CAAKD,CAAL,CAAUF,CAAV,CAAqBzC,CACrBqC,EAAA,CAAYC,CAAA,CAAWK,CAAX,CACZG,EAAA,CAAIF,CAAJ,CAASD,CACTI,EAAA,CAAY,CAER5C,iBAAkBf,CAAA,CAAK+D,CAAAlC,QAAAd,iBAAL,CAAqCc,CAAAd,iBAArC,CAFV,CAGRkD,EAAGlB,CAHK,CAIRa,EAAGL,CAJK,CAKR3C,OAAQ8C,CALA,CAMRhD,MAAOuC,CANC,CAORiB,EAAG,CAPK,CAQRL,IAAK,CACDnD,MAAOuC,CADN,CARG,CAYZA,EAAA,CAAYC,CAAA,CAAWM,CAAX,CACZG,EAAAQ,OAAA,CAAmB,CACfd,SAAUA,CADK,CAEf3C,MAAOuC,CAFQ,CAKfM,EAAJ,EAAUJ,CAAV,CACIQ,CAAAS,WADJ,CAC2B,CAAA,CAD3B,CAGSZ,CAHT,CAGcL,CAHd,GAKIM,CAIA,CAJKD,CAIL,CAHAP,CAGA,CAHYC,CAAA,CAAWC,CAAX,CAGZ,CAFAK,CAEA,CAFKL,CAEL,CADAQ,CAAAQ,OAAAzD,MACA,CADyBuC,CACzB,CAAAU,CAAAU,OAAA,CAAmB,CACfhB,SAAUK,CAAA,EAAKP,CAAL,CAAaI,CAAb,EAAmBG,CAAnB,CAAuB,CADlB,CAEfhD,MAAOuC,CAFQ,CATvB,CAcInC;CAAJ,GACI6C,CAAAC,EAQA,CARcL,CAQd,CARmBP,CAQnB,CAR6BpC,CAQ7B,CARsC,CAQtC,EAPKkC,CAOL,CAPkBO,CAOlB,EAP8BzC,CAO9B,CANI+C,CAAAU,OAMJ,GALIV,CAAAU,OAAAhB,SAKJ,CALgC,CAKhC,EAJSK,CAAA,CAAIC,CAAAU,OAAAhB,SAAJ,CAAgC,CAIzC,GAFAJ,CAEA,CAFYU,CAAAjD,MAEZ,CADAiD,CAAAjD,MACA,CADkBiD,CAAAQ,OAAAzD,MAClB,CAAAiD,CAAAQ,OAAAzD,MAAA,CAAyBuC,CAT7B,CAWAc,EAAAJ,UAAA,CAAkB7D,CAAA,CAAOiE,CAAAJ,UAAP,CAAwBA,CAAxB,CAElBI,EAAAO,WAAA,CAA8B,GAA9B,CAAmBjB,CACnBU,EAAAQ,MAAA,CAAcxB,CAEVgB,EAAAS,MAAA,CADA1D,CAAJ,CACkBkC,CADlB,CAC4BpC,CAD5B,CACqC,CADrC,EAESkC,CAFT,CAEsBO,CAFtB,CAEiC,CAFjC,EAEsCzC,CAFtC,EAKmB2C,CALnB,EAKyBE,CALzB,EAK+BD,CAL/B,GAKsC,CAGtCF,EAAA,CAAa9D,CAAAiF,YAAA,CAAc,CAAC,CACpBR,EAAGlB,CADiB,CAEpBa,EAAGG,CAAAS,MAFiB,CAGpBN,EAAGpD,CAAA,CACC,EAAEJ,CAAF,CAAUwC,CAAA,CAAWa,CAAAS,MAAX,CAAV,CADD,CACsC,CADtC,CAEC,CAAEtB,CAAA,CAAWa,CAAAS,MAAX,CAFH,CAE8B,CALb,CAAD,CAAd,CAML/B,CANK,CAME,CAAA,CANF,CAAA,CAMQ,CANR,CAObsB,EAAAT,WAAA,CAAmB,CAACA,CAAAW,EAAD,CAAeX,CAAAM,EAAf,CAEnBG,EAAAW,SAAA,CAAiB,CACbT,EAAGlB,CADU,CAEbrC,MAAOwC,CAAA,CAAWa,CAAAS,MAAX,CAFM,CAGbZ,EAAGL,CAHU,CAIbY,OAAQR,CAAA/C,OAJK,CAKb+D,UAAWjE,CALE,CAOZiC,EAAL,EAA4C,CAAA,CAA5C,GAA0BoB,CAAAC,QAA1B,GACIlB,CADJ,EACkBO,CADlB,CA/E0B,CAA9B,CA3CmB,CAnBxB,CAkJCuB,eAAgBA,QAAS,CAACb,CAAD,CAAQc,CAAR,CAAmBhD,CAAnB,CAA4B,CAAA,IAC9B6C,EAAWX,CAAAW,SADmB,CACHI,EAAjCpC,IAA4CD,MAAAqC,SADR,CAC+BC,EAAQhB,CAAAS,MAARO;AAAsB/E,CAAA,CAAzF0C,IAA8FsC,oBAAL,CAAzFtC,IAA0HR,MAAA+C,IAAjC,CADrD,CACyG1D,EAASvB,CAAA,CAAK6B,CAAAN,OAAL,CAAqB,CAAC,CAA5KmB,IAA6Kb,QAAAqD,SAAvB,CADlH,CACmKC,EAAQ,CACxNlB,EAAGS,CAAAT,EADqN,CAExNL,EAAGc,CAAAd,EAFqN,CAGxNhD,OAAQ,CAHgN,CAK5NiB,EAAAR,MAAA,CAAgBrB,CAAA,CAAK6B,CAAAR,MAAL,CAAoB,CAACyD,CAAD,EAAavD,CAAb,CAAsB,QAAtB,CAAiCwD,CAAA,CAAQ,OAAR,CAAkB,MAAvE,CAChBlD,EAAAuD,cAAA,CAAwBpF,CAAA,CAAK6B,CAAAuD,cAAL,CAA4BN,CAAA,EAAYvD,CAAZ,CAAqB,QAArB,CAAgCwD,CAAA,CAAQ,KAAR,CAAgB,QAA5E,CACM,MAA9B,GAAIlD,CAAAuD,cAAJ,GACID,CAAAvB,EADJ,EACec,CAAAP,OADf,EAEmC,QAA1B,GAAAtC,CAAAuD,cAAA,CAAqC,CAArC,CAAyC,CAFlD,EAIAD,EAAAzE,MAAA,CAXagC,IAWCQ,WAAA,CAAkBiC,CAAAvB,EAAlB,CAXDlB,KAYTb,QAAAf,SAAJ,GACIqE,CAAAzE,MADJ,CACkBgE,CAAAC,UADlB,CACuCQ,CAAAzE,MADvC,CAGIa,EAAJ,CACI4D,CAAAlB,EADJ,EACekB,CAAAzE,MADf,CAC6B,CAD7B,CAK0B,MAAtB,GAAImB,CAAAR,MAAJ,EACIQ,CAAAR,MACA,CADgB,OAChB,CAAA8D,CAAAlB,EAAA,EAAyB,GAAzB,CAAWkB,CAAAzE,MAFf,EAI2B,OAAtB,GAAImB,CAAAR,MAAJ,EACDQ,CAAAR,MACA,CADgB,MAChB,CAAA8D,CAAAlB,EAAA,EAAWkB,CAAAzE,MAAX,CAAyB,CAFxB,EAKDyE,CAAAlB,EALC;AAKUkB,CAAAzE,MALV,CAKwB,CAGjCqD,EAAAoB,MAAA,CAAcA,CACd/E,EAAAiF,OAAA9E,UAAAqE,eAAAtF,MAAA,CAjCaoD,IAiCb,CAA0Df,SAA1D,CAlCiD,CAlJtD,CAxFH,CA8QqE,CACjE2D,UAAW,UADsD,CAEjEC,gBAAiB/F,CAAAY,YAAAiF,OAAA9E,UAAAiF,WAAAjF,UAAAgF,gBAFgD,CA9QrE,CA4VAE,EAAA,CAAkB1F,CAAA,CAAMM,CAAAqF,WAAAC,OAAN,CAAuC,CACrDC,MAAO,4EAAA,MAAA,CAAA,GAAA,CAD8C,CAOrDC,UAAW,CAAC,KAAD,CAAQ,QAAR,CAP0C,CAQrDC,WAAY,CACR,YADQ,CACM,YADN,CARyC,CAWrDC,UAAW,CACPC,WAAY,CAAC,YAAD,CAAe,WAAf,CAA4B,YAA5B,CADL,CAEPC,WAAY,CAAC,YAAD,CAAe,WAAf,CAA4B,YAA5B,CAFL,CAX0C,CAerDC,SAAU,UAf2C;AAiBrDC,cAAeA,QAAS,CAACC,CAAD,CAAU,CAAA,IAC1BC,EAAW,IADe,CACTT,EAAQS,CAAAT,MADC,CACenD,EAAQjD,CAAAW,OAAA,CAASkG,CAAAC,SAAAC,WAAT,CADvB,CAC+DC,EAAW,gBAAXA,CAA8BJ,CAA9BI,CAAwC,GAAxCA,CAA8C/D,CAAAgE,MAE3IJ,EAAAT,MAAA,CAAiBS,CAAAR,UACjBQ,EAAAK,qBAAA,CAA8B,SAA9B,CAAyCN,CAAzC,CAEAC,EAAAT,MAAA,CAAiBA,CACZnD,EAAA6D,SAAAE,SAAL,GACI/D,CAAA6D,SAAAK,WAAA,CAA0B,CACtBC,QAAS,QADa,CAEtBC,GAAIL,CAFkB,CAGtBM,SAAU,CAAC,CACHF,QAAS,qBADN,CAEHE,SAAU,CAAC,CACHF,QAAS,SADN,CAEHG,KAAM,OAFH,CAGHC,YAAa,IAAbA,CAAoBZ,CAHjB,CAAD,CAFP,CAAD,CAHY,CAA1B,CAkBA,CANAC,CAAAP,WAAAhC,QAAA,CAA4B,QAAS,CAACmD,CAAD,CAAY,CAC7CZ,CAAA,CAASY,CAAT,CAAAC,KAAA,CAAyB,CACrBC,OAAQ,OAARA,CAAkBX,CAAlBW,CAA6B,GADR,CAAzB,CAD6C,CAAjD,CAMA,CAAId,CAAAC,SAAAc,WAAJ,GACI3E,CAAA6D,SAAAK,WAAA,CAA0B,CACtBC,QAAS,OADa,CAEtBS,YAAa,cAAbA;AAA8Bb,CAA9Ba,CACI,gBADJA,CACuBb,CADvBa,CACkC,IAHZ,CAA1B,CAKA,CAAAhB,CAAAP,WAAAhC,QAAA,CAA4B,QAAS,CAACwD,CAAD,CAAQ,CACzCA,CAAAC,SAAA,CAAe,aAAf,CAA+Bf,CAA/B,CADyC,CAA7C,CANJ,CAnBJ,CA8BA,OAAOH,EArCuB,CAjBmB,CAwDrDmB,WAAYA,QAAS,CAACC,CAAD,CAAO,CAAA,IAEpBpB,EAAW,IAFS,CAEHqB,EAAY/H,CAAA,CAAM8H,CAAN,CAFT,CAEsBE,EAAQD,CAAAE,KAAA,CAAe,CAAf,CAF9B,CAEiDC,EAAiB,CAEtFhE,IAAKlE,CAAA,CAAM8H,CAAN,CAAAK,SAAA,CAAqB,EAArB,CAAAC,IAAA,EAFiF,CAGtF5D,OAAQxE,CAAA,CAAM8H,CAAN,CAAAK,SAAA,CAAqB,GAArB,CAAAC,IAAA,EAH8E,CAK9E,EAAZ,CAAIJ,CAAJ,EACID,CAAAE,KAAA,CAAe,CAAf,CAGA,CAHoB,CAGpB,CAFAF,CAEA,CAFYA,CAAAK,IAAA,CAAc,KAAd,CAEZ,CAAA1B,CAAAa,KAAA,CAAc,CACVd,QAASuB,CADC,CAAd,CAJJ,EAUID,CAVJ,CAUgBD,CAGXC,EAAAM,eAAL,EACKN,CAAAO,eADL,EAEIlH,CAAAsF,CAAAtF,iBAFJ,GAGI2G,CAHJ,CAGgB,CACRM,eAAgB,CAAEE,GAAI,CAAN,CAASC,GAAI,CAAb,CAAgB5E,GAAI,CAApB,CAAuB6E,GAAI,CAA3B,CADR,CAERC,MAAO,CACH,CAAC,CAAD,CAAI1I,CAAA,CAAM8H,CAAN,CAAAK,SAAA,CAAqB,GAArB,CAAAC,IAAA,EAAJ,CADG,CAEH,CAAC,EAAD,CAAMN,CAAN,CAFG,CAGH,CAAC,CAAD,CAAI9H,CAAA,CAAM8H,CAAN,CAAAK,SAAA,CAAqB,GAArB,CAAAC,IAAA,EAAJ,CAHG,CAFC,CAHhB,CAaIL,EAAAM,eAAJ,CAEI3B,CAAAP,WAAAhC,QAAA,CAA4B,QAAS,CAACwE,CAAD,CAAgB,CAAA,IAC7CC;AAAMlC,CAAA,CAASiC,CAAT,CAAAE,YADuC,CACFC,EAAWf,CAAAM,eADT,CACmCU,EAAkB3I,CAAA,CAAM2H,CAAN,CAAiB,CACnHM,eAAgB,CACZE,GAAIK,CAAAtE,EAAJiE,CAAYO,CAAAP,GAAZA,CAA0BK,CAAA7H,MADd,CAEZ6C,GAAIgF,CAAA3E,EAAJL,CAAYkF,CAAAlF,GAAZA,CAA0BgF,CAAA3H,OAFd,CAGZuH,GAAII,CAAAtE,EAAJkE,CAAYM,CAAAN,GAAZA,CAA0BI,CAAA7H,MAHd,CAIZ0H,GAAIG,CAAA3E,EAAJwE,CAAYK,CAAAL,GAAZA,CAA0BG,CAAA3H,OAJd,CADmG,CAAjB,CAQtGyF,EAAAN,UAAA,CAAmBuC,CAAnB,CAAAxE,QAAA,CAA0C,QAAS,CAAC6E,CAAD,CAAW,CAC1Dd,CAAA,CAAec,CAAf,CAAA,CAA2BD,CAD+B,CAA9D,CATiD,CAArD,CAFJ,EAiBI3I,CAAA,CAAM,CAAA,CAAN,CAAY8H,CAAZ,CAA4B,CACxBe,WAAYlB,CADY,CAExBmB,UAAWnB,CAFa,CAGxBoB,WAAYpB,CAHY,CAIxBqB,WAAYrB,CAJY,CAKxBsB,UAAWtB,CALa,CAMxBuB,WAAYvB,CANY,CAA5B,CAQA,CAAIA,CAAAO,eAAJ,EACI5B,CAAAP,WAAAhC,QAAA,CAA4B,QAAS,CAACwE,CAAD,CAAgB,CAAA,IAC7CY,EAAU7C,CAAA,CAASiC,CAAT,CAAAE,YADmC,CACEzF,EAAUmG,CAAAjF,EAAVlB,CAAsBmG,CAAAxI,MAAtBqC,CAAsC,CADxC,CAC2CC,EAAUkG,CAAAtF,EAAVZ,CAAsBkG,CAAAtI,OAAtBoC,CAAuC,CADlF,CACqFmG,EAAWC,IAAAC,IAAA,CAASH,CAAAxI,MAAT,CAAwBwI,CAAAtI,OAAxB,CACjJyF,EAAAN,UAAA,CAAmBuC,CAAnB,CAAAxE,QAAA,CAA0C,QAAS,CAAC6E,CAAD,CAAW,CAC1DtC,CAAA,CAASsC,CAAT,CAAAW,mBAAA,CAAsC,CAClCvG,CADkC,CACzBC,CADyB,CAChBmG,CADgB,CAAtC,CAD0D,CAA9D,CAFiD,CAArD,CA1BR,CAoCA9C,EAAAK,qBAAA,CAA8B,MAA9B;AAAsC,IAAtC,CAA4CmB,CAA5C,CAEAxB,EAAA1G,MAAA,CAAiB0G,CAAAoB,KAAjB,CAAiCA,CAE7BC,EAAAM,eAAJ,EACI,CAAC3B,CAAA0C,WAAD,CAAsB1C,CAAAuC,WAAtB,CAAA9E,QAAA,CAAmD,QAAS,CAACyF,CAAD,CAAO,CAE/D,CADyBC,CACzB,EADIC,CACJ,CADWF,CAAAG,QACX,GADwCrD,CAAAC,SAAAqD,UAAA,CAA4BF,CAAAhB,SAA5B,CACxC,GAA2C,gBAA3C,GAAYe,CAAAtC,KAAA,CAAU,eAAV,CAAZ,EACIsC,CAAAtC,KAAA,CAAU,CACN0C,cAAe,gBADT,CAAV,CAH2D,CAAnE,CASJ,OAAOvD,EAnFiB,CAxDyB,CA6IrDwD,kBAAmBA,QAAS,EAAG,CAAA,IACvBxD,EAAW,IADY,CACNyD,CACrBzD,EAAAP,WAAAhC,QAAA,CAA4B,QAAS,CAACwE,CAAD,CAAgB,CAAA,IAE7CyB,EAAc,CACd9F,EAAG+F,MAAAC,UADW,CAEdrG,EAAGoG,MAAAC,UAFW,CAF+B,CAK9CC,EAAkB,CACjBjG,EAAG,CAAC+F,MAAAC,UADa,CAEjBrG,EAAG,CAACoG,MAAAC,UAFa,CAKrB5D,EAAAN,UAAA,CAAmBuC,CAAnB,CAAAxE,QAAA,CAA0C,QAAS,CAAC6E,CAAD,CAAW,CAE1DmB,CAAA,CADWzD,CAAAkD,CAASZ,CAATY,CACJY,QAAA,CAAa,CAAA,CAAb,CACPJ,EAAA,CAAc,CACV9F,EAAGmF,IAAAC,IAAA,CAASU,CAAA9F,EAAT,CAAwB6F,CAAA7F,EAAxB,CADO,CAEVL,EAAGwF,IAAAC,IAAA,CAASU,CAAAnG,EAAT,CAAwBkG,CAAAlG,EAAxB,CAFO,CAIdsG;CAAA,CAAkB,CACdjG,EAAGmF,IAAAgB,IAAA,CAASF,CAAAjG,EAAT,CAA4B6F,CAAA7F,EAA5B,CAAqC6F,CAAApJ,MAArC,CADW,CAEdkD,EAAGwF,IAAAgB,IAAA,CAASF,CAAAtG,EAAT,CAA4BkG,CAAAlG,EAA5B,CAAqCkG,CAAAlJ,OAArC,CAFW,CAPwC,CAA9D,CAaAyF,EAAA,CAASiC,CAAT,CAAAE,YAAA,CAAsC,CAClCvE,EAAG8F,CAAA9F,EAD+B,CAElCvD,MAAOwJ,CAAAjG,EAAPvD,CAA2BqJ,CAAA9F,EAFO,CAGlCL,EAAGmG,CAAAnG,EAH+B,CAIlChD,OAAQsJ,CAAAtG,EAARhD,CAA4BmJ,CAAAnG,EAJM,CAvBW,CAArD,CAF2B,CA7IsB,CA8KrDyG,aAAcA,QAAS,EAAG,CAGlB,IAAAC,cAAJ,EACI,IAAAT,kBAAA,EAGJ,OAAO,KAAAvD,SAAAiE,QAAAhK,UAAA8J,aAAA/K,MAAA,CAAmD,IAAnD,CAAyDqC,SAAzD,CAPe,CA9K2B,CAuLrD6I,MAAOA,QAAS,EAAG,CACf,IAAAX,kBAAA,EACA,KAAAS,cAAA,CAAqB,CAAA,CAFN,CAvLkC,CAAvC,CA4LlBjK,EAAAqF,WAAAW,SAAA,CAAoCZ,CACpCpF,EAAAgG,SAAA,CAAyBoE,QAAS,CAAC9G,CAAD,CAAY,CAAA,IACrB0C,EAANC,IAAiBoE,UAAA,CAAmB,UAAnB,CAA+B/G,CAA/B,CADU,CACiCyD,EAA5Dd,IAAyEc,WAD9C,CAG1CuD,EAAc,CACV,eAAgB,CADN,CAEVC,OAAQ,MAFE,CAKdvE,EAAAL,WAAA,CAPeM,IAOOuE,EAAA,CAAW,sBAAX,CAAA3D,KAAA,CAAwC,CAC1D4D,OAAQzE,CAAAuC,WAAAkC,OADkD,CAAxC,CAAAC,IAAA,CAEf1E,CAFe,CAGtB;CACIA,CAAAuC,WADJ,CAEIvC,CAAAwC,UAFJ,CAGIxC,CAAAyC,WAHJ,CAAAhF,QAAA,CAIU,QAAS,CAACkH,CAAD,CAAY,CACtB5D,CAAL,EACI4D,CAAA9D,KAAA,CAAeyD,CAAf,CAEJK,EAAAD,IAAA,CAAc1E,CAAAL,WAAd,CAJ2B,CAJ/B,CAUAK,EAAAJ,WAAA,CApBeK,IAoBOuE,EAAA,CAAW,sBAAX,CAAA3D,KAAA,CAAwC,CAC1D4D,OAAQzE,CAAA0C,WAAA+B,OADkD,CAAxC,CAAAC,IAAA,CAEf1E,CAFe,CAGtB,EACIA,CAAA0C,WADJ,CAEI1C,CAAA2C,UAFJ,CAGI3C,CAAA4C,WAHJ,CAAAnF,QAAA,CAIU,QAAS,CAACmH,CAAD,CAAY,CACtB7D,CAAL,EACI6D,CAAA/D,KAAA,CAAeyD,CAAf,CAEJM,EAAAF,IAAA,CAAc1E,CAAAJ,WAAd,CAJ2B,CAJ/B,CAUAI,EAAAtF,iBAAA,CAA4B4C,CAAA5C,iBAC5B,OAAOsF,EAnCmC,CA0C9ChG,EAAA6K,aAAA,CAA6BC,QAAS,CAACxH,CAAD,CAAY,CAGzC,IAAAyH,eAAL,EACIvL,CAAA,CAAM,sDAAN,CAA8D,CAAA,CAA9D,CAAoEM,CAAA,CAAO,IAAAoG,WAAP,CAApE,CAJ0C,KAMzB9D,EAAQtC,CAAA,CAAdmG,IAAqBC,WAAP,CANiB,CAS9C8E,EAAkB1H,CAAA0H,gBAAlBA,CAA8C,EAA9CA,CACIjC,IAAAkC,IAAA,CAAU7I,CAAAZ,QAAAY,MAAA8I,UAAA5D,MAAV;AAAgD,GAAhD,CAAuD,EAAvD,CAV0C,CAY9C6D,EAAahL,CAAAiL,KAAA,CANEnF,IAMF,CAA0BvG,CAAA,CAAM4D,CAAN,CAAiB,CACpD+H,MAAO/H,CAAAjD,MAD6C,CAEpDA,OAAQiD,CAAAjD,MAARA,CAA0BiD,CAAAQ,OAAAzD,MAA1BA,EAAoD,CAFA,CAAjB,CAA1B,CAZiC,CAezCiL,EAAaH,CAAAI,MAf4B,CAeVC,EAAe,CAACL,CAAAM,QAfN,CAe0BC,EAAY,CAAC,CAACpI,CAAAU,OAfxC,CAiB9CR,EAXeyC,IAWT8E,eAAA,CAAwB3I,CAAxB,CAA+B1C,CAAA,CAAM4D,CAAN,CAAiB,CAClDM,EAAGN,CAAAM,EAAHA,CAAiBN,CAAAjD,MAAjBuD,CAAmC,CADe,CAElDC,EAAGP,CAAAO,EAAHA,CAAiBP,CAAAjD,MAAjBwD,CAAmC,CAFe,CAGlDmH,gBAAiBA,CAHiC,CAAjB,CAA/B,CAjBwC,CAqBzCW,EAAcrI,CAAAQ,OAAAzD,MArB2B,CAqBHuL,EAAalM,CAAA,CAAM4D,CAAN,CAAiB,CACrEjD,MAAOsL,CAD8D,CAErE/H,EAAGN,CAAAM,EAAHA,CAAiB+H,CAAjB/H,CAA+B,CAFsC,CAGrEC,EAAGP,CAAAO,EAAHA,CAAiB8H,CAAjB9H,CAA+B,CAHsC,CAIrEmH,gBAAiBA,CAJoD,CAAjB,CArBV,CA0B1ClH,EApBWmC,IAoBF8E,eAAA,CAAwB3I,CAAxB,CAA+BwJ,CAA/B,CAA2C,CAAA,CAA3C,CA1BiC,CA4B9CC,EAAcF,CA5BgC,CA4BnBG,EAAgBF,CA5BG,CA4BSG,EAAYjI,CA5BrB,CA4B6BkI,EAAelI,CAGtF4H,EAAJ,GACIG,CAQA,CARcvI,CAAAU,OAAA3D,MAQd,CAPAyL,CAOA,CAPgBpM,CAAA,CAAM4D,CAAN,CAAiB,CAC7BC,EAAGD,CAAAC,EAAHA,CAAiBD,CAAAU,OAAAhB,SAAjBO,CAA6CD,CAAA/C,OADhB,CAE7BF,MAAOwL,CAFsB,CAG7BjI,EAAGN,CAAAM,EAAHA,CAAiBiI,CAAjBjI,CAA+B,CAHF,CAI7BC,EAAGP,CAAAO,EAAHA,CAAiBgI,CAAjBhI,CAA+B,CAJF,CAAjB,CAOhB,CADAkI,CACA,CAlCW9F,IAiCC8E,eAAA,CAAwB3I,CAAxB,CAA+B0J,CAA/B,CAA8C,CAAA,CAA9C,CACZ,CAAAE,CAAA,CAlCW/F,IAkCI8E,eAAA,CAAwB3I,CAAxB,CAA+B0J,CAA/B,CAA8C,CAAA,CAA9C,CATnB,CAWAG,EAAA,CAAM,CACFzI,IAAKA,CADH,CAEFM,OAAQA,CAFN,CAGFyE,WAvCWtC,IAuCCiG,iBAAA,CAA0B1I,CAA1B;AAA+BuI,CAA/B,CAHV,CAIFI,SAAU,CACNlF,MAAOkE,CAAAgB,SAAAlF,MADD,CAENzD,IAAoB,CAAf,GAAA8H,CAAA,CAAmB,CAAnB,CAAuB,CAFtB,CAGNxH,OAAuB,CAAf,GAAAwH,CAAA,CAAmB,CAAnB,CAAuB,CAHzB,CAIN/C,WAAYiD,CAAA,CAAe,CAAf,CAAmB,CAJzB,CAKNhD,UAAWgD,CAAA,CAAe,CAAf,CAAmB,CALxB,CAMN/C,WAAY+C,CAAA,CAAe,CAAf,CAAmB,CANzB,CAJR,CAaNS,EAAAzD,UAAA,CAjDevC,IAiDCmG,gBAAA,CAAyB5I,CAAzB,CAA8BuI,CAA9B,CAChBM,EAAA,CACgD,CADhD,GAAsBtD,IAAAC,IAAA,CAAS6C,CAAT,CAAsBvI,CAAAjD,MAAtB,CAAtB,CACI0I,IAAAgB,IAAA,CAAS8B,CAAT,CAAsBvI,CAAAjD,MAAtB,CACJ4L,EAAAxD,WAAA,CApDexC,IAoDEiG,iBAAA,CApDFjG,IAoD4B8E,eAAA,CAAwB3I,CAAxB,CAA+B1C,CAAA,CAAM4D,CAAN,CAAiB,CACvFM,EAAGN,CAAAM,EAAHA,CAAiBN,CAAAjD,MAAjBuD,CAAmC,CADoD,CAEvFC,EAAGP,CAAAO,EAAHA,CAAiBP,CAAAjD,MAAjBwD,CAAmC,CAFoD,CAGvFmH,gBAAiBqB,CAAA,CAAqB,CAACrB,CAAtB,CAAwC,CAH8B,CAAjB,CAA/B,CAIvC,CAAA,CAJuC,CAA1B,CApDF/E,IAwDH8E,eAAA,CAAwB3I,CAAxB,CAA+B1C,CAAA,CAAMoM,CAAN,CAAqB,CAC5Dd,gBAAiBqB,CAAA,CAAqB,CAACrB,CAAtB,CAAwC,CADG,CAArB,CAA/B,CAER,CAACU,CAFO,CAJK,CAObA,EAAJ,GACIW,CAEA,CAD4C,CAC5C,GAFsBtD,IAAAC,IAAA,CAAS6C,CAAT,CAAsBF,CAAtB,CAEtB,CADI5C,IAAAgB,IAAA,CAAS8B,CAAT,CAAsBF,CAAtB,CACJ,CAAAjM,CAAA,CAAM,CAAA,CAAN,CAAYuM,CAAZ,CAAiB,CACbvD,WA/DOzC,IA+DKiG,iBAAA,CAA0BF,CAA1B,CAAwClI,CAAxC,CADC,CAEb6E,UAhEO1C,IAgEImG,gBAAA,CAAyBJ,CAAzB,CAAuClI,CAAvC,CAFE;AAGb8E,WAjEO3C,IAiEKiG,iBAAA,CAjELjG,IAiE+B8E,eAAA,CAAwB3I,CAAxB,CAA+B1C,CAAA,CAAMkM,CAAN,CAAkB,CACnFZ,gBAAiBqB,CAAA,CACb,CAACrB,CADY,CACM,CAF4D,CAAlB,CAA/B,CAGlC,CAAA,CAHkC,CAA1B,CAjEL/E,IAoEI8E,eAAA,CAAwB3I,CAAxB,CAA+B1C,CAAA,CAAMoM,CAAN,CAAqB,CAC3Dd,gBAAiBqB,CAAA,CACb,CAACrB,CADY,CACM,CAFoC,CAArB,CAA/B,CAGP,CAAA,CAHO,CAHC,CAHC,CAUbmB,SAAU,CACNzD,WAAY8C,CAAA,CAAe,CAAf,CAAmB,CADzB,CAEN7C,UAAW6C,CAAA,CAAe,CAAf,CAAmB,CAFxB,CAGN5C,WAAY4C,CAAA,CAAe,CAAf,CAAmB,CAHzB,CAVG,CAAjB,CAHJ,CAoBA,OAAOS,EArFuC,CAjmBkH,CAAxK,CA0rBAtN,EAAA,CAAgBO,CAAhB,CAA0B,iCAA1B,CAA6D,EAA7D,CAAiE,QAAS,EAAG,EAA7E,CAjsBoB,CAbvB;","sources":["funnel3d.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","Color","U","color","parse","error","extend","merge","pick","relativeLength","seriesType","charts","seriesTypes","RendererProto","Renderer","prototype","cuboidPath","center","width","neckWidth","height","neckHeight","reversed","gradientForSides","animation","edgeWidth","colorByPoint","showInLegend","dataLabels","align","crop","inside","overflow","bindAxes","Series","arguments","xAxis","options","gridLineWidth","lineWidth","title","tickPositions","yAxis","labels","enabled","translate3dShapes","noop","translate","sum","chart","series","ignoreHiddenPoint","plotWidth","plotHeight","cumulative","centerX","centerY","tempWidth","getWidthAt","neckY","data","fraction","tooltipPos","y1","y3","y5","h","shapeArgs","y","top","forEach","point","visible","x","z","bottom","isCylinder","middle","percentage","plotX","plotY","perspective","dlBoxRaw","fullWidth","alignDataLabel","dataLabel","inverted","below","translatedThreshold","len","stacking","dlBox","verticalAlign","column","shapeType","hasNewShapeType","pointClass","funnel3dMethods","elements3d","cuboid","parts","mainParts","sideGroups","sideParts","upperGroup","lowerGroup","pathType","opacitySetter","opacity","funnel3d","renderer","chartIndex","filterId","index","singleSetterForParts","definition","tagName","id","children","type","tableValues","groupName","attr","filter","styledMode","textContent","group","addClass","fillSetter","fill","fillColor","alpha","rgba","partsWithColor","brighten","get","linearGradient","radialGradient","x1","x2","y2","stops","sideGroupName","box","gradientBox","gradient","alteredGradient","partName","frontUpper","backUpper","rightUpper","frontLower","backLower","rightLower","gradBox","diameter","Math","min","setRadialReference","part","grad","elem","element","gradients","gradientUnits","adjustForGradient","bbox","topLeftEdge","Number","MAX_VALUE","bottomRightEdge","getBBox","max","zIndexSetter","finishedOnAdd","Element","onAdd","RendererProto.funnel3d","element3d","strokeAttrs","stroke","g","zIndex","add","upperElem","lowerElem","funnel3dPath","RendererProto.funnel3dPath","getCylinderEnd","alphaCorrection","abs","options3d","cuboidData","call","depth","isTopFirst","isTop","isFrontFirst","isFront","hasMiddle","bottomWidth","bottomArgs","middleWidth","middleTopArgs","middleTop","middleBottom","ret","getCylinderFront","zIndexes","getCylinderBack","useAlphaCorrection"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/funnel3d.src.js b/librerias/gantt/code/modules/funnel3d.src.js new file mode 100644 index 0000000..4037261 --- /dev/null +++ b/librerias/gantt/code/modules/funnel3d.src.js @@ -0,0 +1,733 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * Highcharts funnel module + * + * (c) 2010-2019 Kacper Madej + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/funnel3d', ['highcharts', 'highcharts/highcharts-3d', 'highcharts/modules/cylinder'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'modules/funnel3d.src.js', [_modules['parts/Globals.js'], _modules['parts/Color.js'], _modules['parts/Utilities.js']], function (H, Color, U) { + /* * + * + * Highcharts funnel3d series module + * + * (c) 2010-2020 Highsoft AS + * + * Author: Kacper Madej + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var color = Color.parse; + var error = U.error, extend = U.extend, merge = U.merge, pick = U.pick, relativeLength = U.relativeLength, seriesType = U.seriesType; + var charts = H.charts, seriesTypes = H.seriesTypes, + // Use H.Renderer instead of H.SVGRenderer for VML support. + RendererProto = H.Renderer.prototype, + // + cuboidPath = RendererProto.cuboidPath, funnel3dMethods; + /** + * The funnel3d series type. + * + * @constructor seriesTypes.funnel3d + * @augments seriesTypes.column + * @requires highcharts-3d + * @requires modules/cylinder + * @requires modules/funnel3d + */ + seriesType('funnel3d', 'column', + /** + * A funnel3d is a 3d version of funnel series type. Funnel charts are + * a type of chart often used to visualize stages in a sales project, + * where the top are the initial stages with the most clients. + * + * It requires that the `highcharts-3d.js`, `cylinder.js` and + * `funnel3d.js` module are loaded. + * + * @sample highcharts/demo/funnel3d/ + * Funnel3d + * + * @extends plotOptions.column + * @excluding allAreas, boostThreshold, colorAxis, compare, compareBase, + * dataSorting + * @product highcharts + * @since 7.1.0 + * @requires highcharts-3d + * @requires modules/cylinder + * @requires modules/funnel3d + * @optionparent plotOptions.funnel3d + */ + { + /** @ignore-option */ + center: ['50%', '50%'], + /** + * The max width of the series compared to the width of the plot area, + * or the pixel width if it is a number. + * + * @type {number|string} + * @sample {highcharts} highcharts/demo/funnel3d/ Funnel3d demo + * @product highcharts + */ + width: '90%', + /** + * The width of the neck, the lower part of the funnel. A number defines + * pixel width, a percentage string defines a percentage of the plot + * area width. + * + * @type {number|string} + * @sample {highcharts} highcharts/demo/funnel3d/ Funnel3d demo + * @product highcharts + */ + neckWidth: '30%', + /** + * The height of the series. If it is a number it defines + * the pixel height, if it is a percentage string it is the percentage + * of the plot area height. + * + * @type {number|string} + * @sample {highcharts} highcharts/demo/funnel3d/ Funnel3d demo + * @product highcharts + */ + height: '100%', + /** + * The height of the neck, the lower part of the funnel. A number + * defines pixel width, a percentage string defines a percentage + * of the plot area height. + * + * @type {number|string} + * @sample {highcharts} highcharts/demo/funnel3d/ Funnel3d demo + * @product highcharts + */ + neckHeight: '25%', + /** + * A reversed funnel has the widest area down. A reversed funnel with + * no neck width and neck height is a pyramid. + * + * @product highcharts + */ + reversed: false, + /** + * By deafult sides fill is set to a gradient through this option being + * set to `true`. Set to `false` to get solid color for the sides. + * + * @product highcharts + */ + gradientForSides: true, + animation: false, + edgeWidth: 0, + colorByPoint: true, + showInLegend: false, + dataLabels: { + align: 'right', + crop: false, + inside: false, + overflow: 'allow' + } + }, { + // Override default axis options with series required options for axes + bindAxes: function () { + H.Series.prototype.bindAxes.apply(this, arguments); + extend(this.xAxis.options, { + gridLineWidth: 0, + lineWidth: 0, + title: null, + tickPositions: [] + }); + extend(this.yAxis.options, { + gridLineWidth: 0, + title: null, + labels: { + enabled: false + } + }); + }, + translate3dShapes: H.noop, + translate: function () { + H.Series.prototype.translate.apply(this, arguments); + var sum = 0, series = this, chart = series.chart, options = series.options, reversed = options.reversed, ignoreHiddenPoint = options.ignoreHiddenPoint, plotWidth = chart.plotWidth, plotHeight = chart.plotHeight, cumulative = 0, // start at top + center = options.center, centerX = relativeLength(center[0], plotWidth), centerY = relativeLength(center[1], plotHeight), width = relativeLength(options.width, plotWidth), tempWidth, getWidthAt, height = relativeLength(options.height, plotHeight), neckWidth = relativeLength(options.neckWidth, plotWidth), neckHeight = relativeLength(options.neckHeight, plotHeight), neckY = (centerY - height / 2) + height - neckHeight, data = series.data, fraction, tooltipPos, + // + y1, y3, y5, + // + h, shapeArgs; + // Return the width at a specific y coordinate + series.getWidthAt = getWidthAt = function (y) { + var top = (centerY - height / 2); + return (y > neckY || height === neckHeight) ? + neckWidth : + neckWidth + (width - neckWidth) * + (1 - (y - top) / (height - neckHeight)); + }; + // Expose + series.center = [centerX, centerY, height]; + series.centerX = centerX; + /* + * Individual point coordinate naming: + * + * _________centerX,y1________ + * \ / + * \ / + * \ / + * \ / + * \ / + * ___centerX,y3___ + * + * Additional for the base of the neck: + * + * | | + * | | + * | | + * ___centerX,y5___ + */ + // get the total sum + data.forEach(function (point) { + if (!ignoreHiddenPoint || point.visible !== false) { + sum += point.y; + } + }); + data.forEach(function (point) { + // set start and end positions + y5 = null; + fraction = sum ? point.y / sum : 0; + y1 = centerY - height / 2 + cumulative * height; + y3 = y1 + fraction * height; + tempWidth = getWidthAt(y1); + h = y3 - y1; + shapeArgs = { + // for fill setter + gradientForSides: pick(point.options.gradientForSides, options.gradientForSides), + x: centerX, + y: y1, + height: h, + width: tempWidth, + z: 1, + top: { + width: tempWidth + } + }; + tempWidth = getWidthAt(y3); + shapeArgs.bottom = { + fraction: fraction, + width: tempWidth + }; + // the entire point is within the neck + if (y1 >= neckY) { + shapeArgs.isCylinder = true; + } + else if (y3 > neckY) { + // the base of the neck + y5 = y3; + tempWidth = getWidthAt(neckY); + y3 = neckY; + shapeArgs.bottom.width = tempWidth; + shapeArgs.middle = { + fraction: h ? (neckY - y1) / h : 0, + width: tempWidth + }; + } + if (reversed) { + shapeArgs.y = y1 = centerY + height / 2 - + (cumulative + fraction) * height; + if (shapeArgs.middle) { + shapeArgs.middle.fraction = 1 - + (h ? shapeArgs.middle.fraction : 0); + } + tempWidth = shapeArgs.width; + shapeArgs.width = shapeArgs.bottom.width; + shapeArgs.bottom.width = tempWidth; + } + point.shapeArgs = extend(point.shapeArgs, shapeArgs); + // for tooltips and data labels context + point.percentage = fraction * 100; + point.plotX = centerX; + if (reversed) { + point.plotY = centerY + height / 2 - + (cumulative + fraction / 2) * height; + } + else { + point.plotY = (y1 + (y5 || y3)) / 2; + } + // Placement of tooltips and data labels in 3D + tooltipPos = H.perspective([{ + x: centerX, + y: point.plotY, + z: reversed ? + -(width - getWidthAt(point.plotY)) / 2 : + -(getWidthAt(point.plotY)) / 2 + }], chart, true)[0]; + point.tooltipPos = [tooltipPos.x, tooltipPos.y]; + // base to be used when alignment options are known + point.dlBoxRaw = { + x: centerX, + width: getWidthAt(point.plotY), + y: y1, + bottom: shapeArgs.height, + fullWidth: width + }; + if (!ignoreHiddenPoint || point.visible !== false) { + cumulative += fraction; + } + }); + }, + alignDataLabel: function (point, dataLabel, options) { + var series = this, dlBoxRaw = point.dlBoxRaw, inverted = series.chart.inverted, below = point.plotY > pick(series.translatedThreshold, series.yAxis.len), inside = pick(options.inside, !!series.options.stacking), dlBox = { + x: dlBoxRaw.x, + y: dlBoxRaw.y, + height: 0 + }; + options.align = pick(options.align, !inverted || inside ? 'center' : below ? 'right' : 'left'); + options.verticalAlign = pick(options.verticalAlign, inverted || inside ? 'middle' : below ? 'top' : 'bottom'); + if (options.verticalAlign !== 'top') { + dlBox.y += dlBoxRaw.bottom / + (options.verticalAlign === 'bottom' ? 1 : 2); + } + dlBox.width = series.getWidthAt(dlBox.y); + if (series.options.reversed) { + dlBox.width = dlBoxRaw.fullWidth - dlBox.width; + } + if (inside) { + dlBox.x -= dlBox.width / 2; + } + else { + // swap for inside + if (options.align === 'left') { + options.align = 'right'; + dlBox.x -= dlBox.width * 1.5; + } + else if (options.align === 'right') { + options.align = 'left'; + dlBox.x += dlBox.width / 2; + } + else { + dlBox.x -= dlBox.width / 2; + } + } + point.dlBox = dlBox; + seriesTypes.column.prototype.alignDataLabel.apply(series, arguments); + } + }, /** @lends seriesTypes.funnel3d.prototype.pointClass.prototype */ { + shapeType: 'funnel3d', + hasNewShapeType: H + .seriesTypes.column.prototype + .pointClass.prototype + .hasNewShapeType + }); + /** + * A `funnel3d` series. If the [type](#series.funnel3d.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @sample {highcharts} highcharts/demo/funnel3d/ + * Funnel3d demo + * + * @since 7.1.0 + * @extends series,plotOptions.funnel3d + * @excluding allAreas,boostThreshold,colorAxis,compare,compareBase + * @product highcharts + * @requires highcharts-3d + * @requires modules/cylinder + * @requires modules/funnel3d + * @apioption series.funnel3d + */ + /** + * An array of data points for the series. For the `funnel3d` series + * type, points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values + * will be interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from `pointStart` + * and `pointInterval` given in the series options. If the axis has + * categories, these will be used. Example: + * + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of data + * points exceeds the series' [turboThreshold](#series.funnel3d.turboThreshold), + * this option is not available. + * + * ```js + * data: [{ + * y: 2, + * name: "Point2", + * color: "#00FF00" + * }, { + * y: 4, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|*>} + * @extends series.column.data + * @product highcharts + * @apioption series.funnel3d.data + */ + /** + * By deafult sides fill is set to a gradient through this option being + * set to `true`. Set to `false` to get solid color for the sides. + * + * @type {boolean} + * @product highcharts + * @apioption series.funnel3d.data.gradientForSides + */ + funnel3dMethods = merge(RendererProto.elements3d.cuboid, { + parts: [ + 'top', 'bottom', + 'frontUpper', 'backUpper', + 'frontLower', 'backLower', + 'rightUpper', 'rightLower' + ], + mainParts: ['top', 'bottom'], + sideGroups: [ + 'upperGroup', 'lowerGroup' + ], + sideParts: { + upperGroup: ['frontUpper', 'backUpper', 'rightUpper'], + lowerGroup: ['frontLower', 'backLower', 'rightLower'] + }, + pathType: 'funnel3d', + // override opacity and color setters to control opacity + opacitySetter: function (opacity) { + var funnel3d = this, parts = funnel3d.parts, chart = H.charts[funnel3d.renderer.chartIndex], filterId = 'group-opacity-' + opacity + '-' + chart.index; + // use default for top and bottom + funnel3d.parts = funnel3d.mainParts; + funnel3d.singleSetterForParts('opacity', opacity); + // restore + funnel3d.parts = parts; + if (!chart.renderer.filterId) { + chart.renderer.definition({ + tagName: 'filter', + id: filterId, + children: [{ + tagName: 'feComponentTransfer', + children: [{ + tagName: 'feFuncA', + type: 'table', + tableValues: '0 ' + opacity + }] + }] + }); + funnel3d.sideGroups.forEach(function (groupName) { + funnel3d[groupName].attr({ + filter: 'url(#' + filterId + ')' + }); + }); + // styled mode + if (funnel3d.renderer.styledMode) { + chart.renderer.definition({ + tagName: 'style', + textContent: '.highcharts-' + filterId + + ' {filter:url(#' + filterId + ')}' + }); + funnel3d.sideGroups.forEach(function (group) { + group.addClass('highcharts-' + filterId); + }); + } + } + return funnel3d; + }, + fillSetter: function (fill) { + // extract alpha channel to use the opacitySetter + var funnel3d = this, fillColor = color(fill), alpha = fillColor.rgba[3], partsWithColor = { + // standard color for top and bottom + top: color(fill).brighten(0.1).get(), + bottom: color(fill).brighten(-0.2).get() + }; + if (alpha < 1) { + fillColor.rgba[3] = 1; + fillColor = fillColor.get('rgb'); + // set opacity through the opacitySetter + funnel3d.attr({ + opacity: alpha + }); + } + else { + // use default for full opacity + fillColor = fill; + } + // add gradient for sides + if (!fillColor.linearGradient && + !fillColor.radialGradient && + funnel3d.gradientForSides) { + fillColor = { + linearGradient: { x1: 0, x2: 1, y1: 1, y2: 1 }, + stops: [ + [0, color(fill).brighten(-0.2).get()], + [0.5, fill], + [1, color(fill).brighten(-0.2).get()] + ] + }; + } + // gradient support + if (fillColor.linearGradient) { + // color in steps, as each gradient will generate a key + funnel3d.sideGroups.forEach(function (sideGroupName) { + var box = funnel3d[sideGroupName].gradientBox, gradient = fillColor.linearGradient, alteredGradient = merge(fillColor, { + linearGradient: { + x1: box.x + gradient.x1 * box.width, + y1: box.y + gradient.y1 * box.height, + x2: box.x + gradient.x2 * box.width, + y2: box.y + gradient.y2 * box.height + } + }); + funnel3d.sideParts[sideGroupName].forEach(function (partName) { + partsWithColor[partName] = alteredGradient; + }); + }); + } + else { + merge(true, partsWithColor, { + frontUpper: fillColor, + backUpper: fillColor, + rightUpper: fillColor, + frontLower: fillColor, + backLower: fillColor, + rightLower: fillColor + }); + if (fillColor.radialGradient) { + funnel3d.sideGroups.forEach(function (sideGroupName) { + var gradBox = funnel3d[sideGroupName].gradientBox, centerX = gradBox.x + gradBox.width / 2, centerY = gradBox.y + gradBox.height / 2, diameter = Math.min(gradBox.width, gradBox.height); + funnel3d.sideParts[sideGroupName].forEach(function (partName) { + funnel3d[partName].setRadialReference([ + centerX, centerY, diameter + ]); + }); + }); + } + } + funnel3d.singleSetterForParts('fill', null, partsWithColor); + // fill for animation getter (#6776) + funnel3d.color = funnel3d.fill = fill; + // change gradientUnits to userSpaceOnUse for linearGradient + if (fillColor.linearGradient) { + [funnel3d.frontLower, funnel3d.frontUpper].forEach(function (part) { + var elem = part.element, grad = elem && funnel3d.renderer.gradients[elem.gradient]; + if (grad && grad.attr('gradientUnits') !== 'userSpaceOnUse') { + grad.attr({ + gradientUnits: 'userSpaceOnUse' + }); + } + }); + } + return funnel3d; + }, + adjustForGradient: function () { + var funnel3d = this, bbox; + funnel3d.sideGroups.forEach(function (sideGroupName) { + // use common extremes for groups for matching gradients + var topLeftEdge = { + x: Number.MAX_VALUE, + y: Number.MAX_VALUE + }, bottomRightEdge = { + x: -Number.MAX_VALUE, + y: -Number.MAX_VALUE + }; + // get extremes + funnel3d.sideParts[sideGroupName].forEach(function (partName) { + var part = funnel3d[partName]; + bbox = part.getBBox(true); + topLeftEdge = { + x: Math.min(topLeftEdge.x, bbox.x), + y: Math.min(topLeftEdge.y, bbox.y) + }; + bottomRightEdge = { + x: Math.max(bottomRightEdge.x, bbox.x + bbox.width), + y: Math.max(bottomRightEdge.y, bbox.y + bbox.height) + }; + }); + // store for color fillSetter + funnel3d[sideGroupName].gradientBox = { + x: topLeftEdge.x, + width: bottomRightEdge.x - topLeftEdge.x, + y: topLeftEdge.y, + height: bottomRightEdge.y - topLeftEdge.y + }; + }); + }, + zIndexSetter: function () { + // this.added won't work, because zIndex is set after the prop is set, + // but before the graphic is really added + if (this.finishedOnAdd) { + this.adjustForGradient(); + } + // run default + return this.renderer.Element.prototype.zIndexSetter.apply(this, arguments); + }, + onAdd: function () { + this.adjustForGradient(); + this.finishedOnAdd = true; + } + }); + RendererProto.elements3d.funnel3d = funnel3dMethods; + RendererProto.funnel3d = function (shapeArgs) { + var renderer = this, funnel3d = renderer.element3d('funnel3d', shapeArgs), styledMode = renderer.styledMode, + // hide stroke for Firefox + strokeAttrs = { + 'stroke-width': 1, + stroke: 'none' + }; + // create groups for sides for oppacity setter + funnel3d.upperGroup = renderer.g('funnel3d-upper-group').attr({ + zIndex: funnel3d.frontUpper.zIndex + }).add(funnel3d); + [ + funnel3d.frontUpper, + funnel3d.backUpper, + funnel3d.rightUpper + ].forEach(function (upperElem) { + if (!styledMode) { + upperElem.attr(strokeAttrs); + } + upperElem.add(funnel3d.upperGroup); + }); + funnel3d.lowerGroup = renderer.g('funnel3d-lower-group').attr({ + zIndex: funnel3d.frontLower.zIndex + }).add(funnel3d); + [ + funnel3d.frontLower, + funnel3d.backLower, + funnel3d.rightLower + ].forEach(function (lowerElem) { + if (!styledMode) { + lowerElem.attr(strokeAttrs); + } + lowerElem.add(funnel3d.lowerGroup); + }); + funnel3d.gradientForSides = shapeArgs.gradientForSides; + return funnel3d; + }; + // eslint-disable-next-line valid-jsdoc + /** + * Generates paths and zIndexes. + * @private + */ + RendererProto.funnel3dPath = function (shapeArgs) { + // Check getCylinderEnd for better error message if + // the cylinder module is missing + if (!this.getCylinderEnd) { + error('A required Highcharts module is missing: cylinder.js', true, charts[this.chartIndex]); + } + var renderer = this, chart = charts[renderer.chartIndex], + // adjust angles for visible edges + // based on alpha, selected through visual tests + alphaCorrection = shapeArgs.alphaCorrection = 90 - + Math.abs((chart.options.chart.options3d.alpha % 180) - 90), + // set zIndexes of parts based on cubiod logic, for consistency + cuboidData = cuboidPath.call(renderer, merge(shapeArgs, { + depth: shapeArgs.width, + width: (shapeArgs.width + shapeArgs.bottom.width) / 2 + })), isTopFirst = cuboidData.isTop, isFrontFirst = !cuboidData.isFront, hasMiddle = !!shapeArgs.middle, + // + top = renderer.getCylinderEnd(chart, merge(shapeArgs, { + x: shapeArgs.x - shapeArgs.width / 2, + z: shapeArgs.z - shapeArgs.width / 2, + alphaCorrection: alphaCorrection + })), bottomWidth = shapeArgs.bottom.width, bottomArgs = merge(shapeArgs, { + width: bottomWidth, + x: shapeArgs.x - bottomWidth / 2, + z: shapeArgs.z - bottomWidth / 2, + alphaCorrection: alphaCorrection + }), bottom = renderer.getCylinderEnd(chart, bottomArgs, true), + // + middleWidth = bottomWidth, middleTopArgs = bottomArgs, middleTop = bottom, middleBottom = bottom, ret, + // masking for cylinders or a missing part of a side shape + useAlphaCorrection; + if (hasMiddle) { + middleWidth = shapeArgs.middle.width; + middleTopArgs = merge(shapeArgs, { + y: shapeArgs.y + shapeArgs.middle.fraction * shapeArgs.height, + width: middleWidth, + x: shapeArgs.x - middleWidth / 2, + z: shapeArgs.z - middleWidth / 2 + }); + middleTop = renderer.getCylinderEnd(chart, middleTopArgs, false); + middleBottom = renderer.getCylinderEnd(chart, middleTopArgs, false); + } + ret = { + top: top, + bottom: bottom, + frontUpper: renderer.getCylinderFront(top, middleTop), + zIndexes: { + group: cuboidData.zIndexes.group, + top: isTopFirst !== 0 ? 0 : 3, + bottom: isTopFirst !== 1 ? 0 : 3, + frontUpper: isFrontFirst ? 2 : 1, + backUpper: isFrontFirst ? 1 : 2, + rightUpper: isFrontFirst ? 2 : 1 + } + }; + ret.backUpper = renderer.getCylinderBack(top, middleTop); + useAlphaCorrection = (Math.min(middleWidth, shapeArgs.width) / + Math.max(middleWidth, shapeArgs.width)) !== 1; + ret.rightUpper = renderer.getCylinderFront(renderer.getCylinderEnd(chart, merge(shapeArgs, { + x: shapeArgs.x - shapeArgs.width / 2, + z: shapeArgs.z - shapeArgs.width / 2, + alphaCorrection: useAlphaCorrection ? -alphaCorrection : 0 + }), false), renderer.getCylinderEnd(chart, merge(middleTopArgs, { + alphaCorrection: useAlphaCorrection ? -alphaCorrection : 0 + }), !hasMiddle)); + if (hasMiddle) { + useAlphaCorrection = (Math.min(middleWidth, bottomWidth) / + Math.max(middleWidth, bottomWidth)) !== 1; + merge(true, ret, { + frontLower: renderer.getCylinderFront(middleBottom, bottom), + backLower: renderer.getCylinderBack(middleBottom, bottom), + rightLower: renderer.getCylinderFront(renderer.getCylinderEnd(chart, merge(bottomArgs, { + alphaCorrection: useAlphaCorrection ? + -alphaCorrection : 0 + }), true), renderer.getCylinderEnd(chart, merge(middleTopArgs, { + alphaCorrection: useAlphaCorrection ? + -alphaCorrection : 0 + }), false)), + zIndexes: { + frontLower: isFrontFirst ? 2 : 1, + backLower: isFrontFirst ? 1 : 2, + rightLower: isFrontFirst ? 1 : 2 + } + }); + } + return ret; + }; + + }); + _registerModule(_modules, 'masters/modules/funnel3d.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/gantt.js b/librerias/gantt/code/modules/gantt.js new file mode 100644 index 0000000..6137c8b --- /dev/null +++ b/librerias/gantt/code/modules/gantt.js @@ -0,0 +1,192 @@ +/* + Highcharts Gantt JS v8.1.0 (2020-05-05) + + Gantt series + + (c) 2016-2019 Lars A. V. Cabrera + + License: www.highcharts.com/license +*/ +(function(k){"object"===typeof module&&module.exports?(k["default"]=k,module.exports=k):"function"===typeof define&&define.amd?define("highcharts/modules/gantt",["highcharts"],function(G){k(G);k.Highcharts=G;return k}):k("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(k){function G(w,a,v,n){w.hasOwnProperty(a)||(w[a]=n.apply(null,v))}k=k?k._modules:{};G(k,"parts-gantt/CurrentDateIndicator.js",[k["parts/Globals.js"],k["parts/Utilities.js"],k["parts/PlotLineOrBand.js"]],function(w,a,v){var n= +a.addEvent,x=a.merge;a=a.wrap;var q={currentDateIndicator:!0,color:"#ccd6eb",width:2,label:{format:"%a, %b %d %Y, %H:%M",formatter:function(a,n){return w.dateFormat(n,a)},rotation:0,style:{fontSize:"10px"}}};n(w.Axis,"afterSetOptions",function(){var a=this.options,n=a.currentDateIndicator;n&&(n="object"===typeof n?x(q,n):x(q),n.value=new Date,a.plotLines||(a.plotLines=[]),a.plotLines.push(n))});n(v,"render",function(){this.label&&this.label.attr({text:this.getLabelText(this.options.label)})});a(v.prototype, +"getLabelText",function(a,n){var y=this.options;return y.currentDateIndicator&&y.label&&"function"===typeof y.label.formatter?(y.value=new Date,y.label.formatter.call(this,y.value,y.label.format)):a.call(this,n)})});G(k,"modules/static-scale.src.js",[k["parts/Globals.js"],k["parts/Utilities.js"]],function(w,a){var v=a.addEvent,n=a.defined,x=a.isNumber,q=a.pick;a=w.Chart;v(w.Axis,"afterSetOptions",function(){var a=this.chart.options&&this.chart.options.chart;!this.horiz&&x(this.options.staticScale)&& +(!a.height||a.scrollablePlotArea&&a.scrollablePlotArea.minHeight)&&(this.staticScale=this.options.staticScale)});a.prototype.adjustHeight=function(){"adjustHeight"!==this.redrawTrigger&&((this.axes||[]).forEach(function(a){var v=a.chart,y=!!v.initiatedScale&&v.options.animation,g=a.options.staticScale;if(a.staticScale&&n(a.min)){var f=q(a.brokenAxis&&a.brokenAxis.unitLength,a.max+a.tickInterval-a.min)*g;f=Math.max(f,g);g=f-v.plotHeight;1<=Math.abs(g)&&(v.plotHeight=f,v.redrawTrigger="adjustHeight", +v.setSize(void 0,v.chartHeight+g,y));a.series.forEach(function(f){(f=f.sharedClipKey&&v[f.sharedClipKey])&&f.attr({height:v.plotHeight})})}}),this.initiatedScale=!0);this.redrawTrigger=null};v(a,"render",a.prototype.adjustHeight)});G(k,"parts-gantt/Tree.js",[k["parts/Utilities.js"]],function(w){var a=w.extend,v=w.isNumber,n=w.pick,x=function(a,v){var y=a.reduce(function(g,f){var r=n(f.parent,"");"undefined"===typeof g[r]&&(g[r]=[]);g[r].push(f);return g},{});Object.keys(y).forEach(function(g,f){var r= +y[g];""!==g&&-1===v.indexOf(g)&&(r.forEach(function(g){f[""].push(g)}),delete f[g])});return y},q=function(w,x,y,g,f,r){var u=0,D=0,F=r&&r.after,A=r&&r.before;x={data:g,depth:y-1,id:w,level:y,parent:x};var h,e;"function"===typeof A&&A(x,r);A=(f[w]||[]).map(function(l){var d=q(l.id,w,y+1,l,f,r),c=l.start;l=!0===l.milestone?c:l.end;h=!v(h)||ce?l:e;u=u+1+d.descendants;D=Math.max(d.height+1,D);return d});g&&(g.start=n(g.start,h),g.end=n(g.end,e));a(x,{children:A,descendants:u,height:D}); +"function"===typeof F&&F(x,r);return x};return{getListOfParents:x,getNode:q,getTree:function(a,n){var y=a.map(function(g){return g.id});a=x(a,y);return q("",null,1,null,a,n)}}});G(k,"parts-gantt/TreeGridTick.js",[k["parts/Utilities.js"]],function(w){var a=w.addEvent,v=w.defined,n=w.isObject,x=w.isNumber,q=w.pick,k=w.wrap,B;(function(y){function g(){this.treeGrid||(this.treeGrid=new F(this))}function f(f,h){f=f.treeGrid;var e=!f.labelIcon,l=h.renderer,d=h.xy,c=h.options,b=c.width,p=c.height,I=d.x- +b/2-c.padding;d=d.y-p/2;var H=h.collapsed?90:180,g=h.show&&x(d),E=f.labelIcon;E||(f.labelIcon=E=l.path(l.symbols[c.type](c.x,c.y,b,p)).addClass("highcharts-label-icon").add(h.group));g||E.attr({y:-9999});l.styledMode||E.attr({"stroke-width":1,fill:q(h.color,"#666666")}).css({cursor:"pointer",stroke:c.lineColor,strokeWidth:c.lineWidth});E[e?"attr":"animate"]({translateX:I,translateY:d,rotation:H})}function r(f,h,e,l,d,c,b,p,I){var H=q(this.options&&this.options.labels,c);c=this.pos;var g=this.axis, +E="treegrid"===g.options.type;f=f.apply(this,[h,e,l,d,H,b,p,I]);E&&(h=H&&n(H.symbol,!0)?H.symbol:{},H=H&&x(H.indentation)?H.indentation:0,c=(c=(g=g.treeGrid.mapOfPosToGridNode)&&g[c])&&c.depth||1,f.x+=h.width+2*h.padding+(c-1)*H);return f}function u(g){var h=this,e=h.pos,l=h.axis,d=h.label,c=l.treeGrid.mapOfPosToGridNode,b=l.options,p=q(h.options&&h.options.labels,b&&b.labels),I=p&&n(p.symbol,!0)?p.symbol:{},H=(c=c&&c[e])&&c.depth;b="treegrid"===b.type;var L=-1h&&!c.startOnTick&&(d[0]=h),l> +a&&l-z=h?(f-h)%g:g-(h-f)%g;return a.inclusive?f<=e:f=f)break;else h.to=f)break;else if(a.isInBreak(e,f)){r-=f-e.from;break}}return r};a.prototype.findBreakAt=function(a,f){return q(f,function(f){return f.fromf;)m-=p;for(;mc.to||b>c.from&&hc.from&&hc.from&&h>c.to&&ha&&e>=this.basePointRange&&(a=e),b=void 0;d--;)b&&!1!==b.visible||(b=f[d+1]),e=f[d],!1!==b.visible&& +!1!==e.visible&&(b.x-e.x>a&&(b=(e.x+b.x)/2,f.splice(d+1,0,{isNull:!0,x:b}),c.stacking&&this.options.stacking&&(b=c.stacking.stacks[this.stackKey][b]=new n(c,c.options.stackLabels,!1,b,this.stack),b.total=0)),b=e);return this.getGraphPath(f)};x(a,"init",function(){this.brokenAxis||(this.brokenAxis=new r(this))});x(a,"afterInit",function(){"undefined"!==typeof this.brokenAxis&&this.brokenAxis.setBreaks(this.options.breaks,!1)});x(a,"afterSetTickPositions",function(){var a=this.brokenAxis;if(a&&a.hasBreaks){var e= +this.tickPositions,f=this.tickPositions.info,d=[],c;for(c=0;c=c&&(d-=.5);return{from:d,to:b,showPoints:!1}}function l(b,c,d){var m=[],e=[],p={},a={},z=-1,l="boolean"===typeof c?c:!1;b=v.getTree(b,{after:function(b){b=a[b.pos];var c=0,d=0;b.children.forEach(function(b){d+=(b.descendants||0)+1;c=Math.max((b.height||0)+1,c)});b.descendants=d;b.height=c;b.collapsed&&e.push(b)},before:function(b){var c=f(b.data,!0)?b.data:{},d=r(c.name)? +c.name:"",t=p[b.parent];t=f(t,!0)?a[t.pos]:null;var e=function(b){return b.name===d},C;l&&f(t,!0)&&(C=B(t.children,e))?(e=C.pos,C.nodes.push(b)):e=z++;a[e]||(a[e]=C={depth:t?t.depth+1:0,name:d,nodes:[b],children:[],pos:e},-1!==e&&m.push(d),f(t,!0)&&t.children.push(C));r(b.id)&&(p[b.id]=b);C&&!0===c.collapsed&&(C.collapsed=!0);b.pos=e}});a=function(b,c){var d=function(b,m,t){var e=m+(-1===m?0:c-1),p=(e-m)/2,a=m+p;b.nodes.forEach(function(b){var c=b.data;f(c,!0)&&(c.y=m+(c.seriesIndex||0),delete c.seriesIndex); +b.pos=a});t[a]=b;b.pos=a;b.tickmarkOffset=p+.5;b.collapseStart=e+.5;b.children.forEach(function(b){d(b,e+1,t);e=(b.collapseEnd||0)-.5});b.collapseEnd=e+.5;return t};return d(b["-1"],-1,{})}(a,d);return{categories:m,mapOfIdToNode:p,mapOfPosToGridNode:a,collapsedNodes:e,tree:b}}function d(b){b.target.axes.filter(function(b){return"treegrid"===b.options.type}).forEach(function(c){var d=c.options||{},e=d.labels,p=d.uniqueNames,a=0;if(!c.treeGrid.mapOfPosToGridNode||c.series.some(function(b){return!b.hasRendered|| +b.isDirtyData||b.isDirty}))d=c.series.reduce(function(b,c){c.visible&&((c.options.data||[]).forEach(function(c){f(c,!0)&&(c.seriesIndex=a,b.push(c))}),!0===p&&a++);return b},[]),d=l(d,p||!1,!0===p?a:1),c.categories=d.categories,c.treeGrid.mapOfPosToGridNode=d.mapOfPosToGridNode,c.hasNames=!0,c.treeGrid.tree=d.tree,c.series.forEach(function(b){var c=(b.options.data||[]).map(function(b){return f(b,!0)?u(b):b});b.visible&&b.setData(c,!1)}),c.treeGrid.mapOptionsToLevel=x.getLevelOptions({defaults:e,from:1, +levels:e&&e.levels,to:c.treeGrid.tree&&c.treeGrid.tree.height}),"beforeRender"===b.type&&(c.treeGrid.collapsedNodes=d.collapsedNodes)})}function c(b,c){var d=this.treeGrid.mapOptionsToLevel||{},e=this.ticks,p=e[c],f;if("treegrid"===this.options.type&&this.treeGrid.mapOfPosToGridNode){var l=this.treeGrid.mapOfPosToGridNode[c];(d=d[l.depth])&&(f={labels:d});p?(p.parameters.category=l.name,p.options=f,p.addLabel()):e[c]=new a(this,c,void 0,void 0,{category:l.name,tickmarkOffset:l.tickmarkOffset,options:f})}else b.apply(this, +Array.prototype.slice.call(arguments,1))}function b(b){var c=this.options;c=(c=c&&c.labels)&&g(c.indentation)?c.indentation:0;var d=b.apply(this,Array.prototype.slice.call(arguments,1));if("treegrid"===this.options.type&&this.treeGrid.mapOfPosToGridNode){var e=this.treeGrid.mapOfPosToGridNode[-1].height||0;d.width+=c*(e-1)}return d}function p(b,c,m){var e=this,p="treegrid"===m.type;e.treeGrid||(e.treeGrid=new L(e));p&&(w(c,"beforeRender",d),w(c,"beforeRedraw",d),w(c,"addSeries",function(b){b.options.data&& +(b=l(b.options.data,m.uniqueNames||!1,1),e.treeGrid.collapsedNodes=(e.treeGrid.collapsedNodes||[]).concat(b.collapsedNodes))}),w(e,"foundExtremes",function(){e.treeGrid.collapsedNodes&&e.treeGrid.collapsedNodes.forEach(function(b){var c=e.treeGrid.collapse(b);e.brokenAxis&&(e.brokenAxis.setBreaks(c,!1),e.treeGrid.collapsedNodes&&(e.treeGrid.collapsedNodes=e.treeGrid.collapsedNodes.filter(function(c){return b.collapseStart!==c.collapseStart||b.collapseEnd!==c.collapseEnd})))})}),m=u({grid:{enabled:!0}, +labels:{align:"left",levels:[{level:void 0},{level:1,style:{fontWeight:"bold"}}],symbol:{type:"triangle",x:-5,y:-5,height:10,width:10,padding:5}},uniqueNames:!1},m,{reversed:!0,grid:{columns:void 0}}));b.apply(e,[c,m]);p&&(e.hasNames=!0,e.options.showLastLabel=!0)}function I(b){var c=this.options;"treegrid"===c.type?(this.min=D(this.userMin,c.min,this.dataMin),this.max=D(this.userMax,c.max,this.dataMax),y(this,"foundExtremes"),this.setAxisTranslation(!0),this.tickmarkOffset=.5,this.tickInterval=1, +this.tickPositions=this.treeGrid.mapOfPosToGridNode?this.treeGrid.getTickPositions():[]):b.apply(this,Array.prototype.slice.call(arguments,1))}var H=!1;h.compose=function(d){H||(F(d.prototype,"generateTick",c),F(d.prototype,"getMaxLabelDimensions",b),F(d.prototype,"init",p),F(d.prototype,"setTickInterval",I),n.compose(a),H=!0)};var L=function(){function b(b){this.axis=b}b.prototype.collapse=function(b){var c=this.axis,d=c.options.breaks||[];b=e(b,c.max);d.push(b);return d};b.prototype.expand=function(b){var c= +this.axis,d=c.options.breaks||[],p=e(b,c.max);return d.reduce(function(b,c){c.to===p.to&&c.from===p.from||b.push(c);return b},[])};b.prototype.getTickPositions=function(){var b=this.axis;return Object.keys(b.treeGrid.mapOfPosToGridNode||{}).reduce(function(c,d){d=+d;!(b.min<=d&&b.max>=d)||b.brokenAxis&&b.brokenAxis.isInAnyBreak(d)||c.push(d);return c},[])};b.prototype.isCollapsed=function(b){var c=this.axis,d=c.options.breaks||[],p=e(b,c.max);return d.some(function(b){return b.from===p.from&&b.to=== +p.to})};b.prototype.toggleCollapse=function(b){return this.isCollapsed(b)?this.expand(b):this.collapse(b)};return b}();h.Additions=L})(A||(A={}));k.prototype.utils={getNode:v.getNode};A.compose(k);return A});G(k,"parts-gantt/PathfinderAlgorithms.js",[k["parts/Utilities.js"]],function(k){function a(a,g,u){u=u||0;var f=a.length-1;g-=1e-7;for(var r,n;u<=f;)if(r=f+u>>1,n=g-a[r].xMin,0n)f=r-1;else return r;return 0= +g.x)n=f[r],n=g.x<=n.xMax&&g.x>=n.xMin&&g.y<=n.yMax&&g.y>=n.yMin;if(n)return r}return-1}function n(a){var f=[];if(a.length){f.push(["M",a[0].start.x,a[0].start.y]);for(var g=0;gg(c[d]-b[d+"Max"]);return f(c,d,b,d+(e?"Max":"Min"),e?1:-1)}var q=[],h=w(u.startDirectionX,g(r.x-a.x)>g(r.y-a.y))?"x":"y",e=u.chartObstacles,l=v(e,a);u=v(e,r);if(-1=a[h]===u[h]>=c[h]&&(h="y"===h?"x":"y",r=a[h]m?B(a(E,t.x),E.length-1):0;E[e]&&(0m&&E[e].xMax>=p.x);){if(E[e].xMin<=t.x&&E[e].xMax>=p.x&&E[e].yMin<= +l.y&&E[e].yMax>=f.y)return d?{y:b.y,x:b.x=p[t+"Max"];p=b[t+"Min"]<=p[t+"Min"];var h=b[t+"Max"]>=a[t+"Max"];a=b[t+"Min"]<=a[t+"Min"];var C=g(b[t+"Min"]-c[t]),z=g(b[t+"Max"]-c[t]);d=10>g(C-z)?c[t]g(r.y-f.y)),l=e?"x":"y",d=[],c=!1,b=u.obstacleMetrics,p=B(f.x,r.x)-b.maxWidth-10,I=y(f.x,r.x)+b.maxWidth+10,H=B(f.y,r.y)-b.maxHeight-10,L=y(f.y,r.y)+b.maxHeight+10,E=u.chartObstacles;var z=a(E,p);b=a(E,I);E=E.slice(z,b+1);if(-1<(b=v(E,r))){var m=h(E[b],r,f);d.push({end:r,start:m});r=m}for(;-1<(b=v(E,r));)z=0>r[l]-f[l], +m={x:r.x,y:r.y},m[l]=E[b][z?l+"Max":l+"Min"]+(z?1:-1),d.push({end:r,start:m}),r=m;f=A(f,r,e);f=f.concat(d.reverse());return{path:n(f),obstacles:f}},{requiresObstacles:!0})}});G(k,"parts-gantt/ArrowSymbols.js",[k["parts/Globals.js"]],function(k){k.SVGRenderer.prototype.symbols.arrow=function(a,k,n,x){return[["M",a,k+x/2],["L",a+n,k],["L",a,k+x/2],["L",a+n,k+x]]};k.SVGRenderer.prototype.symbols["arrow-half"]=function(a,v,n,x){return k.SVGRenderer.prototype.symbols.arrow(a,v,n/2,x)};k.SVGRenderer.prototype.symbols["triangle-left"]= +function(a,k,n,x){return[["M",a+n,k],["L",a,k+x/2],["L",a+n,k+x],["Z"]]};k.SVGRenderer.prototype.symbols["arrow-filled"]=k.SVGRenderer.prototype.symbols["triangle-left"];k.SVGRenderer.prototype.symbols["triangle-left-half"]=function(a,v,n,x){return k.SVGRenderer.prototype.symbols["triangle-left"](a,v,n/2,x)};k.SVGRenderer.prototype.symbols["arrow-filled-half"]=k.SVGRenderer.prototype.symbols["triangle-left-half"]});G(k,"parts-gantt/Pathfinder.js",[k["parts/Globals.js"],k["parts/Point.js"],k["parts/Utilities.js"], +k["parts-gantt/PathfinderAlgorithms.js"]],function(k,a,v,n){function x(c){var b=c.shapeArgs;return b?{xMin:b.x,xMax:b.x+b.width,yMin:b.y,yMax:b.y+b.height}:(b=c.graphic&&c.graphic.getBBox())?{xMin:c.plotX-b.width/2,xMax:c.plotX+b.width/2,yMin:c.plotY-b.height/2,yMax:c.plotY+b.height/2}:null}function q(c){for(var b=c.length,e=0,a,f,g=[],h=function(b,c,e){e=A(e,10);var m=b.yMax+e>c.yMin-e&&b.yMin-ec.xMin-e&&b.xMin-ec.xMax?b.xMin-c.xMax:c.xMin-b.xMax:Infinity, +t=a?b.yMin>c.yMax?b.yMin-c.yMax:c.yMin-b.yMax:Infinity;return a&&m?e?h(b,c,Math.floor(e/2)):Infinity:d(p,t)};ef&&g.push(f);g.push(80);return l(Math.floor(g.sort(function(b,c){return b-c})[Math.floor(g.length/10)]/2-1),1)}function w(c,b,d){this.init(c,b,d)}function B(c){this.init(c)}function y(c){if(c.options.pathfinder||c.series.reduce(function(b,c){c.options&&D(!0,c.options.connectors=c.options.connectors||{},c.options.pathfinder);return b||c.options&&c.options.pathfinder}, +!1))D(!0,c.options.connectors=c.options.connectors||{},c.options.pathfinder),r('WARNING: Pathfinder options have been renamed. Use "chart.connectors" or "series.connectors" instead.')}"";var g=v.addEvent,f=v.defined,r=v.error,u=v.extend,D=v.merge,F=v.objectEach,A=v.pick,h=v.splat,e=k.deg2rad,l=Math.max,d=Math.min;u(k.defaultOptions,{connectors:{type:"straight",lineWidth:1,marker:{enabled:!1,align:"center",verticalAlign:"middle",inside:!1,lineWidth:1},startMarker:{symbol:"diamond"},endMarker:{symbol:"arrow-filled"}}}); +w.prototype={init:function(c,b,d){this.fromPoint=c;this.toPoint=b;this.options=d;this.chart=c.series.chart;this.pathfinder=this.chart.pathfinder},renderPath:function(c,b,d){var e=this.chart,a=e.styledMode,p=e.pathfinder,f=!e.options.chart.forExport&&!1!==d,l=this.graphics&&this.graphics.path;p.group||(p.group=e.renderer.g().addClass("highcharts-pathfinder-group").attr({zIndex:-1}).add(e.seriesGroup));p.group.translate(e.plotLeft,e.plotTop);l&&l.renderer||(l=e.renderer.path().add(p.group),a||l.attr({opacity:0})); +l.attr(b);c={d:c};a||(c.opacity=1);l[f?"animate":"attr"](c,d);this.graphics=this.graphics||{};this.graphics.path=l},addMarker:function(c,b,d){var a=this.fromPoint.series.chart,p=a.pathfinder;a=a.renderer;var f="start"===c?this.fromPoint:this.toPoint,l=f.getPathfinderAnchorPoint(b);if(b.enabled&&((d="start"===c?d[1]:d[d.length-2])&&"M"===d[0]||"L"===d[0])){d={x:d[1],y:d[2]};d=f.getRadiansToVector(d,l);l=f.getMarkerVector(d,b.radius,l);d=-d/e;if(b.width&&b.height){var g=b.width;var m=b.height}else g= +m=2*b.radius;this.graphics=this.graphics||{};l={x:l.x-g/2,y:l.y-m/2,width:g,height:m,rotation:d,rotationOriginX:l.x,rotationOriginY:l.y};this.graphics[c]?this.graphics[c].animate(l):(this.graphics[c]=a.symbol(b.symbol).addClass("highcharts-point-connecting-path-"+c+"-marker").attr(l).add(p.group),a.styledMode||this.graphics[c].attr({fill:b.color||this.fromPoint.color,stroke:b.lineColor,"stroke-width":b.lineWidth,opacity:0}).animate({opacity:1},f.series.options.animation))}},getPath:function(c){var b= +this.pathfinder,d=this.chart,e=b.algorithms[c.type],a=b.chartObstacles;if("function"!==typeof e)r('"'+c.type+'" is not a Pathfinder algorithm.');else return e.requiresObstacles&&!a&&(a=b.chartObstacles=b.getChartObstacles(c),d.options.connectors.algorithmMargin=c.algorithmMargin,b.chartObstacleMetrics=b.getObstacleMetrics(a)),e(this.fromPoint.getPathfinderAnchorPoint(c.startMarker),this.toPoint.getPathfinderAnchorPoint(c.endMarker),D({chartObstacles:a,lineObstacles:b.lineObstacles||[],obstacleMetrics:b.chartObstacleMetrics, +hardBounds:{xMin:0,xMax:d.plotWidth,yMin:0,yMax:d.plotHeight},obstacleOptions:{margin:c.algorithmMargin},startDirectionX:b.getAlgorithmStartDirection(c.startMarker)},c))},render:function(){var c=this.fromPoint,b=c.series,e=b.chart,a=e.pathfinder,g=D(e.options.connectors,b.options.connectors,c.options.connectors,this.options),h={};e.styledMode||(h.stroke=g.lineColor||c.color,h["stroke-width"]=g.lineWidth,g.dashStyle&&(h.dashstyle=g.dashStyle));h["class"]="highcharts-point-connecting-path highcharts-color-"+ +c.colorIndex;g=D(h,g);f(g.marker.radius)||(g.marker.radius=d(l(Math.ceil((g.algorithmMargin||8)/2)-1,1),5));c=this.getPath(g);e=c.path;c.obstacles&&(a.lineObstacles=a.lineObstacles||[],a.lineObstacles=a.lineObstacles.concat(c.obstacles));this.renderPath(e,h,b.options.animation);this.addMarker("start",D(g.marker,g.startMarker),e);this.addMarker("end",D(g.marker,g.endMarker),e)},destroy:function(){this.graphics&&(F(this.graphics,function(c){c.destroy()}),delete this.graphics)}};B.prototype={algorithms:n, +init:function(c){this.chart=c;this.connections=[];g(c,"redraw",function(){this.pathfinder.update()})},update:function(c){var b=this.chart,d=this,e=d.connections;d.connections=[];b.series.forEach(function(c){c.visible&&!c.options.isInternal&&c.points.forEach(function(c){var e,m=c.options&&c.options.connect&&h(c.options.connect);c.visible&&!1!==c.isInside&&m&&m.forEach(function(m){e=b.get("string"===typeof m?m:m.to);e instanceof a&&e.series.visible&&e.visible&&!1!==e.isInside&&d.connections.push(new w(c, +e,"string"===typeof m?{}:m))})})});for(var f=0,l,g,r=e.length,m=d.connections.length;fMath.PI;)c-=e;e=Math.tan(c);c>-p&&c<=p?(k=-1,m=!0):c>p&&c<=Math.PI-p?k=-1:c>Math.PI-p||c<=-(Math.PI-p)?(u=-1,m=!0):u=-1;m?(h+=u*f,r+=k*f*e):(h+=l/(2*e)*u,r+=k*t);d.x!==g&&(h=d.x);d.y!==a&&(r=d.y);n.x=h+b*Math.cos(c);n.y=r-b*Math.sin(c);return n}});k.Chart.prototype.callbacks.push(function(c){!1!== +c.options.connectors.enabled&&(y(c),this.pathfinder=new B(this),this.pathfinder.update(!0))})});G(k,"modules/xrange.src.js",[k["parts/Globals.js"],k["parts/Color.js"],k["parts/Point.js"],k["parts/Utilities.js"]],function(k,a,v,n){var x=a.parse;a=n.addEvent;var q=n.clamp,w=n.correctFloat,B=n.defined,y=n.find,g=n.isNumber,f=n.isObject,r=n.merge,u=n.pick;n=n.seriesType;var D=k.seriesTypes.column,F=k.seriesTypes,A=k.Axis,h=k.Series;n("xrange","column",{colorByPoint:!0,dataLabels:{formatter:function(){var e= +this.point.partialFill;f(e)&&(e=e.amount);if(g(e)&&0{point.x} - {point.x2}
    ',pointFormat:'\u25cf {series.name}: {point.yCategory}
    '},borderRadius:3,pointRange:0},{type:"xrange",parallelArrays:["x","x2","y"],requireSorting:!1,animate:F.line.prototype.animate,cropShoulder:1,getExtremesFromAll:!0,autoIncrement:k.noop,buildKDTree:k.noop, +init:function(){F.column.prototype.init.apply(this,arguments);this.options.stacking=void 0},getColumnMetrics:function(){function e(){a.series.forEach(function(c){var b=c.xAxis;c.xAxis=c.yAxis;c.yAxis=b})}var a=this.chart;e();var d=D.prototype.getColumnMetrics.call(this);e();return d},cropData:function(e,a,d,c){a=h.prototype.cropData.call(this,this.x2Data,a,d,c);a.xData=e.slice(a.start,a.end);return a},findPointIndex:function(e){var a=this.cropped,d=this.cropStart,c=this.points,b=e.id;if(b)var f=(f= +y(c,function(c){return c.id===b}))?f.index:void 0;"undefined"===typeof f&&(f=(f=y(c,function(b){return b.x===e.x&&b.x2===e.x2&&!b.touched}))?f.index:void 0);a&&g(f)&&g(d)&&f>=d&&(f-=d);return f},translatePoint:function(e){var a=this.xAxis,d=this.yAxis,c=this.columnMetrics,b=this.options,p=b.minPointLength||0,h=e.plotX,k=u(e.x2,e.x+(e.len||0)),n=a.translate(k,0,0,0,1);k=Math.abs(n-h);var y=this.chart.inverted,z=u(b.borderWidth,1)%2/2,m=c.offset,t=Math.round(c.width);p&&(p-=k,0>p&&(p=0),h-=p/2,n+=p/ +2);h=Math.max(h,-10);n=q(n,-10,a.len+10);B(e.options.pointWidth)&&(m-=(Math.ceil(e.options.pointWidth)-t)/2,t=Math.ceil(e.options.pointWidth));b.pointPlacement&&g(e.plotY)&&d.categories&&(e.plotY=d.translate(e.y,0,1,0,1,b.pointPlacement));e.shapeArgs={x:Math.floor(Math.min(h,n))+z,y:Math.floor(e.plotY+m)+z,width:Math.round(Math.abs(n-h)),height:t,r:this.options.borderRadius};b=e.shapeArgs.x;p=b+e.shapeArgs.width;0>b||p>a.len?(b=q(b,0,a.len),p=q(p,0,a.len),n=p-b,e.dlBox=r(e.shapeArgs,{x:b,width:p- +b,centerX:n?n/2:null})):e.dlBox=null;b=e.tooltipPos;p=y?1:0;n=y?0:1;c=this.columnMetrics?this.columnMetrics.offset:-c.width/2;b[p]=q(b[p]+k/2*(a.reversed?-1:1)*(y?-1:1),0,a.len-1);b[n]=q(b[n]+(y?-1:1)*c,0,d.len-1);if(c=e.partialFill)f(c)&&(c=c.amount),g(c)||(c=0),d=e.shapeArgs,e.partShapeArgs={x:d.x,y:d.y,width:d.width,height:d.height,r:this.options.borderRadius},h=Math.max(Math.round(k*c+e.plotX-h),0),e.clipRectArgs={x:a.reversed?d.x+k-h:d.x,y:d.y,width:h,height:d.height}},translate:function(){D.prototype.translate.apply(this, +arguments);this.points.forEach(function(e){this.translatePoint(e)},this)},drawPoint:function(e,a){var d=this.options,c=this.chart.renderer,b=e.graphic,p=e.shapeType,g=e.shapeArgs,l=e.partShapeArgs,h=e.clipRectArgs,n=e.partialFill,k=d.stacking&&!d.borderRadius,m=e.state,t=d.states[m||"normal"]||{},C="undefined"===typeof m?"attr":a;m=this.pointAttribs(e,m);t=u(this.chart.options.chart.animation,t.animation);if(e.isNull||!1===e.visible)b&&(e.graphic=b.destroy());else{if(b)b.rect[a](g);else e.graphic= +b=c.g("point").addClass(e.getClassName()).add(e.group||this.group),b.rect=c[p](r(g)).addClass(e.getClassName()).addClass("highcharts-partfill-original").add(b);l&&(b.partRect?(b.partRect[a](r(l)),b.partialClipRect[a](r(h))):(b.partialClipRect=c.clipRect(h.x,h.y,h.width,h.height),b.partRect=c[p](l).addClass("highcharts-partfill-overlay").add(b).clip(b.partialClipRect)));this.chart.styledMode||(b.rect[a](m,t).shadow(d.shadow,null,k),l&&(f(n)||(n={}),f(d.partialFill)&&(n=r(n,d.partialFill)),e=n.fill|| +x(m.fill).brighten(-.3).get()||x(e.color||this.color).brighten(-.3).get(),m.fill=e,b.partRect[C](m,t).shadow(d.shadow,null,k)))}},drawPoints:function(){var e=this,a=e.getAnimationVerb();e.points.forEach(function(d){e.drawPoint(d,a)})},getAnimationVerb:function(){return this.chart.pointCount<(this.options.animationLimit||250)?"animate":"attr"}},{resolveColor:function(){var e=this.series;if(e.options.colorByPoint&&!this.options.color){var a=e.options.colors||e.chart.options.colors;var d=this.y%(a?a.length: +e.chart.options.chart.colorCount);a=a&&a[d];e.chart.styledMode||(this.color=a);this.options.colorIndex||(this.colorIndex=d)}else this.color||(this.color=e.color)},init:function(){v.prototype.init.apply(this,arguments);this.y||(this.y=0);return this},setState:function(){v.prototype.setState.apply(this,arguments);this.series.drawPoint(this,this.series.getAnimationVerb())},getLabelConfig:function(){var e=v.prototype.getLabelConfig.call(this),a=this.series.yAxis.categories;e.x2=this.x2;e.yCategory=this.yCategory= +a&&a[this.y];return e},tooltipDateKeys:["x","x2"],isValid:function(){return"number"===typeof this.x&&"number"===typeof this.x2}});a(A,"afterGetSeriesExtremes",function(){var e=this.series,a;if(this.isXAxis){var d=u(this.dataMax,-Number.MAX_VALUE);e.forEach(function(c){c.x2Data&&c.x2Data.forEach(function(b){b>d&&(d=b,a=!0)})});a&&(this.dataMax=d)}});""});G(k,"parts-gantt/GanttSeries.js",[k["parts/Globals.js"],k["parts/Utilities.js"]],function(k,a){var v=a.isNumber,n=a.merge,x=a.pick,q=a.seriesType, +w=a.splat,B=k.dateFormat,y=k.seriesTypes.xrange;q("gantt","xrange",{grouping:!1,dataLabels:{enabled:!0},tooltip:{headerFormat:'{series.name}
    ',pointFormat:null,pointFormatter:function(){var a=this.series,f=a.chart.tooltip,r=a.xAxis,n=a.tooltipOptions.dateTimeLabelFormats,k=r.options.startOfWeek,q=a.tooltipOptions,y=q.xDateFormat;a=this.options.milestone;var h=""+(this.name||this.yCategory)+"";if(q.pointFormat)return this.tooltipFormatter(q.pointFormat); +y||(y=w(f.getDateFormat(r.closestPointRange,this.start,k,n))[0]);f=B(y,this.start);r=B(y,this.end);h+="
    ";return a?h+(f+"
    "):h+("Start: "+f+"
    End: ")+(r+"
    ")}},connectors:{type:"simpleConnect",animation:{reversed:!0},startMarker:{enabled:!0,symbol:"arrow-filled",radius:4,fill:"#fa0",align:"left"},endMarker:{enabled:!1,align:"right"}}},{pointArrayMap:["start","end","y"],keyboardMoveVertical:!1,translatePoint:function(a){y.prototype.translatePoint.call(this,a);if(a.options.milestone){var f= +a.shapeArgs;var g=f.height;a.shapeArgs={x:f.x-g/2,y:f.y,width:g,height:g}}},drawPoint:function(a,f){var g=this.options,n=this.chart.renderer,k=a.shapeArgs,q=a.plotY,x=a.graphic,h=a.selected&&"select",e=g.stacking&&!g.borderRadius;if(a.options.milestone)if(v(q)&&null!==a.y&&!1!==a.visible){k=n.symbols.diamond(k.x,k.y,k.width,k.height);if(x)x[f]({d:k});else a.graphic=n.path(k).addClass(a.getClassName(),!0).add(a.group||this.group);this.chart.styledMode||a.graphic.attr(this.pointAttribs(a,h)).shadow(g.shadow, +null,e)}else x&&(a.graphic=x.destroy());else y.prototype.drawPoint.call(this,a,f)},setData:k.Series.prototype.setData,setGanttPointAliases:function(a){function f(f,g){"undefined"!==typeof g&&(a[f]=g)}f("x",x(a.start,a.x));f("x2",x(a.end,a.x2));f("partialFill",x(a.completed,a.partialFill));f("connect",x(a.dependency,a.connect))}},n(y.prototype.pointClass.prototype,{applyOptions:function(a,f){a=n(a);k.seriesTypes.gantt.prototype.setGanttPointAliases(a);return a=y.prototype.pointClass.prototype.applyOptions.call(this, +a,f)},isValid:function(){return("number"===typeof this.start||"number"===typeof this.x)&&("number"===typeof this.end||"number"===typeof this.x2||this.milestone)}}));""});G(k,"parts-gantt/GanttChart.js",[k["parts/Globals.js"],k["parts/Utilities.js"]],function(k,a){var v=a.isArray,n=a.merge,x=a.splat,q=k.Chart;k.ganttChart=function(a,w,y){var g="string"===typeof a||a.nodeName,f=w.series,r=k.getOptions(),u,D=w;w=arguments[g?1:0];v(w.xAxis)||(w.xAxis=[w.xAxis||{},{}]);w.xAxis=w.xAxis.map(function(a,f){1=== +f&&(u=0);return n(r.xAxis,{grid:{enabled:!0},opposite:!0,linkedTo:u},a,{type:"datetime"})});w.yAxis=x(w.yAxis||{}).map(function(a){return n(r.yAxis,{grid:{enabled:!0},staticScale:50,reversed:!0,type:a.categories?a.type:"treegrid"},a)});w.series=null;w=n(!0,{chart:{type:"gantt"},title:{text:null},legend:{enabled:!1}},w,{isGantt:!0});w.series=D.series=f;w.series.forEach(function(a){a.data.forEach(function(a){k.seriesTypes.gantt.prototype.setGanttPointAliases(a)})});return g?new q(a,w,y):new q(w,w)}}); +G(k,"parts/ScrollbarAxis.js",[k["parts/Globals.js"],k["parts/Utilities.js"]],function(k,a){var v=a.addEvent,n=a.defined,x=a.pick;return function(){function a(){}a.compose=function(a,q){v(a,"afterInit",function(){var a=this;a.options&&a.options.scrollbar&&a.options.scrollbar.enabled&&(a.options.scrollbar.vertical=!a.horiz,a.options.startOnTick=a.options.endOnTick=!1,a.scrollbar=new q(a.chart.renderer,a.options.scrollbar,a.chart),v(a.scrollbar,"changed",function(g){var f=x(a.options&&a.options.min, +a.min),r=x(a.options&&a.options.max,a.max),u=n(a.dataMin)?Math.min(f,a.min,a.dataMin):f,q=(n(a.dataMax)?Math.max(r,a.max,a.dataMax):r)-u;n(f)&&n(r)&&(a.horiz&&!a.reversed||!a.horiz&&a.reversed?(f=u+q*this.to,u+=q*this.from):(f=u+q*(1-this.from),u+=q*(1-this.to)),x(this.options.liveRedraw,k.svg&&!k.isTouchDevice&&!this.chart.isBoosting)||"mouseup"===g.DOMType||!n(g.DOMType)?a.setExtremes(u,f,!0,"mousemove"!==g.DOMType,g):this.setRange(this.from,this.to))}))});v(a,"afterRender",function(){var a=Math.min(x(this.options.min, +this.min),this.min,x(this.dataMin,this.min)),g=Math.max(x(this.options.max,this.max),this.max,x(this.dataMax,this.max)),f=this.scrollbar,k=this.axisTitleMargin+(this.titleOffset||0),u=this.chart.scrollbarsOffsets,q=this.options.margin||0;f&&(this.horiz?(this.opposite||(u[1]+=k),f.position(this.left,this.top+this.height+2+u[1]-(this.opposite?q:0),this.width,this.height),this.opposite||(u[1]+=q),k=1):(this.opposite&&(u[0]+=k),f.position(this.left+this.width+2+u[0]-(this.opposite?0:q),this.top,this.width, +this.height),this.opposite&&(u[0]+=q),k=0),u[k]+=f.size+f.options.margin,isNaN(a)||isNaN(g)||!n(this.min)||!n(this.max)||this.min===this.max?f.setRange(0,1):(u=(this.min-a)/(g-a),a=(this.max-a)/(g-a),this.horiz&&!this.reversed||!this.horiz&&this.reversed?f.setRange(u,a):f.setRange(1-a,1-u)))});v(a,"afterGetOffset",function(){var a=this.horiz?2:1,g=this.scrollbar;g&&(this.chart.scrollbarsOffsets=[0,0],this.chart.axisOffset[a]+=g.size+g.options.margin)})};return a}()});G(k,"parts/Scrollbar.js",[k["parts/Axis.js"], +k["parts/Globals.js"],k["parts/ScrollbarAxis.js"],k["parts/Utilities.js"]],function(k,a,v,n){var x=n.addEvent,q=n.correctFloat,w=n.defined,B=n.destroyObjectProperties,y=n.fireEvent,g=n.merge,f=n.pick,r=n.removeEvent;n=a.defaultOptions;var u=a.hasTouch,D=a.isTouchDevice,F=a.swapXY=function(a,e){e&&a.forEach(function(a){for(var d=a.length,c,b=0;bthis.calculatedWidth?e.minWidth:0;return{chartX:(a.chartX- +this.x-this.xOffset)/(this.barWidth-e),chartY:(a.chartY-this.y-this.yOffset)/(this.barWidth-e)}};a.prototype.destroy=function(){var a=this.chart.scroller;this.removeEvents();["track","scrollbarRifles","scrollbar","scrollbarGroup","group"].forEach(function(a){this[a]&&this[a].destroy&&(this[a]=this[a].destroy())},this);a&&this===a.scrollbar&&(a.scrollbar=null,B(a.scrollbarButtons))};a.prototype.drawScrollbarButton=function(a){var e=this.renderer,d=this.scrollbarButtons,c=this.options,b=this.size;var f= +e.g().add(this.group);d.push(f);f=e.rect().addClass("highcharts-scrollbar-button").add(f);this.chart.styledMode||f.attr({stroke:c.buttonBorderColor,"stroke-width":c.buttonBorderWidth,fill:c.buttonBackgroundColor});f.attr(f.crisp({x:-.5,y:-.5,width:b+1,height:b+1,r:c.buttonBorderRadius},f.strokeWidth()));f=e.path(F([["M",b/2+(a?-1:1),b/2-3],["L",b/2+(a?-1:1),b/2+3],["L",b/2+(a?2:-2),b/2]],c.vertical)).addClass("highcharts-scrollbar-arrow").add(d[a]);this.chart.styledMode||f.attr({fill:c.buttonArrowColor})}; +a.prototype.init=function(e,h,d){this.scrollbarButtons=[];this.renderer=e;this.userOptions=h;this.options=g(a.defaultOptions,h);this.chart=d;this.size=f(this.options.size,this.options.height);h.enabled&&(this.render(),this.addEvents())};a.prototype.mouseDownHandler=function(a){a=this.chart.pointer.normalize(a);a=this.cursorToScrollbarPosition(a);this.chartX=a.chartX;this.chartY=a.chartY;this.initPositions=[this.from,this.to];this.grabbedCenter=!0};a.prototype.mouseMoveHandler=function(a){var e=this.chart.pointer.normalize(a), +d=this.options.vertical?"chartY":"chartX",c=this.initPositions||[];!this.grabbedCenter||a.touches&&0===a.touches[0][d]||(e=this.cursorToScrollbarPosition(e)[d],d=this[d],d=e-d,this.hasDragged=!0,this.updatePosition(c[0]+d,c[1]+d),this.hasDragged&&y(this,"changed",{from:this.from,to:this.to,trigger:"scrollbar",DOMType:a.type,DOMEvent:a}))};a.prototype.mouseUpHandler=function(a){this.hasDragged&&y(this,"changed",{from:this.from,to:this.to,trigger:"scrollbar",DOMType:a.type,DOMEvent:a});this.grabbedCenter= +this.hasDragged=this.chartX=this.chartY=null};a.prototype.position=function(a,f,d,c){var b=this.options.vertical,e=0,g=this.rendered?"animate":"attr";this.x=a;this.y=f+this.trackBorderWidth;this.width=d;this.xOffset=this.height=c;this.yOffset=e;b?(this.width=this.yOffset=d=e=this.size,this.xOffset=f=0,this.barWidth=c-2*d,this.x=a+=this.options.margin):(this.height=this.xOffset=c=f=this.size,this.barWidth=d-2*c,this.y+=this.options.margin);this.group[g]({translateX:a,translateY:this.y});this.track[g]({width:d, +height:c});this.scrollbarButtons[1][g]({translateX:b?0:d-f,translateY:b?c-e:0})};a.prototype.removeEvents=function(){this._events.forEach(function(a){r.apply(null,a)});this._events.length=0};a.prototype.render=function(){var a=this.renderer,f=this.options,d=this.size,c=this.chart.styledMode,b;this.group=b=a.g("scrollbar").attr({zIndex:f.zIndex,translateY:-99999}).add();this.track=a.rect().addClass("highcharts-scrollbar-track").attr({x:0,r:f.trackBorderRadius||0,height:d,width:d}).add(b);c||this.track.attr({fill:f.trackBackgroundColor, +stroke:f.trackBorderColor,"stroke-width":f.trackBorderWidth});this.trackBorderWidth=this.track.strokeWidth();this.track.attr({y:-this.trackBorderWidth%2/2});this.scrollbarGroup=a.g().add(b);this.scrollbar=a.rect().addClass("highcharts-scrollbar-thumb").attr({height:d,width:d,r:f.barBorderRadius||0}).add(this.scrollbarGroup);this.scrollbarRifles=a.path(F([["M",-3,d/4],["L",-3,2*d/3],["M",0,d/4],["L",0,2*d/3],["M",3,d/4],["L",3,2*d/3]],f.vertical)).addClass("highcharts-scrollbar-rifles").add(this.scrollbarGroup); +c||(this.scrollbar.attr({fill:f.barBackgroundColor,stroke:f.barBorderColor,"stroke-width":f.barBorderWidth}),this.scrollbarRifles.attr({stroke:f.rifleColor,"stroke-width":1}));this.scrollbarStrokeWidth=this.scrollbar.strokeWidth();this.scrollbarGroup.translate(-this.scrollbarStrokeWidth%2/2,-this.scrollbarStrokeWidth%2/2);this.drawScrollbarButton(0);this.drawScrollbarButton(1)};a.prototype.setRange=function(a,f){var d=this.options,c=d.vertical,b=d.minWidth,e=this.barWidth,g,h=!this.rendered||this.hasDragged|| +this.chart.navigator&&this.chart.navigator.hasDragged?"attr":"animate";if(w(e)){a=Math.max(a,0);var l=Math.ceil(e*a);this.calculatedWidth=g=q(e*Math.min(f,1)-l);g=g?this.scrollbarRifles.hide():this.scrollbarRifles.show(!0);!1===d.showFull&&(0>=a&&1<=f?this.group.hide():this.group.show());this.rendered=!0}};a.prototype.trackClick=function(a){var e=this.chart.pointer.normalize(a),d=this.to-this.from,c=this.y+this.scrollbarTop,b=this.x+this.scrollbarLeft;this.options.vertical&&e.chartY>c||!this.options.vertical&&e.chartX>b?this.updatePosition(this.from+d,this.to+d):this.updatePosition(this.from-d,this.to-d);y(this, +"changed",{from:this.from,to:this.to,trigger:"scrollbar",DOMEvent:a})};a.prototype.update=function(a){this.destroy();this.init(this.chart.renderer,g(!0,this.options,a),this.chart)};a.prototype.updatePosition=function(a,f){1a&&(f=q(f-a),a=0);this.from=a;this.to=f};a.defaultOptions={height:D?20:14,barBorderRadius:0,buttonBorderRadius:0,liveRedraw:void 0,margin:10,minWidth:6,step:.2,zIndex:3,barBackgroundColor:"#cccccc",barBorderWidth:1,barBorderColor:"#cccccc",buttonArrowColor:"#333333", +buttonBackgroundColor:"#e6e6e6",buttonBorderColor:"#cccccc",buttonBorderWidth:1,rifleColor:"#333333",trackBackgroundColor:"#f2f2f2",trackBorderColor:"#f2f2f2",trackBorderWidth:1};return a}();a.Scrollbar||(n.scrollbar=g(!0,A.defaultOptions,n.scrollbar),a.Scrollbar=A,v.compose(k,A));return a.Scrollbar});G(k,"parts/RangeSelector.js",[k["parts/Globals.js"],k["parts/Utilities.js"]],function(k,a){function v(a){this.init(a)}var n=a.addEvent,x=a.createElement,q=a.css,w=a.defined,B=a.destroyObjectProperties, +y=a.discardElement,g=a.extend,f=a.fireEvent,r=a.isNumber,u=a.merge,D=a.objectEach,F=a.pick,A=a.pInt,h=a.splat,e=k.Axis;a=k.Chart;var l=k.defaultOptions;g(l,{rangeSelector:{verticalAlign:"top",buttonTheme:{width:28,height:18,padding:2,zIndex:7},floating:!1,x:0,y:0,height:void 0,inputPosition:{align:"right",x:0,y:0},buttonPosition:{align:"left",x:0,y:0},labelStyle:{color:"#666666"}}});l.lang=u(l.lang,{rangeSelectorZoom:"Zoom",rangeSelectorFrom:"From",rangeSelectorTo:"To"});v.prototype={clickButton:function(a, +c){var b=this.chart,d=this.buttonOptions[a],f=b.xAxis[0],g=b.scroller&&b.scroller.getUnionExtremes()||f||{},k=g.dataMin,l=g.dataMax,z=f&&Math.round(Math.min(f.max,F(l,f.max))),m=d.type;g=d._range;var t,C=d.dataGrouping;if(null!==k&&null!==l){b.fixedRange=g;C&&(this.forcedDataGrouping=!0,e.prototype.setDataGrouping.call(f||{chart:this.chart},C,!1),this.frozenStates=d.preserveDataGrouping);if("month"===m||"year"===m)if(f){m={range:d,max:z,chart:b,dataMin:k,dataMax:l};var u=f.minFromRange.call(m);r(m.newMax)&& +(z=m.newMax)}else g=d;else if(g)u=Math.max(z-g,k),z=Math.min(u+g,l);else if("ytd"===m)if(f)"undefined"===typeof l&&(k=Number.MAX_VALUE,l=Number.MIN_VALUE,b.series.forEach(function(b){b=b.xData;k=Math.min(b[0],k);l=Math.max(b[b.length-1],l)}),c=!1),z=this.getYTDExtremes(l,k,b.time.useUTC),u=t=z.min,z=z.max;else{this.deferredYTDClick=a;return}else"all"===m&&f&&(u=k,z=l);u+=d._offsetMin;z+=d._offsetMax;this.setSelected(a);if(f)f.setExtremes(u,z,F(c,1),null,{trigger:"rangeSelectorButton",rangeSelectorButton:d}); +else{var q=h(b.options.xAxis)[0];var v=q.range;q.range=g;var x=q.min;q.min=t;n(b,"load",function(){q.range=v;q.min=x})}}},setSelected:function(a){this.selected=this.options.selected=a},defaultButtons:[{type:"month",count:1,text:"1m"},{type:"month",count:3,text:"3m"},{type:"month",count:6,text:"6m"},{type:"ytd",text:"YTD"},{type:"year",count:1,text:"1y"},{type:"all",text:"All"}],init:function(a){var c=this,b=a.options.rangeSelector,d=b.buttons||[].concat(c.defaultButtons),e=b.selected,g=function(){var b= +c.minInput,a=c.maxInput;b&&b.blur&&f(b,"blur");a&&a.blur&&f(a,"blur")};c.chart=a;c.options=b;c.buttons=[];c.buttonOptions=d;this.unMouseDown=n(a.container,"mousedown",g);this.unResize=n(a,"resize",g);d.forEach(c.computeButtonRange);"undefined"!==typeof e&&d[e]&&this.clickButton(e,!1);n(a,"load",function(){a.xAxis&&a.xAxis[0]&&n(a.xAxis[0],"setExtremes",function(b){this.max-this.min!==a.fixedRange&&"rangeSelectorButton"!==b.trigger&&"updatedData"!==b.trigger&&c.forcedDataGrouping&&!c.frozenStates&& +this.setDataGrouping(!1,!1)})})},updateButtonStates:function(){var a=this,c=this.chart,b=c.xAxis[0],e=Math.round(b.max-b.min),f=!b.hasVisibleSeries,g=c.scroller&&c.scroller.getUnionExtremes()||b,h=g.dataMin,k=g.dataMax;c=a.getYTDExtremes(k,h,c.time.useUTC);var l=c.min,m=c.max,t=a.selected,n=r(t),u=a.options.allButtonsEnabled,q=a.buttons;a.buttonOptions.forEach(function(c,d){var g=c._range,p=c.type,C=c.count||1,r=q[d],z=0,J=c._offsetMax-c._offsetMin;c=d===t;var K=g>k-h,v=g=864E5*{month:28,year:365}[p]*C-J&&e-36E5<=864E5*{month:31,year:366}[p]*C+J?g=!0:"ytd"===p?(g=m-l+J===e,x=!c):"all"===p&&(g=b.max-b.min>=k-h,T=!c&&n&&g);p=!u&&(K||v||T||f);C=c&&g||g&&!n&&!x||c&&a.frozenStates;p?z=3:C&&(n=!0,z=2);r.state!==z&&(r.setState(z),0===z&&t===d&&a.setSelected(null))})},computeButtonRange:function(a){var c=a.type,b=a.count||1,d={millisecond:1,second:1E3,minute:6E4,hour:36E5,day:864E5,week:6048E5};if(d[c])a._range=d[c]*b;else if("month"=== +c||"year"===c)a._range=864E5*{month:30,year:365}[c]*b;a._offsetMin=F(a.offsetMin,0);a._offsetMax=F(a.offsetMax,0);a._range+=a._offsetMax-a._offsetMin},setInputValue:function(a,c){var b=this.chart.options.rangeSelector,d=this.chart.time,e=this[a+"Input"];w(c)&&(e.previousValue=e.HCTime,e.HCTime=c);e.value=d.dateFormat(b.inputEditDateFormat||"%Y-%m-%d",e.HCTime);this[a+"DateBox"].attr({text:d.dateFormat(b.inputDateFormat||"%b %e, %Y",e.HCTime)})},showInput:function(a){var c=this.inputGroup,b=this[a+ +"DateBox"];q(this[a+"Input"],{left:c.translateX+b.x+"px",top:c.translateY+"px",width:b.width-2+"px",height:b.height-2+"px",border:"2px solid silver"})},hideInput:function(a){q(this[a+"Input"],{border:0,width:"1px",height:"1px"});this.setInputValue(a)},drawInput:function(a){function c(){var a=m.value,c=(h.inputDateParser||Date.parse)(a),e=d.xAxis[0],f=d.scroller&&d.scroller.xAxis?d.scroller.xAxis:e,t=f.dataMin;f=f.dataMax;c!==m.previousValue&&(m.previousValue=c,r(c)||(c=a.split("-"),c=Date.UTC(A(c[0]), +A(c[1])-1,A(c[2]))),r(c)&&(d.time.useUTC||(c+=6E4*(new Date).getTimezoneOffset()),z?c>b.maxInput.HCTime?c=void 0:cf&&(c=f),"undefined"!==typeof c&&e.setExtremes(z?c:e.min,z?e.max:c,void 0,void 0,{trigger:"rangeSelectorInput"})))}var b=this,d=b.chart,e=d.renderer.style||{},f=d.renderer,h=d.options.rangeSelector,n=b.div,z="min"===a,m,t,C=this.inputGroup;this[a+"Label"]=t=f.label(l.lang[z?"rangeSelectorFrom":"rangeSelectorTo"],this.inputGroup.offset).addClass("highcharts-range-label").attr({padding:2}).add(C); +C.offset+=t.width+5;this[a+"DateBox"]=f=f.label("",C.offset).addClass("highcharts-range-input").attr({padding:2,width:h.inputBoxWidth||90,height:h.inputBoxHeight||17,"text-align":"center"}).on("click",function(){b.showInput(a);b[a+"Input"].focus()});d.styledMode||f.attr({stroke:h.inputBoxBorderColor||"#cccccc","stroke-width":1});f.add(C);C.offset+=f.width+(z?10:0);this[a+"Input"]=m=x("input",{name:a,className:"highcharts-range-selector",type:"text"},{top:d.plotTop+"px"},n);d.styledMode||(t.css(u(e, +h.labelStyle)),f.css(u({color:"#333333"},e,h.inputStyle)),q(m,g({position:"absolute",border:0,width:"1px",height:"1px",padding:0,textAlign:"center",fontSize:e.fontSize,fontFamily:e.fontFamily,top:"-9999em"},h.inputStyle)));m.onfocus=function(){b.showInput(a)};m.onblur=function(){m===k.doc.activeElement&&c();b.hideInput(a);m.blur()};m.onchange=c;m.onkeypress=function(a){13===a.keyCode&&c()}},getPosition:function(){var a=this.chart,c=a.options.rangeSelector;a="top"===c.verticalAlign?a.plotTop-a.axisOffset[0]: +0;return{buttonTop:a+c.buttonPosition.y,inputTop:a+c.inputPosition.y-10}},getYTDExtremes:function(a,c,b){var d=this.chart.time,e=new d.Date(a),f=d.get("FullYear",e);b=b?d.Date.UTC(f,0,1):+new d.Date(f,0,1);c=Math.max(c||0,b);e=e.getTime();return{max:Math.min(a||e,e),min:c}},render:function(a,c){var b=this,d=b.chart,e=d.renderer,f=d.container,g=d.options,h=g.exporting&&!1!==g.exporting.enabled&&g.navigation&&g.navigation.buttonOptions,k=l.lang,m=b.div,t=g.rangeSelector,n=F(g.chart.style&&g.chart.style.zIndex, +0)+1;g=t.floating;var r=b.buttons;m=b.inputGroup;var u=t.buttonTheme,q=t.buttonPosition,v=t.inputPosition,R=t.inputEnabled,w=u&&u.states,y=d.plotLeft,A=b.buttonGroup,S,D=b.options.verticalAlign,B=d.legend,P=B&&B.options,G=q.y,O=v.y,Q=d.hasLoaded,U=Q?"animate":"attr",N=0,M=0;if(!1!==t.enabled){b.rendered||(b.group=S=e.g("range-selector-group").attr({zIndex:7}).add(),b.buttonGroup=A=e.g("range-selector-buttons").add(S),b.zoomText=e.text(k.rangeSelectorZoom,0,15).add(A),d.styledMode||(b.zoomText.css(t.labelStyle), +u["stroke-width"]=F(u["stroke-width"],0)),b.buttonOptions.forEach(function(a,c){r[c]=e.button(a.text,0,0,function(d){var e=a.events&&a.events.click,f;e&&(f=e.call(a,d));!1!==f&&b.clickButton(c);b.isActive=!0},u,w&&w.hover,w&&w.select,w&&w.disabled).attr({"text-align":"center"}).add(A)}),!1!==R&&(b.div=m=x("div",null,{position:"relative",height:0,zIndex:n}),f.parentNode.insertBefore(m,f),b.inputGroup=m=e.g("input-group").add(S),m.offset=0,b.drawInput("min"),b.drawInput("max")));b.zoomText[U]({x:F(y+ +q.x,y)});var V=F(y+q.x,y)+b.zoomText.getBBox().width+5;b.buttonOptions.forEach(function(a,b){r[b][U]({x:V});V+=r[b].width+F(t.buttonSpacing,5)});y=d.plotLeft-d.spacing[3];b.updateButtonStates();h&&this.titleCollision(d)&&"top"===D&&"right"===q.align&&q.y+A.getBBox().height-12<(h.y||0)+h.height&&(N=-40);f=q.x-d.spacing[3];"right"===q.align?f+=N-y:"center"===q.align&&(f-=y/2);A.align({y:q.y,width:A.getBBox().width,align:q.align,x:f},!0,d.spacingBox);b.group.placed=Q;b.buttonGroup.placed=Q;!1!==R&&(N= +h&&this.titleCollision(d)&&"top"===D&&"right"===v.align&&v.y-m.getBBox().height-12<(h.y||0)+h.height+d.spacing[0]?-40:0,"left"===v.align?f=y:"right"===v.align&&(f=-Math.max(d.axisOffset[1],-N)),m.align({y:v.y,width:m.getBBox().width,align:v.align,x:v.x+f-2},!0,d.spacingBox),h=m.alignAttr.translateX+m.alignOptions.x-N+m.getBBox().x+2,f=m.alignOptions.width,k=A.alignAttr.translateX+A.getBBox().x,y=A.getBBox().width+20,(v.align===q.align||k+y>h&&h+f>k&&G=-N?0:-N),translateY:m.alignAttr.translateY+A.getBBox().height+10}),b.setInputValue("min",a),b.setInputValue("max",c),b.inputGroup.placed=Q);b.group.align({verticalAlign:D},!0,d.spacingBox);a=b.group.getBBox().height+20;c=b.group.alignAttr.translateY;"bottom"===D&&(B=P&&"bottom"===P.verticalAlign&&P.enabled&&!P.floating?B.legendHeight+F(P.margin,10):0,a=a+B-20,M=c-a-(g?0:t.y)-(d.titleOffset?d.titleOffset[2]:0)-10);if("top"===D)g&&(M=0),d.titleOffset&&d.titleOffset[0]&&(M=d.titleOffset[0]), +M+=d.margin[0]-d.spacing[0]||0;else if("middle"===D)if(O===G)M=0>O?c+void 0:c;else if(O||G)M=0>O||0>G?M-Math.min(O,G):c-a+NaN;b.group.translate(t.x,t.y+Math.floor(M));!1!==R&&(b.minInput.style.marginTop=b.group.translateY+"px",b.maxInput.style.marginTop=b.group.translateY+"px");b.rendered=!0}},getHeight:function(){var a=this.options,c=this.group,b=a.y,e=a.buttonPosition.y,f=a.inputPosition.y;if(a.height)return a.height;a=c?c.getBBox(!0).height+13+b:0;c=Math.min(f,e);if(0>f&&0>e||0f&&(n?a=g-r:g=a+r);w(a)&&w(g)||(a=g=void 0);return{min:a,max:g}};return a}();return function(){function a(){}a.compose= +function(a){a.keepProps.push("navigatorAxis");n(a,"init",function(){this.navigatorAxis||(this.navigatorAxis=new y(this))});n(a,"zoom",function(a){var f=this.chart.options,g=f.navigator,k=this.navigatorAxis,n=f.chart.pinchType,h=f.rangeSelector;f=f.chart.zoomType;this.isXAxis&&(g&&g.enabled||h&&h.enabled)&&("y"===f?a.zoomed=!1:(!v&&"xy"===f||v&&"xy"===n)&&this.options.range&&(g=k.previousZoom,q(a.newMin)?k.previousZoom=[this.min,this.max]:g&&(a.newMin=g[0],a.newMax=g[1],k.previousZoom=void 0)));"undefined"!== +typeof a.zoomed&&a.preventDefault()})};a.AdditionsClass=y;return a}()});G(k,"parts/Navigator.js",[k["parts/Axis.js"],k["parts/Color.js"],k["parts/Globals.js"],k["parts/NavigatorAxis.js"],k["parts/Scrollbar.js"],k["parts/Utilities.js"]],function(k,a,v,n,x,q){a=a.parse;var w=q.addEvent,B=q.clamp,y=q.correctFloat,g=q.defined,f=q.destroyObjectProperties,r=q.erase,u=q.extend,D=q.find,F=q.isArray,A=q.isNumber,h=q.merge,e=q.pick,l=q.removeEvent,d=q.splat;q=v.Chart;var c=v.defaultOptions,b=v.hasTouch,p=v.isTouchDevice, +G=v.Series,H=function(a){for(var b=[],c=1;cC&&(this.grabbedLeft?c=t.toPixels(b-C-k,!0):this.grabbedRight&&(d=t.toPixels(a+C+k,!0)));this.zoomedMax=B(Math.max(c,d),0,p);this.zoomedMin=B(this.fixedWidth?this.zoomedMax-this.fixedWidth:Math.min(c,d),0,p);this.range=this.zoomedMax-this.zoomedMin;p=Math.round(this.zoomedMax);c=Math.round(this.zoomedMin);n&&(this.navigatorGroup.attr({visibility:"visible"}),r=r&&!this.hasDragged?"animate":"attr",this.drawMasks(c,p,q,r),this.drawOutline(c, +p,q,r),this.navigatorOptions.handles.enabled&&(this.drawHandle(c,0,q,r),this.drawHandle(p,1,q,r)));this.scrollbar&&(q?(q=this.top-m,l=this.left-m+(n||!l.opposite?0:(l.titleOffset||0)+l.axisTitleMargin),m=h+2*m):(q=this.top+(n?this.height:-m),l=this.left-m),this.scrollbar.position(l,q,f,m),this.scrollbar.setRange(this.zoomedMin/(h||1),this.zoomedMax/(h||1)));this.rendered=!0}};a.prototype.addMouseEvents=function(){var a=this,c=a.chart,d=c.container,e=[],f,g;a.mouseMoveHandler=f=function(b){a.onMouseMove(b)}; +a.mouseUpHandler=g=function(b){a.onMouseUp(b)};e=a.getPartsEvents("mousedown");e.push(w(c.renderTo,"mousemove",f),w(d.ownerDocument,"mouseup",g));b&&(e.push(w(c.renderTo,"touchmove",f),w(d.ownerDocument,"touchend",g)),e.concat(a.getPartsEvents("touchstart")));a.eventsToUnbind=e;a.series&&a.series[0]&&e.push(w(a.series[0].xAxis,"foundExtremes",function(){c.navigator.modifyNavigatorAxisExtremes()}))};a.prototype.getPartsEvents=function(a){var b=this,c=[];["shades","handles"].forEach(function(d){b[d].forEach(function(e, +f){c.push(w(e.element,a,function(a){b[d+"Mousedown"](a,f)}))})});return c};a.prototype.shadesMousedown=function(a,b){a=this.chart.pointer.normalize(a);var c=this.chart,d=this.xAxis,e=this.zoomedMin,f=this.left,m=this.size,h=this.range,k=a.chartX;c.inverted&&(k=a.chartY,f=this.top);if(1===b)this.grabbedCenter=k,this.fixedWidth=h,this.dragOffset=k-e;else{a=k-f-h/2;if(0===b)a=Math.max(0,a);else if(2===b&&a+h>=m)if(a=m-h,this.reversedExtremes){a-=h;var t=this.getUnionExtremes().dataMin}else var l=this.getUnionExtremes().dataMax; +a!==e&&(this.fixedWidth=h,b=d.navigatorAxis.toFixedRange(a,a+h,t,l),g(b.min)&&c.xAxis[0].setExtremes(Math.min(b.min,b.max),Math.max(b.min,b.max),!0,null,{trigger:"navigator"}))}};a.prototype.handlesMousedown=function(a,b){this.chart.pointer.normalize(a);a=this.chart;var c=a.xAxis[0],d=this.reversedExtremes;0===b?(this.grabbedLeft=!0,this.otherHandlePos=this.zoomedMax,this.fixedExtreme=d?c.min:c.max):(this.grabbedRight=!0,this.otherHandlePos=this.zoomedMin,this.fixedExtreme=d?c.max:c.min);a.fixedRange= +null};a.prototype.onMouseMove=function(a){var b=this,c=b.chart,d=b.left,f=b.navigatorSize,g=b.range,m=b.dragOffset,h=c.inverted;a.touches&&0===a.touches[0].pageX||(a=c.pointer.normalize(a),c=a.chartX,h&&(d=b.top,c=a.chartY),b.grabbedLeft?(b.hasDragged=!0,b.render(0,0,c-d,b.otherHandlePos)):b.grabbedRight?(b.hasDragged=!0,b.render(0,0,b.otherHandlePos,c-d)):b.grabbedCenter&&(b.hasDragged=!0,cf+m-g&&(c=f+m-g),b.render(0,0,c-m,c-m+g)),b.hasDragged&&b.scrollbar&&e(b.scrollbar.options.liveRedraw, +v.svg&&!p&&!this.chart.isBoosting)&&(a.DOMType=a.type,setTimeout(function(){b.onMouseUp(a)},0)))};a.prototype.onMouseUp=function(a){var b=this.chart,c=this.xAxis,d=this.scrollbar,e=a.DOMEvent||a,f=b.inverted,m=this.rendered&&!this.hasDragged?"animate":"attr",h=Math.round(this.zoomedMax),k=Math.round(this.zoomedMin);if(this.hasDragged&&(!d||!d.hasDragged)||"scrollbar"===a.trigger){d=this.getUnionExtremes();if(this.zoomedMin===this.otherHandlePos)var l=this.fixedExtreme;else if(this.zoomedMax===this.otherHandlePos)var n= +this.fixedExtreme;this.zoomedMax===this.size&&(n=this.reversedExtremes?d.dataMin:d.dataMax);0===this.zoomedMin&&(l=this.reversedExtremes?d.dataMax:d.dataMin);c=c.navigatorAxis.toFixedRange(this.zoomedMin,this.zoomedMax,l,n);g(c.min)&&b.xAxis[0].setExtremes(Math.min(c.min,c.max),Math.max(c.min,c.max),!0,this.hasDragged?!1:null,{trigger:"navigator",triggerOp:"navigator-drag",DOMEvent:e})}"mousemove"!==a.DOMType&&"touchmove"!==a.DOMType&&(this.grabbedLeft=this.grabbedRight=this.grabbedCenter=this.fixedWidth= +this.fixedExtreme=this.otherHandlePos=this.hasDragged=this.dragOffset=null);this.navigatorEnabled&&(this.shades&&this.drawMasks(k,h,f,m),this.outline&&this.drawOutline(k,h,f,m),this.navigatorOptions.handles.enabled&&Object.keys(this.handles).length===this.handles.length&&(this.drawHandle(k,0,f,m),this.drawHandle(h,1,f,m)))};a.prototype.removeEvents=function(){this.eventsToUnbind&&(this.eventsToUnbind.forEach(function(a){a()}),this.eventsToUnbind=void 0);this.removeBaseSeriesEvents()};a.prototype.removeBaseSeriesEvents= +function(){var a=this.baseSeries||[];this.navigatorEnabled&&a[0]&&(!1!==this.navigatorOptions.adaptToUpdatedData&&a.forEach(function(a){l(a,"updatedData",this.updatedDataHandler)},this),a[0].xAxis&&l(a[0].xAxis,"foundExtremes",this.modifyBaseAxisExtremes))};a.prototype.init=function(a){var b=a.options,c=b.navigator,d=c.enabled,f=b.scrollbar,g=f.enabled;b=d?c.height:0;var m=g?f.height:0;this.handles=[];this.shades=[];this.chart=a;this.setBaseSeries();this.height=b;this.scrollbarHeight=m;this.scrollbarEnabled= +g;this.navigatorEnabled=d;this.navigatorOptions=c;this.scrollbarOptions=f;this.outlineHeight=b+m;this.opposite=e(c.opposite,!(d||!a.inverted));var l=this;d=l.baseSeries;f=a.xAxis.length;g=a.yAxis.length;var p=d&&d[0]&&d[0].xAxis||a.xAxis[0]||{options:{}};a.isDirtyBox=!0;l.navigatorEnabled?(l.xAxis=new k(a,h({breaks:p.options.breaks,ordinal:p.options.ordinal},c.xAxis,{id:"navigator-x-axis",yAxis:"navigator-y-axis",isX:!0,type:"datetime",index:f,isInternal:!0,offset:0,keepOrdinalPadding:!0,startOnTick:!1, +endOnTick:!1,minPadding:0,maxPadding:0,zoomEnabled:!1},a.inverted?{offsets:[m,0,-m,0],width:b}:{offsets:[0,-m,0,m],height:b})),l.yAxis=new k(a,h(c.yAxis,{id:"navigator-y-axis",alignTicks:!1,offset:0,index:g,isInternal:!0,zoomEnabled:!1},a.inverted?{width:b}:{height:b})),d||c.series.data?l.updateNavigatorSeries(!1):0===a.series.length&&(l.unbindRedraw=w(a,"beforeRedraw",function(){0m.indexOf(b)?(b&&(l(b,"updatedData",f.updatedDataHandler),delete b.navigatorSeries),a.chart&&a.destroy(),!1):!0});m&&m.length&&m.forEach(function(a){var d=a.navigatorSeries,l=u({color:a.color,visible:a.visible},F(n)?c.navigator.series:n);d&&!1===f.navigatorOptions.adaptToUpdatedData||(q.name="Navigator "+m.length,k=a.options||{},p=k.navigatorOptions||{},t=h(k,q,l,p),t.pointRange=e(l.pointRange,p.pointRange,c.plotOptions[t.type||"line"].pointRange),l=p.data||l.data,f.hasNavigatorData=f.hasNavigatorData|| +!!l,t.data=l||k.data&&k.data.slice(0),d&&d.options?d.update(t,b):(a.navigatorSeries=g.initSeries(t),a.navigatorSeries.baseSeries=a,r.push(a.navigatorSeries)))});if(n.data&&(!m||!m.length)||F(n))f.hasNavigatorData=!1,n=d(n),n.forEach(function(a,b){q.name="Navigator "+(r.length+1);t=h(c.navigator.series,{color:g.series[b]&&!g.series[b].options.isInternal&&g.series[b].color||g.options.colors[b]||g.options.colors[0]},q,a);t.data=a.data;t.data&&(f.hasNavigatorData=!0,r.push(g.initSeries(t)))});a&&this.addBaseSeriesEvents()}; +a.prototype.addBaseSeriesEvents=function(){var a=this,b=a.baseSeries||[];b[0]&&b[0].xAxis&&w(b[0].xAxis,"foundExtremes",this.modifyBaseAxisExtremes);b.forEach(function(b){w(b,"show",function(){this.navigatorSeries&&this.navigatorSeries.setVisible(!0,!1)});w(b,"hide",function(){this.navigatorSeries&&this.navigatorSeries.setVisible(!1,!1)});!1!==this.navigatorOptions.adaptToUpdatedData&&b.xAxis&&w(b,"updatedData",this.updatedDataHandler);w(b,"remove",function(){this.navigatorSeries&&(r(a.series,this.navigatorSeries), +g(this.navigatorSeries.options)&&this.navigatorSeries.remove(!1),delete this.navigatorSeries)})},this)};a.prototype.getBaseSeriesMin=function(a){return this.baseSeries.reduce(function(a,b){return Math.min(a,b.xData?b.xData[0]:a)},a)};a.prototype.modifyNavigatorAxisExtremes=function(){var a=this.xAxis,b;"undefined"!==typeof a.getExtremes&&(!(b=this.getUnionExtremes(!0))||b.dataMin===a.min&&b.dataMax===a.max||(a.min=b.dataMin,a.max=b.dataMax))};a.prototype.modifyBaseAxisExtremes=function(){var a=this.chart.navigator, +b=this.getExtremes(),c=b.dataMin,d=b.dataMax;b=b.max-b.min;var f=a.stickToMin,g=a.stickToMax,h=e(this.options.overscroll,0),k=a.series&&a.series[0],l=!!this.setExtremes;if(!this.eventArgs||"rangeSelectorButton"!==this.eventArgs.trigger){if(f){var n=c;var p=n+b}g&&(p=d+h,f||(n=Math.max(c,p-b,a.getBaseSeriesMin(k&&k.xData?k.xData[0]:-Number.MAX_VALUE))));l&&(f||g)&&A(n)&&(this.min=this.userMin=n,this.max=this.userMax=p)}a.stickToMin=a.stickToMax=null};a.prototype.updatedDataHandler=function(){var a= +this.chart.navigator,b=this.navigatorSeries,c=a.getBaseSeriesMin(this.xData[0]);a.stickToMax=a.reversedExtremes?0===Math.round(a.zoomedMin):Math.round(a.zoomedMax)>=Math.round(a.size);a.stickToMin=A(this.xAxis.min)&&this.xAxis.min<=c&&(!this.chart.fixedRange||!a.stickToMax);b&&!a.hasNavigatorData&&(b.options.pointStart=this.xData[0],b.setData(this.options.data,!1,null,!1))};a.prototype.addChartEvents=function(){this.eventsToUnbind||(this.eventsToUnbind=[]);this.eventsToUnbind.push(w(this.chart,"redraw", +function(){var a=this.navigator,b=a&&(a.baseSeries&&a.baseSeries[0]&&a.baseSeries[0].xAxis||this.xAxis[0]);b&&a.render(b.min,b.max)}),w(this.chart,"getMargins",function(){var a=this.navigator,b=a.opposite?"plotTop":"marginBottom";this.inverted&&(b=a.opposite?"marginRight":"plotLeft");this[b]=(this[b]||0)+(a.navigatorEnabled||!this.inverted?a.outlineHeight:0)+a.navigatorOptions.margin}))};a.prototype.destroy=function(){this.removeEvents();this.xAxis&&(r(this.chart.xAxis,this.xAxis),r(this.chart.axes, +this.xAxis));this.yAxis&&(r(this.chart.yAxis,this.yAxis),r(this.chart.axes,this.yAxis));(this.series||[]).forEach(function(a){a.destroy&&a.destroy()});"series xAxis yAxis shades outline scrollbarTrack scrollbarRifles scrollbarGroup scrollbar navigatorGroup rendered".split(" ").forEach(function(a){this[a]&&this[a].destroy&&this[a].destroy();this[a]=null},this);[this.handles].forEach(function(a){f(a)},this)};return a}();v.Navigator||(v.Navigator=E,n.compose(k),w(q,"beforeShowResetZoom",function(){var a= +this.options,b=a.navigator,c=a.rangeSelector;if((b&&b.enabled||c&&c.enabled)&&(!p&&"x"===a.chart.zoomType||p&&"x"===a.chart.pinchType))return!1}),w(q,"beforeRender",function(){var a=this.options;if(a.navigator.enabled||a.scrollbar.enabled)this.scroller=this.navigator=new E(this)}),w(q,"afterSetChartSize",function(){var a=this.legend,b=this.navigator;if(b){var c=a&&a.options;var d=b.xAxis;var f=b.yAxis;var g=b.scrollbarHeight;this.inverted?(b.left=b.opposite?this.chartWidth-g-b.height:this.spacing[3]+ +g,b.top=this.plotTop+g):(b.left=this.plotLeft+g,b.top=b.navigatorOptions.top||this.chartHeight-b.height-g-this.spacing[2]-(this.rangeSelector&&this.extraBottomMargin?this.rangeSelector.getHeight():0)-(c&&"bottom"===c.verticalAlign&&c.enabled&&!c.floating?a.legendHeight+e(c.margin,10):0)-(this.titleOffset?this.titleOffset[2]:0));d&&f&&(this.inverted?d.options.left=f.options.left=b.left:d.options.top=f.options.top=b.top,d.setAxisSize(),f.setAxisSize())}}),w(q,"update",function(a){var b=a.options.navigator|| +{},c=a.options.scrollbar||{};this.navigator||this.scroller||!b.enabled&&!c.enabled||(h(!0,this.options.navigator,b),h(!0,this.options.scrollbar,c),delete a.options.navigator,delete a.options.scrollbar)}),w(q,"afterUpdate",function(a){this.navigator||this.scroller||!this.options.navigator.enabled&&!this.options.scrollbar.enabled||(this.scroller=this.navigator=new E(this),e(a.redraw,!0)&&this.redraw(a.animation))}),w(q,"afterAddSeries",function(){this.navigator&&this.navigator.setBaseSeries(null,!1)}), +w(G,"afterUpdate",function(){this.chart.navigator&&!this.options.isInternal&&this.chart.navigator.setBaseSeries(null,!1)}),q.prototype.callbacks.push(function(a){var b=a.navigator;b&&a.xAxis[0]&&(a=a.xAxis[0].getExtremes(),b.render(a.min,a.max))}));v.Navigator=E;return v.Navigator});G(k,"masters/modules/gantt.src.js",[],function(){})}); +//# sourceMappingURL=gantt.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/gantt.js.map b/librerias/gantt/code/modules/gantt.js.map new file mode 100644 index 0000000..b2ed6b6 --- /dev/null +++ b/librerias/gantt/code/modules/gantt.js.map @@ -0,0 +1 @@ +{"version":3,"file":"gantt.js.map","lineCount":191,"mappings":"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","sources":["gantt.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","U","PlotLineOrBand","addEvent","merge","wrap","defaultConfig","currentDateIndicator","color","width","label","format","formatter","value","dateFormat","rotation","style","fontSize","Axis","options","cdiOptions","Date","plotLines","push","attr","text","getLabelText","prototype","defaultMethod","defaultLabelOptions","call","defined","isNumber","pick","Chart","chartOptions","chart","horiz","staticScale","height","scrollablePlotArea","minHeight","adjustHeight","Chart.prototype.adjustHeight","redrawTrigger","forEach","axes","axis","animate","initiatedScale","animation","min","brokenAxis","unitLength","max","tickInterval","Math","diff","plotHeight","abs","setSize","chartHeight","series","clipRect","sharedClipKey","extend","getListOfParents","data","ids","listOfParents","reduce","prev","curr","parent","Object","keys","parents","list","children","indexOf","child","getNode","id","level","mapOfIdToChildren","descendants","after","before","node","depth","start","end","map","childStart","childEnd","milestone","Tree","getTree","d","isObject","TreeGridTick","onInit","tick","treeGrid","Additions","renderLabelIcon","params","isNew","labelIcon","renderer","labelBox","xy","x","padding","y","collapsed","shouldRender","show","icon","symbols","type","addClass","add","group","styledMode","css","cursor","stroke","lineColor","strokeWidth","lineWidth","translateX","translateY","wrapGetLabelPosition","proceed","labelOptions","tickmarkOffset","index","step","lbOptions","labels","pos","isTreeGrid","result","symbolOptions","symbol","indentation","mapOfPosToGridNode","wrapRenderLabel","tickPositions","element","Array","slice","arguments","isCollapsed","styles","parentGroup","removeClassName","prefixClassName","removeClass","object","attachedTreeGridEvents","textDecoration","toggleCollapse","applied","compose","TickClass","collapse","TickClass.prototype.collapse","redraw","expand","TickClass.prototype.expand","TickClass.prototype.toggleCollapse","Additions.prototype.collapse","breaks","setBreaks","Additions.prototype.expand","Additions.prototype.toggleCollapse","Color","isArray","getColor","mapOptionsToLevel","parentColor","parentColorIndex","colors","siblings","points","chartOptionsChart","point","i","getColorByPoint","colorByPoint","colorIndexByPoint","length","colorCount","colorVariation","key","parse","brighten","to","get","colorIndex","getLevelOptions","from","levels","converted","defaults","item","levelIsConstant","setTreeValues","tree","idRoot","nodeRoot","mapIdToNode","optionsPoint","childrenTotal","levelDynamic","name","visible","newOptions","val","isLeaf","updateRootId","rootId","rootNode","userOptions","Tick","erase","find","timeUnits","applyGridOptions","align","categories","showLastLabel","labelRotation","getMaxLabelDimensions","Axis.prototype.getMaxLabelDimensions","ticks","dimensions","tickHeight","getBBox","textStr","textPxLength","tickWidth","round","dateFormats","W","H.dateFormats.W","timestamp","firstDay","thursday","valueOf","set","firstThursday","toString","floor","E","H.dateFormats.E","charAt","grid","columns","column","setAxisSize","setAxisTranslation","e","reversed","gridOptions","labelOpts","side","GridAxis","Side","tickPos","nextTickPos","tickSize","crispCorr","enabled","bottom","top","offset","len","translate","left","chartWidth","right","slotWidth","lblMetrics","fontMetrics","labelHeight","useHTML","b","lines","h","f","GridAxisAdditions","isOuterAxis","GridAxisAdditions.prototype.isOuterAxis","columnIndex","linkedParent","parentAxis","thisIndex","lastIndex","coll","otherAxis","isInternal","GridAxis.compose","AxisClass","keepProps","wrapUnsquish","onAfterGetOffset","onAfterGetTitlePosition","onAfterInit","onAfterRender","onAfterSetAxisTranslation","onAfterSetOptions","onAfterSetOptions2","onAfterSetScale","onAfterTickSize","onTrimTicks","onDestroy","GridAxis.onAfterGetOffset","getOffset","GridAxis.onAfterGetTitlePosition","title","axisTitle","axisHeight","axisLeft","opposite","_a","axisTitleOptions","axisTop","axisWidth","titleWidth","xOption","yOption","titleMargin","margin","titleFontSize","offAxis","titlePosition","GridAxis.onAfterInit","isLinked","isFirst","isLast","p","isXAxis","columnOptions","linkedTo","isColumn","GridAxis.onAfterRender","maxLabelDimensions","rightWall","destroy","axisLine","linePath","getLinePath","startPoint","endPoint","distance","tickLength","axisLineExtra","zIndex","axisGroup","showAxis","render","GridAxis.onAfterSetAxisTranslation","tickInfo","info","userLabels","pointRange","dateTimeLabelFormats","unitName","range","count","GridAxis.onAfterSetOptions","gridAxisOptions","className","hour","day","week","month","borderWidth","reserveSpace","units","tickPixelInterval","tickPositioner","gridAxisOptions.tickPositioner","parentInfo","unitIdx","unitRange","getTimeTicks","startOfWeek","minPadding","maxPadding","GridAxis.onAfterSetOptions2","GridAxis.onAfterSetScale","setScale","GridAxis.onAfterTickSize","defaultLeftAxisOptions","_b","labelPadding","cellHeight","GridAxis.onDestroy","keepEvents","GridAxis.onInit","borderColor","tickColor","GridAxis.onTrimTicks","categoryAxis","firstPos","lastPos","startOnTick","endOnTick","GridAxis.wrapUnsquish","StackItem","fireEvent","Series","BrokenAxisAdditions","hasBreaks","isInBreak","BrokenAxisAdditions.isInBreak","brk","repeat","Infinity","test","inclusive","ret","lin2Val","BrokenAxisAdditions.lin2Val","breakArray","nval","val2Lin","BrokenAxisAdditions.val2Lin","findBreakAt","BrokenAxisAdditions.prototype.findBreakAt","isInAnyBreak","BrokenAxisAdditions.prototype.isInAnyBreak","testKeep","keep","inbrk","showPoints","BrokenAxisAdditions.prototype.setBreaks","isDirty","forceRedraw","val2lin","lin2val","ordinal","setExtremes","axis.setExtremes","newMin","newMax","eventArguments","axisBreak","axis.setAxisTranslation","saveOld","breakArrayT","userMin","userMax","pointRangePadding","move","size","breakSize","sort","a","inBrk","transA","minPixelPadding","minPointOffset","BrokenAxis","BrokenAxis.compose","SeriesClass","seriesProto","drawBreaks","seriesProto.drawBreaks","threshold","eventName","brokenAxis_1","toUpperCase","gappedPath","seriesProto.gappedPath","currentDataGrouping","groupingSize","gapSize","yAxis","stack","next","gapUnit","basePointRange","current","xRange","splice","isNull","stacking","stacks","stackKey","stackLabels","total","getGraphPath","newPositions","connectNulls","xAxis","isPointInBreak","drawPointsWrapped","pointArrayMap","TreeSeriesMixin","isString","TreeGridAxis","getBreakFromNode","collapseStart","collapseEnd","getTreeGridFromData","uniqueNames","numberOfSeries","collapsedNodes","mapOfIdToNode","posIterator","uniqueNamesEnabled","treeParams","gridNode","parentNode","parentGridNode","hasSameName","nodes","updateYValuesAndTickPos","setValues","seriesIndex","onBeforeRender","target","filter","some","hasRendered","isDirtyData","arr","s","hasNames","setData","wrapGenerateTick","levelOptions","parameters","category","addLabel","wrapGetMaxLabelDimensions","retVal","treeDepth","wrapInit","concat","n","fontWeight","wrapSetTickInterval","dataMin","dataMax","getTickPositions","Additions.prototype.getTickPositions","Additions.prototype.isCollapsed","utils","findLastObstacleBefore","obstacles","xMin","startIx","cmp","findObstacleFromPoint","obstacle","xMax","yMax","yMin","pathFromSegments","segments","limitObstacleToBounds","bounds","algorithms","straight","simpleConnect","copyFromPoint","fromKey","toKey","getMeOut","direction","useMax","dir","startDirectionX","chartObstacles","startObstacleIx","endObstacleIx","endObstacle","waypoint","endSegment","startObstacle","prevWaypoint","waypoint2","requiresObstacles","fastAvoid","pivotPoint","fromPoint","toPoint","directionIsX","searchDirection","firstPoint","lastPoint","lowestPoint","highestPoint","getDodgeDirection","dirIsX","softBounds","soft","hardBounds","hard","toPointMax","toPointMin","maxOutOfSoftBounds","minOutOfSoftBounds","maxOutOfHardBounds","minOutOfHardBounds","minDistance","maxDistance","minPivot","maxPivot","clearPathTo","obstacleMargin","obstacleOptions","softMinX","softMaxX","softMinY","softMaxY","envelopingObstacle","waypointUseMax","envelopWaypoint","secondEnvelopingObstacle","forceObstacleBreak","pivot","extractFromObstacle","goalPoint","endSegments","metrics","obstacleMetrics","maxWidth","maxHeight","extractedEndPoint","reverse","SVGRenderer","arrow","H.SVGRenderer.prototype.symbols.arrow","w","Point","pathfinderAlgorithms","getPointBB","shapeArgs","bb","graphic","plotX","plotY","calculateObstacleMargin","j","obstacleDistance","distances","bbMargin","yOverlap","xOverlap","xDistance","yDistance","Connection","init","Pathfinder","warnLegacy","pathfinder","acc","connectors","error","objectEach","splat","deg2rad","defaultOptions","marker","verticalAlign","inside","startMarker","endMarker","renderPath","attribs","forExport","pathGraphic","connection","graphics","g","seriesGroup","plotLeft","plotTop","opacity","anim","addMarker","anchor","getPathfinderAnchorPoint","segment","pathVector","radians","getRadiansToVector","markerVector","getMarkerVector","radius","box","rotationOriginX","rotationOriginY","fill","getPath","algorithm","getChartObstacles","algorithmMargin","chartObstacleMetrics","getObstacleMetrics","lineObstacles","plotWidth","getAlgorithmStartDirection","dashStyle","dashstyle","ceil","pathResult","connections","update","deferRender","oldConnections","connects","connect","isInside","k","found","lenOld","lenNew","renderConnections","pathfinderRemoveRenderEvent","calculatedMargin","sLen","pLen","markerOptions","yCenter","undef","v1","v2","atan2","markerRadius","twoPI","PI","rectWidth","rectHeight","rAtan","leftOrRightRegion","rectHalfWidth","rectHalfHeight","rectHorizontalCenter","rectVerticalCenter","markerPoint","xFactor","yFactor","theta","tanTheta","tan","cos","sin","callbacks","clamp","correctFloat","seriesType","columnType","seriesTypes","dataLabels","amount","partialFill","tooltip","headerFormat","pointFormat","borderRadius","parallelArrays","requireSorting","line","cropShoulder","getExtremesFromAll","autoIncrement","noop","buildKDTree","getColumnMetrics","swapAxes","cropData","xData","yData","crop","x2Data","findPointIndex","cropped","cropStart","pointIndex","x2","touched","translatePoint","columnMetrics","minPointLength","posX","plotX2","inverted","crisper","yOffset","pointHeight","widthDifference","pointWidth","pointPlacement","r","dlLeft","dlRight","dlWidth","dlBox","centerX","tooltipPos","xIndex","yIndex","tooltipYOffset","partShapeArgs","clipRectWidth","clipRectArgs","drawPoint","verb","seriesOpts","shapeType","pfOptions","cutOff","pointState","state","stateOpts","states","pointStateVerb","pointAttr","pointAttribs","rect","getClassName","partRect","partialClipRect","clip","shadow","drawPoints","getAnimationVerb","pointCount","animationLimit","resolveColor","setState","getLabelConfig","cfg","yCats","yCategory","tooltipDateKeys","isValid","axisSeries","modMax","Number","MAX_VALUE","xrange","grouping","pointFormatter","formats","tooltipOptions","ttOptions","xDateFormat","tooltipFormatter","getDateFormat","closestPointRange","keyboardMoveVertical","selected","diamondShape","diamond","setGanttPointAliases","addIfExists","prop","completed","dependency","pointClass","applyOptions","gantt","ganttChart","H.ganttChart","renderTo","callback","hasRenderToArg","nodeName","seriesOptions","getOptions","defaultLinkedTo","xAxisOptions","yAxisOptions","legend","isGantt","ScrollbarAxis","ScrollbarAxis.compose","ScrollbarClass","scrollbar","vertical","axisMin","axisMax","unitedMin","unitedMax","liveRedraw","svg","isTouchDevice","isBoosting","DOMType","setRange","scrollMin","scrollMax","axisTitleMargin","titleOffset","scrollbarsOffsets","axisMargin","position","offsetsIndex","isNaN","axisOffset","destroyObjectProperties","removeEvent","hasTouch","swapXY","H.swapXY","seg","temp","Scrollbar","_events","chartY","chartX","scrollbarButtons","scrollbarGroup","scrollbarLeft","scrollbarRifles","scrollbarStrokeWidth","scrollbarTop","track","trackBorderWidth","addEvents","Scrollbar.prototype.addEvents","buttonsOrder","buttons","bar","mouseDownHandler","bind","mouseMoveHandler","mouseUpHandler","buttonToMinClick","buttonToMaxClick","trackClick","ownerDocument","Scrollbar.prototype.buttonToMaxClick","scroller","updatePosition","trigger","DOMEvent","Scrollbar.prototype.buttonToMinClick","cursorToScrollbarPosition","Scrollbar.prototype.cursorToScrollbarPosition","normalizedEvent","minWidthDifference","minWidth","calculatedWidth","xOffset","barWidth","Scrollbar.prototype.destroy","removeEvents","drawScrollbarButton","Scrollbar.prototype.drawScrollbarButton","tempElem","buttonBorderColor","buttonBorderWidth","buttonBackgroundColor","crisp","buttonBorderRadius","buttonArrowColor","Scrollbar.prototype.init","Scrollbar.prototype.mouseDownHandler","pointer","normalize","mousePosition","initPositions","grabbedCenter","Scrollbar.prototype.mouseMoveHandler","touches","chartPosition","scrollPosition","change","hasDragged","Scrollbar.prototype.mouseUpHandler","Scrollbar.prototype.position","method","rendered","Scrollbar.prototype.removeEvents","Scrollbar.prototype.render","trackBorderRadius","trackBackgroundColor","trackBorderColor","barBorderRadius","barBackgroundColor","barBorderColor","barBorderWidth","rifleColor","Scrollbar.prototype.setRange","fullWidth","newSize","navigator","fromPX","newPos","newRiflesPos","hide","showFull","Scrollbar.prototype.trackClick","Scrollbar.prototype.update","Scrollbar.prototype.updatePosition","RangeSelector","createElement","discardElement","pInt","rangeSelector","buttonTheme","floating","inputPosition","buttonPosition","labelStyle","lang","rangeSelectorZoom","rangeSelectorFrom","rangeSelectorTo","clickButton","rangeOptions","buttonOptions","baseAxis","unionExtremes","getUnionExtremes","_range","rangeMin","dataGrouping","fixedRange","forcedDataGrouping","setDataGrouping","frozenStates","preserveDataGrouping","ctx","minFromRange","MIN_VALUE","ytdExtremes","getYTDExtremes","time","useUTC","deferredYTDClick","_offsetMin","_offsetMax","setSelected","rangeSelectorButton","baseXAxisOptions","rangeSetting","minSetting","resetMinAndRange","defaultButtons","selectedOption","blurInputs","minInput","maxInput","blur","unMouseDown","container","unResize","computeButtonRange","updateButtonStates","actualRange","hasNoData","hasVisibleSeries","ytdMin","ytdMax","selectedExists","allButtonsEnabled","button","offsetRange","isSelected","isTooGreatRange","isTooSmallRange","minRange","isYTDButNotSelected","isAllButAlreadyShowingAll","isSameRange","year","disable","select","fixedTimes","millisecond","second","minute","offsetMin","offsetMax","setInputValue","inputTime","input","previousValue","HCTime","inputEditDateFormat","inputDateFormat","showInput","inputGroup","dateBox","border","hideInput","drawInput","updateExtremes","inputValue","inputDateParser","chartAxis","dataAxis","split","UTC","getTimezoneOffset","isMin","chartStyle","div","inputBoxWidth","inputBoxHeight","on","focus","inputBoxBorderColor","inputStyle","textAlign","fontFamily","onfocus","input.onfocus","onblur","input.onblur","doc","activeElement","onchange","onkeypress","input.onkeypress","event","keyCode","getPosition","buttonTop","inputTop","now","startOfYear","getTime","navButtonOptions","exporting","navigation","inputsZIndex","inputEnabled","buttonGroup","legendOptions","buttonPositionY","inputPositionY","hasLoaded","exportingX","zoomText","buttonEvents","events","click","callDefaultEvent","isActive","hover","disabled","insertBefore","buttonLeft","buttonSpacing","spacing","titleCollision","spacingBox","placed","inputGroupX","alignAttr","alignOptions","inputGroupWidth","buttonGroupX","buttonGroupWidth","groupHeight","alignTranslateY","legendHeight","minPosition","marginTop","getHeight","rangeSelectorGroup","yPosition","rangeSelectorHeight","subtitle","rSelector","nodeType","Axis.prototype.minFromRange","getTrueRange","base","timeName","date","basePeriod","updateNames","getAxisMargins","extraBottomMargin","extraTopMargin","optionsRangeSelector","extraBottomMarginWas","extraTopMarginWas","isDirtyBox","marginBottom","renderRangeSelector","extremes","getExtremes","display","alignTo","layout","unbindSetExtremes","unbindRender","destroyEvents","NavigatorAxisAdditions","NavigatorAxisAdditions.prototype.destroy","toFixedRange","NavigatorAxisAdditions.prototype.toFixedRange","pxMin","pxMax","fixedMin","fixedMax","halfPointRange","changeRatio","NavigatorAxis","NavigatorAxis.compose","navigatorAxis","pinchType","zoomType","zoomed","previousZoom","preventDefault","AdditionsClass","numExt","extreme","_i","numbers","defaultSeriesType","areaspline","maskInside","handles","backgroundColor","maskFill","setOpacity","outlineColor","outlineWidth","fillOpacity","compare","approximation","groupPixelWidth","smoothed","overscroll","gridLineColor","gridLineWidth","crosshair","Renderer","halfWidth","markerPosition","Navigator","zoomedMin","zoomedMax","shades","outlineHeight","outline","navigatorSize","navigatorSeries","navigatorOptions","navigatorGroup","navigatorEnabled","baseSeries","drawHandle","Navigator.prototype.drawHandle","parseInt","drawOutline","Navigator.prototype.drawOutline","halfOutline","outlineCorrection","scrollbarHeight","navigatorTop","verticalMin","drawMasks","Navigator.prototype.drawMasks","navigatorHeight","shade","renderElements","Navigator.prototype.renderElements","mouseCursor","visibility","hasMask","handlesOptions","Navigator.prototype.update","Navigator.prototype.render","scrollbarXAxis","fake","maxRange","navigatorWidth","toPixels","toValue","currentRange","grabbedLeft","grabbedRight","fixedWidth","addMouseEvents","Navigator.prototype.addMouseEvents","eventsToUnbind","onMouseMove","onMouseUp","getPartsEvents","modifyNavigatorAxisExtremes","Navigator.prototype.getPartsEvents","navigatorItem","shadesMousedown","Navigator.prototype.shadesMousedown","navigatorPosition","dragOffset","reversedExtremes","ext","handlesMousedown","Navigator.prototype.handlesMousedown","baseXAxis","otherHandlePos","fixedExtreme","Navigator.prototype.onMouseMove","pageX","setTimeout","Navigator.prototype.onMouseUp","triggerOp","Navigator.prototype.removeEvents","unbind","removeBaseSeriesEvents","Navigator.prototype.removeBaseSeriesEvents","adaptToUpdatedData","updatedDataHandler","modifyBaseAxisExtremes","Navigator.prototype.init","scrollbarOptions","scrollbarEnabled","setBaseSeries","xAxisIndex","yAxisIndex","baseXaxis","isX","keepOrdinalPadding","zoomEnabled","offsets","alignTicks","updateNavigatorSeries","unbindRedraw","scrollTrackWidth","valueRange","addBaseSeriesEvents","addChartEvents","Navigator.prototype.getUnionExtremes","returnFalseOnNoBaseSeries","navAxis","navAxisOptions","baseAxisOptions","Navigator.prototype.setBaseSeries","baseSeriesOptions","showInNavigator","Navigator.prototype.updateNavigatorSeries","baseOptions","mergedNavSeriesOptions","chartNavigatorSeriesOptions","baseNavigatorOptions","navSeriesMixin","enableMouseTracking","padXAxis","showInLegend","inactive","navSeries","eachBaseSeries","linkedNavSeries","userNavOptions","plotOptions","navigatorSeriesData","hasNavigatorData","initSeries","userSeriesOptions","Navigator.prototype.addBaseSeriesEvents","setVisible","remove","getBaseSeriesMin","Navigator.prototype.getBaseSeriesMin","currentSeriesMin","Navigator.prototype.modifyNavigatorAxisExtremes","Navigator.prototype.modifyBaseAxisExtremes","baseExtremes","baseDataMin","baseDataMax","stickToMin","stickToMax","hasSetExtremes","eventArgs","Navigator.prototype.updatedDataHandler","xDataMin","pointStart","Navigator.prototype.addChartEvents","marginName","Navigator.prototype.destroy"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/gantt.src.js b/librerias/gantt/code/modules/gantt.src.js new file mode 100644 index 0000000..a660803 --- /dev/null +++ b/librerias/gantt/code/modules/gantt.src.js @@ -0,0 +1,10507 @@ +/** + * @license Highcharts Gantt JS v8.1.0 (2020-05-05) + * + * Gantt series + * + * (c) 2016-2019 Lars A. V. Cabrera + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/gantt', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'parts-gantt/CurrentDateIndicator.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['parts/PlotLineOrBand.js']], function (H, U, PlotLineOrBand) { + /* * + * + * (c) 2016-2020 Highsoft AS + * + * Author: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, merge = U.merge, wrap = U.wrap; + var Axis = H.Axis; + var defaultConfig = { + /** + * Show an indicator on the axis for the current date and time. Can be a + * boolean or a configuration object similar to + * [xAxis.plotLines](#xAxis.plotLines). + * + * @sample gantt/current-date-indicator/demo + * Current date indicator enabled + * @sample gantt/current-date-indicator/object-config + * Current date indicator with custom options + * + * @declare Highcharts.AxisCurrentDateIndicatorOptions + * @type {boolean|*} + * @default true + * @extends xAxis.plotLines + * @excluding value + * @product gantt + * @apioption xAxis.currentDateIndicator + */ + currentDateIndicator: true, + color: '#ccd6eb', + width: 2, + /** + * @declare Highcharts.AxisCurrentDateIndicatorLabelOptions + */ + label: { + /** + * Format of the label. This options is passed as the fist argument to + * [dateFormat](/class-reference/Highcharts#dateFormat) function. + * + * @type {string} + * @default '%a, %b %d %Y, %H:%M' + * @product gantt + * @apioption xAxis.currentDateIndicator.label.format + */ + format: '%a, %b %d %Y, %H:%M', + formatter: function (value, format) { + return H.dateFormat(format, value); + }, + rotation: 0, + /** + * @type {Highcharts.CSSObject} + */ + style: { + /** @internal */ + fontSize: '10px' + } + } + }; + /* eslint-disable no-invalid-this */ + addEvent(Axis, 'afterSetOptions', function () { + var options = this.options, cdiOptions = options.currentDateIndicator; + if (cdiOptions) { + cdiOptions = typeof cdiOptions === 'object' ? + merge(defaultConfig, cdiOptions) : merge(defaultConfig); + cdiOptions.value = new Date(); + if (!options.plotLines) { + options.plotLines = []; + } + options.plotLines.push(cdiOptions); + } + }); + addEvent(PlotLineOrBand, 'render', function () { + // If the label already exists, update its text + if (this.label) { + this.label.attr({ + text: this.getLabelText(this.options.label) + }); + } + }); + wrap(PlotLineOrBand.prototype, 'getLabelText', function (defaultMethod, defaultLabelOptions) { + var options = this.options; + if (options.currentDateIndicator && options.label && + typeof options.label.formatter === 'function') { + options.value = new Date(); + return options.label.formatter + .call(this, options.value, options.label.format); + } + return defaultMethod.call(this, defaultLabelOptions); + }); + + }); + _registerModule(_modules, 'modules/static-scale.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2016-2020 Torstein Honsi, Lars Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, defined = U.defined, isNumber = U.isNumber, pick = U.pick; + var Chart = H.Chart; + /* eslint-disable no-invalid-this */ + /** + * For vertical axes only. Setting the static scale ensures that each tick unit + * is translated into a fixed pixel height. For example, setting the static + * scale to 24 results in each Y axis category taking up 24 pixels, and the + * height of the chart adjusts. Adding or removing items will make the chart + * resize. + * + * @sample gantt/xrange-series/demo/ + * X-range series with static scale + * + * @type {number} + * @default 50 + * @since 6.2.0 + * @product gantt + * @apioption yAxis.staticScale + */ + addEvent(H.Axis, 'afterSetOptions', function () { + var chartOptions = this.chart.options && this.chart.options.chart; + if (!this.horiz && + isNumber(this.options.staticScale) && + (!chartOptions.height || + (chartOptions.scrollablePlotArea && + chartOptions.scrollablePlotArea.minHeight))) { + this.staticScale = this.options.staticScale; + } + }); + Chart.prototype.adjustHeight = function () { + if (this.redrawTrigger !== 'adjustHeight') { + (this.axes || []).forEach(function (axis) { + var chart = axis.chart, animate = !!chart.initiatedScale && + chart.options.animation, staticScale = axis.options.staticScale, height, diff; + if (axis.staticScale && defined(axis.min)) { + height = pick(axis.brokenAxis && axis.brokenAxis.unitLength, axis.max + axis.tickInterval - axis.min) * staticScale; + // Minimum height is 1 x staticScale. + height = Math.max(height, staticScale); + diff = height - chart.plotHeight; + if (Math.abs(diff) >= 1) { + chart.plotHeight = height; + chart.redrawTrigger = 'adjustHeight'; + chart.setSize(void 0, chart.chartHeight + diff, animate); + } + // Make sure clip rects have the right height before initial + // animation. + axis.series.forEach(function (series) { + var clipRect = series.sharedClipKey && + chart[series.sharedClipKey]; + if (clipRect) { + clipRect.attr({ + height: chart.plotHeight + }); + } + }); + } + }); + this.initiatedScale = true; + } + this.redrawTrigger = null; + }; + addEvent(Chart, 'render', Chart.prototype.adjustHeight); + + }); + _registerModule(_modules, 'parts-gantt/Tree.js', [_modules['parts/Utilities.js']], function (U) { + /* * + * + * (c) 2016-2020 Highsoft AS + * + * Authors: Jon Arild Nygard + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /* eslint no-console: 0 */ + var extend = U.extend, isNumber = U.isNumber, pick = U.pick; + /** + * Creates an object map from parent id to childrens index. + * + * @private + * @function Highcharts.Tree#getListOfParents + * + * @param {Array<*>} data + * List of points set in options. `Array.parent` is parent id of point. + * + * @param {Array} ids + * List of all point ids. + * + * @return {Highcharts.Dictionary>} + * Map from parent id to children index in data + */ + var getListOfParents = function (data, ids) { + var listOfParents = data.reduce(function (prev, curr) { + var parent = pick(curr.parent, ''); + if (typeof prev[parent] === 'undefined') { + prev[parent] = []; + } + prev[parent].push(curr); + return prev; + }, {}), parents = Object.keys(listOfParents); + // If parent does not exist, hoist parent to root of tree. + parents.forEach(function (parent, list) { + var children = listOfParents[parent]; + if ((parent !== '') && (ids.indexOf(parent) === -1)) { + children.forEach(function (child) { + list[''].push(child); + }); + delete list[parent]; + } + }); + return listOfParents; + }; + var getNode = function (id, parent, level, data, mapOfIdToChildren, options) { + var descendants = 0, height = 0, after = options && options.after, before = options && options.before, node = { + data: data, + depth: level - 1, + id: id, + level: level, + parent: parent + }, start, end, children; + // Allow custom logic before the children has been created. + if (typeof before === 'function') { + before(node, options); + } + // Call getNode recursively on the children. Calulate the height of the + // node, and the number of descendants. + children = ((mapOfIdToChildren[id] || [])).map(function (child) { + var node = getNode(child.id, id, (level + 1), child, mapOfIdToChildren, options), childStart = child.start, childEnd = (child.milestone === true ? + childStart : + child.end); + // Start should be the lowest child.start. + start = ((!isNumber(start) || childStart < start) ? + childStart : + start); + // End should be the largest child.end. + // If child is milestone, then use start as end. + end = ((!isNumber(end) || childEnd > end) ? + childEnd : + end); + descendants = descendants + 1 + node.descendants; + height = Math.max(node.height + 1, height); + return node; + }); + // Calculate start and end for point if it is not already explicitly set. + if (data) { + data.start = pick(data.start, start); + data.end = pick(data.end, end); + } + extend(node, { + children: children, + descendants: descendants, + height: height + }); + // Allow custom logic after the children has been created. + if (typeof after === 'function') { + after(node, options); + } + return node; + }; + var getTree = function (data, options) { + var ids = data.map(function (d) { + return d.id; + }), mapOfIdToChildren = getListOfParents(data, ids); + return getNode('', null, 1, null, mapOfIdToChildren, options); + }; + var Tree = { + getListOfParents: getListOfParents, + getNode: getNode, + getTree: getTree + }; + + return Tree; + }); + _registerModule(_modules, 'parts-gantt/TreeGridTick.js', [_modules['parts/Utilities.js']], function (U) { + /* * + * + * (c) 2016 Highsoft AS + * Authors: Jon Arild Nygard + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, defined = U.defined, isObject = U.isObject, isNumber = U.isNumber, pick = U.pick, wrap = U.wrap; + /** + * @private + */ + var TreeGridTick; + (function (TreeGridTick) { + /* * + * + * Interfaces + * + * */ + /* * + * + * Variables + * + * */ + var applied = false; + /* * + * + * Functions + * + * */ + /** + * @private + */ + function compose(TickClass) { + if (!applied) { + addEvent(TickClass, 'init', onInit); + wrap(TickClass.prototype, 'getLabelPosition', wrapGetLabelPosition); + wrap(TickClass.prototype, 'renderLabel', wrapRenderLabel); + // backwards compatibility + TickClass.prototype.collapse = function (redraw) { + this.treeGrid.collapse(redraw); + }; + TickClass.prototype.expand = function (redraw) { + this.treeGrid.expand(redraw); + }; + TickClass.prototype.toggleCollapse = function (redraw) { + this.treeGrid.toggleCollapse(redraw); + }; + applied = true; + } + } + TreeGridTick.compose = compose; + /** + * @private + */ + function onInit() { + var tick = this; + if (!tick.treeGrid) { + tick.treeGrid = new Additions(tick); + } + } + /** + * @private + */ + function onTickHover(label) { + label.addClass('highcharts-treegrid-node-active'); + if (!label.renderer.styledMode) { + label.css({ + textDecoration: 'underline' + }); + } + } + /** + * @private + */ + function onTickHoverExit(label, options) { + var css = defined(options.style) ? options.style : {}; + label.removeClass('highcharts-treegrid-node-active'); + if (!label.renderer.styledMode) { + label.css({ textDecoration: css.textDecoration }); + } + } + /** + * @private + */ + function renderLabelIcon(tick, params) { + var treeGrid = tick.treeGrid, isNew = !treeGrid.labelIcon, renderer = params.renderer, labelBox = params.xy, options = params.options, width = options.width, height = options.height, iconCenter = { + x: labelBox.x - (width / 2) - options.padding, + y: labelBox.y - (height / 2) + }, rotation = params.collapsed ? 90 : 180, shouldRender = params.show && isNumber(iconCenter.y); + var icon = treeGrid.labelIcon; + if (!icon) { + treeGrid.labelIcon = icon = renderer + .path(renderer.symbols[options.type](options.x, options.y, width, height)) + .addClass('highcharts-label-icon') + .add(params.group); + } + // Set the new position, and show or hide + if (!shouldRender) { + icon.attr({ y: -9999 }); // #1338 + } + // Presentational attributes + if (!renderer.styledMode) { + icon + .attr({ + 'stroke-width': 1, + 'fill': pick(params.color, '#666666') + }) + .css({ + cursor: 'pointer', + stroke: options.lineColor, + strokeWidth: options.lineWidth + }); + } + // Update the icon positions + icon[isNew ? 'attr' : 'animate']({ + translateX: iconCenter.x, + translateY: iconCenter.y, + rotation: rotation + }); + } + /** + * @private + */ + function wrapGetLabelPosition(proceed, x, y, label, horiz, labelOptions, tickmarkOffset, index, step) { + var tick = this, lbOptions = pick(tick.options && tick.options.labels, labelOptions), pos = tick.pos, axis = tick.axis, options = axis.options, isTreeGrid = options.type === 'treegrid', result = proceed.apply(tick, [x, y, label, horiz, lbOptions, tickmarkOffset, index, step]); + var symbolOptions, indentation, mapOfPosToGridNode, node, level; + if (isTreeGrid) { + symbolOptions = (lbOptions && isObject(lbOptions.symbol, true) ? + lbOptions.symbol : + {}); + indentation = (lbOptions && isNumber(lbOptions.indentation) ? + lbOptions.indentation : + 0); + mapOfPosToGridNode = axis.treeGrid.mapOfPosToGridNode; + node = mapOfPosToGridNode && mapOfPosToGridNode[pos]; + level = (node && node.depth) || 1; + result.x += ( + // Add space for symbols + ((symbolOptions.width) + (symbolOptions.padding * 2)) + + // Apply indentation + ((level - 1) * indentation)); + } + return result; + } + /** + * @private + */ + function wrapRenderLabel(proceed) { + var tick = this, pos = tick.pos, axis = tick.axis, label = tick.label, mapOfPosToGridNode = axis.treeGrid.mapOfPosToGridNode, options = axis.options, labelOptions = pick(tick.options && tick.options.labels, options && options.labels), symbolOptions = (labelOptions && isObject(labelOptions.symbol, true) ? + labelOptions.symbol : + {}), node = mapOfPosToGridNode && mapOfPosToGridNode[pos], level = node && node.depth, isTreeGrid = options.type === 'treegrid', shouldRender = axis.tickPositions.indexOf(pos) > -1, prefixClassName = 'highcharts-treegrid-node-', styledMode = axis.chart.styledMode; + var collapsed, addClassName, removeClassName; + if (isTreeGrid && node) { + // Add class name for hierarchical styling. + if (label && + label.element) { + label.addClass(prefixClassName + 'level-' + level); + } + } + proceed.apply(tick, Array.prototype.slice.call(arguments, 1)); + if (isTreeGrid && + label && + label.element && + node && + node.descendants && + node.descendants > 0) { + collapsed = axis.treeGrid.isCollapsed(node); + renderLabelIcon(tick, { + color: !styledMode && label.styles && label.styles.color || '', + collapsed: collapsed, + group: label.parentGroup, + options: symbolOptions, + renderer: label.renderer, + show: shouldRender, + xy: label.xy + }); + // Add class name for the node. + addClassName = prefixClassName + + (collapsed ? 'collapsed' : 'expanded'); + removeClassName = prefixClassName + + (collapsed ? 'expanded' : 'collapsed'); + label + .addClass(addClassName) + .removeClass(removeClassName); + if (!styledMode) { + label.css({ + cursor: 'pointer' + }); + } + // Add events to both label text and icon + [label, tick.treeGrid.labelIcon].forEach(function (object) { + if (object && !object.attachedTreeGridEvents) { + // On hover + addEvent(object.element, 'mouseover', function () { + onTickHover(label); + }); + // On hover out + addEvent(object.element, 'mouseout', function () { + onTickHoverExit(label, labelOptions); + }); + addEvent(object.element, 'click', function () { + tick.treeGrid.toggleCollapse(); + }); + object.attachedTreeGridEvents = true; + } + }); + } + } + /* * + * + * Classes + * + * */ + /** + * @private + * @class + */ + var Additions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + /** + * @private + */ + function Additions(tick) { + this.tick = tick; + } + /* * + * + * Functions + * + * */ + /** + * Collapse the grid cell. Used when axis is of type treegrid. + * + * @see gantt/treegrid-axis/collapsed-dynamically/demo.js + * + * @private + * @function Highcharts.Tick#collapse + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call to + * {@link Highcharts.Chart#redraw} + */ + Additions.prototype.collapse = function (redraw) { + var tick = this.tick, axis = tick.axis, brokenAxis = axis.brokenAxis; + if (brokenAxis && + axis.treeGrid.mapOfPosToGridNode) { + var pos = tick.pos, node = axis.treeGrid.mapOfPosToGridNode[pos], breaks = axis.treeGrid.collapse(node); + brokenAxis.setBreaks(breaks, pick(redraw, true)); + } + }; + /** + * Expand the grid cell. Used when axis is of type treegrid. + * + * @see gantt/treegrid-axis/collapsed-dynamically/demo.js + * + * @private + * @function Highcharts.Tick#expand + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call to + * {@link Highcharts.Chart#redraw} + */ + Additions.prototype.expand = function (redraw) { + var tick = this.tick, axis = tick.axis, brokenAxis = axis.brokenAxis; + if (brokenAxis && + axis.treeGrid.mapOfPosToGridNode) { + var pos = tick.pos, node = axis.treeGrid.mapOfPosToGridNode[pos], breaks = axis.treeGrid.expand(node); + brokenAxis.setBreaks(breaks, pick(redraw, true)); + } + }; + /** + * Toggle the collapse/expand state of the grid cell. Used when axis is + * of type treegrid. + * + * @see gantt/treegrid-axis/collapsed-dynamically/demo.js + * + * @private + * @function Highcharts.Tick#toggleCollapse + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call to + * {@link Highcharts.Chart#redraw} + */ + Additions.prototype.toggleCollapse = function (redraw) { + var tick = this.tick, axis = tick.axis, brokenAxis = axis.brokenAxis; + if (brokenAxis && + axis.treeGrid.mapOfPosToGridNode) { + var pos = tick.pos, node = axis.treeGrid.mapOfPosToGridNode[pos], breaks = axis.treeGrid.toggleCollapse(node); + brokenAxis.setBreaks(breaks, pick(redraw, true)); + } + }; + return Additions; + }()); + TreeGridTick.Additions = Additions; + })(TreeGridTick || (TreeGridTick = {})); + + return TreeGridTick; + }); + _registerModule(_modules, 'mixins/tree-series.js', [_modules['parts/Color.js'], _modules['parts/Utilities.js']], function (Color, U) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, merge = U.merge, pick = U.pick; + var isBoolean = function (x) { + return typeof x === 'boolean'; + }, isFn = function (x) { + return typeof x === 'function'; + }; + /* eslint-disable valid-jsdoc */ + /** + * @todo Combine buildTree and buildNode with setTreeValues + * @todo Remove logic from Treemap and make it utilize this mixin. + * @private + */ + var setTreeValues = function setTreeValues(tree, options) { + var before = options.before, idRoot = options.idRoot, mapIdToNode = options.mapIdToNode, nodeRoot = mapIdToNode[idRoot], levelIsConstant = (isBoolean(options.levelIsConstant) ? + options.levelIsConstant : + true), points = options.points, point = points[tree.i], optionsPoint = point && point.options || {}, childrenTotal = 0, children = [], value; + extend(tree, { + levelDynamic: tree.level - (levelIsConstant ? 0 : nodeRoot.level), + name: pick(point && point.name, ''), + visible: (idRoot === tree.id || + (isBoolean(options.visible) ? options.visible : false)) + }); + if (isFn(before)) { + tree = before(tree, options); + } + // First give the children some values + tree.children.forEach(function (child, i) { + var newOptions = extend({}, options); + extend(newOptions, { + index: i, + siblings: tree.children.length, + visible: tree.visible + }); + child = setTreeValues(child, newOptions); + children.push(child); + if (child.visible) { + childrenTotal += child.val; + } + }); + tree.visible = childrenTotal > 0 || tree.visible; + // Set the values + value = pick(optionsPoint.value, childrenTotal); + extend(tree, { + children: children, + childrenTotal: childrenTotal, + isLeaf: tree.visible && !childrenTotal, + val: value + }); + return tree; + }; + /** + * @private + */ + var getColor = function getColor(node, options) { + var index = options.index, mapOptionsToLevel = options.mapOptionsToLevel, parentColor = options.parentColor, parentColorIndex = options.parentColorIndex, series = options.series, colors = options.colors, siblings = options.siblings, points = series.points, getColorByPoint, chartOptionsChart = series.chart.options.chart, point, level, colorByPoint, colorIndexByPoint, color, colorIndex; + /** + * @private + */ + function variation(color) { + var colorVariation = level && level.colorVariation; + if (colorVariation) { + if (colorVariation.key === 'brightness') { + return Color.parse(color).brighten(colorVariation.to * (index / siblings)).get(); + } + } + return color; + } + if (node) { + point = points[node.i]; + level = mapOptionsToLevel[node.level] || {}; + getColorByPoint = point && level.colorByPoint; + if (getColorByPoint) { + colorIndexByPoint = point.index % (colors ? + colors.length : + chartOptionsChart.colorCount); + colorByPoint = colors && colors[colorIndexByPoint]; + } + // Select either point color, level color or inherited color. + if (!series.chart.styledMode) { + color = pick(point && point.options.color, level && level.color, colorByPoint, parentColor && variation(parentColor), series.color); + } + colorIndex = pick(point && point.options.colorIndex, level && level.colorIndex, colorIndexByPoint, parentColorIndex, options.colorIndex); + } + return { + color: color, + colorIndex: colorIndex + }; + }; + /** + * Creates a map from level number to its given options. + * + * @private + * @function getLevelOptions + * @param {object} params + * Object containing parameters. + * - `defaults` Object containing default options. The default options + * are merged with the userOptions to get the final options for a + * specific level. + * - `from` The lowest level number. + * - `levels` User options from series.levels. + * - `to` The highest level number. + * @return {Highcharts.Dictionary|null} + * Returns a map from level number to its given options. + */ + var getLevelOptions = function getLevelOptions(params) { + var result = null, defaults, converted, i, from, to, levels; + if (isObject(params)) { + result = {}; + from = isNumber(params.from) ? params.from : 1; + levels = params.levels; + converted = {}; + defaults = isObject(params.defaults) ? params.defaults : {}; + if (isArray(levels)) { + converted = levels.reduce(function (obj, item) { + var level, levelIsConstant, options; + if (isObject(item) && isNumber(item.level)) { + options = merge({}, item); + levelIsConstant = (isBoolean(options.levelIsConstant) ? + options.levelIsConstant : + defaults.levelIsConstant); + // Delete redundant properties. + delete options.levelIsConstant; + delete options.level; + // Calculate which level these options apply to. + level = item.level + (levelIsConstant ? 0 : from - 1); + if (isObject(obj[level])) { + extend(obj[level], options); + } + else { + obj[level] = options; + } + } + return obj; + }, {}); + } + to = isNumber(params.to) ? params.to : 1; + for (i = 0; i <= to; i++) { + result[i] = merge({}, defaults, isObject(converted[i]) ? converted[i] : {}); + } + } + return result; + }; + /** + * Update the rootId property on the series. Also makes sure that it is + * accessible to exporting. + * + * @private + * @function updateRootId + * + * @param {object} series + * The series to operate on. + * + * @return {string} + * Returns the resulting rootId after update. + */ + var updateRootId = function (series) { + var rootId, options; + if (isObject(series)) { + // Get the series options. + options = isObject(series.options) ? series.options : {}; + // Calculate the rootId. + rootId = pick(series.rootNode, options.rootId, ''); + // Set rootId on series.userOptions to pick it up in exporting. + if (isObject(series.userOptions)) { + series.userOptions.rootId = rootId; + } + // Set rootId on series to pick it up on next update. + series.rootNode = rootId; + } + return rootId; + }; + var result = { + getColor: getColor, + getLevelOptions: getLevelOptions, + setTreeValues: setTreeValues, + updateRootId: updateRootId + }; + + return result; + }); + _registerModule(_modules, 'parts-gantt/GridAxis.js', [_modules['parts/Axis.js'], _modules['parts/Globals.js'], _modules['parts/Tick.js'], _modules['parts/Utilities.js']], function (Axis, H, Tick, U) { + /* * + * + * (c) 2016 Highsoft AS + * Authors: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, defined = U.defined, erase = U.erase, find = U.find, isArray = U.isArray, isNumber = U.isNumber, merge = U.merge, pick = U.pick, timeUnits = U.timeUnits, wrap = U.wrap; + var argsToArray = function (args) { + return Array.prototype.slice.call(args, 1); + }, dateFormat = H.dateFormat, isObject = function (x) { + // Always use strict mode + return U.isObject(x, true); + }, Chart = H.Chart; + var applyGridOptions = function applyGridOptions(axis) { + var options = axis.options; + // Center-align by default + if (!options.labels) { + options.labels = {}; + } + options.labels.align = pick(options.labels.align, 'center'); + // @todo: Check against tickLabelPlacement between/on etc + /* Prevents adding the last tick label if the axis is not a category + axis. + Since numeric labels are normally placed at starts and ends of a + range of value, and this module makes the label point at the value, + an "extra" label would appear. */ + if (!axis.categories) { + options.showLastLabel = false; + } + // Prevents rotation of labels when squished, as rotating them would not + // help. + axis.labelRotation = 0; + options.labels.rotation = 0; + }; + /** + * Set grid options for the axis labels. Requires Highcharts Gantt. + * + * @since 6.2.0 + * @product gantt + * @apioption xAxis.grid + */ + /** + * Enable grid on the axis labels. Defaults to true for Gantt charts. + * + * @type {boolean} + * @default true + * @since 6.2.0 + * @product gantt + * @apioption xAxis.grid.enabled + */ + /** + * Set specific options for each column (or row for horizontal axes) in the + * grid. Each extra column/row is its own axis, and the axis options can be set + * here. + * + * @sample gantt/demo/left-axis-table + * Left axis as a table + * + * @type {Array} + * @apioption xAxis.grid.columns + */ + /** + * Set border color for the label grid lines. + * + * @type {Highcharts.ColorString} + * @apioption xAxis.grid.borderColor + */ + /** + * Set border width of the label grid lines. + * + * @type {number} + * @default 1 + * @apioption xAxis.grid.borderWidth + */ + /** + * Set cell height for grid axis labels. By default this is calculated from font + * size. This option only applies to horizontal axes. + * + * @sample gantt/grid-axis/cellheight + * Gant chart with custom cell height + * @type {number} + * @apioption xAxis.grid.cellHeight + */ + ''; // detach doclets above + /** + * Get the largest label width and height. + * + * @private + * @function Highcharts.Axis#getMaxLabelDimensions + * + * @param {Highcharts.Dictionary} ticks + * All the ticks on one axis. + * + * @param {Array} tickPositions + * All the tick positions on one axis. + * + * @return {Highcharts.SizeObject} + * Object containing the properties height and width. + * + * @todo Move this to the generic axis implementation, as it is used there. + */ + Axis.prototype.getMaxLabelDimensions = function (ticks, tickPositions) { + var dimensions = { + width: 0, + height: 0 + }; + tickPositions.forEach(function (pos) { + var tick = ticks[pos], tickHeight = 0, tickWidth = 0, label; + if (isObject(tick)) { + label = isObject(tick.label) ? tick.label : {}; + // Find width and height of tick + tickHeight = label.getBBox ? label.getBBox().height : 0; + if (label.textStr && !isNumber(label.textPxLength)) { + label.textPxLength = label.getBBox().width; + } + tickWidth = isNumber(label.textPxLength) ? + // Math.round ensures crisp lines + Math.round(label.textPxLength) : + 0; + // Update the result if width and/or height are larger + dimensions.height = Math.max(tickHeight, dimensions.height); + dimensions.width = Math.max(tickWidth, dimensions.width); + } + }); + return dimensions; + }; + // Adds week date format + H.dateFormats.W = function (timestamp) { + var d = new this.Date(timestamp); + var firstDay = (this.get('Day', d) + 6) % 7; + var thursday = new this.Date(d.valueOf()); + this.set('Date', thursday, this.get('Date', d) - firstDay + 3); + var firstThursday = new this.Date(this.get('FullYear', thursday), 0, 1); + if (this.get('Day', firstThursday) !== 4) { + this.set('Month', d, 0); + this.set('Date', d, 1 + (11 - this.get('Day', firstThursday)) % 7); + } + return (1 + + Math.floor((thursday.valueOf() - firstThursday.valueOf()) / 604800000)).toString(); + }; + // First letter of the day of the week, e.g. 'M' for 'Monday'. + H.dateFormats.E = function (timestamp) { + return dateFormat('%a', timestamp, true).charAt(0); + }; + /* eslint-disable no-invalid-this */ + addEvent(Chart, 'afterSetChartSize', function () { + this.axes.forEach(function (axis) { + (axis.grid && axis.grid.columns || []).forEach(function (column) { + column.setAxisSize(); + column.setAxisTranslation(); + }); + }); + }); + // Center tick labels in cells. + addEvent(Tick, 'afterGetLabelPosition', function (e) { + var tick = this, label = tick.label, axis = tick.axis, reversed = axis.reversed, chart = axis.chart, options = axis.options, gridOptions = options.grid || {}, labelOpts = axis.options.labels, align = labelOpts.align, + // verticalAlign is currently not supported for axis.labels. + verticalAlign = 'middle', // labelOpts.verticalAlign, + side = GridAxis.Side[axis.side], tickmarkOffset = e.tickmarkOffset, tickPositions = axis.tickPositions, tickPos = tick.pos - tickmarkOffset, nextTickPos = (isNumber(tickPositions[e.index + 1]) ? + tickPositions[e.index + 1] - tickmarkOffset : + axis.max + tickmarkOffset), tickSize = axis.tickSize('tick'), tickWidth = tickSize ? tickSize[0] : 0, crispCorr = tickSize ? tickSize[1] / 2 : 0, labelHeight, lblMetrics, lines, bottom, top, left, right; + // Only center tick labels in grid axes + if (gridOptions.enabled === true) { + // Calculate top and bottom positions of the cell. + if (side === 'top') { + bottom = axis.top + axis.offset; + top = bottom - tickWidth; + } + else if (side === 'bottom') { + top = chart.chartHeight - axis.bottom + axis.offset; + bottom = top + tickWidth; + } + else { + bottom = axis.top + axis.len - axis.translate(reversed ? nextTickPos : tickPos); + top = axis.top + axis.len - axis.translate(reversed ? tickPos : nextTickPos); + } + // Calculate left and right positions of the cell. + if (side === 'right') { + left = chart.chartWidth - axis.right + axis.offset; + right = left + tickWidth; + } + else if (side === 'left') { + right = axis.left + axis.offset; + left = right - tickWidth; + } + else { + left = Math.round(axis.left + axis.translate(reversed ? nextTickPos : tickPos)) - crispCorr; + right = Math.round(axis.left + axis.translate(reversed ? tickPos : nextTickPos)) - crispCorr; + } + tick.slotWidth = right - left; + // Calculate the positioning of the label based on + // alignment. + e.pos.x = (align === 'left' ? + left : + align === 'right' ? + right : + left + ((right - left) / 2) // default to center + ); + e.pos.y = (verticalAlign === 'top' ? + top : + verticalAlign === 'bottom' ? + bottom : + top + ((bottom - top) / 2) // default to middle + ); + lblMetrics = chart.renderer.fontMetrics(labelOpts.style.fontSize, label.element); + labelHeight = label.getBBox().height; + // Adjustment to y position to align the label correctly. + // Would be better to have a setter or similar for this. + if (!labelOpts.useHTML) { + lines = Math.round(labelHeight / lblMetrics.h); + e.pos.y += ( + // Center the label + // TODO: why does this actually center the label? + ((lblMetrics.b - (lblMetrics.h - lblMetrics.f)) / 2) + + // Adjust for height of additional lines. + -(((lines - 1) * lblMetrics.h) / 2)); + } + else { + e.pos.y += ( + // Readjust yCorr in htmlUpdateTransform + lblMetrics.b + + // Adjust for height of html label + -(labelHeight / 2)); + } + e.pos.x += (axis.horiz && labelOpts.x || 0); + } + }); + /* eslint-enable no-invalid-this */ + /** + * Additions for grid axes. + * @private + * @class + */ + var GridAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function GridAxisAdditions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Checks if an axis is the outer axis in its dimension. Since + * axes are placed outwards in order, the axis with the highest + * index is the outermost axis. + * + * Example: If there are multiple x-axes at the top of the chart, + * this function returns true if the axis supplied is the last + * of the x-axes. + * + * @private + * + * @return {boolean} + * True if the axis is the outermost axis in its dimension; false if + * not. + */ + GridAxisAdditions.prototype.isOuterAxis = function () { + var axis = this.axis; + var chart = axis.chart; + var columnIndex = axis.grid.columnIndex; + var columns = (axis.linkedParent && axis.linkedParent.grid.columns || + axis.grid.columns); + var parentAxis = columnIndex ? axis.linkedParent : axis; + var thisIndex = -1, lastIndex = 0; + chart[axis.coll].forEach(function (otherAxis, index) { + if (otherAxis.side === axis.side && !otherAxis.options.isInternal) { + lastIndex = index; + if (otherAxis === parentAxis) { + // Get the index of the axis in question + thisIndex = index; + } + } + }); + return (lastIndex === thisIndex && + (isNumber(columnIndex) ? columns.length === columnIndex : true)); + }; + return GridAxisAdditions; + }()); + /** + * Axis with grid support. + * @private + * @class + */ + var GridAxis = /** @class */ (function () { + function GridAxis() { + } + /* * + * + * Static Functions + * + * */ + /* eslint-disable valid-jsdoc */ + /** + * Extends axis class with grid support. + * @private + */ + GridAxis.compose = function (AxisClass) { + Axis.keepProps.push('grid'); + wrap(AxisClass.prototype, 'unsquish', GridAxis.wrapUnsquish); + // Add event handlers + addEvent(AxisClass, 'init', GridAxis.onInit); + addEvent(AxisClass, 'afterGetOffset', GridAxis.onAfterGetOffset); + addEvent(AxisClass, 'afterGetTitlePosition', GridAxis.onAfterGetTitlePosition); + addEvent(AxisClass, 'afterInit', GridAxis.onAfterInit); + addEvent(AxisClass, 'afterRender', GridAxis.onAfterRender); + addEvent(AxisClass, 'afterSetAxisTranslation', GridAxis.onAfterSetAxisTranslation); + addEvent(AxisClass, 'afterSetOptions', GridAxis.onAfterSetOptions); + addEvent(AxisClass, 'afterSetOptions', GridAxis.onAfterSetOptions2); + addEvent(AxisClass, 'afterSetScale', GridAxis.onAfterSetScale); + addEvent(AxisClass, 'afterTickSize', GridAxis.onAfterTickSize); + addEvent(AxisClass, 'trimTicks', GridAxis.onTrimTicks); + addEvent(AxisClass, 'destroy', GridAxis.onDestroy); + }; + /** + * Handle columns and getOffset. + * @private + */ + GridAxis.onAfterGetOffset = function () { + var grid = this.grid; + (grid && grid.columns || []).forEach(function (column) { + column.getOffset(); + }); + }; + /** + * @private + */ + GridAxis.onAfterGetTitlePosition = function (e) { + var axis = this; + var options = axis.options; + var gridOptions = options.grid || {}; + if (gridOptions.enabled === true) { + // compute anchor points for each of the title align options + var title = axis.axisTitle, axisHeight = axis.height, horiz = axis.horiz, axisLeft = axis.left, offset = axis.offset, opposite = axis.opposite, _a = axis.options.title, axisTitleOptions = _a === void 0 ? {} : _a, axisTop = axis.top, axisWidth = axis.width; + var tickSize = axis.tickSize(); + var titleWidth = title && title.getBBox().width; + var xOption = axisTitleOptions.x || 0; + var yOption = axisTitleOptions.y || 0; + var titleMargin = pick(axisTitleOptions.margin, horiz ? 5 : 10); + var titleFontSize = axis.chart.renderer.fontMetrics(axisTitleOptions.style && + axisTitleOptions.style.fontSize, title).f; + var crispCorr = tickSize ? tickSize[0] / 2 : 0; + // TODO account for alignment + // the position in the perpendicular direction of the axis + var offAxis = ((horiz ? axisTop + axisHeight : axisLeft) + + (horiz ? 1 : -1) * // horizontal axis reverses the margin + (opposite ? -1 : 1) * // so does opposite axes + crispCorr + + (axis.side === GridAxis.Side.bottom ? titleFontSize : 0)); + e.titlePosition.x = horiz ? + axisLeft - titleWidth / 2 - titleMargin + xOption : + offAxis + (opposite ? axisWidth : 0) + offset + xOption; + e.titlePosition.y = horiz ? + (offAxis - + (opposite ? axisHeight : 0) + + (opposite ? titleFontSize : -titleFontSize) / 2 + + offset + + yOption) : + axisTop - titleMargin + yOption; + } + }; + /** + * @private + */ + GridAxis.onAfterInit = function () { + var axis = this; + var chart = axis.chart, _a = axis.options.grid, gridOptions = _a === void 0 ? {} : _a, userOptions = axis.userOptions; + if (gridOptions.enabled) { + applyGridOptions(axis); + /* eslint-disable no-invalid-this */ + // TODO: wrap the axis instead + wrap(axis, 'labelFormatter', function (proceed) { + var _a = this, axis = _a.axis, value = _a.value; + var tickPos = axis.tickPositions; + var series = (axis.isLinked ? + axis.linkedParent : + axis).series[0]; + var isFirst = value === tickPos[0]; + var isLast = value === tickPos[tickPos.length - 1]; + var point = series && find(series.options.data, function (p) { + return p[axis.isXAxis ? 'x' : 'y'] === value; + }); + // Make additional properties available for the + // formatter + this.isFirst = isFirst; + this.isLast = isLast; + this.point = point; + // Call original labelFormatter + return proceed.call(this); + }); + /* eslint-enable no-invalid-this */ + } + if (gridOptions.columns) { + var columns = axis.grid.columns = [], columnIndex = axis.grid.columnIndex = 0; + // Handle columns, each column is a grid axis + while (++columnIndex < gridOptions.columns.length) { + var columnOptions = merge(userOptions, gridOptions.columns[gridOptions.columns.length - columnIndex - 1], { + linkedTo: 0, + // Force to behave like category axis + type: 'category' + }); + delete columnOptions.grid.columns; // Prevent recursion + var column = new Axis(axis.chart, columnOptions); + column.grid.isColumn = true; + column.grid.columnIndex = columnIndex; + // Remove column axis from chart axes array, and place it + // in the columns array. + erase(chart.axes, column); + erase(chart[axis.coll], column); + columns.push(column); + } + } + }; + /** + * Draw an extra line on the far side of the outermost axis, + * creating floor/roof/wall of a grid. And some padding. + * ``` + * Make this: + * (axis.min) __________________________ (axis.max) + * | | | | | + * Into this: + * (axis.min) __________________________ (axis.max) + * ___|____|____|____|____|__ + * ``` + * @private + */ + GridAxis.onAfterRender = function () { + var axis = this; + var grid = axis.grid; + var options = axis.options; + var renderer = axis.chart.renderer; + var gridOptions = options.grid || {}; + var yStartIndex, yEndIndex, xStartIndex, xEndIndex; + if (gridOptions.enabled === true) { + // @todo acutual label padding (top, bottom, left, right) + axis.maxLabelDimensions = axis.getMaxLabelDimensions(axis.ticks, axis.tickPositions); + // Remove right wall before rendering if updating + if (axis.rightWall) { + axis.rightWall.destroy(); + } + /* + Draw an extra axis line on outer axes + > + Make this: |______|______|______|___ + + > _________________________ + Into this: |______|______|______|__| + */ + if (axis.grid && axis.grid.isOuterAxis() && axis.axisLine) { + var lineWidth = options.lineWidth; + if (lineWidth) { + var linePath = axis.getLinePath(lineWidth); + var startPoint = linePath[0]; + var endPoint = linePath[1]; + // Negate distance if top or left axis + // Subtract 1px to draw the line at the end of the tick + var tickLength = (axis.tickSize('tick') || [1])[0]; + var distance = (tickLength - 1) * ((axis.side === GridAxis.Side.top || + axis.side === GridAxis.Side.left) ? -1 : 1); + // If axis is horizontal, reposition line path vertically + if (startPoint[0] === 'M' && endPoint[0] === 'L') { + if (axis.horiz) { + startPoint[2] += distance; + endPoint[2] += distance; + } + else { + // If axis is vertical, reposition line path + // horizontally + startPoint[1] += distance; + endPoint[1] += distance; + } + } + if (!axis.grid.axisLineExtra) { + axis.grid.axisLineExtra = renderer + .path(linePath) + .attr({ + zIndex: 7 + }) + .addClass('highcharts-axis-line') + .add(axis.axisGroup); + if (!renderer.styledMode) { + axis.grid.axisLineExtra.attr({ + stroke: options.lineColor, + 'stroke-width': lineWidth + }); + } + } + else { + axis.grid.axisLineExtra.animate({ + d: linePath + }); + } + // show or hide the line depending on + // options.showEmpty + axis.axisLine[axis.showAxis ? 'show' : 'hide'](true); + } + } + (grid && grid.columns || []).forEach(function (column) { + column.render(); + }); + } + }; + /** + * @private + */ + GridAxis.onAfterSetAxisTranslation = function () { + var axis = this; + var tickInfo = axis.tickPositions && axis.tickPositions.info; + var options = axis.options; + var gridOptions = options.grid || {}; + var userLabels = axis.userOptions.labels || {}; + if (axis.horiz) { + if (gridOptions.enabled === true) { + axis.series.forEach(function (series) { + series.options.pointRange = 0; + }); + } + // Lower level time ticks, like hours or minutes, represent + // points in time and not ranges. These should be aligned + // left in the grid cell by default. The same applies to + // years of higher order. + if (tickInfo && + options.dateTimeLabelFormats && + options.labels && + !defined(userLabels.align) && + (options.dateTimeLabelFormats[tickInfo.unitName].range === false || + tickInfo.count > 1 // years + )) { + options.labels.align = 'left'; + if (!defined(userLabels.x)) { + options.labels.x = 3; + } + } + } + }; + /** + * Creates a left and right wall on horizontal axes: + * - Places leftmost tick at the start of the axis, to create a left + * wall + * - Ensures that the rightmost tick is at the end of the axis, to + * create a right wall. + * @private + */ + GridAxis.onAfterSetOptions = function (e) { + var options = this.options, userOptions = e.userOptions, gridAxisOptions, gridOptions = ((options && isObject(options.grid)) ? options.grid : {}); + if (gridOptions.enabled === true) { + // Merge the user options into default grid axis options so + // that when a user option is set, it takes presedence. + gridAxisOptions = merge(true, { + className: ('highcharts-grid-axis ' + (userOptions.className || '')), + dateTimeLabelFormats: { + hour: { + list: ['%H:%M', '%H'] + }, + day: { + list: ['%A, %e. %B', '%a, %e. %b', '%E'] + }, + week: { + list: ['Week %W', 'W%W'] + }, + month: { + list: ['%B', '%b', '%o'] + } + }, + grid: { + borderWidth: 1 + }, + labels: { + padding: 2, + style: { + fontSize: '13px' + } + }, + margin: 0, + title: { + text: null, + reserveSpace: false, + rotation: 0 + }, + // In a grid axis, only allow one unit of certain types, + // for example we shouln't have one grid cell spanning + // two days. + units: [[ + 'millisecond', + [1, 10, 100] + ], [ + 'second', + [1, 10] + ], [ + 'minute', + [1, 5, 15] + ], [ + 'hour', + [1, 6] + ], [ + 'day', + [1] + ], [ + 'week', + [1] + ], [ + 'month', + [1] + ], [ + 'year', + null + ]] + }, userOptions); + // X-axis specific options + if (this.coll === 'xAxis') { + // For linked axes, tickPixelInterval is used only if + // the tickPositioner below doesn't run or returns + // undefined (like multiple years) + if (defined(userOptions.linkedTo) && + !defined(userOptions.tickPixelInterval)) { + gridAxisOptions.tickPixelInterval = 350; + } + // For the secondary grid axis, use the primary axis' + // tick intervals and return ticks one level higher. + if ( + // Check for tick pixel interval in options + !defined(userOptions.tickPixelInterval) && + // Only for linked axes + defined(userOptions.linkedTo) && + !defined(userOptions.tickPositioner) && + !defined(userOptions.tickInterval)) { + gridAxisOptions.tickPositioner = function (min, max) { + var parentInfo = (this.linkedParent && + this.linkedParent.tickPositions && + this.linkedParent.tickPositions.info); + if (parentInfo) { + var unitIdx, count, unitName, i, units = gridAxisOptions.units, unitRange; + for (i = 0; i < units.length; i++) { + if (units[i][0] === + parentInfo.unitName) { + unitIdx = i; + break; + } + } + // Get the first allowed count on the next + // unit. + if (units[unitIdx + 1]) { + unitName = units[unitIdx + 1][0]; + count = + (units[unitIdx + 1][1] || [1])[0]; + // In case the base X axis shows years, make + // the secondary axis show ten times the + // years (#11427) + } + else if (parentInfo.unitName === 'year') { + unitName = 'year'; + count = parentInfo.count * 10; + } + unitRange = timeUnits[unitName]; + this.tickInterval = unitRange * count; + return this.getTimeTicks({ + unitRange: unitRange, + count: count, + unitName: unitName + }, min, max, this.options.startOfWeek); + } + }; + } + } + // Now merge the combined options into the axis options + merge(true, this.options, gridAxisOptions); + if (this.horiz) { + /* _________________________ + Make this: ___|_____|_____|_____|__| + ^ ^ + _________________________ + Into this: |_____|_____|_____|_____| + ^ ^ */ + options.minPadding = pick(userOptions.minPadding, 0); + options.maxPadding = pick(userOptions.maxPadding, 0); + } + // If borderWidth is set, then use its value for tick and + // line width. + if (isNumber(options.grid.borderWidth)) { + options.tickWidth = options.lineWidth = gridOptions.borderWidth; + } + } + }; + /** + * @private + */ + GridAxis.onAfterSetOptions2 = function (e) { + var axis = this; + var userOptions = e.userOptions; + var gridOptions = userOptions && userOptions.grid || {}; + var columns = gridOptions.columns; + // Add column options to the parent axis. Children has their column + // options set on init in onGridAxisAfterInit. + if (gridOptions.enabled && columns) { + merge(true, axis.options, columns[columns.length - 1]); + } + }; + /** + * Handle columns and setScale. + * @private + */ + GridAxis.onAfterSetScale = function () { + var axis = this; + (axis.grid.columns || []).forEach(function (column) { + column.setScale(); + }); + }; + /** + * Draw vertical axis ticks extra long to create cell floors and roofs. + * Overrides the tickLength for vertical axes. + * @private + */ + GridAxis.onAfterTickSize = function (e) { + var defaultLeftAxisOptions = Axis.defaultLeftAxisOptions; + var _a = this, horiz = _a.horiz, maxLabelDimensions = _a.maxLabelDimensions, _b = _a.options.grid, gridOptions = _b === void 0 ? {} : _b; + if (gridOptions.enabled && maxLabelDimensions) { + var labelPadding = (Math.abs(defaultLeftAxisOptions.labels.x) * 2); + var distance = horiz ? + gridOptions.cellHeight || labelPadding + maxLabelDimensions.height : + labelPadding + maxLabelDimensions.width; + if (isArray(e.tickSize)) { + e.tickSize[0] = distance; + } + else { + e.tickSize = [distance, 0]; + } + } + }; + /** + * @private + */ + GridAxis.onDestroy = function (e) { + var grid = this.grid; + (grid.columns || []).forEach(function (column) { + column.destroy(e.keepEvents); + }); + grid.columns = void 0; + }; + /** + * Wraps axis init to draw cell walls on vertical axes. + * @private + */ + GridAxis.onInit = function (e) { + var axis = this; + var userOptions = e.userOptions || {}; + var gridOptions = userOptions.grid || {}; + if (gridOptions.enabled && defined(gridOptions.borderColor)) { + userOptions.tickColor = userOptions.lineColor = gridOptions.borderColor; + } + if (!axis.grid) { + axis.grid = new GridAxisAdditions(axis); + } + }; + /** + * Makes tick labels which are usually ignored in a linked axis + * displayed if they are within range of linkedParent.min. + * ``` + * _____________________________ + * | | | | | + * Make this: | | 2 | 3 | 4 | + * |___|_______|_______|_______| + * ^ + * _____________________________ + * | | | | | + * Into this: | 1 | 2 | 3 | 4 | + * |___|_______|_______|_______| + * ^ + * ``` + * @private + * @todo Does this function do what the drawing says? Seems to affect + * ticks and not the labels directly? + */ + GridAxis.onTrimTicks = function () { + var axis = this; + var options = axis.options; + var gridOptions = options.grid || {}; + var categoryAxis = axis.categories; + var tickPositions = axis.tickPositions; + var firstPos = tickPositions[0]; + var lastPos = tickPositions[tickPositions.length - 1]; + var linkedMin = axis.linkedParent && axis.linkedParent.min; + var linkedMax = axis.linkedParent && axis.linkedParent.max; + var min = linkedMin || axis.min; + var max = linkedMax || axis.max; + var tickInterval = axis.tickInterval; + var endMoreThanMin = (firstPos < min && + firstPos + tickInterval > min); + var startLessThanMax = (lastPos > max && + lastPos - tickInterval < max); + if (gridOptions.enabled === true && + !categoryAxis && + (axis.horiz || axis.isLinked)) { + if (endMoreThanMin && !options.startOnTick) { + tickPositions[0] = min; + } + if (startLessThanMax && !options.endOnTick) { + tickPositions[tickPositions.length - 1] = max; + } + } + }; + /** + * Avoid altering tickInterval when reserving space. + * @private + */ + GridAxis.wrapUnsquish = function (proceed) { + var axis = this; + var _a = axis.options.grid, gridOptions = _a === void 0 ? {} : _a; + if (gridOptions.enabled === true && axis.categories) { + return axis.tickInterval; + } + return proceed.apply(axis, argsToArray(arguments)); + }; + return GridAxis; + }()); + (function (GridAxis) { + /** + * Enum for which side the axis is on. Maps to axis.side. + * @private + */ + var Side; + (function (Side) { + Side[Side["top"] = 0] = "top"; + Side[Side["right"] = 1] = "right"; + Side[Side["bottom"] = 2] = "bottom"; + Side[Side["left"] = 3] = "left"; + })(Side = GridAxis.Side || (GridAxis.Side = {})); + })(GridAxis || (GridAxis = {})); + GridAxis.compose(Axis); + + return GridAxis; + }); + _registerModule(_modules, 'modules/broken-axis.src.js', [_modules['parts/Axis.js'], _modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['parts/Stacking.js']], function (Axis, H, U, StackItem) { + /* * + * + * (c) 2009-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, find = U.find, fireEvent = U.fireEvent, isArray = U.isArray, isNumber = U.isNumber, pick = U.pick; + var Series = H.Series; + /* eslint-disable valid-jsdoc */ + /** + * Provides support for broken axes. + * @private + * @class + */ + var BrokenAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function BrokenAxisAdditions(axis) { + this.hasBreaks = false; + this.axis = axis; + } + /* * + * + * Static Functions + * + * */ + /** + * @private + */ + BrokenAxisAdditions.isInBreak = function (brk, val) { + var ret, repeat = brk.repeat || Infinity, from = brk.from, length = brk.to - brk.from, test = (val >= from ? + (val - from) % repeat : + repeat - ((from - val) % repeat)); + if (!brk.inclusive) { + ret = test < length && test !== 0; + } + else { + ret = test <= length; + } + return ret; + }; + /** + * @private + */ + BrokenAxisAdditions.lin2Val = function (val) { + var axis = this; + var brokenAxis = axis.brokenAxis; + var breakArray = brokenAxis && brokenAxis.breakArray; + if (!breakArray) { + return val; + } + var nval = val, brk, i; + for (i = 0; i < breakArray.length; i++) { + brk = breakArray[i]; + if (brk.from >= nval) { + break; + } + else if (brk.to < nval) { + nval += brk.len; + } + else if (BrokenAxisAdditions.isInBreak(brk, nval)) { + nval += brk.len; + } + } + return nval; + }; + /** + * @private + */ + BrokenAxisAdditions.val2Lin = function (val) { + var axis = this; + var brokenAxis = axis.brokenAxis; + var breakArray = brokenAxis && brokenAxis.breakArray; + if (!breakArray) { + return val; + } + var nval = val, brk, i; + for (i = 0; i < breakArray.length; i++) { + brk = breakArray[i]; + if (brk.to <= val) { + nval -= brk.len; + } + else if (brk.from >= val) { + break; + } + else if (BrokenAxisAdditions.isInBreak(brk, val)) { + nval -= (val - brk.from); + break; + } + } + return nval; + }; + /* * + * + * Functions + * + * */ + /** + * Returns the first break found where the x is larger then break.from and + * smaller then break.to. + * + * @param {number} x + * The number which should be within a break. + * + * @param {Array} breaks + * The array of breaks to search within. + * + * @return {Highcharts.XAxisBreaksOptions|undefined} + * Returns the first break found that matches, returns false if no break is + * found. + */ + BrokenAxisAdditions.prototype.findBreakAt = function (x, breaks) { + return find(breaks, function (b) { + return b.from < x && x < b.to; + }); + }; + /** + * @private + */ + BrokenAxisAdditions.prototype.isInAnyBreak = function (val, testKeep) { + var brokenAxis = this; + var axis = brokenAxis.axis; + var breaks = axis.options.breaks, i = breaks && breaks.length, inbrk, keep, ret; + if (i) { + while (i--) { + if (BrokenAxisAdditions.isInBreak(breaks[i], val)) { + inbrk = true; + if (!keep) { + keep = pick(breaks[i].showPoints, !axis.isXAxis); + } + } + } + if (inbrk && testKeep) { + ret = inbrk && !keep; + } + else { + ret = inbrk; + } + } + return ret; + }; + /** + * Dynamically set or unset breaks in an axis. This function in lighter than + * usin Axis.update, and it also preserves animation. + * + * @private + * @function Highcharts.Axis#setBreaks + * + * @param {Array} [breaks] + * The breaks to add. When `undefined` it removes existing breaks. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart immediately. + * + * @return {void} + */ + BrokenAxisAdditions.prototype.setBreaks = function (breaks, redraw) { + var brokenAxis = this; + var axis = brokenAxis.axis; + var hasBreaks = (isArray(breaks) && !!breaks.length); + axis.isDirty = brokenAxis.hasBreaks !== hasBreaks; + brokenAxis.hasBreaks = hasBreaks; + axis.options.breaks = axis.userOptions.breaks = breaks; + axis.forceRedraw = true; // Force recalculation in setScale + // Recalculate series related to the axis. + axis.series.forEach(function (series) { + series.isDirty = true; + }); + if (!hasBreaks && axis.val2lin === BrokenAxisAdditions.val2Lin) { + // Revert to prototype functions + delete axis.val2lin; + delete axis.lin2val; + } + if (hasBreaks) { + axis.userOptions.ordinal = false; + axis.lin2val = BrokenAxisAdditions.lin2Val; + axis.val2lin = BrokenAxisAdditions.val2Lin; + axis.setExtremes = function (newMin, newMax, redraw, animation, eventArguments) { + // If trying to set extremes inside a break, extend min to + // after, and max to before the break ( #3857 ) + if (brokenAxis.hasBreaks) { + var axisBreak, breaks = this.options.breaks; + while ((axisBreak = brokenAxis.findBreakAt(newMin, breaks))) { + newMin = axisBreak.to; + } + while ((axisBreak = brokenAxis.findBreakAt(newMax, breaks))) { + newMax = axisBreak.from; + } + // If both min and max is within the same break. + if (newMax < newMin) { + newMax = newMin; + } + } + Axis.prototype.setExtremes.call(this, newMin, newMax, redraw, animation, eventArguments); + }; + axis.setAxisTranslation = function (saveOld) { + Axis.prototype.setAxisTranslation.call(this, saveOld); + brokenAxis.unitLength = null; + if (brokenAxis.hasBreaks) { + var breaks = axis.options.breaks || [], + // Temporary one: + breakArrayT = [], breakArray = [], length = 0, inBrk, repeat, min = axis.userMin || axis.min, max = axis.userMax || axis.max, pointRangePadding = pick(axis.pointRangePadding, 0), start, i; + // Min & max check (#4247) + breaks.forEach(function (brk) { + repeat = brk.repeat || Infinity; + if (BrokenAxisAdditions.isInBreak(brk, min)) { + min += + (brk.to % repeat) - + (min % repeat); + } + if (BrokenAxisAdditions.isInBreak(brk, max)) { + max -= + (max % repeat) - + (brk.from % repeat); + } + }); + // Construct an array holding all breaks in the axis + breaks.forEach(function (brk) { + start = brk.from; + repeat = brk.repeat || Infinity; + while (start - repeat > min) { + start -= repeat; + } + while (start < min) { + start += repeat; + } + for (i = start; i < max; i += repeat) { + breakArrayT.push({ + value: i, + move: 'in' + }); + breakArrayT.push({ + value: i + (brk.to - brk.from), + move: 'out', + size: brk.breakSize + }); + } + }); + breakArrayT.sort(function (a, b) { + return ((a.value === b.value) ? + ((a.move === 'in' ? 0 : 1) - + (b.move === 'in' ? 0 : 1)) : + a.value - b.value); + }); + // Simplify the breaks + inBrk = 0; + start = min; + breakArrayT.forEach(function (brk) { + inBrk += (brk.move === 'in' ? 1 : -1); + if (inBrk === 1 && brk.move === 'in') { + start = brk.value; + } + if (inBrk === 0) { + breakArray.push({ + from: start, + to: brk.value, + len: brk.value - start - (brk.size || 0) + }); + length += brk.value - start - (brk.size || 0); + } + }); + /** + * HC <= 8 backwards compatibility, used by demo samples. + * @deprecated + * @private + * @requires modules/broken-axis + */ + axis.breakArray = brokenAxis.breakArray = breakArray; + // Used with staticScale, and below the actual axis length, + // when breaks are substracted. + brokenAxis.unitLength = max - min - length + pointRangePadding; + fireEvent(axis, 'afterBreaks'); + if (axis.staticScale) { + axis.transA = axis.staticScale; + } + else if (brokenAxis.unitLength) { + axis.transA *= + (max - axis.min + pointRangePadding) / + brokenAxis.unitLength; + } + if (pointRangePadding) { + axis.minPixelPadding = + axis.transA * axis.minPointOffset; + } + axis.min = min; + axis.max = max; + } + }; + } + if (pick(redraw, true)) { + axis.chart.redraw(); + } + }; + return BrokenAxisAdditions; + }()); + /** + * Axis with support of broken data rows. + * @private + * @class + */ + var BrokenAxis = /** @class */ (function () { + function BrokenAxis() { + } + /** + * Adds support for broken axes. + * @private + */ + BrokenAxis.compose = function (AxisClass, SeriesClass) { + AxisClass.keepProps.push('brokenAxis'); + var seriesProto = Series.prototype; + /** + * @private + */ + seriesProto.drawBreaks = function (axis, keys) { + var series = this, points = series.points, breaks, threshold, eventName, y; + if (axis && // #5950 + axis.brokenAxis && + axis.brokenAxis.hasBreaks) { + var brokenAxis_1 = axis.brokenAxis; + keys.forEach(function (key) { + breaks = brokenAxis_1 && brokenAxis_1.breakArray || []; + threshold = axis.isXAxis ? + axis.min : + pick(series.options.threshold, axis.min); + points.forEach(function (point) { + y = pick(point['stack' + key.toUpperCase()], point[key]); + breaks.forEach(function (brk) { + if (isNumber(threshold) && isNumber(y)) { + eventName = false; + if ((threshold < brk.from && y > brk.to) || + (threshold > brk.from && y < brk.from)) { + eventName = 'pointBreak'; + } + else if ((threshold < brk.from && y > brk.from && y < brk.to) || + (threshold > brk.from && y > brk.to && y < brk.from)) { + eventName = 'pointInBreak'; + } + if (eventName) { + fireEvent(axis, eventName, { point: point, brk: brk }); + } + } + }); + }); + }); + } + }; + /** + * Extend getGraphPath by identifying gaps in the data so that we can + * draw a gap in the line or area. This was moved from ordinal axis + * module to broken axis module as of #5045. + * + * @private + * @function Highcharts.Series#gappedPath + * + * @return {Highcharts.SVGPathArray} + * Gapped path + */ + seriesProto.gappedPath = function () { + var currentDataGrouping = this.currentDataGrouping, groupingSize = currentDataGrouping && currentDataGrouping.gapSize, gapSize = this.options.gapSize, points = this.points.slice(), i = points.length - 1, yAxis = this.yAxis, stack; + /** + * Defines when to display a gap in the graph, together with the + * [gapUnit](plotOptions.series.gapUnit) option. + * + * In case when `dataGrouping` is enabled, points can be grouped + * into a larger time span. This can make the grouped points to have + * a greater distance than the absolute value of `gapSize` property, + * which will result in disappearing graph completely. To prevent + * this situation the mentioned distance between grouped points is + * used instead of previously defined `gapSize`. + * + * In practice, this option is most often used to visualize gaps in + * time series. In a stock chart, intraday data is available for + * daytime hours, while gaps will appear in nights and weekends. + * + * @see [gapUnit](plotOptions.series.gapUnit) + * @see [xAxis.breaks](#xAxis.breaks) + * + * @sample {highstock} stock/plotoptions/series-gapsize/ + * Setting the gap size to 2 introduces gaps for weekends + * in daily datasets. + * + * @type {number} + * @default 0 + * @product highstock + * @requires modules/broken-axis + * @apioption plotOptions.series.gapSize + */ + /** + * Together with [gapSize](plotOptions.series.gapSize), this option + * defines where to draw gaps in the graph. + * + * When the `gapUnit` is `"relative"` (default), a gap size of 5 + * means that if the distance between two points is greater than + * 5 times that of the two closest points, the graph will be broken. + * + * When the `gapUnit` is `"value"`, the gap is based on absolute + * axis values, which on a datetime axis is milliseconds. This also + * applies to the navigator series that inherits gap options from + * the base series. + * + * @see [gapSize](plotOptions.series.gapSize) + * + * @type {string} + * @default relative + * @since 5.0.13 + * @product highstock + * @validvalue ["relative", "value"] + * @requires modules/broken-axis + * @apioption plotOptions.series.gapUnit + */ + if (gapSize && i > 0) { // #5008 + // Gap unit is relative + if (this.options.gapUnit !== 'value') { + gapSize *= this.basePointRange; + } + // Setting a new gapSize in case dataGrouping is enabled (#7686) + if (groupingSize && + groupingSize > gapSize && + // Except when DG is forced (e.g. from other series) + // and has lower granularity than actual points (#11351) + groupingSize >= this.basePointRange) { + gapSize = groupingSize; + } + // extension for ordinal breaks + var current = void 0, next = void 0; + while (i--) { + // Reassign next if it is not visible + if (!(next && next.visible !== false)) { + next = points[i + 1]; + } + current = points[i]; + // Skip iteration if one of the points is not visible + if (next.visible === false || current.visible === false) { + continue; + } + if (next.x - current.x > gapSize) { + var xRange = (current.x + next.x) / 2; + points.splice(// insert after this one + i + 1, 0, { + isNull: true, + x: xRange + }); + // For stacked chart generate empty stack items, #6546 + if (yAxis.stacking && this.options.stacking) { + stack = yAxis.stacking.stacks[this.stackKey][xRange] = + new StackItem(yAxis, yAxis.options + .stackLabels, false, xRange, this.stack); + stack.total = 0; + } + } + // Assign current to next for the upcoming iteration + next = current; + } + } + // Call base method + return this.getGraphPath(points); + }; + /* eslint-disable no-invalid-this */ + addEvent(AxisClass, 'init', function () { + var axis = this; + if (!axis.brokenAxis) { + axis.brokenAxis = new BrokenAxisAdditions(axis); + } + }); + addEvent(AxisClass, 'afterInit', function () { + if (typeof this.brokenAxis !== 'undefined') { + this.brokenAxis.setBreaks(this.options.breaks, false); + } + }); + addEvent(AxisClass, 'afterSetTickPositions', function () { + var axis = this; + var brokenAxis = axis.brokenAxis; + if (brokenAxis && + brokenAxis.hasBreaks) { + var tickPositions = this.tickPositions, info = this.tickPositions.info, newPositions = [], i; + for (i = 0; i < tickPositions.length; i++) { + if (!brokenAxis.isInAnyBreak(tickPositions[i])) { + newPositions.push(tickPositions[i]); + } + } + this.tickPositions = newPositions; + this.tickPositions.info = info; + } + }); + // Force Axis to be not-ordinal when breaks are defined + addEvent(AxisClass, 'afterSetOptions', function () { + if (this.brokenAxis && this.brokenAxis.hasBreaks) { + this.options.ordinal = false; + } + }); + addEvent(SeriesClass, 'afterGeneratePoints', function () { + var _a = this, isDirty = _a.isDirty, connectNulls = _a.options.connectNulls, points = _a.points, xAxis = _a.xAxis, yAxis = _a.yAxis; + // Set, or reset visibility of the points. Axis.setBreaks marks the + // series as isDirty + if (isDirty) { + var i = points.length; + while (i--) { + var point = points[i]; + // Respect nulls inside the break (#4275) + var nullGap = point.y === null && connectNulls === false; + var isPointInBreak = (!nullGap && ((xAxis && + xAxis.brokenAxis && + xAxis.brokenAxis.isInAnyBreak(point.x, true)) || (yAxis && + yAxis.brokenAxis && + yAxis.brokenAxis.isInAnyBreak(point.y, true)))); + // Set point.visible if in any break. + // If not in break, reset visible to original value. + point.visible = isPointInBreak ? + false : + point.options.visible !== false; + } + } + }); + addEvent(SeriesClass, 'afterRender', function drawPointsWrapped() { + this.drawBreaks(this.xAxis, ['x']); + this.drawBreaks(this.yAxis, pick(this.pointArrayMap, ['y'])); + }); + }; + return BrokenAxis; + }()); + BrokenAxis.compose(Axis, Series); // @todo remove automatism + + return BrokenAxis; + }); + _registerModule(_modules, 'parts-gantt/TreeGridAxis.js', [_modules['parts/Axis.js'], _modules['parts/Tick.js'], _modules['parts-gantt/Tree.js'], _modules['parts-gantt/TreeGridTick.js'], _modules['mixins/tree-series.js'], _modules['parts/Utilities.js']], function (Axis, Tick, Tree, TreeGridTick, TreeSeriesMixin, U) { + /* * + * + * (c) 2016 Highsoft AS + * Authors: Jon Arild Nygard + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, find = U.find, fireEvent = U.fireEvent, isNumber = U.isNumber, isObject = U.isObject, isString = U.isString, merge = U.merge, pick = U.pick, wrap = U.wrap; + /** + * @private + */ + var TreeGridAxis; + (function (TreeGridAxis) { + /* * + * + * Interfaces + * + * */ + /* * + * + * Variables + * + * */ + var applied = false; + /* * + * + * Functions + * + * */ + /** + * @private + */ + function compose(AxisClass) { + if (!applied) { + wrap(AxisClass.prototype, 'generateTick', wrapGenerateTick); + wrap(AxisClass.prototype, 'getMaxLabelDimensions', wrapGetMaxLabelDimensions); + wrap(AxisClass.prototype, 'init', wrapInit); + wrap(AxisClass.prototype, 'setTickInterval', wrapSetTickInterval); + TreeGridTick.compose(Tick); + applied = true; + } + } + TreeGridAxis.compose = compose; + /** + * @private + */ + function getBreakFromNode(node, max) { + var from = node.collapseStart || 0, to = node.collapseEnd || 0; + // In broken-axis, the axis.max is minimized until it is not within a + // break. Therefore, if break.to is larger than axis.max, the axis.to + // should not add the 0.5 axis.tickMarkOffset, to avoid adding a break + // larger than axis.max. + // TODO consider simplifying broken-axis and this might solve itself + if (to >= max) { + from -= 0.5; + } + return { + from: from, + to: to, + showPoints: false + }; + } + /** + * Creates a tree structure of the data, and the treegrid. Calculates + * categories, and y-values of points based on the tree. + * + * @private + * @function getTreeGridFromData + * + * @param {Array} data + * All the data points to display in the axis. + * + * @param {boolean} uniqueNames + * Wether or not the data node with the same name should share grid cell. If + * true they do share cell. False by default. + * + * @param {number} numberOfSeries + * + * @return {object} + * Returns an object containing categories, mapOfIdToNode, + * mapOfPosToGridNode, and tree. + * + * @todo There should be only one point per line. + * @todo It should be optional to have one category per point, or merge + * cells + * @todo Add unit-tests. + */ + function getTreeGridFromData(data, uniqueNames, numberOfSeries) { + var categories = [], collapsedNodes = [], mapOfIdToNode = {}, mapOfPosToGridNode = {}, posIterator = -1, uniqueNamesEnabled = typeof uniqueNames === 'boolean' ? uniqueNames : false, tree; + // Build the tree from the series data. + var treeParams = { + // After the children has been created. + after: function (node) { + var gridNode = mapOfPosToGridNode[node.pos], height = 0, descendants = 0; + gridNode.children.forEach(function (child) { + descendants += (child.descendants || 0) + 1; + height = Math.max((child.height || 0) + 1, height); + }); + gridNode.descendants = descendants; + gridNode.height = height; + if (gridNode.collapsed) { + collapsedNodes.push(gridNode); + } + }, + // Before the children has been created. + before: function (node) { + var data = isObject(node.data, true) ? node.data : {}, name = isString(data.name) ? data.name : '', parentNode = mapOfIdToNode[node.parent], parentGridNode = (isObject(parentNode, true) ? + mapOfPosToGridNode[parentNode.pos] : + null), hasSameName = function (x) { + return x.name === name; + }, gridNode, pos; + // If not unique names, look for sibling node with the same name + if (uniqueNamesEnabled && + isObject(parentGridNode, true) && + !!(gridNode = find(parentGridNode.children, hasSameName))) { + // If there is a gridNode with the same name, reuse position + pos = gridNode.pos; + // Add data node to list of nodes in the grid node. + gridNode.nodes.push(node); + } + else { + // If it is a new grid node, increment position. + pos = posIterator++; + } + // Add new grid node to map. + if (!mapOfPosToGridNode[pos]) { + mapOfPosToGridNode[pos] = gridNode = { + depth: parentGridNode ? parentGridNode.depth + 1 : 0, + name: name, + nodes: [node], + children: [], + pos: pos + }; + // If not root, then add name to categories. + if (pos !== -1) { + categories.push(name); + } + // Add name to list of children. + if (isObject(parentGridNode, true)) { + parentGridNode.children.push(gridNode); + } + } + // Add data node to map + if (isString(node.id)) { + mapOfIdToNode[node.id] = node; + } + // If one of the points are collapsed, then start the grid node + // in collapsed state. + if (gridNode && + data.collapsed === true) { + gridNode.collapsed = true; + } + // Assign pos to data node + node.pos = pos; + } + }; + var updateYValuesAndTickPos = function (map, numberOfSeries) { + var setValues = function (gridNode, start, result) { + var nodes = gridNode.nodes, end = start + (start === -1 ? 0 : numberOfSeries - 1), diff = (end - start) / 2, padding = 0.5, pos = start + diff; + nodes.forEach(function (node) { + var data = node.data; + if (isObject(data, true)) { + // Update point + data.y = start + (data.seriesIndex || 0); + // Remove the property once used + delete data.seriesIndex; + } + node.pos = pos; + }); + result[pos] = gridNode; + gridNode.pos = pos; + gridNode.tickmarkOffset = diff + padding; + gridNode.collapseStart = end + padding; + gridNode.children.forEach(function (child) { + setValues(child, end + 1, result); + end = (child.collapseEnd || 0) - padding; + }); + // Set collapseEnd to the end of the last child node. + gridNode.collapseEnd = end + padding; + return result; + }; + return setValues(map['-1'], -1, {}); + }; + // Create tree from data + tree = Tree.getTree(data, treeParams); + // Update y values of data, and set calculate tick positions. + mapOfPosToGridNode = updateYValuesAndTickPos(mapOfPosToGridNode, numberOfSeries); + // Return the resulting data. + return { + categories: categories, + mapOfIdToNode: mapOfIdToNode, + mapOfPosToGridNode: mapOfPosToGridNode, + collapsedNodes: collapsedNodes, + tree: tree + }; + } + /** + * Builds the tree of categories and calculates its positions. + * @private + * @param {object} e Event object + * @param {object} e.target The chart instance which the event was fired on. + * @param {object[]} e.target.axes The axes of the chart. + */ + function onBeforeRender(e) { + var chart = e.target, axes = chart.axes; + axes.filter(function (axis) { + return axis.options.type === 'treegrid'; + }).forEach(function (axis) { + var options = axis.options || {}, labelOptions = options.labels, uniqueNames = options.uniqueNames, numberOfSeries = 0, isDirty, data, treeGrid; + // Check whether any of series is rendering for the first time, + // visibility has changed, or its data is dirty, + // and only then update. #10570, #10580 + // Also check if mapOfPosToGridNode exists. #10887 + isDirty = (!axis.treeGrid.mapOfPosToGridNode || + axis.series.some(function (series) { + return !series.hasRendered || + series.isDirtyData || + series.isDirty; + })); + if (isDirty) { + // Concatenate data from all series assigned to this axis. + data = axis.series.reduce(function (arr, s) { + if (s.visible) { + // Push all data to array + (s.options.data || []).forEach(function (data) { + if (isObject(data, true)) { + // Set series index on data. Removed again + // after use. + data.seriesIndex = numberOfSeries; + arr.push(data); + } + }); + // Increment series index + if (uniqueNames === true) { + numberOfSeries++; + } + } + return arr; + }, []); + // setScale is fired after all the series is initialized, + // which is an ideal time to update the axis.categories. + treeGrid = getTreeGridFromData(data, uniqueNames || false, (uniqueNames === true) ? numberOfSeries : 1); + // Assign values to the axis. + axis.categories = treeGrid.categories; + axis.treeGrid.mapOfPosToGridNode = treeGrid.mapOfPosToGridNode; + axis.hasNames = true; + axis.treeGrid.tree = treeGrid.tree; + // Update yData now that we have calculated the y values + axis.series.forEach(function (series) { + var data = (series.options.data || []).map(function (d) { + return isObject(d, true) ? merge(d) : d; + }); + // Avoid destroying points when series is not visible + if (series.visible) { + series.setData(data, false); + } + }); + // Calculate the label options for each level in the tree. + axis.treeGrid.mapOptionsToLevel = + TreeSeriesMixin.getLevelOptions({ + defaults: labelOptions, + from: 1, + levels: labelOptions && labelOptions.levels, + to: axis.treeGrid.tree && axis.treeGrid.tree.height + }); + // Setting initial collapsed nodes + if (e.type === 'beforeRender') { + axis.treeGrid.collapsedNodes = treeGrid.collapsedNodes; + } + } + }); + } + /** + * Generates a tick for initial positioning. + * + * @private + * @function Highcharts.GridAxis#generateTick + * + * @param {Function} proceed + * The original generateTick function. + * + * @param {number} pos + * The tick position in axis values. + */ + function wrapGenerateTick(proceed, pos) { + var axis = this, mapOptionsToLevel = axis.treeGrid.mapOptionsToLevel || {}, isTreeGrid = axis.options.type === 'treegrid', ticks = axis.ticks; + var tick = ticks[pos], levelOptions, options, gridNode; + if (isTreeGrid && + axis.treeGrid.mapOfPosToGridNode) { + gridNode = axis.treeGrid.mapOfPosToGridNode[pos]; + levelOptions = mapOptionsToLevel[gridNode.depth]; + if (levelOptions) { + options = { + labels: levelOptions + }; + } + if (!tick) { + ticks[pos] = tick = + new Tick(axis, pos, void 0, void 0, { + category: gridNode.name, + tickmarkOffset: gridNode.tickmarkOffset, + options: options + }); + } + else { + // update labels depending on tick interval + tick.parameters.category = gridNode.name; + tick.options = options; + tick.addLabel(); + } + } + else { + proceed.apply(axis, Array.prototype.slice.call(arguments, 1)); + } + } + /** + * Override to add indentation to axis.maxLabelDimensions. + * + * @private + * @function Highcharts.GridAxis#getMaxLabelDimensions + * + * @param {Function} proceed + * The original function + */ + function wrapGetMaxLabelDimensions(proceed) { + var axis = this, options = axis.options, labelOptions = options && options.labels, indentation = (labelOptions && isNumber(labelOptions.indentation) ? + labelOptions.indentation : + 0), retVal = proceed.apply(axis, Array.prototype.slice.call(arguments, 1)), isTreeGrid = axis.options.type === 'treegrid'; + var treeDepth; + if (isTreeGrid && axis.treeGrid.mapOfPosToGridNode) { + treeDepth = axis.treeGrid.mapOfPosToGridNode[-1].height || 0; + retVal.width += indentation * (treeDepth - 1); + } + return retVal; + } + /** + * @private + */ + function wrapInit(proceed, chart, userOptions) { + var axis = this, isTreeGrid = userOptions.type === 'treegrid'; + if (!axis.treeGrid) { + axis.treeGrid = new Additions(axis); + } + // Set default and forced options for TreeGrid + if (isTreeGrid) { + // Add event for updating the categories of a treegrid. + // NOTE Preferably these events should be set on the axis. + addEvent(chart, 'beforeRender', onBeforeRender); + addEvent(chart, 'beforeRedraw', onBeforeRender); + // Add new collapsed nodes on addseries + addEvent(chart, 'addSeries', function (e) { + if (e.options.data) { + var treeGrid = getTreeGridFromData(e.options.data, userOptions.uniqueNames || false, 1); + axis.treeGrid.collapsedNodes = (axis.treeGrid.collapsedNodes || []).concat(treeGrid.collapsedNodes); + } + }); + // Collapse all nodes in axis.treegrid.collapsednodes + // where collapsed equals true. + addEvent(axis, 'foundExtremes', function () { + if (axis.treeGrid.collapsedNodes) { + axis.treeGrid.collapsedNodes.forEach(function (node) { + var breaks = axis.treeGrid.collapse(node); + if (axis.brokenAxis) { + axis.brokenAxis.setBreaks(breaks, false); + // remove the node from the axis collapsedNodes + if (axis.treeGrid.collapsedNodes) { + axis.treeGrid.collapsedNodes = axis.treeGrid.collapsedNodes.filter(function (n) { + return node.collapseStart !== n.collapseStart || + node.collapseEnd !== n.collapseEnd; + }); + } + } + }); + } + }); + userOptions = merge({ + // Default options + grid: { + enabled: true + }, + // TODO: add support for align in treegrid. + labels: { + align: 'left', + /** + * Set options on specific levels in a tree grid axis. Takes + * precedence over labels options. + * + * @sample {gantt} gantt/treegrid-axis/labels-levels + * Levels on TreeGrid Labels + * + * @type {Array<*>} + * @product gantt + * @apioption yAxis.labels.levels + * + * @private + */ + levels: [{ + /** + * Specify the level which the options within this object + * applies to. + * + * @type {number} + * @product gantt + * @apioption yAxis.labels.levels.level + * + * @private + */ + level: void 0 + }, { + level: 1, + /** + * @type {Highcharts.CSSObject} + * @product gantt + * @apioption yAxis.labels.levels.style + * + * @private + */ + style: { + /** @ignore-option */ + fontWeight: 'bold' + } + }], + /** + * The symbol for the collapse and expand icon in a + * treegrid. + * + * @product gantt + * @optionparent yAxis.labels.symbol + * + * @private + */ + symbol: { + /** + * The symbol type. Points to a definition function in + * the `Highcharts.Renderer.symbols` collection. + * + * @type {Highcharts.SymbolKeyValue} + * + * @private + */ + type: 'triangle', + x: -5, + y: -5, + height: 10, + width: 10, + padding: 5 + } + }, + uniqueNames: false + }, userOptions, { + // Forced options + reversed: true, + // grid.columns is not supported in treegrid + grid: { + columns: void 0 + } + }); + } + // Now apply the original function with the original arguments, + // which are sliced off this function's arguments + proceed.apply(axis, [chart, userOptions]); + if (isTreeGrid) { + axis.hasNames = true; + axis.options.showLastLabel = true; + } + } + /** + * Set the tick positions, tickInterval, axis min and max. + * + * @private + * @function Highcharts.GridAxis#setTickInterval + * + * @param {Function} proceed + * The original setTickInterval function. + */ + function wrapSetTickInterval(proceed) { + var axis = this, options = axis.options, isTreeGrid = options.type === 'treegrid'; + if (isTreeGrid) { + axis.min = pick(axis.userMin, options.min, axis.dataMin); + axis.max = pick(axis.userMax, options.max, axis.dataMax); + fireEvent(axis, 'foundExtremes'); + // setAxisTranslation modifies the min and max according to + // axis breaks. + axis.setAxisTranslation(true); + axis.tickmarkOffset = 0.5; + axis.tickInterval = 1; + axis.tickPositions = axis.treeGrid.mapOfPosToGridNode ? + axis.treeGrid.getTickPositions() : + []; + } + else { + proceed.apply(axis, Array.prototype.slice.call(arguments, 1)); + } + } + /* * + * + * Classes + * + * */ + /** + * @private + * @class + */ + var Additions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + /** + * @private + */ + function Additions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Calculates the new axis breaks to collapse a node. + * + * @private + * + * @param {Highcharts.Axis} axis + * The axis to check against. + * + * @param {Highcharts.GridNode} node + * The node to collapse. + * + * @param {number} pos + * The tick position to collapse. + * + * @return {Array} + * Returns an array of the new breaks for the axis. + */ + Additions.prototype.collapse = function (node) { + var axis = this.axis, breaks = (axis.options.breaks || []), obj = getBreakFromNode(node, axis.max); + breaks.push(obj); + return breaks; + }; + /** + * Calculates the new axis breaks to expand a node. + * + * @private + * + * @param {Highcharts.Axis} axis + * The axis to check against. + * + * @param {Highcharts.GridNode} node + * The node to expand. + * + * @param {number} pos + * The tick position to expand. + * + * @return {Array} + * Returns an array of the new breaks for the axis. + */ + Additions.prototype.expand = function (node) { + var axis = this.axis, breaks = (axis.options.breaks || []), obj = getBreakFromNode(node, axis.max); + // Remove the break from the axis breaks array. + return breaks.reduce(function (arr, b) { + if (b.to !== obj.to || b.from !== obj.from) { + arr.push(b); + } + return arr; + }, []); + }; + /** + * Creates a list of positions for the ticks on the axis. Filters out + * positions that are outside min and max, or is inside an axis break. + * + * @private + * + * @return {Array} + * List of positions. + */ + Additions.prototype.getTickPositions = function () { + var axis = this.axis; + return Object.keys(axis.treeGrid.mapOfPosToGridNode || {}).reduce(function (arr, key) { + var pos = +key; + if (axis.min <= pos && + axis.max >= pos && + !(axis.brokenAxis && axis.brokenAxis.isInAnyBreak(pos))) { + arr.push(pos); + } + return arr; + }, []); + }; + /** + * Check if a node is collapsed. + * + * @private + * + * @param {Highcharts.Axis} axis + * The axis to check against. + * + * @param {object} node + * The node to check if is collapsed. + * + * @param {number} pos + * The tick position to collapse. + * + * @return {boolean} + * Returns true if collapsed, false if expanded. + */ + Additions.prototype.isCollapsed = function (node) { + var axis = this.axis, breaks = (axis.options.breaks || []), obj = getBreakFromNode(node, axis.max); + return breaks.some(function (b) { + return b.from === obj.from && b.to === obj.to; + }); + }; + /** + * Calculates the new axis breaks after toggling the collapse/expand + * state of a node. If it is collapsed it will be expanded, and if it is + * exapended it will be collapsed. + * + * @private + * + * @param {Highcharts.Axis} axis + * The axis to check against. + * + * @param {Highcharts.GridNode} node + * The node to toggle. + * + * @return {Array} + * Returns an array of the new breaks for the axis. + */ + Additions.prototype.toggleCollapse = function (node) { + return (this.isCollapsed(node) ? + this.expand(node) : + this.collapse(node)); + }; + return Additions; + }()); + TreeGridAxis.Additions = Additions; + })(TreeGridAxis || (TreeGridAxis = {})); + // Make utility functions available for testing. + Axis.prototype.utils = { + getNode: Tree.getNode + }; + TreeGridAxis.compose(Axis); + + return TreeGridAxis; + }); + _registerModule(_modules, 'parts-gantt/PathfinderAlgorithms.js', [_modules['parts/Utilities.js']], function (U) { + /* * + * + * (c) 2016 Highsoft AS + * Author: Øystein Moseng + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend, pick = U.pick; + var min = Math.min, max = Math.max, abs = Math.abs; + /** + * Get index of last obstacle before xMin. Employs a type of binary search, and + * thus requires that obstacles are sorted by xMin value. + * + * @private + * @function findLastObstacleBefore + * + * @param {Array} obstacles + * Array of obstacles to search in. + * + * @param {number} xMin + * The xMin threshold. + * + * @param {number} [startIx] + * Starting index to search from. Must be within array range. + * + * @return {number} + * The index of the last obstacle element before xMin. + */ + function findLastObstacleBefore(obstacles, xMin, startIx) { + var left = startIx || 0, // left limit + right = obstacles.length - 1, // right limit + min = xMin - 0.0000001, // Make sure we include all obstacles at xMin + cursor, cmp; + while (left <= right) { + cursor = (right + left) >> 1; + cmp = min - obstacles[cursor].xMin; + if (cmp > 0) { + left = cursor + 1; + } + else if (cmp < 0) { + right = cursor - 1; + } + else { + return cursor; + } + } + return left > 0 ? left - 1 : 0; + } + /** + * Test if a point lays within an obstacle. + * + * @private + * @function pointWithinObstacle + * + * @param {object} obstacle + * Obstacle to test. + * + * @param {Highcharts.Point} point + * Point with x/y props. + * + * @return {boolean} + * Whether point is within the obstacle or not. + */ + function pointWithinObstacle(obstacle, point) { + return (point.x <= obstacle.xMax && + point.x >= obstacle.xMin && + point.y <= obstacle.yMax && + point.y >= obstacle.yMin); + } + /** + * Find the index of an obstacle that wraps around a point. + * Returns -1 if not found. + * + * @private + * @function findObstacleFromPoint + * + * @param {Array} obstacles + * Obstacles to test. + * + * @param {Highcharts.Point} point + * Point with x/y props. + * + * @return {number} + * Ix of the obstacle in the array, or -1 if not found. + */ + function findObstacleFromPoint(obstacles, point) { + var i = findLastObstacleBefore(obstacles, point.x + 1) + 1; + while (i--) { + if (obstacles[i].xMax >= point.x && + // optimization using lazy evaluation + pointWithinObstacle(obstacles[i], point)) { + return i; + } + } + return -1; + } + /** + * Get SVG path array from array of line segments. + * + * @private + * @function pathFromSegments + * + * @param {Array} segments + * The segments to build the path from. + * + * @return {Highcharts.SVGPathArray} + * SVG path array as accepted by the SVG Renderer. + */ + function pathFromSegments(segments) { + var path = []; + if (segments.length) { + path.push(['M', segments[0].start.x, segments[0].start.y]); + for (var i = 0; i < segments.length; ++i) { + path.push(['L', segments[i].end.x, segments[i].end.y]); + } + } + return path; + } + /** + * Limits obstacle max/mins in all directions to bounds. Modifies input + * obstacle. + * + * @private + * @function limitObstacleToBounds + * + * @param {object} obstacle + * Obstacle to limit. + * + * @param {object} bounds + * Bounds to use as limit. + * + * @return {void} + */ + function limitObstacleToBounds(obstacle, bounds) { + obstacle.yMin = max(obstacle.yMin, bounds.yMin); + obstacle.yMax = min(obstacle.yMax, bounds.yMax); + obstacle.xMin = max(obstacle.xMin, bounds.xMin); + obstacle.xMax = min(obstacle.xMax, bounds.xMax); + } + // Define the available pathfinding algorithms. + // Algorithms take up to 3 arguments: starting point, ending point, and an + // options object. + var algorithms = { + /** + * Get an SVG path from a starting coordinate to an ending coordinate. + * Draws a straight line. + * + * @function Highcharts.Pathfinder.algorithms.straight + * + * @param {Highcharts.PositionObject} start + * Starting coordinate, object with x/y props. + * + * @param {Highcharts.PositionObject} end + * Ending coordinate, object with x/y props. + * + * @return {object} + * An object with the SVG path in Array form as accepted by the SVG + * renderer, as well as an array of new obstacles making up this + * path. + */ + straight: function (start, end) { + return { + path: [ + ['M', start.x, start.y], + ['L', end.x, end.y] + ], + obstacles: [{ start: start, end: end }] + }; + }, + /** + * Find a path from a starting coordinate to an ending coordinate, using + * right angles only, and taking only starting/ending obstacle into + * consideration. + * + * @function Highcharts.Pathfinder.algorithms.simpleConnect + * + * @param {Highcharts.PositionObject} start + * Starting coordinate, object with x/y props. + * + * @param {Highcharts.PositionObject} end + * Ending coordinate, object with x/y props. + * + * @param {object} options + * Options for the algorithm: + * - chartObstacles: Array of chart obstacles to avoid + * - startDirectionX: Optional. True if starting in the X direction. + * If not provided, the algorithm starts in the direction that is + * the furthest between start/end. + * + * @return {object} + * An object with the SVG path in Array form as accepted by the SVG + * renderer, as well as an array of new obstacles making up this + * path. + */ + simpleConnect: extend(function (start, end, options) { + var segments = [], endSegment, dir = pick(options.startDirectionX, abs(end.x - start.x) > abs(end.y - start.y)) ? 'x' : 'y', chartObstacles = options.chartObstacles, startObstacleIx = findObstacleFromPoint(chartObstacles, start), endObstacleIx = findObstacleFromPoint(chartObstacles, end), startObstacle, endObstacle, prevWaypoint, waypoint, waypoint2, useMax, endPoint; + // eslint-disable-next-line valid-jsdoc + /** + * Return a clone of a point with a property set from a target object, + * optionally with an offset + * @private + */ + function copyFromPoint(from, fromKey, to, toKey, offset) { + var point = { + x: from.x, + y: from.y + }; + point[fromKey] = to[toKey || fromKey] + (offset || 0); + return point; + } + // eslint-disable-next-line valid-jsdoc + /** + * Return waypoint outside obstacle. + * @private + */ + function getMeOut(obstacle, point, direction) { + var useMax = abs(point[direction] - obstacle[direction + 'Min']) > + abs(point[direction] - obstacle[direction + 'Max']); + return copyFromPoint(point, direction, obstacle, direction + (useMax ? 'Max' : 'Min'), useMax ? 1 : -1); + } + // Pull out end point + if (endObstacleIx > -1) { + endObstacle = chartObstacles[endObstacleIx]; + waypoint = getMeOut(endObstacle, end, dir); + endSegment = { + start: waypoint, + end: end + }; + endPoint = waypoint; + } + else { + endPoint = end; + } + // If an obstacle envelops the start point, add a segment to get out, + // and around it. + if (startObstacleIx > -1) { + startObstacle = chartObstacles[startObstacleIx]; + waypoint = getMeOut(startObstacle, start, dir); + segments.push({ + start: start, + end: waypoint + }); + // If we are going back again, switch direction to get around start + // obstacle. + if ( + // Going towards max from start: + waypoint[dir] >= start[dir] === + // Going towards min to end: + waypoint[dir] >= endPoint[dir]) { + dir = dir === 'y' ? 'x' : 'y'; + useMax = start[dir] < end[dir]; + segments.push({ + start: waypoint, + end: copyFromPoint(waypoint, dir, startObstacle, dir + (useMax ? 'Max' : 'Min'), useMax ? 1 : -1) + }); + // Switch direction again + dir = dir === 'y' ? 'x' : 'y'; + } + } + // We are around the start obstacle. Go towards the end in one + // direction. + prevWaypoint = segments.length ? + segments[segments.length - 1].end : + start; + waypoint = copyFromPoint(prevWaypoint, dir, endPoint); + segments.push({ + start: prevWaypoint, + end: waypoint + }); + // Final run to end point in the other direction + dir = dir === 'y' ? 'x' : 'y'; + waypoint2 = copyFromPoint(waypoint, dir, endPoint); + segments.push({ + start: waypoint, + end: waypoint2 + }); + // Finally add the endSegment + segments.push(endSegment); + return { + path: pathFromSegments(segments), + obstacles: segments + }; + }, { + requiresObstacles: true + }), + /** + * Find a path from a starting coordinate to an ending coordinate, taking + * obstacles into consideration. Might not always find the optimal path, + * but is fast, and usually good enough. + * + * @function Highcharts.Pathfinder.algorithms.fastAvoid + * + * @param {Highcharts.PositionObject} start + * Starting coordinate, object with x/y props. + * + * @param {Highcharts.PositionObject} end + * Ending coordinate, object with x/y props. + * + * @param {object} options + * Options for the algorithm. + * - chartObstacles: Array of chart obstacles to avoid + * - lineObstacles: Array of line obstacles to jump over + * - obstacleMetrics: Object with metrics of chartObstacles cached + * - hardBounds: Hard boundaries to not cross + * - obstacleOptions: Options for the obstacles, including margin + * - startDirectionX: Optional. True if starting in the X direction. + * If not provided, the algorithm starts in the + * direction that is the furthest between + * start/end. + * + * @return {object} + * An object with the SVG path in Array form as accepted by the SVG + * renderer, as well as an array of new obstacles making up this + * path. + */ + fastAvoid: extend(function (start, end, options) { + /* + Algorithm rules/description + - Find initial direction + - Determine soft/hard max for each direction. + - Move along initial direction until obstacle. + - Change direction. + - If hitting obstacle, first try to change length of previous line + before changing direction again. + + Soft min/max x = start/destination x +/- widest obstacle + margin + Soft min/max y = start/destination y +/- tallest obstacle + margin + + @todo: + - Make retrospective, try changing prev segment to reduce + corners + - Fix logic for breaking out of end-points - not always picking + the best direction currently + - When going around the end obstacle we should not always go the + shortest route, rather pick the one closer to the end point + */ + var dirIsX = pick(options.startDirectionX, abs(end.x - start.x) > abs(end.y - start.y)), dir = dirIsX ? 'x' : 'y', segments, useMax, extractedEndPoint, endSegments = [], forceObstacleBreak = false, // Used in clearPathTo to keep track of + // when to force break through an obstacle. + // Boundaries to stay within. If beyond soft boundary, prefer to + // change direction ASAP. If at hard max, always change immediately. + metrics = options.obstacleMetrics, softMinX = min(start.x, end.x) - metrics.maxWidth - 10, softMaxX = max(start.x, end.x) + metrics.maxWidth + 10, softMinY = min(start.y, end.y) - metrics.maxHeight - 10, softMaxY = max(start.y, end.y) + metrics.maxHeight + 10, + // Obstacles + chartObstacles = options.chartObstacles, startObstacleIx = findLastObstacleBefore(chartObstacles, softMinX), endObstacleIx = findLastObstacleBefore(chartObstacles, softMaxX); + // eslint-disable-next-line valid-jsdoc + /** + * How far can you go between two points before hitting an obstacle? + * Does not work for diagonal lines (because it doesn't have to). + * @private + */ + function pivotPoint(fromPoint, toPoint, directionIsX) { + var firstPoint, lastPoint, highestPoint, lowestPoint, i, searchDirection = fromPoint.x < toPoint.x ? 1 : -1; + if (fromPoint.x < toPoint.x) { + firstPoint = fromPoint; + lastPoint = toPoint; + } + else { + firstPoint = toPoint; + lastPoint = fromPoint; + } + if (fromPoint.y < toPoint.y) { + lowestPoint = fromPoint; + highestPoint = toPoint; + } + else { + lowestPoint = toPoint; + highestPoint = fromPoint; + } + // Go through obstacle range in reverse if toPoint is before + // fromPoint in the X-dimension. + i = searchDirection < 0 ? + // Searching backwards, start at last obstacle before last point + min(findLastObstacleBefore(chartObstacles, lastPoint.x), chartObstacles.length - 1) : + // Forwards. Since we're not sorted by xMax, we have to look + // at all obstacles. + 0; + // Go through obstacles in this X range + while (chartObstacles[i] && (searchDirection > 0 && chartObstacles[i].xMin <= lastPoint.x || + searchDirection < 0 && chartObstacles[i].xMax >= firstPoint.x)) { + // If this obstacle is between from and to points in a straight + // line, pivot at the intersection. + if (chartObstacles[i].xMin <= lastPoint.x && + chartObstacles[i].xMax >= firstPoint.x && + chartObstacles[i].yMin <= highestPoint.y && + chartObstacles[i].yMax >= lowestPoint.y) { + if (directionIsX) { + return { + y: fromPoint.y, + x: fromPoint.x < toPoint.x ? + chartObstacles[i].xMin - 1 : + chartObstacles[i].xMax + 1, + obstacle: chartObstacles[i] + }; + } + // else ... + return { + x: fromPoint.x, + y: fromPoint.y < toPoint.y ? + chartObstacles[i].yMin - 1 : + chartObstacles[i].yMax + 1, + obstacle: chartObstacles[i] + }; + } + i += searchDirection; + } + return toPoint; + } + /** + * Decide in which direction to dodge or get out of an obstacle. + * Considers desired direction, which way is shortest, soft and hard + * bounds. + * + * (? Returns a string, either xMin, xMax, yMin or yMax.) + * + * @private + * @function + * + * @param {object} obstacle + * Obstacle to dodge/escape. + * + * @param {object} fromPoint + * Point with x/y props that's dodging/escaping. + * + * @param {object} toPoint + * Goal point. + * + * @param {boolean} dirIsX + * Dodge in X dimension. + * + * @param {object} bounds + * Hard and soft boundaries. + * + * @return {boolean} + * Use max or not. + */ + function getDodgeDirection(obstacle, fromPoint, toPoint, dirIsX, bounds) { + var softBounds = bounds.soft, hardBounds = bounds.hard, dir = dirIsX ? 'x' : 'y', toPointMax = { x: fromPoint.x, y: fromPoint.y }, toPointMin = { x: fromPoint.x, y: fromPoint.y }, minPivot, maxPivot, maxOutOfSoftBounds = obstacle[dir + 'Max'] >= + softBounds[dir + 'Max'], minOutOfSoftBounds = obstacle[dir + 'Min'] <= + softBounds[dir + 'Min'], maxOutOfHardBounds = obstacle[dir + 'Max'] >= + hardBounds[dir + 'Max'], minOutOfHardBounds = obstacle[dir + 'Min'] <= + hardBounds[dir + 'Min'], + // Find out if we should prefer one direction over the other if + // we can choose freely + minDistance = abs(obstacle[dir + 'Min'] - fromPoint[dir]), maxDistance = abs(obstacle[dir + 'Max'] - fromPoint[dir]), + // If it's a small difference, pick the one leading towards dest + // point. Otherwise pick the shortest distance + useMax = abs(minDistance - maxDistance) < 10 ? + fromPoint[dir] < toPoint[dir] : + maxDistance < minDistance; + // Check if we hit any obstacles trying to go around in either + // direction. + toPointMin[dir] = obstacle[dir + 'Min']; + toPointMax[dir] = obstacle[dir + 'Max']; + minPivot = pivotPoint(fromPoint, toPointMin, dirIsX)[dir] !== + toPointMin[dir]; + maxPivot = pivotPoint(fromPoint, toPointMax, dirIsX)[dir] !== + toPointMax[dir]; + useMax = minPivot ? + (maxPivot ? useMax : true) : + (maxPivot ? false : useMax); + // useMax now contains our preferred choice, bounds not taken into + // account. If both or neither direction is out of bounds we want to + // use this. + // Deal with soft bounds + useMax = minOutOfSoftBounds ? + (maxOutOfSoftBounds ? useMax : true) : // Out on min + (maxOutOfSoftBounds ? false : useMax); // Not out on min + // Deal with hard bounds + useMax = minOutOfHardBounds ? + (maxOutOfHardBounds ? useMax : true) : // Out on min + (maxOutOfHardBounds ? false : useMax); // Not out on min + return useMax; + } + // eslint-disable-next-line valid-jsdoc + /** + * Find a clear path between point. + * @private + */ + function clearPathTo(fromPoint, toPoint, dirIsX) { + // Don't waste time if we've hit goal + if (fromPoint.x === toPoint.x && fromPoint.y === toPoint.y) { + return []; + } + var dir = dirIsX ? 'x' : 'y', pivot, segments, waypoint, waypointUseMax, envelopingObstacle, secondEnvelopingObstacle, envelopWaypoint, obstacleMargin = options.obstacleOptions.margin, bounds = { + soft: { + xMin: softMinX, + xMax: softMaxX, + yMin: softMinY, + yMax: softMaxY + }, + hard: options.hardBounds + }; + // If fromPoint is inside an obstacle we have a problem. Break out + // by just going to the outside of this obstacle. We prefer to go to + // the nearest edge in the chosen direction. + envelopingObstacle = + findObstacleFromPoint(chartObstacles, fromPoint); + if (envelopingObstacle > -1) { + envelopingObstacle = chartObstacles[envelopingObstacle]; + waypointUseMax = getDodgeDirection(envelopingObstacle, fromPoint, toPoint, dirIsX, bounds); + // Cut obstacle to hard bounds to make sure we stay within + limitObstacleToBounds(envelopingObstacle, options.hardBounds); + envelopWaypoint = dirIsX ? { + y: fromPoint.y, + x: envelopingObstacle[waypointUseMax ? 'xMax' : 'xMin'] + + (waypointUseMax ? 1 : -1) + } : { + x: fromPoint.x, + y: envelopingObstacle[waypointUseMax ? 'yMax' : 'yMin'] + + (waypointUseMax ? 1 : -1) + }; + // If we crashed into another obstacle doing this, we put the + // waypoint between them instead + secondEnvelopingObstacle = findObstacleFromPoint(chartObstacles, envelopWaypoint); + if (secondEnvelopingObstacle > -1) { + secondEnvelopingObstacle = chartObstacles[secondEnvelopingObstacle]; + // Cut obstacle to hard bounds + limitObstacleToBounds(secondEnvelopingObstacle, options.hardBounds); + // Modify waypoint to lay between obstacles + envelopWaypoint[dir] = waypointUseMax ? max(envelopingObstacle[dir + 'Max'] - obstacleMargin + 1, (secondEnvelopingObstacle[dir + 'Min'] + + envelopingObstacle[dir + 'Max']) / 2) : + min((envelopingObstacle[dir + 'Min'] + obstacleMargin - 1), ((secondEnvelopingObstacle[dir + 'Max'] + + envelopingObstacle[dir + 'Min']) / 2)); + // We are not going anywhere. If this happens for the first + // time, do nothing. Otherwise, try to go to the extreme of + // the obstacle pair in the current direction. + if (fromPoint.x === envelopWaypoint.x && + fromPoint.y === envelopWaypoint.y) { + if (forceObstacleBreak) { + envelopWaypoint[dir] = waypointUseMax ? + max(envelopingObstacle[dir + 'Max'], secondEnvelopingObstacle[dir + 'Max']) + 1 : + min(envelopingObstacle[dir + 'Min'], secondEnvelopingObstacle[dir + 'Min']) - 1; + } + // Toggle on if off, and the opposite + forceObstacleBreak = !forceObstacleBreak; + } + else { + // This point is not identical to previous. + // Clear break trigger. + forceObstacleBreak = false; + } + } + segments = [{ + start: fromPoint, + end: envelopWaypoint + }]; + } + else { // If not enveloping, use standard pivot calculation + pivot = pivotPoint(fromPoint, { + x: dirIsX ? toPoint.x : fromPoint.x, + y: dirIsX ? fromPoint.y : toPoint.y + }, dirIsX); + segments = [{ + start: fromPoint, + end: { + x: pivot.x, + y: pivot.y + } + }]; + // Pivot before goal, use a waypoint to dodge obstacle + if (pivot[dirIsX ? 'x' : 'y'] !== toPoint[dirIsX ? 'x' : 'y']) { + // Find direction of waypoint + waypointUseMax = getDodgeDirection(pivot.obstacle, pivot, toPoint, !dirIsX, bounds); + // Cut waypoint to hard bounds + limitObstacleToBounds(pivot.obstacle, options.hardBounds); + waypoint = { + x: dirIsX ? + pivot.x : + pivot.obstacle[waypointUseMax ? 'xMax' : 'xMin'] + + (waypointUseMax ? 1 : -1), + y: dirIsX ? + pivot.obstacle[waypointUseMax ? 'yMax' : 'yMin'] + + (waypointUseMax ? 1 : -1) : + pivot.y + }; + // We're changing direction here, store that to make sure we + // also change direction when adding the last segment array + // after handling waypoint. + dirIsX = !dirIsX; + segments = segments.concat(clearPathTo({ + x: pivot.x, + y: pivot.y + }, waypoint, dirIsX)); + } + } + // Get segments for the other direction too + // Recursion is our friend + segments = segments.concat(clearPathTo(segments[segments.length - 1].end, toPoint, !dirIsX)); + return segments; + } + // eslint-disable-next-line valid-jsdoc + /** + * Extract point to outside of obstacle in whichever direction is + * closest. Returns new point outside obstacle. + * @private + */ + function extractFromObstacle(obstacle, point, goalPoint) { + var dirIsX = min(obstacle.xMax - point.x, point.x - obstacle.xMin) < + min(obstacle.yMax - point.y, point.y - obstacle.yMin), bounds = { + soft: options.hardBounds, + hard: options.hardBounds + }, useMax = getDodgeDirection(obstacle, point, goalPoint, dirIsX, bounds); + return dirIsX ? { + y: point.y, + x: obstacle[useMax ? 'xMax' : 'xMin'] + (useMax ? 1 : -1) + } : { + x: point.x, + y: obstacle[useMax ? 'yMax' : 'yMin'] + (useMax ? 1 : -1) + }; + } + // Cut the obstacle array to soft bounds for optimization in large + // datasets. + chartObstacles = + chartObstacles.slice(startObstacleIx, endObstacleIx + 1); + // If an obstacle envelops the end point, move it out of there and add + // a little segment to where it was. + if ((endObstacleIx = findObstacleFromPoint(chartObstacles, end)) > -1) { + extractedEndPoint = extractFromObstacle(chartObstacles[endObstacleIx], end, start); + endSegments.push({ + end: end, + start: extractedEndPoint + }); + end = extractedEndPoint; + } + // If it's still inside one or more obstacles, get out of there by + // force-moving towards the start point. + while ((endObstacleIx = findObstacleFromPoint(chartObstacles, end)) > -1) { + useMax = end[dir] - start[dir] < 0; + extractedEndPoint = { + x: end.x, + y: end.y + }; + extractedEndPoint[dir] = chartObstacles[endObstacleIx][useMax ? dir + 'Max' : dir + 'Min'] + (useMax ? 1 : -1); + endSegments.push({ + end: end, + start: extractedEndPoint + }); + end = extractedEndPoint; + } + // Find the path + segments = clearPathTo(start, end, dirIsX); + // Add the end-point segments + segments = segments.concat(endSegments.reverse()); + return { + path: pathFromSegments(segments), + obstacles: segments + }; + }, { + requiresObstacles: true + }) + }; + + return algorithms; + }); + _registerModule(_modules, 'parts-gantt/ArrowSymbols.js', [_modules['parts/Globals.js']], function (H) { + /* * + * + * (c) 2017 Highsoft AS + * Authors: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Creates an arrow symbol. Like a triangle, except not filled. + * ``` + * o + * o + * o + * o + * o + * o + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols.arrow = function (x, y, w, h) { + return [ + ['M', x, y + h / 2], + ['L', x + w, y], + ['L', x, y + h / 2], + ['L', x + w, y + h] + ]; + }; + /** + * Creates a half-width arrow symbol. Like a triangle, except not filled. + * ``` + * o + * o + * o + * o + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols['arrow-half'] = function (x, y, w, h) { + return H.SVGRenderer.prototype.symbols.arrow(x, y, w / 2, h); + }; + /** + * Creates a left-oriented triangle. + * ``` + * o + * ooooooo + * ooooooooooooo + * ooooooo + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the triangle + * + * @param {number} y + * y position of the triangle + * + * @param {number} w + * width of the triangle + * + * @param {number} h + * height of the triangle + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols['triangle-left'] = function (x, y, w, h) { + return [ + ['M', x + w, y], + ['L', x, y + h / 2], + ['L', x + w, y + h], + ['Z'] + ]; + }; + /** + * Alias function for triangle-left. + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols['arrow-filled'] = + H.SVGRenderer.prototype.symbols['triangle-left']; + /** + * Creates a half-width, left-oriented triangle. + * ``` + * o + * oooo + * ooooooo + * oooo + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the triangle + * + * @param {number} y + * y position of the triangle + * + * @param {number} w + * width of the triangle + * + * @param {number} h + * height of the triangle + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols['triangle-left-half'] = function (x, y, w, h) { + return H.SVGRenderer.prototype.symbols['triangle-left'](x, y, w / 2, h); + }; + /** + * Alias function for triangle-left-half. + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols['arrow-filled-half'] = + H.SVGRenderer.prototype.symbols['triangle-left-half']; + + }); + _registerModule(_modules, 'parts-gantt/Pathfinder.js', [_modules['parts/Globals.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js'], _modules['parts-gantt/PathfinderAlgorithms.js']], function (H, Point, U, pathfinderAlgorithms) { + /* * + * + * (c) 2016 Highsoft AS + * Authors: Øystein Moseng, Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * The default pathfinder algorithm to use for a chart. It is possible to define + * your own algorithms by adding them to the + * `Highcharts.Pathfinder.prototype.algorithms` + * object before the chart has been created. + * + * The default algorithms are as follows: + * + * `straight`: Draws a straight line between the connecting + * points. Does not avoid other points when drawing. + * + * `simpleConnect`: Finds a path between the points using right angles + * only. Takes only starting/ending points into + * account, and will not avoid other points. + * + * `fastAvoid`: Finds a path between the points using right angles + * only. Will attempt to avoid other points, but its + * focus is performance over accuracy. Works well with + * less dense datasets. + * + * @typedef {"fastAvoid"|"simpleConnect"|"straight"|string} Highcharts.PathfinderTypeValue + */ + ''; // detach doclets above + var addEvent = U.addEvent, defined = U.defined, error = U.error, extend = U.extend, merge = U.merge, objectEach = U.objectEach, pick = U.pick, splat = U.splat; + var deg2rad = H.deg2rad, max = Math.max, min = Math.min; + /* + @todo: + - Document how to write your own algorithms + - Consider adding a Point.pathTo method that wraps creating a connection + and rendering it + */ + // Set default Pathfinder options + extend(H.defaultOptions, { + /** + * The Pathfinder module allows you to define connections between any two + * points, represented as lines - optionally with markers for the start + * and/or end points. Multiple algorithms are available for calculating how + * the connecting lines are drawn. + * + * Connector functionality requires Highcharts Gantt to be loaded. In Gantt + * charts, the connectors are used to draw dependencies between tasks. + * + * @see [dependency](series.gantt.data.dependency) + * + * @sample gantt/pathfinder/demo + * Pathfinder connections + * + * @declare Highcharts.ConnectorsOptions + * @product gantt + * @optionparent connectors + */ + connectors: { + /** + * Enable connectors for this chart. Requires Highcharts Gantt. + * + * @type {boolean} + * @default true + * @since 6.2.0 + * @apioption connectors.enabled + */ + /** + * Set the default dash style for this chart's connecting lines. + * + * @type {string} + * @default solid + * @since 6.2.0 + * @apioption connectors.dashStyle + */ + /** + * Set the default color for this chart's Pathfinder connecting lines. + * Defaults to the color of the point being connected. + * + * @type {Highcharts.ColorString} + * @since 6.2.0 + * @apioption connectors.lineColor + */ + /** + * Set the default pathfinder margin to use, in pixels. Some Pathfinder + * algorithms attempt to avoid obstacles, such as other points in the + * chart. These algorithms use this margin to determine how close lines + * can be to an obstacle. The default is to compute this automatically + * from the size of the obstacles in the chart. + * + * To draw connecting lines close to existing points, set this to a low + * number. For more space around existing points, set this number + * higher. + * + * @sample gantt/pathfinder/algorithm-margin + * Small algorithmMargin + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.algorithmMargin + */ + /** + * Set the default pathfinder algorithm to use for this chart. It is + * possible to define your own algorithms by adding them to the + * Highcharts.Pathfinder.prototype.algorithms object before the chart + * has been created. + * + * The default algorithms are as follows: + * + * `straight`: Draws a straight line between the connecting + * points. Does not avoid other points when drawing. + * + * `simpleConnect`: Finds a path between the points using right angles + * only. Takes only starting/ending points into + * account, and will not avoid other points. + * + * `fastAvoid`: Finds a path between the points using right angles + * only. Will attempt to avoid other points, but its + * focus is performance over accuracy. Works well with + * less dense datasets. + * + * Default value: `straight` is used as default for most series types, + * while `simpleConnect` is used as default for Gantt series, to show + * dependencies between points. + * + * @sample gantt/pathfinder/demo + * Different types used + * + * @type {Highcharts.PathfinderTypeValue} + * @default undefined + * @since 6.2.0 + */ + type: 'straight', + /** + * Set the default pixel width for this chart's Pathfinder connecting + * lines. + * + * @since 6.2.0 + */ + lineWidth: 1, + /** + * Marker options for this chart's Pathfinder connectors. Note that + * this option is overridden by the `startMarker` and `endMarker` + * options. + * + * @declare Highcharts.ConnectorsMarkerOptions + * @since 6.2.0 + */ + marker: { + /** + * Set the radius of the connector markers. The default is + * automatically computed based on the algorithmMargin setting. + * + * Setting marker.width and marker.height will override this + * setting. + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.marker.radius + */ + /** + * Set the width of the connector markers. If not supplied, this + * is inferred from the marker radius. + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.marker.width + */ + /** + * Set the height of the connector markers. If not supplied, this + * is inferred from the marker radius. + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.marker.height + */ + /** + * Set the color of the connector markers. By default this is the + * same as the connector color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 6.2.0 + * @apioption connectors.marker.color + */ + /** + * Set the line/border color of the connector markers. By default + * this is the same as the marker color. + * + * @type {Highcharts.ColorString} + * @since 6.2.0 + * @apioption connectors.marker.lineColor + */ + /** + * Enable markers for the connectors. + */ + enabled: false, + /** + * Horizontal alignment of the markers relative to the points. + * + * @type {Highcharts.AlignValue} + */ + align: 'center', + /** + * Vertical alignment of the markers relative to the points. + * + * @type {Highcharts.VerticalAlignValue} + */ + verticalAlign: 'middle', + /** + * Whether or not to draw the markers inside the points. + */ + inside: false, + /** + * Set the line/border width of the pathfinder markers. + */ + lineWidth: 1 + }, + /** + * Marker options specific to the start markers for this chart's + * Pathfinder connectors. Overrides the generic marker options. + * + * @declare Highcharts.ConnectorsStartMarkerOptions + * @extends connectors.marker + * @since 6.2.0 + */ + startMarker: { + /** + * Set the symbol of the connector start markers. + */ + symbol: 'diamond' + }, + /** + * Marker options specific to the end markers for this chart's + * Pathfinder connectors. Overrides the generic marker options. + * + * @declare Highcharts.ConnectorsEndMarkerOptions + * @extends connectors.marker + * @since 6.2.0 + */ + endMarker: { + /** + * Set the symbol of the connector end markers. + */ + symbol: 'arrow-filled' + } + } + }); + /** + * Override Pathfinder connector options for a series. Requires Highcharts Gantt + * to be loaded. + * + * @declare Highcharts.SeriesConnectorsOptionsObject + * @extends connectors + * @since 6.2.0 + * @excluding enabled, algorithmMargin + * @product gantt + * @apioption plotOptions.series.connectors + */ + /** + * Connect to a point. This option can be either a string, referring to the ID + * of another point, or an object, or an array of either. If the option is an + * array, each element defines a connection. + * + * @sample gantt/pathfinder/demo + * Different connection types + * + * @declare Highcharts.XrangePointConnectorsOptionsObject + * @type {string|Array|*} + * @extends plotOptions.series.connectors + * @since 6.2.0 + * @excluding enabled + * @product gantt + * @requires highcharts-gantt + * @apioption series.xrange.data.connect + */ + /** + * The ID of the point to connect to. + * + * @type {string} + * @since 6.2.0 + * @product gantt + * @apioption series.xrange.data.connect.to + */ + /** + * Get point bounding box using plotX/plotY and shapeArgs. If using + * graphic.getBBox() directly, the bbox will be affected by animation. + * + * @private + * @function + * + * @param {Highcharts.Point} point + * The point to get BB of. + * + * @return {Highcharts.Dictionary|null} + * Result xMax, xMin, yMax, yMin. + */ + function getPointBB(point) { + var shapeArgs = point.shapeArgs, bb; + // Prefer using shapeArgs (columns) + if (shapeArgs) { + return { + xMin: shapeArgs.x, + xMax: shapeArgs.x + shapeArgs.width, + yMin: shapeArgs.y, + yMax: shapeArgs.y + shapeArgs.height + }; + } + // Otherwise use plotX/plotY and bb + bb = point.graphic && point.graphic.getBBox(); + return bb ? { + xMin: point.plotX - bb.width / 2, + xMax: point.plotX + bb.width / 2, + yMin: point.plotY - bb.height / 2, + yMax: point.plotY + bb.height / 2 + } : null; + } + /** + * Calculate margin to place around obstacles for the pathfinder in pixels. + * Returns a minimum of 1 pixel margin. + * + * @private + * @function + * + * @param {Array} obstacles + * Obstacles to calculate margin from. + * + * @return {number} + * The calculated margin in pixels. At least 1. + */ + function calculateObstacleMargin(obstacles) { + var len = obstacles.length, i = 0, j, obstacleDistance, distances = [], + // Compute smallest distance between two rectangles + distance = function (a, b, bbMargin) { + // Count the distance even if we are slightly off + var margin = pick(bbMargin, 10), yOverlap = a.yMax + margin > b.yMin - margin && + a.yMin - margin < b.yMax + margin, xOverlap = a.xMax + margin > b.xMin - margin && + a.xMin - margin < b.xMax + margin, xDistance = yOverlap ? (a.xMin > b.xMax ? a.xMin - b.xMax : b.xMin - a.xMax) : Infinity, yDistance = xOverlap ? (a.yMin > b.yMax ? a.yMin - b.yMax : b.yMin - a.yMax) : Infinity; + // If the rectangles collide, try recomputing with smaller margin. + // If they collide anyway, discard the obstacle. + if (xOverlap && yOverlap) { + return (margin ? + distance(a, b, Math.floor(margin / 2)) : + Infinity); + } + return min(xDistance, yDistance); + }; + // Go over all obstacles and compare them to the others. + for (; i < len; ++i) { + // Compare to all obstacles ahead. We will already have compared this + // obstacle to the ones before. + for (j = i + 1; j < len; ++j) { + obstacleDistance = distance(obstacles[i], obstacles[j]); + // TODO: Magic number 80 + if (obstacleDistance < 80) { // Ignore large distances + distances.push(obstacleDistance); + } + } + } + // Ensure we always have at least one value, even in very spaceous charts + distances.push(80); + return max(Math.floor(distances.sort(function (a, b) { + return (a - b); + })[ + // Discard first 10% of the relevant distances, and then grab + // the smallest one. + Math.floor(distances.length / 10)] / 2 - 1 // Divide the distance by 2 and subtract 1. + ), 1 // 1 is the minimum margin + ); + } + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The Connection class. Used internally to represent a connection between two + * points. + * + * @private + * @class + * @name Highcharts.Connection + * + * @param {Highcharts.Point} from + * Connection runs from this Point. + * + * @param {Highcharts.Point} to + * Connection runs to this Point. + * + * @param {Highcharts.ConnectorsOptions} [options] + * Connection options. + */ + function Connection(from, to, options) { + this.init(from, to, options); + } + Connection.prototype = { + /** + * Initialize the Connection object. Used as constructor only. + * + * @function Highcharts.Connection#init + * + * @param {Highcharts.Point} from + * Connection runs from this Point. + * + * @param {Highcharts.Point} to + * Connection runs to this Point. + * + * @param {Highcharts.ConnectorsOptions} [options] + * Connection options. + */ + init: function (from, to, options) { + this.fromPoint = from; + this.toPoint = to; + this.options = options; + this.chart = from.series.chart; + this.pathfinder = this.chart.pathfinder; + }, + /** + * Add (or update) this connection's path on chart. Stores reference to the + * created element on this.graphics.path. + * + * @function Highcharts.Connection#renderPath + * + * @param {Highcharts.SVGPathArray} path + * Path to render, in array format. E.g. ['M', 0, 0, 'L', 10, 10] + * + * @param {Highcharts.SVGAttributes} [attribs] + * SVG attributes for the path. + * + * @param {Highcharts.AnimationOptionsObject} [animation] + * Animation options for the rendering. + */ + renderPath: function (path, attribs, animation) { + var connection = this, chart = this.chart, styledMode = chart.styledMode, pathfinder = chart.pathfinder, animate = !chart.options.chart.forExport && animation !== false, pathGraphic = connection.graphics && connection.graphics.path, anim; + // Add the SVG element of the pathfinder group if it doesn't exist + if (!pathfinder.group) { + pathfinder.group = chart.renderer.g() + .addClass('highcharts-pathfinder-group') + .attr({ zIndex: -1 }) + .add(chart.seriesGroup); + } + // Shift the group to compensate for plot area. + // Note: Do this always (even when redrawing a path) to avoid issues + // when updating chart in a way that changes plot metrics. + pathfinder.group.translate(chart.plotLeft, chart.plotTop); + // Create path if does not exist + if (!(pathGraphic && pathGraphic.renderer)) { + pathGraphic = chart.renderer.path() + .add(pathfinder.group); + if (!styledMode) { + pathGraphic.attr({ + opacity: 0 + }); + } + } + // Set path attribs and animate to the new path + pathGraphic.attr(attribs); + anim = { d: path }; + if (!styledMode) { + anim.opacity = 1; + } + pathGraphic[animate ? 'animate' : 'attr'](anim, animation); + // Store reference on connection + this.graphics = this.graphics || {}; + this.graphics.path = pathGraphic; + }, + /** + * Calculate and add marker graphics for connection to the chart. The + * created/updated elements are stored on this.graphics.start and + * this.graphics.end. + * + * @function Highcharts.Connection#addMarker + * + * @param {string} type + * Marker type, either 'start' or 'end'. + * + * @param {Highcharts.ConnectorsMarkerOptions} options + * All options for this marker. Not calculated or merged with other + * options. + * + * @param {Highcharts.SVGPathArray} path + * Connection path in array format. This is used to calculate the + * rotation angle of the markers. + */ + addMarker: function (type, options, path) { + var connection = this, chart = connection.fromPoint.series.chart, pathfinder = chart.pathfinder, renderer = chart.renderer, point = (type === 'start' ? + connection.fromPoint : + connection.toPoint), anchor = point.getPathfinderAnchorPoint(options), markerVector, radians, rotation, box, width, height, pathVector, segment; + if (!options.enabled) { + return; + } + // Last vector before start/end of path, used to get angle + if (type === 'start') { + segment = path[1]; + } + else { // 'end' + segment = path[path.length - 2]; + } + if (segment && segment[0] === 'M' || segment[0] === 'L') { + pathVector = { + x: segment[1], + y: segment[2] + }; + // Get angle between pathVector and anchor point and use it to + // create marker position. + radians = point.getRadiansToVector(pathVector, anchor); + markerVector = point.getMarkerVector(radians, options.radius, anchor); + // Rotation of marker is calculated from angle between pathVector + // and markerVector. + // (Note: + // Used to recalculate radians between markerVector and pathVector, + // but this should be the same as between pathVector and anchor.) + rotation = -radians / deg2rad; + if (options.width && options.height) { + width = options.width; + height = options.height; + } + else { + width = height = options.radius * 2; + } + // Add graphics object if it does not exist + connection.graphics = connection.graphics || {}; + box = { + x: markerVector.x - (width / 2), + y: markerVector.y - (height / 2), + width: width, + height: height, + rotation: rotation, + rotationOriginX: markerVector.x, + rotationOriginY: markerVector.y + }; + if (!connection.graphics[type]) { + // Create new marker element + connection.graphics[type] = renderer + .symbol(options.symbol) + .addClass('highcharts-point-connecting-path-' + type + '-marker') + .attr(box) + .add(pathfinder.group); + if (!renderer.styledMode) { + connection.graphics[type].attr({ + fill: options.color || connection.fromPoint.color, + stroke: options.lineColor, + 'stroke-width': options.lineWidth, + opacity: 0 + }) + .animate({ + opacity: 1 + }, point.series.options.animation); + } + } + else { + connection.graphics[type].animate(box); + } + } + }, + /** + * Calculate and return connection path. + * Note: Recalculates chart obstacles on demand if they aren't calculated. + * + * @function Highcharts.Connection#getPath + * + * @param {Highcharts.ConnectorsOptions} options + * Connector options. Not calculated or merged with other options. + * + * @return {object|undefined} + * Calculated SVG path data in array format. + */ + getPath: function (options) { + var pathfinder = this.pathfinder, chart = this.chart, algorithm = pathfinder.algorithms[options.type], chartObstacles = pathfinder.chartObstacles; + if (typeof algorithm !== 'function') { + error('"' + options.type + '" is not a Pathfinder algorithm.'); + return; + } + // This function calculates obstacles on demand if they don't exist + if (algorithm.requiresObstacles && !chartObstacles) { + chartObstacles = + pathfinder.chartObstacles = + pathfinder.getChartObstacles(options); + // If the algorithmMargin was computed, store the result in default + // options. + chart.options.connectors.algorithmMargin = + options.algorithmMargin; + // Cache some metrics too + pathfinder.chartObstacleMetrics = + pathfinder.getObstacleMetrics(chartObstacles); + } + // Get the SVG path + return algorithm( + // From + this.fromPoint.getPathfinderAnchorPoint(options.startMarker), + // To + this.toPoint.getPathfinderAnchorPoint(options.endMarker), merge({ + chartObstacles: chartObstacles, + lineObstacles: pathfinder.lineObstacles || [], + obstacleMetrics: pathfinder.chartObstacleMetrics, + hardBounds: { + xMin: 0, + xMax: chart.plotWidth, + yMin: 0, + yMax: chart.plotHeight + }, + obstacleOptions: { + margin: options.algorithmMargin + }, + startDirectionX: pathfinder.getAlgorithmStartDirection(options.startMarker) + }, options)); + }, + /** + * (re)Calculate and (re)draw the connection. + * + * @function Highcharts.Connection#render + */ + render: function () { + var connection = this, fromPoint = connection.fromPoint, series = fromPoint.series, chart = series.chart, pathfinder = chart.pathfinder, pathResult, path, options = merge(chart.options.connectors, series.options.connectors, fromPoint.options.connectors, connection.options), attribs = {}; + // Set path attribs + if (!chart.styledMode) { + attribs.stroke = options.lineColor || fromPoint.color; + attribs['stroke-width'] = options.lineWidth; + if (options.dashStyle) { + attribs.dashstyle = options.dashStyle; + } + } + attribs['class'] = // eslint-disable-line dot-notation + 'highcharts-point-connecting-path ' + + 'highcharts-color-' + fromPoint.colorIndex; + options = merge(attribs, options); + // Set common marker options + if (!defined(options.marker.radius)) { + options.marker.radius = min(max(Math.ceil((options.algorithmMargin || 8) / 2) - 1, 1), 5); + } + // Get the path + pathResult = connection.getPath(options); + path = pathResult.path; + // Always update obstacle storage with obstacles from this path. + // We don't know if future calls will need this for their algorithm. + if (pathResult.obstacles) { + pathfinder.lineObstacles = + pathfinder.lineObstacles || []; + pathfinder.lineObstacles = + pathfinder.lineObstacles.concat(pathResult.obstacles); + } + // Add the calculated path to the pathfinder group + connection.renderPath(path, attribs, series.options.animation); + // Render the markers + connection.addMarker('start', merge(options.marker, options.startMarker), path); + connection.addMarker('end', merge(options.marker, options.endMarker), path); + }, + /** + * Destroy connection by destroying the added graphics elements. + * + * @function Highcharts.Connection#destroy + */ + destroy: function () { + if (this.graphics) { + objectEach(this.graphics, function (val) { + val.destroy(); + }); + delete this.graphics; + } + } + }; + /** + * The Pathfinder class. + * + * @private + * @class + * @name Highcharts.Pathfinder + * + * @param {Highcharts.Chart} chart + * The chart to operate on. + */ + function Pathfinder(chart) { + this.init(chart); + } + Pathfinder.prototype = { + /** + * @name Highcharts.Pathfinder#algorithms + * @type {Highcharts.Dictionary} + */ + algorithms: pathfinderAlgorithms, + /** + * Initialize the Pathfinder object. + * + * @function Highcharts.Pathfinder#init + * + * @param {Highcharts.Chart} chart + * The chart context. + */ + init: function (chart) { + // Initialize pathfinder with chart context + this.chart = chart; + // Init connection reference list + this.connections = []; + // Recalculate paths/obstacles on chart redraw + addEvent(chart, 'redraw', function () { + this.pathfinder.update(); + }); + }, + /** + * Update Pathfinder connections from scratch. + * + * @function Highcharts.Pathfinder#update + * + * @param {boolean} [deferRender] + * Whether or not to defer rendering of connections until + * series.afterAnimate event has fired. Used on first render. + */ + update: function (deferRender) { + var chart = this.chart, pathfinder = this, oldConnections = pathfinder.connections; + // Rebuild pathfinder connections from options + pathfinder.connections = []; + chart.series.forEach(function (series) { + if (series.visible && !series.options.isInternal) { + series.points.forEach(function (point) { + var to, connects = (point.options && + point.options.connect && + splat(point.options.connect)); + if (point.visible && point.isInside !== false && connects) { + connects.forEach(function (connect) { + to = chart.get(typeof connect === 'string' ? + connect : connect.to); + if (to instanceof Point && + to.series.visible && + to.visible && + to.isInside !== false) { + // Add new connection + pathfinder.connections.push(new Connection(point, // from + to, typeof connect === 'string' ? + {} : + connect)); + } + }); + } + }); + } + }); + // Clear connections that should not be updated, and move old info over + // to new connections. + for (var j = 0, k, found, lenOld = oldConnections.length, lenNew = pathfinder.connections.length; j < lenOld; ++j) { + found = false; + for (k = 0; k < lenNew; ++k) { + if (oldConnections[j].fromPoint === + pathfinder.connections[k].fromPoint && + oldConnections[j].toPoint === + pathfinder.connections[k].toPoint) { + pathfinder.connections[k].graphics = + oldConnections[j].graphics; + found = true; + break; + } + } + if (!found) { + oldConnections[j].destroy(); + } + } + // Clear obstacles to force recalculation. This must be done on every + // redraw in case positions have changed. Recalculation is handled in + // Connection.getPath on demand. + delete this.chartObstacles; + delete this.lineObstacles; + // Draw the pending connections + pathfinder.renderConnections(deferRender); + }, + /** + * Draw the chart's connecting paths. + * + * @function Highcharts.Pathfinder#renderConnections + * + * @param {boolean} [deferRender] + * Whether or not to defer render until series animation is finished. + * Used on first render. + */ + renderConnections: function (deferRender) { + if (deferRender) { + // Render after series are done animating + this.chart.series.forEach(function (series) { + var render = function () { + // Find pathfinder connections belonging to this series + // that haven't rendered, and render them now. + var pathfinder = series.chart.pathfinder, conns = pathfinder && pathfinder.connections || []; + conns.forEach(function (connection) { + if (connection.fromPoint && + connection.fromPoint.series === series) { + connection.render(); + } + }); + if (series.pathfinderRemoveRenderEvent) { + series.pathfinderRemoveRenderEvent(); + delete series.pathfinderRemoveRenderEvent; + } + }; + if (series.options.animation === false) { + render(); + } + else { + series.pathfinderRemoveRenderEvent = addEvent(series, 'afterAnimate', render); + } + }); + } + else { + // Go through connections and render them + this.connections.forEach(function (connection) { + connection.render(); + }); + } + }, + /** + * Get obstacles for the points in the chart. Does not include connecting + * lines from Pathfinder. Applies algorithmMargin to the obstacles. + * + * @function Highcharts.Pathfinder#getChartObstacles + * + * @param {object} options + * Options for the calculation. Currenlty only + * options.algorithmMargin. + * + * @return {Array} + * An array of calculated obstacles. Each obstacle is defined as an + * object with xMin, xMax, yMin and yMax properties. + */ + getChartObstacles: function (options) { + var obstacles = [], series = this.chart.series, margin = pick(options.algorithmMargin, 0), calculatedMargin; + for (var i = 0, sLen = series.length; i < sLen; ++i) { + if (series[i].visible && !series[i].options.isInternal) { + for (var j = 0, pLen = series[i].points.length, bb, point; j < pLen; ++j) { + point = series[i].points[j]; + if (point.visible) { + bb = getPointBB(point); + if (bb) { + obstacles.push({ + xMin: bb.xMin - margin, + xMax: bb.xMax + margin, + yMin: bb.yMin - margin, + yMax: bb.yMax + margin + }); + } + } + } + } + } + // Sort obstacles by xMin for optimization + obstacles = obstacles.sort(function (a, b) { + return a.xMin - b.xMin; + }); + // Add auto-calculated margin if the option is not defined + if (!defined(options.algorithmMargin)) { + calculatedMargin = + options.algorithmMargin = + calculateObstacleMargin(obstacles); + obstacles.forEach(function (obstacle) { + obstacle.xMin -= calculatedMargin; + obstacle.xMax += calculatedMargin; + obstacle.yMin -= calculatedMargin; + obstacle.yMax += calculatedMargin; + }); + } + return obstacles; + }, + /** + * Utility function to get metrics for obstacles: + * - Widest obstacle width + * - Tallest obstacle height + * + * @function Highcharts.Pathfinder#getObstacleMetrics + * + * @param {Array} obstacles + * An array of obstacles to inspect. + * + * @return {object} + * The calculated metrics, as an object with maxHeight and maxWidth + * properties. + */ + getObstacleMetrics: function (obstacles) { + var maxWidth = 0, maxHeight = 0, width, height, i = obstacles.length; + while (i--) { + width = obstacles[i].xMax - obstacles[i].xMin; + height = obstacles[i].yMax - obstacles[i].yMin; + if (maxWidth < width) { + maxWidth = width; + } + if (maxHeight < height) { + maxHeight = height; + } + } + return { + maxHeight: maxHeight, + maxWidth: maxWidth + }; + }, + /** + * Utility to get which direction to start the pathfinding algorithm + * (X vs Y), calculated from a set of marker options. + * + * @function Highcharts.Pathfinder#getAlgorithmStartDirection + * + * @param {Highcharts.ConnectorsMarkerOptions} markerOptions + * Marker options to calculate from. + * + * @return {boolean} + * Returns true for X, false for Y, and undefined for autocalculate. + */ + getAlgorithmStartDirection: function (markerOptions) { + var xCenter = markerOptions.align !== 'left' && + markerOptions.align !== 'right', yCenter = markerOptions.verticalAlign !== 'top' && + markerOptions.verticalAlign !== 'bottom', undef; + return xCenter ? + (yCenter ? undef : false) : // x is centered + (yCenter ? true : undef); // x is off-center + } + }; + // Add to Highcharts namespace + H.Connection = Connection; + H.Pathfinder = Pathfinder; + // Add pathfinding capabilities to Points + extend(Point.prototype, /** @lends Point.prototype */ { + /** + * Get coordinates of anchor point for pathfinder connection. + * + * @private + * @function Highcharts.Point#getPathfinderAnchorPoint + * + * @param {Highcharts.ConnectorsMarkerOptions} markerOptions + * Connection options for position on point. + * + * @return {Highcharts.PositionObject} + * An object with x/y properties for the position. Coordinates are + * in plot values, not relative to point. + */ + getPathfinderAnchorPoint: function (markerOptions) { + var bb = getPointBB(this), x, y; + switch (markerOptions.align) { // eslint-disable-line default-case + case 'right': + x = 'xMax'; + break; + case 'left': + x = 'xMin'; + } + switch (markerOptions.verticalAlign) { // eslint-disable-line default-case + case 'top': + y = 'yMin'; + break; + case 'bottom': + y = 'yMax'; + } + return { + x: x ? bb[x] : (bb.xMin + bb.xMax) / 2, + y: y ? bb[y] : (bb.yMin + bb.yMax) / 2 + }; + }, + /** + * Utility to get the angle from one point to another. + * + * @private + * @function Highcharts.Point#getRadiansToVector + * + * @param {Highcharts.PositionObject} v1 + * The first vector, as an object with x/y properties. + * + * @param {Highcharts.PositionObject} v2 + * The second vector, as an object with x/y properties. + * + * @return {number} + * The angle in degrees + */ + getRadiansToVector: function (v1, v2) { + var box; + if (!defined(v2)) { + box = getPointBB(this); + if (box) { + v2 = { + x: (box.xMin + box.xMax) / 2, + y: (box.yMin + box.yMax) / 2 + }; + } + } + return Math.atan2(v2.y - v1.y, v1.x - v2.x); + }, + /** + * Utility to get the position of the marker, based on the path angle and + * the marker's radius. + * + * @private + * @function Highcharts.Point#getMarkerVector + * + * @param {number} radians + * The angle in radians from the point center to another vector. + * + * @param {number} markerRadius + * The radius of the marker, to calculate the additional distance to + * the center of the marker. + * + * @param {object} anchor + * The anchor point of the path and marker as an object with x/y + * properties. + * + * @return {object} + * The marker vector as an object with x/y properties. + */ + getMarkerVector: function (radians, markerRadius, anchor) { + var twoPI = Math.PI * 2.0, theta = radians, bb = getPointBB(this), rectWidth = bb.xMax - bb.xMin, rectHeight = bb.yMax - bb.yMin, rAtan = Math.atan2(rectHeight, rectWidth), tanTheta = 1, leftOrRightRegion = false, rectHalfWidth = rectWidth / 2.0, rectHalfHeight = rectHeight / 2.0, rectHorizontalCenter = bb.xMin + rectHalfWidth, rectVerticalCenter = bb.yMin + rectHalfHeight, edgePoint = { + x: rectHorizontalCenter, + y: rectVerticalCenter + }, markerPoint = {}, xFactor = 1, yFactor = 1; + while (theta < -Math.PI) { + theta += twoPI; + } + while (theta > Math.PI) { + theta -= twoPI; + } + tanTheta = Math.tan(theta); + if ((theta > -rAtan) && (theta <= rAtan)) { + // Right side + yFactor = -1; + leftOrRightRegion = true; + } + else if (theta > rAtan && theta <= (Math.PI - rAtan)) { + // Top side + yFactor = -1; + } + else if (theta > (Math.PI - rAtan) || theta <= -(Math.PI - rAtan)) { + // Left side + xFactor = -1; + leftOrRightRegion = true; + } + else { + // Bottom side + xFactor = -1; + } + // Correct the edgePoint according to the placement of the marker + if (leftOrRightRegion) { + edgePoint.x += xFactor * (rectHalfWidth); + edgePoint.y += yFactor * (rectHalfWidth) * tanTheta; + } + else { + edgePoint.x += xFactor * (rectHeight / (2.0 * tanTheta)); + edgePoint.y += yFactor * (rectHalfHeight); + } + if (anchor.x !== rectHorizontalCenter) { + edgePoint.x = anchor.x; + } + if (anchor.y !== rectVerticalCenter) { + edgePoint.y = anchor.y; + } + markerPoint.x = edgePoint.x + (markerRadius * Math.cos(theta)); + markerPoint.y = edgePoint.y - (markerRadius * Math.sin(theta)); + return markerPoint; + } + }); + /** + * Warn if using legacy options. Copy the options over. Note that this will + * still break if using the legacy options in chart.update, addSeries etc. + * @private + */ + function warnLegacy(chart) { + if (chart.options.pathfinder || + chart.series.reduce(function (acc, series) { + if (series.options) { + merge(true, (series.options.connectors = series.options.connectors || + {}), series.options.pathfinder); + } + return acc || series.options && series.options.pathfinder; + }, false)) { + merge(true, (chart.options.connectors = chart.options.connectors || {}), chart.options.pathfinder); + error('WARNING: Pathfinder options have been renamed. ' + + 'Use "chart.connectors" or "series.connectors" instead.'); + } + } + // Initialize Pathfinder for charts + H.Chart.prototype.callbacks.push(function (chart) { + var options = chart.options; + if (options.connectors.enabled !== false) { + warnLegacy(chart); + this.pathfinder = new Pathfinder(this); + this.pathfinder.update(true); // First draw, defer render + } + }); + + }); + _registerModule(_modules, 'modules/xrange.src.js', [_modules['parts/Globals.js'], _modules['parts/Color.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js']], function (H, Color, Point, U) { + /* * + * + * X-range series module + * + * (c) 2010-2020 Torstein Honsi, Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /* * + * @interface Highcharts.PointOptionsObject in parts/Point.ts + */ /** + * The ending X value of the range point. + * @name Highcharts.PointOptionsObject#x2 + * @type {number|undefined} + * @requires modules/xrange + */ + var color = Color.parse; + var addEvent = U.addEvent, clamp = U.clamp, correctFloat = U.correctFloat, defined = U.defined, find = U.find, isNumber = U.isNumber, isObject = U.isObject, merge = U.merge, pick = U.pick, seriesType = U.seriesType; + var columnType = H.seriesTypes.column, seriesTypes = H.seriesTypes, Axis = H.Axis, Series = H.Series; + /** + * Return color of a point based on its category. + * + * @private + * @function getColorByCategory + * + * @param {object} series + * The series which the point belongs to. + * + * @param {object} point + * The point to calculate its color for. + * + * @return {object} + * Returns an object containing the properties color and colorIndex. + */ + function getColorByCategory(series, point) { + var colors = series.options.colors || series.chart.options.colors, colorCount = colors ? + colors.length : + series.chart.options.chart.colorCount, colorIndex = point.y % colorCount, color = colors && colors[colorIndex]; + return { + colorIndex: colorIndex, + color: color + }; + } + /** + * @private + * @class + * @name Highcharts.seriesTypes.xrange + * + * @augments Highcharts.Series + */ + seriesType('xrange', 'column' + /** + * The X-range series displays ranges on the X axis, typically time + * intervals with a start and end date. + * + * @sample {highcharts} highcharts/demo/x-range/ + * X-range + * @sample {highcharts} highcharts/css/x-range/ + * Styled mode X-range + * @sample {highcharts} highcharts/chart/inverted-xrange/ + * Inverted X-range + * + * @extends plotOptions.column + * @since 6.0.0 + * @product highcharts highstock gantt + * @excluding boostThreshold, crisp, cropThreshold, depth, edgeColor, + * edgeWidth, findNearestPointBy, getExtremesFromAll, + * negativeColor, pointInterval, pointIntervalUnit, + * pointPlacement, pointRange, pointStart, softThreshold, + * stacking, threshold, data, dataSorting + * @requires modules/xrange + * @optionparent plotOptions.xrange + */ + , { + /** + * A partial fill for each point, typically used to visualize how much + * of a task is performed. The partial fill object can be set either on + * series or point level. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range with partial fill + * + * @product highcharts highstock gantt + * @apioption plotOptions.xrange.partialFill + */ + /** + * The fill color to be used for partial fills. Defaults to a darker + * shade of the point color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock gantt + * @apioption plotOptions.xrange.partialFill.fill + */ + /** + * A partial fill for each point, typically used to visualize how much + * of a task is performed. See [completed](series.gantt.data.completed). + * + * @sample gantt/demo/progress-indicator + * Gantt with progress indicator + * + * @product gantt + * @apioption plotOptions.gantt.partialFill + */ + /** + * In an X-range series, this option makes all points of the same Y-axis + * category the same color. + */ + colorByPoint: true, + dataLabels: { + formatter: function () { + var point = this.point, amount = point.partialFill; + if (isObject(amount)) { + amount = amount.amount; + } + if (isNumber(amount) && amount > 0) { + return correctFloat(amount * 100) + '%'; + } + }, + inside: true, + verticalAlign: 'middle' + }, + tooltip: { + headerFormat: '{point.x} - {point.x2}
    ', + pointFormat: '\u25CF {series.name}: {point.yCategory}
    ' + }, + borderRadius: 3, + pointRange: 0 + }, { + type: 'xrange', + parallelArrays: ['x', 'x2', 'y'], + requireSorting: false, + animate: seriesTypes.line.prototype.animate, + cropShoulder: 1, + getExtremesFromAll: true, + autoIncrement: H.noop, + buildKDTree: H.noop, + /* eslint-disable valid-jsdoc */ + /** + * @private + * @function Highcarts.seriesTypes.xrange#init + * @return {void} + */ + init: function () { + seriesTypes.column.prototype.init.apply(this, arguments); + this.options.stacking = void 0; // #13161 + }, + /** + * Borrow the column series metrics, but with swapped axes. This gives + * free access to features like groupPadding, grouping, pointWidth etc. + * + * @private + * @function Highcharts.Series#getColumnMetrics + * + * @return {Highcharts.ColumnMetricsObject} + */ + getColumnMetrics: function () { + var metrics, chart = this.chart; + /** + * @private + */ + function swapAxes() { + chart.series.forEach(function (s) { + var xAxis = s.xAxis; + s.xAxis = s.yAxis; + s.yAxis = xAxis; + }); + } + swapAxes(); + metrics = columnType.prototype.getColumnMetrics.call(this); + swapAxes(); + return metrics; + }, + /** + * Override cropData to show a point where x or x2 is outside visible + * range, but one of them is inside. + * + * @private + * @function Highcharts.Series#cropData + * + * @param {Array} xData + * + * @param {Array} yData + * + * @param {number} min + * + * @param {number} max + * + * @param {number} [cropShoulder] + * + * @return {*} + */ + cropData: function (xData, yData, min, max) { + // Replace xData with x2Data to find the appropriate cropStart + var cropData = Series.prototype.cropData, crop = cropData.call(this, this.x2Data, yData, min, max); + // Re-insert the cropped xData + crop.xData = xData.slice(crop.start, crop.end); + return crop; + }, + /** + * Finds the index of an existing point that matches the given point + * options. + * + * @private + * @function Highcharts.Series#findPointIndex + * @param {object} options The options of the point. + * @returns {number|undefined} Returns index of a matching point, + * returns undefined if no match is found. + */ + findPointIndex: function (options) { + var _a = this, cropped = _a.cropped, cropStart = _a.cropStart, points = _a.points; + var id = options.id; + var pointIndex; + if (id) { + var point = find(points, function (point) { + return point.id === id; + }); + pointIndex = point ? point.index : void 0; + } + if (typeof pointIndex === 'undefined') { + var point = find(points, function (point) { + return (point.x === options.x && + point.x2 === options.x2 && + !point.touched); + }); + pointIndex = point ? point.index : void 0; + } + // Reduce pointIndex if data is cropped + if (cropped && + isNumber(pointIndex) && + isNumber(cropStart) && + pointIndex >= cropStart) { + pointIndex -= cropStart; + } + return pointIndex; + }, + /** + * @private + * @function Highcharts.Series#translatePoint + * + * @param {Highcharts.Point} point + */ + translatePoint: function (point) { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, metrics = series.columnMetrics, options = series.options, minPointLength = options.minPointLength || 0, plotX = point.plotX, posX = pick(point.x2, point.x + (point.len || 0)), plotX2 = xAxis.translate(posX, 0, 0, 0, 1), length = Math.abs(plotX2 - plotX), widthDifference, shapeArgs, partialFill, inverted = this.chart.inverted, borderWidth = pick(options.borderWidth, 1), crisper = borderWidth % 2 / 2, yOffset = metrics.offset, pointHeight = Math.round(metrics.width), dlLeft, dlRight, dlWidth, clipRectWidth, tooltipYOffset; + if (minPointLength) { + widthDifference = minPointLength - length; + if (widthDifference < 0) { + widthDifference = 0; + } + plotX -= widthDifference / 2; + plotX2 += widthDifference / 2; + } + plotX = Math.max(plotX, -10); + plotX2 = clamp(plotX2, -10, xAxis.len + 10); + // Handle individual pointWidth + if (defined(point.options.pointWidth)) { + yOffset -= ((Math.ceil(point.options.pointWidth) - pointHeight) / 2); + pointHeight = Math.ceil(point.options.pointWidth); + } + // Apply pointPlacement to the Y axis + if (options.pointPlacement && + isNumber(point.plotY) && + yAxis.categories) { + point.plotY = yAxis.translate(point.y, 0, 1, 0, 1, options.pointPlacement); + } + point.shapeArgs = { + x: Math.floor(Math.min(plotX, plotX2)) + crisper, + y: Math.floor(point.plotY + yOffset) + crisper, + width: Math.round(Math.abs(plotX2 - plotX)), + height: pointHeight, + r: series.options.borderRadius + }; + // Align data labels inside the shape and inside the plot area + dlLeft = point.shapeArgs.x; + dlRight = dlLeft + point.shapeArgs.width; + if (dlLeft < 0 || dlRight > xAxis.len) { + dlLeft = clamp(dlLeft, 0, xAxis.len); + dlRight = clamp(dlRight, 0, xAxis.len); + dlWidth = dlRight - dlLeft; + point.dlBox = merge(point.shapeArgs, { + x: dlLeft, + width: dlRight - dlLeft, + centerX: dlWidth ? dlWidth / 2 : null + }); + } + else { + point.dlBox = null; + } + // Tooltip position + var tooltipPos = point.tooltipPos; + var xIndex = !inverted ? 0 : 1; + var yIndex = !inverted ? 1 : 0; + tooltipYOffset = series.columnMetrics ? + series.columnMetrics.offset : -metrics.width / 2; + // Limit position by the correct axis size (#9727) + tooltipPos[xIndex] = clamp(tooltipPos[xIndex] + ((!inverted ? 1 : -1) * (xAxis.reversed ? -1 : 1) * + (length / 2)), 0, xAxis.len - 1); + tooltipPos[yIndex] = clamp(tooltipPos[yIndex] + ((inverted ? -1 : 1) * tooltipYOffset), 0, yAxis.len - 1); + // Add a partShapeArgs to the point, based on the shapeArgs property + partialFill = point.partialFill; + if (partialFill) { + // Get the partial fill amount + if (isObject(partialFill)) { + partialFill = partialFill.amount; + } + // If it was not a number, assume 0 + if (!isNumber(partialFill)) { + partialFill = 0; + } + shapeArgs = point.shapeArgs; + point.partShapeArgs = { + x: shapeArgs.x, + y: shapeArgs.y, + width: shapeArgs.width, + height: shapeArgs.height, + r: series.options.borderRadius + }; + clipRectWidth = Math.max(Math.round(length * partialFill + point.plotX - + plotX), 0); + point.clipRectArgs = { + x: xAxis.reversed ? // #10717 + shapeArgs.x + length - clipRectWidth : + shapeArgs.x, + y: shapeArgs.y, + width: clipRectWidth, + height: shapeArgs.height + }; + } + }, + /** + * @private + * @function Highcharts.Series#translate + */ + translate: function () { + columnType.prototype.translate.apply(this, arguments); + this.points.forEach(function (point) { + this.translatePoint(point); + }, this); + }, + /** + * Draws a single point in the series. Needed for partial fill. + * + * This override turns point.graphic into a group containing the + * original graphic and an overlay displaying the partial fill. + * + * @private + * @function Highcharts.Series#drawPoint + * + * @param {Highcharts.Point} point + * An instance of Point in the series. + * + * @param {"animate"|"attr"} verb + * 'animate' (animates changes) or 'attr' (sets options) + */ + drawPoint: function (point, verb) { + var series = this, seriesOpts = series.options, renderer = series.chart.renderer, graphic = point.graphic, type = point.shapeType, shapeArgs = point.shapeArgs, partShapeArgs = point.partShapeArgs, clipRectArgs = point.clipRectArgs, pfOptions = point.partialFill, cutOff = seriesOpts.stacking && !seriesOpts.borderRadius, pointState = point.state, stateOpts = (seriesOpts.states[pointState || 'normal'] || + {}), pointStateVerb = typeof pointState === 'undefined' ? + 'attr' : verb, pointAttr = series.pointAttribs(point, pointState), animation = pick(series.chart.options.chart.animation, stateOpts.animation), fill; + if (!point.isNull && point.visible !== false) { + // Original graphic + if (graphic) { // update + graphic.rect[verb](shapeArgs); + } + else { + point.graphic = graphic = renderer.g('point') + .addClass(point.getClassName()) + .add(point.group || series.group); + graphic.rect = renderer[type](merge(shapeArgs)) + .addClass(point.getClassName()) + .addClass('highcharts-partfill-original') + .add(graphic); + } + // Partial fill graphic + if (partShapeArgs) { + if (graphic.partRect) { + graphic.partRect[verb](merge(partShapeArgs)); + graphic.partialClipRect[verb](merge(clipRectArgs)); + } + else { + graphic.partialClipRect = renderer.clipRect(clipRectArgs.x, clipRectArgs.y, clipRectArgs.width, clipRectArgs.height); + graphic.partRect = + renderer[type](partShapeArgs) + .addClass('highcharts-partfill-overlay') + .add(graphic) + .clip(graphic.partialClipRect); + } + } + // Presentational + if (!series.chart.styledMode) { + graphic + .rect[verb](pointAttr, animation) + .shadow(seriesOpts.shadow, null, cutOff); + if (partShapeArgs) { + // Ensure pfOptions is an object + if (!isObject(pfOptions)) { + pfOptions = {}; + } + if (isObject(seriesOpts.partialFill)) { + pfOptions = merge(pfOptions, seriesOpts.partialFill); + } + fill = (pfOptions.fill || + color(pointAttr.fill).brighten(-0.3).get() || + color(point.color || series.color) + .brighten(-0.3).get()); + pointAttr.fill = fill; + graphic + .partRect[pointStateVerb](pointAttr, animation) + .shadow(seriesOpts.shadow, null, cutOff); + } + } + } + else if (graphic) { + point.graphic = graphic.destroy(); // #1269 + } + }, + /** + * @private + * @function Highcharts.Series#drawPoints + */ + drawPoints: function () { + var series = this, verb = series.getAnimationVerb(); + // Draw the columns + series.points.forEach(function (point) { + series.drawPoint(point, verb); + }); + }, + /** + * Returns "animate", or "attr" if the number of points is above the + * animation limit. + * + * @private + * @function Highcharts.Series#getAnimationVerb + * + * @return {string} + */ + getAnimationVerb: function () { + return (this.chart.pointCount < (this.options.animationLimit || 250) ? + 'animate' : + 'attr'); + } + /* + // Override to remove stroke from points. For partial fill. + pointAttribs: function () { + var series = this, + retVal = columnType.prototype.pointAttribs + .apply(series, arguments); + + //retVal['stroke-width'] = 0; + return retVal; + } + //*/ + /* eslint-enable valid-jsdoc */ + }, { + /** + * The ending X value of the range point. + * @name Highcharts.Point#x2 + * @type {number|undefined} + * @requires modules/xrange + */ + /** + * Extend applyOptions so that `colorByPoint` for x-range means that one + * color is applied per Y axis category. + * + * @private + * @function Highcharts.Point#applyOptions + * + * @return {Highcharts.Series} + */ + /* eslint-disable valid-jsdoc */ + /** + * @private + */ + resolveColor: function () { + var series = this.series, colorByPoint; + if (series.options.colorByPoint && !this.options.color) { + colorByPoint = getColorByCategory(series, this); + if (!series.chart.styledMode) { + this.color = colorByPoint.color; + } + if (!this.options.colorIndex) { + this.colorIndex = colorByPoint.colorIndex; + } + } + else if (!this.color) { + this.color = series.color; + } + }, + /** + * Extend init to have y default to 0. + * + * @private + * @function Highcharts.Point#init + * + * @return {Highcharts.Point} + */ + init: function () { + Point.prototype.init.apply(this, arguments); + if (!this.y) { + this.y = 0; + } + return this; + }, + /** + * @private + * @function Highcharts.Point#setState + */ + setState: function () { + Point.prototype.setState.apply(this, arguments); + this.series.drawPoint(this, this.series.getAnimationVerb()); + }, + /** + * @private + * @function Highcharts.Point#getLabelConfig + * + * @return {Highcharts.PointLabelObject} + */ + // Add x2 and yCategory to the available properties for tooltip formats + getLabelConfig: function () { + var point = this, cfg = Point.prototype.getLabelConfig.call(point), yCats = point.series.yAxis.categories; + cfg.x2 = point.x2; + cfg.yCategory = point.yCategory = yCats && yCats[point.y]; + return cfg; + }, + tooltipDateKeys: ['x', 'x2'], + /** + * @private + * @function Highcharts.Point#isValid + * + * @return {boolean} + */ + isValid: function () { + return typeof this.x === 'number' && + typeof this.x2 === 'number'; + } + /* eslint-enable valid-jsdoc */ + }); + /** + * Max x2 should be considered in xAxis extremes + */ + addEvent(Axis, 'afterGetSeriesExtremes', function () { + var axis = this, // eslint-disable-line no-invalid-this + axisSeries = axis.series, dataMax, modMax; + if (axis.isXAxis) { + dataMax = pick(axis.dataMax, -Number.MAX_VALUE); + axisSeries.forEach(function (series) { + if (series.x2Data) { + series.x2Data + .forEach(function (val) { + if (val > dataMax) { + dataMax = val; + modMax = true; + } + }); + } + }); + if (modMax) { + axis.dataMax = dataMax; + } + } + }); + /** + * An `xrange` series. If the [type](#series.xrange.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.xrange + * @excluding boostThreshold, crisp, cropThreshold, depth, edgeColor, edgeWidth, + * findNearestPointBy, getExtremesFromAll, negativeColor, + * pointInterval, pointIntervalUnit, pointPlacement, pointRange, + * pointStart, softThreshold, stacking, threshold, dataSorting + * @product highcharts highstock gantt + * @requires modules/xrange + * @apioption series.xrange + */ + /** + * An array of data points for the series. For the `xrange` series type, + * points can be given in the following ways: + * + * 1. An array of objects with named values. The objects are point configuration + * objects as seen below. + * ```js + * data: [{ + * x: Date.UTC(2017, 0, 1), + * x2: Date.UTC(2017, 0, 3), + * name: "Test", + * y: 0, + * color: "#00FF00" + * }, { + * x: Date.UTC(2017, 0, 4), + * x2: Date.UTC(2017, 0, 5), + * name: "Deploy", + * y: 1, + * color: "#FF0000" + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @declare Highcharts.XrangePointOptionsObject + * @type {Array<*>} + * @extends series.line.data + * @product highcharts highstock gantt + * @apioption series.xrange.data + */ + /** + * The starting X value of the range point. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range + * + * @type {number} + * @product highcharts highstock gantt + * @apioption series.xrange.data.x + */ + /** + * The ending X value of the range point. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range + * + * @type {number} + * @product highcharts highstock gantt + * @apioption series.xrange.data.x2 + */ + /** + * The Y value of the range point. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range + * + * @type {number} + * @product highcharts highstock gantt + * @apioption series.xrange.data.y + */ + /** + * A partial fill for each point, typically used to visualize how much of + * a task is performed. The partial fill object can be set either on series + * or point level. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range with partial fill + * + * @declare Highcharts.XrangePointPartialFillOptionsObject + * @product highcharts highstock gantt + * @apioption series.xrange.data.partialFill + */ + /** + * The amount of the X-range point to be filled. Values can be 0-1 and are + * converted to percentages in the default data label formatter. + * + * @type {number} + * @product highcharts highstock gantt + * @apioption series.xrange.data.partialFill.amount + */ + /** + * The fill color to be used for partial fills. Defaults to a darker shade + * of the point color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock gantt + * @apioption series.xrange.data.partialFill.fill + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'parts-gantt/GanttSeries.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2016-2020 Highsoft AS + * + * Author: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var isNumber = U.isNumber, merge = U.merge, pick = U.pick, seriesType = U.seriesType, splat = U.splat; + var dateFormat = H.dateFormat, seriesTypes = H.seriesTypes, Series = H.Series, parent = seriesTypes.xrange; + /** + * @private + * @class + * @name Highcharts.seriesTypes.gantt + * + * @augments Highcharts.Series + */ + seriesType('gantt', 'xrange' + /** + * A `gantt` series. If the [type](#series.gantt.type) option is not specified, + * it is inherited from [chart.type](#chart.type). + * + * @extends plotOptions.xrange + * @product gantt + * @requires highcharts-gantt + * @optionparent plotOptions.gantt + */ + , { + // options - default options merged with parent + grouping: false, + dataLabels: { + enabled: true + }, + tooltip: { + headerFormat: '{series.name}
    ', + pointFormat: null, + pointFormatter: function () { + var point = this, series = point.series, tooltip = series.chart.tooltip, xAxis = series.xAxis, formats = series.tooltipOptions.dateTimeLabelFormats, startOfWeek = xAxis.options.startOfWeek, ttOptions = series.tooltipOptions, format = ttOptions.xDateFormat, start, end, milestone = point.options.milestone, retVal = '' + (point.name || point.yCategory) + ''; + if (ttOptions.pointFormat) { + return point.tooltipFormatter(ttOptions.pointFormat); + } + if (!format) { + format = splat(tooltip.getDateFormat(xAxis.closestPointRange, point.start, startOfWeek, formats))[0]; + } + start = dateFormat(format, point.start); + end = dateFormat(format, point.end); + retVal += '
    '; + if (!milestone) { + retVal += 'Start: ' + start + '
    '; + retVal += 'End: ' + end + '
    '; + } + else { + retVal += start + '
    '; + } + return retVal; + } + }, + connectors: { + type: 'simpleConnect', + /** + * @declare Highcharts.ConnectorsAnimationOptionsObject + */ + animation: { + reversed: true // Dependencies go from child to parent + }, + startMarker: { + enabled: true, + symbol: 'arrow-filled', + radius: 4, + fill: '#fa0', + align: 'left' + }, + endMarker: { + enabled: false, + align: 'right' + } + } + }, { + pointArrayMap: ['start', 'end', 'y'], + // Keyboard navigation, don't use nearest vertical mode + keyboardMoveVertical: false, + /* eslint-disable valid-jsdoc */ + /** + * Handle milestones, as they have no x2. + * @private + */ + translatePoint: function (point) { + var series = this, shapeArgs, size; + parent.prototype.translatePoint.call(series, point); + if (point.options.milestone) { + shapeArgs = point.shapeArgs; + size = shapeArgs.height; + point.shapeArgs = { + x: shapeArgs.x - (size / 2), + y: shapeArgs.y, + width: size, + height: size + }; + } + }, + /** + * Draws a single point in the series. + * + * This override draws the point as a diamond if point.options.milestone + * is true, and uses the original drawPoint() if it is false or not set. + * + * @requires highcharts-gantt + * + * @private + * @function Highcharts.seriesTypes.gantt#drawPoint + * + * @param {Highcharts.Point} point + * An instance of Point in the series + * + * @param {"animate"|"attr"} verb + * 'animate' (animates changes) or 'attr' (sets options) + * + * @return {void} + */ + drawPoint: function (point, verb) { + var series = this, seriesOpts = series.options, renderer = series.chart.renderer, shapeArgs = point.shapeArgs, plotY = point.plotY, graphic = point.graphic, state = point.selected && 'select', cutOff = seriesOpts.stacking && !seriesOpts.borderRadius, diamondShape; + if (point.options.milestone) { + if (isNumber(plotY) && point.y !== null && point.visible !== false) { + diamondShape = renderer.symbols.diamond(shapeArgs.x, shapeArgs.y, shapeArgs.width, shapeArgs.height); + if (graphic) { + graphic[verb]({ + d: diamondShape + }); + } + else { + point.graphic = graphic = renderer.path(diamondShape) + .addClass(point.getClassName(), true) + .add(point.group || series.group); + } + // Presentational + if (!series.chart.styledMode) { + point.graphic + .attr(series.pointAttribs(point, state)) + .shadow(seriesOpts.shadow, null, cutOff); + } + } + else if (graphic) { + point.graphic = graphic.destroy(); // #1269 + } + } + else { + parent.prototype.drawPoint.call(series, point, verb); + } + }, + setData: Series.prototype.setData, + /** + * @private + */ + setGanttPointAliases: function (options) { + /** + * Add a value to options if the value exists. + * @private + */ + function addIfExists(prop, val) { + if (typeof val !== 'undefined') { + options[prop] = val; + } + } + addIfExists('x', pick(options.start, options.x)); + addIfExists('x2', pick(options.end, options.x2)); + addIfExists('partialFill', pick(options.completed, options.partialFill)); + addIfExists('connect', pick(options.dependency, options.connect)); + } + /* eslint-enable valid-jsdoc */ + }, merge(parent.prototype.pointClass.prototype, { + // pointProps - point member overrides. We inherit from parent as well. + /* eslint-disable valid-jsdoc */ + /** + * Applies the options containing the x and y data and possible some + * extra properties. This is called on point init or from point.update. + * + * @private + * @function Highcharts.Point#applyOptions + * + * @param {object} options + * The point options + * + * @param {number} x + * The x value + * + * @return {Highcharts.Point} + * The Point instance + */ + applyOptions: function (options, x) { + var point = this, retVal = merge(options); + H.seriesTypes.gantt.prototype.setGanttPointAliases(retVal); + retVal = parent.prototype.pointClass.prototype.applyOptions + .call(point, retVal, x); + return retVal; + }, + isValid: function () { + return ((typeof this.start === 'number' || + typeof this.x === 'number') && + (typeof this.end === 'number' || + typeof this.x2 === 'number' || + this.milestone)); + } + /* eslint-enable valid-jsdoc */ + })); + /** + * A `gantt` series. + * + * @extends series,plotOptions.gantt + * @excluding boostThreshold, connectors, dashStyle, findNearestPointBy, + * getExtremesFromAll, marker, negativeColor, pointInterval, + * pointIntervalUnit, pointPlacement, pointStart + * @product gantt + * @requires highcharts-gantt + * @apioption series.gantt + */ + /** + * Data for a Gantt series. + * + * @declare Highcharts.GanttPointOptionsObject + * @type {Array<*>} + * @extends series.xrange.data + * @excluding className, color, colorIndex, connect, dataLabels, events, id, + * partialFill, selected, x, x2 + * @product gantt + * @apioption series.gantt.data + */ + /** + * Whether the grid node belonging to this point should start as collapsed. Used + * in axes of type treegrid. + * + * @sample {gantt} gantt/treegrid-axis/collapsed/ + * Start as collapsed + * + * @type {boolean} + * @default false + * @product gantt + * @apioption series.gantt.data.collapsed + */ + /** + * The start time of a task. + * + * @type {number} + * @product gantt + * @apioption series.gantt.data.start + */ + /** + * The end time of a task. + * + * @type {number} + * @product gantt + * @apioption series.gantt.data.end + */ + /** + * The Y value of a task. + * + * @type {number} + * @product gantt + * @apioption series.gantt.data.y + */ + /** + * The name of a task. If a `treegrid` y-axis is used (default in Gantt charts), + * this will be picked up automatically, and used to calculate the y-value. + * + * @type {string} + * @product gantt + * @apioption series.gantt.data.name + */ + /** + * Progress indicator, how much of the task completed. If it is a number, the + * `fill` will be applied automatically. + * + * @sample {gantt} gantt/demo/progress-indicator + * Progress indicator + * + * @type {number|*} + * @extends series.xrange.data.partialFill + * @product gantt + * @apioption series.gantt.data.completed + */ + /** + * The amount of the progress indicator, ranging from 0 (not started) to 1 + * (finished). + * + * @type {number} + * @default 0 + * @apioption series.gantt.data.completed.amount + */ + /** + * The fill of the progress indicator. Defaults to a darkened variety of the + * main color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption series.gantt.data.completed.fill + */ + /** + * The ID of the point (task) that this point depends on in Gantt charts. + * Aliases [connect](series.xrange.data.connect). Can also be an object, + * specifying further connecting [options](series.gantt.connectors) between the + * points. Multiple connections can be specified by providing an array. + * + * @sample gantt/demo/project-management + * Dependencies + * @sample gantt/pathfinder/demo + * Different connection types + * + * @type {string|Array|*} + * @extends series.xrange.data.connect + * @since 6.2.0 + * @product gantt + * @apioption series.gantt.data.dependency + */ + /** + * Whether this point is a milestone. If so, only the `start` option is handled, + * while `end` is ignored. + * + * @sample gantt/gantt/milestones + * Milestones + * + * @type {boolean} + * @since 6.2.0 + * @product gantt + * @apioption series.gantt.data.milestone + */ + /** + * The ID of the parent point (task) of this point in Gantt charts. + * + * @sample gantt/demo/subtasks + * Gantt chart with subtasks + * + * @type {string} + * @since 6.2.0 + * @product gantt + * @apioption series.gantt.data.parent + */ + /** + * @excluding afterAnimate + * @apioption series.gantt.events + */ + ''; // adds doclets above to the transpiled file + + }); + _registerModule(_modules, 'parts-gantt/GanttChart.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2016-2020 Highsoft AS + * + * Author: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var isArray = U.isArray, merge = U.merge, splat = U.splat; + var Chart = H.Chart; + /** + * Factory function for Gantt charts. + * + * @example + * // Render a chart in to div#container + * var chart = Highcharts.ganttChart('container', { + * title: { + * text: 'My chart' + * }, + * series: [{ + * data: ... + * }] + * }); + * + * @function Highcharts.ganttChart + * + * @param {string|Highcharts.HTMLDOMElement} renderTo + * The DOM element to render to, or its id. + * + * @param {Highcharts.Options} options + * The chart options structure. + * + * @param {Highcharts.ChartCallbackFunction} [callback] + * Function to run when the chart has loaded and and all external images + * are loaded. Defining a + * [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load) + * handler is equivalent. + * + * @return {Highcharts.Chart} + * Returns the Chart object. + */ + H.ganttChart = function (renderTo, options, callback) { + var hasRenderToArg = typeof renderTo === 'string' || renderTo.nodeName, seriesOptions = options.series, defaultOptions = H.getOptions(), defaultLinkedTo, userOptions = options; + options = arguments[hasRenderToArg ? 1 : 0]; + // If user hasn't defined axes as array, make it into an array and add a + // second axis by default. + if (!isArray(options.xAxis)) { + options.xAxis = [options.xAxis || {}, {}]; + } + // apply X axis options to both single and multi x axes + options.xAxis = options.xAxis.map(function (xAxisOptions, i) { + if (i === 1) { // Second xAxis + defaultLinkedTo = 0; + } + return merge(defaultOptions.xAxis, { + grid: { + enabled: true + }, + opposite: true, + linkedTo: defaultLinkedTo + }, xAxisOptions, // user options + { + type: 'datetime' + }); + }); + // apply Y axis options to both single and multi y axes + options.yAxis = (splat(options.yAxis || {})).map(function (yAxisOptions) { + return merge(defaultOptions.yAxis, // #3802 + { + grid: { + enabled: true + }, + staticScale: 50, + reversed: true, + // Set default type treegrid, but only if 'categories' is + // undefined + type: yAxisOptions.categories ? yAxisOptions.type : 'treegrid' + }, yAxisOptions // user options + ); + }); + options.series = null; + options = merge(true, { + chart: { + type: 'gantt' + }, + title: { + text: null + }, + legend: { + enabled: false + } + }, options, // user's options + // forced options + { + isGantt: true + }); + options.series = userOptions.series = seriesOptions; + options.series.forEach(function (series) { + series.data.forEach(function (point) { + H.seriesTypes.gantt.prototype.setGanttPointAliases(point); + }); + }); + return hasRenderToArg ? + new Chart(renderTo, options, callback) : + new Chart(options, options); // @todo does not look correct + }; + + }); + _registerModule(_modules, 'parts/ScrollbarAxis.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, defined = U.defined, pick = U.pick; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Creates scrollbars if enabled. + * + * @private + */ + var ScrollbarAxis = /** @class */ (function () { + function ScrollbarAxis() { + } + /** + * Attaches to axis events to create scrollbars if enabled. + * + * @private + * + * @param AxisClass + * Axis class to extend. + * + * @param ScrollbarClass + * Scrollbar class to use. + */ + ScrollbarAxis.compose = function (AxisClass, ScrollbarClass) { + // Wrap axis initialization and create scrollbar if enabled: + addEvent(AxisClass, 'afterInit', function () { + var axis = this; + if (axis.options && + axis.options.scrollbar && + axis.options.scrollbar.enabled) { + // Predefined options: + axis.options.scrollbar.vertical = !axis.horiz; + axis.options.startOnTick = axis.options.endOnTick = false; + axis.scrollbar = new ScrollbarClass(axis.chart.renderer, axis.options.scrollbar, axis.chart); + addEvent(axis.scrollbar, 'changed', function (e) { + var axisMin = pick(axis.options && axis.options.min, axis.min), axisMax = pick(axis.options && axis.options.max, axis.max), unitedMin = defined(axis.dataMin) ? + Math.min(axisMin, axis.min, axis.dataMin) : axisMin, unitedMax = defined(axis.dataMax) ? + Math.max(axisMax, axis.max, axis.dataMax) : axisMax, range = unitedMax - unitedMin, to, from; + // #12834, scroll when show/hide series, wrong extremes + if (!defined(axisMin) || !defined(axisMax)) { + return; + } + if ((axis.horiz && !axis.reversed) || + (!axis.horiz && axis.reversed)) { + to = unitedMin + range * this.to; + from = unitedMin + range * this.from; + } + else { + // y-values in browser are reversed, but this also + // applies for reversed horizontal axis: + to = unitedMin + range * (1 - this.from); + from = unitedMin + range * (1 - this.to); + } + if (pick(this.options.liveRedraw, H.svg && !H.isTouchDevice && !this.chart.isBoosting) || + // Mouseup always should change extremes + e.DOMType === 'mouseup' || + // Internal events + !defined(e.DOMType)) { + axis.setExtremes(from, to, true, e.DOMType !== 'mousemove', e); + } + else { + // When live redraw is disabled, don't change extremes + // Only change the position of the scollbar thumb + this.setRange(this.from, this.to); + } + }); + } + }); + // Wrap rendering axis, and update scrollbar if one is created: + addEvent(AxisClass, 'afterRender', function () { + var axis = this, scrollMin = Math.min(pick(axis.options.min, axis.min), axis.min, pick(axis.dataMin, axis.min) // #6930 + ), scrollMax = Math.max(pick(axis.options.max, axis.max), axis.max, pick(axis.dataMax, axis.max) // #6930 + ), scrollbar = axis.scrollbar, offset = axis.axisTitleMargin + (axis.titleOffset || 0), scrollbarsOffsets = axis.chart.scrollbarsOffsets, axisMargin = axis.options.margin || 0, offsetsIndex, from, to; + if (scrollbar) { + if (axis.horiz) { + // Reserve space for labels/title + if (!axis.opposite) { + scrollbarsOffsets[1] += offset; + } + scrollbar.position(axis.left, axis.top + axis.height + 2 + scrollbarsOffsets[1] - + (axis.opposite ? axisMargin : 0), axis.width, axis.height); + // Next scrollbar should reserve space for margin (if set) + if (!axis.opposite) { + scrollbarsOffsets[1] += axisMargin; + } + offsetsIndex = 1; + } + else { + // Reserve space for labels/title + if (axis.opposite) { + scrollbarsOffsets[0] += offset; + } + scrollbar.position(axis.left + axis.width + 2 + scrollbarsOffsets[0] - + (axis.opposite ? 0 : axisMargin), axis.top, axis.width, axis.height); + // Next scrollbar should reserve space for margin (if set) + if (axis.opposite) { + scrollbarsOffsets[0] += axisMargin; + } + offsetsIndex = 0; + } + scrollbarsOffsets[offsetsIndex] += scrollbar.size + + scrollbar.options.margin; + if (isNaN(scrollMin) || + isNaN(scrollMax) || + !defined(axis.min) || + !defined(axis.max) || + axis.min === axis.max // #10733 + ) { + // default action: when extremes are the same or there is + // not extremes on the axis, but scrollbar exists, make it + // full size + scrollbar.setRange(0, 1); + } + else { + from = + (axis.min - scrollMin) / (scrollMax - scrollMin); + to = + (axis.max - scrollMin) / (scrollMax - scrollMin); + if ((axis.horiz && !axis.reversed) || + (!axis.horiz && axis.reversed)) { + scrollbar.setRange(from, to); + } + else { + // inverse vertical axis + scrollbar.setRange(1 - to, 1 - from); + } + } + } + }); + // Make space for a scrollbar: + addEvent(AxisClass, 'afterGetOffset', function () { + var axis = this, index = axis.horiz ? 2 : 1, scrollbar = axis.scrollbar; + if (scrollbar) { + axis.chart.scrollbarsOffsets = [0, 0]; // reset scrollbars offsets + axis.chart.axisOffset[index] += + scrollbar.size + scrollbar.options.margin; + } + }); + }; + return ScrollbarAxis; + }()); + + return ScrollbarAxis; + }); + _registerModule(_modules, 'parts/Scrollbar.js', [_modules['parts/Axis.js'], _modules['parts/Globals.js'], _modules['parts/ScrollbarAxis.js'], _modules['parts/Utilities.js']], function (Axis, H, ScrollbarAxis, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, correctFloat = U.correctFloat, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, fireEvent = U.fireEvent, merge = U.merge, pick = U.pick, removeEvent = U.removeEvent; + var defaultOptions = H.defaultOptions, hasTouch = H.hasTouch, isTouchDevice = H.isTouchDevice; + /** + * When we have vertical scrollbar, rifles and arrow in buttons should be + * rotated. The same method is used in Navigator's handles, to rotate them. + * + * @function Highcharts.swapXY + * + * @param {Highcharts.SVGPathArray} path + * Path to be rotated. + * + * @param {boolean} [vertical] + * If vertical scrollbar, swap x-y values. + * + * @return {Highcharts.SVGPathArray} + * Rotated path. + * + * @requires modules/stock + */ + var swapXY = H.swapXY = function (path, vertical) { + if (vertical) { + path.forEach(function (seg) { + var len = seg.length; + var temp; + for (var i = 0; i < len; i += 2) { + temp = seg[i + 1]; + if (typeof temp === 'number') { + seg[i + 1] = seg[i + 2]; + seg[i + 2] = temp; + } + } + }); + } + return path; + }; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * A reusable scrollbar, internally used in Highstock's navigator and optionally + * on individual axes. + * + * @private + * @class + * @name Highcharts.Scrollbar + * @param {Highcharts.SVGRenderer} renderer + * @param {Highcharts.ScrollbarOptions} options + * @param {Highcharts.Chart} chart + */ + var Scrollbar = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function Scrollbar(renderer, options, chart) { + /* * + * + * Properties + * + * */ + this._events = []; + this.chartX = 0; + this.chartY = 0; + this.from = 0; + this.group = void 0; + this.scrollbar = void 0; + this.scrollbarButtons = []; + this.scrollbarGroup = void 0; + this.scrollbarLeft = 0; + this.scrollbarRifles = void 0; + this.scrollbarStrokeWidth = 1; + this.scrollbarTop = 0; + this.size = 0; + this.to = 0; + this.track = void 0; + this.trackBorderWidth = 1; + this.userOptions = {}; + this.x = 0; + this.y = 0; + this.chart = chart; + this.options = options; + this.renderer = chart.renderer; + this.init(renderer, options, chart); + } + /* * + * + * Functions + * + * */ + /** + * Set up the mouse and touch events for the Scrollbar + * + * @private + * @function Highcharts.Scrollbar#addEvents + * @return {void} + */ + Scrollbar.prototype.addEvents = function () { + var buttonsOrder = this.options.inverted ? [1, 0] : [0, 1], buttons = this.scrollbarButtons, bar = this.scrollbarGroup.element, track = this.track.element, mouseDownHandler = this.mouseDownHandler.bind(this), mouseMoveHandler = this.mouseMoveHandler.bind(this), mouseUpHandler = this.mouseUpHandler.bind(this), _events; + // Mouse events + _events = [ + [buttons[buttonsOrder[0]].element, 'click', this.buttonToMinClick.bind(this)], + [buttons[buttonsOrder[1]].element, 'click', this.buttonToMaxClick.bind(this)], + [track, 'click', this.trackClick.bind(this)], + [bar, 'mousedown', mouseDownHandler], + [bar.ownerDocument, 'mousemove', mouseMoveHandler], + [bar.ownerDocument, 'mouseup', mouseUpHandler] + ]; + // Touch events + if (hasTouch) { + _events.push([bar, 'touchstart', mouseDownHandler], [bar.ownerDocument, 'touchmove', mouseMoveHandler], [bar.ownerDocument, 'touchend', mouseUpHandler]); + } + // Add them all + _events.forEach(function (args) { + addEvent.apply(null, args); + }); + this._events = _events; + }; + Scrollbar.prototype.buttonToMaxClick = function (e) { + var scroller = this; + var range = (scroller.to - scroller.from) * pick(scroller.options.step, 0.2); + scroller.updatePosition(scroller.from + range, scroller.to + range); + fireEvent(scroller, 'changed', { + from: scroller.from, + to: scroller.to, + trigger: 'scrollbar', + DOMEvent: e + }); + }; + Scrollbar.prototype.buttonToMinClick = function (e) { + var scroller = this; + var range = correctFloat(scroller.to - scroller.from) * + pick(scroller.options.step, 0.2); + scroller.updatePosition(correctFloat(scroller.from - range), correctFloat(scroller.to - range)); + fireEvent(scroller, 'changed', { + from: scroller.from, + to: scroller.to, + trigger: 'scrollbar', + DOMEvent: e + }); + }; + /** + * Get normalized (0-1) cursor position over the scrollbar + * + * @private + * @function Highcharts.Scrollbar#cursorToScrollbarPosition + * + * @param {*} normalizedEvent + * normalized event, with chartX and chartY values + * + * @return {Highcharts.Dictionary} + * Local position {chartX, chartY} + */ + Scrollbar.prototype.cursorToScrollbarPosition = function (normalizedEvent) { + var scroller = this, options = scroller.options, minWidthDifference = options.minWidth > scroller.calculatedWidth ? + options.minWidth : + 0; // minWidth distorts translation + return { + chartX: (normalizedEvent.chartX - scroller.x - + scroller.xOffset) / + (scroller.barWidth - minWidthDifference), + chartY: (normalizedEvent.chartY - scroller.y - + scroller.yOffset) / + (scroller.barWidth - minWidthDifference) + }; + }; + /** + * Destroys allocated elements. + * + * @private + * @function Highcharts.Scrollbar#destroy + * @return {void} + */ + Scrollbar.prototype.destroy = function () { + var scroller = this.chart.scroller; + // Disconnect events added in addEvents + this.removeEvents(); + // Destroy properties + [ + 'track', + 'scrollbarRifles', + 'scrollbar', + 'scrollbarGroup', + 'group' + ].forEach(function (prop) { + if (this[prop] && this[prop].destroy) { + this[prop] = this[prop].destroy(); + } + }, this); + // #6421, chart may have more scrollbars + if (scroller && this === scroller.scrollbar) { + scroller.scrollbar = null; + // Destroy elements in collection + destroyObjectProperties(scroller.scrollbarButtons); + } + }; + /** + * Draw the scrollbar buttons with arrows + * + * @private + * @function Highcharts.Scrollbar#drawScrollbarButton + * @param {number} index + * 0 is left, 1 is right + * @return {void} + */ + Scrollbar.prototype.drawScrollbarButton = function (index) { + var scroller = this, renderer = scroller.renderer, scrollbarButtons = scroller.scrollbarButtons, options = scroller.options, size = scroller.size, group, tempElem; + group = renderer.g().add(scroller.group); + scrollbarButtons.push(group); + // Create a rectangle for the scrollbar button + tempElem = renderer.rect() + .addClass('highcharts-scrollbar-button') + .add(group); + // Presentational attributes + if (!this.chart.styledMode) { + tempElem.attr({ + stroke: options.buttonBorderColor, + 'stroke-width': options.buttonBorderWidth, + fill: options.buttonBackgroundColor + }); + } + // Place the rectangle based on the rendered stroke width + tempElem.attr(tempElem.crisp({ + x: -0.5, + y: -0.5, + width: size + 1, + height: size + 1, + r: options.buttonBorderRadius + }, tempElem.strokeWidth())); + // Button arrow + tempElem = renderer + .path(swapXY([[ + 'M', + size / 2 + (index ? -1 : 1), + size / 2 - 3 + ], [ + 'L', + size / 2 + (index ? -1 : 1), + size / 2 + 3 + ], [ + 'L', + size / 2 + (index ? 2 : -2), + size / 2 + ]], options.vertical)) + .addClass('highcharts-scrollbar-arrow') + .add(scrollbarButtons[index]); + if (!this.chart.styledMode) { + tempElem.attr({ + fill: options.buttonArrowColor + }); + } + }; + /** + * @private + * @function Highcharts.Scrollbar#init + * @param {Highcharts.SVGRenderer} renderer + * @param {Highcharts.ScrollbarOptions} options + * @param {Highcharts.Chart} chart + */ + Scrollbar.prototype.init = function (renderer, options, chart) { + this.scrollbarButtons = []; + this.renderer = renderer; + this.userOptions = options; + this.options = merge(Scrollbar.defaultOptions, options); + this.chart = chart; + // backward compatibility + this.size = pick(this.options.size, this.options.height); + // Init + if (options.enabled) { + this.render(); + this.addEvents(); + } + }; + Scrollbar.prototype.mouseDownHandler = function (e) { + var scroller = this; + var normalizedEvent = scroller.chart.pointer.normalize(e), mousePosition = scroller.cursorToScrollbarPosition(normalizedEvent); + scroller.chartX = mousePosition.chartX; + scroller.chartY = mousePosition.chartY; + scroller.initPositions = [scroller.from, scroller.to]; + scroller.grabbedCenter = true; + }; + /** + * Event handler for the mouse move event. + * @private + */ + Scrollbar.prototype.mouseMoveHandler = function (e) { + var scroller = this; + var normalizedEvent = scroller.chart.pointer.normalize(e), options = scroller.options, direction = options.vertical ? 'chartY' : 'chartX', initPositions = scroller.initPositions || [], scrollPosition, chartPosition, change; + // In iOS, a mousemove event with e.pageX === 0 is fired when + // holding the finger down in the center of the scrollbar. This + // should be ignored. + if (scroller.grabbedCenter && + // #4696, scrollbar failed on Android + (!e.touches || e.touches[0][direction] !== 0)) { + chartPosition = scroller.cursorToScrollbarPosition(normalizedEvent)[direction]; + scrollPosition = scroller[direction]; + change = chartPosition - scrollPosition; + scroller.hasDragged = true; + scroller.updatePosition(initPositions[0] + change, initPositions[1] + change); + if (scroller.hasDragged) { + fireEvent(scroller, 'changed', { + from: scroller.from, + to: scroller.to, + trigger: 'scrollbar', + DOMType: e.type, + DOMEvent: e + }); + } + } + }; + /** + * Event handler for the mouse up event. + * @private + */ + Scrollbar.prototype.mouseUpHandler = function (e) { + var scroller = this; + if (scroller.hasDragged) { + fireEvent(scroller, 'changed', { + from: scroller.from, + to: scroller.to, + trigger: 'scrollbar', + DOMType: e.type, + DOMEvent: e + }); + } + scroller.grabbedCenter = + scroller.hasDragged = + scroller.chartX = + scroller.chartY = null; + }; + /** + * Position the scrollbar, method called from a parent with defined + * dimensions. + * + * @private + * @function Highcharts.Scrollbar#position + * @param {number} x + * x-position on the chart + * @param {number} y + * y-position on the chart + * @param {number} width + * width of the scrollbar + * @param {number} height + * height of the scorllbar + * @return {void} + */ + Scrollbar.prototype.position = function (x, y, width, height) { + var scroller = this, options = scroller.options, vertical = options.vertical, xOffset = height, yOffset = 0, method = scroller.rendered ? 'animate' : 'attr'; + scroller.x = x; + scroller.y = y + this.trackBorderWidth; + scroller.width = width; // width with buttons + scroller.height = height; + scroller.xOffset = xOffset; + scroller.yOffset = yOffset; + // If Scrollbar is a vertical type, swap options: + if (vertical) { + scroller.width = scroller.yOffset = width = yOffset = scroller.size; + scroller.xOffset = xOffset = 0; + scroller.barWidth = height - width * 2; // width without buttons + scroller.x = x = x + scroller.options.margin; + } + else { + scroller.height = scroller.xOffset = height = xOffset = + scroller.size; + scroller.barWidth = width - height * 2; // width without buttons + scroller.y = scroller.y + scroller.options.margin; + } + // Set general position for a group: + scroller.group[method]({ + translateX: x, + translateY: scroller.y + }); + // Resize background/track: + scroller.track[method]({ + width: width, + height: height + }); + // Move right/bottom button ot it's place: + scroller.scrollbarButtons[1][method]({ + translateX: vertical ? 0 : width - xOffset, + translateY: vertical ? height - yOffset : 0 + }); + }; + /** + * Removes the event handlers attached previously with addEvents. + * + * @private + * @function Highcharts.Scrollbar#removeEvents + * @return {void} + */ + Scrollbar.prototype.removeEvents = function () { + this._events.forEach(function (args) { + removeEvent.apply(null, args); + }); + this._events.length = 0; + }; + /** + * Render scrollbar with all required items. + * + * @private + * @function Highcharts.Scrollbar#render + */ + Scrollbar.prototype.render = function () { + var scroller = this, renderer = scroller.renderer, options = scroller.options, size = scroller.size, styledMode = this.chart.styledMode, group; + // Draw the scrollbar group + scroller.group = group = renderer.g('scrollbar').attr({ + zIndex: options.zIndex, + translateY: -99999 + }).add(); + // Draw the scrollbar track: + scroller.track = renderer.rect() + .addClass('highcharts-scrollbar-track') + .attr({ + x: 0, + r: options.trackBorderRadius || 0, + height: size, + width: size + }).add(group); + if (!styledMode) { + scroller.track.attr({ + fill: options.trackBackgroundColor, + stroke: options.trackBorderColor, + 'stroke-width': options.trackBorderWidth + }); + } + this.trackBorderWidth = scroller.track.strokeWidth(); + scroller.track.attr({ + y: -this.trackBorderWidth % 2 / 2 + }); + // Draw the scrollbar itself + scroller.scrollbarGroup = renderer.g().add(group); + scroller.scrollbar = renderer.rect() + .addClass('highcharts-scrollbar-thumb') + .attr({ + height: size, + width: size, + r: options.barBorderRadius || 0 + }).add(scroller.scrollbarGroup); + scroller.scrollbarRifles = renderer + .path(swapXY([ + ['M', -3, size / 4], + ['L', -3, 2 * size / 3], + ['M', 0, size / 4], + ['L', 0, 2 * size / 3], + ['M', 3, size / 4], + ['L', 3, 2 * size / 3] + ], options.vertical)) + .addClass('highcharts-scrollbar-rifles') + .add(scroller.scrollbarGroup); + if (!styledMode) { + scroller.scrollbar.attr({ + fill: options.barBackgroundColor, + stroke: options.barBorderColor, + 'stroke-width': options.barBorderWidth + }); + scroller.scrollbarRifles.attr({ + stroke: options.rifleColor, + 'stroke-width': 1 + }); + } + scroller.scrollbarStrokeWidth = scroller.scrollbar.strokeWidth(); + scroller.scrollbarGroup.translate(-scroller.scrollbarStrokeWidth % 2 / 2, -scroller.scrollbarStrokeWidth % 2 / 2); + // Draw the buttons: + scroller.drawScrollbarButton(0); + scroller.drawScrollbarButton(1); + }; + /** + * Set scrollbar size, with a given scale. + * + * @private + * @function Highcharts.Scrollbar#setRange + * @param {number} from + * scale (0-1) where bar should start + * @param {number} to + * scale (0-1) where bar should end + * @return {void} + */ + Scrollbar.prototype.setRange = function (from, to) { + var scroller = this, options = scroller.options, vertical = options.vertical, minWidth = options.minWidth, fullWidth = scroller.barWidth, fromPX, toPX, newPos, newSize, newRiflesPos, method = (this.rendered && + !this.hasDragged && + !(this.chart.navigator && this.chart.navigator.hasDragged)) ? 'animate' : 'attr'; + if (!defined(fullWidth)) { + return; + } + from = Math.max(from, 0); + fromPX = Math.ceil(fullWidth * from); + toPX = fullWidth * Math.min(to, 1); + scroller.calculatedWidth = newSize = correctFloat(toPX - fromPX); + // We need to recalculate position, if minWidth is used + if (newSize < minWidth) { + fromPX = (fullWidth - minWidth + newSize) * from; + newSize = minWidth; + } + newPos = Math.floor(fromPX + scroller.xOffset + scroller.yOffset); + newRiflesPos = newSize / 2 - 0.5; // -0.5 -> rifle line width / 2 + // Store current position: + scroller.from = from; + scroller.to = to; + if (!vertical) { + scroller.scrollbarGroup[method]({ + translateX: newPos + }); + scroller.scrollbar[method]({ + width: newSize + }); + scroller.scrollbarRifles[method]({ + translateX: newRiflesPos + }); + scroller.scrollbarLeft = newPos; + scroller.scrollbarTop = 0; + } + else { + scroller.scrollbarGroup[method]({ + translateY: newPos + }); + scroller.scrollbar[method]({ + height: newSize + }); + scroller.scrollbarRifles[method]({ + translateY: newRiflesPos + }); + scroller.scrollbarTop = newPos; + scroller.scrollbarLeft = 0; + } + if (newSize <= 12) { + scroller.scrollbarRifles.hide(); + } + else { + scroller.scrollbarRifles.show(true); + } + // Show or hide the scrollbar based on the showFull setting + if (options.showFull === false) { + if (from <= 0 && to >= 1) { + scroller.group.hide(); + } + else { + scroller.group.show(); + } + } + scroller.rendered = true; + }; + Scrollbar.prototype.trackClick = function (e) { + var scroller = this; + var normalizedEvent = scroller.chart.pointer.normalize(e), range = scroller.to - scroller.from, top = scroller.y + scroller.scrollbarTop, left = scroller.x + scroller.scrollbarLeft; + if ((scroller.options.vertical && normalizedEvent.chartY > top) || + (!scroller.options.vertical && normalizedEvent.chartX > left)) { + // On the top or on the left side of the track: + scroller.updatePosition(scroller.from + range, scroller.to + range); + } + else { + // On the bottom or the right side of the track: + scroller.updatePosition(scroller.from - range, scroller.to - range); + } + fireEvent(scroller, 'changed', { + from: scroller.from, + to: scroller.to, + trigger: 'scrollbar', + DOMEvent: e + }); + }; + /** + * Update the scrollbar with new options + * + * @private + * @function Highcharts.Scrollbar#update + * @param {Highcharts.ScrollbarOptions} options + * @return {void} + */ + Scrollbar.prototype.update = function (options) { + this.destroy(); + this.init(this.chart.renderer, merge(true, this.options, options), this.chart); + }; + /** + * Update position option in the Scrollbar, with normalized 0-1 scale + * + * @private + * @function Highcharts.Scrollbar#updatePosition + * @param {number} from + * @param {number} to + * @return {void} + */ + Scrollbar.prototype.updatePosition = function (from, to) { + if (to > 1) { + from = correctFloat(1 - correctFloat(to - from)); + to = 1; + } + if (from < 0) { + to = correctFloat(to - from); + from = 0; + } + this.from = from; + this.to = to; + }; + /* * + * + * Static Properties + * + * */ + /** + * + * The scrollbar is a means of panning over the X axis of a stock chart. + * Scrollbars can also be applied to other types of axes. + * + * Another approach to scrollable charts is the [chart.scrollablePlotArea]( + * https://api.highcharts.com/highcharts/chart.scrollablePlotArea) option that + * is especially suitable for simpler cartesian charts on mobile. + * + * In styled mode, all the presentational options for the + * scrollbar are replaced by the classes `.highcharts-scrollbar-thumb`, + * `.highcharts-scrollbar-arrow`, `.highcharts-scrollbar-button`, + * `.highcharts-scrollbar-rifles` and `.highcharts-scrollbar-track`. + * + * @sample stock/yaxis/inverted-bar-scrollbar/ + * A scrollbar on a simple bar chart + * + * @product highstock gantt + * @optionparent scrollbar + * + * @private + */ + Scrollbar.defaultOptions = { + /** + * The height of the scrollbar. The height also applies to the width + * of the scroll arrows so that they are always squares. Defaults to + * 20 for touch devices and 14 for mouse devices. + * + * @sample stock/scrollbar/height/ + * A 30px scrollbar + * + * @type {number} + * @default 20/14 + */ + height: isTouchDevice ? 20 : 14, + /** + * The border rounding radius of the bar. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + */ + barBorderRadius: 0, + /** + * The corner radius of the scrollbar buttons. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + */ + buttonBorderRadius: 0, + /** + * Enable or disable the scrollbar. + * + * @sample stock/scrollbar/enabled/ + * Disable the scrollbar, only use navigator + * + * @type {boolean} + * @default true + * @apioption scrollbar.enabled + */ + /** + * Whether to redraw the main chart as the scrollbar or the navigator + * zoomed window is moved. Defaults to `true` for modern browsers and + * `false` for legacy IE browsers as well as mobile devices. + * + * @sample stock/scrollbar/liveredraw + * Setting live redraw to false + * + * @type {boolean} + * @since 1.3 + */ + liveRedraw: void 0, + /** + * The margin between the scrollbar and its axis when the scrollbar is + * applied directly to an axis. + */ + margin: 10, + /** + * The minimum width of the scrollbar. + * + * @since 1.2.5 + */ + minWidth: 6, + /** + * Whether to show or hide the scrollbar when the scrolled content is + * zoomed out to it full extent. + * + * @type {boolean} + * @default true + * @apioption scrollbar.showFull + */ + step: 0.2, + /** + * The z index of the scrollbar group. + */ + zIndex: 3, + /** + * The background color of the scrollbar itself. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + barBackgroundColor: '#cccccc', + /** + * The width of the bar's border. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + */ + barBorderWidth: 1, + /** + * The color of the scrollbar's border. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + barBorderColor: '#cccccc', + /** + * The color of the small arrow inside the scrollbar buttons. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + buttonArrowColor: '#333333', + /** + * The color of scrollbar buttons. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + buttonBackgroundColor: '#e6e6e6', + /** + * The color of the border of the scrollbar buttons. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + buttonBorderColor: '#cccccc', + /** + * The border width of the scrollbar buttons. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + */ + buttonBorderWidth: 1, + /** + * The color of the small rifles in the middle of the scrollbar. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + rifleColor: '#333333', + /** + * The color of the track background. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + trackBackgroundColor: '#f2f2f2', + /** + * The color of the border of the scrollbar track. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + trackBorderColor: '#f2f2f2', + /** + * The corner radius of the border of the scrollbar track. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + * + * @type {number} + * @default 0 + * @apioption scrollbar.trackBorderRadius + */ + /** + * The width of the border of the scrollbar track. + * + * @sample stock/scrollbar/style/ + * Scrollbar styling + */ + trackBorderWidth: 1 + }; + return Scrollbar; + }()); + if (!H.Scrollbar) { + defaultOptions.scrollbar = merge(true, Scrollbar.defaultOptions, defaultOptions.scrollbar); + H.Scrollbar = Scrollbar; + ScrollbarAxis.compose(Axis, Scrollbar); + } + + return H.Scrollbar; + }); + _registerModule(_modules, 'parts/RangeSelector.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Define the time span for the button + * + * @typedef {"all"|"day"|"hour"|"millisecond"|"minute"|"month"|"second"|"week"|"year"|"ytd"} Highcharts.RangeSelectorButtonTypeValue + */ + /** + * Callback function to react on button clicks. + * + * @callback Highcharts.RangeSelectorClickCallbackFunction + * + * @param {global.Event} e + * Event arguments. + * + * @param {boolean|undefined} + * Return false to cancel the default button event. + */ + /** + * Callback function to parse values entered in the input boxes and return a + * valid JavaScript time as milliseconds since 1970. + * + * @callback Highcharts.RangeSelectorParseCallbackFunction + * + * @param {string} value + * Input value to parse. + * + * @return {number} + * Parsed JavaScript time value. + */ + var addEvent = U.addEvent, createElement = U.createElement, css = U.css, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, discardElement = U.discardElement, extend = U.extend, fireEvent = U.fireEvent, isNumber = U.isNumber, merge = U.merge, objectEach = U.objectEach, pick = U.pick, pInt = U.pInt, splat = U.splat; + var Axis = H.Axis, Chart = H.Chart, defaultOptions = H.defaultOptions; + /* ************************************************************************** * + * Start Range Selector code * + * ************************************************************************** */ + extend(defaultOptions, { + /** + * The range selector is a tool for selecting ranges to display within + * the chart. It provides buttons to select preconfigured ranges in + * the chart, like 1 day, 1 week, 1 month etc. It also provides input + * boxes where min and max dates can be manually input. + * + * @product highstock gantt + * @optionparent rangeSelector + */ + rangeSelector: { + /** + * Whether to enable all buttons from the start. By default buttons are + * only enabled if the corresponding time range exists on the X axis, + * but enabling all buttons allows for dynamically loading different + * time ranges. + * + * @sample {highstock} stock/rangeselector/allbuttonsenabled-true/ + * All buttons enabled + * + * @type {boolean} + * @default false + * @since 2.0.3 + * @apioption rangeSelector.allButtonsEnabled + */ + /** + * An array of configuration objects for the buttons. + * + * Defaults to: + * ```js + * buttons: [{ + * type: 'month', + * count: 1, + * text: '1m' + * }, { + * type: 'month', + * count: 3, + * text: '3m' + * }, { + * type: 'month', + * count: 6, + * text: '6m' + * }, { + * type: 'ytd', + * text: 'YTD' + * }, { + * type: 'year', + * count: 1, + * text: '1y' + * }, { + * type: 'all', + * text: 'All' + * }] + * ``` + * + * @sample {highstock} stock/rangeselector/datagrouping/ + * Data grouping by buttons + * + * @type {Array<*>} + * @apioption rangeSelector.buttons + */ + /** + * How many units of the defined type the button should span. If `type` + * is "month" and `count` is 3, the button spans three months. + * + * @type {number} + * @default 1 + * @apioption rangeSelector.buttons.count + */ + /** + * Fires when clicking on the rangeSelector button. One parameter, + * event, is passed to the function, containing common event + * information. + * + * ```js + * click: function(e) { + * console.log(this); + * } + * ``` + * + * Return false to stop default button's click action. + * + * @sample {highstock} stock/rangeselector/button-click/ + * Click event on the button + * + * @type {Highcharts.RangeSelectorClickCallbackFunction} + * @apioption rangeSelector.buttons.events.click + */ + /** + * Additional range (in milliseconds) added to the end of the calculated + * time span. + * + * @sample {highstock} stock/rangeselector/min-max-offsets/ + * Button offsets + * + * @type {number} + * @default 0 + * @since 6.0.0 + * @apioption rangeSelector.buttons.offsetMax + */ + /** + * Additional range (in milliseconds) added to the start of the + * calculated time span. + * + * @sample {highstock} stock/rangeselector/min-max-offsets/ + * Button offsets + * + * @type {number} + * @default 0 + * @since 6.0.0 + * @apioption rangeSelector.buttons.offsetMin + */ + /** + * When buttons apply dataGrouping on a series, by default zooming + * in/out will deselect buttons and unset dataGrouping. Enable this + * option to keep buttons selected when extremes change. + * + * @sample {highstock} stock/rangeselector/preserve-datagrouping/ + * Different preserveDataGrouping settings + * + * @type {boolean} + * @default false + * @since 6.1.2 + * @apioption rangeSelector.buttons.preserveDataGrouping + */ + /** + * A custom data grouping object for each button. + * + * @see [series.dataGrouping](#plotOptions.series.dataGrouping) + * + * @sample {highstock} stock/rangeselector/datagrouping/ + * Data grouping by range selector buttons + * + * @type {*} + * @extends plotOptions.series.dataGrouping + * @apioption rangeSelector.buttons.dataGrouping + */ + /** + * The text for the button itself. + * + * @type {string} + * @apioption rangeSelector.buttons.text + */ + /** + * Defined the time span for the button. Can be one of `millisecond`, + * `second`, `minute`, `hour`, `day`, `week`, `month`, `year`, `ytd`, + * and `all`. + * + * @type {Highcharts.RangeSelectorButtonTypeValue} + * @apioption rangeSelector.buttons.type + */ + /** + * The space in pixels between the buttons in the range selector. + * + * @type {number} + * @default 0 + * @apioption rangeSelector.buttonSpacing + */ + /** + * Enable or disable the range selector. + * + * @sample {highstock} stock/rangeselector/enabled/ + * Disable the range selector + * + * @type {boolean} + * @default true + * @apioption rangeSelector.enabled + */ + /** + * The vertical alignment of the rangeselector box. Allowed properties + * are `top`, `middle`, `bottom`. + * + * @sample {highstock} stock/rangeselector/vertical-align-middle/ + * Middle + * @sample {highstock} stock/rangeselector/vertical-align-bottom/ + * Bottom + * + * @type {Highcharts.VerticalAlignValue} + * @since 6.0.0 + */ + verticalAlign: 'top', + /** + * A collection of attributes for the buttons. The object takes SVG + * attributes like `fill`, `stroke`, `stroke-width`, as well as `style`, + * a collection of CSS properties for the text. + * + * The object can also be extended with states, so you can set + * presentational options for `hover`, `select` or `disabled` button + * states. + * + * CSS styles for the text label. + * + * In styled mode, the buttons are styled by the + * `.highcharts-range-selector-buttons .highcharts-button` rule with its + * different states. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {Highcharts.SVGAttributes} + */ + buttonTheme: { + /** @ignore */ + width: 28, + /** @ignore */ + height: 18, + /** @ignore */ + padding: 2, + /** @ignore */ + zIndex: 7 // #484, #852 + }, + /** + * When the rangeselector is floating, the plot area does not reserve + * space for it. This opens for positioning anywhere on the chart. + * + * @sample {highstock} stock/rangeselector/floating/ + * Placing the range selector between the plot area and the + * navigator + * + * @since 6.0.0 + */ + floating: false, + /** + * The x offset of the range selector relative to its horizontal + * alignment within `chart.spacingLeft` and `chart.spacingRight`. + * + * @since 6.0.0 + */ + x: 0, + /** + * The y offset of the range selector relative to its horizontal + * alignment within `chart.spacingLeft` and `chart.spacingRight`. + * + * @since 6.0.0 + */ + y: 0, + /** + * Deprecated. The height of the range selector. Currently it is + * calculated dynamically. + * + * @deprecated + * @type {number|undefined} + * @since 2.1.9 + */ + height: void 0, + /** + * The border color of the date input boxes. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {Highcharts.ColorString} + * @default #cccccc + * @since 1.3.7 + * @apioption rangeSelector.inputBoxBorderColor + */ + /** + * The pixel height of the date input boxes. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {number} + * @default 17 + * @since 1.3.7 + * @apioption rangeSelector.inputBoxHeight + */ + /** + * CSS for the container DIV holding the input boxes. Deprecated as + * of 1.2.5\. Use [inputPosition](#rangeSelector.inputPosition) instead. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @deprecated + * @type {Highcharts.CSSObject} + * @apioption rangeSelector.inputBoxStyle + */ + /** + * The pixel width of the date input boxes. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {number} + * @default 90 + * @since 1.3.7 + * @apioption rangeSelector.inputBoxWidth + */ + /** + * The date format in the input boxes when not selected for editing. + * Defaults to `%b %e, %Y`. + * + * @sample {highstock} stock/rangeselector/input-format/ + * Milliseconds in the range selector + * + * @type {string} + * @default %b %e, %Y + * @apioption rangeSelector.inputDateFormat + */ + /** + * A custom callback function to parse values entered in the input boxes + * and return a valid JavaScript time as milliseconds since 1970. + * + * @sample {highstock} stock/rangeselector/input-format/ + * Milliseconds in the range selector + * + * @type {Highcharts.RangeSelectorParseCallbackFunction} + * @since 1.3.3 + * @apioption rangeSelector.inputDateParser + */ + /** + * The date format in the input boxes when they are selected for + * editing. This must be a format that is recognized by JavaScript + * Date.parse. + * + * @sample {highstock} stock/rangeselector/input-format/ + * Milliseconds in the range selector + * + * @type {string} + * @default %Y-%m-%d + * @apioption rangeSelector.inputEditDateFormat + */ + /** + * Enable or disable the date input boxes. Defaults to enabled when + * there is enough space, disabled if not (typically mobile). + * + * @sample {highstock} stock/rangeselector/input-datepicker/ + * Extending the input with a jQuery UI datepicker + * + * @type {boolean} + * @default true + * @apioption rangeSelector.inputEnabled + */ + /** + * Positioning for the input boxes. Allowed properties are `align`, + * `x` and `y`. + * + * @since 1.2.4 + */ + inputPosition: { + /** + * The alignment of the input box. Allowed properties are `left`, + * `center`, `right`. + * + * @sample {highstock} stock/rangeselector/input-button-position/ + * Alignment + * + * @type {Highcharts.AlignValue} + * @since 6.0.0 + */ + align: 'right', + /** + * X offset of the input row. + */ + x: 0, + /** + * Y offset of the input row. + */ + y: 0 + }, + /** + * The index of the button to appear pre-selected. + * + * @type {number} + * @apioption rangeSelector.selected + */ + /** + * Positioning for the button row. + * + * @since 1.2.4 + */ + buttonPosition: { + /** + * The alignment of the input box. Allowed properties are `left`, + * `center`, `right`. + * + * @sample {highstock} stock/rangeselector/input-button-position/ + * Alignment + * + * @type {Highcharts.AlignValue} + * @since 6.0.0 + */ + align: 'left', + /** + * X offset of the button row. + */ + x: 0, + /** + * Y offset of the button row. + */ + y: 0 + }, + /** + * CSS for the HTML inputs in the range selector. + * + * In styled mode, the inputs are styled by the + * `.highcharts-range-input text` rule in SVG mode, and + * `input.highcharts-range-selector` when active. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {Highcharts.CSSObject} + * @apioption rangeSelector.inputStyle + */ + /** + * CSS styles for the labels - the Zoom, From and To texts. + * + * In styled mode, the labels are styled by the + * `.highcharts-range-label` class. + * + * @sample {highstock} stock/rangeselector/styling/ + * Styling the buttons and inputs + * + * @type {Highcharts.CSSObject} + */ + labelStyle: { + /** @ignore */ + color: '#666666' + } + } + }); + defaultOptions.lang = merge(defaultOptions.lang, + /** + * Language object. The language object is global and it can't be set + * on each chart initialization. Instead, use `Highcharts.setOptions` to + * set it before any chart is initialized. + * + * ```js + * Highcharts.setOptions({ + * lang: { + * months: [ + * 'Janvier', 'Février', 'Mars', 'Avril', + * 'Mai', 'Juin', 'Juillet', 'Août', + * 'Septembre', 'Octobre', 'Novembre', 'Décembre' + * ], + * weekdays: [ + * 'Dimanche', 'Lundi', 'Mardi', 'Mercredi', + * 'Jeudi', 'Vendredi', 'Samedi' + * ] + * } + * }); + * ``` + * + * @optionparent lang + */ + { + /** + * The text for the label for the range selector buttons. + * + * @product highstock gantt + */ + rangeSelectorZoom: 'Zoom', + /** + * The text for the label for the "from" input box in the range + * selector. + * + * @product highstock gantt + */ + rangeSelectorFrom: 'From', + /** + * The text for the label for the "to" input box in the range selector. + * + * @product highstock gantt + */ + rangeSelectorTo: 'To' + }); + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The range selector. + * + * @private + * @class + * @name Highcharts.RangeSelector + * @param {Highcharts.Chart} chart + */ + function RangeSelector(chart) { + // Run RangeSelector + this.init(chart); + } + RangeSelector.prototype = { + /** + * The method to run when one of the buttons in the range selectors is + * clicked + * + * @private + * @function Highcharts.RangeSelector#clickButton + * @param {number} i + * The index of the button + * @param {boolean} [redraw] + * @return {void} + */ + clickButton: function (i, redraw) { + var rangeSelector = this, chart = rangeSelector.chart, rangeOptions = rangeSelector.buttonOptions[i], baseAxis = chart.xAxis[0], unionExtremes = (chart.scroller && chart.scroller.getUnionExtremes()) || baseAxis || {}, dataMin = unionExtremes.dataMin, dataMax = unionExtremes.dataMax, newMin, newMax = baseAxis && Math.round(Math.min(baseAxis.max, pick(dataMax, baseAxis.max))), // #1568 + type = rangeOptions.type, baseXAxisOptions, range = rangeOptions._range, rangeMin, minSetting, rangeSetting, ctx, ytdExtremes, dataGrouping = rangeOptions.dataGrouping; + // chart has no data, base series is removed + if (dataMin === null || dataMax === null) { + return; + } + // Set the fixed range before range is altered + chart.fixedRange = range; + // Apply dataGrouping associated to button + if (dataGrouping) { + this.forcedDataGrouping = true; + Axis.prototype.setDataGrouping.call(baseAxis || { chart: this.chart }, dataGrouping, false); + this.frozenStates = rangeOptions.preserveDataGrouping; + } + // Apply range + if (type === 'month' || type === 'year') { + if (!baseAxis) { + // This is set to the user options and picked up later when the + // axis is instantiated so that we know the min and max. + range = rangeOptions; + } + else { + ctx = { + range: rangeOptions, + max: newMax, + chart: chart, + dataMin: dataMin, + dataMax: dataMax + }; + newMin = baseAxis.minFromRange.call(ctx); + if (isNumber(ctx.newMax)) { + newMax = ctx.newMax; + } + } + // Fixed times like minutes, hours, days + } + else if (range) { + newMin = Math.max(newMax - range, dataMin); + newMax = Math.min(newMin + range, dataMax); + } + else if (type === 'ytd') { + // On user clicks on the buttons, or a delayed action running from + // the beforeRender event (below), the baseAxis is defined. + if (baseAxis) { + // When "ytd" is the pre-selected button for the initial view, + // its calculation is delayed and rerun in the beforeRender + // event (below). When the series are initialized, but before + // the chart is rendered, we have access to the xData array + // (#942). + if (typeof dataMax === 'undefined') { + dataMin = Number.MAX_VALUE; + dataMax = Number.MIN_VALUE; + chart.series.forEach(function (series) { + // reassign it to the last item + var xData = series.xData; + dataMin = Math.min(xData[0], dataMin); + dataMax = Math.max(xData[xData.length - 1], dataMax); + }); + redraw = false; + } + ytdExtremes = rangeSelector.getYTDExtremes(dataMax, dataMin, chart.time.useUTC); + newMin = rangeMin = ytdExtremes.min; + newMax = ytdExtremes.max; + // "ytd" is pre-selected. We don't yet have access to processed + // point and extremes data (things like pointStart and pointInterval + // are missing), so we delay the process (#942) + } + else { + rangeSelector.deferredYTDClick = i; + return; + } + } + else if (type === 'all' && baseAxis) { + newMin = dataMin; + newMax = dataMax; + } + newMin += rangeOptions._offsetMin; + newMax += rangeOptions._offsetMax; + rangeSelector.setSelected(i); + // Update the chart + if (!baseAxis) { + // Axis not yet instanciated. Temporarily set min and range + // options and remove them on chart load (#4317). + baseXAxisOptions = splat(chart.options.xAxis)[0]; + rangeSetting = baseXAxisOptions.range; + baseXAxisOptions.range = range; + minSetting = baseXAxisOptions.min; + baseXAxisOptions.min = rangeMin; + addEvent(chart, 'load', function resetMinAndRange() { + baseXAxisOptions.range = rangeSetting; + baseXAxisOptions.min = minSetting; + }); + } + else { + // Existing axis object. Set extremes after render time. + baseAxis.setExtremes(newMin, newMax, pick(redraw, 1), null, // auto animation + { + trigger: 'rangeSelectorButton', + rangeSelectorButton: rangeOptions + }); + } + }, + /** + * Set the selected option. This method only sets the internal flag, it + * doesn't update the buttons or the actual zoomed range. + * + * @private + * @function Highcharts.RangeSelector#setSelected + * @param {number} [selected] + * @return {void} + */ + setSelected: function (selected) { + this.selected = this.options.selected = selected; + }, + /** + * The default buttons for pre-selecting time frames + */ + defaultButtons: [{ + type: 'month', + count: 1, + text: '1m' + }, { + type: 'month', + count: 3, + text: '3m' + }, { + type: 'month', + count: 6, + text: '6m' + }, { + type: 'ytd', + text: 'YTD' + }, { + type: 'year', + count: 1, + text: '1y' + }, { + type: 'all', + text: 'All' + }], + /** + * Initialize the range selector + * + * @private + * @function Highcharts.RangeSelector#init + * @param {Highcharts.Chart} chart + * @return {void} + */ + init: function (chart) { + var rangeSelector = this, options = chart.options.rangeSelector, buttonOptions = options.buttons || + [].concat(rangeSelector.defaultButtons), selectedOption = options.selected, blurInputs = function () { + var minInput = rangeSelector.minInput, maxInput = rangeSelector.maxInput; + // #3274 in some case blur is not defined + if (minInput && minInput.blur) { + fireEvent(minInput, 'blur'); + } + if (maxInput && maxInput.blur) { + fireEvent(maxInput, 'blur'); + } + }; + rangeSelector.chart = chart; + rangeSelector.options = options; + rangeSelector.buttons = []; + rangeSelector.buttonOptions = buttonOptions; + this.unMouseDown = addEvent(chart.container, 'mousedown', blurInputs); + this.unResize = addEvent(chart, 'resize', blurInputs); + // Extend the buttonOptions with actual range + buttonOptions.forEach(rangeSelector.computeButtonRange); + // zoomed range based on a pre-selected button index + if (typeof selectedOption !== 'undefined' && + buttonOptions[selectedOption]) { + this.clickButton(selectedOption, false); + } + addEvent(chart, 'load', function () { + // If a data grouping is applied to the current button, release it + // when extremes change + if (chart.xAxis && chart.xAxis[0]) { + addEvent(chart.xAxis[0], 'setExtremes', function (e) { + if (this.max - this.min !== + chart.fixedRange && + e.trigger !== 'rangeSelectorButton' && + e.trigger !== 'updatedData' && + rangeSelector.forcedDataGrouping && + !rangeSelector.frozenStates) { + this.setDataGrouping(false, false); + } + }); + } + }); + }, + /** + * Dynamically update the range selector buttons after a new range has been + * set + * + * @private + * @function Highcharts.RangeSelector#updateButtonStates + * @return {void} + */ + updateButtonStates: function () { + var rangeSelector = this, chart = this.chart, baseAxis = chart.xAxis[0], actualRange = Math.round(baseAxis.max - baseAxis.min), hasNoData = !baseAxis.hasVisibleSeries, day = 24 * 36e5, // A single day in milliseconds + unionExtremes = (chart.scroller && + chart.scroller.getUnionExtremes()) || baseAxis, dataMin = unionExtremes.dataMin, dataMax = unionExtremes.dataMax, ytdExtremes = rangeSelector.getYTDExtremes(dataMax, dataMin, chart.time.useUTC), ytdMin = ytdExtremes.min, ytdMax = ytdExtremes.max, selected = rangeSelector.selected, selectedExists = isNumber(selected), allButtonsEnabled = rangeSelector.options.allButtonsEnabled, buttons = rangeSelector.buttons; + rangeSelector.buttonOptions.forEach(function (rangeOptions, i) { + var range = rangeOptions._range, type = rangeOptions.type, count = rangeOptions.count || 1, button = buttons[i], state = 0, disable, select, offsetRange = rangeOptions._offsetMax - + rangeOptions._offsetMin, isSelected = i === selected, + // Disable buttons where the range exceeds what is allowed in + // the current view + isTooGreatRange = range > + dataMax - dataMin, + // Disable buttons where the range is smaller than the minimum + // range + isTooSmallRange = range < baseAxis.minRange, + // Do not select the YTD button if not explicitly told so + isYTDButNotSelected = false, + // Disable the All button if we're already showing all + isAllButAlreadyShowingAll = false, isSameRange = range === actualRange; + // Months and years have a variable range so we check the extremes + if ((type === 'month' || type === 'year') && + (actualRange + 36e5 >= + { month: 28, year: 365 }[type] * day * count - offsetRange) && + (actualRange - 36e5 <= + { month: 31, year: 366 }[type] * day * count + offsetRange)) { + isSameRange = true; + } + else if (type === 'ytd') { + isSameRange = (ytdMax - ytdMin + offsetRange) === actualRange; + isYTDButNotSelected = !isSelected; + } + else if (type === 'all') { + isSameRange = (baseAxis.max - baseAxis.min >= + dataMax - dataMin); + isAllButAlreadyShowingAll = (!isSelected && + selectedExists && + isSameRange); + } + // The new zoom area happens to match the range for a button - mark + // it selected. This happens when scrolling across an ordinal gap. + // It can be seen in the intraday demos when selecting 1h and scroll + // across the night gap. + disable = (!allButtonsEnabled && + (isTooGreatRange || + isTooSmallRange || + isAllButAlreadyShowingAll || + hasNoData)); + select = ((isSelected && isSameRange) || + (isSameRange && !selectedExists && !isYTDButNotSelected) || + (isSelected && rangeSelector.frozenStates)); + if (disable) { + state = 3; + } + else if (select) { + selectedExists = true; // Only one button can be selected + state = 2; + } + // If state has changed, update the button + if (button.state !== state) { + button.setState(state); + // Reset (#9209) + if (state === 0 && selected === i) { + rangeSelector.setSelected(null); + } + } + }); + }, + /** + * Compute and cache the range for an individual button + * + * @private + * @function Highcharts.RangeSelector#computeButtonRange + * @param {Highcharts.RangeSelectorButtonsOptions} rangeOptions + * @return {void} + */ + computeButtonRange: function (rangeOptions) { + var type = rangeOptions.type, count = rangeOptions.count || 1, + // these time intervals have a fixed number of milliseconds, as + // opposed to month, ytd and year + fixedTimes = { + millisecond: 1, + second: 1000, + minute: 60 * 1000, + hour: 3600 * 1000, + day: 24 * 3600 * 1000, + week: 7 * 24 * 3600 * 1000 + }; + // Store the range on the button object + if (fixedTimes[type]) { + rangeOptions._range = fixedTimes[type] * count; + } + else if (type === 'month' || type === 'year') { + rangeOptions._range = { + month: 30, + year: 365 + }[type] * 24 * 36e5 * count; + } + rangeOptions._offsetMin = pick(rangeOptions.offsetMin, 0); + rangeOptions._offsetMax = pick(rangeOptions.offsetMax, 0); + rangeOptions._range += + rangeOptions._offsetMax - rangeOptions._offsetMin; + }, + /** + * Set the internal and displayed value of a HTML input for the dates + * + * @private + * @function Highcharts.RangeSelector#setInputValue + * @param {string} name + * @param {number} [inputTime] + * @return {void} + */ + setInputValue: function (name, inputTime) { + var options = this.chart.options.rangeSelector, time = this.chart.time, input = this[name + 'Input']; + if (defined(inputTime)) { + input.previousValue = input.HCTime; + input.HCTime = inputTime; + } + input.value = time.dateFormat(options.inputEditDateFormat || '%Y-%m-%d', input.HCTime); + this[name + 'DateBox'].attr({ + text: time.dateFormat(options.inputDateFormat || '%b %e, %Y', input.HCTime) + }); + }, + /** + * @private + * @function Highcharts.RangeSelector#showInput + * @param {string} name + * @return {void} + */ + showInput: function (name) { + var inputGroup = this.inputGroup, dateBox = this[name + 'DateBox']; + css(this[name + 'Input'], { + left: (inputGroup.translateX + dateBox.x) + 'px', + top: inputGroup.translateY + 'px', + width: (dateBox.width - 2) + 'px', + height: (dateBox.height - 2) + 'px', + border: '2px solid silver' + }); + }, + /** + * @private + * @function Highcharts.RangeSelector#hideInput + * @param {string} name + * @return {void} + */ + hideInput: function (name) { + css(this[name + 'Input'], { + border: 0, + width: '1px', + height: '1px' + }); + this.setInputValue(name); + }, + /** + * Draw either the 'from' or the 'to' HTML input box of the range selector + * + * @private + * @function Highcharts.RangeSelector#drawInput + * @param {string} name + * @return {void} + */ + drawInput: function (name) { + var rangeSelector = this, chart = rangeSelector.chart, chartStyle = chart.renderer.style || {}, renderer = chart.renderer, options = chart.options.rangeSelector, lang = defaultOptions.lang, div = rangeSelector.div, isMin = name === 'min', input, label, dateBox, inputGroup = this.inputGroup; + /** + * @private + */ + function updateExtremes() { + var inputValue = input.value, value = (options.inputDateParser || Date.parse)(inputValue), chartAxis = chart.xAxis[0], dataAxis = chart.scroller && chart.scroller.xAxis ? + chart.scroller.xAxis : + chartAxis, dataMin = dataAxis.dataMin, dataMax = dataAxis.dataMax; + if (value !== input.previousValue) { + input.previousValue = value; + // If the value isn't parsed directly to a value by the + // browser's Date.parse method, like YYYY-MM-DD in IE, try + // parsing it a different way + if (!isNumber(value)) { + value = inputValue.split('-'); + value = Date.UTC(pInt(value[0]), pInt(value[1]) - 1, pInt(value[2])); + } + if (isNumber(value)) { + // Correct for timezone offset (#433) + if (!chart.time.useUTC) { + value = + value + new Date().getTimezoneOffset() * 60 * 1000; + } + // Validate the extremes. If it goes beyound the data min or + // max, use the actual data extreme (#2438). + if (isMin) { + if (value > rangeSelector.maxInput.HCTime) { + value = void 0; + } + else if (value < dataMin) { + value = dataMin; + } + } + else { + if (value < rangeSelector.minInput.HCTime) { + value = void 0; + } + else if (value > dataMax) { + value = dataMax; + } + } + // Set the extremes + if (typeof value !== 'undefined') { // @todo typof undefined + chartAxis.setExtremes(isMin ? value : chartAxis.min, isMin ? chartAxis.max : value, void 0, void 0, { trigger: 'rangeSelectorInput' }); + } + } + } + } + // Create the text label + this[name + 'Label'] = label = renderer + .label(lang[isMin ? 'rangeSelectorFrom' : 'rangeSelectorTo'], this.inputGroup.offset) + .addClass('highcharts-range-label') + .attr({ + padding: 2 + }) + .add(inputGroup); + inputGroup.offset += label.width + 5; + // Create an SVG label that shows updated date ranges and and records + // click events that bring in the HTML input. + this[name + 'DateBox'] = dateBox = renderer + .label('', inputGroup.offset) + .addClass('highcharts-range-input') + .attr({ + padding: 2, + width: options.inputBoxWidth || 90, + height: options.inputBoxHeight || 17, + 'text-align': 'center' + }) + .on('click', function () { + // If it is already focused, the onfocus event doesn't fire + // (#3713) + rangeSelector.showInput(name); + rangeSelector[name + 'Input'].focus(); + }); + if (!chart.styledMode) { + dateBox.attr({ + stroke: options.inputBoxBorderColor || '#cccccc', + 'stroke-width': 1 + }); + } + dateBox.add(inputGroup); + inputGroup.offset += dateBox.width + (isMin ? 10 : 0); + // Create the HTML input element. This is rendered as 1x1 pixel then set + // to the right size when focused. + this[name + 'Input'] = input = createElement('input', { + name: name, + className: 'highcharts-range-selector', + type: 'text' + }, { + top: chart.plotTop + 'px' // prevent jump on focus in Firefox + }, div); + if (!chart.styledMode) { + // Styles + label.css(merge(chartStyle, options.labelStyle)); + dateBox.css(merge({ + color: '#333333' + }, chartStyle, options.inputStyle)); + css(input, extend({ + position: 'absolute', + border: 0, + width: '1px', + height: '1px', + padding: 0, + textAlign: 'center', + fontSize: chartStyle.fontSize, + fontFamily: chartStyle.fontFamily, + top: '-9999em' // #4798 + }, options.inputStyle)); + } + // Blow up the input box + input.onfocus = function () { + rangeSelector.showInput(name); + }; + // Hide away the input box + input.onblur = function () { + // update extermes only when inputs are active + if (input === H.doc.activeElement) { // Only when focused + // Update also when no `change` event is triggered, like when + // clicking inside the SVG (#4710) + updateExtremes(); + } + // #10404 - move hide and blur outside focus + rangeSelector.hideInput(name); + input.blur(); // #4606 + }; + // handle changes in the input boxes + input.onchange = updateExtremes; + input.onkeypress = function (event) { + // IE does not fire onchange on enter + if (event.keyCode === 13) { + updateExtremes(); + } + }; + }, + /** + * Get the position of the range selector buttons and inputs. This can be + * overridden from outside for custom positioning. + * + * @private + * @function Highcharts.RangeSelector#getPosition + * + * @return {Highcharts.Dictionary} + */ + getPosition: function () { + var chart = this.chart, options = chart.options.rangeSelector, top = options.verticalAlign === 'top' ? + chart.plotTop - chart.axisOffset[0] : + 0; // set offset only for varticalAlign top + return { + buttonTop: top + options.buttonPosition.y, + inputTop: top + options.inputPosition.y - 10 + }; + }, + /** + * Get the extremes of YTD. Will choose dataMax if its value is lower than + * the current timestamp. Will choose dataMin if its value is higher than + * the timestamp for the start of current year. + * + * @private + * @function Highcharts.RangeSelector#getYTDExtremes + * + * @param {number} dataMax + * + * @param {number} dataMin + * + * @return {*} + * Returns min and max for the YTD + */ + getYTDExtremes: function (dataMax, dataMin, useUTC) { + var time = this.chart.time, min, now = new time.Date(dataMax), year = time.get('FullYear', now), startOfYear = useUTC ? + time.Date.UTC(year, 0, 1) : // eslint-disable-line new-cap + +new time.Date(year, 0, 1); + min = Math.max(dataMin || 0, startOfYear); + now = now.getTime(); + return { + max: Math.min(dataMax || now, now), + min: min + }; + }, + /** + * Render the range selector including the buttons and the inputs. The first + * time render is called, the elements are created and positioned. On + * subsequent calls, they are moved and updated. + * + * @private + * @function Highcharts.RangeSelector#render + * @param {number} [min] + * X axis minimum + * @param {number} [max] + * X axis maximum + * @return {void} + */ + render: function (min, max) { + var rangeSelector = this, chart = rangeSelector.chart, renderer = chart.renderer, container = chart.container, chartOptions = chart.options, navButtonOptions = (chartOptions.exporting && + chartOptions.exporting.enabled !== false && + chartOptions.navigation && + chartOptions.navigation.buttonOptions), lang = defaultOptions.lang, div = rangeSelector.div, options = chartOptions.rangeSelector, + // Place inputs above the container + inputsZIndex = pick(chartOptions.chart.style && + chartOptions.chart.style.zIndex, 0) + 1, floating = options.floating, buttons = rangeSelector.buttons, inputGroup = rangeSelector.inputGroup, buttonTheme = options.buttonTheme, buttonPosition = options.buttonPosition, inputPosition = options.inputPosition, inputEnabled = options.inputEnabled, states = buttonTheme && buttonTheme.states, plotLeft = chart.plotLeft, buttonLeft, buttonGroup = rangeSelector.buttonGroup, group, groupHeight, rendered = rangeSelector.rendered, verticalAlign = rangeSelector.options.verticalAlign, legend = chart.legend, legendOptions = legend && legend.options, buttonPositionY = buttonPosition.y, inputPositionY = inputPosition.y, animate = chart.hasLoaded, verb = animate ? 'animate' : 'attr', exportingX = 0, alignTranslateY, legendHeight, minPosition, translateY = 0, translateX; + if (options.enabled === false) { + return; + } + // create the elements + if (!rendered) { + rangeSelector.group = group = renderer.g('range-selector-group') + .attr({ + zIndex: 7 + }) + .add(); + rangeSelector.buttonGroup = buttonGroup = + renderer.g('range-selector-buttons').add(group); + rangeSelector.zoomText = renderer + .text(lang.rangeSelectorZoom, 0, 15) + .add(buttonGroup); + if (!chart.styledMode) { + rangeSelector.zoomText.css(options.labelStyle); + buttonTheme['stroke-width'] = + pick(buttonTheme['stroke-width'], 0); + } + rangeSelector.buttonOptions.forEach(function (rangeOptions, i) { + buttons[i] = renderer + .button(rangeOptions.text, 0, 0, function (e) { + // extract events from button object and call + var buttonEvents = (rangeOptions.events && + rangeOptions.events.click), callDefaultEvent; + if (buttonEvents) { + callDefaultEvent = + buttonEvents.call(rangeOptions, e); + } + if (callDefaultEvent !== false) { + rangeSelector.clickButton(i); + } + rangeSelector.isActive = true; + }, buttonTheme, states && states.hover, states && states.select, states && states.disabled) + .attr({ + 'text-align': 'center' + }) + .add(buttonGroup); + }); + // first create a wrapper outside the container in order to make + // the inputs work and make export correct + if (inputEnabled !== false) { + rangeSelector.div = div = createElement('div', null, { + position: 'relative', + height: 0, + zIndex: inputsZIndex + }); + container.parentNode.insertBefore(div, container); + // Create the group to keep the inputs + rangeSelector.inputGroup = inputGroup = + renderer.g('input-group').add(group); + inputGroup.offset = 0; + rangeSelector.drawInput('min'); + rangeSelector.drawInput('max'); + } + } + // #8769, allow dynamically updating margins + rangeSelector.zoomText[verb]({ + x: pick(plotLeft + buttonPosition.x, plotLeft) + }); + // button start position + buttonLeft = pick(plotLeft + buttonPosition.x, plotLeft) + + rangeSelector.zoomText.getBBox().width + 5; + rangeSelector.buttonOptions.forEach(function (rangeOptions, i) { + buttons[i][verb]({ x: buttonLeft }); + // increase button position for the next button + buttonLeft += buttons[i].width + pick(options.buttonSpacing, 5); + }); + plotLeft = chart.plotLeft - chart.spacing[3]; + rangeSelector.updateButtonStates(); + // detect collisiton with exporting + if (navButtonOptions && + this.titleCollision(chart) && + verticalAlign === 'top' && + buttonPosition.align === 'right' && ((buttonPosition.y + + buttonGroup.getBBox().height - 12) < + ((navButtonOptions.y || 0) + + navButtonOptions.height))) { + exportingX = -40; + } + translateX = buttonPosition.x - chart.spacing[3]; + if (buttonPosition.align === 'right') { + translateX += exportingX - plotLeft; // (#13014) + } + else if (buttonPosition.align === 'center') { + translateX -= plotLeft / 2; + } + // align button group + buttonGroup.align({ + y: buttonPosition.y, + width: buttonGroup.getBBox().width, + align: buttonPosition.align, + x: translateX + }, true, chart.spacingBox); + // skip animation + rangeSelector.group.placed = animate; + rangeSelector.buttonGroup.placed = animate; + if (inputEnabled !== false) { + var inputGroupX, inputGroupWidth, buttonGroupX, buttonGroupWidth; + // detect collision with exporting + if (navButtonOptions && + this.titleCollision(chart) && + verticalAlign === 'top' && + inputPosition.align === 'right' && ((inputPosition.y - + inputGroup.getBBox().height - 12) < + ((navButtonOptions.y || 0) + + navButtonOptions.height + + chart.spacing[0]))) { + exportingX = -40; + } + else { + exportingX = 0; + } + if (inputPosition.align === 'left') { + translateX = plotLeft; + } + else if (inputPosition.align === 'right') { + translateX = -Math.max(chart.axisOffset[1], -exportingX); + } + // Update the alignment to the updated spacing box + inputGroup.align({ + y: inputPosition.y, + width: inputGroup.getBBox().width, + align: inputPosition.align, + // fix wrong getBBox() value on right align + x: inputPosition.x + translateX - 2 + }, true, chart.spacingBox); + // detect collision + inputGroupX = (inputGroup.alignAttr.translateX + + inputGroup.alignOptions.x - + exportingX + + // getBBox for detecing left margin + inputGroup.getBBox().x + + // 2px padding to not overlap input and label + 2); + inputGroupWidth = inputGroup.alignOptions.width; + buttonGroupX = buttonGroup.alignAttr.translateX + + buttonGroup.getBBox().x; + // 20 is minimal spacing between elements + buttonGroupWidth = buttonGroup.getBBox().width + 20; + if ((inputPosition.align === + buttonPosition.align) || ((buttonGroupX + buttonGroupWidth > inputGroupX) && + (inputGroupX + inputGroupWidth > buttonGroupX) && + (buttonPositionY < + (inputPositionY + + inputGroup.getBBox().height)))) { + inputGroup.attr({ + translateX: inputGroup.alignAttr.translateX + + (chart.axisOffset[1] >= -exportingX ? 0 : -exportingX), + translateY: inputGroup.alignAttr.translateY + + buttonGroup.getBBox().height + 10 + }); + } + // Set or reset the input values + rangeSelector.setInputValue('min', min); + rangeSelector.setInputValue('max', max); + // skip animation + rangeSelector.inputGroup.placed = animate; + } + // vertical align + rangeSelector.group.align({ + verticalAlign: verticalAlign + }, true, chart.spacingBox); + // set position + groupHeight = + rangeSelector.group.getBBox().height + 20; // # 20 padding + alignTranslateY = + rangeSelector.group.alignAttr.translateY; + // calculate bottom position + if (verticalAlign === 'bottom') { + legendHeight = (legendOptions && + legendOptions.verticalAlign === 'bottom' && + legendOptions.enabled && + !legendOptions.floating ? + legend.legendHeight + pick(legendOptions.margin, 10) : + 0); + groupHeight = groupHeight + legendHeight - 20; + translateY = (alignTranslateY - + groupHeight - + (floating ? 0 : options.y) - + (chart.titleOffset ? chart.titleOffset[2] : 0) - + 10 // 10 spacing + ); + } + if (verticalAlign === 'top') { + if (floating) { + translateY = 0; + } + if (chart.titleOffset && chart.titleOffset[0]) { + translateY = chart.titleOffset[0]; + } + translateY += ((chart.margin[0] - chart.spacing[0]) || 0); + } + else if (verticalAlign === 'middle') { + if (inputPositionY === buttonPositionY) { + if (inputPositionY < 0) { + translateY = alignTranslateY + minPosition; + } + else { + translateY = alignTranslateY; + } + } + else if (inputPositionY || buttonPositionY) { + if (inputPositionY < 0 || + buttonPositionY < 0) { + translateY -= Math.min(inputPositionY, buttonPositionY); + } + else { + translateY = + alignTranslateY - groupHeight + minPosition; + } + } + } + rangeSelector.group.translate(options.x, options.y + Math.floor(translateY)); + // translate HTML inputs + if (inputEnabled !== false) { + rangeSelector.minInput.style.marginTop = + rangeSelector.group.translateY + 'px'; + rangeSelector.maxInput.style.marginTop = + rangeSelector.group.translateY + 'px'; + } + rangeSelector.rendered = true; + }, + /** + * Extracts height of range selector + * + * @private + * @function Highcharts.RangeSelector#getHeight + * @return {number} + * Returns rangeSelector height + */ + getHeight: function () { + var rangeSelector = this, options = rangeSelector.options, rangeSelectorGroup = rangeSelector.group, inputPosition = options.inputPosition, buttonPosition = options.buttonPosition, yPosition = options.y, buttonPositionY = buttonPosition.y, inputPositionY = inputPosition.y, rangeSelectorHeight = 0, minPosition; + if (options.height) { + return options.height; + } + rangeSelectorHeight = rangeSelectorGroup ? + // 13px to keep back compatibility + (rangeSelectorGroup.getBBox(true).height) + 13 + + yPosition : + 0; + minPosition = Math.min(inputPositionY, buttonPositionY); + if ((inputPositionY < 0 && buttonPositionY < 0) || + (inputPositionY > 0 && buttonPositionY > 0)) { + rangeSelectorHeight += Math.abs(minPosition); + } + return rangeSelectorHeight; + }, + /** + * Detect collision with title or subtitle + * + * @private + * @function Highcharts.RangeSelector#titleCollision + * + * @param {Highcharts.Chart} chart + * + * @return {boolean} + * Returns collision status + */ + titleCollision: function (chart) { + return !(chart.options.title.text || + chart.options.subtitle.text); + }, + /** + * Update the range selector with new options + * + * @private + * @function Highcharts.RangeSelector#update + * @param {Highcharts.RangeSelectorOptions} options + * @return {void} + */ + update: function (options) { + var chart = this.chart; + merge(true, chart.options.rangeSelector, options); + this.destroy(); + this.init(chart); + chart.rangeSelector.render(); + }, + /** + * Destroys allocated elements. + * + * @private + * @function Highcharts.RangeSelector#destroy + */ + destroy: function () { + var rSelector = this, minInput = rSelector.minInput, maxInput = rSelector.maxInput; + rSelector.unMouseDown(); + rSelector.unResize(); + // Destroy elements in collections + destroyObjectProperties(rSelector.buttons); + // Clear input element events + if (minInput) { + minInput.onfocus = minInput.onblur = minInput.onchange = null; + } + if (maxInput) { + maxInput.onfocus = maxInput.onblur = maxInput.onchange = null; + } + // Destroy HTML and SVG elements + objectEach(rSelector, function (val, key) { + if (val && key !== 'chart') { + if (val.destroy) { + // SVGElement + val.destroy(); + } + else if (val.nodeType) { + // HTML element + discardElement(this[key]); + } + } + if (val !== RangeSelector.prototype[key]) { + rSelector[key] = null; + } + }, this); + } + }; + /** + * Get the axis min value based on the range option and the current max. For + * stock charts this is extended via the {@link RangeSelector} so that if the + * selected range is a multiple of months or years, it is compensated for + * various month lengths. + * + * @private + * @function Highcharts.Axis#minFromRange + * @return {number|undefined} + * The new minimum value. + */ + Axis.prototype.minFromRange = function () { + var rangeOptions = this.range, type = rangeOptions.type, min, max = this.max, dataMin, range, time = this.chart.time, + // Get the true range from a start date + getTrueRange = function (base, count) { + var timeName = type === 'year' ? 'FullYear' : 'Month'; + var date = new time.Date(base); + var basePeriod = time.get(timeName, date); + time.set(timeName, date, basePeriod + count); + if (basePeriod === time.get(timeName, date)) { + time.set('Date', date, 0); // #6537 + } + return date.getTime() - base; + }; + if (isNumber(rangeOptions)) { + min = max - rangeOptions; + range = rangeOptions; + } + else { + min = max + getTrueRange(max, -rangeOptions.count); + // Let the fixedRange reflect initial settings (#5930) + if (this.chart) { + this.chart.fixedRange = max - min; + } + } + dataMin = pick(this.dataMin, Number.MIN_VALUE); + if (!isNumber(min)) { + min = dataMin; + } + if (min <= dataMin) { + min = dataMin; + if (typeof range === 'undefined') { // #4501 + range = getTrueRange(min, rangeOptions.count); + } + this.newMax = Math.min(min + range, this.dataMax); + } + if (!isNumber(max)) { + min = void 0; + } + return min; + }; + if (!H.RangeSelector) { + // Initialize rangeselector for stock charts + addEvent(Chart, 'afterGetContainer', function () { + if (this.options.rangeSelector.enabled) { + this.rangeSelector = new RangeSelector(this); + } + }); + addEvent(Chart, 'beforeRender', function () { + var chart = this, axes = chart.axes, rangeSelector = chart.rangeSelector, verticalAlign; + if (rangeSelector) { + if (isNumber(rangeSelector.deferredYTDClick)) { + rangeSelector.clickButton(rangeSelector.deferredYTDClick); + delete rangeSelector.deferredYTDClick; + } + axes.forEach(function (axis) { + axis.updateNames(); + axis.setScale(); + }); + chart.getAxisMargins(); + rangeSelector.render(); + verticalAlign = rangeSelector.options.verticalAlign; + if (!rangeSelector.options.floating) { + if (verticalAlign === 'bottom') { + this.extraBottomMargin = true; + } + else if (verticalAlign !== 'middle') { + this.extraTopMargin = true; + } + } + } + }); + addEvent(Chart, 'update', function (e) { + var chart = this, options = e.options, optionsRangeSelector = options.rangeSelector, rangeSelector = chart.rangeSelector, verticalAlign, extraBottomMarginWas = this.extraBottomMargin, extraTopMarginWas = this.extraTopMargin; + if (optionsRangeSelector && + optionsRangeSelector.enabled && + !defined(rangeSelector)) { + this.options.rangeSelector.enabled = true; + this.rangeSelector = new RangeSelector(this); + } + this.extraBottomMargin = false; + this.extraTopMargin = false; + if (rangeSelector) { + rangeSelector.render(); + verticalAlign = (optionsRangeSelector && + optionsRangeSelector.verticalAlign) || (rangeSelector.options && rangeSelector.options.verticalAlign); + if (!rangeSelector.options.floating) { + if (verticalAlign === 'bottom') { + this.extraBottomMargin = true; + } + else if (verticalAlign !== 'middle') { + this.extraTopMargin = true; + } + } + if (this.extraBottomMargin !== extraBottomMarginWas || + this.extraTopMargin !== extraTopMarginWas) { + this.isDirtyBox = true; + } + } + }); + addEvent(Chart, 'render', function () { + var chart = this, rangeSelector = chart.rangeSelector, verticalAlign; + if (rangeSelector && !rangeSelector.options.floating) { + rangeSelector.render(); + verticalAlign = rangeSelector.options.verticalAlign; + if (verticalAlign === 'bottom') { + this.extraBottomMargin = true; + } + else if (verticalAlign !== 'middle') { + this.extraTopMargin = true; + } + } + }); + addEvent(Chart, 'getMargins', function () { + var rangeSelector = this.rangeSelector, rangeSelectorHeight; + if (rangeSelector) { + rangeSelectorHeight = rangeSelector.getHeight(); + if (this.extraTopMargin) { + this.plotTop += rangeSelectorHeight; + } + if (this.extraBottomMargin) { + this.marginBottom += rangeSelectorHeight; + } + } + }); + Chart.prototype.callbacks.push(function (chart) { + var extremes, rangeSelector = chart.rangeSelector, unbindRender, unbindSetExtremes, legend, alignTo, verticalAlign; + /** + * @private + */ + function renderRangeSelector() { + extremes = chart.xAxis[0].getExtremes(); + legend = chart.legend; + verticalAlign = rangeSelector === null || rangeSelector === void 0 ? void 0 : rangeSelector.options.verticalAlign; + if (isNumber(extremes.min)) { + rangeSelector.render(extremes.min, extremes.max); + } + // Re-align the legend so that it's below the rangeselector + if (rangeSelector && legend.display && + verticalAlign === 'top' && + verticalAlign === legend.options.verticalAlign) { + // Create a new alignment box for the legend. + alignTo = merge(chart.spacingBox); + if (legend.options.layout === 'vertical') { + alignTo.y = chart.plotTop; + } + else { + alignTo.y += rangeSelector.getHeight(); + } + legend.group.placed = false; // Don't animate the alignment. + legend.align(alignTo); + } + } + if (rangeSelector) { + // redraw the scroller on setExtremes + unbindSetExtremes = addEvent(chart.xAxis[0], 'afterSetExtremes', function (e) { + rangeSelector.render(e.min, e.max); + }); + // redraw the scroller chart resize + unbindRender = addEvent(chart, 'redraw', renderRangeSelector); + // do it now + renderRangeSelector(); + } + // Remove resize/afterSetExtremes at chart destroy + addEvent(chart, 'destroy', function destroyEvents() { + if (rangeSelector) { + unbindRender(); + unbindSetExtremes(); + } + }); + }); + H.RangeSelector = RangeSelector; + } + + }); + _registerModule(_modules, 'parts/NavigatorAxis.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var isTouchDevice = H.isTouchDevice; + var addEvent = U.addEvent, correctFloat = U.correctFloat, defined = U.defined, isNumber = U.isNumber, pick = U.pick; + /* eslint-disable valid-jsdoc */ + /** + * @private + * @class + */ + var NavigatorAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function NavigatorAxisAdditions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * @private + */ + NavigatorAxisAdditions.prototype.destroy = function () { + this.axis = void 0; + }; + /** + * Add logic to normalize the zoomed range in order to preserve the pressed + * state of range selector buttons + * + * @private + * @function Highcharts.Axis#toFixedRange + * @param {number} [pxMin] + * @param {number} [pxMax] + * @param {number} [fixedMin] + * @param {number} [fixedMax] + * @return {*} + */ + NavigatorAxisAdditions.prototype.toFixedRange = function (pxMin, pxMax, fixedMin, fixedMax) { + var navigator = this; + var axis = navigator.axis; + var chart = axis.chart; + var fixedRange = chart && chart.fixedRange, halfPointRange = (axis.pointRange || 0) / 2, newMin = pick(fixedMin, axis.translate(pxMin, true, !axis.horiz)), newMax = pick(fixedMax, axis.translate(pxMax, true, !axis.horiz)), changeRatio = fixedRange && (newMax - newMin) / fixedRange; + // Add/remove half point range to/from the extremes (#1172) + if (!defined(fixedMin)) { + newMin = correctFloat(newMin + halfPointRange); + } + if (!defined(fixedMax)) { + newMax = correctFloat(newMax - halfPointRange); + } + // If the difference between the fixed range and the actual requested + // range is too great, the user is dragging across an ordinal gap, and + // we need to release the range selector button. + if (changeRatio > 0.7 && changeRatio < 1.3) { + if (fixedMax) { + newMin = newMax - fixedRange; + } + else { + newMax = newMin + fixedRange; + } + } + if (!isNumber(newMin) || !isNumber(newMax)) { // #1195, #7411 + newMin = newMax = void 0; + } + return { + min: newMin, + max: newMax + }; + }; + return NavigatorAxisAdditions; + }()); + /** + * @private + * @class + */ + var NavigatorAxis = /** @class */ (function () { + function NavigatorAxis() { + } + /* * + * + * Static Functions + * + * */ + /** + * @private + */ + NavigatorAxis.compose = function (AxisClass) { + AxisClass.keepProps.push('navigatorAxis'); + /* eslint-disable no-invalid-this */ + addEvent(AxisClass, 'init', function () { + var axis = this; + if (!axis.navigatorAxis) { + axis.navigatorAxis = new NavigatorAxisAdditions(axis); + } + }); + // For Stock charts, override selection zooming with some special + // features because X axis zooming is already allowed by the Navigator + // and Range selector. + addEvent(AxisClass, 'zoom', function (e) { + var axis = this; + var chart = axis.chart; + var chartOptions = chart.options; + var navigator = chartOptions.navigator; + var navigatorAxis = axis.navigatorAxis; + var pinchType = chartOptions.chart.pinchType; + var rangeSelector = chartOptions.rangeSelector; + var zoomType = chartOptions.chart.zoomType; + var previousZoom; + if (axis.isXAxis && ((navigator && navigator.enabled) || + (rangeSelector && rangeSelector.enabled))) { + // For y only zooming, ignore the X axis completely + if (zoomType === 'y') { + e.zoomed = false; + // For xy zooming, record the state of the zoom before zoom + // selection, then when the reset button is pressed, revert to + // this state. This should apply only if the chart is + // initialized with a range (#6612), otherwise zoom all the way + // out. + } + else if (((!isTouchDevice && zoomType === 'xy') || + (isTouchDevice && pinchType === 'xy')) && + axis.options.range) { + previousZoom = navigatorAxis.previousZoom; + if (defined(e.newMin)) { + navigatorAxis.previousZoom = [axis.min, axis.max]; + } + else if (previousZoom) { + e.newMin = previousZoom[0]; + e.newMax = previousZoom[1]; + navigatorAxis.previousZoom = void 0; + } + } + } + if (typeof e.zoomed !== 'undefined') { + e.preventDefault(); + } + }); + /* eslint-enable no-invalid-this */ + }; + /* * + * + * Static Properties + * + * */ + /** + * @private + */ + NavigatorAxis.AdditionsClass = NavigatorAxisAdditions; + return NavigatorAxis; + }()); + + return NavigatorAxis; + }); + _registerModule(_modules, 'parts/Navigator.js', [_modules['parts/Axis.js'], _modules['parts/Color.js'], _modules['parts/Globals.js'], _modules['parts/NavigatorAxis.js'], _modules['parts/Scrollbar.js'], _modules['parts/Utilities.js']], function (Axis, Color, H, NavigatorAxis, Scrollbar, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var color = Color.parse; + var addEvent = U.addEvent, clamp = U.clamp, correctFloat = U.correctFloat, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, erase = U.erase, extend = U.extend, find = U.find, isArray = U.isArray, isNumber = U.isNumber, merge = U.merge, pick = U.pick, removeEvent = U.removeEvent, splat = U.splat; + var Chart = H.Chart, defaultOptions = H.defaultOptions, hasTouch = H.hasTouch, isTouchDevice = H.isTouchDevice, Series = H.Series, seriesTypes = H.seriesTypes, defaultSeriesType, + // Finding the min or max of a set of variables where we don't know if they + // are defined, is a pattern that is repeated several places in Highcharts. + // Consider making this a global utility method. + numExt = function (extreme) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + var numbers = [].filter.call(args, isNumber); + if (numbers.length) { + return Math[extreme].apply(0, numbers); + } + }; + defaultSeriesType = typeof seriesTypes.areaspline === 'undefined' ? + 'line' : + 'areaspline'; + extend(defaultOptions, { + /** + * Maximum range which can be set using the navigator's handles. + * Opposite of [xAxis.minRange](#xAxis.minRange). + * + * @sample {highstock} stock/navigator/maxrange/ + * Defined max and min range + * + * @type {number} + * @since 6.0.0 + * @product highstock gantt + * @apioption xAxis.maxRange + */ + /** + * The navigator is a small series below the main series, displaying + * a view of the entire data set. It provides tools to zoom in and + * out on parts of the data as well as panning across the dataset. + * + * @product highstock gantt + * @optionparent navigator + */ + navigator: { + /** + * Whether the navigator and scrollbar should adapt to updated data + * in the base X axis. When loading data async, as in the demo below, + * this should be `false`. Otherwise new data will trigger navigator + * redraw, which will cause unwanted looping. In the demo below, the + * data in the navigator is set only once. On navigating, only the main + * chart content is updated. + * + * @sample {highstock} stock/demo/lazy-loading/ + * Set to false with async data loading + * + * @type {boolean} + * @default true + * @apioption navigator.adaptToUpdatedData + */ + /** + * An integer identifying the index to use for the base series, or a + * string representing the id of the series. + * + * **Note**: As of Highcharts 5.0, this is now a deprecated option. + * Prefer [series.showInNavigator](#plotOptions.series.showInNavigator). + * + * @see [series.showInNavigator](#plotOptions.series.showInNavigator) + * + * @deprecated + * @type {number|string} + * @default 0 + * @apioption navigator.baseSeries + */ + /** + * Enable or disable the navigator. + * + * @sample {highstock} stock/navigator/enabled/ + * Disable the navigator + * + * @type {boolean} + * @default true + * @apioption navigator.enabled + */ + /** + * When the chart is inverted, whether to draw the navigator on the + * opposite side. + * + * @type {boolean} + * @default false + * @since 5.0.8 + * @apioption navigator.opposite + */ + /** + * The height of the navigator. + * + * @sample {highstock} stock/navigator/height/ + * A higher navigator + */ + height: 40, + /** + * The distance from the nearest element, the X axis or X axis labels. + * + * @sample {highstock} stock/navigator/margin/ + * A margin of 2 draws the navigator closer to the X axis labels + */ + margin: 25, + /** + * Whether the mask should be inside the range marking the zoomed + * range, or outside. In Highstock 1.x it was always `false`. + * + * @sample {highstock} stock/navigator/maskinside-false/ + * False, mask outside + * + * @since 2.0 + */ + maskInside: true, + /** + * Options for the handles for dragging the zoomed area. + * + * @sample {highstock} stock/navigator/handles/ + * Colored handles + */ + handles: { + /** + * Width for handles. + * + * @sample {highstock} stock/navigator/styled-handles/ + * Styled handles + * + * @since 6.0.0 + */ + width: 7, + /** + * Height for handles. + * + * @sample {highstock} stock/navigator/styled-handles/ + * Styled handles + * + * @since 6.0.0 + */ + height: 15, + /** + * Array to define shapes of handles. 0-index for left, 1-index for + * right. + * + * Additionally, the URL to a graphic can be given on this form: + * `url(graphic.png)`. Note that for the image to be applied to + * exported charts, its URL needs to be accessible by the export + * server. + * + * Custom callbacks for symbol path generation can also be added to + * `Highcharts.SVGRenderer.prototype.symbols`. The callback is then + * used by its method name, as shown in the demo. + * + * @sample {highstock} stock/navigator/styled-handles/ + * Styled handles + * + * @type {Array} + * @default ["navigator-handle", "navigator-handle"] + * @since 6.0.0 + */ + symbols: ['navigator-handle', 'navigator-handle'], + /** + * Allows to enable/disable handles. + * + * @since 6.0.0 + */ + enabled: true, + /** + * The width for the handle border and the stripes inside. + * + * @sample {highstock} stock/navigator/styled-handles/ + * Styled handles + * + * @since 6.0.0 + * @apioption navigator.handles.lineWidth + */ + lineWidth: 1, + /** + * The fill for the handle. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + backgroundColor: '#f2f2f2', + /** + * The stroke for the handle border and the stripes inside. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + borderColor: '#999999' + }, + /** + * The color of the mask covering the areas of the navigator series + * that are currently not visible in the main series. The default + * color is bluish with an opacity of 0.3 to see the series below. + * + * @see In styled mode, the mask is styled with the + * `.highcharts-navigator-mask` and + * `.highcharts-navigator-mask-inside` classes. + * + * @sample {highstock} stock/navigator/maskfill/ + * Blue, semi transparent mask + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default rgba(102,133,194,0.3) + */ + maskFill: color('#6685c2').setOpacity(0.3).get(), + /** + * The color of the line marking the currently zoomed area in the + * navigator. + * + * @sample {highstock} stock/navigator/outline/ + * 2px blue outline + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #cccccc + */ + outlineColor: '#cccccc', + /** + * The width of the line marking the currently zoomed area in the + * navigator. + * + * @see In styled mode, the outline stroke width is set with the + * `.highcharts-navigator-outline` class. + * + * @sample {highstock} stock/navigator/outline/ + * 2px blue outline + * + * @type {number} + */ + outlineWidth: 1, + /** + * Options for the navigator series. Available options are the same + * as any series, documented at [plotOptions](#plotOptions.series) + * and [series](#series). + * + * Unless data is explicitly defined on navigator.series, the data + * is borrowed from the first series in the chart. + * + * Default series options for the navigator series are: + * ```js + * series: { + * type: 'areaspline', + * fillOpacity: 0.05, + * dataGrouping: { + * smoothed: true + * }, + * lineWidth: 1, + * marker: { + * enabled: false + * } + * } + * ``` + * + * @see In styled mode, the navigator series is styled with the + * `.highcharts-navigator-series` class. + * + * @sample {highstock} stock/navigator/series-data/ + * Using a separate data set for the navigator + * @sample {highstock} stock/navigator/series/ + * A green navigator series + * + * @type {*|Array<*>|Highcharts.SeriesOptionsType|Array} + */ + series: { + /** + * The type of the navigator series. Defaults to `areaspline` if + * defined, otherwise `line`. + * + * Heads up: + * In column-type navigator, zooming is limited to at least one + * point with its `pointRange`. + * + * @sample {highstock} stock/navigator/column/ + * Column type navigator + * + * @type {string} + * @default areaspline + */ + type: defaultSeriesType, + /** + * The fill opacity of the navigator series. + */ + fillOpacity: 0.05, + /** + * The pixel line width of the navigator series. + */ + lineWidth: 1, + /** + * @ignore-option + */ + compare: null, + /** + * Unless data is explicitly defined, the data is borrowed from the + * first series in the chart. + * + * @type {Array|object|null>} + * @product highstock + * @apioption navigator.series.data + */ + /** + * Data grouping options for the navigator series. + * + * @extends plotOptions.series.dataGrouping + */ + dataGrouping: { + approximation: 'average', + enabled: true, + groupPixelWidth: 2, + smoothed: true, + // Day and week differs from plotOptions.series.dataGrouping + units: [ + ['millisecond', [1, 2, 5, 10, 20, 25, 50, 100, 200, 500]], + ['second', [1, 2, 5, 10, 15, 30]], + ['minute', [1, 2, 5, 10, 15, 30]], + ['hour', [1, 2, 3, 4, 6, 8, 12]], + ['day', [1, 2, 3, 4]], + ['week', [1, 2, 3]], + ['month', [1, 3, 6]], + ['year', null] + ] + }, + /** + * Data label options for the navigator series. Data labels are + * disabled by default on the navigator series. + * + * @extends plotOptions.series.dataLabels + */ + dataLabels: { + enabled: false, + zIndex: 2 // #1839 + }, + id: 'highcharts-navigator-series', + className: 'highcharts-navigator-series', + /** + * Sets the fill color of the navigator series. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption navigator.series.color + */ + /** + * Line color for the navigator series. Allows setting the color + * while disallowing the default candlestick setting. + * + * @type {Highcharts.ColorString|null} + */ + lineColor: null, + marker: { + enabled: false + }, + /** + * Since Highstock v8, default value is the same as default + * `pointRange` defined for a specific type (e.g. `null` for + * column type). + * + * In Highstock version < 8, defaults to 0. + * + * @extends plotOptions.series.pointRange + * @type {number|null} + * @apioption navigator.series.pointRange + */ + /** + * The threshold option. Setting it to 0 will make the default + * navigator area series draw its area from the 0 value and up. + * + * @type {number|null} + */ + threshold: null + }, + /** + * Options for the navigator X axis. Default series options for the + * navigator xAxis are: + * ```js + * xAxis: { + * tickWidth: 0, + * lineWidth: 0, + * gridLineWidth: 1, + * tickPixelInterval: 200, + * labels: { + * align: 'left', + * style: { + * color: '#888' + * }, + * x: 3, + * y: -4 + * } + * } + * ``` + * + * @extends xAxis + * @excluding linkedTo, maxZoom, minRange, opposite, range, scrollbar, + * showEmpty, maxRange + */ + xAxis: { + /** + * Additional range on the right side of the xAxis. Works similar to + * xAxis.maxPadding, but value is set in milliseconds. + * Can be set for both, main xAxis and navigator's xAxis. + * + * @since 6.0.0 + */ + overscroll: 0, + className: 'highcharts-navigator-xaxis', + tickLength: 0, + lineWidth: 0, + gridLineColor: '#e6e6e6', + gridLineWidth: 1, + tickPixelInterval: 200, + labels: { + align: 'left', + /** + * @type {Highcharts.CSSObject} + */ + style: { + /** @ignore */ + color: '#999999' + }, + x: 3, + y: -4 + }, + crosshair: false + }, + /** + * Options for the navigator Y axis. Default series options for the + * navigator yAxis are: + * ```js + * yAxis: { + * gridLineWidth: 0, + * startOnTick: false, + * endOnTick: false, + * minPadding: 0.1, + * maxPadding: 0.1, + * labels: { + * enabled: false + * }, + * title: { + * text: null + * }, + * tickWidth: 0 + * } + * ``` + * + * @extends yAxis + * @excluding height, linkedTo, maxZoom, minRange, ordinal, range, + * showEmpty, scrollbar, top, units, maxRange, minLength, + * maxLength, resize + */ + yAxis: { + className: 'highcharts-navigator-yaxis', + gridLineWidth: 0, + startOnTick: false, + endOnTick: false, + minPadding: 0.1, + maxPadding: 0.1, + labels: { + enabled: false + }, + crosshair: false, + title: { + text: null + }, + tickLength: 0, + tickWidth: 0 + } + } + }); + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Draw one of the handles on the side of the zoomed range in the navigator + * + * @private + * @function Highcharts.Renderer#symbols.navigator-handle + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @param {Highcharts.NavigatorHandlesOptions} options + * @return {Highcharts.SVGPathArray} + * Path to be used in a handle + */ + H.Renderer.prototype.symbols['navigator-handle'] = function (x, y, w, h, options) { + var halfWidth = options.width / 2, markerPosition = Math.round(halfWidth / 3) + 0.5, height = options.height || 0; + return [ + ['M', -halfWidth - 1, 0.5], + ['L', halfWidth, 0.5], + ['L', halfWidth, height + 0.5], + ['L', -halfWidth - 1, height + 0.5], + ['L', -halfWidth - 1, 0.5], + ['M', -markerPosition, 4], + ['L', -markerPosition, height - 3], + ['M', markerPosition - 1, 4], + ['L', markerPosition - 1, height - 3] + ]; + }; + /** + * The Navigator class + * + * @private + * @class + * @name Highcharts.Navigator + * + * @param {Highcharts.Chart} chart + * Chart object + */ + var Navigator = /** @class */ (function () { + function Navigator(chart) { + this.baseSeries = void 0; + this.chart = void 0; + this.handles = void 0; + this.height = void 0; + this.left = void 0; + this.navigatorEnabled = void 0; + this.navigatorGroup = void 0; + this.navigatorOptions = void 0; + this.navigatorSeries = void 0; + this.navigatorSize = void 0; + this.opposite = void 0; + this.outline = void 0; + this.outlineHeight = void 0; + this.range = void 0; + this.rendered = void 0; + this.shades = void 0; + this.size = void 0; + this.top = void 0; + this.xAxis = void 0; + this.yAxis = void 0; + this.zoomedMax = void 0; + this.zoomedMin = void 0; + this.init(chart); + } + /** + * Draw one of the handles on the side of the zoomed range in the navigator + * + * @private + * @function Highcharts.Navigator#drawHandle + * + * @param {number} x + * The x center for the handle + * + * @param {number} index + * 0 for left and 1 for right + * + * @param {boolean|undefined} inverted + * flag for chart.inverted + * + * @param {string} verb + * use 'animate' or 'attr' + */ + Navigator.prototype.drawHandle = function (x, index, inverted, verb) { + var navigator = this, height = navigator.navigatorOptions.handles.height; + // Place it + navigator.handles[index][verb](inverted ? { + translateX: Math.round(navigator.left + navigator.height / 2), + translateY: Math.round(navigator.top + parseInt(x, 10) + 0.5 - height) + } : { + translateX: Math.round(navigator.left + parseInt(x, 10)), + translateY: Math.round(navigator.top + navigator.height / 2 - height / 2 - 1) + }); + }; + /** + * Render outline around the zoomed range + * + * @private + * @function Highcharts.Navigator#drawOutline + * + * @param {number} zoomedMin + * in pixels position where zoomed range starts + * + * @param {number} zoomedMax + * in pixels position where zoomed range ends + * + * @param {boolean|undefined} inverted + * flag if chart is inverted + * + * @param {string} verb + * use 'animate' or 'attr' + */ + Navigator.prototype.drawOutline = function (zoomedMin, zoomedMax, inverted, verb) { + var navigator = this, maskInside = navigator.navigatorOptions.maskInside, outlineWidth = navigator.outline.strokeWidth(), halfOutline = outlineWidth / 2, outlineCorrection = (outlineWidth % 2) / 2, // #5800 + outlineHeight = navigator.outlineHeight, scrollbarHeight = navigator.scrollbarHeight || 0, navigatorSize = navigator.size, left = navigator.left - scrollbarHeight, navigatorTop = navigator.top, verticalMin, path; + if (inverted) { + left -= halfOutline; + verticalMin = navigatorTop + zoomedMax + outlineCorrection; + zoomedMax = navigatorTop + zoomedMin + outlineCorrection; + path = [ + ['M', left + outlineHeight, navigatorTop - scrollbarHeight - outlineCorrection], + ['L', left + outlineHeight, verticalMin], + ['L', left, verticalMin], + ['L', left, zoomedMax], + ['L', left + outlineHeight, zoomedMax], + ['L', left + outlineHeight, navigatorTop + navigatorSize + scrollbarHeight] + ]; + if (maskInside) { + path.push(['M', left + outlineHeight, verticalMin - halfOutline], // upper left of zoomed range + ['L', left + outlineHeight, zoomedMax + halfOutline] // upper right of z.r. + ); + } + } + else { + zoomedMin += left + scrollbarHeight - outlineCorrection; + zoomedMax += left + scrollbarHeight - outlineCorrection; + navigatorTop += halfOutline; + path = [ + ['M', left, navigatorTop], + ['L', zoomedMin, navigatorTop], + ['L', zoomedMin, navigatorTop + outlineHeight], + ['L', zoomedMax, navigatorTop + outlineHeight], + ['L', zoomedMax, navigatorTop], + ['L', left + navigatorSize + scrollbarHeight * 2, navigatorTop] // right + ]; + if (maskInside) { + path.push(['M', zoomedMin - halfOutline, navigatorTop], // upper left of zoomed range + ['L', zoomedMax + halfOutline, navigatorTop] // upper right of z.r. + ); + } + } + navigator.outline[verb]({ + d: path + }); + }; + /** + * Render outline around the zoomed range + * + * @private + * @function Highcharts.Navigator#drawMasks + * + * @param {number} zoomedMin + * in pixels position where zoomed range starts + * + * @param {number} zoomedMax + * in pixels position where zoomed range ends + * + * @param {boolean|undefined} inverted + * flag if chart is inverted + * + * @param {string} verb + * use 'animate' or 'attr' + */ + Navigator.prototype.drawMasks = function (zoomedMin, zoomedMax, inverted, verb) { + var navigator = this, left = navigator.left, top = navigator.top, navigatorHeight = navigator.height, height, width, x, y; + // Determine rectangle position & size + // According to (non)inverted position: + if (inverted) { + x = [left, left, left]; + y = [top, top + zoomedMin, top + zoomedMax]; + width = [navigatorHeight, navigatorHeight, navigatorHeight]; + height = [ + zoomedMin, + zoomedMax - zoomedMin, + navigator.size - zoomedMax + ]; + } + else { + x = [left, left + zoomedMin, left + zoomedMax]; + y = [top, top, top]; + width = [ + zoomedMin, + zoomedMax - zoomedMin, + navigator.size - zoomedMax + ]; + height = [navigatorHeight, navigatorHeight, navigatorHeight]; + } + navigator.shades.forEach(function (shade, i) { + shade[verb]({ + x: x[i], + y: y[i], + width: width[i], + height: height[i] + }); + }); + }; + /** + * Generate DOM elements for a navigator: + * + * - main navigator group + * + * - all shades + * + * - outline + * + * - handles + * + * @private + * @function Highcharts.Navigator#renderElements + */ + Navigator.prototype.renderElements = function () { + var navigator = this, navigatorOptions = navigator.navigatorOptions, maskInside = navigatorOptions.maskInside, chart = navigator.chart, inverted = chart.inverted, renderer = chart.renderer, navigatorGroup, mouseCursor = { + cursor: inverted ? 'ns-resize' : 'ew-resize' + }; + // Create the main navigator group + navigator.navigatorGroup = navigatorGroup = renderer.g('navigator') + .attr({ + zIndex: 8, + visibility: 'hidden' + }) + .add(); + // Create masks, each mask will get events and fill: + [ + !maskInside, + maskInside, + !maskInside + ].forEach(function (hasMask, index) { + navigator.shades[index] = renderer.rect() + .addClass('highcharts-navigator-mask' + + (index === 1 ? '-inside' : '-outside')) + .add(navigatorGroup); + if (!chart.styledMode) { + navigator.shades[index] + .attr({ + fill: hasMask ? + navigatorOptions.maskFill : + 'rgba(0,0,0,0)' + }) + .css((index === 1) && mouseCursor); + } + }); + // Create the outline: + navigator.outline = renderer.path() + .addClass('highcharts-navigator-outline') + .add(navigatorGroup); + if (!chart.styledMode) { + navigator.outline.attr({ + 'stroke-width': navigatorOptions.outlineWidth, + stroke: navigatorOptions.outlineColor + }); + } + // Create the handlers: + if (navigatorOptions.handles.enabled) { + [0, 1].forEach(function (index) { + navigatorOptions.handles.inverted = chart.inverted; + navigator.handles[index] = renderer.symbol(navigatorOptions.handles.symbols[index], -navigatorOptions.handles.width / 2 - 1, 0, navigatorOptions.handles.width, navigatorOptions.handles.height, navigatorOptions.handles); + // zIndex = 6 for right handle, 7 for left. + // Can't be 10, because of the tooltip in inverted chart #2908 + navigator.handles[index].attr({ zIndex: 7 - index }) + .addClass('highcharts-navigator-handle ' + + 'highcharts-navigator-handle-' + + ['left', 'right'][index]).add(navigatorGroup); + if (!chart.styledMode) { + var handlesOptions = navigatorOptions.handles; + navigator.handles[index] + .attr({ + fill: handlesOptions.backgroundColor, + stroke: handlesOptions.borderColor, + 'stroke-width': handlesOptions.lineWidth + }) + .css(mouseCursor); + } + }); + } + }; + /** + * Update navigator + * + * @private + * @function Highcharts.Navigator#update + * + * @param {Highcharts.NavigatorOptions} options + * Options to merge in when updating navigator + */ + Navigator.prototype.update = function (options) { + // Remove references to old navigator series in base series + (this.series || []).forEach(function (series) { + if (series.baseSeries) { + delete series.baseSeries.navigatorSeries; + } + }); + // Destroy and rebuild navigator + this.destroy(); + var chartOptions = this.chart.options; + merge(true, chartOptions.navigator, this.options, options); + this.init(this.chart); + }; + /** + * Render the navigator + * + * @private + * @function Highcharts.Navigator#render + * @param {number} min + * X axis value minimum + * @param {number} max + * X axis value maximum + * @param {number} [pxMin] + * Pixel value minimum + * @param {number} [pxMax] + * Pixel value maximum + * @return {void} + */ + Navigator.prototype.render = function (min, max, pxMin, pxMax) { + var navigator = this, chart = navigator.chart, navigatorWidth, scrollbarLeft, scrollbarTop, scrollbarHeight = navigator.scrollbarHeight, navigatorSize, xAxis = navigator.xAxis, pointRange = xAxis.pointRange || 0, scrollbarXAxis = xAxis.navigatorAxis.fake ? chart.xAxis[0] : xAxis, navigatorEnabled = navigator.navigatorEnabled, zoomedMin, zoomedMax, rendered = navigator.rendered, inverted = chart.inverted, verb, newMin, newMax, currentRange, minRange = chart.xAxis[0].minRange, maxRange = chart.xAxis[0].options.maxRange; + // Don't redraw while moving the handles (#4703). + if (this.hasDragged && !defined(pxMin)) { + return; + } + min = correctFloat(min - pointRange / 2); + max = correctFloat(max + pointRange / 2); + // Don't render the navigator until we have data (#486, #4202, #5172). + if (!isNumber(min) || !isNumber(max)) { + // However, if navigator was already rendered, we may need to resize + // it. For example hidden series, but visible navigator (#6022). + if (rendered) { + pxMin = 0; + pxMax = pick(xAxis.width, scrollbarXAxis.width); + } + else { + return; + } + } + navigator.left = pick(xAxis.left, + // in case of scrollbar only, without navigator + chart.plotLeft + scrollbarHeight + + (inverted ? chart.plotWidth : 0)); + navigator.size = zoomedMax = navigatorSize = pick(xAxis.len, (inverted ? chart.plotHeight : chart.plotWidth) - + 2 * scrollbarHeight); + if (inverted) { + navigatorWidth = scrollbarHeight; + } + else { + navigatorWidth = navigatorSize + 2 * scrollbarHeight; + } + // Get the pixel position of the handles + pxMin = pick(pxMin, xAxis.toPixels(min, true)); + pxMax = pick(pxMax, xAxis.toPixels(max, true)); + // Verify (#1851, #2238) + if (!isNumber(pxMin) || Math.abs(pxMin) === Infinity) { + pxMin = 0; + pxMax = navigatorWidth; + } + // Are we below the minRange? (#2618, #6191) + newMin = xAxis.toValue(pxMin, true); + newMax = xAxis.toValue(pxMax, true); + currentRange = Math.abs(correctFloat(newMax - newMin)); + if (currentRange < minRange) { + if (this.grabbedLeft) { + pxMin = xAxis.toPixels(newMax - minRange - pointRange, true); + } + else if (this.grabbedRight) { + pxMax = xAxis.toPixels(newMin + minRange + pointRange, true); + } + } + else if (defined(maxRange) && + correctFloat(currentRange - pointRange) > maxRange) { + if (this.grabbedLeft) { + pxMin = xAxis.toPixels(newMax - maxRange - pointRange, true); + } + else if (this.grabbedRight) { + pxMax = xAxis.toPixels(newMin + maxRange + pointRange, true); + } + } + // Handles are allowed to cross, but never exceed the plot area + navigator.zoomedMax = clamp(Math.max(pxMin, pxMax), 0, zoomedMax); + navigator.zoomedMin = clamp(navigator.fixedWidth ? + navigator.zoomedMax - navigator.fixedWidth : + Math.min(pxMin, pxMax), 0, zoomedMax); + navigator.range = navigator.zoomedMax - navigator.zoomedMin; + zoomedMax = Math.round(navigator.zoomedMax); + zoomedMin = Math.round(navigator.zoomedMin); + if (navigatorEnabled) { + navigator.navigatorGroup.attr({ + visibility: 'visible' + }); + // Place elements + verb = rendered && !navigator.hasDragged ? 'animate' : 'attr'; + navigator.drawMasks(zoomedMin, zoomedMax, inverted, verb); + navigator.drawOutline(zoomedMin, zoomedMax, inverted, verb); + if (navigator.navigatorOptions.handles.enabled) { + navigator.drawHandle(zoomedMin, 0, inverted, verb); + navigator.drawHandle(zoomedMax, 1, inverted, verb); + } + } + if (navigator.scrollbar) { + if (inverted) { + scrollbarTop = navigator.top - scrollbarHeight; + scrollbarLeft = navigator.left - scrollbarHeight + + (navigatorEnabled || !scrollbarXAxis.opposite ? 0 : + // Multiple axes has offsets: + (scrollbarXAxis.titleOffset || 0) + + // Self margin from the axis.title + scrollbarXAxis.axisTitleMargin); + scrollbarHeight = navigatorSize + 2 * scrollbarHeight; + } + else { + scrollbarTop = navigator.top + (navigatorEnabled ? + navigator.height : + -scrollbarHeight); + scrollbarLeft = navigator.left - scrollbarHeight; + } + // Reposition scrollbar + navigator.scrollbar.position(scrollbarLeft, scrollbarTop, navigatorWidth, scrollbarHeight); + // Keep scale 0-1 + navigator.scrollbar.setRange( + // Use real value, not rounded because range can be very small + // (#1716) + navigator.zoomedMin / (navigatorSize || 1), navigator.zoomedMax / (navigatorSize || 1)); + } + navigator.rendered = true; + }; + /** + * Set up the mouse and touch events for the navigator + * + * @private + * @function Highcharts.Navigator#addMouseEvents + */ + Navigator.prototype.addMouseEvents = function () { + var navigator = this, chart = navigator.chart, container = chart.container, eventsToUnbind = [], mouseMoveHandler, mouseUpHandler; + /** + * Create mouse events' handlers. + * Make them as separate functions to enable wrapping them: + */ + navigator.mouseMoveHandler = mouseMoveHandler = function (e) { + navigator.onMouseMove(e); + }; + navigator.mouseUpHandler = mouseUpHandler = function (e) { + navigator.onMouseUp(e); + }; + // Add shades and handles mousedown events + eventsToUnbind = navigator.getPartsEvents('mousedown'); + // Add mouse move and mouseup events. These are bind to doc/container, + // because Navigator.grabbedSomething flags are stored in mousedown + // events + eventsToUnbind.push(addEvent(chart.renderTo, 'mousemove', mouseMoveHandler), addEvent(container.ownerDocument, 'mouseup', mouseUpHandler)); + // Touch events + if (hasTouch) { + eventsToUnbind.push(addEvent(chart.renderTo, 'touchmove', mouseMoveHandler), addEvent(container.ownerDocument, 'touchend', mouseUpHandler)); + eventsToUnbind.concat(navigator.getPartsEvents('touchstart')); + } + navigator.eventsToUnbind = eventsToUnbind; + // Data events + if (navigator.series && navigator.series[0]) { + eventsToUnbind.push(addEvent(navigator.series[0].xAxis, 'foundExtremes', function () { + chart.navigator.modifyNavigatorAxisExtremes(); + })); + } + }; + /** + * Generate events for handles and masks + * + * @private + * @function Highcharts.Navigator#getPartsEvents + * + * @param {string} eventName + * Event name handler, 'mousedown' or 'touchstart' + * + * @return {Array} + * An array of functions to remove navigator functions from the + * events again. + */ + Navigator.prototype.getPartsEvents = function (eventName) { + var navigator = this, events = []; + ['shades', 'handles'].forEach(function (name) { + navigator[name].forEach(function (navigatorItem, index) { + events.push(addEvent(navigatorItem.element, eventName, function (e) { + navigator[name + 'Mousedown'](e, index); + })); + }); + }); + return events; + }; + /** + * Mousedown on a shaded mask, either: + * + * - will be stored for future drag&drop + * + * - will directly shift to a new range + * + * @private + * @function Highcharts.Navigator#shadesMousedown + * + * @param {Highcharts.PointerEventObject} e + * Mouse event + * + * @param {number} index + * Index of a mask in Navigator.shades array + */ + Navigator.prototype.shadesMousedown = function (e, index) { + e = this.chart.pointer.normalize(e); + var navigator = this, chart = navigator.chart, xAxis = navigator.xAxis, zoomedMin = navigator.zoomedMin, navigatorPosition = navigator.left, navigatorSize = navigator.size, range = navigator.range, chartX = e.chartX, fixedMax, fixedMin, ext, left; + // For inverted chart, swap some options: + if (chart.inverted) { + chartX = e.chartY; + navigatorPosition = navigator.top; + } + if (index === 1) { + // Store information for drag&drop + navigator.grabbedCenter = chartX; + navigator.fixedWidth = range; + navigator.dragOffset = chartX - zoomedMin; + } + else { + // Shift the range by clicking on shaded areas + left = chartX - navigatorPosition - range / 2; + if (index === 0) { + left = Math.max(0, left); + } + else if (index === 2 && left + range >= navigatorSize) { + left = navigatorSize - range; + if (navigator.reversedExtremes) { + // #7713 + left -= range; + fixedMin = navigator.getUnionExtremes().dataMin; + } + else { + // #2293, #3543 + fixedMax = navigator.getUnionExtremes().dataMax; + } + } + if (left !== zoomedMin) { // it has actually moved + navigator.fixedWidth = range; // #1370 + ext = xAxis.navigatorAxis.toFixedRange(left, left + range, fixedMin, fixedMax); + if (defined(ext.min)) { // #7411 + chart.xAxis[0].setExtremes(Math.min(ext.min, ext.max), Math.max(ext.min, ext.max), true, null, // auto animation + { trigger: 'navigator' }); + } + } + } + }; + /** + * Mousedown on a handle mask. + * Will store necessary information for drag&drop. + * + * @private + * @function Highcharts.Navigator#handlesMousedown + * @param {Highcharts.PointerEventObject} e + * Mouse event + * @param {number} index + * Index of a handle in Navigator.handles array + * @return {void} + */ + Navigator.prototype.handlesMousedown = function (e, index) { + e = this.chart.pointer.normalize(e); + var navigator = this, chart = navigator.chart, baseXAxis = chart.xAxis[0], + // For reversed axes, min and max are changed, + // so the other extreme should be stored + reverse = navigator.reversedExtremes; + if (index === 0) { + // Grab the left handle + navigator.grabbedLeft = true; + navigator.otherHandlePos = navigator.zoomedMax; + navigator.fixedExtreme = reverse ? baseXAxis.min : baseXAxis.max; + } + else { + // Grab the right handle + navigator.grabbedRight = true; + navigator.otherHandlePos = navigator.zoomedMin; + navigator.fixedExtreme = reverse ? baseXAxis.max : baseXAxis.min; + } + chart.fixedRange = null; + }; + /** + * Mouse move event based on x/y mouse position. + * + * @private + * @function Highcharts.Navigator#onMouseMove + * + * @param {Highcharts.PointerEventObject} e + * Mouse event + */ + Navigator.prototype.onMouseMove = function (e) { + var navigator = this, chart = navigator.chart, left = navigator.left, navigatorSize = navigator.navigatorSize, range = navigator.range, dragOffset = navigator.dragOffset, inverted = chart.inverted, chartX; + // In iOS, a mousemove event with e.pageX === 0 is fired when holding + // the finger down in the center of the scrollbar. This should be + // ignored. + if (!e.touches || e.touches[0].pageX !== 0) { // #4696 + e = chart.pointer.normalize(e); + chartX = e.chartX; + // Swap some options for inverted chart + if (inverted) { + left = navigator.top; + chartX = e.chartY; + } + // Drag left handle or top handle + if (navigator.grabbedLeft) { + navigator.hasDragged = true; + navigator.render(0, 0, chartX - left, navigator.otherHandlePos); + // Drag right handle or bottom handle + } + else if (navigator.grabbedRight) { + navigator.hasDragged = true; + navigator.render(0, 0, navigator.otherHandlePos, chartX - left); + // Drag scrollbar or open area in navigator + } + else if (navigator.grabbedCenter) { + navigator.hasDragged = true; + if (chartX < dragOffset) { // outside left + chartX = dragOffset; + // outside right + } + else if (chartX > + navigatorSize + dragOffset - range) { + chartX = navigatorSize + dragOffset - range; + } + navigator.render(0, 0, chartX - dragOffset, chartX - dragOffset + range); + } + if (navigator.hasDragged && + navigator.scrollbar && + pick(navigator.scrollbar.options.liveRedraw, + // By default, don't run live redraw on VML, on touch + // devices or if the chart is in boost. + H.svg && !isTouchDevice && !this.chart.isBoosting)) { + e.DOMType = e.type; // DOMType is for IE8 + setTimeout(function () { + navigator.onMouseUp(e); + }, 0); + } + } + }; + /** + * Mouse up event based on x/y mouse position. + * + * @private + * @function Highcharts.Navigator#onMouseUp + * @param {Highcharts.PointerEventObject} e + * Mouse event + * @return {void} + */ + Navigator.prototype.onMouseUp = function (e) { + var navigator = this, chart = navigator.chart, xAxis = navigator.xAxis, scrollbar = navigator.scrollbar, DOMEvent = e.DOMEvent || e, inverted = chart.inverted, verb = navigator.rendered && !navigator.hasDragged ? + 'animate' : 'attr', zoomedMax = Math.round(navigator.zoomedMax), zoomedMin = Math.round(navigator.zoomedMin), unionExtremes, fixedMin, fixedMax, ext; + if ( + // MouseUp is called for both, navigator and scrollbar (that order), + // which causes calling afterSetExtremes twice. Prevent first call + // by checking if scrollbar is going to set new extremes (#6334) + (navigator.hasDragged && (!scrollbar || !scrollbar.hasDragged)) || + e.trigger === 'scrollbar') { + unionExtremes = navigator.getUnionExtremes(); + // When dragging one handle, make sure the other one doesn't change + if (navigator.zoomedMin === navigator.otherHandlePos) { + fixedMin = navigator.fixedExtreme; + } + else if (navigator.zoomedMax === navigator.otherHandlePos) { + fixedMax = navigator.fixedExtreme; + } + // Snap to right edge (#4076) + if (navigator.zoomedMax === navigator.size) { + fixedMax = navigator.reversedExtremes ? + unionExtremes.dataMin : + unionExtremes.dataMax; + } + // Snap to left edge (#7576) + if (navigator.zoomedMin === 0) { + fixedMin = navigator.reversedExtremes ? + unionExtremes.dataMax : + unionExtremes.dataMin; + } + ext = xAxis.navigatorAxis.toFixedRange(navigator.zoomedMin, navigator.zoomedMax, fixedMin, fixedMax); + if (defined(ext.min)) { + chart.xAxis[0].setExtremes(Math.min(ext.min, ext.max), Math.max(ext.min, ext.max), true, + // Run animation when clicking buttons, scrollbar track etc, + // but not when dragging handles or scrollbar + navigator.hasDragged ? false : null, { + trigger: 'navigator', + triggerOp: 'navigator-drag', + DOMEvent: DOMEvent // #1838 + }); + } + } + if (e.DOMType !== 'mousemove' && + e.DOMType !== 'touchmove') { + navigator.grabbedLeft = navigator.grabbedRight = + navigator.grabbedCenter = navigator.fixedWidth = + navigator.fixedExtreme = navigator.otherHandlePos = + navigator.hasDragged = navigator.dragOffset = null; + } + // Update position of navigator shades, outline and handles (#12573) + if (navigator.navigatorEnabled) { + if (navigator.shades) { + navigator.drawMasks(zoomedMin, zoomedMax, inverted, verb); + } + if (navigator.outline) { + navigator.drawOutline(zoomedMin, zoomedMax, inverted, verb); + } + if (navigator.navigatorOptions.handles.enabled && + Object.keys(navigator.handles).length === + navigator.handles.length) { + navigator.drawHandle(zoomedMin, 0, inverted, verb); + navigator.drawHandle(zoomedMax, 1, inverted, verb); + } + } + }; + /** + * Removes the event handlers attached previously with addEvents. + * + * @private + * @function Highcharts.Navigator#removeEvents + * @return {void} + */ + Navigator.prototype.removeEvents = function () { + if (this.eventsToUnbind) { + this.eventsToUnbind.forEach(function (unbind) { + unbind(); + }); + this.eventsToUnbind = void 0; + } + this.removeBaseSeriesEvents(); + }; + /** + * Remove data events. + * + * @private + * @function Highcharts.Navigator#removeBaseSeriesEvents + * @return {void} + */ + Navigator.prototype.removeBaseSeriesEvents = function () { + var baseSeries = this.baseSeries || []; + if (this.navigatorEnabled && baseSeries[0]) { + if (this.navigatorOptions.adaptToUpdatedData !== false) { + baseSeries.forEach(function (series) { + removeEvent(series, 'updatedData', this.updatedDataHandler); + }, this); + } + // We only listen for extremes-events on the first baseSeries + if (baseSeries[0].xAxis) { + removeEvent(baseSeries[0].xAxis, 'foundExtremes', this.modifyBaseAxisExtremes); + } + } + }; + /** + * Initialize the Navigator object + * + * @private + * @function Highcharts.Navigator#init + * + * @param {Highcharts.Chart} chart + */ + Navigator.prototype.init = function (chart) { + var chartOptions = chart.options, navigatorOptions = chartOptions.navigator, navigatorEnabled = navigatorOptions.enabled, scrollbarOptions = chartOptions.scrollbar, scrollbarEnabled = scrollbarOptions.enabled, height = navigatorEnabled ? navigatorOptions.height : 0, scrollbarHeight = scrollbarEnabled ? + scrollbarOptions.height : + 0; + this.handles = []; + this.shades = []; + this.chart = chart; + this.setBaseSeries(); + this.height = height; + this.scrollbarHeight = scrollbarHeight; + this.scrollbarEnabled = scrollbarEnabled; + this.navigatorEnabled = navigatorEnabled; + this.navigatorOptions = navigatorOptions; + this.scrollbarOptions = scrollbarOptions; + this.outlineHeight = height + scrollbarHeight; + this.opposite = pick(navigatorOptions.opposite, Boolean(!navigatorEnabled && chart.inverted)); // #6262 + var navigator = this, baseSeries = navigator.baseSeries, xAxisIndex = chart.xAxis.length, yAxisIndex = chart.yAxis.length, baseXaxis = baseSeries && baseSeries[0] && baseSeries[0].xAxis || + chart.xAxis[0] || { options: {} }; + chart.isDirtyBox = true; + if (navigator.navigatorEnabled) { + // an x axis is required for scrollbar also + navigator.xAxis = new Axis(chart, merge({ + // inherit base xAxis' break and ordinal options + breaks: baseXaxis.options.breaks, + ordinal: baseXaxis.options.ordinal + }, navigatorOptions.xAxis, { + id: 'navigator-x-axis', + yAxis: 'navigator-y-axis', + isX: true, + type: 'datetime', + index: xAxisIndex, + isInternal: true, + offset: 0, + keepOrdinalPadding: true, + startOnTick: false, + endOnTick: false, + minPadding: 0, + maxPadding: 0, + zoomEnabled: false + }, chart.inverted ? { + offsets: [scrollbarHeight, 0, -scrollbarHeight, 0], + width: height + } : { + offsets: [0, -scrollbarHeight, 0, scrollbarHeight], + height: height + })); + navigator.yAxis = new Axis(chart, merge(navigatorOptions.yAxis, { + id: 'navigator-y-axis', + alignTicks: false, + offset: 0, + index: yAxisIndex, + isInternal: true, + zoomEnabled: false + }, chart.inverted ? { + width: height + } : { + height: height + })); + // If we have a base series, initialize the navigator series + if (baseSeries || navigatorOptions.series.data) { + navigator.updateNavigatorSeries(false); + // If not, set up an event to listen for added series + } + else if (chart.series.length === 0) { + navigator.unbindRedraw = addEvent(chart, 'beforeRedraw', function () { + // We've got one, now add it as base + if (chart.series.length > 0 && !navigator.series) { + navigator.setBaseSeries(); + navigator.unbindRedraw(); // reset + } + }); + } + navigator.reversedExtremes = (chart.inverted && !navigator.xAxis.reversed) || (!chart.inverted && navigator.xAxis.reversed); + // Render items, so we can bind events to them: + navigator.renderElements(); + // Add mouse events + navigator.addMouseEvents(); + // in case of scrollbar only, fake an x axis to get translation + } + else { + navigator.xAxis = { + chart: chart, + navigatorAxis: { + fake: true + }, + translate: function (value, reverse) { + var axis = chart.xAxis[0], ext = axis.getExtremes(), scrollTrackWidth = axis.len - 2 * scrollbarHeight, min = numExt('min', axis.options.min, ext.dataMin), valueRange = numExt('max', axis.options.max, ext.dataMax) - min; + return reverse ? + // from pixel to value + (value * valueRange / scrollTrackWidth) + min : + // from value to pixel + scrollTrackWidth * (value - min) / valueRange; + }, + toPixels: function (value) { + return this.translate(value); + }, + toValue: function (value) { + return this.translate(value, true); + } + }; + navigator.xAxis.navigatorAxis.axis = navigator.xAxis; + navigator.xAxis.navigatorAxis.toFixedRange = (NavigatorAxis.AdditionsClass.prototype.toFixedRange.bind(navigator.xAxis.navigatorAxis)); + } + // Initialize the scrollbar + if (chart.options.scrollbar.enabled) { + chart.scrollbar = navigator.scrollbar = new Scrollbar(chart.renderer, merge(chart.options.scrollbar, { + margin: navigator.navigatorEnabled ? 0 : 10, + vertical: chart.inverted + }), chart); + addEvent(navigator.scrollbar, 'changed', function (e) { + var range = navigator.size, to = range * this.to, from = range * this.from; + navigator.hasDragged = navigator.scrollbar.hasDragged; + navigator.render(0, 0, from, to); + if (chart.options.scrollbar.liveRedraw || + (e.DOMType !== 'mousemove' && + e.DOMType !== 'touchmove')) { + setTimeout(function () { + navigator.onMouseUp(e); + }); + } + }); + } + // Add data events + navigator.addBaseSeriesEvents(); + // Add redraw events + navigator.addChartEvents(); + }; + /** + * Get the union data extremes of the chart - the outer data extremes of the + * base X axis and the navigator axis. + * + * @private + * @function Highcharts.Navigator#getUnionExtremes + * @param {boolean} [returnFalseOnNoBaseSeries] + * as the param says. + * @return {Highcharts.Dictionary<(number|undefined)>|undefined} + */ + Navigator.prototype.getUnionExtremes = function (returnFalseOnNoBaseSeries) { + var baseAxis = this.chart.xAxis[0], navAxis = this.xAxis, navAxisOptions = navAxis.options, baseAxisOptions = baseAxis.options, ret; + if (!returnFalseOnNoBaseSeries || baseAxis.dataMin !== null) { + ret = { + dataMin: pick(// #4053 + navAxisOptions && navAxisOptions.min, numExt('min', baseAxisOptions.min, baseAxis.dataMin, navAxis.dataMin, navAxis.min)), + dataMax: pick(navAxisOptions && navAxisOptions.max, numExt('max', baseAxisOptions.max, baseAxis.dataMax, navAxis.dataMax, navAxis.max)) + }; + } + return ret; + }; + /** + * Set the base series and update the navigator series from this. With a bit + * of modification we should be able to make this an API method to be called + * from the outside + * + * @private + * @function Highcharts.Navigator#setBaseSeries + * @param {Highcharts.SeriesOptionsType} [baseSeriesOptions] + * Additional series options for a navigator + * @param {boolean} [redraw] + * Whether to redraw after update. + * @return {void} + */ + Navigator.prototype.setBaseSeries = function (baseSeriesOptions, redraw) { + var chart = this.chart, baseSeries = this.baseSeries = []; + baseSeriesOptions = (baseSeriesOptions || + chart.options && chart.options.navigator.baseSeries || + (chart.series.length ? + // Find the first non-navigator series (#8430) + find(chart.series, function (s) { + return !s.options.isInternal; + }).index : + 0)); + // Iterate through series and add the ones that should be shown in + // navigator. + (chart.series || []).forEach(function (series, i) { + if ( + // Don't include existing nav series + !series.options.isInternal && + (series.options.showInNavigator || + (i === baseSeriesOptions || + series.options.id === baseSeriesOptions) && + series.options.showInNavigator !== false)) { + baseSeries.push(series); + } + }); + // When run after render, this.xAxis already exists + if (this.xAxis && !this.xAxis.navigatorAxis.fake) { + this.updateNavigatorSeries(true, redraw); + } + }; + /** + * Update series in the navigator from baseSeries, adding new if does not + * exist. + * + * @private + * @function Highcharts.Navigator.updateNavigatorSeries + * @param {boolean} addEvents + * @param {boolean} [redraw] + * @return {void} + */ + Navigator.prototype.updateNavigatorSeries = function (addEvents, redraw) { + var navigator = this, chart = navigator.chart, baseSeries = navigator.baseSeries, baseOptions, mergedNavSeriesOptions, chartNavigatorSeriesOptions = navigator.navigatorOptions.series, baseNavigatorOptions, navSeriesMixin = { + enableMouseTracking: false, + index: null, + linkedTo: null, + group: 'nav', + padXAxis: false, + xAxis: 'navigator-x-axis', + yAxis: 'navigator-y-axis', + showInLegend: false, + stacking: void 0, + isInternal: true, + states: { + inactive: { + opacity: 1 + } + } + }, + // Remove navigator series that are no longer in the baseSeries + navigatorSeries = navigator.series = + (navigator.series || []).filter(function (navSeries) { + var base = navSeries.baseSeries; + if (baseSeries.indexOf(base) < 0) { // Not in array + // If there is still a base series connected to this + // series, remove event handler and reference. + if (base) { + removeEvent(base, 'updatedData', navigator.updatedDataHandler); + delete base.navigatorSeries; + } + // Kill the nav series. It may already have been + // destroyed (#8715). + if (navSeries.chart) { + navSeries.destroy(); + } + return false; + } + return true; + }); + // Go through each base series and merge the options to create new + // series + if (baseSeries && baseSeries.length) { + baseSeries.forEach(function eachBaseSeries(base) { + var linkedNavSeries = base.navigatorSeries, userNavOptions = extend( + // Grab color and visibility from base as default + { + color: base.color, + visible: base.visible + }, !isArray(chartNavigatorSeriesOptions) ? + chartNavigatorSeriesOptions : + defaultOptions.navigator.series); + // Don't update if the series exists in nav and we have disabled + // adaptToUpdatedData. + if (linkedNavSeries && + navigator.navigatorOptions.adaptToUpdatedData === false) { + return; + } + navSeriesMixin.name = 'Navigator ' + baseSeries.length; + baseOptions = base.options || {}; + baseNavigatorOptions = baseOptions.navigatorOptions || {}; + mergedNavSeriesOptions = merge(baseOptions, navSeriesMixin, userNavOptions, baseNavigatorOptions); + // Once nav series type is resolved, pick correct pointRange + mergedNavSeriesOptions.pointRange = pick( + // Stricte set pointRange in options + userNavOptions.pointRange, baseNavigatorOptions.pointRange, + // Fallback to default values, e.g. `null` for column + defaultOptions.plotOptions[mergedNavSeriesOptions.type || 'line'].pointRange); + // Merge data separately. Do a slice to avoid mutating the + // navigator options from base series (#4923). + var navigatorSeriesData = baseNavigatorOptions.data || userNavOptions.data; + navigator.hasNavigatorData = + navigator.hasNavigatorData || !!navigatorSeriesData; + mergedNavSeriesOptions.data = + navigatorSeriesData || + baseOptions.data && baseOptions.data.slice(0); + // Update or add the series + if (linkedNavSeries && linkedNavSeries.options) { + linkedNavSeries.update(mergedNavSeriesOptions, redraw); + } + else { + base.navigatorSeries = chart.initSeries(mergedNavSeriesOptions); + base.navigatorSeries.baseSeries = base; // Store ref + navigatorSeries.push(base.navigatorSeries); + } + }); + } + // If user has defined data (and no base series) or explicitly defined + // navigator.series as an array, we create these series on top of any + // base series. + if (chartNavigatorSeriesOptions.data && + !(baseSeries && baseSeries.length) || + isArray(chartNavigatorSeriesOptions)) { + navigator.hasNavigatorData = false; + // Allow navigator.series to be an array + chartNavigatorSeriesOptions = + splat(chartNavigatorSeriesOptions); + chartNavigatorSeriesOptions.forEach(function (userSeriesOptions, i) { + navSeriesMixin.name = + 'Navigator ' + (navigatorSeries.length + 1); + mergedNavSeriesOptions = merge(defaultOptions.navigator.series, { + // Since we don't have a base series to pull color from, + // try to fake it by using color from series with same + // index. Otherwise pull from the colors array. We need + // an explicit color as otherwise updates will increment + // color counter and we'll get a new color for each + // update of the nav series. + color: chart.series[i] && + !chart.series[i].options.isInternal && + chart.series[i].color || + chart.options.colors[i] || + chart.options.colors[0] + }, navSeriesMixin, userSeriesOptions); + mergedNavSeriesOptions.data = userSeriesOptions.data; + if (mergedNavSeriesOptions.data) { + navigator.hasNavigatorData = true; + navigatorSeries.push(chart.initSeries(mergedNavSeriesOptions)); + } + }); + } + if (addEvents) { + this.addBaseSeriesEvents(); + } + }; + /** + * Add data events. + * For example when main series is updated we need to recalculate extremes + * + * @private + * @function Highcharts.Navigator#addBaseSeriesEvent + * @return {void} + */ + Navigator.prototype.addBaseSeriesEvents = function () { + var navigator = this, baseSeries = navigator.baseSeries || []; + // Bind modified extremes event to first base's xAxis only. + // In event of > 1 base-xAxes, the navigator will ignore those. + // Adding this multiple times to the same axis is no problem, as + // duplicates should be discarded by the browser. + if (baseSeries[0] && baseSeries[0].xAxis) { + addEvent(baseSeries[0].xAxis, 'foundExtremes', this.modifyBaseAxisExtremes); + } + baseSeries.forEach(function (base) { + // Link base series show/hide to navigator series visibility + addEvent(base, 'show', function () { + if (this.navigatorSeries) { + this.navigatorSeries.setVisible(true, false); + } + }); + addEvent(base, 'hide', function () { + if (this.navigatorSeries) { + this.navigatorSeries.setVisible(false, false); + } + }); + // Respond to updated data in the base series, unless explicitily + // not adapting to data changes. + if (this.navigatorOptions.adaptToUpdatedData !== false) { + if (base.xAxis) { + addEvent(base, 'updatedData', this.updatedDataHandler); + } + } + // Handle series removal + addEvent(base, 'remove', function () { + if (this.navigatorSeries) { + erase(navigator.series, this.navigatorSeries); + if (defined(this.navigatorSeries.options)) { + this.navigatorSeries.remove(false); + } + delete this.navigatorSeries; + } + }); + }, this); + }; + /** + * Get minimum from all base series connected to the navigator + * @private + * @param {number} currentSeriesMin + * Minium from the current series + * @return {number} Minimum from all series + */ + Navigator.prototype.getBaseSeriesMin = function (currentSeriesMin) { + return this.baseSeries.reduce(function (min, series) { + // (#10193) + return Math.min(min, series.xData ? series.xData[0] : min); + }, currentSeriesMin); + }; + /** + * Set the navigator x axis extremes to reflect the total. The navigator + * extremes should always be the extremes of the union of all series in the + * chart as well as the navigator series. + * + * @private + * @function Highcharts.Navigator#modifyNavigatorAxisExtremes + */ + Navigator.prototype.modifyNavigatorAxisExtremes = function () { + var xAxis = this.xAxis, unionExtremes; + if (typeof xAxis.getExtremes !== 'undefined') { + unionExtremes = this.getUnionExtremes(true); + if (unionExtremes && + (unionExtremes.dataMin !== xAxis.min || + unionExtremes.dataMax !== xAxis.max)) { + xAxis.min = unionExtremes.dataMin; + xAxis.max = unionExtremes.dataMax; + } + } + }; + /** + * Hook to modify the base axis extremes with information from the Navigator + * + * @private + * @function Highcharts.Navigator#modifyBaseAxisExtremes + */ + Navigator.prototype.modifyBaseAxisExtremes = function () { + var baseXAxis = this, navigator = baseXAxis.chart.navigator, baseExtremes = baseXAxis.getExtremes(), baseMin = baseExtremes.min, baseMax = baseExtremes.max, baseDataMin = baseExtremes.dataMin, baseDataMax = baseExtremes.dataMax, range = baseMax - baseMin, stickToMin = navigator.stickToMin, stickToMax = navigator.stickToMax, overscroll = pick(baseXAxis.options.overscroll, 0), newMax, newMin, navigatorSeries = navigator.series && navigator.series[0], hasSetExtremes = !!baseXAxis.setExtremes, + // When the extremes have been set by range selector button, don't + // stick to min or max. The range selector buttons will handle the + // extremes. (#5489) + unmutable = baseXAxis.eventArgs && + baseXAxis.eventArgs.trigger === 'rangeSelectorButton'; + if (!unmutable) { + // If the zoomed range is already at the min, move it to the right + // as new data comes in + if (stickToMin) { + newMin = baseDataMin; + newMax = newMin + range; + } + // If the zoomed range is already at the max, move it to the right + // as new data comes in + if (stickToMax) { + newMax = baseDataMax + overscroll; + // If stickToMin is true, the new min value is set above + if (!stickToMin) { + newMin = Math.max(baseDataMin, // don't go below data extremes (#13184) + newMax - range, navigator.getBaseSeriesMin(navigatorSeries && navigatorSeries.xData ? + navigatorSeries.xData[0] : + -Number.MAX_VALUE)); + } + } + // Update the extremes + if (hasSetExtremes && (stickToMin || stickToMax)) { + if (isNumber(newMin)) { + baseXAxis.min = baseXAxis.userMin = newMin; + baseXAxis.max = baseXAxis.userMax = newMax; + } + } + } + // Reset + navigator.stickToMin = + navigator.stickToMax = null; + }; + /** + * Handler for updated data on the base series. When data is modified, the + * navigator series must reflect it. This is called from the Chart.redraw + * function before axis and series extremes are computed. + * + * @private + * @function Highcharts.Navigator#updateDataHandler + */ + Navigator.prototype.updatedDataHandler = function () { + var navigator = this.chart.navigator, baseSeries = this, navigatorSeries = this.navigatorSeries, xDataMin = navigator.getBaseSeriesMin(baseSeries.xData[0]); + // If the scrollbar is scrolled all the way to the right, keep right as + // new data comes in. + navigator.stickToMax = navigator.reversedExtremes ? + Math.round(navigator.zoomedMin) === 0 : + Math.round(navigator.zoomedMax) >= Math.round(navigator.size); + // Detect whether the zoomed area should stick to the minimum or + // maximum. If the current axis minimum falls outside the new updated + // dataset, we must adjust. + navigator.stickToMin = isNumber(baseSeries.xAxis.min) && + (baseSeries.xAxis.min <= xDataMin) && + (!this.chart.fixedRange || !navigator.stickToMax); + // Set the navigator series data to the new data of the base series + if (navigatorSeries && !navigator.hasNavigatorData) { + navigatorSeries.options.pointStart = baseSeries.xData[0]; + navigatorSeries.setData(baseSeries.options.data, false, null, false); // #5414 + } + }; + /** + * Add chart events, like redrawing navigator, when chart requires that. + * + * @private + * @function Highcharts.Navigator#addChartEvents + * @return {void} + */ + Navigator.prototype.addChartEvents = function () { + if (!this.eventsToUnbind) { + this.eventsToUnbind = []; + } + this.eventsToUnbind.push( + // Move the scrollbar after redraw, like after data updata even if + // axes don't redraw + addEvent(this.chart, 'redraw', function () { + var navigator = this.navigator, xAxis = navigator && (navigator.baseSeries && + navigator.baseSeries[0] && + navigator.baseSeries[0].xAxis || + this.xAxis[0]); // #5709, #13114 + if (xAxis) { + navigator.render(xAxis.min, xAxis.max); + } + }), + // Make room for the navigator, can be placed around the chart: + addEvent(this.chart, 'getMargins', function () { + var chart = this, navigator = chart.navigator, marginName = navigator.opposite ? + 'plotTop' : 'marginBottom'; + if (chart.inverted) { + marginName = navigator.opposite ? + 'marginRight' : 'plotLeft'; + } + chart[marginName] = + (chart[marginName] || 0) + (navigator.navigatorEnabled || !chart.inverted ? + navigator.outlineHeight : + 0) + navigator.navigatorOptions.margin; + })); + }; + /** + * Destroys allocated elements. + * + * @private + * @function Highcharts.Navigator#destroy + */ + Navigator.prototype.destroy = function () { + // Disconnect events added in addEvents + this.removeEvents(); + if (this.xAxis) { + erase(this.chart.xAxis, this.xAxis); + erase(this.chart.axes, this.xAxis); + } + if (this.yAxis) { + erase(this.chart.yAxis, this.yAxis); + erase(this.chart.axes, this.yAxis); + } + // Destroy series + (this.series || []).forEach(function (s) { + if (s.destroy) { + s.destroy(); + } + }); + // Destroy properties + [ + 'series', 'xAxis', 'yAxis', 'shades', 'outline', 'scrollbarTrack', + 'scrollbarRifles', 'scrollbarGroup', 'scrollbar', 'navigatorGroup', + 'rendered' + ].forEach(function (prop) { + if (this[prop] && this[prop].destroy) { + this[prop].destroy(); + } + this[prop] = null; + }, this); + // Destroy elements in collection + [this.handles].forEach(function (coll) { + destroyObjectProperties(coll); + }, this); + }; + return Navigator; + }()); + // End of prototype + if (!H.Navigator) { + H.Navigator = Navigator; + NavigatorAxis.compose(Axis); + // For Stock charts. For x only zooming, do not to create the zoom button + // because X axis zooming is already allowed by the Navigator and Range + // selector. (#9285) + addEvent(Chart, 'beforeShowResetZoom', function () { + var chartOptions = this.options, navigator = chartOptions.navigator, rangeSelector = chartOptions.rangeSelector; + if (((navigator && navigator.enabled) || + (rangeSelector && rangeSelector.enabled)) && + ((!isTouchDevice && chartOptions.chart.zoomType === 'x') || + (isTouchDevice && chartOptions.chart.pinchType === 'x'))) { + return false; + } + }); + // Initialize navigator for stock charts + addEvent(Chart, 'beforeRender', function () { + var options = this.options; + if (options.navigator.enabled || + options.scrollbar.enabled) { + this.scroller = this.navigator = new Navigator(this); + } + }); + // For stock charts, extend the Chart.setChartSize method so that we can set + // the final top position of the navigator once the height of the chart, + // including the legend, is determined. #367. We can't use Chart.getMargins, + // because labels offsets are not calculated yet. + addEvent(Chart, 'afterSetChartSize', function () { + var legend = this.legend, navigator = this.navigator, scrollbarHeight, legendOptions, xAxis, yAxis; + if (navigator) { + legendOptions = legend && legend.options; + xAxis = navigator.xAxis; + yAxis = navigator.yAxis; + scrollbarHeight = navigator.scrollbarHeight; + // Compute the top position + if (this.inverted) { + navigator.left = navigator.opposite ? + this.chartWidth - scrollbarHeight - + navigator.height : + this.spacing[3] + scrollbarHeight; + navigator.top = this.plotTop + scrollbarHeight; + } + else { + navigator.left = this.plotLeft + scrollbarHeight; + navigator.top = navigator.navigatorOptions.top || + this.chartHeight - + navigator.height - + scrollbarHeight - + this.spacing[2] - + (this.rangeSelector && this.extraBottomMargin ? + this.rangeSelector.getHeight() : + 0) - + ((legendOptions && + legendOptions.verticalAlign === 'bottom' && + legendOptions.enabled && + !legendOptions.floating) ? + legend.legendHeight + + pick(legendOptions.margin, 10) : + 0) - + (this.titleOffset ? this.titleOffset[2] : 0); + } + if (xAxis && yAxis) { // false if navigator is disabled (#904) + if (this.inverted) { + xAxis.options.left = yAxis.options.left = navigator.left; + } + else { + xAxis.options.top = yAxis.options.top = navigator.top; + } + xAxis.setAxisSize(); + yAxis.setAxisSize(); + } + } + }); + // Merge options, if no scrolling exists yet + addEvent(Chart, 'update', function (e) { + var navigatorOptions = (e.options.navigator || {}), scrollbarOptions = (e.options.scrollbar || {}); + if (!this.navigator && !this.scroller && + (navigatorOptions.enabled || scrollbarOptions.enabled)) { + merge(true, this.options.navigator, navigatorOptions); + merge(true, this.options.scrollbar, scrollbarOptions); + delete e.options.navigator; + delete e.options.scrollbar; + } + }); + // Initialize navigator, if no scrolling exists yet + addEvent(Chart, 'afterUpdate', function (event) { + if (!this.navigator && !this.scroller && + (this.options.navigator.enabled || + this.options.scrollbar.enabled)) { + this.scroller = this.navigator = new Navigator(this); + if (pick(event.redraw, true)) { + this.redraw(event.animation); // #7067 + } + } + }); + // Handle adding new series + addEvent(Chart, 'afterAddSeries', function () { + if (this.navigator) { + // Recompute which series should be shown in navigator, and add them + this.navigator.setBaseSeries(null, false); + } + }); + // Handle updating series + addEvent(Series, 'afterUpdate', function () { + if (this.chart.navigator && !this.options.isInternal) { + this.chart.navigator.setBaseSeries(null, false); + } + }); + Chart.prototype.callbacks.push(function (chart) { + var extremes, navigator = chart.navigator; + // Initialize the navigator + if (navigator && chart.xAxis[0]) { + extremes = chart.xAxis[0].getExtremes(); + navigator.render(extremes.min, extremes.max); + } + }); + } + H.Navigator = Navigator; + + return H.Navigator; + }); + _registerModule(_modules, 'masters/modules/gantt.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/grid-axis.js b/librerias/gantt/code/modules/grid-axis.js new file mode 100644 index 0000000..a2c33d4 --- /dev/null +++ b/librerias/gantt/code/modules/grid-axis.js @@ -0,0 +1,28 @@ +/* + Highcharts Gantt JS v8.1.0 (2020-05-05) + + GridAxis + + (c) 2016-2019 Lars A. V. Cabrera + + License: www.highcharts.com/license +*/ +(function(d){"object"===typeof module&&module.exports?(d["default"]=d,module.exports=d):"function"===typeof define&&define.amd?define("highcharts/modules/grid-axis",["highcharts"],function(n){d(n);d.Highcharts=n;return d}):d("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(d){function n(d,r,n,f){d.hasOwnProperty(r)||(d[r]=f.apply(null,n))}d=d?d._modules:{};n(d,"parts-gantt/GridAxis.js",[d["parts/Axis.js"],d["parts/Globals.js"],d["parts/Tick.js"],d["parts/Utilities.js"]],function(d,n, +A,f){var h=f.addEvent,p=f.defined,r=f.erase,B=f.find,C=f.isArray,t=f.isNumber,x=f.merge,y=f.pick,D=f.timeUnits,z=f.wrap,E=n.dateFormat,F=n.Chart,G=function(b){var a=b.options;a.labels||(a.labels={});a.labels.align=y(a.labels.align,"center");b.categories||(a.showLastLabel=!1);b.labelRotation=0;a.labels.rotation=0};"";d.prototype.getMaxLabelDimensions=function(b,a){var c={width:0,height:0};a.forEach(function(a){a=b[a];if(f.isObject(a,!0)){var e=f.isObject(a.label,!0)?a.label:{};a=e.getBBox?e.getBBox().height: +0;e.textStr&&!t(e.textPxLength)&&(e.textPxLength=e.getBBox().width);e=t(e.textPxLength)?Math.round(e.textPxLength):0;c.height=Math.max(a,c.height);c.width=Math.max(e,c.width)}});return c};n.dateFormats.W=function(b){b=new this.Date(b);var a=(this.get("Day",b)+6)%7,c=new this.Date(b.valueOf());this.set("Date",c,this.get("Date",b)-a+3);a=new this.Date(this.get("FullYear",c),0,1);4!==this.get("Day",a)&&(this.set("Month",b,0),this.set("Date",b,1+(11-this.get("Day",a))%7));return(1+Math.floor((c.valueOf()- +a.valueOf())/6048E5)).toString()};n.dateFormats.E=function(b){return E("%a",b,!0).charAt(0)};h(F,"afterSetChartSize",function(){this.axes.forEach(function(b){(b.grid&&b.grid.columns||[]).forEach(function(a){a.setAxisSize();a.setAxisTranslation()})})});h(A,"afterGetLabelPosition",function(b){var a=this.label,c=this.axis,m=c.reversed,e=c.chart,l=c.options.grid||{},g=c.options.labels,u=g.align,k=w.Side[c.side],d=b.tickmarkOffset,v=c.tickPositions,q=this.pos-d;v=t(v[b.index+1])?v[b.index+1]-d:c.max+d; +var f=c.tickSize("tick");d=f?f[0]:0;f=f?f[1]/2:0;if(!0===l.enabled){if("top"===k){l=c.top+c.offset;var h=l-d}else"bottom"===k?(h=e.chartHeight-c.bottom+c.offset,l=h+d):(l=c.top+c.len-c.translate(m?v:q),h=c.top+c.len-c.translate(m?q:v));"right"===k?(k=e.chartWidth-c.right+c.offset,m=k+d):"left"===k?(m=c.left+c.offset,k=m-d):(k=Math.round(c.left+c.translate(m?v:q))-f,m=Math.round(c.left+c.translate(m?q:v))-f);this.slotWidth=m-k;b.pos.x="left"===u?k:"right"===u?m:k+(m-k)/2;b.pos.y=h+(l-h)/2;e=e.renderer.fontMetrics(g.style.fontSize, +a.element);a=a.getBBox().height;g.useHTML?b.pos.y+=e.b+-(a/2):(a=Math.round(a/e.h),b.pos.y+=(e.b-(e.h-e.f))/2+-((a-1)*e.h/2));b.pos.x+=c.horiz&&g.x||0}});var H=function(){function b(a){this.axis=a}b.prototype.isOuterAxis=function(){var a=this.axis,c=a.grid.columnIndex,b=a.linkedParent&&a.linkedParent.grid.columns||a.grid.columns,e=c?a.linkedParent:a,d=-1,g=0;a.chart[a.coll].forEach(function(c,b){c.side!==a.side||c.options.isInternal||(g=b,c===e&&(d=b))});return g===d&&(t(c)?b.length===c:!0)};return b}(), +w=function(){function b(){}b.compose=function(a){d.keepProps.push("grid");z(a.prototype,"unsquish",b.wrapUnsquish);h(a,"init",b.onInit);h(a,"afterGetOffset",b.onAfterGetOffset);h(a,"afterGetTitlePosition",b.onAfterGetTitlePosition);h(a,"afterInit",b.onAfterInit);h(a,"afterRender",b.onAfterRender);h(a,"afterSetAxisTranslation",b.onAfterSetAxisTranslation);h(a,"afterSetOptions",b.onAfterSetOptions);h(a,"afterSetOptions",b.onAfterSetOptions2);h(a,"afterSetScale",b.onAfterSetScale);h(a,"afterTickSize", +b.onAfterTickSize);h(a,"trimTicks",b.onTrimTicks);h(a,"destroy",b.onDestroy)};b.onAfterGetOffset=function(){var a=this.grid;(a&&a.columns||[]).forEach(function(a){a.getOffset()})};b.onAfterGetTitlePosition=function(a){if(!0===(this.options.grid||{}).enabled){var c=this.axisTitle,d=this.height,e=this.horiz,l=this.left,g=this.offset,u=this.opposite,k=this.options.title,f=void 0===k?{}:k;k=this.top;var h=this.width,q=this.tickSize(),n=c&&c.getBBox().width,p=f.x||0,r=f.y||0,t=y(f.margin,e?5:10);c=this.chart.renderer.fontMetrics(f.style&& +f.style.fontSize,c).f;q=(e?k+d:l)+(e?1:-1)*(u?-1:1)*(q?q[0]/2:0)+(this.side===b.Side.bottom?c:0);a.titlePosition.x=e?l-n/2-t+p:q+(u?h:0)+g+p;a.titlePosition.y=e?q-(u?d:0)+(u?c:-c)/2+g+r:k-t+r}};b.onAfterInit=function(){var a=this.chart,c=this.options.grid;c=void 0===c?{}:c;var b=this.userOptions;c.enabled&&(G(this),z(this,"labelFormatter",function(a){var c=this.axis,b=this.value,e=c.tickPositions,d=(c.isLinked?c.linkedParent:c).series[0],m=b===e[0];e=b===e[e.length-1];d=d&&B(d.options.data,function(a){return a[c.isXAxis? +"x":"y"]===b});this.isFirst=m;this.isLast=e;this.point=d;return a.call(this)}));if(c.columns)for(var e=this.grid.columns=[],l=this.grid.columnIndex=0;++lf&&!a.startOnTick&&(b[0]=f),d> +h&&d-k} + * @apioption xAxis.grid.columns + */ + /** + * Set border color for the label grid lines. + * + * @type {Highcharts.ColorString} + * @apioption xAxis.grid.borderColor + */ + /** + * Set border width of the label grid lines. + * + * @type {number} + * @default 1 + * @apioption xAxis.grid.borderWidth + */ + /** + * Set cell height for grid axis labels. By default this is calculated from font + * size. This option only applies to horizontal axes. + * + * @sample gantt/grid-axis/cellheight + * Gant chart with custom cell height + * @type {number} + * @apioption xAxis.grid.cellHeight + */ + ''; // detach doclets above + /** + * Get the largest label width and height. + * + * @private + * @function Highcharts.Axis#getMaxLabelDimensions + * + * @param {Highcharts.Dictionary} ticks + * All the ticks on one axis. + * + * @param {Array} tickPositions + * All the tick positions on one axis. + * + * @return {Highcharts.SizeObject} + * Object containing the properties height and width. + * + * @todo Move this to the generic axis implementation, as it is used there. + */ + Axis.prototype.getMaxLabelDimensions = function (ticks, tickPositions) { + var dimensions = { + width: 0, + height: 0 + }; + tickPositions.forEach(function (pos) { + var tick = ticks[pos], tickHeight = 0, tickWidth = 0, label; + if (isObject(tick)) { + label = isObject(tick.label) ? tick.label : {}; + // Find width and height of tick + tickHeight = label.getBBox ? label.getBBox().height : 0; + if (label.textStr && !isNumber(label.textPxLength)) { + label.textPxLength = label.getBBox().width; + } + tickWidth = isNumber(label.textPxLength) ? + // Math.round ensures crisp lines + Math.round(label.textPxLength) : + 0; + // Update the result if width and/or height are larger + dimensions.height = Math.max(tickHeight, dimensions.height); + dimensions.width = Math.max(tickWidth, dimensions.width); + } + }); + return dimensions; + }; + // Adds week date format + H.dateFormats.W = function (timestamp) { + var d = new this.Date(timestamp); + var firstDay = (this.get('Day', d) + 6) % 7; + var thursday = new this.Date(d.valueOf()); + this.set('Date', thursday, this.get('Date', d) - firstDay + 3); + var firstThursday = new this.Date(this.get('FullYear', thursday), 0, 1); + if (this.get('Day', firstThursday) !== 4) { + this.set('Month', d, 0); + this.set('Date', d, 1 + (11 - this.get('Day', firstThursday)) % 7); + } + return (1 + + Math.floor((thursday.valueOf() - firstThursday.valueOf()) / 604800000)).toString(); + }; + // First letter of the day of the week, e.g. 'M' for 'Monday'. + H.dateFormats.E = function (timestamp) { + return dateFormat('%a', timestamp, true).charAt(0); + }; + /* eslint-disable no-invalid-this */ + addEvent(Chart, 'afterSetChartSize', function () { + this.axes.forEach(function (axis) { + (axis.grid && axis.grid.columns || []).forEach(function (column) { + column.setAxisSize(); + column.setAxisTranslation(); + }); + }); + }); + // Center tick labels in cells. + addEvent(Tick, 'afterGetLabelPosition', function (e) { + var tick = this, label = tick.label, axis = tick.axis, reversed = axis.reversed, chart = axis.chart, options = axis.options, gridOptions = options.grid || {}, labelOpts = axis.options.labels, align = labelOpts.align, + // verticalAlign is currently not supported for axis.labels. + verticalAlign = 'middle', // labelOpts.verticalAlign, + side = GridAxis.Side[axis.side], tickmarkOffset = e.tickmarkOffset, tickPositions = axis.tickPositions, tickPos = tick.pos - tickmarkOffset, nextTickPos = (isNumber(tickPositions[e.index + 1]) ? + tickPositions[e.index + 1] - tickmarkOffset : + axis.max + tickmarkOffset), tickSize = axis.tickSize('tick'), tickWidth = tickSize ? tickSize[0] : 0, crispCorr = tickSize ? tickSize[1] / 2 : 0, labelHeight, lblMetrics, lines, bottom, top, left, right; + // Only center tick labels in grid axes + if (gridOptions.enabled === true) { + // Calculate top and bottom positions of the cell. + if (side === 'top') { + bottom = axis.top + axis.offset; + top = bottom - tickWidth; + } + else if (side === 'bottom') { + top = chart.chartHeight - axis.bottom + axis.offset; + bottom = top + tickWidth; + } + else { + bottom = axis.top + axis.len - axis.translate(reversed ? nextTickPos : tickPos); + top = axis.top + axis.len - axis.translate(reversed ? tickPos : nextTickPos); + } + // Calculate left and right positions of the cell. + if (side === 'right') { + left = chart.chartWidth - axis.right + axis.offset; + right = left + tickWidth; + } + else if (side === 'left') { + right = axis.left + axis.offset; + left = right - tickWidth; + } + else { + left = Math.round(axis.left + axis.translate(reversed ? nextTickPos : tickPos)) - crispCorr; + right = Math.round(axis.left + axis.translate(reversed ? tickPos : nextTickPos)) - crispCorr; + } + tick.slotWidth = right - left; + // Calculate the positioning of the label based on + // alignment. + e.pos.x = (align === 'left' ? + left : + align === 'right' ? + right : + left + ((right - left) / 2) // default to center + ); + e.pos.y = (verticalAlign === 'top' ? + top : + verticalAlign === 'bottom' ? + bottom : + top + ((bottom - top) / 2) // default to middle + ); + lblMetrics = chart.renderer.fontMetrics(labelOpts.style.fontSize, label.element); + labelHeight = label.getBBox().height; + // Adjustment to y position to align the label correctly. + // Would be better to have a setter or similar for this. + if (!labelOpts.useHTML) { + lines = Math.round(labelHeight / lblMetrics.h); + e.pos.y += ( + // Center the label + // TODO: why does this actually center the label? + ((lblMetrics.b - (lblMetrics.h - lblMetrics.f)) / 2) + + // Adjust for height of additional lines. + -(((lines - 1) * lblMetrics.h) / 2)); + } + else { + e.pos.y += ( + // Readjust yCorr in htmlUpdateTransform + lblMetrics.b + + // Adjust for height of html label + -(labelHeight / 2)); + } + e.pos.x += (axis.horiz && labelOpts.x || 0); + } + }); + /* eslint-enable no-invalid-this */ + /** + * Additions for grid axes. + * @private + * @class + */ + var GridAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function GridAxisAdditions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Checks if an axis is the outer axis in its dimension. Since + * axes are placed outwards in order, the axis with the highest + * index is the outermost axis. + * + * Example: If there are multiple x-axes at the top of the chart, + * this function returns true if the axis supplied is the last + * of the x-axes. + * + * @private + * + * @return {boolean} + * True if the axis is the outermost axis in its dimension; false if + * not. + */ + GridAxisAdditions.prototype.isOuterAxis = function () { + var axis = this.axis; + var chart = axis.chart; + var columnIndex = axis.grid.columnIndex; + var columns = (axis.linkedParent && axis.linkedParent.grid.columns || + axis.grid.columns); + var parentAxis = columnIndex ? axis.linkedParent : axis; + var thisIndex = -1, lastIndex = 0; + chart[axis.coll].forEach(function (otherAxis, index) { + if (otherAxis.side === axis.side && !otherAxis.options.isInternal) { + lastIndex = index; + if (otherAxis === parentAxis) { + // Get the index of the axis in question + thisIndex = index; + } + } + }); + return (lastIndex === thisIndex && + (isNumber(columnIndex) ? columns.length === columnIndex : true)); + }; + return GridAxisAdditions; + }()); + /** + * Axis with grid support. + * @private + * @class + */ + var GridAxis = /** @class */ (function () { + function GridAxis() { + } + /* * + * + * Static Functions + * + * */ + /* eslint-disable valid-jsdoc */ + /** + * Extends axis class with grid support. + * @private + */ + GridAxis.compose = function (AxisClass) { + Axis.keepProps.push('grid'); + wrap(AxisClass.prototype, 'unsquish', GridAxis.wrapUnsquish); + // Add event handlers + addEvent(AxisClass, 'init', GridAxis.onInit); + addEvent(AxisClass, 'afterGetOffset', GridAxis.onAfterGetOffset); + addEvent(AxisClass, 'afterGetTitlePosition', GridAxis.onAfterGetTitlePosition); + addEvent(AxisClass, 'afterInit', GridAxis.onAfterInit); + addEvent(AxisClass, 'afterRender', GridAxis.onAfterRender); + addEvent(AxisClass, 'afterSetAxisTranslation', GridAxis.onAfterSetAxisTranslation); + addEvent(AxisClass, 'afterSetOptions', GridAxis.onAfterSetOptions); + addEvent(AxisClass, 'afterSetOptions', GridAxis.onAfterSetOptions2); + addEvent(AxisClass, 'afterSetScale', GridAxis.onAfterSetScale); + addEvent(AxisClass, 'afterTickSize', GridAxis.onAfterTickSize); + addEvent(AxisClass, 'trimTicks', GridAxis.onTrimTicks); + addEvent(AxisClass, 'destroy', GridAxis.onDestroy); + }; + /** + * Handle columns and getOffset. + * @private + */ + GridAxis.onAfterGetOffset = function () { + var grid = this.grid; + (grid && grid.columns || []).forEach(function (column) { + column.getOffset(); + }); + }; + /** + * @private + */ + GridAxis.onAfterGetTitlePosition = function (e) { + var axis = this; + var options = axis.options; + var gridOptions = options.grid || {}; + if (gridOptions.enabled === true) { + // compute anchor points for each of the title align options + var title = axis.axisTitle, axisHeight = axis.height, horiz = axis.horiz, axisLeft = axis.left, offset = axis.offset, opposite = axis.opposite, _a = axis.options.title, axisTitleOptions = _a === void 0 ? {} : _a, axisTop = axis.top, axisWidth = axis.width; + var tickSize = axis.tickSize(); + var titleWidth = title && title.getBBox().width; + var xOption = axisTitleOptions.x || 0; + var yOption = axisTitleOptions.y || 0; + var titleMargin = pick(axisTitleOptions.margin, horiz ? 5 : 10); + var titleFontSize = axis.chart.renderer.fontMetrics(axisTitleOptions.style && + axisTitleOptions.style.fontSize, title).f; + var crispCorr = tickSize ? tickSize[0] / 2 : 0; + // TODO account for alignment + // the position in the perpendicular direction of the axis + var offAxis = ((horiz ? axisTop + axisHeight : axisLeft) + + (horiz ? 1 : -1) * // horizontal axis reverses the margin + (opposite ? -1 : 1) * // so does opposite axes + crispCorr + + (axis.side === GridAxis.Side.bottom ? titleFontSize : 0)); + e.titlePosition.x = horiz ? + axisLeft - titleWidth / 2 - titleMargin + xOption : + offAxis + (opposite ? axisWidth : 0) + offset + xOption; + e.titlePosition.y = horiz ? + (offAxis - + (opposite ? axisHeight : 0) + + (opposite ? titleFontSize : -titleFontSize) / 2 + + offset + + yOption) : + axisTop - titleMargin + yOption; + } + }; + /** + * @private + */ + GridAxis.onAfterInit = function () { + var axis = this; + var chart = axis.chart, _a = axis.options.grid, gridOptions = _a === void 0 ? {} : _a, userOptions = axis.userOptions; + if (gridOptions.enabled) { + applyGridOptions(axis); + /* eslint-disable no-invalid-this */ + // TODO: wrap the axis instead + wrap(axis, 'labelFormatter', function (proceed) { + var _a = this, axis = _a.axis, value = _a.value; + var tickPos = axis.tickPositions; + var series = (axis.isLinked ? + axis.linkedParent : + axis).series[0]; + var isFirst = value === tickPos[0]; + var isLast = value === tickPos[tickPos.length - 1]; + var point = series && find(series.options.data, function (p) { + return p[axis.isXAxis ? 'x' : 'y'] === value; + }); + // Make additional properties available for the + // formatter + this.isFirst = isFirst; + this.isLast = isLast; + this.point = point; + // Call original labelFormatter + return proceed.call(this); + }); + /* eslint-enable no-invalid-this */ + } + if (gridOptions.columns) { + var columns = axis.grid.columns = [], columnIndex = axis.grid.columnIndex = 0; + // Handle columns, each column is a grid axis + while (++columnIndex < gridOptions.columns.length) { + var columnOptions = merge(userOptions, gridOptions.columns[gridOptions.columns.length - columnIndex - 1], { + linkedTo: 0, + // Force to behave like category axis + type: 'category' + }); + delete columnOptions.grid.columns; // Prevent recursion + var column = new Axis(axis.chart, columnOptions); + column.grid.isColumn = true; + column.grid.columnIndex = columnIndex; + // Remove column axis from chart axes array, and place it + // in the columns array. + erase(chart.axes, column); + erase(chart[axis.coll], column); + columns.push(column); + } + } + }; + /** + * Draw an extra line on the far side of the outermost axis, + * creating floor/roof/wall of a grid. And some padding. + * ``` + * Make this: + * (axis.min) __________________________ (axis.max) + * | | | | | + * Into this: + * (axis.min) __________________________ (axis.max) + * ___|____|____|____|____|__ + * ``` + * @private + */ + GridAxis.onAfterRender = function () { + var axis = this; + var grid = axis.grid; + var options = axis.options; + var renderer = axis.chart.renderer; + var gridOptions = options.grid || {}; + var yStartIndex, yEndIndex, xStartIndex, xEndIndex; + if (gridOptions.enabled === true) { + // @todo acutual label padding (top, bottom, left, right) + axis.maxLabelDimensions = axis.getMaxLabelDimensions(axis.ticks, axis.tickPositions); + // Remove right wall before rendering if updating + if (axis.rightWall) { + axis.rightWall.destroy(); + } + /* + Draw an extra axis line on outer axes + > + Make this: |______|______|______|___ + + > _________________________ + Into this: |______|______|______|__| + */ + if (axis.grid && axis.grid.isOuterAxis() && axis.axisLine) { + var lineWidth = options.lineWidth; + if (lineWidth) { + var linePath = axis.getLinePath(lineWidth); + var startPoint = linePath[0]; + var endPoint = linePath[1]; + // Negate distance if top or left axis + // Subtract 1px to draw the line at the end of the tick + var tickLength = (axis.tickSize('tick') || [1])[0]; + var distance = (tickLength - 1) * ((axis.side === GridAxis.Side.top || + axis.side === GridAxis.Side.left) ? -1 : 1); + // If axis is horizontal, reposition line path vertically + if (startPoint[0] === 'M' && endPoint[0] === 'L') { + if (axis.horiz) { + startPoint[2] += distance; + endPoint[2] += distance; + } + else { + // If axis is vertical, reposition line path + // horizontally + startPoint[1] += distance; + endPoint[1] += distance; + } + } + if (!axis.grid.axisLineExtra) { + axis.grid.axisLineExtra = renderer + .path(linePath) + .attr({ + zIndex: 7 + }) + .addClass('highcharts-axis-line') + .add(axis.axisGroup); + if (!renderer.styledMode) { + axis.grid.axisLineExtra.attr({ + stroke: options.lineColor, + 'stroke-width': lineWidth + }); + } + } + else { + axis.grid.axisLineExtra.animate({ + d: linePath + }); + } + // show or hide the line depending on + // options.showEmpty + axis.axisLine[axis.showAxis ? 'show' : 'hide'](true); + } + } + (grid && grid.columns || []).forEach(function (column) { + column.render(); + }); + } + }; + /** + * @private + */ + GridAxis.onAfterSetAxisTranslation = function () { + var axis = this; + var tickInfo = axis.tickPositions && axis.tickPositions.info; + var options = axis.options; + var gridOptions = options.grid || {}; + var userLabels = axis.userOptions.labels || {}; + if (axis.horiz) { + if (gridOptions.enabled === true) { + axis.series.forEach(function (series) { + series.options.pointRange = 0; + }); + } + // Lower level time ticks, like hours or minutes, represent + // points in time and not ranges. These should be aligned + // left in the grid cell by default. The same applies to + // years of higher order. + if (tickInfo && + options.dateTimeLabelFormats && + options.labels && + !defined(userLabels.align) && + (options.dateTimeLabelFormats[tickInfo.unitName].range === false || + tickInfo.count > 1 // years + )) { + options.labels.align = 'left'; + if (!defined(userLabels.x)) { + options.labels.x = 3; + } + } + } + }; + /** + * Creates a left and right wall on horizontal axes: + * - Places leftmost tick at the start of the axis, to create a left + * wall + * - Ensures that the rightmost tick is at the end of the axis, to + * create a right wall. + * @private + */ + GridAxis.onAfterSetOptions = function (e) { + var options = this.options, userOptions = e.userOptions, gridAxisOptions, gridOptions = ((options && isObject(options.grid)) ? options.grid : {}); + if (gridOptions.enabled === true) { + // Merge the user options into default grid axis options so + // that when a user option is set, it takes presedence. + gridAxisOptions = merge(true, { + className: ('highcharts-grid-axis ' + (userOptions.className || '')), + dateTimeLabelFormats: { + hour: { + list: ['%H:%M', '%H'] + }, + day: { + list: ['%A, %e. %B', '%a, %e. %b', '%E'] + }, + week: { + list: ['Week %W', 'W%W'] + }, + month: { + list: ['%B', '%b', '%o'] + } + }, + grid: { + borderWidth: 1 + }, + labels: { + padding: 2, + style: { + fontSize: '13px' + } + }, + margin: 0, + title: { + text: null, + reserveSpace: false, + rotation: 0 + }, + // In a grid axis, only allow one unit of certain types, + // for example we shouln't have one grid cell spanning + // two days. + units: [[ + 'millisecond', + [1, 10, 100] + ], [ + 'second', + [1, 10] + ], [ + 'minute', + [1, 5, 15] + ], [ + 'hour', + [1, 6] + ], [ + 'day', + [1] + ], [ + 'week', + [1] + ], [ + 'month', + [1] + ], [ + 'year', + null + ]] + }, userOptions); + // X-axis specific options + if (this.coll === 'xAxis') { + // For linked axes, tickPixelInterval is used only if + // the tickPositioner below doesn't run or returns + // undefined (like multiple years) + if (defined(userOptions.linkedTo) && + !defined(userOptions.tickPixelInterval)) { + gridAxisOptions.tickPixelInterval = 350; + } + // For the secondary grid axis, use the primary axis' + // tick intervals and return ticks one level higher. + if ( + // Check for tick pixel interval in options + !defined(userOptions.tickPixelInterval) && + // Only for linked axes + defined(userOptions.linkedTo) && + !defined(userOptions.tickPositioner) && + !defined(userOptions.tickInterval)) { + gridAxisOptions.tickPositioner = function (min, max) { + var parentInfo = (this.linkedParent && + this.linkedParent.tickPositions && + this.linkedParent.tickPositions.info); + if (parentInfo) { + var unitIdx, count, unitName, i, units = gridAxisOptions.units, unitRange; + for (i = 0; i < units.length; i++) { + if (units[i][0] === + parentInfo.unitName) { + unitIdx = i; + break; + } + } + // Get the first allowed count on the next + // unit. + if (units[unitIdx + 1]) { + unitName = units[unitIdx + 1][0]; + count = + (units[unitIdx + 1][1] || [1])[0]; + // In case the base X axis shows years, make + // the secondary axis show ten times the + // years (#11427) + } + else if (parentInfo.unitName === 'year') { + unitName = 'year'; + count = parentInfo.count * 10; + } + unitRange = timeUnits[unitName]; + this.tickInterval = unitRange * count; + return this.getTimeTicks({ + unitRange: unitRange, + count: count, + unitName: unitName + }, min, max, this.options.startOfWeek); + } + }; + } + } + // Now merge the combined options into the axis options + merge(true, this.options, gridAxisOptions); + if (this.horiz) { + /* _________________________ + Make this: ___|_____|_____|_____|__| + ^ ^ + _________________________ + Into this: |_____|_____|_____|_____| + ^ ^ */ + options.minPadding = pick(userOptions.minPadding, 0); + options.maxPadding = pick(userOptions.maxPadding, 0); + } + // If borderWidth is set, then use its value for tick and + // line width. + if (isNumber(options.grid.borderWidth)) { + options.tickWidth = options.lineWidth = gridOptions.borderWidth; + } + } + }; + /** + * @private + */ + GridAxis.onAfterSetOptions2 = function (e) { + var axis = this; + var userOptions = e.userOptions; + var gridOptions = userOptions && userOptions.grid || {}; + var columns = gridOptions.columns; + // Add column options to the parent axis. Children has their column + // options set on init in onGridAxisAfterInit. + if (gridOptions.enabled && columns) { + merge(true, axis.options, columns[columns.length - 1]); + } + }; + /** + * Handle columns and setScale. + * @private + */ + GridAxis.onAfterSetScale = function () { + var axis = this; + (axis.grid.columns || []).forEach(function (column) { + column.setScale(); + }); + }; + /** + * Draw vertical axis ticks extra long to create cell floors and roofs. + * Overrides the tickLength for vertical axes. + * @private + */ + GridAxis.onAfterTickSize = function (e) { + var defaultLeftAxisOptions = Axis.defaultLeftAxisOptions; + var _a = this, horiz = _a.horiz, maxLabelDimensions = _a.maxLabelDimensions, _b = _a.options.grid, gridOptions = _b === void 0 ? {} : _b; + if (gridOptions.enabled && maxLabelDimensions) { + var labelPadding = (Math.abs(defaultLeftAxisOptions.labels.x) * 2); + var distance = horiz ? + gridOptions.cellHeight || labelPadding + maxLabelDimensions.height : + labelPadding + maxLabelDimensions.width; + if (isArray(e.tickSize)) { + e.tickSize[0] = distance; + } + else { + e.tickSize = [distance, 0]; + } + } + }; + /** + * @private + */ + GridAxis.onDestroy = function (e) { + var grid = this.grid; + (grid.columns || []).forEach(function (column) { + column.destroy(e.keepEvents); + }); + grid.columns = void 0; + }; + /** + * Wraps axis init to draw cell walls on vertical axes. + * @private + */ + GridAxis.onInit = function (e) { + var axis = this; + var userOptions = e.userOptions || {}; + var gridOptions = userOptions.grid || {}; + if (gridOptions.enabled && defined(gridOptions.borderColor)) { + userOptions.tickColor = userOptions.lineColor = gridOptions.borderColor; + } + if (!axis.grid) { + axis.grid = new GridAxisAdditions(axis); + } + }; + /** + * Makes tick labels which are usually ignored in a linked axis + * displayed if they are within range of linkedParent.min. + * ``` + * _____________________________ + * | | | | | + * Make this: | | 2 | 3 | 4 | + * |___|_______|_______|_______| + * ^ + * _____________________________ + * | | | | | + * Into this: | 1 | 2 | 3 | 4 | + * |___|_______|_______|_______| + * ^ + * ``` + * @private + * @todo Does this function do what the drawing says? Seems to affect + * ticks and not the labels directly? + */ + GridAxis.onTrimTicks = function () { + var axis = this; + var options = axis.options; + var gridOptions = options.grid || {}; + var categoryAxis = axis.categories; + var tickPositions = axis.tickPositions; + var firstPos = tickPositions[0]; + var lastPos = tickPositions[tickPositions.length - 1]; + var linkedMin = axis.linkedParent && axis.linkedParent.min; + var linkedMax = axis.linkedParent && axis.linkedParent.max; + var min = linkedMin || axis.min; + var max = linkedMax || axis.max; + var tickInterval = axis.tickInterval; + var endMoreThanMin = (firstPos < min && + firstPos + tickInterval > min); + var startLessThanMax = (lastPos > max && + lastPos - tickInterval < max); + if (gridOptions.enabled === true && + !categoryAxis && + (axis.horiz || axis.isLinked)) { + if (endMoreThanMin && !options.startOnTick) { + tickPositions[0] = min; + } + if (startLessThanMax && !options.endOnTick) { + tickPositions[tickPositions.length - 1] = max; + } + } + }; + /** + * Avoid altering tickInterval when reserving space. + * @private + */ + GridAxis.wrapUnsquish = function (proceed) { + var axis = this; + var _a = axis.options.grid, gridOptions = _a === void 0 ? {} : _a; + if (gridOptions.enabled === true && axis.categories) { + return axis.tickInterval; + } + return proceed.apply(axis, argsToArray(arguments)); + }; + return GridAxis; + }()); + (function (GridAxis) { + /** + * Enum for which side the axis is on. Maps to axis.side. + * @private + */ + var Side; + (function (Side) { + Side[Side["top"] = 0] = "top"; + Side[Side["right"] = 1] = "right"; + Side[Side["bottom"] = 2] = "bottom"; + Side[Side["left"] = 3] = "left"; + })(Side = GridAxis.Side || (GridAxis.Side = {})); + })(GridAxis || (GridAxis = {})); + GridAxis.compose(Axis); + + return GridAxis; + }); + _registerModule(_modules, 'masters/modules/grid-axis.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/heatmap.js b/librerias/gantt/code/modules/heatmap.js new file mode 100644 index 0000000..0430591 --- /dev/null +++ b/librerias/gantt/code/modules/heatmap.js @@ -0,0 +1,39 @@ +/* + Highmaps JS v8.1.0 (2020-05-05) + + (c) 2009-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/heatmap",["highcharts"],function(r){b(r);b.Highcharts=r;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function r(b,h,g,z){b.hasOwnProperty(h)||(b[h]=z.apply(null,g))}b=b?b._modules:{};r(b,"parts-map/ColorSeriesMixin.js",[b["parts/Globals.js"]],function(b){b.colorPointMixin={setVisible:function(b){var g=this,h=b?"show": +"hide";g.visible=g.options.visible=!!b;["graphic","dataLabel"].forEach(function(b){if(g[b])g[b][h]()})}};b.colorSeriesMixin={optionalAxis:"colorAxis",colorAxis:0,translateColors:function(){var b=this,g=this.options.nullColor,v=this.colorAxis,r=this.colorKey;(this.data.length?this.data:this.points).forEach(function(h){var p=h.getNestedProperty(r);if(p=h.options.color||(h.isNull||null===h.value?g:v&&"undefined"!==typeof p?v.toColor(p,h):h.color||b.color))h.color=p})}}});r(b,"parts-map/ColorAxis.js", +[b["parts/Axis.js"],b["parts/Color.js"],b["parts/Globals.js"],b["parts/Legend.js"],b["mixins/legend-symbol.js"],b["parts/Point.js"],b["parts/Utilities.js"]],function(b,h,g,z,r,C,p){var v=this&&this.__extends||function(){var a=function(e,c){a=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(c,n){c.__proto__=n}||function(c,n){for(var k in n)n.hasOwnProperty(k)&&(c[k]=n[k])};return a(e,c)};return function(e,c){function k(){this.constructor=e}a(e,c);e.prototype=null===c?Object.create(c): +(k.prototype=c.prototype,new k)}}(),w=h.parse;h=p.addEvent;var D=p.erase,u=p.extend,x=p.Fx,a=p.isNumber,f=p.merge,y=p.pick,F=p.splat;"";p=g.Chart;var q=g.Series,l=g.colorPointMixin,m=g.noop;u(q.prototype,g.colorSeriesMixin);u(C.prototype,l);p.prototype.collectionsWithUpdate.push("colorAxis");p.prototype.collectionsWithInit.colorAxis=[p.prototype.addColorAxis];var B=function(e){function d(c,k){var n=e.call(this,c,k)||this;n.beforePadding=!1;n.chart=void 0;n.coll="colorAxis";n.dataClasses=void 0;n.legendItem= +void 0;n.legendItems=void 0;n.name="";n.options=void 0;n.stops=void 0;n.visible=!0;n.init(c,k);return n}v(d,e);d.buildOptions=function(c,k,n){c=c.options.legend||{};var t=n.layout?"vertical"!==n.layout:"vertical"!==c.layout;return f(k,{side:t?2:1,reversed:!t},n,{opposite:!t,showEmpty:!1,title:null,visible:c.enabled&&(n?!1!==n.visible:!0)})};d.prototype.init=function(c,k){var n=d.buildOptions(c,d.defaultOptions,k);this.coll="colorAxis";e.prototype.init.call(this,c,n);k.dataClasses&&this.initDataClasses(k); +this.initStops();this.horiz=!n.opposite;this.zoomEnabled=!1};d.prototype.initDataClasses=function(c){var k=this.chart,n,t=0,a=k.options.chart.colorCount,e=this.options,d=c.dataClasses.length;this.dataClasses=n=[];this.legendItems=[];c.dataClasses.forEach(function(c,b){c=f(c);n.push(c);if(k.styledMode||!c.color)"category"===e.dataClassColor?(k.styledMode||(b=k.options.colors,a=b.length,c.color=b[t]),c.colorIndex=t,t++,t===a&&(t=0)):c.color=w(e.minColor).tweenTo(w(e.maxColor),2>d?.5:b/(d-1))})};d.prototype.hasData= +function(){return!!(this.tickPositions||[]).length};d.prototype.setTickPositions=function(){if(!this.dataClasses)return e.prototype.setTickPositions.call(this)};d.prototype.initStops=function(){this.stops=this.options.stops||[[0,this.options.minColor],[1,this.options.maxColor]];this.stops.forEach(function(c){c.color=w(c[1])})};d.prototype.setOptions=function(c){e.prototype.setOptions.call(this,c);this.options.crosshair=this.options.marker};d.prototype.setAxisSize=function(){var c=this.legendSymbol, +k=this.chart,a=k.options.legend||{},t,e;c?(this.left=a=c.attr("x"),this.top=t=c.attr("y"),this.width=e=c.attr("width"),this.height=c=c.attr("height"),this.right=k.chartWidth-a-e,this.bottom=k.chartHeight-t-c,this.len=this.horiz?e:c,this.pos=this.horiz?a:t):this.len=(this.horiz?a.symbolWidth:a.symbolHeight)||d.defaultLegendLength};d.prototype.normalizedValue=function(c){this.logarithmic&&(c=this.logarithmic.log2lin(c));return 1-(this.max-c)/(this.max-this.min||1)};d.prototype.toColor=function(c,k){var a= +this.dataClasses,e=this.stops,d;if(a)for(d=a.length;d--;){var b=a[d];var f=b.from;e=b.to;if(("undefined"===typeof f||c>=f)&&("undefined"===typeof e||c<=e)){var l=b.color;k&&(k.dataClass=d,k.colorIndex=b.colorIndex);break}}else{c=this.normalizedValue(c);for(d=e.length;d--&&!(c>e[d][0]););f=e[d]||e[d+1];e=e[d+1]||f;c=1-(e[0]-c)/(e[0]-f[0]||1);l=f.color.tweenTo(e.color,c)}return l};d.prototype.getOffset=function(){var c=this.legendGroup,k=this.chart.axisOffset[this.side];c&&(this.axisParent=c,e.prototype.getOffset.call(this), +this.added||(this.added=!0,this.labelLeft=0,this.labelRight=this.width),this.chart.axisOffset[this.side]=k)};d.prototype.setLegendColor=function(){var c=this.reversed,k=c?1:0;c=c?0:1;k=this.horiz?[k,0,c,0]:[0,c,0,k];this.legendColor={linearGradient:{x1:k[0],y1:k[1],x2:k[2],y2:k[3]},stops:this.stops}};d.prototype.drawLegendSymbol=function(c,k){var e=c.padding,a=c.options,f=this.horiz,b=y(a.symbolWidth,f?d.defaultLegendLength:12),l=y(a.symbolHeight,f?12:d.defaultLegendLength),m=y(a.labelPadding,f?16: +30);a=y(a.itemDistance,10);this.setLegendColor();k.legendSymbol=this.chart.renderer.rect(0,c.baseline-11,b,l).attr({zIndex:1}).add(k.legendGroup);this.legendItemWidth=b+e+(f?a:m);this.legendItemHeight=l+e+(f?m:0)};d.prototype.setState=function(c){this.series.forEach(function(a){a.setState(c)})};d.prototype.setVisible=function(){};d.prototype.getSeriesExtremes=function(){var c=this.series,a=c.length,e;this.dataMin=Infinity;for(this.dataMax=-Infinity;a--;){var d=c[a];var f=d.colorKey=y(d.options.colorKey, +d.colorKey,d.pointValKey,d.zoneAxis,"y");var b=d.pointArrayMap;var l=d[f+"Min"]&&d[f+"Max"];if(d[f+"Data"])var m=d[f+"Data"];else if(b){m=[];b=b.indexOf(f);var g=d.yData;if(0<=b&&g)for(e=0;ef+b&&(l=f+b+2);a.plotX=l;a.plotY=this.len-l;e.prototype.drawCrosshair.call(this,c,a);a.plotX=d;a.plotY=k;this.cross&&!this.cross.addedToColorAxis&&this.legendGroup&&(this.cross.addClass("highcharts-coloraxis-marker").add(this.legendGroup),this.cross.addedToColorAxis=!0,!this.chart.styledMode&& +this.crosshair&&this.cross.attr({fill:this.crosshair.color}))}};d.prototype.getPlotLinePath=function(c){var d=c.translatedValue;return a(d)?this.horiz?[["M",d-4,this.top-6],["L",d+4,this.top-6],["L",d,this.top],["Z"]]:[["M",this.left,d],["L",this.left-6,d+6],["L",this.left-6,d-6],["Z"]]:e.prototype.getPlotLinePath.call(this,c)};d.prototype.update=function(c,a){var b=this.chart,k=b.legend,l=d.buildOptions(b,{},c);this.series.forEach(function(c){c.isDirtyData=!0});(c.dataClasses&&k.allItems||this.dataClasses)&& +this.destroyItems();b.options[this.coll]=f(this.userOptions,l);e.prototype.update.call(this,l,a);this.legendItem&&(this.setLegendColor(),k.colorizeItem(this,!0))};d.prototype.destroyItems=function(){var c=this.chart;this.legendItem?c.legend.destroyItem(this):this.legendItems&&this.legendItems.forEach(function(a){c.legend.destroyItem(a)});c.isDirtyLegend=!0};d.prototype.remove=function(c){this.destroyItems();e.prototype.remove.call(this,c)};d.prototype.getDataClassLegendSymbols=function(){var c=this, +a=c.chart,d=c.legendItems,e=a.options.legend,f=e.valueDecimals,b=e.valueSuffix||"",l;d.length||c.dataClasses.forEach(function(e,k){var n=!0,g=e.from,q=e.to,h=a.numberFormatter;l="";"undefined"===typeof g?l="< ":"undefined"===typeof q&&(l="> ");"undefined"!==typeof g&&(l+=h(g,f)+b);"undefined"!==typeof g&&"undefined"!==typeof q&&(l+=" - ");"undefined"!==typeof q&&(l+=h(q,f)+b);d.push(u({chart:a,name:l,options:{},drawLegendSymbol:r.drawRectangle,visible:!0,setState:m,isDataClass:!0,setVisible:function(){n= +c.visible=!n;c.series.forEach(function(a){a.points.forEach(function(a){a.dataClass===k&&a.setVisible(n)})});a.legend.colorizeItem(this,n)}},e))});return d};d.defaultLegendLength=200;d.defaultOptions={lineWidth:0,minPadding:0,maxPadding:0,gridLineWidth:1,tickPixelInterval:72,startOnTick:!0,endOnTick:!0,offset:0,marker:{animation:{duration:50},width:.01,color:"#999999"},labels:{overflow:"justify",rotation:0},minColor:"#e6ebf5",maxColor:"#003399",tickLength:5,showInLegend:!0};d.keepProps=["legendGroup", +"legendItemHeight","legendItemWidth","legendItem","legendSymbol"];return d}(b);Array.prototype.push.apply(b.keepProps,B.keepProps);g.ColorAxis=B;["fill","stroke"].forEach(function(a){x.prototype[a+"Setter"]=function(){this.elem.attr(a,w(this.start).tweenTo(w(this.end),this.pos),null,!0)}});h(p,"afterGetAxes",function(){var a=this,d=a.options;this.colorAxis=[];d.colorAxis&&(d.colorAxis=F(d.colorAxis),d.colorAxis.forEach(function(c,d){c.index=d;new B(a,c)}))});h(q,"bindAxes",function(){var a=this.axisTypes; +a?-1===a.indexOf("colorAxis")&&a.push("colorAxis"):this.axisTypes=["colorAxis"]});h(z,"afterGetAllItems",function(a){var d=[],c,e;(this.chart.colorAxis||[]).forEach(function(e){(c=e.options)&&c.showInLegend&&(c.dataClasses&&c.visible?d=d.concat(e.getDataClassLegendSymbols()):c.visible&&d.push(e),e.series.forEach(function(d){if(!d.options.showInLegend||c.dataClasses)"point"===d.options.legendType?d.points.forEach(function(c){D(a.allItems,c)}):D(a.allItems,d)}))});for(e=d.length;e--;)a.allItems.unshift(d[e])}); +h(z,"afterColorizeItem",function(a){a.visible&&a.item.legendColor&&a.item.legendSymbol.attr({fill:a.item.legendColor})});h(z,"afterUpdate",function(){var a=this.chart.colorAxis;a&&a.forEach(function(a,c,e){a.update({},e)})});h(q,"afterTranslate",function(){(this.chart.colorAxis&&this.chart.colorAxis.length||this.colorAttribs)&&this.translateColors()});return B});r(b,"parts-map/ColorMapSeriesMixin.js",[b["parts/Globals.js"],b["parts/Point.js"],b["parts/Utilities.js"]],function(b,h,g){var v=g.defined; +g=b.noop;var r=b.seriesTypes;b.colorMapPointMixin={dataLabelOnNull:!0,isValid:function(){return null!==this.value&&Infinity!==this.value&&-Infinity!==this.value},setState:function(b){h.prototype.setState.call(this,b);this.graphic&&this.graphic.attr({zIndex:"hover"===b?1:0})}};b.colorMapSeriesMixin={pointArrayMap:["value"],axisTypes:["xAxis","yAxis","colorAxis"],trackerGroups:["group","markerGroup","dataLabelsGroup"],getSymbol:g,parallelArrays:["x","y","value"],colorKey:"value",pointAttribs:r.column.prototype.pointAttribs, +colorAttribs:function(b){var g={};v(b.color)&&(g[this.colorProp||"fill"]=b.color);return g}}});r(b,"parts-map/HeatmapSeries.js",[b["parts/Globals.js"],b["mixins/legend-symbol.js"],b["parts/Utilities.js"]],function(b,h,g){var r=g.clamp,v=g.extend,C=g.fireEvent,p=g.isNumber,A=g.merge,w=g.pick;g=g.seriesType;var E=b.colorMapPointMixin,u=b.Series,x=b.SVGRenderer.prototype.symbols;g("heatmap","scatter",{animation:!1,borderWidth:0,nullColor:"#f7f7f7",dataLabels:{formatter:function(){return this.point.value}, +inside:!0,verticalAlign:"middle",crop:!1,overflow:!1,padding:0},marker:{symbol:"rect",radius:0,lineColor:void 0,states:{hover:{lineWidthPlus:0},select:{}}},clip:!0,pointRange:null,tooltip:{pointFormat:"{point.x}, {point.y}: {point.value}
    "},states:{hover:{halo:!1,brightness:.2}}},A(b.colorMapSeriesMixin,{pointArrayMap:["y","value"],hasPointSpecificOptions:!0,getExtremesFromAll:!0,directTouch:!0,init:function(){u.prototype.init.apply(this,arguments);var a=this.options;a.pointRange=w(a.pointRange, +a.colsize||1);this.yAxis.axisPointRange=a.rowsize||1;v(x,{ellipse:x.circle,rect:x.square})},getSymbol:u.prototype.getSymbol,setClip:function(a){var b=this.chart;u.prototype.setClip.apply(this,arguments);(!1!==this.options.clip||a)&&this.markerGroup.clip((a||this.clipBox)&&this.sharedClipKey?b[this.sharedClipKey]:b.clipRect)},translate:function(){var a=this.options,b=a.marker&&a.marker.symbol||"",g=x[b]?b:"rect";a=this.options;var h=-1!==["circle","square"].indexOf(g);this.generatePoints();this.points.forEach(function(a){var f= +a.getCellAttributes(),m={x:Math.min(f.x1,f.x2),y:Math.min(f.y1,f.y2),width:Math.max(Math.abs(f.x2-f.x1),0),height:Math.max(Math.abs(f.y2-f.y1),0)};var q=a.hasImage=0===(a.marker&&a.marker.symbol||b||"").indexOf("url");if(h){var e=Math.abs(m.width-m.height);m.x=Math.min(f.x1,f.x2)+(m.width= from) && + (typeof to === 'undefined' || value <= to)) { + color = dataClass.color; + if (point) { + point.dataClass = i; + point.colorIndex = dataClass.colorIndex; + } + break; + } + } + } + else { + pos = axis.normalizedValue(value); + i = stops.length; + while (i--) { + if (pos > stops[i][0]) { + break; + } + } + from = stops[i] || stops[i + 1]; + to = stops[i + 1] || from; + // The position within the gradient + pos = 1 - (to[0] - pos) / ((to[0] - from[0]) || 1); + color = from.color.tweenTo(to.color, pos); + } + return color; + }; + /** + * Override the getOffset method to add the whole axis groups inside the + * legend. + * @private + */ + ColorAxis.prototype.getOffset = function () { + var axis = this; + var group = axis.legendGroup; + var sideOffset = axis.chart.axisOffset[axis.side]; + if (group) { + // Hook for the getOffset method to add groups to this parent + // group + axis.axisParent = group; + // Call the base + _super.prototype.getOffset.call(this); + // First time only + if (!axis.added) { + axis.added = true; + axis.labelLeft = 0; + axis.labelRight = axis.width; + } + // Reset it to avoid color axis reserving space + axis.chart.axisOffset[axis.side] = sideOffset; + } + }; + /** + * Create the color gradient. + * @private + */ + ColorAxis.prototype.setLegendColor = function () { + var axis = this; + var horiz = axis.horiz; + var reversed = axis.reversed; + var one = reversed ? 1 : 0; + var zero = reversed ? 0 : 1; + var grad = horiz ? [one, 0, zero, 0] : [0, zero, 0, one]; // #3190 + axis.legendColor = { + linearGradient: { + x1: grad[0], + y1: grad[1], + x2: grad[2], + y2: grad[3] + }, + stops: axis.stops + }; + }; + /** + * The color axis appears inside the legend and has its own legend symbol. + * @private + */ + ColorAxis.prototype.drawLegendSymbol = function (legend, item) { + var axis = this; + var padding = legend.padding; + var legendOptions = legend.options; + var horiz = axis.horiz; + var width = pick(legendOptions.symbolWidth, horiz ? ColorAxis.defaultLegendLength : 12); + var height = pick(legendOptions.symbolHeight, horiz ? 12 : ColorAxis.defaultLegendLength); + var labelPadding = pick(legendOptions.labelPadding, horiz ? 16 : 30); + var itemDistance = pick(legendOptions.itemDistance, 10); + this.setLegendColor(); + // Create the gradient + item.legendSymbol = this.chart.renderer.rect(0, legend.baseline - 11, width, height).attr({ + zIndex: 1 + }).add(item.legendGroup); + // Set how much space this legend item takes up + axis.legendItemWidth = width + padding + (horiz ? itemDistance : labelPadding); + axis.legendItemHeight = height + padding + (horiz ? labelPadding : 0); + }; + /** + * Fool the legend. + * @private + */ + ColorAxis.prototype.setState = function (state) { + this.series.forEach(function (series) { + series.setState(state); + }); + }; + /** + * @private + */ + ColorAxis.prototype.setVisible = function () { + }; + /** + * @private + */ + ColorAxis.prototype.getSeriesExtremes = function () { + var axis = this; + var series = axis.series; + var colorValArray, colorKey, colorValIndex, pointArrayMap, calculatedExtremes, cSeries, i = series.length, yData, j; + this.dataMin = Infinity; + this.dataMax = -Infinity; + while (i--) { // x, y, value, other + cSeries = series[i]; + colorKey = cSeries.colorKey = pick(cSeries.options.colorKey, cSeries.colorKey, cSeries.pointValKey, cSeries.zoneAxis, 'y'); + pointArrayMap = cSeries.pointArrayMap; + calculatedExtremes = cSeries[colorKey + 'Min'] && + cSeries[colorKey + 'Max']; + if (cSeries[colorKey + 'Data']) { + colorValArray = cSeries[colorKey + 'Data']; + } + else { + if (!pointArrayMap) { + colorValArray = cSeries.yData; + } + else { + colorValArray = []; + colorValIndex = pointArrayMap.indexOf(colorKey); + yData = cSeries.yData; + if (colorValIndex >= 0 && yData) { + for (j = 0; j < yData.length; j++) { + colorValArray.push(pick(yData[j][colorValIndex], yData[j])); + } + } + } + } + // If color key extremes are already calculated, use them. + if (calculatedExtremes) { + cSeries.minColorValue = cSeries[colorKey + 'Min']; + cSeries.maxColorValue = cSeries[colorKey + 'Max']; + } + else { + var cExtremes = Series.prototype.getExtremes.call(cSeries, colorValArray); + cSeries.minColorValue = cExtremes.dataMin; + cSeries.maxColorValue = cExtremes.dataMax; + } + if (typeof cSeries.minColorValue !== 'undefined') { + this.dataMin = + Math.min(this.dataMin, cSeries.minColorValue); + this.dataMax = + Math.max(this.dataMax, cSeries.maxColorValue); + } + if (!calculatedExtremes) { + Series.prototype.applyExtremes.call(cSeries); + } + } + }; + /** + * Internal function to draw a crosshair. + * + * @function Highcharts.ColorAxis#drawCrosshair + * + * @param {Highcharts.PointerEventObject} [e] + * The event arguments from the modified pointer event, extended with + * `chartX` and `chartY` + * + * @param {Highcharts.Point} [point] + * The Point object if the crosshair snaps to points. + * + * @fires Highcharts.ColorAxis#event:afterDrawCrosshair + * @fires Highcharts.ColorAxis#event:drawCrosshair + */ + ColorAxis.prototype.drawCrosshair = function (e, point) { + var axis = this; + var plotX = point && point.plotX; + var plotY = point && point.plotY; + var axisPos = axis.pos; + var axisLen = axis.len; + var crossPos; + if (point) { + crossPos = axis.toPixels(point.getNestedProperty(point.series.colorKey)); + if (crossPos < axisPos) { + crossPos = axisPos - 2; + } + else if (crossPos > axisPos + axisLen) { + crossPos = axisPos + axisLen + 2; + } + point.plotX = crossPos; + point.plotY = axis.len - crossPos; + _super.prototype.drawCrosshair.call(this, e, point); + point.plotX = plotX; + point.plotY = plotY; + if (axis.cross && + !axis.cross.addedToColorAxis && + axis.legendGroup) { + axis.cross + .addClass('highcharts-coloraxis-marker') + .add(axis.legendGroup); + axis.cross.addedToColorAxis = true; + if (!axis.chart.styledMode && + axis.crosshair) { + axis.cross.attr({ + fill: axis.crosshair.color + }); + } + } + } + }; + /** + * @private + */ + ColorAxis.prototype.getPlotLinePath = function (options) { + var axis = this; + var left = axis.left; + var pos = options.translatedValue; + var top = axis.top; + // crosshairs only + return isNumber(pos) ? // pos can be 0 (#3969) + (axis.horiz ? [ + ['M', pos - 4, this.top - 6], + ['L', pos + 4, this.top - 6], + ['L', pos, this.top], + ['Z'] + ] : [ + ['M', this.left, pos], + ['L', this.left - 6, pos + 6], + ['L', this.left - 6, pos - 6], + ['Z'] + ]) : + _super.prototype.getPlotLinePath.call(this, options); + }; + /** + * Updates a color axis instance with a new set of options. The options are + * merged with the existing options, so only new or altered options need to + * be specified. + * + * @function Highcharts.ColorAxis#update + * + * @param {Highcharts.ColorAxisOptions} newOptions + * The new options that will be merged in with existing options on the color + * axis. + * + * @param {boolean} [redraw] + * Whether to redraw the chart after the color axis is altered. If doing + * more operations on the chart, it is a good idea to set redraw to `false` + * and call {@link Highcharts.Chart#redraw} after. + */ + ColorAxis.prototype.update = function (newOptions, redraw) { + var axis = this; + var chart = axis.chart; + var legend = chart.legend; + var updatedOptions = ColorAxis.buildOptions(chart, {}, newOptions); + this.series.forEach(function (series) { + // Needed for Axis.update when choropleth colors change + series.isDirtyData = true; + }); + // When updating data classes, destroy old items and make sure new + // ones are created (#3207) + if (newOptions.dataClasses && legend.allItems || axis.dataClasses) { + axis.destroyItems(); + } + // Keep the options structure updated for export. Unlike xAxis and + // yAxis, the colorAxis is not an array. (#3207) + chart.options[axis.coll] = + merge(axis.userOptions, updatedOptions); + _super.prototype.update.call(this, updatedOptions, redraw); + if (axis.legendItem) { + axis.setLegendColor(); + legend.colorizeItem(this, true); + } + }; + /** + * Destroy color axis legend items. + * @private + */ + ColorAxis.prototype.destroyItems = function () { + var axis = this; + var chart = axis.chart; + if (axis.legendItem) { + chart.legend.destroyItem(axis); + } + else if (axis.legendItems) { + axis.legendItems.forEach(function (item) { + chart.legend.destroyItem(item); + }); + } + chart.isDirtyLegend = true; + }; + /** + * Removes the color axis and the related legend item. + * + * @function Highcharts.ColorAxis#remove + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart following the remove. + */ + ColorAxis.prototype.remove = function (redraw) { + this.destroyItems(); + _super.prototype.remove.call(this, redraw); + }; + /** + * Get the legend item symbols for data classes. + * @private + */ + ColorAxis.prototype.getDataClassLegendSymbols = function () { + var axis = this; + var chart = axis.chart; + var legendItems = axis.legendItems; + var legendOptions = chart.options.legend; + var valueDecimals = legendOptions.valueDecimals; + var valueSuffix = legendOptions.valueSuffix || ''; + var name; + if (!legendItems.length) { + axis.dataClasses.forEach(function (dataClass, i) { + var vis = true, from = dataClass.from, to = dataClass.to; + var numberFormatter = chart.numberFormatter; + // Assemble the default name. This can be overridden + // by legend.options.labelFormatter + name = ''; + if (typeof from === 'undefined') { + name = '< '; + } + else if (typeof to === 'undefined') { + name = '> '; + } + if (typeof from !== 'undefined') { + name += numberFormatter(from, valueDecimals) + valueSuffix; + } + if (typeof from !== 'undefined' && typeof to !== 'undefined') { + name += ' - '; + } + if (typeof to !== 'undefined') { + name += numberFormatter(to, valueDecimals) + valueSuffix; + } + // Add a mock object to the legend items + legendItems.push(extend({ + chart: chart, + name: name, + options: {}, + drawLegendSymbol: LegendSymbolMixin.drawRectangle, + visible: true, + setState: noop, + isDataClass: true, + setVisible: function () { + vis = axis.visible = !vis; + axis.series.forEach(function (series) { + series.points.forEach(function (point) { + if (point.dataClass === i) { + point.setVisible(vis); + } + }); + }); + chart.legend.colorizeItem(this, vis); + } + }, dataClass)); + }); + } + return legendItems; + }; + /* * + * + * Static Functions + * + * */ + ColorAxis.defaultLegendLength = 200; + /** + * A color axis for series. Visually, the color + * axis will appear as a gradient or as separate items inside the + * legend, depending on whether the axis is scalar or based on data + * classes. + * + * For supported color formats, see the + * [docs article about colors](https://www.highcharts.com/docs/chart-design-and-style/colors). + * + * A scalar color axis is represented by a gradient. The colors either + * range between the [minColor](#colorAxis.minColor) and the + * [maxColor](#colorAxis.maxColor), or for more fine grained control the + * colors can be defined in [stops](#colorAxis.stops). Often times, the + * color axis needs to be adjusted to get the right color spread for the + * data. In addition to stops, consider using a logarithmic + * [axis type](#colorAxis.type), or setting [min](#colorAxis.min) and + * [max](#colorAxis.max) to avoid the colors being determined by + * outliers. + * + * When [dataClasses](#colorAxis.dataClasses) are used, the ranges are + * subdivided into separate classes like categories based on their + * values. This can be used for ranges between two values, but also for + * a true category. However, when your data is categorized, it may be as + * convenient to add each category to a separate series. + * + * Color axis does not work with: `sankey`, `sunburst`, `dependencywheel`, + * `networkgraph`, `wordcloud`, `venn`, `gauge` and `solidgauge` series + * types. + * + * Since v7.2.0 `colorAxis` can also be an array of options objects. + * + * See [the Axis object](/class-reference/Highcharts.Axis) for + * programmatic access to the axis. + * + * @sample {highcharts} highcharts/coloraxis/custom-color-key + * Column chart with color axis + * @sample {highcharts} highcharts/coloraxis/horizontal-layout + * Horizontal layout + * @sample {highmaps} maps/coloraxis/dataclasscolor + * With data classes + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor + * Min color and max color + * + * @extends xAxis + * @excluding alignTicks, allowDecimals, alternateGridColor, breaks, + * categories, crosshair, dateTimeLabelFormats, height, left, + * lineWidth, linkedTo, maxZoom, minRange, minTickInterval, + * offset, opposite, pane, plotBands, plotLines, + * reversedStacks, showEmpty, title, top, width, zoomEnabled + * @product highcharts highstock highmaps + * @type {*|Array<*>} + * @optionparent colorAxis + * @ignore + */ + ColorAxis.defaultOptions = { + /** + * Whether to allow decimals on the color axis. + * @type {boolean} + * @default true + * @product highcharts highstock highmaps + * @apioption colorAxis.allowDecimals + */ + /** + * Determines how to set each data class' color if no individual + * color is set. The default value, `tween`, computes intermediate + * colors between `minColor` and `maxColor`. The other possible + * value, `category`, pulls colors from the global or chart specific + * [colors](#colors) array. + * + * @sample {highmaps} maps/coloraxis/dataclasscolor/ + * Category colors + * + * @type {string} + * @default tween + * @product highcharts highstock highmaps + * @validvalue ["tween", "category"] + * @apioption colorAxis.dataClassColor + */ + /** + * An array of data classes or ranges for the choropleth map. If + * none given, the color axis is scalar and values are distributed + * as a gradient between the minimum and maximum colors. + * + * @sample {highmaps} maps/demo/data-class-ranges/ + * Multiple ranges + * + * @sample {highmaps} maps/demo/data-class-two-ranges/ + * Two ranges + * + * @type {Array<*>} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses + */ + /** + * The layout of the color axis. Can be `'horizontal'` or `'vertical'`. + * If none given, the color axis has the same layout as the legend. + * + * @sample highcharts/coloraxis/horizontal-layout/ + * Horizontal color axis layout with vertical legend + * + * @type {string|undefined} + * @since 7.2.0 + * @product highcharts highstock highmaps + * @apioption colorAxis.layout + */ + /** + * The color of each data class. If not set, the color is pulled + * from the global or chart-specific [colors](#colors) array. In + * styled mode, this option is ignored. Instead, use colors defined + * in CSS. + * + * @sample {highmaps} maps/demo/data-class-two-ranges/ + * Explicit colors + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses.color + */ + /** + * The start of the value range that the data class represents, + * relating to the point value. + * + * The range of each `dataClass` is closed in both ends, but can be + * overridden by the next `dataClass`. + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses.from + */ + /** + * The name of the data class as it appears in the legend. + * If no name is given, it is automatically created based on the + * `from` and `to` values. For full programmatic control, + * [legend.labelFormatter](#legend.labelFormatter) can be used. + * In the formatter, `this.from` and `this.to` can be accessed. + * + * @sample {highmaps} maps/coloraxis/dataclasses-name/ + * Named data classes + * + * @sample {highmaps} maps/coloraxis/dataclasses-labelformatter/ + * Formatted data classes + * + * @type {string} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses.name + */ + /** + * The end of the value range that the data class represents, + * relating to the point value. + * + * The range of each `dataClass` is closed in both ends, but can be + * overridden by the next `dataClass`. + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.dataClasses.to + */ + /** @ignore-option */ + lineWidth: 0, + /** + * Padding of the min value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. + * + * @product highcharts highstock highmaps + */ + minPadding: 0, + /** + * The maximum value of the axis in terms of map point values. If + * `null`, the max value is automatically calculated. If the + * `endOnTick` option is true, the max value might be rounded up. + * + * @sample {highmaps} maps/coloraxis/gridlines/ + * Explicit min and max to reduce the effect of outliers + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.max + */ + /** + * The minimum value of the axis in terms of map point values. If + * `null`, the min value is automatically calculated. If the + * `startOnTick` option is true, the min value might be rounded + * down. + * + * @sample {highmaps} maps/coloraxis/gridlines/ + * Explicit min and max to reduce the effect of outliers + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.min + */ + /** + * Padding of the max value relative to the length of the axis. A + * padding of 0.05 will make a 100px axis 5px longer. + * + * @product highcharts highstock highmaps + */ + maxPadding: 0, + /** + * Color of the grid lines extending from the axis across the + * gradient. + * + * @sample {highmaps} maps/coloraxis/gridlines/ + * Grid lines demonstrated + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @default #e6e6e6 + * @product highcharts highstock highmaps + * @apioption colorAxis.gridLineColor + */ + /** + * The width of the grid lines extending from the axis across the + * gradient of a scalar color axis. + * + * @sample {highmaps} maps/coloraxis/gridlines/ + * Grid lines demonstrated + * + * @product highcharts highstock highmaps + */ + gridLineWidth: 1, + /** + * The interval of the tick marks in axis units. When `null`, the + * tick interval is computed to approximately follow the + * `tickPixelInterval`. + * + * @type {number} + * @product highcharts highstock highmaps + * @apioption colorAxis.tickInterval + */ + /** + * If [tickInterval](#colorAxis.tickInterval) is `null` this option + * sets the approximate pixel interval of the tick marks. + * + * @product highcharts highstock highmaps + */ + tickPixelInterval: 72, + /** + * Whether to force the axis to start on a tick. Use this option + * with the `maxPadding` option to control the axis start. + * + * @product highcharts highstock highmaps + */ + startOnTick: true, + /** + * Whether to force the axis to end on a tick. Use this option with + * the [maxPadding](#colorAxis.maxPadding) option to control the + * axis end. + * + * @product highcharts highstock highmaps + */ + endOnTick: true, + /** @ignore */ + offset: 0, + /** + * The triangular marker on a scalar color axis that points to the + * value of the hovered area. To disable the marker, set + * `marker: null`. + * + * @sample {highmaps} maps/coloraxis/marker/ + * Black marker + * + * @declare Highcharts.PointMarkerOptionsObject + * @product highcharts highstock highmaps + */ + marker: { + /** + * Animation for the marker as it moves between values. Set to + * `false` to disable animation. Defaults to `{ duration: 50 }`. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + * @product highcharts highstock highmaps + */ + animation: { + /** @internal */ + duration: 50 + }, + /** @internal */ + width: 0.01, + /** + * The color of the marker. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock highmaps + */ + color: '#999999' + }, + /** + * The axis labels show the number for each tick. + * + * For more live examples on label options, see [xAxis.labels in the + * Highcharts API.](/highcharts#xAxis.labels) + * + * @extends xAxis.labels + * @product highcharts highstock highmaps + */ + labels: { + /** + * How to handle overflowing labels on horizontal color axis. If set + * to `"allow"`, it will not be aligned at all. By default it + * `"justify"` labels inside the chart area. If there is room to + * move it, it will be aligned to the edge, else it will be removed. + * + * @validvalue ["allow", "justify"] + * @product highcharts highstock highmaps + */ + overflow: 'justify', + rotation: 0 + }, + /** + * The color to represent the minimum of the color axis. Unless + * [dataClasses](#colorAxis.dataClasses) or + * [stops](#colorAxis.stops) are set, the gradient starts at this + * value. + * + * If dataClasses are set, the color is based on minColor and + * maxColor unless a color is set for each data class, or the + * [dataClassColor](#colorAxis.dataClassColor) is set. + * + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor/ + * Min and max colors on scalar (gradient) axis + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor-dataclasses/ + * On data classes + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock highmaps + */ + minColor: '#e6ebf5', + /** + * The color to represent the maximum of the color axis. Unless + * [dataClasses](#colorAxis.dataClasses) or + * [stops](#colorAxis.stops) are set, the gradient ends at this + * value. + * + * If dataClasses are set, the color is based on minColor and + * maxColor unless a color is set for each data class, or the + * [dataClassColor](#colorAxis.dataClassColor) is set. + * + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor/ + * Min and max colors on scalar (gradient) axis + * @sample {highmaps} maps/coloraxis/mincolor-maxcolor-dataclasses/ + * On data classes + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock highmaps + */ + maxColor: '#003399', + /** + * Color stops for the gradient of a scalar color axis. Use this in + * cases where a linear gradient between a `minColor` and `maxColor` + * is not sufficient. The stops is an array of tuples, where the + * first item is a float between 0 and 1 assigning the relative + * position in the gradient, and the second item is the color. + * + * @sample {highmaps} maps/demo/heatmap/ + * Heatmap with three color stops + * + * @type {Array>} + * @product highcharts highstock highmaps + * @apioption colorAxis.stops + */ + /** + * The pixel length of the main tick marks on the color axis. + */ + tickLength: 5, + /** + * The type of interpolation to use for the color axis. Can be + * `linear` or `logarithmic`. + * + * @sample highcharts/coloraxis/logarithmic-with-emulate-negative-values/ + * Logarithmic color axis with extension to emulate negative + * values + * + * @type {Highcharts.ColorAxisTypeValue} + * @default linear + * @product highcharts highstock highmaps + * @apioption colorAxis.type + */ + /** + * Whether to reverse the axis so that the highest number is closest + * to the origin. Defaults to `false` in a horizontal legend and + * `true` in a vertical legend, where the smallest value starts on + * top. + * + * @type {boolean} + * @product highcharts highstock highmaps + * @apioption colorAxis.reversed + */ + /** + * @product highcharts highstock highmaps + * @excluding afterBreaks, pointBreak, pointInBreak + * @apioption colorAxis.events + */ + /** + * Fires when the legend item belonging to the colorAxis is clicked. + * One parameter, `event`, is passed to the function. + * + * @type {Function} + * @product highcharts highstock highmaps + * @apioption colorAxis.events.legendItemClick + */ + /** + * Whether to display the colorAxis in the legend. + * + * @sample highcharts/coloraxis/hidden-coloraxis-with-3d-chart/ + * Hidden color axis with 3d chart + * + * @see [heatmap.showInLegend](#series.heatmap.showInLegend) + * + * @since 4.2.7 + * @product highcharts highstock highmaps + */ + showInLegend: true + }; + /** + * @private + */ + ColorAxis.keepProps = [ + 'legendGroup', + 'legendItemHeight', + 'legendItemWidth', + 'legendItem', + 'legendSymbol' + ]; + return ColorAxis; + }(Axis)); + // Properties to preserve after destroy, for Axis.update (#5881, #6025). + Array.prototype.push.apply(Axis.keepProps, ColorAxis.keepProps); + H.ColorAxis = ColorAxis; + /** + * Handle animation of the color attributes directly + * + * @private + * @function Highcharts.Fx#fillSetter + */ /** + * Handle animation of the color attributes directly + * + * @private + * @function Highcharts.Fx#strokeSetter + */ + ['fill', 'stroke'].forEach(function (prop) { + Fx.prototype[prop + 'Setter'] = function () { + this.elem.attr(prop, color(this.start).tweenTo(color(this.end), this.pos), null, true); + }; + }); + // Extend the chart getAxes method to also get the color axis + addEvent(Chart, 'afterGetAxes', function () { + var chart = this, options = chart.options; + this.colorAxis = []; + if (options.colorAxis) { + options.colorAxis = splat(options.colorAxis); + options.colorAxis.forEach(function (axisOptions, i) { + axisOptions.index = i; + new ColorAxis(chart, axisOptions); // eslint-disable-line no-new + }); + } + }); + // Add colorAxis to series axisTypes + addEvent(Series, 'bindAxes', function () { + var axisTypes = this.axisTypes; + if (!axisTypes) { + this.axisTypes = ['colorAxis']; + } + else if (axisTypes.indexOf('colorAxis') === -1) { + axisTypes.push('colorAxis'); + } + }); + // Add the color axis. This also removes the axis' own series to prevent + // them from showing up individually. + addEvent(Legend, 'afterGetAllItems', function (e) { + var colorAxisItems = [], colorAxes = this.chart.colorAxis || [], options, i; + colorAxes.forEach(function (colorAxis) { + options = colorAxis.options; + if (options && options.showInLegend) { + // Data classes + if (options.dataClasses && options.visible) { + colorAxisItems = colorAxisItems.concat(colorAxis.getDataClassLegendSymbols()); + // Gradient legend + } + else if (options.visible) { + // Add this axis on top + colorAxisItems.push(colorAxis); + } + // If dataClasses are defined or showInLegend option is not set to + // true, do not add color axis' series to legend. + colorAxis.series.forEach(function (series) { + if (!series.options.showInLegend || options.dataClasses) { + if (series.options.legendType === 'point') { + series.points.forEach(function (point) { + erase(e.allItems, point); + }); + } + else { + erase(e.allItems, series); + } + } + }); + } + }); + i = colorAxisItems.length; + while (i--) { + e.allItems.unshift(colorAxisItems[i]); + } + }); + addEvent(Legend, 'afterColorizeItem', function (e) { + if (e.visible && e.item.legendColor) { + e.item.legendSymbol.attr({ + fill: e.item.legendColor + }); + } + }); + // Updates in the legend need to be reflected in the color axis (6888) + addEvent(Legend, 'afterUpdate', function () { + var colorAxes = this.chart.colorAxis; + if (colorAxes) { + colorAxes.forEach(function (colorAxis) { + colorAxis.update({}, arguments[2]); + }); + } + }); + // Calculate and set colors for points + addEvent(Series, 'afterTranslate', function () { + if (this.chart.colorAxis && + this.chart.colorAxis.length || + this.colorAttribs) { + this.translateColors(); + } + }); + + return ColorAxis; + }); + _registerModule(_modules, 'parts-map/ColorMapSeriesMixin.js', [_modules['parts/Globals.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js']], function (H, Point, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var defined = U.defined; + var noop = H.noop, seriesTypes = H.seriesTypes; + /** + * Mixin for maps and heatmaps + * + * @private + * @mixin Highcharts.colorMapPointMixin + */ + H.colorMapPointMixin = { + dataLabelOnNull: true, + /* eslint-disable valid-jsdoc */ + /** + * Color points have a value option that determines whether or not it is + * a null point + * @private + * @function Highcharts.colorMapPointMixin.isValid + * @return {boolean} + */ + isValid: function () { + // undefined is allowed + return (this.value !== null && + this.value !== Infinity && + this.value !== -Infinity); + }, + /** + * @private + * @function Highcharts.colorMapPointMixin.setState + * @param {string} state + * @return {void} + */ + setState: function (state) { + Point.prototype.setState.call(this, state); + if (this.graphic) { + this.graphic.attr({ + zIndex: state === 'hover' ? 1 : 0 + }); + } + } + /* eslint-enable valid-jsdoc */ + }; + /** + * @private + * @mixin Highcharts.colorMapSeriesMixin + */ + H.colorMapSeriesMixin = { + pointArrayMap: ['value'], + axisTypes: ['xAxis', 'yAxis', 'colorAxis'], + trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'], + getSymbol: noop, + parallelArrays: ['x', 'y', 'value'], + colorKey: 'value', + pointAttribs: seriesTypes.column.prototype.pointAttribs, + /* eslint-disable valid-jsdoc */ + /** + * Get the color attibutes to apply on the graphic + * @private + * @function Highcharts.colorMapSeriesMixin.colorAttribs + * @param {Highcharts.Point} point + * @return {Highcharts.SVGAttributes} + */ + colorAttribs: function (point) { + var ret = {}; + if (defined(point.color)) { + ret[this.colorProp || 'fill'] = point.color; + } + return ret; + } + }; + + }); + _registerModule(_modules, 'parts-map/HeatmapSeries.js', [_modules['parts/Globals.js'], _modules['mixins/legend-symbol.js'], _modules['parts/Utilities.js']], function (H, LegendSymbolMixin, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /* * + * @interface Highcharts.PointOptionsObject in parts/Point.ts + */ /** + * Heatmap series only. Point padding for a single point. + * @name Highcharts.PointOptionsObject#pointPadding + * @type {number|undefined} + */ /** + * Heatmap series only. The value of the point, resulting in a color controled + * by options as set in the colorAxis configuration. + * @name Highcharts.PointOptionsObject#value + * @type {number|null|undefined} + */ + var clamp = U.clamp, extend = U.extend, fireEvent = U.fireEvent, isNumber = U.isNumber, merge = U.merge, pick = U.pick, seriesType = U.seriesType; + var colorMapPointMixin = H.colorMapPointMixin, colorMapSeriesMixin = H.colorMapSeriesMixin, noop = H.noop, Series = H.Series, seriesTypes = H.seriesTypes, symbols = H.SVGRenderer.prototype.symbols; + /** + * @private + * @class + * @name Highcharts.seriesTypes.heatmap + * + * @augments Highcharts.Series + */ + seriesType('heatmap', 'scatter', + /** + * A heatmap is a graphical representation of data where the individual + * values contained in a matrix are represented as colors. + * + * @productdesc {highcharts} + * Requires `modules/heatmap`. + * + * @sample highcharts/demo/heatmap/ + * Simple heatmap + * @sample highcharts/demo/heatmap-canvas/ + * Heavy heatmap + * + * @extends plotOptions.scatter + * @excluding animationLimit, connectEnds, connectNulls, dashStyle, + * findNearestPointBy, getExtremesFromAll, jitter, linecap, + * lineWidth, pointInterval, pointIntervalUnit, pointRange, + * pointStart, shadow, softThreshold, stacking, step, + * threshold, cluster + * @product highcharts highmaps + * @optionparent plotOptions.heatmap + */ + { + /** + * Animation is disabled by default on the heatmap series. + */ + animation: false, + /** + * The border width for each heat map item. + */ + borderWidth: 0, + /** + * Padding between the points in the heatmap. + * + * @type {number} + * @default 0 + * @since 6.0 + * @apioption plotOptions.heatmap.pointPadding + */ + /** + * @default value + * @apioption plotOptions.heatmap.colorKey + */ + /** + * The main color of the series. In heat maps this color is rarely used, + * as we mostly use the color to denote the value of each point. Unless + * options are set in the [colorAxis](#colorAxis), the default value + * is pulled from the [options.colors](#colors) array. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 4.0 + * @product highcharts + * @apioption plotOptions.heatmap.color + */ + /** + * The column size - how many X axis units each column in the heatmap + * should span. + * + * @sample {highcharts} maps/demo/heatmap/ + * One day + * @sample {highmaps} maps/demo/heatmap/ + * One day + * + * @type {number} + * @default 1 + * @since 4.0 + * @product highcharts highmaps + * @apioption plotOptions.heatmap.colsize + */ + /** + * The row size - how many Y axis units each heatmap row should span. + * + * @sample {highcharts} maps/demo/heatmap/ + * 1 by default + * @sample {highmaps} maps/demo/heatmap/ + * 1 by default + * + * @type {number} + * @default 1 + * @since 4.0 + * @product highcharts highmaps + * @apioption plotOptions.heatmap.rowsize + */ + /** + * The color applied to null points. In styled mode, a general CSS class + * is applied instead. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ + nullColor: '#f7f7f7', + dataLabels: { + formatter: function () { + return this.point.value; + }, + inside: true, + verticalAlign: 'middle', + crop: false, + overflow: false, + padding: 0 // #3837 + }, + /** + * @excluding radius, enabledThreshold + */ + marker: { + /** + * A predefined shape or symbol for the marker. When undefined, the + * symbol is pulled from options.symbols. Other possible values are + * `'circle'`, `'square'`,`'diamond'`, `'triangle'`, + * `'triangle-down'`, `'rect'`, and `'ellipse'`. + * + * Additionally, the URL to a graphic can be given on this form: + * `'url(graphic.png)'`. Note that for the image to be applied to + * exported charts, its URL needs to be accessible by the export + * server. + * + * Custom callbacks for symbol path generation can also be added to + * `Highcharts.SVGRenderer.prototype.symbols`. The callback is then + * used by its method name, as shown in the demo. + * + * @sample {highcharts} highcharts/plotoptions/series-marker-symbol/ + * Predefined, graphic and custom markers + * @sample {highstock} highcharts/plotoptions/series-marker-symbol/ + * Predefined, graphic and custom markers + */ + symbol: 'rect', + /** @ignore-option */ + radius: 0, + lineColor: void 0, + states: { + /** + * @excluding radius, radiusPlus + */ + hover: { + /** + * Set the marker's fixed width on hover state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.hover.width + */ + /** + * Set the marker's fixed height on hover state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.hover.height + */ + /** + * The number of pixels to increase the width of the + * selected point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * 20px greater width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.hover.widthPlus + */ + /** + * The number of pixels to increase the height of the + * selected point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * 20px greater width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.hover.heightPlus + */ + /** + * The additional line width for a hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-linewidthplus + * 5 pixels wider lineWidth on hover + * @sample {highmaps} maps/plotoptions/heatmap-marker-states-hover-linewidthplus + * 5 pixels wider lineWidth on hover + */ + lineWidthPlus: 0 + }, + /** + * @excluding radius + */ + select: { + /** + * Set the marker's fixed width on select state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.select.width + */ + /** + * Set the marker's fixed height on select state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.select.height + */ + /** + * The number of pixels to increase the width of the + * selected point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * 20px greater width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.select.widthPlus + */ + /** + * The number of pixels to increase the height of the + * selected point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * 20px greater width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption plotOptions.heatmap.marker.states.select.heightPlus + */ + } + } + }, + clip: true, + /** @ignore-option */ + pointRange: null, + tooltip: { + pointFormat: '{point.x}, {point.y}: {point.value}
    ' + }, + states: { + hover: { + /** @ignore-option */ + halo: false, + /** + * How much to brighten the point on interaction. Requires the + * main color to be defined in hex or rgb(a) format. + * + * In styled mode, the hover brightening is by default replaced + * with a fill-opacity set in the `.highcharts-point:hover` + * rule. + */ + brightness: 0.2 + } + } + }, merge(colorMapSeriesMixin, { + pointArrayMap: ['y', 'value'], + hasPointSpecificOptions: true, + getExtremesFromAll: true, + directTouch: true, + /* eslint-disable valid-jsdoc */ + /** + * Override the init method to add point ranges on both axes. + * + * @private + * @function Highcharts.seriesTypes.heatmap#init + * @return {void} + */ + init: function () { + var options; + Series.prototype.init.apply(this, arguments); + options = this.options; + // #3758, prevent resetting in setData + options.pointRange = pick(options.pointRange, options.colsize || 1); + // general point range + this.yAxis.axisPointRange = options.rowsize || 1; + // Bind new symbol names + extend(symbols, { + ellipse: symbols.circle, + rect: symbols.square + }); + }, + getSymbol: Series.prototype.getSymbol, + /** + * @private + * @function Highcharts.seriesTypes.heatmap#setClip + * @return {void} + */ + setClip: function (animation) { + var series = this, chart = series.chart; + Series.prototype.setClip.apply(series, arguments); + if (series.options.clip !== false || animation) { + series.markerGroup + .clip((animation || series.clipBox) && series.sharedClipKey ? + chart[series.sharedClipKey] : + chart.clipRect); + } + }, + /** + * @private + * @function Highcharts.seriesTypes.heatmap#translate + * @return {void} + */ + translate: function () { + var series = this, options = series.options, symbol = options.marker && options.marker.symbol || '', shape = symbols[symbol] ? symbol : 'rect', options = series.options, hasRegularShape = ['circle', 'square'].indexOf(shape) !== -1; + series.generatePoints(); + series.points.forEach(function (point) { + var pointAttr, sizeDiff, hasImage, cellAttr = point.getCellAttributes(), shapeArgs = { + x: Math.min(cellAttr.x1, cellAttr.x2), + y: Math.min(cellAttr.y1, cellAttr.y2), + width: Math.max(Math.abs(cellAttr.x2 - cellAttr.x1), 0), + height: Math.max(Math.abs(cellAttr.y2 - cellAttr.y1), 0) + }; + hasImage = point.hasImage = + (point.marker && point.marker.symbol || symbol || '') + .indexOf('url') === 0; + // If marker shape is regular (symetric), find shorter + // cell's side. + if (hasRegularShape) { + sizeDiff = Math.abs(shapeArgs.width - shapeArgs.height); + shapeArgs.x = Math.min(cellAttr.x1, cellAttr.x2) + + (shapeArgs.width < shapeArgs.height ? 0 : sizeDiff / 2); + shapeArgs.y = Math.min(cellAttr.y1, cellAttr.y2) + + (shapeArgs.width < shapeArgs.height ? sizeDiff / 2 : 0); + shapeArgs.width = shapeArgs.height = + Math.min(shapeArgs.width, shapeArgs.height); + } + pointAttr = { + plotX: (cellAttr.x1 + cellAttr.x2) / 2, + plotY: (cellAttr.y1 + cellAttr.y2) / 2, + clientX: (cellAttr.x1 + cellAttr.x2) / 2, + shapeType: 'path', + shapeArgs: merge(true, shapeArgs, { + d: symbols[shape](shapeArgs.x, shapeArgs.y, shapeArgs.width, shapeArgs.height) + }) + }; + if (hasImage) { + point.marker = { + width: shapeArgs.width, + height: shapeArgs.height + }; + } + extend(point, pointAttr); + }); + fireEvent(series, 'afterTranslate'); + }, + /** + * @private + * @function Highcharts.seriesTypes.heatmap#pointAttribs + * @param {Highcharts.HeatmapPoint} point + * @param {string} state + * @return {Highcharts.SVGAttributes} + */ + pointAttribs: function (point, state) { + var series = this, attr = Series.prototype.pointAttribs + .call(series, point, state), seriesOptions = series.options || {}, plotOptions = series.chart.options.plotOptions || {}, seriesPlotOptions = plotOptions.series || {}, heatmapPlotOptions = plotOptions.heatmap || {}, stateOptions, brightness, + // Get old properties in order to keep backward compatibility + borderColor = seriesOptions.borderColor || + heatmapPlotOptions.borderColor || + seriesPlotOptions.borderColor, borderWidth = seriesOptions.borderWidth || + heatmapPlotOptions.borderWidth || + seriesPlotOptions.borderWidth || + attr['stroke-width']; + // Apply lineColor, or set it to default series color. + attr.stroke = ((point && point.marker && point.marker.lineColor) || + (seriesOptions.marker && seriesOptions.marker.lineColor) || + borderColor || + this.color); + // Apply old borderWidth property if exists. + attr['stroke-width'] = borderWidth; + if (state) { + stateOptions = + merge(seriesOptions.states[state], seriesOptions.marker && + seriesOptions.marker.states[state], point.options.states && + point.options.states[state] || {}); + brightness = stateOptions.brightness; + attr.fill = + stateOptions.color || + H.color(attr.fill).brighten(brightness || 0).get(); + attr.stroke = stateOptions.lineColor; + } + return attr; + }, + /** + * @private + * @function Highcharts.seriesTypes.heatmap#markerAttribs + * @param {Highcharts.HeatmapPoint} point + * @return {Highcharts.SVGAttributes} + */ + markerAttribs: function (point, state) { + var pointMarkerOptions = point.marker || {}, seriesMarkerOptions = this.options.marker || {}, seriesStateOptions, pointStateOptions, shapeArgs = point.shapeArgs || {}, hasImage = point.hasImage, attribs = {}; + if (hasImage) { + return { + x: point.plotX, + y: point.plotY + }; + } + // Setting width and height attributes on image does not affect + // on its dimensions. + if (state) { + seriesStateOptions = seriesMarkerOptions.states[state] || {}; + pointStateOptions = pointMarkerOptions.states && + pointMarkerOptions.states[state] || {}; + [['width', 'x'], ['height', 'y']].forEach(function (dimension) { + // Set new width and height basing on state options. + attribs[dimension[0]] = (pointStateOptions[dimension[0]] || + seriesStateOptions[dimension[0]] || + shapeArgs[dimension[0]]) + (pointStateOptions[dimension[0] + 'Plus'] || + seriesStateOptions[dimension[0] + 'Plus'] || 0); + // Align marker by a new size. + attribs[dimension[1]] = shapeArgs[dimension[1]] + + (shapeArgs[dimension[0]] - attribs[dimension[0]]) / 2; + }); + } + return state ? attribs : shapeArgs; + }, + /** + * @private + * @function Highcharts.seriesTypes.heatmap#drawPoints + * @return {void} + */ + drawPoints: function () { + var _this = this; + // In styled mode, use CSS, otherwise the fill used in the style + // sheet will take precedence over the fill attribute. + var seriesMarkerOptions = this.options.marker || {}; + if (seriesMarkerOptions.enabled || this._hasPointMarkers) { + Series.prototype.drawPoints.call(this); + this.points.forEach(function (point) { + point.graphic && + point.graphic[_this.chart.styledMode ? 'css' : 'animate'](_this.colorAttribs(point)); + }); + } + }, + // Define hasData function for non-cartesian series. + // Returns true if the series has points at all. + hasData: function () { + return !!this.processedXData.length; // != 0 + }, + // Override to also allow null points, used when building the k-d-tree + // for tooltips in boost mode. + getValidPoints: function (points, insideOnly) { + return Series.prototype.getValidPoints.call(this, points, insideOnly, true); + }, + /** + * @ignore + * @deprecated + * @function Highcharts.seriesTypes.heatmap#getBox + */ + getBox: noop, + /** + * @private + * @borrows Highcharts.LegendSymbolMixin.drawRectangle as Highcharts.seriesTypes.heatmap#drawLegendSymbol + */ + drawLegendSymbol: LegendSymbolMixin.drawRectangle, + /** + * @private + * @borrows Highcharts.seriesTypes.column#alignDataLabel as Highcharts.seriesTypes.heatmap#alignDataLabel + */ + alignDataLabel: seriesTypes.column.prototype.alignDataLabel, + /** + * @private + * @function Highcharts.seriesTypes.heatmap#getExtremes + * @return {void} + */ + getExtremes: function () { + // Get the extremes from the value data + var _a = Series.prototype.getExtremes + .call(this, this.valueData), dataMin = _a.dataMin, dataMax = _a.dataMax; + if (isNumber(dataMin)) { + this.valueMin = dataMin; + } + if (isNumber(dataMax)) { + this.valueMax = dataMax; + } + // Get the extremes from the y data + return Series.prototype.getExtremes.call(this); + } + /* eslint-enable valid-jsdoc */ + }), merge(colorMapPointMixin, { + /** + * Heatmap series only. Padding between the points in the heatmap. + * @name Highcharts.Point#pointPadding + * @type {number|undefined} + */ + /** + * Heatmap series only. The value of the point, resulting in a color + * controled by options as set in the colorAxis configuration. + * @name Highcharts.Point#value + * @type {number|null|undefined} + */ + /* eslint-disable valid-jsdoc */ + /** + * @private + * @function Highcharts.Point#applyOptions + * @param {Highcharts.HeatmapPointOptions} options + * @param {number} x + * @return {Highcharts.SVGPathArray} + */ + applyOptions: function (options, x) { + var point = H.Point.prototype + .applyOptions.call(this, options, x); + point.formatPrefix = + point.isNull || point.value === null ? + 'null' : 'point'; + return point; + }, + /** + * Color points have a value option that determines whether or not it is + * a null point + * @private + * @function Highcharts.HeatmapPoint.isValid + * @return {boolean} + */ + isValid: function () { + // undefined is allowed + return (this.value !== Infinity && + this.value !== -Infinity); + }, + /** + * @private + * @function Highcharts.Point#haloPath + * @param {number} size + * @return {Highcharts.SVGPathArray} + */ + haloPath: function (size) { + if (!size) { + return []; + } + var rect = this.shapeArgs; + return [ + 'M', + rect.x - size, + rect.y - size, + 'L', + rect.x - size, + rect.y + rect.height + size, + rect.x + rect.width + size, + rect.y + rect.height + size, + rect.x + rect.width + size, + rect.y - size, + 'Z' + ]; + }, + getCellAttributes: function () { + var point = this, series = point.series, seriesOptions = series.options, xPad = (seriesOptions.colsize || 1) / 2, yPad = (seriesOptions.rowsize || 1) / 2, xAxis = series.xAxis, yAxis = series.yAxis, markerOptions = point.options.marker || series.options.marker, pointPlacement = series.pointPlacementToXValue(), // #7860 + pointPadding = pick(point.pointPadding, seriesOptions.pointPadding, 0), cellAttr = { + x1: clamp(Math.round(xAxis.len - + (xAxis.translate(point.x - xPad, false, true, false, true, -pointPlacement) || 0)), -xAxis.len, 2 * xAxis.len), + x2: clamp(Math.round(xAxis.len - + (xAxis.translate(point.x + xPad, false, true, false, true, -pointPlacement) || 0)), -xAxis.len, 2 * xAxis.len), + y1: clamp(Math.round((yAxis.translate(point.y - yPad, false, true, false, true) || 0)), -yAxis.len, 2 * yAxis.len), + y2: clamp(Math.round((yAxis.translate(point.y + yPad, false, true, false, true) || 0)), -yAxis.len, 2 * yAxis.len) + }; + // Handle marker's fixed width, and height values including border + // and pointPadding while calculating cell attributes. + [['width', 'x'], ['height', 'y']].forEach(function (dimension) { + var prop = dimension[0], direction = dimension[1]; + var start = direction + '1', end = direction + '2'; + var side = Math.abs(cellAttr[start] - cellAttr[end]), borderWidth = markerOptions && + markerOptions.lineWidth || 0, plotPos = Math.abs(cellAttr[start] + cellAttr[end]) / 2; + if (markerOptions[prop] && + markerOptions[prop] < side) { + cellAttr[start] = plotPos - (markerOptions[prop] / 2) - + (borderWidth / 2); + cellAttr[end] = plotPos + (markerOptions[prop] / 2) + + (borderWidth / 2); + } + // Handle pointPadding + if (pointPadding) { + if (direction === 'y') { + start = end; + end = direction + '1'; + } + cellAttr[start] += pointPadding; + cellAttr[end] -= pointPadding; + } + }); + return cellAttr; + } + /* eslint-enable valid-jsdoc */ + })); + /** + * A `heatmap` series. If the [type](#series.heatmap.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @productdesc {highcharts} + * Requires `modules/heatmap`. + * + * @extends series,plotOptions.heatmap + * @excluding dataParser, dataURL, pointRange, stack, + * @product highcharts highmaps + * @apioption series.heatmap + */ + /** + * An array of data points for the series. For the `heatmap` series + * type, points can be given in the following ways: + * + * 1. An array of arrays with 3 or 2 values. In this case, the values + * correspond to `x,y,value`. If the first value is a string, it is + * applied as the name of the point, and the `x` value is inferred. + * The `x` value can also be omitted, in which case the inner arrays + * should be of length 2\. Then the `x` value is automatically calculated, + * either starting at 0 and incremented by 1, or from `pointStart` + * and `pointInterval` given in the series options. + * + * ```js + * data: [ + * [0, 9, 7], + * [1, 10, 4], + * [2, 6, 3] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of data + * points exceeds the series' [turboThreshold](#series.heatmap.turboThreshold), + * this option is not available. + * + * ```js + * data: [{ + * x: 1, + * y: 3, + * value: 10, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 7, + * value: 10, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|*>} + * @extends series.line.data + * @product highcharts highmaps + * @apioption series.heatmap.data + */ + /** + * The color of the point. In heat maps the point color is rarely set + * explicitly, as we use the color to denote the `value`. Options for + * this are set in the [colorAxis](#colorAxis) configuration. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highmaps + * @apioption series.heatmap.data.color + */ + /** + * The value of the point, resulting in a color controled by options + * as set in the [colorAxis](#colorAxis) configuration. + * + * @type {number} + * @product highcharts highmaps + * @apioption series.heatmap.data.value + */ + /** + * The x value of the point. For datetime axes, + * the X value is the timestamp in milliseconds since 1970. + * + * @type {number} + * @product highcharts highmaps + * @apioption series.heatmap.data.x + */ + /** + * The y value of the point. + * + * @type {number} + * @product highcharts highmaps + * @apioption series.heatmap.data.y + */ + /** + * Point padding for a single point. + * + * @sample maps/plotoptions/tilemap-pointpadding + * Point padding on tiles + * + * @type {number} + * @product highcharts highmaps + * @apioption series.heatmap.data.pointPadding + */ + /** + * @excluding radius, enabledThreshold + * @product highcharts highmaps + * @apioption series.heatmap.data.marker + */ + /** + * @excluding radius, enabledThreshold + * @product highcharts highmaps + * @apioption series.heatmap.marker + */ + /** + * @excluding radius, radiusPlus + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.hover + */ + /** + * @excluding radius + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.select + */ + /** + * @excluding radius, radiusPlus + * @product highcharts highmaps + * @apioption series.heatmap.data.marker.states.hover + */ + /** + * @excluding radius + * @product highcharts highmaps + * @apioption series.heatmap.data.marker.states.select + */ + /** + * Set the marker's fixed width on hover state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-linewidthplus + * 5 pixels wider lineWidth on hover + * + * @type {number|undefined} + * @default 0 + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.hover.lineWidthPlus + */ + /** + * Set the marker's fixed width on hover state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.hover.width + */ + /** + * Set the marker's fixed height on hover state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.hover.height + */ + /** + * The number of pixels to increase the width of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.hover.widthPlus + */ + /** + * The number of pixels to increase the height of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.hover.heightPlus + */ + /** + * The number of pixels to increase the width of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.select.widthPlus + */ + /** + * The number of pixels to increase the height of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.marker.states.select.heightPlus + */ + /** + * Set the marker's fixed width on hover state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-linewidthplus + * 5 pixels wider lineWidth on hover + * + * @type {number|undefined} + * @default 0 + * @product highcharts highmaps + * @apioption series.heatmap.data.marker.states.hover.lineWidthPlus + */ + /** + * Set the marker's fixed width on hover state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.data.marker.states.hover.width + */ + /** + * Set the marker's fixed height on hover state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.data.marker.states.hover.height + */ + /** + * The number of pixels to increase the width of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highstock + * @apioption series.heatmap.data.marker.states.hover.widthPlus + */ + /** + * The number of pixels to increase the height of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highstock + * @apioption series.heatmap.data.marker.states.hover.heightPlus + */ + /** + * Set the marker's fixed width on select state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.data.marker.states.select.width + */ + /** + * Set the marker's fixed height on select state. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-width + * 70px fixed marker's width and height on hover + * + * @type {number|undefined} + * @default undefined + * @product highcharts highmaps + * @apioption series.heatmap.data.marker.states.select.height + */ + /** + * The number of pixels to increase the width of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highstock + * @apioption series.heatmap.data.marker.states.select.widthPlus + */ + /** + * The number of pixels to increase the height of the + * hovered point. + * + * @sample {highcharts} maps/plotoptions/heatmap-marker-states-hover-widthplus + * One day + * + * @type {number|undefined} + * @default undefined + * @product highcharts highstock + * @apioption series.heatmap.data.marker.states.select.heightPlus + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'masters/modules/heatmap.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/histogram-bellcurve.js b/librerias/gantt/code/modules/histogram-bellcurve.js new file mode 100644 index 0000000..7cac753 --- /dev/null +++ b/librerias/gantt/code/modules/histogram-bellcurve.js @@ -0,0 +1,18 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2010-2019 Highsoft AS + Author: Sebastian Domas + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/histogram-bellcurve",["highcharts"],function(c){a(c);a.Highcharts=c;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function c(f,a,d,c){f.hasOwnProperty(a)||(f[a]=c.apply(null,d))}a=a?a._modules:{};c(a,"mixins/derived-series.js",[a["parts/Globals.js"],a["parts/Utilities.js"]],function(a,c){var f=c.addEvent,p=c.defined, +l=a.Series;return{hasDerivedData:!0,init:function(){l.prototype.init.apply(this,arguments);this.initialised=!1;this.baseSeries=null;this.eventRemovers=[];this.addEvents()},setDerivedData:a.noop,setBaseSeries:function(){var b=this.chart,a=this.options.baseSeries;this.baseSeries=p(a)&&(b.series[a]||b.get(a))||null},addEvents:function(){var b=this;var a=f(this.chart,"afterLinkSeries",function(){b.setBaseSeries();b.baseSeries&&!b.initialised&&(b.setDerivedData(),b.addBaseSeriesEvents(),b.initialised= +!0)});this.eventRemovers.push(a)},addBaseSeriesEvents:function(){var a=this;var c=f(a.baseSeries,"updatedData",function(){a.setDerivedData()});var d=f(a.baseSeries,"destroy",function(){a.baseSeries=null;a.initialised=!1});a.eventRemovers.push(c,d)},destroy:function(){this.eventRemovers.forEach(function(a){a()});l.prototype.destroy.apply(this,arguments)}}});c(a,"modules/histogram.src.js",[a["parts/Utilities.js"],a["mixins/derived-series.js"]],function(a,c){function f(a){return function(h){for(var b= +1;a[b]<=h;)b++;return a[--b]}}var p=a.arrayMax,l=a.arrayMin,b=a.correctFloat,m=a.isNumber,k=a.merge,r=a.objectEach;a=a.seriesType;var g={"square-root":function(a){return Math.ceil(Math.sqrt(a.options.data.length))},sturges:function(a){return Math.ceil(Math.log(a.options.data.length)*Math.LOG2E)},rice:function(a){return Math.ceil(2*Math.pow(a.options.data.length,1/3))}};a("histogram","column",{binsNumber:"square-root",binWidth:void 0,pointPadding:0,groupPadding:0,grouping:!1,pointPlacement:"between", +tooltip:{headerFormat:"",pointFormat:'{point.x} - {point.x2}
    \u25cf {series.name} {point.y}
    '}},k(c,{setDerivedData:function(){var a=this.baseSeries.yData;a.length&&(a=this.derivedData(a,this.binsNumber(),this.options.binWidth),this.setData(a,!1))},derivedData:function(a,e,c){var h=p(a),g=b(l(a)),n=[],d={},k=[];c=this.binWidth=this.options.pointRange=b(m(c)?c||1:(h-g)/e);for(e=g;e=c||0>=b(b(g+n.length*c)-e));e=b(e+c))n.push(e),d[e]=0;0!==d[g]&&(n.push(b(g)),d[b(g)]=0);var q=f(n.map(function(a){return parseFloat(a)}));a.forEach(function(a){a=b(q(a));d[a]++});r(d,function(a,h){k.push({x:Number(h),y:a,x2:b(Number(h)+c)})});k.sort(function(a,h){return a.x-h.x});return k},binsNumber:function(){var a=this.options.binsNumber,b=g[a]||"function"===typeof a&&a;return Math.ceil(b&&b(this.baseSeries)||(m(a)?a:g["square-root"](this.baseSeries)))}}));""});c(a,"modules/bellcurve.src.js", +[a["parts/Utilities.js"],a["mixins/derived-series.js"]],function(a,c){function d(a){var b=a.length;a=a.reduce(function(a,b){return a+b},0);return 0} + * An array of data + */ + setDerivedData: noop, + /** + * Sets base series for the series + * + * @private + * @function derivedSeriesMixin.setBaseSeries + * @return {void} + */ + setBaseSeries: function () { + var chart = this.chart, baseSeriesOptions = this.options.baseSeries, baseSeries = (defined(baseSeriesOptions) && + (chart.series[baseSeriesOptions] || + chart.get(baseSeriesOptions))); + this.baseSeries = baseSeries || null; + }, + /** + * Adds events for the series + * + * @private + * @function derivedSeriesMixin.addEvents + * @return {void} + */ + addEvents: function () { + var derivedSeries = this, chartSeriesLinked; + chartSeriesLinked = addEvent(this.chart, 'afterLinkSeries', function () { + derivedSeries.setBaseSeries(); + if (derivedSeries.baseSeries && !derivedSeries.initialised) { + derivedSeries.setDerivedData(); + derivedSeries.addBaseSeriesEvents(); + derivedSeries.initialised = true; + } + }); + this.eventRemovers.push(chartSeriesLinked); + }, + /** + * Adds events to the base series - it required for recalculating the data + * in the series if the base series is updated / removed / etc. + * + * @private + * @function derivedSeriesMixin.addBaseSeriesEvents + * @return {void} + */ + addBaseSeriesEvents: function () { + var derivedSeries = this, updatedDataRemover, destroyRemover; + updatedDataRemover = addEvent(derivedSeries.baseSeries, 'updatedData', function () { + derivedSeries.setDerivedData(); + }); + destroyRemover = addEvent(derivedSeries.baseSeries, 'destroy', function () { + derivedSeries.baseSeries = null; + derivedSeries.initialised = false; + }); + derivedSeries.eventRemovers.push(updatedDataRemover, destroyRemover); + }, + /** + * Destroys the series + * + * @private + * @function derivedSeriesMixin.destroy + */ + destroy: function () { + this.eventRemovers.forEach(function (remover) { + remover(); + }); + Series.prototype.destroy.apply(this, arguments); + } + /* eslint-disable valid-jsdoc */ + }; + + return derivedSeriesMixin; + }); + _registerModule(_modules, 'modules/histogram.src.js', [_modules['parts/Utilities.js'], _modules['mixins/derived-series.js']], function (U, derivedSeriesMixin) { + /* * + * + * Copyright (c) 2010-2017 Highsoft AS + * Author: Sebastian Domas + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var arrayMax = U.arrayMax, arrayMin = U.arrayMin, correctFloat = U.correctFloat, isNumber = U.isNumber, merge = U.merge, objectEach = U.objectEach, seriesType = U.seriesType; + /* ************************************************************************** * + * HISTOGRAM + * ************************************************************************** */ + /** + * A dictionary with formulas for calculating number of bins based on the + * base series + **/ + var binsNumberFormulas = { + 'square-root': function (baseSeries) { + return Math.ceil(Math.sqrt(baseSeries.options.data.length)); + }, + 'sturges': function (baseSeries) { + return Math.ceil(Math.log(baseSeries.options.data.length) * Math.LOG2E); + }, + 'rice': function (baseSeries) { + return Math.ceil(2 * Math.pow(baseSeries.options.data.length, 1 / 3)); + } + }; + /** + * Returns a function for mapping number to the closed (right opened) bins + * @private + * @param {Array} bins - Width of the bins + * @return {Function} + **/ + function fitToBinLeftClosed(bins) { + return function (y) { + var i = 1; + while (bins[i] <= y) { + i++; + } + return bins[--i]; + }; + } + /** + * Histogram class + * @private + * @class + * @name Highcharts.seriesTypes.histogram + * @augments Highcharts.Series + */ + seriesType('histogram', 'column', + /** + * A histogram is a column series which represents the distribution of the + * data set in the base series. Histogram splits data into bins and shows + * their frequencies. + * + * @sample {highcharts} highcharts/demo/histogram/ + * Histogram + * + * @extends plotOptions.column + * @excluding boostThreshold, dragDrop, pointInterval, pointIntervalUnit, + * stacking + * @product highcharts + * @since 6.0.0 + * @requires modules/histogram + * @optionparent plotOptions.histogram + */ + { + /** + * A preferable number of bins. It is a suggestion, so a histogram may + * have a different number of bins. By default it is set to the square + * root of the base series' data length. Available options are: + * `square-root`, `sturges`, `rice`. You can also define a function + * which takes a `baseSeries` as a parameter and should return a + * positive integer. + * + * @type {"square-root"|"sturges"|"rice"|number|function} + */ + binsNumber: 'square-root', + /** + * Width of each bin. By default the bin's width is calculated as + * `(max - min) / number of bins`. This option takes precedence over + * [binsNumber](#plotOptions.histogram.binsNumber). + * + * @type {number} + */ + binWidth: void 0, + pointPadding: 0, + groupPadding: 0, + grouping: false, + pointPlacement: 'between', + tooltip: { + headerFormat: '', + pointFormat: ('{point.x} - {point.x2}' + + '
    ' + + '\u25CF' + + ' {series.name} {point.y}
    ') + } + }, merge(derivedSeriesMixin, { + setDerivedData: function () { + var yData = this.baseSeries.yData; + if (!yData.length) { + return; + } + var data = this.derivedData(yData, this.binsNumber(), this.options.binWidth); + this.setData(data, false); + }, + derivedData: function (baseData, binsNumber, binWidth) { + var series = this, max = arrayMax(baseData), + // Float correction needed, because first frequency value is not + // corrected when generating frequencies (within for loop). + min = correctFloat(arrayMin(baseData)), frequencies = [], bins = {}, data = [], x, fitToBin; + binWidth = series.binWidth = series.options.pointRange = (correctFloat(isNumber(binWidth) ? + (binWidth || 1) : + (max - min) / binsNumber)); + // If binWidth is 0 then max and min are equaled, + // increment the x with some positive value to quit the loop + for (x = min; + // This condition is needed because of the margin of error while + // operating on decimal numbers. Without that, additional bin + // was sometimes noticeable on the graph, because of too small + // precision of float correction. + x < max && + (series.userOptions.binWidth || + correctFloat(max - x) >= binWidth || + // #13069 - Every add and subtract operation should + // be corrected, due to general problems with + // operations on float numbers in JS. + correctFloat(correctFloat(min + (frequencies.length * binWidth)) - + x) <= 0); x = correctFloat(x + binWidth)) { + frequencies.push(x); + bins[x] = 0; + } + if (bins[min] !== 0) { + frequencies.push(correctFloat(min)); + bins[correctFloat(min)] = 0; + } + fitToBin = fitToBinLeftClosed(frequencies.map(function (elem) { + return parseFloat(elem); + })); + baseData.forEach(function (y) { + var x = correctFloat(fitToBin(y)); + bins[x]++; + }); + objectEach(bins, function (frequency, x) { + data.push({ + x: Number(x), + y: frequency, + x2: correctFloat(Number(x) + binWidth) + }); + }); + data.sort(function (a, b) { + return a.x - b.x; + }); + return data; + }, + binsNumber: function () { + var binsNumberOption = this.options.binsNumber; + var binsNumber = binsNumberFormulas[binsNumberOption] || + // #7457 + (typeof binsNumberOption === 'function' && binsNumberOption); + return Math.ceil((binsNumber && binsNumber(this.baseSeries)) || + (isNumber(binsNumberOption) ? + binsNumberOption : + binsNumberFormulas['square-root'](this.baseSeries))); + } + })); + /** + * A `histogram` series. If the [type](#series.histogram.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.histogram + * @excluding data, dataParser, dataURL + * @product highcharts + * @since 6.0.0 + * @requires modules/histogram + * @apioption series.histogram + */ + /** + * An integer identifying the index to use for the base series, or a string + * representing the id of the series. + * + * @type {number|string} + * @apioption series.histogram.baseSeries + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'modules/bellcurve.src.js', [_modules['parts/Utilities.js'], _modules['mixins/derived-series.js']], function (U, derivedSeriesMixin) { + /* * + * + * (c) 2010-2020 Highsoft AS + * + * Author: Sebastian Domas + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var correctFloat = U.correctFloat, isNumber = U.isNumber, merge = U.merge, seriesType = U.seriesType; + /* ************************************************************************** * + * BELL CURVE * + * ************************************************************************** */ + /* eslint-disable valid-jsdoc */ + /** + * @private + */ + function mean(data) { + var length = data.length, sum = data.reduce(function (sum, value) { + return (sum += value); + }, 0); + return length > 0 && sum / length; + } + /** + * @private + */ + function standardDeviation(data, average) { + var len = data.length, sum; + average = isNumber(average) ? average : mean(data); + sum = data.reduce(function (sum, value) { + var diff = value - average; + return (sum += diff * diff); + }, 0); + return len > 1 && Math.sqrt(sum / (len - 1)); + } + /** + * @private + */ + function normalDensity(x, mean, standardDeviation) { + var translation = x - mean; + return Math.exp(-(translation * translation) / + (2 * standardDeviation * standardDeviation)) / (standardDeviation * Math.sqrt(2 * Math.PI)); + } + /* eslint-enable valid-jsdoc */ + /** + * Bell curve class + * + * @private + * @class + * @name Highcharts.seriesTypes.bellcurve + * + * @augments Highcharts.Series + */ + seriesType('bellcurve', 'areaspline' + /** + * A bell curve is an areaspline series which represents the probability + * density function of the normal distribution. It calculates mean and + * standard deviation of the base series data and plots the curve according + * to the calculated parameters. + * + * @sample {highcharts} highcharts/demo/bellcurve/ + * Bell curve + * + * @extends plotOptions.areaspline + * @since 6.0.0 + * @product highcharts + * @excluding boostThreshold, connectNulls, dragDrop, stacking, + * pointInterval, pointIntervalUnit + * @requires modules/bellcurve + * @optionparent plotOptions.bellcurve + */ + , { + /** + * This option allows to define the length of the bell curve. A unit of + * the length of the bell curve is standard deviation. + * + * @sample highcharts/plotoptions/bellcurve-intervals-pointsininterval + * Intervals and points in interval + */ + intervals: 3, + /** + * Defines how many points should be plotted within 1 interval. See + * `plotOptions.bellcurve.intervals`. + * + * @sample highcharts/plotoptions/bellcurve-intervals-pointsininterval + * Intervals and points in interval + */ + pointsInInterval: 3, + marker: { + enabled: false + } + }, merge(derivedSeriesMixin, { + setMean: function () { + this.mean = correctFloat(mean(this.baseSeries.yData)); + }, + setStandardDeviation: function () { + this.standardDeviation = correctFloat(standardDeviation(this.baseSeries.yData, this.mean)); + }, + setDerivedData: function () { + if (this.baseSeries.yData.length > 1) { + this.setMean(); + this.setStandardDeviation(); + this.setData(this.derivedData(this.mean, this.standardDeviation), false); + } + return (void 0); + }, + derivedData: function (mean, standardDeviation) { + var intervals = this.options.intervals, pointsInInterval = this.options.pointsInInterval, x = mean - intervals * standardDeviation, stop = intervals * pointsInInterval * 2 + 1, increment = standardDeviation / pointsInInterval, data = [], i; + for (i = 0; i < stop; i++) { + data.push([x, normalDensity(x, mean, standardDeviation)]); + x += increment; + } + return data; + } + })); + /** + * A `bellcurve` series. If the [type](#series.bellcurve.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * For options that apply to multiple series, it is recommended to add + * them to the [plotOptions.series](#plotOptions.series) options structure. + * To apply to all series of this specific type, apply it to + * [plotOptions.bellcurve](#plotOptions.bellcurve). + * + * @extends series,plotOptions.bellcurve + * @since 6.0.0 + * @product highcharts + * @excluding dataParser, dataURL, data + * @requires modules/bellcurve + * @apioption series.bellcurve + */ + /** + * An integer identifying the index to use for the base series, or a string + * representing the id of the series. + * + * @type {number|string} + * @apioption series.bellcurve.baseSeries + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'masters/modules/histogram-bellcurve.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/item-series.js b/librerias/gantt/code/modules/item-series.js new file mode 100644 index 0000000..84b83ba --- /dev/null +++ b/librerias/gantt/code/modules/item-series.js @@ -0,0 +1,18 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Item series type for Highcharts + + (c) 2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/item-series",["highcharts"],function(d){b(d);b.Highcharts=d;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function d(b,c,d,D){b.hasOwnProperty(c)||(b[c]=D.apply(null,d))}b=b?b._modules:{};d(b,"modules/item-series.src.js",[b["parts/Globals.js"],b["parts/Utilities.js"]],function(b,c){var d=c.defined,D=c.extend,E=c.fireEvent, +B=c.isNumber,F=c.merge,G=c.objectEach,H=c.pick;c=c.seriesType;var m=b.seriesTypes.pie.prototype.pointClass.prototype;c("item","pie",{endAngle:void 0,innerSize:"40%",itemPadding:.1,layout:"vertical",marker:F(b.defaultOptions.plotOptions.line.marker,{radius:null}),rows:void 0,crisp:!1,showInLegend:!0,startAngle:void 0},{markerAttribs:void 0,translate:function(){this.slots||(this.slots=[]);B(this.options.startAngle)&&B(this.options.endAngle)?(b.seriesTypes.pie.prototype.translate.call(this),this.slots= +this.getSlots()):(this.generatePoints(),E(this,"afterTranslate"))},getSlots:function(){function a(a){0this.total;)for(A=q,q=n.length=0,l=h,h=[],g++,p=c/g/2,f?(d=(p-f)/p*c,0<=d?p=f:(d=0,m=1)):p=Math.floor(p*m),r=p;0b)break;a--}else for(a=Math.floor(a);a this.total) { + finalItemCount = itemCount; + // Reset + slots.length = 0; + itemCount = 0; + // Now rows is the last successful run + rows = testRows; + testRows = []; + itemSize++; + // Total number of rows (arcs) from the center to the + // perimeter + rowCount = diameter / itemSize / 2; + if (rowsOption) { + innerSize = ((rowCount - rowsOption) / rowCount) * diameter; + if (innerSize >= 0) { + rowCount = rowsOption; + // If innerSize is negative, we are trying to set too + // many rows in the rows option, so fall back to + // treating it as innerSize 0 + } + else { + innerSize = 0; + rowFraction = 1; + } + } + else { + rowCount = Math.floor(rowCount * rowFraction); + } + for (row = rowCount; row > 0; row--) { + rowRadius = (innerSize + (row / rowCount) * + (diameter - innerSize - itemSize)) / 2; + rowLength = fullAngle * rowRadius; + colCount = Math.ceil(rowLength / itemSize); + testRows.push({ + rowRadius: rowRadius, + rowLength: rowLength, + colCount: colCount + }); + itemCount += colCount + 1; + } + } + if (!rows) { + return; + } + // We now have more slots than we have total items. Loop over + // the rows and remove the last slot until the count is correct. + // For each iteration we sort the last slot by the angle, and + // remove those with the highest angles. + var overshoot = finalItemCount - this.total; + /** + * @private + * @param {Highcharts.ItemRowContainerObject} item + * Wrapped object with angle and row + * @return {void} + */ + function cutOffRow(item) { + if (overshoot > 0) { + item.row.colCount--; + overshoot--; + } + } + while (overshoot > 0) { + rows + // Return a simplified representation of the angle of + // the last slot within each row. + .map(function (row) { + return { + angle: row.colCount / row.rowLength, + row: row + }; + }) + // Sort by the angles... + .sort(function (a, b) { + return b.angle - a.angle; + }) + // ...so that we can ignore the items with the lowest + // angles... + .slice(0, Math.min(overshoot, Math.ceil(rows.length / 2))) + // ...and remove the ones with the highest angles + .forEach(cutOffRow); + } + rows.forEach(function (row) { + var rowRadius = row.rowRadius, colCount = row.colCount; + increment = colCount ? fullAngle / colCount : 0; + for (col = 0; col <= colCount; col += 1) { + angle = this.startAngleRad + col * increment; + x = center[0] + Math.cos(angle) * rowRadius; + y = center[1] + Math.sin(angle) * rowRadius; + slots.push({ x: x, y: y, angle: angle }); + } + }, this); + // Sort by angle + slots.sort(function (a, b) { + return a.angle - b.angle; + }); + this.itemSize = itemSize; + return slots; + }, + getRows: function () { + var rows = this.options.rows, cols, ratio; + // Get the row count that gives the most square cells + if (!rows) { + ratio = this.chart.plotWidth / this.chart.plotHeight; + rows = Math.sqrt(this.total); + if (ratio > 1) { + rows = Math.ceil(rows); + while (rows > 0) { + cols = this.total / rows; + if (cols / rows > ratio) { + break; + } + rows--; + } + } + else { + rows = Math.floor(rows); + while (rows < this.total) { + cols = this.total / rows; + if (cols / rows < ratio) { + break; + } + rows++; + } + } + } + return rows; + }, + drawPoints: function () { + var series = this, options = this.options, renderer = series.chart.renderer, seriesMarkerOptions = options.marker, borderWidth = this.borderWidth, crisp = borderWidth % 2 ? 0.5 : 1, i = 0, rows = this.getRows(), cols = Math.ceil(this.total / rows), cellWidth = this.chart.plotWidth / cols, cellHeight = this.chart.plotHeight / rows, itemSize = this.itemSize || Math.min(cellWidth, cellHeight); + /* + this.slots.forEach(slot => { + this.chart.renderer.circle(slot.x, slot.y, 6) + .attr({ + fill: 'silver' + }) + .add(this.group); + }); + //*/ + this.points.forEach(function (point) { + var attr, graphics, pointAttr, pointMarkerOptions = point.marker || {}, symbol = (pointMarkerOptions.symbol || + seriesMarkerOptions.symbol), r = pick(pointMarkerOptions.radius, seriesMarkerOptions.radius), size = defined(r) ? 2 * r : itemSize, padding = size * options.itemPadding, x, y, width, height; + point.graphics = graphics = point.graphics || {}; + if (!series.chart.styledMode) { + pointAttr = series.pointAttribs(point, point.selected && 'select'); + } + if (!point.isNull && point.visible) { + if (!point.graphic) { + point.graphic = renderer.g('point') + .add(series.group); + } + for (var val = 0; val < point.y; val++) { + // Semi-circle + if (series.center && series.slots) { + // Fill up the slots from left to right + var slot = series.slots.shift(); + x = slot.x - itemSize / 2; + y = slot.y - itemSize / 2; + } + else if (options.layout === 'horizontal') { + x = cellWidth * (i % cols); + y = cellHeight * Math.floor(i / cols); + } + else { + x = cellWidth * Math.floor(i / rows); + y = cellHeight * (i % rows); + } + x += padding; + y += padding; + width = Math.round(size - 2 * padding); + height = width; + if (series.options.crisp) { + x = Math.round(x) - crisp; + y = Math.round(y) + crisp; + } + attr = { + x: x, + y: y, + width: width, + height: height + }; + if (typeof r !== 'undefined') { + attr.r = r; + } + if (graphics[val]) { + graphics[val].animate(attr); + } + else { + graphics[val] = renderer + .symbol(symbol, null, null, null, null, { + backgroundSize: 'within' + }) + .attr(extend(attr, pointAttr)) + .add(point.graphic); + } + graphics[val].isActive = true; + i++; + } + } + objectEach(graphics, function (graphic, key) { + if (!graphic.isActive) { + graphic.destroy(); + delete graphics[key]; + } + else { + graphic.isActive = false; + } + }); + }); + }, + drawDataLabels: function () { + if (this.center && this.slots) { + H.seriesTypes.pie.prototype.drawDataLabels.call(this); + // else, it's just a dot chart with no natural place to put the + // data labels + } + else { + this.points.forEach(function (point) { + point.destroyElements({ dataLabel: 1 }); + }); + } + }, + // Fade in the whole chart + animate: function (init) { + if (init) { + this.group.attr({ + opacity: 0 + }); + } + else { + this.group.animate({ + opacity: 1 + }, this.options.animation); + } + } + }, + // Point class + { + connectorShapes: piePoint.connectorShapes, + getConnectorPath: piePoint.getConnectorPath, + setVisible: piePoint.setVisible, + getTranslate: piePoint.getTranslate + }); + /** + * An `item` series. If the [type](#series.item.type) option is not specified, + * it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.item + * @excluding dataParser, dataURL, stack, xAxis, yAxis, dataSorting + * @product highcharts + * @requires modules/item-series + * @apioption series.item + */ + /** + * An array of data points for the series. For the `item` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.item.turboThreshold), + * this option is not available. + * ```js + * data: [{ + * y: 1, + * name: "Point2", + * color: "#00FF00" + * }, { + * y: 7, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.pie.data + * @excludes sliced + * @product highcharts + * @apioption series.item.data + */ + /** + * The sequential index of the data point in the legend. + * + * @type {number} + * @product highcharts + * @apioption series.pie.data.legendIndex + */ + ''; // adds the doclets above to the transpiled file + + }); + _registerModule(_modules, 'masters/modules/item-series.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/lollipop.js b/librerias/gantt/code/modules/lollipop.js new file mode 100644 index 0000000..0af67a7 --- /dev/null +++ b/librerias/gantt/code/modules/lollipop.js @@ -0,0 +1,11 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2009-2019 Sebastian Bochan, Rafal Sebestjanski + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/lollipop",["highcharts"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,e,b,c){a.hasOwnProperty(e)||(a[e]=c.apply(null,b))}a=a?a._modules:{};b(a,"modules/lollipop.src.js",[a["parts/Globals.js"],a["parts/Utilities.js"]],function(a,b){b=b.seriesType;var d=a.seriesTypes.area.prototype, +c=a.seriesTypes.column.prototype;b("lollipop","dumbbell",{lowColor:void 0,threshold:0,connectorWidth:1,groupPadding:.2,pointPadding:.1,states:{hover:{lineWidthPlus:0,connectorWidthPlus:1,halo:!1}},tooltip:{pointFormat:'\u25cf {series.name}: {point.low}
    '}},{translatePoint:d.translate,drawPoint:d.drawPoints,drawDataLabels:c.drawDataLabels,setShapeArgs:c.translate},{pointSetState:d.pointClass.prototype.setState,setState:a.seriesTypes.dumbbell.prototype.pointClass.prototype.setState}); +""});b(a,"masters/modules/lollipop.src.js",[],function(){})}); +//# sourceMappingURL=lollipop.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/lollipop.js.map b/librerias/gantt/code/modules/lollipop.js.map new file mode 100644 index 0000000..8f98a49 --- /dev/null +++ b/librerias/gantt/code/modules/lollipop.js.map @@ -0,0 +1 @@ +{"version":3,"file":"lollipop.js.map","lineCount":10,"mappings":"A;;;;;;;AAQC,SAAS,CAACA,CAAD,CAAU,CACM,QAAtB,GAAI,MAAOC,OAAX,EAAkCA,MAAAC,QAAlC,EACIF,CAAA,CAAQ,SAAR,CACA,CADqBA,CACrB,CAAAC,MAAAC,QAAA,CAAiBF,CAFrB,EAG6B,UAAtB,GAAI,MAAOG,OAAX,EAAoCA,MAAAC,IAApC,CACHD,MAAA,CAAO,6BAAP,CAAsC,CAAC,YAAD,CAAtC,CAAsD,QAAS,CAACE,CAAD,CAAa,CACxEL,CAAA,CAAQK,CAAR,CACAL,EAAAK,WAAA,CAAqBA,CACrB,OAAOL,EAHiE,CAA5E,CADG,CAOHA,CAAA,CAA8B,WAAtB,GAAA,MAAOK,WAAP,CAAoCA,UAApC,CAAiDC,IAAAA,EAAzD,CAXY,CAAnB,CAAA,CAaC,QAAS,CAACD,CAAD,CAAa,CAEpBE,QAASA,EAAe,CAACC,CAAD,CAAMC,CAAN,CAAYC,CAAZ,CAAkBC,CAAlB,CAAsB,CACrCH,CAAAI,eAAA,CAAmBH,CAAnB,CAAL,GACID,CAAA,CAAIC,CAAJ,CADJ,CACgBE,CAAAE,MAAA,CAAS,IAAT,CAAeH,CAAf,CADhB,CAD0C,CAD1CI,CAAAA,CAAWT,CAAA,CAAaA,CAAAS,SAAb,CAAmC,EAMlDP,EAAA,CAAgBO,CAAhB,CAA0B,yBAA1B,CAAqD,CAACA,CAAA,CAAS,kBAAT,CAAD,CAA+BA,CAAA,CAAS,oBAAT,CAA/B,CAArD,CAAqH,QAAS,CAACC,CAAD,CAAIC,CAAJ,CAAO,CAU7HC,CAAAA,CAAaD,CAAAC,WAVgH,KAW7HC,EAAYH,CAAAI,YAAAC,KAAAC,UAXiH;AAWnFC,EAAWP,CAAAI,YAAAI,OAAAF,UAmBzDJ,EAAA,CAAW,UAAX,CAAuB,UAAvB,CAAmC,CAE/BO,SAAU,IAAK,EAFgB,CAI/BC,UAAW,CAJoB,CAM/BC,eAAgB,CANe,CAQ/BC,aAAc,EARiB,CAU/BC,aAAc,EAViB,CAY/BC,OAAQ,CACJC,MAAO,CAEHC,cAAe,CAFZ,CAIHC,mBAAoB,CAJjB,CAMHC,KAAM,CAAA,CANH,CADH,CAZuB,CAsB/BC,QAAS,CACLC,YAAa,yFADR,CAtBsB,CAAnC,CAyBG,CACCC,eAAgBlB,CAAAmB,UADjB,CAECC,UAAWpB,CAAAqB,WAFZ,CAGCC,eAAgBlB,CAAAkB,eAHjB,CAICC,aAAcnB,CAAAe,UAJf,CAzBH,CA8BG,CACCK,cAAexB,CAAAyB,WAAAtB,UAAAuB,SADhB,CAECA,SAAU7B,CAAAI,YAAA0B,SAAAxB,UAAAsB,WAAAtB,UAAAuB,SAFX,CA9BH,CA2GA;EAzIiI,CAArI,CA4IArC,EAAA,CAAgBO,CAAhB,CAA0B,iCAA1B,CAA6D,EAA7D,CAAiE,QAAS,EAAG,EAA7E,CAnJoB,CAbvB;","sources":["lollipop.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","U","seriesType","areaProto","seriesTypes","area","prototype","colProto","column","lowColor","threshold","connectorWidth","groupPadding","pointPadding","states","hover","lineWidthPlus","connectorWidthPlus","halo","tooltip","pointFormat","translatePoint","translate","drawPoint","drawPoints","drawDataLabels","setShapeArgs","pointSetState","pointClass","setState","dumbbell"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/lollipop.src.js b/librerias/gantt/code/modules/lollipop.src.js new file mode 100644 index 0000000..22a0329 --- /dev/null +++ b/librerias/gantt/code/modules/lollipop.src.js @@ -0,0 +1,173 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * (c) 2009-2019 Sebastian Bochan, Rafal Sebestjanski + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/lollipop', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'modules/lollipop.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Sebastian Bochan, Rafal Sebestjanski + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var seriesType = U.seriesType; + var areaProto = H.seriesTypes.area.prototype, colProto = H.seriesTypes.column.prototype; + /** + * The lollipop series is a carteseian series with a line anchored from + * the x axis and a dot at the end to mark the value. + * Requires `highcharts-more.js`, `modules/dumbbell.js` and + * `modules/lollipop.js`. + * + * @sample {highcharts} highcharts/demo/lollipop/ + * Lollipop chart + * @sample {highcharts} highcharts/series-dumbbell/styled-mode-dumbbell/ + * Styled mode + * + * @extends plotOptions.dumbbell + * @product highcharts highstock + * @excluding fillColor, fillOpacity, lineWidth, stack, stacking, lowColor, + * stickyTracking, trackByArea + * @since 8.0.0 + * @optionparent plotOptions.lollipop + */ + seriesType('lollipop', 'dumbbell', { + /** @ignore-option */ + lowColor: void 0, + /** @ignore-option */ + threshold: 0, + /** @ignore-option */ + connectorWidth: 1, + /** @ignore-option */ + groupPadding: 0.2, + /** @ignore-option */ + pointPadding: 0.1, + /** @ignore-option */ + states: { + hover: { + /** @ignore-option */ + lineWidthPlus: 0, + /** @ignore-option */ + connectorWidthPlus: 1, + /** @ignore-option */ + halo: false + } + }, + tooltip: { + pointFormat: ' {series.name}: {point.low}
    ' + } + }, { + translatePoint: areaProto.translate, + drawPoint: areaProto.drawPoints, + drawDataLabels: colProto.drawDataLabels, + setShapeArgs: colProto.translate + }, { + pointSetState: areaProto.pointClass.prototype.setState, + setState: H.seriesTypes.dumbbell.prototype.pointClass.prototype.setState + }); + /** + * The `lollipop` series. If the [type](#series.lollipop.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.lollipop + * @product highcharts highstock + * @requires highcharts-more + * @requires modules/dumbbell + * @requires modules/lollipop + * @apioption series.lollipop + */ + /** + * An array of data points for the series. For the `lollipop` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 6], + * [1, 2], + * [2, 6] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.lollipop.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 9, + * name: "Point2", + * color: "#00FF00", + * connectorWidth: 3, + * connectorColor: "#FF00FF" + * }, { + * x: 1, + * y: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.dumbbell.data + * @excluding lowColor + * @product highcharts highstock + * @apioption series.lollipop.data + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'masters/modules/lollipop.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/marker-clusters.js b/librerias/gantt/code/modules/marker-clusters.js new file mode 100644 index 0000000..b8c44f1 --- /dev/null +++ b/librerias/gantt/code/modules/marker-clusters.js @@ -0,0 +1,45 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Marker clusters module for Highcharts + + (c) 2010-2019 Wojciech Chmiel + + License: www.highcharts.com/license +*/ +(function(r){"object"===typeof module&&module.exports?(r["default"]=r,module.exports=r):"function"===typeof define&&define.amd?define("highcharts/modules/marker-clusters",["highcharts"],function(x){r(x);r.Highcharts=x;return r}):r("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(r){function x(r,x,v,H){r.hasOwnProperty(x)||(r[x]=H.apply(null,v))}r=r?r._modules:{};x(r,"modules/marker-clusters.src.js",[r["parts/Globals.js"],r["parts/Point.js"],r["parts/Utilities.js"]],function(r,x,v){function H(a){var b= +a.length,d=0,f=0,c;for(c=0;cClustered points: {point.clusterPointsAmount}
    "}});Z.prototype.symbols.cluster=function(a,b,d,f){d/=2;f/=2;var c=this.arc(a+d,b+f,d-4,f-4,{start:.5*Math.PI,end:2.5* +Math.PI,open:!1});var k=this.arc(a+d,b+f,d-3,f-3,{start:.5*Math.PI,end:2.5*Math.PI,innerR:d-2,open:!1});return this.arc(a+d,b+f,d-1,f-1,{start:.5*Math.PI,end:2.5*Math.PI,innerR:d,open:!1}).concat(k,c)};w.prototype.animateClusterPoint=function(a){var b=this.xAxis,d=this.yAxis,f=this.chart,c=S((this.options.cluster||{}).animation),k=c.duration||500,h=(this.markerClusterInfo||{}).pointsState,m=(h||{}).newState,t=(h||{}).oldState,g=[],l=h=0,p=0,q=!1,u=!1;if(t&&m){var e=m[a.stateId];l=b.toPixels(e.x)- +f.plotLeft;p=d.toPixels(e.y)-f.plotTop;if(1===e.parentsId.length){a=(m||{})[a.stateId].parentsId[0];var n=t[a];e.point&&e.point.graphic&&n&&n.point&&n.point.plotX&&n.point.plotY&&n.point.plotX!==e.point.plotX&&n.point.plotY!==e.point.plotY&&(a=e.point.graphic.getBBox(),h=a.width/2,e.point.graphic.attr({x:n.point.plotX-h,y:n.point.plotY-h}),e.point.graphic.animate({x:l-e.point.graphic.radius,y:p-e.point.graphic.radius},c,function(){u=!0;n.point&&n.point.destroy&&n.point.destroy()}),e.point.dataLabel&& +e.point.dataLabel.alignAttr&&n.point.dataLabel&&n.point.dataLabel.alignAttr&&(e.point.dataLabel.attr({x:n.point.dataLabel.alignAttr.x,y:n.point.dataLabel.alignAttr.y}),e.point.dataLabel.animate({x:e.point.dataLabel.alignAttr.x,y:e.point.dataLabel.alignAttr.y},c)))}else 0===e.parentsId.length?(Q(e,!0,!0),F(function(){P(e,.1,c,!0,!0)},k/2)):(Q(e,!0,!0),e.parentsId.forEach(function(a){t&&t[a]&&(n=t[a],g.push(n),n.point&&n.point.graphic&&(q=!0,n.point.graphic.show(),n.point.graphic.animate({x:l-n.point.graphic.radius, +y:p-n.point.graphic.radius,opacity:.4},c,function(){u=!0;K(e,g,c,.7)}),n.point.dataLabel&&-9999!==n.point.dataLabel.y&&e.point&&e.point.dataLabel&&e.point.dataLabel.alignAttr&&(n.point.dataLabel.show(),n.point.dataLabel.animate({x:e.point.dataLabel.alignAttr.x,y:e.point.dataLabel.alignAttr.y,opacity:.4},c))))}),F(function(){u||K(e,g,c,.85)},k),q||F(function(){K(e,g,c,.1)},k/2))}};w.prototype.getGridOffset=function(){var a=this.chart,b=this.xAxis,d=this.yAxis;b=this.dataMinX&&this.dataMaxX?b.reversed? +b.toPixels(this.dataMaxX):b.toPixels(this.dataMinX):a.plotLeft;a=this.dataMinY&&this.dataMaxY?d.reversed?d.toPixels(this.dataMinY):d.toPixels(this.dataMaxY):a.plotTop;return{plotLeft:b,plotTop:a}};w.prototype.getScaledGridSize=function(a){var b=this.xAxis,d=!0,f=1,c=1;a=a.processedGridSize||C.layoutAlgorithm.gridSize;this.gridValueSize||(this.gridValueSize=Math.abs(b.toValue(a)-b.toValue(0)));b=b.toPixels(this.gridValueSize)-b.toPixels(0);for(b=+(a/b).toFixed(14);d&&1!==b;){var k=Math.pow(2,f);.75< +b&&1.25>b?d=!1:b>=1/k&&b<1/k*2?(d=!1,c=k):b<=k&&b>k/2&&(d=!1,c=1/k);f++}return a/c/b};w.prototype.getRealExtremes=function(){var a=this.chart,b=this.xAxis,d=this.yAxis;var f=b?b.toValue(a.plotLeft):0;b=b?b.toValue(a.plotLeft+a.plotWidth):0;var c=d?d.toValue(a.plotTop):0;a=d?d.toValue(a.plotTop+a.plotHeight):0;f>b&&(f=I([f,b],2),b=f[0],f=f[1]);c>a&&(c=I([c,a],2),a=c[0],c=c[1]);return{minX:f,maxX:b,minY:c,maxY:a}};w.prototype.onDrillToCluster=function(a){(a.point||a.target).firePointEvent("drillToCluster", +a,function(a){var b=a.point||a.target,f=b.series.xAxis,c=b.series.yAxis,k=b.series.chart;if((b.series.options.cluster||{}).drillToCluster&&b.clusteredData){var h=b.clusteredData.map(function(a){return a.x}).sort(function(a,b){return a-b});var m=b.clusteredData.map(function(a){return a.y}).sort(function(a,b){return a-b});b=h[0];var t=h[h.length-1];h=m[0];var g=m[m.length-1];m=Math.abs(.1*(t-b));var l=Math.abs(.1*(g-h));k.pointer.zoomX=!0;k.pointer.zoomY=!0;b>t&&(t=I([t,b],2),b=t[0],t=t[1]);h>g&&(g= +I([g,h],2),h=g[0],g=g[1]);k.zoom({originalEvent:a,xAxis:[{axis:f,min:b-m,max:t+m}],yAxis:[{axis:c,min:h-l,max:g+l}]})}})};w.prototype.getClusterDistancesFromPoint=function(a,b,d){var f=this.xAxis,c=this.yAxis,k=[],h;for(h=0;hc[e].oldX+1||c[e].posXc[e].oldY+1||c[e].posYt.minX||this.initMaxY&&this.initMaxYt.minY?(this.initMaxX=t.maxX,this.initMinX=t.minX,this.initMaxY=t.maxY,this.initMinY=t.minY,m=this.markerClusterAlgorithms?this.markerClusterAlgorithms.kmeans.call(this, +a,b,d,f):{},this.baseClusters=null):(this.baseClusters||(this.baseClusters={clusters:this.markerClusterInfo.clusters,noise:this.markerClusterInfo.noise}),this.baseClusters.clusters.forEach(function(a){a.pointsOutside=[];a.pointsInside=[];a.data.forEach(function(b){p=Math.sqrt(Math.pow(c.toPixels(b.x)-c.toPixels(a.x),2)+Math.pow(k.toPixels(b.y)-k.toPixels(a.y),2));q=a.clusterZone&&a.clusterZone.marker&&a.clusterZone.marker.radius?a.clusterZone.marker.radius:g&&g.radius?g.radius:C.marker.radius;l=0<= +h-q?h-q:q;p>q+l&&B(a.pointsOutside)?a.pointsOutside.push(b):B(a.pointsInside)&&a.pointsInside.push(b)});a.pointsInside.length&&(m[a.id]=a.pointsInside);a.pointsOutside.forEach(function(b,f){m[a.id+"_noise"+f]=[b]})}),this.baseClusters.noise.forEach(function(a){m[a.id]=a.data}));return m}};w.prototype.preventClusterCollisions=function(a){var b=this.xAxis,d=this.yAxis,f=I(a.key.split("-").map(parseFloat),2),c=f[0],k=f[1],h=a.gridSize,m=a.groupedData,t=a.defaultRadius,g=a.clusterRadius,l=k*h,p=c*h,q= +b.toPixels(a.x),u=d.toPixels(a.y);f=[];var e=0,n=0,r=(this.options.cluster||{}).marker,J=(this.options.cluster||{}).zones,v=this.getGridOffset(),w,x,z,A,D,F,G;q-=v.plotLeft;u-=v.plotTop;for(z=1;5>z;z++){var E=z%2?-1:1;var y=3>z?-1:1;E=Math.floor((q+E*g)/h);y=Math.floor((u+y*g)/h);E=[y+"-"+E,y+"-"+k,c+"-"+E];for(y=0;y=J[z].from&&e<=J[z].to&&(n=B((J[z].marker||{}).radius)?J[z].marker.radius||0:r&&r.radius?r.radius:C.marker.radius);1A-k?l+g:l+h-g);D!==c&&Math.abs(u-x)D-c?p+g:p+h-g)}});f=b.toValue(q+v.plotLeft);y=d.toValue(u+v.plotTop);m[a.key].posX=f;m[a.key].posY=y; +return{x:f,y:y}};w.prototype.isValidGroupedDataObject=function(a){var b=!1,d;if(!M(a))return!1;R(a,function(a){b=!0;if(U(a)&&a.length)for(d=0;d=t){var p=a[l];var q=Math.random().toString(36).substring(2,7)+"-"+X++;var u=p.length;if(b.zones)for(g=0;g=b.zones[g].from&&u<=b.zones[g].to){var e=b.zones[g];e.zoneIndex=g;var n=b.zones[g].marker;var r=b.zones[g].className}var v=H(p);"grid"!==b.layoutAlgorithm.type||b.allowOverlap?v={x:v.x,y:v.y}:(g=this.options.marker||{},v=this.preventClusterCollisions({x:v.x,y:v.y,key:l,groupedData:a,gridSize:this.getScaledGridSize(b.layoutAlgorithm),defaultRadius:g.radius|| +3+(g.lineWidth||0),clusterRadius:n&&n.radius?n.radius:(b.marker||{}).radius||C.marker.radius}));for(g=0;g=k.minX-d&&a.xData[q]<=k.maxX+d&&(a.yData[q]||k.minY)>=k.minY-f&&(a.yData[q]||k.maxY)<=k.maxY+f&&(h.push(a.xData[q]),m.push(a.yData[q]),t.push(q))}B(n)&&B(g)&&D(r)&&D(l)&&(a.dataMaxX=n,a.dataMinX=g,a.dataMaxY=r,a.dataMinY=l);k=L(u)?u:a.markerClusterAlgorithms?u&&a.markerClusterAlgorithms[u]?a.markerClusterAlgorithms[u]: +h.length 0) && !(r = i.next()).done) ar.push(r.value); + } + catch (error) { e = { error: error }; } + finally { + try { + if (r && !r.done && (m = i["return"])) m.call(i); + } + finally { if (e) throw e.error; } + } + return ar; + }; + /** + * Function callback when a cluster is clicked. + * + * @callback Highcharts.MarkerClusterDrillCallbackFunction + * + * @param {Highcharts.Point} this + * The point where the event occured. + * + * @param {Highcharts.PointClickEventObject} event + * Event arguments. + */ + ''; // detach doclets from following code + var addEvent = U.addEvent, animObject = U.animObject, defined = U.defined, error = U.error, isArray = U.isArray, isFunction = U.isFunction, isObject = U.isObject, isNumber = U.isNumber, merge = U.merge, objectEach = U.objectEach, relativeLength = U.relativeLength, syncTimeout = U.syncTimeout; + /* eslint-disable no-invalid-this */ + var Series = H.Series, Scatter = H.seriesTypes.scatter, SvgRenderer = H.SVGRenderer, baseGeneratePoints = Series.prototype.generatePoints, stateIdCounter = 0, + // Points that ids are included in the oldPointsStateId array + // are hidden before animation. Other ones are destroyed. + oldPointsStateId = []; + /** + * Options for marker clusters, the concept of sampling the data + * values into larger blocks in order to ease readability and + * increase performance of the JavaScript charts. + * + * Note: marker clusters module is not working with `boost` + * and `draggable-points` modules. + * + * The marker clusters feature requires the marker-clusters.js + * file to be loaded, found in the modules directory of the download + * package, or online at [code.highcharts.com/modules/marker-clusters.js + * ](code.highcharts.com/modules/marker-clusters.js). + * + * @sample maps/marker-clusters/europe + * Maps marker clusters + * @sample highcharts/marker-clusters/basic + * Scatter marker clusters + * @sample maps/marker-clusters/optimized-kmeans + * Marker clusters with colorAxis + * + * @product highcharts highmaps + * @since 8.0.0 + * @optionparent plotOptions.scatter.cluster + * + * @private + */ + var clusterDefaultOptions = { + /** + * Whether to enable the marker-clusters module. + * + * @sample maps/marker-clusters/basic + * Maps marker clusters + * @sample highcharts/marker-clusters/basic + * Scatter marker clusters + */ + enabled: false, + /** + * When set to `false` prevent cluster overlapping - this option + * works only when `layoutAlgorithm.type = "grid"`. + * + * @sample highcharts/marker-clusters/grid + * Prevent overlapping + */ + allowOverlap: true, + /** + * Options for the cluster marker animation. + * @type {boolean|Highcharts.AnimationOptionsObject} + * @default { "duration": 500 } + */ + animation: { + /** @ignore-option */ + duration: 500 + }, + /** + * Zoom the plot area to the cluster points range when a cluster is clicked. + */ + drillToCluster: true, + /** + * The minimum amount of points to be combined into a cluster. + * This value has to be greater or equal to 2. + * + * @sample highcharts/marker-clusters/basic + * At least three points in the cluster + */ + minimumClusterSize: 2, + /** + * Options for layout algorithm. Inside there + * are options to change the type of the algorithm, gridSize, + * distance or iterations. + */ + layoutAlgorithm: { + /** + * Type of the algorithm used to combine points into a cluster. + * There are three available algorithms: + * + * 1) `grid` - grid-based clustering technique. Points are assigned + * to squares of set size depending on their position on the plot + * area. Points inside the grid square are combined into a cluster. + * The grid size can be controlled by `gridSize` property + * (grid size changes at certain zoom levels). + * + * 2) `kmeans` - based on K-Means clustering technique. In the + * first step, points are divided using the grid method (distance + * property is a grid size) to find the initial amount of clusters. + * Next, each point is classified by computing the distance between + * each cluster center and that point. When the closest cluster + * distance is lower than distance property set by a user the point + * is added to this cluster otherwise is classified as `noise`. The + * algorithm is repeated until each cluster center not change its + * previous position more than one pixel. This technique is more + * accurate but also more time consuming than the `grid` algorithm, + * especially for big datasets. + * + * 3) `optimizedKmeans` - based on K-Means clustering technique. This + * algorithm uses k-means algorithm only on the chart initialization + * or when chart extremes have greater range than on initialization. + * When a chart is redrawn the algorithm checks only clustered points + * distance from the cluster center and rebuild it when the point is + * spaced enough to be outside the cluster. It provides performance + * improvement and more stable clusters position yet can be used rather + * on small and sparse datasets. + * + * By default, the algorithm depends on visible quantity of points + * and `kmeansThreshold`. When there are more visible points than the + * `kmeansThreshold` the `grid` algorithm is used, otherwise `kmeans`. + * + * The custom clustering algorithm can be added by assigning a callback + * function as the type property. This function takes an array of + * `processedXData`, `processedYData`, `processedXData` indexes and + * `layoutAlgorithm` options as arguments and should return an object + * with grouped data. + * + * The algorithm should return an object like that: + *
    {
    +                 *  clusterId1: [{
    +                 *      x: 573,
    +                 *      y: 285,
    +                 *      index: 1 // point index in the data array
    +                 *  }, {
    +                 *      x: 521,
    +                 *      y: 197,
    +                 *      index: 2
    +                 *  }],
    +                 *  clusterId2: [{
    +                 *      ...
    +                 *  }]
    +                 *  ...
    +                 * }
    + * + * `clusterId` (example above - unique id of a cluster or noise) + * is an array of points belonging to a cluster. If the + * array has only one point or fewer points than set in + * `cluster.minimumClusterSize` it won't be combined into a cluster. + * + * @sample maps/marker-clusters/optimized-kmeans + * Optimized K-Means algorithm + * @sample highcharts/marker-clusters/kmeans + * K-Means algorithm + * @sample highcharts/marker-clusters/grid + * Grid algorithm + * @sample maps/marker-clusters/custom-alg + * Custom algorithm + * + * @type {string|Function} + * @see [cluster.minimumClusterSize](#plotOptions.scatter.marker.cluster.minimumClusterSize) + * @apioption plotOptions.scatter.cluster.layoutAlgorithm.type + */ + /** + * When `type` is set to the `grid`, + * `gridSize` is a size of a grid square element either as a number + * defining pixels, or a percentage defining a percentage + * of the plot area width. + * + * @type {number|string} + */ + gridSize: 50, + /** + * When `type` is set to `kmeans`, + * `iterations` are the number of iterations that this algorithm will be + * repeated to find clusters positions. + * + * @type {number} + * @apioption plotOptions.scatter.cluster.layoutAlgorithm.iterations + */ + /** + * When `type` is set to `kmeans`, + * `distance` is a maximum distance between point and cluster center + * so that this point will be inside the cluster. The distance + * is either a number defining pixels or a percentage + * defining a percentage of the plot area width. + * + * @type {number|string} + */ + distance: 40, + /** + * When `type` is set to `undefined` and there are more visible points + * than the kmeansThreshold the `grid` algorithm is used to find + * clusters, otherwise `kmeans`. It ensures good performance on + * large datasets and better clusters arrangement after the zoom. + */ + kmeansThreshold: 100 + }, + /** + * Options for the cluster marker. + * @extends plotOptions.series.marker + * @excluding enabledThreshold, states + * @type {Highcharts.PointMarkerOptionsObject} + */ + marker: { + /** @internal */ + symbol: 'cluster', + /** @internal */ + radius: 15, + /** @internal */ + lineWidth: 0, + /** @internal */ + lineColor: '#ffffff' + }, + /** + * Fires when the cluster point is clicked and `drillToCluster` is enabled. + * One parameter, `event`, is passed to the function. The default action + * is to zoom to the cluster points range. This can be prevented + * by calling `event.preventDefault()`. + * + * @type {Highcharts.MarkerClusterDrillCallbackFunction} + * @product highcharts highmaps + * @see [cluster.drillToCluster](#plotOptions.scatter.marker.cluster.drillToCluster) + * @apioption plotOptions.scatter.cluster.events.drillToCluster + */ + /** + * An array defining zones within marker clusters. + * + * In styled mode, the color zones are styled with the + * `.highcharts-cluster-zone-{n}` class, or custom + * classed from the `className` + * option. + * + * @sample highcharts/marker-clusters/basic + * Marker clusters zones + * @sample maps/marker-clusters/custom-alg + * Zones on maps + * + * @type {Array<*>} + * @product highcharts highmaps + * @apioption plotOptions.scatter.cluster.zones + */ + /** + * Styled mode only. A custom class name for the zone. + * + * @sample highcharts/css/color-zones/ + * Zones styled by class name + * + * @type {string} + * @apioption plotOptions.scatter.cluster.zones.className + */ + /** + * Settings for the cluster marker belonging to the zone. + * + * @see [cluster.marker](#plotOptions.scatter.cluster.marker) + * @extends plotOptions.scatter.cluster.marker + * @product highcharts highmaps + * @apioption plotOptions.scatter.cluster.zones.marker + */ + /** + * The value where the zone starts. + * + * @type {number} + * @product highcharts highmaps + * @apioption plotOptions.scatter.cluster.zones.from + */ + /** + * The value where the zone ends. + * + * @type {number} + * @product highcharts highmaps + * @apioption plotOptions.scatter.cluster.zones.to + */ + /** + * The fill color of the cluster marker in hover state. When + * `undefined`, the series' or point's fillColor for normal + * state is used. + * + * @type {Highcharts.ColorType} + * @apioption plotOptions.scatter.cluster.states.hover.fillColor + */ + /** + * Options for the cluster data labels. + * @type {Highcharts.DataLabelsOptions} + */ + dataLabels: { + /** @internal */ + enabled: true, + /** @internal */ + format: '{point.clusterPointsAmount}', + /** @internal */ + verticalAlign: 'middle', + /** @internal */ + align: 'center', + /** @internal */ + style: { + color: 'contrast' + }, + /** @internal */ + inside: true + } + }; + (H.defaultOptions.plotOptions || {}).series = merge((H.defaultOptions.plotOptions || {}).series, { + cluster: clusterDefaultOptions, + tooltip: { + /** + * The HTML of the cluster point's in the tooltip. Works only with + * marker-clusters module and analogously to + * [pointFormat](#tooltip.pointFormat). + * + * The cluster tooltip can be also formatted using + * `tooltip.formatter` callback function and `point.isCluster` flag. + * + * @sample highcharts/marker-clusters/grid + * Format tooltip for cluster points. + * + * @sample maps/marker-clusters/europe/ + * Format tooltip for clusters using tooltip.formatter + * + * @apioption tooltip.clusterFormat + */ + clusterFormat: 'Clustered points: ' + + '{point.clusterPointsAmount}
    ' + } + }); + // Utils. + /* eslint-disable require-jsdoc */ + function getClusterPosition(points) { + var pointsLen = points.length, sumX = 0, sumY = 0, i; + for (i = 0; i < pointsLen; i++) { + sumX += points[i].x; + sumY += points[i].y; + } + return { + x: sumX / pointsLen, + y: sumY / pointsLen + }; + } + // Prepare array with sorted data objects to be + // compared in getPointsState method. + function getDataState(clusteredData, stateDataLen) { + var state = []; + state.length = stateDataLen; + clusteredData.clusters.forEach(function (cluster) { + cluster.data.forEach(function (elem) { + state[elem.dataIndex] = elem; + }); + }); + clusteredData.noise.forEach(function (noise) { + state[noise.data[0].dataIndex] = noise.data[0]; + }); + return state; + } + function fadeInElement(elem, opacity, animation) { + elem + .attr({ + opacity: opacity + }) + .animate({ + opacity: 1 + }, animation); + } + function fadeInStatePoint(stateObj, opacity, animation, fadeinGraphic, fadeinDataLabel) { + if (stateObj.point) { + if (fadeinGraphic && stateObj.point.graphic) { + stateObj.point.graphic.show(); + fadeInElement(stateObj.point.graphic, opacity, animation); + } + if (fadeinDataLabel && stateObj.point.dataLabel) { + stateObj.point.dataLabel.show(); + fadeInElement(stateObj.point.dataLabel, opacity, animation); + } + } + } + function hideStatePoint(stateObj, hideGraphic, hideDataLabel) { + if (stateObj.point) { + if (hideGraphic && stateObj.point.graphic) { + stateObj.point.graphic.hide(); + } + if (hideDataLabel && stateObj.point.dataLabel) { + stateObj.point.dataLabel.hide(); + } + } + } + function destroyOldPoints(oldState) { + if (oldState) { + objectEach(oldState, function (state) { + if (state.point && state.point.destroy) { + state.point.destroy(); + } + }); + } + } + function fadeInNewPointAndDestoryOld(newPointObj, oldPoints, animation, opacity) { + // Fade in new point. + fadeInStatePoint(newPointObj, opacity, animation, true, true); + // Destroy old animated points. + oldPoints.forEach(function (p) { + if (p.point && p.point.destroy) { + p.point.destroy(); + } + }); + } + // Generate unique stateId for a state element. + function getStateId() { + return Math.random().toString(36).substring(2, 7) + '-' + stateIdCounter++; + } + // Useful for debugging. + // function drawGridLines( + // series: Highcharts.Series, + // options: Highcharts.MarkerClusterLayoutAlgorithmOptions + // ): void { + // var chart = series.chart, + // xAxis = series.xAxis, + // yAxis = series.yAxis, + // xAxisLen = series.xAxis.len, + // yAxisLen = series.yAxis.len, + // i, j, elem, text, + // currentX = 0, + // currentY = 0, + // scaledGridSize = 50, + // gridX = 0, + // gridY = 0, + // gridOffset = series.getGridOffset(), + // mapXSize, mapYSize; + // if (series.debugGridLines && series.debugGridLines.length) { + // series.debugGridLines.forEach(function (gridItem): void { + // if (gridItem && gridItem.destroy) { + // gridItem.destroy(); + // } + // }); + // } + // series.debugGridLines = []; + // scaledGridSize = series.getScaledGridSize(options); + // mapXSize = Math.abs( + // xAxis.toPixels(xAxis.dataMax || 0) - + // xAxis.toPixels(xAxis.dataMin || 0) + // ); + // mapYSize = Math.abs( + // yAxis.toPixels(yAxis.dataMax || 0) - + // yAxis.toPixels(yAxis.dataMin || 0) + // ); + // gridX = Math.ceil(mapXSize / scaledGridSize); + // gridY = Math.ceil(mapYSize / scaledGridSize); + // for (i = 0; i < gridX; i++) { + // currentX = i * scaledGridSize; + // if ( + // gridOffset.plotLeft + currentX >= 0 && + // gridOffset.plotLeft + currentX < xAxisLen + // ) { + // for (j = 0; j < gridY; j++) { + // currentY = j * scaledGridSize; + // if ( + // gridOffset.plotTop + currentY >= 0 && + // gridOffset.plotTop + currentY < yAxisLen + // ) { + // if (j % 2 === 0 && i % 2 === 0) { + // var rect = chart.renderer + // .rect( + // gridOffset.plotLeft + currentX, + // gridOffset.plotTop + currentY, + // scaledGridSize * 2, + // scaledGridSize * 2 + // ) + // .attr({ + // stroke: series.color, + // 'stroke-width': '2px' + // }) + // .add() + // .toFront(); + // series.debugGridLines.push(rect); + // } + // elem = chart.renderer + // .rect( + // gridOffset.plotLeft + currentX, + // gridOffset.plotTop + currentY, + // scaledGridSize, + // scaledGridSize + // ) + // .attr({ + // stroke: series.color, + // opacity: 0.3, + // 'stroke-width': '1px' + // }) + // .add() + // .toFront(); + // text = chart.renderer + // .text( + // j + '-' + i, + // gridOffset.plotLeft + currentX + 2, + // gridOffset.plotTop + currentY + 7 + // ) + // .css({ + // fill: 'rgba(0, 0, 0, 0.7)', + // fontSize: '7px' + // }) + // .add() + // .toFront(); + // series.debugGridLines.push(elem); + // series.debugGridLines.push(text); + // } + // } + // } + // } + // } + /* eslint-enable require-jsdoc */ + // Cluster symbol. + SvgRenderer.prototype.symbols.cluster = function (x, y, width, height) { + var w = width / 2, h = height / 2, outerWidth = 1, space = 1, inner, outer1, outer2; + inner = this.arc(x + w, y + h, w - space * 4, h - space * 4, { + start: Math.PI * 0.5, + end: Math.PI * 2.5, + open: false + }); + outer1 = this.arc(x + w, y + h, w - space * 3, h - space * 3, { + start: Math.PI * 0.5, + end: Math.PI * 2.5, + innerR: w - outerWidth * 2, + open: false + }); + outer2 = this.arc(x + w, y + h, w - space, h - space, { + start: Math.PI * 0.5, + end: Math.PI * 2.5, + innerR: w, + open: false + }); + return outer2.concat(outer1, inner); + }; + Scatter.prototype.animateClusterPoint = function (clusterObj) { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, chart = series.chart, clusterOptions = series.options.cluster, animation = animObject((clusterOptions || {}).animation), animDuration = animation.duration || 500, pointsState = (series.markerClusterInfo || {}).pointsState, newState = (pointsState || {}).newState, oldState = (pointsState || {}).oldState, parentId, oldPointObj, newPointObj, oldPoints = [], newPointBBox, offset = 0, newX = 0, newY = 0, isOldPointGrahic = false, isCbHandled = false; + if (oldState && newState) { + newPointObj = newState[clusterObj.stateId]; + newX = xAxis.toPixels(newPointObj.x) - chart.plotLeft; + newY = yAxis.toPixels(newPointObj.y) - chart.plotTop; + // Point has one ancestor. + if (newPointObj.parentsId.length === 1) { + parentId = (newState || {})[clusterObj.stateId].parentsId[0]; + oldPointObj = oldState[parentId]; + // If old and new poistions are the same do not animate. + if (newPointObj.point && + newPointObj.point.graphic && + oldPointObj && + oldPointObj.point && + oldPointObj.point.plotX && + oldPointObj.point.plotY && + oldPointObj.point.plotX !== newPointObj.point.plotX && + oldPointObj.point.plotY !== newPointObj.point.plotY) { + newPointBBox = newPointObj.point.graphic.getBBox(); + offset = newPointBBox.width / 2; + newPointObj.point.graphic.attr({ + x: oldPointObj.point.plotX - offset, + y: oldPointObj.point.plotY - offset + }); + newPointObj.point.graphic.animate({ + x: newX - newPointObj.point.graphic.radius, + y: newY - newPointObj.point.graphic.radius + }, animation, function () { + isCbHandled = true; + // Destroy old point. + if (oldPointObj.point && oldPointObj.point.destroy) { + oldPointObj.point.destroy(); + } + }); + // Data label animation. + if (newPointObj.point.dataLabel && + newPointObj.point.dataLabel.alignAttr && + oldPointObj.point.dataLabel && + oldPointObj.point.dataLabel.alignAttr) { + newPointObj.point.dataLabel.attr({ + x: oldPointObj.point.dataLabel.alignAttr.x, + y: oldPointObj.point.dataLabel.alignAttr.y + }); + newPointObj.point.dataLabel.animate({ + x: newPointObj.point.dataLabel.alignAttr.x, + y: newPointObj.point.dataLabel.alignAttr.y + }, animation); + } + } + } + else if (newPointObj.parentsId.length === 0) { + // Point has no ancestors - new point. + // Hide new point. + hideStatePoint(newPointObj, true, true); + syncTimeout(function () { + // Fade in new point. + fadeInStatePoint(newPointObj, 0.1, animation, true, true); + }, animDuration / 2); + } + else { + // Point has many ancestors. + // Hide new point before animation. + hideStatePoint(newPointObj, true, true); + newPointObj.parentsId.forEach(function (elem) { + if (oldState && oldState[elem]) { + oldPointObj = oldState[elem]; + oldPoints.push(oldPointObj); + if (oldPointObj.point && + oldPointObj.point.graphic) { + isOldPointGrahic = true; + oldPointObj.point.graphic.show(); + oldPointObj.point.graphic.animate({ + x: newX - oldPointObj.point.graphic.radius, + y: newY - oldPointObj.point.graphic.radius, + opacity: 0.4 + }, animation, function () { + isCbHandled = true; + fadeInNewPointAndDestoryOld(newPointObj, oldPoints, animation, 0.7); + }); + if (oldPointObj.point.dataLabel && + oldPointObj.point.dataLabel.y !== -9999 && + newPointObj.point && + newPointObj.point.dataLabel && + newPointObj.point.dataLabel.alignAttr) { + oldPointObj.point.dataLabel.show(); + oldPointObj.point.dataLabel.animate({ + x: newPointObj.point.dataLabel.alignAttr.x, + y: newPointObj.point.dataLabel.alignAttr.y, + opacity: 0.4 + }, animation); + } + } + } + }); + // Make sure point is faded in. + syncTimeout(function () { + if (!isCbHandled) { + fadeInNewPointAndDestoryOld(newPointObj, oldPoints, animation, 0.85); + } + }, animDuration); + if (!isOldPointGrahic) { + syncTimeout(function () { + fadeInNewPointAndDestoryOld(newPointObj, oldPoints, animation, 0.1); + }, animDuration / 2); + } + } + } + }; + Scatter.prototype.getGridOffset = function () { + var series = this, chart = series.chart, xAxis = series.xAxis, yAxis = series.yAxis, plotLeft = 0, plotTop = 0; + if (series.dataMinX && series.dataMaxX) { + plotLeft = xAxis.reversed ? + xAxis.toPixels(series.dataMaxX) : xAxis.toPixels(series.dataMinX); + } + else { + plotLeft = chart.plotLeft; + } + if (series.dataMinY && series.dataMaxY) { + plotTop = yAxis.reversed ? + yAxis.toPixels(series.dataMinY) : yAxis.toPixels(series.dataMaxY); + } + else { + plotTop = chart.plotTop; + } + return { plotLeft: plotLeft, plotTop: plotTop }; + }; + Scatter.prototype.getScaledGridSize = function (options) { + var series = this, xAxis = series.xAxis, search = true, k = 1, divider = 1, processedGridSize = options.processedGridSize || + clusterDefaultOptions.layoutAlgorithm.gridSize, gridSize, scale, level; + if (!series.gridValueSize) { + series.gridValueSize = Math.abs(xAxis.toValue(processedGridSize) - xAxis.toValue(0)); + } + gridSize = xAxis.toPixels(series.gridValueSize) - xAxis.toPixels(0); + scale = +(processedGridSize / gridSize).toFixed(14); + // Find the level and its divider. + while (search && scale !== 1) { + level = Math.pow(2, k); + if (scale > 0.75 && scale < 1.25) { + search = false; + } + else if (scale >= (1 / level) && scale < 2 * (1 / level)) { + search = false; + divider = level; + } + else if (scale <= level && scale > level / 2) { + search = false; + divider = 1 / level; + } + k++; + } + return (processedGridSize / divider) / scale; + }; + Scatter.prototype.getRealExtremes = function () { + var _a, _b; + var series = this, chart = series.chart, xAxis = series.xAxis, yAxis = series.yAxis, realMinX = xAxis ? xAxis.toValue(chart.plotLeft) : 0, realMaxX = xAxis ? + xAxis.toValue(chart.plotLeft + chart.plotWidth) : 0, realMinY = yAxis ? yAxis.toValue(chart.plotTop) : 0, realMaxY = yAxis ? + yAxis.toValue(chart.plotTop + chart.plotHeight) : 0; + if (realMinX > realMaxX) { + _a = __read([realMinX, realMaxX], 2), realMaxX = _a[0], realMinX = _a[1]; + } + if (realMinY > realMaxY) { + _b = __read([realMinY, realMaxY], 2), realMaxY = _b[0], realMinY = _b[1]; + } + return { + minX: realMinX, + maxX: realMaxX, + minY: realMinY, + maxY: realMaxY + }; + }; + Scatter.prototype.onDrillToCluster = function (event) { + var point = event.point || event.target; + point.firePointEvent('drillToCluster', event, function (e) { + var _a, _b; + var point = e.point || e.target, series = point.series, xAxis = point.series.xAxis, yAxis = point.series.yAxis, chart = point.series.chart, clusterOptions = series.options.cluster, drillToCluster = (clusterOptions || {}).drillToCluster, offsetX, offsetY, sortedDataX, sortedDataY, minX, minY, maxX, maxY; + if (drillToCluster && point.clusteredData) { + sortedDataX = point.clusteredData.map(function (data) { + return data.x; + }).sort(function (a, b) { return a - b; }); + sortedDataY = point.clusteredData.map(function (data) { + return data.y; + }).sort(function (a, b) { return a - b; }); + minX = sortedDataX[0]; + maxX = sortedDataX[sortedDataX.length - 1]; + minY = sortedDataY[0]; + maxY = sortedDataY[sortedDataY.length - 1]; + offsetX = Math.abs((maxX - minX) * 0.1); + offsetY = Math.abs((maxY - minY) * 0.1); + chart.pointer.zoomX = true; + chart.pointer.zoomY = true; + // Swap when minus values. + if (minX > maxX) { + _a = __read([maxX, minX], 2), minX = _a[0], maxX = _a[1]; + } + if (minY > maxY) { + _b = __read([maxY, minY], 2), minY = _b[0], maxY = _b[1]; + } + chart.zoom({ + originalEvent: e, + xAxis: [{ + axis: xAxis, + min: minX - offsetX, + max: maxX + offsetX + }], + yAxis: [{ + axis: yAxis, + min: minY - offsetY, + max: maxY + offsetY + }] + }); + } + }); + }; + Scatter.prototype.getClusterDistancesFromPoint = function (clusters, pointX, pointY) { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, pointClusterDistance = [], j, distance; + for (j = 0; j < clusters.length; j++) { + distance = Math.sqrt(Math.pow(xAxis.toPixels(pointX) - + xAxis.toPixels(clusters[j].posX), 2) + + Math.pow(yAxis.toPixels(pointY) - + yAxis.toPixels(clusters[j].posY), 2)); + pointClusterDistance.push({ + clusterIndex: j, + distance: distance + }); + } + return pointClusterDistance.sort(function (a, b) { return a.distance - b.distance; }); + }; + // Point state used when animation is enabled to compare + // and bind old points with new ones. + Scatter.prototype.getPointsState = function (clusteredData, oldMarkerClusterInfo, dataLength) { + var oldDataStateArr = oldMarkerClusterInfo ? + getDataState(oldMarkerClusterInfo, dataLength) : [], newDataStateArr = getDataState(clusteredData, dataLength), state = {}, newState, oldState, i; + // Clear global array before populate with new ids. + oldPointsStateId = []; + // Build points state structure. + clusteredData.clusters.forEach(function (cluster) { + state[cluster.stateId] = { + x: cluster.x, + y: cluster.y, + id: cluster.stateId, + point: cluster.point, + parentsId: [] + }; + }); + clusteredData.noise.forEach(function (noise) { + state[noise.stateId] = { + x: noise.x, + y: noise.y, + id: noise.stateId, + point: noise.point, + parentsId: [] + }; + }); + // Bind new and old state. + for (i = 0; i < newDataStateArr.length; i++) { + newState = newDataStateArr[i]; + oldState = oldDataStateArr[i]; + if (newState && + oldState && + newState.parentStateId && + oldState.parentStateId && + state[newState.parentStateId] && + state[newState.parentStateId].parentsId.indexOf(oldState.parentStateId) === -1) { + state[newState.parentStateId].parentsId.push(oldState.parentStateId); + if (oldPointsStateId.indexOf(oldState.parentStateId) === -1) { + oldPointsStateId.push(oldState.parentStateId); + } + } + } + return state; + }; + Scatter.prototype.markerClusterAlgorithms = { + grid: function (dataX, dataY, dataIndexes, options) { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, grid = {}, gridOffset = series.getGridOffset(), scaledGridSize, x, y, gridX, gridY, key, i; + // drawGridLines(series, options); + scaledGridSize = series.getScaledGridSize(options); + for (i = 0; i < dataX.length; i++) { + x = xAxis.toPixels(dataX[i]) - gridOffset.plotLeft; + y = yAxis.toPixels(dataY[i]) - gridOffset.plotTop; + gridX = Math.floor(x / scaledGridSize); + gridY = Math.floor(y / scaledGridSize); + key = gridY + '-' + gridX; + if (!grid[key]) { + grid[key] = []; + } + grid[key].push({ + dataIndex: dataIndexes[i], + x: dataX[i], + y: dataY[i] + }); + } + return grid; + }, + kmeans: function (dataX, dataY, dataIndexes, options) { + var series = this, clusters = [], noise = [], group = {}, pointMaxDistance = options.processedDistance || + clusterDefaultOptions.layoutAlgorithm.distance, iterations = options.iterations, + // Max pixel difference beetwen new and old cluster position. + maxClusterShift = 1, currentIteration = 0, repeat = true, pointX = 0, pointY = 0, tempPos, pointClusterDistance = [], groupedData, key, i, j; + options.processedGridSize = options.processedDistance; + // Use grid method to get groupedData object. + groupedData = series.markerClusterAlgorithms ? + series.markerClusterAlgorithms.grid.call(series, dataX, dataY, dataIndexes, options) : {}; + // Find clusters amount and its start positions + // based on grid grouped data. + for (key in groupedData) { + if (groupedData[key].length > 1) { + tempPos = getClusterPosition(groupedData[key]); + clusters.push({ + posX: tempPos.x, + posY: tempPos.y, + oldX: 0, + oldY: 0, + startPointsLen: groupedData[key].length, + points: [] + }); + } + } + // Start kmeans iteration process. + while (repeat) { + clusters.map(function (c) { + c.points.length = 0; + return c; + }); + noise.length = 0; + for (i = 0; i < dataX.length; i++) { + pointX = dataX[i]; + pointY = dataY[i]; + pointClusterDistance = series.getClusterDistancesFromPoint(clusters, pointX, pointY); + if (pointClusterDistance.length && + pointClusterDistance[0].distance < pointMaxDistance) { + clusters[pointClusterDistance[0].clusterIndex].points.push({ + x: pointX, + y: pointY, + dataIndex: dataIndexes[i] + }); + } + else { + noise.push({ + x: pointX, + y: pointY, + dataIndex: dataIndexes[i] + }); + } + } + // When cluster points array has only one point the + // point should be classified again. + for (j = 0; j < clusters.length; j++) { + if (clusters[j].points.length === 1) { + pointClusterDistance = series.getClusterDistancesFromPoint(clusters, clusters[j].points[0].x, clusters[j].points[0].y); + if (pointClusterDistance[1].distance < pointMaxDistance) { + // Add point to the next closest cluster. + clusters[pointClusterDistance[1].clusterIndex].points + .push(clusters[j].points[0]); + // Clear points array. + clusters[pointClusterDistance[0].clusterIndex] + .points.length = 0; + } + } + } + // Compute a new clusters position and check if it + // is different than the old one. + repeat = false; + for (j = 0; j < clusters.length; j++) { + tempPos = getClusterPosition(clusters[j].points); + clusters[j].oldX = clusters[j].posX; + clusters[j].oldY = clusters[j].posY; + clusters[j].posX = tempPos.x; + clusters[j].posY = tempPos.y; + // Repeat the algorithm if at least one cluster + // is shifted more than maxClusterShift property. + if (clusters[j].posX > clusters[j].oldX + maxClusterShift || + clusters[j].posX < clusters[j].oldX - maxClusterShift || + clusters[j].posY > clusters[j].oldY + maxClusterShift || + clusters[j].posY < clusters[j].oldY - maxClusterShift) { + repeat = true; + } + } + // If iterations property is set repeat the algorithm + // specified amount of times. + if (iterations) { + repeat = currentIteration < iterations - 1; + } + currentIteration++; + } + clusters.forEach(function (cluster, i) { + group['cluster' + i] = cluster.points; + }); + noise.forEach(function (noise, i) { + group['noise' + i] = [noise]; + }); + return group; + }, + optimizedKmeans: function (processedXData, processedYData, dataIndexes, options) { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, pointMaxDistance = options.processedDistance || + clusterDefaultOptions.layoutAlgorithm.gridSize, group = {}, extremes = series.getRealExtremes(), clusterMarkerOptions = (series.options.cluster || {}).marker, offset, distance, radius; + if (!series.markerClusterInfo || (series.initMaxX && series.initMaxX < extremes.maxX || + series.initMinX && series.initMinX > extremes.minX || + series.initMaxY && series.initMaxY < extremes.maxY || + series.initMinY && series.initMinY > extremes.minY)) { + series.initMaxX = extremes.maxX; + series.initMinX = extremes.minX; + series.initMaxY = extremes.maxY; + series.initMinY = extremes.minY; + group = series.markerClusterAlgorithms ? + series.markerClusterAlgorithms.kmeans.call(series, processedXData, processedYData, dataIndexes, options) : {}; + series.baseClusters = null; + } + else { + if (!series.baseClusters) { + series.baseClusters = { + clusters: series.markerClusterInfo.clusters, + noise: series.markerClusterInfo.noise + }; + } + series.baseClusters.clusters.forEach(function (cluster) { + cluster.pointsOutside = []; + cluster.pointsInside = []; + cluster.data.forEach(function (dataPoint) { + distance = Math.sqrt(Math.pow(xAxis.toPixels(dataPoint.x) - + xAxis.toPixels(cluster.x), 2) + + Math.pow(yAxis.toPixels(dataPoint.y) - + yAxis.toPixels(cluster.y), 2)); + if (cluster.clusterZone && + cluster.clusterZone.marker && + cluster.clusterZone.marker.radius) { + radius = cluster.clusterZone.marker.radius; + } + else if (clusterMarkerOptions && + clusterMarkerOptions.radius) { + radius = clusterMarkerOptions.radius; + } + else { + radius = clusterDefaultOptions.marker.radius; + } + offset = pointMaxDistance - radius >= 0 ? + pointMaxDistance - radius : radius; + if (distance > radius + offset && + defined(cluster.pointsOutside)) { + cluster.pointsOutside.push(dataPoint); + } + else if (defined(cluster.pointsInside)) { + cluster.pointsInside.push(dataPoint); + } + }); + if (cluster.pointsInside.length) { + group[cluster.id] = cluster.pointsInside; + } + cluster.pointsOutside.forEach(function (p, i) { + group[cluster.id + '_noise' + i] = [p]; + }); + }); + series.baseClusters.noise.forEach(function (noise) { + group[noise.id] = noise.data; + }); + } + return group; + } + }; + Scatter.prototype.preventClusterCollisions = function (props) { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, _a = __read(props.key.split('-').map(parseFloat), 2), gridY = _a[0], gridX = _a[1], gridSize = props.gridSize, groupedData = props.groupedData, defaultRadius = props.defaultRadius, clusterRadius = props.clusterRadius, gridXPx = gridX * gridSize, gridYPx = gridY * gridSize, xPixel = xAxis.toPixels(props.x), yPixel = yAxis.toPixels(props.y), gridsToCheckCollision = [], pointsLen = 0, radius = 0, clusterMarkerOptions = (series.options.cluster || {}).marker, zoneOptions = (series.options.cluster || {}).zones, gridOffset = series.getGridOffset(), nextXPixel, nextYPixel, signX, signY, cornerGridX, cornerGridY, i, j, itemX, itemY, nextClusterPos, maxDist, keys, x, y; + // Distance to the grid start. + xPixel -= gridOffset.plotLeft; + yPixel -= gridOffset.plotTop; + for (i = 1; i < 5; i++) { + signX = i % 2 ? -1 : 1; + signY = i < 3 ? -1 : 1; + cornerGridX = Math.floor((xPixel + signX * clusterRadius) / gridSize); + cornerGridY = Math.floor((yPixel + signY * clusterRadius) / gridSize); + keys = [ + cornerGridY + '-' + cornerGridX, + cornerGridY + '-' + gridX, + gridY + '-' + cornerGridX + ]; + for (j = 0; j < keys.length; j++) { + if (gridsToCheckCollision.indexOf(keys[j]) === -1 && + keys[j] !== props.key) { + gridsToCheckCollision.push(keys[j]); + } + } + } + gridsToCheckCollision.forEach(function (item) { + var _a; + if (groupedData[item]) { + // Cluster or noise position is already computed. + if (!groupedData[item].posX) { + nextClusterPos = getClusterPosition(groupedData[item]); + groupedData[item].posX = nextClusterPos.x; + groupedData[item].posY = nextClusterPos.y; + } + nextXPixel = xAxis.toPixels(groupedData[item].posX || 0) - + gridOffset.plotLeft; + nextYPixel = yAxis.toPixels(groupedData[item].posY || 0) - + gridOffset.plotTop; + _a = __read(item.split('-').map(parseFloat), 2), itemY = _a[0], itemX = _a[1]; + if (zoneOptions) { + pointsLen = groupedData[item].length; + for (i = 0; i < zoneOptions.length; i++) { + if (pointsLen >= zoneOptions[i].from && + pointsLen <= zoneOptions[i].to) { + if (defined((zoneOptions[i].marker || {}).radius)) { + radius = zoneOptions[i].marker.radius || 0; + } + else if (clusterMarkerOptions && + clusterMarkerOptions.radius) { + radius = clusterMarkerOptions.radius; + } + else { + radius = clusterDefaultOptions.marker.radius; + } + } + } + } + if (groupedData[item].length > 1 && + radius === 0 && + clusterMarkerOptions && + clusterMarkerOptions.radius) { + radius = clusterMarkerOptions.radius; + } + else if (groupedData[item].length === 1) { + radius = defaultRadius; + } + maxDist = clusterRadius + radius; + radius = 0; + if (itemX !== gridX && + Math.abs(xPixel - nextXPixel) < maxDist) { + xPixel = itemX - gridX < 0 ? gridXPx + clusterRadius : + gridXPx + gridSize - clusterRadius; + } + if (itemY !== gridY && + Math.abs(yPixel - nextYPixel) < maxDist) { + yPixel = itemY - gridY < 0 ? gridYPx + clusterRadius : + gridYPx + gridSize - clusterRadius; + } + } + }); + x = xAxis.toValue(xPixel + gridOffset.plotLeft); + y = yAxis.toValue(yPixel + gridOffset.plotTop); + groupedData[props.key].posX = x; + groupedData[props.key].posY = y; + return { x: x, y: y }; + }; + // Check if user algorithm result is valid groupedDataObject. + Scatter.prototype.isValidGroupedDataObject = function (groupedData) { + var result = false, i; + if (!isObject(groupedData)) { + return false; + } + objectEach(groupedData, function (elem) { + result = true; + if (!isArray(elem) || !elem.length) { + result = false; + return; + } + for (i = 0; i < elem.length; i++) { + if (!isObject(elem[i]) || (!elem[i].x || !elem[i].y)) { + result = false; + return; + } + } + }); + return result; + }; + Scatter.prototype.getClusteredData = function (groupedData, options) { + var series = this, groupedXData = [], groupedYData = [], clusters = [], // Container for clusters. + noise = [], // Container for points not belonging to any cluster. + groupMap = [], index = 0, + // Prevent minimumClusterSize lower than 2. + minimumClusterSize = Math.max(2, options.minimumClusterSize || 2), stateId, point, points, pointUserOptions, pointsLen, marker, clusterPos, pointOptions, clusterTempPos, zoneOptions, clusterZone, clusterZoneClassName, i, k; + // Check if groupedData is valid when user uses a custom algorithm. + if (isFunction(options.layoutAlgorithm.type) && + !series.isValidGroupedDataObject(groupedData)) { + error('Highcharts marker-clusters module: ' + + 'The custom algorithm result is not valid!', false, series.chart); + return false; + } + for (k in groupedData) { + if (groupedData[k].length >= minimumClusterSize) { + points = groupedData[k]; + stateId = getStateId(); + pointsLen = points.length; + // Get zone options for cluster. + if (options.zones) { + for (i = 0; i < options.zones.length; i++) { + if (pointsLen >= options.zones[i].from && + pointsLen <= options.zones[i].to) { + clusterZone = options.zones[i]; + clusterZone.zoneIndex = i; + zoneOptions = options.zones[i].marker; + clusterZoneClassName = options.zones[i].className; + } + } + } + clusterTempPos = getClusterPosition(points); + if (options.layoutAlgorithm.type === 'grid' && + !options.allowOverlap) { + marker = series.options.marker || {}; + clusterPos = series.preventClusterCollisions({ + x: clusterTempPos.x, + y: clusterTempPos.y, + key: k, + groupedData: groupedData, + gridSize: series.getScaledGridSize(options.layoutAlgorithm), + defaultRadius: marker.radius || 3 + (marker.lineWidth || 0), + clusterRadius: (zoneOptions && zoneOptions.radius) ? + zoneOptions.radius : + (options.marker || {}).radius || + clusterDefaultOptions.marker.radius + }); + } + else { + clusterPos = { + x: clusterTempPos.x, + y: clusterTempPos.y + }; + } + for (i = 0; i < pointsLen; i++) { + points[i].parentStateId = stateId; + } + clusters.push({ + x: clusterPos.x, + y: clusterPos.y, + id: k, + stateId: stateId, + index: index, + data: points, + clusterZone: clusterZone, + clusterZoneClassName: clusterZoneClassName + }); + groupedXData.push(clusterPos.x); + groupedYData.push(clusterPos.y); + groupMap.push({ + options: { + formatPrefix: 'cluster', + dataLabels: options.dataLabels, + marker: merge(options.marker, { + states: options.states + }, zoneOptions || {}) + } + }); + // Save cluster data points options. + if (series.options.data && series.options.data.length) { + for (i = 0; i < pointsLen; i++) { + if (isObject(series.options.data[points[i].dataIndex])) { + points[i].options = + series.options.data[points[i].dataIndex]; + } + } + } + index++; + zoneOptions = null; + } + else { + for (i = 0; i < groupedData[k].length; i++) { + // Points not belonging to any cluster. + point = groupedData[k][i]; + stateId = getStateId(); + pointOptions = null; + pointUserOptions = + ((series.options || {}).data || [])[point.dataIndex]; + groupedXData.push(point.x); + groupedYData.push(point.y); + point.parentStateId = stateId; + noise.push({ + x: point.x, + y: point.y, + id: k, + stateId: stateId, + index: index, + data: groupedData[k] + }); + if (pointUserOptions && + typeof pointUserOptions === 'object' && + !isArray(pointUserOptions)) { + pointOptions = merge(pointUserOptions, { x: point.x, y: point.y }); + } + else { + pointOptions = { + userOptions: pointUserOptions, + x: point.x, + y: point.y + }; + } + groupMap.push({ options: pointOptions }); + index++; + } + } + } + return { + clusters: clusters, + noise: noise, + groupedXData: groupedXData, + groupedYData: groupedYData, + groupMap: groupMap + }; + }; + // Destroy clustered data points. + Scatter.prototype.destroyClusteredData = function () { + var clusteredSeriesData = this.markerClusterSeriesData; + // Clear previous groups. + (clusteredSeriesData || []).forEach(function (point) { + if (point && point.destroy) { + point.destroy(); + } + }); + this.markerClusterSeriesData = null; + }; + // Hide clustered data points. + Scatter.prototype.hideClusteredData = function () { + var series = this, clusteredSeriesData = this.markerClusterSeriesData, oldState = ((series.markerClusterInfo || {}).pointsState || {}).oldState || {}, oldPointsId = oldPointsStateId.map(function (elem) { + return (oldState[elem].point || {}).id || ''; + }); + (clusteredSeriesData || []).forEach(function (point) { + // If an old point is used in animation hide it, otherwise destroy. + if (point && + oldPointsId.indexOf(point.id) !== -1) { + if (point.graphic) { + point.graphic.hide(); + } + if (point.dataLabel) { + point.dataLabel.hide(); + } + } + else { + if (point && point.destroy) { + point.destroy(); + } + } + }); + }; + // Override the generatePoints method by adding a reference to grouped data. + Scatter.prototype.generatePoints = function () { + var series = this, chart = series.chart, xAxis = series.xAxis, yAxis = series.yAxis, clusterOptions = series.options.cluster, realExtremes = series.getRealExtremes(), visibleXData = [], visibleYData = [], visibleDataIndexes = [], oldPointsState, oldDataLen, oldMarkerClusterInfo, kmeansThreshold, cropDataOffsetX, cropDataOffsetY, seriesMinX, seriesMaxX, seriesMinY, seriesMaxY, type, algorithm, clusteredData, groupedData, layoutAlgOptions, point, i; + if (clusterOptions && + clusterOptions.enabled && + series.xData && + series.yData && + !chart.polar) { + type = clusterOptions.layoutAlgorithm.type; + layoutAlgOptions = clusterOptions.layoutAlgorithm; + // Get processed algorithm properties. + layoutAlgOptions.processedGridSize = relativeLength(layoutAlgOptions.gridSize || + clusterDefaultOptions.layoutAlgorithm.gridSize, chart.plotWidth); + layoutAlgOptions.processedDistance = relativeLength(layoutAlgOptions.distance || + clusterDefaultOptions.layoutAlgorithm.distance, chart.plotWidth); + kmeansThreshold = layoutAlgOptions.kmeansThreshold || + clusterDefaultOptions.layoutAlgorithm.kmeansThreshold; + // Offset to prevent cluster size changes. + cropDataOffsetX = Math.abs(xAxis.toValue(layoutAlgOptions.processedGridSize / 2) - + xAxis.toValue(0)); + cropDataOffsetY = Math.abs(yAxis.toValue(layoutAlgOptions.processedGridSize / 2) - + yAxis.toValue(0)); + // Get only visible data. + for (i = 0; i < series.xData.length; i++) { + if (!series.dataMaxX) { + if (!defined(seriesMaxX) || + !defined(seriesMinX) || + !defined(seriesMaxY) || + !defined(seriesMinY)) { + seriesMaxX = seriesMinX = series.xData[i]; + seriesMaxY = seriesMinY = series.yData[i]; + } + else if (isNumber(series.yData[i]) && + isNumber(seriesMaxY) && + isNumber(seriesMinY)) { + seriesMaxX = Math.max(series.xData[i], seriesMaxX); + seriesMinX = Math.min(series.xData[i], seriesMinX); + seriesMaxY = Math.max(series.yData[i] || seriesMaxY, seriesMaxY); + seriesMinY = Math.min(series.yData[i] || seriesMinY, seriesMinY); + } + } + // Crop data to visible ones with appropriate offset to prevent + // cluster size changes on the edge of the plot area. + if (series.xData[i] >= (realExtremes.minX - cropDataOffsetX) && + series.xData[i] <= (realExtremes.maxX + cropDataOffsetX) && + (series.yData[i] || realExtremes.minY) >= + (realExtremes.minY - cropDataOffsetY) && + (series.yData[i] || realExtremes.maxY) <= + (realExtremes.maxY + cropDataOffsetY)) { + visibleXData.push(series.xData[i]); + visibleYData.push(series.yData[i]); + visibleDataIndexes.push(i); + } + } + // Save data max values. + if (defined(seriesMaxX) && defined(seriesMinX) && + isNumber(seriesMaxY) && isNumber(seriesMinY)) { + series.dataMaxX = seriesMaxX; + series.dataMinX = seriesMinX; + series.dataMaxY = seriesMaxY; + series.dataMinY = seriesMinY; + } + if (isFunction(type)) { + algorithm = type; + } + else if (series.markerClusterAlgorithms) { + if (type && series.markerClusterAlgorithms[type]) { + algorithm = series.markerClusterAlgorithms[type]; + } + else { + algorithm = visibleXData.length < kmeansThreshold ? + series.markerClusterAlgorithms.kmeans : + series.markerClusterAlgorithms.grid; + } + } + else { + algorithm = function () { + return false; + }; + } + groupedData = algorithm.call(this, visibleXData, visibleYData, visibleDataIndexes, layoutAlgOptions); + clusteredData = groupedData ? series.getClusteredData(groupedData, clusterOptions) : groupedData; + // When animation is enabled get old points state. + if (clusterOptions.animation && + series.markerClusterInfo && + series.markerClusterInfo.pointsState && + series.markerClusterInfo.pointsState.oldState) { + // Destroy old points. + destroyOldPoints(series.markerClusterInfo.pointsState.oldState); + oldPointsState = series.markerClusterInfo.pointsState.newState; + } + else { + oldPointsState = {}; + } + // Save points old state info. + oldDataLen = series.xData.length; + oldMarkerClusterInfo = series.markerClusterInfo; + if (clusteredData) { + series.processedXData = clusteredData.groupedXData; + series.processedYData = clusteredData.groupedYData; + series.hasGroupedData = true; + series.markerClusterInfo = clusteredData; + series.groupMap = clusteredData.groupMap; + } + baseGeneratePoints.apply(this); + if (clusteredData && series.markerClusterInfo) { + // Mark cluster points. Safe point reference in the cluster object. + (series.markerClusterInfo.clusters || []).forEach(function (cluster) { + point = series.points[cluster.index]; + point.isCluster = true; + point.clusteredData = cluster.data; + point.clusterPointsAmount = cluster.data.length; + cluster.point = point; + // Add zoom to cluster range. + addEvent(point, 'click', series.onDrillToCluster); + }); + // Safe point reference in the noise object. + (series.markerClusterInfo.noise || []).forEach(function (noise) { + noise.point = series.points[noise.index]; + }); + // When animation is enabled save points state. + if (clusterOptions.animation && + series.markerClusterInfo) { + series.markerClusterInfo.pointsState = { + oldState: oldPointsState, + newState: series.getPointsState(clusteredData, oldMarkerClusterInfo, oldDataLen) + }; + } + // Record grouped data in order to let it be destroyed the next time + // processData runs. + if (!clusterOptions.animation) { + this.destroyClusteredData(); + } + else { + this.hideClusteredData(); + } + this.markerClusterSeriesData = + this.hasGroupedData ? this.points : null; + } + } + else { + baseGeneratePoints.apply(this); + } + }; + // Handle animation. + addEvent(H.Chart, 'render', function () { + var chart = this; + (chart.series || []).forEach(function (series) { + if (series.markerClusterInfo) { + var options = series.options.cluster, pointsState = (series.markerClusterInfo || {}).pointsState, oldState = (pointsState || {}).oldState; + if ((options || {}).animation && + series.markerClusterInfo && + series.chart.pointer.pinchDown.length === 0 && + (series.xAxis.eventArgs || {}).trigger !== 'pan' && + oldState && + Object.keys(oldState).length) { + series.markerClusterInfo.clusters.forEach(function (cluster) { + series.animateClusterPoint(cluster); + }); + series.markerClusterInfo.noise.forEach(function (noise) { + series.animateClusterPoint(noise); + }); + } + } + }); + }); + // Override point prototype to throw a warning when trying to update + // clustered point. + addEvent(Point, 'update', function () { + if (this.dataGroup) { + error('Highcharts marker-clusters module: ' + + 'Running `Point.update` when point belongs to clustered series' + + ' is not supported.', false, this.series.chart); + return false; + } + }); + // Destroy grouped data on series destroy. + addEvent(Series, 'destroy', Scatter.prototype.destroyClusteredData); + // Add classes, change mouse cursor. + addEvent(Series, 'afterRender', function () { + var series = this, clusterZoomEnabled = (series.options.cluster || {}).drillToCluster; + if (series.markerClusterInfo && series.markerClusterInfo.clusters) { + series.markerClusterInfo.clusters.forEach(function (cluster) { + if (cluster.point && cluster.point.graphic) { + cluster.point.graphic.addClass('highcharts-cluster-point'); + // Change cursor to pointer when drillToCluster is enabled. + if (clusterZoomEnabled && cluster.point) { + cluster.point.graphic.css({ + cursor: 'pointer' + }); + if (cluster.point.dataLabel) { + cluster.point.dataLabel.css({ + cursor: 'pointer' + }); + } + } + if (defined(cluster.clusterZone)) { + cluster.point.graphic.addClass(cluster.clusterZoneClassName || + 'highcharts-cluster-zone-' + + cluster.clusterZone.zoneIndex); + } + } + }); + } + }); + addEvent(Point, 'drillToCluster', function (event) { + var point = event.point || event.target, series = point.series, clusterOptions = series.options.cluster, onDrillToCluster = ((clusterOptions || {}).events || {}).drillToCluster; + if (isFunction(onDrillToCluster)) { + onDrillToCluster.call(this, event); + } + }); + // Destroy the old tooltip after zoom. + addEvent(H.Axis, 'setExtremes', function () { + var chart = this.chart, animationDuration = 0, animation; + chart.series.forEach(function (series) { + if (series.markerClusterInfo) { + animation = animObject((series.options.cluster || {}).animation); + animationDuration = animation.duration || 0; + } + }); + syncTimeout(function () { + if (chart.tooltip) { + chart.tooltip.destroy(); + } + }, animationDuration); + }); + + }); + _registerModule(_modules, 'masters/modules/marker-clusters.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/networkgraph.js b/librerias/gantt/code/modules/networkgraph.js new file mode 100644 index 0000000..3ae7d51 --- /dev/null +++ b/librerias/gantt/code/modules/networkgraph.js @@ -0,0 +1,55 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Force directed graph module + + (c) 2010-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(h){"object"===typeof module&&module.exports?(h["default"]=h,module.exports=h):"function"===typeof define&&define.amd?define("highcharts/modules/networkgraph",["highcharts"],function(l){h(l);h.Highcharts=l;return h}):h("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(h){function l(g,a,c,e){g.hasOwnProperty(a)||(g[a]=e.apply(null,c))}h=h?h._modules:{};l(h,"mixins/nodes.js",[h["parts/Globals.js"],h["parts/Point.js"],h["parts/Utilities.js"]],function(g,a,c){var e=c.defined,d=c.extend, +f=c.find,m=c.pick;g.NodesMixin={createNode:function(e){function a(b,k){return f(b,function(b){return b.id===k})}var b=a(this.nodes,e),k=this.pointClass;if(!b){var q=this.options.nodes&&a(this.options.nodes,e);b=(new k).init(this,d({className:"highcharts-node",isNode:!0,id:e,y:1},q));b.linksTo=[];b.linksFrom=[];b.formatPrefix="node";b.name=b.name||b.options.id;b.mass=m(b.options.mass,b.options.marker&&b.options.marker.radius,this.options.marker&&this.options.marker.radius,4);b.getSum=function(){var k= +0,e=0;b.linksTo.forEach(function(b){k+=b.weight});b.linksFrom.forEach(function(b){e+=b.weight});return Math.max(k,e)};b.offset=function(k,e){for(var a=0,q=0;qa?1:0)},barycenter:function(){var a=this.options.gravitationalConstant,c=this.barycenter.xFactor,e=this.barycenter.yFactor;c=(c-(this.box.left+this.box.width)/2)*a;e= +(e-(this.box.top+this.box.height)/2)*a;this.nodes.forEach(function(a){a.fixedPosition||(a.plotX-=c/a.mass/a.degree,a.plotY-=e/a.mass/a.degree)})},repulsive:function(a,c,e){c=c*this.diffTemperature/a.mass/a.degree;a.fixedPosition||(a.plotX+=e.x*c,a.plotY+=e.y*c)},attractive:function(a,c,e){var d=a.getMass(),f=-e.x*c*this.diffTemperature;c=-e.y*c*this.diffTemperature;a.fromNode.fixedPosition||(a.fromNode.plotX-=f*d.fromNode/a.fromNode.degree,a.fromNode.plotY-=c*d.fromNode/a.fromNode.degree);a.toNode.fixedPosition|| +(a.toNode.plotX+=f*d.toNode/a.toNode.degree,a.toNode.plotY+=c*d.toNode/a.toNode.degree)},integrate:function(a,c){var e=-a.options.friction,d=a.options.maxSpeed,f=(c.plotX+c.dispX-c.prevX)*e;e*=c.plotY+c.dispY-c.prevY;var m=Math.abs,g=m(f)/(f||1);m=m(e)/(e||1);f=g*Math.min(d,Math.abs(f));e=m*Math.min(d,Math.abs(e));c.prevX=c.plotX+c.dispX;c.prevY=c.plotY+c.dispY;c.plotX+=f;c.plotY+=e;c.temperature=a.vectorLength({x:f,y:e})},getK:function(a){return Math.pow(a.box.width*a.box.height/a.nodes.length,.5)}}, +euler:{attractiveForceFunction:function(a,c){return a*a/c},repulsiveForceFunction:function(a,c){return c*c/a},barycenter:function(){var a=this.options.gravitationalConstant,c=this.barycenter.xFactor,e=this.barycenter.yFactor;this.nodes.forEach(function(d){if(!d.fixedPosition){var f=d.getDegree();f*=1+f/2;d.dispX+=(c-d.plotX)*a*f/d.degree;d.dispY+=(e-d.plotY)*a*f/d.degree}})},repulsive:function(a,c,e,d){a.dispX+=e.x/d*c/a.degree;a.dispY+=e.y/d*c/a.degree},attractive:function(a,c,e,d){var f=a.getMass(), +m=e.x/d*c;c*=e.y/d;a.fromNode.fixedPosition||(a.fromNode.dispX-=m*f.fromNode/a.fromNode.degree,a.fromNode.dispY-=c*f.fromNode/a.fromNode.degree);a.toNode.fixedPosition||(a.toNode.dispX+=m*f.toNode/a.toNode.degree,a.toNode.dispY+=c*f.toNode/a.toNode.degree)},integrate:function(a,c){c.dispX+=c.dispX*a.options.friction;c.dispY+=c.dispY*a.options.friction;var e=c.temperature=a.vectorLength({x:c.dispX,y:c.dispY});0!==e&&(c.plotX+=c.dispX/e*Math.min(Math.abs(c.dispX),a.temperature),c.plotY+=c.dispY/e*Math.min(Math.abs(c.dispY), +a.temperature))},getK:function(a){return Math.pow(a.box.width*a.box.height/a.nodes.length,.3)}}}});l(h,"modules/networkgraph/QuadTree.js",[h["parts/Globals.js"],h["parts/Utilities.js"]],function(g,a){a=a.extend;var c=g.QuadTreeNode=function(a){this.box=a;this.boxSize=Math.min(a.width,a.height);this.nodes=[];this.body=this.isInternal=!1;this.isEmpty=!0};a(c.prototype,{insert:function(a,d){this.isInternal?this.nodes[this.getBoxPosition(a)].insert(a,d-1):(this.isEmpty=!1,this.body?d?(this.isInternal= +!0,this.divideBox(),!0!==this.body&&(this.nodes[this.getBoxPosition(this.body)].insert(this.body,d-1),this.body=!0),this.nodes[this.getBoxPosition(a)].insert(a,d-1)):(d=new c({top:a.plotX,left:a.plotY,width:.1,height:.1}),d.body=a,d.isInternal=!1,this.nodes.push(d)):(this.isInternal=!1,this.body=a))},updateMassAndCenter:function(){var a=0,c=0,f=0;this.isInternal?(this.nodes.forEach(function(e){e.isEmpty||(a+=e.mass,c+=e.plotX*e.mass,f+=e.plotY*e.mass)}),c/=a,f/=a):this.body&&(a=this.body.mass,c=this.body.plotX, +f=this.body.plotY);this.mass=a;this.plotX=c;this.plotY=f},divideBox:function(){var a=this.box.width/2,d=this.box.height/2;this.nodes[0]=new c({left:this.box.left,top:this.box.top,width:a,height:d});this.nodes[1]=new c({left:this.box.left+a,top:this.box.top,width:a,height:d});this.nodes[2]=new c({left:this.box.left+a,top:this.box.top+d,width:a,height:d});this.nodes[3]=new c({left:this.box.left,top:this.box.top+d,width:a,height:d})},getBoxPosition:function(a){var c=a.plotYMath.abs(this.systemTemperature-this.prevSystemTemperature)||0>=this.temperature},getSystemTemperature:function(){return this.nodes.reduce(function(b,a){return b+a.temperature},0)},vectorLength:function(b){return Math.sqrt(b.x*b.x+b.y*b.y)},getDistR:function(b,a){b=this.getDistXY(b,a); +return this.vectorLength(b)},getDistXY:function(b,a){var c=b.plotX-a.plotX;b=b.plotY-a.plotY;return{x:c,y:b,absX:Math.abs(c),absY:Math.abs(b)}}});c(a,"predraw",function(){this.graphLayoutsLookup&&this.graphLayoutsLookup.forEach(function(b){b.stop()})});c(a,"render",function(){function b(b){b.maxIterations--&&isFinite(b.temperature)&&!b.isStable()&&!b.enableSimulation&&(b.beforeStep&&b.beforeStep(),b.step(),c=!1,a=!0)}var a=!1;if(this.graphLayoutsLookup){n(!1,this);for(this.graphLayoutsLookup.forEach(function(b){b.start()});!c;){var c= +!0;this.graphLayoutsLookup.forEach(b)}a&&this.series.forEach(function(b){b&&b.layout&&b.render()})}});c(a,"beforePrint",function(){this.graphLayoutsLookup.forEach(function(b){b.updateSimulation(!1)});this.redraw()});c(a,"afterPrint",function(){this.graphLayoutsLookup.forEach(function(b){b.updateSimulation()});this.redraw()})});l(h,"modules/networkgraph/draggable-nodes.js",[h["parts/Globals.js"],h["parts/Utilities.js"]],function(g,a){var c=a.addEvent;a=g.Chart;g.dragNodesMixin={onMouseDown:function(a, +c){c=this.chart.pointer.normalize(c);a.fixedPosition={chartX:c.chartX,chartY:c.chartY,plotX:a.plotX,plotY:a.plotY};a.inDragMode=!0},onMouseMove:function(a,c){if(a.fixedPosition&&a.inDragMode){var e=this.chart,d=e.pointer.normalize(c);c=a.fixedPosition.chartX-d.chartX;d=a.fixedPosition.chartY-d.chartY;if(5"+this.point.toNode.name},linkTextPath:{enabled:!0}, +textPath:{enabled:!1},style:{transition:"opacity 2000ms"}},link:{color:"rgba(100, 100, 100, 0.5)",width:1},draggable:!0,layoutAlgorithm:{initialPositions:"circle",initialPositionRadius:1,enableSimulation:!1,theta:.5,maxSpeed:10,approximation:"none",type:"reingold-fruchterman",integration:"euler",maxIterations:1E3,gravitationalConstant:.0625,friction:-.981},showInLegend:!1},{forces:["barycenter","repulsive","attractive"],hasDraggableNodes:!0,drawGraph:null,isCartesian:!1,requireSorting:!1,directTouch:!0, +noSharedTooltip:!0,pointArrayMap:["from","to"],trackerGroups:["group","markerGroup","dataLabelsGroup"],drawTracker:g.TrackerMixin.drawTrackerPoint,animate:null,buildKDTree:g.noop,createNode:g.NodesMixin.createNode,destroy:function(){this.layout.removeElementFromCollection(this,this.layout.series);g.NodesMixin.destroy.call(this)},init:function(){n.prototype.init.apply(this,arguments);e(this,"updatedData",function(){this.layout&&this.layout.stop()});return this},generatePoints:function(){var a;g.NodesMixin.generatePoints.apply(this, +arguments);this.options.nodes&&this.options.nodes.forEach(function(a){this.nodeLookup[a.id]||(this.nodeLookup[a.id]=this.createNode(a.id))},this);for(a=this.nodes.length-1;0<=a;a--){var b=this.nodes[a];b.degree=b.getDegree();b.radius=h(b.marker&&b.marker.radius,this.options.marker&&this.options.marker.radius,0);this.nodeLookup[b.id]||b.remove()}this.data.forEach(function(a){a.formatPrefix="link"});this.indexateNodes()},getPointsCollection:function(){return this.nodes||[]},indexateNodes:function(){this.nodes.forEach(function(a, +b){a.index=b})},markerAttribs:function(a,b){b=n.prototype.markerAttribs.call(this,a,b);f(a.plotY)||(b.y=0);b.x=(a.plotX||0)-(b.width/2||0);return b},translate:function(){this.processedXData||this.processData();this.generatePoints();this.deferLayout();this.nodes.forEach(function(a){a.isInside=!0;a.linksFrom.forEach(function(a){a.shapeType="path";a.y=1})})},deferLayout:function(){var a=this.options.layoutAlgorithm,b=this.chart.graphLayoutsStorage,c=this.chart.graphLayoutsLookup,e=this.chart.options.chart; +if(this.visible){b||(this.chart.graphLayoutsStorage=b={},this.chart.graphLayoutsLookup=c=[]);var d=b[a.type];d||(a.enableSimulation=f(e.forExport)?!e.forExport:a.enableSimulation,b[a.type]=d=new g.layouts[a.type],d.init(a),c.splice(d.index,0,d));this.layout=d;d.setArea(0,0,this.chart.plotWidth,this.chart.plotHeight);d.addElementsToCollection([this],d.series);d.addElementsToCollection(this.nodes,d.nodes);d.addElementsToCollection(this.points,d.links)}},render:function(){var a=this.points,b=this.chart.hoverPoint, +c=[];this.points=this.nodes;l.line.prototype.render.call(this);this.points=a;a.forEach(function(a){a.fromNode&&a.toNode&&(a.renderLink(),a.redrawLink())});b&&b.series===this&&this.redrawHalo(b);this.chart.hasRendered&&!this.options.dataLabels.allowOverlap&&(this.nodes.concat(this.points).forEach(function(a){a.dataLabel&&c.push(a.dataLabel)}),this.chart.hideOverlappingLabels(c))},drawDataLabels:function(){var a=this.options.dataLabels.textPath;n.prototype.drawDataLabels.apply(this,arguments);this.points= +this.data;this.options.dataLabels.textPath=this.options.dataLabels.linkTextPath;n.prototype.drawDataLabels.apply(this,arguments);this.points=this.nodes;this.options.dataLabels.textPath=a},pointAttribs:function(a,b){var c=b||a&&a.state||"normal";b=n.prototype.pointAttribs.call(this,a,c);c=this.options.states[c];a&&!a.isNode&&(b=a.getLinkAttributes(),c&&(b={stroke:c.linkColor||b.stroke,dashstyle:c.linkDashStyle||b.dashstyle,opacity:h(c.linkOpacity,b.opacity),"stroke-width":c.linkColor||b["stroke-width"]})); +return b},redrawHalo:b.redrawHalo,onMouseDown:b.onMouseDown,onMouseMove:b.onMouseMove,onMouseUp:b.onMouseUp,setState:function(a,b){b?(this.points=this.nodes.concat(this.data),n.prototype.setState.apply(this,arguments),this.points=this.data):n.prototype.setState.apply(this,arguments);this.layout.simulation||a||this.render()}},{setState:g.NodesMixin.setNodeState,init:function(){a.prototype.init.apply(this,arguments);this.series.options.draggable&&!this.series.chart.styledMode&&(e(this,"mouseOver",function(){d(this.series.chart.container, +{cursor:"move"})}),e(this,"mouseOut",function(){d(this.series.chart.container,{cursor:"default"})}));return this},getDegree:function(){var a=this.isNode?this.linksFrom.length+this.linksTo.length:0;return 0===a?1:a},getLinkAttributes:function(){var a=this.series.options.link,b=this.options;return{"stroke-width":h(b.width,a.width),stroke:b.color||a.color,dashstyle:b.dashStyle||a.dashStyle,opacity:h(b.opacity,a.opacity,1)}},renderLink:function(){if(!this.graphic&&(this.graphic=this.series.chart.renderer.path(this.getLinkPath()).add(this.series.group), +!this.series.chart.styledMode)){var a=this.series.pointAttribs(this);this.graphic.attr(a);(this.dataLabels||[]).forEach(function(b){b&&b.attr({opacity:a.opacity})})}},redrawLink:function(){var a=this.getLinkPath();if(this.graphic){this.shapeArgs={d:a};if(!this.series.chart.styledMode){var b=this.series.pointAttribs(this);this.graphic.attr(b);(this.dataLabels||[]).forEach(function(a){a&&a.attr({opacity:b.opacity})})}this.graphic.animate(this.shapeArgs);var c=a[0];a=a[1];"M"===c[0]&&"L"===a[0]&&(this.plotX= +(c[1]+a[1])/2,this.plotY=(c[2]+a[2])/2)}},getMass:function(){var a=this.fromNode.mass,b=this.toNode.mass,c=a+b;return{fromNode:1-a/c,toNode:1-b/c}},getLinkPath:function(){var a=this.fromNode,b=this.toNode;a.plotX>b.plotX&&(a=this.toNode,b=this.fromNode);return[["M",a.plotX||0,a.plotY||0],["L",b.plotX||0,b.plotY||0]]},isValid:function(){return!this.isNode||f(this.id)},remove:function(a,b){var c=this.series,e=c.options.nodes||[],d,f=e.length;if(this.isNode){c.points=[];[].concat(this.linksFrom).concat(this.linksTo).forEach(function(a){d= +a.fromNode.linksFrom.indexOf(a);-1 d ? 1 : 0); // Force only for close nodes + }, + /** + * Barycenter force. Calculate and applys barycenter forces on the + * nodes. Making them closer to the center of their barycenter point. + * + * In Verlet integration, force is applied on a node immidatelly to it's + * `plotX` and `plotY` position. + * + * @private + * @return {void} + */ + barycenter: function () { + var gravitationalConstant = this.options.gravitationalConstant, xFactor = this.barycenter.xFactor, yFactor = this.barycenter.yFactor; + // To consider: + xFactor = (xFactor - (this.box.left + this.box.width) / 2) * + gravitationalConstant; + yFactor = (yFactor - (this.box.top + this.box.height) / 2) * + gravitationalConstant; + this.nodes.forEach(function (node) { + if (!node.fixedPosition) { + node.plotX -= + xFactor / node.mass / node.degree; + node.plotY -= + yFactor / node.mass / node.degree; + } + }); + }, + /** + * Repulsive force. + * + * In Verlet integration, force is applied on a node immidatelly to it's + * `plotX` and `plotY` position. + * + * @private + * @param {Highcharts.Point} node + * Node that should be translated by force. + * @param {number} force + * Force calcualated in `repulsiveForceFunction` + * @param {Highcharts.PositionObject} distance + * Distance between two nodes e.g. `{x, y}` + * @return {void} + */ + repulsive: function (node, force, distanceXY) { + var factor = force * this.diffTemperature / node.mass / node.degree; + if (!node.fixedPosition) { + node.plotX += distanceXY.x * factor; + node.plotY += distanceXY.y * factor; + } + }, + /** + * Attractive force. + * + * In Verlet integration, force is applied on a node immidatelly to it's + * `plotX` and `plotY` position. + * + * @private + * @param {Highcharts.Point} link + * Link that connects two nodes + * @param {number} force + * Force calcualated in `repulsiveForceFunction` + * @param {Highcharts.PositionObject} distance + * Distance between two nodes e.g. `{x, y}` + * @return {void} + */ + attractive: function (link, force, distanceXY) { + var massFactor = link.getMass(), translatedX = -distanceXY.x * force * this.diffTemperature, translatedY = -distanceXY.y * force * this.diffTemperature; + if (!link.fromNode.fixedPosition) { + link.fromNode.plotX -= + translatedX * massFactor.fromNode / link.fromNode.degree; + link.fromNode.plotY -= + translatedY * massFactor.fromNode / link.fromNode.degree; + } + if (!link.toNode.fixedPosition) { + link.toNode.plotX += + translatedX * massFactor.toNode / link.toNode.degree; + link.toNode.plotY += + translatedY * massFactor.toNode / link.toNode.degree; + } + }, + /** + * Integration method. + * + * In Verlet integration, forces are applied on node immidatelly to it's + * `plotX` and `plotY` position. + * + * Verlet without velocity: + * + * x(n+1) = 2 * x(n) - x(n-1) + A(T) * deltaT ^ 2 + * + * where: + * - x(n+1) - new position + * - x(n) - current position + * - x(n-1) - previous position + * + * Assuming A(t) = 0 (no acceleration) and (deltaT = 1) we get: + * + * x(n+1) = x(n) + (x(n) - x(n-1)) + * + * where: + * - (x(n) - x(n-1)) - position change + * + * TO DO: + * Consider Verlet with velocity to support additional + * forces. Or even Time-Corrected Verlet by Jonathan + * "lonesock" Dummer + * + * @private + * @param {Highcharts.NetworkgraphLayout} layout layout object + * @param {Highcharts.Point} node node that should be translated + * @return {void} + */ + integrate: function (layout, node) { + var friction = -layout.options.friction, maxSpeed = layout.options.maxSpeed, prevX = node.prevX, prevY = node.prevY, + // Apply friciton: + diffX = ((node.plotX + node.dispX - + prevX) * friction), diffY = ((node.plotY + node.dispY - + prevY) * friction), abs = Math.abs, signX = abs(diffX) / (diffX || 1), // need to deal with 0 + signY = abs(diffY) / (diffY || 1); + // Apply max speed: + diffX = signX * Math.min(maxSpeed, Math.abs(diffX)); + diffY = signY * Math.min(maxSpeed, Math.abs(diffY)); + // Store for the next iteration: + node.prevX = node.plotX + node.dispX; + node.prevY = node.plotY + node.dispY; + // Update positions: + node.plotX += diffX; + node.plotY += diffY; + node.temperature = layout.vectorLength({ + x: diffX, + y: diffY + }); + }, + /** + * Estiamte the best possible distance between two nodes, making graph + * readable. + * + * @private + * @param {Highcharts.NetworkgraphLayout} layout layout object + * @return {number} + */ + getK: function (layout) { + return Math.pow(layout.box.width * layout.box.height / layout.nodes.length, 0.5); + } + }, + euler: { + /** + * Attractive force funtion. Can be replaced by API's + * `layoutAlgorithm.attractiveForce` + * + * Other forces that can be used: + * + * basic, not recommended: + * `function (d, k) { return d / k }` + * + * @private + * @param {number} d current distance between two nodes + * @param {number} k expected distance between two nodes + * @return {number} force + */ + attractiveForceFunction: function (d, k) { + return d * d / k; + }, + /** + * Repulsive force funtion. Can be replaced by API's + * `layoutAlgorithm.repulsiveForce`. + * + * Other forces that can be used: + * + * basic, not recommended: + * `function (d, k) { return k / d }` + * + * standard: + * `function (d, k) { return k * k / d }` + * + * grid-variant: + * `function (d, k) { return k * k / d * (2 * k - d > 0 ? 1 : 0) }` + * + * @private + * @param {number} d current distance between two nodes + * @param {number} k expected distance between two nodes + * @return {number} force + */ + repulsiveForceFunction: function (d, k) { + return k * k / d; + }, + /** + * Barycenter force. Calculate and applys barycenter forces on the + * nodes. Making them closer to the center of their barycenter point. + * + * In Euler integration, force is stored in a node, not changing it's + * position. Later, in `integrate()` forces are applied on nodes. + * + * @private + * @return {void} + */ + barycenter: function () { + var gravitationalConstant = this.options.gravitationalConstant, xFactor = this.barycenter.xFactor, yFactor = this.barycenter.yFactor; + this.nodes.forEach(function (node) { + if (!node.fixedPosition) { + var degree = node.getDegree(), phi = degree * (1 + degree / 2); + node.dispX += ((xFactor - node.plotX) * + gravitationalConstant * + phi / node.degree); + node.dispY += ((yFactor - node.plotY) * + gravitationalConstant * + phi / node.degree); + } + }); + }, + /** + * Repulsive force. + * + * @private + * @param {Highcharts.Point} node + * Node that should be translated by force. + * @param {number} force + * Force calcualated in `repulsiveForceFunction` + * @param {Highcharts.PositionObject} distanceXY + * Distance between two nodes e.g. `{x, y}` + * @return {void} + */ + repulsive: function (node, force, distanceXY, distanceR) { + node.dispX += + (distanceXY.x / distanceR) * force / node.degree; + node.dispY += + (distanceXY.y / distanceR) * force / node.degree; + }, + /** + * Attractive force. + * + * In Euler integration, force is stored in a node, not changing it's + * position. Later, in `integrate()` forces are applied on nodes. + * + * @private + * @param {Highcharts.Point} link + * Link that connects two nodes + * @param {number} force + * Force calcualated in `repulsiveForceFunction` + * @param {Highcharts.PositionObject} distanceXY + * Distance between two nodes e.g. `{x, y}` + * @param {number} distanceR + * @return {void} + */ + attractive: function (link, force, distanceXY, distanceR) { + var massFactor = link.getMass(), translatedX = (distanceXY.x / distanceR) * force, translatedY = (distanceXY.y / distanceR) * force; + if (!link.fromNode.fixedPosition) { + link.fromNode.dispX -= + translatedX * massFactor.fromNode / link.fromNode.degree; + link.fromNode.dispY -= + translatedY * massFactor.fromNode / link.fromNode.degree; + } + if (!link.toNode.fixedPosition) { + link.toNode.dispX += + translatedX * massFactor.toNode / link.toNode.degree; + link.toNode.dispY += + translatedY * massFactor.toNode / link.toNode.degree; + } + }, + /** + * Integration method. + * + * In Euler integration, force were stored in a node, not changing it's + * position. Now, in the integrator method, we apply changes. + * + * Euler: + * + * Basic form: `x(n+1) = x(n) + v(n)` + * + * With Rengoild-Fruchterman we get: + * `x(n+1) = x(n) + v(n) / length(v(n)) * min(v(n), temperature(n))` + * where: + * - `x(n+1)`: next position + * - `x(n)`: current position + * - `v(n)`: velocity (comes from net force) + * - `temperature(n)`: current temperature + * + * Known issues: + * Oscillations when force vector has the same magnitude but opposite + * direction in the next step. Potentially solved by decreasing force by + * `v * (1 / node.degree)` + * + * Note: + * Actually `min(v(n), temperature(n))` replaces simulated annealing. + * + * @private + * @param {Highcharts.NetworkgraphLayout} layout + * Layout object + * @param {Highcharts.Point} node + * Node that should be translated + * @return {void} + */ + integrate: function (layout, node) { + var distanceR; + node.dispX += + node.dispX * layout.options.friction; + node.dispY += + node.dispY * layout.options.friction; + distanceR = node.temperature = layout.vectorLength({ + x: node.dispX, + y: node.dispY + }); + if (distanceR !== 0) { + node.plotX += (node.dispX / distanceR * + Math.min(Math.abs(node.dispX), layout.temperature)); + node.plotY += (node.dispY / distanceR * + Math.min(Math.abs(node.dispY), layout.temperature)); + } + }, + /** + * Estiamte the best possible distance between two nodes, making graph + * readable. + * + * @private + * @param {object} layout layout object + * @return {number} + */ + getK: function (layout) { + return Math.pow(layout.box.width * layout.box.height / layout.nodes.length, 0.3); + } + } + }; + + }); + _registerModule(_modules, 'modules/networkgraph/QuadTree.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * Networkgraph series + * + * (c) 2010-2020 Paweł Fus + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The QuadTree node class. Used in Networkgraph chart as a base for Barnes-Hut + * approximation. + * + * @private + * @class + * @name Highcharts.QuadTreeNode + * + * @param {Highcharts.Dictionary} box Available space for the node + */ + var QuadTreeNode = H.QuadTreeNode = function (box) { + /** + * Read only. The available space for node. + * + * @name Highcharts.QuadTreeNode#box + * @type {Highcharts.Dictionary} + */ + this.box = box; + /** + * Read only. The minium of width and height values. + * + * @name Highcharts.QuadTreeNode#boxSize + * @type {number} + */ + this.boxSize = Math.min(box.width, box.height); + /** + * Read only. Array of subnodes. Empty if QuadTreeNode has just one Point. + * When added another Point to this QuadTreeNode, array is filled with four + * subnodes. + * + * @name Highcharts.QuadTreeNode#nodes + * @type {Array} + */ + this.nodes = []; + /** + * Read only. Flag to determine if QuadTreeNode is internal (and has + * subnodes with mass and central position) or external (bound to Point). + * + * @name Highcharts.QuadTreeNode#isInternal + * @type {boolean} + */ + this.isInternal = false; + /** + * Read only. If QuadTreeNode is an external node, Point is stored in + * `this.body`. + * + * @name Highcharts.QuadTreeNode#body + * @type {boolean|Highcharts.Point} + */ + this.body = false; + /** + * Read only. Internal nodes when created are empty to reserve the space. If + * Point is added to this QuadTreeNode, QuadTreeNode is no longer empty. + * + * @name Highcharts.QuadTreeNode#isEmpty + * @type {boolean} + */ + this.isEmpty = true; + }; + extend(QuadTreeNode.prototype, + /** @lends Highcharts.QuadTreeNode.prototype */ + { + /** + * Insert recursively point(node) into the QuadTree. If the given + * quadrant is already occupied, divide it into smaller quadrants. + * + * @param {Highcharts.Point} point + * Point/node to be inserted + * @param {number} depth + * Max depth of the QuadTree + */ + insert: function (point, depth) { + var newQuadTreeNode; + if (this.isInternal) { + // Internal node: + this.nodes[this.getBoxPosition(point)].insert(point, depth - 1); + } + else { + this.isEmpty = false; + if (!this.body) { + // First body in a quadrant: + this.isInternal = false; + this.body = point; + } + else { + if (depth) { + // Every other body in a quadrant: + this.isInternal = true; + this.divideBox(); + // Reinsert main body only once: + if (this.body !== true) { + this.nodes[this.getBoxPosition(this.body)] + .insert(this.body, depth - 1); + this.body = true; + } + // Add second body: + this.nodes[this.getBoxPosition(point)] + .insert(point, depth - 1); + } + else { + // We are below max allowed depth. That means either: + // - really huge number of points + // - falling two points into exactly the same position + // In this case, create another node in the QuadTree. + // + // Alternatively we could add some noise to the + // position, but that could result in different + // rendered chart in exporting. + newQuadTreeNode = new QuadTreeNode({ + top: point.plotX, + left: point.plotY, + // Width/height below 1px + width: 0.1, + height: 0.1 + }); + newQuadTreeNode.body = point; + newQuadTreeNode.isInternal = false; + this.nodes.push(newQuadTreeNode); + } + } + } + }, + /** + * Each quad node requires it's mass and center position. That mass and + * position is used to imitate real node in the layout by approximation. + */ + updateMassAndCenter: function () { + var mass = 0, plotX = 0, plotY = 0; + if (this.isInternal) { + // Calcualte weightened mass of the quad node: + this.nodes.forEach(function (pointMass) { + if (!pointMass.isEmpty) { + mass += pointMass.mass; + plotX += + pointMass.plotX * pointMass.mass; + plotY += + pointMass.plotY * pointMass.mass; + } + }); + plotX /= mass; + plotY /= mass; + } + else if (this.body) { + // Just one node, use coordinates directly: + mass = this.body.mass; + plotX = this.body.plotX; + plotY = this.body.plotY; + } + // Store details: + this.mass = mass; + this.plotX = plotX; + this.plotY = plotY; + }, + /** + * When inserting another node into the box, that already hove one node, + * divide the available space into another four quadrants. + * + * Indexes of quadrants are: + * ``` + * ------------- ------------- + * | | | | | + * | | | 0 | 1 | + * | | divide() | | | + * | 1 | -----------> ------------- + * | | | | | + * | | | 3 | 2 | + * | | | | | + * ------------- ------------- + * ``` + */ + divideBox: function () { + var halfWidth = this.box.width / 2, halfHeight = this.box.height / 2; + // Top left + this.nodes[0] = new QuadTreeNode({ + left: this.box.left, + top: this.box.top, + width: halfWidth, + height: halfHeight + }); + // Top right + this.nodes[1] = new QuadTreeNode({ + left: this.box.left + halfWidth, + top: this.box.top, + width: halfWidth, + height: halfHeight + }); + // Bottom right + this.nodes[2] = new QuadTreeNode({ + left: this.box.left + halfWidth, + top: this.box.top + halfHeight, + width: halfWidth, + height: halfHeight + }); + // Bottom left + this.nodes[3] = new QuadTreeNode({ + left: this.box.left, + top: this.box.top + halfHeight, + width: halfWidth, + height: halfHeight + }); + }, + /** + * Determine which of the quadrants should be used when placing node in + * the QuadTree. Returned index is always in range `< 0 , 3 >`. + * + * @param {Highcharts.Point} point + * @return {number} + */ + getBoxPosition: function (point) { + var left = point.plotX < this.box.left + this.box.width / 2, top = point.plotY < this.box.top + this.box.height / 2, index; + if (left) { + if (top) { + // Top left + index = 0; + } + else { + // Bottom left + index = 3; + } + } + else { + if (top) { + // Top right + index = 1; + } + else { + // Bottom right + index = 2; + } + } + return index; + } + }); + /** + * The QuadTree class. Used in Networkgraph chart as a base for Barnes-Hut + * approximation. + * + * @private + * @class + * @name Highcharts.QuadTree + * + * @param {number} x left position of the plotting area + * @param {number} y top position of the plotting area + * @param {number} width width of the plotting area + * @param {number} height height of the plotting area + */ + var QuadTree = H.QuadTree = function (x, y, width, height) { + // Boundary rectangle: + this.box = { + left: x, + top: y, + width: width, + height: height + }; + this.maxDepth = 25; + this.root = new QuadTreeNode(this.box, '0'); + this.root.isInternal = true; + this.root.isRoot = true; + this.root.divideBox(); + }; + extend(QuadTree.prototype, + /** @lends Highcharts.QuadTree.prototype */ + { + /** + * Insert nodes into the QuadTree + * + * @param {Array} points + */ + insertNodes: function (points) { + points.forEach(function (point) { + this.root.insert(point, this.maxDepth); + }, this); + }, + /** + * Depfth first treversal (DFS). Using `before` and `after` callbacks, + * we can get two results: preorder and postorder traversals, reminder: + * + * ``` + * (a) + * / \ + * (b) (c) + * / \ + * (d) (e) + * ``` + * + * DFS (preorder): `a -> b -> d -> e -> c` + * + * DFS (postorder): `d -> e -> b -> c -> a` + * + * @param {Highcharts.QuadTreeNode|null} node + * @param {Function} [beforeCallback] function to be called before + * visiting children nodes + * @param {Function} [afterCallback] function to be called after + * visiting children nodes + */ + visitNodeRecursive: function (node, beforeCallback, afterCallback) { + var goFurther; + if (!node) { + node = this.root; + } + if (node === this.root && beforeCallback) { + goFurther = beforeCallback(node); + } + if (goFurther === false) { + return; + } + node.nodes.forEach(function (qtNode) { + if (qtNode.isInternal) { + if (beforeCallback) { + goFurther = beforeCallback(qtNode); + } + if (goFurther === false) { + return; + } + this.visitNodeRecursive(qtNode, beforeCallback, afterCallback); + } + else if (qtNode.body) { + if (beforeCallback) { + beforeCallback(qtNode.body); + } + } + if (afterCallback) { + afterCallback(qtNode); + } + }, this); + if (node === this.root && afterCallback) { + afterCallback(node); + } + }, + /** + * Calculate mass of the each QuadNode in the tree. + */ + calculateMassAndCenter: function () { + this.visitNodeRecursive(null, null, function (node) { + node.updateMassAndCenter(); + }); + } + }); + + }); + _registerModule(_modules, 'modules/networkgraph/layouts.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * Networkgraph series + * + * (c) 2010-2020 Paweł Fus + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, merge = U.merge, clamp = U.clamp, defined = U.defined, extend = U.extend, isFunction = U.isFunction, pick = U.pick, setAnimation = U.setAnimation; + var Chart = H.Chart; + /* eslint-disable no-invalid-this, valid-jsdoc */ + H.layouts = { + 'reingold-fruchterman': function () { + } + }; + extend( + /** + * Reingold-Fruchterman algorithm from + * "Graph Drawing by Force-directed Placement" paper. + * @private + */ + H.layouts['reingold-fruchterman'].prototype, { + init: function (options) { + this.options = options; + this.nodes = []; + this.links = []; + this.series = []; + this.box = { + x: 0, + y: 0, + width: 0, + height: 0 + }; + this.setInitialRendering(true); + this.integration = + H.networkgraphIntegrations[options.integration]; + this.enableSimulation = options.enableSimulation; + this.attractiveForce = pick(options.attractiveForce, this.integration.attractiveForceFunction); + this.repulsiveForce = pick(options.repulsiveForce, this.integration.repulsiveForceFunction); + this.approximation = options.approximation; + }, + updateSimulation: function (enable) { + this.enableSimulation = pick(enable, this.options.enableSimulation); + }, + start: function () { + var layout = this, series = this.series, options = this.options; + layout.currentStep = 0; + layout.forces = series[0] && series[0].forces || []; + layout.chart = series[0] && series[0].chart; + if (layout.initialRendering) { + layout.initPositions(); + // Render elements in initial positions: + series.forEach(function (s) { + s.finishedAnimating = true; // #13169 + s.render(); + }); + } + layout.setK(); + layout.resetSimulation(options); + if (layout.enableSimulation) { + layout.step(); + } + }, + step: function () { + var layout = this, series = this.series, options = this.options; + // Algorithm: + layout.currentStep++; + if (layout.approximation === 'barnes-hut') { + layout.createQuadTree(); + layout.quadTree.calculateMassAndCenter(); + } + layout.forces.forEach(function (forceName) { + layout[forceName + 'Forces'](layout.temperature); + }); + // Limit to the plotting area and cool down: + layout.applyLimits(layout.temperature); + // Cool down the system: + layout.temperature = layout.coolDown(layout.startTemperature, layout.diffTemperature, layout.currentStep); + layout.prevSystemTemperature = layout.systemTemperature; + layout.systemTemperature = layout.getSystemTemperature(); + if (layout.enableSimulation) { + series.forEach(function (s) { + // Chart could be destroyed during the simulation + if (s.chart) { + s.render(); + } + }); + if (layout.maxIterations-- && + isFinite(layout.temperature) && + !layout.isStable()) { + if (layout.simulation) { + H.win.cancelAnimationFrame(layout.simulation); + } + layout.simulation = H.win.requestAnimationFrame(function () { + layout.step(); + }); + } + else { + layout.simulation = false; + } + } + }, + stop: function () { + if (this.simulation) { + H.win.cancelAnimationFrame(this.simulation); + } + }, + setArea: function (x, y, w, h) { + this.box = { + left: x, + top: y, + width: w, + height: h + }; + }, + setK: function () { + // Optimal distance between nodes, + // available space around the node: + this.k = this.options.linkLength || this.integration.getK(this); + }, + addElementsToCollection: function (elements, collection) { + elements.forEach(function (elem) { + if (collection.indexOf(elem) === -1) { + collection.push(elem); + } + }); + }, + removeElementFromCollection: function (element, collection) { + var index = collection.indexOf(element); + if (index !== -1) { + collection.splice(index, 1); + } + }, + clear: function () { + this.nodes.length = 0; + this.links.length = 0; + this.series.length = 0; + this.resetSimulation(); + }, + resetSimulation: function () { + this.forcedStop = false; + this.systemTemperature = 0; + this.setMaxIterations(); + this.setTemperature(); + this.setDiffTemperature(); + }, + setMaxIterations: function (maxIterations) { + this.maxIterations = pick(maxIterations, this.options.maxIterations); + }, + setTemperature: function () { + this.temperature = this.startTemperature = + Math.sqrt(this.nodes.length); + }, + setDiffTemperature: function () { + this.diffTemperature = this.startTemperature / + (this.options.maxIterations + 1); + }, + setInitialRendering: function (enable) { + this.initialRendering = enable; + }, + createQuadTree: function () { + this.quadTree = new H.QuadTree(this.box.left, this.box.top, this.box.width, this.box.height); + this.quadTree.insertNodes(this.nodes); + }, + initPositions: function () { + var initialPositions = this.options.initialPositions; + if (isFunction(initialPositions)) { + initialPositions.call(this); + this.nodes.forEach(function (node) { + if (!defined(node.prevX)) { + node.prevX = node.plotX; + } + if (!defined(node.prevY)) { + node.prevY = node.plotY; + } + node.dispX = 0; + node.dispY = 0; + }); + } + else if (initialPositions === 'circle') { + this.setCircularPositions(); + } + else { + this.setRandomPositions(); + } + }, + setCircularPositions: function () { + var box = this.box, nodes = this.nodes, nodesLength = nodes.length + 1, angle = 2 * Math.PI / nodesLength, rootNodes = nodes.filter(function (node) { + return node.linksTo.length === 0; + }), sortedNodes = [], visitedNodes = {}, radius = this.options.initialPositionRadius; + /** + * @private + */ + function addToNodes(node) { + node.linksFrom.forEach(function (link) { + if (!visitedNodes[link.toNode.id]) { + visitedNodes[link.toNode.id] = true; + sortedNodes.push(link.toNode); + addToNodes(link.toNode); + } + }); + } + // Start with identified root nodes an sort the nodes by their + // hierarchy. In trees, this ensures that branches don't cross + // eachother. + rootNodes.forEach(function (rootNode) { + sortedNodes.push(rootNode); + addToNodes(rootNode); + }); + // Cyclic tree, no root node found + if (!sortedNodes.length) { + sortedNodes = nodes; + // Dangling, cyclic trees + } + else { + nodes.forEach(function (node) { + if (sortedNodes.indexOf(node) === -1) { + sortedNodes.push(node); + } + }); + } + // Initial positions are laid out along a small circle, appearing + // as a cluster in the middle + sortedNodes.forEach(function (node, index) { + node.plotX = node.prevX = pick(node.plotX, box.width / 2 + radius * Math.cos(index * angle)); + node.plotY = node.prevY = pick(node.plotY, box.height / 2 + radius * Math.sin(index * angle)); + node.dispX = 0; + node.dispY = 0; + }); + }, + setRandomPositions: function () { + var box = this.box, nodes = this.nodes, nodesLength = nodes.length + 1; + /** + * Return a repeatable, quasi-random number based on an integer + * input. For the initial positions + * @private + */ + function unrandom(n) { + var rand = n * n / Math.PI; + rand = rand - Math.floor(rand); + return rand; + } + // Initial positions: + nodes.forEach(function (node, index) { + node.plotX = node.prevX = pick(node.plotX, box.width * unrandom(index)); + node.plotY = node.prevY = pick(node.plotY, box.height * unrandom(nodesLength + index)); + node.dispX = 0; + node.dispY = 0; + }); + }, + force: function (name) { + this.integration[name].apply(this, Array.prototype.slice.call(arguments, 1)); + }, + barycenterForces: function () { + this.getBarycenter(); + this.force('barycenter'); + }, + getBarycenter: function () { + var systemMass = 0, cx = 0, cy = 0; + this.nodes.forEach(function (node) { + cx += node.plotX * node.mass; + cy += node.plotY * node.mass; + systemMass += node.mass; + }); + this.barycenter = { + x: cx, + y: cy, + xFactor: cx / systemMass, + yFactor: cy / systemMass + }; + return this.barycenter; + }, + barnesHutApproximation: function (node, quadNode) { + var layout = this, distanceXY = layout.getDistXY(node, quadNode), distanceR = layout.vectorLength(distanceXY), goDeeper, force; + if (node !== quadNode && distanceR !== 0) { + if (quadNode.isInternal) { + // Internal node: + if (quadNode.boxSize / distanceR < + layout.options.theta && + distanceR !== 0) { + // Treat as an external node: + force = layout.repulsiveForce(distanceR, layout.k); + layout.force('repulsive', node, force * quadNode.mass, distanceXY, distanceR); + goDeeper = false; + } + else { + // Go deeper: + goDeeper = true; + } + } + else { + // External node, direct force: + force = layout.repulsiveForce(distanceR, layout.k); + layout.force('repulsive', node, force * quadNode.mass, distanceXY, distanceR); + } + } + return goDeeper; + }, + repulsiveForces: function () { + var layout = this; + if (layout.approximation === 'barnes-hut') { + layout.nodes.forEach(function (node) { + layout.quadTree.visitNodeRecursive(null, function (quadNode) { + return layout.barnesHutApproximation(node, quadNode); + }); + }); + } + else { + layout.nodes.forEach(function (node) { + layout.nodes.forEach(function (repNode) { + var force, distanceR, distanceXY; + if ( + // Node can not repulse itself: + node !== repNode && + // Only close nodes affect each other: + // layout.getDistR(node, repNode) < 2 * k && + // Not dragged: + !node.fixedPosition) { + distanceXY = layout.getDistXY(node, repNode); + distanceR = layout.vectorLength(distanceXY); + if (distanceR !== 0) { + force = layout.repulsiveForce(distanceR, layout.k); + layout.force('repulsive', node, force * repNode.mass, distanceXY, distanceR); + } + } + }); + }); + } + }, + attractiveForces: function () { + var layout = this, distanceXY, distanceR, force; + layout.links.forEach(function (link) { + if (link.fromNode && link.toNode) { + distanceXY = layout.getDistXY(link.fromNode, link.toNode); + distanceR = layout.vectorLength(distanceXY); + if (distanceR !== 0) { + force = layout.attractiveForce(distanceR, layout.k); + layout.force('attractive', link, force, distanceXY, distanceR); + } + } + }); + }, + applyLimits: function () { + var layout = this, nodes = layout.nodes; + nodes.forEach(function (node) { + if (node.fixedPosition) { + return; + } + layout.integration.integrate(layout, node); + layout.applyLimitBox(node, layout.box); + // Reset displacement: + node.dispX = 0; + node.dispY = 0; + }); + }, + /** + * External box that nodes should fall. When hitting an edge, node + * should stop or bounce. + * @private + */ + applyLimitBox: function (node, box) { + var radius = node.radius; + /* + TO DO: Consider elastic collision instead of stopping. + o' means end position when hitting plotting area edge: + + - "inelastic": + o + \ + ______ + | o' + | \ + | \ + + - "elastic"/"bounced": + o + \ + ______ + | ^ + | / \ + |o' \ + + Euler sample: + if (plotX < 0) { + plotX = 0; + dispX *= -1; + } + + if (plotX > box.width) { + plotX = box.width; + dispX *= -1; + } + + */ + // Limit X-coordinates: + node.plotX = clamp(node.plotX, box.left + radius, box.width - radius); + // Limit Y-coordinates: + node.plotY = clamp(node.plotY, box.top + radius, box.height - radius); + }, + /** + * From "A comparison of simulated annealing cooling strategies" by + * Nourani and Andresen work. + * @private + */ + coolDown: function (temperature, temperatureStep, currentStep) { + // Logarithmic: + /* + return Math.sqrt(this.nodes.length) - + Math.log( + currentStep * layout.diffTemperature + ); + */ + // Exponential: + /* + var alpha = 0.1; + layout.temperature = Math.sqrt(layout.nodes.length) * + Math.pow(alpha, layout.diffTemperature); + */ + // Linear: + return temperature - temperatureStep * currentStep; + }, + isStable: function () { + return Math.abs(this.systemTemperature - + this.prevSystemTemperature) < 0.00001 || this.temperature <= 0; + }, + getSystemTemperature: function () { + return this.nodes.reduce(function (value, node) { + return value + node.temperature; + }, 0); + }, + vectorLength: function (vector) { + return Math.sqrt(vector.x * vector.x + vector.y * vector.y); + }, + getDistR: function (nodeA, nodeB) { + var distance = this.getDistXY(nodeA, nodeB); + return this.vectorLength(distance); + }, + getDistXY: function (nodeA, nodeB) { + var xDist = nodeA.plotX - nodeB.plotX, yDist = nodeA.plotY - nodeB.plotY; + return { + x: xDist, + y: yDist, + absX: Math.abs(xDist), + absY: Math.abs(yDist) + }; + } + }); + /* ************************************************************************** * + * Multiple series support: + * ************************************************************************** */ + // Clear previous layouts + addEvent(Chart, 'predraw', function () { + if (this.graphLayoutsLookup) { + this.graphLayoutsLookup.forEach(function (layout) { + layout.stop(); + }); + } + }); + addEvent(Chart, 'render', function () { + var systemsStable, afterRender = false; + /** + * @private + */ + function layoutStep(layout) { + if (layout.maxIterations-- && + isFinite(layout.temperature) && + !layout.isStable() && + !layout.enableSimulation) { + // Hook similar to build-in addEvent, but instead of + // creating whole events logic, use just a function. + // It's faster which is important for rAF code. + // Used e.g. in packed-bubble series for bubble radius + // calculations + if (layout.beforeStep) { + layout.beforeStep(); + } + layout.step(); + systemsStable = false; + afterRender = true; + } + } + if (this.graphLayoutsLookup) { + setAnimation(false, this); + // Start simulation + this.graphLayoutsLookup.forEach(function (layout) { + layout.start(); + }); + // Just one sync step, to run different layouts similar to + // async mode. + while (!systemsStable) { + systemsStable = true; + this.graphLayoutsLookup.forEach(layoutStep); + } + if (afterRender) { + this.series.forEach(function (s) { + if (s && s.layout) { + s.render(); + } + }); + } + } + }); + // disable simulation before print if enabled + addEvent(Chart, 'beforePrint', function () { + this.graphLayoutsLookup.forEach(function (layout) { + layout.updateSimulation(false); + }); + this.redraw(); + }); + // re-enable simulation after print + addEvent(Chart, 'afterPrint', function () { + this.graphLayoutsLookup.forEach(function (layout) { + // return to default simulation + layout.updateSimulation(); + }); + this.redraw(); + }); + + }); + _registerModule(_modules, 'modules/networkgraph/draggable-nodes.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * Networkgraph series + * + * (c) 2010-2020 Paweł Fus + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent; + var Chart = H.Chart; + /* eslint-disable no-invalid-this, valid-jsdoc */ + H.dragNodesMixin = { + /** + * Mouse down action, initializing drag&drop mode. + * + * @private + * @param {Highcharts.Point} point The point that event occured. + * @param {Highcharts.PointerEventObject} event Browser event, before normalization. + * @return {void} + */ + onMouseDown: function (point, event) { + var normalizedEvent = this.chart.pointer.normalize(event); + point.fixedPosition = { + chartX: normalizedEvent.chartX, + chartY: normalizedEvent.chartY, + plotX: point.plotX, + plotY: point.plotY + }; + point.inDragMode = true; + }, + /** + * Mouse move action during drag&drop. + * + * @private + * + * @param {global.Event} event Browser event, before normalization. + * @param {Highcharts.Point} point The point that event occured. + * + * @return {void} + */ + onMouseMove: function (point, event) { + if (point.fixedPosition && point.inDragMode) { + var series = this, chart = series.chart, normalizedEvent = chart.pointer.normalize(event), diffX = point.fixedPosition.chartX - normalizedEvent.chartX, diffY = point.fixedPosition.chartY - normalizedEvent.chartY, newPlotX, newPlotY; + // At least 5px to apply change (avoids simple click): + if (Math.abs(diffX) > 5 || Math.abs(diffY) > 5) { + newPlotX = point.fixedPosition.plotX - diffX; + newPlotY = point.fixedPosition.plotY - diffY; + if (chart.isInsidePlot(newPlotX, newPlotY)) { + point.plotX = newPlotX; + point.plotY = newPlotY; + point.hasDragged = true; + this.redrawHalo(point); + if (!series.layout.simulation) { + // When dragging nodes, we don't need to calculate + // initial positions and rendering nodes: + series.layout.setInitialRendering(false); + // Start new simulation: + if (!series.layout.enableSimulation) { + // Run only one iteration to speed things up: + series.layout.setMaxIterations(1); + } + else { + series.layout.start(); + } + series.chart.redraw(); + // Restore defaults: + series.layout.setInitialRendering(true); + } + else { + // Extend current simulation: + series.layout.resetSimulation(); + } + } + } + } + }, + /** + * Mouse up action, finalizing drag&drop. + * + * @private + * @param {Highcharts.Point} point The point that event occured. + * @return {void} + */ + onMouseUp: function (point, event) { + if (point.fixedPosition && point.hasDragged) { + if (this.layout.enableSimulation) { + this.layout.start(); + } + else { + this.chart.redraw(); + } + point.inDragMode = point.hasDragged = false; + if (!this.options.fixedDraggable) { + delete point.fixedPosition; + } + } + }, + // Draggable mode: + /** + * Redraw halo on mousemove during the drag&drop action. + * + * @private + * @param {Highcharts.Point} point The point that should show halo. + * @return {void} + */ + redrawHalo: function (point) { + if (point && this.halo) { + this.halo.attr({ + d: point.haloPath(this.options.states.hover.halo.size) + }); + } + } + }; + /* + * Draggable mode: + */ + addEvent(Chart, 'load', function () { + var chart = this, mousedownUnbinder, mousemoveUnbinder, mouseupUnbinder; + if (chart.container) { + mousedownUnbinder = addEvent(chart.container, 'mousedown', function (event) { + var point = chart.hoverPoint; + if (point && + point.series && + point.series.hasDraggableNodes && + point.series.options.draggable) { + point.series.onMouseDown(point, event); + mousemoveUnbinder = addEvent(chart.container, 'mousemove', function (e) { + return point && + point.series && + point.series.onMouseMove(point, e); + }); + mouseupUnbinder = addEvent(chart.container.ownerDocument, 'mouseup', function (e) { + mousemoveUnbinder(); + mouseupUnbinder(); + return point && + point.series && + point.series.onMouseUp(point, e); + }); + } + }); + } + addEvent(chart, 'destroy', function () { + mousedownUnbinder(); + }); + }); + + }); + _registerModule(_modules, 'modules/networkgraph/networkgraph.src.js', [_modules['parts/Globals.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js']], function (H, Point, U) { + /* * + * + * Networkgraph series + * + * (c) 2010-2020 Paweł Fus + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Formatter callback function. + * + * @callback Highcharts.SeriesNetworkgraphDataLabelsFormatterCallbackFunction + * + * @param {Highcharts.SeriesNetworkgraphDataLabelsFormatterContextObject|Highcharts.PointLabelObject} this + * Data label context to format + * + * @return {string} + * Formatted data label text + */ + /** + * Context for the formatter function. + * + * @interface Highcharts.SeriesNetworkgraphDataLabelsFormatterContextObject + * @extends Highcharts.PointLabelObject + * @since 7.0.0 + */ /** + * The color of the node. + * @name Highcharts.SeriesNetworkgraphDataLabelsFormatterContextObject#color + * @type {Highcharts.ColorString} + * @since 7.0.0 + */ /** + * The point (node) object. The node name, if defined, is available through + * `this.point.name`. Arrays: `this.point.linksFrom` and `this.point.linksTo` + * contains all nodes connected to this point. + * @name Highcharts.SeriesNetworkgraphDataLabelsFormatterContextObject#point + * @type {Highcharts.Point} + * @since 7.0.0 + */ /** + * The ID of the node. + * @name Highcharts.SeriesNetworkgraphDataLabelsFormatterContextObject#key + * @type {string} + * @since 7.0.0 + */ + ''; // detach doclets above + var addEvent = U.addEvent, css = U.css, defined = U.defined, pick = U.pick, seriesType = U.seriesType; + var seriesTypes = H.seriesTypes, Series = H.Series, dragNodesMixin = H.dragNodesMixin; + /** + * @private + * @class + * @name Highcharts.seriesTypes.networkgraph + * + * @extends Highcharts.Series + */ + seriesType('networkgraph', 'line', + /** + * A networkgraph is a type of relationship chart, where connnections + * (links) attracts nodes (points) and other nodes repulse each other. + * + * @extends plotOptions.line + * @product highcharts + * @sample highcharts/demo/network-graph/ + * Networkgraph + * @since 7.0.0 + * @excluding boostThreshold, animation, animationLimit, connectEnds, + * colorAxis, colorKey, connectNulls, dragDrop, + * getExtremesFromAll, label, linecap, negativeColor, + * pointInterval, pointIntervalUnit, pointPlacement, + * pointStart, softThreshold, stack, stacking, step, + * threshold, xAxis, yAxis, zoneAxis, dataSorting + * @requires modules/networkgraph + * @optionparent plotOptions.networkgraph + */ + { + stickyTracking: false, + /** + * @ignore-option + * @private + */ + inactiveOtherPoints: true, + marker: { + enabled: true, + states: { + /** + * The opposite state of a hover for a single point node. + * Applied to all not connected nodes to the hovered one. + * + * @declare Highcharts.PointStatesInactiveOptionsObject + */ + inactive: { + /** + * Opacity of inactive markers. + */ + opacity: 0.3, + /** + * Animation when not hovering over the node. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + */ + animation: { + /** @internal */ + duration: 50 + } + } + } + }, + states: { + /** + * The opposite state of a hover for a single point link. Applied + * to all links that are not comming from the hovered node. + * + * @declare Highcharts.SeriesStatesInactiveOptionsObject + */ + inactive: { + /** + * Opacity of inactive links. + */ + linkOpacity: 0.3, + /** + * Animation when not hovering over the node. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + */ + animation: { + /** @internal */ + duration: 50 + } + } + }, + /** + * @sample highcharts/series-networkgraph/link-datalabels + * Networkgraph with labels on links + * @sample highcharts/series-networkgraph/textpath-datalabels + * Networkgraph with labels around nodes + * @sample highcharts/series-networkgraph/link-datalabels + * Data labels moved into the nodes + * @sample highcharts/series-networkgraph/link-datalabels + * Data labels moved under the links + * + * @declare Highcharts.SeriesNetworkgraphDataLabelsOptionsObject + * + * @private + */ + dataLabels: { + /** + * The + * [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) + * specifying what to show for _node_ in the networkgraph. In v7.0 + * defaults to `{key}`, since v7.1 defaults to `undefined` and + * `formatter` is used instead. + * + * @type {string} + * @since 7.0.0 + * @apioption plotOptions.networkgraph.dataLabels.format + */ + // eslint-disable-next-line valid-jsdoc + /** + * Callback JavaScript function to format the data label for a node. + * Note that if a `format` is defined, the format takes precedence + * and the formatter is ignored. + * + * @type {Highcharts.SeriesNetworkgraphDataLabelsFormatterCallbackFunction} + * @since 7.0.0 + */ + formatter: function () { + return this.key; + }, + /** + * The + * [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) + * specifying what to show for _links_ in the networkgraph. + * (Default: `undefined`) + * + * @type {string} + * @since 7.1.0 + * @apioption plotOptions.networkgraph.dataLabels.linkFormat + */ + // eslint-disable-next-line valid-jsdoc + /** + * Callback to format data labels for _links_ in the sankey diagram. + * The `linkFormat` option takes precedence over the + * `linkFormatter`. + * + * @type {Highcharts.SeriesNetworkgraphDataLabelsFormatterCallbackFunction} + * @since 7.1.0 + */ + linkFormatter: function () { + return (this.point.fromNode.name + + '
    ' + + this.point.toNode.name); + }, + /** + * Options for a _link_ label text which should follow link + * connection. Border and background are disabled for a label that + * follows a path. + * + * **Note:** Only SVG-based renderer supports this option. Setting + * `useHTML` to true will disable this option. + * + * @extends plotOptions.networkgraph.dataLabels.textPath + * @since 7.1.0 + */ + linkTextPath: { + enabled: true + }, + textPath: { + enabled: false + }, + style: { + transition: 'opacity 2000ms' + } + }, + /** + * Link style options + * @private + */ + link: { + /** + * A name for the dash style to use for links. + * + * @type {string} + * @apioption plotOptions.networkgraph.link.dashStyle + */ + /** + * Color of the link between two nodes. + */ + color: 'rgba(100, 100, 100, 0.5)', + /** + * Width (px) of the link between two nodes. + */ + width: 1 + }, + /** + * Flag to determine if nodes are draggable or not. + * @private + */ + draggable: true, + layoutAlgorithm: { + /** + * Repulsive force applied on a node. Passed are two arguments: + * - `d` - which is current distance between two nodes + * - `k` - which is desired distance between two nodes + * + * In `verlet` integration, defaults to: + * `function (d, k) { return (k - d) / d * (k > d ? 1 : 0) }` + * + * @see [layoutAlgorithm.integration](#series.networkgraph.layoutAlgorithm.integration) + * + * @sample highcharts/series-networkgraph/forces/ + * Custom forces with Euler integration + * @sample highcharts/series-networkgraph/cuboids/ + * Custom forces with Verlet integration + * + * @type {Function} + * @default function (d, k) { return k * k / d; } + * @apioption plotOptions.networkgraph.layoutAlgorithm.repulsiveForce + */ + /** + * Attraction force applied on a node which is conected to another + * node by a link. Passed are two arguments: + * - `d` - which is current distance between two nodes + * - `k` - which is desired distance between two nodes + * + * In `verlet` integration, defaults to: + * `function (d, k) { return (k - d) / d; }` + * + * @see [layoutAlgorithm.integration](#series.networkgraph.layoutAlgorithm.integration) + * + * @sample highcharts/series-networkgraph/forces/ + * Custom forces with Euler integration + * @sample highcharts/series-networkgraph/cuboids/ + * Custom forces with Verlet integration + * + * @type {Function} + * @default function (d, k) { return k * k / d; } + * @apioption plotOptions.networkgraph.layoutAlgorithm.attractiveForce + */ + /** + * Ideal length (px) of the link between two nodes. When not + * defined, length is calculated as: + * `Math.pow(availableWidth * availableHeight / nodesLength, 0.4);` + * + * Note: Because of the algorithm specification, length of each link + * might be not exactly as specified. + * + * @sample highcharts/series-networkgraph/styled-links/ + * Numerical values + * + * @type {number} + * @apioption plotOptions.networkgraph.layoutAlgorithm.linkLength + */ + /** + * Initial layout algorithm for positioning nodes. Can be one of + * built-in options ("circle", "random") or a function where + * positions should be set on each node (`this.nodes`) as + * `node.plotX` and `node.plotY` + * + * @sample highcharts/series-networkgraph/initial-positions/ + * Initial positions with callback + * + * @type {"circle"|"random"|Function} + */ + initialPositions: 'circle', + /** + * When `initialPositions` are set to 'circle', + * `initialPositionRadius` is a distance from the center of circle, + * in which nodes are created. + * + * @type {number} + * @default 1 + * @since 7.1.0 + */ + initialPositionRadius: 1, + /** + * Experimental. Enables live simulation of the algorithm + * implementation. All nodes are animated as the forces applies on + * them. + * + * @sample highcharts/demo/network-graph/ + * Live simulation enabled + */ + enableSimulation: false, + /** + * Barnes-Hut approximation only. + * Deteremines when distance between cell and node is small enough + * to caculate forces. Value of `theta` is compared directly with + * quotient `s / d`, where `s` is the size of the cell, and `d` is + * distance between center of cell's mass and currently compared + * node. + * + * @see [layoutAlgorithm.approximation](#series.networkgraph.layoutAlgorithm.approximation) + * + * @since 7.1.0 + */ + theta: 0.5, + /** + * Verlet integration only. + * Max speed that node can get in one iteration. In terms of + * simulation, it's a maximum translation (in pixels) that node can + * move (in both, x and y, dimensions). While `friction` is applied + * on all nodes, max speed is applied only for nodes that move very + * fast, for example small or disconnected ones. + * + * @see [layoutAlgorithm.integration](#series.networkgraph.layoutAlgorithm.integration) + * @see [layoutAlgorithm.friction](#series.networkgraph.layoutAlgorithm.friction) + * + * @since 7.1.0 + */ + maxSpeed: 10, + /** + * Approximation used to calculate repulsive forces affecting nodes. + * By default, when calculateing net force, nodes are compared + * against each other, which gives O(N^2) complexity. Using + * Barnes-Hut approximation, we decrease this to O(N log N), but the + * resulting graph will have different layout. Barnes-Hut + * approximation divides space into rectangles via quad tree, where + * forces exerted on nodes are calculated directly for nearby cells, + * and for all others, cells are treated as a separate node with + * center of mass. + * + * @see [layoutAlgorithm.theta](#series.networkgraph.layoutAlgorithm.theta) + * + * @sample highcharts/series-networkgraph/barnes-hut-approximation/ + * A graph with Barnes-Hut approximation + * + * @type {string} + * @validvalue ["barnes-hut", "none"] + * @since 7.1.0 + */ + approximation: 'none', + /** + * Type of the algorithm used when positioning nodes. + * + * @type {string} + * @validvalue ["reingold-fruchterman"] + */ + type: 'reingold-fruchterman', + /** + * Integration type. Available options are `'euler'` and `'verlet'`. + * Integration determines how forces are applied on particles. In + * Euler integration, force is applied direct as + * `newPosition += velocity;`. + * In Verlet integration, new position is based on a previous + * posittion without velocity: + * `newPosition += previousPosition - newPosition`. + * + * Note that different integrations give different results as forces + * are different. + * + * In Highcharts v7.0.x only `'euler'` integration was supported. + * + * @sample highcharts/series-networkgraph/integration-comparison/ + * Comparison of Verlet and Euler integrations + * + * @type {string} + * @validvalue ["euler", "verlet"] + * @since 7.1.0 + */ + integration: 'euler', + /** + * Max number of iterations before algorithm will stop. In general, + * algorithm should find positions sooner, but when rendering huge + * number of nodes, it is recommended to increase this value as + * finding perfect graph positions can require more time. + */ + maxIterations: 1000, + /** + * Gravitational const used in the barycenter force of the + * algorithm. + * + * @sample highcharts/series-networkgraph/forces/ + * Custom forces with Euler integration + */ + gravitationalConstant: 0.0625, + /** + * Friction applied on forces to prevent nodes rushing to fast to + * the desired positions. + */ + friction: -0.981 + }, + showInLegend: false + }, { + /** + * Array of internal forces. Each force should be later defined in + * integrations.js. + * @private + */ + forces: ['barycenter', 'repulsive', 'attractive'], + hasDraggableNodes: true, + drawGraph: null, + isCartesian: false, + requireSorting: false, + directTouch: true, + noSharedTooltip: true, + pointArrayMap: ['from', 'to'], + trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'], + drawTracker: H.TrackerMixin.drawTrackerPoint, + // Animation is run in `series.simulation`. + animate: null, + buildKDTree: H.noop, + /** + * Create a single node that holds information on incoming and outgoing + * links. + * @private + */ + createNode: H.NodesMixin.createNode, + destroy: function () { + this.layout.removeElementFromCollection(this, this.layout.series); + H.NodesMixin.destroy.call(this); + }, + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Extend init with base event, which should stop simulation during + * update. After data is updated, `chart.render` resumes the simulation. + * @private + */ + init: function () { + Series.prototype.init.apply(this, arguments); + addEvent(this, 'updatedData', function () { + if (this.layout) { + this.layout.stop(); + } + }); + return this; + }, + /** + * Extend generatePoints by adding the nodes, which are Point objects + * but pushed to the this.nodes array. + * @private + */ + generatePoints: function () { + var node, i; + H.NodesMixin.generatePoints.apply(this, arguments); + // In networkgraph, it's fine to define stanalone nodes, create + // them: + if (this.options.nodes) { + this.options.nodes.forEach(function (nodeOptions) { + if (!this.nodeLookup[nodeOptions.id]) { + this.nodeLookup[nodeOptions.id] = + this.createNode(nodeOptions.id); + } + }, this); + } + for (i = this.nodes.length - 1; i >= 0; i--) { + node = this.nodes[i]; + node.degree = node.getDegree(); + node.radius = pick(node.marker && node.marker.radius, this.options.marker && this.options.marker.radius, 0); + // If node exists, but it's not available in nodeLookup, + // then it's leftover from previous runs (e.g. setData) + if (!this.nodeLookup[node.id]) { + node.remove(); + } + } + this.data.forEach(function (link) { + link.formatPrefix = 'link'; + }); + this.indexateNodes(); + }, + /** + * In networkgraph, series.points refers to links, + * but series.nodes refers to actual points. + * @private + */ + getPointsCollection: function () { + return this.nodes || []; + }, + /** + * Set index for each node. Required for proper `node.update()`. + * Note that links are indexated out of the box in `generatePoints()`. + * + * @private + */ + indexateNodes: function () { + this.nodes.forEach(function (node, index) { + node.index = index; + }); + }, + /** + * Extend the default marker attribs by using a non-rounded X position, + * otherwise the nodes will jump from pixel to pixel which looks a bit + * jaggy when approaching equilibrium. + * @private + */ + markerAttribs: function (point, state) { + var attribs = Series.prototype.markerAttribs.call(this, point, state); + // series.render() is called before initial positions are set: + if (!defined(point.plotY)) { + attribs.y = 0; + } + attribs.x = (point.plotX || 0) - (attribs.width / 2 || 0); + return attribs; + }, + /** + * Run pre-translation and register nodes&links to the deffered layout. + * @private + */ + translate: function () { + if (!this.processedXData) { + this.processData(); + } + this.generatePoints(); + this.deferLayout(); + this.nodes.forEach(function (node) { + // Draw the links from this node + node.isInside = true; + node.linksFrom.forEach(function (point) { + point.shapeType = 'path'; + // Pass test in drawPoints + point.y = 1; + }); + }); + }, + /** + * Defer the layout. + * Each series first registers all nodes and links, then layout + * calculates all nodes positions and calls `series.render()` in every + * simulation step. + * + * Note: + * Animation is done through `requestAnimationFrame` directly, without + * `Highcharts.animate()` use. + * @private + */ + deferLayout: function () { + var layoutOptions = this.options.layoutAlgorithm, graphLayoutsStorage = this.chart.graphLayoutsStorage, graphLayoutsLookup = this.chart.graphLayoutsLookup, chartOptions = this.chart.options.chart, layout; + if (!this.visible) { + return; + } + if (!graphLayoutsStorage) { + this.chart.graphLayoutsStorage = graphLayoutsStorage = {}; + this.chart.graphLayoutsLookup = graphLayoutsLookup = []; + } + layout = graphLayoutsStorage[layoutOptions.type]; + if (!layout) { + layoutOptions.enableSimulation = + !defined(chartOptions.forExport) ? + layoutOptions.enableSimulation : + !chartOptions.forExport; + graphLayoutsStorage[layoutOptions.type] = layout = + new H.layouts[layoutOptions.type](); + layout.init(layoutOptions); + graphLayoutsLookup.splice(layout.index, 0, layout); + } + this.layout = layout; + layout.setArea(0, 0, this.chart.plotWidth, this.chart.plotHeight); + layout.addElementsToCollection([this], layout.series); + layout.addElementsToCollection(this.nodes, layout.nodes); + layout.addElementsToCollection(this.points, layout.links); + }, + /** + * Extend the render function to also render this.nodes together with + * the points. + * @private + */ + render: function () { + var series = this, points = series.points, hoverPoint = series.chart.hoverPoint, dataLabels = []; + // Render markers: + series.points = series.nodes; + seriesTypes.line.prototype.render.call(this); + series.points = points; + points.forEach(function (point) { + if (point.fromNode && point.toNode) { + point.renderLink(); + point.redrawLink(); + } + }); + if (hoverPoint && hoverPoint.series === series) { + series.redrawHalo(hoverPoint); + } + if (series.chart.hasRendered && + !series.options.dataLabels.allowOverlap) { + series.nodes.concat(series.points).forEach(function (node) { + if (node.dataLabel) { + dataLabels.push(node.dataLabel); + } + }); + series.chart.hideOverlappingLabels(dataLabels); + } + }, + // Networkgraph has two separate collecions of nodes and lines, render + // dataLabels for both sets: + drawDataLabels: function () { + var textPath = this.options.dataLabels.textPath; + // Render node labels: + Series.prototype.drawDataLabels.apply(this, arguments); + // Render link labels: + this.points = this.data; + this.options.dataLabels.textPath = + this.options.dataLabels.linkTextPath; + Series.prototype.drawDataLabels.apply(this, arguments); + // Restore nodes + this.points = this.nodes; + this.options.dataLabels.textPath = textPath; + }, + // Return the presentational attributes. + pointAttribs: function (point, state) { + // By default, only `selected` state is passed on + var pointState = state || point && point.state || 'normal', attribs = Series.prototype.pointAttribs.call(this, point, pointState), stateOptions = this.options.states[pointState]; + if (point && !point.isNode) { + attribs = point.getLinkAttributes(); + // For link, get prefixed names: + if (stateOptions) { + attribs = { + // TO DO: API? + stroke: stateOptions.linkColor || attribs.stroke, + dashstyle: (stateOptions.linkDashStyle || attribs.dashstyle), + opacity: pick(stateOptions.linkOpacity, attribs.opacity), + 'stroke-width': stateOptions.linkColor || + attribs['stroke-width'] + }; + } + } + return attribs; + }, + // Draggable mode: + /** + * Redraw halo on mousemove during the drag&drop action. + * @private + * @param {Highcharts.Point} point The point that should show halo. + */ + redrawHalo: dragNodesMixin.redrawHalo, + /** + * Mouse down action, initializing drag&drop mode. + * @private + * @param {global.Event} event Browser event, before normalization. + * @param {Highcharts.Point} point The point that event occured. + */ + onMouseDown: dragNodesMixin.onMouseDown, + /** + * Mouse move action during drag&drop. + * @private + * @param {global.Event} event Browser event, before normalization. + * @param {Highcharts.Point} point The point that event occured. + */ + onMouseMove: dragNodesMixin.onMouseMove, + /** + * Mouse up action, finalizing drag&drop. + * @private + * @param {Highcharts.Point} point The point that event occured. + */ + onMouseUp: dragNodesMixin.onMouseUp, + /** + * When state should be passed down to all points, concat nodes and + * links and apply this state to all of them. + * @private + */ + setState: function (state, inherit) { + if (inherit) { + this.points = this.nodes.concat(this.data); + Series.prototype.setState.apply(this, arguments); + this.points = this.data; + } + else { + Series.prototype.setState.apply(this, arguments); + } + // If simulation is done, re-render points with new states: + if (!this.layout.simulation && !state) { + this.render(); + } + } + }, { + setState: H.NodesMixin.setNodeState, + /** + * Basic `point.init()` and additional styles applied when + * `series.draggable` is enabled. + * @private + */ + init: function () { + Point.prototype.init.apply(this, arguments); + if (this.series.options.draggable && + !this.series.chart.styledMode) { + addEvent(this, 'mouseOver', function () { + css(this.series.chart.container, { cursor: 'move' }); + }); + addEvent(this, 'mouseOut', function () { + css(this.series.chart.container, { cursor: 'default' }); + }); + } + return this; + }, + /** + * Return degree of a node. If node has no connections, it still has + * deg=1. + * @private + * @return {number} + */ + getDegree: function () { + var deg = this.isNode ? + this.linksFrom.length + this.linksTo.length : + 0; + return deg === 0 ? 1 : deg; + }, + // Links: + /** + * Get presentational attributes of link connecting two nodes. + * @private + * @return {Highcharts.SVGAttributes} + */ + getLinkAttributes: function () { + var linkOptions = this.series.options.link, pointOptions = this.options; + return { + 'stroke-width': pick(pointOptions.width, linkOptions.width), + stroke: (pointOptions.color || linkOptions.color), + dashstyle: (pointOptions.dashStyle || linkOptions.dashStyle), + opacity: pick(pointOptions.opacity, linkOptions.opacity, 1) + }; + }, + /** + * Render link and add it to the DOM. + * @private + */ + renderLink: function () { + var attribs; + if (!this.graphic) { + this.graphic = this.series.chart.renderer + .path(this.getLinkPath()) + .add(this.series.group); + if (!this.series.chart.styledMode) { + attribs = this.series.pointAttribs(this); + this.graphic.attr(attribs); + (this.dataLabels || []).forEach(function (label) { + if (label) { + label.attr({ + opacity: attribs.opacity + }); + } + }); + } + } + }, + /** + * Redraw link's path. + * @private + */ + redrawLink: function () { + var path = this.getLinkPath(), attribs; + if (this.graphic) { + this.shapeArgs = { + d: path + }; + if (!this.series.chart.styledMode) { + attribs = this.series.pointAttribs(this); + this.graphic.attr(attribs); + (this.dataLabels || []).forEach(function (label) { + if (label) { + label.attr({ + opacity: attribs.opacity + }); + } + }); + } + this.graphic.animate(this.shapeArgs); + // Required for dataLabels + var start = path[0]; + var end = path[1]; + if (start[0] === 'M' && end[0] === 'L') { + this.plotX = (start[1] + end[1]) / 2; + this.plotY = (start[2] + end[2]) / 2; + } + } + }, + /** + * Get mass fraction applied on two nodes connected to each other. By + * default, when mass is equal to `1`, mass fraction for both nodes + * equal to 0.5. + * @private + * @return {Highcharts.Dictionary} + * For example `{ fromNode: 0.5, toNode: 0.5 }` + */ + getMass: function () { + var m1 = this.fromNode.mass, m2 = this.toNode.mass, sum = m1 + m2; + return { + fromNode: 1 - m1 / sum, + toNode: 1 - m2 / sum + }; + }, + /** + * Get link path connecting two nodes. + * @private + * @return {Array} + * Path: `['M', x, y, 'L', x, y]` + */ + getLinkPath: function () { + var left = this.fromNode, right = this.toNode; + // Start always from left to the right node, to prevent rendering + // labels upside down + if (left.plotX > right.plotX) { + left = this.toNode; + right = this.fromNode; + } + return [ + ['M', left.plotX || 0, left.plotY || 0], + ['L', right.plotX || 0, right.plotY || 0] + ]; + /* + IDEA: different link shapes? + return [ + 'M', + from.plotX, + from.plotY, + 'Q', + (to.plotX + from.plotX) / 2, + (to.plotY + from.plotY) / 2 + 15, + to.plotX, + to.plotY + ];*/ + }, + isValid: function () { + return !this.isNode || defined(this.id); + }, + /** + * Common method for removing points and nodes in networkgraph. To + * remove `link`, use `series.data[index].remove()`. To remove `node` + * with all connections, use `series.nodes[index].remove()`. + * @private + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call. When + * doing more operations on the chart, for example running + * `point.remove()` in a loop, it is best practice to set + * `redraw` to false and call `chart.redraw()` after. + * @param {boolean|Highcharts.AnimationOptionsObject} [animation=false] + * Whether to apply animation, and optionally animation + * configuration. + * @return {void} + */ + remove: function (redraw, animation) { + var point = this, series = point.series, nodesOptions = series.options.nodes || [], index, i = nodesOptions.length; + // For nodes, remove all connected links: + if (point.isNode) { + // Temporary disable series.points array, because + // Series.removePoint() modifies it + series.points = []; + // Remove link from all nodes collections: + [] + .concat(point.linksFrom) + .concat(point.linksTo) + .forEach(function (linkFromTo) { + // Incoming links + index = linkFromTo.fromNode.linksFrom.indexOf(linkFromTo); + if (index > -1) { + linkFromTo.fromNode.linksFrom.splice(index, 1); + } + // Outcoming links + index = linkFromTo.toNode.linksTo.indexOf(linkFromTo); + if (index > -1) { + linkFromTo.toNode.linksTo.splice(index, 1); + } + // Remove link from data/points collections + Series.prototype.removePoint.call(series, series.data.indexOf(linkFromTo), false, false); + }); + // Restore points array, after links are removed + series.points = series.data.slice(); + // Proceed with removing node. It's similar to + // Series.removePoint() method, but doesn't modify other arrays + series.nodes.splice(series.nodes.indexOf(point), 1); + // Remove node options from config + while (i--) { + if (nodesOptions[i].id === point.options.id) { + series.options.nodes.splice(i, 1); + break; + } + } + if (point) { + point.destroy(); + } + // Run redraw if requested + series.isDirty = true; + series.isDirtyData = true; + if (redraw) { + series.chart.redraw(redraw); + } + } + else { + series.removePoint(series.data.indexOf(point), redraw, animation); + } + }, + /** + * Destroy point. If it's a node, remove all links coming out of this + * node. Then remove point from the layout. + * @private + * @return {void} + */ + destroy: function () { + if (this.isNode) { + this.linksFrom.concat(this.linksTo).forEach(function (link) { + // Removing multiple nodes at the same time + // will try to remove link between nodes twice + if (link.destroyElements) { + link.destroyElements(); + } + }); + } + this.series.layout.removeElementFromCollection(this, this.series.layout[this.isNode ? 'nodes' : 'links']); + return Point.prototype.destroy.apply(this, arguments); + } + }); + /** + * A `networkgraph` series. If the [type](#series.networkgraph.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.networkgraph + * @excluding boostThreshold, animation, animationLimit, connectEnds, + * connectNulls, dragDrop, getExtremesFromAll, label, linecap, + * negativeColor, pointInterval, pointIntervalUnit, + * pointPlacement, pointStart, softThreshold, stack, stacking, + * step, threshold, xAxis, yAxis, zoneAxis, dataSorting + * @product highcharts + * @requires modules/networkgraph + * @apioption series.networkgraph + */ + /** + * An array of data points for the series. For the `networkgraph` series type, + * points can be given in the following way: + * + * An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.area.turboThreshold), this option is not available. + * + * ```js + * data: [{ + * from: 'Category1', + * to: 'Category2' + * }, { + * from: 'Category1', + * to: 'Category3' + * }] + * ``` + * + * @type {Array} + * @extends series.line.data + * @excluding drilldown,marker,x,y,draDrop + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * @product highcharts + * @apioption series.networkgraph.data + */ + /** + * @type {Highcharts.SeriesNetworkgraphDataLabelsOptionsObject|Array} + * @product highcharts + * @apioption series.networkgraph.data.dataLabels + */ + /** + * The node that the link runs from. + * + * @type {string} + * @product highcharts + * @apioption series.networkgraph.data.from + */ + /** + * The node that the link runs to. + * + * @type {string} + * @product highcharts + * @apioption series.networkgraph.data.to + */ + /** + * A collection of options for the individual nodes. The nodes in a + * networkgraph diagram are auto-generated instances of `Highcharts.Point`, + * but options can be applied here and linked by the `id`. + * + * @sample highcharts/series-networkgraph/data-options/ + * Networkgraph diagram with node options + * + * @type {Array<*>} + * @product highcharts + * @apioption series.networkgraph.nodes + */ + /** + * The id of the auto-generated node, refering to the `from` or `to` setting of + * the link. + * + * @type {string} + * @product highcharts + * @apioption series.networkgraph.nodes.id + */ + /** + * The color of the auto generated node. + * + * @type {Highcharts.ColorString} + * @product highcharts + * @apioption series.networkgraph.nodes.color + */ + /** + * The color index of the auto generated node, especially for use in styled + * mode. + * + * @type {number} + * @product highcharts + * @apioption series.networkgraph.nodes.colorIndex + */ + /** + * The name to display for the node in data labels and tooltips. Use this when + * the name is different from the `id`. Where the id must be unique for each + * node, this is not necessary for the name. + * + * @sample highcharts/series-networkgraph/data-options/ + * Networkgraph diagram with node options + * + * @type {string} + * @product highcharts + * @apioption series.networkgraph.nodes.name + */ + /** + * Mass of the node. By default, each node has mass equal to it's marker radius + * . Mass is used to determine how two connected nodes should affect + * each other: + * + * Attractive force is multiplied by the ratio of two connected + * nodes; if a big node has weights twice as the small one, then the small one + * will move towards the big one twice faster than the big one to the small one + * . + * + * @sample highcharts/series-networkgraph/ragdoll/ + * Mass determined by marker.radius + * + * @type {number} + * @product highcharts + * @apioption series.networkgraph.nodes.mass + */ + /** + * Individual data label for each node. The options are the same as + * the ones for [series.networkgraph.dataLabels](#series.networkgraph.dataLabels). + * + * @type {Highcharts.SeriesNetworkgraphDataLabelsOptionsObject|Array} + * + * @apioption series.networkgraph.nodes.dataLabels + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'masters/modules/networkgraph.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/no-data-to-display.js b/librerias/gantt/code/modules/no-data-to-display.js new file mode 100644 index 0000000..bd3a778 --- /dev/null +++ b/librerias/gantt/code/modules/no-data-to-display.js @@ -0,0 +1,14 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Plugin for displaying a message when there is no data visible in chart. + + (c) 2010-2019 Highsoft AS + Author: Oystein Moseng + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/no-data-to-display",["highcharts"],function(c){a(c);a.Highcharts=c;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function c(a,d,c,e){a.hasOwnProperty(d)||(a[d]=e.apply(null,c))}a=a?a._modules:{};c(a,"modules/no-data-to-display.src.js",[a["parts/Globals.js"],a["parts/Utilities.js"]],function(a,d){var c=d.addEvent,e= +d.extend;d=a.Chart.prototype;var f=a.getOptions();e(f.lang,{noData:"No data to display"});f.noData={attr:{zIndex:1},position:{x:0,y:0,align:"center",verticalAlign:"middle"},style:{fontWeight:"bold",fontSize:"12px",color:"#666666"}};d.showNoData=function(a){var b=this.options;a=a||b&&b.lang.noData;b=b&&b.noData;!this.noDataLabel&&this.renderer&&(this.noDataLabel=this.renderer.label(a,0,0,null,null,null,b.useHTML,null,"no-data"),this.styledMode||this.noDataLabel.attr(b.attr).css(b.style),this.noDataLabel.add(), +this.noDataLabel.align(e(this.noDataLabel.getBBox(),b.position),!1,"plotBox"))};d.hideNoData=function(){this.noDataLabel&&(this.noDataLabel=this.noDataLabel.destroy())};d.hasData=function(){for(var a=this.series||[],b=a.length;b--;)if(a[b].hasData()&&!a[b].options.isInternal)return!0;return this.loadingShown};c(a.Chart,"render",function(){this.hasData()?this.hideNoData():this.showNoData()})});c(a,"masters/modules/no-data-to-display.src.js",[],function(){})}); +//# sourceMappingURL=no-data-to-display.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/no-data-to-display.js.map b/librerias/gantt/code/modules/no-data-to-display.js.map new file mode 100644 index 0000000..018dbb7 --- /dev/null +++ b/librerias/gantt/code/modules/no-data-to-display.js.map @@ -0,0 +1 @@ +{"version":3,"file":"no-data-to-display.js.map","lineCount":13,"mappings":"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","sources":["no-data-to-display.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","U","addEvent","extend","chartPrototype","Chart","prototype","defaultOptions","getOptions","lang","noData","attr","zIndex","position","x","y","align","verticalAlign","style","fontWeight","fontSize","color","showNoData","chartPrototype.showNoData","str","options","chart","text","noDataOptions","noDataLabel","renderer","label","useHTML","styledMode","css","add","getBBox","hideNoData","chartPrototype.hideNoData","destroy","hasData","chartPrototype.hasData","series","i","length","isInternal","loadingShown","handleNoData"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/no-data-to-display.src.js b/librerias/gantt/code/modules/no-data-to-display.src.js new file mode 100644 index 0000000..44d0df4 --- /dev/null +++ b/librerias/gantt/code/modules/no-data-to-display.src.js @@ -0,0 +1,221 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * Plugin for displaying a message when there is no data visible in chart. + * + * (c) 2010-2019 Highsoft AS + * Author: Oystein Moseng + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/no-data-to-display', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'modules/no-data-to-display.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * Plugin for displaying a message when there is no data visible in chart. + * + * (c) 2010-2020 Highsoft AS + * + * Author: Oystein Moseng + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, extend = U.extend; + var chartPrototype = H.Chart.prototype, defaultOptions = H.getOptions(); + // Add language option + extend(defaultOptions.lang, + /** + * @optionparent lang + */ + { + /** + * The text to display when the chart contains no data. + * + * @see [noData](#noData) + * + * @sample highcharts/no-data-to-display/no-data-line + * No-data text + * + * @since 3.0.8 + * @product highcharts highstock + * @requires modules/no-data-to-display + */ + noData: 'No data to display' + }); + // Add default display options for message + /** + * Options for displaying a message like "No data to display". + * This feature requires the file no-data-to-display.js to be loaded in the + * page. The actual text to display is set in the lang.noData option. + * + * @sample highcharts/no-data-to-display/no-data-line + * Line chart with no-data module + * @sample highcharts/no-data-to-display/no-data-pie + * Pie chart with no-data module + * + * @product highcharts highstock gantt + * @requires modules/no-data-to-display + * @optionparent noData + */ + defaultOptions.noData = { + /** + * An object of additional SVG attributes for the no-data label. + * + * @type {Highcharts.SVGAttributes} + * @since 3.0.8 + * @product highcharts highstock gantt + * @apioption noData.attr + */ + attr: { + zIndex: 1 + }, + /** + * Whether to insert the label as HTML, or as pseudo-HTML rendered with + * SVG. + * + * @type {boolean} + * @default false + * @since 4.1.10 + * @product highcharts highstock gantt + * @apioption noData.useHTML + */ + /** + * The position of the no-data label, relative to the plot area. + * + * @type {Highcharts.AlignObject} + * @since 3.0.8 + */ + position: { + /** + * Horizontal offset of the label, in pixels. + */ + x: 0, + /** + * Vertical offset of the label, in pixels. + */ + y: 0, + /** + * Horizontal alignment of the label. + * + * @type {Highcharts.AlignValue} + */ + align: 'center', + /** + * Vertical alignment of the label. + * + * @type {Highcharts.VerticalAlignValue} + */ + verticalAlign: 'middle' + }, + /** + * CSS styles for the no-data label. + * + * @sample highcharts/no-data-to-display/no-data-line + * Styled no-data text + * + * @type {Highcharts.CSSObject} + */ + style: { + /** @ignore */ + fontWeight: 'bold', + /** @ignore */ + fontSize: '12px', + /** @ignore */ + color: '#666666' + } + }; + /** + * Display a no-data message. + * @private + * @function Highcharts.Chart#showNoData + * @param {string} [str] + * An optional message to show in place of the default one + * @return {void} + * @requires modules/no-data-to-display + */ + chartPrototype.showNoData = function (str) { + var chart = this, options = chart.options, text = str || (options && options.lang.noData), noDataOptions = options && options.noData; + if (!chart.noDataLabel && chart.renderer) { + chart.noDataLabel = chart.renderer + .label(text, 0, 0, null, null, null, noDataOptions.useHTML, null, 'no-data'); + if (!chart.styledMode) { + chart.noDataLabel + .attr(noDataOptions.attr) + .css(noDataOptions.style); + } + chart.noDataLabel.add(); + chart.noDataLabel.align(extend(chart.noDataLabel.getBBox(), noDataOptions.position), false, 'plotBox'); + } + }; + /** + * Hide no-data message. + * + * @private + * @function Highcharts.Chart#hideNoData + * @return {void} + * @requires modules/no-data-to-display + */ + chartPrototype.hideNoData = function () { + var chart = this; + if (chart.noDataLabel) { + chart.noDataLabel = chart.noDataLabel.destroy(); + } + }; + /** + * Returns true if there are data points within the plot area now. + * + * @private + * @function Highcharts.Chart#hasData + * @return {boolean|undefined} + * True, if there are data points. + * @requires modules/no-data-to-display + */ + chartPrototype.hasData = function () { + var chart = this, series = chart.series || [], i = series.length; + while (i--) { + if (series[i].hasData() && !series[i].options.isInternal) { + return true; + } + } + return chart.loadingShown; // #4588 + }; + /* eslint-disable no-invalid-this */ + // Add event listener to handle automatic show or hide no-data message. + addEvent(H.Chart, 'render', function handleNoData() { + if (this.hasData()) { + this.hideNoData(); + } + else { + this.showNoData(); + } + }); + + }); + _registerModule(_modules, 'masters/modules/no-data-to-display.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/offline-exporting.js b/librerias/gantt/code/modules/offline-exporting.js new file mode 100644 index 0000000..6e401ee --- /dev/null +++ b/librerias/gantt/code/modules/offline-exporting.js @@ -0,0 +1,24 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Client side exporting module + + (c) 2015-2019 Torstein Honsi / Oystein Moseng + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/offline-exporting",["highcharts","highcharts/modules/exporting"],function(f){a(f);a.Highcharts=f;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function f(b,d,a,x){b.hasOwnProperty(d)||(b[d]=x.apply(null,a))}a=a?a._modules:{};f(a,"mixins/download-url.js",[a["parts/Globals.js"]],function(b){var d=b.win,a=d.navigator, +x=d.document,f=d.URL||d.webkitURL||d,g=/Edge\/\d+/.test(a.userAgent);b.dataURLtoBlob=function(b){if((b=b.match(/data:([^;]*)(;base64)?,([0-9A-Za-z+/]+)/))&&3e.userAgent.indexOf("Chrome");try{if(!a&&0>e.userAgent.toLowerCase().indexOf("firefox"))return l.createObjectURL(new g.Blob([b], +{type:"image/svg+xml;charset-utf-16"}))}catch(k){}return"data:image/svg+xml;charset=UTF-8,"+encodeURIComponent(b)};b.imageToDataUrl=function(b,a,k,c,d,e,f,n,m){var h=new g.Image,u=function(){setTimeout(function(){var e=y.createElement("canvas"),g=e.getContext&&e.getContext("2d");try{if(g){e.height=h.height*c;e.width=h.width*c;g.drawImage(h,0,0,e.width,e.height);try{var w=e.toDataURL(a);d(w,a,k,c)}catch(B){t(b,a,k,c)}}else f(b,a,k,c)}finally{m&&m(b,a,k,c)}},A)},q=function(){n(b,a,k,c);m&&m(b,a,k,c)}; +var t=function(){h=new g.Image;t=e;h.crossOrigin="Anonymous";h.onload=u;h.onerror=q;h.src=b};h.onload=u;h.onerror=q;h.src=b};b.downloadSVGLocal=function(a,f,k,c){function t(a,b){b=new g.jsPDF("l","pt",[a.width.baseVal.value+2*b,a.height.baseVal.value+2*b]);[].forEach.call(a.querySelectorAll('*[visibility="hidden"]'),function(b){b.parentNode.removeChild(b)});g.svg2pdf(a,b,{removeInvalid:!0});return b.output("datauristring")}function u(){m.innerHTML=a;var e=m.getElementsByTagName("text"),d;[].forEach.call(e, +function(b){["font-family","font-size"].forEach(function(a){for(var c=b;c&&c!==m;){if(c.style[a]){b.style[a]=c.style[a];break}c=c.parentNode}});b.style["font-family"]=b.style["font-family"]&&b.style["font-family"].split(" ").splice(-1);d=b.getElementsByTagName("title");[].forEach.call(d,function(a){b.removeChild(a)})});e=t(m.firstChild,0);try{b.downloadURL(e,z),c&&c()}catch(E){k(E)}}var q=!0,n=f.libURL||b.getOptions().exporting.libURL,m=y.createElement("div"),h=f.type||"image/png",z=(f.filename|| +"chart")+"."+("image/svg+xml"===h?"svg":h.split("/")[1]),p=f.scale||1;n="/"!==n.slice(-1)?n+"/":n;if("image/svg+xml"===h)try{if("undefined"!==typeof e.msSaveOrOpenBlob){var C=new MSBlobBuilder;C.append(a);var r=C.getBlob("image/svg+xml")}else r=b.svgToDataUrl(a);b.downloadURL(r,z);c&&c()}catch(w){k(w)}else if("application/pdf"===h)g.jsPDF&&g.svg2pdf?u():(q=!0,d(n+"jspdf.js",function(){d(n+"svg2pdf.js",function(){u()})}));else{r=b.svgToDataUrl(a);var v=function(){try{l.revokeObjectURL(r)}catch(w){}}; +b.imageToDataUrl(r,h,{},p,function(a){try{b.downloadURL(a,z),c&&c()}catch(B){k(B)}},function(){var f=y.createElement("canvas"),u=f.getContext("2d"),t=a.match(/^]*width\s*=\s*"?(\d+)"?[^>]*>/)[1]*p,m=a.match(/^]*height\s*=\s*"?(\d+)"?[^>]*>/)[1]*p,l=function(){u.drawSvg(a,0,0,t,m);try{b.downloadURL(e.msSaveOrOpenBlob?f.msToBlob():f.toDataURL(h),z),c&&c()}catch(F){k(F)}finally{v()}};f.width=t;f.height=m;g.canvg?l():(q=!0,d(n+"rgbcolor.js",function(){d(n+"canvg.js",function(){l()})}))}, +k,k,function(){q&&v()})}};b.Chart.prototype.getSVGForLocalExport=function(a,e,d,c){var f=this,k=0,g,n,m,h,l=function(){k===q.length&&c(f.sanitizeSVG(g.innerHTML,n))},p=function(b,a,c){++k;c.imageElement.setAttributeNS("http://www.w3.org/1999/xlink","href",b);l()};f.unbindGetSVG=D(f,"getSVG",function(b){n=b.chartCopy.options;g=b.chartCopy.container.cloneNode(!0)});f.getSVGForExport(a,e);var q=g.getElementsByTagName("image");try{if(!q.length){c(f.sanitizeSVG(g.innerHTML,n));return}var r=0;for(m=q.length;r< +m;++r){var v=q[r];(h=v.getAttributeNS("http://www.w3.org/1999/xlink","href"))?b.imageToDataUrl(h,"image/png",{imageElement:v},a.scale,p,d,d,d):(++k,v.parentNode.removeChild(v),l())}}catch(w){d(w)}f.unbindGetSVG()};b.Chart.prototype.exportChartLocal=function(a,e){var d=this,c=b.merge(d.options.exporting,a),g=function(a){!1===c.fallbackToExportServer?c.error?c.error(c,a):b.error(28,!0):d.exportChart(c)};a=function(){return[].some.call(d.container.getElementsByTagName("image"),function(a){a=a.getAttribute("href"); +return""!==a&&0!==a.indexOf("data:")})};p&&d.styledMode&&(b.SVGRenderer.prototype.inlineWhitelist=[/^blockSize/,/^border/,/^caretColor/,/^color/,/^columnRule/,/^columnRuleColor/,/^cssFloat/,/^cursor/,/^fill$/,/^fillOpacity/,/^font/,/^inlineSize/,/^length/,/^lineHeight/,/^opacity/,/^outline/,/^parentRule/,/^rx$/,/^ry$/,/^stroke/,/^textAlign/,/^textAnchor/,/^textDecoration/,/^transform/,/^vectorEffect/,/^visibility/,/^x$/,/^y$/]);p&&("application/pdf"===c.type||d.container.getElementsByTagName("image").length&& +"image/svg+xml"!==c.type)||"application/pdf"===c.type&&a()?g("Image type not supported for this chart/browser."):d.getSVGForLocalExport(c,e,g,function(a){-1 3 && + win.atob && + win.ArrayBuffer && + win.Uint8Array && + win.Blob && + domurl.createObjectURL) { + // Try to convert data URL to Blob + var binStr = win.atob(parts[3]), buf = new win.ArrayBuffer(binStr.length), binary = new win.Uint8Array(buf), blob; + for (var i = 0; i < binary.length; ++i) { + binary[i] = binStr.charCodeAt(i); + } + blob = new win.Blob([binary], { 'type': parts[1] }); + return domurl.createObjectURL(blob); + } + }; + /** + * Download a data URL in the browser. Can also take a blob as first param. + * + * @private + * @function Highcharts.downloadURL + * @param {string|global.URL} dataURL + * The dataURL/Blob to download + * @param {string} filename + * The name of the resulting file (w/extension) + * @return {void} + */ + Highcharts.downloadURL = function (dataURL, filename) { + var a = doc.createElement('a'), windowRef; + // IE specific blob implementation + // Don't use for normal dataURLs + if (typeof dataURL !== 'string' && + !(dataURL instanceof String) && + nav.msSaveOrOpenBlob) { + nav.msSaveOrOpenBlob(dataURL, filename); + return; + } + // Some browsers have limitations for data URL lengths. Try to convert to + // Blob or fall back. Edge always needs that blob. + if (isEdgeBrowser || dataURL.length > 2000000) { + dataURL = Highcharts.dataURLtoBlob(dataURL); + if (!dataURL) { + throw new Error('Failed to convert to blob'); + } + } + // Try HTML5 download attr if supported + if (typeof a.download !== 'undefined') { + a.href = dataURL; + a.download = filename; // HTML5 download attribute + doc.body.appendChild(a); + a.click(); + doc.body.removeChild(a); + } + else { + // No download attr, just opening data URI + try { + windowRef = win.open(dataURL, 'chart'); + if (typeof windowRef === 'undefined' || windowRef === null) { + throw new Error('Failed to open window'); + } + } + catch (e) { + // window.open failed, trying location.href + win.location.href = dataURL; + } + } + }; + + }); + _registerModule(_modules, 'modules/offline-exporting.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (Highcharts, U) { + /* * + * + * Client side exporting module + * + * (c) 2015 Torstein Honsi / Oystein Moseng + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /* global MSBlobBuilder */ + var extend = U.extend; + var addEvent = Highcharts.addEvent, merge = Highcharts.merge, win = Highcharts.win, nav = win.navigator, doc = win.document, domurl = win.URL || win.webkitURL || win, isMSBrowser = /Edge\/|Trident\/|MSIE /.test(nav.userAgent), + // Milliseconds to defer image load event handlers to offset IE bug + loadEventDeferDelay = isMSBrowser ? 150 : 0; + // Dummy object so we can reuse our canvas-tools.js without errors + Highcharts.CanVGRenderer = {}; + /* eslint-disable valid-jsdoc */ + /** + * Downloads a script and executes a callback when done. + * + * @private + * @function getScript + * @param {string} scriptLocation + * @param {Function} callback + * @return {void} + */ + function getScript(scriptLocation, callback) { + var head = doc.getElementsByTagName('head')[0], script = doc.createElement('script'); + script.type = 'text/javascript'; + script.src = scriptLocation; + script.onload = callback; + script.onerror = function () { + Highcharts.error('Error loading script ' + scriptLocation); + }; + head.appendChild(script); + } + /** + * Get blob URL from SVG code. Falls back to normal data URI. + * + * @private + * @function Highcharts.svgToDataURL + * @param {string} svg + * @return {string} + */ + Highcharts.svgToDataUrl = function (svg) { + // Webkit and not chrome + var webKit = (nav.userAgent.indexOf('WebKit') > -1 && + nav.userAgent.indexOf('Chrome') < 0); + try { + // Safari requires data URI since it doesn't allow navigation to blob + // URLs. Firefox has an issue with Blobs and internal references, + // leading to gradients not working using Blobs (#4550) + if (!webKit && nav.userAgent.toLowerCase().indexOf('firefox') < 0) { + return domurl.createObjectURL(new win.Blob([svg], { + type: 'image/svg+xml;charset-utf-16' + })); + } + } + catch (e) { + // Ignore + } + return 'data:image/svg+xml;charset=UTF-8,' + encodeURIComponent(svg); + }; + /** + * Get data:URL from image URL. Pass in callbacks to handle results. + * + * @private + * @function Highcharts.imageToDataUrl + * + * @param {string} imageURL + * + * @param {string} imageType + * + * @param {*} callbackArgs + * callbackArgs is used only by callbacks. + * + * @param {number} scale + * + * @param {Function} successCallback + * Receives four arguments: imageURL, imageType, callbackArgs, and scale. + * + * @param {Function} taintedCallback + * Receives four arguments: imageURL, imageType, callbackArgs, and scale. + * + * @param {Function} noCanvasSupportCallback + * Receives four arguments: imageURL, imageType, callbackArgs, and scale. + * + * @param {Function} failedLoadCallback + * Receives four arguments: imageURL, imageType, callbackArgs, and scale. + * + * @param {Function} [finallyCallback] + * finallyCallback is always called at the end of the process. All + * callbacks receive four arguments: imageURL, imageType, callbackArgs, + * and scale. + * + * @return {void} + */ + Highcharts.imageToDataUrl = function (imageURL, imageType, callbackArgs, scale, successCallback, taintedCallback, noCanvasSupportCallback, failedLoadCallback, finallyCallback) { + var img = new win.Image(), taintedHandler, loadHandler = function () { + setTimeout(function () { + var canvas = doc.createElement('canvas'), ctx = canvas.getContext && canvas.getContext('2d'), dataURL; + try { + if (!ctx) { + noCanvasSupportCallback(imageURL, imageType, callbackArgs, scale); + } + else { + canvas.height = img.height * scale; + canvas.width = img.width * scale; + ctx.drawImage(img, 0, 0, canvas.width, canvas.height); + // Now we try to get the contents of the canvas. + try { + dataURL = canvas.toDataURL(imageType); + successCallback(dataURL, imageType, callbackArgs, scale); + } + catch (e) { + taintedHandler(imageURL, imageType, callbackArgs, scale); + } + } + } + finally { + if (finallyCallback) { + finallyCallback(imageURL, imageType, callbackArgs, scale); + } + } + // IE bug where image is not always ready despite calling load + // event. + }, loadEventDeferDelay); + }, + // Image load failed (e.g. invalid URL) + errorHandler = function () { + failedLoadCallback(imageURL, imageType, callbackArgs, scale); + if (finallyCallback) { + finallyCallback(imageURL, imageType, callbackArgs, scale); + } + }; + // This is called on load if the image drawing to canvas failed with a + // security error. We retry the drawing with crossOrigin set to Anonymous. + taintedHandler = function () { + img = new win.Image(); + taintedHandler = taintedCallback; + // Must be set prior to loading image source + img.crossOrigin = 'Anonymous'; + img.onload = loadHandler; + img.onerror = errorHandler; + img.src = imageURL; + }; + img.onload = loadHandler; + img.onerror = errorHandler; + img.src = imageURL; + }; + /* eslint-enable valid-jsdoc */ + /** + * Get data URL to an image of an SVG and call download on it options object: + * + * - **filename:** Name of resulting downloaded file without extension. Default + * is `chart`. + * + * - **type:** File type of resulting download. Default is `image/png`. + * + * - **scale:** Scaling factor of downloaded image compared to source. Default + * is `1`. + * + * - **libURL:** URL pointing to location of dependency scripts to download on + * demand. Default is the exporting.libURL option of the global Highcharts + * options pointing to our server. + * + * @function Highcharts.downloadSVGLocal + * + * @param {string} svg + * The generated SVG + * + * @param {Highcharts.ExportingOptions} options + * The exporting options + * + * @param {Function} failCallback + * The callback function in case of errors + * + * @param {Function} [successCallback] + * The callback function in case of success + * + * @return {void} + */ + Highcharts.downloadSVGLocal = function (svg, options, failCallback, successCallback) { + var svgurl, blob, objectURLRevoke = true, finallyHandler, libURL = (options.libURL || Highcharts.getOptions().exporting.libURL), dummySVGContainer = doc.createElement('div'), imageType = options.type || 'image/png', filename = ((options.filename || 'chart') + + '.' + + (imageType === 'image/svg+xml' ? 'svg' : imageType.split('/')[1])), scale = options.scale || 1; + // Allow libURL to end with or without fordward slash + libURL = libURL.slice(-1) !== '/' ? libURL + '/' : libURL; + /* eslint-disable valid-jsdoc */ + /** + * @private + */ + function svgToPdf(svgElement, margin) { + var width = svgElement.width.baseVal.value + 2 * margin, height = svgElement.height.baseVal.value + 2 * margin, pdf = new win.jsPDF(// eslint-disable-line new-cap + 'l', 'pt', [width, height]); + // Workaround for #7090, hidden elements were drawn anyway. It comes + // down to https://github.com/yWorks/svg2pdf.js/issues/28. Check this + // later. + [].forEach.call(svgElement.querySelectorAll('*[visibility="hidden"]'), function (node) { + node.parentNode.removeChild(node); + }); + win.svg2pdf(svgElement, pdf, { removeInvalid: true }); + return pdf.output('datauristring'); + } + /** + * @private + * @return {void} + */ + function downloadPDF() { + dummySVGContainer.innerHTML = svg; + var textElements = dummySVGContainer.getElementsByTagName('text'), titleElements, svgData, + // Copy style property to element from parents if it's not there. + // Searches up hierarchy until it finds prop, or hits the chart + // container. + setStylePropertyFromParents = function (el, propName) { + var curParent = el; + while (curParent && curParent !== dummySVGContainer) { + if (curParent.style[propName]) { + el.style[propName] = + curParent.style[propName]; + break; + } + curParent = curParent.parentNode; + } + }; + // Workaround for the text styling. Making sure it does pick up settings + // for parent elements. + [].forEach.call(textElements, function (el) { + // Workaround for the text styling. making sure it does pick up the + // root element + ['font-family', 'font-size'].forEach(function (property) { + setStylePropertyFromParents(el, property); + }); + el.style['font-family'] = (el.style['font-family'] && + el.style['font-family'].split(' ').splice(-1)); + // Workaround for plotband with width, removing title from text + // nodes + titleElements = el.getElementsByTagName('title'); + [].forEach.call(titleElements, function (titleElement) { + el.removeChild(titleElement); + }); + }); + svgData = svgToPdf(dummySVGContainer.firstChild, 0); + try { + Highcharts.downloadURL(svgData, filename); + if (successCallback) { + successCallback(); + } + } + catch (e) { + failCallback(e); + } + } + /* eslint-enable valid-jsdoc */ + // Initiate download depending on file type + if (imageType === 'image/svg+xml') { + // SVG download. In this case, we want to use Microsoft specific Blob if + // available + try { + if (typeof nav.msSaveOrOpenBlob !== 'undefined') { + blob = new MSBlobBuilder(); + blob.append(svg); + svgurl = blob.getBlob('image/svg+xml'); + } + else { + svgurl = Highcharts.svgToDataUrl(svg); + } + Highcharts.downloadURL(svgurl, filename); + if (successCallback) { + successCallback(); + } + } + catch (e) { + failCallback(e); + } + } + else if (imageType === 'application/pdf') { + if (win.jsPDF && win.svg2pdf) { + downloadPDF(); + } + else { + // Must load pdf libraries first. // Don't destroy the object URL + // yet since we are doing things asynchronously. A cleaner solution + // would be nice, but this will do for now. + objectURLRevoke = true; + getScript(libURL + 'jspdf.js', function () { + getScript(libURL + 'svg2pdf.js', function () { + downloadPDF(); + }); + }); + } + } + else { + // PNG/JPEG download - create bitmap from SVG + svgurl = Highcharts.svgToDataUrl(svg); + finallyHandler = function () { + try { + domurl.revokeObjectURL(svgurl); + } + catch (e) { + // Ignore + } + }; + // First, try to get PNG by rendering on canvas + Highcharts.imageToDataUrl(svgurl, imageType, {}, scale, function (imageURL) { + // Success + try { + Highcharts.downloadURL(imageURL, filename); + if (successCallback) { + successCallback(); + } + } + catch (e) { + failCallback(e); + } + }, function () { + // Failed due to tainted canvas + // Create new and untainted canvas + var canvas = doc.createElement('canvas'), ctx = canvas.getContext('2d'), imageWidth = svg.match(/^]*width\s*=\s*\"?(\d+)\"?[^>]*>/)[1] * scale, imageHeight = svg.match(/^]*height\s*=\s*\"?(\d+)\"?[^>]*>/)[1] * scale, downloadWithCanVG = function () { + ctx.drawSvg(svg, 0, 0, imageWidth, imageHeight); + try { + Highcharts.downloadURL(nav.msSaveOrOpenBlob ? + canvas.msToBlob() : + canvas.toDataURL(imageType), filename); + if (successCallback) { + successCallback(); + } + } + catch (e) { + failCallback(e); + } + finally { + finallyHandler(); + } + }; + canvas.width = imageWidth; + canvas.height = imageHeight; + if (win.canvg) { + // Use preloaded canvg + downloadWithCanVG(); + } + else { + // Must load canVG first. // Don't destroy the object URL + // yet since we are doing things asynchronously. A cleaner + // solution would be nice, but this will do for now. + objectURLRevoke = true; + // Get RGBColor.js first, then canvg + getScript(libURL + 'rgbcolor.js', function () { + getScript(libURL + 'canvg.js', function () { + downloadWithCanVG(); + }); + }); + } + }, + // No canvas support + failCallback, + // Failed to load image + failCallback, + // Finally + function () { + if (objectURLRevoke) { + finallyHandler(); + } + }); + } + }; + /* eslint-disable valid-jsdoc */ + /** + * Get SVG of chart prepared for client side export. This converts embedded + * images in the SVG to data URIs. It requires the regular exporting module. The + * options and chartOptions arguments are passed to the getSVGForExport + * function. + * + * @private + * @function Highcharts.Chart#getSVGForLocalExport + * @param {Highcharts.ExportingOptions} options + * @param {Highcharts.Options} chartOptions + * @param {Function} failCallback + * @param {Function} successCallback + * @return {void} + */ + Highcharts.Chart.prototype.getSVGForLocalExport = function (options, chartOptions, failCallback, successCallback) { + var chart = this, images, imagesEmbedded = 0, chartCopyContainer, chartCopyOptions, el, i, l, href, + // After grabbing the SVG of the chart's copy container we need to do + // sanitation on the SVG + sanitize = function (svg) { + return chart.sanitizeSVG(svg, chartCopyOptions); + }, + // When done with last image we have our SVG + checkDone = function () { + if (imagesEmbedded === images.length) { + successCallback(sanitize(chartCopyContainer.innerHTML)); + } + }, + // Success handler, we converted image to base64! + embeddedSuccess = function (imageURL, imageType, callbackArgs) { + ++imagesEmbedded; + // Change image href in chart copy + callbackArgs.imageElement.setAttributeNS('http://www.w3.org/1999/xlink', 'href', imageURL); + checkDone(); + }; + // Hook into getSVG to get a copy of the chart copy's container (#8273) + chart.unbindGetSVG = addEvent(chart, 'getSVG', function (e) { + chartCopyOptions = e.chartCopy.options; + chartCopyContainer = e.chartCopy.container.cloneNode(true); + }); + // Trigger hook to get chart copy + chart.getSVGForExport(options, chartOptions); + images = chartCopyContainer.getElementsByTagName('image'); + try { + // If there are no images to embed, the SVG is okay now. + if (!images.length) { + // Use SVG of chart copy + successCallback(sanitize(chartCopyContainer.innerHTML)); + return; + } + // Go through the images we want to embed + for (i = 0, l = images.length; i < l; ++i) { + el = images[i]; + href = el.getAttributeNS('http://www.w3.org/1999/xlink', 'href'); + if (href) { + Highcharts.imageToDataUrl(href, 'image/png', { imageElement: el }, options.scale, embeddedSuccess, + // Tainted canvas + failCallback, + // No canvas support + failCallback, + // Failed to load source + failCallback); + // Hidden, boosted series have blank href (#10243) + } + else { + ++imagesEmbedded; + el.parentNode.removeChild(el); + checkDone(); + } + } + } + catch (e) { + failCallback(e); + } + // Clean up + chart.unbindGetSVG(); + }; + /* eslint-enable valid-jsdoc */ + /** + * Exporting and offline-exporting modules required. Export a chart to an image + * locally in the user's browser. + * + * @function Highcharts.Chart#exportChartLocal + * + * @param {Highcharts.ExportingOptions} [exportingOptions] + * Exporting options, the same as in + * {@link Highcharts.Chart#exportChart}. + * + * @param {Highcharts.Options} [chartOptions] + * Additional chart options for the exported chart. For example a + * different background color can be added here, or `dataLabels` + * for export only. + * + * @return {void} + * + * @requires modules/exporting + */ + Highcharts.Chart.prototype.exportChartLocal = function (exportingOptions, chartOptions) { + var chart = this, options = Highcharts.merge(chart.options.exporting, exportingOptions), fallbackToExportServer = function (err) { + if (options.fallbackToExportServer === false) { + if (options.error) { + options.error(options, err); + } + else { + Highcharts.error(28, true); // Fallback disabled + } + } + else { + chart.exportChart(options); + } + }, svgSuccess = function (svg) { + // If SVG contains foreignObjects all exports except SVG will fail, + // as both CanVG and svg2pdf choke on this. Gracefully fall back. + if (svg.indexOf(' -1 && + options.type !== 'image/svg+xml') { + fallbackToExportServer('Image type not supported' + + 'for charts with embedded HTML'); + } + else { + Highcharts.downloadSVGLocal(svg, extend({ filename: chart.getFilename() }, options), fallbackToExportServer); + } + }, + // Return true if the SVG contains images with external data. With the + // boost module there are `image` elements with encoded PNGs, these are + // supported by svg2pdf and should pass (#10243). + hasExternalImages = function () { + return [].some.call(chart.container.getElementsByTagName('image'), function (image) { + var href = image.getAttribute('href'); + return href !== '' && href.indexOf('data:') !== 0; + }); + }; + // If we are on IE and in styled mode, add a whitelist to the renderer for + // inline styles that we want to pass through. There are so many styles by + // default in IE that we don't want to blacklist them all. + if (isMSBrowser && chart.styledMode) { + Highcharts.SVGRenderer.prototype.inlineWhitelist = [ + /^blockSize/, + /^border/, + /^caretColor/, + /^color/, + /^columnRule/, + /^columnRuleColor/, + /^cssFloat/, + /^cursor/, + /^fill$/, + /^fillOpacity/, + /^font/, + /^inlineSize/, + /^length/, + /^lineHeight/, + /^opacity/, + /^outline/, + /^parentRule/, + /^rx$/, + /^ry$/, + /^stroke/, + /^textAlign/, + /^textAnchor/, + /^textDecoration/, + /^transform/, + /^vectorEffect/, + /^visibility/, + /^x$/, + /^y$/ + ]; + } + // Always fall back on: + // - MS browsers: Embedded images JPEG/PNG, or any PDF + // - Embedded images and PDF + if ((isMSBrowser && + (options.type === 'application/pdf' || + chart.container.getElementsByTagName('image').length && + options.type !== 'image/svg+xml')) || (options.type === 'application/pdf' && + hasExternalImages())) { + fallbackToExportServer('Image type not supported for this chart/browser.'); + return; + } + chart.getSVGForLocalExport(options, chartOptions, fallbackToExportServer, svgSuccess); + }; + // Extend the default options to use the local exporter logic + merge(true, Highcharts.getOptions().exporting, { + libURL: 'https://code.highcharts.com/8.1.0/lib/', + // When offline-exporting is loaded, redefine the menu item definitions + // related to download. + menuItemDefinitions: { + downloadPNG: { + textKey: 'downloadPNG', + onclick: function () { + this.exportChartLocal(); + } + }, + downloadJPEG: { + textKey: 'downloadJPEG', + onclick: function () { + this.exportChartLocal({ + type: 'image/jpeg' + }); + } + }, + downloadSVG: { + textKey: 'downloadSVG', + onclick: function () { + this.exportChartLocal({ + type: 'image/svg+xml' + }); + } + }, + downloadPDF: { + textKey: 'downloadPDF', + onclick: function () { + this.exportChartLocal({ + type: 'application/pdf' + }); + } + } + } + }); + + }); + _registerModule(_modules, 'masters/modules/offline-exporting.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/oldie-polyfills.js b/librerias/gantt/code/modules/oldie-polyfills.js new file mode 100644 index 0000000..a29a6c7 --- /dev/null +++ b/librerias/gantt/code/modules/oldie-polyfills.js @@ -0,0 +1,16 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Old IE (v6, v7, v8) array polyfills for Highcharts v7+. + + (c) 2010-2019 Highsoft AS + Author: Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(e){"object"===typeof module&&module.exports?(e["default"]=e,module.exports=e):"function"===typeof define&&define.amd?define("highcharts/modules/oldie-polyfills",["highcharts"],function(f){e(f);e.Highcharts=f;return e}):e("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(e){function f(c,b,a,d){c.hasOwnProperty(b)||(c[b]=d.apply(null,a))}e=e?e._modules:{};f(e,"modules/oldie-polyfills.src.js",[],function(){Array.prototype.forEach||(Array.prototype.forEach=function(c,b){for(var a= +0,d=this.length;a 1 ? 0 : 1, accumulator = arguments.length > 1 ? initialValue : this[0], len = this.length; + for (; i < len; ++i) { + accumulator = func.call(context, accumulator, this[i], i, this); + } + return accumulator; + }; + } + if (!Function.prototype.bind) { + Function.prototype.bind = function () { + var thatFunc = this; + var thatArg = arguments[0]; + var args = Array.prototype.slice.call(arguments, 1); + if (typeof thatFunc !== 'function') { + // closest thing possible to the ECMAScript 5 + // internal IsCallable function + throw new TypeError('Function.prototype.bind - ' + + 'what is trying to be bound is not callable'); + } + return function () { + var funcArgs = args.concat(Array.prototype.slice.call(arguments)); + return thatFunc.apply(thatArg, funcArgs); + }; + }; + } + if (!Object.keys) { + Object.keys = function (obj) { + var result = [], prop; + for (prop in obj) { + if (Object.hasOwnProperty.call(obj, prop)) { + result.push(prop); + } + } + return result; + }; + } + // Add a getElementsByClassName function if the browser doesn't have one + // Limitation: only works with one class name + // Copyright: Eike Send https://eike.se/nd + // License: MIT License + if (!document.getElementsByClassName) { + document.getElementsByClassName = function (search) { + var d = document, elements, pattern, i, results = []; + if (d.querySelectorAll) { // IE8 + return d.querySelectorAll('.' + search); + } + if (d.evaluate) { // IE6, IE7 + pattern = './/*[contains(concat(\' \', @class, \' \'), \' ' + + search + ' \')]'; + elements = d.evaluate(pattern, d, null, 0, null); + while ((i = elements.iterateNext())) { + results.push(i); + } + } + else { + elements = d.getElementsByTagName('*'); + pattern = new RegExp('(^|\\s)' + search + '(\\s|$)'); + for (i = 0; i < elements.length; i++) { + if (pattern.test(elements[i].className)) { + results.push(elements[i]); + } + } + } + return results; + }; + } + + }); + _registerModule(_modules, 'masters/modules/oldie-polyfills.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/oldie.js b/librerias/gantt/code/modules/oldie.js new file mode 100644 index 0000000..08fe419 --- /dev/null +++ b/librerias/gantt/code/modules/oldie.js @@ -0,0 +1,36 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Old IE (v6, v7, v8) module for Highcharts v6+. + + (c) 2010-2019 Highsoft AS + Author: Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(e){"object"===typeof module&&module.exports?(e["default"]=e,module.exports=e):"function"===typeof define&&define.amd?define("highcharts/modules/oldie",["highcharts"],function(n){e(n);e.Highcharts=n;return e}):e("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(e){function n(m,e,g,n){m.hasOwnProperty(e)||(m[e]=n.apply(null,g))}e=e?e._modules:{};n(e,"modules/oldie.src.js",[e["parts/Globals.js"],e["parts/Color.js"],e["parts/Utilities.js"]],function(m,e,g){var n=e.parse,k=g.addEvent, +C=g.createElement,x=g.css,F=g.defined,G=g.discardElement,H=g.erase,z=g.extend,A=g.extendClass,O=g.isArray,L=g.isNumber,D=g.isObject;e=g.merge;var P=g.offset,u=g.pick,r=g.pInt,Q=g.uniqueKey,M=m.Chart,v=m.deg2rad,h=m.doc,N=m.noop,E=m.svg,y=m.SVGElement,t=m.SVGRenderer,w=m.win;m.getOptions().global.VMLRadialGradientURL="http://code.highcharts.com/8.1.0/gfx/vml-radial-gradient.png";h&&!h.defaultView&&(m.getStyle=g.getStyle=function(a,b){var c={width:"clientWidth",height:"clientHeight"}[b];if(a.style[b])return r(a.style[b]); +"opacity"===b&&(b="filter");if(c)return a.style.zoom=1,Math.max(a[c]-2*g.getStyle(a,"padding"),0);a=a.currentStyle[b.replace(/\-(\w)/g,function(a,b){return b.toUpperCase()})];"filter"===b&&(a=a.replace(/alpha\(opacity=([0-9]+)\)/,function(a,b){return b/100}));return""===a?1:r(a)});E||(k(y,"afterInit",function(){"text"===this.element.nodeName&&this.css({position:"absolute"})}),m.Pointer.prototype.normalize=function(a,b){a=a||w.event;a.target||(a.target=a.srcElement);b||(this.chartPosition=b=P(this.chart.container)); +return z(a,{chartX:Math.round(Math.max(a.x,a.clientX-b.left)),chartY:Math.round(a.y)})},M.prototype.ieSanitizeSVG=function(a){return a=a.replace(//g,"<$1title>").replace(/height=([^" ]+)/g,'height="$1"').replace(/width=([^" ]+)/g,'width="$1"').replace(/hc-svg-href="([^"]+)">/g,'xlink:href="$1"/>').replace(/ id=([^" >]+)/g,' id="$1"').replace(/class=([^" >]+)/g,'class="$1"').replace(/ transform /g," ").replace(/:(path|rect)/g,"$1").replace(/style="([^"]+)"/g, +function(a){return a.toLowerCase()})},M.prototype.isReadyToRender=function(){var a=this;return E||w!=w.top||"complete"===h.readyState?!0:(h.attachEvent("onreadystatechange",function(){h.detachEvent("onreadystatechange",a.firstRender);"complete"===h.readyState&&a.firstRender()}),!1)},h.createElementNS||(h.createElementNS=function(a,b){return h.createElement(b)}),m.addEventListenerPolyfill=function(a,b){function c(a){a.target=a.srcElement||w;b.call(d,a)}var d=this;d.attachEvent&&(d.hcEventsIE||(d.hcEventsIE= +{}),b.hcKey||(b.hcKey=Q()),d.hcEventsIE[b.hcKey]=c,d.attachEvent("on"+a,c))},m.removeEventListenerPolyfill=function(a,b){this.detachEvent&&(b=this.hcEventsIE[b.hcKey],this.detachEvent("on"+a,b))},k={docMode8:h&&8===h.documentMode,init:function(a,b){var c=["<",b,' filled="f" stroked="f"'],d=["position: ","absolute",";"],f="div"===b;("shape"===b||f)&&d.push("left:0;top:0;width:1px;height:1px;");d.push("visibility: ",f?"hidden":"visible");c.push(' style="',d.join(""),'"/>');b&&(c=f||"span"===b||"img"=== +b?c.join(""):a.prepVML(c),this.element=C(c));this.renderer=a},add:function(a){var b=this.renderer,c=this.element,d=b.box,f=a&&a.inverted;d=a?a.element||a:d;a&&(this.parentGroup=a);f&&b.invertChild(c,d);d.appendChild(c);this.added=!0;this.alignOnAdd&&!this.deferUpdateTransform&&this.updateTransform();if(this.onAdd)this.onAdd();this.className&&this.attr("class",this.className);return this},updateTransform:y.prototype.htmlUpdateTransform,setSpanRotation:function(){var a=this.rotation,b=Math.cos(a*v), +c=Math.sin(a*v);x(this.element,{filter:a?["progid:DXImageTransform.Microsoft.Matrix(M11=",b,", M12=",-c,", M21=",c,", M22=",b,", sizingMethod='auto expand')"].join(""):"none"})},getSpanCorrection:function(a,b,c,d,f){var p=d?Math.cos(d*v):1,e=d?Math.sin(d*v):0,I=u(this.elemHeight,this.element.offsetHeight);this.xCorr=0>p&&-a;this.yCorr=0>e&&-I;var l=0>p*e;this.xCorr+=e*b*(l?1-c:c);this.yCorr-=p*b*(d?l?c:1-c:1);f&&"left"!==f&&(this.xCorr-=a*c*(0>p?-1:1),d&&(this.yCorr-=I*c*(0>e?-1:1)),x(this.element, +{textAlign:f}))},pathToVML:function(a){for(var b=a.length,c=[];b--;)L(a[b])?c[b]=Math.round(10*a[b])-5:"Z"===a[b]?c[b]="x":(c[b]=a[b],!a.isArc||"wa"!==a[b]&&"at"!==a[b]||(c[b+5]===c[b+7]&&(c[b+7]+=a[b+7]>a[b+5]?1:-1),c[b+6]===c[b+8]&&(c[b+8]+=a[b+8]>a[b+6]?1:-1)));return c.join(" ")||"x"},clip:function(a){var b=this;if(a){var c=a.members;H(c,b);c.push(b);b.destroyClip=function(){H(c,b)};a=a.getCSS(b)}else b.destroyClip&&b.destroyClip(),a={clip:b.docMode8?"inherit":"rect(auto)"};return b.css(a)},css:y.prototype.htmlCss, +safeRemoveChild:function(a){a.parentNode&&G(a)},destroy:function(){this.destroyClip&&this.destroyClip();return y.prototype.destroy.apply(this)},on:function(a,b){this.element["on"+a]=function(){var a=w.event;a.target=a.srcElement;b(a)};return this},cutOffPath:function(a,b){a=a.split(/[ ,]/);var c=a.length;if(9===c||11===c)a[c-4]=a[c-2]=r(a[c-2])-10*b;return a.join(" ")},shadow:function(a,b,c){var d=[],f,p=this.element,e=this.renderer,I=p.style,l=p.path;l&&"string"!==typeof l.value&&(l="x");var m=l; +if(a){var g=u(a.width,3);var q=(a.opacity||.15)/g;for(f=1;3>=f;f++){var h=2*g+1-2*f;c&&(m=this.cutOffPath(l.value,h+.5));var k=[''];var n=C(e.prepVML(k),null,{left:r(I.left)+u(a.offsetX,1),top:r(I.top)+u(a.offsetY,1)});c&&(n.cutOff=h+1);k=[''];C(e.prepVML(k),null,null,n);b?b.element.appendChild(n):p.parentNode.insertBefore(n, +p);d.push(n)}this.shadows=d}return this},updateShadows:N,setAttr:function(a,b){this.docMode8?this.element[a]=b:this.element.setAttribute(a,b)},getAttr:function(a){return this.docMode8?this.element[a]:this.element.getAttribute(a)},classSetter:function(a){(this.added?this.element:this).className=a},dashstyleSetter:function(a,b,c){(c.getElementsByTagName("stroke")[0]||C(this.renderer.prepVML([""]),null,null,c))[b]=a||"solid";this[b]=a},dSetter:function(a,b,c){var d=this.shadows;a=a||[];this.d= +a.join&&a.join(" ");c.path=a=this.pathToVML(a);if(d)for(c=d.length;c--;)d[c].path=d[c].cutOff?this.cutOffPath(a,d[c].cutOff):a;this.setAttr(b,a)},fillSetter:function(a,b,c){var d=c.nodeName;"SPAN"===d?c.style.color=a:"IMG"!==d&&(c.filled="none"!==a,this.setAttr("fillcolor",this.renderer.color(a,c,b,this)))},"fill-opacitySetter":function(a,b,c){C(this.renderer.prepVML(["<",b.split("-")[0],' opacity="',a,'"/>']),null,null,c)},opacitySetter:N,rotationSetter:function(a,b,c){c=c.style;this[b]=c[b]=a;c.left= +-Math.round(Math.sin(a*v)+1)+"px";c.top=Math.round(Math.cos(a*v))+"px"},strokeSetter:function(a,b,c){this.setAttr("strokecolor",this.renderer.color(a,c,b,this))},"stroke-widthSetter":function(a,b,c){c.stroked=!!a;this[b]=a;L(a)&&(a+="px");this.setAttr("strokeweight",a)},titleSetter:function(a,b){this.setAttr(b,a)},visibilitySetter:function(a,b,c){"inherit"===a&&(a="visible");this.shadows&&this.shadows.forEach(function(c){c.style[b]=a});"DIV"===c.nodeName&&(a="hidden"===a?"-999em":0,this.docMode8|| +(c.style[b]=a?"visible":"hidden"),b="top");c.style[b]=a},xSetter:function(a,b,c){this[b]=a;"x"===b?b="left":"y"===b&&(b="top");this.updateClipping?(this[b]=a,this.updateClipping()):c.style[b]=a},zIndexSetter:function(a,b,c){c.style[b]=a},fillGetter:function(){return this.getAttr("fillcolor")||""},strokeGetter:function(){return this.getAttr("strokecolor")||""},classGetter:function(){return this.getAttr("className")||""}},k["stroke-opacitySetter"]=k["fill-opacitySetter"],m.VMLElement=k=A(y,k),k.prototype.ySetter= +k.prototype.widthSetter=k.prototype.heightSetter=k.prototype.xSetter,k={Element:k,isIE8:-1'];C(f.prepVML(g),null,null,b)};var u=a[0];var D=a[a.length-1];0D[0]&&a.push([1,D[1]]);a.forEach(function(a,b){e.test(a[1])?(J=n(a[1]),k=J.get("rgb"),r=J.get("a")):(k=a[1],r=1);z.push(100*a[0]+"% "+k);b?(v=r,w=k): +(t=r,y=k)});if("fill"===c)if("gradient"===h)c=q.x1||q[0]||0,a=q.y1||q[1]||0,u=q.x2||q[2]||0,q=q.y2||q[3]||0,x='angle="'+(90-180*Math.atan((q-a)/(u-c))/Math.PI)+'"',A();else{l=q.r;var E=2*l,F=2*l,G=q.cx,H=q.cy,K=b.radialReference,B;l=function(){K&&(B=d.getBBox(),G+=(K[0]-B.x)/B.width-.5,H+=(K[1]-B.y)/B.height-.5,E*=K[2]/B.width,F*=K[2]/B.height);x='src="'+m.getOptions().global.VMLRadialGradientURL+'" size="'+E+","+F+'" origin="0.5,0.5" position="'+G+","+H+'" color2="'+y+'" ';A()};d.added?l():d.onAdd= +l;l=w}else l=k}else if(e.test(a)&&"IMG"!==b.tagName){var J=n(a);d[c+"-opacitySetter"](J.get("a"),c,b);l=J.get("rgb")}else l=b.getElementsByTagName(c),l.length&&(l[0].opacity=1,l[0].type="solid"),l=a;return l},prepVML:function(a){var b=this.isIE8;a=a.join("");b?(a=a.replace("/>",' xmlns="urn:schemas-microsoft-com:vml" />'),a=-1===a.indexOf('style="')?a.replace("/>",' style="display:inline-block;behavior:url(#default#VML);" />'):a.replace('style="','style="display:inline-block;behavior:url(#default#VML);')): +a=a.replace("<","/g, '<$1title>') + .replace(/height=([^" ]+)/g, 'height="$1"') + .replace(/width=([^" ]+)/g, 'width="$1"') + .replace(/hc-svg-href="([^"]+)">/g, 'xlink:href="$1"/>') + .replace(/ id=([^" >]+)/g, ' id="$1"') // #4003 + .replace(/class=([^" >]+)/g, 'class="$1"') + .replace(/ transform /g, ' ') + .replace(/:(path|rect)/g, '$1') + .replace(/style="([^"]+)"/g, function (s) { + return s.toLowerCase(); + }); + return svg; + }; + /** + * VML namespaces can't be added until after complete. Listening + * for Perini's doScroll hack is not enough. + * + * @private + * @function Highcharts.Chart#isReadyToRender + */ + Chart.prototype.isReadyToRender = function () { + var chart = this; + // Note: win == win.top is required + if (!svg && + (win == win.top && // eslint-disable-line eqeqeq + doc.readyState !== 'complete')) { + doc.attachEvent('onreadystatechange', function () { + doc.detachEvent('onreadystatechange', chart.firstRender); + if (doc.readyState === 'complete') { + chart.firstRender(); + } + }); + return false; + } + return true; + }; + // IE compatibility hack for generating SVG content that it doesn't really + // understand. Used by the exporting module. + if (!doc.createElementNS) { + doc.createElementNS = function (ns, tagName) { + return doc.createElement(tagName); + }; + } + /** + * Old IE polyfill for addEventListener, called from inside the addEvent + * function. + * + * @private + * @function Highcharts.addEventListenerPolyfill + * @param {string} type + * @param {Highcharts.EventCallbackFunction} fn + * @return {void} + */ + H.addEventListenerPolyfill = function (type, fn) { + var el = this; + /** + * @private + */ + function wrappedFn(e) { + e.target = e.srcElement || win; // #2820 + fn.call(el, e); + } + if (el.attachEvent) { + if (!el.hcEventsIE) { + el.hcEventsIE = {}; + } + // unique function string (#6746) + if (!fn.hcKey) { + fn.hcKey = uniqueKey(); + } + // Link wrapped fn with original fn, so we can get this in + // removeEvent + el.hcEventsIE[fn.hcKey] = wrappedFn; + el.attachEvent('on' + type, wrappedFn); + } + }; + /** + * @private + * @function Highcharts.removeEventListenerPolyfill + * @param {string} type + * @param {Highcharts.EventCallbackFunction} fn + * @return {void} + */ + H.removeEventListenerPolyfill = function (type, fn) { + if (this.detachEvent) { + fn = this.hcEventsIE[fn.hcKey]; + this.detachEvent('on' + type, fn); + } + }; + /** + * The VML element wrapper. + * + * @private + * @class + * @name Highcharts.VMLElement + * + * @augments Highcharts.SVGElement + */ + VMLElement = { + docMode8: doc && doc.documentMode === 8, + /** + * Initialize a new VML element wrapper. It builds the markup as a + * string to minimize DOM traffic. + * + * @function Highcharts.VMLElement#init + * @param {Highcharts.VMLRenderer} renderer + * @param {string} nodeName + */ + init: function (renderer, nodeName) { + var wrapper = this, markup = ['<', nodeName, ' filled="f" stroked="f"'], style = ['position: ', 'absolute', ';'], isDiv = nodeName === 'div'; + // divs and shapes need size + if (nodeName === 'shape' || isDiv) { + style.push('left:0;top:0;width:1px;height:1px;'); + } + style.push('visibility: ', isDiv ? 'hidden' : 'visible'); + markup.push(' style="', style.join(''), '"/>'); + // create element with default attributes and style + if (nodeName) { + markup = isDiv || nodeName === 'span' || nodeName === 'img' ? + markup.join('') : + renderer.prepVML(markup); + wrapper.element = createElement(markup); + } + wrapper.renderer = renderer; + }, + /** + * Add the node to the given parent + * + * @function Highcharts.VMLElement + * @param {Highcharts.VMLElement} parent + * @return {Highcharts.VMLElement} + */ + add: function (parent) { + var wrapper = this, renderer = wrapper.renderer, element = wrapper.element, box = renderer.box, inverted = parent && parent.inverted, + // get the parent node + parentNode = parent ? + parent.element || parent : + box; + if (parent) { + this.parentGroup = parent; + } + // if the parent group is inverted, apply inversion on all children + if (inverted) { // only on groups + renderer.invertChild(element, parentNode); + } + // append it + parentNode.appendChild(element); + // align text after adding to be able to read offset + wrapper.added = true; + if (wrapper.alignOnAdd && !wrapper.deferUpdateTransform) { + wrapper.updateTransform(); + } + // fire an event for internal hooks + if (wrapper.onAdd) { + wrapper.onAdd(); + } + // IE8 Standards can't set the class name before the element is + // appended + if (this.className) { + this.attr('class', this.className); + } + return wrapper; + }, + /** + * VML always uses htmlUpdateTransform + * + * @function Highcharts.VMLElement#updateTransform + */ + updateTransform: SVGElement.prototype.htmlUpdateTransform, + /** + * Set the rotation of a span with oldIE's filter + * + * @function Highcharts.VMLElement#setSpanRotation + * @return {void} + */ + setSpanRotation: function () { + // Adjust for alignment and rotation. Rotation of useHTML content is + // not yet implemented but it can probably be implemented for + // Firefox 3.5+ on user request. FF3.5+ has support for CSS3 + // transform. The getBBox method also needs to be updated to + // compensate for the rotation, like it currently does for SVG. + // Test case: https://jsfiddle.net/highcharts/Ybt44/ + var rotation = this.rotation, costheta = Math.cos(rotation * deg2rad), sintheta = Math.sin(rotation * deg2rad); + css(this.element, { + filter: rotation ? [ + 'progid:DXImageTransform.Microsoft.Matrix(M11=', costheta, + ', M12=', -sintheta, ', M21=', sintheta, ', M22=', costheta, + ', sizingMethod=\'auto expand\')' + ].join('') : 'none' + }); + }, + /** + * Get the positioning correction for the span after rotating. + * + * @function Highcharts.VMLElement#getSpanCorrection + */ + getSpanCorrection: function (width, baseline, alignCorrection, rotation, align) { + var costheta = rotation ? Math.cos(rotation * deg2rad) : 1, sintheta = rotation ? Math.sin(rotation * deg2rad) : 0, height = pick(this.elemHeight, this.element.offsetHeight), quad, nonLeft = align && align !== 'left'; + // correct x and y + this.xCorr = (costheta < 0 && -width); + this.yCorr = (sintheta < 0 && -height); + // correct for baseline and corners spilling out after rotation + quad = costheta * sintheta < 0; + this.xCorr += (sintheta * + baseline * + (quad ? 1 - alignCorrection : alignCorrection)); + this.yCorr -= (costheta * + baseline * + (rotation ? (quad ? alignCorrection : 1 - alignCorrection) : 1)); + // correct for the length/height of the text + if (nonLeft) { + this.xCorr -= + width * alignCorrection * (costheta < 0 ? -1 : 1); + if (rotation) { + this.yCorr -= (height * + alignCorrection * + (sintheta < 0 ? -1 : 1)); + } + css(this.element, { + textAlign: align + }); + } + }, + /** + * Converts a subset of an SVG path definition to its VML counterpart. + * Takes an array as the parameter and returns a string. + * + * @function Highcharts.VMLElement#pathToVML + */ + pathToVML: function (value) { + // convert paths + var i = value.length, path = []; + while (i--) { + // Multiply by 10 to allow subpixel precision. + // Substracting half a pixel seems to make the coordinates + // align with SVG, but this hasn't been tested thoroughly + if (isNumber(value[i])) { + path[i] = Math.round(value[i] * 10) - 5; + } + else if (value[i] === 'Z') { // close the path + path[i] = 'x'; + } + else { + path[i] = value[i]; + // When the start X and end X coordinates of an arc are too + // close, they are rounded to the same value above. In this + // case, substract or add 1 from the end X and Y positions. + // #186, #760, #1371, #1410. + if (value.isArc && + (value[i] === 'wa' || value[i] === 'at')) { + // Start and end X + if (path[i + 5] === path[i + 7]) { + path[i + 7] += + value[i + 7] > value[i + 5] ? 1 : -1; + } + // Start and end Y + if (path[i + 6] === path[i + 8]) { + path[i + 8] += + value[i + 8] > value[i + 6] ? 1 : -1; + } + } + } + } + return path.join(' ') || 'x'; + }, + /** + * Set the element's clipping to a predefined rectangle + * + * @function Highcharts.VMLElement#clip + * @param {Highcharts.VMLClipRectObject} clipRect + * @return {Highcharts.VMLElement} + */ + clip: function (clipRect) { + var wrapper = this, clipMembers, cssRet; + if (clipRect) { + clipMembers = clipRect.members; + // Ensure unique list of elements (#1258) + erase(clipMembers, wrapper); + clipMembers.push(wrapper); + wrapper.destroyClip = function () { + erase(clipMembers, wrapper); + }; + cssRet = clipRect.getCSS(wrapper); + } + else { + if (wrapper.destroyClip) { + wrapper.destroyClip(); + } + cssRet = { + clip: wrapper.docMode8 ? 'inherit' : 'rect(auto)' + }; // #1214 + } + return wrapper.css(cssRet); + }, + /** + * Set styles for the element + * + * @function Highcharts.VMLElement#css + * @param {Highcharts.CSSObject} styles + * @return {Highcharts.VMLElement} + */ + css: SVGElement.prototype.htmlCss, + /** + * Removes a child either by removeChild or move to garbageBin. + * Issue 490; in VML removeChild results in Orphaned nodes according to + * sIEve, discardElement does not. + * + * @function Highcharts.VMLElement#safeRemoveChild + * @param {Highcharts.HTMLDOMElement} element + * @return {void} + */ + safeRemoveChild: function (element) { + // discardElement will detach the node from its parent before + // attaching it to the garbage bin. Therefore it is important that + // the node is attached and have parent. + if (element.parentNode) { + discardElement(element); + } + }, + /** + * Extend element.destroy by removing it from the clip members array + * + * @function Highcharts.VMLElement#destroy + */ + destroy: function () { + if (this.destroyClip) { + this.destroyClip(); + } + return SVGElement.prototype.destroy.apply(this); + }, + /** + * Add an event listener. VML override for normalizing event parameters. + * + * @function Highcharts.VMLElement#on + * @param {string} eventType + * @param {Function} handler + * @return {Highcharts.VMLElement} + */ + on: function (eventType, handler) { + // simplest possible event model for internal use + this.element['on' + eventType] = function () { + var e = win.event; + e.target = e.srcElement; + handler(e); + }; + return this; + }, + /** + * In stacked columns, cut off the shadows so that they don't overlap + * + * @function Highcharts.VMLElement#cutOffPath + * @param {string} path + * @param {number} length + * @return {string} + */ + cutOffPath: function (path, length) { + var len; + // The extra comma tricks the trailing comma remover in + // "gulp scripts" task + path = path.split(/[ ,]/); + len = path.length; + if (len === 9 || len === 11) { + path[len - 4] = path[len - 2] = + pInt(path[len - 2]) - 10 * length; + } + return path.join(' '); + }, + /** + * Apply a drop shadow by copying elements and giving them different + * strokes. + * + * @function Highcharts.VMLElement#shadow + * @param {Highcharts.ShadowOptionsObject} shadowOptions + * @param {Highcharts.VMLElement} group + * @param {boolean} cutOff + * @return {Highcharts.VMLElement} + */ + shadow: function (shadowOptions, group, cutOff) { + var shadows = [], i, element = this.element, renderer = this.renderer, shadow, elemStyle = element.style, markup, path = element.path, strokeWidth, modifiedPath, shadowWidth, shadowElementOpacity; + // some times empty paths are not strings + if (path && typeof path.value !== 'string') { + path = 'x'; + } + modifiedPath = path; + if (shadowOptions) { + shadowWidth = pick(shadowOptions.width, 3); + shadowElementOpacity = + (shadowOptions.opacity || 0.15) / shadowWidth; + for (i = 1; i <= 3; i++) { + strokeWidth = (shadowWidth * 2) + 1 - (2 * i); + // Cut off shadows for stacked column items + if (cutOff) { + modifiedPath = this.cutOffPath(path.value, strokeWidth + 0.5); + } + markup = [ + '' + ]; + shadow = createElement(renderer.prepVML(markup), null, { + left: pInt(elemStyle.left) + + pick(shadowOptions.offsetX, 1), + top: pInt(elemStyle.top) + + pick(shadowOptions.offsetY, 1) + }); + if (cutOff) { + shadow.cutOff = strokeWidth + 1; + } + // apply the opacity + markup = [ + '' + ]; + createElement(renderer.prepVML(markup), null, null, shadow); + // insert it + if (group) { + group.element.appendChild(shadow); + } + else { + element.parentNode + .insertBefore(shadow, element); + } + // record it + shadows.push(shadow); + } + this.shadows = shadows; + } + return this; + }, + updateShadows: noop, + setAttr: function (key, value) { + if (this.docMode8) { // IE8 setAttribute bug + this.element[key] = value; + } + else { + this.element.setAttribute(key, value); + } + }, + getAttr: function (key) { + if (this.docMode8) { // IE8 setAttribute bug + return this.element[key]; + } + return this.element.getAttribute(key); + }, + classSetter: function (value) { + // IE8 Standards mode has problems retrieving the className unless + // set like this. IE8 Standards can't set the class name before the + // element is appended. + (this.added ? this.element : this).className = value; + }, + dashstyleSetter: function (value, key, element) { + var strokeElem = element.getElementsByTagName('stroke')[0] || + createElement(this.renderer.prepVML(['']), null, null, element); + strokeElem[key] = value || 'solid'; + // Because changing stroke-width will change the dash length and + // cause an epileptic effect + this[key] = value; + }, + dSetter: function (value, key, element) { + var i, shadows = this.shadows; + value = value || []; + // Used in getter for animation + this.d = value.join && value.join(' '); + element.path = value = this.pathToVML(value); + // update shadows + if (shadows) { + i = shadows.length; + while (i--) { + shadows[i].path = shadows[i].cutOff ? + this.cutOffPath(value, shadows[i].cutOff) : + value; + } + } + this.setAttr(key, value); + }, + fillSetter: function (value, key, element) { + var nodeName = element.nodeName; + if (nodeName === 'SPAN') { // text color + element.style.color = value; + } + else if (nodeName !== 'IMG') { // #1336 + element.filled = value !== 'none'; + this.setAttr('fillcolor', this.renderer.color(value, element, key, this)); + } + }, + 'fill-opacitySetter': function (value, key, element) { + createElement(this.renderer.prepVML(['<', key.split('-')[0], ' opacity="', value, '"/>']), null, null, element); + }, + // Don't bother - animation is too slow and filters introduce artifacts + opacitySetter: noop, + rotationSetter: function (value, key, element) { + var style = element.style; + // style is for #1873: + this[key] = style[key] = value; + // Correction for the 1x1 size of the shape container. Used in gauge + // needles. + style.left = + -Math.round(Math.sin(value * deg2rad) + 1) + 'px'; + style.top = + Math.round(Math.cos(value * deg2rad)) + 'px'; + }, + strokeSetter: function (value, key, element) { + this.setAttr('strokecolor', this.renderer.color(value, element, key, this)); + }, + 'stroke-widthSetter': function (value, key, element) { + element.stroked = !!value; // VML "stroked" attribute + this[key] = value; // used in getter, issue #113 + if (isNumber(value)) { + value += 'px'; + } + this.setAttr('strokeweight', value); + }, + titleSetter: function (value, key) { + this.setAttr(key, value); + }, + visibilitySetter: function (value, key, element) { + // Handle inherited visibility + if (value === 'inherit') { + value = 'visible'; + } + // Let the shadow follow the main element + if (this.shadows) { + this.shadows.forEach(function (shadow) { + shadow.style[key] = value; + }); + } + // Instead of toggling the visibility CSS property, move the div out + // of the viewport. This works around #61 and #586 + if (element.nodeName === 'DIV') { + value = value === 'hidden' ? '-999em' : 0; + // In order to redraw, IE7 needs the div to be visible when + // tucked away outside the viewport. So the visibility is + // actually opposite of the expected value. This applies to the + // tooltip only. + if (!this.docMode8) { + element.style[key] = value ? 'visible' : 'hidden'; + } + key = 'top'; + } + element.style[key] = value; + }, + xSetter: function (value, key, element) { + this[key] = value; // used in getter + if (key === 'x') { + key = 'left'; + } + else if (key === 'y') { + key = 'top'; + } + // clipping rectangle special + if (this.updateClipping) { + // the key is now 'left' or 'top' for 'x' and 'y' + this[key] = value; + this.updateClipping(); + } + else { + // normal + element.style[key] = value; + } + }, + zIndexSetter: function (value, key, element) { + element.style[key] = value; + }, + fillGetter: function () { + return this.getAttr('fillcolor') || ''; + }, + strokeGetter: function () { + return this.getAttr('strokecolor') || ''; + }, + // #7850 + classGetter: function () { + return this.getAttr('className') || ''; + } + }; + VMLElement['stroke-opacitySetter'] = + VMLElement['fill-opacitySetter']; + H.VMLElement = VMLElement = extendClass(SVGElement, VMLElement); + // Some shared setters + VMLElement.prototype.ySetter = + VMLElement.prototype.widthSetter = + VMLElement.prototype.heightSetter = + VMLElement.prototype.xSetter; + /** + * The VML renderer + * + * @private + * @class + * @name Highcharts.VMLRenderer + * + * @augments Highcharts.SVGRenderer + */ + VMLRendererExtension = { + Element: VMLElement, + isIE8: win.navigator.userAgent.indexOf('MSIE 8.0') > -1, + /** + * Initialize the VMLRenderer. + * + * @function Highcharts.VMLRenderer#init + * @param {Highcharts.HTMLDOMElement} container + * @param {number} width + * @param {number} height + * @return {void} + */ + init: function (container, width, height) { + var renderer = this, boxWrapper, box, css; + // Extended SVGRenderer member + this.crispPolyLine = SVGRenderer.prototype.crispPolyLine; + renderer.alignedObjects = []; + boxWrapper = renderer.createElement('div') + .css({ position: 'relative' }); + box = boxWrapper.element; + container.appendChild(boxWrapper.element); + // generate the containing box + renderer.isVML = true; + renderer.box = box; + renderer.boxWrapper = boxWrapper; + renderer.gradients = {}; + renderer.cache = {}; // Cache for numerical bounding boxes + renderer.cacheKeys = []; + renderer.imgCount = 0; + renderer.setSize(width, height, false); + // The only way to make IE6 and IE7 print is to use a global + // namespace. However, with IE8 the only way to make the dynamic + // shapes visible in screen and print mode seems to be to add the + // xmlns attribute and the behaviour style inline. + if (!doc.namespaces.hcv) { + doc.namespaces.add('hcv', 'urn:schemas-microsoft-com:vml'); + // Setup default CSS (#2153, #2368, #2384) + css = 'hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke' + + '{ behavior:url(#default#VML); display: inline-block; } '; + try { + doc.createStyleSheet().cssText = css; + } + catch (e) { + doc.styleSheets[0].cssText += css; + } + } + }, + /** + * Detect whether the renderer is hidden. This happens when one of the + * parent elements has display: none + * + * @function Highcharts.VMLRenderer#isHidden + */ + isHidden: function () { + return !this.box.offsetWidth; + }, + /** + * Define a clipping rectangle. In VML it is accomplished by storing the + * values for setting the CSS style to all associated members. + * + * @function Highcharts.VMLRenderer#clipRect + * @param {number|Highcharts.SizeObject} x + * @param {number} y + * @param {number} width + * @param {number} height + * @return {Highcharts.VMLElement} + */ + clipRect: function (x, y, width, height) { + // create a dummy element + var clipRect = this.createElement(), isObj = isObject(x); + // mimic a rectangle with its style object for automatic updating in + // attr + return extend(clipRect, { + members: [], + count: 0, + left: (isObj ? x.x : x) + 1, + top: (isObj ? x.y : y) + 1, + width: (isObj ? x.width : width) - 1, + height: (isObj ? x.height : height) - 1, + getCSS: function (wrapper) { + var element = wrapper.element, nodeName = element.nodeName, isShape = nodeName === 'shape', inverted = wrapper.inverted, rect = this, top = rect.top - (isShape ? element.offsetTop : 0), left = rect.left, right = left + rect.width, bottom = top + rect.height, ret = { + clip: 'rect(' + + Math.round(inverted ? left : top) + 'px,' + + Math.round(inverted ? bottom : right) + 'px,' + + Math.round(inverted ? right : bottom) + 'px,' + + Math.round(inverted ? top : left) + 'px)' + }; + // issue 74 workaround + if (!inverted && wrapper.docMode8 && nodeName === 'DIV') { + extend(ret, { + width: right + 'px', + height: bottom + 'px' + }); + } + return ret; + }, + // used in attr and animation to update the clipping of all + // members + updateClipping: function () { + clipRect.members.forEach(function (member) { + // Member.element is falsy on deleted series, like in + // stock/members/series-remove demo. Should be removed + // from members, but this will do. + if (member.element) { + member.css(clipRect.getCSS(member)); + } + }); + } + }); + }, + /** + * Take a color and return it if it's a string, make it a gradient if + * it's a gradient configuration object, and apply opacity. + * + * @function Highcharts.VMLRenderer#color + * + * @param {T} color + * The color or config object + * + * @return {T} + */ + color: function (colorOption, elem, prop, wrapper) { + var renderer = this, colorObject, regexRgba = /^rgba/, markup, fillType, ret = 'none'; + // Check for linear or radial gradient + if (colorOption && + colorOption.linearGradient) { + fillType = 'gradient'; + } + else if (colorOption && + colorOption.radialGradient) { + fillType = 'pattern'; + } + if (fillType) { + var stopColor, stopOpacity, gradient = (colorOption.linearGradient || + colorOption.radialGradient), x1, y1, x2, y2, opacity1, opacity2, color1, color2, fillAttr = '', stops = colorOption.stops, firstStop, lastStop, colors = [], addFillNode = function () { + // Add the fill subnode. When colors attribute is used, + // the meanings of opacity and o:opacity2 are reversed. + markup = ['']; + createElement(renderer.prepVML(markup), null, null, elem); + }; + // Extend from 0 to 1 + firstStop = stops[0]; + lastStop = stops[stops.length - 1]; + if (firstStop[0] > 0) { + stops.unshift([ + 0, + firstStop[1] + ]); + } + if (lastStop[0] < 1) { + stops.push([ + 1, + lastStop[1] + ]); + } + // Compute the stops + stops.forEach(function (stop, i) { + if (regexRgba.test(stop[1])) { + colorObject = color(stop[1]); + stopColor = colorObject.get('rgb'); + stopOpacity = colorObject.get('a'); + } + else { + stopColor = stop[1]; + stopOpacity = 1; + } + // Build the color attribute + colors.push((stop[0] * 100) + '% ' + stopColor); + // Only start and end opacities are allowed, so we use the + // first and the last + if (!i) { + opacity1 = stopOpacity; + color2 = stopColor; + } + else { + opacity2 = stopOpacity; + color1 = stopColor; + } + }); + // Apply the gradient to fills only. + if (prop === 'fill') { + // Handle linear gradient angle + if (fillType === 'gradient') { + x1 = gradient.x1 || gradient[0] || 0; + y1 = gradient.y1 || gradient[1] || 0; + x2 = gradient.x2 || gradient[2] || 0; + y2 = gradient.y2 || gradient[3] || 0; + fillAttr = 'angle="' + (90 - Math.atan((y2 - y1) / // y vector + (x2 - x1) // x vector + ) * 180 / Math.PI) + '"'; + addFillNode(); + // Radial (circular) gradient + } + else { + var r = gradient.r, sizex = r * 2, sizey = r * 2, cx = gradient.cx, cy = gradient.cy, radialReference = elem.radialReference, bBox, applyRadialGradient = function () { + if (radialReference) { + bBox = wrapper.getBBox(); + cx += (radialReference[0] - bBox.x) / + bBox.width - 0.5; + cy += (radialReference[1] - bBox.y) / + bBox.height - 0.5; + sizex *= radialReference[2] / bBox.width; + sizey *= radialReference[2] / bBox.height; + } + fillAttr = + 'src="' + H.getOptions().global.VMLRadialGradientURL + + '" ' + + 'size="' + sizex + ',' + sizey + '" ' + + 'origin="0.5,0.5" ' + + 'position="' + cx + ',' + cy + '" ' + + 'color2="' + color2 + '" '; + addFillNode(); + }; + // Apply radial gradient + if (wrapper.added) { + applyRadialGradient(); + } + else { + // We need to know the bounding box to get the size + // and position right + wrapper.onAdd = applyRadialGradient; + } + // The fill element's color attribute is broken in IE8 + // standards mode, so we need to set the parent shape's + // fillcolor attribute instead. + ret = color1; + } + // Gradients are not supported for VML stroke, return the first + // color. #722. + } + else { + ret = stopColor; + } + // If the color is an rgba color, split it and add a fill node + // to hold the opacity component + } + else if (regexRgba.test(colorOption) && elem.tagName !== 'IMG') { + colorObject = color(colorOption); + wrapper[prop + '-opacitySetter'](colorObject.get('a'), prop, elem); + ret = colorObject.get('rgb'); + } + else { + // 'stroke' or 'fill' node + var propNodes = elem.getElementsByTagName(prop); + if (propNodes.length) { + propNodes[0].opacity = 1; + propNodes[0].type = 'solid'; + } + ret = colorOption; + } + return ret; + }, + /** + * Take a VML string and prepare it for either IE8 or IE6/IE7. + * + * @function Highcharts.VMLRenderer#prepVML + * + * @param {Array<(number|string)>} markup + * A string array of the VML markup to prepare + * + * @return {string} + */ + prepVML: function (markup) { + var vmlStyle = 'display:inline-block;behavior:url(#default#VML);', isIE8 = this.isIE8; + markup = markup.join(''); + if (isIE8) { // add xmlns and style inline + markup = markup.replace('/>', ' xmlns="urn:schemas-microsoft-com:vml" />'); + if (markup.indexOf('style="') === -1) { + markup = markup.replace('/>', ' style="' + vmlStyle + '" />'); + } + else { + markup = markup.replace('style="', 'style="' + vmlStyle); + } + } + else { // add namespace + markup = markup.replace('<', '} x + * @param {number} [y] + * @param {number} [r] + * @return {Highcharts.VMLElement} + */ + circle: function (x, y, r) { + var circle = this.symbol('circle'); + if (isObject(x)) { + r = x.r; + y = x.y; + x = x.x; + } + circle.isCircle = true; // Causes x and y to mean center (#1682) + circle.r = r; + return circle.attr({ x: x, y: y }); + }, + /** + * Create a group using an outer div and an inner v:group to allow + * rotating and flipping. A simple v:group would have problems with + * positioning child HTML elements and CSS clip. + * + * @function Highcharts.VMLRenderer#g + * + * @param {string} name + * The name of the group + * + * @return {Highcharts.VMLElement} + */ + g: function (name) { + var wrapper, attribs; + // set the class name + if (name) { + attribs = { + 'className': 'highcharts-' + name, + 'class': 'highcharts-' + name + }; + } + // the div to hold HTML and clipping + wrapper = this.createElement('div').attr(attribs); + return wrapper; + }, + /** + * VML override to create a regular HTML image. + * + * @function Highcharts.VMLRenderer#image + * + * @param {string} src + * + * @param {number} x + * + * @param {number} y + * + * @param {number} width + * + * @param {number} height + * @return {Highcharts.VMLElement} + */ + image: function (src, x, y, width, height) { + var obj = this.createElement('img').attr({ src: src }); + if (arguments.length > 1) { + obj.attr({ + x: x, + y: y, + width: width, + height: height + }); + } + return obj; + }, + /** + * For rectangles, VML uses a shape for rect to overcome bugs and + * rotation problems + * + * @function Highcharts.VMLRenderer#createElement + * @param {string} nodeName + * @return {Highcharts.VMLElement} + */ + createElement: function (nodeName) { + return nodeName === 'rect' ? + this.symbol(nodeName) : + SVGRenderer.prototype.createElement.call(this, nodeName); + }, + /** + * In the VML renderer, each child of an inverted div (group) is + * inverted + * + * @function Highcharts.VMLRenderer#invertChild + * + * @param {Highcharts.HTMLDOMElement} element + * + * @param {Highcharts.HTMLDOMElement} parentNode + */ + invertChild: function (element, parentNode) { + var ren = this, parentStyle = parentNode.style, imgStyle = element.tagName === 'IMG' && element.style; // #1111 + css(element, { + flip: 'x', + left: pInt(parentStyle.width) - + (imgStyle ? pInt(imgStyle.top) : 1), + top: pInt(parentStyle.height) - + (imgStyle ? pInt(imgStyle.left) : 1), + rotation: -90 + }); + // Recursively invert child elements, needed for nested composite + // shapes like box plots and error bars. #1680, #1806. + [].forEach.call(element.childNodes, function (child) { + ren.invertChild(child, element); + }); + }, + /** + * Symbol definitions that override the parent SVG renderer's symbols + * + * @name Highcharts.VMLRenderer#symbols + * @type {Highcharts.Dictionary} + */ + symbols: { + // VML specific arc function + arc: function (x, y, w, h, options) { + var start = options.start, end = options.end, radius = options.r || w || h, innerRadius = options.innerR, cosStart = Math.cos(start), sinStart = Math.sin(start), cosEnd = Math.cos(end), sinEnd = Math.sin(end), ret; + if (end - start === 0) { // no angle, don't show it. + return ['x']; + } + ret = [ + 'wa', + x - radius, + y - radius, + x + radius, + y + radius, + x + radius * cosStart, + y + radius * sinStart, + x + radius * cosEnd, + y + radius * sinEnd // end y + ]; + if (options.open && !innerRadius) { + ret.push('e', 'M', x, // - innerRadius, + y // - innerRadius + ); + } + ret.push('at', // anti clockwise arc to + x - innerRadius, // left + y - innerRadius, // top + x + innerRadius, // right + y + innerRadius, // bottom + x + innerRadius * cosEnd, // start x + y + innerRadius * sinEnd, // start y + x + innerRadius * cosStart, // end x + y + innerRadius * sinStart, // end y + 'x', // finish path + 'e' // close + ); + ret.isArc = true; + return ret; + }, + // Add circle symbol path. This performs significantly faster than + // v:oval. + circle: function (x, y, w, h, wrapper) { + if (wrapper && defined(wrapper.r)) { + w = h = 2 * wrapper.r; + } + // Center correction, #1682 + if (wrapper && wrapper.isCircle) { + x -= w / 2; + y -= h / 2; + } + // Return the path + return [ + 'wa', + x, + y, + x + w, + y + h, + x + w, + y + h / 2, + x + w, + y + h / 2, + 'e' // close + ]; + }, + /** + * Add rectangle symbol path which eases rotation and omits arcsize + * problems compared to the built-in VML roundrect shape. When + * borders are not rounded, use the simpler square path, else use + * the callout path without the arrow. + */ + rect: function (x, y, w, h, options) { + return SVGRenderer.prototype.symbols[!defined(options) || !options.r ? 'square' : 'callout'].call(0, x, y, w, h, options); + } + } + }; + H.VMLRenderer = VMLRenderer = function () { + this.init.apply(this, arguments); + }; + VMLRenderer.prototype = merge(SVGRenderer.prototype, VMLRendererExtension); + // general renderer + H.Renderer = VMLRenderer; + } + SVGRenderer.prototype.getSpanWidth = function (wrapper, tspan) { + var renderer = this, bBox = wrapper.getBBox(true), actualWidth = bBox.width; + // Old IE cannot measure the actualWidth for SVG elements (#2314) + if (!svg && renderer.forExport) { + actualWidth = renderer.measureSpanWidth(tspan.firstChild.data, wrapper.styles); + } + return actualWidth; + }; + // This method is used with exporting in old IE, when emulating SVG (see #2314) + SVGRenderer.prototype.measureSpanWidth = function (text, styles) { + var measuringSpan = doc.createElement('span'), offsetWidth, textNode = doc.createTextNode(text); + measuringSpan.appendChild(textNode); + css(measuringSpan, styles); + this.box.appendChild(measuringSpan); + offsetWidth = measuringSpan.offsetWidth; + discardElement(measuringSpan); // #2463 + return offsetWidth; + }; + + }); + _registerModule(_modules, 'masters/modules/oldie.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/organization.js b/librerias/gantt/code/modules/organization.js new file mode 100644 index 0000000..d34cba8 --- /dev/null +++ b/librerias/gantt/code/modules/organization.js @@ -0,0 +1,19 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + Organization chart series type + + (c) 2019-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/organization",["highcharts","highcharts/modules/sankey"],function(f){b(f);b.Highcharts=f;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function f(b,m,f,r){b.hasOwnProperty(m)||(b[m]=r.apply(null,f))}b=b?b._modules:{};f(b,"modules/organization.src.js",[b["parts/Globals.js"],b["parts/Utilities.js"]],function(b,f){var m= +f.css,r=f.pick,u=f.seriesType,v=f.wrap,q=b.seriesTypes.sankey.prototype;u("organization","sankey",{borderColor:"#666666",borderRadius:3,linkRadius:10,borderWidth:1,dataLabels:{nodeFormatter:function(){function a(a){return Object.keys(a).reduce(function(c,d){return c+d+":"+a[d]+";"},'style="')+'"'}var c={width:"100%",height:"100%",display:"flex","flex-direction":"row","align-items":"center","justify-content":"center"},g={"max-height":"100%","border-radius":"50%"},d={width:"100%",padding:0,"text-align":"center", +"white-space":"normal"},e={margin:0},t={margin:0},b={opacity:.75,margin:"5px"};this.point.image&&(g["max-width"]="30%",d.width="70%");this.series.chart.renderer.forExport&&(c.display="block",d.position="absolute",d.left=this.point.image?"30%":0,d.top=0);c="
    ";this.point.image&&(c+='");c+="
    ";this.point.name&&(c+="

    "+this.point.name+"

    ");this.point.title&&(c+="

    "+(this.point.title||"")+"

    ");this.point.description&& +(c+="

    "+this.point.description+"

    ");return c+"
    "},style:{fontWeight:"normal",fontSize:"13px"},useHTML:!0},hangingIndent:20,linkColor:"#666666",linkLineWidth:1,nodeWidth:50,tooltip:{nodeFormat:"{point.name}
    {point.title}
    {point.description}"}},{pointAttribs:function(a,c){var g=this,d=q.pointAttribs.call(g,a,c),e=g.mapOptionsToLevel[(a.isNode?a.level:a.fromNode.level)||0]||{},t=a.options,b=e.states&&e.states[c]||{};c=["borderRadius","linkColor","linkLineWidth"].reduce(function(a, +c){a[c]=r(b[c],t[c],e[c],g.options[c]);return a},{});a.isNode?c.borderRadius&&(d.r=c.borderRadius):(d.stroke=c.linkColor,d["stroke-width"]=c.linkLineWidth,delete d.fill);return d},createNode:function(a){a=q.createNode.call(this,a);a.getSum=function(){return 1};return a},createNodeColumn:function(){var a=q.createNodeColumn.call(this);v(a,"offset",function(a,g,d){a=a.call(this,g,d);return g.hangsFrom?{absoluteTop:g.hangsFrom.nodeY}:a});return a},translateNode:function(a,c){q.translateNode.call(this, +a,c);a.hangsFrom&&(a.shapeArgs.height-=this.options.hangingIndent,this.chart.inverted||(a.shapeArgs.y+=this.options.hangingIndent));a.nodeHeight=this.chart.inverted?a.shapeArgs.width:a.shapeArgs.height},curvedPath:function(a,c){for(var g=[],d=0;d=n)&&(l=h=Math.floor(h+(p?-.5:.5)*b.shapeArgs.width)+d,k=b.shapeArgs.y,0'; + if (this.point.image) { + html += ''; + } + html += '
    '; + if (this.point.name) { + html += '

    ' + + this.point.name + '

    '; + } + if (this.point.title) { + html += '

    ' + + (this.point.title || '') + '

    '; + } + if (this.point.description) { + html += '

    ' + + this.point.description + '

    '; + } + html += '
    ' + + ''; + return html; + }, + /* eslint-enable valid-jsdoc */ + style: { + /** @internal */ + fontWeight: 'normal', + /** @internal */ + fontSize: '13px' + }, + useHTML: true + }, + /** + * The indentation in pixels of hanging nodes, nodes which parent has + * [layout](#series.organization.nodes.layout) set to `hanging`. + * + * @private + */ + hangingIndent: 20, + /** + * The color of the links between nodes. + * + * @type {Highcharts.ColorString} + * @private + */ + linkColor: '#666666', + /** + * The line width of the links connecting nodes, in pixels. + * + * @sample highcharts/series-organization/link-options + * Square links + * + * @private + */ + linkLineWidth: 1, + /** + * In a horizontal chart, the width of the nodes in pixels. Node that + * most organization charts are vertical, so the name of this option + * is counterintuitive. + * + * @private + */ + nodeWidth: 50, + tooltip: { + nodeFormat: '{point.name}
    {point.title}
    {point.description}' + } + }, { + pointAttribs: function (point, state) { + var series = this, attribs = base.pointAttribs.call(series, point, state), level = point.isNode ? point.level : point.fromNode.level, levelOptions = series.mapOptionsToLevel[level || 0] || {}, options = point.options, stateOptions = (levelOptions.states && levelOptions.states[state]) || {}, values = ['borderRadius', 'linkColor', 'linkLineWidth'] + .reduce(function (obj, key) { + obj[key] = pick(stateOptions[key], options[key], levelOptions[key], series.options[key]); + return obj; + }, {}); + if (!point.isNode) { + attribs.stroke = values.linkColor; + attribs['stroke-width'] = values.linkLineWidth; + delete attribs.fill; + } + else { + if (values.borderRadius) { + attribs.r = values.borderRadius; + } + } + return attribs; + }, + createNode: function (id) { + var node = base.createNode + .call(this, id); + // All nodes in an org chart are equal width + node.getSum = function () { + return 1; + }; + return node; + }, + createNodeColumn: function () { + var column = base.createNodeColumn.call(this); + // Wrap the offset function so that the hanging node's children are + // aligned to their parent + wrap(column, 'offset', function (proceed, node, factor) { + var offset = proceed.call(this, node, factor); // eslint-disable-line no-invalid-this + // Modify the default output if the parent's layout is 'hanging' + if (node.hangsFrom) { + return { + absoluteTop: node.hangsFrom.nodeY + }; + } + return offset; + }); + return column; + }, + translateNode: function (node, column) { + base.translateNode.call(this, node, column); + if (node.hangsFrom) { + node.shapeArgs.height -= + this.options.hangingIndent; + if (!this.chart.inverted) { + node.shapeArgs.y += this.options.hangingIndent; + } + } + node.nodeHeight = this.chart.inverted ? + node.shapeArgs.width : + node.shapeArgs.height; + }, + // General function to apply corner radius to a path - can be lifted to + // renderer or utilities if we need it elsewhere. + curvedPath: function (path, r) { + var d = []; + for (var i = 0; i < path.length; i++) { + var x = path[i][1]; + var y = path[i][2]; + if (typeof x === 'number' && typeof y === 'number') { + // moveTo + if (i === 0) { + d.push(['M', x, y]); + } + else if (i === path.length - 1) { + d.push(['L', x, y]); + // curveTo + } + else if (r) { + var prevSeg = path[i - 1]; + var nextSeg = path[i + 1]; + if (prevSeg && nextSeg) { + var x1 = prevSeg[1], y1 = prevSeg[2], x2 = nextSeg[1], y2 = nextSeg[2]; + // Only apply to breaks + if (typeof x1 === 'number' && + typeof x2 === 'number' && + typeof y1 === 'number' && + typeof y2 === 'number' && + x1 !== x2 && + y1 !== y2) { + var directionX = x1 < x2 ? 1 : -1, directionY = y1 < y2 ? 1 : -1; + d.push([ + 'L', + x - directionX * Math.min(Math.abs(x - x1), r), + y - directionY * Math.min(Math.abs(y - y1), r) + ], [ + 'C', + x, + y, + x, + y, + x + directionX * Math.min(Math.abs(x - x2), r), + y + directionY * Math.min(Math.abs(y - y2), r) + ]); + } + } + // lineTo + } + else { + d.push(['L', x, y]); + } + } + } + return d; + }, + translateLink: function (point) { + var fromNode = point.fromNode, toNode = point.toNode, crisp = Math.round(this.options.linkLineWidth) % 2 / 2, x1 = Math.floor(fromNode.shapeArgs.x + + fromNode.shapeArgs.width) + crisp, y1 = Math.floor(fromNode.shapeArgs.y + + fromNode.shapeArgs.height / 2) + crisp, x2 = Math.floor(toNode.shapeArgs.x) + crisp, y2 = Math.floor(toNode.shapeArgs.y + + toNode.shapeArgs.height / 2) + crisp, xMiddle, hangingIndent = this.options.hangingIndent, toOffset = toNode.options.offset, percentOffset = /%$/.test(toOffset) && parseInt(toOffset, 10), inverted = this.chart.inverted; + if (inverted) { + x1 -= fromNode.shapeArgs.width; + x2 += toNode.shapeArgs.width; + } + xMiddle = Math.floor(x2 + + (inverted ? 1 : -1) * + (this.colDistance - this.nodeWidth) / 2) + crisp; + // Put the link on the side of the node when an offset is given. HR + // node in the main demo. + if (percentOffset && + (percentOffset >= 50 || percentOffset <= -50)) { + xMiddle = x2 = Math.floor(x2 + (inverted ? -0.5 : 0.5) * + toNode.shapeArgs.width) + crisp; + y2 = toNode.shapeArgs.y; + if (percentOffset > 0) { + y2 += toNode.shapeArgs.height; + } + } + if (toNode.hangsFrom === fromNode) { + if (this.chart.inverted) { + y1 = Math.floor(fromNode.shapeArgs.y + + fromNode.shapeArgs.height - + hangingIndent / 2) + crisp; + y2 = (toNode.shapeArgs.y + + toNode.shapeArgs.height); + } + else { + y1 = Math.floor(fromNode.shapeArgs.y + + hangingIndent / 2) + crisp; + } + xMiddle = x2 = Math.floor(toNode.shapeArgs.x + + toNode.shapeArgs.width / 2) + crisp; + } + point.plotY = 1; + point.shapeType = 'path'; + point.shapeArgs = { + d: this.curvedPath([ + ['M', x1, y1], + ['L', xMiddle, y1], + ['L', xMiddle, y2], + ['L', x2, y2] + ], this.options.linkRadius) + }; + }, + alignDataLabel: function (point, dataLabel, options) { + // Align the data label to the point graphic + if (options.useHTML) { + var width = point.shapeArgs.width, height = point.shapeArgs.height, padjust = (this.options.borderWidth + + 2 * this.options.dataLabels.padding); + if (this.chart.inverted) { + width = height; + height = point.shapeArgs.width; + } + height -= padjust; + width -= padjust; + // Set the size of the surrounding div emulating `g` + var text = dataLabel.text; + if (text) { + css(text.element.parentNode, { + width: width + 'px', + height: height + 'px' + }); + // Set properties for the span emulating `text` + css(text.element, { + left: 0, + top: 0, + width: '100%', + height: '100%', + overflow: 'hidden' + }); + } + // The getBBox function is used in `alignDataLabel` to align + // inside the box + dataLabel.getBBox = function () { + return { + width: width, + height: height + }; + }; + // Overwrite dataLabel dimensions (#13100). + dataLabel.width = width; + dataLabel.height = height; + } + H.seriesTypes.column.prototype.alignDataLabel.apply(this, arguments); + } + }); + /** + * An `organization` series. If the [type](#series.organization.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.organization + * @exclude dataSorting + * @product highcharts + * @requires modules/organization + * @apioption series.organization + */ + /** + * @type {Highcharts.SeriesOrganizationDataLabelsOptionsObject|Array} + * @product highcharts + * @apioption series.organization.data.dataLabels + */ + /** + * A collection of options for the individual nodes. The nodes in an org chart + * are auto-generated instances of `Highcharts.Point`, but options can be + * applied here and linked by the `id`. + * + * @extends series.sankey.nodes + * @type {Array<*>} + * @product highcharts + * @apioption series.organization.nodes + */ + /** + * Individual data label for each node. The options are the same as + * the ones for [series.organization.dataLabels](#series.organization.dataLabels). + * + * @type {Highcharts.SeriesOrganizationDataLabelsOptionsObject|Array} + * + * @apioption series.organization.nodes.dataLabels + */ + /** + * The job description for the node card, will be inserted by the default + * `dataLabel.nodeFormatter`. + * + * @sample highcharts/demo/organization-chart + * Org chart with job descriptions + * + * @type {string} + * @product highcharts + * @apioption series.organization.nodes.description + */ + /** + * An image for the node card, will be inserted by the default + * `dataLabel.nodeFormatter`. + * + * @sample highcharts/demo/organization-chart + * Org chart with images + * + * @type {string} + * @product highcharts + * @apioption series.organization.nodes.image + */ + /** + * Layout for the node's children. If `hanging`, this node's children will hang + * below their parent, allowing a tighter packing of nodes in the diagram. + * + * @sample highcharts/demo/organization-chart + * Hanging layout + * + * @type {Highcharts.SeriesOrganizationNodesLayoutValue} + * @default normal + * @product highcharts + * @apioption series.organization.nodes.layout + */ + /** + * The job title for the node card, will be inserted by the default + * `dataLabel.nodeFormatter`. + * + * @sample highcharts/demo/organization-chart + * Org chart with job titles + * + * @type {string} + * @product highcharts + * @apioption series.organization.nodes.title + */ + /** + * An array of data points for the series. For the `organization` series + * type, points can be given in the following way: + * + * An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of data + * points exceeds the series' [turboThreshold](#series.area.turboThreshold), + * this option is not available. + * + * ```js + * data: [{ + * from: 'Category1', + * to: 'Category2', + * weight: 2 + * }, { + * from: 'Category1', + * to: 'Category3', + * weight: 5 + * }] + * ``` + * + * @type {Array<*>} + * @extends series.sankey.data + * @product highcharts + * @apioption series.organization.data + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'masters/modules/organization.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/overlapping-datalabels.js b/librerias/gantt/code/modules/overlapping-datalabels.js new file mode 100644 index 0000000..f2e022c --- /dev/null +++ b/librerias/gantt/code/modules/overlapping-datalabels.js @@ -0,0 +1,9 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2009-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/overlapping-datalabels",["highcharts"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){(function(a,c,d,e){a.hasOwnProperty(c)||(a[c]=e.apply(null,d))})(a?a._modules:{},"masters/modules/overlapping-datalabels.src.js",[],function(){})}); +//# sourceMappingURL=overlapping-datalabels.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/overlapping-datalabels.js.map b/librerias/gantt/code/modules/overlapping-datalabels.js.map new file mode 100644 index 0000000..0ca030d --- /dev/null +++ b/librerias/gantt/code/modules/overlapping-datalabels.js.map @@ -0,0 +1 @@ +{"version":3,"file":"overlapping-datalabels.js.map","lineCount":8,"mappings":"A;;;;;;;AAQC,SAAS,CAACA,CAAD,CAAU,CACM,QAAtB,GAAI,MAAOC,OAAX,EAAkCA,MAAAC,QAAlC,EACIF,CAAA,CAAQ,SAAR,CACA,CADqBA,CACrB,CAAAC,MAAAC,QAAA,CAAiBF,CAFrB,EAG6B,UAAtB,GAAI,MAAOG,OAAX,EAAoCA,MAAAC,IAApC,CACHD,MAAA,CAAO,2CAAP,CAAoD,CAAC,YAAD,CAApD,CAAoE,QAAS,CAACE,CAAD,CAAa,CACtFL,CAAA,CAAQK,CAAR,CACAL,EAAAK,WAAA,CAAqBA,CACrB,OAAOL,EAH+E,CAA1F,CADG,CAOHA,CAAA,CAA8B,WAAtB,GAAA,MAAOK,WAAP,CAAoCA,UAApC,CAAiDC,IAAAA,EAAzD,CAXY,CAAnB,CAAA,CAaC,QAAS,CAACD,CAAD,CAAa,CAEpBE,SAAwB,CAACC,CAAD,CAAMC,CAAN,CAAYC,CAAZ,CAAkBC,CAAlB,CAAsB,CACrCH,CAAAI,eAAA,CAAmBH,CAAnB,CAAL,GACID,CAAA,CAAIC,CAAJ,CADJ,CACgBE,CAAAE,MAAA,CAAS,IAAT,CAAeH,CAAf,CADhB,CAD0C,CAA9CH,CAKA,CANeF,CAAAS,CAAaT,CAAAS,SAAbA,CAAmC,EAMlD,CAA0B,+CAA1B,CAA2E,EAA3E,CAA+E,QAAS,EAAG,EAA3F,CAPoB,CAbvB;","sources":["overlapping-datalabels.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/overlapping-datalabels.src.js b/librerias/gantt/code/modules/overlapping-datalabels.src.js new file mode 100644 index 0000000..abc1a08 --- /dev/null +++ b/librerias/gantt/code/modules/overlapping-datalabels.src.js @@ -0,0 +1,33 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * (c) 2009-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/overlapping-datalabels', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'masters/modules/overlapping-datalabels.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/parallel-coordinates.js b/librerias/gantt/code/modules/parallel-coordinates.js new file mode 100644 index 0000000..b9b4db6 --- /dev/null +++ b/librerias/gantt/code/modules/parallel-coordinates.js @@ -0,0 +1,20 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Support for parallel coordinates in Highcharts + + (c) 2010-2019 Pawel Fus + + License: www.highcharts.com/license +*/ +(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/parallel-coordinates",["highcharts"],function(g){b(g);b.Highcharts=g;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function g(b,h,e,g){b.hasOwnProperty(h)||(b[h]=g.apply(null,e))}b=b?b._modules:{};g(b,"modules/parallel-coordinates.src.js",[b["parts/Axis.js"],b["parts/Globals.js"],b["parts/Utilities.js"]],function(b, +h,e){function g(a){var d=this.series&&this.series.chart,f=a.apply(this,Array.prototype.slice.call(arguments,1)),b;if(d&&d.hasParallelCoordinates&&!n(f.formattedValue)){var k=d.yAxis[this.x];var c=k.options;d=(b=p(c.tooltipValueFormat,c.labels.format))?v(b,q(this,{value:this.y}),d):k.dateTime?d.time.dateFormat(d.time.resolveDTLFormat(c.dateTimeLabelFormats[k.tickPositions.info.unitName]).main,this.y):c.categories?c.categories[this.y]:this.y;f.formattedValue=f.point.formattedValue=d}return f}var l= +e.addEvent,w=e.arrayMax,x=e.arrayMin,n=e.defined,y=e.erase,q=e.extend,v=e.format,m=e.merge,p=e.pick,r=e.splat,z=e.wrap;e=h.Chart;var A=e.prototype,t={lineWidth:0,tickLength:0,opposite:!0,type:"category"};h.setOptions({chart:{parallelCoordinates:!1,parallelAxes:{lineWidth:1,title:{text:"",reserveSpace:!1},labels:{x:0,y:4,align:"center",reserveSpace:!1},offset:0}}});var B=function(){function a(a){this.axis=a}a.prototype.setPosition=function(a,f){var d=this.axis,b=d.chart,c=((this.position||0)+.5)/(b.parallelInfo.counter+ +1);b.polar?f.angle=360*c:(f[a[0]]=100*c+"%",d[a[1]]=f[a[1]]=0,d[a[2]]=f[a[2]]=null,d[a[3]]=f[a[3]]=null)};return a}(),u=function(){function a(){}a.compose=function(a){a.keepProps.push("parallel");l(a,"init",function(){this.parallelCoordinates||(this.parallelCoordinates=new B(this))});l(a,"afterSetOptions",function(a){var d=this.chart,b=this.parallelCoordinates,c=["left","width","height","top"];d.hasParallelCoordinates&&(d.inverted&&(c=c.reverse()),this.isXAxis?this.options=m(this.options,t,a.userOptions): +(this.options=m(this.options,this.chart.options.chart.parallelAxes,a.userOptions),b.position=p(b.position,d.yAxis.length),b.setPosition(c,this.options)))});l(a,"getSeriesExtremes",function(a){var d=this.chart,b=this.parallelCoordinates;if(b&&d&&d.hasParallelCoordinates&&!this.isXAxis){var c=b.position,f=[];this.series.forEach(function(a){a.visible&&n(a.yData[c])&&f.push(a.yData[c])});this.dataMin=x(f);this.dataMax=w(f);a.preventDefault()}})};return a}();u.compose(b);l(e,"init",function(a){a=a.args[0]; +var d=r(a.yAxis||{}),b=d.length,e=[];if(this.hasParallelCoordinates=a.chart&&a.chart.parallelCoordinates){for(this.setParallelInfo(a);b<=this.parallelInfo.counter;b++)e.push({});a.legend||(a.legend={});"undefined"===typeof a.legend.enabled&&(a.legend.enabled=!1);m(!0,a,{boost:{seriesThreshold:Number.MAX_VALUE},plotOptions:{series:{boostThreshold:Number.MAX_VALUE}}});a.yAxis=d.concat(e);a.xAxis=m(t,r(a.xAxis||{})[0])}});l(e,"update",function(a){a=a.options;a.chart&&(n(a.chart.parallelCoordinates)&& +(this.hasParallelCoordinates=a.chart.parallelCoordinates),this.options.chart.parallelAxes=m(this.options.chart.parallelAxes,a.chart.parallelAxes));this.hasParallelCoordinates&&(a.series&&this.setParallelInfo(a),this.yAxis.forEach(function(a){a.update({},!1)}))});q(A,{setParallelInfo:function(a){var b=this;a=a.series;b.parallelInfo={counter:0};a.forEach(function(a){a.data&&(b.parallelInfo.counter=Math.max(b.parallelInfo.counter,a.data.length-1))})}});l(h.Series,"bindAxes",function(a){if(this.chart.hasParallelCoordinates){var b= +this;this.chart.axes.forEach(function(a){b.insert(a.series);a.isDirty=!0});b.xAxis=this.chart.xAxis[0];b.yAxis=this.chart.yAxis[0];a.preventDefault()}});l(h.Series,"afterTranslate",function(){var a=this.chart,b=this.points,e=b&&b.length,g=Number.MAX_VALUE,k;if(this.chart.hasParallelCoordinates){for(k=0;k} axisPosition + * ['left', 'width', 'height', 'top'] or ['top', 'height', 'width', 'left'] + * for an inverted chart. + * + * @param {Highcharts.AxisOptions} options + * Axis options. + */ + ParallelAxisAdditions.prototype.setPosition = function (axisPosition, options) { + var parallel = this; + var axis = parallel.axis; + var chart = axis.chart; + var fraction = ((parallel.position || 0) + 0.5) / + (chart.parallelInfo.counter + 1); + if (chart.polar) { + options.angle = 360 * fraction; + } + else { + options[axisPosition[0]] = 100 * fraction + '%'; + axis[axisPosition[1]] = + options[axisPosition[1]] = 0; + // In case of chart.update(inverted), remove old options: + axis[axisPosition[2]] = + options[axisPosition[2]] = null; + axis[axisPosition[3]] = + options[axisPosition[3]] = null; + } + }; + return ParallelAxisAdditions; + }()); + /** + * Axis with parallel support. + * @private + * @class + */ + var ParallelAxis = /** @class */ (function () { + function ParallelAxis() { + } + /** + * Adds support for parallel axes. + * @private + */ + ParallelAxis.compose = function (AxisClass) { + /* eslint-disable no-invalid-this */ + // On update, keep parallel additions. + AxisClass.keepProps.push('parallel'); + // Add parallel addition + addEvent(AxisClass, 'init', function () { + var axis = this; + if (!axis.parallelCoordinates) { + axis.parallelCoordinates = new ParallelAxisAdditions(axis); + } + }); + // Update default options with predefined for a parallel coords. + addEvent(AxisClass, 'afterSetOptions', function (e) { + var axis = this; + var chart = axis.chart; + var parallelCoordinates = axis.parallelCoordinates; + var axisPosition = ['left', 'width', 'height', 'top']; + if (chart.hasParallelCoordinates) { + if (chart.inverted) { + axisPosition = axisPosition.reverse(); + } + if (axis.isXAxis) { + axis.options = merge(axis.options, defaultXAxisOptions, e.userOptions); + } + else { + axis.options = merge(axis.options, axis.chart.options.chart.parallelAxes, e.userOptions); + parallelCoordinates.position = pick(parallelCoordinates.position, chart.yAxis.length); + parallelCoordinates.setPosition(axisPosition, axis.options); + } + } + }); + // Each axis should gather extremes from points on a particular position + // in series.data. Not like the default one, which gathers extremes from + // all series bind to this axis. Consider using series.points instead of + // series.yData. + addEvent(AxisClass, 'getSeriesExtremes', function (e) { + var axis = this; + var chart = axis.chart; + var parallelCoordinates = axis.parallelCoordinates; + if (!parallelCoordinates) { + return; + } + if (chart && chart.hasParallelCoordinates && !axis.isXAxis) { + var index = parallelCoordinates.position, currentPoints = []; + axis.series.forEach(function (series) { + if (series.visible && + defined(series.yData[index])) { + // We need to use push() beacause of null points + currentPoints.push(series.yData[index]); + } + }); + axis.dataMin = arrayMin(currentPoints); + axis.dataMax = arrayMax(currentPoints); + e.preventDefault(); + } + }); + /* eslint-enable no-invalid-this */ + }; + return ParallelAxis; + }()); + ParallelAxis.compose(Axis); + /* eslint-disable no-invalid-this */ + // Initialize parallelCoordinates + addEvent(Chart, 'init', function (e) { + var options = e.args[0], defaultyAxis = splat(options.yAxis || {}), yAxisLength = defaultyAxis.length, newYAxes = []; + /** + * Flag used in parallel coordinates plot to check if chart has ||-coords + * (parallel coords). + * + * @requires module:modules/parallel-coordinates + * + * @name Highcharts.Chart#hasParallelCoordinates + * @type {boolean} + */ + this.hasParallelCoordinates = options.chart && + options.chart.parallelCoordinates; + if (this.hasParallelCoordinates) { + this.setParallelInfo(options); + // Push empty yAxes in case user did not define them: + for (; yAxisLength <= this.parallelInfo.counter; yAxisLength++) { + newYAxes.push({}); + } + if (!options.legend) { + options.legend = {}; + } + if (typeof options.legend.enabled === 'undefined') { + options.legend.enabled = false; + } + merge(true, options, + // Disable boost + { + boost: { + seriesThreshold: Number.MAX_VALUE + }, + plotOptions: { + series: { + boostThreshold: Number.MAX_VALUE + } + } + }); + options.yAxis = defaultyAxis.concat(newYAxes); + options.xAxis = merge(defaultXAxisOptions, // docs + splat(options.xAxis || {})[0]); + } + }); + // Initialize parallelCoordinates + addEvent(Chart, 'update', function (e) { + var options = e.options; + if (options.chart) { + if (defined(options.chart.parallelCoordinates)) { + this.hasParallelCoordinates = options.chart.parallelCoordinates; + } + this.options.chart.parallelAxes = merge(this.options.chart.parallelAxes, options.chart.parallelAxes); + } + if (this.hasParallelCoordinates) { + // (#10081) + if (options.series) { + this.setParallelInfo(options); + } + this.yAxis.forEach(function (axis) { + axis.update({}, false); + }); + } + }); + /* eslint-disable valid-jsdoc */ + extend(ChartProto, /** @lends Highcharts.Chart.prototype */ { + /** + * Define how many parellel axes we have according to the longest dataset. + * This is quite heavy - loop over all series and check series.data.length + * Consider: + * + * - make this an option, so user needs to set this to get better + * performance + * + * - check only first series for number of points and assume the rest is the + * same + * + * @private + * @function Highcharts.Chart#setParallelInfo + * @param {Highcharts.Options} options + * User options + * @return {void} + * @requires modules/parallel-coordinates + */ + setParallelInfo: function (options) { + var chart = this, seriesOptions = options.series; + chart.parallelInfo = { + counter: 0 + }; + seriesOptions.forEach(function (series) { + if (series.data) { + chart.parallelInfo.counter = Math.max(chart.parallelInfo.counter, series.data.length - 1); + } + }); + } + }); + // Bind each series to each yAxis. yAxis needs a reference to all series to + // calculate extremes. + addEvent(H.Series, 'bindAxes', function (e) { + if (this.chart.hasParallelCoordinates) { + var series = this; + this.chart.axes.forEach(function (axis) { + series.insert(axis.series); + axis.isDirty = true; + }); + series.xAxis = this.chart.xAxis[0]; + series.yAxis = this.chart.yAxis[0]; + e.preventDefault(); + } + }); + // Translate each point using corresponding yAxis. + addEvent(H.Series, 'afterTranslate', function () { + var series = this, chart = this.chart, points = series.points, dataLength = points && points.length, closestPointRangePx = Number.MAX_VALUE, lastPlotX, point, i; + if (this.chart.hasParallelCoordinates) { + for (i = 0; i < dataLength; i++) { + point = points[i]; + if (defined(point.y)) { + if (chart.polar) { + point.plotX = chart.yAxis[i].angleRad || 0; + } + else if (chart.inverted) { + point.plotX = (chart.plotHeight - + chart.yAxis[i].top + + chart.plotTop); + } + else { + point.plotX = chart.yAxis[i].left - chart.plotLeft; + } + point.clientX = point.plotX; + point.plotY = chart.yAxis[i] + .translate(point.y, false, true, null, true); + if (typeof lastPlotX !== 'undefined') { + closestPointRangePx = Math.min(closestPointRangePx, Math.abs(point.plotX - lastPlotX)); + } + lastPlotX = point.plotX; + point.isInside = chart.isInsidePlot(point.plotX, point.plotY, chart.inverted); + } + else { + point.isNull = true; + } + } + this.closestPointRangePx = closestPointRangePx; + } + }, { order: 1 }); + // On destroy, we need to remove series from each axis.series + addEvent(H.Series, 'destroy', function () { + if (this.chart.hasParallelCoordinates) { + (this.chart.axes || []).forEach(function (axis) { + if (axis && axis.series) { + erase(axis.series, this); + axis.isDirty = axis.forceRedraw = true; + } + }, this); + } + }); + /** + * @private + */ + function addFormattedValue(proceed) { + var chart = this.series && this.series.chart, config = proceed.apply(this, Array.prototype.slice.call(arguments, 1)), formattedValue, yAxisOptions, labelFormat, yAxis; + if (chart && + chart.hasParallelCoordinates && + !defined(config.formattedValue)) { + yAxis = chart.yAxis[this.x]; + yAxisOptions = yAxis.options; + labelFormat = pick( + /** + * Parallel coordinates only. Format that will be used for point.y + * and available in [tooltip.pointFormat](#tooltip.pointFormat) as + * `{point.formattedValue}`. If not set, `{point.formattedValue}` + * will use other options, in this order: + * + * 1. [yAxis.labels.format](#yAxis.labels.format) will be used if + * set + * + * 2. If yAxis is a category, then category name will be displayed + * + * 3. If yAxis is a datetime, then value will use the same format as + * yAxis labels + * + * 4. If yAxis is linear/logarithmic type, then simple value will be + * used + * + * @sample {highcharts} + * /highcharts/parallel-coordinates/tooltipvalueformat/ + * Different tooltipValueFormats's + * + * @type {string} + * @default undefined + * @since 6.0.0 + * @product highcharts + * @requires modules/parallel-coordinates + * @apioption yAxis.tooltipValueFormat + */ + yAxisOptions.tooltipValueFormat, yAxisOptions.labels.format); + if (labelFormat) { + formattedValue = format(labelFormat, extend(this, { value: this.y }), chart); + } + else if (yAxis.dateTime) { + formattedValue = chart.time.dateFormat(chart.time.resolveDTLFormat(yAxisOptions.dateTimeLabelFormats[yAxis.tickPositions.info.unitName]).main, this.y); + } + else if (yAxisOptions.categories) { + formattedValue = yAxisOptions.categories[this.y]; + } + else { + formattedValue = this.y; + } + config.formattedValue = config.point.formattedValue = formattedValue; + } + return config; + } + ['line', 'spline'].forEach(function (seriesName) { + wrap(H.seriesTypes[seriesName].prototype.pointClass.prototype, 'getLabelConfig', addFormattedValue); + }); + + return ParallelAxis; + }); + _registerModule(_modules, 'masters/modules/parallel-coordinates.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/pareto.js b/librerias/gantt/code/modules/pareto.js new file mode 100644 index 0000000..5d6f158 --- /dev/null +++ b/librerias/gantt/code/modules/pareto.js @@ -0,0 +1,14 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Pareto series type for Highcharts + + (c) 2010-2019 Sebastian Bochan + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/pareto",["highcharts"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,e,c,b){a.hasOwnProperty(e)||(a[e]=b.apply(null,c))}a=a?a._modules:{};b(a,"mixins/derived-series.js",[a["parts/Globals.js"],a["parts/Utilities.js"]],function(a,b){var c=b.addEvent,d=b.defined,f=a.Series; +return{hasDerivedData:!0,init:function(){f.prototype.init.apply(this,arguments);this.initialised=!1;this.baseSeries=null;this.eventRemovers=[];this.addEvents()},setDerivedData:a.noop,setBaseSeries:function(){var a=this.chart,b=this.options.baseSeries;this.baseSeries=d(b)&&(a.series[b]||a.get(b))||null},addEvents:function(){var a=this;var b=c(this.chart,"afterLinkSeries",function(){a.setBaseSeries();a.baseSeries&&!a.initialised&&(a.setDerivedData(),a.addBaseSeriesEvents(),a.initialised=!0)});this.eventRemovers.push(b)}, +addBaseSeriesEvents:function(){var a=this;var b=c(a.baseSeries,"updatedData",function(){a.setDerivedData()});var d=c(a.baseSeries,"destroy",function(){a.baseSeries=null;a.initialised=!1});a.eventRemovers.push(b,d)},destroy:function(){this.eventRemovers.forEach(function(a){a()});f.prototype.destroy.apply(this,arguments)}}});b(a,"modules/pareto.src.js",[a["parts/Utilities.js"],a["mixins/derived-series.js"]],function(a,b){var c=a.correctFloat,d=a.merge;a=a.seriesType;a("pareto","line",{zIndex:3},d(b, +{setDerivedData:function(){var a=this.baseSeries.xData,b=this.baseSeries.yData,c=this.sumPointsPercents(b,a,null,!0);this.setData(this.sumPointsPercents(b,a,c,!1),!1)},sumPointsPercents:function(a,b,d,e){var f=0,h=0,k=[],g;a.forEach(function(a,l){null!==a&&(e?f+=a:(g=a/d*100,k.push([b[l],c(h+g)]),h+=g))});return e?f:k}}));""});b(a,"masters/modules/pareto.src.js",[],function(){})}); +//# sourceMappingURL=pareto.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/pareto.js.map b/librerias/gantt/code/modules/pareto.js.map new file mode 100644 index 0000000..0e5f9b4 --- /dev/null +++ b/librerias/gantt/code/modules/pareto.js.map @@ -0,0 +1 @@ +{"version":3,"file":"pareto.js.map","lineCount":13,"mappings":"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","sources":["pareto.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","U","addEvent","defined","Series","derivedSeriesMixin","hasDerivedData","init","prototype","arguments","initialised","baseSeries","eventRemovers","addEvents","setDerivedData","noop","setBaseSeries","chart","baseSeriesOptions","options","series","get","derivedSeries","chartSeriesLinked","addBaseSeriesEvents","push","updatedDataRemover","destroyRemover","destroy","forEach","remover","correctFloat","merge","seriesType","zIndex","xValues","xData","yValues","yData","sum","sumPointsPercents","setData","isSum","sumY","sumPercent","percentPoints","percentPoint","point","i"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/pareto.src.js b/librerias/gantt/code/modules/pareto.src.js new file mode 100644 index 0000000..71510ea --- /dev/null +++ b/librerias/gantt/code/modules/pareto.src.js @@ -0,0 +1,291 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * Pareto series type for Highcharts + * + * (c) 2010-2019 Sebastian Bochan + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/pareto', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'mixins/derived-series.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, defined = U.defined; + var Series = H.Series, noop = H.noop; + /* ************************************************************************** * + * + * DERIVED SERIES MIXIN + * + * ************************************************************************** */ + /** + * Provides methods for auto setting/updating series data based on the based + * series data. + * + * @private + * @mixin derivedSeriesMixin + */ + var derivedSeriesMixin = { + hasDerivedData: true, + /* eslint-disable valid-jsdoc */ + /** + * Initialise series + * + * @private + * @function derivedSeriesMixin.init + * @return {void} + */ + init: function () { + Series.prototype.init.apply(this, arguments); + this.initialised = false; + this.baseSeries = null; + this.eventRemovers = []; + this.addEvents(); + }, + /** + * Method to be implemented - inside the method the series has already + * access to the base series via m `this.baseSeries` and the bases data is + * initialised. It should return data in the format accepted by + * `Series.setData()` method + * + * @private + * @function derivedSeriesMixin.setDerivedData + * @return {Array} + * An array of data + */ + setDerivedData: noop, + /** + * Sets base series for the series + * + * @private + * @function derivedSeriesMixin.setBaseSeries + * @return {void} + */ + setBaseSeries: function () { + var chart = this.chart, baseSeriesOptions = this.options.baseSeries, baseSeries = (defined(baseSeriesOptions) && + (chart.series[baseSeriesOptions] || + chart.get(baseSeriesOptions))); + this.baseSeries = baseSeries || null; + }, + /** + * Adds events for the series + * + * @private + * @function derivedSeriesMixin.addEvents + * @return {void} + */ + addEvents: function () { + var derivedSeries = this, chartSeriesLinked; + chartSeriesLinked = addEvent(this.chart, 'afterLinkSeries', function () { + derivedSeries.setBaseSeries(); + if (derivedSeries.baseSeries && !derivedSeries.initialised) { + derivedSeries.setDerivedData(); + derivedSeries.addBaseSeriesEvents(); + derivedSeries.initialised = true; + } + }); + this.eventRemovers.push(chartSeriesLinked); + }, + /** + * Adds events to the base series - it required for recalculating the data + * in the series if the base series is updated / removed / etc. + * + * @private + * @function derivedSeriesMixin.addBaseSeriesEvents + * @return {void} + */ + addBaseSeriesEvents: function () { + var derivedSeries = this, updatedDataRemover, destroyRemover; + updatedDataRemover = addEvent(derivedSeries.baseSeries, 'updatedData', function () { + derivedSeries.setDerivedData(); + }); + destroyRemover = addEvent(derivedSeries.baseSeries, 'destroy', function () { + derivedSeries.baseSeries = null; + derivedSeries.initialised = false; + }); + derivedSeries.eventRemovers.push(updatedDataRemover, destroyRemover); + }, + /** + * Destroys the series + * + * @private + * @function derivedSeriesMixin.destroy + */ + destroy: function () { + this.eventRemovers.forEach(function (remover) { + remover(); + }); + Series.prototype.destroy.apply(this, arguments); + } + /* eslint-disable valid-jsdoc */ + }; + + return derivedSeriesMixin; + }); + _registerModule(_modules, 'modules/pareto.src.js', [_modules['parts/Utilities.js'], _modules['mixins/derived-series.js']], function (U, derivedSeriesMixin) { + /* * + * + * (c) 2010-2017 Sebastian Bochan + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var correctFloat = U.correctFloat, merge = U.merge, seriesType = U.seriesType; + /** + * The pareto series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.pareto + * + * @augments Highcharts.Series + */ + seriesType('pareto', 'line' + /** + * A pareto diagram is a type of chart that contains both bars and a line + * graph, where individual values are represented in descending order by + * bars, and the cumulative total is represented by the line. + * + * @sample {highcharts} highcharts/demo/pareto/ + * Pareto diagram + * + * @extends plotOptions.line + * @since 6.0.0 + * @product highcharts + * @excluding allAreas, boostThreshold, borderColor, borderRadius, + * borderWidth, crisp, colorAxis, depth, data, dragDrop, + * edgeColor, edgeWidth, findNearestPointBy, gapSize, gapUnit, + * grouping, groupPadding, groupZPadding, maxPointWidth, keys, + * negativeColor, pointInterval, pointIntervalUnit, + * pointPadding, pointPlacement, pointRange, pointStart, + * pointWidth, shadow, step, softThreshold, stacking, + * threshold, zoneAxis, zones + * @requires modules/pareto + * @optionparent plotOptions.pareto + */ + , { + /** + * Higher zIndex than column series to draw line above shapes. + */ + zIndex: 3 + }, + /* eslint-disable no-invalid-this, valid-jsdoc */ + merge(derivedSeriesMixin, { + /** + * Calculate sum and return percent points. + * + * @private + * @function Highcharts.Series#setDerivedData + * @requires modules/pareto + */ + setDerivedData: function () { + var xValues = this.baseSeries.xData, yValues = this.baseSeries.yData, sum = this.sumPointsPercents(yValues, xValues, null, true); + this.setData(this.sumPointsPercents(yValues, xValues, sum, false), false); + }, + /** + * Calculate y sum and each percent point. + * + * @private + * @function Highcharts.Series#sumPointsPercents + * + * @param {Array} yValues + * Y values + * + * @param {Array} xValues + * X values + * + * @param {number} sum + * Sum of all y values + * + * @param {boolean} [isSum] + * Declares if calculate sum of all points + * + * @return {number|Array} + * Returns sum of points or array of points [x,sum] + * + * @requires modules/pareto + */ + sumPointsPercents: function (yValues, xValues, sum, isSum) { + var sumY = 0, sumPercent = 0, percentPoints = [], percentPoint; + yValues.forEach(function (point, i) { + if (point !== null) { + if (isSum) { + sumY += point; + } + else { + percentPoint = (point / sum) * 100; + percentPoints.push([ + xValues[i], + correctFloat(sumPercent + percentPoint) + ]); + sumPercent += percentPoint; + } + } + }); + return (isSum ? sumY : percentPoints); + } + }) + /* eslint-enable no-invalid-this, valid-jsdoc */ + ); + /** + * A `pareto` series. If the [type](#series.pareto.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.pareto + * @since 6.0.0 + * @product highcharts + * @excluding data, dataParser, dataURL + * @requires modules/pareto + * @apioption series.pareto + */ + /** + * An integer identifying the index to use for the base series, or a string + * representing the id of the series. + * + * @type {number|string} + * @default undefined + * @apioption series.pareto.baseSeries + */ + /** + * An array of data points for the series. For the `pareto` series type, + * points are calculated dynamically. + * + * @type {Array|*>} + * @extends series.column.data + * @since 6.0.0 + * @product highcharts + * @apioption series.pareto.data + */ + ''; // adds the doclets above to the transpiled file + + }); + _registerModule(_modules, 'masters/modules/pareto.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/pathfinder.js b/librerias/gantt/code/modules/pathfinder.js new file mode 100644 index 0000000..33968a5 --- /dev/null +++ b/librerias/gantt/code/modules/pathfinder.js @@ -0,0 +1,36 @@ +/* + Highcharts Gantt JS v8.1.0 (2020-05-05) + + Pathfinder + + (c) 2016-2019 ystein Moseng + + License: www.highcharts.com/license +*/ +(function(d){"object"===typeof module&&module.exports?(d["default"]=d,module.exports=d):"function"===typeof define&&define.amd?define("highcharts/modules/pathfinder",["highcharts"],function(l){d(l);d.Highcharts=l;return d}):d("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(d){function l(C,p,h,d){C.hasOwnProperty(p)||(C[p]=d.apply(null,h))}d=d?d._modules:{};l(d,"parts-gantt/PathfinderAlgorithms.js",[d["parts/Utilities.js"]],function(d){function p(e,c,f){f=f||0;var h=e.length-1;c-=1e-7; +for(var d,p;f<=h;)if(d=h+f>>1,p=c-e[d].xMin,0p)h=d-1;else return d;return 0=c.x)h=e[f],h=c.x<=h.xMax&&c.x>=h.xMin&&c.y<=h.yMax&&c.y>=h.yMin;if(h)return f}return-1}function C(e){var c=[];if(e.length){c.push(["M",e[0].start.x,e[0].start.y]);for(var f=0;fw(g[u]-a[u+"Max"]);return d(g,u,a,u+(b?"Max":"Min"),b?1:-1)}var n=[],r=F(f.startDirectionX,w(c.x-e.x)>w(c.y-e.y))?"x":"y",t=f.chartObstacles,x=h(t,e);f=h(t,c);if(-1=e[r]===f[r]>=a[r]&&(r="y"===r?"x":"y",c=e[r]u?t(p(m,e.x),m.length-1):0;m[k]&&(0u&&m[k].xMax>=z.x);){if(m[k].xMin<=e.x&&m[k].xMax>=z.x&&m[k].yMin<=v.y&&m[k].yMax>=c.y)return g?{y:a.y,x:a.x=k[c+"Max"];k=a[c+"Min"]<=k[c+"Min"];var H=a[c+"Max"]>=e[c+"Max"];e=a[c+ +"Min"]<=e[c+"Min"];var h=w(a[c+"Min"]-b[c]),v=w(a[c+"Max"]-b[c]);g=10>w(h-v)?b[c]w(c.y-e.y)),A=I?"x":"y",G=[],a=!1,b=f.obstacleMetrics,g=t(e.x,c.x)-b.maxWidth-10,u=y(e.x,c.x)+b.maxWidth+10,z=t(e.y,c.y)-b.maxHeight-10,H=y(e.y,c.y)+ +b.maxHeight+10,m=f.chartObstacles;var E=p(m,g);b=p(m,u);m=m.slice(E,b+1);if(-1<(b=h(m,c))){var q=r(m[b],c,e);G.push({end:c,start:q});c=q}for(;-1<(b=h(m,c));)E=0>c[A]-e[A],q={x:c.x,y:c.y},q[A]=m[b][E?A+"Max":A+"Min"]+(E?1:-1),G.push({end:c,start:q}),c=q;e=x(e,c,I);e=e.concat(G.reverse());return{path:C(e),obstacles:e}},{requiresObstacles:!0})}});l(d,"parts-gantt/ArrowSymbols.js",[d["parts/Globals.js"]],function(d){d.SVGRenderer.prototype.symbols.arrow=function(d,h,l,n){return[["M",d,h+n/2],["L",d+l, +h],["L",d,h+n/2],["L",d+l,h+n]]};d.SVGRenderer.prototype.symbols["arrow-half"]=function(p,h,l,n){return d.SVGRenderer.prototype.symbols.arrow(p,h,l/2,n)};d.SVGRenderer.prototype.symbols["triangle-left"]=function(d,h,l,n){return[["M",d+l,h],["L",d,h+n/2],["L",d+l,h+n],["Z"]]};d.SVGRenderer.prototype.symbols["arrow-filled"]=d.SVGRenderer.prototype.symbols["triangle-left"];d.SVGRenderer.prototype.symbols["triangle-left-half"]=function(p,h,l,n){return d.SVGRenderer.prototype.symbols["triangle-left"](p, +h,l/2,n)};d.SVGRenderer.prototype.symbols["arrow-filled-half"]=d.SVGRenderer.prototype.symbols["triangle-left-half"]});l(d,"parts-gantt/Pathfinder.js",[d["parts/Globals.js"],d["parts/Point.js"],d["parts/Utilities.js"],d["parts-gantt/PathfinderAlgorithms.js"]],function(d,l,h,x){function n(a){var b=a.shapeArgs;return b?{xMin:b.x,xMax:b.x+b.width,yMin:b.y,yMax:b.y+b.height}:(b=a.graphic&&a.graphic.getBBox())?{xMin:a.plotX-b.width/2,xMax:a.plotX+b.width/2,yMin:a.plotY-b.height/2,yMax:a.plotY+b.height/ +2}:null}function p(a){for(var b=a.length,g=0,c,e,d=[],m=function(b,a,g){g=J(g,10);var c=b.yMax+g>a.yMin-g&&b.yMin-ga.xMin-g&&b.xMin-ga.xMax?b.xMin-a.xMax:a.xMin-b.xMax:Infinity,u=e?b.yMin>a.yMax?b.yMin-a.yMax:a.yMin-b.yMax:Infinity;return e&&c?g?m(b,a,Math.floor(g/2)):Infinity:G(d,u)};ge&&d.push(e);d.push(80);return A(Math.floor(d.sort(function(b,a){return b-a})[Math.floor(d.length/10)]/2-1),1)}function F(a,b,g){this.init(a, +b,g)}function t(a){this.init(a)}function y(a){if(a.options.pathfinder||a.series.reduce(function(b,a){a.options&&D(!0,a.options.connectors=a.options.connectors||{},a.options.pathfinder);return b||a.options&&a.options.pathfinder},!1))D(!0,a.options.connectors=a.options.connectors||{},a.options.pathfinder),c('WARNING: Pathfinder options have been renamed. Use "chart.connectors" or "series.connectors" instead.')}"";var w=h.addEvent,e=h.defined,c=h.error,f=h.extend,D=h.merge,C=h.objectEach,J=h.pick,r= +h.splat,I=d.deg2rad,A=Math.max,G=Math.min;f(d.defaultOptions,{connectors:{type:"straight",lineWidth:1,marker:{enabled:!1,align:"center",verticalAlign:"middle",inside:!1,lineWidth:1},startMarker:{symbol:"diamond"},endMarker:{symbol:"arrow-filled"}}});F.prototype={init:function(a,b,g){this.fromPoint=a;this.toPoint=b;this.options=g;this.chart=a.series.chart;this.pathfinder=this.chart.pathfinder},renderPath:function(a,b,g){var c=this.chart,e=c.styledMode,d=c.pathfinder,m=!c.options.chart.forExport&&!1!== +g,f=this.graphics&&this.graphics.path;d.group||(d.group=c.renderer.g().addClass("highcharts-pathfinder-group").attr({zIndex:-1}).add(c.seriesGroup));d.group.translate(c.plotLeft,c.plotTop);f&&f.renderer||(f=c.renderer.path().add(d.group),e||f.attr({opacity:0}));f.attr(b);a={d:a};e||(a.opacity=1);f[m?"animate":"attr"](a,g);this.graphics=this.graphics||{};this.graphics.path=f},addMarker:function(a,b,g){var c=this.fromPoint.series.chart,e=c.pathfinder;c=c.renderer;var d="start"===a?this.fromPoint:this.toPoint, +f=d.getPathfinderAnchorPoint(b);if(b.enabled&&((g="start"===a?g[1]:g[g.length-2])&&"M"===g[0]||"L"===g[0])){g={x:g[1],y:g[2]};g=d.getRadiansToVector(g,f);f=d.getMarkerVector(g,b.radius,f);g=-g/I;if(b.width&&b.height){var h=b.width;var q=b.height}else h=q=2*b.radius;this.graphics=this.graphics||{};f={x:f.x-h/2,y:f.y-q/2,width:h,height:q,rotation:g,rotationOriginX:f.x,rotationOriginY:f.y};this.graphics[a]?this.graphics[a].animate(f):(this.graphics[a]=c.symbol(b.symbol).addClass("highcharts-point-connecting-path-"+ +a+"-marker").attr(f).add(e.group),c.styledMode||this.graphics[a].attr({fill:b.color||this.fromPoint.color,stroke:b.lineColor,"stroke-width":b.lineWidth,opacity:0}).animate({opacity:1},d.series.options.animation))}},getPath:function(a){var b=this.pathfinder,g=this.chart,e=b.algorithms[a.type],d=b.chartObstacles;if("function"!==typeof e)c('"'+a.type+'" is not a Pathfinder algorithm.');else return e.requiresObstacles&&!d&&(d=b.chartObstacles=b.getChartObstacles(a),g.options.connectors.algorithmMargin= +a.algorithmMargin,b.chartObstacleMetrics=b.getObstacleMetrics(d)),e(this.fromPoint.getPathfinderAnchorPoint(a.startMarker),this.toPoint.getPathfinderAnchorPoint(a.endMarker),D({chartObstacles:d,lineObstacles:b.lineObstacles||[],obstacleMetrics:b.chartObstacleMetrics,hardBounds:{xMin:0,xMax:g.plotWidth,yMin:0,yMax:g.plotHeight},obstacleOptions:{margin:a.algorithmMargin},startDirectionX:b.getAlgorithmStartDirection(a.startMarker)},a))},render:function(){var a=this.fromPoint,b=a.series,g=b.chart,c=g.pathfinder, +d=D(g.options.connectors,b.options.connectors,a.options.connectors,this.options),f={};g.styledMode||(f.stroke=d.lineColor||a.color,f["stroke-width"]=d.lineWidth,d.dashStyle&&(f.dashstyle=d.dashStyle));f["class"]="highcharts-point-connecting-path highcharts-color-"+a.colorIndex;d=D(f,d);e(d.marker.radius)||(d.marker.radius=G(A(Math.ceil((d.algorithmMargin||8)/2)-1,1),5));a=this.getPath(d);g=a.path;a.obstacles&&(c.lineObstacles=c.lineObstacles||[],c.lineObstacles=c.lineObstacles.concat(a.obstacles)); +this.renderPath(g,f,b.options.animation);this.addMarker("start",D(d.marker,d.startMarker),g);this.addMarker("end",D(d.marker,d.endMarker),g)},destroy:function(){this.graphics&&(C(this.graphics,function(a){a.destroy()}),delete this.graphics)}};t.prototype={algorithms:x,init:function(a){this.chart=a;this.connections=[];w(a,"redraw",function(){this.pathfinder.update()})},update:function(a){var b=this.chart,c=this,d=c.connections;c.connections=[];b.series.forEach(function(a){a.visible&&!a.options.isInternal&& +a.points.forEach(function(a){var d,e=a.options&&a.options.connect&&r(a.options.connect);a.visible&&!1!==a.isInside&&e&&e.forEach(function(e){d=b.get("string"===typeof e?e:e.to);d instanceof l&&d.series.visible&&d.visible&&!1!==d.isInside&&c.connections.push(new F(a,d,"string"===typeof e?{}:e))})})});for(var e=0,f,h,n=d.length,q=c.connections.length;eMath.PI;)a-=d;d=Math.tan(a);a>-h&&a<=h?(y=-1,l=!0):a>h&&a<=Math.PI- +h?y=-1:a>Math.PI-h||a<=-(Math.PI-h)?(x=-1,l=!0):x=-1;l?(r+=x*f,t+=y*f*d):(r+=g/(2*d)*x,t+=y*k);c.x!==p&&(r=c.x);c.y!==e&&(t=c.y);w.x=r+b*Math.cos(a);w.y=t-b*Math.sin(a);return w}});d.Chart.prototype.callbacks.push(function(a){!1!==a.options.connectors.enabled&&(y(a),this.pathfinder=new t(this),this.pathfinder.update(!0))})});l(d,"masters/modules/pathfinder.src.js",[],function(){})}); +//# sourceMappingURL=pathfinder.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/pathfinder.js.map b/librerias/gantt/code/modules/pathfinder.js.map new file mode 100644 index 0000000..8a2dfa0 --- /dev/null +++ b/librerias/gantt/code/modules/pathfinder.js.map @@ -0,0 +1 @@ +{"version":3,"file":"pathfinder.js.map","lineCount":35,"mappings":"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","sources":["pathfinder.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","U","findLastObstacleBefore","obstacles","xMin","startIx","left","right","length","min","cursor","cmp","findObstacleFromPoint","point","i","x","obstacle","xMax","y","yMax","yMin","pathFromSegments","segments","push","start","end","limitObstacleToBounds","bounds","max","extend","pick","Math","abs","algorithms","straight","simpleConnect","options","copyFromPoint","from","fromKey","to","toKey","offset","getMeOut","direction","useMax","dir","startDirectionX","chartObstacles","startObstacleIx","endObstacleIx","endObstacle","waypoint","endSegment","endPoint","startObstacle","prevWaypoint","waypoint2","requiresObstacles","fastAvoid","pivotPoint","fromPoint","toPoint","directionIsX","searchDirection","firstPoint","lastPoint","lowestPoint","highestPoint","getDodgeDirection","dirIsX","softBounds","soft","hardBounds","hard","toPointMax","toPointMin","maxOutOfSoftBounds","minOutOfSoftBounds","maxOutOfHardBounds","minOutOfHardBounds","minDistance","maxDistance","minPivot","maxPivot","clearPathTo","obstacleMargin","obstacleOptions","margin","softMinX","softMaxX","softMinY","softMaxY","envelopingObstacle","waypointUseMax","envelopWaypoint","secondEnvelopingObstacle","forceObstacleBreak","pivot","concat","extractFromObstacle","goalPoint","endSegments","metrics","obstacleMetrics","maxWidth","maxHeight","slice","extractedEndPoint","reverse","H","SVGRenderer","prototype","symbols","arrow","H.SVGRenderer.prototype.symbols.arrow","w","h","Point","pathfinderAlgorithms","getPointBB","shapeArgs","width","height","bb","graphic","getBBox","plotX","plotY","calculateObstacleMargin","len","j","obstacleDistance","distances","distance","a","b","bbMargin","yOverlap","xOverlap","xDistance","Infinity","yDistance","floor","sort","Connection","init","Pathfinder","chart","warnLegacy","pathfinder","series","reduce","acc","merge","connectors","error","addEvent","defined","objectEach","splat","deg2rad","defaultOptions","type","lineWidth","marker","enabled","align","verticalAlign","inside","startMarker","symbol","endMarker","renderPath","attribs","animation","styledMode","animate","forExport","pathGraphic","connection","graphics","group","renderer","g","addClass","attr","zIndex","add","seriesGroup","translate","plotLeft","plotTop","opacity","anim","d","addMarker","anchor","getPathfinderAnchorPoint","segment","pathVector","radians","getRadiansToVector","markerVector","getMarkerVector","radius","rotation","box","rotationOriginX","rotationOriginY","fill","color","stroke","lineColor","getPath","algorithm","getChartObstacles","algorithmMargin","chartObstacleMetrics","getObstacleMetrics","lineObstacles","plotWidth","plotHeight","getAlgorithmStartDirection","render","dashStyle","dashstyle","colorIndex","ceil","pathResult","destroy","val","connections","update","deferRender","oldConnections","forEach","visible","isInternal","points","connects","connect","isInside","get","k","found","lenOld","lenNew","renderConnections","pathfinderRemoveRenderEvent","calculatedMargin","sLen","pLen","markerOptions","yCenter","undef","v1","v2","atan2","markerRadius","twoPI","PI","rectWidth","rectHeight","rAtan","leftOrRightRegion","rectHalfWidth","rectHalfHeight","rectHorizontalCenter","rectVerticalCenter","markerPoint","xFactor","yFactor","theta","tanTheta","tan","cos","sin","Chart","callbacks"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/pathfinder.src.js b/librerias/gantt/code/modules/pathfinder.src.js new file mode 100644 index 0000000..77d9dd5 --- /dev/null +++ b/librerias/gantt/code/modules/pathfinder.src.js @@ -0,0 +1,1964 @@ +/** + * @license Highcharts Gantt JS v8.1.0 (2020-05-05) + * + * Pathfinder + * + * (c) 2016-2019 Øystein Moseng + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/pathfinder', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'parts-gantt/PathfinderAlgorithms.js', [_modules['parts/Utilities.js']], function (U) { + /* * + * + * (c) 2016 Highsoft AS + * Author: Øystein Moseng + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend, pick = U.pick; + var min = Math.min, max = Math.max, abs = Math.abs; + /** + * Get index of last obstacle before xMin. Employs a type of binary search, and + * thus requires that obstacles are sorted by xMin value. + * + * @private + * @function findLastObstacleBefore + * + * @param {Array} obstacles + * Array of obstacles to search in. + * + * @param {number} xMin + * The xMin threshold. + * + * @param {number} [startIx] + * Starting index to search from. Must be within array range. + * + * @return {number} + * The index of the last obstacle element before xMin. + */ + function findLastObstacleBefore(obstacles, xMin, startIx) { + var left = startIx || 0, // left limit + right = obstacles.length - 1, // right limit + min = xMin - 0.0000001, // Make sure we include all obstacles at xMin + cursor, cmp; + while (left <= right) { + cursor = (right + left) >> 1; + cmp = min - obstacles[cursor].xMin; + if (cmp > 0) { + left = cursor + 1; + } + else if (cmp < 0) { + right = cursor - 1; + } + else { + return cursor; + } + } + return left > 0 ? left - 1 : 0; + } + /** + * Test if a point lays within an obstacle. + * + * @private + * @function pointWithinObstacle + * + * @param {object} obstacle + * Obstacle to test. + * + * @param {Highcharts.Point} point + * Point with x/y props. + * + * @return {boolean} + * Whether point is within the obstacle or not. + */ + function pointWithinObstacle(obstacle, point) { + return (point.x <= obstacle.xMax && + point.x >= obstacle.xMin && + point.y <= obstacle.yMax && + point.y >= obstacle.yMin); + } + /** + * Find the index of an obstacle that wraps around a point. + * Returns -1 if not found. + * + * @private + * @function findObstacleFromPoint + * + * @param {Array} obstacles + * Obstacles to test. + * + * @param {Highcharts.Point} point + * Point with x/y props. + * + * @return {number} + * Ix of the obstacle in the array, or -1 if not found. + */ + function findObstacleFromPoint(obstacles, point) { + var i = findLastObstacleBefore(obstacles, point.x + 1) + 1; + while (i--) { + if (obstacles[i].xMax >= point.x && + // optimization using lazy evaluation + pointWithinObstacle(obstacles[i], point)) { + return i; + } + } + return -1; + } + /** + * Get SVG path array from array of line segments. + * + * @private + * @function pathFromSegments + * + * @param {Array} segments + * The segments to build the path from. + * + * @return {Highcharts.SVGPathArray} + * SVG path array as accepted by the SVG Renderer. + */ + function pathFromSegments(segments) { + var path = []; + if (segments.length) { + path.push(['M', segments[0].start.x, segments[0].start.y]); + for (var i = 0; i < segments.length; ++i) { + path.push(['L', segments[i].end.x, segments[i].end.y]); + } + } + return path; + } + /** + * Limits obstacle max/mins in all directions to bounds. Modifies input + * obstacle. + * + * @private + * @function limitObstacleToBounds + * + * @param {object} obstacle + * Obstacle to limit. + * + * @param {object} bounds + * Bounds to use as limit. + * + * @return {void} + */ + function limitObstacleToBounds(obstacle, bounds) { + obstacle.yMin = max(obstacle.yMin, bounds.yMin); + obstacle.yMax = min(obstacle.yMax, bounds.yMax); + obstacle.xMin = max(obstacle.xMin, bounds.xMin); + obstacle.xMax = min(obstacle.xMax, bounds.xMax); + } + // Define the available pathfinding algorithms. + // Algorithms take up to 3 arguments: starting point, ending point, and an + // options object. + var algorithms = { + /** + * Get an SVG path from a starting coordinate to an ending coordinate. + * Draws a straight line. + * + * @function Highcharts.Pathfinder.algorithms.straight + * + * @param {Highcharts.PositionObject} start + * Starting coordinate, object with x/y props. + * + * @param {Highcharts.PositionObject} end + * Ending coordinate, object with x/y props. + * + * @return {object} + * An object with the SVG path in Array form as accepted by the SVG + * renderer, as well as an array of new obstacles making up this + * path. + */ + straight: function (start, end) { + return { + path: [ + ['M', start.x, start.y], + ['L', end.x, end.y] + ], + obstacles: [{ start: start, end: end }] + }; + }, + /** + * Find a path from a starting coordinate to an ending coordinate, using + * right angles only, and taking only starting/ending obstacle into + * consideration. + * + * @function Highcharts.Pathfinder.algorithms.simpleConnect + * + * @param {Highcharts.PositionObject} start + * Starting coordinate, object with x/y props. + * + * @param {Highcharts.PositionObject} end + * Ending coordinate, object with x/y props. + * + * @param {object} options + * Options for the algorithm: + * - chartObstacles: Array of chart obstacles to avoid + * - startDirectionX: Optional. True if starting in the X direction. + * If not provided, the algorithm starts in the direction that is + * the furthest between start/end. + * + * @return {object} + * An object with the SVG path in Array form as accepted by the SVG + * renderer, as well as an array of new obstacles making up this + * path. + */ + simpleConnect: extend(function (start, end, options) { + var segments = [], endSegment, dir = pick(options.startDirectionX, abs(end.x - start.x) > abs(end.y - start.y)) ? 'x' : 'y', chartObstacles = options.chartObstacles, startObstacleIx = findObstacleFromPoint(chartObstacles, start), endObstacleIx = findObstacleFromPoint(chartObstacles, end), startObstacle, endObstacle, prevWaypoint, waypoint, waypoint2, useMax, endPoint; + // eslint-disable-next-line valid-jsdoc + /** + * Return a clone of a point with a property set from a target object, + * optionally with an offset + * @private + */ + function copyFromPoint(from, fromKey, to, toKey, offset) { + var point = { + x: from.x, + y: from.y + }; + point[fromKey] = to[toKey || fromKey] + (offset || 0); + return point; + } + // eslint-disable-next-line valid-jsdoc + /** + * Return waypoint outside obstacle. + * @private + */ + function getMeOut(obstacle, point, direction) { + var useMax = abs(point[direction] - obstacle[direction + 'Min']) > + abs(point[direction] - obstacle[direction + 'Max']); + return copyFromPoint(point, direction, obstacle, direction + (useMax ? 'Max' : 'Min'), useMax ? 1 : -1); + } + // Pull out end point + if (endObstacleIx > -1) { + endObstacle = chartObstacles[endObstacleIx]; + waypoint = getMeOut(endObstacle, end, dir); + endSegment = { + start: waypoint, + end: end + }; + endPoint = waypoint; + } + else { + endPoint = end; + } + // If an obstacle envelops the start point, add a segment to get out, + // and around it. + if (startObstacleIx > -1) { + startObstacle = chartObstacles[startObstacleIx]; + waypoint = getMeOut(startObstacle, start, dir); + segments.push({ + start: start, + end: waypoint + }); + // If we are going back again, switch direction to get around start + // obstacle. + if ( + // Going towards max from start: + waypoint[dir] >= start[dir] === + // Going towards min to end: + waypoint[dir] >= endPoint[dir]) { + dir = dir === 'y' ? 'x' : 'y'; + useMax = start[dir] < end[dir]; + segments.push({ + start: waypoint, + end: copyFromPoint(waypoint, dir, startObstacle, dir + (useMax ? 'Max' : 'Min'), useMax ? 1 : -1) + }); + // Switch direction again + dir = dir === 'y' ? 'x' : 'y'; + } + } + // We are around the start obstacle. Go towards the end in one + // direction. + prevWaypoint = segments.length ? + segments[segments.length - 1].end : + start; + waypoint = copyFromPoint(prevWaypoint, dir, endPoint); + segments.push({ + start: prevWaypoint, + end: waypoint + }); + // Final run to end point in the other direction + dir = dir === 'y' ? 'x' : 'y'; + waypoint2 = copyFromPoint(waypoint, dir, endPoint); + segments.push({ + start: waypoint, + end: waypoint2 + }); + // Finally add the endSegment + segments.push(endSegment); + return { + path: pathFromSegments(segments), + obstacles: segments + }; + }, { + requiresObstacles: true + }), + /** + * Find a path from a starting coordinate to an ending coordinate, taking + * obstacles into consideration. Might not always find the optimal path, + * but is fast, and usually good enough. + * + * @function Highcharts.Pathfinder.algorithms.fastAvoid + * + * @param {Highcharts.PositionObject} start + * Starting coordinate, object with x/y props. + * + * @param {Highcharts.PositionObject} end + * Ending coordinate, object with x/y props. + * + * @param {object} options + * Options for the algorithm. + * - chartObstacles: Array of chart obstacles to avoid + * - lineObstacles: Array of line obstacles to jump over + * - obstacleMetrics: Object with metrics of chartObstacles cached + * - hardBounds: Hard boundaries to not cross + * - obstacleOptions: Options for the obstacles, including margin + * - startDirectionX: Optional. True if starting in the X direction. + * If not provided, the algorithm starts in the + * direction that is the furthest between + * start/end. + * + * @return {object} + * An object with the SVG path in Array form as accepted by the SVG + * renderer, as well as an array of new obstacles making up this + * path. + */ + fastAvoid: extend(function (start, end, options) { + /* + Algorithm rules/description + - Find initial direction + - Determine soft/hard max for each direction. + - Move along initial direction until obstacle. + - Change direction. + - If hitting obstacle, first try to change length of previous line + before changing direction again. + + Soft min/max x = start/destination x +/- widest obstacle + margin + Soft min/max y = start/destination y +/- tallest obstacle + margin + + @todo: + - Make retrospective, try changing prev segment to reduce + corners + - Fix logic for breaking out of end-points - not always picking + the best direction currently + - When going around the end obstacle we should not always go the + shortest route, rather pick the one closer to the end point + */ + var dirIsX = pick(options.startDirectionX, abs(end.x - start.x) > abs(end.y - start.y)), dir = dirIsX ? 'x' : 'y', segments, useMax, extractedEndPoint, endSegments = [], forceObstacleBreak = false, // Used in clearPathTo to keep track of + // when to force break through an obstacle. + // Boundaries to stay within. If beyond soft boundary, prefer to + // change direction ASAP. If at hard max, always change immediately. + metrics = options.obstacleMetrics, softMinX = min(start.x, end.x) - metrics.maxWidth - 10, softMaxX = max(start.x, end.x) + metrics.maxWidth + 10, softMinY = min(start.y, end.y) - metrics.maxHeight - 10, softMaxY = max(start.y, end.y) + metrics.maxHeight + 10, + // Obstacles + chartObstacles = options.chartObstacles, startObstacleIx = findLastObstacleBefore(chartObstacles, softMinX), endObstacleIx = findLastObstacleBefore(chartObstacles, softMaxX); + // eslint-disable-next-line valid-jsdoc + /** + * How far can you go between two points before hitting an obstacle? + * Does not work for diagonal lines (because it doesn't have to). + * @private + */ + function pivotPoint(fromPoint, toPoint, directionIsX) { + var firstPoint, lastPoint, highestPoint, lowestPoint, i, searchDirection = fromPoint.x < toPoint.x ? 1 : -1; + if (fromPoint.x < toPoint.x) { + firstPoint = fromPoint; + lastPoint = toPoint; + } + else { + firstPoint = toPoint; + lastPoint = fromPoint; + } + if (fromPoint.y < toPoint.y) { + lowestPoint = fromPoint; + highestPoint = toPoint; + } + else { + lowestPoint = toPoint; + highestPoint = fromPoint; + } + // Go through obstacle range in reverse if toPoint is before + // fromPoint in the X-dimension. + i = searchDirection < 0 ? + // Searching backwards, start at last obstacle before last point + min(findLastObstacleBefore(chartObstacles, lastPoint.x), chartObstacles.length - 1) : + // Forwards. Since we're not sorted by xMax, we have to look + // at all obstacles. + 0; + // Go through obstacles in this X range + while (chartObstacles[i] && (searchDirection > 0 && chartObstacles[i].xMin <= lastPoint.x || + searchDirection < 0 && chartObstacles[i].xMax >= firstPoint.x)) { + // If this obstacle is between from and to points in a straight + // line, pivot at the intersection. + if (chartObstacles[i].xMin <= lastPoint.x && + chartObstacles[i].xMax >= firstPoint.x && + chartObstacles[i].yMin <= highestPoint.y && + chartObstacles[i].yMax >= lowestPoint.y) { + if (directionIsX) { + return { + y: fromPoint.y, + x: fromPoint.x < toPoint.x ? + chartObstacles[i].xMin - 1 : + chartObstacles[i].xMax + 1, + obstacle: chartObstacles[i] + }; + } + // else ... + return { + x: fromPoint.x, + y: fromPoint.y < toPoint.y ? + chartObstacles[i].yMin - 1 : + chartObstacles[i].yMax + 1, + obstacle: chartObstacles[i] + }; + } + i += searchDirection; + } + return toPoint; + } + /** + * Decide in which direction to dodge or get out of an obstacle. + * Considers desired direction, which way is shortest, soft and hard + * bounds. + * + * (? Returns a string, either xMin, xMax, yMin or yMax.) + * + * @private + * @function + * + * @param {object} obstacle + * Obstacle to dodge/escape. + * + * @param {object} fromPoint + * Point with x/y props that's dodging/escaping. + * + * @param {object} toPoint + * Goal point. + * + * @param {boolean} dirIsX + * Dodge in X dimension. + * + * @param {object} bounds + * Hard and soft boundaries. + * + * @return {boolean} + * Use max or not. + */ + function getDodgeDirection(obstacle, fromPoint, toPoint, dirIsX, bounds) { + var softBounds = bounds.soft, hardBounds = bounds.hard, dir = dirIsX ? 'x' : 'y', toPointMax = { x: fromPoint.x, y: fromPoint.y }, toPointMin = { x: fromPoint.x, y: fromPoint.y }, minPivot, maxPivot, maxOutOfSoftBounds = obstacle[dir + 'Max'] >= + softBounds[dir + 'Max'], minOutOfSoftBounds = obstacle[dir + 'Min'] <= + softBounds[dir + 'Min'], maxOutOfHardBounds = obstacle[dir + 'Max'] >= + hardBounds[dir + 'Max'], minOutOfHardBounds = obstacle[dir + 'Min'] <= + hardBounds[dir + 'Min'], + // Find out if we should prefer one direction over the other if + // we can choose freely + minDistance = abs(obstacle[dir + 'Min'] - fromPoint[dir]), maxDistance = abs(obstacle[dir + 'Max'] - fromPoint[dir]), + // If it's a small difference, pick the one leading towards dest + // point. Otherwise pick the shortest distance + useMax = abs(minDistance - maxDistance) < 10 ? + fromPoint[dir] < toPoint[dir] : + maxDistance < minDistance; + // Check if we hit any obstacles trying to go around in either + // direction. + toPointMin[dir] = obstacle[dir + 'Min']; + toPointMax[dir] = obstacle[dir + 'Max']; + minPivot = pivotPoint(fromPoint, toPointMin, dirIsX)[dir] !== + toPointMin[dir]; + maxPivot = pivotPoint(fromPoint, toPointMax, dirIsX)[dir] !== + toPointMax[dir]; + useMax = minPivot ? + (maxPivot ? useMax : true) : + (maxPivot ? false : useMax); + // useMax now contains our preferred choice, bounds not taken into + // account. If both or neither direction is out of bounds we want to + // use this. + // Deal with soft bounds + useMax = minOutOfSoftBounds ? + (maxOutOfSoftBounds ? useMax : true) : // Out on min + (maxOutOfSoftBounds ? false : useMax); // Not out on min + // Deal with hard bounds + useMax = minOutOfHardBounds ? + (maxOutOfHardBounds ? useMax : true) : // Out on min + (maxOutOfHardBounds ? false : useMax); // Not out on min + return useMax; + } + // eslint-disable-next-line valid-jsdoc + /** + * Find a clear path between point. + * @private + */ + function clearPathTo(fromPoint, toPoint, dirIsX) { + // Don't waste time if we've hit goal + if (fromPoint.x === toPoint.x && fromPoint.y === toPoint.y) { + return []; + } + var dir = dirIsX ? 'x' : 'y', pivot, segments, waypoint, waypointUseMax, envelopingObstacle, secondEnvelopingObstacle, envelopWaypoint, obstacleMargin = options.obstacleOptions.margin, bounds = { + soft: { + xMin: softMinX, + xMax: softMaxX, + yMin: softMinY, + yMax: softMaxY + }, + hard: options.hardBounds + }; + // If fromPoint is inside an obstacle we have a problem. Break out + // by just going to the outside of this obstacle. We prefer to go to + // the nearest edge in the chosen direction. + envelopingObstacle = + findObstacleFromPoint(chartObstacles, fromPoint); + if (envelopingObstacle > -1) { + envelopingObstacle = chartObstacles[envelopingObstacle]; + waypointUseMax = getDodgeDirection(envelopingObstacle, fromPoint, toPoint, dirIsX, bounds); + // Cut obstacle to hard bounds to make sure we stay within + limitObstacleToBounds(envelopingObstacle, options.hardBounds); + envelopWaypoint = dirIsX ? { + y: fromPoint.y, + x: envelopingObstacle[waypointUseMax ? 'xMax' : 'xMin'] + + (waypointUseMax ? 1 : -1) + } : { + x: fromPoint.x, + y: envelopingObstacle[waypointUseMax ? 'yMax' : 'yMin'] + + (waypointUseMax ? 1 : -1) + }; + // If we crashed into another obstacle doing this, we put the + // waypoint between them instead + secondEnvelopingObstacle = findObstacleFromPoint(chartObstacles, envelopWaypoint); + if (secondEnvelopingObstacle > -1) { + secondEnvelopingObstacle = chartObstacles[secondEnvelopingObstacle]; + // Cut obstacle to hard bounds + limitObstacleToBounds(secondEnvelopingObstacle, options.hardBounds); + // Modify waypoint to lay between obstacles + envelopWaypoint[dir] = waypointUseMax ? max(envelopingObstacle[dir + 'Max'] - obstacleMargin + 1, (secondEnvelopingObstacle[dir + 'Min'] + + envelopingObstacle[dir + 'Max']) / 2) : + min((envelopingObstacle[dir + 'Min'] + obstacleMargin - 1), ((secondEnvelopingObstacle[dir + 'Max'] + + envelopingObstacle[dir + 'Min']) / 2)); + // We are not going anywhere. If this happens for the first + // time, do nothing. Otherwise, try to go to the extreme of + // the obstacle pair in the current direction. + if (fromPoint.x === envelopWaypoint.x && + fromPoint.y === envelopWaypoint.y) { + if (forceObstacleBreak) { + envelopWaypoint[dir] = waypointUseMax ? + max(envelopingObstacle[dir + 'Max'], secondEnvelopingObstacle[dir + 'Max']) + 1 : + min(envelopingObstacle[dir + 'Min'], secondEnvelopingObstacle[dir + 'Min']) - 1; + } + // Toggle on if off, and the opposite + forceObstacleBreak = !forceObstacleBreak; + } + else { + // This point is not identical to previous. + // Clear break trigger. + forceObstacleBreak = false; + } + } + segments = [{ + start: fromPoint, + end: envelopWaypoint + }]; + } + else { // If not enveloping, use standard pivot calculation + pivot = pivotPoint(fromPoint, { + x: dirIsX ? toPoint.x : fromPoint.x, + y: dirIsX ? fromPoint.y : toPoint.y + }, dirIsX); + segments = [{ + start: fromPoint, + end: { + x: pivot.x, + y: pivot.y + } + }]; + // Pivot before goal, use a waypoint to dodge obstacle + if (pivot[dirIsX ? 'x' : 'y'] !== toPoint[dirIsX ? 'x' : 'y']) { + // Find direction of waypoint + waypointUseMax = getDodgeDirection(pivot.obstacle, pivot, toPoint, !dirIsX, bounds); + // Cut waypoint to hard bounds + limitObstacleToBounds(pivot.obstacle, options.hardBounds); + waypoint = { + x: dirIsX ? + pivot.x : + pivot.obstacle[waypointUseMax ? 'xMax' : 'xMin'] + + (waypointUseMax ? 1 : -1), + y: dirIsX ? + pivot.obstacle[waypointUseMax ? 'yMax' : 'yMin'] + + (waypointUseMax ? 1 : -1) : + pivot.y + }; + // We're changing direction here, store that to make sure we + // also change direction when adding the last segment array + // after handling waypoint. + dirIsX = !dirIsX; + segments = segments.concat(clearPathTo({ + x: pivot.x, + y: pivot.y + }, waypoint, dirIsX)); + } + } + // Get segments for the other direction too + // Recursion is our friend + segments = segments.concat(clearPathTo(segments[segments.length - 1].end, toPoint, !dirIsX)); + return segments; + } + // eslint-disable-next-line valid-jsdoc + /** + * Extract point to outside of obstacle in whichever direction is + * closest. Returns new point outside obstacle. + * @private + */ + function extractFromObstacle(obstacle, point, goalPoint) { + var dirIsX = min(obstacle.xMax - point.x, point.x - obstacle.xMin) < + min(obstacle.yMax - point.y, point.y - obstacle.yMin), bounds = { + soft: options.hardBounds, + hard: options.hardBounds + }, useMax = getDodgeDirection(obstacle, point, goalPoint, dirIsX, bounds); + return dirIsX ? { + y: point.y, + x: obstacle[useMax ? 'xMax' : 'xMin'] + (useMax ? 1 : -1) + } : { + x: point.x, + y: obstacle[useMax ? 'yMax' : 'yMin'] + (useMax ? 1 : -1) + }; + } + // Cut the obstacle array to soft bounds for optimization in large + // datasets. + chartObstacles = + chartObstacles.slice(startObstacleIx, endObstacleIx + 1); + // If an obstacle envelops the end point, move it out of there and add + // a little segment to where it was. + if ((endObstacleIx = findObstacleFromPoint(chartObstacles, end)) > -1) { + extractedEndPoint = extractFromObstacle(chartObstacles[endObstacleIx], end, start); + endSegments.push({ + end: end, + start: extractedEndPoint + }); + end = extractedEndPoint; + } + // If it's still inside one or more obstacles, get out of there by + // force-moving towards the start point. + while ((endObstacleIx = findObstacleFromPoint(chartObstacles, end)) > -1) { + useMax = end[dir] - start[dir] < 0; + extractedEndPoint = { + x: end.x, + y: end.y + }; + extractedEndPoint[dir] = chartObstacles[endObstacleIx][useMax ? dir + 'Max' : dir + 'Min'] + (useMax ? 1 : -1); + endSegments.push({ + end: end, + start: extractedEndPoint + }); + end = extractedEndPoint; + } + // Find the path + segments = clearPathTo(start, end, dirIsX); + // Add the end-point segments + segments = segments.concat(endSegments.reverse()); + return { + path: pathFromSegments(segments), + obstacles: segments + }; + }, { + requiresObstacles: true + }) + }; + + return algorithms; + }); + _registerModule(_modules, 'parts-gantt/ArrowSymbols.js', [_modules['parts/Globals.js']], function (H) { + /* * + * + * (c) 2017 Highsoft AS + * Authors: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Creates an arrow symbol. Like a triangle, except not filled. + * ``` + * o + * o + * o + * o + * o + * o + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols.arrow = function (x, y, w, h) { + return [ + ['M', x, y + h / 2], + ['L', x + w, y], + ['L', x, y + h / 2], + ['L', x + w, y + h] + ]; + }; + /** + * Creates a half-width arrow symbol. Like a triangle, except not filled. + * ``` + * o + * o + * o + * o + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols['arrow-half'] = function (x, y, w, h) { + return H.SVGRenderer.prototype.symbols.arrow(x, y, w / 2, h); + }; + /** + * Creates a left-oriented triangle. + * ``` + * o + * ooooooo + * ooooooooooooo + * ooooooo + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the triangle + * + * @param {number} y + * y position of the triangle + * + * @param {number} w + * width of the triangle + * + * @param {number} h + * height of the triangle + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols['triangle-left'] = function (x, y, w, h) { + return [ + ['M', x + w, y], + ['L', x, y + h / 2], + ['L', x + w, y + h], + ['Z'] + ]; + }; + /** + * Alias function for triangle-left. + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols['arrow-filled'] = + H.SVGRenderer.prototype.symbols['triangle-left']; + /** + * Creates a half-width, left-oriented triangle. + * ``` + * o + * oooo + * ooooooo + * oooo + * o + * ``` + * + * @private + * @function + * + * @param {number} x + * x position of the triangle + * + * @param {number} y + * y position of the triangle + * + * @param {number} w + * width of the triangle + * + * @param {number} h + * height of the triangle + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols['triangle-left-half'] = function (x, y, w, h) { + return H.SVGRenderer.prototype.symbols['triangle-left'](x, y, w / 2, h); + }; + /** + * Alias function for triangle-left-half. + * + * @private + * @function + * + * @param {number} x + * x position of the arrow + * + * @param {number} y + * y position of the arrow + * + * @param {number} w + * width of the arrow + * + * @param {number} h + * height of the arrow + * + * @return {Highcharts.SVGPathArray} + * Path array + */ + H.SVGRenderer.prototype.symbols['arrow-filled-half'] = + H.SVGRenderer.prototype.symbols['triangle-left-half']; + + }); + _registerModule(_modules, 'parts-gantt/Pathfinder.js', [_modules['parts/Globals.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js'], _modules['parts-gantt/PathfinderAlgorithms.js']], function (H, Point, U, pathfinderAlgorithms) { + /* * + * + * (c) 2016 Highsoft AS + * Authors: Øystein Moseng, Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * The default pathfinder algorithm to use for a chart. It is possible to define + * your own algorithms by adding them to the + * `Highcharts.Pathfinder.prototype.algorithms` + * object before the chart has been created. + * + * The default algorithms are as follows: + * + * `straight`: Draws a straight line between the connecting + * points. Does not avoid other points when drawing. + * + * `simpleConnect`: Finds a path between the points using right angles + * only. Takes only starting/ending points into + * account, and will not avoid other points. + * + * `fastAvoid`: Finds a path between the points using right angles + * only. Will attempt to avoid other points, but its + * focus is performance over accuracy. Works well with + * less dense datasets. + * + * @typedef {"fastAvoid"|"simpleConnect"|"straight"|string} Highcharts.PathfinderTypeValue + */ + ''; // detach doclets above + var addEvent = U.addEvent, defined = U.defined, error = U.error, extend = U.extend, merge = U.merge, objectEach = U.objectEach, pick = U.pick, splat = U.splat; + var deg2rad = H.deg2rad, max = Math.max, min = Math.min; + /* + @todo: + - Document how to write your own algorithms + - Consider adding a Point.pathTo method that wraps creating a connection + and rendering it + */ + // Set default Pathfinder options + extend(H.defaultOptions, { + /** + * The Pathfinder module allows you to define connections between any two + * points, represented as lines - optionally with markers for the start + * and/or end points. Multiple algorithms are available for calculating how + * the connecting lines are drawn. + * + * Connector functionality requires Highcharts Gantt to be loaded. In Gantt + * charts, the connectors are used to draw dependencies between tasks. + * + * @see [dependency](series.gantt.data.dependency) + * + * @sample gantt/pathfinder/demo + * Pathfinder connections + * + * @declare Highcharts.ConnectorsOptions + * @product gantt + * @optionparent connectors + */ + connectors: { + /** + * Enable connectors for this chart. Requires Highcharts Gantt. + * + * @type {boolean} + * @default true + * @since 6.2.0 + * @apioption connectors.enabled + */ + /** + * Set the default dash style for this chart's connecting lines. + * + * @type {string} + * @default solid + * @since 6.2.0 + * @apioption connectors.dashStyle + */ + /** + * Set the default color for this chart's Pathfinder connecting lines. + * Defaults to the color of the point being connected. + * + * @type {Highcharts.ColorString} + * @since 6.2.0 + * @apioption connectors.lineColor + */ + /** + * Set the default pathfinder margin to use, in pixels. Some Pathfinder + * algorithms attempt to avoid obstacles, such as other points in the + * chart. These algorithms use this margin to determine how close lines + * can be to an obstacle. The default is to compute this automatically + * from the size of the obstacles in the chart. + * + * To draw connecting lines close to existing points, set this to a low + * number. For more space around existing points, set this number + * higher. + * + * @sample gantt/pathfinder/algorithm-margin + * Small algorithmMargin + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.algorithmMargin + */ + /** + * Set the default pathfinder algorithm to use for this chart. It is + * possible to define your own algorithms by adding them to the + * Highcharts.Pathfinder.prototype.algorithms object before the chart + * has been created. + * + * The default algorithms are as follows: + * + * `straight`: Draws a straight line between the connecting + * points. Does not avoid other points when drawing. + * + * `simpleConnect`: Finds a path between the points using right angles + * only. Takes only starting/ending points into + * account, and will not avoid other points. + * + * `fastAvoid`: Finds a path between the points using right angles + * only. Will attempt to avoid other points, but its + * focus is performance over accuracy. Works well with + * less dense datasets. + * + * Default value: `straight` is used as default for most series types, + * while `simpleConnect` is used as default for Gantt series, to show + * dependencies between points. + * + * @sample gantt/pathfinder/demo + * Different types used + * + * @type {Highcharts.PathfinderTypeValue} + * @default undefined + * @since 6.2.0 + */ + type: 'straight', + /** + * Set the default pixel width for this chart's Pathfinder connecting + * lines. + * + * @since 6.2.0 + */ + lineWidth: 1, + /** + * Marker options for this chart's Pathfinder connectors. Note that + * this option is overridden by the `startMarker` and `endMarker` + * options. + * + * @declare Highcharts.ConnectorsMarkerOptions + * @since 6.2.0 + */ + marker: { + /** + * Set the radius of the connector markers. The default is + * automatically computed based on the algorithmMargin setting. + * + * Setting marker.width and marker.height will override this + * setting. + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.marker.radius + */ + /** + * Set the width of the connector markers. If not supplied, this + * is inferred from the marker radius. + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.marker.width + */ + /** + * Set the height of the connector markers. If not supplied, this + * is inferred from the marker radius. + * + * @type {number} + * @since 6.2.0 + * @apioption connectors.marker.height + */ + /** + * Set the color of the connector markers. By default this is the + * same as the connector color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 6.2.0 + * @apioption connectors.marker.color + */ + /** + * Set the line/border color of the connector markers. By default + * this is the same as the marker color. + * + * @type {Highcharts.ColorString} + * @since 6.2.0 + * @apioption connectors.marker.lineColor + */ + /** + * Enable markers for the connectors. + */ + enabled: false, + /** + * Horizontal alignment of the markers relative to the points. + * + * @type {Highcharts.AlignValue} + */ + align: 'center', + /** + * Vertical alignment of the markers relative to the points. + * + * @type {Highcharts.VerticalAlignValue} + */ + verticalAlign: 'middle', + /** + * Whether or not to draw the markers inside the points. + */ + inside: false, + /** + * Set the line/border width of the pathfinder markers. + */ + lineWidth: 1 + }, + /** + * Marker options specific to the start markers for this chart's + * Pathfinder connectors. Overrides the generic marker options. + * + * @declare Highcharts.ConnectorsStartMarkerOptions + * @extends connectors.marker + * @since 6.2.0 + */ + startMarker: { + /** + * Set the symbol of the connector start markers. + */ + symbol: 'diamond' + }, + /** + * Marker options specific to the end markers for this chart's + * Pathfinder connectors. Overrides the generic marker options. + * + * @declare Highcharts.ConnectorsEndMarkerOptions + * @extends connectors.marker + * @since 6.2.0 + */ + endMarker: { + /** + * Set the symbol of the connector end markers. + */ + symbol: 'arrow-filled' + } + } + }); + /** + * Override Pathfinder connector options for a series. Requires Highcharts Gantt + * to be loaded. + * + * @declare Highcharts.SeriesConnectorsOptionsObject + * @extends connectors + * @since 6.2.0 + * @excluding enabled, algorithmMargin + * @product gantt + * @apioption plotOptions.series.connectors + */ + /** + * Connect to a point. This option can be either a string, referring to the ID + * of another point, or an object, or an array of either. If the option is an + * array, each element defines a connection. + * + * @sample gantt/pathfinder/demo + * Different connection types + * + * @declare Highcharts.XrangePointConnectorsOptionsObject + * @type {string|Array|*} + * @extends plotOptions.series.connectors + * @since 6.2.0 + * @excluding enabled + * @product gantt + * @requires highcharts-gantt + * @apioption series.xrange.data.connect + */ + /** + * The ID of the point to connect to. + * + * @type {string} + * @since 6.2.0 + * @product gantt + * @apioption series.xrange.data.connect.to + */ + /** + * Get point bounding box using plotX/plotY and shapeArgs. If using + * graphic.getBBox() directly, the bbox will be affected by animation. + * + * @private + * @function + * + * @param {Highcharts.Point} point + * The point to get BB of. + * + * @return {Highcharts.Dictionary|null} + * Result xMax, xMin, yMax, yMin. + */ + function getPointBB(point) { + var shapeArgs = point.shapeArgs, bb; + // Prefer using shapeArgs (columns) + if (shapeArgs) { + return { + xMin: shapeArgs.x, + xMax: shapeArgs.x + shapeArgs.width, + yMin: shapeArgs.y, + yMax: shapeArgs.y + shapeArgs.height + }; + } + // Otherwise use plotX/plotY and bb + bb = point.graphic && point.graphic.getBBox(); + return bb ? { + xMin: point.plotX - bb.width / 2, + xMax: point.plotX + bb.width / 2, + yMin: point.plotY - bb.height / 2, + yMax: point.plotY + bb.height / 2 + } : null; + } + /** + * Calculate margin to place around obstacles for the pathfinder in pixels. + * Returns a minimum of 1 pixel margin. + * + * @private + * @function + * + * @param {Array} obstacles + * Obstacles to calculate margin from. + * + * @return {number} + * The calculated margin in pixels. At least 1. + */ + function calculateObstacleMargin(obstacles) { + var len = obstacles.length, i = 0, j, obstacleDistance, distances = [], + // Compute smallest distance between two rectangles + distance = function (a, b, bbMargin) { + // Count the distance even if we are slightly off + var margin = pick(bbMargin, 10), yOverlap = a.yMax + margin > b.yMin - margin && + a.yMin - margin < b.yMax + margin, xOverlap = a.xMax + margin > b.xMin - margin && + a.xMin - margin < b.xMax + margin, xDistance = yOverlap ? (a.xMin > b.xMax ? a.xMin - b.xMax : b.xMin - a.xMax) : Infinity, yDistance = xOverlap ? (a.yMin > b.yMax ? a.yMin - b.yMax : b.yMin - a.yMax) : Infinity; + // If the rectangles collide, try recomputing with smaller margin. + // If they collide anyway, discard the obstacle. + if (xOverlap && yOverlap) { + return (margin ? + distance(a, b, Math.floor(margin / 2)) : + Infinity); + } + return min(xDistance, yDistance); + }; + // Go over all obstacles and compare them to the others. + for (; i < len; ++i) { + // Compare to all obstacles ahead. We will already have compared this + // obstacle to the ones before. + for (j = i + 1; j < len; ++j) { + obstacleDistance = distance(obstacles[i], obstacles[j]); + // TODO: Magic number 80 + if (obstacleDistance < 80) { // Ignore large distances + distances.push(obstacleDistance); + } + } + } + // Ensure we always have at least one value, even in very spaceous charts + distances.push(80); + return max(Math.floor(distances.sort(function (a, b) { + return (a - b); + })[ + // Discard first 10% of the relevant distances, and then grab + // the smallest one. + Math.floor(distances.length / 10)] / 2 - 1 // Divide the distance by 2 and subtract 1. + ), 1 // 1 is the minimum margin + ); + } + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The Connection class. Used internally to represent a connection between two + * points. + * + * @private + * @class + * @name Highcharts.Connection + * + * @param {Highcharts.Point} from + * Connection runs from this Point. + * + * @param {Highcharts.Point} to + * Connection runs to this Point. + * + * @param {Highcharts.ConnectorsOptions} [options] + * Connection options. + */ + function Connection(from, to, options) { + this.init(from, to, options); + } + Connection.prototype = { + /** + * Initialize the Connection object. Used as constructor only. + * + * @function Highcharts.Connection#init + * + * @param {Highcharts.Point} from + * Connection runs from this Point. + * + * @param {Highcharts.Point} to + * Connection runs to this Point. + * + * @param {Highcharts.ConnectorsOptions} [options] + * Connection options. + */ + init: function (from, to, options) { + this.fromPoint = from; + this.toPoint = to; + this.options = options; + this.chart = from.series.chart; + this.pathfinder = this.chart.pathfinder; + }, + /** + * Add (or update) this connection's path on chart. Stores reference to the + * created element on this.graphics.path. + * + * @function Highcharts.Connection#renderPath + * + * @param {Highcharts.SVGPathArray} path + * Path to render, in array format. E.g. ['M', 0, 0, 'L', 10, 10] + * + * @param {Highcharts.SVGAttributes} [attribs] + * SVG attributes for the path. + * + * @param {Highcharts.AnimationOptionsObject} [animation] + * Animation options for the rendering. + */ + renderPath: function (path, attribs, animation) { + var connection = this, chart = this.chart, styledMode = chart.styledMode, pathfinder = chart.pathfinder, animate = !chart.options.chart.forExport && animation !== false, pathGraphic = connection.graphics && connection.graphics.path, anim; + // Add the SVG element of the pathfinder group if it doesn't exist + if (!pathfinder.group) { + pathfinder.group = chart.renderer.g() + .addClass('highcharts-pathfinder-group') + .attr({ zIndex: -1 }) + .add(chart.seriesGroup); + } + // Shift the group to compensate for plot area. + // Note: Do this always (even when redrawing a path) to avoid issues + // when updating chart in a way that changes plot metrics. + pathfinder.group.translate(chart.plotLeft, chart.plotTop); + // Create path if does not exist + if (!(pathGraphic && pathGraphic.renderer)) { + pathGraphic = chart.renderer.path() + .add(pathfinder.group); + if (!styledMode) { + pathGraphic.attr({ + opacity: 0 + }); + } + } + // Set path attribs and animate to the new path + pathGraphic.attr(attribs); + anim = { d: path }; + if (!styledMode) { + anim.opacity = 1; + } + pathGraphic[animate ? 'animate' : 'attr'](anim, animation); + // Store reference on connection + this.graphics = this.graphics || {}; + this.graphics.path = pathGraphic; + }, + /** + * Calculate and add marker graphics for connection to the chart. The + * created/updated elements are stored on this.graphics.start and + * this.graphics.end. + * + * @function Highcharts.Connection#addMarker + * + * @param {string} type + * Marker type, either 'start' or 'end'. + * + * @param {Highcharts.ConnectorsMarkerOptions} options + * All options for this marker. Not calculated or merged with other + * options. + * + * @param {Highcharts.SVGPathArray} path + * Connection path in array format. This is used to calculate the + * rotation angle of the markers. + */ + addMarker: function (type, options, path) { + var connection = this, chart = connection.fromPoint.series.chart, pathfinder = chart.pathfinder, renderer = chart.renderer, point = (type === 'start' ? + connection.fromPoint : + connection.toPoint), anchor = point.getPathfinderAnchorPoint(options), markerVector, radians, rotation, box, width, height, pathVector, segment; + if (!options.enabled) { + return; + } + // Last vector before start/end of path, used to get angle + if (type === 'start') { + segment = path[1]; + } + else { // 'end' + segment = path[path.length - 2]; + } + if (segment && segment[0] === 'M' || segment[0] === 'L') { + pathVector = { + x: segment[1], + y: segment[2] + }; + // Get angle between pathVector and anchor point and use it to + // create marker position. + radians = point.getRadiansToVector(pathVector, anchor); + markerVector = point.getMarkerVector(radians, options.radius, anchor); + // Rotation of marker is calculated from angle between pathVector + // and markerVector. + // (Note: + // Used to recalculate radians between markerVector and pathVector, + // but this should be the same as between pathVector and anchor.) + rotation = -radians / deg2rad; + if (options.width && options.height) { + width = options.width; + height = options.height; + } + else { + width = height = options.radius * 2; + } + // Add graphics object if it does not exist + connection.graphics = connection.graphics || {}; + box = { + x: markerVector.x - (width / 2), + y: markerVector.y - (height / 2), + width: width, + height: height, + rotation: rotation, + rotationOriginX: markerVector.x, + rotationOriginY: markerVector.y + }; + if (!connection.graphics[type]) { + // Create new marker element + connection.graphics[type] = renderer + .symbol(options.symbol) + .addClass('highcharts-point-connecting-path-' + type + '-marker') + .attr(box) + .add(pathfinder.group); + if (!renderer.styledMode) { + connection.graphics[type].attr({ + fill: options.color || connection.fromPoint.color, + stroke: options.lineColor, + 'stroke-width': options.lineWidth, + opacity: 0 + }) + .animate({ + opacity: 1 + }, point.series.options.animation); + } + } + else { + connection.graphics[type].animate(box); + } + } + }, + /** + * Calculate and return connection path. + * Note: Recalculates chart obstacles on demand if they aren't calculated. + * + * @function Highcharts.Connection#getPath + * + * @param {Highcharts.ConnectorsOptions} options + * Connector options. Not calculated or merged with other options. + * + * @return {object|undefined} + * Calculated SVG path data in array format. + */ + getPath: function (options) { + var pathfinder = this.pathfinder, chart = this.chart, algorithm = pathfinder.algorithms[options.type], chartObstacles = pathfinder.chartObstacles; + if (typeof algorithm !== 'function') { + error('"' + options.type + '" is not a Pathfinder algorithm.'); + return; + } + // This function calculates obstacles on demand if they don't exist + if (algorithm.requiresObstacles && !chartObstacles) { + chartObstacles = + pathfinder.chartObstacles = + pathfinder.getChartObstacles(options); + // If the algorithmMargin was computed, store the result in default + // options. + chart.options.connectors.algorithmMargin = + options.algorithmMargin; + // Cache some metrics too + pathfinder.chartObstacleMetrics = + pathfinder.getObstacleMetrics(chartObstacles); + } + // Get the SVG path + return algorithm( + // From + this.fromPoint.getPathfinderAnchorPoint(options.startMarker), + // To + this.toPoint.getPathfinderAnchorPoint(options.endMarker), merge({ + chartObstacles: chartObstacles, + lineObstacles: pathfinder.lineObstacles || [], + obstacleMetrics: pathfinder.chartObstacleMetrics, + hardBounds: { + xMin: 0, + xMax: chart.plotWidth, + yMin: 0, + yMax: chart.plotHeight + }, + obstacleOptions: { + margin: options.algorithmMargin + }, + startDirectionX: pathfinder.getAlgorithmStartDirection(options.startMarker) + }, options)); + }, + /** + * (re)Calculate and (re)draw the connection. + * + * @function Highcharts.Connection#render + */ + render: function () { + var connection = this, fromPoint = connection.fromPoint, series = fromPoint.series, chart = series.chart, pathfinder = chart.pathfinder, pathResult, path, options = merge(chart.options.connectors, series.options.connectors, fromPoint.options.connectors, connection.options), attribs = {}; + // Set path attribs + if (!chart.styledMode) { + attribs.stroke = options.lineColor || fromPoint.color; + attribs['stroke-width'] = options.lineWidth; + if (options.dashStyle) { + attribs.dashstyle = options.dashStyle; + } + } + attribs['class'] = // eslint-disable-line dot-notation + 'highcharts-point-connecting-path ' + + 'highcharts-color-' + fromPoint.colorIndex; + options = merge(attribs, options); + // Set common marker options + if (!defined(options.marker.radius)) { + options.marker.radius = min(max(Math.ceil((options.algorithmMargin || 8) / 2) - 1, 1), 5); + } + // Get the path + pathResult = connection.getPath(options); + path = pathResult.path; + // Always update obstacle storage with obstacles from this path. + // We don't know if future calls will need this for their algorithm. + if (pathResult.obstacles) { + pathfinder.lineObstacles = + pathfinder.lineObstacles || []; + pathfinder.lineObstacles = + pathfinder.lineObstacles.concat(pathResult.obstacles); + } + // Add the calculated path to the pathfinder group + connection.renderPath(path, attribs, series.options.animation); + // Render the markers + connection.addMarker('start', merge(options.marker, options.startMarker), path); + connection.addMarker('end', merge(options.marker, options.endMarker), path); + }, + /** + * Destroy connection by destroying the added graphics elements. + * + * @function Highcharts.Connection#destroy + */ + destroy: function () { + if (this.graphics) { + objectEach(this.graphics, function (val) { + val.destroy(); + }); + delete this.graphics; + } + } + }; + /** + * The Pathfinder class. + * + * @private + * @class + * @name Highcharts.Pathfinder + * + * @param {Highcharts.Chart} chart + * The chart to operate on. + */ + function Pathfinder(chart) { + this.init(chart); + } + Pathfinder.prototype = { + /** + * @name Highcharts.Pathfinder#algorithms + * @type {Highcharts.Dictionary} + */ + algorithms: pathfinderAlgorithms, + /** + * Initialize the Pathfinder object. + * + * @function Highcharts.Pathfinder#init + * + * @param {Highcharts.Chart} chart + * The chart context. + */ + init: function (chart) { + // Initialize pathfinder with chart context + this.chart = chart; + // Init connection reference list + this.connections = []; + // Recalculate paths/obstacles on chart redraw + addEvent(chart, 'redraw', function () { + this.pathfinder.update(); + }); + }, + /** + * Update Pathfinder connections from scratch. + * + * @function Highcharts.Pathfinder#update + * + * @param {boolean} [deferRender] + * Whether or not to defer rendering of connections until + * series.afterAnimate event has fired. Used on first render. + */ + update: function (deferRender) { + var chart = this.chart, pathfinder = this, oldConnections = pathfinder.connections; + // Rebuild pathfinder connections from options + pathfinder.connections = []; + chart.series.forEach(function (series) { + if (series.visible && !series.options.isInternal) { + series.points.forEach(function (point) { + var to, connects = (point.options && + point.options.connect && + splat(point.options.connect)); + if (point.visible && point.isInside !== false && connects) { + connects.forEach(function (connect) { + to = chart.get(typeof connect === 'string' ? + connect : connect.to); + if (to instanceof Point && + to.series.visible && + to.visible && + to.isInside !== false) { + // Add new connection + pathfinder.connections.push(new Connection(point, // from + to, typeof connect === 'string' ? + {} : + connect)); + } + }); + } + }); + } + }); + // Clear connections that should not be updated, and move old info over + // to new connections. + for (var j = 0, k, found, lenOld = oldConnections.length, lenNew = pathfinder.connections.length; j < lenOld; ++j) { + found = false; + for (k = 0; k < lenNew; ++k) { + if (oldConnections[j].fromPoint === + pathfinder.connections[k].fromPoint && + oldConnections[j].toPoint === + pathfinder.connections[k].toPoint) { + pathfinder.connections[k].graphics = + oldConnections[j].graphics; + found = true; + break; + } + } + if (!found) { + oldConnections[j].destroy(); + } + } + // Clear obstacles to force recalculation. This must be done on every + // redraw in case positions have changed. Recalculation is handled in + // Connection.getPath on demand. + delete this.chartObstacles; + delete this.lineObstacles; + // Draw the pending connections + pathfinder.renderConnections(deferRender); + }, + /** + * Draw the chart's connecting paths. + * + * @function Highcharts.Pathfinder#renderConnections + * + * @param {boolean} [deferRender] + * Whether or not to defer render until series animation is finished. + * Used on first render. + */ + renderConnections: function (deferRender) { + if (deferRender) { + // Render after series are done animating + this.chart.series.forEach(function (series) { + var render = function () { + // Find pathfinder connections belonging to this series + // that haven't rendered, and render them now. + var pathfinder = series.chart.pathfinder, conns = pathfinder && pathfinder.connections || []; + conns.forEach(function (connection) { + if (connection.fromPoint && + connection.fromPoint.series === series) { + connection.render(); + } + }); + if (series.pathfinderRemoveRenderEvent) { + series.pathfinderRemoveRenderEvent(); + delete series.pathfinderRemoveRenderEvent; + } + }; + if (series.options.animation === false) { + render(); + } + else { + series.pathfinderRemoveRenderEvent = addEvent(series, 'afterAnimate', render); + } + }); + } + else { + // Go through connections and render them + this.connections.forEach(function (connection) { + connection.render(); + }); + } + }, + /** + * Get obstacles for the points in the chart. Does not include connecting + * lines from Pathfinder. Applies algorithmMargin to the obstacles. + * + * @function Highcharts.Pathfinder#getChartObstacles + * + * @param {object} options + * Options for the calculation. Currenlty only + * options.algorithmMargin. + * + * @return {Array} + * An array of calculated obstacles. Each obstacle is defined as an + * object with xMin, xMax, yMin and yMax properties. + */ + getChartObstacles: function (options) { + var obstacles = [], series = this.chart.series, margin = pick(options.algorithmMargin, 0), calculatedMargin; + for (var i = 0, sLen = series.length; i < sLen; ++i) { + if (series[i].visible && !series[i].options.isInternal) { + for (var j = 0, pLen = series[i].points.length, bb, point; j < pLen; ++j) { + point = series[i].points[j]; + if (point.visible) { + bb = getPointBB(point); + if (bb) { + obstacles.push({ + xMin: bb.xMin - margin, + xMax: bb.xMax + margin, + yMin: bb.yMin - margin, + yMax: bb.yMax + margin + }); + } + } + } + } + } + // Sort obstacles by xMin for optimization + obstacles = obstacles.sort(function (a, b) { + return a.xMin - b.xMin; + }); + // Add auto-calculated margin if the option is not defined + if (!defined(options.algorithmMargin)) { + calculatedMargin = + options.algorithmMargin = + calculateObstacleMargin(obstacles); + obstacles.forEach(function (obstacle) { + obstacle.xMin -= calculatedMargin; + obstacle.xMax += calculatedMargin; + obstacle.yMin -= calculatedMargin; + obstacle.yMax += calculatedMargin; + }); + } + return obstacles; + }, + /** + * Utility function to get metrics for obstacles: + * - Widest obstacle width + * - Tallest obstacle height + * + * @function Highcharts.Pathfinder#getObstacleMetrics + * + * @param {Array} obstacles + * An array of obstacles to inspect. + * + * @return {object} + * The calculated metrics, as an object with maxHeight and maxWidth + * properties. + */ + getObstacleMetrics: function (obstacles) { + var maxWidth = 0, maxHeight = 0, width, height, i = obstacles.length; + while (i--) { + width = obstacles[i].xMax - obstacles[i].xMin; + height = obstacles[i].yMax - obstacles[i].yMin; + if (maxWidth < width) { + maxWidth = width; + } + if (maxHeight < height) { + maxHeight = height; + } + } + return { + maxHeight: maxHeight, + maxWidth: maxWidth + }; + }, + /** + * Utility to get which direction to start the pathfinding algorithm + * (X vs Y), calculated from a set of marker options. + * + * @function Highcharts.Pathfinder#getAlgorithmStartDirection + * + * @param {Highcharts.ConnectorsMarkerOptions} markerOptions + * Marker options to calculate from. + * + * @return {boolean} + * Returns true for X, false for Y, and undefined for autocalculate. + */ + getAlgorithmStartDirection: function (markerOptions) { + var xCenter = markerOptions.align !== 'left' && + markerOptions.align !== 'right', yCenter = markerOptions.verticalAlign !== 'top' && + markerOptions.verticalAlign !== 'bottom', undef; + return xCenter ? + (yCenter ? undef : false) : // x is centered + (yCenter ? true : undef); // x is off-center + } + }; + // Add to Highcharts namespace + H.Connection = Connection; + H.Pathfinder = Pathfinder; + // Add pathfinding capabilities to Points + extend(Point.prototype, /** @lends Point.prototype */ { + /** + * Get coordinates of anchor point for pathfinder connection. + * + * @private + * @function Highcharts.Point#getPathfinderAnchorPoint + * + * @param {Highcharts.ConnectorsMarkerOptions} markerOptions + * Connection options for position on point. + * + * @return {Highcharts.PositionObject} + * An object with x/y properties for the position. Coordinates are + * in plot values, not relative to point. + */ + getPathfinderAnchorPoint: function (markerOptions) { + var bb = getPointBB(this), x, y; + switch (markerOptions.align) { // eslint-disable-line default-case + case 'right': + x = 'xMax'; + break; + case 'left': + x = 'xMin'; + } + switch (markerOptions.verticalAlign) { // eslint-disable-line default-case + case 'top': + y = 'yMin'; + break; + case 'bottom': + y = 'yMax'; + } + return { + x: x ? bb[x] : (bb.xMin + bb.xMax) / 2, + y: y ? bb[y] : (bb.yMin + bb.yMax) / 2 + }; + }, + /** + * Utility to get the angle from one point to another. + * + * @private + * @function Highcharts.Point#getRadiansToVector + * + * @param {Highcharts.PositionObject} v1 + * The first vector, as an object with x/y properties. + * + * @param {Highcharts.PositionObject} v2 + * The second vector, as an object with x/y properties. + * + * @return {number} + * The angle in degrees + */ + getRadiansToVector: function (v1, v2) { + var box; + if (!defined(v2)) { + box = getPointBB(this); + if (box) { + v2 = { + x: (box.xMin + box.xMax) / 2, + y: (box.yMin + box.yMax) / 2 + }; + } + } + return Math.atan2(v2.y - v1.y, v1.x - v2.x); + }, + /** + * Utility to get the position of the marker, based on the path angle and + * the marker's radius. + * + * @private + * @function Highcharts.Point#getMarkerVector + * + * @param {number} radians + * The angle in radians from the point center to another vector. + * + * @param {number} markerRadius + * The radius of the marker, to calculate the additional distance to + * the center of the marker. + * + * @param {object} anchor + * The anchor point of the path and marker as an object with x/y + * properties. + * + * @return {object} + * The marker vector as an object with x/y properties. + */ + getMarkerVector: function (radians, markerRadius, anchor) { + var twoPI = Math.PI * 2.0, theta = radians, bb = getPointBB(this), rectWidth = bb.xMax - bb.xMin, rectHeight = bb.yMax - bb.yMin, rAtan = Math.atan2(rectHeight, rectWidth), tanTheta = 1, leftOrRightRegion = false, rectHalfWidth = rectWidth / 2.0, rectHalfHeight = rectHeight / 2.0, rectHorizontalCenter = bb.xMin + rectHalfWidth, rectVerticalCenter = bb.yMin + rectHalfHeight, edgePoint = { + x: rectHorizontalCenter, + y: rectVerticalCenter + }, markerPoint = {}, xFactor = 1, yFactor = 1; + while (theta < -Math.PI) { + theta += twoPI; + } + while (theta > Math.PI) { + theta -= twoPI; + } + tanTheta = Math.tan(theta); + if ((theta > -rAtan) && (theta <= rAtan)) { + // Right side + yFactor = -1; + leftOrRightRegion = true; + } + else if (theta > rAtan && theta <= (Math.PI - rAtan)) { + // Top side + yFactor = -1; + } + else if (theta > (Math.PI - rAtan) || theta <= -(Math.PI - rAtan)) { + // Left side + xFactor = -1; + leftOrRightRegion = true; + } + else { + // Bottom side + xFactor = -1; + } + // Correct the edgePoint according to the placement of the marker + if (leftOrRightRegion) { + edgePoint.x += xFactor * (rectHalfWidth); + edgePoint.y += yFactor * (rectHalfWidth) * tanTheta; + } + else { + edgePoint.x += xFactor * (rectHeight / (2.0 * tanTheta)); + edgePoint.y += yFactor * (rectHalfHeight); + } + if (anchor.x !== rectHorizontalCenter) { + edgePoint.x = anchor.x; + } + if (anchor.y !== rectVerticalCenter) { + edgePoint.y = anchor.y; + } + markerPoint.x = edgePoint.x + (markerRadius * Math.cos(theta)); + markerPoint.y = edgePoint.y - (markerRadius * Math.sin(theta)); + return markerPoint; + } + }); + /** + * Warn if using legacy options. Copy the options over. Note that this will + * still break if using the legacy options in chart.update, addSeries etc. + * @private + */ + function warnLegacy(chart) { + if (chart.options.pathfinder || + chart.series.reduce(function (acc, series) { + if (series.options) { + merge(true, (series.options.connectors = series.options.connectors || + {}), series.options.pathfinder); + } + return acc || series.options && series.options.pathfinder; + }, false)) { + merge(true, (chart.options.connectors = chart.options.connectors || {}), chart.options.pathfinder); + error('WARNING: Pathfinder options have been renamed. ' + + 'Use "chart.connectors" or "series.connectors" instead.'); + } + } + // Initialize Pathfinder for charts + H.Chart.prototype.callbacks.push(function (chart) { + var options = chart.options; + if (options.connectors.enabled !== false) { + warnLegacy(chart); + this.pathfinder = new Pathfinder(this); + this.pathfinder.update(true); // First draw, defer render + } + }); + + }); + _registerModule(_modules, 'masters/modules/pathfinder.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/pattern-fill.js b/librerias/gantt/code/modules/pattern-fill.js new file mode 100644 index 0000000..2b912b8 --- /dev/null +++ b/librerias/gantt/code/modules/pattern-fill.js @@ -0,0 +1,23 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Module for adding patterns and images as point fills. + + (c) 2010-2019 Highsoft AS + Author: Torstein Hnsi, ystein Moseng + + License: www.highcharts.com/license +*/ +(function(c){"object"===typeof module&&module.exports?(c["default"]=c,module.exports=c):"function"===typeof define&&define.amd?define("highcharts/modules/pattern-fill",["highcharts"],function(g){c(g);c.Highcharts=g;return c}):c("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(c){function g(c,n,e,g){c.hasOwnProperty(n)||(c[n]=g.apply(null,e))}c=c?c._modules:{};g(c,"modules/pattern-fill.src.js",[c["parts/Globals.js"],c["parts/Point.js"],c["parts/Utilities.js"]],function(c,g,e){function n(a, +b){a=JSON.stringify(a);var c=a.length||0,f=0,d=0;if(b){b=Math.max(Math.floor(c/500),1);for(var h=0;h +b.aspectRatio?b.aspectWidth=b.height*a.aspectRatio:b.aspectHeight=b.width/a.aspectRatio);a._width=a.width||Math.ceil(b.aspectWidth||b.width);a._height=a.height||Math.ceil(b.aspectHeight||b.height)}a.width||(a._x=a.x||0,a._x+=b.x-Math.round(b.aspectWidth?Math.abs(b.aspectWidth-b.width)/2:0));a.height||(a._y=a.y||0,a._y+=b.y-Math.round(b.aspectHeight?Math.abs(b.aspectHeight-b.height)/2:0))}};c.SVGRenderer.prototype.addPattern=function(a,b){b=q(b,!0);var c=t(b),f=a.width||a._width||32,d=a.height||a._height|| +32,h=a.color||"#343434",k=a.id,g=this,e=function(a){g.rect(0,0,f,d).attr({fill:a}).add(m)};k||(this.idCounter=this.idCounter||0,k="highcharts-pattern-"+this.idCounter+"-"+(this.chartIndex||0),++this.idCounter);this.defIds=this.defIds||[];if(!(-1 bBox.aspectRatio) { + // Height of bBox will determine width + bBox.aspectWidth = bBox.height * pattern.aspectRatio; + } + else { + // Width of bBox will determine height + bBox.aspectHeight = bBox.width / pattern.aspectRatio; + } + } + // We set the width/height on internal properties to differentiate + // between the options set by a user and by this function. + pattern._width = pattern.width || + Math.ceil(bBox.aspectWidth || bBox.width); + pattern._height = pattern.height || + Math.ceil(bBox.aspectHeight || bBox.height); + } + // Set x/y accordingly, centering if using aspect ratio, otherwise adjusting + // so bounding box corner is 0,0 of pattern. + if (!pattern.width) { + pattern._x = pattern.x || 0; + pattern._x += bBox.x - Math.round(bBox.aspectWidth ? + Math.abs(bBox.aspectWidth - bBox.width) / 2 : + 0); + } + if (!pattern.height) { + pattern._y = pattern.y || 0; + pattern._y += bBox.y - Math.round(bBox.aspectHeight ? + Math.abs(bBox.aspectHeight - bBox.height) / 2 : + 0); + } + }; + /* eslint-disable no-invalid-this */ + /** + * Add a pattern to the renderer. + * + * @private + * @function Highcharts.SVGRenderer#addPattern + * + * @param {Highcharts.PatternObject} options + * The pattern options. + * + * @param {boolean|Highcharts.AnimationOptionsObject} [animation] + * The animation options. + * + * @return {Highcharts.SVGElement|undefined} + * The added pattern. Undefined if the pattern already exists. + * + * @requires modules/pattern-fill + */ + H.SVGRenderer.prototype.addPattern = function (options, animation) { + var pattern, animate = pick(animation, true), animationOptions = animObject(animate), path, defaultSize = 32, width = options.width || options._width || defaultSize, height = (options.height || options._height || defaultSize), color = options.color || '#343434', id = options.id, ren = this, rect = function (fill) { + ren.rect(0, 0, width, height) + .attr({ fill: fill }) + .add(pattern); + }, attribs; + if (!id) { + this.idCounter = this.idCounter || 0; + id = 'highcharts-pattern-' + this.idCounter + '-' + (this.chartIndex || 0); + ++this.idCounter; + } + // Do nothing if ID already exists + this.defIds = this.defIds || []; + if (this.defIds.indexOf(id) > -1) { + return; + } + // Store ID in list to avoid duplicates + this.defIds.push(id); + // Calculate pattern element attributes + var attrs = { + id: id, + patternUnits: 'userSpaceOnUse', + patternContentUnits: options.patternContentUnits || 'userSpaceOnUse', + width: width, + height: height, + x: options._x || options.x || 0, + y: options._y || options.y || 0 + }; + if (options.patternTransform) { + attrs.patternTransform = options.patternTransform; + } + pattern = this.createElement('pattern').attr(attrs).add(this.defs); + // Set id on the SVGRenderer object + pattern.id = id; + // Use an SVG path for the pattern + if (options.path) { + path = options.path; + // The background + if (options.backgroundColor) { + rect(options.backgroundColor); + } + // The pattern + attribs = { + 'd': path.d || path + }; + if (!this.styledMode) { + attribs.stroke = path.stroke || color; + attribs['stroke-width'] = pick(path.strokeWidth, 2); + attribs.fill = path.fill || 'none'; + } + if (path.transform) { + attribs.transform = path.transform; + } + this.createElement('path').attr(attribs).add(pattern); + pattern.color = color; + // Image pattern + } + else if (options.image) { + if (animate) { + this.image(options.image, 0, 0, width, height, function () { + // Onload + this.animate({ + opacity: pick(options.opacity, 1) + }, animationOptions); + removeEvent(this.element, 'load'); + }).attr({ opacity: 0 }).add(pattern); + } + else { + this.image(options.image, 0, 0, width, height).add(pattern); + } + } + // For non-animated patterns, set opacity now + if (!(options.image && animate) && typeof options.opacity !== 'undefined') { + [].forEach.call(pattern.element.childNodes, function (child) { + child.setAttribute('opacity', options.opacity); + }); + } + // Store for future reference + this.patternElements = this.patternElements || {}; + this.patternElements[id] = pattern; + return pattern; + }; + // Make sure we have a series color + wrap(H.Series.prototype, 'getColor', function (proceed) { + var oldColor = this.options.color; + // Temporarely remove color options to get defaults + if (oldColor && + oldColor.pattern && + !oldColor.pattern.color) { + delete this.options.color; + // Get default + proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + // Replace with old, but add default color + oldColor.pattern.color = + this.color; + this.color = this.options.color = oldColor; + } + else { + // We have a color, no need to do anything special + proceed.apply(this, Array.prototype.slice.call(arguments, 1)); + } + }); + // Calculate pattern dimensions on points that have their own pattern. + addEvent(H.Series, 'render', function () { + var isResizing = this.chart.isResizing; + if (this.isDirtyData || isResizing || !this.chart.hasRendered) { + (this.points || []).forEach(function (point) { + var colorOptions = point.options && point.options.color; + if (colorOptions && + colorOptions.pattern) { + // For most points we want to recalculate the dimensions on + // render, where we have the shape args and bbox. But if we + // are resizing and don't have the shape args, defer it, since + // the bounding box is still not resized. + if (isResizing && + !(point.shapeArgs && + point.shapeArgs.width && + point.shapeArgs.height)) { + colorOptions.pattern._width = + 'defer'; + colorOptions.pattern._height = + 'defer'; + } + else { + point.calculatePatternDimensions(colorOptions.pattern); + } + } + }); + } + }); + // Merge series color options to points + addEvent(Point, 'afterInit', function () { + var point = this, colorOptions = point.options.color; + // Only do this if we have defined a specific color on this point. Otherwise + // we will end up trying to re-add the series color for each point. + if (colorOptions && colorOptions.pattern) { + // Move path definition to object, allows for merge with series path + // definition + if (typeof colorOptions.pattern.path === 'string') { + colorOptions.pattern.path = { + d: colorOptions.pattern.path + }; + } + // Merge with series options + point.color = point.options.color = merge(point.series.options.color, colorOptions); + } + }); + // Add functionality to SVG renderer to handle patterns as complex colors + addEvent(H.SVGRenderer, 'complexColor', function (args) { + var color = args.args[0], prop = args.args[1], element = args.args[2], chartIndex = (this.chartIndex || 0); + var pattern = color.pattern, value = '#343434'; + // Handle patternIndex + if (typeof color.patternIndex !== 'undefined' && H.patterns) { + pattern = H.patterns[color.patternIndex]; + } + // Skip and call default if there is no pattern + if (!pattern) { + return true; + } + // We have a pattern. + if (pattern.image || + typeof pattern.path === 'string' || + pattern.path && pattern.path.d) { + // Real pattern. Add it and set the color value to be a reference. + // Force Hash-based IDs for legend items, as they are drawn before + // point render, meaning they are drawn before autocalculated image + // width/heights. We don't want them to highjack the width/height for + // this ID if it is defined by users. + var forceHashId = element.parentNode && + element.parentNode.getAttribute('class'); + forceHashId = forceHashId && + forceHashId.indexOf('highcharts-legend') > -1; + // If we don't have a width/height yet, handle it. Try faking a point + // and running the algorithm again. + if (pattern._width === 'defer' || pattern._height === 'defer') { + Point.prototype.calculatePatternDimensions.call({ graphic: { element: element } }, pattern); + } + // If we don't have an explicit ID, compute a hash from the + // definition and use that as the ID. This ensures that points with + // the same pattern definition reuse existing pattern elements by + // default. We combine two hashes, the second with an additional + // preSeed algorithm, to minimize collision probability. + if (forceHashId || !pattern.id) { + // Make a copy so we don't accidentally edit options when setting ID + pattern = merge({}, pattern); + pattern.id = 'highcharts-pattern-' + chartIndex + '-' + + hashFromObject(pattern) + hashFromObject(pattern, true); + } + // Add it. This function does nothing if an element with this ID + // already exists. + this.addPattern(pattern, !this.forExport && pick(pattern.animation, this.globalAnimation, { duration: 100 })); + value = "url(" + this.url + "#" + pattern.id + ")"; + } + else { + // Not a full pattern definition, just add color + value = pattern.color || value; + } + // Set the fill/stroke prop on the element + element.setAttribute(prop, value); + // Allow the color to be concatenated into tooltips formatters etc. + color.toString = function () { + return value; + }; + // Skip default handler + return false; + }); + // When animation is used, we have to recalculate pattern dimensions after + // resize, as the bounding boxes are not available until then. + addEvent(H.Chart, 'endResize', function () { + if ((this.renderer && this.renderer.defIds || []).filter(function (id) { + return (id && + id.indexOf && + id.indexOf('highcharts-pattern-') === 0); + }).length) { + // We have non-default patterns to fix. Find them by looping through + // all points. + this.series.forEach(function (series) { + series.points.forEach(function (point) { + var colorOptions = point.options && point.options.color; + if (colorOptions && + colorOptions.pattern) { + colorOptions.pattern._width = + 'defer'; + colorOptions.pattern._height = + 'defer'; + } + }); + }); + // Redraw without animation + this.redraw(false); + } + }); + // Add a garbage collector to delete old patterns with autogenerated hashes that + // are no longer being referenced. + addEvent(H.Chart, 'redraw', function () { + var usedIds = {}, renderer = this.renderer, + // Get the autocomputed patterns - these are the ones we might delete + patterns = (renderer.defIds || []).filter(function (pattern) { + return (pattern.indexOf && + pattern.indexOf('highcharts-pattern-') === 0); + }); + if (patterns.length) { + // Look through the DOM for usage of the patterns. This can be points, + // series, tooltips etc. + [].forEach.call(this.renderTo.querySelectorAll('[color^="url("], [fill^="url("], [stroke^="url("]'), function (node) { + var id = node.getAttribute('fill') || + node.getAttribute('color') || + node.getAttribute('stroke'); + if (id) { + var sanitizedId = id.replace(renderer.url, '').replace('url(#', '').replace(')', ''); + usedIds[sanitizedId] = true; + } + }); + // Loop through the patterns that exist and see if they are used + patterns.forEach(function (id) { + if (!usedIds[id]) { + // Remove id from used id list + erase(renderer.defIds, id); + // Remove pattern element + if (renderer.patternElements[id]) { + renderer.patternElements[id].destroy(); + delete renderer.patternElements[id]; + } + } + }); + } + }); + + }); + _registerModule(_modules, 'masters/modules/pattern-fill.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/price-indicator.js b/librerias/gantt/code/modules/price-indicator.js new file mode 100644 index 0000000..5bd521a --- /dev/null +++ b/librerias/gantt/code/modules/price-indicator.js @@ -0,0 +1,15 @@ +/* + Highstock JS v8.1.0 (2020-05-05) + + Advanced Highstock tools + + (c) 2010-2019 Highsoft AS + Author: Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/price-indicator",["highcharts","highcharts/modules/stock"],function(c){a(c);a.Highcharts=c;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function c(a,d,c,f){a.hasOwnProperty(d)||(a[d]=f.apply(null,c))}a=a?a._modules:{};c(a,"modules/price-indicator.src.js",[a["parts/Globals.js"],a["parts/Utilities.js"]],function(a, +c){var d=c.addEvent,f=c.isArray,m=c.merge;d(a.Series,"afterRender",function(){var a=this.options,c=a.pointRange,d=a.lastVisiblePrice,e=a.lastPrice;if((d||e)&&"highcharts-navigator-series"!==a.id){var n=this.xAxis,b=this.yAxis,p=b.crosshair,q=b.cross,r=b.crossLabel,g=this.points,h=g.length,k=this.xData[this.xData.length-1],l=this.yData[this.yData.length-1];e&&e.enabled&&(b.crosshair=b.options.crosshair=a.lastPrice,b.cross=this.lastPrice,e=f(l)?l[3]:l,b.drawCrosshair(null,{x:k,y:e,plotX:n.toPixels(k, +!0),plotY:b.toPixels(e,!0)}),this.yAxis.cross&&(this.lastPrice=this.yAxis.cross,this.lastPrice.y=e));d&&d.enabled&&0 0) { + crop = (points[pLength - 1].x === x) || pointRange === null ? 1 : 2; + yAxis.crosshair = yAxis.options.crosshair = merge({ + color: 'transparent' + }, seriesOptions.lastVisiblePrice); + yAxis.cross = serie.lastVisiblePrice; + lastPoint = points[pLength - crop]; + if (serie.crossLabel) { + serie.crossLabel.destroy(); + // Set to undefined to avoid collision with + // the yAxis crosshair #11480 + delete yAxis.crossLabel; + } + // Save price + yAxis.drawCrosshair(null, lastPoint); + if (yAxis.cross) { + serie.lastVisiblePrice = yAxis.cross; + serie.lastVisiblePrice.y = lastPoint.y; + } + serie.crossLabel = yAxis.crossLabel; + } + // Restore crosshair: + yAxis.crosshair = origOptions; + yAxis.cross = origGraphic; + yAxis.crossLabel = origLabel; + } + }); + + }); + _registerModule(_modules, 'masters/modules/price-indicator.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/pyramid3d.js b/librerias/gantt/code/modules/pyramid3d.js new file mode 100644 index 0000000..57cd635 --- /dev/null +++ b/librerias/gantt/code/modules/pyramid3d.js @@ -0,0 +1,12 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Highcharts 3D funnel module + + (c) 2010-2019 Kacper Madej + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/pyramid3d",["highcharts","highcharts/highcharts-3d","highcharts/modules/cylinder","highcharts/modules/funnel3d"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,b,c,d){a.hasOwnProperty(b)||(a[b]=d.apply(null,c))}a=a?a._modules:{};b(a,"modules/pyramid3d.src.js",[a["parts/Utilities.js"]], +function(a){a=a.seriesType;a("pyramid3d","funnel3d",{reversed:!0,neckHeight:0,neckWidth:0,dataLabels:{verticalAlign:"top"}});""});b(a,"masters/modules/pyramid3d.src.js",[],function(){})}); +//# sourceMappingURL=pyramid3d.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/pyramid3d.js.map b/librerias/gantt/code/modules/pyramid3d.js.map new file mode 100644 index 0000000..4856d14 --- /dev/null +++ b/librerias/gantt/code/modules/pyramid3d.js.map @@ -0,0 +1 @@ +{"version":3,"file":"pyramid3d.js.map","lineCount":11,"mappings":"A;;;;;;;;;AAUC,SAAS,CAACA,CAAD,CAAU,CACM,QAAtB,GAAI,MAAOC,OAAX,EAAkCA,MAAAC,QAAlC,EACIF,CAAA,CAAQ,SAAR,CACA,CADqBA,CACrB,CAAAC,MAAAC,QAAA,CAAiBF,CAFrB,EAG6B,UAAtB,GAAI,MAAOG,OAAX,EAAoCA,MAAAC,IAApC,CACHD,MAAA,CAAO,8BAAP,CAAuC,CAAC,YAAD,CAAe,0BAAf,CAA2C,6BAA3C,CAA0E,6BAA1E,CAAvC,CAAiJ,QAAS,CAACE,CAAD,CAAa,CACnKL,CAAA,CAAQK,CAAR,CACAL,EAAAK,WAAA,CAAqBA,CACrB,OAAOL,EAH4J,CAAvK,CADG,CAOHA,CAAA,CAA8B,WAAtB,GAAA,MAAOK,WAAP,CAAoCA,UAApC,CAAiDC,IAAAA,EAAzD,CAXY,CAAnB,CAAA,CAaC,QAAS,CAACD,CAAD,CAAa,CAEpBE,QAASA,EAAe,CAACC,CAAD,CAAMC,CAAN,CAAYC,CAAZ,CAAkBC,CAAlB,CAAsB,CACrCH,CAAAI,eAAA,CAAmBH,CAAnB,CAAL,GACID,CAAA,CAAIC,CAAJ,CADJ,CACgBE,CAAAE,MAAA,CAAS,IAAT,CAAeH,CAAf,CADhB,CAD0C,CAD1CI,CAAAA,CAAWT,CAAA,CAAaA,CAAAS,SAAb,CAAmC,EAMlDP,EAAA,CAAgBO,CAAhB,CAA0B,0BAA1B,CAAsD,CAACA,CAAA,CAAS,oBAAT,CAAD,CAAtD;AAAwF,QAAS,CAACC,CAAD,CAAI,CAa7FC,CAAAA,CAAaD,CAAAC,WAWjBA,EAAA,CAAW,WAAX,CAAwB,UAAxB,CAmBA,CAOIC,SAAU,CAAA,CAPd,CAQIC,WAAY,CARhB,CASIC,UAAW,CATf,CAUIC,WAAY,CACRC,cAAe,KADP,CAVhB,CAnBA,CA6FA,GArHiG,CAArG,CAwHAd,EAAA,CAAgBO,CAAhB,CAA0B,kCAA1B,CAA8D,EAA9D,CAAkE,QAAS,EAAG,EAA9E,CA/HoB,CAbvB;","sources":["pyramid3d.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","U","seriesType","reversed","neckHeight","neckWidth","dataLabels","verticalAlign"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/pyramid3d.src.js b/librerias/gantt/code/modules/pyramid3d.src.js new file mode 100644 index 0000000..c9161ad --- /dev/null +++ b/librerias/gantt/code/modules/pyramid3d.src.js @@ -0,0 +1,155 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * Highcharts 3D funnel module + * + * (c) 2010-2019 Kacper Madej + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/pyramid3d', ['highcharts', 'highcharts/highcharts-3d', 'highcharts/modules/cylinder', 'highcharts/modules/funnel3d'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'modules/pyramid3d.src.js', [_modules['parts/Utilities.js']], function (U) { + /* * + * + * Highcharts pyramid3d series module + * + * (c) 2010-2020 Highsoft AS + * Author: Kacper Madej + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var seriesType = U.seriesType; + /** + * The pyramid3d series type. + * + * @constructor seriesTypes.pyramid3d + * @augments seriesTypes.funnel3d + * @requires highcharts-3d + * @requires modules/cylinder + * @requires modules/funnel3d + * @requires modules/pyramid3d + */ + seriesType('pyramid3d', 'funnel3d', + /** + * A pyramid3d is a 3d version of pyramid series type. Pyramid charts are + * a type of chart often used to visualize stages in a sales project, + * where the top are the initial stages with the most clients. + * + * @sample highcharts/demo/pyramid3d/ + * Pyramid3d + * + * @extends plotOptions.funnel3d + * @excluding neckHeight, neckWidth, dataSorting + * @product highcharts + * @since 7.1.0 + * @requires highcharts-3d + * @requires modules/cylinder + * @requires modules/funnel3d + * @requires modules/pyramid3d + * @optionparent plotOptions.pyramid3d + */ + { + /** + * A reversed pyramid3d is funnel3d, but the latter supports neck + * related options: neckHeight and neckWidth + * + * @product highcharts + */ + reversed: true, + neckHeight: 0, + neckWidth: 0, + dataLabels: { + verticalAlign: 'top' + } + }); + /** + * A `pyramid3d` series. If the [type](#series.pyramid3d.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @since 7.1.0 + * @extends series,plotOptions.pyramid3d + * @excluding allAreas,boostThreshold,colorAxis,compare,compareBase,dataSorting + * @product highcharts + * @sample {highcharts} highcharts/demo/pyramid3d/ Pyramid3d + * @requires modules/pyramid3d + * @apioption series.pyramid3d + */ + /** + * An array of data points for the series. For the `pyramid3d` series + * type, points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values + * will be interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from `pointStart` + * and `pointInterval` given in the series options. If the axis has + * categories, these will be used. Example: + * + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of data + * points exceeds the series' + * [turboThreshold](#series.pyramid3d.turboThreshold), + * this option is not available. + * + * ```js + * data: [{ + * y: 2, + * name: "Point2", + * color: "#00FF00" + * }, { + * y: 4, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|*>} + * @extends series.funnel3d.data + * @product highcharts + * @apioption series.pyramid3d.data + */ + ''; // adds doclets above to the transpiled file + + }); + _registerModule(_modules, 'masters/modules/pyramid3d.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/sankey.js b/librerias/gantt/code/modules/sankey.js new file mode 100644 index 0000000..9e4d53c --- /dev/null +++ b/librerias/gantt/code/modules/sankey.js @@ -0,0 +1,35 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Sankey diagram module + + (c) 2010-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/sankey",["highcharts"],function(n){b(n);b.Highcharts=n;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function n(b,h,k,l){b.hasOwnProperty(h)||(b[h]=l.apply(null,k))}b=b?b._modules:{};n(b,"mixins/nodes.js",[b["parts/Globals.js"],b["parts/Point.js"],b["parts/Utilities.js"]],function(b,h,k){var l=k.defined,u=k.extend, +q=k.find,n=k.pick;b.NodesMixin={createNode:function(b){function d(a,d){return q(a,function(c){return c.id===d})}var a=d(this.nodes,b),x=this.pointClass;if(!a){var h=this.options.nodes&&d(this.options.nodes,b);a=(new x).init(this,u({className:"highcharts-node",isNode:!0,id:b,y:1},h));a.linksTo=[];a.linksFrom=[];a.formatPrefix="node";a.name=a.name||a.options.id;a.mass=n(a.options.mass,a.options.marker&&a.options.marker.radius,this.options.marker&&this.options.marker.radius,4);a.getSum=function(){var d= +0,b=0;a.linksTo.forEach(function(c){d+=c.weight});a.linksFrom.forEach(function(c){b+=c.weight});return Math.max(d,b)};a.offset=function(d,b){for(var c=0,e=0;e{series.name}
    ',pointFormat:"{point.fromNode.name} \u2192 {point.toNode.name}: {point.weight}
    ",nodeFormat:"{point.name}: {point.sum}
    "}},{isCartesian:!1,invertable:!0,forceDL:!0,orderNodes:!0,pointArrayMap:["from", +"to"],createNode:b.NodesMixin.createNode,searchPoint:b.noop,setData:b.NodesMixin.setData,destroy:b.NodesMixin.destroy,getNodePadding:function(){var a=this.options.nodePadding||0;if(this.nodeColumns){var e=this.nodeColumns.reduce(function(a,c){return Math.max(a,c.length)},0);e*a>this.chart.plotSizeY&&(a=this.chart.plotSizeY/e)}return a},createNodeColumn:function(){var a=this,e=this.chart,b=[];b.sum=function(){return this.reduce(function(a,c){return a+c.getSum()},0)};b.offset=function(c,e){for(var d= +0,f,m=a.nodePadding,g=0;gb){var f=d.fromNode;b=f.column}}c.column=b+1;f&&"hanging"===f.options.layout&&(c.hangsFrom=f,e=-1,u(f.linksFrom,function(a,b){(a=a.toNode===c)&&(e=b);return a}),c.column+=e)}a[c.column]||(a[c.column]=this.createNodeColumn());a[c.column].push(c)},this);for(var b=0;bl+k;g.inverted&&(t=g.plotSizeY-t,b=(g.plotSizeY||0)-b,d=g.plotSizeX-d,k=-k,f=-f,q=l>d);a.shapeType="path";a.linkBase=[t,t+f,b,b+f];if(q&&"number"===typeof b)a.shapeArgs={d:[["M",l+k,t],["C",l+k+p,t,d-p,b,d,b],["L",d+(n?k:0),b+f/2],["L",d,b+f],["C",d-p,b+f,l+k+p, +t+f,l+k,t+f],["Z"]]};else if("number"===typeof b){p=d-20-f;n=d-20;q=d;var r=l+k,A=r+20,u=A+f,x=t,v=t+f,z=v+20,C=z+(g.plotHeight-t-f),y=C+20,E=y+f,F=b,D=F+f,G=D+20,H=y+.7*f,I=q-.7*f,J=r+.7*f;a.shapeArgs={d:[["M",r,x],["C",J,x,u,v-.7*f,u,z],["L",u,C],["C",u,H,J,E,r,E],["L",q,E],["C",I,E,p,H,p,C],["L",p,G],["C",p,D-.7*f,I,F,q,F],["L",q,D],["C",n,D,n,D,n,G],["L",n,C],["C",n,y,n,y,q,y],["L",r,y],["C",A,y,A,y,A,C],["L",A,z],["C",A,v,A,v,r,v],["Z"]]}}a.dlBox={x:l+(d-l+k)/2,y:t+(b-t)/2,height:f,width:0}; +a.tooltipPos=g.inverted?[g.plotSizeY-a.dlBox.y-f/2,g.plotSizeX-a.dlBox.x]:[a.dlBox.x,a.dlBox.y+f/2];a.y=a.plotY=1;a.color||(a.color=c.color)},translate:function(){var a=this,b=function(b){for(var c=b.slice(),e=a.options.minLinkWidth||0,f,k=0,l,p=h.plotSizeY-g.borderWidth-(b.length-1)*d.nodePadding;b.length;){k=p/b.sum();f=!1;for(l=b.length;l--;)b[l].getSum()*k 0 || tree.visible; + // Set the values + value = pick(optionsPoint.value, childrenTotal); + extend(tree, { + children: children, + childrenTotal: childrenTotal, + isLeaf: tree.visible && !childrenTotal, + val: value + }); + return tree; + }; + /** + * @private + */ + var getColor = function getColor(node, options) { + var index = options.index, mapOptionsToLevel = options.mapOptionsToLevel, parentColor = options.parentColor, parentColorIndex = options.parentColorIndex, series = options.series, colors = options.colors, siblings = options.siblings, points = series.points, getColorByPoint, chartOptionsChart = series.chart.options.chart, point, level, colorByPoint, colorIndexByPoint, color, colorIndex; + /** + * @private + */ + function variation(color) { + var colorVariation = level && level.colorVariation; + if (colorVariation) { + if (colorVariation.key === 'brightness') { + return Color.parse(color).brighten(colorVariation.to * (index / siblings)).get(); + } + } + return color; + } + if (node) { + point = points[node.i]; + level = mapOptionsToLevel[node.level] || {}; + getColorByPoint = point && level.colorByPoint; + if (getColorByPoint) { + colorIndexByPoint = point.index % (colors ? + colors.length : + chartOptionsChart.colorCount); + colorByPoint = colors && colors[colorIndexByPoint]; + } + // Select either point color, level color or inherited color. + if (!series.chart.styledMode) { + color = pick(point && point.options.color, level && level.color, colorByPoint, parentColor && variation(parentColor), series.color); + } + colorIndex = pick(point && point.options.colorIndex, level && level.colorIndex, colorIndexByPoint, parentColorIndex, options.colorIndex); + } + return { + color: color, + colorIndex: colorIndex + }; + }; + /** + * Creates a map from level number to its given options. + * + * @private + * @function getLevelOptions + * @param {object} params + * Object containing parameters. + * - `defaults` Object containing default options. The default options + * are merged with the userOptions to get the final options for a + * specific level. + * - `from` The lowest level number. + * - `levels` User options from series.levels. + * - `to` The highest level number. + * @return {Highcharts.Dictionary|null} + * Returns a map from level number to its given options. + */ + var getLevelOptions = function getLevelOptions(params) { + var result = null, defaults, converted, i, from, to, levels; + if (isObject(params)) { + result = {}; + from = isNumber(params.from) ? params.from : 1; + levels = params.levels; + converted = {}; + defaults = isObject(params.defaults) ? params.defaults : {}; + if (isArray(levels)) { + converted = levels.reduce(function (obj, item) { + var level, levelIsConstant, options; + if (isObject(item) && isNumber(item.level)) { + options = merge({}, item); + levelIsConstant = (isBoolean(options.levelIsConstant) ? + options.levelIsConstant : + defaults.levelIsConstant); + // Delete redundant properties. + delete options.levelIsConstant; + delete options.level; + // Calculate which level these options apply to. + level = item.level + (levelIsConstant ? 0 : from - 1); + if (isObject(obj[level])) { + extend(obj[level], options); + } + else { + obj[level] = options; + } + } + return obj; + }, {}); + } + to = isNumber(params.to) ? params.to : 1; + for (i = 0; i <= to; i++) { + result[i] = merge({}, defaults, isObject(converted[i]) ? converted[i] : {}); + } + } + return result; + }; + /** + * Update the rootId property on the series. Also makes sure that it is + * accessible to exporting. + * + * @private + * @function updateRootId + * + * @param {object} series + * The series to operate on. + * + * @return {string} + * Returns the resulting rootId after update. + */ + var updateRootId = function (series) { + var rootId, options; + if (isObject(series)) { + // Get the series options. + options = isObject(series.options) ? series.options : {}; + // Calculate the rootId. + rootId = pick(series.rootNode, options.rootId, ''); + // Set rootId on series.userOptions to pick it up in exporting. + if (isObject(series.userOptions)) { + series.userOptions.rootId = rootId; + } + // Set rootId on series to pick it up on next update. + series.rootNode = rootId; + } + return rootId; + }; + var result = { + getColor: getColor, + getLevelOptions: getLevelOptions, + setTreeValues: setTreeValues, + updateRootId: updateRootId + }; + + return result; + }); + _registerModule(_modules, 'modules/sankey.src.js', [_modules['parts/Globals.js'], _modules['parts/Color.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js'], _modules['mixins/tree-series.js']], function (H, Color, Point, U, mixinTreeSeries) { + /* * + * + * Sankey diagram module + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * A node in a sankey diagram. + * + * @interface Highcharts.SankeyNodeObject + * @extends Highcharts.Point + * @product highcharts + */ /** + * The color of the auto generated node. + * + * @name Highcharts.SankeyNodeObject#color + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + */ /** + * The color index of the auto generated node, especially for use in styled + * mode. + * + * @name Highcharts.SankeyNodeObject#colorIndex + * @type {number} + */ /** + * An optional column index of where to place the node. The default behaviour is + * to place it next to the preceding node. + * + * @see {@link https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/sankey-node-column/|Highcharts-Demo:} + * Specified node column + * + * @name Highcharts.SankeyNodeObject#column + * @type {number} + * @since 6.0.5 + */ /** + * The id of the auto-generated node, refering to the `from` or `to` setting of + * the link. + * + * @name Highcharts.SankeyNodeObject#id + * @type {string} + */ /** + * The name to display for the node in data labels and tooltips. Use this when + * the name is different from the `id`. Where the id must be unique for each + * node, this is not necessary for the name. + * + * @see {@link https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/css/sankey/|Highcharts-Demo:} + * Sankey diagram with node options + * + * @name Highcharts.SankeyNodeObject#name + * @type {string} + * @product highcharts + */ /** + * The vertical offset of a node in terms of weight. Positive values shift the + * node downwards, negative shift it upwards. + * + * @see {@link https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/sankey-node-column/|Highcharts-Demo:} + * Specified node offset + * + * @name Highcharts.SankeyNodeObject#offset + * @type {number} + * @default 0 + * @since 6.0.5 + */ + /** + * Formatter callback function. + * + * @callback Highcharts.SeriesSankeyDataLabelsFormatterCallbackFunction + * + * @param {Highcharts.SeriesSankeyDataLabelsFormatterContextObject|Highcharts.PointLabelObject} this + * Data label context to format + * + * @return {string|undefined} + * Formatted data label text + */ + /** + * Context for the node formatter function. + * + * @interface Highcharts.SeriesSankeyDataLabelsFormatterContextObject + * @extends Highcharts.PointLabelObject + */ /** + * The node object. The node name, if defined, is available through + * `this.point.name`. + * @name Highcharts.SeriesSankeyDataLabelsFormatterContextObject#point + * @type {Highcharts.SankeyNodeObject} + */ + var defined = U.defined, find = U.find, isObject = U.isObject, merge = U.merge, pick = U.pick, relativeLength = U.relativeLength, seriesType = U.seriesType, stableSort = U.stableSort; + var getLevelOptions = mixinTreeSeries.getLevelOptions; + // eslint-disable-next-line valid-jsdoc + /** + * @private + */ + var getDLOptions = function getDLOptions(params) { + var optionsPoint = (isObject(params.optionsPoint) ? + params.optionsPoint.dataLabels : + {}), optionsLevel = (isObject(params.level) ? + params.level.dataLabels : + {}), options = merge({ + style: {} + }, optionsLevel, optionsPoint); + return options; + }; + /** + * @private + * @class + * @name Highcharts.seriesTypes.sankey + * + * @augments Highcharts.Series + */ + seriesType('sankey', 'column', + /** + * A sankey diagram is a type of flow diagram, in which the width of the + * link between two nodes is shown proportionally to the flow quantity. + * + * @sample highcharts/demo/sankey-diagram/ + * Sankey diagram + * @sample highcharts/plotoptions/sankey-inverted/ + * Inverted sankey diagram + * @sample highcharts/plotoptions/sankey-outgoing + * Sankey diagram with outgoing links + * + * @extends plotOptions.column + * @since 6.0.0 + * @product highcharts + * @excluding animationLimit, boostThreshold, borderRadius, + * crisp, cropThreshold, colorAxis, colorKey, depth, dragDrop, + * edgeColor, edgeWidth, findNearestPointBy, grouping, + * groupPadding, groupZPadding, maxPointWidth, negativeColor, + * pointInterval, pointIntervalUnit, pointPadding, + * pointPlacement, pointRange, pointStart, pointWidth, + * shadow, softThreshold, stacking, threshold, zoneAxis, + * zones, minPointLength, dataSorting + * @requires modules/sankey + * @optionparent plotOptions.sankey + */ + { + borderWidth: 0, + colorByPoint: true, + /** + * Higher numbers makes the links in a sankey diagram or dependency + * wheelrender more curved. A `curveFactor` of 0 makes the lines + * straight. + * + * @private + */ + curveFactor: 0.33, + /** + * Options for the data labels appearing on top of the nodes and links. + * For sankey charts, data labels are visible for the nodes by default, + * but hidden for links. This is controlled by modifying the + * `nodeFormat`, and the `format` that applies to links and is an empty + * string by default. + * + * @declare Highcharts.SeriesSankeyDataLabelsOptionsObject + * + * @private + */ + dataLabels: { + enabled: true, + backgroundColor: 'none', + crop: false, + /** + * The + * [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) + * specifying what to show for _nodes_ in the sankey diagram. By + * default the `nodeFormatter` returns `{point.name}`. + * + * @sample highcharts/plotoptions/sankey-link-datalabels/ + * Node and link data labels + * + * @type {string} + */ + nodeFormat: void 0, + // eslint-disable-next-line valid-jsdoc + /** + * Callback to format data labels for _nodes_ in the sankey diagram. + * The `nodeFormat` option takes precedence over the + * `nodeFormatter`. + * + * @type {Highcharts.SeriesSankeyDataLabelsFormatterCallbackFunction} + * @since 6.0.2 + */ + nodeFormatter: function () { + return this.point.name; + }, + format: void 0, + // eslint-disable-next-line valid-jsdoc + /** + * @type {Highcharts.SeriesSankeyDataLabelsFormatterCallbackFunction} + */ + formatter: function () { + return; + }, + inside: true + }, + /** + * @ignore-option + * + * @private + */ + inactiveOtherPoints: true, + /** + * Set options on specific levels. Takes precedence over series options, + * but not node and link options. + * + * @sample highcharts/demo/sunburst + * Sunburst chart + * + * @type {Array<*>} + * @since 7.1.0 + * @apioption plotOptions.sankey.levels + */ + /** + * Can set `borderColor` on all nodes which lay on the same level. + * + * @type {Highcharts.ColorString} + * @apioption plotOptions.sankey.levels.borderColor + */ + /** + * Can set `borderWidth` on all nodes which lay on the same level. + * + * @type {number} + * @apioption plotOptions.sankey.levels.borderWidth + */ + /** + * Can set `color` on all nodes which lay on the same level. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.sankey.levels.color + */ + /** + * Can set `colorByPoint` on all nodes which lay on the same level. + * + * @type {boolean} + * @default true + * @apioption plotOptions.sankey.levels.colorByPoint + */ + /** + * Can set `dataLabels` on all points which lay on the same level. + * + * @extends plotOptions.sankey.dataLabels + * @apioption plotOptions.sankey.levels.dataLabels + */ + /** + * Decides which level takes effect from the options set in the levels + * object. + * + * @type {number} + * @apioption plotOptions.sankey.levels.level + */ + /** + * Can set `linkOpacity` on all points which lay on the same level. + * + * @type {number} + * @default 0.5 + * @apioption plotOptions.sankey.levels.linkOpacity + */ + /** + * Can set `states` on all nodes and points which lay on the same level. + * + * @extends plotOptions.sankey.states + * @apioption plotOptions.sankey.levels.states + */ + /** + * Opacity for the links between nodes in the sankey diagram. + * + * @private + */ + linkOpacity: 0.5, + /** + * The minimal width for a line of a sankey. By default, + * 0 values are not shown. + * + * @sample highcharts/plotoptions/sankey-minlinkwidth + * Sankey diagram with minimal link height + * + * @type {number} + * @since 7.1.3 + * @default 0 + * @apioption plotOptions.sankey.minLinkWidth + * + * @private + */ + minLinkWidth: 0, + /** + * The pixel width of each node in a sankey diagram or dependency wheel, + * or the height in case the chart is inverted. + * + * @private + */ + nodeWidth: 20, + /** + * The padding between nodes in a sankey diagram or dependency wheel, in + * pixels. + * + * If the number of nodes is so great that it is possible to lay them + * out within the plot area with the given `nodePadding`, they will be + * rendered with a smaller padding as a strategy to avoid overflow. + * + * @private + */ + nodePadding: 10, + showInLegend: false, + states: { + hover: { + /** + * Opacity for the links between nodes in the sankey diagram in + * hover mode. + */ + linkOpacity: 1 + }, + /** + * The opposite state of a hover for a single point node/link. + * + * @declare Highcharts.SeriesStatesInactiveOptionsObject + */ + inactive: { + /** + * Opacity for the links between nodes in the sankey diagram in + * inactive mode. + */ + linkOpacity: 0.1, + /** + * Opacity of inactive markers. + * + * @type {number} + * @apioption plotOptions.series.states.inactive.opacity + */ + opacity: 0.1, + /** + * Animation when not hovering over the marker. + * + * @type {boolean|Highcharts.AnimationOptionsObject} + * @apioption plotOptions.series.states.inactive.animation + */ + animation: { + /** @internal */ + duration: 50 + } + } + }, + tooltip: { + /** + * A callback for defining the format for _nodes_ in the chart's + * tooltip, as opposed to links. + * + * @type {Highcharts.FormatterCallbackFunction} + * @since 6.0.2 + * @apioption plotOptions.sankey.tooltip.nodeFormatter + */ + /** + * Whether the tooltip should follow the pointer or stay fixed on + * the item. + */ + followPointer: true, + headerFormat: '{series.name}
    ', + pointFormat: '{point.fromNode.name} \u2192 {point.toNode.name}: {point.weight}
    ', + /** + * The + * [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) + * specifying what to show for _nodes_ in tooltip of a diagram + * series, as opposed to links. + */ + nodeFormat: '{point.name}: {point.sum}
    ' + } + }, { + isCartesian: false, + invertable: true, + forceDL: true, + orderNodes: true, + pointArrayMap: ['from', 'to'], + // Create a single node that holds information on incoming and outgoing + // links. + createNode: H.NodesMixin.createNode, + searchPoint: H.noop, + setData: H.NodesMixin.setData, + destroy: H.NodesMixin.destroy, + /* eslint-disable valid-jsdoc */ + /** + * Overridable function to get node padding, overridden in dependency + * wheel series type. + * @private + */ + getNodePadding: function () { + var nodePadding = this.options.nodePadding || 0; + // If the number of columns is so great that they will overflow with + // the given nodePadding, we sacrifice the padding in order to + // render all nodes within the plot area (#11917). + if (this.nodeColumns) { + var maxLength = this.nodeColumns.reduce(function (acc, col) { return Math.max(acc, col.length); }, 0); + if (maxLength * nodePadding > this.chart.plotSizeY) { + nodePadding = this.chart.plotSizeY / maxLength; + } + } + return nodePadding; + }, + /** + * Create a node column. + * @private + */ + createNodeColumn: function () { + var series = this, chart = this.chart, column = []; + column.sum = function () { + return this.reduce(function (sum, node) { + return sum + node.getSum(); + }, 0); + }; + // Get the offset in pixels of a node inside the column. + column.offset = function (node, factor) { + var offset = 0, totalNodeOffset, nodePadding = series.nodePadding; + for (var i = 0; i < column.length; i++) { + var sum = column[i].getSum(); + var height = Math.max(sum * factor, series.options.minLinkWidth); + if (sum) { + totalNodeOffset = height + nodePadding; + } + else { + // If node sum equals 0 nodePadding is missed #12453 + totalNodeOffset = 0; + } + if (column[i] === node) { + return { + relativeTop: offset + relativeLength(node.options.offset || 0, totalNodeOffset) + }; + } + offset += totalNodeOffset; + } + }; + // Get the top position of the column in pixels. + column.top = function (factor) { + var nodePadding = series.nodePadding; + var height = this.reduce(function (height, node) { + if (height > 0) { + height += nodePadding; + } + var nodeHeight = Math.max(node.getSum() * factor, series.options.minLinkWidth); + height += nodeHeight; + return height; + }, 0); + return (chart.plotSizeY - height) / 2; + }; + return column; + }, + /** + * Create node columns by analyzing the nodes and the relations between + * incoming and outgoing links. + * @private + */ + createNodeColumns: function () { + var columns = []; + this.nodes.forEach(function (node) { + var fromColumn = -1, fromNode, i, point; + if (!defined(node.options.column)) { + // No links to this node, place it left + if (node.linksTo.length === 0) { + node.column = 0; + // There are incoming links, place it to the right of the + // highest order column that links to this one. + } + else { + for (i = 0; i < node.linksTo.length; i++) { + point = node.linksTo[0]; + if (point.fromNode.column > fromColumn) { + fromNode = point.fromNode; + fromColumn = fromNode.column; + } + } + node.column = fromColumn + 1; + // Hanging layout for organization chart + if (fromNode && + fromNode.options.layout === 'hanging') { + node.hangsFrom = fromNode; + i = -1; // Reuse existing variable i + find(fromNode.linksFrom, function (link, index) { + var found = link.toNode === node; + if (found) { + i = index; + } + return found; + }); + node.column += i; + } + } + } + if (!columns[node.column]) { + columns[node.column] = this.createNodeColumn(); + } + columns[node.column].push(node); + }, this); + // Fill in empty columns (#8865) + for (var i = 0; i < columns.length; i++) { + if (typeof columns[i] === 'undefined') { + columns[i] = this.createNodeColumn(); + } + } + return columns; + }, + /** + * Define hasData function for non-cartesian series. + * @private + * @return {boolean} + * Returns true if the series has points at all. + */ + hasData: function () { + return !!this.processedXData.length; // != 0 + }, + /** + * Return the presentational attributes. + * @private + */ + pointAttribs: function (point, state) { + var series = this, level = point.isNode ? point.level : point.fromNode.level, levelOptions = series.mapOptionsToLevel[level || 0] || {}, options = point.options, stateOptions = (levelOptions.states && levelOptions.states[state]) || {}, values = [ + 'colorByPoint', 'borderColor', 'borderWidth', 'linkOpacity' + ].reduce(function (obj, key) { + obj[key] = pick(stateOptions[key], options[key], levelOptions[key], series.options[key]); + return obj; + }, {}), color = pick(stateOptions.color, options.color, values.colorByPoint ? point.color : levelOptions.color); + // Node attributes + if (point.isNode) { + return { + fill: color, + stroke: values.borderColor, + 'stroke-width': values.borderWidth + }; + } + // Link attributes + return { + fill: Color.parse(color).setOpacity(values.linkOpacity).get() + }; + }, + /** + * Extend generatePoints by adding the nodes, which are Point objects + * but pushed to the this.nodes array. + * @private + */ + generatePoints: function () { + H.NodesMixin.generatePoints.apply(this, arguments); + /** + * Order the nodes, starting with the root node(s). (#9818) + * @private + */ + function order(node, level) { + // Prevents circular recursion: + if (typeof node.level === 'undefined') { + node.level = level; + node.linksFrom.forEach(function (link) { + if (link.toNode) { + order(link.toNode, level + 1); + } + }); + } + } + if (this.orderNodes) { + this.nodes + // Identify the root node(s) + .filter(function (node) { + return node.linksTo.length === 0; + }) + // Start by the root node(s) and recursively set the level + // on all following nodes. + .forEach(function (node) { + order(node, 0); + }); + stableSort(this.nodes, function (a, b) { + return a.level - b.level; + }); + } + }, + /** + * Run translation operations for one node. + * @private + */ + translateNode: function (node, column) { + var translationFactor = this.translationFactor, chart = this.chart, options = this.options, sum = node.getSum(), height = Math.max(Math.round(sum * translationFactor), this.options.minLinkWidth), crisp = Math.round(options.borderWidth) % 2 / 2, nodeOffset = column.offset(node, translationFactor), fromNodeTop = Math.floor(pick(nodeOffset.absoluteTop, (column.top(translationFactor) + + nodeOffset.relativeTop))) + crisp, left = Math.floor(this.colDistance * node.column + + options.borderWidth / 2) + crisp, nodeLeft = chart.inverted ? + chart.plotSizeX - left : + left, nodeWidth = Math.round(this.nodeWidth); + node.sum = sum; + // If node sum is 0, don't render the rect #12453 + if (sum) { + // Draw the node + node.shapeType = 'rect'; + node.nodeX = nodeLeft; + node.nodeY = fromNodeTop; + if (!chart.inverted) { + node.shapeArgs = { + x: nodeLeft, + y: fromNodeTop, + width: node.options.width || options.width || nodeWidth, + height: node.options.height || options.height || height + }; + } + else { + node.shapeArgs = { + x: nodeLeft - nodeWidth, + y: chart.plotSizeY - fromNodeTop - height, + width: node.options.height || options.height || nodeWidth, + height: node.options.width || options.width || height + }; + } + node.shapeArgs.display = node.hasShape() ? '' : 'none'; + // Calculate data label options for the point + node.dlOptions = getDLOptions({ + level: this.mapOptionsToLevel[node.level], + optionsPoint: node.options + }); + // Pass test in drawPoints + node.plotY = 1; + // Set the anchor position for tooltips + node.tooltipPos = chart.inverted ? [ + chart.plotSizeY - node.shapeArgs.y - node.shapeArgs.height / 2, + chart.plotSizeX - node.shapeArgs.x - node.shapeArgs.width / 2 + ] : [ + node.shapeArgs.x + node.shapeArgs.width / 2, + node.shapeArgs.y + node.shapeArgs.height / 2 + ]; + } + else { + node.dlOptions = { + enabled: false + }; + } + }, + /** + * Run translation operations for one link. + * @private + */ + translateLink: function (point) { + var getY = function (node, fromOrTo) { + var _a; + var linkTop = (node.offset(point, fromOrTo) * + translationFactor); + var y = Math.min(node.nodeY + linkTop, + // Prevent links from spilling below the node (#12014) + node.nodeY + ((_a = node.shapeArgs) === null || _a === void 0 ? void 0 : _a.height) - linkHeight); + return y; + }; + var fromNode = point.fromNode, toNode = point.toNode, chart = this.chart, translationFactor = this.translationFactor, linkHeight = Math.max(point.weight * translationFactor, this.options.minLinkWidth), options = this.options, curvy = ((chart.inverted ? -this.colDistance : this.colDistance) * + options.curveFactor), fromY = getY(fromNode, 'linksFrom'), toY = getY(toNode, 'linksTo'), nodeLeft = fromNode.nodeX, nodeW = this.nodeWidth, right = toNode.column * this.colDistance, outgoing = point.outgoing, straight = right > nodeLeft + nodeW; + if (chart.inverted) { + fromY = chart.plotSizeY - fromY; + toY = (chart.plotSizeY || 0) - toY; + right = chart.plotSizeX - right; + nodeW = -nodeW; + linkHeight = -linkHeight; + straight = nodeLeft > right; + } + point.shapeType = 'path'; + point.linkBase = [ + fromY, + fromY + linkHeight, + toY, + toY + linkHeight + ]; + // Links going from left to right + if (straight && typeof toY === 'number') { + point.shapeArgs = { + d: [ + ['M', nodeLeft + nodeW, fromY], + [ + 'C', + nodeLeft + nodeW + curvy, + fromY, + right - curvy, + toY, + right, + toY + ], + ['L', right + (outgoing ? nodeW : 0), toY + linkHeight / 2], + ['L', right, toY + linkHeight], + [ + 'C', + right - curvy, + toY + linkHeight, + nodeLeft + nodeW + curvy, + fromY + linkHeight, + nodeLeft + nodeW, fromY + linkHeight + ], + ['Z'] + ] + }; + // Experimental: Circular links pointing backwards. In + // v6.1.0 this breaks the rendering completely, so even + // this experimental rendering is an improvement. #8218. + // @todo + // - Make room for the link in the layout + // - Automatically determine if the link should go up or + // down. + } + else if (typeof toY === 'number') { + var bend = 20, vDist = chart.plotHeight - fromY - linkHeight, x1 = right - bend - linkHeight, x2 = right - bend, x3 = right, x4 = nodeLeft + nodeW, x5 = x4 + bend, x6 = x5 + linkHeight, fy1 = fromY, fy2 = fromY + linkHeight, fy3 = fy2 + bend, y4 = fy3 + vDist, y5 = y4 + bend, y6 = y5 + linkHeight, ty1 = toY, ty2 = ty1 + linkHeight, ty3 = ty2 + bend, cfy1 = fy2 - linkHeight * 0.7, cy2 = y5 + linkHeight * 0.7, cty1 = ty2 - linkHeight * 0.7, cx1 = x3 - linkHeight * 0.7, cx2 = x4 + linkHeight * 0.7; + point.shapeArgs = { + d: [ + ['M', x4, fy1], + ['C', cx2, fy1, x6, cfy1, x6, fy3], + ['L', x6, y4], + ['C', x6, cy2, cx2, y6, x4, y6], + ['L', x3, y6], + ['C', cx1, y6, x1, cy2, x1, y4], + ['L', x1, ty3], + ['C', x1, cty1, cx1, ty1, x3, ty1], + ['L', x3, ty2], + ['C', x2, ty2, x2, ty2, x2, ty3], + ['L', x2, y4], + ['C', x2, y5, x2, y5, x3, y5], + ['L', x4, y5], + ['C', x5, y5, x5, y5, x5, y4], + ['L', x5, fy3], + ['C', x5, fy2, x5, fy2, x4, fy2], + ['Z'] + ] + }; + } + // Place data labels in the middle + point.dlBox = { + x: nodeLeft + (right - nodeLeft + nodeW) / 2, + y: fromY + (toY - fromY) / 2, + height: linkHeight, + width: 0 + }; + // And set the tooltip anchor in the middle + point.tooltipPos = chart.inverted ? [ + chart.plotSizeY - point.dlBox.y - linkHeight / 2, + chart.plotSizeX - point.dlBox.x + ] : [ + point.dlBox.x, + point.dlBox.y + linkHeight / 2 + ]; + // Pass test in drawPoints + point.y = point.plotY = 1; + if (!point.color) { + point.color = fromNode.color; + } + }, + /** + * Run pre-translation by generating the nodeColumns. + * @private + */ + translate: function () { + var _this = this; + // Get the translation factor needed for each column to fill up the + // plot height + var getColumnTranslationFactor = function (column) { + var nodes = column.slice(); + var minLinkWidth = _this.options.minLinkWidth || 0; + var exceedsMinLinkWidth; + var factor = 0; + var i; + var remainingHeight = chart.plotSizeY - + options.borderWidth - (column.length - 1) * series.nodePadding; + // Because the minLinkWidth option doesn't obey the direct + // translation, we need to run translation iteratively, check + // node heights, remove those nodes affected by minLinkWidth, + // check again, etc. + while (column.length) { + factor = remainingHeight / column.sum(); + exceedsMinLinkWidth = false; + i = column.length; + while (i--) { + if (column[i].getSum() * factor < minLinkWidth) { + column.splice(i, 1); + remainingHeight -= minLinkWidth + series.nodePadding; + exceedsMinLinkWidth = true; + } + } + if (!exceedsMinLinkWidth) { + break; + } + } + // Re-insert original nodes + column.length = 0; + nodes.forEach(function (node) { return column.push(node); }); + return factor; + }; + if (!this.processedXData) { + this.processData(); + } + this.generatePoints(); + this.nodeColumns = this.createNodeColumns(); + this.nodeWidth = relativeLength(this.options.nodeWidth, this.chart.plotSizeX); + var series = this, chart = this.chart, options = this.options, nodeWidth = this.nodeWidth, nodeColumns = this.nodeColumns; + this.nodePadding = this.getNodePadding(); + // Find out how much space is needed. Base it on the translation + // factor of the most spaceous column. + this.translationFactor = nodeColumns.reduce(function (translationFactor, column) { return Math.min(translationFactor, getColumnTranslationFactor(column)); }, Infinity); + this.colDistance = + (chart.plotSizeX - nodeWidth - + options.borderWidth) / Math.max(1, nodeColumns.length - 1); + // Calculate level options used in sankey and organization + series.mapOptionsToLevel = getLevelOptions({ + // NOTE: if support for allowTraversingTree is added, then from + // should be the level of the root node. + from: 1, + levels: options.levels, + to: nodeColumns.length - 1, + defaults: { + borderColor: options.borderColor, + borderRadius: options.borderRadius, + borderWidth: options.borderWidth, + color: series.color, + colorByPoint: options.colorByPoint, + // NOTE: if support for allowTraversingTree is added, then + // levelIsConstant should be optional. + levelIsConstant: true, + linkColor: options.linkColor, + linkLineWidth: options.linkLineWidth, + linkOpacity: options.linkOpacity, + states: options.states + } + }); + // First translate all nodes so we can use them when drawing links + nodeColumns.forEach(function (column) { + column.forEach(function (node) { + series.translateNode(node, column); + }); + }, this); + // Then translate links + this.nodes.forEach(function (node) { + // Translate the links from this node + node.linksFrom.forEach(function (linkPoint) { + // If weight is 0 - don't render the link path #12453, + // render null points (for organization chart) + if ((linkPoint.weight || linkPoint.isNull) && linkPoint.to) { + series.translateLink(linkPoint); + linkPoint.allowShadow = false; + } + }); + }); + }, + /** + * Extend the render function to also render this.nodes together with + * the points. + * @private + */ + render: function () { + var points = this.points; + this.points = this.points.concat(this.nodes || []); + H.seriesTypes.column.prototype.render.call(this); + this.points = points; + }, + /* eslint-enable valid-jsdoc */ + animate: H.Series.prototype.animate + }, { + applyOptions: function (options, x) { + Point.prototype.applyOptions.call(this, options, x); + // Treat point.level as a synonym of point.column + if (defined(this.options.level)) { + this.options.column = this.column = this.options.level; + } + return this; + }, + setState: H.NodesMixin.setNodeState, + getClassName: function () { + return (this.isNode ? 'highcharts-node ' : 'highcharts-link ') + + Point.prototype.getClassName.call(this); + }, + isValid: function () { + return this.isNode || typeof this.weight === 'number'; + } + }); + /** + * A `sankey` series. If the [type](#series.sankey.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.sankey + * @excluding animationLimit, boostBlending, boostThreshold, borderColor, + * borderRadius, borderWidth, crisp, cropThreshold, dataParser, + * dataURL, depth, dragDrop, edgeColor, edgeWidth, + * findNearestPointBy, getExtremesFromAll, grouping, groupPadding, + * groupZPadding, label, maxPointWidth, negativeColor, pointInterval, + * pointIntervalUnit, pointPadding, pointPlacement, pointRange, + * pointStart, pointWidth, shadow, softThreshold, stacking, + * threshold, zoneAxis, zones, dataSorting + * @product highcharts + * @requires modules/sankey + * @apioption series.sankey + */ + /** + * A collection of options for the individual nodes. The nodes in a sankey + * diagram are auto-generated instances of `Highcharts.Point`, but options can + * be applied here and linked by the `id`. + * + * @sample highcharts/css/sankey/ + * Sankey diagram with node options + * + * @declare Highcharts.SeriesSankeyNodesOptionsObject + * @type {Array<*>} + * @product highcharts + * @apioption series.sankey.nodes + */ + /** + * The id of the auto-generated node, refering to the `from` or `to` setting of + * the link. + * + * @type {string} + * @product highcharts + * @apioption series.sankey.nodes.id + */ + /** + * The color of the auto generated node. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts + * @apioption series.sankey.nodes.color + */ + /** + * The color index of the auto generated node, especially for use in styled + * mode. + * + * @type {number} + * @product highcharts + * @apioption series.sankey.nodes.colorIndex + */ + /** + * An optional column index of where to place the node. The default behaviour is + * to place it next to the preceding node. Note that this option name is + * counter intuitive in inverted charts, like for example an organization chart + * rendered top down. In this case the "columns" are horizontal. + * + * @sample highcharts/plotoptions/sankey-node-column/ + * Specified node column + * + * @type {number} + * @since 6.0.5 + * @product highcharts + * @apioption series.sankey.nodes.column + */ + /** + * Individual data label for each node. The options are the same as + * the ones for [series.sankey.dataLabels](#series.sankey.dataLabels). + * + * @extends plotOptions.sankey.dataLabels + * @apioption series.sankey.nodes.dataLabels + */ + /** + * An optional level index of where to place the node. The default behaviour is + * to place it next to the preceding node. Alias of `nodes.column`, but in + * inverted sankeys and org charts, the levels are laid out as rows. + * + * @type {number} + * @since 7.1.0 + * @product highcharts + * @apioption series.sankey.nodes.level + */ + /** + * The name to display for the node in data labels and tooltips. Use this when + * the name is different from the `id`. Where the id must be unique for each + * node, this is not necessary for the name. + * + * @sample highcharts/css/sankey/ + * Sankey diagram with node options + * + * @type {string} + * @product highcharts + * @apioption series.sankey.nodes.name + */ + /** + * In a horizontal layout, the vertical offset of a node in terms of weight. + * Positive values shift the node downwards, negative shift it upwards. In a + * vertical layout, like organization chart, the offset is horizontal. + * + * If a percantage string is given, the node is offset by the percentage of the + * node size plus `nodePadding`. + * + * @sample highcharts/plotoptions/sankey-node-column/ + * Specified node offset + * + * @type {number|string} + * @default 0 + * @since 6.0.5 + * @product highcharts + * @apioption series.sankey.nodes.offset + */ + /** + * An array of data points for the series. For the `sankey` series type, + * points can be given in the following way: + * + * An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of data + * points exceeds the series' [turboThreshold](#series.area.turboThreshold), + * this option is not available. + * + * ```js + * data: [{ + * from: 'Category1', + * to: 'Category2', + * weight: 2 + * }, { + * from: 'Category1', + * to: 'Category3', + * weight: 5 + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @declare Highcharts.SeriesSankeyPointOptionsObject + * @type {Array<*>} + * @extends series.line.data + * @excluding dragDrop, drilldown, marker, x, y + * @product highcharts + * @apioption series.sankey.data + */ + /** + * The color for the individual _link_. By default, the link color is the same + * as the node it extends from. The `series.fillOpacity` option also applies to + * the points, so when setting a specific link color, consider setting the + * `fillOpacity` to 1. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts + * @apioption series.sankey.data.color + */ + /** + * @type {Highcharts.SeriesSankeyDataLabelsOptionsObject|Array} + * @product highcharts + * @apioption series.sankey.data.dataLabels + */ + /** + * The node that the link runs from. + * + * @type {string} + * @product highcharts + * @apioption series.sankey.data.from + */ + /** + * The node that the link runs to. + * + * @type {string} + * @product highcharts + * @apioption series.sankey.data.to + */ + /** + * Whether the link goes out of the system. + * + * @sample highcharts/plotoptions/sankey-outgoing + * Sankey chart with outgoing links + * + * @type {boolean} + * @default false + * @product highcharts + * @apioption series.sankey.data.outgoing + */ + /** + * The weight of the link. + * + * @type {number|null} + * @product highcharts + * @apioption series.sankey.data.weight + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'masters/modules/sankey.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/sonification.js b/librerias/gantt/code/modules/sonification.js new file mode 100644 index 0000000..7b3cc06 --- /dev/null +++ b/librerias/gantt/code/modules/sonification.js @@ -0,0 +1,58 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Sonification module + + (c) 2012-2019 ystein Moseng + + License: www.highcharts.com/license +*/ +(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/sonification",["highcharts"],function(n){b(n);b.Highcharts=n;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function n(e,b,d,p){e.hasOwnProperty(b)||(e[b]=p.apply(null,d))}b=b?b._modules:{};n(b,"modules/sonification/Instrument.js",[b["parts/Globals.js"],b["parts/Utilities.js"]],function(e,b){function d(c){this.init(c)} +var p=b.error,m=b.merge,g=b.pick,q=b.uniqueKey,k={type:"oscillator",playCallbackInterval:20,oscillator:{waveformShape:"sine"}};d.prototype.init=function(c){this.initAudioContext()?(this.options=m(k,c),this.id=this.options.id=c&&c.id||q(),c=e.audioContext,this.gainNode=c.createGain(),this.setGain(0),(this.panNode=c.createStereoPanner&&c.createStereoPanner())?(this.setPan(0),this.gainNode.connect(this.panNode),this.panNode.connect(c.destination)):this.gainNode.connect(c.destination),"oscillator"=== +this.options.type&&this.initOscillator(this.options.oscillator),this.playCallbackTimers=[]):p(29)};d.prototype.copy=function(c){return new d(m(this.options,{id:null},c))};d.prototype.initAudioContext=function(){var c=e.win.AudioContext||e.win.webkitAudioContext,a=!!e.audioContext;return c?(e.audioContext=e.audioContext||new c,!a&&e.audioContext&&"running"===e.audioContext.state&&e.audioContext.suspend(),!!(e.audioContext&&e.audioContext.createOscillator&&e.audioContext.createGain)):!1};d.prototype.initOscillator= +function(c){this.oscillator=e.audioContext.createOscillator();this.oscillator.type=c.waveformShape;this.oscillator.connect(this.gainNode);this.oscillatorStarted=!1};d.prototype.setPan=function(c){this.panNode&&this.panNode.pan.setValueAtTime(c,e.audioContext.currentTime)};d.prototype.setGain=function(c,a){this.gainNode&&(1.2b?f:a},Infinity):c};d.prototype.clearPlayCallbackTimers= +function(){this.playCallbackTimers.forEach(function(c){clearInterval(c)});this.playCallbackTimers=[]};d.prototype.setFrequency=function(c,a){a=a||{};c=this.getValidFrequency(c,a.min,a.max);"oscillator"===this.options.type&&this.oscillatorPlay(c)};d.prototype.oscillatorPlay=function(c){this.oscillatorStarted||(this.oscillator.start(),this.oscillatorStarted=!0);this.oscillator.frequency.setValueAtTime(c,e.audioContext.currentTime)};d.prototype.preparePlay=function(){this.setGain(.001);"suspended"=== +e.audioContext.state&&e.audioContext.resume();this.oscillator&&!this.oscillatorStarted&&(this.oscillator.start(),this.oscillatorStarted=!0)};d.prototype.play=function(c){var a=this,f=c.duration||0,h=function(f,h,e){var b=c.duration,d=0,k=a.options.playCallbackInterval;if("function"===typeof f){var g=setInterval(function(){d++;var c=d*k/b;if(1<=c)a[h](f(1),e),clearInterval(g);else a[h](f(c),e)},k);a.playCallbackTimers.push(g)}else a[h](f,e)};if(a.id)if("suspended"===e.audioContext.state||this.oscillator&& +!this.oscillatorStarted)a.preparePlay(),setTimeout(function(){a.play(c)},10);else{a.playCallbackTimers.length&&a.clearPlayCallbackTimers();a.cancelGainRamp();a.stopOscillatorTimeout&&(clearTimeout(a.stopOscillatorTimeout),delete a.stopOscillatorTimeout);a.stopTimeout&&(clearTimeout(a.stopTimeout),delete a.stopTimeout,a.stopCallback&&(a._play=a.play,a.play=function(){},a.stopCallback("cancelled"),a.play=a._play));var b=f=c.max||f.push(new b.sonification.TimelineEvent({time:c.max}));f.length&&a.addTimelineEvents(f)})}function y(a){return a.reduce(function(a,b){return a+u(b).reduce(function(a,b){return(b=b.series&&b.seriesOptions&& +b.seriesOptions.timeExtremes)?Math.max(a,b.max-b.min):a},0)},0)}function z(c,d){var e=Math.max(d-t(c),0),f=y(c);return c.reduce(function(c,d){d=u(d).reduce(function(c,d){d instanceof b.sonification.TimelinePath?c.push(d):d.series&&(d.seriesOptions.duration=d.seriesOptions.duration||p.virtualAxisTranslate(d.seriesOptions.timeExtremes.max-d.seriesOptions.timeExtremes.min,{min:0,max:f},{min:0,max:e}),c.push(a(d.series,d.seriesOptions)));return c},[]);c.push(d);return c},[])}"";var A=d.find,B=d.isArray, +v=d.merge,w=d.pick,u=d.splat;return{chartSonify:function(a){var c=v(this.options.sonification,a);this.sonification.timeline&&this.sonification.timeline.pause();this.sonification.duration=c.duration;var d=q(this,c.instruments,c.dataExtremes);a=h(c.order,this,function(a){return f(a,d,c)});a=r(a,c.afterSeriesWait||0);a=z(a,c.duration);a.forEach(function(a){n(a)});this.sonification.timeline=new b.sonification.Timeline({paths:a,onEnd:c.onEnd});this.sonification.timeline.play()},seriesSonify:function(c){var d= +a(this,c),e=this.chart.sonification;e.timeline&&e.timeline.pause();e.duration=c.duration;e.timeline=new b.sonification.Timeline({paths:[d]});e.timeline.play()},pause:function(a){this.sonification.timeline?this.sonification.timeline.pause(w(a,!0)):this.sonification.currentlyPlayingPoint&&this.sonification.currentlyPlayingPoint.cancelSonify(a)},resume:function(a){this.sonification.timeline&&this.sonification.timeline.play(a)},rewind:function(a){this.sonification.timeline&&this.sonification.timeline.rewind(a)}, +cancel:function(a){this.pauseSonify(a);this.resetSonifyCursor()},getCurrentPoints:function(){if(this.sonification.timeline){var a=this.sonification.timeline.getCursor();return Object.keys(a).map(function(b){return a[b].eventObject}).filter(function(a){return a instanceof l})}return[]},setCursor:function(a){var b=this.sonification.timeline;b&&u(a).forEach(function(a){b.setCursor(a.id)})},resetCursor:function(){this.sonification.timeline&&this.sonification.timeline.resetCursor()},resetCursorEnd:function(){this.sonification.timeline&& +this.sonification.timeline.resetCursorEnd()}}});n(b,"modules/sonification/Timeline.js",[b["parts/Globals.js"],b["parts/Utilities.js"],b["modules/sonification/utilities.js"]],function(b,l,d){function e(a){this.init(a||{})}function m(a){this.init(a)}function g(a){this.init(a||{})}var n=l.merge,k=l.splat,c=l.uniqueKey;e.prototype.init=function(a){this.options=a;this.time=a.time||0;this.id=this.options.id=a.id||c()};e.prototype.play=function(a){var b=this.options.eventObject,c=this.options.onEnd,d=a&& +a.onEnd,e=this.options.playOptions&&this.options.playOptions.onEnd;a=n(this.options.playOptions,a);b&&b.sonify?(a.onEnd=c||d||e?function(){var a=arguments;[c,d,e].forEach(function(b){b&&b.apply(this,a)})}:void 0,b.sonify(a)):(d&&d(),c&&c())};e.prototype.cancel=function(a){this.options.eventObject.cancelSonify(a)};m.prototype.init=function(a){this.options=a;this.id=this.options.id=a.id||c();this.cursor=0;this.eventsPlaying={};this.events=a.silentWait?[new e({time:0}),new e({time:a.silentWait})]:this.options.events; +this.sortEvents();this.updateEventIdMap();this.signalHandler=new d.SignalHandler(["playOnEnd","masterOnEnd","onStart","onEventStart","onEventEnd"]);this.signalHandler.registerSignalCallbacks(n(a,{masterOnEnd:a.onEnd}))};m.prototype.sortEvents=function(){this.events=this.events.sort(function(a,b){return a.time-b.time})};m.prototype.updateEventIdMap=function(){this.eventIdMap=this.events.reduce(function(a,b,c){a[b.id]=c;return a},{})};m.prototype.addTimelineEvents=function(a){this.events=this.events.concat(a); +this.sortEvents();this.updateEventIdMap()};m.prototype.getCursor=function(){return this.events[this.cursor]};m.prototype.setCursor=function(a){a=this.eventIdMap[a];return"undefined"!==typeof a?(this.cursor=a,!0):!1};m.prototype.play=function(a){this.pause();this.signalHandler.emitSignal("onStart");this.signalHandler.clearSignalCallbacks(["playOnEnd"]);this.signalHandler.registerSignalCallbacks({playOnEnd:a});this.playEvents(1)};m.prototype.rewind=function(a){this.pause();this.signalHandler.emitSignal("onStart"); +this.signalHandler.clearSignalCallbacks(["playOnEnd"]);this.signalHandler.registerSignalCallbacks({playOnEnd:a});this.playEvents(-1)};m.prototype.resetCursor=function(){this.cursor=0};m.prototype.resetCursorEnd=function(){this.cursor=this.events.length-1};m.prototype.pause=function(a){var b=this;clearTimeout(b.nextScheduledPlay);Object.keys(b.eventsPlaying).forEach(function(c){b.eventsPlaying[c]&&b.eventsPlaying[c].cancel(a)});b.eventsPlaying={}};m.prototype.playEvents=function(a){var b=this,c=b.events[this.cursor], +d=b.events[this.cursor+a],e=function(a){b.signalHandler.emitSignal("masterOnEnd",a);b.signalHandler.emitSignal("playOnEnd",a)};c.timelinePath=b;if(!1===b.signalHandler.emitSignal("onEventStart",c))e({event:c,cancelled:!0});else if(b.eventsPlaying[c.id]=c,c.play({onEnd:function(a){a={event:c,cancelled:!!a};delete b.eventsPlaying[c.id];b.signalHandler.emitSignal("onEventEnd",a);d||e(a)}}),d){var g=Math.abs(d.time-c.time);1>g?(b.cursor+=a,b.playEvents(a)):this.nextScheduledPlay=setTimeout(function(){b.cursor+= +a;b.playEvents(a)},g)}};g.prototype.init=function(a){this.options=a;this.cursor=0;this.paths=a.paths;this.pathsPlaying={};this.signalHandler=new d.SignalHandler(["playOnEnd","masterOnEnd","onPathStart","onPathEnd"]);this.signalHandler.registerSignalCallbacks(n(a,{masterOnEnd:a.onEnd}))};g.prototype.play=function(a){this.pause();this.signalHandler.clearSignalCallbacks(["playOnEnd"]);this.signalHandler.registerSignalCallbacks({playOnEnd:a});this.playPaths(1)};g.prototype.rewind=function(a){this.pause(); +this.signalHandler.clearSignalCallbacks(["playOnEnd"]);this.signalHandler.registerSignalCallbacks({playOnEnd:a});this.playPaths(-1)};g.prototype.playPaths=function(a){var c=k(this.paths[this.cursor]),d=this.paths[this.cursor+a],e=this,g=this.signalHandler,l=0,m=function(b){g.emitSignal("onPathStart",b);e.pathsPlaying[b.id]=b;b[0=c.length&&(d&&!f?(e.cursor+=a,k(d).forEach(function(b){b[0< +a?"resetCursor":"resetCursorEnd"]()}),e.playPaths(a)):(g.emitSignal("playOnEnd",h),g.emitSignal("masterOnEnd",h)))})};c.forEach(function(a){a&&(a.timeline=e,setTimeout(function(){m(a)},b.sonification.fadeOutDuration))})};g.prototype.pause=function(a){var b=this;Object.keys(b.pathsPlaying).forEach(function(c){b.pathsPlaying[c]&&b.pathsPlaying[c].pause(a)});b.pathsPlaying={}};g.prototype.resetCursor=function(){this.paths.forEach(function(a){k(a).forEach(function(a){a.resetCursor()})});this.cursor=0}; +g.prototype.resetCursorEnd=function(){this.paths.forEach(function(a){k(a).forEach(function(a){a.resetCursorEnd()})});this.cursor=this.paths.length-1};g.prototype.setCursor=function(a){return this.paths.some(function(b){return k(b).some(function(b){return b.setCursor(a)})})};g.prototype.getCursor=function(){return this.getCurrentPlayingPaths().reduce(function(a,b){a[b.id]=b.getCursor();return a},{})};g.prototype.atStart=function(){return!this.getCurrentPlayingPaths().some(function(a){return a.cursor})}; +g.prototype.getCurrentPlayingPaths=function(){return k(this.paths[this.cursor])};return{TimelineEvent:e,TimelinePath:m,Timeline:g}});n(b,"modules/sonification/options.js",[],function(){return{sonification:{enabled:!1,duration:2E3,afterSeriesWait:1E3,order:"sequential",pointPlayTime:"x",instruments:[{instrument:"sineMusical",instrumentMapping:{duration:400,frequency:"y",volume:.7},instrumentOptions:{minFrequency:392,maxFrequency:1046}}]}}});n(b,"modules/sonification/sonification.js",[b["parts/Globals.js"], +b["parts/Point.js"],b["parts/Utilities.js"],b["modules/sonification/Instrument.js"],b["modules/sonification/instrumentDefinitions.js"],b["modules/sonification/Earcon.js"],b["modules/sonification/pointSonify.js"],b["modules/sonification/chartSonify.js"],b["modules/sonification/utilities.js"],b["modules/sonification/Timeline.js"],b["modules/sonification/options.js"]],function(b,l,d,n,m,g,q,k,c,a,f){var e=d.addEvent,p=d.extend,t=d.merge;b.sonification={fadeOutDuration:20,utilities:c,Instrument:n,instruments:m, +Earcon:g,TimelineEvent:a.TimelineEvent,TimelinePath:a.TimelinePath,Timeline:a.Timeline};t(!0,b.defaultOptions,f);l.prototype.sonify=q.pointSonify;l.prototype.cancelSonify=q.pointCancelSonify;b.Series.prototype.sonify=k.seriesSonify;p(b.Chart.prototype,{sonify:k.chartSonify,pauseSonify:k.pause,resumeSonify:k.resume,rewindSonify:k.rewind,cancelSonify:k.cancel,getCurrentSonifyPoints:k.getCurrentPoints,setSonifyCursor:k.setCursor,resetSonifyCursor:k.resetCursor,resetSonifyCursorEnd:k.resetCursorEnd}); +e(b.Chart,"init",function(){this.sonification={}});e(b.Chart,"update",function(a){(a=a.options.sonification)&&t(!0,this.options.sonification,a)})});n(b,"masters/modules/sonification.src.js",[],function(){})}); +//# sourceMappingURL=sonification.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/sonification.js.map b/librerias/gantt/code/modules/sonification.js.map new file mode 100644 index 0000000..9108515 --- /dev/null +++ b/librerias/gantt/code/modules/sonification.js.map @@ -0,0 +1 @@ +{"version":3,"file":"sonification.js.map","lineCount":57,"mappings":"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","sources":["sonification.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","U","Instrument","options","init","error","merge","pick","uniqueKey","defaultOptions","type","playCallbackInterval","oscillator","waveformShape","prototype","Instrument.prototype.init","initAudioContext","id","ctx","audioContext","gainNode","createGain","setGain","panNode","createStereoPanner","setPan","connect","destination","initOscillator","playCallbackTimers","copy","Instrument.prototype.copy","Instrument.prototype.initAudioContext","Context","win","AudioContext","webkitAudioContext","hasOldContext","state","suspend","createOscillator","Instrument.prototype.initOscillator","oscillatorStarted","Instrument.prototype.setPan","panValue","pan","setValueAtTime","currentTime","Instrument.prototype.setGain","gainValue","rampTime","console","warn","gain","value","linearRampToValueAtTime","cancelGainRamp","Instrument.prototype.cancelGainRamp","cancelScheduledValues","getValidFrequency","Instrument.prototype.getValidFrequency","frequency","min","max","validFrequencies","allowedFrequencies","maximum","Infinity","minimum","length","reduce","acc","cur","Math","abs","clearPlayCallbackTimers","Instrument.prototype.clearPlayCallbackTimers","forEach","timer","clearInterval","setFrequency","Instrument.prototype.setFrequency","frequencyLimits","limits","validFrequency","oscillatorPlay","Instrument.prototype.oscillatorPlay","start","preparePlay","Instrument.prototype.preparePlay","resume","play","Instrument.prototype.play","instrument","duration","setOrStartTimer","setter","setterData","target","currentDurationIx","callbackInterval","setInterval","curTime","push","setTimeout","stopOscillatorTimeout","clearTimeout","stopTimeout","stopCallback","_play","instrument.play","immediate","sonification","fadeOutDuration","onEnd","onStop","stop","minFrequency","maxFrequency","volume","mute","Instrument.prototype.mute","Instrument.prototype.stop","immediately","onStopped","callbackData","instr","reset","e","disconnect","frequencies","musicalFrequencies","SignalHandler","supportedSignals","clamp","SignalHandler.prototype.init","signals","registerSignalCallbacks","SignalHandler.prototype.registerSignalCallbacks","signalHandler","supportedSignal","signal","clearSignalCallbacks","SignalHandler.prototype.clearSignalCallbacks","signalNames","signalName","emitSignal","SignalHandler.prototype.emitSignal","data","retval","handler","result","utilities","getMusicalScale","semitones","filter","freq","i","interval","some","allowedInterval","calculateDataExtremes","chart","prop","series","extremes","points","point","val","virtualAxisTranslate","dataExtremes","lenValueAxis","virtualAxisValue","instruments","waveform","Earcon","Earcon.prototype.init","instrumentsPlaying","sonify","Earcon.prototype.sonify","playOptions","masterVolume","masterPan","earcon","playOnEnd","masterOnEnd","opts","instrumentOpts","copyId","instrOnEnd","instrumentOpts.onEnd","arguments","Object","keys","instrumentCopy","cancelSonify","Earcon.prototype.cancelSonify","fadeOut","playing","instrIds","defaultInstrumentOptions","minDuration","maxDuration","minVolume","maxVolume","minPan","maxPan","pointSonifyFunctions","pointSonify","getMappingValue","makeFunction","allowedExtremes","time","currentlyPlayingPoint","isNull","visible","instrumentDefinition","mapping","instrumentMapping","instrumentOptions","cancelled","pointCancelSonify","Point","getPointTimeValue","timeProp","getTimeExtremes","getExtremesForInstrumentProps","newExtremes","instrumentParameter","getPointEarcons","earconDefinitions","earcons","earconDefinition","condition","cond","onPoint","makeInstrumentCopies","map","instrumentDef","buildTimelinePathFromSeries","timeExtremes","pointPlayTime","timelineEvents","events","concat","TimelineEvent","eventObject","TimelinePath","onStart","onEventStart","event","timelinePath","timeline","pause","resetCursor","onPointStart","onEventEnd","eventData","onPointEnd","buildSeriesOptions","chartSonifyOptions","seriesOptions","onSeriesStart","onSeriesEnd","isArray","find","optEntry","buildPathOrder","orderOptions","seriesOptionsCallback","order","seriesList","orderList","orderDef","simulItems","splat","items","item","itemObject","get","silentWait","addAfterSeriesWaits","wait","newOrder","simultaneousPaths","getWaitTime","waitTime","def","syncSimultaneousPaths","paths","hasEvents","eventsToAdd","addTimelineEvents","getSimulPathDurationTotal","durationTotal","maxPathDuration","buildPathsFromOrder","totalAvailableDurationMs","totalUsedDuration","allPaths","simulPaths","chartSonifyFunctions","chartSonify","afterSeriesWait","Timeline","seriesSonify","chartSonification","rewind","cancel","pauseSonify","resetSonifyCursor","getCurrentPoints","cursorObj","getCursor","eventObj","setCursor","resetCursorEnd","TimelineEvent.prototype.init","TimelineEvent.prototype.play","playOptionsOnEnd","TimelineEvent.prototype.cancel","TimelinePath.prototype.init","cursor","eventsPlaying","sortEvents","updateEventIdMap","TimelinePath.prototype.sortEvents","sort","a","b","TimelinePath.prototype.updateEventIdMap","eventIdMap","TimelinePath.prototype.addTimelineEvents","newEvents","TimelinePath.prototype.getCursor","TimelinePath.prototype.setCursor","eventId","ix","TimelinePath.prototype.play","playEvents","TimelinePath.prototype.rewind","TimelinePath.prototype.resetCursor","TimelinePath.prototype.resetCursorEnd","TimelinePath.prototype.pause","nextScheduledPlay","TimelinePath.prototype.playEvents","direction","curEvent","nextEvent","signalData","timeDiff","Timeline.prototype.init","pathsPlaying","Timeline.prototype.play","playPaths","Timeline.prototype.rewind","Timeline.prototype.playPaths","curPaths","nextPaths","pathsEnded","playPath","nextPath","Timeline.prototype.pause","Timeline.prototype.resetCursor","Timeline.prototype.resetCursorEnd","Timeline.prototype.setCursor","Timeline.prototype.getCursor","getCurrentPlayingPaths","atStart","Timeline.prototype.atStart","Timeline.prototype.getCurrentPlayingPaths","timelineClasses","enabled","TimelineClasses","sonificationOptions","addEvent","extend","Series","Chart","resumeSonify","rewindSonify","getCurrentSonifyPoints","setSonifyCursor","resetSonifyCursorEnd","newOptions"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/sonification.src.js b/librerias/gantt/code/modules/sonification.src.js new file mode 100644 index 0000000..fd4e090 --- /dev/null +++ b/librerias/gantt/code/modules/sonification.src.js @@ -0,0 +1,3028 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * Sonification module + * + * (c) 2012-2019 Øystein Moseng + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/sonification', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'modules/sonification/Instrument.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Instrument class for sonification module. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var error = U.error, merge = U.merge, pick = U.pick, uniqueKey = U.uniqueKey; + /** + * A set of options for the Instrument class. + * + * @requires module:modules/sonification + * + * @interface Highcharts.InstrumentOptionsObject + */ /** + * The type of instrument. Currently only `oscillator` is supported. Defaults + * to `oscillator`. + * @name Highcharts.InstrumentOptionsObject#type + * @type {string|undefined} + */ /** + * The unique ID of the instrument. Generated if not supplied. + * @name Highcharts.InstrumentOptionsObject#id + * @type {string|undefined} + */ /** + * When using functions to determine frequency or other parameters during + * playback, this options specifies how often to call the callback functions. + * Number given in milliseconds. Defaults to 20. + * @name Highcharts.InstrumentOptionsObject#playCallbackInterval + * @type {number|undefined} + */ /** + * A list of allowed frequencies for this instrument. If trying to play a + * frequency not on this list, the closest frequency will be used. Set to `null` + * to allow all frequencies to be used. Defaults to `null`. + * @name Highcharts.InstrumentOptionsObject#allowedFrequencies + * @type {Array|undefined} + */ /** + * Options specific to oscillator instruments. + * @name Highcharts.InstrumentOptionsObject#oscillator + * @type {Highcharts.OscillatorOptionsObject|undefined} + */ + /** + * Options for playing an instrument. + * + * @requires module:modules/sonification + * + * @interface Highcharts.InstrumentPlayOptionsObject + */ /** + * The frequency of the note to play. Can be a fixed number, or a function. The + * function receives one argument: the relative time of the note playing (0 + * being the start, and 1 being the end of the note). It should return the + * frequency number for each point in time. The poll interval of this function + * is specified by the Instrument.playCallbackInterval option. + * @name Highcharts.InstrumentPlayOptionsObject#frequency + * @type {number|Function} + */ /** + * The duration of the note in milliseconds. + * @name Highcharts.InstrumentPlayOptionsObject#duration + * @type {number} + */ /** + * The minimum frequency to allow. If the instrument has a set of allowed + * frequencies, the closest frequency is used by default. Use this option to + * stop too low frequencies from being used. + * @name Highcharts.InstrumentPlayOptionsObject#minFrequency + * @type {number|undefined} + */ /** + * The maximum frequency to allow. If the instrument has a set of allowed + * frequencies, the closest frequency is used by default. Use this option to + * stop too high frequencies from being used. + * @name Highcharts.InstrumentPlayOptionsObject#maxFrequency + * @type {number|undefined} + */ /** + * The volume of the instrument. Can be a fixed number between 0 and 1, or a + * function. The function receives one argument: the relative time of the note + * playing (0 being the start, and 1 being the end of the note). It should + * return the volume for each point in time. The poll interval of this function + * is specified by the Instrument.playCallbackInterval option. Defaults to 1. + * @name Highcharts.InstrumentPlayOptionsObject#volume + * @type {number|Function|undefined} + */ /** + * The panning of the instrument. Can be a fixed number between -1 and 1, or a + * function. The function receives one argument: the relative time of the note + * playing (0 being the start, and 1 being the end of the note). It should + * return the panning value for each point in time. The poll interval of this + * function is specified by the Instrument.playCallbackInterval option. + * Defaults to 0. + * @name Highcharts.InstrumentPlayOptionsObject#pan + * @type {number|Function|undefined} + */ /** + * Callback function to be called when the play is completed. + * @name Highcharts.InstrumentPlayOptionsObject#onEnd + * @type {Function|undefined} + */ + /** + * @requires module:modules/sonification + * + * @interface Highcharts.OscillatorOptionsObject + */ /** + * The waveform shape to use for oscillator instruments. Defaults to `sine`. + * @name Highcharts.OscillatorOptionsObject#waveformShape + * @type {string|undefined} + */ + // Default options for Instrument constructor + var defaultOptions = { + type: 'oscillator', + playCallbackInterval: 20, + oscillator: { + waveformShape: 'sine' + } + }; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The Instrument class. Instrument objects represent an instrument capable of + * playing a certain pitch for a specified duration. + * + * @sample highcharts/sonification/instrument/ + * Using Instruments directly + * @sample highcharts/sonification/instrument-advanced/ + * Using callbacks for instrument parameters + * + * @requires module:modules/sonification + * + * @class + * @name Highcharts.Instrument + * + * @param {Highcharts.InstrumentOptionsObject} options + * Options for the instrument instance. + */ + function Instrument(options) { + this.init(options); + } + Instrument.prototype.init = function (options) { + if (!this.initAudioContext()) { + error(29); + return; + } + this.options = merge(defaultOptions, options); + this.id = this.options.id = options && options.id || uniqueKey(); + // Init the audio nodes + var ctx = H.audioContext; + this.gainNode = ctx.createGain(); + this.setGain(0); + this.panNode = ctx.createStereoPanner && ctx.createStereoPanner(); + if (this.panNode) { + this.setPan(0); + this.gainNode.connect(this.panNode); + this.panNode.connect(ctx.destination); + } + else { + this.gainNode.connect(ctx.destination); + } + // Oscillator initialization + if (this.options.type === 'oscillator') { + this.initOscillator(this.options.oscillator); + } + // Init timer list + this.playCallbackTimers = []; + }; + /** + * Return a copy of an instrument. Only one instrument instance can play at a + * time, so use this to get a new copy of the instrument that can play alongside + * it. The new instrument copy will receive a new ID unless one is supplied in + * options. + * + * @function Highcharts.Instrument#copy + * + * @param {Highcharts.InstrumentOptionsObject} [options] + * Options to merge in for the copy. + * + * @return {Highcharts.Instrument} + * A new Instrument instance with the same options. + */ + Instrument.prototype.copy = function (options) { + return new Instrument(merge(this.options, { id: null }, options)); + }; + /** + * Init the audio context, if we do not have one. + * @private + * @return {boolean} True if successful, false if not. + */ + Instrument.prototype.initAudioContext = function () { + var Context = H.win.AudioContext || H.win.webkitAudioContext, hasOldContext = !!H.audioContext; + if (Context) { + H.audioContext = H.audioContext || new Context(); + if (!hasOldContext && + H.audioContext && + H.audioContext.state === 'running') { + H.audioContext.suspend(); // Pause until we need it + } + return !!(H.audioContext && + H.audioContext.createOscillator && + H.audioContext.createGain); + } + return false; + }; + /** + * Init an oscillator instrument. + * @private + * @param {Highcharts.OscillatorOptionsObject} oscillatorOptions + * The oscillator options passed to Highcharts.Instrument#init. + * @return {void} + */ + Instrument.prototype.initOscillator = function (options) { + var ctx = H.audioContext; + this.oscillator = ctx.createOscillator(); + this.oscillator.type = options.waveformShape; + this.oscillator.connect(this.gainNode); + this.oscillatorStarted = false; + }; + /** + * Set pan position. + * @private + * @param {number} panValue + * The pan position to set for the instrument. + * @return {void} + */ + Instrument.prototype.setPan = function (panValue) { + if (this.panNode) { + this.panNode.pan.setValueAtTime(panValue, H.audioContext.currentTime); + } + }; + /** + * Set gain level. A maximum of 1.2 is allowed before we emit a warning. The + * actual volume is not set above this level regardless of input. + * @private + * @param {number} gainValue + * The gain level to set for the instrument. + * @param {number} [rampTime=0] + * Gradually change the gain level, time given in milliseconds. + * @return {void} + */ + Instrument.prototype.setGain = function (gainValue, rampTime) { + if (this.gainNode) { + if (gainValue > 1.2) { + console.warn(// eslint-disable-line + 'Highcharts sonification warning: ' + + 'Volume of instrument set too high.'); + gainValue = 1.2; + } + if (rampTime) { + this.gainNode.gain.setValueAtTime(this.gainNode.gain.value, H.audioContext.currentTime); + this.gainNode.gain.linearRampToValueAtTime(gainValue, H.audioContext.currentTime + rampTime / 1000); + } + else { + this.gainNode.gain.setValueAtTime(gainValue, H.audioContext.currentTime); + } + } + }; + /** + * Cancel ongoing gain ramps. + * @private + * @return {void} + */ + Instrument.prototype.cancelGainRamp = function () { + if (this.gainNode) { + this.gainNode.gain.cancelScheduledValues(0); + } + }; + /** + * Get the closest valid frequency for this instrument. + * @private + * @param {number} frequency - The target frequency. + * @param {number} [min] - Minimum frequency to return. + * @param {number} [max] - Maximum frequency to return. + * @return {number} The closest valid frequency to the input frequency. + */ + Instrument.prototype.getValidFrequency = function (frequency, min, max) { + var validFrequencies = this.options.allowedFrequencies, maximum = pick(max, Infinity), minimum = pick(min, -Infinity); + return !validFrequencies || !validFrequencies.length ? + // No valid frequencies for this instrument, return the target + frequency : + // Use the valid frequencies and return the closest match + validFrequencies.reduce(function (acc, cur) { + // Find the closest allowed value + return Math.abs(cur - frequency) < Math.abs(acc - frequency) && + cur < maximum && cur > minimum ? + cur : acc; + }, Infinity); + }; + /** + * Clear existing play callback timers. + * @private + * @return {void} + */ + Instrument.prototype.clearPlayCallbackTimers = function () { + this.playCallbackTimers.forEach(function (timer) { + clearInterval(timer); + }); + this.playCallbackTimers = []; + }; + /** + * Set the current frequency being played by the instrument. The closest valid + * frequency between the frequency limits is used. + * @param {number} frequency + * The frequency to set. + * @param {Highcharts.Dictionary} [frequencyLimits] + * Object with maxFrequency and minFrequency + * @return {void} + */ + Instrument.prototype.setFrequency = function (frequency, frequencyLimits) { + var limits = frequencyLimits || {}, validFrequency = this.getValidFrequency(frequency, limits.min, limits.max); + if (this.options.type === 'oscillator') { + this.oscillatorPlay(validFrequency); + } + }; + /** + * Play oscillator instrument. + * @private + * @param {number} frequency - The frequency to play. + */ + Instrument.prototype.oscillatorPlay = function (frequency) { + if (!this.oscillatorStarted) { + this.oscillator.start(); + this.oscillatorStarted = true; + } + this.oscillator.frequency.setValueAtTime(frequency, H.audioContext.currentTime); + }; + /** + * Prepare instrument before playing. Resumes the audio context and starts the + * oscillator. + * @private + */ + Instrument.prototype.preparePlay = function () { + this.setGain(0.001); + if (H.audioContext.state === 'suspended') { + H.audioContext.resume(); + } + if (this.oscillator && !this.oscillatorStarted) { + this.oscillator.start(); + this.oscillatorStarted = true; + } + }; + /** + * Play the instrument according to options. + * + * @sample highcharts/sonification/instrument/ + * Using Instruments directly + * @sample highcharts/sonification/instrument-advanced/ + * Using callbacks for instrument parameters + * + * @function Highcharts.Instrument#play + * + * @param {Highcharts.InstrumentPlayOptionsObject} options + * Options for the playback of the instrument. + * + * @return {void} + */ + Instrument.prototype.play = function (options) { + var instrument = this, duration = options.duration || 0, + // Set a value, or if it is a function, set it continously as a timer. + // Pass in the value/function to set, the setter function, and any + // additional data to pass through to the setter function. + setOrStartTimer = function (value, setter, setterData) { + var target = options.duration, currentDurationIx = 0, callbackInterval = instrument.options.playCallbackInterval; + if (typeof value === 'function') { + var timer = setInterval(function () { + currentDurationIx++; + var curTime = (currentDurationIx * callbackInterval / target); + if (curTime >= 1) { + instrument[setter](value(1), setterData); + clearInterval(timer); + } + else { + instrument[setter](value(curTime), setterData); + } + }, callbackInterval); + instrument.playCallbackTimers.push(timer); + } + else { + instrument[setter](value, setterData); + } + }; + if (!instrument.id) { + // No audio support - do nothing + return; + } + // If the AudioContext is suspended we have to resume it before playing + if (H.audioContext.state === 'suspended' || + this.oscillator && !this.oscillatorStarted) { + instrument.preparePlay(); + // Try again in 10ms + setTimeout(function () { + instrument.play(options); + }, 10); + return; + } + // Clear any existing play timers + if (instrument.playCallbackTimers.length) { + instrument.clearPlayCallbackTimers(); + } + // Clear any gain ramps + instrument.cancelGainRamp(); + // Clear stop oscillator timer + if (instrument.stopOscillatorTimeout) { + clearTimeout(instrument.stopOscillatorTimeout); + delete instrument.stopOscillatorTimeout; + } + // If a note is playing right now, clear the stop timeout, and call the + // callback. + if (instrument.stopTimeout) { + clearTimeout(instrument.stopTimeout); + delete instrument.stopTimeout; + if (instrument.stopCallback) { + // We have a callback for the play we are interrupting. We do not + // allow this callback to start a new play, because that leads to + // chaos. We pass in 'cancelled' to indicate that this note did not + // finish, but still stopped. + instrument._play = instrument.play; + instrument.play = function () { }; + instrument.stopCallback('cancelled'); + instrument.play = instrument._play; + } + } + // Stop the note without fadeOut if the duration is too short to hear the + // note otherwise. + var immediate = duration < H.sonification.fadeOutDuration + 20; + // Stop the instrument after the duration of the note + instrument.stopCallback = options.onEnd; + var onStop = function () { + delete instrument.stopTimeout; + instrument.stop(immediate); + }; + if (duration) { + instrument.stopTimeout = setTimeout(onStop, immediate ? duration : + duration - H.sonification.fadeOutDuration); + // Play the note + setOrStartTimer(options.frequency, 'setFrequency', { + minFrequency: options.minFrequency, + maxFrequency: options.maxFrequency + }); + // Set the volume and panning + setOrStartTimer(pick(options.volume, 1), 'setGain', 4); // Slight ramp + setOrStartTimer(pick(options.pan, 0), 'setPan'); + } + else { + // No note duration, so just stop immediately + onStop(); + } + }; + /** + * Mute an instrument that is playing. If the instrument is not currently + * playing, this function does nothing. + * + * @function Highcharts.Instrument#mute + */ + Instrument.prototype.mute = function () { + this.setGain(0.0001, H.sonification.fadeOutDuration * 0.8); + }; + /** + * Stop the instrument playing. + * + * @function Highcharts.Instrument#stop + * + * @param {boolean} immediately + * Whether to do the stop immediately or fade out. + * + * @param {Function} [onStopped] + * Callback function to be called when the stop is completed. + * + * @param {*} [callbackData] + * Data to send to the onEnd callback functions. + * + * @return {void} + */ + Instrument.prototype.stop = function (immediately, onStopped, callbackData) { + var instr = this, reset = function () { + // Remove timeout reference + if (instr.stopOscillatorTimeout) { + delete instr.stopOscillatorTimeout; + } + // The oscillator may have stopped in the meantime here, so allow + // this function to fail if so. + try { + instr.oscillator.stop(); + } + catch (e) { + // silent error + } + instr.oscillator.disconnect(instr.gainNode); + // We need a new oscillator in order to restart it + instr.initOscillator(instr.options.oscillator); + // Done stopping, call the callback from the stop + if (onStopped) { + onStopped(callbackData); + } + // Call the callback for the play we finished + if (instr.stopCallback) { + instr.stopCallback(callbackData); + } + }; + // Clear any existing timers + if (instr.playCallbackTimers.length) { + instr.clearPlayCallbackTimers(); + } + if (instr.stopTimeout) { + clearTimeout(instr.stopTimeout); + } + if (immediately) { + instr.setGain(0); + reset(); + } + else { + instr.mute(); + // Stop the oscillator after the mute fade-out has finished + instr.stopOscillatorTimeout = + setTimeout(reset, H.sonification.fadeOutDuration + 100); + } + }; + + return Instrument; + }); + _registerModule(_modules, 'modules/sonification/musicalFrequencies.js', [], function () { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * List of musical frequencies from C0 to C8. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var frequencies = [ + 16.351597831287414, + 17.323914436054505, + 18.354047994837977, + 19.445436482630058, + 20.601722307054366, + 21.826764464562746, + 23.12465141947715, + 24.499714748859326, + 25.956543598746574, + 27.5, + 29.13523509488062, + 30.86770632850775, + 32.70319566257483, + 34.64782887210901, + 36.70809598967594, + 38.890872965260115, + 41.20344461410875, + 43.653528929125486, + 46.2493028389543, + 48.999429497718666, + 51.91308719749314, + 55, + 58.27047018976124, + 61.7354126570155, + 65.40639132514966, + 69.29565774421802, + 73.41619197935188, + 77.78174593052023, + 82.4068892282175, + 87.30705785825097, + 92.4986056779086, + 97.99885899543733, + 103.82617439498628, + 110, + 116.54094037952248, + 123.47082531403103, + 130.8127826502993, + 138.59131548843604, + 146.8323839587038, + 155.56349186104046, + 164.81377845643496, + 174.61411571650194, + 184.9972113558172, + 195.99771799087463, + 207.65234878997256, + 220, + 233.08188075904496, + 246.94165062806206, + 261.6255653005986, + 277.1826309768721, + 293.6647679174076, + 311.1269837220809, + 329.6275569128699, + 349.2282314330039, + 369.9944227116344, + 391.99543598174927, + 415.3046975799451, + 440, + 466.1637615180899, + 493.8833012561241, + 523.2511306011972, + 554.3652619537442, + 587.3295358348151, + 622.2539674441618, + 659.2551138257398, + 698.4564628660078, + 739.9888454232688, + 783.9908719634985, + 830.6093951598903, + 880, + 932.3275230361799, + 987.7666025122483, + 1046.5022612023945, + 1108.7305239074883, + 1174.6590716696303, + 1244.5079348883237, + 1318.5102276514797, + 1396.9129257320155, + 1479.9776908465376, + 1567.981743926997, + 1661.2187903197805, + 1760, + 1864.6550460723597, + 1975.533205024496, + 2093.004522404789, + 2217.4610478149766, + 2349.31814333926, + 2489.0158697766474, + 2637.02045530296, + 2793.825851464031, + 2959.955381693075, + 3135.9634878539946, + 3322.437580639561, + 3520, + 3729.3100921447194, + 3951.066410048992, + 4186.009044809578 // C8 + ]; + + return frequencies; + }); + _registerModule(_modules, 'modules/sonification/utilities.js', [_modules['modules/sonification/musicalFrequencies.js'], _modules['parts/Utilities.js']], function (musicalFrequencies, U) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Utility functions for sonification. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var clamp = U.clamp; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The SignalHandler class. Stores signal callbacks (event handlers), and + * provides an interface to register them, and emit signals. The word "event" is + * not used to avoid confusion with TimelineEvents. + * + * @requires module:modules/sonification + * + * @private + * @class + * @name Highcharts.SignalHandler + * + * @param {Array} supportedSignals + * List of supported signal names. + */ + function SignalHandler(supportedSignals) { + this.init(supportedSignals || []); + } + SignalHandler.prototype.init = function (supportedSignals) { + this.supportedSignals = supportedSignals; + this.signals = {}; + }; + /** + * Register a set of signal callbacks with this SignalHandler. + * Multiple signal callbacks can be registered for the same signal. + * @private + * @param {Highcharts.Dictionary<(Function|undefined)>} signals + * An object that contains a mapping from the signal name to the callbacks. Only + * supported events are considered. + * @return {void} + */ + SignalHandler.prototype.registerSignalCallbacks = function (signals) { + var signalHandler = this; + signalHandler.supportedSignals.forEach(function (supportedSignal) { + var signal = signals[supportedSignal]; + if (signal) { + (signalHandler.signals[supportedSignal] = + signalHandler.signals[supportedSignal] || []).push(signal); + } + }); + }; + /** + * Clear signal callbacks, optionally by name. + * @private + * @param {Array} [signalNames] - A list of signal names to clear. If + * not supplied, all signal callbacks are removed. + * @return {void} + */ + SignalHandler.prototype.clearSignalCallbacks = function (signalNames) { + var signalHandler = this; + if (signalNames) { + signalNames.forEach(function (signalName) { + if (signalHandler.signals[signalName]) { + delete signalHandler.signals[signalName]; + } + }); + } + else { + signalHandler.signals = {}; + } + }; + /** + * Emit a signal. Does nothing if the signal does not exist, or has no + * registered callbacks. + * @private + * @param {string} signalNames + * Name of signal to emit. + * @param {*} [data] + * Data to pass to the callback. + * @return {*} + */ + SignalHandler.prototype.emitSignal = function (signalName, data) { + var retval; + if (this.signals[signalName]) { + this.signals[signalName].forEach(function (handler) { + var result = handler(data); + retval = typeof result !== 'undefined' ? result : retval; + }); + } + return retval; + }; + var utilities = { + // List of musical frequencies from C0 to C8 + musicalFrequencies: musicalFrequencies, + // SignalHandler class + SignalHandler: SignalHandler, + /** + * Get a musical scale by specifying the semitones from 1-12 to include. + * 1: C, 2: C#, 3: D, 4: D#, 5: E, 6: F, + * 7: F#, 8: G, 9: G#, 10: A, 11: Bb, 12: B + * @private + * @param {Array} semitones + * Array of semitones from 1-12 to include in the scale. Duplicate entries + * are ignored. + * @return {Array} + * Array of frequencies from C0 to C8 that are included in this scale. + */ + getMusicalScale: function (semitones) { + return musicalFrequencies.filter(function (freq, i) { + var interval = i % 12 + 1; + return semitones.some(function (allowedInterval) { + return allowedInterval === interval; + }); + }); + }, + /** + * Calculate the extreme values in a chart for a data prop. + * @private + * @param {Highcharts.Chart} chart - The chart + * @param {string} prop - The data prop to find extremes for + * @return {Highcharts.RangeObject} Object with min and max properties + */ + calculateDataExtremes: function (chart, prop) { + return chart.series.reduce(function (extremes, series) { + // We use cropped points rather than series.data here, to allow + // users to zoom in for better fidelity. + series.points.forEach(function (point) { + var val = typeof point[prop] !== 'undefined' ? + point[prop] : point.options[prop]; + extremes.min = Math.min(extremes.min, val); + extremes.max = Math.max(extremes.max, val); + }); + return extremes; + }, { + min: Infinity, + max: -Infinity + }); + }, + /** + * Translate a value on a virtual axis. Creates a new, virtual, axis with a + * min and max, and maps the relative value onto this axis. + * @private + * @param {number} value + * The relative data value to translate. + * @param {Highcharts.RangeObject} DataExtremesObject + * The possible extremes for this value. + * @param {object} limits + * Limits for the virtual axis. + * @return {number} + * The value mapped to the virtual axis. + */ + virtualAxisTranslate: function (value, dataExtremes, limits) { + var lenValueAxis = dataExtremes.max - dataExtremes.min, lenVirtualAxis = limits.max - limits.min, virtualAxisValue = limits.min + + lenVirtualAxis * (value - dataExtremes.min) / lenValueAxis; + return lenValueAxis > 0 ? + clamp(virtualAxisValue, limits.min, limits.max) : + limits.min; + } + }; + + return utilities; + }); + _registerModule(_modules, 'modules/sonification/instrumentDefinitions.js', [_modules['modules/sonification/Instrument.js'], _modules['modules/sonification/utilities.js']], function (Instrument, utilities) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Instrument definitions for sonification module. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var instruments = {}; + ['sine', 'square', 'triangle', 'sawtooth'].forEach(function (waveform) { + // Add basic instruments + instruments[waveform] = new Instrument({ + oscillator: { waveformShape: waveform } + }); + // Add musical instruments + instruments[waveform + 'Musical'] = new Instrument({ + allowedFrequencies: utilities.musicalFrequencies, + oscillator: { waveformShape: waveform } + }); + // Add scaled instruments + instruments[waveform + 'Major'] = new Instrument({ + allowedFrequencies: utilities.getMusicalScale([1, 3, 5, 6, 8, 10, 12]), + oscillator: { waveformShape: waveform } + }); + }); + + return instruments; + }); + _registerModule(_modules, 'modules/sonification/Earcon.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Earcons for the sonification module in Highcharts. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var error = U.error, merge = U.merge, pick = U.pick, uniqueKey = U.uniqueKey; + /** + * Define an Instrument and the options for playing it. + * + * @requires module:modules/sonification + * + * @interface Highcharts.EarconInstrument + */ /** + * An instrument instance or the name of the instrument in the + * Highcharts.sonification.instruments map. + * @name Highcharts.EarconInstrument#instrument + * @type {string|Highcharts.Instrument} + */ /** + * The options to pass to Instrument.play. + * @name Highcharts.EarconInstrument#playOptions + * @type {Highcharts.InstrumentPlayOptionsObject} + */ + /** + * Options for an Earcon. + * + * @requires module:modules/sonification + * + * @interface Highcharts.EarconOptionsObject + */ /** + * The instruments and their options defining this earcon. + * @name Highcharts.EarconOptionsObject#instruments + * @type {Array} + */ /** + * The unique ID of the Earcon. Generated if not supplied. + * @name Highcharts.EarconOptionsObject#id + * @type {string|undefined} + */ /** + * Global panning of all instruments. Overrides all panning on individual + * instruments. Can be a number between -1 and 1. + * @name Highcharts.EarconOptionsObject#pan + * @type {number|undefined} + */ /** + * Master volume for all instruments. Volume settings on individual instruments + * can still be used for relative volume between the instruments. This setting + * does not affect volumes set by functions in individual instruments. Can be a + * number between 0 and 1. Defaults to 1. + * @name Highcharts.EarconOptionsObject#volume + * @type {number|undefined} + */ /** + * Callback function to call when earcon has finished playing. + * @name Highcharts.EarconOptionsObject#onEnd + * @type {Function|undefined} + */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The Earcon class. Earcon objects represent a certain sound consisting of + * one or more instruments playing a predefined sound. + * + * @sample highcharts/sonification/earcon/ + * Using earcons directly + * + * @requires module:modules/sonification + * + * @class + * @name Highcharts.Earcon + * + * @param {Highcharts.EarconOptionsObject} options + * Options for the Earcon instance. + */ + function Earcon(options) { + this.init(options || {}); + } + Earcon.prototype.init = function (options) { + this.options = options; + if (!this.options.id) { + this.options.id = this.id = uniqueKey(); + } + this.instrumentsPlaying = {}; + }; + /** + * Play the earcon, optionally overriding init options. + * + * @sample highcharts/sonification/earcon/ + * Using earcons directly + * + * @function Highcharts.Earcon#sonify + * + * @param {Highcharts.EarconOptionsObject} options + * Override existing options. + * + * @return {void} + */ + Earcon.prototype.sonify = function (options) { + var playOptions = merge(this.options, options); + // Find master volume/pan settings + var masterVolume = pick(playOptions.volume, 1), masterPan = playOptions.pan, earcon = this, playOnEnd = options && options.onEnd, masterOnEnd = earcon.options.onEnd; + // Go through the instruments and play them + playOptions.instruments.forEach(function (opts) { + var instrument = typeof opts.instrument === 'string' ? + H.sonification.instruments[opts.instrument] : opts.instrument, instrumentOpts = merge(opts.playOptions), instrOnEnd, instrumentCopy, copyId = ''; + if (instrument && instrument.play) { + if (opts.playOptions) { + // Handle master pan/volume + if (typeof opts.playOptions.volume !== 'function') { + instrumentOpts.volume = pick(masterVolume, 1) * + pick(opts.playOptions.volume, 1); + } + instrumentOpts.pan = pick(masterPan, instrumentOpts.pan); + // Handle onEnd + instrOnEnd = instrumentOpts.onEnd; + instrumentOpts.onEnd = function () { + delete earcon.instrumentsPlaying[copyId]; + if (instrOnEnd) { + instrOnEnd.apply(this, arguments); + } + if (!Object.keys(earcon.instrumentsPlaying).length) { + if (playOnEnd) { + playOnEnd.apply(this, arguments); + } + if (masterOnEnd) { + masterOnEnd.apply(this, arguments); + } + } + }; + // Play the instrument. Use a copy so we can play multiple at + // the same time. + instrumentCopy = instrument.copy(); + copyId = instrumentCopy.id; + earcon.instrumentsPlaying[copyId] = instrumentCopy; + instrumentCopy.play(instrumentOpts); + } + } + else { + error(30); + } + }); + }; + /** + * Cancel any current sonification of the Earcon. Calls onEnd functions. + * + * @function Highcharts.Earcon#cancelSonify + * + * @param {boolean} [fadeOut=false] + * Whether or not to fade out as we stop. If false, the earcon is + * cancelled synchronously. + * + * @return {void} + */ + Earcon.prototype.cancelSonify = function (fadeOut) { + var playing = this.instrumentsPlaying, instrIds = playing && Object.keys(playing); + if (instrIds && instrIds.length) { + instrIds.forEach(function (instr) { + playing[instr].stop(!fadeOut, null, 'cancelled'); + }); + this.instrumentsPlaying = {}; + } + }; + + return Earcon; + }); + _registerModule(_modules, 'modules/sonification/pointSonify.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/sonification/utilities.js']], function (H, U, utilities) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Code for sonifying single points. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var error = U.error, merge = U.merge, pick = U.pick; + /** + * Define the parameter mapping for an instrument. + * + * @requires module:modules/sonification + * + * @interface Highcharts.PointInstrumentMappingObject + */ /** + * Define the volume of the instrument. This can be a string with a data + * property name, e.g. `'y'`, in which case this data property is used to define + * the volume relative to the `y`-values of the other points. A higher `y` value + * would then result in a higher volume. This option can also be a fixed number + * or a function. If it is a function, this function is called in regular + * intervals while the note is playing. It receives three arguments: The point, + * the dataExtremes, and the current relative time - where 0 is the beginning of + * the note and 1 is the end. The function should return the volume of the note + * as a number between 0 and 1. + * @name Highcharts.PointInstrumentMappingObject#volume + * @type {string|number|Function} + */ /** + * Define the duration of the notes for this instrument. This can be a string + * with a data property name, e.g. `'y'`, in which case this data property is + * used to define the duration relative to the `y`-values of the other points. A + * higher `y` value would then result in a longer duration. This option can also + * be a fixed number or a function. If it is a function, this function is called + * once before the note starts playing, and should return the duration in + * milliseconds. It receives two arguments: The point, and the dataExtremes. + * @name Highcharts.PointInstrumentMappingObject#duration + * @type {string|number|Function} + */ /** + * Define the panning of the instrument. This can be a string with a data + * property name, e.g. `'x'`, in which case this data property is used to define + * the panning relative to the `x`-values of the other points. A higher `x` + * value would then result in a higher panning value (panned further to the + * right). This option can also be a fixed number or a function. If it is a + * function, this function is called in regular intervals while the note is + * playing. It receives three arguments: The point, the dataExtremes, and the + * current relative time - where 0 is the beginning of the note and 1 is the + * end. The function should return the panning of the note as a number between + * -1 and 1. + * @name Highcharts.PointInstrumentMappingObject#pan + * @type {string|number|Function|undefined} + */ /** + * Define the frequency of the instrument. This can be a string with a data + * property name, e.g. `'y'`, in which case this data property is used to define + * the frequency relative to the `y`-values of the other points. A higher `y` + * value would then result in a higher frequency. This option can also be a + * fixed number or a function. If it is a function, this function is called in + * regular intervals while the note is playing. It receives three arguments: + * The point, the dataExtremes, and the current relative time - where 0 is the + * beginning of the note and 1 is the end. The function should return the + * frequency of the note as a number (in Hz). + * @name Highcharts.PointInstrumentMappingObject#frequency + * @type {string|number|Function} + */ + /** + * @requires module:modules/sonification + * + * @interface Highcharts.PointInstrumentOptionsObject + */ /** + * The minimum duration for a note when using a data property for duration. Can + * be overridden by using either a fixed number or a function for + * instrumentMapping.duration. Defaults to 20. + * @name Highcharts.PointInstrumentOptionsObject#minDuration + * @type {number|undefined} + */ /** + * The maximum duration for a note when using a data property for duration. Can + * be overridden by using either a fixed number or a function for + * instrumentMapping.duration. Defaults to 2000. + * @name Highcharts.PointInstrumentOptionsObject#maxDuration + * @type {number|undefined} + */ /** + * The minimum pan value for a note when using a data property for panning. Can + * be overridden by using either a fixed number or a function for + * instrumentMapping.pan. Defaults to -1 (fully left). + * @name Highcharts.PointInstrumentOptionsObject#minPan + * @type {number|undefined} + */ /** + * The maximum pan value for a note when using a data property for panning. Can + * be overridden by using either a fixed number or a function for + * instrumentMapping.pan. Defaults to 1 (fully right). + * @name Highcharts.PointInstrumentOptionsObject#maxPan + * @type {number|undefined} + */ /** + * The minimum volume for a note when using a data property for volume. Can be + * overridden by using either a fixed number or a function for + * instrumentMapping.volume. Defaults to 0.1. + * @name Highcharts.PointInstrumentOptionsObject#minVolume + * @type {number|undefined} + */ /** + * The maximum volume for a note when using a data property for volume. Can be + * overridden by using either a fixed number or a function for + * instrumentMapping.volume. Defaults to 1. + * @name Highcharts.PointInstrumentOptionsObject#maxVolume + * @type {number|undefined} + */ /** + * The minimum frequency for a note when using a data property for frequency. + * Can be overridden by using either a fixed number or a function for + * instrumentMapping.frequency. Defaults to 220. + * @name Highcharts.PointInstrumentOptionsObject#minFrequency + * @type {number|undefined} + */ /** + * The maximum frequency for a note when using a data property for frequency. + * Can be overridden by using either a fixed number or a function for + * instrumentMapping.frequency. Defaults to 2200. + * @name Highcharts.PointInstrumentOptionsObject#maxFrequency + * @type {number|undefined} + */ + /** + * An instrument definition for a point, specifying the instrument to play and + * how to play it. + * + * @interface Highcharts.PointInstrumentObject + */ /** + * An Instrument instance or the name of the instrument in the + * Highcharts.sonification.instruments map. + * @name Highcharts.PointInstrumentObject#instrument + * @type {Highcharts.Instrument|string} + */ /** + * Mapping of instrument parameters for this instrument. + * @name Highcharts.PointInstrumentObject#instrumentMapping + * @type {Highcharts.PointInstrumentMappingObject} + */ /** + * Options for this instrument. + * @name Highcharts.PointInstrumentObject#instrumentOptions + * @type {Highcharts.PointInstrumentOptionsObject|undefined} + */ /** + * Callback to call when the instrument has stopped playing. + * @name Highcharts.PointInstrumentObject#onEnd + * @type {Function|undefined} + */ + /** + * Options for sonifying a point. + * @interface Highcharts.PointSonifyOptionsObject + */ /** + * The instrument definitions for this point. + * @name Highcharts.PointSonifyOptionsObject#instruments + * @type {Array} + */ /** + * Optionally provide the minimum/maximum values for the points. If this is not + * supplied, it is calculated from the points in the chart on demand. This + * option is supplied in the following format, as a map of point data properties + * to objects with min/max values: + * ```js + * dataExtremes: { + * y: { + * min: 0, + * max: 100 + * }, + * z: { + * min: -10, + * max: 10 + * } + * // Properties used and not provided are calculated on demand + * } + * ``` + * @name Highcharts.PointSonifyOptionsObject#dataExtremes + * @type {object|undefined} + */ /** + * Callback called when the sonification has finished. + * @name Highcharts.PointSonifyOptionsObject#onEnd + * @type {Function|undefined} + */ + // Defaults for the instrument options + // NOTE: Also change defaults in Highcharts.PointInstrumentOptionsObject if + // making changes here. + var defaultInstrumentOptions = { + minDuration: 20, + maxDuration: 2000, + minVolume: 0.1, + maxVolume: 1, + minPan: -1, + maxPan: 1, + minFrequency: 220, + maxFrequency: 2200 + }; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Sonify a single point. + * + * @sample highcharts/sonification/point-basic/ + * Click on points to sonify + * @sample highcharts/sonification/point-advanced/ + * Sonify bubbles + * + * @requires module:modules/sonification + * + * @function Highcharts.Point#sonify + * + * @param {Highcharts.PointSonifyOptionsObject} options + * Options for the sonification of the point. + * + * @return {void} + */ + function pointSonify(options) { + var point = this, chart = point.series.chart, dataExtremes = options.dataExtremes || {}, + // Get the value to pass to instrument.play from the mapping value + // passed in. + getMappingValue = function (value, makeFunction, allowedExtremes) { + // Function. Return new function if we try to use callback, + // otherwise call it now and return result. + if (typeof value === 'function') { + return makeFunction ? + function (time) { + return value(point, dataExtremes, time); + } : + value(point, dataExtremes); + } + // String, this is a data prop. + if (typeof value === 'string') { + // Find data extremes if we don't have them + dataExtremes[value] = dataExtremes[value] || + utilities.calculateDataExtremes(point.series.chart, value); + // Find the value + return utilities.virtualAxisTranslate(pick(point[value], point.options[value]), dataExtremes[value], allowedExtremes); + } + // Fixed number or something else weird, just use that + return value; + }; + // Register playing point on chart + chart.sonification.currentlyPlayingPoint = point; + // Keep track of instruments playing + point.sonification = point.sonification || {}; + point.sonification.instrumentsPlaying = + point.sonification.instrumentsPlaying || {}; + // Register signal handler for the point + var signalHandler = point.sonification.signalHandler = + point.sonification.signalHandler || + new utilities.SignalHandler(['onEnd']); + signalHandler.clearSignalCallbacks(); + signalHandler.registerSignalCallbacks({ onEnd: options.onEnd }); + // If we have a null point or invisible point, just return + if (point.isNull || !point.visible || !point.series.visible) { + signalHandler.emitSignal('onEnd'); + return; + } + // Go through instruments and play them + options.instruments.forEach(function (instrumentDefinition) { + var instrument = typeof instrumentDefinition.instrument === 'string' ? + H.sonification.instruments[instrumentDefinition.instrument] : + instrumentDefinition.instrument, mapping = instrumentDefinition.instrumentMapping || {}, extremes = merge(defaultInstrumentOptions, instrumentDefinition.instrumentOptions), id = instrument.id, onEnd = function (cancelled) { + // Instrument on end + if (instrumentDefinition.onEnd) { + instrumentDefinition.onEnd.apply(this, arguments); + } + // Remove currently playing point reference on chart + if (chart.sonification && + chart.sonification.currentlyPlayingPoint) { + delete chart.sonification.currentlyPlayingPoint; + } + // Remove reference from instruments playing + if (point.sonification && point.sonification.instrumentsPlaying) { + delete point.sonification.instrumentsPlaying[id]; + // This was the last instrument? + if (!Object.keys(point.sonification.instrumentsPlaying).length) { + signalHandler.emitSignal('onEnd', cancelled); + } + } + }; + // Play the note on the instrument + if (instrument && instrument.play) { + point.sonification.instrumentsPlaying[instrument.id] = + instrument; + instrument.play({ + frequency: getMappingValue(mapping.frequency, true, { min: extremes.minFrequency, max: extremes.maxFrequency }), + duration: getMappingValue(mapping.duration, false, { min: extremes.minDuration, max: extremes.maxDuration }), + pan: getMappingValue(mapping.pan, true, { min: extremes.minPan, max: extremes.maxPan }), + volume: getMappingValue(mapping.volume, true, { min: extremes.minVolume, max: extremes.maxVolume }), + onEnd: onEnd, + minFrequency: extremes.minFrequency, + maxFrequency: extremes.maxFrequency + }); + } + else { + error(30); + } + }); + } + /** + * Cancel sonification of a point. Calls onEnd functions. + * + * @requires module:modules/sonification + * + * @function Highcharts.Point#cancelSonify + * + * @param {boolean} [fadeOut=false] + * Whether or not to fade out as we stop. If false, the points are + * cancelled synchronously. + * + * @return {void} + */ + function pointCancelSonify(fadeOut) { + var playing = this.sonification && this.sonification.instrumentsPlaying, instrIds = playing && Object.keys(playing); + if (instrIds && instrIds.length) { + instrIds.forEach(function (instr) { + playing[instr].stop(!fadeOut, null, 'cancelled'); + }); + this.sonification.instrumentsPlaying = {}; + this.sonification.signalHandler.emitSignal('onEnd', 'cancelled'); + } + } + var pointSonifyFunctions = { + pointSonify: pointSonify, + pointCancelSonify: pointCancelSonify + }; + + return pointSonifyFunctions; + }); + _registerModule(_modules, 'modules/sonification/chartSonify.js', [_modules['parts/Globals.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js'], _modules['modules/sonification/utilities.js']], function (H, Point, U, utilities) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Sonification functions for chart/series. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * An Earcon configuration, specifying an Earcon and when to play it. + * + * @requires module:modules/sonification + * + * @interface Highcharts.EarconConfiguration + */ /** + * An Earcon instance. + * @name Highcharts.EarconConfiguration#earcon + * @type {Highcharts.Earcon} + */ /** + * The ID of the point to play the Earcon on. + * @name Highcharts.EarconConfiguration#onPoint + * @type {string|undefined} + */ /** + * A function to determine whether or not to play this earcon on a point. The + * function is called for every point, receiving that point as parameter. It + * should return either a boolean indicating whether or not to play the earcon, + * or a new Earcon instance - in which case the new Earcon will be played. + * @name Highcharts.EarconConfiguration#condition + * @type {Function|undefined} + */ + /** + * Options for sonifying a series. + * + * @requires module:modules/sonification + * + * @interface Highcharts.SonifySeriesOptionsObject + */ /** + * The duration for playing the points. Note that points might continue to play + * after the duration has passed, but no new points will start playing. + * @name Highcharts.SonifySeriesOptionsObject#duration + * @type {number} + */ /** + * The axis to use for when to play the points. Can be a string with a data + * property (e.g. `x`), or a function. If it is a function, this function + * receives the point as argument, and should return a numeric value. The points + * with the lowest numeric values are then played first, and the time between + * points will be proportional to the distance between the numeric values. + * @name Highcharts.SonifySeriesOptionsObject#pointPlayTime + * @type {string|Function} + */ /** + * The instrument definitions for the points in this series. + * @name Highcharts.SonifySeriesOptionsObject#instruments + * @type {Array} + */ /** + * Earcons to add to the series. + * @name Highcharts.SonifySeriesOptionsObject#earcons + * @type {Array|undefined} + */ /** + * Optionally provide the minimum/maximum data values for the points. If this is + * not supplied, it is calculated from all points in the chart on demand. This + * option is supplied in the following format, as a map of point data properties + * to objects with min/max values: + * ```js + * dataExtremes: { + * y: { + * min: 0, + * max: 100 + * }, + * z: { + * min: -10, + * max: 10 + * } + * // Properties used and not provided are calculated on demand + * } + * ``` + * @name Highcharts.SonifySeriesOptionsObject#dataExtremes + * @type {Highcharts.Dictionary|undefined} + */ /** + * Callback before a point is played. + * @name Highcharts.SonifySeriesOptionsObject#onPointStart + * @type {Function|undefined} + */ /** + * Callback after a point has finished playing. + * @name Highcharts.SonifySeriesOptionsObject#onPointEnd + * @type {Function|undefined} + */ /** + * Callback after the series has played. + * @name Highcharts.SonifySeriesOptionsObject#onEnd + * @type {Function|undefined} + */ + ''; // detach doclets above + var find = U.find, isArray = U.isArray, merge = U.merge, pick = U.pick, splat = U.splat; + /** + * Get the relative time value of a point. + * @private + * @param {Highcharts.Point} point + * The point. + * @param {Function|string} timeProp + * The time axis data prop or the time function. + * @return {number} + * The time value. + */ + function getPointTimeValue(point, timeProp) { + return typeof timeProp === 'function' ? + timeProp(point) : + pick(point[timeProp], point.options[timeProp]); + } + /** + * Get the time extremes of this series. This is handled outside of the + * dataExtremes, as we always want to just sonify the visible points, and we + * always want the extremes to be the extremes of the visible points. + * @private + * @param {Highcharts.Series} series + * The series to compute on. + * @param {Function|string} timeProp + * The time axis data prop or the time function. + * @return {Highcharts.RangeObject} + * Object with min/max extremes for the time values. + */ + function getTimeExtremes(series, timeProp) { + // Compute the extremes from the visible points. + return series.points.reduce(function (acc, point) { + var value = getPointTimeValue(point, timeProp); + acc.min = Math.min(acc.min, value); + acc.max = Math.max(acc.max, value); + return acc; + }, { + min: Infinity, + max: -Infinity + }); + } + /** + * Calculate value extremes for used instrument data properties. + * @private + * @param {Highcharts.Chart} chart + * The chart to calculate extremes from. + * @param {Array} instruments + * The instrument definitions used. + * @param {Highcharts.Dictionary} [dataExtremes] + * Predefined extremes for each data prop. + * @return {Highcharts.Dictionary} + * New extremes with data properties mapped to min/max objects. + */ + function getExtremesForInstrumentProps(chart, instruments, dataExtremes) { + return (instruments || []).reduce(function (newExtremes, instrumentDefinition) { + Object.keys(instrumentDefinition.instrumentMapping || {}).forEach(function (instrumentParameter) { + var value = instrumentDefinition.instrumentMapping[instrumentParameter]; + if (typeof value === 'string' && !newExtremes[value]) { + // This instrument parameter is mapped to a data prop. + // If we don't have predefined data extremes, find them. + newExtremes[value] = utilities.calculateDataExtremes(chart, value); + } + }); + return newExtremes; + }, merge(dataExtremes)); + } + /** + * Get earcons for the point if there are any. + * @private + * @param {Highcharts.Point} point + * The point to find earcons for. + * @param {Array} earconDefinitions + * Earcons to check. + * @return {Array} + * Array of earcons to be played with this point. + */ + function getPointEarcons(point, earconDefinitions) { + return earconDefinitions.reduce(function (earcons, earconDefinition) { + var cond, earcon = earconDefinition.earcon; + if (earconDefinition.condition) { + // We have a condition. This overrides onPoint + cond = earconDefinition.condition(point); + if (cond instanceof H.sonification.Earcon) { + // Condition returned an earcon + earcons.push(cond); + } + else if (cond) { + // Condition returned true + earcons.push(earcon); + } + } + else if (earconDefinition.onPoint && + point.id === earconDefinition.onPoint) { + // We have earcon onPoint + earcons.push(earcon); + } + return earcons; + }, []); + } + /** + * Utility function to get a new list of instrument options where all the + * instrument references are copies. + * @private + * @param {Array} instruments + * The instrument options. + * @return {Array} + * Array of copied instrument options. + */ + function makeInstrumentCopies(instruments) { + return instruments.map(function (instrumentDef) { + var instrument = instrumentDef.instrument, copy = (typeof instrument === 'string' ? + H.sonification.instruments[instrument] : + instrument).copy(); + return merge(instrumentDef, { instrument: copy }); + }); + } + /** + * Create a TimelinePath from a series. Takes the same options as seriesSonify. + * To intuitively allow multiple series to play simultaneously we make copies of + * the instruments for each series. + * @private + * @param {Highcharts.Series} series + * The series to build from. + * @param {Highcharts.SonifySeriesOptionsObject} options + * The options for building the TimelinePath. + * @return {Highcharts.TimelinePath} + * A timeline path with events. + */ + function buildTimelinePathFromSeries(series, options) { + // options.timeExtremes is internal and used so that the calculations from + // chart.sonify can be reused. + var timeExtremes = options.timeExtremes || getTimeExtremes(series, options.pointPlayTime), + // Get time offset for a point, relative to duration + pointToTime = function (point) { + return utilities.virtualAxisTranslate(getPointTimeValue(point, options.pointPlayTime), timeExtremes, { min: 0, max: options.duration }); + }, + // Compute any data extremes that aren't defined yet + dataExtremes = getExtremesForInstrumentProps(series.chart, options.instruments, options.dataExtremes), + // Make copies of the instruments used for this series, to allow + // multiple series with the same instrument to play together + instruments = makeInstrumentCopies(options.instruments), + // Go through the points, convert to events, optionally add Earcons + timelineEvents = series.points.reduce(function (events, point) { + var earcons = getPointEarcons(point, options.earcons || []), time = pointToTime(point); + return events.concat( + // Event object for point + new H.sonification.TimelineEvent({ + eventObject: point, + time: time, + id: point.id, + playOptions: { + instruments: instruments, + dataExtremes: dataExtremes + } + }), + // Earcons + earcons.map(function (earcon) { + return new H.sonification.TimelineEvent({ + eventObject: earcon, + time: time + }); + })); + }, []); + // Build the timeline path + return new H.sonification.TimelinePath({ + events: timelineEvents, + onStart: function () { + if (options.onStart) { + options.onStart(series); + } + }, + onEventStart: function (event) { + var eventObject = event.options && event.options.eventObject; + if (eventObject instanceof Point) { + // Check for hidden series + if (!eventObject.series.visible && + !eventObject.series.chart.series.some(function (series) { + return series.visible; + })) { + // We have no visible series, stop the path. + event.timelinePath.timeline.pause(); + event.timelinePath.timeline.resetCursor(); + return false; + } + // Emit onPointStart + if (options.onPointStart) { + options.onPointStart(event, eventObject); + } + } + }, + onEventEnd: function (eventData) { + var eventObject = eventData.event && eventData.event.options && + eventData.event.options.eventObject; + if (eventObject instanceof Point && options.onPointEnd) { + options.onPointEnd(eventData.event, eventObject); + } + }, + onEnd: function () { + if (options.onEnd) { + options.onEnd(series); + } + } + }); + } + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Sonify a series. + * + * @sample highcharts/sonification/series-basic/ + * Click on series to sonify + * @sample highcharts/sonification/series-earcon/ + * Series with earcon + * @sample highcharts/sonification/point-play-time/ + * Play y-axis by time + * @sample highcharts/sonification/earcon-on-point/ + * Earcon set on point + * + * @requires module:modules/sonification + * + * @function Highcharts.Series#sonify + * + * @param {Highcharts.SonifySeriesOptionsObject} options + * The options for sonifying this series. + * + * @return {void} + */ + function seriesSonify(options) { + var timelinePath = buildTimelinePathFromSeries(this, options), chartSonification = this.chart.sonification; + // Only one timeline can play at a time. If we want multiple series playing + // at the same time, use chart.sonify. + if (chartSonification.timeline) { + chartSonification.timeline.pause(); + } + // Store reference to duration + chartSonification.duration = options.duration; + // Create new timeline for this series, and play it. + chartSonification.timeline = new H.sonification.Timeline({ + paths: [timelinePath] + }); + chartSonification.timeline.play(); + } + /** + * Utility function to assemble options for creating a TimelinePath from a + * series when sonifying an entire chart. + * @private + * @param {Highcharts.Series} series + * The series to return options for. + * @param {Highcharts.RangeObject} dataExtremes + * Pre-calculated data extremes for the chart. + * @param {Highcharts.SonificationOptions} chartSonifyOptions + * Options passed in to chart.sonify. + * @return {Partial} + * Options for buildTimelinePathFromSeries. + */ + function buildSeriesOptions(series, dataExtremes, chartSonifyOptions) { + var seriesOptions = chartSonifyOptions.seriesOptions || {}; + return merge({ + // Calculated dataExtremes for chart + dataExtremes: dataExtremes, + // We need to get timeExtremes for each series. We pass this + // in when building the TimelinePath objects to avoid + // calculating twice. + timeExtremes: getTimeExtremes(series, chartSonifyOptions.pointPlayTime), + // Some options we just pass on + instruments: chartSonifyOptions.instruments, + onStart: chartSonifyOptions.onSeriesStart, + onEnd: chartSonifyOptions.onSeriesEnd, + earcons: chartSonifyOptions.earcons + }, + // Merge in the specific series options by ID + isArray(seriesOptions) ? (find(seriesOptions, function (optEntry) { + return optEntry.id === pick(series.id, series.options.id); + }) || {}) : seriesOptions, { + // Forced options + pointPlayTime: chartSonifyOptions.pointPlayTime + }); + } + /** + * Utility function to normalize the ordering of timeline paths when sonifying + * a chart. + * @private + * @param {string|Array>} orderOptions - + * Order options for the sonification. + * @param {Highcharts.Chart} chart - The chart we are sonifying. + * @param {Function} seriesOptionsCallback + * A function that takes a series as argument, and returns the series options + * for that series to be used with buildTimelinePathFromSeries. + * @return {Array>} If order is + * sequential, we return an array of objects to create series paths from. If + * order is simultaneous we return an array of an array with the same. If there + * is a custom order, we return an array of arrays of either objects (for + * series) or TimelinePaths (for earcons and delays). + */ + function buildPathOrder(orderOptions, chart, seriesOptionsCallback) { + var order; + if (orderOptions === 'sequential' || orderOptions === 'simultaneous') { + // Just add the series from the chart + order = chart.series.reduce(function (seriesList, series) { + if (series.visible) { + seriesList.push({ + series: series, + seriesOptions: seriesOptionsCallback(series) + }); + } + return seriesList; + }, []); + // If order is simultaneous, group all series together + if (orderOptions === 'simultaneous') { + order = [order]; + } + } + else { + // We have a specific order, and potentially custom items - like + // earcons or silent waits. + order = orderOptions.reduce(function (orderList, orderDef) { + // Return set of items to play simultaneously. Could be only one. + var simulItems = splat(orderDef).reduce(function (items, item) { + var itemObject; + // Is this item a series ID? + if (typeof item === 'string') { + var series = chart.get(item); + if (series.visible) { + itemObject = { + series: series, + seriesOptions: seriesOptionsCallback(series) + }; + } + // Is it an earcon? If so, just create the path. + } + else if (item instanceof H.sonification.Earcon) { + // Path with a single event + itemObject = new H.sonification.TimelinePath({ + events: [new H.sonification.TimelineEvent({ + eventObject: item + })] + }); + } + // Is this item a silent wait? If so, just create the path. + if (item.silentWait) { + itemObject = new H.sonification.TimelinePath({ + silentWait: item.silentWait + }); + } + // Add to items to play simultaneously + if (itemObject) { + items.push(itemObject); + } + return items; + }, []); + // Add to order list + if (simulItems.length) { + orderList.push(simulItems); + } + return orderList; + }, []); + } + return order; + } + /** + * Utility function to add a silent wait after all series. + * @private + * @param {Array>} order + * The order of items. + * @param {number} wait + * The wait in milliseconds to add. + * @return {Array>} + * The order with waits inserted. + */ + function addAfterSeriesWaits(order, wait) { + if (!wait) { + return order; + } + return order.reduce(function (newOrder, orderDef, i) { + var simultaneousPaths = splat(orderDef); + newOrder.push(simultaneousPaths); + // Go through the simultaneous paths and see if there is a series there + if (i < order.length - 1 && // Do not add wait after last series + simultaneousPaths.some(function (item) { + return item.series; + })) { + // We have a series, meaning we should add a wait after these + // paths have finished. + newOrder.push(new H.sonification.TimelinePath({ + silentWait: wait + })); + } + return newOrder; + }, []); + } + /** + * Utility function to find the total amout of wait time in the TimelinePaths. + * @private + * @param {Array>} order - The order of + * TimelinePaths/items. + * @return {number} The total time in ms spent on wait paths between playing. + */ + function getWaitTime(order) { + return order.reduce(function (waitTime, orderDef) { + var def = splat(orderDef); + return waitTime + (def.length === 1 && + def[0].options && + def[0].options.silentWait || 0); + }, 0); + } + /** + * Utility function to ensure simultaneous paths have start/end events at the + * same time, to sync them. + * @private + * @param {Array} paths - The paths to sync. + */ + function syncSimultaneousPaths(paths) { + // Find the extremes for these paths + var extremes = paths.reduce(function (extremes, path) { + var events = path.events; + if (events && events.length) { + extremes.min = Math.min(events[0].time, extremes.min); + extremes.max = Math.max(events[events.length - 1].time, extremes.max); + } + return extremes; + }, { + min: Infinity, + max: -Infinity + }); + // Go through the paths and add events to make them fit the same timespan + paths.forEach(function (path) { + var events = path.events, hasEvents = events && events.length, eventsToAdd = []; + if (!(hasEvents && events[0].time <= extremes.min)) { + eventsToAdd.push(new H.sonification.TimelineEvent({ + time: extremes.min + })); + } + if (!(hasEvents && events[events.length - 1].time >= extremes.max)) { + eventsToAdd.push(new H.sonification.TimelineEvent({ + time: extremes.max + })); + } + if (eventsToAdd.length) { + path.addTimelineEvents(eventsToAdd); + } + }); + } + /** + * Utility function to find the total duration span for all simul path sets + * that include series. + * @private + * @param {Array>} order - The + * order of TimelinePaths/items. + * @return {number} The total time value span difference for all series. + */ + function getSimulPathDurationTotal(order) { + return order.reduce(function (durationTotal, orderDef) { + return durationTotal + splat(orderDef).reduce(function (maxPathDuration, item) { + var timeExtremes = (item.series && + item.seriesOptions && + item.seriesOptions.timeExtremes); + return timeExtremes ? + Math.max(maxPathDuration, timeExtremes.max - timeExtremes.min) : maxPathDuration; + }, 0); + }, 0); + } + /** + * Function to calculate the duration in ms for a series. + * @private + * @param {number} seriesValueDuration - The duration of the series in value + * difference. + * @param {number} totalValueDuration - The total duration of all (non + * simultaneous) series in value difference. + * @param {number} totalDurationMs - The desired total duration for all series + * in milliseconds. + * @return {number} The duration for the series in milliseconds. + */ + function getSeriesDurationMs(seriesValueDuration, totalValueDuration, totalDurationMs) { + // A series spanning the whole chart would get the full duration. + return utilities.virtualAxisTranslate(seriesValueDuration, { min: 0, max: totalValueDuration }, { min: 0, max: totalDurationMs }); + } + /** + * Convert series building objects into paths and return a new list of + * TimelinePaths. + * @private + * @param {Array>} order - The + * order list. + * @param {number} duration - Total duration to aim for in milliseconds. + * @return {Array>} Array of TimelinePath objects + * to play. + */ + function buildPathsFromOrder(order, duration) { + // Find time used for waits (custom or after series), and subtract it from + // available duration. + var totalAvailableDurationMs = Math.max(duration - getWaitTime(order), 0), + // Add up simultaneous path durations to find total value span duration + // of everything + totalUsedDuration = getSimulPathDurationTotal(order); + // Go through the order list and convert the items + return order.reduce(function (allPaths, orderDef) { + var simultaneousPaths = splat(orderDef).reduce(function (simulPaths, item) { + if (item instanceof H.sonification.TimelinePath) { + // This item is already a path object + simulPaths.push(item); + } + else if (item.series) { + // We have a series. + // We need to set the duration of the series + item.seriesOptions.duration = + item.seriesOptions.duration || getSeriesDurationMs(item.seriesOptions.timeExtremes.max - + item.seriesOptions.timeExtremes.min, totalUsedDuration, totalAvailableDurationMs); + // Add the path + simulPaths.push(buildTimelinePathFromSeries(item.series, item.seriesOptions)); + } + return simulPaths; + }, []); + // Add in the simultaneous paths + allPaths.push(simultaneousPaths); + return allPaths; + }, []); + } + /** + * @private + * @param {Highcharts.Chart} chart The chart to get options for. + * @param {Highcharts.SonificationOptions} userOptions + * Options to merge with options on chart and default options. + * @returns {Highcharts.SonificationOptions} The merged options. + */ + function getChartSonifyOptions(chart, userOptions) { + return merge(chart.options.sonification, userOptions); + } + /** + * Options for sonifying a chart. + * + * @requires module:modules/sonification + * + * @interface Highcharts.SonificationOptions + */ /** + * Duration for sonifying the entire chart. The duration is distributed across + * the different series intelligently, but does not take earcons into account. + * It is also possible to set the duration explicitly per series, using + * `seriesOptions`. Note that points may continue to play after the duration has + * passed, but no new points will start playing. + * @name Highcharts.SonificationOptions#duration + * @type {number} + */ /** + * Define the order to play the series in. This can be given as a string, or an + * array specifying a custom ordering. If given as a string, valid values are + * `sequential` - where each series is played in order - or `simultaneous`, + * where all series are played at once. For custom ordering, supply an array as + * the order. Each element in the array can be either a string with a series ID, + * an Earcon object, or an object with a numeric `silentWait` property + * designating a number of milliseconds to wait before continuing. Each element + * of the array will be played in order. To play elements simultaneously, group + * the elements in an array. + * @name Highcharts.SonificationOptions#order + * @type {string|Array>} + */ /** + * The axis to use for when to play the points. Can be a string with a data + * property (e.g. `x`), or a function. If it is a function, this function + * receives the point as argument, and should return a numeric value. The points + * with the lowest numeric values are then played first, and the time between + * points will be proportional to the distance between the numeric values. This + * option can not be overridden per series. + * @name Highcharts.SonificationOptions#pointPlayTime + * @type {string|Function} + */ /** + * Milliseconds of silent waiting to add between series. Note that waiting time + * is considered part of the sonify duration. + * @name Highcharts.SonificationOptions#afterSeriesWait + * @type {number|undefined} + */ /** + * Options as given to `series.sonify` to override options per series. If the + * option is supplied as an array of options objects, the `id` property of the + * object should correspond to the series' id. If the option is supplied as a + * single object, the options apply to all series. + * @name Highcharts.SonificationOptions#seriesOptions + * @type {Object|Array|undefined} + */ /** + * The instrument definitions for the points in this chart. + * @name Highcharts.SonificationOptions#instruments + * @type {Array|undefined} + */ /** + * Earcons to add to the chart. Note that earcons can also be added per series + * using `seriesOptions`. + * @name Highcharts.SonificationOptions#earcons + * @type {Array|undefined} + */ /** + * Optionally provide the minimum/maximum data values for the points. If this is + * not supplied, it is calculated from all points in the chart on demand. This + * option is supplied in the following format, as a map of point data properties + * to objects with min/max values: + * ```js + * dataExtremes: { + * y: { + * min: 0, + * max: 100 + * }, + * z: { + * min: -10, + * max: 10 + * } + * // Properties used and not provided are calculated on demand + * } + * ``` + * @name Highcharts.SonificationOptions#dataExtremes + * @type {Highcharts.Dictionary|undefined} + */ /** + * Callback before a series is played. + * @name Highcharts.SonificationOptions#onSeriesStart + * @type {Function|undefined} + */ /** + * Callback after a series has finished playing. + * @name Highcharts.SonificationOptions#onSeriesEnd + * @type {Function|undefined} + */ /** + * Callback after the chart has played. + * @name Highcharts.SonificationOptions#onEnd + * @type {Function|undefined} + */ + /** + * Sonify a chart. + * + * @sample highcharts/sonification/chart-sequential/ + * Sonify a basic chart + * @sample highcharts/sonification/chart-simultaneous/ + * Sonify series simultaneously + * @sample highcharts/sonification/chart-custom-order/ + * Custom defined order of series + * @sample highcharts/sonification/chart-earcon/ + * Earcons on chart + * @sample highcharts/sonification/chart-events/ + * Sonification events on chart + * + * @requires module:modules/sonification + * + * @function Highcharts.Chart#sonify + * + * @param {Highcharts.SonificationOptions} options + * The options for sonifying this chart. + * + * @return {void} + */ + function chartSonify(options) { + var opts = getChartSonifyOptions(this, options); + // Only one timeline can play at a time. + if (this.sonification.timeline) { + this.sonification.timeline.pause(); + } + // Store reference to duration + this.sonification.duration = opts.duration; + // Calculate data extremes for the props used + var dataExtremes = getExtremesForInstrumentProps(this, opts.instruments, opts.dataExtremes); + // Figure out ordering of series and custom paths + var order = buildPathOrder(opts.order, this, function (series) { + return buildSeriesOptions(series, dataExtremes, opts); + }); + // Add waits after simultaneous paths with series in them. + order = addAfterSeriesWaits(order, opts.afterSeriesWait || 0); + // We now have a list of either TimelinePath objects or series that need to + // be converted to TimelinePath objects. Convert everything to paths. + var paths = buildPathsFromOrder(order, opts.duration); + // Sync simultaneous paths + paths.forEach(function (simultaneousPaths) { + syncSimultaneousPaths(simultaneousPaths); + }); + // We have a set of paths. Create the timeline, and play it. + this.sonification.timeline = new H.sonification.Timeline({ + paths: paths, + onEnd: opts.onEnd + }); + this.sonification.timeline.play(); + } + /** + * Get a list of the points currently under cursor. + * + * @requires module:modules/sonification + * + * @function Highcharts.Chart#getCurrentSonifyPoints + * + * @return {Array} + * The points currently under the cursor. + */ + function getCurrentPoints() { + var cursorObj; + if (this.sonification.timeline) { + cursorObj = this.sonification.timeline.getCursor(); // Cursor per pathID + return Object.keys(cursorObj).map(function (path) { + // Get the event objects under cursor for each path + return cursorObj[path].eventObject; + }).filter(function (eventObj) { + // Return the events that are points + return eventObj instanceof Point; + }); + } + return []; + } + /** + * Set the cursor to a point or set of points in different series. + * + * @requires module:modules/sonification + * + * @function Highcharts.Chart#setSonifyCursor + * + * @param {Highcharts.Point|Array} points + * The point or points to set the cursor to. If setting multiple points + * under the cursor, the points have to be in different series that are + * being played simultaneously. + */ + function setCursor(points) { + var timeline = this.sonification.timeline; + if (timeline) { + splat(points).forEach(function (point) { + // We created the events with the ID of the points, which makes + // this easy. Just call setCursor for each ID. + timeline.setCursor(point.id); + }); + } + } + /** + * Pause the running sonification. + * + * @requires module:modules/sonification + * + * @function Highcharts.Chart#pauseSonify + * + * @param {boolean} [fadeOut=true] + * Fade out as we pause to avoid clicks. + * + * @return {void} + */ + function pause(fadeOut) { + if (this.sonification.timeline) { + this.sonification.timeline.pause(pick(fadeOut, true)); + } + else if (this.sonification.currentlyPlayingPoint) { + this.sonification.currentlyPlayingPoint.cancelSonify(fadeOut); + } + } + /** + * Resume the currently running sonification. Requires series.sonify or + * chart.sonify to have been played at some point earlier. + * + * @requires module:modules/sonification + * + * @function Highcharts.Chart#resumeSonify + * + * @param {Function} onEnd + * Callback to call when play finished. + * + * @return {void} + */ + function resume(onEnd) { + if (this.sonification.timeline) { + this.sonification.timeline.play(onEnd); + } + } + /** + * Play backwards from cursor. Requires series.sonify or chart.sonify to have + * been played at some point earlier. + * + * @requires module:modules/sonification + * + * @function Highcharts.Chart#rewindSonify + * + * @param {Function} onEnd + * Callback to call when play finished. + * + * @return {void} + */ + function rewind(onEnd) { + if (this.sonification.timeline) { + this.sonification.timeline.rewind(onEnd); + } + } + /** + * Cancel current sonification and reset cursor. + * + * @requires module:modules/sonification + * + * @function Highcharts.Chart#cancelSonify + * + * @param {boolean} [fadeOut=true] + * Fade out as we pause to avoid clicks. + * + * @return {void} + */ + function cancel(fadeOut) { + this.pauseSonify(fadeOut); + this.resetSonifyCursor(); + } + /** + * Reset cursor to start. Requires series.sonify or chart.sonify to have been + * played at some point earlier. + * + * @requires module:modules/sonification + * + * @function Highcharts.Chart#resetSonifyCursor + * + * @return {void} + */ + function resetCursor() { + if (this.sonification.timeline) { + this.sonification.timeline.resetCursor(); + } + } + /** + * Reset cursor to end. Requires series.sonify or chart.sonify to have been + * played at some point earlier. + * + * @requires module:modules/sonification + * + * @function Highcharts.Chart#resetSonifyCursorEnd + * + * @return {void} + */ + function resetCursorEnd() { + if (this.sonification.timeline) { + this.sonification.timeline.resetCursorEnd(); + } + } + // Export functions + var chartSonifyFunctions = { + chartSonify: chartSonify, + seriesSonify: seriesSonify, + pause: pause, + resume: resume, + rewind: rewind, + cancel: cancel, + getCurrentPoints: getCurrentPoints, + setCursor: setCursor, + resetCursor: resetCursor, + resetCursorEnd: resetCursorEnd + }; + + return chartSonifyFunctions; + }); + _registerModule(_modules, 'modules/sonification/Timeline.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['modules/sonification/utilities.js']], function (H, U, utilities) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * TimelineEvent class definition. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var merge = U.merge, splat = U.splat, uniqueKey = U.uniqueKey; + /** + * A set of options for the TimelineEvent class. + * + * @requires module:modules/sonification + * + * @private + * @interface Highcharts.TimelineEventOptionsObject + */ /** + * The object we want to sonify when playing the TimelineEvent. Can be any + * object that implements the `sonify` and `cancelSonify` functions. If this is + * not supplied, the TimelineEvent is considered a silent event, and the onEnd + * event is immediately called. + * @name Highcharts.TimelineEventOptionsObject#eventObject + * @type {*} + */ /** + * Options to pass on to the eventObject when playing it. + * @name Highcharts.TimelineEventOptionsObject#playOptions + * @type {object|undefined} + */ /** + * The time at which we want this event to play (in milliseconds offset). This + * is not used for the TimelineEvent.play function, but rather intended as a + * property to decide when to call TimelineEvent.play. Defaults to 0. + * @name Highcharts.TimelineEventOptionsObject#time + * @type {number|undefined} + */ /** + * Unique ID for the event. Generated automatically if not supplied. + * @name Highcharts.TimelineEventOptionsObject#id + * @type {string|undefined} + */ /** + * Callback called when the play has finished. + * @name Highcharts.TimelineEventOptionsObject#onEnd + * @type {Function|undefined} + */ + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * The TimelineEvent class. Represents a sound event on a timeline. + * + * @requires module:modules/sonification + * + * @private + * @class + * @name Highcharts.TimelineEvent + * + * @param {Highcharts.TimelineEventOptionsObject} options + * Options for the TimelineEvent. + */ + function TimelineEvent(options) { + this.init(options || {}); + } + TimelineEvent.prototype.init = function (options) { + this.options = options; + this.time = options.time || 0; + this.id = this.options.id = options.id || uniqueKey(); + }; + /** + * Play the event. Does not take the TimelineEvent.time option into account, + * and plays the event immediately. + * + * @function Highcharts.TimelineEvent#play + * + * @param {Highcharts.TimelineEventOptionsObject} [options] + * Options to pass in to the eventObject when playing it. + * + * @return {void} + */ + TimelineEvent.prototype.play = function (options) { + var eventObject = this.options.eventObject, masterOnEnd = this.options.onEnd, playOnEnd = options && options.onEnd, playOptionsOnEnd = this.options.playOptions && + this.options.playOptions.onEnd, playOptions = merge(this.options.playOptions, options); + if (eventObject && eventObject.sonify) { + // If we have multiple onEnds defined, use all + playOptions.onEnd = masterOnEnd || playOnEnd || playOptionsOnEnd ? + function () { + var args = arguments; + [masterOnEnd, playOnEnd, playOptionsOnEnd].forEach(function (onEnd) { + if (onEnd) { + onEnd.apply(this, args); + } + }); + } : void 0; + eventObject.sonify(playOptions); + } + else { + if (playOnEnd) { + playOnEnd(); + } + if (masterOnEnd) { + masterOnEnd(); + } + } + }; + /** + * Cancel the sonification of this event. Does nothing if the event is not + * currently sonifying. + * + * @function Highcharts.TimelineEvent#cancel + * + * @param {boolean} [fadeOut=false] + * Whether or not to fade out as we stop. If false, the event is + * cancelled synchronously. + */ + TimelineEvent.prototype.cancel = function (fadeOut) { + this.options.eventObject.cancelSonify(fadeOut); + }; + /** + * A set of options for the TimelinePath class. + * + * @requires module:modules/ + * + * @private + * @interface Highcharts.TimelinePathOptionsObject + */ /** + * List of TimelineEvents to play on this track. + * @name Highcharts.TimelinePathOptionsObject#events + * @type {Array} + */ /** + * If this option is supplied, this path ignores all events and just waits for + * the specified number of milliseconds before calling onEnd. + * @name Highcharts.TimelinePathOptionsObject#silentWait + * @type {number|undefined} + */ /** + * Unique ID for this timeline path. Automatically generated if not supplied. + * @name Highcharts.TimelinePathOptionsObject#id + * @type {string|undefined} + */ /** + * Callback called before the path starts playing. + * @name Highcharts.TimelinePathOptionsObject#onStart + * @type {Function|undefined} + */ /** + * Callback function to call before an event plays. + * @name Highcharts.TimelinePathOptionsObject#onEventStart + * @type {Function|undefined} + */ /** + * Callback function to call after an event has stopped playing. + * @name Highcharts.TimelinePathOptionsObject#onEventEnd + * @type {Function|undefined} + */ /** + * Callback called when the whole path is finished. + * @name Highcharts.TimelinePathOptionsObject#onEnd + * @type {Function|undefined} + */ + /** + * The TimelinePath class. Represents a track on a timeline with a list of + * sound events to play at certain times relative to each other. + * + * @requires module:modules/sonification + * + * @private + * @class + * @name Highcharts.TimelinePath + * + * @param {Highcharts.TimelinePathOptionsObject} options + * Options for the TimelinePath. + */ + function TimelinePath(options) { + this.init(options); + } + TimelinePath.prototype.init = function (options) { + this.options = options; + this.id = this.options.id = options.id || uniqueKey(); + this.cursor = 0; + this.eventsPlaying = {}; + // Handle silent wait, otherwise use events from options + this.events = options.silentWait ? + [ + new TimelineEvent({ time: 0 }), + new TimelineEvent({ time: options.silentWait }) + ] : + this.options.events; + // We need to sort our events by time + this.sortEvents(); + // Get map from event ID to index + this.updateEventIdMap(); + // Signal events to fire + this.signalHandler = new utilities.SignalHandler(['playOnEnd', 'masterOnEnd', 'onStart', 'onEventStart', 'onEventEnd']); + this.signalHandler.registerSignalCallbacks(merge(options, { masterOnEnd: options.onEnd })); + }; + /** + * Sort the internal event list by time. + * @private + */ + TimelinePath.prototype.sortEvents = function () { + this.events = this.events.sort(function (a, b) { + return a.time - b.time; + }); + }; + /** + * Update the internal eventId to index map. + * @private + */ + TimelinePath.prototype.updateEventIdMap = function () { + this.eventIdMap = this.events.reduce(function (acc, cur, i) { + acc[cur.id] = i; + return acc; + }, {}); + }; + /** + * Add events to the path. Should not be done while the path is playing. + * The new events are inserted according to their time property. + * @private + * @param {Array} newEvents - The new timeline events + * to add. + */ + TimelinePath.prototype.addTimelineEvents = function (newEvents) { + this.events = this.events.concat(newEvents); + this.sortEvents(); // Sort events by time + this.updateEventIdMap(); // Update the event ID to index map + }; + /** + * Get the current TimelineEvent under the cursor. + * @private + * @return {Highcharts.TimelineEvent} The current timeline event. + */ + TimelinePath.prototype.getCursor = function () { + return this.events[this.cursor]; + }; + /** + * Set the current TimelineEvent under the cursor. + * @private + * @param {string} eventId + * The ID of the timeline event to set as current. + * @return {boolean} + * True if there is an event with this ID in the path. False otherwise. + */ + TimelinePath.prototype.setCursor = function (eventId) { + var ix = this.eventIdMap[eventId]; + if (typeof ix !== 'undefined') { + this.cursor = ix; + return true; + } + return false; + }; + /** + * Play the timeline from the current cursor. + * @private + * @param {Function} onEnd + * Callback to call when play finished. Does not override other onEnd callbacks. + * @return {void} + */ + TimelinePath.prototype.play = function (onEnd) { + this.pause(); + this.signalHandler.emitSignal('onStart'); + this.signalHandler.clearSignalCallbacks(['playOnEnd']); + this.signalHandler.registerSignalCallbacks({ playOnEnd: onEnd }); + this.playEvents(1); + }; + /** + * Play the timeline backwards from the current cursor. + * @private + * @param {Function} onEnd + * Callback to call when play finished. Does not override other onEnd callbacks. + * @return {void} + */ + TimelinePath.prototype.rewind = function (onEnd) { + this.pause(); + this.signalHandler.emitSignal('onStart'); + this.signalHandler.clearSignalCallbacks(['playOnEnd']); + this.signalHandler.registerSignalCallbacks({ playOnEnd: onEnd }); + this.playEvents(-1); + }; + /** + * Reset the cursor to the beginning. + * @private + */ + TimelinePath.prototype.resetCursor = function () { + this.cursor = 0; + }; + /** + * Reset the cursor to the end. + * @private + */ + TimelinePath.prototype.resetCursorEnd = function () { + this.cursor = this.events.length - 1; + }; + /** + * Cancel current playing. Leaves the cursor intact. + * @private + * @param {boolean} [fadeOut=false] - Whether or not to fade out as we stop. If + * false, the path is cancelled synchronously. + */ + TimelinePath.prototype.pause = function (fadeOut) { + var timelinePath = this; + // Cancel next scheduled play + clearTimeout(timelinePath.nextScheduledPlay); + // Cancel currently playing events + Object.keys(timelinePath.eventsPlaying).forEach(function (id) { + if (timelinePath.eventsPlaying[id]) { + timelinePath.eventsPlaying[id].cancel(fadeOut); + } + }); + timelinePath.eventsPlaying = {}; + }; + /** + * Play the events, starting from current cursor, and going in specified + * direction. + * @private + * @param {number} direction + * The direction to play, 1 for forwards and -1 for backwards. + * @return {void} + */ + TimelinePath.prototype.playEvents = function (direction) { + var timelinePath = this, curEvent = timelinePath.events[this.cursor], nextEvent = timelinePath.events[this.cursor + direction], timeDiff, onEnd = function (signalData) { + timelinePath.signalHandler.emitSignal('masterOnEnd', signalData); + timelinePath.signalHandler.emitSignal('playOnEnd', signalData); + }; + // Store reference to path on event + curEvent.timelinePath = timelinePath; + // Emit event, cancel if returns false + if (timelinePath.signalHandler.emitSignal('onEventStart', curEvent) === false) { + onEnd({ + event: curEvent, + cancelled: true + }); + return; + } + // Play the current event + timelinePath.eventsPlaying[curEvent.id] = curEvent; + curEvent.play({ + onEnd: function (cancelled) { + var signalData = { + event: curEvent, + cancelled: !!cancelled + }; + // Keep track of currently playing events for cancelling + delete timelinePath.eventsPlaying[curEvent.id]; + // Handle onEventEnd + timelinePath.signalHandler.emitSignal('onEventEnd', signalData); + // Reached end of path? + if (!nextEvent) { + onEnd(signalData); + } + } + }); + // Schedule next + if (nextEvent) { + timeDiff = Math.abs(nextEvent.time - curEvent.time); + if (timeDiff < 1) { + // Play immediately + timelinePath.cursor += direction; + timelinePath.playEvents(direction); + } + else { + // Schedule after the difference in ms + this.nextScheduledPlay = setTimeout(function () { + timelinePath.cursor += direction; + timelinePath.playEvents(direction); + }, timeDiff); + } + } + }; + /* ************************************************************************** * + * TIMELINE * + * ************************************************************************** */ + /** + * A set of options for the Timeline class. + * + * @requires module:modules/sonification + * + * @private + * @interface Highcharts.TimelineOptionsObject + */ /** + * List of TimelinePaths to play. Multiple paths can be grouped together and + * played simultaneously by supplying an array of paths in place of a single + * path. + * @name Highcharts.TimelineOptionsObject#paths + * @type {Array<(Highcharts.TimelinePath|Array)>} + */ /** + * Callback function to call before a path plays. + * @name Highcharts.TimelineOptionsObject#onPathStart + * @type {Function|undefined} + */ /** + * Callback function to call after a path has stopped playing. + * @name Highcharts.TimelineOptionsObject#onPathEnd + * @type {Function|undefined} + */ /** + * Callback called when the whole path is finished. + * @name Highcharts.TimelineOptionsObject#onEnd + * @type {Function|undefined} + */ + /** + * The Timeline class. Represents a sonification timeline with a list of + * timeline paths with events to play at certain times relative to each other. + * + * @requires module:modules/sonification + * + * @private + * @class + * @name Highcharts.Timeline + * + * @param {Highcharts.TimelineOptionsObject} options + * Options for the Timeline. + */ + function Timeline(options) { + this.init(options || {}); + } + Timeline.prototype.init = function (options) { + this.options = options; + this.cursor = 0; + this.paths = options.paths; + this.pathsPlaying = {}; + this.signalHandler = new utilities.SignalHandler(['playOnEnd', 'masterOnEnd', 'onPathStart', 'onPathEnd']); + this.signalHandler.registerSignalCallbacks(merge(options, { masterOnEnd: options.onEnd })); + }; + /** + * Play the timeline forwards from cursor. + * @private + * @param {Function} [onEnd] + * Callback to call when play finished. Does not override other onEnd callbacks. + * @return {void} + */ + Timeline.prototype.play = function (onEnd) { + this.pause(); + this.signalHandler.clearSignalCallbacks(['playOnEnd']); + this.signalHandler.registerSignalCallbacks({ playOnEnd: onEnd }); + this.playPaths(1); + }; + /** + * Play the timeline backwards from cursor. + * @private + * @param {Function} onEnd + * Callback to call when play finished. Does not override other onEnd callbacks. + * @return {void} + */ + Timeline.prototype.rewind = function (onEnd) { + this.pause(); + this.signalHandler.clearSignalCallbacks(['playOnEnd']); + this.signalHandler.registerSignalCallbacks({ playOnEnd: onEnd }); + this.playPaths(-1); + }; + /** + * Play the timeline in the specified direction. + * @private + * @param {number} direction + * Direction to play in. 1 for forwards, -1 for backwards. + * @return {void} + */ + Timeline.prototype.playPaths = function (direction) { + var curPaths = splat(this.paths[this.cursor]), nextPaths = this.paths[this.cursor + direction], timeline = this, signalHandler = this.signalHandler, pathsEnded = 0, + // Play a path + playPath = function (path) { + // Emit signal and set playing state + signalHandler.emitSignal('onPathStart', path); + timeline.pathsPlaying[path.id] = path; + // Do the play + path[direction > 0 ? 'play' : 'rewind'](function (callbackData) { + // Play ended callback + // Data to pass to signal callbacks + var cancelled = callbackData && callbackData.cancelled, signalData = { + path: path, + cancelled: cancelled + }; + // Clear state and send signal + delete timeline.pathsPlaying[path.id]; + signalHandler.emitSignal('onPathEnd', signalData); + // Handle next paths + pathsEnded++; + if (pathsEnded >= curPaths.length) { + // We finished all of the current paths for cursor. + if (nextPaths && !cancelled) { + // We have more paths, move cursor along + timeline.cursor += direction; + // Reset upcoming path cursors before playing + splat(nextPaths).forEach(function (nextPath) { + nextPath[direction > 0 ? 'resetCursor' : 'resetCursorEnd'](); + }); + // Play next + timeline.playPaths(direction); + } + else { + // If it is the last path in this direction, call onEnd + signalHandler.emitSignal('playOnEnd', signalData); + signalHandler.emitSignal('masterOnEnd', signalData); + } + } + }); + }; + // Go through the paths under cursor and play them + curPaths.forEach(function (path) { + if (path) { + // Store reference to timeline + path.timeline = timeline; + // Leave a timeout to let notes fade out before next play + setTimeout(function () { + playPath(path); + }, H.sonification.fadeOutDuration); + } + }); + }; + /** + * Stop the playing of the timeline. Cancels all current sounds, but does not + * affect the cursor. + * @private + * @param {boolean} [fadeOut=false] + * Whether or not to fade out as we stop. If false, the timeline is cancelled + * synchronously. + * @return {void} + */ + Timeline.prototype.pause = function (fadeOut) { + var timeline = this; + // Cancel currently playing events + Object.keys(timeline.pathsPlaying).forEach(function (id) { + if (timeline.pathsPlaying[id]) { + timeline.pathsPlaying[id].pause(fadeOut); + } + }); + timeline.pathsPlaying = {}; + }; + /** + * Reset the cursor to the beginning of the timeline. + * @private + * @return {void} + */ + Timeline.prototype.resetCursor = function () { + this.paths.forEach(function (paths) { + splat(paths).forEach(function (path) { + path.resetCursor(); + }); + }); + this.cursor = 0; + }; + /** + * Reset the cursor to the end of the timeline. + * @private + * @return {void} + */ + Timeline.prototype.resetCursorEnd = function () { + this.paths.forEach(function (paths) { + splat(paths).forEach(function (path) { + path.resetCursorEnd(); + }); + }); + this.cursor = this.paths.length - 1; + }; + /** + * Set the current TimelineEvent under the cursor. If multiple paths are being + * played at the same time, this function only affects a single path (the one + * that contains the eventId that is passed in). + * @private + * @param {string} eventId + * The ID of the timeline event to set as current. + * @return {boolean} + * True if the cursor was set, false if no TimelineEvent was found for this ID. + */ + Timeline.prototype.setCursor = function (eventId) { + return this.paths.some(function (paths) { + return splat(paths).some(function (path) { + return path.setCursor(eventId); + }); + }); + }; + /** + * Get the current TimelineEvents under the cursors. This function will return + * the event under the cursor for each currently playing path, as an object + * where the path ID is mapped to the TimelineEvent under that path's cursor. + * @private + * @return {Highcharts.Dictionary} + * The TimelineEvents under each path's cursors. + */ + Timeline.prototype.getCursor = function () { + return this.getCurrentPlayingPaths().reduce(function (acc, cur) { + acc[cur.id] = cur.getCursor(); + return acc; + }, {}); + }; + /** + * Check if timeline is reset or at start. + * @private + * @return {boolean} + * True if timeline is at the beginning. + */ + Timeline.prototype.atStart = function () { + return !this.getCurrentPlayingPaths().some(function (path) { + return path.cursor; + }); + }; + /** + * Get the current TimelinePaths being played. + * @private + * @return {Array} + * The TimelinePaths currently being played. + */ + Timeline.prototype.getCurrentPlayingPaths = function () { + return splat(this.paths[this.cursor]); + }; + // Export the classes + var timelineClasses = { + TimelineEvent: TimelineEvent, + TimelinePath: TimelinePath, + Timeline: Timeline + }; + + return timelineClasses; + }); + _registerModule(_modules, 'modules/sonification/options.js', [], function () { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Default options for sonification. + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + // Experimental, disabled by default, not exposed in API + var options = { + sonification: { + enabled: false, + duration: 2000, + afterSeriesWait: 1000, + order: 'sequential', + pointPlayTime: 'x', + instruments: [{ + instrument: 'sineMusical', + instrumentMapping: { + duration: 400, + frequency: 'y', + volume: 0.7 + }, + // Start at G4 note, end at C6 + instrumentOptions: { + minFrequency: 392, + maxFrequency: 1046 + } + }] + } + }; + + return options; + }); + _registerModule(_modules, 'modules/sonification/sonification.js', [_modules['parts/Globals.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js'], _modules['modules/sonification/Instrument.js'], _modules['modules/sonification/instrumentDefinitions.js'], _modules['modules/sonification/Earcon.js'], _modules['modules/sonification/pointSonify.js'], _modules['modules/sonification/chartSonify.js'], _modules['modules/sonification/utilities.js'], _modules['modules/sonification/Timeline.js'], _modules['modules/sonification/options.js']], function (H, Point, U, Instrument, instruments, Earcon, pointSonifyFunctions, chartSonifyFunctions, utilities, TimelineClasses, sonificationOptions) { + /* * + * + * (c) 2009-2020 Øystein Moseng + * + * Sonification module for Highcharts + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, extend = U.extend, merge = U.merge; + // Expose on the Highcharts object + /** + * Global classes and objects related to sonification. + * + * @requires module:modules/sonification + * + * @name Highcharts.sonification + * @type {Highcharts.SonificationObject} + */ + /** + * Global classes and objects related to sonification. + * + * @requires module:modules/sonification + * + * @interface Highcharts.SonificationObject + */ /** + * Note fade-out-time in milliseconds. Most notes are faded out quickly by + * default if there is time. This is to avoid abrupt stops which will cause + * perceived clicks. + * @name Highcharts.SonificationObject#fadeOutDuration + * @type {number} + */ /** + * Utility functions. + * @name Highcharts.SonificationObject#utilities + * @private + * @type {object} + */ /** + * The Instrument class. + * @name Highcharts.SonificationObject#Instrument + * @type {Function} + */ /** + * Predefined instruments, given as an object with a map between the instrument + * name and the Highcharts.Instrument object. + * @name Highcharts.SonificationObject#instruments + * @type {Object} + */ /** + * The Earcon class. + * @name Highcharts.SonificationObject#Earcon + * @type {Function} + */ /** + * The TimelineEvent class. + * @private + * @name Highcharts.SonificationObject#TimelineEvent + * @type {Function} + */ /** + * The TimelinePath class. + * @private + * @name Highcharts.SonificationObject#TimelinePath + * @type {Function} + */ /** + * The Timeline class. + * @private + * @name Highcharts.SonificationObject#Timeline + * @type {Function} + */ + H.sonification = { + fadeOutDuration: 20, + // Classes and functions + utilities: utilities, + Instrument: Instrument, + instruments: instruments, + Earcon: Earcon, + TimelineEvent: TimelineClasses.TimelineEvent, + TimelinePath: TimelineClasses.TimelinePath, + Timeline: TimelineClasses.Timeline + }; + // Add default options + merge(true, H.defaultOptions, sonificationOptions); + // Chart specific + Point.prototype.sonify = pointSonifyFunctions.pointSonify; + Point.prototype.cancelSonify = pointSonifyFunctions.pointCancelSonify; + H.Series.prototype.sonify = chartSonifyFunctions.seriesSonify; + extend(H.Chart.prototype, { + sonify: chartSonifyFunctions.chartSonify, + pauseSonify: chartSonifyFunctions.pause, + resumeSonify: chartSonifyFunctions.resume, + rewindSonify: chartSonifyFunctions.rewind, + cancelSonify: chartSonifyFunctions.cancel, + getCurrentSonifyPoints: chartSonifyFunctions.getCurrentPoints, + setSonifyCursor: chartSonifyFunctions.setCursor, + resetSonifyCursor: chartSonifyFunctions.resetCursor, + resetSonifyCursorEnd: chartSonifyFunctions.resetCursorEnd + }); + /* eslint-disable no-invalid-this */ + // Prepare charts for sonification on init + addEvent(H.Chart, 'init', function () { + this.sonification = {}; + }); + // Update with chart/series/point updates + addEvent(H.Chart, 'update', function (e) { + var newOptions = e.options.sonification; + if (newOptions) { + merge(true, this.options.sonification, newOptions); + } + }); + + }); + _registerModule(_modules, 'masters/modules/sonification.src.js', [], function () { + + + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/static-scale.js b/librerias/gantt/code/modules/static-scale.js new file mode 100644 index 0000000..287b242 --- /dev/null +++ b/librerias/gantt/code/modules/static-scale.js @@ -0,0 +1,13 @@ +/* + Highcharts Gantt JS v8.1.0 (2020-05-05) + + StaticScale + + (c) 2016-2019 Torstein Honsi, Lars A. V. Cabrera + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/static-scale",["highcharts"],function(c){a(c);a.Highcharts=c;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function c(a,b,c,f){a.hasOwnProperty(b)||(a[b]=f.apply(null,c))}a=a?a._modules:{};c(a,"modules/static-scale.src.js",[a["parts/Globals.js"],a["parts/Utilities.js"]],function(a,b){var c=b.addEvent,f=b.defined,g= +b.isNumber,h=b.pick;b=a.Chart;c(a.Axis,"afterSetOptions",function(){var a=this.chart.options&&this.chart.options.chart;!this.horiz&&g(this.options.staticScale)&&(!a.height||a.scrollablePlotArea&&a.scrollablePlotArea.minHeight)&&(this.staticScale=this.options.staticScale)});b.prototype.adjustHeight=function(){"adjustHeight"!==this.redrawTrigger&&((this.axes||[]).forEach(function(a){var b=a.chart,c=!!b.initiatedScale&&b.options.animation,d=a.options.staticScale;if(a.staticScale&&f(a.min)){var e=h(a.brokenAxis&& +a.brokenAxis.unitLength,a.max+a.tickInterval-a.min)*d;e=Math.max(e,d);d=e-b.plotHeight;1<=Math.abs(d)&&(b.plotHeight=e,b.redrawTrigger="adjustHeight",b.setSize(void 0,b.chartHeight+d,c));a.series.forEach(function(a){(a=a.sharedClipKey&&b[a.sharedClipKey])&&a.attr({height:b.plotHeight})})}}),this.initiatedScale=!0);this.redrawTrigger=null};c(b,"render",b.prototype.adjustHeight)});c(a,"masters/modules/static-scale.src.js",[],function(){})}); +//# sourceMappingURL=static-scale.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/static-scale.js.map b/librerias/gantt/code/modules/static-scale.js.map new file mode 100644 index 0000000..f65e3b9 --- /dev/null +++ b/librerias/gantt/code/modules/static-scale.js.map @@ -0,0 +1 @@ +{"version":3,"file":"static-scale.js.map","lineCount":12,"mappings":"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","sources":["static-scale.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","U","addEvent","defined","isNumber","pick","Chart","Axis","chartOptions","chart","options","horiz","staticScale","height","scrollablePlotArea","minHeight","prototype","adjustHeight","Chart.prototype.adjustHeight","redrawTrigger","forEach","axes","axis","animate","initiatedScale","animation","min","brokenAxis","unitLength","max","tickInterval","Math","diff","plotHeight","abs","setSize","chartHeight","series","clipRect","sharedClipKey","attr"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/static-scale.src.js b/librerias/gantt/code/modules/static-scale.src.js new file mode 100644 index 0000000..6caee9e --- /dev/null +++ b/librerias/gantt/code/modules/static-scale.src.js @@ -0,0 +1,109 @@ +/** + * @license Highcharts Gantt JS v8.1.0 (2020-05-05) + * + * StaticScale + * + * (c) 2016-2019 Torstein Honsi, Lars A. V. Cabrera + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/static-scale', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'modules/static-scale.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2016-2020 Torstein Honsi, Lars Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, defined = U.defined, isNumber = U.isNumber, pick = U.pick; + var Chart = H.Chart; + /* eslint-disable no-invalid-this */ + /** + * For vertical axes only. Setting the static scale ensures that each tick unit + * is translated into a fixed pixel height. For example, setting the static + * scale to 24 results in each Y axis category taking up 24 pixels, and the + * height of the chart adjusts. Adding or removing items will make the chart + * resize. + * + * @sample gantt/xrange-series/demo/ + * X-range series with static scale + * + * @type {number} + * @default 50 + * @since 6.2.0 + * @product gantt + * @apioption yAxis.staticScale + */ + addEvent(H.Axis, 'afterSetOptions', function () { + var chartOptions = this.chart.options && this.chart.options.chart; + if (!this.horiz && + isNumber(this.options.staticScale) && + (!chartOptions.height || + (chartOptions.scrollablePlotArea && + chartOptions.scrollablePlotArea.minHeight))) { + this.staticScale = this.options.staticScale; + } + }); + Chart.prototype.adjustHeight = function () { + if (this.redrawTrigger !== 'adjustHeight') { + (this.axes || []).forEach(function (axis) { + var chart = axis.chart, animate = !!chart.initiatedScale && + chart.options.animation, staticScale = axis.options.staticScale, height, diff; + if (axis.staticScale && defined(axis.min)) { + height = pick(axis.brokenAxis && axis.brokenAxis.unitLength, axis.max + axis.tickInterval - axis.min) * staticScale; + // Minimum height is 1 x staticScale. + height = Math.max(height, staticScale); + diff = height - chart.plotHeight; + if (Math.abs(diff) >= 1) { + chart.plotHeight = height; + chart.redrawTrigger = 'adjustHeight'; + chart.setSize(void 0, chart.chartHeight + diff, animate); + } + // Make sure clip rects have the right height before initial + // animation. + axis.series.forEach(function (series) { + var clipRect = series.sharedClipKey && + chart[series.sharedClipKey]; + if (clipRect) { + clipRect.attr({ + height: chart.plotHeight + }); + } + }); + } + }); + this.initiatedScale = true; + } + this.redrawTrigger = null; + }; + addEvent(Chart, 'render', Chart.prototype.adjustHeight); + + }); + _registerModule(_modules, 'masters/modules/static-scale.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/stock-tools.js b/librerias/gantt/code/modules/stock-tools.js new file mode 100644 index 0000000..2c9208d --- /dev/null +++ b/librerias/gantt/code/modules/stock-tools.js @@ -0,0 +1,94 @@ +/* + Highstock JS v8.1.0 (2020-05-05) + + Advanced Highstock tools + + (c) 2010-2019 Highsoft AS + Author: Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(g){"object"===typeof module&&module.exports?(g["default"]=g,module.exports=g):"function"===typeof define&&define.amd?define("highcharts/modules/stock-tools",["highcharts","highcharts/modules/stock"],function(q){g(q);g.Highcharts=q;return g}):g("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(g){function q(m,l,g,n){m.hasOwnProperty(l)||(m[l]=n.apply(null,g))}g=g?g._modules:{};q(g,"mixins/navigation.js",[],function(){return{initUpdate:function(m){m.navigation||(m.navigation={updates:[], +update:function(l,m){this.updates.forEach(function(n){n.update.call(n.context,l,m)})}})},addUpdate:function(m,l){l.navigation||this.initUpdate(l);l.navigation.updates.push({update:m,context:l})}}});q(g,"annotations/navigationBindings.js",[g["parts/Globals.js"],g["parts/Utilities.js"],g["mixins/navigation.js"]],function(m,l,g){function n(b){var d=b.prototype.defaultOptions.events&&b.prototype.defaultOptions.events.click;a(!0,b.prototype.defaultOptions.events,{click:function(a){var b=this,c=b.chart.navigationBindings, +e=c.activeAnnotation;d&&d.click.call(b,a);e!==b?(c.deselectAnnotation(),c.activeAnnotation=b,b.setControlPointsVisibility(!0),u(c,"showPopup",{annotation:b,formType:"annotation-toolbar",options:c.annotationToFields(b),onSubmit:function(a){var d={};"remove"===a.actionType?(c.activeAnnotation=!1,c.chart.removeAnnotation(b)):(c.fieldsToOptions(a.fields,d),c.deselectAnnotation(),a=d.typeOptions,"measure"===b.options.type&&(a.crosshairY.enabled=0!==a.crosshairY.strokeWidth,a.crosshairX.enabled=0!==a.crosshairX.strokeWidth), +b.update(d))}})):(c.deselectAnnotation(),u(c,"closePopup"));a.activeAnnotation=!0}})}var v=l.addEvent,y=l.attr,t=l.format,u=l.fireEvent,p=l.isArray,q=l.isFunction,w=l.isNumber,h=l.isObject,a=l.merge,b=l.objectEach,c=l.pick,e=m.doc,k=m.win,f=function(){function d(a,b){this.selectedButton=this.boundClassNames=void 0;this.chart=a;this.options=b;this.eventsToUnbind=[];this.container=e.getElementsByClassName(this.options.bindingsClassName||"")}d.prototype.initEvents=function(){var a=this,d=a.chart,c=a.container, +e=a.options;a.boundClassNames={};b(e.bindings||{},function(b){a.boundClassNames[b.className]=b});[].forEach.call(c,function(b){a.eventsToUnbind.push(v(b,"click",function(d){var c=a.getButtonEvents(b,d);c&&a.bindingsButtonClick(c.button,c.events,d)}))});b(e.events||{},function(b,d){q(b)&&a.eventsToUnbind.push(v(a,d,b))});a.eventsToUnbind.push(v(d.container,"click",function(b){!d.cancelClick&&d.isInsidePlot(b.chartX-d.plotLeft,b.chartY-d.plotTop)&&a.bindingsChartClick(this,b)}));a.eventsToUnbind.push(v(d.container, +"mousemove",function(b){a.bindingsContainerMouseMove(this,b)}))};d.prototype.initUpdate=function(){var a=this;g.addUpdate(function(b){a.update(b)},this.chart)};d.prototype.bindingsButtonClick=function(a,b,d){var c=this.chart;this.selectedButtonElement&&(u(this,"deselectButton",{button:this.selectedButtonElement}),this.nextEvent&&(this.currentUserDetails&&"annotations"===this.currentUserDetails.coll&&c.removeAnnotation(this.currentUserDetails),this.mouseMoveEvent=this.nextEvent=!1));this.selectedButton= +b;this.selectedButtonElement=a;u(this,"selectButton",{button:a});b.init&&b.init.call(this,a,d);(b.start||b.steps)&&c.renderer.boxWrapper.addClass("highcharts-draw-mode")};d.prototype.bindingsChartClick=function(a,b){a=this.chart;var d=this.selectedButton;a=a.renderer.boxWrapper;var c;if(c=this.activeAnnotation&&!b.activeAnnotation&&b.target.parentNode){a:{c=b.target;var e=k.Element.prototype,f=e.matches||e.msMatchesSelector||e.webkitMatchesSelector,r=null;if(e.closest)r=e.closest.call(c,".highcharts-popup"); +else{do{if(f.call(c,".highcharts-popup"))break a;c=c.parentElement||c.parentNode}while(null!==c&&1===c.nodeType)}c=r}c=!c}c&&(u(this,"closePopup"),this.deselectAnnotation());d&&d.start&&(this.nextEvent?(this.nextEvent(b,this.currentUserDetails),this.steps&&(this.stepIndex++,d.steps[this.stepIndex]?this.mouseMoveEvent=this.nextEvent=d.steps[this.stepIndex]:(u(this,"deselectButton",{button:this.selectedButtonElement}),a.removeClass("highcharts-draw-mode"),d.end&&d.end.call(this,b,this.currentUserDetails), +this.mouseMoveEvent=this.nextEvent=!1,this.selectedButton=null))):(this.currentUserDetails=d.start.call(this,b),d.steps?(this.stepIndex=0,this.steps=!0,this.mouseMoveEvent=this.nextEvent=d.steps[this.stepIndex]):(u(this,"deselectButton",{button:this.selectedButtonElement}),a.removeClass("highcharts-draw-mode"),this.steps=!1,this.selectedButton=null,d.end&&d.end.call(this,b,this.currentUserDetails))))};d.prototype.bindingsContainerMouseMove=function(a,b){this.mouseMoveEvent&&this.mouseMoveEvent(b, +this.currentUserDetails)};d.prototype.fieldsToOptions=function(a,d){b(a,function(a,b){var e=parseFloat(a),f=b.split("."),r=d,k=f.length-1;!w(e)||a.match(/px/g)||b.match(/format/g)||(a=e);""!==a&&"undefined"!==a&&f.forEach(function(b,d){var e=c(f[d+1],"");k===d?r[b]=a:(r[b]||(r[b]=e.match(/\d/g)?[]:{}),r=r[b])})});return d};d.prototype.deselectAnnotation=function(){this.activeAnnotation&&(this.activeAnnotation.setControlPointsVisibility(!1),this.activeAnnotation=!1)};d.prototype.annotationToFields= +function(a){function e(d,c,f,r){if(f&&-1===g.indexOf(c)&&(0<=(f.indexOf&&f.indexOf(c))||f[c]||!0===f))if(p(d))r[c]=[],d.forEach(function(a,d){h(a)?(r[c][d]={},b(a,function(a,b){e(a,b,k[c],r[c][d])})):e(a,0,k[c],r[c])});else if(h(d)){var x={};p(r)?(r.push(x),x[c]={},x=x[c]):r[c]=x;b(d,function(a,b){e(a,b,0===c?f:k[c],x)})}else"format"===c?r[c]=[t(d,a.labels[0].points[0]).toString(),"text"]:p(r)?r.push([d,l(d)]):r[c]=[d,l(d)]}var f=a.options,r=d.annotationsEditable,k=r.nestedOptions,l=this.utils.getFieldType, +m=c(f.type,f.shapes&&f.shapes[0]&&f.shapes[0].type,f.labels&&f.labels[0]&&f.labels[0].itemType,"label"),g=d.annotationsNonEditable[f.langKey]||[],n={langKey:f.langKey,type:m};b(f,function(a,d){"typeOptions"===d?(n[d]={},b(f[d],function(a,b){e(a,b,k,n[d],!0)})):e(a,d,r[m],n)});return n};d.prototype.getClickedClassNames=function(a,b){var d=b.target;b=[];for(var c;d&&((c=y(d,"class"))&&(b=b.concat(c.split(" ").map(function(a){return[a,d]}))),d=d.parentNode,d!==a););return b};d.prototype.getButtonEvents= +function(a,b){var d=this,c;this.getClickedClassNames(a,b).forEach(function(a){d.boundClassNames[a[0]]&&!c&&(c={events:d.boundClassNames[a[0]],button:a[1]})});return c};d.prototype.update=function(b){this.options=a(!0,this.options,b);this.removeEvents();this.initEvents()};d.prototype.removeEvents=function(){this.eventsToUnbind.forEach(function(a){a()})};d.prototype.destroy=function(){this.removeEvents()};d.annotationsEditable={nestedOptions:{labelOptions:["style","format","backgroundColor"],labels:["style"], +label:["style"],style:["fontSize","color"],background:["fill","strokeWidth","stroke"],innerBackground:["fill","strokeWidth","stroke"],outerBackground:["fill","strokeWidth","stroke"],shapeOptions:["fill","strokeWidth","stroke"],shapes:["fill","strokeWidth","stroke"],line:["strokeWidth","stroke"],backgroundColors:[!0],connector:["fill","strokeWidth","stroke"],crosshairX:["strokeWidth","stroke"],crosshairY:["strokeWidth","stroke"]},circle:["shapes"],verticalLine:[],label:["labelOptions"],measure:["background", +"crosshairY","crosshairX"],fibonacci:[],tunnel:["background","line","height"],pitchfork:["innerBackground","outerBackground"],rect:["shapes"],crookedLine:[],basicAnnotation:[]};d.annotationsNonEditable={rectangle:["crosshairX","crosshairY","label"]};return d}();f.prototype.utils={updateRectSize:function(a,b){var d=b.chart,c=b.options.typeOptions,e=d.pointer.getCoordinates(a);a=e.xAxis[0].value-c.point.x;c=c.point.y-e.yAxis[0].value;b.update({typeOptions:{background:{width:d.inverted?c:a,height:d.inverted? +a:c}}})},getFieldType:function(a){return{string:"text",number:"number","boolean":"checkbox"}[typeof a]}};m.Chart.prototype.initNavigationBindings=function(){var a=this.options;a&&a.navigation&&a.navigation.bindings&&(this.navigationBindings=new f(this,a.navigation),this.navigationBindings.initEvents(),this.navigationBindings.initUpdate())};v(m.Chart,"load",function(){this.initNavigationBindings()});v(m.Chart,"destroy",function(){this.navigationBindings&&this.navigationBindings.destroy()});v(f,"deselectButton", +function(){this.selectedButtonElement=null});v(m.Annotation,"remove",function(){this.chart.navigationBindings&&this.chart.navigationBindings.deselectAnnotation()});m.Annotation&&(n(m.Annotation),b(m.Annotation.types,function(a){n(a)}));m.setOptions({lang:{navigation:{popup:{simpleShapes:"Simple shapes",lines:"Lines",circle:"Circle",rectangle:"Rectangle",label:"Label",shapeOptions:"Shape options",typeOptions:"Details",fill:"Fill",format:"Text",strokeWidth:"Line width",stroke:"Line color",title:"Title", +name:"Name",labelOptions:"Label options",labels:"Labels",backgroundColor:"Background color",backgroundColors:"Background colors",borderColor:"Border color",borderRadius:"Border radius",borderWidth:"Border width",style:"Style",padding:"Padding",fontSize:"Font size",color:"Color",height:"Height",shapes:"Shape options"}}},navigation:{bindingsClassName:"highcharts-bindings-container",bindings:{circleAnnotation:{className:"highcharts-circle-annotation",start:function(b){b=this.chart.pointer.getCoordinates(b); +var d=this.chart.options.navigation;return this.chart.addAnnotation(a({langKey:"circle",type:"basicAnnotation",shapes:[{type:"circle",point:{xAxis:0,yAxis:0,x:b.xAxis[0].value,y:b.yAxis[0].value},r:5}]},d.annotationsOptions,d.bindings.circleAnnotation.annotationsOptions))},steps:[function(a,b){var d=b.options.shapes[0].point,c=this.chart.xAxis[0].toPixels(d.x);d=this.chart.yAxis[0].toPixels(d.y);var e=this.chart.inverted;b.update({shapes:[{r:Math.max(Math.sqrt(Math.pow(e?d-a.chartX:c-a.chartX,2)+ +Math.pow(e?c-a.chartY:d-a.chartY,2)),5)}]})}]},rectangleAnnotation:{className:"highcharts-rectangle-annotation",start:function(b){var d=this.chart.pointer.getCoordinates(b);b=this.chart.options.navigation;var c=d.xAxis[0].value;d=d.yAxis[0].value;return this.chart.addAnnotation(a({langKey:"rectangle",type:"basicAnnotation",shapes:[{type:"path",points:[{xAxis:0,yAxis:0,x:c,y:d},{xAxis:0,yAxis:0,x:c,y:d},{xAxis:0,yAxis:0,x:c,y:d},{xAxis:0,yAxis:0,x:c,y:d}]}]},b.annotationsOptions,b.bindings.rectangleAnnotation.annotationsOptions))}, +steps:[function(a,b){var d=b.options.shapes[0].points,c=this.chart.pointer.getCoordinates(a);a=c.xAxis[0].value;c=c.yAxis[0].value;d[1].x=a;d[2].x=a;d[2].y=c;d[3].y=c;b.update({shapes:[{points:d}]})}]},labelAnnotation:{className:"highcharts-label-annotation",start:function(b){b=this.chart.pointer.getCoordinates(b);var c=this.chart.options.navigation;return this.chart.addAnnotation(a({langKey:"label",type:"basicAnnotation",labelOptions:{format:"{y:.2f}"},labels:[{point:{xAxis:0,yAxis:0,x:b.xAxis[0].value, +y:b.yAxis[0].value},overflow:"none",crop:!0}]},c.annotationsOptions,c.bindings.labelAnnotation.annotationsOptions))}}},events:{},annotationsOptions:{}}});return f});q(g,"modules/stock-tools-bindings.js",[g["parts/Globals.js"],g["annotations/navigationBindings.js"],g["parts/Utilities.js"]],function(m,l,g){var n=g.correctFloat,v=g.defined,q=g.extend,t=g.fireEvent,u=g.isNumber,p=g.merge,y=g.pick,w=g.uniqueKey,h=l.prototype.utils;h.addFlagFromForm=function(a){return function(b){var c=this,e=c.chart,k= +e.stockTools,f=h.getFieldType;b=h.attractToPoint(b,e);var d={type:"flags",onSeries:b.series.id,shape:a,data:[{x:b.x,y:b.y}],point:{events:{click:function(){var a=this,b=a.options;t(c,"showPopup",{point:a,formType:"annotation-toolbar",options:{langKey:"flags",type:"flags",title:[b.title,f(b.title)],name:[b.name,f(b.name)]},onSubmit:function(b){"remove"===b.actionType?a.remove():a.update(c.fieldsToOptions(b.fields,{}))}})}}}};k&&k.guiEnabled||e.addSeries(d);t(c,"showPopup",{formType:"flag",options:{langKey:"flags", +type:"flags",title:["A",f("A")],name:["Flag A",f("Flag A")]},onSubmit:function(a){c.fieldsToOptions(a.fields,d.data[0]);e.addSeries(d)}})}};h.manageIndicators=function(a){var b=this.chart,c={linkedTo:a.linkedTo,type:a.type},e=["ad","cmf","mfi","vbp","vwap"],k="ad atr cci cmf macd mfi roc rsi ao aroon aroonoscillator trix apo dpo ppo natr williamsr stochastic slowstochastic linearRegression linearRegressionSlope linearRegressionIntercept linearRegressionAngle".split(" ");if("edit"===a.actionType)this.fieldsToOptions(a.fields, +c),(a=b.get(a.seriesId))&&a.update(c,!1);else if("remove"===a.actionType){if(a=b.get(a.seriesId)){var f=a.yAxis;a.linkedSeries&&a.linkedSeries.forEach(function(a){a.remove(!1)});a.remove(!1);0<=k.indexOf(a.type)&&(f.remove(!1),this.resizeYAxes())}}else c.id=w(),this.fieldsToOptions(a.fields,c),0<=k.indexOf(a.type)?(f=b.addAxis({id:w(),offset:0,opposite:!0,title:{text:""},tickPixelInterval:40,showLastLabel:!1,labels:{align:"left",y:-2}},!1,!1),c.yAxis=f.options.id,this.resizeYAxes()):c.yAxis=b.get(a.linkedTo).options.yAxis, +0<=e.indexOf(a.type)&&(c.params.volumeSeriesID=b.series.filter(function(a){return"column"===a.options.type})[0].options.id),b.addSeries(c,!1);t(this,"deselectButton",{button:this.selectedButtonElement});b.redraw()};h.updateHeight=function(a,b){b.update({typeOptions:{height:this.chart.pointer.getCoordinates(a).yAxis[0].value-b.options.typeOptions.points[1].y}})};h.attractToPoint=function(a,b){a=b.pointer.getCoordinates(a);var c=a.xAxis[0].value;a=a.yAxis[0].value;var e=Number.MAX_VALUE,k;b.series.forEach(function(a){a.points.forEach(function(a){a&& +e>Math.abs(a.x-c)&&(e=Math.abs(a.x-c),k=a)})});return{x:k.x,y:k.y,below:a=a&&(b.x=k,b.y=f)});c.update({typeOptions:{points:e.points}})}}; +q(l.prototype,{getYAxisPositions:function(a,b,c){function e(a){return v(a)&&!u(a)&&a.match("%")}var k=0;a=a.map(function(a){var d=e(a.options.height)?parseFloat(a.options.height)/100:a.height/b;a=e(a.options.top)?parseFloat(a.options.top)/100:n(a.top-a.chart.plotTop)/b;u(d)||(d=c/100);k=n(k+d);return{height:100*d,top:100*a}});a.allAxesHeight=k;return a},getYAxisResizers:function(a){var b=[];a.forEach(function(c,e){c=a[e+1];b[e]=c?{enabled:!0,controlledAxis:{next:[y(c.options.id,c.options.index)]}}: +{enabled:!1}});return b},resizeYAxes:function(a){a=a||20;var b=this.chart,c=b.yAxis.filter(h.isNotNavigatorYAxis),e=c.length;b=this.getYAxisPositions(c,b.plotHeight,a);var k=this.getYAxisResizers(c),f=b.allAxesHeight,d=a;1e?(b[0].height=n(b[0].height-d),b=this.recalculateYAxisPositions(b,d)):(a=100/e,b=this.recalculateYAxisPositions(b,a/(e-1),!0,-1)),b[e-1]={top:n(100-a),height:a}):(d=100*n(1-f),5>e?(b[0].height=n(b[0].height+d),b=this.recalculateYAxisPositions(b,d)):b=this.recalculateYAxisPositions(b, +d/e,!0,1));b.forEach(function(a,b){c[b].update({height:a.height+"%",top:a.top+"%",resize:k[b]},!1)})},recalculateYAxisPositions:function(a,b,c,e){a.forEach(function(k,f){f=a[f-1];k.top=f?n(f.height+f.top):0;c&&(k.height=n(k.height+e*b))});return a}});g={segment:{className:"highcharts-segment",start:function(a){a=this.chart.pointer.getCoordinates(a);var b=this.chart.options.navigation;a=p({langKey:"segment",type:"crookedLine",typeOptions:{points:[{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value, +y:a.yAxis[0].value}]}},b.annotationsOptions,b.bindings.segment.annotationsOptions);return this.chart.addAnnotation(a)},steps:[h.updateNthPoint(1)]},arrowSegment:{className:"highcharts-arrow-segment",start:function(a){a=this.chart.pointer.getCoordinates(a);var b=this.chart.options.navigation;a=p({langKey:"arrowSegment",type:"crookedLine",typeOptions:{line:{markerEnd:"arrow"},points:[{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value,y:a.yAxis[0].value}]}},b.annotationsOptions,b.bindings.arrowSegment.annotationsOptions); +return this.chart.addAnnotation(a)},steps:[h.updateNthPoint(1)]},ray:{className:"highcharts-ray",start:function(a){a=this.chart.pointer.getCoordinates(a);var b=this.chart.options.navigation;a=p({langKey:"ray",type:"crookedLine",typeOptions:{type:"ray",points:[{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value,y:a.yAxis[0].value}]}},b.annotationsOptions,b.bindings.ray.annotationsOptions);return this.chart.addAnnotation(a)},steps:[h.updateNthPoint(1)]},arrowRay:{className:"highcharts-arrow-ray", +start:function(a){a=this.chart.pointer.getCoordinates(a);var b=this.chart.options.navigation;a=p({langKey:"arrowRay",type:"infinityLine",typeOptions:{type:"ray",line:{markerEnd:"arrow"},points:[{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value,y:a.yAxis[0].value}]}},b.annotationsOptions,b.bindings.arrowRay.annotationsOptions);return this.chart.addAnnotation(a)},steps:[h.updateNthPoint(1)]},infinityLine:{className:"highcharts-infinity-line",start:function(a){a=this.chart.pointer.getCoordinates(a); +var b=this.chart.options.navigation;a=p({langKey:"infinityLine",type:"infinityLine",typeOptions:{type:"line",points:[{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value,y:a.yAxis[0].value}]}},b.annotationsOptions,b.bindings.infinityLine.annotationsOptions);return this.chart.addAnnotation(a)},steps:[h.updateNthPoint(1)]},arrowInfinityLine:{className:"highcharts-arrow-infinity-line",start:function(a){a=this.chart.pointer.getCoordinates(a);var b=this.chart.options.navigation;a=p({langKey:"arrowInfinityLine", +type:"infinityLine",typeOptions:{type:"line",line:{markerEnd:"arrow"},points:[{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value,y:a.yAxis[0].value}]}},b.annotationsOptions,b.bindings.arrowInfinityLine.annotationsOptions);return this.chart.addAnnotation(a)},steps:[h.updateNthPoint(1)]},horizontalLine:{className:"highcharts-horizontal-line",start:function(a){a=this.chart.pointer.getCoordinates(a);var b=this.chart.options.navigation;a=p({langKey:"horizontalLine",type:"infinityLine",draggable:"y", +typeOptions:{type:"horizontalLine",points:[{x:a.xAxis[0].value,y:a.yAxis[0].value}]}},b.annotationsOptions,b.bindings.horizontalLine.annotationsOptions);this.chart.addAnnotation(a)}},verticalLine:{className:"highcharts-vertical-line",start:function(a){a=this.chart.pointer.getCoordinates(a);var b=this.chart.options.navigation;a=p({langKey:"verticalLine",type:"infinityLine",draggable:"x",typeOptions:{type:"verticalLine",points:[{x:a.xAxis[0].value,y:a.yAxis[0].value}]}},b.annotationsOptions,b.bindings.verticalLine.annotationsOptions); +this.chart.addAnnotation(a)}},crooked3:{className:"highcharts-crooked3",start:function(a){a=this.chart.pointer.getCoordinates(a);var b=this.chart.options.navigation;a=p({langKey:"crooked3",type:"crookedLine",typeOptions:{points:[{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value,y:a.yAxis[0].value}]}},b.annotationsOptions,b.bindings.crooked3.annotationsOptions);return this.chart.addAnnotation(a)},steps:[h.updateNthPoint(1),h.updateNthPoint(2)]},crooked5:{className:"highcharts-crooked5", +start:function(a){a=this.chart.pointer.getCoordinates(a);var b=this.chart.options.navigation;a=p({langKey:"crookedLine",type:"crookedLine",typeOptions:{points:[{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value,y:a.yAxis[0].value}]}},b.annotationsOptions,b.bindings.crooked5.annotationsOptions);return this.chart.addAnnotation(a)},steps:[h.updateNthPoint(1),h.updateNthPoint(2), +h.updateNthPoint(3),h.updateNthPoint(4)]},elliott3:{className:"highcharts-elliott3",start:function(a){a=this.chart.pointer.getCoordinates(a);var b=this.chart.options.navigation;a=p({langKey:"elliott3",type:"elliottWave",typeOptions:{points:[{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value,y:a.yAxis[0].value}]},labelOptions:{style:{color:"#666666"}}},b.annotationsOptions,b.bindings.elliott3.annotationsOptions); +return this.chart.addAnnotation(a)},steps:[h.updateNthPoint(1),h.updateNthPoint(2),h.updateNthPoint(3)]},elliott5:{className:"highcharts-elliott5",start:function(a){a=this.chart.pointer.getCoordinates(a);var b=this.chart.options.navigation;a=p({langKey:"elliott5",type:"elliottWave",typeOptions:{points:[{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value,y:a.yAxis[0].value}, +{x:a.xAxis[0].value,y:a.yAxis[0].value}]},labelOptions:{style:{color:"#666666"}}},b.annotationsOptions,b.bindings.elliott5.annotationsOptions);return this.chart.addAnnotation(a)},steps:[h.updateNthPoint(1),h.updateNthPoint(2),h.updateNthPoint(3),h.updateNthPoint(4),h.updateNthPoint(5)]},measureX:{className:"highcharts-measure-x",start:function(a){a=this.chart.pointer.getCoordinates(a);var b=this.chart.options.navigation;a=p({langKey:"measure",type:"measure",typeOptions:{selectType:"x",point:{x:a.xAxis[0].value, +y:a.yAxis[0].value,xAxis:0,yAxis:0},crosshairX:{strokeWidth:1,stroke:"#000000"},crosshairY:{enabled:!1,strokeWidth:0,stroke:"#000000"},background:{width:0,height:0,strokeWidth:0,stroke:"#ffffff"}},labelOptions:{style:{color:"#666666"}}},b.annotationsOptions,b.bindings.measureX.annotationsOptions);return this.chart.addAnnotation(a)},steps:[h.updateRectSize]},measureY:{className:"highcharts-measure-y",start:function(a){a=this.chart.pointer.getCoordinates(a);var b=this.chart.options.navigation;a=p({langKey:"measure", +type:"measure",typeOptions:{selectType:"y",point:{x:a.xAxis[0].value,y:a.yAxis[0].value,xAxis:0,yAxis:0},crosshairX:{enabled:!1,strokeWidth:0,stroke:"#000000"},crosshairY:{strokeWidth:1,stroke:"#000000"},background:{width:0,height:0,strokeWidth:0,stroke:"#ffffff"}},labelOptions:{style:{color:"#666666"}}},b.annotationsOptions,b.bindings.measureY.annotationsOptions);return this.chart.addAnnotation(a)},steps:[h.updateRectSize]},measureXY:{className:"highcharts-measure-xy",start:function(a){a=this.chart.pointer.getCoordinates(a); +var b=this.chart.options.navigation;a=p({langKey:"measure",type:"measure",typeOptions:{selectType:"xy",point:{x:a.xAxis[0].value,y:a.yAxis[0].value,xAxis:0,yAxis:0},background:{width:0,height:0,strokeWidth:10},crosshairX:{strokeWidth:1,stroke:"#000000"},crosshairY:{strokeWidth:1,stroke:"#000000"}},labelOptions:{style:{color:"#666666"}}},b.annotationsOptions,b.bindings.measureXY.annotationsOptions);return this.chart.addAnnotation(a)},steps:[h.updateRectSize]},fibonacci:{className:"highcharts-fibonacci", +start:function(a){a=this.chart.pointer.getCoordinates(a);var b=this.chart.options.navigation;a=p({langKey:"fibonacci",type:"fibonacci",typeOptions:{points:[{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value,y:a.yAxis[0].value}]},labelOptions:{style:{color:"#666666"}}},b.annotationsOptions,b.bindings.fibonacci.annotationsOptions);return this.chart.addAnnotation(a)},steps:[h.updateNthPoint(1),h.updateHeight]},parallelChannel:{className:"highcharts-parallel-channel",start:function(a){a=this.chart.pointer.getCoordinates(a); +var b=this.chart.options.navigation;a=p({langKey:"parallelChannel",type:"tunnel",typeOptions:{points:[{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value,y:a.yAxis[0].value}]}},b.annotationsOptions,b.bindings.parallelChannel.annotationsOptions);return this.chart.addAnnotation(a)},steps:[h.updateNthPoint(1),h.updateHeight]},pitchfork:{className:"highcharts-pitchfork",start:function(a){a=this.chart.pointer.getCoordinates(a);var b=this.chart.options.navigation;a=p({langKey:"pitchfork",type:"pitchfork", +typeOptions:{points:[{x:a.xAxis[0].value,y:a.yAxis[0].value,controlPoint:{style:{fill:"red"}}},{x:a.xAxis[0].value,y:a.yAxis[0].value},{x:a.xAxis[0].value,y:a.yAxis[0].value}],innerBackground:{fill:"rgba(100, 170, 255, 0.8)"}},shapeOptions:{strokeWidth:2}},b.annotationsOptions,b.bindings.pitchfork.annotationsOptions);return this.chart.addAnnotation(a)},steps:[h.updateNthPoint(1),h.updateNthPoint(2)]},verticalCounter:{className:"highcharts-vertical-counter",start:function(a){a=h.attractToPoint(a,this.chart); +var b=this.chart.options.navigation,c=v(this.verticalCounter)?this.verticalCounter:0;a=p({langKey:"verticalCounter",type:"verticalLine",typeOptions:{point:{x:a.x,y:a.y,xAxis:a.xAxis,yAxis:a.yAxis},label:{offset:a.below?40:-40,text:c.toString()}},labelOptions:{style:{color:"#666666",fontSize:"11px"}},shapeOptions:{stroke:"rgba(0, 0, 0, 0.75)",strokeWidth:1}},b.annotationsOptions,b.bindings.verticalCounter.annotationsOptions);a=this.chart.addAnnotation(a);a.options.events.click.call(a,{})}},verticalLabel:{className:"highcharts-vertical-label", +start:function(a){a=h.attractToPoint(a,this.chart);var b=this.chart.options.navigation;a=p({langKey:"verticalLabel",type:"verticalLine",typeOptions:{point:{x:a.x,y:a.y,xAxis:a.xAxis,yAxis:a.yAxis},label:{offset:a.below?40:-40}},labelOptions:{style:{color:"#666666",fontSize:"11px"}},shapeOptions:{stroke:"rgba(0, 0, 0, 0.75)",strokeWidth:1}},b.annotationsOptions,b.bindings.verticalLabel.annotationsOptions);a=this.chart.addAnnotation(a);a.options.events.click.call(a,{})}},verticalArrow:{className:"highcharts-vertical-arrow", +start:function(a){a=h.attractToPoint(a,this.chart);var b=this.chart.options.navigation;a=p({langKey:"verticalArrow",type:"verticalLine",typeOptions:{point:{x:a.x,y:a.y,xAxis:a.xAxis,yAxis:a.yAxis},label:{offset:a.below?40:-40,format:" "},connector:{fill:"none",stroke:a.below?"red":"green"}},shapeOptions:{stroke:"rgba(0, 0, 0, 0.75)",strokeWidth:1}},b.annotationsOptions,b.bindings.verticalArrow.annotationsOptions);a=this.chart.addAnnotation(a);a.options.events.click.call(a,{})}},flagCirclepin:{className:"highcharts-flag-circlepin", +start:h.addFlagFromForm("circlepin")},flagDiamondpin:{className:"highcharts-flag-diamondpin",start:h.addFlagFromForm("flag")},flagSquarepin:{className:"highcharts-flag-squarepin",start:h.addFlagFromForm("squarepin")},flagSimplepin:{className:"highcharts-flag-simplepin",start:h.addFlagFromForm("nopin")},zoomX:{className:"highcharts-zoom-x",init:function(a){this.chart.update({chart:{zoomType:"x"}});t(this,"deselectButton",{button:a})}},zoomY:{className:"highcharts-zoom-y",init:function(a){this.chart.update({chart:{zoomType:"y"}}); +t(this,"deselectButton",{button:a})}},zoomXY:{className:"highcharts-zoom-xy",init:function(a){this.chart.update({chart:{zoomType:"xy"}});t(this,"deselectButton",{button:a})}},seriesTypeLine:{className:"highcharts-series-type-line",init:function(a){this.chart.series[0].update({type:"line",useOhlcData:!0});t(this,"deselectButton",{button:a})}},seriesTypeOhlc:{className:"highcharts-series-type-ohlc",init:function(a){this.chart.series[0].update({type:"ohlc"});t(this,"deselectButton",{button:a})}},seriesTypeCandlestick:{className:"highcharts-series-type-candlestick", +init:function(a){this.chart.series[0].update({type:"candlestick"});t(this,"deselectButton",{button:a})}},fullScreen:{className:"highcharts-full-screen",init:function(a){this.chart.fullscreen.toggle();t(this,"deselectButton",{button:a})}},currentPriceIndicator:{className:"highcharts-current-price-indicator",init:function(a){var b=this.chart,c=b.series[0],e=c.options,k=e.lastVisiblePrice&&e.lastVisiblePrice.enabled;e=e.lastPrice&&e.lastPrice.enabled;b=b.stockTools;var f=b.getIconsURL();b&&b.guiEnabled&& +(a.firstChild.style["background-image"]=e?'url("'+f+'current-price-show.svg")':'url("'+f+'current-price-hide.svg")');c.update({lastPrice:{enabled:!e,color:"red"},lastVisiblePrice:{enabled:!k,label:{enabled:!0}}});t(this,"deselectButton",{button:a})}},indicators:{className:"highcharts-indicators",init:function(){var a=this;t(a,"showPopup",{formType:"indicators",options:{},onSubmit:function(b){a.utils.manageIndicators.call(a,b)}})}},toggleAnnotations:{className:"highcharts-toggle-annotations",init:function(a){var b= +this.chart,c=b.stockTools,e=c.getIconsURL();this.toggledAnnotations=!this.toggledAnnotations;(b.annotations||[]).forEach(function(a){a.setVisibility(!this.toggledAnnotations)},this);c&&c.guiEnabled&&(a.firstChild.style["background-image"]=this.toggledAnnotations?'url("'+e+'annotations-hidden.svg")':'url("'+e+'annotations-visible.svg")');t(this,"deselectButton",{button:a})}},saveChart:{className:"highcharts-save-chart",init:function(a){var b=this.chart,c=[],e=[],k=[],f=[];b.annotations.forEach(function(a, +b){c[b]=a.userOptions});b.series.forEach(function(a){a.is("sma")?e.push(a.userOptions):"flags"===a.type&&k.push(a.userOptions)});b.yAxis.forEach(function(a){h.isNotNavigatorYAxis(a)&&f.push(a.options)});m.win.localStorage.setItem("highcharts-chart",JSON.stringify({annotations:c,indicators:e,flags:k,yAxes:f}));t(this,"deselectButton",{button:a})}}};m.setOptions({navigation:{bindings:g}});l.prototype.utils=p(h,l.prototype.utils)});q(g,"modules/stock-tools-gui.js",[g["parts/Globals.js"],g["parts/Utilities.js"], +g["annotations/navigationBindings.js"]],function(g,l,q){var n=l.addEvent,m=l.createElement,y=l.css,t=l.extend,u=l.fireEvent,p=l.getStyle,z=l.isArray,w=l.merge,h=l.pick;g.setOptions({lang:{stockTools:{gui:{simpleShapes:"Simple shapes",lines:"Lines",crookedLines:"Crooked lines",measure:"Measure",advanced:"Advanced",toggleAnnotations:"Toggle annotations",verticalLabels:"Vertical labels",flags:"Flags",zoomChange:"Zoom change",typeChange:"Type change",saveChart:"Save chart",indicators:"Indicators",currentPriceIndicator:"Current Price Indicators", +zoomX:"Zoom X",zoomY:"Zoom Y",zoomXY:"Zooom XY",fullScreen:"Fullscreen",typeOHLC:"OHLC",typeLine:"Line",typeCandlestick:"Candlestick",circle:"Circle",label:"Label",rectangle:"Rectangle",flagCirclepin:"Flag circle",flagDiamondpin:"Flag diamond",flagSquarepin:"Flag square",flagSimplepin:"Flag simple",measureXY:"Measure XY",measureX:"Measure X",measureY:"Measure Y",segment:"Segment",arrowSegment:"Arrow segment",ray:"Ray",arrowRay:"Arrow ray",line:"Line",arrowLine:"Arrow line",horizontalLine:"Horizontal line", +verticalLine:"Vertical line",infinityLine:"Infinity line",crooked3:"Crooked 3 line",crooked5:"Crooked 5 line",elliott3:"Elliott 3 line",elliott5:"Elliott 5 line",verticalCounter:"Vertical counter",verticalLabel:"Vertical label",verticalArrow:"Vertical arrow",fibonacci:"Fibonacci",pitchfork:"Pitchfork",parallelChannel:"Parallel channel"}},navigation:{popup:{circle:"Circle",rectangle:"Rectangle",label:"Label",segment:"Segment",arrowSegment:"Arrow segment",ray:"Ray",arrowRay:"Arrow ray",line:"Line", +arrowLine:"Arrow line",horizontalLine:"Horizontal line",verticalLine:"Vertical line",crooked3:"Crooked 3 line",crooked5:"Crooked 5 line",elliott3:"Elliott 3 line",elliott5:"Elliott 5 line",verticalCounter:"Vertical counter",verticalLabel:"Vertical label",verticalArrow:"Vertical arrow",fibonacci:"Fibonacci",pitchfork:"Pitchfork",parallelChannel:"Parallel channel",infinityLine:"Infinity line",measure:"Measure",measureXY:"Measure XY",measureX:"Measure X",measureY:"Measure Y",flags:"Flags",addButton:"add", +saveButton:"save",editButton:"edit",removeButton:"remove",series:"Series",volume:"Volume",connector:"Connector",innerBackground:"Inner background",outerBackground:"Outer background",crosshairX:"Crosshair X",crosshairY:"Crosshair Y",tunnel:"Tunnel",background:"Background"}}},stockTools:{gui:{enabled:!0,className:"highcharts-bindings-wrapper",toolbarClassName:"stocktools-toolbar",buttons:"indicators separator simpleShapes lines crookedLines measure advanced toggleAnnotations separator verticalLabels flags separator zoomChange fullScreen typeChange separator currentPriceIndicator saveChart".split(" "), +definitions:{separator:{symbol:"separator.svg"},simpleShapes:{items:["label","circle","rectangle"],circle:{symbol:"circle.svg"},rectangle:{symbol:"rectangle.svg"},label:{symbol:"label.svg"}},flags:{items:["flagCirclepin","flagDiamondpin","flagSquarepin","flagSimplepin"],flagSimplepin:{symbol:"flag-basic.svg"},flagDiamondpin:{symbol:"flag-diamond.svg"},flagSquarepin:{symbol:"flag-trapeze.svg"},flagCirclepin:{symbol:"flag-elipse.svg"}},lines:{items:"segment arrowSegment ray arrowRay line arrowLine horizontalLine verticalLine".split(" "), +segment:{symbol:"segment.svg"},arrowSegment:{symbol:"arrow-segment.svg"},ray:{symbol:"ray.svg"},arrowRay:{symbol:"arrow-ray.svg"},line:{symbol:"line.svg"},arrowLine:{symbol:"arrow-line.svg"},verticalLine:{symbol:"vertical-line.svg"},horizontalLine:{symbol:"horizontal-line.svg"}},crookedLines:{items:["elliott3","elliott5","crooked3","crooked5"],crooked3:{symbol:"crooked-3.svg"},crooked5:{symbol:"crooked-5.svg"},elliott3:{symbol:"elliott-3.svg"},elliott5:{symbol:"elliott-5.svg"}},verticalLabels:{items:["verticalCounter", +"verticalLabel","verticalArrow"],verticalCounter:{symbol:"vertical-counter.svg"},verticalLabel:{symbol:"vertical-label.svg"},verticalArrow:{symbol:"vertical-arrow.svg"}},advanced:{items:["fibonacci","pitchfork","parallelChannel"],pitchfork:{symbol:"pitchfork.svg"},fibonacci:{symbol:"fibonacci.svg"},parallelChannel:{symbol:"parallel-channel.svg"}},measure:{items:["measureXY","measureX","measureY"],measureX:{symbol:"measure-x.svg"},measureY:{symbol:"measure-y.svg"},measureXY:{symbol:"measure-xy.svg"}}, +toggleAnnotations:{symbol:"annotations-visible.svg"},currentPriceIndicator:{symbol:"current-price-show.svg"},indicators:{symbol:"indicators.svg"},zoomChange:{items:["zoomX","zoomY","zoomXY"],zoomX:{symbol:"zoom-x.svg"},zoomY:{symbol:"zoom-y.svg"},zoomXY:{symbol:"zoom-xy.svg"}},typeChange:{items:["typeOHLC","typeLine","typeCandlestick"],typeOHLC:{symbol:"series-ohlc.svg"},typeLine:{symbol:"series-line.svg"},typeCandlestick:{symbol:"series-candlestick.svg"}},fullScreen:{symbol:"fullscreen.svg"},saveChart:{symbol:"save-chart.svg"}}}}}); +n(g.Chart,"afterGetContainer",function(){this.setStockTools()});n(g.Chart,"getMargins",function(){var a=this.stockTools&&this.stockTools.listWrapper;(a=a&&(a.startWidth+p(a,"padding-left")+p(a,"padding-right")||a.offsetWidth))&&ag.offsetHeight&&f.offsetTop>t||(t=0),y(q,{top:-t+"px",left:d+3+"px"}),f.className+=" highcharts-current",h.startWidth=g.offsetWidth,h.style.width=h.startWidth+p(h,"padding-left")+q.offsetWidth+3+"px")}))};a.prototype.addSubmenuItems=function(a,c){var b= +this,k=this.submenu,f=this.lang,d=this.listWrapper,h;c.items.forEach(function(e){h=b.addButton(k,c,e,f);b.eventsToUnbind.push(n(h.mainButton,"click",function(){b.switchSymbol(this,a,!0);d.style.width=d.startWidth+"px";k.style.display="none"}))});var g=k.querySelectorAll("li > .highcharts-menu-item-btn")[0];b.switchSymbol(g,!1)};a.prototype.eraseActiveButtons=function(a,c,e){[].forEach.call(a,function(a){a!==c&&(a.classList.remove("highcharts-current"),a.classList.remove("highcharts-active"),e=a.querySelectorAll(".highcharts-submenu-wrapper"), +0this.wrapper.offsetHeight- +50?this.arrowWrapper.style.display="block":(this.toolbar.style.marginTop="0px",this.arrowWrapper.style.display="none")};a.prototype.showHideToolbar=function(){var a=this.chart,c=this.wrapper,e=this.listWrapper,g=this.submenu,f=this.visible,d;this.showhideBtn=d=m("div",{className:"highcharts-toggle-toolbar highcharts-arrow-left"},null,c);d.style["background-image"]="url("+this.iconsURL+"arrow-right.svg)";f?(c.style.height="100%",d.style.top=p(e,"padding-top")+"px",d.style.left=c.offsetWidth+p(e,"padding-left")+ +"px"):(g&&(g.style.display="none"),d.style.left="0px",this.visible=f=!1,e.classList.add("highcharts-hide"),d.classList.toggle("highcharts-arrow-right"),c.style.height=d.offsetHeight+"px");this.eventsToUnbind.push(n(d,"click",function(){a.update({stockTools:{gui:{visible:!f,placed:!0}}})}))};a.prototype.switchSymbol=function(a,c){var b=a.parentNode,g=b.classList.value;b=b.parentNode.parentNode;b.className="";g&&b.classList.add(g.trim());b.querySelectorAll(".highcharts-menu-item-btn")[0].style["background-image"]= +a.style["background-image"];c&&this.selectButton(b)};a.prototype.selectButton=function(a){0<=a.className.indexOf("highcharts-active")?a.classList.remove("highcharts-active"):a.classList.add("highcharts-active")};a.prototype.unselectAllButtons=function(a){var b=a.parentNode.querySelectorAll(".highcharts-active");[].forEach.call(b,function(b){b!==a&&b.classList.remove("highcharts-active")})};a.prototype.update=function(a){w(!0,this.chart.options.stockTools,a);this.destroy();this.chart.setStockTools(a); +this.chart.navigationBindings&&this.chart.navigationBindings.update()};a.prototype.destroy=function(){var a=this.wrapper,c=a&&a.parentNode;this.eventsToUnbind.forEach(function(a){a()});c&&c.removeChild(a);this.chart.isDirtyBox=!0;this.chart.redraw()};a.prototype.redraw=function(){this.showHideNavigatorion()};a.prototype.getIconsURL=function(){return this.chart.options.navigation.iconsURL||this.options.iconsURL||"https://code.highcharts.com/8.1.0/gfx/stock-icons/"};return a}();l.prototype.classMapping= +{circle:"highcharts-circle-annotation",rectangle:"highcharts-rectangle-annotation",label:"highcharts-label-annotation",segment:"highcharts-segment",arrowSegment:"highcharts-arrow-segment",ray:"highcharts-ray",arrowRay:"highcharts-arrow-ray",line:"highcharts-infinity-line",arrowLine:"highcharts-arrow-infinity-line",verticalLine:"highcharts-vertical-line",horizontalLine:"highcharts-horizontal-line",crooked3:"highcharts-crooked3",crooked5:"highcharts-crooked5",elliott3:"highcharts-elliott3",elliott5:"highcharts-elliott5", +pitchfork:"highcharts-pitchfork",fibonacci:"highcharts-fibonacci",parallelChannel:"highcharts-parallel-channel",measureX:"highcharts-measure-x",measureY:"highcharts-measure-y",measureXY:"highcharts-measure-xy",verticalCounter:"highcharts-vertical-counter",verticalLabel:"highcharts-vertical-label",verticalArrow:"highcharts-vertical-arrow",currentPriceIndicator:"highcharts-current-price-indicator",indicators:"highcharts-indicators",flagCirclepin:"highcharts-flag-circlepin",flagDiamondpin:"highcharts-flag-diamondpin", +flagSquarepin:"highcharts-flag-squarepin",flagSimplepin:"highcharts-flag-simplepin",zoomX:"highcharts-zoom-x",zoomY:"highcharts-zoom-y",zoomXY:"highcharts-zoom-xy",typeLine:"highcharts-series-type-line",typeOHLC:"highcharts-series-type-ohlc",typeCandlestick:"highcharts-series-type-candlestick",fullScreen:"highcharts-full-screen",toggleAnnotations:"highcharts-toggle-annotations",saveChart:"highcharts-save-chart",separator:"highcharts-separator"};t(g.Chart.prototype,{setStockTools:function(a){var b= +this.options,c=b.lang;a=w(b.stockTools&&b.stockTools.gui,a&&a.gui);this.stockTools=new g.Toolbar(a,c.stockTools&&c.stockTools.gui,this);this.stockTools.guiEnabled&&(this.isDirtyBox=!0)}});n(q,"selectButton",function(a){var b=a.button,c=this.chart.stockTools;c&&c.guiEnabled&&(c.unselectAllButtons(a.button),0<=b.parentNode.className.indexOf("highcharts-submenu-wrapper")&&(b=b.parentNode.parentNode),c.selectButton(b))});n(q,"deselectButton",function(a){a=a.button;var b=this.chart.stockTools;b&&b.guiEnabled&& +(0<=a.parentNode.className.indexOf("highcharts-submenu-wrapper")&&(a=a.parentNode.parentNode),b.selectButton(a))});g.Toolbar=l;return g.Toolbar});q(g,"masters/modules/stock-tools.src.js",[],function(){})}); +//# sourceMappingURL=stock-tools.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/stock-tools.js.map b/librerias/gantt/code/modules/stock-tools.js.map new file mode 100644 index 0000000..a445abf --- /dev/null +++ b/librerias/gantt/code/modules/stock-tools.js.map @@ -0,0 +1 @@ +{"version":3,"file":"stock-tools.js.map","lineCount":93,"mappings":"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","sources":["stock-tools.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","chartNavigation","initUpdate","chart","navigation","updates","update","options","redraw","forEach","updateConfig","call","context","addUpdate","push","H","U","chartNavigationMixin","selectableAnnotation","annotationType","originalClick","prototype","defaultOptions","events","click","merge","selectAndshowPopup","event","annotation","navigationBindings","prevAnnotation","activeAnnotation","deselectAnnotation","setControlPointsVisibility","fireEvent","formType","annotationToFields","onSubmit","data","config","actionType","removeAnnotation","fieldsToOptions","fields","typeOptions","type","crosshairY","enabled","strokeWidth","crosshairX","addEvent","attr","format","isArray","isFunction","isNumber","isObject","objectEach","pick","doc","win","NavigationBindings","selectedButton","boundClassNames","eventsToUnbind","container","getElementsByClassName","bindingsClassName","initEvents","NavigationBindings.prototype.initEvents","bindingsContainer","bindings","value","className","subContainer","getButtonEvents","bindingsButtonClick","button","callback","eventName","e","cancelClick","isInsidePlot","chartX","plotLeft","chartY","plotTop","bindingsChartClick","bindingsContainerMouseMove","NavigationBindings.prototype.initUpdate","NavigationBindings.prototype.bindingsButtonClick","clickEvent","selectedButtonElement","nextEvent","currentUserDetails","coll","mouseMoveEvent","init","start","steps","renderer","boxWrapper","addClass","NavigationBindings.prototype.bindingsChartClick","svgContainer","ElementProto","Element","elementMatches","matches","msMatchesSelector","webkitMatchesSelector","ret","closest","el","s","parentElement","parentNode","nodeType","stepIndex","removeClass","end","NavigationBindings.prototype.bindingsContainerMouseMove","_container","moveEvent","NavigationBindings.prototype.fieldsToOptions","field","parsedValue","parseFloat","split","parent","pathLength","length","match","name","index","nextName","NavigationBindings.prototype.deselectAnnotation","NavigationBindings.prototype.annotationToFields","traverse","option","key","parentEditables","nonEditables","indexOf","arrayOption","i","nestedOption","nestedKey","nestedEditables","nextParent","labels","points","toString","getFieldType","editables","annotationsEditable","nestedOptions","utils","shapes","itemType","annotationsNonEditable","langKey","visualOptions","typeOption","typeKey","getClickedClassNames","NavigationBindings.prototype.getClickedClassNames","element","target","classNames","elemClassName","concat","map","NavigationBindings.prototype.getButtonEvents","NavigationBindings.prototype.update","removeEvents","NavigationBindings.prototype.removeEvents","unbinder","destroy","NavigationBindings.prototype.destroy","labelOptions","label","style","background","innerBackground","outerBackground","shapeOptions","line","backgroundColors","connector","circle","verticalLine","measure","fibonacci","tunnel","pitchfork","rect","crookedLine","basicAnnotation","rectangle","bindingsUtils","updateRectSize","coords","pointer","getCoordinates","width","xAxis","point","x","height","y","yAxis","inverted","Chart","initNavigationBindings","H.Chart.prototype.initNavigationBindings","Annotation","types","setOptions","lang","popup","simpleShapes","lines","fill","stroke","title","backgroundColor","borderColor","borderRadius","borderWidth","padding","fontSize","color","circleAnnotation","addAnnotation","r","annotationsOptions","toPixels","Math","max","distance","sqrt","pow","rectangleAnnotation","labelAnnotation","overflow","crop","correctFloat","defined","extend","uniqueKey","addFlagFromForm","bindingsUtils.addFlagFromForm","toolbar","stockTools","attractToPoint","seriesOptions","onSeries","series","id","shape","pointConfig","updated","remove","guiEnabled","addSeries","manageIndicators","bindingsUtils.manageIndicators","seriesConfig","linkedTo","indicatorsWithVolume","indicatorsWithAxes","get","seriesId","linkedSeries","resizeYAxes","addAxis","offset","opposite","text","tickPixelInterval","showLastLabel","align","params","volumeSeriesID","filter","updateHeight","bindingsUtils.updateHeight","bindingsUtils.attractToPoint","distX","Number","MAX_VALUE","closestPoint","abs","below","isNotNavigatorYAxis","bindingsUtils.isNotNavigatorYAxis","axis","userOptions","updateNthPoint","bindingsUtils.updateNthPoint","startIndex","getYAxisPositions","yAxes","plotHeight","defaultHeight","isPercentage","prop","allAxesHeight","positions","top","getYAxisResizers","resizers","_yAxis","nextYAxis","controlledAxis","next","allAxesLength","changedSpace","recalculateYAxisPositions","position","resize","modifyHeight","adder","prevPosition","stockToolsBindings","segment","arrowSegment","markerEnd","ray","arrowRay","infinityLine","arrowInfinityLine","horizontalLine","draggable","crooked3","crooked5","elliott3","elliott5","measureX","selectType","measureY","measureXY","parallelChannel","controlPoint","verticalCounter","verticalLabel","verticalArrow","flagCirclepin","flagDiamondpin","flagSquarepin","flagSimplepin","zoomX","zoomType","zoomY","zoomXY","seriesTypeLine","useOhlcData","seriesTypeOhlc","seriesTypeCandlestick","fullScreen","fullscreen","toggle","currentPriceIndicator","lastVisiblePrice","lastPrice","gui","iconsURL","getIconsURL","firstChild","indicators","toggleAnnotations","toggledAnnotations","annotations","setVisibility","saveChart","flags","is","localStorage","setItem","JSON","stringify","createElement","css","getStyle","crookedLines","advanced","verticalLabels","zoomChange","typeChange","typeOHLC","typeLine","typeCandlestick","arrowLine","addButton","saveButton","editButton","removeButton","volume","toolbarClassName","buttons","definitions","separator","symbol","items","setStockTools","listWrapper","offsetWidth","startWidth","plotWidth","Toolbar","langOptions","wrapper","submenu","showhideBtn","arrowWrapper","arrowUp","arrowDown","visible","placed","createHTML","showHideNavigatorion","Toolbar.prototype.init","_self","guiOptions","addSubmenu","defs","allButtons","childNodes","btnName","buttonWrapper","eraseActiveButtons","Toolbar.prototype.addSubmenu","parentBtn","submenuArrow","buttonWidth","menuWrapper","topMargin","submenuWrapper","UL","addSubmenuItems","stopPropagation","classList","display","offsetHeight","offsetTop","left","Toolbar.prototype.addSubmenuItems","submenuBtn","mainButton","switchSymbol","firstSubmenuItem","querySelectorAll","Toolbar.prototype.eraseActiveButtons","currentButton","submenuItems","btn","Toolbar.prototype.addButton","btnOptions","userClassName","LI","classMapping","SPAN","addNavigation","Toolbar.prototype.addNavigation","stockToolbar","DIV","insertBefore","scrollButtons","Toolbar.prototype.scrollButtons","targetY","step","Toolbar.prototype.createHTML","showHideToolbar","Toolbar.prototype.showHideNavigatorion","marginTop","Toolbar.prototype.showHideToolbar","add","Toolbar.prototype.switchSymbol","buttonWrapperClass","mainNavButton","trim","selectButton","Toolbar.prototype.selectButton","activeClass","unselectAllButtons","Toolbar.prototype.unselectAllButtons","activeButtons","activeBtn","Toolbar.prototype.update","Toolbar.prototype.destroy","stockToolsDiv","removeChild","isDirtyBox","Toolbar.prototype.redraw","Toolbar.prototype.getIconsURL","chartOptions"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/stock-tools.src.js b/librerias/gantt/code/modules/stock-tools.src.js new file mode 100644 index 0000000..097a2b6 --- /dev/null +++ b/librerias/gantt/code/modules/stock-tools.src.js @@ -0,0 +1,4131 @@ +/** + * @license Highstock JS v8.1.0 (2020-05-05) + * + * Advanced Highstock tools + * + * (c) 2010-2019 Highsoft AS + * Author: Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/stock-tools', ['highcharts', 'highcharts/modules/stock'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'mixins/navigation.js', [], function () { + /** + * + * (c) 2010-2018 Paweł Fus + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var chartNavigation = { + /** + * Initializes `chart.navigation` object which delegates `update()` methods + * to all other common classes (used in exporting and navigationBindings). + * + * @private + * @param {Highcharts.Chart} chart + * The chart instance. + * @return {void} + */ + initUpdate: function (chart) { + if (!chart.navigation) { + chart.navigation = { + updates: [], + update: function (options, redraw) { + this.updates.forEach(function (updateConfig) { + updateConfig.update.call(updateConfig.context, options, redraw); + }); + } + }; + } + }, + /** + * Registers an `update()` method in the `chart.navigation` object. + * + * @private + * @param {Highcharts.ChartNavigationUpdateFunction} update + * The `update()` method that will be called in `chart.update()`. + * @param {Highcharts.Chart} chart + * The chart instance. `update()` will use that as a context + * (`this`). + * @return {void} + */ + addUpdate: function (update, chart) { + if (!chart.navigation) { + this.initUpdate(chart); + } + chart.navigation.updates.push({ + update: update, + context: chart + }); + } + }; + + return chartNavigation; + }); + _registerModule(_modules, 'annotations/navigationBindings.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['mixins/navigation.js']], function (H, U, chartNavigationMixin) { + /* * + * + * (c) 2009-2017 Highsoft, Black Label + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * A config object for navigation bindings in annotations. + * + * @interface Highcharts.NavigationBindingsOptionsObject + */ /** + * ClassName of the element for a binding. + * @name Highcharts.NavigationBindingsOptionsObject#className + * @type {string|undefined} + */ /** + * Last event to be fired after last step event. + * @name Highcharts.NavigationBindingsOptionsObject#end + * @type {Function|undefined} + */ /** + * Initial event, fired on a button click. + * @name Highcharts.NavigationBindingsOptionsObject#init + * @type {Function|undefined} + */ /** + * Event fired on first click on a chart. + * @name Highcharts.NavigationBindingsOptionsObject#start + * @type {Function|undefined} + */ /** + * Last event to be fired after last step event. Array of step events to be + * called sequentially after each user click. + * @name Highcharts.NavigationBindingsOptionsObject#steps + * @type {Array|undefined} + */ + var addEvent = U.addEvent, attr = U.attr, extend = U.extend, format = U.format, fireEvent = U.fireEvent, isArray = U.isArray, isFunction = U.isFunction, isNumber = U.isNumber, isObject = U.isObject, merge = U.merge, objectEach = U.objectEach, pick = U.pick; + var doc = H.doc, win = H.win, PREFIX = 'highcharts-'; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * IE 9-11 polyfill for Element.closest(): + * @private + */ + function closestPolyfill(el, s) { + var ElementProto = win.Element.prototype, elementMatches = ElementProto.matches || + ElementProto.msMatchesSelector || + ElementProto.webkitMatchesSelector, ret = null; + if (ElementProto.closest) { + ret = ElementProto.closest.call(el, s); + } + else { + do { + if (elementMatches.call(el, s)) { + return el; + } + el = el.parentElement || el.parentNode; + } while (el !== null && el.nodeType === 1); + } + return ret; + } + /** + * @private + * @interface bindingsUtils + */ + var bindingsUtils = { + /** + * Update size of background (rect) in some annotations: Measure, Simple + * Rect. + * + * @private + * @function Highcharts.NavigationBindingsUtilsObject.updateRectSize + * + * @param {Highcharts.PointerEventObject} event + * Normalized browser event + * + * @param {Highcharts.Annotation} annotation + * Annotation to be updated + */ + updateRectSize: function (event, annotation) { + var chart = annotation.chart, options = annotation.options.typeOptions, coords = chart.pointer.getCoordinates(event), width = coords.xAxis[0].value - options.point.x, height = options.point.y - coords.yAxis[0].value; + annotation.update({ + typeOptions: { + background: { + width: chart.inverted ? height : width, + height: chart.inverted ? width : height + } + } + }); + }, + /** + * Get field type according to value + * + * @private + * @function Highcharts.NavigationBindingsUtilsObject.getFieldType + * + * @param {'boolean'|'number'|'string'} value + * Atomic type (one of: string, number, boolean) + * + * @return {'checkbox'|'number'|'text'} + * Field type (one of: text, number, checkbox) + */ + getFieldType: function (value) { + return { + 'string': 'text', + 'number': 'number', + 'boolean': 'checkbox' + }[typeof value]; + } + }; + /** + * @private + */ + var NavigationBindings = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function NavigationBindings(chart, options) { + this.boundClassNames = void 0; + this.selectedButton = void 0; + this.chart = chart; + this.options = options; + this.eventsToUnbind = []; + this.container = doc.getElementsByClassName(this.options.bindingsClassName || ''); + } + // Private properties added by bindings: + // Active (selected) annotation that is editted through popup/forms + // activeAnnotation: Annotation + // Holder for current step, used on mouse move to update bound object + // mouseMoveEvent: function () {} + // Next event in `step` array to be called on chart's click + // nextEvent: function () {} + // Index in the `step` array of the current event + // stepIndex: 0 + // Flag to determine if current binding has steps + // steps: true|false + // Bindings holder for all events + // selectedButton: {} + // Holder for user options, returned from `start` event, and passed on to + // `step`'s' and `end`. + // currentUserDetails: {} + /* * + * + * Functions + * + * */ + /** + * Initi all events conencted to NavigationBindings. + * + * @private + * @function Highcharts.NavigationBindings#initEvents + */ + NavigationBindings.prototype.initEvents = function () { + var navigation = this, chart = navigation.chart, bindingsContainer = navigation.container, options = navigation.options; + // Shorthand object for getting events for buttons: + navigation.boundClassNames = {}; + objectEach((options.bindings || {}), function (value) { + navigation.boundClassNames[value.className] = value; + }); + // Handle multiple containers with the same class names: + [].forEach.call(bindingsContainer, function (subContainer) { + navigation.eventsToUnbind.push(addEvent(subContainer, 'click', function (event) { + var bindings = navigation.getButtonEvents(subContainer, event); + if (bindings) { + navigation.bindingsButtonClick(bindings.button, bindings.events, event); + } + })); + }); + objectEach(options.events || {}, function (callback, eventName) { + if (isFunction(callback)) { + navigation.eventsToUnbind.push(addEvent(navigation, eventName, callback)); + } + }); + navigation.eventsToUnbind.push(addEvent(chart.container, 'click', function (e) { + if (!chart.cancelClick && + chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop)) { + navigation.bindingsChartClick(this, e); + } + })); + navigation.eventsToUnbind.push(addEvent(chart.container, 'mousemove', function (e) { + navigation.bindingsContainerMouseMove(this, e); + })); + }; + /** + * Common chart.update() delegation, shared between bindings and exporting. + * + * @private + * @function Highcharts.NavigationBindings#initUpdate + */ + NavigationBindings.prototype.initUpdate = function () { + var navigation = this; + chartNavigationMixin.addUpdate(function (options) { + navigation.update(options); + }, this.chart); + }; + /** + * Hook for click on a button, method selcts/unselects buttons, + * then calls `bindings.init` callback. + * + * @private + * @function Highcharts.NavigationBindings#bindingsButtonClick + * + * @param {Highcharts.HTMLDOMElement} [button] + * Clicked button + * + * @param {object} events + * Events passed down from bindings (`init`, `start`, `step`, `end`) + * + * @param {Highcharts.PointerEventObject} clickEvent + * Browser's click event + */ + NavigationBindings.prototype.bindingsButtonClick = function (button, events, clickEvent) { + var navigation = this, chart = navigation.chart; + if (navigation.selectedButtonElement) { + fireEvent(navigation, 'deselectButton', { button: navigation.selectedButtonElement }); + if (navigation.nextEvent) { + // Remove in-progress annotations adders: + if (navigation.currentUserDetails && + navigation.currentUserDetails.coll === 'annotations') { + chart.removeAnnotation(navigation.currentUserDetails); + } + navigation.mouseMoveEvent = navigation.nextEvent = false; + } + } + navigation.selectedButton = events; + navigation.selectedButtonElement = button; + fireEvent(navigation, 'selectButton', { button: button }); + // Call "init" event, for example to open modal window + if (events.init) { + events.init.call(navigation, button, clickEvent); + } + if (events.start || events.steps) { + chart.renderer.boxWrapper.addClass(PREFIX + 'draw-mode'); + } + }; + /** + * Hook for click on a chart, first click on a chart calls `start` event, + * then on all subsequent clicks iterate over `steps` array. + * When finished, calls `end` event. + * + * @private + * @function Highcharts.NavigationBindings#bindingsChartClick + * + * @param {Highcharts.Chart} chart + * Chart that click was performed on. + * + * @param {Highcharts.PointerEventObject} clickEvent + * Browser's click event. + */ + NavigationBindings.prototype.bindingsChartClick = function (chart, clickEvent) { + var navigation = this, chart = navigation.chart, selectedButton = navigation.selectedButton, svgContainer = chart.renderer.boxWrapper; + // Click outside popups, should close them and deselect the annotation + if (navigation.activeAnnotation && + !clickEvent.activeAnnotation && + // Element could be removed in the child action, e.g. button + clickEvent.target.parentNode && + // TO DO: Polyfill for IE11? + !closestPolyfill(clickEvent.target, '.' + PREFIX + 'popup')) { + fireEvent(navigation, 'closePopup'); + navigation.deselectAnnotation(); + } + if (!selectedButton || !selectedButton.start) { + return; + } + if (!navigation.nextEvent) { + // Call init method: + navigation.currentUserDetails = selectedButton.start.call(navigation, clickEvent); + // If steps exists (e.g. Annotations), bind them: + if (selectedButton.steps) { + navigation.stepIndex = 0; + navigation.steps = true; + navigation.mouseMoveEvent = navigation.nextEvent = + selectedButton.steps[navigation.stepIndex]; + } + else { + fireEvent(navigation, 'deselectButton', { button: navigation.selectedButtonElement }); + svgContainer.removeClass(PREFIX + 'draw-mode'); + navigation.steps = false; + navigation.selectedButton = null; + // First click is also the last one: + if (selectedButton.end) { + selectedButton.end.call(navigation, clickEvent, navigation.currentUserDetails); + } + } + } + else { + navigation.nextEvent(clickEvent, navigation.currentUserDetails); + if (navigation.steps) { + navigation.stepIndex++; + if (selectedButton.steps[navigation.stepIndex]) { + // If we have more steps, bind them one by one: + navigation.mouseMoveEvent = navigation.nextEvent = + selectedButton.steps[navigation.stepIndex]; + } + else { + fireEvent(navigation, 'deselectButton', { button: navigation.selectedButtonElement }); + svgContainer.removeClass(PREFIX + 'draw-mode'); + // That was the last step, call end(): + if (selectedButton.end) { + selectedButton.end.call(navigation, clickEvent, navigation.currentUserDetails); + } + navigation.nextEvent = false; + navigation.mouseMoveEvent = false; + navigation.selectedButton = null; + } + } + } + }; + /** + * Hook for mouse move on a chart's container. It calls current step. + * + * @private + * @function Highcharts.NavigationBindings#bindingsContainerMouseMove + * + * @param {Highcharts.HTMLDOMElement} container + * Chart's container. + * + * @param {global.Event} moveEvent + * Browser's move event. + */ + NavigationBindings.prototype.bindingsContainerMouseMove = function (_container, moveEvent) { + if (this.mouseMoveEvent) { + this.mouseMoveEvent(moveEvent, this.currentUserDetails); + } + }; + /** + * Translate fields (e.g. `params.period` or `marker.styles.color`) to + * Highcharts options object (e.g. `{ params: { period } }`). + * + * @private + * @function Highcharts.NavigationBindings#fieldsToOptions + * + * @param {Highcharts.Dictionary} fields + * Fields from popup form. + * + * @param {T} config + * Default config to be modified. + * + * @return {T} + * Modified config + */ + NavigationBindings.prototype.fieldsToOptions = function (fields, config) { + objectEach(fields, function (value, field) { + var parsedValue = parseFloat(value), path = field.split('.'), parent = config, pathLength = path.length - 1; + // If it's a number (not "format" options), parse it: + if (isNumber(parsedValue) && + !value.match(/px/g) && + !field.match(/format/g)) { + value = parsedValue; + } + // Remove empty strings or values like 0 + if (value !== '' && value !== 'undefined') { + path.forEach(function (name, index) { + var nextName = pick(path[index + 1], ''); + if (pathLength === index) { + // Last index, put value: + parent[name] = value; + } + else if (!parent[name]) { + // Create middle property: + parent[name] = nextName.match(/\d/g) ? [] : {}; + parent = parent[name]; + } + else { + // Jump into next property + parent = parent[name]; + } + }); + } + }); + return config; + }; + /** + * Shorthand method to deselect an annotation. + * + * @function Highcharts.NavigationBindings#deselectAnnotation + */ + NavigationBindings.prototype.deselectAnnotation = function () { + if (this.activeAnnotation) { + this.activeAnnotation.setControlPointsVisibility(false); + this.activeAnnotation = false; + } + }; + /** + * Generates API config for popup in the same format as options for + * Annotation object. + * + * @function Highcharts.NavigationBindings#annotationToFields + * + * @param {Highcharts.Annotation} annotation + * Annotations object + * + * @return {Highcharts.Dictionary} + * Annotation options to be displayed in popup box + */ + NavigationBindings.prototype.annotationToFields = function (annotation) { + var options = annotation.options, editables = NavigationBindings.annotationsEditable, nestedEditables = editables.nestedOptions, getFieldType = this.utils.getFieldType, type = pick(options.type, options.shapes && options.shapes[0] && + options.shapes[0].type, options.labels && options.labels[0] && + options.labels[0].itemType, 'label'), nonEditables = NavigationBindings.annotationsNonEditable[options.langKey] || [], visualOptions = { + langKey: options.langKey, + type: type + }; + /** + * Nested options traversing. Method goes down to the options and copies + * allowed options (with values) to new object, which is last parameter: + * "parent". + * + * @private + * + * @param {*} option + * Atomic type or object/array + * + * @param {string} key + * Option name, for example "visible" or "x", "y" + * + * @param {object} parentEditables + * Editables from NavigationBindings.annotationsEditable + * + * @param {object} parent + * Where new options will be assigned + */ + function traverse(option, key, parentEditables, parent) { + var nextParent; + if (parentEditables && + nonEditables.indexOf(key) === -1 && + ((parentEditables.indexOf && + parentEditables.indexOf(key)) >= 0 || + parentEditables[key] || // nested array + parentEditables === true // simple array + )) { + // Roots: + if (isArray(option)) { + parent[key] = []; + option.forEach(function (arrayOption, i) { + if (!isObject(arrayOption)) { + // Simple arrays, e.g. [String, Number, Boolean] + traverse(arrayOption, 0, nestedEditables[key], parent[key]); + } + else { + // Advanced arrays, e.g. [Object, Object] + parent[key][i] = {}; + objectEach(arrayOption, function (nestedOption, nestedKey) { + traverse(nestedOption, nestedKey, nestedEditables[key], parent[key][i]); + }); + } + }); + } + else if (isObject(option)) { + nextParent = {}; + if (isArray(parent)) { + parent.push(nextParent); + nextParent[key] = {}; + nextParent = nextParent[key]; + } + else { + parent[key] = nextParent; + } + objectEach(option, function (nestedOption, nestedKey) { + traverse(nestedOption, nestedKey, key === 0 ? parentEditables : nestedEditables[key], nextParent); + }); + } + else { + // Leaf: + if (key === 'format') { + parent[key] = [ + format(option, annotation.labels[0].points[0]).toString(), + 'text' + ]; + } + else if (isArray(parent)) { + parent.push([option, getFieldType(option)]); + } + else { + parent[key] = [option, getFieldType(option)]; + } + } + } + } + objectEach(options, function (option, key) { + if (key === 'typeOptions') { + visualOptions[key] = {}; + objectEach(options[key], function (typeOption, typeKey) { + traverse(typeOption, typeKey, nestedEditables, visualOptions[key], true); + }); + } + else { + traverse(option, key, editables[type], visualOptions); + } + }); + return visualOptions; + }; + /** + * Get all class names for all parents in the element. Iterates until finds + * main container. + * + * @function Highcharts.NavigationBindings#getClickedClassNames + * + * @param {Highcharts.HTMLDOMElement} + * Container that event is bound to. + * + * @param {global.Event} event + * Browser's event. + * + * @return {Array>} + * Array of class names with corresponding elements + */ + NavigationBindings.prototype.getClickedClassNames = function (container, event) { + var element = event.target, classNames = [], elemClassName; + while (element) { + elemClassName = attr(element, 'class'); + if (elemClassName) { + classNames = classNames.concat(elemClassName + .split(' ') + .map(function (name) { + return [ + name, + element + ]; + })); + } + element = element.parentNode; + if (element === container) { + return classNames; + } + } + return classNames; + }; + /** + * Get events bound to a button. It's a custom event delegation to find all + * events connected to the element. + * + * @private + * @function Highcharts.NavigationBindings#getButtonEvents + * + * @param {Highcharts.HTMLDOMElement} container + * Container that event is bound to. + * + * @param {global.Event} event + * Browser's event. + * + * @return {object} + * Object with events (init, start, steps, and end) + */ + NavigationBindings.prototype.getButtonEvents = function (container, event) { + var navigation = this, classNames = this.getClickedClassNames(container, event), bindings; + classNames.forEach(function (className) { + if (navigation.boundClassNames[className[0]] && !bindings) { + bindings = { + events: navigation.boundClassNames[className[0]], + button: className[1] + }; + } + }); + return bindings; + }; + /** + * Bindings are just events, so the whole update process is simply + * removing old events and adding new ones. + * + * @private + * @function Highcharts.NavigationBindings#update + */ + NavigationBindings.prototype.update = function (options) { + this.options = merge(true, this.options, options); + this.removeEvents(); + this.initEvents(); + }; + /** + * Remove all events created in the navigation. + * + * @private + * @function Highcharts.NavigationBindings#removeEvents + */ + NavigationBindings.prototype.removeEvents = function () { + this.eventsToUnbind.forEach(function (unbinder) { + unbinder(); + }); + }; + NavigationBindings.prototype.destroy = function () { + this.removeEvents(); + }; + /* * + * + * Static Properties + * + * */ + // Define which options from annotations should show up in edit box: + NavigationBindings.annotationsEditable = { + // `typeOptions` are always available + // Nested and shared options: + nestedOptions: { + labelOptions: ['style', 'format', 'backgroundColor'], + labels: ['style'], + label: ['style'], + style: ['fontSize', 'color'], + background: ['fill', 'strokeWidth', 'stroke'], + innerBackground: ['fill', 'strokeWidth', 'stroke'], + outerBackground: ['fill', 'strokeWidth', 'stroke'], + shapeOptions: ['fill', 'strokeWidth', 'stroke'], + shapes: ['fill', 'strokeWidth', 'stroke'], + line: ['strokeWidth', 'stroke'], + backgroundColors: [true], + connector: ['fill', 'strokeWidth', 'stroke'], + crosshairX: ['strokeWidth', 'stroke'], + crosshairY: ['strokeWidth', 'stroke'] + }, + // Simple shapes: + circle: ['shapes'], + verticalLine: [], + label: ['labelOptions'], + // Measure + measure: ['background', 'crosshairY', 'crosshairX'], + // Others: + fibonacci: [], + tunnel: ['background', 'line', 'height'], + pitchfork: ['innerBackground', 'outerBackground'], + rect: ['shapes'], + // Crooked lines, elliots, arrows etc: + crookedLine: [], + basicAnnotation: [] + }; + // Define non editable fields per annotation, for example Rectangle inherits + // options from Measure, but crosshairs are not available + NavigationBindings.annotationsNonEditable = { + rectangle: ['crosshairX', 'crosshairY', 'label'] + }; + return NavigationBindings; + }()); + /** + * General utils for bindings + * + * @private + * @name Highcharts.NavigationBindings.utils + * @type {bindingsUtils} + */ + NavigationBindings.prototype.utils = bindingsUtils; + H.Chart.prototype.initNavigationBindings = function () { + var chart = this, options = chart.options; + if (options && options.navigation && options.navigation.bindings) { + chart.navigationBindings = new NavigationBindings(chart, options.navigation); + chart.navigationBindings.initEvents(); + chart.navigationBindings.initUpdate(); + } + }; + addEvent(H.Chart, 'load', function () { + this.initNavigationBindings(); + }); + addEvent(H.Chart, 'destroy', function () { + if (this.navigationBindings) { + this.navigationBindings.destroy(); + } + }); + addEvent(NavigationBindings, 'deselectButton', function () { + this.selectedButtonElement = null; + }); + addEvent(H.Annotation, 'remove', function () { + if (this.chart.navigationBindings) { + this.chart.navigationBindings.deselectAnnotation(); + } + }); + /** + * Show edit-annotation form: + * @private + */ + function selectableAnnotation(annotationType) { + var originalClick = annotationType.prototype.defaultOptions.events && + annotationType.prototype.defaultOptions.events.click; + /** + * @private + */ + function selectAndshowPopup(event) { + var annotation = this, navigation = annotation.chart.navigationBindings, prevAnnotation = navigation.activeAnnotation; + if (originalClick) { + originalClick.click.call(annotation, event); + } + if (prevAnnotation !== annotation) { + // Select current: + navigation.deselectAnnotation(); + navigation.activeAnnotation = annotation; + annotation.setControlPointsVisibility(true); + fireEvent(navigation, 'showPopup', { + annotation: annotation, + formType: 'annotation-toolbar', + options: navigation.annotationToFields(annotation), + onSubmit: function (data) { + var config = {}, typeOptions; + if (data.actionType === 'remove') { + navigation.activeAnnotation = false; + navigation.chart.removeAnnotation(annotation); + } + else { + navigation.fieldsToOptions(data.fields, config); + navigation.deselectAnnotation(); + typeOptions = config.typeOptions; + if (annotation.options.type === 'measure') { + // Manually disable crooshars according to + // stroke width of the shape: + typeOptions.crosshairY.enabled = + typeOptions.crosshairY.strokeWidth !== 0; + typeOptions.crosshairX.enabled = + typeOptions.crosshairX.strokeWidth !== 0; + } + annotation.update(config); + } + } + }); + } + else { + // Deselect current: + navigation.deselectAnnotation(); + fireEvent(navigation, 'closePopup'); + } + // Let bubble event to chart.click: + event.activeAnnotation = true; + } + merge(true, annotationType.prototype.defaultOptions.events, { + click: selectAndshowPopup + }); + } + if (H.Annotation) { + // Basic shapes: + selectableAnnotation(H.Annotation); + // Advanced annotations: + objectEach(H.Annotation.types, function (annotationType) { + selectableAnnotation(annotationType); + }); + } + H.setOptions({ + /** + * @optionparent lang + */ + lang: { + /** + * Configure the Popup strings in the chart. Requires the + * `annotations.js` or `annotations-advanced.src.js` module to be + * loaded. + * + * @since 7.0.0 + * @product highcharts highstock + */ + navigation: { + /** + * Translations for all field names used in popup. + * + * @product highcharts highstock + */ + popup: { + simpleShapes: 'Simple shapes', + lines: 'Lines', + circle: 'Circle', + rectangle: 'Rectangle', + label: 'Label', + shapeOptions: 'Shape options', + typeOptions: 'Details', + fill: 'Fill', + format: 'Text', + strokeWidth: 'Line width', + stroke: 'Line color', + title: 'Title', + name: 'Name', + labelOptions: 'Label options', + labels: 'Labels', + backgroundColor: 'Background color', + backgroundColors: 'Background colors', + borderColor: 'Border color', + borderRadius: 'Border radius', + borderWidth: 'Border width', + style: 'Style', + padding: 'Padding', + fontSize: 'Font size', + color: 'Color', + height: 'Height', + shapes: 'Shape options' + } + } + }, + /** + * @optionparent navigation + * @product highcharts highstock + */ + navigation: { + /** + * A CSS class name where all bindings will be attached to. Multiple + * charts on the same page should have separate class names to prevent + * duplicating events. + * + * Default value of versions < 7.0.4 `highcharts-bindings-wrapper` + * + * @since 7.0.0 + * @type {string} + */ + bindingsClassName: 'highcharts-bindings-container', + /** + * Bindings definitions for custom HTML buttons. Each binding implements + * simple event-driven interface: + * + * - `className`: classname used to bind event to + * + * - `init`: initial event, fired on button click + * + * - `start`: fired on first click on a chart + * + * - `steps`: array of sequential events fired one after another on each + * of users clicks + * + * - `end`: last event to be called after last step event + * + * @type {Highcharts.Dictionary|*} + * @sample stock/stocktools/stocktools-thresholds + * Custom bindings in Highstock + * @since 7.0.0 + * @product highcharts highstock + */ + bindings: { + /** + * A circle annotation bindings. Includes `start` and one event in + * `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @default {"className": "highcharts-circle-annotation", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + circleAnnotation: { + /** @ignore-option */ + className: 'highcharts-circle-annotation', + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation; + return this.chart.addAnnotation(merge({ + langKey: 'circle', + type: 'basicAnnotation', + shapes: [{ + type: 'circle', + point: { + xAxis: 0, + yAxis: 0, + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, + r: 5 + }] + }, navigation + .annotationsOptions, navigation + .bindings + .circleAnnotation + .annotationsOptions)); + }, + /** @ignore-option */ + steps: [ + function (e, annotation) { + var point = annotation.options.shapes[0].point, x = this.chart.xAxis[0].toPixels(point.x), y = this.chart.yAxis[0].toPixels(point.y), inverted = this.chart.inverted, distance = Math.max(Math.sqrt(Math.pow(inverted ? y - e.chartX : x - e.chartX, 2) + + Math.pow(inverted ? x - e.chartY : y - e.chartY, 2)), 5); + annotation.update({ + shapes: [{ + r: distance + }] + }); + } + ] + }, + /** + * A rectangle annotation bindings. Includes `start` and one event + * in `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @default {"className": "highcharts-rectangle-annotation", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + rectangleAnnotation: { + /** @ignore-option */ + className: 'highcharts-rectangle-annotation', + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, x = coords.xAxis[0].value, y = coords.yAxis[0].value; + return this.chart.addAnnotation(merge({ + langKey: 'rectangle', + type: 'basicAnnotation', + shapes: [{ + type: 'path', + points: [{ + xAxis: 0, + yAxis: 0, + x: x, + y: y + }, { + xAxis: 0, + yAxis: 0, + x: x, + y: y + }, { + xAxis: 0, + yAxis: 0, + x: x, + y: y + }, { + xAxis: 0, + yAxis: 0, + x: x, + y: y + }] + }] + }, navigation + .annotationsOptions, navigation + .bindings + .rectangleAnnotation + .annotationsOptions)); + }, + /** @ignore-option */ + steps: [ + function (e, annotation) { + var points = annotation.options.shapes[0].points, coords = this.chart.pointer.getCoordinates(e), x = coords.xAxis[0].value, y = coords.yAxis[0].value; + // Top right point + points[1].x = x; + // Bottom right point (cursor position) + points[2].x = x; + points[2].y = y; + // Bottom left + points[3].y = y; + annotation.update({ + shapes: [{ + points: points + }] + }); + } + ] + }, + /** + * A label annotation bindings. Includes `start` event only. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @default {"className": "highcharts-label-annotation", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + labelAnnotation: { + /** @ignore-option */ + className: 'highcharts-label-annotation', + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation; + return this.chart.addAnnotation(merge({ + langKey: 'label', + type: 'basicAnnotation', + labelOptions: { + format: '{y:.2f}' + }, + labels: [{ + point: { + xAxis: 0, + yAxis: 0, + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, + overflow: 'none', + crop: true + }] + }, navigation + .annotationsOptions, navigation + .bindings + .labelAnnotation + .annotationsOptions)); + } + } + }, + /** + * Path where Highcharts will look for icons. Change this to use icons + * from a different server. + * + * @type {string} + * @default https://code.highcharts.com/8.1.0/gfx/stock-icons/ + * @since 7.1.3 + * @apioption navigation.iconsURL + */ + /** + * A `showPopup` event. Fired when selecting for example an annotation. + * + * @type {Function} + * @apioption navigation.events.showPopup + */ + /** + * A `closePopup` event. Fired when Popup should be hidden, for example + * when clicking on an annotation again. + * + * @type {Function} + * @apioption navigation.events.closePopup + */ + /** + * Event fired on a button click. + * + * @type {Function} + * @sample highcharts/annotations/gui/ + * Change icon in a dropddown on event + * @sample highcharts/annotations/gui-buttons/ + * Change button class on event + * @apioption navigation.events.selectButton + */ + /** + * Event fired when button state should change, for example after + * adding an annotation. + * + * @type {Function} + * @sample highcharts/annotations/gui/ + * Change icon in a dropddown on event + * @sample highcharts/annotations/gui-buttons/ + * Change button class on event + * @apioption navigation.events.deselectButton + */ + /** + * Events to communicate between Stock Tools and custom GUI. + * + * @since 7.0.0 + * @product highcharts highstock + * @optionparent navigation.events + */ + events: {}, + /** + * Additional options to be merged into all annotations. + * + * @sample stock/stocktools/navigation-annotation-options + * Set red color of all line annotations + * + * @type {Highcharts.AnnotationsOptions} + * @extends annotations + * @exclude crookedLine, elliottWave, fibonacci, infinityLine, + * measure, pitchfork, tunnel, verticalLine, basicAnnotation + * @apioption navigation.annotationsOptions + */ + annotationsOptions: {} + } + }); + + return NavigationBindings; + }); + _registerModule(_modules, 'modules/stock-tools-bindings.js', [_modules['parts/Globals.js'], _modules['annotations/navigationBindings.js'], _modules['parts/Utilities.js']], function (H, NavigationBindings, U) { + /** + * + * Events generator for Stock tools + * + * (c) 2009-2020 Paweł Fus + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var correctFloat = U.correctFloat, defined = U.defined, extend = U.extend, fireEvent = U.fireEvent, isNumber = U.isNumber, merge = U.merge, pick = U.pick, uniqueKey = U.uniqueKey; + var bindingsUtils = NavigationBindings.prototype.utils, PREFIX = 'highcharts-'; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Generates function which will add a flag series using modal in GUI. + * Method fires an event "showPopup" with config: + * `{type, options, callback}`. + * + * Example: NavigationBindings.utils.addFlagFromForm('url(...)') - will + * generate function that shows modal in GUI. + * + * @private + * @function bindingsUtils.addFlagFromForm + * + * @param {Highcharts.FlagsShapeValue} type + * Type of flag series, e.g. "squarepin" + * + * @return {Function} + * Callback to be used in `start` callback + */ + bindingsUtils.addFlagFromForm = function (type) { + return function (e) { + var navigation = this, chart = navigation.chart, toolbar = chart.stockTools, getFieldType = bindingsUtils.getFieldType, point = bindingsUtils.attractToPoint(e, chart), pointConfig = { + x: point.x, + y: point.y + }, seriesOptions = { + type: 'flags', + onSeries: point.series.id, + shape: type, + data: [pointConfig], + point: { + events: { + click: function () { + var point = this, options = point.options; + fireEvent(navigation, 'showPopup', { + point: point, + formType: 'annotation-toolbar', + options: { + langKey: 'flags', + type: 'flags', + title: [ + options.title, + getFieldType(options.title) + ], + name: [ + options.name, + getFieldType(options.name) + ] + }, + onSubmit: function (updated) { + if (updated.actionType === 'remove') { + point.remove(); + } + else { + point.update(navigation.fieldsToOptions(updated.fields, {})); + } + } + }); + } + } + } + }; + if (!toolbar || !toolbar.guiEnabled) { + chart.addSeries(seriesOptions); + } + fireEvent(navigation, 'showPopup', { + formType: 'flag', + // Enabled options: + options: { + langKey: 'flags', + type: 'flags', + title: ['A', getFieldType('A')], + name: ['Flag A', getFieldType('Flag A')] + }, + // Callback on submit: + onSubmit: function (data) { + navigation.fieldsToOptions(data.fields, seriesOptions.data[0]); + chart.addSeries(seriesOptions); + } + }); + }; + }; + bindingsUtils.manageIndicators = function (data) { + var navigation = this, chart = navigation.chart, seriesConfig = { + linkedTo: data.linkedTo, + type: data.type + }, indicatorsWithVolume = [ + 'ad', + 'cmf', + 'mfi', + 'vbp', + 'vwap' + ], indicatorsWithAxes = [ + 'ad', + 'atr', + 'cci', + 'cmf', + 'macd', + 'mfi', + 'roc', + 'rsi', + 'ao', + 'aroon', + 'aroonoscillator', + 'trix', + 'apo', + 'dpo', + 'ppo', + 'natr', + 'williamsr', + 'stochastic', + 'slowstochastic', + 'linearRegression', + 'linearRegressionSlope', + 'linearRegressionIntercept', + 'linearRegressionAngle' + ], yAxis, series; + if (data.actionType === 'edit') { + navigation.fieldsToOptions(data.fields, seriesConfig); + series = chart.get(data.seriesId); + if (series) { + series.update(seriesConfig, false); + } + } + else if (data.actionType === 'remove') { + series = chart.get(data.seriesId); + if (series) { + yAxis = series.yAxis; + if (series.linkedSeries) { + series.linkedSeries.forEach(function (linkedSeries) { + linkedSeries.remove(false); + }); + } + series.remove(false); + if (indicatorsWithAxes.indexOf(series.type) >= 0) { + yAxis.remove(false); + navigation.resizeYAxes(); + } + } + } + else { + seriesConfig.id = uniqueKey(); + navigation.fieldsToOptions(data.fields, seriesConfig); + if (indicatorsWithAxes.indexOf(data.type) >= 0) { + yAxis = chart.addAxis({ + id: uniqueKey(), + offset: 0, + opposite: true, + title: { + text: '' + }, + tickPixelInterval: 40, + showLastLabel: false, + labels: { + align: 'left', + y: -2 + } + }, false, false); + seriesConfig.yAxis = yAxis.options.id; + navigation.resizeYAxes(); + } + else { + seriesConfig.yAxis = chart.get(data.linkedTo).options.yAxis; + } + if (indicatorsWithVolume.indexOf(data.type) >= 0) { + seriesConfig.params.volumeSeriesID = chart.series.filter(function (series) { + return series.options.type === 'column'; + })[0].options.id; + } + chart.addSeries(seriesConfig, false); + } + fireEvent(navigation, 'deselectButton', { + button: navigation.selectedButtonElement + }); + chart.redraw(); + }; + /** + * Update height for an annotation. Height is calculated as a difference + * between last point in `typeOptions` and current position. It's a value, + * not pixels height. + * + * @private + * @function bindingsUtils.updateHeight + * + * @param {Highcharts.PointerEventObject} e + * normalized browser event + * + * @param {Highcharts.Annotation} annotation + * Annotation to be updated + * + * @return {void} + */ + bindingsUtils.updateHeight = function (e, annotation) { + annotation.update({ + typeOptions: { + height: this.chart.pointer.getCoordinates(e).yAxis[0].value - + annotation.options.typeOptions.points[1].y + } + }); + }; + // @todo + // Consider using getHoverData(), but always kdTree (columns?) + bindingsUtils.attractToPoint = function (e, chart) { + var coords = chart.pointer.getCoordinates(e), x = coords.xAxis[0].value, y = coords.yAxis[0].value, distX = Number.MAX_VALUE, closestPoint; + chart.series.forEach(function (series) { + series.points.forEach(function (point) { + if (point && distX > Math.abs(point.x - x)) { + distX = Math.abs(point.x - x); + closestPoint = point; + } + }); + }); + return { + x: closestPoint.x, + y: closestPoint.y, + below: y < closestPoint.y, + series: closestPoint.series, + xAxis: closestPoint.series.xAxis.index || 0, + yAxis: closestPoint.series.yAxis.index || 0 + }; + }; + /** + * Shorthand to check if given yAxis comes from navigator. + * + * @private + * @function bindingsUtils.isNotNavigatorYAxis + * + * @param {Highcharts.Axis} axis + * Axis to check. + * + * @return {boolean} + * True, if axis comes from navigator. + */ + bindingsUtils.isNotNavigatorYAxis = function (axis) { + return axis.userOptions.className !== PREFIX + 'navigator-yaxis'; + }; + /** + * Update each point after specified index, most of the annotations use + * this. For example crooked line: logic behind updating each point is the + * same, only index changes when adding an annotation. + * + * Example: NavigationBindings.utils.updateNthPoint(1) - will generate + * function that updates all consecutive points except point with index=0. + * + * @private + * @function bindingsUtils.updateNthPoint + * + * @param {number} startIndex + * Index from each point should udpated + * + * @return {Function} + * Callback to be used in steps array + */ + bindingsUtils.updateNthPoint = function (startIndex) { + return function (e, annotation) { + var options = annotation.options.typeOptions, coords = this.chart.pointer.getCoordinates(e), x = coords.xAxis[0].value, y = coords.yAxis[0].value; + options.points.forEach(function (point, index) { + if (index >= startIndex) { + point.x = x; + point.y = y; + } + }); + annotation.update({ + typeOptions: { + points: options.points + } + }); + }; + }; + // Extends NavigationBindigs to support indicators and resizers: + extend(NavigationBindings.prototype, { + /* eslint-disable valid-jsdoc */ + /** + * Get current positions for all yAxes. If new axis does not have position, + * returned is default height and last available top place. + * + * @private + * @function Highcharts.NavigationBindings#getYAxisPositions + * + * @param {Array} yAxes + * Array of yAxes available in the chart. + * + * @param {number} plotHeight + * Available height in the chart. + * + * @param {number} defaultHeight + * Default height in percents. + * + * @return {Array} + * An array of calculated positions in percentages. + * Format: `{top: Number, height: Number}` + */ + getYAxisPositions: function (yAxes, plotHeight, defaultHeight) { + var positions, allAxesHeight = 0; + /** @private */ + function isPercentage(prop) { + return defined(prop) && !isNumber(prop) && prop.match('%'); + } + positions = yAxes.map(function (yAxis) { + var height = isPercentage(yAxis.options.height) ? + parseFloat(yAxis.options.height) / 100 : + yAxis.height / plotHeight, top = isPercentage(yAxis.options.top) ? + parseFloat(yAxis.options.top) / 100 : + correctFloat(yAxis.top - yAxis.chart.plotTop) / plotHeight; + // New yAxis does not contain "height" info yet + if (!isNumber(height)) { + height = defaultHeight / 100; + } + allAxesHeight = correctFloat(allAxesHeight + height); + return { + height: height * 100, + top: top * 100 + }; + }); + positions.allAxesHeight = allAxesHeight; + return positions; + }, + /** + * Get current resize options for each yAxis. Note that each resize is + * linked to the next axis, except the last one which shouldn't affect + * axes in the navigator. Because indicator can be removed with it's yAxis + * in the middle of yAxis array, we need to bind closest yAxes back. + * + * @private + * @function Highcharts.NavigationBindings#getYAxisResizers + * + * @param {Array} yAxes + * Array of yAxes available in the chart + * + * @return {Array} + * An array of resizer options. + * Format: `{enabled: Boolean, controlledAxis: { next: [String]}}` + */ + getYAxisResizers: function (yAxes) { + var resizers = []; + yAxes.forEach(function (_yAxis, index) { + var nextYAxis = yAxes[index + 1]; + // We have next axis, bind them: + if (nextYAxis) { + resizers[index] = { + enabled: true, + controlledAxis: { + next: [ + pick(nextYAxis.options.id, nextYAxis.options.index) + ] + } + }; + } + else { + // Remove binding: + resizers[index] = { + enabled: false + }; + } + }); + return resizers; + }, + /** + * Resize all yAxes (except navigator) to fit the plotting height. Method + * checks if new axis is added, then shrinks other main axis up to 5 panes. + * If added is more thatn 5 panes, it rescales all other axes to fit new + * yAxis. + * + * If axis is removed, and we have more than 5 panes, rescales all other + * axes. If chart has less than 5 panes, first pane receives all extra + * space. + * + * @private + * @function Highcharts.NavigationBindings#resizeYAxes + * @param {number} [defaultHeight] + * Default height for yAxis + * @return {void} + */ + resizeYAxes: function (defaultHeight) { + defaultHeight = defaultHeight || 20; // in %, but as a number + var chart = this.chart, + // Only non-navigator axes + yAxes = chart.yAxis.filter(bindingsUtils.isNotNavigatorYAxis), plotHeight = chart.plotHeight, allAxesLength = yAxes.length, + // Gather current heights (in %) + positions = this.getYAxisPositions(yAxes, plotHeight, defaultHeight), resizers = this.getYAxisResizers(yAxes), allAxesHeight = positions.allAxesHeight, changedSpace = defaultHeight; + // More than 100% + if (allAxesHeight > 1) { + // Simple case, add new panes up to 5 + if (allAxesLength < 6) { + // Added axis, decrease first pane's height: + positions[0].height = correctFloat(positions[0].height - changedSpace); + // And update all other "top" positions: + positions = this.recalculateYAxisPositions(positions, changedSpace); + } + else { + // We have more panes, rescale all others to gain some space, + // This is new height for upcoming yAxis: + defaultHeight = 100 / allAxesLength; + // This is how much we need to take from each other yAxis: + changedSpace = defaultHeight / (allAxesLength - 1); + // Now update all positions: + positions = this.recalculateYAxisPositions(positions, changedSpace, true, -1); + } + // Set last position manually: + positions[allAxesLength - 1] = { + top: correctFloat(100 - defaultHeight), + height: defaultHeight + }; + } + else { + // Less than 100% + changedSpace = correctFloat(1 - allAxesHeight) * 100; + // Simple case, return first pane it's space: + if (allAxesLength < 5) { + positions[0].height = correctFloat(positions[0].height + changedSpace); + positions = this.recalculateYAxisPositions(positions, changedSpace); + } + else { + // There were more panes, return to each pane a bit of space: + changedSpace /= allAxesLength; + // Removed axis, add extra space to the first pane: + // And update all other positions: + positions = this.recalculateYAxisPositions(positions, changedSpace, true, 1); + } + } + positions.forEach(function (position, index) { + // if (index === 0) debugger; + yAxes[index].update({ + height: position.height + '%', + top: position.top + '%', + resize: resizers[index] + }, false); + }); + }, + /** + * Utility to modify calculated positions according to the remaining/needed + * space. Later, these positions are used in `yAxis.update({ top, height })` + * + * @private + * @function Highcharts.NavigationBindings#recalculateYAxisPositions + * @param {Array>} positions + * Default positions of all yAxes. + * @param {number} changedSpace + * How much space should be added or removed. + * @param {boolean} modifyHeight + * Update only `top` or both `top` and `height`. + * @param {number} adder + * `-1` or `1`, to determine whether we should add or remove space. + * + * @return {Array} + * Modified positions, + */ + recalculateYAxisPositions: function (positions, changedSpace, modifyHeight, adder) { + positions.forEach(function (position, index) { + var prevPosition = positions[index - 1]; + position.top = !prevPosition ? 0 : + correctFloat(prevPosition.height + prevPosition.top); + if (modifyHeight) { + position.height = correctFloat(position.height + adder * changedSpace); + } + }); + return positions; + } + /* eslint-enable valid-jsdoc */ + }); + /** + * @type {Highcharts.Dictionary} + * @since 7.0.0 + * @optionparent navigation.bindings + */ + var stockToolsBindings = { + // Line type annotations: + /** + * A segment annotation bindings. Includes `start` and one event in `steps` + * array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-segment", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + segment: { + /** @ignore-option */ + className: 'highcharts-segment', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'segment', + type: 'crookedLine', + typeOptions: { + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.segment.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1) + ] + }, + /** + * A segment with an arrow annotation bindings. Includes `start` and one + * event in `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-arrow-segment", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + arrowSegment: { + /** @ignore-option */ + className: 'highcharts-arrow-segment', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'arrowSegment', + type: 'crookedLine', + typeOptions: { + line: { + markerEnd: 'arrow' + }, + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.arrowSegment.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1) + ] + }, + /** + * A ray annotation bindings. Includes `start` and one event in `steps` + * array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-ray", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + ray: { + /** @ignore-option */ + className: 'highcharts-ray', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'ray', + type: 'crookedLine', + typeOptions: { + type: 'ray', + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.ray.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1) + ] + }, + /** + * A ray with an arrow annotation bindings. Includes `start` and one event + * in `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-arrow-ray", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + arrowRay: { + /** @ignore-option */ + className: 'highcharts-arrow-ray', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'arrowRay', + type: 'infinityLine', + typeOptions: { + type: 'ray', + line: { + markerEnd: 'arrow' + }, + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.arrowRay.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1) + ] + }, + /** + * A line annotation. Includes `start` and one event in `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-infinity-line", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + infinityLine: { + /** @ignore-option */ + className: 'highcharts-infinity-line', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'infinityLine', + type: 'infinityLine', + typeOptions: { + type: 'line', + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.infinityLine.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1) + ] + }, + /** + * A line with arrow annotation. Includes `start` and one event in `steps` + * array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-arrow-infinity-line", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + arrowInfinityLine: { + /** @ignore-option */ + className: 'highcharts-arrow-infinity-line', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'arrowInfinityLine', + type: 'infinityLine', + typeOptions: { + type: 'line', + line: { + markerEnd: 'arrow' + }, + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.arrowInfinityLine.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1) + ] + }, + /** + * A horizontal line annotation. Includes `start` event. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-horizontal-line", "start": function() {}, "annotationsOptions": {}} + */ + horizontalLine: { + /** @ignore-option */ + className: 'highcharts-horizontal-line', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'horizontalLine', + type: 'infinityLine', + draggable: 'y', + typeOptions: { + type: 'horizontalLine', + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.horizontalLine.annotationsOptions); + this.chart.addAnnotation(options); + } + }, + /** + * A vertical line annotation. Includes `start` event. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-vertical-line", "start": function() {}, "annotationsOptions": {}} + */ + verticalLine: { + /** @ignore-option */ + className: 'highcharts-vertical-line', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'verticalLine', + type: 'infinityLine', + draggable: 'x', + typeOptions: { + type: 'verticalLine', + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.verticalLine.annotationsOptions); + this.chart.addAnnotation(options); + } + }, + /** + * Crooked line (three points) annotation bindings. Includes `start` and two + * events in `steps` (for second and third points in crooked line) array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-crooked3", "start": function() {}, "steps": [function() {}, function() {}], "annotationsOptions": {}} + */ + // Crooked Line type annotations: + crooked3: { + /** @ignore-option */ + className: 'highcharts-crooked3', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'crooked3', + type: 'crookedLine', + typeOptions: { + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.crooked3.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1), + bindingsUtils.updateNthPoint(2) + ] + }, + /** + * Crooked line (five points) annotation bindings. Includes `start` and four + * events in `steps` (for all consequent points in crooked line) array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-crooked3", "start": function() {}, "steps": [function() {}, function() {}, function() {}, function() {}], "annotationsOptions": {}} + */ + crooked5: { + /** @ignore-option */ + className: 'highcharts-crooked5', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'crookedLine', + type: 'crookedLine', + typeOptions: { + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.crooked5.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1), + bindingsUtils.updateNthPoint(2), + bindingsUtils.updateNthPoint(3), + bindingsUtils.updateNthPoint(4) + ] + }, + /** + * Elliott wave (three points) annotation bindings. Includes `start` and two + * events in `steps` (for second and third points) array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-elliott3", "start": function() {}, "steps": [function() {}, function() {}], "annotationsOptions": {}} + */ + elliott3: { + /** @ignore-option */ + className: 'highcharts-elliott3', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'elliott3', + type: 'elliottWave', + typeOptions: { + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + }, + labelOptions: { + style: { + color: '#666666' + } + } + }, navigation.annotationsOptions, navigation.bindings.elliott3.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1), + bindingsUtils.updateNthPoint(2), + bindingsUtils.updateNthPoint(3) + ] + }, + /** + * Elliott wave (five points) annotation bindings. Includes `start` and four + * event in `steps` (for all consequent points in Elliott wave) array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-elliott3", "start": function() {}, "steps": [function() {}, function() {}, function() {}, function() {}], "annotationsOptions": {}} + */ + elliott5: { + /** @ignore-option */ + className: 'highcharts-elliott5', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'elliott5', + type: 'elliottWave', + typeOptions: { + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + }, + labelOptions: { + style: { + color: '#666666' + } + } + }, navigation.annotationsOptions, navigation.bindings.elliott5.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1), + bindingsUtils.updateNthPoint(2), + bindingsUtils.updateNthPoint(3), + bindingsUtils.updateNthPoint(4), + bindingsUtils.updateNthPoint(5) + ] + }, + /** + * A measure (x-dimension) annotation bindings. Includes `start` and one + * event in `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-measure-x", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + measureX: { + /** @ignore-option */ + className: 'highcharts-measure-x', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'measure', + type: 'measure', + typeOptions: { + selectType: 'x', + point: { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value, + xAxis: 0, + yAxis: 0 + }, + crosshairX: { + strokeWidth: 1, + stroke: '#000000' + }, + crosshairY: { + enabled: false, + strokeWidth: 0, + stroke: '#000000' + }, + background: { + width: 0, + height: 0, + strokeWidth: 0, + stroke: '#ffffff' + } + }, + labelOptions: { + style: { + color: '#666666' + } + } + }, navigation.annotationsOptions, navigation.bindings.measureX.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateRectSize + ] + }, + /** + * A measure (y-dimension) annotation bindings. Includes `start` and one + * event in `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-measure-y", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + measureY: { + /** @ignore-option */ + className: 'highcharts-measure-y', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'measure', + type: 'measure', + typeOptions: { + selectType: 'y', + point: { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value, + xAxis: 0, + yAxis: 0 + }, + crosshairX: { + enabled: false, + strokeWidth: 0, + stroke: '#000000' + }, + crosshairY: { + strokeWidth: 1, + stroke: '#000000' + }, + background: { + width: 0, + height: 0, + strokeWidth: 0, + stroke: '#ffffff' + } + }, + labelOptions: { + style: { + color: '#666666' + } + } + }, navigation.annotationsOptions, navigation.bindings.measureY.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateRectSize + ] + }, + /** + * A measure (xy-dimension) annotation bindings. Includes `start` and one + * event in `steps` array. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-measure-xy", "start": function() {}, "steps": [function() {}], "annotationsOptions": {}} + */ + measureXY: { + /** @ignore-option */ + className: 'highcharts-measure-xy', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'measure', + type: 'measure', + typeOptions: { + selectType: 'xy', + point: { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value, + xAxis: 0, + yAxis: 0 + }, + background: { + width: 0, + height: 0, + strokeWidth: 10 + }, + crosshairX: { + strokeWidth: 1, + stroke: '#000000' + }, + crosshairY: { + strokeWidth: 1, + stroke: '#000000' + } + }, + labelOptions: { + style: { + color: '#666666' + } + } + }, navigation.annotationsOptions, navigation.bindings.measureXY.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateRectSize + ] + }, + // Advanced type annotations: + /** + * A fibonacci annotation bindings. Includes `start` and two events in + * `steps` array (updates second point, then height). + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-fibonacci", "start": function() {}, "steps": [function() {}, function() {}], "annotationsOptions": {}} + */ + fibonacci: { + /** @ignore-option */ + className: 'highcharts-fibonacci', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'fibonacci', + type: 'fibonacci', + typeOptions: { + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + }, + labelOptions: { + style: { + color: '#666666' + } + } + }, navigation.annotationsOptions, navigation.bindings.fibonacci.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1), + bindingsUtils.updateHeight + ] + }, + /** + * A parallel channel (tunnel) annotation bindings. Includes `start` and + * two events in `steps` array (updates second point, then height). + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-parallel-channel", "start": function() {}, "steps": [function() {}, function() {}], "annotationsOptions": {}} + */ + parallelChannel: { + /** @ignore-option */ + className: 'highcharts-parallel-channel', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'parallelChannel', + type: 'tunnel', + typeOptions: { + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }] + } + }, navigation.annotationsOptions, navigation.bindings.parallelChannel.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1), + bindingsUtils.updateHeight + ] + }, + /** + * An Andrew's pitchfork annotation bindings. Includes `start` and two + * events in `steps` array (sets second and third control points). + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-pitchfork", "start": function() {}, "steps": [function() {}, function() {}], "annotationsOptions": {}} + */ + pitchfork: { + /** @ignore-option */ + className: 'highcharts-pitchfork', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var coords = this.chart.pointer.getCoordinates(e), navigation = this.chart.options.navigation, options = merge({ + langKey: 'pitchfork', + type: 'pitchfork', + typeOptions: { + points: [{ + x: coords.xAxis[0].value, + y: coords.yAxis[0].value, + controlPoint: { + style: { + fill: 'red' + } + } + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }, { + x: coords.xAxis[0].value, + y: coords.yAxis[0].value + }], + innerBackground: { + fill: 'rgba(100, 170, 255, 0.8)' + } + }, + shapeOptions: { + strokeWidth: 2 + } + }, navigation.annotationsOptions, navigation.bindings.pitchfork.annotationsOptions); + return this.chart.addAnnotation(options); + }, + /** @ignore-option */ + steps: [ + bindingsUtils.updateNthPoint(1), + bindingsUtils.updateNthPoint(2) + ] + }, + // Labels with arrow and auto increments + /** + * A vertical counter annotation bindings. Includes `start` event. On click, + * finds the closest point and marks it with a numeric annotation - + * incrementing counter on each add. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-vertical-counter", "start": function() {}, "annotationsOptions": {}} + */ + verticalCounter: { + /** @ignore-option */ + className: 'highcharts-vertical-counter', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var closestPoint = bindingsUtils.attractToPoint(e, this.chart), navigation = this.chart.options.navigation, verticalCounter = !defined(this.verticalCounter) ? 0 : + this.verticalCounter, options = merge({ + langKey: 'verticalCounter', + type: 'verticalLine', + typeOptions: { + point: { + x: closestPoint.x, + y: closestPoint.y, + xAxis: closestPoint.xAxis, + yAxis: closestPoint.yAxis + }, + label: { + offset: closestPoint.below ? 40 : -40, + text: verticalCounter.toString() + } + }, + labelOptions: { + style: { + color: '#666666', + fontSize: '11px' + } + }, + shapeOptions: { + stroke: 'rgba(0, 0, 0, 0.75)', + strokeWidth: 1 + } + }, navigation.annotationsOptions, navigation.bindings.verticalCounter.annotationsOptions), annotation; + annotation = this.chart.addAnnotation(options); + verticalCounter++; + annotation.options.events.click.call(annotation, {}); + } + }, + /** + * A vertical arrow annotation bindings. Includes `start` event. On click, + * finds the closest point and marks it with an arrow and a label with + * value. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-vertical-label", "start": function() {}, "annotationsOptions": {}} + */ + verticalLabel: { + /** @ignore-option */ + className: 'highcharts-vertical-label', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var closestPoint = bindingsUtils.attractToPoint(e, this.chart), navigation = this.chart.options.navigation, options = merge({ + langKey: 'verticalLabel', + type: 'verticalLine', + typeOptions: { + point: { + x: closestPoint.x, + y: closestPoint.y, + xAxis: closestPoint.xAxis, + yAxis: closestPoint.yAxis + }, + label: { + offset: closestPoint.below ? 40 : -40 + } + }, + labelOptions: { + style: { + color: '#666666', + fontSize: '11px' + } + }, + shapeOptions: { + stroke: 'rgba(0, 0, 0, 0.75)', + strokeWidth: 1 + } + }, navigation.annotationsOptions, navigation.bindings.verticalLabel.annotationsOptions), annotation; + annotation = this.chart.addAnnotation(options); + annotation.options.events.click.call(annotation, {}); + } + }, + /** + * A vertical arrow annotation bindings. Includes `start` event. On click, + * finds the closest point and marks it with an arrow. Green arrow when + * pointing from above, red when pointing from below the point. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-vertical-arrow", "start": function() {}, "annotationsOptions": {}} + */ + verticalArrow: { + /** @ignore-option */ + className: 'highcharts-vertical-arrow', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + start: function (e) { + var closestPoint = bindingsUtils.attractToPoint(e, this.chart), navigation = this.chart.options.navigation, options = merge({ + langKey: 'verticalArrow', + type: 'verticalLine', + typeOptions: { + point: { + x: closestPoint.x, + y: closestPoint.y, + xAxis: closestPoint.xAxis, + yAxis: closestPoint.yAxis + }, + label: { + offset: closestPoint.below ? 40 : -40, + format: ' ' + }, + connector: { + fill: 'none', + stroke: closestPoint.below ? 'red' : 'green' + } + }, + shapeOptions: { + stroke: 'rgba(0, 0, 0, 0.75)', + strokeWidth: 1 + } + }, navigation.annotationsOptions, navigation.bindings.verticalArrow.annotationsOptions), annotation; + annotation = this.chart.addAnnotation(options); + annotation.options.events.click.call(annotation, {}); + } + }, + // Flag types: + /** + * A flag series bindings. Includes `start` event. On click, finds the + * closest point and marks it with a flag with `'circlepin'` shape. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-flag-circlepin", "start": function() {}} + */ + flagCirclepin: { + /** @ignore-option */ + className: 'highcharts-flag-circlepin', + /** @ignore-option */ + start: bindingsUtils.addFlagFromForm('circlepin') + }, + /** + * A flag series bindings. Includes `start` event. On click, finds the + * closest point and marks it with a flag with `'diamondpin'` shape. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-flag-diamondpin", "start": function() {}} + */ + flagDiamondpin: { + /** @ignore-option */ + className: 'highcharts-flag-diamondpin', + /** @ignore-option */ + start: bindingsUtils.addFlagFromForm('flag') + }, + /** + * A flag series bindings. Includes `start` event. + * On click, finds the closest point and marks it with a flag with + * `'squarepin'` shape. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-flag-squarepin", "start": function() {}} + */ + flagSquarepin: { + /** @ignore-option */ + className: 'highcharts-flag-squarepin', + /** @ignore-option */ + start: bindingsUtils.addFlagFromForm('squarepin') + }, + /** + * A flag series bindings. Includes `start` event. + * On click, finds the closest point and marks it with a flag without pin + * shape. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-flag-simplepin", "start": function() {}} + */ + flagSimplepin: { + /** @ignore-option */ + className: 'highcharts-flag-simplepin', + /** @ignore-option */ + start: bindingsUtils.addFlagFromForm('nopin') + }, + // Other tools: + /** + * Enables zooming in xAxis on a chart. Includes `start` event which + * changes [chart.zoomType](#chart.zoomType). + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-zoom-x", "init": function() {}} + */ + zoomX: { + /** @ignore-option */ + className: 'highcharts-zoom-x', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function (button) { + this.chart.update({ + chart: { + zoomType: 'x' + } + }); + fireEvent(this, 'deselectButton', { button: button }); + } + }, + /** + * Enables zooming in yAxis on a chart. Includes `start` event which + * changes [chart.zoomType](#chart.zoomType). + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-zoom-y", "init": function() {}} + */ + zoomY: { + /** @ignore-option */ + className: 'highcharts-zoom-y', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function (button) { + this.chart.update({ + chart: { + zoomType: 'y' + } + }); + fireEvent(this, 'deselectButton', { button: button }); + } + }, + /** + * Enables zooming in xAxis and yAxis on a chart. Includes `start` event + * which changes [chart.zoomType](#chart.zoomType). + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-zoom-xy", "init": function() {}} + */ + zoomXY: { + /** @ignore-option */ + className: 'highcharts-zoom-xy', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function (button) { + this.chart.update({ + chart: { + zoomType: 'xy' + } + }); + fireEvent(this, 'deselectButton', { button: button }); + } + }, + /** + * Changes main series to `'line'` type. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-series-type-line", "init": function() {}} + */ + seriesTypeLine: { + /** @ignore-option */ + className: 'highcharts-series-type-line', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function (button) { + this.chart.series[0].update({ + type: 'line', + useOhlcData: true + }); + fireEvent(this, 'deselectButton', { button: button }); + } + }, + /** + * Changes main series to `'ohlc'` type. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-series-type-ohlc", "init": function() {}} + */ + seriesTypeOhlc: { + /** @ignore-option */ + className: 'highcharts-series-type-ohlc', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function (button) { + this.chart.series[0].update({ + type: 'ohlc' + }); + fireEvent(this, 'deselectButton', { button: button }); + } + }, + /** + * Changes main series to `'candlestick'` type. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-series-type-candlestick", "init": function() {}} + */ + seriesTypeCandlestick: { + /** @ignore-option */ + className: 'highcharts-series-type-candlestick', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function (button) { + this.chart.series[0].update({ + type: 'candlestick' + }); + fireEvent(this, 'deselectButton', { button: button }); + } + }, + /** + * Displays chart in fullscreen. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-full-screen", "init": function() {}} + */ + fullScreen: { + /** @ignore-option */ + className: 'highcharts-full-screen', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function (button) { + this.chart.fullscreen.toggle(); + fireEvent(this, 'deselectButton', { button: button }); + } + }, + /** + * Hides/shows two price indicators: + * - last price in the dataset + * - last price in the selected range + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-current-price-indicator", "init": function() {}} + */ + currentPriceIndicator: { + /** @ignore-option */ + className: 'highcharts-current-price-indicator', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function (button) { + var chart = this.chart, series = chart.series[0], options = series.options, lastVisiblePrice = (options.lastVisiblePrice && + options.lastVisiblePrice.enabled), lastPrice = options.lastPrice && options.lastPrice.enabled, gui = chart.stockTools, iconsURL = gui.getIconsURL(); + if (gui && gui.guiEnabled) { + if (lastPrice) { + button.firstChild.style['background-image'] = + 'url("' + iconsURL + + 'current-price-show.svg")'; + } + else { + button.firstChild.style['background-image'] = + 'url("' + iconsURL + + 'current-price-hide.svg")'; + } + } + series.update({ + // line + lastPrice: { + enabled: !lastPrice, + color: 'red' + }, + // label + lastVisiblePrice: { + enabled: !lastVisiblePrice, + label: { + enabled: true + } + } + }); + fireEvent(this, 'deselectButton', { button: button }); + } + }, + /** + * Indicators bindings. Includes `init` event to show a popup. + * + * Note: In order to show base series from the chart in the popup's + * dropdown each series requires + * [series.id](https://api.highcharts.com/highstock/series.line.id) to be + * defined. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-indicators", "init": function() {}} + */ + indicators: { + /** @ignore-option */ + className: 'highcharts-indicators', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function () { + var navigation = this; + fireEvent(navigation, 'showPopup', { + formType: 'indicators', + options: {}, + // Callback on submit: + onSubmit: function (data) { + navigation.utils.manageIndicators.call(navigation, data); + } + }); + } + }, + /** + * Hides/shows all annotations on a chart. + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-toggle-annotations", "init": function() {}} + */ + toggleAnnotations: { + /** @ignore-option */ + className: 'highcharts-toggle-annotations', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function (button) { + var chart = this.chart, gui = chart.stockTools, iconsURL = gui.getIconsURL(); + this.toggledAnnotations = !this.toggledAnnotations; + (chart.annotations || []).forEach(function (annotation) { + annotation.setVisibility(!this.toggledAnnotations); + }, this); + if (gui && gui.guiEnabled) { + if (this.toggledAnnotations) { + button.firstChild.style['background-image'] = + 'url("' + iconsURL + + 'annotations-hidden.svg")'; + } + else { + button.firstChild.style['background-image'] = + 'url("' + iconsURL + + 'annotations-visible.svg")'; + } + } + fireEvent(this, 'deselectButton', { button: button }); + } + }, + /** + * Save a chart in localStorage under `highcharts-chart` key. + * Stored items: + * - annotations + * - indicators (with yAxes) + * - flags + * + * @type {Highcharts.NavigationBindingsOptionsObject} + * @product highstock + * @default {"className": "highcharts-save-chart", "init": function() {}} + */ + saveChart: { + /** @ignore-option */ + className: 'highcharts-save-chart', + // eslint-disable-next-line valid-jsdoc + /** @ignore-option */ + init: function (button) { + var navigation = this, chart = navigation.chart, annotations = [], indicators = [], flags = [], yAxes = []; + chart.annotations.forEach(function (annotation, index) { + annotations[index] = annotation.userOptions; + }); + chart.series.forEach(function (series) { + if (series.is('sma')) { + indicators.push(series.userOptions); + } + else if (series.type === 'flags') { + flags.push(series.userOptions); + } + }); + chart.yAxis.forEach(function (yAxis) { + if (bindingsUtils.isNotNavigatorYAxis(yAxis)) { + yAxes.push(yAxis.options); + } + }); + H.win.localStorage.setItem(PREFIX + 'chart', JSON.stringify({ + annotations: annotations, + indicators: indicators, + flags: flags, + yAxes: yAxes + })); + fireEvent(this, 'deselectButton', { button: button }); + } + } + }; + H.setOptions({ + navigation: { + bindings: stockToolsBindings + } + }); + NavigationBindings.prototype.utils = merge(bindingsUtils, NavigationBindings.prototype.utils); + + }); + _registerModule(_modules, 'modules/stock-tools-gui.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['annotations/navigationBindings.js']], function (H, U, NavigationBindings) { + /* * + * + * GUI generator for Stock tools + * + * (c) 2009-2017 Sebastian Bochan + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, createElement = U.createElement, css = U.css, extend = U.extend, fireEvent = U.fireEvent, getStyle = U.getStyle, isArray = U.isArray, merge = U.merge, pick = U.pick; + var win = H.win, DIV = 'div', SPAN = 'span', UL = 'ul', LI = 'li', PREFIX = 'highcharts-', activeClass = PREFIX + 'active'; + H.setOptions({ + /** + * @optionparent lang + */ + lang: { + /** + * Configure the stockTools GUI titles(hints) in the chart. Requires + * the `stock-tools.js` module to be loaded. + * + * @product highstock + * @since 7.0.0 + */ + stockTools: { + gui: { + // Main buttons: + simpleShapes: 'Simple shapes', + lines: 'Lines', + crookedLines: 'Crooked lines', + measure: 'Measure', + advanced: 'Advanced', + toggleAnnotations: 'Toggle annotations', + verticalLabels: 'Vertical labels', + flags: 'Flags', + zoomChange: 'Zoom change', + typeChange: 'Type change', + saveChart: 'Save chart', + indicators: 'Indicators', + currentPriceIndicator: 'Current Price Indicators', + // Other features: + zoomX: 'Zoom X', + zoomY: 'Zoom Y', + zoomXY: 'Zooom XY', + fullScreen: 'Fullscreen', + typeOHLC: 'OHLC', + typeLine: 'Line', + typeCandlestick: 'Candlestick', + // Basic shapes: + circle: 'Circle', + label: 'Label', + rectangle: 'Rectangle', + // Flags: + flagCirclepin: 'Flag circle', + flagDiamondpin: 'Flag diamond', + flagSquarepin: 'Flag square', + flagSimplepin: 'Flag simple', + // Measures: + measureXY: 'Measure XY', + measureX: 'Measure X', + measureY: 'Measure Y', + // Segment, ray and line: + segment: 'Segment', + arrowSegment: 'Arrow segment', + ray: 'Ray', + arrowRay: 'Arrow ray', + line: 'Line', + arrowLine: 'Arrow line', + horizontalLine: 'Horizontal line', + verticalLine: 'Vertical line', + infinityLine: 'Infinity line', + // Crooked lines: + crooked3: 'Crooked 3 line', + crooked5: 'Crooked 5 line', + elliott3: 'Elliott 3 line', + elliott5: 'Elliott 5 line', + // Counters: + verticalCounter: 'Vertical counter', + verticalLabel: 'Vertical label', + verticalArrow: 'Vertical arrow', + // Advanced: + fibonacci: 'Fibonacci', + pitchfork: 'Pitchfork', + parallelChannel: 'Parallel channel' + } + }, + navigation: { + popup: { + // Annotations: + circle: 'Circle', + rectangle: 'Rectangle', + label: 'Label', + segment: 'Segment', + arrowSegment: 'Arrow segment', + ray: 'Ray', + arrowRay: 'Arrow ray', + line: 'Line', + arrowLine: 'Arrow line', + horizontalLine: 'Horizontal line', + verticalLine: 'Vertical line', + crooked3: 'Crooked 3 line', + crooked5: 'Crooked 5 line', + elliott3: 'Elliott 3 line', + elliott5: 'Elliott 5 line', + verticalCounter: 'Vertical counter', + verticalLabel: 'Vertical label', + verticalArrow: 'Vertical arrow', + fibonacci: 'Fibonacci', + pitchfork: 'Pitchfork', + parallelChannel: 'Parallel channel', + infinityLine: 'Infinity line', + measure: 'Measure', + measureXY: 'Measure XY', + measureX: 'Measure X', + measureY: 'Measure Y', + // Flags: + flags: 'Flags', + // GUI elements: + addButton: 'add', + saveButton: 'save', + editButton: 'edit', + removeButton: 'remove', + series: 'Series', + volume: 'Volume', + connector: 'Connector', + // Field names: + innerBackground: 'Inner background', + outerBackground: 'Outer background', + crosshairX: 'Crosshair X', + crosshairY: 'Crosshair Y', + tunnel: 'Tunnel', + background: 'Background' + } + } + }, + /** + * Configure the stockTools gui strings in the chart. Requires the + * [stockTools module]() to be loaded. For a description of the module + * and information on its features, see [Highcharts StockTools](). + * + * @product highstock + * + * @sample stock/demo/stock-tools-gui Stock Tools GUI + * + * @sample stock/demo/stock-tools-custom-gui Stock Tools customized GUI + * + * @since 7.0.0 + * @optionparent stockTools + */ + stockTools: { + /** + * Definitions of buttons in Stock Tools GUI. + */ + gui: { + /** + * Path where Highcharts will look for icons. Change this to use + * icons from a different server. + * + * Since 7.1.3 use [iconsURL](#navigation.iconsURL) for popup and + * stock tools. + * + * @deprecated + * @apioption stockTools.gui.iconsURL + * + */ + /** + * Enable or disable the stockTools gui. + */ + enabled: true, + /** + * A CSS class name to apply to the stocktools' div, + * allowing unique CSS styling for each chart. + */ + className: 'highcharts-bindings-wrapper', + /** + * A CSS class name to apply to the container of buttons, + * allowing unique CSS styling for each chart. + */ + toolbarClassName: 'stocktools-toolbar', + /** + * A collection of strings pointing to config options for the + * toolbar items. Each name refers to unique key from definitions + * object. + * + * @default [ + * 'indicators', + * 'separator', + * 'simpleShapes', + * 'lines', + * 'crookedLines', + * 'measure', + * 'advanced', + * 'toggleAnnotations', + * 'separator', + * 'verticalLabels', + * 'flags', + * 'separator', + * 'zoomChange', + * 'fullScreen', + * 'typeChange', + * 'separator', + * 'currentPriceIndicator', + * 'saveChart' + * ] + */ + buttons: [ + 'indicators', + 'separator', + 'simpleShapes', + 'lines', + 'crookedLines', + 'measure', + 'advanced', + 'toggleAnnotations', + 'separator', + 'verticalLabels', + 'flags', + 'separator', + 'zoomChange', + 'fullScreen', + 'typeChange', + 'separator', + 'currentPriceIndicator', + 'saveChart' + ], + /** + * An options object of the buttons definitions. Each name refers to + * unique key from buttons array. + */ + definitions: { + separator: { + /** + * A predefined background symbol for the button. + */ + symbol: 'separator.svg' + }, + simpleShapes: { + /** + * A collection of strings pointing to config options for + * the items. + * + * @type {array} + * @default [ + * 'label', + * 'circle', + * 'rectangle' + * ] + * + */ + items: [ + 'label', + 'circle', + 'rectangle' + ], + circle: { + /** + * A predefined background symbol for the button. + * + * @type {string} + * + */ + symbol: 'circle.svg' + }, + rectangle: { + /** + * A predefined background symbol for the button. + * + * @type {string} + * + */ + symbol: 'rectangle.svg' + }, + label: { + /** + * A predefined background symbol for the button. + * + * @type {string} + * + */ + symbol: 'label.svg' + } + }, + flags: { + /** + * A collection of strings pointing to config options for + * the items. + * + * @type {array} + * @default [ + * 'flagCirclepin', + * 'flagDiamondpin', + * 'flagSquarepin', + * 'flagSimplepin' + * ] + * + */ + items: [ + 'flagCirclepin', + 'flagDiamondpin', + 'flagSquarepin', + 'flagSimplepin' + ], + flagSimplepin: { + /** + * A predefined background symbol for the button. + * + * @type {string} + * + */ + symbol: 'flag-basic.svg' + }, + flagDiamondpin: { + /** + * A predefined background symbol for the button. + * + * @type {string} + * + */ + symbol: 'flag-diamond.svg' + }, + flagSquarepin: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'flag-trapeze.svg' + }, + flagCirclepin: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'flag-elipse.svg' + } + }, + lines: { + /** + * A collection of strings pointing to config options for + * the items. + * + * @type {array} + * @default [ + * 'segment', + * 'arrowSegment', + * 'ray', + * 'arrowRay', + * 'line', + * 'arrowLine', + * 'horizontalLine', + * 'verticalLine' + * ] + */ + items: [ + 'segment', + 'arrowSegment', + 'ray', + 'arrowRay', + 'line', + 'arrowLine', + 'horizontalLine', + 'verticalLine' + ], + segment: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'segment.svg' + }, + arrowSegment: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'arrow-segment.svg' + }, + ray: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'ray.svg' + }, + arrowRay: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'arrow-ray.svg' + }, + line: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'line.svg' + }, + arrowLine: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'arrow-line.svg' + }, + verticalLine: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'vertical-line.svg' + }, + horizontalLine: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'horizontal-line.svg' + } + }, + crookedLines: { + /** + * A collection of strings pointing to config options for + * the items. + * + * @type {array} + * @default [ + * 'elliott3', + * 'elliott5', + * 'crooked3', + * 'crooked5' + * ] + * + */ + items: [ + 'elliott3', + 'elliott5', + 'crooked3', + 'crooked5' + ], + crooked3: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'crooked-3.svg' + }, + crooked5: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'crooked-5.svg' + }, + elliott3: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'elliott-3.svg' + }, + elliott5: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'elliott-5.svg' + } + }, + verticalLabels: { + /** + * A collection of strings pointing to config options for + * the items. + * + * @type {array} + * @default [ + * 'verticalCounter', + * 'verticalLabel', + * 'verticalArrow' + * ] + */ + items: [ + 'verticalCounter', + 'verticalLabel', + 'verticalArrow' + ], + verticalCounter: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'vertical-counter.svg' + }, + verticalLabel: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'vertical-label.svg' + }, + verticalArrow: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'vertical-arrow.svg' + } + }, + advanced: { + /** + * A collection of strings pointing to config options for + * the items. + * + * @type {array} + * @default [ + * 'fibonacci', + * 'pitchfork', + * 'parallelChannel' + * ] + */ + items: [ + 'fibonacci', + 'pitchfork', + 'parallelChannel' + ], + pitchfork: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'pitchfork.svg' + }, + fibonacci: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'fibonacci.svg' + }, + parallelChannel: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'parallel-channel.svg' + } + }, + measure: { + /** + * A collection of strings pointing to config options for + * the items. + * + * @type {array} + * @default [ + * 'measureXY', + * 'measureX', + * 'measureY' + * ] + */ + items: [ + 'measureXY', + 'measureX', + 'measureY' + ], + measureX: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'measure-x.svg' + }, + measureY: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'measure-y.svg' + }, + measureXY: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'measure-xy.svg' + } + }, + toggleAnnotations: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'annotations-visible.svg' + }, + currentPriceIndicator: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'current-price-show.svg' + }, + indicators: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'indicators.svg' + }, + zoomChange: { + /** + * A collection of strings pointing to config options for + * the items. + * + * @type {array} + * @default [ + * 'zoomX', + * 'zoomY', + * 'zoomXY' + * ] + */ + items: [ + 'zoomX', + 'zoomY', + 'zoomXY' + ], + zoomX: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'zoom-x.svg' + }, + zoomY: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'zoom-y.svg' + }, + zoomXY: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'zoom-xy.svg' + } + }, + typeChange: { + /** + * A collection of strings pointing to config options for + * the items. + * + * @type {array} + * @default [ + * 'typeOHLC', + * 'typeLine', + * 'typeCandlestick' + * ] + */ + items: [ + 'typeOHLC', + 'typeLine', + 'typeCandlestick' + ], + typeOHLC: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'series-ohlc.svg' + }, + typeLine: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'series-line.svg' + }, + typeCandlestick: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'series-candlestick.svg' + } + }, + fullScreen: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'fullscreen.svg' + }, + saveChart: { + /** + * A predefined background symbol for the button. + * + * @type {string} + */ + symbol: 'save-chart.svg' + } + } + } + } + }); + /* eslint-disable no-invalid-this, valid-jsdoc */ + // Run HTML generator + addEvent(H.Chart, 'afterGetContainer', function () { + this.setStockTools(); + }); + addEvent(H.Chart, 'getMargins', function () { + var listWrapper = this.stockTools && this.stockTools.listWrapper, offsetWidth = listWrapper && ((listWrapper.startWidth + + getStyle(listWrapper, 'padding-left') + + getStyle(listWrapper, 'padding-right')) || listWrapper.offsetWidth); + if (offsetWidth && offsetWidth < this.plotWidth) { + this.plotLeft += offsetWidth; + } + }); + addEvent(H.Chart, 'destroy', function () { + if (this.stockTools) { + this.stockTools.destroy(); + } + }); + addEvent(H.Chart, 'redraw', function () { + if (this.stockTools && this.stockTools.guiEnabled) { + this.stockTools.redraw(); + } + }); + /** + * Toolbar Class + * @private + * @constructor + * @param {Object} - options of toolbar + * @param {Chart} - Reference to chart + */ + var Toolbar = /** @class */ (function () { + function Toolbar(options, langOptions, chart) { + this.arrowDown = void 0; + this.arrowUp = void 0; + this.arrowWrapper = void 0; + this.listWrapper = void 0; + this.showhideBtn = void 0; + this.submenu = void 0; + this.toolbar = void 0; + this.wrapper = void 0; + this.chart = chart; + this.options = options; + this.lang = langOptions; + // set url for icons. + this.iconsURL = this.getIconsURL(); + this.guiEnabled = options.enabled; + this.visible = pick(options.visible, true); + this.placed = pick(options.placed, false); + // General events collection which should be removed upon + // destroy/update: + this.eventsToUnbind = []; + if (this.guiEnabled) { + this.createHTML(); + this.init(); + this.showHideNavigatorion(); + } + fireEvent(this, 'afterInit'); + } + /** + * Initialize the toolbar. Create buttons and submenu for each option + * defined in `stockTools.gui`. + * @private + */ + Toolbar.prototype.init = function () { + var _self = this, lang = this.lang, guiOptions = this.options, toolbar = this.toolbar, addSubmenu = _self.addSubmenu, buttons = guiOptions.buttons, defs = guiOptions.definitions, allButtons = toolbar.childNodes, button; + // create buttons + buttons.forEach(function (btnName) { + button = _self.addButton(toolbar, defs, btnName, lang); + _self.eventsToUnbind.push(addEvent(button.buttonWrapper, 'click', function () { + _self.eraseActiveButtons(allButtons, button.buttonWrapper); + })); + if (isArray(defs[btnName].items)) { + // create submenu buttons + addSubmenu.call(_self, button, defs[btnName]); + } + }); + }; + /** + * Create submenu (list of buttons) for the option. In example main button + * is Line, in submenu will be buttons with types of lines. + * @private + * @param {Highcharts.Dictionary} + * button which has submenu + * @param {Highcharts.StockToolsGuiDefinitionsButtonsOptions} + * list of all buttons + */ + Toolbar.prototype.addSubmenu = function (parentBtn, button) { + var _self = this, submenuArrow = parentBtn.submenuArrow, buttonWrapper = parentBtn.buttonWrapper, buttonWidth = getStyle(buttonWrapper, 'width'), wrapper = this.wrapper, menuWrapper = this.listWrapper, allButtons = this.toolbar.childNodes, topMargin = 0, submenuWrapper; + // create submenu container + this.submenu = submenuWrapper = createElement(UL, { + className: PREFIX + 'submenu-wrapper' + }, null, buttonWrapper); + // create submenu buttons and select the first one + this.addSubmenuItems(buttonWrapper, button); + // show / hide submenu + _self.eventsToUnbind.push(addEvent(submenuArrow, 'click', function (e) { + e.stopPropagation(); + // Erase active class on all other buttons + _self.eraseActiveButtons(allButtons, buttonWrapper); + // hide menu + if (buttonWrapper.className.indexOf(PREFIX + 'current') >= 0) { + menuWrapper.style.width = + menuWrapper.startWidth + 'px'; + buttonWrapper.classList.remove(PREFIX + 'current'); + submenuWrapper.style.display = 'none'; + } + else { + // show menu + // to calculate height of element + submenuWrapper.style.display = 'block'; + topMargin = submenuWrapper.offsetHeight - + buttonWrapper.offsetHeight - 3; + // calculate position of submenu in the box + // if submenu is inside, reset top margin + if ( + // cut on the bottom + !(submenuWrapper.offsetHeight + + buttonWrapper.offsetTop > + wrapper.offsetHeight && + // cut on the top + buttonWrapper.offsetTop > topMargin)) { + topMargin = 0; + } + // apply calculated styles + css(submenuWrapper, { + top: -topMargin + 'px', + left: buttonWidth + 3 + 'px' + }); + buttonWrapper.className += ' ' + PREFIX + 'current'; + menuWrapper.startWidth = wrapper.offsetWidth; + menuWrapper.style.width = menuWrapper.startWidth + + getStyle(menuWrapper, 'padding-left') + + submenuWrapper.offsetWidth + 3 + 'px'; + } + })); + }; + /** + * Create buttons in submenu + * @private + * @param {Highcharts.HTMLDOMElement} + * button where submenu is placed + * @param {Highcharts.StockToolsGuiDefinitionsButtonsOptions} + * list of all buttons options + * + */ + Toolbar.prototype.addSubmenuItems = function (buttonWrapper, button) { + var _self = this, submenuWrapper = this.submenu, lang = this.lang, menuWrapper = this.listWrapper, items = button.items, firstSubmenuItem, submenuBtn; + // add items to submenu + items.forEach(function (btnName) { + // add buttons to submenu + submenuBtn = _self.addButton(submenuWrapper, button, btnName, lang); + _self.eventsToUnbind.push(addEvent(submenuBtn.mainButton, 'click', function () { + _self.switchSymbol(this, buttonWrapper, true); + menuWrapper.style.width = + menuWrapper.startWidth + 'px'; + submenuWrapper.style.display = 'none'; + })); + }); + // select first submenu item + firstSubmenuItem = submenuWrapper + .querySelectorAll('li > .' + PREFIX + 'menu-item-btn')[0]; + // replace current symbol, in main button, with submenu's button style + _self.switchSymbol(firstSubmenuItem, false); + }; + /* + * Erase active class on all other buttons. + * + * @param {Array} - Array of HTML buttons + * @param {HTMLDOMElement} - Current HTML button + * + */ + Toolbar.prototype.eraseActiveButtons = function (buttons, currentButton, submenuItems) { + [].forEach.call(buttons, function (btn) { + if (btn !== currentButton) { + btn.classList.remove(PREFIX + 'current'); + btn.classList.remove(PREFIX + 'active'); + submenuItems = + btn.querySelectorAll('.' + PREFIX + 'submenu-wrapper'); + // hide submenu + if (submenuItems.length > 0) { + submenuItems[0].style.display = 'none'; + } + } + }); + }; + /** + * Create single button. Consist of HTML elements `li`, `span`, and (if + * exists) submenu container. + * @private + * @param {Highcharts.HTMLDOMElement} target + * HTML reference, where button should be added + * @param {Highcharts.StockToolsGuiDefinitionsButtonsOptions|Highcharts.StockToolsGuiDefinitionsOptions} options + * All options, by btnName refer to particular button + * @param {string} btnName + * of functionality mapped for specific class + * @param {Highcharts.Dictionary} lang + * All titles, by btnName refer to particular button + * @return {Object} - references to all created HTML elements + */ + Toolbar.prototype.addButton = function (target, options, btnName, lang) { + if (lang === void 0) { lang = {}; } + var btnOptions = options[btnName], items = btnOptions.items, classMapping = Toolbar.prototype.classMapping, userClassName = btnOptions.className || '', mainButton, submenuArrow, buttonWrapper; + // main button wrapper + buttonWrapper = createElement(LI, { + className: pick(classMapping[btnName], '') + ' ' + userClassName, + title: lang[btnName] || btnName + }, null, target); + // single button + mainButton = createElement(SPAN, { + className: PREFIX + 'menu-item-btn' + }, null, buttonWrapper); + // submenu + if (items && items.length) { + // arrow is a hook to show / hide submenu + submenuArrow = createElement(SPAN, { + className: PREFIX + 'submenu-item-arrow ' + + PREFIX + 'arrow-right' + }, null, buttonWrapper); + submenuArrow.style['background-image'] = 'url(' + + this.iconsURL + 'arrow-bottom.svg)'; + } + else { + mainButton.style['background-image'] = 'url(' + + this.iconsURL + btnOptions.symbol + ')'; + } + return { + buttonWrapper: buttonWrapper, + mainButton: mainButton, + submenuArrow: submenuArrow + }; + }; + /* + * Create navigation's HTML elements: container and arrows. + * + */ + Toolbar.prototype.addNavigation = function () { + var stockToolbar = this, wrapper = stockToolbar.wrapper; + // arrow wrapper + stockToolbar.arrowWrapper = createElement(DIV, { + className: PREFIX + 'arrow-wrapper' + }); + stockToolbar.arrowUp = createElement(DIV, { + className: PREFIX + 'arrow-up' + }, null, stockToolbar.arrowWrapper); + stockToolbar.arrowUp.style['background-image'] = + 'url(' + this.iconsURL + 'arrow-right.svg)'; + stockToolbar.arrowDown = createElement(DIV, { + className: PREFIX + 'arrow-down' + }, null, stockToolbar.arrowWrapper); + stockToolbar.arrowDown.style['background-image'] = + 'url(' + this.iconsURL + 'arrow-right.svg)'; + wrapper.insertBefore(stockToolbar.arrowWrapper, wrapper.childNodes[0]); + // attach scroll events + stockToolbar.scrollButtons(); + }; + /* + * Add events to navigation (two arrows) which allows user to scroll + * top/down GUI buttons, if container's height is not enough. + * + */ + Toolbar.prototype.scrollButtons = function () { + var targetY = 0, _self = this, wrapper = _self.wrapper, toolbar = _self.toolbar, step = 0.1 * wrapper.offsetHeight; // 0.1 = 10% + _self.eventsToUnbind.push(addEvent(_self.arrowUp, 'click', function () { + if (targetY > 0) { + targetY -= step; + toolbar.style['margin-top'] = -targetY + 'px'; + } + })); + _self.eventsToUnbind.push(addEvent(_self.arrowDown, 'click', function () { + if (wrapper.offsetHeight + targetY <= + toolbar.offsetHeight + step) { + targetY += step; + toolbar.style['margin-top'] = -targetY + 'px'; + } + })); + }; + /* + * Create stockTools HTML main elements. + * + */ + Toolbar.prototype.createHTML = function () { + var stockToolbar = this, chart = stockToolbar.chart, guiOptions = stockToolbar.options, container = chart.container, navigation = chart.options.navigation, bindingsClassName = navigation && navigation.bindingsClassName, listWrapper, toolbar, wrapper; + // create main container + stockToolbar.wrapper = wrapper = createElement(DIV, { + className: PREFIX + 'stocktools-wrapper ' + + guiOptions.className + ' ' + bindingsClassName + }); + container.parentNode.insertBefore(wrapper, container); + // toolbar + stockToolbar.toolbar = toolbar = createElement(UL, { + className: PREFIX + 'stocktools-toolbar ' + + guiOptions.toolbarClassName + }); + // add container for list of buttons + stockToolbar.listWrapper = listWrapper = createElement(DIV, { + className: PREFIX + 'menu-wrapper' + }); + wrapper.insertBefore(listWrapper, wrapper.childNodes[0]); + listWrapper.insertBefore(toolbar, listWrapper.childNodes[0]); + stockToolbar.showHideToolbar(); + // add navigation which allows user to scroll down / top GUI buttons + stockToolbar.addNavigation(); + }; + /** + * Function called in redraw verifies if the navigation should be visible. + * @private + */ + Toolbar.prototype.showHideNavigatorion = function () { + // arrows + // 50px space for arrows + if (this.visible && + this.toolbar.offsetHeight > (this.wrapper.offsetHeight - 50)) { + this.arrowWrapper.style.display = 'block'; + } + else { + // reset margin if whole toolbar is visible + this.toolbar.style.marginTop = '0px'; + // hide arrows + this.arrowWrapper.style.display = 'none'; + } + }; + /** + * Create button which shows or hides GUI toolbar. + * @private + */ + Toolbar.prototype.showHideToolbar = function () { + var stockToolbar = this, chart = this.chart, wrapper = stockToolbar.wrapper, toolbar = this.listWrapper, submenu = this.submenu, visible = this.visible, showhideBtn; + // Show hide toolbar + this.showhideBtn = showhideBtn = createElement(DIV, { + className: PREFIX + 'toggle-toolbar ' + PREFIX + 'arrow-left' + }, null, wrapper); + showhideBtn.style['background-image'] = + 'url(' + this.iconsURL + 'arrow-right.svg)'; + if (!visible) { + // hide + if (submenu) { + submenu.style.display = 'none'; + } + showhideBtn.style.left = '0px'; + stockToolbar.visible = visible = false; + toolbar.classList.add(PREFIX + 'hide'); + showhideBtn.classList.toggle(PREFIX + 'arrow-right'); + wrapper.style.height = showhideBtn.offsetHeight + 'px'; + } + else { + wrapper.style.height = '100%'; + showhideBtn.style.top = getStyle(toolbar, 'padding-top') + 'px'; + showhideBtn.style.left = (wrapper.offsetWidth + + getStyle(toolbar, 'padding-left')) + 'px'; + } + // Toggle menu + stockToolbar.eventsToUnbind.push(addEvent(showhideBtn, 'click', function () { + chart.update({ + stockTools: { + gui: { + visible: !visible, + placed: true + } + } + }); + })); + }; + /* + * In main GUI button, replace icon and class with submenu button's + * class / symbol. + * + * @param {HTMLDOMElement} - submenu button + * @param {Boolean} - true or false + * + */ + Toolbar.prototype.switchSymbol = function (button, redraw) { + var buttonWrapper = button.parentNode, buttonWrapperClass = buttonWrapper.classList.value, + // main button in first level og GUI + mainNavButton = buttonWrapper.parentNode.parentNode; + // set class + mainNavButton.className = ''; + if (buttonWrapperClass) { + mainNavButton.classList.add(buttonWrapperClass.trim()); + } + // set icon + mainNavButton + .querySelectorAll('.' + PREFIX + 'menu-item-btn')[0] + .style['background-image'] = + button.style['background-image']; + // set active class + if (redraw) { + this.selectButton(mainNavButton); + } + }; + /* + * Set select state (active class) on button. + * + * @param {HTMLDOMElement} - button + * + */ + Toolbar.prototype.selectButton = function (button) { + if (button.className.indexOf(activeClass) >= 0) { + button.classList.remove(activeClass); + } + else { + button.classList.add(activeClass); + } + }; + /* + * Remove active class from all buttons except defined. + * + * @param {HTMLDOMElement} - button which should not be deactivated + * + */ + Toolbar.prototype.unselectAllButtons = function (button) { + var activeButtons = button.parentNode + .querySelectorAll('.' + activeClass); + [].forEach.call(activeButtons, function (activeBtn) { + if (activeBtn !== button) { + activeBtn.classList.remove(activeClass); + } + }); + }; + /* + * Update GUI with given options. + * + * @param {Object} - general options for Stock Tools + */ + Toolbar.prototype.update = function (options) { + merge(true, this.chart.options.stockTools, options); + this.destroy(); + this.chart.setStockTools(options); + // If Stock Tools are updated, then bindings should be updated too: + if (this.chart.navigationBindings) { + this.chart.navigationBindings.update(); + } + }; + /** + * Destroy all HTML GUI elements. + * @private + */ + Toolbar.prototype.destroy = function () { + var stockToolsDiv = this.wrapper, parent = stockToolsDiv && stockToolsDiv.parentNode; + this.eventsToUnbind.forEach(function (unbinder) { + unbinder(); + }); + // Remove the empty element + if (parent) { + parent.removeChild(stockToolsDiv); + } + // redraw + this.chart.isDirtyBox = true; + this.chart.redraw(); + }; + /** + * Redraw, GUI requires to verify if the navigation should be visible. + * @private + */ + Toolbar.prototype.redraw = function () { + this.showHideNavigatorion(); + }; + Toolbar.prototype.getIconsURL = function () { + return this.chart.options.navigation.iconsURL || + this.options.iconsURL || + 'https://code.highcharts.com/8.1.0/gfx/stock-icons/'; + }; + return Toolbar; + }()); + /** + * Mapping JSON fields to CSS classes. + * @private + */ + Toolbar.prototype.classMapping = { + circle: PREFIX + 'circle-annotation', + rectangle: PREFIX + 'rectangle-annotation', + label: PREFIX + 'label-annotation', + segment: PREFIX + 'segment', + arrowSegment: PREFIX + 'arrow-segment', + ray: PREFIX + 'ray', + arrowRay: PREFIX + 'arrow-ray', + line: PREFIX + 'infinity-line', + arrowLine: PREFIX + 'arrow-infinity-line', + verticalLine: PREFIX + 'vertical-line', + horizontalLine: PREFIX + 'horizontal-line', + crooked3: PREFIX + 'crooked3', + crooked5: PREFIX + 'crooked5', + elliott3: PREFIX + 'elliott3', + elliott5: PREFIX + 'elliott5', + pitchfork: PREFIX + 'pitchfork', + fibonacci: PREFIX + 'fibonacci', + parallelChannel: PREFIX + 'parallel-channel', + measureX: PREFIX + 'measure-x', + measureY: PREFIX + 'measure-y', + measureXY: PREFIX + 'measure-xy', + verticalCounter: PREFIX + 'vertical-counter', + verticalLabel: PREFIX + 'vertical-label', + verticalArrow: PREFIX + 'vertical-arrow', + currentPriceIndicator: PREFIX + 'current-price-indicator', + indicators: PREFIX + 'indicators', + flagCirclepin: PREFIX + 'flag-circlepin', + flagDiamondpin: PREFIX + 'flag-diamondpin', + flagSquarepin: PREFIX + 'flag-squarepin', + flagSimplepin: PREFIX + 'flag-simplepin', + zoomX: PREFIX + 'zoom-x', + zoomY: PREFIX + 'zoom-y', + zoomXY: PREFIX + 'zoom-xy', + typeLine: PREFIX + 'series-type-line', + typeOHLC: PREFIX + 'series-type-ohlc', + typeCandlestick: PREFIX + 'series-type-candlestick', + fullScreen: PREFIX + 'full-screen', + toggleAnnotations: PREFIX + 'toggle-annotations', + saveChart: PREFIX + 'save-chart', + separator: PREFIX + 'separator' + }; + extend(H.Chart.prototype, { + /** + * Verify if Toolbar should be added. + * @private + * @param {Highcharts.StockToolsOptions} - chart options + * @return {void} + */ + setStockTools: function (options) { + var chartOptions = this.options, lang = chartOptions.lang, guiOptions = merge(chartOptions.stockTools && chartOptions.stockTools.gui, options && options.gui), langOptions = lang.stockTools && lang.stockTools.gui; + this.stockTools = new H.Toolbar(guiOptions, langOptions, this); + if (this.stockTools.guiEnabled) { + this.isDirtyBox = true; + } + } + }); + // Comunication with bindings: + addEvent(NavigationBindings, 'selectButton', function (event) { + var button = event.button, className = PREFIX + 'submenu-wrapper', gui = this.chart.stockTools; + if (gui && gui.guiEnabled) { + // Unslect other active buttons + gui.unselectAllButtons(event.button); + // If clicked on a submenu, select state for it's parent + if (button.parentNode.className.indexOf(className) >= 0) { + button = button.parentNode.parentNode; + } + // Set active class on the current button + gui.selectButton(button); + } + }); + addEvent(NavigationBindings, 'deselectButton', function (event) { + var button = event.button, className = PREFIX + 'submenu-wrapper', gui = this.chart.stockTools; + if (gui && gui.guiEnabled) { + // If deselecting a button from a submenu, select state for it's parent + if (button.parentNode.className.indexOf(className) >= 0) { + button = button.parentNode.parentNode; + } + gui.selectButton(button); + } + }); + H.Toolbar = Toolbar; + + return H.Toolbar; + }); + _registerModule(_modules, 'masters/modules/stock-tools.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/streamgraph.js b/librerias/gantt/code/modules/streamgraph.js new file mode 100644 index 0000000..356e5e7 --- /dev/null +++ b/librerias/gantt/code/modules/streamgraph.js @@ -0,0 +1,12 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Streamgraph module + + (c) 2010-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/streamgraph",["highcharts"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,d,b,c){a.hasOwnProperty(d)||(a[d]=c.apply(null,b))}a=a?a._modules:{};b(a,"modules/streamgraph.src.js",[a["parts/Utilities.js"]],function(a){a=a.seriesType;a("streamgraph","areaspline",{fillOpacity:1, +lineWidth:0,marker:{enabled:!1},stacking:"stream"},{negStacks:!1,streamStacker:function(a,b,c){a[0]-=b.total/2;a[1]-=b.total/2;this.stackedYData[c]=a}});""});b(a,"masters/modules/streamgraph.src.js",[],function(){})}); +//# sourceMappingURL=streamgraph.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/streamgraph.js.map b/librerias/gantt/code/modules/streamgraph.js.map new file mode 100644 index 0000000..b2e1f47 --- /dev/null +++ b/librerias/gantt/code/modules/streamgraph.js.map @@ -0,0 +1 @@ +{"version":3,"file":"streamgraph.js.map","lineCount":11,"mappings":"A;;;;;;;;;AAUC,SAAS,CAACA,CAAD,CAAU,CACM,QAAtB,GAAI,MAAOC,OAAX,EAAkCA,MAAAC,QAAlC,EACIF,CAAA,CAAQ,SAAR,CACA,CADqBA,CACrB,CAAAC,MAAAC,QAAA,CAAiBF,CAFrB,EAG6B,UAAtB,GAAI,MAAOG,OAAX,EAAoCA,MAAAC,IAApC,CACHD,MAAA,CAAO,gCAAP,CAAyC,CAAC,YAAD,CAAzC,CAAyD,QAAS,CAACE,CAAD,CAAa,CAC3EL,CAAA,CAAQK,CAAR,CACAL,EAAAK,WAAA,CAAqBA,CACrB,OAAOL,EAHoE,CAA/E,CADG,CAOHA,CAAA,CAA8B,WAAtB,GAAA,MAAOK,WAAP,CAAoCA,UAApC,CAAiDC,IAAAA,EAAzD,CAXY,CAAnB,CAAA,CAaC,QAAS,CAACD,CAAD,CAAa,CAEpBE,QAASA,EAAe,CAACC,CAAD,CAAMC,CAAN,CAAYC,CAAZ,CAAkBC,CAAlB,CAAsB,CACrCH,CAAAI,eAAA,CAAmBH,CAAnB,CAAL,GACID,CAAA,CAAIC,CAAJ,CADJ,CACgBE,CAAAE,MAAA,CAAS,IAAT,CAAeH,CAAf,CADhB,CAD0C,CAD1CI,CAAAA,CAAWT,CAAA,CAAaA,CAAAS,SAAb,CAAmC,EAMlDP,EAAA,CAAgBO,CAAhB,CAA0B,4BAA1B,CAAwD,CAACA,CAAA,CAAS,oBAAT,CAAD,CAAxD,CAA0F,QAAS,CAACC,CAAD,CAAI,CAY/FC,CAAAA,CAAaD,CAAAC,WAQjBA,EAAA,CAAW,aAAX,CAA0B,YAA1B,CAcE,CACEC,YAAa,CADf;AAEEC,UAAW,CAFb,CAGEC,OAAQ,CACJC,QAAS,CAAA,CADL,CAHV,CAMEC,SAAU,QANZ,CAdF,CAsBG,CACCC,UAAW,CAAA,CADZ,CAICC,cAAeA,QAAS,CAACC,CAAD,CAAgBC,CAAhB,CAAuBC,CAAvB,CAA0B,CAE9CF,CAAA,CAAc,CAAd,CAAA,EAAoBC,CAAAE,MAApB,CAAkC,CAElCH,EAAA,CAAc,CAAd,CAAA,EAAoBC,CAAAE,MAApB,CAAkC,CAElC,KAAAC,aAAA,CAAkBF,CAAlB,CAAA,CAAuBF,CANuB,CAJnD,CAtBH,CAwGA,GA5HmG,CAAvG,CA+HAjB,EAAA,CAAgBO,CAAhB,CAA0B,oCAA1B,CAAgE,EAAhE,CAAoE,QAAS,EAAG,EAAhF,CAtIoB,CAbvB;","sources":["streamgraph.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","U","seriesType","fillOpacity","lineWidth","marker","enabled","stacking","negStacks","streamStacker","pointExtremes","stack","i","total","stackedYData"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/streamgraph.src.js b/librerias/gantt/code/modules/streamgraph.src.js new file mode 100644 index 0000000..c1b39e4 --- /dev/null +++ b/librerias/gantt/code/modules/streamgraph.src.js @@ -0,0 +1,162 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * Streamgraph module + * + * (c) 2010-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/streamgraph', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'modules/streamgraph.src.js', [_modules['parts/Utilities.js']], function (U) { + /* * + * + * Streamgraph module + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var seriesType = U.seriesType; + /** + * @private + * @class + * @name Highcharts.seriesTypes.streamgraph + * + * @augments Highcharts.Series + */ + seriesType('streamgraph', 'areaspline' + /** + * A streamgraph is a type of stacked area graph which is displaced around a + * central axis, resulting in a flowing, organic shape. + * + * @sample {highcharts|highstock} highcharts/demo/streamgraph/ + * Streamgraph + * + * @extends plotOptions.areaspline + * @since 6.0.0 + * @product highcharts highstock + * @requires modules/streamgraph + * @optionparent plotOptions.streamgraph + */ + , { + fillOpacity: 1, + lineWidth: 0, + marker: { + enabled: false + }, + stacking: 'stream' + // Prototype functions + }, { + negStacks: false, + // Modifier function for stream stacks. It simply moves the point up or + // down in order to center the full stack vertically. + streamStacker: function (pointExtremes, stack, i) { + // Y bottom value + pointExtremes[0] -= stack.total / 2; + // Y value + pointExtremes[1] -= stack.total / 2; + // Record the Y data for use when getting axis extremes + this.stackedYData[i] = pointExtremes; + } + }); + /** + * A `streamgraph` series. If the [type](#series.streamgraph.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.streamgraph + * @excluding dataParser, dataURL, step + * @product highcharts highstock + * @requires modules/streamgraph + * @apioption series.streamgraph + */ + /** + * An array of data points for the series. For the `streamgraph` series type, + * points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `y` options. The `x` values will be automatically + * calculated, either starting at 0 and incremented by 1, or from + * `pointStart` and `pointInterval` given in the series options. If the axis + * has categories, these will be used. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of arrays with 2 values. In this case, the values correspond to + * `x,y`. If the first value is a string, it is applied as the name of the + * point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 9], + * [1, 7], + * [2, 6] + * ] + * ``` + * + * 3. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.area.turboThreshold), + * this option is not available. + * ```js + * data: [{ + * x: 1, + * y: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|null|*>} + * @extends series.line.data + * @product highcharts highstock + * @apioption series.streamgraph.data + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'masters/modules/streamgraph.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/sunburst.js b/librerias/gantt/code/modules/sunburst.js new file mode 100644 index 0000000..d4a9ae2 --- /dev/null +++ b/librerias/gantt/code/modules/sunburst.js @@ -0,0 +1,57 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2016-2019 Highsoft AS + Authors: Jon Arild Nygard + + License: www.highcharts.com/license +*/ +(function(d){"object"===typeof module&&module.exports?(d["default"]=d,module.exports=d):"function"===typeof define&&define.amd?define("highcharts/modules/sunburst",["highcharts"],function(C){d(C);d.Highcharts=C;return d}):d("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(d){function C(d,b,y,w){d.hasOwnProperty(b)||(d[b]=w.apply(null,y))}d=d?d._modules:{};C(d,"mixins/draw-point.js",[],function(){var d=function(b){var d,w=this,u=w.graphic,m=b.animatableAttribs,l=b.onComplete,q=b.css,B= +b.renderer,g=null===(d=w.series)||void 0===d?void 0:d.options.animation;if(w.shouldDraw())u||(w.graphic=u=B[b.shapeType](b.shapeArgs).add(b.group)),u.css(q).attr(b.attribs).animate(m,b.isNew?!1:g,l);else if(u){var t=function(){w.graphic=u=u.destroy();"function"===typeof l&&l()};Object.keys(m).length?u.animate(m,void 0,function(){t()}):t()}};return function(b){(b.attribs=b.attribs||{})["class"]=this.getClassName();d.call(this,b)}});C(d,"mixins/tree-series.js",[d["parts/Color.js"],d["parts/Utilities.js"]], +function(d,b){var y=b.extend,w=b.isArray,u=b.isNumber,m=b.isObject,l=b.merge,q=b.pick;return{getColor:function(b,g){var t=g.index,l=g.mapOptionsToLevel,B=g.parentColor,w=g.parentColorIndex,m=g.series,F=g.colors,u=g.siblings,v=m.points,G=m.chart.options.chart,E;if(b){v=v[b.i];b=l[b.level]||{};if(l=v&&b.colorByPoint){var D=v.index%(F?F.length:G.colorCount);var y=F&&F[D]}if(!m.chart.styledMode){F=v&&v.options.color;G=b&&b.color;if(E=B)E=(E=b&&b.colorVariation)&&"brightness"===E.key?d.parse(B).brighten(t/ +u*E.to).get():B;E=q(F,G,y,E,m.color)}var I=q(v&&v.options.colorIndex,b&&b.colorIndex,D,w,g.colorIndex)}return{color:E,colorIndex:I}},getLevelOptions:function(b){var g=null;if(m(b)){g={};var d=u(b.from)?b.from:1;var q=b.levels;var B={};var I=m(b.defaults)?b.defaults:{};w(q)&&(B=q.reduce(function(b,g){if(m(g)&&u(g.level)){var t=l({},g);var q="boolean"===typeof t.levelIsConstant?t.levelIsConstant:I.levelIsConstant;delete t.levelIsConstant;delete t.level;g=g.level+(q?0:d-1);m(b[g])?y(b[g],t):b[g]=t}return b}, +{}));q=u(b.to)?b.to:1;for(b=0;b<=q;b++)g[b]=l({},I,m(B[b])?B[b]:{})}return g},setTreeValues:function U(b,d){var g=d.before,l=d.idRoot,t=d.mapIdToNode[l],m=d.points[b.i],w=m&&m.options||{},v=0,u=[];y(b,{levelDynamic:b.level-(("boolean"===typeof d.levelIsConstant?d.levelIsConstant:1)?0:t.level),name:q(m&&m.name,""),visible:l===b.id||("boolean"===typeof d.visible?d.visible:!1)});"function"===typeof g&&(b=g(b,d));b.children.forEach(function(g,l){var t=y({},d);y(t,{index:l,siblings:b.children.length,visible:b.visible}); +g=U(g,t);u.push(g);g.visible&&(v+=g.val)});b.visible=0{point.name}: {point.value}
    "},ignoreHiddenPoint:!0,layoutAlgorithm:"sliceAndDice",layoutStartingDirection:"vertical",alternateStartingDirection:!1,levelIsConstant:!0,drillUpButton:{position:{align:"right",x:-10,y:10}},traverseUpButton:{position:{align:"right", +x:-10,y:10}},borderColor:"#e6e6e6",borderWidth:1,colorKey:"colorValue",opacity:.15,states:{hover:{borderColor:"#999999",brightness:K.heatmap?0:.1,halo:!1,opacity:.75,shadow:!1}}},{pointArrayMap:["value"],directTouch:!0,optionalAxis:"colorAxis",getSymbol:l,parallelArrays:["x","y","value","colorValue"],colorKey:"colorValue",trackerGroups:["group","dataLabelsGroup"],getListOfParents:function(a,c){a=M(a)?a:[];var e=M(c)?c:[];c=a.reduce(function(a,c,e){c=D(c.parent,"");"undefined"===typeof a[c]&&(a[c]= +[]);a[c].push(e);return a},{"":[]});f(c,function(a,c,b){""!==c&&-1===e.indexOf(c)&&(a.forEach(function(a){b[""].push(a)}),delete b[c])});return c},getTree:function(){var a=this.data.map(function(a){return a.id});a=this.getListOfParents(this.data,a);this.nodeMap=[];return this.buildNode("",-1,0,a,null)},hasData:function(){return!!this.processedXData.length},init:function(a,c){var e=d.colorMapSeriesMixin;e&&(this.colorAttribs=e.colorAttribs);this.eventsToUnbind.push(B(this,"setOptions",function(a){a= +a.userOptions;t(a.allowDrillToNode)&&!t(a.allowTraversingTree)&&(a.allowTraversingTree=a.allowDrillToNode,delete a.allowDrillToNode);t(a.drillUpButton)&&!t(a.traverseUpButton)&&(a.traverseUpButton=a.drillUpButton,delete a.drillUpButton)}));J.prototype.init.call(this,a,c);this.options.allowTraversingTree&&this.eventsToUnbind.push(B(this,"click",this.onClickDrillToNode))},buildNode:function(a,c,e,b,h){var f=this,x=[],p=f.points[c],d=0,k;(b[a]||[]).forEach(function(c){k=f.buildNode(f.points[c].id,c, +e+1,b,a);d=Math.max(k.height+1,d);x.push(k)});c={id:a,i:c,children:x,height:d,level:e,parent:h,visible:!1};f.nodeMap[c.id]=c;p&&(p.node=c);return c},setTreeValues:function(a){var c=this,e=c.options,b=c.nodeMap[c.rootNode];e="boolean"===typeof e.levelIsConstant?e.levelIsConstant:!0;var h=0,f=[],x=c.points[a.i];a.children.forEach(function(a){a=c.setTreeValues(a);f.push(a);a.ignore||(h+=a.val)});R(f,function(a,c){return a.sortIndex-c.sortIndex});var d=D(x&&x.options.value,h);x&&(x.value=d);C(a,{children:f, +childrenTotal:h,ignore:!(D(x&&x.visible,!0)&&0n.lP.lR&&h.algorithmCalcPoints(a,!1,n,f,d);k===z&&h.algorithmCalcPoints(a,!0,n,f,d);k+=1});return f},algorithmFill:function(a,c,e){var f=[],h,b=c.direction,d=c.x,k=c.y, +z=c.width,n=c.height,r,l,g,m;e.forEach(function(e){h=e.val/c.val*c.height*c.width;r=d;l=k;0===b?(m=n,g=h/m,z-=g,d+=g):(g=z,m=h/g,n-=m,k+=m);f.push({x:r,y:l,width:g,height:m});a&&(b=1-b)});return f},strip:function(a,c){return this.algorithmLowAspectRatio(!1,a,c)},squarified:function(a,c){return this.algorithmLowAspectRatio(!0,a,c)},sliceAndDice:function(a,c){return this.algorithmFill(!0,a,c)},stripes:function(a,c){return this.algorithmFill(!1,a,c)},translate:function(){var a=this,c=a.options,e=z(a); +J.prototype.translate.call(a);var f=a.tree=a.getTree();var b=a.nodeMap[e];a.renderTraverseUpButton(e);a.mapOptionsToLevel=O({from:b.level+1,levels:c.levels,to:f.height,defaults:{levelIsConstant:a.options.levelIsConstant,colorByPoint:c.colorByPoint}});""===e||b&&b.children.length||(a.setRootNode("",!1),e=a.rootNode,b=a.nodeMap[e]);k(a.nodeMap[a.rootNode],function(c){var e=!1,b=c.parent;c.visible=!0;if(b||""===b)e=a.nodeMap[b];return e});k(a.nodeMap[a.rootNode].children,function(a){var c=!1;a.forEach(function(a){a.visible= +!0;a.children.length&&(c=(c||[]).concat(a.children))});return c});a.setTreeValues(f);a.axisRatio=a.xAxis.len/a.yAxis.len;a.nodeMap[""].pointValues=e={x:0,y:0,width:100,height:100};a.nodeMap[""].values=e=G(e,{width:e.width*a.axisRatio,direction:"vertical"===c.layoutStartingDirection?0:1,val:f.val});a.calculateChildrenAreas(f,e);a.colorAxis||c.colorByPoint||a.setColorRecursive(a.tree);c.allowTraversingTree&&(c=b.pointValues,a.xAxis.setExtremes(c.x,c.x+c.width,!1),a.yAxis.setExtremes(c.y,c.y+c.height, +!1),a.xAxis.setScale(),a.yAxis.setScale());a.setPointValues()},drawDataLabels:function(){var a=this,c=a.mapOptionsToLevel,e,b;a.points.filter(function(a){return a.node.visible}).forEach(function(f){b=c[f.node.level];e={style:{}};f.node.isLeaf||(e.enabled=!1);b&&b.dataLabels&&(e=G(e,b.dataLabels),a._hasPointLabels=!0);f.shapeArgs&&(e.style.width=f.shapeArgs.width,f.dataLabel&&f.dataLabel.css({width:f.shapeArgs.width+"px"}));f.dlOptions=G(e,f.options.dataLabels)});J.prototype.drawDataLabels.call(this)}, +alignDataLabel:function(a,c,e){var f=e.style;!t(f.textOverflow)&&c.text&&c.getBBox().width>c.text.textWidth&&c.css({textOverflow:"ellipsis",width:f.width+="px"});K.column.prototype.alignDataLabel.apply(this,arguments);a.dataLabel&&a.dataLabel.attr({zIndex:(a.node.zIndex||0)+1})},pointAttribs:function(a,c){var e=Q(this.mapOptionsToLevel)?this.mapOptionsToLevel:{},f=a&&e[a.node.level]||{};e=this.options;var b=c&&e.states[c]||{},d=a&&a.getClassName()||"";a={stroke:a&&a.borderColor||f.borderColor||b.borderColor|| +e.borderColor,"stroke-width":D(a&&a.borderWidth,f.borderWidth,b.borderWidth,e.borderWidth),dashstyle:a&&a.borderDashStyle||f.borderDashStyle||b.borderDashStyle||e.borderDashStyle,fill:a&&a.color||this.color};-1!==d.indexOf("highcharts-above-level")?(a.fill="none",a["stroke-width"]=0):-1!==d.indexOf("highcharts-internal-node-interactive")?(c=D(b.opacity,e.opacity),a.fill=q(a.fill).setOpacity(c).get(),a.cursor="pointer"):-1!==d.indexOf("highcharts-internal-node")?a.fill="none":c&&(a.fill=q(a.fill).brighten(b.brightness).get()); +return a},drawPoints:function(){var a=this,c=a.chart,e=c.renderer,f=c.styledMode,b=a.options,d=f?{}:b.shadow,k=b.borderRadius,z=c.pointCountf.innerArcLength&&f.outerArcLength>h.radius){var H=0;f.dataLabelPath&&"circular"===A&&(k.textPath={enabled:!0})}else 11.5*h.radius?"circular"===A?k.textPath={enabled:!0, +attributes:{dy:5}}:A="parallel":(f.dataLabel&&f.dataLabel.textPathWrapper&&"circular"===A&&(k.textPath={enabled:!1}),A="perpendicular");"auto"!==A&&"circular"!==A&&(H=h.end-(h.end-h.start)/2);k.style.width="parallel"===A?Math.min(2.5*h.radius,(f.outerArcLength+f.innerArcLength)/2):h.radius;"perpendicular"===A&&f.series.chart.renderer.fontMetrics(k.style.fontSize).h>f.outerArcLength&&(k.style.width=1);k.style.width=Math.max(k.style.width-2*(k.padding||0),1);H=H*G%180;"parallel"===A&&(H-=90);90H&&(H+=180);k.rotation=H}k.textPath&&(0===f.shapeExisting.innerR&&k.textPath.enabled?(k.rotation=0,k.textPath.enabled=!1,k.style.width=Math.max(2*f.shapeExisting.r-2*(k.padding||0),1)):f.dlOptions&&f.dlOptions.textPath&&!f.dlOptions.textPath.enabled&&"circular"===A&&(k.textPath.enabled=!0),k.textPath.enabled&&(k.rotation=0,k.style.width=Math.max((f.outerArcLength+f.innerArcLength)/2-2*(k.padding||0),1)));0===k.rotation&&(k.rotation=.001);f.dlOptions=k;if(!E&&v){E=!0;var V=F}f.draw({animatableAttribs:P, +attribs:l(z,!u.styledMode&&b.pointAttribs(f,f.selected&&"select")),onComplete:V,group:m,renderer:D,shapeType:"arc",shapeArgs:n})});v&&E?(b.hasRendered=!1,b.options.dataLabels.defer=!0,L.prototype.drawDataLabels.call(b),b.hasRendered=!0,y&&F()):L.prototype.drawDataLabels.call(b)},pointAttribs:E.column.prototype.pointAttribs,layoutAlgorithm:function(b,d,g){var f=b.start,a=b.end-f,c=b.val,e=b.x,k=b.y,h=g&&B(g.levelSize)&&q(g.levelSize.value)?g.levelSize.value:0,m=b.r,l=m+h,z=g&&q(g.slicedOffset)?g.slicedOffset: +0;return(d||[]).reduce(function(b,d){var g=1/c*d.val*a,n=f+g/2,p=e+Math.cos(n)*z;n=k+Math.sin(n)*z;d={x:d.sliced?p:e,y:d.sliced?n:k,innerR:m,r:l,radius:h,start:f,end:f+g};b.push(d);f=d.end;return b},[])},setShapeArgs:function(b,d,g){var f=[],a=g[b.level+1];b=b.children.filter(function(a){return a.visible});f=this.layoutAlgorithm(d,b,a);b.forEach(function(a,b){b=f[b];var c=b.start+(b.end-b.start)/2,d=b.innerR+(b.r-b.innerR)/2,e=b.end-b.start;d=0===b.innerR&&6.28a.val?a.childrenTotal:a.val:a.childrenTotal;this.points[a.i]&&(this.points[a.i].innerArcLength=e*b.innerR,this.points[a.i].outerArcLength=e*b.r);a.shapeArgs=t(b,{plotX:d.x,plotY:d.y+4*Math.abs(Math.cos(c))});a.values=t(b,{val:k});a.children.length&&this.setShapeArgs(a,a.values,g)},this)},translate:function(){var b=this,d=b.options,l=b.center=M.call(b),n=b.startAndEndRadians=v(d.startAngle,d.endAngle),a=l[3]/2,c=l[2]/2-a,e=R(b),p=b.nodeMap,h=p&&p[e], +t={};b.shapeRoot=h&&h.shapeArgs;L.prototype.translate.call(b);var x=b.tree=b.getTree();b.renderTraverseUpButton(e);p=b.nodeMap;h=p[e];var u=g(h.parent)?h.parent:"";u=p[u];var q=O(h);var w=q.from,r=q.to;q=Q({from:w,levels:b.options.levels,to:r,defaults:{colorByPoint:d.colorByPoint,dataLabels:d.dataLabels,levelIsConstant:d.levelIsConstant,levelSize:d.levelSize,slicedOffset:d.slicedOffset}});q=N(q,{diffRadius:c,from:w,to:r});D(x,{before:J,idRoot:e,levelIsConstant:d.levelIsConstant,mapOptionsToLevel:q, +mapIdToNode:p,points:b.points,series:b});d=p[""].shapeArgs={end:n.end,r:a,start:n.start,val:h.val,x:l[0],y:l[1]};this.setShapeArgs(u,d,q);b.mapOptionsToLevel=q;b.data.forEach(function(a){t[a.id]&&m(31,!1,b.chart);t[a.id]=!0});t={}},alignDataLabel:function(b,d,g){if(!g.textPath||!g.textPath.enabled)return E.treemap.prototype.alignDataLabel.apply(this,arguments)},animate:function(b){var d=this.chart,f=[d.plotWidth/2,d.plotHeight/2],g=d.plotLeft,a=d.plotTop;d=this.group;b?(b={translateX:f[0]+g,translateY:f[1]+ +a,scaleX:.001,scaleY:.001,rotation:10,opacity:.01},d.attr(b)):(b={translateX:g,translateY:a,scaleX:1,scaleY:1,rotation:0,opacity:1},d.animate(b,this.options.animation))},utils:{calculateLevelSizes:N,getLevelFromAndTo:O,range:K}},{draw:C,shouldDraw:function(){return!this.isNull},isValid:function(){return!0},getDataLabelPath:function(b){var d=this.series.chart.renderer,f=this.shapeExisting,g=f.start,a=f.end,c=g+(a-g)/2;c=0>c&&c>-Math.PI||c>Math.PI;var e=f.r+(b.options.distance||0);g===-Math.PI/2&&u(a)=== +u(1.5*Math.PI)&&(g=-Math.PI+Math.PI/360,a=-Math.PI/360,c=!0);if(a-g>Math.PI){c=!1;var l=!0}this.dataLabelPath&&(this.dataLabelPath=this.dataLabelPath.destroy());this.dataLabelPath=d.arc({open:!0,longArc:l?1:0}).add(b);this.dataLabelPath.attr({start:c?g:a,end:c?a:g,clockwise:+c,x:f.x,y:f.y,r:(e+f.innerR)/2});return this.dataLabelPath}})});C(d,"masters/modules/sunburst.src.js",[],function(){})}); +//# sourceMappingURL=sunburst.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/sunburst.js.map b/librerias/gantt/code/modules/sunburst.js.map new file mode 100644 index 0000000..38ac692 --- /dev/null +++ b/librerias/gantt/code/modules/sunburst.js.map @@ -0,0 +1 @@ +{"version":3,"file":"sunburst.js.map","lineCount":56,"mappings":"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","sources":["sunburst.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","draw","params","_a","component","graphic","animatableAttribs","onComplete","css","renderer","animation","series","options","shouldDraw","shapeType","shapeArgs","add","group","attr","attribs","animate","isNew","destroy","Object","keys","length","drawPoint","point","getClassName","call","Color","U","extend","isArray","isNumber","isObject","merge","pick","result","getColor","node","index","mapOptionsToLevel","parentColor","parentColorIndex","colors","siblings","points","chartOptionsChart","chart","color","i","level","getColorByPoint","colorByPoint","colorIndexByPoint","colorCount","styledMode","colorVariation","key","parse","brighten","to","get","colorIndex","getLevelOptions","from","levels","converted","defaults","reduce","item","levelIsConstant","setTreeValues","tree","before","idRoot","nodeRoot","mapIdToNode","optionsPoint","childrenTotal","children","levelDynamic","name","visible","id","forEach","child","newOptions","push","val","value","isLeaf","updateRootId","rootId","rootNode","userOptions","H","mixinTreeSeries","LegendSymbolMixin","Point","addEvent","correctFloat","defined","error","fireEvent","isString","objectEach","seriesType","stableSort","seriesTypes","noop","Series","eachObject","list","func","context","recursive","next","treemapAxisDefaultValues","allowTraversingTree","animationLimit","showInLegend","marker","dataLabels","defer","enabled","formatter","inside","verticalAlign","tooltip","headerFormat","pointFormat","ignoreHiddenPoint","layoutAlgorithm","layoutStartingDirection","alternateStartingDirection","drillUpButton","position","align","x","y","traverseUpButton","borderColor","borderWidth","colorKey","opacity","states","hover","brightness","heatmap","halo","shadow","pointArrayMap","directTouch","optionalAxis","getSymbol","parallelArrays","trackerGroups","getListOfParents","data","existingIds","arr","ids","listOfParents","prev","curr","parent","indexOf","getTree","allIds","map","d","parentList","nodeMap","buildNode","hasData","processedXData","init","colorMapSeriesMixin","colorAttribs","eventsToUnbind","event","allowDrillToNode","prototype","onClickDrillToNode","height","Math","max","ignore","a","b","sortIndex","calculateChildrenAreas","area","algorithm","alternate","childrenValues","filter","n","direction","values","pointValues","axisRatio","AXIS_MAX","width","setPointValues","xAxis","yAxis","crispCorr","pointAttribs","x1","round","toPixels","x2","y1","y2","min","abs","plotX","plotY","setColorRecursive","colorInfo","algorithmGroup","h","w","p","plot","startDirection","lH","nH","lW","nW","total","elArr","lP","nR","lR","aspectRatio","addElement","this.addElement","el","reset","this.reset","algorithmCalcPoints","directionChange","last","childrenArea","pX","pY","pW","pH","gW","gH","end","keep","algorithmLowAspectRatio","pTot","algorithmFill","strip","squarified","sliceAndDice","stripes","translate","renderTraverseUpButton","setRootNode","concat","len","seriesArea","colorAxis","setExtremes","setScale","drawDataLabels","style","_hasPointLabels","dataLabel","dlOptions","alignDataLabel","labelOptions","textOverflow","text","getBBox","textWidth","column","arguments","zIndex","state","stateOptions","className","borderDashStyle","fill","setOpacity","cursor","drawPoints","borderRadius","withinAnimationLimit","pointCount","groupKey","hasGraphic","shouldAnimate","r","selected","g","survive","drillId","interactByLeaf","drillToByLeaf","drillToByGroup","setState","trigger","nodeParent","drillUp","drillToNode","redraw","eventArguments","eventArgs","newRootId","previousRootId","defaultFn","idPreviousRoot","isDirty","buttonOptions","backText","placed","theme","button","select","addClass","relativeTo","buildKDTree","drawLegendSymbol","drawRectangle","getExtremes","colorValueData","dataMax","valueMin","dataMin","valueMax","getExtremesFromAll","inactiveOtherPoints","utils","setVisible","pie","pointClass","isValid","is","treeAxis","endOnTick","gridLineWidth","lineWidth","minPadding","maxPadding","startOnTick","title","tickPositions","setOptions","splat","CenteredSeriesMixin","getCenter","getStartAndEndRadians","rad2deg","PI","range","calculateLevelSizes","levelOptions","totalWeight","remainingSize","levelsNotIncluded","k","diffRadius","unit","levelSize","weight","getLevelFromAndTo","cbSetTreeValuesBefore","sliced","sunburstOptions","center","allowOverlap","rotationMode","slicedOffset","sunburstSeries","shapeRoot","hasRendered","nodePreviousRoot","shapePreviousRoot","radians","startAndEndRadians","optionsChart","innerR","animateLabelsCalled","addedHack","hackDataLabelAnimation","dataLabelsGroup","animateLabels","visibility","shapeExisting","shape","start","tooltipPos","isNull","optionsLevel","rotation","innerArcLength","outerArcLength","radius","rotationRad","dataLabelPath","textPath","attributes","dy","textPathWrapper","fontMetrics","fontSize","padding","startAngle","innerRadius","outerRadius","radiansCenter","cos","sin","setShapeArgs","parentValues","angle","twoPi","positions","endAngle","nodeIds","idTop","nodeTop","treemap","plotWidth","plotHeight","plotLeft","plotTop","translateX","translateY","scaleX","scaleY","sunburstPoint","getDataLabelPath","label","upperHalf","distance","moreThanHalf","arc","open","longArc","clockwise"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/sunburst.src.js b/librerias/gantt/code/modules/sunburst.src.js new file mode 100644 index 0000000..ae6c28f --- /dev/null +++ b/librerias/gantt/code/modules/sunburst.src.js @@ -0,0 +1,2774 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * (c) 2016-2019 Highsoft AS + * Authors: Jon Arild Nygard + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/sunburst', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'mixins/draw-point.js', [], function () { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var isFn = function (x) { + return typeof x === 'function'; + }; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Handles the drawing of a component. + * Can be used for any type of component that reserves the graphic property, and + * provides a shouldDraw on its context. + * + * @private + * @function draw + * @param {DrawPointParams} params + * Parameters. + * + * @todo add type checking. + * @todo export this function to enable usage + */ + var draw = function draw(params) { + var _a; + var component = this, graphic = component.graphic, animatableAttribs = params.animatableAttribs, onComplete = params.onComplete, css = params.css, renderer = params.renderer, animation = (_a = component.series) === null || _a === void 0 ? void 0 : _a.options.animation; + if (component.shouldDraw()) { + if (!graphic) { + component.graphic = graphic = + renderer[params.shapeType](params.shapeArgs) + .add(params.group); + } + graphic + .css(css) + .attr(params.attribs) + .animate(animatableAttribs, params.isNew ? false : animation, onComplete); + } + else if (graphic) { + var destroy = function () { + component.graphic = graphic = graphic.destroy(); + if (isFn(onComplete)) { + onComplete(); + } + }; + // animate only runs complete callback if something was animated. + if (Object.keys(animatableAttribs).length) { + graphic.animate(animatableAttribs, void 0, function () { + destroy(); + }); + } + else { + destroy(); + } + } + }; + /** + * An extended version of draw customized for points. + * It calls additional methods that is expected when rendering a point. + * @private + * @param {Highcharts.Dictionary} params Parameters + */ + var drawPoint = function drawPoint(params) { + var point = this, attribs = params.attribs = params.attribs || {}; + // Assigning class in dot notation does go well in IE8 + // eslint-disable-next-line dot-notation + attribs['class'] = point.getClassName(); + // Call draw to render component + draw.call(point, params); + }; + + return drawPoint; + }); + _registerModule(_modules, 'mixins/tree-series.js', [_modules['parts/Color.js'], _modules['parts/Utilities.js']], function (Color, U) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, merge = U.merge, pick = U.pick; + var isBoolean = function (x) { + return typeof x === 'boolean'; + }, isFn = function (x) { + return typeof x === 'function'; + }; + /* eslint-disable valid-jsdoc */ + /** + * @todo Combine buildTree and buildNode with setTreeValues + * @todo Remove logic from Treemap and make it utilize this mixin. + * @private + */ + var setTreeValues = function setTreeValues(tree, options) { + var before = options.before, idRoot = options.idRoot, mapIdToNode = options.mapIdToNode, nodeRoot = mapIdToNode[idRoot], levelIsConstant = (isBoolean(options.levelIsConstant) ? + options.levelIsConstant : + true), points = options.points, point = points[tree.i], optionsPoint = point && point.options || {}, childrenTotal = 0, children = [], value; + extend(tree, { + levelDynamic: tree.level - (levelIsConstant ? 0 : nodeRoot.level), + name: pick(point && point.name, ''), + visible: (idRoot === tree.id || + (isBoolean(options.visible) ? options.visible : false)) + }); + if (isFn(before)) { + tree = before(tree, options); + } + // First give the children some values + tree.children.forEach(function (child, i) { + var newOptions = extend({}, options); + extend(newOptions, { + index: i, + siblings: tree.children.length, + visible: tree.visible + }); + child = setTreeValues(child, newOptions); + children.push(child); + if (child.visible) { + childrenTotal += child.val; + } + }); + tree.visible = childrenTotal > 0 || tree.visible; + // Set the values + value = pick(optionsPoint.value, childrenTotal); + extend(tree, { + children: children, + childrenTotal: childrenTotal, + isLeaf: tree.visible && !childrenTotal, + val: value + }); + return tree; + }; + /** + * @private + */ + var getColor = function getColor(node, options) { + var index = options.index, mapOptionsToLevel = options.mapOptionsToLevel, parentColor = options.parentColor, parentColorIndex = options.parentColorIndex, series = options.series, colors = options.colors, siblings = options.siblings, points = series.points, getColorByPoint, chartOptionsChart = series.chart.options.chart, point, level, colorByPoint, colorIndexByPoint, color, colorIndex; + /** + * @private + */ + function variation(color) { + var colorVariation = level && level.colorVariation; + if (colorVariation) { + if (colorVariation.key === 'brightness') { + return Color.parse(color).brighten(colorVariation.to * (index / siblings)).get(); + } + } + return color; + } + if (node) { + point = points[node.i]; + level = mapOptionsToLevel[node.level] || {}; + getColorByPoint = point && level.colorByPoint; + if (getColorByPoint) { + colorIndexByPoint = point.index % (colors ? + colors.length : + chartOptionsChart.colorCount); + colorByPoint = colors && colors[colorIndexByPoint]; + } + // Select either point color, level color or inherited color. + if (!series.chart.styledMode) { + color = pick(point && point.options.color, level && level.color, colorByPoint, parentColor && variation(parentColor), series.color); + } + colorIndex = pick(point && point.options.colorIndex, level && level.colorIndex, colorIndexByPoint, parentColorIndex, options.colorIndex); + } + return { + color: color, + colorIndex: colorIndex + }; + }; + /** + * Creates a map from level number to its given options. + * + * @private + * @function getLevelOptions + * @param {object} params + * Object containing parameters. + * - `defaults` Object containing default options. The default options + * are merged with the userOptions to get the final options for a + * specific level. + * - `from` The lowest level number. + * - `levels` User options from series.levels. + * - `to` The highest level number. + * @return {Highcharts.Dictionary|null} + * Returns a map from level number to its given options. + */ + var getLevelOptions = function getLevelOptions(params) { + var result = null, defaults, converted, i, from, to, levels; + if (isObject(params)) { + result = {}; + from = isNumber(params.from) ? params.from : 1; + levels = params.levels; + converted = {}; + defaults = isObject(params.defaults) ? params.defaults : {}; + if (isArray(levels)) { + converted = levels.reduce(function (obj, item) { + var level, levelIsConstant, options; + if (isObject(item) && isNumber(item.level)) { + options = merge({}, item); + levelIsConstant = (isBoolean(options.levelIsConstant) ? + options.levelIsConstant : + defaults.levelIsConstant); + // Delete redundant properties. + delete options.levelIsConstant; + delete options.level; + // Calculate which level these options apply to. + level = item.level + (levelIsConstant ? 0 : from - 1); + if (isObject(obj[level])) { + extend(obj[level], options); + } + else { + obj[level] = options; + } + } + return obj; + }, {}); + } + to = isNumber(params.to) ? params.to : 1; + for (i = 0; i <= to; i++) { + result[i] = merge({}, defaults, isObject(converted[i]) ? converted[i] : {}); + } + } + return result; + }; + /** + * Update the rootId property on the series. Also makes sure that it is + * accessible to exporting. + * + * @private + * @function updateRootId + * + * @param {object} series + * The series to operate on. + * + * @return {string} + * Returns the resulting rootId after update. + */ + var updateRootId = function (series) { + var rootId, options; + if (isObject(series)) { + // Get the series options. + options = isObject(series.options) ? series.options : {}; + // Calculate the rootId. + rootId = pick(series.rootNode, options.rootId, ''); + // Set rootId on series.userOptions to pick it up in exporting. + if (isObject(series.userOptions)) { + series.userOptions.rootId = rootId; + } + // Set rootId on series to pick it up on next update. + series.rootNode = rootId; + } + return rootId; + }; + var result = { + getColor: getColor, + getLevelOptions: getLevelOptions, + setTreeValues: setTreeValues, + updateRootId: updateRootId + }; + + return result; + }); + _registerModule(_modules, 'modules/treemap.src.js', [_modules['parts/Globals.js'], _modules['mixins/tree-series.js'], _modules['mixins/draw-point.js'], _modules['parts/Color.js'], _modules['mixins/legend-symbol.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js']], function (H, mixinTreeSeries, drawPoint, Color, LegendSymbolMixin, Point, U) { + /* * + * + * (c) 2014-2020 Highsoft AS + * + * Authors: Jon Arild Nygard / Oystein Moseng + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var color = Color.parse; + var addEvent = U.addEvent, correctFloat = U.correctFloat, defined = U.defined, error = U.error, extend = U.extend, fireEvent = U.fireEvent, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, isString = U.isString, merge = U.merge, objectEach = U.objectEach, pick = U.pick, seriesType = U.seriesType, stableSort = U.stableSort; + /* eslint-disable no-invalid-this */ + var AXIS_MAX = 100; + var seriesTypes = H.seriesTypes, noop = H.noop, getColor = mixinTreeSeries.getColor, getLevelOptions = mixinTreeSeries.getLevelOptions, + // @todo Similar to eachObject, this function is likely redundant + isBoolean = function (x) { + return typeof x === 'boolean'; + }, Series = H.Series, + // @todo Similar to recursive, this function is likely redundant + eachObject = function (list, func, context) { + context = context || this; + objectEach(list, function (val, key) { + func.call(context, val, key, list); + }); + }, + // @todo find correct name for this function. + // @todo Similar to reduce, this function is likely redundant + recursive = function (item, func, context) { + var next; + context = context || this; + next = func.call(context, item); + if (next !== false) { + recursive(next, func, context); + } + }, updateRootId = mixinTreeSeries.updateRootId, treemapAxisDefaultValues = false; + /* eslint-enable no-invalid-this */ + /** + * @private + * @class + * @name Highcharts.seriesTypes.treemap + * + * @augments Highcharts.Series + */ + seriesType('treemap', 'scatter' + /** + * A treemap displays hierarchical data using nested rectangles. The data + * can be laid out in varying ways depending on options. + * + * @sample highcharts/demo/treemap-large-dataset/ + * Treemap + * + * @extends plotOptions.scatter + * @excluding dragDrop, marker, jitter, dataSorting + * @product highcharts + * @requires modules/treemap + * @optionparent plotOptions.treemap + */ + , { + /** + * When enabled the user can click on a point which is a parent and + * zoom in on its children. Deprecated and replaced by + * [allowTraversingTree](#plotOptions.treemap.allowTraversingTree). + * + * @sample {highcharts} highcharts/plotoptions/treemap-allowdrilltonode/ + * Enabled + * + * @deprecated + * @type {boolean} + * @default false + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.allowDrillToNode + */ + /** + * When enabled the user can click on a point which is a parent and + * zoom in on its children. + * + * @sample {highcharts} highcharts/plotoptions/treemap-allowtraversingtree/ + * Enabled + * + * @since 7.0.3 + * @product highcharts + */ + allowTraversingTree: false, + animationLimit: 250, + /** + * When the series contains less points than the crop threshold, all + * points are drawn, event if the points fall outside the visible plot + * area at the current zoom. The advantage of drawing all points + * (including markers and columns), is that animation is performed on + * updates. On the other hand, when the series contains more points than + * the crop threshold, the series data is cropped to only contain points + * that fall within the plot area. The advantage of cropping away + * invisible points is to increase performance on large series. + * + * @type {number} + * @default 300 + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.cropThreshold + */ + /** + * Fires on a request for change of root node for the tree, before the + * update is made. An event object is passed to the function, containing + * additional properties `newRootId`, `previousRootId`, `redraw` and + * `trigger`. + * + * @type {function} + * @default undefined + * @sample {highcharts} highcharts/plotoptions/treemap-events-setrootnode/ + * Alert update information on setRootNode event. + * @since 7.0.3 + * @product highcharts + * @apioption plotOptions.treemap.events.setRootNode + */ + /** + * This option decides if the user can interact with the parent nodes + * or just the leaf nodes. When this option is undefined, it will be + * true by default. However when allowTraversingTree is true, then it + * will be false by default. + * + * @sample {highcharts} highcharts/plotoptions/treemap-interactbyleaf-false/ + * False + * @sample {highcharts} highcharts/plotoptions/treemap-interactbyleaf-true-and-allowtraversingtree/ + * InteractByLeaf and allowTraversingTree is true + * + * @type {boolean} + * @since 4.1.2 + * @product highcharts + * @apioption plotOptions.treemap.interactByLeaf + */ + /** + * The sort index of the point inside the treemap level. + * + * @sample {highcharts} highcharts/plotoptions/treemap-sortindex/ + * Sort by years + * + * @type {number} + * @since 4.1.10 + * @product highcharts + * @apioption plotOptions.treemap.sortIndex + */ + /** + * A series specific or series type specific color set to apply instead + * of the global [colors](#colors) when + * [colorByPoint](#plotOptions.treemap.colorByPoint) is true. + * + * @type {Array} + * @since 3.0 + * @product highcharts + * @apioption plotOptions.treemap.colors + */ + /** + * Whether to display this series type or specific series item in the + * legend. + */ + showInLegend: false, + /** + * @ignore-option + */ + marker: false, + /** + * When using automatic point colors pulled from the `options.colors` + * collection, this option determines whether the chart should receive + * one color per series or one color per point. + * + * @see [series colors](#plotOptions.treemap.colors) + * + * @since 2.0 + * @product highcharts + * @apioption plotOptions.treemap.colorByPoint + */ + colorByPoint: false, + /** + * @since 4.1.0 + */ + dataLabels: { + defer: false, + enabled: true, + formatter: function () { + var point = this && this.point ? + this.point : + {}, name = isString(point.name) ? point.name : ''; + return name; + }, + inside: true, + verticalAlign: 'middle' + }, + tooltip: { + headerFormat: '', + pointFormat: '{point.name}: {point.value}
    ' + }, + /** + * Whether to ignore hidden points when the layout algorithm runs. + * If `false`, hidden points will leave open spaces. + * + * @since 5.0.8 + */ + ignoreHiddenPoint: true, + /** + * This option decides which algorithm is used for setting position + * and dimensions of the points. + * + * @see [How to write your own algorithm](https://www.highcharts.com/docs/chart-and-series-types/treemap) + * + * @sample {highcharts} highcharts/plotoptions/treemap-layoutalgorithm-sliceanddice/ + * SliceAndDice by default + * @sample {highcharts} highcharts/plotoptions/treemap-layoutalgorithm-stripes/ + * Stripes + * @sample {highcharts} highcharts/plotoptions/treemap-layoutalgorithm-squarified/ + * Squarified + * @sample {highcharts} highcharts/plotoptions/treemap-layoutalgorithm-strip/ + * Strip + * + * @since 4.1.0 + * @validvalue ["sliceAndDice", "stripes", "squarified", "strip"] + */ + layoutAlgorithm: 'sliceAndDice', + /** + * Defines which direction the layout algorithm will start drawing. + * + * @since 4.1.0 + * @validvalue ["vertical", "horizontal"] + */ + layoutStartingDirection: 'vertical', + /** + * Enabling this option will make the treemap alternate the drawing + * direction between vertical and horizontal. The next levels starting + * direction will always be the opposite of the previous. + * + * @sample {highcharts} highcharts/plotoptions/treemap-alternatestartingdirection-true/ + * Enabled + * + * @since 4.1.0 + */ + alternateStartingDirection: false, + /** + * Used together with the levels and allowTraversingTree options. When + * set to false the first level visible to be level one, which is + * dynamic when traversing the tree. Otherwise the level will be the + * same as the tree structure. + * + * @since 4.1.0 + */ + levelIsConstant: true, + /** + * Options for the button appearing when drilling down in a treemap. + * Deprecated and replaced by + * [traverseUpButton](#plotOptions.treemap.traverseUpButton). + * + * @deprecated + */ + drillUpButton: { + /** + * The position of the button. + * + * @deprecated + */ + position: { + /** + * Vertical alignment of the button. + * + * @deprecated + * @type {Highcharts.VerticalAlignValue} + * @default top + * @product highcharts + * @apioption plotOptions.treemap.drillUpButton.position.verticalAlign + */ + /** + * Horizontal alignment of the button. + * + * @deprecated + * @type {Highcharts.AlignValue} + */ + align: 'right', + /** + * Horizontal offset of the button. + * + * @deprecated + */ + x: -10, + /** + * Vertical offset of the button. + * + * @deprecated + */ + y: 10 + } + }, + /** + * Options for the button appearing when traversing down in a treemap. + */ + traverseUpButton: { + /** + * The position of the button. + */ + position: { + /** + * Vertical alignment of the button. + * + * @type {Highcharts.VerticalAlignValue} + * @default top + * @product highcharts + * @apioption plotOptions.treemap.traverseUpButton.position.verticalAlign + */ + /** + * Horizontal alignment of the button. + * + * @type {Highcharts.AlignValue} + */ + align: 'right', + /** + * Horizontal offset of the button. + */ + x: -10, + /** + * Vertical offset of the button. + */ + y: 10 + } + }, + /** + * Set options on specific levels. Takes precedence over series options, + * but not point options. + * + * @sample {highcharts} highcharts/plotoptions/treemap-levels/ + * Styling dataLabels and borders + * @sample {highcharts} highcharts/demo/treemap-with-levels/ + * Different layoutAlgorithm + * + * @type {Array<*>} + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.levels + */ + /** + * Can set a `borderColor` on all points which lies on the same level. + * + * @type {Highcharts.ColorString} + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.borderColor + */ + /** + * Set the dash style of the border of all the point which lies on the + * level. See + * [plotOptions.scatter.dashStyle](#plotoptions.scatter.dashstyle) + * for possible options. + * + * @type {Highcharts.DashStyleValue} + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.borderDashStyle + */ + /** + * Can set the borderWidth on all points which lies on the same level. + * + * @type {number} + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.borderWidth + */ + /** + * Can set a color on all points which lies on the same level. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.color + */ + /** + * A configuration object to define how the color of a child varies from + * the parent's color. The variation is distributed among the children + * of node. For example when setting brightness, the brightness change + * will range from the parent's original brightness on the first child, + * to the amount set in the `to` setting on the last node. This allows a + * gradient-like color scheme that sets children out from each other + * while highlighting the grouping on treemaps and sectors on sunburst + * charts. + * + * @sample highcharts/demo/sunburst/ + * Sunburst with color variation + * + * @since 6.0.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.colorVariation + */ + /** + * The key of a color variation. Currently supports `brightness` only. + * + * @type {string} + * @since 6.0.0 + * @product highcharts + * @validvalue ["brightness"] + * @apioption plotOptions.treemap.levels.colorVariation.key + */ + /** + * The ending value of a color variation. The last sibling will receive + * this value. + * + * @type {number} + * @since 6.0.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.colorVariation.to + */ + /** + * Can set the options of dataLabels on each point which lies on the + * level. + * [plotOptions.treemap.dataLabels](#plotOptions.treemap.dataLabels) for + * possible values. + * + * @extends plotOptions.treemap.dataLabels + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.dataLabels + */ + /** + * Can set the layoutAlgorithm option on a specific level. + * + * @type {string} + * @since 4.1.0 + * @product highcharts + * @validvalue ["sliceAndDice", "stripes", "squarified", "strip"] + * @apioption plotOptions.treemap.levels.layoutAlgorithm + */ + /** + * Can set the layoutStartingDirection option on a specific level. + * + * @type {string} + * @since 4.1.0 + * @product highcharts + * @validvalue ["vertical", "horizontal"] + * @apioption plotOptions.treemap.levels.layoutStartingDirection + */ + /** + * Decides which level takes effect from the options set in the levels + * object. + * + * @sample {highcharts} highcharts/plotoptions/treemap-levels/ + * Styling of both levels + * + * @type {number} + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.level + */ + // Presentational options + /** + * The color of the border surrounding each tree map item. + * + * @type {Highcharts.ColorString} + */ + borderColor: '#e6e6e6', + /** + * The width of the border surrounding each tree map item. + */ + borderWidth: 1, + colorKey: 'colorValue', + /** + * The opacity of a point in treemap. When a point has children, the + * visibility of the children is determined by the opacity. + * + * @since 4.2.4 + */ + opacity: 0.15, + /** + * A wrapper object for all the series options in specific states. + * + * @extends plotOptions.heatmap.states + */ + states: { + /** + * Options for the hovered series + * + * @extends plotOptions.heatmap.states.hover + * @excluding halo + */ + hover: { + /** + * The border color for the hovered state. + */ + borderColor: '#999999', + /** + * Brightness for the hovered point. Defaults to 0 if the + * heatmap series is loaded first, otherwise 0.1. + * + * @type {number} + * @default undefined + */ + brightness: seriesTypes.heatmap ? 0 : 0.1, + /** + * @extends plotOptions.heatmap.states.hover.halo + */ + halo: false, + /** + * The opacity of a point in treemap. When a point has children, + * the visibility of the children is determined by the opacity. + * + * @since 4.2.4 + */ + opacity: 0.75, + /** + * The shadow option for hovered state. + */ + shadow: false + } + } + // Prototype members + }, { + pointArrayMap: ['value'], + directTouch: true, + optionalAxis: 'colorAxis', + getSymbol: noop, + parallelArrays: ['x', 'y', 'value', 'colorValue'], + colorKey: 'colorValue', + trackerGroups: ['group', 'dataLabelsGroup'], + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Creates an object map from parent id to childrens index. + * + * @private + * @function Highcharts.Series#getListOfParents + * + * @param {Highcharts.SeriesTreemapDataOptions} [data] + * List of points set in options. + * + * @param {Array} [existingIds] + * List of all point ids. + * + * @return {object} + * Map from parent id to children index in data. + */ + getListOfParents: function (data, existingIds) { + var arr = isArray(data) ? data : [], ids = isArray(existingIds) ? existingIds : [], listOfParents = arr.reduce(function (prev, curr, i) { + var parent = pick(curr.parent, ''); + if (typeof prev[parent] === 'undefined') { + prev[parent] = []; + } + prev[parent].push(i); + return prev; + }, { + '': [] // Root of tree + }); + // If parent does not exist, hoist parent to root of tree. + eachObject(listOfParents, function (children, parent, list) { + if ((parent !== '') && (ids.indexOf(parent) === -1)) { + children.forEach(function (child) { + list[''].push(child); + }); + delete list[parent]; + } + }); + return listOfParents; + }, + // Creates a tree structured object from the series points + getTree: function () { + var series = this, allIds = this.data.map(function (d) { + return d.id; + }), parentList = series.getListOfParents(this.data, allIds); + series.nodeMap = []; + return series.buildNode('', -1, 0, parentList, null); + }, + // Define hasData function for non-cartesian series. + // Returns true if the series has points at all. + hasData: function () { + return !!this.processedXData.length; // != 0 + }, + init: function (chart, options) { + var series = this, colorMapSeriesMixin = H.colorMapSeriesMixin; + // If color series logic is loaded, add some properties + if (colorMapSeriesMixin) { + this.colorAttribs = colorMapSeriesMixin.colorAttribs; + } + // Handle deprecated options. + series.eventsToUnbind.push(addEvent(series, 'setOptions', function (event) { + var options = event.userOptions; + if (defined(options.allowDrillToNode) && + !defined(options.allowTraversingTree)) { + options.allowTraversingTree = options.allowDrillToNode; + delete options.allowDrillToNode; + } + if (defined(options.drillUpButton) && + !defined(options.traverseUpButton)) { + options.traverseUpButton = options.drillUpButton; + delete options.drillUpButton; + } + })); + Series.prototype.init.call(series, chart, options); + if (series.options.allowTraversingTree) { + series.eventsToUnbind.push(addEvent(series, 'click', series.onClickDrillToNode)); + } + }, + buildNode: function (id, i, level, list, parent) { + var series = this, children = [], point = series.points[i], height = 0, node, child; + // Actions + ((list[id] || [])).forEach(function (i) { + child = series.buildNode(series.points[i].id, i, (level + 1), list, id); + height = Math.max(child.height + 1, height); + children.push(child); + }); + node = { + id: id, + i: i, + children: children, + height: height, + level: level, + parent: parent, + visible: false // @todo move this to better location + }; + series.nodeMap[node.id] = node; + if (point) { + point.node = node; + } + return node; + }, + setTreeValues: function (tree) { + var series = this, options = series.options, idRoot = series.rootNode, mapIdToNode = series.nodeMap, nodeRoot = mapIdToNode[idRoot], levelIsConstant = (isBoolean(options.levelIsConstant) ? + options.levelIsConstant : + true), childrenTotal = 0, children = [], val, point = series.points[tree.i]; + // First give the children some values + tree.children.forEach(function (child) { + child = series.setTreeValues(child); + children.push(child); + if (!child.ignore) { + childrenTotal += child.val; + } + }); + // Sort the children + stableSort(children, function (a, b) { + return a.sortIndex - b.sortIndex; + }); + // Set the values + val = pick(point && point.options.value, childrenTotal); + if (point) { + point.value = val; + } + extend(tree, { + children: children, + childrenTotal: childrenTotal, + // Ignore this node if point is not visible + ignore: !(pick(point && point.visible, true) && (val > 0)), + isLeaf: tree.visible && !childrenTotal, + levelDynamic: (tree.level - (levelIsConstant ? 0 : nodeRoot.level)), + name: pick(point && point.name, ''), + sortIndex: pick(point && point.sortIndex, -val), + val: val + }); + return tree; + }, + /** + * Recursive function which calculates the area for all children of a + * node. + * + * @private + * @function Highcharts.Series#calculateChildrenAreas + * + * @param {object} node + * The node which is parent to the children. + * + * @param {object} area + * The rectangular area of the parent. + */ + calculateChildrenAreas: function (parent, area) { + var series = this, options = series.options, mapOptionsToLevel = series.mapOptionsToLevel, level = mapOptionsToLevel[parent.level + 1], algorithm = pick((series[(level && level.layoutAlgorithm)] && + level.layoutAlgorithm), options.layoutAlgorithm), alternate = options.alternateStartingDirection, childrenValues = [], children; + // Collect all children which should be included + children = parent.children.filter(function (n) { + return !n.ignore; + }); + if (level && level.layoutStartingDirection) { + area.direction = level.layoutStartingDirection === 'vertical' ? + 0 : + 1; + } + childrenValues = series[algorithm](area, children); + children.forEach(function (child, index) { + var values = childrenValues[index]; + child.values = merge(values, { + val: child.childrenTotal, + direction: (alternate ? 1 - area.direction : area.direction) + }); + child.pointValues = merge(values, { + x: (values.x / series.axisRatio), + // Flip y-values to avoid visual regression with csvCoord in + // Axis.translate at setPointValues. #12488 + y: AXIS_MAX - values.y - values.height, + width: (values.width / series.axisRatio) + }); + // If node has children, then call method recursively + if (child.children.length) { + series.calculateChildrenAreas(child, child.values); + } + }); + }, + setPointValues: function () { + var series = this; + var points = series.points, xAxis = series.xAxis, yAxis = series.yAxis; + var styledMode = series.chart.styledMode; + // Get the crisp correction in classic mode. For this to work in + // styled mode, we would need to first add the shape (without x, + // y, width and height), then read the rendered stroke width + // using point.graphic.strokeWidth(), then modify and apply the + // shapeArgs. This applies also to column series, but the + // downside is performance and code complexity. + var getCrispCorrection = function (point) { return (styledMode ? + 0 : + ((series.pointAttribs(point)['stroke-width'] || 0) % 2) / 2); }; + points.forEach(function (point) { + var _a = point.node, values = _a.pointValues, visible = _a.visible; + // Points which is ignored, have no values. + if (values && visible) { + var height = values.height, width = values.width, x = values.x, y = values.y; + var crispCorr = getCrispCorrection(point); + var x1 = Math.round(xAxis.toPixels(x, true)) - crispCorr; + var x2 = Math.round(xAxis.toPixels(x + width, true)) - crispCorr; + var y1 = Math.round(yAxis.toPixels(y, true)) - crispCorr; + var y2 = Math.round(yAxis.toPixels(y + height, true)) - crispCorr; + // Set point values + point.shapeArgs = { + x: Math.min(x1, x2), + y: Math.min(y1, y2), + width: Math.abs(x2 - x1), + height: Math.abs(y2 - y1) + }; + point.plotX = + point.shapeArgs.x + (point.shapeArgs.width / 2); + point.plotY = + point.shapeArgs.y + (point.shapeArgs.height / 2); + } + else { + // Reset visibility + delete point.plotX; + delete point.plotY; + } + }); + }, + // Set the node's color recursively, from the parent down. + setColorRecursive: function (node, parentColor, colorIndex, index, siblings) { + var series = this, chart = series && series.chart, colors = chart && chart.options && chart.options.colors, colorInfo, point; + if (node) { + colorInfo = getColor(node, { + colors: colors, + index: index, + mapOptionsToLevel: series.mapOptionsToLevel, + parentColor: parentColor, + parentColorIndex: colorIndex, + series: series, + siblings: siblings + }); + point = series.points[node.i]; + if (point) { + point.color = colorInfo.color; + point.colorIndex = colorInfo.colorIndex; + } + // Do it all again with the children + (node.children || []).forEach(function (child, i) { + series.setColorRecursive(child, colorInfo.color, colorInfo.colorIndex, i, node.children.length); + }); + } + }, + algorithmGroup: function (h, w, d, p) { + this.height = h; + this.width = w; + this.plot = p; + this.direction = d; + this.startDirection = d; + this.total = 0; + this.nW = 0; + this.lW = 0; + this.nH = 0; + this.lH = 0; + this.elArr = []; + this.lP = { + total: 0, + lH: 0, + nH: 0, + lW: 0, + nW: 0, + nR: 0, + lR: 0, + aspectRatio: function (w, h) { + return Math.max((w / h), (h / w)); + } + }; + this.addElement = function (el) { + this.lP.total = this.elArr[this.elArr.length - 1]; + this.total = this.total + el; + if (this.direction === 0) { + // Calculate last point old aspect ratio + this.lW = this.nW; + this.lP.lH = this.lP.total / this.lW; + this.lP.lR = this.lP.aspectRatio(this.lW, this.lP.lH); + // Calculate last point new aspect ratio + this.nW = this.total / this.height; + this.lP.nH = this.lP.total / this.nW; + this.lP.nR = this.lP.aspectRatio(this.nW, this.lP.nH); + } + else { + // Calculate last point old aspect ratio + this.lH = this.nH; + this.lP.lW = this.lP.total / this.lH; + this.lP.lR = this.lP.aspectRatio(this.lP.lW, this.lH); + // Calculate last point new aspect ratio + this.nH = this.total / this.width; + this.lP.nW = this.lP.total / this.nH; + this.lP.nR = this.lP.aspectRatio(this.lP.nW, this.nH); + } + this.elArr.push(el); + }; + this.reset = function () { + this.nW = 0; + this.lW = 0; + this.elArr = []; + this.total = 0; + }; + }, + algorithmCalcPoints: function (directionChange, last, group, childrenArea) { + var pX, pY, pW, pH, gW = group.lW, gH = group.lH, plot = group.plot, keep, i = 0, end = group.elArr.length - 1; + if (last) { + gW = group.nW; + gH = group.nH; + } + else { + keep = group.elArr[group.elArr.length - 1]; + } + group.elArr.forEach(function (p) { + if (last || (i < end)) { + if (group.direction === 0) { + pX = plot.x; + pY = plot.y; + pW = gW; + pH = p / pW; + } + else { + pX = plot.x; + pY = plot.y; + pH = gH; + pW = p / pH; + } + childrenArea.push({ + x: pX, + y: pY, + width: pW, + height: correctFloat(pH) + }); + if (group.direction === 0) { + plot.y = plot.y + pH; + } + else { + plot.x = plot.x + pW; + } + } + i = i + 1; + }); + // Reset variables + group.reset(); + if (group.direction === 0) { + group.width = group.width - gW; + } + else { + group.height = group.height - gH; + } + plot.y = plot.parent.y + (plot.parent.height - group.height); + plot.x = plot.parent.x + (plot.parent.width - group.width); + if (directionChange) { + group.direction = 1 - group.direction; + } + // If not last, then add uncalculated element + if (!last) { + group.addElement(keep); + } + }, + algorithmLowAspectRatio: function (directionChange, parent, children) { + var childrenArea = [], series = this, pTot, plot = { + x: parent.x, + y: parent.y, + parent: parent + }, direction = parent.direction, i = 0, end = children.length - 1, group = new this.algorithmGroup(// eslint-disable-line new-cap + parent.height, parent.width, direction, plot); + // Loop through and calculate all areas + children.forEach(function (child) { + pTot = + (parent.width * parent.height) * (child.val / parent.val); + group.addElement(pTot); + if (group.lP.nR > group.lP.lR) { + series.algorithmCalcPoints(directionChange, false, group, childrenArea, plot // @todo no supported + ); + } + // If last child, then calculate all remaining areas + if (i === end) { + series.algorithmCalcPoints(directionChange, true, group, childrenArea, plot // @todo not supported + ); + } + i = i + 1; + }); + return childrenArea; + }, + algorithmFill: function (directionChange, parent, children) { + var childrenArea = [], pTot, direction = parent.direction, x = parent.x, y = parent.y, width = parent.width, height = parent.height, pX, pY, pW, pH; + children.forEach(function (child) { + pTot = + (parent.width * parent.height) * (child.val / parent.val); + pX = x; + pY = y; + if (direction === 0) { + pH = height; + pW = pTot / pH; + width = width - pW; + x = x + pW; + } + else { + pW = width; + pH = pTot / pW; + height = height - pH; + y = y + pH; + } + childrenArea.push({ + x: pX, + y: pY, + width: pW, + height: pH + }); + if (directionChange) { + direction = 1 - direction; + } + }); + return childrenArea; + }, + strip: function (parent, children) { + return this.algorithmLowAspectRatio(false, parent, children); + }, + squarified: function (parent, children) { + return this.algorithmLowAspectRatio(true, parent, children); + }, + sliceAndDice: function (parent, children) { + return this.algorithmFill(true, parent, children); + }, + stripes: function (parent, children) { + return this.algorithmFill(false, parent, children); + }, + translate: function () { + var series = this, options = series.options, + // NOTE: updateRootId modifies series. + rootId = updateRootId(series), rootNode, pointValues, seriesArea, tree, val; + // Call prototype function + Series.prototype.translate.call(series); + // @todo Only if series.isDirtyData is true + tree = series.tree = series.getTree(); + rootNode = series.nodeMap[rootId]; + series.renderTraverseUpButton(rootId); + series.mapOptionsToLevel = getLevelOptions({ + from: rootNode.level + 1, + levels: options.levels, + to: tree.height, + defaults: { + levelIsConstant: series.options.levelIsConstant, + colorByPoint: options.colorByPoint + } + }); + if (rootId !== '' && + (!rootNode || !rootNode.children.length)) { + series.setRootNode('', false); + rootId = series.rootNode; + rootNode = series.nodeMap[rootId]; + } + // Parents of the root node is by default visible + recursive(series.nodeMap[series.rootNode], function (node) { + var next = false, p = node.parent; + node.visible = true; + if (p || p === '') { + next = series.nodeMap[p]; + } + return next; + }); + // Children of the root node is by default visible + recursive(series.nodeMap[series.rootNode].children, function (children) { + var next = false; + children.forEach(function (child) { + child.visible = true; + if (child.children.length) { + next = (next || []).concat(child.children); + } + }); + return next; + }); + series.setTreeValues(tree); + // Calculate plotting values. + series.axisRatio = (series.xAxis.len / series.yAxis.len); + series.nodeMap[''].pointValues = pointValues = { + x: 0, + y: 0, + width: AXIS_MAX, + height: AXIS_MAX + }; + series.nodeMap[''].values = seriesArea = merge(pointValues, { + width: (pointValues.width * series.axisRatio), + direction: (options.layoutStartingDirection === 'vertical' ? 0 : 1), + val: tree.val + }); + series.calculateChildrenAreas(tree, seriesArea); + // Logic for point colors + if (!series.colorAxis && + !options.colorByPoint) { + series.setColorRecursive(series.tree); + } + // Update axis extremes according to the root node. + if (options.allowTraversingTree) { + val = rootNode.pointValues; + series.xAxis.setExtremes(val.x, val.x + val.width, false); + series.yAxis.setExtremes(val.y, val.y + val.height, false); + series.xAxis.setScale(); + series.yAxis.setScale(); + } + // Assign values to points. + series.setPointValues(); + }, + /** + * Extend drawDataLabels with logic to handle custom options related to + * the treemap series: + * + * - Points which is not a leaf node, has dataLabels disabled by + * default. + * + * - Options set on series.levels is merged in. + * + * - Width of the dataLabel is set to match the width of the point + * shape. + * + * @private + * @function Highcharts.Series#drawDataLabels + */ + drawDataLabels: function () { + var series = this, mapOptionsToLevel = series.mapOptionsToLevel, points = series.points.filter(function (n) { + return n.node.visible; + }), options, level; + points.forEach(function (point) { + level = mapOptionsToLevel[point.node.level]; + // Set options to new object to avoid problems with scope + options = { style: {} }; + // If not a leaf, then label should be disabled as default + if (!point.node.isLeaf) { + options.enabled = false; + } + // If options for level exists, include them as well + if (level && level.dataLabels) { + options = merge(options, level.dataLabels); + series._hasPointLabels = true; + } + // Set dataLabel width to the width of the point shape. + if (point.shapeArgs) { + options.style.width = point.shapeArgs.width; + if (point.dataLabel) { + point.dataLabel.css({ + width: point.shapeArgs.width + 'px' + }); + } + } + // Merge custom options with point options + point.dlOptions = merge(options, point.options.dataLabels); + }); + Series.prototype.drawDataLabels.call(this); + }, + // Over the alignment method by setting z index + alignDataLabel: function (point, dataLabel, labelOptions) { + var style = labelOptions.style; + // #8160: Prevent the label from exceeding the point's + // boundaries in treemaps by applying ellipsis overflow. + // The issue was happening when datalabel's text contained a + // long sequence of characters without a whitespace. + if (!defined(style.textOverflow) && + dataLabel.text && + dataLabel.getBBox().width > dataLabel.text.textWidth) { + dataLabel.css({ + textOverflow: 'ellipsis', + // unit (px) is required when useHTML is true + width: style.width += 'px' + }); + } + seriesTypes.column.prototype.alignDataLabel.apply(this, arguments); + if (point.dataLabel) { + // point.node.zIndex could be undefined (#6956) + point.dataLabel.attr({ zIndex: (point.node.zIndex || 0) + 1 }); + } + }, + // Get presentational attributes + pointAttribs: function (point, state) { + var series = this, mapOptionsToLevel = (isObject(series.mapOptionsToLevel) ? + series.mapOptionsToLevel : + {}), level = point && mapOptionsToLevel[point.node.level] || {}, options = this.options, attr, stateOptions = (state && options.states[state]) || {}, className = (point && point.getClassName()) || '', opacity; + // Set attributes by precedence. Point trumps level trumps series. + // Stroke width uses pick because it can be 0. + attr = { + 'stroke': (point && point.borderColor) || + level.borderColor || + stateOptions.borderColor || + options.borderColor, + 'stroke-width': pick(point && point.borderWidth, level.borderWidth, stateOptions.borderWidth, options.borderWidth), + 'dashstyle': (point && point.borderDashStyle) || + level.borderDashStyle || + stateOptions.borderDashStyle || + options.borderDashStyle, + 'fill': (point && point.color) || this.color + }; + // Hide levels above the current view + if (className.indexOf('highcharts-above-level') !== -1) { + attr.fill = 'none'; + attr['stroke-width'] = 0; + // Nodes with children that accept interaction + } + else if (className.indexOf('highcharts-internal-node-interactive') !== -1) { + opacity = pick(stateOptions.opacity, options.opacity); + attr.fill = color(attr.fill).setOpacity(opacity).get(); + attr.cursor = 'pointer'; + // Hide nodes that have children + } + else if (className.indexOf('highcharts-internal-node') !== -1) { + attr.fill = 'none'; + } + else if (state) { + // Brighten and hoist the hover nodes + attr.fill = color(attr.fill) + .brighten(stateOptions.brightness) + .get(); + } + return attr; + }, + // Override drawPoints + drawPoints: function () { + var series = this, chart = series.chart, renderer = chart.renderer, points = series.points, styledMode = chart.styledMode, options = series.options, shadow = styledMode ? {} : options.shadow, borderRadius = options.borderRadius, withinAnimationLimit = chart.pointCount < options.animationLimit, allowTraversingTree = options.allowTraversingTree; + points.forEach(function (point) { + var levelDynamic = point.node.levelDynamic, animate = {}, attr = {}, css = {}, groupKey = 'level-group-' + levelDynamic, hasGraphic = !!point.graphic, shouldAnimate = withinAnimationLimit && hasGraphic, shapeArgs = point.shapeArgs; + // Don't bother with calculate styling if the point is not drawn + if (point.shouldDraw()) { + if (borderRadius) { + attr.r = borderRadius; + } + merge(true, // Extend object + // Which object to extend + shouldAnimate ? animate : attr, + // Add shapeArgs to animate/attr if graphic exists + hasGraphic ? shapeArgs : {}, + // Add style attribs if !styleMode + styledMode ? + {} : + series.pointAttribs(point, (point.selected && 'select'))); + // In styled mode apply point.color. Use CSS, otherwise the + // fill used in the style sheet will take precedence over + // the fill attribute. + if (series.colorAttribs && styledMode) { + // Heatmap is loaded + extend(css, series.colorAttribs(point)); + } + if (!series[groupKey]) { + series[groupKey] = renderer.g(groupKey) + .attr({ + // @todo Set the zIndex based upon the number of + // levels, instead of using 1000 + zIndex: 1000 - levelDynamic + }) + .add(series.group); + series[groupKey].survive = true; + } + } + // Draw the point + point.draw({ + animatableAttribs: animate, + attribs: attr, + css: css, + group: series[groupKey], + renderer: renderer, + shadow: shadow, + shapeArgs: shapeArgs, + shapeType: 'rect' + }); + // If setRootNode is allowed, set a point cursor on clickables & + // add drillId to point + if (allowTraversingTree && point.graphic) { + point.drillId = options.interactByLeaf ? + series.drillToByLeaf(point) : + series.drillToByGroup(point); + } + }); + }, + // Add drilling on the suitable points + onClickDrillToNode: function (event) { + var series = this, point = event.point, drillId = point && point.drillId; + // If a drill id is returned, add click event and cursor. + if (isString(drillId)) { + point.setState(''); // Remove hover + series.setRootNode(drillId, true, { trigger: 'click' }); + } + }, + /** + * Finds the drill id for a parent node. Returns false if point should + * not have a click event. + * + * @private + * @function Highcharts.Series#drillToByGroup + * + * @param {Highcharts.Point} point + * + * @return {boolean|string} + * Drill to id or false when point should not have a click + * event. + */ + drillToByGroup: function (point) { + var series = this, drillId = false; + if ((point.node.level - series.nodeMap[series.rootNode].level) === + 1 && + !point.node.isLeaf) { + drillId = point.id; + } + return drillId; + }, + /** + * Finds the drill id for a leaf node. Returns false if point should not + * have a click event + * + * @private + * @function Highcharts.Series#drillToByLeaf + * + * @param {Highcharts.Point} point + * + * @return {boolean|string} + * Drill to id or false when point should not have a click + * event. + */ + drillToByLeaf: function (point) { + var series = this, drillId = false, nodeParent; + if ((point.node.parent !== series.rootNode) && + point.node.isLeaf) { + nodeParent = point.node; + while (!drillId) { + nodeParent = series.nodeMap[nodeParent.parent]; + if (nodeParent.parent === series.rootNode) { + drillId = nodeParent.id; + } + } + } + return drillId; + }, + drillUp: function () { + var series = this, node = series.nodeMap[series.rootNode]; + if (node && isString(node.parent)) { + series.setRootNode(node.parent, true, { trigger: 'traverseUpButton' }); + } + }, + // TODO remove this function at a suitable version. + drillToNode: function (id, redraw) { + error('WARNING: treemap.drillToNode has been renamed to treemap.' + + 'setRootNode, and will be removed in the next major version.'); + this.setRootNode(id, redraw); + }, + /** + * Sets a new root node for the series. + * + * @private + * @function Highcharts.Series#setRootNode + * + * @param {string} id The id of the new root node. + * @param {boolean} [redraw=true] Wether to redraw the chart or not. + * @param {object} [eventArguments] Arguments to be accessed in + * event handler. + * @param {string} [eventArguments.newRootId] Id of the new root. + * @param {string} [eventArguments.previousRootId] Id of the previous + * root. + * @param {boolean} [eventArguments.redraw] Wether to redraw the + * chart after. + * @param {object} [eventArguments.series] The series to update the root + * of. + * @param {string} [eventArguments.trigger] The action which + * triggered the event. Undefined if the setRootNode is called + * directly. + * @return {void} + * + * @fires Highcharts.Series#event:setRootNode + */ + setRootNode: function (id, redraw, eventArguments) { + var series = this, eventArgs = extend({ + newRootId: id, + previousRootId: series.rootNode, + redraw: pick(redraw, true), + series: series + }, eventArguments); + /** + * The default functionality of the setRootNode event. + * + * @private + * @param {object} args The event arguments. + * @param {string} args.newRootId Id of the new root. + * @param {string} args.previousRootId Id of the previous root. + * @param {boolean} args.redraw Wether to redraw the chart after. + * @param {object} args.series The series to update the root of. + * @param {string} [args.trigger=undefined] The action which + * triggered the event. Undefined if the setRootNode is called + * directly. + * @return {void} + */ + var defaultFn = function (args) { + var series = args.series; + // Store previous and new root ids on the series. + series.idPreviousRoot = args.previousRootId; + series.rootNode = args.newRootId; + // Redraw the chart + series.isDirty = true; // Force redraw + if (args.redraw) { + series.chart.redraw(); + } + }; + // Fire setRootNode event. + fireEvent(series, 'setRootNode', eventArgs, defaultFn); + }, + renderTraverseUpButton: function (rootId) { + var series = this, nodeMap = series.nodeMap, node = nodeMap[rootId], name = node.name, buttonOptions = series.options.traverseUpButton, backText = pick(buttonOptions.text, name, '< Back'), attr, states; + if (rootId === '') { + if (series.drillUpButton) { + series.drillUpButton = + series.drillUpButton.destroy(); + } + } + else if (!this.drillUpButton) { + attr = buttonOptions.theme; + states = attr && attr.states; + this.drillUpButton = this.chart.renderer + .button(backText, null, null, function () { + series.drillUp(); + }, attr, states && states.hover, states && states.select) + .addClass('highcharts-drillup-button') + .attr({ + align: buttonOptions.position.align, + zIndex: 7 + }) + .add() + .align(buttonOptions.position, false, buttonOptions.relativeTo || 'plotBox'); + } + else { + this.drillUpButton.placed = false; + this.drillUpButton.attr({ + text: backText + }) + .align(); + } + }, + buildKDTree: noop, + drawLegendSymbol: LegendSymbolMixin.drawRectangle, + getExtremes: function () { + // Get the extremes from the value data + var _a = Series.prototype.getExtremes + .call(this, this.colorValueData), dataMin = _a.dataMin, dataMax = _a.dataMax; + this.valueMin = dataMin; + this.valueMax = dataMax; + // Get the extremes from the y data + return Series.prototype.getExtremes.call(this); + }, + getExtremesFromAll: true, + /** + * Workaround for `inactive` state. Since `series.opacity` option is + * already reserved, don't use that state at all by disabling + * `inactiveOtherPoints` and not inheriting states by points. + * + * @private + */ + setState: function (state) { + this.options.inactiveOtherPoints = true; + Series.prototype.setState.call(this, state, false); + this.options.inactiveOtherPoints = false; + }, + utils: { + recursive: recursive + } + /* eslint-enable no-invalid-this, valid-jsdoc */ + }, { + draw: drawPoint, + setVisible: seriesTypes.pie.prototype.pointClass.prototype.setVisible, + /* eslint-disable no-invalid-this, valid-jsdoc */ + getClassName: function () { + var className = Point.prototype.getClassName.call(this), series = this.series, options = series.options; + // Above the current level + if (this.node.level <= series.nodeMap[series.rootNode].level) { + className += ' highcharts-above-level'; + } + else if (!this.node.isLeaf && + !pick(options.interactByLeaf, !options.allowTraversingTree)) { + className += ' highcharts-internal-node-interactive'; + } + else if (!this.node.isLeaf) { + className += ' highcharts-internal-node'; + } + return className; + }, + /** + * A tree point is valid if it has han id too, assume it may be a parent + * item. + * + * @private + * @function Highcharts.Point#isValid + */ + isValid: function () { + return this.id || isNumber(this.value); + }, + setState: function (state) { + Point.prototype.setState.call(this, state); + // Graphic does not exist when point is not visible. + if (this.graphic) { + this.graphic.attr({ + zIndex: state === 'hover' ? 1 : 0 + }); + } + }, + shouldDraw: function () { + var point = this; + return isNumber(point.plotY) && point.y !== null; + } + }); + addEvent(H.Series, 'afterBindAxes', function () { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, treeAxis; + if (xAxis && yAxis) { + if (series.is('treemap')) { + treeAxis = { + endOnTick: false, + gridLineWidth: 0, + lineWidth: 0, + min: 0, + dataMin: 0, + minPadding: 0, + max: AXIS_MAX, + dataMax: AXIS_MAX, + maxPadding: 0, + startOnTick: false, + title: null, + tickPositions: [] + }; + extend(yAxis.options, treeAxis); + extend(xAxis.options, treeAxis); + treemapAxisDefaultValues = true; + } + else if (treemapAxisDefaultValues) { + yAxis.setOptions(yAxis.userOptions); + xAxis.setOptions(xAxis.userOptions); + treemapAxisDefaultValues = false; + } + } + }); + /* eslint-enable no-invalid-this, valid-jsdoc */ + /** + * A `treemap` series. If the [type](#series.treemap.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.treemap + * @excluding dataParser, dataURL, stack, dataSorting + * @product highcharts + * @requires modules/treemap + * @apioption series.treemap + */ + /** + * An array of data points for the series. For the `treemap` series + * type, points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `value` options. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.treemap.turboThreshold), + * this option is not available. + * ```js + * data: [{ + * value: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * value: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array} + * @extends series.heatmap.data + * @excluding x, y + * @product highcharts + * @apioption series.treemap.data + */ + /** + * The value of the point, resulting in a relative area of the point + * in the treemap. + * + * @type {number|null} + * @product highcharts + * @apioption series.treemap.data.value + */ + /** + * Serves a purpose only if a `colorAxis` object is defined in the chart + * options. This value will decide which color the point gets from the + * scale of the colorAxis. + * + * @type {number} + * @since 4.1.0 + * @product highcharts + * @apioption series.treemap.data.colorValue + */ + /** + * Only for treemap. Use this option to build a tree structure. The + * value should be the id of the point which is the parent. If no points + * has a matching id, or this option is undefined, then the parent will + * be set to the root. + * + * @sample {highcharts} highcharts/point/parent/ + * Point parent + * @sample {highcharts} highcharts/demo/treemap-with-levels/ + * Example where parent id is not matching + * + * @type {string} + * @since 4.1.0 + * @product highcharts + * @apioption series.treemap.data.parent + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'modules/sunburst.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['mixins/draw-point.js'], _modules['mixins/tree-series.js']], function (H, U, drawPoint, mixinTreeSeries) { + /* * + * + * This module implements sunburst charts in Highcharts. + * + * (c) 2016-2020 Highsoft AS + * + * Authors: Jon Arild Nygard + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var correctFloat = U.correctFloat, error = U.error, extend = U.extend, isNumber = U.isNumber, isObject = U.isObject, isString = U.isString, merge = U.merge, seriesType = U.seriesType, splat = U.splat; + var CenteredSeriesMixin = H.CenteredSeriesMixin, Series = H.Series, getCenter = CenteredSeriesMixin.getCenter, getColor = mixinTreeSeries.getColor, getLevelOptions = mixinTreeSeries.getLevelOptions, getStartAndEndRadians = CenteredSeriesMixin.getStartAndEndRadians, isBoolean = function (x) { + return typeof x === 'boolean'; + }, noop = H.noop, rad2deg = 180 / Math.PI, seriesTypes = H.seriesTypes, setTreeValues = mixinTreeSeries.setTreeValues, updateRootId = mixinTreeSeries.updateRootId; + // TODO introduce step, which should default to 1. + var range = function range(from, to) { + var result = [], i; + if (isNumber(from) && isNumber(to) && from <= to) { + for (i = from; i <= to; i++) { + result.push(i); + } + } + return result; + }; + /** + * @private + * @function calculateLevelSizes + * + * @param {object} levelOptions + * Map of level to its options. + * + * @param {Highcharts.Dictionary} params + * Object containing number parameters `innerRadius` and `outerRadius`. + * + * @return {Highcharts.SunburstSeriesLevelsOptions|undefined} + * Returns the modified options, or undefined. + */ + var calculateLevelSizes = function calculateLevelSizes(levelOptions, params) { + var result, p = isObject(params) ? params : {}, totalWeight = 0, diffRadius, levels, levelsNotIncluded, remainingSize, from, to; + if (isObject(levelOptions)) { + result = merge({}, levelOptions); + from = isNumber(p.from) ? p.from : 0; + to = isNumber(p.to) ? p.to : 0; + levels = range(from, to); + levelsNotIncluded = Object.keys(result).filter(function (k) { + return levels.indexOf(+k) === -1; + }); + diffRadius = remainingSize = isNumber(p.diffRadius) ? p.diffRadius : 0; + // Convert percentage to pixels. + // Calculate the remaining size to divide between "weight" levels. + // Calculate total weight to use in convertion from weight to pixels. + levels.forEach(function (level) { + var options = result[level], unit = options.levelSize.unit, value = options.levelSize.value; + if (unit === 'weight') { + totalWeight += value; + } + else if (unit === 'percentage') { + options.levelSize = { + unit: 'pixels', + value: (value / 100) * diffRadius + }; + remainingSize -= options.levelSize.value; + } + else if (unit === 'pixels') { + remainingSize -= value; + } + }); + // Convert weight to pixels. + levels.forEach(function (level) { + var options = result[level], weight; + if (options.levelSize.unit === 'weight') { + weight = options.levelSize.value; + result[level].levelSize = { + unit: 'pixels', + value: (weight / totalWeight) * remainingSize + }; + } + }); + // Set all levels not included in interval [from,to] to have 0 pixels. + levelsNotIncluded.forEach(function (level) { + result[level].levelSize = { + value: 0, + unit: 'pixels' + }; + }); + } + return result; + }; + /** + * Find a set of coordinates given a start coordinates, an angle, and a + * distance. + * + * @private + * @function getEndPoint + * + * @param {number} x + * Start coordinate x + * + * @param {number} y + * Start coordinate y + * + * @param {number} angle + * Angle in radians + * + * @param {number} distance + * Distance from start to end coordinates + * + * @return {Highcharts.SVGAttributes} + * Returns the end coordinates, x and y. + */ + var getEndPoint = function getEndPoint(x, y, angle, distance) { + return { + x: x + (Math.cos(angle) * distance), + y: y + (Math.sin(angle) * distance) + }; + }; + var layoutAlgorithm = function layoutAlgorithm(parent, children, options) { + var startAngle = parent.start, range = parent.end - startAngle, total = parent.val, x = parent.x, y = parent.y, radius = ((options && + isObject(options.levelSize) && + isNumber(options.levelSize.value)) ? + options.levelSize.value : + 0), innerRadius = parent.r, outerRadius = innerRadius + radius, slicedOffset = options && isNumber(options.slicedOffset) ? + options.slicedOffset : + 0; + return (children || []).reduce(function (arr, child) { + var percentage = (1 / total) * child.val, radians = percentage * range, radiansCenter = startAngle + (radians / 2), offsetPosition = getEndPoint(x, y, radiansCenter, slicedOffset), values = { + x: child.sliced ? offsetPosition.x : x, + y: child.sliced ? offsetPosition.y : y, + innerR: innerRadius, + r: outerRadius, + radius: radius, + start: startAngle, + end: startAngle + radians + }; + arr.push(values); + startAngle = values.end; + return arr; + }, []); + }; + var getDlOptions = function getDlOptions(params) { + // Set options to new object to avoid problems with scope + var point = params.point, shape = isObject(params.shapeArgs) ? params.shapeArgs : {}, optionsPoint = (isObject(params.optionsPoint) ? + params.optionsPoint.dataLabels : + {}), + // The splat was used because levels dataLabels + // options doesn't work as an array + optionsLevel = splat(isObject(params.level) ? + params.level.dataLabels : + {})[0], options = merge({ + style: {} + }, optionsLevel, optionsPoint), rotationRad, rotation, rotationMode = options.rotationMode; + if (!isNumber(options.rotation)) { + if (rotationMode === 'auto' || rotationMode === 'circular') { + if (point.innerArcLength < 1 && + point.outerArcLength > shape.radius) { + rotationRad = 0; + // Triger setTextPath function to get textOutline etc. + if (point.dataLabelPath && rotationMode === 'circular') { + options.textPath = { + enabled: true + }; + } + } + else if (point.innerArcLength > 1 && + point.outerArcLength > 1.5 * shape.radius) { + if (rotationMode === 'circular') { + options.textPath = { + enabled: true, + attributes: { + dy: 5 + } + }; + } + else { + rotationMode = 'parallel'; + } + } + else { + // Trigger the destroyTextPath function + if (point.dataLabel && + point.dataLabel.textPathWrapper && + rotationMode === 'circular') { + options.textPath = { + enabled: false + }; + } + rotationMode = 'perpendicular'; + } + } + if (rotationMode !== 'auto' && rotationMode !== 'circular') { + rotationRad = (shape.end - + (shape.end - shape.start) / 2); + } + if (rotationMode === 'parallel') { + options.style.width = Math.min(shape.radius * 2.5, (point.outerArcLength + point.innerArcLength) / 2); + } + else { + options.style.width = shape.radius; + } + if (rotationMode === 'perpendicular' && + point.series.chart.renderer.fontMetrics(options.style.fontSize).h > point.outerArcLength) { + options.style.width = 1; + } + // Apply padding (#8515) + options.style.width = Math.max(options.style.width - 2 * (options.padding || 0), 1); + rotation = (rotationRad * rad2deg) % 180; + if (rotationMode === 'parallel') { + rotation -= 90; + } + // Prevent text from rotating upside down + if (rotation > 90) { + rotation -= 180; + } + else if (rotation < -90) { + rotation += 180; + } + options.rotation = rotation; + } + if (options.textPath) { + if (point.shapeExisting.innerR === 0 && + options.textPath.enabled) { + // Enable rotation to render text + options.rotation = 0; + // Center dataLabel - disable textPath + options.textPath.enabled = false; + // Setting width and padding + options.style.width = Math.max((point.shapeExisting.r * 2) - + 2 * (options.padding || 0), 1); + } + else if (point.dlOptions && + point.dlOptions.textPath && + !point.dlOptions.textPath.enabled && + (rotationMode === 'circular')) { + // Bring dataLabel back if was a center dataLabel + options.textPath.enabled = true; + } + if (options.textPath.enabled) { + // Enable rotation to render text + options.rotation = 0; + // Setting width and padding + options.style.width = Math.max((point.outerArcLength + + point.innerArcLength) / 2 - + 2 * (options.padding || 0), 1); + } + } + // NOTE: alignDataLabel positions the data label differntly when rotation is + // 0. Avoiding this by setting rotation to a small number. + if (options.rotation === 0) { + options.rotation = 0.001; + } + return options; + }; + var getAnimation = function getAnimation(shape, params) { + var point = params.point, radians = params.radians, innerR = params.innerR, idRoot = params.idRoot, idPreviousRoot = params.idPreviousRoot, shapeExisting = params.shapeExisting, shapeRoot = params.shapeRoot, shapePreviousRoot = params.shapePreviousRoot, visible = params.visible, from = {}, to = { + end: shape.end, + start: shape.start, + innerR: shape.innerR, + r: shape.r, + x: shape.x, + y: shape.y + }; + if (visible) { + // Animate points in + if (!point.graphic && shapePreviousRoot) { + if (idRoot === point.id) { + from = { + start: radians.start, + end: radians.end + }; + } + else { + from = (shapePreviousRoot.end <= shape.start) ? { + start: radians.end, + end: radians.end + } : { + start: radians.start, + end: radians.start + }; + } + // Animate from center and outwards. + from.innerR = from.r = innerR; + } + } + else { + // Animate points out + if (point.graphic) { + if (idPreviousRoot === point.id) { + to = { + innerR: innerR, + r: innerR + }; + } + else if (shapeRoot) { + to = (shapeRoot.end <= shapeExisting.start) ? + { + innerR: innerR, + r: innerR, + start: radians.end, + end: radians.end + } : { + innerR: innerR, + r: innerR, + start: radians.start, + end: radians.start + }; + } + } + } + return { + from: from, + to: to + }; + }; + var getDrillId = function getDrillId(point, idRoot, mapIdToNode) { + var drillId, node = point.node, nodeRoot; + if (!node.isLeaf) { + // When it is the root node, the drillId should be set to parent. + if (idRoot === point.id) { + nodeRoot = mapIdToNode[idRoot]; + drillId = nodeRoot.parent; + } + else { + drillId = point.id; + } + } + return drillId; + }; + var getLevelFromAndTo = function getLevelFromAndTo(_a) { + var level = _a.level, height = _a.height; + // Never displays level below 1 + var from = level > 0 ? level : 1; + var to = level + height; + return { from: from, to: to }; + }; + var cbSetTreeValuesBefore = function before(node, options) { + var mapIdToNode = options.mapIdToNode, nodeParent = mapIdToNode[node.parent], series = options.series, chart = series.chart, points = series.points, point = points[node.i], colors = (series.options.colors || chart && chart.options.colors), colorInfo = getColor(node, { + colors: colors, + colorIndex: series.colorIndex, + index: options.index, + mapOptionsToLevel: options.mapOptionsToLevel, + parentColor: nodeParent && nodeParent.color, + parentColorIndex: nodeParent && nodeParent.colorIndex, + series: options.series, + siblings: options.siblings + }); + node.color = colorInfo.color; + node.colorIndex = colorInfo.colorIndex; + if (point) { + point.color = node.color; + point.colorIndex = node.colorIndex; + // Set slicing on node, but avoid slicing the top node. + node.sliced = (node.id !== options.idRoot) ? point.sliced : false; + } + return node; + }; + /** + * A Sunburst displays hierarchical data, where a level in the hierarchy is + * represented by a circle. The center represents the root node of the tree. + * The visualization bears a resemblance to both treemap and pie charts. + * + * @sample highcharts/demo/sunburst + * Sunburst chart + * + * @extends plotOptions.pie + * @excluding allAreas, clip, colorAxis, colorKey, compare, compareBase, + * dataGrouping, depth, dragDrop, endAngle, gapSize, gapUnit, + * ignoreHiddenPoint, innerSize, joinBy, legendType, linecap, + * minSize, navigatorOptions, pointRange + * @product highcharts + * @requires modules/sunburst.js + * @optionparent plotOptions.sunburst + * @private + */ + var sunburstOptions = { + /** + * Set options on specific levels. Takes precedence over series options, + * but not point options. + * + * @sample highcharts/demo/sunburst + * Sunburst chart + * + * @type {Array<*>} + * @apioption plotOptions.sunburst.levels + */ + /** + * Can set a `borderColor` on all points which lies on the same level. + * + * @type {Highcharts.ColorString} + * @apioption plotOptions.sunburst.levels.borderColor + */ + /** + * Can set a `borderWidth` on all points which lies on the same level. + * + * @type {number} + * @apioption plotOptions.sunburst.levels.borderWidth + */ + /** + * Can set a `borderDashStyle` on all points which lies on the same level. + * + * @type {Highcharts.DashStyleValue} + * @apioption plotOptions.sunburst.levels.borderDashStyle + */ + /** + * Can set a `color` on all points which lies on the same level. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.sunburst.levels.color + */ + /** + * Can set a `colorVariation` on all points which lies on the same level. + * + * @apioption plotOptions.sunburst.levels.colorVariation + */ + /** + * The key of a color variation. Currently supports `brightness` only. + * + * @type {string} + * @apioption plotOptions.sunburst.levels.colorVariation.key + */ + /** + * The ending value of a color variation. The last sibling will receive this + * value. + * + * @type {number} + * @apioption plotOptions.sunburst.levels.colorVariation.to + */ + /** + * Can set `dataLabels` on all points which lies on the same level. + * + * @extends plotOptions.sunburst.dataLabels + * @apioption plotOptions.sunburst.levels.dataLabels + */ + /** + * Can set a `levelSize` on all points which lies on the same level. + * + * @type {object} + * @apioption plotOptions.sunburst.levels.levelSize + */ + /** + * Can set a `rotation` on all points which lies on the same level. + * + * @type {number} + * @apioption plotOptions.sunburst.levels.rotation + */ + /** + * Can set a `rotationMode` on all points which lies on the same level. + * + * @type {string} + * @apioption plotOptions.sunburst.levels.rotationMode + */ + /** + * When enabled the user can click on a point which is a parent and + * zoom in on its children. Deprecated and replaced by + * [allowTraversingTree](#plotOptions.sunburst.allowTraversingTree). + * + * @deprecated + * @type {boolean} + * @default false + * @since 6.0.0 + * @product highcharts + * @apioption plotOptions.sunburst.allowDrillToNode + */ + /** + * When enabled the user can click on a point which is a parent and + * zoom in on its children. + * + * @type {boolean} + * @default false + * @since 7.0.3 + * @product highcharts + * @apioption plotOptions.sunburst.allowTraversingTree + */ + /** + * The center of the sunburst chart relative to the plot area. Can be + * percentages or pixel values. + * + * @sample {highcharts} highcharts/plotoptions/pie-center/ + * Centered at 100, 100 + * + * @type {Array} + * @default ["50%", "50%"] + * @product highcharts + */ + center: ['50%', '50%'], + colorByPoint: false, + /** + * Disable inherited opacity from Treemap series. + * + * @ignore-option + */ + opacity: 1, + /** + * @declare Highcharts.SeriesSunburstDataLabelsOptionsObject + */ + dataLabels: { + allowOverlap: true, + defer: true, + /** + * Decides how the data label will be rotated relative to the perimeter + * of the sunburst. Valid values are `auto`, `circular`, `parallel` and + * `perpendicular`. When `auto`, the best fit will be + * computed for the point. The `circular` option works similiar + * to `auto`, but uses the `textPath` feature - labels are curved, + * resulting in a better layout, however multiple lines and + * `textOutline` are not supported. + * + * The `series.rotation` option takes precedence over `rotationMode`. + * + * @type {string} + * @sample {highcharts} highcharts/plotoptions/sunburst-datalabels-rotationmode-circular/ + * Circular rotation mode + * @validvalue ["auto", "perpendicular", "parallel", "circular"] + * @since 6.0.0 + */ + rotationMode: 'auto', + style: { + /** @internal */ + textOverflow: 'ellipsis' + } + }, + /** + * Which point to use as a root in the visualization. + * + * @type {string} + */ + rootId: void 0, + /** + * Used together with the levels and `allowDrillToNode` options. When + * set to false the first level visible when drilling is considered + * to be level one. Otherwise the level will be the same as the tree + * structure. + */ + levelIsConstant: true, + /** + * Determines the width of the ring per level. + * + * @sample {highcharts} highcharts/plotoptions/sunburst-levelsize/ + * Sunburst with various sizes per level + * + * @since 6.0.5 + */ + levelSize: { + /** + * The value used for calculating the width of the ring. Its' affect is + * determined by `levelSize.unit`. + * + * @sample {highcharts} highcharts/plotoptions/sunburst-levelsize/ + * Sunburst with various sizes per level + */ + value: 1, + /** + * How to interpret `levelSize.value`. + * + * - `percentage` gives a width relative to result of outer radius minus + * inner radius. + * + * - `pixels` gives the ring a fixed width in pixels. + * + * - `weight` takes the remaining width after percentage and pixels, and + * distributes it accross all "weighted" levels. The value relative to + * the sum of all weights determines the width. + * + * @sample {highcharts} highcharts/plotoptions/sunburst-levelsize/ + * Sunburst with various sizes per level + * + * @validvalue ["percentage", "pixels", "weight"] + */ + unit: 'weight' + }, + /** + * Options for the button appearing when traversing down in a treemap. + * + * @extends plotOptions.treemap.traverseUpButton + * @since 6.0.0 + * @apioption plotOptions.sunburst.traverseUpButton + */ + /** + * If a point is sliced, moved out from the center, how many pixels + * should it be moved?. + * + * @sample highcharts/plotoptions/sunburst-sliced + * Sliced sunburst + * + * @since 6.0.4 + */ + slicedOffset: 10 + }; + // Properties of the Sunburst series. + var sunburstSeries = { + drawDataLabels: noop, + drawPoints: function drawPoints() { + var series = this, mapOptionsToLevel = series.mapOptionsToLevel, shapeRoot = series.shapeRoot, group = series.group, hasRendered = series.hasRendered, idRoot = series.rootNode, idPreviousRoot = series.idPreviousRoot, nodeMap = series.nodeMap, nodePreviousRoot = nodeMap[idPreviousRoot], shapePreviousRoot = nodePreviousRoot && nodePreviousRoot.shapeArgs, points = series.points, radians = series.startAndEndRadians, chart = series.chart, optionsChart = chart && chart.options && chart.options.chart || {}, animation = (isBoolean(optionsChart.animation) ? + optionsChart.animation : + true), positions = series.center, center = { + x: positions[0], + y: positions[1] + }, innerR = positions[3] / 2, renderer = series.chart.renderer, animateLabels, animateLabelsCalled = false, addedHack = false, hackDataLabelAnimation = !!(animation && + hasRendered && + idRoot !== idPreviousRoot && + series.dataLabelsGroup); + if (hackDataLabelAnimation) { + series.dataLabelsGroup.attr({ opacity: 0 }); + animateLabels = function () { + var s = series; + animateLabelsCalled = true; + if (s.dataLabelsGroup) { + s.dataLabelsGroup.animate({ + opacity: 1, + visibility: 'visible' + }); + } + }; + } + points.forEach(function (point) { + var node = point.node, level = mapOptionsToLevel[node.level], shapeExisting = point.shapeExisting || {}, shape = node.shapeArgs || {}, animationInfo, onComplete, visible = !!(node.visible && node.shapeArgs); + if (hasRendered && animation) { + animationInfo = getAnimation(shape, { + center: center, + point: point, + radians: radians, + innerR: innerR, + idRoot: idRoot, + idPreviousRoot: idPreviousRoot, + shapeExisting: shapeExisting, + shapeRoot: shapeRoot, + shapePreviousRoot: shapePreviousRoot, + visible: visible + }); + } + else { + // When animation is disabled, attr is called from animation. + animationInfo = { + to: shape, + from: {} + }; + } + extend(point, { + shapeExisting: shape, + tooltipPos: [shape.plotX, shape.plotY], + drillId: getDrillId(point, idRoot, nodeMap), + name: '' + (point.name || point.id || point.index), + plotX: shape.plotX, + plotY: shape.plotY, + value: node.val, + isNull: !visible // used for dataLabels & point.draw + }); + point.dlOptions = getDlOptions({ + point: point, + level: level, + optionsPoint: point.options, + shapeArgs: shape + }); + if (!addedHack && visible) { + addedHack = true; + onComplete = animateLabels; + } + point.draw({ + animatableAttribs: animationInfo.to, + attribs: extend(animationInfo.from, (!chart.styledMode && series.pointAttribs(point, (point.selected && 'select')))), + onComplete: onComplete, + group: group, + renderer: renderer, + shapeType: 'arc', + shapeArgs: shape + }); + }); + // Draw data labels after points + // TODO draw labels one by one to avoid addtional looping + if (hackDataLabelAnimation && addedHack) { + series.hasRendered = false; + series.options.dataLabels.defer = true; + Series.prototype.drawDataLabels.call(series); + series.hasRendered = true; + // If animateLabels is called before labels were hidden, then call + // it again. + if (animateLabelsCalled) { + animateLabels(); + } + } + else { + Series.prototype.drawDataLabels.call(series); + } + }, + pointAttribs: seriesTypes.column.prototype.pointAttribs, + // The layout algorithm for the levels + layoutAlgorithm: layoutAlgorithm, + // Set the shape arguments on the nodes. Recursive from root down. + setShapeArgs: function (parent, parentValues, mapOptionsToLevel) { + var childrenValues = [], level = parent.level + 1, options = mapOptionsToLevel[level], + // Collect all children which should be included + children = parent.children.filter(function (n) { + return n.visible; + }), twoPi = 6.28; // Two times Pi. + childrenValues = this.layoutAlgorithm(parentValues, children, options); + children.forEach(function (child, index) { + var values = childrenValues[index], angle = values.start + ((values.end - values.start) / 2), radius = values.innerR + ((values.r - values.innerR) / 2), radians = (values.end - values.start), isCircle = (values.innerR === 0 && radians > twoPi), center = (isCircle ? + { x: values.x, y: values.y } : + getEndPoint(values.x, values.y, angle, radius)), val = (child.val ? + (child.childrenTotal > child.val ? + child.childrenTotal : + child.val) : + child.childrenTotal); + // The inner arc length is a convenience for data label filters. + if (this.points[child.i]) { + this.points[child.i].innerArcLength = radians * values.innerR; + this.points[child.i].outerArcLength = radians * values.r; + } + child.shapeArgs = merge(values, { + plotX: center.x, + plotY: center.y + 4 * Math.abs(Math.cos(angle)) + }); + child.values = merge(values, { + val: val + }); + // If node has children, then call method recursively + if (child.children.length) { + this.setShapeArgs(child, child.values, mapOptionsToLevel); + } + }, this); + }, + translate: function translate() { + var series = this, options = series.options, positions = series.center = getCenter.call(series), radians = series.startAndEndRadians = getStartAndEndRadians(options.startAngle, options.endAngle), innerRadius = positions[3] / 2, outerRadius = positions[2] / 2, diffRadius = outerRadius - innerRadius, + // NOTE: updateRootId modifies series. + rootId = updateRootId(series), mapIdToNode = series.nodeMap, mapOptionsToLevel, idTop, nodeRoot = mapIdToNode && mapIdToNode[rootId], nodeTop, tree, values, nodeIds = {}; + series.shapeRoot = nodeRoot && nodeRoot.shapeArgs; + // Call prototype function + Series.prototype.translate.call(series); + // @todo Only if series.isDirtyData is true + tree = series.tree = series.getTree(); + // Render traverseUpButton, after series.nodeMap i calculated. + series.renderTraverseUpButton(rootId); + mapIdToNode = series.nodeMap; + nodeRoot = mapIdToNode[rootId]; + idTop = isString(nodeRoot.parent) ? nodeRoot.parent : ''; + nodeTop = mapIdToNode[idTop]; + var _a = getLevelFromAndTo(nodeRoot), from = _a.from, to = _a.to; + mapOptionsToLevel = getLevelOptions({ + from: from, + levels: series.options.levels, + to: to, + defaults: { + colorByPoint: options.colorByPoint, + dataLabels: options.dataLabels, + levelIsConstant: options.levelIsConstant, + levelSize: options.levelSize, + slicedOffset: options.slicedOffset + } + }); + // NOTE consider doing calculateLevelSizes in a callback to + // getLevelOptions + mapOptionsToLevel = calculateLevelSizes(mapOptionsToLevel, { + diffRadius: diffRadius, + from: from, + to: to + }); + // TODO Try to combine setTreeValues & setColorRecursive to avoid + // unnecessary looping. + setTreeValues(tree, { + before: cbSetTreeValuesBefore, + idRoot: rootId, + levelIsConstant: options.levelIsConstant, + mapOptionsToLevel: mapOptionsToLevel, + mapIdToNode: mapIdToNode, + points: series.points, + series: series + }); + values = mapIdToNode[''].shapeArgs = { + end: radians.end, + r: innerRadius, + start: radians.start, + val: nodeRoot.val, + x: positions[0], + y: positions[1] + }; + this.setShapeArgs(nodeTop, values, mapOptionsToLevel); + // Set mapOptionsToLevel on series for use in drawPoints. + series.mapOptionsToLevel = mapOptionsToLevel; + // #10669 - verify if all nodes have unique ids + series.data.forEach(function (child) { + if (nodeIds[child.id]) { + error(31, false, series.chart); + } + // map + nodeIds[child.id] = true; + }); + // reset object + nodeIds = {}; + }, + alignDataLabel: function (point, dataLabel, labelOptions) { + if (labelOptions.textPath && labelOptions.textPath.enabled) { + return; + } + return seriesTypes.treemap.prototype.alignDataLabel + .apply(this, arguments); + }, + // Animate the slices in. Similar to the animation of polar charts. + animate: function (init) { + var chart = this.chart, center = [ + chart.plotWidth / 2, + chart.plotHeight / 2 + ], plotLeft = chart.plotLeft, plotTop = chart.plotTop, attribs, group = this.group; + // Initialize the animation + if (init) { + // Scale down the group and place it in the center + attribs = { + translateX: center[0] + plotLeft, + translateY: center[1] + plotTop, + scaleX: 0.001, + scaleY: 0.001, + rotation: 10, + opacity: 0.01 + }; + group.attr(attribs); + // Run the animation + } + else { + attribs = { + translateX: plotLeft, + translateY: plotTop, + scaleX: 1, + scaleY: 1, + rotation: 0, + opacity: 1 + }; + group.animate(attribs, this.options.animation); + } + }, + utils: { + calculateLevelSizes: calculateLevelSizes, + getLevelFromAndTo: getLevelFromAndTo, + range: range + } + }; + // Properties of the Sunburst series. + var sunburstPoint = { + draw: drawPoint, + shouldDraw: function shouldDraw() { + return !this.isNull; + }, + isValid: function isValid() { + return true; + }, + getDataLabelPath: function (label) { + var renderer = this.series.chart.renderer, shapeArgs = this.shapeExisting, start = shapeArgs.start, end = shapeArgs.end, angle = start + (end - start) / 2, // arc middle value + upperHalf = angle < 0 && + angle > -Math.PI || + angle > Math.PI, r = (shapeArgs.r + (label.options.distance || 0)), moreThanHalf; + // Check if point is a full circle + if (start === -Math.PI / 2 && + correctFloat(end) === correctFloat(Math.PI * 1.5)) { + start = -Math.PI + Math.PI / 360; + end = -Math.PI / 360; + upperHalf = true; + } + // Check if dataLabels should be render in the + // upper half of the circle + if (end - start > Math.PI) { + upperHalf = false; + moreThanHalf = true; + } + if (this.dataLabelPath) { + this.dataLabelPath = this.dataLabelPath.destroy(); + } + this.dataLabelPath = renderer + .arc({ + open: true, + longArc: moreThanHalf ? 1 : 0 + }) + // Add it inside the data label group so it gets destroyed + // with the label + .add(label); + this.dataLabelPath.attr({ + start: (upperHalf ? start : end), + end: (upperHalf ? end : start), + clockwise: +upperHalf, + x: shapeArgs.x, + y: shapeArgs.y, + r: (r + shapeArgs.innerR) / 2 + }); + return this.dataLabelPath; + } + }; + /** + * A `sunburst` series. If the [type](#series.sunburst.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.sunburst + * @excluding dataParser, dataURL, stack, dataSorting + * @product highcharts + * @requires modules/sunburst.js + * @apioption series.sunburst + */ + /** + * @type {Array} + * @extends series.treemap.data + * @excluding x, y + * @product highcharts + * @apioption series.sunburst.data + */ + /** + * @type {Highcharts.SeriesSunburstDataLabelsOptionsObject|Array} + * @product highcharts + * @apioption series.sunburst.data.dataLabels + */ + /** + * The value of the point, resulting in a relative area of the point + * in the sunburst. + * + * @type {number|null} + * @since 6.0.0 + * @product highcharts + * @apioption series.sunburst.data.value + */ + /** + * Use this option to build a tree structure. The value should be the id of the + * point which is the parent. If no points has a matching id, or this option is + * undefined, then the parent will be set to the root. + * + * @type {string} + * @since 6.0.0 + * @product highcharts + * @apioption series.sunburst.data.parent + */ + /** + * Whether to display a slice offset from the center. When a sunburst point is + * sliced, its children are also offset. + * + * @sample highcharts/plotoptions/sunburst-sliced + * Sliced sunburst + * + * @type {boolean} + * @default false + * @since 6.0.4 + * @product highcharts + * @apioption series.sunburst.data.sliced + */ + /** + * @private + * @class + * @name Highcharts.seriesTypes.sunburst + * + * @augments Highcharts.Series + */ + seriesType('sunburst', 'treemap', sunburstOptions, sunburstSeries, sunburstPoint); + + }); + _registerModule(_modules, 'masters/modules/sunburst.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/tilemap.js b/librerias/gantt/code/modules/tilemap.js new file mode 100644 index 0000000..25da772 --- /dev/null +++ b/librerias/gantt/code/modules/tilemap.js @@ -0,0 +1,23 @@ +/* + Highmaps JS v8.1.0 (2020-05-05) + + Tilemap module + + (c) 2010-2019 Highsoft AS + + License: www.highcharts.com/license +*/ +(function(d){"object"===typeof module&&module.exports?(d["default"]=d,module.exports=d):"function"===typeof define&&define.amd?define("highcharts/modules/tilemap",["highcharts","highcharts/modules/map"],function(f){d(f);d.Highcharts=f;return d}):d("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(d){function f(e,d,f,v){e.hasOwnProperty(d)||(e[d]=v.apply(null,f))}d=d?d._modules:{};f(d,"modules/tilemap.src.js",[d["parts/Globals.js"],d["parts/Utilities.js"]],function(e,d){function f(a,b, +c){a=a.options;return{xPad:(a.colsize||1)/-b,yPad:(a.rowsize||1)/-c}}"";var v=d.addEvent,h=d.clamp,y=d.extend,x=d.pick;d=d.seriesType;e.tileShapeTypes={hexagon:{alignDataLabel:e.seriesTypes.scatter.prototype.alignDataLabel,getSeriesPadding:function(a){return f(a,3,2)},haloPath:function(a){if(!a)return[];var b=this.tileEdges;return[["M",b.x2-a,b.y1+a],["L",b.x3+a,b.y1+a],["L",b.x4+1.5*a,b.y2],["L",b.x3+a,b.y3-a],["L",b.x2-a,b.y3-a],["L",b.x1-1.5*a,b.y2],["Z"]]},translate:function(){var a=this.options, +b=this.xAxis,c=this.yAxis,d=a.pointPadding||0,e=(a.colsize||1)/3,f=(a.rowsize||1)/2,n;this.generatePoints();this.points.forEach(function(a){var t=h(Math.floor(b.len-b.translate(a.x-2*e,0,1,0,1)),-b.len,2*b.len),k=h(Math.floor(b.len-b.translate(a.x-e,0,1,0,1)),-b.len,2*b.len),q=h(Math.floor(b.len-b.translate(a.x+e,0,1,0,1)),-b.len,2*b.len),u=h(Math.floor(b.len-b.translate(a.x+2*e,0,1,0,1)),-b.len,2*b.len),r=h(Math.floor(c.translate(a.y-f,0,1,0,1)),-c.len,2*c.len),g=h(Math.floor(c.translate(a.y,0,1, +0,1)),-c.len,2*c.len),l=h(Math.floor(c.translate(a.y+f,0,1,0,1)),-c.len,2*c.len),m=x(a.pointPadding,d),p=m*Math.abs(k-t)/Math.abs(l-g);p=b.reversed?-p:p;var w=b.reversed?-m:m;m=c.reversed?-m:m;a.x%2&&(n=n||Math.round(Math.abs(l-r)/2)*(c.reversed?-1:1),r+=n,g+=n,l+=n);a.plotX=a.clientX=(k+q)/2;a.plotY=g;t+=p+w;k+=w;q-=w;u-=p+w;r-=m;l+=m;a.tileEdges={x1:t,x2:k,x3:q,x4:u,y1:r,y2:g,y3:l};a.shapeType="path";a.shapeArgs={d:[["M",k,r],["L",q,r],["L",u,g],["L",q,l],["L",k,l],["L",t,g],["Z"]]}});this.translateColors()}}, +diamond:{alignDataLabel:e.seriesTypes.scatter.prototype.alignDataLabel,getSeriesPadding:function(a){return f(a,2,2)},haloPath:function(a){if(!a)return[];var b=this.tileEdges;return[["M",b.x2,b.y1+a],["L",b.x3+a,b.y2],["L",b.x2,b.y3-a],["L",b.x1-a,b.y2],["Z"]]},translate:function(){var a=this.options,b=this.xAxis,c=this.yAxis,d=a.pointPadding||0,e=a.colsize||1,f=(a.rowsize||1)/2,n;this.generatePoints();this.points.forEach(function(a){var p=h(Math.round(b.len-b.translate(a.x-e,0,1,0,0)),-b.len,2*b.len), +k=h(Math.round(b.len-b.translate(a.x,0,1,0,0)),-b.len,2*b.len),q=h(Math.round(b.len-b.translate(a.x+e,0,1,0,0)),-b.len,2*b.len),u=h(Math.round(c.translate(a.y-f,0,1,0,0)),-c.len,2*c.len),r=h(Math.round(c.translate(a.y,0,1,0,0)),-c.len,2*c.len),g=h(Math.round(c.translate(a.y+f,0,1,0,0)),-c.len,2*c.len),l=x(a.pointPadding,d),m=l*Math.abs(k-p)/Math.abs(g-r);m=b.reversed?-m:m;l=c.reversed?-l:l;a.x%2&&(n=Math.abs(g-u)/2*(c.reversed?-1:1),u+=n,r+=n,g+=n);a.plotX=a.clientX=k;a.plotY=r;p+=m;q-=m;u-=l;g+= +l;a.tileEdges={x1:p,x2:k,x3:q,y1:u,y2:r,y3:g};a.shapeType="path";a.shapeArgs={d:[["M",k,u],["L",q,r],["L",k,g],["L",p,r],["Z"]]}});this.translateColors()}},circle:{alignDataLabel:e.seriesTypes.scatter.prototype.alignDataLabel,getSeriesPadding:function(a){return f(a,2,2)},haloPath:function(a){return e.seriesTypes.scatter.prototype.pointClass.prototype.haloPath.call(this,a+(a&&this.radius))},translate:function(){var a=this.options,b=this.xAxis,c=this.yAxis,d=a.pointPadding||0,e=(a.rowsize||1)/2,f=a.colsize|| +1,n,t,v,k,q=!1;this.generatePoints();this.points.forEach(function(a){var p=h(Math.round(b.len-b.translate(a.x,0,1,0,0)),-b.len,2*b.len),g=h(Math.round(c.translate(a.y,0,1,0,0)),-c.len,2*c.len),l=d,m=!1;"undefined"!==typeof a.pointPadding&&(l=a.pointPadding,q=m=!0);if(!k||q)n=Math.abs(h(Math.floor(b.len-b.translate(a.x+f,0,1,0,0)),-b.len,2*b.len)-p),t=Math.abs(h(Math.floor(c.translate(a.y+e,0,1,0,0)),-c.len,2*c.len)-g),v=Math.floor(Math.sqrt(n*n+t*t)/2),k=Math.min(n,v,t)-l,q&&!m&&(q=!1);a.x%2&&(g+= +t*(c.reversed?-1:1));a.plotX=a.clientX=p;a.plotY=g;a.radius=k;a.shapeType="circle";a.shapeArgs={x:p,y:g,r:k}});this.translateColors()}},square:{alignDataLabel:e.seriesTypes.heatmap.prototype.alignDataLabel,translate:e.seriesTypes.heatmap.prototype.translate,getSeriesPadding:function(){},haloPath:e.seriesTypes.heatmap.prototype.pointClass.prototype.haloPath}};v(e.Axis,"afterSetAxisTranslation",function(){if(!this.recomputingForTilemap&&"colorAxis"!==this.coll){var a=this,b=a.series.map(function(b){return b.getSeriesPixelPadding&& +b.getSeriesPixelPadding(a)}).reduce(function(a,b){return(a&&a.padding)>(b&&b.padding)?a:b},void 0)||{padding:0,axisLengthFactor:1},c=Math.round(b.padding*b.axisLengthFactor);b.padding&&(a.len-=c,a.recomputingForTilemap=!0,a.setAxisTranslation(),delete a.recomputingForTilemap,a.minPixelPadding+=b.padding,a.len+=c)}});d("tilemap","heatmap",{marker:null,states:{hover:{halo:{enabled:!0,size:2,opacity:.5,attributes:{zIndex:3}}}},pointPadding:2,tileShape:"hexagon"},{markerAttribs:e.seriesTypes.scatter.prototype.markerAttribs, +pointAttribs:e.seriesTypes.column.prototype.pointAttribs,getSymbol:e.noop,drawPoints:function(){var a=this;e.seriesTypes.column.prototype.drawPoints.call(this);this.points.forEach(function(b){b.graphic&&b.graphic[a.chart.styledMode?"css":"animate"](a.colorAttribs(b))})},setOptions:function(){var a=e.seriesTypes.heatmap.prototype.setOptions.apply(this,Array.prototype.slice.call(arguments));this.tileShape=e.tileShapeTypes[a.tileShape];return a},alignDataLabel:function(){return this.tileShape.alignDataLabel.apply(this, +Array.prototype.slice.call(arguments))},getSeriesPixelPadding:function(a){var b=a.isXAxis,c=this.tileShape.getSeriesPadding(this);if(!c)return{padding:0,axisLengthFactor:1};var d=Math.round(a.translate(b?2*c.xPad:c.yPad,0,1,0,1));a=Math.round(a.translate(b?c.xPad:0,0,1,0,1));return{padding:Math.abs(d-a)||0,axisLengthFactor:b?2:1.1}},translate:function(){return this.tileShape.translate.apply(this,Array.prototype.slice.call(arguments))}},y({haloPath:function(){return this.series.tileShape.haloPath.apply(this, +Array.prototype.slice.call(arguments))}},e.colorPointMixin));""});f(d,"masters/modules/tilemap.src.js",[],function(){})}); +//# sourceMappingURL=tilemap.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/tilemap.js.map b/librerias/gantt/code/modules/tilemap.js.map new file mode 100644 index 0000000..4df95fa --- /dev/null +++ b/librerias/gantt/code/modules/tilemap.js.map @@ -0,0 +1 @@ +{"version":3,"file":"tilemap.js.map","lineCount":22,"mappings":"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","sources":["tilemap.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","U","tilePaddingFromTileSize","series","xDiv","yDiv","options","xPad","colsize","yPad","rowsize","addEvent","clamp","extend","pick","seriesType","tileShapeTypes","hexagon","alignDataLabel","seriesTypes","scatter","prototype","getSeriesPadding","haloPath","size","tileEdges","x2","y1","x3","x4","y2","y3","x1","translate","xAxis","yAxis","seriesPointPadding","pointPadding","yShift","generatePoints","points","forEach","point","Math","floor","len","x","y","midPointPadding","abs","xMidPadding","reversed","xPointPadding","yPointPadding","round","plotX","clientX","plotY","shapeType","shapeArgs","d","translateColors","diamond","circle","pointClass","call","radius","yRadius","colsizePx","yRadiusPx","xRadiusPx","forceNextRadiusCompute","hasPerPointPadding","sqrt","min","r","square","heatmap","Axis","recomputingForTilemap","coll","axis","seriesPadding","map","getSeriesPixelPadding","reduce","a","b","padding","axisLengthFactor","lengthPadding","setAxisTranslation","minPixelPadding","marker","states","hover","halo","enabled","opacity","attributes","zIndex","tileShape","markerAttribs","pointAttribs","column","getSymbol","noop","drawPoints","_this","graphic","chart","styledMode","colorAttribs","setOptions","ret","Array","slice","arguments","isX","isXAxis","coord1","coord2","colorPointMixin"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/tilemap.src.js b/librerias/gantt/code/modules/tilemap.src.js new file mode 100644 index 0000000..ce9e347 --- /dev/null +++ b/librerias/gantt/code/modules/tilemap.src.js @@ -0,0 +1,615 @@ +/** + * @license Highmaps JS v8.1.0 (2020-05-05) + * + * Tilemap module + * + * (c) 2010-2019 Highsoft AS + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/tilemap', ['highcharts', 'highcharts/modules/map'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'modules/tilemap.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * Tilemaps module + * + * (c) 2010-2017 Highsoft AS + * Author: Øystein Moseng + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * @typedef {"circle"|"diamond"|"hexagon"|"square"} Highcharts.TilemapShapeValue + */ + ''; // detach doclets above + var addEvent = U.addEvent, clamp = U.clamp, extend = U.extend, pick = U.pick, seriesType = U.seriesType; + /** + * Utility func to get padding definition from tile size division + * @private + * @param {Highcharts.TilemapSeries} series + * series + * @param {Highcharts.number} xDiv + * xDiv + * @param {Highcharts.number} yDiv + * yDiv + * @return {Highcharts.TilemapPaddingObject} + */ + function tilePaddingFromTileSize(series, xDiv, yDiv) { + var options = series.options; + return { + xPad: (options.colsize || 1) / -xDiv, + yPad: (options.rowsize || 1) / -yDiv + }; + } + // Map of shape types. + H.tileShapeTypes = { + // Hexagon shape type. + hexagon: { + alignDataLabel: H.seriesTypes.scatter.prototype.alignDataLabel, + getSeriesPadding: function (series) { + return tilePaddingFromTileSize(series, 3, 2); + }, + haloPath: function (size) { + if (!size) { + return []; + } + var hexagon = this.tileEdges; + return [ + ['M', hexagon.x2 - size, hexagon.y1 + size], + ['L', hexagon.x3 + size, hexagon.y1 + size], + ['L', hexagon.x4 + size * 1.5, hexagon.y2], + ['L', hexagon.x3 + size, hexagon.y3 - size], + ['L', hexagon.x2 - size, hexagon.y3 - size], + ['L', hexagon.x1 - size * 1.5, hexagon.y2], + ['Z'] + ]; + }, + translate: function () { + var series = this, options = series.options, xAxis = series.xAxis, yAxis = series.yAxis, seriesPointPadding = options.pointPadding || 0, xPad = (options.colsize || 1) / 3, yPad = (options.rowsize || 1) / 2, yShift; + series.generatePoints(); + series.points.forEach(function (point) { + var x1 = clamp(Math.floor(xAxis.len - + xAxis.translate(point.x - xPad * 2, 0, 1, 0, 1)), -xAxis.len, 2 * xAxis.len), x2 = clamp(Math.floor(xAxis.len - + xAxis.translate(point.x - xPad, 0, 1, 0, 1)), -xAxis.len, 2 * xAxis.len), x3 = clamp(Math.floor(xAxis.len - + xAxis.translate(point.x + xPad, 0, 1, 0, 1)), -xAxis.len, 2 * xAxis.len), x4 = clamp(Math.floor(xAxis.len - + xAxis.translate(point.x + xPad * 2, 0, 1, 0, 1)), -xAxis.len, 2 * xAxis.len), y1 = clamp(Math.floor(yAxis.translate(point.y - yPad, 0, 1, 0, 1)), -yAxis.len, 2 * yAxis.len), y2 = clamp(Math.floor(yAxis.translate(point.y, 0, 1, 0, 1)), -yAxis.len, 2 * yAxis.len), y3 = clamp(Math.floor(yAxis.translate(point.y + yPad, 0, 1, 0, 1)), -yAxis.len, 2 * yAxis.len), pointPadding = pick(point.pointPadding, seriesPointPadding), + // We calculate the point padding of the midpoints to + // preserve the angles of the shape. + midPointPadding = pointPadding * + Math.abs(x2 - x1) / Math.abs(y3 - y2), xMidPadding = xAxis.reversed ? + -midPointPadding : midPointPadding, xPointPadding = xAxis.reversed ? + -pointPadding : pointPadding, yPointPadding = yAxis.reversed ? + -pointPadding : pointPadding; + // Shift y-values for every second grid column + if (point.x % 2) { + yShift = yShift || Math.round(Math.abs(y3 - y1) / 2) * + // We have to reverse the shift for reversed y-axes + (yAxis.reversed ? -1 : 1); + y1 += yShift; + y2 += yShift; + y3 += yShift; + } + // Set plotX and plotY for use in K-D-Tree and more + point.plotX = point.clientX = (x2 + x3) / 2; + point.plotY = y2; + // Apply point padding to translated coordinates + x1 += xMidPadding + xPointPadding; + x2 += xPointPadding; + x3 -= xPointPadding; + x4 -= xMidPadding + xPointPadding; + y1 -= yPointPadding; + y3 += yPointPadding; + // Store points for halo creation + point.tileEdges = { + x1: x1, x2: x2, x3: x3, x4: x4, y1: y1, y2: y2, y3: y3 + }; + // Finally set the shape for this point + point.shapeType = 'path'; + point.shapeArgs = { + d: [ + ['M', x2, y1], + ['L', x3, y1], + ['L', x4, y2], + ['L', x3, y3], + ['L', x2, y3], + ['L', x1, y2], + ['Z'] + ] + }; + }); + series.translateColors(); + } + }, + // Diamond shape type. + diamond: { + alignDataLabel: H.seriesTypes.scatter.prototype.alignDataLabel, + getSeriesPadding: function (series) { + return tilePaddingFromTileSize(series, 2, 2); + }, + haloPath: function (size) { + if (!size) { + return []; + } + var diamond = this.tileEdges; + return [ + ['M', diamond.x2, diamond.y1 + size], + ['L', diamond.x3 + size, diamond.y2], + ['L', diamond.x2, diamond.y3 - size], + ['L', diamond.x1 - size, diamond.y2], + ['Z'] + ]; + }, + translate: function () { + var series = this, options = series.options, xAxis = series.xAxis, yAxis = series.yAxis, seriesPointPadding = options.pointPadding || 0, xPad = (options.colsize || 1), yPad = (options.rowsize || 1) / 2, yShift; + series.generatePoints(); + series.points.forEach(function (point) { + var x1 = clamp(Math.round(xAxis.len - + xAxis.translate(point.x - xPad, 0, 1, 0, 0)), -xAxis.len, 2 * xAxis.len), x2 = clamp(Math.round(xAxis.len - + xAxis.translate(point.x, 0, 1, 0, 0)), -xAxis.len, 2 * xAxis.len), x3 = clamp(Math.round(xAxis.len - + xAxis.translate(point.x + xPad, 0, 1, 0, 0)), -xAxis.len, 2 * xAxis.len), y1 = clamp(Math.round(yAxis.translate(point.y - yPad, 0, 1, 0, 0)), -yAxis.len, 2 * yAxis.len), y2 = clamp(Math.round(yAxis.translate(point.y, 0, 1, 0, 0)), -yAxis.len, 2 * yAxis.len), y3 = clamp(Math.round(yAxis.translate(point.y + yPad, 0, 1, 0, 0)), -yAxis.len, 2 * yAxis.len), pointPadding = pick(point.pointPadding, seriesPointPadding), + // We calculate the point padding of the midpoints to + // preserve the angles of the shape. + midPointPadding = pointPadding * + Math.abs(x2 - x1) / Math.abs(y3 - y2), xPointPadding = xAxis.reversed ? + -midPointPadding : midPointPadding, yPointPadding = yAxis.reversed ? + -pointPadding : pointPadding; + // Shift y-values for every second grid column + // We have to reverse the shift for reversed y-axes + if (point.x % 2) { + yShift = Math.abs(y3 - y1) / 2 * (yAxis.reversed ? -1 : 1); + y1 += yShift; + y2 += yShift; + y3 += yShift; + } + // Set plotX and plotY for use in K-D-Tree and more + point.plotX = point.clientX = x2; + point.plotY = y2; + // Apply point padding to translated coordinates + x1 += xPointPadding; + x3 -= xPointPadding; + y1 -= yPointPadding; + y3 += yPointPadding; + // Store points for halo creation + point.tileEdges = { + x1: x1, x2: x2, x3: x3, y1: y1, y2: y2, y3: y3 + }; + // Set this point's shape parameters + point.shapeType = 'path'; + point.shapeArgs = { + d: [ + ['M', x2, y1], + ['L', x3, y2], + ['L', x2, y3], + ['L', x1, y2], + ['Z'] + ] + }; + }); + series.translateColors(); + } + }, + // Circle shape type. + circle: { + alignDataLabel: H.seriesTypes.scatter.prototype.alignDataLabel, + getSeriesPadding: function (series) { + return tilePaddingFromTileSize(series, 2, 2); + }, + haloPath: function (size) { + return H.seriesTypes.scatter.prototype.pointClass.prototype.haloPath + .call(this, size + (size && this.radius)); + }, + translate: function () { + var series = this, options = series.options, xAxis = series.xAxis, yAxis = series.yAxis, seriesPointPadding = options.pointPadding || 0, yRadius = (options.rowsize || 1) / 2, colsize = (options.colsize || 1), colsizePx, yRadiusPx, xRadiusPx, radius, forceNextRadiusCompute = false; + series.generatePoints(); + series.points.forEach(function (point) { + var x = clamp(Math.round(xAxis.len - + xAxis.translate(point.x, 0, 1, 0, 0)), -xAxis.len, 2 * xAxis.len), y = clamp(Math.round(yAxis.translate(point.y, 0, 1, 0, 0)), -yAxis.len, 2 * yAxis.len), pointPadding = seriesPointPadding, hasPerPointPadding = false; + // If there is point padding defined on a single point, add it + if (typeof point.pointPadding !== 'undefined') { + pointPadding = point.pointPadding; + hasPerPointPadding = true; + forceNextRadiusCompute = true; + } + // Find radius if not found already. + // Use the smallest one (x vs y) to avoid overlap. + // Note that the radius will be recomputed for each series. + // Ideal (max) x radius is dependent on y radius: + /* + * (circle 2) + + * (circle 3) + | yRadiusPx + (circle 1) *-------| + colsizePx + + The distance between circle 1 and 3 (and circle 2 and 3) is + 2r, which is the hypotenuse of the triangle created by + colsizePx and yRadiusPx. If the distance between circle 2 + and circle 1 is less than 2r, we use half of that distance + instead (yRadiusPx). + */ + if (!radius || forceNextRadiusCompute) { + colsizePx = Math.abs(clamp(Math.floor(xAxis.len - + xAxis.translate(point.x + colsize, 0, 1, 0, 0)), -xAxis.len, 2 * xAxis.len) - x); + yRadiusPx = Math.abs(clamp(Math.floor(yAxis.translate(point.y + yRadius, 0, 1, 0, 0)), -yAxis.len, 2 * yAxis.len) - y); + xRadiusPx = Math.floor(Math.sqrt((colsizePx * colsizePx + yRadiusPx * yRadiusPx)) / 2); + radius = Math.min(colsizePx, xRadiusPx, yRadiusPx) - pointPadding; + // If we have per point padding we need to always compute + // the radius for this point and the next. If we used to + // have per point padding but don't anymore, don't force + // compute next radius. + if (forceNextRadiusCompute && !hasPerPointPadding) { + forceNextRadiusCompute = false; + } + } + // Shift y-values for every second grid column. + // Note that we always use the optimal y axis radius for this. + // Also note: We have to reverse the shift for reversed y-axes. + if (point.x % 2) { + y += yRadiusPx * (yAxis.reversed ? -1 : 1); + } + // Set plotX and plotY for use in K-D-Tree and more + point.plotX = point.clientX = x; + point.plotY = y; + // Save radius for halo + point.radius = radius; + // Set this point's shape parameters + point.shapeType = 'circle'; + point.shapeArgs = { + x: x, + y: y, + r: radius + }; + }); + series.translateColors(); + } + }, + // Square shape type. + square: { + alignDataLabel: H.seriesTypes.heatmap.prototype.alignDataLabel, + translate: H.seriesTypes.heatmap.prototype.translate, + getSeriesPadding: function () { + }, + haloPath: H.seriesTypes.heatmap.prototype.pointClass.prototype.haloPath + } + }; + /* eslint-disable no-invalid-this */ + // Extension to add pixel padding for series. Uses getSeriesPixelPadding on each + // series and adds the largest padding required. If no series has this function + // defined, we add nothing. + addEvent(H.Axis, 'afterSetAxisTranslation', function () { + if (this.recomputingForTilemap || this.coll === 'colorAxis') { + return; + } + var axis = this, + // Find which series' padding to use + seriesPadding = axis.series + .map(function (series) { + return series.getSeriesPixelPadding && + series.getSeriesPixelPadding(axis); + }) + .reduce(function (a, b) { + return (a && a.padding) > (b && b.padding) ? + a : + b; + }, void 0) || + { + padding: 0, + axisLengthFactor: 1 + }, lengthPadding = Math.round(seriesPadding.padding * seriesPadding.axisLengthFactor); + // Don't waste time on this if we're not adding extra padding + if (seriesPadding.padding) { + // Recompute translation with new axis length now (minus padding) + axis.len -= lengthPadding; + axis.recomputingForTilemap = true; + axis.setAxisTranslation(); + delete axis.recomputingForTilemap; + axis.minPixelPadding += seriesPadding.padding; + axis.len += lengthPadding; + } + }); + /** + * @private + * @class + * @name Highcharts.seriesTypes.tilemap + * + * @augments Highcharts.Series + */ + seriesType('tilemap', 'heatmap' + /** + * A tilemap series is a type of heatmap where the tile shapes are + * configurable. + * + * @sample highcharts/demo/honeycomb-usa/ + * Honeycomb tilemap, USA + * @sample maps/plotoptions/honeycomb-brazil/ + * Honeycomb tilemap, Brazil + * @sample maps/plotoptions/honeycomb-china/ + * Honeycomb tilemap, China + * @sample maps/plotoptions/honeycomb-europe/ + * Honeycomb tilemap, Europe + * @sample maps/demo/circlemap-africa/ + * Circlemap tilemap, Africa + * @sample maps/demo/diamondmap + * Diamondmap tilemap + * + * @extends plotOptions.heatmap + * @since 6.0.0 + * @excluding jitter, joinBy, shadow, allAreas, mapData, marker, data, + * dataSorting + * @product highcharts highmaps + * @requires modules/tilemap.js + * @optionparent plotOptions.tilemap + */ + , { + // Remove marker from tilemap default options, as it was before + // heatmap refactoring. + marker: null, + states: { + hover: { + halo: { + enabled: true, + size: 2, + opacity: 0.5, + attributes: { + zIndex: 3 + } + } + } + }, + /** + * The padding between points in the tilemap. + * + * @sample maps/plotoptions/tilemap-pointpadding + * Point padding on tiles + */ + pointPadding: 2, + /** + * The column size - how many X axis units each column in the tilemap + * should span. Works as in [Heatmaps](#plotOptions.heatmap.colsize). + * + * @sample {highcharts} maps/demo/heatmap/ + * One day + * @sample {highmaps} maps/demo/heatmap/ + * One day + * + * @type {number} + * @default 1 + * @product highcharts highmaps + * @apioption plotOptions.tilemap.colsize + */ + /** + * The row size - how many Y axis units each tilemap row should span. + * Analogous to [colsize](#plotOptions.tilemap.colsize). + * + * @sample {highcharts} maps/demo/heatmap/ + * 1 by default + * @sample {highmaps} maps/demo/heatmap/ + * 1 by default + * + * @type {number} + * @default 1 + * @product highcharts highmaps + * @apioption plotOptions.tilemap.rowsize + */ + /** + * The shape of the tiles in the tilemap. Possible values are `hexagon`, + * `circle`, `diamond`, and `square`. + * + * @sample maps/demo/circlemap-africa + * Circular tile shapes + * @sample maps/demo/diamondmap + * Diamond tile shapes + * + * @type {Highcharts.TilemapShapeValue} + */ + tileShape: 'hexagon' + }, { + // Use drawPoints, markerAttribs, pointAttribs methods from the old + // heatmap implementation. + // TODO: Consider standarizing heatmap and tilemap into more + // consistent form. + markerAttribs: H.seriesTypes.scatter.prototype.markerAttribs, + pointAttribs: H.seriesTypes.column.prototype.pointAttribs, + // Revert the noop on getSymbol. + getSymbol: H.noop, + drawPoints: function () { + var _this = this; + // In styled mode, use CSS, otherwise the fill used in the style + // sheet will take precedence over the fill attribute. + H.seriesTypes.column.prototype.drawPoints.call(this); + this.points.forEach(function (point) { + point.graphic && + point.graphic[_this.chart.styledMode ? 'css' : 'animate'](_this.colorAttribs(point)); + }); + }, + // Set tile shape object on series + setOptions: function () { + // Call original function + var ret = H.seriesTypes.heatmap.prototype.setOptions.apply(this, Array.prototype.slice.call(arguments)); + this.tileShape = H.tileShapeTypes[ret.tileShape]; + return ret; + }, + // Use the shape's defined data label alignment function + alignDataLabel: function () { + return this.tileShape.alignDataLabel.apply(this, Array.prototype.slice.call(arguments)); + }, + // Get metrics for padding of axis for this series + getSeriesPixelPadding: function (axis) { + var isX = axis.isXAxis, padding = this.tileShape.getSeriesPadding(this), coord1, coord2; + // If the shape type does not require padding, return no-op padding + if (!padding) { + return { + padding: 0, + axisLengthFactor: 1 + }; + } + // Use translate to compute how far outside the points we + // draw, and use this difference as padding. + coord1 = Math.round(axis.translate(isX ? + padding.xPad * 2 : + padding.yPad, 0, 1, 0, 1)); + coord2 = Math.round(axis.translate(isX ? padding.xPad : 0, 0, 1, 0, 1)); + return { + padding: Math.abs(coord1 - coord2) || 0, + // Offset the yAxis length to compensate for shift. Setting the + // length factor to 2 would add the same margin to max as min. + // Now we only add a slight bit of the min margin to max, as we + // don't actually draw outside the max bounds. For the xAxis we + // draw outside on both sides so we add the same margin to min + // and max. + axisLengthFactor: isX ? 2 : 1.1 + }; + }, + // Use translate from tileShape + translate: function () { + return this.tileShape.translate.apply(this, Array.prototype.slice.call(arguments)); + } + }, extend({ + // eslint-disable-next-line valid-jsdoc + /** + * @private + * @function Highcharts.Point#haloPath + * + * @return {Highcharts.SVGElement|Highcharts.SVGPathArray|Array} + */ + haloPath: function () { + return this.series.tileShape.haloPath.apply(this, Array.prototype.slice.call(arguments)); + } + }, H.colorPointMixin)); + /** + * A `tilemap` series. If the [type](#series.tilemap.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.tilemap + * @excluding allAreas, dataParser, dataURL, joinBy, mapData, marker, + * pointRange, shadow, stack, dataSorting + * @product highcharts highmaps + * @requires modules/tilemap.js + * @apioption series.tilemap + */ + /** + * An array of data points for the series. For the `tilemap` series + * type, points can be given in the following ways: + * + * 1. An array of arrays with 3 or 2 values. In this case, the values correspond + * to `x,y,value`. If the first value is a string, it is applied as the name + * of the point, and the `x` value is inferred. The `x` value can also be + * omitted, in which case the inner arrays should be of length 2\. Then the + * `x` value is automatically calculated, either starting at 0 and + * incremented by 1, or from `pointStart` and `pointInterval` given in the + * series options. + * ```js + * data: [ + * [0, 9, 7], + * [1, 10, 4], + * [2, 6, 3] + * ] + * ``` + * + * 2. An array of objects with named values. The objects are point configuration + * objects as seen below. If the total number of data points exceeds the + * series' [turboThreshold](#series.tilemap.turboThreshold), this option is + * not available. + * ```js + * data: [{ + * x: 1, + * y: 3, + * value: 10, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 7, + * value: 10, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * Note that for some [tileShapes](#plotOptions.tilemap.tileShape) the grid + * coordinates are offset. + * + * @sample maps/series/tilemap-gridoffset + * Offset grid coordinates + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|Array<(number|string),number,number>|*>} + * @extends series.heatmap.data + * @excluding marker + * @product highcharts highmaps + * @apioption series.tilemap.data + */ + /** + * The color of the point. In tilemaps the point color is rarely set + * explicitly, as we use the color to denote the `value`. Options for + * this are set in the [colorAxis](#colorAxis) configuration. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highmaps + * @apioption series.tilemap.data.color + */ + /** + * The x coordinate of the point. + * + * Note that for some [tileShapes](#plotOptions.tilemap.tileShape) the grid + * coordinates are offset. + * + * @sample maps/series/tilemap-gridoffset + * Offset grid coordinates + * + * @type {number} + * @product highcharts highmaps + * @apioption series.tilemap.data.x + */ + /** + * The y coordinate of the point. + * + * Note that for some [tileShapes](#plotOptions.tilemap.tileShape) the grid + * coordinates are offset. + * + * @sample maps/series/tilemap-gridoffset + * Offset grid coordinates + * + * @type {number} + * @product highcharts highmaps + * @apioption series.tilemap.data.y + */ + ''; // adds doclets above to the transpiled file + + }); + _registerModule(_modules, 'masters/modules/tilemap.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/timeline.js b/librerias/gantt/code/modules/timeline.js new file mode 100644 index 0000000..d12462d --- /dev/null +++ b/librerias/gantt/code/modules/timeline.js @@ -0,0 +1,24 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Timeline series + + (c) 2010-2019 Highsoft AS + Author: Daniel Studencki + + License: www.highcharts.com/license +*/ +(function(c){"object"===typeof module&&module.exports?(c["default"]=c,module.exports=c):"function"===typeof define&&define.amd?define("highcharts/modules/timeline",["highcharts"],function(l){c(l);c.Highcharts=l;return c}):c("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(c){function l(c,l,q,f){c.hasOwnProperty(l)||(c[l]=f.apply(null,q))}c=c?c._modules:{};l(c,"modules/timeline.src.js",[c["parts/Globals.js"],c["parts/Point.js"],c["mixins/legend-symbol.js"],c["parts/Utilities.js"]],function(c, +l,q,f){var p=f.addEvent,w=f.arrayMax,x=f.arrayMin,t=f.defined,y=f.isNumber,r=f.merge,z=f.objectEach,n=f.pick;f=f.seriesType;var m=c.Series,u=c.seriesTypes;f("timeline","line",{colorByPoint:!0,stickyTracking:!1,ignoreHiddenPoint:!0,legendType:"point",lineWidth:4,tooltip:{headerFormat:'\u25cf {point.key}
    ',pointFormat:"{point.description}"},states:{hover:{lineWidthPlus:0}},dataLabels:{enabled:!0,allowOverlap:!0,alternate:!0, +backgroundColor:"#ffffff",borderWidth:1,borderColor:"#999999",borderRadius:3,color:"#333333",connectorWidth:1,distance:100,formatter:function(){var a=this.series.chart.styledMode?"\u25cf ":'\u25cf ';return a+=''+(this.key||"")+"
    "+(this.point.label||"")},style:{textOutline:"none",fontWeight:"normal",fontSize:"12px"},shadow:!1,verticalAlign:"middle"},marker:{enabledThreshold:0,symbol:"square",radius:6, +lineWidth:2,height:15},showInLegend:!1,colorKey:"x"},{trackerGroups:["markerGroup","dataLabelsGroup"],drawLegendSymbol:q.drawRectangle,drawTracker:c.TrackerMixin.drawTrackerPoint,init:function(){var a=this;m.prototype.init.apply(a,arguments);p(a,"afterTranslate",function(){var b,k=Number.MAX_VALUE;a.points.forEach(function(a){a.isInside=a.isInside&&a.visible;a.visible&&!a.isNull&&(t(b)&&(k=Math.min(k,Math.abs(a.plotX-b))),b=a.plotX)});a.closestPointRangePx=k});p(a,"drawDataLabels",function(){a.distributeDL()}); +p(a,"afterDrawDataLabels",function(){var b;a.points.forEach(function(a){if(b=a.dataLabel)return b.animate=function(a){this.targetPosition&&(this.targetPosition=a);return c.SVGElement.prototype.animate.apply(this,arguments)},b.targetPosition||(b.targetPosition={}),a.drawConnector()})});p(a.chart,"afterHideOverlappingLabel",function(){a.points.forEach(function(a){a.connector&&a.dataLabel&&a.dataLabel.oldOpacity!==a.dataLabel.newOpacity&&a.alignConnector()})})},alignDataLabel:function(a,b,k,c){var d= +this.chart.inverted,g=this.visibilityMap.filter(function(a){return a}),e=this.visiblePointsCount,h=g.indexOf(a);g=this.options.dataLabels;var v=a.userDLOptions||{};h=g.alternate?h&&h!==e-1?2:1.5:1;e=Math.floor(this.xAxis.len/e);var f=b.padding;if(a.visible){var l=Math.abs(v.x||a.options.dataLabels.x);d?(d=2*(l-f)-a.itemHeight/2,d={width:d+"px",textOverflow:b.width/d*b.height/2>e*h?"ellipsis":"none"}):d={width:(v.width||g.width||e*h-2*f)+"px"};b.css(d);this.chart.styledMode||b.shadow(g.shadow)}m.prototype.alignDataLabel.apply(this, +arguments)},processData:function(){var a=0,b;this.visibilityMap=this.getVisibilityMap();this.visibilityMap.forEach(function(b){b&&a++});this.visiblePointsCount=a;for(b=0;b\u25CF ' + + ' {point.key}
    ', + pointFormat: '{point.description}' + }, + states: { + hover: { + lineWidthPlus: 0 + } + }, + /** + * @declare Highcharts.TimelineDataLabelsOptionsObject + * + * @private + */ + dataLabels: { + enabled: true, + allowOverlap: true, + /** + * Whether to position data labels alternately. For example, if + * [distance](#plotOptions.timeline.dataLabels.distance) + * is set equal to `100`, then data labels will be positioned + * alternately (on both sides of the point) at a distance of 100px. + * + * @sample {highcharts} highcharts/series-timeline/alternate-disabled + * Alternate disabled + */ + alternate: true, + backgroundColor: '#ffffff', + borderWidth: 1, + borderColor: '#999999', + borderRadius: 3, + color: '#333333', + /** + * The color of the line connecting the data label to the point. + * The default color is the same as the point's color. + * + * In styled mode, the connector stroke is given in the + * `.highcharts-data-label-connector` class. + * + * @sample {highcharts} highcharts/series-timeline/connector-styles + * Custom connector width and color + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @apioption plotOptions.timeline.dataLabels.connectorColor + */ + /** + * The width of the line connecting the data label to the point. + * + * In styled mode, the connector stroke width is given in the + * `.highcharts-data-label-connector` class. + * + * @sample {highcharts} highcharts/series-timeline/connector-styles + * Custom connector width and color + */ + connectorWidth: 1, + /** + * A pixel value defining the distance between the data label and + * the point. Negative numbers puts the label on top of the point. + */ + distance: 100, + // eslint-disable-next-line valid-jsdoc + /** + * @type {Highcharts.TimelineDataLabelsFormatterCallbackFunction} + * @default function () { + * var format; + * + * if (!this.series.chart.styledMode) { + * format = ''; + * } else { + * format = ''; + * } + * format += '' + (this.key || '') + '
    ' + + * (this.point.label || ''); + * return format; + * } + */ + formatter: function () { + var format; + if (!this.series.chart.styledMode) { + format = ''; + } + else { + format = ''; + } + format += '' + + (this.key || '') + '
    ' + + (this.point.label || ''); + return format; + }, + style: { + /** @internal */ + textOutline: 'none', + /** @internal */ + fontWeight: 'normal', + /** @internal */ + fontSize: '12px' + }, + /** + * Shadow options for the data label. + * + * @type {boolean|Highcharts.CSSObject} + */ + shadow: false, + /** + * @type {number} + * @apioption plotOptions.timeline.dataLabels.width + */ + verticalAlign: 'middle' + }, + marker: { + enabledThreshold: 0, + symbol: 'square', + radius: 6, + lineWidth: 2, + height: 15 + }, + showInLegend: false, + colorKey: 'x' + }, + /** + * @lends Highcharts.Series# + */ + { + trackerGroups: ['markerGroup', 'dataLabelsGroup'], + // Use a simple symbol from LegendSymbolMixin + drawLegendSymbol: LegendSymbolMixin.drawRectangle, + // Use a group of trackers from TrackerMixin + drawTracker: TrackerMixin.drawTrackerPoint, + init: function () { + var series = this; + Series.prototype.init.apply(series, arguments); + addEvent(series, 'afterTranslate', function () { + var lastPlotX, closestPointRangePx = Number.MAX_VALUE; + series.points.forEach(function (point) { + // Set the isInside parameter basing also on the real point + // visibility, in order to avoid showing hidden points + // in drawPoints method. + point.isInside = point.isInside && point.visible; + // New way of calculating closestPointRangePx value, which + // respects the real point visibility is needed. + if (point.visible && !point.isNull) { + if (defined(lastPlotX)) { + closestPointRangePx = Math.min(closestPointRangePx, Math.abs(point.plotX - lastPlotX)); + } + lastPlotX = point.plotX; + } + }); + series.closestPointRangePx = closestPointRangePx; + }); + // Distribute data labels before rendering them. Distribution is + // based on the 'dataLabels.distance' and 'dataLabels.alternate' + // property. + addEvent(series, 'drawDataLabels', function () { + // Distribute data labels basing on defined algorithm. + series.distributeDL(); // @todo use this scope for series + }); + addEvent(series, 'afterDrawDataLabels', function () { + var dataLabel; // @todo use this scope for series + // Draw or align connector for each point. + series.points.forEach(function (point) { + dataLabel = point.dataLabel; + if (dataLabel) { + // Within this wrap method is necessary to save the + // current animation params, because the data label + // target position (after animation) is needed to align + // connectors. + dataLabel.animate = function (params) { + if (this.targetPosition) { + this.targetPosition = params; + } + return H.SVGElement.prototype.animate.apply(this, arguments); + }; + // Initialize the targetPosition field within data label + // object. It's necessary because there is need to know + // expected position of specific data label, when + // aligning connectors. This field is overrided inside + // of SVGElement.animate() wrapped method. + if (!dataLabel.targetPosition) { + dataLabel.targetPosition = {}; + } + return point.drawConnector(); + } + }); + }); + addEvent(series.chart, 'afterHideOverlappingLabel', function () { + series.points.forEach(function (p) { + if (p.connector && + p.dataLabel && + p.dataLabel.oldOpacity !== p.dataLabel.newOpacity) { + p.alignConnector(); + } + }); + }); + }, + alignDataLabel: function (point, dataLabel, options, alignTo) { + var series = this, isInverted = series.chart.inverted, visiblePoints = series.visibilityMap.filter(function (point) { + return point; + }), visiblePointsCount = series.visiblePointsCount, pointIndex = visiblePoints.indexOf(point), isFirstOrLast = (!pointIndex || pointIndex === visiblePointsCount - 1), dataLabelsOptions = series.options.dataLabels, userDLOptions = point.userDLOptions || {}, + // Define multiplier which is used to calculate data label + // width. If data labels are alternate, they have two times more + // space to adapt (excepting first and last ones, which has only + // one and half), than in case of placing all data labels side + // by side. + multiplier = dataLabelsOptions.alternate ? + (isFirstOrLast ? 1.5 : 2) : + 1, distance, availableSpace = Math.floor(series.xAxis.len / visiblePointsCount), pad = dataLabel.padding, targetDLWidth, styles; + // Adjust data label width to the currently available space. + if (point.visible) { + distance = Math.abs(userDLOptions.x || point.options.dataLabels.x); + if (isInverted) { + targetDLWidth = ((distance - pad) * 2 - (point.itemHeight / 2)); + styles = { + width: targetDLWidth + 'px', + // Apply ellipsis when data label height is exceeded. + textOverflow: dataLabel.width / targetDLWidth * + dataLabel.height / 2 > availableSpace * multiplier ? + 'ellipsis' : 'none' + }; + } + else { + styles = { + width: (userDLOptions.width || + dataLabelsOptions.width || + availableSpace * multiplier - (pad * 2)) + 'px' + }; + } + dataLabel.css(styles); + if (!series.chart.styledMode) { + dataLabel.shadow(dataLabelsOptions.shadow); + } + } + Series.prototype.alignDataLabel.apply(series, arguments); + }, + processData: function () { + var series = this, visiblePoints = 0, i; + series.visibilityMap = series.getVisibilityMap(); + // Calculate currently visible points. + series.visibilityMap.forEach(function (point) { + if (point) { + visiblePoints++; + } + }); + series.visiblePointsCount = visiblePoints; + for (i = 0; i < series.xData.length; i++) { + series.yData[i] = 1; + } + Series.prototype.processData.call(this, arguments); + return; + }, + getXExtremes: function (xData) { + var series = this, filteredData = xData.filter(function (x, i) { + return series.points[i].isValid() && + series.points[i].visible; + }); + return { + min: arrayMin(filteredData), + max: arrayMax(filteredData) + }; + }, + generatePoints: function () { + var series = this; + Series.prototype.generatePoints.apply(series); + series.points.forEach(function (point, i) { + point.applyOptions({ + x: series.xData[i] + }, series.xData[i]); + }); + }, + getVisibilityMap: function () { + var series = this, map = (series.data.length ? + series.data : series.userOptions.data).map(function (point) { + return (point && + point.visible !== false && + !point.isNull) ? point : false; + }); + return map; + }, + distributeDL: function () { + var series = this, dataLabelsOptions = series.options.dataLabels, options, pointDLOptions, newOptions = {}, visibilityIndex = 1, distance = dataLabelsOptions.distance; + series.points.forEach(function (point) { + if (point.visible && !point.isNull) { + options = point.options; + pointDLOptions = point.options.dataLabels; + if (!series.hasRendered) { + point.userDLOptions = + merge({}, pointDLOptions); + } + newOptions[series.chart.inverted ? 'x' : 'y'] = + dataLabelsOptions.alternate && visibilityIndex % 2 ? + -distance : distance; + options.dataLabels = merge(newOptions, point.userDLOptions); + visibilityIndex++; + } + }); + }, + markerAttribs: function (point, state) { + var series = this, seriesMarkerOptions = series.options.marker, seriesStateOptions, pointMarkerOptions = point.marker || {}, symbol = (pointMarkerOptions.symbol || seriesMarkerOptions.symbol), pointStateOptions, width = pick(pointMarkerOptions.width, seriesMarkerOptions.width, series.closestPointRangePx), height = pick(pointMarkerOptions.height, seriesMarkerOptions.height), radius = 0, attribs; + // Call default markerAttribs method, when the xAxis type + // is set to datetime. + if (series.xAxis.dateTime) { + return seriesTypes.line.prototype.markerAttribs + .call(this, point, state); + } + // Handle hover and select states + if (state) { + seriesStateOptions = + seriesMarkerOptions.states[state] || {}; + pointStateOptions = pointMarkerOptions.states && + pointMarkerOptions.states[state] || {}; + radius = pick(pointStateOptions.radius, seriesStateOptions.radius, radius + (seriesStateOptions.radiusPlus || 0)); + } + point.hasImage = (symbol && symbol.indexOf('url') === 0); + attribs = { + x: Math.floor(point.plotX) - (width / 2) - (radius / 2), + y: point.plotY - (height / 2) - (radius / 2), + width: width + radius, + height: height + radius + }; + return attribs; + }, + bindAxes: function () { + var series = this; + Series.prototype.bindAxes.call(series); + ['xAxis', 'yAxis'].forEach(function (axis) { + // Initially set the linked xAxis type to category. + if (axis === 'xAxis' && !series[axis].userOptions.type) { + series[axis].categories = series[axis].hasNames = true; + } + }); + } + }, + /** + * @lends Highcharts.Point# + */ + { + init: function () { + var point = Point.prototype.init.apply(this, arguments); + point.name = pick(point.name, 'Event'); + point.y = 1; + return point; + }, + isValid: function () { + return this.options.y !== null; + }, + setVisible: function (vis, redraw) { + var point = this, series = point.series; + redraw = pick(redraw, series.options.ignoreHiddenPoint); + seriesTypes.pie.prototype.pointClass.prototype + .setVisible.call(point, vis, false); + // Process new data + series.processData(); + if (redraw) { + series.chart.redraw(); + } + }, + setState: function () { + var proceed = Series.prototype.pointClass.prototype.setState; + // Prevent triggering the setState method on null points. + if (!this.isNull) { + proceed.apply(this, arguments); + } + }, + getConnectorPath: function () { + var point = this, chart = point.series.chart, xAxisLen = point.series.xAxis.len, inverted = chart.inverted, direction = inverted ? 'x2' : 'y2', dl = point.dataLabel, targetDLPos = dl.targetPosition, coords = { + x1: point.plotX, + y1: point.plotY, + x2: point.plotX, + y2: isNumber(targetDLPos.y) ? targetDLPos.y : dl.y + }, negativeDistance = ((dl.alignAttr || dl)[direction[0]] < + point.series.yAxis.len / 2), path; + // Recalculate coords when the chart is inverted. + if (inverted) { + coords = { + x1: point.plotY, + y1: xAxisLen - point.plotX, + x2: targetDLPos.x || dl.x, + y2: xAxisLen - point.plotX + }; + } + // Subtract data label width or height from expected coordinate so + // that the connector would start from the appropriate edge. + if (negativeDistance) { + coords[direction] += dl[inverted ? 'width' : 'height']; + } + // Change coordinates so that they will be relative to data label. + objectEach(coords, function (_coord, i) { + coords[i] -= (dl.alignAttr || dl)[i[0]]; + }); + path = chart.renderer.crispLine([ + ['M', coords.x1, coords.y1], + ['L', coords.x2, coords.y2] + ], dl.options.connectorWidth); + return path; + }, + drawConnector: function () { + var point = this, series = point.series; + if (!point.connector) { + point.connector = series.chart.renderer + .path(point.getConnectorPath()) + .attr({ + zIndex: -1 + }) + .add(point.dataLabel); + } + if (point.series.chart.isInsidePlot(// #10507 + point.dataLabel.x, point.dataLabel.y)) { + point.alignConnector(); + } + }, + alignConnector: function () { + var point = this, series = point.series, connector = point.connector, dl = point.dataLabel, dlOptions = point.dataLabel.options = merge(series.options.dataLabels, point.options.dataLabels), chart = point.series.chart, bBox = connector.getBBox(), plotPos = { + x: bBox.x + dl.translateX, + y: bBox.y + dl.translateY + }, isVisible; + // Include a half of connector width in order to run animation, + // when connectors are aligned to the plot area edge. + if (chart.inverted) { + plotPos.y -= dl.options.connectorWidth / 2; + } + else { + plotPos.x += dl.options.connectorWidth / 2; + } + isVisible = chart.isInsidePlot(plotPos.x, plotPos.y); + connector[isVisible ? 'animate' : 'attr']({ + d: point.getConnectorPath() + }); + if (!series.chart.styledMode) { + connector.attr({ + stroke: dlOptions.connectorColor || point.color, + 'stroke-width': dlOptions.connectorWidth, + opacity: dl[defined(dl.newOpacity) ? 'newOpacity' : 'opacity'] + }); + } + } + }); + /** + * The `timeline` series. If the [type](#series.timeline.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.timeline + * @excluding animationLimit, boostThreshold, connectEnds, connectNulls, + * cropThreshold, dashStyle, dataParser, dataURL, findNearestPointBy, + * getExtremesFromAll, lineWidth, negativeColor, + * pointInterval, pointIntervalUnit, pointPlacement, pointStart, + * softThreshold, stacking, stack, step, threshold, turboThreshold, + * zoneAxis, zones, dataSorting + * @product highcharts + * @requires modules/timeline + * @apioption series.timeline + */ + /** + * An array of data points for the series. For the `timeline` series type, + * points can be given with three general parameters, `name`, `label`, + * and `description`: + * + * Example: + * + * ```js + * series: [{ + * type: 'timeline', + * data: [{ + * name: 'Jan 2018', + * label: 'Some event label', + * description: 'Description to show in tooltip' + * }] + * }] + * ``` + * If all points additionally have the `x` values, and xAxis type is set to + * `datetime`, then events are laid out on a true time axis, where their + * placement reflects the actual time between them. + * + * @sample {highcharts} highcharts/series-timeline/alternate-labels + * Alternate labels + * @sample {highcharts} highcharts/series-timeline/datetime-axis + * Real time intervals + * + * @type {Array<*>} + * @extends series.line.data + * @excluding marker, y + * @product highcharts + * @apioption series.timeline.data + */ + /** + * The name of event. + * + * @type {string} + * @product highcharts + * @apioption series.timeline.data.name + */ + /** + * The label of event. + * + * @type {string} + * @product highcharts + * @apioption series.timeline.data.label + */ + /** + * The description of event. This description will be shown in tooltip. + * + * @type {string} + * @product highcharts + * @apioption series.timeline.data.description + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'masters/modules/timeline.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/treegrid.js b/librerias/gantt/code/modules/treegrid.js new file mode 100644 index 0000000..be71c0d --- /dev/null +++ b/librerias/gantt/code/modules/treegrid.js @@ -0,0 +1,61 @@ +/* + Highcharts Gantt JS v8.1.0 (2020-05-05) + + Tree Grid + + (c) 2016-2019 Jon Arild Nygard + + License: www.highcharts.com/license +*/ +(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/treegrid",["highcharts"],function(E){b(E);b.Highcharts=E;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function E(b,r,y,t){b.hasOwnProperty(r)||(b[r]=t.apply(null,y))}b=b?b._modules:{};E(b,"parts-gantt/Tree.js",[b["parts/Utilities.js"]],function(b){var r=b.extend,y=b.isNumber,t=b.pick,k=function(b,g){var n=b.reduce(function(d, +u){var n=t(u.parent,"");"undefined"===typeof d[n]&&(d[n]=[]);d[n].push(u);return d},{});Object.keys(n).forEach(function(d,u){var b=n[d];""!==d&&-1===g.indexOf(d)&&(b.forEach(function(d){u[""].push(d)}),delete u[d])});return n},g=function(b,k,n,d,u,z){var A=0,m=0,v=z&&z.after,e=z&&z.before;k={data:d,depth:n-1,id:b,level:n,parent:k};var c,h;"function"===typeof e&&e(k,z);e=(u[b]||[]).map(function(e){var a=g(e.id,b,n+1,e,u,z),f=e.start;e=!0===e.milestone?f:e.end;c=!y(c)||fh?e:h;A=A+ +1+a.descendants;m=Math.max(a.height+1,m);return a});d&&(d.start=t(d.start,c),d.end=t(d.end,h));r(k,{children:e,descendants:A,height:m});"function"===typeof v&&v(k,z);return k};return{getListOfParents:k,getNode:g,getTree:function(b,r){var n=b.map(function(d){return d.id});b=k(b,n);return g("",null,1,null,b,r)}}});E(b,"parts-gantt/TreeGridTick.js",[b["parts/Utilities.js"]],function(b){var r=b.addEvent,y=b.defined,t=b.isObject,k=b.isNumber,g=b.pick,B=b.wrap,C;(function(b){function d(){this.treeGrid|| +(this.treeGrid=new v(this))}function n(e,c){e=e.treeGrid;var h=!e.labelIcon,p=c.renderer,a=c.xy,f=c.options,l=f.width,D=f.height,G=a.x-l/2-f.padding;a=a.y-D/2;var d=c.collapsed?90:180,b=c.show&&k(a),w=e.labelIcon;w||(e.labelIcon=w=p.path(p.symbols[f.type](f.x,f.y,l,D)).addClass("highcharts-label-icon").add(c.group));b||w.attr({y:-9999});p.styledMode||w.attr({"stroke-width":1,fill:g(c.color,"#666666")}).css({cursor:"pointer",stroke:f.lineColor,strokeWidth:f.lineWidth});w[h?"attr":"animate"]({translateX:G, +translateY:a,rotation:d})}function z(e,c,h,p,a,f,l,D,G){var d=g(this.options&&this.options.labels,f);f=this.pos;var b=this.axis,w="treegrid"===b.options.type;e=e.apply(this,[c,h,p,a,d,l,D,G]);w&&(c=d&&t(d.symbol,!0)?d.symbol:{},d=d&&k(d.indentation)?d.indentation:0,f=(f=(b=b.treeGrid.mapOfPosToGridNode)&&b[f])&&f.depth||1,e.x+=c.width+2*c.padding+(f-1)*d);return e}function A(e){var c=this,h=c.pos,d=c.axis,a=c.label,f=d.treeGrid.mapOfPosToGridNode,l=d.options,D=g(c.options&&c.options.labels,l&&l.labels), +G=D&&t(D.symbol,!0)?D.symbol:{},b=(f=f&&f[h])&&f.depth;l="treegrid"===l.type;var m=-1h&&!a.startOnTick&&(e[0]=h),d>m&&d-q=c?(d-c)%e:e-(c-d)%e;return b.inclusive? +d<=h:d=b)break;else c.to=b)break;else if(k.isInBreak(h,b)){e-=b-h.from;break}}return e};k.prototype.findBreakAt=function(b,d){return g(d,function(d){return d.from< +b&&bm;)x-=g;for(;xb.to||h>b.from&&kb.from&&kb.from&&k>b.to&&kc&&b>=this.basePointRange&&(c=b),e=void 0;a--;)e&&!1!==e.visible||(e=d[a+1]),b=d[a],!1!==e.visible&&!1!==b.visible&&(e.x-b.x>c&&(e=(b.x+e.x)/2,d.splice(a+1,0,{isNull:!0,x:e}),f.stacking&&this.options.stacking&&(e=f.stacking.stacks[this.stackKey][e]=new t(f,f.options.stackLabels,!1,e,this.stack),e.total=0)),e=b);return this.getGraphPath(d)};k(b,"init",function(){this.brokenAxis||(this.brokenAxis=new z(this))}); +k(b,"afterInit",function(){"undefined"!==typeof this.brokenAxis&&this.brokenAxis.setBreaks(this.options.breaks,!1)});k(b,"afterSetTickPositions",function(){var c=this.brokenAxis;if(c&&c.hasBreaks){var b=this.tickPositions,e=this.tickPositions.info,a=[],d;for(d=0;d=c&&(b-=.5);return{from:b,to:a,showPoints:!1}}function e(a,b,c){var e=[],d=[],f={},g={},h=-1,q="boolean"===typeof b?b:!1;a=y.getTree(a,{after:function(a){a=g[a.pos];var b= +0,c=0;a.children.forEach(function(a){c+=(a.descendants||0)+1;b=Math.max((a.height||0)+1,b)});a.descendants=c;a.height=b;a.collapsed&&d.push(a)},before:function(a){var b=u(a.data,!0)?a.data:{},c=z(b.name)?b.name:"",d=f[a.parent];d=u(d,!0)?g[d.pos]:null;var k=function(a){return a.name===c},l;q&&u(d,!0)&&(l=C(d.children,k))?(k=l.pos,l.nodes.push(a)):k=h++;g[k]||(g[k]=l={depth:d?d.depth+1:0,name:c,nodes:[a],children:[],pos:k},-1!==k&&e.push(c),u(d,!0)&&d.children.push(l));z(a.id)&&(f[a.id]=a);l&&!0=== +b.collapsed&&(l.collapsed=!0);a.pos=k}});g=function(a,b){var c=function(a,d,e){var f=d+(-1===d?0:b-1),g=(f-d)/2,h=d+g;a.nodes.forEach(function(a){var b=a.data;u(b,!0)&&(b.y=d+(b.seriesIndex||0),delete b.seriesIndex);a.pos=h});e[h]=a;a.pos=h;a.tickmarkOffset=g+.5;a.collapseStart=f+.5;a.children.forEach(function(a){c(a,f+1,e);f=(a.collapseEnd||0)-.5});a.collapseEnd=f+.5;return e};return c(a["-1"],-1,{})}(g,c);return{categories:e,mapOfIdToNode:f,mapOfPosToGridNode:g,collapsedNodes:d,tree:a}}function a(a){a.target.axes.filter(function(a){return"treegrid"=== +a.options.type}).forEach(function(b){var c=b.options||{},d=c.labels,f=c.uniqueNames,g=0;if(!b.treeGrid.mapOfPosToGridNode||b.series.some(function(a){return!a.hasRendered||a.isDirtyData||a.isDirty}))c=b.series.reduce(function(a,b){b.visible&&((b.options.data||[]).forEach(function(b){u(b,!0)&&(b.seriesIndex=g,a.push(b))}),!0===f&&g++);return a},[]),c=e(c,f||!1,!0===f?g:1),b.categories=c.categories,b.treeGrid.mapOfPosToGridNode=c.mapOfPosToGridNode,b.hasNames=!0,b.treeGrid.tree=c.tree,b.series.forEach(function(a){var b= +(a.options.data||[]).map(function(a){return u(a,!0)?A(a):a});a.visible&&a.setData(b,!1)}),b.treeGrid.mapOptionsToLevel=k.getLevelOptions({defaults:d,from:1,levels:d&&d.levels,to:b.treeGrid.tree&&b.treeGrid.tree.height}),"beforeRender"===a.type&&(b.treeGrid.collapsedNodes=c.collapsedNodes)})}function f(a,b){var c=this.treeGrid.mapOptionsToLevel||{},d=this.ticks,e=d[b],f;if("treegrid"===this.options.type&&this.treeGrid.mapOfPosToGridNode){var g=this.treeGrid.mapOfPosToGridNode[b];(c=c[g.depth])&&(f= +{labels:c});e?(e.parameters.category=g.name,e.options=f,e.addLabel()):d[b]=new r(this,b,void 0,void 0,{category:g.name,tickmarkOffset:g.tickmarkOffset,options:f})}else a.apply(this,Array.prototype.slice.call(arguments,1))}function g(a){var b=this.options;b=(b=b&&b.labels)&&d(b.indentation)?b.indentation:0;var c=a.apply(this,Array.prototype.slice.call(arguments,1));if("treegrid"===this.options.type&&this.treeGrid.mapOfPosToGridNode){var e=this.treeGrid.mapOfPosToGridNode[-1].height||0;c.width+=b*(e- +1)}return c}function D(b,c,d){var f=this,g="treegrid"===d.type;f.treeGrid||(f.treeGrid=new I(f));g&&(B(c,"beforeRender",a),B(c,"beforeRedraw",a),B(c,"addSeries",function(a){a.options.data&&(a=e(a.options.data,d.uniqueNames||!1,1),f.treeGrid.collapsedNodes=(f.treeGrid.collapsedNodes||[]).concat(a.collapsedNodes))}),B(f,"foundExtremes",function(){f.treeGrid.collapsedNodes&&f.treeGrid.collapsedNodes.forEach(function(a){var b=f.treeGrid.collapse(a);f.brokenAxis&&(f.brokenAxis.setBreaks(b,!1),f.treeGrid.collapsedNodes&& +(f.treeGrid.collapsedNodes=f.treeGrid.collapsedNodes.filter(function(b){return a.collapseStart!==b.collapseStart||a.collapseEnd!==b.collapseEnd})))})}),d=A({grid:{enabled:!0},labels:{align:"left",levels:[{level:void 0},{level:1,style:{fontWeight:"bold"}}],symbol:{type:"triangle",x:-5,y:-5,height:10,width:10,padding:5}},uniqueNames:!1},d,{reversed:!0,grid:{columns:void 0}}));b.apply(f,[c,d]);g&&(f.hasNames=!0,f.options.showLastLabel=!0)}function E(a){var b=this.options;"treegrid"===b.type?(this.min= +m(this.userMin,b.min,this.dataMin),this.max=m(this.userMax,b.max,this.dataMax),n(this,"foundExtremes"),this.setAxisTranslation(!0),this.tickmarkOffset=.5,this.tickInterval=1,this.tickPositions=this.treeGrid.mapOfPosToGridNode?this.treeGrid.getTickPositions():[]):a.apply(this,Array.prototype.slice.call(arguments,1))}var H=!1;c.compose=function(a){H||(v(a.prototype,"generateTick",f),v(a.prototype,"getMaxLabelDimensions",g),v(a.prototype,"init",D),v(a.prototype,"setTickInterval",E),t.compose(r),H=!0)}; +var I=function(){function a(a){this.axis=a}a.prototype.collapse=function(a){var c=this.axis,d=c.options.breaks||[];a=b(a,c.max);d.push(a);return d};a.prototype.expand=function(a){var c=this.axis,d=c.options.breaks||[],e=b(a,c.max);return d.reduce(function(a,b){b.to===e.to&&b.from===e.from||a.push(b);return a},[])};a.prototype.getTickPositions=function(){var a=this.axis;return Object.keys(a.treeGrid.mapOfPosToGridNode||{}).reduce(function(b,c){c=+c;!(a.min<=c&&a.max>=c)||a.brokenAxis&&a.brokenAxis.isInAnyBreak(c)|| +b.push(c);return b},[])};a.prototype.isCollapsed=function(a){var c=this.axis,d=c.options.breaks||[],e=b(a,c.max);return d.some(function(a){return a.from===e.from&&a.to===e.to})};a.prototype.toggleCollapse=function(a){return this.isCollapsed(a)?this.expand(a):this.collapse(a)};return a}();c.Additions=I})(e||(e={}));b.prototype.utils={getNode:y.getNode};e.compose(b);return e});E(b,"masters/modules/treegrid.src.js",[],function(){})}); +//# sourceMappingURL=treegrid.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/treegrid.js.map b/librerias/gantt/code/modules/treegrid.js.map new file mode 100644 index 0000000..390bcc1 --- /dev/null +++ b/librerias/gantt/code/modules/treegrid.js.map @@ -0,0 +1 @@ +{"version":3,"file":"treegrid.js.map","lineCount":60,"mappings":"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","sources":["treegrid.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","U","extend","isNumber","pick","getListOfParents","data","ids","listOfParents","reduce","prev","curr","parent","push","Object","keys","parents","forEach","list","children","indexOf","child","getNode","id","level","mapOfIdToChildren","options","descendants","height","after","before","node","depth","start","end","map","childStart","childEnd","milestone","Math","max","Tree","getTree","d","addEvent","defined","isObject","wrap","TreeGridTick","onInit","tick","treeGrid","Additions","renderLabelIcon","params","isNew","labelIcon","renderer","labelBox","xy","width","x","padding","y","rotation","collapsed","shouldRender","show","icon","symbols","type","addClass","add","group","attr","styledMode","color","css","cursor","stroke","lineColor","strokeWidth","lineWidth","translateX","translateY","wrapGetLabelPosition","proceed","label","horiz","labelOptions","tickmarkOffset","index","step","lbOptions","labels","pos","axis","isTreeGrid","result","symbolOptions","symbol","indentation","mapOfPosToGridNode","wrapRenderLabel","tickPositions","chart","element","Array","prototype","slice","call","arguments","isCollapsed","styles","parentGroup","removeClassName","prefixClassName","removeClass","object","attachedTreeGridEvents","textDecoration","style","toggleCollapse","applied","compose","TickClass","collapse","TickClass.prototype.collapse","redraw","expand","TickClass.prototype.expand","TickClass.prototype.toggleCollapse","Additions.prototype.collapse","brokenAxis","breaks","setBreaks","Additions.prototype.expand","Additions.prototype.toggleCollapse","Color","isArray","merge","getColor","mapOptionsToLevel","parentColor","parentColorIndex","series","colors","siblings","points","chartOptionsChart","point","i","getColorByPoint","colorByPoint","colorIndexByPoint","length","colorCount","colorVariation","key","parse","brighten","to","get","colorIndex","getLevelOptions","from","levels","converted","defaults","item","levelIsConstant","setTreeValues","tree","idRoot","nodeRoot","mapIdToNode","optionsPoint","childrenTotal","levelDynamic","name","visible","newOptions","val","value","isLeaf","updateRootId","rootId","rootNode","userOptions","Axis","H","Tick","erase","find","timeUnits","dateFormat","Chart","applyGridOptions","align","categories","showLastLabel","labelRotation","getMaxLabelDimensions","Axis.prototype.getMaxLabelDimensions","ticks","dimensions","tickHeight","getBBox","textStr","textPxLength","tickWidth","round","dateFormats","W","H.dateFormats.W","timestamp","Date","firstDay","thursday","valueOf","set","firstThursday","toString","floor","E","H.dateFormats.E","charAt","axes","grid","columns","column","setAxisSize","setAxisTranslation","e","reversed","gridOptions","labelOpts","side","GridAxis","Side","tickPos","nextTickPos","tickSize","crispCorr","enabled","bottom","top","offset","chartHeight","len","translate","left","chartWidth","right","slotWidth","lblMetrics","fontMetrics","fontSize","labelHeight","useHTML","b","lines","h","f","GridAxisAdditions","isOuterAxis","GridAxisAdditions.prototype.isOuterAxis","columnIndex","linkedParent","parentAxis","thisIndex","lastIndex","coll","otherAxis","isInternal","GridAxis.compose","AxisClass","keepProps","wrapUnsquish","onAfterGetOffset","onAfterGetTitlePosition","onAfterInit","onAfterRender","onAfterSetAxisTranslation","onAfterSetOptions","onAfterSetOptions2","onAfterSetScale","onAfterTickSize","onTrimTicks","onDestroy","GridAxis.onAfterGetOffset","getOffset","GridAxis.onAfterGetTitlePosition","title","axisTitle","axisHeight","axisLeft","opposite","_a","axisTitleOptions","axisTop","axisWidth","titleWidth","xOption","yOption","titleMargin","margin","titleFontSize","offAxis","titlePosition","GridAxis.onAfterInit","isLinked","isFirst","isLast","p","isXAxis","columnOptions","linkedTo","isColumn","GridAxis.onAfterRender","maxLabelDimensions","rightWall","destroy","axisLine","linePath","getLinePath","startPoint","endPoint","distance","tickLength","axisLineExtra","animate","zIndex","axisGroup","showAxis","render","GridAxis.onAfterSetAxisTranslation","tickInfo","info","userLabels","pointRange","dateTimeLabelFormats","unitName","range","count","GridAxis.onAfterSetOptions","gridAxisOptions","className","hour","day","week","month","borderWidth","text","reserveSpace","units","tickPixelInterval","tickPositioner","tickInterval","gridAxisOptions.tickPositioner","min","parentInfo","unitIdx","unitRange","getTimeTicks","startOfWeek","minPadding","maxPadding","GridAxis.onAfterSetOptions2","GridAxis.onAfterSetScale","setScale","GridAxis.onAfterTickSize","defaultLeftAxisOptions","_b","labelPadding","abs","cellHeight","GridAxis.onDestroy","keepEvents","GridAxis.onInit","borderColor","tickColor","GridAxis.onTrimTicks","categoryAxis","firstPos","lastPos","startOnTick","endOnTick","GridAxis.wrapUnsquish","StackItem","fireEvent","Series","BrokenAxisAdditions","hasBreaks","isInBreak","BrokenAxisAdditions.isInBreak","brk","repeat","Infinity","test","inclusive","ret","lin2Val","BrokenAxisAdditions.lin2Val","breakArray","nval","val2Lin","BrokenAxisAdditions.val2Lin","findBreakAt","BrokenAxisAdditions.prototype.findBreakAt","isInAnyBreak","BrokenAxisAdditions.prototype.isInAnyBreak","testKeep","keep","inbrk","showPoints","BrokenAxisAdditions.prototype.setBreaks","isDirty","forceRedraw","val2lin","lin2val","ordinal","setExtremes","axis.setExtremes","newMin","newMax","animation","eventArguments","axisBreak","axis.setAxisTranslation","saveOld","unitLength","breakArrayT","userMin","userMax","pointRangePadding","move","size","breakSize","sort","a","inBrk","staticScale","transA","minPixelPadding","minPointOffset","BrokenAxis","BrokenAxis.compose","SeriesClass","seriesProto","drawBreaks","seriesProto.drawBreaks","threshold","eventName","brokenAxis_1","toUpperCase","gappedPath","seriesProto.gappedPath","currentDataGrouping","groupingSize","gapSize","yAxis","stack","next","gapUnit","basePointRange","current","xRange","splice","isNull","stacking","stacks","stackKey","stackLabels","total","getGraphPath","newPositions","connectNulls","xAxis","isPointInBreak","drawPointsWrapped","pointArrayMap","TreeSeriesMixin","isString","TreeGridAxis","getBreakFromNode","collapseStart","collapseEnd","getTreeGridFromData","uniqueNames","numberOfSeries","collapsedNodes","mapOfIdToNode","posIterator","uniqueNamesEnabled","treeParams","gridNode","parentNode","parentGridNode","hasSameName","nodes","updateYValuesAndTickPos","setValues","diff","seriesIndex","onBeforeRender","target","filter","some","hasRendered","isDirtyData","arr","s","hasNames","setData","wrapGenerateTick","levelOptions","parameters","category","addLabel","wrapGetMaxLabelDimensions","retVal","treeDepth","wrapInit","concat","n","fontWeight","wrapSetTickInterval","dataMin","dataMax","getTickPositions","Additions.prototype.getTickPositions","Additions.prototype.isCollapsed","utils"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/treegrid.src.js b/librerias/gantt/code/modules/treegrid.src.js new file mode 100644 index 0000000..01354e8 --- /dev/null +++ b/librerias/gantt/code/modules/treegrid.src.js @@ -0,0 +1,2660 @@ +/** + * @license Highcharts Gantt JS v8.1.0 (2020-05-05) + * + * Tree Grid + * + * (c) 2016-2019 Jon Arild Nygard + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/treegrid', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'parts-gantt/Tree.js', [_modules['parts/Utilities.js']], function (U) { + /* * + * + * (c) 2016-2020 Highsoft AS + * + * Authors: Jon Arild Nygard + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /* eslint no-console: 0 */ + var extend = U.extend, isNumber = U.isNumber, pick = U.pick; + /** + * Creates an object map from parent id to childrens index. + * + * @private + * @function Highcharts.Tree#getListOfParents + * + * @param {Array<*>} data + * List of points set in options. `Array.parent` is parent id of point. + * + * @param {Array} ids + * List of all point ids. + * + * @return {Highcharts.Dictionary>} + * Map from parent id to children index in data + */ + var getListOfParents = function (data, ids) { + var listOfParents = data.reduce(function (prev, curr) { + var parent = pick(curr.parent, ''); + if (typeof prev[parent] === 'undefined') { + prev[parent] = []; + } + prev[parent].push(curr); + return prev; + }, {}), parents = Object.keys(listOfParents); + // If parent does not exist, hoist parent to root of tree. + parents.forEach(function (parent, list) { + var children = listOfParents[parent]; + if ((parent !== '') && (ids.indexOf(parent) === -1)) { + children.forEach(function (child) { + list[''].push(child); + }); + delete list[parent]; + } + }); + return listOfParents; + }; + var getNode = function (id, parent, level, data, mapOfIdToChildren, options) { + var descendants = 0, height = 0, after = options && options.after, before = options && options.before, node = { + data: data, + depth: level - 1, + id: id, + level: level, + parent: parent + }, start, end, children; + // Allow custom logic before the children has been created. + if (typeof before === 'function') { + before(node, options); + } + // Call getNode recursively on the children. Calulate the height of the + // node, and the number of descendants. + children = ((mapOfIdToChildren[id] || [])).map(function (child) { + var node = getNode(child.id, id, (level + 1), child, mapOfIdToChildren, options), childStart = child.start, childEnd = (child.milestone === true ? + childStart : + child.end); + // Start should be the lowest child.start. + start = ((!isNumber(start) || childStart < start) ? + childStart : + start); + // End should be the largest child.end. + // If child is milestone, then use start as end. + end = ((!isNumber(end) || childEnd > end) ? + childEnd : + end); + descendants = descendants + 1 + node.descendants; + height = Math.max(node.height + 1, height); + return node; + }); + // Calculate start and end for point if it is not already explicitly set. + if (data) { + data.start = pick(data.start, start); + data.end = pick(data.end, end); + } + extend(node, { + children: children, + descendants: descendants, + height: height + }); + // Allow custom logic after the children has been created. + if (typeof after === 'function') { + after(node, options); + } + return node; + }; + var getTree = function (data, options) { + var ids = data.map(function (d) { + return d.id; + }), mapOfIdToChildren = getListOfParents(data, ids); + return getNode('', null, 1, null, mapOfIdToChildren, options); + }; + var Tree = { + getListOfParents: getListOfParents, + getNode: getNode, + getTree: getTree + }; + + return Tree; + }); + _registerModule(_modules, 'parts-gantt/TreeGridTick.js', [_modules['parts/Utilities.js']], function (U) { + /* * + * + * (c) 2016 Highsoft AS + * Authors: Jon Arild Nygard + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, defined = U.defined, isObject = U.isObject, isNumber = U.isNumber, pick = U.pick, wrap = U.wrap; + /** + * @private + */ + var TreeGridTick; + (function (TreeGridTick) { + /* * + * + * Interfaces + * + * */ + /* * + * + * Variables + * + * */ + var applied = false; + /* * + * + * Functions + * + * */ + /** + * @private + */ + function compose(TickClass) { + if (!applied) { + addEvent(TickClass, 'init', onInit); + wrap(TickClass.prototype, 'getLabelPosition', wrapGetLabelPosition); + wrap(TickClass.prototype, 'renderLabel', wrapRenderLabel); + // backwards compatibility + TickClass.prototype.collapse = function (redraw) { + this.treeGrid.collapse(redraw); + }; + TickClass.prototype.expand = function (redraw) { + this.treeGrid.expand(redraw); + }; + TickClass.prototype.toggleCollapse = function (redraw) { + this.treeGrid.toggleCollapse(redraw); + }; + applied = true; + } + } + TreeGridTick.compose = compose; + /** + * @private + */ + function onInit() { + var tick = this; + if (!tick.treeGrid) { + tick.treeGrid = new Additions(tick); + } + } + /** + * @private + */ + function onTickHover(label) { + label.addClass('highcharts-treegrid-node-active'); + if (!label.renderer.styledMode) { + label.css({ + textDecoration: 'underline' + }); + } + } + /** + * @private + */ + function onTickHoverExit(label, options) { + var css = defined(options.style) ? options.style : {}; + label.removeClass('highcharts-treegrid-node-active'); + if (!label.renderer.styledMode) { + label.css({ textDecoration: css.textDecoration }); + } + } + /** + * @private + */ + function renderLabelIcon(tick, params) { + var treeGrid = tick.treeGrid, isNew = !treeGrid.labelIcon, renderer = params.renderer, labelBox = params.xy, options = params.options, width = options.width, height = options.height, iconCenter = { + x: labelBox.x - (width / 2) - options.padding, + y: labelBox.y - (height / 2) + }, rotation = params.collapsed ? 90 : 180, shouldRender = params.show && isNumber(iconCenter.y); + var icon = treeGrid.labelIcon; + if (!icon) { + treeGrid.labelIcon = icon = renderer + .path(renderer.symbols[options.type](options.x, options.y, width, height)) + .addClass('highcharts-label-icon') + .add(params.group); + } + // Set the new position, and show or hide + if (!shouldRender) { + icon.attr({ y: -9999 }); // #1338 + } + // Presentational attributes + if (!renderer.styledMode) { + icon + .attr({ + 'stroke-width': 1, + 'fill': pick(params.color, '#666666') + }) + .css({ + cursor: 'pointer', + stroke: options.lineColor, + strokeWidth: options.lineWidth + }); + } + // Update the icon positions + icon[isNew ? 'attr' : 'animate']({ + translateX: iconCenter.x, + translateY: iconCenter.y, + rotation: rotation + }); + } + /** + * @private + */ + function wrapGetLabelPosition(proceed, x, y, label, horiz, labelOptions, tickmarkOffset, index, step) { + var tick = this, lbOptions = pick(tick.options && tick.options.labels, labelOptions), pos = tick.pos, axis = tick.axis, options = axis.options, isTreeGrid = options.type === 'treegrid', result = proceed.apply(tick, [x, y, label, horiz, lbOptions, tickmarkOffset, index, step]); + var symbolOptions, indentation, mapOfPosToGridNode, node, level; + if (isTreeGrid) { + symbolOptions = (lbOptions && isObject(lbOptions.symbol, true) ? + lbOptions.symbol : + {}); + indentation = (lbOptions && isNumber(lbOptions.indentation) ? + lbOptions.indentation : + 0); + mapOfPosToGridNode = axis.treeGrid.mapOfPosToGridNode; + node = mapOfPosToGridNode && mapOfPosToGridNode[pos]; + level = (node && node.depth) || 1; + result.x += ( + // Add space for symbols + ((symbolOptions.width) + (symbolOptions.padding * 2)) + + // Apply indentation + ((level - 1) * indentation)); + } + return result; + } + /** + * @private + */ + function wrapRenderLabel(proceed) { + var tick = this, pos = tick.pos, axis = tick.axis, label = tick.label, mapOfPosToGridNode = axis.treeGrid.mapOfPosToGridNode, options = axis.options, labelOptions = pick(tick.options && tick.options.labels, options && options.labels), symbolOptions = (labelOptions && isObject(labelOptions.symbol, true) ? + labelOptions.symbol : + {}), node = mapOfPosToGridNode && mapOfPosToGridNode[pos], level = node && node.depth, isTreeGrid = options.type === 'treegrid', shouldRender = axis.tickPositions.indexOf(pos) > -1, prefixClassName = 'highcharts-treegrid-node-', styledMode = axis.chart.styledMode; + var collapsed, addClassName, removeClassName; + if (isTreeGrid && node) { + // Add class name for hierarchical styling. + if (label && + label.element) { + label.addClass(prefixClassName + 'level-' + level); + } + } + proceed.apply(tick, Array.prototype.slice.call(arguments, 1)); + if (isTreeGrid && + label && + label.element && + node && + node.descendants && + node.descendants > 0) { + collapsed = axis.treeGrid.isCollapsed(node); + renderLabelIcon(tick, { + color: !styledMode && label.styles && label.styles.color || '', + collapsed: collapsed, + group: label.parentGroup, + options: symbolOptions, + renderer: label.renderer, + show: shouldRender, + xy: label.xy + }); + // Add class name for the node. + addClassName = prefixClassName + + (collapsed ? 'collapsed' : 'expanded'); + removeClassName = prefixClassName + + (collapsed ? 'expanded' : 'collapsed'); + label + .addClass(addClassName) + .removeClass(removeClassName); + if (!styledMode) { + label.css({ + cursor: 'pointer' + }); + } + // Add events to both label text and icon + [label, tick.treeGrid.labelIcon].forEach(function (object) { + if (object && !object.attachedTreeGridEvents) { + // On hover + addEvent(object.element, 'mouseover', function () { + onTickHover(label); + }); + // On hover out + addEvent(object.element, 'mouseout', function () { + onTickHoverExit(label, labelOptions); + }); + addEvent(object.element, 'click', function () { + tick.treeGrid.toggleCollapse(); + }); + object.attachedTreeGridEvents = true; + } + }); + } + } + /* * + * + * Classes + * + * */ + /** + * @private + * @class + */ + var Additions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + /** + * @private + */ + function Additions(tick) { + this.tick = tick; + } + /* * + * + * Functions + * + * */ + /** + * Collapse the grid cell. Used when axis is of type treegrid. + * + * @see gantt/treegrid-axis/collapsed-dynamically/demo.js + * + * @private + * @function Highcharts.Tick#collapse + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call to + * {@link Highcharts.Chart#redraw} + */ + Additions.prototype.collapse = function (redraw) { + var tick = this.tick, axis = tick.axis, brokenAxis = axis.brokenAxis; + if (brokenAxis && + axis.treeGrid.mapOfPosToGridNode) { + var pos = tick.pos, node = axis.treeGrid.mapOfPosToGridNode[pos], breaks = axis.treeGrid.collapse(node); + brokenAxis.setBreaks(breaks, pick(redraw, true)); + } + }; + /** + * Expand the grid cell. Used when axis is of type treegrid. + * + * @see gantt/treegrid-axis/collapsed-dynamically/demo.js + * + * @private + * @function Highcharts.Tick#expand + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call to + * {@link Highcharts.Chart#redraw} + */ + Additions.prototype.expand = function (redraw) { + var tick = this.tick, axis = tick.axis, brokenAxis = axis.brokenAxis; + if (brokenAxis && + axis.treeGrid.mapOfPosToGridNode) { + var pos = tick.pos, node = axis.treeGrid.mapOfPosToGridNode[pos], breaks = axis.treeGrid.expand(node); + brokenAxis.setBreaks(breaks, pick(redraw, true)); + } + }; + /** + * Toggle the collapse/expand state of the grid cell. Used when axis is + * of type treegrid. + * + * @see gantt/treegrid-axis/collapsed-dynamically/demo.js + * + * @private + * @function Highcharts.Tick#toggleCollapse + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart or wait for an explicit call to + * {@link Highcharts.Chart#redraw} + */ + Additions.prototype.toggleCollapse = function (redraw) { + var tick = this.tick, axis = tick.axis, brokenAxis = axis.brokenAxis; + if (brokenAxis && + axis.treeGrid.mapOfPosToGridNode) { + var pos = tick.pos, node = axis.treeGrid.mapOfPosToGridNode[pos], breaks = axis.treeGrid.toggleCollapse(node); + brokenAxis.setBreaks(breaks, pick(redraw, true)); + } + }; + return Additions; + }()); + TreeGridTick.Additions = Additions; + })(TreeGridTick || (TreeGridTick = {})); + + return TreeGridTick; + }); + _registerModule(_modules, 'mixins/tree-series.js', [_modules['parts/Color.js'], _modules['parts/Utilities.js']], function (Color, U) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var extend = U.extend, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, merge = U.merge, pick = U.pick; + var isBoolean = function (x) { + return typeof x === 'boolean'; + }, isFn = function (x) { + return typeof x === 'function'; + }; + /* eslint-disable valid-jsdoc */ + /** + * @todo Combine buildTree and buildNode with setTreeValues + * @todo Remove logic from Treemap and make it utilize this mixin. + * @private + */ + var setTreeValues = function setTreeValues(tree, options) { + var before = options.before, idRoot = options.idRoot, mapIdToNode = options.mapIdToNode, nodeRoot = mapIdToNode[idRoot], levelIsConstant = (isBoolean(options.levelIsConstant) ? + options.levelIsConstant : + true), points = options.points, point = points[tree.i], optionsPoint = point && point.options || {}, childrenTotal = 0, children = [], value; + extend(tree, { + levelDynamic: tree.level - (levelIsConstant ? 0 : nodeRoot.level), + name: pick(point && point.name, ''), + visible: (idRoot === tree.id || + (isBoolean(options.visible) ? options.visible : false)) + }); + if (isFn(before)) { + tree = before(tree, options); + } + // First give the children some values + tree.children.forEach(function (child, i) { + var newOptions = extend({}, options); + extend(newOptions, { + index: i, + siblings: tree.children.length, + visible: tree.visible + }); + child = setTreeValues(child, newOptions); + children.push(child); + if (child.visible) { + childrenTotal += child.val; + } + }); + tree.visible = childrenTotal > 0 || tree.visible; + // Set the values + value = pick(optionsPoint.value, childrenTotal); + extend(tree, { + children: children, + childrenTotal: childrenTotal, + isLeaf: tree.visible && !childrenTotal, + val: value + }); + return tree; + }; + /** + * @private + */ + var getColor = function getColor(node, options) { + var index = options.index, mapOptionsToLevel = options.mapOptionsToLevel, parentColor = options.parentColor, parentColorIndex = options.parentColorIndex, series = options.series, colors = options.colors, siblings = options.siblings, points = series.points, getColorByPoint, chartOptionsChart = series.chart.options.chart, point, level, colorByPoint, colorIndexByPoint, color, colorIndex; + /** + * @private + */ + function variation(color) { + var colorVariation = level && level.colorVariation; + if (colorVariation) { + if (colorVariation.key === 'brightness') { + return Color.parse(color).brighten(colorVariation.to * (index / siblings)).get(); + } + } + return color; + } + if (node) { + point = points[node.i]; + level = mapOptionsToLevel[node.level] || {}; + getColorByPoint = point && level.colorByPoint; + if (getColorByPoint) { + colorIndexByPoint = point.index % (colors ? + colors.length : + chartOptionsChart.colorCount); + colorByPoint = colors && colors[colorIndexByPoint]; + } + // Select either point color, level color or inherited color. + if (!series.chart.styledMode) { + color = pick(point && point.options.color, level && level.color, colorByPoint, parentColor && variation(parentColor), series.color); + } + colorIndex = pick(point && point.options.colorIndex, level && level.colorIndex, colorIndexByPoint, parentColorIndex, options.colorIndex); + } + return { + color: color, + colorIndex: colorIndex + }; + }; + /** + * Creates a map from level number to its given options. + * + * @private + * @function getLevelOptions + * @param {object} params + * Object containing parameters. + * - `defaults` Object containing default options. The default options + * are merged with the userOptions to get the final options for a + * specific level. + * - `from` The lowest level number. + * - `levels` User options from series.levels. + * - `to` The highest level number. + * @return {Highcharts.Dictionary|null} + * Returns a map from level number to its given options. + */ + var getLevelOptions = function getLevelOptions(params) { + var result = null, defaults, converted, i, from, to, levels; + if (isObject(params)) { + result = {}; + from = isNumber(params.from) ? params.from : 1; + levels = params.levels; + converted = {}; + defaults = isObject(params.defaults) ? params.defaults : {}; + if (isArray(levels)) { + converted = levels.reduce(function (obj, item) { + var level, levelIsConstant, options; + if (isObject(item) && isNumber(item.level)) { + options = merge({}, item); + levelIsConstant = (isBoolean(options.levelIsConstant) ? + options.levelIsConstant : + defaults.levelIsConstant); + // Delete redundant properties. + delete options.levelIsConstant; + delete options.level; + // Calculate which level these options apply to. + level = item.level + (levelIsConstant ? 0 : from - 1); + if (isObject(obj[level])) { + extend(obj[level], options); + } + else { + obj[level] = options; + } + } + return obj; + }, {}); + } + to = isNumber(params.to) ? params.to : 1; + for (i = 0; i <= to; i++) { + result[i] = merge({}, defaults, isObject(converted[i]) ? converted[i] : {}); + } + } + return result; + }; + /** + * Update the rootId property on the series. Also makes sure that it is + * accessible to exporting. + * + * @private + * @function updateRootId + * + * @param {object} series + * The series to operate on. + * + * @return {string} + * Returns the resulting rootId after update. + */ + var updateRootId = function (series) { + var rootId, options; + if (isObject(series)) { + // Get the series options. + options = isObject(series.options) ? series.options : {}; + // Calculate the rootId. + rootId = pick(series.rootNode, options.rootId, ''); + // Set rootId on series.userOptions to pick it up in exporting. + if (isObject(series.userOptions)) { + series.userOptions.rootId = rootId; + } + // Set rootId on series to pick it up on next update. + series.rootNode = rootId; + } + return rootId; + }; + var result = { + getColor: getColor, + getLevelOptions: getLevelOptions, + setTreeValues: setTreeValues, + updateRootId: updateRootId + }; + + return result; + }); + _registerModule(_modules, 'parts-gantt/GridAxis.js', [_modules['parts/Axis.js'], _modules['parts/Globals.js'], _modules['parts/Tick.js'], _modules['parts/Utilities.js']], function (Axis, H, Tick, U) { + /* * + * + * (c) 2016 Highsoft AS + * Authors: Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, defined = U.defined, erase = U.erase, find = U.find, isArray = U.isArray, isNumber = U.isNumber, merge = U.merge, pick = U.pick, timeUnits = U.timeUnits, wrap = U.wrap; + var argsToArray = function (args) { + return Array.prototype.slice.call(args, 1); + }, dateFormat = H.dateFormat, isObject = function (x) { + // Always use strict mode + return U.isObject(x, true); + }, Chart = H.Chart; + var applyGridOptions = function applyGridOptions(axis) { + var options = axis.options; + // Center-align by default + if (!options.labels) { + options.labels = {}; + } + options.labels.align = pick(options.labels.align, 'center'); + // @todo: Check against tickLabelPlacement between/on etc + /* Prevents adding the last tick label if the axis is not a category + axis. + Since numeric labels are normally placed at starts and ends of a + range of value, and this module makes the label point at the value, + an "extra" label would appear. */ + if (!axis.categories) { + options.showLastLabel = false; + } + // Prevents rotation of labels when squished, as rotating them would not + // help. + axis.labelRotation = 0; + options.labels.rotation = 0; + }; + /** + * Set grid options for the axis labels. Requires Highcharts Gantt. + * + * @since 6.2.0 + * @product gantt + * @apioption xAxis.grid + */ + /** + * Enable grid on the axis labels. Defaults to true for Gantt charts. + * + * @type {boolean} + * @default true + * @since 6.2.0 + * @product gantt + * @apioption xAxis.grid.enabled + */ + /** + * Set specific options for each column (or row for horizontal axes) in the + * grid. Each extra column/row is its own axis, and the axis options can be set + * here. + * + * @sample gantt/demo/left-axis-table + * Left axis as a table + * + * @type {Array} + * @apioption xAxis.grid.columns + */ + /** + * Set border color for the label grid lines. + * + * @type {Highcharts.ColorString} + * @apioption xAxis.grid.borderColor + */ + /** + * Set border width of the label grid lines. + * + * @type {number} + * @default 1 + * @apioption xAxis.grid.borderWidth + */ + /** + * Set cell height for grid axis labels. By default this is calculated from font + * size. This option only applies to horizontal axes. + * + * @sample gantt/grid-axis/cellheight + * Gant chart with custom cell height + * @type {number} + * @apioption xAxis.grid.cellHeight + */ + ''; // detach doclets above + /** + * Get the largest label width and height. + * + * @private + * @function Highcharts.Axis#getMaxLabelDimensions + * + * @param {Highcharts.Dictionary} ticks + * All the ticks on one axis. + * + * @param {Array} tickPositions + * All the tick positions on one axis. + * + * @return {Highcharts.SizeObject} + * Object containing the properties height and width. + * + * @todo Move this to the generic axis implementation, as it is used there. + */ + Axis.prototype.getMaxLabelDimensions = function (ticks, tickPositions) { + var dimensions = { + width: 0, + height: 0 + }; + tickPositions.forEach(function (pos) { + var tick = ticks[pos], tickHeight = 0, tickWidth = 0, label; + if (isObject(tick)) { + label = isObject(tick.label) ? tick.label : {}; + // Find width and height of tick + tickHeight = label.getBBox ? label.getBBox().height : 0; + if (label.textStr && !isNumber(label.textPxLength)) { + label.textPxLength = label.getBBox().width; + } + tickWidth = isNumber(label.textPxLength) ? + // Math.round ensures crisp lines + Math.round(label.textPxLength) : + 0; + // Update the result if width and/or height are larger + dimensions.height = Math.max(tickHeight, dimensions.height); + dimensions.width = Math.max(tickWidth, dimensions.width); + } + }); + return dimensions; + }; + // Adds week date format + H.dateFormats.W = function (timestamp) { + var d = new this.Date(timestamp); + var firstDay = (this.get('Day', d) + 6) % 7; + var thursday = new this.Date(d.valueOf()); + this.set('Date', thursday, this.get('Date', d) - firstDay + 3); + var firstThursday = new this.Date(this.get('FullYear', thursday), 0, 1); + if (this.get('Day', firstThursday) !== 4) { + this.set('Month', d, 0); + this.set('Date', d, 1 + (11 - this.get('Day', firstThursday)) % 7); + } + return (1 + + Math.floor((thursday.valueOf() - firstThursday.valueOf()) / 604800000)).toString(); + }; + // First letter of the day of the week, e.g. 'M' for 'Monday'. + H.dateFormats.E = function (timestamp) { + return dateFormat('%a', timestamp, true).charAt(0); + }; + /* eslint-disable no-invalid-this */ + addEvent(Chart, 'afterSetChartSize', function () { + this.axes.forEach(function (axis) { + (axis.grid && axis.grid.columns || []).forEach(function (column) { + column.setAxisSize(); + column.setAxisTranslation(); + }); + }); + }); + // Center tick labels in cells. + addEvent(Tick, 'afterGetLabelPosition', function (e) { + var tick = this, label = tick.label, axis = tick.axis, reversed = axis.reversed, chart = axis.chart, options = axis.options, gridOptions = options.grid || {}, labelOpts = axis.options.labels, align = labelOpts.align, + // verticalAlign is currently not supported for axis.labels. + verticalAlign = 'middle', // labelOpts.verticalAlign, + side = GridAxis.Side[axis.side], tickmarkOffset = e.tickmarkOffset, tickPositions = axis.tickPositions, tickPos = tick.pos - tickmarkOffset, nextTickPos = (isNumber(tickPositions[e.index + 1]) ? + tickPositions[e.index + 1] - tickmarkOffset : + axis.max + tickmarkOffset), tickSize = axis.tickSize('tick'), tickWidth = tickSize ? tickSize[0] : 0, crispCorr = tickSize ? tickSize[1] / 2 : 0, labelHeight, lblMetrics, lines, bottom, top, left, right; + // Only center tick labels in grid axes + if (gridOptions.enabled === true) { + // Calculate top and bottom positions of the cell. + if (side === 'top') { + bottom = axis.top + axis.offset; + top = bottom - tickWidth; + } + else if (side === 'bottom') { + top = chart.chartHeight - axis.bottom + axis.offset; + bottom = top + tickWidth; + } + else { + bottom = axis.top + axis.len - axis.translate(reversed ? nextTickPos : tickPos); + top = axis.top + axis.len - axis.translate(reversed ? tickPos : nextTickPos); + } + // Calculate left and right positions of the cell. + if (side === 'right') { + left = chart.chartWidth - axis.right + axis.offset; + right = left + tickWidth; + } + else if (side === 'left') { + right = axis.left + axis.offset; + left = right - tickWidth; + } + else { + left = Math.round(axis.left + axis.translate(reversed ? nextTickPos : tickPos)) - crispCorr; + right = Math.round(axis.left + axis.translate(reversed ? tickPos : nextTickPos)) - crispCorr; + } + tick.slotWidth = right - left; + // Calculate the positioning of the label based on + // alignment. + e.pos.x = (align === 'left' ? + left : + align === 'right' ? + right : + left + ((right - left) / 2) // default to center + ); + e.pos.y = (verticalAlign === 'top' ? + top : + verticalAlign === 'bottom' ? + bottom : + top + ((bottom - top) / 2) // default to middle + ); + lblMetrics = chart.renderer.fontMetrics(labelOpts.style.fontSize, label.element); + labelHeight = label.getBBox().height; + // Adjustment to y position to align the label correctly. + // Would be better to have a setter or similar for this. + if (!labelOpts.useHTML) { + lines = Math.round(labelHeight / lblMetrics.h); + e.pos.y += ( + // Center the label + // TODO: why does this actually center the label? + ((lblMetrics.b - (lblMetrics.h - lblMetrics.f)) / 2) + + // Adjust for height of additional lines. + -(((lines - 1) * lblMetrics.h) / 2)); + } + else { + e.pos.y += ( + // Readjust yCorr in htmlUpdateTransform + lblMetrics.b + + // Adjust for height of html label + -(labelHeight / 2)); + } + e.pos.x += (axis.horiz && labelOpts.x || 0); + } + }); + /* eslint-enable no-invalid-this */ + /** + * Additions for grid axes. + * @private + * @class + */ + var GridAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function GridAxisAdditions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Checks if an axis is the outer axis in its dimension. Since + * axes are placed outwards in order, the axis with the highest + * index is the outermost axis. + * + * Example: If there are multiple x-axes at the top of the chart, + * this function returns true if the axis supplied is the last + * of the x-axes. + * + * @private + * + * @return {boolean} + * True if the axis is the outermost axis in its dimension; false if + * not. + */ + GridAxisAdditions.prototype.isOuterAxis = function () { + var axis = this.axis; + var chart = axis.chart; + var columnIndex = axis.grid.columnIndex; + var columns = (axis.linkedParent && axis.linkedParent.grid.columns || + axis.grid.columns); + var parentAxis = columnIndex ? axis.linkedParent : axis; + var thisIndex = -1, lastIndex = 0; + chart[axis.coll].forEach(function (otherAxis, index) { + if (otherAxis.side === axis.side && !otherAxis.options.isInternal) { + lastIndex = index; + if (otherAxis === parentAxis) { + // Get the index of the axis in question + thisIndex = index; + } + } + }); + return (lastIndex === thisIndex && + (isNumber(columnIndex) ? columns.length === columnIndex : true)); + }; + return GridAxisAdditions; + }()); + /** + * Axis with grid support. + * @private + * @class + */ + var GridAxis = /** @class */ (function () { + function GridAxis() { + } + /* * + * + * Static Functions + * + * */ + /* eslint-disable valid-jsdoc */ + /** + * Extends axis class with grid support. + * @private + */ + GridAxis.compose = function (AxisClass) { + Axis.keepProps.push('grid'); + wrap(AxisClass.prototype, 'unsquish', GridAxis.wrapUnsquish); + // Add event handlers + addEvent(AxisClass, 'init', GridAxis.onInit); + addEvent(AxisClass, 'afterGetOffset', GridAxis.onAfterGetOffset); + addEvent(AxisClass, 'afterGetTitlePosition', GridAxis.onAfterGetTitlePosition); + addEvent(AxisClass, 'afterInit', GridAxis.onAfterInit); + addEvent(AxisClass, 'afterRender', GridAxis.onAfterRender); + addEvent(AxisClass, 'afterSetAxisTranslation', GridAxis.onAfterSetAxisTranslation); + addEvent(AxisClass, 'afterSetOptions', GridAxis.onAfterSetOptions); + addEvent(AxisClass, 'afterSetOptions', GridAxis.onAfterSetOptions2); + addEvent(AxisClass, 'afterSetScale', GridAxis.onAfterSetScale); + addEvent(AxisClass, 'afterTickSize', GridAxis.onAfterTickSize); + addEvent(AxisClass, 'trimTicks', GridAxis.onTrimTicks); + addEvent(AxisClass, 'destroy', GridAxis.onDestroy); + }; + /** + * Handle columns and getOffset. + * @private + */ + GridAxis.onAfterGetOffset = function () { + var grid = this.grid; + (grid && grid.columns || []).forEach(function (column) { + column.getOffset(); + }); + }; + /** + * @private + */ + GridAxis.onAfterGetTitlePosition = function (e) { + var axis = this; + var options = axis.options; + var gridOptions = options.grid || {}; + if (gridOptions.enabled === true) { + // compute anchor points for each of the title align options + var title = axis.axisTitle, axisHeight = axis.height, horiz = axis.horiz, axisLeft = axis.left, offset = axis.offset, opposite = axis.opposite, _a = axis.options.title, axisTitleOptions = _a === void 0 ? {} : _a, axisTop = axis.top, axisWidth = axis.width; + var tickSize = axis.tickSize(); + var titleWidth = title && title.getBBox().width; + var xOption = axisTitleOptions.x || 0; + var yOption = axisTitleOptions.y || 0; + var titleMargin = pick(axisTitleOptions.margin, horiz ? 5 : 10); + var titleFontSize = axis.chart.renderer.fontMetrics(axisTitleOptions.style && + axisTitleOptions.style.fontSize, title).f; + var crispCorr = tickSize ? tickSize[0] / 2 : 0; + // TODO account for alignment + // the position in the perpendicular direction of the axis + var offAxis = ((horiz ? axisTop + axisHeight : axisLeft) + + (horiz ? 1 : -1) * // horizontal axis reverses the margin + (opposite ? -1 : 1) * // so does opposite axes + crispCorr + + (axis.side === GridAxis.Side.bottom ? titleFontSize : 0)); + e.titlePosition.x = horiz ? + axisLeft - titleWidth / 2 - titleMargin + xOption : + offAxis + (opposite ? axisWidth : 0) + offset + xOption; + e.titlePosition.y = horiz ? + (offAxis - + (opposite ? axisHeight : 0) + + (opposite ? titleFontSize : -titleFontSize) / 2 + + offset + + yOption) : + axisTop - titleMargin + yOption; + } + }; + /** + * @private + */ + GridAxis.onAfterInit = function () { + var axis = this; + var chart = axis.chart, _a = axis.options.grid, gridOptions = _a === void 0 ? {} : _a, userOptions = axis.userOptions; + if (gridOptions.enabled) { + applyGridOptions(axis); + /* eslint-disable no-invalid-this */ + // TODO: wrap the axis instead + wrap(axis, 'labelFormatter', function (proceed) { + var _a = this, axis = _a.axis, value = _a.value; + var tickPos = axis.tickPositions; + var series = (axis.isLinked ? + axis.linkedParent : + axis).series[0]; + var isFirst = value === tickPos[0]; + var isLast = value === tickPos[tickPos.length - 1]; + var point = series && find(series.options.data, function (p) { + return p[axis.isXAxis ? 'x' : 'y'] === value; + }); + // Make additional properties available for the + // formatter + this.isFirst = isFirst; + this.isLast = isLast; + this.point = point; + // Call original labelFormatter + return proceed.call(this); + }); + /* eslint-enable no-invalid-this */ + } + if (gridOptions.columns) { + var columns = axis.grid.columns = [], columnIndex = axis.grid.columnIndex = 0; + // Handle columns, each column is a grid axis + while (++columnIndex < gridOptions.columns.length) { + var columnOptions = merge(userOptions, gridOptions.columns[gridOptions.columns.length - columnIndex - 1], { + linkedTo: 0, + // Force to behave like category axis + type: 'category' + }); + delete columnOptions.grid.columns; // Prevent recursion + var column = new Axis(axis.chart, columnOptions); + column.grid.isColumn = true; + column.grid.columnIndex = columnIndex; + // Remove column axis from chart axes array, and place it + // in the columns array. + erase(chart.axes, column); + erase(chart[axis.coll], column); + columns.push(column); + } + } + }; + /** + * Draw an extra line on the far side of the outermost axis, + * creating floor/roof/wall of a grid. And some padding. + * ``` + * Make this: + * (axis.min) __________________________ (axis.max) + * | | | | | + * Into this: + * (axis.min) __________________________ (axis.max) + * ___|____|____|____|____|__ + * ``` + * @private + */ + GridAxis.onAfterRender = function () { + var axis = this; + var grid = axis.grid; + var options = axis.options; + var renderer = axis.chart.renderer; + var gridOptions = options.grid || {}; + var yStartIndex, yEndIndex, xStartIndex, xEndIndex; + if (gridOptions.enabled === true) { + // @todo acutual label padding (top, bottom, left, right) + axis.maxLabelDimensions = axis.getMaxLabelDimensions(axis.ticks, axis.tickPositions); + // Remove right wall before rendering if updating + if (axis.rightWall) { + axis.rightWall.destroy(); + } + /* + Draw an extra axis line on outer axes + > + Make this: |______|______|______|___ + + > _________________________ + Into this: |______|______|______|__| + */ + if (axis.grid && axis.grid.isOuterAxis() && axis.axisLine) { + var lineWidth = options.lineWidth; + if (lineWidth) { + var linePath = axis.getLinePath(lineWidth); + var startPoint = linePath[0]; + var endPoint = linePath[1]; + // Negate distance if top or left axis + // Subtract 1px to draw the line at the end of the tick + var tickLength = (axis.tickSize('tick') || [1])[0]; + var distance = (tickLength - 1) * ((axis.side === GridAxis.Side.top || + axis.side === GridAxis.Side.left) ? -1 : 1); + // If axis is horizontal, reposition line path vertically + if (startPoint[0] === 'M' && endPoint[0] === 'L') { + if (axis.horiz) { + startPoint[2] += distance; + endPoint[2] += distance; + } + else { + // If axis is vertical, reposition line path + // horizontally + startPoint[1] += distance; + endPoint[1] += distance; + } + } + if (!axis.grid.axisLineExtra) { + axis.grid.axisLineExtra = renderer + .path(linePath) + .attr({ + zIndex: 7 + }) + .addClass('highcharts-axis-line') + .add(axis.axisGroup); + if (!renderer.styledMode) { + axis.grid.axisLineExtra.attr({ + stroke: options.lineColor, + 'stroke-width': lineWidth + }); + } + } + else { + axis.grid.axisLineExtra.animate({ + d: linePath + }); + } + // show or hide the line depending on + // options.showEmpty + axis.axisLine[axis.showAxis ? 'show' : 'hide'](true); + } + } + (grid && grid.columns || []).forEach(function (column) { + column.render(); + }); + } + }; + /** + * @private + */ + GridAxis.onAfterSetAxisTranslation = function () { + var axis = this; + var tickInfo = axis.tickPositions && axis.tickPositions.info; + var options = axis.options; + var gridOptions = options.grid || {}; + var userLabels = axis.userOptions.labels || {}; + if (axis.horiz) { + if (gridOptions.enabled === true) { + axis.series.forEach(function (series) { + series.options.pointRange = 0; + }); + } + // Lower level time ticks, like hours or minutes, represent + // points in time and not ranges. These should be aligned + // left in the grid cell by default. The same applies to + // years of higher order. + if (tickInfo && + options.dateTimeLabelFormats && + options.labels && + !defined(userLabels.align) && + (options.dateTimeLabelFormats[tickInfo.unitName].range === false || + tickInfo.count > 1 // years + )) { + options.labels.align = 'left'; + if (!defined(userLabels.x)) { + options.labels.x = 3; + } + } + } + }; + /** + * Creates a left and right wall on horizontal axes: + * - Places leftmost tick at the start of the axis, to create a left + * wall + * - Ensures that the rightmost tick is at the end of the axis, to + * create a right wall. + * @private + */ + GridAxis.onAfterSetOptions = function (e) { + var options = this.options, userOptions = e.userOptions, gridAxisOptions, gridOptions = ((options && isObject(options.grid)) ? options.grid : {}); + if (gridOptions.enabled === true) { + // Merge the user options into default grid axis options so + // that when a user option is set, it takes presedence. + gridAxisOptions = merge(true, { + className: ('highcharts-grid-axis ' + (userOptions.className || '')), + dateTimeLabelFormats: { + hour: { + list: ['%H:%M', '%H'] + }, + day: { + list: ['%A, %e. %B', '%a, %e. %b', '%E'] + }, + week: { + list: ['Week %W', 'W%W'] + }, + month: { + list: ['%B', '%b', '%o'] + } + }, + grid: { + borderWidth: 1 + }, + labels: { + padding: 2, + style: { + fontSize: '13px' + } + }, + margin: 0, + title: { + text: null, + reserveSpace: false, + rotation: 0 + }, + // In a grid axis, only allow one unit of certain types, + // for example we shouln't have one grid cell spanning + // two days. + units: [[ + 'millisecond', + [1, 10, 100] + ], [ + 'second', + [1, 10] + ], [ + 'minute', + [1, 5, 15] + ], [ + 'hour', + [1, 6] + ], [ + 'day', + [1] + ], [ + 'week', + [1] + ], [ + 'month', + [1] + ], [ + 'year', + null + ]] + }, userOptions); + // X-axis specific options + if (this.coll === 'xAxis') { + // For linked axes, tickPixelInterval is used only if + // the tickPositioner below doesn't run or returns + // undefined (like multiple years) + if (defined(userOptions.linkedTo) && + !defined(userOptions.tickPixelInterval)) { + gridAxisOptions.tickPixelInterval = 350; + } + // For the secondary grid axis, use the primary axis' + // tick intervals and return ticks one level higher. + if ( + // Check for tick pixel interval in options + !defined(userOptions.tickPixelInterval) && + // Only for linked axes + defined(userOptions.linkedTo) && + !defined(userOptions.tickPositioner) && + !defined(userOptions.tickInterval)) { + gridAxisOptions.tickPositioner = function (min, max) { + var parentInfo = (this.linkedParent && + this.linkedParent.tickPositions && + this.linkedParent.tickPositions.info); + if (parentInfo) { + var unitIdx, count, unitName, i, units = gridAxisOptions.units, unitRange; + for (i = 0; i < units.length; i++) { + if (units[i][0] === + parentInfo.unitName) { + unitIdx = i; + break; + } + } + // Get the first allowed count on the next + // unit. + if (units[unitIdx + 1]) { + unitName = units[unitIdx + 1][0]; + count = + (units[unitIdx + 1][1] || [1])[0]; + // In case the base X axis shows years, make + // the secondary axis show ten times the + // years (#11427) + } + else if (parentInfo.unitName === 'year') { + unitName = 'year'; + count = parentInfo.count * 10; + } + unitRange = timeUnits[unitName]; + this.tickInterval = unitRange * count; + return this.getTimeTicks({ + unitRange: unitRange, + count: count, + unitName: unitName + }, min, max, this.options.startOfWeek); + } + }; + } + } + // Now merge the combined options into the axis options + merge(true, this.options, gridAxisOptions); + if (this.horiz) { + /* _________________________ + Make this: ___|_____|_____|_____|__| + ^ ^ + _________________________ + Into this: |_____|_____|_____|_____| + ^ ^ */ + options.minPadding = pick(userOptions.minPadding, 0); + options.maxPadding = pick(userOptions.maxPadding, 0); + } + // If borderWidth is set, then use its value for tick and + // line width. + if (isNumber(options.grid.borderWidth)) { + options.tickWidth = options.lineWidth = gridOptions.borderWidth; + } + } + }; + /** + * @private + */ + GridAxis.onAfterSetOptions2 = function (e) { + var axis = this; + var userOptions = e.userOptions; + var gridOptions = userOptions && userOptions.grid || {}; + var columns = gridOptions.columns; + // Add column options to the parent axis. Children has their column + // options set on init in onGridAxisAfterInit. + if (gridOptions.enabled && columns) { + merge(true, axis.options, columns[columns.length - 1]); + } + }; + /** + * Handle columns and setScale. + * @private + */ + GridAxis.onAfterSetScale = function () { + var axis = this; + (axis.grid.columns || []).forEach(function (column) { + column.setScale(); + }); + }; + /** + * Draw vertical axis ticks extra long to create cell floors and roofs. + * Overrides the tickLength for vertical axes. + * @private + */ + GridAxis.onAfterTickSize = function (e) { + var defaultLeftAxisOptions = Axis.defaultLeftAxisOptions; + var _a = this, horiz = _a.horiz, maxLabelDimensions = _a.maxLabelDimensions, _b = _a.options.grid, gridOptions = _b === void 0 ? {} : _b; + if (gridOptions.enabled && maxLabelDimensions) { + var labelPadding = (Math.abs(defaultLeftAxisOptions.labels.x) * 2); + var distance = horiz ? + gridOptions.cellHeight || labelPadding + maxLabelDimensions.height : + labelPadding + maxLabelDimensions.width; + if (isArray(e.tickSize)) { + e.tickSize[0] = distance; + } + else { + e.tickSize = [distance, 0]; + } + } + }; + /** + * @private + */ + GridAxis.onDestroy = function (e) { + var grid = this.grid; + (grid.columns || []).forEach(function (column) { + column.destroy(e.keepEvents); + }); + grid.columns = void 0; + }; + /** + * Wraps axis init to draw cell walls on vertical axes. + * @private + */ + GridAxis.onInit = function (e) { + var axis = this; + var userOptions = e.userOptions || {}; + var gridOptions = userOptions.grid || {}; + if (gridOptions.enabled && defined(gridOptions.borderColor)) { + userOptions.tickColor = userOptions.lineColor = gridOptions.borderColor; + } + if (!axis.grid) { + axis.grid = new GridAxisAdditions(axis); + } + }; + /** + * Makes tick labels which are usually ignored in a linked axis + * displayed if they are within range of linkedParent.min. + * ``` + * _____________________________ + * | | | | | + * Make this: | | 2 | 3 | 4 | + * |___|_______|_______|_______| + * ^ + * _____________________________ + * | | | | | + * Into this: | 1 | 2 | 3 | 4 | + * |___|_______|_______|_______| + * ^ + * ``` + * @private + * @todo Does this function do what the drawing says? Seems to affect + * ticks and not the labels directly? + */ + GridAxis.onTrimTicks = function () { + var axis = this; + var options = axis.options; + var gridOptions = options.grid || {}; + var categoryAxis = axis.categories; + var tickPositions = axis.tickPositions; + var firstPos = tickPositions[0]; + var lastPos = tickPositions[tickPositions.length - 1]; + var linkedMin = axis.linkedParent && axis.linkedParent.min; + var linkedMax = axis.linkedParent && axis.linkedParent.max; + var min = linkedMin || axis.min; + var max = linkedMax || axis.max; + var tickInterval = axis.tickInterval; + var endMoreThanMin = (firstPos < min && + firstPos + tickInterval > min); + var startLessThanMax = (lastPos > max && + lastPos - tickInterval < max); + if (gridOptions.enabled === true && + !categoryAxis && + (axis.horiz || axis.isLinked)) { + if (endMoreThanMin && !options.startOnTick) { + tickPositions[0] = min; + } + if (startLessThanMax && !options.endOnTick) { + tickPositions[tickPositions.length - 1] = max; + } + } + }; + /** + * Avoid altering tickInterval when reserving space. + * @private + */ + GridAxis.wrapUnsquish = function (proceed) { + var axis = this; + var _a = axis.options.grid, gridOptions = _a === void 0 ? {} : _a; + if (gridOptions.enabled === true && axis.categories) { + return axis.tickInterval; + } + return proceed.apply(axis, argsToArray(arguments)); + }; + return GridAxis; + }()); + (function (GridAxis) { + /** + * Enum for which side the axis is on. Maps to axis.side. + * @private + */ + var Side; + (function (Side) { + Side[Side["top"] = 0] = "top"; + Side[Side["right"] = 1] = "right"; + Side[Side["bottom"] = 2] = "bottom"; + Side[Side["left"] = 3] = "left"; + })(Side = GridAxis.Side || (GridAxis.Side = {})); + })(GridAxis || (GridAxis = {})); + GridAxis.compose(Axis); + + return GridAxis; + }); + _registerModule(_modules, 'modules/broken-axis.src.js', [_modules['parts/Axis.js'], _modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['parts/Stacking.js']], function (Axis, H, U, StackItem) { + /* * + * + * (c) 2009-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, find = U.find, fireEvent = U.fireEvent, isArray = U.isArray, isNumber = U.isNumber, pick = U.pick; + var Series = H.Series; + /* eslint-disable valid-jsdoc */ + /** + * Provides support for broken axes. + * @private + * @class + */ + var BrokenAxisAdditions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + function BrokenAxisAdditions(axis) { + this.hasBreaks = false; + this.axis = axis; + } + /* * + * + * Static Functions + * + * */ + /** + * @private + */ + BrokenAxisAdditions.isInBreak = function (brk, val) { + var ret, repeat = brk.repeat || Infinity, from = brk.from, length = brk.to - brk.from, test = (val >= from ? + (val - from) % repeat : + repeat - ((from - val) % repeat)); + if (!brk.inclusive) { + ret = test < length && test !== 0; + } + else { + ret = test <= length; + } + return ret; + }; + /** + * @private + */ + BrokenAxisAdditions.lin2Val = function (val) { + var axis = this; + var brokenAxis = axis.brokenAxis; + var breakArray = brokenAxis && brokenAxis.breakArray; + if (!breakArray) { + return val; + } + var nval = val, brk, i; + for (i = 0; i < breakArray.length; i++) { + brk = breakArray[i]; + if (brk.from >= nval) { + break; + } + else if (brk.to < nval) { + nval += brk.len; + } + else if (BrokenAxisAdditions.isInBreak(brk, nval)) { + nval += brk.len; + } + } + return nval; + }; + /** + * @private + */ + BrokenAxisAdditions.val2Lin = function (val) { + var axis = this; + var brokenAxis = axis.brokenAxis; + var breakArray = brokenAxis && brokenAxis.breakArray; + if (!breakArray) { + return val; + } + var nval = val, brk, i; + for (i = 0; i < breakArray.length; i++) { + brk = breakArray[i]; + if (brk.to <= val) { + nval -= brk.len; + } + else if (brk.from >= val) { + break; + } + else if (BrokenAxisAdditions.isInBreak(brk, val)) { + nval -= (val - brk.from); + break; + } + } + return nval; + }; + /* * + * + * Functions + * + * */ + /** + * Returns the first break found where the x is larger then break.from and + * smaller then break.to. + * + * @param {number} x + * The number which should be within a break. + * + * @param {Array} breaks + * The array of breaks to search within. + * + * @return {Highcharts.XAxisBreaksOptions|undefined} + * Returns the first break found that matches, returns false if no break is + * found. + */ + BrokenAxisAdditions.prototype.findBreakAt = function (x, breaks) { + return find(breaks, function (b) { + return b.from < x && x < b.to; + }); + }; + /** + * @private + */ + BrokenAxisAdditions.prototype.isInAnyBreak = function (val, testKeep) { + var brokenAxis = this; + var axis = brokenAxis.axis; + var breaks = axis.options.breaks, i = breaks && breaks.length, inbrk, keep, ret; + if (i) { + while (i--) { + if (BrokenAxisAdditions.isInBreak(breaks[i], val)) { + inbrk = true; + if (!keep) { + keep = pick(breaks[i].showPoints, !axis.isXAxis); + } + } + } + if (inbrk && testKeep) { + ret = inbrk && !keep; + } + else { + ret = inbrk; + } + } + return ret; + }; + /** + * Dynamically set or unset breaks in an axis. This function in lighter than + * usin Axis.update, and it also preserves animation. + * + * @private + * @function Highcharts.Axis#setBreaks + * + * @param {Array} [breaks] + * The breaks to add. When `undefined` it removes existing breaks. + * + * @param {boolean} [redraw=true] + * Whether to redraw the chart immediately. + * + * @return {void} + */ + BrokenAxisAdditions.prototype.setBreaks = function (breaks, redraw) { + var brokenAxis = this; + var axis = brokenAxis.axis; + var hasBreaks = (isArray(breaks) && !!breaks.length); + axis.isDirty = brokenAxis.hasBreaks !== hasBreaks; + brokenAxis.hasBreaks = hasBreaks; + axis.options.breaks = axis.userOptions.breaks = breaks; + axis.forceRedraw = true; // Force recalculation in setScale + // Recalculate series related to the axis. + axis.series.forEach(function (series) { + series.isDirty = true; + }); + if (!hasBreaks && axis.val2lin === BrokenAxisAdditions.val2Lin) { + // Revert to prototype functions + delete axis.val2lin; + delete axis.lin2val; + } + if (hasBreaks) { + axis.userOptions.ordinal = false; + axis.lin2val = BrokenAxisAdditions.lin2Val; + axis.val2lin = BrokenAxisAdditions.val2Lin; + axis.setExtremes = function (newMin, newMax, redraw, animation, eventArguments) { + // If trying to set extremes inside a break, extend min to + // after, and max to before the break ( #3857 ) + if (brokenAxis.hasBreaks) { + var axisBreak, breaks = this.options.breaks; + while ((axisBreak = brokenAxis.findBreakAt(newMin, breaks))) { + newMin = axisBreak.to; + } + while ((axisBreak = brokenAxis.findBreakAt(newMax, breaks))) { + newMax = axisBreak.from; + } + // If both min and max is within the same break. + if (newMax < newMin) { + newMax = newMin; + } + } + Axis.prototype.setExtremes.call(this, newMin, newMax, redraw, animation, eventArguments); + }; + axis.setAxisTranslation = function (saveOld) { + Axis.prototype.setAxisTranslation.call(this, saveOld); + brokenAxis.unitLength = null; + if (brokenAxis.hasBreaks) { + var breaks = axis.options.breaks || [], + // Temporary one: + breakArrayT = [], breakArray = [], length = 0, inBrk, repeat, min = axis.userMin || axis.min, max = axis.userMax || axis.max, pointRangePadding = pick(axis.pointRangePadding, 0), start, i; + // Min & max check (#4247) + breaks.forEach(function (brk) { + repeat = brk.repeat || Infinity; + if (BrokenAxisAdditions.isInBreak(brk, min)) { + min += + (brk.to % repeat) - + (min % repeat); + } + if (BrokenAxisAdditions.isInBreak(brk, max)) { + max -= + (max % repeat) - + (brk.from % repeat); + } + }); + // Construct an array holding all breaks in the axis + breaks.forEach(function (brk) { + start = brk.from; + repeat = brk.repeat || Infinity; + while (start - repeat > min) { + start -= repeat; + } + while (start < min) { + start += repeat; + } + for (i = start; i < max; i += repeat) { + breakArrayT.push({ + value: i, + move: 'in' + }); + breakArrayT.push({ + value: i + (brk.to - brk.from), + move: 'out', + size: brk.breakSize + }); + } + }); + breakArrayT.sort(function (a, b) { + return ((a.value === b.value) ? + ((a.move === 'in' ? 0 : 1) - + (b.move === 'in' ? 0 : 1)) : + a.value - b.value); + }); + // Simplify the breaks + inBrk = 0; + start = min; + breakArrayT.forEach(function (brk) { + inBrk += (brk.move === 'in' ? 1 : -1); + if (inBrk === 1 && brk.move === 'in') { + start = brk.value; + } + if (inBrk === 0) { + breakArray.push({ + from: start, + to: brk.value, + len: brk.value - start - (brk.size || 0) + }); + length += brk.value - start - (brk.size || 0); + } + }); + /** + * HC <= 8 backwards compatibility, used by demo samples. + * @deprecated + * @private + * @requires modules/broken-axis + */ + axis.breakArray = brokenAxis.breakArray = breakArray; + // Used with staticScale, and below the actual axis length, + // when breaks are substracted. + brokenAxis.unitLength = max - min - length + pointRangePadding; + fireEvent(axis, 'afterBreaks'); + if (axis.staticScale) { + axis.transA = axis.staticScale; + } + else if (brokenAxis.unitLength) { + axis.transA *= + (max - axis.min + pointRangePadding) / + brokenAxis.unitLength; + } + if (pointRangePadding) { + axis.minPixelPadding = + axis.transA * axis.minPointOffset; + } + axis.min = min; + axis.max = max; + } + }; + } + if (pick(redraw, true)) { + axis.chart.redraw(); + } + }; + return BrokenAxisAdditions; + }()); + /** + * Axis with support of broken data rows. + * @private + * @class + */ + var BrokenAxis = /** @class */ (function () { + function BrokenAxis() { + } + /** + * Adds support for broken axes. + * @private + */ + BrokenAxis.compose = function (AxisClass, SeriesClass) { + AxisClass.keepProps.push('brokenAxis'); + var seriesProto = Series.prototype; + /** + * @private + */ + seriesProto.drawBreaks = function (axis, keys) { + var series = this, points = series.points, breaks, threshold, eventName, y; + if (axis && // #5950 + axis.brokenAxis && + axis.brokenAxis.hasBreaks) { + var brokenAxis_1 = axis.brokenAxis; + keys.forEach(function (key) { + breaks = brokenAxis_1 && brokenAxis_1.breakArray || []; + threshold = axis.isXAxis ? + axis.min : + pick(series.options.threshold, axis.min); + points.forEach(function (point) { + y = pick(point['stack' + key.toUpperCase()], point[key]); + breaks.forEach(function (brk) { + if (isNumber(threshold) && isNumber(y)) { + eventName = false; + if ((threshold < brk.from && y > brk.to) || + (threshold > brk.from && y < brk.from)) { + eventName = 'pointBreak'; + } + else if ((threshold < brk.from && y > brk.from && y < brk.to) || + (threshold > brk.from && y > brk.to && y < brk.from)) { + eventName = 'pointInBreak'; + } + if (eventName) { + fireEvent(axis, eventName, { point: point, brk: brk }); + } + } + }); + }); + }); + } + }; + /** + * Extend getGraphPath by identifying gaps in the data so that we can + * draw a gap in the line or area. This was moved from ordinal axis + * module to broken axis module as of #5045. + * + * @private + * @function Highcharts.Series#gappedPath + * + * @return {Highcharts.SVGPathArray} + * Gapped path + */ + seriesProto.gappedPath = function () { + var currentDataGrouping = this.currentDataGrouping, groupingSize = currentDataGrouping && currentDataGrouping.gapSize, gapSize = this.options.gapSize, points = this.points.slice(), i = points.length - 1, yAxis = this.yAxis, stack; + /** + * Defines when to display a gap in the graph, together with the + * [gapUnit](plotOptions.series.gapUnit) option. + * + * In case when `dataGrouping` is enabled, points can be grouped + * into a larger time span. This can make the grouped points to have + * a greater distance than the absolute value of `gapSize` property, + * which will result in disappearing graph completely. To prevent + * this situation the mentioned distance between grouped points is + * used instead of previously defined `gapSize`. + * + * In practice, this option is most often used to visualize gaps in + * time series. In a stock chart, intraday data is available for + * daytime hours, while gaps will appear in nights and weekends. + * + * @see [gapUnit](plotOptions.series.gapUnit) + * @see [xAxis.breaks](#xAxis.breaks) + * + * @sample {highstock} stock/plotoptions/series-gapsize/ + * Setting the gap size to 2 introduces gaps for weekends + * in daily datasets. + * + * @type {number} + * @default 0 + * @product highstock + * @requires modules/broken-axis + * @apioption plotOptions.series.gapSize + */ + /** + * Together with [gapSize](plotOptions.series.gapSize), this option + * defines where to draw gaps in the graph. + * + * When the `gapUnit` is `"relative"` (default), a gap size of 5 + * means that if the distance between two points is greater than + * 5 times that of the two closest points, the graph will be broken. + * + * When the `gapUnit` is `"value"`, the gap is based on absolute + * axis values, which on a datetime axis is milliseconds. This also + * applies to the navigator series that inherits gap options from + * the base series. + * + * @see [gapSize](plotOptions.series.gapSize) + * + * @type {string} + * @default relative + * @since 5.0.13 + * @product highstock + * @validvalue ["relative", "value"] + * @requires modules/broken-axis + * @apioption plotOptions.series.gapUnit + */ + if (gapSize && i > 0) { // #5008 + // Gap unit is relative + if (this.options.gapUnit !== 'value') { + gapSize *= this.basePointRange; + } + // Setting a new gapSize in case dataGrouping is enabled (#7686) + if (groupingSize && + groupingSize > gapSize && + // Except when DG is forced (e.g. from other series) + // and has lower granularity than actual points (#11351) + groupingSize >= this.basePointRange) { + gapSize = groupingSize; + } + // extension for ordinal breaks + var current = void 0, next = void 0; + while (i--) { + // Reassign next if it is not visible + if (!(next && next.visible !== false)) { + next = points[i + 1]; + } + current = points[i]; + // Skip iteration if one of the points is not visible + if (next.visible === false || current.visible === false) { + continue; + } + if (next.x - current.x > gapSize) { + var xRange = (current.x + next.x) / 2; + points.splice(// insert after this one + i + 1, 0, { + isNull: true, + x: xRange + }); + // For stacked chart generate empty stack items, #6546 + if (yAxis.stacking && this.options.stacking) { + stack = yAxis.stacking.stacks[this.stackKey][xRange] = + new StackItem(yAxis, yAxis.options + .stackLabels, false, xRange, this.stack); + stack.total = 0; + } + } + // Assign current to next for the upcoming iteration + next = current; + } + } + // Call base method + return this.getGraphPath(points); + }; + /* eslint-disable no-invalid-this */ + addEvent(AxisClass, 'init', function () { + var axis = this; + if (!axis.brokenAxis) { + axis.brokenAxis = new BrokenAxisAdditions(axis); + } + }); + addEvent(AxisClass, 'afterInit', function () { + if (typeof this.brokenAxis !== 'undefined') { + this.brokenAxis.setBreaks(this.options.breaks, false); + } + }); + addEvent(AxisClass, 'afterSetTickPositions', function () { + var axis = this; + var brokenAxis = axis.brokenAxis; + if (brokenAxis && + brokenAxis.hasBreaks) { + var tickPositions = this.tickPositions, info = this.tickPositions.info, newPositions = [], i; + for (i = 0; i < tickPositions.length; i++) { + if (!brokenAxis.isInAnyBreak(tickPositions[i])) { + newPositions.push(tickPositions[i]); + } + } + this.tickPositions = newPositions; + this.tickPositions.info = info; + } + }); + // Force Axis to be not-ordinal when breaks are defined + addEvent(AxisClass, 'afterSetOptions', function () { + if (this.brokenAxis && this.brokenAxis.hasBreaks) { + this.options.ordinal = false; + } + }); + addEvent(SeriesClass, 'afterGeneratePoints', function () { + var _a = this, isDirty = _a.isDirty, connectNulls = _a.options.connectNulls, points = _a.points, xAxis = _a.xAxis, yAxis = _a.yAxis; + // Set, or reset visibility of the points. Axis.setBreaks marks the + // series as isDirty + if (isDirty) { + var i = points.length; + while (i--) { + var point = points[i]; + // Respect nulls inside the break (#4275) + var nullGap = point.y === null && connectNulls === false; + var isPointInBreak = (!nullGap && ((xAxis && + xAxis.brokenAxis && + xAxis.brokenAxis.isInAnyBreak(point.x, true)) || (yAxis && + yAxis.brokenAxis && + yAxis.brokenAxis.isInAnyBreak(point.y, true)))); + // Set point.visible if in any break. + // If not in break, reset visible to original value. + point.visible = isPointInBreak ? + false : + point.options.visible !== false; + } + } + }); + addEvent(SeriesClass, 'afterRender', function drawPointsWrapped() { + this.drawBreaks(this.xAxis, ['x']); + this.drawBreaks(this.yAxis, pick(this.pointArrayMap, ['y'])); + }); + }; + return BrokenAxis; + }()); + BrokenAxis.compose(Axis, Series); // @todo remove automatism + + return BrokenAxis; + }); + _registerModule(_modules, 'parts-gantt/TreeGridAxis.js', [_modules['parts/Axis.js'], _modules['parts/Tick.js'], _modules['parts-gantt/Tree.js'], _modules['parts-gantt/TreeGridTick.js'], _modules['mixins/tree-series.js'], _modules['parts/Utilities.js']], function (Axis, Tick, Tree, TreeGridTick, TreeSeriesMixin, U) { + /* * + * + * (c) 2016 Highsoft AS + * Authors: Jon Arild Nygard + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, find = U.find, fireEvent = U.fireEvent, isNumber = U.isNumber, isObject = U.isObject, isString = U.isString, merge = U.merge, pick = U.pick, wrap = U.wrap; + /** + * @private + */ + var TreeGridAxis; + (function (TreeGridAxis) { + /* * + * + * Interfaces + * + * */ + /* * + * + * Variables + * + * */ + var applied = false; + /* * + * + * Functions + * + * */ + /** + * @private + */ + function compose(AxisClass) { + if (!applied) { + wrap(AxisClass.prototype, 'generateTick', wrapGenerateTick); + wrap(AxisClass.prototype, 'getMaxLabelDimensions', wrapGetMaxLabelDimensions); + wrap(AxisClass.prototype, 'init', wrapInit); + wrap(AxisClass.prototype, 'setTickInterval', wrapSetTickInterval); + TreeGridTick.compose(Tick); + applied = true; + } + } + TreeGridAxis.compose = compose; + /** + * @private + */ + function getBreakFromNode(node, max) { + var from = node.collapseStart || 0, to = node.collapseEnd || 0; + // In broken-axis, the axis.max is minimized until it is not within a + // break. Therefore, if break.to is larger than axis.max, the axis.to + // should not add the 0.5 axis.tickMarkOffset, to avoid adding a break + // larger than axis.max. + // TODO consider simplifying broken-axis and this might solve itself + if (to >= max) { + from -= 0.5; + } + return { + from: from, + to: to, + showPoints: false + }; + } + /** + * Creates a tree structure of the data, and the treegrid. Calculates + * categories, and y-values of points based on the tree. + * + * @private + * @function getTreeGridFromData + * + * @param {Array} data + * All the data points to display in the axis. + * + * @param {boolean} uniqueNames + * Wether or not the data node with the same name should share grid cell. If + * true they do share cell. False by default. + * + * @param {number} numberOfSeries + * + * @return {object} + * Returns an object containing categories, mapOfIdToNode, + * mapOfPosToGridNode, and tree. + * + * @todo There should be only one point per line. + * @todo It should be optional to have one category per point, or merge + * cells + * @todo Add unit-tests. + */ + function getTreeGridFromData(data, uniqueNames, numberOfSeries) { + var categories = [], collapsedNodes = [], mapOfIdToNode = {}, mapOfPosToGridNode = {}, posIterator = -1, uniqueNamesEnabled = typeof uniqueNames === 'boolean' ? uniqueNames : false, tree; + // Build the tree from the series data. + var treeParams = { + // After the children has been created. + after: function (node) { + var gridNode = mapOfPosToGridNode[node.pos], height = 0, descendants = 0; + gridNode.children.forEach(function (child) { + descendants += (child.descendants || 0) + 1; + height = Math.max((child.height || 0) + 1, height); + }); + gridNode.descendants = descendants; + gridNode.height = height; + if (gridNode.collapsed) { + collapsedNodes.push(gridNode); + } + }, + // Before the children has been created. + before: function (node) { + var data = isObject(node.data, true) ? node.data : {}, name = isString(data.name) ? data.name : '', parentNode = mapOfIdToNode[node.parent], parentGridNode = (isObject(parentNode, true) ? + mapOfPosToGridNode[parentNode.pos] : + null), hasSameName = function (x) { + return x.name === name; + }, gridNode, pos; + // If not unique names, look for sibling node with the same name + if (uniqueNamesEnabled && + isObject(parentGridNode, true) && + !!(gridNode = find(parentGridNode.children, hasSameName))) { + // If there is a gridNode with the same name, reuse position + pos = gridNode.pos; + // Add data node to list of nodes in the grid node. + gridNode.nodes.push(node); + } + else { + // If it is a new grid node, increment position. + pos = posIterator++; + } + // Add new grid node to map. + if (!mapOfPosToGridNode[pos]) { + mapOfPosToGridNode[pos] = gridNode = { + depth: parentGridNode ? parentGridNode.depth + 1 : 0, + name: name, + nodes: [node], + children: [], + pos: pos + }; + // If not root, then add name to categories. + if (pos !== -1) { + categories.push(name); + } + // Add name to list of children. + if (isObject(parentGridNode, true)) { + parentGridNode.children.push(gridNode); + } + } + // Add data node to map + if (isString(node.id)) { + mapOfIdToNode[node.id] = node; + } + // If one of the points are collapsed, then start the grid node + // in collapsed state. + if (gridNode && + data.collapsed === true) { + gridNode.collapsed = true; + } + // Assign pos to data node + node.pos = pos; + } + }; + var updateYValuesAndTickPos = function (map, numberOfSeries) { + var setValues = function (gridNode, start, result) { + var nodes = gridNode.nodes, end = start + (start === -1 ? 0 : numberOfSeries - 1), diff = (end - start) / 2, padding = 0.5, pos = start + diff; + nodes.forEach(function (node) { + var data = node.data; + if (isObject(data, true)) { + // Update point + data.y = start + (data.seriesIndex || 0); + // Remove the property once used + delete data.seriesIndex; + } + node.pos = pos; + }); + result[pos] = gridNode; + gridNode.pos = pos; + gridNode.tickmarkOffset = diff + padding; + gridNode.collapseStart = end + padding; + gridNode.children.forEach(function (child) { + setValues(child, end + 1, result); + end = (child.collapseEnd || 0) - padding; + }); + // Set collapseEnd to the end of the last child node. + gridNode.collapseEnd = end + padding; + return result; + }; + return setValues(map['-1'], -1, {}); + }; + // Create tree from data + tree = Tree.getTree(data, treeParams); + // Update y values of data, and set calculate tick positions. + mapOfPosToGridNode = updateYValuesAndTickPos(mapOfPosToGridNode, numberOfSeries); + // Return the resulting data. + return { + categories: categories, + mapOfIdToNode: mapOfIdToNode, + mapOfPosToGridNode: mapOfPosToGridNode, + collapsedNodes: collapsedNodes, + tree: tree + }; + } + /** + * Builds the tree of categories and calculates its positions. + * @private + * @param {object} e Event object + * @param {object} e.target The chart instance which the event was fired on. + * @param {object[]} e.target.axes The axes of the chart. + */ + function onBeforeRender(e) { + var chart = e.target, axes = chart.axes; + axes.filter(function (axis) { + return axis.options.type === 'treegrid'; + }).forEach(function (axis) { + var options = axis.options || {}, labelOptions = options.labels, uniqueNames = options.uniqueNames, numberOfSeries = 0, isDirty, data, treeGrid; + // Check whether any of series is rendering for the first time, + // visibility has changed, or its data is dirty, + // and only then update. #10570, #10580 + // Also check if mapOfPosToGridNode exists. #10887 + isDirty = (!axis.treeGrid.mapOfPosToGridNode || + axis.series.some(function (series) { + return !series.hasRendered || + series.isDirtyData || + series.isDirty; + })); + if (isDirty) { + // Concatenate data from all series assigned to this axis. + data = axis.series.reduce(function (arr, s) { + if (s.visible) { + // Push all data to array + (s.options.data || []).forEach(function (data) { + if (isObject(data, true)) { + // Set series index on data. Removed again + // after use. + data.seriesIndex = numberOfSeries; + arr.push(data); + } + }); + // Increment series index + if (uniqueNames === true) { + numberOfSeries++; + } + } + return arr; + }, []); + // setScale is fired after all the series is initialized, + // which is an ideal time to update the axis.categories. + treeGrid = getTreeGridFromData(data, uniqueNames || false, (uniqueNames === true) ? numberOfSeries : 1); + // Assign values to the axis. + axis.categories = treeGrid.categories; + axis.treeGrid.mapOfPosToGridNode = treeGrid.mapOfPosToGridNode; + axis.hasNames = true; + axis.treeGrid.tree = treeGrid.tree; + // Update yData now that we have calculated the y values + axis.series.forEach(function (series) { + var data = (series.options.data || []).map(function (d) { + return isObject(d, true) ? merge(d) : d; + }); + // Avoid destroying points when series is not visible + if (series.visible) { + series.setData(data, false); + } + }); + // Calculate the label options for each level in the tree. + axis.treeGrid.mapOptionsToLevel = + TreeSeriesMixin.getLevelOptions({ + defaults: labelOptions, + from: 1, + levels: labelOptions && labelOptions.levels, + to: axis.treeGrid.tree && axis.treeGrid.tree.height + }); + // Setting initial collapsed nodes + if (e.type === 'beforeRender') { + axis.treeGrid.collapsedNodes = treeGrid.collapsedNodes; + } + } + }); + } + /** + * Generates a tick for initial positioning. + * + * @private + * @function Highcharts.GridAxis#generateTick + * + * @param {Function} proceed + * The original generateTick function. + * + * @param {number} pos + * The tick position in axis values. + */ + function wrapGenerateTick(proceed, pos) { + var axis = this, mapOptionsToLevel = axis.treeGrid.mapOptionsToLevel || {}, isTreeGrid = axis.options.type === 'treegrid', ticks = axis.ticks; + var tick = ticks[pos], levelOptions, options, gridNode; + if (isTreeGrid && + axis.treeGrid.mapOfPosToGridNode) { + gridNode = axis.treeGrid.mapOfPosToGridNode[pos]; + levelOptions = mapOptionsToLevel[gridNode.depth]; + if (levelOptions) { + options = { + labels: levelOptions + }; + } + if (!tick) { + ticks[pos] = tick = + new Tick(axis, pos, void 0, void 0, { + category: gridNode.name, + tickmarkOffset: gridNode.tickmarkOffset, + options: options + }); + } + else { + // update labels depending on tick interval + tick.parameters.category = gridNode.name; + tick.options = options; + tick.addLabel(); + } + } + else { + proceed.apply(axis, Array.prototype.slice.call(arguments, 1)); + } + } + /** + * Override to add indentation to axis.maxLabelDimensions. + * + * @private + * @function Highcharts.GridAxis#getMaxLabelDimensions + * + * @param {Function} proceed + * The original function + */ + function wrapGetMaxLabelDimensions(proceed) { + var axis = this, options = axis.options, labelOptions = options && options.labels, indentation = (labelOptions && isNumber(labelOptions.indentation) ? + labelOptions.indentation : + 0), retVal = proceed.apply(axis, Array.prototype.slice.call(arguments, 1)), isTreeGrid = axis.options.type === 'treegrid'; + var treeDepth; + if (isTreeGrid && axis.treeGrid.mapOfPosToGridNode) { + treeDepth = axis.treeGrid.mapOfPosToGridNode[-1].height || 0; + retVal.width += indentation * (treeDepth - 1); + } + return retVal; + } + /** + * @private + */ + function wrapInit(proceed, chart, userOptions) { + var axis = this, isTreeGrid = userOptions.type === 'treegrid'; + if (!axis.treeGrid) { + axis.treeGrid = new Additions(axis); + } + // Set default and forced options for TreeGrid + if (isTreeGrid) { + // Add event for updating the categories of a treegrid. + // NOTE Preferably these events should be set on the axis. + addEvent(chart, 'beforeRender', onBeforeRender); + addEvent(chart, 'beforeRedraw', onBeforeRender); + // Add new collapsed nodes on addseries + addEvent(chart, 'addSeries', function (e) { + if (e.options.data) { + var treeGrid = getTreeGridFromData(e.options.data, userOptions.uniqueNames || false, 1); + axis.treeGrid.collapsedNodes = (axis.treeGrid.collapsedNodes || []).concat(treeGrid.collapsedNodes); + } + }); + // Collapse all nodes in axis.treegrid.collapsednodes + // where collapsed equals true. + addEvent(axis, 'foundExtremes', function () { + if (axis.treeGrid.collapsedNodes) { + axis.treeGrid.collapsedNodes.forEach(function (node) { + var breaks = axis.treeGrid.collapse(node); + if (axis.brokenAxis) { + axis.brokenAxis.setBreaks(breaks, false); + // remove the node from the axis collapsedNodes + if (axis.treeGrid.collapsedNodes) { + axis.treeGrid.collapsedNodes = axis.treeGrid.collapsedNodes.filter(function (n) { + return node.collapseStart !== n.collapseStart || + node.collapseEnd !== n.collapseEnd; + }); + } + } + }); + } + }); + userOptions = merge({ + // Default options + grid: { + enabled: true + }, + // TODO: add support for align in treegrid. + labels: { + align: 'left', + /** + * Set options on specific levels in a tree grid axis. Takes + * precedence over labels options. + * + * @sample {gantt} gantt/treegrid-axis/labels-levels + * Levels on TreeGrid Labels + * + * @type {Array<*>} + * @product gantt + * @apioption yAxis.labels.levels + * + * @private + */ + levels: [{ + /** + * Specify the level which the options within this object + * applies to. + * + * @type {number} + * @product gantt + * @apioption yAxis.labels.levels.level + * + * @private + */ + level: void 0 + }, { + level: 1, + /** + * @type {Highcharts.CSSObject} + * @product gantt + * @apioption yAxis.labels.levels.style + * + * @private + */ + style: { + /** @ignore-option */ + fontWeight: 'bold' + } + }], + /** + * The symbol for the collapse and expand icon in a + * treegrid. + * + * @product gantt + * @optionparent yAxis.labels.symbol + * + * @private + */ + symbol: { + /** + * The symbol type. Points to a definition function in + * the `Highcharts.Renderer.symbols` collection. + * + * @type {Highcharts.SymbolKeyValue} + * + * @private + */ + type: 'triangle', + x: -5, + y: -5, + height: 10, + width: 10, + padding: 5 + } + }, + uniqueNames: false + }, userOptions, { + // Forced options + reversed: true, + // grid.columns is not supported in treegrid + grid: { + columns: void 0 + } + }); + } + // Now apply the original function with the original arguments, + // which are sliced off this function's arguments + proceed.apply(axis, [chart, userOptions]); + if (isTreeGrid) { + axis.hasNames = true; + axis.options.showLastLabel = true; + } + } + /** + * Set the tick positions, tickInterval, axis min and max. + * + * @private + * @function Highcharts.GridAxis#setTickInterval + * + * @param {Function} proceed + * The original setTickInterval function. + */ + function wrapSetTickInterval(proceed) { + var axis = this, options = axis.options, isTreeGrid = options.type === 'treegrid'; + if (isTreeGrid) { + axis.min = pick(axis.userMin, options.min, axis.dataMin); + axis.max = pick(axis.userMax, options.max, axis.dataMax); + fireEvent(axis, 'foundExtremes'); + // setAxisTranslation modifies the min and max according to + // axis breaks. + axis.setAxisTranslation(true); + axis.tickmarkOffset = 0.5; + axis.tickInterval = 1; + axis.tickPositions = axis.treeGrid.mapOfPosToGridNode ? + axis.treeGrid.getTickPositions() : + []; + } + else { + proceed.apply(axis, Array.prototype.slice.call(arguments, 1)); + } + } + /* * + * + * Classes + * + * */ + /** + * @private + * @class + */ + var Additions = /** @class */ (function () { + /* * + * + * Constructors + * + * */ + /** + * @private + */ + function Additions(axis) { + this.axis = axis; + } + /* * + * + * Functions + * + * */ + /** + * Calculates the new axis breaks to collapse a node. + * + * @private + * + * @param {Highcharts.Axis} axis + * The axis to check against. + * + * @param {Highcharts.GridNode} node + * The node to collapse. + * + * @param {number} pos + * The tick position to collapse. + * + * @return {Array} + * Returns an array of the new breaks for the axis. + */ + Additions.prototype.collapse = function (node) { + var axis = this.axis, breaks = (axis.options.breaks || []), obj = getBreakFromNode(node, axis.max); + breaks.push(obj); + return breaks; + }; + /** + * Calculates the new axis breaks to expand a node. + * + * @private + * + * @param {Highcharts.Axis} axis + * The axis to check against. + * + * @param {Highcharts.GridNode} node + * The node to expand. + * + * @param {number} pos + * The tick position to expand. + * + * @return {Array} + * Returns an array of the new breaks for the axis. + */ + Additions.prototype.expand = function (node) { + var axis = this.axis, breaks = (axis.options.breaks || []), obj = getBreakFromNode(node, axis.max); + // Remove the break from the axis breaks array. + return breaks.reduce(function (arr, b) { + if (b.to !== obj.to || b.from !== obj.from) { + arr.push(b); + } + return arr; + }, []); + }; + /** + * Creates a list of positions for the ticks on the axis. Filters out + * positions that are outside min and max, or is inside an axis break. + * + * @private + * + * @return {Array} + * List of positions. + */ + Additions.prototype.getTickPositions = function () { + var axis = this.axis; + return Object.keys(axis.treeGrid.mapOfPosToGridNode || {}).reduce(function (arr, key) { + var pos = +key; + if (axis.min <= pos && + axis.max >= pos && + !(axis.brokenAxis && axis.brokenAxis.isInAnyBreak(pos))) { + arr.push(pos); + } + return arr; + }, []); + }; + /** + * Check if a node is collapsed. + * + * @private + * + * @param {Highcharts.Axis} axis + * The axis to check against. + * + * @param {object} node + * The node to check if is collapsed. + * + * @param {number} pos + * The tick position to collapse. + * + * @return {boolean} + * Returns true if collapsed, false if expanded. + */ + Additions.prototype.isCollapsed = function (node) { + var axis = this.axis, breaks = (axis.options.breaks || []), obj = getBreakFromNode(node, axis.max); + return breaks.some(function (b) { + return b.from === obj.from && b.to === obj.to; + }); + }; + /** + * Calculates the new axis breaks after toggling the collapse/expand + * state of a node. If it is collapsed it will be expanded, and if it is + * exapended it will be collapsed. + * + * @private + * + * @param {Highcharts.Axis} axis + * The axis to check against. + * + * @param {Highcharts.GridNode} node + * The node to toggle. + * + * @return {Array} + * Returns an array of the new breaks for the axis. + */ + Additions.prototype.toggleCollapse = function (node) { + return (this.isCollapsed(node) ? + this.expand(node) : + this.collapse(node)); + }; + return Additions; + }()); + TreeGridAxis.Additions = Additions; + })(TreeGridAxis || (TreeGridAxis = {})); + // Make utility functions available for testing. + Axis.prototype.utils = { + getNode: Tree.getNode + }; + TreeGridAxis.compose(Axis); + + return TreeGridAxis; + }); + _registerModule(_modules, 'masters/modules/treegrid.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/treemap.js b/librerias/gantt/code/modules/treemap.js new file mode 100644 index 0000000..668fd2e --- /dev/null +++ b/librerias/gantt/code/modules/treemap.js @@ -0,0 +1,42 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2014-2019 Highsoft AS + Authors: Jon Arild Nygard / Oystein Moseng + + License: www.highcharts.com/license +*/ +(function(c){"object"===typeof module&&module.exports?(c["default"]=c,module.exports=c):"function"===typeof define&&define.amd?define("highcharts/modules/treemap",["highcharts"],function(w){c(w);c.Highcharts=w;return c}):c("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(c){function w(c,d,x,l){c.hasOwnProperty(d)||(c[d]=l.apply(null,x))}c=c?c._modules:{};w(c,"mixins/tree-series.js",[c["parts/Color.js"],c["parts/Utilities.js"]],function(c,d){var x=d.extend,l=d.isArray,n=d.isNumber,q=d.isObject, +h=d.merge,v=d.pick;return{getColor:function(f,k){var r=k.index,d=k.mapOptionsToLevel,h=k.parentColor,q=k.parentColorIndex,C=k.series,A=k.colors,x=k.siblings,p=C.points,l=C.chart.options.chart,y;if(f){p=p[f.i];f=d[f.level]||{};if(d=p&&f.colorByPoint){var t=p.index%(A?A.length:l.colorCount);var n=A&&A[t]}if(!C.chart.styledMode){A=p&&p.options.color;l=f&&f.color;if(y=h)y=(y=f&&f.colorVariation)&&"brightness"===y.key?c.parse(h).brighten(r/x*y.to).get():h;y=v(A,l,n,y,C.color)}var w=v(p&&p.options.colorIndex, +f&&f.colorIndex,t,q,k.colorIndex)}return{color:y,colorIndex:w}},getLevelOptions:function(f){var k=null;if(q(f)){k={};var d=n(f.from)?f.from:1;var c=f.levels;var z={};var v=q(f.defaults)?f.defaults:{};l(c)&&(z=c.reduce(function(k,c){if(q(c)&&n(c.level)){var f=h({},c);var r="boolean"===typeof f.levelIsConstant?f.levelIsConstant:v.levelIsConstant;delete f.levelIsConstant;delete f.level;c=c.level+(r?0:d-1);q(k[c])?x(k[c],f):k[c]=f}return k},{}));c=n(f.to)?f.to:1;for(f=0;f<=c;f++)k[f]=h({},v,q(z[f])?z[f]: +{})}return k},setTreeValues:function J(k,c){var d=c.before,h=c.idRoot,r=c.mapIdToNode[h],l=c.points[k.i],q=l&&l.options||{},p=0,n=[];x(k,{levelDynamic:k.level-(("boolean"===typeof c.levelIsConstant?c.levelIsConstant:1)?0:r.level),name:v(l&&l.name,""),visible:h===k.id||("boolean"===typeof c.visible?c.visible:!1)});"function"===typeof d&&(k=d(k,c));k.children.forEach(function(d,h){var l=x({},c);x(l,{index:h,siblings:k.children.length,visible:k.visible});d=J(d,l);n.push(d);d.visible&&(p+=d.val)});k.visible= +0{point.name}: {point.value}
    "},ignoreHiddenPoint:!0,layoutAlgorithm:"sliceAndDice",layoutStartingDirection:"vertical",alternateStartingDirection:!1,levelIsConstant:!0,drillUpButton:{position:{align:"right",x:-10,y:10}}, +traverseUpButton:{position:{align:"right",x:-10,y:10}},borderColor:"#e6e6e6",borderWidth:1,colorKey:"colorValue",opacity:.15,states:{hover:{borderColor:"#999999",brightness:H.heatmap?0:.1,halo:!1,opacity:.75,shadow:!1}}},{pointArrayMap:["value"],directTouch:!0,optionalAxis:"colorAxis",getSymbol:h,parallelArrays:["x","y","value","colorValue"],colorKey:"colorValue",trackerGroups:["group","dataLabelsGroup"],getListOfParents:function(a,b){a=C(a)?a:[];var e=C(b)?b:[];b=a.reduce(function(a,b,e){b=t(b.parent, +"");"undefined"===typeof a[b]&&(a[b]=[]);a[b].push(e);return a},{"":[]});P(b,function(a,b,c){""!==b&&-1===e.indexOf(b)&&(a.forEach(function(a){c[""].push(a)}),delete c[b])});return b},getTree:function(){var a=this.data.map(function(a){return a.id});a=this.getListOfParents(this.data,a);this.nodeMap=[];return this.buildNode("",-1,0,a,null)},hasData:function(){return!!this.processedXData.length},init:function(a,b){var e=c.colorMapSeriesMixin;e&&(this.colorAttribs=e.colorAttribs);this.eventsToUnbind.push(f(this, +"setOptions",function(a){a=a.userOptions;r(a.allowDrillToNode)&&!r(a.allowTraversingTree)&&(a.allowTraversingTree=a.allowDrillToNode,delete a.allowDrillToNode);r(a.drillUpButton)&&!r(a.traverseUpButton)&&(a.traverseUpButton=a.drillUpButton,delete a.drillUpButton)}));F.prototype.init.call(this,a,b);this.options.allowTraversingTree&&this.eventsToUnbind.push(f(this,"click",this.onClickDrillToNode))},buildNode:function(a,b,e,c,g){var B=this,m=[],u=B.points[b],d=0,D;(c[a]||[]).forEach(function(b){D=B.buildNode(B.points[b].id, +b,e+1,c,a);d=Math.max(D.height+1,d);m.push(D)});b={id:a,i:b,children:m,height:d,level:e,parent:g,visible:!1};B.nodeMap[b.id]=b;u&&(u.node=b);return b},setTreeValues:function(a){var b=this,e=b.options,c=b.nodeMap[b.rootNode];e="boolean"===typeof e.levelIsConstant?e.levelIsConstant:!0;var g=0,B=[],m=b.points[a.i];a.children.forEach(function(a){a=b.setTreeValues(a);B.push(a);a.ignore||(g+=a.val)});M(B,function(a,b){return a.sortIndex-b.sortIndex});var d=t(m&&m.options.value,g);m&&(m.value=d);z(a,{children:B, +childrenTotal:g,ignore:!(t(m&&m.visible,!0)&&0k.lP.lR&&g.algorithmCalcPoints(a,!1,k,c,f);h===l&&g.algorithmCalcPoints(a,!0,k,c,f);h+=1});return c},algorithmFill:function(a,b,e){var c=[],g,d=b.direction,f=b.x,h=b.y, +k=b.width,l=b.height,q,n,p,r;e.forEach(function(e){g=e.val/b.val*b.height*b.width;q=f;n=h;0===d?(r=l,p=g/r,k-=p,f+=p):(p=k,r=g/p,l-=r,h+=r);c.push({x:q,y:n,width:p,height:r});a&&(d=1-d)});return c},strip:function(a,b){return this.algorithmLowAspectRatio(!1,a,b)},squarified:function(a,b){return this.algorithmLowAspectRatio(!0,a,b)},sliceAndDice:function(a,b){return this.algorithmFill(!0,a,b)},stripes:function(a,b){return this.algorithmFill(!1,a,b)},translate:function(){var a=this,b=a.options,c=Q(a); +F.prototype.translate.call(a);var d=a.tree=a.getTree();var g=a.nodeMap[c];a.renderTraverseUpButton(c);a.mapOptionsToLevel=O({from:g.level+1,levels:b.levels,to:d.height,defaults:{levelIsConstant:a.options.levelIsConstant,colorByPoint:b.colorByPoint}});""===c||g&&g.children.length||(a.setRootNode("",!1),c=a.rootNode,g=a.nodeMap[c]);G(a.nodeMap[a.rootNode],function(b){var c=!1,e=b.parent;b.visible=!0;if(e||""===e)c=a.nodeMap[e];return c});G(a.nodeMap[a.rootNode].children,function(a){var b=!1;a.forEach(function(a){a.visible= +!0;a.children.length&&(b=(b||[]).concat(a.children))});return b});a.setTreeValues(d);a.axisRatio=a.xAxis.len/a.yAxis.len;a.nodeMap[""].pointValues=c={x:0,y:0,width:100,height:100};a.nodeMap[""].values=c=E(c,{width:c.width*a.axisRatio,direction:"vertical"===b.layoutStartingDirection?0:1,val:d.val});a.calculateChildrenAreas(d,c);a.colorAxis||b.colorByPoint||a.setColorRecursive(a.tree);b.allowTraversingTree&&(b=g.pointValues,a.xAxis.setExtremes(b.x,b.x+b.width,!1),a.yAxis.setExtremes(b.y,b.y+b.height, +!1),a.xAxis.setScale(),a.yAxis.setScale());a.setPointValues()},drawDataLabels:function(){var a=this,b=a.mapOptionsToLevel,c,d;a.points.filter(function(a){return a.node.visible}).forEach(function(e){d=b[e.node.level];c={style:{}};e.node.isLeaf||(c.enabled=!1);d&&d.dataLabels&&(c=E(c,d.dataLabels),a._hasPointLabels=!0);e.shapeArgs&&(c.style.width=e.shapeArgs.width,e.dataLabel&&e.dataLabel.css({width:e.shapeArgs.width+"px"}));e.dlOptions=E(c,e.options.dataLabels)});F.prototype.drawDataLabels.call(this)}, +alignDataLabel:function(a,b,c){var e=c.style;!r(e.textOverflow)&&b.text&&b.getBBox().width>b.text.textWidth&&b.css({textOverflow:"ellipsis",width:e.width+="px"});H.column.prototype.alignDataLabel.apply(this,arguments);a.dataLabel&&a.dataLabel.attr({zIndex:(a.node.zIndex||0)+1})},pointAttribs:function(a,b){var c=L(this.mapOptionsToLevel)?this.mapOptionsToLevel:{},d=a&&c[a.node.level]||{};c=this.options;var g=b&&c.states[b]||{},f=a&&a.getClassName()||"";a={stroke:a&&a.borderColor||d.borderColor||g.borderColor|| +c.borderColor,"stroke-width":t(a&&a.borderWidth,d.borderWidth,g.borderWidth,c.borderWidth),dashstyle:a&&a.borderDashStyle||d.borderDashStyle||g.borderDashStyle||c.borderDashStyle,fill:a&&a.color||this.color};-1!==f.indexOf("highcharts-above-level")?(a.fill="none",a["stroke-width"]=0):-1!==f.indexOf("highcharts-internal-node-interactive")?(b=t(g.opacity,c.opacity),a.fill=v(a.fill).setOpacity(b).get(),a.cursor="pointer"):-1!==f.indexOf("highcharts-internal-node")?a.fill="none":b&&(a.fill=v(a.fill).brighten(g.brightness).get()); +return a},drawPoints:function(){var a=this,b=a.chart,c=b.renderer,d=b.styledMode,f=a.options,h=d?{}:f.shadow,k=f.borderRadius,l=b.pointCount 0 || tree.visible; + // Set the values + value = pick(optionsPoint.value, childrenTotal); + extend(tree, { + children: children, + childrenTotal: childrenTotal, + isLeaf: tree.visible && !childrenTotal, + val: value + }); + return tree; + }; + /** + * @private + */ + var getColor = function getColor(node, options) { + var index = options.index, mapOptionsToLevel = options.mapOptionsToLevel, parentColor = options.parentColor, parentColorIndex = options.parentColorIndex, series = options.series, colors = options.colors, siblings = options.siblings, points = series.points, getColorByPoint, chartOptionsChart = series.chart.options.chart, point, level, colorByPoint, colorIndexByPoint, color, colorIndex; + /** + * @private + */ + function variation(color) { + var colorVariation = level && level.colorVariation; + if (colorVariation) { + if (colorVariation.key === 'brightness') { + return Color.parse(color).brighten(colorVariation.to * (index / siblings)).get(); + } + } + return color; + } + if (node) { + point = points[node.i]; + level = mapOptionsToLevel[node.level] || {}; + getColorByPoint = point && level.colorByPoint; + if (getColorByPoint) { + colorIndexByPoint = point.index % (colors ? + colors.length : + chartOptionsChart.colorCount); + colorByPoint = colors && colors[colorIndexByPoint]; + } + // Select either point color, level color or inherited color. + if (!series.chart.styledMode) { + color = pick(point && point.options.color, level && level.color, colorByPoint, parentColor && variation(parentColor), series.color); + } + colorIndex = pick(point && point.options.colorIndex, level && level.colorIndex, colorIndexByPoint, parentColorIndex, options.colorIndex); + } + return { + color: color, + colorIndex: colorIndex + }; + }; + /** + * Creates a map from level number to its given options. + * + * @private + * @function getLevelOptions + * @param {object} params + * Object containing parameters. + * - `defaults` Object containing default options. The default options + * are merged with the userOptions to get the final options for a + * specific level. + * - `from` The lowest level number. + * - `levels` User options from series.levels. + * - `to` The highest level number. + * @return {Highcharts.Dictionary|null} + * Returns a map from level number to its given options. + */ + var getLevelOptions = function getLevelOptions(params) { + var result = null, defaults, converted, i, from, to, levels; + if (isObject(params)) { + result = {}; + from = isNumber(params.from) ? params.from : 1; + levels = params.levels; + converted = {}; + defaults = isObject(params.defaults) ? params.defaults : {}; + if (isArray(levels)) { + converted = levels.reduce(function (obj, item) { + var level, levelIsConstant, options; + if (isObject(item) && isNumber(item.level)) { + options = merge({}, item); + levelIsConstant = (isBoolean(options.levelIsConstant) ? + options.levelIsConstant : + defaults.levelIsConstant); + // Delete redundant properties. + delete options.levelIsConstant; + delete options.level; + // Calculate which level these options apply to. + level = item.level + (levelIsConstant ? 0 : from - 1); + if (isObject(obj[level])) { + extend(obj[level], options); + } + else { + obj[level] = options; + } + } + return obj; + }, {}); + } + to = isNumber(params.to) ? params.to : 1; + for (i = 0; i <= to; i++) { + result[i] = merge({}, defaults, isObject(converted[i]) ? converted[i] : {}); + } + } + return result; + }; + /** + * Update the rootId property on the series. Also makes sure that it is + * accessible to exporting. + * + * @private + * @function updateRootId + * + * @param {object} series + * The series to operate on. + * + * @return {string} + * Returns the resulting rootId after update. + */ + var updateRootId = function (series) { + var rootId, options; + if (isObject(series)) { + // Get the series options. + options = isObject(series.options) ? series.options : {}; + // Calculate the rootId. + rootId = pick(series.rootNode, options.rootId, ''); + // Set rootId on series.userOptions to pick it up in exporting. + if (isObject(series.userOptions)) { + series.userOptions.rootId = rootId; + } + // Set rootId on series to pick it up on next update. + series.rootNode = rootId; + } + return rootId; + }; + var result = { + getColor: getColor, + getLevelOptions: getLevelOptions, + setTreeValues: setTreeValues, + updateRootId: updateRootId + }; + + return result; + }); + _registerModule(_modules, 'mixins/draw-point.js', [], function () { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var isFn = function (x) { + return typeof x === 'function'; + }; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Handles the drawing of a component. + * Can be used for any type of component that reserves the graphic property, and + * provides a shouldDraw on its context. + * + * @private + * @function draw + * @param {DrawPointParams} params + * Parameters. + * + * @todo add type checking. + * @todo export this function to enable usage + */ + var draw = function draw(params) { + var _a; + var component = this, graphic = component.graphic, animatableAttribs = params.animatableAttribs, onComplete = params.onComplete, css = params.css, renderer = params.renderer, animation = (_a = component.series) === null || _a === void 0 ? void 0 : _a.options.animation; + if (component.shouldDraw()) { + if (!graphic) { + component.graphic = graphic = + renderer[params.shapeType](params.shapeArgs) + .add(params.group); + } + graphic + .css(css) + .attr(params.attribs) + .animate(animatableAttribs, params.isNew ? false : animation, onComplete); + } + else if (graphic) { + var destroy = function () { + component.graphic = graphic = graphic.destroy(); + if (isFn(onComplete)) { + onComplete(); + } + }; + // animate only runs complete callback if something was animated. + if (Object.keys(animatableAttribs).length) { + graphic.animate(animatableAttribs, void 0, function () { + destroy(); + }); + } + else { + destroy(); + } + } + }; + /** + * An extended version of draw customized for points. + * It calls additional methods that is expected when rendering a point. + * @private + * @param {Highcharts.Dictionary} params Parameters + */ + var drawPoint = function drawPoint(params) { + var point = this, attribs = params.attribs = params.attribs || {}; + // Assigning class in dot notation does go well in IE8 + // eslint-disable-next-line dot-notation + attribs['class'] = point.getClassName(); + // Call draw to render component + draw.call(point, params); + }; + + return drawPoint; + }); + _registerModule(_modules, 'modules/treemap.src.js', [_modules['parts/Globals.js'], _modules['mixins/tree-series.js'], _modules['mixins/draw-point.js'], _modules['parts/Color.js'], _modules['mixins/legend-symbol.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js']], function (H, mixinTreeSeries, drawPoint, Color, LegendSymbolMixin, Point, U) { + /* * + * + * (c) 2014-2020 Highsoft AS + * + * Authors: Jon Arild Nygard / Oystein Moseng + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var color = Color.parse; + var addEvent = U.addEvent, correctFloat = U.correctFloat, defined = U.defined, error = U.error, extend = U.extend, fireEvent = U.fireEvent, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, isString = U.isString, merge = U.merge, objectEach = U.objectEach, pick = U.pick, seriesType = U.seriesType, stableSort = U.stableSort; + /* eslint-disable no-invalid-this */ + var AXIS_MAX = 100; + var seriesTypes = H.seriesTypes, noop = H.noop, getColor = mixinTreeSeries.getColor, getLevelOptions = mixinTreeSeries.getLevelOptions, + // @todo Similar to eachObject, this function is likely redundant + isBoolean = function (x) { + return typeof x === 'boolean'; + }, Series = H.Series, + // @todo Similar to recursive, this function is likely redundant + eachObject = function (list, func, context) { + context = context || this; + objectEach(list, function (val, key) { + func.call(context, val, key, list); + }); + }, + // @todo find correct name for this function. + // @todo Similar to reduce, this function is likely redundant + recursive = function (item, func, context) { + var next; + context = context || this; + next = func.call(context, item); + if (next !== false) { + recursive(next, func, context); + } + }, updateRootId = mixinTreeSeries.updateRootId, treemapAxisDefaultValues = false; + /* eslint-enable no-invalid-this */ + /** + * @private + * @class + * @name Highcharts.seriesTypes.treemap + * + * @augments Highcharts.Series + */ + seriesType('treemap', 'scatter' + /** + * A treemap displays hierarchical data using nested rectangles. The data + * can be laid out in varying ways depending on options. + * + * @sample highcharts/demo/treemap-large-dataset/ + * Treemap + * + * @extends plotOptions.scatter + * @excluding dragDrop, marker, jitter, dataSorting + * @product highcharts + * @requires modules/treemap + * @optionparent plotOptions.treemap + */ + , { + /** + * When enabled the user can click on a point which is a parent and + * zoom in on its children. Deprecated and replaced by + * [allowTraversingTree](#plotOptions.treemap.allowTraversingTree). + * + * @sample {highcharts} highcharts/plotoptions/treemap-allowdrilltonode/ + * Enabled + * + * @deprecated + * @type {boolean} + * @default false + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.allowDrillToNode + */ + /** + * When enabled the user can click on a point which is a parent and + * zoom in on its children. + * + * @sample {highcharts} highcharts/plotoptions/treemap-allowtraversingtree/ + * Enabled + * + * @since 7.0.3 + * @product highcharts + */ + allowTraversingTree: false, + animationLimit: 250, + /** + * When the series contains less points than the crop threshold, all + * points are drawn, event if the points fall outside the visible plot + * area at the current zoom. The advantage of drawing all points + * (including markers and columns), is that animation is performed on + * updates. On the other hand, when the series contains more points than + * the crop threshold, the series data is cropped to only contain points + * that fall within the plot area. The advantage of cropping away + * invisible points is to increase performance on large series. + * + * @type {number} + * @default 300 + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.cropThreshold + */ + /** + * Fires on a request for change of root node for the tree, before the + * update is made. An event object is passed to the function, containing + * additional properties `newRootId`, `previousRootId`, `redraw` and + * `trigger`. + * + * @type {function} + * @default undefined + * @sample {highcharts} highcharts/plotoptions/treemap-events-setrootnode/ + * Alert update information on setRootNode event. + * @since 7.0.3 + * @product highcharts + * @apioption plotOptions.treemap.events.setRootNode + */ + /** + * This option decides if the user can interact with the parent nodes + * or just the leaf nodes. When this option is undefined, it will be + * true by default. However when allowTraversingTree is true, then it + * will be false by default. + * + * @sample {highcharts} highcharts/plotoptions/treemap-interactbyleaf-false/ + * False + * @sample {highcharts} highcharts/plotoptions/treemap-interactbyleaf-true-and-allowtraversingtree/ + * InteractByLeaf and allowTraversingTree is true + * + * @type {boolean} + * @since 4.1.2 + * @product highcharts + * @apioption plotOptions.treemap.interactByLeaf + */ + /** + * The sort index of the point inside the treemap level. + * + * @sample {highcharts} highcharts/plotoptions/treemap-sortindex/ + * Sort by years + * + * @type {number} + * @since 4.1.10 + * @product highcharts + * @apioption plotOptions.treemap.sortIndex + */ + /** + * A series specific or series type specific color set to apply instead + * of the global [colors](#colors) when + * [colorByPoint](#plotOptions.treemap.colorByPoint) is true. + * + * @type {Array} + * @since 3.0 + * @product highcharts + * @apioption plotOptions.treemap.colors + */ + /** + * Whether to display this series type or specific series item in the + * legend. + */ + showInLegend: false, + /** + * @ignore-option + */ + marker: false, + /** + * When using automatic point colors pulled from the `options.colors` + * collection, this option determines whether the chart should receive + * one color per series or one color per point. + * + * @see [series colors](#plotOptions.treemap.colors) + * + * @since 2.0 + * @product highcharts + * @apioption plotOptions.treemap.colorByPoint + */ + colorByPoint: false, + /** + * @since 4.1.0 + */ + dataLabels: { + defer: false, + enabled: true, + formatter: function () { + var point = this && this.point ? + this.point : + {}, name = isString(point.name) ? point.name : ''; + return name; + }, + inside: true, + verticalAlign: 'middle' + }, + tooltip: { + headerFormat: '', + pointFormat: '{point.name}: {point.value}
    ' + }, + /** + * Whether to ignore hidden points when the layout algorithm runs. + * If `false`, hidden points will leave open spaces. + * + * @since 5.0.8 + */ + ignoreHiddenPoint: true, + /** + * This option decides which algorithm is used for setting position + * and dimensions of the points. + * + * @see [How to write your own algorithm](https://www.highcharts.com/docs/chart-and-series-types/treemap) + * + * @sample {highcharts} highcharts/plotoptions/treemap-layoutalgorithm-sliceanddice/ + * SliceAndDice by default + * @sample {highcharts} highcharts/plotoptions/treemap-layoutalgorithm-stripes/ + * Stripes + * @sample {highcharts} highcharts/plotoptions/treemap-layoutalgorithm-squarified/ + * Squarified + * @sample {highcharts} highcharts/plotoptions/treemap-layoutalgorithm-strip/ + * Strip + * + * @since 4.1.0 + * @validvalue ["sliceAndDice", "stripes", "squarified", "strip"] + */ + layoutAlgorithm: 'sliceAndDice', + /** + * Defines which direction the layout algorithm will start drawing. + * + * @since 4.1.0 + * @validvalue ["vertical", "horizontal"] + */ + layoutStartingDirection: 'vertical', + /** + * Enabling this option will make the treemap alternate the drawing + * direction between vertical and horizontal. The next levels starting + * direction will always be the opposite of the previous. + * + * @sample {highcharts} highcharts/plotoptions/treemap-alternatestartingdirection-true/ + * Enabled + * + * @since 4.1.0 + */ + alternateStartingDirection: false, + /** + * Used together with the levels and allowTraversingTree options. When + * set to false the first level visible to be level one, which is + * dynamic when traversing the tree. Otherwise the level will be the + * same as the tree structure. + * + * @since 4.1.0 + */ + levelIsConstant: true, + /** + * Options for the button appearing when drilling down in a treemap. + * Deprecated and replaced by + * [traverseUpButton](#plotOptions.treemap.traverseUpButton). + * + * @deprecated + */ + drillUpButton: { + /** + * The position of the button. + * + * @deprecated + */ + position: { + /** + * Vertical alignment of the button. + * + * @deprecated + * @type {Highcharts.VerticalAlignValue} + * @default top + * @product highcharts + * @apioption plotOptions.treemap.drillUpButton.position.verticalAlign + */ + /** + * Horizontal alignment of the button. + * + * @deprecated + * @type {Highcharts.AlignValue} + */ + align: 'right', + /** + * Horizontal offset of the button. + * + * @deprecated + */ + x: -10, + /** + * Vertical offset of the button. + * + * @deprecated + */ + y: 10 + } + }, + /** + * Options for the button appearing when traversing down in a treemap. + */ + traverseUpButton: { + /** + * The position of the button. + */ + position: { + /** + * Vertical alignment of the button. + * + * @type {Highcharts.VerticalAlignValue} + * @default top + * @product highcharts + * @apioption plotOptions.treemap.traverseUpButton.position.verticalAlign + */ + /** + * Horizontal alignment of the button. + * + * @type {Highcharts.AlignValue} + */ + align: 'right', + /** + * Horizontal offset of the button. + */ + x: -10, + /** + * Vertical offset of the button. + */ + y: 10 + } + }, + /** + * Set options on specific levels. Takes precedence over series options, + * but not point options. + * + * @sample {highcharts} highcharts/plotoptions/treemap-levels/ + * Styling dataLabels and borders + * @sample {highcharts} highcharts/demo/treemap-with-levels/ + * Different layoutAlgorithm + * + * @type {Array<*>} + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.levels + */ + /** + * Can set a `borderColor` on all points which lies on the same level. + * + * @type {Highcharts.ColorString} + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.borderColor + */ + /** + * Set the dash style of the border of all the point which lies on the + * level. See + * [plotOptions.scatter.dashStyle](#plotoptions.scatter.dashstyle) + * for possible options. + * + * @type {Highcharts.DashStyleValue} + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.borderDashStyle + */ + /** + * Can set the borderWidth on all points which lies on the same level. + * + * @type {number} + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.borderWidth + */ + /** + * Can set a color on all points which lies on the same level. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.color + */ + /** + * A configuration object to define how the color of a child varies from + * the parent's color. The variation is distributed among the children + * of node. For example when setting brightness, the brightness change + * will range from the parent's original brightness on the first child, + * to the amount set in the `to` setting on the last node. This allows a + * gradient-like color scheme that sets children out from each other + * while highlighting the grouping on treemaps and sectors on sunburst + * charts. + * + * @sample highcharts/demo/sunburst/ + * Sunburst with color variation + * + * @since 6.0.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.colorVariation + */ + /** + * The key of a color variation. Currently supports `brightness` only. + * + * @type {string} + * @since 6.0.0 + * @product highcharts + * @validvalue ["brightness"] + * @apioption plotOptions.treemap.levels.colorVariation.key + */ + /** + * The ending value of a color variation. The last sibling will receive + * this value. + * + * @type {number} + * @since 6.0.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.colorVariation.to + */ + /** + * Can set the options of dataLabels on each point which lies on the + * level. + * [plotOptions.treemap.dataLabels](#plotOptions.treemap.dataLabels) for + * possible values. + * + * @extends plotOptions.treemap.dataLabels + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.dataLabels + */ + /** + * Can set the layoutAlgorithm option on a specific level. + * + * @type {string} + * @since 4.1.0 + * @product highcharts + * @validvalue ["sliceAndDice", "stripes", "squarified", "strip"] + * @apioption plotOptions.treemap.levels.layoutAlgorithm + */ + /** + * Can set the layoutStartingDirection option on a specific level. + * + * @type {string} + * @since 4.1.0 + * @product highcharts + * @validvalue ["vertical", "horizontal"] + * @apioption plotOptions.treemap.levels.layoutStartingDirection + */ + /** + * Decides which level takes effect from the options set in the levels + * object. + * + * @sample {highcharts} highcharts/plotoptions/treemap-levels/ + * Styling of both levels + * + * @type {number} + * @since 4.1.0 + * @product highcharts + * @apioption plotOptions.treemap.levels.level + */ + // Presentational options + /** + * The color of the border surrounding each tree map item. + * + * @type {Highcharts.ColorString} + */ + borderColor: '#e6e6e6', + /** + * The width of the border surrounding each tree map item. + */ + borderWidth: 1, + colorKey: 'colorValue', + /** + * The opacity of a point in treemap. When a point has children, the + * visibility of the children is determined by the opacity. + * + * @since 4.2.4 + */ + opacity: 0.15, + /** + * A wrapper object for all the series options in specific states. + * + * @extends plotOptions.heatmap.states + */ + states: { + /** + * Options for the hovered series + * + * @extends plotOptions.heatmap.states.hover + * @excluding halo + */ + hover: { + /** + * The border color for the hovered state. + */ + borderColor: '#999999', + /** + * Brightness for the hovered point. Defaults to 0 if the + * heatmap series is loaded first, otherwise 0.1. + * + * @type {number} + * @default undefined + */ + brightness: seriesTypes.heatmap ? 0 : 0.1, + /** + * @extends plotOptions.heatmap.states.hover.halo + */ + halo: false, + /** + * The opacity of a point in treemap. When a point has children, + * the visibility of the children is determined by the opacity. + * + * @since 4.2.4 + */ + opacity: 0.75, + /** + * The shadow option for hovered state. + */ + shadow: false + } + } + // Prototype members + }, { + pointArrayMap: ['value'], + directTouch: true, + optionalAxis: 'colorAxis', + getSymbol: noop, + parallelArrays: ['x', 'y', 'value', 'colorValue'], + colorKey: 'colorValue', + trackerGroups: ['group', 'dataLabelsGroup'], + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Creates an object map from parent id to childrens index. + * + * @private + * @function Highcharts.Series#getListOfParents + * + * @param {Highcharts.SeriesTreemapDataOptions} [data] + * List of points set in options. + * + * @param {Array} [existingIds] + * List of all point ids. + * + * @return {object} + * Map from parent id to children index in data. + */ + getListOfParents: function (data, existingIds) { + var arr = isArray(data) ? data : [], ids = isArray(existingIds) ? existingIds : [], listOfParents = arr.reduce(function (prev, curr, i) { + var parent = pick(curr.parent, ''); + if (typeof prev[parent] === 'undefined') { + prev[parent] = []; + } + prev[parent].push(i); + return prev; + }, { + '': [] // Root of tree + }); + // If parent does not exist, hoist parent to root of tree. + eachObject(listOfParents, function (children, parent, list) { + if ((parent !== '') && (ids.indexOf(parent) === -1)) { + children.forEach(function (child) { + list[''].push(child); + }); + delete list[parent]; + } + }); + return listOfParents; + }, + // Creates a tree structured object from the series points + getTree: function () { + var series = this, allIds = this.data.map(function (d) { + return d.id; + }), parentList = series.getListOfParents(this.data, allIds); + series.nodeMap = []; + return series.buildNode('', -1, 0, parentList, null); + }, + // Define hasData function for non-cartesian series. + // Returns true if the series has points at all. + hasData: function () { + return !!this.processedXData.length; // != 0 + }, + init: function (chart, options) { + var series = this, colorMapSeriesMixin = H.colorMapSeriesMixin; + // If color series logic is loaded, add some properties + if (colorMapSeriesMixin) { + this.colorAttribs = colorMapSeriesMixin.colorAttribs; + } + // Handle deprecated options. + series.eventsToUnbind.push(addEvent(series, 'setOptions', function (event) { + var options = event.userOptions; + if (defined(options.allowDrillToNode) && + !defined(options.allowTraversingTree)) { + options.allowTraversingTree = options.allowDrillToNode; + delete options.allowDrillToNode; + } + if (defined(options.drillUpButton) && + !defined(options.traverseUpButton)) { + options.traverseUpButton = options.drillUpButton; + delete options.drillUpButton; + } + })); + Series.prototype.init.call(series, chart, options); + if (series.options.allowTraversingTree) { + series.eventsToUnbind.push(addEvent(series, 'click', series.onClickDrillToNode)); + } + }, + buildNode: function (id, i, level, list, parent) { + var series = this, children = [], point = series.points[i], height = 0, node, child; + // Actions + ((list[id] || [])).forEach(function (i) { + child = series.buildNode(series.points[i].id, i, (level + 1), list, id); + height = Math.max(child.height + 1, height); + children.push(child); + }); + node = { + id: id, + i: i, + children: children, + height: height, + level: level, + parent: parent, + visible: false // @todo move this to better location + }; + series.nodeMap[node.id] = node; + if (point) { + point.node = node; + } + return node; + }, + setTreeValues: function (tree) { + var series = this, options = series.options, idRoot = series.rootNode, mapIdToNode = series.nodeMap, nodeRoot = mapIdToNode[idRoot], levelIsConstant = (isBoolean(options.levelIsConstant) ? + options.levelIsConstant : + true), childrenTotal = 0, children = [], val, point = series.points[tree.i]; + // First give the children some values + tree.children.forEach(function (child) { + child = series.setTreeValues(child); + children.push(child); + if (!child.ignore) { + childrenTotal += child.val; + } + }); + // Sort the children + stableSort(children, function (a, b) { + return a.sortIndex - b.sortIndex; + }); + // Set the values + val = pick(point && point.options.value, childrenTotal); + if (point) { + point.value = val; + } + extend(tree, { + children: children, + childrenTotal: childrenTotal, + // Ignore this node if point is not visible + ignore: !(pick(point && point.visible, true) && (val > 0)), + isLeaf: tree.visible && !childrenTotal, + levelDynamic: (tree.level - (levelIsConstant ? 0 : nodeRoot.level)), + name: pick(point && point.name, ''), + sortIndex: pick(point && point.sortIndex, -val), + val: val + }); + return tree; + }, + /** + * Recursive function which calculates the area for all children of a + * node. + * + * @private + * @function Highcharts.Series#calculateChildrenAreas + * + * @param {object} node + * The node which is parent to the children. + * + * @param {object} area + * The rectangular area of the parent. + */ + calculateChildrenAreas: function (parent, area) { + var series = this, options = series.options, mapOptionsToLevel = series.mapOptionsToLevel, level = mapOptionsToLevel[parent.level + 1], algorithm = pick((series[(level && level.layoutAlgorithm)] && + level.layoutAlgorithm), options.layoutAlgorithm), alternate = options.alternateStartingDirection, childrenValues = [], children; + // Collect all children which should be included + children = parent.children.filter(function (n) { + return !n.ignore; + }); + if (level && level.layoutStartingDirection) { + area.direction = level.layoutStartingDirection === 'vertical' ? + 0 : + 1; + } + childrenValues = series[algorithm](area, children); + children.forEach(function (child, index) { + var values = childrenValues[index]; + child.values = merge(values, { + val: child.childrenTotal, + direction: (alternate ? 1 - area.direction : area.direction) + }); + child.pointValues = merge(values, { + x: (values.x / series.axisRatio), + // Flip y-values to avoid visual regression with csvCoord in + // Axis.translate at setPointValues. #12488 + y: AXIS_MAX - values.y - values.height, + width: (values.width / series.axisRatio) + }); + // If node has children, then call method recursively + if (child.children.length) { + series.calculateChildrenAreas(child, child.values); + } + }); + }, + setPointValues: function () { + var series = this; + var points = series.points, xAxis = series.xAxis, yAxis = series.yAxis; + var styledMode = series.chart.styledMode; + // Get the crisp correction in classic mode. For this to work in + // styled mode, we would need to first add the shape (without x, + // y, width and height), then read the rendered stroke width + // using point.graphic.strokeWidth(), then modify and apply the + // shapeArgs. This applies also to column series, but the + // downside is performance and code complexity. + var getCrispCorrection = function (point) { return (styledMode ? + 0 : + ((series.pointAttribs(point)['stroke-width'] || 0) % 2) / 2); }; + points.forEach(function (point) { + var _a = point.node, values = _a.pointValues, visible = _a.visible; + // Points which is ignored, have no values. + if (values && visible) { + var height = values.height, width = values.width, x = values.x, y = values.y; + var crispCorr = getCrispCorrection(point); + var x1 = Math.round(xAxis.toPixels(x, true)) - crispCorr; + var x2 = Math.round(xAxis.toPixels(x + width, true)) - crispCorr; + var y1 = Math.round(yAxis.toPixels(y, true)) - crispCorr; + var y2 = Math.round(yAxis.toPixels(y + height, true)) - crispCorr; + // Set point values + point.shapeArgs = { + x: Math.min(x1, x2), + y: Math.min(y1, y2), + width: Math.abs(x2 - x1), + height: Math.abs(y2 - y1) + }; + point.plotX = + point.shapeArgs.x + (point.shapeArgs.width / 2); + point.plotY = + point.shapeArgs.y + (point.shapeArgs.height / 2); + } + else { + // Reset visibility + delete point.plotX; + delete point.plotY; + } + }); + }, + // Set the node's color recursively, from the parent down. + setColorRecursive: function (node, parentColor, colorIndex, index, siblings) { + var series = this, chart = series && series.chart, colors = chart && chart.options && chart.options.colors, colorInfo, point; + if (node) { + colorInfo = getColor(node, { + colors: colors, + index: index, + mapOptionsToLevel: series.mapOptionsToLevel, + parentColor: parentColor, + parentColorIndex: colorIndex, + series: series, + siblings: siblings + }); + point = series.points[node.i]; + if (point) { + point.color = colorInfo.color; + point.colorIndex = colorInfo.colorIndex; + } + // Do it all again with the children + (node.children || []).forEach(function (child, i) { + series.setColorRecursive(child, colorInfo.color, colorInfo.colorIndex, i, node.children.length); + }); + } + }, + algorithmGroup: function (h, w, d, p) { + this.height = h; + this.width = w; + this.plot = p; + this.direction = d; + this.startDirection = d; + this.total = 0; + this.nW = 0; + this.lW = 0; + this.nH = 0; + this.lH = 0; + this.elArr = []; + this.lP = { + total: 0, + lH: 0, + nH: 0, + lW: 0, + nW: 0, + nR: 0, + lR: 0, + aspectRatio: function (w, h) { + return Math.max((w / h), (h / w)); + } + }; + this.addElement = function (el) { + this.lP.total = this.elArr[this.elArr.length - 1]; + this.total = this.total + el; + if (this.direction === 0) { + // Calculate last point old aspect ratio + this.lW = this.nW; + this.lP.lH = this.lP.total / this.lW; + this.lP.lR = this.lP.aspectRatio(this.lW, this.lP.lH); + // Calculate last point new aspect ratio + this.nW = this.total / this.height; + this.lP.nH = this.lP.total / this.nW; + this.lP.nR = this.lP.aspectRatio(this.nW, this.lP.nH); + } + else { + // Calculate last point old aspect ratio + this.lH = this.nH; + this.lP.lW = this.lP.total / this.lH; + this.lP.lR = this.lP.aspectRatio(this.lP.lW, this.lH); + // Calculate last point new aspect ratio + this.nH = this.total / this.width; + this.lP.nW = this.lP.total / this.nH; + this.lP.nR = this.lP.aspectRatio(this.lP.nW, this.nH); + } + this.elArr.push(el); + }; + this.reset = function () { + this.nW = 0; + this.lW = 0; + this.elArr = []; + this.total = 0; + }; + }, + algorithmCalcPoints: function (directionChange, last, group, childrenArea) { + var pX, pY, pW, pH, gW = group.lW, gH = group.lH, plot = group.plot, keep, i = 0, end = group.elArr.length - 1; + if (last) { + gW = group.nW; + gH = group.nH; + } + else { + keep = group.elArr[group.elArr.length - 1]; + } + group.elArr.forEach(function (p) { + if (last || (i < end)) { + if (group.direction === 0) { + pX = plot.x; + pY = plot.y; + pW = gW; + pH = p / pW; + } + else { + pX = plot.x; + pY = plot.y; + pH = gH; + pW = p / pH; + } + childrenArea.push({ + x: pX, + y: pY, + width: pW, + height: correctFloat(pH) + }); + if (group.direction === 0) { + plot.y = plot.y + pH; + } + else { + plot.x = plot.x + pW; + } + } + i = i + 1; + }); + // Reset variables + group.reset(); + if (group.direction === 0) { + group.width = group.width - gW; + } + else { + group.height = group.height - gH; + } + plot.y = plot.parent.y + (plot.parent.height - group.height); + plot.x = plot.parent.x + (plot.parent.width - group.width); + if (directionChange) { + group.direction = 1 - group.direction; + } + // If not last, then add uncalculated element + if (!last) { + group.addElement(keep); + } + }, + algorithmLowAspectRatio: function (directionChange, parent, children) { + var childrenArea = [], series = this, pTot, plot = { + x: parent.x, + y: parent.y, + parent: parent + }, direction = parent.direction, i = 0, end = children.length - 1, group = new this.algorithmGroup(// eslint-disable-line new-cap + parent.height, parent.width, direction, plot); + // Loop through and calculate all areas + children.forEach(function (child) { + pTot = + (parent.width * parent.height) * (child.val / parent.val); + group.addElement(pTot); + if (group.lP.nR > group.lP.lR) { + series.algorithmCalcPoints(directionChange, false, group, childrenArea, plot // @todo no supported + ); + } + // If last child, then calculate all remaining areas + if (i === end) { + series.algorithmCalcPoints(directionChange, true, group, childrenArea, plot // @todo not supported + ); + } + i = i + 1; + }); + return childrenArea; + }, + algorithmFill: function (directionChange, parent, children) { + var childrenArea = [], pTot, direction = parent.direction, x = parent.x, y = parent.y, width = parent.width, height = parent.height, pX, pY, pW, pH; + children.forEach(function (child) { + pTot = + (parent.width * parent.height) * (child.val / parent.val); + pX = x; + pY = y; + if (direction === 0) { + pH = height; + pW = pTot / pH; + width = width - pW; + x = x + pW; + } + else { + pW = width; + pH = pTot / pW; + height = height - pH; + y = y + pH; + } + childrenArea.push({ + x: pX, + y: pY, + width: pW, + height: pH + }); + if (directionChange) { + direction = 1 - direction; + } + }); + return childrenArea; + }, + strip: function (parent, children) { + return this.algorithmLowAspectRatio(false, parent, children); + }, + squarified: function (parent, children) { + return this.algorithmLowAspectRatio(true, parent, children); + }, + sliceAndDice: function (parent, children) { + return this.algorithmFill(true, parent, children); + }, + stripes: function (parent, children) { + return this.algorithmFill(false, parent, children); + }, + translate: function () { + var series = this, options = series.options, + // NOTE: updateRootId modifies series. + rootId = updateRootId(series), rootNode, pointValues, seriesArea, tree, val; + // Call prototype function + Series.prototype.translate.call(series); + // @todo Only if series.isDirtyData is true + tree = series.tree = series.getTree(); + rootNode = series.nodeMap[rootId]; + series.renderTraverseUpButton(rootId); + series.mapOptionsToLevel = getLevelOptions({ + from: rootNode.level + 1, + levels: options.levels, + to: tree.height, + defaults: { + levelIsConstant: series.options.levelIsConstant, + colorByPoint: options.colorByPoint + } + }); + if (rootId !== '' && + (!rootNode || !rootNode.children.length)) { + series.setRootNode('', false); + rootId = series.rootNode; + rootNode = series.nodeMap[rootId]; + } + // Parents of the root node is by default visible + recursive(series.nodeMap[series.rootNode], function (node) { + var next = false, p = node.parent; + node.visible = true; + if (p || p === '') { + next = series.nodeMap[p]; + } + return next; + }); + // Children of the root node is by default visible + recursive(series.nodeMap[series.rootNode].children, function (children) { + var next = false; + children.forEach(function (child) { + child.visible = true; + if (child.children.length) { + next = (next || []).concat(child.children); + } + }); + return next; + }); + series.setTreeValues(tree); + // Calculate plotting values. + series.axisRatio = (series.xAxis.len / series.yAxis.len); + series.nodeMap[''].pointValues = pointValues = { + x: 0, + y: 0, + width: AXIS_MAX, + height: AXIS_MAX + }; + series.nodeMap[''].values = seriesArea = merge(pointValues, { + width: (pointValues.width * series.axisRatio), + direction: (options.layoutStartingDirection === 'vertical' ? 0 : 1), + val: tree.val + }); + series.calculateChildrenAreas(tree, seriesArea); + // Logic for point colors + if (!series.colorAxis && + !options.colorByPoint) { + series.setColorRecursive(series.tree); + } + // Update axis extremes according to the root node. + if (options.allowTraversingTree) { + val = rootNode.pointValues; + series.xAxis.setExtremes(val.x, val.x + val.width, false); + series.yAxis.setExtremes(val.y, val.y + val.height, false); + series.xAxis.setScale(); + series.yAxis.setScale(); + } + // Assign values to points. + series.setPointValues(); + }, + /** + * Extend drawDataLabels with logic to handle custom options related to + * the treemap series: + * + * - Points which is not a leaf node, has dataLabels disabled by + * default. + * + * - Options set on series.levels is merged in. + * + * - Width of the dataLabel is set to match the width of the point + * shape. + * + * @private + * @function Highcharts.Series#drawDataLabels + */ + drawDataLabels: function () { + var series = this, mapOptionsToLevel = series.mapOptionsToLevel, points = series.points.filter(function (n) { + return n.node.visible; + }), options, level; + points.forEach(function (point) { + level = mapOptionsToLevel[point.node.level]; + // Set options to new object to avoid problems with scope + options = { style: {} }; + // If not a leaf, then label should be disabled as default + if (!point.node.isLeaf) { + options.enabled = false; + } + // If options for level exists, include them as well + if (level && level.dataLabels) { + options = merge(options, level.dataLabels); + series._hasPointLabels = true; + } + // Set dataLabel width to the width of the point shape. + if (point.shapeArgs) { + options.style.width = point.shapeArgs.width; + if (point.dataLabel) { + point.dataLabel.css({ + width: point.shapeArgs.width + 'px' + }); + } + } + // Merge custom options with point options + point.dlOptions = merge(options, point.options.dataLabels); + }); + Series.prototype.drawDataLabels.call(this); + }, + // Over the alignment method by setting z index + alignDataLabel: function (point, dataLabel, labelOptions) { + var style = labelOptions.style; + // #8160: Prevent the label from exceeding the point's + // boundaries in treemaps by applying ellipsis overflow. + // The issue was happening when datalabel's text contained a + // long sequence of characters without a whitespace. + if (!defined(style.textOverflow) && + dataLabel.text && + dataLabel.getBBox().width > dataLabel.text.textWidth) { + dataLabel.css({ + textOverflow: 'ellipsis', + // unit (px) is required when useHTML is true + width: style.width += 'px' + }); + } + seriesTypes.column.prototype.alignDataLabel.apply(this, arguments); + if (point.dataLabel) { + // point.node.zIndex could be undefined (#6956) + point.dataLabel.attr({ zIndex: (point.node.zIndex || 0) + 1 }); + } + }, + // Get presentational attributes + pointAttribs: function (point, state) { + var series = this, mapOptionsToLevel = (isObject(series.mapOptionsToLevel) ? + series.mapOptionsToLevel : + {}), level = point && mapOptionsToLevel[point.node.level] || {}, options = this.options, attr, stateOptions = (state && options.states[state]) || {}, className = (point && point.getClassName()) || '', opacity; + // Set attributes by precedence. Point trumps level trumps series. + // Stroke width uses pick because it can be 0. + attr = { + 'stroke': (point && point.borderColor) || + level.borderColor || + stateOptions.borderColor || + options.borderColor, + 'stroke-width': pick(point && point.borderWidth, level.borderWidth, stateOptions.borderWidth, options.borderWidth), + 'dashstyle': (point && point.borderDashStyle) || + level.borderDashStyle || + stateOptions.borderDashStyle || + options.borderDashStyle, + 'fill': (point && point.color) || this.color + }; + // Hide levels above the current view + if (className.indexOf('highcharts-above-level') !== -1) { + attr.fill = 'none'; + attr['stroke-width'] = 0; + // Nodes with children that accept interaction + } + else if (className.indexOf('highcharts-internal-node-interactive') !== -1) { + opacity = pick(stateOptions.opacity, options.opacity); + attr.fill = color(attr.fill).setOpacity(opacity).get(); + attr.cursor = 'pointer'; + // Hide nodes that have children + } + else if (className.indexOf('highcharts-internal-node') !== -1) { + attr.fill = 'none'; + } + else if (state) { + // Brighten and hoist the hover nodes + attr.fill = color(attr.fill) + .brighten(stateOptions.brightness) + .get(); + } + return attr; + }, + // Override drawPoints + drawPoints: function () { + var series = this, chart = series.chart, renderer = chart.renderer, points = series.points, styledMode = chart.styledMode, options = series.options, shadow = styledMode ? {} : options.shadow, borderRadius = options.borderRadius, withinAnimationLimit = chart.pointCount < options.animationLimit, allowTraversingTree = options.allowTraversingTree; + points.forEach(function (point) { + var levelDynamic = point.node.levelDynamic, animate = {}, attr = {}, css = {}, groupKey = 'level-group-' + levelDynamic, hasGraphic = !!point.graphic, shouldAnimate = withinAnimationLimit && hasGraphic, shapeArgs = point.shapeArgs; + // Don't bother with calculate styling if the point is not drawn + if (point.shouldDraw()) { + if (borderRadius) { + attr.r = borderRadius; + } + merge(true, // Extend object + // Which object to extend + shouldAnimate ? animate : attr, + // Add shapeArgs to animate/attr if graphic exists + hasGraphic ? shapeArgs : {}, + // Add style attribs if !styleMode + styledMode ? + {} : + series.pointAttribs(point, (point.selected && 'select'))); + // In styled mode apply point.color. Use CSS, otherwise the + // fill used in the style sheet will take precedence over + // the fill attribute. + if (series.colorAttribs && styledMode) { + // Heatmap is loaded + extend(css, series.colorAttribs(point)); + } + if (!series[groupKey]) { + series[groupKey] = renderer.g(groupKey) + .attr({ + // @todo Set the zIndex based upon the number of + // levels, instead of using 1000 + zIndex: 1000 - levelDynamic + }) + .add(series.group); + series[groupKey].survive = true; + } + } + // Draw the point + point.draw({ + animatableAttribs: animate, + attribs: attr, + css: css, + group: series[groupKey], + renderer: renderer, + shadow: shadow, + shapeArgs: shapeArgs, + shapeType: 'rect' + }); + // If setRootNode is allowed, set a point cursor on clickables & + // add drillId to point + if (allowTraversingTree && point.graphic) { + point.drillId = options.interactByLeaf ? + series.drillToByLeaf(point) : + series.drillToByGroup(point); + } + }); + }, + // Add drilling on the suitable points + onClickDrillToNode: function (event) { + var series = this, point = event.point, drillId = point && point.drillId; + // If a drill id is returned, add click event and cursor. + if (isString(drillId)) { + point.setState(''); // Remove hover + series.setRootNode(drillId, true, { trigger: 'click' }); + } + }, + /** + * Finds the drill id for a parent node. Returns false if point should + * not have a click event. + * + * @private + * @function Highcharts.Series#drillToByGroup + * + * @param {Highcharts.Point} point + * + * @return {boolean|string} + * Drill to id or false when point should not have a click + * event. + */ + drillToByGroup: function (point) { + var series = this, drillId = false; + if ((point.node.level - series.nodeMap[series.rootNode].level) === + 1 && + !point.node.isLeaf) { + drillId = point.id; + } + return drillId; + }, + /** + * Finds the drill id for a leaf node. Returns false if point should not + * have a click event + * + * @private + * @function Highcharts.Series#drillToByLeaf + * + * @param {Highcharts.Point} point + * + * @return {boolean|string} + * Drill to id or false when point should not have a click + * event. + */ + drillToByLeaf: function (point) { + var series = this, drillId = false, nodeParent; + if ((point.node.parent !== series.rootNode) && + point.node.isLeaf) { + nodeParent = point.node; + while (!drillId) { + nodeParent = series.nodeMap[nodeParent.parent]; + if (nodeParent.parent === series.rootNode) { + drillId = nodeParent.id; + } + } + } + return drillId; + }, + drillUp: function () { + var series = this, node = series.nodeMap[series.rootNode]; + if (node && isString(node.parent)) { + series.setRootNode(node.parent, true, { trigger: 'traverseUpButton' }); + } + }, + // TODO remove this function at a suitable version. + drillToNode: function (id, redraw) { + error('WARNING: treemap.drillToNode has been renamed to treemap.' + + 'setRootNode, and will be removed in the next major version.'); + this.setRootNode(id, redraw); + }, + /** + * Sets a new root node for the series. + * + * @private + * @function Highcharts.Series#setRootNode + * + * @param {string} id The id of the new root node. + * @param {boolean} [redraw=true] Wether to redraw the chart or not. + * @param {object} [eventArguments] Arguments to be accessed in + * event handler. + * @param {string} [eventArguments.newRootId] Id of the new root. + * @param {string} [eventArguments.previousRootId] Id of the previous + * root. + * @param {boolean} [eventArguments.redraw] Wether to redraw the + * chart after. + * @param {object} [eventArguments.series] The series to update the root + * of. + * @param {string} [eventArguments.trigger] The action which + * triggered the event. Undefined if the setRootNode is called + * directly. + * @return {void} + * + * @fires Highcharts.Series#event:setRootNode + */ + setRootNode: function (id, redraw, eventArguments) { + var series = this, eventArgs = extend({ + newRootId: id, + previousRootId: series.rootNode, + redraw: pick(redraw, true), + series: series + }, eventArguments); + /** + * The default functionality of the setRootNode event. + * + * @private + * @param {object} args The event arguments. + * @param {string} args.newRootId Id of the new root. + * @param {string} args.previousRootId Id of the previous root. + * @param {boolean} args.redraw Wether to redraw the chart after. + * @param {object} args.series The series to update the root of. + * @param {string} [args.trigger=undefined] The action which + * triggered the event. Undefined if the setRootNode is called + * directly. + * @return {void} + */ + var defaultFn = function (args) { + var series = args.series; + // Store previous and new root ids on the series. + series.idPreviousRoot = args.previousRootId; + series.rootNode = args.newRootId; + // Redraw the chart + series.isDirty = true; // Force redraw + if (args.redraw) { + series.chart.redraw(); + } + }; + // Fire setRootNode event. + fireEvent(series, 'setRootNode', eventArgs, defaultFn); + }, + renderTraverseUpButton: function (rootId) { + var series = this, nodeMap = series.nodeMap, node = nodeMap[rootId], name = node.name, buttonOptions = series.options.traverseUpButton, backText = pick(buttonOptions.text, name, '< Back'), attr, states; + if (rootId === '') { + if (series.drillUpButton) { + series.drillUpButton = + series.drillUpButton.destroy(); + } + } + else if (!this.drillUpButton) { + attr = buttonOptions.theme; + states = attr && attr.states; + this.drillUpButton = this.chart.renderer + .button(backText, null, null, function () { + series.drillUp(); + }, attr, states && states.hover, states && states.select) + .addClass('highcharts-drillup-button') + .attr({ + align: buttonOptions.position.align, + zIndex: 7 + }) + .add() + .align(buttonOptions.position, false, buttonOptions.relativeTo || 'plotBox'); + } + else { + this.drillUpButton.placed = false; + this.drillUpButton.attr({ + text: backText + }) + .align(); + } + }, + buildKDTree: noop, + drawLegendSymbol: LegendSymbolMixin.drawRectangle, + getExtremes: function () { + // Get the extremes from the value data + var _a = Series.prototype.getExtremes + .call(this, this.colorValueData), dataMin = _a.dataMin, dataMax = _a.dataMax; + this.valueMin = dataMin; + this.valueMax = dataMax; + // Get the extremes from the y data + return Series.prototype.getExtremes.call(this); + }, + getExtremesFromAll: true, + /** + * Workaround for `inactive` state. Since `series.opacity` option is + * already reserved, don't use that state at all by disabling + * `inactiveOtherPoints` and not inheriting states by points. + * + * @private + */ + setState: function (state) { + this.options.inactiveOtherPoints = true; + Series.prototype.setState.call(this, state, false); + this.options.inactiveOtherPoints = false; + }, + utils: { + recursive: recursive + } + /* eslint-enable no-invalid-this, valid-jsdoc */ + }, { + draw: drawPoint, + setVisible: seriesTypes.pie.prototype.pointClass.prototype.setVisible, + /* eslint-disable no-invalid-this, valid-jsdoc */ + getClassName: function () { + var className = Point.prototype.getClassName.call(this), series = this.series, options = series.options; + // Above the current level + if (this.node.level <= series.nodeMap[series.rootNode].level) { + className += ' highcharts-above-level'; + } + else if (!this.node.isLeaf && + !pick(options.interactByLeaf, !options.allowTraversingTree)) { + className += ' highcharts-internal-node-interactive'; + } + else if (!this.node.isLeaf) { + className += ' highcharts-internal-node'; + } + return className; + }, + /** + * A tree point is valid if it has han id too, assume it may be a parent + * item. + * + * @private + * @function Highcharts.Point#isValid + */ + isValid: function () { + return this.id || isNumber(this.value); + }, + setState: function (state) { + Point.prototype.setState.call(this, state); + // Graphic does not exist when point is not visible. + if (this.graphic) { + this.graphic.attr({ + zIndex: state === 'hover' ? 1 : 0 + }); + } + }, + shouldDraw: function () { + var point = this; + return isNumber(point.plotY) && point.y !== null; + } + }); + addEvent(H.Series, 'afterBindAxes', function () { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, treeAxis; + if (xAxis && yAxis) { + if (series.is('treemap')) { + treeAxis = { + endOnTick: false, + gridLineWidth: 0, + lineWidth: 0, + min: 0, + dataMin: 0, + minPadding: 0, + max: AXIS_MAX, + dataMax: AXIS_MAX, + maxPadding: 0, + startOnTick: false, + title: null, + tickPositions: [] + }; + extend(yAxis.options, treeAxis); + extend(xAxis.options, treeAxis); + treemapAxisDefaultValues = true; + } + else if (treemapAxisDefaultValues) { + yAxis.setOptions(yAxis.userOptions); + xAxis.setOptions(xAxis.userOptions); + treemapAxisDefaultValues = false; + } + } + }); + /* eslint-enable no-invalid-this, valid-jsdoc */ + /** + * A `treemap` series. If the [type](#series.treemap.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.treemap + * @excluding dataParser, dataURL, stack, dataSorting + * @product highcharts + * @requires modules/treemap + * @apioption series.treemap + */ + /** + * An array of data points for the series. For the `treemap` series + * type, points can be given in the following ways: + * + * 1. An array of numerical values. In this case, the numerical values will be + * interpreted as `value` options. Example: + * ```js + * data: [0, 5, 3, 5] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.treemap.turboThreshold), + * this option is not available. + * ```js + * data: [{ + * value: 9, + * name: "Point2", + * color: "#00FF00" + * }, { + * value: 6, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array} + * @extends series.heatmap.data + * @excluding x, y + * @product highcharts + * @apioption series.treemap.data + */ + /** + * The value of the point, resulting in a relative area of the point + * in the treemap. + * + * @type {number|null} + * @product highcharts + * @apioption series.treemap.data.value + */ + /** + * Serves a purpose only if a `colorAxis` object is defined in the chart + * options. This value will decide which color the point gets from the + * scale of the colorAxis. + * + * @type {number} + * @since 4.1.0 + * @product highcharts + * @apioption series.treemap.data.colorValue + */ + /** + * Only for treemap. Use this option to build a tree structure. The + * value should be the id of the point which is the parent. If no points + * has a matching id, or this option is undefined, then the parent will + * be set to the root. + * + * @sample {highcharts} highcharts/point/parent/ + * Point parent + * @sample {highcharts} highcharts/demo/treemap-with-levels/ + * Example where parent id is not matching + * + * @type {string} + * @since 4.1.0 + * @product highcharts + * @apioption series.treemap.data.parent + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'masters/modules/treemap.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/variable-pie.js b/librerias/gantt/code/modules/variable-pie.js new file mode 100644 index 0000000..e69ca11 --- /dev/null +++ b/librerias/gantt/code/modules/variable-pie.js @@ -0,0 +1,17 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Variable Pie module for Highcharts + + (c) 2010-2019 Grzegorz Blachliski + + License: www.highcharts.com/license +*/ +(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/variable-pie",["highcharts"],function(g){b(g);b.Highcharts=g;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function g(b,d,g,n){b.hasOwnProperty(d)||(b[d]=n.apply(null,g))}b=b?b._modules:{};g(b,"modules/variable-pie.src.js",[b["parts/Globals.js"],b["parts/Utilities.js"]],function(b,d){var g=d.arrayMax,n=d.arrayMin, +w=d.clamp,x=d.fireEvent,p=d.pick;d=d.seriesType;var y=b.seriesTypes.pie.prototype;d("variablepie","pie",{minPointSize:"10%",maxPointSize:"100%",zMin:void 0,zMax:void 0,sizeBy:"area",tooltip:{pointFormat:'\u25cf {series.name}
    Value: {point.y}
    Size: {point.z}
    '}},{pointArrayMap:["y","z"],parallelArrays:["x","y","z"],redraw:function(){this.center=null;y.redraw.call(this,arguments)},zValEval:function(a){return"number"!==typeof a||isNaN(a)?null:!0}, +calculateExtremes:function(){var a=this.chart,b=this.options;var c=this.zData;var d=Math.min(a.plotWidth,a.plotHeight)-2*(b.slicedOffset||0),l={};a=this.center||this.getCenter();["minPointSize","maxPointSize"].forEach(function(a){var c=b[a],k=/%$/.test(c);c=parseInt(c,10);l[a]=k?d*c/100:2*c});this.minPxSize=a[3]+l.minPointSize;this.maxPxSize=w(a[2],a[3]+l.minPointSize,l.maxPointSize);c.length&&(a=p(b.zMin,n(c.filter(this.zValEval))),c=p(b.zMax,g(c.filter(this.zValEval))),this.getRadii(a,c,this.minPxSize, +this.maxPxSize))},getRadii:function(a,b,c,d){var l=0,g=this.zData,q=g.length,k=[],p="radius"!==this.options.sizeBy,u=b-a;for(l;l=b?h=d/2:(h=01.5*Math.PI?e-=2*Math.PI:e<-Math.PI/2&&(e+=2*Math.PI);f.slicedTranslation={translateX:Math.round(Math.cos(e)*d),translateY:Math.round(Math.sin(e)*d)};var v=Math.cos(e)*a[2]/2;var w=Math.sin(e)*a[2]/2;r=Math.cos(e)*m;m*=Math.sin(e);f.tooltipPos=[a[0]+.7*v,a[1]+.7*w];f.half=e<-Math.PI/2||e>Math.PI/2?1:0;f.angle=e;v=Math.min(g,f.labelDistance/5);f.labelPosition={natural:{x:a[0]+r+Math.cos(e)*f.labelDistance,y:a[1]+m+Math.sin(e)*f.labelDistance},"final":{},alignment:f.half?"right": +"left",connectorPosition:{breakAt:{x:a[0]+r+Math.cos(e)*v,y:a[1]+m+Math.sin(e)*v},touchingSliceAt:{x:a[0]+r,y:a[1]+m}}}}x(this,"afterTranslate")}});""});g(b,"masters/modules/variable-pie.src.js",[],function(){})}); +//# sourceMappingURL=variable-pie.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/variable-pie.js.map b/librerias/gantt/code/modules/variable-pie.js.map new file mode 100644 index 0000000..9eebf6a --- /dev/null +++ b/librerias/gantt/code/modules/variable-pie.js.map @@ -0,0 +1 @@ +{"version":3,"file":"variable-pie.js.map","lineCount":16,"mappings":"A;;;;;;;;;AAUC,SAAS,CAACA,CAAD,CAAU,CACM,QAAtB,GAAI,MAAOC,OAAX,EAAkCA,MAAAC,QAAlC,EACIF,CAAA,CAAQ,SAAR,CACA,CADqBA,CACrB,CAAAC,MAAAC,QAAA,CAAiBF,CAFrB,EAG6B,UAAtB,GAAI,MAAOG,OAAX,EAAoCA,MAAAC,IAApC,CACHD,MAAA,CAAO,iCAAP,CAA0C,CAAC,YAAD,CAA1C,CAA0D,QAAS,CAACE,CAAD,CAAa,CAC5EL,CAAA,CAAQK,CAAR,CACAL,EAAAK,WAAA,CAAqBA,CACrB,OAAOL,EAHqE,CAAhF,CADG,CAOHA,CAAA,CAA8B,WAAtB,GAAA,MAAOK,WAAP,CAAoCA,UAApC,CAAiDC,IAAAA,EAAzD,CAXY,CAAnB,CAAA,CAaC,QAAS,CAACD,CAAD,CAAa,CAEpBE,QAASA,EAAe,CAACC,CAAD,CAAMC,CAAN,CAAYC,CAAZ,CAAkBC,CAAlB,CAAsB,CACrCH,CAAAI,eAAA,CAAmBH,CAAnB,CAAL,GACID,CAAA,CAAIC,CAAJ,CADJ,CACgBE,CAAAE,MAAA,CAAS,IAAT,CAAeH,CAAf,CADhB,CAD0C,CAD1CI,CAAAA,CAAWT,CAAA,CAAaA,CAAAS,SAAb,CAAmC,EAMlDP,EAAA,CAAgBO,CAAhB,CAA0B,6BAA1B,CAAyD,CAACA,CAAA,CAAS,kBAAT,CAAD,CAA+BA,CAAA,CAAS,oBAAT,CAA/B,CAAzD,CAAyH,QAAS,CAACC,CAAD,CAAIC,CAAJ,CAAO,CAAA,IAejIC,EAAWD,CAAAC,SAfsH,CAe1GC,EAAWF,CAAAE,SAf+F;AAenFC,EAAQH,CAAAG,MAf2E,CAelEC,EAAYJ,CAAAI,UAfsD,CAezCC,EAAOL,CAAAK,KAAQC,EAAAA,CAAaN,CAAAM,WACxH,KAAIC,EAAWR,CAAAS,YAAAC,IAAAC,UAUfJ,EAAA,CAAW,aAAX,CAA0B,KAA1B,CAiBA,CAaIK,aAAc,KAblB,CAwBIC,aAAc,MAxBlB,CAsCIC,KAAM,IAAK,EAtCf,CAkDIC,KAAM,IAAK,EAlDf,CA+DIC,OAAQ,MA/DZ,CAgEIC,QAAS,CACLC,YAAa,6GADR,CAhEb,CAjBA,CAoFG,CACCC,cAAe,CAAC,GAAD,CAAM,GAAN,CADhB,CAECC,eAAgB,CAAC,GAAD,CAAM,GAAN,CAAW,GAAX,CAFjB,CAKCC,OAAQA,QAAS,EAAG,CAChB,IAAAC,OAAA,CAAc,IACdd,EAAAa,OAAAE,KAAA,CAAqB,IAArB,CAA2BC,SAA3B,CAFgB,CALrB,CAYCC,SAAUA,QAAS,CAACC,CAAD,CAAO,CACtB,MAAoB,QAApB,GAAI,MAAOA,EAAX,EAAiCC,KAAA,CAAMD,CAAN,CAAjC,CAGO,IAHP,CACW,CAAA,CAFW,CAZ3B;AAoBCE,kBAAmBA,QAAS,EAAG,CAAA,IACRC,EAANC,IAAcD,MADA,CAC0EE,EAAxFD,IAAwGE,QAAiFC,KAAAA,EAAzLH,IAAiMG,MADnL,KACiMC,EAAeC,IAAAC,IAAA,CAAtLP,CAAAQ,UAAsL,CAAxJR,CAAAS,WAAwJ,CAAfJ,CAAzE,CAAyEA,EAApEH,CAAAQ,aAAoEL,EAAtC,CAAsCA,CADjM,CAG3BM,EAAW,EAGXC,EAAAA,CALaX,IAKDR,OAAZmB,EALaX,IAKgBY,UAAA,EAC7B,EAAC,cAAD,CAAiB,cAAjB,CAAAC,QAAA,CAAyC,QAAS,CAACC,CAAD,CAAO,CAAA,IACjDC,EAASd,CAAA,CAAca,CAAd,CADwC,CACnBE,EAAY,IAAAC,KAAA,CAAUF,CAAV,CAC9CA,EAAA,CAASG,QAAA,CAASH,CAAT,CAAiB,EAAjB,CACTL,EAAA,CAASI,CAAT,CAAA,CAAiBE,CAAA,CACbZ,CADa,CACEW,CADF,CACW,GADX,CAEJ,CAFI,CAEbA,CALiD,CAAzD,CANaf,KAabmB,UAAA,CAAmBR,CAAA,CAAU,CAAV,CAAnB,CAAkCD,CAAA5B,aAbrBkB,KAcboB,UAAA,CAAmB9C,CAAA,CAAMqC,CAAA,CAAU,CAAV,CAAN,CAAoBA,CAAA,CAAU,CAAV,CAApB,CAAmCD,CAAA5B,aAAnC,CAA0D4B,CAAA3B,aAA1D,CACfoB,EAAAY,OAAJ,GACI/B,CAEA,CAFOR,CAAA,CAAKyB,CAAAjB,KAAL,CAAyBX,CAAA,CAAS8B,CAAAkB,OAAA,CAhBhCrB,IAgB6CL,SAAb,CAAT,CAAzB,CAEP,CADAV,CACA,CADOT,CAAA,CAAKyB,CAAAhB,KAAL,CAAyBb,CAAA,CAAS+B,CAAAkB,OAAA,CAjBhCrB,IAiB6CL,SAAb,CAAT,CAAzB,CACP,CAAA,IAAA2B,SAAA,CAActC,CAAd,CAAoBC,CAApB,CAlBSe,IAkBiBmB,UAA1B;AAlBSnB,IAkBmCoB,UAA5C,CAHJ,CAhB2B,CApBhC,CAkECE,SAAUA,QAAS,CAACtC,CAAD,CAAOC,CAAP,CAAasC,CAAb,CAAsBC,CAAtB,CAA+B,CAAA,IAC1CC,EAAI,CADsC,CAC9BtB,EAAQ,IAAAA,MADsB,CACVuB,EAAMvB,CAAAY,OADI,CACUY,EAAQ,EADlB,CAC8CC,EAAgC,QAAhCA,GAAd,IAAA1B,QAA2BhB,OAD3D,CACwF2C,EAAS5C,CAAT4C,CAAgB7C,CAEtJ,KAAKyC,CAAL,CAAQA,CAAR,CAAYC,CAAZ,CAAiBD,CAAA,EAAjB,CAAsB,CAGlB,IAAAK,EAAQ,IAAAnC,SAAA,CAAcQ,CAAA,CAAMsB,CAAN,CAAd,CAAA,CAA0BtB,CAAA,CAAMsB,CAAN,CAA1B,CAAqCzC,CACzC8C,EAAJ,EAAa9C,CAAb,CACI+C,CADJ,CACaR,CADb,CACuB,CADvB,CAGSO,CAAJ,EAAa7C,CAAb,CACD8C,CADC,CACQP,CADR,CACkB,CADlB,EAKDQ,CAIA,CAJe,CAAT,CAAAH,CAAA,EAAcC,CAAd,CAAsB9C,CAAtB,EAA8B6C,CAA9B,CAAuC,EAI7C,CAHID,CAGJ,GAFII,CAEJ,CAFU3B,IAAA4B,KAAA,CAAUD,CAAV,CAEV,EAAAD,CAAA,CAAS1B,IAAA6B,KAAA,CAAUX,CAAV,CAAoBS,CAApB,EAA2BR,CAA3B,CAAqCD,CAArC,EAAT,CAA0D,CATzD,CAWLI,EAAAQ,KAAA,CAAWJ,CAAX,CAlBkB,CAoBtB,IAAAJ,MAAA,CAAaA,CAvBiC,CAlEnD,CA8FCS,UAAWA,QAAS,CAACzB,CAAD,CAAY,CAC5B,IAAA0B,eAAA,EAD4B,KAETC,EAAa,CAFJ,CAG5BpC,EADaF,IACHE,QAHkB,CAGFO,EAAeP,CAAAO,aAHb,CAGmC8B,EAAkB9B,CAAlB8B,EAAkCrC,CAAAsC,YAAlCD,EAAyD,CAAzDA,CAHnC,CAGyIE,EAAavC,CAAAuC,WAAbA,EAAmC,CAH5K,CAG+KC,EAAgBrC,IAAAsC,GAAhBD,CAA0B,GAA1BA,EAAiCD,CAAjCC,CAA8C,EAA9CA,CAH/K,CAGkOE,EAAcvC,IAAAsC,GAAdC,CAAwB,GAAxBA,EAA+BpE,CAAA,CAAK0B,CAAA2C,SAAL,CAAuBJ,CAAvB,CAAoC,GAApC,CAA/BG,CAA0E,EAA1EA,CAA+EE,EAAAA,CAAOF,CAAPE,CAAqBJ,CAHtU,KAI5BK,EAFa/C,IAEJ+C,OAJmB,CAMVC,EAAgB9C,CAAA+C,WAAAC,SAA6BC;CAAAA,CAAoBjD,CAAAiD,kBANvD,KAMqFzB,EAAMqB,CAAAhC,OAJ1Gf,KAKb0C,cAAA,CAAuBA,CALV1C,KAMb4C,YAAA,CAAqBA,CANR5C,KAQbF,kBAAA,EAIKa,EAAL,GAZaX,IAaTR,OADJ,CACoBmB,CADpB,CAZaX,IAamBY,UAAA,EADhC,CAIA,KAAKa,CAAL,CAAS,CAAT,CAAYA,CAAZ,CAAgBC,CAAhB,CAAqBD,CAAA,EAArB,CAA0B,CACtB,IAAA2B,EAAQL,CAAA,CAAOtB,CAAP,CACR,KAAA4B,EAlBSrD,IAkBI2B,MAAA,CAAaF,CAAb,CAEb2B,EAAAJ,cAAA,CAAsBxE,CAAA,CAAK4E,CAAAlD,QAAA+C,WAAL,EAClBG,CAAAlD,QAAA+C,WAAAC,SADkB,CACiBF,CADjB,CApBbhD,KAuBTsD,iBAAA,CAA0BjD,IAAAkD,IAAA,CAvBjBvD,IAuB0BsD,iBAAT,EAAoC,CAApC,CAAuCF,CAAAJ,cAAvC,CAE1B,KAAAQ,EAAQd,CAARc,CAAyBlB,CAAzBkB,CAAsCV,CACtC,IAAI,CAACK,CAAL,EAA0BC,CAAAK,QAA1B,CACInB,CAAA,EAAcc,CAAAM,WAAd,CAAiC,GAErC,KAAAC,EAAMjB,CAANiB,CAAuBrB,CAAvBqB,CAAoCb,CAEpCM,EAAAQ,UAAA,CAAkB,KAClBR,EAAAS,UAAA,CAAkB,CACdC,EAAGnD,CAAA,CAAU,CAAV,CADW,CAEdoD,EAAGpD,CAAA,CAAU,CAAV,CAFW,CAGdqD,EAAGX,CAHW,CAIdY,OAAQtD,CAAA,CAAU,CAAV,CAARsD,CAAuB,CAJT,CAKdT,MAAOnD,IAAA6D,MAAA,CArCgCC,GAqChC,CAAWX,CAAX,CAAPA,CArCuCW,GAgCzB,CAMdR,IAAKtD,IAAA6D,MAAA,CAtCkCC,GAsClC;AAAWR,CAAX,CAALA,CAtCuCQ,GAgCzB,CASlBC,EAAA,EAAST,CAAT,CAAeH,CAAf,EAAwB,CACpBY,EAAJ,CAAY,GAAZ,CAAkB/D,IAAAsC,GAAlB,CACIyB,CADJ,EACa,CADb,CACiB/D,IAAAsC,GADjB,CAGSyB,CAHT,CAGiB,CAAC/D,IAAAsC,GAHlB,CAG4B,CAH5B,GAIIyB,CAJJ,EAIa,CAJb,CAIiB/D,IAAAsC,GAJjB,CAOAS,EAAAiB,kBAAA,CAA0B,CACtBC,WAAYjE,IAAA6D,MAAA,CAAW7D,IAAAkE,IAAA,CAASH,CAAT,CAAX,CAA6B3D,CAA7B,CADU,CAEtB+D,WAAYnE,IAAA6D,MAAA,CAAW7D,IAAAoE,IAAA,CAASL,CAAT,CAAX,CAA6B3D,CAA7B,CAFU,CAK1B,KAAAiE,EAAUrE,IAAAkE,IAAA,CAASH,CAAT,CAAVM,CAA4B/D,CAAA,CAAU,CAAV,CAA5B+D,CAA2C,CAC3C,KAAAC,EAAUtE,IAAAoE,IAAA,CAASL,CAAT,CAAVO,CAA4BhE,CAAA,CAAU,CAAV,CAA5BgE,CAA2C,CAC3CC,EAAA,CAAevE,IAAAkE,IAAA,CAASH,CAAT,CAAf,CAAiCf,CACjCwB,EAAA,EAAexE,IAAAoE,IAAA,CAASL,CAAT,CACfhB,EAAA0B,WAAA,CAAmB,CACfnE,CAAA,CAAU,CAAV,CADe,CACU,EADV,CACA+D,CADA,CAEf/D,CAAA,CAAU,CAAV,CAFe,CAEU,EAFV,CAEAgE,CAFA,CAInBvB,EAAA2B,KAAA,CAAaX,CAAA,CAAQ,CAAC/D,IAAAsC,GAAT,CAAmB,CAAnB,EAAwByB,CAAxB,CAAgC/D,IAAAsC,GAAhC,CAA0C,CAA1C,CACT,CADS,CAET,CACJS,EAAAgB,MAAA,CAAcA,CAIdY,EAAA,CAAuB3E,IAAAC,IAAA,CAASiC,CAAT,CAA0Ba,CAAAJ,cAA1B,CAAgD,CAAhD,CACvBI,EAAA6B,cAAA,CAAsB,CAClBC,QAAS,CAGLpB,EAAGnD,CAAA,CAAU,CAAV,CAAHmD,CAAkBc,CAAlBd,CACIzD,IAAAkE,IAAA,CAASH,CAAT,CADJN,CACsBV,CAAAJ,cAJjB,CAKLe,EAAGpD,CAAA,CAAU,CAAV,CAAHoD,CAAkBc,CAAlBd,CACI1D,IAAAoE,IAAA,CAASL,CAAT,CADJL,CACsBX,CAAAJ,cANjB,CADS,CASlB,QAAS,EATS,CAiBlBmC,UAAW/B,CAAA2B,KAAA,CAAa,OAAb;AAAuB,MAjBhB,CAkBlBK,kBAAmB,CACfC,QAAS,CACLvB,EAAGnD,CAAA,CAAU,CAAV,CAAHmD,CAAkBc,CAAlBd,CACIzD,IAAAkE,IAAA,CAASH,CAAT,CADJN,CACsBkB,CAFjB,CAGLjB,EAAGpD,CAAA,CAAU,CAAV,CAAHoD,CAAkBc,CAAlBd,CACI1D,IAAAoE,IAAA,CAASL,CAAT,CADJL,CACsBiB,CAJjB,CADM,CAOfM,gBAAiB,CACbxB,EAAGnD,CAAA,CAAU,CAAV,CAAHmD,CAAkBc,CADL,CAEbb,EAAGpD,CAAA,CAAU,CAAV,CAAHoD,CAAkBc,CAFL,CAPF,CAlBD,CAtDA,CAsF1BtG,CAAA,CAtGayB,IAsGb,CAAkB,gBAAlB,CAxG4B,CA9FjC,CApFH,CAuVA,GAjXqI,CAAzI,CAoXAtC,EAAA,CAAgBO,CAAhB,CAA0B,qCAA1B,CAAiE,EAAjE,CAAqE,QAAS,EAAG,EAAjF,CA3XoB,CAbvB;","sources":["variable-pie.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","U","arrayMax","arrayMin","clamp","fireEvent","pick","seriesType","pieProto","seriesTypes","pie","prototype","minPointSize","maxPointSize","zMin","zMax","sizeBy","tooltip","pointFormat","pointArrayMap","parallelArrays","redraw","center","call","arguments","zValEval","zVal","isNaN","calculateExtremes","chart","series","seriesOptions","options","zData","smallestSize","Math","min","plotWidth","plotHeight","slicedOffset","extremes","positions","getCenter","forEach","prop","length","isPercent","test","parseInt","minPxSize","maxPxSize","filter","getRadii","minSize","maxSize","i","len","radii","sizeByArea","zRange","value","radius","pos","sqrt","ceil","push","translate","generatePoints","cumulative","connectorOffset","borderWidth","startAngle","startAngleRad","PI","endAngleRad","endAngle","circ","points","labelDistance","dataLabels","distance","ignoreHiddenPoint","point","pointRadii","maxLabelDistance","max","start","visible","percentage","end","shapeType","shapeArgs","x","y","r","innerR","round","precision","angle","slicedTranslation","translateX","cos","translateY","sin","radiusX","radiusY","pointRadiusX","pointRadiusY","tooltipPos","half","finalConnectorOffset","labelPosition","natural","alignment","connectorPosition","breakAt","touchingSliceAt"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/variable-pie.src.js b/librerias/gantt/code/modules/variable-pie.src.js new file mode 100644 index 0000000..cc65454 --- /dev/null +++ b/librerias/gantt/code/modules/variable-pie.src.js @@ -0,0 +1,407 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * Variable Pie module for Highcharts + * + * (c) 2010-2019 Grzegorz Blachliński + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/variable-pie', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'modules/variable-pie.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * Variable Pie module for Highcharts + * + * (c) 2010-2017 Grzegorz Blachliński + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * @typedef {"area"|"radius"} Highcharts.VariablePieSizeByValue + */ + var arrayMax = U.arrayMax, arrayMin = U.arrayMin, clamp = U.clamp, fireEvent = U.fireEvent, pick = U.pick, seriesType = U.seriesType; + var pieProto = H.seriesTypes.pie.prototype; + /** + * The variablepie series type. + * + * @private + * @class + * @name Highcharts.seriesTypes.variablepie + * + * @augments Highcharts.Series + */ + seriesType('variablepie', 'pie', + /** + * A variable pie series is a two dimensional series type, where each point + * renders an Y and Z value. Each point is drawn as a pie slice where the + * size (arc) of the slice relates to the Y value and the radius of pie + * slice relates to the Z value. + * + * @sample {highcharts} highcharts/demo/variable-radius-pie/ + * Variable-radius pie chart + * + * @extends plotOptions.pie + * @excluding dragDrop + * @since 6.0.0 + * @product highcharts + * @requires modules/variable-pie.js + * @optionparent plotOptions.variablepie + */ + { + /** + * The minimum size of the points' radius related to chart's `plotArea`. + * If a number is set, it applies in pixels. + * + * @sample {highcharts} highcharts/variable-radius-pie/min-max-point-size/ + * Example of minPointSize and maxPointSize + * @sample {highcharts} highcharts/variable-radius-pie/min-point-size-100/ + * minPointSize set to 100 + * + * @type {number|string} + * @since 6.0.0 + */ + minPointSize: '10%', + /** + * The maximum size of the points' radius related to chart's `plotArea`. + * If a number is set, it applies in pixels. + * + * @sample {highcharts} highcharts/variable-radius-pie/min-max-point-size/ + * Example of minPointSize and maxPointSize + * + * @type {number|string} + * @since 6.0.0 + */ + maxPointSize: '100%', + /** + * The minimum possible z value for the point's radius calculation. If + * the point's Z value is smaller than zMin, the slice will be drawn + * according to the zMin value. + * + * @sample {highcharts} highcharts/variable-radius-pie/zmin-5/ + * zMin set to 5, smaller z values are treated as 5 + * @sample {highcharts} highcharts/variable-radius-pie/zmin-zmax/ + * Series limited by both zMin and zMax + * + * @type {number} + * @since 6.0.0 + */ + zMin: void 0, + /** + * The maximum possible z value for the point's radius calculation. If + * the point's Z value is bigger than zMax, the slice will be drawn + * according to the zMax value + * + * @sample {highcharts} highcharts/variable-radius-pie/zmin-zmax/ + * Series limited by both zMin and zMax + * + * @type {number} + * @since 6.0.0 + */ + zMax: void 0, + /** + * Whether the pie slice's value should be represented by the area or + * the radius of the slice. Can be either `area` or `radius`. The + * default, `area`, corresponds best to the human perception of the size + * of each pie slice. + * + * @sample {highcharts} highcharts/variable-radius-pie/sizeby/ + * Difference between area and radius sizeBy + * + * @type {Highcharts.VariablePieSizeByValue} + * @since 6.0.0 + */ + sizeBy: 'area', + tooltip: { + pointFormat: '\u25CF {series.name}
    Value: {point.y}
    Size: {point.z}
    ' + } + }, { + pointArrayMap: ['y', 'z'], + parallelArrays: ['x', 'y', 'z'], + // It is needed to null series.center on chart redraw. Probably good + // idea will be to add this option in directly in pie series. + redraw: function () { + this.center = null; + pieProto.redraw.call(this, arguments); + }, + // For arrayMin and arrayMax calculations array shouldn't have + // null/undefined/string values. In this case it is needed to check if + // points Z value is a Number. + zValEval: function (zVal) { + if (typeof zVal === 'number' && !isNaN(zVal)) { + return true; + } + return null; + }, + // Before standard translate method for pie chart it is needed to + // calculate min/max radius of each pie slice based on its Z value. + calculateExtremes: function () { + var series = this, chart = series.chart, plotWidth = chart.plotWidth, plotHeight = chart.plotHeight, seriesOptions = series.options, slicingRoom = 2 * (seriesOptions.slicedOffset || 0), zMin, zMax, zData = series.zData, smallestSize = Math.min(plotWidth, plotHeight) - slicingRoom, + // Min and max size of pie slice: + extremes = {}, + // In pie charts size of a pie is changed to make space for + // dataLabels, then series.center is changing. + positions = series.center || series.getCenter(); + ['minPointSize', 'maxPointSize'].forEach(function (prop) { + var length = seriesOptions[prop], isPercent = /%$/.test(length); + length = parseInt(length, 10); + extremes[prop] = isPercent ? + smallestSize * length / 100 : + length * 2; // Because it should be radius, not diameter. + }); + series.minPxSize = positions[3] + extremes.minPointSize; + series.maxPxSize = clamp(positions[2], positions[3] + extremes.minPointSize, extremes.maxPointSize); + if (zData.length) { + zMin = pick(seriesOptions.zMin, arrayMin(zData.filter(series.zValEval))); + zMax = pick(seriesOptions.zMax, arrayMax(zData.filter(series.zValEval))); + this.getRadii(zMin, zMax, series.minPxSize, series.maxPxSize); + } + }, + /* eslint-disable valid-jsdoc */ + /** + * Finding radius of series points based on their Z value and min/max Z + * value for all series. + * + * @private + * @function Highcharts.Series#getRadii + * + * @param {number} zMin + * Min threshold for Z value. If point's Z value is smaller that + * zMin, point will have the smallest possible radius. + * + * @param {number} zMax + * Max threshold for Z value. If point's Z value is bigger that + * zMax, point will have the biggest possible radius. + * + * @param {number} minSize + * Minimal pixel size possible for radius. + * + * @param {numbner} maxSize + * Minimal pixel size possible for radius. + * + * @return {void} + */ + getRadii: function (zMin, zMax, minSize, maxSize) { + var i = 0, pos, zData = this.zData, len = zData.length, radii = [], options = this.options, sizeByArea = options.sizeBy !== 'radius', zRange = zMax - zMin, value, radius; + // Calculate radius for all pie slice's based on their Z values + for (i; i < len; i++) { + // if zData[i] is null/undefined/string we need to take zMin for + // smallest radius. + value = this.zValEval(zData[i]) ? zData[i] : zMin; + if (value <= zMin) { + radius = minSize / 2; + } + else if (value >= zMax) { + radius = maxSize / 2; + } + else { + // Relative size, a number between 0 and 1 + pos = zRange > 0 ? (value - zMin) / zRange : 0.5; + if (sizeByArea) { + pos = Math.sqrt(pos); + } + radius = Math.ceil(minSize + pos * (maxSize - minSize)) / 2; + } + radii.push(radius); + } + this.radii = radii; + }, + /* eslint-enable valid-jsdoc */ + // Extend translate by updating radius for each pie slice instead of + // using one global radius. + translate: function (positions) { + this.generatePoints(); + var series = this, cumulative = 0, precision = 1000, // issue #172 + options = series.options, slicedOffset = options.slicedOffset, connectorOffset = slicedOffset + (options.borderWidth || 0), finalConnectorOffset, start, end, angle, startAngle = options.startAngle || 0, startAngleRad = Math.PI / 180 * (startAngle - 90), endAngleRad = Math.PI / 180 * (pick(options.endAngle, startAngle + 360) - 90), circ = endAngleRad - startAngleRad, // 2 * Math.PI, + points = series.points, + // the x component of the radius vector for a given point + radiusX, radiusY, labelDistance = options.dataLabels.distance, ignoreHiddenPoint = options.ignoreHiddenPoint, i, len = points.length, point, pointRadii, pointRadiusX, pointRadiusY; + series.startAngleRad = startAngleRad; + series.endAngleRad = endAngleRad; + // Use calculateExtremes to get series.radii array. + series.calculateExtremes(); + // Get positions - either an integer or a percentage string must be + // given. If positions are passed as a parameter, we're in a + // recursive loop for adjusting space for data labels. + if (!positions) { + series.center = positions = series.getCenter(); + } + // Calculate the geometry for each point + for (i = 0; i < len; i++) { + point = points[i]; + pointRadii = series.radii[i]; + // Used for distance calculation for specific point. + point.labelDistance = pick(point.options.dataLabels && + point.options.dataLabels.distance, labelDistance); + // Saved for later dataLabels distance calculation. + series.maxLabelDistance = Math.max(series.maxLabelDistance || 0, point.labelDistance); + // set start and end angle + start = startAngleRad + (cumulative * circ); + if (!ignoreHiddenPoint || point.visible) { + cumulative += point.percentage / 100; + } + end = startAngleRad + (cumulative * circ); + // set the shape + point.shapeType = 'arc'; + point.shapeArgs = { + x: positions[0], + y: positions[1], + r: pointRadii, + innerR: positions[3] / 2, + start: Math.round(start * precision) / precision, + end: Math.round(end * precision) / precision + }; + // The angle must stay within -90 and 270 (#2645) + angle = (end + start) / 2; + if (angle > 1.5 * Math.PI) { + angle -= 2 * Math.PI; + } + else if (angle < -Math.PI / 2) { + angle += 2 * Math.PI; + } + // Center for the sliced out slice + point.slicedTranslation = { + translateX: Math.round(Math.cos(angle) * slicedOffset), + translateY: Math.round(Math.sin(angle) * slicedOffset) + }; + // set the anchor point for tooltips + radiusX = Math.cos(angle) * positions[2] / 2; + radiusY = Math.sin(angle) * positions[2] / 2; + pointRadiusX = Math.cos(angle) * pointRadii; + pointRadiusY = Math.sin(angle) * pointRadii; + point.tooltipPos = [ + positions[0] + radiusX * 0.7, + positions[1] + radiusY * 0.7 + ]; + point.half = angle < -Math.PI / 2 || angle > Math.PI / 2 ? + 1 : + 0; + point.angle = angle; + // Set the anchor point for data labels. Use point.labelDistance + // instead of labelDistance // #1174 + // finalConnectorOffset - not override connectorOffset value. + finalConnectorOffset = Math.min(connectorOffset, point.labelDistance / 5); // #1678 + point.labelPosition = { + natural: { + // initial position of the data label - it's utilized + // for finding the final position for the label + x: positions[0] + pointRadiusX + + Math.cos(angle) * point.labelDistance, + y: positions[1] + pointRadiusY + + Math.sin(angle) * point.labelDistance + }, + 'final': { + // used for generating connector path - + // initialized later in drawDataLabels function + // x: undefined, + // y: undefined + }, + // left - pie on the left side of the data label + // right - pie on the right side of the data label + alignment: point.half ? 'right' : 'left', + connectorPosition: { + breakAt: { + x: positions[0] + pointRadiusX + + Math.cos(angle) * finalConnectorOffset, + y: positions[1] + pointRadiusY + + Math.sin(angle) * finalConnectorOffset + }, + touchingSliceAt: { + x: positions[0] + pointRadiusX, + y: positions[1] + pointRadiusY + } + } + }; + } + fireEvent(series, 'afterTranslate'); + } + }); + /** + * A `variablepie` series. If the [type](#series.variablepie.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.variablepie + * @excluding dataParser, dataURL, stack, xAxis, yAxis, dataSorting + * @product highcharts + * @requires modules/variable-pie.js + * @apioption series.variablepie + */ + /** + * An array of data points for the series. For the `variablepie` series type, + * points can be given in the following ways: + * + * 1. An array of arrays with 2 values. In this case, the numerical values will + * be interpreted as `y, z` options. Example: + * ```js + * data: [ + * [40, 75], + * [50, 50], + * [60, 40] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.variablepie.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * y: 1, + * z: 4, + * name: "Point2", + * color: "#00FF00" + * }, { + * y: 7, + * z: 10, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|*>} + * @extends series.pie.data + * @excluding marker, x + * @product highcharts + * @apioption series.variablepie.data + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'masters/modules/variable-pie.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/variwide.js b/librerias/gantt/code/modules/variwide.js new file mode 100644 index 0000000..566c653 --- /dev/null +++ b/librerias/gantt/code/modules/variwide.js @@ -0,0 +1,17 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Highcharts variwide module + + (c) 2010-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/variwide",["highcharts"],function(f){a(f);a.Highcharts=f;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function f(a,e,f,l){a.hasOwnProperty(e)||(a[e]=l.apply(null,f))}a=a?a._modules:{};f(a,"modules/variwide.src.js",[a["parts/Globals.js"],a["parts/Utilities.js"]],function(a,e){var f=e.addEvent,l=e.isNumber,n=e.pick, +q=e.seriesType;e=e.wrap;var p=a.seriesTypes;q("variwide","column",{pointPadding:0,groupPadding:0},{irregularWidths:!0,pointArrayMap:["y","z"],parallelArrays:["x","y","z"],processData:function(b){this.totalZ=0;this.relZ=[];p.column.prototype.processData.call(this,b);(this.xAxis.reversed?this.zData.slice().reverse():this.zData).forEach(function(b,a){this.relZ[a]=this.totalZ;this.totalZ+=b},this);this.xAxis.categories&&(this.xAxis.variwide=!0,this.xAxis.zData=this.zData)},postTranslate:function(b,a, +h){var g=this.xAxis,c=this.relZ;b=g.reversed?c.length-b:b;var d=g.reversed?-1:1,m=g.len,k=this.totalZ;g=b/c.length*m;var f=(b+d)/c.length*m,e=n(c[b],k)/k*m;c=n(c[b+d],k)/k*m;h&&(h.crosshairWidth=c-e);return e+(a-g)*(c-e)/(f-g)},translate:function(){var b=this.options.crisp,a=this.xAxis;this.options.crisp=!1;p.column.prototype.translate.call(this);this.options.crisp=b;var h=this.chart.inverted,g=this.borderWidth%2/2;this.points.forEach(function(c,b){if(a.variwide){var d=this.postTranslate(b,c.shapeArgs.x, +c);b=this.postTranslate(b,c.shapeArgs.x+c.shapeArgs.width)}else d=c.plotX,b=a.translate(c.x+c.z,0,0,0,1);this.options.crisp&&(d=Math.round(d)-g,b=Math.round(b)-g);c.shapeArgs.x=d;c.shapeArgs.width=Math.max(b-d,1);c.plotX=(d+b)/2;h?c.tooltipPos[1]=a.len-c.shapeArgs.x-c.shapeArgs.width/2:c.tooltipPos[0]=c.shapeArgs.x+c.shapeArgs.width/2},this);this.options.stacking&&this.correctStackLabels()},correctStackLabels:function(){var b=this,a=b.options,h=b.yAxis,g,c,e,f;b.points.forEach(function(d){f=d.x;c= +d.shapeArgs.width;(e=h.stacking.stacks[(b.negStacks&&d.y<(a.startFromThreshold?0:a.threshold)?"-":"")+b.stackKey])&&(g=e[f])&&!d.isNull&&g.setOffset(-(c/2)||0,c||0,void 0,void 0,d.plotX)})}},{isValid:function(){return l(this.y)&&l(this.z)}});a.Tick.prototype.postTranslate=function(b,a,e){var d=this.axis,c=b[a]-d.pos;d.horiz||(c=d.len-c);c=d.series[0].postTranslate(e,c);d.horiz||(c=d.len-c);b[a]=d.pos+c};f(a.Axis,"afterDrawCrosshair",function(b){this.variwide&&this.cross&&this.cross.attr("stroke-width", +b.point&&b.point.crosshairWidth)});f(a.Axis,"afterRender",function(){var b=this;!this.horiz&&this.variwide&&this.chart.labelCollectors.push(function(){return b.tickPositions.filter(function(a){return b.ticks[a].label}).map(function(a,e){a=b.ticks[a].label;a.labelrank=b.zData[e];return a})})});f(a.Tick,"afterGetPosition",function(a){var b=this.axis,e=b.horiz?"x":"y";b.variwide&&(this[e+"Orig"]=a.pos[e],this.postTranslate(a.pos,e,this.pos))});e(a.Tick.prototype,"getLabelPosition",function(a,e,f,g,c, +l,m,k){var b=Array.prototype.slice.call(arguments,1),d=c?"x":"y";this.axis.variwide&&"number"===typeof this[d+"Orig"]&&(b[c?0:1]=this[d+"Orig"]);b=a.apply(this,b);this.axis.variwide&&this.axis.categories&&this.postTranslate(b,d,k);return b});""});f(a,"masters/modules/variwide.src.js",[],function(){})}); +//# sourceMappingURL=variwide.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/variwide.js.map b/librerias/gantt/code/modules/variwide.js.map new file mode 100644 index 0000000..15deb32 --- /dev/null +++ b/librerias/gantt/code/modules/variwide.js.map @@ -0,0 +1 @@ +{"version":3,"file":"variwide.js.map","lineCount":16,"mappings":"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","sources":["variwide.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","U","addEvent","isNumber","pick","seriesType","wrap","seriesTypes","pointPadding","groupPadding","irregularWidths","pointArrayMap","parallelArrays","processData","force","totalZ","relZ","column","prototype","call","forEach","xAxis","reversed","zData","slice","reverse","z","i","categories","variwide","postTranslate","index","x","point","axis","length","goRight","len","linearSlotLeft","linearSlotRight","slotLeft","slotRight","crosshairWidth","translate","crispOption","options","crisp","inverted","chart","borderWidth","points","left","shapeArgs","right","width","plotX","Math","round","max","tooltipPos","stacking","correctStackLabels","series","yAxis","pointStack","pointWidth","stack","xValue","stacks","negStacks","y","startFromThreshold","threshold","stackKey","isNull","setOffset","isValid","Tick","H.Tick.prototype.postTranslate","xy","xOrY","pos","horiz","Axis","e","cross","attr","labelCollectors","push","tickPositions","filter","ticks","label","map","labelrank","proceed","labelOptions","tickmarkOffset","Array","arguments"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/variwide.src.js b/librerias/gantt/code/modules/variwide.src.js new file mode 100644 index 0000000..bb3c1e7 --- /dev/null +++ b/librerias/gantt/code/modules/variwide.src.js @@ -0,0 +1,345 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * Highcharts variwide module + * + * (c) 2010-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/variwide', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'modules/variwide.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * Highcharts variwide module + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var addEvent = U.addEvent, isNumber = U.isNumber, pick = U.pick, seriesType = U.seriesType, wrap = U.wrap; + var seriesTypes = H.seriesTypes; + /** + * @private + * @class + * @name Highcharts.seriesTypes.variwide + * + * @augments Highcharts.Series + */ + seriesType('variwide', 'column' + /** + * A variwide chart (related to marimekko chart) is a column chart with a + * variable width expressing a third dimension. + * + * @sample {highcharts} highcharts/demo/variwide/ + * Variwide chart + * @sample {highcharts} highcharts/series-variwide/inverted/ + * Inverted variwide chart + * @sample {highcharts} highcharts/series-variwide/datetime/ + * Variwide columns on a datetime axis + * + * @extends plotOptions.column + * @since 6.0.0 + * @product highcharts + * @excluding boostThreshold, crisp, depth, edgeColor, edgeWidth, + * groupZPadding + * @requires modules/variwide + * @optionparent plotOptions.variwide + */ + , { + /** + * In a variwide chart, the point padding is 0 in order to express the + * horizontal stacking of items. + */ + pointPadding: 0, + /** + * In a variwide chart, the group padding is 0 in order to express the + * horizontal stacking of items. + */ + groupPadding: 0 + }, { + irregularWidths: true, + pointArrayMap: ['y', 'z'], + parallelArrays: ['x', 'y', 'z'], + processData: function (force) { + this.totalZ = 0; + this.relZ = []; + seriesTypes.column.prototype.processData.call(this, force); + (this.xAxis.reversed ? + this.zData.slice().reverse() : + this.zData).forEach(function (z, i) { + this.relZ[i] = this.totalZ; + this.totalZ += z; + }, this); + if (this.xAxis.categories) { + this.xAxis.variwide = true; + this.xAxis.zData = this.zData; // Used for label rank + } + return; + }, + /* eslint-disable valid-jsdoc */ + /** + * Translate an x value inside a given category index into the distorted + * axis translation. + * + * @private + * @function Highcharts.Series#postTranslate + * + * @param {number} index + * The category index + * + * @param {number} x + * The X pixel position in undistorted axis pixels + * + * @param {Highcharts.Point} point + * For crosshairWidth for every point + * + * @return {number} + * Distorted X position + */ + postTranslate: function (index, x, point) { + var axis = this.xAxis, relZ = this.relZ, i = axis.reversed ? relZ.length - index : index, goRight = axis.reversed ? -1 : 1, len = axis.len, totalZ = this.totalZ, linearSlotLeft = i / relZ.length * len, linearSlotRight = (i + goRight) / relZ.length * len, slotLeft = (pick(relZ[i], totalZ) / totalZ) * len, slotRight = (pick(relZ[i + goRight], totalZ) / totalZ) * len, xInsideLinearSlot = x - linearSlotLeft, ret; + // Set crosshairWidth for every point (#8173) + if (point) { + point.crosshairWidth = slotRight - slotLeft; + } + ret = slotLeft + + xInsideLinearSlot * (slotRight - slotLeft) / + (linearSlotRight - linearSlotLeft); + return ret; + }, + /* eslint-enable valid-jsdoc */ + // Extend translation by distoring X position based on Z. + translate: function () { + // Temporarily disable crisping when computing original shapeArgs + var crispOption = this.options.crisp, xAxis = this.xAxis; + this.options.crisp = false; + seriesTypes.column.prototype.translate.call(this); + // Reset option + this.options.crisp = crispOption; + var inverted = this.chart.inverted, crisp = this.borderWidth % 2 / 2; + // Distort the points to reflect z dimension + this.points.forEach(function (point, i) { + var left, right; + if (xAxis.variwide) { + left = this.postTranslate(i, point.shapeArgs.x, point); + right = this.postTranslate(i, point.shapeArgs.x + + point.shapeArgs.width); + // For linear or datetime axes, the variwide column should + // start with X and extend Z units, without modifying the + // axis. + } + else { + left = point.plotX; + right = xAxis.translate(point.x + point.z, 0, 0, 0, 1); + } + if (this.options.crisp) { + left = Math.round(left) - crisp; + right = Math.round(right) - crisp; + } + point.shapeArgs.x = left; + point.shapeArgs.width = Math.max(right - left, 1); + // Crosshair position (#8083) + point.plotX = (left + right) / 2; + // Adjust the tooltip position + if (!inverted) { + point.tooltipPos[0] = + point.shapeArgs.x + + point.shapeArgs.width / 2; + } + else { + point.tooltipPos[1] = + xAxis.len - point.shapeArgs.x - + point.shapeArgs.width / 2; + } + }, this); + if (this.options.stacking) { + this.correctStackLabels(); + } + }, + // Function that corrects stack labels positions + correctStackLabels: function () { + var series = this, options = series.options, yAxis = series.yAxis, pointStack, pointWidth, stack, xValue; + series.points.forEach(function (point) { + xValue = point.x; + pointWidth = point.shapeArgs.width; + stack = yAxis.stacking.stacks[(series.negStacks && + point.y < (options.startFromThreshold ? + 0 : + options.threshold) ? + '-' : + '') + series.stackKey]; + if (stack) { + pointStack = stack[xValue]; + if (pointStack && !point.isNull) { + pointStack.setOffset(-(pointWidth / 2) || 0, pointWidth || 0, void 0, void 0, point.plotX); + } + } + }); + } + // Point functions + }, { + isValid: function () { + return isNumber(this.y) && isNumber(this.z); + } + }); + H.Tick.prototype.postTranslate = function (xy, xOrY, index) { + var axis = this.axis, pos = xy[xOrY] - axis.pos; + if (!axis.horiz) { + pos = axis.len - pos; + } + pos = axis.series[0].postTranslate(index, pos); + if (!axis.horiz) { + pos = axis.len - pos; + } + xy[xOrY] = axis.pos + pos; + }; + /* eslint-disable no-invalid-this */ + // Same width as the category (#8083) + addEvent(H.Axis, 'afterDrawCrosshair', function (e) { + if (this.variwide && this.cross) { + this.cross.attr('stroke-width', (e.point && e.point.crosshairWidth)); + } + }); + // On a vertical axis, apply anti-collision logic to the labels. + addEvent(H.Axis, 'afterRender', function () { + var axis = this; + if (!this.horiz && this.variwide) { + this.chart.labelCollectors.push(function () { + return axis.tickPositions + .filter(function (pos) { + return axis.ticks[pos].label; + }) + .map(function (pos, i) { + var label = axis.ticks[pos].label; + label.labelrank = axis.zData[i]; + return label; + }); + }); + } + }); + addEvent(H.Tick, 'afterGetPosition', function (e) { + var axis = this.axis, xOrY = axis.horiz ? 'x' : 'y'; + if (axis.variwide) { + this[xOrY + 'Orig'] = e.pos[xOrY]; + this.postTranslate(e.pos, xOrY, this.pos); + } + }); + wrap(H.Tick.prototype, 'getLabelPosition', function (proceed, x, y, label, horiz, labelOptions, tickmarkOffset, index) { + var args = Array.prototype.slice.call(arguments, 1), xy, xOrY = horiz ? 'x' : 'y'; + // Replace the x with the original x + if (this.axis.variwide && + typeof this[xOrY + 'Orig'] === 'number') { + args[horiz ? 0 : 1] = this[xOrY + 'Orig']; + } + xy = proceed.apply(this, args); + // Post-translate + if (this.axis.variwide && this.axis.categories) { + this.postTranslate(xy, xOrY, index); + } + return xy; + }); + /** + * A `variwide` series. If the [type](#series.variwide.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.variwide + * @product highcharts + * @requires modules/variwide + * @apioption series.variwide + */ + /** + * An array of data points for the series. For the `variwide` series type, + * points can be given in the following ways: + * + * 1. An array of arrays with 3 or 2 values. In this case, the values correspond + * to `x,y,z`. If the first value is a string, it is applied as the name of + * the point, and the `x` value is inferred. The `x` value can also be + * omitted, in which case the inner arrays should be of length 2. Then the + * `x` value is automatically calculated, either starting at 0 and + * incremented by 1, or from `pointStart` and `pointInterval` given in the + * series options. + * ```js + * data: [ + * [0, 1, 2], + * [1, 5, 5], + * [2, 0, 2] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.variwide.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 1, + * y: 1, + * z: 1, + * name: "Point2", + * color: "#00FF00" + * }, { + * x: 1, + * y: 5, + * z: 4, + * name: "Point1", + * color: "#FF00FF" + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|Array<(number|string),number,number>|*>} + * @extends series.line.data + * @excluding marker + * @product highcharts + * @apioption series.variwide.data + */ + /** + * The relative width for each column. On a category axis, the widths are + * distributed so they sum up to the X axis length. On linear and datetime axes, + * the columns will be laid out from the X value and Z units along the axis. + * + * @type {number} + * @product highcharts + * @apioption series.variwide.data.z + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'masters/modules/variwide.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/vector.js b/librerias/gantt/code/modules/vector.js new file mode 100644 index 0000000..e9d9779 --- /dev/null +++ b/librerias/gantt/code/modules/vector.js @@ -0,0 +1,15 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Vector plot series module + + (c) 2010-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/vector",["highcharts"],function(c){a(c);a.Highcharts=c;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function c(a,d,c,e){a.hasOwnProperty(d)||(a[d]=e.apply(null,c))}a=a?a._modules:{};c(a,"modules/vector.src.js",[a["parts/Globals.js"],a["parts/Utilities.js"]],function(a,d){var c=d.animObject,e=d.arrayMax,g=d.pick;d= +d.seriesType;d("vector","scatter",{lineWidth:2,marker:null,rotationOrigin:"center",states:{hover:{lineWidthPlus:1}},tooltip:{pointFormat:"[{point.x}, {point.y}]
    Length: {point.length}
    Direction: {point.direction}\u00b0
    "},vectorLength:20},{pointArrayMap:["y","length","direction"],parallelArrays:["x","y","length","direction"],pointAttribs:function(a,b){var f=this.options;a=a.color||this.color;var c=this.options.lineWidth;b&&(a=f.states[b].color||a,c=(f.states[b].lineWidth|| +c)+(f.states[b].lineWidthPlus||0));return{stroke:a,"stroke-width":c}},markerAttribs:a.noop,getSymbol:a.noop,arrow:function(a){a=a.length/this.lengthMax*this.options.vectorLength/20;var b={start:10*a,center:0,end:-10*a}[this.options.rotationOrigin]||0;return[["M",0,7*a+b],["L",-1.5*a,7*a+b],["L",0,10*a+b],["L",1.5*a,7*a+b],["L",0,7*a+b],["L",0,-10*a+b]]},translate:function(){a.Series.prototype.translate.call(this);this.lengthMax=e(this.lengthData)},drawPoints:function(){var a=this.chart;this.points.forEach(function(b){var c= +b.plotX,d=b.plotY;!1===this.options.clip||a.isInsidePlot(c,d,a.inverted)?(b.graphic||(b.graphic=this.chart.renderer.path().add(this.markerGroup).addClass("highcharts-point highcharts-color-"+g(b.colorIndex,b.series.colorIndex))),b.graphic.attr({d:this.arrow(b),translateX:c,translateY:d,rotation:b.direction}),this.chart.styledMode||b.graphic.attr(this.pointAttribs(b))):b.graphic&&(b.graphic=b.graphic.destroy())},this)},drawGraph:a.noop,animate:function(a){a?this.markerGroup.attr({opacity:.01}):this.markerGroup.animate({opacity:1}, +c(this.options.animation))}});""});c(a,"masters/modules/vector.src.js",[],function(){})}); +//# sourceMappingURL=vector.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/vector.js.map b/librerias/gantt/code/modules/vector.js.map new file mode 100644 index 0000000..353edf5 --- /dev/null +++ b/librerias/gantt/code/modules/vector.js.map @@ -0,0 +1 @@ +{"version":3,"file":"vector.js.map","lineCount":14,"mappings":"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","sources":["vector.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","U","animObject","arrayMax","pick","seriesType","lineWidth","marker","rotationOrigin","states","hover","lineWidthPlus","tooltip","pointFormat","vectorLength","pointArrayMap","parallelArrays","pointAttribs","point","state","options","stroke","color","strokeWidth","markerAttribs","noop","getSymbol","arrow","u","length","lengthMax","o","start","center","end","translate","Series","prototype","call","lengthData","drawPoints","chart","points","forEach","plotX","plotY","clip","isInsidePlot","inverted","graphic","renderer","add","markerGroup","addClass","colorIndex","series","attr","d","translateX","translateY","rotation","direction","styledMode","destroy","drawGraph","animate","init","opacity","animation"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/vector.src.js b/librerias/gantt/code/modules/vector.src.js new file mode 100644 index 0000000..bbb38dc --- /dev/null +++ b/librerias/gantt/code/modules/vector.src.js @@ -0,0 +1,360 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * Vector plot series module + * + * (c) 2010-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/vector', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'modules/vector.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * Vector plot series module + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var animObject = U.animObject, arrayMax = U.arrayMax, pick = U.pick, seriesType = U.seriesType; + /** + * The vector series class. + * + * @private + * @class + * @name Highcharts.seriesTypes.vector + * + * @augments Highcharts.seriesTypes.scatter + */ + seriesType('vector', 'scatter' + /** + * A vector plot is a type of cartesian chart where each point has an X and + * Y position, a length and a direction. Vectors are drawn as arrows. + * + * @sample {highcharts|highstock} highcharts/demo/vector-plot/ + * Vector pot + * + * @since 6.0.0 + * @extends plotOptions.scatter + * @excluding boostThreshold, marker, connectEnds, connectNulls, + * cropThreshold, dashStyle, dragDrop, gapSize, gapUnit, + * dataGrouping, linecap, shadow, stacking, step, jitter + * @product highcharts highstock + * @requires modules/vector + * @optionparent plotOptions.vector + */ + , { + /** + * The line width for each vector arrow. + */ + lineWidth: 2, + /** + * @ignore + */ + marker: null, + /** + * What part of the vector it should be rotated around. Can be one of + * `start`, `center` and `end`. When `start`, the vectors will start + * from the given [x, y] position, and when `end` the vectors will end + * in the [x, y] position. + * + * @sample highcharts/plotoptions/vector-rotationorigin-start/ + * Rotate from start + * + * @validvalue ["start", "center", "end"] + */ + rotationOrigin: 'center', + states: { + hover: { + /** + * Additonal line width for the vector errors when they are + * hovered. + */ + lineWidthPlus: 1 + } + }, + tooltip: { + /** + * @default [{point.x}, {point.y}] Length: {point.length} Direction: {point.direction}° + */ + pointFormat: '[{point.x}, {point.y}]
    Length: {point.length}
    Direction: {point.direction}\u00B0
    ' + }, + /** + * Maximum length of the arrows in the vector plot. The individual arrow + * length is computed between 0 and this value. + */ + vectorLength: 20 + }, { + pointArrayMap: ['y', 'length', 'direction'], + parallelArrays: ['x', 'y', 'length', 'direction'], + /* eslint-disable valid-jsdoc */ + /** + * Get presentational attributes. + * + * @private + * @function Highcharts.seriesTypes.vector#pointAttribs + * + * @param {Highcharts.Point} point + * + * @param {string} [state] + * + * @return {Highcharts.SVGAttributes} + */ + pointAttribs: function (point, state) { + var options = this.options, stroke = point.color || this.color, strokeWidth = this.options.lineWidth; + if (state) { + stroke = options.states[state].color || stroke; + strokeWidth = + (options.states[state].lineWidth || strokeWidth) + + (options.states[state].lineWidthPlus || 0); + } + return { + 'stroke': stroke, + 'stroke-width': strokeWidth + }; + }, + /** + * @ignore + * @deprecated + * @function Highcharts.seriesTypes.vector#markerAttribs + */ + markerAttribs: H.noop, + /** + * @ignore + * @deprecated + * @function Highcharts.seriesTypes.vector#getSymbol + */ + getSymbol: H.noop, + /** + * Create a single arrow. It is later rotated around the zero + * centerpoint. + * + * @private + * @function Highcharts.seriesTypes.vector#arrow + * + * @param {Highcharts.Point} point + * + * @return {Highcharts.SVGPathArray} + */ + arrow: function (point) { + var path, fraction = point.length / this.lengthMax, u = fraction * this.options.vectorLength / 20, o = { + start: 10 * u, + center: 0, + end: -10 * u + }[this.options.rotationOrigin] || 0; + // The stem and the arrow head. Draw the arrow first with rotation + // 0, which is the arrow pointing down (vector from north to south). + path = [ + ['M', 0, 7 * u + o], + ['L', -1.5 * u, 7 * u + o], + ['L', 0, 10 * u + o], + ['L', 1.5 * u, 7 * u + o], + ['L', 0, 7 * u + o], + ['L', 0, -10 * u + o] // top + ]; + return path; + }, + /** + * @private + * @function Highcharts.seriesTypes.vector#translate + */ + translate: function () { + H.Series.prototype.translate.call(this); + this.lengthMax = arrayMax(this.lengthData); + }, + /** + * @private + * @function Highcharts.seriesTypes.vector#drawPoints + */ + drawPoints: function () { + var chart = this.chart; + this.points.forEach(function (point) { + var plotX = point.plotX, plotY = point.plotY; + if (this.options.clip === false || + chart.isInsidePlot(plotX, plotY, chart.inverted)) { + if (!point.graphic) { + point.graphic = this.chart.renderer + .path() + .add(this.markerGroup) + .addClass('highcharts-point ' + + 'highcharts-color-' + + pick(point.colorIndex, point.series.colorIndex)); + } + point.graphic + .attr({ + d: this.arrow(point), + translateX: plotX, + translateY: plotY, + rotation: point.direction + }); + if (!this.chart.styledMode) { + point.graphic + .attr(this.pointAttribs(point)); + } + } + else if (point.graphic) { + point.graphic = point.graphic.destroy(); + } + }, this); + }, + /** + * @ignore + * @deprecated + * @function Highcharts.seriesTypes.vector#drawGraph + */ + drawGraph: H.noop, + /* + drawLegendSymbol: function (legend, item) { + var options = legend.options, + symbolHeight = legend.symbolHeight, + square = options.squareSymbol, + symbolWidth = square ? symbolHeight : legend.symbolWidth, + path = this.arrow.call({ + lengthMax: 1, + options: { + vectorLength: symbolWidth + } + }, { + length: 1 + }); + + item.legendLine = this.chart.renderer.path(path) + .addClass('highcharts-point') + .attr({ + zIndex: 3, + translateY: symbolWidth / 2, + rotation: 270, + 'stroke-width': 1, + 'stroke': 'black' + }).add(item.legendGroup); + + }, + */ + /** + * Fade in the arrows on initializing series. + * + * @private + * @function Highcharts.seriesTypes.vector#animate + * + * @param {boolean} [init] + */ + animate: function (init) { + if (init) { + this.markerGroup.attr({ + opacity: 0.01 + }); + } + else { + this.markerGroup.animate({ + opacity: 1 + }, animObject(this.options.animation)); + } + } + /* eslint-enable valid-jsdoc */ + }); + /** + * A `vector` series. If the [type](#series.vector.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.vector + * @excluding dataParser, dataURL + * @product highcharts highstock + * @requires modules/vector + * @apioption series.vector + */ + /** + * An array of data points for the series. For the `vector` series type, + * points can be given in the following ways: + * + * 1. An array of arrays with 4 values. In this case, the values correspond to + * to `x,y,length,direction`. If the first value is a string, it is applied + * as the name of the point, and the `x` value is inferred. + * ```js + * data: [ + * [0, 0, 10, 90], + * [0, 1, 5, 180], + * [1, 1, 2, 270] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.area.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: 0, + * y: 0, + * name: "Point2", + * length: 10, + * direction: 90 + * }, { + * x: 1, + * y: 1, + * name: "Point1", + * direction: 270 + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|*>} + * @extends series.line.data + * @product highcharts highstock + * @apioption series.vector.data + */ + /** + * The length of the vector. The rendered length will relate to the + * `vectorLength` setting. + * + * @type {number} + * @product highcharts highstock + * @apioption series.vector.data.length + */ + /** + * The vector direction in degrees, where 0 is north (pointing towards south). + * + * @type {number} + * @product highcharts highstock + * @apioption series.vector.data.direction + */ + ''; // adds doclets above to the transpiled file + + }); + _registerModule(_modules, 'masters/modules/vector.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/venn.js b/librerias/gantt/code/modules/venn.js new file mode 100644 index 0000000..27f37f7 --- /dev/null +++ b/librerias/gantt/code/modules/venn.js @@ -0,0 +1,34 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2017-2019 Highsoft AS + Authors: Jon Arild Nygard + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/venn",["highcharts"],function(q){a(q);a.Highcharts=q;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function q(a,e,f,k){a.hasOwnProperty(e)||(a[e]=k.apply(null,f))}a=a?a._modules:{};q(a,"mixins/draw-point.js",[],function(){var a=function(e){var f,a=this,t=a.graphic,p=e.animatableAttribs,h=e.onComplete,z=e.css,q=e.renderer, +u=null===(f=a.series)||void 0===f?void 0:f.options.animation;if(a.shouldDraw())t||(a.graphic=t=q[e.shapeType](e.shapeArgs).add(e.group)),t.css(z).attr(e.attribs).animate(p,e.isNew?!1:u,h);else if(t){var r=function(){a.graphic=t=t.destroy();"function"===typeof h&&h()};Object.keys(p).length?t.animate(p,void 0,function(){r()}):r()}};return function(e){(e.attribs=e.attribs||{})["class"]=this.getClassName();a.call(this,e)}});q(a,"mixins/geometry.js",[],function(){return{getAngleBetweenPoints:function(a, +e){return Math.atan2(e.x-a.x,e.y-a.y)},getCenterOfPoints:function(a){var e=a.reduce(function(e,a){e.x+=a.x;e.y+=a.y;return e},{x:0,y:0});return{x:e.x/a.length,y:e.y/a.length}},getDistanceBetweenPoints:function(a,e){return Math.sqrt(Math.pow(e.x-a.x,2)+Math.pow(e.y-a.y,2))}}});q(a,"mixins/geometry-circles.js",[a["mixins/geometry.js"]],function(a){function e(c,b){b=Math.pow(10,b);return Math.round(c*b)/b}function f(c){if(0>=c)throw Error("radius of circle must be a positive number.");return Math.PI* +c*c}function k(c,b){return c*c*Math.acos(1-b/c)-(c-b)*Math.sqrt(b*(2*c-b))}function t(c,b){var a=v(c,b),g=c.r,f=b.r,h=[];if(aMath.abs(g-f)){g*=g;var k=(g-f*f+a*a)/(2*a);f=Math.sqrt(g-k*k);g=c.x;h=b.x;c=c.y;var p=b.y;b=g+k*(h-g)/a;k=c+k*(p-c)/a;c=f/a*-(p-c);a=f/a*-(h-g);h=[{x:e(b+c,14),y:e(k-a,14)},{x:e(b-c,14),y:e(k+a,14)}]}return h}function p(c){return c.reduce(function(c,a,e,f){f=f.slice(e+1).reduce(function(c,b,f){var g=[e,f+e+1];return c.concat(t(a,b).map(function(c){c.indexes=g;return c}))}, +[]);return c.concat(f)},[])}function h(c,b){return v(c,b)<=b.r+1e-10}function z(c,b){return!b.some(function(b){return!h(c,b)})}function q(c){return p(c).filter(function(b){return z(b,c)})}var u=a.getAngleBetweenPoints,r=a.getCenterOfPoints,v=a.getDistanceBetweenPoints;return{getAreaOfCircle:f,getAreaOfIntersectionBetweenCircles:function(c){var b=q(c);if(12*g&&(h=2*g);if(!b||b.width>h)b={r:g,largeArc:h>g?1:0,width:h,x:a.x,y:a.y};return b},null);if(g){var h=g.r;b.arcs.push(["A",h,h,0,g.largeArc,1,g.x,g.y]);b.startPoint=a}return b},{startPoint:e,arcs:[]}).arcs;if(0!==b.length&&1!==b.length){b.unshift(["M",e.x,e.y]);var f= +{center:a,d:b}}}return f},getCircleCircleIntersection:t,getCirclesIntersectionPoints:p,getCirclesIntersectionPolygon:q,getCircularSegmentArea:k,getOverlapBetweenCircles:function(c,b,a){var g=0;aA;A++){f.sort(k);var u=f[f.length-1],r=a(f),v=t(r,u,2,-1);v.fx=f[f.length-2].fx?v.fx>u.fx?(r=t(r,u,.5,.5),f=r.fx=l)throw Error("a must be smaller than b.");if(0c;){e=(l-b)/2;g=b+e;var I=a(g);0=l?d:u(ab)a.left=b;if(!w(a.right)||a.rightd)a.top=d;if(!w(a.bottom)||a.bottom} params Parameters + */ + var drawPoint = function drawPoint(params) { + var point = this, attribs = params.attribs = params.attribs || {}; + // Assigning class in dot notation does go well in IE8 + // eslint-disable-next-line dot-notation + attribs['class'] = point.getClassName(); + // Call draw to render component + draw.call(point, params); + }; + + return drawPoint; + }); + _registerModule(_modules, 'mixins/geometry.js', [], function () { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * Calculates the center between a list of points. + * @private + * @param {Array} points + * A list of points to calculate the center of. + * @return {Highcharts.PositionObject} + * Calculated center + */ + var getCenterOfPoints = function getCenterOfPoints(points) { + var sum = points.reduce(function (sum, point) { + sum.x += point.x; + sum.y += point.y; + return sum; + }, { x: 0, y: 0 }); + return { + x: sum.x / points.length, + y: sum.y / points.length + }; + }; + /** + * Calculates the distance between two points based on their x and y + * coordinates. + * @private + * @param {Highcharts.PositionObject} p1 + * The x and y coordinates of the first point. + * @param {Highcharts.PositionObject} p2 + * The x and y coordinates of the second point. + * @return {number} + * Returns the distance between the points. + */ + var getDistanceBetweenPoints = function getDistanceBetweenPoints(p1, p2) { + return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2)); + }; + /** + * Calculates the angle between two points. + * @todo add unit tests. + * @private + * @param {Highcharts.PositionObject} p1 The first point. + * @param {Highcharts.PositionObject} p2 The second point. + * @return {number} Returns the angle in radians. + */ + var getAngleBetweenPoints = function getAngleBetweenPoints(p1, p2) { + return Math.atan2(p2.x - p1.x, p2.y - p1.y); + }; + var geometry = { + getAngleBetweenPoints: getAngleBetweenPoints, + getCenterOfPoints: getCenterOfPoints, + getDistanceBetweenPoints: getDistanceBetweenPoints + }; + + return geometry; + }); + _registerModule(_modules, 'mixins/geometry-circles.js', [_modules['mixins/geometry.js']], function (geometry) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var getAngleBetweenPoints = geometry.getAngleBetweenPoints, getCenterOfPoints = geometry.getCenterOfPoints, getDistanceBetweenPoints = geometry.getDistanceBetweenPoints; + /** + * @private + * @param {number} x + * Number to round + * @param {number} decimals + * Number of decimals to round to + * @return {number} + * Rounded number + */ + function round(x, decimals) { + var a = Math.pow(10, decimals); + return Math.round(x * a) / a; + } + /** + * Calculates the area of a circle based on its radius. + * @private + * @param {number} r + * The radius of the circle. + * @return {number} + * Returns the area of the circle. + */ + function getAreaOfCircle(r) { + if (r <= 0) { + throw new Error('radius of circle must be a positive number.'); + } + return Math.PI * r * r; + } + /** + * Calculates the area of a circular segment based on the radius of the circle + * and the height of the segment. + * See http://mathworld.wolfram.com/CircularSegment.html + * @private + * @param {number} r + * The radius of the circle. + * @param {number} h + * The height of the circular segment. + * @return {number} + * Returns the area of the circular segment. + */ + function getCircularSegmentArea(r, h) { + return r * r * Math.acos(1 - h / r) - (r - h) * Math.sqrt(h * (2 * r - h)); + } + /** + * Calculates the area of overlap between two circles based on their radiuses + * and the distance between them. + * See http://mathworld.wolfram.com/Circle-CircleIntersection.html + * @private + * @param {number} r1 + * Radius of the first circle. + * @param {number} r2 + * Radius of the second circle. + * @param {number} d + * The distance between the two circles. + * @return {number} + * Returns the area of overlap between the two circles. + */ + function getOverlapBetweenCircles(r1, r2, d) { + var overlap = 0; + // If the distance is larger than the sum of the radiuses then the circles + // does not overlap. + if (d < r1 + r2) { + if (d <= Math.abs(r2 - r1)) { + // If the circles are completely overlapping, then the overlap + // equals the area of the smallest circle. + overlap = getAreaOfCircle(r1 < r2 ? r1 : r2); + } + else { + // Height of first triangle segment. + var d1 = (r1 * r1 - r2 * r2 + d * d) / (2 * d), + // Height of second triangle segment. + d2 = d - d1; + overlap = (getCircularSegmentArea(r1, r1 - d1) + + getCircularSegmentArea(r2, r2 - d2)); + } + // Round the result to two decimals. + overlap = round(overlap, 14); + } + return overlap; + } + /** + * Calculates the intersection points of two circles. + * + * NOTE: does not handle floating errors well. + * @private + * @param {Highcharts.CircleObject} c1 + * The first circle. + * @param {Highcharts.CircleObject} c2 + * The second sircle. + * @return {Array} + * Returns the resulting intersection points. + */ + function getCircleCircleIntersection(c1, c2) { + var d = getDistanceBetweenPoints(c1, c2), r1 = c1.r, r2 = c2.r; + var points = []; + if (d < r1 + r2 && d > Math.abs(r1 - r2)) { + // If the circles are overlapping, but not completely overlapping, then + // it exists intersecting points. + var r1Square = r1 * r1, r2Square = r2 * r2, + // d^2 - r^2 + R^2 / 2d + x = (r1Square - r2Square + d * d) / (2 * d), + // y^2 = R^2 - x^2 + y = Math.sqrt(r1Square - x * x), x1 = c1.x, x2 = c2.x, y1 = c1.y, y2 = c2.y, x0 = x1 + x * (x2 - x1) / d, y0 = y1 + x * (y2 - y1) / d, rx = -(y2 - y1) * (y / d), ry = -(x2 - x1) * (y / d); + points = [ + { x: round(x0 + rx, 14), y: round(y0 - ry, 14) }, + { x: round(x0 - rx, 14), y: round(y0 + ry, 14) } + ]; + } + return points; + } + /** + * Calculates all the intersection points for between a list of circles. + * @private + * @param {Array} circles + * The circles to calculate the points from. + * @return {Array} + * Returns a list of intersection points. + */ + function getCirclesIntersectionPoints(circles) { + return circles.reduce(function (points, c1, i, arr) { + var additional = arr.slice(i + 1) + .reduce(function (points, c2, j) { + var indexes = [i, j + i + 1]; + return points.concat(getCircleCircleIntersection(c1, c2) + .map(function (p) { + p.indexes = indexes; + return p; + })); + }, []); + return points.concat(additional); + }, []); + } + /** + * Tests wether the first circle is completely overlapping the second circle. + * + * @private + * @param {Highcharts.CircleObject} circle1 The first circle. + * @param {Highcharts.CircleObject} circle2 The The second circle. + * @return {boolean} Returns true if circle1 is completely overlapping circle2, + * false if not. + */ + function isCircle1CompletelyOverlappingCircle2(circle1, circle2) { + return getDistanceBetweenPoints(circle1, circle2) + circle2.r < + circle1.r + 1e-10; + } + /** + * Tests wether a point lies within a given circle. + * @private + * @param {Highcharts.PositionObject} point + * The point to test for. + * @param {Highcharts.CircleObject} circle + * The circle to test if the point is within. + * @return {boolean} + * Returns true if the point is inside, false if outside. + */ + function isPointInsideCircle(point, circle) { + return getDistanceBetweenPoints(point, circle) <= circle.r + 1e-10; + } + /** + * Tests wether a point lies within a set of circles. + * @private + * @param {Highcharts.PositionObject} point + * The point to test. + * @param {Array} circles + * The list of circles to test against. + * @return {boolean} + * Returns true if the point is inside all the circles, false if not. + */ + function isPointInsideAllCircles(point, circles) { + return !circles.some(function (circle) { + return !isPointInsideCircle(point, circle); + }); + } + /** + * Tests wether a point lies outside a set of circles. + * + * TODO: add unit tests. + * @private + * @param {Highcharts.PositionObject} point + * The point to test. + * @param {Array} circles + * The list of circles to test against. + * @return {boolean} + * Returns true if the point is outside all the circles, false if not. + */ + function isPointOutsideAllCircles(point, circles) { + return !circles.some(function (circle) { + return isPointInsideCircle(point, circle); + }); + } + /** + * Calculates the points for the polygon of the intersection area between a set + * of circles. + * + * @private + * @param {Array} circles + * List of circles to calculate polygon of. + * @return {Array} Return list of points in the + * intersection polygon. + */ + function getCirclesIntersectionPolygon(circles) { + return getCirclesIntersectionPoints(circles) + .filter(function (p) { + return isPointInsideAllCircles(p, circles); + }); + } + /** + * Calculate the path for the area of overlap between a set of circles. + * @todo handle cases with only 1 or 0 arcs. + * @private + * @param {Array} circles + * List of circles to calculate area of. + * @return {Highcharts.GeometryIntersectionObject|undefined} + * Returns the path for the area of overlap. Returns an empty string if + * there are no intersection between all the circles. + */ + function getAreaOfIntersectionBetweenCircles(circles) { + var intersectionPoints = getCirclesIntersectionPolygon(circles), result; + if (intersectionPoints.length > 1) { + // Calculate the center of the intersection points. + var center_1 = getCenterOfPoints(intersectionPoints); + intersectionPoints = intersectionPoints + // Calculate the angle between the center and the points. + .map(function (p) { + p.angle = getAngleBetweenPoints(center_1, p); + return p; + }) + // Sort the points by the angle to the center. + .sort(function (a, b) { + return b.angle - a.angle; + }); + var startPoint = intersectionPoints[intersectionPoints.length - 1]; + var arcs = intersectionPoints + .reduce(function (data, p1) { + var startPoint = data.startPoint, midPoint = getCenterOfPoints([startPoint, p1]); + // Calculate the arc from the intersection points and their + // circles. + var arc = p1.indexes + // Filter out circles that are not included in both + // intersection points. + .filter(function (index) { + return startPoint.indexes.indexOf(index) > -1; + }) + // Iterate the circles of the intersection points and + // calculate arcs. + .reduce(function (arc, index) { + var circle = circles[index], angle1 = getAngleBetweenPoints(circle, p1), angle2 = getAngleBetweenPoints(circle, startPoint), angleDiff = angle2 - angle1 + + (angle2 < angle1 ? 2 * Math.PI : 0), angle = angle2 - angleDiff / 2; + var width = getDistanceBetweenPoints(midPoint, { + x: circle.x + circle.r * Math.sin(angle), + y: circle.y + circle.r * Math.cos(angle) + }); + var r = circle.r; + // Width can sometimes become to large due to floating + // point errors + if (width > r * 2) { + width = r * 2; + } + // Get the arc with the smallest width. + if (!arc || arc.width > width) { + arc = { + r: r, + largeArc: width > r ? 1 : 0, + width: width, + x: p1.x, + y: p1.y + }; + } + // Return the chosen arc. + return arc; + }, null); + // If we find an arc then add it to the list and update p2. + if (arc) { + var r = arc.r; + data.arcs.push(['A', r, r, 0, arc.largeArc, 1, arc.x, arc.y]); + data.startPoint = p1; + } + return data; + }, { + startPoint: startPoint, + arcs: [] + }).arcs; + if (arcs.length === 0) { + // empty + } + else if (arcs.length === 1) { + // empty + } + else { + arcs.unshift(['M', startPoint.x, startPoint.y]); + result = { + center: center_1, + d: arcs + }; + } + } + return result; + } + var geometryCircles = { + getAreaOfCircle: getAreaOfCircle, + getAreaOfIntersectionBetweenCircles: getAreaOfIntersectionBetweenCircles, + getCircleCircleIntersection: getCircleCircleIntersection, + getCirclesIntersectionPoints: getCirclesIntersectionPoints, + getCirclesIntersectionPolygon: getCirclesIntersectionPolygon, + getCircularSegmentArea: getCircularSegmentArea, + getOverlapBetweenCircles: getOverlapBetweenCircles, + isCircle1CompletelyOverlappingCircle2: isCircle1CompletelyOverlappingCircle2, + isPointInsideCircle: isPointInsideCircle, + isPointInsideAllCircles: isPointInsideAllCircles, + isPointOutsideAllCircles: isPointOutsideAllCircles, + round: round + }; + + return geometryCircles; + }); + _registerModule(_modules, 'mixins/nelder-mead.js', [], function () { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /* eslint-disable valid-jsdoc */ + var getCentroid = function (simplex) { + var arr = simplex.slice(0, -1), length = arr.length, result = [], sum = function (data, point) { + data.sum += point[data.i]; + return data; + }; + for (var i = 0; i < length; i++) { + result[i] = arr.reduce(sum, { sum: 0, i: i }).sum / length; + } + return result; + }; + /** + * Finds an optimal position for a given point. + * @todo add unit tests. + * @todo add constraints to optimize the algorithm. + * @private + * @param {Highcharts.NelderMeadTestFunction} fn + * The function to test a point. + * @param {Highcharts.NelderMeadPointArray} initial + * The initial point to optimize. + * @return {Highcharts.NelderMeadPointArray} + * Returns the opimized position of a point. + */ + var nelderMead = function nelderMead(fn, initial) { + var maxIterations = 100, sortByFx = function (a, b) { + return a.fx - b.fx; + }, pRef = 1, // Reflection parameter + pExp = 2, // Expansion parameter + pCon = -0.5, // Contraction parameter + pOCon = pCon * pRef, // Outwards contraction parameter + pShrink = 0.5; // Shrink parameter + /** + * @private + */ + var weightedSum = function weightedSum(weight1, v1, weight2, v2) { + return v1.map(function (x, i) { + return weight1 * x + weight2 * v2[i]; + }); + }; + /** + * @private + */ + var getSimplex = function getSimplex(initial) { + var n = initial.length, simplex = new Array(n + 1); + // Initial point to the simplex. + simplex[0] = initial; + simplex[0].fx = fn(initial); + // Create a set of extra points based on the initial. + for (var i = 0; i < n; ++i) { + var point = initial.slice(); + point[i] = point[i] ? point[i] * 1.05 : 0.001; + point.fx = fn(point); + simplex[i + 1] = point; + } + return simplex; + }; + var updateSimplex = function (simplex, point) { + point.fx = fn(point); + simplex[simplex.length - 1] = point; + return simplex; + }; + var shrinkSimplex = function (simplex) { + var best = simplex[0]; + return simplex.map(function (point) { + var p = weightedSum(1 - pShrink, best, pShrink, point); + p.fx = fn(p); + return p; + }); + }; + var getPoint = function (centroid, worst, a, b) { + var point = weightedSum(a, centroid, b, worst); + point.fx = fn(point); + return point; + }; + // Create a simplex + var simplex = getSimplex(initial); + // Iterate from 0 to max iterations + for (var i = 0; i < maxIterations; i++) { + // Sort the simplex + simplex.sort(sortByFx); + // Create a centroid from the simplex + var worst = simplex[simplex.length - 1]; + var centroid = getCentroid(simplex); + // Calculate the reflected point. + var reflected = getPoint(centroid, worst, 1 + pRef, -pRef); + if (reflected.fx < simplex[0].fx) { + // If reflected point is the best, then possibly expand. + var expanded = getPoint(centroid, worst, 1 + pExp, -pExp); + simplex = updateSimplex(simplex, (expanded.fx < reflected.fx) ? expanded : reflected); + } + else if (reflected.fx >= simplex[simplex.length - 2].fx) { + // If the reflected point is worse than the second worse, then + // contract. + var contracted; + if (reflected.fx > worst.fx) { + // If the reflected is worse than the worst point, do a + // contraction + contracted = getPoint(centroid, worst, 1 + pCon, -pCon); + if (contracted.fx < worst.fx) { + simplex = updateSimplex(simplex, contracted); + } + else { + simplex = shrinkSimplex(simplex); + } + } + else { + // Otherwise do an outwards contraction + contracted = getPoint(centroid, worst, 1 - pOCon, pOCon); + if (contracted.fx < reflected.fx) { + simplex = updateSimplex(simplex, contracted); + } + else { + simplex = shrinkSimplex(simplex); + } + } + } + else { + simplex = updateSimplex(simplex, reflected); + } + } + return simplex[0]; + }; + var content = { + getCentroid: getCentroid, + nelderMead: nelderMead + }; + + return content; + }); + _registerModule(_modules, 'modules/venn.src.js', [_modules['parts/Globals.js'], _modules['mixins/draw-point.js'], _modules['mixins/geometry.js'], _modules['mixins/geometry-circles.js'], _modules['mixins/nelder-mead.js'], _modules['parts/Color.js'], _modules['parts/Utilities.js']], function (H, draw, geometry, geometryCirclesModule, nelderMeadModule, Color, U) { + /* * + * + * Experimental Highcharts module which enables visualization of a Venn + * diagram. + * + * (c) 2016-2020 Highsoft AS + * Authors: Jon Arild Nygard + * + * Layout algorithm by Ben Frederickson: + * https://www.benfrederickson.com/better-venn-diagrams/ + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var getAreaOfCircle = geometryCirclesModule.getAreaOfCircle, getAreaOfIntersectionBetweenCircles = geometryCirclesModule.getAreaOfIntersectionBetweenCircles, getCircleCircleIntersection = geometryCirclesModule.getCircleCircleIntersection, getCirclesIntersectionPolygon = geometryCirclesModule.getCirclesIntersectionPolygon, getOverlapBetweenCirclesByDistance = geometryCirclesModule.getOverlapBetweenCircles, isCircle1CompletelyOverlappingCircle2 = geometryCirclesModule.isCircle1CompletelyOverlappingCircle2, isPointInsideAllCircles = geometryCirclesModule.isPointInsideAllCircles, isPointInsideCircle = geometryCirclesModule.isPointInsideCircle, isPointOutsideAllCircles = geometryCirclesModule.isPointOutsideAllCircles; + // TODO: replace with individual imports + var nelderMead = nelderMeadModule.nelderMead; + var color = Color.parse; + var addEvent = U.addEvent, animObject = U.animObject, extend = U.extend, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, isString = U.isString, merge = U.merge, seriesType = U.seriesType; + var getCenterOfPoints = geometry.getCenterOfPoints, getDistanceBetweenPoints = geometry.getDistanceBetweenPoints, seriesTypes = H.seriesTypes; + var objectValues = function objectValues(obj) { + return Object.keys(obj).map(function (x) { + return obj[x]; + }); + }; + /** + * Calculates the area of overlap between a list of circles. + * @private + * @todo add support for calculating overlap between more than 2 circles. + * @param {Array} circles + * List of circles with their given positions. + * @return {number} + * Returns the area of overlap between all the circles. + */ + var getOverlapBetweenCircles = function getOverlapBetweenCircles(circles) { + var overlap = 0; + // When there is only two circles we can find the overlap by using their + // radiuses and the distance between them. + if (circles.length === 2) { + var circle1 = circles[0]; + var circle2 = circles[1]; + overlap = getOverlapBetweenCirclesByDistance(circle1.r, circle2.r, getDistanceBetweenPoints(circle1, circle2)); + } + return overlap; + }; + /** + * Calculates the difference between the desired overlap and the actual overlap + * between two circles. + * @private + * @param {Dictionary} mapOfIdToCircle + * Map from id to circle. + * @param {Array} relations + * List of relations to calculate the loss of. + * @return {number} + * Returns the loss between positions of the circles for the given relations. + */ + var loss = function loss(mapOfIdToCircle, relations) { + var precision = 10e10; + // Iterate all the relations and calculate their individual loss. + return relations.reduce(function (totalLoss, relation) { + var loss = 0; + if (relation.sets.length > 1) { + var wantedOverlap = relation.value; + // Calculate the actual overlap between the sets. + var actualOverlap = getOverlapBetweenCircles( + // Get the circles for the given sets. + relation.sets.map(function (set) { + return mapOfIdToCircle[set]; + })); + var diff = wantedOverlap - actualOverlap; + loss = Math.round((diff * diff) * precision) / precision; + } + // Add calculated loss to the sum. + return totalLoss + loss; + }, 0); + }; + /** + * Finds the root of a given function. The root is the input value needed for + * a function to return 0. + * + * See https://en.wikipedia.org/wiki/Bisection_method#Algorithm + * + * TODO: Add unit tests. + * + * @param {Function} f + * The function to find the root of. + * @param {number} a + * The lowest number in the search range. + * @param {number} b + * The highest number in the search range. + * @param {number} [tolerance=1e-10] + * The allowed difference between the returned value and root. + * @param {number} [maxIterations=100] + * The maximum iterations allowed. + * @return {number} + * Root number. + */ + var bisect = function bisect(f, a, b, tolerance, maxIterations) { + var fA = f(a), fB = f(b), nMax = maxIterations || 100, tol = tolerance || 1e-10, delta = b - a, n = 1, x, fX; + if (a >= b) { + throw new Error('a must be smaller than b.'); + } + else if (fA * fB > 0) { + throw new Error('f(a) and f(b) must have opposite signs.'); + } + if (fA === 0) { + x = a; + } + else if (fB === 0) { + x = b; + } + else { + while (n++ <= nMax && fX !== 0 && delta > tol) { + delta = (b - a) / 2; + x = a + delta; + fX = f(x); + // Update low and high for next search interval. + if (fA * fX > 0) { + a = x; + } + else { + b = x; + } + } + } + return x; + }; + /** + * Uses the bisection method to make a best guess of the ideal distance between + * two circles too get the desired overlap. + * Currently there is no known formula to calculate the distance from the area + * of overlap, which makes the bisection method preferred. + * @private + * @param {number} r1 + * Radius of the first circle. + * @param {number} r2 + * Radiues of the second circle. + * @param {number} overlap + * The wanted overlap between the two circles. + * @return {number} + * Returns the distance needed to get the wanted overlap between the two + * circles. + */ + var getDistanceBetweenCirclesByOverlap = function getDistanceBetweenCirclesByOverlap(r1, r2, overlap) { + var maxDistance = r1 + r2, distance; + if (overlap <= 0) { + // If overlap is below or equal to zero, then there is no overlap. + distance = maxDistance; + } + else if (getAreaOfCircle(r1 < r2 ? r1 : r2) <= overlap) { + // When area of overlap is larger than the area of the smallest circle, + // then it is completely overlapping. + distance = 0; + } + else { + distance = bisect(function (x) { + var actualOverlap = getOverlapBetweenCirclesByDistance(r1, r2, x); + // Return the differance between wanted and actual overlap. + return overlap - actualOverlap; + }, 0, maxDistance); + } + return distance; + }; + var isSet = function (x) { + return isArray(x.sets) && x.sets.length === 1; + }; + /** + * Calculates a margin for a point based on the iternal and external circles. + * The margin describes if the point is well placed within the internal circles, + * and away from the external + * @private + * @todo add unit tests. + * @param {Highcharts.PositionObject} point + * The point to evaluate. + * @param {Array} internal + * The internal circles. + * @param {Array} external + * The external circles. + * @return {number} + * Returns the margin. + */ + var getMarginFromCircles = function getMarginFromCircles(point, internal, external) { + var margin = internal.reduce(function (margin, circle) { + var m = circle.r - getDistanceBetweenPoints(point, circle); + return (m <= margin) ? m : margin; + }, Number.MAX_VALUE); + margin = external.reduce(function (margin, circle) { + var m = getDistanceBetweenPoints(point, circle) - circle.r; + return (m <= margin) ? m : margin; + }, margin); + return margin; + }; + /** + * Finds the optimal label position by looking for a position that has a low + * distance from the internal circles, and as large possible distane to the + * external circles. + * @private + * @todo Optimize the intial position. + * @todo Add unit tests. + * @param {Array} internal + * Internal circles. + * @param {Array} external + * External circles. + * @return {Highcharts.PositionObject} + * Returns the found position. + */ + var getLabelPosition = function getLabelPosition(internal, external) { + // Get the best label position within the internal circles. + var best = internal.reduce(function (best, circle) { + var d = circle.r / 2; + // Give a set of points with the circle to evaluate as the best label + // position. + return [ + { x: circle.x, y: circle.y }, + { x: circle.x + d, y: circle.y }, + { x: circle.x - d, y: circle.y }, + { x: circle.x, y: circle.y + d }, + { x: circle.x, y: circle.y - d } + ] + // Iterate the given points and return the one with the largest + // margin. + .reduce(function (best, point) { + var margin = getMarginFromCircles(point, internal, external); + // If the margin better than the current best, then update best. + if (best.margin < margin) { + best.point = point; + best.margin = margin; + } + return best; + }, best); + }, { + point: void 0, + margin: -Number.MAX_VALUE + }).point; + // Use nelder mead to optimize the initial label position. + var optimal = nelderMead(function (p) { + return -(getMarginFromCircles({ x: p[0], y: p[1] }, internal, external)); + }, [best.x, best.y]); + // Update best to be the point which was found to have the best margin. + best = { + x: optimal[0], + y: optimal[1] + }; + if (!(isPointInsideAllCircles(best, internal) && + isPointOutsideAllCircles(best, external))) { + // If point was either outside one of the internal, or inside one of the + // external, then it was invalid and should use a fallback. + if (internal.length > 1) { + best = getCenterOfPoints(getCirclesIntersectionPolygon(internal)); + } + else { + best = { + x: internal[0].x, + y: internal[0].y + }; + } + } + // Return the best point. + return best; + }; + /** + * Finds the available width for a label, by taking the label position and + * finding the largest distance, which is inside all internal circles, and + * outside all external circles. + * + * @private + * @param {Highcharts.PositionObject} pos + * The x and y coordinate of the label. + * @param {Array} internal + * Internal circles. + * @param {Array} external + * External circles. + * @return {number} + * Returns available width for the label. + */ + var getLabelWidth = function getLabelWidth(pos, internal, external) { + var radius = internal.reduce(function (min, circle) { + return Math.min(circle.r, min); + }, Infinity), + // Filter out external circles that are completely overlapping. + filteredExternals = external.filter(function (circle) { + return !isPointInsideCircle(pos, circle); + }); + var findDistance = function (maxDistance, direction) { + return bisect(function (x) { + var testPos = { + x: pos.x + (direction * x), + y: pos.y + }, isValid = (isPointInsideAllCircles(testPos, internal) && + isPointOutsideAllCircles(testPos, filteredExternals)); + // If the position is valid, then we want to move towards the max + // distance. If not, then we want to away from the max distance. + return -(maxDistance - x) + (isValid ? 0 : Number.MAX_VALUE); + }, 0, maxDistance); + }; + // Find the smallest distance of left and right. + return Math.min(findDistance(radius, -1), findDistance(radius, 1)) * 2; + }; + /** + * Calulates data label values for a given relations object. + * + * @private + * @todo add unit tests + * @param {Highcharts.VennRelationObject} relation A relations object. + * @param {Array} setRelations The list of + * relations that is a set. + * @return {Highcharts.VennLabelValuesObject} + * Returns an object containing position and width of the label. + */ + function getLabelValues(relation, setRelations) { + var sets = relation.sets; + // Create a list of internal and external circles. + var data = setRelations.reduce(function (data, set) { + // If the set exists in this relation, then it is internal, + // otherwise it will be external. + var isInternal = sets.indexOf(set.sets[0]) > -1; + var property = isInternal ? 'internal' : 'external'; + // Add the circle to the list. + data[property].push(set.circle); + return data; + }, { + internal: [], + external: [] + }); + // Filter out external circles that are completely overlapping all internal + data.external = data.external.filter(function (externalCircle) { + return data.internal.some(function (internalCircle) { + return !isCircle1CompletelyOverlappingCircle2(externalCircle, internalCircle); + }); + }); + // Calulate the label position. + var position = getLabelPosition(data.internal, data.external); + // Calculate the label width + var width = getLabelWidth(position, data.internal, data.external); + return { + position: position, + width: width + }; + } + /** + * Takes an array of relations and adds the properties `totalOverlap` and + * `overlapping` to each set. The property `totalOverlap` is the sum of value + * for each relation where this set is included. The property `overlapping` is + * a map of how much this set is overlapping another set. + * NOTE: This algorithm ignores relations consisting of more than 2 sets. + * @private + * @param {Array} relations + * The list of relations that should be sorted. + * @return {Array} + * Returns the modified input relations with added properties `totalOverlap` and + * `overlapping`. + */ + var addOverlapToSets = function addOverlapToSets(relations) { + // Calculate the amount of overlap per set. + var mapOfIdToProps = relations + // Filter out relations consisting of 2 sets. + .filter(function (relation) { + return relation.sets.length === 2; + }) + // Sum up the amount of overlap for each set. + .reduce(function (map, relation) { + var sets = relation.sets; + sets.forEach(function (set, i, arr) { + if (!isObject(map[set])) { + map[set] = { + overlapping: {}, + totalOverlap: 0 + }; + } + map[set].totalOverlap += relation.value; + map[set].overlapping[arr[1 - i]] = relation.value; + }); + return map; + }, {}); + relations + // Filter out single sets + .filter(isSet) + // Extend the set with the calculated properties. + .forEach(function (set) { + var properties = mapOfIdToProps[set.sets[0]]; + extend(set, properties); + }); + // Returns the modified relations. + return relations; + }; + /** + * Takes two sets and finds the one with the largest total overlap. + * @private + * @param {object} a The first set to compare. + * @param {object} b The second set to compare. + * @return {number} Returns 0 if a and b are equal, <0 if a is greater, >0 if b + * is greater. + */ + var sortByTotalOverlap = function sortByTotalOverlap(a, b) { + return b.totalOverlap - a.totalOverlap; + }; + /** + * Uses a greedy approach to position all the sets. Works well with a small + * number of sets, and are in these cases a good choice aesthetically. + * @private + * @param {Array} relations List of the overlap between two or more + * sets, or the size of a single set. + * @return {Array} List of circles and their calculated positions. + */ + var layoutGreedyVenn = function layoutGreedyVenn(relations) { + var positionedSets = [], mapOfIdToCircles = {}; + // Define a circle for each set. + relations + .filter(function (relation) { + return relation.sets.length === 1; + }).forEach(function (relation) { + mapOfIdToCircles[relation.sets[0]] = relation.circle = { + x: Number.MAX_VALUE, + y: Number.MAX_VALUE, + r: Math.sqrt(relation.value / Math.PI) + }; + }); + /** + * Takes a set and updates the position, and add the set to the list of + * positioned sets. + * @private + * @param {object} set + * The set to add to its final position. + * @param {object} coordinates + * The coordinates to position the set at. + * @return {void} + */ + var positionSet = function positionSet(set, coordinates) { + var circle = set.circle; + circle.x = coordinates.x; + circle.y = coordinates.y; + positionedSets.push(set); + }; + // Find overlap between sets. Ignore relations with more then 2 sets. + addOverlapToSets(relations); + // Sort sets by the sum of their size from large to small. + var sortedByOverlap = relations + .filter(isSet) + .sort(sortByTotalOverlap); + // Position the most overlapped set at 0,0. + positionSet(sortedByOverlap.shift(), { x: 0, y: 0 }); + var relationsWithTwoSets = relations.filter(function (x) { + return x.sets.length === 2; + }); + // Iterate and position the remaining sets. + sortedByOverlap.forEach(function (set) { + var circle = set.circle, radius = circle.r, overlapping = set.overlapping; + var bestPosition = positionedSets + .reduce(function (best, positionedSet, i) { + var positionedCircle = positionedSet.circle, overlap = overlapping[positionedSet.sets[0]]; + // Calculate the distance between the sets to get the correct + // overlap + var distance = getDistanceBetweenCirclesByOverlap(radius, positionedCircle.r, overlap); + // Create a list of possible coordinates calculated from + // distance. + var possibleCoordinates = [ + { x: positionedCircle.x + distance, y: positionedCircle.y }, + { x: positionedCircle.x - distance, y: positionedCircle.y }, + { x: positionedCircle.x, y: positionedCircle.y + distance }, + { x: positionedCircle.x, y: positionedCircle.y - distance } + ]; + // If there are more circles overlapping, then add the + // intersection points as possible positions. + positionedSets.slice(i + 1).forEach(function (positionedSet2) { + var positionedCircle2 = positionedSet2.circle, overlap2 = overlapping[positionedSet2.sets[0]], distance2 = getDistanceBetweenCirclesByOverlap(radius, positionedCircle2.r, overlap2); + // Add intersections to list of coordinates. + possibleCoordinates = possibleCoordinates.concat(getCircleCircleIntersection({ + x: positionedCircle.x, + y: positionedCircle.y, + r: distance + }, { + x: positionedCircle2.x, + y: positionedCircle2.y, + r: distance2 + })); + }); + // Iterate all suggested coordinates and find the best one. + possibleCoordinates.forEach(function (coordinates) { + circle.x = coordinates.x; + circle.y = coordinates.y; + // Calculate loss for the suggested coordinates. + var currentLoss = loss(mapOfIdToCircles, relationsWithTwoSets); + // If the loss is better, then use these new coordinates. + if (currentLoss < best.loss) { + best.loss = currentLoss; + best.coordinates = coordinates; + } + }); + // Return resulting coordinates. + return best; + }, { + loss: Number.MAX_VALUE, + coordinates: void 0 + }); + // Add the set to its final position. + positionSet(set, bestPosition.coordinates); + }); + // Return the positions of each set. + return mapOfIdToCircles; + }; + /** + * Calculates the positions, and the label values of all the sets in the venn + * diagram. + * + * @private + * @todo Add support for constrained MDS. + * @param {Array} relations + * List of the overlap between two or more sets, or the size of a single set. + * @return {Highcharts.Dictionary<*>} + * List of circles and their calculated positions. + */ + function layout(relations) { + var mapOfIdToShape = {}; + var mapOfIdToLabelValues = {}; + // Calculate best initial positions by using greedy layout. + if (relations.length > 0) { + var mapOfIdToCircles_1 = layoutGreedyVenn(relations); + var setRelations_1 = relations.filter(isSet); + relations + .forEach(function (relation) { + var sets = relation.sets; + var id = sets.join(); + // Get shape from map of circles, or calculate intersection. + var shape = isSet(relation) ? + mapOfIdToCircles_1[id] : + getAreaOfIntersectionBetweenCircles(sets.map(function (set) { + return mapOfIdToCircles_1[set]; + })); + // Calculate label values if the set has a shape + if (shape) { + mapOfIdToShape[id] = shape; + mapOfIdToLabelValues[id] = getLabelValues(relation, setRelations_1); + } + }); + } + return { mapOfIdToShape: mapOfIdToShape, mapOfIdToLabelValues: mapOfIdToLabelValues }; + } + var isValidRelation = function (x) { + var map = {}; + return (isObject(x) && + (isNumber(x.value) && x.value > -1) && + (isArray(x.sets) && x.sets.length > 0) && + !x.sets.some(function (set) { + var invalid = false; + if (!map[set] && isString(set)) { + map[set] = true; + } + else { + invalid = true; + } + return invalid; + })); + }; + var isValidSet = function (x) { + return (isValidRelation(x) && isSet(x) && x.value > 0); + }; + /** + * Prepares the venn data so that it is usable for the layout function. Filter + * out sets, or intersections that includes sets, that are missing in the data + * or has (value < 1). Adds missing relations between sets in the data as + * value = 0. + * @private + * @param {Array} data The raw input data. + * @return {Array} Returns an array of valid venn data. + */ + var processVennData = function processVennData(data) { + var d = isArray(data) ? data : []; + var validSets = d + .reduce(function (arr, x) { + // Check if x is a valid set, and that it is not an duplicate. + if (isValidSet(x) && arr.indexOf(x.sets[0]) === -1) { + arr.push(x.sets[0]); + } + return arr; + }, []) + .sort(); + var mapOfIdToRelation = d.reduce(function (mapOfIdToRelation, relation) { + if (isValidRelation(relation) && + !relation.sets.some(function (set) { + return validSets.indexOf(set) === -1; + })) { + mapOfIdToRelation[relation.sets.sort().join()] = + relation; + } + return mapOfIdToRelation; + }, {}); + validSets.reduce(function (combinations, set, i, arr) { + var remaining = arr.slice(i + 1); + remaining.forEach(function (set2) { + combinations.push(set + ',' + set2); + }); + return combinations; + }, []).forEach(function (combination) { + if (!mapOfIdToRelation[combination]) { + var obj = { + sets: combination.split(','), + value: 0 + }; + mapOfIdToRelation[combination] = obj; + } + }); + // Transform map into array. + return objectValues(mapOfIdToRelation); + }; + /** + * Calculates the proper scale to fit the cloud inside the plotting area. + * @private + * @todo add unit test + * @param {number} targetWidth + * Width of target area. + * @param {number} targetHeight + * Height of target area. + * @param {Highcharts.PolygonBoxObject} field + * The playing field. + * @return {Highcharts.Dictionary} + * Returns the value to scale the playing field up to the size of the target + * area, and center of x and y. + */ + var getScale = function getScale(targetWidth, targetHeight, field) { + var height = field.bottom - field.top, // top is smaller than bottom + width = field.right - field.left, scaleX = width > 0 ? 1 / width * targetWidth : 1, scaleY = height > 0 ? 1 / height * targetHeight : 1, adjustX = (field.right + field.left) / 2, adjustY = (field.top + field.bottom) / 2, scale = Math.min(scaleX, scaleY); + return { + scale: scale, + centerX: targetWidth / 2 - adjustX * scale, + centerY: targetHeight / 2 - adjustY * scale + }; + }; + /** + * If a circle is outside a give field, then the boundaries of the field is + * adjusted accordingly. Modifies the field object which is passed as the first + * parameter. + * @private + * @todo NOTE: Copied from wordcloud, can probably be unified. + * @param {Highcharts.PolygonBoxObject} field + * The bounding box of a playing field. + * @param {Highcharts.CircleObject} circle + * The bounding box for a placed point. + * @return {Highcharts.PolygonBoxObject} + * Returns a modified field object. + */ + var updateFieldBoundaries = function updateFieldBoundaries(field, circle) { + var left = circle.x - circle.r, right = circle.x + circle.r, bottom = circle.y + circle.r, top = circle.y - circle.r; + // TODO improve type checking. + if (!isNumber(field.left) || field.left > left) { + field.left = left; + } + if (!isNumber(field.right) || field.right < right) { + field.right = right; + } + if (!isNumber(field.top) || field.top > top) { + field.top = top; + } + if (!isNumber(field.bottom) || field.bottom < bottom) { + field.bottom = bottom; + } + return field; + }; + /** + * A Venn diagram displays all possible logical relations between a collection + * of different sets. The sets are represented by circles, and the relation + * between the sets are displayed by the overlap or lack of overlap between + * them. The venn diagram is a special case of Euler diagrams, which can also + * be displayed by this series type. + * + * @sample {highcharts} highcharts/demo/venn-diagram/ + * Venn diagram + * @sample {highcharts} highcharts/demo/euler-diagram/ + * Euler diagram + * + * @extends plotOptions.scatter + * @excluding connectEnds, connectNulls, cropThreshold, dragDrop, + * findNearestPointBy, getExtremesFromAll, jitter, label, linecap, + * lineWidth, linkedTo, marker, negativeColor, pointInterval, + * pointIntervalUnit, pointPlacement, pointStart, softThreshold, + * stacking, steps, threshold, xAxis, yAxis, zoneAxis, zones, + * dataSorting + * @product highcharts + * @requires modules/venn + * @optionparent plotOptions.venn + */ + var vennOptions = { + borderColor: '#cccccc', + borderDashStyle: 'solid', + borderWidth: 1, + brighten: 0, + clip: false, + colorByPoint: true, + dataLabels: { + enabled: true, + verticalAlign: 'middle', + formatter: function () { + return this.point.name; + } + }, + /** + * @ignore-option + * @private + */ + inactiveOtherPoints: true, + marker: false, + opacity: 0.75, + showInLegend: false, + states: { + /** + * @excluding halo + */ + hover: { + opacity: 1, + borderColor: '#333333' + }, + /** + * @excluding halo + */ + select: { + color: '#cccccc', + borderColor: '#000000', + animation: false + }, + inactive: { + opacity: 0.075 + } + }, + tooltip: { + pointFormat: '{point.name}: {point.value}' + } + }; + var vennSeries = { + isCartesian: false, + axisTypes: [], + directTouch: true, + pointArrayMap: ['value'], + translate: function () { + var chart = this.chart; + this.processedXData = this.xData; + this.generatePoints(); + // Process the data before passing it into the layout function. + var relations = processVennData(this.options.data); + // Calculate the positions of each circle. + var _a = layout(relations), mapOfIdToShape = _a.mapOfIdToShape, mapOfIdToLabelValues = _a.mapOfIdToLabelValues; + // Calculate the scale, and center of the plot area. + var field = Object.keys(mapOfIdToShape) + .filter(function (key) { + var shape = mapOfIdToShape[key]; + return shape && isNumber(shape.r); + }) + .reduce(function (field, key) { + return updateFieldBoundaries(field, mapOfIdToShape[key]); + }, { top: 0, bottom: 0, left: 0, right: 0 }), scaling = getScale(chart.plotWidth, chart.plotHeight, field), scale = scaling.scale, centerX = scaling.centerX, centerY = scaling.centerY; + // Iterate all points and calculate and draw their graphics. + this.points.forEach(function (point) { + var sets = isArray(point.sets) ? point.sets : [], id = sets.join(), shape = mapOfIdToShape[id], shapeArgs, dataLabelValues = mapOfIdToLabelValues[id] || {}, dataLabelWidth = dataLabelValues.width, dataLabelPosition = dataLabelValues.position, dlOptions = point.options && point.options.dataLabels; + if (shape) { + if (shape.r) { + shapeArgs = { + x: centerX + shape.x * scale, + y: centerY + shape.y * scale, + r: shape.r * scale + }; + } + else if (shape.d) { + var d = shape.d; + d.forEach(function (seg) { + if (seg[0] === 'M') { + seg[1] = centerX + seg[1] * scale; + seg[2] = centerY + seg[2] * scale; + } + else if (seg[0] === 'A') { + seg[1] = seg[1] * scale; + seg[2] = seg[2] * scale; + seg[6] = centerX + seg[6] * scale; + seg[7] = centerY + seg[7] * scale; + } + }); + shapeArgs = { d: d }; + } + // Scale the position for the data label. + if (dataLabelPosition) { + dataLabelPosition.x = centerX + dataLabelPosition.x * scale; + dataLabelPosition.y = centerY + dataLabelPosition.y * scale; + } + else { + dataLabelPosition = {}; + } + if (isNumber(dataLabelWidth)) { + dataLabelWidth = Math.round(dataLabelWidth * scale); + } + } + point.shapeArgs = shapeArgs; + // Placement for the data labels + if (dataLabelPosition && shapeArgs) { + point.plotX = dataLabelPosition.x; + point.plotY = dataLabelPosition.y; + } + // Add width for the data label + if (dataLabelWidth && shapeArgs) { + point.dlOptions = merge(true, { + style: { + width: dataLabelWidth + } + }, isObject(dlOptions) && dlOptions); + } + // Set name for usage in tooltip and in data label. + point.name = point.options.name || sets.join('∩'); + }); + }, + /* eslint-disable valid-jsdoc */ + /** + * Draw the graphics for each point. + * @private + */ + drawPoints: function () { + var series = this, + // Series properties + chart = series.chart, group = series.group, points = series.points || [], + // Chart properties + renderer = chart.renderer; + // Iterate all points and calculate and draw their graphics. + points.forEach(function (point) { + var attribs = { + zIndex: isArray(point.sets) ? point.sets.length : 0 + }, shapeArgs = point.shapeArgs; + // Add point attribs + if (!chart.styledMode) { + extend(attribs, series.pointAttribs(point, point.state)); + } + // Draw the point graphic. + point.draw({ + isNew: !point.graphic, + animatableAttribs: shapeArgs, + attribs: attribs, + group: group, + renderer: renderer, + shapeType: shapeArgs && shapeArgs.d ? 'path' : 'circle' + }); + }); + }, + /** + * Calculates the style attributes for a point. The attributes can vary + * depending on the state of the point. + * @private + * @param {Highcharts.Point} point + * The point which will get the resulting attributes. + * @param {string} [state] + * The state of the point. + * @return {Highcharts.SVGAttributes} + * Returns the calculated attributes. + */ + pointAttribs: function (point, state) { + var series = this, seriesOptions = series.options || {}, pointOptions = point && point.options || {}, stateOptions = (state && seriesOptions.states[state]) || {}, options = merge(seriesOptions, { color: point && point.color }, pointOptions, stateOptions); + // Return resulting values for the attributes. + return { + 'fill': color(options.color) + .setOpacity(options.opacity) + .brighten(options.brightness) + .get(), + 'stroke': options.borderColor, + 'stroke-width': options.borderWidth, + 'dashstyle': options.borderDashStyle + }; + }, + /* eslint-enable valid-jsdoc */ + animate: function (init) { + if (!init) { + var series = this, animOptions = animObject(series.options.animation); + series.points.forEach(function (point) { + var args = point.shapeArgs; + if (point.graphic && args) { + var attr = {}, animate = {}; + if (args.d) { + // If shape is a path, then animate opacity. + attr.opacity = 0.001; + } + else { + // If shape is a circle, then animate radius. + attr.r = 0; + animate.r = args.r; + } + point.graphic + .attr(attr) + .animate(animate, animOptions); + // If shape is path, then fade it in after the circles + // animation + if (args.d) { + setTimeout(function () { + if (point && point.graphic) { + point.graphic.animate({ + opacity: 1 + }); + } + }, animOptions.duration); + } + } + }, series); + } + }, + utils: { + addOverlapToSets: addOverlapToSets, + geometry: geometry, + geometryCircles: geometryCirclesModule, + getLabelWidth: getLabelWidth, + getMarginFromCircles: getMarginFromCircles, + getDistanceBetweenCirclesByOverlap: getDistanceBetweenCirclesByOverlap, + layoutGreedyVenn: layoutGreedyVenn, + loss: loss, + nelderMead: nelderMeadModule, + processVennData: processVennData, + sortByTotalOverlap: sortByTotalOverlap + } + }; + var vennPoint = { + draw: draw, + shouldDraw: function () { + var point = this; + // Only draw points with single sets. + return !!point.shapeArgs; + }, + isValid: function () { + return isNumber(this.value); + } + }; + /** + * A `venn` series. If the [type](#series.venn.type) option is + * not specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.venn + * @excluding connectEnds, connectNulls, cropThreshold, dataParser, dataURL, + * findNearestPointBy, getExtremesFromAll, label, linecap, lineWidth, + * linkedTo, marker, negativeColor, pointInterval, pointIntervalUnit, + * pointPlacement, pointStart, softThreshold, stack, stacking, steps, + * threshold, xAxis, yAxis, zoneAxis, zones, dataSorting + * @product highcharts + * @requires modules/venn + * @apioption series.venn + */ + /** + * @type {Array<*>} + * @extends series.scatter.data + * @excluding marker, x, y + * @product highcharts + * @apioption series.venn.data + */ + /** + * The name of the point. Used in data labels and tooltip. If name is not + * defined then it will default to the joined values in + * [sets](#series.venn.sets). + * + * @sample {highcharts} highcharts/demo/venn-diagram/ + * Venn diagram + * @sample {highcharts} highcharts/demo/euler-diagram/ + * Euler diagram + * + * @type {number} + * @since 7.0.0 + * @product highcharts + * @apioption series.venn.data.name + */ + /** + * The value of the point, resulting in a relative area of the circle, or area + * of overlap between two sets in the venn or euler diagram. + * + * @sample {highcharts} highcharts/demo/venn-diagram/ + * Venn diagram + * @sample {highcharts} highcharts/demo/euler-diagram/ + * Euler diagram + * + * @type {number} + * @since 7.0.0 + * @product highcharts + * @apioption series.venn.data.value + */ + /** + * The set or sets the options will be applied to. If a single entry is defined, + * then it will create a new set. If more than one entry is defined, then it + * will define the overlap between the sets in the array. + * + * @sample {highcharts} highcharts/demo/venn-diagram/ + * Venn diagram + * @sample {highcharts} highcharts/demo/euler-diagram/ + * Euler diagram + * + * @type {Array} + * @since 7.0.0 + * @product highcharts + * @apioption series.venn.data.sets + */ + /** + * @excluding halo + * @apioption series.venn.states.hover + */ + /** + * @excluding halo + * @apioption series.venn.states.select + */ + /** + * @private + * @class + * @name Highcharts.seriesTypes.venn + * + * @augments Highcharts.Series + */ + seriesType('venn', 'scatter', vennOptions, vennSeries, vennPoint); + /* eslint-disable no-invalid-this */ + // Modify final series options. + addEvent(seriesTypes.venn, 'afterSetOptions', function (e) { + var options = e.options, states = options.states; + if (this.is('venn')) { + // Explicitly disable all halo options. + Object.keys(states).forEach(function (state) { + states[state].halo = false; + }); + } + }); + + }); + _registerModule(_modules, 'masters/modules/venn.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/windbarb.js b/librerias/gantt/code/modules/windbarb.js new file mode 100644 index 0000000..9db7fa0 --- /dev/null +++ b/librerias/gantt/code/modules/windbarb.js @@ -0,0 +1,20 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + Wind barb series module + + (c) 2010-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/modules/windbarb",["highcharts"],function(k){a(k);a.Highcharts=k;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function k(a,f,k,n){a.hasOwnProperty(f)||(a[f]=n.apply(null,k))}a=a?a._modules:{};k(a,"mixins/on-series.js",[a["parts/Globals.js"],a["parts/Utilities.js"]],function(a,f){var k=f.defined,t=f.stableSort,u=a.seriesTypes; +return{getPlotBox:function(){return a.Series.prototype.getPlotBox.call(this.options.onSeries&&this.chart.get(this.options.onSeries)||this)},translate:function(){u.column.prototype.translate.apply(this);var a=this,l=a.options,g=a.chart,h=a.points,e=h.length-1,c,b=l.onSeries;b=b&&g.get(b);l=l.onKey||"y";var d=b&&b.options.step,f=b&&b.points,p=f&&f.length,n=g.inverted,r=a.xAxis,x=a.yAxis,v=0,q;if(b&&b.visible&&p){v=(b.pointXOffset||0)+(b.barW||0)/2;g=b.currentDataGrouping;var y=f[p-1].x+(g?g.totalRange: +0);t(h,function(b,c){return b.x-c.x});for(l="plot"+l[0].toUpperCase()+l.substr(1);p--&&h[e];){var m=f[p];g=h[e];g.y=m.y;if(m.x<=g.x&&"undefined"!==typeof m[l]){if(g.x<=y&&(g.plotY=m[l],m.xe)break}}}h.forEach(function(b,d){b.plotX+=v;if("undefined"===typeof b.plotY||n)0<=b.plotX&&b.plotX<=r.len?n?(b.plotY=r.translate(b.x,0,1,0,1),b.plotX=k(b.y)?x.translate(b.y,0,0,0,1):0): +b.plotY=(r.opposite?0:a.yAxis.len)+r.offset:b.shapeArgs={};if((c=h[d-1])&&c.plotX===b.plotX){"undefined"===typeof c.stackIndex&&(c.stackIndex=0);var e=c.stackIndex+1}b.stackIndex=e});this.onSeries=b}}});k(a,"modules/windbarb.src.js",[a["parts/Globals.js"],a["parts/Utilities.js"],a["mixins/on-series.js"]],function(a,f,k){function n(){a.approximations&&!a.approximations.windbarb&&(a.approximations.windbarb=function(h,e){var c=0,b=0,d,f=h.length;for(d=0;d\u25cf {series.name}: {point.value} ({point.beaufort})
    '},vectorLength:20,colorKey:"value",yOffset:-20, +xOffset:0},{pointArrayMap:["value","direction"],parallelArrays:["x","value","direction"],beaufortName:"Calm;Light air;Light breeze;Gentle breeze;Moderate breeze;Fresh breeze;Strong breeze;Near gale;Gale;Strong gale;Storm;Violent storm;Hurricane".split(";"),beaufortFloor:[0,.3,1.6,3.4,5.5,8,10.8,13.9,17.2,20.8,24.5,28.5,32.7],trackerGroups:["markerGroup"],init:function(h,e){n();a.Series.prototype.init.call(this,h,e)},pointAttribs:function(a,e){var c=this.options;a=a.color||this.color;var b=this.options.lineWidth; +e&&(a=c.states[e].color||a,b=(c.states[e].lineWidth||b)+(c.states[e].lineWidthPlus||0));return{stroke:a,"stroke-width":b}},markerAttribs:function(){},getPlotBox:k.getPlotBox,windArrow:function(a){var e=1.943844*a.value,c=this.options.vectorLength/20,b=-10;if(a.isNull)return[];if(0===a.beaufortLevel)return this.chart.renderer.symbols.circle(-10*c,-10*c,20*c,20*c);a=[["M",0,7*c],["L",-1.5*c,7*c],["L",0,10*c],["L",1.5*c,7*c],["L",0,7*c],["L",0,-10*c]];var d=(e-e%50)/50;if(0c.value);b++);c.beaufortLevel=b-1;c.beaufort=e[b-1]})},drawPoints:function(){var a= +this.chart,e=this.yAxis,c=a.inverted,b=this.options.vectorLength/2;this.points.forEach(function(d){var f=d.plotX,g=d.plotY;!1===this.options.clip||a.isInsidePlot(f,0,!1)?(d.graphic||(d.graphic=this.chart.renderer.path().add(this.markerGroup).addClass("highcharts-point highcharts-color-"+l(d.colorIndex,d.series.colorIndex))),d.graphic.attr({d:this.windArrow(d),translateX:f+this.options.xOffset,translateY:g+this.options.yOffset,rotation:d.direction}),this.chart.styledMode||d.graphic.attr(this.pointAttribs(d))): +d.graphic&&(d.graphic=d.graphic.destroy());d.tooltipPos=[f+this.options.xOffset+(c&&!this.onSeries?b:0),g+this.options.yOffset-(c?0:b+e.pos-a.plotTop)]},this)},animate:function(a){a?this.markerGroup.attr({opacity:.01}):this.markerGroup.animate({opacity:1},u(this.options.animation))},invertGroups:g,getExtremes:function(){return{}}},{isValid:function(){return t(this.value)&&0<=this.value}});""});k(a,"masters/modules/windbarb.src.js",[],function(){})}); +//# sourceMappingURL=windbarb.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/windbarb.js.map b/librerias/gantt/code/modules/windbarb.js.map new file mode 100644 index 0000000..1a915f7 --- /dev/null +++ b/librerias/gantt/code/modules/windbarb.js.map @@ -0,0 +1 @@ +{"version":3,"file":"windbarb.js.map","lineCount":19,"mappings":"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","sources":["windbarb.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","U","defined","stableSort","seriesTypes","onSeriesMixin","getPlotBox","Series","prototype","call","options","onSeries","chart","get","translate","column","series","points","cursor","length","lastPoint","optionsOnSeries","onKey","step","onData","i","inverted","xAxis","yAxis","xOffset","rightPoint","visible","pointXOffset","barW","currentDataGrouping","lastX","x","totalRange","a","b","toUpperCase","substr","leftPoint","point","y","plotY","distanceRatio","forEach","plotX","len","opposite","offset","shapeArgs","stackIndex","registerApproximation","approximations","windbarb","H.approximations.windbarb","values","directions","vectorX","vectorY","Math","cos","deg2rad","sin","reduce","sum","value","atan2","animObject","isNumber","pick","seriesType","noop","dataGrouping","enabled","approximation","groupPixelWidth","lineWidth","states","hover","lineWidthPlus","tooltip","pointFormat","vectorLength","colorKey","yOffset","pointArrayMap","parallelArrays","beaufortName","beaufortFloor","trackerGroups","init","pointAttribs","state","stroke","color","strokeWidth","markerAttribs","windArrow","knots","u","pos","isNull","beaufortLevel","renderer","symbols","circle","barbs","push","level","beaufort","drawPoints","shapeOffset","clip","isInsidePlot","graphic","add","markerGroup","addClass","colorIndex","attr","d","translateX","translateY","rotation","direction","styledMode","destroy","tooltipPos","plotTop","animate","opacity","animation","invertGroups","getExtremes","isValid"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/windbarb.src.js b/librerias/gantt/code/modules/windbarb.src.js new file mode 100644 index 0000000..103e0c1 --- /dev/null +++ b/librerias/gantt/code/modules/windbarb.src.js @@ -0,0 +1,561 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * Wind barb series module + * + * (c) 2010-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/windbarb', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'mixins/on-series.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var defined = U.defined, stableSort = U.stableSort; + var seriesTypes = H.seriesTypes; + /** + * @private + * @mixin onSeriesMixin + */ + var onSeriesMixin = { + /* eslint-disable valid-jsdoc */ + /** + * Override getPlotBox. If the onSeries option is valid, return the plot box + * of the onSeries, otherwise proceed as usual. + * + * @private + * @function onSeriesMixin.getPlotBox + * @return {Highcharts.SeriesPlotBoxObject} + */ + getPlotBox: function () { + return H.Series.prototype.getPlotBox.call((this.options.onSeries && + this.chart.get(this.options.onSeries)) || this); + }, + /** + * Extend the translate method by placing the point on the related series + * + * @private + * @function onSeriesMixin.translate + * @return {void} + */ + translate: function () { + seriesTypes.column.prototype.translate.apply(this); + var series = this, options = series.options, chart = series.chart, points = series.points, cursor = points.length - 1, point, lastPoint, optionsOnSeries = options.onSeries, onSeries = (optionsOnSeries && + chart.get(optionsOnSeries)), onKey = options.onKey || 'y', step = onSeries && onSeries.options.step, onData = (onSeries && onSeries.points), i = onData && onData.length, inverted = chart.inverted, xAxis = series.xAxis, yAxis = series.yAxis, xOffset = 0, leftPoint, lastX, rightPoint, currentDataGrouping, distanceRatio; + // relate to a master series + if (onSeries && onSeries.visible && i) { + xOffset = (onSeries.pointXOffset || 0) + (onSeries.barW || 0) / 2; + currentDataGrouping = onSeries.currentDataGrouping; + lastX = (onData[i - 1].x + + (currentDataGrouping ? currentDataGrouping.totalRange : 0)); // #2374 + // sort the data points + stableSort(points, function (a, b) { + return (a.x - b.x); + }); + onKey = 'plot' + onKey[0].toUpperCase() + onKey.substr(1); + while (i-- && points[cursor]) { + leftPoint = onData[i]; + point = points[cursor]; + point.y = leftPoint.y; + if (leftPoint.x <= point.x && + typeof leftPoint[onKey] !== 'undefined') { + if (point.x <= lastX) { // #803 + point.plotY = leftPoint[onKey]; + // interpolate between points, #666 + if (leftPoint.x < point.x && + !step) { + rightPoint = onData[i + 1]; + if (rightPoint && + typeof rightPoint[onKey] !== 'undefined') { + // the distance ratio, between 0 and 1 + distanceRatio = + (point.x - leftPoint.x) / + (rightPoint.x - leftPoint.x); + point.plotY += + distanceRatio * + // the plotY distance + (rightPoint[onKey] - leftPoint[onKey]); + point.y += + distanceRatio * + (rightPoint.y - leftPoint.y); + } + } + } + cursor--; + i++; // check again for points in the same x position + if (cursor < 0) { + break; + } + } + } + } + // Add plotY position and handle stacking + points.forEach(function (point, i) { + var stackIndex; + point.plotX += xOffset; // #2049 + // Undefined plotY means the point is either on axis, outside series + // range or hidden series. If the series is outside the range of the + // x axis it should fall through with an undefined plotY, but then + // we must remove the shapeArgs (#847). For inverted charts, we need + // to calculate position anyway, because series.invertGroups is not + // defined + if (typeof point.plotY === 'undefined' || inverted) { + if (point.plotX >= 0 && + point.plotX <= xAxis.len) { + // We're inside xAxis range + if (inverted) { + point.plotY = xAxis.translate(point.x, 0, 1, 0, 1); + point.plotX = defined(point.y) ? + yAxis.translate(point.y, 0, 0, 0, 1) : + 0; + } + else { + point.plotY = (xAxis.opposite ? 0 : series.yAxis.len) + + xAxis.offset; // For the windbarb demo + } + } + else { + point.shapeArgs = {}; // 847 + } + } + // if multiple flags appear at the same x, order them into a stack + lastPoint = points[i - 1]; + if (lastPoint && lastPoint.plotX === point.plotX) { + if (typeof lastPoint.stackIndex === 'undefined') { + lastPoint.stackIndex = 0; + } + stackIndex = lastPoint.stackIndex + 1; + } + point.stackIndex = stackIndex; // #3639 + }); + this.onSeries = onSeries; + } + /* eslint-enable valid-jsdoc */ + }; + + return onSeriesMixin; + }); + _registerModule(_modules, 'modules/windbarb.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['mixins/on-series.js']], function (H, U, onSeriesMixin) { + /* * + * + * Wind barb series module + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var animObject = U.animObject, isNumber = U.isNumber, pick = U.pick, seriesType = U.seriesType; + var noop = H.noop; + // eslint-disable-next-line valid-jsdoc + /** + * Once off, register the windbarb approximation for data grouping. This can be + * called anywhere (not necessarily in the translate function), but must happen + * after the data grouping module is loaded and before the wind barb series uses + * it. + * @private + */ + function registerApproximation() { + if (H.approximations && !H.approximations.windbarb) { + H.approximations.windbarb = function (values, directions) { + var vectorX = 0, vectorY = 0, i, len = values.length; + for (i = 0; i < len; i++) { + vectorX += values[i] * Math.cos(directions[i] * H.deg2rad); + vectorY += values[i] * Math.sin(directions[i] * H.deg2rad); + } + return [ + // Wind speed + values.reduce(function (sum, value) { + return sum + value; + }, 0) / values.length, + // Wind direction + Math.atan2(vectorY, vectorX) / H.deg2rad + ]; + }; + } + } + registerApproximation(); + /** + * @private + * @class + * @name Highcharts.seriesTypes.windbarb + * + * @augments Highcharts.Series + */ + seriesType('windbarb', 'column' + /** + * Wind barbs are a convenient way to represent wind speed and direction in + * one graphical form. Wind direction is given by the stem direction, and + * wind speed by the number and shape of barbs. + * + * @sample {highcharts|highstock} highcharts/demo/windbarb-series/ + * Wind barb series + * + * @extends plotOptions.column + * @excluding boostThreshold, marker, connectEnds, connectNulls, + * cropThreshold, dashStyle, dragDrop, gapSize, gapUnit, + * linecap, shadow, stacking, step + * @since 6.0.0 + * @product highcharts highstock + * @requires modules/windbarb + * @optionparent plotOptions.windbarb + */ + , { + /** + * Data grouping options for the wind barbs. In Highcharts, this + * requires the `modules/datagrouping.js` module to be loaded. In + * Highstock, data grouping is included. + * + * @sample highcharts/plotoptions/windbarb-datagrouping + * Wind barb with data grouping + * + * @since 7.1.0 + * @product highcharts highstock + */ + dataGrouping: { + /** + * Whether to enable data grouping. + * + * @product highcharts highstock + */ + enabled: true, + /** + * Approximation function for the data grouping. The default + * returns an average of wind speed and a vector average direction + * weighted by wind speed. + * + * @product highcharts highstock + * + * @type {string|Function} + */ + approximation: 'windbarb', + /** + * The approximate data group width. + * + * @product highcharts highstock + */ + groupPixelWidth: 30 + }, + /** + * The line width of the wind barb symbols. + */ + lineWidth: 2, + /** + * The id of another series in the chart that the wind barbs are + * projected on. When `null`, the wind symbols are drawn on the X axis, + * but offset up or down by the `yOffset` setting. + * + * @sample {highcharts|highstock} highcharts/plotoptions/windbarb-onseries + * Projected on area series + * + * @type {string|null} + */ + onSeries: null, + states: { + hover: { + lineWidthPlus: 0 + } + }, + tooltip: { + /** + * The default point format for the wind barb tooltip. Note the + * `point.beaufort` property that refers to the Beaufort wind scale. + * The names can be internationalized by modifying + * `Highcharts.seriesTypes.windbarb.prototype.beaufortNames`. + */ + pointFormat: '\u25CF {series.name}: {point.value} ({point.beaufort})
    ' + }, + /** + * Pixel length of the stems. + */ + vectorLength: 20, + /** + * @default value + */ + colorKey: 'value', + /** + * Vertical offset from the cartesian position, in pixels. The default + * value makes sure the symbols don't overlap the X axis when `onSeries` + * is `null`, and that they don't overlap the linked series when + * `onSeries` is given. + */ + yOffset: -20, + /** + * Horizontal offset from the cartesian position, in pixels. When the + * chart is inverted, this option allows translation like + * [yOffset](#plotOptions.windbarb.yOffset) in non inverted charts. + * + * @since 6.1.0 + */ + xOffset: 0 + }, { + pointArrayMap: ['value', 'direction'], + parallelArrays: ['x', 'value', 'direction'], + beaufortName: ['Calm', 'Light air', 'Light breeze', + 'Gentle breeze', 'Moderate breeze', 'Fresh breeze', + 'Strong breeze', 'Near gale', 'Gale', 'Strong gale', 'Storm', + 'Violent storm', 'Hurricane'], + beaufortFloor: [0, 0.3, 1.6, 3.4, 5.5, 8.0, 10.8, 13.9, 17.2, 20.8, + 24.5, 28.5, 32.7], + trackerGroups: ['markerGroup'], + init: function (chart, options) { + registerApproximation(); + H.Series.prototype.init.call(this, chart, options); + }, + // Get presentational attributes. + pointAttribs: function (point, state) { + var options = this.options, stroke = point.color || this.color, strokeWidth = this.options.lineWidth; + if (state) { + stroke = options.states[state].color || stroke; + strokeWidth = + (options.states[state].lineWidth || strokeWidth) + + (options.states[state].lineWidthPlus || 0); + } + return { + 'stroke': stroke, + 'stroke-width': strokeWidth + }; + }, + markerAttribs: function () { + return; + }, + getPlotBox: onSeriesMixin.getPlotBox, + // Create a single wind arrow. It is later rotated around the zero + // centerpoint. + windArrow: function (point) { + var knots = point.value * 1.943844, level = point.beaufortLevel, path, barbs, u = this.options.vectorLength / 20, pos = -10; + if (point.isNull) { + return []; + } + if (level === 0) { + return this.chart.renderer.symbols.circle(-10 * u, -10 * u, 20 * u, 20 * u); + } + // The stem and the arrow head + path = [ + ['M', 0, 7 * u], + ['L', -1.5 * u, 7 * u], + ['L', 0, 10 * u], + ['L', 1.5 * u, 7 * u], + ['L', 0, 7 * u], + ['L', 0, -10 * u] // top + ]; + // For each full 50 knots, add a pennant + barbs = (knots - knots % 50) / 50; // pennants + if (barbs > 0) { + while (barbs--) { + path.push(pos === -10 ? ['L', 0, pos * u] : ['M', 0, pos * u], ['L', 5 * u, pos * u + 2], ['L', 0, pos * u + 4]); + // Substract from the rest and move position for next + knots -= 50; + pos += 7; + } + } + // For each full 10 knots, add a full barb + barbs = (knots - knots % 10) / 10; + if (barbs > 0) { + while (barbs--) { + path.push(pos === -10 ? ['L', 0, pos * u] : ['M', 0, pos * u], ['L', 7 * u, pos * u]); + knots -= 10; + pos += 3; + } + } + // For each full 5 knots, add a half barb + barbs = (knots - knots % 5) / 5; // half barbs + if (barbs > 0) { + while (barbs--) { + path.push(pos === -10 ? ['L', 0, pos * u] : ['M', 0, pos * u], ['L', 4 * u, pos * u]); + knots -= 5; + pos += 3; + } + } + return path; + }, + translate: function () { + var beaufortFloor = this.beaufortFloor, beaufortName = this.beaufortName; + onSeriesMixin.translate.call(this); + this.points.forEach(function (point) { + var level = 0; + // Find the beaufort level (zero based) + for (; level < beaufortFloor.length; level++) { + if (beaufortFloor[level] > point.value) { + break; + } + } + point.beaufortLevel = level - 1; + point.beaufort = beaufortName[level - 1]; + }); + }, + drawPoints: function () { + var chart = this.chart, yAxis = this.yAxis, inverted = chart.inverted, shapeOffset = this.options.vectorLength / 2; + this.points.forEach(function (point) { + var plotX = point.plotX, plotY = point.plotY; + // Check if it's inside the plot area, but only for the X + // dimension. + if (this.options.clip === false || + chart.isInsidePlot(plotX, 0, false)) { + // Create the graphic the first time + if (!point.graphic) { + point.graphic = this.chart.renderer + .path() + .add(this.markerGroup) + .addClass('highcharts-point ' + + 'highcharts-color-' + + pick(point.colorIndex, point.series.colorIndex)); + } + // Position the graphic + point.graphic + .attr({ + d: this.windArrow(point), + translateX: plotX + this.options.xOffset, + translateY: plotY + this.options.yOffset, + rotation: point.direction + }); + if (!this.chart.styledMode) { + point.graphic + .attr(this.pointAttribs(point)); + } + } + else if (point.graphic) { + point.graphic = point.graphic.destroy(); + } + // Set the tooltip anchor position + point.tooltipPos = [ + plotX + this.options.xOffset + + (inverted && !this.onSeries ? shapeOffset : 0), + plotY + this.options.yOffset - + (inverted ? + 0 : + shapeOffset + yAxis.pos - chart.plotTop) + ]; // #6327 + }, this); + }, + // Fade in the arrows on initializing series. + animate: function (init) { + if (init) { + this.markerGroup.attr({ + opacity: 0.01 + }); + } + else { + this.markerGroup.animate({ + opacity: 1 + }, animObject(this.options.animation)); + } + }, + // Don't invert the marker group (#4960) + invertGroups: noop, + // No data extremes for the Y axis + getExtremes: function () { return ({}); } + }, { + isValid: function () { + return isNumber(this.value) && this.value >= 0; + } + }); + /** + * A `windbarb` series. If the [type](#series.windbarb.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.windbarb + * @excluding dataParser, dataURL + * @product highcharts highstock + * @requires modules/windbarb + * @apioption series.windbarb + */ + /** + * An array of data points for the series. For the `windbarb` series type, + * points can be given in the following ways: + * + * 1. An array of arrays with 3 values. In this case, the values correspond to + * `x,value,direction`. If the first value is a string, it is applied as the + * name of the point, and the `x` value is inferred. + * ```js + * data: [ + * [Date.UTC(2017, 0, 1, 0), 3.3, 90], + * [Date.UTC(2017, 0, 1, 1), 12.1, 180], + * [Date.UTC(2017, 0, 1, 2), 11.1, 270] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.area.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * x: Date.UTC(2017, 0, 1, 0), + * value: 12.1, + * direction: 90 + * }, { + * x: Date.UTC(2017, 0, 1, 1), + * value: 11.1, + * direction: 270 + * }] + * ``` + * + * @sample {highcharts} highcharts/chart/reflow-true/ + * Numerical values + * @sample {highcharts} highcharts/series/data-array-of-arrays/ + * Arrays of numeric x and y + * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ + * Arrays of datetime x and y + * @sample {highcharts} highcharts/series/data-array-of-name-value/ + * Arrays of point.name and y + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @type {Array|*>} + * @extends series.line.data + * @product highcharts highstock + * @apioption series.windbarb.data + */ + /** + * The wind speed in meters per second. + * + * @type {number|null} + * @product highcharts highstock + * @apioption series.windbarb.data.value + */ + /** + * The wind direction in degrees, where 0 is north (pointing towards south). + * + * @type {number} + * @product highcharts highstock + * @apioption series.windbarb.data.direction + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'masters/modules/windbarb.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/wordcloud.js b/librerias/gantt/code/modules/wordcloud.js new file mode 100644 index 0000000..70a37fb --- /dev/null +++ b/librerias/gantt/code/modules/wordcloud.js @@ -0,0 +1,27 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2016-2019 Highsoft AS + Authors: Jon Arild Nygard + + License: www.highcharts.com/license +*/ +(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/wordcloud",["highcharts"],function(l){b(l);b.Highcharts=l;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function l(b,e,z,h){b.hasOwnProperty(e)||(b[e]=h.apply(null,z))}b=b?b._modules:{};l(b,"mixins/draw-point.js",[],function(){var b=function(e){var b,h=this,p=h.graphic,t=e.animatableAttribs,u=e.onComplete,l=e.css, +q=e.renderer,y=null===(b=h.series)||void 0===b?void 0:b.options.animation;if(h.shouldDraw())p||(h.graphic=p=q[e.shapeType](e.shapeArgs).add(e.group)),p.css(l).attr(e.attribs).animate(t,e.isNew?!1:y,u);else if(p){var v=function(){h.graphic=p=p.destroy();"function"===typeof u&&u()};Object.keys(t).length?p.animate(t,void 0,function(){v()}):v()}};return function(e){(e.attribs=e.attribs||{})["class"]=this.getClassName();b.call(this,e)}});l(b,"mixins/polygon.js",[b["parts/Globals.js"],b["parts/Utilities.js"]], +function(b,e){var l=e.find,h=e.isArray,p=e.isNumber,t=b.deg2rad,u=function(a,c){c=p(c)?c:14;c=Math.pow(10,c);return Math.round(a*c)/c},H=function(a,c){var b=c[0]-a[0];a=c[1]-a[1];return[[-a,b],[a,-b]]},q=function(a,c){a=a.map(function(a){return a[0]*c[0]+a[1]*c[1]});return{min:Math.min.apply(this,a),max:Math.max.apply(this,a)}},y=function(a,c){var b=a[0];a=a[1];var k=t*-c;c=Math.cos(k);k=Math.sin(k);return[u(b*c-a*k),u(b*k+a*c)]},v=function(a,c,b){a=y([a[0]-c[0],a[1]-c[1]],b);return[a[0]+c[0],a[1]+ +c[1]]},C=function(a){var c=a.axes;if(!h(c)){c=[];var b=b=a.concat([a[0]]);b.reduce(function(a,b){var k=H(a,b)[0];l(c,function(a){return a[0]===k[0]&&a[1]===k[1]})||c.push(k);return b});a.axes=c}return c},F=function(a,c){a=C(a);c=C(c);return a.concat(c)};return{getBoundingBoxFromPolygon:function(a){return a.reduce(function(a,b){var c=b[0];b=b[1];a.left=Math.min(c,a.left);a.right=Math.max(c,a.right);a.bottom=Math.max(b,a.bottom);a.top=Math.min(b,a.top);return a},{left:Number.MAX_VALUE,right:-Number.MAX_VALUE, +bottom:-Number.MAX_VALUE,top:Number.MAX_VALUE})},getPolygon:function(a,b,e,k,h){var c=[a,b],l=a-e/2;a+=e/2;e=b-k/2;b+=k/2;return[[l,e],[a,e],[a,b],[l,b]].map(function(a){return v(a,c,-h)})},isPolygonsColliding:function(a,b){var c=F(a,b);return!l(c,function(c){var e=q(a,c);c=q(b,c);return!!(c.min>e.max||c.maxa.right||f.righta.bottom||f.bottom=g&&("boolean"===typeof c&&d>=b-a&&(c={x:f-(b-d),y:-f}),b-=a,"boolean"===typeof c&&d>=b-a&&(c={x:-f,y:-f+(b-d)}),b-=a,"boolean"===typeof c&&(c=d>=b-a?{x:-f+(b-d),y:f}:{x:f,y:f-(b-d-a)}),c.x*=5,c.y*=5);return c}function u(g,d,f){var a=2*Math.max(Math.abs(f.top),Math.abs(f.bottom));f=2*Math.max(Math.abs(f.left),Math.abs(f.right));return Math.min(0d?g/d:1;g=d>g?d/g:1;return{width:a*f,height:a*g,ratioX:f,ratioY:g}}function q(a,d,f,b){var g=!1;k(a)&&k(d)&&k(f)&&k(b)&&0f&&(g=f+d%a*((b-f)/(a-1||1)));return g}function y(a,d){var g,b=[];for(g=1;1E4>g;g++)b.push(a(g,d));return function(a){return 1E4>=a?b[a-1]:!1}}function v(a,d){var g=d.width/2,b=-(d.height/2),c=d.height/ +2;return!(-(d.width/2)a.right&&ba.bottom)}function C(g,d){var b=d.placed,c=d.field,e=d.rectangle,k=d.polygon,h=d.spiral,l=1,r={x:0,y:0},n=g.rect=a({},e);g.polygon=k;for(g.rotation=d.rotation;!1!==r&&(p(g,b)||v(n,c));)r=h(l),A(r)&&(n.left=e.left+r.x,n.right=e.right+r.x,n.top=e.top+r.y,n.bottom=e.bottom+r.y,g.polygon=K(r.x,r.y,k)),l++;return r}function F(a,d){if(A(a)&&A(d)){var g=d.bottom-d.top;var b=d.right-d.left;d=a.ratioX;var c=a.ratioY;g=b*d>g*c?b:g;a=I(a,{width:a.width+g* +d*2,height:a.height+g*c*2})}return a}var a=e.extend,c=e.find,z=e.isArray,k=e.isNumber,A=e.isObject,I=e.merge;e=e.seriesType;var B=b.noop,J=h.getBoundingBoxFromPolygon,L=h.getPolygon,D=h.isPolygonsColliding,K=h.movePolygon,E=b.Series;e("wordcloud","column",{allowExtendPlayingField:!0,animation:{duration:500},borderWidth:0,clip:!1,colorByPoint:!0,minFontSize:1,maxFontSize:25,placementStrategy:"center",rotation:{from:0,orientations:2,to:90},showInLegend:!1,spiral:"rectangular",style:{fontFamily:"sans-serif", +fontWeight:"900",whiteSpace:"nowrap"},tooltip:{followPointer:!0,pointFormat:'\u25cf {series.name}: {point.weight}
    '}},{animate:E.prototype.animate,animateDrilldown:B,animateDrillupFrom:B,setClip:B,bindAxes:function(){var g={endOnTick:!1,gridLineWidth:0,lineWidth:0,maxPadding:0,startOnTick:!1,title:null,tickPositions:[]};E.prototype.bindAxes.call(this);a(this.yAxis.options,g);a(this.xAxis.options,g)},pointAttribs:function(a,d){a=b.seriesTypes.column.prototype.pointAttribs.call(this, +a,d);delete a.stroke;delete a["stroke-width"];return a},deriveFontSize:function(a,d,b){a=k(a)?a:0;d=k(d)?d:1;b=k(b)?b:1;return Math.floor(Math.max(b,a*d))},drawPoints:function(){var b=this,d=b.hasRendered,c=b.xAxis,e=b.yAxis,l=b.group,h=b.options,p=h.animation,t=h.allowExtendPlayingField,r=b.chart.renderer,n=r.text().add(l),q=[],v=b.placementStrategy[h.placementStrategy],z=h.rotation,B=b.points.map(function(a){return a.weight}),D=Math.max.apply(null,B),G=b.points.concat().sort(function(a,b){return b.weight- +a.weight});b.group.attr({scaleX:1,scaleY:1});G.forEach(function(d){var c=b.deriveFontSize(1/D*d.weight,h.maxFontSize,h.minFontSize);c=a({fontSize:c+"px"},h.style);n.css(c).attr({x:0,y:0,text:d.name});c=n.getBBox(!0);d.dimensions={height:c.height,width:c.width}});var w=H(c.len,e.len,G);var E=y(b.spirals[h.spiral],{field:w});G.forEach(function(c){var g=b.deriveFontSize(1/D*c.weight,h.maxFontSize,h.minFontSize);g=a({fontSize:g+"px"},h.style);var f=v(c,{data:G,field:w,placed:q,rotation:z}),e=a(b.pointAttribs(c, +c.selected&&"select"),{align:"center","alignment-baseline":"middle",x:f.x,y:f.y,text:c.name,rotation:f.rotation}),n=L(f.x,f.y,c.dimensions.width,c.dimensions.height,f.rotation),m=J(n),x=C(c,{rectangle:m,polygon:n,field:w,placed:q,spiral:E,rotation:f.rotation});!x&&t&&(w=F(w,m),x=C(c,{rectangle:m,polygon:n,field:w,placed:q,spiral:E,rotation:f.rotation}));if(A(x)){e.x+=x.x;e.y+=x.y;m.left+=x.x;m.right+=x.x;m.top+=x.y;m.bottom+=x.y;f=w;if(!k(f.left)||f.left>m.left)f.left=m.left;if(!k(f.right)||f.right< +m.right)f.right=m.right;if(!k(f.top)||f.top>m.top)f.top=m.top;if(!k(f.bottom)||f.bottom=a&&(b={x:d*Math.cos(d),y:d*Math.sin(d)},Math.min(Math.abs(b.x),Math.abs(b.y))< +c||(b=!1));return b},rectangular:function(a,b){a=t(a,b);b=b.field;a&&(a.x*=b.ratioX,a.y*=b.ratioY);return a},square:t},utils:{extendPlayingField:F,getRotation:q,isPolygonsColliding:D,rotate2DToOrigin:h.rotate2DToOrigin,rotate2DToPoint:h.rotate2DToPoint},getPlotBox:function(){var a=this.chart,b=a.inverted,c=this[b?"yAxis":"xAxis"];b=this[b?"xAxis":"yAxis"];return{translateX:(c?c.left:a.plotLeft)+(c?c.len:a.plotWidth)/2,translateY:(b?b.top:a.plotTop)+(b?b.len:a.plotHeight)/2,scaleX:1,scaleY:1}}},{draw:l, +shouldDraw:function(){return!this.isNull},isValid:function(){return!0},weight:1})});l(b,"masters/modules/wordcloud.src.js",[],function(){})}); +//# sourceMappingURL=wordcloud.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/wordcloud.js.map b/librerias/gantt/code/modules/wordcloud.js.map new file mode 100644 index 0000000..e569ea6 --- /dev/null +++ b/librerias/gantt/code/modules/wordcloud.js.map @@ -0,0 +1 @@ +{"version":3,"file":"wordcloud.js.map","lineCount":26,"mappings":"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","sources":["wordcloud.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","draw","params","_a","component","graphic","animatableAttribs","onComplete","css","renderer","animation","series","options","shouldDraw","shapeType","shapeArgs","add","group","attr","attribs","animate","isNew","destroy","Object","keys","length","drawPoint","point","getClassName","call","H","U","find","isArray","isNumber","deg2rad","correctFloat","number","precision","p","magnitude","Math","pow","round","getNormals","p1","p2","dx","dy","project","polygon","target","products","map","ax","bx","ay","by","min","max","rotate2DToOrigin","angle","x","y","rad","cosAngle","cos","sinAngle","sin","rotate2DToPoint","origin","rotated","getAxesFromPolygon","axes","points","concat","reduce","findAxis","axis","normals","existing","push","getAxes","polygon1","polygon2","axes1","axes2","collision","getBoundingBoxFromPolygon","left","right","bottom","top","Number","MAX_VALUE","getPolygon","width","height","rotation","isPolygonsColliding","overlappingOnAllAxes","projection1","projection2","isOverlapping","movePolygon","deltaX","deltaY","intersectsAnyWord","intersects","rect","lastCollidedWith","isIntersecting","r2","result","squareSpiral","attempt","a","k","ceil","sqrt","t","m","getScale","targetWidth","targetHeight","field","abs","scaleX","scaleY","getPlayingField","data","info","dimensions","maxHeight","maxWidth","area","ratioX","ratioY","getRotation","orientations","index","from","to","getSpiral","i","arr","outsidePlayingField","intersectionTesting","placed","rectangle","spiral","delta","extend","isObject","extendPlayingField","merge","seriesType","noop","Series","wordCloudOptions","allowExtendPlayingField","duration","borderWidth","clip","colorByPoint","minFontSize","maxFontSize","placementStrategy","showInLegend","style","fontFamily","fontWeight","whiteSpace","tooltip","followPointer","pointFormat","wordCloudSeries","prototype","animateDrilldown","animateDrillupFrom","setClip","bindAxes","wordcloudAxis","endOnTick","gridLineWidth","lineWidth","maxPadding","startOnTick","title","tickPositions","yAxis","xAxis","pointAttribs","state","seriesTypes","column","stroke","deriveFontSize","relativeWeight","weight","floor","drawPoints","hasRendered","chart","testElement","text","weights","maxWeight","sort","b","forEach","fontSize","name","bBox","getBBox","len","spirals","placement","selected","align","isNull","scale","hasData","visible","random","r","center","pointArrayMap","archimedeanSpiral","maxDelta","rectangularSpiral","utils","getPlotBox","inverted","translateX","plotLeft","plotWidth","translateY","plotTop","plotHeight","wordCloudPoint","isValid"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/wordcloud.src.js b/librerias/gantt/code/modules/wordcloud.src.js new file mode 100644 index 0000000..e774437 --- /dev/null +++ b/librerias/gantt/code/modules/wordcloud.src.js @@ -0,0 +1,1295 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * (c) 2016-2019 Highsoft AS + * Authors: Jon Arild Nygard + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/wordcloud', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'mixins/draw-point.js', [], function () { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var isFn = function (x) { + return typeof x === 'function'; + }; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Handles the drawing of a component. + * Can be used for any type of component that reserves the graphic property, and + * provides a shouldDraw on its context. + * + * @private + * @function draw + * @param {DrawPointParams} params + * Parameters. + * + * @todo add type checking. + * @todo export this function to enable usage + */ + var draw = function draw(params) { + var _a; + var component = this, graphic = component.graphic, animatableAttribs = params.animatableAttribs, onComplete = params.onComplete, css = params.css, renderer = params.renderer, animation = (_a = component.series) === null || _a === void 0 ? void 0 : _a.options.animation; + if (component.shouldDraw()) { + if (!graphic) { + component.graphic = graphic = + renderer[params.shapeType](params.shapeArgs) + .add(params.group); + } + graphic + .css(css) + .attr(params.attribs) + .animate(animatableAttribs, params.isNew ? false : animation, onComplete); + } + else if (graphic) { + var destroy = function () { + component.graphic = graphic = graphic.destroy(); + if (isFn(onComplete)) { + onComplete(); + } + }; + // animate only runs complete callback if something was animated. + if (Object.keys(animatableAttribs).length) { + graphic.animate(animatableAttribs, void 0, function () { + destroy(); + }); + } + else { + destroy(); + } + } + }; + /** + * An extended version of draw customized for points. + * It calls additional methods that is expected when rendering a point. + * @private + * @param {Highcharts.Dictionary} params Parameters + */ + var drawPoint = function drawPoint(params) { + var point = this, attribs = params.attribs = params.attribs || {}; + // Assigning class in dot notation does go well in IE8 + // eslint-disable-next-line dot-notation + attribs['class'] = point.getClassName(); + // Call draw to render component + draw.call(point, params); + }; + + return drawPoint; + }); + _registerModule(_modules, 'mixins/polygon.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js']], function (H, U) { + /* * + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /** + * @private + * @interface Highcharts.PolygonPointObject + */ /** + * @name Highcharts.PolygonPointObject#0 + * @type {number} + */ /** + * @name Highcharts.PolygonPointObject#1 + * @type {number} + */ + /** + * @private + * @interface Highcharts.PolygonObject + * @extends Array + */ /** + * @name Highcharts.PolygonObject#axes + * @type {Array} + */ + var find = U.find, isArray = U.isArray, isNumber = U.isNumber; + var deg2rad = H.deg2rad; + /* eslint-disable no-invalid-this, valid-jsdoc */ + /** + * Alternative solution to correctFloat. + * E.g Highcharts.correctFloat(123, 2) returns 120, when it should be 123. + * + * @private + * @function correctFloat + * @param {number} number + * @param {number} [precision] + * @return {number} + */ + var correctFloat = function (number, precision) { + var p = isNumber(precision) ? precision : 14, magnitude = Math.pow(10, p); + return Math.round(number * magnitude) / magnitude; + }; + /** + * Calculates the normals to a line between two points. + * + * @private + * @function getNormals + * @param {Highcharts.PolygonPointObject} p1 + * Start point for the line. Array of x and y value. + * @param {Highcharts.PolygonPointObject} p2 + * End point for the line. Array of x and y value. + * @return {Highcharts.PolygonObject} + * Returns the two normals in an array. + */ + var getNormals = function getNormal(p1, p2) { + var dx = p2[0] - p1[0], // x2 - x1 + dy = p2[1] - p1[1]; // y2 - y1 + return [ + [-dy, dx], + [dy, -dx] + ]; + }; + /** + * Calculates the dot product of two coordinates. The result is a scalar value. + * + * @private + * @function dotProduct + * @param {Highcharts.PolygonPointObject} a + * The x and y coordinates of the first point. + * + * @param {Highcharts.PolygonPointObject} b + * The x and y coordinates of the second point. + * + * @return {number} + * Returns the dot product of a and b. + */ + var dotProduct = function dotProduct(a, b) { + var ax = a[0], ay = a[1], bx = b[0], by = b[1]; + return ax * bx + ay * by; + }; + /** + * Projects a polygon onto a coordinate. + * + * @private + * @function project + * @param {Highcharts.PolygonObject} polygon + * Array of points in a polygon. + * @param {Highcharts.PolygonPointObject} target + * The coordinate of pr + * @return {Highcharts.RangeObject} + */ + var project = function project(polygon, target) { + var products = polygon.map(function (point) { + return dotProduct(point, target); + }); + return { + min: Math.min.apply(this, products), + max: Math.max.apply(this, products) + }; + }; + /** + * Rotates a point clockwise around the origin. + * + * @private + * @function rotate2DToOrigin + * @param {Highcharts.PolygonPointObject} point + * The x and y coordinates for the point. + * @param {number} angle + * The angle of rotation. + * @return {Highcharts.PolygonPointObject} + * The x and y coordinate for the rotated point. + */ + var rotate2DToOrigin = function (point, angle) { + var x = point[0], y = point[1], rad = deg2rad * -angle, cosAngle = Math.cos(rad), sinAngle = Math.sin(rad); + return [ + correctFloat(x * cosAngle - y * sinAngle), + correctFloat(x * sinAngle + y * cosAngle) + ]; + }; + /** + * Rotate a point clockwise around another point. + * + * @private + * @function rotate2DToPoint + * @param {Highcharts.PolygonPointObject} point + * The x and y coordinates for the point. + * @param {Highcharts.PolygonPointObject} origin + * The point to rotate around. + * @param {number} angle + * The angle of rotation. + * @return {Highcharts.PolygonPointObject} + * The x and y coordinate for the rotated point. + */ + var rotate2DToPoint = function (point, origin, angle) { + var x = point[0] - origin[0], y = point[1] - origin[1], rotated = rotate2DToOrigin([x, y], angle); + return [ + rotated[0] + origin[0], + rotated[1] + origin[1] + ]; + }; + /** + * @private + */ + var isAxesEqual = function (axis1, axis2) { + return (axis1[0] === axis2[0] && + axis1[1] === axis2[1]); + }; + /** + * @private + */ + var getAxesFromPolygon = function (polygon) { + var points, axes = polygon.axes; + if (!isArray(axes)) { + axes = []; + points = points = polygon.concat([polygon[0]]); + points.reduce(function findAxis(p1, p2) { + var normals = getNormals(p1, p2), axis = normals[0]; // Use the left normal as axis. + // Check that the axis is unique. + if (!find(axes, function (existing) { + return isAxesEqual(existing, axis); + })) { + axes.push(axis); + } + // Return p2 to be used as p1 in next iteration. + return p2; + }); + polygon.axes = axes; + } + return axes; + }; + /** + * @private + */ + var getAxes = function (polygon1, polygon2) { + // Get the axis from both polygons. + var axes1 = getAxesFromPolygon(polygon1), axes2 = getAxesFromPolygon(polygon2); + return axes1.concat(axes2); + }; + /** + * @private + */ + var getPolygon = function (x, y, width, height, rotation) { + var origin = [x, y], left = x - (width / 2), right = x + (width / 2), top = y - (height / 2), bottom = y + (height / 2), polygon = [ + [left, top], + [right, top], + [right, bottom], + [left, bottom] + ]; + return polygon.map(function (point) { + return rotate2DToPoint(point, origin, -rotation); + }); + }; + /** + * @private + */ + var getBoundingBoxFromPolygon = function (points) { + return points.reduce(function (obj, point) { + var x = point[0], y = point[1]; + obj.left = Math.min(x, obj.left); + obj.right = Math.max(x, obj.right); + obj.bottom = Math.max(y, obj.bottom); + obj.top = Math.min(y, obj.top); + return obj; + }, { + left: Number.MAX_VALUE, + right: -Number.MAX_VALUE, + bottom: -Number.MAX_VALUE, + top: Number.MAX_VALUE + }); + }; + /** + * @private + */ + var isPolygonsOverlappingOnAxis = function (axis, polygon1, polygon2) { + var projection1 = project(polygon1, axis), projection2 = project(polygon2, axis), isOverlapping = !(projection2.min > projection1.max || + projection2.max < projection1.min); + return !isOverlapping; + }; + /** + * Checks wether two convex polygons are colliding by using the Separating Axis + * Theorem. + * + * @private + * @function isPolygonsColliding + * @param {Highcharts.PolygonObject} polygon1 + * First polygon. + * + * @param {Highcharts.PolygonObject} polygon2 + * Second polygon. + * + * @return {boolean} + * Returns true if they are colliding, otherwise false. + */ + var isPolygonsColliding = function isPolygonsColliding(polygon1, polygon2) { + var axes = getAxes(polygon1, polygon2), overlappingOnAllAxes = !find(axes, function (axis) { + return isPolygonsOverlappingOnAxis(axis, polygon1, polygon2); + }); + return overlappingOnAllAxes; + }; + /** + * @private + */ + var movePolygon = function (deltaX, deltaY, polygon) { + return polygon.map(function (point) { + return [ + point[0] + deltaX, + point[1] + deltaY + ]; + }); + }; + var collision = { + getBoundingBoxFromPolygon: getBoundingBoxFromPolygon, + getPolygon: getPolygon, + isPolygonsColliding: isPolygonsColliding, + movePolygon: movePolygon, + rotate2DToOrigin: rotate2DToOrigin, + rotate2DToPoint: rotate2DToPoint + }; + + return collision; + }); + _registerModule(_modules, 'modules/wordcloud.src.js', [_modules['parts/Globals.js'], _modules['parts/Utilities.js'], _modules['mixins/draw-point.js'], _modules['mixins/polygon.js']], function (H, U, drawPoint, polygon) { + /* * + * + * Experimental Highcharts module which enables visualization of a word cloud. + * + * (c) 2016-2020 Highsoft AS + * Authors: Jon Arild Nygard + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * */ + var extend = U.extend, find = U.find, isArray = U.isArray, isNumber = U.isNumber, isObject = U.isObject, merge = U.merge, seriesType = U.seriesType; + var noop = H.noop, getBoundingBoxFromPolygon = polygon.getBoundingBoxFromPolygon, getPolygon = polygon.getPolygon, isPolygonsColliding = polygon.isPolygonsColliding, movePolygon = polygon.movePolygon, Series = H.Series; + /** + * Detects if there is a collision between two rectangles. + * + * @private + * @function isRectanglesIntersecting + * + * @param {Highcharts.PolygonBoxObject} r1 + * First rectangle. + * + * @param {Highcharts.PolygonBoxObject} r2 + * Second rectangle. + * + * @return {boolean} + * Returns true if the rectangles overlap. + */ + function isRectanglesIntersecting(r1, r2) { + return !(r2.left > r1.right || + r2.right < r1.left || + r2.top > r1.bottom || + r2.bottom < r1.top); + } + /** + * Detects if a word collides with any previously placed words. + * + * @private + * @function intersectsAnyWord + * + * @param {Highcharts.Point} point + * Point which the word is connected to. + * + * @param {Array} points + * Previously placed points to check against. + * + * @return {boolean} + * Returns true if there is collision. + */ + function intersectsAnyWord(point, points) { + var intersects = false, rect = point.rect, polygon = point.polygon, lastCollidedWith = point.lastCollidedWith, isIntersecting = function (p) { + var result = isRectanglesIntersecting(rect, p.rect); + if (result && + (point.rotation % 90 || p.rotation % 90)) { + result = isPolygonsColliding(polygon, p.polygon); + } + return result; + }; + // If the point has already intersected a different point, chances are they + // are still intersecting. So as an enhancement we check this first. + if (lastCollidedWith) { + intersects = isIntersecting(lastCollidedWith); + // If they no longer intersects, remove the cache from the point. + if (!intersects) { + delete point.lastCollidedWith; + } + } + // If not already found, then check if we can find a point that is + // intersecting. + if (!intersects) { + intersects = !!find(points, function (p) { + var result = isIntersecting(p); + if (result) { + point.lastCollidedWith = p; + } + return result; + }); + } + return intersects; + } + /** + * Gives a set of cordinates for an Archimedian Spiral. + * + * @private + * @function archimedeanSpiral + * + * @param {number} attempt + * How far along the spiral we have traversed. + * + * @param {Highcharts.WordcloudSpiralParamsObject} [params] + * Additional parameters. + * + * @return {boolean|Highcharts.PositionObject} + * Resulting coordinates, x and y. False if the word should be dropped from the + * visualization. + */ + function archimedeanSpiral(attempt, params) { + var field = params.field, result = false, maxDelta = (field.width * field.width) + (field.height * field.height), t = attempt * 0.8; // 0.2 * 4 = 0.8. Enlarging the spiral. + // Emergency brake. TODO make spiralling logic more foolproof. + if (attempt <= 10000) { + result = { + x: t * Math.cos(t), + y: t * Math.sin(t) + }; + if (!(Math.min(Math.abs(result.x), Math.abs(result.y)) < maxDelta)) { + result = false; + } + } + return result; + } + /** + * Gives a set of cordinates for an rectangular spiral. + * + * @private + * @function squareSpiral + * + * @param {number} attempt + * How far along the spiral we have traversed. + * + * @param {Highcharts.WordcloudSpiralParamsObject} [params] + * Additional parameters. + * + * @return {boolean|Highcharts.PositionObject} + * Resulting coordinates, x and y. False if the word should be dropped from the + * visualization. + */ + function squareSpiral(attempt, params) { + var a = attempt * 4, k = Math.ceil((Math.sqrt(a) - 1) / 2), t = 2 * k + 1, m = Math.pow(t, 2), isBoolean = function (x) { + return typeof x === 'boolean'; + }, result = false; + t -= 1; + if (attempt <= 10000) { + if (isBoolean(result) && a >= m - t) { + result = { + x: k - (m - a), + y: -k + }; + } + m -= t; + if (isBoolean(result) && a >= m - t) { + result = { + x: -k, + y: -k + (m - a) + }; + } + m -= t; + if (isBoolean(result)) { + if (a >= m - t) { + result = { + x: -k + (m - a), + y: k + }; + } + else { + result = { + x: k, + y: k - (m - a - t) + }; + } + } + result.x *= 5; + result.y *= 5; + } + return result; + } + /** + * Gives a set of cordinates for an rectangular spiral. + * + * @private + * @function rectangularSpiral + * + * @param {number} attempt + * How far along the spiral we have traversed. + * + * @param {Highcharts.WordcloudSpiralParamsObject} [params] + * Additional parameters. + * + * @return {boolean|Higcharts.PositionObject} + * Resulting coordinates, x and y. False if the word should be dropped from the + * visualization. + */ + function rectangularSpiral(attempt, params) { + var result = squareSpiral(attempt, params), field = params.field; + if (result) { + result.x *= field.ratioX; + result.y *= field.ratioY; + } + return result; + } + /** + * @private + * @function getRandomPosition + * + * @param {number} size + * Random factor. + * + * @return {number} + * Random position. + */ + function getRandomPosition(size) { + return Math.round((size * (Math.random() + 0.5)) / 2); + } + /** + * Calculates the proper scale to fit the cloud inside the plotting area. + * + * @private + * @function getScale + * + * @param {number} targetWidth + * Width of target area. + * + * @param {number} targetHeight + * Height of target area. + * + * @param {object} field + * The playing field. + * + * @param {Highcharts.Series} series + * Series object. + * + * @return {number} + * Returns the value to scale the playing field up to the size of the target + * area. + */ + function getScale(targetWidth, targetHeight, field) { + var height = Math.max(Math.abs(field.top), Math.abs(field.bottom)) * 2, width = Math.max(Math.abs(field.left), Math.abs(field.right)) * 2, scaleX = width > 0 ? 1 / width * targetWidth : 1, scaleY = height > 0 ? 1 / height * targetHeight : 1; + return Math.min(scaleX, scaleY); + } + /** + * Calculates what is called the playing field. The field is the area which all + * the words are allowed to be positioned within. The area is proportioned to + * match the target aspect ratio. + * + * @private + * @function getPlayingField + * + * @param {number} targetWidth + * Width of the target area. + * + * @param {number} targetHeight + * Height of the target area. + * + * @param {Array} data + * Array of points. + * + * @param {object} data.dimensions + * The height and width of the word. + * + * @return {object} + * The width and height of the playing field. + */ + function getPlayingField(targetWidth, targetHeight, data) { + var info = data.reduce(function (obj, point) { + var dimensions = point.dimensions, x = Math.max(dimensions.width, dimensions.height); + // Find largest height. + obj.maxHeight = Math.max(obj.maxHeight, dimensions.height); + // Find largest width. + obj.maxWidth = Math.max(obj.maxWidth, dimensions.width); + // Sum up the total maximum area of all the words. + obj.area += x * x; + return obj; + }, { + maxHeight: 0, + maxWidth: 0, + area: 0 + }), + /** + * Use largest width, largest height, or root of total area to give size + * to the playing field. + */ + x = Math.max(info.maxHeight, // Have enough space for the tallest word + info.maxWidth, // Have enough space for the broadest word + // Adjust 15% to account for close packing of words + Math.sqrt(info.area) * 0.85), ratioX = targetWidth > targetHeight ? targetWidth / targetHeight : 1, ratioY = targetHeight > targetWidth ? targetHeight / targetWidth : 1; + return { + width: x * ratioX, + height: x * ratioY, + ratioX: ratioX, + ratioY: ratioY + }; + } + /** + * Calculates a number of degrees to rotate, based upon a number of orientations + * within a range from-to. + * + * @private + * @function getRotation + * + * @param {number} [orientations] + * Number of orientations. + * + * @param {number} [index] + * Index of point, used to decide orientation. + * + * @param {number} [from] + * The smallest degree of rotation. + * + * @param {number} [to] + * The largest degree of rotation. + * + * @return {boolean|number} + * Returns the resulting rotation for the word. Returns false if invalid input + * parameters. + */ + function getRotation(orientations, index, from, to) { + var result = false, // Default to false + range, intervals, orientation; + // Check if we have valid input parameters. + if (isNumber(orientations) && + isNumber(index) && + isNumber(from) && + isNumber(to) && + orientations > 0 && + index > -1 && + to > from) { + range = to - from; + intervals = range / (orientations - 1 || 1); + orientation = index % orientations; + result = from + (orientation * intervals); + } + return result; + } + /** + * Calculates the spiral positions and store them in scope for quick access. + * + * @private + * @function getSpiral + * + * @param {Function} fn + * The spiral function. + * + * @param {object} params + * Additional parameters for the spiral. + * + * @return {Function} + * Function with access to spiral positions. + */ + function getSpiral(fn, params) { + var length = 10000, i, arr = []; + for (i = 1; i < length; i++) { + arr.push(fn(i, params)); // @todo unnecessary amount of precaclulation + } + return function (attempt) { + return attempt <= length ? arr[attempt - 1] : false; + }; + } + /** + * Detects if a word is placed outside the playing field. + * + * @private + * @function outsidePlayingField + * + * @param {Highcharts.PolygonBoxObject} rect + * The word box. + * + * @param {Highcharts.WordcloudFieldObject} field + * The width and height of the playing field. + * + * @return {boolean} + * Returns true if the word is placed outside the field. + */ + function outsidePlayingField(rect, field) { + var playingField = { + left: -(field.width / 2), + right: field.width / 2, + top: -(field.height / 2), + bottom: field.height / 2 + }; + return !(playingField.left < rect.left && + playingField.right > rect.right && + playingField.top < rect.top && + playingField.bottom > rect.bottom); + } + /** + * Check if a point intersects with previously placed words, or if it goes + * outside the field boundaries. If a collision, then try to adjusts the + * position. + * + * @private + * @function intersectionTesting + * + * @param {Highcharts.Point} point + * Point to test for intersections. + * + * @param {Highcharts.WordcloudTestOptionsObject} options + * Options object. + * + * @return {boolean|Highcharts.PositionObject} + * Returns an object with how much to correct the positions. Returns false if + * the word should not be placed at all. + */ + function intersectionTesting(point, options) { + var placed = options.placed, field = options.field, rectangle = options.rectangle, polygon = options.polygon, spiral = options.spiral, attempt = 1, delta = { + x: 0, + y: 0 + }, + // Make a copy to update values during intersection testing. + rect = point.rect = extend({}, rectangle); + point.polygon = polygon; + point.rotation = options.rotation; + /* while w intersects any previously placed words: + do { + move w a little bit along a spiral path + } while any part of w is outside the playing field and + the spiral radius is still smallish */ + while (delta !== false && + (intersectsAnyWord(point, placed) || + outsidePlayingField(rect, field))) { + delta = spiral(attempt); + if (isObject(delta)) { + // Update the DOMRect with new positions. + rect.left = rectangle.left + delta.x; + rect.right = rectangle.right + delta.x; + rect.top = rectangle.top + delta.y; + rect.bottom = rectangle.bottom + delta.y; + point.polygon = movePolygon(delta.x, delta.y, polygon); + } + attempt++; + } + return delta; + } + /** + * Extends the playing field to have enough space to fit a given word. + * + * @private + * @function extendPlayingField + * + * @param {Highcharts.WordcloudFieldObject} field + * The width, height and ratios of a playing field. + * + * @param {Highcharts.PolygonBoxObject} rectangle + * The bounding box of the word to add space for. + * + * @return {Highcharts.WordcloudFieldObject} + * Returns the extended playing field with updated height and width. + */ + function extendPlayingField(field, rectangle) { + var height, width, ratioX, ratioY, x, extendWidth, extendHeight, result; + if (isObject(field) && isObject(rectangle)) { + height = (rectangle.bottom - rectangle.top); + width = (rectangle.right - rectangle.left); + ratioX = field.ratioX; + ratioY = field.ratioY; + // Use the same variable to extend both the height and width. + x = ((width * ratioX) > (height * ratioY)) ? width : height; + // Multiply variable with ratios to preserve aspect ratio. + extendWidth = x * ratioX; + extendHeight = x * ratioY; + // Calculate the size of the new field after adding space for the word. + result = merge(field, { + // Add space on the left and right. + width: field.width + (extendWidth * 2), + // Add space on the top and bottom. + height: field.height + (extendHeight * 2) + }); + } + else { + result = field; + } + // Return the new extended field. + return result; + } + /** + * If a rectangle is outside a give field, then the boundaries of the field is + * adjusted accordingly. Modifies the field object which is passed as the first + * parameter. + * + * @private + * @function updateFieldBoundaries + * + * @param {Highcharts.WordcloudFieldObject} field + * The bounding box of a playing field. + * + * @param {Highcharts.PolygonBoxObject} rectangle + * The bounding box for a placed point. + * + * @return {Highcharts.WordcloudFieldObject} + * Returns a modified field object. + */ + function updateFieldBoundaries(field, rectangle) { + // @todo improve type checking. + if (!isNumber(field.left) || field.left > rectangle.left) { + field.left = rectangle.left; + } + if (!isNumber(field.right) || field.right < rectangle.right) { + field.right = rectangle.right; + } + if (!isNumber(field.top) || field.top > rectangle.top) { + field.top = rectangle.top; + } + if (!isNumber(field.bottom) || field.bottom < rectangle.bottom) { + field.bottom = rectangle.bottom; + } + return field; + } + /** + * A word cloud is a visualization of a set of words, where the size and + * placement of a word is determined by how it is weighted. + * + * @sample highcharts/demo/wordcloud + * Word Cloud chart + * + * @extends plotOptions.column + * @excluding allAreas, boostThreshold, clip, colorAxis, compare, + * compareBase, crisp, cropTreshold, dataGrouping, dataLabels, + * depth, dragDrop, edgeColor, findNearestPointBy, + * getExtremesFromAll, grouping, groupPadding, groupZPadding, + * joinBy, maxPointWidth, minPointLength, navigatorOptions, + * negativeColor, pointInterval, pointIntervalUnit, pointPadding, + * pointPlacement, pointRange, pointStart, pointWidth, pointStart, + * pointWidth, shadow, showCheckbox, showInNavigator, + * softThreshold, stacking, threshold, zoneAxis, zones, + * dataSorting + * @product highcharts + * @since 6.0.0 + * @requires modules/wordcloud + * @optionparent plotOptions.wordcloud + */ + var wordCloudOptions = { + /** + * If there is no space for a word on the playing field, then this option + * will allow the playing field to be extended to fit the word. If false + * then the word will be dropped from the visualization. + * + * NB! This option is currently not decided to be published in the API, and + * is therefore marked as private. + * + * @private + */ + allowExtendPlayingField: true, + animation: { + /** @internal */ + duration: 500 + }, + borderWidth: 0, + clip: false, + colorByPoint: true, + /** + * A threshold determining the minimum font size that can be applied to a + * word. + */ + minFontSize: 1, + /** + * The word with the largest weight will have a font size equal to this + * value. The font size of a word is the ratio between its weight and the + * largest occuring weight, multiplied with the value of maxFontSize. + */ + maxFontSize: 25, + /** + * This option decides which algorithm is used for placement, and rotation + * of a word. The choice of algorith is therefore a crucial part of the + * resulting layout of the wordcloud. It is possible for users to add their + * own custom placement strategies for use in word cloud. Read more about it + * in our + * [documentation](https://www.highcharts.com/docs/chart-and-series-types/word-cloud-series#custom-placement-strategies) + * + * @validvalue: ["center", "random"] + */ + placementStrategy: 'center', + /** + * Rotation options for the words in the wordcloud. + * + * @sample highcharts/plotoptions/wordcloud-rotation + * Word cloud with rotation + */ + rotation: { + /** + * The smallest degree of rotation for a word. + */ + from: 0, + /** + * The number of possible orientations for a word, within the range of + * `rotation.from` and `rotation.to`. Must be a number larger than 0. + */ + orientations: 2, + /** + * The largest degree of rotation for a word. + */ + to: 90 + }, + showInLegend: false, + /** + * Spiral used for placing a word after the initial position experienced a + * collision with either another word or the borders. + * It is possible for users to add their own custom spiralling algorithms + * for use in word cloud. Read more about it in our + * [documentation](https://www.highcharts.com/docs/chart-and-series-types/word-cloud-series#custom-spiralling-algorithm) + * + * @validvalue: ["archimedean", "rectangular", "square"] + */ + spiral: 'rectangular', + /** + * CSS styles for the words. + * + * @type {Highcharts.CSSObject} + * @default {"fontFamily":"sans-serif", "fontWeight": "900"} + */ + style: { + /** @ignore-option */ + fontFamily: 'sans-serif', + /** @ignore-option */ + fontWeight: '900', + /** @ignore-option */ + whiteSpace: 'nowrap' + }, + tooltip: { + followPointer: true, + pointFormat: '\u25CF {series.name}: {point.weight}
    ' + } + }; + // Properties of the WordCloud series. + var wordCloudSeries = { + animate: Series.prototype.animate, + animateDrilldown: noop, + animateDrillupFrom: noop, + setClip: noop, + bindAxes: function () { + var wordcloudAxis = { + endOnTick: false, + gridLineWidth: 0, + lineWidth: 0, + maxPadding: 0, + startOnTick: false, + title: null, + tickPositions: [] + }; + Series.prototype.bindAxes.call(this); + extend(this.yAxis.options, wordcloudAxis); + extend(this.xAxis.options, wordcloudAxis); + }, + pointAttribs: function (point, state) { + var attribs = H.seriesTypes.column.prototype + .pointAttribs.call(this, point, state); + delete attribs.stroke; + delete attribs['stroke-width']; + return attribs; + }, + /** + * Calculates the fontSize of a word based on its weight. + * + * @private + * @function Highcharts.Series#deriveFontSize + * + * @param {number} [relativeWeight=0] + * The weight of the word, on a scale 0-1. + * + * @param {number} [maxFontSize=1] + * The maximum font size of a word. + * + * @param {number} [minFontSize=1] + * The minimum font size of a word. + * + * @return {number} + * Returns the resulting fontSize of a word. If minFontSize is larger then + * maxFontSize the result will equal minFontSize. + */ + deriveFontSize: function deriveFontSize(relativeWeight, maxFontSize, minFontSize) { + var weight = isNumber(relativeWeight) ? relativeWeight : 0, max = isNumber(maxFontSize) ? maxFontSize : 1, min = isNumber(minFontSize) ? minFontSize : 1; + return Math.floor(Math.max(min, weight * max)); + }, + drawPoints: function () { + var series = this, hasRendered = series.hasRendered, xAxis = series.xAxis, yAxis = series.yAxis, chart = series.chart, group = series.group, options = series.options, animation = options.animation, allowExtendPlayingField = options.allowExtendPlayingField, renderer = chart.renderer, testElement = renderer.text().add(group), placed = [], placementStrategy = series.placementStrategy[options.placementStrategy], spiral, rotation = options.rotation, scale, weights = series.points.map(function (p) { + return p.weight; + }), maxWeight = Math.max.apply(null, weights), + // concat() prevents from sorting the original array. + data = series.points.concat().sort(function (a, b) { + return b.weight - a.weight; // Sort descending + }), field; + // Reset the scale before finding the dimensions (#11993). + // SVGGRaphicsElement.getBBox() (used in SVGElement.getBBox(boolean)) + // returns slightly different values for the same element depending on + // whether it is rendered in a group which has already defined scale + // (e.g. 6) or in the group without a scale (scale = 1). + series.group.attr({ + scaleX: 1, + scaleY: 1 + }); + // Get the dimensions for each word. + // Used in calculating the playing field. + data.forEach(function (point) { + var relativeWeight = 1 / maxWeight * point.weight, fontSize = series.deriveFontSize(relativeWeight, options.maxFontSize, options.minFontSize), css = extend({ + fontSize: fontSize + 'px' + }, options.style), bBox; + testElement.css(css).attr({ + x: 0, + y: 0, + text: point.name + }); + bBox = testElement.getBBox(true); + point.dimensions = { + height: bBox.height, + width: bBox.width + }; + }); + // Calculate the playing field. + field = getPlayingField(xAxis.len, yAxis.len, data); + spiral = getSpiral(series.spirals[options.spiral], { + field: field + }); + // Draw all the points. + data.forEach(function (point) { + var relativeWeight = 1 / maxWeight * point.weight, fontSize = series.deriveFontSize(relativeWeight, options.maxFontSize, options.minFontSize), css = extend({ + fontSize: fontSize + 'px' + }, options.style), placement = placementStrategy(point, { + data: data, + field: field, + placed: placed, + rotation: rotation + }), attr = extend(series.pointAttribs(point, (point.selected && 'select')), { + align: 'center', + 'alignment-baseline': 'middle', + x: placement.x, + y: placement.y, + text: point.name, + rotation: placement.rotation + }), polygon = getPolygon(placement.x, placement.y, point.dimensions.width, point.dimensions.height, placement.rotation), rectangle = getBoundingBoxFromPolygon(polygon), delta = intersectionTesting(point, { + rectangle: rectangle, + polygon: polygon, + field: field, + placed: placed, + spiral: spiral, + rotation: placement.rotation + }), animate; + // If there is no space for the word, extend the playing field. + if (!delta && allowExtendPlayingField) { + // Extend the playing field to fit the word. + field = extendPlayingField(field, rectangle); + // Run intersection testing one more time to place the word. + delta = intersectionTesting(point, { + rectangle: rectangle, + polygon: polygon, + field: field, + placed: placed, + spiral: spiral, + rotation: placement.rotation + }); + } + // Check if point was placed, if so delete it, otherwise place it on + // the correct positions. + if (isObject(delta)) { + attr.x += delta.x; + attr.y += delta.y; + rectangle.left += delta.x; + rectangle.right += delta.x; + rectangle.top += delta.y; + rectangle.bottom += delta.y; + field = updateFieldBoundaries(field, rectangle); + placed.push(point); + point.isNull = false; + } + else { + point.isNull = true; + } + if (animation) { + // Animate to new positions + animate = { + x: attr.x, + y: attr.y + }; + // Animate from center of chart + if (!hasRendered) { + attr.x = 0; + attr.y = 0; + // or animate from previous position + } + else { + delete attr.x; + delete attr.y; + } + } + point.draw({ + animatableAttribs: animate, + attribs: attr, + css: css, + group: group, + renderer: renderer, + shapeArgs: void 0, + shapeType: 'text' + }); + }); + // Destroy the element after use. + testElement = testElement.destroy(); + // Scale the series group to fit within the plotArea. + scale = getScale(xAxis.len, yAxis.len, field); + series.group.attr({ + scaleX: scale, + scaleY: scale + }); + }, + hasData: function () { + var series = this; + return (isObject(series) && + series.visible === true && + isArray(series.points) && + series.points.length > 0); + }, + // Strategies used for deciding rotation and initial position of a word. To + // implement a custom strategy, have a look at the function random for + // example. + placementStrategy: { + random: function (point, options) { + var field = options.field, r = options.rotation; + return { + x: getRandomPosition(field.width) - (field.width / 2), + y: getRandomPosition(field.height) - (field.height / 2), + rotation: getRotation(r.orientations, point.index, r.from, r.to) + }; + }, + center: function (point, options) { + var r = options.rotation; + return { + x: 0, + y: 0, + rotation: getRotation(r.orientations, point.index, r.from, r.to) + }; + } + }, + pointArrayMap: ['weight'], + // Spirals used for placing a word after the initial position experienced a + // collision with either another word or the borders. To implement a custom + // spiral, look at the function archimedeanSpiral for example. + spirals: { + 'archimedean': archimedeanSpiral, + 'rectangular': rectangularSpiral, + 'square': squareSpiral + }, + utils: { + extendPlayingField: extendPlayingField, + getRotation: getRotation, + isPolygonsColliding: isPolygonsColliding, + rotate2DToOrigin: polygon.rotate2DToOrigin, + rotate2DToPoint: polygon.rotate2DToPoint + }, + getPlotBox: function () { + var series = this, chart = series.chart, inverted = chart.inverted, + // Swap axes for inverted (#2339) + xAxis = series[(inverted ? 'yAxis' : 'xAxis')], yAxis = series[(inverted ? 'xAxis' : 'yAxis')], width = xAxis ? xAxis.len : chart.plotWidth, height = yAxis ? yAxis.len : chart.plotHeight, x = xAxis ? xAxis.left : chart.plotLeft, y = yAxis ? yAxis.top : chart.plotTop; + return { + translateX: x + (width / 2), + translateY: y + (height / 2), + scaleX: 1, + scaleY: 1 + }; + } + }; + // Properties of the Sunburst series. + var wordCloudPoint = { + draw: drawPoint, + shouldDraw: function shouldDraw() { + var point = this; + return !point.isNull; + }, + isValid: function isValid() { + return true; + }, + weight: 1 + }; + /** + * A `wordcloud` series. If the [type](#series.wordcloud.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.wordcloud + * @exclude dataSorting + * @product highcharts + * @requires modules/wordcloud + * @apioption series.wordcloud + */ + /** + * An array of data points for the series. For the `wordcloud` series type, + * points can be given in the following ways: + * + * 1. An array of arrays with 2 values. In this case, the values correspond to + * `name,weight`. + * ```js + * data: [ + * ['Lorem', 4], + * ['Ipsum', 1] + * ] + * ``` + * + * 2. An array of objects with named values. The following snippet shows only a + * few settings, see the complete options set below. If the total number of + * data points exceeds the series' + * [turboThreshold](#series.arearange.turboThreshold), this option is not + * available. + * ```js + * data: [{ + * name: "Lorem", + * weight: 4 + * }, { + * name: "Ipsum", + * weight: 1 + * }] + * ``` + * + * @type {Array|*>} + * @extends series.line.data + * @excluding drilldown, marker, x, y + * @product highcharts + * @apioption series.wordcloud.data + */ + /** + * The name decides the text for a word. + * + * @type {string} + * @since 6.0.0 + * @product highcharts + * @apioption series.sunburst.data.name + */ + /** + * The weighting of a word. The weight decides the relative size of a word + * compared to the rest of the collection. + * + * @type {number} + * @since 6.0.0 + * @product highcharts + * @apioption series.sunburst.data.weight + */ + /** + * @private + * @class + * @name Highcharts.seriesTypes.wordcloud + * + * @augments Highcharts.Series + */ + seriesType('wordcloud', 'column', wordCloudOptions, wordCloudSeries, wordCloudPoint); + + }); + _registerModule(_modules, 'masters/modules/wordcloud.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/modules/xrange.js b/librerias/gantt/code/modules/xrange.js new file mode 100644 index 0000000..98120c4 --- /dev/null +++ b/librerias/gantt/code/modules/xrange.js @@ -0,0 +1,22 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + X-range series + + (c) 2010-2019 Torstein Honsi, Lars A. V. Cabrera + + License: www.highcharts.com/license +*/ +(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/xrange",["highcharts"],function(h){b(h);b.Highcharts=h;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function h(b,n,h,f){b.hasOwnProperty(n)||(b[n]=f.apply(null,h))}b=b?b._modules:{};h(b,"modules/xrange.src.js",[b["parts/Globals.js"],b["parts/Color.js"],b["parts/Point.js"],b["parts/Utilities.js"]],function(b,h,w,f){var n= +h.parse;h=f.addEvent;var p=f.clamp,A=f.correctFloat,B=f.defined,x=f.find,r=f.isNumber,u=f.isObject,t=f.merge,v=f.pick;f=f.seriesType;var y=b.seriesTypes.column,z=b.seriesTypes,C=b.Axis,D=b.Series;f("xrange","column",{colorByPoint:!0,dataLabels:{formatter:function(){var a=this.point.partialFill;u(a)&&(a=a.amount);if(r(a)&&0{point.x} - {point.x2}
    ',pointFormat:'\u25cf {series.name}: {point.yCategory}
    '}, +borderRadius:3,pointRange:0},{type:"xrange",parallelArrays:["x","x2","y"],requireSorting:!1,animate:z.line.prototype.animate,cropShoulder:1,getExtremesFromAll:!0,autoIncrement:b.noop,buildKDTree:b.noop,init:function(){z.column.prototype.init.apply(this,arguments);this.options.stacking=void 0},getColumnMetrics:function(){function a(){g.series.forEach(function(a){var c=a.xAxis;a.xAxis=a.yAxis;a.yAxis=c})}var g=this.chart;a();var d=y.prototype.getColumnMetrics.call(this);a();return d},cropData:function(a, +g,d,b){g=D.prototype.cropData.call(this,this.x2Data,g,d,b);g.xData=a.slice(g.start,g.end);return g},findPointIndex:function(a){var g=this.cropped,d=this.cropStart,b=this.points,c=a.id;if(c)var e=(e=x(b,function(a){return a.id===c}))?e.index:void 0;"undefined"===typeof e&&(e=(e=x(b,function(c){return c.x===a.x&&c.x2===a.x2&&!c.touched}))?e.index:void 0);g&&r(e)&&r(d)&&e>=d&&(e-=d);return e},translatePoint:function(a){var g=this.xAxis,d=this.yAxis,b=this.columnMetrics,c=this.options,e=c.minPointLength|| +0,f=a.plotX,h=v(a.x2,a.x+(a.len||0)),k=g.translate(h,0,0,0,1);h=Math.abs(k-f);var m=this.chart.inverted,n=v(c.borderWidth,1)%2/2,l=b.offset,q=Math.round(b.width);e&&(e-=h,0>e&&(e=0),f-=e/2,k+=e/2);f=Math.max(f,-10);k=p(k,-10,g.len+10);B(a.options.pointWidth)&&(l-=(Math.ceil(a.options.pointWidth)-q)/2,q=Math.ceil(a.options.pointWidth));c.pointPlacement&&r(a.plotY)&&d.categories&&(a.plotY=d.translate(a.y,0,1,0,1,c.pointPlacement));a.shapeArgs={x:Math.floor(Math.min(f,k))+n,y:Math.floor(a.plotY+l)+n, +width:Math.round(Math.abs(k-f)),height:q,r:this.options.borderRadius};c=a.shapeArgs.x;e=c+a.shapeArgs.width;0>c||e>g.len?(c=p(c,0,g.len),e=p(e,0,g.len),k=e-c,a.dlBox=t(a.shapeArgs,{x:c,width:e-c,centerX:k?k/2:null})):a.dlBox=null;c=a.tooltipPos;e=m?1:0;k=m?0:1;b=this.columnMetrics?this.columnMetrics.offset:-b.width/2;c[e]=p(c[e]+h/2*(g.reversed?-1:1)*(m?-1:1),0,g.len-1);c[k]=p(c[k]+(m?-1:1)*b,0,d.len-1);if(b=a.partialFill)u(b)&&(b=b.amount),r(b)||(b=0),d=a.shapeArgs,a.partShapeArgs={x:d.x,y:d.y,width:d.width, +height:d.height,r:this.options.borderRadius},f=Math.max(Math.round(h*b+a.plotX-f),0),a.clipRectArgs={x:g.reversed?d.x+h-f:d.x,y:d.y,width:f,height:d.height}},translate:function(){y.prototype.translate.apply(this,arguments);this.points.forEach(function(a){this.translatePoint(a)},this)},drawPoint:function(a,b){var d=this.options,g=this.chart.renderer,c=a.graphic,e=a.shapeType,f=a.shapeArgs,h=a.partShapeArgs,k=a.clipRectArgs,m=a.partialFill,p=d.stacking&&!d.borderRadius,l=a.state,q=d.states[l||"normal"]|| +{},r="undefined"===typeof l?"attr":b;l=this.pointAttribs(a,l);q=v(this.chart.options.chart.animation,q.animation);if(a.isNull||!1===a.visible)c&&(a.graphic=c.destroy());else{if(c)c.rect[b](f);else a.graphic=c=g.g("point").addClass(a.getClassName()).add(a.group||this.group),c.rect=g[e](t(f)).addClass(a.getClassName()).addClass("highcharts-partfill-original").add(c);h&&(c.partRect?(c.partRect[b](t(h)),c.partialClipRect[b](t(k))):(c.partialClipRect=g.clipRect(k.x,k.y,k.width,k.height),c.partRect=g[e](h).addClass("highcharts-partfill-overlay").add(c).clip(c.partialClipRect))); +this.chart.styledMode||(c.rect[b](l,q).shadow(d.shadow,null,p),h&&(u(m)||(m={}),u(d.partialFill)&&(m=t(m,d.partialFill)),a=m.fill||n(l.fill).brighten(-.3).get()||n(a.color||this.color).brighten(-.3).get(),l.fill=a,c.partRect[r](l,q).shadow(d.shadow,null,p)))}},drawPoints:function(){var a=this,b=a.getAnimationVerb();a.points.forEach(function(g){a.drawPoint(g,b)})},getAnimationVerb:function(){return this.chart.pointCount<(this.options.animationLimit||250)?"animate":"attr"}},{resolveColor:function(){var a= +this.series;if(a.options.colorByPoint&&!this.options.color){var b=a.options.colors||a.chart.options.colors;var d=this.y%(b?b.length:a.chart.options.chart.colorCount);b=b&&b[d];a.chart.styledMode||(this.color=b);this.options.colorIndex||(this.colorIndex=d)}else this.color||(this.color=a.color)},init:function(){w.prototype.init.apply(this,arguments);this.y||(this.y=0);return this},setState:function(){w.prototype.setState.apply(this,arguments);this.series.drawPoint(this,this.series.getAnimationVerb())}, +getLabelConfig:function(){var a=w.prototype.getLabelConfig.call(this),b=this.series.yAxis.categories;a.x2=this.x2;a.yCategory=this.yCategory=b&&b[this.y];return a},tooltipDateKeys:["x","x2"],isValid:function(){return"number"===typeof this.x&&"number"===typeof this.x2}});h(C,"afterGetSeriesExtremes",function(){var a=this.series,b;if(this.isXAxis){var d=v(this.dataMax,-Number.MAX_VALUE);a.forEach(function(a){a.x2Data&&a.x2Data.forEach(function(a){a>d&&(d=a,b=!0)})});b&&(this.dataMax=d)}});""});h(b, +"masters/modules/xrange.src.js",[],function(){})}); +//# sourceMappingURL=xrange.js.map \ No newline at end of file diff --git a/librerias/gantt/code/modules/xrange.js.map b/librerias/gantt/code/modules/xrange.js.map new file mode 100644 index 0000000..9871a2e --- /dev/null +++ b/librerias/gantt/code/modules/xrange.js.map @@ -0,0 +1 @@ +{"version":3,"file":"xrange.js.map","lineCount":21,"mappings":"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","sources":["xrange.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","H","Color","Point","U","color","parse","addEvent","clamp","correctFloat","defined","find","isNumber","isObject","merge","pick","seriesType","columnType","seriesTypes","column","Axis","Series","colorByPoint","dataLabels","formatter","amount","point","partialFill","inside","verticalAlign","tooltip","headerFormat","pointFormat","borderRadius","pointRange","type","parallelArrays","requireSorting","animate","line","prototype","cropShoulder","getExtremesFromAll","autoIncrement","noop","buildKDTree","init","arguments","options","stacking","getColumnMetrics","swapAxes","chart","series","forEach","s","xAxis","yAxis","metrics","call","cropData","xData","yData","min","max","crop","x2Data","slice","start","end","findPointIndex","cropped","_a","cropStart","points","id","pointIndex","index","x","x2","touched","translatePoint","columnMetrics","minPointLength","plotX","posX","len","plotX2","translate","length","Math","abs","inverted","crisper","borderWidth","yOffset","offset","pointHeight","round","width","widthDifference","pointWidth","ceil","pointPlacement","plotY","categories","y","shapeArgs","floor","height","r","dlLeft","dlRight","dlWidth","dlBox","centerX","tooltipPos","xIndex","yIndex","tooltipYOffset","reversed","partShapeArgs","clipRectWidth","clipRectArgs","drawPoint","verb","seriesOpts","renderer","graphic","shapeType","pfOptions","cutOff","pointState","state","stateOpts","states","pointStateVerb","pointAttr","pointAttribs","animation","isNull","visible","destroy","rect","g","addClass","getClassName","add","group","partRect","partialClipRect","clipRect","clip","styledMode","shadow","fill","brighten","get","drawPoints","getAnimationVerb","pointCount","animationLimit","resolveColor","colors","colorIndex","colorCount","setState","getLabelConfig","cfg","yCats","yCategory","tooltipDateKeys","isValid","axisSeries","axis","modMax","isXAxis","dataMax","Number","MAX_VALUE","val"]} \ No newline at end of file diff --git a/librerias/gantt/code/modules/xrange.src.js b/librerias/gantt/code/modules/xrange.src.js new file mode 100644 index 0000000..3ee21e9 --- /dev/null +++ b/librerias/gantt/code/modules/xrange.src.js @@ -0,0 +1,703 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * X-range series + * + * (c) 2010-2019 Torstein Honsi, Lars A. V. Cabrera + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/modules/xrange', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'modules/xrange.src.js', [_modules['parts/Globals.js'], _modules['parts/Color.js'], _modules['parts/Point.js'], _modules['parts/Utilities.js']], function (H, Color, Point, U) { + /* * + * + * X-range series module + * + * (c) 2010-2020 Torstein Honsi, Lars A. V. Cabrera + * + * License: www.highcharts.com/license + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /* * + * @interface Highcharts.PointOptionsObject in parts/Point.ts + */ /** + * The ending X value of the range point. + * @name Highcharts.PointOptionsObject#x2 + * @type {number|undefined} + * @requires modules/xrange + */ + var color = Color.parse; + var addEvent = U.addEvent, clamp = U.clamp, correctFloat = U.correctFloat, defined = U.defined, find = U.find, isNumber = U.isNumber, isObject = U.isObject, merge = U.merge, pick = U.pick, seriesType = U.seriesType; + var columnType = H.seriesTypes.column, seriesTypes = H.seriesTypes, Axis = H.Axis, Series = H.Series; + /** + * Return color of a point based on its category. + * + * @private + * @function getColorByCategory + * + * @param {object} series + * The series which the point belongs to. + * + * @param {object} point + * The point to calculate its color for. + * + * @return {object} + * Returns an object containing the properties color and colorIndex. + */ + function getColorByCategory(series, point) { + var colors = series.options.colors || series.chart.options.colors, colorCount = colors ? + colors.length : + series.chart.options.chart.colorCount, colorIndex = point.y % colorCount, color = colors && colors[colorIndex]; + return { + colorIndex: colorIndex, + color: color + }; + } + /** + * @private + * @class + * @name Highcharts.seriesTypes.xrange + * + * @augments Highcharts.Series + */ + seriesType('xrange', 'column' + /** + * The X-range series displays ranges on the X axis, typically time + * intervals with a start and end date. + * + * @sample {highcharts} highcharts/demo/x-range/ + * X-range + * @sample {highcharts} highcharts/css/x-range/ + * Styled mode X-range + * @sample {highcharts} highcharts/chart/inverted-xrange/ + * Inverted X-range + * + * @extends plotOptions.column + * @since 6.0.0 + * @product highcharts highstock gantt + * @excluding boostThreshold, crisp, cropThreshold, depth, edgeColor, + * edgeWidth, findNearestPointBy, getExtremesFromAll, + * negativeColor, pointInterval, pointIntervalUnit, + * pointPlacement, pointRange, pointStart, softThreshold, + * stacking, threshold, data, dataSorting + * @requires modules/xrange + * @optionparent plotOptions.xrange + */ + , { + /** + * A partial fill for each point, typically used to visualize how much + * of a task is performed. The partial fill object can be set either on + * series or point level. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range with partial fill + * + * @product highcharts highstock gantt + * @apioption plotOptions.xrange.partialFill + */ + /** + * The fill color to be used for partial fills. Defaults to a darker + * shade of the point color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock gantt + * @apioption plotOptions.xrange.partialFill.fill + */ + /** + * A partial fill for each point, typically used to visualize how much + * of a task is performed. See [completed](series.gantt.data.completed). + * + * @sample gantt/demo/progress-indicator + * Gantt with progress indicator + * + * @product gantt + * @apioption plotOptions.gantt.partialFill + */ + /** + * In an X-range series, this option makes all points of the same Y-axis + * category the same color. + */ + colorByPoint: true, + dataLabels: { + formatter: function () { + var point = this.point, amount = point.partialFill; + if (isObject(amount)) { + amount = amount.amount; + } + if (isNumber(amount) && amount > 0) { + return correctFloat(amount * 100) + '%'; + } + }, + inside: true, + verticalAlign: 'middle' + }, + tooltip: { + headerFormat: '{point.x} - {point.x2}
    ', + pointFormat: '\u25CF {series.name}: {point.yCategory}
    ' + }, + borderRadius: 3, + pointRange: 0 + }, { + type: 'xrange', + parallelArrays: ['x', 'x2', 'y'], + requireSorting: false, + animate: seriesTypes.line.prototype.animate, + cropShoulder: 1, + getExtremesFromAll: true, + autoIncrement: H.noop, + buildKDTree: H.noop, + /* eslint-disable valid-jsdoc */ + /** + * @private + * @function Highcarts.seriesTypes.xrange#init + * @return {void} + */ + init: function () { + seriesTypes.column.prototype.init.apply(this, arguments); + this.options.stacking = void 0; // #13161 + }, + /** + * Borrow the column series metrics, but with swapped axes. This gives + * free access to features like groupPadding, grouping, pointWidth etc. + * + * @private + * @function Highcharts.Series#getColumnMetrics + * + * @return {Highcharts.ColumnMetricsObject} + */ + getColumnMetrics: function () { + var metrics, chart = this.chart; + /** + * @private + */ + function swapAxes() { + chart.series.forEach(function (s) { + var xAxis = s.xAxis; + s.xAxis = s.yAxis; + s.yAxis = xAxis; + }); + } + swapAxes(); + metrics = columnType.prototype.getColumnMetrics.call(this); + swapAxes(); + return metrics; + }, + /** + * Override cropData to show a point where x or x2 is outside visible + * range, but one of them is inside. + * + * @private + * @function Highcharts.Series#cropData + * + * @param {Array} xData + * + * @param {Array} yData + * + * @param {number} min + * + * @param {number} max + * + * @param {number} [cropShoulder] + * + * @return {*} + */ + cropData: function (xData, yData, min, max) { + // Replace xData with x2Data to find the appropriate cropStart + var cropData = Series.prototype.cropData, crop = cropData.call(this, this.x2Data, yData, min, max); + // Re-insert the cropped xData + crop.xData = xData.slice(crop.start, crop.end); + return crop; + }, + /** + * Finds the index of an existing point that matches the given point + * options. + * + * @private + * @function Highcharts.Series#findPointIndex + * @param {object} options The options of the point. + * @returns {number|undefined} Returns index of a matching point, + * returns undefined if no match is found. + */ + findPointIndex: function (options) { + var _a = this, cropped = _a.cropped, cropStart = _a.cropStart, points = _a.points; + var id = options.id; + var pointIndex; + if (id) { + var point = find(points, function (point) { + return point.id === id; + }); + pointIndex = point ? point.index : void 0; + } + if (typeof pointIndex === 'undefined') { + var point = find(points, function (point) { + return (point.x === options.x && + point.x2 === options.x2 && + !point.touched); + }); + pointIndex = point ? point.index : void 0; + } + // Reduce pointIndex if data is cropped + if (cropped && + isNumber(pointIndex) && + isNumber(cropStart) && + pointIndex >= cropStart) { + pointIndex -= cropStart; + } + return pointIndex; + }, + /** + * @private + * @function Highcharts.Series#translatePoint + * + * @param {Highcharts.Point} point + */ + translatePoint: function (point) { + var series = this, xAxis = series.xAxis, yAxis = series.yAxis, metrics = series.columnMetrics, options = series.options, minPointLength = options.minPointLength || 0, plotX = point.plotX, posX = pick(point.x2, point.x + (point.len || 0)), plotX2 = xAxis.translate(posX, 0, 0, 0, 1), length = Math.abs(plotX2 - plotX), widthDifference, shapeArgs, partialFill, inverted = this.chart.inverted, borderWidth = pick(options.borderWidth, 1), crisper = borderWidth % 2 / 2, yOffset = metrics.offset, pointHeight = Math.round(metrics.width), dlLeft, dlRight, dlWidth, clipRectWidth, tooltipYOffset; + if (minPointLength) { + widthDifference = minPointLength - length; + if (widthDifference < 0) { + widthDifference = 0; + } + plotX -= widthDifference / 2; + plotX2 += widthDifference / 2; + } + plotX = Math.max(plotX, -10); + plotX2 = clamp(plotX2, -10, xAxis.len + 10); + // Handle individual pointWidth + if (defined(point.options.pointWidth)) { + yOffset -= ((Math.ceil(point.options.pointWidth) - pointHeight) / 2); + pointHeight = Math.ceil(point.options.pointWidth); + } + // Apply pointPlacement to the Y axis + if (options.pointPlacement && + isNumber(point.plotY) && + yAxis.categories) { + point.plotY = yAxis.translate(point.y, 0, 1, 0, 1, options.pointPlacement); + } + point.shapeArgs = { + x: Math.floor(Math.min(plotX, plotX2)) + crisper, + y: Math.floor(point.plotY + yOffset) + crisper, + width: Math.round(Math.abs(plotX2 - plotX)), + height: pointHeight, + r: series.options.borderRadius + }; + // Align data labels inside the shape and inside the plot area + dlLeft = point.shapeArgs.x; + dlRight = dlLeft + point.shapeArgs.width; + if (dlLeft < 0 || dlRight > xAxis.len) { + dlLeft = clamp(dlLeft, 0, xAxis.len); + dlRight = clamp(dlRight, 0, xAxis.len); + dlWidth = dlRight - dlLeft; + point.dlBox = merge(point.shapeArgs, { + x: dlLeft, + width: dlRight - dlLeft, + centerX: dlWidth ? dlWidth / 2 : null + }); + } + else { + point.dlBox = null; + } + // Tooltip position + var tooltipPos = point.tooltipPos; + var xIndex = !inverted ? 0 : 1; + var yIndex = !inverted ? 1 : 0; + tooltipYOffset = series.columnMetrics ? + series.columnMetrics.offset : -metrics.width / 2; + // Limit position by the correct axis size (#9727) + tooltipPos[xIndex] = clamp(tooltipPos[xIndex] + ((!inverted ? 1 : -1) * (xAxis.reversed ? -1 : 1) * + (length / 2)), 0, xAxis.len - 1); + tooltipPos[yIndex] = clamp(tooltipPos[yIndex] + ((inverted ? -1 : 1) * tooltipYOffset), 0, yAxis.len - 1); + // Add a partShapeArgs to the point, based on the shapeArgs property + partialFill = point.partialFill; + if (partialFill) { + // Get the partial fill amount + if (isObject(partialFill)) { + partialFill = partialFill.amount; + } + // If it was not a number, assume 0 + if (!isNumber(partialFill)) { + partialFill = 0; + } + shapeArgs = point.shapeArgs; + point.partShapeArgs = { + x: shapeArgs.x, + y: shapeArgs.y, + width: shapeArgs.width, + height: shapeArgs.height, + r: series.options.borderRadius + }; + clipRectWidth = Math.max(Math.round(length * partialFill + point.plotX - + plotX), 0); + point.clipRectArgs = { + x: xAxis.reversed ? // #10717 + shapeArgs.x + length - clipRectWidth : + shapeArgs.x, + y: shapeArgs.y, + width: clipRectWidth, + height: shapeArgs.height + }; + } + }, + /** + * @private + * @function Highcharts.Series#translate + */ + translate: function () { + columnType.prototype.translate.apply(this, arguments); + this.points.forEach(function (point) { + this.translatePoint(point); + }, this); + }, + /** + * Draws a single point in the series. Needed for partial fill. + * + * This override turns point.graphic into a group containing the + * original graphic and an overlay displaying the partial fill. + * + * @private + * @function Highcharts.Series#drawPoint + * + * @param {Highcharts.Point} point + * An instance of Point in the series. + * + * @param {"animate"|"attr"} verb + * 'animate' (animates changes) or 'attr' (sets options) + */ + drawPoint: function (point, verb) { + var series = this, seriesOpts = series.options, renderer = series.chart.renderer, graphic = point.graphic, type = point.shapeType, shapeArgs = point.shapeArgs, partShapeArgs = point.partShapeArgs, clipRectArgs = point.clipRectArgs, pfOptions = point.partialFill, cutOff = seriesOpts.stacking && !seriesOpts.borderRadius, pointState = point.state, stateOpts = (seriesOpts.states[pointState || 'normal'] || + {}), pointStateVerb = typeof pointState === 'undefined' ? + 'attr' : verb, pointAttr = series.pointAttribs(point, pointState), animation = pick(series.chart.options.chart.animation, stateOpts.animation), fill; + if (!point.isNull && point.visible !== false) { + // Original graphic + if (graphic) { // update + graphic.rect[verb](shapeArgs); + } + else { + point.graphic = graphic = renderer.g('point') + .addClass(point.getClassName()) + .add(point.group || series.group); + graphic.rect = renderer[type](merge(shapeArgs)) + .addClass(point.getClassName()) + .addClass('highcharts-partfill-original') + .add(graphic); + } + // Partial fill graphic + if (partShapeArgs) { + if (graphic.partRect) { + graphic.partRect[verb](merge(partShapeArgs)); + graphic.partialClipRect[verb](merge(clipRectArgs)); + } + else { + graphic.partialClipRect = renderer.clipRect(clipRectArgs.x, clipRectArgs.y, clipRectArgs.width, clipRectArgs.height); + graphic.partRect = + renderer[type](partShapeArgs) + .addClass('highcharts-partfill-overlay') + .add(graphic) + .clip(graphic.partialClipRect); + } + } + // Presentational + if (!series.chart.styledMode) { + graphic + .rect[verb](pointAttr, animation) + .shadow(seriesOpts.shadow, null, cutOff); + if (partShapeArgs) { + // Ensure pfOptions is an object + if (!isObject(pfOptions)) { + pfOptions = {}; + } + if (isObject(seriesOpts.partialFill)) { + pfOptions = merge(pfOptions, seriesOpts.partialFill); + } + fill = (pfOptions.fill || + color(pointAttr.fill).brighten(-0.3).get() || + color(point.color || series.color) + .brighten(-0.3).get()); + pointAttr.fill = fill; + graphic + .partRect[pointStateVerb](pointAttr, animation) + .shadow(seriesOpts.shadow, null, cutOff); + } + } + } + else if (graphic) { + point.graphic = graphic.destroy(); // #1269 + } + }, + /** + * @private + * @function Highcharts.Series#drawPoints + */ + drawPoints: function () { + var series = this, verb = series.getAnimationVerb(); + // Draw the columns + series.points.forEach(function (point) { + series.drawPoint(point, verb); + }); + }, + /** + * Returns "animate", or "attr" if the number of points is above the + * animation limit. + * + * @private + * @function Highcharts.Series#getAnimationVerb + * + * @return {string} + */ + getAnimationVerb: function () { + return (this.chart.pointCount < (this.options.animationLimit || 250) ? + 'animate' : + 'attr'); + } + /* + // Override to remove stroke from points. For partial fill. + pointAttribs: function () { + var series = this, + retVal = columnType.prototype.pointAttribs + .apply(series, arguments); + + //retVal['stroke-width'] = 0; + return retVal; + } + //*/ + /* eslint-enable valid-jsdoc */ + }, { + /** + * The ending X value of the range point. + * @name Highcharts.Point#x2 + * @type {number|undefined} + * @requires modules/xrange + */ + /** + * Extend applyOptions so that `colorByPoint` for x-range means that one + * color is applied per Y axis category. + * + * @private + * @function Highcharts.Point#applyOptions + * + * @return {Highcharts.Series} + */ + /* eslint-disable valid-jsdoc */ + /** + * @private + */ + resolveColor: function () { + var series = this.series, colorByPoint; + if (series.options.colorByPoint && !this.options.color) { + colorByPoint = getColorByCategory(series, this); + if (!series.chart.styledMode) { + this.color = colorByPoint.color; + } + if (!this.options.colorIndex) { + this.colorIndex = colorByPoint.colorIndex; + } + } + else if (!this.color) { + this.color = series.color; + } + }, + /** + * Extend init to have y default to 0. + * + * @private + * @function Highcharts.Point#init + * + * @return {Highcharts.Point} + */ + init: function () { + Point.prototype.init.apply(this, arguments); + if (!this.y) { + this.y = 0; + } + return this; + }, + /** + * @private + * @function Highcharts.Point#setState + */ + setState: function () { + Point.prototype.setState.apply(this, arguments); + this.series.drawPoint(this, this.series.getAnimationVerb()); + }, + /** + * @private + * @function Highcharts.Point#getLabelConfig + * + * @return {Highcharts.PointLabelObject} + */ + // Add x2 and yCategory to the available properties for tooltip formats + getLabelConfig: function () { + var point = this, cfg = Point.prototype.getLabelConfig.call(point), yCats = point.series.yAxis.categories; + cfg.x2 = point.x2; + cfg.yCategory = point.yCategory = yCats && yCats[point.y]; + return cfg; + }, + tooltipDateKeys: ['x', 'x2'], + /** + * @private + * @function Highcharts.Point#isValid + * + * @return {boolean} + */ + isValid: function () { + return typeof this.x === 'number' && + typeof this.x2 === 'number'; + } + /* eslint-enable valid-jsdoc */ + }); + /** + * Max x2 should be considered in xAxis extremes + */ + addEvent(Axis, 'afterGetSeriesExtremes', function () { + var axis = this, // eslint-disable-line no-invalid-this + axisSeries = axis.series, dataMax, modMax; + if (axis.isXAxis) { + dataMax = pick(axis.dataMax, -Number.MAX_VALUE); + axisSeries.forEach(function (series) { + if (series.x2Data) { + series.x2Data + .forEach(function (val) { + if (val > dataMax) { + dataMax = val; + modMax = true; + } + }); + } + }); + if (modMax) { + axis.dataMax = dataMax; + } + } + }); + /** + * An `xrange` series. If the [type](#series.xrange.type) option is not + * specified, it is inherited from [chart.type](#chart.type). + * + * @extends series,plotOptions.xrange + * @excluding boostThreshold, crisp, cropThreshold, depth, edgeColor, edgeWidth, + * findNearestPointBy, getExtremesFromAll, negativeColor, + * pointInterval, pointIntervalUnit, pointPlacement, pointRange, + * pointStart, softThreshold, stacking, threshold, dataSorting + * @product highcharts highstock gantt + * @requires modules/xrange + * @apioption series.xrange + */ + /** + * An array of data points for the series. For the `xrange` series type, + * points can be given in the following ways: + * + * 1. An array of objects with named values. The objects are point configuration + * objects as seen below. + * ```js + * data: [{ + * x: Date.UTC(2017, 0, 1), + * x2: Date.UTC(2017, 0, 3), + * name: "Test", + * y: 0, + * color: "#00FF00" + * }, { + * x: Date.UTC(2017, 0, 4), + * x2: Date.UTC(2017, 0, 5), + * name: "Deploy", + * y: 1, + * color: "#FF0000" + * }] + * ``` + * + * @sample {highcharts} highcharts/series/data-array-of-objects/ + * Config objects + * + * @declare Highcharts.XrangePointOptionsObject + * @type {Array<*>} + * @extends series.line.data + * @product highcharts highstock gantt + * @apioption series.xrange.data + */ + /** + * The starting X value of the range point. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range + * + * @type {number} + * @product highcharts highstock gantt + * @apioption series.xrange.data.x + */ + /** + * The ending X value of the range point. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range + * + * @type {number} + * @product highcharts highstock gantt + * @apioption series.xrange.data.x2 + */ + /** + * The Y value of the range point. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range + * + * @type {number} + * @product highcharts highstock gantt + * @apioption series.xrange.data.y + */ + /** + * A partial fill for each point, typically used to visualize how much of + * a task is performed. The partial fill object can be set either on series + * or point level. + * + * @sample {highcharts} highcharts/demo/x-range + * X-range with partial fill + * + * @declare Highcharts.XrangePointPartialFillOptionsObject + * @product highcharts highstock gantt + * @apioption series.xrange.data.partialFill + */ + /** + * The amount of the X-range point to be filled. Values can be 0-1 and are + * converted to percentages in the default data label formatter. + * + * @type {number} + * @product highcharts highstock gantt + * @apioption series.xrange.data.partialFill.amount + */ + /** + * The fill color to be used for partial fills. Defaults to a darker shade + * of the point color. + * + * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} + * @product highcharts highstock gantt + * @apioption series.xrange.data.partialFill.fill + */ + ''; // adds doclets above to transpiled file + + }); + _registerModule(_modules, 'masters/modules/xrange.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/themes/avocado.js b/librerias/gantt/code/themes/avocado.js new file mode 100644 index 0000000..fe2872c --- /dev/null +++ b/librerias/gantt/code/themes/avocado.js @@ -0,0 +1,10 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2009-2019 Highsoft AS + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/themes/avocado",["highcharts"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,b,c,d){a.hasOwnProperty(b)||(a[b]=d.apply(null,c))}a=a?a._modules:{};b(a,"themes/avocado.js",[a["parts/Globals.js"]],function(a){a.theme={colors:["#F3E796","#95C471","#35729E","#251735"],colorAxis:{maxColor:"#05426E", +minColor:"#F3E796"},plotOptions:{map:{nullColor:"#FCFEFE"}},navigator:{maskFill:"rgba(170, 205, 170, 0.5)",series:{color:"#95C471",lineColor:"#35729E"}}};a.setOptions(a.theme)});b(a,"masters/themes/avocado.src.js",[],function(){})}); +//# sourceMappingURL=avocado.js.map \ No newline at end of file diff --git a/librerias/gantt/code/themes/avocado.js.map b/librerias/gantt/code/themes/avocado.js.map new file mode 100644 index 0000000..4c99701 --- /dev/null +++ b/librerias/gantt/code/themes/avocado.js.map @@ -0,0 +1 @@ +{"version":3,"file":"avocado.js.map","lineCount":9,"mappings":"A;;;;;;;AAQC,SAAS,CAACA,CAAD,CAAU,CACM,QAAtB,GAAI,MAAOC,OAAX,EAAkCA,MAAAC,QAAlC,EACIF,CAAA,CAAQ,SAAR,CACA,CADqBA,CACrB,CAAAC,MAAAC,QAAA,CAAiBF,CAFrB,EAG6B,UAAtB,GAAI,MAAOG,OAAX,EAAoCA,MAAAC,IAApC,CACHD,MAAA,CAAO,2BAAP,CAAoC,CAAC,YAAD,CAApC,CAAoD,QAAS,CAACE,CAAD,CAAa,CACtEL,CAAA,CAAQK,CAAR,CACAL,EAAAK,WAAA,CAAqBA,CACrB,OAAOL,EAH+D,CAA1E,CADG,CAOHA,CAAA,CAA8B,WAAtB,GAAA,MAAOK,WAAP,CAAoCA,UAApC,CAAiDC,IAAAA,EAAzD,CAXY,CAAnB,CAAA,CAaC,QAAS,CAACD,CAAD,CAAa,CAEpBE,QAASA,EAAe,CAACC,CAAD,CAAMC,CAAN,CAAYC,CAAZ,CAAkBC,CAAlB,CAAsB,CACrCH,CAAAI,eAAA,CAAmBH,CAAnB,CAAL,GACID,CAAA,CAAIC,CAAJ,CADJ,CACgBE,CAAAE,MAAA,CAAS,IAAT,CAAeH,CAAf,CADhB,CAD0C,CAD1CI,CAAAA,CAAWT,CAAA,CAAaA,CAAAS,SAAb,CAAmC,EAMlDP,EAAA,CAAgBO,CAAhB,CAA0B,mBAA1B,CAA+C,CAACA,CAAA,CAAS,kBAAT,CAAD,CAA/C,CAA+E,QAAS,CAACT,CAAD,CAAa,CAejGA,CAAAU,MAAA,CAAmB,CACfC,OAAQ,CAAC,SAAD,CAAY,SAAZ,CAAuB,SAAvB,CAAkC,SAAlC,CADO,CAEfC,UAAW,CACPC,SAAU,SADH;AAEPC,SAAU,SAFH,CAFI,CAMfC,YAAa,CACTC,IAAK,CACDC,UAAW,SADV,CADI,CANE,CAWfC,UAAW,CACPC,SAAU,0BADH,CAEPC,OAAQ,CACJC,MAAO,SADH,CAEJC,UAAW,SAFP,CAFD,CAXI,CAoBnBtB,EAAAuB,WAAA,CAAsBvB,CAAAU,MAAtB,CAnCiG,CAArG,CAsCAR,EAAA,CAAgBO,CAAhB,CAA0B,+BAA1B,CAA2D,EAA3D,CAA+D,QAAS,EAAG,EAA3E,CA7CoB,CAbvB;","sources":["avocado.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","theme","colors","colorAxis","maxColor","minColor","plotOptions","map","nullColor","navigator","maskFill","series","color","lineColor","setOptions"]} \ No newline at end of file diff --git a/librerias/gantt/code/themes/avocado.src.js b/librerias/gantt/code/themes/avocado.src.js new file mode 100644 index 0000000..ad8da31 --- /dev/null +++ b/librerias/gantt/code/themes/avocado.src.js @@ -0,0 +1,71 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * (c) 2009-2019 Highsoft AS + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/themes/avocado', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'themes/avocado.js', [_modules['parts/Globals.js']], function (Highcharts) { + /* * + * + * (c) 2010-2020 Highsoft AS + * + * Author: Øystein Moseng + * + * License: www.highcharts.com/license + * + * Accessible high-contrast theme for Highcharts. Considers colorblindness and + * monochrome rendering. + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + Highcharts.theme = { + colors: ['#F3E796', '#95C471', '#35729E', '#251735'], + colorAxis: { + maxColor: '#05426E', + minColor: '#F3E796' + }, + plotOptions: { + map: { + nullColor: '#FCFEFE' + } + }, + navigator: { + maskFill: 'rgba(170, 205, 170, 0.5)', + series: { + color: '#95C471', + lineColor: '#35729E' + } + } + }; + // Apply the theme + Highcharts.setOptions(Highcharts.theme); + + }); + _registerModule(_modules, 'masters/themes/avocado.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/themes/dark-blue.js b/librerias/gantt/code/themes/dark-blue.js new file mode 100644 index 0000000..bec1431 --- /dev/null +++ b/librerias/gantt/code/themes/dark-blue.js @@ -0,0 +1,15 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2009-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/themes/dark-blue",["highcharts"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,b,c,d){a.hasOwnProperty(b)||(a[b]=d.apply(null,c))}a=a?a._modules:{};b(a,"themes/dark-blue.js",[a["parts/Globals.js"]],function(a){a.theme={colors:"#DDDF0D #55BF3B #DF5353 #7798BF #aaeeee #ff0066 #eeaaee #55BF3B #DF5353 #7798BF #aaeeee".split(" "), +chart:{backgroundColor:{linearGradient:{x1:0,y1:0,x2:1,y2:1},stops:[[0,"rgb(48, 48, 96)"],[1,"rgb(0, 0, 0)"]]},borderColor:"#000000",borderWidth:2,className:"dark-container",plotBackgroundColor:"rgba(255, 255, 255, .1)",plotBorderColor:"#CCCCCC",plotBorderWidth:1},title:{style:{color:"#C0C0C0",font:'bold 16px "Trebuchet MS", Verdana, sans-serif'}},subtitle:{style:{color:"#666666",font:'bold 12px "Trebuchet MS", Verdana, sans-serif'}},xAxis:{gridLineColor:"#333333",gridLineWidth:1,labels:{style:{color:"#A0A0A0"}}, +lineColor:"#A0A0A0",tickColor:"#A0A0A0",title:{style:{color:"#CCC",fontWeight:"bold",fontSize:"12px",fontFamily:"Trebuchet MS, Verdana, sans-serif"}}},yAxis:{gridLineColor:"#333333",labels:{style:{color:"#A0A0A0"}},lineColor:"#A0A0A0",minorTickInterval:null,tickColor:"#A0A0A0",tickWidth:1,title:{style:{color:"#CCC",fontWeight:"bold",fontSize:"12px",fontFamily:"Trebuchet MS, Verdana, sans-serif"}}},tooltip:{backgroundColor:"rgba(0, 0, 0, 0.75)",style:{color:"#F0F0F0"}},toolbar:{itemStyle:{color:"silver"}}, +plotOptions:{line:{dataLabels:{color:"#CCC"},marker:{lineColor:"#333"}},spline:{marker:{lineColor:"#333"}},scatter:{marker:{lineColor:"#333"}},candlestick:{lineColor:"white"}},legend:{backgroundColor:"rgba(0, 0, 0, 0.5)",itemStyle:{font:"9pt Trebuchet MS, Verdana, sans-serif",color:"#A0A0A0"},itemHoverStyle:{color:"#FFF"},itemHiddenStyle:{color:"#444"},title:{style:{color:"#C0C0C0"}}},credits:{style:{color:"#666"}},labels:{style:{color:"#CCC"}},navigation:{buttonOptions:{symbolStroke:"#DDDDDD",theme:{fill:{linearGradient:{x1:0, +y1:0,x2:0,y2:1},stops:[[.4,"#606060"],[.6,"#333333"]]},stroke:"#000000"}}},rangeSelector:{buttonTheme:{fill:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[.4,"#888"],[.6,"#555"]]},stroke:"#000000",style:{color:"#CCC",fontWeight:"bold"},states:{hover:{fill:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[.4,"#BBB"],[.6,"#888"]]},stroke:"#000000",style:{color:"white"}},select:{fill:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[.1,"#000"],[.3,"#333"]]},stroke:"#000000",style:{color:"yellow"}}}},inputStyle:{backgroundColor:"#333", +color:"silver"},labelStyle:{color:"silver"}},navigator:{handles:{backgroundColor:"#666",borderColor:"#AAA"},outlineColor:"#CCC",maskFill:"rgba(16, 16, 16, 0.5)",series:{color:"#7798BF",lineColor:"#A6C7ED"}},scrollbar:{barBackgroundColor:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[.4,"#888"],[.6,"#555"]]},barBorderColor:"#CCC",buttonArrowColor:"#CCC",buttonBackgroundColor:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[.4,"#888"],[.6,"#555"]]},buttonBorderColor:"#CCC",rifleColor:"#FFF",trackBackgroundColor:{linearGradient:{x1:0, +y1:0,x2:0,y2:1},stops:[[0,"#000"],[1,"#333"]]},trackBorderColor:"#666"}};a.setOptions(a.theme)});b(a,"masters/themes/dark-blue.src.js",[],function(){})}); +//# sourceMappingURL=dark-blue.js.map \ No newline at end of file diff --git a/librerias/gantt/code/themes/dark-blue.js.map b/librerias/gantt/code/themes/dark-blue.js.map new file mode 100644 index 0000000..b40cfda --- /dev/null +++ b/librerias/gantt/code/themes/dark-blue.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dark-blue.js.map","lineCount":14,"mappings":"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","sources":["dark-blue.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","theme","colors","chart","backgroundColor","linearGradient","x1","y1","x2","y2","stops","borderColor","borderWidth","className","plotBackgroundColor","plotBorderColor","plotBorderWidth","title","style","color","font","subtitle","xAxis","gridLineColor","gridLineWidth","labels","lineColor","tickColor","fontWeight","fontSize","fontFamily","yAxis","minorTickInterval","tickWidth","tooltip","toolbar","itemStyle","plotOptions","line","dataLabels","marker","spline","scatter","candlestick","legend","itemHoverStyle","itemHiddenStyle","credits","navigation","buttonOptions","symbolStroke","fill","stroke","rangeSelector","buttonTheme","states","hover","select","inputStyle","labelStyle","navigator","handles","outlineColor","maskFill","series","scrollbar","barBackgroundColor","barBorderColor","buttonArrowColor","buttonBackgroundColor","buttonBorderColor","rifleColor","trackBackgroundColor","trackBorderColor","setOptions"]} \ No newline at end of file diff --git a/librerias/gantt/code/themes/dark-blue.src.js b/librerias/gantt/code/themes/dark-blue.src.js new file mode 100644 index 0000000..32ca2ad --- /dev/null +++ b/librerias/gantt/code/themes/dark-blue.src.js @@ -0,0 +1,288 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * (c) 2009-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/themes/dark-blue', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'themes/dark-blue.js', [_modules['parts/Globals.js']], function (Highcharts) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * Dark blue theme for Highcharts JS + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + Highcharts.theme = { + colors: ['#DDDF0D', '#55BF3B', '#DF5353', '#7798BF', '#aaeeee', + '#ff0066', '#eeaaee', '#55BF3B', '#DF5353', '#7798BF', '#aaeeee'], + chart: { + backgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 }, + stops: [ + [0, 'rgb(48, 48, 96)'], + [1, 'rgb(0, 0, 0)'] + ] + }, + borderColor: '#000000', + borderWidth: 2, + className: 'dark-container', + plotBackgroundColor: 'rgba(255, 255, 255, .1)', + plotBorderColor: '#CCCCCC', + plotBorderWidth: 1 + }, + title: { + style: { + color: '#C0C0C0', + font: 'bold 16px "Trebuchet MS", Verdana, sans-serif' + } + }, + subtitle: { + style: { + color: '#666666', + font: 'bold 12px "Trebuchet MS", Verdana, sans-serif' + } + }, + xAxis: { + gridLineColor: '#333333', + gridLineWidth: 1, + labels: { + style: { + color: '#A0A0A0' + } + }, + lineColor: '#A0A0A0', + tickColor: '#A0A0A0', + title: { + style: { + color: '#CCC', + fontWeight: 'bold', + fontSize: '12px', + fontFamily: 'Trebuchet MS, Verdana, sans-serif' + } + } + }, + yAxis: { + gridLineColor: '#333333', + labels: { + style: { + color: '#A0A0A0' + } + }, + lineColor: '#A0A0A0', + minorTickInterval: null, + tickColor: '#A0A0A0', + tickWidth: 1, + title: { + style: { + color: '#CCC', + fontWeight: 'bold', + fontSize: '12px', + fontFamily: 'Trebuchet MS, Verdana, sans-serif' + } + } + }, + tooltip: { + backgroundColor: 'rgba(0, 0, 0, 0.75)', + style: { + color: '#F0F0F0' + } + }, + toolbar: { + itemStyle: { + color: 'silver' + } + }, + plotOptions: { + line: { + dataLabels: { + color: '#CCC' + }, + marker: { + lineColor: '#333' + } + }, + spline: { + marker: { + lineColor: '#333' + } + }, + scatter: { + marker: { + lineColor: '#333' + } + }, + candlestick: { + lineColor: 'white' + } + }, + legend: { + backgroundColor: 'rgba(0, 0, 0, 0.5)', + itemStyle: { + font: '9pt Trebuchet MS, Verdana, sans-serif', + color: '#A0A0A0' + }, + itemHoverStyle: { + color: '#FFF' + }, + itemHiddenStyle: { + color: '#444' + }, + title: { + style: { + color: '#C0C0C0' + } + } + }, + credits: { + style: { + color: '#666' + } + }, + labels: { + style: { + color: '#CCC' + } + }, + navigation: { + buttonOptions: { + symbolStroke: '#DDDDDD', + theme: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#606060'], + [0.6, '#333333'] + ] + }, + stroke: '#000000' + } + } + }, + // scroll charts + rangeSelector: { + buttonTheme: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + stroke: '#000000', + style: { + color: '#CCC', + fontWeight: 'bold' + }, + states: { + hover: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#BBB'], + [0.6, '#888'] + ] + }, + stroke: '#000000', + style: { + color: 'white' + } + }, + select: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.1, '#000'], + [0.3, '#333'] + ] + }, + stroke: '#000000', + style: { + color: 'yellow' + } + } + } + }, + inputStyle: { + backgroundColor: '#333', + color: 'silver' + }, + labelStyle: { + color: 'silver' + } + }, + navigator: { + handles: { + backgroundColor: '#666', + borderColor: '#AAA' + }, + outlineColor: '#CCC', + maskFill: 'rgba(16, 16, 16, 0.5)', + series: { + color: '#7798BF', + lineColor: '#A6C7ED' + } + }, + scrollbar: { + barBackgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + barBorderColor: '#CCC', + buttonArrowColor: '#CCC', + buttonBackgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + buttonBorderColor: '#CCC', + rifleColor: '#FFF', + trackBackgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0, '#000'], + [1, '#333'] + ] + }, + trackBorderColor: '#666' + } + }; + // Apply the theme + Highcharts.setOptions(Highcharts.theme); + + }); + _registerModule(_modules, 'masters/themes/dark-blue.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/themes/dark-green.js b/librerias/gantt/code/themes/dark-green.js new file mode 100644 index 0000000..3fc1ef7 --- /dev/null +++ b/librerias/gantt/code/themes/dark-green.js @@ -0,0 +1,15 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2009-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/themes/dark-green",["highcharts"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,b,c,d){a.hasOwnProperty(b)||(a[b]=d.apply(null,c))}a=a?a._modules:{};b(a,"themes/dark-green.js",[a["parts/Globals.js"]],function(a){a.theme={colors:"#DDDF0D #55BF3B #DF5353 #7798BF #aaeeee #ff0066 #eeaaee #55BF3B #DF5353 #7798BF #aaeeee".split(" "), +chart:{backgroundColor:{linearGradient:{x1:0,y1:0,x2:1,y2:1},stops:[[0,"rgb(48, 96, 48)"],[1,"rgb(0, 0, 0)"]]},borderColor:"#000000",borderWidth:2,className:"dark-container",plotBackgroundColor:"rgba(255, 255, 255, .1)",plotBorderColor:"#CCCCCC",plotBorderWidth:1},title:{style:{color:"#C0C0C0",font:'bold 16px "Trebuchet MS", Verdana, sans-serif'}},subtitle:{style:{color:"#666666",font:'bold 12px "Trebuchet MS", Verdana, sans-serif'}},xAxis:{gridLineColor:"#333333",gridLineWidth:1,labels:{style:{color:"#A0A0A0"}}, +lineColor:"#A0A0A0",tickColor:"#A0A0A0",title:{style:{color:"#CCC",fontWeight:"bold",fontSize:"12px",fontFamily:"Trebuchet MS, Verdana, sans-serif"}}},yAxis:{gridLineColor:"#333333",labels:{style:{color:"#A0A0A0"}},lineColor:"#A0A0A0",minorTickInterval:null,tickColor:"#A0A0A0",tickWidth:1,title:{style:{color:"#CCC",fontWeight:"bold",fontSize:"12px",fontFamily:"Trebuchet MS, Verdana, sans-serif"}}},tooltip:{backgroundColor:"rgba(0, 0, 0, 0.75)",style:{color:"#F0F0F0"}},toolbar:{itemStyle:{color:"silver"}}, +plotOptions:{line:{dataLabels:{color:"#CCC"},marker:{lineColor:"#333"}},spline:{marker:{lineColor:"#333"}},scatter:{marker:{lineColor:"#333"}},candlestick:{lineColor:"white"}},legend:{backgroundColor:"rgba(0, 0, 0, 0.5)",itemStyle:{font:"9pt Trebuchet MS, Verdana, sans-serif",color:"#A0A0A0"},itemHoverStyle:{color:"#FFF"},itemHiddenStyle:{color:"#444"},title:{style:{color:"#C0C0C0"}}},credits:{style:{color:"#666"}},labels:{style:{color:"#CCC"}},navigation:{buttonOptions:{symbolStroke:"#DDDDDD",theme:{fill:{linearGradient:{x1:0, +y1:0,x2:0,y2:1},stops:[[.4,"#606060"],[.6,"#333333"]]},stroke:"#000000"}}},rangeSelector:{buttonTheme:{fill:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[.4,"#888"],[.6,"#555"]]},stroke:"#000000",style:{color:"#CCC",fontWeight:"bold"},states:{hover:{fill:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[.4,"#BBB"],[.6,"#888"]]},stroke:"#000000",style:{color:"white"}},select:{fill:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[.1,"#000"],[.3,"#333"]]},stroke:"#000000",style:{color:"yellow"}}}},inputStyle:{backgroundColor:"#333", +color:"silver"},labelStyle:{color:"silver"}},navigator:{handles:{backgroundColor:"#666",borderColor:"#AAA"},outlineColor:"#CCC",maskFill:"rgba(16, 16, 16, 0.5)",series:{color:"#7798BF",lineColor:"#A6C7ED"}},scrollbar:{barBackgroundColor:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[.4,"#888"],[.6,"#555"]]},barBorderColor:"#CCC",buttonArrowColor:"#CCC",buttonBackgroundColor:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[.4,"#888"],[.6,"#555"]]},buttonBorderColor:"#CCC",rifleColor:"#FFF",trackBackgroundColor:{linearGradient:{x1:0, +y1:0,x2:0,y2:1},stops:[[0,"#000"],[1,"#333"]]},trackBorderColor:"#666"}};a.setOptions(a.theme)});b(a,"masters/themes/dark-green.src.js",[],function(){})}); +//# sourceMappingURL=dark-green.js.map \ No newline at end of file diff --git a/librerias/gantt/code/themes/dark-green.js.map b/librerias/gantt/code/themes/dark-green.js.map new file mode 100644 index 0000000..62fc50a --- /dev/null +++ b/librerias/gantt/code/themes/dark-green.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dark-green.js.map","lineCount":14,"mappings":"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","sources":["dark-green.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","theme","colors","chart","backgroundColor","linearGradient","x1","y1","x2","y2","stops","borderColor","borderWidth","className","plotBackgroundColor","plotBorderColor","plotBorderWidth","title","style","color","font","subtitle","xAxis","gridLineColor","gridLineWidth","labels","lineColor","tickColor","fontWeight","fontSize","fontFamily","yAxis","minorTickInterval","tickWidth","tooltip","toolbar","itemStyle","plotOptions","line","dataLabels","marker","spline","scatter","candlestick","legend","itemHoverStyle","itemHiddenStyle","credits","navigation","buttonOptions","symbolStroke","fill","stroke","rangeSelector","buttonTheme","states","hover","select","inputStyle","labelStyle","navigator","handles","outlineColor","maskFill","series","scrollbar","barBackgroundColor","barBorderColor","buttonArrowColor","buttonBackgroundColor","buttonBorderColor","rifleColor","trackBackgroundColor","trackBorderColor","setOptions"]} \ No newline at end of file diff --git a/librerias/gantt/code/themes/dark-green.src.js b/librerias/gantt/code/themes/dark-green.src.js new file mode 100644 index 0000000..d68e65d --- /dev/null +++ b/librerias/gantt/code/themes/dark-green.src.js @@ -0,0 +1,288 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * (c) 2009-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/themes/dark-green', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'themes/dark-green.js', [_modules['parts/Globals.js']], function (Highcharts) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * Dark blue theme for Highcharts JS + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + Highcharts.theme = { + colors: ['#DDDF0D', '#55BF3B', '#DF5353', '#7798BF', '#aaeeee', + '#ff0066', '#eeaaee', '#55BF3B', '#DF5353', '#7798BF', '#aaeeee'], + chart: { + backgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 }, + stops: [ + [0, 'rgb(48, 96, 48)'], + [1, 'rgb(0, 0, 0)'] + ] + }, + borderColor: '#000000', + borderWidth: 2, + className: 'dark-container', + plotBackgroundColor: 'rgba(255, 255, 255, .1)', + plotBorderColor: '#CCCCCC', + plotBorderWidth: 1 + }, + title: { + style: { + color: '#C0C0C0', + font: 'bold 16px "Trebuchet MS", Verdana, sans-serif' + } + }, + subtitle: { + style: { + color: '#666666', + font: 'bold 12px "Trebuchet MS", Verdana, sans-serif' + } + }, + xAxis: { + gridLineColor: '#333333', + gridLineWidth: 1, + labels: { + style: { + color: '#A0A0A0' + } + }, + lineColor: '#A0A0A0', + tickColor: '#A0A0A0', + title: { + style: { + color: '#CCC', + fontWeight: 'bold', + fontSize: '12px', + fontFamily: 'Trebuchet MS, Verdana, sans-serif' + } + } + }, + yAxis: { + gridLineColor: '#333333', + labels: { + style: { + color: '#A0A0A0' + } + }, + lineColor: '#A0A0A0', + minorTickInterval: null, + tickColor: '#A0A0A0', + tickWidth: 1, + title: { + style: { + color: '#CCC', + fontWeight: 'bold', + fontSize: '12px', + fontFamily: 'Trebuchet MS, Verdana, sans-serif' + } + } + }, + tooltip: { + backgroundColor: 'rgba(0, 0, 0, 0.75)', + style: { + color: '#F0F0F0' + } + }, + toolbar: { + itemStyle: { + color: 'silver' + } + }, + plotOptions: { + line: { + dataLabels: { + color: '#CCC' + }, + marker: { + lineColor: '#333' + } + }, + spline: { + marker: { + lineColor: '#333' + } + }, + scatter: { + marker: { + lineColor: '#333' + } + }, + candlestick: { + lineColor: 'white' + } + }, + legend: { + backgroundColor: 'rgba(0, 0, 0, 0.5)', + itemStyle: { + font: '9pt Trebuchet MS, Verdana, sans-serif', + color: '#A0A0A0' + }, + itemHoverStyle: { + color: '#FFF' + }, + itemHiddenStyle: { + color: '#444' + }, + title: { + style: { + color: '#C0C0C0' + } + } + }, + credits: { + style: { + color: '#666' + } + }, + labels: { + style: { + color: '#CCC' + } + }, + navigation: { + buttonOptions: { + symbolStroke: '#DDDDDD', + theme: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#606060'], + [0.6, '#333333'] + ] + }, + stroke: '#000000' + } + } + }, + // scroll charts + rangeSelector: { + buttonTheme: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + stroke: '#000000', + style: { + color: '#CCC', + fontWeight: 'bold' + }, + states: { + hover: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#BBB'], + [0.6, '#888'] + ] + }, + stroke: '#000000', + style: { + color: 'white' + } + }, + select: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.1, '#000'], + [0.3, '#333'] + ] + }, + stroke: '#000000', + style: { + color: 'yellow' + } + } + } + }, + inputStyle: { + backgroundColor: '#333', + color: 'silver' + }, + labelStyle: { + color: 'silver' + } + }, + navigator: { + handles: { + backgroundColor: '#666', + borderColor: '#AAA' + }, + outlineColor: '#CCC', + maskFill: 'rgba(16, 16, 16, 0.5)', + series: { + color: '#7798BF', + lineColor: '#A6C7ED' + } + }, + scrollbar: { + barBackgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + barBorderColor: '#CCC', + buttonArrowColor: '#CCC', + buttonBackgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + buttonBorderColor: '#CCC', + rifleColor: '#FFF', + trackBackgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0, '#000'], + [1, '#333'] + ] + }, + trackBorderColor: '#666' + } + }; + // Apply the theme + Highcharts.setOptions(Highcharts.theme); + + }); + _registerModule(_modules, 'masters/themes/dark-green.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/themes/dark-unica.js b/librerias/gantt/code/themes/dark-unica.js new file mode 100644 index 0000000..daeac4e --- /dev/null +++ b/librerias/gantt/code/themes/dark-unica.js @@ -0,0 +1,14 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2009-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/themes/dark-unica",["highcharts"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,b,c,d){a.hasOwnProperty(b)||(a[b]=d.apply(null,c))}a=a?a._modules:{};b(a,"themes/dark-unica.js",[a["parts/Globals.js"]],function(a){a.createElement("link",{href:"https://fonts.googleapis.com/css?family=Unica+One", +rel:"stylesheet",type:"text/css"},null,document.getElementsByTagName("head")[0]);a.theme={colors:"#2b908f #90ee7e #f45b5b #7798BF #aaeeee #ff0066 #eeaaee #55BF3B #DF5353 #7798BF #aaeeee".split(" "),chart:{backgroundColor:{linearGradient:{x1:0,y1:0,x2:1,y2:1},stops:[[0,"#2a2a2b"],[1,"#3e3e40"]]},style:{fontFamily:"'Unica One', sans-serif"},plotBorderColor:"#606063"},title:{style:{color:"#E0E0E3",textTransform:"uppercase",fontSize:"20px"}},subtitle:{style:{color:"#E0E0E3",textTransform:"uppercase"}}, +xAxis:{gridLineColor:"#707073",labels:{style:{color:"#E0E0E3"}},lineColor:"#707073",minorGridLineColor:"#505053",tickColor:"#707073",title:{style:{color:"#A0A0A3"}}},yAxis:{gridLineColor:"#707073",labels:{style:{color:"#E0E0E3"}},lineColor:"#707073",minorGridLineColor:"#505053",tickColor:"#707073",tickWidth:1,title:{style:{color:"#A0A0A3"}}},tooltip:{backgroundColor:"rgba(0, 0, 0, 0.85)",style:{color:"#F0F0F0"}},plotOptions:{series:{dataLabels:{color:"#F0F0F3",style:{fontSize:"13px"}},marker:{lineColor:"#333"}}, +boxplot:{fillColor:"#505053"},candlestick:{lineColor:"white"},errorbar:{color:"white"}},legend:{backgroundColor:"rgba(0, 0, 0, 0.5)",itemStyle:{color:"#E0E0E3"},itemHoverStyle:{color:"#FFF"},itemHiddenStyle:{color:"#606063"},title:{style:{color:"#C0C0C0"}}},credits:{style:{color:"#666"}},labels:{style:{color:"#707073"}},drilldown:{activeAxisLabelStyle:{color:"#F0F0F3"},activeDataLabelStyle:{color:"#F0F0F3"}},navigation:{buttonOptions:{symbolStroke:"#DDDDDD",theme:{fill:"#505053"}}},rangeSelector:{buttonTheme:{fill:"#505053", +stroke:"#000000",style:{color:"#CCC"},states:{hover:{fill:"#707073",stroke:"#000000",style:{color:"white"}},select:{fill:"#000003",stroke:"#000000",style:{color:"white"}}}},inputBoxBorderColor:"#505053",inputStyle:{backgroundColor:"#333",color:"silver"},labelStyle:{color:"silver"}},navigator:{handles:{backgroundColor:"#666",borderColor:"#AAA"},outlineColor:"#CCC",maskFill:"rgba(255,255,255,0.1)",series:{color:"#7798BF",lineColor:"#A6C7ED"},xAxis:{gridLineColor:"#505053"}},scrollbar:{barBackgroundColor:"#808083", +barBorderColor:"#808083",buttonArrowColor:"#CCC",buttonBackgroundColor:"#606063",buttonBorderColor:"#606063",rifleColor:"#FFF",trackBackgroundColor:"#404043",trackBorderColor:"#404043"}};a.setOptions(a.theme)});b(a,"masters/themes/dark-unica.src.js",[],function(){})}); +//# sourceMappingURL=dark-unica.js.map \ No newline at end of file diff --git a/librerias/gantt/code/themes/dark-unica.js.map b/librerias/gantt/code/themes/dark-unica.js.map new file mode 100644 index 0000000..ed241ca --- /dev/null +++ b/librerias/gantt/code/themes/dark-unica.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dark-unica.js.map","lineCount":13,"mappings":"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","sources":["dark-unica.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","createElement","href","rel","type","document","getElementsByTagName","theme","colors","chart","backgroundColor","linearGradient","x1","y1","x2","y2","stops","style","fontFamily","plotBorderColor","title","color","textTransform","fontSize","subtitle","xAxis","gridLineColor","labels","lineColor","minorGridLineColor","tickColor","yAxis","tickWidth","tooltip","plotOptions","series","dataLabels","marker","boxplot","fillColor","candlestick","errorbar","legend","itemStyle","itemHoverStyle","itemHiddenStyle","credits","drilldown","activeAxisLabelStyle","activeDataLabelStyle","navigation","buttonOptions","symbolStroke","fill","rangeSelector","buttonTheme","stroke","states","hover","select","inputBoxBorderColor","inputStyle","labelStyle","navigator","handles","borderColor","outlineColor","maskFill","scrollbar","barBackgroundColor","barBorderColor","buttonArrowColor","buttonBackgroundColor","buttonBorderColor","rifleColor","trackBackgroundColor","trackBorderColor","setOptions"]} \ No newline at end of file diff --git a/librerias/gantt/code/themes/dark-unica.src.js b/librerias/gantt/code/themes/dark-unica.src.js new file mode 100644 index 0000000..3910276 --- /dev/null +++ b/librerias/gantt/code/themes/dark-unica.src.js @@ -0,0 +1,249 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * (c) 2009-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/themes/dark-unica', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'themes/dark-unica.js', [_modules['parts/Globals.js']], function (Highcharts) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * Dark theme for Highcharts JS + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /* global document */ + // Load the fonts + Highcharts.createElement('link', { + href: 'https://fonts.googleapis.com/css?family=Unica+One', + rel: 'stylesheet', + type: 'text/css' + }, null, document.getElementsByTagName('head')[0]); + Highcharts.theme = { + colors: ['#2b908f', '#90ee7e', '#f45b5b', '#7798BF', '#aaeeee', '#ff0066', + '#eeaaee', '#55BF3B', '#DF5353', '#7798BF', '#aaeeee'], + chart: { + backgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 }, + stops: [ + [0, '#2a2a2b'], + [1, '#3e3e40'] + ] + }, + style: { + fontFamily: '\'Unica One\', sans-serif' + }, + plotBorderColor: '#606063' + }, + title: { + style: { + color: '#E0E0E3', + textTransform: 'uppercase', + fontSize: '20px' + } + }, + subtitle: { + style: { + color: '#E0E0E3', + textTransform: 'uppercase' + } + }, + xAxis: { + gridLineColor: '#707073', + labels: { + style: { + color: '#E0E0E3' + } + }, + lineColor: '#707073', + minorGridLineColor: '#505053', + tickColor: '#707073', + title: { + style: { + color: '#A0A0A3' + } + } + }, + yAxis: { + gridLineColor: '#707073', + labels: { + style: { + color: '#E0E0E3' + } + }, + lineColor: '#707073', + minorGridLineColor: '#505053', + tickColor: '#707073', + tickWidth: 1, + title: { + style: { + color: '#A0A0A3' + } + } + }, + tooltip: { + backgroundColor: 'rgba(0, 0, 0, 0.85)', + style: { + color: '#F0F0F0' + } + }, + plotOptions: { + series: { + dataLabels: { + color: '#F0F0F3', + style: { + fontSize: '13px' + } + }, + marker: { + lineColor: '#333' + } + }, + boxplot: { + fillColor: '#505053' + }, + candlestick: { + lineColor: 'white' + }, + errorbar: { + color: 'white' + } + }, + legend: { + backgroundColor: 'rgba(0, 0, 0, 0.5)', + itemStyle: { + color: '#E0E0E3' + }, + itemHoverStyle: { + color: '#FFF' + }, + itemHiddenStyle: { + color: '#606063' + }, + title: { + style: { + color: '#C0C0C0' + } + } + }, + credits: { + style: { + color: '#666' + } + }, + labels: { + style: { + color: '#707073' + } + }, + drilldown: { + activeAxisLabelStyle: { + color: '#F0F0F3' + }, + activeDataLabelStyle: { + color: '#F0F0F3' + } + }, + navigation: { + buttonOptions: { + symbolStroke: '#DDDDDD', + theme: { + fill: '#505053' + } + } + }, + // scroll charts + rangeSelector: { + buttonTheme: { + fill: '#505053', + stroke: '#000000', + style: { + color: '#CCC' + }, + states: { + hover: { + fill: '#707073', + stroke: '#000000', + style: { + color: 'white' + } + }, + select: { + fill: '#000003', + stroke: '#000000', + style: { + color: 'white' + } + } + } + }, + inputBoxBorderColor: '#505053', + inputStyle: { + backgroundColor: '#333', + color: 'silver' + }, + labelStyle: { + color: 'silver' + } + }, + navigator: { + handles: { + backgroundColor: '#666', + borderColor: '#AAA' + }, + outlineColor: '#CCC', + maskFill: 'rgba(255,255,255,0.1)', + series: { + color: '#7798BF', + lineColor: '#A6C7ED' + }, + xAxis: { + gridLineColor: '#505053' + } + }, + scrollbar: { + barBackgroundColor: '#808083', + barBorderColor: '#808083', + buttonArrowColor: '#CCC', + buttonBackgroundColor: '#606063', + buttonBorderColor: '#606063', + rifleColor: '#FFF', + trackBackgroundColor: '#404043', + trackBorderColor: '#404043' + } + }; + // Apply the theme + Highcharts.setOptions(Highcharts.theme); + + }); + _registerModule(_modules, 'masters/themes/dark-unica.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/themes/gray.js b/librerias/gantt/code/themes/gray.js new file mode 100644 index 0000000..1f8bf8f --- /dev/null +++ b/librerias/gantt/code/themes/gray.js @@ -0,0 +1,15 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2009-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/themes/gray",["highcharts"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,b,c,d){a.hasOwnProperty(b)||(a[b]=d.apply(null,c))}a=a?a._modules:{};b(a,"themes/gray.js",[a["parts/Globals.js"]],function(a){a.theme={colors:"#DDDF0D #7798BF #55BF3B #DF5353 #aaeeee #ff0066 #eeaaee #55BF3B #DF5353 #7798BF #aaeeee".split(" "), +chart:{backgroundColor:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[0,"rgb(96, 96, 96)"],[1,"rgb(16, 16, 16)"]]},borderWidth:0,borderRadius:0,plotBackgroundColor:null,plotShadow:!1,plotBorderWidth:0},title:{style:{color:"#FFF",font:"16px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif"}},subtitle:{style:{color:"#DDD",font:"12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif"}},xAxis:{gridLineWidth:0,lineColor:"#999",tickColor:"#999",labels:{style:{color:"#999", +fontWeight:"bold"}},title:{style:{color:"#AAA",font:"bold 12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif"}}},yAxis:{alternateGridColor:null,minorTickInterval:null,gridLineColor:"rgba(255, 255, 255, .1)",minorGridLineColor:"rgba(255,255,255,0.07)",lineWidth:0,tickWidth:0,labels:{style:{color:"#999",fontWeight:"bold"}},title:{style:{color:"#AAA",font:"bold 12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif"}}},legend:{backgroundColor:"rgba(48, 48, 48, 0.8)", +itemStyle:{color:"#CCC"},itemHoverStyle:{color:"#FFF"},itemHiddenStyle:{color:"#333"},title:{style:{color:"#E0E0E0"}}},labels:{style:{color:"#CCC"}},tooltip:{backgroundColor:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[0,"rgba(96, 96, 96, .8)"],[1,"rgba(16, 16, 16, .8)"]]},borderWidth:0,style:{color:"#FFF"}},plotOptions:{series:{dataLabels:{color:"#444"},nullColor:"#444444"},line:{dataLabels:{color:"#CCC"},marker:{lineColor:"#333"}},spline:{marker:{lineColor:"#333"}},scatter:{marker:{lineColor:"#333"}}, +candlestick:{lineColor:"white"}},toolbar:{itemStyle:{color:"#CCC"}},navigation:{buttonOptions:{symbolStroke:"#DDDDDD",theme:{fill:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[.4,"#606060"],[.6,"#333333"]]},stroke:"#000000"}}},rangeSelector:{buttonTheme:{fill:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[.4,"#888"],[.6,"#555"]]},stroke:"#000000",style:{color:"#CCC",fontWeight:"bold"},states:{hover:{fill:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[.4,"#BBB"],[.6,"#888"]]},stroke:"#000000",style:{color:"white"}}, +select:{fill:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[.1,"#000"],[.3,"#333"]]},stroke:"#000000",style:{color:"yellow"}}}},inputStyle:{backgroundColor:"#333",color:"silver"},labelStyle:{color:"silver"}},navigator:{handles:{backgroundColor:"#666",borderColor:"#AAA"},outlineColor:"#CCC",maskFill:"rgba(16, 16, 16, 0.5)",series:{color:"#7798BF",lineColor:"#A6C7ED"}},scrollbar:{barBackgroundColor:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[.4,"#888"],[.6,"#555"]]},barBorderColor:"#CCC",buttonArrowColor:"#CCC", +buttonBackgroundColor:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[.4,"#888"],[.6,"#555"]]},buttonBorderColor:"#CCC",rifleColor:"#FFF",trackBackgroundColor:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[0,"#000"],[1,"#333"]]},trackBorderColor:"#666"}};a.setOptions(a.theme)});b(a,"masters/themes/gray.src.js",[],function(){})}); +//# sourceMappingURL=gray.js.map \ No newline at end of file diff --git a/librerias/gantt/code/themes/gray.js.map b/librerias/gantt/code/themes/gray.js.map new file mode 100644 index 0000000..760e281 --- /dev/null +++ b/librerias/gantt/code/themes/gray.js.map @@ -0,0 +1 @@ +{"version":3,"file":"gray.js.map","lineCount":14,"mappings":"A;;;;;;;AAQC,SAAS,CAACA,CAAD,CAAU,CACM,QAAtB,GAAI,MAAOC,OAAX,EAAkCA,MAAAC,QAAlC,EACIF,CAAA,CAAQ,SAAR,CACA,CADqBA,CACrB,CAAAC,MAAAC,QAAA,CAAiBF,CAFrB,EAG6B,UAAtB,GAAI,MAAOG,OAAX,EAAoCA,MAAAC,IAApC,CACHD,MAAA,CAAO,wBAAP,CAAiC,CAAC,YAAD,CAAjC,CAAiD,QAAS,CAACE,CAAD,CAAa,CACnEL,CAAA,CAAQK,CAAR,CACAL,EAAAK,WAAA,CAAqBA,CACrB,OAAOL,EAH4D,CAAvE,CADG,CAOHA,CAAA,CAA8B,WAAtB,GAAA,MAAOK,WAAP,CAAoCA,UAApC,CAAiDC,IAAAA,EAAzD,CAXY,CAAnB,CAAA,CAaC,QAAS,CAACD,CAAD,CAAa,CAEpBE,QAASA,EAAe,CAACC,CAAD,CAAMC,CAAN,CAAYC,CAAZ,CAAkBC,CAAlB,CAAsB,CACrCH,CAAAI,eAAA,CAAmBH,CAAnB,CAAL,GACID,CAAA,CAAIC,CAAJ,CADJ,CACgBE,CAAAE,MAAA,CAAS,IAAT,CAAeH,CAAf,CADhB,CAD0C,CAD1CI,CAAAA,CAAWT,CAAA,CAAaA,CAAAS,SAAb,CAAmC,EAMlDP,EAAA,CAAgBO,CAAhB,CAA0B,gBAA1B,CAA4C,CAACA,CAAA,CAAS,kBAAT,CAAD,CAA5C,CAA4E,QAAS,CAACT,CAAD,CAAa,CAY9FA,CAAAU,MAAA,CAAmB,CACfC,OAAQ,yFAAA,MAAA,CAAA,GAAA,CADO;AAGfC,MAAO,CACHC,gBAAiB,CACbC,eAAgB,CAAEC,GAAI,CAAN,CAASC,GAAI,CAAb,CAAgBC,GAAI,CAApB,CAAuBC,GAAI,CAA3B,CADH,CAEbC,MAAO,CACH,CAAC,CAAD,CAAI,iBAAJ,CADG,CAEH,CAAC,CAAD,CAAI,iBAAJ,CAFG,CAFM,CADd,CAQHC,YAAa,CARV,CASHC,aAAc,CATX,CAUHC,oBAAqB,IAVlB,CAWHC,WAAY,CAAA,CAXT,CAYHC,gBAAiB,CAZd,CAHQ,CAiBfC,MAAO,CACHC,MAAO,CACHC,MAAO,MADJ,CAEHC,KAAM,gFAFH,CADJ,CAjBQ,CAwBfC,SAAU,CACNH,MAAO,CACHC,MAAO,MADJ,CAEHC,KAAM,gFAFH,CADD,CAxBK,CA+BfE,MAAO,CACHC,cAAe,CADZ,CAEHC,UAAW,MAFR,CAGHC,UAAW,MAHR,CAIHC,OAAQ,CACJR,MAAO,CACHC,MAAO,MADJ;AAEHQ,WAAY,MAFT,CADH,CAJL,CAUHV,MAAO,CACHC,MAAO,CACHC,MAAO,MADJ,CAEHC,KAAM,qFAFH,CADJ,CAVJ,CA/BQ,CAiDfQ,MAAO,CACHC,mBAAoB,IADjB,CAEHC,kBAAmB,IAFhB,CAGHC,cAAe,yBAHZ,CAIHC,mBAAoB,wBAJjB,CAKHC,UAAW,CALR,CAMHC,UAAW,CANR,CAOHR,OAAQ,CACJR,MAAO,CACHC,MAAO,MADJ,CAEHQ,WAAY,MAFT,CADH,CAPL,CAaHV,MAAO,CACHC,MAAO,CACHC,MAAO,MADJ,CAEHC,KAAM,qFAFH,CADJ,CAbJ,CAjDQ,CAsEfe,OAAQ,CACJ9B,gBAAiB,uBADb;AAEJ+B,UAAW,CACPjB,MAAO,MADA,CAFP,CAKJkB,eAAgB,CACZlB,MAAO,MADK,CALZ,CAQJmB,gBAAiB,CACbnB,MAAO,MADM,CARb,CAWJF,MAAO,CACHC,MAAO,CACHC,MAAO,SADJ,CADJ,CAXH,CAtEO,CAuFfO,OAAQ,CACJR,MAAO,CACHC,MAAO,MADJ,CADH,CAvFO,CA4FfoB,QAAS,CACLlC,gBAAiB,CACbC,eAAgB,CAAEC,GAAI,CAAN,CAASC,GAAI,CAAb,CAAgBC,GAAI,CAApB,CAAuBC,GAAI,CAA3B,CADH,CAEbC,MAAO,CACH,CAAC,CAAD,CAAI,sBAAJ,CADG,CAEH,CAAC,CAAD,CAAI,sBAAJ,CAFG,CAFM,CADZ,CAQLC,YAAa,CARR,CASLM,MAAO,CACHC,MAAO,MADJ,CATF,CA5FM,CAyGfqB,YAAa,CACTC,OAAQ,CACJC,WAAY,CACRvB,MAAO,MADC,CADR,CAIJwB,UAAW,SAJP,CADC,CAOTC,KAAM,CACFF,WAAY,CACRvB,MAAO,MADC,CADV,CAIF0B,OAAQ,CACJrB,UAAW,MADP,CAJN,CAPG,CAeTsB,OAAQ,CACJD,OAAQ,CACJrB,UAAW,MADP,CADJ,CAfC,CAoBTuB,QAAS,CACLF,OAAQ,CACJrB,UAAW,MADP,CADH,CApBA;AAyBTwB,YAAa,CACTxB,UAAW,OADF,CAzBJ,CAzGE,CAsIfyB,QAAS,CACLb,UAAW,CACPjB,MAAO,MADA,CADN,CAtIM,CA2If+B,WAAY,CACRC,cAAe,CACXC,aAAc,SADH,CAEXlD,MAAO,CACHmD,KAAM,CACF/C,eAAgB,CAAEC,GAAI,CAAN,CAASC,GAAI,CAAb,CAAgBC,GAAI,CAApB,CAAuBC,GAAI,CAA3B,CADd,CAEFC,MAAO,CACH,CAAC,EAAD,CAAM,SAAN,CADG,CAEH,CAAC,EAAD,CAAM,SAAN,CAFG,CAFL,CADH,CAQH2C,OAAQ,SARL,CAFI,CADP,CA3IG,CA2JfC,cAAe,CACXC,YAAa,CACTH,KAAM,CACF/C,eAAgB,CAAEC,GAAI,CAAN,CAASC,GAAI,CAAb,CAAgBC,GAAI,CAApB,CAAuBC,GAAI,CAA3B,CADd,CAEFC,MAAO,CACH,CAAC,EAAD,CAAM,MAAN,CADG,CAEH,CAAC,EAAD,CAAM,MAAN,CAFG,CAFL,CADG,CAQT2C,OAAQ,SARC,CASTpC,MAAO,CACHC,MAAO,MADJ,CAEHQ,WAAY,MAFT,CATE,CAaT8B,OAAQ,CACJC,MAAO,CACHL,KAAM,CACF/C,eAAgB,CAAEC,GAAI,CAAN,CAASC,GAAI,CAAb,CAAgBC,GAAI,CAApB,CAAuBC,GAAI,CAA3B,CADd,CAEFC,MAAO,CACH,CAAC,EAAD,CAAM,MAAN,CADG,CAEH,CAAC,EAAD,CAAM,MAAN,CAFG,CAFL,CADH,CAQH2C,OAAQ,SARL,CASHpC,MAAO,CACHC,MAAO,OADJ,CATJ,CADH;AAcJwC,OAAQ,CACJN,KAAM,CACF/C,eAAgB,CAAEC,GAAI,CAAN,CAASC,GAAI,CAAb,CAAgBC,GAAI,CAApB,CAAuBC,GAAI,CAA3B,CADd,CAEFC,MAAO,CACH,CAAC,EAAD,CAAM,MAAN,CADG,CAEH,CAAC,EAAD,CAAM,MAAN,CAFG,CAFL,CADF,CAQJ2C,OAAQ,SARJ,CASJpC,MAAO,CACHC,MAAO,QADJ,CATH,CAdJ,CAbC,CADF,CA2CXyC,WAAY,CACRvD,gBAAiB,MADT,CAERc,MAAO,QAFC,CA3CD,CA+CX0C,WAAY,CACR1C,MAAO,QADC,CA/CD,CA3JA,CA8Mf2C,UAAW,CACPC,QAAS,CACL1D,gBAAiB,MADZ,CAEL2D,YAAa,MAFR,CADF,CAKPC,aAAc,MALP,CAMPC,SAAU,uBANH,CAOPzB,OAAQ,CACJtB,MAAO,SADH,CAEJK,UAAW,SAFP,CAPD,CA9MI,CA0Nf2C,UAAW,CACPC,mBAAoB,CAChB9D,eAAgB,CAAEC,GAAI,CAAN,CAASC,GAAI,CAAb,CAAgBC,GAAI,CAApB,CAAuBC,GAAI,CAA3B,CADA,CAEhBC,MAAO,CACH,CAAC,EAAD,CAAM,MAAN,CADG,CAEH,CAAC,EAAD,CAAM,MAAN,CAFG,CAFS,CADb,CAQP0D,eAAgB,MART,CASPC,iBAAkB,MATX;AAUPC,sBAAuB,CACnBjE,eAAgB,CAAEC,GAAI,CAAN,CAASC,GAAI,CAAb,CAAgBC,GAAI,CAApB,CAAuBC,GAAI,CAA3B,CADG,CAEnBC,MAAO,CACH,CAAC,EAAD,CAAM,MAAN,CADG,CAEH,CAAC,EAAD,CAAM,MAAN,CAFG,CAFY,CAVhB,CAiBP6D,kBAAmB,MAjBZ,CAkBPC,WAAY,MAlBL,CAmBPC,qBAAsB,CAClBpE,eAAgB,CAAEC,GAAI,CAAN,CAASC,GAAI,CAAb,CAAgBC,GAAI,CAApB,CAAuBC,GAAI,CAA3B,CADE,CAElBC,MAAO,CACH,CAAC,CAAD,CAAI,MAAJ,CADG,CAEH,CAAC,CAAD,CAAI,MAAJ,CAFG,CAFW,CAnBf,CA0BPgE,iBAAkB,MA1BX,CA1NI,CAwPnBnF,EAAAoF,WAAA,CAAsBpF,CAAAU,MAAtB,CApQ8F,CAAlG,CAuQAR,EAAA,CAAgBO,CAAhB,CAA0B,4BAA1B,CAAwD,EAAxD,CAA4D,QAAS,EAAG,EAAxE,CA9QoB,CAbvB;","sources":["gray.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","theme","colors","chart","backgroundColor","linearGradient","x1","y1","x2","y2","stops","borderWidth","borderRadius","plotBackgroundColor","plotShadow","plotBorderWidth","title","style","color","font","subtitle","xAxis","gridLineWidth","lineColor","tickColor","labels","fontWeight","yAxis","alternateGridColor","minorTickInterval","gridLineColor","minorGridLineColor","lineWidth","tickWidth","legend","itemStyle","itemHoverStyle","itemHiddenStyle","tooltip","plotOptions","series","dataLabels","nullColor","line","marker","spline","scatter","candlestick","toolbar","navigation","buttonOptions","symbolStroke","fill","stroke","rangeSelector","buttonTheme","states","hover","select","inputStyle","labelStyle","navigator","handles","borderColor","outlineColor","maskFill","scrollbar","barBackgroundColor","barBorderColor","buttonArrowColor","buttonBackgroundColor","buttonBorderColor","rifleColor","trackBackgroundColor","trackBorderColor","setOptions"]} \ No newline at end of file diff --git a/librerias/gantt/code/themes/gray.src.js b/librerias/gantt/code/themes/gray.src.js new file mode 100644 index 0000000..0ccdcaa --- /dev/null +++ b/librerias/gantt/code/themes/gray.src.js @@ -0,0 +1,296 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * (c) 2009-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/themes/gray', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'themes/gray.js', [_modules['parts/Globals.js']], function (Highcharts) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * Gray theme for Highcharts JS + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + Highcharts.theme = { + colors: ['#DDDF0D', '#7798BF', '#55BF3B', '#DF5353', '#aaeeee', + '#ff0066', '#eeaaee', '#55BF3B', '#DF5353', '#7798BF', '#aaeeee'], + chart: { + backgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0, 'rgb(96, 96, 96)'], + [1, 'rgb(16, 16, 16)'] + ] + }, + borderWidth: 0, + borderRadius: 0, + plotBackgroundColor: null, + plotShadow: false, + plotBorderWidth: 0 + }, + title: { + style: { + color: '#FFF', + font: '16px Lucida Grande, Lucida Sans Unicode,' + + ' Verdana, Arial, Helvetica, sans-serif' + } + }, + subtitle: { + style: { + color: '#DDD', + font: '12px Lucida Grande, Lucida Sans Unicode,' + + ' Verdana, Arial, Helvetica, sans-serif' + } + }, + xAxis: { + gridLineWidth: 0, + lineColor: '#999', + tickColor: '#999', + labels: { + style: { + color: '#999', + fontWeight: 'bold' + } + }, + title: { + style: { + color: '#AAA', + font: 'bold 12px Lucida Grande, Lucida Sans Unicode,' + + ' Verdana, Arial, Helvetica, sans-serif' + } + } + }, + yAxis: { + alternateGridColor: null, + minorTickInterval: null, + gridLineColor: 'rgba(255, 255, 255, .1)', + minorGridLineColor: 'rgba(255,255,255,0.07)', + lineWidth: 0, + tickWidth: 0, + labels: { + style: { + color: '#999', + fontWeight: 'bold' + } + }, + title: { + style: { + color: '#AAA', + font: 'bold 12px Lucida Grande, Lucida Sans Unicode,' + + ' Verdana, Arial, Helvetica, sans-serif' + } + } + }, + legend: { + backgroundColor: 'rgba(48, 48, 48, 0.8)', + itemStyle: { + color: '#CCC' + }, + itemHoverStyle: { + color: '#FFF' + }, + itemHiddenStyle: { + color: '#333' + }, + title: { + style: { + color: '#E0E0E0' + } + } + }, + labels: { + style: { + color: '#CCC' + } + }, + tooltip: { + backgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0, 'rgba(96, 96, 96, .8)'], + [1, 'rgba(16, 16, 16, .8)'] + ] + }, + borderWidth: 0, + style: { + color: '#FFF' + } + }, + plotOptions: { + series: { + dataLabels: { + color: '#444' + }, + nullColor: '#444444' + }, + line: { + dataLabels: { + color: '#CCC' + }, + marker: { + lineColor: '#333' + } + }, + spline: { + marker: { + lineColor: '#333' + } + }, + scatter: { + marker: { + lineColor: '#333' + } + }, + candlestick: { + lineColor: 'white' + } + }, + toolbar: { + itemStyle: { + color: '#CCC' + } + }, + navigation: { + buttonOptions: { + symbolStroke: '#DDDDDD', + theme: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#606060'], + [0.6, '#333333'] + ] + }, + stroke: '#000000' + } + } + }, + // scroll charts + rangeSelector: { + buttonTheme: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + stroke: '#000000', + style: { + color: '#CCC', + fontWeight: 'bold' + }, + states: { + hover: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#BBB'], + [0.6, '#888'] + ] + }, + stroke: '#000000', + style: { + color: 'white' + } + }, + select: { + fill: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.1, '#000'], + [0.3, '#333'] + ] + }, + stroke: '#000000', + style: { + color: 'yellow' + } + } + } + }, + inputStyle: { + backgroundColor: '#333', + color: 'silver' + }, + labelStyle: { + color: 'silver' + } + }, + navigator: { + handles: { + backgroundColor: '#666', + borderColor: '#AAA' + }, + outlineColor: '#CCC', + maskFill: 'rgba(16, 16, 16, 0.5)', + series: { + color: '#7798BF', + lineColor: '#A6C7ED' + } + }, + scrollbar: { + barBackgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + barBorderColor: '#CCC', + buttonArrowColor: '#CCC', + buttonBackgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0.4, '#888'], + [0.6, '#555'] + ] + }, + buttonBorderColor: '#CCC', + rifleColor: '#FFF', + trackBackgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0, '#000'], + [1, '#333'] + ] + }, + trackBorderColor: '#666' + } + }; + // Apply the theme + Highcharts.setOptions(Highcharts.theme); + + }); + _registerModule(_modules, 'masters/themes/gray.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/themes/grid-light.js b/librerias/gantt/code/themes/grid-light.js new file mode 100644 index 0000000..dbfc987 --- /dev/null +++ b/librerias/gantt/code/themes/grid-light.js @@ -0,0 +1,11 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2009-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/themes/grid-light",["highcharts"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,b,c,d){a.hasOwnProperty(b)||(a[b]=d.apply(null,c))}a=a?a._modules:{};b(a,"themes/grid-light.js",[a["parts/Globals.js"]],function(a){a.createElement("link",{href:"https://fonts.googleapis.com/css?family=Dosis:400,600", +rel:"stylesheet",type:"text/css"},null,document.getElementsByTagName("head")[0]);a.theme={colors:"#7cb5ec #f7a35c #90ee7e #7798BF #aaeeee #ff0066 #eeaaee #55BF3B #DF5353 #7798BF #aaeeee".split(" "),chart:{backgroundColor:null,style:{fontFamily:"Dosis, sans-serif"}},title:{style:{fontSize:"16px",fontWeight:"bold",textTransform:"uppercase"}},tooltip:{borderWidth:0,backgroundColor:"rgba(219,219,216,0.8)",shadow:!1},legend:{backgroundColor:"#F0F0EA",itemStyle:{fontWeight:"bold",fontSize:"13px"}},xAxis:{gridLineWidth:1, +labels:{style:{fontSize:"12px"}}},yAxis:{minorTickInterval:"auto",title:{style:{textTransform:"uppercase"}},labels:{style:{fontSize:"12px"}}},plotOptions:{candlestick:{lineColor:"#404048"}}};a.setOptions(a.theme)});b(a,"masters/themes/grid-light.src.js",[],function(){})}); +//# sourceMappingURL=grid-light.js.map \ No newline at end of file diff --git a/librerias/gantt/code/themes/grid-light.js.map b/librerias/gantt/code/themes/grid-light.js.map new file mode 100644 index 0000000..ff67773 --- /dev/null +++ b/librerias/gantt/code/themes/grid-light.js.map @@ -0,0 +1 @@ +{"version":3,"file":"grid-light.js.map","lineCount":10,"mappings":"A;;;;;;;AAQC,SAAS,CAACA,CAAD,CAAU,CACM,QAAtB,GAAI,MAAOC,OAAX,EAAkCA,MAAAC,QAAlC,EACIF,CAAA,CAAQ,SAAR,CACA,CADqBA,CACrB,CAAAC,MAAAC,QAAA,CAAiBF,CAFrB,EAG6B,UAAtB,GAAI,MAAOG,OAAX,EAAoCA,MAAAC,IAApC,CACHD,MAAA,CAAO,8BAAP,CAAuC,CAAC,YAAD,CAAvC,CAAuD,QAAS,CAACE,CAAD,CAAa,CACzEL,CAAA,CAAQK,CAAR,CACAL,EAAAK,WAAA,CAAqBA,CACrB,OAAOL,EAHkE,CAA7E,CADG,CAOHA,CAAA,CAA8B,WAAtB,GAAA,MAAOK,WAAP,CAAoCA,UAApC,CAAiDC,IAAAA,EAAzD,CAXY,CAAnB,CAAA,CAaC,QAAS,CAACD,CAAD,CAAa,CAEpBE,QAASA,EAAe,CAACC,CAAD,CAAMC,CAAN,CAAYC,CAAZ,CAAkBC,CAAlB,CAAsB,CACrCH,CAAAI,eAAA,CAAmBH,CAAnB,CAAL,GACID,CAAA,CAAIC,CAAJ,CADJ,CACgBE,CAAAE,MAAA,CAAS,IAAT,CAAeH,CAAf,CADhB,CAD0C,CAD1CI,CAAAA,CAAWT,CAAA,CAAaA,CAAAS,SAAb,CAAmC,EAMlDP,EAAA,CAAgBO,CAAhB,CAA0B,sBAA1B,CAAkD,CAACA,CAAA,CAAS,kBAAT,CAAD,CAAlD,CAAkF,QAAS,CAACT,CAAD,CAAa,CAcpGA,CAAAU,cAAA,CAAyB,MAAzB,CAAiC,CAC7BC,KAAM,uDADuB;AAE7BC,IAAK,YAFwB,CAG7BC,KAAM,UAHuB,CAAjC,CAIG,IAJH,CAISC,QAAAC,qBAAA,CAA8B,MAA9B,CAAA,CAAsC,CAAtC,CAJT,CAKAf,EAAAgB,MAAA,CAAmB,CACfC,OAAQ,yFAAA,MAAA,CAAA,GAAA,CADO,CAGfC,MAAO,CACHC,gBAAiB,IADd,CAEHC,MAAO,CACHC,WAAY,mBADT,CAFJ,CAHQ,CASfC,MAAO,CACHF,MAAO,CACHG,SAAU,MADP,CAEHC,WAAY,MAFT,CAGHC,cAAe,WAHZ,CADJ,CATQ,CAgBfC,QAAS,CACLC,YAAa,CADR,CAELR,gBAAiB,uBAFZ,CAGLS,OAAQ,CAAA,CAHH,CAhBM,CAqBfC,OAAQ,CACJV,gBAAiB,SADb,CAEJW,UAAW,CACPN,WAAY,MADL,CAEPD,SAAU,MAFH,CAFP,CArBO,CA4BfQ,MAAO,CACHC,cAAe,CADZ;AAEHC,OAAQ,CACJb,MAAO,CACHG,SAAU,MADP,CADH,CAFL,CA5BQ,CAoCfW,MAAO,CACHC,kBAAmB,MADhB,CAEHb,MAAO,CACHF,MAAO,CACHK,cAAe,WADZ,CADJ,CAFJ,CAOHQ,OAAQ,CACJb,MAAO,CACHG,SAAU,MADP,CADH,CAPL,CApCQ,CAiDfa,YAAa,CACTC,YAAa,CACTC,UAAW,SADF,CADJ,CAjDE,CAwDnBtC,EAAAuC,WAAA,CAAsBvC,CAAAgB,MAAtB,CA3EoG,CAAxG,CA8EAd,EAAA,CAAgBO,CAAhB,CAA0B,kCAA1B,CAA8D,EAA9D,CAAkE,QAAS,EAAG,EAA9E,CArFoB,CAbvB;","sources":["grid-light.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","createElement","href","rel","type","document","getElementsByTagName","theme","colors","chart","backgroundColor","style","fontFamily","title","fontSize","fontWeight","textTransform","tooltip","borderWidth","shadow","legend","itemStyle","xAxis","gridLineWidth","labels","yAxis","minorTickInterval","plotOptions","candlestick","lineColor","setOptions"]} \ No newline at end of file diff --git a/librerias/gantt/code/themes/grid-light.src.js b/librerias/gantt/code/themes/grid-light.src.js new file mode 100644 index 0000000..3346c2d --- /dev/null +++ b/librerias/gantt/code/themes/grid-light.src.js @@ -0,0 +1,111 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * (c) 2009-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/themes/grid-light', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'themes/grid-light.js', [_modules['parts/Globals.js']], function (Highcharts) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * Grid-light theme for Highcharts JS + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /* global document */ + // Load the fonts + Highcharts.createElement('link', { + href: 'https://fonts.googleapis.com/css?family=Dosis:400,600', + rel: 'stylesheet', + type: 'text/css' + }, null, document.getElementsByTagName('head')[0]); + Highcharts.theme = { + colors: ['#7cb5ec', '#f7a35c', '#90ee7e', '#7798BF', '#aaeeee', '#ff0066', + '#eeaaee', '#55BF3B', '#DF5353', '#7798BF', '#aaeeee'], + chart: { + backgroundColor: null, + style: { + fontFamily: 'Dosis, sans-serif' + } + }, + title: { + style: { + fontSize: '16px', + fontWeight: 'bold', + textTransform: 'uppercase' + } + }, + tooltip: { + borderWidth: 0, + backgroundColor: 'rgba(219,219,216,0.8)', + shadow: false + }, + legend: { + backgroundColor: '#F0F0EA', + itemStyle: { + fontWeight: 'bold', + fontSize: '13px' + } + }, + xAxis: { + gridLineWidth: 1, + labels: { + style: { + fontSize: '12px' + } + } + }, + yAxis: { + minorTickInterval: 'auto', + title: { + style: { + textTransform: 'uppercase' + } + }, + labels: { + style: { + fontSize: '12px' + } + } + }, + plotOptions: { + candlestick: { + lineColor: '#404048' + } + } + }; + // Apply the theme + Highcharts.setOptions(Highcharts.theme); + + }); + _registerModule(_modules, 'masters/themes/grid-light.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/themes/grid.js b/librerias/gantt/code/themes/grid.js new file mode 100644 index 0000000..41cf4d5 --- /dev/null +++ b/librerias/gantt/code/themes/grid.js @@ -0,0 +1,12 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2009-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/themes/grid",["highcharts"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,b,c,d){a.hasOwnProperty(b)||(a[b]=d.apply(null,c))}a=a?a._modules:{};b(a,"themes/grid.js",[a["parts/Globals.js"]],function(a){a.theme={colors:"#058DC7 #50B432 #ED561B #DDDF00 #24CBE5 #64E572 #FF9655 #FFF263 #6AF9C4".split(" "), +chart:{backgroundColor:{linearGradient:{x1:0,y1:0,x2:1,y2:1},stops:[[0,"rgb(255, 255, 255)"],[1,"rgb(240, 240, 255)"]]},borderWidth:2,plotBackgroundColor:"rgba(255, 255, 255, .9)",plotShadow:!0,plotBorderWidth:1},title:{style:{color:"#000",font:'bold 16px "Trebuchet MS", Verdana, sans-serif'}},subtitle:{style:{color:"#666666",font:'bold 12px "Trebuchet MS", Verdana, sans-serif'}},xAxis:{gridLineWidth:1,lineColor:"#000",tickColor:"#000",labels:{style:{color:"#000",font:"11px Trebuchet MS, Verdana, sans-serif"}}, +title:{style:{color:"#333",fontWeight:"bold",fontSize:"12px",fontFamily:"Trebuchet MS, Verdana, sans-serif"}}},yAxis:{minorTickInterval:"auto",lineColor:"#000",lineWidth:1,tickWidth:1,tickColor:"#000",labels:{style:{color:"#000",font:"11px Trebuchet MS, Verdana, sans-serif"}},title:{style:{color:"#333",fontWeight:"bold",fontSize:"12px",fontFamily:"Trebuchet MS, Verdana, sans-serif"}}},legend:{itemStyle:{font:"9pt Trebuchet MS, Verdana, sans-serif",color:"black"},itemHoverStyle:{color:"#039"},itemHiddenStyle:{color:"gray"}}, +labels:{style:{color:"#99b"}},navigation:{buttonOptions:{theme:{stroke:"#CCCCCC"}}}};a.setOptions(a.theme)});b(a,"masters/themes/grid.src.js",[],function(){})}); +//# sourceMappingURL=grid.js.map \ No newline at end of file diff --git a/librerias/gantt/code/themes/grid.js.map b/librerias/gantt/code/themes/grid.js.map new file mode 100644 index 0000000..c67343b --- /dev/null +++ b/librerias/gantt/code/themes/grid.js.map @@ -0,0 +1 @@ +{"version":3,"file":"grid.js.map","lineCount":11,"mappings":"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","sources":["grid.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","theme","colors","chart","backgroundColor","linearGradient","x1","y1","x2","y2","stops","borderWidth","plotBackgroundColor","plotShadow","plotBorderWidth","title","style","color","font","subtitle","xAxis","gridLineWidth","lineColor","tickColor","labels","fontWeight","fontSize","fontFamily","yAxis","minorTickInterval","lineWidth","tickWidth","legend","itemStyle","itemHoverStyle","itemHiddenStyle","navigation","buttonOptions","stroke","setOptions"]} \ No newline at end of file diff --git a/librerias/gantt/code/themes/grid.src.js b/librerias/gantt/code/themes/grid.src.js new file mode 100644 index 0000000..41b68d1 --- /dev/null +++ b/librerias/gantt/code/themes/grid.src.js @@ -0,0 +1,142 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * (c) 2009-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/themes/grid', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'themes/grid.js', [_modules['parts/Globals.js']], function (Highcharts) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * Grid theme for Highcharts JS + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + Highcharts.theme = { + colors: ['#058DC7', '#50B432', '#ED561B', '#DDDF00', '#24CBE5', '#64E572', + '#FF9655', '#FFF263', '#6AF9C4'], + chart: { + backgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 }, + stops: [ + [0, 'rgb(255, 255, 255)'], + [1, 'rgb(240, 240, 255)'] + ] + }, + borderWidth: 2, + plotBackgroundColor: 'rgba(255, 255, 255, .9)', + plotShadow: true, + plotBorderWidth: 1 + }, + title: { + style: { + color: '#000', + font: 'bold 16px "Trebuchet MS", Verdana, sans-serif' + } + }, + subtitle: { + style: { + color: '#666666', + font: 'bold 12px "Trebuchet MS", Verdana, sans-serif' + } + }, + xAxis: { + gridLineWidth: 1, + lineColor: '#000', + tickColor: '#000', + labels: { + style: { + color: '#000', + font: '11px Trebuchet MS, Verdana, sans-serif' + } + }, + title: { + style: { + color: '#333', + fontWeight: 'bold', + fontSize: '12px', + fontFamily: 'Trebuchet MS, Verdana, sans-serif' + } + } + }, + yAxis: { + minorTickInterval: 'auto', + lineColor: '#000', + lineWidth: 1, + tickWidth: 1, + tickColor: '#000', + labels: { + style: { + color: '#000', + font: '11px Trebuchet MS, Verdana, sans-serif' + } + }, + title: { + style: { + color: '#333', + fontWeight: 'bold', + fontSize: '12px', + fontFamily: 'Trebuchet MS, Verdana, sans-serif' + } + } + }, + legend: { + itemStyle: { + font: '9pt Trebuchet MS, Verdana, sans-serif', + color: 'black' + }, + itemHoverStyle: { + color: '#039' + }, + itemHiddenStyle: { + color: 'gray' + } + }, + labels: { + style: { + color: '#99b' + } + }, + navigation: { + buttonOptions: { + theme: { + stroke: '#CCCCCC' + } + } + } + }; + // Apply the theme + Highcharts.setOptions(Highcharts.theme); + + }); + _registerModule(_modules, 'masters/themes/grid.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/themes/high-contrast-dark.js b/librerias/gantt/code/themes/high-contrast-dark.js new file mode 100644 index 0000000..102890e --- /dev/null +++ b/librerias/gantt/code/themes/high-contrast-dark.js @@ -0,0 +1,13 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2009-2019 Highsoft AS + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/themes/high-contrast-dark",["highcharts"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,b,c,d){a.hasOwnProperty(b)||(a[b]=d.apply(null,c))}a=a?a._modules:{};b(a,"themes/high-contrast-dark.js",[a["parts/Globals.js"]],function(a){a.theme={colors:"#a6f0ff #70d49e #e898a5 #007faa #f9db72 #f45b5b #1e824c #e7934c #dadfe1 #a0618b".split(" "), +chart:{backgroundColor:"#1f1f20",plotBorderColor:"#606063"},title:{style:{color:"#F0F0F3"}},subtitle:{style:{color:"#F0F0F3"}},xAxis:{gridLineColor:"#707073",labels:{style:{color:"#F0F0F3"}},lineColor:"#707073",minorGridLineColor:"#505053",tickColor:"#707073",title:{style:{color:"#F0F0F3"}}},yAxis:{gridLineColor:"#707073",labels:{style:{color:"#F0F0F3"}},lineColor:"#707073",minorGridLineColor:"#505053",tickColor:"#707073",title:{style:{color:"#F0F0F3"}}},tooltip:{backgroundColor:"rgba(0, 0, 0, 0.85)", +style:{color:"#F0F0F3"}},plotOptions:{series:{dataLabels:{color:"#F0F0F3"},marker:{lineColor:"#333"}},boxplot:{fillColor:"#505053"},candlestick:{lineColor:"white"},errorbar:{color:"white"},map:{nullColor:"#353535"}},legend:{backgroundColor:"transparent",itemStyle:{color:"#F0F0F3"},itemHoverStyle:{color:"#FFF"},itemHiddenStyle:{color:"#606063"},title:{style:{color:"#D0D0D0"}}},credits:{style:{color:"#F0F0F3"}},labels:{style:{color:"#707073"}},drilldown:{activeAxisLabelStyle:{color:"#F0F0F3"},activeDataLabelStyle:{color:"#F0F0F3"}}, +navigation:{buttonOptions:{symbolStroke:"#DDDDDD",theme:{fill:"#505053"}}},rangeSelector:{buttonTheme:{fill:"#505053",stroke:"#000000",style:{color:"#eee"},states:{hover:{fill:"#707073",stroke:"#000000",style:{color:"#F0F0F3"}},select:{fill:"#303030",stroke:"#101010",style:{color:"#F0F0F3"}}}},inputBoxBorderColor:"#505053",inputStyle:{backgroundColor:"#333",color:"#F0F0F3"},labelStyle:{color:"#F0F0F3"}},navigator:{handles:{backgroundColor:"#666",borderColor:"#AAA"},outlineColor:"#CCC",maskFill:"rgba(180,180,255,0.2)", +series:{color:"#7798BF",lineColor:"#A6C7ED"},xAxis:{gridLineColor:"#505053"}},scrollbar:{barBackgroundColor:"#808083",barBorderColor:"#808083",buttonArrowColor:"#CCC",buttonBackgroundColor:"#606063",buttonBorderColor:"#606063",rifleColor:"#FFF",trackBackgroundColor:"#404043",trackBorderColor:"#404043"}};a.setOptions(a.theme)});b(a,"masters/themes/high-contrast-dark.src.js",[],function(){})}); +//# sourceMappingURL=high-contrast-dark.js.map \ No newline at end of file diff --git a/librerias/gantt/code/themes/high-contrast-dark.js.map b/librerias/gantt/code/themes/high-contrast-dark.js.map new file mode 100644 index 0000000..607fe14 --- /dev/null +++ b/librerias/gantt/code/themes/high-contrast-dark.js.map @@ -0,0 +1 @@ +{"version":3,"file":"high-contrast-dark.js.map","lineCount":12,"mappings":"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","sources":["high-contrast-dark.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","theme","colors","chart","backgroundColor","plotBorderColor","title","style","color","textBright","subtitle","xAxis","gridLineColor","labels","lineColor","minorGridLineColor","tickColor","yAxis","tooltip","plotOptions","series","dataLabels","marker","boxplot","fillColor","candlestick","errorbar","map","nullColor","legend","itemStyle","itemHoverStyle","itemHiddenStyle","credits","drilldown","activeAxisLabelStyle","activeDataLabelStyle","navigation","buttonOptions","symbolStroke","fill","rangeSelector","buttonTheme","stroke","states","hover","select","inputBoxBorderColor","inputStyle","labelStyle","navigator","handles","borderColor","outlineColor","maskFill","scrollbar","barBackgroundColor","barBorderColor","buttonArrowColor","buttonBackgroundColor","buttonBorderColor","rifleColor","trackBackgroundColor","trackBorderColor","setOptions"]} \ No newline at end of file diff --git a/librerias/gantt/code/themes/high-contrast-dark.src.js b/librerias/gantt/code/themes/high-contrast-dark.src.js new file mode 100644 index 0000000..084d01f --- /dev/null +++ b/librerias/gantt/code/themes/high-contrast-dark.src.js @@ -0,0 +1,243 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * (c) 2009-2019 Highsoft AS + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/themes/high-contrast-dark', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'themes/high-contrast-dark.js', [_modules['parts/Globals.js']], function (Highcharts) { + /* * + * + * (c) 2010-2020 Highsoft AS + * + * Author: Øystein Moseng + * + * License: www.highcharts.com/license + * + * Accessible high-contrast dark theme for Highcharts. Specifically tailored + * towards 3:1 contrast against black/off-black backgrounds. Neighboring + * colors are tested for color blindness. + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + var textBright = '#F0F0F3'; + Highcharts.theme = { + colors: [ + '#a6f0ff', + '#70d49e', + '#e898a5', + '#007faa', + '#f9db72', + '#f45b5b', + '#1e824c', + '#e7934c', + '#dadfe1', + '#a0618b' + ], + chart: { + backgroundColor: '#1f1f20', + plotBorderColor: '#606063' + }, + title: { + style: { + color: textBright + } + }, + subtitle: { + style: { + color: textBright + } + }, + xAxis: { + gridLineColor: '#707073', + labels: { + style: { + color: textBright + } + }, + lineColor: '#707073', + minorGridLineColor: '#505053', + tickColor: '#707073', + title: { + style: { + color: textBright + } + } + }, + yAxis: { + gridLineColor: '#707073', + labels: { + style: { + color: textBright + } + }, + lineColor: '#707073', + minorGridLineColor: '#505053', + tickColor: '#707073', + title: { + style: { + color: textBright + } + } + }, + tooltip: { + backgroundColor: 'rgba(0, 0, 0, 0.85)', + style: { + color: textBright + } + }, + plotOptions: { + series: { + dataLabels: { + color: textBright + }, + marker: { + lineColor: '#333' + } + }, + boxplot: { + fillColor: '#505053' + }, + candlestick: { + lineColor: 'white' + }, + errorbar: { + color: 'white' + }, + map: { + nullColor: '#353535' + } + }, + legend: { + backgroundColor: 'transparent', + itemStyle: { + color: textBright + }, + itemHoverStyle: { + color: '#FFF' + }, + itemHiddenStyle: { + color: '#606063' + }, + title: { + style: { + color: '#D0D0D0' + } + } + }, + credits: { + style: { + color: textBright + } + }, + labels: { + style: { + color: '#707073' + } + }, + drilldown: { + activeAxisLabelStyle: { + color: textBright + }, + activeDataLabelStyle: { + color: textBright + } + }, + navigation: { + buttonOptions: { + symbolStroke: '#DDDDDD', + theme: { + fill: '#505053' + } + } + }, + rangeSelector: { + buttonTheme: { + fill: '#505053', + stroke: '#000000', + style: { + color: '#eee' + }, + states: { + hover: { + fill: '#707073', + stroke: '#000000', + style: { + color: textBright + } + }, + select: { + fill: '#303030', + stroke: '#101010', + style: { + color: textBright + } + } + } + }, + inputBoxBorderColor: '#505053', + inputStyle: { + backgroundColor: '#333', + color: textBright + }, + labelStyle: { + color: textBright + } + }, + navigator: { + handles: { + backgroundColor: '#666', + borderColor: '#AAA' + }, + outlineColor: '#CCC', + maskFill: 'rgba(180,180,255,0.2)', + series: { + color: '#7798BF', + lineColor: '#A6C7ED' + }, + xAxis: { + gridLineColor: '#505053' + } + }, + scrollbar: { + barBackgroundColor: '#808083', + barBorderColor: '#808083', + buttonArrowColor: '#CCC', + buttonBackgroundColor: '#606063', + buttonBorderColor: '#606063', + rifleColor: '#FFF', + trackBackgroundColor: '#404043', + trackBorderColor: '#404043' + } + }; + // Apply the theme + Highcharts.setOptions(Highcharts.theme); + + }); + _registerModule(_modules, 'masters/themes/high-contrast-dark.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/themes/high-contrast-light.js b/librerias/gantt/code/themes/high-contrast-light.js new file mode 100644 index 0000000..260d106 --- /dev/null +++ b/librerias/gantt/code/themes/high-contrast-light.js @@ -0,0 +1,10 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2009-2019 Highsoft AS + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/themes/high-contrast-light",["highcharts"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,b,c,d){a.hasOwnProperty(b)||(a[b]=d.apply(null,c))}a=a?a._modules:{};b(a,"themes/high-contrast-light.js",[a["parts/Globals.js"]],function(a){a.theme={colors:"#5f98cf #434348 #49a65e #f45b5b #708090 #b68c51 #397550 #c0493d #4f4a7a #b381b3".split(" "), +navigator:{series:{color:"#5f98cf",lineColor:"#5f98cf"}}};a.setOptions(a.theme)});b(a,"masters/themes/high-contrast-light.src.js",[],function(){})}); +//# sourceMappingURL=high-contrast-light.js.map \ No newline at end of file diff --git a/librerias/gantt/code/themes/high-contrast-light.js.map b/librerias/gantt/code/themes/high-contrast-light.js.map new file mode 100644 index 0000000..2136e49 --- /dev/null +++ b/librerias/gantt/code/themes/high-contrast-light.js.map @@ -0,0 +1 @@ +{"version":3,"file":"high-contrast-light.js.map","lineCount":9,"mappings":"A;;;;;;;AAQC,SAAS,CAACA,CAAD,CAAU,CACM,QAAtB,GAAI,MAAOC,OAAX,EAAkCA,MAAAC,QAAlC,EACIF,CAAA,CAAQ,SAAR,CACA,CADqBA,CACrB,CAAAC,MAAAC,QAAA,CAAiBF,CAFrB,EAG6B,UAAtB,GAAI,MAAOG,OAAX,EAAoCA,MAAAC,IAApC,CACHD,MAAA,CAAO,uCAAP,CAAgD,CAAC,YAAD,CAAhD,CAAgE,QAAS,CAACE,CAAD,CAAa,CAClFL,CAAA,CAAQK,CAAR,CACAL,EAAAK,WAAA,CAAqBA,CACrB,OAAOL,EAH2E,CAAtF,CADG,CAOHA,CAAA,CAA8B,WAAtB,GAAA,MAAOK,WAAP,CAAoCA,UAApC,CAAiDC,IAAAA,EAAzD,CAXY,CAAnB,CAAA,CAaC,QAAS,CAACD,CAAD,CAAa,CAEpBE,QAASA,EAAe,CAACC,CAAD,CAAMC,CAAN,CAAYC,CAAZ,CAAkBC,CAAlB,CAAsB,CACrCH,CAAAI,eAAA,CAAmBH,CAAnB,CAAL,GACID,CAAA,CAAIC,CAAJ,CADJ,CACgBE,CAAAE,MAAA,CAAS,IAAT,CAAeH,CAAf,CADhB,CAD0C,CAD1CI,CAAAA,CAAWT,CAAA,CAAaA,CAAAS,SAAb,CAAmC,EAMlDP,EAAA,CAAgBO,CAAhB,CAA0B,+BAA1B,CAA2D,CAACA,CAAA,CAAS,kBAAT,CAAD,CAA3D,CAA2F,QAAS,CAACT,CAAD,CAAa,CAgB7GA,CAAAU,MAAA,CAAmB,CACfC,OAAQ,iFAAA,MAAA,CAAA,GAAA,CADO;AAafC,UAAW,CACPC,OAAQ,CACJC,MAAO,SADH,CAEJC,UAAW,SAFP,CADD,CAbI,CAqBnBf,EAAAgB,WAAA,CAAsBhB,CAAAU,MAAtB,CArC6G,CAAjH,CAwCAR,EAAA,CAAgBO,CAAhB,CAA0B,2CAA1B,CAAuE,EAAvE,CAA2E,QAAS,EAAG,EAAvF,CA/CoB,CAbvB;","sources":["high-contrast-light.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","theme","colors","navigator","series","color","lineColor","setOptions"]} \ No newline at end of file diff --git a/librerias/gantt/code/themes/high-contrast-light.src.js b/librerias/gantt/code/themes/high-contrast-light.src.js new file mode 100644 index 0000000..346e031 --- /dev/null +++ b/librerias/gantt/code/themes/high-contrast-light.src.js @@ -0,0 +1,73 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * (c) 2009-2019 Highsoft AS + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/themes/high-contrast-light', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'themes/high-contrast-light.js', [_modules['parts/Globals.js']], function (Highcharts) { + /* * + * + * (c) 2010-2020 Highsoft AS + * + * Author: Øystein Moseng + * + * License: www.highcharts.com/license + * + * Accessible high-contrast theme for Highcharts. Specifically tailored + * towards 3:1 contrast against white/off-white backgrounds. Neighboring + * colors are tested for color blindness. + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + Highcharts.theme = { + colors: [ + '#5f98cf', + '#434348', + '#49a65e', + '#f45b5b', + '#708090', + '#b68c51', + '#397550', + '#c0493d', + '#4f4a7a', + '#b381b3' + ], + navigator: { + series: { + color: '#5f98cf', + lineColor: '#5f98cf' + } + } + }; + // Apply the theme + Highcharts.setOptions(Highcharts.theme); + + }); + _registerModule(_modules, 'masters/themes/high-contrast-light.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/themes/sand-signika.js b/librerias/gantt/code/themes/sand-signika.js new file mode 100644 index 0000000..3584f1b --- /dev/null +++ b/librerias/gantt/code/themes/sand-signika.js @@ -0,0 +1,12 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2009-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/themes/sand-signika",["highcharts"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,b,c,d){a.hasOwnProperty(b)||(a[b]=d.apply(null,c))}a=a?a._modules:{};b(a,"themes/sand-signika.js",[a["parts/Globals.js"]],function(a){a.createElement("link",{href:"https://fonts.googleapis.com/css?family=Signika:400,700", +rel:"stylesheet",type:"text/css"},null,document.getElementsByTagName("head")[0]);a.addEvent(a.Chart,"afterGetContainer",function(){this.container.style.background="url(https://www.highcharts.com/samples/graphics/sand.png)"});a.theme={colors:"#f45b5b #8085e9 #8d4654 #7798BF #aaeeee #ff0066 #eeaaee #55BF3B #DF5353 #7798BF #aaeeee".split(" "),chart:{backgroundColor:null,style:{fontFamily:"Signika, serif"}},title:{style:{color:"black",fontSize:"16px",fontWeight:"bold"}},subtitle:{style:{color:"black"}}, +tooltip:{borderWidth:0},labels:{style:{color:"#6e6e70"}},legend:{backgroundColor:"#E0E0E8",itemStyle:{fontWeight:"bold",fontSize:"13px"}},xAxis:{labels:{style:{color:"#6e6e70"}}},yAxis:{labels:{style:{color:"#6e6e70"}}},plotOptions:{series:{shadow:!0},candlestick:{lineColor:"#404048"},map:{shadow:!1}},navigator:{xAxis:{gridLineColor:"#D0D0D8"}},rangeSelector:{buttonTheme:{fill:"white",stroke:"#C0C0C8","stroke-width":1,states:{select:{fill:"#D0D0D8"}}}},scrollbar:{trackBorderColor:"#C0C0C8"}};a.setOptions(a.theme)}); +b(a,"masters/themes/sand-signika.src.js",[],function(){})}); +//# sourceMappingURL=sand-signika.js.map \ No newline at end of file diff --git a/librerias/gantt/code/themes/sand-signika.js.map b/librerias/gantt/code/themes/sand-signika.js.map new file mode 100644 index 0000000..00c73f8 --- /dev/null +++ b/librerias/gantt/code/themes/sand-signika.js.map @@ -0,0 +1 @@ +{"version":3,"file":"sand-signika.js.map","lineCount":11,"mappings":"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","sources":["sand-signika.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","createElement","href","rel","type","document","getElementsByTagName","addEvent","Chart","container","style","background","theme","colors","chart","backgroundColor","fontFamily","title","color","fontSize","fontWeight","subtitle","tooltip","borderWidth","labels","legend","itemStyle","xAxis","yAxis","plotOptions","series","shadow","candlestick","lineColor","map","navigator","gridLineColor","rangeSelector","buttonTheme","fill","stroke","states","select","scrollbar","trackBorderColor","setOptions"]} \ No newline at end of file diff --git a/librerias/gantt/code/themes/sand-signika.src.js b/librerias/gantt/code/themes/sand-signika.src.js new file mode 100644 index 0000000..cdeff6c --- /dev/null +++ b/librerias/gantt/code/themes/sand-signika.src.js @@ -0,0 +1,145 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * (c) 2009-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/themes/sand-signika', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'themes/sand-signika.js', [_modules['parts/Globals.js']], function (Highcharts) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * Sand-Signika theme for Highcharts JS + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + /* global document */ + // Load the fonts + Highcharts.createElement('link', { + href: 'https://fonts.googleapis.com/css?family=Signika:400,700', + rel: 'stylesheet', + type: 'text/css' + }, null, document.getElementsByTagName('head')[0]); + // Add the background image to the container + Highcharts.addEvent(Highcharts.Chart, 'afterGetContainer', function () { + // eslint-disable-next-line no-invalid-this + this.container.style.background = + 'url(https://www.highcharts.com/samples/graphics/sand.png)'; + }); + Highcharts.theme = { + colors: ['#f45b5b', '#8085e9', '#8d4654', '#7798BF', '#aaeeee', + '#ff0066', '#eeaaee', '#55BF3B', '#DF5353', '#7798BF', '#aaeeee'], + chart: { + backgroundColor: null, + style: { + fontFamily: 'Signika, serif' + } + }, + title: { + style: { + color: 'black', + fontSize: '16px', + fontWeight: 'bold' + } + }, + subtitle: { + style: { + color: 'black' + } + }, + tooltip: { + borderWidth: 0 + }, + labels: { + style: { + color: '#6e6e70' + } + }, + legend: { + backgroundColor: '#E0E0E8', + itemStyle: { + fontWeight: 'bold', + fontSize: '13px' + } + }, + xAxis: { + labels: { + style: { + color: '#6e6e70' + } + } + }, + yAxis: { + labels: { + style: { + color: '#6e6e70' + } + } + }, + plotOptions: { + series: { + shadow: true + }, + candlestick: { + lineColor: '#404048' + }, + map: { + shadow: false + } + }, + // Highstock specific + navigator: { + xAxis: { + gridLineColor: '#D0D0D8' + } + }, + rangeSelector: { + buttonTheme: { + fill: 'white', + stroke: '#C0C0C8', + 'stroke-width': 1, + states: { + select: { + fill: '#D0D0D8' + } + } + } + }, + scrollbar: { + trackBorderColor: '#C0C0C8' + } + }; + // Apply the theme + Highcharts.setOptions(Highcharts.theme); + + }); + _registerModule(_modules, 'masters/themes/sand-signika.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/themes/skies.js b/librerias/gantt/code/themes/skies.js new file mode 100644 index 0000000..b9b71d8 --- /dev/null +++ b/librerias/gantt/code/themes/skies.js @@ -0,0 +1,12 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2009-2019 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/themes/skies",["highcharts"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,b,c,d){a.hasOwnProperty(b)||(a[b]=d.apply(null,c))}a=a?a._modules:{};b(a,"themes/skies.js",[a["parts/Globals.js"]],function(a){a.theme={colors:"#514F78 #42A07B #9B5E4A #72727F #1F949A #82914E #86777F #42A07B".split(" "), +chart:{className:"skies",borderWidth:0,plotShadow:!0,plotBackgroundImage:"https://www.highcharts.com/demo/gfx/skies.jpg",plotBackgroundColor:{linearGradient:{x1:0,y1:0,x2:1,y2:1},stops:[[0,"rgba(255, 255, 255, 1)"],[1,"rgba(255, 255, 255, 0)"]]},plotBorderWidth:1},title:{style:{color:"#3E576F",font:"16px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif"}},subtitle:{style:{color:"#6D869F",font:"12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif"}}, +xAxis:{gridLineWidth:0,lineColor:"#C0D0E0",tickColor:"#C0D0E0",labels:{style:{color:"#666",fontWeight:"bold"}},title:{style:{color:"#666",font:"12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif"}}},yAxis:{alternateGridColor:"rgba(255, 255, 255, .5)",lineColor:"#C0D0E0",tickColor:"#C0D0E0",tickWidth:1,labels:{style:{color:"#666",fontWeight:"bold"}},title:{style:{color:"#666",font:"12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif"}}},legend:{itemStyle:{font:"9pt Trebuchet MS, Verdana, sans-serif", +color:"#3E576F"},itemHoverStyle:{color:"black"},itemHiddenStyle:{color:"silver"}},labels:{style:{color:"#3E576F"}}};a.setOptions(a.theme)});b(a,"masters/themes/skies.src.js",[],function(){})}); +//# sourceMappingURL=skies.js.map \ No newline at end of file diff --git a/librerias/gantt/code/themes/skies.js.map b/librerias/gantt/code/themes/skies.js.map new file mode 100644 index 0000000..b35e71f --- /dev/null +++ b/librerias/gantt/code/themes/skies.js.map @@ -0,0 +1 @@ +{"version":3,"file":"skies.js.map","lineCount":11,"mappings":"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","sources":["skies.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","theme","colors","chart","className","borderWidth","plotShadow","plotBackgroundImage","plotBackgroundColor","linearGradient","x1","y1","x2","y2","stops","plotBorderWidth","title","style","color","font","subtitle","xAxis","gridLineWidth","lineColor","tickColor","labels","fontWeight","yAxis","alternateGridColor","tickWidth","legend","itemStyle","itemHoverStyle","itemHiddenStyle","setOptions"]} \ No newline at end of file diff --git a/librerias/gantt/code/themes/skies.src.js b/librerias/gantt/code/themes/skies.src.js new file mode 100644 index 0000000..94236e0 --- /dev/null +++ b/librerias/gantt/code/themes/skies.src.js @@ -0,0 +1,135 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * (c) 2009-2019 Torstein Honsi + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/themes/skies', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'themes/skies.js', [_modules['parts/Globals.js']], function (Highcharts) { + /* * + * + * (c) 2010-2020 Torstein Honsi + * + * License: www.highcharts.com/license + * + * Skies theme for Highcharts JS + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + Highcharts.theme = { + colors: ['#514F78', '#42A07B', '#9B5E4A', '#72727F', '#1F949A', + '#82914E', '#86777F', '#42A07B'], + chart: { + className: 'skies', + borderWidth: 0, + plotShadow: true, + plotBackgroundImage: 'https://www.highcharts.com/demo/gfx/skies.jpg', + plotBackgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 }, + stops: [ + [0, 'rgba(255, 255, 255, 1)'], + [1, 'rgba(255, 255, 255, 0)'] + ] + }, + plotBorderWidth: 1 + }, + title: { + style: { + color: '#3E576F', + font: '16px Lucida Grande, Lucida Sans Unicode,' + + ' Verdana, Arial, Helvetica, sans-serif' + } + }, + subtitle: { + style: { + color: '#6D869F', + font: '12px Lucida Grande, Lucida Sans Unicode,' + + ' Verdana, Arial, Helvetica, sans-serif' + } + }, + xAxis: { + gridLineWidth: 0, + lineColor: '#C0D0E0', + tickColor: '#C0D0E0', + labels: { + style: { + color: '#666', + fontWeight: 'bold' + } + }, + title: { + style: { + color: '#666', + font: '12px Lucida Grande, Lucida Sans Unicode,' + + ' Verdana, Arial, Helvetica, sans-serif' + } + } + }, + yAxis: { + alternateGridColor: 'rgba(255, 255, 255, .5)', + lineColor: '#C0D0E0', + tickColor: '#C0D0E0', + tickWidth: 1, + labels: { + style: { + color: '#666', + fontWeight: 'bold' + } + }, + title: { + style: { + color: '#666', + font: '12px Lucida Grande, Lucida Sans Unicode,' + + ' Verdana, Arial, Helvetica, sans-serif' + } + } + }, + legend: { + itemStyle: { + font: '9pt Trebuchet MS, Verdana, sans-serif', + color: '#3E576F' + }, + itemHoverStyle: { + color: 'black' + }, + itemHiddenStyle: { + color: 'silver' + } + }, + labels: { + style: { + color: '#3E576F' + } + } + }; + // Apply the theme + Highcharts.setOptions(Highcharts.theme); + + }); + _registerModule(_modules, 'masters/themes/skies.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/librerias/gantt/code/themes/sunset.js b/librerias/gantt/code/themes/sunset.js new file mode 100644 index 0000000..ac9d40b --- /dev/null +++ b/librerias/gantt/code/themes/sunset.js @@ -0,0 +1,10 @@ +/* + Highcharts JS v8.1.0 (2020-05-05) + + (c) 2009-2019 Highsoft AS + + License: www.highcharts.com/license +*/ +(function(a){"object"===typeof module&&module.exports?(a["default"]=a,module.exports=a):"function"===typeof define&&define.amd?define("highcharts/themes/sunset",["highcharts"],function(b){a(b);a.Highcharts=b;return a}):a("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(a){function b(a,b,c,d){a.hasOwnProperty(b)||(a[b]=d.apply(null,c))}a=a?a._modules:{};b(a,"themes/sunset.js",[a["parts/Globals.js"]],function(a){a.theme={colors:["#FDD089","#FF7F79","#A0446E","#251535"],colorAxis:{maxColor:"#60042E", +minColor:"#FDD089"},plotOptions:{map:{nullColor:"#fefefc"}},navigator:{series:{color:"#FF7F79",lineColor:"#A0446E"}}};a.setOptions(a.theme)});b(a,"masters/themes/sunset.src.js",[],function(){})}); +//# sourceMappingURL=sunset.js.map \ No newline at end of file diff --git a/librerias/gantt/code/themes/sunset.js.map b/librerias/gantt/code/themes/sunset.js.map new file mode 100644 index 0000000..17257cc --- /dev/null +++ b/librerias/gantt/code/themes/sunset.js.map @@ -0,0 +1 @@ +{"version":3,"file":"sunset.js.map","lineCount":9,"mappings":"A;;;;;;;AAQC,SAAS,CAACA,CAAD,CAAU,CACM,QAAtB,GAAI,MAAOC,OAAX,EAAkCA,MAAAC,QAAlC,EACIF,CAAA,CAAQ,SAAR,CACA,CADqBA,CACrB,CAAAC,MAAAC,QAAA,CAAiBF,CAFrB,EAG6B,UAAtB,GAAI,MAAOG,OAAX,EAAoCA,MAAAC,IAApC,CACHD,MAAA,CAAO,0BAAP,CAAmC,CAAC,YAAD,CAAnC,CAAmD,QAAS,CAACE,CAAD,CAAa,CACrEL,CAAA,CAAQK,CAAR,CACAL,EAAAK,WAAA,CAAqBA,CACrB,OAAOL,EAH8D,CAAzE,CADG,CAOHA,CAAA,CAA8B,WAAtB,GAAA,MAAOK,WAAP,CAAoCA,UAApC,CAAiDC,IAAAA,EAAzD,CAXY,CAAnB,CAAA,CAaC,QAAS,CAACD,CAAD,CAAa,CAEpBE,QAASA,EAAe,CAACC,CAAD,CAAMC,CAAN,CAAYC,CAAZ,CAAkBC,CAAlB,CAAsB,CACrCH,CAAAI,eAAA,CAAmBH,CAAnB,CAAL,GACID,CAAA,CAAIC,CAAJ,CADJ,CACgBE,CAAAE,MAAA,CAAS,IAAT,CAAeH,CAAf,CADhB,CAD0C,CAD1CI,CAAAA,CAAWT,CAAA,CAAaA,CAAAS,SAAb,CAAmC,EAMlDP,EAAA,CAAgBO,CAAhB,CAA0B,kBAA1B,CAA8C,CAACA,CAAA,CAAS,kBAAT,CAAD,CAA9C,CAA8E,QAAS,CAACT,CAAD,CAAa,CAehGA,CAAAU,MAAA,CAAmB,CACfC,OAAQ,CAAC,SAAD,CAAY,SAAZ,CAAuB,SAAvB,CAAkC,SAAlC,CADO,CAEfC,UAAW,CACPC,SAAU,SADH;AAEPC,SAAU,SAFH,CAFI,CAMfC,YAAa,CACTC,IAAK,CACDC,UAAW,SADV,CADI,CANE,CAWfC,UAAW,CACPC,OAAQ,CACJC,MAAO,SADH,CAEJC,UAAW,SAFP,CADD,CAXI,CAmBnBrB,EAAAsB,WAAA,CAAsBtB,CAAAU,MAAtB,CAlCgG,CAApG,CAqCAR,EAAA,CAAgBO,CAAhB,CAA0B,8BAA1B,CAA0D,EAA1D,CAA8D,QAAS,EAAG,EAA1E,CA5CoB,CAbvB;","sources":["sunset.src.js"],"names":["factory","module","exports","define","amd","Highcharts","undefined","_registerModule","obj","path","args","fn","hasOwnProperty","apply","_modules","theme","colors","colorAxis","maxColor","minColor","plotOptions","map","nullColor","navigator","series","color","lineColor","setOptions"]} \ No newline at end of file diff --git a/librerias/gantt/code/themes/sunset.src.js b/librerias/gantt/code/themes/sunset.src.js new file mode 100644 index 0000000..adaa8f9 --- /dev/null +++ b/librerias/gantt/code/themes/sunset.src.js @@ -0,0 +1,70 @@ +/** + * @license Highcharts JS v8.1.0 (2020-05-05) + * + * (c) 2009-2019 Highsoft AS + * + * License: www.highcharts.com/license + */ +'use strict'; +(function (factory) { + if (typeof module === 'object' && module.exports) { + factory['default'] = factory; + module.exports = factory; + } else if (typeof define === 'function' && define.amd) { + define('highcharts/themes/sunset', ['highcharts'], function (Highcharts) { + factory(Highcharts); + factory.Highcharts = Highcharts; + return factory; + }); + } else { + factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined); + } +}(function (Highcharts) { + var _modules = Highcharts ? Highcharts._modules : {}; + function _registerModule(obj, path, args, fn) { + if (!obj.hasOwnProperty(path)) { + obj[path] = fn.apply(null, args); + } + } + _registerModule(_modules, 'themes/sunset.js', [_modules['parts/Globals.js']], function (Highcharts) { + /* * + * + * (c) 2010-2020 Highsoft AS + * + * Author: Øystein Moseng + * + * License: www.highcharts.com/license + * + * Accessible high-contrast theme for Highcharts. Considers colorblindness and + * monochrome rendering. + * + * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! + * + * */ + Highcharts.theme = { + colors: ['#FDD089', '#FF7F79', '#A0446E', '#251535'], + colorAxis: { + maxColor: '#60042E', + minColor: '#FDD089' + }, + plotOptions: { + map: { + nullColor: '#fefefc' + } + }, + navigator: { + series: { + color: '#FF7F79', + lineColor: '#A0446E' + } + } + }; + // Apply the theme + Highcharts.setOptions(Highcharts.theme); + + }); + _registerModule(_modules, 'masters/themes/sunset.src.js', [], function () { + + + }); +})); \ No newline at end of file diff --git a/milfs b/milfs index 13e4bbf..3f489b7 160000 --- a/milfs +++ b/milfs @@ -1 +1 @@ -Subproject commit 13e4bbffa691e1324ab316c4b557dbfee320625b +Subproject commit 3f489b76b837347f824fc946a5e3b4ce115fabf5